Irrlicht+Newton Problems

Post your questions, suggestions and experiences regarding game design, integration of external libraries here. For irrEdit, irrXML and irrKlang, see the
ambiera forums
Post Reply
blackb
Posts: 13
Joined: Mon Oct 26, 2009 2:25 pm

Irrlicht+Newton Problems

Post by blackb »

Hi @all,

its me aggain :roll:
At the moment I am trying to setup Newton with Irrlicht. I was looking for some good (and working) tutorials but I can't find them :evil:
Does anyone know a working tutorial on Irrlicht 1.5.1 and Newton 2.0 for Visual Studio 2008 Express?
I always get an Error about an unresolved external symbol "__imp__NewtonCreate" in function "_main"...I added all this directoris from newton and Irrlicht (Irrlicht was workin fine before trying it with newton)...

Hope someone can help me (and hope it is the right forum here :D )

BB
Brainsaw
Posts: 1183
Joined: Wed Jan 07, 2004 12:57 pm
Location: Bavaria

Post by Brainsaw »

This is a linker error. Did you add the Newton lib to the linker?
Dustbin::Games on the web: https://www.dustbin-online.de/

Dustbin::Games on facebook: https://www.facebook.com/dustbingames/
Dustbin::Games on twitter: https://twitter.com/dustbingames
blackb
Posts: 13
Joined: Mon Oct 26, 2009 2:25 pm

Post by blackb »

No, that was the Problem (The code was from an tutorial, so I thought it would work...that was what I ment by saying "there are no working tutorials out there xD)

Thank you :)

I will be back (with more problems to solve :roll: )...

BB
Virion
Competition winner
Posts: 2148
Joined: Mon Dec 18, 2006 5:04 am

Post by Virion »

it's obviously you have not linked the library. it's not about the code but IDE setup.
blackb
Posts: 13
Joined: Mon Oct 26, 2009 2:25 pm

Post by blackb »

Sorry, I usually do things like this in my code. :oops:
...
Ok, what about tutorials for Irrlicht in combination with newton, does anyone know some good tutorials?
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Post by Seven »

I use Newton2 as one of my libs and can assist as needed. feel free to ask away......
blackb
Posts: 13
Joined: Mon Oct 26, 2009 2:25 pm

Post by blackb »

Ok, I have got an AnimatedMeshSceneNode called dwarf (for testing, I am using the dwarf model that was included in irrlicht) and another AnimatedMeshSceneNode called terrain (Will replace it by a not animated one later...Somewhere I read that the terrainscenenode is not good for newton).
I move the dwarf by pressing the arrowkeys (forward,backward,turn left/right) and by pressing the right Mousebutton+left/right arrowkey it moves to this direction without turning arround.
Now, the first thing I have to do ist create a gravitation and a collision detecting (would be bad to fall through the ground :D ) but I don't find code for this (or better, a tutorial to learn what code is used for what action)...

BB
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Post by Seven »

I set up my framework with a generic IPhysicsManager, IPhysicsWorld and IPhysicsObject interface. I then created interfaces for each of the physics libraires that I wanted to test. this allowed me to create game objects that have physics attached, but the gaem objects do not know what physics library is being used. I have working libraries for Newton, Newton2, Physx, and ODE. I actuall recommend this style for everyone, because it allows me to change the physics engine at will, without changing the game itself.

example for gaem object

Code: Select all

class IrrObjectBox : public IrrObject
{
	virtual void CreatePhysicsObject()  
	{ 
		IRR_LOG(L"IrrObject_Box::CreatePhysicsObject()");		
	
		// make sure the object is available
		DestroyPhysicsObject(); 

		// make sure the node is valid
		IRR_CHECK(m_Node,L"-- no node to create physics object from");

		// create a physics object to represent this node
		IPhysicsObjectData data;
		data.type = POT_PRIMITIVE_BOX;
		data.position = GetPosition();
		data.rotation = GetRotation();
		data.scale = GetScale()*2;
		data.mass = GetMass();
		data.gravity = true;
		data.bboffset = GetBBOffset();
		data.frozen = GetFrozen();
		data.userdata = GetID();
		m_PhysicsObject = GetLevel()->GetPhysicsWorld()->CreatePhysicsObject(data);
	}
}


updating the node each frame requries a call to the physicsobject

Code: Select all

