void SurfacePointsRenderer::Render(const Scene &scene) { // Declare shared variables for Poisson point generation BBox octBounds = scene.WorldBound(); octBounds.Expand(.001f * powf(octBounds.Volume(), 1.f/3.f)); Octree<SurfacePoint> pointOctree(octBounds); // Create scene bounding sphere to catch rays that leave the scene Point sceneCenter; float sceneRadius; scene.WorldBound().BoundingSphere(&sceneCenter, &sceneRadius); Transform ObjectToWorld(Translate(sceneCenter - Point(0,0,0))); Transform WorldToObject(Inverse(ObjectToWorld)); Reference<Shape> sph = new Sphere(&ObjectToWorld, &WorldToObject, true, sceneRadius, -sceneRadius, sceneRadius, 360.f); //Reference<Material> nullMaterial = Reference<Material>(NULL); Material nullMaterial; GeometricPrimitive sphere(sph, nullMaterial, NULL); int maxFails = 2000, repeatedFails = 0, maxRepeatedFails = 0; if (PbrtOptions.quickRender) maxFails = max(10, maxFails / 10); int totalPathsTraced = 0, totalRaysTraced = 0, numPointsAdded = 0; ProgressReporter prog(maxFails, "Depositing samples"); // Launch tasks to trace rays to find Poisson points PBRT_SUBSURFACE_STARTED_RAYS_FOR_POINTS(); vector<Task *> tasks; RWMutex *mutex = RWMutex::Create(); int nTasks = NumSystemCores(); for (int i = 0; i < nTasks; ++i) tasks.push_back(new SurfacePointTask(scene, pCamera, time, i, minDist, maxFails, *mutex, repeatedFails, maxRepeatedFails, totalPathsTraced, totalRaysTraced, numPointsAdded, sphere, pointOctree, points, prog)); EnqueueTasks(tasks); WaitForAllTasks(); for (uint32_t i = 0; i < tasks.size(); ++i) delete tasks[i]; RWMutex::Destroy(mutex); prog.Done(); PBRT_SUBSURFACE_FINISHED_RAYS_FOR_POINTS(totalRaysTraced, numPointsAdded); if (filename != "") { // Write surface points to file FILE *f = fopen(filename.c_str(), "w"); if (!f) { Error("Unable to open output file \"%s\" (%s)", filename.c_str(), strerror(errno)); return; } fprintf(f, "# points generated by SurfacePointsRenderer\n"); fprintf(f, "# position (x,y,z), normal (x,y,z), area, rayEpsilon\n"); for (u_int i = 0; i < points.size(); ++i) { const SurfacePoint &sp = points[i]; fprintf(f, "%g %g %g %g %g %g %g %g\n", sp.p.x, sp.p.y, sp.p.z, sp.n.x, sp.n.y, sp.n.z, sp.area, sp.rayEpsilon); } fclose(f); } }
Action::ResultE QuadParticleSystemDrawer::draw(DrawEnv *pEnv, ParticleSystemUnrecPtr System, const MFUInt32& Sort) { bool isSorted(Sort.size() > 0); UInt32 NumParticles; if(isSorted) { NumParticles = Sort.size(); } else { NumParticles = System->getNumParticles(); } Pnt3f P1,P2,P3,P4; UInt32 Index; //Calculate the CameraToObject basis Matrix WorldToObject(pEnv->getObjectToWorld()); WorldToObject.invert(); Matrix CameraToObject(pEnv->getCameraToWorld()); CameraToObject.mult(WorldToObject); glBegin(GL_QUADS); for(UInt32 i(0); i<NumParticles;++i) { if(isSorted) { Index = Sort[i]; } else { Index = i; } //Loop through all particles //Get The Normal of the Particle Vec3f Normal = getQuadNormal(pEnv, System, Index, CameraToObject); //Calculate the Binormal as the cross between Normal and Up Vec3f Binormal = getQuadUpDir(pEnv, System, Index, CameraToObject).cross(Normal); //Get the Up Direction of the Particle Vec3f Up = Normal.cross(Binormal); //Determine Local Space of the Particle //This is where error occurs Pnt3f Position = System->getPosition(Index); //Determine the Width and Height of the quad Real32 Width = System->getSize(Index).x()*getQuadSizeScaling().x(),Height =System->getSize(Index).y()*getQuadSizeScaling().y(); //Calculate Quads positions P1 = Position + (Width/2.0f)*Binormal + (Height/2.0f)*Up; P2 = Position + (Width/2.0f)*Binormal - (Height/2.0f)*Up; P3 = Position - (Width/2.0f)*Binormal - (Height/2.0f)*Up; P4 = Position - (Width/2.0f)*Binormal + (Height/2.0f)*Up; //Draw the Quad glNormal3fv(Normal.getValues()); glColor4fv(System->getColor(Index).getValuesRGBA()); glTexCoord2f(1.0, 1.0); glVertex3fv(P1.getValues()); glTexCoord2f(0.0, 1.0); glVertex3fv(P4.getValues()); glTexCoord2f(0.0, 0.0); glVertex3fv(P3.getValues()); glTexCoord2f(1.0, 0.0); glVertex3fv(P2.getValues()); } glColor4f(1.0f,1.0f,1.0f,1.0f); glEnd(); //Generate a local space for the particle return Action::Continue; }
void CreateRadianceProbes::Render(const Scene *scene) { // Compute scene bounds and initialize probe integrators if (bbox.pMin.x > bbox.pMax.x) bbox = scene->WorldBound(); surfaceIntegrator->Preprocess(scene, camera, this); volumeIntegrator->Preprocess(scene, camera, this); Sample *origSample = new Sample(NULL, surfaceIntegrator, volumeIntegrator, scene); // Compute sampling rate in each dimension Vector delta = bbox.pMax - bbox.pMin; int nProbes[3]; for (int i = 0; i < 3; ++i) nProbes[i] = max(1, Ceil2Int(delta[i] / probeSpacing)); // Allocate SH coefficient vector pointers for sample points int count = nProbes[0] * nProbes[1] * nProbes[2]; Spectrum **c_in = new Spectrum *[count]; for (int i = 0; i < count; ++i) c_in[i] = new Spectrum[SHTerms(lmax)]; // Compute random points on surfaces of scene // Create scene bounding sphere to catch rays that leave the scene Point sceneCenter; float sceneRadius; scene->WorldBound().BoundingSphere(&sceneCenter, &sceneRadius); Transform ObjectToWorld(Translate(sceneCenter - Point(0,0,0))); Transform WorldToObject(Inverse(ObjectToWorld)); Reference<Shape> sph = new Sphere(&ObjectToWorld, &WorldToObject, true, sceneRadius, -sceneRadius, sceneRadius, 360.f); Reference<Material> nullMaterial = Reference<Material>(NULL); GeometricPrimitive sphere(sph, nullMaterial, NULL); vector<Point> surfacePoints; uint32_t nPoints = 32768, maxDepth = 32; surfacePoints.reserve(nPoints + maxDepth); Point pCamera = camera->CameraToWorld(camera->shutterOpen, Point(0, 0, 0)); surfacePoints.push_back(pCamera); RNG rng; while (surfacePoints.size() < nPoints) { // Generate random path from camera and deposit surface points Point pray = pCamera; Vector dir = UniformSampleSphere(rng.RandomFloat(), rng.RandomFloat()); float rayEpsilon = 0.f; for (uint32_t i = 0; i < maxDepth; ++i) { Ray ray(pray, dir, rayEpsilon, INFINITY, time); Intersection isect; if (!scene->Intersect(ray, &isect) && !sphere.Intersect(ray, &isect)) break; surfacePoints.push_back(ray(ray.maxt)); DifferentialGeometry &hitGeometry = isect.dg; pray = isect.dg.p; rayEpsilon = isect.rayEpsilon; hitGeometry.nn = Faceforward(hitGeometry.nn, -ray.d); dir = UniformSampleSphere(rng.RandomFloat(), rng.RandomFloat()); dir = Faceforward(dir, hitGeometry.nn); } } // Launch tasks to compute radiance probes at sample points vector<Task *> tasks; ProgressReporter prog(count, "Radiance Probes"); for (int i = 0; i < count; ++i) tasks.push_back(new CreateRadProbeTask(i, nProbes, time, bbox, lmax, includeDirectInProbes, includeIndirectInProbes, nIndirSamples, prog, origSample, surfacePoints, scene, this, c_in[i])); EnqueueTasks(tasks); WaitForAllTasks(); for (uint32_t i = 0; i < tasks.size(); ++i) delete tasks[i]; prog.Done(); // Write radiance probe coefficients to file FILE *f = fopen(filename.c_str(), "w"); if (f) { if (fprintf(f, "%d %d %d\n", lmax, includeDirectInProbes?1:0, includeIndirectInProbes?1:0) < 0 || fprintf(f, "%d %d %d\n", nProbes[0], nProbes[1], nProbes[2]) < 0 || fprintf(f, "%f %f %f %f %f %f\n", bbox.pMin.x, bbox.pMin.y, bbox.pMin.z, bbox.pMax.x, bbox.pMax.y, bbox.pMax.z) < 0) { Error("Error writing radiance file \"%s\" (%s)", filename.c_str(), strerror(errno)); exit(1); } for (int i = 0; i < nProbes[0] * nProbes[1] * nProbes[2]; ++i) { for (int j = 0; j < SHTerms(lmax); ++j) { fprintf(f, " "); if (c_in[i][j].Write(f) == false) { Error("Error writing radiance file \"%s\" (%s)", filename.c_str(), strerror(errno)); exit(1); } fprintf(f, "\n"); } fprintf(f, "\n"); } fclose(f); } for (int i = 0; i < nProbes[0] * nProbes[1] * nProbes[2]; ++i) delete[] c_in[i]; delete[] c_in; delete origSample; }