Esempio n. 1
0
        public static void CreateShapes(Demo demo, PhysicsScene scene)
        {
            TriangleMesh   triangleMesh   = null;
            ShapePrimitive shapePrimitive = null;
            Shape          shape          = null;

            shapePrimitive = scene.Factory.ShapePrimitiveManager.Create("CapsuleY1");
            shapePrimitive.CreateCapsuleY(1.5f, 1.0f);

            shape = scene.Factory.ShapeManager.Create("CapsuleY1");
            shape.Set(shapePrimitive, Matrix4.Identity, 0.0f);

            shapePrimitive = scene.Factory.ShapePrimitiveManager.Create("CapsuleY2");
            shapePrimitive.CreateCapsuleY(2.0f, 0.5f);

            shape = scene.Factory.ShapeManager.Create("CapsuleY2");
            shape.Set(shapePrimitive, Matrix4.Identity, 0.0f);

            shapePrimitive = scene.Factory.ShapePrimitiveManager.Create("CapsuleY3");
            shapePrimitive.CreateCapsuleY(2.5f, 0.5f);

            shape = scene.Factory.ShapeManager.Create("CapsuleY3");
            shape.Set(shapePrimitive, Matrix4.Identity, 0.0f);

            triangleMesh = scene.Factory.TriangleMeshManager.Create("CapsuleY1");
            triangleMesh.CreateCapsuleY(10, 15, 1.5f, 1.0f);
            if (!demo.Meshes.ContainsKey("CapsuleY1"))
            {
                demo.Meshes.Add("CapsuleY1", new DemoMesh(demo, triangleMesh, demo.Textures["Default"], Vector2.One, true, true, true, false, true, CullFaceMode.Back, false, false));
            }

            triangleMesh = scene.Factory.TriangleMeshManager.Create("CapsuleY2");
            triangleMesh.CreateCapsuleY(10, 15, 2.0f, 0.5f);
            if (!demo.Meshes.ContainsKey("CapsuleY2"))
            {
                demo.Meshes.Add("CapsuleY2", new DemoMesh(demo, triangleMesh, demo.Textures["Default"], Vector2.One, true, true, true, false, true, CullFaceMode.Back, false, false));
            }

            triangleMesh = scene.Factory.TriangleMeshManager.Create("CapsuleY3");
            triangleMesh.CreateCapsuleY(10, 15, 2.5f, 0.5f);
            if (!demo.Meshes.ContainsKey("CapsuleY3"))
            {
                demo.Meshes.Add("CapsuleY3", new DemoMesh(demo, triangleMesh, demo.Textures["Default"], Vector2.One, true, true, true, false, true, CullFaceMode.Back, false, false));
            }
        }
