bool Physics::buildStaticGeometry( osg::Group* p_root, const std::string& levelFile )
{
    NewtonCollision* p_collision = NULL;

    // check if a serialization file exists, if so then load it. otherwise build the static geometry on the fly.
    assert( levelFile.length() && "internal error: missing levelFile name!" );
    std::string file = cleanPath( levelFile );
    std::vector< std::string > path;
    explode( file, "/", &path );
    file = yaf3d::Application::get()->getMediaPath() + YAF3DPHYSICS_MEDIA_FOLDER + path[ path.size() - 1 ] + YAF3DPHYSICS_SERIALIZE_POSTFIX;
    std::ifstream serializationfile;
    serializationfile.open( file.c_str(), std::ios_base::binary | std::ios_base::in );
    if ( !serializationfile )
    {
        log_warning << "Physics: no serialization file for physics static geometry exists, building on-the-fly ..." << std::endl;

        p_collision = NewtonCreateTreeCollision( _p_world, levelCollisionCallback );
        NewtonTreeCollisionBeginBuild( p_collision );

        // build the collision faces
        //--------------------------
        // start timer
        osg::Timer_t start_tick = osg::Timer::instance()->tick();
        //! iterate through all geometries and create their collision faces
        PhysicsVisitor physVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN, p_collision );
        p_root->accept( physVisitor );
        // stop timer and give out the time messure
        osg::Timer_t end_tick = osg::Timer::instance()->tick();
        log_debug << "Physics: elapsed time for building physics collision faces = "<< osg::Timer::instance()->delta_s( start_tick, end_tick ) << std::endl;
        log_debug << "Physics:  total num of evaluated primitives: " << physVisitor.getNumPrimitives() << std::endl;
        log_debug << "Physics:  total num of vertices: " << physVisitor.getNumVertices() << std::endl;

        //--------------------------
        // finalize tree building with optimization off ( because the meshes are already optimized by
        //  osg _and_ Newton has currently problems with optimization )
        NewtonTreeCollisionEndBuild( p_collision, 0 /* 1 */);
    }
    else
    {
        log_debug << "Physics: loading serialization file for physics static geometry: '" << file << "' ..." << std::endl;

        // start timer
        osg::Timer_t start_tick = osg::Timer::instance()->tick();

        p_collision = NewtonCreateTreeCollisionFromSerialization( _p_world, NULL, deserializationCallback, &serializationfile );
        assert( p_collision && "internal error, something went wrong during physics deserialization!" );

        // stop timer and give out the time messure
        osg::Timer_t end_tick = osg::Timer::instance()->tick();
        log_debug << "Physics: elapsed time for deserializing physics collision faces = "<< osg::Timer::instance()->delta_s( start_tick, end_tick ) << std::endl;

        serializationfile.close();
    }

    _p_body = NewtonCreateBody( _p_world, p_collision );

    // release collision object
    NewtonReleaseCollision( _p_world, p_collision );

    // set Material Id for this object
    NewtonBodySetMaterialGroupID( _p_body, getMaterialId( "level" ) );

    osg::Matrixf mat;
    mat.identity();
    NewtonBodySetMatrix( _p_body, mat.ptr() );

    // calculate the world bbox and world size
    float  bmin[ 4 ], bmax[ 4 ];
    NewtonCollisionCalculateAABB( p_collision, mat.ptr(), bmin, bmax );
    bmin[ 0 ] -= 10.0f;
    bmin[ 1 ] -= 10.0f;
    bmin[ 2 ] -= 10.0f;
    bmin[ 3 ] = 1.0f;
    bmax[ 0 ] += 10.0f;
    bmax[ 1 ] += 10.0f;
    bmax[ 2 ] += 10.0f;
    bmax[ 3 ] = 1.0f;
    NewtonSetWorldSize( _p_world, bmin, bmax );

    return true;
}
NewtonCollision* CreateCollisionTree (NewtonWorld* world, DemoEntity* const entity, int materialID, bool optimize)
{
	// measure the time to build a collision tree
	unsigned64 timer0 = dGetTimeInMicrosenconds();

	// create the collision tree geometry
	NewtonCollision* collision = NewtonCreateTreeCollision(world, materialID);

	// set the application level callback
#ifdef USE_STATIC_MESHES_DEBUG_COLLISION
	NewtonStaticCollisionSetDebugCallback (collision, ShowMeshCollidingFaces);
#endif

	// prepare to create collision geometry
	NewtonTreeCollisionBeginBuild(collision);

	// iterate the entire geometry an build the collision
	for (DemoEntity* model = entity->GetFirst(); model; model = model->GetNext()) {

		dMatrix matrix (model->GetMeshMatrix() * model->CalculateGlobalMatrix(entity));
		DemoMesh* const mesh = (DemoMesh*)model->GetMesh();
		dAssert (mesh->IsType(DemoMesh::GetRttiType()));

		dFloat* const vertex = mesh->m_vertex;
		for (DemoMesh::dListNode* nodes = mesh->GetFirst(); nodes; nodes = nodes->GetNext()) {
			DemoSubMesh& segment = nodes->GetInfo();
			int matID = segment.m_textureHandle;
			for (int i = 0; i < segment.m_indexCount; i += 3) {
				dFloat face[3][3];
				for (int j = 0; j < 3; j ++) {
					int index = segment.m_indexes[i + j] * 3;
					face[j][0] = vertex[index + 0];
					face[j][1] = vertex[index + 1];
					face[j][2] = vertex[index + 2];
				}
				matrix.TransformTriplex (&face[0][0], 3 * sizeof (dFloat), &face[0][0], 3 * sizeof (dFloat), 3);

				// use material ids as physics materials 
				NewtonTreeCollisionAddFace(collision, 3, &face[0][0], 3 * sizeof (dFloat), matID);
			}
		}
	}
	NewtonTreeCollisionEndBuild(collision, optimize ? 1 : 0);


	// test Serialization
#if 0
	FILE* file = fopen ("serialize.bin", "wb");
	NewtonCollisionSerialize (world, collision, DemoEntityManager::SerializeFile, file);
	fclose (file);
	NewtonDestroyCollision (collision);

	file = fopen ("serialize.bin", "rb");
	collision = NewtonCreateCollisionFromSerialization (world, DemoEntityManager::DeserializeFile, file);
	fclose (file);
#endif	



	// measure the time to build a collision tree
	timer0 = (dGetTimeInMicrosenconds() - timer0) / 1000;

	return collision;
}
	void AddCollisionTreeMesh (DemoEntityManager* const scene)
	{
		// open the level data
		char fullPathName[2048];
		GetWorkingFileName ("playground.ngd", fullPathName);

		scene->LoadScene (fullPathName);

		// find the visual mesh and make a collision tree
		NewtonWorld* const world = scene->GetNewton();
		DemoEntity* const entity = scene->GetLast()->GetInfo();
		DemoMesh* const mesh = (DemoMesh*)entity->GetMesh();
		dAssert (mesh->IsType(DemoMesh::GetRttiType()));

		NewtonCollision* const tree = NewtonCreateTreeCollision(world, 0);
		NewtonTreeCollisionBeginBuild(tree);

		dFloat* const vertex = mesh->m_vertex;
		for (DemoMesh::dListNode* node = mesh->GetFirst(); node; node = node->GetNext()){
			DemoSubMesh* const subMesh = &node->GetInfo();
			unsigned int* const indices = subMesh->m_indexes;
			int trianglesCount = subMesh->m_indexCount;
			for (int i = 0; i < trianglesCount; i += 3) {

				dVector face[3];
				int index = indices[i + 0] * 3;
				face[0] = dVector (vertex[index + 0], vertex[index + 1], vertex[index + 2]);

				index = indices[i + 1] * 3;
				face[1] = dVector (vertex[index + 0], vertex[index + 1], vertex[index + 2]);

				index = indices[i + 2] * 3;
				face[2] = dVector (vertex[index + 0], vertex[index + 1], vertex[index + 2]);

				int matID = 0;
				//matID = matID == 2 ? 1 : 2 ;
				NewtonTreeCollisionAddFace(tree, 3, &face[0].m_x, sizeof (dVector), matID);
			}
		}
		NewtonTreeCollisionEndBuild (tree, 0);

		// add the collision tree to the collision scene
		void* const proxy = NewtonSceneCollisionAddSubCollision (m_sceneCollision, tree);

		// destroy the original tree collision
		NewtonDestroyCollision (tree);

		// set the parameter on the added collision share
		dMatrix matrix (entity->GetCurrentMatrix());
		NewtonCollision* const collisionTree = NewtonSceneCollisionGetCollisionFromNode (m_sceneCollision, proxy);

		NewtonSceneCollisionSetSubCollisionMatrix (m_sceneCollision, proxy, &matrix[0][0]);	
		NewtonCollisionSetUserData(collisionTree, mesh);

		// set the application level callback
#ifdef USE_STATIC_MESHES_DEBUG_COLLISION
		NewtonStaticCollisionSetDebugCallback (collisionTree, ShowMeshCollidingFaces);
#endif

		mesh->AddRef();

		scene->RemoveEntity (entity);

	#ifdef USE_TEST_ALL_FACE_USER_RAYCAST_CALLBACK
		// set a ray cast callback for all face ray cast 
		NewtonTreeCollisionSetUserRayCastCallback (collisionTree, AllRayHitCallback);
		dVector p0 (0,  100, 0, 0);
		dVector p1 (0, -100, 0, 0);
		dVector normal(0.0f);
		dLong id;
		dFloat parameter;
		parameter = NewtonCollisionRayCast (collisionTree, &p0[0], &p1[0], &normal[0], &id);
	#endif
	}
