Skip to content

Instantly share code, notes, and snippets.

@rameshvarun
Created December 4, 2014 05:18
Show Gist options
  • Save rameshvarun/7ac2f721e1af7eb11874 to your computer and use it in GitHub Desktop.
Save rameshvarun/7ac2f721e1af7eb11874 to your computer and use it in GitHub Desktop.
Multi-threaded Scene Render.
#include "Scene.h"
#include <fstream>
#include <sstream>
#include <iostream>
#include <vector>
#include <thread>
Scene::Scene()
:currMaterial(NULL),currTexIndex(-1),use_shadow(true),use_transparent_shadow(false),attenuation_coefficient(1.f),camera(NULL),accel_structure(NONE),uniform_grid(NULL)
{
rtSampleRate(1);
}
Scene::~Scene()
{
if(currMaterial!=NULL)delete currMaterial;
if((int)textures.size()>0)for(int i=0;i<(int)textures.size();i++)delete textures[i];
if((int)volumetric_textures.size()>0)for(int i=0;i<(int)volumetric_textures.size();i++)delete volumetric_textures[i];
if(camera!=NULL)delete camera;
if((int)objects.size()>0)for(int i=0;i<(int)objects.size();i++)delete objects[i];
if((int)lights.size()>0)for(int i=0;i<(int)lights.size();i++)delete lights[i];
if((int)areaLights.size()>0)for(int i=0;i<(int)areaLights.size();i++)delete areaLights[i];
if((int)aabb_trees.size()>0)for(int i=0;i<(int)aabb_trees.size();i++)delete aabb_trees[i];
if(uniform_grid!=NULL)delete uniform_grid;
}
std::string Scene::info() {
std::stringstream out;
out<<"\nobject number: "<<objects.size()<<std::endl;
for(int i = 0; i < (int)objects.size(); i++) {
out<<"obj "<<i<<": "<<objects[i]->name<<std::endl;
}
out<<"\nlight number: "<<lights.size()<<std::endl;
for (int i = 0; i < (int)lights.size(); i++) {
out<<"light "<<i<<": "<<lights[i]->name<<std::endl;
}
out<<"\narea light number: "<<areaLights.size()<<std::endl;
for (int i = 0; i < (int)areaLights.size(); i++) {
out<<"area light "<<i<<": "<<areaLights[i]->name<<std::endl;
}
return out.str();
}
#include <atomic>
void Scene::Render() {
std::vector<std::thread> threads;
std::cout<<"------------------ray tracing started------------------"<<std::endl;
STImage *im = new STImage(width, height);
ImagePlane imPlane = ImagePlane(width, height);
int subimage_w0=242;int subimage_w1=242;
int subimage_h0=310;int subimage_h1=310;
bool use_subimage=false;
int NUM_THREADS = 8;
int SECTION_SIZE = width / NUM_THREADS;
std::atomic<int> progress(0);
for(int i = 0; i < NUM_THREADS; ++i) {
auto render_section = [this, &progress, use_subimage, subimage_w0, subimage_w1, subimage_h0, subimage_h1, &im, &imPlane](int start, int end) {
for (int w = start; w < end; w++) {
for (int h = 0; h < height; h++) {
if(use_subimage && (w<subimage_w0||w>subimage_w1||h<subimage_h0||h>subimage_h1)){
im->SetPixel(w, h, STColor4ub(0,0,255,255));
continue;
}
if(use_subimage)std::cout<<"trace_ray: "<<w<<", "<<h<<std::endl;
std::vector<Ray *>* rays = imPlane.getRays(camera, w, h, sampleRate, focus, aperture);
STColor3f avg = STColor3f(0.f, 0.f, 0.f);
for (int i = 0; i < (int)rays->size(); i++) {
STColor3f ray_color = TraceRay(*rays->at(i));
if(use_subimage)std::cout<<"ray_color: "<<ray_color.r<<", "<<ray_color.g<<", "<<ray_color.b<<std::endl;
avg += ray_color;
delete rays->at(i);
}
avg /= (float)rays->size();
float slant = 1.2;
avg = (avg - STColor3f(0.5))*slant + STColor3f(0.5);
im->SetPixel(w, h, STColor4ub(avg));
delete rays;
int old = progress.fetch_add(1);
float percentage = ((float)old) / (width*height);
if(old % (width * 100) == 0) {
std::cout << percentage << "% complete..." << std::endl;
}
}
}
};
int start = SECTION_SIZE*i;
int end = (i == NUM_THREADS - 1) ? width : start + SECTION_SIZE;
threads.push_back(std::thread(render_section, start, end));
std::cout << "Thread assigned to " << start << " to " << end << "..." << std::endl;
}
for(std::thread& thread : threads)
thread.join();
STImage *im2 = new STImage(width, height);
for(int x = 0; x < width; ++x) {
for(int y = 0; y < height; ++y) {
int rx = x - 0; int ry = y - 0;
int gx = x - 3; int gy = y - 3;
int bx = x - 6; int by = y - 6;
STColor4ub original = im->GetPixel(x, y);
STColor4ub color;
color.r = (rx >= 0 && rx < width && ry >= 0 && ry < height) ? im->GetPixel(rx, ry).r : 0;
color.g = (gx >= 0 && gx < width && gy >= 0 && gy < height) ? im->GetPixel(gx, gy).g : 0;
color.b = (bx >= 0 && bx < width && by >= 0 && by < height) ? im->GetPixel(bx, by).b : 0;
color.a = 255;
float mix = sqrt( pow((float)x - width/2, 2) + pow((float)y - height/2, 2) );
mix /= 512.0f;
if(mix > 1.0f) mix = 1.0f;
if(mix < 0.0f) mix = 0.0f;
color.r = color.r * mix + (1 - mix) * original.r;
color.g = color.g * mix + (1 - mix) * original.g;
color.b = color.b * mix + (1 - mix) * original.b;
im2->SetPixel(x, y, color);
}
}
im2->Save(imageFilename);
delete im;
delete im2;
std::cout<<"------------------ray tracing finished------------------"<<std::endl;
}
STColor3f Scene::TraceRay(const Ray &ray, int bounce) {
if (bounce == bounceDepth){
return STColor3f();
}
SceneObject *object;
Intersection* inter = Intersect(ray, object);
if (!inter){
return STColor3f();
}
if (object->shape->name == "light") {
delete inter;
return object->material.diffuse;
}
STVector3 d = ray.d;
d.Normalize();
STVector3 reflected_d = STVector3::Dot(-1. * ray.d, inter->normal) * 2 * inter->normal + ray.d;
Ray* refracted = NULL;
Ray* reflected = new Ray(inter->point, reflected_d, shadowBias);
float cos_theta_1 = STVector3::Dot(inter->normal, d);
////participating media
if(object->material.isParticipatingMedia()) {
if(cos_theta_1 > 0) { //exiting participating media
refracted = new Ray(inter->point, ray.d, shadowBias);
STColor3f result = TraceRay(*refracted, bounce + 1);
delete refracted;
delete reflected;
return result;
}
else { //entering participating media
refracted = new Ray(inter->point, ray.d, shadowBias);
STColor3f color = TraceRay(*refracted, bounce + 1);
//calculate attenuation based on distance ray traveled through medium
float atten = object->material.participatingMediaAttenuation(refracted->e, refracted->at(inter->t), *(object->aabb));
STColor3f atten_color(atten, atten, atten);
STColor3f result = color * atten_color;
delete refracted;
delete reflected;
return result;
}
}
////from inside to outside, n1>n2
if (cos_theta_1 > 0 && !object->material.isOpaque()) {
float dist = (ray.at(inter->t) - ray.e).Length();
STColor3f atten = ((STColor3f(1,1,1) - object->material.refract) * attenuation_coefficient * (-dist)).Exp();
Ray *refracted = object->material.refracted(ray, inter, shadowBias);
if (refracted) {
float nt = object->material.snell;
float sin_theta_2 = nt * sqrt(1 - cos_theta_1 * cos_theta_1);
float cos_theta_2 = sqrt(1 - sin_theta_2 * sin_theta_2);
float r0 = pow((nt - 1) / (nt + 1), 2);
float refl = r0 + (1 - r0) * pow(1 - cos_theta_2, 5);
STColor3f reflected_ray_color = TraceRay(*reflected, bounce + 1);
STColor3f refracted_ray_color = TraceRay(*refracted, bounce + 1);
STColor3f result = atten * (reflected_ray_color * refl + refracted_ray_color * (1 - refl));
delete reflected;
delete refracted;
delete inter;
return result;
} else {
STColor3f reflected_ray_color = TraceRay(*reflected, bounce + 1);
STColor3f result = atten * reflected_ray_color;
delete reflected;
delete inter;
return result;
}
}
std::vector<Light *> visibleLights;
std::vector<STColor3f> attenuation;
if(!use_transparent_shadow){fillLights(visibleLights, inter);}
else{fillLightsWithAttenuation(visibleLights, attenuation, inter);}
////from outside to inside, n1<n2
if (!object->material.isOpaque() && object->material.snell) {
refracted = object->material.refracted(ray, inter, shadowBias);
if (refracted) {
float nt = object->material.snell;
float r0 = pow((nt - 1) / (nt + 1), 2);
float refl = r0 + (1 - r0) * pow(1 + cos_theta_1, 5);
STColor3f reflected_ray_color = TraceRay(*reflected, bounce + 1);
STColor3f refracted_ray_color = TraceRay(*refracted, bounce + 1);
STColor3f result = reflected_ray_color * refl + refracted_ray_color * (1 - refl);
delete inter;
delete reflected;
delete refracted;
return result;
} else {
STColor3f result = TraceRay(*reflected, bounce + 1);
delete inter;
delete reflected;
return result;
}
}
STColor3f result;
if(use_transparent_shadow){
result = object->material.shade(inter, ray.d * -1., visibleLights, attenuation, object->material.isMatte() ? STColor3f() : TraceRay(*reflected, bounce + 1), refracted ? TraceRay(*refracted, bounce + 1) : STColor3f());
}
else{
result = object->material.shade(inter, ray.d * -1., visibleLights, object->material.isMatte() ? STColor3f() : TraceRay(*reflected, bounce + 1), refracted ? TraceRay(*refracted, bounce + 1) : STColor3f());
}
if(object->texture_index!=-1){
STColor3f tex_color=textureColor(object->texture_index,inter->uv);
result*=tex_color;
}
delete inter;
delete reflected;
if (refracted) delete refracted;
return result;
}
////find the visible lights from the intersection
void Scene::fillLights(std::vector<Light *> &visibleLights, Intersection* inter) {
if(!use_shadow){
for(int i=0;i<(int)lights.size();i++){visibleLights.push_back(lights[i]);}
return;
}
SceneObject *dummy;
for (int i = 0; i < (int)lights.size(); i++) {
if(lights[i]->name=="ambient")visibleLights.push_back(lights[i]);
else{
STVector3 toL = lights[i]->direction(inter->point);
Intersection* lightInt = Intersect(Ray(inter->point, toL, shadowBias), dummy);
if (!lightInt || ////no obstacle between light and object
((lights[i]->name == "point" || lights[i]->name == "area") && (lightInt->t > 1. || lightInt->t < shadowBias)) ||
(lights[i]->name == "directional" && lightInt->t < shadowBias)) { ////out of range between object and light
visibleLights.push_back(lights[i]);
}
delete lightInt;
}
}
for (int i = 0; i < (int)areaLights.size(); i++) {
STVector3 toL = areaLights[i]->direction(inter->point);
Intersection* lightInt = Intersect(Ray(inter->point, toL, shadowBias), dummy);
if ((toL.x == 0. || toL.y == 0. || toL.z == 0.) || (!lightInt || (lightInt->t > 1. || lightInt->t < shadowBias))) {
visibleLights.push_back(areaLights[i]);
}
delete lightInt;
}
}
void Scene::fillLightsWithAttenuation(std::vector<Light *>& visibleLights,std::vector<STColor3f>& attenuations, Intersection* inter)
{
if(!use_shadow){
for(int i=0;i<(int)lights.size();i++){visibleLights.push_back(lights[i]);}
return;
}
for (int i = 0; i < (int)lights.size(); i++) {
if(lights[i]->name=="ambient"){
visibleLights.push_back(lights[i]);
attenuations.push_back(STColor3f(1.f,1.f,1.f));
}
else{
STVector3 toL = lights[i]->direction(inter->point);
Ray* shadow_ray = new Ray(inter->point,toL,shadowBias);
STColor3f atten= traceShadowRay(*shadow_ray,*lights[i]);
if (atten.r!=0.f&&atten.g!=0.f&&atten.b!=0.f) {
visibleLights.push_back(lights[i]);
attenuations.push_back(atten);
}
delete shadow_ray;
}
}
for (int i = 0; i < (int)areaLights.size(); i++) {
STVector3 toL = areaLights[i]->direction(inter->point);
Ray* shadow_ray = new Ray(inter->point,toL,shadowBias);
STColor3f atten= traceShadowRay(*shadow_ray,*areaLights[i]);
if (atten.r!=0.f&&atten.g!=0.f&&atten.b!=0.f) {
visibleLights.push_back(areaLights[i]);
attenuations.push_back(atten);
}
delete shadow_ray;
}
}
STColor3f Scene::traceShadowRay(const Ray& ray,const Light& light)
{
SceneObject *object=NULL;
Intersection* inter = Intersect(ray, object);
if(object!=NULL){
if(((light.name == "point" || light.name == "area") && (inter->t > 1. || inter->t < shadowBias))
|| (light.name == "directional" && inter->t < shadowBias)){
delete inter;
return STColor3f(1,1,1);
}
if(object->material.isOpaque()){
delete inter;
return STColor3f(0,0,0);
}
float cos_theta_1 = STVector3::Dot(inter->normal, ray.d);
STColor3f atten(1.f,1.f,1.f);
if (cos_theta_1 > 0 ) {
float dist = (ray.at(inter->t) - ray.e).Length();
atten *= ((STColor3f(1,1,1) - object->material.refract) * attenuation_coefficient * (-dist)).Exp();
}
Ray* continue_ray=new Ray(ray.at(inter->t),ray.e+ray.d-ray.at(inter->t),shadowBias);
STColor3f continue_atten=traceShadowRay(*continue_ray,light);
delete inter;
delete continue_ray;
return atten*continue_atten;
}
else{
delete inter;
return STColor3f(1,1,1);
}
}
void Scene::rtClear()
{
currMaterial = NULL;
matStack.clear();
matStack.push_back(STTransform4::Identity());
focus = 0.;
}
void Scene::rtCamera(const STPoint3& eye, const STVector3& up, const STPoint3& lookAt, float fovy, float aspect)
{
camera = new Camera(eye, up, lookAt, fovy, aspect);
}
void Scene::rtOutput(int imgWidth, int imgHeight, const std::string& outputFilename)
{
width = imgWidth;
height = imgHeight;
imageFilename = outputFilename;
}
void Scene::rtBounceDepth(int depth)
{
bounceDepth = depth;
}
void Scene::rtShadowBias(float bias)
{
shadowBias = bias;
}
void Scene::rtSampleRate(int r)
{
sampleRate = r;
for (int i = 0; i < (int)areaLights.size(); i++) areaLights[i]->setSampleRate(r);
}
void Scene::rtPushMatrix()
{
if (!matStack.empty()) matStack.push_back(matStack.back());
}
void Scene::rtPopMatrix()
{
if (!matStack.empty()) matStack.pop_back();
}
void Scene::rtRotate(float rx, float ry, float rz)
{
if (!matStack.empty()) {
float conv = 3.14159265358979f / 180.f;
STTransform4 M = matStack.back() * STTransform4::Rotation(rx * conv, ry * conv, rz * conv);
matStack.pop_back();
matStack.push_back(M);
}
}
void Scene::rtScale(float sx, float sy, float sz)
{
if (!matStack.empty()) {
STTransform4 M = matStack.back() * STTransform4::Scaling(sx, sy, sz);
matStack.pop_back();
matStack.push_back(M);
}
}
void Scene::rtTranslate(float tx, float ty, float tz)
{
if (!matStack.empty()) {
STTransform4 M = matStack.back() * STTransform4::Translation(tx, ty, tz);
matStack.pop_back();
matStack.push_back(M);
}
}
void Scene::rtSphere(const STPoint3& center, float radius)
{
objects.push_back(new SceneObject(new Sphere(center, radius), currMaterial, &matStack.back()));
}
void Scene::rtTriangle(const STPoint3& v1, const STPoint3& v2, const STPoint3& v3)
{
objects.push_back(new SceneObject(new Triangle(v1, v2, v3), currMaterial, &matStack.back()));
}
void Scene::rtTriangle(const STPoint3& v1, const STPoint3& v2, const STPoint3& v3, const STPoint2& uv1, const STPoint2& uv2, const STPoint2& uv3)
{
objects.push_back(new SceneObject(new Triangle(v1, v2, v3, uv1, uv2, uv3), currMaterial, &matStack.back(), currTexIndex));
}
void Scene::rtBox(const STPoint3& o, const STPoint3& x, const STPoint3& y, const STPoint3& z)
{
objects.push_back(new SceneObject(new Box(o, x, y, z), currMaterial, &matStack.back()));
}
void Scene::rtBox(const STPoint3& center,const STVector3& size)
{
objects.push_back(new SceneObject(new Box(center,size), currMaterial, &matStack.back()));
}
void Scene::rtCylinder(const STPoint3& A, const STPoint3 B, float radius)
{
objects.push_back(new SceneObject(new Cylinder(A, B, radius), currMaterial, &matStack.back()));
}
void Scene::rtParticipatingMedia( const STPoint3& center,const STVector3& size,const std::string& file_name )
{
Material* participating_media_material=new Material();
objects.push_back(new SceneObject(new Box(center,size), currMaterial, &matStack.back()));
}
void Scene::rtCompound(char c)
{
if (objects.size() > 1) {
SceneObject *two = objects.back();
objects.pop_back();
SceneObject *one = objects.back();
objects.pop_back();
objects.push_back(new SceneObject(new CompoundShape(one->shape, two->shape, c, shadowBias), &one->material, &one->transform));
delete one;
delete two;
}
}
void Scene::rtGroupObjects(int num) {
SceneObject *prevObj = objects.back();
objects.pop_back();
ObjectGroup* boundVol = new ObjectGroup(prevObj); ////add the bounding volume for the group
for (int i = 0; i < num; i++) {
ObjectGroup* bv=dynamic_cast<ObjectGroup*>(objects.back());
if(bv!=0)boundVol->addSubObject(bv); ////handle the case that objects.back() is already a ObjectGroup
else boundVol->addSubObject(new ObjectGroup(objects.back()));
objects.pop_back();
}
objects.push_back(boundVol);
}
void Scene::rtTriangleMesh(const std::string& file_name,const bool& counter_clockwise,const bool& smoothed_normal)
{
std::vector<STTriangleMesh*> meshes;
STTriangleMesh::LoadObj(meshes,file_name);
for(int i = 0; i < (int)meshes.size(); i++) {
objects.push_back(new SceneObject(new TriangleMesh(*meshes[i],counter_clockwise,smoothed_normal), currMaterial, &matStack.back(), currTexIndex));
}
//objects.push_back(new SceneObject(new TriangleMesh(file_name,counter_clockwise,smoothed_normal), currMaterial, &matStack.back(), currTexIndex));
}
void Scene::rtTriangleMeshWithMaterialAndTexture(const std::string& file_name,const bool& counter_clockwise, const bool& smoothed_normal)
{
std::vector<STTriangleMesh*> meshes;
STTriangleMesh::LoadObj(meshes,file_name);
for(int i = 0; i < (int)meshes.size(); i++) {
STTriangleMesh* st_mesh=meshes[i];
int tex_index=-1;if(st_mesh->mSurfaceColorImg)rtLoadTexture(st_mesh->mSurfaceColorImg,tex_index);
STColor3f amb(st_mesh->mMaterialAmbient[0],st_mesh->mMaterialAmbient[1],st_mesh->mMaterialAmbient[2]);
STColor3f diff(st_mesh->mMaterialDiffuse[0],st_mesh->mMaterialDiffuse[1],st_mesh->mMaterialDiffuse[2]);
STColor3f spec(st_mesh->mMaterialSpecular[0],st_mesh->mMaterialSpecular[1],st_mesh->mMaterialSpecular[2]);
float shin=st_mesh->mShininess;
Material* mat=new Material(amb, diff, spec, /*mirror*/STColor3f(),shin);
objects.push_back(new SceneObject(new TriangleMesh(*meshes[i],counter_clockwise,smoothed_normal), mat, &matStack.back(), tex_index));
}
}
void Scene::rtAmbientLight(const STColor3f& col)
{
lights.push_back(new AmbientLight(col));
}
void Scene::rtPointLight(const STPoint3& loc, const STColor3f& col)
{
lights.push_back(new PointLight(matStack.back() * loc, col));
}
void Scene::rtDirectionalLight(const STVector3& dir, const STColor3f& col)
{
lights.push_back(new DirectionalLight(matStack.back() * dir, col));
}
void Scene::rtAreaLight(const STPoint3& v1, const STPoint3& v2, const STPoint3& v3, const STColor3f& col)
{
areaLights.push_back(new AreaLight(matStack.back() * v1, matStack.back() * v2, matStack.back() * v3, col, sampleRate));
}
void Scene::rtMaterial(const STColor3f& amb, const STColor3f& diff, const STColor3f& spec, const STColor3f& mirr, float shine)
{
if (currMaterial != NULL) delete currMaterial;
currMaterial = new Material(amb, diff, spec, mirr, shine);
}
void Scene::rtMaterial(const Material& mat)
{
if(currMaterial == NULL)currMaterial=new Material(mat.ambient,mat.diffuse,mat.specular,mat.mirror,mat.shininess,mat.refract,mat.snell,mat.volumetric_texture);
else{
currMaterial->ambient=mat.ambient;
currMaterial->diffuse=mat.diffuse;
currMaterial->specular=mat.specular;
currMaterial->mirror=mat.mirror;
currMaterial->shininess=mat.shininess;
currMaterial->refract=mat.refract;
currMaterial->snell=mat.snell;
currMaterial->volumetric_texture=mat.volumetric_texture;
}
}
void Scene::rtTransparentMaterial(const STColor3f& amb, const STColor3f& diff, const STColor3f& spec, const STColor3f& mirr, float shine, const STColor3f& refr, float sn)
{
if (currMaterial != NULL) delete currMaterial;
currMaterial = new Material(amb, diff, spec, mirr, shine, refr, sn);
}
void Scene::rtSetFocus(const STPoint3& focal)
{
STPoint3 pt = matStack.back() * focal;
focus = camera->getFocalRatio(pt);
}
void Scene::rtSetApeture(float a)
{
aperture = a;
}
void Scene::buildAccelStructures(std::string& accel)
{
if(accel=="aabb"){accel_structure=AABB_TREE;}
else if(accel=="grid"){accel_structure=UNIFORM_GRID;}
else{accel_structure=NONE;}
switch(accel_structure){
case AABB_TREE:
buildAABBTrees();
break;
case UNIFORM_GRID:
buildUniformGrids();
break;
default:
break;
}
}
void Scene::buildAABBTrees()
{
////by default all objects are organized in ONE aabb tree
accel_structure=AABB_TREE;
AABBTree* aabb_tree=new AABBTree(objects);
aabb_trees.push_back(aabb_tree);
}
void Scene::buildUniformGrids()
{
accel_structure=UNIFORM_GRID;
////calculate the scene bounding box
AABB scene_bounding_box;getObjectsAABB(objects,scene_bounding_box);
////default scene subdivision
int subdivision=10;STVector3 edge_length=scene_bounding_box.edgeLength();
float dx=AABB::getMax(edge_length.x,edge_length.y,edge_length.z)/(float)subdivision;
int scene_subdivision[3]={1,1,1};
for(int d=0;d<3;d++)scene_subdivision[d]=(int)ceil(edge_length.Component(d)/dx);
uniform_grid=new UniformGrid(objects,scene_bounding_box,scene_subdivision);
}
Intersection* Scene::Intersect(const Ray& ray, /*result*/SceneObject *& object)
{
switch(accel_structure){
case AABB_TREE:return IntersectAABBTree(ray,object);
case UNIFORM_GRID:return IntersectUniformGrid(ray,object);
default:return IntersectionNoAccelStructure(ray,object);
}
}
Intersection* Scene::IntersectionNoAccelStructure(const Ray& ray, /*result*/SceneObject*& object)
{
Intersection* min_inter = NULL;
SceneObject* current_object=NULL;
SceneObject* min_object = NULL;
for (int i = 0; i < (int)objects.size(); i++) {
SceneObject* obj = objects[i];
Intersection *inter = obj->getIntersectionWithObject(ray,current_object);
if (inter && (!min_inter || inter->t < min_inter->t) && ray.inRange(inter->t)) {
if (min_inter) delete min_inter;
min_inter = inter;
min_object = current_object;
} else delete inter;
}
object = min_object;
return min_inter;
}
Intersection* Scene::IntersectAABBTree(const Ray& ray, /*result*/SceneObject*& object)
{
Intersection* min_inter = NULL;
SceneObject* current_object=NULL;
SceneObject* min_object = NULL;
for (int i = 0; i < (int)aabb_trees.size(); i++) {
AABBTree* tree = aabb_trees[i];
Intersection *inter = tree->getIntersectionWithObject(ray,current_object);
if (inter && (!min_inter || inter->t < min_inter->t) && ray.inRange(inter->t)) {
if (min_inter) delete min_inter;
min_inter = inter;
min_object = current_object;
} else delete inter;
}
object = min_object;
return min_inter;
}
Intersection* Scene::IntersectUniformGrid(const Ray& ray, /*result*/SceneObject*& object)
{
return uniform_grid->getIntersectionWithObject(ray,object);
}
void Scene::getObjectsAABB(const std::vector<SceneObject*>& objs, /*result*/AABB& aabb)
{
aabb.xmin=FLT_MAX;aabb.xmax=-FLT_MAX;aabb.ymin=FLT_MAX;aabb.ymax=-FLT_MAX;aabb.zmin=FLT_MAX;aabb.zmax=-FLT_MAX;
for(int i=0;i<(int)objects.size();i++){
AABB::combine(&aabb,objects[i]->aabb,&aabb);
}
float offset=aabb.maxEdgeLength()*.001f;
aabb.enlarge(offset);
}
void Scene::initializeSceneFromScript(std::string sceneFilename)
{
rtClear();
std::ifstream sceneFile(sceneFilename.c_str());
if(sceneFile.fail()){
printf("Scene::initializeSceneFromScript - Could not find input scene file '%s'\n", sceneFilename.c_str());
exit(1);
}
char line[1024];
while (!sceneFile.eof()){
sceneFile.getline(line, 1023);
std::stringstream ss;
ss.str(line);
std::string command;
ss >> command;
if (command == "Camera")
{
float ex, ey, ez, ux, uy, uz, lx, ly, lz, f, a;
ss >> ex >> ey >> ez >> ux >> uy >> uz >> lx >> ly >> lz >> f >> a;
STPoint3 eye(ex, ey, ez);
STVector3 up(ux, uy, uz);
STPoint3 lookAt(lx, ly, lz);
rtCamera(eye, up, lookAt, f, a);
}
else
if (command == "Output")
{
int w, h;
std::string fname;
ss >> w >> h >> fname;
rtOutput(w, h, fname);
}
else if (command == "BounceDepth")
{
int depth;
ss >> depth;
rtBounceDepth(depth);
}
else if (command == "ShadowBias")
{
float bias;
ss >> bias;
rtShadowBias(bias);
}
else if (command == "PushMatrix")
{
rtPushMatrix();
}
else if (command == "PopMatrix")
{
rtPopMatrix();
}
else if (command == "Rotate")
{
float rx, ry, rz;
ss >> rx >> ry >> rz;
rtRotate(rx, ry, rz);
}
else if (command == "Scale")
{
float sx, sy, sz;
ss >> sx >> sy >> sz;
rtScale(sx, sy, sz);
}
else if (command == "Translate")
{
float tx, ty, tz;
ss >> tx >> ty >> tz;
rtTranslate(tx, ty, tz);
}
else if (command == "Sphere")
{
float cx, cy, cz, r;
ss >> cx >> cy >> cz >> r;
STPoint3 center(cx, cy, cz);
rtSphere(center, r);
}
else if (command == "Triangle")
{
float x1, y1, z1, x2, y2, z2, x3, y3, z3;
ss >> x1 >> y1 >> z1 >> x2 >> y2 >> z2 >> x3 >> y3 >> z3;
STPoint3 v[3];
v[0] = STPoint3(x1, y1, z1);
v[1] = STPoint3(x2, y2, z2);
v[2] = STPoint3(x3, y3, z3);
rtTriangle(v[0], v[1], v[2]);
}
else if (command == "Box")
{
float o1, o2, o3, x1, x2, x3, y1, y2, y3, z1, z2, z3;
ss >> o1 >> o2 >> o3 >> x1 >> x2 >> x3 >> y1 >> y2 >> y3 >> z1 >> z2 >> z3;
STPoint3 o = STPoint3(o1, o2, o3);
STPoint3 x = STPoint3(x1, x2, x3);
STPoint3 y = STPoint3(y1, y2, y3);
STPoint3 z = STPoint3(z1, z2, z3);
rtBox(o, x, y, z);
}
else if (command == "Cylinder")
{
float a1, a2, a3, b1, b2, b3, r;
ss >> a1 >> a2 >> a3 >> b1 >> b2 >> b3 >> r;
STPoint3 A(a1, a2 ,a3);
STPoint3 B(b1, b2, b3);
rtCylinder(A, B, r);
}
else if (command == "ParticipatingMedia")
{
float c1,c2,c3,s1,s2,s3;
std::string file_name;
ss >> c1 >> c2 >> c3 >> s1 >> s2 >> s3 >> file_name;
STPoint3 center(c1, c2, c3);
STVector3 size(s1, s2, s3);
rtParticipatingMedia(center,size,file_name);
}
else if (command == "Compound")
{
char c;
ss >> c;
rtCompound(c);
}
else if (command == "Group")
{
int num;
ss >> num;
rtGroupObjects(num);
}
else if(command == "TriangleMesh")
{
std::string file_name;int counter_clockwise;int smoothed_normal;
ss >> file_name >> counter_clockwise >> smoothed_normal;
rtTriangleMesh(file_name,(counter_clockwise!=0),(smoothed_normal!=0));
}
else if (command == "AmbientLight")
{
float r, g, b;
ss >> r >> g >> b;
STColor3f col(r, g, b);
rtAmbientLight(col);
}
else if (command == "PointLight")
{
float px, py, pz, r, g, b;
ss >> px >> py >> pz >> r >> g >> b;
STPoint3 pos(px, py, pz);
STColor3f col(r, g, b);
rtPointLight(pos, col);
}
else if (command == "DirectionalLight")
{
float dx, dy, dz, r, g, b;
ss >> dx >> dy >> dz >> r >> g >> b;
STVector3 dir(dx, dy, dz);
STColor3f col(r, g, b);
rtDirectionalLight(dir, col);
}
else if (command == "AreaLight")
{
float x1, y1, z1, x2, y2, z2, x3, y3, z3, r, g, b;
ss >> x1 >> y1 >> z1 >> x2 >> y2 >> z2 >> x3 >> y3 >> z3 >> r >> g >> b;
STPoint3 v[3];
v[0] = STPoint3(x1, y1, z1);
v[1] = STPoint3(x2, y2, z2);
v[2] = STPoint3(x3, y3, z3);
STColor3f col(r, g, b);
rtAreaLight(v[0], v[1], v[2], col);
}
else if (command == "Material")
{
float ra, ga, ba, rd, gd, bd, rs, gs, bs, rr, gr, br, shine;
ss >> ra >> ga >> ba >> rd >> gd >> bd >> rs >> gs >> bs >> rr >> gr >> br >> shine;
STColor3f amb(ra, ga, ba);
STColor3f diff(rd, gd, bd);
STColor3f spec(rs, gs, bs);
STColor3f mirr(rr, gr, br);
rtMaterial(amb, diff, spec, mirr, shine);
}
else if (command == "TMaterial")
{
float ra, ga, ba, rd, gd, bd, rs, gs, bs, rr, gr, br, shine, rf, gf, bf, snell;
ss >> ra >> ga >> ba >> rd >> gd >> bd >> rs >> gs >> bs >> rr >> gr >> br >> shine >> rf >> gf >> bf >> snell;
STColor3f amb(ra, ga, ba);
STColor3f diff(rd, gd, bd);
STColor3f spec(rs, gs, bs);
STColor3f mirr(rr, gr, br);
STColor3f refr(rf, gf, bf);
rtTransparentMaterial(amb, diff, spec, mirr, shine, refr, snell);
}
else if (command == "Aperture")
{
float a;
ss >> a;
rtSetApeture(a);
}
else if (command == "Focus")
{
float x, y, z;
ss >> x >> y >> z;
rtSetFocus(STPoint3(x, y, z));
}
}
sceneFile.close();
}
void Scene::rtLoadTexture(const std::string image_name,int& tex_index)
{
textures.push_back(new STImage(image_name));tex_index=textures.size()-1;
}
void Scene::rtLoadTexture(STImage* texture_image,int& tex_index)
{
textures.push_back(texture_image);tex_index=textures.size()-1;
}
void Scene::rtVolumetricTexture(VolumetricTexture* vt)
{
volumetric_textures.push_back(vt);
}
STColor3f Scene::textureColor(const int texture_index,const STPoint2& uv)
{
STImage* tex_img=textures[texture_index];
int i=(int)floor(tex_img->GetWidth()*uv.x);
int j=(int)floor(tex_img->GetHeight()*uv.y);
if(i<0)i=0;if(i>tex_img->GetWidth()-1)i=tex_img->GetWidth()-1;
if(j<0)j=0;if(j>tex_img->GetHeight()-1)j=tex_img->GetHeight()-1;
STColor3f color(tex_img->GetPixel(i,j));
return color;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment