private void UpdateTransforms(SimulateMethodArgs args) { MataliPhysicsObject mataliPhysicsObj = scene.Factory.PhysicsObjectManager.Get(args.OwnerIndex); mataliPhysicsObj.MainWorldTransform.GetTransformMatrix(ref tempMat1); ((IPhysicsObject)mataliPhysicsObj.UserTagObj).PhysicsWorldTransform = tempMat1; }
private void BoxCollideWithGround(MataliPhysicsObject baseObject, MataliPhysicsObject collidingObject) { String materialName = ((IPhysicsObject)collidingObject.UserTagObj).MaterialName; if (materialName.Equals("Ground")) { // Set the collision sound volume based on the contact speed SoundEffectInstance instance = Sound.Instance.PlaySoundEffect(bounceSound); // Print a text message on the screen Notifier.AddMessage("Contact with ground"); // Create a 3D text to be rendered Text3DInfo text3d = new Text3DInfo(); text3d.Text = "BOOM!!"; // The larger the contact speed, the longer the 3D text will stay displayed text3d.Duration = 1 * 500; text3d.ElapsedTime = 0; Vector3 contactPosition = Vector3.Zero; baseObject.MainWorldTransform.GetPosition(ref contactPosition); // Scale down the vector font since it's quite large, and display the text // above the contact position text3d.Transform = Matrix.CreateScale(0.03f) * Matrix.CreateTranslation(contactPosition + Vector3.UnitY * 4); // Add this 3D text to the display list text3ds.Add(text3d); } }
/// <summary> /// Performs raycast picking with the given near and far points. /// </summary> /// <param name="nearPoint">The near point of the pick ray</param> /// <param name="farPoint">The far point of the pick ray</param> /// <returns>A list of picked objects</returns> public List <PickedObject> PickRayCast(Vector3 nearPoint, Vector3 farPoint) { pickedObjects.Clear(); Vector3 rayDirection = (farPoint - nearPoint); rayDirection.Normalize(); scene.UpdatePhysicsObjectsIntersectedByRay(ref nearPoint, ref rayDirection, 0, false); int objectsCollided = scene.IntersectedPhysicsObjectsCount; Vector3 hitPosition = Vector3.Zero; for (int i = 0; i < objectsCollided; i++) { MataliPhysicsObject obj = scene.GetIntersectedPhysicsObject(i, ref hitPosition); IPhysicsObject physObj = GetIPhysicsObject(obj); if (physObj != null && physObj.Pickable) { PickedObject pickedObject = new PickedObject(physObj, i); pickedObjects.Add(pickedObject); } } return(pickedObjects); }
private void CheckCollision(CollisionMethodArgs args) { MataliPhysicsObject mataliPhysicsObj = scene.Factory.PhysicsObjectManager.Get(args.OwnerIndex); MataliObject mataliObj = (MataliObject)mataliPhysicsObj.UserTagObj; Dictionary <MataliPhysicsObject, bool> table = collisionTable[mataliPhysicsObj]; for (int i = 0; i < args.Collisions.Count; i++) { MataliPhysicsObject collidingObject = scene.Factory.PhysicsObjectManager.Get(args.Collisions[i]); if (table.ContainsKey(collidingObject)) { if (mataliObj.CollisionContinueCallback != null) { mataliObj.CollisionContinueCallback(mataliPhysicsObj, collidingObject); } } else { table.Add(collidingObject, true); if (mataliObj.CollisionStartCallback != null) { mataliObj.CollisionStartCallback(mataliPhysicsObj, collidingObject); } } } }
/// <summary> /// Modifies an existing height map field with short arrays. /// </summary> /// <param name="physObj"></param> /// <param name="heightmap"></param> /// <param name="width"></param> /// <param name="height"></param> public void ModifyHeightmapShort(IPhysicsObject physObj, short[] heightmap, int width, int height) { if (!objectIDs.ContainsKey(physObj)) { return; } MataliPhysicsObject mataliPhysicsObj = objectIDs[physObj]; if (mataliPhysicsObj.InternalControllers.HeightmapController == null) { return; } int index = 0; for (int i = 0; i < height; ++i) { for (int j = 0; j < width; ++j, index++) { mataliPhysicsObj.InternalControllers.HeightmapController.SetHeight(i, j, heightmap[index]); } } mataliPhysicsObj.InternalControllers.HeightmapController.UpdateBounding(); }
protected override void obj_collision_done(MataliPhysicsObject baseObject, MataliPhysicsObject collidingObject) { SoundEffectInstance instance = Sound.Instance.PlaySoundEffect(bounceSound); baseObject.MainWorldTransform.GetLinearVelocity(ref linear_velocity); linear_velocity = Vector3.Normalize(linear_velocity) * scaling_const; baseObject.MainWorldTransform.SetLinearVelocity(linear_velocity); }
public void SetRotation(IPhysicsObject physObj, Quaternion rotation) { if (objectIDs.ContainsKey(physObj)) { MataliPhysicsObject mataliObj = objectIDs[physObj]; mataliObj.MainWorldTransform.SetRotation(Matrix.CreateFromQuaternion(rotation)); mataliObj.RecalculateMainTransform(); } }
public void SetPosition(IPhysicsObject physObj, Vector3 position) { if (objectIDs.ContainsKey(physObj)) { MataliPhysicsObject mataliObj = objectIDs[physObj]; mataliObj.MainWorldTransform.SetPosition(position); mataliObj.RecalculateMainTransform(); } }
public void SetTransform(IPhysicsObject physObj, Matrix transform) { if (objectIDs.ContainsKey(physObj)) { MataliPhysicsObject mataliObj = objectIDs[physObj]; mataliObj.MainWorldTransform.SetTransformMatrix(transform); mataliObj.RecalculateMainTransform(); } }
protected override void obj_collision_done(MataliPhysicsObject baseObject, MataliPhysicsObject collidingObject) { String materialName = ((IPhysicsObject)collidingObject.UserTagObj).MaterialName; if (materialName.Equals("ball")) { point_scored = true; } }
protected override void obj_collision_done(MataliPhysicsObject baseObject, MataliPhysicsObject collidingObject) { String materialName = ((IPhysicsObject)collidingObject.UserTagObj).MaterialName; if (materialName.Equals("slime")) { obtained = true; timeAlive = 0; } baseObject.MainWorldTransform.SetLinearVelocity(Vector3.Zero); }
public BoundingBox GetAxisAlignedBoundingBox(IPhysicsObject physObj) { BoundingBox aabb = new BoundingBox(); if (objectIDs.ContainsKey(physObj)) { MataliPhysicsObject mataliPhysicsObj = objectIDs[physObj]; mataliPhysicsObj.GetBoundingBox(ref aabb); } return(aabb); }
public IPhysicsObject GetIPhysicsObject(MataliPhysicsObject matPhysObj) { foreach (KeyValuePair <IPhysicsObject, MataliPhysicsObject> pair in objectIDs) { if (matPhysObj.Equals(pair.Value)) { return(pair.Key); } } return(null); }
public List <List <Vector3> > GetCollisionMesh(IPhysicsObject physObj) { List <List <Vector3> > collisionMesh = new List <List <Vector3> >(); Matrix mat; if (objectIDs.ContainsKey(physObj)) { MataliPhysicsObject mataliPhysicsObj = objectIDs[physObj]; if (mataliPhysicsObj.Shape == null) { return(collisionMesh); } mat = physObj.PhysicsWorldTransform; if ((physObj is MataliObject) && (((MataliObject)physObj).ShapeOriginalMatrixSet)) { mat = ((MataliObject)physObj).ShapeOriginalMatrix * mat; } if (mataliPhysicsObj.Shape.TriangleVertexCount > 0) { VertexPositionNormalTexture[] verts = new VertexPositionNormalTexture[mataliPhysicsObj.Shape.VertexCount]; int[] indices = new int[mataliPhysicsObj.Shape.IndexCount]; mataliPhysicsObj.Shape.GetMeshVertices(1, 1, false, false, verts); mataliPhysicsObj.Shape.GetMeshIndices(false, indices); if (!mat.Equals(Matrix.Identity)) { for (int i = 0; i < verts.Length; ++i) { verts[i].Position = Vector3.Transform(verts[i].Position, mat); } } for (int i = 0; i < indices.Length; i += 3) { List <Vector3> triangle = new List <Vector3>(); triangle.Add(verts[indices[i]].Position); triangle.Add(verts[indices[i + 1]].Position); triangle.Add(verts[indices[i + 2]].Position); collisionMesh.Add(triangle); } } } return(collisionMesh); }
public void RemovePhysicsObject(IPhysicsObject physObj) { if (objectIDs.ContainsKey(physObj)) { MataliPhysicsObject mataliPhysicsObj = objectIDs[physObj]; scene.RemovePhysicsObject(mataliPhysicsObj, true, true); collisionTable.Remove(mataliPhysicsObj); foreach (MataliPhysicsObject obj in collisionTable.Keys) { if (collisionTable[obj].ContainsKey(mataliPhysicsObj)) { collisionTable[obj].Remove(mataliPhysicsObj); } } objectIDs.Remove(physObj); } }
protected override void obj_collision_start(MataliPhysicsObject baseObject, MataliPhysicsObject collidingObject) { }
public void AddPhysicsObject(IPhysicsObject physObj) { if (objectIDs.ContainsKey(physObj)) { return; } // rigidbody is dynamic if and only if mass is non zero, otherwise static bool isDynamic = (physObj.Mass != 0.0f && physObj.Interactable) || (physObj.Shape == ShapeType.TriangleMesh); physObj.PhysicsWorldTransform = physObj.CompoundInitialWorldTransform; MataliPhysicsObject mataliPhysicsObj = scene.Factory.PhysicsObjectManager.Create(nameCount.ToString()); if (physObj is MataliVehicle) { MataliVehicle vehicle = (MataliVehicle)physObj; if (!vehicle.HasEnoughParts) { throw new GoblinException("Your vehicle does not have enough parts. You need to at least" + " have a body and four wheels"); } MataliPhysicsObject body = scene.Factory.PhysicsObjectManager.Create("Car Body " + nameCount); body.EnableFeedback = true; body.Material.RigidGroup = true; body.EnableBreakRigidGroup = false; mataliPhysicsObj.AddPhysicsObject(body); // Add vehicle body if (vehicle.Body.Count == 1) { vehicle.Body[0].CompoundInitialWorldTransform = vehicle.Body[0].RelativeTransform; vehicle.Body[0].PhysicsWorldTransform = physObj.CompoundInitialWorldTransform * vehicle.Body[0].RelativeTransform; body.Material.RigidGroup = true; body.EnableBreakRigidGroup = false; SetPhysicalProperties(body, vehicle.Body[0]); objectIDs.Add(vehicle.Body[0], body); } else { for (int i = 0; i < vehicle.Body.Count; ++i) { MataliPhysicsObject bodyPart = scene.Factory.PhysicsObjectManager.Create("Car Body Parts " + nameCount + " " + i); vehicle.Body[i].CompoundInitialWorldTransform = vehicle.Body[i].RelativeTransform; vehicle.Body[i].PhysicsWorldTransform = MatrixHelper.Empty; bodyPart.Material.RigidGroup = true; bodyPart.EnableBreakRigidGroup = false; SetPhysicalProperties(bodyPart, vehicle.Body[i]); body.AddPhysicsObject(bodyPart); objectIDs.Add(vehicle.Body[i], body); } } // Add vehicle wheels for (int i = 0; i < 4; ++i) { for (int j = 0; j < vehicle.Wheels[i].Count; ++j) { MataliPhysicsObject wheelPart = scene.Factory.PhysicsObjectManager.Create("Car Wheel Parts " + nameCount + " " + i + " " + j); vehicle.Wheels[i][j].CompoundInitialWorldTransform = vehicle.Wheels[i][j].RelativeTransform; vehicle.Wheels[i][j].PhysicsWorldTransform = MatrixHelper.Empty; for (int k = 0; k < vehicle.Body.Count; ++k) { wheelPart.DisableCollision(objectIDs[vehicle.Body[k]], true); } SetPhysicalProperties(wheelPart, vehicle.Wheels[i][j]); mataliPhysicsObj.AddPhysicsObject(wheelPart); objectIDs.Add(vehicle.Wheels[i][j], wheelPart); } } mataliPhysicsObj.UpdateFromInitLocalTransform(); if (vehicle.Constraints.Count > 0) { constraintsToBeAdded.AddRange(vehicle.Constraints); } AddConstraint(); } else if (physObj is MataliCloth) { MataliCloth cloth = (MataliCloth)physObj; int i = 0; foreach (MataliObject particle in cloth.Particles) { MataliPhysicsObject clothParticle = scene.Factory.PhysicsObjectManager.Create("Point Cloth " + nameCount + " Particle " + i); mataliPhysicsObj.AddPhysicsObject(clothParticle); SetPhysicalProperties(clothParticle, particle); objectIDs.Add(particle, clothParticle); i++; } mataliPhysicsObj.UpdateFromInitLocalTransform(); constraintsToBeAdded.AddRange(cloth.Constraints); AddConstraint(); } SetPhysicalProperties(mataliPhysicsObj, physObj); scene.UpdateFromInitLocalTransform(mataliPhysicsObj); objectIDs.Add(physObj, mataliPhysicsObj); nameCount++; }
/// <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(flipTriangle, 2, frictions, restitutions, 1.0f, 0.0f, triVerts); } 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; }
private void SetPhysicalProperties(MataliPhysicsObject mataliPhysicsObj, IPhysicsObject physObj) { mataliPhysicsObj.UserTagObj = physObj; mataliPhysicsObj.InitLocalTransform.SetTransformMatrix(physObj.CompoundInitialWorldTransform); mataliPhysicsObj.InitLocalTransform.SetLinearVelocity(physObj.InitialLinearVelocity); mataliPhysicsObj.InitLocalTransform.SetAngularVelocity(physObj.InitialAngularVelocity); mataliPhysicsObj.UserControllers.EnableDraw = false; mataliPhysicsObj.UserControllers.EnablePostDraw = false; if (physObj is MataliObject && ((MataliObject)physObj).PostTransformCallback != null) mataliPhysicsObj.UserControllers.PostTransformMethods += new SimulateMethod(((MataliObject)physObj).PostTransformCallback); if ((physObj is MataliVehicle) || (physObj is MataliCloth)) return; mataliPhysicsObj.UserControllers.PostTransformMethods += new SimulateMethod(UpdateTransforms); SetShape(mataliPhysicsObj, physObj); if (physObj is MataliObject) { if (physObj.Mass > 0) mataliPhysicsObj.Integral.SetMass(physObj.Mass); else mataliPhysicsObj.Integral.SetDensity(((MataliObject)physObj).Density); mataliPhysicsObj.Material.StaticFriction = ((MataliObject)physObj).StaticFriction; mataliPhysicsObj.Material.DynamicFriction = ((MataliObject)physObj).DynamicFriction; mataliPhysicsObj.Material.Restitution = ((MataliObject)physObj).Restitution; mataliPhysicsObj.MaxPreUpdateAngularVelocity = ((MataliObject)physObj).MaxPreUpdateAngularVelocity; mataliPhysicsObj.MaxPostUpdateAngularVelocity = ((MataliObject)physObj).MaxPostUpdateAngularVelocity; mataliPhysicsObj.MinResponseAngularVelocity = ((MataliObject)physObj).MinResponseAngularVelocity; mataliPhysicsObj.MinResponseLinearVelocity = ((MataliObject)physObj).MinResponseLinearVelocity; if ((((MataliObject)physObj).CollisionStartCallback != null) || (((MataliObject)physObj).CollisionContinueCallback != null) || (((MataliObject)physObj).CollisionEndCallback != null)) { mataliPhysicsObj.UserControllers.CollisionMethods += new CollisionMethod(CheckCollision); Dictionary<MataliPhysicsObject, bool> table = new Dictionary<MataliPhysicsObject, bool>(); collisionTable.Add(mataliPhysicsObj, table); } } else mataliPhysicsObj.Integral.SetMass(physObj.Mass); mataliPhysicsObj.EnableCollisions = physObj.Collidable; mataliPhysicsObj.EnableMoving = physObj.Interactable; if (!physObj.ApplyGravity) { mataliPhysicsObj.EnableLocalGravity = true; mataliPhysicsObj.LocalGravityAcceleration = 0; } mataliPhysicsObj.EnableSleeping = !physObj.NeverDeactivate; mataliPhysicsObj.EnableScreenToRayInteraction = physObj.Pickable; }
public IPhysicsObject GetIPhysicsObject(MataliPhysicsObject matPhysObj) { foreach (KeyValuePair<IPhysicsObject, MataliPhysicsObject> pair in objectIDs) { if (matPhysObj.Equals(pair.Value)) { return pair.Key; } } return null; }
protected abstract void obj_collision_done(MataliPhysicsObject baseObject, MataliPhysicsObject collidingObject);
protected override void obj_collision_done(Komires.MataliPhysics.PhysicsObject baseObject, Komires.MataliPhysics.PhysicsObject collidingObject) { }
private void SetPhysicalProperties(MataliPhysicsObject mataliPhysicsObj, IPhysicsObject physObj) { mataliPhysicsObj.UserTagObj = physObj; mataliPhysicsObj.InitLocalTransform.SetTransformMatrix(physObj.CompoundInitialWorldTransform); mataliPhysicsObj.InitLocalTransform.SetLinearVelocity(physObj.InitialLinearVelocity); mataliPhysicsObj.InitLocalTransform.SetAngularVelocity(physObj.InitialAngularVelocity); mataliPhysicsObj.UserControllers.EnableDraw = false; mataliPhysicsObj.UserControllers.EnablePostDraw = false; if (physObj is MataliObject && ((MataliObject)physObj).PostTransformCallback != null) { mataliPhysicsObj.UserControllers.PostTransformMethods += new SimulateMethod(((MataliObject)physObj).PostTransformCallback); } if ((physObj is MataliVehicle) || (physObj is MataliCloth)) { return; } mataliPhysicsObj.UserControllers.PostTransformMethods += new SimulateMethod(UpdateTransforms); SetShape(mataliPhysicsObj, physObj); if (physObj is MataliObject) { if (physObj.Mass > 0) { mataliPhysicsObj.Integral.SetMass(physObj.Mass); } else { mataliPhysicsObj.Integral.SetDensity(((MataliObject)physObj).Density); } mataliPhysicsObj.Material.StaticFriction = ((MataliObject)physObj).StaticFriction; mataliPhysicsObj.Material.DynamicFriction = ((MataliObject)physObj).DynamicFriction; mataliPhysicsObj.Material.Restitution = ((MataliObject)physObj).Restitution; mataliPhysicsObj.MaxPreUpdateAngularVelocity = ((MataliObject)physObj).MaxPreUpdateAngularVelocity; mataliPhysicsObj.MaxPostUpdateAngularVelocity = ((MataliObject)physObj).MaxPostUpdateAngularVelocity; mataliPhysicsObj.MinResponseAngularVelocity = ((MataliObject)physObj).MinResponseAngularVelocity; mataliPhysicsObj.MinResponseLinearVelocity = ((MataliObject)physObj).MinResponseLinearVelocity; if ((((MataliObject)physObj).CollisionStartCallback != null) || (((MataliObject)physObj).CollisionContinueCallback != null) || (((MataliObject)physObj).CollisionEndCallback != null)) { mataliPhysicsObj.UserControllers.CollisionMethods += new CollisionMethod(CheckCollision); Dictionary <MataliPhysicsObject, bool> table = new Dictionary <MataliPhysicsObject, bool>(); collisionTable.Add(mataliPhysicsObj, table); } } else { mataliPhysicsObj.Integral.SetMass(physObj.Mass); } mataliPhysicsObj.EnableCollisions = physObj.Collidable; mataliPhysicsObj.EnableMoving = physObj.Interactable; if (!physObj.ApplyGravity) { mataliPhysicsObj.EnableLocalGravity = true; mataliPhysicsObj.LocalGravityAcceleration = 0; } mataliPhysicsObj.EnableSleeping = !physObj.NeverDeactivate; mataliPhysicsObj.EnableScreenToRayInteraction = physObj.Pickable; }
/// <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; }