ShatterEffect(NewtonWorld* const world, NewtonMesh* const mesh, int interiorMaterial)
		:dList<ShatterAtom>(), m_world (world)
	{
		// first we populate the bounding Box area with few random point to get some interior subdivisions.
		// the subdivision are local to the point placement, by placing these points visual ally with a 3d tool
		// and have precise control of how the debris are created.
		// the number of pieces is equal to the number of point inside the Mesh plus the number of point on the mesh 
		dVector size;
		dMatrix matrix(GetIdentityMatrix()); 
		NewtonMeshCalculateOOBB(mesh, &matrix[0][0], &size.m_x, &size.m_y, &size.m_z);

		// pepper the inside of the BBox box of the mesh with random points
		int count = 0;
		dVector points[NUMBER_OF_ITERNAL_PARTS + 1];
		while (count < NUMBER_OF_ITERNAL_PARTS) {			
			dFloat x = RandomVariable(size.m_x);
			dFloat y = RandomVariable(size.m_y);
			dFloat z = RandomVariable(size.m_z);
			if ((x <= size.m_x) && (x >= -size.m_x) && (y <= size.m_y) && (y >= -size.m_y) && (z <= size.m_z) && (z >= -size.m_z)){
				points[count] = dVector (x, y, z);
				count ++;
			}
		} 

		// create a texture matrix, for applying the material's UV to all internal faces
		dMatrix textureMatrix (GetIdentityMatrix());
		textureMatrix[0][0] = 1.0f / size.m_x;
		textureMatrix[1][1] = 1.0f / size.m_y;

		// now we call create we decompose the mesh into several convex pieces 
		NewtonMesh* const debriMeshPieces = NewtonMeshVoronoiDecomposition (mesh, count, sizeof (dVector), &points[0].m_x, interiorMaterial, &textureMatrix[0][0]);


		// Get the volume of the original mesh
		NewtonCollision* const collision = NewtonCreateConvexHullFromMesh (m_world, mesh, 0.0f, 0);
		dFloat volume = NewtonConvexCollisionCalculateVolume (collision);
		NewtonReleaseCollision(m_world, collision);

		// now we iterate over each pieces and for each one we create a visual entity and a rigid body
		NewtonMesh* nextDebri;
		for (NewtonMesh* debri = NewtonMeshCreateFirstLayer (debriMeshPieces); debri; debri = nextDebri) {
			nextDebri = NewtonMeshCreateNextLayer (debriMeshPieces, debri); 

			NewtonCollision* const collision = NewtonCreateConvexHullFromMesh (m_world, debri, 0.0f, 0);
			if (collision) {
				ShatterAtom& atom = Append()->GetInfo();
				atom.m_mesh = new DemoMesh(debri);
				atom.m_collision = collision;
				NewtonConvexCollisionCalculateInertialMatrix (atom.m_collision, &atom.m_momentOfInirtia[0], &atom.m_centerOfMass[0]);	
				dFloat debriVolume = NewtonConvexCollisionCalculateVolume (atom.m_collision);
				atom.m_massFraction = debriVolume / volume;
			}
			NewtonMeshDestroy(debri);
		}

		NewtonMeshDestroy(debriMeshPieces);
	}
Example #2
0
	void LoadTetrahedraCube(DemoEntityManager* const scene, int materialID)
	{
		dFloat mass = 5.0f;
		NewtonWorld* const world = scene->GetNewton();

		char name[2048];
		dGetWorkingFileName ("box.tet", name);
		NewtonMesh* const tetraCube = NewtonMeshLoadTetrahedraMesh(scene->GetNewton(), name);

		dMatrix aligmentUV(dGetIdentityMatrix());
		int material = LoadTexture("smilli.tga");
		NewtonMeshApplyBoxMapping(tetraCube, material, material, material, &aligmentUV[0][0]);
		NewtonMeshCalculateVertexNormals(tetraCube, 60.0f * dDegreeToRad);

		// make a deformable collision mesh
		NewtonCollision* const deformableCollision = NewtonCreateDeformableSolid(world, tetraCube, materialID);

		//create a rigid body with a deformable mesh
		m_body = CreateRigidBody(scene, mass, deformableCollision);

		// create the soft body mesh
		//m_mesh = new TetrahedraSoftMesh(tetraCube, m_body);
		DemoMesh* const mesh = new TetrahedraSoftMesh(scene, tetraCube, m_body);
		SetMesh(mesh, dGetIdentityMatrix());

		// do not forget to destroy this objects, else you get bad memory leaks.
		mesh->Release ();
		NewtonDestroyCollision(deformableCollision);
		NewtonMeshDestroy(tetraCube);
	}
void dMeshNodeInfo::ReplaceMesh (NewtonMesh* const mesh)
{
	if (m_mesh) {
		NewtonMeshDestroy(m_mesh);
	}
	SetMesh (mesh);
}
Example #4
0
	void BuildRegularTetrahedra (DemoEntityManager* const scene, int materialID)
	{
		dFloat mass = 5.0f;
		NewtonWorld* const world = scene->GetNewton();

		dVector tetra[] = { dVector(-1.0f, 0.0f, -0.71f, 0.0f),
							dVector(1.0f, 0.0f, -0.71f, 0.0f),
							dVector(0.0f, -1.0f, 0.71f, 0.0f),
							dVector(0.0f, 1.0f, 0.71f, 0.0f) };

		NewtonMesh* const tetrahedra = NewtonMeshCreate(scene->GetNewton());
		NewtonMeshBeginBuild(tetrahedra);
			AddTetra (tetrahedra, 0, 1, 2, 3, tetra, 0);
		NewtonMeshEndBuild(tetrahedra);

		dMatrix aligmentUV(dGetIdentityMatrix());
		int material = LoadTexture("smilli.tga");
		NewtonMeshApplyBoxMapping (tetrahedra, material, material, material, &aligmentUV[0][0]);
		NewtonMeshCalculateVertexNormals (tetrahedra, 60.0f * dDegreeToRad);

		// make a deformable collision mesh
		NewtonCollision* const deformableCollision = NewtonCreateDeformableSolid(world, tetrahedra, materialID);

		//create a rigid body with a deformable mesh
		m_body = CreateRigidBody (scene, mass, deformableCollision);

		// create the soft body mesh
		DemoMesh* const mesh = new TetrahedraSoftMesh(scene, tetrahedra, m_body);
		SetMesh(mesh, dGetIdentityMatrix());

		// do not forget to destroy this objects, else you get bad memory leaks.
		mesh->Release ();
		NewtonMeshDestroy (tetrahedra);
		NewtonDestroyCollision(deformableCollision);
	}
