/// <summary>
        /// this method is a bit hacky since I did not know where to place it. I may move it to a better
        /// place somewhen in the future
        /// </summary>
        /// <param name="ray"></param>
        /// <param name="entity"></param>
        public bool GetIntersectionPoint(
            ref Ray3 ray,
            Entity entity,
            out Vector3 outIsectPt
            )
        {
            // find the matching collision entity (in order to get the alignedbox3tree
            CollisionEntity collisionEntity = testList.GetCollisionEntity(entity);

            if (collisionEntity == null)
            {
                outIsectPt = Vector3.Zero;
                return(false);
            }

            Debug.Assert(collisionEntity.VolumeType == VolumeType.AlignedBox3Tree);
            if (collisionEntity.VolumeType != VolumeType.AlignedBox3Tree)
            {
                outIsectPt = Vector3.Zero;
                return(false);
            }

            // get world transform of from the given entity
            Matrix          worldTransform;
            AlignedBox3Tree tree = (AlignedBox3Tree)collisionEntity.Volumes[0];

            OrientationHelper.CalculateWorldTransform(entity, out worldTransform);

            // transform the ray into the coordinate system of the entity
            Matrix  worldToEntityTransform = Matrix.Invert(worldTransform);
            Matrix  inverseTransposeWorldToEntityTransform = Matrix.Transpose(Matrix.Invert(worldToEntityTransform));
            Vector3 entitySpaceRayOrigin    = Vector3.Transform(ray.Origin, worldToEntityTransform);
            Vector3 entitySpaceRayDirection = Vector3.Transform(ray.Direction, inverseTransposeWorldToEntityTransform);

            entitySpaceRayDirection.Normalize();
            Ray3 entitySpaceRay = new Ray3(entitySpaceRayOrigin, entitySpaceRayDirection);

            float t; // parameter on ray, outIsectPt = ray.Origin + t * ray.Direction;
            bool  intersection = GetIntersectionPoint(ref entitySpaceRay, tree.Root, tree.Positions, out t);

            if (intersection)
            {
                outIsectPt = Vector3.Transform(entitySpaceRay.Origin + t * entitySpaceRay.Direction, worldTransform);
            }
            else
            {
                outIsectPt = Vector3.Zero;
            }
            return(intersection);
        }
Exemple #2
0
        private void Run()
        {
#if XBOX
            this.thread.SetProcessorAffinity(processor);
#endif
            try
            {
                while (true)
                {
                    startEvent.WaitOne();

                    double startTime = Now;

                    if (lastFrame > 0)
                    {
                        double targetFps = 60;
                        double waitTime  = startTime - lastFrame;
                        double newTarget = ((1000d / targetFps) - waitTime);
                        targetMilliseconds = System.Math.Max(2, targetMilliseconds * 0.9 + newTarget * 0.1);
                    }

                    //Console.WriteLine("{0}", targetMilliseconds);

                    Contact            lastContact = null;
                    TestList.TestEntry entry       = testList.GetNextCollisionEntry();
                    while (entry != null && (Now - startTime) < targetMilliseconds) // todo: extract constant
                    {
                        // do collision detection with this entry!
                        ContactTest test = CollisionManager.ContactTests[
                            BoundingVolumeTypeUtil.ToNumber(entry.EntityA.VolumeType),
                            BoundingVolumeTypeUtil.ToNumber(entry.EntityB.VolumeType)
                                           ];


                        Vector3    scale1, position1, scale2, position2;
                        Quaternion rotation1, rotation2;
                        Matrix     worldTransform1, worldTransform2;
                        OrientationHelper.GetTranslation(entry.EntityA.Entity, out position1);
                        OrientationHelper.GetRotation(entry.EntityA.Entity, out rotation1);
                        OrientationHelper.GetScale(entry.EntityA.Entity, out scale1);
                        OrientationHelper.CalculateWorldTransform(ref position1, ref rotation1, ref scale1, out worldTransform1);

                        OrientationHelper.GetTranslation(entry.EntityB.Entity, out position2);
                        OrientationHelper.GetRotation(entry.EntityB.Entity, out rotation2);
                        OrientationHelper.GetScale(entry.EntityB.Entity, out scale2);
                        OrientationHelper.CalculateWorldTransform(ref position2, ref rotation2, ref scale2, out worldTransform2);

                        // the xbox does not like too many allocations. so if possible we recycle the last contact
                        // that we allocated but did not need because there was no collision...
                        Contact contact = null;
                        if (lastContact == null || lastContact.Count > 0)
                        {
                            contact = AllocateContact(entry.EntityA.Entity, entry.EntityB.Entity);
                        }
                        else
                        {
                            lastContact.Recycle(entry.EntityA.Entity, entry.EntityB.Entity);
                        }

                        test(
                            entry.EntityA.Entity, entry.EntityA.Volumes, ref worldTransform1, ref position1, ref rotation1, ref scale1,
                            entry.EntityB.Entity, entry.EntityB.Volumes, ref worldTransform2, ref position2, ref rotation2, ref scale2,
                            entry.EntityA.NeedAllContacts || entry.EntityB.NeedAllContacts, ref contact
                            );
                        if (contact.Count > 0)
                        {
                            Debug.Assert(contact.EntityA == entry.EntityA.Entity && contact.EntityB == entry.EntityB.Entity);
                            contacts.Add(contact);
                        }

                        // get next entry
                        entry = testList.GetNextCollisionEntry();
                    }

                    lastFrame = Now;

                    finishedEvent.Set();
                }
            }
            catch (Exception ex)
            {
                if (!this.aborted)
                {
                    System.Console.WriteLine("unexpected Exception {0}\n{1}\n{2}", ex.GetType().Name, ex.Message, ex.StackTrace);
                    Game.Instance.CrashDebugger.Crash(ex);
                    finishedEvent.Set(); // => the simulationthread should be able to proceed!
                }
            }
        }