Camera Auto Panning

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
Desconocido
Posts: 9
Joined: Mon Aug 31, 2009 12:00 am

Camera Auto Panning

Post by Desconocido »

So basically, what I'm trying to accomplish is a camera that automatically pans/moves forward slowly, as seen in some platforming games, or top-down helicopter shooters (what I'm aiming at now).

So far I've come up with the following function:

Code: Select all

void render::Camera(float sY, float eY)
{
	float cY = sY;
	float LastFrame = cY;
	float CurrentFrame = cY+1;

	if(LastFrame == CurrentFrame)
		CurrentFrame = CurrentFrame + 1;
	if(LastFrame > CurrentFrame)
		CurrentFrame = LastFrame;
	if(CurrentFrame <= eY)
	{
		LastFrame = LastFrame + 1;
		rScene->addCameraSceneNode(0, vector3df(0, CurrentFrame, 0), vector3df(0, CurrentFrame, 10));
	}
}
cY is equal to Camera Y(Currnet Y Position), sY is Start Y (where I start panning), and eY is End Y (when panning should stop). Unfortunatly tho this code just displays the camera at the start Y, and does not move at all. I thought maybe it was because it wasnt being consitently being updated, but running while(CurrentFrame <= eY) instead of if(CurrentFrame <= eY), just presents me with a white screen, not loading anything. Any and all help is appreciated, thanks in advance!
Image
DtD
Posts: 264
Joined: Mon Aug 11, 2008 7:05 am
Location: Kansas
Contact:

Post by DtD »

So you want a camera that slowly follows the user as opposed to always being on him?

Well, first of all, you're creating a camera every frame, which well lead to huge memory leaks, among other things. You should move the old one with camera->setPosition and camera->setTarget.

~DtD
Desconocido
Posts: 9
Joined: Mon Aug 31, 2009 12:00 am

Post by Desconocido »

Noo, I dont want the camera to follow the user, I just want it to move automatically along the y axis. The user will control a player model, but the model will not go out side of the screen, and will thus inexitably move forward as the camera does. I hope that clarifies this some?
Image
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

You could use a scene node animator to move the camera. Unfortunately, this won't update the camera target, only the camera position. You can update the target manually...

Code: Select all

scene::ICameraSceneNode* camera = smgr->addCameraSceneNode();

// this will move the camera...
core::ISceneNodeAnimator* anim = smgr->createFlyStraightAnimator(beg_pos, end_pos, time_to_fly);
  camera->addAnimator(anim);
anim->drop();

while (device->run())
{
  if (driver->beginScene(...))
  {
    smgr->drawAll();
    driver->endScene();
  }

  const core::vector3df camera_pos = camera->getAbsolutePosition();

  // make sure the camera looks straight down
  const core::vector3df target_pos(camera_pos.X, camera_pos.Y - 100.f, camera_pos.Z);
  camera->setTarget(target_position);
}
You could also write your own animator to update the camera target. It would be essentially the same as the implementation of the fly straight animator, so it would be copy and paste for the most part.

Of course you could just do it all manually...

Code: Select all

const core::vector3df beg_pos;(...);
const core::vector3df end_pos(...);
const f32 time_to_fly = 60.f; // 60 seconds
f32 time_flying = 0.f;

u32 prev_time = timer->getTime();
while (device->run())
{
  const u32 curr_time = timer->getTime();
  const f32 elapsed_time = (curr_time - prev_time) / 1000.f;
  prev_time = curr_time;

  time_flying += elapsed_time;
  f32 percent0to1 = time_flying / time_to_fly;
  if (1.f < percent0to1)
    percent0to1 = 1.f;

  const core::vector3df camera_pos = beg_pos.getInterpolated(end_pos, percent0to1);
  camera->setPosition(camera_pos);

  const core::vector3df target_pos(camera_pos.X, camera_pos.Y - 100.f, camera_pos.Z);
  camera->setTarget(target_pos);
  
  // render the scene like normal
}
Travis
Desconocido
Posts: 9
Joined: Mon Aug 31, 2009 12:00 am

Post by Desconocido »

thanks man! Definitely helpful :). I'll try it tomorrow if I can.
Image
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

By the way, the code you posted is very weird. I'm going to add some comments just to show how weird it is..

Code: Select all

void render::Camera(float sY, float eY) 
{ 
   float cY = sY; 
   float LastFrame = cY; 
   float CurrentFrame = cY+1; 

   // since LastFrame is cY and CurrentFrame is cY + 1, this is equivalent
   // to 
   //
   //   if (cY == (cY + 1))
   //
   // with floating point numbers, this is actually possible, when the value
   // of cY gets sufficiently large, but I don't think this is what you are
   // trying to check for. Assuming that cY is less than 10e5, this test
   // should always fail.
   //
   if(LastFrame == CurrentFrame) 
      CurrentFrame = CurrentFrame + 1; 

   // since LastFrame is cY and CurrentFrame is cY + 1 or cY + 2, this is
   // roughtly equivalent to
   // 
   //    if (cY > (cY + 1))
   //
   // or
   // 
   //    if (cY > (cY + 2))
   //
   // with floating point numbers, this is never possible. Any floating point
   // number + 1 will always give a result that is greater than or equal to
   // that number. There may be some rounding error, but it will never be
   // less than the original. So this expression will always fail, regardless of
   // the values of LastFrame and CurrentFrame.
   //
   if(LastFrame > CurrentFrame) 
      CurrentFrame = LastFrame; 

   // this could be simplified to 
   //
   //    if ((cY + 1) <= eY)
   //
   // but I'm not sure if that will actually do what you want. None of the
   // logic in this function seems to make any sense.
   if(CurrentFrame <= eY) 
   { 
      // incrementing LastFrame, which is a local variable, will have no
      // effect on the result of this function. when the function returns
      // the variable LastFrame will be destroyed, so why increment it?
      LastFrame = LastFrame + 1; 

      // as pointed out earlier, you are creating a new camera every time
      // the condition CurrentFrame <= eY is true. this is very bad.
      rScene->addCameraSceneNode(0, vector3df(0, CurrentFrame, 0), vector3df(0, CurrentFrame, 10)); 
   } 
} 
Travis
Post Reply