bool Light::intersects(const Point &p) const { Intersection i = world->intersect(Ray(origin, p - origin)); const PrimitiveModel *model = i.getModel(); if ((model) && (model->normalAt(p) * (origin - p) < 0)) { return false; } return i.getPoint().near(p); }
/** * Computes the first intersection between a ray and all * the Objects of the scene. * @param ray the ray to be intersected * @param intersection the first intersection computed if * there is one * @return true if there is an intersection, false otherwise. **/ bool Scene::intersect(const ray::Ray & ray, scene::Intersection & intersection) { bool isIntersected=false; float minDistance=INFINITY; Intersection interTest; for(iterator_object it=_objects.begin(); it!=_objects.end();++it) { if((*it)->intersect(ray,interTest)) { float currentDistance=glm::distance2(interTest.getPoint(), ray.getOrigin()); if(currentDistance<minDistance) { isIntersected=true; minDistance=currentDistance; intersection=interTest; } } } return isIntersected; }
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; }
Intersection Cylindre::intersect(Rayon* r) { Intersection inter; double a; double b; double c; double delta; double t, t1, t2; /* equation du Cylindre y²+z²=rayon² avec 0<x<longueur=height * (dy.t+py)²+(dz.t+pz)²=rayon² * (dy²+dz²)t²+(dy.py+dz.pz)t+(py²+pz²-rayon²)=0 * at²+bt+c=0 */ inter.setObjet(this); a=pow(r->getDirection().y,2)+pow(r->getDirection().z,2); b=(r->getDirection().y*r->getPosition().y)+(r->getDirection().z*r->getPosition().z); c=pow(r->getPosition().y,2)+pow(r->getPosition().z,2)-pow(this->r,2); //calcul du discriminant delta = pow(b,2)-4*a*c; if (delta <= 0) { inter.setDistance(DBL_MAX); //distance infinie (pas d'intersection) //si py²+pz²-rayon²<=0 ou c<0 //on se situe sur l'alignement du cylindre if(c<0){ if( (this->height!=0) && (r->getPosition().x>this->height || (r->getPosition().x>=0.0 && r->getPosition().x<this->height))){ if(r->getDirection().x!=0.0){ t = (this->height-r->getPosition().x)/r->getDirection().x; inter.setPoint( vector3(this->height, t * r->getDirection().y + r->getPosition().y, t * r->getDirection().z + r->getPosition().z) ); if(t>EPSILON && c<=0){ inter.setDistance ( (inter.getPoint()-r->getPosition()).Length() ); }else{ inter.setDistance(DBL_MAX); } }else{ inter.setDistance ( DBL_MAX ); } } if( (this->height!=0) && (r->getPosition().x<this->height || (r->getPosition().x>0.0 && r->getPosition().x<=this->height))){ if(r->getDirection().x!=0.0){ t = (-r->getPosition().x)/r->getDirection().x; inter.setPoint(vector3(0.0, t * r->getDirection().y + r->getPosition().y, t * r->getDirection().z + r->getPosition().z) ); if(t>EPSILON && c<=0){ inter.setDistance ( (inter.getPoint()-r->getPosition()).Length() ); }else{ inter.setDistance(DBL_MAX); } }else{ inter.setDistance(DBL_MAX); } } } }else{ //deux solutions t1 = (-b + sqrt (delta)) / 2*a; t2 = (-b - sqrt (delta)) / 2*a; if (t1 <= EPSILON && t2 <= EPSILON){ inter.setDistance(DBL_MAX); }else{ if ((t1 <= t2 && t1 > EPSILON) || (t2 < t1 && t2 < EPSILON)){ t = t1; }else if ((t2 < t1 && t2 > EPSILON) || (t1 < t2 && t1 < EPSILON)){ t = t2; } inter.setPoint(vector3(t * r->getDirection().x + r->getPosition().x, t * r->getDirection().x + r->getPosition().x, t * r->getDirection().z + r->getPosition().z)); inter.setDistance ( (inter.getPoint()-r->getPosition()).Length() ); if( (this->height!=0) && (inter.getPoint().x>this->height) || (r->getPosition().x>this->height && c<=0)){ if(r->getDirection().x!=0.0){ t = (this->height-r->getPosition().x)/r->getDirection().x; inter.setPoint(vector3(this->height, t * r->getDirection().y + r->getPosition().y, t * r->getDirection().z + r->getPosition().z) ); if(t>EPSILON && c<=0){ inter.setDistance ( (inter.getPoint()-r->getPosition()).Length() ); }else{ inter.setDistance(DBL_MAX); } }else{ inter.setDistance(DBL_MAX); } } if( (this->height!=0) && (inter.getPoint().x<0.0) || (r->getPosition().x<0.0 && c<=0)){ if(r->getDirection().x!=0.0){ t = (-r->getPosition().x)/r->getDirection().x; inter.setPoint(vector3(0.0, t * r->getDirection().y + r->getPosition().y, t * r->getDirection().z + r->getPosition().z) ); if(t>EPSILON){ inter.setDistance ( (inter.getPoint()-r->getPosition()).Length() ); }else{ inter.setDistance(DBL_MAX); } }else{ inter.setDistance(DBL_MAX); } } } } //TODO: la normale return (inter); }