static int MakeRandomGuassianPointCloud (NewtonMesh* const mesh, dVector* const points, int count) { dVector size(0.0f); dMatrix matrix(dGetIdentityMatrix()); NewtonMeshCalculateOOBB(mesh, &matrix[0][0], &size.m_x, &size.m_y, &size.m_z); dVector minBox (matrix.m_posit - matrix[0].Scale (size.m_x) - matrix[1].Scale (size.m_y) - matrix[2].Scale (size.m_z)); dVector maxBox (matrix.m_posit + matrix[0].Scale (size.m_x) + matrix[1].Scale (size.m_y) + matrix[2].Scale (size.m_z)); size = (maxBox - minBox).Scale (0.5f); dVector origin = (maxBox + minBox).Scale (0.5f); dFloat biasExp = 10.0f; dFloat r = dSqrt (size.DotProduct3(size)); r = powf(r, 1.0f/biasExp); for (int i = 0; i < count; i++) { dVector& p = points[i]; bool test; do { p = dVector (2.0f * RandomVariable(r), 2.0f * RandomVariable(r), 2.0f * RandomVariable(r), 0.0f); dFloat len = dSqrt (p.DotProduct3(p)); dFloat scale = powf(len, biasExp) / len; p = p.Scale (scale) + origin; test = (p.m_x > minBox.m_x) && (p.m_x < maxBox.m_x) && (p.m_y > minBox.m_y) && (p.m_y < maxBox.m_y) && (p.m_z > minBox.m_z) && (p.m_z < maxBox.m_z); } while (!test); } return count; }
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); }
static int MakeRandomPoisonPointCloud(NewtonMesh* const mesh, dVector* const points) { dVector size(0.0f); dMatrix matrix(dGetIdentityMatrix()); NewtonMeshCalculateOOBB(mesh, &matrix[0][0], &size.m_x, &size.m_y, &size.m_z); dVector minBox (matrix.m_posit - matrix[0].Scale (size.m_x) - matrix[1].Scale (size.m_y) - matrix[2].Scale (size.m_z)); dVector maxBox (matrix.m_posit + matrix[0].Scale (size.m_x) + matrix[1].Scale (size.m_y) + matrix[2].Scale (size.m_z)); size = maxBox - minBox; int xCount = int (size.m_x / POINT_DENSITY_PER_METERS) + 1; int yCount = int (size.m_y / POINT_DENSITY_PER_METERS) + 1; int zCount = int (size.m_z / POINT_DENSITY_PER_METERS) + 1; int count = 0; dFloat z0 = minBox.m_z; for (int iz = 0; (iz < zCount) && (count < MAX_POINT_CLOUD_SIZE); iz ++) { dFloat y0 = minBox.m_y; for (int iy = 0; (iy < yCount) && (count < MAX_POINT_CLOUD_SIZE); iy ++) { dFloat x0 = minBox.m_x; for (int ix = 0; (ix < xCount) && (count < MAX_POINT_CLOUD_SIZE); ix ++) { dFloat x = x0; dFloat y = y0; dFloat z = z0; x += RandomVariable(POISON_VARIANCE); y += RandomVariable(POISON_VARIANCE); z += RandomVariable(POISON_VARIANCE); points[count] = dVector (x, y, z); count ++; x0 += POINT_DENSITY_PER_METERS; } y0 += POINT_DENSITY_PER_METERS; } z0 += POINT_DENSITY_PER_METERS; } return count; }
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); }