Esempio n. 1
0
        /// <summary>
        /// Initialization of the rigid-body
        /// </summary>
        public override void Awake()
        {
            CalculateShape(ShapeType.Box);

            RigidBody = new SteerableCollider(CollisionShape)
            {
                Position      = Conversion.ToJitterVector(transform.position),
                Orientation   = JMatrix.CreateFromQuaternion(Conversion.ToJitterQuaternion(transform.rotation)),
                CenterOfMass  = CenterOfMass,
                IsStatic      = IsStatic,
                IsActive      = IsActive,
                Tag           = BodyTag.DrawMe,
                Mass          = 20.0f,
                GameObject    = gameObject,
                SyncedObjects = SyncedObjects,
                Material      = new Jitter.Dynamics.Material {
                    KineticFriction = 1.0f, Restitution = 1.0f, StaticFriction = 1.0f
                }
            };

            StartOrientation = RigidBody.Orientation;
            StartPosition    = RigidBody.Position;

            PhysicsManager.Instance.World.AddBody(RigidBody);
        }
Esempio n. 2
0
        /// <summary>
        /// Initialization of the rigid-body
        /// </summary>
        public override void Awake()
        {
            CalculateShape(ShapeType);

            RigidBody = new Collider(CollisionShape)
            {
                Position      = Conversion.ToJitterVector(transform.position) + CenterOfMass,
                Orientation   = JMatrix.CreateFromQuaternion(Conversion.ToJitterQuaternion(transform.rotation)),
                CenterOfMass  = CenterOfMass,
                IsStatic      = IsStatic,
                IsActive      = IsActive,
                IsAnimated    = IsAnimated,
                Tag           = Tag,
                PureCollider  = PureCollider,
                GameObject    = gameObject,
                SyncedObjects = new List <Follower>(),
                Material      = new Jitter.Dynamics.Material {
                    KineticFriction = 10.0f, Restitution = 0.0f, StaticFriction = 10.0f
                },
                Mass = 20.0f
            };

            StartPosition    = RigidBody.Position;
            StartOrientation = RigidBody.Orientation;

            PhysicsManager.Instance.World.AddBody(RigidBody);

            if (ShapeType == ShapeType.BoxInvisible)
            {
                gameObject.Model = null;
            }

            base.Awake();
        }
Esempio n. 3
0
        public void RegisterDetail(DetailObject obj)
        {
            if (this.HasDetail(obj.ID))
            {
                throw new InvalidOperationException();
            }

            obj.Changed += Obj_Changed;
            obj.InteractionTriggered += Obj_InterationTriggered;
            this.details.Add(obj);

            if (obj.Shape != null)
            {
                var body = new RigidBody(obj.Shape);
                body.Position        = obj.WorldPosition.Jitter();
                body.Orientation     = JMatrix.CreateFromQuaternion(obj.WorldRotation.Jitter());
                body.IsStatic        = true;
                body.Tag             = obj;
                body.EnableDebugDraw = true;
                body.Material        = this.blockMaterial;
                this.detailBodies.Add(obj.ID, body);

                this.AddBody(body);

                obj.PositionChanged += (s, e) =>
                {
                    body.Position    = obj.WorldPosition.Jitter();
                    body.Orientation = JMatrix.CreateFromQuaternion(obj.WorldRotation.Jitter());
                };
            }

            this.OnDetailCreated(obj);
        }
Esempio n. 4
0
        private void SetTransform(ScalableTransform t)
        {
            storedScale = t.Scale;
            var tr      = new Transform(t.Rotation, t.Translation);
            var current = tr * baseTransform.Invert();

            Body.Position    = current.Translation.ToJVector();
            Body.Orientation = JMatrix.CreateFromQuaternion(current.Rotation.ToQuaternion());
        }
        public void CopyState()
        {
            var position = gameObject.transform.position;
            var rotation = gameObject.transform.rotation;

            rigidBody.Position = new JVector(position.X, position.Y, position.Z);
            // NOTE(francois): I tried using JMatrix.CreateFromAxisAngle and it did not work (both in rad and deg).
            rigidBody.Orientation = JMatrix.CreateFromQuaternion(new JQuaternion(rotation.X, rotation.Y, rotation.Z, rotation.W));
            rigidBody.IsStatic    = isStatic;
        }
