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 = dFloat (pow(r, 1.0f/biasExp)); for (int i = 0; i < count; i++) { dVector& p = points[i]; bool test; do { p = dVector (2.0f * dGaussianRandom (r), 2.0f * dGaussianRandom (r), 2.0f * dGaussianRandom (r), 0.0f); dFloat len = dSqrt (p.DotProduct3(p)); dFloat scale = dFloat (pow(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; }
void Init (dFloat location_x, dFloat location_z, PrimitiveType shapeType, int materialID, PrimitiveType castingShapeType) { m_pith = dGaussianRandom (3.1416f * 2.0f); m_yaw = dGaussianRandom (3.1416f * 2.0f); m_roll = dGaussianRandom (3.1416f * 2.0f); m_step = 15.0f * (dAbs (dGaussianRandom (0.25f)) + 0.0001f) * 3.1416f/180.0f; CreatCasterBody(location_x, location_z, shapeType, materialID); NewtonWorld* const world = ((dCustomControllerManager<dClosestDistanceRecord>*)GetManager())->GetWorld(); DemoEntityManager* const scene = (DemoEntityManager*)NewtonWorldGetUserData(world); dMatrix matrix; NewtonBodyGetMatrix(m_body, &matrix[0][0]); matrix.m_posit.m_y += 10.0f; m_castingVisualEntity = new ClosestDistanceEntity (scene, matrix, materialID, castingShapeType); }
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 += dGaussianRandom (POISON_VARIANCE); y += dGaussianRandom (POISON_VARIANCE); z += dGaussianRandom (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; }
NewtonCollision* CreateConvexCollision (NewtonWorld* const world, const dMatrix& srcMatrix, const dVector& originalSize, PrimitiveType type, int materialID__) { dVector size (originalSize); NewtonCollision* collision = NULL; switch (type) { case _NULL_PRIMITIVE: { collision = NewtonCreateNull (world); break; } case _SPHERE_PRIMITIVE: { // create the collision collision = NewtonCreateSphere (world, size.m_x * 0.5f, 0, NULL); break; } case _BOX_PRIMITIVE: { // create the collision collision = NewtonCreateBox (world, size.m_x, size.m_y, size.m_z, 0, NULL); break; } case _CONE_PRIMITIVE: { dFloat r = size.m_x * 0.5f; dFloat h = size.m_y; // create the collision collision = NewtonCreateCone (world, r, h, 0, NULL); break; } case _CYLINDER_PRIMITIVE: { // create the collision collision = NewtonCreateCylinder (world, size.m_x * 0.5f, size.m_z * 0.5f, size.m_y, 0, NULL); break; } case _CAPSULE_PRIMITIVE: { // create the collision collision = NewtonCreateCapsule (world, size.m_x * 0.5f, size.m_z * 0.5f, size.m_y, 0, NULL); break; } case _CHAMFER_CYLINDER_PRIMITIVE: { // create the collision collision = NewtonCreateChamferCylinder (world, size.m_x * 0.5f, size.m_y, 0, NULL); break; } case _RANDOM_CONVEX_HULL_PRIMITIVE: { // Create a clouds of random point around the origin #define SAMPLE_COUNT 200 dVector cloud [SAMPLE_COUNT]; // make sure that at least the top and bottom are present cloud [0] = dVector ( size.m_x * 0.5f, 0.0f, 0.0f, 0.0f); cloud [1] = dVector (-size.m_x * 0.5f, 0.0f, 0.0f, 0.0f); cloud [2] = dVector ( 0.0f, size.m_y * 0.5f, 0.0f, 0.0f); cloud [3] = dVector ( 0.0f, -size.m_y * 0.5f, 0.0f, 0.0f); cloud [4] = dVector (0.0f, 0.0f, size.m_z * 0.5f, 0.0f); cloud [5] = dVector (0.0f, 0.0f, -size.m_z * 0.5f, 0.0f); int count = 6; // populate the cloud with pseudo Gaussian random points for (int i = 6; i < SAMPLE_COUNT; i ++) { cloud [i].m_x = dGaussianRandom (size.m_x); cloud [i].m_y = dGaussianRandom (size.m_y); cloud [i].m_z = dGaussianRandom (size.m_z); count ++; } collision = NewtonCreateConvexHull (world, count, &cloud[0].m_x, sizeof (dVector), 0.01f, 0, NULL); break; } case _REGULAR_CONVEX_HULL_PRIMITIVE: { // Create a clouds of random point around the origin #define STEPS_HULL 6 //#define STEPS_HULL 3 //dVector cloud [STEPS_HULL * 4 + 256]; dFloat cloud [STEPS_HULL * 4 + 256][3]; int count = 0; dFloat radius = size.m_y; dFloat height = size.m_x * 0.999f; dFloat x = - height * 0.5f; dMatrix rotation (dPitchMatrix(2.0f * dPi / STEPS_HULL)); for (int i = 0; i < 4; i ++) { dFloat pad = ((i == 1) || (i == 2)) * 0.25f * radius; dVector p (x, 0.0f, radius + pad); x += 0.3333f * height; dMatrix acc (dGetIdentityMatrix()); for (int j = 0; j < STEPS_HULL; j ++) { dVector tmp (acc.RotateVector(p)); cloud[count][0] = tmp.m_x; cloud[count][1] = tmp.m_y; cloud[count][2] = tmp.m_z; acc = acc * rotation; count ++; } } collision = NewtonCreateConvexHull (world, count, &cloud[0][0], 3 * sizeof (dFloat), 0.02f, 0, NULL); break; } case _COMPOUND_CONVEX_CRUZ_PRIMITIVE: { //dMatrix matrix (GetIdentityMatrix()); dMatrix matrix (dPitchMatrix(15.0f * dDegreeToRad) * dYawMatrix(15.0f * dDegreeToRad) * dRollMatrix(15.0f * dDegreeToRad)); matrix.m_posit = dVector (size.m_x * 0.5f, 0.0f, 0.0f, 1.0f); NewtonCollision* const collisionA = NewtonCreateBox (world, size.m_x, size.m_x * 0.25f, size.m_x * 0.25f, 0, &matrix[0][0]); matrix.m_posit = dVector (0.0f, size.m_x * 0.5f, 0.0f, 1.0f); NewtonCollision* const collisionB = NewtonCreateBox (world, size.m_x * 0.25f, size.m_x, size.m_x * 0.25f, 0, &matrix[0][0]); matrix.m_posit = dVector (0.0f, 0.0f, size.m_x * 0.5f, 1.0f); NewtonCollision* const collisionC = NewtonCreateBox (world, size.m_x * 0.25f, size.m_x * 0.25f, size.m_x, 0, &matrix[0][0]); collision = NewtonCreateCompoundCollision (world, 0); NewtonCompoundCollisionBeginAddRemove(collision); NewtonCompoundCollisionAddSubCollision (collision, collisionA); NewtonCompoundCollisionAddSubCollision (collision, collisionB); NewtonCompoundCollisionAddSubCollision (collision, collisionC); NewtonCompoundCollisionEndAddRemove(collision); NewtonDestroyCollision(collisionA); NewtonDestroyCollision(collisionB); NewtonDestroyCollision(collisionC); break; } default: dAssert (0); } dMatrix matrix (srcMatrix); matrix.m_front = matrix.m_front.Scale (1.0f / dSqrt (matrix.m_front.DotProduct3(matrix.m_front))); matrix.m_right = matrix.m_front.CrossProduct(matrix.m_up); matrix.m_right = matrix.m_right.Scale (1.0f / dSqrt (matrix.m_right.DotProduct3(matrix.m_right))); matrix.m_up = matrix.m_right.CrossProduct(matrix.m_front); NewtonCollisionSetMatrix(collision, &matrix[0][0]); return collision; }
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); }