public override CollisionShape GetCollisionShape()
        {
            if (collisionShapePtr == null) {
                Vector3[] verts = hullMesh.vertices;
                int[] tris = hullMesh.triangles;
                //todo test for convex. Make convex if not.
                TriangleMesh tm = new TriangleMesh();
                for (int i = 0; i < tris.Length; i += 3) {
                    tm.AddTriangle(verts[tris[i]].ToBullet(),
                                   verts[tris[i + 1]].ToBullet(),
                                   verts[tris[i + 2]].ToBullet(),
                                   true);
                }
                collisionShapePtr = new ConvexTriangleMeshShape(tm);
                ((ConvexTriangleMeshShape)collisionShapePtr).LocalScaling = m_localScaling.ToBullet();

            }
            return collisionShapePtr;
        }
Beispiel #2
0
        public BulletTriangleMesh(IModelo model, Vector3 pos, Matrix rotation, Vector3 scale)
        {
            TriangleMesh TriangleMesh = new BulletSharp.TriangleMesh(true, false);

            Vector3[] vertices = null;
            int[]     indices  = null;
            ExtractData(ref vertices, ref indices, model);
            for (int i = 0; i < indices.Count(); i += 3)
            {
                TriangleMesh.AddTriangle(vertices[indices[i]], vertices[indices[i + 1]], vertices[indices[i + 2]]);
            }
            vertices = null;
            indices  = null;

            BvhTriangleMeshShape = new BvhTriangleMeshShape(TriangleMesh, true, true);
            this.Shape           = BvhTriangleMeshShape;

            this.Scale         = scale;
            Shape.LocalScaling = scale;
            Object             = LocalCreateRigidBody(0, Matrix.CreateTranslation(pos) * rotation, Shape);
        }
        public BulletTriangleMesh(IModelo model, Vector3 pos, Matrix rotation, Vector3 scale)
        {
            TriangleMesh TriangleMesh = new BulletSharp.TriangleMesh(true,false);
            Vector3[] vertices = null;
            int[] indices = null;
            ExtractData(ref vertices, ref indices, model);                                    
            for (int i = 0; i < indices.Count(); i+=3)
            {

                TriangleMesh.AddTriangle(vertices[indices[i]], vertices[indices[i+1]], vertices[indices[i+2]]);
            }
            vertices = null;
            indices = null;     
                        
            BvhTriangleMeshShape = new BvhTriangleMeshShape(TriangleMesh, true, true);
            this.Shape = BvhTriangleMeshShape;
            
            this.Scale = scale;
            Shape.LocalScaling = scale;
            Object = LocalCreateRigidBody(0, Matrix.CreateTranslation(pos) * rotation, Shape);
        }
        /// <summary>
        /// Give it a mesh and it'll create a BulletSharp.TriangleMesh out of it
        /// </summary>
        /// <param name="mesh">The mesh you're converting</param>
        /// <returns>A bullet trimesh</returns>
        public static TriangleMesh Convert(MeshPtr mesh, Vector3 pos, Quaternion orientation, Vector3 scale)
        {
            // get our two main objects
            TriangleMesh BulletMesh = new TriangleMesh(true, false);

            Launch.Log("[Loading] Converting " + mesh.Name + " to a BulletSharp.TriangleMesh");

            uint vertex_count = default(uint);
            Vector3[] vertices = default(Vector3[]);
            uint index_count = default(uint);
            uint[] indices = default(uint[]);

            GetMeshInformation(mesh, ref vertex_count, ref vertices, ref index_count, ref indices, pos, orientation, scale);

            BulletMesh.PreallocateIndexes((int) index_count);
            BulletMesh.PreallocateVertices((int) vertex_count);
            //BulletMesh.WeldingThreshold = 0.1f;

            for (int a = 0; a < index_count; a += 3) {
                BulletMesh.AddTriangle(vertices[indices[a]], vertices[indices[a + 1]], vertices[indices[a + 2]], true);
            }

            return BulletMesh;
        }
        static void TestGCCollection()
        {
            var conf = new DefaultCollisionConfiguration();
            var dispatcher = new CollisionDispatcher(conf);
            var broadphase = new DbvtBroadphase();
            //var broadphase = new AxisSweep3(new Vector3(-1000, -1000, -1000), new Vector3(1000, 1000, 1000));
            world = new DiscreteDynamicsWorld(dispatcher, broadphase, null, conf);
            world.Gravity = new Vector3(0, -10, 0);
            dispatcher.NearCallback = DispatcherNearCallback;

            CreateBody(0.0f, new BoxShape(50, 1, 50), Vector3.Zero);
            var dynamicObject = CreateBody(10.0f, new SphereShape(1.0f), new Vector3(2, 2, 0));
            var dynamicObject2 = CreateBody(1.0f, new SphereShape(1.0f), new Vector3(0, 2, 0));

            var ghostPairCallback = new GhostPairCallback();
            broadphase.OverlappingPairCache.SetInternalGhostPairCallback(ghostPairCallback);
            AddToDisposeQueue(ghostPairCallback);
            ghostPairCallback = null;
            var ghostObject = new PairCachingGhostObject();
            ghostObject.CollisionShape = new BoxShape(2);
            ghostObject.WorldTransform = Matrix.Translation(2,2,0);
            world.AddCollisionObject(ghostObject);

            var trimesh = new TriangleMesh();
            Vector3 v0 = new Vector3(0, 0, 0);
            Vector3 v1 = new Vector3(1, 0, 0);
            Vector3 v2 = new Vector3(0, 1, 0);
            Vector3 v3 = new Vector3(1, 1, 0);
            trimesh.AddTriangle(v0, v1, v2);
            trimesh.AddTriangle(v1, v3, v2);
            var triangleMeshShape = new BvhTriangleMeshShape(trimesh, false);
            var triMeshObject = CreateBody(0, triangleMeshShape, new Vector3(20,0,20));
            AddToDisposeQueue(triangleMeshShape);
            AddToDisposeQueue(trimesh);
            AddToDisposeQueue(triMeshObject);
            triangleMeshShape = null;
            trimesh = null;

            AddToDisposeQueue(conf);
            AddToDisposeQueue(dispatcher);
            AddToDisposeQueue(broadphase);
            AddToDisposeQueue(world);

            //conf.Dispose();
            conf = null;
            //dispatcher.Dispose();
            dispatcher = null;
            //broadphase.Dispose();
            broadphase = null;
            world.DebugDrawer = new DebugDrawTest();
            AddToDisposeQueue(world.DebugDrawer);
            world.SetInternalTickCallback(WorldPreTickCallback);
            for (int i = 0; i < 600; i++)
            {
                world.StepSimulation(1.0f / 60.0f);
            }

            world.DispatchInfo.DebugDraw = new DebugDrawTest2();
            AddToDisposeQueue(world.DispatchInfo.DebugDraw);
            world.DispatchInfo.DebugDraw = world.DispatchInfo.DebugDraw;
            AddToDisposeQueue(world.DispatchInfo.DebugDraw);
            world.DispatchInfo.DebugDraw = null;
            world.DebugDrawer = null;
            world.DebugDrawer = new DebugDrawTest2();
            world.StepSimulation(1.0f / 60.0f);
            world.DebugDrawWorld();
            AddToDisposeQueue(world.DispatchInfo.DebugDraw);

            world.DebugDrawer = new DebugDrawTest();
            world.DebugDrawWorld();
            AddToDisposeQueue(world.DebugDrawer);
            world.DebugDrawer = null;

            TestContactTest(dynamicObject, dynamicObject2);
            TestGhostObjectPairs(ghostObject);
            TestRayCast(dynamicObject);
            TestTriangleMeshRayCast(triMeshObject);
            dynamicObject = null;
            dynamicObject2 = null;
            triMeshObject = null;

            //world.SetInternalTickCallback(null);
            world.Dispose();
            world = null;

            GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
            GC.WaitForPendingFinalizers();

            TestWeakRefs();
            disposeQueue.Clear();
        }
        public override void ConvexDecompResult(ConvexResult result)
        {
            TriangleMesh trimesh = new TriangleMesh();
            demo.trimeshes.Add(trimesh);

            Vector3 localScaling = new Vector3(6.0f, 6.0f, 6.0f);

            if (output == null)
                return;

            output.WriteLine("## Hull Piece {0} with {1} vertices and {2} triangles.", mHullCount, result.mHullVertices.Length, result.mHullIndices.Length / 3);

            output.WriteLine("usemtl Material{0}", mBaseCount);
            output.WriteLine("o Object{0}", mBaseCount);

            foreach (Vector3 p in result.mHullVertices)
            {
                output.WriteLine(string.Format(floatFormat, "v {0:F9} {1:F9} {2:F9}", p.X, p.Y, p.Z));
            }

            //calc centroid, to shift vertices around center of mass
            demo.centroid = Vector3.Zero;

            AlignedVector3Array vertices = new AlignedVector3Array();
            if (true)
            {
                foreach (Vector3 vertex in result.mHullVertices)
                {
                    demo.centroid += vertex * localScaling;
                }
            }

            demo.centroid /= (float)result.mHullVertices.Length;

            if (true)
            {
                foreach (Vector3 vertex in result.mHullVertices)
                {
                    vertices.Add(vertex * localScaling - demo.centroid);
                }
            }

            if (true)
            {
                int[] src = result.mHullIndices;
                for (int i = 0; i < src.Length; i += 3)
                {
                    int index0 = src[i];
                    int index1 = src[i + 1];
                    int index2 = src[i + 2];

                    Vector3 vertex0 = result.mHullVertices[index0] * localScaling - demo.centroid;
                    Vector3 vertex1 = result.mHullVertices[index1] * localScaling - demo.centroid;
                    Vector3 vertex2 = result.mHullVertices[index2] * localScaling - demo.centroid;

                    trimesh.AddTriangle(vertex0, vertex1, vertex2);

                    index0 += mBaseCount;
                    index1 += mBaseCount;
                    index2 += mBaseCount;

                    output.WriteLine("f {0} {1} {2}", index0 + 1, index1 + 1, index2 + 1);
                }
            }

            //this is a tools issue: due to collision margin, convex objects overlap, compensate for it here:
            //#define SHRINK_OBJECT_INWARDS 1
            #if SHRINK_OBJECT_INWARDS

            float collisionMargin = 0.01f;

            btAlignedObjectArray<btVector3> planeEquations;
            btGeometryUtil::getPlaneEquationsFromVertices(vertices,planeEquations);

            btAlignedObjectArray<btVector3> shiftedPlaneEquations;
            for (int p=0;p<planeEquations.size();p++)
            {
                btVector3 plane = planeEquations[p];
                plane[3] += collisionMargin;
                shiftedPlaneEquations.push_back(plane);
            }
            btAlignedObjectArray<btVector3> shiftedVertices;
            btGeometryUtil::getVerticesFromPlaneEquations(shiftedPlaneEquations,shiftedVertices);

            btConvexHullShape* convexShape = new btConvexHullShape(&(shiftedVertices[0].getX()),shiftedVertices.size());

            #else //SHRINK_OBJECT_INWARDS

            ConvexHullShape convexShape = new ConvexHullShape(vertices);
            #endif

            if (demo.sEnableSAT)
            {
                convexShape.InitializePolyhedralFeatures();
            }
            convexShape.Margin = 0.01f;
            convexShapes.Add(convexShape);
            convexCentroids.Add(demo.centroid);
            demo.CollisionShapes.Add(convexShape);
            mBaseCount += result.mHullVertices.Length; // advance the 'base index' counter.
        }
        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()
        {
            ManifoldPoint.ContactAdded += MyContactCallback;

            SetupEmptyDynamicsWorld();

            CompoundCollisionAlgorithm.CompoundChildShapePairCallback = MyCompoundChildShapeCallback;
            convexDecompositionObjectOffset = new Vector3(10, 0, 0);

            // Load wavefront file
            var wo = new WavefrontObj();
            int tcount = wo.LoadObj("data/file.obj");
            if (tcount == 0)
            {
                return;
            }

            // Convert file data to TriangleMesh
            var 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.AddTriangleRef(ref vertex0, ref vertex1, ref vertex2);
            }

            // Create a hull approximation
            ConvexHullShape convexShape;
            using (var tmpConvexShape = new ConvexTriangleMeshShape(trimesh))
            {
                using (var hull = new ShapeHull(tmpConvexShape))
                {
                    hull.BuildHull(tmpConvexShape.Margin);
                    convexShape = new ConvexHullShape(hull.Vertices);
                }
            }
            if (sEnableSAT)
            {
                convexShape.InitializePolyhedralFeatures();
            }
            CollisionShapes.Add(convexShape);

            // Add non-moving body to world
            float mass = 1.0f;
            LocalCreateRigidBody(mass, Matrix.Translation(0, 2, 14), convexShape);

            const bool useQuantization = true;
            var concaveShape = new BvhTriangleMeshShape(trimesh, useQuantization);
            LocalCreateRigidBody(0, Matrix.Translation(convexDecompositionObjectOffset), concaveShape);

            CollisionShapes.Add(concaveShape);

            // HACD
            var hacd = new Hacd();
            hacd.SetPoints(wo.Vertices);
            hacd.SetTriangles(wo.Indices);
            hacd.CompacityWeight = 0.1;
            hacd.VolumeWeight = 0.0;

            // Recommended HACD parameters: 2 100 false false false
            hacd.NClusters = 2;                      // minimum number of clusters
            hacd.Concavity = 100;                    // maximum concavity
            hacd.AddExtraDistPoints = false;
            hacd.AddNeighboursDistPoints = false;
            hacd.AddFacesPoints = false;
            hacd.NumVerticesPerConvexHull = 100;     // max of 100 vertices per convex-hull

            hacd.Compute();
            hacd.Save("output.wrl", false);

            // Generate convex result
            var outputFile = new FileStream("file_convex.obj", FileMode.Create, FileAccess.Write);
            var writer = new StreamWriter(outputFile);

            var convexDecomposition = new ConvexDecomposition(writer, this);
            convexDecomposition.LocalScaling = localScaling;

            for (int c = 0; c < hacd.NClusters; c++)
            {
                Vector3[] points;
                int[] triangles;
                hacd.GetCH(c, out points, out triangles);

                convexDecomposition.ConvexDecompResult(points, triangles);
            }

            // Combine convex shapes into a compound shape
            var compound = new CompoundShape();
            for (i = 0; i < convexDecomposition.convexShapes.Count; i++)
            {
                Vector3 centroid = convexDecomposition.convexCentroids[i];
                var convexShape2 = convexDecomposition.convexShapes[i];
                Matrix trans = Matrix.Translation(centroid);
                if (sEnableSAT)
                {
                    convexShape2.InitializePolyhedralFeatures();
                }
                CollisionShapes.Add(convexShape2);
                compound.AddChildShape(trans, convexShape2);

                LocalCreateRigidBody(1.0f, trans, convexShape2);
            }
            CollisionShapes.Add(compound);

            writer.Dispose();
            outputFile.Dispose();

            #if true
            mass = 10.0f;
            var body2 = LocalCreateRigidBody(mass, Matrix.Translation(-convexDecompositionObjectOffset), compound);
            body2.CollisionFlags |= CollisionFlags.CustomMaterialCallback;

            convexDecompositionObjectOffset.Z = 6;
            body2 = LocalCreateRigidBody(mass, Matrix.Translation(-convexDecompositionObjectOffset), compound);
            body2.CollisionFlags |= CollisionFlags.CustomMaterialCallback;

            convexDecompositionObjectOffset.Z = -6;
            body2 = LocalCreateRigidBody(mass, Matrix.Translation(-convexDecompositionObjectOffset), compound);
            body2.CollisionFlags |= CollisionFlags.CustomMaterialCallback;
            #endif
        }
        public void ConvexDecompResult(Vector3[] hullVertices, int[] hullIndices)
        {
            if (output == null)
                return;

            output.WriteLine("## Hull Piece {0} with {1} vertices and {2} triangles.", convexShapes.Count, hullVertices.Length, hullIndices.Length / 3);

            output.WriteLine("usemtl Material{0}", mBaseCount);
            output.WriteLine("o Object{0}", mBaseCount);

            foreach (Vector3 p in hullVertices)
            {
                output.WriteLine(string.Format(floatFormat, "v {0:F9} {1:F9} {2:F9}", p.X, p.Y, p.Z));
            }

            // Calc centroid, to shift vertices around center of mass
            Vector3 centroid = Vector3.Zero;
            foreach (Vector3 vertex in hullVertices)
            {
                centroid += vertex * LocalScaling;
            }
            centroid /= (float)hullVertices.Length;

            List<Vector3> outVertices = new List<Vector3>();
            foreach (Vector3 vertex in hullVertices)
            {
                outVertices.Add(vertex * LocalScaling - centroid);
            }

            // Create TriangleMesh
            var trimesh = new TriangleMesh();
            for (int i = 0; i < hullIndices.Length; i += 3)
            {
                int index0 = hullIndices[i];
                int index1 = hullIndices[i + 1];
                int index2 = hullIndices[i + 2];

                Vector3 vertex0 = hullVertices[index0] * LocalScaling - centroid;
                Vector3 vertex1 = hullVertices[index1] * LocalScaling - centroid;
                Vector3 vertex2 = hullVertices[index2] * LocalScaling - centroid;

                index0 += mBaseCount;
                index1 += mBaseCount;
                index2 += mBaseCount;

                output.WriteLine("f {0} {1} {2}", index0 + 1, index1 + 1, index2 + 1);
            }

            //this is a tools issue: due to collision margin, convex objects overlap, compensate for it here:
            //#define SHRINK_OBJECT_INWARDS 1
            #if SHRINK_OBJECT_INWARDS

            float collisionMargin = 0.01f;

            AlignedVector3Array planeEquations;
            GeometryUtil.GetPlaneEquationsFromVertices(hullVertices, planeEquations);

            AlignedVector3Array shiftedPlaneEquations;
            for (int p=0;p<planeEquations.Count;p++)
            {
                Vector3 plane = planeEquations[p];
                plane[3] += collisionMargin;
                shiftedPlaneEquations.Add(plane);
            }
            AlignedVector3Array shiftedVertices;
            GeometryUtil.GetVerticesFromPlaneEquations(shiftedPlaneEquations, shiftedVertices);
            ConvexHullShape convexShape = new ConvexHullShape(shiftedVertices);
            #else //SHRINK_OBJECT_INWARDS

            ConvexHullShape convexShape = new ConvexHullShape(outVertices);
            #endif

            convexShape.Margin = 0.01f;
            convexShapes.Add(convexShape);
            convexCentroids.Add(centroid);
            mBaseCount += hullVertices.Length; // advance the 'base index' counter.
        }
