Panda3D
 All Classes Functions Variables Enumerations
occluderNode.cxx
00001 // Filename: occluderNode.cxx
00002 // Created by:  jenes (11Mar11)
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 "occluderNode.h"
00016 
00017 #include "geomNode.h"
00018 #include "cullTraverserData.h"
00019 #include "cullTraverser.h"
00020 #include "renderState.h"
00021 #include "plane.h"
00022 #include "pnmImage.h"
00023 #include "textureAttrib.h"
00024 #include "colorAttrib.h"
00025 #include "depthOffsetAttrib.h"
00026 #include "cullFaceAttrib.h"
00027 #include "transparencyAttrib.h"
00028 #include "transformState.h"
00029 #include "cullableObject.h"
00030 #include "cullHandler.h"
00031 #include "boundingSphere.h"
00032 #include "geomVertexData.h"
00033 #include "geomTriangles.h"
00034 #include "geomLinestrips.h"
00035 #include "geomVertexWriter.h"
00036 #include "geom.h"
00037 #include "datagram.h"
00038 #include "datagramIterator.h"
00039 #include "bamReader.h"
00040 #include "bamWriter.h"
00041 
00042 #include "plane.h"
00043 
00044 TypeHandle OccluderNode::_type_handle;
00045 PT(Texture) OccluderNode::_viz_tex;
00046 
00047 
00048 ////////////////////////////////////////////////////////////////////
00049 //     Function: OccluderNode::Constructor
00050 //       Access: Public
00051 //  Description: The default constructor creates a default occlusion
00052 //               polygon in the XZ plane (or XY plane in a y-up
00053 //               coordinate system).  Use the normal Panda set_pos(),
00054 //               set_hpr(), set_scale() to position it appropriately,
00055 //               or replace the vertices with set_vertices().
00056 ////////////////////////////////////////////////////////////////////
00057 OccluderNode::
00058 OccluderNode(const string &name) :
00059   PandaNode(name)
00060 {
00061   set_cull_callback();
00062   // OccluderNodes are hidden by default.
00063   set_overall_hidden(true);
00064   set_double_sided(false);
00065   set_min_coverage(0.0);
00066   set_vertices(LPoint3::rfu(-1.0, 0.0, -1.0),
00067                LPoint3::rfu(1.0, 0.0, -1.0),
00068                LPoint3::rfu(1.0, 0.0, 1.0),
00069                LPoint3::rfu(-1.0, 0.0, 1.0));
00070 }
00071 
00072 ////////////////////////////////////////////////////////////////////
00073 //     Function: OccluderNode::Copy Constructor
00074 //       Access: Protected
00075 //  Description:
00076 ////////////////////////////////////////////////////////////////////
00077 OccluderNode::
00078 OccluderNode(const OccluderNode &copy) :
00079   PandaNode(copy),
00080   _double_sided(copy._double_sided),
00081   _min_coverage(copy._min_coverage),
00082   _vertices(copy._vertices)
00083 {
00084 }
00085 
00086 ////////////////////////////////////////////////////////////////////
00087 //     Function: OccluderNode::Destructor
00088 //       Access: Public, Virtual
00089 //  Description:
00090 ////////////////////////////////////////////////////////////////////
00091 OccluderNode::
00092 ~OccluderNode() {
00093 }
00094 
00095 ////////////////////////////////////////////////////////////////////
00096 //     Function: OccluderNode::make_copy
00097 //       Access: Public, Virtual
00098 //  Description: Returns a newly-allocated Node that is a shallow copy
00099 //               of this one.  It will be a different Node pointer,
00100 //               but its internal data may or may not be shared with
00101 //               that of the original Node.
00102 ////////////////////////////////////////////////////////////////////
00103 PandaNode *OccluderNode::
00104 make_copy() const {
00105   return new OccluderNode(*this);
00106 }
00107 
00108 ////////////////////////////////////////////////////////////////////
00109 //     Function: OccluderNode::preserve_name
00110 //       Access: Public, Virtual
00111 //  Description: Returns true if the node's name has extrinsic meaning
00112 //               and must be preserved across a flatten operation,
00113 //               false otherwise.
00114 ////////////////////////////////////////////////////////////////////
00115 bool OccluderNode::
00116 preserve_name() const {
00117   return true;
00118 }
00119 
00120 ////////////////////////////////////////////////////////////////////
00121 //     Function: OccluderNode::xform
00122 //       Access: Public, Virtual
00123 //  Description: Transforms the contents of this node by the indicated
00124 //               matrix, if it means anything to do so.  For most
00125 //               kinds of nodes, this does nothing.
00126 ////////////////////////////////////////////////////////////////////
00127 void OccluderNode::
00128 xform(const LMatrix4 &mat) {
00129   nassertv(!mat.is_nan());
00130 
00131   for (Vertices::iterator vi = _vertices.begin();
00132        vi != _vertices.end();
00133        ++vi) {
00134     (*vi) = (*vi) * mat;
00135   }
00136 }
00137 
00138 ////////////////////////////////////////////////////////////////////
00139 //     Function: OccluderNode::cull_callback
00140 //       Access: Public, Virtual
00141 //  Description: This function will be called during the cull
00142 //               traversal to perform any additional operations that
00143 //               should be performed at cull time.  This may include
00144 //               additional manipulation of render state or additional
00145 //               visible/invisible decisions, or any other arbitrary
00146 //               operation.
00147 //
00148 //               Note that this function will *not* be called unless
00149 //               set_cull_callback() is called in the constructor of
00150 //               the derived class.  It is necessary to call
00151 //               set_cull_callback() to indicated that we require
00152 //               cull_callback() to be called.
00153 //
00154 //               By the time this function is called, the node has
00155 //               already passed the bounding-volume test for the
00156 //               viewing frustum, and the node's transform and state
00157 //               have already been applied to the indicated
00158 //               CullTraverserData object.
00159 //
00160 //               The return value is true if this node should be
00161 //               visible, or false if it should be culled.
00162 ////////////////////////////////////////////////////////////////////
00163 bool OccluderNode::
00164 cull_callback(CullTraverser *trav, CullTraverserData &data) {
00165   // Normally, an OccluderNode is invisible.  But if someone shows it,
00166   // we will draw a visualization, a checkerboard-textured polygon.
00167   CullableObject *occluder_viz = 
00168     new CullableObject(get_occluder_viz(trav, data), get_occluder_viz_state(trav, data), 
00169                        data.get_net_transform(trav),
00170                        data.get_modelview_transform(trav),
00171                        trav->get_gsg());
00172   trav->get_cull_handler()->record_object(occluder_viz, trav);
00173 
00174   // Also get the frame.
00175   nassertr(_frame_viz != (Geom *)NULL, false);
00176   CullableObject *frame_viz = 
00177     new CullableObject(_frame_viz, get_frame_viz_state(trav, data), 
00178                        data.get_net_transform(trav),
00179                        data.get_modelview_transform(trav),
00180                        trav->get_gsg());
00181   trav->get_cull_handler()->record_object(frame_viz, trav);
00182 
00183   // Now carry on to render our child nodes.
00184   return true;
00185 }
00186 
00187 ////////////////////////////////////////////////////////////////////
00188 //     Function: OccluderNode::is_renderable
00189 //       Access: Public, Virtual
00190 //  Description: Returns true if there is some value to visiting this
00191 //               particular node during the cull traversal for any
00192 //               camera, false otherwise.  This will be used to
00193 //               optimize the result of get_net_draw_show_mask(), so
00194 //               that any subtrees that contain only nodes for which
00195 //               is_renderable() is false need not be visited.
00196 ////////////////////////////////////////////////////////////////////
00197 bool OccluderNode::
00198 is_renderable() const {
00199   return true;
00200 }
00201 
00202 
00203 ////////////////////////////////////////////////////////////////////
00204 //     Function: OccluderNode::output
00205 //       Access: Public, Virtual
00206 //  Description: Writes a brief description of the node to the
00207 //               indicated output stream.  This is invoked by the <<
00208 //               operator.  It may be overridden in derived classes to
00209 //               include some information relevant to the class.
00210 ////////////////////////////////////////////////////////////////////
00211 void OccluderNode::
00212 output(ostream &out) const {
00213   PandaNode::output(out);
00214 }
00215 
00216 ////////////////////////////////////////////////////////////////////
00217 //     Function: OccluderNode::compute_internal_bounds
00218 //       Access: Protected, Virtual
00219 //  Description: Called when needed to recompute the node's
00220 //               _internal_bound object.  Nodes that contain anything
00221 //               of substance should redefine this to do the right
00222 //               thing.
00223 ////////////////////////////////////////////////////////////////////
00224 void OccluderNode::
00225 compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
00226                         int &internal_vertices,
00227                         int pipeline_stage,
00228                         Thread *current_thread) const {
00229   // First, get ourselves a fresh, empty bounding volume.
00230   PT(BoundingVolume) bound = new BoundingSphere;
00231   GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, bound);
00232 
00233   // Now actually compute the bounding volume by putting it around all
00234   // of our vertices.
00235   if (!_vertices.empty()) {
00236     const LPoint3 *vertices_begin = &_vertices[0];
00237     const LPoint3 *vertices_end = vertices_begin + _vertices.size();
00238     gbv->around(vertices_begin, vertices_end);
00239   }
00240 
00241   internal_bounds = bound;
00242   internal_vertices = 0;
00243 }
00244 
00245 ////////////////////////////////////////////////////////////////////
00246 //     Function: OccluderNode::get_occluder_viz
00247 //       Access: Protected
00248 //  Description: Returns a Geom that represents the visualization of
00249 //               the OccluderNode, as seen from the front.
00250 ////////////////////////////////////////////////////////////////////
00251 PT(Geom) OccluderNode::
00252 get_occluder_viz(CullTraverser *trav, CullTraverserData &data) {
00253   if (_occluder_viz == (Geom *)NULL) {
00254     nassertr(_vertices.size() == 4, NULL);
00255 
00256     if (pgraph_cat.is_debug()) {
00257       pgraph_cat.debug()
00258         << "Recomputing viz for " << *this << "\n";
00259     }
00260     
00261     PT(GeomVertexData) vdata = new GeomVertexData
00262       (get_name(), GeomVertexFormat::get_v3n3t2(), Geom::UH_static);
00263     
00264     // Compute the polygon normal from the first three vertices.
00265     LPlane plane(_vertices[0], _vertices[1], _vertices[2]);
00266     LVector3 poly_normal = plane.get_normal();
00267     
00268     GeomVertexWriter vertex(vdata, InternalName::get_vertex());
00269     GeomVertexWriter normal(vdata, InternalName::get_normal());
00270     GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
00271     vertex.add_data3(_vertices[0]);
00272     normal.add_data3(poly_normal);
00273     texcoord.add_data2(0.0, 0.0);
00274     
00275     vertex.add_data3(_vertices[1]);
00276     normal.add_data3(poly_normal);
00277     texcoord.add_data2(8.0, 0.0);
00278     
00279     vertex.add_data3(_vertices[2]);
00280     normal.add_data3(poly_normal);
00281     texcoord.add_data2(8.0, 8.0);
00282     
00283     vertex.add_data3(_vertices[3]);
00284     normal.add_data3(poly_normal);
00285     texcoord.add_data2(0.0, 8.0);
00286     
00287     PT(GeomTriangles) triangles = new GeomTriangles(Geom::UH_static);
00288     triangles->add_vertices(0, 1, 2);
00289     triangles->close_primitive();
00290     triangles->add_vertices(0, 2, 3);
00291     triangles->close_primitive();
00292     
00293     _occluder_viz = new Geom(vdata);
00294     _occluder_viz->add_primitive(triangles);
00295 
00296     PT(GeomLinestrips) lines = new GeomLinestrips(Geom::UH_static);
00297     lines->add_vertices(0, 1, 2, 3);
00298     lines->add_vertex(0);
00299     lines->close_primitive();
00300     
00301     _frame_viz = new Geom(vdata);
00302     _frame_viz->add_primitive(lines);
00303   }
00304 
00305   return _occluder_viz;
00306 }
00307 
00308 ////////////////////////////////////////////////////////////////////
00309 //     Function: OccluderNode::get_occluder_viz_state
00310 //       Access: Protected
00311 //  Description: Returns the RenderState to apply to the visualization.
00312 ////////////////////////////////////////////////////////////////////
00313 CPT(RenderState) OccluderNode::
00314 get_occluder_viz_state(CullTraverser *trav, CullTraverserData &data) {
00315   if (_viz_tex == NULL) {
00316     // Create a default texture.  We set it up as a 2x2 graytone
00317     // checkerboard, since that's real easy, and it doesn't look like
00318     // a CollisionPolygon.
00319     _viz_tex = new Texture("occluder_viz");
00320     _viz_tex->setup_2d_texture(2, 2, Texture::T_unsigned_byte, Texture::F_luminance);
00321     PTA_uchar image;
00322     image.set_data("\x20\x80\x80\x20");
00323     _viz_tex->set_ram_image(image);
00324     _viz_tex->set_minfilter(Texture::FT_nearest);
00325     _viz_tex->set_magfilter(Texture::FT_nearest);
00326   }
00327 
00328   static CPT(RenderState) viz_state;
00329   if (viz_state == NULL) {
00330     viz_state = RenderState::make
00331       (ColorAttrib::make_flat(LVecBase4(1.0f, 1.0f, 1.0f, 0.5f)),
00332        TransparencyAttrib::make(TransparencyAttrib::M_alpha),
00333        DepthOffsetAttrib::make(),
00334        TextureAttrib::make(_viz_tex));
00335     viz_state = viz_state->adjust_all_priorities(1);
00336   }
00337 
00338   CPT(RenderState) state = viz_state;
00339   if (is_double_sided()) {
00340     state = viz_state->set_attrib(CullFaceAttrib::make(CullFaceAttrib::M_cull_none), 1);
00341   } else {
00342     state = viz_state->set_attrib(CullFaceAttrib::make(CullFaceAttrib::M_cull_clockwise), 1);
00343   }
00344 
00345   return state->compose(viz_state);
00346 }
00347 
00348 ////////////////////////////////////////////////////////////////////
00349 //     Function: OccluderNode::get_frame_viz_state
00350 //       Access: Protected
00351 //  Description: Returns the RenderState to apply to the frame.
00352 ////////////////////////////////////////////////////////////////////
00353 CPT(RenderState) OccluderNode::
00354 get_frame_viz_state(CullTraverser *trav, CullTraverserData &data) {
00355   static CPT(RenderState) viz_state;
00356   if (viz_state == NULL) {
00357     viz_state = RenderState::make
00358       (ColorAttrib::make_flat(LVecBase4(0.0f, 0.0f, 0.0f, 1.0f)),
00359        TextureAttrib::make_off());
00360     viz_state = viz_state->adjust_all_priorities(1);
00361   }
00362 
00363   return data._state->compose(viz_state);
00364 }
00365 
00366 ////////////////////////////////////////////////////////////////////
00367 //     Function: OccluderNode::register_with_read_factory
00368 //       Access: Public, Static
00369 //  Description: Tells the BamReader how to create objects of type
00370 //               OccluderNode.
00371 ////////////////////////////////////////////////////////////////////
00372 void OccluderNode::
00373 register_with_read_factory() {
00374   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00375 }
00376 
00377 ////////////////////////////////////////////////////////////////////
00378 //     Function: OccluderNode::write_datagram
00379 //       Access: Public, Virtual
00380 //  Description: Writes the contents of this object to the datagram
00381 //               for shipping out to a Bam file.
00382 ////////////////////////////////////////////////////////////////////
00383 void OccluderNode::
00384 write_datagram(BamWriter *manager, Datagram &dg) {
00385   PandaNode::write_datagram(manager, dg);
00386 
00387   dg.add_uint16(_vertices.size());
00388   for (Vertices::const_iterator vi = _vertices.begin();
00389        vi != _vertices.end();
00390        ++vi) {
00391     (*vi).write_datagram(dg);
00392   }
00393 }
00394 
00395 ////////////////////////////////////////////////////////////////////
00396 //     Function: OccluderNode::complete_pointers
00397 //       Access: Public, Virtual
00398 //  Description: Receives an array of pointers, one for each time
00399 //               manager->read_pointer() was called in fillin().
00400 //               Returns the number of pointers processed.
00401 ////////////////////////////////////////////////////////////////////
00402 int OccluderNode::
00403 complete_pointers(TypedWritable **p_list, BamReader *manager) {
00404   int pi = PandaNode::complete_pointers(p_list, manager);
00405 
00406   return pi;
00407 }
00408 
00409 ////////////////////////////////////////////////////////////////////
00410 //     Function: OccluderNode::make_from_bam
00411 //       Access: Protected, Static
00412 //  Description: This function is called by the BamReader's factory
00413 //               when a new object of type OccluderNode is encountered
00414 //               in the Bam file.  It should create the OccluderNode
00415 //               and extract its information from the file.
00416 ////////////////////////////////////////////////////////////////////
00417 TypedWritable *OccluderNode::
00418 make_from_bam(const FactoryParams &params) {
00419   OccluderNode *node = new OccluderNode("");
00420   DatagramIterator scan;
00421   BamReader *manager;
00422 
00423   parse_params(params, scan, manager);
00424   node->fillin(scan, manager);
00425 
00426   return node;
00427 }
00428 
00429 ////////////////////////////////////////////////////////////////////
00430 //     Function: OccluderNode::fillin
00431 //       Access: Protected
00432 //  Description: This internal function is called by make_from_bam to
00433 //               read in all of the relevant data from the BamFile for
00434 //               the new OccluderNode.
00435 ////////////////////////////////////////////////////////////////////
00436 void OccluderNode::
00437 fillin(DatagramIterator &scan, BamReader *manager) {
00438   PandaNode::fillin(scan, manager);
00439 
00440   int num_vertices = scan.get_uint16();
00441   _vertices.clear();
00442   _vertices.reserve(num_vertices);
00443   for (int i = 0; i < num_vertices; i++) {
00444     LPoint3 vertex;
00445     vertex.read_datagram(scan);
00446     _vertices.push_back(vertex);
00447   }
00448 }
 All Classes Functions Variables Enumerations