コード例 #1
0
        public bool Hit(Ray r, double tMin, double tMax, out HitRecord hr)
        {
            var t = (K - r.Origin.y) / r.Dir.y;

            if (t < tMin || t > tMax)
            {
                hr = default(HitRecord);
                return(false);
            }

            var x = r.Origin.x + t * r.Dir.x;
            var z = r.Origin.z + t * r.Dir.z;

            if (x < X0 || x > X1 || z < Z0 || z > Z1)
            {
                hr = default;
                return(false);
            }

            var u             = (x - X0) / (X1 - X0);
            var v             = (z - Z0) / (Z1 - Z0);
            var outwardNormal = new Vec3(0, 1, 0);

            hr = new HitRecord
            {
                T        = t,
                Point    = r.At(t),
                Material = Mp,
                U        = u,
                V        = v
            };
            hr.SetFaceNormal(r, outwardNormal);
            return(true);
        }
コード例 #2
0
ファイル: ConstantMedium.cs プロジェクト: rje/ray
        public bool Hit(Ray r, double tMin, double tMax, out HitRecord hr)
        {
            hr = default;
            if (!Boundary.Hit(r, -MathUtils.Infinity, MathUtils.Infinity, out var hr1))
            {
                return(false);
            }

            if (!Boundary.Hit(r, hr1.T + 0.0001, MathUtils.Infinity, out var hr2))
            {
                return(false);
            }

            if (hr1.T < tMin)
            {
                hr1.T = tMin;
            }
            if (hr2.T > tMax)
            {
                hr2.T = tMax;
            }

            if (hr1.T >= hr2.T)
            {
                return(false);
            }

            if (hr1.T < 0)
            {
                hr1.T = 0;
            }

            var rayLen             = r.Dir.Length;
            var distInsideBoundary = (hr2.T - hr1.T) * rayLen;
            var hitDist            = NegInvDensity * Math.Log(MathUtils.RandDouble());

            if (hitDist > distInsideBoundary)
            {
                return(false);
            }

            var t = hr1.T + hitDist / rayLen;
            var p = r.At(t);

            hr = new HitRecord
            {
                Point       = p,
                T           = t,
                IsFrontFace = true,
                Material    = PhaseFunction,
                Normal      = new Vec3(1, 0, 0),
                U           = 0,
                V           = 0
            };
            return(true);
        }
コード例 #3
0
ファイル: Sphere.cs プロジェクト: amvi88/YetAnotherRaytracer
        public HitData IsHit(Ray ray, double tMin, double tMax)
        {
            HitData result = new HitData {
                IsHit = false
            };

            Vector3 oc           = ray.Origin - this.Center;
            var     a            = ray.Direction.LengthSquared;
            var     half_b       = Vector3.DotProduct(oc, ray.Direction);
            var     c            = oc.LengthSquared - this.Radius * Radius;
            var     discriminant = half_b * half_b - a * c;

            if (discriminant > 0)
            {
                var root = Math.Sqrt(discriminant);
                var temp = (-half_b - root) / a;
                if (temp < tMax && temp > tMin)
                {
                    result.T      = temp;
                    result.P      = ray.At(result.T);
                    result.Normal = (result.P - this.Center) / this.Radius;
                    result.IsHit  = true;

                    Vector3 outwardNormal = (result.P - this.Center) / this.Radius;
                    result.SetFaceNormal(ray, outwardNormal);
                    return(result);
                }
                temp = (-half_b + root) / a;
                if (temp < tMax && temp > tMin)
                {
                    result.T      = temp;
                    result.P      = ray.At(result.T);
                    result.Normal = (result.P - this.Center) / this.Radius;
                    result.IsHit  = true;

                    Vector3 outwardNormal = (result.P - this.Center) / this.Radius;
                    result.SetFaceNormal(ray, outwardNormal);
                    return(result);
                }
            }
            return(result);
        }
コード例 #4
0
        public bool Hit(Ray ray, double tMin, double tMax, out HitRecord hit)
        {
            var oc           = ray.Origin - Center;
            var a            = ray.Direction.LengthSquared;
            var halfB        = Vector3.Dot(oc, ray.Direction);
            var c            = oc.LengthSquared - Radius * Radius;
            var discriminant = halfB * halfB - a * c;

            hit = default;

            if (discriminant > 0)
            {
                var root = Math.Sqrt(discriminant);

                var temp = (-halfB - root) / a;

                if (temp < tMax && temp > tMin)
                {
                    hit.T     = temp;
                    hit.Point = ray.At(hit.T);

                    var outwardNormal = (hit.Point - Center) / Radius;
                    hit.SetFaceNormal(ray, outwardNormal);
                    return(true);
                }

                temp = (-halfB + root) / a;

                if (temp < tMax && temp > tMin)
                {
                    hit.T     = temp;
                    hit.Point = ray.At(hit.T);

                    var outwardNormal = (hit.Point - Center) / Radius;
                    hit.SetFaceNormal(ray, outwardNormal);
                    return(true);
                }
            }

            return(false);
        }