Beispiel #10
0
		CollisionShape bulletGetCollisionShape(Shape shape, SceneNode node)
		{
			switch (shape)
			{
				case Shape.Box:
					{
						return new BoxShape(node.BoundingBox.Extent.X / 2);
					}

				case Shape.Shpere:
					{
						return new SphereShape(node.BoundingBox.Extent.X / 2);
					}

				case Shape.Mesh:
					{
						MeshSceneNode meshNode = node as MeshSceneNode;
						if (meshNode == null)
							throw new ArgumentException();

						TriangleMesh triangleMesh = new TriangleMesh();
						for (int i = 0; i < meshNode.Mesh.MeshBufferCount; i++)
						{
							MeshBuffer b = meshNode.Mesh.GetMeshBuffer(i);
							ushort[] inds = b.Indices as ushort[];
							Vertex3DTTCoords[] verts = b.Vertices as Vertex3DTTCoords[];

							if (inds == null || verts == null)
								throw new ArgumentException();

							for (int j = 0; j < inds.Length; j += 3)
							{
								Vector3Df v0 = verts[inds[j + 0]].Position;
								Vector3Df v1 = verts[inds[j + 1]].Position;
								Vector3Df v2 = verts[inds[j + 2]].Position;

								triangleMesh.AddTriangle(
									new Vector3(v0.X, v0.Y, v0.Z),
									new Vector3(v1.X, v1.Y, v1.Z),
									new Vector3(v2.X, v2.Y, v2.Z));
							}
						}

						return new BvhTriangleMeshShape(triangleMesh, false);
					}

				default:
					throw new ArgumentException();
			}
		}
        protected override void OnInitializePhysics()
        {
            ManifoldPoint.ContactAdded += MyContactCallback;

            SetupEmptyDynamicsWorld();

            //CompoundCollisionAlgorithm.CompoundChildShapePairCallback = MyCompoundChildShapeCallback;
            convexDecompositionObjectOffset = new Vector3(10, 0, 0);

            // Load wavefront file
            var wo = new WavefrontObj();
            //string filename = UnityEngine.Application.dataPath + "/BulletUnity/Examples/Scripts/BulletSharpDemos/ConvexDecompositionDemo/data/file.obj";
            UnityEngine.TextAsset bytes = (UnityEngine.TextAsset)UnityEngine.Resources.Load("file.obj");
            System.IO.Stream byteStream = new System.IO.MemoryStream(bytes.bytes);

            int tcount = wo.LoadObj(byteStream);
            if (tcount == 0)
            {
                return;
            }

            // Convert file data to TriangleMesh
            var 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.AddTriangleRef(ref vertex0, ref vertex1, ref vertex2);
            }

            // Create a hull approximation
            ConvexHullShape convexShape;
            using (var tmpConvexShape = new ConvexTriangleMeshShape(trimesh))
            {
                using (var hull = new ShapeHull(tmpConvexShape))
                {
                    hull.BuildHull(tmpConvexShape.Margin);
                    convexShape = new ConvexHullShape(hull.Vertices);
                }
            }
            if (sEnableSAT)
            {
                convexShape.InitializePolyhedralFeatures();
            }
            CollisionShapes.Add(convexShape);

            // Add non-moving body to world
            float mass = 1.0f;
            LocalCreateRigidBody(mass, Matrix.Translation(0, 2, 14), convexShape);

            const bool useQuantization = true;
            var concaveShape = new BvhTriangleMeshShape(trimesh, useQuantization);
            LocalCreateRigidBody(0, Matrix.Translation(convexDecompositionObjectOffset), concaveShape);

            CollisionShapes.Add(concaveShape);

            // HACD
            var hacd = new Hacd();
            hacd.SetPoints(wo.Vertices);
            hacd.SetTriangles(wo.Indices);
            hacd.CompacityWeight = 0.1;
            hacd.VolumeWeight = 0.0;

            // Recommended HACD parameters: 2 100 false false false
            hacd.NClusters = 2;                      // minimum number of clusters
            hacd.Concavity = 100;                    // maximum concavity
            hacd.AddExtraDistPoints = false;
            hacd.AddNeighboursDistPoints = false;
            hacd.AddFacesPoints = false;
            hacd.NVerticesPerCH = 100;     // max of 100 vertices per convex-hull

            hacd.Compute();
            hacd.Save("output.wrl", false);

            // Generate convex result
            var outputFile = new FileStream("file_convex.obj", FileMode.Create, FileAccess.Write);
            var writer = new StreamWriter(outputFile);

            var convexDecomposition = new ConvexDecomposition(writer, this);
            convexDecomposition.LocalScaling = localScaling;

            for (int c = 0; c < hacd.NClusters; c++)
            {
                int nVertices = hacd.GetNPointsCH(c);
                int trianglesLen = hacd.GetNTrianglesCH(c) * 3;
                double[] points = new double[nVertices * 3];
                long[] triangles = new long[trianglesLen];
                hacd.GetCH(c, points, triangles);

                if (trianglesLen == 0)
                {
                    continue;
                }

                Vector3[] verticesArray = new Vector3[nVertices];
                int vi3 = 0;
                for (int vi = 0; vi < nVertices; vi++)
                {
                    verticesArray[vi] = new Vector3(
                        (float)points[vi3], (float)points[vi3 + 1], (float)points[vi3 + 2]);
                    vi3 += 3;
                }

                int[] trianglesInt = new int[trianglesLen];
                for (int ti = 0; ti < trianglesLen; ti++)
                {
                    trianglesInt[ti] = (int)triangles[ti];
                }

                convexDecomposition.ConvexDecompResult(verticesArray, trianglesInt);
            }

            // Combine convex shapes into a compound shape
            var compound = new CompoundShape();
            for (i = 0; i < convexDecomposition.convexShapes.Count; i++)
            {
                Vector3 centroid = convexDecomposition.convexCentroids[i];
                var convexShape2 = convexDecomposition.convexShapes[i];
                Matrix trans = Matrix.Translation(centroid);
                if (sEnableSAT)
                {
                    convexShape2.InitializePolyhedralFeatures();
                }
                CollisionShapes.Add(convexShape2);
                compound.AddChildShape(trans, convexShape2);

                LocalCreateRigidBody(1.0f, trans, convexShape2);
            }
            CollisionShapes.Add(compound);

            writer.Dispose();
            outputFile.Dispose();

            #if true
            mass = 10.0f;
            var body2 = LocalCreateRigidBody(mass, Matrix.Translation(-convexDecompositionObjectOffset), compound);
            body2.CollisionFlags |= CollisionFlags.CustomMaterialCallback;

            convexDecompositionObjectOffset.Z = 6;
            body2 = LocalCreateRigidBody(mass, Matrix.Translation(-convexDecompositionObjectOffset), compound);
            body2.CollisionFlags |= CollisionFlags.CustomMaterialCallback;

            convexDecompositionObjectOffset.Z = -6;
            body2 = LocalCreateRigidBody(mass, Matrix.Translation(-convexDecompositionObjectOffset), compound);
            body2.CollisionFlags |= CollisionFlags.CustomMaterialCallback;
            #endif
        }