/// <summary> /// Initializes a new instance of the DistanceConstraint class. /// </summary> /// <param name="body1">The first body.</param> /// <param name="body2">The second body.</param> /// <param name="anchor1">The anchor point of the first body in world space. /// The distance is given by the initial distance between both anchor points.</param> /// <param name="anchor2">The anchor point of the second body in world space. /// The distance is given by the initial distance between both anchor points.</param> public PointOnPoint(RigidBody body, JVector localAnchor) : base(body, null) { localAnchor1 = localAnchor; this.anchor = body.position + JVector.Transform(localAnchor, body.orientation); }
/// <summary> /// Initializes a new instance of the DistanceConstraint class. /// </summary> /// <param name="body1">The first body.</param> /// <param name="body2">The second body.</param> /// <param name="anchor1">The anchor point of the first body in world space. /// The distance is given by the initial distance between both anchor points.</param> /// <param name="anchor2">The anchor point of the second body in world space. /// The distance is given by the initial distance between both anchor points.</param> public PointOnPoint(RigidBody body1, RigidBody body2, JVector anchor) : base(body1, body2) { JVector.Subtract(ref anchor, ref body1.position, out localAnchor1); JVector.Subtract(ref anchor, ref body2.position, out localAnchor2); JVector.Transform(ref localAnchor1, ref body1.invOrientation, out localAnchor1); JVector.Transform(ref localAnchor2, ref body2.invOrientation, out localAnchor2); }
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 maxIter = 15; float distSq = v.LengthSquared(); float epsilon = 0.00001f; while ((distSq > epsilon) && (maxIter-- != 0)) { 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; }
/// <summary> /// Initializes a new instance of the DistanceConstraint class. /// </summary> /// <param name="body1">The first body.</param> /// <param name="body2">The second body.</param> /// <param name="anchor1">The anchor point of the first body in world space. /// The distance is given by the initial distance between both anchor points.</param> /// <param name="anchor2">The anchor point of the second body in world space. /// The distance is given by the initial distance between both anchor points.</param> public PointPointDistance(RigidBody body1, RigidBody body2, JVector anchor1,JVector anchor2) : base(body1, body2) { JVector.Subtract(ref anchor1, ref body1.position, out localAnchor1); JVector.Subtract(ref anchor2, ref body2.position, out localAnchor2); JVector.Transform(ref localAnchor1, ref body1.invOrientation, out localAnchor1); JVector.Transform(ref localAnchor2, ref body2.invOrientation, out localAnchor2); distance = (anchor1 - anchor2).Length(); }
/// <summary> /// Initializes a new instance of the WorldLineConstraint. /// </summary> /// <param name="body">The body of the constraint.</param> /// <param name="localAnchor">The anchor point on the body in local (body) /// coordinates.</param> /// <param name="lineDirection">The axis defining the line in world space.</param>/param> public PointOnLine(RigidBody body, JVector localAnchor, JVector lineDirection) : base(body, null) { if (lineDirection.LengthSquared() == 0.0f) throw new ArgumentException("Line direction can't be zero", "lineDirection"); localAnchor1 = localAnchor; this.anchor = body.position + JVector.Transform(localAnchor, body.orientation); this.lineNormal = lineDirection; this.lineNormal.Normalize(); }
/// <summary> /// Constraints a point on a body to be fixed on a line /// which is fixed on another body. /// </summary> /// <param name="body1"></param> /// <param name="body2"></param> /// <param name="lineStartPointBody1"></param> /// <param name="lineDirection"></param> /// <param name="pointBody2"></param> public PointOnLine(RigidBody body1, RigidBody body2, JVector lineStartPointBody1, JVector pointBody2) : base(body1,body2) { JVector.Subtract(ref lineStartPointBody1, ref body1.position, out localAnchor1); JVector.Subtract(ref pointBody2, ref body2.position, out localAnchor2); JVector.Transform(ref localAnchor1, ref body1.invOrientation, out localAnchor1); JVector.Transform(ref localAnchor2, ref body2.invOrientation, out localAnchor2); lineNormal = JVector.Normalize(lineStartPointBody1 - pointBody2); }
/// <summary> /// Initializes a new instance of the HingeJoint class. /// </summary> /// <param name="world">The world class where the constraints get added to.</param> /// <param name="body1">The first body connected to the second one.</param> /// <param name="body2">The second body connected to the first one.</param> /// <param name="position">The position in world space where both bodies get connected.</param> /// <param name="hingeAxis">The axis if the hinge.</param> public HingeJoint(World world, RigidBody body1, RigidBody body2, JVector position, JVector hingeAxis) : base(world) { worldPointConstraint = new PointOnPoint[2]; hingeAxis *= 0.5f; JVector pos1 = position; JVector.Add(ref pos1,ref hingeAxis,out pos1); JVector pos2 = position; JVector.Subtract(ref pos2,ref hingeAxis,out pos2); worldPointConstraint[0] = new PointOnPoint(body1,body2,pos1); worldPointConstraint[1] = new PointOnPoint(body1,body2,pos2); }
/// <summary> /// SupportMapping. Finds the point in the shape furthest away from the given direction. /// Imagine a plane with a normal in the search direction. Now move the plane along the normal /// until the plane does not intersect the shape. The last intersection point is the result. /// </summary> /// <param name="direction">The direction.</param> /// <param name="result">The result.</param> public override void SupportMapping(ref JVector direction, out JVector result) { float maxDotProduct = float.MinValue; int maxIndex = 0; float dotProduct; for (int i = 0; i < vertices.Count; i++) { dotProduct = JVector.Dot(vertices[i], direction); if (dotProduct > maxDotProduct) { maxDotProduct = dotProduct; maxIndex = i; } } result = vertices[maxIndex] - this.shifted; }
public static int[] Build(List<JVector> pointCloud, Approximation factor) { List<int> allIndices = new List<int>(); int steps = (int)factor; for (int thetaIndex = 0; thetaIndex < steps; thetaIndex++) { // [0,PI] float theta = JMath.Pi / (steps - 1) * thetaIndex; float sinTheta = (float)Math.Sin(theta); float cosTheta = (float)Math.Cos(theta); for (int phiIndex = 0; phiIndex < steps; phiIndex++) { // [-PI,PI] float phi = (2.0f * JMath.Pi) / (steps - 0) * phiIndex - JMath.Pi; float sinPhi = (float)Math.Sin(phi); float cosPhi = (float)Math.Cos(phi); JVector dir = new JVector(sinTheta * cosPhi, cosTheta, sinTheta * sinPhi); int index = FindExtremePoint(pointCloud, ref dir); allIndices.Add(index); } } allIndices.Sort(); for (int i = 1; i < allIndices.Count; i++) { if (allIndices[i - 1] == allIndices[i]) { allIndices.RemoveAt(i - 1); i--; } } return allIndices.ToArray(); // or using 3.5 extensions // return allIndices.Distinct().ToArray(); }
/// <summary> /// Creates a matrix which rotates around the given axis by the given angle. /// </summary> /// <param name="axis">The axis.</param> /// <param name="angle">The angle.</param> /// <param name="result">The resulting rotation matrix</param> #region public static void CreateFromAxisAngle(ref JVector axis, float angle, out JMatrix result) public static void CreateFromAxisAngle(ref JVector axis, float angle, out JMatrix result) { float x = axis.X; float y = axis.Y; float z = axis.Z; float num2 = (float)Math.Sin((double)angle); float num = (float)Math.Cos((double)angle); float num11 = x * x; float num10 = y * y; float num9 = z * z; float num8 = x * y; float num7 = x * z; float num6 = y * z; result.M11 = num11 + (num * (1f - num11)); result.M12 = (num8 - (num * num8)) + (num2 * z); result.M13 = (num7 - (num * num7)) - (num2 * y); result.M21 = (num8 - (num * num8)) - (num2 * z); result.M22 = num10 + (num * (1f - num10)); result.M23 = (num6 - (num * num6)) + (num2 * x); result.M31 = (num7 - (num * num7)) + (num2 * y); result.M32 = (num6 - (num * num6)) - (num2 * x); result.M33 = num9 + (num * (1f - num9)); }
/// <summary> /// Transforms the bounding box into the space given by orientation and position. /// </summary> /// <param name="position"></param> /// <param name="orientation"></param> /// <param name="result"></param> internal void InverseTransform(ref JVector position, ref JMatrix orientation) { JVector.Subtract(ref Max, ref position, out Max); JVector.Subtract(ref Min, ref position, out Min); JVector center; JVector.Add(ref Max, ref Min, out center); center.X *= 0.5f; center.Y *= 0.5f; center.Z *= 0.5f; JVector halfExtents; JVector.Subtract(ref Max, ref Min, out halfExtents); halfExtents.X *= 0.5f; halfExtents.Y *= 0.5f; halfExtents.Z *= 0.5f; JVector.TransposedTransform(ref center, ref orientation, out center); JMatrix abs; JMath.Absolute(ref orientation, out abs); JVector.TransposedTransform(ref halfExtents, ref abs, out halfExtents); JVector.Add(ref center, ref halfExtents, out Max); JVector.Subtract(ref center, ref halfExtents, out Min); }
/// <summary> /// /// </summary> /// <param name="rayOrigin"></param> /// <param name="rayDelta"></param> /// <returns></returns> public abstract int Prepare(ref JVector rayOrigin, ref JVector rayDelta);
public bool RayIntersect(JVector origin, JVector direction) { return(RayIntersect(ref origin, ref direction)); }
/// <summary> /// Checks whether a point is inside, outside or intersecting /// a point. /// </summary> /// <param name="point">A point in space.</param> /// <returns>The ContainmentType of the point.</returns> public ContainmentType Contains(ref JVector point) { return ((((this.Min.X <= point.X) && (point.X <= this.Max.X)) && ((this.Min.Y <= point.Y) && (point.Y <= this.Max.Y))) && ((this.Min.Z <= point.Z) && (point.Z <= this.Max.Z))) ? ContainmentType.Contains : ContainmentType.Disjoint; }
public void AddPoint(ref JVector point) { JVector.Max(ref this.Max, ref point, out this.Max); JVector.Min(ref this.Min, ref point, out this.Min); }
public static JBBox CreateFromPoints(JVector[] points) { JVector vector3 = new JVector(float.MaxValue); JVector vector2 = new JVector(float.MinValue); for (int i = 0; i < points.Length; i++) { JVector.Min(ref vector3, ref points[i], out vector3); JVector.Max(ref vector2, ref points[i], out vector2); } return new JBBox(vector3, vector2); }
/// <summary> /// Translate all subshapes in the way that the center of mass is /// in (0,0,0) /// </summary> private void DoShifting() { for (int i = 0; i < Shapes.Length; i++) shifted += Shapes[i].position; shifted *= (1.0f / shapes.Length); for (int i = 0; i < Shapes.Length; i++) Shapes[i].position -= shifted; }
/// <summary> /// Constructor /// </summary> /// <param name="min">The minimum point of the box.</param> /// <param name="max">The maximum point of the box.</param> public JBBox(JVector min, JVector max) { this.Min = min; this.Max = max; }
public void AddPoint(JVector point) { AddPoint(ref point); }
/// <summary> /// Checks whether a point is inside, outside or intersecting /// a point. /// </summary> /// <param name="point">A point in space.</param> /// <returns>The ContainmentType of the point.</returns> public ContainmentType Contains(ref JVector point) { return(((((this.Min.X <= point.X) && (point.X <= this.Max.X)) && ((this.Min.Y <= point.Y) && (point.Y <= this.Max.Y))) && ((this.Min.Z <= point.Z) && (point.Z <= this.Max.Z))) ? ContainmentType.Contains : ContainmentType.Disjoint); }
/// <summary> /// Checks wether a point is within a box or not. /// </summary> /// <param name="point"></param> /// <returns></returns> public ContainmentType Contains(JVector point) { return(this.Contains(ref point)); }
/// <summary> /// /// </summary> /// <param name="rayOrigin"></param> /// <param name="rayEnd"></param> /// <returns></returns> public override int Prepare(ref JVector rayOrigin, ref JVector rayEnd) { JBBox box = JBBox.SmallBox; box.AddPoint(ref rayOrigin); box.AddPoint(ref rayEnd); return this.Prepare(ref box); }
public bool RayIntersect(JVector origin, JVector direction) { return RayIntersect(ref origin, ref direction); }
/// <summary> /// SupportMapping. Finds the point in the shape furthest away from the given direction. /// Imagine a plane with a normal in the search direction. Now move the plane along the normal /// until the plane does not intersect the shape. The last intersection point is the result. /// </summary> /// <param name="direction">The direction.</param> /// <param name="result">The result.</param> public override void SupportMapping(ref JVector direction, out JVector result) { JVector.Transform(ref direction, ref shapes[currentShape].invOrientation, out result); shapes[currentShape].Shape.SupportMapping(ref direction, out result); JVector.Transform(ref result, ref shapes[currentShape].orientation, out result); JVector.Add(ref result, ref shapes[currentShape].position, out result); }
public bool SegmentIntersect(JVector origin, JVector direction) { return SegmentIntersect(ref origin, ref direction); }
/// <summary> /// Creates a new instance of the TransformedShape struct. /// </summary> /// <param name="shape">The shape.</param> /// <param name="orientation">The orientation this shape should have.</param> /// <param name="position">The position this shape should have.</param> public TransformedShape(Shape shape, JMatrix orientation, JVector position) { this.position = position; this.orientation = orientation; JMatrix.Transpose(ref orientation, out invOrientation); this.shape = shape; this.boundingBox = new JBBox(); UpdateBoundingBox(); }
/// <summary> /// Creates a matrix which rotates around the given axis by the given angle. /// </summary> /// <param name="axis">The axis.</param> /// <param name="angle">The angle.</param> /// <returns>The resulting rotation matrix</returns> public static JMatrix CreateFromAxisAngle(JVector axis, float angle) { JMatrix result; CreateFromAxisAngle(ref axis, angle, out result); return result; }
/// <summary> /// Checks wether a point is within a box or not. /// </summary> /// <param name="point"></param> /// <returns></returns> public ContainmentType Contains(JVector point) { return this.Contains(ref point); }
public bool UpdateClosestVectorAndPoints() { if (_needsUpdate) { _cachedBC.Reset(); _needsUpdate = false; JVector p, a, b, c, d; switch (NumVertices) { case 0: _cachedValidClosest = false; break; case 1: _cachedPA = _simplexPointsP[0]; _cachedPB = _simplexPointsQ[0]; _cachedV = _cachedPA - _cachedPB; _cachedBC.Reset(); _cachedBC.SetBarycentricCoordinates(1f, 0f, 0f, 0f); _cachedValidClosest = _cachedBC.IsValid; break; case 2: //closest point origin from line segment JVector from = _simplexVectorW[0]; JVector to = _simplexVectorW[1]; JVector nearest; JVector diff = from * (-1); JVector v = to - from; float t = JVector.Dot(v, diff); if (t > 0) { float dotVV = v.LengthSquared(); if (t < dotVV) { t /= dotVV; diff -= t * v; _cachedBC.UsedVertices.UsedVertexA = true; _cachedBC.UsedVertices.UsedVertexB = true; } else { t = 1; diff -= v; //reduce to 1 point _cachedBC.UsedVertices.UsedVertexB = true; } } else { t = 0; //reduce to 1 point _cachedBC.UsedVertices.UsedVertexA = true; } _cachedBC.SetBarycentricCoordinates(1 - t, t, 0, 0); nearest = from + t * v; _cachedPA = _simplexPointsP[0] + t * (_simplexPointsP[1] - _simplexPointsP[0]); _cachedPB = _simplexPointsQ[0] + t * (_simplexPointsQ[1] - _simplexPointsQ[0]); _cachedV = _cachedPA - _cachedPB; ReduceVertices(_cachedBC.UsedVertices); _cachedValidClosest = _cachedBC.IsValid; break; case 3: //closest point origin from triangle p = new JVector(); a = _simplexVectorW[0]; b = _simplexVectorW[1]; c = _simplexVectorW[2]; ClosestPtPointTriangle(p, a, b, c, ref _cachedBC); _cachedPA = _simplexPointsP[0] * _cachedBC.BarycentricCoords[0] + _simplexPointsP[1] * _cachedBC.BarycentricCoords[1] + _simplexPointsP[2] * _cachedBC.BarycentricCoords[2] + _simplexPointsP[3] * _cachedBC.BarycentricCoords[3]; _cachedPB = _simplexPointsQ[0] * _cachedBC.BarycentricCoords[0] + _simplexPointsQ[1] * _cachedBC.BarycentricCoords[1] + _simplexPointsQ[2] * _cachedBC.BarycentricCoords[2]+ _simplexPointsQ[3] * _cachedBC.BarycentricCoords[3]; _cachedV = _cachedPA - _cachedPB; ReduceVertices(_cachedBC.UsedVertices); _cachedValidClosest = _cachedBC.IsValid; break; case 4: p = new JVector(); a = _simplexVectorW[0]; b = _simplexVectorW[1]; c = _simplexVectorW[2]; d = _simplexVectorW[3]; bool hasSeperation = ClosestPtPointTetrahedron(p, a, b, c, d, ref _cachedBC); if (hasSeperation) { _cachedPA = _simplexPointsP[0] * _cachedBC.BarycentricCoords[0] + _simplexPointsP[1] * _cachedBC.BarycentricCoords[1] + _simplexPointsP[2] * _cachedBC.BarycentricCoords[2] + _simplexPointsP[3] * _cachedBC.BarycentricCoords[3]; _cachedPB = _simplexPointsQ[0] * _cachedBC.BarycentricCoords[0] + _simplexPointsQ[1] * _cachedBC.BarycentricCoords[1] + _simplexPointsQ[2] * _cachedBC.BarycentricCoords[2] + _simplexPointsQ[3] * _cachedBC.BarycentricCoords[3]; _cachedV = _cachedPA - _cachedPB; ReduceVertices(_cachedBC.UsedVertices); } else { if (_cachedBC.Degenerate) { _cachedValidClosest = false; } else { _cachedValidClosest = true; //degenerate case == false, penetration = true + zero _cachedV.X = _cachedV.Y = _cachedV.Z = 0f; } break; // !!!!!!!!!!!! proverit na vsakiy sluchai } _cachedValidClosest = _cachedBC.IsValid; //closest point origin from tetrahedron break; default: _cachedValidClosest = false; break; } } return _cachedValidClosest; }
public void GetCorners(JVector[] corners) { corners[0].Set(this.Min.X, this.Max.Y, this.Max.Z); corners[1].Set(this.Max.X, this.Max.Y, this.Max.Z); corners[2].Set(this.Max.X, this.Min.Y, this.Max.Z); corners[3].Set(this.Min.X, this.Min.Y, this.Max.Z); corners[4].Set(this.Min.X, this.Max.Y, this.Min.Z); corners[5].Set(this.Max.X, this.Max.Y, this.Min.Z); corners[6].Set(this.Max.X, this.Min.Y, this.Min.Z); corners[7].Set(this.Min.X, this.Min.Y, this.Min.Z); }
public bool SegmentIntersect(JVector origin, JVector direction) { return(SegmentIntersect(ref origin, ref direction)); }
public bool SegmentIntersect(ref JVector origin,ref JVector direction) { float enter = 0.0f, exit = 1.0f; if (!Intersect1D(origin.X, direction.X, Min.X, Max.X,ref enter,ref exit)) return false; if (!Intersect1D(origin.Y, direction.Y, Min.Y, Max.Y, ref enter, ref exit)) return false; if (!Intersect1D(origin.Z, direction.Z, Min.Z, Max.Z,ref enter,ref exit)) return false; return true; }
public bool InSimplex(JVector w) { //check in case lastW is already removed if (w == _lastW) return true; //w is in the current (reduced) simplex int numverts = NumVertices; for (int i = 0; i < numverts; i++) if (_simplexVectorW[i] == w) return true; return false; }
public void Transform(ref JMatrix orientation) { JVector halfExtents = 0.5f * (Max - Min); JVector center = 0.5f * (Max + Min); JVector.Transform(ref center, ref orientation, out center); JMatrix abs; JMath.Absolute(ref orientation, out abs); JVector.Transform(ref halfExtents, ref abs, out halfExtents); Max = center + halfExtents; Min = center - halfExtents; }
/// Test if point p and d lie on opposite sides of plane through abc public int PointOutsideOfPlane(JVector p, JVector a, JVector b, JVector c, JVector d) { JVector normal = JVector.Cross(b - a, c - a); float signp = JVector.Dot(p - a, normal); // [AP AB AC] float signd = JVector.Dot(d - a, normal); // [AD AB AC] //if (CatchDegenerateTetrahedron) if (signd * signd < (1e-4f * 1e-4f)) return -1; // Points on opposite sides if expression signs are opposite return signp * signd < 0f ? 1 : 0; }
public void Reset() { _cachedValidClosest = false; _numVertices = 0; _needsUpdate = true; _lastW = new JVector(1e30f, 1e30f, 1e30f); _cachedBC.Reset(); }