Terrain integration into newton physics

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
Cairon
Posts: 40
Joined: Sun Apr 11, 2004 12:52 am
Contact:

Terrain integration into newton physics

Post by Cairon »

Hi!

I'm trying to implement my terrain into the newton world. I'm using the same code as for my BSP Level. You can see the result at:

http://aoh.arturh.com/terrain.JPG

Another problem i have with my existing code is, that i cannot set the position of my bsp level, because this results in an endless loop at NewtonTreeCollisionEndBuild(newtonmap, 1);

First, my function for creating the NewtonCollison* from the scene node and the mesh:

Code: Select all


NewtonCollision* GetNewtonCollision(scene::ISceneNode* node, scene::IAnimatedMesh* mesh)
{
	NewtonCollision* newtonmap;
	newtonmap = NewtonCreateTreeCollision(nWorld, NULL);
	NewtonTreeCollisionBeginBuild(newtonmap);
	int cMeshBuffer, j;
	int v1i, v2i, v3i;
	scene::IMeshBuffer *mb;

	core::vector3df vArray[3]; // vertex array (3*3 floats)

	int tmpCount = 0;

	core::vector3df scale = node->getScale();
	core::vector3df translation = node->getPosition();

	for (cMeshBuffer=0; cMeshBuffer<mesh->getMesh(0)->getMeshBufferCount(); cMeshBuffer++)
	{	
		mb = mesh->getMesh(0)->getMeshBuffer(cMeshBuffer);
		video::S3DVertex2TCoords* mb_vertices = (irr::video::S3DVertex2TCoords*)mb->getVertices();

		u16* mb_indices  = mb->getIndices();

		// add each triangle from the mesh
		int IndexCount = mb->getIndexCount();
		for (j=0; j<IndexCount; j+=3)
		{
			v1i = mb_indices[j];
			v2i = mb_indices[j+1];
			v3i = mb_indices[j+2];
			
			// to make thing easier, her we can use engine data type
			vArray[0] = ((mb_vertices[v1i].Pos +translation) * scale) * IrrToNewton;
			vArray[1] = ((mb_vertices[v2i].Pos +translation) * scale) * IrrToNewton;
			vArray[2] = ((mb_vertices[v3i].Pos +translation) * scale) * IrrToNewton;
			
			// make sure we do not add degenerated polygons to the tree
			core::vector3df e0 (vArray[1] - vArray[0]);
			core::vector3df e1 (vArray[2] - vArray[0]);

			// the area of the face is the cross product
			core::vector3df area (e0.crossProduct (e1));

			// skip faces with very small area
			float mag = area.dotProduct (area);
			if (mag > 1.0e-9f) {
				NewtonTreeCollisionAddFace(newtonmap, 3, &vArray[0].X, sizeof (core::vector3df), 1);
			} 
		}
	}

	// we definilte wan to optimize the mesh (improve performace and vehaviuor a lot)
	NewtonTreeCollisionEndBuild(newtonmap, 1);	

	return newtonmap;
}
The code for creating my bsp level:

Code: Select all

	for(u32 b=0; b<App->Map->BSPLevels.size(); b++)
	{
		wcstombs(cBuffer, App->Map->BSPLevels[b].BspFilename.c_str(),256);
		scene::IAnimatedMesh* quakeLevelMesh = resmanager->getMesh(cBuffer);
		quakeLevelMeshes.push_back(quakeLevelMesh);

		if (quakeLevelMesh)
		{
			scene::ISceneNode* quakeLevelNode = smgr->addOctTreeSceneNode(quakeLevelMesh->getMesh(0));
			quakeLevelNodes.push_back(quakeLevelNode);

			if (quakeLevelNode)
			{
				quakeLevelNode->setVisible(true);
				quakeLevelNode->setScale(App->Map->BSPLevels[b].scale);
				quakeLevelNode->setPosition(App->Map->BSPLevels[b].position);
				quakeLevelNode->setMaterialType(video::EMT_SOLID );
				quakeLevelNode->setMaterialFlag(video::EMF_LIGHTING,true);
				quakeLevelNode->setMaterialFlag(video::EMF_TRILINEAR_FILTER,true);		
				quakeLevelNode->setMaterialFlag(video::EMF_BACK_FACE_CULLING,true);

				// create map triangle selector
				mapSelector = smgr->createOctTreeTriangleSelector(quakeLevelMesh->getMesh(0), quakeLevelNode, 128);

				metaSelector->addTriangleSelector(mapSelector);
				// ------------------------------------------------------------------
				//	Add Level to Newton Physic Engine

				NewtonCollision* newtonmap = GetNewtonCollision(quakeLevelNode, quakeLevelMesh);
				// create a ridid body to represent the world
				NewtonBody* newtonmapbody;
				newtonmapbody = NewtonCreateBody(nWorld, newtonmap);


				DebugBodies.push_back(newtonmapbody);


				// release the collsion tree (this way the application does not have to do book keeping of Newton objects
				NewtonReleaseCollision (nWorld, newtonmap);

				// set the newton world size based on the bsp size
				core::vector3df boxP0; 
				core::vector3df boxP1; 
				core::matrix4 matrix; 
				NewtonBodyGetMatrix (newtonmapbody, &matrix.M[0]); 
				NewtonCollisionCalculateAABB (newtonmap, &matrix.M[0],  &boxP0.X, &boxP1.X); 
				NewtonSetWorldSize (nWorld, &boxP0.X, &boxP1.X);

				// the world uses the ground material
				NewtonBodySetMaterialGroupID (newtonmapbody, Physics->m_groundMaterial);

				// ------------------------------------------------------------------
			}
		}		
	}
And here is my code to implement the terrain:

Code: Select all

	for(u32 t=0; t<App->Map->Terrains.size(); t++)
	{
		video::IImage* texture = resmanager->createImageFromFile(util->Convert(cBuffer, App->Map->Terrains[t].texture.c_str(), 255));
		if (texture == NULL )
			Log("Could not load terrain texture: %s", cBuffer);
		
		video::IImage* heightmap = resmanager->createImageFromFile(util->Convert(cBuffer, App->Map->Terrains[t].heightmap.c_str(), 255));
		if (heightmap == NULL )
			Log("Could not load heightmap texture: %s", cBuffer);
		
		video::ITexture* detail = resmanager->getTexture(util->Convert(cBuffer, App->Map->Terrains[t].detail.c_str(), 255)) ;
		if (detail == NULL )
			Log("Could not load detail texture: %s", cBuffer);
		
		if ( texture && heightmap && detail )
		{
			scene::IAnimatedMesh* terrainMesh = 
				resmanager->addTerrainMesh("terrain", texture, heightmap, App->Map->Terrains[t].stretch,App->Map->Terrains[t].maxheight, App->Map->Terrains[t].blocksize);

			scene::ISceneNode* terrain =  smgr->addOctTreeSceneNode ( terrainMesh );

			scene::ITriangleSelector* selector = smgr->createOctTreeTriangleSelector ( terrainMesh->getMesh ( 0 ),terrain, 128 );

			metaSelector->addTriangleSelector(selector);
			terrain->setTriangleSelector(selector);

			terrains.push_back(terrain);

			terrain->setScale(App->Map->Terrains[t].scale);
			terrain->setPosition(App->Map->Terrains[t].position);

			NewtonCollision* newtonmap = GetNewtonCollision(terrain, terrainMesh);
			// create a ridid body to represent the world
			NewtonBody* newtonmapbody;
			newtonmapbody = NewtonCreateBody(nWorld, newtonmap);
			DebugBodies.push_back(newtonmapbody);
			NewtonReleaseCollision (nWorld, newtonmap);
			NewtonBodySetMaterialGroupID (newtonmapbody, Physics->m_groundMaterial);
		}
	}
Does anyone implemented a code for newton that works better? i rewrote some parts of the mercior tutorial for my code.
Arena of Honor: http://aoh.arturh.com
Cairon
Posts: 40
Joined: Sun Apr 11, 2004 12:52 am
Contact:

Post by Cairon »

i've got it, with a function wrote by Sprintz in this thread: http://irrlicht.sourceforge.net/phpBB2/ ... php?t=4917

But I use this only for loading terrain. But it only works when i set optimize = 0 in NewtonTreeCollisionEndBuild(newtonmap, optimize) :-( dunno why, but my fps is still very high (300-400 in debug compile)

And i fixed a bug in my own function, which i use for loading the bsp level.

vArray[0] = (((mb_vertices[v1i].Pos ) * scale) * IrrToNewton) +translation;
vArray[1] = (((mb_vertices[v2i].Pos ) * scale) * IrrToNewton) +translation;
vArray[2] = (((mb_vertices[v3i].Pos ) * scale) * IrrToNewton) +translation;

The () are different positioned, i have to multiply by IrrToNewton first, because the position is already in irrlicht coordinates.
Arena of Honor: http://aoh.arturh.com
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

It's Spintz!!! ;)

Anyways, I think it's an issue with Newton. From what i'd gotten from the Newton forums, before I abandoned them, was that for terrain, you should be using some type of user mesh, etc. You can see some posts by me, about a serializer i was trying to right, and problems i was having.

Once the mesh you're optimizing with newton gets to be over 64x64, newton takes, literally, days, to optimize the mesh. It works, but it takes a long, long, long, long, long, long, long, long time. There was some answer to this, like i said about usermeshcollision objects or something or other, but my issue with them was that in order to use them, you had to handle the physics yourself, newton didn't. I figured why bother, if I'm using a physics engine, it should be doing the physics, not me. So, now I'm working on using Novodex and seeing how that goes, I like the documentation and the setup a lot better than newton, and from what i hear, it's faster, not as accurate, but faster, and I want faster, not as accurate.

Try looking around / asking about this problem on the newton forums.
Cairon
Posts: 40
Joined: Sun Apr 11, 2004 12:52 am
Contact:

Post by Cairon »

sorry, Spintz! :)

But now everything works fine, and its fast enougth for me even without optimization.
I'm trying now to implement the jeep from the newton sdk example...

Has somebody did this before? Could someone send my some code? kontakt at arturh dot com, or contact me via icq.

Because its a lotta work to convert all this from opengl to irrlicht... but i'll try ^^
Arena of Honor: http://aoh.arturh.com
Post Reply