/// <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); }
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! } } }