Example #5
0
void dMeshNodeInfo::ReplaceMesh (NewtonMesh* mesh)
{
	if (m_mesh) {
		NewtonMeshDestroy(m_mesh);
	}
	m_mesh = mesh;
}
	DelaunayEffect(NewtonWorld* const world, NewtonMesh* const mesh, int interiorMaterial)
		:FractureEffect(world)
	{
		// first we populate the bounding Box area with few random point to get some interior subdivisions.
		// the subdivision are local to the point placement, by placing these points visual ally with a 3d tool
		// and have precise control of how the debris are created.
		// the number of pieces is equal to the number of point inside the Mesh plus the number of point on the mesh 
		dVector size(0.0f);
		dMatrix matrix(dGetIdentityMatrix());
		NewtonMeshCalculateOOBB(mesh, &matrix[0][0], &size.m_x, &size.m_y, &size.m_z);

		// create a texture matrix, for applying the material's UV to all internal faces
		dMatrix textureMatrix(dGetIdentityMatrix());
		textureMatrix[0][0] = 1.0f / size.m_x;
		textureMatrix[1][1] = 1.0f / size.m_y;

		// Get the volume of the original mesh
		NewtonCollision* const collision1 = NewtonCreateConvexHullFromMesh(m_world, mesh, 0.0f, 0);
		dFloat volume = NewtonConvexCollisionCalculateVolume(collision1);
		NewtonDestroyCollision(collision1);

		// now we call create we decompose the mesh into several convex pieces 
		NewtonMesh* const debriMeshPieces = NewtonMeshCreateTetrahedraIsoSurface(mesh);
		dAssert(debriMeshPieces);

		// now we iterate over each pieces and for each one we create a visual entity and a rigid body
		NewtonMesh* nextDebri;
		for (NewtonMesh* debri = NewtonMeshCreateFirstLayer(debriMeshPieces); debri; debri = nextDebri) {
			// get next segment piece
			nextDebri = NewtonMeshCreateNextLayer(debriMeshPieces, debri);
			
			//clip the Delaunay convexes against the mesh, make a convex hull collision shape
			NewtonCollision* const collision = NewtonCreateConvexHullFromMesh(m_world, debri, 0.0f, 0);
			if (collision) {
				// we have a piece which has a convex collision  representation, add that to the list
				FractureAtom& atom = Append()->GetInfo();
				atom.m_mesh = new DemoMesh(debri);
				atom.m_collision = collision;
				NewtonConvexCollisionCalculateInertialMatrix(atom.m_collision, &atom.m_momentOfInirtia[0], &atom.m_centerOfMass[0]);
				dFloat debriVolume = NewtonConvexCollisionCalculateVolume(atom.m_collision);
				atom.m_massFraction = debriVolume / volume;
			}
			NewtonMeshDestroy(debri);
		}

		NewtonMeshDestroy(debriMeshPieces);
	}
// create a mesh using the NewtonMesh low lever interface
static NewtonBody* CreateSimpleBox_NewtonMesh (DemoEntityManager* const scene, const dVector& origin, const dVector& scale, dFloat mass)
{
	dBigVector array[8];
	dBigVector scale1 (scale);
	for (int i = 0; i < 8; i ++) {
		dBigVector p(&BoxPoints[i * 4]);
		array[i] = scale1 * p;
	}

	NewtonMeshVertexFormat vertexFormat;
	NewtonMeshClearVertexFormat(&vertexFormat);

	vertexFormat.m_faceCount = 10;
	vertexFormat.m_faceIndexCount = faceIndexList;
	vertexFormat.m_faceMaterial = faceMateriaIndexList;

	vertexFormat.m_vertex.m_data = &array[0][0];
	vertexFormat.m_vertex.m_indexList = BoxIndices;
	vertexFormat.m_vertex.m_strideInBytes = sizeof (dBigVector);

	vertexFormat.m_normal.m_data = normal;
	vertexFormat.m_normal.m_indexList = faceNormalIndex;
	vertexFormat.m_normal.m_strideInBytes = 3 * sizeof (dFloat);

	// all channel are now optionals so we not longer has to pass default values
//	vertexFormat.m_uv0.m_data = uv0;
//	vertexFormat.m_uv0.m_indexList = uv0_indexList;
//	vertexFormat.m_uv0.m_strideInBytes = 2 * sizeof (dFloat);

	// now we create and empty mesh
	NewtonMesh* const newtonMesh = NewtonMeshCreate(scene->GetNewton());
	NewtonMeshBuildFromVertexListIndexList(newtonMesh, &vertexFormat);

	// now we can use this mesh for lot of stuff, we can apply UV, we can decompose into convex, 
	NewtonCollision* const collision = NewtonCreateConvexHullFromMesh(scene->GetNewton(), newtonMesh, 0.001f, 0);

	// for now we will simple make simple Box,  make a visual Mesh
	DemoMesh* const visualMesh = new DemoMesh (newtonMesh);

	dMatrix matrix (dGetIdentityMatrix());
	matrix.m_posit = origin;
	matrix.m_posit.m_w = 1.0f;

	NewtonBody* const body = CreateSimpleSolid(scene, visualMesh, mass, matrix, collision, 0);
	dVector veloc(1, 0, 2, 0);
	NewtonBodySetVelocity(body, &veloc[0]);

	visualMesh->Release();
	NewtonDestroyCollision(collision);
	NewtonMeshDestroy (newtonMesh);
	return body;
}
Example #8
0
	void CreateTetrahedraPrimitive(DemoEntityManager* const scene, int materialID)
	{
		dFloat mass = 5.0f;
		dVector size (1.0f);

		NewtonWorld* const world = scene->GetNewton();
		NewtonCollision* const primitiveShape = CreateConvexCollision (world, dGetIdentityMatrix(), size, _SPHERE_PRIMITIVE, materialID);
		//NewtonCollision* const primitiveShape = CreateConvexCollision (world, dGetIdentityMatrix(), size, _BOX_PRIMITIVE, materialID);
		NewtonMesh* const skinMesh = NewtonMeshCreateFromCollision(primitiveShape);

		dMatrix aligmentUV(dGetIdentityMatrix());
		int material = LoadTexture("smilli.tga");
		NewtonMeshApplySphericalMapping(skinMesh, material, &aligmentUV[0][0]);

		// now now make an tetrahedra iso surface approximation of this mesh
		NewtonMesh* const tetraIsoSurface = NewtonMeshCreateTetrahedraIsoSurface(skinMesh);

		// calculate the linear blend weight for the tetrahedra mesh
		NewtonCreateTetrahedraLinearBlendSkinWeightsChannel (tetraIsoSurface, skinMesh);
		NewtonDestroyCollision(primitiveShape);

		// make a deformable collision mesh
		NewtonCollision* const deformableCollision = NewtonCreateDeformableSolid(world, tetraIsoSurface, materialID);

		//create a rigid body with a deformable mesh
		m_body = CreateRigidBody(scene, mass, deformableCollision);

		// create the soft body mesh
		//DemoMesh* const mesh = new TetrahedraSoftMesh(tetraIsoSurface, m_body);
		DemoMesh* const mesh = new LinearBlendMeshTetra(scene, skinMesh, m_body);
		SetMesh(mesh, dGetIdentityMatrix());
		
		// do not forget to destroy this objects, else you get bad memory leaks.
		mesh->Release ();
		NewtonMeshDestroy(skinMesh);
		NewtonDestroyCollision(deformableCollision);
		NewtonMeshDestroy(tetraIsoSurface);
	}
	static void AddFracturedPrimitive(DemoEntityManager* const scene, dFloat mass, const dVector& origin, const dVector& size, int xCount, int zCount, dFloat spacing, PrimitiveType type, int materialID, const dMatrix& shapeOffsetMatrix)
	{
		// create the shape and visual mesh as a common data to be re used
		NewtonWorld* const world = scene->GetNewton();
		NewtonCollision* const collision = CreateConvexCollision(world, shapeOffsetMatrix, size, type, materialID);

		// create a newton mesh from the collision primitive
		NewtonMesh* const mesh = NewtonMeshCreateFromCollision(collision);

		// apply a material map
		int externalMaterial = LoadTexture("reljef.tga");
		//int internalMaterial = LoadTexture("KAMEN-stup.tga");
		int internalMaterial = LoadTexture("concreteBrick.tga");

		dMatrix aligmentUV(dGetIdentityMatrix());
		NewtonMeshApplyBoxMapping(mesh, externalMaterial, externalMaterial, externalMaterial, &aligmentUV[0][0]);

		// create a newton mesh from the collision primitive
		VoronoidEffect fracture(world, mesh, internalMaterial);

		DemoMesh* const visualMesh = new DemoMesh(mesh);

		dFloat startElevation = 100.0f;
		dMatrix matrix(dGetIdentityMatrix());
		for (int i = 0; i < xCount; i++) {
			dFloat x = origin.m_x + (i - xCount / 2) * spacing;
			for (int j = 0; j < zCount; j++) {
				dFloat z = origin.m_z + (j - zCount / 2) * spacing;

				matrix.m_posit.m_x = x;
				matrix.m_posit.m_z = z;
				dVector floor(FindFloor(world, dVector(matrix.m_posit.m_x, startElevation, matrix.m_posit.m_z, 0.0f), 2.0f * startElevation));
				matrix.m_posit.m_y = floor.m_y + 1.0f;
				SimpleFracturedEffectEntity::AddFracturedEntity(scene, visualMesh, collision, fracture, matrix.m_posit);
			}
		}

		// do not forget to release the assets	
		NewtonMeshDestroy(mesh);
		visualMesh->Release();
		NewtonDestroyCollision(collision);
	}
