vec3 Scene::calculPixel(const Rayon& ray, float dist, const vec3& oeil, float &oclu) const { #if 0 return vec3(dist*0.17, dist*0.19, dist*0.23); #else const vec3 dRay = ray.getDirection(); vec3 p(ray.getOrigine() + dRay*dist); node->repositionne(p); const vec3 n(node->getNormal(p)); Material texture = node->getMaterial(p); //return texture.getColor(); std::vector<Lumiere> lumieres2; //lumieres2.reserve(NB_RAYONS_CIEL+this->lumieres.size()); float ombre = calculPoisson(p, n, lumieres2); oclu = ombre; if(ombre > 0) { //for(const Lumiere& l: this->lumieres) //lumieres2.push_back(l); vec3 color = phong(texture, p, lumieres2, n, oeil); //color *= ombre; color = glm::clamp(color, vec3(0,0,0), vec3(1,1,1)); return color; } else return NOIR; #endif }
Color Scene::lanceRayon(const Rayon& ray, int iteration) const { this->addObjectsTabToBinder(); Color result(0.0,0.0,0.0); float minDist(1000.0) ; float dist (0.0) ; Hit hit ; if (binder->intersect(ray,0.0,100.0,hit)) { //result = hit.getObject()->getOptic()->getColor(hit.getU(),hit.getV()); //result = hit.getObject()->getOptic()->getColor(0.5,0.5); Color coulObj(hit.getObject()->getOptic()->getColor(hit.getU(),hit.getV())); for ( std::vector<std::shared_ptr<LightSource>>::const_iterator it = lightsTab.begin(); it != lightsTab.end() ; ++it) // pour chaque source { //d = calcul distance point intersection source Vector directi(it->get()->getOrigin()-hit.getImpactPoint()); float distInterSource = directi.getNorm() ; directi.normalize(); //initialiser Ray : point intersect, direction(point intersect, source), couleur = on s'en fout Color c(0.0,0.0,0.0); Color resultNorm(0.0,0.0,0.0); Rayon ray(hit.getImpactPoint(),directi,c); if (! binder->intersect(ray, 0, distInterSource)) { Color diff(it->get()->getColor()*coulObj*(dotProduct(hit.getNormal(),ray.getDirect()))); Vector moinsV(-directi.getX(),-directi.getY(),-directi.getZ()); Vector miroirV(moinsV + hit.getNormal()*(2*(dotProduct(directi,hit.getNormal())))); //Vmir = V symétrique par rapport à N //spec = coulspec(obj)* (tronquerAZero(RayS.Vmir))^n * coul(source) Color spec(it->get()->getColor()*coulObj*dotProduct(ray.getDirect(),miroirV)); resultNorm = diff + spec ; if ( iteration < 2) { //Res2 = influence rayon réfléchi Rayon reflected(hit.getImpactPoint(),miroirV,c); Color reflectedColor(0.0,0.0,0.0); reflectedColor = this->lanceRayon(reflected,iteration+1); //return pourcent1*Res + ourcent2*Res2 result = resultNorm*0.8 + reflectedColor*0.2 ; } else { result = resultNorm ; } } } } return result; }
bool Sphere::intersect(const Rayon &rayon, float& dist) const { Vector OC(sphereOrigin-rayon.getOrigin()); float k(dotProduct(OC,rayon.getDirect())); float h(dotProduct(OC,OC) - k*k); if (h <= radius*radius) { return true; } else { return false; } }
bool Sphere::intersect(const Rayon &rayon, Hit &hit, float& dist) const { const float m_Pi = 3.14159265358979323846; Vector OC(sphereOrigin-rayon.getOrigin()); float k(dotProduct(OC,rayon.getDirect())); float h(dotProduct(OC,OC) - k*k); float radiusSquare = radius*radius ; if (h <= radiusSquare) { float delta = sqrt(radiusSquare-h); hit.setImpactPoint(rayon.getDistantPoint(k-delta)); dist = k-delta ; if (dist <0) { return false ; } Vector normal(hit.getImpactPoint()-sphereOrigin); normal.normalize(); hit.setNormal(normal); hit.setV( (hit.getImpactPoint().z - (sphereOrigin.z - radius)) / (2*radius) ); Vector A (radius,0.0,0.0); Vector B (hit.getImpactPoint().x-sphereOrigin.x,hit.getImpactPoint().y-sphereOrigin.y,0.0); A.normalize(); B.normalize(); float cosAlpha = dotProduct(A,B) ; float alphaAlpha = acos(cosAlpha) ; float alpha ; if (B.getY() >0) { alpha = alphaAlpha; } else { alpha = 2*m_Pi - alphaAlpha ; } hit.setU(alpha/(2*m_Pi)); return true; } else { return false; } }
bool Terrain::intersect(const Rayon& rayon, float &coeffDistance, int &i) const { float dmin; float dmax; if(!box.intersect(rayon, dmin, dmax )) return false; //à modifier à cause de la précision des floats, mais c'est bizarre que ça marche comme un gant. faire attention que le point de départ ne soit pas en dehors de la box. //dmin = 0.0; //dmax = 3000.0; coeffDistance = dmin; for(i = 0; i<128; i++) { vec3 pos = rayon.getOrigine() + coeffDistance*rayon.getDirection(); float h = getHauteur( pos ); if(h == HAUTEUR_HORS_MAP) { if(i == 0) { coeffDistance += 0.01f; continue; } else break; } h = fabsf(pos.z - h); if( h <(0.002 * coeffDistance) ) { return true; }else if(coeffDistance > dmax ) break; coeffDistance += 0.3*h; } return false; }
bool Triangle::calculIntersection(const Rayon &r, Intersection &I){ //MINIMUM STORAGE RAY TRIANGLE INTERSECTION BY TRUMBORE AND MULLER /*glm::vec3 edge1, edge2, tvec, pvec, qvec; float det, inv_det; float u, v, t; Intersection inter; edge1 = V1 - V0; edge2 = V2 - V0; pvec = glm::cross(r.Vect(), edge2); det = glm::dot(edge1, pvec); //bool i = glm::intersectRayTriangle(r.Orig(), r.Vect(), V0, V1, V2, edge1); if (det < 0.000001){ return false; } tvec = r.Orig() - V0; u = glm::dot(tvec, pvec); if (u < 0.0f || u > det){ return false; } qvec = glm::cross(tvec, edge1); v = glm::dot(r.Vect(), qvec); if (v < 0.0f || u + v > det){ return false; } t = glm::dot(edge2, qvec); inv_det = 1.0f / det; t *= inv_det; u *= inv_det; v *= inv_det; //Intersection inter; inter.dist = t; inter.Objet = this; inter.normal = glm::normalize(glm::cross(edge1, edge2)); I = inter; if (det > -0.000001 && det < 0.000001){ return false; } //inv_det = 1.0f / det; tvec = r.Orig() - V0; u = glm::dot(tvec, pvec) * inv_det; if (u < 0.0f || u > 1.0f){ return false; } qvec = glm::cross(tvec, edge1); v = glm::dot(r.Vect(), qvec)*inv_det; if (v < 0.0f || u + v > 1.0f){ return false; } t = glm::dot(edge2, qvec) * inv_det; //Intersection inter; inter.dist = t; inter.Objet = this; glm::vec3 normal = glm::cross(edge1, edge2); if (normal.z > 0){ normal.z = -normal.z; inter.normal = glm::normalize(normal); I = inter; return true; } inter.normal = glm::normalize(normal); I = inter; return true;*/ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* glm::vec3 edge1 = V1 - V0; glm::vec3 edge2 = V2 - V0; glm::vec3 pvec = glm::cross(r.Vect(), edge2); float det = glm::dot(edge1, pvec); if (det == 0){ return false; } float invDet = 1.0f / det; glm::vec3 tvec = r.Orig() - V0; float u; if (det < 0){ u = glm::dot(tvec, pvec) * invDet; } else{ u = glm::dot(tvec, pvec); } if (u < 0 || u > 1.0f){ return false; } glm::vec3 qvec = glm::cross(tvec, edge1); float v = glm::dot(r.Orig(), qvec) * invDet; if (v < 0 || u + v > 1.0f){ return false; } float t = glm::dot(edge2, qvec) * invDet; Intersection inter; inter.dist = t; inter.Objet = this; glm::vec3 normale = glm::normalize(glm::cross(edge1, edge2)); inter.normal = glm::normalize(glm::cross(edge2, edge1)); if (inter.normal.z > 0){ inter.normal.z = -inter.normal.z; } I = inter; return true;*/ //////////////////////////////////////////////////////////////////////////////////////////////////////////// double det, invdet; glm::vec3 edge1 = V1 - V0; glm::vec3 edge2 = V2 - V0; /* Find the cross product of edge2 and the ray direction */ glm::vec3 s1 = glm::cross(r.Vect(), edge2); det = glm::dot(edge1, s1); if (det > -0.000001 && det < 0.000001) { return false; } invdet = 1 / det; glm::vec3 s2 = r.Orig() - V0; double u = glm::dot(s2, s1) * invdet; if (u < 0 || u > 1) { return false; } glm::vec3 s3 = glm::cross(s2, edge1); double v = glm::dot(r.Vect(), s3) * invdet; if (v < 0 || (u + v) > 1) { return false; } double tmp = glm::dot(edge2, s3) * invdet; if (tmp < 0) { return false; } /* subtract tiny amount - otherwise artifacts due to floating point imprecisions... */ float dist = tmp /*- 0.005*/; glm::vec3 normal = glm::normalize(glm::cross(edge2, edge1)); Intersection inter; inter.dist = dist; inter.Objet = this; inter.normal = -normal; //if (inter.normal.z >= 0){ inter.normal.z = -inter.normal.z; } I = inter; return true; }
bool Scene::intersect(const Rayon& r, float& dist, int& i) const { return intersect(r.getOrigine(), r.getDirection(), dist, i); }
inline float Box::intersectIn(const Rayon& r) const { float tmax, tymax, tzmax; if(r.getDirection()(0) == 0) tmax = FLT_MAX; else if(r.getDirection()(0) > 0) tmax = (max(0) - r.getOrigine()(0)) / r.getDirection()(0); else tmax = (min(0) - r.getOrigine()(0)) / r.getDirection()(0); if(r.getDirection()(1) == 0) tymax = FLT_MAX; else if(r.getDirection()(1) >= 0) tymax = (max(1) - r.getOrigine()(1)) / r.getDirection()(1); else tymax = (min(1) - r.getOrigine()(1)) / r.getDirection()(1); if(tymax < tmax) tmax = tymax; if(r.getDirection()(2) == 0) return tmax; else if(r.getDirection()(2) > 0) tzmax = (max(2) - r.getOrigine()(2)) / r.getDirection()(2); else tzmax = (min(2) - r.getOrigine()(2)) / r.getDirection()(2); if(tzmax < tmax) return tzmax; return tmax; }
bool Box::intersect(const Rayon &r, float &distanceMin, float &distanceMax) const { if(this->isIn(r.getOrigine())) { distanceMin = 0; distanceMax = intersectIn(r); return true; } float tmin, tmax, tymin, tymax, tzmin, tzmax; float div; if(r.getDirection()(0) == 0) { tmin = FLT_MIN; tmax = FLT_MAX; } else if(r.getDirection()(0) > 0) { div = 1 / r.getDirection()(0); tmin = (min(0) - r.getOrigine()(0)) * div; tmax = (max(0) - r.getOrigine()(0)) * div; } else { div = 1 / r.getDirection()(0); tmin = (max(0) - r.getOrigine()(0)) * div; tmax = (min(0) - r.getOrigine()(0)) * div; } if(r.getDirection()(1) == 0) { tymin = FLT_MIN; tymax = FLT_MAX; } else if(r.getDirection()(1) >= 0) { div = 1 / r.getDirection()(1); tymin = (min(1) - r.getOrigine()(1)) * div; tymax = (max(1) - r.getOrigine()(1)) * div; } else { div = 1 / r.getDirection()(1); tymin = (max(1) - r.getOrigine()(1)) * div; tymax = (min(1) - r.getOrigine()(1)) * div; } if( (tmin > tymax) || (tymin > tmax) ) return false; if(tymin > tmin) tmin = tymin; if(tymax < tmax) tmax = tymax; if(r.getDirection()(2) == 0) { tzmin = FLT_MIN; tzmax = FLT_MAX; } else if(r.getDirection()(2) > 0) { div = 1 / r.getDirection()(2); tzmin = (min(2) - r.getOrigine()(2)) * div; tzmax = (max(2) - r.getOrigine()(2)) * div; } else { div = 1 / r.getDirection()(2); tzmin = (max(2) - r.getOrigine()(2)) * div; tzmax = (min(2) - r.getOrigine()(2)) * div; } if( (tmin > tzmax) || (tzmin > tmax) ) return false; if(tzmin > tmin) tmin = tzmin; if(tzmax < tmax) tmax = tzmax; if(tmin>=0) distanceMin = tmin; //else // return false; //inutile apparament //distanceMin += 0.002; if(tmax>0) distanceMax = tmax; return true; }