//---------------------------------------------------------------------------------------------------------------------- float vecAngle(const ngl::Vec3 &_vec1, const ngl::Vec3 &_vec2) { // calculate the angle between two vectors using the dot product float angle; angle=_vec1.dot(_vec2)/_vec1.length()*_vec2.length(); angle=ngl::degrees(acos(angle)); return angle; }
Ray::Ray(ngl::Vec3 _origin, ngl::Vec3 _direction) { m_origin = _origin; // check that it is unit length, if not, normalize if (_direction.length() > 1.1 || _direction.length() < 0.9) {_direction.normalize();} m_direction = _direction; }
//---------------------------------------------------------------------------------------------------------------------- ngl::Vec3 lenClamp(ngl::Vec3 io_inVec, const float &_maxLen) { // check if given vector is longer than the given maximum if(io_inVec.length()>_maxLen) { // normalize and multiply by the maximum length to clamp io_inVec.normalize(); io_inVec=io_inVec*_maxLen; return io_inVec; } return io_inVec; }
//add wall function void Scene::addWall(ngl::Vec3 io_point, float io_size, ngl::Vec3 io_normal, bool io_draw) { //OctreeAbstract reference Wall *newWall = new Wall; io_normal.normalize(); newWall->centre = io_point; newWall->size = io_size; newWall->a = io_normal.m_x; newWall->b = io_normal.m_y; newWall->c = io_normal.m_z; newWall->d = -(newWall->a * io_point.m_x + newWall->b * io_point.m_y + newWall->c * io_point.m_z); newWall->draw_flag = io_draw; m_walls.push_back(newWall); }
ngl::Mat4 Bvh::getRotationFromZ(ngl::Vec3 _vec) const { ngl::Mat4 rotM; float x, y, z; // rotate negative z axis to _vec direction _vec.normalize(); ngl::Vec3 nz(0,0,-1); float angle = acos(_vec.dot(nz)); ngl::Vec3 norm = _vec.cross(nz); if(norm.length()<= 0.0001) { x= z = 0.0; y = 1.0; } else { norm.normalize(); x = norm.m_x; y = norm.m_y; z = norm.m_z; } // Axis and Angle matrix rotation see // http://en.wikipedia.org/wiki/Rotation_matrix for more details float c = cos(angle); float s = sin(angle); float C=1-c; float xs = x*s; float ys = y*s; float zs = z*s; float xC = x*C; float yC = y*C; float zC = z*C; float xyC = x*yC; float yzC = y*zC; float zxC = z*xC; rotM.m_m[0][0]=x*xC+c; rotM.m_m[0][1]= xyC-zs; rotM.m_m[0][2]= zxC+ys; rotM.m_m[1][0]=xyC+zs; rotM.m_m[1][1]=y*yC+c; rotM.m_m[1][2]= yzC-xs; rotM.m_m[2][0]=zxC-ys; rotM.m_m[2][1]=yzC+xs; rotM.m_m[2][2]=z*zC+c; return rotM; }
void NGLScene::paintGL() { if(testangle==89) vary=-1; if(testangle==-89) vary=1; //This bit has been MOVED TO TIMER EVENT for more 'slow-motion' control // testangle+=vary; std::cout<<testangle<<std::endl; ngl::Vec3 v1(-5+15*sin((testangle)*(M_PI/180))-2,-5+15*sin((testangle)*(M_PI/180)), 4*sin((testangle)*(M_PI/180))-2); ngl::Vec3 v2(-4,0.01,-5+15*sin((testangle)*(M_PI/180)));//transform the triangle vao to 2,2,0 ngl::Vec3 v2NonNormalized=v2; ngl::Vec3 v1NonNormalized=v1; // clear the screen and depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Rotation based on the mouse position for our global transform // Rotation based on the mouse position for our global // transform ngl::Mat4 rotX; ngl::Mat4 rotY; // create the rotation matrices rotX.rotateX(m_spinXFace); rotY.rotateY(m_spinYFace); // multiply the rotations m_mouseGlobalTX=rotY*rotX; // add the translations m_mouseGlobalTX.m_m[3][0] = m_modelPos.m_x; m_mouseGlobalTX.m_m[3][1] = m_modelPos.m_y; m_mouseGlobalTX.m_m[3][2] = m_modelPos.m_z; ngl::ShaderLib *shader=ngl::ShaderLib::instance(); (*shader)["Phong"]->use(); ngl::Material m(ngl::STDMAT::PEWTER); // load our material values to the shader into the structure material (see Vertex shader) m.loadToShader("material"); ngl::Mat4 MV; ngl::Mat4 MVP; ngl::Mat3 normalMatrix; ngl::Mat4 M; //********* m_transform.reset(); //draw box { m_transform.setPosition(v1NonNormalized); M=m_transform.getMatrix()*m_mouseGlobalTX; MV= M*m_cam->getViewMatrix(); MVP= M*m_cam->getVPMatrix(); normalMatrix=MV; normalMatrix.inverse(); shader->setShaderParamFromMat4("MV",MV); shader->setShaderParamFromMat4("MVP",MVP); shader->setShaderParamFromMat3("normalMatrix",normalMatrix); shader->setShaderParamFromMat4("M",M); //ngl::VAOPrimitives::instance()->draw("cube"); m_vao2->bind(); m_vao2->draw(); m_vao2->unbind(); } v1.normalize(); v2.normalize(); float angle = /*atan2(v1.m_y,v1.m_x) - atan2(v2.m_y,v2.m_x);//*/acos(v1.dot(v2)); ngl::Vec3 rotationAxis = v1.cross(v2); rotationAxis.normalize(); // ngl::Quaternion q ; // q.fromAxisAngle(rotationAxis,angle); ngl::Mat4 s,rotateMat,translateMat; s=1; //Use either RotationBetweenVectors or matrixFromAxisAngle rotateMat=RotationBetweenVectors(v2,v1).toMat4(); //rotateMat=matrixFromAxisAngle(rotationAxis,angle);//q.toMat4(); //calculate euler angles from axis-angle // double heading,attitude,bank; // toEuler(rotationAxis.m_x, rotationAxis.m_y, rotationAxis.m_z, angle, heading, attitude, bank); // m_transform.reset(); // std::cout<<bank*(180/M_PI)<<","<<heading*(180/M_PI)<<","<<attitude*(180/M_PI)<<","<<std::endl; // m_transform.setRotation(bank*(180/M_PI),heading*(180/M_PI),attitude*(180/M_PI)); // r= m_transform.getMatrix(); m_transform.reset(); m_transform.setPosition(v2NonNormalized); translateMat= m_transform.getMatrix(); ngl::Mat4 modelmatrix=s*rotateMat*translateMat; m_transform.reset(); //draw triangle { // load our material values to the shader into the structure material (see Vertex shader) m.set(ngl::STDMAT::BRONZE); m.loadToShader("material"); M=/*m_transform.getMatrix()*/ modelmatrix*m_mouseGlobalTX; MV= M*m_cam->getViewMatrix(); MVP= M*m_cam->getVPMatrix(); normalMatrix=MV; normalMatrix.inverse(); shader->setShaderParamFromMat4("MV",MV); shader->setShaderParamFromMat4("MVP",MVP); shader->setShaderParamFromMat3("normalMatrix",normalMatrix); shader->setShaderParamFromMat4("M",M); // ngl::VAOPrimitives::instance()->draw("cube"); m_vao->bind(); m_vao->draw(); m_vao->unbind(); } // //draw the tip-cube of the triangle // { // m.set(ngl::GOLD); // // load our material values to the shader into the structure material (see Vertex shader) // m.loadToShader("material"); // translateMat=1; // // rotateMat=1; // // scaleMat=1; // //not working // // ngl::Vec3 v=v1.cross(v2); // // float c=v1.dot(v2); // // float h=1-c/v.dot(v); // // rotateMat=ngl::Mat4(c*h*v.m_x*v.m_x, h*v.m_x*v.m_y-v.m_z, h*v.m_x*v.m_z+v.m_y, 1, // // h*v.m_x*v.m_y+v.m_z, c+h*v.m_y*v.m_y, h*v.m_y*v.m_z-v.m_x, 1, // // h*v.m_x*v.m_z-v.m_y, h*v.m_y*v.m_z+v.m_x, c+h*v.m_z*v.m_z, 1, // // 0 , 0 , 0, 1); // // rotateMat.transpose(); // //not working // // ngl::Mat4 trs=m_transform.getMatrix(); // // rotateMat=matrixFromAxisAngle(rotationAxis,angle); // // translateMat.translate(-v2NonNormalized.m_x,-(v2NonNormalized.m_y),-v2NonNormalized.m_z); // //Based on [R] = [T].inverse * [R0] * [T] //http://www.euclideanspace.com/maths/geometry/affine/aroundPoint/ // /* // translate the arbitrary point to the origin (subtract P which is translate by -Px,-Py,-Pz) // rotate about the origin (can use 3×3 matrix R0) // then translate back. (add P which is translate by +Px,+Py,+Pz) // */ // translateMat.inverse();//step 1.. translate pointToRotate to origin // //(rotation matrix) - same as the triangle's "rotateMat" //step 2 rotate.. // translateMat2.translate(v2NonNormalized.m_x,(v2NonNormalized.m_y),v2NonNormalized.m_z);//step3 ..translate pointToRotate back to its original position in 3d space // std::cout<<translateMat2.m_30<<","<<translateMat2.m_31<<","<<translateMat2.m_32<<std::endl; // // std::cout<<"mat Matrix():\n"<<" "<<rotateMat.m_00<<" "<< rotateMat.m_01<<" "<<rotateMat.m_02 <<" "<<rotateMat.m_03<<" "<< // // rotateMat.m_10<<" "<< rotateMat.m_11<<" "<<rotateMat.m_12 <<" "<<rotateMat.m_13<<" "<< rotateMat.m_20<<" "<< rotateMat.m_21<<" "<<rotateMat.m_22 <<" "<<rotateMat.m_23<<" "<< rotateMat.m_30<<" "<< // // rotateMat.m_31<<" "<<rotateMat.m_32 <<" "<<rotateMat.m_33<<" "<<std::endl; // // std::cout<<angle<<std::endl; // //place one one sphere-primitive in the tip of the triangle, but we translate first and then rotate (this effectively shows the "trajectory of the triangle rotation") // /* // * In order to calculate the rotation about any arbitrary point we need to calculate its new rotation and translation. // * In other words rotation about a point is an 'proper' isometry transformation' which means that it has a linear // * and a rotational component. // * [resulting transform] = [+Px,+Py,+Pz] * [rotation] * [-Px,-Py,-Pz] // */ // M= translateMat*rotateMat*translateMat2 /**scaleMat*/; //in ngl multiplication happens from left to right // M= M*m_mouseGlobalTX; // MV= M*m_cam->getViewMatrix(); // MVP= M*m_cam->getVPMatrix(); // normalMatrix=MV; // normalMatrix.inverse(); // shader->setShaderParamFromMat4("MV",MV); // shader->setShaderParamFromMat4("MVP",MVP); // shader->setShaderParamFromMat3("normalMatrix",normalMatrix); // shader->setShaderParamFromMat4("M",M); //// ngl::VAOPrimitives::instance()->createSphere("mysphere",0.1,10); // ngl::VAOPrimitives::instance()->draw("cube"); // } // //*********NOW********* STEP 2 // //Calculate rotation vector from 2nd to 1st triangle // //then // m.set(ngl::BRONZE); // // load our material values to the shader into the structure material (see Vertex shader) // m.loadToShader("material"); // //... rotate and draw the 2nd triangle as well // m_transform.reset(); // { ////------------------------------------------------------------------------------------------------------------------------------------ ////------------------------------------------------------------------------------------------------------------------------------------ ///************** ////not working //// eulerAngles.m_x = atan2( rotationAxis.m_y, rotationAxis.m_z ); //// if (rotationAxis.m_z >= 0) { //// eulerAngles.m_y = -atan2( rotationAxis.m_x * cos(eulerAngles.m_x), rotationAxis.m_z ); //// }else{ //// eulerAngles.m_y = atan2( rotationAxis.m_x * cos(eulerAngles.m_x), -rotationAxis.m_z ); //// } //// eulerAngles.m_z = atan2( cos(eulerAngles.m_x), sin(eulerAngles.m_x) * sin(eulerAngles.m_y) ); // // //// eulerAngles.m_x= 0; //// eulerAngles.m_y = atan2((v1-v2).m_x, (v1-v2).m_z); //// float padj = sqrt(pow((v1-v2).m_x, 2) + pow((v1-v2).m_z, 2)); //// eulerAngles.m_y = atan2(padj, (v1-v2).m_y) ; // **************/ // //convert axis anle to euler angles //// toEuler(rotationAxis.m_x, rotationAxis.m_y, rotationAxis.m_z, angle); //// m_transform.setRotation(eulerAngles.m_x*(180/M_PI),eulerAngles.m_y*(180/M_PI),eulerAngles.m_z*(180/M_PI)); // ngl::Mat4 trs=m_transform.getMatrix(); ////------------------------------------------------------------------------------------------------------------------------------------ ////------------------------------------------------------------------------------------------------------------------------------------ // //The following work with ngl::Transformation too, as well as with individual matrices // // m_transform.reset(); // // if(testangle<360) // // testangle++; // // else // // { // // testangle=0; // // } // // m_transform.setRotation(testangle,0,0); // //Rotate based where v1 is (make v2NonNormalized(triangle) to point towards v1-cube) // rotateMat=matrixFromAxisAngle(rotationAxis,angle);//m_transform.getMatrix(); // translateMat.translate(v2NonNormalized.m_x,v2NonNormalized.m_y,v2NonNormalized.m_z); //// std::cout<<"mat Matrix():\n"<<" "<<rotateMat.m_00<<" "<< rotateMat.m_01<<" "<<rotateMat.m_02 <<" "<<rotateMat.m_03<<" "<< //// rotateMat.m_10<<" "<< rotateMat.m_11<<" "<<rotateMat.m_12 <<" "<<rotateMat.m_13<<" "<< rotateMat.m_20<<" "<< rotateMat.m_21<<" "<<rotateMat.m_22 <<" "<<rotateMat.m_23<<" "<< rotateMat.m_30<<" "<< //// rotateMat.m_31<<" "<<rotateMat.m_32 <<" "<<rotateMat.m_33<<" "<<std::endl; //// std::cout<<angle<<std::endl; ////not quite working // float norm_u_norm_v = sqrt(v2NonNormalized.lengthSquared() * v1NonNormalized.lengthSquared()); // ngl::Vec3 w = v2.cross(v1); // ngl::Quaternion q = ngl::Quaternion(norm_u_norm_v + v2NonNormalized.dot(v1NonNormalized), w.m_x, w.m_y, w.m_z); // q.normalise(); // rotateMat=q.toMat4(); ////not quite working either // rotateMat=ngl::lookAt(v2NonNormalized,v1NonNormalized,ngl::Vec3(0,1,0)); // M=rotateMat*translateMat;//left to right multiplication in ngl (first rotate then translate) // M=/*m_transform.getMatrix()*/ M/* trs*/*m_mouseGlobalTX; // MV= M*m_cam->getViewMatrix(); // MVP= M*m_cam->getVPMatrix(); // normalMatrix=MV; // normalMatrix.inverse(); // shader->setShaderParamFromMat4("MV",MV); // shader->setShaderParamFromMat4("MVP",MVP); // shader->setShaderParamFromMat3("normalMatrix",normalMatrix); // shader->setShaderParamFromMat4("M",M); // m_vao->bind(); // m_vao->draw();//draw triangle now // m_vao->unbind(); // } // //*********NOW********* STEP 3 // //draw the tip-cube of the triangle //{ // m.set(ngl::GOLD); // // load our material values to the shader into the structure material (see Vertex shader) // m.loadToShader("material"); // translateMat=1; //// rotateMat=1; //// scaleMat=1; ////not working //// ngl::Vec3 v=v1.cross(v2); //// float c=v1.dot(v2); //// float h=1-c/v.dot(v); //// rotateMat=ngl::Mat4(c*h*v.m_x*v.m_x, h*v.m_x*v.m_y-v.m_z, h*v.m_x*v.m_z+v.m_y, 1, //// h*v.m_x*v.m_y+v.m_z, c+h*v.m_y*v.m_y, h*v.m_y*v.m_z-v.m_x, 1, //// h*v.m_x*v.m_z-v.m_y, h*v.m_y*v.m_z+v.m_x, c+h*v.m_z*v.m_z, 1, //// 0 , 0 , 0, 1); //// rotateMat.transpose(); ////not working //// ngl::Mat4 trs=m_transform.getMatrix(); //// rotateMat=matrixFromAxisAngle(rotationAxis,angle); //// translateMat.translate(-v2NonNormalized.m_x,-(v2NonNormalized.m_y),-v2NonNormalized.m_z); // //Based on [R] = [T].inverse * [R0] * [T] //http://www.euclideanspace.com/maths/geometry/affine/aroundPoint/ // /* // translate the arbitrary point to the origin (subtract P which is translate by -Px,-Py,-Pz) // rotate about the origin (can use 3×3 matrix R0) // then translate back. (add P which is translate by +Px,+Py,+Pz) // */ // translateMat.inverse();//step 1.. translate pointToRotate to origin // //(rotation matrix) - same as the triangle's "rotateMat" //step 2 rotate.. // translateMat2.translate(v2NonNormalized.m_x,(v2NonNormalized.m_y),v2NonNormalized.m_z);//step3 ..translate pointToRotate back to its original position in 3d space // std::cout<<translateMat2.m_30<<","<<translateMat2.m_31<<","<<translateMat2.m_32<<std::endl; //// std::cout<<"mat Matrix():\n"<<" "<<rotateMat.m_00<<" "<< rotateMat.m_01<<" "<<rotateMat.m_02 <<" "<<rotateMat.m_03<<" "<< //// rotateMat.m_10<<" "<< rotateMat.m_11<<" "<<rotateMat.m_12 <<" "<<rotateMat.m_13<<" "<< rotateMat.m_20<<" "<< rotateMat.m_21<<" "<<rotateMat.m_22 <<" "<<rotateMat.m_23<<" "<< rotateMat.m_30<<" "<< //// rotateMat.m_31<<" "<<rotateMat.m_32 <<" "<<rotateMat.m_33<<" "<<std::endl; //// std::cout<<angle<<std::endl; // //place one one sphere-primitive in the tip of the triangle, but we translate first and then rotate (this effectively shows the "trajectory of the triangle rotation") // /* // * In order to calculate the rotation about any arbitrary point we need to calculate its new rotation and translation. // * In other words rotation about a point is an 'proper' isometry transformation' which means that it has a linear // * and a rotational component. // * [resulting transform] = [+Px,+Py,+Pz] * [rotation] * [-Px,-Py,-Pz] // */ // M= translateMat*rotateMat*translateMat2 /**scaleMat*/; //in ngl multiplication happens from left to right // M= M*m_mouseGlobalTX; // MV= M*m_cam->getViewMatrix(); // MVP= M*m_cam->getVPMatrix(); // normalMatrix=MV; // normalMatrix.inverse(); // shader->setShaderParamFromMat4("MV",MV); // shader->setShaderParamFromMat4("MVP",MVP); // shader->setShaderParamFromMat3("normalMatrix",normalMatrix); // shader->setShaderParamFromMat4("M",M); // ngl::VAOPrimitives::instance()->createSphere("mysphere",0.1,10); // ngl::VAOPrimitives::instance()->draw("cube"); //} }
//return shortest arc quaternion that rotates start to dest ngl::Quaternion NGLScene::RotationBetweenVectors(ngl::Vec3 start, ngl::Vec3 dest){ ngl::Quaternion q; (start).normalize(); (dest).normalize(); float cosTheta = start.dot(dest); ngl::Vec3 rotationAxis; /** * https://bitbucket.org/sinbad/ogre/src/9db75e3ba05c/OgreMain/include/OgreVector3.h?fileviewer=file-view-default#cl-651 * * Gets the shortest arc quaternion to rotate this vector to the destination vector. @remarks If you call this with a dest vector that is close to the inverse of this vector, we will rotate 180 degrees around the 'fallbackAxis' (if specified, or a generated axis if not) since in this case ANY axis of rotation is valid. */ if (cosTheta >= 1.0f)//same vectors { return ngl::Quaternion();//identity quaternion } if (cosTheta < (1e-6f - 1.0f)) { // Generate an axis rotationAxis = ngl::Vec3 (0.0f, 0.0f, 1.0f).cross( start); if (rotationAxis.length()==0) // pick another if colinear rotationAxis = ngl::Vec3 (0.0f, 1.0f, 0.0f).cross( start); rotationAxis.normalize(); q.fromAxisAngle(rotationAxis,180.0f); } // if (cosTheta < -1 + 0.001f) // { // // special case when vectors in opposite directions: // // there is no "ideal" rotation axis // // So guess one; any will do as long as it's perpendicular to start // rotationAxis = ngl::Vec3 (0.0f, 0.0f, 1.0f).cross( start); // float t=rotationAxis.lengthSquared(); // if (t< 0.01 ) // bad luck, they were parallel, try again! // rotationAxis = ngl::Vec3 (1.0f, 0.0f, 0.0f).cross( start); // (rotationAxis).normalize(); // q.fromAxisAngle(rotationAxis,180.0f); // return q; // } rotationAxis = start.cross(dest); float s = sqrt( (1+cosTheta)*2 ); float invs = 1 / s; return ngl::Quaternion( s * 0.5f, rotationAxis.m_x * invs, rotationAxis.m_y * invs, rotationAxis.m_z * invs ); }
void Ray::setDirection(ngl::Vec3 _direction) { // check that it is unit length, if not, normalize if (_direction.length() > 1.1 || _direction.length() < 0.9) {_direction.normalize();} m_direction = _direction; }
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * TRACE ALGORITHM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ngl::Colour Renderer::trace(ngl::Vec3 _from, ngl::Vec3 _direction, int depth) { // create vector that will store intersection values for parameter t in the primary ray // a primary ray has a form like R = O + t * D where O is the origin vector, and D direction. std::vector<double> intersections; geo::Ray cam_ray(_from,_direction); // iterate over objects in the scene and find intersections for(unsigned int i = 0; i < m_scene->m_objects.size(); i++) { // each Shape subclass (Sphere, Plane...) has its own method for calculating intersections intersections.push_back( m_scene->m_objects.at(i)->getIntersection(cam_ray)); } // find closest object int closest_index = getIndexClosest(intersections); // if no intersections are found RETURN black = if(closest_index == -1) {return ngl::Colour(0,0,0,1);} // calculate pHit (position of the new intersection) and nHit (normal at hit point) ngl::Vec3 pHit = _from + intersections.at(closest_index) * _direction; ngl::Vec3 nHit = m_scene->m_objects.at(closest_index)->getNormalAt(pHit); // calculate if we are inside or outside bool inside = false; if(_direction.dot(nHit) > 0) { nHit = -nHit; inside = true; } float bias = 0.01; // calculate if point is obscured or shadowed bool isObscured = raycast(pHit + nHit * bias, closest_index); // // // // // // // // // // // // // // put all contributions together // // // // // // // // // // // // // // // is the object reflective or refractive??? if ((m_scene->m_objects.at(closest_index)->getMaterial()->isReflective() || m_scene->m_objects.at(closest_index)->getMaterial()->isRefractive()) && depth < m_max_depth) { ngl::Colour crfr(0,0,0,1); ngl::Colour crfl(0,0,0,1); // check whether it is REFLECTIVE if (m_scene->m_objects.at(closest_index)->getMaterial()->isReflective()) { // calculate reflection dir float bias = 0.01; ngl::Vec3 refl_dir = _direction - nHit * 2 * _direction.dot(nHit); refl_dir.normalize(); // fire ray along reflection direction from hit point crfl = trace(pHit + bias*nHit, refl_dir, depth+1); } // check whether it is REFRACTIVE if (m_scene->m_objects.at(closest_index)->getMaterial()->isRefractive()) { // calculate refrection dir (transmission ray) float ior = m_scene->m_objects.at(closest_index)->getMaterial()->getIOR(); float eta = inside; float bias = 0.01; float cosi = -nHit.dot(_direction); if (eta == true) // we are inside { eta = ior; } else // we are outside { eta = 1 / ior; } float k = 1 - eta * eta * (1 - cosi * cosi); ngl::Vec3 refr_dir = _direction * eta + nHit * (eta * cosi - sqrt(k)); refr_dir.normalize(); crfr = trace(pHit - nHit * bias, refr_dir, depth+1); } ngl::Colour surfaceColor = m_scene->m_objects.at(closest_index)->getColour(pHit); float cosineFactor = std::max(-nHit.dot(cam_ray.getDirection()),(float)0); float attenuation; ngl::Colour Ka(1,0,0.4,1); ngl::Colour Kd; ngl::Colour Ks; float ambient_intensity = 0.05; ngl::Colour ambient_contrib = Ka * surfaceColor * ambient_intensity; ngl::Colour diffuse_contrib(0,0,0,1); ngl::Colour specular_contrib(0,0,0,1); for(unsigned int m = 0; m < m_scene->m_lights.size(); m++) { ngl::Vec3 v_distance = m_scene->m_lights.at(m)->m_pos - pHit; float distance = v_distance.length(); float radius = 8; attenuation = 1 - pow(distance/radius,2); Kd = m_scene->m_lights.at(m)->m_diff_col; Ks = m_scene->m_lights.at(m)->m_spec_col; ngl::Vec3 L = m_scene->m_lights.at(m)->m_pos - pHit; L.normalize(); ngl::Vec3 N = nHit; ngl::Vec3 R = 2 * (L.dot(N) * N) - L; R.normalize(); diffuse_contrib += (surfaceColor * (Kd * pow(std::max(L.dot(N),(float)0),2) * m_scene->m_lights.at(m)->m_diff_int))*attenuation; specular_contrib += ((Ks * pow(std::max(R.dot(-_direction),(float)0),900)*400 * m_scene->m_lights.at(m)->m_spec_int))*attenuation; } specular_contrib.clamp(0,0.8); ngl::Colour s01 = crfl * m_scene->m_objects.at(closest_index)->getMaterial()->getReflIntensity(); ngl::Colour s02 = crfr * m_scene->m_objects.at(closest_index)->getMaterial()->getTransparency(); ngl::Colour s03 = s01 + s02; ngl::Colour diffuseColor = m_scene->m_objects.at(closest_index)->getColour(pHit) * cosineFactor * m_scene->m_objects.at(closest_index)->getMaterial()->getDiffuseIntensity(); // Do PHONG MODEL calculations stuff. By now I keep it VERY VERY simple ngl::Colour outRadiance = diffuseColor + s03 + specular_contrib + ambient_contrib; outRadiance.clamp(0,1); return isObscured ? outRadiance * 0.7f : outRadiance; } // if it is not REFLECTIVE nor REFRACTIVE else { ngl::Colour surfaceColor = m_scene->m_objects.at(closest_index)->getColour(pHit); float attenuation; ngl::Colour Ka(1,0,0.4,1); ngl::Colour Kd; ngl::Colour Ks; float ambient_intensity = 0.05; ngl::Colour ambient_contrib = Ka * surfaceColor * ambient_intensity; ngl::Colour diffuse_contrib(0,0,0,1); ngl::Colour specular_contrib(0,0,0,1); for(unsigned int m = 0; m < m_scene->m_lights.size(); m++) { ngl::Vec3 v_distance = m_scene->m_lights.at(m)->m_pos - pHit; float distance = v_distance.length(); float radius = 8; attenuation = 1 - pow(distance/radius,2); Kd = m_scene->m_lights.at(m)->m_diff_col; Ks = m_scene->m_lights.at(m)->m_spec_col; ngl::Vec3 L = m_scene->m_lights.at(m)->m_pos - pHit; L.normalize(); ngl::Vec3 N = nHit; ngl::Vec3 R = 2 * (L.dot(N) * N) - L; R.normalize(); float spec_hardness = m_scene->m_objects.at(closest_index)->getMaterial()->m_spec_hardness; diffuse_contrib += (surfaceColor * (Kd * pow(std::max(L.dot(N),(float)0),2) * m_scene->m_lights.at(m)->m_diff_int))*attenuation; specular_contrib += ((Ks * pow(std::max(R.dot(-_direction),(float)0),spec_hardness) * m_scene->m_lights.at(m)->m_spec_int))*attenuation; } diffuse_contrib.clamp(0,1); specular_contrib.clamp(0,1); ngl::Colour outRadiance = diffuse_contrib + specular_contrib + ambient_contrib; outRadiance.clamp(0,1); return isObscured ? outRadiance * 0.7f : outRadiance; } }