public void GetLocalVectorToOut(Vec2 worldVector, Vec2 result) { Rot.MulTrans(Xf.Q, worldVector, result); }
public override bool Raycast(RayCastOutput output, RayCastInput input, Transform xf, int childIndex) { // Put the ray into the edge's frame of reference. Vec2 p1 = pool0.Set(input.P1).SubLocal(xf.P); Rot.MulTrans(xf.Q, p1, p1); Vec2 p2 = pool1.Set(input.P2).SubLocal(xf.P); Rot.MulTrans(xf.Q, p1, p1); Vec2 d = p2.SubLocal(p1); // we don't use p2 later Vec2 v1 = Vertex1; Vec2 v2 = Vertex2; Vec2 normal = pool2.Set(v2).SubLocal(v1); normal.Set(normal.Y, -normal.X); normal.Normalize(); // q = p1 + t * d // dot(normal, q - v1) = 0 // dot(normal, p1 - v1) + t * dot(normal, d) = 0 pool3.Set(v1).SubLocal(p1); float numerator = Vec2.Dot(normal, pool3); float denominator = Vec2.Dot(normal, d); if (denominator == 0.0f) { return(false); } float t = numerator / denominator; if (t < 0.0f || 1.0f < t) { return(false); } Vec2 q = pool3; Vec2 r = pool4; // Vec2 q = p1 + t * d; q.Set(d).MulLocal(t).AddLocal(p1); // q = v1 + s * r // s = dot(q - v1, r) / dot(r, r) // Vec2 r = v2 - v1; r.Set(v2).SubLocal(v1); float rr = Vec2.Dot(r, r); if (rr == 0.0f) { return(false); } pool5.Set(q).SubLocal(v1); float s = Vec2.Dot(pool5, r) / rr; if (s < 0.0f || 1.0f < s) { return(false); } output.Fraction = t; if (numerator > 0.0f) { // argOutput.normal = -normal; output.Normal.Set(normal).NegateLocal(); } else { // output.normal = normal; output.Normal.Set(normal); } return(true); }
public override bool Raycast(RayCastOutput output, RayCastInput input, Transform xf, int childIndex) { Vec2 p1 = pool1; Vec2 p2 = pool2; Vec2 d = pool3; Vec2 temp = pool4; p1.Set(input.P1).SubLocal(xf.P); Rot.MulTrans(xf.Q, p1, p1); p2.Set(input.P2).SubLocal(xf.P); Rot.MulTrans(xf.Q, p2, p2); d.Set(p2).SubLocal(p1); // if (count == 2) { // } else { float lower = 0, upper = input.MaxFraction; int index = -1; for (int i = 0; i < VertexCount; ++i) { // p = p1 + a * d // dot(normal, p - v) = 0 // dot(normal, p1 - v) + a * dot(normal, d) = 0 temp.Set(Vertices[i]).SubLocal(p1); float numerator = Vec2.Dot(Normals[i], temp); float denominator = Vec2.Dot(Normals[i], d); if (denominator == 0.0f) { if (numerator < 0.0f) { return(false); } } else { // Note: we want this predicate without division: // lower < numerator / denominator, where denominator < 0 // Since denominator < 0, we have to flip the inequality: // lower < numerator / denominator <==> denominator * lower > // numerator. if (denominator < 0.0f && numerator < lower * denominator) { // Increase lower. // The segment enters this half-space. lower = numerator / denominator; index = i; } else if (denominator > 0.0f && numerator < upper * denominator) { // Decrease upper. // The segment exits this half-space. upper = numerator / denominator; } } if (upper < lower) { return(false); } } Debug.Assert(0.0f <= lower && lower <= input.MaxFraction); if (index >= 0) { output.Fraction = lower; Rot.MulToOutUnsafe(xf.Q, Normals[index], output.Normal); // normal = Mul(xf.R, m_normals[index]); return(true); } return(false); }