Ray AbstractObject::genSurfaceSample(){ Ray ray; if(!areaThreshold.size()){ ray.direction = vec3f(0,0,0); ray.radiance = vec3f(0,0,0); return ray; } float randArea = rng->genFloat() * boundArea; uint index = std::lower_bound(areaThreshold.begin(), areaThreshold.end(), randArea) - areaThreshold.begin(); if(index == areaThreshold.size()) index--; ray.contactObj = this; ray.contactTriangleID = index; ray.origin = genRandTrianglePosition(ray.contactTriangleID); UniformSphereSampler uniformSampler; vec3f normal = ray.contactObj->getWorldNormal(ray.contactTriangleID, ray.origin); ray.direction = uniformSampler.sample(*rng, vec3f(), &ray.directionProb); if(ray.direction.dot(normal) < 0) ray.direction = -ray.direction; ray.radiance = ray.evalBSDF(ray); ray.insideObj = scene->findInsideObject(ray, ray.contactObj); ray.directionProb *= 2; ray.originProb = 1 / boundArea * pickProb; Scene::ObjSourceInfo info; NoSelfCondition condition(scene, ray); float dist = scene->intersect(ray, info, &condition); if(dist > 0){ ray.intersectObj = scene->objects[info.objID]; ray.intersectDist = dist; ray.intersectTriangleID = info.triID; } return ray; }
Ray SceneObject::emit(bool isUniformOrigin , bool isUniformDir) const { Ray ray; if(!areaValues.size()) { ray.direction = vec3f(0, 0, 0); ray.directionProb = 1; ray.color = vec3f(0, 0, 0); return ray; } if (isUniformOrigin) { float rnd = RandGenerator::genFloat()*totalArea; unsigned index = (lower_bound(areaValues.begin(), areaValues.end(), rnd)-areaValues.begin()); if(index >= areaValues.size()) index = areaValues.size() - 1; ray.contactObject = (SceneObject*)this; ray.contactObjectTriangleID = index; ray.origin = genRandTrianglePosition(ray.contactObjectTriangleID); ray.originProb = weight / totalArea; } else { float rnd = RandGenerator::genFloat()*totalEnergy; unsigned index = (lower_bound(energyDensity.begin(), energyDensity.end(), rnd)-energyDensity.begin()); if(index >= energyDensity.size()) index = energyDensity.size() - 1; ray.contactObject = (SceneObject*)this; ray.contactObjectTriangleID = index; ray.origin = genRandTrianglePosition(ray.contactObjectTriangleID); float prob; if (index == 0) prob = energyDensity[index] / totalEnergy; else prob = (energyDensity[index] - energyDensity[index - 1]) / totalEnergy; ray.originProb = weight * prob / areaValues[index]; } UniformSphericalSampler uniformSphericalSampler; CosineSphericalSampler cosineSphericalSampler; LocalFrame lf = ray.contactObject->getAutoGenWorldLocalFrame(ray.contactObjectTriangleID, ray.origin); if (isUniformDir) ray.direction = uniformSphericalSampler.genSample(lf); else ray.direction = cosineSphericalSampler.genSample(lf); if(ray.getContactNormal().dot(ray.direction) < 0) ray.direction = -ray.direction; ray.insideObject = scene->findInsideObject(ray, ray.contactObject); ray.current_tid = scene->getContactTreeTid(ray); ray.color = ray.getBSDF(ray); if(!emissive()) ray.color = vec3f(1, 1, 1); if (isUniformDir) ray.directionProb = uniformSphericalSampler.getProbDensity(lf , ray.direction) * 2.f; else ray.directionProb = cosineSphericalSampler.getProbDensity(lf, ray.direction); ray.directionSampleType = ray.originSampleType = Ray::RANDOM; if(!scene->usingGPU()) { Scene::ObjSourceInformation osi; NoSelfIntersectionCondition condition(scene, ray); float dist = scene->intersect(ray, osi, &condition); if(dist > 0) { ray.intersectDist = dist; ray.intersectObject = scene->objects[osi.objID]; ray.intersectObjectTriangleID = osi.triangleID; } } return ray; }