Exemple #4
0
Terrain::Terrain(const ion::base::String& identifier,NewtonWorld *pNewtonworld,ion::scene::Renderer& rRenderer,
		ion::base::Streamable& heightmap,const ion_uint32 width,const ion_uint32 depth,const ion_uint32 patchwidth,
		const ion_uint32 patchdepth,const ion::math::Vector3f& offset,const ion::math::Vector3f& size):
m_pNewtonworld(pNewtonworld),Node(identifier)
{
	ion_uint32 numpatchesX=(width-1)/(patchwidth-1),numpatchesZ=(depth-1)/(patchdepth-1);
	ion_uint16 *pHeightbuffer=new ion_uint16[(width+1)*(depth+1)];

	{
		ion_uint16 *pHLine=pHeightbuffer;
		for (ion_uint32 z=0;z<depth;++z) {
			heightmap.read(pHLine,width*sizeof(ion_uint16));

			// Copy the first height to the one extra height for correct normal vector calculations
			pHLine[width]=pHLine[0];

			pHLine+=(width+1);
		}
		// Copy the first line to the one extra line for correct normal vector calculations
		memcpy(pHeightbuffer+(width+1)*depth,pHeightbuffer,(width+1)*sizeof(ion_uint16));
	}

	const ion::math::Vector3f psize(
		size.x()/((float)numpatchesX),
		size.y(),
		size.z()/((float)numpatchesZ)
		);

	ion::math::Vector3f poffset(
		offset.x()/*-psize.x()*0.5f*/,
		offset.y(),
		offset.z()/*-psize.z()*0.5f*/
		);

	ion::base::Localfile serializefile;
	bool fileok=serializefile.open(serializefilename,"rb");
	if (fileok) {
		ion::base::log("Terrain::Terrain()",ion::base::Message) << "Using previously serialized terrain data\n";
		serializefile.open(serializefilename,"rb");
		m_pTreeCollision=NewtonCreateTreeCollisionFromSerialization(pNewtonworld,0,TerrainDeserialize,&serializefile);
		serializefile.close();
	} else {
		ion::base::log("Terrain::Terrain()",ion::base::Message) << "Calculating terrain data\n";
		m_pTreeCollision=NewtonCreateTreeCollision(pNewtonworld,0);
		NewtonTreeCollisionBeginBuild(m_pTreeCollision);
		{
			for (ion_uint32 z=0;z<(depth-1);++z) {
				/*float zz1=offset.z()+((float)z)/((float)(depth-1))*zsize;
				float zz2=offset.z()+((float)(z+1))/((float)(depth-1))*zsize;*/

				float zz1=offset.z()+( ((float)z)/((float)(patchdepth-1)) )*psize.z();
				float zz2=offset.z()+( ((float)(z+1))/((float)(patchdepth-1)) )*psize.z();

				unsigned int zT=(z/patchdepth)&1;
				for (ion_uint32 x=0;x<(width-1);++x) {
					float xx1=offset.x()+( ((float)x)/((float)(patchwidth-1)) )*psize.x();
					float xx2=offset.x()+( ((float)(x+1))/((float)(patchwidth-1)) )*psize.x();
					/*float xx1=offset.x()+((float)x)/((float)(width-1))*xsize;
					float xx2=offset.x()+((float)(x+1))/((float)(width-1))*xsize;*/

					float yy11=offset.y()+((float)(pHeightbuffer[x+z*(width+1)]))/65535.0f*size.y();
					float yy21=offset.y()+((float)(pHeightbuffer[x+1+z*(width+1)]))/65535.0f*size.y();
					float yy12=offset.y()+((float)(pHeightbuffer[x+(z+1)*(width+1)]))/65535.0f*size.y();
					float yy22=offset.y()+((float)(pHeightbuffer[x+1+(z+1)*(width+1)]))/65535.0f*size.y();

					float tri1[]={
						xx1,yy11,zz1,
						xx1,yy12,zz2,
						xx2,yy21,zz1
					};

					float tri2[]={
						xx2,yy21,zz1,
						xx1,yy12,zz2,
						xx2,yy22,zz2
					};

					unsigned int xT=(x/patchwidth)&1;

					unsigned int matID=((xT&zT)==1) ? 0 : (xT|zT);

					NewtonTreeCollisionAddFace(m_pTreeCollision,3,tri1,12,0);
					NewtonTreeCollisionAddFace(m_pTreeCollision,3,tri2,12,0);
				}
			}
		}
		NewtonTreeCollisionEndBuild(m_pTreeCollision,0);

		serializefile.open(serializefilename,"wb");
		NewtonTreeCollisionSerialize(m_pTreeCollision,TerrainSerialize,&serializefile);
		serializefile.close();
	}

	NewtonBody *pTerrainBody=NewtonCreateBody(m_pNewtonworld,m_pTreeCollision);
	NewtonReleaseCollision(m_pNewtonworld,m_pTreeCollision);
	NewtonBodySetMatrix(pTerrainBody,ion::math::Matrix4f::identitymatrix());

	for (ion_uint32 z=0;z<numpatchesZ;++z) {

		/*if (z==0) {
			heightmap.read(pHeightbuffer,sizeof(ion_uint16)*width*patchdepth);
		} else {
			memcpy(pHeightbuffer,pHeightbuffer+width*(patchdepth-1),width*sizeof(ion_uint16));
			heightmap.read(pHeightbuffer+width,sizeof(ion_uint16)*width*(patchdepth-1));
		}*/

		poffset.x()=offset.x()/*-psize.x()*0.5f*/;

		for (ion_uint32 x=0;x<numpatchesX;++x) {
			ion_uint16 *pH=pHeightbuffer+x*(patchwidth-1)+z*(width+1)*(patchdepth-1);
			TerrainPatch *pPatch=new TerrainPatch("tpatch",rRenderer,pH,patchwidth,width+1,patchdepth,
				(z==(numpatchesZ-1)),poffset,psize);

			poffset.x()+=psize.x();
			m_Patches.push_back(pPatch);
			addChild(*pPatch);
		}

		poffset.z()+=psize.z();
	}

	delete [] pHeightbuffer;
}
static NewtonBody* CreateBackgroundWallsAndCellingBody(NewtonWorld* world)
{
	// make a flat quad 
	dFloat floor[4][3] =
	{
		{ -100.0f, 0.0f, 100.0f },
		{ 100.0f, 0.0f, 100.0f },
		{ 100.0f, 0.0f, -100.0f },
		{ -100.0f, 0.0f, -100.0f },
	};

	dFloat wall_N[4][3] =
	{
		{ -100.0f, 0.0f, 100.0f },
		{ -100.0f, 100.0f, 100.0f },
		{ 100.0f, 100.0f, 100.0f },
		{ 100.0f, 0.0f, 100.0f },
	};

	dFloat wall_W[4][3] =
	{
		{ 100.0f, 0.0f, 100.0f },
		{ 100.0f, 100.0f, 100.0f },
		{ 100.0f, 100.0f, -100.0f },
		{ 100.0f, 0.0f, -100.0f },
	};

	dFloat wall_S[4][3] =
	{
		{ 100.0f, 0.0f, -100.0f },
		{ 100.0f, 100.0f, -100.0f },
		{ -100.0f, 100.0f, -100.0f },
		{ -100.0f, 0.0f, -100.0f },
	};

	dFloat wall_E[4][3] =
	{
		{ -100.0f, 0.0f, -100.0f },
		{ -100.0f, 100.0f, -100.0f },
		{ -100.0f, 100.0f, 100.0f },
		{ -100.0f, 0.0f, 100.0f },
	};

	dFloat celling[4][3] =
	{
		{ -100.0f, 100.0f, -100.0f },
		{ 100.0f, 100.0f, -100.0f },
		{ 100.0f, 100.0f, 100.0f },
		{ -100.0f, 100.0f, 100.0f },
	};

	// crate a collision tree
	NewtonCollision* const collision = NewtonCreateTreeCollision(world, 0);

	// start building the collision mesh
	NewtonTreeCollisionBeginBuild(collision);

	// add the face one at a time
	NewtonTreeCollisionAddFace(collision, 4, &floor[0][0], 3 * sizeof (dFloat), 0);
	NewtonTreeCollisionAddFace(collision, 4, &wall_N[0][0], 3 * sizeof (dFloat), 0);
	NewtonTreeCollisionAddFace(collision, 4, &wall_W[0][0], 3 * sizeof (dFloat), 0);
	NewtonTreeCollisionAddFace(collision, 4, &wall_S[0][0], 3 * sizeof (dFloat), 0);
	NewtonTreeCollisionAddFace(collision, 4, &wall_E[0][0], 3 * sizeof (dFloat), 0);
	NewtonTreeCollisionAddFace(collision, 4, &celling[0][0], 3 * sizeof (dFloat), 0);

	// finish building the collision
	NewtonTreeCollisionEndBuild(collision, 1);

	// create a body with a collision and locate at the identity matrix position 
	dMatrix matrix(dGetIdentityMatrix());
	NewtonBody* const body = NewtonCreateDynamicBody(world, collision, &matrix[0][0]);

	// do no forget to destroy the collision after you not longer need it
	NewtonDestroyCollision(collision);
	return body;
}
	void cCollideShapeNewton::CreateFromVertices(const unsigned int* apIndexArray, int alIndexNum,
										const float *apVertexArray, int alVtxStride, int alVtxNum)
	{
		float vTriVec[9];

		bool bOptimize = false;
		bool bCreatedPlane = false;
		cPlanef plane;

		mpNewtonCollision = NewtonCreateTreeCollision(mpNewtonWorld, NULL);
		//Log("-- Creating mesh collision.:\n");
		NewtonTreeCollisionBeginBuild(mpNewtonCollision);
		for(int tri = 0; tri < alIndexNum; tri+=3)
		{
			//Log("tri: %d:\n", tri/3);
			for(int idx =0; idx < 3; idx++)
			{
				int lVtx = apIndexArray[tri + 2-idx]*alVtxStride;

				vTriVec[idx*3 + 0] = apVertexArray[lVtx + 0];
				vTriVec[idx*3 + 1] = apVertexArray[lVtx + 1];
				vTriVec[idx*3 + 2] = apVertexArray[lVtx + 2];
			}

			if(bOptimize==false)
			{
				cPlanef tempPlane;
				cVector3f vP1(vTriVec[0+0],vTriVec[0+1],vTriVec[0+2]);
				cVector3f vP2(vTriVec[1*3+0],vTriVec[1*3+1],vTriVec[1*3+2]);
				cVector3f vP3(vTriVec[2*3+0],vTriVec[2*3+1],vTriVec[2*3+2]);

				tempPlane.FromPoints(vP1, vP2, vP3);

				//Log("P1: %s P2: %s P3: %s\n",vP1.ToString().c_str(),vP2.ToString().c_str(),vP3.ToString().c_str());
				//Log("Plane: a: %f b: %f c: %f d: %f\n",tempPlane.a,tempPlane.b,tempPlane.c,tempPlane.d);

				if(bCreatedPlane==false){
					plane = tempPlane;
					bCreatedPlane = true;
				}
				else
				{
					if(	std::abs(plane.a - tempPlane.a) > 0.001f ||
						std::abs(plane.b - tempPlane.b) > 0.001f ||
						std::abs(plane.c - tempPlane.c) > 0.001f ||
						std::abs(plane.d - tempPlane.d) > 0.001f )
					{
						bOptimize = true;
					}
				}
			}

			NewtonTreeCollisionAddFace(mpNewtonCollision,3,vTriVec,sizeof(float)*3,1);
		}

		NewtonTreeCollisionEndBuild(mpNewtonCollision, bOptimize ? 1: 0);

		//Set bounding box size
		mBoundingVolume.AddArrayPoints(apVertexArray, alVtxNum);
		mBoundingVolume.CreateFromPoints(alVtxStride);
	}
Exemple #7
0
/*
=============
CMod_PhysicsBeginBSPCollisionTree
=============
*/
void CMod_PhysicsBeginBSPCollisionTree() {
	g_collision = NewtonCreateTreeCollision (g_world);
	NewtonTreeCollisionBeginBuild (g_collision);
}
void dNewtonCollisionMesh::BeginFace()
{
	NewtonTreeCollisionBeginBuild(m_shape);
}