void Grid::initializeRayMarch(MarchingInfo &mi, const Ray &r, float tmin) const { Vec3f rayOrigin = r.getOrigin(); Vec3f rayDir = r.getDirection(); Vec3f boxMin = mpBox->getMin(); Vec3f boxMax = mpBox->getMax(); float rayT; if (mpBox->Inside(rayOrigin)) rayT = 0.0; else if (!mpBox->IntersectP(r, &rayT)) { return; } printf("rayT=%f\n", rayT); Vec3f gridIntersect = r.pointAtParameter(rayT); cout << "gridIntersect=" << gridIntersect << endl; cout << "Box min=" << mpBox->getMin() << endl; printf("mVoxel:%d, %d, %d \n", mVoxel[0], mVoxel[1], mVoxel[2]); //MarchingInfo for indices int pos[3]; int axis; int sign[3]; float delta[3]; float next[3]; int indices[3]; for (axis = 0; axis < 3; axis++) { pos[axis] = posToVoxel(gridIntersect, axis); if (rayDir[axis] != 0) sign[axis] = rayDir[axis] > 0 ? 1 : -1; if (sign[axis] >= 0) { next[axis] = rayT + (voxelToPos(pos[axis]+1, axis) - gridIntersect[axis])/rayDir[axis]; delta[axis] = mVoxel[axis] / rayDir[axis]; } else { next[axis] = rayT + (voxelToPos(pos[axis], axis) - gridIntersect[axis])/rayDir[axis]; delta[axis] = mVoxel[axis] / rayDir[axis]; } } printf("Indices:%d, %d, %d \n", pos[0], pos[1], pos[2]); mi.setIndices(pos[0], pos[1], pos[2]); mi.setSign(sign[0], sign[1], sign[2]); mi.setDelta(delta[0], delta[1], delta[2]); mi.setNext(next[0], next[1], next[2]); mi.set_tmin(rayT); }
// GridAccel Method Definitions GridAccel::GridAccel(const vector<Reference<Primitive> > &p, bool forRefined, bool refineImmediately) : gridForRefined(forRefined) { PBRT_GRID_STARTED_CONSTRUCTION(this, p.size()); // Create reader-writeer mutex for grid rwMutex = RWMutex::Create(); // Initialize _primitives_ with primitives for grid if (refineImmediately) for (u_int i = 0; i < p.size(); ++i) p[i]->FullyRefine(primitives); else primitives = p; // Compute bounds and choose grid resolution for (u_int i = 0; i < primitives.size(); ++i) bounds = Union(bounds, primitives[i]->WorldBound()); Vector delta = bounds.pMax - bounds.pMin; // Find _voxelsPerUnitDist_ for grid int maxAxis = bounds.MaximumExtent(); float invMaxWidth = 1.f / delta[maxAxis]; Assert(invMaxWidth > 0.f); float cubeRoot = 3.f * powf(float(primitives.size()), 1.f/3.f); float voxelsPerUnitDist = cubeRoot * invMaxWidth; for (int axis = 0; axis < 3; ++axis) { NVoxels[axis] = Round2Int(delta[axis] * voxelsPerUnitDist); NVoxels[axis] = Clamp(NVoxels[axis], 1, 64); } PBRT_GRID_BOUNDS_AND_RESOLUTION(&bounds, NVoxels); // Compute voxel widths and allocate voxels for (int axis = 0; axis < 3; ++axis) { Width[axis] = delta[axis] / NVoxels[axis]; InvWidth[axis] = (Width[axis] == 0.f) ? 0.f : 1.f / Width[axis]; } int nVoxels = NVoxels[0] * NVoxels[1] * NVoxels[2]; voxels = AllocAligned<Voxel *>(nVoxels); memset(voxels, 0, nVoxels * sizeof(Voxel *)); // Add primitives to grid voxels for (u_int i = 0; i < primitives.size(); ++i) { // Find voxel extent of primitive BBox pb = primitives[i]->WorldBound(); int vmin[3], vmax[3]; for (int axis = 0; axis < 3; ++axis) { vmin[axis] = posToVoxel(pb.pMin, axis); vmax[axis] = posToVoxel(pb.pMax, axis); } // Add primitive to overlapping voxels PBRT_GRID_VOXELIZED_PRIMITIVE(vmin, vmax); for (int z = vmin[2]; z <= vmax[2]; ++z) for (int y = vmin[1]; y <= vmax[1]; ++y) for (int x = vmin[0]; x <= vmax[0]; ++x) { int o = offset(x, y, z); if (!voxels[o]) { // Allocate new voxel and store primitive in it voxels[o] = voxelArena.Alloc<Voxel>(); *voxels[o] = Voxel(primitives[i]); } else { // Add primitive to already-allocated voxel voxels[o]->AddPrimitive(primitives[i]); } } } PBRT_GRID_FINISHED_CONSTRUCTION(this); }
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; }
bool GridAccel::IntersectP(const Ray &ray) const { PBRT_GRID_INTERSECTIONP_TEST(const_cast<GridAccel *>(this), const_cast<Ray *>(&ray)); RWMutexLock lock(*rwMutex, READ); // Check ray against overall grid bounds float rayT; if (bounds.Inside(ray(ray.mint))) rayT = ray.mint; else if (!bounds.IntersectP(ray, &rayT)) { PBRT_GRID_RAY_MISSED_BOUNDS(); return false; } Point gridIntersect = ray(rayT); // Set up 3D DDA for ray float NextCrossingT[3], DeltaT[3]; int Step[3], Out[3], Pos[3]; for (int axis = 0; axis < 3; ++axis) { // Compute current voxel for axis Pos[axis] = posToVoxel(gridIntersect, axis); if (ray.d[axis] >= 0) { // Handle ray with positive direction for voxel stepping NextCrossingT[axis] = rayT + (voxelToPos(Pos[axis]+1, axis) - gridIntersect[axis]) / ray.d[axis]; DeltaT[axis] = Width[axis] / ray.d[axis]; Step[axis] = 1; Out[axis] = NVoxels[axis]; } else { // Handle ray with negative direction for voxel stepping NextCrossingT[axis] = rayT + (voxelToPos(Pos[axis], axis) - gridIntersect[axis]) / ray.d[axis]; DeltaT[axis] = -Width[axis] / ray.d[axis]; Step[axis] = -1; Out[axis] = -1; } } // Walk grid for shadow ray for (;;) { int o = offset(Pos[0], Pos[1], Pos[2]); Voxel *voxel = voxels[o]; PBRT_GRID_RAY_TRAVERSED_VOXEL(Pos, voxel ? voxel->size() : 0); if (voxel && voxel->IntersectP(ray, lock)) return true; // Advance to next voxel // Find _stepAxis_ for stepping to next voxel int bits = ((NextCrossingT[0] < NextCrossingT[1]) << 2) + ((NextCrossingT[0] < NextCrossingT[2]) << 1) + ((NextCrossingT[1] < NextCrossingT[2])); const int cmpToAxis[8] = { 2, 1, 2, 1, 2, 2, 0, 0 }; int stepAxis = cmpToAxis[bits]; if (ray.maxt < NextCrossingT[stepAxis]) break; Pos[stepAxis] += Step[stepAxis]; if (Pos[stepAxis] == Out[stepAxis]) break; NextCrossingT[stepAxis] += DeltaT[stepAxis]; } return false; }
bool Heightfield2::IntersectP(const Ray &r) const{ Ray ray; (*WorldToObject)(r, &ray); float rayT; if(bounds.Inside(ray(ray.mint))) rayT = ray.mint; else if(!bounds.IntersectP(ray, &rayT)) return false; Point gridIntersect = ray(rayT); // Set up 2D DDA for ray float NextCrossingT[2], DeltaT[2]; int Step[2], Out[2], Pos[2]; for (int axis = 0; axis < 2; ++axis) { // Compute current voxel for axis Pos[axis] = posToVoxel(gridIntersect, axis); if (ray.d[axis] >= 0) { // Handle ray with positive direction for voxel stepping NextCrossingT[axis] = rayT + (voxelToPos(Pos[axis]+1, axis) - gridIntersect[axis]) / ray.d[axis]; DeltaT[axis] = width[axis] / ray.d[axis]; Step[axis] = 1; Out[axis] = nVoxels[axis]; } else { // Handle ray with negative direction for voxel stepping NextCrossingT[axis] = rayT + (voxelToPos(Pos[axis], axis) - gridIntersect[axis]) / ray.d[axis]; DeltaT[axis] = -width[axis] / ray.d[axis]; Step[axis] = -1; Out[axis] = -1; } } // Walk ray through voxel grid bool hitSomething = false; int index[3]; for (;;) { // Check for intersection in current voxel and advance to next index[0] = Pos[0] + Pos[1]*nx; index[1] = Pos[0]+1 + Pos[1]*nx; index[2] = Pos[0]+1 + (Pos[1]+1)*nx; hitSomething |= TriangleIntersectP(r, index); if(hitSomething) return hitSomething; index[1] = Pos[0]+1 + (Pos[1]+1)*nx; index[2] = Pos[0] + (Pos[1]+1)*nx; hitSomething |= TriangleIntersectP(r, index); if(hitSomething) return hitSomething; // Advance to next voxel // Find _stepAxis_ for stepping to next voxel int stepAxis = (NextCrossingT[0] < NextCrossingT[1])? 0 : 1; Pos[stepAxis] += Step[stepAxis]; if (Pos[stepAxis] == Out[stepAxis]) break; NextCrossingT[stepAxis] += DeltaT[stepAxis]; } return hitSomething; }