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
00055
00056 if(m_center_material)
00057 return 1.0;
00058 else
00059 return 1.0;
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
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
00121
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
00129
00130
00131 Ray rtl(intersection_point, light->get_center() - intersection_point);
00132
00133
00134 Ray normal(get_final_normal(intersection_point) );
00135
00136
00137 double theta = dot_product(rtl.direction(), normal.direction());
00138
00139
00140 reflect = ray.direction() - (normal.direction() * 2.0 * dot_product(ray.direction(), normal.direction()));;
00141
00142
00143
00144
00145
00146 #if 0
00147 double refraction_index = get_refraction_index(intersection_point);
00148 double refract_coefficient = refraction_index / 1.0003;
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
00155 #endif
00156
00157
00158 if ( theta > 0.0 ) {
00159
00160
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
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
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
00185
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