Browse Source

better support for small collision polygons

David Rose 17 years ago
parent
commit
2210ebe3df
2 changed files with 62 additions and 29 deletions
  1. 2 2
      panda/src/collide/collisionPolygon.cxx
  2. 60 27
      panda/src/collide/collisionTraverser.cxx

+ 2 - 2
panda/src/collide/collisionPolygon.cxx

@@ -97,7 +97,7 @@ verify_points(const LPoint3f *begin, const LPoint3f *end) {
       // Make sure no points are repeated.
       const LPoint3f *pj;
       for (pj = begin; pj != pi && all_ok; ++pj) {
-        if ((*pj).almost_equal(*pi)) {
+        if ((*pj) == (*pi)) {
           all_ok = false;
         }
       }
@@ -1198,7 +1198,7 @@ setup_points(const LPoint3f *begin, const LPoint3f *end) {
     normal[2] += p0[0] * p1[1] - p0[1] * p1[0];
   }
 
-  if (IS_NEARLY_ZERO(normal.length_squared())) {
+  if (normal.length_squared() == 0.0f) {
     // The polygon has no area.
     return;
   }

+ 60 - 27
panda/src/collide/collisionTraverser.cxx

@@ -1302,7 +1302,7 @@ compare_collider_to_geom(CollisionEntry &entry, const Geom *geom,
     nassertv(ci != _colliders.end());
 
     if (geom->get_primitive_type() == Geom::PT_polygons) {
-      const GeomVertexData *data =geom->get_vertex_data();
+      const GeomVertexData *data = geom->get_vertex_data();
       GeomVertexReader vertex(data, InternalName::get_vertex());
       
       int num_primitives = geom->get_num_primitives();
@@ -1311,33 +1311,66 @@ compare_collider_to_geom(CollisionEntry &entry, const Geom *geom,
         CPT(GeomPrimitive) tris = primitive->decompose();
         nassertv(tris->is_of_type(GeomTriangles::get_class_type()));
 
-        GeomVertexReader index(tris->get_vertices(), 0);
-        while (!index.is_at_end()) {
-          Vertexf v[3];
-
-          vertex.set_row(index.get_data1i());
-          v[0] = vertex.get_data3f();
-          vertex.set_row(index.get_data1i());
-          v[1] = vertex.get_data3f();
-          vertex.set_row(index.get_data1i());
-          v[2] = vertex.get_data3f();
-          
-          // Generate a temporary CollisionGeom on the fly for each
-          // triangle in the Geom.
-          if (CollisionPolygon::verify_points(v[0], v[1], v[2])) {
-            bool within_solid_bounds = true;
-            if (from_node_gbv != (GeometricBoundingVolume *)NULL) {
-              PT(BoundingSphere) sphere = new BoundingSphere;
-              sphere->around(v, v + 3);
-              within_solid_bounds = (sphere->contains(from_node_gbv) != 0);
-              #ifdef DO_PSTATS
-              CollisionGeom::_volume_pcollector.add_level(1);
-              #endif  // DO_PSTATS
+        if (tris->is_indexed()) {
+          // Indexed case.
+          GeomVertexReader index(tris->get_vertices(), 0);
+          while (!index.is_at_end()) {
+            Vertexf v[3];
+            
+            vertex.set_row(index.get_data1i());
+            v[0] = vertex.get_data3f();
+            vertex.set_row(index.get_data1i());
+            v[1] = vertex.get_data3f();
+            vertex.set_row(index.get_data1i());
+            v[2] = vertex.get_data3f();
+            
+            // Generate a temporary CollisionGeom on the fly for each
+            // triangle in the Geom.
+            if (CollisionPolygon::verify_points(v[0], v[1], v[2])) {
+              bool within_solid_bounds = true;
+              if (from_node_gbv != (GeometricBoundingVolume *)NULL) {
+                PT(BoundingSphere) sphere = new BoundingSphere;
+                sphere->around(v, v + 3);
+                within_solid_bounds = (sphere->contains(from_node_gbv) != 0);
+#ifdef DO_PSTATS
+                CollisionGeom::_volume_pcollector.add_level(1);
+#endif  // DO_PSTATS
+              }
+              if (within_solid_bounds) {
+                PT(CollisionGeom) cgeom = new CollisionGeom(v[0], v[1], v[2]);
+                entry._into = cgeom;
+                entry.test_intersection((*ci).second, this);
+              }
             }
-            if (within_solid_bounds) {
-              PT(CollisionGeom) cgeom = new CollisionGeom(v[0], v[1], v[2]);
-              entry._into = cgeom;
-              entry.test_intersection((*ci).second, this);
+          }
+        } else {
+          // Non-indexed case.
+          vertex.set_row(primitive->get_first_vertex());
+          int num_vertices = primitive->get_num_vertices();
+          for (int i = 0; i < num_vertices; i += 3) {
+            Vertexf v[3];
+            
+            v[0] = vertex.get_data3f();
+            v[1] = vertex.get_data3f();
+            v[2] = vertex.get_data3f();
+            
+            // Generate a temporary CollisionGeom on the fly for each
+            // triangle in the Geom.
+            if (CollisionPolygon::verify_points(v[0], v[1], v[2])) {
+              bool within_solid_bounds = true;
+              if (from_node_gbv != (GeometricBoundingVolume *)NULL) {
+                PT(BoundingSphere) sphere = new BoundingSphere;
+                sphere->around(v, v + 3);
+                within_solid_bounds = (sphere->contains(from_node_gbv) != 0);
+#ifdef DO_PSTATS
+                CollisionGeom::_volume_pcollector.add_level(1);
+#endif  // DO_PSTATS
+              }
+              if (within_solid_bounds) {
+                PT(CollisionGeom) cgeom = new CollisionGeom(v[0], v[1], v[2]);
+                entry._into = cgeom;
+                entry.test_intersection((*ci).second, this);
+              }
             }
           }
         }