Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

How to arbitrarily set camera position in world coordinates

Discussion in 'Scripting' started by MutantSurvivor, Jan 4, 2010.

  1. MutantSurvivor

    MutantSurvivor

    Joined:
    Jan 4, 2010
    Posts:
    13
    Hi,

    I want to know how I can set the position and direction of the camera purely using the world coordinates.

    By this I mean I want to be able to force the camera to be in whatever position I want it to be regardless of where it currently is, only using the world coordinates. It is only the X and Y coordinates that I want to set but have the Z coordinate (I assume Z relates to height above the ground, I am not used to working with 3D) determined by the height of the ground at that particular point in world space.

    To put this in context, I am creating an application using Unity in conjunction with ReacTIVision / TUIO that will allow the user to control the camera position by moving an object around that has a fiducial marker on the bottom on a 'table' which contains a top down map of the terrain. Wherever the object is placed (and tracked by the camera below the 'table'), so the camera will appear.

    Although I have been programming for many years (php actionscript, java, lingo etc) I have not really worked much with 3D and find it very confusing, especially all of the transforms, viewports, matrices etc.

    Many thanks
     
  2. MutantSurvivor

    MutantSurvivor

    Joined:
    Jan 4, 2010
    Posts:
    13
    I've been doing some hunting around the Unity manual.

    Is it just a case of setting the Transform of the camera?

    Camera.transform.position = Vector3(x, y, z);
    Camera.transform.rotation = ???
     
    CrandellWS likes this.
  3. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    In Unity, the convention is that Y is the height. This is kind of arbitrary to some extent, but generally things are easier if you stick with that.

    Yes.

    That should be camera.transform.eulerAngles actually. Also note the difference between Camera (a type) and camera, which is equivalent to "GetComponent(Camera)".

    --Eric
     
    CrandellWS likes this.
  4. MutantSurvivor

    MutantSurvivor

    Joined:
    Jan 4, 2010
    Posts:
    13
    Eric,

    Brilliant, thanks for your swift reply (is nice to find a forum that moves quickly). Need to look into EulerAngles and also the Camera / camera issue to see if I understand it.

    OK, another question

    How do I find the height of the the ground / terrain at a particular X and Z coordinates (the terrain will be fairly simple, i.e. nothing above the ground)?

    Ta
     
  5. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Is this with the Unity terrain system? If so, Terrain.SampleHeight().

    --Eric
     
  6. MutantSurvivor

    MutantSurvivor

    Joined:
    Jan 4, 2010
    Posts:
    13
    Hmm not sure to be honest, haven't got that far. Someone else is building the terrain and I think that they might use Maya and import it.

    I'm going to get hold of a sample terrain from somewhere and try it out when I get home tonight.
     
  7. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You can convert a terrain from Maya (or any other 3D app) to a Unity terrain with this.

    --Eric
     
  8. Sandor

    Sandor

    Joined:
    Apr 17, 2009
    Posts:
    91
    @ MutantSurvivor: you should head over to www.xtuio.com. You can grab the uniTUIO sources (TUIO framework for Unity) to see how we are handling the touches coming from a TUIO enablad device (like a MT table or wall). Basically it is the same you want to do. I am not sure if the fiducial stuff is still inside or if we are doing only the 2dcur stuff from TUIO.

    If you are doing something with fiducial support and you would like to integrate that in uniTUIO, please give me a short note. If you have questions - please ask me or Ben...

    Hope this helps :)

    Cheers,
     
  9. MutantSurvivor

    MutantSurvivor

    Joined:
    Jan 4, 2010
    Posts:
    13
    Hi Sandor,

    I spent a few weeks banging my head against a wall trying to get unity working with reacTIVision until I discovered uniTUIO (the day after it was released, lucky timing eh) which makes it all very easy, thanks for all your work.

    It does handle the fiducial stuff, creates a tuio object for each marker. I am then taking the position and angle from that to position the camera.

    Not had a chance to try the suggestions from earlier out yet (this is a pet project and have to fit it around a full time job and a family) but will hopefully get to try it tonight or at the weekend.

    Thanks
     
  10. Sandor

    Sandor

    Joined:
    Apr 17, 2009
    Posts:
    91
    Hey MutantSurvivor,

    glad to hear that you have found us allready :) I know - time is precious, but if you find some time, i would love to see a very basic fiducial example scene (just place an object in the scene with Fid_Id, rotation and x/yz)...

    To your camera question: i am not a coder, but i think that shooting a raycast "downwards" against your terrain at a specific point in the scene and calculating the distance to the hitpoint would help you getting the same height on any point over your terrain... Have a look at some camera scripts over at www.unifycommunity.com - they could help you with this stuff

    BTW: in a "standard" Unity scene "x" is left/right "y" is up/down and "z" forward/backward (the depth)... So you are looking for setting the x&z coordinates and keep the y coordinate at a constant height over the ground - right?

    Rock On!
     
  11. MutantSurvivor

    MutantSurvivor

    Joined:
    Jan 4, 2010
    Posts:
    13
    OK, finally I have had a chance to get on with this and it is working to an extent.

    I imported the uniTUIO scripts into my movie, attached a BBTouchEventManager and also a BBBasicTouchManipulation to an object (and set the Rendering Camera to the Main Camera I am using).

    I also added a getTuioObject method to the inputController to allow me to retrieve the Tuio Object by its ficucial marker id.

    I created a script which I have attached here which I attached to the Camera. I have not yet implemented the rotation component of the motion, just the position) It kind of works but is very sporadic, it tends to move a couple of times but then stops.

    Anyone any ideas what is causing the problem?
     

    Attached Files:

  12. Sandor

    Sandor

    Joined:
    Apr 17, 2009
    Posts:
    91
    Hey, thanks for posting this. But it is hard to say something to the problems without knowing the changes you made to the "BBInputController" script... Please post that also here, or send it to me and i will have a look at...

    Cheers,
     
  13. MutantSurvivor

    MutantSurvivor

    Joined:
    Jan 4, 2010
    Posts:
    13
    I am at work at the moment so don't have the file on me will upload it tonight.

    All I did to the inputCOntroller was create a function that is pretty much like this (written in kind of phpish psuedcode as I am not used to c# and can't rememer exactly what I wrote)

    public TuioObject getTuioObject(int f_id) {
    to = null; // var to hold object
    objects = Client.getTuioObjects();
    foreach(objects as o){
    if (o->getFId() == f_id){ to = o; }
    }
    return to;
    }

    This seems to be working fine as far as I can tell.
     
  14. Sandor

    Sandor

    Joined:
    Apr 17, 2009
    Posts:
    91
    no hurry with the script. Take your time till you have your hands on your code...

    Cheers,
     
  15. MutantSurvivor

    MutantSurvivor

    Joined:
    Jan 4, 2010
    Posts:
    13
    Here is the modified BBInputController class.

    I suppose really I should have extended it and added the methods in there (there is also a method to just output a string representation of the object that I was using in a prior iteration of the testing) in case things get updated. I will do this soon.
     

    Attached Files:

  16. tinmanassets

    tinmanassets

    Joined:
    Jan 6, 2009
    Posts:
    61
    Hey Mutantsurvivor!

    Sorry it has taken me a few days to get over here, sandor has been reminding me, but the time gets away from me..

    anyhow. What you want to do is really implement these three methods in the BBInputController:

    public void addTuioObject(TuioObject o) {}
    public void updateTuioObject(TuioObject o) {}
    public void removeTuioObject(TuioObject o) {}

    This is where all the fiducial object info is going to be coming in and it is sent to the BBInputController much like the touches on the iPhone (ie touch down == addObject, touch move == update object, and touch up == remove object) this makes it nice and easy to keep track of all your touch events.

    Unfortunately I haven't had time to build that other half of the input stream (ie non-cursors) so my apologies for that. But you basically just need to put in those three methods above (they can be very similar to the matching cursor methods. (probably add a new instance var: objectDidChange.. and then in the refresh: method, be sure to call the eventDelegate.finishFrame and reset your objectDidChange.

    TUIOcursors and TUIOobjects are very similar and you might be able to just get away with treating the objects like cursors, but if not then just add a few special cases to BBTouchEventManager (and maybe add a fid id to the BBTouchEvent class) and then everything else should work after that.

    I realize that this might be a big change, but if you get stuck, let me know and I will find a few hours to throw at it for yah.

    Cheers!
    -B
     
  17. MutantSurvivor

    MutantSurvivor

    Joined:
    Jan 4, 2010
    Posts:
    13
    Many thanks for that Ben, it is late and I am about to go to bed so can't really digest it properly but it looks like you have given me some good leads.

    Will be getting on with it tomorrow evening I suspect, needs to be soon as the artifact we are making is in an exhibition opening in a week and I still have to build the table (and go to work and look after my daughter).

    I my need a bit of help so your offer is greatly appreciated, will take a look when I am fresher, see if I can make sense of it and get back to you.

    Once again many thanks
     
  18. Sandor

    Sandor

    Joined:
    Apr 17, 2009
    Posts:
    91
    Glad to see that you guys found together! Don't hesitate to PM me if you need some help/advise with your table - there I can be more helpfull than with the C# stuff...

    Cheers,

    Sandor
     
  19. MutantSurvivor

    MutantSurvivor

    Joined:
    Jan 4, 2010
    Posts:
    13
    OK Ben, I am a bit rusty at this sort of programming to be honest (my day job is php/symfony) web development. I used to do a load of flash, director and prior to that java stuff but it has been a couple of years.

    I have taken a good look through the classes in light of your message and I think I know what is going on a bit more now. I see that I will get a lot more mileage out of using the callback events (by way of the methods that you mentioned in the inputController).

    I think that one approach could be to simply use the cursor methods already in the TouchEventManager to control TouchEvent object (strictly speaking I should write matching Tuio methods but am pushed for time) but am not sure how I should then use the TouchEvents to control my camera. Any suggestions?

    Will be working on this (and need to get it finished) at the weekend so any more help, hints and suggestions will be very gratefully recieved.

    Manay thanks

    Mutant
     
  20. tinmanassets

    tinmanassets

    Joined:
    Jan 6, 2009
    Posts:
    61
    Hey Mutant,

    The way I have done it previously is to make a big touchable collider that sits in front of the camera and covers the whole visible rect. That object moves when the camera moves etc.. (you can probably just make the collider a child of the camera)

    Then have the touches that are intercepted on that object move the camera around. (so lets say you get a touch that is to the right of center, you might move the camera to the right, or rotate it to the right around some central axis etc.. )

    Cheers!
    -B
     
  21. MutantSurvivor

    MutantSurvivor

    Joined:
    Jan 4, 2010
    Posts:
    13
    Hi Ben

    Not really sure what a collider is or how it works. Is it an easy thing to do.

    What I need is to define a rectangle of x and z coordinates which correspond to the limits of the scene I am viewing (using their coordinates rather than world as it is the parent of the camera) and to have this correspond with the rectangle ot the TUIO table (ie when the object is in the bottom left of the table, the camera will likewise be at the the bottom left of the model and pointing in the direction that the object is pointing) All positions of the object/camera are absolute (well relative to the parent scene) rather than relative to where it was before as is more traditional in a game.

    So I just need to read in the position of the object (I am assuming it goes from 0 to 1 in each axis) and its angle and set the transform of the camera to that.
     
  22. tinmanassets

    tinmanassets

    Joined:
    Jan 6, 2009
    Posts:
    61
    Hey Mutant,

    Colliders are pretty easy, but your last description makes me think that using a BBTouchable object may be a bit overkill for what you are looking to do..

    Instead, have a look at the BBCrosshairController object. It gets access to all the events and uses their screen positions to position a crosshair on the screen.

    You could make a subclass of that (or just add some extra code to that class) and you would have easy access to all the touch events and their screen positions.

    This route sounds more like what you would want to do to achieve what you are talking about. Basically you would grab the first touch event, get the screen coordinates, then translate the camera object to the resulting model position (via either some math, or some map of some sort)

    Cheers!
    -B
     
  23. MutantSurvivor

    MutantSurvivor

    Joined:
    Jan 4, 2010
    Posts:
    13
    Hey Ben,

    Well I have made quite a bit of progress. Basically I made the 3 methods in the InputCotroller act as the Cursor ones were and wrote 3 corresponding methods in the TouchEventManager

    I left the up and down methods empty and wrote the move method as follows.
    Code (csharp):
    1.  
    2.     public void objectCursorMove(TuioObject o){
    3.         if(this.hasMoved(o)){
    4.             MyCamera.transform.localPosition    = this.getTransformPosition(o.getPosition());
    5.             MyCamera.transform.localEulerAngles = this.getTransformEulerAngles(o.getAngle());
    6.         }
    7.        }
    8.  
    I also added methods to test if it had moved (hasMoved) and to determine the transform position and Euler Angle from the object (getTransformPosition and getTransformEulerAngles)

    It seems to be working pretty well. Only thing is I keep getting the following error
    Code (csharp):
    1.  
    2. m_ThreadCheck  !Thread::EqualsCurrentThreadID(m_ThreadID)
    3.  
    A quick scout around this forum tells me that this is because I am calling API functions from a thread other than the main one. I am not sure where this thread is (haven't done any thread stuff for years) or how I can call stuff not from it. I get the impression that it may not be a problem. Any ideas?

    The other problem I have is that it runs fine on my laptop (First gen Intel MacBook) but on my partner's G5 MacBook it runs very slowly and jerkily. For the actual installation we will be using a G5 iMac which may well be worse. I guess we have to simplify the model or animation in order to give the processor a bit of a break but it is a bit of a pain.
     
  24. MutantSurvivor

    MutantSurvivor

    Joined:
    Jan 4, 2010
    Posts:
    13
    Hey Ben,

    Well I have made quite a bit of progress. Basically I made the 3 methods in the InputCotroller act as the Cursor ones were and wrote 3 corresponding methods in the TouchEventManager

    I left the up and down methods empty and wrote the move method as follows.
    Code (csharp):
    1.  
    2.     public void objectCursorMove(TuioObject o){
    3.         if(this.hasMoved(o)){
    4.             MyCamera.transform.localPosition    = this.getTransformPosition(o.getPosition());
    5.             MyCamera.transform.localEulerAngles = this.getTransformEulerAngles(o.getAngle());
    6.         }
    7.        }
    8.  
    I also added methods to test if it had moved (hasMoved) and to determine the transform position and Euler Angle from the object (getTransformPosition and getTransformEulerAngles)

    It seems to be working pretty well. Only thing is I keep getting the following error
    Code (csharp):
    1.  
    2. m_ThreadCheck  !Thread::EqualsCurrentThreadID(m_ThreadID)
    3.  
    A quick scout around this forum tells me that this is because I am calling API functions from a thread other than the main one. I am not sure where this thread is (haven't done any thread stuff for years) or how I can call stuff not from it. I get the impression that it may not be a problem. Any ideas?

    The other problem I have is that it runs fine on my laptop (First gen Intel MacBook) but on my partner's G5 MacBook it runs very slowly and jerkily. For the actual installation we will be using a G5 iMac which may well be worse. I guess we have to simplify the model or animation in order to give the processor a bit of a break but it is a bit of a pain.