float Ray::intersect (const Vec3Df & p0, const Vec3Df & p1, const Vec3Df & p2, Vec3Df & intersectionPoint) const { Vec3Df e0 = p1-p0; Vec3Df e1 = p2-p0; Vec3Df n = Vec3Df::crossProduct(e0,e1); n.normalize(); Vec3Df q = Vec3Df::crossProduct(direction,e1); float a = Vec3Df::dotProduct(e0,q); if (Vec3Df::dotProduct(n,direction) >= 0 || a < epsilon) return -1; Vec3Df s = (origin-p0)/a; Vec3Df r = Vec3Df::crossProduct(s,e0); intersectionPoint[1] = Vec3Df::dotProduct(s,q); intersectionPoint[2] = Vec3Df::dotProduct(r,direction); intersectionPoint[0] = 1 - intersectionPoint[2] - intersectionPoint[1]; if (intersectionPoint[0] < 0 || intersectionPoint[1] < 0 || intersectionPoint[2] < 0) return -1; float t = Vec3Df::dotProduct(e1,r); if (t < 0) return -1; else return t; }
Vec3Df Glass::genColor (const Vec3Df & camPos, Ray *r, const std::vector<Light> &lights, Brdf::Type type) const { const Object *o = r->getIntersectedObject(); float size = o->getBoundingBox().getRadius(); const Vertex &closestIntersection = r->getIntersection(); const Vec3Df & pos = closestIntersection.getPos(); Vec3Df dir = camPos-pos; Vec3Df normal = normalTexture->getNormal(r); dir = dir.refract(1, normal, coeff); dir.normalize(); //Works well only for convex object Ray ray(pos-o->getTrans()+3*size*dir, -dir); if (!o->getKDtree().intersect(ray)) { return controller->getRayTracer()->getColor(pos+size*dir, pos-camPos); } const Vertex i = ray.getIntersection(); dir = (-dir).refract(coeff,-normalTexture->getNormal(&ray), 1); Vec3Df glassColor = controller->getRayTracer()->getColor(dir, i.getPos()+o->getTrans(), false); Vec3Df brdfColor = Vec3Df(); // If at least slightly opaque if (alpha) { brdfColor = Material::genColor(camPos, r, lights, type); } return Vec3Df::interpolate(brdfColor, glassColor, alpha); }
bool Sphere::intersect(const Vec3Df& origin, const Vec3Df& dir, Vec3Df& new_origin, Vec3Df& normal) { Vec3Df trans_origin = origin - this->_origin; float a = Vec3Df::dotProduct(dir, dir); float b = 2 * Vec3Df::dotProduct(trans_origin, dir); float c = Vec3Df::dotProduct(trans_origin, trans_origin) - this->_radius * this->_radius; float disc = b * b - 4 * a * c; if (disc < 0) return false; // We use the following in place of the quadratic formula for // more numeric precision. float q = (b > 0) ? -0.5 * (b + sqrtf(disc)) : -0.5 * (b - sqrtf(disc)); float t0 = q / a; float t1 = c / q; if (t0 < t1) std::swap(t0,t1); float t; if (t0 < EPSILON) return false; if (t1 < 0) t = t0; else t = t1; normal = trans_origin + t * dir; normal.normalize(); new_origin = origin + t * dir; return true; }
float Ray::intersect (const Vec3Df & p0, const Vec3Df & p1, const Vec3Df & p2, Vec3Df & intersectionPoint, Vec3Df & bary) const { Vec3Df e0 = p1-p0; Vec3Df e1 = p2-p0; Vec3Df n = Vec3Df::crossProduct(e0,e1); Vec3Df dir (this->direction); n.normalize(); Vec3Df q = Vec3Df::crossProduct(dir,e1); float a = Vec3Df::dotProduct(e0,q); if (Vec3Df::dotProduct(n,dir) >= 0 || std::abs(a) < epsilon) return -1; Vec3Df s = (this->origin-p0)/a; Vec3Df r = Vec3Df::crossProduct(s,e0); bary[1] = Vec3Df::dotProduct(s,q); bary[2] = Vec3Df::dotProduct(r,dir); bary[0] = 1 - bary[2] - bary[1]; if (bary[0] < 0 || bary[1] < 0 || bary[2] < 0) return -1; float t = Vec3Df::dotProduct(e1,r); intersectionPoint = Vec3Df(p0 * bary[0] + p1 * bary[1] + p2 * bary[2])/(bary[0] + bary[1] + bary[2]); if (t < 0) return -1; else return t; }
void Surfel::BuildFromVertices ( const Vertex& iA, const Vertex& iB, const Vertex& iC, const Vec3Df& iTranslation ) { // Edge eX is opposed to vertex X. Vec3Df eA = iC.getPos () - iB.getPos (); Vec3Df eB = iC.getPos () - iA.getPos (); Vec3Df eC = iA.getPos () - iB.getPos (); float a = eA.getLength (); float b = eB.getLength (); float c = eC.getLength (); eA.normalize (); eB.normalize (); eC.normalize (); // The perimeter of the triangle. float p = (a + b + c); // The semiperimeter of the triangle. float s = 0.5f * p; // The area of the triangle. float k = sqrt ( s * ( s - a ) * ( s - b ) * ( s - c ) ); // The surfel radius equals the radius of the circle inscribed // in the triangle defined by vertices iA, iB and iC. m_radius = k / s; // The surfel's position is defined by the center of the inscribed // circle, which is subsequently defined by the intersection point // of the angle bisections. m_position = a * iA.getPos () + b * iB.getPos () + c * iC.getPos (); m_position /= p; m_position += iTranslation; // We interpolate the normals the same way. m_normal = a * iA.getNormal () + b * iB.getNormal () + c * iC.getNormal (); m_normal /= p; }
void Camera::rotate (float theta, float phi) { Vec3Df up (getUpVector ()); Vec3Df right (getRightVector ()); Vec3Df ce (eye - center); float d = ce.getLength (); ce.normalize (); Vec3Df c = Vec3Df (sin (theta), sin (phi), cos (theta)); eye = center + d * (c[0]*right + c[1]*up + c[2]*ce); }
bool Shadow::hard(const Vec3Df & pos, const Vec3Df& light) const { Ray riShadow; Vec3Df dir = light - pos; float dist = dir.normalize(); bool inter = rt->intersect(dir, pos, riShadow); if(inter && dynamic_cast<const Glass *>(&riShadow.getIntersectedObject()->getMaterial())) return true; return !inter || (inter && riShadow.getIntersectionDistance() > dist); }
Vec3Df Sphere::shade(const Vec3Df& cam_pos, const Vec3Df& intersect, const Vec3Df& light_pos, const Vec3Df& normal){ if (!_mat.has_tex()) return Shape::shade(cam_pos, intersect, light_pos, normal); float u, v; Vec3Df mid = this->_origin; Vec3Df dir = intersect - mid; dir.normalize(); u = 0.5 + (atan2(dir[2], dir[0]))/(2*M_PI); v = 0.5 - asin(dir[1])/M_PI; Vec3Df diffuse = this->_tex->getColor(u,v); this->_mat.set_Kd(diffuse[0], diffuse[1], diffuse[2]); return Shape::shade(cam_pos, intersect, light_pos, normal); }
/// Computes lighting for a single vertex with given calculation model. Vec3Df computeLighting(Vec3Df &vertexPos, Vec3Df &normal, LightModel lightModel) { const Vec3Df lightColor = Vec3Df(1,1,1); const Vec3Df lightColorBoss = Vec3Df(1, 0, 0); switch (lightModel) { case DIFFUSE_LIGHTING: { // We cheat here: assuming a distant sun, this is an reasonable approximation Vec3Df l = (Vec3Df(LightPos[0],LightPos[1],LightPos[2]) - Vec3Df(0,0,0)); l.normalize(); return Vec3Df::dotProduct(l, normal) * lightColor; } case PHONG_LIGHTNING: { Vec3Df lightDir = boss.position - vertexPos; lightDir.normalize(); Vec3Df reflDir = 2 * Vec3Df::dotProduct(lightDir, normal) * normal - lightDir; reflDir.normalize(); Vec3Df viewDir = camPos - vertexPos; viewDir.normalize(); //Using only 1 light source float ambiant = std::fmax(0, ka*ia); float diffuse = std::fmax(0, kd*Vec3Df::dotProduct(lightDir, normal)*id); float specular = std::fmax(0, ks*std::pow(std::fmax(0, Vec3Df::dotProduct(reflDir, viewDir)), alpha)*is); float intensity = ambiant + diffuse + specular; Vec3Df final = intensity * lightColorBoss; return final; } default: return Vec3Df(0, 0, 0); } }
RotationMatrix::RotationMatrix(double _teta, Vec3Df axis){ axis.normalize(); float c = std::cos(_teta*PI/180.); float s = std::sin(_teta*PI/180.); float ux = axis[0]; float uy = axis[1]; float uz = axis[2]; new (this) RotationMatrix( ux*ux +(1.-ux*ux)*c , ux*uy*(1-c) - uz*s ,ux*uz*(1-c) + uy*s , 0., ux*uy*(1-c) + uz*s, uy*uy +(1.-uy*uy)*c, uy*uz*(1-c) - ux*s , 0. , ux*uz*(1-c) - uy*s, uy*uz*(1-c) + ux*s ,uz*uz +(1.-uz*uz)*c , 0., 0., 0., 0., 0., _teta ); }
Projectile spawnProjectile(Vec3Df direction) { Vec3Df spawnPos = character.getAngleRefPos(); direction.normalize(); spawnPos += direction * character.getArmRadius(); Projectile projectile = Projectile(spawnPos, direction); projectile.movementSpeed = 3.0; projectile.width = 0.5; projectile.height = 0.5; projectiles.push_back(projectile); return projectile; }
void Scene::buildOriginalScene2 () { Mesh groundMesh; groundMesh.loadOFF ("models/ground.off"); groundMesh.scale(Vec3Df(20.f, 25.f, 1.f)); Material groundMat; Object ground (groundMesh, groundMat); ground.setTrans(Vec3Df(0.f, -15.f, 0.f)); objects.push_back (ground); Mesh killerooMesh; killerooMesh.loadOFF ("models/killeroo.off"); killerooMesh.scale(0.3f); killerooMesh.rotate(0); killerooMesh.rotate(0); killerooMesh.rotate(0); killerooMesh.rotate(2); killerooMesh.rotate(2); Material killerooMat (1.f, 1.f, 2.f, 0.f, Vec3Df (0.1f, .6f, 0.5f)); Object killeroo (killerooMesh, killerooMat); killeroo.setTrans (Vec3Df (0., 29.f, 4.f)); objects.push_back (killeroo); float stepX = 2.2f; float stepY = 2.2f; float offsetX = -2.8f; float offsetY = 3.f; for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { Mesh ramMesh; ramMesh.loadOFF ("models/ram.off"); Material ramMat (1.f, 1.f, 2.f, 0.f, Vec3Df (1.f, .6f, .2f)); Object ram (ramMesh, ramMat); float randX = (rand()%100)/100.f - 0.5f; float randY = (rand()%100)/100.f - 0.5f; ram.setTrans (Vec3Df (offsetX + i*stepX + randX, offsetY + j*stepY + randY, 0.f)); objects.push_back (ram); } } Vec3Df lightPos(Vec3Df (2.0f, 25.0f, 15.0f)); Vec3Df dir = -lightPos; dir.normalize(); Light l0 (lightPos , dir, 2.f, Vec3Df (1.0f, 1.0f, 1.0f), 1.0f); lights.push_back (l0); }
bool Plane::intersect(const Vec3Df& origin, const Vec3Df& dir, Vec3Df& new_origin, Vec3Df& normal) { normal = _coeff; normal.normalize(); float denom = Vec3Df::dotProduct(dir,normal); if (denom > -EPSILON && denom < EPSILON) return false; // Calculate term t in the expressen 'p = o + tD' float t = Vec3Df::dotProduct(_origin - origin, normal) / denom; if (t < EPSILON) return false; new_origin = origin + t * dir; return true; }
void Mesh::draw(){ glBegin(GL_TRIANGLES); for (int i=0;i<triangles.size();++i) { Vec3Df edge01 = vertices[triangles[i].v[1]].p - vertices[triangles[i].v[0]].p; Vec3Df edge02 = vertices[triangles[i].v[2]].p - vertices[triangles[i].v[0]].p; Vec3Df n = Vec3Df::crossProduct (edge01, edge02); n.normalize (); glNormal3f(n[0], n[1], n[2]); for(int v = 0; v < 3 ; v++){ glVertex3f(vertices[triangles[i].v[v]].p[0], vertices[triangles[i].v[v]].p[1] , vertices[triangles[i].v[v]].p[2]); } } glEnd(); }
/************************************************************ * Fonctions de calcul des normales pour chaque sommet ************************************************************/ void Mesh::computeVertexNormals () { //initialisation des normales des vertex for (unsigned int i = 0; i < vertices.size (); i++) vertices[i].n = Vec3Df (0.0, 0.0, 0.0); //Somme des normales du 1 voisinage du vertex for (unsigned int i = 0; i < triangles.size (); i++) { Vec3Df edge01 = vertices[triangles[i].v[1]].p - vertices[triangles[i].v[0]].p; Vec3Df edge02 = vertices[triangles[i].v[2]].p - vertices[triangles[i].v[0]].p; Vec3Df n = Vec3Df::crossProduct (edge01, edge02); n.normalize (); for (unsigned int j = 0; j < 3; j++) vertices[triangles[i].v[j]].n += n; } //Normalisation for (unsigned int i = 0; i < vertices.size (); i++) vertices[i].n.normalize (); }
void Mesh::draw() { glBegin(GL_TRIANGLES); for (unsigned int i = 0;i<triangles.size();++i) { unsigned int triMat = triangleMaterials.at(i); Vec3Df col = this->materials.at(triMat).Kd(); glColor3fv(col.pointer()); Vec3Df edge01 = vertices[triangles[i].v[1]].p - vertices[triangles[i].v[0]].p; Vec3Df edge02 = vertices[triangles[i].v[2]].p - vertices[triangles[i].v[0]].p; Vec3Df n = Vec3Df::crossProduct(edge01, edge02); n.normalize(); glNormal3f(n[0], n[1], n[2]); for (int v = 0; v < 3; v++) { glVertex3f(vertices[triangles[i].v[v]].p[0], vertices[triangles[i].v[v]].p[1], vertices[triangles[i].v[v]].p[2]); } } glEnd(); }
void GridAARayIterator::raysForPixel(int i, int j, std::vector<Ray>& res) { res.clear(); float tanX = tan (_fieldOfView)*_aspectRatio; float tanY = tan (_fieldOfView); for (int k = 0; k < gridSize; k++) { for(int l = 0; l < gridSize; l++) { Vec3Df stepX = (float (k+gridSize*i) - gridSize*_screenWidth/2.f)/(gridSize * _screenWidth) * tanX * _rightVector; Vec3Df stepY = (float (l+gridSize*j) - gridSize*_screenHeight/2.f)/(gridSize * _screenHeight) * tanY * _upVector; Vec3Df step = stepX + stepY; Vec3Df dir = _direction + step; dir.normalize (); res.push_back(Ray(_camPos, dir)); } } }
void draw () { //On récupère la matrice objet monde GLfloat modl[16]; glGetFloatv( GL_MODELVIEW_MATRIX, modl ); GLfloat lightPos[4]; glGetLightfv(GL_LIGHT1, GL_POSITION, lightPos); //Vec3Df lightPosition() const vector<Vertex> & V = mesh.V; const vector<Triangle> & T = mesh.T; glBegin (GL_TRIANGLES); for (unsigned int i = 0; i < T.size (); i++) { /*if(i < (unsigned int)T.size()/2){ glColor3ub(255, 12, 4); } else{ glColor3ub(1, 12, 200); }*/ if (polygonMode != Gouraud) { Vec3Df e01 = V[T[i].v[1]].p - V[T[i].v[0]].p; Vec3Df e02 = V[T[i].v[2]].p - V[T[i].v[0]].p; Vec3Df n = Vec3Df::crossProduct (e01, e02); n.normalize (); glNormal3f (n[0], n[1], n[2]); //glColorMaterial(GLenum face, GLenum mode) //modl.V[T[i].v] } //glGetFloatv(GLenum pname, GLfloat *params) for (unsigned int j = 0; j < 3; j++) { const Vertex & v = V[T[i].v[j]]; if (polygonMode == Gouraud) glNormal3f (v.n[0], v.n[1], v.n[2]); glVertex3f (v.p[0], v.p[1], v.p[2]); } } glEnd (); }
/************************************************************ * Normal calculations ************************************************************/ void Mesh::computeVertexNormals() { for (unsigned int i = 0; i < vertices.size(); i++) vertices[i].n = Vec3Df(0.0, 0.0, 0.0); //Sum up neighboring normals for (unsigned int i = 0; i < triangles.size(); i++) { Vec3Df edge01 = vertices[triangles[i].v[1]].p - vertices[triangles[i].v[0]].p; Vec3Df edge02 = vertices[triangles[i].v[2]].p - vertices[triangles[i].v[0]].p; Vec3Df n = Vec3Df::crossProduct(edge01, edge02); n.normalize(); //triangles[i].normal = new Vec3Df(n.p[0], n.p[1], n.p[2]); for (unsigned int j = 0; j < 3; j++) vertices[triangles[i].v[j]].n += n; } //Normalize for (unsigned int i = 0; i < vertices.size(); i++) vertices[i].n.normalize(); }
void Mesh::recomputeNormals () { for (unsigned int i = 0; i < V.size (); i++) V[i].n = Vec3Df (0.0, 0.0, 0.0); for (unsigned int i = 0; i < T.size (); i++) { Vec3Df e01 = V[T[i].v[1]].p - V[T[i].v[0]].p; Vec3Df e02 = V[T[i].v[2]].p - V[T[i].v[0]].p; if(ponderate_normal) { Vec3Df e12 = V[T[i].v[2]].p - V[T[i].v[1]].p; e01.normalize(); e02.normalize(); e12.normalize(); Vec3Df n[3] = { Vec3Df::crossProduct (e01, e02), Vec3Df::crossProduct (e12,-e01), Vec3Df::crossProduct (-e02,-e12) }; float angles[3] = { acos(Vec3Df::dotProduct(e01, e02)), acos(Vec3Df::dotProduct(-e01, e12)), acos(Vec3Df::dotProduct(-e12, -e02)), }; for (unsigned int j = 0; j < 3; j++) { n[j].normalize(); V[T[i].v[j]].n += angles[j]* n[j]; } } else { Vec3Df n = Vec3Df::crossProduct (e01, e02); n.normalize (); for (unsigned int j = 0; j < 3; j++) V[T[i].v[j]].n += n; } } for (unsigned int i = 0; i < V.size (); i++) V[i].n.normalize (); }
Vec3Df Material::genColor (const Vec3Df & camPos, Ray *intersectingRay, const std::vector<Light> & lights, Brdf::Type type) const { const Vertex &closestIntersection = intersectingRay->getIntersection(); float ambientOcclusionContribution = (type & Brdf::Ambient)? controller->getRayTracer()->getAmbientOcclusion(closestIntersection): 0.f; Vec3Df usedColor = colorTexture->getColor(intersectingRay); const Brdf brdf(lights, usedColor, controller->getRayTracer()->getBackgroundColor(), diffuse, specular, ambientOcclusionContribution, alpha); Vec3Df normal = normalTexture->getNormal(intersectingRay); if(glossyRatio == 0) return brdf(closestIntersection.getPos(), normal, camPos, type); /* Glossy Material */ const Vec3Df spec = brdf(closestIntersection.getPos(), normal, camPos, Brdf::Type(Brdf::Specular&type)); const Vec3Df glossyColor = glossyRatio<1? brdf(closestIntersection.getPos(), normal, camPos, Brdf::Type((Brdf::Ambient|Brdf::Diffuse)&type)): Vec3Df(); const Vec3Df & pos = closestIntersection.getPos(); Vec3Df dir = (camPos-pos).reflect(normal); dir.normalize(); const Vec3Df reflectedColor = controller->getRayTracer()->getColor(dir, pos, false); return spec + Vec3Df::interpolate(glossyColor, reflectedColor, glossyRatio); }
void GLViewer::mousePressEvent(QMouseEvent * event) { const WindowModel *windowModel = controller->getWindowModel(); if (windowModel->isDragEnabled()) { float fov, ar; float screenWidth; float screenHeight; Vec3Df camPos; Vec3Df viewDirection; Vec3Df upVector; Vec3Df rightVector; getCameraInformation(fov, ar, screenWidth, screenHeight, camPos, viewDirection, upVector, rightVector); float tanX = tan(fov)*ar; float tanY = tan(fov); Vec3Df stepX = (float (event->x()) - screenWidth/2.f)/screenWidth * tanX * rightVector; Vec3Df stepY = (float (screenHeight-event->y()) - screenHeight/2.f)/screenHeight * tanY * upVector; Vec3Df step = stepX + stepY; Vec3Df dir = viewDirection + step; float distanceCameraScreen = dir.getLength(); dir.normalize(); Ray ray; if (controller->getRayTracer()->intersect(dir, camPos, ray)) { Object *o=ray.getIntersectedObject(); QPoint p = event->globalPos(); Vec3Df oPos = o->getTrans(); float ratio = distanceCameraScreen/sqrt(ray.getIntersectionDistance()); controller->viewerStartsDragging(o, oPos, p, ratio); } } if (!controller->getWindowModel()->isRealTime()) { controller->viewerSetDisplayMode(WindowModel::OpenGLDisplayMode); } else { controller->forceThreadUpdate(); } QGLViewer::mousePressEvent(event); }
QImage RayTracer::render (const Vec3Df & camPos, const Vec3Df & direction, const Vec3Df & upVector, const Vec3Df & rightVector, float fieldOfView, float aspectRatio, unsigned int screenWidth, unsigned int screenHeight) { QImage image (QSize (screenWidth, screenHeight), QImage::Format_RGB888); Scene * scene = Scene::getInstance (); std::vector<Light> lights = scene->getLights(); Light light = lights[0]; QProgressDialog progressDialog ("Raytracing...", "Cancel", 0, 100); progressDialog.show (); //#pragma omp parallel for for (unsigned int i = 0; i < screenWidth; i++) { progressDialog.setValue ((100*i)/screenWidth); for (unsigned int j = 0; j < screenHeight; j++) { float tanX = tan (fieldOfView)*aspectRatio; float tanY = tan (fieldOfView); //Nombre de découpe par dimension du pixel (Antialiasing) int aliaNb = 2; if(!activeAA) aliaNb=1; aliaNb++; Vec3Df c (backgroundColor); Vec3Df tempc(0.,0.,0.); for(int pixi=1; pixi<aliaNb; pixi++){ for(int pixj=1; pixj<aliaNb; pixj++){ Vec3Df stepX = (float (i)-0.5+float(pixi)/float(aliaNb) - screenWidth/2.f)/screenWidth * tanX * rightVector; Vec3Df stepY = (float (j)-0.5+float(pixj)/float(aliaNb) - screenHeight/2.f)/screenHeight * tanY * upVector; Vec3Df step = stepX + stepY; Vec3Df dir = direction + step; dir.normalize (); Vec3Df intersectionPoint; Vec3Df IntersPointNormal; float occlusion; int idObj = getIntersectionPoint(camPos,dir,intersectionPoint,IntersPointNormal,occlusion); if(idObj>=0) { tempc += Brdf(camPos, IntersPointNormal, idObj,intersectionPoint,occlusion,0)/std::pow(aliaNb-1,2); c=tempc; } } } image.setPixel (i, j, qRgb (clamp (c[0], 0, 255), clamp (c[1], 0, 255), clamp (c[2], 0, 255))); } } progressDialog.setValue (100); return image; }
void GLWidget :: drawMesh() { const vector<Vertex> & V = mesh->getVertices(); const vector<Triangle> & T = mesh->getTriangles(); if (mode == renderFill || mode == renderFillWire) { glEnable( GL_POLYGON_OFFSET_FILL ); glPolygonOffset( 1., 1. ); glBegin (GL_TRIANGLES); for (unsigned int i = 0; i < T.size (); i++) { const Triangle & t = T[i]; for (unsigned int j = 0; j < 3; j++) { glNormalVec3Df (V[t.getVertex (j)].getNormal ()); glVertexVec3Df (V[t.getVertex (j)].getPos ()); } } glEnd (); glDisable( GL_POLYGON_OFFSET_FILL ); if (mode == renderFillWire) { glDisable(GL_LIGHTING) ; glColor4f(0., 0., 0., .25) ; glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glBegin( GL_TRIANGLES ); for (unsigned int i = 0; i < T.size (); i++) { const Triangle & t = T[i]; for (unsigned int j = 0; j < 3; j++) { glNormalVec3Df (V[t.getVertex (j)].getNormal ()); glVertexVec3Df (V[t.getVertex (j)].getPos ()); } } glEnd() ; } } else if (mode == renderLine) { glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); glBegin( GL_TRIANGLES ); for (unsigned int i = 0; i < T.size (); i++) { const Triangle & t = T[i]; for (unsigned int j = 0; j < 3; j++) { glNormalVec3Df (V[t.getVertex (j)].getNormal ()); glVertexVec3Df (V[t.getVertex (j)].getPos ()); } } glEnd() ; } else if (mode == renderFlat) { glEnable( GL_POLYGON_OFFSET_FILL ); glPolygonOffset( 1., 1. ); glBegin (GL_TRIANGLES); for (unsigned int i = 0; i < T.size (); i++) { const Triangle & t = T[i]; Vec3Df normal = Vec3Df::crossProduct (V[t.getVertex (1)].getPos () - V[t.getVertex (0)].getPos (), V[t.getVertex (2)].getPos () - V[t.getVertex (0)].getPos ()); normal.normalize (); glNormalVec3Df (normal); for (unsigned int j = 0; j < 3; j++) glVertexVec3Df (V[t.getVertex (j)].getPos ()); } glEnd (); glDisable( GL_POLYGON_OFFSET_FILL ); } }
Hit ComplexObject::intersectMesh(Vec3Df origin, Vec3Df dest) { // hit is is where we keep track of hits with backfaces // For the moment we use noHit as a symbol Hit hit = noHit; //Material that is displayed if no material is found in Mesh Material errorMat = Material(); errorMat.set_Kd(1,1,0); errorMat.set_Ka(1,1,0); errorMat.set_Ks(1,1,0); errorMat.set_Ns(96.7f); errorMat.set_illum(2); Material actualMat = errorMat; for (int i = 0; i < mesh.triangles.size(); i++) { Triangle T = mesh.triangles[i]; //now return the actual material which is defined in the mesh int materialIndex = 999; if(mesh.triangleMaterials.size()>0){ materialIndex = mesh.triangleMaterials[i]; } if(0 <= materialIndex && materialIndex < mesh.materials.size()){ actualMat = mesh.materials[materialIndex]; } // Our implementation is based on the proposed algorithm of Dan Sunday at: http://geomalgorithms.com/a06-_intersect-2.html Vertex v0 = mesh.vertices[T.v[0]]; Vertex v1 = mesh.vertices[T.v[1]]; Vertex v2 = mesh.vertices[T.v[2]]; // Edge vectors Vec3Df u = v1.p-v0.p; Vec3Df v = v2.p-v0.p; Vec3Df n = Vec3Df::crossProduct(u, v); // Normal of the triangle Vec3Df w0 = origin - v0.p; float a = -Vec3Df::dotProduct(n, w0); float b = Vec3Df::dotProduct(n, dest); // Use this as a threshold to avoid division overflow if (fabs(b) < 0.0000001) { // ray is parallel to triangle plane (either precisely on or disjoint from plane) continue; } // Get intersection point of ray with triangle plane float r = a / b; if (r < 0.01) // ray goes away from triangle { continue; } // intersect point of ray and plane Vec3Df I = origin + (r * dest); // Next up; triangle text; is I inside T? float uu, uv, vv, wu, wv, D; uu = Vec3Df::dotProduct(u, u); uv = Vec3Df::dotProduct(u, v); vv = Vec3Df::dotProduct(v, v); Vec3Df w = I - v0.p; wu = Vec3Df::dotProduct(w, u); wv = Vec3Df::dotProduct(w, v); D = uv * uv - uu * vv; // get and test parametric coords float s, t; s = (uv * wv - vv * wu) / D; if (s < 0.0 || s > 1.0) // I is outside T continue; t = (uv * wu - uu * wv) / D; if (t < 0.0 || (s + t) > 1.0) // I is outside T continue; n.normalize(); // We can now truncate the normal to length of 1 // If we get here I (the ray hitpoint) is in T (the triangle): // We check if we already found a hit before if (hit.isHit == 0) { // In that case we can just assign the current hit as the first one hit = Hit(1, I, n, actualMat); } else { // If so, we check whether this one is closer to the origin float previousDistance = (hit.hitPoint - origin).getLength(); float currentDistance = (I - origin).getLength(); // Now check if it's closer if (currentDistance < previousDistance) { // If it is then we save the current hit hit = Hit(1, I, n, actualMat); } else { // If not we discard this hit and continue looking for one which is continue; } } } return hit; }
void KDTree::Node::buildNode(const KDTree& tree, int maxDepth) { // Find the median plan Vec3Df n; if (boundingBox.getSize() == boundingBox.getWidth() ){ n = Vec3Df (boundingBox.getMax()[0] - boundingBox.getMin()[0], 0.0, 0.0); } else if (boundingBox.getSize() == boundingBox.getHeight()){ n = Vec3Df (0.0, boundingBox.getMax()[1] - boundingBox.getMin()[1], 0.0); } else{ n = Vec3Df( 0.0, 0.0, boundingBox.getMax()[2] - boundingBox.getMin()[2]); } n.normalize(); Vec3Df position = getMedianPoint(tree.getMesh(), n);; plan.n = n; plan.position = position; if (depth == maxDepth) { return; } //seperate triangles vector<int> leftIndexes, rightIndexes; for (int idx : triangleIndexes){ const Triangle& t = tree.getMesh().getTriangles()[idx]; const Vec3Df& a = tree.getMesh().getVertices()[ t.getVertex(0)].getPos(); const Vec3Df& b = tree.getMesh().getVertices()[ t.getVertex(1)].getPos(); const Vec3Df& c = tree.getMesh().getVertices()[ t.getVertex(2)].getPos(); //regarder si tous les sommets sont du même côté du plan... if ( plan.isLeft(a) && plan.isLeft(b) && plan.isLeft(c) ){ //Ils sont tous à gauche leftIndexes.push_back(idx); } else if( plan.isRight(a) && plan.isRight(b) && plan.isRight(c) ){ //Ils sont tous à droite rightIndexes.push_back(idx); } else { // Le triangle doit être ajouté des deux côtés rightIndexes.push_back(idx); leftIndexes.push_back(idx); } } if(rightIndexes == leftIndexes) return; if (triangleIndexes.size() == rightIndexes.size() || triangleIndexes.size() == leftIndexes.size()) return; if(rightIndexes.size() != 0){ right_node = new KDTree::Node(rightIndexes, depth + 1, tree); right_node->buildNode(tree, maxDepth); } if(leftIndexes.size() != 0){ left_node = new KDTree::Node(leftIndexes, depth + 1, tree); left_node->buildNode(tree, maxDepth); } }
Vec3Df RayTracer::Brdf(const Vec3Df & camPos, const Vec3Df & normal, int idObj, const Vec3Df & intersectionPoint, float occlusion, int PTRays){ Scene * scene = Scene::getInstance (); std::vector<Light> lights = scene->getLights(); Object & object = scene->getObjects()[idObj]; Vec3Df ci; for(unsigned int i =0;i<lights.size();i++) { Light light = lights[i]; Vec3Df n = normal; n.normalize(); Vec3Df wi = light.getPos() - intersectionPoint; wi.normalize(); Vec3Df w0 = (camPos-intersectionPoint); w0.normalize(); Vec3Df r = 2*(Vec3Df::dotProduct(wi,n))*n-wi; r.normalize(); float diffuse = Vec3Df::dotProduct(wi, n); float shininess = 11; float spec = pow(std::max(Vec3Df::dotProduct(r,w0),0.f),shininess); diffuse = std::max(diffuse,0.0f); Vec3Df lightColor = light.getColor(); Material material = object.getMaterial(); float matDiffuse = material.getDiffuse(); float matSpecular = material.getSpecular(); Vec3Df matDiffuseColor = material.getColor(); Vec3Df matSpecularColor = material.getColor(); Vec3Df intersectionPoint2; Vec3Df IntersPointNormal2; //Area Lighting float radius=0.3f; //Miroir if(scene->getObjects()[idObj].getRefl()>0 && activeMirror) { Vec3Df vDir= intersectionPoint-camPos; vDir.normalize(); Vec3Df planA = Vec3Df::crossProduct(n, Vec3Df::crossProduct(vDir, n)); Vec3Df newDir = Vec3Df::dotProduct(planA, vDir)*planA - Vec3Df::dotProduct(vDir, n)*n; float occ; int obj = getIntersectionPoint(intersectionPoint, newDir, intersectionPoint2, IntersPointNormal2, occ); if(obj>-1) { if(activeShadow) { if(getIntersectionPoint(intersectionPoint,-intersectionPoint+light.getPos(),intersectionPoint2,IntersPointNormal2)==-1) { ci += Brdf(intersectionPoint,IntersPointNormal2,obj,intersectionPoint2,occ,0)*scene->getObjects()[idObj].getRefl(); } } else ci += Brdf(intersectionPoint,IntersPointNormal2,obj,intersectionPoint2,occ,0)*scene->getObjects()[idObj].getRefl(); } } //PathTracing if(activePT) { if(PTRays < depthPT) { for(int h=0; h< nbRayPT; h++) { Vec3Df n1; Vec3Df n2; normal.getTwoOrthogonals(n1,n2); float a = ((float)std::rand())/((float)RAND_MAX); float b = ((float)std::rand())/((float)RAND_MAX)*2.-1.; float c = ((float)std::rand())/((float)RAND_MAX)*2.-1.; Vec3Df dir = normal*a+n1*b+n2*c; dir.normalize(); int objPT = getIntersectionPoint(intersectionPoint,dir,intersectionPoint2,IntersPointNormal2); ci+=Brdf(intersectionPoint,IntersPointNormal2,objPT,intersectionPoint2,0.,PTRays+1)/(nbRayPT*depthPT); } } //si pt<pt_max //lancer plein de rayons //contribution+=brdf(pt+1) } if(scene->getObjects()[idObj].getRefl()<1.0 || true) { if(nbRayShadow>0 && activeShadow) for(int p = 0;p<nbRayShadow;p++) { float a = ((float)std::rand())/((float)RAND_MAX)*2.-1.; float b = ((float)std::rand())/((float)RAND_MAX)*2.-1.; float c = ((float)std::rand())/((float)RAND_MAX)*2.-1.; float sum = a+b+c; a=a/sum*radius; b=b/sum*radius; c=c/sum*radius; Vec3Df lightposbis; lightposbis[0]=light.getPos()[0]+a; lightposbis[1]=light.getPos()[1]+b; lightposbis[2]=light.getPos()[2]+c; if(getIntersectionPoint(intersectionPoint,-intersectionPoint+lightposbis,intersectionPoint2,IntersPointNormal2)==-1) { ci += (((matDiffuse * diffuse * matDiffuseColor) +( matSpecular * spec * matSpecularColor*0.5))*lightColor)*255/nbRayShadow; } } else if(activeShadow) { if(getIntersectionPoint(intersectionPoint,-intersectionPoint+light.getPos(),intersectionPoint2,IntersPointNormal2)==-1) { ci += (((matDiffuse * diffuse * matDiffuseColor) +( matSpecular * spec * matSpecularColor*0.5))*lightColor)*255; } } else //sans ombre { ci += (((matDiffuse * diffuse * matDiffuseColor) +( matSpecular * spec * matSpecularColor*0.5))*lightColor)*255; } //ci += (((matDiffuse * diffuse * matDiffuseColor) +( matSpecular * spec * matSpecularColor*0.5))*lightColor)*255/nbrayshadow; } } if(activeAO) return ci*(1.f-occlusion); else return ci; }