Moving an object with Newton collision.

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
Delee
Posts: 18
Joined: Sat Apr 14, 2007 8:36 am

Moving an object with Newton collision.

Post by Delee »

I am curious how you force an object to move with Newton... for example, if I press forward on my keyboard, it will move a ball within the program forward.

I have tried to look at the Character Controller tutorial that comes with Newton, but it is much too advanced for my current understanding and far too involved. It is also written with a 3D engine I am not familiar with, so I get even more confused.

Currently, I can create a ball by clicking the mouse button. This will throw the ball forward and it will bounce around for a while. After that, I tried to move the mesh with Irrlicht and adjust the corresponding matrix in Newton, but that results in no collision detection being done.

Have I got it backwards? Should I be moving the object with Newton and only then with Irrlicht in the callbacks? I tried setting the object's velocity, anticipating this would shoot the object forward, but it didn't do anything at all. Am I missing some sort of update function?

Any help with the order in which things should be done and what functions to look at would be very appreciated. A very simple example would be especially awsome. :)
Luben
Posts: 568
Joined: Sun Oct 09, 2005 10:12 am
Location: #irrlicht @freenode

Post by Luben »

Yeah, you got it backwards. In the setTransformation callback, Newton tells us where the object is, and we are supposed to update the graphical representation. The physics comes first.
To push things forward and such, you should add a force to the body in the setForceAndTorque callback.
I'm not sure about the names of the callbacks, but it's something like that. Maybe i'll post a small tut on the wiki and show how it can be done.
If you don't have anything nice to say, don't say anything at all.
roxaz
Posts: 575
Joined: Tue Jan 23, 2007 8:35 pm
Location: LT

Post by roxaz »

Check this out. its my player controller using newton. updateMovement() is called every frame and it updates movement direction. Player_MeshTransform callback represents camera position lifted by 4 units above ground. Camera is surrounded by capsule by the way. So capsule do not care about cam torque and camera do not care about capsule torque. Torques are ignored. Player_ForceAndTorque takes user data of newton body which is my player object, as you see i have pointer to vector move and i can access it from callback. with tmp->node->getAbsoluteTransformation().rotateVect(dir); i rotate my direction vector move to point at the same forward position like camera (node). then all forces are applied. there is only one bug - when you are moving lets say forward speed is not constant, it is growing and growing. im not good at physics so i didnt make speed control yet :P

Code: Select all

void Player::updateMovement()
{
	//vector3df move(0,0,0);
	if(keysDown[KEY_KEY_W])
		move->Z += MAX_SPD;
	if(keysDown[KEY_KEY_S])
		move->Z -= MAX_SPD;
	if(keysDown[KEY_KEY_A])
		move->X -= MAX_SPD;
	if(keysDown[KEY_KEY_D])
		move->X += MAX_SPD;
}

void _cdecl Player::Player_MeshTransform(const NewtonBody *body, const float *matrix)
{
	// copy the matrix into an irrlicht matrix4
	matrix4 mat;
	memcpy(&mat, matrix, sizeof(float)*16);

	// Retreive the user data attached to the newton body
	Object *tmp = (Object*)NewtonBodyGetUserData(body);
	if (tmp)
	{
		vector3df newPos = mat.getTranslation();
		newPos.Y += 4;
		// Position the node
		tmp->node->setPosition(newPos);		// set position
		//tmp->node->setRotation(mat.getRotationDegrees());	// and rotation
	}
}

