private static ConvexHullShape CreateTaruShape() { var shape = new ConvexHullShape(); for (int i = 0; i < Taru.Vertices.Length / 3; i++) { Vector3 vertex = new Vector3( Taru.Vertices[i * 3], Taru.Vertices[i * 3 + 1], Taru.Vertices[i * 3 + 2]); shape.AddPoint(vertex); } return(shape); }
private static CollisionShape loadConvexHull(Mesh mesh, Vector3 scale) { TriangleMesh trimesh = new TriangleMesh(); // Shift vertices in so margin is not visible Vector3 shift = Vector3.Normalize(scale) - new Vector3(0.04f); for (int i = 0; i < mesh.submeshes[0].vertex_data.Length; i += 3) { int index0 = (int)mesh.submeshes[0].index_data[i]; int index1 = (int)mesh.submeshes[0].index_data[i + 1]; int index2 = (int)mesh.submeshes[0].index_data[i + 2]; Vector3 vertex0 = new Vector3(mesh.submeshes[0].vertex_data[index0].position.X, mesh.submeshes[0].vertex_data[index0].position.Y, mesh.submeshes[0].vertex_data[index0].position.Z) * (scale); //vertex0 *= shift; Vector3 vertex1 = new Vector3(mesh.submeshes[0].vertex_data[index1].position.X, mesh.submeshes[0].vertex_data[index1].position.Y, mesh.submeshes[0].vertex_data[index1].position.Z) * (scale); //vertex1 *= shift; Vector3 vertex2 = new Vector3(mesh.submeshes[0].vertex_data[index2].position.X, mesh.submeshes[0].vertex_data[index2].position.Y, mesh.submeshes[0].vertex_data[index2].position.Z) * (scale); //vertex2 *= shift; trimesh.AddTriangle(vertex0, vertex1, vertex2); } ConvexShape tmpShape = new ConvexTriangleMeshShape(trimesh); ShapeHull hull = new ShapeHull(tmpShape); float margin = tmpShape.Margin; hull.BuildHull(margin); tmpShape.UserObject = hull; ConvexHullShape convexShape = new ConvexHullShape(); foreach (Vector3 v in hull.Vertices) { convexShape.AddPoint(v); } hull.Dispose(); tmpShape.Dispose(); return(convexShape); }
protected override void OnInitializePhysics() { ManifoldPoint.ContactAdded += MyContactCallback; SetupEmptyDynamicsWorld(); WavefrontObj wo = new WavefrontObj(); int tcount = wo.LoadObj("data/file.obj"); if (tcount > 0) { TriangleMesh trimesh = new TriangleMesh(); trimeshes.Add(trimesh); Vector3 localScaling = new Vector3(6, 6, 6); List <int> indices = wo.Indices; List <Vector3> vertices = wo.Vertices; int i; for (i = 0; i < tcount; i++) { int index0 = indices[i * 3]; int index1 = indices[i * 3 + 1]; int index2 = indices[i * 3 + 2]; Vector3 vertex0 = vertices[index0] * localScaling; Vector3 vertex1 = vertices[index1] * localScaling; Vector3 vertex2 = vertices[index2] * localScaling; trimesh.AddTriangle(vertex0, vertex1, vertex2); } ConvexShape tmpConvexShape = new ConvexTriangleMeshShape(trimesh); //create a hull approximation ShapeHull hull = new ShapeHull(tmpConvexShape); float margin = tmpConvexShape.Margin; hull.BuildHull(margin); tmpConvexShape.UserObject = hull; ConvexHullShape convexShape = new ConvexHullShape(); foreach (Vector3 v in hull.Vertices) { convexShape.AddPoint(v); } if (sEnableSAT) { convexShape.InitializePolyhedralFeatures(); } tmpConvexShape.Dispose(); //hull.Dispose(); CollisionShapes.Add(convexShape); float mass = 1.0f; LocalCreateRigidBody(mass, Matrix.Translation(0, 2, 14), convexShape); const bool useQuantization = true; CollisionShape concaveShape = new BvhTriangleMeshShape(trimesh, useQuantization); LocalCreateRigidBody(0, Matrix.Translation(convexDecompositionObjectOffset), concaveShape); CollisionShapes.Add(concaveShape); // Bullet Convex Decomposition FileStream outputFile = new FileStream("file_convex.obj", FileMode.Create, FileAccess.Write); StreamWriter writer = new StreamWriter(outputFile); DecompDesc desc = new DecompDesc { mVertices = wo.Vertices.ToArray(), mTcount = tcount, mIndices = wo.Indices.ToArray(), mDepth = 5, mCpercent = 5, mPpercent = 15, mMaxVertices = 16, mSkinWidth = 0.0f }; MyConvexDecomposition convexDecomposition = new MyConvexDecomposition(writer, this); desc.mCallback = convexDecomposition; // HACD Hacd myHACD = new Hacd(); myHACD.SetPoints(wo.Vertices); myHACD.SetTriangles(wo.Indices); myHACD.CompacityWeight = 0.1; myHACD.VolumeWeight = 0.0; // HACD parameters // Recommended parameters: 2 100 0 0 0 0 int nClusters = 2; const double concavity = 100; //bool invert = false; const bool addExtraDistPoints = false; const bool addNeighboursDistPoints = false; const bool addFacesPoints = false; myHACD.NClusters = nClusters; // minimum number of clusters myHACD.VerticesPerConvexHull = 100; // max of 100 vertices per convex-hull myHACD.Concavity = concavity; // maximum concavity myHACD.AddExtraDistPoints = addExtraDistPoints; myHACD.AddNeighboursDistPoints = addNeighboursDistPoints; myHACD.AddFacesPoints = addFacesPoints; myHACD.Compute(); nClusters = myHACD.NClusters; myHACD.Save("output.wrl", false); if (true) { CompoundShape compound = new CompoundShape(); CollisionShapes.Add(compound); Matrix trans = Matrix.Identity; for (int c = 0; c < nClusters; c++) { //generate convex result Vector3[] points; int[] triangles; myHACD.GetCH(c, out points, out triangles); ConvexResult r = new ConvexResult(points, triangles); convexDecomposition.ConvexDecompResult(r); } for (i = 0; i < convexDecomposition.convexShapes.Count; i++) { Vector3 centroid = convexDecomposition.convexCentroids[i]; trans = Matrix.Translation(centroid); ConvexHullShape convexShape2 = convexDecomposition.convexShapes[i] as ConvexHullShape; compound.AddChildShape(trans, convexShape2); RigidBody body = LocalCreateRigidBody(1.0f, trans, convexShape2); } #if true mass = 10.0f; trans = Matrix.Translation(-convexDecompositionObjectOffset); RigidBody body2 = LocalCreateRigidBody(mass, trans, compound); body2.CollisionFlags |= CollisionFlags.CustomMaterialCallback; convexDecompositionObjectOffset.Z = 6; trans = Matrix.Translation(-convexDecompositionObjectOffset); body2 = LocalCreateRigidBody(mass, trans, compound); body2.CollisionFlags |= CollisionFlags.CustomMaterialCallback; convexDecompositionObjectOffset.Z = -6; trans = Matrix.Translation(-convexDecompositionObjectOffset); body2 = LocalCreateRigidBody(mass, trans, compound); body2.CollisionFlags |= CollisionFlags.CustomMaterialCallback; #endif } writer.Dispose(); outputFile.Dispose(); } }
protected override void OnInitializePhysics() { // collision configuration contains default setup for memory, collision setup DefaultCollisionConstructionInfo cci = new DefaultCollisionConstructionInfo(); cci.DefaultMaxPersistentManifoldPoolSize = 32768; CollisionConf = new DefaultCollisionConfiguration(cci); Dispatcher = new CollisionDispatcher(CollisionConf); Dispatcher.DispatcherFlags = DispatcherFlags.DisableContactPoolDynamicAllocation; // the maximum size of the collision world. Make sure objects stay within these boundaries // Don't make the world AABB size too large, it will harm simulation quality and performance Vector3 worldAabbMin = new Vector3(-1000, -1000, -1000); Vector3 worldAabbMax = new Vector3(1000, 1000, 1000); HashedOverlappingPairCache pairCache = new HashedOverlappingPairCache(); Broadphase = new AxisSweep3(worldAabbMin, worldAabbMax, 3500, pairCache); //Broadphase = new DbvtBroadphase(); Solver = new SequentialImpulseConstraintSolver(); World = new DiscreteDynamicsWorld(Dispatcher, Broadphase, Solver, CollisionConf); World.Gravity = new Vector3(0, -10, 0); World.SolverInfo.SolverMode |= SolverModes.EnableFrictionDirectionCaching; World.SolverInfo.NumIterations = 5; if (benchmark < 5) { // create the ground CollisionShape groundShape = new BoxShape(250, 50, 250); CollisionShapes.Add(groundShape); CollisionObject ground = base.LocalCreateRigidBody(0, Matrix.Translation(0, -50, 0), groundShape); ground.UserObject = "Ground"; } float cubeSize = 1.0f; float spacing = cubeSize; float mass = 1.0f; int size = 8; Vector3 pos = new Vector3(0.0f, cubeSize * 2, 0.0f); float offset = -size * (cubeSize * 2.0f + spacing) * 0.5f; switch (benchmark) { case 1: // 3000 BoxShape blockShape = new BoxShape(cubeSize - collisionRadius); mass = 2.0f; for (int k = 0; k < 20; k++) { for (int j = 0; j < size; j++) { pos[2] = offset + (float)j * (cubeSize * 2.0f + spacing); for (int i = 0; i < size; i++) { pos[0] = offset + (float)i * (cubeSize * 2.0f + spacing); RigidBody cmbody = LocalCreateRigidBody(mass, Matrix.Translation(pos), blockShape); } } offset -= 0.05f * spacing * (size - 1); // spacing *= 1.01f; pos[1] += (cubeSize * 2.0f + spacing); } break; case 2: CreatePyramid(new Vector3(-20, 0, 0), 12, new Vector3(cubeSize)); CreateWall(new Vector3(-2.0f, 0.0f, 0.0f), 12, new Vector3(cubeSize)); CreateWall(new Vector3(4.0f, 0.0f, 0.0f), 12, new Vector3(cubeSize)); CreateWall(new Vector3(10.0f, 0.0f, 0.0f), 12, new Vector3(cubeSize)); CreateTowerCircle(new Vector3(25.0f, 0.0f, 0.0f), 8, 24, new Vector3(cubeSize)); break; case 3: // TODO: Ragdolls break; case 4: cubeSize = 1.5f; ConvexHullShape convexHullShape = new ConvexHullShape(); float scaling = 1; convexHullShape.LocalScaling = new Vector3(scaling); for (int i = 0; i < Taru.Vtx.Length / 3; i++) { Vector3 vtx = new Vector3(Taru.Vtx[i * 3], Taru.Vtx[i * 3 + 1], Taru.Vtx[i * 3 + 2]); convexHullShape.AddPoint(vtx * (1.0f / scaling)); } //this will enable polyhedral contact clipping, better quality, slightly slower convexHullShape.InitializePolyhedralFeatures(); for (int k = 0; k < 15; k++) { for (int j = 0; j < size; j++) { pos[2] = offset + (float)j * (cubeSize * 2.0f + spacing); for (int i = 0; i < size; i++) { pos[0] = offset + (float)i * (cubeSize * 2.0f + spacing); LocalCreateRigidBody(mass, Matrix.Translation(pos), convexHullShape); } } offset -= 0.05f * spacing * (size - 1); spacing *= 1.01f; pos[1] += (cubeSize * 2.0f + spacing); } break; case 5: Vector3 boxSize = new Vector3(1.5f); float boxMass = 1.0f; float sphereRadius = 1.5f; float sphereMass = 1.0f; float capsuleHalf = 2.0f; float capsuleRadius = 1.0f; float capsuleMass = 1.0f; size = 10; int height = 10; cubeSize = boxSize[0]; spacing = 2.0f; pos = new Vector3(0.0f, 20.0f, 0.0f); offset = -size * (cubeSize * 2.0f + spacing) * 0.5f; int numBodies = 0; Random random = new Random(); for (int k = 0; k < height; k++) { for (int j = 0; j < size; j++) { pos[2] = offset + (float)j * (cubeSize * 2.0f + spacing); for (int i = 0; i < size; i++) { pos[0] = offset + (float)i * (cubeSize * 2.0f + spacing); Vector3 bpos = new Vector3(0, 25, 0) + new Vector3(5.0f * pos.X, pos.Y, 5.0f * pos.Z); int idx = random.Next(10); Matrix trans = Matrix.Translation(bpos); switch (idx) { case 0: case 1: case 2: { float r = 0.5f * (idx + 1); BoxShape boxShape = new BoxShape(boxSize * r); LocalCreateRigidBody(boxMass * r, trans, boxShape); } break; case 3: case 4: case 5: { float r = 0.5f * (idx - 3 + 1); SphereShape sphereShape = new SphereShape(sphereRadius * r); LocalCreateRigidBody(sphereMass * r, trans, sphereShape); } break; case 6: case 7: case 8: { float r = 0.5f * (idx - 6 + 1); CapsuleShape capsuleShape = new CapsuleShape(capsuleRadius * r, capsuleHalf * r); LocalCreateRigidBody(capsuleMass * r, trans, capsuleShape); } break; } numBodies++; } } offset -= 0.05f * spacing * (size - 1); spacing *= 1.1f; pos[1] += (cubeSize * 2.0f + spacing); } //CreateLargeMeshBody(); break; case 6: boxSize = new Vector3(1.5f, 1.5f, 1.5f); convexHullShape = new ConvexHullShape(); for (int i = 0; i < Taru.Vtx.Length / 3; i++) { Vector3 vtx = new Vector3(Taru.Vtx[i * 3], Taru.Vtx[i * 3 + 1], Taru.Vtx[i * 3 + 2]); convexHullShape.AddPoint(vtx); } size = 10; height = 10; cubeSize = boxSize[0]; spacing = 2.0f; pos = new Vector3(0.0f, 20.0f, 0.0f); offset = -size * (cubeSize * 2.0f + spacing) * 0.5f; for (int k = 0; k < height; k++) { for (int j = 0; j < size; j++) { pos[2] = offset + (float)j * (cubeSize * 2.0f + spacing); for (int i = 0; i < size; i++) { pos[0] = offset + (float)i * (cubeSize * 2.0f + spacing); Vector3 bpos = new Vector3(0, 25, 0) + new Vector3(5.0f * pos.X, pos.Y, 5.0f * pos.Z); LocalCreateRigidBody(mass, Matrix.Translation(bpos), convexHullShape); } } offset -= 0.05f * spacing * (size - 1); spacing *= 1.1f; pos[1] += (cubeSize * 2.0f + spacing); } //CreateLargeMeshBody(); break; case 7: // TODO //CreateTest6(); //InitRays(); break; } }
public override void InitializeDemo() { SetCameraDistance(50); int totalTriangles = 2 * (NUM_VERTS_X - 1) * (NUM_VERTS_Y - 1); int vertStride = 1; int indexStride = 3; BulletGlobals.gContactAddedCallback = new CustomMaterialCombinerCallback(); gVertices = new ObjectArray <IndexedVector3>(totalVerts); gIndices = new ObjectArray <int>(totalTriangles * 3); SetVertexPositions(waveheight, 0.0f); gVertices.GetRawArray()[1].Y = 0.1f; int index = 0; int i, j; for (i = 0; i < NUM_VERTS_X - 1; i++) { for (j = 0; j < NUM_VERTS_Y - 1; j++) { #if SWAP_WINDING #if SHIFT_INDICES gIndices[index++] = j * NUM_VERTS_X + i; gIndices[index++] = (j + 1) * NUM_VERTS_X + i + 1; gIndices[index++] = j * NUM_VERTS_X + i + 1; gIndices[index++] = j * NUM_VERTS_X + i; gIndices[index++] = (j + 1) * NUM_VERTS_X + i; gIndices[index++] = (j + 1) * NUM_VERTS_X + i + 1; #else gIndices[index++] = (j + 1) * NUM_VERTS_X + i + 1; gIndices[index++] = j * NUM_VERTS_X + i + 1; gIndices[index++] = j * NUM_VERTS_X + i; gIndices[index++] = (j + 1) * NUM_VERTS_X + i; gIndices[index++] = (j + 1) * NUM_VERTS_X + i + 1; gIndices[index++] = j * NUM_VERTS_X + i; #endif //SHIFT_INDICES #else //SWAP_WINDING #if SHIFT_INDICES gIndices[index++] = (j + 1) * NUM_VERTS_X + i + 1; gIndices[index++] = j * NUM_VERTS_X + i; gIndices[index++] = j * NUM_VERTS_X + i + 1; #if TEST_INCONSISTENT_WINDING gIndices[index++] = j * NUM_VERTS_X + i; gIndices[index++] = (j + 1) * NUM_VERTS_X + i; gIndices[index++] = (j + 1) * NUM_VERTS_X + i + 1; #else //TEST_INCONSISTENT_WINDING gIndices[index++] = (j + 1) * NUM_VERTS_X + i; gIndices[index++] = j * NUM_VERTS_X + i; gIndices[index++] = (j + 1) * NUM_VERTS_X + i + 1; #endif //TEST_INCONSISTENT_WINDING #else //SHIFT_INDICES gIndices[index++] = j * NUM_VERTS_X + i; gIndices[index++] = j * NUM_VERTS_X + i + 1; gIndices[index++] = (j + 1) * NUM_VERTS_X + i + 1; gIndices[index++] = j * NUM_VERTS_X + i; gIndices[index++] = (j + 1) * NUM_VERTS_X + i + 1; gIndices[index++] = (j + 1) * NUM_VERTS_X + i; #endif //SHIFT_INDICES #endif //SWAP_WINDING } } m_indexVertexArrays = new TriangleIndexVertexArray(totalTriangles, gIndices, indexStride, totalVerts, gVertices, vertStride); bool useQuantizedAabbCompression = true; IndexedVector3 aabbMin = new IndexedVector3(-1000, -1000, -1000); IndexedVector3 aabbMax = new IndexedVector3(1000, 1000, 1000); trimeshShape = new BvhTriangleMeshShape(m_indexVertexArrays, useQuantizedAabbCompression, ref aabbMin, ref aabbMax, true); CollisionShape groundShape = trimeshShape; TriangleInfoMap triangleInfoMap = new TriangleInfoMap(); InternalEdgeUtility.GenerateInternalEdgeInfo(trimeshShape, triangleInfoMap); m_collisionConfiguration = new DefaultCollisionConfiguration(); m_dispatcher = new CollisionDispatcher(m_collisionConfiguration); m_broadphase = new DbvtBroadphase(); m_constraintSolver = new SequentialImpulseConstraintSolver(); m_dynamicsWorld = new DiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_constraintSolver, m_collisionConfiguration); m_dynamicsWorld.SetDebugDrawer(m_debugDraw); IndexedVector3 gravity = new IndexedVector3(0, -10, 0); m_dynamicsWorld.SetGravity(ref gravity); float mass = 0.0f; IndexedMatrix startTransform = IndexedMatrix.CreateTranslation(new IndexedVector3(0, -2, 0)); ConvexHullShape colShape = new ConvexHullShape(new List <IndexedVector3>(), 0); for (int k = 0; k < DemoMeshes.TaruVtxCount; k++) { IndexedVector3 vtx = DemoMeshes.TaruVtx[k]; colShape.AddPoint(ref vtx); } //this will enable polyhedral contact clipping, better quality, slightly slower //colShape.InitializePolyhedralFeatures(); //the polyhedral contact clipping can use either GJK or SAT test to find the separating axis m_dynamicsWorld.GetDispatchInfo().m_enableSatConvex = false; { //for (int i2 = 0; i2 < 1; i2++) //{ // startTransform._origin = new IndexedVector3(-10.0f + i2 * 3.0f, 2.2f + i2 * 0.1f, -1.3f); // RigidBody body = LocalCreateRigidBody(10, startTransform, colShape); // body.SetActivationState(ActivationState.DISABLE_DEACTIVATION); // body.SetLinearVelocity(new IndexedVector3(0, 0, -1)); // //body->setContactProcessingThreshold(0.f); //} } { BoxShape colShape2 = new BoxShape(new IndexedVector3(1, 1, 1)); //colShape.InitializePolyhedralFeatures(); m_collisionShapes.Add(colShape2); startTransform._origin = new IndexedVector3(-16.0f + i * 3.0f, 1.0f + i * 0.1f, -1.3f); RigidBody body = LocalCreateRigidBody(10, startTransform, colShape2); body.SetActivationState(ActivationState.DISABLE_DEACTIVATION); body.SetLinearVelocity(new IndexedVector3(0, 0, -1)); } startTransform = IndexedMatrix.Identity; staticBody = LocalCreateRigidBody(mass, startTransform, groundShape); //staticBody->setContactProcessingThreshold(-0.031f); staticBody.SetCollisionFlags(staticBody.GetCollisionFlags() | CollisionFlags.CF_KINEMATIC_OBJECT); //STATIC_OBJECT); //enable custom material callback staticBody.SetCollisionFlags(staticBody.GetCollisionFlags() | CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK); m_debugDraw.SetDebugMode(DebugDrawModes.DBG_DrawText | DebugDrawModes.DBG_NoHelpText | DebugDrawModes.DBG_DrawWireframe | DebugDrawModes.DBG_DrawContactPoints); //base.InitializeDemo(); //ClientResetScene(); }
/// <summary> /// Adds the point. /// </summary> /// <param name="point">The point.</param> public void AddPoint(float3 point) { var btPoint = Translator.Float3ToBtVector3(point); BtConvexHullShape.AddPoint(btPoint, true); }