Page 1 of 1

IrrNewt terrain and Player unit

Posted: Sat Oct 18, 2008 4:51 am
by Minnek
I'm using a class to interface between the "model" (node + Newton body) and the player, and it basically sets velocity based on direction and etc without affecting the Y velocity. However, this leads to the effect that I don't "follow" the terrain (ie, if I go off of a very gently sloped hill, I'll float in the air for a half second before falling) and if the velocity is too high or it hits against the terrain too hard, it'll fire into the air as though the player were to have "jumped", even though it's just a result of the physics.

Is there a way to dampen this effect? Would I want to do something like... make a collision response class that sets the Y velocity to 0 on a collision if the colliding body is a player unit's Newton body?

I'm new to working with physics engines in general, so if you could provide examples in code or just word things a little more simply, I'd really appreciate it.

Thanks for any and all help!

reply

Posted: Sat Oct 18, 2008 9:14 am
by m3ltd0wn
set a mass on the player, then setforcecontinous (0, -9.81*mass,0) and the player will stay o the ground ;)

Code: Select all

//create actor body
	irr::newton::SBodyFromNode actorData;
	actorData.Type = newton::EBT_AUTODETECT;
	actorData.Node = actor;
	actor_body = p_world->createBody(actorData);
	actor_body->setMass(56.f);
	actor_body->setCentreOfMass(vector3df(0,-1,0));
	   actor_body->addForceContinuous(vector3df(0,-9.81*actor_body->getMass(),0));
	actor_body->setContinuousCollisionMode(true);
	actor_material=p_world->createMaterial();
	actor_body->setMaterial(actor_material);
	actor_material->setFriction(terrain_material, 0, 0);
	actor_material->setCollidable(terrain_material, true);

Posted: Mon Oct 20, 2008 1:46 am
by Minnek
They stay on the ground now, thanks!

However, now they rotate when I'd like them not to, and when I use the getUtils()-avoidRotationOnAllAxes() function, I'm unable to maintain a rotation on them - when I set the rotation, they just turn back to their original direction.

Also, now they strangely bounce around when I walk them into slight upward grades on the terrain, and their bounding box acts really strangely... it'll tip over or spin around on the ground.

How do I fix that? I want them to stay upright without spinning around or tipping over - think of the way player characters or NPCs in games like World of Warcraft move around. I'm trying to duplicate that with the Newton engine (I'm trying to use it for Newtonian physics for non-player objects, and then have the simple collision detection for upright objects...)

Much appreciated, again.

Posted: Mon Oct 20, 2008 2:01 am
by Seven
have you used the controller? I am using it with limited success and will continue to debug my own app. It may be what you are looking for.

Code: Select all

	virtual void CreatePhysicsObject()
	{
		// create the base physics object - it will destroy the old one :)
		CSObject::CreatePhysicsObject();

		// create a Physics model for it
		if (m_AnimatedSceneNode)
		{
			//body
			newton::SBodyFromNode bodyData;
			bodyData.Type = newton::EBT_PRIMITIVE_CAPSULE;
			bodyData.Node = m_AnimatedSceneNode;
			bodyData.Size = GetBaseDimensions() + GetBBOffset();

			matrix4 mat;
			mat.makeIdentity();
			mat.setTranslation(GetPositionOffset());
			mat.setRotationDegrees(GetRotationOffset());
			bodyData.BodyOffsetFromNode = mat;


			m_Controller = m_Level->m_NewtonWorld->createCharacterController(m_Level->m_NewtonWorld->createBody(bodyData),false);
			m_Controller->setRotationUpdate(false);
			m_Controller->setContinuousCollisionMode(true);

			//the body rotate never
			m_Level->m_NewtonWorld->getUtils()->avoidRotationOnAllAxes(m_Controller);

			// set the force to apply if in front of the character there is a stair
			m_Controller->setClimbStairForce(core::vector3df(0,4,0));

			//set the max stair-step height from floor for the first stair-step
			//from the below stair-step for all the stairs-step except the first
			m_Controller->setStairMaxHeight( 4 );

			//add gravity
			m_Controller->addForceContinuous(m_Level->GetGravity());

			m_Controller->setFreeze(GetFrozen());
		}
	}

Posted: Mon Oct 20, 2008 2:09 am
by Seven
a little note :

