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, 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; }
int main( int argc, char* argv[] ) { Options opt; Matrix3 mat; Matrix4 trn; make_transformation_matrix( &trn, Vector3::Zero, Quaternion::Identity, Vector3( 2, 2, 2 ) ); make_normal_matrix( &mat, trn ); if ( !parse_args( &opt, argc, argv ) ) { return 1; } RaytracerApplication app( opt ); // load the given scene if ( !load_scene( &app.scene, opt.input_filename ) ) { std::cout << "Error loading scene " << opt.input_filename << ". Aborting.\n"; return 1; } if ( opt.open_window ) { real_t fps = 30.0; const char* title = "15462 Project 2 - Raytracer"; // start a new application return Application::start_application( &app, opt.width, opt.height, fps, title ); } else { app.initialize(); app.toggle_raytracing( opt.width, opt.height ); if ( !app.raytracing ) { return 1; } assert( app.buffer ); // raytrace until done app.raytracer.raytrace( app.buffer, 0 ); // output result app.output_image(); return 0; } }
/** * 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; }
bool Triangle::intersect_frustum(const Frustum& frustum) const { Frustum instance_frustum; int right_side = 0; // check each vertex against all instanced planes for (int i = 0; i < 6; i++) { instance_frustum.planes[i].point = inverse_transform_matrix.transform_point(frustum.planes[i].point); Matrix3 N; make_normal_matrix(&N, inverse_transform_matrix); instance_frustum.planes[i].normal = normalize(N * frustum.planes[i].normal); // check if all three of triangle's points are on the wrong side for (int j = 0; j < 3; j++) { Vector3 point = vertices[j].position; Plane plane = instance_frustum.planes[i]; // if any point is inside plane, continue if (dot(point - plane.point, plane.normal) < 0.0) { right_side++; break; } } } if (right_side == 6) { return true; } return false; }
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; }
Color3 calcColor(real_t time, ray_t ray, int bestGeom, const Scene* scene, int depth) { Geometry* const* geometries = scene->get_geometries(); Geometry& geom = *geometries[bestGeom]; Vector3 ptIntersection; Vector3 normal; Vector4 temp; Matrix4 transform; Color3 color = geom.getAmbientColor() * scene->ambient_light; Color3 k = geom.getDiffuseColor(); Matrix3 normalMatrix; make_transformation_matrix(&transform, geom.position, geom.orientation, geom.scale); make_normal_matrix(&normalMatrix,transform); normal = geom.getNormal(); normal = normalMatrix * normal; normal = normalize(normal); Vector3 testIntersect = geom.getIntersectionPt(); Vector4 test = Vector4(testIntersect.x, testIntersect.y, testIntersect.z, 1.0); test = transform * test; ptIntersection = Vector3(test.x, test.y, test.z); //ptIntersection = ray.eye + (time * ray.direction); const PointLight* lights = scene->get_lights(); for( size_t i = 0; i < scene->num_lights(); i++) { PointLight light = lights[i]; Vector3 lPos = light.position; Vector3 vLight = lPos - ptIntersection; real_t d = length(vLight); //normalized vLight at one point... // matters? ray_t shadowRay; shadowRay.eye = ptIntersection; shadowRay.direction = normalize(vLight); shadowRay.end = lPos; if(hitLight(shadowRay, light, scene, bestGeom)) { real_t a = dot(normal,vLight); real_t b = 0; real_t max = (a > b) ? a : b; real_t atten = light.attenuation.constant + (light.attenuation.linear * d) + (light.attenuation.constant * d * d); Color3 c = Color3(light.color.r / atten, light.color.g / atten, light.color.b / atten); //Color3 c = light.color; color += c * k * max; } } color = color * geom.getTextureColor(); if(depth > 0) { real_t dDotn = dot(ray.direction, normal); ray_t reflectedRay; reflectedRay.eye = ptIntersection; reflectedRay.direction = ray.direction - (2 * dDotn * normal); reflectedRay.end = ptIntersection + reflectedRay.direction; color += geom.getTextureColor() * geom.getSpecularColor() * traceSpecularColor(reflectedRay, scene, depth - 1, bestGeom); } return color; }
void Renderable::update_normal_matrix(const glm::mat4 &view_matrix) { normal_matrix_property = make_normal_matrix(view_matrix); }
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; } } }