void IrrObject::Frame(float elapsedtime)
{
	IrrObjectMessage msg;
	if (next_state != state)
	{
		if (force_state_change)
		{
			msg.Create(MSG_RESERVED_Exit,0,0,0,0,0,stringw(L""));
			ProcessStateMachine(&msg);
					
			state = next_state;
			next_state = state;
			force_state_change = false;
					
			msg.Create(MSG_RESERVED_Enter,0,0,0,0,0,stringw(L""));
			ProcessStateMachine(&msg);
		}
	}

	// match the nodes to the physics object position and rotation each frame
	if (m_PhysicsObject)
	{
		SetNodePosition(m_PhysicsObject->GetPosition());
		SetNodeRotation(m_PhysicsObject->GetRotation());
	}

	if (GetDebug()) DrawPhysicsBoundingBox();

	msg.Create(MSG_RESERVED_Update,0,0,0,0,0,stringw(L""));
	ProcessStateMachine(&msg);
}
the calls tot he physics object are handled behind the scenes, so that this call

Code: Select all

  SetNodePosition(m_PhysicsObject->GetPosition());
  SetNodeRotation(m_PhysicsObject->GetRotation());
is handlded internally by the IPhysicsObject_Newton2 class

Code: Select all

vector3df CPhysicsObject_Newton2::GetPosition()			
{	
	if(!m_NewtonBody) return vector3df(0,0,0);	
	core::matrix4 temp_mat;
	NewtonBodyGetMatrix(m_NewtonBody,GetMatrixPointer(temp_mat));
	core::vector3df pos=temp_mat.getTranslation()*NewtonToIrr;
	return pos;
}
vector3df CPhysicsObject_Newton2::GetRotation()			
{	
	if(!m_NewtonBody) return vector3df(0,0,0);	
	core::matrix4 temp_mat;
	NewtonBodyGetMatrix(m_NewtonBody,GetMatrixPointer(temp_mat));
	return temp_mat.getRotationDegrees();
}


Newton2 comes with a spendid set of tutorials. Also, Irrnewt is a phenomenol teaching tool. Take a look at Irrnewt to see how they did it in there. Most of the techniques are the same for Newton2.

generically speaking, for Newton2 you do this.

create the world

Code: Select all

	// create the newton world
	m_NewtonWorld = NewtonCreate (NULL,NULL);
create physics objects and add to the world

Code: Select all

IPhysicsObject* CPhysicsWorld_Newton2::CreatePhysicsObject(IPhysicsObjectData data)
{
	NewtonCollision* collision = CreateCollision(data);
	if (collision)
	{
		CPhysicsObject_Newton2* obj = new CPhysicsObject_Newton2(this);
		obj->m_NewtonBody = NewtonCreateBody(m_NewtonWorld,collision);
		NewtonBodySetUserData(obj->m_NewtonBody,obj);
		NewtonBodySetForceAndTorqueCallback(obj->m_NewtonBody,defBodyForceAndTorqueCallback);
		if(data.gravity) obj->AddContinuousForce(m_WorldData.gravity);
		obj->SetMass(data.mass);
		obj->SetPosition(data.position);
		obj->SetRotation(data.rotation);
		obj->SetLinearDamping(data.linearDamping);
		obj->SetAngularDamping(data.angularDamping);
		obj->SetFreeze(data.frozen);
		obj->SetUserdata(data.userdata);
		return obj;
	}
	return NULL;
}

NewtonCollision* CPhysicsWorld_Newton2::CreateCollision(IPhysicsObjectData data)
{
	switch (data.type)
	{
		case POT_AUTO_DETECT				: {													} break;
		case POT_PRIMITIVE_SPHERE			: {	return CreateCollision_Sphere(data);			} break;
		case POT_PRIMITIVE_BOX				: {	return CreateCollision_Cube(data);				} break;
		case POT_PRIMITIVE_CONE				: {	return CreateCollision_Cone(data);				} break;
		case POT_PRIMITIVE_CAPSULE			: {	return CreateCollision_Capsule(data);			} break;
		case POT_PRIMITIVE_CYLINDER			: {	return CreateCollision_Cylinder(data);			} break;
		case POT_PRIMITIVE_CHAMFERCYLINDER	: {	return CreateCollision_ChamferCylinder(data);	} break;
		case POT_CONVEXHULL					: {	return CreateCollision_ConvexHull(data);		} break;
		case POT_TREE						: { return CreateCollision_Tree(data);				} break;			
	}
	return NULL;
}

