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); }
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); }
public Vector3 getDimensions() { return(Vector3Helper.GetDimensions(geomNode.Model.MinimumBoundingBox)); }
public float getZDim() { return(Vector3Helper.GetDimensions(geomNode.Model.MinimumBoundingBox).Z); }
/// <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; }