Esempio n. 6
0
        private void IntegrateCallback(object obj)
        {
            RigidBody body = obj as RigidBody;

            JVector temp;

            JVector.Multiply(ref body.linearVelocity, timestep, out temp);
            JVector.Add(ref temp, ref body.position, out body.position);

            if (!(body.isParticle))
            {
                //exponential map
                JVector axis;
                double  angle = body.angularVelocity.Length();

                if (angle < 0.001f)
                {
                    // use Taylor's expansions of sync function
                    // axis = body.angularVelocity * (0.5f * timestep - (timestep * timestep * timestep) * (0.020833333333f) * angle * angle);
                    JVector.Multiply(ref body.angularVelocity, (0.5f * timestep - (timestep * timestep * timestep) * (0.020833333333f) * angle * angle), out axis);
                }
                else
                {
                    // sync(fAngle) = sin(c*fAngle)/t
                    JVector.Multiply(ref body.angularVelocity, ((double)Math.Sin(0.5f * angle * timestep) / angle), out axis);
                }

                JQuaternion dorn = new JQuaternion(axis.X, axis.Y, axis.Z, (double)Math.Cos(angle * timestep * 0.5f));
                JQuaternion ornA; JQuaternion.CreateFromMatrix(ref body.orientation, out ornA);

                JQuaternion.Multiply(ref dorn, ref ornA, out dorn);

                dorn.Normalize(); JMatrix.CreateFromQuaternion(ref dorn, out body.orientation);
            }

            if ((body.Damping & RigidBody.DampingType.Linear) != 0)
            {
                JVector.Multiply(ref body.linearVelocity, currentLinearDampFactor, out body.linearVelocity);
            }

            if ((body.Damping & RigidBody.DampingType.Angular) != 0)
            {
                JVector.Multiply(ref body.angularVelocity, currentAngularDampFactor, out body.angularVelocity);
            }

            body.Update();


            if (CollisionSystem.EnableSpeculativeContacts || body.EnableSpeculativeContacts)
            {
                body.SweptExpandBoundingBox(timestep);
            }
        }
