コード例 #1
0
        public virtual void Update(float elapsedTime)
        {
            if (pauseSimulation)
            {
                return;
            }

            elapsedTime *= simulationSpeed;

            if (numSubSteps > 1)
            {
                int updateTime = Math.Max((int)(Math.Round(elapsedTime / simulationTimeStep)), 1);
                updateTime = Math.Min(numSubSteps, updateTime);
                for (int i = 0; i < updateTime; i++)
                {
                    HavokDllBridge.update(simulationTimeStep);
                }
            }
            else
            {
                HavokDllBridge.update(elapsedTime);
            }

            IntPtr bodyPtr      = Marshal.AllocHGlobal(objectIDs.Count * sizeof(int));
            IntPtr transformPtr = Marshal.AllocHGlobal(objectIDs.Count * sizeof(float) * 16);

            int totalSize = 0;

            HavokDllBridge.get_updated_transforms(bodyPtr, transformPtr, ref totalSize);

            unsafe
            {
                int *   bodyAddr = (int *)bodyPtr;
                IntPtr  tmpPtr   = transformPtr;
                float[] mat      = new float[16];
                IntPtr  body     = IntPtr.Zero;
                for (int i = 0; i < totalSize; i++)
                {
                    body = new IntPtr(*bodyAddr);
                    if (reverseIDs.ContainsKey(body))
                    {
                        tmpVec1 = scaleTable[body];

                        Matrix.CreateScale(ref tmpVec1, out tmpMat1);

                        Marshal.Copy(tmpPtr, mat, 0, mat.Length);
                        MatrixHelper.FloatsToMatrix(mat, out tmpMat2);

                        Matrix.Multiply(ref tmpMat1, ref tmpMat2, out tmpMat1);
                        reverseIDs[body].PhysicsWorldTransform = tmpMat1;
                    }

                    tmpPtr = new IntPtr(tmpPtr.ToInt32() + sizeof(float) * 16);
                    bodyAddr++;
                }
            }

            Marshal.FreeHGlobal(bodyPtr);
            Marshal.FreeHGlobal(transformPtr);
        }
コード例 #2
0
 public void Dispose()
 {
     HavokDllBridge.dispose();
     objectIDs.Clear();
     reverseIDs.Clear();
     scaleTable.Clear();
 }
コード例 #3
0
        public void SetAngularVelocity(IPhysicsObject physObj, Vector3 velocity)
        {
            if (!objectIDs.ContainsKey(physObj))
            {
                return;
            }

            HavokDllBridge.set_angular_velocity(objectIDs[physObj], Vector3Helper.ToFloats(velocity));
        }
コード例 #4
0
        public void AddTorque(IPhysicsObject physObj, float timeStep, Vector3 torque)
        {
            if (!objectIDs.ContainsKey(physObj))
            {
                return;
            }

            HavokDllBridge.add_torque(objectIDs[physObj], timeStep, Vector3Helper.ToFloats(torque));
        }
コード例 #5
0
        public Vector3 GetAngularVelocity(IPhysicsObject physObj)
        {
            if (!objectIDs.ContainsKey(physObj))
            {
                return(Vector3.Zero);
            }

            float[] velocity = new float[3];
            HavokDllBridge.get_angular_velocity(objectIDs[physObj], velocity);
            return(new Vector3(velocity[0], velocity[1], velocity[2]));
        }
コード例 #6
0
        public Vector3 GetPosition(IPhysicsObject physObj)
        {
            if (!objectIDs.ContainsKey(physObj))
            {
                return(Vector3.Zero);
            }

            float[] position = new float[3];
            HavokDllBridge.get_body_position(objectIDs[physObj], position);
            return(Vector3Helper.FromFloats(position));
        }
コード例 #7
0
        public void RemovePhysicsObject(IPhysicsObject physObj)
        {
            if (objectIDs.ContainsKey(physObj))
            {
                HavokDllBridge.remove_rigid_body(objectIDs[physObj]);

                reverseIDs.Remove(objectIDs[physObj]);
                scaleTable.Remove(objectIDs[physObj]);
                objectIDs.Remove(physObj);
            }
        }
