소스 검색

visualize PlaneNodes

David Rose 20 년 전
부모
커밋
efc319c451
5개의 변경된 파일237개의 추가작업 그리고 18개의 파일을 삭제
  1. 11 0
      panda/src/mathutil/plane_src.I
  2. 3 0
      panda/src/mathutil/plane_src.h
  3. 42 5
      panda/src/pgraph/planeNode.I
  4. 160 12
      panda/src/pgraph/planeNode.cxx
  5. 21 1
      panda/src/pgraph/planeNode.h

+ 11 - 0
panda/src/mathutil/plane_src.I

@@ -171,6 +171,17 @@ dist_to_plane(const FLOATNAME(LPoint3) &point) const {
   return (_v.v._0 * point[0] + _v.v._1 * point[1] + _v.v._2 * point[2] + _v.v._3);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: Plane::project
+//       Access: Published
+//  Description: Returns the point within the plane nearest to the
+//               indicated point in space.
+////////////////////////////////////////////////////////////////////
+INLINE_MATHUTIL FLOATNAME(LPoint3) FLOATNAME(Plane)::
+project(const FLOATNAME(LPoint3) &point) const {
+  return point - get_normal() * dist_to_plane(point);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: Plane::intersects_line
 //       Access: Published

+ 3 - 0
panda/src/mathutil/plane_src.h

@@ -45,6 +45,9 @@ PUBLISHED:
   FLOATNAME(LPoint3) get_point() const;
 
   INLINE_MATHUTIL FLOATTYPE dist_to_plane(const FLOATNAME(LPoint3) &point) const;
+  INLINE_MATHUTIL FLOATNAME(LPoint3) project(const FLOATNAME(LPoint3) &point) const;
+
+
   INLINE_MATHUTIL bool intersects_line(FLOATNAME(LPoint3) &intersection_point,
                                        const FLOATNAME(LPoint3) &p1,
                                        const FLOATNAME(LPoint3) &p2) const;

+ 42 - 5
panda/src/pgraph/planeNode.I

@@ -23,7 +23,9 @@
 //  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE PlaneNode::CData::
-CData() {
+CData() :
+  _viz_scale(100.0f)
+{
   // The default plane (perpendicular to the Z-axis) is used until
   // another one is specified explicitly.
 }
@@ -35,12 +37,15 @@ CData() {
 ////////////////////////////////////////////////////////////////////
 INLINE PlaneNode::CData::
 CData(const PlaneNode::CData &copy) :
-  _plane(copy._plane)
+  _plane(copy._plane),
+  _front_viz(copy._front_viz),
+  _back_viz(copy._back_viz),
+  _viz_scale(copy._viz_scale)
 {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: set_plane
+//     Function: PlaneNode::set_plane
 //       Access: Public
 //  Description: Sets the particular plane represented by the
 //               PlaneNode.
@@ -48,11 +53,15 @@ CData(const PlaneNode::CData &copy) :
 INLINE void PlaneNode::
 set_plane(const Planef &plane) {
   CDWriter cdata(_cycler);
-  cdata->_plane = plane;
+  if (cdata->_plane != plane) {
+    cdata->_plane = plane;
+    cdata->_front_viz = NULL;
+    cdata->_back_viz = NULL;
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: get_plane
+//     Function: PlaneNode::get_plane
 //       Access: Public
 //  Description: Returns the plane represented by the PlaneNode.
 ////////////////////////////////////////////////////////////////////
@@ -61,6 +70,34 @@ get_plane() const {
   CDReader cdata(_cycler);
   return cdata->_plane;
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: PlaneNode::set_viz_scale
+//       Access: Public
+//  Description: Specifies the size of the visual representation of
+//               the plane that is drawn if the PlaneNode is shown.
+////////////////////////////////////////////////////////////////////
+INLINE void PlaneNode::
+set_viz_scale(float viz_scale) {
+  CDWriter cdata(_cycler);
+  if (cdata->_viz_scale != viz_scale) {
+    cdata->_viz_scale = viz_scale;
+    cdata->_front_viz = NULL;
+    cdata->_back_viz = NULL;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PlaneNode::get_viz_scale
+//       Access: Public
+//  Description: Returns the size of the visual representation of
+//               the plane that is drawn if the PlaneNode is shown.
+////////////////////////////////////////////////////////////////////
+INLINE float PlaneNode::
+get_viz_scale() const {
+  CDReader cdata(_cycler);
+  return cdata->_viz_scale;
+}
  
 ////////////////////////////////////////////////////////////////////
 //     Function: PlaneNode::set_priority

+ 160 - 12
panda/src/pgraph/planeNode.cxx

@@ -22,6 +22,13 @@
 #include "bamReader.h"
 #include "datagram.h"
 #include "datagramIterator.h"
+#include "geomVertexWriter.h"
+#include "geomVertexData.h"
+#include "geomLines.h"
+#include "geom.h"
+#include "cullableObject.h"
+#include "cullHandler.h"
+#include "boundingPlane.h"
 
 UpdateSeq PlaneNode::_sort_seq;
 
@@ -70,6 +77,9 @@ PlaneNode(const string &name, const Planef &plane) :
   PandaNode(name),
   _priority(0)
 {
+  // PlaneNodes are hidden by default.
+  set_draw_mask(DrawMask::all_off());
+
   set_plane(plane);
 }
 
@@ -86,6 +96,17 @@ PlaneNode(const PlaneNode &copy) :
 {
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: PlaneNode::output
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void PlaneNode::
+output(ostream &out) const {
+  PandaNode::output(out);
+  out << " " << get_plane();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: PlaneNode::make_copy
 //       Access: Public, Virtual
@@ -111,28 +132,155 @@ xform(const LMatrix4f &mat) {
   PandaNode::xform(mat);
   CDWriter cdata(_cycler);
   cdata->_plane = cdata->_plane * mat;
+  cdata->_front_viz = NULL;
+  cdata->_back_viz = NULL;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: PlaneNode::output
+//     Function: PlaneNode::has_cull_callback
 //       Access: Public, Virtual
-//  Description: 
+//  Description: Should be overridden by derived classes to return
+//               true if cull_callback() has been defined.  Otherwise,
+//               returns false to indicate cull_callback() does not
+//               need to be called for this node during the cull
+//               traversal.
 ////////////////////////////////////////////////////////////////////
-void PlaneNode::
-output(ostream &out) const {
-  PandaNode::output(out);
-  out << " " << get_plane();
+bool PlaneNode::
+has_cull_callback() const {
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: PlaneNode::write
+//     Function: PlaneNode::cull_callback
 //       Access: Public, Virtual
-//  Description: 
+//  Description: If has_cull_callback() returns true, this function
+//               will be called during the cull traversal to perform
+//               any additional operations that should be performed at
+//               cull time.  This may include additional manipulation
+//               of render state or additional visible/invisible
+//               decisions, or any other arbitrary operation.
+//
+//               By the time this function is called, the node has
+//               already passed the bounding-volume test for the
+//               viewing frustum, and the node's transform and state
+//               have already been applied to the indicated
+//               CullTraverserData object.
+//
+//               The return value is true if this node should be
+//               visible, or false if it should be culled.
 ////////////////////////////////////////////////////////////////////
-void PlaneNode::
-write(ostream &out, int indent_level) const {
-  PandaNode::write(out, indent_level);
-  get_plane().write(out, indent_level + 2);
+bool PlaneNode::
+cull_callback(CullTraverser *trav, CullTraverserData &data) {
+  // Normally, a PlaneNode is invisible.  But if someone shows it, we
+  // will draw a visualization, a nice yellow wireframe.
+
+  CullableObject *plane_viz = 
+    new CullableObject(get_viz(trav, data), data._state, 
+                       data._modelview_transform);
+  trav->get_cull_handler()->record_object(plane_viz, trav);
+
+  // Now carry on to render our child nodes.
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PlaneNode::compute_internal_bounds
+//       Access: Protected, Virtual
+//  Description: Returns a newly-allocated BoundingVolume that
+//               represents the internal contents of the node.  Should
+//               be overridden by PandaNode classes that contain
+//               something internally.
+////////////////////////////////////////////////////////////////////
+PT(BoundingVolume) PlaneNode::
+compute_internal_bounds(int pipeline_stage) const {
+  CDStageReader cdata(_cycler, pipeline_stage);
+  return new BoundingPlane(cdata->_plane);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PlaneNode::get_viz
+//       Access: Protected
+//  Description: Returns a Geom that represents the visualization of
+//               the PlaneNode.
+////////////////////////////////////////////////////////////////////
+PT(Geom) PlaneNode::
+get_viz(CullTraverser *trav, CullTraverserData &data) {
+  CDReader cdata(_cycler);
+  
+  // Figure out whether we are looking at the front or the back of the
+  // plane.
+  const Lens *lens = trav->get_scene()->get_lens();
+  Planef eye_plane = cdata->_plane * data._modelview_transform->get_mat();
+  bool front = (eye_plane.dist_to_plane(lens->get_nodal_point()) >= 0.0f);
+
+  if (cdata->_front_viz != (Geom *)NULL) {
+    return front ? cdata->_front_viz : cdata->_back_viz;
+  }
+
+  if (pgraph_cat.is_debug()) {
+    pgraph_cat.debug()
+      << "Recomputing viz for " << *this << "\n";
+  }
+
+  CDWriter cdataw(_cycler, cdata, false);
+  const Planef &plane = cdataw->_plane;
+
+  PT(GeomVertexData) vdata = new GeomVertexData
+    (get_name(), GeomVertexFormat::get_v3cp(), Geom::UH_static);
+
+  GeomVertexWriter vertex(vdata, InternalName::get_vertex());
+  PT(GeomLines) lines = new GeomLines(Geom::UH_static);
+
+  LVector3f a, b;
+
+  if (fabs(plane[0]) > fabs(plane[1])) {
+    // X > Y
+    if (fabs(plane[0]) > fabs(plane[2])) {
+      // X > Y && X > Z.  X is the largest.
+      a.set(0, 1, 0);
+      b.set(0, 0, 1);
+    } else {
+      // X > Y && Z > X.  Z is the largest.
+      a.set(1, 0, 0);
+      b.set(0, 1, 0);
+    }
+  } else {
+    // Y > X
+    if (fabs(plane[1]) > fabs(plane[2])) {
+      // Y > X && Y > Z.  Y is the largest.
+      a.set(1, 0, 0);
+      b.set(0, 0, 1);
+    } else {
+      // Y > X && Z > Y.  Z is the largest.
+      a.set(1, 0, 0);
+      b.set(0, 1, 0);
+    }
+  }
+
+  static const int num_segs = 10;
+  a *= cdataw->_viz_scale / (num_segs * 2);
+  b *= cdataw->_viz_scale / (num_segs * 2);
+  
+  for (int x = -num_segs; x <= num_segs; ++x) {
+    vertex.add_data3f(plane.project(a * x - b * num_segs));
+    vertex.add_data3f(plane.project(a * x + b * num_segs));
+    lines->add_next_vertices(2);
+    lines->close_primitive();
+  }
+  for (int y = -num_segs; y <= num_segs; ++y) {
+    vertex.add_data3f(plane.project(b * y - a * num_segs));
+    vertex.add_data3f(plane.project(b * y + a * num_segs));
+    lines->add_next_vertices(2);
+    lines->close_primitive();
+  }
+
+  cdataw->_front_viz = new Geom(vdata->set_color(Colorf(1.0f, 1.0f, 0.0f, 1.0f)));
+  cdataw->_front_viz->add_primitive(lines);
+
+  cdataw->_back_viz = new Geom(vdata->set_color(Colorf(0.4f, 0.4f, 0.0f, 1.0f)));
+  cdataw->_back_viz->add_primitive(lines);
+
+  return front ? cdataw->_front_viz : cdataw->_back_viz;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 21 - 1
panda/src/pgraph/planeNode.h

@@ -24,6 +24,13 @@
 #include "plane.h"
 #include "pandaNode.h"
 #include "updateSeq.h"
+#include "geom.h"
+#include "cycleData.h"
+#include "cycleDataReader.h"
+#include "cycleDataWriter.h"
+#include "cycleDataStageReader.h"
+#include "cycleDataStageWriter.h"
+#include "pipelineCycler.h"
 
 ////////////////////////////////////////////////////////////////////
 //       Class : PlaneNode
@@ -40,20 +47,29 @@ protected:
   PlaneNode(const PlaneNode &copy);
 public:
   virtual void output(ostream &out) const;
-  virtual void write(ostream &out, int indent_level = 0) const;
 
   virtual PandaNode *make_copy() const;
   virtual void xform(const LMatrix4f &mat);
 
+  virtual bool has_cull_callback() const;
+  virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data);
+
 PUBLISHED:
   INLINE void set_plane(const Planef &plane);
   INLINE const Planef &get_plane() const;
 
+  INLINE void set_viz_scale(float viz_scale);
+  INLINE float get_viz_scale() const;
+
   INLINE void set_priority(int priority);
   INLINE int get_priority() const;
 
 public:
   INLINE static UpdateSeq get_sort_seq();
+
+protected:
+  virtual PT(BoundingVolume) compute_internal_bounds(int pipeline_stage) const;
+  PT(Geom) get_viz(CullTraverser *trav, CullTraverserData &data);
   
 private:
   // The priority is not cycled, because there's no real reason to do
@@ -75,11 +91,15 @@ private:
     }
 
     Planef _plane;
+    PT(Geom) _front_viz, _back_viz;
+    float _viz_scale;
   };
 
   PipelineCycler<CData> _cycler;
   typedef CycleDataReader<CData> CDReader;
   typedef CycleDataWriter<CData> CDWriter;
+  typedef CycleDataStageReader<CData> CDStageReader;
+  typedef CycleDataStageWriter<CData> CDStageWriter;
 
 public:
   static void register_with_read_factory();