Browse Source

Fix bug with Collide flag "polyset" and nested <Transform> elements

rdb 10 years ago
parent
commit
8dbe681143

+ 10 - 6
panda/src/collide/collisionBox.cxx

@@ -144,15 +144,19 @@ test_intersection(const CollisionEntry &entry) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void CollisionBox::
 void CollisionBox::
 xform(const LMatrix4 &mat) {
 xform(const LMatrix4 &mat) {
+  _min = _min * mat;
+  _max = _max * mat;
   _center = _center * mat;
   _center = _center * mat;
-  for(int v = 0; v < 8; v++)
+  for(int v = 0; v < 8; v++) {
     _vertex[v] = _vertex[v] * mat;
     _vertex[v] = _vertex[v] * mat;
-  for(int p = 0; p < 6 ; p++)
+  }
+  for(int p = 0; p < 6 ; p++) {
     _planes[p] = set_plane(p);
     _planes[p] = set_plane(p);
-  _x = _vertex[0].get_x()-_center.get_x(); 
-  _y = _vertex[0].get_y()-_center.get_y();
-  _z = _vertex[0].get_z()-_center.get_z();
-  _radius = sqrt( _x*_x + _y*_y + _z*_z );
+  }
+  _x = _vertex[0].get_x() - _center.get_x();
+  _y = _vertex[0].get_y() - _center.get_y();
+  _z = _vertex[0].get_z() - _center.get_z();
+  _radius = sqrt(_x * _x + _y * _y + _z * _z);
   setup_box();
   setup_box();
   mark_viz_stale();
   mark_viz_stale();
   mark_internal_bounds_stale();
   mark_internal_bounds_stale();

+ 19 - 22
panda/src/egg2pg/eggLoader.cxx

@@ -1865,6 +1865,10 @@ make_node(EggGroup *egg_group, PandaNode *parent) {
     node = new CollisionNode(egg_group->get_name());
     node = new CollisionNode(egg_group->get_name());
 
 
     make_collision_solids(egg_group, egg_group, (CollisionNode *)node.p());
     make_collision_solids(egg_group, egg_group, (CollisionNode *)node.p());
+
+    // Transform all of the collision solids into local space.
+    node->xform(LCAST(PN_stdfloat, egg_group->get_vertex_to_node()));
+
     if ((egg_group->get_collide_flags() & EggGroup::CF_keep) != 0) {
     if ((egg_group->get_collide_flags() & EggGroup::CF_keep) != 0) {
       // If we also specified to keep the geometry, continue the
       // If we also specified to keep the geometry, continue the
       // traversal.  In this case, we create a new PandaNode to be the
       // traversal.  In this case, we create a new PandaNode to be the
@@ -1925,8 +1929,11 @@ make_node(EggGroup *egg_group, PandaNode *parent) {
     pnode->set_pos(center);
     pnode->set_pos(center);
     pnode->set_color(color);
     pnode->set_color(color);
     pnode->set_radius(radius);
     pnode->set_radius(radius);
+
+    pnode->xform(LCAST(PN_stdfloat, egg_group->get_vertex_to_node()));
+
     node = pnode;
     node = pnode;
-    
+
   } else if (egg_group->get_switch_flag()) {
   } else if (egg_group->get_switch_flag()) {
     if (egg_group->get_switch_fps() != 0.0) {
     if (egg_group->get_switch_fps() != 0.0) {
       // Create a sequence node.
       // Create a sequence node.
@@ -2790,7 +2797,6 @@ find_first_polygon(EggGroup *egg_group) {
 bool EggLoader::
 bool EggLoader::
 make_sphere(EggGroup *egg_group, EggGroup::CollideFlags flags, 
 make_sphere(EggGroup *egg_group, EggGroup::CollideFlags flags, 
             LPoint3 &center, PN_stdfloat &radius, LColor &color) {
             LPoint3 &center, PN_stdfloat &radius, LColor &color) {
-  bool success=false;
   EggGroup *geom_group = find_collision_geometry(egg_group, flags);
   EggGroup *geom_group = find_collision_geometry(egg_group, flags);
   if (geom_group != (EggGroup *)NULL) {
   if (geom_group != (EggGroup *)NULL) {
     // Collect all of the vertices.
     // Collect all of the vertices.
@@ -2822,15 +2828,12 @@ make_sphere(EggGroup *egg_group, EggGroup::CollideFlags flags,
       d_center /= (double)num_vertices;
       d_center /= (double)num_vertices;
       //egg2pg_cat.debug() << "make_sphere d_center: " << d_center << "\n";
       //egg2pg_cat.debug() << "make_sphere d_center: " << d_center << "\n";
 
 
-      LMatrix4d mat = egg_group->get_vertex_to_node();
-      d_center = d_center * mat;
-
       // And the furthest vertex determines the radius.
       // And the furthest vertex determines the radius.
       double radius2 = 0.0;
       double radius2 = 0.0;
       for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
       for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
         EggVertex *vtx = (*vi);
         EggVertex *vtx = (*vi);
         LPoint3d p3 = vtx->get_pos3();
         LPoint3d p3 = vtx->get_pos3();
-                LVector3d v = p3 * mat - d_center;
+                LVector3d v = p3 - d_center;
         radius2 = max(radius2, v.length_squared());
         radius2 = max(radius2, v.length_squared());
       }
       }
 
 
@@ -2841,10 +2844,10 @@ make_sphere(EggGroup *egg_group, EggGroup::CollideFlags flags,
       vi = vertices.begin();
       vi = vertices.begin();
       EggVertex *clr_vtx = (*vi);
       EggVertex *clr_vtx = (*vi);
       color = clr_vtx->get_color();
       color = clr_vtx->get_color();
-      success = true;
+      return true;
     }
     }
   }
   }
-  return success;
+  return false;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -2900,9 +2903,8 @@ make_box(EggGroup *egg_group, EggGroup::CollideFlags flags,
                  max(max_pd[2], pos[2]));
                  max(max_pd[2], pos[2]));
     }
     }
 
 
-    LMatrix4d mat = egg_group->get_vertex_to_node();
-    min_p = LCAST(PN_stdfloat, min_pd * mat);
-    max_p = LCAST(PN_stdfloat, max_pd * mat);
+    min_p = LCAST(PN_stdfloat, min_pd);
+    max_p = LCAST(PN_stdfloat, max_pd);
     return (min_pd != max_pd);
     return (min_pd != max_pd);
   }
   }
   return false;
   return false;
@@ -3170,7 +3172,6 @@ make_collision_tube(EggGroup *egg_group, CollisionNode *cnode,
     // also determine the centroid).  We compute this in node space.
     // also determine the centroid).  We compute this in node space.
     size_t num_vertices = vertices.size();
     size_t num_vertices = vertices.size();
     if (num_vertices != 0) {
     if (num_vertices != 0) {
-      LMatrix4d mat = egg_group->get_vertex_to_node();
       pvector<LPoint3d> vpos;
       pvector<LPoint3d> vpos;
       vpos.reserve(num_vertices);
       vpos.reserve(num_vertices);
       
       
@@ -3178,7 +3179,7 @@ make_collision_tube(EggGroup *egg_group, CollisionNode *cnode,
       pset<EggVertex *>::const_iterator vi;
       pset<EggVertex *>::const_iterator vi;
       for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
       for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
         EggVertex *vtx = (*vi);
         EggVertex *vtx = (*vi);
-        LPoint3d pos = vtx->get_pos3() * mat;
+        const LPoint3d &pos = vtx->get_pos3();
         vpos.push_back(pos);
         vpos.push_back(pos);
         center += pos;
         center += pos;
       }
       }
@@ -3420,20 +3421,18 @@ create_collision_plane(EggPolygon *egg_poly, EggGroup *parent_group) {
       << "\n";
       << "\n";
   }
   }
 
 
-  LMatrix4d mat = egg_poly->get_vertex_to_node();
-
   pvector<LVertex> vertices;
   pvector<LVertex> vertices;
   if (!egg_poly->empty()) {
   if (!egg_poly->empty()) {
     EggPolygon::const_iterator vi;
     EggPolygon::const_iterator vi;
     vi = egg_poly->begin();
     vi = egg_poly->begin();
 
 
-    LVertexd vert = (*vi)->get_pos3() * mat;
+    LVertexd vert = (*vi)->get_pos3();
     vertices.push_back(LCAST(PN_stdfloat, vert));
     vertices.push_back(LCAST(PN_stdfloat, vert));
 
 
     LVertexd last_vert = vert;
     LVertexd last_vert = vert;
     ++vi;
     ++vi;
     while (vi != egg_poly->end()) {
     while (vi != egg_poly->end()) {
-      vert = (*vi)->get_pos3() * mat;
+      vert = (*vi)->get_pos3();
       if (!vert.almost_equal(last_vert)) {
       if (!vert.almost_equal(last_vert)) {
         vertices.push_back(LCAST(PN_stdfloat, vert));
         vertices.push_back(LCAST(PN_stdfloat, vert));
       }
       }
@@ -3461,7 +3460,6 @@ void EggLoader::
 create_collision_polygons(CollisionNode *cnode, EggPolygon *egg_poly,
 create_collision_polygons(CollisionNode *cnode, EggPolygon *egg_poly,
                           EggGroup *parent_group,
                           EggGroup *parent_group,
                           EggGroup::CollideFlags flags) {
                           EggGroup::CollideFlags flags) {
-  LMatrix4d mat = egg_poly->get_vertex_to_node();
 
 
   PT(EggGroup) group = new EggGroup;
   PT(EggGroup) group = new EggGroup;
 
 
@@ -3489,13 +3487,13 @@ create_collision_polygons(CollisionNode *cnode, EggPolygon *egg_poly,
       EggPolygon::const_iterator vi;
       EggPolygon::const_iterator vi;
       vi = poly->begin();
       vi = poly->begin();
 
 
-      LVertexd vert = (*vi)->get_pos3() * mat;
+      LVertexd vert = (*vi)->get_pos3();
       vertices.push_back(LCAST(PN_stdfloat, vert));
       vertices.push_back(LCAST(PN_stdfloat, vert));
 
 
       LVertexd last_vert = vert;
       LVertexd last_vert = vert;
       ++vi;
       ++vi;
       while (vi != poly->end()) {
       while (vi != poly->end()) {
-        vert = (*vi)->get_pos3() * mat;
+        vert = (*vi)->get_pos3();
         if (!vert.almost_equal(last_vert)) {
         if (!vert.almost_equal(last_vert)) {
           vertices.push_back(LCAST(PN_stdfloat, vert));
           vertices.push_back(LCAST(PN_stdfloat, vert));
         }
         }
@@ -3513,12 +3511,11 @@ create_collision_polygons(CollisionNode *cnode, EggPolygon *egg_poly,
       if (cspoly->is_valid()) {
       if (cspoly->is_valid()) {
         apply_collision_flags(cspoly, flags);
         apply_collision_flags(cspoly, flags);
         cnode->add_solid(cspoly);
         cnode->add_solid(cspoly);
-      }        
+      }
     }
     }
   }
   }
 }
 }
 
 
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggLoader::create_collision_floor_mesh
 //     Function: EggLoader::create_collision_floor_mesh
 //       Access: Private
 //       Access: Private

+ 2 - 3
panda/src/pgraph/polylightNode.I

@@ -85,11 +85,10 @@ disable(){
 //  Description: Set this light's position
 //  Description: Set this light's position
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void PolylightNode::
 INLINE void PolylightNode::
-set_pos(const LVecBase3 &position){
+set_pos(const LPoint3 &position) {
   _position = position;
   _position = position;
 }
 }
 
 
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PolylightNode::set_pos
 //     Function: PolylightNode::set_pos
 //       Access: Published
 //       Access: Published
@@ -107,7 +106,7 @@ set_pos(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z){
 //       Access: Published
 //       Access: Published
 //  Description: Returns position as a LPoint3
 //  Description: Returns position as a LPoint3
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE LVecBase3 PolylightNode::
+INLINE LPoint3 PolylightNode::
 get_pos() const {
 get_pos() const {
   return _position;
   return _position;
 }
 }

+ 24 - 0
panda/src/pgraph/polylightNode.cxx

@@ -65,6 +65,30 @@ make_copy() const {
   return new PolylightNode(*this);
   return new PolylightNode(*this);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: PolylightNode::xform
+//       Access: Public, Virtual
+//  Description: Transforms the contents of this node by the indicated
+//               matrix, if it means anything to do so.  For most
+//               kinds of nodes, this does nothing.
+////////////////////////////////////////////////////////////////////
+void PolylightNode::
+xform(const LMatrix4 &mat) {
+  nassertv(!mat.is_nan());
+
+  if (mat.almost_equal(LMatrix4::ident_mat())) {
+    return;
+  }
+
+  _position = _position * mat;
+
+  // This is a little cheesy and fails miserably in the presence of a
+  // non-uniform scale.
+  LVector3 radius_v = LVector3(_radius, 0.0f, 0.0f) * mat;
+  _radius = length(radius_v);
+  mark_internal_bounds_stale();
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PolylightNode::Constructor
 //     Function: PolylightNode::Constructor
 //       Access: Public
 //       Access: Public

+ 4 - 4
panda/src/pgraph/polylightNode.h

@@ -58,9 +58,9 @@ PUBLISHED:
   PolylightNode(const string &name);
   PolylightNode(const string &name);
   INLINE void enable();
   INLINE void enable();
   INLINE void disable();
   INLINE void disable();
-  INLINE void set_pos(const LVecBase3 &position);
+  INLINE void set_pos(const LPoint3 &position);
   INLINE void set_pos(PN_stdfloat x,PN_stdfloat y, PN_stdfloat z);
   INLINE void set_pos(PN_stdfloat x,PN_stdfloat y, PN_stdfloat z);
-  INLINE LVecBase3 get_pos() const;
+  INLINE LPoint3 get_pos() const;
   INLINE void set_color(const LColor &color);
   INLINE void set_color(const LColor &color);
   INLINE void set_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b);
   INLINE void set_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b);
   INLINE LColor get_color() const;
   INLINE LColor get_color() const;
@@ -100,11 +100,11 @@ PUBLISHED:
 public:
 public:
   LColor flicker() const;
   LColor flicker() const;
   virtual PandaNode *make_copy() const;
   virtual PandaNode *make_copy() const;
+  virtual void xform(const LMatrix4 &mat);
 
 
-  
 private:
 private:
   bool _enabled;
   bool _enabled;
-  LVecBase3 _position;
+  LPoint3 _position;
   LColor _color;
   LColor _color;
   PN_stdfloat _radius;
   PN_stdfloat _radius;
   Attenuation_Type _attenuation_type;
   Attenuation_Type _attenuation_type;