Vec rayTrace(Ray ray) { Vec retorno; retorno.x = 0; retorno.y = 0; retorno.z = 0; int indiceObject = objetoMaisProximo(ray); //objeto nao encontrado if(indiceObject < 0) { //para resolver o caso em que os raios que saem do olho (eye) não encontram objetos if(ray.depth == 0) { retorno.x = arq->background[0]; retorno.y = arq->background[1]; retorno.z = arq->background[2]; } //para resolver o caso em que na recursão não se encontra o ponto transmitido ou refletido else { retorno.x = 0.f; retorno.y = 0.f; retorno.z = 0.f; } } //objeto encontrado else { //cálculo das cores local, refletida e transmitida Object object = *arq->objects.at(indiceObject); Vec corLocal = shade(object, ray); //setando para preto as cores transmitidas e refletidas Vec corRefletida; corRefletida.x = 0; corRefletida.y = 0; corRefletida.z = 0; Vec corTransmitida; corTransmitida.x = 0; corTransmitida.y = 0; corTransmitida.z = 0; //recursao if(ray.depth < arq->profundidade) { //so executa a recursao caso pretender usar as cores obtidas if(object.KS > 0) corRefletida = rayTrace(raioRefletido(object, ray)); if(object.KT > 0) corTransmitida = rayTrace(raioTransmitido(object, ray)); } //mesclando as cores retorno = mesclarCores(object, corLocal, corRefletida, corTransmitida); } return retorno; }
void GlutCLWindow::glutDisplayCallback() { /* * Only render the scene to the PBO if the PBO has not been populated yet. * * TODO: also need to check for changes in the scene content and the camera position, however * with animated or interactive scenes we can just always render. This should be fast enough * at some point so that won't be a problem. */ if (reallocPBO) { allocatePBO(); progression = 0; rayTrace(); reallocPBO = false; if (maxProgression > 0) glutPostRedisplay(); } else if (progression < maxProgression) { /* * Progressive refinement, take more samples and accumulate the values into the PBO. */ progression++; rayTrace(); glutPostRedisplay(); } /* * Draw PBO to screen as a full-window image. */ glClear(GL_COLOR_BUFFER_BIT); glDisable(GL_DEPTH_TEST); glRasterPos2i(0, 0); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo); glDrawPixels(width, height, GL_RGBA, GL_FLOAT, 0); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); if (reportFPS) { if (++frame_counter == fpsAvgFrames) { timespec time; clock_gettime(CLOCK_REALTIME, &time); fps = (double) fpsAvgFrames / (((time.tv_nsec/1000000000.0 + time.tv_sec) - (last_render_end.tv_nsec/1000000000.0 + last_render_end.tv_sec))); frame_counter = 0; last_render_end = time; } std::ostringstream fpsStr; fpsStr << "FPS: "; fpsStr << fps; drawString(0.0f + 20.0f / width, 1.0f - 20.0f / height, fpsStr.str()); } /* * Call glFinish() and * Flip the back/front buffer */ glutSwapBuffers(); }
tf::Vector3 RayTracePluginUtils::calcNormal(tf::Vector3 start, tf::Vector3 end){ tf::Vector3 direction = end-start; double distance = 0.0005; std::vector<tf::Vector3> orthog = getOrthogonalBasis(direction); tf::Point p1 = start + direction*rayTrace(start, end); start = start+orthog[0]*distance; end = end+orthog[0]*distance; tf::Point p2 = start + direction*rayTrace(start,end); start = start+orthog[1]*distance; end = end+orthog[1]*distance; tf::Point p3 = start + direction*rayTrace(start,end); return (p3-p1).cross(p2-p1).normalize(); }
void GLBox::initializeGL() { // this method is called exactly once on program start clearImage(); glViewport(0, 0, m_winWidth, m_winHeight); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-m_winWidth/2, m_winWidth/2, -m_winHeight/2, m_winHeight/2, 0, 1); glClear (GL_COLOR_BUFFER_BIT); std::cout << "Started..." << std::endl; // import .bmp Image testImage("C:/GIT/CGProject/input/tiles24.bmp"); // import .obj loadOBJ("C:/GIT/CGProject/input/teapot.obj", faces, &testImage); qDebug() << faces.size() << " Faces loaded!"; for (unsigned int i = 0; (i < faces.size()); i++){ Tree.Add(&faces[i]); } // Tree.printTree(); printf("Sizes: AABB %d; Node %d; Facecount: %u, Nodecount: %u, AABBcount: %u\n", sizeof(AABB), sizeof(Node), (unsigned int)faces.size(), Tree.nodecount, AABB::aabbcount); rayTrace(); }
void calculate_image(void) { color c; Ray ray; Uint32 *pixmem32; Uint32 sdl_color; Uint8 *p; for(int i=ImageH-1; i>=0; --i) { for(int j=ImageW-1;j>=0; --j) { ray = convertToRay(i, j); c = rayTrace(ray, 0); c.scale(); /* Make p point to the place we want to draw the pixel */ p = (Uint8 *)screen->pixels + ((ImageW - 1) - j) * screen->pitch + i * screen->format->BytesPerPixel; /* Draw the pixel! */ *p=(Uint8)(0xFF * c.b); p++; *p=(Uint8)(0xFF * c.g); p++; *p=(Uint8)(0xFF * c.r); } } }
/** * Service for Ray tracing in the loaded world. */ bool RayTracePluginUtils::rayTrace(gazebo_ray_trace::RayTrace::Request &req, gazebo_ray_trace::RayTrace::Response &resp) { math::Vector3 start, end; start.x = req.start.x; start.y = req.start.y; start.z = req.start.z; end.x = req.end.x; end.y = req.end.y; end.z = req.end.z; gazebo::physics::RayShapePtr ray_; gazebo::physics::PhysicsEnginePtr engine = world_->GetPhysicsEngine(); engine->InitForThread(); ray_ = boost::dynamic_pointer_cast<gazebo::physics::RayShape> (engine->CreateShape("ray", gazebo::physics::CollisionPtr())); // resp.dist = rayTrace(start, end, ray_); resp.dist = rayTrace(start, end, ray_); // ROS_INFO("Traced ray and responded with distance: %f", resp.dist); return true; }
/** * Ray Traces all particles */ std::vector<double> RayTracePluginUtils::rayTraceAllParticles(tf::Point start, tf::Point end) { tf::Transform trans; // ROS_INFO("Setting up ray"); gazebo::physics::RayShapePtr ray_; gazebo::physics::PhysicsEnginePtr engine = world_->GetPhysicsEngine(); engine->InitForThread(); ray_ = boost::dynamic_pointer_cast<gazebo::physics::RayShape> (engine->CreateShape("ray", gazebo::physics::CollisionPtr())); std::vector<double> dist; dist.resize(particles_.poses.size()); for(int i=0; i<particles_.poses.size(); i++){ tf::Vector3 v = tf::Vector3(particles_.poses[i].position.x, particles_.poses[i].position.y, particles_.poses[i].position.z); trans.setOrigin(v); tf::Quaternion q; tf::quaternionMsgToTF(particles_.poses[i].orientation, q); trans.setRotation(q); trans = trans.inverse(); dist[i] = rayTrace(vectorTFToGazebo(trans*start), vectorTFToGazebo(trans*end), ray_); } // ROS_INFO("Returning Ray"); return dist; }
/* calcula uma linha da imagem a cada camada de idle */ int idle_cb(void) { int x; /* Faz uma linha de pixels por vez */ if (yc<height) { IupGLMakeCurrent(canvas); glBegin(GL_POINTS); for( x = 0; x < width; ++x ) { Color pixel; Vector ray; ray = camGetRay( camera, x, yc ); pixel = rayTrace( scene, eye, ray, 0 ); imageSetPixel( image, x, yc, pixel ); glColor3f((float)pixel.red,(float)pixel.green,(float)pixel.blue); glVertex2i(x,yc); } glEnd(); glFlush(); IupGLSwapBuffers(canvas); /* change the back buffer with the front buffer */ yc++; } else { IupSetFunction (IUP_IDLE_ACTION, (Icallback) NULL); /* a imagem ja' esta' completa */ finish_time = clock(); duration = (double)(finish_time - start_time)/CLOCKS_PER_SEC; IupSetfAttribute(label, "TITLE", "tempo=%.3lf s", duration); } return IUP_DEFAULT; }
double RayTracePluginUtils::rayTrace(tf::Vector3 start, tf::Vector3 end) { gazebo::physics::RayShapePtr ray_; gazebo::physics::PhysicsEnginePtr engine = world_->GetPhysicsEngine(); engine->InitForThread(); ray_ = boost::dynamic_pointer_cast<gazebo::physics::RayShape> (engine->CreateShape("ray", gazebo::physics::CollisionPtr())); return rayTrace(vectorTFToGazebo(start), vectorTFToGazebo(end), ray_); }
void Renderer::renderScene(SceneDesc& desc) { if (desc.threadsPow == 0) { rayTrace(desc.film, desc.shapeUnion, desc.camera, desc.lights); rayTraceReflection(desc.film, &desc.shapeUnion, desc.camera, std::ref(desc.lights), 4); } else { rayTraceConcurrence(desc); } //parserObj(config["obj"]); }
/** rayTrace **/ intensity_t rayTrace(scene_t *scene, point_t base, vector_t unitDir, double total_dist, entity_t *self) { intensity_t intensity = ((intensity_t){0, 0, 0}); entity_t * closestEnt; hitinfo_t * hit = malloc(sizeof(hitinfo_t)); closestEnt = closest(scene, base, unitDir, self, hit); if (closestEnt == NULL) { free(hit); return (intensity); } total_dist += hit->distance; window_t * window = ((window_t *)(scene->window->entDerived)); sobj_t * sobj = ((sobj_t *)(closestEnt->entDerived)); intensity = ((tuple_t){window->ambient.x * sobj->color.r, window->ambient.y * sobj->color.g, window->ambient.z * sobj->color.b}); intensity_t light = lighting(scene, closestEnt, hit); intensity.x += light.x; intensity.y += light.y; intensity.z += light.z; intensity.x /= 255; intensity.y /= 255; intensity.z /= 255; intensity.x /= total_dist; intensity.y /= total_dist; intensity.z /= total_dist; sobj_t * closestSobj = closestEnt->entDerived; if (length(((tuple_t)(closestSobj->reflective))) != 0) { vector_t U = scale(unitDir, -1); vector_t N = hit->normal; vector_t V = unitize(add(scale(N, (2 * dot(U, N))), unitDir)); intensity_t reflection; reflection = rayTrace(scene, hit->hitpoint, V, total_dist, closestEnt); multiply(reflection, closestSobj->reflective); intensity = add(intensity, reflection); } free(hit); return (intensity); } /* End rayTrace */
void Camera::RenderPath(Scene &scn, int n) { RayTrace rayTrace(scn); for (int y = 0; y < _img.YRes; y++) { for (int x = 0; x < _img.XRes; x++) { // compute the primary ray Vector3 cy; cy.Cross(_worldMatrix.c, _worldMatrix.b); Vector3 cx = cy / pow(cy.Magnitude(), 2); cy.Cross(cx, _worldMatrix.c); float hfov = 2.f * atanf(_aspect * tanf(_verticalFOV / 2.f)); float cw = 2.f * tanf(hfov/2.f); float ch = cw / _aspect; Ray ray; ray.Origin = _worldMatrix.d; ray.Direction = _worldMatrix.c + ((float)(x + 0.5f) / (float)_img.XRes - 0.5f) * cw * cx + ((float)(y + 0.5f)/(float)_img.YRes - 0.5f) * ch * cy; ray.type = Ray::PRIMARY; // shoot the primary ray Intersection hit; if (x > 124 && x <= 140 && y == _img.YRes - 495 ) { // Color white = Color::WHITE; // std::cout << "debug pixel" << std::endl; // _img.SetPixel(x, y, white.ToInt()); // continue; } rayTrace.TraceRay(ray, hit); if (n != -1) { Color c; c.FromInt(_img.GetPixel(x, y)); Color avg = Color::BLACK; avg.AddScaled(c, n - 1); avg.Add(hit.Shade); avg.Scale(1.0f / n); _img.SetPixel(x, y, avg.ToInt()); } else _img.SetPixel(x, y, hit.Shade.ToInt()); } } }
RayTraceIterRange rayTrace (const nm::MapMetaData& info, const gm::Point& p1, const gm::Point& p2, bool project_onto_grid, bool project_source_onto_grid, float max_range) { gm::Point np2 = p2; if (max_range > 0) { double distance = euclideanDistance(p1,p2); if (distance > max_range) { np2.x = ((p2.x - p1.x) * max_range/distance) + p1.x; np2.y = ((p2.y - p1.y) * max_range/distance) + p1.y; } } Cell c1 = pointCell(info, p1); Cell c2 = pointCell(info, np2); ROS_DEBUG_STREAM_NAMED ("ray_trace", "Ray tracing between " << c1.x << ", " << c1.y << " and " << c2.x << ", " << c2.y); const RayTraceIterator done(c1, c1, true); const RayTraceIterRange empty_range(done, done); if (!withinBounds(info, c1)) { if (project_source_onto_grid) { const optional<Cell> c = rayTraceOntoGrid(info, c2, c1); if (c) c1 = *c; else return empty_range; } else throw PointOutOfBoundsException(p1); } if (!withinBounds(info, np2)) { if (project_onto_grid) { const optional<Cell> c = rayTraceOntoGrid(info, c1, c2); if (c) c2 = *c; else return empty_range; } else { throw PointOutOfBoundsException(np2); } } ROS_DEBUG_STREAM_NAMED ("ray_trace", "Projected ray trace endpoints to " << c1.x << ", " << c1.y << " and " << c2.x << ", " << c2.y); return rayTrace(c1, c2); }
void renderPicture() { for(int x = 0; x<ImageW; x++) { for(int y =0; y<ImageH; y++) { std::cout<<x<<","<<y<<std::endl; position rp = {199,199,-200}; // reference point position pixel = {x,y,0}; ray r = createRay(rp,pixel); color c = rayTrace(r, 0); setFramebuffer(x,y,c.r,c.g,c.b); } } }
void App::trace(int x, int y) { Color3 sum = Color3::black(); if (m_currentRays == 1) { sum = rayTrace(m_debugCamera->worldRay(x + 0.5f, y + 0.5f, m_currentImage->rect2DBounds()), m_world); } // Don't calculate blur if either aperture or focal length are 0 else if(m_aperture == 0 || m_focalLength == 0) { for (int i = 0; i < m_currentRays; ++i) { sum += rayTrace(m_debugCamera->worldRay(x + rnd.uniform(), y + rnd.uniform(), m_currentImage->rect2DBounds()), m_world); } } else { for (int i = 0; i < m_currentRays; ++i) { // Save the original ray Ray oldRay = m_debugCamera->worldRay(x, y, m_currentImage->rect2DBounds()); // Calculate the origin of the new ray by multiplying the x and y values by a fraction of the aperture (keep z the same) Point3 newOrigin = Point3(oldRay.origin().x + (rnd.uniform() * m_aperture/20.0f), oldRay.origin().y + (rnd.uniform() * m_aperture/20.0f), oldRay.origin().z); // Determine the direction between the end point of the original ray and the new origin Vector3 newDirection = ((oldRay.origin() + oldRay.direction()* m_focalLength) - newOrigin); // Normalize the direction of the new ray newDirection /= newDirection.magnitude(); // Create a new ray from origin and direction, then add to sum Ray newRay = Ray(newOrigin, newDirection); sum += rayTrace(newRay, m_world); } } m_currentImage->set(x, y, sum / (float)m_currentRays); }
/** makePixel **/ pixel_t makePixel(scene_t *scene, int colndx, int rowndx) { intensity_t intensity; vector_t dir; window_t * windowPtr; dir = genRay(scene, colndx, rowndx); windowPtr = scene->window->entDerived; intensity = rayTrace(scene, windowPtr->viewPoint, dir, 0.0, NULL); if (intensity.x > 1.0) intensity.x = 1.0; if (intensity.y > 1.0) intensity.y = 1.0; if (intensity.z > 1.0) intensity.z = 1.0; return((pixel_t){(255 * intensity.x), (255 * intensity.y), (255 * intensity.z)}); } /* End makePixel */
void pintarTela() { for(int i = 0; i < arq->size[0];i++){ for(int j = 0;j < arq->size[1];j++){ //criação do raio que sai do olho e passa pelo ponto relativo ao pixel atual Ray ray; ray.depth = 0; ray.org = arq->eye; ray.dir = vsub(pixelParaPonto2d(i, j), arq->eye); if(i >= 90 && i <= 110 && j >= 80 && j <= 120) { int teste = 0; } //ray trace no pixel atual retornando sua cor para ser pintada na tela tela[(i*arq->size[1]) + j] = rayTrace(ray); } } }
sm::LaserScan::Ptr simulateRangeScan (const nm::OccupancyGrid& grid, const gm::Pose& sensor_pose, const sm::LaserScan& scanner_info, const bool unknown_obstacles) { sm::LaserScan::Ptr result(new sm::LaserScan(scanner_info)); const double angle_range = scanner_info.angle_max - scanner_info.angle_min; const unsigned n = (unsigned) round(1+angle_range/scanner_info.angle_increment); const gm::Point& p0 = sensor_pose.position; const Cell c0 = pointCell(grid.info, p0); const double theta0 = tf::getYaw(sensor_pose.orientation); result->ranges.resize(n); for (unsigned i=0; i<n; i++) { const double theta = scanner_info.angle_min+i*scanner_info.angle_increment; const gm::Point scan_max = rayEndPoint(p0, theta0 + theta, scanner_info.range_max+1); result->ranges[i] = scanner_info.range_max+1; // Default if loop terminates BOOST_FOREACH (const Cell& c, rayTrace(grid.info, p0, scan_max, true)) { const gm::Point p = cellCenter(grid.info, c); const double d = sqrt(pow(p.x-p0.x, 2) + pow(p.y-p0.y, 2)); char data = grid.data[cellIndex(grid.info, c)]; if (d > scanner_info.range_max) break; else if (data == OCCUPIED && !(c==c0)) { result->ranges[i] = d; break; } else if (data == UNKNOWN && !(c==c0)) { result->ranges[i] = unknown_obstacles ? d : scanner_info.range_max+1; break; } } } return result; }
color rayTrace(Ray &ray, int times) { float t = (float)(~(1<<31)); int iObjectIndex = 0; color c, cRefl; vect point; if(times < MAX_REFLECTION_TIMES_LIMIT) { if(rayIntersect(ray, iObjectIndex, t)) { point = ray.d * t + ray.p0; Ray newRay= Ray(point, g_papoObjects[iObjectIndex]->getReflection((-1.0)*ray.d,point)); cRefl = rayTrace(newRay, times + 1); c = getLighting(ray, point,iObjectIndex) *(1 - g_papoObjects[iObjectIndex]->reflPerc) + g_papoObjects[iObjectIndex]->reflPerc * cRefl; } } return c; }
/* calcula uma linha da imagem a cada camada de idle */ int idle_cb(void) { int x; double ray[VECTOR]; float pixel[COLOR]; /* Faz uma linha de pixels por vez */ if (yc < height) { IupGLMakeCurrent(canvas); glBegin(GL_POINTS); { for (x = 0; x < width; ++x) { camGetRay(camera, x, yc, ray); rayTrace(scene, eye, ray, 0, pixel); imageSetPixel(image, x, yc, pixel); glColor3f((float) pixel[RED], (float) pixel[GREEN], (float) pixel[BLUE]); glVertex2i(x, yc); } } glEnd(); glFlush(); IupGLSwapBuffers(canvas); yc++; } else { IupSetFunction (IUP_IDLE_ACTION, (Icallback) NULL); /* a imagem ja' esta' completa */ finish_time = clock(); duration = (double)(finish_time - start_time)/CLOCKS_PER_SEC; IupSetfAttribute(label, "TITLE", "tempo=%.3lf s", duration); glFlush(); } return IUP_DEFAULT; }
void MyScene::render(int type, int width, int height, unsigned char* pixels) { if (!isLoaded) { return; } // Add your rendering code here. // Keep track of your progress as a value between 0 and 1 // so the progress bar can update as the rendering progresses pixelArray = pixels; screenWidth = width; screenHeight = height; //clear the screen for (int row = 0; row < height; ++row){ for (int col = 0; col < width; ++col){ int i = pxIdx(col, row); pixelArray[i] = 0; pixelArray[i + 1] = 0; pixelArray[i + 2] = 0; } } keepWorking = true; renderProgress = 0; for (int row = 0; keepWorking && (row < height); ++row){ for (int col = 0; col < width; ++col){ Point3 worldCoord = Point3((col + 0.5)*(2 / (double)width) - 1, 1 - (row + 0.5)*(2 / (double)height), -1); worldCoord = camera.getCameraToWorld()*worldCoord; Point3 eye = camera.getEye(); Vector3 ray = worldCoord - eye; ray.normalize(); rayTrace(eye, ray); } renderProgress = (row + 1) / (double)height; Fl::check(); } }
RayTraceIterRange rayTrace (const nm::MapMetaData& info, const gm::Point& p1, const gm::Point& p2, bool project_onto_grid, bool project_source_onto_grid) { Cell c1 = pointCell(info, p1); Cell c2 = pointCell(info, p2); ROS_DEBUG_STREAM_NAMED ("ray_trace", "Ray tracing between " << c1.x << ", " << c1.y << " and " << c2.x << ", " << c2.y); const RayTraceIterator done(c1, c1, true); const RayTraceIterRange empty_range(done, done); if (!withinBounds(info, c1)) { if (project_source_onto_grid) { const optional<Cell> c = rayTraceOntoGrid(info, c2, c1); if (c) c1 = *c; else return empty_range; } else throw PointOutOfBoundsException(p1); } if (!withinBounds(info, p2)) { if (project_onto_grid) { const optional<Cell> c = rayTraceOntoGrid(info, c1, c2); if (c) c2 = *c; else return empty_range; } else { throw PointOutOfBoundsException(p2); } } ROS_DEBUG_STREAM_NAMED ("ray_trace", "Projected ray trace endpoints to " << c1.x << ", " << c1.y << " and " << c2.x << ", " << c2.y); return rayTrace(c1, c2); }
Vec3f scene::rayTrace(Vec3f eye, Vec3f dir, int recurseDepth) { //start with black, add color as we go Vec3f answer(0,0,0); //test for intersection against all our objects float dist = myObjGroup->testIntersections(eye, dir); //if we saw nothing, return the background color of our scene if (dist==9999999) return bgColor; Vec3f textureColor; //get the material index and normal vector(at the point we saw) of the object we saw int matIndex = myObjGroup->getClosest()->getMatIndex(); Vec3f normal = myObjGroup->getClosest()->getNormal(eye, dir * dist); //determine texture color if (myMaterials.at(matIndex).texture==NULL) //this is multiplicative, rather than additive //so if there is no texture, just use ones textureColor.Set(1,1,1); else { //if there is a texture image, ask the object for the image coordinates (between 0 and 1) Vec3f coords = myObjGroup->getClosest()->getTextureCoords(eye, dir * dist); //get the color from that image location textureColor.Set( PIC_PIXEL(myMaterials.at(matIndex).texture,(int)(myMaterials.at(matIndex).texture->nx*coords.x()),(int)(myMaterials.at(matIndex).texture->ny*coords.y()),0), PIC_PIXEL(myMaterials.at(matIndex).texture,(int)(myMaterials.at(matIndex).texture->nx*coords.x()),(int)(myMaterials.at(matIndex).texture->ny*coords.y()),1), PIC_PIXEL(myMaterials.at(matIndex).texture,(int)(myMaterials.at(matIndex).texture->nx*coords.x()),(int)(myMaterials.at(matIndex).texture->ny*coords.y()),2)); textureColor = textureColor*(1/255.0); } // add ambient light/color to our answer answer += multiplyColorVectors(ambLight, myMaterials.at(matIndex).diffuseCol); // set point slightly above the actual surface, prevents // issues with that point intersecting itself Vec3f point = eye + (dir * dist) + (normal * .0001); Vec3f real_point = eye + (dir * dist); // get the diffuse color of our material Vec3f diffuseColor = myMaterials.at(matIndex).diffuseCol; // iterate through lights for (int iter = 0; iter < myLights.size(); iter++) { Vec3f lightPos = myLights.at(iter).position; Vec3f direction= lightPos - point; direction.Normalize(); float distance = myObjGroup->testIntersections(point, direction); // if nothing between point and light if (distance == 9999999) { Vec3f color = multiplyColorVectors(diffuseColor, myLights.at(iter).color); float nl = abs(direction.Dot3(normal)); answer += (color * nl); // now do the specular // we need vector that goes from point to eye Vec3f backDir = dir * -1.0f; Vec3f h = (backDir + direction); h.Normalize(); Vec3f Cp = myMaterials.at(matIndex).specularCol; float p = myMaterials.at(matIndex).shininess; float nh = abs(normal.Dot3(h)); nh = pow(nh, p); answer += multiplyColorVectors(myLights.at(iter).color, Cp) * nh; } } //if the light can see the surface point, //add its diffuse color to a total diffuse for the point (using our illumination model) //use testIntersection to help decide this //add the diffuse light times the accumulated diffuse light to our answer if (recurseDepth < 3) { Vec3f e = dir * -1.0f; e.Normalize(); Vec3f r = dir + normal * 2.0f * e.Dot3(normal); r.Normalize(); Vec3f bounced = rayTrace(point, r, recurseDepth + 1); answer += (multiplyColorVectors(bounced, myMaterials.at(matIndex).reflectiveCol)); // refraction Vec3f transparentColor = myMaterials.at(matIndex).transparentCol; float transpar = transparentColor.Dot3(transparentColor); if (transpar > 0.0f) { float exitAngle, entryAngle; if (dir.Dot3(normal) < 0.0f) { entryAngle = acos(dir.Dot3(normal * -1.0f)); exitAngle = entryAngle * myMaterials.at(matIndex).refractionIndex; } else { entryAngle = acos(dir.Dot3(normal)); exitAngle = entryAngle / myMaterials.at(matIndex).refractionIndex; } Vec3f b = (dir + (normal * cos(entryAngle))) * (1.0f /sin(entryAngle)); b.Normalize(); Vec3f refracted = (b * sin(exitAngle)) - (normal * cos(exitAngle)); refracted.Normalize(); answer += multiplyColorVectors(rayTrace(real_point, refracted, recurseDepth + 1), myMaterials.at(matIndex).transparentCol); } } //put a limit on the depth of recursion //if (recurseDepth<3) //{ //reflect our view across the normal //recusively raytrace from the surface point along the reflected view //add the color seen times the reflective color //if going into material (dot prod of dir and normal is negative), bend toward normal //find entry angle using inverse cos of dot product of dir and -normal //multiply entry angle by index of refraction to get exit angle //else, bend away //find entry angle using inverse cos of dot product of dir and normal //divide entry angle by index of refraction to get exit angle //recursively raytrace from the other side of the object along the new direction //add the color seen times the transparent color //} //multiply whatever color we have found by the texture color answer=multiplyColorVectors(answer,textureColor); return answer; }
RGBAPixel GeometricObject::rayTrace(AreaLight& lightSrc, Point3D& pt, Ray& viewRay, vector<GeometricObject*>& shapes){ double r = 0.0; double g = 0.0; double b = 0.0; int dim = 6; //6 for testing purposes. 25 for production purposes. int total_rays = dim*dim; vector<Point3D> lightPts = lightSrc.shape.generatePoints(total_rays); for(int i = 0; i < dim; i++){ for(int j = 0; j < dim; j++){ Point3D samplePt(lightPts[i*dim+j]); Vector3D dir(pt, samplePt); //direction from shape hit point to light source dir.normalize(); Point3D rayPt(pt+(dir*0.01)); Ray backtraceRay(rayPt,dir, "shadow"); //ray from hit point on shape to light source double tHitLight = samplePt.distance(rayPt); bool hitShape = false; Point3D trash(0,0,0); for(int k = 0; k < shapes.size(); k++){ if(shapes[k] == this) continue; double tHitAnotherShape = shapes[k]->hit(backtraceRay,trash); if(tHitAnotherShape > 0 && tHitAnotherShape < tHitLight){ hitShape = true; break; } } if(!hitShape){ PointLight ptLt(samplePt, 1, material.kd, material.ks); RGBAPixel tempPixel = rayTrace(ptLt, pt, viewRay, shapes); r += tempPixel.red; g += tempPixel.green; b += tempPixel.blue; } r = r*material.directScale; g = g*material.directScale; b = b*material.directScale; //Mirror Reflection if(viewRay.recurseLevel < 3){ Vector3D n(this->getNormal(pt)); Vector3D recViewDir(viewRay.d - (2*viewRay.d*n)*n); recViewDir.normalize(); Ray recViewRay(pt,recViewDir, "view"); recViewRay.recurseLevel = viewRay.recurseLevel+1; Point3D recPt; RGBAPixel recColor; GeometricObject* nextShape = NULL; double minTime = 100000.0; double tHitAnotherShape = 0.0; for(int k = 0; k < shapes.size(); k++){ if(shapes[k] == this) continue; tHitAnotherShape = shapes[k]->hit(recViewRay,recPt); if(tHitAnotherShape > 0.0 && tHitAnotherShape < minTime){ nextShape = shapes[k]; minTime = tHitAnotherShape; } } if(nextShape != NULL){ recColor = nextShape->rayTrace(lightSrc, recPt, recViewRay, shapes); r += (recColor.red); g += (recColor.green); b += (recColor.blue); } } } } r = r / total_rays * 1.5; g = g / total_rays * 1.5; b = b / total_rays * 1.5; r =std::min((int)r,255); g =std::min((int)g,255); b =std::min((int)b,255); RGBAPixel pixel(r,g,b); return pixel; }
int main(int argc, char *argv[]) { // Main function for the raytracer. Parses input parameters, // sets up the initial blank image, and calls the functions // that set up the scene and do the raytracing. struct image *im; // Will hold the raytraced image struct view *cam; // Camera and view for this scene int sx; // Size of the raytraced image int antialiasing; // Flag to determine whether antialiaing is enabled or disabled char output_name[1024]; // Name of the output file for the raytraced .ppm image struct point3D e; // Camera view parameters 'e', 'g', and 'up' struct point3D g; struct point3D up; double du, dv; // Increase along u and v directions for pixel coordinates struct point3D pc,d; // Point structures to keep the coordinates of a pixel and // the direction or a ray struct ray3D *ray; // Structure to keep the ray from e to a pixel // struct colourRGB col; // Return colour for raytraced pixels struct colourRGB background; // Background colour int i,j; // Counters for pixel coordinates unsigned char *rgbIm; if (argc<5) { fprintf(stderr,"RayTracer: Can not parse input parameters\n"); fprintf(stderr,"USAGE: RayTracer size rec_depth antialias output_name\n"); fprintf(stderr," size = Image size (both along x and y)\n"); fprintf(stderr," rec_depth = Recursion depth\n"); fprintf(stderr," antialias = A single digit, 0 disables antialiasing. Anything else enables antialiasing\n"); fprintf(stderr," output_name = Name of the output file, e.g. MyRender.ppm\n"); exit(0); } sx=atoi(argv[1]); MAX_DEPTH=atoi(argv[2]); if (atoi(argv[3])==0) antialiasing=0; else antialiasing=1; strcpy(&output_name[0],argv[4]); fprintf(stderr,"Rendering image at %d x %d\n",sx,sx); fprintf(stderr,"Recursion depth = %d\n",MAX_DEPTH); if (!antialiasing) fprintf(stderr,"Antialising is off\n"); else fprintf(stderr,"Antialising is on\n"); fprintf(stderr,"Output file name: %s\n",output_name); object_list=NULL; light_list=NULL; texture_list=NULL; // Allocate memory for the new image im=newImage(sx, sx); if (!im) { fprintf(stderr,"Unable to allocate memory for raytraced image\n"); exit(0); } else rgbIm=(unsigned char *)im->rgbdata; /////////////////////////////////////////////////// // TO DO: You will need to implement several of the // functions below. For Assignment 3, you can use // the simple scene already provided. But // for Assignment 4 you need to create your own // *interesting* scene. /////////////////////////////////////////////////// buildScene(); // Create a scene. This defines all the // objects in the world of the raytracer ////////////////////////////////////////// // TO DO: For Assignment 3 you can use the setup // already provided here. For Assignment 4 // you may want to move the camera // and change the view parameters // to suit your scene. ////////////////////////////////////////// // Mind the homogeneous coordinate w of all vectors below. DO NOT // forget to set it to 1, or you'll get junk out of the // geometric transformations later on. // Camera center is at (0,0,-1) e.px=0; e.py=0; e.pz=-1; e.pw=1; // To define the gaze vector, we choose a point 'pc' in the scene that // the camera is looking at, and do the vector subtraction pc-e. // Here we set up the camera to be looking at the origin. g.px=0-e.px; g.py=0-e.py; g.pz=0-e.pz; g.pw=1; // In this case, the camera is looking along the world Z axis, so // vector w should end up being [0, 0, -1] // Define the 'up' vector to be the Y axis up.px=0; up.py=1; up.pz=0; up.pw=1; // Set up view with given the above vectors, a 4x4 window, // and a focal length of -1 (why? where is the image plane?) // Note that the top-left corner of the window is at (-2, 2) // in camera coordinates. cam=setupView(&e, &g, &up, -1, -2, 2, 4); if (cam==NULL) { fprintf(stderr,"Unable to set up the view and camera parameters. Our of memory!\n"); cleanup(object_list,light_list, texture_list); deleteImage(im); exit(0); } // Set up background colour here background.R=0; background.G=0; background.B=0; // Do the raytracing ////////////////////////////////////////////////////// // TO DO: You will need code here to do the raytracing // for each pixel in the image. Refer to the // lecture notes, in particular, to the // raytracing pseudocode, for details on what // to do here. Make sure you undersand the // overall procedure of raytracing for a single // pixel. ////////////////////////////////////////////////////// du=cam->wsize/(sx-1); // du and dv. In the notes in terms of wl and wr, wt and wb, dv=-cam->wsize/(sx-1); // here we use wl, wt, and wsize. du=dv since the image is // and dv is negative since y increases downward in pixel // coordinates and upward in camera coordinates. colourRGB col; point3D origin; point3D direction; ray3D initialRay; colourRGB total; int offset; int aaSamples; fprintf(stderr,"View parameters:\n"); fprintf(stderr,"Left=%f, Top=%f, Width=%f, f=%f\n",cam->wl,cam->wt,cam->wsize,cam->f); fprintf(stderr,"Camera to world conversion matrix (make sure it makes sense!):\n"); printmatrix(cam->C2W); fprintf(stderr,"World to camera conversion matrix:\n"); printmatrix(cam->W2C); fprintf(stderr,"\n"); fprintf(stderr,"Rendering row: "); #pragma omp parallel for schedule(dynamic,32) shared(rgbIm, object_list, light_list, texture_list) private(j) for (j=0;j<sx;j++) // For each of the pixels in the image // for (j=2;j<3;j++) { fprintf(stderr,"%d/%d, ",j,sx); #pragma omp parallel for private(origin, direction, col, initialRay, i, aaSamples, offset, total) for (i=0;i<sx;i++) // for (i=2;i<3;i++) { if (!antialiasing){ col.R = 0; col.G = 0; col.B = 0; // = newPoint(cam->wl+i*du,cam->wt+j*dv,cam->f); origin.px = cam->wl+i*du; origin.py = cam->wt+j*dv; origin.pz = cam->f; origin.pw = 1.0; matVecMult(cam->C2W, &origin); // Construct direction vector using Pij - e // point3D direction;// = newPoint(origin->px,origin->py, origin->pz); direction.px = origin.px; direction.py = origin.py; direction.pz = origin.pz; direction.pw = 1.0; subVectors(&e, &direction); normalize(&direction); // Construct ray using both origin and direction. // ray3D initialRay;// = newRay(origin, direction); initialRay.p0 = origin; initialRay.d = direction; // Setting up colors. // col = (struct colourRGB *)calloc(1,sizeof(struct colourRGB)); // Tracing ray rayTrace(&initialRay, 1, &col, NULL); offset = (sx * j * 3) + (i * 3); *(rgbIm + offset + 0) = col.R*255; *(rgbIm + offset + 1) = col.G*255; *(rgbIm + offset + 2) = col.B*255; // Tear down col struct. // free(col); } else { total.R = 0; total.G = 0; total.B = 0; for (aaSamples = 0; aaSamples < 20; aaSamples ++){ col.R = 0; col.G = 0; col.B = 0; // point3D origin;// = newPoint(cam->wl+i*du,cam->wt+j*dv,cam->f); origin.px = cam->wl+(i+drand48()-0.5)*du; origin.py = cam->wt+(j+drand48()-0.5)*dv; origin.pz = cam->f; origin.pw = 1.0; matVecMult(cam->C2W, &origin); // Construct direction vector using Pij - e // point3D direction;// = newPoint(origin->px,origin->py, origin->pz); direction.px = origin.px; direction.py = origin.py; direction.pz = origin.pz; direction.pw = 1.0; subVectors(&e, &direction); normalize(&direction); // Construct ray using both origin and direction. // ray3D initialRay;// = newRay(origin, direction); initialRay.p0 = origin; initialRay.d = direction; // Setting up colors. // col = (struct colourRGB *)calloc(1,sizeof(struct colourRGB)); // Tracing ray rayTrace(&initialRay, 1, &col, NULL); total.R += col.R; total.G += col.G; total.B += col.B; } offset = (sx * j * 3) + (i * 3); total.R = total.R / 20 * 255.0; total.G = total.G / 20 * 255.0; total.B = total.B / 20 * 255.0; *(rgbIm + offset + 0) = total.R; *(rgbIm + offset + 1) = total.G; *(rgbIm + offset + 2) = total.B; } } // end for i } // end for j fprintf(stderr,"\nDone!\n"); // Output rendered image imageOutput(im,output_name); // Exit section. Clean up and return. cleanup(object_list,light_list,texture_list); // Object, light, and texture lists deleteImage(im); // Rendered image free(cam); // camera view exit(0); }
virtual void Execute() { CDB::COLLIDER DB; DB.ray_options (CDB::OPT_CULL); xr_vector<RC> cache; { RC rc; rc.C[0].set (0,0,0); rc.C[1].set (0,0,0); rc.C[2].set (0,0,0); cache.assign (g_nodes.size()*2,rc); } FPU::m24r (); Query Q; Q.Begin (g_nodes.size()); for (u32 N=Nstart; N<Nend; N++) { // initialize process thProgress = float(N-Nstart)/float(Nend-Nstart); vertex& BaseNode= g_nodes[N]; Fvector& BasePos = BaseNode.Pos; Fvector TestPos = BasePos; TestPos.y+=cover_height; float c_total [8] = {0,0,0,0,0,0,0,0}; float c_passed[8] = {0,0,0,0,0,0,0,0}; // perform volumetric query Q.Init (BasePos); Q.Perform (N); // main cycle: trace rays and compute counts for (Nearest_it it=Q.q_List.begin(); it!=Q.q_List.end(); it++) { // calc dir & range u32 ID = *it; R_ASSERT (ID<g_nodes.size()); if (N==ID) continue; vertex& N = g_nodes[ID]; Fvector& Pos = N.Pos; Fvector Dir; Dir.sub (Pos,BasePos); float range = Dir.magnitude(); Dir.div (range); // raytrace int sector = calcSphereSector(Dir); c_total [sector] += 1.f; c_passed [sector] += rayTrace (&DB, TestPos, Dir, range, cache[ID].C); // } Q.Clear (); // analyze probabilities float value [8]; for (int dirs=0; dirs<8; dirs++) { R_ASSERT(c_passed[dirs]<=c_total[dirs]); if (c_total[dirs]==0) value[dirs] = 0; else value[dirs] = float(c_passed[dirs])/float(c_total[dirs]); clamp(value[dirs],0.f,1.f); } BaseNode.cover [0] = (value[2]+value[3]+value[4]+value[5])/4.f; clamp(BaseNode.cover[0],0.f,1.f); // left BaseNode.cover [1] = (value[0]+value[1]+value[2]+value[3])/4.f; clamp(BaseNode.cover[1],0.f,1.f); // forward BaseNode.cover [2] = (value[6]+value[7]+value[0]+value[1])/4.f; clamp(BaseNode.cover[2],0.f,1.f); // right BaseNode.cover [3] = (value[4]+value[5]+value[6]+value[7])/4.f; clamp(BaseNode.cover[3],0.f,1.f); // back } }
Colour* rayTrace(const Colour& ambient, const Point3D& eye, Ray ray, SceneNode* root, const std::list<Light*>& lights, int level, double fogDist){ if(level <= 0) return NULL; Intersection* i = root->intersect(ray); bool fogOn = true; if(fogDist <= 0) fogOn = false; if(i != NULL){ Colour color(0,0,0); Colour fog(0.8,0.8,0.8); Colour diffuse(0,0,0), specular(0,0,0); Material* material = i->getMaterial(); Vector3D n = i->getNormal(); n.normalize(); Point3D p = i->getPoint(); Vector3D v = eye - p; v.normalize(); for (std::list<Light*>::const_iterator I = lights.begin(); I != lights.end(); ++I) { Light light = **I; Vector3D l = light.position - p; l.normalize(); Vector3D r = 2*l*n*n - l; r.normalize(); // shadows Ray lightRay = Ray(p, l); Intersection* lightIsc = root->intersect(lightRay); if(lightIsc == NULL){ // add light contribution //std::cerr << "light" << std::endl; if(n*l > 0) diffuse = diffuse + material->getDiffuse() * (l*n) * light.colour; if(r*v > 0) specular = specular + material->getSpecular() * pow((r*v), material->getShininess()) * light.colour; } } //secondaty rays Vector3D r = 2*v*n*n - v; r.normalize(); Ray refRay(p, r); Colour* reflectedColor = rayTrace(ambient, eye, refRay, root, lights, level-1, fogDist); if(reflectedColor != NULL){ if(n*r > 0) diffuse = diffuse + material->getDiffuse() * (r*n) * material->getReflectivity() * (*reflectedColor); if(r*v > 0) specular = specular + material->getSpecular() * pow((r*v), material->getShininess()) * material->getReflectivity() * (*reflectedColor); } color = ambient*material->getColor() + diffuse + specular; if(fogOn){ double dist = i->getT()/fogDist; if(dist>1) dist=1; color = (1-dist)*color + dist*fog; } return new Colour(color); } return NULL; }
void a4_render(// What to render SceneNode* root, // Where to output the image const std::string& filename, // Image size int width, int height, // Viewing parameters const Point3D& eye, const Vector3D& view, const Vector3D& up, double fov, // Lighting parameters const Colour& ambient, const std::list<Light*>& lights, double fogDist ) { // Fill in raytracing code here. std::cerr << "Stub: a4_render(" << root << ",\n " << filename << ", " << width << ", " << height << ",\n " << eye << ", " << view << ", " << up << ", " << fov << ",\n " << ambient << ",\n {"; for (std::list<Light*>::const_iterator I = lights.begin(); I != lights.end(); ++I) { if (I != lights.begin()) std::cerr << ", "; std::cerr << **I; } std::cerr << "});" << std::endl; Vector3D viewVector = view; Vector3D upVector = up; Vector3D sideVector = viewVector.cross(upVector); viewVector.normalize(); upVector.normalize(); sideVector.normalize(); Image img(width, height, 3); int progress = 0; int numPixels = width*height; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int newProgress = (int)((double)(y*width + x)/numPixels*100); if(newProgress >= progress+5){ progress = newProgress; std::cerr << progress << std::endl; } double d = height/2.0/tan(toRadian(fov)/2); Vector3D dir = (x-(width/2.0))*sideVector + ((height/2.0)-y)*upVector + d*viewVector; dir.normalize(); Ray ray = Ray(eye, dir); bool fogOn = true; if(fogDist <= 0) fogOn = false; Colour* color = rayTrace(ambient, eye, ray, root, lights, 5, fogDist); Colour fog(1,1,1); if(color == NULL) { // sunset colours Colour horizon(0.94, 0.55, 0.05); Colour zenith(0.2, 0.27, 0.4); Colour bg = zenith*(1-(double)y/height) + horizon*((double)y/height); if(fogOn) color = new Colour(0.8,0.8,0.8); else color = new Colour(bg); } img(x, y, 0) = color->R(); img(x, y, 1) = color->G(); img(x, y, 2) = color->B(); } } img.savePng(filename); }
Color Union::rayTrace(CRay ray, int depth, CObject* &_object,IntersectResult*& res) { if(depth>max_depth) return Color::white(); int size = (int)CVector.size(); float distance = 100000000.0f; CObject* primitive_near = NULL; bool visible = true; Color totalColor = Color::black(); CObject* pLight; int num=0; IntersectResult s = IntersectResult::noHit(); for(int i=0;i<size;i++){ CObject* primitive = CVector.at(i); IntersectResult result = primitive->isIntersected(ray); if(result.isHit){ if(result.distance < distance){ s = result; distance = result.distance; primitive_near = result.object; num = i; } } } _object = primitive_near; res = &s; if(primitive_near == NULL) { return Color::black(); } else if(primitive_near->isLight()){ return Color::white(); } else if(!s.front){ cout<<depth<<" "<<s.object->code<<endl; GVector3 v = ray.getDirection(); v = v.normalize(); GVector3 normal = s.normal.normalize(); double cosA = v.dotMul(normal); double sinA = sqrt(1-cosA*cosA); double n = 1.000 / 1.500; //cout<<sinA<<endl; if(sinA >= n){ //cout<<"zhixingle"<<endl; CRay newray; newray.setDirection(normal*(-cosA) + (ray.getDirection() - normal*cosA).normalize()*sinA); newray.setOrigin(s.position + ray.getDirection()*1e-3); CObject* no_use = NULL; IntersectResult* n0=NULL; Color refraction_second = rayTrace(newray,depth+1,no_use,n0); //cout<<refraction_second.r<<" "<<refraction_second.g<<" "<<refraction_second.b<<endl; Color absorbance(0,0,0); if(n0){ Color absorbance = primitive_near->getMaterial()->getColor().multiply(0.15f * ((-1)*n0->distance)); } Color transparancy = Color(exp(absorbance.r),exp(absorbance.g),exp(absorbance.b)); return refraction_second.moderate(transparancy); } else{ double sinB = sinA / n; double cosB = sqrt(1 - sinB*sinB); CRay newray; newray.setDirection(normal*cosB + (v-normal*cosA).normalize()*sinB); newray.setOrigin(s.position + newray.getDirection()*1e-3); //cout<<"Origin:"<<newray.getOrigin().getX()<<" "<<newray.getOrigin().getY()<<" "<<newray.getOrigin().getZ()<<endl; //cout<<"Direction:"<<newray.getDirection().getX()<<" "<<newray.getDirection().getY()<<" "<<newray.getDirection().getZ()<<endl; CObject* no_use = NULL; IntersectResult* n0=NULL; Color refraction_second = rayTrace(newray,depth+1,no_use,n0); //cout<<refraction_second.r<<" "<<refraction_second.g<<" "<<refraction_second.b<<endl; Color absorbance(0,0,0); if(n0){ Color absorbance = primitive_near->getMaterial()->getColor().multiply(0.15f * ((-1)*n0->distance)); } Color transparancy = Color(exp(absorbance.r),exp(absorbance.g),exp(absorbance.b)); return refraction_second.moderate(transparancy); } } else{ GVector3 point; point = ray.getPoint(distance); for(int i=0;i<size;i++){ CObject* primitive = CVector.at(i); if(primitive->isLight()){ pLight = primitive; GVector3 inDir = ((Lamp*) primitive)->getCenter() - point; inDir = inDir.normalize(); CRay line(point+inDir*0.001,inDir); for(int j=0;j<size;j++){ CObject* ano_primitive = CVector.at(j); if(!ano_primitive->isLight() && j!=num){ IntersectResult result = ano_primitive->isIntersected(line); if(result.isHit && result.distance < inDir.getLength()){ visible = false; break; } } } break; } } } GVector3 point; point = ray.getPoint(distance); if(visible){ GVector3 lig = ((Lamp*)pLight)->getCenter() - point; lig = lig.normalize(); primitive_near->getMaterial()->setLightDir(lig); totalColor = totalColor.add( primitive_near->getMaterial()->sample(ray, point, primitive_near->getNormal(point)) ); } float reflection = primitive_near->getMaterial()->getRef(); if( (reflection>0.0f) && (depth<max_depth) ){ GVector3 normal_point = primitive_near->getNormal(point); normal_point = normal_point.normalize(); float s0 = ray.getDirection().dotMul(normal_point) * (-2.0f); CRay newRay; newRay.setDirection(normal_point * s0 + ray.getDirection()); newRay.setOrigin(point + newRay.getDirection()*1e-3); CObject* no_use = NULL; IntersectResult* n0=NULL; Color reflectionColor = rayTrace(newRay,depth+1,no_use,n0); reflectionColor = reflectionColor.multiply(reflection); //reflectionColor = reflectionColor.moderate(primitive_near->getMaterial()->getColor()); totalColor = totalColor.add(reflectionColor.moderate(primitive_near->getMaterial()->getColor())); } float refraction = primitive_near->getMaterial()->getRefr(); //cout<<refraction<<endl; if((refraction>0.0f) && (depth<max_depth)){ GVector3 normal_point = primitive_near->getNormal(point); GVector3 Direction = ray.getDirection().normalize(); normal_point = normal_point.normalize(); float cosA = -Direction.dotMul(normal_point); float sinA = sqrt(1-cosA*cosA); float sinB = sinA / 1.5; float cosB = sqrt(1 - sinB*sinB); //cout<<sinA<<" "<<cosA<<" "<<sinB<<" "<<cosB<<endl; CRay newray; newray.setDirection(normal_point*(-cosB) + (Direction + normal_point*cosA).normalize()*sinB); newray.setOrigin(point + newray.getDirection() * 1e-3); CObject* no_use = NULL; IntersectResult* n0=NULL; Color refractionColor = rayTrace(newray,depth+1,no_use,n0); refractionColor = refractionColor.multiply(refraction); //refractionColor = refractionColor.moderate(primitive_near->getMaterial()->getColor()); totalColor = totalColor.add(refractionColor); } return totalColor; }
void rtShade(struct object3D *obj, struct point3D *p, struct point3D *n, struct ray3D *ray, int depth, double a, double b, struct colourRGB *col) { // This function implements the shading model as described in lecture. It takes // - A pointer to the first object intersected by the ray (to get the colour properties) // - The coordinates of the intersection point (in world coordinates) // - The normal at the point // - The ray (needed to determine the reflection direction to use for the global component, as well as for // the Phong specular component) // - The current racursion depth // - The (a,b) texture coordinates (meaningless unless texture is enabled) // // Returns: // - The colour for this ray (using the col pointer) // // struct colourRGB tmp_col; // Accumulator for colour components // Apply Ambient Light. // Ambient = r_a * I_a * 255 // = Albedo_ra * objectColor double R,G,B; double refractHit = 0; double reflectHit = 0; double numLights = 0; point3D nAdj = *n; // printf("RT SHADE CALLED.\n"); if (obj->texImg==NULL) { R = obj->col.R; G = obj->col.G; B = obj->col.B; // printf("PICTURE UNDETECTED. USING R G B = [%f, %f, %f]\n", R,G,B); } else { // printf("Getting image coordinates @ [%f, %f]\n", a, b); // Get object colour from the texture given the texture coordinates (a,b), and the texturing function // for the object. Note that we will use textures also for Photon Mapping. // printf("CHECKING IMAGE COORDTINATES [%f, %f]\n", a, b); obj->textureMap(obj->texImg,a,b,&R,&G,&B); // printf("PICTURE DETECTED. USING A B = [%f, %f]\n", a, b); // printf("DONE\n"); } // double numSources = 0.0; colourRGB reflectCol, refractCol, tmp_col; tmp_col.R = 0; tmp_col.G = 0; tmp_col.B = 0; reflectCol.R = 0; reflectCol.G = 0; reflectCol.B = 0; refractCol.R = 0; refractCol.G = 0; refractCol.B = 0; // Create a ray from light source pointLS *lightSource = light_list; while (lightSource != NULL){ // numSources += 1.0; // This will hold the colour as we process all the components of // the Phong illumination model // tmp_col.R=; // tmp_col.G=obj->col.G; // tmp_col.B=obj->col.B; // Set up ray FindFirstHit. ray3D lightDirection;// = newRay(p, &lightSource->p0); lightDirection.p0 = *p; lightDirection.d = lightSource->p0; subVectors(p, &lightDirection.d); double tempLambda; object3D *tempObject; point3D tempP; point3D tempN; // Obtain intersection information. findFirstHit(&lightDirection, &tempLambda, obj, &tempObject, &tempP, &tempN, &a, &b); if (obj->frontAndBack && dot(&nAdj, &lightDirection.d) < 0){ nAdj.px = fabs(nAdj.px) * fabs(lightDirection.d.px) / lightDirection.d.px; nAdj.py = fabs(nAdj.py) * fabs(lightDirection.d.py) / lightDirection.d.py; nAdj.pz = fabs(nAdj.pz) * fabs(lightDirection.d.pz) / lightDirection.d.pz; } // if (a > 0.0001 && b > 0.0001){ // // printf("a, b returned as %f, %f\n", a, b); // } // Apply Ambient Light. // Ambient = r_a * I_a * 255 // = Albedo_ra * objectColor tmp_col.R += (R * obj->alb.ra * lightSource->col.R);// / NUM_LIGHTS;// lightSource->col.R;// / NUM_LIGHTS; tmp_col.G += (G * obj->alb.ra * lightSource->col.G);// / NUM_LIGHTS;// lightSource->col.G;// / NUM_LIGHTS; tmp_col.B += (B * obj->alb.ra * lightSource->col.B);// / NUM_LIGHTS;// lightSource->col.B;// / NUM_LIGHTS; // printf("AMBIENT LIGHT: [%f, %f, %f]\n", tmp_col.R,tmp_col.G,tmp_col.B); // Light source is shining on object if we get here. // Set up Phong components: point3D s;// = newPoint(lightSource->p0.px - p->px, lightSource->p0.py - p->py, lightSource->p0.pz - p->pz); s.px = lightSource->p0.px - p->px; s.py = lightSource->p0.py - p->py; s.pz = lightSource->p0.pz - p->pz; s.pw = 1.0; point3D c;// = newPoint(-ray->d.px, -ray->d.py, -ray->d.pz); c.px = -ray->d.px; c.py = -ray->d.py; c.pz = -ray->d.pz; c.pw = 1.0; subVectors(p, &s); // normalize(s); point3D m; //= newPoint(2 * dot(s,n) * n->px, // 2 * dot(s,n) * n->py, // 2 * dot(s,n) * n->pz); m.px = 2 * dot(&s,&nAdj) * nAdj.px; m.py = 2 * dot(&s,&nAdj) * nAdj.py; m.pz = 2 * dot(&s,&nAdj) * nAdj.pz; subVectors(&s, &m); normalize(&m); normalize(&nAdj); normalize(&s); double dotProduct = dot(&nAdj,&s); if (tempLambda < 0.000000001 || tempLambda > 1.0000000){ // Apply Diffuse // Diffuse = r_d * I_d * max(0, n dot s) // = Albedo_rd * lightSource * max(0, n dot s) tmp_col.R += (obj->alb.rd * lightSource->col.R * max(0, dotProduct)) * R;// + tmp_col.G += (obj->alb.rd * lightSource->col.G * max(0, dotProduct)) * G;// + tmp_col.B += (obj->alb.rd * lightSource->col.B * max(0, dotProduct)) * B;// + // printf("DIFFUSE LIGHT: [%f, %f, %f]\n", tmp_col.R,tmp_col.G,tmp_col.B); // Apply Specular // Specular = r_s * I_s * max(0, c dot m) ^ shinyness // = Albedo_rs * lightSource * max(0, c dot m) ^ shinyness tmp_col.R += (obj->alb.rs * lightSource->col.R * pow(max(0, dot(&c, &m)), obj->shinyness)); tmp_col.G += (obj->alb.rs * lightSource->col.G * pow(max(0, dot(&c, &m)), obj->shinyness)); tmp_col.B += (obj->alb.rs * lightSource->col.B * pow(max(0, dot(&c, &m)), obj->shinyness)); } colourRGB reflectedColor; reflectedColor.R = 0; reflectedColor.G = 0; reflectedColor.B = 0; if (depth < MAX_DEPTH){ if (obj->alb.rs > 0){ // Apply Reflections // This involves shooting a ray out from the intersection // position and obtaining a colour from that ray. // First I will obtain the mirror vector: point3D refPoint;// = newPoint(-2.0 * dot(&ray->d, n) * n->px, // -2.0 * dot(&ray->d, n) * n->py, // -2.0 * dot(&ray->d, n) * n->pz); refPoint.px = -2.0 * dot(&ray->d, &nAdj) * nAdj.px; refPoint.py = -2.0 * dot(&ray->d, &nAdj) * nAdj.py; refPoint.pz = -2.0 * dot(&ray->d, &nAdj) * nAdj.pz; refPoint.pw = 1.0; addVectors(&ray->d, &refPoint); normalize(&refPoint); ray3D refRay;// = newRay(p, refPoint); refRay.p0 = *p; refRay.d = refPoint; // Then I will obtain the colour using mirror vector. reflectHit ++; if (reflectCol.R == 0) { rayTrace(&refRay, ++depth, &reflectedColor, tempObject); reflectCol.R = obj->alb.rg * reflectedColor.R * R * NUM_LIGHTS;// * lightSource->col.R; reflectCol.G = obj->alb.rg * reflectedColor.G * G * NUM_LIGHTS;// * lightSource->col.G; reflectCol.B = obj->alb.rg * reflectedColor.B * B * NUM_LIGHTS;// * lightSource->col.B; } // Clean up created pointers. // free(refRay); // free(refPoint); // DRT Colours } if (obj->alpha < 1){ // Apply Refractions // This involves shooting a ray out from the intersection // position, finding the angle of refraction and then // shooting a ray out in that general direction. struct point3D vVec, neg_vVec, refractDir, neg_n, neg_d; vVec.px = p->px - ray->p0.px; vVec.py = p->py - ray->p0.py; vVec.pz = p->pz - ray->p0.pz; neg_vVec.px = - vVec.px; neg_vVec.py = - vVec.py; neg_vVec.pz = - vVec.pz; neg_n.px = -nAdj.px; neg_n.py = -nAdj.py; neg_n.pz = -nAdj.pz; neg_d.px = -ray->d.px; neg_d.py = -ray->d.py; neg_d.pz = -ray->d.pz; refractDir.pw = 1.0; if (dot(n, &vVec) < 0){ // Entering medium double nr = 1 / obj->r_index; double rootContent = sqrt(1 - pow(nr, 2) * (1 - pow(dot(&neg_vVec, n), 2))); if (rootContent >= 0.0) { refractDir.px = (nr * (dot(&neg_vVec, &nAdj)- rootContent)*nAdj.px - (nr * neg_vVec.px)); refractDir.py = (nr * (dot(&neg_vVec, &nAdj)- rootContent)*nAdj.py - (nr * neg_vVec.py)); refractDir.pz = (nr * (dot(&neg_vVec, &nAdj)- rootContent)*nAdj.pz - (nr * neg_vVec.pz)); } } else { // Exiting medium double nr = obj->r_index; double rootContent = sqrt(1 - pow(nr, 2) * (1-(pow(dot(&neg_n, &neg_d), 2)))); if (rootContent >= 0.0) { refractDir.px = (nr * (dot(&neg_d, &neg_n) - rootContent) * neg_n.px - (nr * neg_d.px)); refractDir.py = (nr * (dot(&neg_d, &neg_n) - rootContent) * neg_n.py - (nr * neg_d.py)); refractDir.pz = (nr * (dot(&neg_d, &neg_n) - rootContent) * neg_n.pz - (nr * neg_d.pz)); } } ray3D refRay; refRay.p0.px = p->px + 0.00009; refRay.p0.py = p->py + 0.00009; refRay.p0.pz = p->pz + 0.00009; refRay.p0.pw = 1.0; refRay.d = refractDir; colourRGB refractedColor; refractedColor.R = 0; refractedColor.G = 0; refractedColor.B = 0; // colourRGB refractedColor; rayTrace(&refRay, ++depth, &refractedColor, obj); refractHit ++; refractCol.R += (1 - obj->alpha) * refractedColor.R * R;// * lightSource->col.R;// / NUM_LIGHTS; refractCol.G += (1 - obj->alpha) * refractedColor.G * G;// * lightSource->col.G;// / NUM_LIGHTS; refractCol.B += (1 - obj->alpha) * refractedColor.B * B;// * lightSource->col.B;// / NUM_LIGHTS; } } // tmp_col.R += reflectCol.R + refractCol.R;// + reflectCol.R + refractCol.R; // tmp_col.G += reflectCol.G + refractCol.G;// + reflectCol.G + refractCol.G; // tmp_col.B += reflectCol.B + refractCol.B;// + reflectCol.B + refractCol.B; // Move pointer to next light source. numLights ++; lightSource = lightSource->next; // Clean up created pointers. // free(m); // free(s); // free(c); // free(lightDirection); } // Finally update the color with what we've calculated. // col->R = min(drtR/numSources, 1); // col->G = min(drtG/numSources, 1); // col->B = min(drtB/numSources, 1); col->R = min(tmp_col.R + reflectCol.R/fmax(NUM_LIGHTS, 1) + refractCol.R/fmax(refractHit, 1), 1); col->G = min(tmp_col.G + reflectCol.G/fmax(NUM_LIGHTS, 1) + refractCol.G/fmax(refractHit, 1), 1); col->B = min(tmp_col.B + reflectCol.B/fmax(NUM_LIGHTS, 1) + refractCol.B/fmax(refractHit, 1), 1); // col->R = (n->px + 1) / 2; // col->G = (n->py + 1) / 2; // col->B = (n->pz + 1) / 2; // printf("RTSHADE COMPLETE %f, [%f, %f, %f]\n", numSources, col->R, col->G, col->B); return; }