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; }
static void CheckEscape(GameMap *map, IntVector3 hitBlock, IntVector3 a, IntVector3 b, IntVector3 dir, float& bestDist, IntVector3& bestDir) { hitBlock += dir; IntVector3 aa = a + dir; IntVector3 bb = b + dir; if(map->IsSolidWrapped(hitBlock.x, hitBlock.y, hitBlock.z)) return; if(map->IsSolidWrapped(aa.x, aa.y, aa.z)) return; if(map->IsSolidWrapped(bb.x, bb.y, bb.z)) return; float dist; if(dir.x == 1) { dist = 1.f - fractf(a.x); dist += 1.f - fractf(b.x); }else if(dir.x == -1) { dist = fractf(a.x); dist += fractf(b.x); }else if(dir.y == 1) { dist = 1.f - fractf(a.y); dist += 1.f - fractf(b.y); }else if(dir.y == -1) { dist = fractf(a.y); dist += fractf(b.y); }else if(dir.z == 1) { dist = 1.f - fractf(a.z); dist += 1.f - fractf(b.z); }else if(dir.z == -1) { dist = fractf(a.z); dist += fractf(b.z); }else{ SPAssert(false); return; } if(dist < bestDist){ bestDist = dist; bestDir = dir; } }