// check if a clause subsumes another clause. subsumed clause // must have MORE elements than the subsuming clause. // int ST(Array<Literal> &C, Array<Literal> &D, int i, int j, Substitutions &theta) { // check if clause D literals are exhausted if (j > D.getSize()) { return(NOMATCH); } // search for a possible unifying literal int a = j; Literal Li(C[i]); if (theta.applyTo(Li) != OK) { ERROR("applyTo failed.", errno); return(NOTOK); } Substitutions mu; for ( ; a <= D.getSize(); a++) { mu.clear(); Literal Ka(D[a]); if (unify(Li, Ka, mu) == OK) break; } if (a > D.getSize()) { return(NOMATCH); } // attempt to extend the matching Substitutions theta_mu(theta*mu); // if (i == C.getSize() || ST(C, D, i+1, 1, theta*mu) == OK) if (i == C.getSize() || ST(C, D, i+1, 1, theta_mu) == OK) { return(OK); } else return(ST(C, D, i, a+1, theta)); }
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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; } }
//------------------------------------------------------------------------------------------------------------------------------------ // called when we want to draw the 3D data in our app. //------------------------------------------------------------------------------------------------------------------------------------ void draw3D() { // draw the grid on the floor setColour(0.25f, 0.25f, 0.25f); for(float i = -10.0f; i <= 10.1f; i += 1.0f) { Vec3 zmin(i, 0, -10); Vec3 zmax(i, 0, 10); Vec3 xmin(-10, 0, i); Vec3 xmax(10, 0, i); drawLine(xmin, xmax); drawLine(zmin, zmax); } // If using the GPU to compute the lighting (which is what you want to do!) if(!g_manualLighting) { // turn on lighting enableLighting(); // set the diffuse material colour (this will be modulated by the effect of the lighting) setColour(1.0f, 1.0f, 1.0f); // draw the cube geometry drawPrimitives(g_pointsVN, 24, kQuads); // turn off lighting disableLighting(); } else { // otherwise, compute the lighting manually. Don't ever do this in practice! It's insane! (But it may be useful for educational purposes) // The direction from the vertex to the light (effectively sunlight in this case!). Vec3 L(-0.6f, 1.0f, -0.2f); // make sure L has been normalised! L = normalize(L); // start drawing some quads begin(kQuads); // loop through each vertex normal for(int i = 0; i < 24; ++i) { // compute N.L // Make sure we clamp this to zero (so that we ignore any negative values). float N_dot_L = std::max(dot(L, g_pointsVN[i].n), 0.0f); // the ambient material colour (always gets added to the final colour) Vec3 Ka(0.2f, 0.2f, 0.2f); // the diffuse material colour Vec3 Kd(1.0f, 1.0f, 1.0f); // Compute the final colour Vec3 colour = Ka + (Kd * N_dot_L); // set the vertex colour setColour(colour); // specify the vertex addVertex(g_pointsVN[i].v); } // finish drawing our quads end(); } // if we are displaying normals if(g_displayNormals) { // make colour pink setColour(1.0f, 0.0f, 1.0f); // loop through each vertex for(int i = 0; i < 24; ++i) { // compute an offset (along the normal direction) from the vertex Vec3 pn = g_pointsVN[i].v + (g_pointsVN[i].n * 0.2f); // draw a line to show the normal drawLine(g_pointsVN[i].v, pn); } } }