public override (double?, SurfaceInteraction) Intersect(Ray r) { var ray = WorldToObject.Apply(r); // Compute plane intersection for quad // Reject intersections for rays parallel to the quad's plane if (ray.d.z == 0) { return(null, null); } double tShapeHit = -ray.o.z / ray.d.z; if (tShapeHit <= Renderer.Epsilon) { return(null, null); } // See if hit point is inside var pHit = ray.Point(tShapeHit); if (pHit.x < -width / 2 || pHit.x > width / 2 || pHit.y < -height / 2 || pHit.y > height / 2) { return(null, null); } // Refine disk intersection point pHit.z = 0; var dpdu = new Vector3(1, 0, 0); var si = new SurfaceInteraction(pHit, new Vector3(0, 0, 1), -ray.d, dpdu, this); return(tShapeHit, ObjectToWorld.Apply(si)); }
public TransformBufferLayout(Matrix cameraToClipSpace, Matrix worldToCamera, Matrix objectToWorld) { Matrix clipSpaceToCamera = cameraToClipSpace; clipSpaceToCamera.Invert(); Matrix cameraToWorld = worldToCamera; cameraToWorld.Invert(); Matrix worldToObject = objectToWorld; worldToObject.Invert(); CameraToClipSpace = cameraToClipSpace; ClipSpaceToCamera = clipSpaceToCamera; WorldToCamera = worldToCamera; CameraToWorld = cameraToWorld; WorldToClipSpace = Matrix.Multiply(worldToCamera, cameraToClipSpace); ClipSpaceToWorld = Matrix.Multiply(clipSpaceToCamera, cameraToWorld); ObjectToWorld = objectToWorld; WorldToObject = worldToObject; ObjectToCamera = Matrix.Multiply(objectToWorld, worldToCamera); ObjectToClipSpace = Matrix.Multiply(ObjectToCamera, cameraToClipSpace); // transpose all as mem layout in hlsl constant buffer is row based CameraToClipSpace.Transpose(); ClipSpaceToCamera.Transpose(); WorldToCamera.Transpose(); CameraToWorld.Transpose(); WorldToClipSpace.Transpose(); ClipSpaceToWorld.Transpose(); ObjectToWorld.Transpose(); WorldToObject.Transpose(); ObjectToCamera.Transpose(); ObjectToClipSpace.Transpose(); }
public override (double?, SurfaceInteraction) Intersect(Ray _r) { Ray ray = WorldToObject.Apply(_r); double a = 1; double b = 2 * Vector3.Dot(ray.o, ray.d); double c = Vector3.Dot(ray.o, ray.o) - Radius * Radius; (bool hasSolution, double t0, double t1) = Utils.Quadratic(a, b, c); if (!hasSolution || (t0 < Renderer.Epsilon && t1 < Renderer.Epsilon)) { return(null, null); } double tHit = (t0 < Renderer.Epsilon ? t1 : t0); Vector3 pHit = ray.Point(tHit); Vector3 normal = pHit * (1.0 / Radius); Vector3 dpdu = new Vector3(-pHit.y, pHit.x, 0); SurfaceInteraction si = new SurfaceInteraction(pHit, normal, -ray.d, dpdu, this); return(tHit, ObjectToWorld.Apply(si)); }
private bool DoIntersection(Ray r, out float phi, out Point phit, out float thit) { phi = 0.0f; phit = new Point(); thit = 0.0f; // Transform _Ray_ to object space Ray ray = WorldToObject.TransformRay(r); // Compute quadratic cylinder coefficients float A = ray.Direction.X * ray.Direction.X + ray.Direction.Y * ray.Direction.Y; float B = 2 * (ray.Direction.X * ray.Origin.X + ray.Direction.Y * ray.Origin.Y); float C = ray.Origin.X * ray.Origin.X + ray.Origin.Y * ray.Origin.Y - _radius * _radius; // Solve quadratic equation for _t_ values float t0, t1; if (!MathUtility.TryQuadratic(A, B, C, out t0, out t1)) return false; // Compute intersection distance along ray if (t0 > ray.MaxT || t1 < ray.MinT) return false; thit = t0; if (t0 < ray.MinT) { thit = t1; if (thit > ray.MaxT) return false; } // Compute cylinder hit point and $\phi$ phit = ray.Evaluate(thit); phi = MathUtility.Atan2(phit.Y, phit.X); if (phi < 0.0) phi += 2.0f * MathUtility.Pi; // Test cylinder intersection against clipping parameters if (phit.Z < _zMin || phit.Z > _zMax || phi > _phiMax) { if (thit == t1) return false; thit = t1; if (t1 > ray.MaxT) return false; // Compute cylinder hit point and $\phi$ phit = ray.Evaluate(thit); phi = MathUtility.Atan2(phit.Y, phit.X); if (phi < 0.0f) phi += 2.0f * MathUtility.Pi; if (phit.Z < _zMin || phit.Z > _zMax || phi > _phiMax) return false; } return true; }
public override double Pdf(SurfaceInteraction _si, Vector3 wi) { SurfaceInteraction si = WorldToObject.Apply(_si); double dist2 = si.Point.LengthSquared(); if (dist2 <= Radius * Radius) { // Point inside sphere return(base.Pdf(_si, wi)); } // Point outside sphere double sinThetaMax = Radius / Math.Sqrt(dist2); double cosThetaMax = Utils.SinToCos(sinThetaMax); return(Samplers.UniformConePdf(cosThetaMax)); }
public override (SurfaceInteraction, double) Sample(SurfaceInteraction _si) { SurfaceInteraction si = WorldToObject.Apply(_si); double dc2 = si.Point.LengthSquared(); if (dc2 <= Radius * Radius) { // Point inside sphere return(base.Sample(_si)); } // Point outside sphere double dc = Math.Sqrt(dc2); double sinThetaMax = Radius / dc; double cosThetaMax = Utils.SinToCos(sinThetaMax); // Determine theta and phi for uniform cone sampling double cosTheta = (cosThetaMax - 1) * Samplers.ThreadSafeRandom.NextDouble() + 1; double sinTheta = Utils.CosToSin(cosTheta); double phi = Samplers.ThreadSafeRandom.NextDouble() * 2.0 * Math.PI; // Distance between reference point and sample point on sphere double ds = dc * cosTheta - Math.Sqrt(Math.Max(0, Radius * Radius - dc2 * sinTheta * sinTheta)); // Kosinusni zakon double cosAlpha = (dc2 + Radius * Radius - ds * ds) / (2 * dc * Radius); double sinAlpha = Utils.CosToSin(cosAlpha); // Construct coordinate system and use phi and theta as spherical coordinates to get point on sphere Vector3 wcZ = si.Point.Clone().Normalize(); (Vector3 wcX, Vector3 wcY) = Utils.CoordinateSystem(wcZ); Vector3 nObj = Utils.SphericalDirection(sinAlpha, cosAlpha, phi, wcX, wcY, wcZ); Vector3 pObj = nObj * Radius; // Surface interaction Vector3 dpdu = new Vector3(-nObj.y, nObj.x, 0.0); SurfaceInteraction siSample = new SurfaceInteraction(pObj, nObj, Vector3.ZeroVector, dpdu, this); // Uniform cone PDF double pdf = Samplers.UniformConePdf(cosThetaMax); return(ObjectToWorld.Apply(siSample), pdf); }
public override (double?, SurfaceInteraction) Intersect(Ray r) { var ray = WorldToObject.Apply(r); // TODO: Compute quadratic sphere coefficients // TODO: Initialize _double_ ray coordinate values double a = (ray.d.x * ray.d.x) + (ray.d.y * ray.d.y) + (ray.d.z * ray.d.z); double b = ((ray.d.x * ray.o.x) + (ray.d.y * ray.o.y) + (ray.d.z * ray.o.z)) * 2; double c = (ray.o.x * ray.o.x) + (ray.o.y * ray.o.y) + (ray.o.z * ray.o.z) - (Radius * Radius); // TODO: Solve quadratic equation for _t_ values (bool ok, double t0, double t1) = Utils.Quadratic(a, b, c); // TODO: Check quadric shape _t0_ and _t1_ for nearest intersection if (!ok /*|| t0 > ray.max*/ || t1 <= 0) { return(null, null); } // TODO: Compute sphere hit position and $\phi$ double tShapeHit = t0; if (tShapeHit <= Renderer.Epsilon) // skor 0. { tShapeHit = t1; //if (t1 > ray.max) //{ // return (null, null); //} } Vector3 pHit = ray.Point(tShapeHit); //pHit. if (pHit.x == 0 && pHit.y == 0) { pHit.x = 1e-5 * Radius; } Vector3 dpdu = new Vector3(-pHit.y, pHit.x, 0); // TODO: Return shape hit and surface interaction return(tShapeHit, ObjectToWorld.Apply(new SurfaceInteraction(pHit, pHit, -ray.d, dpdu, this))); }
private bool DoIntersection(Ray r, out float phi, out float dist2, out Point phit, out float thit) { phi = dist2 = thit = 0; phit = Point.Zero; // Transform _Ray_ to object space Ray ray = WorldToObject.TransformRay(r); // Compute plane intersection for disk if (Math.Abs(ray.Direction.Z) < 1e-7) { return(false); } thit = (_height - ray.Origin.Z) / ray.Direction.Z; if (thit < ray.MinT || thit > ray.MaxT) { return(false); } // See if hit point is inside disk radii and $\phimax$ phit = ray.Evaluate(thit); dist2 = phit.X * phit.X + phit.Y * phit.Y; if (dist2 > _radius * _radius || dist2 < _innerRadius * _innerRadius) { return(false); } // Test disk $\phi$ value against $\phimax$ phi = MathUtility.Atan2(phit.Y, phit.X); if (phi < 0) { phi += 2.0f * MathUtility.Pi; } if (phi > _phiMax) { return(false); } return(true); }
public override (double?, SurfaceInteraction) Intersect(Ray r) { Ray ray = WorldToObject.Apply(r); var ox = ray.o.x; var oy = ray.o.y; var oz = ray.o.z; var dx = ray.d.x; var dy = ray.d.y; var dz = ray.d.z; var a = dx * dx + dy * dy + dz * dz; var b = 2 * (dx * ox + dy * oy + dz * oz); var c = ox * ox + oy * oy + oz * oz - Radius * Radius; var(solvable, t0, t1) = Utils.Quadratic(a, b, c); if (!solvable) { return(null, null); } var shapeHit = t0 <= 0 ? t1 : t0; var hit = ray.Point(shapeHit); hit *= Radius / hit.Length(); if (Math.Abs(hit.x) < Double.Epsilon && Math.Abs(hit.y) < double.Epsilon) { hit.x = 1e-5 * Radius; } var dpdu = Dpdu(hit); var normal = innerOrientation ? -hit : hit; var interaction = new SurfaceInteraction(hit, normal, -ray.d, dpdu, this); return(shapeHit, ObjectToWorld.Apply(interaction)); }
public override (double?, SurfaceInteraction) Intersect(Ray ray) { Ray r = WorldToObject.Apply(ray); // Compute quadratic sphere coefficients // Initialize _double_ ray coordinate values double a = r.d.x * r.d.x + r.d.y * r.d.y + r.d.z * r.d.z; double b = 2 * (r.d.x * r.o.x + r.d.y * r.o.y + r.d.z * r.o.z); double c = r.o.x * r.o.x + r.o.y * r.o.y + r.o.z * r.o.z - Radius * Radius; // Solve quadratic equation for _t_ values (bool s, double t0, double t1) = Utils.Quadratic(a, b, c); if (!s) { return(null, null); } // Check quadric shape _t0_ and _t1_ for nearest intersection if (t1 <= 0) { return(null, null); } double tShapeHit = t0; if (tShapeHit <= Renderer.Epsilon) { tShapeHit = t1; } // Compute sphere hit position and $\phi$ var pHit = r.Point(tShapeHit); var dpdu = new Vector3(-pHit.y, pHit.x, 0); var si = new SurfaceInteraction(pHit, pHit.Clone().Normalize(), -r.d, dpdu, this); return(tShapeHit, ObjectToWorld.Apply(si)); }
public override (double?, SurfaceInteraction) Intersect(Ray r) { var ray = WorldToObject.Apply(r); // Compute plane intersection for disk // Reject disk intersections for rays parallel to the disk's plane if (ray.d.z == 0) { return(null, null); } double tShapeHit = (height - ray.o.z) / ray.d.z; if (tShapeHit <= Renderer.Epsilon) { return(null, null); } // See if hit point is inside disk radii and $\phimax$ var pHit = ray.Point(tShapeHit); var dist2 = pHit.x * pHit.x + pHit.y * pHit.y; if (dist2 > radius * radius + Renderer.Epsilon) { return(null, null); } // Refine disk intersection point pHit.z = height; var dpdu = new Vector3(-pHit.y, pHit.x, 0); var si = new SurfaceInteraction(pHit, new Vector3(0, 0, 1), -ray.d, dpdu, this); return(tShapeHit, ObjectToWorld.Apply(si)); }
private bool DoIntersection(Ray r, out float phi, out Point phit, out float thit) { phi = 0.0f; phit = new Point(); thit = 0.0f; // Transform _Ray_ to object space Ray ray = WorldToObject.TransformRay(r); // Compute quadratic sphere coefficients float A = ray.Direction.X * ray.Direction.X + ray.Direction.Y * ray.Direction.Y + ray.Direction.Z * ray.Direction.Z; float B = 2 * (ray.Direction.X * ray.Origin.X + ray.Direction.Y * ray.Origin.Y + ray.Direction.Z * ray.Origin.Z); float C = ray.Origin.X * ray.Origin.X + ray.Origin.Y * ray.Origin.Y + ray.Origin.Z * ray.Origin.Z - _radius * _radius; // Solve quadratic equation for _t_ values float t0, t1; if (!MathUtility.TryQuadratic(A, B, C, out t0, out t1)) { return(false); } // Compute intersection distance along ray if (t0 > ray.MaxT || t1 < ray.MinT) { return(false); } thit = t0; if (t0 < ray.MinT) { thit = t1; if (thit > ray.MaxT) { return(false); } } // Compute sphere hit position and $\phi$ phit = ray.Evaluate(thit); if (phit.X == 0.0f && phit.Y == 0.0f) { phit.X = 1e-5f * _radius; } phi = MathUtility.Atan2(phit.Y, phit.X); if (phi < 0.0f) { phi += 2.0f * MathUtility.Pi; } // Test sphere intersection against clipping parameters if ((_zMin > -_radius && phit.Z < _zMin) || (_zMax < _radius && phit.Z > _zMax) || phi > _phiMax) { if (thit == t1) { return(false); } if (t1 > ray.MaxT) { return(false); } thit = t1; // Compute sphere hit position and $\phi$ phit = ray.Evaluate(thit); if (phit.X == 0.0f && phit.Y == 0.0f) { phit.X = 1e-5f * _radius; } phi = MathUtility.Atan2(phit.Y, phit.X); if (phi < 0.0f) { phi += 2.0f * MathUtility.Pi; } if ((_zMin > -_radius && phit.Z < _zMin) || (_zMax < _radius && phit.Z > _zMax) || phi > _phiMax) { return(false); } } return(true); }
public override (double?, SurfaceInteraction) Intersect(Ray ray) { Ray r = WorldToObject.Apply(ray); // TODO: Compute quadratic sphere coefficients // TODO: Initialize _double_ ray coordinate values (double dx, double dy, double dz) = (r.d.x, r.d.y, r.d.z); (double ox, double oy, double oz) = (r.o.x, r.o.y, r.o.z); double a = dx * dx + dy * dy + dz * dz; double b = 2 * (dx * ox + dy * oy + dz * oz); double c = ox * ox + oy * oy + oz * oz - this.Radius * this.Radius; // TODO: Solve quadratic equation for _t_ values (bool zzz, double t0, double t1) = Utils.Quadratic(a, b, c); if (!zzz) { return(null, null); } // TODO: Check quadric shape _t0_ and _t1_ for nearest intersection //double tShapeHit; //if (t1 < Renderer.Epsilon) // return (null, null); //if (t0 < Renderer.Epsilon) // tShapeHit = t1; //else //{ // Ray temp = new Ray(r.o, r.d); // double d1 = Vector3.Dot(temp.Point(t0), temp.o); // double d2 = Vector3.Dot(temp.Point(t1), temp.o); // if (d1 == d2) // return (null, null); // else if (d1 > d2) // { // if (Outside) // tShapeHit = t0; // else // tShapeHit = t1; // } // else // { // if (Outside) // tShapeHit = t1; // else // tShapeHit = t0; // } //} //if (t1 - t0 <= Renderer.Epsilon) // return (null, null); //Ray temp = new Ray(r.o, r.d); //double d0 = Vector3.Dot(temp.o, temp.Point(t0)); //double d1 = Vector3.Dot(temp.o, temp.Point(t1)); //double tShapeHit; //if (d0 >= d1) // tShapeHit = t0; //else // tShapeHit = t1; if (Outside) { Console.WriteLine("HERE"); //if (t1 < Renderer.Epsilon) // return (null, null); //double tShapeHit = t0; //if (tShapeHit < Renderer.Epsilon) //{ // tShapeHit = t1; //} double tShapeHit; Ray temp = new Ray(r.o, r.d); Vector3 p_t0 = temp.Point(t0); Vector3 p_t1 = temp.Point(t1); double d0 = Math.Sqrt(Math.Pow(temp.o.x - p_t0.x, 2) + Math.Pow(temp.o.y - p_t0.y, 2) + Math.Pow(temp.o.z - p_t0.z, 2)); double d1 = Math.Sqrt(Math.Pow(temp.o.x - p_t1.x, 2) + Math.Pow(temp.o.y - p_t1.y, 2) + Math.Pow(temp.o.z - p_t1.z, 2)); if (d0 > d1) { tShapeHit = t1; } else { tShapeHit = t0; } //// TODO: Compute sphere hit position and $\phi$ Vector3 pHit = r.Point(tShapeHit); //pHit *= Radius / Math.Sqrt(pHit.x * pHit.x + pHit.y * pHit.y + pHit.z * pHit.z); //if (Math.Sqrt(pHit.x * pHit.x + pHit.y * pHit.y + pHit.z * pHit.z) >= this.Radius + Renderer.Epsilon) // return (null, null); //if (Math.Sqrt(pHit.x * pHit.x + pHit.y * pHit.y + pHit.z * pHit.z) <= this.Radius - Renderer.Epsilon) // return (null, null); //double phi = Math.Atan2(pHit.y, pHit.x); //if (phi < 0) // phi += 2 * Math.PI; //double theta = Math.Acos(Utils.Clamp(pHit.z / this.Radius, -1, 1)); //double invR = 1 / Math.Sqrt(pHit.x * pHit.x + pHit.y * pHit.y); //Vector3 n = new Vector3(pHit.z * pHit.x * invR, pHit.z * pHit.y * invR, -this.Radius * Math.Sin(theta)); Vector3 n = (ObjectToWorld.ApplyPoint(pHit) - ObjectToWorld.ApplyPoint(Vector3.ZeroVector)).Clone().Normalize(); //Vector3 n = new Vector3(0, 0, 1); //Vector3 n = pHit.Clone() * this.Radius; // TODO: Return shape hit and surface interaction Vector3 dpdu = new Vector3(-pHit.y, pHit.x, 0); //Console.WriteLine("dpdu1 " + dpdu.x + " " + dpdu.y + " " + dpdu.z); n.Faceforward(dpdu); //Console.WriteLine("normal " + n.x + " " + n.y + " " + n.z); double abDot = Vector3.Dot(n, dpdu); double bbDot = Vector3.Dot(n, n); Vector3 proj = abDot / bbDot * n; dpdu -= proj; //Console.WriteLine("proj " + proj.x + " " + proj.y + " " + proj.z); //Console.WriteLine("dot " + Vector3.Dot(n, dpdu)); var si = new SurfaceInteraction(pHit, n, -ray.d, dpdu, this); //var si = new SurfaceInteraction(pHit, new Vector3(0, 0, 1), -ray.d, dpdu, this); return(tShapeHit, ObjectToWorld.Apply(si)); } else { //Console.WriteLine(r.o.x + " " + r.o.y + " " + r.o.z); //Console.WriteLine(t0); //Console.WriteLine(t1); //System.Environment.Exit(1); double tShapeHit; Ray temp = new Ray(r.o, r.d); Vector3 p_t0 = temp.Point(t0); Vector3 p_t1 = temp.Point(t1); Vector3 x = p_t0 - temp.o; Vector3 y = p_t1 - temp.o; double x_x = Vector3.Dot(x, temp.d); double y_x = Vector3.Dot(y, temp.d); //Console.WriteLine(temp.d.x + " " + temp.d.y + " " + temp.d.z); //Console.WriteLine(x_x); //Console.WriteLine(y_x); //System.Environment.Exit(1); if (x_x > 0) { tShapeHit = t0; } else if (y_x > 0) { tShapeHit = t1; } else { return(null, null); } //// TODO: Compute sphere hit position and $\phi$ Vector3 pHit = r.Point(tShapeHit); //pHit *= Radius / Math.Sqrt(pHit.x * pHit.x + pHit.y * pHit.y + pHit.z * pHit.z); //if (Math.Sqrt(pHit.x * pHit.x + pHit.y * pHit.y + pHit.z * pHit.z) >= this.Radius + Renderer.Epsilon) // return (null, null); //if (Math.Sqrt(pHit.x * pHit.x + pHit.y * pHit.y + pHit.z * pHit.z) <= this.Radius - Renderer.Epsilon) // return (null, null); //double phi = Math.Atan2(pHit.y, pHit.x); //if (phi < 0) // phi += 2 * Math.PI; //double theta = Math.Acos(Utils.Clamp(pHit.z / this.Radius, -1, 1)); //double invR = 1 / Math.Sqrt(pHit.x * pHit.x + pHit.y * pHit.y); //Vector3 n = new Vector3(pHit.z * pHit.x * invR, pHit.z * pHit.y * invR, -this.Radius * Math.Sin(theta)); Vector3 n = (ObjectToWorld.ApplyPoint(Vector3.ZeroVector) - ObjectToWorld.ApplyPoint(pHit)).Clone().Normalize(); //Vector3 n = new Vector3(0, 0, 1); //Vector3 n = pHit.Clone() * this.Radius; // TODO: Return shape hit and surface interaction Vector3 dpdu = new Vector3(-pHit.y, pHit.x, 0); //Console.WriteLine("dpdu1 " + dpdu.x + " " + dpdu.y + " " + dpdu.z); dpdu.Faceforward(n); //Console.WriteLine("normal " + n.x + " " + n.y + " " + n.z); double abDot = Vector3.Dot(n, dpdu); double bbDot = Vector3.Dot(n, n); Vector3 proj = abDot / bbDot * n; dpdu -= proj; //Console.WriteLine("proj " + proj.x + " " + proj.y + " " + proj.z); //Console.WriteLine("dot " + Vector3.Dot(n, dpdu)); var si = new SurfaceInteraction(pHit, n, -ray.d, dpdu, this); //var si = new SurfaceInteraction(pHit, new Vector3(0, 0, 1), -ray.d, dpdu, this); return(tShapeHit, ObjectToWorld.Apply(si)); } // A dummy return example //double dummyHit = 0.0; //Vector3 dummyVector = new Vector3(0, 0, 0); //SurfaceInteraction dummySurfaceInteraction = new SurfaceInteraction(dummyVector, dummyVector, dummyVector, dummyVector, this); //return (dummyHit, dummySurfaceInteraction); }