Target Orbiting Camera

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Target Orbiting Camera

Post by Midnight »

Ok for my game I need a camera that orbits a ship in space now I have a basic understanding of how to go about this and I figure I'll create a class based off of the FPS camera.

What I need help with is the math for the sphere it will travel on.

I want it to have zoom and the object it targets moves in all directions because it is a space ship.

I know this deals with PI and obviously the radius will be the distance from object and I'd like to add collision so the camera won't get closer then a certain distance either colliding with the mesh or with a sphere that is just big enough to get all of the target inside and not closer.

does anyone have a working demo of this or know where i can get outside help or is this easy and I'm just uneducated?

it will take me a huge amount of time to figure out how to render this properly as the camera position will need to update for the targets movement and it's relative position to the target.

if you don't know what I mean then image the camera in the game Nexus thats the sort of effect I'm after here.

can anyone help?
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

It sounds like you want to use spherical coordinates. Given a spherical coordinates, you can easily get cartesian coordinates which you would use to figure out where to put the camera.

This page will be of some help, but the only thing you really need to know is...

Code: Select all

  //r is the radius of the sphere
  //Φ is the angle up from the equator of the sphere [0 to 180°]
  //Θ is the angle around the equator of the sphere [0 to 360°]

  x = r * cos(Θ) * sin(Φ);
  y = r * sin(Θ) * sin(Φ);
  z = r * cos(Φ);
All you need to do is write code to maintain r and the angles Θ and Φ. When one of them changes, you update x,y,z which gives you the offset from the center of the sphere.
Last edited by vitek on Tue Nov 14, 2006 12:54 am, edited 1 time in total.
Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Post by Midnight »

you're the man vitek your on it like a bonnet man.

I think you gave me everything I needed to know here thanks a bunch dude. 8)


Edit:

ok sry new question.

how do I setup the sphere?
is there anything special about the symbols for azimuth and zenith and how the heck do i setup those circles?

also isn't sin and cos built into a class somewhere like in windows?

and one more thing how and when do i update the position of the sphere to the new ship coordinates?

sry to sound like a needy noob here but I never took trig or calculus in school so this is all new to me not to mention I've been dwelling in 2d gui for 2 years now.

would it be too much to ask for a simple example?
I never seen this done before with anything so i have no frame of reference to work from here.

any additional information would help a lot thanks.
Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Post by Midnight »

ok after thinking on it awhile I remembered the rotation variables so that answers my circle question i guess.

"sigh"

man this stuff is hard to conceptualize.

ok so azimuth would be x,z rotation and zenith is y rotation right?

radius is distance from cam to target now how do I get all these coords in order.. first i need the ships position and set cameras position to a default spot like 20 units away and directly behind the model and a little above it.

this is really really confusing me. jump one hurdle only to find a bigger one on the other side.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

how do I setup the sphere?
You just create 3 variables somewhere [Radius, Theta, Phi], use them to get cartesian coordinates, and use the cartesian coordinates to update the camera position.
is there anything special about the symbols for azimuth and zenith?
I'm not quite sure what you are asking. I see nothing about them as being special.
also isn't sin and cos built into a class somewhere like in windows?
Yes, sin and cos are math functions from the standard C library. You might have to include <math.h>
how and when do i update the position of the sphere to the new ship coordinates?
There is really no sphere. The use of spherical coordinates is just a way to calculate the position of the camera relative to come other object [eg the center of the sphere]. Just keep in mind that the center of the sphere is the center of the object you want the camera to move around. The spherical coordinates make it so that you can easily move the camera around the object in a spherical orbit. The cartesian coordinates you get is where you need to put the camera relative to the ship.
would it be too much to ask for a simple example?
No problem...

Code: Select all

#include <irrlicht.h> 
#pragma comment(lib, "Irrlicht.lib") 

using namespace irr;

