示例#1
0
NewtonCollision* CreateNewtonMesh (NewtonWorld* world, StaticEntity* ent, int* shapeIdArray)
{
	NewtonCollision* collision;

	// now create and empty collision tree
	collision = NewtonCreateTreeCollision (world, 0);

	// start adding faces to the collision tree
	NewtonTreeCollisionBeginBuild (collision);

	Vertex vert;
	unsigned int i,j;
	unsigned int counter = 0;

	// step over the collision geometry and add all faces to the collision tree
	for (i = 0; i <  ent->meshObj->mesh.size(); i ++) {
		// add each sub mesh as a face id, will will use this later for a multi material sound effect in and advanced tutorial
		for (j = 0; j < ent->meshObj->mesh[i]->numFaces; j++) {
			glm::vec3 face[3];

			vert=ent->meshObj->mesh[i]->vertex[ent->meshObj->mesh[i]->face[j].point[0]];
            face[0] = glm::vec3(vert.x, vert.y, vert.z)*ent->scale;

            vert=ent->meshObj->mesh[i]->vertex[ent->meshObj->mesh[i]->face[j].point[1]];
            face[1] = glm::vec3 (vert.x, vert.y, vert.z)*ent->scale;

            vert=ent->meshObj->mesh[i]->vertex[ent->meshObj->mesh[i]->face[j].point[2]];
            face[2] = glm::vec3 (vert.x, vert.y, vert.z)*ent->scale;

            counter++;

			if (shapeIdArray) {
				NewtonTreeCollisionAddFace(collision, 3, &face[0].x, sizeof (glm::vec3), shapeIdArray[i]);
			} else {
				NewtonTreeCollisionAddFace(collision, 3, &face[0].x, sizeof (glm::vec3), i + 1);
			}


		}
	}

	// end adding faces to the collision tree, also optimize the mesh for best performance
	NewtonTreeCollisionEndBuild (collision, 1);

	return collision;
}
示例#2
0
void CEffectsGame::CreateScene()
{
	pScene->CreateSkybox("clear");

	NewtonBody *bFloor = AddBox(pScene, pWorld, Vector3(0,-0.5,0), Vector3(1000,1,1000), Vector3());	
	NewtonCollision *col = NewtonCreateTreeCollision(pWorld, 0);
	NewtonTreeCollisionBeginBuild(col);
	Vector3 v[4] = {
		Vector3(-1000,0.5f,-1000),
		Vector3(-1000,0.5f,+1000),
		Vector3(+1000,0.5f,+1000),
		Vector3(+1000,0.5f,-1000)
	};
	NewtonTreeCollisionAddFace(col, 4, &v[0][0], sizeof(Vector3), 1);
	NewtonTreeCollisionEndBuild(col, 0);

	



	NewtonBodySetCollision(bFloor, col);

	CObject3D *f = (CObject3D*)NewtonBodyGetUserData(bFloor);
	f->visible = false;

	NewtonBodySetMaterialGroupID(bFloor, gLevelChunksMaterialID);

	// floor
	static CTexture *floorTex = new CTexture("textures/512.png");
	CMaterial *floorMat = new CMaterial();
	floorMat->features = EShaderFeature::LIGHT | EShaderFeature::FOG | EShaderFeature::SHADOW | EShaderFeature::TEXTURE;
	CPlaneGeometry *floorGeom = new CPlaneGeometry(1000,1000);
	CObject3D *floor = new CMesh( floorGeom, floorMat );
	floor->geometry->materials.AddToTail(floorMat);
	floorMat->pTexture = floorTex;
	floorGeom->SetTextureScale(40,40);
	floor->SetPosition(-500, 0, -500);
	pScene->Add(floor);

	

	pLevel = new CLevel(pScene, pWorld);
	pLevel->Create(32,80,32);

	int width = 24;
	int depth = 24;
	int storeys = 8;
	int storyHeight = 8;

	for (int y=0; y<storeys*storyHeight; y++)
		for (int x=0; x<width; x++)
			for (int z=0; z<depth; z++)
			{
				int block = 0;
				if (x==0 || z==0 || x==width-1 || z==depth-1) block = 1;
				if (y%storyHeight == storyHeight-1) block = 1;
				if (x>5 && z>5 && x<width-5 && z<depth-5) block = 0;

				if (y%storyHeight > 2 && y%storyHeight <= 4) 
				{
					if (x%8 >= 2 && x%8 < 7) block = 0;
					if (z%8 >= 2 && z%8 < 7) block = 0;
				}

				if ((x==5 && z==5) || (x==width-5 && z==depth-5) || (x==5 && z==depth-5) || (x==width-5 && z==5) ) block = 4;

				
				if (block > 0)	block = 4;
				pLevel->GetTile(x,y,z)->type = block;
			}

	int sx = 55;
	int sz = 55;
	



	pLevel->Recreate();

	for (int x=0; x<pLevel->chunksX; x++)
		for (int y=0; y<pLevel->chunksY; y++)
			for (int z=0; z<pLevel->chunksZ; z++)
			{
				pLevel->GetChunk(x,y,z)->RecreateCollision();
			}	

	// once the map has been created, creatie bodies that will collide
	/*for (int x=0; x<pLevel->sizeX; x++)
		for (int y=0; y<pLevel->sizeY; y++)
			for (int z=0; z<pLevel->sizeZ; z++)
			{
				if (pLevel->GetTile(x,y,z)->type == 0) continue;

				CObject3D *o = new CObject3D();
				o->SetPosition(Vector3(x+0.5, y+0.5, z+0.5));
				
				NewtonBody *box = CPhysics::CreateBox(pWorld, o, 1,1,1, 0);
				NewtonBodySetFreezeState(box, 1);

				delete o;
			}*/

	// let's create a collision tree for each chunk
/*	for (int x=0; x<pLevel->chunksX; x++)
		for (int y=0; y<pLevel->chunksY; y++)
			for (int z=0; z<pLevel->chunksZ; z++)
			{
				NewtonCollision * col = NewtonCreateTreeCollision(pWorld, 0);
				NewtonTreeCollisionBeginBuild(col);

				CArray<Vector3> &verts = pLevel->GetChunk(x,y,z)->pMesh->geometry->vertices;
				for (int i=0; i<pLevel->GetChunk(x,y,z)->pMesh->geometry->faces.Size(); i++)
				{
					Face3 face = pLevel->GetChunk(x,y,z)->pMesh->geometry->faces[i];
					Vector3 v[] = { verts[face.a], verts[face.b], verts[face.c] };
					NewtonTreeCollisionAddFace(col, 3, &v[0][0], sizeof(Vector3), 1);
				}
				NewtonTreeCollisionEndBuild(col, 1);

				// create body
				float m[16] = { 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 };
				NewtonBody *body = NewtonCreateBody(pWorld, col, &m[0]);
				NewtonReleaseCollision(pWorld, col);
				NewtonBody
			}
*/
	/*
	CreateBuilding(0,0,0, 3,8,3);
	CreateBuilding(20,0,-10, 2,4,6);
	CreateBuilding(-5,0,-20, 5,2,3);
	*/

	// point light that will circle the building
	pLight = new CPointLight(Vector3(), SRGBA(255,200,50));
	pLight->range = 8.0f;
	pLight->overbright = true;
	pScene->Add(pLight);

	pScene->fog = new SFog( SRGBA(172,201,241, 255), 200, 500);

	// point light at 0,1,0
	CLight *pLight = new CPointLight(Vector3(0,1,0), RED);//SRGBA(255,233,155,255));
	//pScene->Add( pLight );
	pLight->specular = pLight->color;//SRGBA(255,255,255,100);
	pLight->range = 1;
	pLight->intensity = 1;	

	// directional Sun light
	CDirectionalLight *pDirLight = new CDirectionalLight(Vector3(0,0,0), SRGBA(255,225,175,255));
	pDirLight->SetPosition(+70,90,-70);
	pDirLight->LookAt(Vector3());
	pDirLight->UpdateMatrixWorld(true);
	pDirLight->shadowNear = 20;
	pDirLight->shadowFar = 200;
	pDirLight->castShadow = true;
	float aspect = (float)gEngine.width / gEngine.height;
	pDirLight->width = 200.0f;
	pDirLight->height = pDirLight->width / aspect;
	pScene->Add( pDirLight );
	
	// ambient light
	pScene->ambientColor = SRGBA(200,200,255,255);

	pCamera->LookAt(Vector3());
}
示例#3
0
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) {
				int index;	
				dVector face[3];

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

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

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

				matrix.TransformTriplex (&face[0].m_x, sizeof (dVector), &face[0].m_x, sizeof (dVector), 3);

				// use material ids as physics materials 
				NewtonTreeCollisionAddFace(collision, 3, &face[0].m_x, sizeof (dVector), 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 CollisionDetection::addStaticTreeCollisionMesh( Entity *entity, string name)
{
    bool meshCreated = false;
    NewtonCollision *treeCollision;

    std::stringstream out;
    out << name;

    string fileString = ConstManager::getString("cmesh_file_path");
    fileString += out.str();
    fileString.append(".cmesh");
    cout << fileString<<endl;
    char *fileName = (char*) fileString.c_str();

    if( !gernerateMeshes )
    {
        FILE* meshFile;
        meshFile = fopen(fileName,"r");
        if (meshFile!=NULL)
        {
            treeCollision = NewtonCreateCollisionFromSerialization (newtonWorld, myDeserializeCollisionCallbackFunction, meshFile);
            fclose (meshFile);
            meshCreated = true;
        }
        else
        {
            cout << "Colision detection could not read file.\nAttempting to create mesh from scratch" << endl;
        }
    }

    if( !meshCreated )
    {
        treeCollision = NewtonCreateTreeCollision (newtonWorld, 0);
        NewtonTreeCollisionBeginBuild(treeCollision);

        size_t vertex_count;
        size_t index_count;
        Ogre::Vector3 *vertices;
        unsigned long *indices;

        GetMeshInformation(   entity->getMesh(), vertex_count, vertices, index_count, indices,
                              entity->getParentNode()->getPosition(),
                              entity->getParentNode()->getOrientation(),
                              entity->getParentNode()->_getDerivedScale());

    /*                               Ogre::Vector3(),
                                  Ogre::Quaternion::IDENTITY,
                                  Ogre::Vector3(1,1,1)); */
        dFloat vArray[9];
        int i0, i1, i2;
        for (int i = 0; i < static_cast<int>(index_count); i += 3)
        {
            i0 = indices[i];
            i1 = indices[i+1];
            i2 = indices[i+2];

            vArray[0] = vertices[i0].x;
            vArray[1] = vertices[i0].y;
            vArray[2] = vertices[i0].z;

            vArray[3] = vertices[i1].x;
            vArray[4] = vertices[i1].y;
            vArray[5] = vertices[i1].z;

            vArray[6] = vertices[i2].x;
            vArray[7] = vertices[i2].y;
            vArray[8] = vertices[i2].z;

             NewtonTreeCollisionAddFace(treeCollision, 3, vArray,
                        sizeof(dFloat)*3, i);
        }

        NewtonTreeCollisionEndBuild(treeCollision, 1);

        FILE* meshFile;
        meshFile = fopen(fileName,"w");
        if (meshFile!=NULL)
        {
            NewtonCollisionSerialize(newtonWorld, treeCollision, mySerializeCollisionCallbackFunction, meshFile);
            fclose (meshFile);
        }
        else
        {
            cout << "Colision detection could not write cmesh file." << endl;
        }
    }

    NewtonBody* rigidTree = NewtonCreateBody (newtonWorld, treeCollision);
    NewtonReleaseCollision (newtonWorld, treeCollision);

    NewtonBodySetMatrix (rigidTree, &idmatrix[0]);

    dFloat boxP0[3];
    dFloat boxP1[3];

    //possibly need this if we rely on newton
    //NewtonCollisionCalculateAABB (treeCollision, &idmatrix[0], &boxP0[0], &boxP1[0]);

    collisionsMap.insert(pair<Entity*,NewtonCollision*>(entity,treeCollision));
    bodysMap.insert(pair<Entity*,NewtonBody*>(entity,rigidTree));
}
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;
}
示例#6
0
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;
}
	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
	}
示例#8
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;
}
	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);
	}
void dNewtonCollisionMesh::EndFace(bool optimize)
{
	NewtonTreeCollisionEndBuild(m_shape, optimize ? 1 : 0);
}