I set my own box instead of letting irrnewt decide it
Base dimensions is a base rectangle/box that the physics is built off of
BBOffset is the offset from that base. make the box bigger/smaller on each axis
positionoffset is an offset of the aniamtedscenenode to the box. in case the scene node is not cetnerered exactly as i need
rotation offset is the rotation offset of the scenenode to the controller
example, studiomax files are rotated 270 degrees by default


I cannot currently destroy the dang thing without an exception, but i will figure it out :)

Posted: Mon Oct 20, 2008 2:18 am
by Minnek
I'm using the controller now, yes... it's closer to behaving the way I'd like it to, but I still have an issue with floating off the ground when I move into a slope. I've spent all day working with it and I'm not getting anything halfways satisfactory... at least it's not jittering its rotation now. However, the bounding base is still falling over (it's a tall rectangular prism w/ square ends) and the floating is annoying as well.

Thanks though, this brings me one step closer by confirming that the controller is definitely a right step. Now to figure out how to control it more appropriately...

Posted: Mon Oct 20, 2008 6:36 am
by Minnek
Okay, with some modification to my code and some observations, it appears I've solved the crisis I was having, to some extent at least. I can still move up any gradient, but...

Code: Select all

		// Create a node for the loaded model.
		scene::IAnimatedMeshSceneNode* _MeshSceneNode = Game::CreateMeshNode(filename);
		// Create the Body structure
		newton::SBodyFromNode bodyData;
		bodyData.Type = newton::EBT_AUTODETECT;
		bodyData.Node = _MeshSceneNode;
		
		// Lock the rotation around anything but the Y axis. 
		// TODO: Check for obsoletion with avoidRotationOnAllAxes()
		m_LockRotation = true;
		
		// Create the actual Newton body.
		m_Model = Game::s_World->createCharacterController(Game::s_World->createBody(bodyData));
		// Set the material to material #1 for testing purposes.
		// Properties of Material #1:
		// No friction.
		// Collides w/ terrain material.
		// Zero elasticity and zero softness.
		m_Model->setMaterial(Game::s_World->getAllMaterials()[1]);
		
		// Avoid all rotations. Ever. >:(
		Game::s_World->getUtils()->avoidRotationOnAllAxes(m_Model);
		
		// No reason for this since we set the variable earlier, but
		// just in case I move the option to the XML file I load from...
		if(m_LockRotation)
			m_Model->setRotationUpdate(false);
		
		// Just for doublechecking's sake, we don't want any magical
		// poof-through-the-walls models.
		m_Model->setContinuousCollisionMode(true);
That loads the model, sets no rotation update on the Node, avoids rotation...

Next I have my movement code, which is as thus:

Code: Select all

	void ObjModel::moveLateral(float multiplier) {
		core::vector3df tmp = m_Model->getVelocity();
		tmp.X = tmp.Z = 0;
		tmp += m_Model->FRIgetDirectionPositionY(core::vector3df(multiplier,0,0));
		m_Model->setVelocity(tmp);
	}
	
	void ObjModel::turn(float speed) {
		m_Model->getNode()->setRotation(core::vector3df(0,m_Model->getNode()->getRotation().Y+speed,0));
	}
moveLateral moves my model in a straight line along the arbitrary axis along which it faces, ie moves it in a straight line forward (or back if multiplier is negative).

turn, of course, turns the model's scene node, which in turn (ha, ha) will cause the newton body to turn. (I'm... really not sure how that works. But it does.)

Finally, and it may or may not have an effect, but I have an update function that's called each game loop:

Code: Select all

void ObjModel::__update(const float& dt) {
	if(m_LockRotation) {
		core::vector3df tmp;
		tmp = m_Model->getNode()->getRotation();
		tmp.Z = 0;
		tmp.X = 0;
		m_Model->setRotation(tmp);
	}
}
It... probably does absolutely nothing, but I included it for the sake of completeness.

The variables should be pretty self-explanatory in naming, but if there're any questions, I'll answer them. It looks like almost everything is solved at this point - I'll probably finalize this and commit it to my SVN.

Thanks for all the help, guys. I'll leave this thread open and "unsolved" until we know everyone here has their questions and needs resolved. I'm happy to help with anything else, and if I have any more questions within the next day or two, I may post them here as well as long as they relate.