Ejemplo n.º 1
0
        private void CreateObjects()
        {
            ModelLoader loader = new ModelLoader();

            overlayNode       = new GeometryNode("Overlay");
            overlayNode.Model = (Model)loader.Load("", "p1_wedge");
            ((Model)overlayNode.Model).UseInternalMaterials = true;

            // Get the dimension of the model
            Vector3 dimension = Vector3Helper.GetDimensions(overlayNode.Model.MinimumBoundingBox);
            // Scale the model to fit to the size of 5 markers
            float scale = markerSize * 5 / Math.Max(dimension.X, dimension.Z);

            TransformNode overlayTransNode = new TransformNode()
            {
                Translation = new Vector3(0, 0, dimension.Y * scale / 2),
                Rotation    = Quaternion.CreateFromAxisAngle(Vector3.UnitX, MathHelper.ToRadians(90)) *
                              Quaternion.CreateFromAxisAngle(Vector3.UnitY, MathHelper.ToRadians(90)),
                Scale = new Vector3(scale, scale, scale)
            };

            scene.RootNode.AddChild(overlayTransNode);
            overlayTransNode.AddChild(overlayNode);
        }
Ejemplo n.º 2
0
        private IntPtr GetCollisionShape(IPhysicsObject physObj, Vector3 scale)
        {
            IntPtr collisionShape = IntPtr.Zero;

            Vector3 boundingBox = Vector3Helper.GetDimensions(physObj.Model.MinimumBoundingBox);

            float[] dim          = new float[3];
            float[] top          = new float[3];
            float[] bottom       = new float[3];
            float[] vertexCloud  = null;
            float   radius       = 0;
            float   height       = 0;
            float   convexRadius = 0.05f;

            if (physObj is HavokObject)
            {
                convexRadius = ((HavokObject)physObj).ConvexRadius;
            }

            switch (physObj.Shape)
            {
            case ShapeType.Box:
                if (physObj.ShapeData.Count == 3)
                {
                    dim[0] = physObj.ShapeData[0];
                    dim[1] = physObj.ShapeData[1];
                    dim[2] = physObj.ShapeData[2];
                }
                else
                {
                    dim[0] = boundingBox.X * scale.X;
                    dim[1] = boundingBox.Y * scale.Y;
                    dim[2] = boundingBox.Z * scale.Z;
                }

                collisionShape = HavokDllBridge.create_box_shape(dim, convexRadius);

                break;

            case ShapeType.Sphere:
                if (physObj.ShapeData.Count == 1)
                {
                    radius = physObj.ShapeData[0];
                }
                else
                {
                    radius = boundingBox.X * scale.X / 2;
                }

                collisionShape = HavokDllBridge.create_sphere_shape(radius);

                break;

            case ShapeType.Capsule:
            case ShapeType.Cylinder:
                if (physObj.ShapeData.Count == 2)
                {
                    radius = physObj.ShapeData[0];
                    height = physObj.ShapeData[1];
                }
                else
                {
                    radius = boundingBox.X * scale.X / 2;
                    height = boundingBox.Y * scale.Y;
                }

                if (physObj.Shape == ShapeType.Capsule)
                {
                    top[1]         = height / 2 - radius;
                    bottom[1]      = -height / 2 + radius;
                    collisionShape = HavokDllBridge.create_capsule_shape(top, bottom, radius);
                }
                else
                {
                    top[1]         = height / 2;
                    bottom[1]      = -height / 2;
                    collisionShape = HavokDllBridge.create_cylinder_shape(top, bottom, radius, convexRadius);
                }

                break;

            case ShapeType.Cone:
                throw new GoblinException("Cone shape is not supported by Havok physics");

            case ShapeType.ChamferCylinder:
                throw new GoblinException("ChamferCylinder is not supported by Havok physics");

            case ShapeType.ConvexHull:
                List <Vector3> vertices = physObj.MeshProvider.Vertices;
                vertexCloud = new float[vertices.Count * 3];
                for (int i = 0; i < vertices.Count; i++)
                {
                    vertexCloud[i * 3]     = vertices[i].X * scale.X;
                    vertexCloud[i * 3 + 1] = vertices[i].Y * scale.Y;
                    vertexCloud[i * 3 + 2] = vertices[i].Z * scale.Z;
                }

                collisionShape = HavokDllBridge.create_convex_shape(vertices.Count, vertexCloud,
                                                                    sizeof(float) * 3, convexRadius);

                break;

            case ShapeType.TriangleMesh:
                if (physObj.MeshProvider == null)
                {
                    throw new GoblinException("MeshProvider cannot be null to construct TriangleMesh shape");
                }

                List <int> indices = physObj.MeshProvider.Indices;
                vertices = physObj.MeshProvider.Vertices;

                vertexCloud = new float[vertices.Count * 3];
                for (int i = 0; i < vertices.Count; i++)
                {
                    vertexCloud[i * 3]     = vertices[i].X * scale.X;
                    vertexCloud[i * 3 + 1] = vertices[i].Y * scale.Y;
                    vertexCloud[i * 3 + 2] = vertices[i].Z * scale.Z;
                }

                collisionShape = HavokDllBridge.create_mesh_shape(vertices.Count, vertexCloud,
                                                                  sizeof(float) * 3, indices.Count / 3, indices.ToArray(), convexRadius);

                break;

            case ShapeType.Compound:
                break;
            }

            if (physObj is HavokObject)
            {
                if (((HavokObject)physObj).IsPhantom)
                {
                    collisionShape = HavokDllBridge.create_phantom_shape(collisionShape,
                                                                         ((HavokObject)physObj).PhantomEnterCallback,
                                                                         ((HavokObject)physObj).PhantomLeaveCallback);
                }
            }

            return(collisionShape);
        }
Ejemplo n.º 3
0
 public Vector3 getDimensions()
 {
     return(Vector3Helper.GetDimensions(geomNode.Model.MinimumBoundingBox));
 }
Ejemplo n.º 4
0
 public float getZDim()
 {
     return(Vector3Helper.GetDimensions(geomNode.Model.MinimumBoundingBox).Z);
 }
Ejemplo n.º 5
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;
        }