How to apply newton physics on 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!
Post Reply
RapchikProgrammer
Posts: 279
Joined: Fri Dec 24, 2004 6:37 pm

How to apply newton physics on camera?

Post by RapchikProgrammer »

Hey all! I am making a game and i am really stuck on this part! How the heck do i apply newton physics on a camera? I mean i can apply the physics on everything but how to do it on the camera?

I am using this technique, i make a newton sphere and place the camera inside it! Then as the camera moves it would move! But now how does the camera move? I cant move in the forward direction with this code and secondly all the movement is not at all smooth its very jerky! So anyone knows a way to solve this problem! I mean how to move and strafe!
Mecharius
Posts: 17
Joined: Wed Jun 07, 2006 7:05 am

Post by Mecharius »

Hey,
I can think of two options...
Firstly just get the position of the scenenode that the Newton sphere represents every frame and then move the camera to match...

Code: Select all

core::vector3df location;
location = mySceneNode->getAbsolutePosition();
camera->setPosition(location);

The second - easier - way to is make the camera a child of the scenenode...

Code: Select all

mySceneNode->addChild(cameraSceneNode);
RapchikProgrammer
Posts: 279
Joined: Fri Dec 24, 2004 6:37 pm

Post by RapchikProgrammer »

I have tried making the camera a child but even then i dont figure out how to move the collision sphere or to remove the jerky motion!
Mecharius
Posts: 17
Joined: Wed Jun 07, 2006 7:05 am

Post by Mecharius »

Not sure, I've got it working ok with the first method (just setting the position of the camera).

Maybe its your Newton settings that are causing the jerky motion?

Are you using an FPS camera?
kruseborn
Posts: 2
Joined: Fri Aug 04, 2006 1:28 pm

Post by kruseborn »

Hi!

I have the same problem and have try to fixed it all day now.
I have tested to do
core::vector3df location;
location = mySceneNode->getAbsolutePosition();
camera->setPosition(location);
but it does not work, the sphere is not attacht to the body.

and when i do mySceneNode->addChild(cameraSceneNode);
its attacht but the camera fps is not working, if i am pushing to move forward nothing happens.

you think you can post all your code here, the one you got working.
it would realy help me alot.

/kruseborn
RapchikProgrammer
Posts: 279
Joined: Fri Dec 24, 2004 6:37 pm

Post by RapchikProgrammer »

I am going making my game opensource, but believe me the mess my code is rit now you wont be able to understand one bit! I am actually rewriting all the code to have atleast something better than the mess i hav rit now!
And how are you doing it mecharius! Can u post some of ur code or any example app, cause this problem is really making me mad! And about my camera! I am using an fps camera without the movement controls! The idea is i'll still get the camera rotation from mouse as its an fps camera but no movement as an fps might go through the sphere, so no movement using fps camera! I am thinking about using my own movement but the event method allows me only jerky motion and still i cant go forward! I mean in the direction of the camera! So there are a lot of problems! Another problem i have:

Code: Select all

NewtonBodyGetMatrix(phyBody, &mat.M[0]); 
mat.setTranslation(pos * IrrToNewton); 
NewtonBodySetMatrix(phyBody, &mat.M[0]);
I use the above code to move my bsp file in my bsp class and it works without a problem! But i then use it in my model class to move my model and it gives me a send/dont send error! The common windows error!
RapchikProgrammer
Posts: 279
Joined: Fri Dec 24, 2004 6:37 pm

Post by RapchikProgrammer »

Im very very stuck here! If anyone could give me some help here i would really like it!
needforhint
Posts: 322
Joined: Tue Aug 30, 2005 10:34 am
Location: slovakia

Post by needforhint »

I think you should read info you need in Newton tutorial, where they show a level geometry load and have some 3rd person elipse in it. you should simulate that and return the transform of that elipse to you camera. So do this with your newton result transform:

Code: Select all

core::matrix4 NewtonTransMatrix = Newotnblabla;
CameraNode.GetAbsoluteTransformation() = &NewtonTransMatrix;
but you might want to not touch the rotation of camera; so set the rotationcamera back as it was, so this might be the finall code

Code: Select all

// with this you store newton untransformed camera rotation
core::vector3df inputRot = CameraNode.GetRotation();
// now to get the physique transformation matrix of newton elipse agent
core::matrix4 NewtonTransMatrix = Newotnblabla;
CameraNode.GetAbsoluteTransformation() = &NewtonTransMatrix;
// and now set the prevoious rotation of camera again;
 CameraNode.SetRotation(inputRot);


what is this thing...
Zeuss
Posts: 114
Joined: Mon Nov 08, 2004 9:02 pm
Location: Canberra - Australia
Contact:

Post by Zeuss »