Code: Select all

NewtonCollision* CPhysicsWorld_Newton2::CreateCollision_Sphere(IPhysicsObjectData data)
{
	return NewtonCreateSphere(m_NewtonWorld, data.scale.X*IrrToNewton, data.scale.Y*IrrToNewton,data.scale.Z*IrrToNewton,0,0);
}

NewtonCollision* CPhysicsWorld_Newton2::CreateCollision_Cube(IPhysicsObjectData data)
{
	data.scale += data.bboffset;
	return NewtonCreateBox (m_NewtonWorld, data.scale.X*IrrToNewton, data.scale.Y*IrrToNewton,data.scale.Z*IrrToNewton,0,0);
}

NewtonCollision* CPhysicsWorld_Newton2::CreateCollision_Cone(IPhysicsObjectData data)
{
	return NewtonCreateCone(m_NewtonWorld, data.scale.X*IrrToNewton, data.scale.Y*IrrToNewton,0,0);
}

and then update the world each frame

Code: Select all

void CPhysicsWorld_Newton2::Update(float elapsedtime)
{
	if (m_NewtonWorld)	NewtonUpdate (m_NewtonWorld, elapsedtime);
}
blackb
Posts: 13
Joined: Mon Oct 26, 2009 2:25 pm

Post by blackb »

Too much input :shock:
Give me a second...will try to understand this...I expected something smaller... :oops:

I read it, but i don't understand it...can you explain generally how to use this (to include it in a header file and then use this physic object for grafitation and collision detecting)?...

BB
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Post by Seven »

sorry, i was trying to chat about design vs example.

take a look at irrnewt, it is very well designed and fairly easy to follow.

then, write a basic irrlicht app that does nothing but setup the irrlicht screen. then, add a single cube and add gravity to it. I can write something small for you if you like, just to get you going.
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Post by Seven »

ok, a full blown app. pretty much as simple as i can get it. move around with the arrow keys and 'shoot' a box with the spacebar. the app was put together quick, so it isnt perfect, but it should get you a good idea of how we use newton.

once you get it down, it might? be easier to let the newton callback move the node for you. it's a matter of preference, i prefer to move thenode manually, but either is fine.

if you need anything else, let me know.

Code: Select all

#include <irrlicht.h>
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
//#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#endif

#include "newton.h"
#pragma comment(lib, "Newton.lib")

inline irr::f32* GetMatrixPointer(const core::matrix4& mat) { return const_cast<f32*>(mat.pointer()); }
const irr::f32 NewtonToIrr =  32.0f;
const irr::f32 IrrToNewton = ( 1.0f / NewtonToIrr ) ;

// all the irrlicht stuff
IrrlichtDevice*		device			= 0;
IVideoDriver*		driver			= 0;
ISceneManager*		smgr			= 0;
IGUIEnvironment*	guienv			= 0;
ICameraSceneNode*	camera			= 0;
NewtonWorld*		newtonWorld		= 0;
float				gravity			= -10;

// a small class to hold a scenenode and a physicsobject and keep them in sync
class CPhysicsObject_Newton2
{
public:
	ISceneNode* m_Node;
	NewtonBody* m_NewtonBody;

	vector3df m_Force;
	vector3df m_ContinuousForce;
	bool m_Gravity;
	float m_Mass;

	CPhysicsObject_Newton2(ISceneNode* node, NewtonBody* body) 
	{
		m_Node = node;
		m_NewtonBody = body;
		m_Mass = 10;

	}
	~CPhysicsObject_Newton2()
	{ 
		if (m_NewtonBody) NewtonDestroyBody(newtonWorld,m_NewtonBody);
		m_Node = 0; 
		m_NewtonBody = 0;	
	}

	void update()
	{
		if (m_Node && m_NewtonBody)
		{
			core::matrix4 temp_mat;
			NewtonBodyGetMatrix(m_NewtonBody,GetMatrixPointer(temp_mat));
			m_Node->setPosition(temp_mat.getTranslation()*NewtonToIrr);
			
			NewtonBodyGetMatrix(m_NewtonBody,GetMatrixPointer(temp_mat));
			m_Node->setRotation(temp_mat.getRotationDegrees());
		}
	}

