TEST(IntersectTest, IntersectValueTest) { Sphere sphere = Sphere(vec3(1,0,0), 1); float *thit = new float(0); LocalGeo *local = new LocalGeo(Point(vec4(0,0,0,1)), Normal(vec3(0,0,0))); // 2 real positive roots, pick smaller one Ray ray1 = Ray(vec3(-1,0,0), vec3(1,0,0), 0, 0, 100); sphere.intersect(ray1, thit, local); EXPECT_EQ(*thit, 1); EXPECT_EQ(local->point.p, vec4(0,0,0,1)); EXPECT_EQ(local->normal.p, vec3(-1,0,0)); // tangent Ray ray2 = Ray(vec3(0,0,0), vec3(0,1,0), 0, 0, 100); EXPECT_EQ(sphere.intersect(ray2, thit, local), true); EXPECT_EQ(*thit, 0); EXPECT_EQ(local->point.p, vec4(0,0,0,1)); EXPECT_EQ(local->normal.p, vec3(-1,0,0)); // one positive, one negative Ray ray3 = Ray(vec3(1,0,0), vec3(1,0,0), 0, 0, 100); EXPECT_EQ(sphere.intersect(ray3, thit, local), true); EXPECT_EQ(*thit, 1); EXPECT_EQ(local->point.p, vec4(2,0,0,1)); EXPECT_EQ(local->normal.p, vec3(1,0,0)); // no intersection Ray ray4 = Ray(vec3(-1,0,0), vec3(0,1,0), 0, 0, 100); EXPECT_EQ(sphere.intersect(ray4, thit, local), false); }
double intersect(Ray& r, Vector& normal){ if(boundVol.intersect(r, normal)<0) return -1; double t=1e30; Vector norm; bool found=false; int in=-1; for(int i=0;i<98;i++){ double t2=triangles[i].intersect(r, norm); if(t2<t&&t2>EPS){ found=true; t=t2; in=i; } } if(found){ Vector a=triangles[in].p3-triangles[in].p1; Vector b=triangles[in].p2-triangles[in].p1; Vector c=r[t]-triangles[in].p1; double aa=a*a; double ab=a*b; double ac=a*c; double bb=b*b; double bc=b*c; double det=1/(aa*bb-ab*ab); double u=(bb*ac-ab*bc)*det; double v=(aa*bc-ab*ac)*det; normal=triangles[in].n1*(1-u-v)+triangles[in].n2*(v)+triangles[in].n3*(u); return t; } return -1; }
static void IsectRaySphere(benchmark::State& state) { RayIntersection isect; Ray ray(Vector4(0, 0, -10), Vector4(0, 0, 1)); Sphere obj; float hit; for (auto _ : state) { hit = obj.intersect(ray, isect); benchmark::DoNotOptimize(hit); } }
TEST(SphereTest, TranslateIntersectNormalTest) { Sphere sphere = Sphere(vec3(2,0,0), 1); sphere.set_transform(mat4(1,0,0,0, 0,1,0,0, 0,0,1,0, -1,0,0,1)); //center now at (1,0,0) Ray ray = Ray(vec3(0,0,2), vec3(0,0,-1), 0, 0, 100); EXPECT_EQ(sphere.intersectP(ray), true); LocalGeo *local = new LocalGeo(Point(), Normal()); float *t = new float(0); sphere.intersect(ray, t, local); EXPECT_EQ(local->normal.p, vec3(-1,0,0)); }
Color trace(Ray * ray, vector<Sphere> balls, int depth){ if (depth == 0){ return Color(0.0f, 0.0f, 0.0f); } float closest_t = 999999999999999999; //FIX ME MAX FLOAT Sphere * closest_sphere = 0; bool hit = false; int id = 0; for (int x = 0; x < balls.size(); x++){ Sphere sphere = ((balls)[x]); if (sphere.hit(ray) == 1){ hit = true; float intersect = sphere.intersect(ray); if (intersect < closest_t){ closest_t = intersect; closest_sphere = &((balls)[x]); id = x; } } } Color rgb(0.0f, 0.0f, 0.0f); if (hit){ //return closest_sphere->diffuse(ray, closest_t) + closest_sphere->specular(ray, closest_t)+trace(; /* for (int a = 0.0f; a < alights.size(); a++){ rgb.red += .3f*alights[a].red; rgb.green += .15*alights[a].green; rgb.blue += 0.0f*alights[a].blue; } */ for (int a = 0.0f; a < plights.size(); a++){ rgb.red += .3f*plights[a].red; rgb.green += .15*plights[a].green; rgb.blue += 0.0f*plights[a].blue; } rgb= rgb + closest_sphere->diffspec(ray, closest_t, id); } return rgb;; }
void renderNormal(Sphere scene, PerspectiveCamera camera) { for(int y=0;y<Y_RES;y++) { float sy = (float)y/Y_RES; for(int x=0;x<X_RES;x++) { float sx = (float)x/X_RES; Ray3 ray = camera.generateRay(sx,sy); IntersectResult result = scene.intersect(ray); if(result.getGeometry()) { fbuffer[y][x][0]=(result.getNormal().getx()+1)*128; fbuffer[y][x][1]=(result.getNormal().gety()+1)*128; fbuffer[y][x][2]=(result.getNormal().getz()+1)*128; } } } }
void rayTrace2( Sphere scene, PerspectiveCamera camera) { for(int y=0;y<Y_RES;y++) { float sy = (float)y/Y_RES; for(int x=0;x<X_RES;x++) { float sx = (float)x/X_RES; Ray3 ray = camera.generateRay(sx,sy); IntersectResult result = scene.intersect(ray); if(result.getGeometry()) { cout<<"x:"<<y<<" y:"<<x<<endl; Color color = PhongMaterial(Color::red,Color::white,16,1).sample(ray, result.getPosition(), result.getNormal()); fbuffer[y][x][0]=color.getR()*255; fbuffer[y][x][1]=color.getG()*255; fbuffer[y][x][2]=color.getB()*255; } } } }
void renderDepth(Sphere scene, PerspectiveCamera camera, int maxDepth) { for(int y=0;y<Y_RES;y++) { float sy = (float)y/Y_RES; for(int x=0;x<X_RES;x++) { float sx = (float)x/X_RES; Ray3 ray = camera.generateRay(sx,sy); IntersectResult result = scene.intersect(ray); if(result.getGeometry()) { int depth = 255 - Min((result.getDistance()/maxDepth)*255,255); //cout<< "x: " << x << " y: " << y << " depth: "<<depth<<" dis: "<<result.getDistance()<<endl; fbuffer[y][x][0]=depth; fbuffer[y][x][1]=depth; fbuffer[y][x][2]=depth; } } } }
/** Phong lighting model ** @param pt intersection point ** @param n normal of pt ** @param light pointer to the light source ** @param obj pointer to the object ** @param ray ray ** @return color calculated from local shading using phong model **/ Vec phongModel(Vec pt, Vec n, Light* light, Shape* obj, Ray ray) { float t; Vec v = ray.getOrig() - pt; v = v.normalize(); // vector to viewer Vec l = light->pos - pt; float dis = l.mag(); // distance to light source l = l.normalize(); // vector to light source Vec ir = n * (2 * n.dot(l)) - l; ir = ir.normalize(); // vector of ideal reflector Vec intensity = light->intensity; // light intensity Ray shadowRay(pt, l, 0, 9999, ShadowRay); // shadow ray to the light source float f = light->attenFac(dis); // attentuation factor Pigment p = obj->getPigment(); Vec obj_color; // object color float scalar; int tmp; if (p.type == SOLID) { obj_color = p.c1; } else if (p.type == CHECKER) { scalar = p.width; tmp = (int)(pt.x/scalar) + (int)(pt.y/scalar) + (int)(pt.z/scalar); if (tmp % 2 == 0) obj_color = p.c1; else obj_color = p.c2; } else if (p.type == TEXTURE) { if (obj->getType() == sphere) obj_color = sphereMapping(pt, n, p); } // get the surface parameters SurFinish appearance = obj->getSurFin(); float Ka = appearance.ambient; // ambient coefficient float Kd = appearance.diffuse; // diffuse coefficient float Ks = appearance.specular; // specular coefficient float shininess = appearance.shininess; // for each object in the scene, see if is blocks the light if (light->type != ambient) { for (ShapeIter its = scene.shapes.begin(); its != scene.shapes.end(); its++) { if ((*its) == obj) continue; if ((*its)->getType() == sphere) { Sphere *shape = dynamic_cast<Sphere*>(*its); if (shape->intersect(shadowRay, t) && t < dis) return black; } else if((*its)->getType() == polyhedron){ Polyhedron *shape = dynamic_cast<Polyhedron*>(*its); if (shape->intersect(shadowRay, t) && t < dis) { return black; } } else if((*its)->getType() == triangleMesh){ TriangleMesh *shape = dynamic_cast<TriangleMesh*>(*its); if (shape->intersect(shadowRay, t) && shadowRay.calcDest(t).mag() < dis) return black; } } } Vec diffuse(0.0, 0.0, 0.0); Vec specular(0.0, 0.0, 0.0); // if the light is casted from front if (n.dot(l) > 0) { diffuse = intensity * (Kd * n.dot(l) * f); specular = white * (Ks * pow(v.dot(ir),shininess) * f); // update light color intensity.x = (light->type != ambient) ? diffuse.x * obj_color.x + specular.x : obj_color.x * Ka; intensity.y = (light->type != ambient) ? diffuse.y * obj_color.y + specular.y : obj_color.y * Ka; intensity.z = (light->type != ambient) ? diffuse.z * obj_color.z + specular.z : obj_color.z * Ka; } // if the light is casted from behind else { intensity.x = (light->type != ambient) ? black.x : obj_color.x * Ka; intensity.y = (light->type != ambient) ? black.y : obj_color.y * Ka; intensity.z = (light->type != ambient) ? black.z : obj_color.z * Ka; } return intensity; }
/** Ray Tracer ** @param ray the ray to be traced ** @param depth recursion depth ** @return color value **/ Vec trace(Ray ray, int depth){ if (debugMode) { printf("\nrecursion = %d\n", depth); printf("ray origin = "); ray.getOrig().print(); printf("ray direction = "); ray.getDir().print(); } if (depth == 0) return black; // return background color Vec color, local, reflected, transmitted; Vec pt, normal; float tClosest = ray.getTmax(); // set dis to a maximum value Shape *ObjPtr = NULL; // set the Obj pointer to null // look for intersection point for each object in the scene bool inside = false; for (ShapeIter its = scene.shapes.begin(); its != scene.shapes.end(); its++) { if ((*its) == ray.ObjPtr) continue; float t; if ((*its)->getType() == sphere) { Sphere *shape = dynamic_cast<Sphere*>(*its); if (shape->intersect(ray, t)) { if (t < tClosest && t > ray.getTmin()) { inside = (shape->intersect(ray, t) == -1) ? true : false; tClosest = t; // update tClosest ObjPtr = (*its); // set ObjPtr to point to the object } } } else if((*its)->getType() == polyhedron){ Polyhedron *shape = dynamic_cast<Polyhedron*>(*its); if (shape->intersect(ray, t)) { if (t < tClosest && t > ray.getTmin()) { tClosest = t; ObjPtr = (*its); } } } else if((*its)->getType() == triangleMesh){ TriangleMesh *shape = dynamic_cast<TriangleMesh*>(*its); if (shape->intersect(ray, t)) { if (t < tClosest && t > ray.getTmin()) { tClosest = t; ObjPtr = (*its); } } } } if (ObjPtr != NULL) { SurFinish appearance = ObjPtr->getSurFin(); float Kr = appearance.reflective; // reflectivity float Kt = appearance.transmission; // transmitivity float ior_obj = appearance.ior; // index of refraction pt = ray.calcDest(tClosest); // set the pos variable pt to the nearest intersection point normal = ObjPtr->calcNorm(pt); // normal of intersection point if (normal.dot(ray.getDir()) > 0) normal = normal * (-1); if(inside) normal = normal * (-1); local.setVec(0.0, 0.0, 0.0); // set local shading to black // for each light source in the scene for (LightIter itl = scene.lights.begin(); itl != scene.lights.end(); itl++){ Light *LightPtr = (*itl); // pointer to the light source // calculate local shading according to Phong model local = local + phongModel(pt, normal, LightPtr, ObjPtr, ray) / scene.numL; // Recursively cast reflected and refracted rays if (Kr > 0) { // specular reflective Ray refl = reflect(ray, pt, normal); refl.ObjPtr = ObjPtr; reflected = reflected + trace(refl, depth-1)/scene.numL; } if (Kt > 0 && ior_obj != 0) { // translucent Ray refr = transmit(ray, pt, normal, ior_air, ior_obj); refr.ObjPtr = ObjPtr; transmitted = transmitted + trace(refr, depth-1)/scene.numL; } } // update light color color.setVec(local + reflected * Kr + transmitted * Kt); } // if no intersection else { color.setVec(background); // set color to background color } if (debugMode == 1) { printf("\nPrinting information for depth = %d\n", depth); Vec orig = ray.getOrig(); Vec dir = ray.getDir(); printf("RAY:\n"); printf("origin = %f %f %f\n", orig.x, orig.y, orig.z); printf("direction = %f %f %f\n", dir.x, dir.y, dir.z); printf("INTERSECTION:\n"); printf("intersection point = %f %f %f\n", pt.x, pt.y, pt.z); printf("normal = %f %f %f\n", normal.x, normal.y, normal.z); printf("LIGHT VISIBILITY:\n"); printf("local shading = %f %f %f\n", local.x, local.y, local.z); printf("reflected shading = %f %f %f\n", reflected.x, reflected.y, reflected.z); printf("transmitted shading = %f %f %f\n", transmitted.x, transmitted.y, transmitted.z); printf("PIXEL COLOR:\n"); printf("color = %f %f %f\n", color.x, color.y, color.z); printf("\n"); } return color; }
void IntersectionUI::writeTest() const { // creates a deterministic sequence of ray positions and directions // and writes the resulting intersections to a file // you must add the proper intersect calls for this file to be generated double invBase[5] = {1.0 / 2.0, 1.0 / 3.0, 1.0 / 5.0, 1.0 / 7.0, 1.0 / 11.0}; double values[5] = {0.0, 0.0, 0.0, 0.0, 0.0}; std::ofstream file("../intersections.txt"); file.precision(4); const int seed = static_cast<int>(intersectionUI->m_iSeed->value()); // generate a halton sequence to pick position/ray combinations // skip the first 'seed' values for (int i = 0; i < seed; i++) { for (int j = 0; j < 5; j++) { double r = 1.0 - values[j] - 1e-10; if (invBase[j] < r) values[j] += invBase[j]; else { double hh; double h = invBase[j]; do { hh = h; h *= invBase[j]; } while (h >= r); values[j] += ((hh + h) - 1.0); } } } for (int i = seed; i < (seed + 1638); i++) { for (int j = 0; j < 5; j++) { double r = 1.0 - values[j] - 1e-10; if (invBase[j] < r) values[j] += invBase[j]; else { double hh; double h = invBase[j]; do { hh = h; h *= invBase[j]; } while (h >= r); values[j] += ((hh + h) - 1.0); } } // create the ray from the five random values // compute ray origin Point3 p; p[0] = values[4] * sin(values[0] * M_PI) * cos(values[1] * 2.0 * M_PI); p[1] = values[4] * sin(values[0] * M_PI) * sin(values[1] * 2.0 * M_PI); p[2] = values[4] * cos(values[0] * M_PI); // compute ray direction Vector3 dir; dir[0] = sin(values[2] * M_PI) * cos(values[3] * 2.0 * M_PI); dir[1] = sin(values[2] * M_PI) * sin(values[3] * 2.0 * M_PI); dir[2] = cos(values[2] * M_PI); HitRecord cubeHr, cylinderHr, coneHr, sphereHr; // ToDo: intersect with your shapes here and store the result // in the appropriate hit record //cube.intersect(p, dir); Cube cube = Cube(1); cubeHr = *(cube.intersect(p, dir)); //cylinder.intersect(p, dir); Cylinder cylinder = Cylinder(1, 1); cylinderHr = *(cylinder.intersect(p, dir)); //coneHr = cone.intersect(p, dir); Cone cone = Cone(1, 1); coneHr = *(cone.intersect(p, dir)); //sphereHr = sphere.intersect(p, dir); Sphere sphere = Sphere(1); sphereHr = *(sphere.intersect(p, dir)); // write out file << i << " Cube " << cubeHr << std::endl; file << i << " Cylinder " << cylinderHr << std::endl; file << i << " Cone " << coneHr << std::endl; file << i << " Sphere " << sphereHr << std::endl; } file.close(); }