Esempio n. 2
0
        /// <summary>
        ///
        /// </summary>
        /// <remarks>
        /// For all of the shapes that has directions (e.g., Cylinder, Hemisphere), Y direction is
        /// used, so if you would like it to face other directions, use MataliObject.ShapeOriginalMatrix
        /// to orient them.
        ///
        /// For a cylinder with different bottom and top radius, IPhysicsObject.ShapeData are used.
        /// ShapeData[0] - bottom radius, ShapeData[1] - height, ShapeData[2] = top radius
        ///
        /// For Compound shape, an additional information can be set by using
        /// MataliObject.CompoundShape.
        ///
        /// For additional shape types such as Heightmap, Point, and so on, set Shape to ShapeType.Extra
        /// and define MataliObject.ExtraShape.
        /// </remarks>
        /// <param name="mataliPhysicsObj"></param>
        /// <param name="physObj"></param>
        private void SetShape(MataliPhysicsObject mataliPhysicsObj, IPhysicsObject physObj)
        {
            Vector3 boundingBox = Vector3.Zero;

            if (physObj.Model != null)
            {
                boundingBox = Vector3Helper.GetDimensions(physObj.Model.MinimumBoundingBox);
            }
            Vector3 size = Vector3.Zero;

            MataliObject mataliObj = null;

            if (physObj is MataliObject)
            {
                mataliObj = (MataliObject)physObj;
            }

            switch (physObj.Shape)
            {
            case ShapeType.Box:
                if (physObj.ShapeData.Count == 3)
                {
                    size = new Vector3(physObj.ShapeData[0], physObj.ShapeData[1], physObj.ShapeData[2]);
                }
                else
                {
                    size = boundingBox;
                }

                size /= 2;
                break;

            case ShapeType.Sphere:
                if (physObj.ShapeData.Count == 1)
                {
                    size = new Vector3(physObj.ShapeData[0], 0, 0);
                }
                else
                {
                    size = boundingBox / 2;
                }
                break;

            case ShapeType.Cone:
            case ShapeType.Cylinder:
            case ShapeType.Capsule:
                if (physObj.ShapeData.Count == 2)
                {
                    size = new Vector3(physObj.ShapeData[0], physObj.ShapeData[1], physObj.ShapeData[0]);
                }
                else if (physObj.ShapeData.Count == 3)
                {
                    size = new Vector3(physObj.ShapeData[0], physObj.ShapeData[1], physObj.ShapeData[2]);
                }
                else
                {
                    size = new Vector3(boundingBox.X / 2, boundingBox.Y, boundingBox.X / 2);
                }
                break;

            case ShapeType.Compound:
                // size is used solely for naming, not used for the collision shape
                size = new Vector3(physObj.ShapeData.Count, physObj.ShapeData[0],
                                   physObj.ShapeData[physObj.ShapeData.Count - 1]);
                break;

            case ShapeType.ConvexHull:
                // size is used solely for naming, not used for the collision shape
                size = new Vector3(physObj.MeshProvider.Vertices.Count,
                                   physObj.MeshProvider.Indices.Count, physObj.MeshProvider.Vertices[0].X);
                break;

            case ShapeType.Extra:
                if (mataliObj == null)
                {
                    throw new GoblinException("For extra shape type, you need to define the 'physObj' " +
                                              "as MataliObject instance");
                }

                if (mataliObj.ExtraShape == ExtraShapeType.Undefined)
                {
                    throw new GoblinException("Undefined type is not allowed if Extra shape type is specified");
                }

                // size is used solely for naming, not used for the collision shape
                switch (mataliObj.ExtraShape)
                {
                case ExtraShapeType.Point:
                    if (physObj.ShapeData.Count != 3)
                    {
                        throw new GoblinException("For Point shape type, you need to specify the position (x,y,z) in ShapeData");
                    }

                    size = new Vector3(physObj.ShapeData[0], physObj.ShapeData[1], physObj.ShapeData[2]);
                    break;

                case ExtraShapeType.Heightmap:
                    if (physObj.ShapeData.Count < 2)
                    {
                        throw new GoblinException("There needs to be at least two floats specifying the " +
                                                  "width and height");
                    }

                    size = new Vector3(physObj.ShapeData[0], physObj.ShapeData[1], physObj.ShapeData.Count);
                    break;

                case ExtraShapeType.Edge:
                    if (physObj.ShapeData.Count != 6)
                    {
                        throw new GoblinException("For Edge shape type, you need to specify the start and " +
                                                  "end positions (x,y,z) in ShapeData");
                    }

                    size = new Vector3(physObj.ShapeData[0] + physObj.ShapeData[3],
                                       physObj.ShapeData[1] + physObj.ShapeData[4],
                                       physObj.ShapeData[2] + physObj.ShapeData[5]);
                    break;

                default:
                    throw new GoblinException(mataliObj.ExtraShape.ToString() + " not implemented yet");
                }
                break;
            }

            String shapeName     = physObj.Shape.ToString() + size.ToString();
            String primitiveName = physObj.Shape.ToString() + size.ToString();

            if (mataliObj != null)
            {
                String suffix = "";
                if (physObj.Shape == ShapeType.Extra)
                {
                    suffix += mataliObj.ExtraShape.ToString();
                }
                else if (physObj.Shape == ShapeType.Compound)
                {
                    suffix += mataliObj.CompoundShape.ToString();
                }
                suffix += mataliObj.ShapeOriginalMatrix.ToString();
                suffix += mataliObj.ShapeCollisionMargin;

                shapeName     += suffix;
                primitiveName += suffix;
            }
            Shape          shape     = null;
            ShapePrimitive primitive = null;

            if (scene.Factory.ShapeManager.Contains(shapeName))
            {
                shape = scene.Factory.ShapeManager.Find(shapeName);
            }
            else
            {
                if (physObj.Shape != ShapeType.Compound)
                {
                    primitive = scene.Factory.ShapePrimitiveManager.Create(primitiveName);
                }
                shape = scene.Factory.ShapeManager.Create(shapeName);
                bool shapeSet = false;
                switch (physObj.Shape)
                {
                case ShapeType.Box:
                    primitive.CreateBox(size.X, size.Y, size.Z);
                    break;

                case ShapeType.Sphere:
                    primitive.CreateSphere(size.X);
                    break;

                case ShapeType.Cone:
                    primitive.CreateConeY(size.Y, size.X);
                    break;

                case ShapeType.Cylinder:
                    if (size.X != size.Z)
                    {
                        primitive.CreateCylinder2RY(size.Y, size.X, size.Z);
                    }
                    else
                    {
                        primitive.CreateCylinderY(size.Y, size.X);
                    }
                    break;

                case ShapeType.Capsule:
                    primitive.CreateCapsuleY(size.Y - size.X * 2, size.X);
                    break;

                case ShapeType.Compound:
                    ShapeCompoundType type = ShapeCompoundType.ConvexHull;
                    if (mataliObj != null)
                    {
                        if (mataliObj.CompoundShape == CompoundShapeType.MinkowskiSum)
                        {
                            type = ShapeCompoundType.MinkowskiSum;
                        }
                    }

                    int            dataIndex         = 0;
                    Shape          compoundShapePart = null;
                    ShapePrimitive compoundPrimitive = null;
                    float[]        matrixVals        = new float[16];
                    while (dataIndex < physObj.ShapeData.Count)
                    {
                        ShapeType shapeType = (ShapeType)Enum.ToObject(typeof(ShapeType), (int)physObj.ShapeData[dataIndex++]);
                        switch (shapeType)
                        {
                        case ShapeType.Cylinder:
                            size = new Vector3(physObj.ShapeData[dataIndex], physObj.ShapeData[dataIndex + 1],
                                               physObj.ShapeData[dataIndex]);
                            dataIndex += 2;
                            break;

                        case ShapeType.Sphere:
                            size = new Vector3(physObj.ShapeData[dataIndex], 0, 0);
                            dataIndex++;
                            break;
                        }

                        shapeName     = shapeType.ToString() + size.ToString();
                        primitiveName = shapeType.ToString() + size.ToString();

                        if (scene.Factory.ShapeManager.Contains(shapeName))
                        {
                            compoundShapePart = scene.Factory.ShapeManager.Find(shapeName);
                        }
                        else
                        {
                            compoundPrimitive = scene.Factory.ShapePrimitiveManager.Create(primitiveName);
                            compoundShapePart = scene.Factory.ShapeManager.Create(shapeName);
                            switch (shapeType)
                            {
                            case ShapeType.Cylinder:
                                compoundPrimitive.CreateCylinderY(size.Y, size.X);
                                break;

                            case ShapeType.Sphere:
                                compoundPrimitive.CreateSphere(size.X);
                                break;

                            default:
                                throw new GoblinException(shape.ToString() + " is not supported yet as a compound part");
                            }

                            compoundShapePart.Set(compoundPrimitive, Matrix.Identity, 0.0f);
                        }

                        for (int i = 0; i < 16; ++i)
                        {
                            matrixVals[i] = physObj.ShapeData[dataIndex + i];
                        }
                        dataIndex += 16;
                        shape.Add(compoundShapePart, MatrixHelper.FloatsToMatrix(matrixVals), 0.0f, type);
                    }

                    float margin = 0.0f;
                    if (mataliObj != null)
                    {
                        margin = mataliObj.ShapeCollisionMargin;
                    }
                    shape.CreateMesh(margin);

                    shapeSet = true;
                    break;

                case ShapeType.ConvexHull:
                case ShapeType.TriangleMesh:
                    float[] frictions    = null;
                    float[] restitutions = null;

                    if (physObj.Shape == ShapeType.ConvexHull)
                    {
                        primitive.CreateConvex(physObj.MeshProvider.Vertices);
                    }
                    else
                    {
                        int triangleCount = physObj.MeshProvider.Indices.Count / 3;
                        frictions    = new float[triangleCount];
                        restitutions = new float[triangleCount];

                        for (int i = 0; i < frictions.Length; i++)
                        {
                            frictions[i]    = 1.0f;
                            restitutions[i] = 0.0f;
                        }

                        Vector3[] triVerts = new Vector3[physObj.MeshProvider.Indices.Count];
                        for (int i = 0; i < triVerts.Length; ++i)
                        {
                            triVerts[i] = physObj.MeshProvider.Vertices[physObj.MeshProvider.Indices[i]];
                        }

                        bool flipTriangle = (physObj is MataliObject) ? ((MataliObject)physObj).FlipTriangleOrder : true;
                        primitive.CreateTriangleMesh(triVerts, flipTriangle, 2, frictions, restitutions, 1.0f, 0.0f);
                    }

                    break;

                case ShapeType.Extra:
                    switch (mataliObj.ExtraShape)
                    {
                    case ExtraShapeType.Heightmap:
                        int     width             = (int)physObj.ShapeData[0];
                        int     height            = (int)physObj.ShapeData[1];
                        float[] heightData        = new float[height * width];
                        float[] heightFrictions   = new float[height * width];
                        float[] heightRestituions = new float[height * width];

                        if (physObj.ShapeData.Count < (2 + heightData.Length))
                        {
                            throw new GoblinException("You also need to specify the hegith map data");
                        }
                        Buffer.BlockCopy(physObj.ShapeData.ToArray(), 2 * sizeof(float), heightData, 0,
                                         heightData.Length * sizeof(float));

                        if (physObj.ShapeData.Count > (2 + heightData.Length * 2))
                        {
                            Buffer.BlockCopy(physObj.ShapeData.ToArray(), (2 + heightData.Length) * sizeof(float),
                                             heightFrictions, 0, heightFrictions.Length * sizeof(float));
                        }
                        else
                        {
                            for (int i = 0; i < heightFrictions.Length; ++i)
                            {
                                heightFrictions[i] = mataliObj.TriangleMeshFriction;
                            }
                        }

                        if (physObj.ShapeData.Count > (2 + heightData.Length * 3))
                        {
                            Buffer.BlockCopy(physObj.ShapeData.ToArray(), (2 + heightData.Length * 2) * sizeof(float),
                                             heightRestituions, 0, heightRestituions.Length * sizeof(float));
                        }
                        else
                        {
                            for (int i = 0; i < heightRestituions.Length; ++i)
                            {
                                heightRestituions[i] = mataliObj.TriangleMeshRestitution;
                            }
                        }

                        primitive.CreateHeightmap(0, 0, width, height, width, height, heightData, heightFrictions, heightRestituions,
                                                  mataliObj.TriangleMeshFriction, mataliObj.TriangleMeshRestitution, mataliObj.IsDynamic);
                        shape.Set(primitive, mataliObj.ShapeOriginalMatrix, mataliObj.ShapeCollisionMargin);
                        shape.CreateMesh(0.0f);
                        shapeSet = true;

                        mataliPhysicsObj.InternalControllers.CreateHeightmapController(true);
                        break;

                    case ExtraShapeType.Point:
                        primitive.CreatePoint(physObj.ShapeData[0], physObj.ShapeData[1], physObj.ShapeData[2]);
                        break;

                    case ExtraShapeType.Edge:
                        primitive.CreateEdge(new Vector3(physObj.ShapeData[0], physObj.ShapeData[1], physObj.ShapeData[2]),
                                             new Vector3(physObj.ShapeData[3], physObj.ShapeData[4], physObj.ShapeData[5]));
                        break;

                    case ExtraShapeType.Plane:
                        primitive.CreatePlaneY(physObj.ShapeData[0], (physObj.ShapeData[1] > 0));
                        break;

                    case ExtraShapeType.Triangle:
                        primitive.CreateTriangle(
                            new Vector3(physObj.ShapeData[0], physObj.ShapeData[1], physObj.ShapeData[2]),
                            new Vector3(physObj.ShapeData[3], physObj.ShapeData[4], physObj.ShapeData[5]),
                            new Vector3(physObj.ShapeData[6], physObj.ShapeData[7], physObj.ShapeData[8]));
                        break;

                    case ExtraShapeType.Tetrahedron:
                        primitive.CreateTetrahedron(
                            new Vector3(physObj.ShapeData[0], physObj.ShapeData[1], physObj.ShapeData[2]),
                            new Vector3(physObj.ShapeData[3], physObj.ShapeData[4], physObj.ShapeData[5]),
                            new Vector3(physObj.ShapeData[6], physObj.ShapeData[7], physObj.ShapeData[8]),
                            new Vector3(physObj.ShapeData[9], physObj.ShapeData[10], physObj.ShapeData[11]));
                        break;

                    case ExtraShapeType.Fluid:
                        break;

                    case ExtraShapeType.Hemisphere:
                        primitive.CreateHemisphereY(physObj.ShapeData[0]);
                        break;
                    }
                    break;
                }

                if (!shapeSet)
                {
                    if (mataliObj != null)
                    {
                        shape.Set(primitive, mataliObj.ShapeOriginalMatrix, mataliObj.ShapeCollisionMargin);
                    }
                    else
                    {
                        shape.Set(primitive, Matrix.Identity, 0.0f);
                    }

                    if (buildCollisionMesh)
                    {
                        float margin = 0.0f;
                        if (mataliObj != null)
                        {
                            margin = mataliObj.ShapeCollisionMargin;
                        }
                        shape.CreateMesh(margin);
                    }
                }
            }

            mataliPhysicsObj.Shape = shape;
        }