Example #10
0
static void AddStaticMesh(DemoEntityManager* const scene)
{
    char fileName[2048];

    NewtonWorld* const world = scene->GetNewton();
    GetWorkingFileName ("ramp.off", fileName);
    NewtonMesh* const ntMesh = NewtonMeshLoadOFF(world, fileName);

    dMatrix matrix (dGetIdentityMatrix());
    DemoMesh* mesh = new DemoMesh(ntMesh);
    DemoEntity* const entity = new DemoEntity(matrix, NULL);
    entity->SetMesh(mesh, dGetIdentityMatrix());
    mesh->Release();

    scene->Append(entity);

    CreateLevelMeshBody (world, entity, true);

    NewtonMeshDestroy (ntMesh);
}
static void AddShatterPrimitive (DemoEntityManager* const scene, dFloat mass, const dVector& origin, const dVector& size, int xCount, int zCount, dFloat spacing, PrimitiveType type, int materialID)
{
	dMatrix matrix (GetIdentityMatrix());

	// create the shape and visual mesh as a common data to be re used
	NewtonWorld* const world = scene->GetNewton();
	NewtonCollision* const collision = CreateConvexCollision (world, GetIdentityMatrix(), size, type, materialID);


	// create a newton mesh from the collision primitive
	NewtonMesh* const mesh = NewtonMeshCreateFromCollision(collision);

	// apply a material map
	int externalMaterial = LoadTexture("reljef.tga");
	int internalMaterial = LoadTexture("KAMEN-stup.tga");
	NewtonMeshApplyBoxMapping(mesh, externalMaterial, externalMaterial, externalMaterial);

	// create a newton mesh from the collision primitive
	ShatterEffect shatter (world, mesh, internalMaterial);

	DemoMesh* const visualMesh = new DemoMesh(mesh);

	for (int i = 0; i < xCount; i ++) {
		dFloat x = origin.m_x + (i - xCount / 2) * spacing;
		for (int j = 0; j < zCount; j ++) {
			dFloat z = origin.m_z + (j - zCount / 2) * spacing;

			matrix.m_posit.m_x = x;
			matrix.m_posit.m_z = z;
			matrix.m_posit.m_y = FindFloor (world, x, z) + 4.0f;
			AddShatterEntity (scene, visualMesh, collision, shatter, matrix.m_posit);
		}
	}


	// do not forget to release the assets	
	NewtonMeshDestroy (mesh);
	visualMesh->Release(); 
	NewtonReleaseCollision(world, collision);

}
// destroy the clipper Mesh
static void DestroyWorldCallback(const NewtonWorld* newtonWorld)
{
	NewtonMeshDestroy(meshClipper);
}
static void CreateSimpleVoronoiShatter (DemoEntityManager* const scene)
{
	// create a collision primitive
//	dVector size (2.0f, 2.0f, 2.0f);
//	dVector size = dVector (10.0f, 0.5f, 10.0f, 0.0f);
	dVector size = dVector (5.0f, 5.0f, 5.0f, 0.0f);
	NewtonWorld* const world = scene->GetNewton();

//	NewtonCollision* const collision = CreateConvexCollision (world, GetIdentityMatrix(), size, _BOX_PRIMITIVE, 0);
	NewtonCollision* const collision = CreateConvexCollision (world, GetIdentityMatrix(), size, _CAPSULE_PRIMITIVE, 0);
//	NewtonCollision* const collision = CreateConvexCollision (world, GetIdentityMatrix(), size, _SPHERE_PRIMITIVE, 0);
//	NewtonCollision* const collision = CreateConvexCollision (world, GetIdentityMatrix(), size, _REGULAR_CONVEX_HULL_PRIMITIVE, 0);
//	NewtonCollision* const collision = CreateConvexCollision (world, GetIdentityMatrix(), size, _RANDOM_CONVEX_HULL_PRIMITIVE, 0);
	
	

	// create a newton mesh from the collision primitive
	NewtonMesh* const mesh = NewtonMeshCreateFromCollision(collision);

	// apply a simple Box Mapping
	int tex0 = LoadTexture("reljef.tga");
	NewtonMeshApplyBoxMapping(mesh, tex0, tex0, tex0);

	// pepper the bing box of the mesh with random points
	dVector points[NUMBER_OF_ITERNAL_PARTS + 100];
	int count = 0;

	while (count < NUMBER_OF_ITERNAL_PARTS) {
		dFloat x = RandomVariable(size.m_x);
		dFloat y = RandomVariable(size.m_y);
		dFloat z = RandomVariable(size.m_z);
		if ((x <= size.m_x) && (x >= -size.m_x) && (y <= size.m_y) && (y >= -size.m_y) && (z <= size.m_z) && (z >= -size.m_z)){
			points[count] = dVector (x, y, z);
			count ++;
		}
	} 

count = 4;

	// Create the array of convex pieces from the mesh
	int interior = LoadTexture("KAMEN-stup.tga");
//	int interior = LoadTexture("camo.tga");
	dMatrix textureMatrix (GetIdentityMatrix());
	textureMatrix[0][0] = 1.0f / size.m_x;
	textureMatrix[1][1] = 1.0f / size.m_y;
	NewtonMesh* const convexParts = NewtonMeshVoronoiDecomposition (mesh, count, sizeof (dVector), &points[0].m_x, interior, &textureMatrix[0][0]);
//	NewtonMesh* const convexParts = NewtonMeshConvexDecomposition (mesh, 1000000);

#if 1
dScene xxxx(world);
dScene::dTreeNode* const modelNode = xxxx.CreateSceneNode(xxxx.GetRootNode());
dScene::dTreeNode* const meshNode = xxxx.CreateMeshNode(modelNode);
dMeshNodeInfo* const modelMesh = (dMeshNodeInfo*)xxxx.GetInfoFromNode(meshNode);
modelMesh->ReplaceMesh (convexParts);
xxxx.Serialize("../../../media/xxx.ngd");
#endif

	DemoEntity* const entity = new DemoEntity(NULL);
	entity->SetMatrix(*scene, dQuaternion(), dVector (0, 10, 0, 0));
	entity->InterpolateMatrix (*scene, 1.0f);
	
	
	scene->Append (entity);
	DemoMesh* const mesh1 = new DemoMesh(convexParts);
	entity->SetMesh(mesh1);
	mesh1->Release();

/*
DemoEntity* const entity2 = new DemoEntity(NULL);
entity2->SetMatrix(*scene, dQuaternion(), dVector (0, 10, 0, 0));
entity2->InterpolateMatrix (*scene, 1.0f);

scene->Append (entity2);
DemoMesh* const mesh2 = new DemoMesh(mesh);
entity2->SetMesh(mesh2);
mesh2->Release();
*/

	// make sure the assets are released before leaving the function
	if (convexParts) {
		NewtonMeshDestroy (convexParts);
	}
	NewtonMeshDestroy (mesh);
	NewtonReleaseCollision(world, collision);
}
Example #14
0
DemoMesh::DemoMesh(const char* const name, const NewtonCollision* const collision, const char* const texture0, const char* const texture1, const char* const texture2, dFloat opacity, const dMatrix& uvMatrix)
	:DemoMeshInterface()
	,dList<DemoSubMesh>()
	,m_uv(NULL)
	,m_vertex(NULL)
	,m_normal(NULL)
	,m_optimizedOpaqueDiplayList(0)		
	,m_optimizedTransparentDiplayList(0)
{
	// create a helper mesh from the collision collision
	NewtonMesh* const mesh = NewtonMeshCreateFromCollision(collision);

	// apply the vertex normals
	NewtonMeshCalculateVertexNormals(mesh, 30.0f * dDegreeToRad);

	dMatrix aligmentUV(uvMatrix);
//	NewtonCollisionGetMatrix(collision, &aligmentUV[0][0]);
	aligmentUV = aligmentUV.Inverse();

	// apply uv projections
	NewtonCollisionInfoRecord info;
	NewtonCollisionGetInfo (collision, &info);
	switch (info.m_collisionType) 
	{
		case SERIALIZE_ID_SPHERE:
		{
			NewtonMeshApplySphericalMapping(mesh, LoadTexture (texture0), &aligmentUV[0][0]);
			break;
		}

		case SERIALIZE_ID_CONE:
		case SERIALIZE_ID_CAPSULE:
		case SERIALIZE_ID_CYLINDER:
		case SERIALIZE_ID_CHAMFERCYLINDER:
		{
			//NewtonMeshApplySphericalMapping(mesh, LoadTexture(texture0));
			NewtonMeshApplyCylindricalMapping(mesh, LoadTexture(texture0), LoadTexture(texture1), &aligmentUV[0][0]);
			break;
		}

		default:
		{
			int tex0 = LoadTexture(texture0);
			int tex1 = LoadTexture(texture1);
			int tex2 = LoadTexture(texture2);
			NewtonMeshApplyBoxMapping(mesh, tex0, tex1, tex2, &aligmentUV[0][0]);
			break;
		}
	}

	// extract vertex data  from the newton mesh		
	int vertexCount = NewtonMeshGetPointCount (mesh); 
	AllocVertexData(vertexCount);
	NewtonMeshGetVertexChannel(mesh, 3 * sizeof (dFloat), (dFloat*)m_vertex);
	NewtonMeshGetNormalChannel(mesh, 3 * sizeof (dFloat), (dFloat*)m_normal);
	NewtonMeshGetUV0Channel(mesh, 2 * sizeof (dFloat), (dFloat*)m_uv);

	// extract the materials index array for mesh
	void* const geometryHandle = NewtonMeshBeginHandle (mesh); 
	for (int handle = NewtonMeshFirstMaterial (mesh, geometryHandle); handle != -1; handle = NewtonMeshNextMaterial (mesh, geometryHandle, handle)) {
		int material = NewtonMeshMaterialGetMaterial (mesh, geometryHandle, handle); 
		int indexCount = NewtonMeshMaterialGetIndexCount (mesh, geometryHandle, handle); 

		DemoSubMesh* const segment = AddSubMesh();

		segment->m_textureHandle = (GLuint)material;
		segment->SetOpacity(opacity);

		segment->AllocIndexData (indexCount);
		NewtonMeshMaterialGetIndexStream (mesh, geometryHandle, handle, (int*)segment->m_indexes); 
	}
	NewtonMeshEndHandle (mesh, geometryHandle); 

	// destroy helper mesh
	NewtonMeshDestroy(mesh);

	// optimize this mesh for hardware buffers if possible
	OptimizeForRender ();
}
static void CreateConvexAproximation (const char* const name, DemoEntityManager* const scene, const dVector& origin, int instaceCount, const char* const texture)
{
	char fileName[2048];
	dGetWorkingFileName (name, fileName);

	NewtonWorld* const world = scene->GetNewton();
	dScene compoundTestMesh (world);
	compoundTestMesh.Deserialize(fileName);

	// freeze the scale and pivot on the model 
	compoundTestMesh.FreezeScale();
//	compoundTestMesh.FreezeGeometryPivot ();
	
	dMeshNodeInfo* meshInfo = NULL;
	dMatrix scale (dGetIdentityMatrix());
	for (dScene::dTreeNode* node = compoundTestMesh.GetFirstNode (); node; node = compoundTestMesh.GetNextNode (node)) {
		dNodeInfo* info = compoundTestMesh.GetInfoFromNode(node);
		if (info->GetTypeId() == dMeshNodeInfo::GetRttiType()) {
			for (void* link = compoundTestMesh.GetFirstParentLink(node); link; link = compoundTestMesh.GetNextParentLink (node, link)) {
				dScene::dTreeNode* const node = compoundTestMesh.GetNodeFromLink(link);
				dNodeInfo* const info = compoundTestMesh.GetInfoFromNode(node);
				if (info->GetTypeId() == dSceneNodeInfo::GetRttiType()) {
					scale = ((dSceneNodeInfo*)info)->GetGeometryTransform();
					break;
				}
			}
			
			meshInfo = (dMeshNodeInfo*) info;
			break;
		}
	}

	NewtonMeshApplyTransform(meshInfo->GetMesh(), &scale[0][0]);

	dAssert (meshInfo);
	dAssert (meshInfo->GetMesh());
#if 1
	NewtonMesh* const mesh = meshInfo->GetMesh();
#else
	dGetWorkingFileName ("mesh.off", fileName);
	NewtonMesh* const mesh = NewtonMeshLoadOFF(world, fileName);
//	dMatrix scale (GetIdentityMatrix());
//	//dFloat scaleMag = 0.05f;
//	dFloat scaleMag = 1.0f;
//	scale[0][0] = scaleMag;
//	scale[1][1] = scaleMag;
//	scale[2][2] = scaleMag;
//	NewtonMesApplyTransform (mesh, &scale[0][0]);
#endif
	//NewtonMesh* const newtonMesh = NewtonMeshSimplify(mesh, 500, ReportProgress);

	// create a convex approximation form the original mesh, 32 convex max and no more than 100 vertex convex hulls
//	NewtonMesh* const convexApproximation = NewtonMeshApproximateConvexDecomposition (mesh, 0.01f, 0.2f, 32, 100, ReportProgress, scene);
	NewtonMesh* const convexApproximation = NewtonMeshApproximateConvexDecomposition (mesh, 0.01f, 0.2f, 256, 100, ReportProgress, scene);
//	NewtonMesh* const convexApproximation = NewtonMeshApproximateConvexDecomposition (mesh, 0.00001f, 0.0f, 256, 100, ReportProgress, scene);

	// create a compound collision by creation a convex hull of each segment of the source mesh 
	NewtonCollision* const compound = NewtonCreateCompoundCollisionFromMesh (world, convexApproximation, 0.001f, 0, 0);

	// test collision mode
//	NewtonCollisionSetCollisonMode(compound, 0);
	
	// make a visual Mesh
	int tex = LoadTexture(texture);
	dMatrix aligmentUV(dGetIdentityMatrix());

	NewtonMeshApplyBoxMapping(mesh, tex, tex, tex, &aligmentUV[0][0]);
	DemoMesh* const visualMesh = new DemoMesh (mesh);

	dMatrix matrix (dGetIdentityMatrix());
	matrix.m_posit = origin;
	for (int ix = 0; ix < instaceCount; ix ++) {
		for (int iz = 0; iz < instaceCount; iz ++) {
			dFloat y = origin.m_y;
			dFloat x = origin.m_x + (ix - instaceCount/2) * 10.0f;
			dFloat z = origin.m_z + (iz - instaceCount/2) * 10.0f;
			matrix.m_posit = FindFloor (world, dVector (x, y + 10.0f, z, 0.0f), 20.0f); ;
			matrix.m_posit.m_y += 2.0f;
			CreateSimpleSolid (scene, visualMesh, 10.0f, matrix, compound, 0);
		}
	}

	visualMesh->Release();

	NewtonDestroyCollision(compound);
	NewtonMeshDestroy (convexApproximation);
}
static NewtonBody* CreateSimpleNewtonMeshBox (DemoEntityManager* const scene, const dVector& origin, const dVector& scale, dFloat mass)
{
	// the vertex array, vertices's has for values, x, y, z, w
	// w is use as a id to have multiple copy of the same very, like for example mesh that share more than two edges.
	// in most case w can be set to 0.0
	static dFloat64 BoxPoints[] = {
		-1.0, -1.0, -1.0, 0.0,
		-1.0, -1.0,  1.0, 0.0,
		-1.0,  1.0,  1.0, 0.0,
		-1.0,  1.0, -1.0, 0.0,
		 1.0, -1.0, -1.0, 0.0,
		 1.0, -1.0,  1.0, 0.0,
		 1.0,  1.0,  1.0, 0.0,
		 1.0,  1.0, -1.0, 0.0,
	};

	// the vertex index list is an array of all the face, in any order, the can be convex or concave, 
	// and has and variable umber of indices
	static int BoxIndices[] = { 
		2,3,0,1,  // this is quad
		5,2,1,    // triangle
		6,2,5,    // another triangle 
		5,1,0,4,  // another quad
		2,7,3,    // and so on 
		6,7,2,
		3,4,0,
		7,4,3,
		7,5,4,
		6,5,7
	};

	// the number of index for each face is specified by an array of consecutive face index
	static int faceIndexList [] = {4, 3, 3, 4, 3, 3, 3, 3, 3, 3}; 
  
	// each face can have an arbitrary index that the application can use as a material index
	// for example the index point to a texture, we can have the each face of the cube with a different texture
	static int faceMateriaIndexList [] = {0, 4, 4, 2, 3, 3, 3, 3, 3, 3}; 


	// the normal is specified per vertex and each vertex can have a unique normal or a duplicated
	// for example a cube has 6 normals
	static dFloat normal[] = {
		1.0, 0.0, 0.0,
		-1.0, 0.0, 0.0,
		0.0, 1.0, 0.0,
		0.0, -1.0, 0.0,
		0.0, 0.0, 1.0,
		0.0, 0.0, -1.0,
	};

	static int faceNormalIndex [] = {
		0, 0, 0, 0, // first face uses the first normal of each vertex
		3, 3, 3,    // second face uses the third normal
		3, 3, 3,    // third face uses the fifth normal
		1, 1, 1, 1, // third face use the second normal
		2, 2, 2,    // and so on
		2, 2, 2,    
		4, 2, 1,    // a face can have per vertex normals
		4, 4, 4,    
		5, 5, 5,    // two coplanar face can even has different normals 
		3, 2, 0,    
	}; 
	
/*
	// the UV are encode the same way as the vertex an the normals, a UV list and an index list
	// since we do not have UV we can assign the all to zero
	static dFloat uv0[] = { 0, 0};
	static int uv0_indexList [] = { 
		0, 0, 0, 0,
		0, 0, 0,
		0, 0, 0,
		0, 0, 0, 0,
		0, 0, 0,
		0, 0, 0,
		0, 0, 0,
		0, 0, 0,
		0, 0, 0,
		0, 0, 0,
	};
*/	


	dBigVector array[8];
	dBigVector scale1 (scale);
	for (int i = 0; i < 8; i ++) {
		dBigVector p(&BoxPoints[i * 4]);
		array[i] = scale1 * p;
	}

	NewtonMeshVertexFormat vertexFormat;
	NewtonMeshClearVertexFormat(&vertexFormat);

	vertexFormat.m_faceCount = 10;
	vertexFormat.m_faceIndexCount = faceIndexList;
	vertexFormat.m_faceMaterial = faceMateriaIndexList;

	vertexFormat.m_vertex.m_data = &array[0][0];
	vertexFormat.m_vertex.m_indexList = BoxIndices;
	vertexFormat.m_vertex.m_strideInBytes = sizeof (dBigVector);

	vertexFormat.m_normal.m_data = normal;
	vertexFormat.m_normal.m_indexList = faceNormalIndex;
	vertexFormat.m_normal.m_strideInBytes = 3 * sizeof (dFloat);

	// all channel are now optionals so we not longer has to pass default values
//	vertexFormat.m_uv0.m_data = uv0;
//	vertexFormat.m_uv0.m_indexList = uv0_indexList;
//	vertexFormat.m_uv0.m_strideInBytes = 2 * sizeof (dFloat);

	// now we create and empty mesh
	NewtonMesh* const newtonMesh = NewtonMeshCreate(scene->GetNewton());
	NewtonMeshBuildFromVertexListIndexList(newtonMesh, &vertexFormat);

	// now we can use this mesh for lot of stuff, we can apply UV, we can decompose into convex, 
	NewtonCollision* const collision = NewtonCreateConvexHullFromMesh(scene->GetNewton(), newtonMesh, 0.001f, 0);

	// for now we will simple make simple Box,  make a visual Mesh
	DemoMesh* const visualMesh = new DemoMesh (newtonMesh);

	dMatrix matrix (dGetIdentityMatrix());
	matrix.m_posit = origin;
	matrix.m_posit.m_w = 1.0f;
	NewtonBody* const body = CreateSimpleSolid (scene, visualMesh, mass, matrix, collision, 0);

	visualMesh->Release();
	NewtonDestroyCollision(collision);
	NewtonMeshDestroy (newtonMesh);

	return body;
}
static void DestroyThisBodyCallback (const NewtonBody* body, const NewtonJoint* contactJoint)
{
	NewtonWorld* world;
	NewtonMesh* topMesh;
	NewtonMesh* bottomMesh;
	NewtonMesh* effectMesh;
	RenderPrimitive* srcPrimitive;
	dMatrix matrix;
	dFloat maxForce;
	dVector point;
	dVector dir0;
	dVector dir1;


	// Get the world;
	world = NewtonBodyGetWorld (body);

	// find a the strongest force 
	maxForce = 0.0f;
	for (void* contact = NewtonContactJointGetFirstContact (contactJoint); contact; contact = NewtonContactJointGetNextContact (contactJoint, contact)) {
		dVector force;
		NewtonMaterial* material;

		material = NewtonContactGetMaterial (contact);
		NewtonMaterialGetContactForce (material, &force.m_x);
		if (force.m_x > maxForce) {
			dVector normal;
			NewtonMaterialGetContactPositionAndNormal(material, &point[0], &normal[0]);
			NewtonMaterialGetContactTangentDirections (material, &dir0[0], &dir0[0]);
		}
	}

	// get the visual primitive
	srcPrimitive = (RenderPrimitive*) NewtonBodyGetUserData (body);

	// get the effect mesh that is use to create the debris pieces
	effectMesh = srcPrimitive->m_specialEffect;


	// calculate the cut plane plane
	NewtonBodyGetMatrix (body, &matrix[0][0]);

	dMatrix clipMatrix (dgGrammSchmidt(dir0) * 
						dYawMatrix(30.0f * 3.1416f/180.0f * RandomVariable(1.0f)) * 
						dRollMatrix(30.0f * 3.1416f/180.0f * RandomVariable(1.0f)));

	clipMatrix.m_posit = point;
	clipMatrix.m_posit.m_w = 1.0f;
	clipMatrix = clipMatrix * matrix.Inverse();

	// break the mesh into two pieces
	NewtonMeshClip (effectMesh, meshClipper, &clipMatrix[0][0], &topMesh, &bottomMesh);
	if (topMesh && bottomMesh) {
		dFloat volume;
		NewtonMesh* meshPartA = NULL;
		NewtonMesh* meshPartB = NULL;

		volume = NewtonConvexCollisionCalculateVolume (NewtonBodyGetCollision(body));

		// the clipper was able to make a cut now we can create new debris piece for replacement
		dMatrix clipMatrix1 (dgGrammSchmidt(dir1) * 
							 dYawMatrix(30.0f * 3.1416f/180.0f * RandomVariable(1.0f)) * 
							 dRollMatrix(30.0f * 3.1416f/180.0f * RandomVariable(1.0f)));
		NewtonMeshClip (bottomMesh, meshClipper, &clipMatrix1[0][0], &meshPartA, &meshPartB);
		if (meshPartA && meshPartB) {
			// creat another split (you can make as many depend of the FPS)
			CreateDebriPiece (body, meshPartA, volume);
			CreateDebriPiece (body, meshPartB, volume);

			NewtonMeshDestroy(meshPartA);
			NewtonMeshDestroy(meshPartB);
		} else {
			CreateDebriPiece (body, bottomMesh, volume);
		}
		NewtonMeshDestroy(bottomMesh);


		dMatrix clipMatrix2 (dgGrammSchmidt(dir1) * 
							 dYawMatrix(30.0f * 3.1416f/180.0f * RandomVariable(1.0f)) * 
			                 dRollMatrix(30.0f * 3.1416f/180.0f * RandomVariable(1.0f)));
		NewtonMeshClip (topMesh, meshClipper, &clipMatrix2[0][0], &meshPartA, &meshPartB);
		if (meshPartA && meshPartB) {
			// creat another split (you can make as many depend of the FPS)
			CreateDebriPiece (body, meshPartA, volume);
			CreateDebriPiece (body, meshPartB, volume);

			NewtonMeshDestroy(meshPartA);
			NewtonMeshDestroy(meshPartB);
		} else {
			CreateDebriPiece (body, topMesh, volume);
		}
		NewtonMeshDestroy(topMesh);


		// remove the old visual from graphics world
		SceneManager* system = (SceneManager*) NewtonWorldGetUserData(world);
		delete srcPrimitive;
		system->Remove(srcPrimitive);

		// finally destroy this body;
		NewtonDestroyBody(world, body);
	}
}
	VoronoidEffect(NewtonWorld* const world, NewtonMesh* const mesh, int interiorMaterial)
		:FractureEffect(world)
	{
		// first we populate the bounding Box area with few random point to get some interior subdivisions.
		// the subdivision are local to the point placement, by placing these points visual ally with a 3d tool
		// and have precise control of how the debris are created.
		// the number of pieces is equal to the number of point inside the Mesh plus the number of point on the mesh 
		dVector size(0.0f);
		dMatrix matrix(dGetIdentityMatrix());
		NewtonMeshCalculateOOBB(mesh, &matrix[0][0], &size.m_x, &size.m_y, &size.m_z);

		dVector points[NUMBER_OF_INTERNAL_PARTS + 8];

		int count = 0;
		// pepper the inside of the BBox box of the mesh with random points
		while (count < NUMBER_OF_INTERNAL_PARTS) {
			dFloat x = dGaussianRandom (size.m_x);
			dFloat y = dGaussianRandom (size.m_y);
			dFloat z = dGaussianRandom (size.m_z);
			if ((x <= size.m_x) && (x >= -size.m_x) && (y <= size.m_y) && (y >= -size.m_y) && (z <= size.m_z) && (z >= -size.m_z)) {
				points[count] = dVector(x, y, z);
				count++;
			}
		}

		// add the bounding box as a safeguard area
		points[count + 0] = dVector(size.m_x, size.m_y, size.m_z, 0.0f);
		points[count + 1] = dVector(size.m_x, size.m_y, -size.m_z, 0.0f);
		points[count + 2] = dVector(size.m_x, -size.m_y, size.m_z, 0.0f);
		points[count + 3] = dVector(size.m_x, -size.m_y, -size.m_z, 0.0f);
		points[count + 4] = dVector(-size.m_x, size.m_y, size.m_z, 0.0f);
		points[count + 5] = dVector(-size.m_x, size.m_y, -size.m_z, 0.0f);
		points[count + 6] = dVector(-size.m_x, -size.m_y, size.m_z, 0.0f);
		points[count + 7] = dVector(-size.m_x, -size.m_y, -size.m_z, 0.0f);
		count += 8;


		// create a texture matrix, for applying the material's UV to all internal faces
		dMatrix textureMatrix(dGetIdentityMatrix());
		textureMatrix[0][0] = 1.0f / size.m_x;
		textureMatrix[1][1] = 1.0f / size.m_y;

		// Get the volume of the original mesh
		NewtonCollision* const collision1 = NewtonCreateConvexHullFromMesh(m_world, mesh, 0.0f, 0);
		dFloat volume = NewtonConvexCollisionCalculateVolume(collision1);
		NewtonDestroyCollision(collision1);

		// now we call create we decompose the mesh into several convex pieces 
		NewtonMesh* const debriMeshPieces = NewtonMeshCreateVoronoiConvexDecomposition(m_world, count, &points[0].m_x, sizeof (dVector), interiorMaterial, &textureMatrix[0][0]);
		dAssert(debriMeshPieces);

		// now we iterate over each pieces and for each one we create a visual entity and a rigid body
		NewtonMesh* nextDebri;
		for (NewtonMesh* debri = NewtonMeshCreateFirstLayer(debriMeshPieces); debri; debri = nextDebri) {
			// get next segment piece
			nextDebri = NewtonMeshCreateNextLayer(debriMeshPieces, debri);

			//clip the voronoi convexes against the mesh 
			NewtonMesh* const fracturePiece = NewtonMeshConvexMeshIntersection(mesh, debri);
			if (fracturePiece) {
				// make a convex hull collision shape
				NewtonCollision* const collision = NewtonCreateConvexHullFromMesh(m_world, fracturePiece, 0.0f, 0);
				if (collision) {
					// we have a piece which has a convex collision  representation, add that to the list
					FractureAtom& atom = Append()->GetInfo();
					atom.m_mesh = new DemoMesh(fracturePiece);
					atom.m_collision = collision;
					NewtonConvexCollisionCalculateInertialMatrix(atom.m_collision, &atom.m_momentOfInirtia[0], &atom.m_centerOfMass[0]);
					dFloat debriVolume = NewtonConvexCollisionCalculateVolume(atom.m_collision);
					atom.m_massFraction = debriVolume / volume;
				}
				NewtonMeshDestroy(fracturePiece);
			}

			NewtonMeshDestroy(debri);
		}

		NewtonMeshDestroy(debriMeshPieces);
	}
