From c1fe4c1938c15853841b55da54230eafb010b3c4 Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 21 Mar 2002 04:34:47 +0000 Subject: [PATCH] pgraph viz collision solids --- panda/src/collide/collisionPlane.cxx | 75 ++++++++++- panda/src/collide/collisionPlane.h | 1 + panda/src/collide/collisionPolygon.cxx | 46 ++++++- panda/src/collide/collisionPolygon.h | 1 + panda/src/collide/collisionRay.cxx | 44 ++++++- panda/src/collide/collisionRay.h | 1 + panda/src/collide/collisionSegment.cxx | 34 ++++- panda/src/collide/collisionSegment.h | 1 + panda/src/collide/collisionSolid.I | 1 + panda/src/collide/collisionSolid.cxx | 166 +++++++++++++++++++++++-- panda/src/collide/collisionSolid.h | 14 ++- panda/src/collide/collisionSphere.cxx | 23 ++++ panda/src/collide/collisionSphere.h | 1 + panda/src/collide/qpcollisionNode.cxx | 20 ++- 14 files changed, 402 insertions(+), 26 deletions(-) diff --git a/panda/src/collide/collisionPlane.cxx b/panda/src/collide/collisionPlane.cxx index 2f668d0aaa..e08723f981 100644 --- a/panda/src/collide/collisionPlane.cxx +++ b/panda/src/collide/collisionPlane.cxx @@ -27,16 +27,17 @@ #include "config_collide.h" #include "pointerToArray.h" -#include "geomNode.h" +#include "qpgeomNode.h" #include "geom.h" #include "datagram.h" #include "datagramIterator.h" #include "bamReader.h" #include "bamWriter.h" - #include "omniBoundingVolume.h" #include "geomQuad.h" +#include "geomNode.h" + TypeHandle CollisionPlane::_type_handle; //////////////////////////////////////////////////////////////////// @@ -357,6 +358,76 @@ recompute_viz(Node *parent) { add_wireframe_viz(parent, viz); } +//////////////////////////////////////////////////////////////////// +// Function: CollisionPlane::fill_viz_geom +// Access: Protected, Virtual +// Description: Fills the _viz_geom GeomNode up with Geoms suitable +// for rendering this solid. +//////////////////////////////////////////////////////////////////// +void CollisionPlane:: +fill_viz_geom() { + if (collide_cat.is_debug()) { + collide_cat.debug() + << "Recomputing viz for " << *this << "\n"; + } + + // Since we can't represent an infinite plane, we'll have to be + // satisfied with drawing a big polygon. Choose four points on the + // plane to be the corners of the polygon. + + // We must choose four points fairly reasonably spread apart on + // the plane. We'll start with a center point and one corner + // point, and then use cross products to find the remaining three + // corners of a square. + + // The center point will be on the axis with the largest + // coefficent. The first corner will be diagonal in the other two + // dimensions. + + LPoint3f cp; + LVector3f p1, p2, p3, p4; + + LVector3f normal = get_normal(); + float D = _plane._d; + + if (fabs(normal[0]) > fabs(normal[1]) && + fabs(normal[0]) > fabs(normal[2])) { + // X has the largest coefficient. + cp.set(-D / normal[0], 0.0f, 0.0f); + p1 = LPoint3f(-(normal[1] + normal[2] + D)/normal[0], 1.0f, 1.0f) - cp; + + } else if (fabs(normal[1]) > fabs(normal[2])) { + // Y has the largest coefficient. + cp.set(0.0f, -D / normal[1], 0.0f); + p1 = LPoint3f(1.0f, -(normal[0] + normal[2] + D)/normal[1], 1.0f) - cp; + + } else { + // Z has the largest coefficient. + cp.set(0.0f, 0.0f, -D / normal[2]); + p1 = LPoint3f(1.0f, 1.0f, -(normal[0] + normal[1] + D)/normal[2]) - cp; + } + + p1.normalize(); + p2 = cross(normal, p1); + p3 = cross(normal, p2); + p4 = cross(normal, p3); + + static const double plane_scale = 10.0; + + PTA_Vertexf verts; + verts.push_back(cp + p1 * plane_scale); + verts.push_back(cp + p2 * plane_scale); + verts.push_back(cp + p3 * plane_scale); + verts.push_back(cp + p4 * plane_scale); + + GeomQuad *quad = new GeomQuad; + quad->set_coords(verts); + quad->set_num_prims(1); + + _viz_geom->add_geom(quad, get_solid_viz_state()); + _viz_geom->add_geom(quad, get_wireframe_viz_state()); +} + //////////////////////////////////////////////////////////////////// // Function: CollisionPlane::write_datagram // Access: Public diff --git a/panda/src/collide/collisionPlane.h b/panda/src/collide/collisionPlane.h index ffc1c7fee3..6f8f09f70c 100644 --- a/panda/src/collide/collisionPlane.h +++ b/panda/src/collide/collisionPlane.h @@ -81,6 +81,7 @@ protected: const qpCollisionEntry &entry) const; virtual void recompute_viz(Node *parent); + virtual void fill_viz_geom(); private: Planef _plane; diff --git a/panda/src/collide/collisionPolygon.cxx b/panda/src/collide/collisionPolygon.cxx index d5518fcfa8..f622c63178 100644 --- a/panda/src/collide/collisionPolygon.cxx +++ b/panda/src/collide/collisionPolygon.cxx @@ -29,7 +29,7 @@ #include "boundingSphere.h" #include "pointerToArray.h" -#include "geomNode.h" +#include "qpgeomNode.h" #include "geom.h" #include "datagram.h" #include "datagramIterator.h" @@ -37,6 +37,8 @@ #include "bamWriter.h" #include "geomPolygon.h" +#include "geomNode.h" + #include TypeHandle CollisionPolygon::_type_handle; @@ -697,6 +699,48 @@ recompute_viz(Node *parent) { add_wireframe_viz(parent, viz); } +//////////////////////////////////////////////////////////////////// +// Function: CollisionPolygon::fill_viz_geom +// Access: Protected, Virtual +// Description: Fills the _viz_geom GeomNode up with Geoms suitable +// for rendering this solid. +//////////////////////////////////////////////////////////////////// +void CollisionPolygon:: +fill_viz_geom() { + if (collide_cat.is_debug()) { + collide_cat.debug() + << "Recomputing viz for " << *this << "\n"; + } + + if (_points.size() < 3) { + if (collide_cat.is_debug()) { + collide_cat.debug() + << "(Degenerate poly, ignoring.)\n"; + } + return; + } + + PTA_Vertexf verts; + Points::const_iterator pi; + for (pi = _points.begin(); pi != _points.end(); ++pi) { + verts.push_back(to_3d(*pi)); + } + if (_reversed) { + reverse(verts.begin(), verts.end()); + } + + PTA_int lengths; + lengths.push_back(_points.size()); + + GeomPolygon *polygon = new GeomPolygon; + polygon->set_coords(verts); + polygon->set_num_prims(1); + polygon->set_lengths(lengths); + + _viz_geom->add_geom(polygon, get_solid_viz_state()); + _viz_geom->add_geom(polygon, get_wireframe_viz_state()); +} + //////////////////////////////////////////////////////////////////// // Function: CollisionPolygon::is_inside // Access: Private diff --git a/panda/src/collide/collisionPolygon.h b/panda/src/collide/collisionPolygon.h index c7844ba916..ec952f6f34 100644 --- a/panda/src/collide/collisionPolygon.h +++ b/panda/src/collide/collisionPolygon.h @@ -90,6 +90,7 @@ protected: const qpCollisionEntry &entry) const; virtual void recompute_viz(Node *parent); + virtual void fill_viz_geom(); private: bool is_inside(const LPoint2f &p) const; diff --git a/panda/src/collide/collisionRay.cxx b/panda/src/collide/collisionRay.cxx index 2fa1a27631..2e81729893 100644 --- a/panda/src/collide/collisionRay.cxx +++ b/panda/src/collide/collisionRay.cxx @@ -23,13 +23,15 @@ #include "qpcollisionEntry.h" #include "config_collide.h" #include "geom.h" -#include "geomNode.h" +#include "qpgeomNode.h" #include "geomLinestrip.h" #include "boundingLine.h" -#include "lensNode.h" #include "qplensNode.h" #include "lens.h" +#include "lensNode.h" +#include "geomNode.h" + TypeHandle CollisionRay::_type_handle; @@ -219,3 +221,41 @@ recompute_viz(Node *parent) { viz->add_geom(ray); add_other_viz(parent, viz); } + +//////////////////////////////////////////////////////////////////// +// Function: CollisionRay::fill_viz_geom +// Access: Protected, Virtual +// Description: Fills the _viz_geom GeomNode up with Geoms suitable +// for rendering this solid. +//////////////////////////////////////////////////////////////////// +void CollisionRay:: +fill_viz_geom() { + if (collide_cat.is_debug()) { + collide_cat.debug() + << "Recomputing viz for " << *this << "\n"; + } + + GeomLinestrip *ray = new GeomLinestrip; + PTA_Vertexf verts; + PTA_Colorf colors; + PTA_int lengths; + + #define NUM_POINTS 100 + verts.reserve(NUM_POINTS); + colors.reserve(NUM_POINTS); + + for (int i = 0; i < NUM_POINTS; i++) { + verts.push_back(_origin + (double)i * _direction); + colors.push_back(Colorf(1.0f, 1.0f, 1.0f, 1.0f)+ + ((double)i / 100.0) * Colorf(0.0f, 0.0f, 0.0f, -1.0f)); + } + ray->set_coords(verts); + ray->set_colors(colors, G_PER_VERTEX); + + lengths.push_back(NUM_POINTS-1); + ray->set_lengths(lengths); + + ray->set_num_prims(1); + + _viz_geom->add_geom(ray, get_other_viz_state()); +} diff --git a/panda/src/collide/collisionRay.h b/panda/src/collide/collisionRay.h index bf4d3a9f5d..16228576a2 100644 --- a/panda/src/collide/collisionRay.h +++ b/panda/src/collide/collisionRay.h @@ -80,6 +80,7 @@ protected: protected: virtual void recompute_viz(Node *parent); + virtual void fill_viz_geom(); private: LPoint3f _origin; diff --git a/panda/src/collide/collisionSegment.cxx b/panda/src/collide/collisionSegment.cxx index 15c6389792..beca4fcc1f 100644 --- a/panda/src/collide/collisionSegment.cxx +++ b/panda/src/collide/collisionSegment.cxx @@ -25,14 +25,15 @@ #include "config_collide.h" #include "geom.h" -#include "geomNode.h" -#include "lensNode.h" #include "qplensNode.h" +#include "qpgeomNode.h" #include "lens.h" - #include "geomLine.h" #include "geometricBoundingVolume.h" +#include "geomNode.h" +#include "lensNode.h" + TypeHandle CollisionSegment::_type_handle; @@ -213,3 +214,30 @@ recompute_viz(Node *parent) { viz->add_geom(segment); add_other_viz(parent, viz); } + +//////////////////////////////////////////////////////////////////// +// Function: CollisionSegment::fill_viz_geom +// Access: Protected, Virtual +// Description: Fills the _viz_geom GeomNode up with Geoms suitable +// for rendering this solid. +//////////////////////////////////////////////////////////////////// +void CollisionSegment:: +fill_viz_geom() { + if (collide_cat.is_debug()) { + collide_cat.debug() + << "Recomputing viz for " << *this << "\n"; + } + + GeomLine *segment = new GeomLine; + PTA_Vertexf verts; + PTA_Colorf colors; + verts.push_back(_a); + verts.push_back(_b); + colors.push_back(Colorf(1.0f, 1.0f, 1.0f, 1.0f)); + segment->set_coords(verts); + segment->set_colors(colors, G_OVERALL); + + segment->set_num_prims(1); + + _viz_geom->add_geom(segment, get_other_viz_state()); +} diff --git a/panda/src/collide/collisionSegment.h b/panda/src/collide/collisionSegment.h index a1803c1e0f..e3ac1e115a 100644 --- a/panda/src/collide/collisionSegment.h +++ b/panda/src/collide/collisionSegment.h @@ -83,6 +83,7 @@ protected: protected: virtual void recompute_viz(Node *parent); + virtual void fill_viz_geom(); private: LPoint3f _a, _b; diff --git a/panda/src/collide/collisionSolid.I b/panda/src/collide/collisionSolid.I index 624e49f4e4..3ac02d5161 100644 --- a/panda/src/collide/collisionSolid.I +++ b/panda/src/collide/collisionSolid.I @@ -60,4 +60,5 @@ is_tangible() const { INLINE void CollisionSolid:: mark_viz_stale() { _viz_stale = true; + _viz_geom_stale = true; } diff --git a/panda/src/collide/collisionSolid.cxx b/panda/src/collide/collisionSolid.cxx index bbb6ed5754..8c71621558 100644 --- a/panda/src/collide/collisionSolid.cxx +++ b/panda/src/collide/collisionSolid.cxx @@ -24,20 +24,25 @@ #include "collisionRay.h" #include "collisionSegment.h" -#include -#include -#include -#include -#include -#include +#include "datagram.h" +#include "datagramIterator.h" +#include "bamReader.h" +#include "bamWriter.h" +#include "indent.h" +#include "cullFaceAttrib.h" +#include "colorAttrib.h" +#include "renderModeAttrib.h" +#include "transparencyAttrib.h" +#include "qpgeomNode.h" -#include -#include -#include -#include -#include -#include -#include +#include "renderRelation.h" +#include "geomNode.h" +#include "cullFaceTransition.h" +#include "colorTransition.h" +#include "renderModeTransition.h" +#include "lightTransition.h" +#include "transparencyTransition.h" +#include "textureTransition.h" TypeHandle CollisionSolid::_type_handle; @@ -49,6 +54,7 @@ TypeHandle CollisionSolid::_type_handle; CollisionSolid:: CollisionSolid() { _viz_stale = true; + _viz_geom_stale = true; _tangible = true; } @@ -63,6 +69,7 @@ CollisionSolid(const CollisionSolid ©) : { // Actually, there's not a whole lot here we want to copy. _viz_stale = true; + _viz_geom_stale = true; } //////////////////////////////////////////////////////////////////// @@ -89,6 +96,26 @@ update_viz(Node *parent) { } } +//////////////////////////////////////////////////////////////////// +// Function: CollisionSolid::get_viz +// Access: Public +// Description: Returns a GeomNode that may be rendered to visualize +// the CollisionSolid. +//////////////////////////////////////////////////////////////////// +qpGeomNode *CollisionSolid:: +get_viz() { + if (_viz_geom_stale) { + if (_viz_geom == (qpGeomNode *)NULL) { + _viz_geom = new qpGeomNode("viz"); + } else { + _viz_geom->remove_all_geoms(); + } + fill_viz_geom(); + _viz_geom_stale = false; + } + return _viz_geom; +} + //////////////////////////////////////////////////////////////////// // Function: CollisionSolid::output // Access: Public, Virtual @@ -330,3 +357,116 @@ add_other_viz(Node *parent, GeomNode *viz) { _other_viz_arcs.push_back(arc); } + +//////////////////////////////////////////////////////////////////// +// Function: CollisionSolid::fill_viz_geom +// Access: Protected, Virtual +// Description: Fills the _viz_geom GeomNode up with Geoms suitable +// for rendering this solid. +//////////////////////////////////////////////////////////////////// +void CollisionSolid:: +fill_viz_geom() { +} + +//////////////////////////////////////////////////////////////////// +// Function: CollisionSolid::get_solid_viz_state +// Access: Protected +// Description: Returns a RenderState for rendering collision +// visualizations in solid. This automatically returns +// the appropriate state according to the setting of +// _tangible. +//////////////////////////////////////////////////////////////////// +CPT(RenderState) CollisionSolid:: +get_solid_viz_state() { + // Once someone asks for this pointer, we hold its reference count + // and never free it. + static CPT(RenderState) base_state = (const RenderState *)NULL; + if (base_state == (const RenderState *)NULL) { + base_state = RenderState::make + (CullFaceAttrib::make(CullFaceAttrib::M_cull_clockwise), + RenderModeAttrib::make(RenderModeAttrib::M_filled), + TransparencyAttrib::make(TransparencyAttrib::M_alpha)); + } + + if (_tangible) { + static CPT(RenderState) tangible_state = (const RenderState *)NULL; + if (tangible_state == (const RenderState *)NULL) { + tangible_state = base_state->add_attrib + (ColorAttrib::make_flat(Colorf(1.0f, 1.0f, 1.0f, 0.5f))); + } + return tangible_state; + + } else { + static CPT(RenderState) intangible_state = (const RenderState *)NULL; + if (intangible_state == (const RenderState *)NULL) { + intangible_state = base_state->add_attrib + (ColorAttrib::make_flat(Colorf(1.0f, 0.3f, 0.5f, 0.5f))); + } + return intangible_state; + } +} + + +//////////////////////////////////////////////////////////////////// +// Function: CollisionSolid::get_wireframe_viz_state +// Access: Protected +// Description: Returns a RenderState for rendering collision +// visualizations in wireframe. This automatically returns +// the appropriate state according to the setting of +// _tangible. +//////////////////////////////////////////////////////////////////// +CPT(RenderState) CollisionSolid:: +get_wireframe_viz_state() { + // Once someone asks for this pointer, we hold its reference count + // and never free it. + static CPT(RenderState) base_state = (const RenderState *)NULL; + if (base_state == (const RenderState *)NULL) { + base_state = RenderState::make + (CullFaceAttrib::make(CullFaceAttrib::M_cull_none), + RenderModeAttrib::make(RenderModeAttrib::M_wireframe), + TransparencyAttrib::make(TransparencyAttrib::M_none)); + } + + if (_tangible) { + static CPT(RenderState) tangible_state = (const RenderState *)NULL; + if (tangible_state == (const RenderState *)NULL) { + tangible_state = base_state->add_attrib + (ColorAttrib::make_flat(Colorf(0.0f, 0.0f, 1.0f, 1.0f))); + } + return tangible_state; + + } else { + static CPT(RenderState) intangible_state = (const RenderState *)NULL; + if (intangible_state == (const RenderState *)NULL) { + intangible_state = base_state->add_attrib + (ColorAttrib::make_flat(Colorf(1.0f, 1.0f, 0.0f, 1.0f))); + } + return intangible_state; + } +} + + +//////////////////////////////////////////////////////////////////// +// Function: CollisionSolid::get_other_viz_state +// Access: Protected +// Description: Returns a RenderState for rendering collision +// visualizations for things that are neither solid nor +// exactly wireframe, like rays and segments. +//////////////////////////////////////////////////////////////////// +CPT(RenderState) CollisionSolid:: +get_other_viz_state() { + // Once someone asks for this pointer, we hold its reference count + // and never free it. + static CPT(RenderState) base_state = (const RenderState *)NULL; + if (base_state == (const RenderState *)NULL) { + base_state = RenderState::make + (CullFaceAttrib::make(CullFaceAttrib::M_cull_clockwise), + RenderModeAttrib::make(RenderModeAttrib::M_filled), + TransparencyAttrib::make(TransparencyAttrib::M_alpha)); + } + + // We don't bother to make a distinction here between tangible and + // intangible. + return base_state; +} + diff --git a/panda/src/collide/collisionSolid.h b/panda/src/collide/collisionSolid.h index 12d2d1379f..7b7f2e7ae5 100644 --- a/panda/src/collide/collisionSolid.h +++ b/panda/src/collide/collisionSolid.h @@ -24,8 +24,10 @@ #include "typedWritableReferenceCount.h" #include "boundedObject.h" #include "luse.h" -#include "nodeRelation.h" #include "pointerTo.h" +#include "renderState.h" + +#include "nodeRelation.h" #include "node.h" #include "vector_PT_NodeRelation.h" @@ -36,6 +38,7 @@ class qpCollisionEntry; class CollisionSphere; class Node; class GeomNode; +class qpGeomNode; class CollisionNode; class qpCollisionNode; @@ -79,6 +82,7 @@ public: virtual void xform(const LMatrix4f &mat)=0; void update_viz(Node *parent); + qpGeomNode *get_viz(); PUBLISHED: virtual void output(ostream &out) const; @@ -115,12 +119,20 @@ protected: void add_other_viz(Node *parent, GeomNode *viz); virtual void recompute_viz(Node *parent)=0; + virtual void fill_viz_geom(); + + CPT(RenderState) get_solid_viz_state(); + CPT(RenderState) get_wireframe_viz_state(); + CPT(RenderState) get_other_viz_state(); typedef vector_PT_NodeRelation VizArcs; VizArcs _solid_viz_arcs; VizArcs _wireframe_viz_arcs; VizArcs _other_viz_arcs; + PT(qpGeomNode) _viz_geom; bool _viz_stale; + + bool _viz_geom_stale; bool _tangible; public: diff --git a/panda/src/collide/collisionSphere.cxx b/panda/src/collide/collisionSphere.cxx index 3ce75dc059..3f34a6af22 100644 --- a/panda/src/collide/collisionSphere.cxx +++ b/panda/src/collide/collisionSphere.cxx @@ -433,6 +433,29 @@ recompute_viz(Node *parent) { // add_wireframe_viz(parent, viz); } +//////////////////////////////////////////////////////////////////// +// Function: CollisionSphere::fill_viz_geom +// Access: Protected, Virtual +// Description: Fills the _viz_geom GeomNode up with Geoms suitable +// for rendering this solid. +//////////////////////////////////////////////////////////////////// +void CollisionSphere:: +fill_viz_geom() { + if (collide_cat.is_debug()) { + collide_cat.debug() + << "Recomputing viz for " << *this << "\n"; + } + + GeomSphere *sphere = new GeomSphere; + PTA_Vertexf verts; + verts.push_back(_center); + verts.push_back(_center + LVector3f(_radius, 0.0f, 0.0f)); + sphere->set_coords(verts); + sphere->set_num_prims(1); + + _viz_geom->add_geom(sphere, get_solid_viz_state()); +} + //////////////////////////////////////////////////////////////////// // Function: CollisionSphere::intersects_line // Access: Protected diff --git a/panda/src/collide/collisionSphere.h b/panda/src/collide/collisionSphere.h index 182c5dc358..e6bb035029 100644 --- a/panda/src/collide/collisionSphere.h +++ b/panda/src/collide/collisionSphere.h @@ -84,6 +84,7 @@ protected: const qpCollisionEntry &entry) const; virtual void recompute_viz(Node *parent); + virtual void fill_viz_geom(); bool intersects_line(double &t1, double &t2, const LPoint3f &from, const LVector3f &delta) const; diff --git a/panda/src/collide/qpcollisionNode.cxx b/panda/src/collide/qpcollisionNode.cxx index 185447f366..951f4679c3 100644 --- a/panda/src/collide/qpcollisionNode.cxx +++ b/panda/src/collide/qpcollisionNode.cxx @@ -19,6 +19,9 @@ #include "collisionNode.h" #include "config_collide.h" +#include "qpgeomNode.h" +#include "cullTraverserData.h" +#include "qpcullTraverser.h" #include "datagram.h" #include "datagramIterator.h" #include "bamReader.h" @@ -194,13 +197,22 @@ has_cull_callback() const { // visible, or false if it should be culled. //////////////////////////////////////////////////////////////////// bool qpCollisionNode:: -cull_callback(qpCullTraverser *, CullTraverserData &) { - /* +cull_callback(qpCullTraverser *trav, CullTraverserData &data) { + // Append our collision vizzes to the drawing, even though they're + // not actually part of the scene graph. Solids::iterator si; for (si = _solids.begin(); si != _solids.end(); ++si) { - (*si)->update_viz(this); + CollisionSolid *solid = (*si); + PandaNode *node = solid->get_viz(); + CullTraverserData next_data(data, node); + + // We don't want to inherit the render state from above for these + // guys. + next_data._state = RenderState::make_empty(); + trav->traverse(next_data); } - */ + + // Now carry on to render our child nodes. return true; }