public Sphere(Transform objectToWorld, bool reverseOrientation, float radius, float z0, float z1, float phiMax) : base(objectToWorld, reverseOrientation) { _radius = radius; _zMin = MathUtility.Clamp(Math.Min(z0, z1), -radius, radius); _zMax = MathUtility.Clamp(Math.Max(z0, z1), -radius, radius); _thetaMin = MathUtility.Acos(MathUtility.Clamp(_zMin / radius, -1.0f, 1.0f)); _thetaMax = MathUtility.Acos(MathUtility.Clamp(_zMax / radius, -1.0f, 1.0f)); _phiMax = MathUtility.ToRadians(MathUtility.Clamp(phiMax, 0.0f, 360.0f)); }
public static Quaternion Slerp(float t, Quaternion q1, Quaternion q2) { float cosTheta = Dot(q1, q2); if (cosTheta > .9995f) { return(Normalize((1.0f - t) * q1 + t * q2)); } float theta = MathUtility.Acos(MathUtility.Clamp(cosTheta, -1.0f, 1.0f)); float thetap = theta * t; Quaternion qperp = Normalize(q2 - q1 * cosTheta); return(q1 * MathUtility.Cos(thetap) + qperp * MathUtility.Sin(thetap)); }
public override bool TryIntersect(Ray r, out float tHit, out float rayEpsilon, out DifferentialGeometry dg) { tHit = float.NegativeInfinity; rayEpsilon = 0.0f; dg = null; float phi; Point phit; float thit; if (!DoIntersection(r, out phi, out phit, out thit)) { return(false); } // Find parametric representation of sphere hit float u = phi / _phiMax; float theta = MathUtility.Acos(MathUtility.Clamp(phit.Z / _radius, -1.0f, 1.0f)); float v = (theta - _thetaMin) / (_thetaMax - _thetaMin); // Compute sphere $\dpdu$ and $\dpdv$ float zradius = MathUtility.Sqrt(phit.X * phit.X + phit.Y * phit.Y); float invzradius = 1.0f / zradius; float cosphi = phit.X * invzradius; float sinphi = phit.Y * invzradius; var dpdu = new Vector(-_phiMax * phit.Y, _phiMax * phit.X, 0); var dpdv = (_thetaMax - _thetaMin) * new Vector(phit.Z * cosphi, phit.Z * sinphi, -_radius * MathUtility.Sin(theta)); // Compute sphere $\dndu$ and $\dndv$ Vector d2Pduu = -_phiMax * _phiMax * new Vector(phit.X, phit.Y, 0); Vector d2Pduv = (_thetaMax - _thetaMin) * phit.Z * _phiMax * new Vector(-sinphi, cosphi, 0.0f); Vector d2Pdvv = -(_thetaMax - _thetaMin) * (_thetaMax - _thetaMin) * new Vector(phit.X, phit.Y, phit.Z); // Compute coefficients for fundamental forms float E = Vector.Dot(dpdu, dpdu); float F = Vector.Dot(dpdu, dpdv); float G = Vector.Dot(dpdv, dpdv); Vector N = Vector.Normalize(Vector.Cross(dpdu, dpdv)); float e = Vector.Dot(N, d2Pduu); float f = Vector.Dot(N, d2Pduv); float g = Vector.Dot(N, d2Pdvv); // Compute $\dndu$ and $\dndv$ from fundamental form coefficients float invEGF2 = 1.0f / (E * G - F * F); var dndu = (Normal)((f * F - e * G) * invEGF2 * dpdu + (e * F - f * E) * invEGF2 * dpdv); var dndv = (Normal)((g * F - f * G) * invEGF2 * dpdu + (f * F - g * E) * invEGF2 * dpdv); // Initialize _DifferentialGeometry_ from parametric information var o2w = ObjectToWorld; dg = new DifferentialGeometry( o2w.TransformPoint(ref phit), o2w.TransformVector(ref dpdu), o2w.TransformVector(ref dpdv), o2w.TransformNormal(ref dndu), o2w.TransformNormal(ref dndv), u, v, this); // Update _tHit_ for quadric intersection tHit = thit; // Compute _rayEpsilon_ for quadric intersection rayEpsilon = 5e-4f * tHit; return(true); }
public static float SphericalTheta(Vector v) { return(MathUtility.Acos(MathUtility.Clamp(v.Z, -1.0f, 1.0f))); }