public static bool InfiniteCylinderSigned(Vector3f vOrigin, Vector3f vDirection, Vector3f vCylOrigin, Vector3f vCylAxis, float fRadius, out float fRayT) { // [RMS] ugh this is shit...not even sure it works in general, but works for a ray inside cylinder fRayT = 0.0f; Vector3f AB = vCylAxis; Vector3f AO = (vOrigin - vCylOrigin); if (AO.DistanceSquared(AO.Dot(AB) * AB) > fRadius * fRadius) { return(false); } Vector3f AOxAB = AO.Cross(AB); Vector3f VxAB = vDirection.Cross(AB); float ab2 = AB.Dot(AB); float a = VxAB.Dot(VxAB); float b = 2 * VxAB.Dot(AOxAB); float c = AOxAB.Dot(AOxAB) - (fRadius * fRadius * ab2); double discrim = b * b - 4 * a * c; if (discrim <= 0) { return(false); } discrim = Math.Sqrt(discrim); fRayT = (-b - (float)discrim) / (2 * a); //float t1 = (-b + (float)discrim) / (2 * a); return(true); }
Vector2f propagate_uv(Vector3f pos, Vector2f nbrUV, ref Frame3f fNbr, ref Frame3f fSeed) { Vector2f local_uv = compute_local_uv(ref fNbr, pos); Frame3f fSeedToLocal = fSeed; fSeedToLocal.AlignAxis(2, fNbr.Z); Vector3f vAlignedSeedX = fSeedToLocal.X; Vector3f vLocalX = fNbr.X; float fCosTheta = vLocalX.Dot(vAlignedSeedX); // compute rotated min-dist vector for this particle float fTmp = 1 - fCosTheta * fCosTheta; if (fTmp < 0) { fTmp = 0; // need to clamp so that sqrt works... } float fSinTheta = (float)Math.Sqrt(fTmp); Vector3f vCross = vLocalX.Cross(vAlignedSeedX); if (vCross.Dot(fNbr.Z) < 0) // get the right sign... { fSinTheta = -fSinTheta; } Matrix2f mFrameRotate = new Matrix2f(fCosTheta, fSinTheta, -fSinTheta, fCosTheta); return(nbrUV + mFrameRotate * local_uv); }
public static float PlaneAngleSignedD(Vector3f vFrom, Vector3f vTo, int nPlaneNormalIdx = 1) { vFrom[nPlaneNormalIdx] = vTo[nPlaneNormalIdx] = 0.0f; vFrom.Normalize(); vTo.Normalize(); float fSign = Math.Sign(vFrom.Cross(vTo)[nPlaneNormalIdx]); float fAngle = fSign * Vector3f.AngleD(vFrom, vTo); return(fAngle); }
public static float PlaneAngleSignedD(Vector3f vFrom, Vector3f vTo, Vector3f planeN) { vFrom = vFrom - Vector3f.Dot(vFrom, planeN) * planeN; vTo = vTo - Vector3f.Dot(vTo, planeN) * planeN; vFrom.Normalize(); vTo.Normalize(); Vector3f c = Vector3f.Cross(vFrom, vTo); float fSign = Math.Sign(Vector3f.Dot(c, planeN)); float fAngle = fSign * Vector3f.AngleD(vFrom, vTo); return(fAngle); }
public static float PlaneAngleSignedD(Vector3f vFrom, Vector3f vTo, int nPlaneNormalIdx = 1) { vFrom[nPlaneNormalIdx] = vTo[nPlaneNormalIdx] = 0.0f; vFrom.Normalize(); vTo.Normalize(); Vector3f c = vFrom.Cross(vTo); if (c.LengthSquared < MathUtil.ZeroTolerancef) { // vectors are parallel return(vFrom.Dot(vTo) < 0 ? 180.0f : 0); } float fSign = Math.Sign(c[nPlaneNormalIdx]); float fAngle = fSign * Vector3f.AngleD(vFrom, vTo); return(fAngle); }
public static float PlaneAngleSignedD(Vector3f vFrom, Vector3f vTo, Vector3f planeN) { vFrom = vFrom - Vector3f.Dot(vFrom, planeN) * planeN; vTo = vTo - Vector3f.Dot(vTo, planeN) * planeN; vFrom.Normalize(); vTo.Normalize(); var c = Vector3f.Cross(vFrom, vTo); if (c.LengthSquared < MathUtil.ZeroTolerancef) { // vectors are parallel return(vFrom.Dot(vTo) < 0 ? 180.0f : 0); } float fSign = Math.Sign(Vector3f.Dot(c, planeN)); float fAngle = fSign * Vector3f.AngleD(vFrom, vTo); return(fAngle); }
// this function can take non-normalized vectors vFrom and vTo (normalizes internally) public void SetFromTo(Vector3f vFrom, Vector3f vTo) { // [TODO] this page seems to have optimized version: // http://lolengine.net/blog/2013/09/18/beautiful-maths-quaternion-from-vectors // [RMS] not ideal to explicitly normalize here, but if we don't, // output quaternion is not normalized and this causes problems, // eg like drift if we do repeated SetFromTo() Vector3f from = vFrom.Normalized, to = vTo.Normalized; Vector3f bisector = (from + to).Normalized; w = from.Dot(bisector); if (w != 0) { Vector3f cross = from.Cross(bisector); x = cross.x; y = cross.y; z = cross.z; } else { float invLength; if (Math.Abs(from.x) >= Math.Abs(from.y)) { // V1.x or V1.z is the largest magnitude component. invLength = (float)(1.0 / Math.Sqrt(from.x * from.x + from.z * from.z)); x = -from.z * invLength; y = 0; z = +from.x * invLength; } else { // V1.y or V1.z is the largest magnitude component. invLength = (float)(1.0 / Math.Sqrt(from.y * from.y + from.z * from.z)); x = 0; y = +from.z * invLength; z = -from.y * invLength; } } Normalize(); // aaahhh just to be safe... }
public bool Find() { if (Result != IntersectionResult.NotComputed) { return(Result != g3.IntersectionResult.NoIntersection); } // Compute the offset origin, edges, and normal. Vector3f diff = ray.Origin - triangle.V0; Vector3f edge1 = triangle.V1 - triangle.V0; Vector3f edge2 = triangle.V2 - triangle.V0; Vector3f normal = edge1.Cross(edge2); // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction, // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2)) // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q)) // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N) float DdN = ray.Direction.Dot(normal); float sign; if (DdN > MathUtil.ZeroTolerance) { sign = 1; } else if (DdN < -MathUtil.ZeroTolerance) { sign = -1; DdN = -DdN; } else { // Ray and triangle are parallel, call it a "no intersection" // even if the ray does intersect. Result = IntersectionResult.NoIntersection; return(false); } float DdQxE2 = sign * ray.Direction.Dot(diff.Cross(edge2)); if (DdQxE2 >= 0) { float DdE1xQ = sign * ray.Direction.Dot(edge1.Cross(diff)); if (DdE1xQ >= 0) { if (DdQxE2 + DdE1xQ <= DdN) { // Line intersects triangle, check if ray does. float QdN = -sign *diff.Dot(normal); if (QdN >= 0) { // Ray intersects triangle. float inv = (1) / DdN; RayParameter = QdN * inv; float mTriBary1 = DdQxE2 * inv; float mTriBary2 = DdE1xQ * inv; TriangleBaryCoords = new Vector3f(1 - mTriBary1 - mTriBary2, mTriBary1, mTriBary2); Type = IntersectionType.Point; Quantity = 1; Result = IntersectionResult.Intersects; return(true); } // else: t < 0, no intersection } // else: b1+b2 > 1, no intersection } // else: b2 < 0, no intersection } // else: b1 < 0, no intersection Result = IntersectionResult.NoIntersection; return(false); }
/// <summary> /// minimal intersection test, computes ray-t /// </summary> public static bool Intersects(ref Ray3f ray, ref Vector3f V0, ref Vector3f V1, ref Vector3f V2, out float rayT) { // Compute the offset origin, edges, and normal. Vector3f diff = ray.Origin - V0; Vector3f edge1 = V1 - V0; Vector3f edge2 = V2 - V0; Vector3f normal = edge1.Cross(ref edge2); rayT = float.MaxValue; // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction, // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2)) // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q)) // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N) float DdN = ray.Direction.Dot(ref normal); float sign; if (DdN > MathUtil.ZeroTolerance) { sign = 1; } else if (DdN < -MathUtil.ZeroTolerance) { sign = -1; DdN = -DdN; } else { // Ray and triangle are parallel, call it a "no intersection" // even if the ray does intersect. return(false); } Vector3f cross = diff.Cross(ref edge2); float DdQxE2 = sign * ray.Direction.Dot(ref cross); if (DdQxE2 >= 0) { cross = edge1.Cross(ref diff); float DdE1xQ = sign * ray.Direction.Dot(ref cross); if (DdE1xQ >= 0) { if (DdQxE2 + DdE1xQ <= DdN) { // Line intersects triangle, check if ray does. float QdN = -sign *diff.Dot(ref normal); if (QdN >= 0) { // Ray intersects triangle. float inv = (1) / DdN; rayT = QdN * inv; return(true); } // else: t < 0, no intersection } // else: b1+b2 > 1, no intersection } // else: b2 < 0, no intersection } // else: b1 < 0, no intersection return(false); }