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); }
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; }
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 CreateDebriPiece (const NewtonBody* sourceBody, NewtonMesh* mesh, dFloat volume) { dFloat Ixx; dFloat Iyy; dFloat Izz; dFloat mass; dFloat shapeVolume; NewtonWorld* world; NewtonBody* rigidBody; NewtonCollision* collision; OGLMesh* meshInstance; SceneManager* system; RenderPrimitive* primitive; dVector inertia; dVector origin; dVector veloc; dVector omega; dMatrix matrix; world = NewtonBodyGetWorld (sourceBody); NewtonBodyGetMatrix (sourceBody, &matrix[0][0]); NewtonBodyGetMassMatrix (sourceBody, &mass, &Ixx, &Iyy, &Izz); // make a visual object meshInstance = new OGLMesh(); meshInstance->BuildFromMesh (mesh); // create a visual geometry primitive = new RenderPrimitive (matrix, meshInstance); meshInstance->Release(); // save the graphics system system = (SceneManager*) NewtonWorldGetUserData(world); system->AddModel (primitive); collision = NewtonCreateConvexHullFromMesh (world, mesh, 0.1f, DEBRI_ID); // calculate the moment of inertia and the relative center of mass of the solid shapeVolume = NewtonConvexCollisionCalculateVolume (collision); NewtonConvexCollisionCalculateInertialMatrix (collision, &inertia[0], &origin[0]); mass = mass * shapeVolume / volume; Ixx = mass * inertia[0]; Iyy = mass * inertia[1]; Izz = mass * inertia[2]; //create the rigid body rigidBody = NewtonCreateBody (world, collision); // set the correct center of gravity for this body NewtonBodySetCentreOfMass (rigidBody, &origin[0]); // set the mass matrix NewtonBodySetMassMatrix (rigidBody, mass, Ixx, Iyy, Izz); // save the pointer to the graphic object with the body. NewtonBodySetUserData (rigidBody, primitive); // assign the wood id // NewtonBodySetMaterialGroupID (rigidBody, NewtonBodyGetMaterialGroupID(source)); // set continue collision mode NewtonBodySetContinuousCollisionMode (rigidBody, 1); // set a destructor for this rigid body NewtonBodySetDestructorCallback (rigidBody, PhysicsBodyDestructor); // set the transform call back function NewtonBodySetTransformCallback (rigidBody, PhysicsSetTransform); // set the force and torque call back function NewtonBodySetForceAndTorqueCallback (rigidBody, PhysicsApplyGravityForce); // set the matrix for both the rigid body and the graphic body NewtonBodySetMatrix (rigidBody, &matrix[0][0]); PhysicsSetTransform (rigidBody, &matrix[0][0], 0); NewtonBodyGetVelocity(sourceBody, &veloc[0]); NewtonBodyGetOmega(sourceBody, &omega[0]); veloc += omega * matrix.RotateVector(origin); // for now so that I can see the body veloc = dVector (0, 0, 0, 0); // omega = dVector (0, 0, 0, 0); NewtonBodySetVelocity(rigidBody, &veloc[0]); NewtonBodySetOmega(rigidBody, &omega[0]); NewtonReleaseCollision(world, collision); }
// create a mesh using the dNewtonMesh wrapper static NewtonBody* CreateSimpledBox_dNetwonMesh(DemoEntityManager* const scene, const dVector& origin, const dVector& scale, dFloat mass) { dVector array[8]; dVector scale1(scale); for (int i = 0; i < 8; i++) { dVector p(&BoxPoints[i * 4]); array[i] = scale1 * p; } dNewtonMesh buildMesh(scene->GetNewton()); // start build a mesh buildMesh.BeginBuild(); // add faces one at a time int index = 0; const int faceCount = sizeof (faceIndexList)/sizeof (faceIndexList[0]); for (int i = 0; i < faceCount; i ++) { const int indexCount = faceIndexList[i]; const int faceMaterail = faceMateriaIndexList[i]; buildMesh.BeginPolygon(); for (int j = 0; j < indexCount; j ++) { // add a mesh point int k = BoxIndices[index + j]; buildMesh.AddPoint(array[k].m_x, array[k].m_y, array[k].m_z); // add vertex normal int n = faceNormalIndex[index + j]; buildMesh.AddNormal (dFloat32 (normal[n * 3 + 0]), dFloat32 (normal[n * 3 + 1]), dFloat32 (normal[n * 3 + 2])); // add face material index buildMesh.AddMaterial(faceMaterail); // continue adding more vertex attributes of you want, uv, binormal, weights, etc } buildMesh.EndPolygon(); index += indexCount; } buildMesh.EndBuild(); // get the newtonMesh from the dNewtonMesh class and use it to build a render mesh, collision or anything NewtonMesh* const newtonMesh = buildMesh.GetMesh(); // test collision tree //NewtonCollision* const collisionTree = NewtonCreateTreeCollisionFromMesh (scene->GetNewton(), newtonMesh, 0); //NewtonDestroyCollision(collisionTree); // 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); return 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); }