コード例 #5
0
        public bool Hit(Ray r, double tMin, double tMax, out HitRecord hitRec)
        {
            var center = CenterForTime(r.Time);
            var oc     = r.Origin - center;
            var a      = r.Dir.LengthSquared;
            var halfB  = Vec3.Dot(oc, r.Dir);
            var c      = oc.LengthSquared - Radius * Radius;

            var disc = halfB * halfB - a * c;

            if (disc < 0)
            {
                hitRec = default(HitRecord);
                return(false);
            }

            var sqrtd = Math.Sqrt(disc);

            var root = (-halfB - sqrtd) / a;

            if (root < tMin || tMax < root)
            {
                root = (-halfB + sqrtd) / a;
                if (root < tMin || tMax < root)
                {
                    hitRec = default(HitRecord);
                    return(false);
                }
            }

            var t             = root;
            var point         = r.At(t);
            var outwardNormal = (point - center) / Radius;

            Sphere.GetSphereUV(outwardNormal, out var u, out var v);
            hitRec = new HitRecord
            {
                T        = t,
                Point    = point,
                Material = Material,
                U        = u,
                V        = v
            };
            hitRec.SetFaceNormal(r, outwardNormal);
            return(true);
        }
コード例 #6
0
        public void AtTest()
        {
            Point3 origin = new Point3(); // TODO: Initialize to an appropriate value

            Point3 lookAt = new Point3(); // TODO: Initialize to an appropriate value

            Ray target = new Ray(origin, lookAt);

            double t = 0; // TODO: Initialize to an appropriate value

            Point3 expected = new Point3();
            Point3 actual;

            actual = target.At(t);

            Assert.AreEqual(expected, actual, "Aurora.Ray.At did not return the expected value.");
            Assert.Inconclusive("Verify the correctness of this test method.");
        }
コード例 #7
0
 /// <summary>Adds a line based on a ray to the environment for the
 /// current frame.</summary>
 /// <param name="ray">The ray we want to visualize!</param>
 /// <param name="length">How long should the ray be? Actual length
 /// will be ray.direction.Magnitude * length.</param>
 /// <param name="color">Color for the line, this is embedded in the
 /// vertex color of the line.</param>
 /// <param name="thickness">Thickness of the line in meters.</param>
 public static void Add(Ray ray, float length, Color32 color, float thickness)
 => NativeAPI.line_add(ray.position, ray.At(length), color, color, thickness);
コード例 #8
0
ファイル: DemoMath.cs プロジェクト: studentutu/StereoKit
    public void Update()
    {
        Color colIntersect = Color.HSV(0, 0.8f, 1);
        Color colTest      = Color.HSV(0, 0.6f, 1);
        Color colObj       = Color.HSV(0.05f, 0.7f, 1);
        Color active       = new Color(1, 1, 1, 0.7f);
        Color notActive    = new Color(1, 1, 1, 1);

        // Plane and Ray
        bool planeRayActive = UI.HandleBegin("PlaneRay", ref posePlaneRay, new Bounds(Vec3.One * 0.4f));

        boundsMesh.Draw(boundsMat, Matrix.S(0.4f), planeRayActive ? active:notActive);

        Plane ground    = new Plane(new Vec3(1, 2, 0), 0);
        Ray   groundRay = new Ray(Vec3.Zero + new Vec3(0, 0.2f, 0), Vec3.AngleXZ(Time.Totalf * 90, -2).Normalized);

        Lines.Add(groundRay.position, groundRay.At(0.1f), new Color32(255, 0, 0, 255), 2 * Units.mm2m);
        planeMesh.Draw(material, Matrix.TRS(Vec3.Zero, Quat.LookDir(ground.normal), 0.25f), colObj);
        if (groundRay.Intersect(ground, out Vec3 groundAt))
        {
            sphereMesh.Draw(material, Matrix.TS(groundAt, 0.02f), colIntersect);
        }

        UI.HandleEnd();

        Tests.Screenshot("RayIntersectPlane.jpg", 400, 400, posePlaneRay.position + new Vec3(0.0f, 0.3f, 0.15f), posePlaneRay.position + Vec3.Up * 0.1f);

        // Line and Plane
        bool linePlaneActive = UI.HandleBegin("LinePlane", ref poseLinePlane, new Bounds(Vec3.One * 0.4f));

        boundsMesh.Draw(boundsMat, Matrix.S(0.4f), linePlaneActive ? active : notActive);

        Plane groundLinePlane = new Plane(new Vec3(1, 2, 0), 0);
        Ray   groundLineRay   = new Ray(Vec3.Zero + new Vec3(0, 0.25f, 0), Vec3.AngleXZ(Time.Totalf * 90, -2).Normalized);
        Vec3  groundLineP1    = groundLineRay.At((SKMath.Cos(Time.Totalf * 3) + 1) * 0.2f);
        Vec3  groundLineP2    = groundLineRay.At((SKMath.Cos(Time.Totalf * 3) + 1) * 0.2f + 0.1f);

        Lines.Add(groundLineP1, groundLineP2, colTest, 2 * Units.mm2m);
        sphereMesh.Draw(material, Matrix.TS(groundLineP1, 0.01f), colTest);
        sphereMesh.Draw(material, Matrix.TS(groundLineP2, 0.01f), colTest);
        bool groundLineIntersects = groundLinePlane.Intersect(groundLineP1, groundLineP2, out Vec3 groundLineAt);

        planeMesh.Draw(material, Matrix.TRS(Vec3.Zero, Quat.LookDir(groundLinePlane.normal), 0.25f), groundLineIntersects? colIntersect : colObj);
        if (groundLineIntersects)
        {
            sphereMesh.Draw(material, Matrix.TS(groundLineAt, 0.02f), colIntersect);
        }

        UI.HandleEnd();

        Tests.Screenshot("LineIntersectPlane.jpg", 400, 400, poseLinePlane.position + new Vec3(0.0f, 0.3f, 0.15f), poseLinePlane.position + Vec3.Up * 0.1f);

        // Sphere and Ray
        bool sphereRayActive = UI.HandleBegin("SphereRay", ref poseSphereRay, new Bounds(Vec3.One * 0.4f));

        boundsMesh.Draw(boundsMat, Matrix.S(0.4f), sphereRayActive ? active : notActive);

        Sphere sphere    = new Sphere(Vec3.Zero, 0.25f);
        Vec3   sphereDir = Vec3.AngleXZ(Time.Totalf * 90, SKMath.Cos(Time.Totalf * 3) * 1.5f + 0.1f).Normalized;
        Ray    sphereRay = new Ray(sphere.center - sphereDir * 0.35f, sphereDir);

        Lines.Add(sphereRay.position, sphereRay.At(0.1f), colTest, 2 * Units.mm2m);
        if (sphereRay.Intersect(sphere, out Vec3 sphereAt))
        {
            sphereMesh.Draw(material, Matrix.TS(sphereAt, 0.02f), colIntersect);
        }
        sphereMesh.Draw(material, Matrix.TS(sphere.center, 0.25f), colObj);

        UI.HandleEnd();

        Tests.Screenshot("RayIntersectSphere.jpg", 400, 400, poseSphereRay.position + new Vec3(0.0f, 0.3f, 0.15f), poseSphereRay.position);

        // Bounds and Ray
        bool boundsRayActive = UI.HandleBegin("BoundsRay", ref poseBoundsRay, new Bounds(Vec3.One * 0.4f));

        boundsMesh.Draw(boundsMat, Matrix.S(0.4f), boundsRayActive ? active : notActive);

        Bounds bounds    = new Bounds(Vec3.Zero, Vec3.One * 0.25f);
        Vec3   boundsDir = Vec3.AngleXZ(Time.Totalf * 90, SKMath.Cos(Time.Totalf * 3) * 1.5f).Normalized;
        Ray    boundsRay = new Ray(bounds.center - boundsDir * 0.35f, boundsDir);

        Lines.Add(boundsRay.position, boundsRay.At(0.1f), colTest, 2 * Units.mm2m);
        if (boundsRay.Intersect(bounds, out Vec3 boundsAt))
        {
            sphereMesh.Draw(material, Matrix.TS(boundsAt, 0.02f), colIntersect);
        }
        cubeMesh.Draw(material, Matrix.TS(bounds.center, 0.25f), colObj);

        UI.HandleEnd();

        Tests.Screenshot("RayIntersectBounds.jpg", 400, 400, poseBoundsRay.position + new Vec3(0.0f, 0.3f, 0.15f), poseBoundsRay.position);

        // Bounds and Line
        bool boundsLineActive = UI.HandleBegin("BoundsLine", ref poseBoundsLine, new Bounds(Vec3.One * 0.4f));

        boundsMesh.Draw(boundsMat, Matrix.TS(Vec3.Zero, 0.4f), boundsLineActive ? active : notActive);

        Bounds boundsLine   = new Bounds(Vec3.Zero, Vec3.One * 0.25f);
        Vec3   boundsLineP1 = boundsLine.center + Vec3.AngleXZ(Time.Totalf * 45, SKMath.Cos(Time.Totalf * 3)) * 0.35f;
        Vec3   boundsLineP2 = boundsLine.center + Vec3.AngleXZ(Time.Totalf * 90, SKMath.Cos(Time.Totalf * 6)) * SKMath.Cos(Time.Totalf) * 0.35f;

        Lines.Add(boundsLineP1, boundsLineP2, colTest, 2 * Units.mm2m);
        sphereMesh.Draw(material, Matrix.TS(boundsLineP1, 0.01f), colTest);
        sphereMesh.Draw(material, Matrix.TS(boundsLineP2, 0.01f), colTest);
        cubeMesh.Draw(material, Matrix.TS(boundsLine.center, 0.25f),
                      boundsLine.Contains(boundsLineP1, boundsLineP2) ? colIntersect : colObj);

        UI.HandleEnd();

        Tests.Screenshot("LineIntersectBounds.jpg", 400, 400, poseBoundsLine.position + new Vec3(0.0f, 0.3f, 0.15f), poseBoundsLine.position);

        // Mesh and Ray
        bool meshRayActive = UI.HandleBegin("MeshRay", ref poseMeshRay, new Bounds(Vec3.One * 0.4f));

        boundsMesh.Draw(boundsMat, Matrix.S(0.4f), meshRayActive ? active : notActive);
        suzanne.Draw(material, Matrix.Identity, colObj);

        Vec3 meshDir = Vec3.AngleXZ(Time.Totalf * 90, SKMath.Cos(Time.Totalf * 3) * 1.5f).Normalized;
        Ray  meshRay = new Ray(bounds.center + Vec3.Up * 0.1f - meshDir * 0.35f, meshDir);

        if (meshRay.Intersect(suzanne, out Ray meshAt))
        {
            Lines.Add(meshRay.position, meshAt.position, colTest, 2 * Units.mm2m);
            sphereMesh.Draw(material, Matrix.TS(meshAt.position, 0.02f), colIntersect);
        }
        else
        {
            Lines.Add(meshRay.position, meshRay.At(0.4f), colTest, 2 * Units.mm2m);
        }

        UI.HandleEnd();

        //if (Tests.IsTesting)
        //    Renderer.Screenshot(poseBoundsLine.position + new Vec3(0.0f, 0.3f, 0.15f), poseBoundsLine.position, 400, 400, "../../../docs/img/screenshots/LineIntersectBounds.jpg");

        // Cross product
        bool crossActive = UI.HandleBegin("Cross", ref poseCross, new Bounds(Vec3.One * 0.4f));

        boundsMesh.Draw(boundsMat, Matrix.S(0.4f), crossActive ? active : notActive);

        Vec3 crossStart = Vec3.Zero;
        //Vec3 right      = Vec3.Cross(Vec3.Forward, Vec3.Up); // These are the same!
        Vec3 right = Vec3.PerpendicularRight(Vec3.Forward, Vec3.Up);

        Lines.Add(crossStart, crossStart + Vec3.Up * 0.1f, new Color32(255, 255, 255, 255), 2 * Units.mm2m);
        Lines.Add(crossStart, crossStart + Vec3.Forward * 0.1f, new Color32(255, 255, 255, 255), 2 * Units.mm2m);
        Lines.Add(crossStart, crossStart + right * 0.1f, new Color32(0, 255, 0, 255), 2 * Units.mm2m);
        Text.Add("Up", Matrix.TR(crossStart + Vec3.Up * 0.1f, Quat.LookDir(-Vec3.Forward)), TextAlign.BottomCenter);
        Text.Add("Fwd", Matrix.TR(crossStart + Vec3.Forward * 0.1f, Quat.LookDir(-Vec3.Forward)), TextAlign.BottomCenter);
        Text.Add("Vec3.Cross(Fwd,Up)", Matrix.TR(crossStart + right * 0.1f, Quat.LookDir(-Vec3.Forward)), TextAlign.BottomCenter);

        UI.HandleEnd();

        Tests.Screenshot("CrossProduct.jpg", 400, 400, poseCross.position + new Vec3(0.075f, 0.1f, 0.15f), poseCross.position + new Vec3(0.075f, 0, 0));
    }