// see: btSubSimplexConvexCast.cpp /// <summary> /// Checks if a ray definied through it's origin and direction collides /// with a shape. /// </summary> /// <param name="support">The supportmap implementation representing the shape.</param> /// <param name="orientation">The orientation of the shape.</param> /// <param name="invOrientation">The inverse orientation of the shape.</param> /// <param name="position">The position of the shape.</param> /// <param name="origin">The origin of the ray.</param> /// <param name="direction">The direction of the ray.</param> /// <param name="fraction">The fraction which gives information where at the /// ray the collision occured. The hitPoint is calculated by: origin+friction*direction.</param> /// <param name="normal">The normal from the ray collision.</param> /// <returns>Returns true if the ray hit the shape, false otherwise.</returns> public static bool Raycast(ISupportMappable support, ref JMatrix orientation, ref JMatrix invOrientation, ref JVector position, ref JVector origin, ref JVector direction, out float fraction, out JVector normal) { VoronoiSimplexSolver simplexSolver = simplexSolverPool.GetNew(); simplexSolver.Reset(); normal = JVector.Zero; fraction = float.MaxValue; float lambda = 0.0f; JVector r = direction; JVector x = origin; JVector w, p, v; JVector arbitraryPoint; SupportMapTransformed(support, ref orientation, ref position, ref r, out arbitraryPoint); JVector.Subtract(ref x, ref arbitraryPoint, out v); int maxIter = MaxIterations; float distSq = v.LengthSquared(); float epsilon = 0.000001f; float VdotR; while ((distSq > epsilon) && (maxIter-- != 0)) { SupportMapTransformed(support, ref orientation, ref position, ref v, out p); JVector.Subtract(ref x, ref p, out w); float VdotW = JVector.Dot(ref v, ref w); if (VdotW > 0.0f) { VdotR = JVector.Dot(ref v, ref r); if (VdotR >= -JMath.Epsilon) { simplexSolverPool.GiveBack(simplexSolver); return(false); } else { lambda = lambda - VdotW / VdotR; JVector.Multiply(ref r, lambda, out x); JVector.Add(ref origin, ref x, out x); JVector.Subtract(ref x, ref p, out w); normal = v; } } if (!simplexSolver.InSimplex(w)) { simplexSolver.AddVertex(w, x, p); } if (simplexSolver.Closest(out v)) { distSq = v.LengthSquared(); } else { distSq = 0.0f; } } #region Retrieving hitPoint // Giving back the fraction like this *should* work // but is inaccurate against large objects: // fraction = lambda; JVector p1, p2; simplexSolver.ComputePoints(out p1, out p2); p2 = p2 - origin; fraction = p2.Length() / direction.Length(); #endregion if (normal.LengthSquared() > JMath.Epsilon * JMath.Epsilon) { normal.Normalize(); } simplexSolverPool.GiveBack(simplexSolver); return(true); }
/// <summary> /// Checks if given point is within a shape. /// </summary> /// <param name="support">The supportmap implementation representing the shape.</param> /// <param name="orientation">The orientation of the shape.</param> /// <param name="invOrientation">The inverse orientation of the shape.</param> /// <param name="position">The position of the shape.</param> /// <param name="point">The point to check.</param> /// <returns>Returns true if the point is within the shape, otherwise false.</returns> public static bool Pointcast(ISupportMappable support, ref JMatrix orientation, ref JVector position, ref JVector point) { JVector arbitraryPoint; SupportMapTransformed(support, ref orientation, ref position, ref point, out arbitraryPoint); JVector.Subtract(ref point, ref arbitraryPoint, out arbitraryPoint); JVector r; support.SupportCenter(out r); JVector.Transform(ref r, ref orientation, out r); JVector.Add(ref position, ref r, out r); JVector.Subtract(ref point, ref r, out r); JVector x = point; JVector w, p; float VdotR; JVector v; JVector.Subtract(ref x, ref arbitraryPoint, out v); float dist = v.LengthSquared(); float epsilon = 0.0001f; int maxIter = MaxIterations; VoronoiSimplexSolver simplexSolver = simplexSolverPool.GetNew(); simplexSolver.Reset(); while ((dist > epsilon) && (maxIter-- != 0)) { SupportMapTransformed(support, ref orientation, ref position, ref v, out p); JVector.Subtract(ref x, ref p, out w); float VdotW = JVector.Dot(ref v, ref w); if (VdotW > 0.0f) { VdotR = JVector.Dot(ref v, ref r); if (VdotR >= -(JMath.Epsilon * JMath.Epsilon)) { simplexSolverPool.GiveBack(simplexSolver); return(false); } else { simplexSolver.Reset(); } } if (!simplexSolver.InSimplex(w)) { simplexSolver.AddVertex(w, x, p); } if (simplexSolver.Closest(out v)) { dist = v.LengthSquared(); } else { dist = 0.0f; } } simplexSolverPool.GiveBack(simplexSolver); return(true); }
/// <summary> /// Checks if given point is within a shape. /// </summary> /// <param name="support">The supportmap implementation representing the shape.</param> /// <param name="orientation">The orientation of the shape.</param> /// <param name="invOrientation">The inverse orientation of the shape.</param> /// <param name="position">The position of the shape.</param> /// <param name="point">The point to check.</param> /// <returns>Returns true if the point is within the shape, otherwise false.</returns> public static bool Pointcast(ISupportMappable support, ref MatrixD orientation, ref Vector3D position, ref Vector3D point) { Vector3D arbitraryPoint; SupportMapTransformed(support, ref orientation, ref position, ref point, out arbitraryPoint); Vector3D.Subtract(ref point, ref arbitraryPoint, out arbitraryPoint); Vector3D r; support.SupportCenter(out r); Vector3D.Transform(ref r, ref orientation, out r); Vector3D.Add(ref position, ref r, out r); Vector3D.Subtract(ref point, ref r, out r); Vector3D x = point; Vector3D w, p; double VdotR; Vector3D v; Vector3D.Subtract(ref x, ref arbitraryPoint, out v); double dist = v.LengthSquared(); double epsilon = 0.0001f; int maxIter = MaxIterations; VoronoiSimplexSolver simplexSolver = simplexSolverPool.GetNew(); simplexSolver.Reset(); while ((dist > epsilon) && (maxIter-- != 0)) { SupportMapTransformed(support, ref orientation, ref position, ref v, out p); Vector3D.Subtract(ref x, ref p, out w); double VdotW = Vector3D.Dot(v, w); if (VdotW > 0.0f) { VdotR = Vector3D.Dot(v, r); if (VdotR >= -(MathHelper.EPSILON * MathHelper.EPSILON)) { simplexSolverPool.GiveBack(simplexSolver); return(false); } else { simplexSolver.Reset(); } } if (!simplexSolver.InSimplex(w)) { simplexSolver.AddVertex(w, x, p); } if (simplexSolver.Closest(out v)) { dist = v.LengthSquared(); } else { dist = 0.0f; } } simplexSolverPool.GiveBack(simplexSolver); return(true); }
// see: btSubSimplexConvexCast.cpp /// <summary> /// Checks if a ray definied through it's origin and direction collides /// with a shape. /// </summary> /// <param name="support">The supportmap implementation representing the shape.</param> /// <param name="orientation">The orientation of the shape.</param> /// <param name="invOrientation">The inverse orientation of the shape.</param> /// <param name="position">The position of the shape.</param> /// <param name="origin">The origin of the ray.</param> /// <param name="direction">The direction of the ray.</param> /// <param name="fraction">The fraction which gives information where at the /// ray the collision occured. The hitPoint is calculated by: origin+friction*direction.</param> /// <param name="normal">The normal from the ray collision.</param> /// <returns>Returns true if the ray hit the shape, false otherwise.</returns> public static bool Raycast(ISupportMappable support, ref MatrixD orientation, ref MatrixD invOrientation, ref Vector3D position, ref Vector3D origin, ref Vector3D direction, out double fraction, out Vector3D normal) { VoronoiSimplexSolver simplexSolver = simplexSolverPool.GetNew(); simplexSolver.Reset(); normal = Vector3D.Zero; fraction = double.MaxValue; double lambda = 0.0f; Vector3D r = direction; Vector3D x = origin; Vector3D w, p, v; Vector3D arbitraryPoint; SupportMapTransformed(support, ref orientation, ref position, ref r, out arbitraryPoint); Vector3D.Subtract(ref x, ref arbitraryPoint, out v); int maxIter = MaxIterations; double distSq = v.LengthSquared(); double epsilon = 0.000001f; double VdotR; while ((distSq > epsilon) && (maxIter-- != 0)) { SupportMapTransformed(support, ref orientation, ref position, ref v, out p); Vector3D.Subtract(ref x, ref p, out w); double VdotW = Vector3D.Dot(v, w); if (VdotW > 0.0f) { VdotR = Vector3D.Dot(v, r); if (VdotR >= -MathHelper.EPSILON) { simplexSolverPool.GiveBack(simplexSolver); return(false); } else { lambda = lambda - VdotW / VdotR; Vector3D.Multiply(ref r, lambda, out x); Vector3D.Add(ref origin, ref x, out x); Vector3D.Subtract(ref x, ref p, out w); normal = v; } } if (!simplexSolver.InSimplex(w)) { simplexSolver.AddVertex(w, x, p); } if (simplexSolver.Closest(out v)) { distSq = v.LengthSquared(); } else { distSq = 0.0f; } } #region Retrieving hitPoint // Giving back the fraction like this *should* work // but is inaccurate against large objects: // fraction = lambda; Vector3D p1, p2; simplexSolver.ComputePoints(out p1, out p2); p2 = p2 - origin; fraction = p2.Length() / direction.Length(); #endregion if (normal.LengthSquared() > MathHelper.EPSILON * MathHelper.EPSILON) { normal.Normalize(); } simplexSolverPool.GiveBack(simplexSolver); return(true); }
public static bool ClosestPoints(ISupportMappable support1, ISupportMappable support2, ref MatrixD orientation1, ref MatrixD orientation2, ref Vector3D position1, ref Vector3D position2, out Vector3D p1, out Vector3D p2, out Vector3D normal) { VoronoiSimplexSolver simplexSolver = simplexSolverPool.GetNew(); simplexSolver.Reset(); p1 = p2 = Vector3D.Zero; Vector3D r = position1 - position2; Vector3D w, v; Vector3D supVertexA; Vector3D rn, vn; rn = Vector3D.Negate(r); SupportMapTransformed(support1, ref orientation1, ref position1, ref rn, out supVertexA); Vector3D supVertexB; SupportMapTransformed(support2, ref orientation2, ref position2, ref r, out supVertexB); v = supVertexA - supVertexB; normal = Vector3D.Zero; int maxIter = 15; double distSq = v.LengthSquared(); double epsilon = 0.00001f; while ((distSq > epsilon) && (maxIter-- != 0)) { vn = Vector3D.Negate(v); SupportMapTransformed(support1, ref orientation1, ref position1, ref vn, out supVertexA); SupportMapTransformed(support2, ref orientation2, ref position2, ref v, out supVertexB); w = supVertexA - supVertexB; if (!simplexSolver.InSimplex(w)) { simplexSolver.AddVertex(w, supVertexA, supVertexB); } if (simplexSolver.Closest(out v)) { distSq = v.LengthSquared(); normal = v; } else { distSq = 0.0f; } } simplexSolver.ComputePoints(out p1, out p2); if (normal.LengthSquared() > MathHelper.EPSILON * MathHelper.EPSILON) { normal.Normalize(); } simplexSolverPool.GiveBack(simplexSolver); return(true); }
public static bool ClosestPoints(ISupportMappable support1, ISupportMappable support2, ref Matrix3 orientation1, ref Matrix3 orientation2, ref Vector3 position1, ref Vector3 position2, out Vector3 p1, out Vector3 p2, out Vector3 normal) { VoronoiSimplexSolver simplexSolver = simplexSolverPool.GetNew(); simplexSolver.Reset(); p1 = p2 = Vector3.Zero; Vector3 r = position1 - position2; Vector3 w, v; Vector3 supVertexA; Vector3 rn, vn; rn = r * -1; SupportMapTransformed(support1, ref orientation1, ref position1, ref rn, out supVertexA); Vector3 supVertexB; SupportMapTransformed(support2, ref orientation2, ref position2, ref r, out supVertexB); v = supVertexA - supVertexB; normal = Vector3.Zero; int maxIter = 15; float distSq = v.LengthSquared; float epsilon = 0.00001f; while ((distSq > epsilon) && (maxIter-- != 0)) { vn = v * -1; SupportMapTransformed(support1, ref orientation1, ref position1, ref vn, out supVertexA); SupportMapTransformed(support2, ref orientation2, ref position2, ref v, out supVertexB); w = supVertexA - supVertexB; if (!simplexSolver.InSimplex(w)) { simplexSolver.AddVertex(w, supVertexA, supVertexB); } if (simplexSolver.Closest(out v)) { distSq = v.LengthSquared; normal = v; } else { distSq = 0.0f; } } simplexSolver.ComputePoints(out p1, out p2); if (normal.LengthSquared > JMath.Epsilon * JMath.Epsilon) { normal.Normalize(); } simplexSolverPool.GiveBack(simplexSolver); return(true); }
public static bool ClosestPoints(ISupportMappable support1, ISupportMappable support2, ref JMatrix orientation1, ref JMatrix orientation2, ref JVector position1, ref JVector position2, out JVector p1, out JVector p2, out JVector normal) { VoronoiSimplexSolver simplexSolver = simplexSolverPool.GetNew(); simplexSolver.Reset(); p1 = p2 = JVector.Zero; JVector r = position1 - position2; JVector w, v; JVector supVertexA; JVector rn, vn; rn = JVector.Negate(r); SupportMapTransformed(support1, ref orientation1, ref position1, ref rn, out supVertexA); JVector supVertexB; SupportMapTransformed(support2, ref orientation2, ref position2, ref r, out supVertexB); v = supVertexA - supVertexB; normal = JVector.Zero; int iter = 0; float distSq = v.LengthSquared(); float epsilon = 0.00001f; while ((distSq > epsilon) && (iter++ < MaxIterations)) { IterationsTaken = iter; vn = JVector.Negate(v); SupportMapTransformed(support1, ref orientation1, ref position1, ref vn, out supVertexA); SupportMapTransformed(support2, ref orientation2, ref position2, ref v, out supVertexB); w = supVertexA - supVertexB; if (!simplexSolver.InSimplex(w)) { simplexSolver.AddVertex(w, supVertexA, supVertexB); } if (simplexSolver.Closest(out v)) { distSq = v.LengthSquared(); normal = v; } else { distSq = 0.0f; } } simplexSolver.ComputePoints(out p1, out p2); if (normal.LengthSquared() > JMath.Epsilon * JMath.Epsilon) { normal.Normalize(); } simplexSolverPool.GiveBack(simplexSolver); return(true); }