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 #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
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
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 ref<const Polyhedron::Vertex> c;
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();
00152 }
00153
00154 Real h = dot(c->coordinate(), v);
00155 Real d;
00156
00157 ref<const Polyhedron::Vertex> last_vertex;
00158 for(;;) {
00159
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) {
00168 vert = (*e)->otherVertex(c);
00169 d = dot(vert->coordinate(), v);
00170 }
00171 }
00172
00173 if (e == end) {
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 }
00184
00185 }
00186
00187
00188
00189
00190