From 8dbe681143f7e658ed257dc25a67bdf4dbdc9e3d Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 24 Feb 2015 23:51:00 +0100 Subject: [PATCH] Fix bug with Collide flag "polyset" and nested elements --- panda/src/collide/collisionBox.cxx | 16 +++++++----- panda/src/egg2pg/eggLoader.cxx | 41 ++++++++++++++---------------- panda/src/pgraph/polylightNode.I | 5 ++-- panda/src/pgraph/polylightNode.cxx | 24 +++++++++++++++++ panda/src/pgraph/polylightNode.h | 8 +++--- 5 files changed, 59 insertions(+), 35 deletions(-) diff --git a/panda/src/collide/collisionBox.cxx b/panda/src/collide/collisionBox.cxx index f467d73a8b..e1bdf03970 100644 --- a/panda/src/collide/collisionBox.cxx +++ b/panda/src/collide/collisionBox.cxx @@ -144,15 +144,19 @@ test_intersection(const CollisionEntry &entry) const { //////////////////////////////////////////////////////////////////// void CollisionBox:: xform(const LMatrix4 &mat) { + _min = _min * mat; + _max = _max * mat; _center = _center * mat; - for(int v = 0; v < 8; v++) + for(int v = 0; v < 8; v++) { _vertex[v] = _vertex[v] * mat; - for(int p = 0; p < 6 ; p++) + } + for(int p = 0; p < 6 ; 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(); mark_viz_stale(); mark_internal_bounds_stale(); diff --git a/panda/src/egg2pg/eggLoader.cxx b/panda/src/egg2pg/eggLoader.cxx index 8cafc8dced..ae3be83199 100644 --- a/panda/src/egg2pg/eggLoader.cxx +++ b/panda/src/egg2pg/eggLoader.cxx @@ -1865,6 +1865,10 @@ make_node(EggGroup *egg_group, PandaNode *parent) { node = new CollisionNode(egg_group->get_name()); 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 we also specified to keep the geometry, continue 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_color(color); pnode->set_radius(radius); + + pnode->xform(LCAST(PN_stdfloat, egg_group->get_vertex_to_node())); + node = pnode; - + } else if (egg_group->get_switch_flag()) { if (egg_group->get_switch_fps() != 0.0) { // Create a sequence node. @@ -2790,7 +2797,6 @@ find_first_polygon(EggGroup *egg_group) { bool EggLoader:: make_sphere(EggGroup *egg_group, EggGroup::CollideFlags flags, LPoint3 ¢er, PN_stdfloat &radius, LColor &color) { - bool success=false; EggGroup *geom_group = find_collision_geometry(egg_group, flags); if (geom_group != (EggGroup *)NULL) { // Collect all of the vertices. @@ -2822,15 +2828,12 @@ make_sphere(EggGroup *egg_group, EggGroup::CollideFlags flags, d_center /= (double)num_vertices; //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. double radius2 = 0.0; for (vi = vertices.begin(); vi != vertices.end(); ++vi) { EggVertex *vtx = (*vi); LPoint3d p3 = vtx->get_pos3(); - LVector3d v = p3 * mat - d_center; + LVector3d v = p3 - d_center; radius2 = max(radius2, v.length_squared()); } @@ -2841,10 +2844,10 @@ make_sphere(EggGroup *egg_group, EggGroup::CollideFlags flags, vi = vertices.begin(); EggVertex *clr_vtx = (*vi); 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])); } - 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 false; @@ -3170,7 +3172,6 @@ make_collision_tube(EggGroup *egg_group, CollisionNode *cnode, // also determine the centroid). We compute this in node space. size_t num_vertices = vertices.size(); if (num_vertices != 0) { - LMatrix4d mat = egg_group->get_vertex_to_node(); pvector vpos; vpos.reserve(num_vertices); @@ -3178,7 +3179,7 @@ make_collision_tube(EggGroup *egg_group, CollisionNode *cnode, pset::const_iterator vi; for (vi = vertices.begin(); vi != vertices.end(); ++vi) { EggVertex *vtx = (*vi); - LPoint3d pos = vtx->get_pos3() * mat; + const LPoint3d &pos = vtx->get_pos3(); vpos.push_back(pos); center += pos; } @@ -3420,20 +3421,18 @@ create_collision_plane(EggPolygon *egg_poly, EggGroup *parent_group) { << "\n"; } - LMatrix4d mat = egg_poly->get_vertex_to_node(); - pvector vertices; if (!egg_poly->empty()) { EggPolygon::const_iterator vi; vi = egg_poly->begin(); - LVertexd vert = (*vi)->get_pos3() * mat; + LVertexd vert = (*vi)->get_pos3(); vertices.push_back(LCAST(PN_stdfloat, vert)); LVertexd last_vert = vert; ++vi; while (vi != egg_poly->end()) { - vert = (*vi)->get_pos3() * mat; + vert = (*vi)->get_pos3(); if (!vert.almost_equal(last_vert)) { vertices.push_back(LCAST(PN_stdfloat, vert)); } @@ -3461,7 +3460,6 @@ void EggLoader:: create_collision_polygons(CollisionNode *cnode, EggPolygon *egg_poly, EggGroup *parent_group, EggGroup::CollideFlags flags) { - LMatrix4d mat = egg_poly->get_vertex_to_node(); PT(EggGroup) group = new EggGroup; @@ -3489,13 +3487,13 @@ create_collision_polygons(CollisionNode *cnode, EggPolygon *egg_poly, EggPolygon::const_iterator vi; vi = poly->begin(); - LVertexd vert = (*vi)->get_pos3() * mat; + LVertexd vert = (*vi)->get_pos3(); vertices.push_back(LCAST(PN_stdfloat, vert)); LVertexd last_vert = vert; ++vi; while (vi != poly->end()) { - vert = (*vi)->get_pos3() * mat; + vert = (*vi)->get_pos3(); if (!vert.almost_equal(last_vert)) { vertices.push_back(LCAST(PN_stdfloat, vert)); } @@ -3513,12 +3511,11 @@ create_collision_polygons(CollisionNode *cnode, EggPolygon *egg_poly, if (cspoly->is_valid()) { apply_collision_flags(cspoly, flags); cnode->add_solid(cspoly); - } + } } } } - //////////////////////////////////////////////////////////////////// // Function: EggLoader::create_collision_floor_mesh // Access: Private diff --git a/panda/src/pgraph/polylightNode.I b/panda/src/pgraph/polylightNode.I index 4571035db7..c9b7de7c6d 100755 --- a/panda/src/pgraph/polylightNode.I +++ b/panda/src/pgraph/polylightNode.I @@ -85,11 +85,10 @@ disable(){ // Description: Set this light's position //////////////////////////////////////////////////////////////////// INLINE void PolylightNode:: -set_pos(const LVecBase3 &position){ +set_pos(const LPoint3 &position) { _position = position; } - //////////////////////////////////////////////////////////////////// // Function: PolylightNode::set_pos // Access: Published @@ -107,7 +106,7 @@ set_pos(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z){ // Access: Published // Description: Returns position as a LPoint3 //////////////////////////////////////////////////////////////////// -INLINE LVecBase3 PolylightNode:: +INLINE LPoint3 PolylightNode:: get_pos() const { return _position; } diff --git a/panda/src/pgraph/polylightNode.cxx b/panda/src/pgraph/polylightNode.cxx index 1d2c87693c..8d383db018 100755 --- a/panda/src/pgraph/polylightNode.cxx +++ b/panda/src/pgraph/polylightNode.cxx @@ -65,6 +65,30 @@ make_copy() const { 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 // Access: Public diff --git a/panda/src/pgraph/polylightNode.h b/panda/src/pgraph/polylightNode.h index 8eb3aacbee..caacbecf57 100755 --- a/panda/src/pgraph/polylightNode.h +++ b/panda/src/pgraph/polylightNode.h @@ -58,9 +58,9 @@ PUBLISHED: PolylightNode(const string &name); INLINE void enable(); 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 LVecBase3 get_pos() const; + INLINE LPoint3 get_pos() const; INLINE void set_color(const LColor &color); INLINE void set_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b); INLINE LColor get_color() const; @@ -100,11 +100,11 @@ PUBLISHED: public: LColor flicker() const; virtual PandaNode *make_copy() const; + virtual void xform(const LMatrix4 &mat); - private: bool _enabled; - LVecBase3 _position; + LPoint3 _position; LColor _color; PN_stdfloat _radius; Attenuation_Type _attenuation_type;