// ImageFilm Method Definitions ImageFilm::ImageFilm(int xres, int yres, Filter *filt, const float crop[4], const string &fn, bool premult, int wf) : Film(xres, yres) { filter = filt; memcpy(cropWindow, crop, 4 * sizeof(float)); filename = fn; premultiplyAlpha = premult; writeFrequency = sampleCount = wf; // Compute film image extent xPixelStart = Ceil2Int(xResolution * cropWindow[0]); xPixelCount = max(1, Ceil2Int(xResolution * cropWindow[1]) - xPixelStart); yPixelStart = Ceil2Int(yResolution * cropWindow[2]); yPixelCount = max(1, Ceil2Int(yResolution * cropWindow[3]) - yPixelStart); // Allocate film image storage pixels = new BlockedArray<Pixel>(xPixelCount, yPixelCount); // Precompute filter weight table #define FILTER_TABLE_SIZE 16 filterTable = new float[FILTER_TABLE_SIZE * FILTER_TABLE_SIZE]; float *ftp = filterTable; for (int y = 0; y < FILTER_TABLE_SIZE; ++y) { float fy = ((float)y + .5f) * filter->yWidth / FILTER_TABLE_SIZE; for (int x = 0; x < FILTER_TABLE_SIZE; ++x) { float fx = ((float)x + .5f) * filter->xWidth / FILTER_TABLE_SIZE; *ftp++ = filter->Evaluate(fx, fy); } } }
PotentialField::PotentialField(const BBox& bbox, double div_size) : bound(bbox), division(div_size) { Vector3D diag = bound.getDiagnal(); grids[0] = Ceil2Int(diag.x / division); grids[1] = Ceil2Int(diag.y / division); grids[2] = Ceil2Int(diag.z / division); }
void ImageFilm::AddSample(const Sample &sample, const Ray &ray, const Spectrum &L, float alpha) { // Compute sample's raster extent float dImageX = sample.imageX - 0.5f; float dImageY = sample.imageY - 0.5f; int x0 = Ceil2Int (dImageX - filter->xWidth); int x1 = Floor2Int(dImageX + filter->xWidth); int y0 = Ceil2Int (dImageY - filter->yWidth); int y1 = Floor2Int(dImageY + filter->yWidth); x0 = max(x0, xPixelStart); x1 = min(x1, xPixelStart + xPixelCount - 1); y0 = max(y0, yPixelStart); y1 = min(y1, yPixelStart + yPixelCount - 1); if ((x1-x0) < 0 || (y1-y0) < 0) return; // Loop over filter support and add sample to pixel arrays // Precompute $x$ and $y$ filter table offsets int *ifx = (int *)alloca((x1-x0+1) * sizeof(int)); for (int x = x0; x <= x1; ++x) { float fx = fabsf((x - dImageX) * filter->invXWidth * FILTER_TABLE_SIZE); ifx[x-x0] = min(Floor2Int(fx), FILTER_TABLE_SIZE-1); } int *ify = (int *)alloca((y1-y0+1) * sizeof(int)); for (int y = y0; y <= y1; ++y) { float fy = fabsf((y - dImageY) * filter->invYWidth * FILTER_TABLE_SIZE); ify[y-y0] = min(Floor2Int(fy), FILTER_TABLE_SIZE-1); } for (int y = y0; y <= y1; ++y) for (int x = x0; x <= x1; ++x) { // Evaluate filter value at $(x,y)$ pixel int offset = ify[y-y0]*FILTER_TABLE_SIZE + ifx[x-x0]; float filterWt = filterTable[offset]; //printf("BEFORE add weight : "); //L.printSelf(); // Update pixel values with filtered sample contribution Pixel &pixel = (*pixels)(x - xPixelStart, y - yPixelStart); pixel.L.AddWeighted(filterWt, L); //printf("AFTER add weight : "); //pixel.L.printSelf(); pixel.alpha += alpha * filterWt; pixel.weightSum += filterWt; } // Possibly write out in-progress image if (--sampleCount == 0) { WriteImage(); sampleCount = writeFrequency; } }
Vector3D PotentialField::gradiance(const Point3D& m_pos) const { Vector3D ret; Vector3D diag = m_pos - bound.pMin; if (diag.x < 0 || diag.y < 0 || diag.z < 0) { return ret; } // ceil grid index double divIdx[3] = { diag.x / division, diag.y / division, diag.z / division }; int ceilIdx = Ceil2Int(divIdx[0]) + Ceil2Int(divIdx[1]) * grids[1] + Ceil2Int(divIdx[2]) * grids[0] * grids[1]; int floorIdx = Floor2Int(divIdx[0]) + Floor2Int(divIdx[1]) * grids[1] + Floor2Int(divIdx[2]) * grids[0] * grids[1]; ret = lerp(m_field[floorIdx], m_field[ceilIdx], diag.getLength() / divDiag); return ret; }
Spectrum EmissionIntegrator::Li(const Scene *scene, const Renderer *renderer, const RayDifferential &ray, const Sample *sample, RNG &rng, Spectrum *T, MemoryArena &arena) const { VolumeRegion *vr = scene->volumeRegion; Assert(sample != NULL); float t0, t1; if (!vr || !vr->IntersectP(ray, &t0, &t1) || (t1-t0) == 0.f) { *T = Spectrum(1.f); return 0.f; } // Do emission-only volume integration in _vr_ Spectrum Lv(0.); // Prepare for volume integration stepping int nSamples = Ceil2Int((t1-t0) / stepSize); float step = (t1 - t0) / nSamples; Spectrum Tr(1.f); pbrt::Point p = ray(t0), pPrev; Vector w = -ray.d; t0 += sample->oneD[scatterSampleOffset][0] * step; for (int i = 0; i < nSamples; ++i, t0 += step) { // Advance to sample at _t0_ and update _T_ pPrev = p; p = ray(t0); Ray tauRay(pPrev, p - pPrev, 0.f, 1.f, ray.time, ray.depth); Spectrum stepTau = vr->tau(tauRay, .5f * stepSize, rng.RandomFloat()); Tr *= Exp(-stepTau); // Possibly terminate ray marching if transmittance is small if (Tr.y() < 1e-3) { const float continueProb = .5f; if (rng.RandomFloat() > continueProb) { Tr = 0.f; break; } Tr /= continueProb; } // Compute emission-only source term at _p_ Lv += Tr * vr->Lve(p, w, ray.time); } *T = Tr; return Lv * step; }
Spectrum VSDScatteringIntegrator::LiSingle(const Scene *scene, const Renderer *renderer, const RayDifferential &ray, const Sample *sample, RNG &rng, Spectrum *T, MemoryArena &arena) const { VolumeRegion *vr = scene->volumeRegion; float t0, t1; vr->IntersectP(ray, &t0, &t1); // Do single scattering volume integration in _vr_ Spectrum Lv(0.); // Prepare for volume integration stepping int nSamples = Ceil2Int((t1-t0) / stepSize); float step = (t1 - t0) / nSamples; Spectrum Tr(1.f); Point p = ray(t0), pPrev; t0 += sample->oneD[scatterSampleOffset][0] * step; // Compute the emission from the voxels, not from the light sources for (int i = 0; i < nSamples; ++i, t0 += step) { // Advance to sample at _t0_ and update _T_ pPrev = p; p = ray(t0); Ray tauRay(pPrev, p - pPrev, 0.f, 1.f, ray.time, ray.depth); Spectrum stepTau = vr->tau(tauRay, .5f * stepSize, rng.RandomFloat()); Tr *= Exp(-stepTau); // Possibly terminate ray marching if transmittance is small if (Tr.y() < 1e-3) { const float continueProb = .5f; if (rng.RandomFloat() > continueProb) { Tr = 0.f; break; } Tr /= continueProb; } // Compute emission term at _p_ Lv += Tr * vr->PhotonDensity(p); } *T = Tr; return Lv * step; }
Spectrum SingleScatteringFluorescenceRWLIntegrator::Li(const Scene *scene, const Renderer *renderer, const RayDifferential &ray, const Sample *sample, RNG &rng, Spectrum *T, MemoryArena &arena) const { VolumeRegion *vr = scene->volumeRegion; float t0, t1; if (!vr || !vr->IntersectP(ray, &t0, &t1) || (t1-t0) == 0.f) { *T = 1.f; return 0.f; } // Do single scattering volume integration in _vr_ Spectrum Lv(0.); // Prepare for volume integration stepping int nSamples = Ceil2Int((t1-t0) / stepSize); float step = (t1 - t0) / nSamples; Spectrum Tr(1.f); Point p = ray(t0), pPrev; Vector w = -ray.d; t0 += sample->oneD[scatterSampleOffset][0] * step; // Compute sample patterns for single scattering samples float *lightNum = arena.Alloc<float>(nSamples); LDShuffleScrambled1D(1, nSamples, lightNum, rng); float *lightComp = arena.Alloc<float>(nSamples); LDShuffleScrambled1D(1, nSamples, lightComp, rng); float *lightPos = arena.Alloc<float>(2*nSamples); LDShuffleScrambled2D(1, nSamples, lightPos, rng); uint32_t sampOffset = 0; for (int i = 0; i < nSamples; ++i, t0 += step) { // Advance to sample at _t0_ and update _T_ pPrev = p; p = ray(t0); Ray tauRay(pPrev, p - pPrev, 0.f, 1.f, ray.time, ray.depth); Spectrum stepTau = vr->tau(tauRay, 0.5f * stepSize, rng.RandomFloat()); Tr *= Exp(-stepTau); // Possibly terminate ray marching if transmittance is small if (Tr.y() < 1e-3) { const float continueProb = .5f; if (rng.RandomFloat() > continueProb) { Tr = 0.f; break; } Tr /= continueProb; } // Compute fluorescence emission Spectrum sigma = vr->Mu(p, w, ray.time); if (!sigma.IsBlack() && scene->lights.size() > 0) { int nLights = scene->lights.size(); int ln = min(Floor2Int(lightNum[sampOffset] * nLights), nLights-1); Light *light = scene->lights[ln]; // Add contribution of _light_ due to the in-scattering at _p_ float pdf; VisibilityTester vis; Vector wo; LightSample ls(lightComp[sampOffset], lightPos[2*sampOffset], lightPos[2*sampOffset+1]); Spectrum L = light->Sample_L(p, 0.f, ls, ray.time, &wo, &pdf, &vis); if (!L.IsBlack() && pdf > 0.f && vis.Unoccluded(scene)) { Spectrum Ld = L * vis.Transmittance(scene, renderer, NULL, rng, arena); int lambdaExcIndex = light->GetLaserWavelengthIndex(); float Lpower = Ld.GetLaserEmissionPower(lambdaExcIndex); float yield = vr->Yeild(Point()); Spectrum fEx = vr->fEx(Point()); Spectrum fEm = vr->fEm(Point()); float scale = fEx.GetSampleValueAtWavelengthIndex(lambdaExcIndex); Lv += Lpower * Tr * sigma * vr->p(p, w, -wo, ray.time) * scale * fEm * yield * float(nLights) / pdf; } } ++sampOffset; } *T = Tr; return Lv * step; }
Spectrum SingleScatteringIntegrator::Li(const Scene *scene, const Renderer *renderer, const RayDifferential &ray, const Sample *sample, Spectrum *T, MemoryArena &arena) const { VolumeRegion *vr = scene->volumeRegion; float t0, t1; if (!vr || !vr->IntersectP(ray, &t0, &t1)) { *T = 1.f; return 0.f; } // Do single scattering volume integration in _vr_ Spectrum Lv(0.); // Prepare for volume integration stepping int nSamples = Ceil2Int((t1-t0) / stepSize); float step = (t1 - t0) / nSamples; Spectrum Tr(1.f); Point p = ray(t0), pPrev; Vector w = -ray.d; t0 += sample->oneD[scatterSampleOffset][0] * step; // Compute sample patterns for single scattering samples float *lightNum = arena.Alloc<float>(nSamples); LDShuffleScrambled1D(1, nSamples, lightNum, *sample->rng); float *lightComp = arena.Alloc<float>(nSamples); LDShuffleScrambled1D(1, nSamples, lightComp, *sample->rng); float *lightPos = arena.Alloc<float>(2*nSamples); LDShuffleScrambled2D(1, nSamples, lightPos, *sample->rng); u_int sampOffset = 0; for (int i = 0; i < nSamples; ++i, t0 += step) { // Advance to sample at _t0_ and update _T_ pPrev = p; p = ray(t0); Ray tauRay(pPrev, p - pPrev, 0.f, 1.f, ray.time, ray.depth); Spectrum stepTau = vr->tau(tauRay, .5f * stepSize, sample->rng->RandomFloat()); Tr *= Exp(-stepTau); // Possibly terminate ray marching if transmittance is small if (Tr.y() < 1e-3) { const float continueProb = .5f; if (sample->rng->RandomFloat() > continueProb) break; Tr /= continueProb; } // Compute single-scattering source term at _p_ Lv += Tr * vr->Lve(p, w, ray.time); Spectrum ss = vr->sigma_s(p, w, ray.time); if (!ss.IsBlack() && scene->lights.size() > 0) { int nLights = scene->lights.size(); int ln = min(Floor2Int(lightNum[sampOffset] * nLights), nLights-1); Light *light = scene->lights[ln]; // Add contribution of _light_ due to scattering at _p_ float pdf; VisibilityTester vis; Vector wo; LightSample ls(lightComp[sampOffset], lightPos[2*sampOffset], lightPos[2*sampOffset+1]); Spectrum L = light->Sample_L(p, 0.f, ls, ray.time, &wo, &pdf, &vis); if (!L.IsBlack() && pdf > 0.f && vis.Unoccluded(scene)) { Spectrum Ld = L * vis.Transmittance(scene, renderer, NULL, sample->rng, arena); Lv += Tr * ss * vr->p(p, w, -wo, ray.time) * Ld * float(nLights) / pdf; } } ++sampOffset; } *T = Tr; return Lv * step; }
Spectrum PhotonVolumeIntegrator::Li(const Scene *scene, const Renderer *renderer, const RayDifferential &ray, const Sample *sample, RNG &rng, Spectrum *T, MemoryArena &arena) const { VolumeRegion *vr = scene->volumeRegion; RainbowVolume* rv = dynamic_cast<RainbowVolume*>(vr); KdTree<Photon>* volumeMap = photonShooter->volumeMap; float t0, t1; if (!vr || !vr->IntersectP(ray, &t0, &t1) || (t1-t0) == 0.f){ *T = 1.f; return 0.f; } // Do single scattering & photon multiple scattering volume integration in _vr_ Spectrum Lv(0.); // Prepare for volume integration stepping int nSamples = Ceil2Int((t1-t0) / stepSize); float step = (t1 - t0) / nSamples; Spectrum Tr(1.f); Point p = ray(t0), pPrev; Vector w = -ray.d; t0 += sample->oneD[scatterSampleOffset][0] * step; float *lightNum = arena.Alloc<float>(nSamples); LDShuffleScrambled1D(1, nSamples, lightNum, rng); float *lightComp = arena.Alloc<float>(nSamples); LDShuffleScrambled1D(1, nSamples, lightComp, rng); float *lightPos = arena.Alloc<float>(2*nSamples); LDShuffleScrambled2D(1, nSamples, lightPos, rng); int sampOffset = 0; ClosePhoton *lookupBuf = new ClosePhoton[nSamples]; for (int i = 0; i < nSamples; ++i, t0 += step) { // Advance to sample at _t0_ and update _T_ pPrev = p; p = ray(t0); Ray tauRay(pPrev, p - pPrev, 0.f, 1.f, ray.time, ray.depth); Spectrum stepTau = vr->tau(tauRay,.5f * stepSize, rng.RandomFloat()); Tr = Exp(-stepTau); // Possibly terminate raymarching if transmittance is small. if (Tr.y() < 1e-3) { const float continueProb = .5f; if (rng.RandomFloat() > continueProb){ Tr = 0.f; break; } Tr /= continueProb; } // Compute single-scattering source term at _p_ & photon mapped MS Spectrum L_i(0.); Spectrum L_d(0.); Spectrum L_ii(0.); // Lv += Tr*vr->Lve(p, w, ray.time); Spectrum ss = vr->sigma_s(p, w, ray.time); Spectrum sa = vr->sigma_a(p, w, ray.time); if (!ss.IsBlack() && scene->lights.size() > 0) { int nLights = scene->lights.size(); int ln = min(Floor2Int(lightNum[sampOffset] * nLights), nLights-1); Light *light = scene->lights[ln]; // Add contribution of _light_ due to scattering at _p_ float pdf; VisibilityTester vis; Vector wo; LightSample ls(lightComp[sampOffset], lightPos[2*sampOffset], lightPos[2*sampOffset+1]); Spectrum L = light->Sample_L(p, 0.f, ls, ray.time, &wo, &pdf, &vis); if (!L.IsBlack() && pdf > 0.f && vis.Unoccluded(scene)) { Spectrum Ld = L * vis.Transmittance(scene,renderer, NULL, rng, arena); if(rv){ L_d = rv->rainbowReflection(Ld, ray.d, wo); } else { L_d = vr->p(p, w, -wo, ray.time) * Ld * float(nLights)/pdf; } } } // Compute 'indirect' in-scattered radiance from photon map if(!rv){ L_ii += LPhoton(volumeMap, nUsed, lookupBuf, w, p, vr, maxDistSquared, ray.time); } // Compute total in-scattered radiance if (sa.y()!=0.0 || ss.y()!=0.0) L_i = L_d + (ss/(sa+ss))*L_ii; else L_i = L_d; Spectrum nLv = (sa*vr->Lve(p,w,ray.time)*step) + (ss*L_i*step) + (Tr * Lv) ; Lv = nLv; sampOffset++; } *T = Tr; return Lv; }
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; }
//----------------------------------------------------------------------------- // Draws shield decals //----------------------------------------------------------------------------- void C_Shield::DrawShieldDecals( Vector* pt, bool hitDecals ) { if (m_Decals.Size() == 0) return; // Compute ripples: for ( int r = m_Decals.Size(); --r >= 0; ) { // At the moment, nothing passes! bool passDecal = false; if ((!hitDecals) && (passDecal == hitDecals)) continue; SetCurrentDecal( r ); // We have to force a flush here because we're changing the proxy state if (!hitDecals) materials->Bind( m_pPassDecal, (IClientRenderable*)this ); else materials->Bind( passDecal ? m_pPassDecal2 : m_pHitDecal, (IClientRenderable*)this ); float dtime = gpGlobals->curtime - m_Decals[r].m_StartTime; float decay = exp( -( 2 * dtime) ); // Retire the animation if it wraps // This gets set by TextureAnimatedWrapped above if ((m_Decals[r].m_StartTime < 0.0f) || (decay < 1e-3)) { m_Decals.Remove(r); continue; } IMesh* pMesh = materials->GetDynamicMesh(); // Figure out the quads we must mod2x.... float u0 = m_Decals[r].m_RippleU - m_Decals[r].m_Radius; float u1 = m_Decals[r].m_RippleU + m_Decals[r].m_Radius; float v0 = m_Decals[r].m_RippleV - m_Decals[r].m_Radius; float v1 = m_Decals[r].m_RippleV + m_Decals[r].m_Radius; float du = u1 - u0; float dv = v1 - v0; int i0 = Floor2Int( v0 * (m_SubdivisionCount - 1) ); int i1 = Ceil2Int( v1 * (m_SubdivisionCount - 1) ); int j0 = Floor2Int( u0 * (m_SubdivisionCount - 1) ); int j1 = Ceil2Int( u1 * (m_SubdivisionCount - 1) ); if (i0 < 0) i0 = 0; if (i1 >= m_SubdivisionCount) i1 = m_SubdivisionCount - 1; if (j0 < 0) j0 = 0; if (j1 >= m_SubdivisionCount) j1 = m_SubdivisionCount - 1; int numTriangles = (i1 - i0) * (j1 - j0) * 2; CMeshBuilder meshBuilder; meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, numTriangles ); float decalDu = m_InvSubdivisionCount / du; float decalDv = m_InvSubdivisionCount / dv; unsigned char color[3]; color[0] = s_ImpactDecalColor[0] * decay; color[1] = s_ImpactDecalColor[1] * decay; color[2] = s_ImpactDecalColor[2] * decay; for ( int i = i0; i < i1; ++i) { float t = (float)i * m_InvSubdivisionCount; for (int j = j0; j < j1; ++j) { float s = (float)j * m_InvSubdivisionCount; int idx = i * m_SubdivisionCount + j; // Compute (u,v) into the decal float decalU = (s - u0) / du; float decalV = (t - v0) / dv; meshBuilder.Position3fv( pt[idx].Base() ); meshBuilder.Color3ubv( color ); meshBuilder.TexCoord2f( 0, decalU, decalV ); meshBuilder.AdvanceVertex(); meshBuilder.Position3fv( pt[idx + m_SubdivisionCount].Base() ); meshBuilder.Color3ubv( color ); meshBuilder.TexCoord2f( 0, decalU, decalV + decalDv ); meshBuilder.AdvanceVertex(); meshBuilder.Position3fv( pt[idx + 1].Base() ); meshBuilder.Color3ubv( color ); meshBuilder.TexCoord2f( 0, decalU + decalDu, decalV ); meshBuilder.AdvanceVertex(); meshBuilder.Position3fv( pt[idx + 1].Base() ); meshBuilder.Color3ubv( color ); meshBuilder.TexCoord2f( 0, decalU + decalDu, decalV ); meshBuilder.AdvanceVertex(); meshBuilder.Position3fv( pt[idx + m_SubdivisionCount].Base() ); meshBuilder.Color3ubv( color ); meshBuilder.TexCoord2f( 0, decalU, decalV + decalDv ); meshBuilder.AdvanceVertex(); meshBuilder.Position3fv( pt[idx + m_SubdivisionCount + 1].Base() ); meshBuilder.Color3ubv( color ); meshBuilder.TexCoord2f( 0, decalU + decalDu, decalV + decalDv ); meshBuilder.AdvanceVertex(); } } meshBuilder.End(); pMesh->Draw(); } }
#endif // ImageFilm Method Definitions FalseColorFilm::FalseColorFilm(int xres, int yres, Filter *filt, const float crop[4], const string &fn, bool openWindow) #ifdef PBRT_FILM_FALSECOLOR_LOCK : Film(xres, yres), mutex(*Mutex::Create()), changed(false) #else : Film(xres, yres), changed(false) #endif { filter = filt; memcpy(cropWindow, crop, 4 * sizeof(float)); filename = fn; // Compute film image extent xPixelStart = Ceil2Int(xResolution * cropWindow[0]); xPixelCount = max(1, Ceil2Int(xResolution * cropWindow[1]) - xPixelStart); yPixelStart = Ceil2Int(yResolution * cropWindow[2]); yPixelCount = max(1, Ceil2Int(yResolution * cropWindow[3]) - yPixelStart); // Allocate film image storage pixels = new BlockedArray<Pixel>(xPixelCount, yPixelCount); // Possibly open window for image display if (openWindow || PbrtOptions.openWindow) { Warning("Support for opening image display window not available in this build."); } } void FalseColorFilm::AddSample(const CameraSample &sample,
//------------------------------------------------------------------------------ // Purpose : Window has been touched. Break out pieces based on touching // entity's bounding box // Input : // Output : //------------------------------------------------------------------------------ void CBreakableSurface::SurfaceTouch( CBaseEntity *pOther ) { // If tile only break if object is moving fast if (m_nSurfaceType == SHATTERSURFACE_TILE) { Vector vVel; pOther->GetVelocity( &vVel, NULL ); if (vVel.Length() < 500) { return; } } // Find nearest point on plane for max Vector vecAbsMins, vecAbsMaxs; pOther->CollisionProp()->WorldSpaceAABB( &vecAbsMins, &vecAbsMaxs ); Vector vToPlane = (vecAbsMaxs - m_vCorner); float vDistToPlane = DotProduct(m_vNormal,vToPlane); Vector vTouchPos = vecAbsMaxs + vDistToPlane*m_vNormal; float flMinsWidth,flMinsHeight; PanePos(vTouchPos, &flMinsWidth, &flMinsHeight); // Find nearest point on plane for mins vToPlane = (vecAbsMins - m_vCorner); vDistToPlane = DotProduct(m_vNormal,vToPlane); vTouchPos = vecAbsMins + vDistToPlane*m_vNormal; float flMaxsWidth,flMaxsHeight; PanePos(vTouchPos, &flMaxsWidth, &flMaxsHeight); int nMinWidth = Floor2Int(MAX(0, MIN(flMinsWidth,flMaxsWidth))); int nMaxWidth = Ceil2Int(MIN(m_nNumWide,MAX(flMinsWidth,flMaxsWidth))); int nMinHeight = Floor2Int(MAX(0, MIN(flMinsHeight,flMaxsHeight))); int nMaxHeight = Ceil2Int(MIN(m_nNumHigh,MAX(flMinsHeight,flMaxsHeight))); Vector vHitVel; pOther->GetVelocity( &vHitVel, NULL ); // Move faster then penetrating object so can see shards vHitVel *= 5; // If I'm not broken yet, break me if ( !m_bIsBroken ) { Die( pOther, vHitVel ); } for (int height=nMinHeight;height<nMaxHeight;height++) { // Randomly break the one before so it doesn't look square if (random->RandomInt(0,1)) { ShatterPane(nMinWidth-1, height,vHitVel,pOther->GetLocalOrigin()); } for (int width=nMinWidth;width<nMaxWidth;width++) { ShatterPane(width, height,vHitVel,pOther->GetLocalOrigin()); } // Randomly break the one after so it doesn't look square if (random->RandomInt(0,1)) { ShatterPane(nMaxWidth+1, height,vHitVel,pOther->GetLocalOrigin()); } } }