	// simple functions to manipulate the forces of the object
	void addForce(vector3df force)				{ m_Force += force; 			}
	void addContinuousForce(vector3df force)	{ m_ContinuousForce += force;	}
	void setForce(vector3df force)				{ m_Force = force;				}
	void setContinousForce(vector3df force)		{ m_ContinuousForce = force;	}
	vector3df getForce()						{ return m_Force;				}
	vector3df getContinuousForce()				{ return m_ContinuousForce;		}
	vector3df getTotalForce() 
	{	
		vector3df tf = getForce() + getContinuousForce();
		tf += gravity;
		return tf;
	}


	void setPosition(vector3df pos)	
	{
		if(!m_NewtonBody) return;

		irr::core::matrix4 irr_mat;
		NewtonBodyGetMatrix(m_NewtonBody,GetMatrixPointer(irr_mat));
		irr_mat.setTranslation(pos*IrrToNewton);
		NewtonBodySetMatrix(m_NewtonBody,GetMatrixPointer(irr_mat));
	}
	void setRotation(vector3df rot)	
	{
		if(!m_NewtonBody) return;
		core::matrix4 temp_mat;
		NewtonBodyGetMatrix(m_NewtonBody,GetMatrixPointer(temp_mat));
		temp_mat.setRotationDegrees(rot);
		NewtonBodySetMatrix(m_NewtonBody,GetMatrixPointer(temp_mat));
	}
	vector3df getPosition()			
	{	
		if(!m_NewtonBody) return vector3df(0,0,0);	
		core::matrix4 temp_mat;
		NewtonBodyGetMatrix(m_NewtonBody,GetMatrixPointer(temp_mat));
		core::vector3df pos=temp_mat.getTranslation()*NewtonToIrr;
		return pos;
	}
	vector3df getRotation()			
	{	
		if(!m_NewtonBody) return vector3df(0,0,0);	
		core::matrix4 temp_mat;
		NewtonBodyGetMatrix(m_NewtonBody,GetMatrixPointer(temp_mat));
		return temp_mat.getRotationDegrees();
	}
	void setFreeze(bool value)		
	{
		if(!m_NewtonBody) return;
		NewtonBodySetFreezeState (m_NewtonBody,value);
	}
	void setMass(float value)		
	{
		if(!m_NewtonBody) return;
		irr::f32 current_mass,inx,iny,inz;
		NewtonBodyGetMassMatrix(m_NewtonBody,&current_mass,&inx,&iny,&inz);
		NewtonBodySetMassMatrix(m_NewtonBody,value/*no current_mass*/,inx,iny,inz);
	}
	float getMass()
	{
		if(!m_NewtonBody) return 0;

		dFloat mass;
		dFloat Ixx;
		dFloat Iyy;
		dFloat Izz;
		NewtonBodyGetMassMatrix (m_NewtonBody, &mass, &Ixx, &Iyy, &Izz);
		return mass;
	}
	void setLinearDamping(float value) 
	{
		if(!m_NewtonBody) return;
		NewtonBodySetLinearDamping(m_NewtonBody,value);
	}

	void setAngularDamping(vector3df value)
	{
		if(!m_NewtonBody) return;
		float ad[3];
		ad[0] = value.X;
		ad[1] = value.Y;
		ad[2] = value.Z;
		NewtonBodySetAngularDamping(m_NewtonBody,ad);
	}
};

////////////////////////////////////////////////
void defBodyForceAndTorqueCallback (const NewtonBody* n_body, dFloat timestep, int threadIndex) 
{
	// get a pointer to the object
	CPhysicsObject_Newton2* obj = (CPhysicsObject_Newton2*)NewtonBodyGetUserData(n_body);

	// store the total force on the object
	irr::f32 tf[3];
	tf[0] = obj->getTotalForce().X;
	tf[1] = obj->getTotalForce().Y;
	tf[2] = obj->getTotalForce().Z;

	//reset force
	obj->setForce(vector3df());

	// add the forces to the newton body
	NewtonBodyAddForce(n_body, tf);
}

NewtonCollision* CreateCollision_Cube(ISceneNode* cube)
{
	vector3df scale = cube->getScale();
	return NewtonCreateBox (newtonWorld, scale.X*IrrToNewton, scale.Y*IrrToNewton,scale.Z*IrrToNewton,0,0);
}

