Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics
[Home] [Tutorials] [All Classes] [Grouped Classes]

X:/dropbox/visualizationlibrary/src/vlGraphics/RayIntersector.cpp

Go to the documentation of this file.
00001 /**************************************************************************************/
00002 /*                                                                                    */
00003 /*  Visualization Library                                                             */
00004 /*  http://www.visualizationlibrary.org                                               */
00005 /*                                                                                    */
00006 /*  Copyright (c) 2005-2010, Michele Bosi                                             */
00007 /*  All rights reserved.                                                              */
00008 /*                                                                                    */
00009 /*  Redistribution and use in source and binary forms, with or without modification,  */
00010 /*  are permitted provided that the following conditions are met:                     */
00011 /*                                                                                    */
00012 /*  - Redistributions of source code must retain the above copyright notice, this     */
00013 /*  list of conditions and the following disclaimer.                                  */
00014 /*                                                                                    */
00015 /*  - Redistributions in binary form must reproduce the above copyright notice, this  */
00016 /*  list of conditions and the following disclaimer in the documentation and/or       */
00017 /*  other materials provided with the distribution.                                   */
00018 /*                                                                                    */
00019 /*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
00020 /*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
00021 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
00022 /*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  */
00023 /*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    */
00024 /*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      */
00025 /*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    */
00026 /*  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           */
00027 /*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS     */
00028 /*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                      */
00029 /*                                                                                    */
00030 /**************************************************************************************/
00031 
00032 #include <vlGraphics/RayIntersector.hpp>
00033 #include <vlGraphics/SceneManager.hpp>
00034 #include <vlGraphics/LineIterator.hpp>
00035 #include <iostream>
00036 
00037 using namespace vl;
00038 
00039 //-----------------------------------------------------------------------------
00040 void RayIntersector::intersect(const Ray& ray, SceneManager* scene_manager)
00041 {
00042   actors()->clear();
00043   scene_manager->extractActors( *actors() );
00044   setRay(ray);
00045   intersect();
00046 }
00047 //-----------------------------------------------------------------------------
00048 void RayIntersector::intersect()
00049 {
00050   mIntersections.clear();
00051   for(int i=0; i<actors()->size(); ++i)
00052   {
00053     if (!frustum().cull(actors()->at(i)->boundingBox()))
00054     {
00055       intersect(actors()->at(i));
00056     }
00057   }
00058 
00059   std::sort( mIntersections.begin(), mIntersections.end(), sorter );
00060 }
00061 //-----------------------------------------------------------------------------
00062 void RayIntersector::intersect(Actor* act)
00063 {
00064   Geometry* geom = cast<Geometry>(act->lod(0));
00065   if (geom)
00066     intersectGeometry(act, geom);
00067 }
00068 //-----------------------------------------------------------------------------
00069 void RayIntersector::intersectGeometry(Actor* act, Geometry* geom)
00070 {
00071   ArrayAbstract* posarr = geom->vertexArray() ? geom->vertexArray() : geom->vertexAttribArray(vl::VA_Position) ? geom->vertexAttribArray(vl::VA_Position)->data() : NULL;
00072   if (posarr)
00073   {
00074     mat4 matrix = act->transform() ? act->transform()->worldMatrix() : mat4();
00075     for(int i=0; i<geom->drawCalls()->size(); ++i)
00076     {
00077       DrawCall* prim = geom->drawCalls()->at(i);
00078       int itri = 0;
00079       if(prim->primitiveType() == vl::PT_LINES ||
00080               prim->primitiveType() == vl::PT_LINE_STRIP ||
00081               prim->primitiveType() == vl::PT_LINE_LOOP)
00082       {
00083         for(LineIterator liit = prim->lineIterator(); liit.hasNext(); liit.next(), ++itri)
00084         {
00085             int ia = liit.a();
00086             int ib = liit.b();
00087             vec3 a = posarr->getAsVec3(ia);
00088             vec3 b = posarr->getAsVec3(ib);
00089             if(act->transform())
00090             {
00091                 a = matrix * a;
00092                 b = matrix * b;
00093             }
00094             // Compute distance to the line. Compute all and keep the minimum( attribute for an epsilon?)
00095             intersectLine(a, b, ia, ib, act, geom, prim, itri);
00096         }
00097       }
00098       else if(prim->primitiveType() == vl::PT_POINTS)
00099       {
00100           for(unsigned int i = 0; i < posarr->size(); i += 3, ++itri)
00101           {
00102              vec3 a = posarr->getAsVec3(i);
00103              if(act->transform())
00104              {
00105                  a = matrix * a;
00106              }
00107              intersectPoint(a, i, act, geom, prim, itri);
00108           }
00109       }
00110       else
00111       {
00112         for(TriangleIterator trit = prim->triangleIterator(); trit.hasNext(); trit.next(), ++itri)
00113         {
00114             int ia = trit.a();
00115             int ib = trit.b();
00116             int ic = trit.c();
00117             vec3 a = posarr->getAsVec3(ia);
00118             vec3 b = posarr->getAsVec3(ib);
00119             vec3 c = posarr->getAsVec3(ic);
00120             if (act->transform())
00121             {
00122                 a = matrix * a;
00123                 b = matrix * b;
00124                 c = matrix * c;
00125             }
00126             intersectTriangle(a, b, c, ia, ib, ic, act, geom, prim, itri);
00127         }
00128       }
00129     }
00130   }
00131 }
00132 //-----------------------------------------------------------------------------
00133 template<class T>
00134 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)
00135 {
00136   T v1 = b-a;
00137   T v2 = c-a;
00138   T n = cross(v1,v2).normalize();
00139   real det = (real)dot(n,(T)ray().direction());
00140   if(det == 0)
00141     return;
00142   real t = (real)dot(n, a-(T)ray().origin()) / det;
00143   if (t<0)
00144     return;
00145   vec3  rp = ray().origin() + ray().direction() * t;
00146   T fp = (T)rp;
00147   T pts[] = { a, b, c, a };
00148   for(int i=0; i<3; ++i)
00149   {
00150     T bi_norm = -cross(pts[i+1]-pts[i],n).normalize();
00151     if (dot(fp-pts[i],bi_norm) < 0)
00152       return;
00153   }
00154 
00155   // compute the nearest point
00156   T aRp = rp - a;
00157   T bRp = rp - b;
00158   T cRp = rp - c;
00159 
00160   T v3 = b - c;
00161   float d1 = cross(aRp, v1).length() / v1.length();
00162   float d2 = cross(aRp, v2).length() / v2.length();
00163   float d3 = cross(cRp, v3).length() / v3.length();
00164 
00165   int ila, ilb;
00166   int l_idx;
00167   if(d1 < d2)
00168   {
00169       if(d1 < d3)
00170       {
00171           ila = ia;
00172           ilb = ib;
00173           l_idx = 1;
00174       }
00175       else
00176       {
00177           ila = ic;
00178           ilb = ib;
00179           l_idx = 2;
00180       }
00181   }
00182   else
00183   {
00184       if(d2 < d3)
00185       {
00186           ila = ia;
00187           ilb = ic;
00188           l_idx = 3;
00189       }
00190       else
00191       {
00192           ila = ic;
00193           ilb = ib;
00194           l_idx = 2;
00195       }
00196   }
00197 
00198   ref<RayIntersectionGeometry> record = new vl::RayIntersectionGeometry;
00199   record->setIntersectionPoint( rp );
00200   record->setTriangleIndex(tri_idx);
00201   record->setTriangle(ia, ib, ic);
00202   record->setLineIndex(l_idx);
00203   record->setLine(ila, ilb);
00204   record->setNearestPoint(aRp.lengthSquared() < bRp.lengthSquared() ? (aRp.lengthSquared() < cRp.lengthSquared() ? ia : ic) : (bRp.lengthSquared() < cRp.lengthSquared() ? ib : ic));
00205   record->setActor(act);
00206   record->setGeometry(geom);
00207   record->setPrimitives(prim);
00208   record->setDistance( t );
00209   mIntersections.push_back(record);
00210 }
00211 //-----------------------------------------------------------------------------
00212 template<class T>
00213 void RayIntersector::intersectLine(const T& a, const T& b, int ia, int ib, Actor* act, Geometry* geom, DrawCall* prim, int tri_idx)
00214 {
00215   T v1 = b-a;
00216 
00217   //--------------------------------------------------------------------------
00218 
00219 
00220   float denominator = ray().direction().y() * (b.x() - a.x()) - ray().direction().x() * (b.y() - a.y());
00221     if(denominator == 0)
00222         return;
00223     float t = (ray().direction().x() * (a.y() - ray().origin().y()) - ray().direction().y() * (a.x() - ray().origin().x())) / denominator;
00224   if(t < 0 || t > 1)
00225       return;
00226 
00227 
00228   //--------------------------------------------------------------------------
00229 
00230 
00231 
00232 
00233       T   u = b - a;
00234       T   v = ray().direction();
00235       T   w = a - ray().origin();
00236       float    a1 = dot(u,u);        // always >= 0
00237       float    b1 = dot(u,v);
00238       float    c = dot(v,v);        // always >= 0
00239       float    d = dot(u,w);
00240       float    e = dot(v,w);
00241       float    D = a1*c - b1*b1;       // always >= 0
00242       float    sc, tc;
00243 
00244       // compute the line parameters of the two closest points
00245       if (D < 00000001) {         // the lines are almost parallel
00246           sc = 0.0;
00247           tc = (b1>c ? d/b1 : e/c);   // use the largest denominator
00248       }
00249       else {
00250           sc = (b1*e - c*d) / D;
00251           tc = (a1*e - b1*d) / D;
00252       }
00253 
00254       // get the difference of the two closest points
00255       T   dP = w + (sc * u) - (tc * v);  // = L1(sc) - L2(tc)
00256 
00257       float dist = dP.length();   // return the closest distance
00258 
00259       std::cout << "iligne : " << tri_idx << "; Dist : " << dist << "\n" << std::endl;
00260       if(dist > 1)
00261           return;
00262 
00263 
00264         ref<RayIntersectionGeometry> record = new vl::RayIntersectionGeometry;
00265         //record->setIntersectionPoint( -1 );
00266         record->setTriangleIndex(-1);
00267         record->setTriangle(-1, -1, -1);
00268         record->setLineIndex(tri_idx);
00269         record->setLine(ia, ib);
00270         record->setNearestPoint(-1); // pour que ca ne crash pas dans ViewerActorTree au moment du decoupage de l'actor
00271         //record->setNearestPoint(aRp.lengthSquared() < bRp.lengthSquared() ? (aRp.lengthSquared() < cRp.lengthSquared() ? ia : ic) : (bRp.lengthSquared() < cRp.lengthSquared() ? ib : ic));
00272         record->setActor(act);
00273         record->setGeometry(geom);
00274         record->setPrimitives(prim);
00275         //record->setDistance( dist );
00276         mIntersections.push_back(record);
00277 
00278 }
00279 //-----------------------------------------------------------------------------
00280 template<class T>
00281 void RayIntersector::intersectPoint(const T& a, int ia, Actor* act, Geometry* geom, DrawCall* prim, int prim_idx)
00282 {
00283     // Find the equation of the plan thanks to the normal and one point
00284     float nd = ray().direction().x() * a.x() + ray().direction().y() * a.y() + ray().direction().z() * a.z();
00285 
00286     // Find the intersection between the ray and the plan
00287     float k = (-nd - ray().direction().x() * ray().origin().x() - ray().direction().y() * ray().origin().y() - ray().direction().z() * ray().origin().z());/* /
00288             (ray().direction().x() * ray.direction().x() + ray().direction().y() * ray.direction().y() + ray().direction().z() * ray().direction().z());*/
00289 
00290     // Compute the distance between the intersection and our point (a)
00291     T intersectionPoint(ray().origin().x() + k * ray().direction().x(),
00292                         ray().origin().y() + k * ray().direction().y(),
00293                         ray().origin().z() + k * ray().direction().z());
00294 
00295     float distance = length(a - intersectionPoint);
00296     if(distance > 0.1)  // To convert into pixel
00297         return;
00298 
00299     ref<RayIntersectionGeometry> record = new vl::RayIntersectionGeometry;
00300     record->setIntersectionPoint(a);
00301     record->setTriangleIndex(-1);
00302     record->setTriangle(-1, -1, -1);
00303     record->setLineIndex(-1);
00304     record->setLine(-1, -1);
00305     record->setNearestPoint(prim_idx);
00306     record->setActor(act);
00307     record->setGeometry(geom);
00308     record->setPrimitives(prim);
00309     mIntersections.push_back(record);
00310 
00311 }
00312 //-----------------------------------------------------------------------------

Visualization Library 2011.09.1160 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 2 2013 13:40:39.
Permission is granted to use this page to write and publish articles regarding Visualization Library.