Vector2 Sphere::Intersect(StraightLine line, Vector2 center, double r,char sign) { //cout << "LINE " << line.a << sign <<endl; double *x = Quadratic((1 + line.a*line.a), 2 * line.a*(line.b - center.y) - 2 * center.x, (line.b - center.y)*(line.b - center.y) - r*r + center.x*center.x); if (x == NULL) { cout << "!!!" << endl; exit(1); } double* y = new double[2]; y[0] = line.a*x[0] + line.b; y[1] = line.a*x[1] + line.b; /* cout << x[0] << " " << y[0] << endl; cout << x[1] << " " << y[1] << endl;*/ Vector2 points[] = { Vector2(x[0],y[0]), Vector2(x[1],y[1]), }; if (sign == '-') { if ((points[0].x) <= (points[1].x)) return points[0]; else return points[1]; } if (sign == '+') { // cout << x[1] << " " << y[1] << endl; if ((points[0].x) >= (points[1].x)) return points[0]; else return points[1]; } }
bool Cone::Intersect(const Ray &r, float *tHit, float *rayEpsilon, DifferentialGeometry *dg) const { float phi; pbrt::Point phit; // Transform _Ray_ to object space Ray ray; (*WorldToObject)(r, &ray); // Compute quadratic cone coefficients float k = radius / height; k = k*k; float A = ray.d.x * ray.d.x + ray.d.y * ray.d.y - k * ray.d.z * ray.d.z; float B = 2 * (ray.d.x * ray.o.x + ray.d.y * ray.o.y - k * ray.d.z * (ray.o.z-height) ); float C = ray.o.x * ray.o.x + ray.o.y * ray.o.y - k * (ray.o.z -height) * (ray.o.z-height); // Solve quadratic equation for _t_ values float t0, t1; if (!Quadratic(A, B, C, &t0, &t1)) return false; // Compute intersection distance along ray if (t0 > ray.maxt || t1 < ray.mint) return false; float thit = t0; if (t0 < ray.mint) { thit = t1; if (thit > ray.maxt) return false; } // Compute cone inverse mapping phit = ray(thit); phi = atan2f(phit.y, phit.x); if (phi < 0.) phi += 2.f*M_PI; // Test cone intersection against clipping parameters if (phit.z < 0 || phit.z > height || phi > phiMax) { if (thit == t1) return false; thit = t1; if (t1 > ray.maxt) return false; // Compute cone inverse mapping phit = ray(thit); phi = atan2f(phit.y, phit.x); if (phi < 0.) phi += 2.f*M_PI; if (phit.z < 0 || phit.z > height || phi > phiMax) return false; } // Find parametric representation of cone hit float u = phi / phiMax; float v = phit.z / height; // Compute cone $\dpdu$ and $\dpdv$ Vector dpdu(-phiMax * phit.y, phiMax * phit.x, 0); Vector dpdv(-phit.x / (1.f - v), -phit.y / (1.f - v), height); // Compute cone $\dndu$ and $\dndv$ Vector d2Pduu = -phiMax * phiMax * Vector(phit.x, phit.y, 0.); Vector d2Pduv = phiMax / (1.f - v) * Vector(phit.y, -phit.x, 0.); Vector d2Pdvv(0, 0, 0); // Compute coefficients for fundamental forms float E = Dot(dpdu, dpdu); float F = Dot(dpdu, dpdv); float G = Dot(dpdv, dpdv); Vector N = Normalize(Cross(dpdu, dpdv)); float e = Dot(N, d2Pduu); float f = Dot(N, d2Pduv); float g = Dot(N, d2Pdvv); // Compute $\dndu$ and $\dndv$ from fundamental form coefficients float invEGF2 = 1.f / (E*G - F*F); Normal dndu = Normal((f*F - e*G) * invEGF2 * dpdu + (e*F - f*E) * invEGF2 * dpdv); Normal dndv = Normal((g*F - f*G) * invEGF2 * dpdu + (f*F - g*E) * invEGF2 * dpdv); // Initialize _DifferentialGeometry_ from parametric information const Transform &o2w = *ObjectToWorld; *dg = DifferentialGeometry(o2w(phit), o2w(dpdu), o2w(dpdv), o2w(dndu), o2w(dndv), u, v, this); // Update _tHit_ for quadric intersection *tHit = thit; // Compute _rayEpsilon_ for quadric intersection *rayEpsilon = 5e-4f * *tHit; return true; }
int main(int, char **argv) { const double myT = water_prop.kT; // room temperature in Hartree const double R = 2.7; Functional x(Identity()); Grid n(gd); n = 0.001*VectorXd::Ones(gd.NxNyNz) + 0.001*(-10*r2(gd)).cwise().exp(); compare_functionals(Sum(), x + kT, myT, n, 2e-13); compare_functionals(Quadratic(), sqr(x + kT) - x + 2*kT, myT, n, 2e-12); compare_functionals(Sqrt(), sqrt(x), myT, n, 1e-12); compare_functionals(SqrtAndMore(), sqrt(x) - x + 2*kT, myT, n, 1e-12); compare_functionals(Log(), log(x), myT, n, 3e-14); compare_functionals(LogAndSqr(), log(x) + sqr(x), myT, n, 3e-14); compare_functionals(LogAndSqrAndInverse(), log(x) + (sqr(x)-Pow(3)) + Functional(1)/x, myT, n, 3e-10); compare_functionals(LogOneMinusX(), log(1-x), myT, n, 1e-12); compare_functionals(LogOneMinusNbar(R), log(1-StepConvolve(R)), myT, n, 1e-13); compare_functionals(SquareXshell(R), sqr(xShellConvolve(R)), myT, n); Functional n2 = ShellConvolve(R); Functional n3 = StepConvolve(R); compare_functionals(n2_and_n3(R), sqr(n2) + sqr(n3), myT, n, 1e-14); const double four_pi_r2 = 4*M_PI*R*R; Functional one_minus_n3 = 1 - n3; Functional phi1 = (-1/four_pi_r2)*n2*log(one_minus_n3); compare_functionals(Phi1(R), phi1, myT, n, 1e-13); const double four_pi_r = 4*M_PI*R; Functional n2x = xShellConvolve(R); Functional n2y = yShellConvolve(R); Functional n2z = zShellConvolve(R); Functional phi2 = (sqr(n2) - sqr(n2x) - sqr(n2y) - sqr(n2z))/(four_pi_r*one_minus_n3); compare_functionals(Phi2(R), phi2, myT, n, 1e-14); Functional phi3rf = n2*(sqr(n2) - 3*(sqr(n2x) + sqr(n2y) + sqr(n2z)))/(24*M_PI*sqr(one_minus_n3)); compare_functionals(Phi3rf(R), phi3rf, myT, n, 1e-13); compare_functionals(AlmostRF(R), myT*(phi1 + phi2 + phi3rf), myT, n, 2e-14); Functional veff = EffectivePotentialToDensity(); compare_functionals(SquareVeff(R), sqr(veff), myT, Grid(gd, -myT*n.cwise().log()), 1e-12); compare_functionals(AlmostRFnokT(R), phi1 + phi2 + phi3rf, myT, n, 3e-14); compare_functionals(AlmostRF(R), (myT*phi1).set_name("phi1") + (myT*phi2).set_name("phi2") + (myT*phi3rf).set_name("phi3"), myT, n, 4e-14); compare_functionals(Phi1Veff(R), phi1(veff), myT, Grid(gd, -myT*n.cwise().log()), 1e-13); compare_functionals(Phi2Veff(R), phi2(veff), myT, Grid(gd, -myT*n.cwise().log()), 1e-14); compare_functionals(Phi3rfVeff(R), phi3rf(veff), myT, Grid(gd, -myT*n.cwise().log()), 1e-13); compare_functionals(IdealGasFast(), IdealGasOfVeff, myT, Grid(gd, -myT*n.cwise().log()), 1e-12); double mu = -1; compare_functionals(Phi1plus(R, mu), phi1(veff) + IdealGasOfVeff + ChemicalPotential(mu)(veff), myT, Grid(gd, -myT*n.cwise().log()), 1e-12); if (errors == 0) printf("\n%s passes!\n", argv[0]); else printf("\n%s fails %d tests!\n", argv[0], errors); return errors; }
Painter& Painter::Path(CParser& p) { Pointf current(0, 0); while(!p.IsEof()) { int c = p.GetChar(); p.Spaces(); bool rel = IsLower(c); Pointf t, t1, t2; switch(ToUpper(c)) { case 'M': current = ReadPoint(p, current, rel); Move(current); case 'L': while(p.IsDouble2()) { current = ReadPoint(p, current, rel); Line(current); } break; case 'Z': Close(); break; case 'H': while(p.IsDouble2()) { current.x = p.ReadDouble() + rel * current.x; Line(current); } break; case 'V': while(p.IsDouble2()) { current.y = p.ReadDouble() + rel * current.y; Line(current); } break; case 'C': while(p.IsDouble2()) { t1 = ReadPoint(p, current, rel); t2 = ReadPoint(p, current, rel); current = ReadPoint(p, current, rel); Cubic(t1, t2, current); } break; case 'S': while(p.IsDouble2()) { t2 = ReadPoint(p, current, rel); current = ReadPoint(p, current, rel); Cubic(t2, current); } break; case 'Q': while(p.IsDouble2()) { t1 = ReadPoint(p, current, rel); current = ReadPoint(p, current, rel); Quadratic(t1, current); } break; case 'T': while(p.IsDouble2()) { current = ReadPoint(p, current, rel); Quadratic(current); } break; case 'A': while(p.IsDouble2()) { t1 = ReadPoint(p, Pointf(0, 0), false); double xangle = ReadDouble(p); bool large = ReadBool(p); bool sweep = ReadBool(p); current = ReadPoint(p, current, rel); SvgArc(t1, xangle * M_PI / 180.0, large, sweep, current); } break; default: return *this; } } return *this; }
bool Hyperboloid::Intersect(const Ray &r, float *tHit, float *rayEpsilon, DifferentialGeometry *dg) const { float phi, v; Point phit; // Transform _Ray_ to object space Ray ray; (*WorldToObject)(r, &ray); // Compute quadratic hyperboloid coefficients float A = a*ray.d.x*ray.d.x + a*ray.d.y*ray.d.y - c*ray.d.z*ray.d.z; float B = 2.f * (a*ray.d.x*ray.o.x + a*ray.d.y*ray.o.y - c*ray.d.z*ray.o.z); float C = a*ray.o.x*ray.o.x + a*ray.o.y*ray.o.y - c*ray.o.z*ray.o.z - 1; // Solve quadratic equation for _t_ values float t0, t1; if (!Quadratic(A, B, C, &t0, &t1)) return false; // Compute intersection distance along ray if (t0 > ray.maxt || t1 < ray.mint) return false; float thit = t0; if (t0 < ray.mint) { thit = t1; if (thit > ray.maxt) return false; } // Compute hyperboloid inverse mapping phit = ray(thit); v = (phit.z - p1.z)/(p2.z - p1.z); Point pr = (1.f-v) * p1 + v * p2; phi = atan2f(pr.x*phit.y - phit.x*pr.y, phit.x*pr.x + phit.y*pr.y); if (phi < 0) phi += 2*M_PI; // Test hyperboloid 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 hyperboloid inverse mapping phit = ray(thit); v = (phit.z - p1.z)/(p2.z - p1.z); Point pr = (1.f-v) * p1 + v * p2; phi = atan2f(pr.x*phit.y - phit.x*pr.y, phit.x*pr.x + phit.y*pr.y); if (phi < 0) phi += 2*M_PI; if (phit.z < zmin || phit.z > zmax || phi > phiMax) return false; } // Compute parametric representation of hyperboloid hit float u = phi / phiMax; // Compute hyperboloid $\dpdu$ and $\dpdv$ float cosphi = cosf(phi), sinphi = sinf(phi); Vector dpdu(-phiMax * phit.y, phiMax * phit.x, 0.); Vector dpdv((p2.x-p1.x) * cosphi - (p2.y-p1.y) * sinphi, (p2.x-p1.x) * sinphi + (p2.y-p1.y) * cosphi, p2.z-p1.z); // Compute hyperboloid $\dndu$ and $\dndv$ Vector d2Pduu = -phiMax * phiMax * Vector(phit.x, phit.y, 0); Vector d2Pduv = phiMax * Vector(-dpdv.y, dpdv.x, 0.); Vector d2Pdvv(0, 0, 0); // Compute coefficients for fundamental forms float E = Dot(dpdu, dpdu); float F = Dot(dpdu, dpdv); float G = Dot(dpdv, dpdv); Vector N = Normalize(Cross(dpdu, dpdv)); float e = Dot(N, d2Pduu); float f = Dot(N, d2Pduv); float g = Dot(N, d2Pdvv); // Compute $\dndu$ and $\dndv$ from fundamental form coefficients float invEGF2 = 1.f / (E*G - F*F); Normal dndu = Normal((f*F - e*G) * invEGF2 * dpdu + (e*F - f*E) * invEGF2 * dpdv); Normal dndv = Normal((g*F - f*G) * invEGF2 * dpdu + (f*F - g*E) * invEGF2 * dpdv); // Initialize _DifferentialGeometry_ from parametric information const Transform &o2w = *ObjectToWorld; *dg = DifferentialGeometry(o2w(phit), o2w(dpdu), o2w(dpdv), o2w(dndu), o2w(dndv), u, v, this); // Update _tHit_ for quadric intersection *tHit = thit; // Compute _rayEpsilon_ for quadric intersection *rayEpsilon = 5e-4f * *tHit; return true; }
bool Cylinder::Intersect(const Ray &r, Float *tHit, SurfaceInteraction *isect, bool testAlphaTexture) const { Float phi; Point3f pHit; // Transform _Ray_ to object space Vector3f oErr, dErr; Ray ray = (*WorldToObject)(r, &oErr, &dErr); // Compute quadratic cylinder coefficients // Initialize _EFloat_ ray coordinate values EFloat ox(ray.o.x, oErr.x), oy(ray.o.y, oErr.y), oz(ray.o.z, oErr.z); EFloat dx(ray.d.x, dErr.x), dy(ray.d.y, dErr.y), dz(ray.d.z, dErr.z); EFloat a = dx * dx + dy * dy; EFloat b = 2 * (dx * ox + dy * oy); EFloat c = ox * ox + oy * oy - EFloat(radius) * EFloat(radius); // Solve quadratic equation for _t_ values EFloat t0, t1; if (!Quadratic(a, b, c, &t0, &t1)) return false; // Check quadric shape _t0_ and _t1_ for nearest intersection if (t0.UpperBound() > ray.tMax || t1.LowerBound() <= 0) return false; EFloat tShapeHit = t0; if (tShapeHit.LowerBound() <= 0) { tShapeHit = t1; if (tShapeHit.UpperBound() > ray.tMax) return false; } // Compute cylinder hit point and $\phi$ pHit = ray((Float)tShapeHit); // Refine cylinder intersection point Float hitRad = std::sqrt(pHit.x * pHit.x + pHit.y * pHit.y); pHit.x *= radius / hitRad; pHit.y *= radius / hitRad; phi = std::atan2(pHit.y, pHit.x); if (phi < 0) phi += 2 * Pi; // Test cylinder intersection against clipping parameters if (pHit.z < zMin || pHit.z > zMax || phi > phiMax) { if (tShapeHit == t1) return false; tShapeHit = t1; if (t1.UpperBound() > ray.tMax) return false; // Compute cylinder hit point and $\phi$ pHit = ray((Float)tShapeHit); // Refine cylinder intersection point Float hitRad = std::sqrt(pHit.x * pHit.x + pHit.y * pHit.y); pHit.x *= radius / hitRad; pHit.y *= radius / hitRad; phi = std::atan2(pHit.y, pHit.x); if (phi < 0) phi += 2 * Pi; if (pHit.z < zMin || pHit.z > zMax || phi > phiMax) return false; } // Find parametric representation of cylinder hit Float u = phi / phiMax; Float v = (pHit.z - zMin) / (zMax - zMin); // Compute cylinder $\dpdu$ and $\dpdv$ Vector3f dpdu(-phiMax * pHit.y, phiMax * pHit.x, 0); Vector3f dpdv(0, 0, zMax - zMin); // Compute cylinder $\dndu$ and $\dndv$ Vector3f d2Pduu = -phiMax * phiMax * Vector3f(pHit.x, pHit.y, 0); Vector3f d2Pduv(0, 0, 0), d2Pdvv(0, 0, 0); // Compute coefficients for fundamental forms Float E = Dot(dpdu, dpdu); Float F = Dot(dpdu, dpdv); Float G = Dot(dpdv, dpdv); Vector3f N = Normalize(Cross(dpdu, dpdv)); Float e = Dot(N, d2Pduu); Float f = Dot(N, d2Pduv); Float g = Dot(N, d2Pdvv); // Compute $\dndu$ and $\dndv$ from fundamental form coefficients Float invEGF2 = 1 / (E * G - F * F); Normal3f dndu = Normal3f((f * F - e * G) * invEGF2 * dpdu + (e * F - f * E) * invEGF2 * dpdv); Normal3f dndv = Normal3f((g * F - f * G) * invEGF2 * dpdu + (f * F - g * E) * invEGF2 * dpdv); // Compute error bounds for cylinder intersection Vector3f pError = gamma(3) * Abs(Vector3f(pHit.x, pHit.y, 0)); // Initialize _SurfaceInteraction_ from parametric information *isect = (*ObjectToWorld)(SurfaceInteraction(pHit, pError, Point2f(u, v), -ray.d, dpdu, dpdv, dndu, dndv, ray.time, this)); // Update _tHit_ for quadric intersection *tHit = (Float)tShapeHit; return true; }
Painter& Painter::RelQuadratic(double x, double y) { return Quadratic(x, y, true); }
bool NaiadFoamParticle::Intersect(const Ray &rayInc, float *tHit, float *rayEpsilon, DifferentialGeometry *dg) const { /*const float X0 = ray.o.x; const float Y0 = ray.o.y; const float Z0 = ray.o.z; const float Xd = ray.d.x; const float Yd = ray.d.y; const float Zd = ray.d.z; const float Xc = pos.x; const float Yc = pos.y; const float Zc = pos.z; const float B = 2.0f * (Xd * (X0 - Xc) + Yd * (Y0 - Yc) + Zd * (Z0 - Zc)); const float C = (X0-Xc)*(X0-Xc) + (Y0-Yc)*(Y0-Yc) + (Z0-Zc)*(Z0-Zc) - r*r; const float discriminant = B*B - 4*C; if (discriminant < 0.0f) return false; const float t0 = (- B - sqrt(discriminant)) / 2.0f; const float t1 = (- B + sqrt(discriminant)) / 2.0f; if (t0 < 0 || t0 != t0) { return true; }*/ Matrix4x4 w2o_m; w2o_m.m[0][3] = -pos.x; w2o_m.m[1][3] = -pos.y; w2o_m.m[2][3] = -pos.z; Transform w2o = Transform(w2o_m); const float thetaMin = -M_PI; const float thetaMax = 0; const float phiMax = 2.f*M_PI; float phi; Point phit; // Transform _Ray_ to object space Ray ray; w2o(rayInc, &ray); // Compute quadratic sphere coefficients float A = ray.d.x*ray.d.x + ray.d.y*ray.d.y + ray.d.z*ray.d.z; float B = 2 * (ray.d.x*ray.o.x + ray.d.y*ray.o.y + ray.d.z*ray.o.z); float C = ray.o.x*ray.o.x + ray.o.y*ray.o.y + ray.o.z*ray.o.z - r*r; // Solve quadratic equation for _t_ values float t0, t1; if (!Quadratic(A, B, C, &t0, &t1)) return false; // Compute intersection distance along ray if (t0 > ray.maxt || t1 < ray.mint) return false; float thit = t0; if (t0 < ray.mint) { thit = t1; if (thit > ray.maxt) return false; } // Compute sphere hit position and $\phi$ phit = ray(thit); rayInc.hitFoam = true; PerspectiveCamera * cam = PerspectiveCamera::cur_cam; Transform c2w; cam->CameraToWorld.Interpolate(0.f, &c2w); Transform w2c = Inverse(c2w); Transform c2s = cam->CameraToScreen; Transform s2r = cam->ScreenToRaster; Point cPos = w2c(phit); Point rPos = s2r(c2s(cPos)); int x = (int)(rPos.x + 0.5); int y = (int)(rPos.y + 0.5); int w = cam->film->xResolution; int h = cam->film->yResolution; if (x > 0 && y > 0 && x < w && y < h) { rayInc.hitFoam = true; /*printf("%i %i %i %i\n", x, y, w ,h); std::cout << parent << std::endl; std::cout << parent->parent << std::endl; std::cout << parent->parent->foamPlane[0] << std::endl; std::cout << parent->parent->foamPlane.size() << std::endl; std::cout << x + y*w << std::endl;*/ //std::cout << NaiadFoam::cur->FoamPlane().size() << std::endl; rayInc.alphaFoam = NaiadFoam::cur->FoamPlane()[x + y*w]; } /*if (phit.x == 0.f && phit.y == 0.f) phit.x = 1e-5f * r; phi = atan2f(phit.y, phit.x); if (phi < 0.) phi += 2.f*M_PI; // Find parametric representation of sphere hit float u = phi / phiMax; float theta = acosf(Clamp(phit.z / r, -1.f, 1.f)); float v = (theta - thetaMin) / (thetaMax - thetaMin); // Compute sphere $\dpdu$ and $\dpdv$ float zradius = sqrtf(phit.x*phit.x + phit.y*phit.y); float invzradius = 1.f / zradius; float cosphi = phit.x * invzradius; float sinphi = phit.y * invzradius; Vector dpdu(-phiMax * phit.y, phiMax * phit.x, 0); Vector dpdv = (thetaMax-thetaMin) * Vector(phit.z * cosphi, phit.z * sinphi, -r * sinf(theta)); // Compute sphere $\dndu$ and $\dndv$ Vector d2Pduu = -phiMax * phiMax * Vector(phit.x, phit.y, 0); Vector d2Pduv = (thetaMax - thetaMin) * phit.z * phiMax * Vector(-sinphi, cosphi, 0.); Vector d2Pdvv = -(thetaMax - thetaMin) * (thetaMax - thetaMin) * Vector(phit.x, phit.y, phit.z); // Compute coefficients for fundamental forms float E = Dot(dpdu, dpdu); float F = Dot(dpdu, dpdv); float G = Dot(dpdv, dpdv); Vector N = Normalize(Cross(dpdu, dpdv)); float e = Dot(N, d2Pduu); float f = Dot(N, d2Pduv); float g = Dot(N, d2Pdvv); // Compute $\dndu$ and $\dndv$ from fundamental form coefficients float invEGF2 = 1.f / (E*G - F*F); Normal dndu = Normal((f*F - e*G) * invEGF2 * dpdu + (e*F - f*E) * invEGF2 * dpdv); Normal dndv = Normal((g*F - f*G) * invEGF2 * dpdu + (f*F - g*E) * invEGF2 * dpdv); //std::cout << "Got here?" << std::endl; Matrix4x4 o2w_m; o2w_m.m[0][3] = pos.x; o2w_m.m[1][3] = pos.y; o2w_m.m[2][3] = pos.z; Transform o2w = Transform(o2w_m); // Initialize _DifferentialGeometry_ from parametric information *dg = DifferentialGeometry(o2w(phit), o2w(dpdu), o2w(dpdv), o2w(dndu), o2w(dndv), u, v, parent); dg->mult = 1.f;*/ // Update _tHit_ for quadric intersection //*tHit = thit; // Compute _rayEpsilon_ for quadric intersection //*rayEpsilon = 5e-4f * *tHit; return true; }
void OGL_Light::BindIntoShader(OGL_Shader* _shader, unsigned int _index) { std::string typeName = ""; std::string index = std::to_string(_index); switch (m_Type) { case DIRECTIONAL: typeName = "Directional"; glUniform3fv(_shader->GetUniform("u_" + typeName + "Lights[" + index + "].Direction"), 1, m_Direction.ToStdVec().data()); break; case POINT: typeName = "Point"; glUniform3fv(_shader->GetUniform("u_" + typeName + "Lights[" + index + "].Position"), 1, m_Position.ToStdVec().data()); // These values describe a light with a range of 20 units glUniform1f(_shader->GetUniform("u_" + typeName + "Lights[" + index + "].Constant"), Constant()); glUniform1f(_shader->GetUniform("u_" + typeName + "Lights[" + index + "].Linear"), Linear()); glUniform1f(_shader->GetUniform("u_" + typeName + "Lights[" + index + "].Quadratic"), Quadratic()); break; case SPOT: typeName = "Spot"; glUniform3fv(_shader->GetUniform("u_" + typeName + "Lights[" + index + "].Position"), 1, m_Position.ToStdVec().data()); glUniform3fv(_shader->GetUniform("u_" + typeName + "Lights[" + index + "].Direction"), 1, m_Direction.ToStdVec().data()); glUniform1f(_shader->GetUniform("u_" + typeName + "Lights[" + index + "].OuterCutoff"), Cutoff()); glUniform1f(_shader->GetUniform("u_" + typeName + "Lights[" + index + "].InnerCutoff"), InnerCutoff()); break; default: return; } glUniform3fv(_shader->GetUniform("u_" + typeName + "Lights[" + index + "].Ia"), 1, m_Ia.ToStdVec().data()); glUniform3fv(_shader->GetUniform("u_" + typeName + "Lights[" + index + "].Id"), 1, m_Id.ToStdVec().data()); glUniform3fv(_shader->GetUniform("u_" + typeName + "Lights[" + index + "].Is"), 1, m_Is.ToStdVec().data()); }
Painter& Painter::Quadratic(double x, double y) { Quadratic(x, y, false); return *this; }
Painter& Painter::RelQuadratic(double x, double y) { Quadratic(x, y, true); return *this; }
bool Paraboloid::Intersect(const Ray &r, Float *tHit, SurfaceInteraction *isect) const { Float phi; Point3f pHit; // Transform _Ray_ to object space Vector3f oErr, dErr; Ray ray = (*WorldToObject)(r, &oErr, &dErr); // Compute quadratic paraboloid coefficients // Initialize _EFloat_ ray coordinate values EFloat ox(ray.o.x, oErr.x), oy(ray.o.y, oErr.y), oz(ray.o.z, oErr.z); EFloat dx(ray.d.x, dErr.x), dy(ray.d.y, dErr.y), dz(ray.d.z, dErr.z); EFloat k = EFloat(zMax) / (EFloat(radius) * EFloat(radius)); EFloat a = k * (dx * dx + dy * dy); EFloat b = 2.f * k * (dx * ox + dy * oy) - dz; EFloat c = k * (ox * ox + oy * oy) - oz; // Solve quadratic equation for _t_ values EFloat t0, t1; if (!Quadratic(a, b, c, &t0, &t1)) return false; // Check quadric shape _t0_ and _t1_ for nearest intersection if (t0.UpperBound() > ray.tMax || t1.LowerBound() <= 0) return false; EFloat tShapeHit = t0; if (tShapeHit.LowerBound() <= 0) { tShapeHit = t1; if (tShapeHit.UpperBound() > ray.tMax) return false; } // Compute paraboloid inverse mapping pHit = ray((Float)tShapeHit); phi = std::atan2(pHit.y, pHit.x); if (phi < 0.) phi += 2 * Pi; // Test paraboloid intersection against clipping parameters if (pHit.z < zMin || pHit.z > zMax || phi > phiMax) { if (tShapeHit == t1) return false; tShapeHit = t1; if (t1.UpperBound() > ray.tMax) return false; // Compute paraboloid inverse mapping pHit = ray((Float)tShapeHit); phi = std::atan2(pHit.y, pHit.x); if (phi < 0.) phi += 2 * Pi; if (pHit.z < zMin || pHit.z > zMax || phi > phiMax) return false; } // Find parametric representation of paraboloid hit Float u = phi / phiMax; Float v = (pHit.z - zMin) / (zMax - zMin); // Compute paraboloid $\dpdu$ and $\dpdv$ Vector3f dpdu(-phiMax * pHit.y, phiMax * pHit.x, 0.); Vector3f dpdv = (zMax - zMin) * Vector3f(pHit.x / (2 * pHit.z), pHit.y / (2 * pHit.z), 1.); // Compute paraboloid $\dndu$ and $\dndv$ Vector3f d2Pduu = -phiMax * phiMax * Vector3f(pHit.x, pHit.y, 0); Vector3f d2Pduv = (zMax - zMin) * phiMax * Vector3f(-pHit.y / (2 * pHit.z), pHit.x / (2 * pHit.z), 0); Vector3f d2Pdvv = -(zMax - zMin) * (zMax - zMin) * Vector3f(pHit.x / (4 * pHit.z * pHit.z), pHit.y / (4 * pHit.z * pHit.z), 0.); // Compute coefficients for fundamental forms Float E = Dot(dpdu, dpdu); Float F = Dot(dpdu, dpdv); Float G = Dot(dpdv, dpdv); Vector3f N = Normalize(Cross(dpdu, dpdv)); Float e = Dot(N, d2Pduu); Float f = Dot(N, d2Pduv); Float g = Dot(N, d2Pdvv); // Compute $\dndu$ and $\dndv$ from fundamental form coefficients Float invEGF2 = 1 / (E * G - F * F); Normal3f dndu = Normal3f((f * F - e * G) * invEGF2 * dpdu + (e * F - f * E) * invEGF2 * dpdv); Normal3f dndv = Normal3f((g * F - f * G) * invEGF2 * dpdu + (f * F - g * E) * invEGF2 * dpdv); // Compute error bounds for paraboloid intersection // Compute error bounds for intersection computed with ray equation EFloat px = ox + tShapeHit * dx; EFloat py = oy + tShapeHit * dy; EFloat pz = oz + tShapeHit * dz; Vector3f pError = Vector3f(px.GetAbsoluteError(), py.GetAbsoluteError(), pz.GetAbsoluteError()); // Initialize _SurfaceInteraction_ from parametric information *isect = (*ObjectToWorld)(SurfaceInteraction(pHit, pError, Point2f(u, v), -ray.d, dpdu, dpdv, dndu, dndv, ray.time, this)); *tHit = (Float)tShapeHit; return true; }
bool Sphere::Intersect(const Ray &r, Float *tHit, SurfaceInteraction *isect, bool testAlphaTexture) const { Float phi; Point3f pHit; // Transform _Ray_ to object space Vector3f oErr, dErr; Ray ray = (*WorldToObject)(r, &oErr, &dErr); // Compute quadratic sphere coefficients // Initialize _EFloat_ ray coordinate values EFloat ox(ray.o.x, oErr.x), oy(ray.o.y, oErr.y), oz(ray.o.z, oErr.z); EFloat dx(ray.d.x, dErr.x), dy(ray.d.y, dErr.y), dz(ray.d.z, dErr.z); EFloat a = dx * dx + dy * dy + dz * dz; EFloat b = 2 * (dx * ox + dy * oy + dz * oz); EFloat c = ox * ox + oy * oy + oz * oz - EFloat(radius) * EFloat(radius); // Solve quadratic equation for _t_ values EFloat t0, t1; if (!Quadratic(a, b, c, &t0, &t1)) return false; // Check quadric shape _t0_ and _t1_ for nearest intersection if (t0.UpperBound() > ray.tMax || t1.LowerBound() <= 0) return false; EFloat tShapeHit = t0; if (tShapeHit.LowerBound() <= 0) { tShapeHit = t1; if (tShapeHit.UpperBound() > ray.tMax) return false; } // Compute sphere hit position and $\phi$ pHit = ray((Float)tShapeHit); // Refine sphere intersection point pHit *= radius / Distance(pHit, Point3f(0, 0, 0)); if (pHit.x == 0 && pHit.y == 0) pHit.x = 1e-5f * radius; phi = std::atan2(pHit.y, pHit.x); if (phi < 0) phi += 2 * Pi; // Test sphere intersection against clipping parameters if ((zMin > -radius && pHit.z < zMin) || (zMax < radius && pHit.z > zMax) || phi > phiMax) { if (tShapeHit == t1) return false; if (t1.UpperBound() > ray.tMax) return false; tShapeHit = t1; // Compute sphere hit position and $\phi$ pHit = ray((Float)tShapeHit); // Refine sphere intersection point pHit *= radius / Distance(pHit, Point3f(0, 0, 0)); if (pHit.x == 0 && pHit.y == 0) pHit.x = 1e-5f * radius; phi = std::atan2(pHit.y, pHit.x); if (phi < 0) phi += 2 * Pi; if ((zMin > -radius && pHit.z < zMin) || (zMax < radius && pHit.z > zMax) || phi > phiMax) return false; } // Find parametric representation of sphere hit Float u = phi / phiMax; Float theta = std::acos(Clamp(pHit.z / radius, -1, 1)); Float v = (theta - thetaMin) / (thetaMax - thetaMin); // Compute sphere $\dpdu$ and $\dpdv$ Float zRadius = std::sqrt(pHit.x * pHit.x + pHit.y * pHit.y); Float invZRadius = 1 / zRadius; Float cosPhi = pHit.x * invZRadius; Float sinPhi = pHit.y * invZRadius; Vector3f dpdu(-phiMax * pHit.y, phiMax * pHit.x, 0); Vector3f dpdv = (thetaMax - thetaMin) * Vector3f(pHit.z * cosPhi, pHit.z * sinPhi, -radius * std::sin(theta)); // Compute sphere $\dndu$ and $\dndv$ Vector3f d2Pduu = -phiMax * phiMax * Vector3f(pHit.x, pHit.y, 0); Vector3f d2Pduv = (thetaMax - thetaMin) * pHit.z * phiMax * Vector3f(-sinPhi, cosPhi, 0.); Vector3f d2Pdvv = -(thetaMax - thetaMin) * (thetaMax - thetaMin) * Vector3f(pHit.x, pHit.y, pHit.z); // Compute coefficients for fundamental forms Float E = Dot(dpdu, dpdu); Float F = Dot(dpdu, dpdv); Float G = Dot(dpdv, dpdv); Vector3f N = Normalize(Cross(dpdu, dpdv)); Float e = Dot(N, d2Pduu); Float f = Dot(N, d2Pduv); Float g = Dot(N, d2Pdvv); // Compute $\dndu$ and $\dndv$ from fundamental form coefficients Float invEGF2 = 1 / (E * G - F * F); Normal3f dndu = Normal3f((f * F - e * G) * invEGF2 * dpdu + (e * F - f * E) * invEGF2 * dpdv); Normal3f dndv = Normal3f((g * F - f * G) * invEGF2 * dpdu + (f * F - g * E) * invEGF2 * dpdv); // Compute error bounds for sphere intersection Vector3f pError = gamma(5) * Abs((Vector3f)pHit); // Initialize _SurfaceInteraction_ from parametric information *isect = (*ObjectToWorld)(SurfaceInteraction(pHit, pError, Point2f(u, v), -ray.d, dpdu, dpdv, dndu, dndv, ray.time, this)); // Update _tHit_ for quadric intersection *tHit = (Float)tShapeHit; return true; }
void BoundsPainter::QuadraticOp(const Pointf& p1, const Pointf& p, bool) { sw.Quadratic(p1, p); Quadratic(p1, p); }
// 1. -- intersection or not. // 2. -- fill differentialGeometry bool Sphere::Intersect(const Ray &r, float *tHit, float *rayEpsilon, DifferentialGeometry *dg) const { float phi; Point phit; // Transform _Ray_ to object space Ray ray; (*WorldToObject)(r, &ray); // 1. -- intersection or not. // Compute quadratic sphere coefficients float A = ray.d.x*ray.d.x + ray.d.y*ray.d.y + ray.d.z*ray.d.z; float B = 2 * (ray.d.x*ray.o.x + ray.d.y*ray.o.y + ray.d.z*ray.o.z); float C = ray.o.x*ray.o.x + ray.o.y*ray.o.y + ray.o.z*ray.o.z - radius*radius; // Solve quadratic equation for _t_ values float t0, t1; if (!Quadratic(A, B, C, &t0, &t1)) // in pbrt.h: Find quadratic discriminant return false; // Compute intersection distance along ray if (t0 > ray.maxt || t1 < ray.mint) return false; float thit = t0; if (t0 < ray.mint) { thit = t1; if (thit > ray.maxt) return false; } // Compute sphere hit position and $\phi$ phit = ray(thit); if (phit.x == 0.f && phit.y == 0.f) phit.x = 1e-5f * radius; phi = atan2f(phit.y, phit.x); if (phi < 0.) phi += 2.f*M_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(thit); if (phit.x == 0.f && phit.y == 0.f) phit.x = 1e-5f * radius; phi = atan2f(phit.y, phit.x); if (phi < 0.) phi += 2.f*M_PI; if ((zmin > -radius && phit.z < zmin) || (zmax < radius && phit.z > zmax) || phi > phiMax) return false; } // 2. -- fill differentialGeometry // Find parametric representation of sphere hit float u = phi / phiMax; float theta = acosf(Clamp(phit.z / radius, -1.f, 1.f)); float v = (theta - thetaMin) / (thetaMax - thetaMin); // Compute sphere $\dpdu$ and $\dpdv$ float zradius = sqrtf(phit.x*phit.x + phit.y*phit.y); float invzradius = 1.f / zradius; float cosphi = phit.x * invzradius; float sinphi = phit.y * invzradius; Vector dpdu(-phiMax * phit.y, phiMax * phit.x, 0); Vector dpdv = (thetaMax-thetaMin) * Vector(phit.z * cosphi, phit.z * sinphi, -radius * sinf(theta)); // Compute sphere $\dndu$ and $\dndv$ Vector d2Pduu = -phiMax * phiMax * Vector(phit.x, phit.y, 0); Vector d2Pduv = (thetaMax - thetaMin) * phit.z * phiMax * Vector(-sinphi, cosphi, 0.); Vector d2Pdvv = -(thetaMax - thetaMin) * (thetaMax - thetaMin) * Vector(phit.x, phit.y, phit.z); // Compute coefficients for fundamental forms float E = Dot(dpdu, dpdu); float F = Dot(dpdu, dpdv); float G = Dot(dpdv, dpdv); Vector N = Normalize(Cross(dpdu, dpdv)); float e = Dot(N, d2Pduu); float f = Dot(N, d2Pduv); float g = Dot(N, d2Pdvv); // Compute $\dndu$ and $\dndv$ from fundamental form coefficients float invEGF2 = 1.f / (E*G - F*F); Normal dndu = Normal((f*F - e*G) * invEGF2 * dpdu + (e*F - f*E) * invEGF2 * dpdv); Normal dndv = Normal((g*F - f*G) * invEGF2 * dpdu + (f*F - g*E) * invEGF2 * dpdv); // Initialize _DifferentialGeometry_ from parametric information const Transform &o2w = *ObjectToWorld; *dg = DifferentialGeometry(o2w(phit), o2w(dpdu), o2w(dpdv), o2w(dndu), o2w(dndv), u, v, this); // Update _tHit_ for quadric intersection *tHit = thit; // Compute _rayEpsilon_ for quadric intersection *rayEpsilon = 5e-4f * *tHit; return true; }
float Cubic(float a,float b,float c,float d,float t) { return Linear(Quadratic(a,b,c,t),Quadratic(b,c,d,t),t); }
bool Hyperboloid::Intersect(const Ray &r, Float *tHit, SurfaceInteraction *isect) const { Float phi, v; Point3f pHit; // Transform _Ray_ to object space Vector3f oErr, dErr; Ray ray = (*WorldToObject)(r, &oErr, &dErr); // Compute quadratic hyperboloid coefficients // Initialize _EFloat_ ray coordinate values EFloat ox(ray.o.x, oErr.x), oy(ray.o.y, oErr.y), oz(ray.o.z, oErr.z); EFloat dx(ray.d.x, dErr.x), dy(ray.d.y, dErr.y), dz(ray.d.z, dErr.z); EFloat a = ah * dx * dx + ah * dy * dy - ch * dz * dz; EFloat b = 2.f * (ah * dx * ox + ah * dy * oy - ch * dz * oz); EFloat c = ah * ox * ox + ah * oy * oy - ch * oz * oz - 1.f; // Solve quadratic equation for _t_ values EFloat t0, t1; if (!Quadratic(a, b, c, &t0, &t1)) return false; // Check quadric shape _t0_ and _t1_ for nearest intersection if (t0.UpperBound() > ray.tMax || t1.LowerBound() <= 0) return false; EFloat tShapeHit = t0; if (t0.LowerBound() <= 0) { tShapeHit = t1; if (tShapeHit.UpperBound() > ray.tMax) return false; } // Compute hyperboloid inverse mapping pHit = ray((Float)tShapeHit); v = (pHit.z - p1.z) / (p2.z - p1.z); Point3f pr = (1 - v) * p1 + v * p2; phi = std::atan2(pr.x * pHit.y - pHit.x * pr.y, pHit.x * pr.x + pHit.y * pr.y); if (phi < 0) phi += 2 * Pi; // Test hyperboloid intersection against clipping parameters if (pHit.z < zMin || pHit.z > zMax || phi > phiMax) { if (tShapeHit == t1) return false; tShapeHit = t1; if (t1.UpperBound() > ray.tMax) return false; // Compute hyperboloid inverse mapping pHit = ray((Float)tShapeHit); v = (pHit.z - p1.z) / (p2.z - p1.z); Point3f pr = (1 - v) * p1 + v * p2; phi = std::atan2(pr.x * pHit.y - pHit.x * pr.y, pHit.x * pr.x + pHit.y * pr.y); if (phi < 0) phi += 2 * Pi; if (pHit.z < zMin || pHit.z > zMax || phi > phiMax) return false; } // Compute parametric representation of hyperboloid hit Float u = phi / phiMax; // Compute hyperboloid $\dpdu$ and $\dpdv$ Float cosPhi = std::cos(phi), sinPhi = std::sin(phi); Vector3f dpdu(-phiMax * pHit.y, phiMax * pHit.x, 0.); Vector3f dpdv((p2.x - p1.x) * cosPhi - (p2.y - p1.y) * sinPhi, (p2.x - p1.x) * sinPhi + (p2.y - p1.y) * cosPhi, p2.z - p1.z); // Compute hyperboloid $\dndu$ and $\dndv$ Vector3f d2Pduu = -phiMax * phiMax * Vector3f(pHit.x, pHit.y, 0); Vector3f d2Pduv = phiMax * Vector3f(-dpdv.y, dpdv.x, 0.); Vector3f d2Pdvv(0, 0, 0); // Compute coefficients for fundamental forms Float E = Dot(dpdu, dpdu); Float F = Dot(dpdu, dpdv); Float G = Dot(dpdv, dpdv); Vector3f N = Normalize(Cross(dpdu, dpdv)); Float e = Dot(N, d2Pduu); Float f = Dot(N, d2Pduv); Float g = Dot(N, d2Pdvv); // Compute $\dndu$ and $\dndv$ from fundamental form coefficients Float invEGF2 = 1 / (E * G - F * F); Normal3f dndu = Normal3f((f * F - e * G) * invEGF2 * dpdu + (e * F - f * E) * invEGF2 * dpdv); Normal3f dndv = Normal3f((g * F - f * G) * invEGF2 * dpdu + (f * F - g * E) * invEGF2 * dpdv); // Compute error bounds for hyperboloid intersection // Compute error bounds for intersection computed with ray equation EFloat px = ox + tShapeHit * dx; EFloat py = oy + tShapeHit * dy; EFloat pz = oz + tShapeHit * dz; Vector3f pError = Vector3f(px.GetAbsoluteError(), py.GetAbsoluteError(), pz.GetAbsoluteError()); // Initialize _SurfaceInteraction_ from parametric information *isect = (*ObjectToWorld)(SurfaceInteraction(pHit, pError, Point2f(u, v), -ray.d, dpdu, dpdv, dndu, dndv, ray.time, this)); *tHit = (Float)tShapeHit; return true; }
Real OneDimSolve::Solve(Real Y, Real X, Real Dev, int Lim) { enum Loop { start, captured1, captured2, binary, finish }; Tracer et("OneDimSolve::Solve"); lim=Lim; Captured = false; if (Dev==0.0) Throw(SolutionException("Dev is zero")); L=0; C=1; U=2; vpol=1; hpol=1; y[C]=0.0; y[U]=0.0; if (Dev<0.0) { hpol=-1; Dev = -Dev; } YY=Y; // target value x[L] = X; // initial trial value if (!function.IsValid(X)) Throw(SolutionException("Starting value is invalid")); Loop TheLoop = start; for (;;) { switch (TheLoop) { case start: LookAt(L); if (Finish) { TheLoop = finish; break; } if (y[L]>0.0) VFlip(); // so Y[L] < 0 x[U] = X + Dev * hpol; if (!function.maxXinf && x[U] > function.maxX) x[U] = (function.maxX + X) / 2.0; if (!function.minXinf && x[U] < function.minX) x[U] = (function.minX + X) / 2.0; LookAt(U); if (Finish) { TheLoop = finish; break; } if (y[U] > 0.0) { TheLoop = captured1; Captured = true; break; } if (y[U] == y[L]) Throw(SolutionException("Function is flat")); if (y[U] < y[L]) HFlip(); // Change direction State(L,U,C); for (i=0; i<20; i++) { // cout << "Searching for crossing point\n"; // Have L C then crossing point, Y[L]<Y[C]<0 x[U] = x[C] + Dev * hpol; if (!function.maxXinf && x[U] > function.maxX) x[U] = (function.maxX + x[C]) / 2.0; if (!function.minXinf && x[U] < function.minX) x[U] = (function.minX + x[C]) / 2.0; LookAt(U); if (Finish) { TheLoop = finish; break; } if (y[U] > 0) { TheLoop = captured2; Captured = true; break; } if (y[U] < y[C]) Throw(SolutionException("Function is not monotone")); Dev *= 2.0; State(C,U,L); } if (TheLoop != start ) break; Throw(SolutionException("Can't locate a crossing point")); case captured1: // cout << "Captured - 1\n"; // We have 2 points L and U with crossing between them Linear(L,C,U); // linear interpolation // - result to C LookAt(C); if (Finish) { TheLoop = finish; break; } if (y[C] > 0.0) Flip(); // Want y[C] < 0 if (y[C] < 0.5*y[L]) { State(C,L,U); TheLoop = binary; break; } case captured2: // cout << "Captured - 2\n"; // We have L,C before crossing, U after crossing Quadratic(L,C,U); // quad interpolation // - result to L State(C,L,U); if ((x[C] - x[L])*hpol <= 0.0 || (x[C] - x[U])*hpol >= 0.0) { TheLoop = captured1; break; } LookAt(C); if (Finish) { TheLoop = finish; break; } // cout << "Through first stage\n"; if (y[C] > 0.0) Flip(); if (y[C] > 0.5*y[L]) { TheLoop = captured2; break; } else { State(C,L,U); TheLoop = captured1; break; } case binary: // We have L, U around crossing - do binary search // cout << "Binary\n"; for (i=3; i; i--) { x[C] = 0.5*(x[L]+x[U]); LookAt(C); if (Finish) { TheLoop = finish; break; } if (y[C]>0.0) State(L,U,C); else State(C,L,U); } if (TheLoop != binary) break; TheLoop = captured1; break; case finish: return x[Last]; } } }
bool Sphere::Intersect(const Ray &r, Float *distance, Float *rayEpsilon, DifferentialGeometry *dg) const { Ray ray; (*worldToLocal)(r, &ray); // Compute quadratic sphere coefficients Float A = ray.d.x * ray.d.x + ray.d.y * ray.d.y + ray.d.z * ray.d.z; Float B = 2 * (ray.d.x * ray.o.x + ray.d.y * ray.o.y + ray.d.z * ray.o.z); Float C = ray.o.x * ray.o.x + ray.o.y * ray.o.y + ray.o.z * ray.o.z - mRad * mRad; Float t0, t1; if (!Quadratic(A, B, C, &t0, &t1)) return false; // Compute intersection distance along ray if (t0 > ray.maxT || t1 < ray.minT) return false; Float thit = t0; if (t0 < ray.minT) { thit = t1; if (thit > ray.maxT) return false; } //这里开始计算参数化变量 //计算phi Point phit; Float phi; phit = ray(thit); if (phit.x == 0.f && phit.y == 0.f) phit.x = 1e-5f * mRad; //排除除零的情况 phi = atan2f(phit.y, phit.x); if (phi < 0.) phi += 2.f * Pi; //保证phi在2PI之中 //判断是否在Z坐标之间的裁剪空间中 if ((mZMin > -mRad && phit.z < mZMin) || (mZMax < mRad && phit.z > mZMax) || phi > mPhiMax) { if (thit == t1) return false; if (t1 > ray.maxT) return false; thit = t1; phit = ray(thit); if (phit.x == 0.f && phit.y == 0.f) phit.x = 1e-5f * mRad; phi = atan2f(phit.y, phit.x); if (phi < 0.) phi += 2.f * Pi; if ((mZMin > -mRad && phit.z < mZMin) || (mZMax < mRad && phit.z > mZMax) || phi > mPhiMax) return false; } // Find parametric representation of sphere hit //寻找参数化的u和v Float u = phi / mPhiMax; Float theta = acosf(Clamp(phit.z / mRad, -1.f, 1.f)); Float v = (theta - mThetaMin) / (mThetaMax - mThetaMin); // 计算偏导 偏导还不是很熟悉,所以这里照搬了PBRT的公式,详细公式可以查阅PBRT Float zradius = sqrtf(phit.x * phit.x + phit.y * phit.y); Float invzradius = 1.f / zradius; Float cosphi = phit.x * invzradius; Float sinphi = phit.y * invzradius; Vector3f dpdu(-mPhiMax * phit.y, mPhiMax * phit.x, 0); Vector3f dpdv = (mThetaMax - mThetaMin) * Vector3f(phit.z * cosphi, phit.z * sinphi, -mRad * sinf(theta)); //计算法线的偏导 Vector3f d2Pduu = -mPhiMax * mPhiMax * Vector3f(phit.x, phit.y, 0); Vector3f d2Pduv = (mThetaMax - mThetaMin) * phit.z * mPhiMax * Vector3f(-sinphi, cosphi, 0.); Vector3f d2Pdvv = -(mThetaMax - mThetaMin) * (mThetaMax - mThetaMin) * Vector3f(phit.x, phit.y, phit.z); Float E = Dot(dpdu, dpdu); Float F = Dot(dpdu, dpdv); Float G = Dot(dpdv, dpdv); Vector3f N = Normalize(Cross(dpdu, dpdv)); Float e = Dot(N, d2Pduu); Float f = Dot(N, d2Pduv); Float g = Dot(N, d2Pdvv); Float invEGF2 = 1.f / (E * G - F * F); Normal dndu = Normal( (f * F - e * G) * invEGF2 * dpdu + (e * F - f * E) * invEGF2 * dpdv); Normal dndv = Normal( (g * F - f * G) * invEGF2 * dpdu + (f * F - g * E) * invEGF2 * dpdv); const Transform &o2w = *localToWorld; *dg = DifferentialGeometry(o2w(phit), o2w(dpdu), o2w(dpdv), o2w(dndu), o2w(dndv), u, v, this); *distance = thit; *rayEpsilon = 5e-4f * *distance; //交点处的Float误差 return true; }
Painter& Painter::Quadratic(double x, double y) { return Quadratic(x, y, false); }