/** * Initializes the raytracer for the given scene. Overrides any previous * initializations. May be invoked before a previous raytrace completes. * @param scene The scene to raytrace. * @param width The width of the image being raytraced. * @param height The height of the image being raytraced. * @return true on success, false on error. The raytrace will abort if * false is returned. */ bool Raytracer::initialize(Scene* _scene, size_t _width, size_t _height, bool _extras) { this->scene = _scene; this->width = _width; this->height = _height; this->extras = _extras; size_t num_geometries = scene->num_geometries(); // invert scene transformation matrices for (size_t i = 0; i < num_geometries; i++) { make_inverse_transformation_matrix(&scene->get_geometries()[i]->inverse_transform_matrix, scene->get_geometries()[i]->position, scene->get_geometries()[i]->orientation, scene->get_geometries()[i]->scale); make_transformation_matrix(&scene->get_geometries()[i]->transform_matrix, scene->get_geometries()[i]->position, scene->get_geometries()[i]->orientation, scene->get_geometries()[i]->scale); make_normal_matrix(&scene->get_geometries()[i]->normal_matrix, scene->get_geometries()[i]->transform_matrix); // calculate bounding volume for models scene->get_geometries()[i]->make_bounding_volume(); cout << "Created bounding volume for geometry " << i << endl; } //cout << scene->camera.orientation << endl; return true; }
bool Geometry::initialize() { make_inverse_transformation_matrix(&invMat, position, orientation, scale); make_transformation_matrix(&mat, position, orientation, scale); make_normal_matrix(&normMat, mat); return true; }
/** * Initializes the raytracer for the given scene. Overrides any previous * initializations. May be invoked before a previous raytrace completes. * @param scene The scene to raytrace. * @param width The width of the image being raytraced. * @param height The height of the image being raytraced. * @return true on success, false on error. The raytrace will abort if * false is returned. */ bool Raytracer::initialize( Scene* scene, size_t width, size_t height ) { this->scene = scene; this->width = width; this->height = height; this->camera = scene->camera; // Compute basis vectors with information from camera Vector3 g = camera.get_direction(); Vector3 t = camera.get_up(); w = normalize(g); u = normalize(cross(t,w)); v = cross(w,u); u = -u; e = camera.get_position(); //retrieve addition data for viewing frame fov = camera.get_fov_radians(); nearClip = camera.get_near_clip(); current_row = 0; // compute bounds for the viewing frame top = tan(fov/2.0)*fabs(nearClip); right = ((1.0)*width/height)*top; left = -right; bottom = -top; Geometry* const* sceneObjects = scene->get_geometries(); for(unsigned int i=0; i<scene->num_geometries(); i++){ Geometry* shape = sceneObjects[i]; make_inverse_transformation_matrix(&shape->inv_trans, shape->position, shape->orientation, shape->scale); Matrix4 trans; make_transformation_matrix(&trans, shape->position, shape->orientation, shape->scale); make_normal_matrix(&shape->norm_matrix,trans); } return true; }
ray_t transform(ray_t curRay, const Geometry& geom) { Matrix4 transform; Vector4 eye; Vector4 direction; Vector4 end; eye = Vector4(curRay.eye.x, curRay.eye.y, curRay.eye.z, 1.0); end = Vector4(curRay.end.x, curRay.end.y, curRay.end.z, 1.0); make_inverse_transformation_matrix(&transform, geom.position, geom.orientation, geom.scale); eye = transform * eye; end = transform * end; curRay.eye = Vector3(eye.x, eye.y, eye.z); direction = end - eye; lastLength = length(direction); direction = normalize(direction); curRay.end = Vector3(end.x, end.y, end.z); curRay.direction = Vector3(direction.x, direction.y, direction.z); return curRay; }
static Color3 raycolor(const Scene* scene, RayInfo ray, int n) { Geometry* const* geometry = scene->get_geometries(); const PointLight* light = scene->get_lights(); IntersectionInfo intersection; intersection.t0 = EP; intersection.t1 = 1000000; int index; for(int i=0; i<scene->num_geometries();i++) { Matrix4 inversematrix; make_inverse_transformation_matrix(&inversematrix, geometry[i]->position, geometry[i]->orientation, geometry[i]->scale ); RayInfo rayinformation; rayinformation.origin = inversematrix.transform_point(ray.origin); rayinformation.direction = inversematrix.transform_vector(ray.direction); bool check = geometry[i]->check_geometry(rayinformation,intersection); if(check) { index = i; } } Color3 color = Color3::Black; if(intersection.t1 != 1000000) { Matrix4 transmatrix; make_transformation_matrix(&transmatrix, geometry[index]->position, geometry[index]->orientation, geometry[index]->scale ); intersection.worldposition = transmatrix.transform_point(intersection.localposition); Matrix3 normalmatrix; make_normal_matrix(&normalmatrix, transmatrix ); intersection.worldnormal = normalize(normalmatrix*intersection.localnormal); color = intersection.material.ambient*scene->ambient_light; for(int i=0; i<scene->num_lights();i++) { RayInfo shadowworldrayinfo; shadowworldrayinfo.origin = intersection.worldposition; shadowworldrayinfo.direction = normalize(light[i].position - intersection.worldposition); bool hit = false; IntersectionInfo shadowintersection; shadowintersection.t0 = EP; shadowintersection.t1 = length(light[i].position - intersection.worldposition); real_t d = dot(intersection.worldnormal,shadowworldrayinfo.direction); if(d > 0) { for(int j=0; j<scene->num_geometries();j++) { Matrix4 shadowinversematrix; make_inverse_transformation_matrix(&shadowinversematrix, geometry[j]->position, geometry[j]->orientation, geometry[j]->scale ); RayInfo shadowlocalrayinfo; shadowlocalrayinfo.origin = shadowinversematrix.transform_point(shadowworldrayinfo.origin); shadowlocalrayinfo.direction = shadowinversematrix.transform_vector(shadowworldrayinfo.direction); bool check = geometry[j]->check_geometry(shadowlocalrayinfo,shadowintersection); if(check == true) { hit = true; break; } } if(hit == false) { color = color + intersection.material.diffuse*light[i].color*d; } } } RayInfo reflectionworldrayinfo; reflectionworldrayinfo.origin = intersection.worldposition; Vector3 r = ray.direction - 2*dot(ray.direction,intersection.worldnormal)*intersection.worldnormal; reflectionworldrayinfo.direction = normalize(r); n++; if(intersection.material.refractive_index != 0) { real_t judge = dot(ray.direction,intersection.worldnormal); real_t c; RayInfo refractionworldrayinfo; refractionworldrayinfo.origin = intersection.worldposition; real_t refractiveratio = scene->refractive_index/intersection.material.refractive_index; if(judge<0) { refract(ray, intersection.worldnormal, refractiveratio,refractionworldrayinfo); c = -dot(ray.direction,intersection.worldnormal); } else { if(refract(ray, -intersection.worldnormal, 1/refractiveratio,refractionworldrayinfo)) { c = dot(refractionworldrayinfo.direction,intersection.worldnormal); } else { if(n<=MAXNUMBER) { return intersection.material.specular*raycolor(scene,reflectionworldrayinfo,n); } } } real_t R0 = (intersection.material.refractive_index-1)*(intersection.material.refractive_index-1)/(intersection.material.refractive_index+1)/(intersection.material.refractive_index+1); real_t R = R0 + (1-R0)*pow(1-c,5); if(n<=MAXNUMBER) { return intersection.material.specular*(R*raycolor(scene,reflectionworldrayinfo,n) + (1-R)*raycolor(scene,refractionworldrayinfo,n)); } } else { if(n<=MAXNUMBER) { color = color + intersection.material.specular*raycolor(scene,reflectionworldrayinfo,n); } } return color; } return scene->background_color; }
/** * Test for intersection with triangles and if there is, set the intersection data structure contents */ IntersectionData Triangle::intersection_test(Vector3 ray_position, Vector3 ray_direction) { if(!calculated_matrices) // if the matrix calculations haven't been calculated, do so now { make_transformation_matrix(&matrix, position, orientation, scale); make_inverse_transformation_matrix(&inverse_matrix, position, orientation, scale); make_normal_matrix(&normal_matrix, matrix); calculated_matrices = true; // now they are cached } // transform the ray into local coordinates Vector3 ray_position_local = inverse_matrix.transform_point( ray_position ); Vector3 ray_direction_local = inverse_matrix.transform_vector( ray_direction ); Vector3 v1 = vertices[0].position; Vector3 v2 = vertices[1].position; Vector3 v3 = vertices[2].position; // all of the following calculations are based off of the Shirley text real_t a = v1.x - v2.x; real_t b = v1.y - v2.y; real_t c = v1.z - v2.z; real_t d = v1.x - v3.x; real_t e = v1.y - v3.y; real_t f = v1.z - v3.z; real_t g = ray_direction_local.x; real_t h = ray_direction_local.y; real_t i = ray_direction_local.z; real_t j = v1.x - ray_position_local.x; real_t k = v1.y - ray_position_local.y; real_t l = v1.z - ray_position_local.z; real_t M = a*(e*i - h*f) + b*(g*f - d*i) + c*(d*h - e*g); real_t t = -1*(f*(a*k - j*b) + e*(j*c - a*l) + d*(b*l - k*c))/M; IntersectionData intersection; intersection.was_intersection = false; if(t<0) // there was an intersection, but it occurred before the beginning point of the ray return intersection; // was_intersection is currently false, indicating no intersection real_t gamma = (i*(a*k - j*b) + h*(j*c - a*l) + g*(b*l - k*c))/M; if(gamma < 0 or gamma > 1) return intersection; real_t beta = (j*(e*i - h*f) + k*(g*f - d*i) + l*(d*h - e*g))/M; if(beta < 0 or beta > 1 - gamma) return intersection; real_t alpha = 1 - beta - gamma; intersection.was_intersection = true; // retrieve all of the properties of the vertices so we can interpolate them Vector3 v1n = vertices[0].normal; Vector3 v2n = vertices[1].normal; Vector3 v3n = vertices[2].normal; Color3 v1d = vertices[0].material->diffuse; Color3 v2d = vertices[1].material->diffuse; Color3 v3d = vertices[2].material->diffuse; Color3 v1a = vertices[0].material->ambient; Color3 v2a = vertices[1].material->ambient; Color3 v3a = vertices[2].material->ambient; Color3 v1s = vertices[0].material->specular; Color3 v2s = vertices[1].material->specular; Color3 v3s = vertices[2].material->specular; real_t v1i = vertices[0].material->refractive_index; real_t v2i = vertices[1].material->refractive_index; real_t v3i = vertices[2].material->refractive_index; Vector2 v1t = vertices[0].tex_coord; Vector2 v2t = vertices[1].tex_coord; Vector2 v3t = vertices[2].tex_coord; int tex_width1, tex_height1, tex_width2, tex_height2, tex_width3, tex_height3; vertices[0].material->get_texture_size(&tex_width1, &tex_height1); vertices[1].material->get_texture_size(&tex_width2, &tex_height2); vertices[2].material->get_texture_size(&tex_width3, &tex_height3); intersection.time = t; intersection.diffuse = v1d*alpha + v2d*beta + v3d*gamma; intersection.ambient = v1a*alpha + v2a*beta + v3a*gamma; intersection.specular = v1s*alpha + v2s*beta + v3s*gamma; intersection.refractive_index = v1i*alpha + v2i*beta + v3i*gamma; Vector2 tex_coord = v1t*alpha + v2t*beta + v3t*gamma; Vector3 normal_local = v1n*alpha + v2n*beta + v3n*gamma; // Vector3 normal_local = cross(Vector3(v1 - v2), Vector3(v2 - v3)); // in case there is no texture, default the texture colors to white Color3 v1c = Color3(1.0,1.0,1.0); Color3 v2c = Color3(1.0,1.0,1.0); Color3 v3c = Color3(1.0,1.0,1.0); if(tex_width1 != 0 && tex_height1 != 0) v1c = vertices[0].material->get_texture_pixel((int)(tex_coord.x*tex_width1)%tex_width1, (int)(tex_coord.y*tex_height1)%tex_height1); if(tex_width2 != 0 && tex_height2 != 0) v2c = vertices[1].material->get_texture_pixel((int)(tex_coord.x*tex_width2)%tex_width2, (int)(tex_coord.y*tex_height2)%tex_height2); if(tex_width3 != 0 && tex_height3 != 0) v3c = vertices[2].material->get_texture_pixel((int)(tex_coord.x*tex_width3)%tex_width3, (int)(tex_coord.y*tex_height3)%tex_height3); intersection.texture_pixel = v1c*alpha + v2c*beta + v3c*gamma; intersection.normal = normal_matrix * normal_local; intersection.normal = normalize(intersection.normal); // normals have to be renormalized return intersection; }
bool Sphere::Hit(Ray ray, real_t t0, real_t t1, HitRecord &rec) { Vector3 localPos; Matrix4 inverseMatrix, transMatrix; Matrix3 temp, normalMatrix; Ray localRay; // calculate transform/ transform inverse/ normal matrix make_transformation_matrix(&transMatrix, position, orientation, scale); make_inverse_transformation_matrix(&inverseMatrix, position, orientation, scale); make_normal_matrix(&normalMatrix, transMatrix); // get the local ray localRay.origin = inverseMatrix.transform_point(ray.origin); localRay.dir = inverseMatrix.transform_vector(ray.dir); // do the intersection calculation real_t result, x1, x2, oriDotOri , dirDotDir, oriDotDir; oriDotDir = dot(localRay.dir , localRay.origin); dirDotDir = dot(localRay.dir , localRay.dir); oriDotOri = dot(localRay.origin , localRay.origin); result = oriDotDir*oriDotDir-dirDotDir*(oriDotOri-radius*radius); // no intersection if(result < 0) return false; else { x1=(-oriDotDir - sqrt(result)) / dirDotDir; x2=(-oriDotDir + sqrt(result)) / dirDotDir; // x1 is the place is the intersection if(x1>t0 && x1<t1) { localPos = localRay.origin + x1*localRay.dir; // set material SetMaterialColors(rec.ambientColor, rec.diffuseColor,rec.specularColor); rec.refractiveIdx = material->refractive_index; // set normal rec.normal=(localPos)/radius; rec.normal=normalize(normalMatrix*rec.normal); // set texture color rec.textureColor = GetTexture(localPos); // set position rec.position = transMatrix.transform_point(localPos); // set t rec.t = x1; return true; } else { // x2 is the place is the intersection if(x2>t0 && x2<t1) { localPos = localRay.origin + x2*localRay.dir; //set material SetMaterialColors(rec.ambientColor, rec.diffuseColor,rec.specularColor); rec.refractiveIdx = material->refractive_index; // set normal rec.normal=(localPos)/radius; rec.normal=normalize(normalMatrix*rec.normal); // set texture rec.textureColor = GetTexture(localPos); // set position rec.position = transMatrix.transform_point(localPos); // set t rec.t = x2; return true; } return false; } } }