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); }
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); }
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); }
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); }
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); }
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."); }
/// <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);
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)); }