コード例 #8
0
        public Quaternion GetRotation(IPhysicsObject physObj)
        {
            if (!objectIDs.ContainsKey(physObj))
            {
                return(Quaternion.Identity);
            }

            float[] rotation = new float[4];
            HavokDllBridge.get_body_rotation(objectIDs[physObj], rotation);
            return(new Quaternion(rotation[0], rotation[1], rotation[2], rotation[3]));
        }
コード例 #9
0
        public Matrix GetTransform(IPhysicsObject physObj)
        {
            if (!objectIDs.ContainsKey(physObj))
            {
                return(Matrix.Identity);
            }

            float[] transform = new float[16];
            HavokDllBridge.get_body_transform(objectIDs[physObj], transform);
            return(MatrixHelper.FloatsToMatrix(transform));
        }
コード例 #10
0
        public void InitializePhysics()
        {
            Vector3 g = info.Gravity * info.GravityDirection;

            if (!HavokDllBridge.init_world(Vector3Helper.ToFloats(g), info.WorldSize,
                                           info.CollisionTolerance, info.HavokSimulationType, info.HavokSolverType,
                                           info.FireCollisionCallbacks, info.EnableDeactivation))
            {
                throw new GoblinException("Failed to initialize Havok physics");
            }
        }
コード例 #11
0
        public void ApplyHardKeyFrame(IPhysicsObject physObj, Vector3 newPos, Quaternion newRot, float timeStep)
        {
            if (!objectIDs.ContainsKey(physObj))
            {
                return;
            }

            float[] pos = Vector3Helper.ToFloats(ref newPos);
            float[] rot = { newRot.X, newRot.Y, newRot.Z, newRot.W };

            HavokDllBridge.apply_hard_keyframe(objectIDs[physObj], pos, rot, timeStep);
        }
コード例 #12
0
        public BoundingBox GetAxisAlignedBoundingBox(IPhysicsObject physObj)
        {
            if (!objectIDs.ContainsKey(physObj))
            {
                return(new BoundingBox());
            }

            float[] min = new float[3];
            float[] max = new float[3];
            HavokDllBridge.get_AABB(objectIDs[physObj], min, max);
            Vector3Helper.FromFloats(min, out tmpVec1);
            Vector3Helper.FromFloats(max, out tmpVec2);

            return(new BoundingBox(tmpVec1, tmpVec2));
        }
コード例 #13
0
        public void RestartsSimulation()
        {
            HavokDllBridge.dispose();

            InitializePhysics();

            List <IPhysicsObject> physObjs = new List <IPhysicsObject>(objectIDs.Keys);

            objectIDs.Clear();
            reverseIDs.Clear();
            scaleTable.Clear();

            foreach (IPhysicsObject physObj in physObjs)
            {
                AddPhysicsObject(physObj);
            }
        }
コード例 #14
0
        public void StopKeyframe(IPhysicsObject physObj)
        {
            if (!objectIDs.ContainsKey(physObj))
            {
                return;
            }

            Vector3    scale, trans;
            Quaternion quat;

            physObj.PhysicsWorldTransform.Decompose(out scale, out quat, out trans);

            float[] pos = Vector3Helper.ToFloats(ref trans);
            float[] rot = { quat.X, quat.Y, quat.Z, quat.W };

            HavokDllBridge.apply_hard_keyframe(objectIDs[physObj], pos, rot, 0.016f);
        }
