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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
        }
예제 #6
0
        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);
        }
예제 #7
0
        // 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...
        }
예제 #8
0
        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);
        }
예제 #9
0
        /// <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);
        }