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 = cast<Geometry>(act->lod(0));
00063 if (geom)
00064 intersectGeometry(act, geom);
00065 }
00066
00067 void RayIntersector::intersectGeometry(Actor* act, Geometry* geom)
00068 {
00069 ArrayAbstract* posarr = geom->vertexArray() ? geom->vertexArray() : geom->vertexAttribArray(vl::VA_Position) ? geom->vertexAttribArray(vl::VA_Position)->data() : NULL;
00070 if (posarr)
00071 {
00072 mat4 matrix = act->transform() ? act->transform()->worldMatrix() : mat4();
00073 for(int i=0; i<geom->drawCalls()->size(); ++i)
00074 {
00075 DrawCall* prim = geom->drawCalls()->at(i);
00076 int itri = 0;
00077 for(TriangleIterator trit = prim->triangleIterator(); trit.hasNext(); trit.next(), ++itri)
00078 {
00079 int ia = trit.a();
00080 int ib = trit.b();
00081 int ic = trit.c();
00082 vec3 a = posarr->getAsVec3(ia);
00083 vec3 b = posarr->getAsVec3(ib);
00084 vec3 c = posarr->getAsVec3(ic);
00085 if (act->transform())
00086 {
00087 a = matrix * a;
00088 b = matrix * b;
00089 c = matrix * c;
00090 }
00091 intersectTriangle(a, b, c, ia, ib, ic, act, geom, prim, itri);
00092 }
00093 }
00094 }
00095 }
00096
00097 template<class T>
00098 void RayIntersector::intersectTriangle(const T& a, const T& b, const T& c, int ia, int ib, int ic, Actor* act, Geometry* geom, DrawCall* prim, int tri_idx)
00099 {
00100 T v1 = b-a;
00101 T v2 = c-a;
00102 T n = cross(v1,v2).normalize();
00103 real det = (real)dot(n,(T)ray().direction());
00104 if(det == 0)
00105 return;
00106 real t = (real)dot(n, a-(T)ray().origin()) / det;
00107 if (t<0)
00108 return;
00109 vec3 rp = ray().origin() + ray().direction() * t;
00110 T fp = (T)rp;
00111 T pts[] = { a, b, c, a };
00112 for(int i=0; i<3; ++i)
00113 {
00114 T bi_norm = -cross(pts[i+1]-pts[i],n).normalize();
00115 if (dot(fp-pts[i],bi_norm) < 0)
00116 return;
00117 }
00118 ref<RayIntersectionGeometry> record = new vl::RayIntersectionGeometry;
00119 record->setIntersectionPoint( rp );
00120 record->setTriangleIndex(tri_idx);
00121 record->setTriangle(ia, ib, ic);
00122 record->setActor(act);
00123 record->setGeometry(geom);
00124 record->setPrimitives(prim);
00125 record->setDistance( t );
00126 mIntersections.push_back(record);
00127 }
00128