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); }
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); }
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); }
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; }
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); }
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); }
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); }
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; }
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); }