Example #19
0
	void BuildClothPatch (DemoEntityManager* const scene, int size_x, int size_z)
	{
		NewtonWorld* const world = scene->GetNewton();
		
		NewtonMesh* const clothPatch = CreateQuadClothPatch(scene, size_x, size_z);

		// create the array of points;
		int vertexCount = NewtonMeshGetVertexCount(clothPatch);
		int stride = NewtonMeshGetVertexStrideInByte (clothPatch) / sizeof (dFloat64); 
		const dFloat64* const meshPoints = NewtonMeshGetVertexArray (clothPatch); 

		dVector* const points = new dVector[vertexCount];
		for (int i =0; i < vertexCount; i ++ ) {
			points[i].m_x = dFloat (meshPoints[i * stride + 0]);
			points[i].m_y = dFloat (meshPoints[i * stride + 1]);
			points[i].m_z = dFloat (meshPoints[i * stride + 2]);
			points[i].m_w = 0.0f;
		}

		dFloat mass = 8.0f;
		// set the particle masses 
		dFloat unitMass = mass / vertexCount;
		dFloat* const clothMass = new dFloat[vertexCount];
		for (int i =0; i < vertexCount; i ++ ) {			
			clothMass[i] = unitMass;
		}

		int linksCount = 0;
		const int maxLinkCount = size_x * size_z * 16;

		// create the structual constation array;
		dFloat structuralSpring = dAbs(mass * DEMO_GRAVITY) / 0.01f;
		dFloat structuralDamper = 30.0f;

		int* const links = new int[2 * maxLinkCount];
		dFloat* const spring = new dFloat[maxLinkCount];
		dFloat* const damper = new dFloat[maxLinkCount];
		for (void* edgeNode = NewtonMeshGetFirstEdge (clothPatch); edgeNode; edgeNode = NewtonMeshGetNextEdge (clothPatch, edgeNode)) {
			int v0;
			int v1;
			NewtonMeshGetEdgeIndices (clothPatch, edgeNode, &v0, &v1);
			links[linksCount * 2 + 0] = v0;
			links[linksCount * 2 + 1] = v1;
			spring[linksCount] = structuralSpring;
			damper[linksCount] = structuralDamper;
			linksCount ++;
			dAssert (linksCount <= maxLinkCount);
		}
		

		// add shear constraints
		dFloat shearSpring = structuralSpring;
		dFloat shearDamper = structuralDamper;
		for (void* faceNode = NewtonMeshGetFirstFace (clothPatch); faceNode; faceNode = NewtonMeshGetNextFace (clothPatch, faceNode)) {
			if (!NewtonMeshIsFaceOpen(clothPatch, faceNode)) {
				int face[8];
				int indexCount = NewtonMeshGetFaceIndexCount (clothPatch, faceNode);
				NewtonMeshGetFaceIndices (clothPatch, faceNode, face);
				for (int i = 2; i < indexCount - 1; i ++) {
					links[linksCount * 2 + 0] = face[0];
					links[linksCount * 2 + 1] = face[i];
					spring[linksCount] = shearSpring;
					damper[linksCount] = shearDamper;

					linksCount ++;
					dAssert (linksCount <= maxLinkCount);
				}
				for (int i = 3; i < indexCount; i ++) {
					links[linksCount * 2 + 0] = face[1];
					links[linksCount * 2 + 1] = face[i];
					spring[linksCount] = shearSpring;
					damper[linksCount] = shearDamper;
					linksCount ++;
					dAssert (linksCount <= maxLinkCount);
				}
			}
		}

//linksCount = 0;
		NewtonCollision* const deformableCollision = NewtonCreateMassSpringDamperSystem(world, 0, 
													 &points[0].m_x, vertexCount, sizeof (dVector), clothMass,
													 links, linksCount, spring, damper);
		
		m_body = CreateRigidBody(scene, mass, deformableCollision);

		DemoMesh* const mesh = new ClothPatchMesh (scene, clothPatch, m_body);
		SetMesh(mesh, dGetIdentityMatrix());

		// do not forget to destroy this objects, else you get bad memory leaks.
		mesh->Release();
		NewtonDestroyCollision(deformableCollision);
		NewtonMeshDestroy(clothPatch);
		delete[] links;
		delete[] damper;
		delete[] spring;
		delete[] clothMass;
		delete[] points;
	}
