Page 1 of 1

How to apply newton physics on camera?

Posted: Wed Aug 02, 2006 6:56 pm
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!

Posted: Fri Aug 04, 2006 7:18 am
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);

Posted: Fri Aug 04, 2006 10:09 am
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!

Posted: Fri Aug 04, 2006 12:30 pm
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?

Posted: Fri Aug 04, 2006 1:35 pm
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

Posted: Fri Aug 04, 2006 9:25 pm
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!

Posted: Sun Aug 06, 2006 4:17 pm
by RapchikProgrammer
Im very very stuck here! If anyone could give me some help here i would really like it!

Posted: Mon Aug 07, 2006 12:07 pm
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);



Posted: Mon Aug 07, 2006 3:54 pm
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.

Posted: Wed Aug 09, 2006 9:29 pm
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); 
} 

Posted: Wed Aug 09, 2006 10:37 pm
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.

Posted: Thu Aug 10, 2006 10:48 am
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!

Posted: Fri Aug 11, 2006 4:10 pm
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;
};