Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

physics/GJKCollisionModel.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002   Copyright (C)1996 David Jung <opensim@pobox.com>
00003 
00004   This program/file is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU General Public License as published by
00006   the Free Software Foundation; either version 2 of the License, or
00007   (at your option) any later version.
00008   
00009   This program is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012   GNU General Public License for more details. (http://www.gnu.org)
00013   
00014   You should have received a copy of the GNU General Public License
00015   along with this program; if not, write to the Free Software
00016   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017   
00018   $Id: GJKCollisionModel.cpp 1031 2004-02-11 20:46:36Z jungd $
00019   $Revision: 1.5 $
00020   $Date: 2004-02-11 15:46:36 -0500 (Wed, 11 Feb 2004) $
00021   $Author: jungd $
00022  
00023 ****************************************************************************/
00024 
00025 #include <physics/GJKCollisionModel>
00026 
00027 #include <physics/Shape>
00028 #include <physics/Box>
00029 #include <physics/Sphere>
00030 #include <physics/Polyhedron>
00031 
00032 #include <gfx/Color4>
00033 #include <gfx/Triangle3>
00034 #include <gfx/TriangleContainer>
00035 #include <gfx/TriangleIterator>
00036 #include <gfx/VisualTriangles>
00037 #include <gfx/IndexedPoint3Array>
00038 
00039 
00040 using physics::GJKCollisionModel;
00041 using physics::Shape;
00042 using physics::Box;
00043 
00044 using gfx::Triangle3;
00045 using gfx::Color4;
00046 using gfx::TriangleContainer;
00047 using gfx::TriangleIterator;
00048 using gfx::VisualTriangles;
00049 using gfx::IndexedPoint3Array;
00050 
00051 using base::Matrix3;
00052 using base::transpose;
00053 using base::cross;
00054 using base::reflist;
00055 
00056 
00057 
00058 GJKCollisionModel::GJKCollisionModel(const gfx::TriangleContainer& triangles)
00059 {
00060   ref<const Polyhedron> poly(NewNamedObj("GJKCollisionModel Polyhedron") Polyhedron(triangles));
00061   shape = poly;
00062   supportFunction = NewObj PolyhedronSupport(poly);
00063 }
00064 
00065 GJKCollisionModel::GJKCollisionModel(ref<const Shape> shape)
00066   : shape(shape)
00067 {
00068   initSupportFunction();
00069 }
00070 
00071 
00072 GJKCollisionModel::GJKCollisionModel(const GJKCollisionModel& cm)
00073   : shape(cm.shape)
00074 {
00075   initSupportFunction();
00076 }
00077 
00078 GJKCollisionModel::~GJKCollisionModel()
00079 {
00080   if (supportFunction) DeleteObj supportFunction;
00081 }
00082 
00083 
00084 void GJKCollisionModel::initSupportFunction()
00085 {
00086   if (instanceof(*shape, const Box))
00087     supportFunction = NewObj BoxSupport(shape);
00088   else if (instanceof(*shape, const Sphere))
00089     supportFunction = NewObj SphereSupport(shape);
00090   else if (instanceof(*shape, const Polyhedron)) 
00091     supportFunction = NewObj PolyhedronSupport(shape);
00092   else {
00093     // if we don't directly support this Shape class, convert it into a Polyhedron via it's Visual
00094     Logln(shape->className() + " class not directly supported; converting to Polyhedron via Visual.");
00095     ref<Polyhedron> poly(NewNamedObj("GJKCollisionModel Polyhedron") Polyhedron(VisualTriangles(*shape)));
00096     shape = poly;
00097     supportFunction = NewObj PolyhedronSupport(shape);
00098   }
00099 }
00100 
00101 
00102 
00103 base::Point3 GJKCollisionModel::BoxSupport::operator()(ref<GJKModelState> s, const base::Vector3& v) const
00104 {
00105   base::Dimension3 ext(box->dimensions()/2.0);
00106   return Point3(v.x<0? -ext.x : ext.x,
00107                 v.y<0? -ext.y : ext.y,
00108                 v.z<0? -ext.z : ext.z);
00109 }
00110  
00111 
00112 base::Point3 GJKCollisionModel::SphereSupport::operator()(ref<GJKModelState> s, const base::Vector3& v) const
00113 {
00114   Real l = v.length();
00115 
00116   if (!base::equals(l,0)) {
00117     Real r = sphere->radius() / l;
00118     return v*r;
00119   }
00120   else 
00121     return Point3();
00122 }
00123  
00124 
00125 base::Point3 GJKCollisionModel::PolyhedronSupport::operator()(ref<GJKModelState> s, const base::Vector3& v) const
00126 {
00127   /*
00128 
00129   Real d;
00130   reflist<Polyhedron::Vertex>::const_iterator vert = poly->vertices_begin();
00131   reflist<Polyhedron::Vertex>::const_iterator end = poly->vertices_end();
00132   ref<const Polyhedron::Vertex> c(*vert);
00133   Real h = dot(c->coordinate(), v);
00134   while (vert != end) {
00135     if ((d = dot((*vert)->coordinate(),v)) > h) {
00136       c = *vert;
00137       h = d;
00138     }
00139     ++vert;
00140   } 
00141   return c->coordinate();
00142   */
00143 
00144   // Start with the last support point (if any) and hill climb until we get to the top
00145   ref<const Polyhedron::Vertex> c; // current vertex
00146   if (s->lastSupport != 0)
00147     c = s->lastSupport;
00148   else {
00149     if (poly->vertices_begin() == poly->vertices_end())
00150       throw std::runtime_error(Exception("can't collide a polyhedron that has no vertices"));
00151     c = *poly->vertices_begin(); // first vert (any would do)
00152   }
00153 
00154   Real h = dot(c->coordinate(), v);
00155   Real d;
00156 
00157   ref<const Polyhedron::Vertex> last_vertex;
00158   for(;;) {
00159     // loop through edges of c and check each vert at the other end of the edge (vert)
00160     Polyhedron::EdgeList::const_iterator_const e = c->edges_begin();
00161     Polyhedron::EdgeList::const_iterator_const end = c->edges_end();
00162     
00163     ref<const Polyhedron::Vertex> vert = (*e)->otherVertex(c);
00164     d = dot(vert->coordinate(), v);
00165     while ((e != end) && ((vert == last_vertex)||(d <= h)) ) {
00166       ++e;
00167       if (e != end) { //!!! remove??
00168         vert = (*e)->otherVertex(c);
00169         d = dot(vert->coordinate(), v);
00170       }
00171     }
00172     // we either found a d > h (that wasn't the last vertex) or exhasted the edges
00173     if (e == end) { // no more edges; must have the biggest h
00174       s->lastSupport = c;
00175       s->lastSupportPoint = c->coordinate();
00176 
00177       return c->coordinate();
00178     }
00179     
00180     last_vertex = c;
00181     c = vert;
00182     h = d;
00183   } // for
00184   
00185 }
00186 
00187 
00188 
00189 
00190 

Generated on Thu Jul 29 15:56:23 2004 for OpenSim by doxygen 1.3.6