Color World::runBiDi(vec origin, vec direction) const { Thing *emitter = emitters[Random::upto(emitters.size())]; std::vector<Color> cumEmtWeight; std::vector<HitInfo> emtHits; std::vector<Color> cumEyeWeight; std::vector<HitInfo> eyeHits; std::vector<int> todo; cumEmtWeight.reserve(depth); emtHits.reserve(depth); cumEyeWeight.reserve(depth); eyeHits.reserve(depth); todo.reserve(depth); HitInfo emtInfo; vec emtN; vec source; source = emitter->randomSurfacePoint(emtN); emtInfo.hit = true; emtInfo.incoming = emtN; emtInfo.normal = emtN; emtInfo.location = source; emtInfo.mat = emitter->getMaterial(); cumEmtWeight.push_back(emitter->getMaterial()->getColor()); emtHits.push_back(emtInfo); bool done = false; for (int d = 1; d < depth && !done; d++) { HitInfo newI; newI.follow(emtHits[d-1]); vec newDirection = emtHits[d-1].mat->sample(emtHits[d-1].incoming, emtHits[d-1].normal); objects->hit(&newI, emtHits[d-1].location, newDirection); cumEmtWeight.push_back(emtHits[d-1].mat->combineColor( cumEmtWeight[d-1] * emtHits[d-1].mat->sampledPdf( emtHits[d-1].incoming, newDirection, emtHits[d-1].normal))); if (newI.hit) emtHits.push_back(newI); else done = true; } HitInfo eyeInfo; objects->hit(&eyeInfo, origin, direction); done = false; if (!eyeInfo.hit) return Color(0,0,0); cumEyeWeight.push_back(eyeInfo.mat->getColor()); eyeHits.push_back(eyeInfo); /*for (int d = 1; d < depth && !done; d++) { HitInfo newI; newI.follow(eyeHits[d-1]); vec newDirection = eyeHits[d-1].mat->sample(eyeHits[d-1].incoming, eyeHits[d-1].normal); objects->hit(&newI, eyeHits[d-1].location, newDirection); cumEyeWeight.push_back(eyeHits[d-1].mat->combineColor( cumEyeWeight[d-1] * eyeHits[d-1].mat->sampledPdf( eyeHits[d-1].incoming, newDirection, eyeHits[d-1].normal))); if (newI.hit) eyeHits.push_back(newI); else done = true; }*/ for (int d = 1; d < depth && !todo.empty(); d++) { HitInfo newI; int index = todo.back(); todo.pop_back(); newI.follow(eyeHits[index]); vec newDirection = eyeHits[index].mat->sample(eyeHits[index].incoming, eyeHits[index].normal); objects->hit(&newI, eyeHits[index].location, newDirection); if (newI.hit) { Color newc = eyeHits[index].mat->combineColor( cumEyeWeight[index] * eyeHits[index].mat->sampledPdf( eyeHits[index].incoming, newDirection, eyeHits[index].normal)); int ints = 1;//newc.intensity() * 5 + 1; for (int x=0; x<ints; x++) todo.push_back(eyeHits.size()); eyeHits.push_back(newI); cumEyeWeight.push_back(newc * (1.0/ints)); } else done = true; } Color accum; for (int x=0; x<emtHits.size(); x++) for (int y=0; y<eyeHits.size(); y++) { vec dir = eyeHits[y].location - emtHits[x].location; double dist = dir.magnitude(); dir.normalize(); HitInfo inf; inf.distanceOnly = true; inf.distance = dist; objects->hit(&inf, emtHits[x].location, dir); if (inf.distance >= dist - EPSILON || !inf.hit) { //hit accum += cumEyeWeight[y] * cumEmtWeight[x] * eyeHits[y].mat->pdf(eyeHits[y].incoming, dir * -1, eyeHits[y].normal) * emtHits[x].mat->pdf(emtHits[x].incoming, dir, emtHits[x].normal); } } return accum; /*if (eyeInfo.hit) { vec newn; vec dtl = eyeInfo.location - emitter->randomSurfacePoint(newn); return emitter->getMaterial()->getColor() * eyeInfo.mat->pdf(direction*-1, dtl, eyeInfo.normal); } else return Color(0,0,0);*/ }
void World::createCache() { Thing *emitter; HitInfo c; int length =0; int resetcount = 1; HitInfo emtInfo; vec emtN; vec source; emitter = emitters[Random::upto(emitters.size())]; source = emitter->randomSurfacePoint(emtN); emtInfo.hit = true; emtInfo.incoming = emtN; emtInfo.normal = emtN; emtInfo.location = source; emtInfo.mat = emitter->getMaterial(); colorcache.push_back(emitter->getMaterial()->getColor()); hicache.push_back(emtInfo); bool done = false; for (int d = 1; d < cacheSize; d++) { int i = d - 1; double ints = colorcache[i].intensity(); if (ints < .01 || length > 60 || done) { emitter = emitters[Random::upto(emitters.size())]; source = emitter->randomSurfacePoint(emtN); emtInfo.distance = 0; emtInfo.previousDistances = 0; emtInfo.hit = true; emtInfo.incoming = emtN; emtInfo.normal = emtN; emtInfo.location = source; emtInfo.mat = emitter->getMaterial(); int intes = 1;//emitter->getMaterial()->getColor().intensity() + 1; for (int x=0; x<intes; x++) { colorcache.push_back(emitter->getMaterial()->getColor() * (1.0/intes)); hicache.push_back(emtInfo); } resetcount++; d += intes-1; done = false; length = 0; continue; } length++; HitInfo newI; newI.follow(hicache[d-1]); vec newDirection = hicache[d-1].mat->sample(hicache[d-1].incoming, hicache[d-1].normal); objects->hit(&newI, hicache[d-1].location, newDirection); if (newI.hit) { Color newc = hicache[d-1].mat->combineColor(colorcache[d-1] * hicache[d-1].mat->sampledPdf(hicache[d-1].incoming, newDirection, hicache[d-1].normal)); int intes = 1;//newc.intensity()*3 + 1; for (int x=0; x<intes; x++) { hicache.push_back(newI); colorcache.push_back(newc * (1.0/intes)); } d += intes-1; } else { done = true; d--; } } cacheweight = (cacheSize * 1.0 / resetcount); }