Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <vlGraphics/RayIntersector.hpp>
00033 #include <vlGraphics/SceneManager.hpp>
00034
00035 using namespace vl;
00036
00037
00038 void RayIntersector::intersect(const Ray& ray, SceneManager* scene_manager)
00039 {
00040 actors()->clear();
00041 scene_manager->extractActors( *actors() );
00042 setRay(ray);
00043 intersect();
00044 }
00045
00046 void RayIntersector::intersect()
00047 {
00048 mIntersections.clear();
00049 for(int i=0; i<actors()->size(); ++i)
00050 {
00051 if (!frustum().cull(actors()->at(i)->boundingBox()))
00052 {
00053 intersect(actors()->at(i));
00054 }
00055 }
00056
00057 std::sort( mIntersections.begin(), mIntersections.end(), sorter );
00058 }
00059
00060 void RayIntersector::intersect(Actor* act)
00061 {
00062 Geometry* geom = dynamic_cast<Geometry*>(act->lod(0).get());
00063 if (geom)
00064 intersectGeometry(act, geom);
00065 }
00066
00067 void RayIntersector::intersectGeometry(Actor* act, Geometry* geom)
00068 {
00069 ArrayFloat3* vert3f = dynamic_cast<ArrayFloat3*>(geom->vertexArray());
00070 ArrayDouble3* vert3d = dynamic_cast<ArrayDouble3*>(geom->vertexArray());
00071 ArrayHFloat3* vert3h = dynamic_cast<ArrayHFloat3*>(geom->vertexArray());
00072 if (vert3f)
00073 {
00074 fmat4 matrix = act->transform() ? (fmat4)act->transform()->worldMatrix() : fmat4();
00075 for(int i=0; i<geom->drawCalls()->size(); ++i)
00076 {
00077 DrawCall* prim = geom->drawCalls()->at(i);
00078 int itri = 0;
00079 for(TriangleIterator trit = prim->triangleIterator(); !trit.isEnd(); trit.next(), ++itri)
00080 {
00081 fvec3 a = vert3f->at(trit.a());
00082 fvec3 b = vert3f->at(trit.b());
00083 fvec3 c = vert3f->at(trit.c());
00084 if (act->transform())
00085 {
00086 a = matrix * a;
00087 b = matrix * b;
00088 c = matrix * c;
00089 }
00090 intersectTriangle(a, b, c, act, geom, prim, itri);
00091 }
00092 }
00093 }
00094 else
00095 if (vert3d)
00096 {
00097 dmat4 matrix = act->transform() ? (dmat4)act->transform()->worldMatrix() : dmat4();
00098 for(int i=0; i<geom->drawCalls()->size(); ++i)
00099 {
00100 DrawCall* prim = geom->drawCalls()->at(i);
00101 int itri = 0;
00102 for(TriangleIterator trit = prim->triangleIterator(); !trit.isEnd(); trit.next(), ++itri)
00103 {
00104 dvec3 a = vert3d->at(trit.a());
00105 dvec3 b = vert3d->at(trit.b());
00106 dvec3 c = vert3d->at(trit.c());
00107 if (act->transform())
00108 {
00109 a = matrix * a;
00110 b = matrix * b;
00111 c = matrix * c;
00112 }
00113 intersectTriangle(a, b, c, act, geom, prim, itri);
00114 }
00115 }
00116 }
00117 else
00118 if (vert3h)
00119 {
00120 fmat4 matrix = act->transform() ? (fmat4)act->transform()->worldMatrix() : fmat4();
00121 for(int i=0; i<geom->drawCalls()->size(); ++i)
00122 {
00123 DrawCall* prim = geom->drawCalls()->at(i);
00124 int itri = 0;
00125 for(TriangleIterator trit = prim->triangleIterator(); !trit.isEnd(); trit.next(), ++itri)
00126 {
00127 fvec3 a = (fvec3)vert3h->at(trit.a());
00128 fvec3 b = (fvec3)vert3h->at(trit.b());
00129 fvec3 c = (fvec3)vert3h->at(trit.c());
00130 if (act->transform())
00131 {
00132 a = matrix * a;
00133 b = matrix * b;
00134 c = matrix * c;
00135 }
00136 intersectTriangle(a, b, c, act, geom, prim, itri);
00137 }
00138 }
00139 }
00140 }
00141
00142 template<class T>
00143 void RayIntersector::intersectTriangle(const T& a, const T& b, const T& c, Actor* act, Geometry* geom, DrawCall* prim, int tri_idx)
00144 {
00145 T v1 = b-a;
00146 T v2 = c-a;
00147 T n = cross(v1,v2).normalize();
00148 Real det = (Real)dot(n,(T)ray().direction());
00149 if(det == 0)
00150 return;
00151 Real t = (Real)dot(n, a-(T)ray().origin()) / det;
00152 if (t<0)
00153 return;
00154 vec3 rp = ray().origin() + ray().direction() * t;
00155 T fp = (T)rp;
00156 T pts[] = { a, b, c, a };
00157 for(int i=0; i<3; ++i)
00158 {
00159 T bi_norm = -cross(pts[i+1]-pts[i],n).normalize();
00160 if (dot(fp-pts[i],bi_norm) < 0)
00161 return;
00162 }
00163 ref<RayIntersectionGeometry> record = new vl::RayIntersectionGeometry;
00164 record->setIntersectionPoint( rp );
00165 record->setTriangleIndex(tri_idx);
00166 record->setActor(act);
00167 record->setGeometry(geom);
00168 record->setPrimitives(prim);
00169 record->setDistance( t );
00170 mIntersections.push_back(record);
00171 }
00172