コード例 #15
0
        public void ApplySoftKeyFrame(IPhysicsObject physObj, Vector3 newPos, Quaternion newRot,
                                      Vector3 angularPositionFactor, Vector3 angularVelocityFactor, Vector3 linearPositionFactor,
                                      Vector3 linearVelocityFactor, float maxAngularAcceleration, float maxLinearAcceleration,
                                      float maxAllowedDistance, float timeStep)
        {
            if (!objectIDs.ContainsKey(physObj))
            {
                return;
            }

            float[] pos           = Vector3Helper.ToFloats(ref newPos);
            float[] rot           = { newRot.X, newRot.Y, newRot.Z, newRot.W };
            float[] angularPosFac = Vector3Helper.ToFloats(ref angularPositionFactor);
            float[] angularVelFac = Vector3Helper.ToFloats(ref angularVelocityFactor);
            float[] linearPosFac  = Vector3Helper.ToFloats(ref linearPositionFactor);
            float[] linearVelFac  = Vector3Helper.ToFloats(ref linearVelocityFactor);

            HavokDllBridge.apply_soft_keyframe(objectIDs[physObj], pos, rot, angularPosFac,
                                               angularVelFac, linearPosFac, linearVelFac, maxAngularAcceleration,
                                               maxLinearAcceleration, maxAllowedDistance, timeStep);
        }
コード例 #16
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);
        }
コード例 #17
0
 public void SetBodyWorldLeaveCallback(HavokDllBridge.BodyLeaveWorldCallback callback)
 {
     HavokDllBridge.add_world_leave_callback(callback);
 }
コード例 #18
0
        public void AddPhysicsObject(IPhysicsObject physObj)
        {
            if (objectIDs.ContainsKey(physObj))
            {
                return;
            }

            physObj.PhysicsWorldTransform = physObj.CompoundInitialWorldTransform;

            HavokPhysics.MotionType            motionType  = MotionType.MOTION_INVALID;
            HavokPhysics.CollidableQualityType qualityType =
                CollidableQualityType.COLLIDABLE_QUALITY_INVALID;
            float friction                = -1;
            float restitution             = -1;
            float maxLinearVelocity       = -1;
            float maxAngularVelocity      = -1;
            float allowedPenetrationDepth = -1;
            float gravityFactor           = 1;

            if ((physObj is HavokObject))
            {
                HavokObject havokObj = (HavokObject)physObj;
                motionType              = havokObj.MotionType;
                qualityType             = havokObj.QualityType;
                friction                = havokObj.Friction;
                restitution             = havokObj.Restitution;
                maxLinearVelocity       = havokObj.MaxLinearVelocity;
                maxAngularVelocity      = havokObj.MaxAngularVelocity;
                allowedPenetrationDepth = havokObj.AllowedPenetrationDepth;
                gravityFactor           = havokObj.GravityFactor;
            }
            else
            {
                bool isDynamic = (physObj.Mass != 0.0f && physObj.Interactable);
                if (isDynamic)
                {
                    motionType = MotionType.MOTION_DYNAMIC;
                }
                else
                {
                    motionType = MotionType.MOTION_FIXED;
                }
            }

            Quaternion rotation;
            Vector3    trans;
            Vector3    scale;

            physObj.CompoundInitialWorldTransform.Decompose(out scale, out rotation, out trans);

            IntPtr shape = GetCollisionShape(physObj, scale);

            float[] pos = Vector3Helper.ToFloats(ref trans);
            float[] rot = { rotation.X, rotation.Y, rotation.Z, rotation.W };

            IntPtr body = HavokDllBridge.add_rigid_body(shape, physObj.Mass, motionType, qualityType,
                                                        pos, rot, Vector3Helper.ToFloats(physObj.InitialLinearVelocity), physObj.LinearDamping,
                                                        maxLinearVelocity, Vector3Helper.ToFloats(physObj.InitialAngularVelocity),
                                                        physObj.AngularDamping.X, maxAngularVelocity, friction, restitution,
                                                        allowedPenetrationDepth, physObj.NeverDeactivate, gravityFactor);

            objectIDs.Add(physObj, body);
            reverseIDs.Add(body, physObj);
            scaleTable.Add(body, scale);

            if ((physObj is HavokObject))
            {
                if (((HavokObject)physObj).ContactCallback != null ||
                    ((HavokObject)physObj).CollisionStartCallback != null ||
                    ((HavokObject)physObj).CollisionEndCallback != null)
                {
                    HavokDllBridge.add_contact_listener(body, ((HavokObject)physObj).ContactCallback,
                                                        ((HavokObject)physObj).CollisionStartCallback,
                                                        ((HavokObject)physObj).CollisionEndCallback);
                }
            }
        }