public override void DoWork() { MyRBBoxElement rbBoxElement = (MyRBBoxElement)m_RBElement; MyBoxSensorElement seBoxElement = (MyBoxSensorElement)m_SensorElement; Matrix rbBoxMatrix = rbBoxElement.GetGlobalTransformation(); Matrix seBoxMatrix = seBoxElement.GetGlobalTransformation(); BoundingBox rbBB = new BoundingBox(-rbBoxElement.Size / 2f, rbBoxElement.Size / 2f); BoundingBox seBB = new BoundingBox(-seBoxElement.Extent, seBoxElement.Extent); MyOrientedBoundingBox rbBoxOriented = MyOrientedBoundingBox.CreateFromBoundingBox(rbBB).Transform(rbBoxMatrix); MyOrientedBoundingBox seBoxOriented = MyOrientedBoundingBox.CreateFromBoundingBox(seBB).Transform(seBoxMatrix); m_IsInside = rbBoxOriented.Intersects(ref seBoxOriented); }
public override void DoWork() { MyRBBoxElement box = (MyRBBoxElement)m_RBElement; MySphereSensorElement sphere = (MySphereSensorElement)m_SensorElement; Matrix boxMatrix = box.GetGlobalTransformation(); Vector3 sphereCenter = sphere.GetGlobalTransformation().Translation; Matrix invBoxMatrix = Matrix.Invert(boxMatrix); Vector3 boxLocalsphereCenter = Vector3.Transform(sphereCenter, invBoxMatrix); bool penetration = false; Vector3 normal = new Vector3(); Vector3 closestPos = new Vector3(); uint customData = 0; box.GetClosestPoint(boxLocalsphereCenter, ref closestPos, ref normal, ref penetration, ref customData); if (penetration) { m_IsInside = true; return; } closestPos = Vector3.Transform(closestPos, boxMatrix); float vLength = (sphereCenter - closestPos).LengthSquared(); if (vLength <= sphere.Radius * sphere.Radius) { if (vLength <= (sphere.Radius / 2f) * (sphere.Radius / 2f) || sphere.SpecialDetectingAngle == null) { m_IsInside = true; } else if (sphere.SpecialDetectingAngle != null) { Vector3 normalizeDirectionToRBElement = Vector3.Normalize(boxMatrix.Translation - sphereCenter); float cosAngle = Vector3.Dot(normalizeDirectionToRBElement, sphere.GetGlobalTransformation().Forward); m_IsInside = Math.Abs(cosAngle) >= sphere.SpecialDetectingAngle.Value; } } else { m_IsInside = false; } }
protected override bool Interact(bool staticCollision) { if (!staticCollision && GetRigidBody1().IsStatic() && GetRigidBody2().IsStatic()) { return(false); } MyRBBoxElement box = null; MyRBSphereElement sphere = null; if (RBElement1.GetElementType() == MyRBElementType.ET_BOX) { SwapElements(); } box = (MyRBBoxElement)RBElement2; sphere = (MyRBSphereElement)RBElement1; Matrix boxMatrix = box.GetGlobalTransformation(); Vector3 sphereCenter = sphere.GetGlobalTransformation().Translation; Matrix invBoxMatrix = Matrix.Invert(boxMatrix); Vector3 boxLocalsphereCenter = Vector3.Transform(sphereCenter, invBoxMatrix); bool penetration = false; Vector3 normal = new Vector3(); Vector3 closestPos = new Vector3(); uint customData = 0; box.GetClosestPoint(boxLocalsphereCenter, ref closestPos, ref normal, ref penetration, ref customData); closestPos = Vector3.Transform(closestPos, boxMatrix); normal = -Vector3.TransformNormal(normal, boxMatrix); normal = MyMwcUtils.Normalize(normal); float vLength = (sphereCenter - closestPos).Length(); if (staticCollision) { return(vLength > 0 && vLength < sphere.Radius); } else { float eps = MyPhysics.physicsSystem.GetRigidBodyModule().CollisionEpsilon; float dt = MyPhysics.physicsSystem.GetRigidBodyModule().CurrentTimeStep; Vector3 pointVelocity1 = new Vector3(); Vector3 pointVelocity2 = new Vector3(); GetRigidBody1().GetGlobalPointVelocity(ref closestPos, out pointVelocity1); GetRigidBody2().GetGlobalPointVelocity(ref closestPos, out pointVelocity2); float dynEps = 0; if (vLength >= eps) { float dot = Vector3.Dot(pointVelocity1 - pointVelocity2, normal) * dt; if (dot >= 0) { dynEps = dot; } } float radius = sphere.Radius; //Second part of condition commented due to 5968: Bug B - rocket passing through prefab //Does not seem to have any reason to be there if (vLength > 0 /*&& vLength < (radius + eps + dynEps)*/) { float error = vLength - (radius + 0.5f * eps); //error = System.Math.Min(error, eps); MySmallCollPointInfo[] collInfo = MyContactInfoCache.SCPIStackAlloc(); collInfo[0] = new MySmallCollPointInfo(closestPos - sphereCenter, closestPos - boxMatrix.Translation, GetRigidBody1().LinearVelocity, GetRigidBody2().LinearVelocity, normal, error, closestPos); MyPhysics.physicsSystem.GetContactConstraintModule().AddContactConstraint(this, collInfo, 1); MyContactInfoCache.FreeStackAlloc(collInfo); } } return(false); }
protected override bool Interact(bool staticCollision) { if (!staticCollision) { MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("BoxBoxInteraction"); } try { MyRBBoxElement rbbox0 = (MyRBBoxElement)RBElement1; MyRBBoxElement rbbox1 = (MyRBBoxElement)RBElement2; MyBox box0 = m_TempBox1; MyBox box1 = m_TempBox2; Matrix matrix0 = rbbox0.GetGlobalTransformation(); Matrix matrix1 = rbbox1.GetGlobalTransformation(); box0.Transform.Orientation = matrix0; box0.Transform.Orientation.Translation = Vector3.Zero; box0.Transform.Position = matrix0.Translation - Vector3.TransformNormal(rbbox0.Size * 0.5f, matrix0); box1.Transform.Orientation = matrix1; box1.Transform.Orientation.Translation = Vector3.Zero; box1.Transform.Position = matrix1.Translation - Vector3.TransformNormal(rbbox1.Size * 0.5f, matrix1); box0.SideLengths = rbbox0.Size; box1.SideLengths = rbbox1.Size; // see if the boxes are separate along any axis, and if not keep a // record of the depths along each axis for (int i = 0; i < 15; ++i) { switch (i) { case 0: seperatingAxes[0] = box0.Orientation.Right; break; case 1: seperatingAxes[1] = box0.Orientation.Up; break; case 2: seperatingAxes[2] = box0.Orientation.Backward; break; case 3: seperatingAxes[3] = box1.Orientation.Right; break; case 4: seperatingAxes[4] = box1.Orientation.Up; break; case 5: seperatingAxes[5] = box1.Orientation.Backward; break; case 6: Vector3.Cross(ref seperatingAxes[0], ref seperatingAxes[3], out seperatingAxes[6]); break; case 7: Vector3.Cross(ref seperatingAxes[0], ref seperatingAxes[4], out seperatingAxes[7]); break; case 8: Vector3.Cross(ref seperatingAxes[0], ref seperatingAxes[5], out seperatingAxes[8]); break; case 9: Vector3.Cross(ref seperatingAxes[1], ref seperatingAxes[3], out seperatingAxes[9]); break; case 10: Vector3.Cross(ref seperatingAxes[1], ref seperatingAxes[4], out seperatingAxes[10]); break; case 11: Vector3.Cross(ref seperatingAxes[1], ref seperatingAxes[5], out seperatingAxes[11]); break; case 12: Vector3.Cross(ref seperatingAxes[2], ref seperatingAxes[3], out seperatingAxes[12]); break; case 13: Vector3.Cross(ref seperatingAxes[2], ref seperatingAxes[4], out seperatingAxes[13]); break; case 14: Vector3.Cross(ref seperatingAxes[2], ref seperatingAxes[5], out seperatingAxes[14]); break; } // If we can't normalise the axis, skip it if (seperatingAxes[i].LengthSquared() < MyPhysicsConfig.CollisionEpsilon) { continue; } overlapDepth[i] = float.MaxValue; if (Disjoint(out overlapDepth[i], ref seperatingAxes[i], box0, box1, MyPhysicsConfig.CollisionEpsilon)) { return(false); } } if (staticCollision) { return(true); // Static collision: we're done. } // Dynamic collision. // The boxes overlap, find the seperation depth closest to 0. float minDepth = float.MaxValue; int minAxis = -1; for (int i = 0; i < 15; ++i) { // If we can't normalise the axis, skip it float l2 = seperatingAxes[i].LengthSquared(); if (l2 < MyPhysicsConfig.CollisionEpsilon) { continue; } // Normalise the separation axis and depth float invl = 1.0f / (float)System.Math.Sqrt(l2); seperatingAxes[i] *= invl; overlapDepth[i] *= invl; // If this axis is the minmum, select it if (overlapDepth[i] < minDepth) { minDepth = overlapDepth[i]; minAxis = i; } } if (minAxis == -1) { return(false); } // Make sure the axis is facing towards the 0th box. // if not, invert it Vector3 D = box1.GetCentre() - box0.GetCentre(); Vector3 N = seperatingAxes[minAxis]; float depth = overlapDepth[minAxis]; if (Vector3.Dot(D, N) < 0.0f) { N *= -1.0f; } float minA = MathHelper.Min(box0.SideLengths.X, MathHelper.Min(box0.SideLengths.Y, box0.SideLengths.Z)); float minB = MathHelper.Min(box1.SideLengths.X, MathHelper.Min(box1.SideLengths.Y, box1.SideLengths.Z)); float combinationDist = 0.05f * MathHelper.Min(minA, minB); // the contact points contactPts.Clear(); int numPts = contactPts.Count; GetBoxBoxIntersectionPoints(contactPts, box0, box1, combinationDist, MyPhysicsConfig.CollisionEpsilon); numPts = contactPts.Count; MyRigidBody rbo0 = GetRigidBody1(); MyRigidBody rbo1 = GetRigidBody2(); float dt = MyPhysics.physicsSystem.GetRigidBodyModule().CurrentTimeStep; Vector3 body0OldPos = rbo0.Position; Vector3 body1OldPos = rbo1.Position; Vector3 body0NewPos = (rbo0.Position + rbo0.LinearVelocity * dt); Vector3 body1NewPos = (rbo1.Position + rbo1.LinearVelocity * dt); #region REFERENCE: Vector3 bodyDelta = body0NewPos - body0OldPos - body1NewPos + body1OldPos; Vector3 bodyDelta; Vector3.Subtract(ref body0NewPos, ref body0OldPos, out bodyDelta); Vector3.Subtract(ref bodyDelta, ref body1NewPos, out bodyDelta); Vector3.Add(ref bodyDelta, ref body1OldPos, out bodyDelta); #endregion #region REFERENCE: float bodyDeltaLen = Vector3.Dot(bodyDelta,N); float bodyDeltaLen; Vector3.Dot(ref bodyDelta, ref N, out bodyDeltaLen); #endregion float oldDepth = depth + bodyDeltaLen; MySmallCollPointInfo[] collPtArray = MyContactInfoCache.SCPIStackAlloc(); { int numCollPts = 0; Vector3 SATPoint; switch (minAxis) { // Box0 face, Box1 corner collision case 0: case 1: case 2: { // Get the lowest point on the box1 along box1 normal GetSupportPoint(out SATPoint, box1, -N); break; } // We have a Box2 corner/Box1 face collision case 3: case 4: case 5: { // Find with vertex on the triangleVertexes collided GetSupportPoint(out SATPoint, box0, N); break; } // We have an edge/edge collision case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: { { // Retrieve which edges collided. int i = minAxis - 6; int ia = i / 3; int ib = i - ia * 3; // find two P0, P1 point on both edges. Vector3 P0, P1; GetSupportPoint(out P0, box0, N); GetSupportPoint(out P1, box1, -N); // Find the edge intersection. // plane along N and F, and passing through PB Vector3 box0Orient, box1Orient; MyPhysicsUtils.MyPhysicsUnsafe.Get(ref box0.Transform.Orientation, ia, out box0Orient); MyPhysicsUtils.MyPhysicsUnsafe.Get(ref box1.Transform.Orientation, ib, out box1Orient); #region REFERENCE: Vector3 planeNormal = Vector3.Cross(N, box1Orient[ib]); Vector3 planeNormal; Vector3.Cross(ref N, ref box1Orient, out planeNormal); #endregion #region REFERENCE: float planeD = Vector3.Dot(planeNormal, P1); float planeD; Vector3.Dot(ref planeNormal, ref P1, out planeD); #endregion // find the intersection t, where Pintersection = P0 + t*box edge dir #region REFERENCE: float div = Vector3.Dot(box0Orient, planeNormal); float div; Vector3.Dot(ref box0Orient, ref planeNormal, out div); #endregion // plane and ray colinear, skip the intersection. if (System.Math.Abs(div) < MyPhysicsConfig.CollisionEpsilon) { return(false); } float t = (planeD - Vector3.Dot(P0, planeNormal)) / div; // point on edge of box0 #region REFERENCE: P0 += box0Orient * t; P0 = Vector3.Add(Vector3.Multiply(box0Orient, t), P0); #endregion #region REFERENCE: SATPoint = (P0 + (0.5f * depth) * N); Vector3.Multiply(ref N, 0.5f * depth, out SATPoint); Vector3.Add(ref SATPoint, ref P0, out SATPoint); #endregion } break; } default: { SATPoint = Vector3.Zero; Debug.Assert(false); break; } } // distribute the depth according to the distance to the SAT point if (numPts > 0) { float minDist = float.MaxValue; float maxDist = float.MinValue; for (int i = 0; i < numPts; ++i) { float dist = MyPhysicsUtils.PointPointDistance(contactPts[i].Pos, SATPoint); if (dist < minDist) { minDist = dist; } if (dist > maxDist) { maxDist = dist; } } // got some intersection points for (int i = 0; i < numPts; ++i) { float minDepthScale = 0.0f; float dist = MyPhysicsUtils.PointPointDistance(contactPts[i].Pos, SATPoint); float safeDivisionDist = (maxDist - minDist); if ((maxDist - minDist) == 0.0f) { safeDivisionDist = MyPhysicsConfig.CollisionEpsilon; } float depthScale = (dist - minDist) / safeDivisionDist; depth = (1.0f - depthScale) * oldDepth + minDepthScale * depthScale * oldDepth; if (numCollPts < MyPhysicsConfig.MaxContactPoints) { collPtArray[numCollPts++] = new MySmallCollPointInfo(contactPts[i].Pos - body0OldPos, contactPts[i].Pos - body1OldPos, GetRigidBody1().LinearVelocity, GetRigidBody2().LinearVelocity, N, depth, contactPts[i].Pos); } } } else { #region REFERENCE: collPts.Add(new CollPointInfo(SATPoint - body0NewPos, SATPoint - body1NewPos, oldDepth)); //collPts.Add(new CollPointInfo(SATPoint - body0NewPos, SATPoint - body1NewPos, oldDepth)); Vector3 cp0; Vector3.Subtract(ref SATPoint, ref body0NewPos, out cp0); Vector3 cp1; Vector3.Subtract(ref SATPoint, ref body1NewPos, out cp1); if (numCollPts < MyPhysicsConfig.MaxContactPoints) { collPtArray[numCollPts++] = new MySmallCollPointInfo(cp0, cp1, GetRigidBody1().LinearVelocity, GetRigidBody2().LinearVelocity, N, oldDepth, SATPoint); } #endregion } // report Collisions MyPhysics.physicsSystem.GetContactConstraintModule().AddContactConstraint(this, collPtArray, numCollPts); } MyContactInfoCache.FreeStackAlloc(collPtArray); } catch { throw; } finally { if (!staticCollision) { MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); } } return(false); }