class MyEventReceiver : public IEventReceiver
{
public:
   MyEventReceiver()
   {
      u32 k;
      for (k = 0; k < sizeof(Keys) / sizeof(*Keys); ++k)
         Keys[k] = false;
   }

   virtual ~MyEventReceiver()
   {
   }

   // you may need to change the parameter type depending on your Irrlicht version
   virtual bool OnEvent(const SEvent& event)
   {
      if (event.EventType == EET_KEY_INPUT_EVENT)
      {
         Keys[event.KeyInput.Key] = event.KeyInput.PressedDown;
         return true;
      }

      return false;
   }

public:
   bool Keys[KEY_KEY_CODES_COUNT];
};

int main()
{ 
   // create device and exit if creation failed 
   IrrlichtDevice *device = createDevice(EDT_DIRECT3D9, core::dimension2d<s32>(800, 600), 32, false, false, false);
   if (device == 0) 
      return 1; // could not create selected driver.

   MyEventReceiver receiver;
   device->setEventReceiver(&receiver);

   video::IVideoDriver* driver = device->getVideoDriver(); 
   scene::ISceneManager* smgr = device->getSceneManager(); 

   // the thing we want to look at
   scene::ISceneNode* box =
      smgr->addCubeSceneNode();

   // add camera
   scene::ICameraSceneNode* cam =
      smgr->addCameraSceneNode(box);
   cam->setTarget( box->getAbsolutePosition() );

   // add a dynamic light
   smgr->addLightSceneNode(0, core::vector3df(-20, 0, 0), video::SColorf(1.f, 0.f, 0.f, 1.f));
   smgr->addLightSceneNode(0, core::vector3df(0, -20, 0), video::SColorf(0.f, 1.f, 0.f, 1.f));  
   smgr->addLightSceneNode(0, core::vector3df(0, 0, -20), video::SColorf(0.f, 0.f, 1.f, 1.f));

   f32 Radius = 20.f;
   f32 Theta  = 180.f; // degrees
   f32 Phi    = 90.f; // degrees

   f32 LinearVelocity = 20.f;
   f32 AngularVelocity = 40.f;

   u32 oldNow = device->getTimer()->getRealTime();

   while(device->run()) 
   {
      // calculate elapsed time as fractional seconds
      u32 now = device->getTimer()->getRealTime();
      f32 Elapsed = (now - oldNow) / 1000.f;
      oldNow = now;

      // window is active, so render scene
      if (device->isWindowActive())
      {
         if (driver->beginScene(true, true, video::SColor(255, 100, 100, 140)))
         {
            smgr->drawAll();

            driver->endScene();
         }

         // adjust camera position based on current key input
         if (receiver.Keys[KEY_NUMPAD1])
            Radius -= (LinearVelocity * Elapsed);
         if (receiver.Keys[KEY_NUMPAD3])
            Radius += (LinearVelocity * Elapsed);
         if (receiver.Keys[KEY_NUMPAD4])
            Theta += (AngularVelocity * Elapsed);
         if (receiver.Keys[KEY_NUMPAD6])
            Theta -= (AngularVelocity * Elapsed);
         if (receiver.Keys[KEY_NUMPAD8])
            Phi += (AngularVelocity * Elapsed);
         if (receiver.Keys[KEY_NUMPAD2])
            Phi -= (AngularVelocity * Elapsed);
         if (receiver.Keys[KEY_NUMPAD5])
         {
            Theta = 180.f;
            Phi   = 90.f;
         }

         // prevent camera from walking into our box
         if (Radius < 10.f)
            Radius = 10.f;

         // lame ass gimble lock prevention. if you don't want to do this
         // you need to adjust the up vector of the camera so it never is
         // parallel to the look at vector
         if (Phi < 10.f)
            Phi = 10.f;
         else if (170.f < Phi)
            Phi = 170.f;

         f32 sinOfPhi = sinf(Phi * core::DEGTORAD);
         f32 cosOfPhi = cosf(Phi * core::DEGTORAD);

         f32 sinOfTheta = sinf(Theta * core::DEGTORAD);
         f32 cosOfTheta = cosf(Theta * core::DEGTORAD);

         core::vector3df offset;

         // these are switched around a little from what i posted above
         offset.X = Radius * sinOfTheta * sinOfPhi;
         offset.Y = Radius * cosOfPhi;
         offset.Z = Radius * cosOfTheta * sinOfPhi;

         // camera is a child of the cube, so our offset is actually
         // the position of the camera
         cam->setPosition(offset);
         cam->setTarget( box->getAbsolutePosition() );
         cam->updateAbsolutePosition();

         wchar_t caption[128];
         swprintf(caption, 128, L"r=%f theta=%f phi=%f",
            Radius, Theta, Phi);

         device->setWindowCaption(caption);
      }
   }

   device->drop(); 

   return 0; 
}
Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Post by Midnight »

