renderable.cpp

Go to the documentation of this file.
00001 #include "renderable.h"
00002 #include <vector>
00003 #include "color.h"
00004 
00005 using Magick::Color;
00006 using Magick::ColorRGB;
00007 
00008 using std::vector;
00009 
00010 //{{{
00011 double Renderable::get_diffuse(const Point3D& intersection_point) const {
00012     double diffuse;
00013     if(m_center_material)
00014     {
00015         diffuse = m_material->get_diffuse(intersection_point - m_center);
00016     }
00017     else
00018     {
00019         diffuse = m_material->get_diffuse(intersection_point);
00020     }
00021 
00022     return (diffuse <= 0.0) ? 0.0 :
00023            (diffuse >= 1.0) ? 1.0 :
00024            diffuse;
00025 }
00026 //}}}
00027 //{{{
00028 double Renderable::get_reflection(const Point3D& intersection_point) const {
00029     double reflection ;
00030     if(m_center_material)
00031     {
00032         reflection = m_material->get_reflection(intersection_point - m_center);
00033     }
00034     else
00035     {
00036         reflection = m_material->get_reflection(intersection_point);
00037     }
00038 
00039     return (reflection <= 0.0) ? 0.0 :
00040            (reflection >= 1.0) ? 1.0 :
00041            reflection;
00042 }
00043 //}}}
00044 //{{{
00045 double Renderable::get_reflectivity(const Point3D& intersection_point) const {
00046     if(m_center_material)
00047         return m_material->get_reflectivity(intersection_point - m_center);
00048     else
00049         return m_material->get_reflectivity(intersection_point);
00050 }
00051 //}}}
00052 //{{{
00053 double Renderable::get_specular(const Point3D& intersection_point) const {
00054     // Really?
00055     // follow up: This currently doesn't appear to be used.
00056     if(m_center_material)
00057         return 1.0;
00058     else
00059         return 1.0; // fah!
00060 
00061 }
00062 //}}}
00063 //{{{
00064 double Renderable::get_opacity(const Point3D& intersection_point) const {
00065     if(m_center_material)
00066         return m_material->get_opacity(intersection_point - m_center);
00067     else
00068         return m_material->get_opacity(intersection_point);
00069 }
00070 //}}}
00071 //{{{
00072 double Renderable::get_refraction_index(const Point3D& intersection_point) const {
00073     if(m_center_material)
00074         return m_material->get_refraction_index(intersection_point - m_center);
00075     else
00076         return m_material->get_refraction_index(intersection_point);
00077 }
00078 //}}}
00079 //{{{
00080 Magick::Color Renderable::get_color(const Point3D& intersection_point) const {
00081     return m_material->get_color(intersection_point, this);
00082 }
00083 //}}}
00084 //{{{
00085 bool Renderable::is_light(const Point3D& intersection_point) const {
00086     if(m_center_material)
00087         return  m_material->is_light(intersection_point - m_center);
00088     else
00089         return  m_material->is_light(intersection_point);
00090 }
00091 //}}}
00092 //{{{
00093 bool Renderable::set_is_light(bool v) {
00094     m_material->set_is_light(v);
00095 }
00096 //}}}
00097 
00098 //{{{
00099 Ray Renderable::get_final_normal(const Point3D& p)
00100 {
00101     if(m_bumpmap == NULL)
00102     {
00103         return get_normal(p);
00104     }
00105     else
00106     {
00107         return m_bumpmap->perturb_normal(get_normal(p), p);
00108     }
00109 }
00110 //}}}
00111 
00112 Magick::Color Renderable::get_color_contribution(const Point3D &intersection_point, const Ray &ray, Vector &reflect, Vector &refract) {
00113     // Determine the color of the pixel at the point of intersection.
00114     double ambient_factor = 0.2;
00115     Magick::ColorRGB rv = get_color(intersection_point) * ambient_factor;
00116     Scene * scene = Scene::get_instance();
00117 
00118     if ( is_light(intersection_point) == false ) {
00119 
00120         // now calculate all rays to light sources, and accumulate each source's contribution to
00121         // the pixel color.
00122         vector<Renderable *>::iterator iter, end = scene->get_scene()->end();
00123         for ( iter = scene->get_scene()->begin(); iter != end; ++iter ) {
00124 
00125             if ( (*iter)->is_light(intersection_point) == true) {
00126                 Renderable * light = *iter;
00127 
00128                 //double diffusion = light->get_diffuse(intersection_point);
00129                 //if ( diffusion > 0.0 ) {
00130                     // Calculate the ray to the light source (rtl).
00131                     Ray rtl(intersection_point, light->get_center() - intersection_point);
00132 
00133                     // Calculate the normal of the surface at the point of intersection.
00134                     Ray normal(get_final_normal(intersection_point) ); 
00135 
00136                     // Determine the angle, in radians, between the normal and the ray to the light source.
00137                     double theta = dot_product(rtl.direction(), normal.direction());
00138 
00139                     // Determine the vector at which the incoming ray is reflected.
00140                     reflect = ray.direction() - (normal.direction() * 2.0 * dot_product(ray.direction(), normal.direction()));;
00141 
00142                     // Determine the vector at which the incoming ray is refracted.  This is done
00143                     // according to Snell's Law.
00144                     
00145                     // TODO{: only perform calculations if object is actually refracting light
00146 #if 0
00147                     double refraction_index = get_refraction_index(intersection_point);
00148                     double refract_coefficient = refraction_index / 1.0003; // / scene->global_refraction_index();
00149                     double normal_dot_neg_ray = dot_product(normal.direction(), -ray.direction());
00150                     double sqrt_val = 1.0 + (refract_coefficient * refract_coefficient) * (normal_dot_neg_ray * normal_dot_neg_ray);
00151                     if (sqrt_val >= 0.0) {
00152                         refract = ray.direction() * refract_coefficient + normal.direction() * ((normal_dot_neg_ray * refract_coefficient) - sqrt(sqrt_val));
00153                     }
00154                     // }TODO
00155 #endif
00156 
00157                     // Determine diffuse lighting.
00158                     if ( theta > 0.0 ) {
00159 
00160                         // If this spot is in shadow, skip it.
00161                         if ( is_in_shadow(rtl, intersection_point) == true )
00162                             continue;
00163                         double specular_color = 0.0;
00164                         double reflectivity = get_reflectivity(intersection_point) ;
00165                             // Determine specular lighting.
00166                         
00167                         if(reflectivity > 0.001)
00168                         {
00169                             double spec_theta = dot_product(reflect, rtl.direction());
00170                             if(spec_theta > 0.0001)
00171                                 specular_color = powf(spec_theta, reflectivity);
00172                             else
00173                                 specular_color = 0.0;
00174                         }
00175 
00176                         //diffusion *= theta;
00177                         double diffusion = get_diffuse(intersection_point) * theta;
00178                         if(diffusion > 1.0)
00179                         {
00180                             log_warn("Diffusion %d", diffusion);
00181                         }
00182 
00183                         rv += get_color(intersection_point) * (light->get_color(intersection_point) * diffusion);
00184                         // I don't think this does what you think it does.  It uses the reflection coefficient
00185                         // as the specular coefficient.  These are not the same thing.
00186                         rv += light->get_color(intersection_point) * specular_color * get_reflection(intersection_point);
00187                     }
00188                 //}
00189             }
00190         }
00191     }
00192     else {
00193         rv = get_color(intersection_point);
00194     }
00195 
00196     return rv;
00197 }
00198 
00199 bool Renderable::initialize(xmlNode * node)
00200 {
00201     log_debug("Initializing primitive...");
00202     xml_properties props = get_properties(node);
00203     Scene * scene = Scene::get_instance();
00204 
00205     m_material = scene->get_material( props["material"] );
00206     if(!m_material)
00207     {
00208         log_err("Material of type '%s' not found.", props["material"].c_str() );
00209     }
00210     else
00211     {
00212         log_debug("Added material '%s'", props["material"].c_str() );
00213     }
00214 
00215     if(props.find("bumpmap") != props.end())
00216     {
00217         m_bumpmap = scene->get_bumpmap( props["bumpmap"] );
00218     }
00219     else
00220     {
00221         m_bumpmap = NULL;
00222     }
00223 
00224     if(props.find("center_material") != props.end())
00225     {
00226         m_center_material = true;
00227     }
00228     else
00229     {
00230         m_center_material = false;
00231     }
00232 
00233     return true;  
00234 }
00235 

Generated on Tue Oct 30 22:12:15 2007 for mbrt by  doxygen 1.5.2