I've found attaching the camera to a newton object thats moving to be very shakey, and not useable (you get shearing and other nasty effects). So you have to make a list of object positions over say the last 10th of a second, and use the average from that.

Are you attaching the camera to an object so it can collide and interact with the newton world?

If so, you could always just add a force on the sphere in the direction you wish to travel. But won't be fun on hills and stuff. Have the camera rolling around. The force will always be in the direction the camera is facing, and the strafe will be a multiple of the right vector.

This can be obtained like this:

Code: Select all

matrix4 CameraMatrix = Camera->getRelativeTransformation();

core::vector3df ForwardsDirection( CameraMatrix.M[0], CameraMatrix.M[1], CameraMatrix.M[2] );
core::vector3df RightDirection( CameraMatrix.M[8], CameraMatrix.M[9], CameraMatrix.M[10] );
The force has to be applied within the Apply Force and Torque callback.
Help make Irrlicht even Better! Create and submit your own Irrlicht Extension
Want a Games Education? Try The Academy of Interactive Entertainment
RapchikProgrammer
Posts: 279
Joined: Fri Dec 24, 2004 6:37 pm

Post by RapchikProgrammer »

I am still havin probs!!! Heres my code:

Code: Select all

bool Engine::OnEvent(SEvent event) 
{ 
   if(event.KeyInput.PressedDown) 
   { 
   if(event.KeyInput.Key == KEY_KEY_W) 
      movingforward = true; 

   vector3df forwardVector; 
   vector3df pos = cam->getPosition(); 
    vector3df rot = cam->getTarget(); 

      const float offset = 90.0f; 
      const float pi_div_180 = 0.0174532f; 
      core::vector3df movevect(sin((rot.Y)*pi_div_180), (NEWTON_GRAVITY)?(0):(-sin((rot.X)*pi_div_180)), cos((rot.Y)*pi_div_180)) ; 
      movevect.normalize(); 
      core::vector3df strafevect(sin((rot.Y+offset)*pi_div_180), 0.0f, cos((rot.Y+offset)*pi_div_180)) ; 
      strafevect.normalize(); 

      core::vector3df goal_vel(0,0,0) ; 

      float MoveSpeed = 12.0f; 

      if (movingforward) 
         goal_vel += movevect ;//* ((f32) App->elapsedTime * MoveSpeed * IrrToNewton * 2.0f); 
      if (movingbackward) 
         goal_vel -= movevect ;//* ((f32) App->elapsedTime * MoveSpeed * IrrToNewton); 
    

      if (strafingleft) 
         goal_vel -= strafevect ;//* ((f32) App->elapsedTime * MoveSpeed * IrrToNewton); 
      if (strafingright) 
         goal_vel += strafevect ;//* ((f32) App->elapsedTime * MoveSpeed * IrrToNewton); 

      goal_vel.setLength(MoveSpeed); 

      //goal_vel *= * (f32) App->elapsedTime * MoveSpeed * IrrToNewton; 
       
      core::vector3df current_vel ; 
      NewtonBodyGetVelocity(camBody, &current_vel.X); 
       
      core::vector3df accel = ((goal_vel-current_vel) / NewtonGetTimeStep(phy->nWorld) ) * 0.5f; 

      if (NEWTON_GRAVITY) 
         accel.Y = 0; 
      nm->force = accel; 
       
    //cam->setPosition(pos); 

   } 
   if(!event.KeyInput.PressedDown) 
   { 
      movingforward = false; 
   } 
   return false; 
} 
I took the code from some place i dont remember!

And here's the apply force and torque event code:

Code: Select all

void Physics::ApplyForceAndTorqueEvent (const NewtonBody* body) 
{ 
   float mass; 
   float Ixx; 
   float Iyy; 
   float Izz; 

   NewtonBodyGetMassMatrix (body, &mass, &Ixx, &Iyy, &Izz); 

   vector3df force; 
   newtonMesh* nm = (newtonMesh *)NewtonBodyGetUserData(body); 
   force = nm->force; 
   force.Y += NEWTON_GRAVITY * mass * IrrToNewton; 

   vector3df torque (0.0f * IrrToNewton, 0.0f * IrrToNewton, 0.0f * IrrToNewton);  
    
   NewtonBodyAddForce (body, &force.X); 
   NewtonBodyAddTorque (body, &torque.X); 
   nm->force.set(0,0,0); 
} 
Mikenoworth
Posts: 78
Joined: Sat May 27, 2006 9:24 pm
Location: Logan, UT

Post by Mikenoworth »

What are your current problems?

You might want a seperate apply force & torque callback especially made for your camera. This way you can tweak what happens when force and torque is applied to it. Ie. Exclude the set torque code to ignore torque alltogether.

I cleaned up your code, removed some stuff, yaddayadda. I'm guessing your storing accel for some reason other than to pass it to newton.

Code: Select all

