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

This commit is contained in:
rdb 2015-02-24 23:51:00 +01:00
parent 46ddd46c5c
commit 8dbe681143
5 changed files with 59 additions and 35 deletions

View File

@ -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();

View File

@ -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 &center, 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<LPoint3d> vpos;
vpos.reserve(num_vertices);
@ -3178,7 +3179,7 @@ make_collision_tube(EggGroup *egg_group, CollisionNode *cnode,
pset<EggVertex *>::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<LVertex> 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

View File

@ -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;
}

View File

@ -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

View File

@ -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;