void _cdecl Player::Player_ForceAndTorque(const NewtonBody* body) 
{ 
   float mass; 
   float Ixx;
   float Iyy; 
   float Izz; 
   float force[3]; 
   float torque[3];

   Player *tmp = (Player*)NewtonBodyGetUserData(body);

   vector3df dir;
   dir.X = tmp->move->X;
   dir.Y = tmp->move->Y;
   dir.Z = tmp->move->Z;

   tmp->node->getAbsoluteTransformation().rotateVect(dir);
   /*tmp->node->setPosition(node->getAbsolutePosition() + move);*/

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

   float currForce[3];
   NewtonBodyGetForce(body, &currForce[0]);

   force[0] = dir.X * mass;
   force[1] = GRAVITY_Y * mass;
   force[2] = dir.Z * mass; 

   tmp->move->X = 0;
   tmp->move->Y = 0;
   tmp->move->Z = 0;

   torque[0] = 0.0f; 
   torque[1] = 0.0f; 
   torque[2] = 0.0f; 

   NewtonBodyAddForce (body, force); 
   NewtonBodyAddTorque (body, torque); 
}
Delee
Posts: 18
Joined: Sat Apr 14, 2007 8:36 am

Post by Delee »

Hi again, thanks a lot for the replies! What roxaz posted is similar to what I thought had to happen. However, when I tried it, pushing forward doesn't do anything. It doesn't look like the callbacks are being called, although they are set correctly as they do get called when the object is added and falls to the ground.

I get the feeling I'm missing some key piece of the puzzle I'm too tired to see. :)

Do I need to tell Newton that it should be updating the object as a result of applied forces somehow? Currently, when I push forward, only where the object should be at is updated. For testing, it is currently just a universal variable, rather than being part of the character object. Does updating the user data result in Newton updating the body? I am not sure how it is supposed to work.
roxaz
Posts: 575
Joined: Tue Jan 23, 2007 8:35 pm
Location: LT

Post by roxaz »

it workls like this: you move newton bodies, they have their collision geometry and interact with each other. so all collision thing happens in newton. to see result you just design your mesh transform callback to update object mesh to look like newton body. check out my simple object mesh transform callback, maybe comments will make it clear for you.

Code: Select all

void _cdecl Object::Object_MeshTransform(const NewtonBody *body, const float *matrix)
{
	// copy the matrix into an irrlicht matrix4
	matrix4 mat;
	memcpy(&mat, matrix, sizeof(float)*16);

	// Retreive the user data attached to the newton body.
	Object *tmp = (Object*)NewtonBodyGetUserData(body);
	if (tmp)
	{
		// Position the node. mat.getTranslation() takes newton body position and tmp->node->setPosition() update our scene node position
		tmp->node->setPosition(mat.getTranslation());
// mat.getRotationDegrees() gets current newton body rotation and tmp->node->setRotation() rotate our scene node just like newton body is rotated.
		tmp->node->setRotation(mat.getRotationDegrees());	
	}
}
Delee
Posts: 18
Joined: Sat Apr 14, 2007 8:36 am

Post by Delee »

Thanks a lot for all of your help! :)

I finally figured out what I was doing wrong. Everything was working fine for my general shapes as they were not expected to be shifted by the user and only needed to react to collisions. Therefore, when they stopped moving, Newton didn't bother checking on them anymore.
The Newton Engine does not call the NewtonApplyForceAndTorque callback function for bodies that are inactive or have reached a state of stable equilibrium.
However, this needed to work differently for a character which had to respond to user input... Newton had to check on it consistently. So I made this happen by adding the following when I created my character.

Code: Select all

NewtonBodySetAutoFreeze(body, 0);
NewtonWorldUnfreezeBody(nWorld, body);
My character now moves around and collides into things perfectly! Now, I just have to figure out how to make it stay upright. :)

Again, my thanks for your help.
Luben
Posts: 568
Joined: Sun Oct 09, 2005 10:12 am
Location: #irrlicht @freenode

Post by Luben »

You can use a upvector constraint for that, like this

Code: Select all

vector3df upDirection (0.0f, 1.0f, 0.0f);
UpVector = NewtonConstraintCreateUpVector (World, &upDirection.X, Body);
I think the newton sdk has a character controller example somewhere.
If you don't have anything nice to say, don't say anything at all.
Post Reply