Hit Quad::intersect(const Ray &ray) { /**************************************************** * RT1.1: INTERSECTION CALCULATION * * Given: ray, A, B, C, D * Sought: intersects? if true: *t * * Insert calculation of ray/quad intersection here. * * If the ray does not intersect the quad, return false. * Otherwise, return true and place the distance of the * intersection point from the ray origin in *t (see example). ****************************************************/ Hit min_hit(std::numeric_limits<double>::infinity(),Vector()); Triangle t1(A,B,C); Triangle t2(C,D,A); Hit hit(t1.intersect(ray)); if (hit.t<min_hit.t) { hit.N = N; return hit; } Hit hit2(t2.intersect(ray)); if (hit2.t<min_hit.t) { hit2.N = N; return hit2; } return Hit::NO_HIT(); }
// ------------------------------------------------------- findMinHit ---------------------------------------------------------------- // Hit Scene::findMinHit(const Ray &ray){ // Find nearest object and distance Hit min_hit(std::numeric_limits<double>::infinity(),Vector()); for (unsigned int i = 0; i < objects.size(); ++i) { Hit hit(objects[i]->intersect(ray)); if (hit.t<min_hit.t) { min_hit = hit; } } return min_hit; }
Color Scene::trace(const Ray &ray) { // Find hit object and distance Hit min_hit(std::numeric_limits<double>::infinity(),Vector()); Object *obj = NULL; for (unsigned int i = 0; i < objects.size(); ++i) { Hit hit(objects[i]->intersect(ray)); if (hit.t<min_hit.t) { min_hit = hit; obj = objects[i]; } } // No hit? Return background color. if (!obj) return Color(0.0, 0.0, 0.0); Material *material = obj->material; //the hit objects material Point hit = ray.at(min_hit.t); //the hit point Vector N = min_hit.N; //the normal at hit point Vector V = -ray.D; //the view vector /**************************************************** * This is where you should insert the color * calculation (Phong model). * * Given: material, hit, N, V, lights[] * Sought: color * * Hints: (see triple.h) * Triple.dot(Vector) dot product * Vector+Vector vector sum * Vector-Vector vector difference * Point-Point yields vector * Vector.normalize() normalizes vector, returns length * double*Color scales each color component (r,g,b) * Color*Color dito * pow(a,b) a to the power of b ****************************************************/ Color color = material->color; // place holder return color; }
Object* CubeGrid::getNearest(const Ray& ray){ //if ray does not intersect boundbox return NULL int firstI, firstJ, firstK; double minx = bound.f1.value; double maxx = bound.f2.value; double miny = bound.f3.value; double maxy = bound.f4.value; double minz = bound.f5.value; double maxz = bound.f6.value; double xstep = (maxx - minx) / NCUBES; double ystep = (maxy - miny) / NCUBES; double zstep = (maxz - minz) / NCUBES; bool inside = false; Point p; Ray currentRay(p, ray.D); if(bound.contains(ray.O)){ firstI = (int)((ray.O.x - minx) / xstep); firstJ = (int)((ray.O.y - miny) / ystep); firstK = (int)((ray.O.z - minz) / zstep); //std::cout<<"reflected "<<firstI<<" "<<firstJ<<" "<<firstK<<std::endl; currentRay.O = ray.O; inside = true; } else{ double t = bound.intersect(ray); if(t == std::numeric_limits<double>::infinity()) return NULL; //ray does not even hot the big bounding box else{ p = ray.at(t); firstI = (int)((p.x - minx) / xstep); firstJ = (int)((p.y - miny) / ystep); firstK = (int)((p.z - minz) / zstep); currentRay.O = p; } } std::set<Object*> objs; std::vector<Box*> rayBoxes; //rayBoxes.push_back(&boxes[firstI][firstJ][firstK]); int i = firstI==NCUBES?NCUBES-1:firstI, j = firstJ==NCUBES?NCUBES-1:firstJ, k = firstK==NCUBES?NCUBES-1:firstK; //std::cout<<"i,j,k: "<<i<<" "<<j<<" "<<k<<std::endl; while( i >= 0 && i <= NCUBES - 1 && j >= 0 && j <= NCUBES - 1 && k >= 0 && k <= NCUBES - 1 ){ //if(printTrue) std::cout<<"i,j,k: "<<i<<" "<<j<<" "<<k<<" ray.D: "<<ray.D<<std::endl; rayBoxes.push_back(&boxes[i][j][k]); for(unsigned int l = 0; l < boxes[i][j][k].objects.size(); l++){ objs.insert(boxes[i][j][k].objects[l]); } double dist[3]; if(ray.D.x < 0){ dist[0] = (boxes[i][j][k].f1.intersect(ray)).t; } else{ dist[0] = (boxes[i][j][k].f2.intersect(ray)).t; } if(ray.D.y < 0){ dist[1] = (boxes[i][j][k].f3.intersect(ray)).t; } else{ dist[1] = (boxes[i][j][k].f4.intersect(ray)).t; } if(ray.D.z < 0){ dist[2] = (boxes[i][j][k].f5.intersect(ray)).t; } else{ dist[2] = (boxes[i][j][k].f6.intersect(ray)).t; } //if(printTrue) std::cout<<"dist: "<<dist[0]<<" "<<dist[1]<<" "<<dist[2]<<std::endl; int l=4; double min = std::numeric_limits<double>::infinity(); for(int m = 0; m<3;m++){ if(!isnan(dist[m]) && dist[m] < min){ min = dist[m]; l = m; } } switch(l){ case 0: if(ray.D.x < 0) i--; else i++; break; case 1: if(ray.D.y < 0) j--; else j++; break; case 2: if(ray.D.z < 0) k--; else k++; break; } } // while( // i >= 0 && i <= NCUBES - 1 && // j >= 0 && j <= NCUBES - 1 && // k >= 0 && k <= NCUBES - 1 // ){ // rayBoxes.push_back(&boxes[i][j][k]); // for(unsigned int l = 0; l < boxes[i][j][k].objects.size(); l++){ // objs.insert(boxes[i][j][k].objects[l]); // } // //std::cout<<"inserted into objs: "<<boxes[i][j][k].objects.size()<<" objects"<<std::endl; // // int nextFace = 8; // double dist = std::numeric_limits<double>::infinity(); // Face* faces[] = {&boxes[i][j][k].f1, &boxes[i][j][k].f2, &boxes[i][j][k].f3, // &boxes[i][j][k].f4, &boxes[i][j][k].f5, &boxes[i][j][k].f6}; // for(int l = 0; l< 6 ; l++){ // double d = boxes[i][j][k].computeDist(currentRay, faces[l]); // if(!isnan(d) && d>=0.00000001 && d<dist){ // dist = d; // nextFace = l; // } // } // // currentRay.O = currentRay.at(dist); // switch(nextFace){ // case 0: i-= 1; break; // case 1: i+= 1; break; // case 2: j-= 1; break; // case 3: j+= 1; break; // case 4: k-= 1; break; // case 5: k+= 1; break; // } // // if(nextFace>5){ // // break; // } // } Hit min_hit(std::numeric_limits<double>::infinity(),Vector()); Object* retObj = NULL; //std::cout << "size for this ray: "<<objs.size()<<std::endl; std::vector<Object*> objConsider (objs.begin(), objs.end()); //std::cout<<"objects considered: "<<objConsider.size()<<std::endl; for (unsigned int i = 0; i < objConsider.size(); ++i) { Hit hit(objConsider[i]->intersect(ray)); if (!isnan(hit.t) && hit.t<min_hit.t) { min_hit = hit; retObj = objConsider[i]; } } // if(inside && retObj!=NULL) // std::cout<<"reflected ray found object"<<std::endl; return retObj; }
// ----------------------------------------------------- tracePhong ------------------------------------------------------------------ // Color Scene::tracePhongGooch(const Ray &ray, int recursionDepth){ // Find hit object and distance Hit min_hit(std::numeric_limits<double>::infinity(),Vector()); Object *obj = NULL; for (unsigned int i = 0; i < objects.size(); ++i) { Hit hit(objects[i]->intersect(ray)); if (hit.t<min_hit.t) { min_hit = hit; obj = objects[i]; } } // No hit? Return background color. if (!obj) return Color(0.0, 0.0, 0.0); Material *material = obj->material; //the hit objects material Point hit = ray.at(min_hit.t); //the hit point Vector N = min_hit.N; //the normal at hit point Vector V = -ray.D; //the view vector /**************************************************** * This is where you should insert the color * calculation (Phong model). * * Given: material, hit, N, V, lights[] * Sought: color * * Hints: (see triple.h) * Triple.dot(Vector) dot product * Vector+Vector vector sum * Vector-Vector vector difference * Point-Point yields vector * Vector.normalize() normalizes vector, returns length * double*Color scales each color component (r,g,b) * Color*Color dito * pow(a,b) a to the power of b ****************************************************/ Color color; //For each light for(unsigned int i = 0; i < lights.size(); i++){ bool isShadow = false; if (rendermode == phong) //Ambiant color += lights[i]->color * material->color * material->ka; //Shadow if(Shadow){ //Ray from light to object Ray light(lights[i]->position, hit - lights[i]->position); //Hit from light to nearest object Hit minHit = findMinHit(light); //Hit from current object to light Hit currentHit(obj->intersect(light)); // if (minHit.t < currentHit.t) isShadow = true; } //No Shadow -> Calculate colors if(!isShadow){ //The light vector Vector L = lights[i]->position - hit;L.normalize(); //The R vector (required for specular shading) Vector R = (-1*L) + 2 * (L.dot(N)) * N; if (rendermode == phong) //Diffuse if (material->texture){ color += (max(0.0,N.dot(L)) * lights[i]->color) * obj->calcTexture(hit) * material->kd; } else { color += (max(0.0,N.dot(L)) * lights[i]->color) * material->color * material->kd; } if (rendermode == gooch && ray.D.dot(N)<-0.2){ Color kCool = Color(0.0,0.0,kBlue) + alpha * (lights[i]->color * material->color * material->kd); Color kWarm = Color(kYellow,kYellow,0.0) + beta * (lights[i]->color * material->color * material->kd); color += (kCool *(1 - N.dot(L))/2) + (kWarm * (1 + N.dot(L))/2); } //Specular + dot(R,V)^n LightColor ks color += pow(max(0.0,R.dot(V)), material->n) * lights[i]->color * material->ks; } } //Reflection if(recursionDepth <= maxRecursionDepth && ray.D.dot(N)<-0.2){ Color buffer(0.0, 0.0, 0.0); //The reflected direction Vector reflectV((V + 2*(-N.dot(V))*N)); for (unsigned int i=0; i<4; i++){ //The reflected ray Ray reflect(hit + 0.001 * N, -reflectV); //Calculate reflection through recursion buffer += material->ks*tracePhongGooch(reflect, recursionDepth+1); reflectV.x += 0.01 * cos(0.5); reflectV.y += 0.01 * sin(0.5); } //Color = average buffer value color += buffer/4; } return color; }
Color Scene::trace(const Ray &ray, int steps,double eta1) { // Find hit object and distance Hit min_hit(std::numeric_limits<double>::infinity(),Vector()); Object *obj = NULL; for (unsigned int i = 0; i < objects.size(); ++i) { Hit hit(objects[i]->intersect(ray)); if (hit.t<min_hit.t) { min_hit = hit; obj = objects[i]; } } // No hit? Return background color. if (!obj) return Color(0.0, 0.0, 0.0); Material *material = obj->material; //the hit objects material Point hit = ray.at(min_hit.t); //the hit point Vector N = min_hit.N; //the normal at hit point Vector V = -ray.D; //the view vector /**************************************************** * This is where you should insert the color * calculation (Phong model). * * Given: material, hit, N, V, lights[] * Sought: color * * Hints: (see triple.h) * Triple.dot(Vector) dot product * Vector+Vector vector sum * Vector-Vector vector difference * Point-Point yields vector * Vector.normalize() normalizes vector, returns length * double*Color scales each color component (r,g,b) * Color*Color dito * pow(a,b) a to the power of b ****************************************************/ // extract and/or declare variables // for lighting calculations Color ambient = Color(1.0,1.0,1.0); // ambient colour Color base = material->color; // material colour double ka = material->ka; // ambient intensity; double kd = material->kd; // diffuse intensity double ks = material->ks; // specular intensity double e = material->n; // exponent of specular highlight size double reflect = material->reflect; // reflect coefficient double refract = material->refract; // refraction coefficient double eta2 = material->eta; // refraction index if(eta1 == eta2){ eta2 = AIR_ETA; } // get reflected ray Vector vec_ref = ray.D - (2.0 *(ray.D.dot(N))*N); // reflect ray direction Ray ray_ref(hit,vec_ref); //reflect ray // jiggle the ray jiggle(ray_ref); // hack Vector frac_n; if(ray.D.dot(N) < 0.0){ frac_n = N; }else{ frac_n = -N; } // get refracted ray bool frac_flag; Vector frac_dir = fractf(eta1,eta2,ray.D,frac_n); // direction of refraction Ray ray_frac(hit,frac_dir); // ray going out of the material if(frac_dir.length_2() > 0.0 && refract > 0.0){ frac_flag = true; }else{ frac_flag = false; } // jiggle the ray jiggle(ray_frac); Color c_ref; // colour of reflected ray Color c_frac; // colour of refracted ray // recursively trace reflected/refracted rays up to steps times if(steps > 0){ if(reflect > 0.0) c_ref = trace(ray_ref,steps-1,eta1); if(frac_flag) c_frac = trace(ray_frac, steps-1,eta2); } Color color = ka * base * ambient; // set ambient colour for(unsigned int i = 0;i<lights.size();i++){ bool shaded = false; // flag if the current light cast a shadow Vector L = hit - lights[i]->position; // vector of light direction Vector SL = lights[i]->position - hit; // vector of shadow feeler L.normalize(); SL.normalize(); // get shadow feelers Ray feeler = Ray(hit,SL); //jiggle Ray jiggle(feeler); // test to see if object is in shadow if(shadows){ for(unsigned int j = 0;j<objects.size();j++){ Hit test(objects[j]->intersect(feeler)); if(test.t >= 0.0) { shaded = true; break; } } } if(!shaded){ Color lc = lights[i]->color; // colour of light double lnDot = L.dot(N); // dot product of light Vector R = L - (2.0*N*lnDot); // reflection vector R.normalize(); double rvDot = R.dot(V) ; color += (kd*base*lc*max(0.0,lnDot)) + (ks*lc*pow(max(0.0,rvDot),e)); } } color += reflect*c_ref + refract*c_frac; return color; }