CPhysicsObject_Newton2* CreatePhysicsObject(vector3df pos, vector3df rot, vector3df scale, float mass)
{
	ISceneNode* node = smgr->addCubeSceneNode(1);
	node->setMaterialTexture(0, driver->getTexture("media/fire.bmp"));
	node->setMaterialFlag(video::EMF_LIGHTING, false);
	node->setMaterialFlag(video::EMF_FOG_ENABLE,false);
	node->setScale(scale);
	node->setPosition(pos);
	node->setRotation(rot);
	NewtonCollision* collision = CreateCollision_Cube(node);
	if (collision)
	{
		NewtonBody* body = NewtonCreateBody(newtonWorld,collision);
		CPhysicsObject_Newton2* obj = new CPhysicsObject_Newton2(node,body);
		obj->setMass(mass);
		obj->setPosition(node->getPosition());
		obj->setRotation(node->getRotation());
		obj->setLinearDamping(1);
		obj->setAngularDamping(vector3df(1,1,1));
		obj->setFreeze(false);

		NewtonBodySetUserData(obj->m_NewtonBody,obj);
		NewtonBodySetForceAndTorqueCallback(obj->m_NewtonBody,defBodyForceAndTorqueCallback);

		return obj;
	}
	return NULL;
}

core::list<CPhysicsObject_Newton2*> m_List;

void createBoxAtCamera()
{
	CPhysicsObject_Newton2* obj = CreatePhysicsObject(camera->getPosition(),vector3df(30,30,30),vector3df(20,20,20),10);
	core::vector3df dir = camera->getTarget() - camera->getPosition();
	dir.normalize();
	obj->addContinuousForce(dir * 200);
	m_List.push_back(obj);
}

u32 cur_time,delta,last_time;
float updateTime () 
{
	cur_time = device->getTimer()->getRealTime ();
	delta = (float)((float)(cur_time - last_time) / 2);
	last_time = cur_time;
	return delta;
}

class MyEventReceiver : public IEventReceiver
{
public:
	virtual bool OnEvent(const SEvent& e)
	{
		switch (e.EventType)
		{
			case EET_KEY_INPUT_EVENT : 
				{
					if (e.KeyInput.PressedDown)
					switch (e.KeyInput.Key)
					{
						case KEY_SPACE : createBoxAtCamera(); break;
					}
				} 	break;
	
		}
		return false;
	}
};

int main()
{
	MyEventReceiver receiver;
	device = createDevice( video::EDT_DIRECT3D9, dimension2d<u32>(640, 480), 16,	false, false, false, 0);
	if (!device)return 1;
	device->setWindowCaption(L"Hello World! - Irrlicht Engine Demo");
	device->setEventReceiver(&receiver);

	driver	= device->getVideoDriver();
	smgr	= device->getSceneManager();
	guienv	= device->getGUIEnvironment();
	camera = smgr->addCameraSceneNodeFPS();
	camera->setPosition(vector3df(-100,10,-100));
	camera->setTarget(vector3df(0,-200,0));

	// create the newton world
	newtonWorld = NewtonCreate (NULL,NULL);

	// organize the world before beginning updates (optional)
	NewtonInvalidateCache (newtonWorld);

	// create the floor
	m_List.push_back(CreatePhysicsObject(vector3df(0,-200,0),vector3df(0,0,0),vector3df(500,10,500),0));

	while(device->run())
	{
		// update the newton world
		if (newtonWorld)	NewtonUpdate (newtonWorld, updateTime());
		
		// update the objects
		if (!m_List.empty()) 
		{
			core::list<CPhysicsObject_Newton2*>::Iterator it = m_List.begin();
			for (; it != m_List.end(); it++)
			{
				(*it)->update();	
			}
		}

		driver->beginScene(true, true, SColor(255,100,101,140));
		smgr->drawAll();
		guienv->drawAll();
		driver->endScene();
	}

	// delete the list of objects
	core::list<CPhysicsObject_Newton2*>::Iterator it = m_List.begin();
	for (; it != m_List.end();)
	{
		delete (*it);
		it = m_List.erase(it);
	}

	// destroy the newton world
	if (newtonWorld) NewtonDestroy (newtonWorld); newtonWorld = 0;

	device->drop();

	return 0;
}
blackb
Posts: 13
Joined: Mon Oct 26, 2009 2:25 pm

Post by blackb »

Ok, I don't understand all of this but now I am able to learn it by myself I think (If not I will ask aggain^^).
Thank you :)
Post Reply