void DifferentialGeometry::ComputeDifferentials( const RayDifferential &ray) const { if (ray.hasDifferentials) { // Estimate screen space change in $\pt{}$ and $(u,v)$ // Compute auxiliary intersection points with plane float d = -Dot(nn, Vector(p.x, p.y, p.z)); Vector rxv(ray.rxOrigin.x, ray.rxOrigin.y, ray.rxOrigin.z); float tx = -(Dot(nn, rxv) + d) / Dot(nn, ray.rxDirection); if (isnan(tx)) goto fail; Point px = ray.rxOrigin + tx * ray.rxDirection; Vector ryv(ray.ryOrigin.x, ray.ryOrigin.y, ray.ryOrigin.z); float ty = -(Dot(nn, ryv) + d) / Dot(nn, ray.ryDirection); if (isnan(ty)) goto fail; Point py = ray.ryOrigin + ty * ray.ryDirection; dpdx = px - p; dpdy = py - p; // Compute $(u,v)$ offsets at auxiliary points // Initialize _A_, _Bx_, and _By_ matrices for offset computation float A[2][2], Bx[2], By[2]; int axes[2]; if (fabsf(nn.x) > fabsf(nn.y) && fabsf(nn.x) > fabsf(nn.z)) { axes[0] = 1; axes[1] = 2; } else if (fabsf(nn.y) > fabsf(nn.z)) { axes[0] = 0; axes[1] = 2; } else { axes[0] = 0; axes[1] = 1; } // Initialize matrices for chosen projection plane A[0][0] = dpdu[axes[0]]; A[0][1] = dpdv[axes[0]]; A[1][0] = dpdu[axes[1]]; A[1][1] = dpdv[axes[1]]; Bx[0] = px[axes[0]] - p[axes[0]]; Bx[1] = px[axes[1]] - p[axes[1]]; By[0] = py[axes[0]] - p[axes[0]]; By[1] = py[axes[1]] - p[axes[1]]; if (!SolveLinearSystem2x2(A, Bx, &dudx, &dvdx)) { dudx = 0.; dvdx = 0.; } if (!SolveLinearSystem2x2(A, By, &dudy, &dvdy)) { dudy = 0.; dvdy = 0.; } } else { fail: dudx = dvdx = 0.; dudy = dvdy = 0.; dpdx = dpdy = Vector(0,0,0); } }
void SurfaceInteraction::ComputeDifferentials( const RayDifferential &ray) const { if (ray.hasDifferentials) { // Estimate screen space change in $\pt{}$ and $(u,v)$ // Compute auxiliary intersection points with plane Float d = Dot(n, Vector3f(p.x, p.y, p.z)); Float tx = -(Dot(n, Vector3f(ray.rxOrigin)) - d) / Dot(n, ray.rxDirection); if (std::isnan(tx)) goto fail; Point3f px = ray.rxOrigin + tx * ray.rxDirection; Float ty = -(Dot(n, Vector3f(ray.ryOrigin)) - d) / Dot(n, ray.ryDirection); if (std::isnan(ty)) goto fail; Point3f py = ray.ryOrigin + ty * ray.ryDirection; dpdx = px - p; dpdy = py - p; // Compute $(u,v)$ offsets at auxiliary points // Choose two dimensions to use for ray offset computation int dim[2]; if (std::abs(n.x) > std::abs(n.y) && std::abs(n.x) > std::abs(n.z)) { dim[0] = 1; dim[1] = 2; } else if (std::abs(n.y) > std::abs(n.z)) { dim[0] = 0; dim[1] = 2; } else { dim[0] = 0; dim[1] = 1; } // Initialize _A_, _Bx_, and _By_ matrices for offset computation Float A[2][2] = {{dpdu[dim[0]], dpdv[dim[0]]}, {dpdu[dim[1]], dpdv[dim[1]]}}; Float Bx[2] = {px[dim[0]] - p[dim[0]], px[dim[1]] - p[dim[1]]}; Float By[2] = {py[dim[0]] - p[dim[0]], py[dim[1]] - p[dim[1]]}; if (!SolveLinearSystem2x2(A, Bx, &dudx, &dvdx)) dudx = dvdx = 0; if (!SolveLinearSystem2x2(A, By, &dudy, &dvdy)) dudy = dvdy = 0; } else { fail: dudx = dvdx = 0; dudy = dvdy = 0; dpdx = dpdy = Vector3f(0, 0, 0); } }
void Triangle::GetShadingGeometry(const Transform &obj2world, const DifferentialGeometry &dg, DifferentialGeometry *dgShading) const { if (!mesh->n && !mesh->s) { *dgShading = dg; return; } // Initialize _Triangle_ shading geometry with _n_ and _s_ // Compute barycentric coordinates for point float b[3]; // Initialize _A_ and _C_ matrices for barycentrics float uv[3][2]; GetUVs(uv); float A[2][2] = { { uv[1][0] - uv[0][0], uv[2][0] - uv[0][0] }, { uv[1][1] - uv[0][1], uv[2][1] - uv[0][1] } }; float C[2] = { dg.u - uv[0][0], dg.v - uv[0][1] }; if (!SolveLinearSystem2x2(A, C, &b[1], &b[2])) { // Handle degenerate parametric mapping b[0] = b[1] = b[2] = 1.f/3.f; } else b[0] = 1.f - b[1] - b[2]; // Use _n_ and _s_ to compute shading tangents for triangle, _ss_ and _ts_ Normal ns; Vector ss, ts; if (mesh->n) ns = Normalize(obj2world(b[0] * mesh->n[v[0]] + b[1] * mesh->n[v[1]] + b[2] * mesh->n[v[2]])); else ns = dg.nn; if (mesh->s) ss = Normalize(obj2world(b[0] * mesh->s[v[0]] + b[1] * mesh->s[v[1]] + b[2] * mesh->s[v[2]])); else ss = Normalize(dg.dpdu); ts = Cross(ss, ns); if (ts.LengthSquared() > 0.f) { ts = Normalize(ts); ss = Cross(ts, ns); } else CoordinateSystem((Vector)ns, &ss, &ts); Normal dndu, dndv; // Compute $\dndu$ and $\dndv$ for triangle shading geometry if (mesh->n) { float uvs[3][2]; GetUVs(uvs); // Compute deltas for triangle partial derivatives of normal float du1 = uvs[0][0] - uvs[2][0]; float du2 = uvs[1][0] - uvs[2][0]; float dv1 = uvs[0][1] - uvs[2][1]; float dv2 = uvs[1][1] - uvs[2][1]; Normal dn1 = mesh->n[v[0]] - mesh->n[v[2]]; Normal dn2 = mesh->n[v[1]] - mesh->n[v[2]]; float determinant = du1 * dv2 - dv1 * du2; if (determinant == 0.f) dndu = dndv = Normal(0,0,0); else { float invdet = 1.f / determinant; dndu = ( dv2 * dn1 - dv1 * dn2) * invdet; dndv = (-du2 * dn1 + du1 * dn2) * invdet; } } else dndu = dndv = Normal(0,0,0); *dgShading = DifferentialGeometry(dg.p, ss, ts, (*ObjectToWorld)(dndu), (*ObjectToWorld)(dndv), dg.u, dg.v, dg.shape); dgShading->dudx = dg.dudx; dgShading->dvdx = dg.dvdx; dgShading->dudy = dg.dudy; dgShading->dvdy = dg.dvdy; dgShading->dpdx = dg.dpdx; dgShading->dpdy = dg.dpdy; }
void Heightfield2::GetShadingGeometry(const Transform &obj2world, const DifferentialGeometry &dg, DifferentialGeometry *dgShading) const { // Initialize _Triangle_ shading geometry with _n_ and _s_ // *dgShading = dg; // return; Point p = Point(dg.u, dg.v, 0); int x = posToVoxel(p, 0); int y = posToVoxel(p, 1); int index1 = x + y*nx; int index2, index3; const Point &p1o = point[index1]; if((dg.u-p1o.x)*width[1] > (dg.v-p1o.y)*width[0]){ index2 = x+1 + y*nx; index3 = x+1 + (y+1)*nx; }else{ index2 = x+1 + (y+1)*nx; index3 = x + (y+1)*nx; } const Point &p2o = point[index2]; const Point &p3o = point[index3]; const Normal &normal0 = normal[index1]; const Normal &normal1 = normal[index2]; const Normal &normal2 = normal[index3]; // Compute barycentric coordinates for point float b[3]; // Initialize _A_ and _C_ matrices for barycentrics float A[2][2] = { { p2o.x - p1o.x, p3o.x - p1o.x }, { p2o.y - p1o.y, p3o.y - p1o.y } }; float C[2] = { dg.u - p1o.x, dg.v - p1o.y }; if (!SolveLinearSystem2x2(A, C, &b[1], &b[2])) { // Handle degenerate parametric mapping b[0] = b[1] = b[2] = 1.f/3.f; } else b[0] = 1.f - b[1] - b[2]; // Use _n_ and _s_ to compute shading tangents for triangle, _ss_ and _ts_ Normal ns; Vector ss, ts; ns = Normalize(obj2world(b[0] * normal0 + b[1] * normal1 + b[2] * normal2)); ss = Normalize(dg.dpdu); ts = Cross(ss, ns); if (ts.LengthSquared() > 0.f) { ts = Normalize(ts); ss = Cross(ts, ns); } else CoordinateSystem((Vector)ns, &ss, &ts); Normal dndu, dndv; // Compute $\dndu$ and $\dndv$ for triangle shading geometry // Compute deltas for triangle partial derivatives of normal float du1 = p1o.x - p3o.x; float du2 = p2o.x - p3o.x; float dv1 = p1o.y - p3o.y; float dv2 = p2o.y - p3o.y; Normal dn1 = normal0 - normal2; Normal dn2 = normal1 - normal2; float determinant = du1 * dv2 - dv1 * du2; if (determinant == 0.f) dndu = dndv = Normal(0,0,0); else { float invdet = 1.f / determinant; dndu = ( dv2 * dn1 - dv1 * dn2) * invdet; dndv = (-du2 * dn1 + du1 * dn2) * invdet; } *dgShading = DifferentialGeometry(dg.p, ss, ts, obj2world(dndu), obj2world(dndv), dg.u, dg.v, dg.shape); dgShading->dudx = dg.dudx; dgShading->dvdx = dg.dvdx; dgShading->dudy = dg.dudy; dgShading->dvdy = dg.dvdy; dgShading->dpdx = dg.dpdx; dgShading->dpdy = dg.dpdy; }