Example #20
0
 mesh::~mesh()
 {
     if (_mesh)
         NewtonMeshDestroy(_mesh);
     _mesh = NULL;
 }
void ConvexApproximationObject::BuildMesh()
{

	// since max does no provide the iNode that will own this mesh I have no choice bu to apply the root matrix to all vertex
	ConvexApproximationClassDesc* const desc = (ConvexApproximationClassDesc*) ConvexApproximationClassDesc::GetDescriptor();
	INode* const sourceNode = desc->m_sourceNode;
	//dMatrix rootMatrix1 (GetMatrixFromMaxMatrix (sourceNode->GetNodeTM (0)));
	dMatrix rootMatrix (GetMatrixFromMaxMatrix (sourceNode->GetObjectTM(0)));

	dVector scale;
	dMatrix stretchAxis;
	dMatrix orthogonalRootTransform;
	rootMatrix.PolarDecomposition (orthogonalRootTransform, scale, stretchAxis);
	orthogonalRootTransform = orthogonalRootTransform.Inverse();

	// create a Newton world, as a manager of everything Newton related stuff
	NewtonWorld* const world = NewtonCreate ();

	// create an empty mesh and load the max mesh to it
	NewtonMesh* const sourceMesh = NewtonMeshCreate (world);

	// load all faces
	NewtonMeshBeginFace(sourceMesh);
	LoadGeometries (sourceMesh, orthogonalRootTransform);
	NewtonMeshEndFace(sourceMesh);


	// make a convex approximation form this newton mesh effect
	desc->m_progress = -1;
	Interface* const inteface = desc->m_currentInterface;
	
	inteface->ProgressStart("Creation Convex approx ...", TRUE, ConvexApproximationClassDesc::ReportMaxProgress, NULL);
	NewtonMesh* approximationMesh = NewtonMeshApproximateConvexDecomposition (sourceMesh, m_currentConcavity, 0.2f, m_currentMaxCount, 1000, ConvexApproximationClassDesc::ReportProgress);
	inteface->ProgressEnd();

	NewtonMeshDestroy (sourceMesh);



	// now convert the new mesh to a max poly Object
	MNMesh& maxMesh = GetMesh();
	maxMesh.ClearAndFree();

	int faceCount = 0;
	int vertexCount = NewtonMeshGetVertexCount(approximationMesh);
	for (void* face = NewtonMeshGetFirstFace(approximationMesh); face; face = NewtonMeshGetNextFace(approximationMesh, face)) {
		if (!NewtonMeshIsFaceOpen(approximationMesh, face)) {
			faceCount ++;
		}
	}

	//maxMesh.Clear();
	maxMesh.setNumVerts(vertexCount);
	maxMesh.setNumFaces(faceCount);

	// add all vertex
	int vertexStride = NewtonMeshGetVertexStrideInByte(approximationMesh) / sizeof (dFloat64);
	dFloat64* const vertex = NewtonMeshGetVertexArray (approximationMesh); 
	for (int j = 0; j < vertexCount; j ++) {
		dVector p (orthogonalRootTransform.TransformVector(dVector (float (vertex[vertexStride * j + 0]), float (vertex[vertexStride * j + 1]), float (vertex[vertexStride * j + 2]), float(1.0f))));
		maxMesh.P(j) = Point3 (p.m_x, p.m_y, p.m_z);
	}

	// count the number of face and make a face map
	int faceIndex = 0;
	for (void* face = NewtonMeshGetFirstFace(approximationMesh); face; face = NewtonMeshGetNextFace(approximationMesh, face)) {
		if (!NewtonMeshIsFaceOpen(approximationMesh, face)) {
			int faceIndices[256];
			int indexCount = NewtonMeshGetFaceIndexCount (approximationMesh, face);

			NewtonMeshGetFaceIndices (approximationMesh, face, faceIndices);
			MNFace* const face = maxMesh.F(faceIndex);
			face->MakePoly(indexCount, faceIndices, NULL, NULL);
			face->material = 0;
			faceIndex ++;
		}
	}

	maxMesh.InvalidateGeomCache();
	maxMesh.InvalidateTopoCache();
	maxMesh.FillInMesh();
	maxMesh.AutoSmooth(45.0f * 3.1416f / 160.0f, false, false);


	NewtonMeshDestroy (approximationMesh);
	NewtonDestroy (world);
}
static void AddStructuredFractured (DemoEntityManager* const scene, const dVector& origin, int materialID, const char* const assetName)
{
	// create the shape and visual mesh as a common data to be re used
	NewtonWorld* const world = scene->GetNewton();


#if 0
	// load the mesh asset
	DemoEntity entity(GetIdentityMatrix(), NULL);	
	entity.LoadNGD_mesh (assetName, world);
	DemoMesh____* const mesh = entity.GetMesh();
	dAssert (mesh);

	// convert the mesh to a newtonMesh
	NewtonMesh* const solidMesh = mesh->CreateNewtonMesh (world, entity.GetMeshMatrix() * entity.GetCurrentMatrix());
#else
	int externalMaterial = LoadTexture("wood_0.tga");
	NewtonCollision* const collision = CreateConvexCollision (world, dGetIdentityMatrix(), dVector (3.0f, 3.0f, 3.0f, 0.0), _BOX_PRIMITIVE, 0);
	NewtonMesh* const solidMesh = NewtonMeshCreateFromCollision(collision);
	NewtonDestroyCollision(collision);
	//NewtonMeshTriangulate(solidMesh);
	NewtonMeshApplyBoxMapping (solidMesh, externalMaterial, externalMaterial, externalMaterial);
#endif


	// create a random point cloud
	dVector points[MAX_POINT_CLOUD_SIZE];
	int pointCount = MakeRandomPoisonPointCloud (solidMesh, points);
//	int pointCount = MakeRandomGuassianPointCloud (solidMesh, points, MAX_POINT_CLOUD_SIZE);

	// create and interiors material for texturing the fractured pieces
	//int internalMaterial = LoadTexture("KAMEN-stup.tga");
	int internalMaterial = LoadTexture("concreteBrick.tga");

	// crate a texture matrix for uv mapping of fractured pieces
	dMatrix textureMatrix (dGetIdentityMatrix());
	textureMatrix[0][0] = 1.0f / 2.0f;
	textureMatrix[1][1] = 1.0f / 2.0f;

	/// create the fractured collision and mesh
	int debreePhysMaterial = NewtonMaterialGetDefaultGroupID(world);
	NewtonCollision* structuredFracturedCollision = NewtonCreateFracturedCompoundCollision (world, solidMesh, 0, debreePhysMaterial, pointCount, &points[0][0], sizeof (dVector), internalMaterial, &textureMatrix[0][0],
																							OnReconstructMainMeshCallBack, OnEmitFracturedCompound, OnEmitFracturedChunk);

// uncomment this to test serialization
#if 0
	FILE* file = fopen ("serialize.bin", "wb");
	NewtonCollisionSerialize (world, structuredFracturedCollision, DemoEntityManager::SerializeFile, file);
	NewtonDestroyCollision (structuredFracturedCollision);
	fclose (file);

	file = fopen ("serialize.bin", "rb");
	structuredFracturedCollision = NewtonCreateCollisionFromSerialization (world, DemoEntityManager::DeserializeFile, file);
	NewtonFracturedCompoundSetCallbacks (structuredFracturedCollision, OnReconstructMainMeshCallBack, OnEmitFracturedCompound, OnEmitFracturedChunk);
	fclose (file);
#endif	

#if 0
	// test the interface
	dTree<void*, void*> detachableNodes;
	NewtonCompoundCollisionBeginAddRemove(structuredFracturedCollision);	

	// remove all chunk that can be detached for the first layer
	for (void* node = NewtonCompoundCollisionGetFirstNode(structuredFracturedCollision); node; node = NewtonCompoundCollisionGetNextNode(structuredFracturedCollision, node)) { 
		if (NewtonFracturedCompoundIsNodeFreeToDetach (structuredFracturedCollision, node)) {
			detachableNodes.Insert(node, node);
		}

		// remove any node that can be deched fro the secund layer, this codul; be reusive
		void* neighbors[32];
		int count = NewtonFracturedCompoundNeighborNodeList (structuredFracturedCollision, node, neighbors, sizeof (neighbors) / sizeof (neighbors[0]));
		for (int i = 0; i < count; i ++ ) {
			if (NewtonFracturedCompoundIsNodeFreeToDetach (structuredFracturedCollision, neighbors[i])) {
				detachableNodes.Insert(node, node);
			}
		}
	}

	// now delete the actual nodes
	dTree<void*, void*>::Iterator iter (detachableNodes) ;
	for (iter.Begin(); iter; iter ++) { 
		void* const node = iter.GetNode()->GetInfo(); 
		NewtonCompoundCollisionRemoveSubCollision (structuredFracturedCollision, node);
	}
	NewtonCompoundCollisionEndAddRemove(structuredFracturedCollision);	
#endif
	
#if 1
	dVector plane (0.0f, 1.0f, 0.0f, 0.0f);
	NewtonCollision* const crack = NewtonFracturedCompoundPlaneClip (structuredFracturedCollision, &plane[0]);
	if (crack) {
		NewtonDestroyCollision (structuredFracturedCollision);
	}
#endif




    dVector com(0.0f);
    dVector inertia(0.0f);
    NewtonConvexCollisionCalculateInertialMatrix (structuredFracturedCollision, &inertia[0], &com[0]);	

    //dFloat mass = 10.0f;
    //int materialId = 0;
    //create the rigid body
	dMatrix matrix (dGetIdentityMatrix());
	matrix.m_posit = origin;
	matrix.m_posit.m_y = 20.0;
	matrix.m_posit.m_w = 1.0f;
    NewtonBody* const rigidBody = NewtonCreateDynamicBody (world, structuredFracturedCollision, &matrix[0][0]);

	// set the mass and center of mass
	dFloat density = 1.0f;
	dFloat mass = density * NewtonConvexCollisionCalculateVolume (structuredFracturedCollision);
	NewtonBodySetMassProperties (rigidBody, mass, structuredFracturedCollision);


	// set the transform call back function
	NewtonBodySetTransformCallback (rigidBody, DemoEntity::TransformCallback);

	// set the force and torque call back function
	NewtonBodySetForceAndTorqueCallback (rigidBody, PhysicsApplyGravityForce);

	// create the entity and visual mesh and attach to the body as user data
	CreateVisualEntity (scene, rigidBody);

    // assign the wood id
//    NewtonBodySetMaterialGroupID (rigidBody, materialId);

    // set a destructor for this rigid body
//    NewtonBodySetDestructorCallback (rigidBody, PhysicsBodyDestructor);

	// release the interior texture
//	ReleaseTexture (internalMaterial);

	// delete the solid mesh since it no longed needed
	NewtonMeshDestroy (solidMesh);

	// destroy the fracture collision
	NewtonDestroyCollision (structuredFracturedCollision);
}