Panda3D
 All Classes Functions Variables Enumerations
planeNode.cxx
00001 // Filename: planeNode.cxx
00002 // Created by:  drose (11Jul02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "planeNode.h"
00016 #include "geometricBoundingVolume.h"
00017 #include "bamWriter.h"
00018 #include "bamReader.h"
00019 #include "datagram.h"
00020 #include "datagramIterator.h"
00021 #include "geomVertexWriter.h"
00022 #include "geomVertexData.h"
00023 #include "geomLines.h"
00024 #include "geom.h"
00025 #include "cullableObject.h"
00026 #include "cullHandler.h"
00027 #include "boundingPlane.h"
00028 
00029 UpdateSeq PlaneNode::_sort_seq;
00030 
00031 TypeHandle PlaneNode::_type_handle;
00032 
00033 ////////////////////////////////////////////////////////////////////
00034 //     Function: PlaneNode::CData::make_copy
00035 //       Access: Public, Virtual
00036 //  Description:
00037 ////////////////////////////////////////////////////////////////////
00038 CycleData *PlaneNode::CData::
00039 make_copy() const {
00040   return new CData(*this);
00041 }
00042 
00043 ////////////////////////////////////////////////////////////////////
00044 //     Function: PlaneNode::CData::write_datagram
00045 //       Access: Public, Virtual
00046 //  Description: Writes the contents of this object to the datagram
00047 //               for shipping out to a Bam file.
00048 ////////////////////////////////////////////////////////////////////
00049 void PlaneNode::CData::
00050 write_datagram(BamWriter *, Datagram &dg) const {
00051   _plane.write_datagram(dg);
00052 }
00053 
00054 ////////////////////////////////////////////////////////////////////
00055 //     Function: PlaneNode::CData::fillin
00056 //       Access: Public, Virtual
00057 //  Description: This internal function is called by make_from_bam to
00058 //               read in all of the relevant data from the BamFile for
00059 //               the new Light.
00060 ////////////////////////////////////////////////////////////////////
00061 void PlaneNode::CData::
00062 fillin(DatagramIterator &scan, BamReader *) {
00063   _plane.read_datagram(scan);
00064 }
00065 
00066 ////////////////////////////////////////////////////////////////////
00067 //     Function: PlaneNode::Constructor
00068 //       Access: Public
00069 //  Description:
00070 ////////////////////////////////////////////////////////////////////
00071 PlaneNode::
00072 PlaneNode(const string &name, const LPlane &plane) :
00073   PandaNode(name),
00074   _priority(0),
00075   _clip_effect(~0)
00076 {
00077   set_cull_callback();
00078 
00079   // PlaneNodes are hidden by default.
00080   set_overall_hidden(true);
00081 
00082   set_plane(plane);
00083 }
00084 
00085 ////////////////////////////////////////////////////////////////////
00086 //     Function: PlaneNode::Copy Constructor
00087 //       Access: Protected
00088 //  Description:
00089 ////////////////////////////////////////////////////////////////////
00090 PlaneNode::
00091 PlaneNode(const PlaneNode &copy) :
00092   PandaNode(copy),
00093   _priority(copy._priority),
00094   _clip_effect(copy._clip_effect),
00095   _cycler(copy._cycler)
00096 {
00097 }
00098 
00099 ////////////////////////////////////////////////////////////////////
00100 //     Function: PlaneNode::output
00101 //       Access: Public, Virtual
00102 //  Description: 
00103 ////////////////////////////////////////////////////////////////////
00104 void PlaneNode::
00105 output(ostream &out) const {
00106   PandaNode::output(out);
00107   out << " " << get_plane();
00108 }
00109 
00110 ////////////////////////////////////////////////////////////////////
00111 //     Function: PlaneNode::make_copy
00112 //       Access: Public, Virtual
00113 //  Description: Returns a newly-allocated Node that is a shallow copy
00114 //               of this one.  It will be a different Node pointer,
00115 //               but its internal data may or may not be shared with
00116 //               that of the original Node.
00117 ////////////////////////////////////////////////////////////////////
00118 PandaNode *PlaneNode::
00119 make_copy() const {
00120   return new PlaneNode(*this);
00121 }
00122 
00123 ////////////////////////////////////////////////////////////////////
00124 //     Function: PlaneNode::xform
00125 //       Access: Public, Virtual
00126 //  Description: Transforms the contents of this PandaNode by the
00127 //               indicated matrix, if it means anything to do so.  For
00128 //               most kinds of PandaNodes, this does nothing.
00129 ////////////////////////////////////////////////////////////////////
00130 void PlaneNode::
00131 xform(const LMatrix4 &mat) {
00132   PandaNode::xform(mat);
00133   CDWriter cdata(_cycler);
00134   cdata->_plane = cdata->_plane * mat;
00135   cdata->_front_viz = NULL;
00136   cdata->_back_viz = NULL;
00137 }
00138 
00139 ////////////////////////////////////////////////////////////////////
00140 //     Function: PlaneNode::cull_callback
00141 //       Access: Public, Virtual
00142 //  Description: This function will be called during the cull
00143 //               traversal to perform any additional operations that
00144 //               should be performed at cull time.  This may include
00145 //               additional manipulation of render state or additional
00146 //               visible/invisible decisions, or any other arbitrary
00147 //               operation.
00148 //
00149 //               Note that this function will *not* be called unless
00150 //               set_cull_callback() is called in the constructor of
00151 //               the derived class.  It is necessary to call
00152 //               set_cull_callback() to indicated that we require
00153 //               cull_callback() to be called.
00154 //
00155 //               By the time this function is called, the node has
00156 //               already passed the bounding-volume test for the
00157 //               viewing frustum, and the node's transform and state
00158 //               have already been applied to the indicated
00159 //               CullTraverserData object.
00160 //
00161 //               The return value is true if this node should be
00162 //               visible, or false if it should be culled.
00163 ////////////////////////////////////////////////////////////////////
00164 bool PlaneNode::
00165 cull_callback(CullTraverser *trav, CullTraverserData &data) {
00166   // Normally, a PlaneNode is invisible.  But if someone shows it, we
00167   // will draw a visualization, a nice yellow wireframe.
00168 
00169   CullableObject *plane_viz = 
00170     new CullableObject(get_viz(trav, data), data._state, 
00171                        data.get_net_transform(trav),
00172                        data.get_modelview_transform(trav),
00173                        trav->get_gsg());
00174   trav->get_cull_handler()->record_object(plane_viz, trav);
00175 
00176   // Now carry on to render our child nodes.
00177   return true;
00178 }
00179 
00180 ////////////////////////////////////////////////////////////////////
00181 //     Function: PlaneNode::is_renderable
00182 //       Access: Public, Virtual
00183 //  Description: Returns true if there is some value to visiting this
00184 //               particular node during the cull traversal for any
00185 //               camera, false otherwise.  This will be used to
00186 //               optimize the result of get_net_draw_show_mask(), so
00187 //               that any subtrees that contain only nodes for which
00188 //               is_renderable() is false need not be visited.
00189 ////////////////////////////////////////////////////////////////////
00190 bool PlaneNode::
00191 is_renderable() const {
00192   return true;
00193 }
00194 
00195 ////////////////////////////////////////////////////////////////////
00196 //     Function: PlaneNode::compute_internal_bounds
00197 //       Access: Protected, Virtual
00198 //  Description: Returns a newly-allocated BoundingVolume that
00199 //               represents the internal contents of the node.  Should
00200 //               be overridden by PandaNode classes that contain
00201 //               something internally.
00202 ////////////////////////////////////////////////////////////////////
00203 void PlaneNode::
00204 compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
00205                         int &internal_vertices,
00206                         int pipeline_stage,
00207                         Thread *current_thread) const {
00208   CDStageReader cdata(_cycler, pipeline_stage, current_thread);
00209   internal_bounds = new BoundingPlane(cdata->_plane);
00210   internal_vertices = 0;
00211 }
00212 
00213 ////////////////////////////////////////////////////////////////////
00214 //     Function: PlaneNode::get_viz
00215 //       Access: Protected
00216 //  Description: Returns a Geom that represents the visualization of
00217 //               the PlaneNode.
00218 ////////////////////////////////////////////////////////////////////
00219 PT(Geom) PlaneNode::
00220 get_viz(CullTraverser *trav, CullTraverserData &data) {
00221   CDLockedReader cdata(_cycler);
00222   
00223   // Figure out whether we are looking at the front or the back of the
00224   // plane.
00225   const Lens *lens = trav->get_scene()->get_lens();
00226   LPlane eye_plane = cdata->_plane * data.get_modelview_transform(trav)->get_mat();
00227   bool front = (eye_plane.dist_to_plane(lens->get_nodal_point()) >= 0.0f);
00228 
00229   if (cdata->_front_viz != (Geom *)NULL) {
00230     return front ? cdata->_front_viz : cdata->_back_viz;
00231   }
00232 
00233   if (pgraph_cat.is_debug()) {
00234     pgraph_cat.debug()
00235       << "Recomputing viz for " << *this << "\n";
00236   }
00237 
00238   CDWriter cdataw(_cycler, cdata, false);
00239   const LPlane &plane = cdataw->_plane;
00240 
00241   PT(GeomVertexData) vdata = new GeomVertexData
00242     (get_name(), GeomVertexFormat::get_v3cp(), Geom::UH_static);
00243 
00244   GeomVertexWriter vertex(vdata, InternalName::get_vertex());
00245   PT(GeomLines) lines = new GeomLines(Geom::UH_static);
00246 
00247   LVector3 a, b;
00248 
00249   if (fabs(plane[0]) > fabs(plane[1])) {
00250     // X > Y
00251     if (fabs(plane[0]) > fabs(plane[2])) {
00252       // X > Y && X > Z.  X is the largest.
00253       a.set(0, 1, 0);
00254       b.set(0, 0, 1);
00255     } else {
00256       // X > Y && Z > X.  Z is the largest.
00257       a.set(1, 0, 0);
00258       b.set(0, 1, 0);
00259     }
00260   } else {
00261     // Y > X
00262     if (fabs(plane[1]) > fabs(plane[2])) {
00263       // Y > X && Y > Z.  Y is the largest.
00264       a.set(1, 0, 0);
00265       b.set(0, 0, 1);
00266     } else {
00267       // Y > X && Z > Y.  Z is the largest.
00268       a.set(1, 0, 0);
00269       b.set(0, 1, 0);
00270     }
00271   }
00272 
00273   static const int num_segs = 10;
00274   a *= cdataw->_viz_scale / (num_segs * 2);
00275   b *= cdataw->_viz_scale / (num_segs * 2);
00276   
00277   for (int x = -num_segs; x <= num_segs; ++x) {
00278     vertex.add_data3(plane.project(a * x - b * num_segs));
00279     vertex.add_data3(plane.project(a * x + b * num_segs));
00280     lines->add_next_vertices(2);
00281     lines->close_primitive();
00282   }
00283   for (int y = -num_segs; y <= num_segs; ++y) {
00284     vertex.add_data3(plane.project(b * y - a * num_segs));
00285     vertex.add_data3(plane.project(b * y + a * num_segs));
00286     lines->add_next_vertices(2);
00287     lines->close_primitive();
00288   }
00289 
00290   cdataw->_front_viz = new Geom(vdata->set_color(LColor(1.0f, 1.0f, 0.0f, 1.0f)));
00291   cdataw->_front_viz->add_primitive(lines);
00292 
00293   cdataw->_back_viz = new Geom(vdata->set_color(LColor(0.4, 0.4, 0.0f, 1.0f)));
00294   cdataw->_back_viz->add_primitive(lines);
00295 
00296   return front ? cdataw->_front_viz : cdataw->_back_viz;
00297 }
00298 
00299 ////////////////////////////////////////////////////////////////////
00300 //     Function: PlaneNode::register_with_read_factory
00301 //       Access: Public, Static
00302 //  Description: Tells the BamReader how to create objects of type
00303 //               PlaneNode.
00304 ////////////////////////////////////////////////////////////////////
00305 void PlaneNode::
00306 register_with_read_factory() {
00307   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00308 }
00309 
00310 ////////////////////////////////////////////////////////////////////
00311 //     Function: PlaneNode::write_datagram
00312 //       Access: Public, Virtual
00313 //  Description: Writes the contents of this object to the datagram
00314 //               for shipping out to a Bam file.
00315 ////////////////////////////////////////////////////////////////////
00316 void PlaneNode::
00317 write_datagram(BamWriter *manager, Datagram &dg) {
00318   PandaNode::write_datagram(manager, dg);
00319   manager->write_cdata(dg, _cycler);
00320   dg.add_int32(_priority);
00321   dg.add_uint8(_clip_effect);
00322 }
00323 
00324 ////////////////////////////////////////////////////////////////////
00325 //     Function: PlaneNode::make_from_bam
00326 //       Access: Protected, Static
00327 //  Description: This function is called by the BamReader's factory
00328 //               when a new object of type PlaneNode is encountered
00329 //               in the Bam file.  It should create the PlaneNode
00330 //               and extract its information from the file.
00331 ////////////////////////////////////////////////////////////////////
00332 TypedWritable *PlaneNode::
00333 make_from_bam(const FactoryParams &params) {
00334   PlaneNode *node = new PlaneNode("");
00335   DatagramIterator scan;
00336   BamReader *manager;
00337 
00338   parse_params(params, scan, manager);
00339   node->fillin(scan, manager);
00340 
00341   return node;
00342 }
00343 
00344 ////////////////////////////////////////////////////////////////////
00345 //     Function: PlaneNode::fillin
00346 //       Access: Protected
00347 //  Description: This internal function is called by make_from_bam to
00348 //               read in all of the relevant data from the BamFile for
00349 //               the new PlaneNode.
00350 ////////////////////////////////////////////////////////////////////
00351 void PlaneNode::
00352 fillin(DatagramIterator &scan, BamReader *manager) {
00353   PandaNode::fillin(scan, manager);
00354   manager->read_cdata(scan, _cycler);
00355   _priority = scan.get_int32();
00356 
00357   if (manager->get_file_minor_ver() < 9) {
00358     _clip_effect = ~0;
00359   } else {
00360     _clip_effect = scan.get_uint8();
00361   }
00362 }
 All Classes Functions Variables Enumerations