00001
00002
00003
00004
00005
00006
00007 #include "polygon.h"
00008 #include "scene.h"
00009 #include <math.h>
00010 #include <algorithm>
00011
00012
00013 Polygon::StaticInit Polygon::m_init;
00014
00015
00016 Polygon::Polygon(std::string color, std::string material, std::string bumpmap)
00017 : m_normal(),
00018 m_vertices()
00019 {
00020 Scene * scene = Scene::get_instance();
00021 m_material = scene->get_material(material);
00022 m_bumpmap = scene->get_bumpmap(bumpmap);
00023 }
00024
00025
00026
00027 bool Polygon::add_vertex(Point3D vertex) {
00028 if(find(m_vertices.begin(), m_vertices.end(), vertex) == m_vertices.end()) {
00029 if(m_vertices.size() >= 3) {
00030
00031
00032
00033
00034
00035
00036
00037 if(dot_product(m_vertices[2] - m_vertices[0], cross_product((m_vertices[1] - m_vertices[0]), (vertex - m_vertices[2]))) == 0) {
00038 return false;
00039 }
00040 else {
00041 log_warn("mbrt does not support Polygons with more than 3 vertices.");
00042 }
00043 }
00044
00045 m_vertices.push_back(vertex);
00046
00047
00048 if(m_vertices.size() == 3) {
00049 m_normal = Ray(m_vertices[0], cross_product((m_vertices[1] - m_vertices[0]), (m_vertices[2] - m_vertices[0])));
00050 m_d = dot_product(m_vertices[0], m_normal.direction());
00051 }
00052 return true;
00053 }
00054 else {
00055
00056 return false;
00057 }
00058 }
00059
00060
00061
00062 bool Polygon::collides_with(const Ray &ray, double &t) const {
00063
00064
00065 Point3D orig = ray.origin();
00066 Vector dir = ray.direction();
00067
00068 double denominator = dot_product(dir, m_normal.direction());
00069 if(denominator > -0.0001 && denominator < 0.0001) {
00070 return false;
00071 }
00072
00073 double numerator = m_d - dot_product(orig, m_normal.direction());
00074 if(numerator > -0.0001 && numerator < 0.0001) {
00075 return false;
00076 }
00077
00078 t = numerator / denominator;
00079 if(t <= 0) {
00080 return false;
00081 }
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 Point3D intersection_point = ray.origin() + (ray.direction() * t);
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 Vector u, v, n;
00111 u = m_vertices[1] - m_vertices[0];
00112 v = m_vertices[2] - m_vertices[0];
00113 n = cross_product(u, v);
00114
00115 float uu, uv, vv, wu, wv, D;
00116 uu = dot_product(u,u);
00117 uv = dot_product(u,v);
00118 vv = dot_product(v,v);
00119 Vector w = intersection_point - m_vertices[0];
00120 wu = dot_product(w,u);
00121 wv = dot_product(w,v);
00122 D = uv * uv - uu * vv;
00123
00124
00125 float s, _t;
00126 s = (uv * wv - vv * wu) / D;
00127 if (s < 0.0 || s > 1.0)
00128 return false;
00129 _t = (uv * wu - uu * wv) / D;
00130 if (_t < 0.0 || (s + _t) > 1.0)
00131 return false;
00132
00133 return true;
00134
00135 }
00136
00137
00138 #if 0
00139
00140
00141
00142
00143
00144 Point3D projected_intersection(0, 0, 0);
00145 vector<Point3D> projection;
00146 vector<Point3D>::iterator iter = m_vertices.begin();
00147 vector<Point3D>::iterator end = m_vertices.end();
00148 if( fabs(intersection_point.x) > fabs(intersection_point.y) && fabs(intersection_point.x) > fabs(intersection_point.z)) {
00149 for(; iter != end; ++iter) {
00150 projection.push_back(Point3D(iter->y - intersection_point.y , iter->z - intersection_point.z, 0));
00151 }
00152 }
00153 else if( fabs(intersection_point.y) > fabs(intersection_point.x) && fabs(intersection_point.y) > fabs(intersection_point.z)) {
00154 for(; iter != end; ++iter) {
00155 projection.push_back(Point3D(iter->x - intersection_point.x, iter->z - intersection_point.z, 0));
00156 }
00157 }
00158 else if( fabs(intersection_point.z) > fabs(intersection_point.x) && fabs(intersection_point.z) > fabs(intersection_point.y)) {
00159 for(; iter != end; ++iter) {
00160 projection.push_back(Point3D(iter->x - intersection_point.x, iter->y - intersection_point.y, 0));
00161 }
00162 }
00163
00164
00165
00166
00167
00168
00169 int ncross = 0;
00170 vector<Point3D>::iterator iter = projection.begin();
00171 vector<Point3D>::iterator end = projection.end();
00172 Point3D prev_vertex = *(iter++);
00173 for(; iter != end; ++iter) {
00174
00175
00176
00177
00178
00179
00180
00181 if(prev_vertex.y > 0)
00182
00183 prev_vertex = *iter;
00184 }
00185
00186 return true;
00187 #endif
00188
00189
00190
00191 Ray Polygon::get_normal(const Point3D &p) const {
00192 return Ray(p, m_normal.direction() );
00193 }
00194