Esempio n. 7
0
        public void RestoreState(BinaryReader reader)
        {
            Body.Position = new JVector(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
            var q = new JQuaternion(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());

            Body.Orientation = JMatrix.CreateFromQuaternion(q);
            if (Body.IsStatic)
            {
                return;
            }
            Body.LinearVelocity  = new JVector(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
            Body.AngularVelocity = new JVector(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
        }
Esempio n. 8
0
        /// <summary>
        /// Functionality which is applied before the physics is updated
        /// </summary>
        /// <param name="timestep"></param>
        public override void PreStep(float timestep)
        {
            if (IsAnimated)
            {
                _oldRotation = Conversion.ToXnaQuaternion(JQuaternion.CreateFromMatrix(Orientation)).ToEuler().Y;
                _newRotation = GameObject.transform.eulerAngles.Y;

                // First calculate the correct orientation/rotation and then adjust the position with respect to the rotated COM
                Orientation = JMatrix.CreateFromQuaternion(Conversion.ToJitterQuaternion(GameObject.transform.rotation));
                Position    = Conversion.ToJitterVector(GameObject.transform.position) + JVector.Transform(CenterOfMass, Orientation);
            }
            else
            {
                _oldRotation = GameObject.transform.eulerAngles.Y;
            }
        }
Esempio n. 9
0
        protected override void OnAdded(ComponentStateEventArgs registrationArgs)
        {
            base.OnAdded(registrationArgs);
            Body.Tag = Record.Name;
            var offset = Body.Position;
            var rot    = JMatrix.CreateFromQuaternion(transform.Rotation.ToQuaternion());

            JVector.Transform(ref offset, ref rot, out offset);
            Offset           = offset.ToVector3();
            Body.Orientation = Body.Orientation * rot;
            Body.Position    = offset + transform.Translation.ToJVector();
            baseTransform    = new Transform(JQuaternion.CreateFromMatrix(Body.Orientation).ToQuaternion(),
                                             Body.Position.ToVector3()).Invert() * new Transform(transform.Rotation, transform.Translation);
            storedScale = transform.Scale;
            transform.Bind(GetTransform, SetTransform);
        }
Esempio n. 10
0
        private void IntegrateCallback(object obj)
        {
            var body = obj as RigidBody;

            JVector temp;
            JVector.Multiply(ref body.linearVelocity, timestep, out temp);
            JVector.Add(ref temp, ref body.position, out body.position);

            if (!(body.isParticle))
            {
                JVector axis;
                float angle = body.angularVelocity.Length();

                if (angle < 0.001f)
                {
                    JVector.Multiply(ref body.angularVelocity,
                                     (0.5f*timestep - (timestep*timestep*timestep)*(0.020833333333f)*angle*angle),
                                     out axis);
                }
                else
                {
                    JVector.Multiply(ref body.angularVelocity, ((float) Math.Sin(0.5f*angle*timestep)/angle), out axis);
                }

                var dorn = new JQuaternion(axis.X, axis.Y, axis.Z, (float) Math.Cos(angle*timestep*0.5f));
                JQuaternion ornA;
                JQuaternion.CreateFromMatrix(ref body.orientation, out ornA);

                JQuaternion.Multiply(ref dorn, ref ornA, out dorn);

                dorn.Normalize();
                JMatrix.CreateFromQuaternion(ref dorn, out body.orientation);
            }

            if ((body.Damping & RigidBody.DampingType.Linear) != 0)
                JVector.Multiply(ref body.linearVelocity, currentLinearDampFactor, out body.linearVelocity);

            if ((body.Damping & RigidBody.DampingType.Angular) != 0)
                JVector.Multiply(ref body.angularVelocity, currentAngularDampFactor, out body.angularVelocity);

            body.Update();


            if (CollisionSystem.EnableSpeculativeContacts || body.EnableSpeculativeContacts)
                body.SweptExpandBoundingBox(timestep);
        }
Esempio n. 11
0
        private BatchedControlEntity BatchPhysics(IGameContext gameContext, INode node, BatchedControlEntity entity)
        {
            var physicsComponentsToProcess = new List <Tuple <INode, PhysicalBaseRigidBodyComponent> >();

            FindPhysicsComponentsUnderNode(node, physicsComponentsToProcess);

            var transformedShapes = new List <CompoundShape.TransformedShape>();

            foreach (var pair in physicsComponentsToProcess)
            {
                foreach (var body in pair.Item2.RigidBodies)
                {
                    transformedShapes.Add(new CompoundShape.TransformedShape(
                                              body.Shape,
                                              JMatrix.CreateFromQuaternion(pair.Item2.FinalTransform.AbsoluteRotation.ToJitterQuaternion()),
                                              pair.Item2.FinalTransform.AbsolutePosition.ToJitterVector()));
                }
            }

            if (transformedShapes.Count == 0)
            {
                return(entity);
            }

            var compoundShape = new CompoundShape(transformedShapes);

            if (entity == null)
            {
                entity = CreateBatchedControlEntity();
            }

            foreach (var pair in physicsComponentsToProcess)
            {
                pair.Item2.SetBatchedEntity(entity);
            }

            entity.AttachBatchedPhysics(compoundShape);

            _hierarchy.MoveNode(node, _hierarchy.Lookup(entity));

            _consoleHandle.LogInfo("Batching physics objected combined " + transformedShapes.Count + " shapes.");

            return(entity);
        }
Esempio n. 12
0
        /// <summary>
        /// Single threaded.
        /// </summary>
        /// <param name="spawnable_idx"></param>
        /// <returns></returns>
        protected KeyValuePair <int, RigidBody> SpawnObject(int spawnable_idx, JVector?pos = null, JVector?vel = null, JQuaternion?ori = null)
        {
            var rb = new RigidBody(spawnable_rigid_bodies[spawnable_idx].Shape);

            if (pos.HasValue)
            {
                rb.Position = pos.Value;
            }
            if (vel.HasValue)
            {
                rb.LinearVelocity = vel.Value;
            }
            if (ori.HasValue)
            {
                rb.Orientation = JMatrix.CreateFromQuaternion(ori.Value);
            }
            for (;;)
            {
                var id = random.Next(startobject_high_edge, int.MaxValue);
                if (!objects.ContainsKey(id))
                {
                    add_to_world(id, spawnable_idx, rb);
                    var ev = new Event3D
                    {
                        ObjectNotification = new Event3D_ObjectNotification
                        {
                            Id        = id,
                            SpawnId   = spawnable_idx,
                            Spawn     = true,
                            Transform = ArenaServiceConv.ToArenaTransform(rb)
                        }
                    };
                    send_to_all_players(ev);
                    return(new KeyValuePair <int, RigidBody>(id, rb));
                }
            }
        }
 public static JMatrix ToJMatrix(this Quaternion rot)
 {
     return(JMatrix.CreateFromQuaternion(rot.ToJQuaternion()));
 }
Esempio n. 14
0
        private void Update(float totalSecondsElapsed)
        {
            var originalRotation = new Dictionary <int, Quaternion>();
            var originalPosition = new Dictionary <int, Vector3>();

            _stopwatch.Start();
            _physicsMetrics.StaticImmovableObjects = 0;
            _physicsMetrics.PhysicsObjects         = 0;

            foreach (var kv in _rigidBodyMappings)
            {
                if (kv.StaticAndImmovable)
                {
                    _physicsMetrics.StaticImmovableObjects++;
                }
                else
                {
                    _physicsMetrics.PhysicsObjects++;
                }

                if (kv.StaticAndImmovable && kv.PerformedInitialSync)
                {
                    continue;
                }

                var rigidBody    = kv.RigidBody;
                var hasTransform = kv.HasTransform;

                // Put the lookup in the transform cache.
                _transformCache[rigidBody.GetHashCode()] = new WeakReference <IHasTransform>(hasTransform);

                // Sync game world to physics system.
                var rot = hasTransform.FinalTransform.AbsoluteRotation;
                var pos = hasTransform.FinalTransform.AbsolutePosition;
                originalRotation[rigidBody.GetHashCode()] = rot;
                originalPosition[rigidBody.GetHashCode()] = pos;

                // If the position of the entity differs from what we expect, then the user
                // probably explicitly set it and we need to sync the rigid body.
                if (_lastFramePosition.ContainsKey(rigidBody.GetHashCode()))
                {
                    var lastPosition = _lastFramePosition[rigidBody.GetHashCode()];
                    if ((lastPosition - hasTransform.Transform.LocalPosition).LengthSquared() > 0.0001f)
                    {
                        rigidBody.Position = pos.ToJitterVector();
                    }
                }
                else
                {
                    rigidBody.Position = pos.ToJitterVector();
                }

                // If the rotation of the entity differs from what we expect, then the user
                // probably explicitly set it and we need to sync the rigid body.
                if (_lastFrameRotation.ContainsKey(rigidBody.GetHashCode()))
                {
                    var lastRotation = _lastFrameRotation[rigidBody.GetHashCode()];

                    var a         = Quaternion.Normalize(lastRotation);
                    var b         = Quaternion.Normalize(hasTransform.Transform.LocalRotation);
                    var closeness = 1 - (a.X * b.X + a.Y * b.Y + a.Z * b.Z + a.W * b.W);

                    if (closeness > 0.0001f)
                    {
                        rigidBody.Orientation = JMatrix.CreateFromQuaternion(rot.ToJitterQuaternion());
                    }
                }
                else
                {
                    rigidBody.Orientation = JMatrix.CreateFromQuaternion(rot.ToJitterQuaternion());
                }
            }

            _lastFramePosition.Clear();
            _lastFrameRotation.Clear();

            _stopwatch.Stop();
            _physicsMetrics.SyncToPhysicsTime = _stopwatch.Elapsed.TotalMilliseconds;
            _stopwatch.Restart();

            _physicsWorld.Step(totalSecondsElapsed, true);

            _stopwatch.Stop();
            _physicsMetrics.PhysicsStepTime = _stopwatch.Elapsed.TotalMilliseconds;
            _stopwatch.Restart();

            foreach (var kv in _rigidBodyMappings)
            {
                if (kv.StaticAndImmovable && kv.PerformedInitialSync)
                {
                    continue;
                }

                var rigidBody = kv.RigidBody;
                var hasMatrix = kv.HasTransform;

                // Calculate the changes that the physics system made in world space.
                var oldWorldRot = Quaternion.Normalize(originalRotation[rigidBody.GetHashCode()]);
                var oldWorldPos = originalPosition[rigidBody.GetHashCode()];
                var newWorldRot = Quaternion.Normalize(JQuaternion.CreateFromMatrix(rigidBody.Orientation).ToXNAQuaternion());
                var newWorldPos = rigidBody.Position.ToXNAVector();

                // Determine the localised differences in position.
                var localPos = newWorldPos - oldWorldPos;

                // Update the local components of the transform.
                hasMatrix.Transform.LocalPosition += localPos;
                hasMatrix.Transform.LocalRotation *= Quaternion.Inverse(oldWorldRot) * newWorldRot;

                // Save the current rotation / position for the next frame.
                _lastFramePosition[rigidBody.GetHashCode()] = hasMatrix.Transform.LocalPosition;
                _lastFrameRotation[rigidBody.GetHashCode()] = hasMatrix.Transform.LocalRotation;

                if (kv.StaticAndImmovable && !kv.PerformedInitialSync)
                {
                    kv.PerformedInitialSync = true;
                }
            }

            _stopwatch.Stop();
            _physicsMetrics.SyncFromPhysicsTime = _stopwatch.Elapsed.TotalMilliseconds;
            _stopwatch.Reset();
        }
Esempio n. 15
0
        private void Update(float totalSecondsElapsed)
        {
            var originalRotation = new Dictionary <int, Quaternion>();
            var originalPosition = new Dictionary <int, Vector3>();

            _stopwatch.Start();
            _physicsMetrics.StaticImmovableObjects = 0;
            _physicsMetrics.PhysicsObjects         = 0;

            var gcRigidBodyMappings = new List <RigidBodyMapping>();

            foreach (var kv in _rigidBodyMappings)
            {
                if (kv.StaticAndImmovable)
                {
                    _physicsMetrics.StaticImmovableObjects++;
                }
                else
                {
                    _physicsMetrics.PhysicsObjects++;
                }

                if (kv.StaticAndImmovable && kv.PerformedInitialSync)
                {
                    continue;
                }

                var           rigidBody = kv.RigidBody;
                IHasTransform hasTransform;

                if (!kv.HasTransform.TryGetTarget(out hasTransform))
                {
                    // The transform has been garbage collected.  We need to mark the rigid body mapping
                    // as pending deletion and skip it for now.
                    gcRigidBodyMappings.Add(kv);
                    continue;
                }

                // Sync game world to physics system.
                var rot = hasTransform.FinalTransform.AbsoluteRotation;
                var pos = hasTransform.FinalTransform.AbsolutePosition;
                originalRotation[rigidBody.GetHashCode()] = rot;
                originalPosition[rigidBody.GetHashCode()] = pos;

                // If the position of the entity differs from what we expect, then the user
                // probably explicitly set it and we need to sync the rigid body.
                if (_lastFramePosition.ContainsKey(rigidBody.GetHashCode()))
                {
                    var lastPosition = _lastFramePosition[rigidBody.GetHashCode()];
                    if ((lastPosition - hasTransform.Transform.LocalPosition).LengthSquared() > 0.0001f)
                    {
                        rigidBody.Position = pos.ToJitterVector();
                    }
                }
                else
                {
                    rigidBody.Position = pos.ToJitterVector();
                }

                // If the rotation of the entity differs from what we expect, then the user
                // probably explicitly set it and we need to sync the rigid body.
                if (_lastFrameRotation.ContainsKey(rigidBody.GetHashCode()))
                {
                    var lastRotation = _lastFrameRotation[rigidBody.GetHashCode()];

                    var a         = Quaternion.Normalize(lastRotation);
                    var b         = Quaternion.Normalize(hasTransform.Transform.LocalRotation);
                    var closeness = 1 - (a.X * b.X + a.Y * b.Y + a.Z * b.Z + a.W * b.W);

                    if (closeness > 0.0001f)
                    {
                        rigidBody.Orientation = JMatrix.CreateFromQuaternion(rot.ToJitterQuaternion());
                    }
                }
                else
                {
                    rigidBody.Orientation = JMatrix.CreateFromQuaternion(rot.ToJitterQuaternion());
                }
            }

            if (gcRigidBodyMappings.Count > 0)
            {
                foreach (var kv in gcRigidBodyMappings)
                {
                    // Remove the rigid body whose transform has been garbage collected.
                    _physicsWorld.RemoveBody(kv.RigidBody);
                    _rigidBodyMappings.Remove(kv);
                }
            }

            _lastFramePosition.Clear();
            _lastFrameRotation.Clear();

            _stopwatch.Stop();
            _physicsMetrics.SyncToPhysicsTime = _stopwatch.Elapsed.TotalMilliseconds;
            _stopwatch.Restart();

            _physicsWorld.Step(totalSecondsElapsed, true);

            _stopwatch.Stop();
            _physicsMetrics.PhysicsStepTime = _stopwatch.Elapsed.TotalMilliseconds;
            _stopwatch.Restart();

            foreach (var kv in _rigidBodyMappings)
            {
                if (kv.StaticAndImmovable && kv.PerformedInitialSync)
                {
                    continue;
                }

                var           rigidBody = kv.RigidBody;
                IHasTransform hasTransform;

                if (!kv.HasTransform.TryGetTarget(out hasTransform))
                {
                    // The transform has been garbage collected.  Next step we'll detect it's been garbage
                    // collected and deal with it then.
                    continue;
                }

                // Calculate the changes that the physics system made in world space.
                var oldWorldRot = Quaternion.Normalize(originalRotation[rigidBody.GetHashCode()]);
                var oldWorldPos = originalPosition[rigidBody.GetHashCode()];
                var newWorldRot = Quaternion.Normalize(JQuaternion.CreateFromMatrix(rigidBody.Orientation).ToXNAQuaternion());
                var newWorldPos = rigidBody.Position.ToXNAVector();

                // Determine the localised differences in position.
                var localPos = newWorldPos - oldWorldPos;

                // Update the local components of the transform.
                hasTransform.Transform.LocalPosition += localPos;
                hasTransform.Transform.LocalRotation *= Quaternion.Inverse(oldWorldRot) * newWorldRot;

                // Save the current rotation / position for the next frame.
                _lastFramePosition[rigidBody.GetHashCode()] = hasTransform.Transform.LocalPosition;
                _lastFrameRotation[rigidBody.GetHashCode()] = hasTransform.Transform.LocalRotation;

                if (kv.StaticAndImmovable && !kv.PerformedInitialSync)
                {
                    kv.PerformedInitialSync = true;
                }
            }

            _stopwatch.Stop();
            _physicsMetrics.SyncFromPhysicsTime = _stopwatch.Elapsed.TotalMilliseconds;
            _stopwatch.Reset();
        }
Esempio n. 16
0
        private static JMatrix to_j(Quaternion r)
        {
            var q = new JQuaternion(r.X, r.Y, r.Z, r.W);

            return(JMatrix.CreateFromQuaternion(q));
        }