瀏覽代碼

pgraph viz collision solids

David Rose 24 年之前
父節點
當前提交
c1fe4c1938

+ 73 - 2
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

+ 1 - 0
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;

+ 45 - 1
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 <algorithm>
 
 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

+ 1 - 0
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;

+ 42 - 2
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());
+}

+ 1 - 0
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;

+ 31 - 3
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());
+}

+ 1 - 0
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;

+ 1 - 0
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;
 }

+ 154 - 14
panda/src/collide/collisionSolid.cxx

@@ -24,20 +24,25 @@
 #include "collisionRay.h"
 #include "collisionSegment.h"
 
-#include <renderRelation.h>
-#include <geomNode.h>
-#include <datagram.h>
-#include <datagramIterator.h>
-#include <bamReader.h>
-#include <bamWriter.h>
-
-#include <indent.h>
-#include <cullFaceTransition.h>
-#include <colorTransition.h>
-#include <renderModeTransition.h>
-#include <lightTransition.h>
-#include <transparencyTransition.h>
-#include <textureTransition.h>
+#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 "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 &copy) :
 {
   // 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;
+}
+

+ 13 - 1
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:

+ 23 - 0
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

+ 1 - 0
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;

+ 16 - 4
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;
 }