bool Engine::OnEvent(SEvent event) 
{ 
   if(event.KeyInput.PressedDown) 
   {    		
		// Notes:
		//
		// You don't want to calculate for newton units until everything is
		// ready to be passed into newton, keeps your code looking clean.
				
		//vector3df pos = cam->getPosition(); 
		//vector3df rot = cam->getTarget(); 

		const float SPEED = 10.0f;

		//const float offset = 90.0f;		
		//const float pi_div_180 = 0.0174532f; 

		// We'll use Zuess's helpful insight to get the forward, up, and right
		// vectors of the camera.
		matrix4 CameraMatrix = Camera->getRelativeTransformation(); 
		vector3df forwardvector	( CameraMatrix.M[0], CameraMatrix.M[1], CameraMatrix.M[2]  ); 
		vector3df rightvector	( CameraMatrix.M[8], CameraMatrix.M[9], CameraMatrix.M[10] ); 
		vector3df upvector		( CameraMatrix.M[4], CameraMatrix.M[5], CameraMatrix.M[6]  ); 

		// here is the end result vector, used as the force
for the cameras rigid body.
		core::vector3df movement;		
	  
		// forwards..
		if(event.KeyInput.Key == KEY_KEY_W)
			movement = forwardvector * SPEED;    // multiply by speed to adjust how fast the movement is.
		// backwards..
		if(event.KeyInput.Key == KEY_KEY_S)
			movement = -forwardvector * SPEED;
		 // left movement..
		if(event.KeyInput.Key == KEY_KEY_A)
			movement = -rightvector * SPEED;
		// right movement..
		if(event.KeyInput.Key == KEY_KEY_D)
			movement = rightvector * SPEED;
    
		// Same thing as you did in your code.. (?) calc acceleration and store it.
		core::vector3df current_vel; 
		NewtonBodyGetVelocity( camBody, &current_vel.X );
		core::vector3df accel = ( (movement - current_vel) / NewtonGetTimeStep(phy->nWorld) ) * 0.5f; 

		if (NEWTON_GRAVITY) 
			 accel.Y = 0; 
		
		nm->force = accel;

		// You can use NewtonBodyAddForce to add to the bodies current force,
		// or you can use NewtonBodySetForce to set the force exactly to this amount.
		// I don't know how extreme newtons force vectors tend to be, so you will
		// want to play with the constant SPEED.
		movement *= IRR_TO_NEWTON;
		NewtonBodySetForce( camBody, &movement.X );
		//NewtonBodyAddForce( camBody, &movement.X );		
	} 

	return false; 
I don't see any immediate errors in the code, but if you get any just tell me.
Stout Beer
RapchikProgrammer
Posts: 279
Joined: Fri Dec 24, 2004 6:37 pm

Post by RapchikProgrammer »

Ok, the code you gave me is a lot cleaner and more efficient, I was planning to do this after collision was complete but thanx for the help! Secondly i will make a new force and torque event later but i am just using it as it is until the camera works coz i am completely redesigning the game from scratch! Now about ur code! I try it with my apply force and torque event but the sphere seems to move away very fast without even me pressing a button! I just cant find a solution for this damn problem! It would be very great of you if you could post a very small example just showing this!

BTW heres my complete code of the project! Its very crappy coz i dumped it long ago just using to try and make the camera work!

http://file.uploadr.com/8bc0

Its juz 13.7 kb so do chck it out, n juz put in map-20kdm2.pk3 , irrlicht and newton dlls with it!
kruseborn
Posts: 2
Joined: Fri Aug 04, 2006 1:28 pm

Post by kruseborn »

i have tryed some things to get a fps camera working with newton,
this code its a start, but the speed its not ok, if its comes closer to the wall its goes faster, the speed should be the same even if you look up or get close to the walls. so if anyone have a solution please write how.

in the main i creating a fps camera
g_camera = g_sceneManager->addCameraSceneNodeFPS();
g_camera->setPosition(core::vector3df(30, 100, 30));
then i send the g_camera to a nother class

in the next class i have a function to creat the camera.

Camera* CGame::createCamera(core::vector3df position)
{
Camera *camera = new Camera();

camera->cameraNode = m_camera;
camera->cameraNode->setPosition(position);

camera->node = m_sceneManager->addEmptySceneNode();
camera->node->setPosition(position);

camera->collision = NewtonCreateChamferCylinder(m_nWorld, 30, 60, NULL);
//camera->collision = NewtonCreateCapsule(m_nWorld, 30, 50, NULL);
camera->body = NewtonCreateBody(m_nWorld, camera->collision);

//NewtonBodySetAutoFreeze(body, 0) followed by NewtonWorldUnfreezeBody(world, body), this will make the body active forever.
NewtonBodySetAutoFreeze(camera->body, 0);
NewtonWorldUnfreezeBody(m_nWorld, camera->body);

NewtonBodySetUserData(camera->body, camera->node);

// makes character stand
NewtonConstraintCreateUpVector(m_nWorld, &(core::vector3df(0, 1, 0).X), camera->body);

// set the viscous damping the the minimum
NewtonBodySetLinearDamping (camera->body, 0.0f);
NewtonBodySetAngularDamping (camera->body, &(core::vector3df(0, 0, 0).X));

NewtonBodySetMassMatrix(camera->body, 80, 100, 100, 100);
NewtonBodySetFreezeTreshold(camera->body, 1.0f, 1.0f, 1);

NewtonBodySetTransformCallback(camera->body, SetCameraMeshTransformEvent);
NewtonBodySetForceAndTorqueCallback(camera->body, ApplyCameraForceAndTorqueEvent);

core::matrix4 mat;
mat.setTranslation(position);
NewtonBodySetMatrix(camera->body, &mat.M[0]);

//setting up the gun
camera->gunMesh = m_sceneManager->getMesh("data/gun.md2");
camera->gunNode = m_sceneManager->addAnimatedMeshSceneNode(camera->gunMesh);
camera->gunNode->setMaterialFlag(video::EMF_LIGHTING, false);
camera->gunNode->setMaterialTexture(0, m_driver->getTexture("data/gun.pcx"));
camera->gunNode->setMD2Animation("idle");
camera->gunNode->setPosition(core::vector3df(0, 0, 6));
camera->gunNode->setRotation(core::vector3df(65, 280, -65));
camera->gunNode->setParent(m_camera);

cameraArray[0] = camera;
g_cameratest = cameraArray[0]->cameraNode;

return camera;
}

void SetCameraMeshTransformEvent(const NewtonBody* body, const float* matrix)
{
//get graphic object
scene::ISceneNode* node = (scene::ISceneNode*)NewtonBodyGetUserData(body);

//copy matrix to an irrlicht matrix
core::matrix4 mat;
memcpy(mat.M, matrix, sizeof(float)*16);

//set transformation

if(g_cameratest)
{
core::vector3df pos(0, 40, 0);
g_cameratest->setPosition(mat.getTranslation() + pos);
}
node->setPosition(mat.getTranslation());
node->setRotation(mat.getRotationDegrees());
}

void ApplyForceAndTorqueEvent(const NewtonBody* body)
{
float mass;
float Ixx;
float Iyy;
float Izz;


NewtonBodyGetMassMatrix(body, &mass, &Ixx, &Iyy, &Izz);

core::vector3df force(0, -800*mass, 0);
NewtonBodyAddForce(body, &force.X);

}

bool CGame::OnEvent(SEvent event)
{
int const SPEED = 500;

if(event.KeyInput.PressedDown && event.KeyInput.Key == KEY_KEY_W)
{
core::vector3df camvec = (m_camera->getTarget() - m_camera->getAbsolutePosition()).normalize() * SPEED;
core::vector3df velocity(camvec.X, 0.0f, camvec.Z);
NewtonBodySetVelocity(cameraArray[0]->body, &velocity.X);
}

if(event.KeyInput.PressedDown && event.KeyInput.Key == KEY_KEY_S)
{
core::vector3df camvec = (m_camera->getTarget() - m_camera->getAbsolutePosition()).normalize() * -SPEED;
core::vector3df velocity(camvec.X, 0.0f, camvec.Z);
NewtonBodySetVelocity(cameraArray[0]->body, &velocity.X);

}

if(event.KeyInput.PressedDown && event.KeyInput.Key == KEY_KEY_D)
{
core::vector3df camvec = (m_camera->getTarget() - m_camera->getAbsolutePosition()).normalize() * -SPEED;
core::vector3df velocity(-camvec.Z, 0.0f, camvec.X);
NewtonBodySetVelocity(cameraArray[0]->body, &velocity.X);

}

if(event.KeyInput.PressedDown && event.KeyInput.Key == KEY_KEY_A)
{
core::vector3df camvec = (m_camera->getTarget() - m_camera->getAbsolutePosition()).normalize() * SPEED;
core::vector3df velocity(-camvec.Z, 0.0f, camvec.X);
NewtonBodySetVelocity(cameraArray[0]->body, &velocity.X);
}


if(!event.KeyInput.PressedDown && g_cameratest != NULL)
NewtonBodySetVelocity(cameraArray[0]->body, &(core::vector3df(0, 0, 0).X));

return false;
}

the camera its a struct:

struct Camera
{
scene::ICameraSceneNode *cameraNode;
scene::ISceneNode *node;
NewtonCollision *collision;
NewtonBody *body;
scene::IAnimatedMesh *gunMesh;
scene::IAnimatedMeshSceneNode *gunNode;
};
Post Reply