uuuu is niice yeah.

I liike.

vitek you have saved me such a headache you are my hero. 8)

Now all i have to do is add in mouse control and zoom and wrap it in a nice class and I think I'll post it in the snippet section when it's done.
Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Post by Midnight »

Need some help please!
First I started with FPS cam.

I call it the Orb cam. short for Spherical Camera (too long)

anyways heres the code I compiled once with irr 1.0 by mistake it worked but the model was invisable that was using the node for sydney as the animated mesh wouldn't work. 3d box was disabled in 1.0 or different maybe.

anyways I fixed it to 1.1 and it compiles fine but crashes using anything as the parent or "target" (which is nessesary for the cam obviously)

I'm not the greatest coder and without compile errors I'm kinda lost maybe somebody can take a look?





Edited for nudity... it was the full kind you missed it sry
Last edited by Midnight on Mon Nov 27, 2006 7:28 am, edited 1 time in total.
Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Post by Midnight »

sry bout the last one wasn't able to fix but here is a repost



EDIT:: ok that didn't work I'll setup the file for download in the morning its late the main file is there I'm sure you can guess the missing parts for now
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

I don't think that I would make a custom camera node for this purpose. I would drive the camera from somewhere else, much like I did in my sample code.

Travis
Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Post by Midnight »

why not?
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

Because it doesn't make sense to make a new camera type for every different way you want the camera to behave.

What if I want to make a camera that only moves vertically, but can look left/right with keyboard input? I would have to implement another complete camera class, when all I really needed to do was write a small class to move/rotate the camera given the inputs from the keyboard and mouse.

This is really more about separating responsibilities and design than anything. By doing this, classes become simpler and more powerful. The camera class is responsible for maintaining the view and projection matrices and hooking them into the scene graph, while the fictional camera controller class would be responsible for moving and manipulating the camera itself.

Travis
Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Post by Midnight »

fair enough.

but irrlicht is the way it is and right now I'm trying to escape a bug and the FPS cam doesn't seem to have.

this class is what I want and I'd like help with it if you can please.
xhrit
Posts: 140
Joined: Mon Jun 14, 2004 8:54 am
Location: earth
Contact:

...

Post by xhrit »

just use a plain old camera and do all the changes from an outside class using complex maths.
Core2Duo E8400 3.0ghz - 2048mb DDR2 800 - geForce 9600 - Slackware12.1

Word-image-symbol programming limits, controls, and imprisons the individual.
Smash the control images, smash the control machine.
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

Midnight, I'm casually interested in helping, but there's no way that I'm going to start copying and pasting that amount of code in the hope that it's compilable as-is. Could you zip up all of your source and any build files and necessary resources (other than the ones in Irrlicht), and upload it somewhere? If you can get this to a stage where it's: unzip -> compile* -> run, then I'll try and figure out what's going on.

(* Ideally on Windows using MSVC6/7/8)
Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Post by Midnight »

ok I'll sort it out... just been addicted to this new game for awhile called carpe diem.. I need some time lol
Post Reply