Panda3D

sheetNode.cxx

00001 // Filename: sheetNode.cxx
00002 // Created by:  drose (11Oct03)
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 "sheetNode.h"
00016 #include "cullTraverser.h"
00017 #include "cullTraverserData.h"
00018 #include "cullableObject.h"
00019 #include "cullHandler.h"
00020 #include "bamWriter.h"
00021 #include "bamReader.h"
00022 #include "datagram.h"
00023 #include "datagramIterator.h"
00024 #include "pStatTimer.h"
00025 #include "geom.h"
00026 #include "geomTristrips.h"
00027 #include "geomVertexWriter.h"
00028 #include "boundingSphere.h"
00029 #include "colorAttrib.h"
00030 #include "renderState.h"
00031 
00032 TypeHandle SheetNode::_type_handle;
00033 
00034 PStatCollector SheetNode::_sheet_node_pcollector("*:SheetNode");
00035 
00036 ////////////////////////////////////////////////////////////////////
00037 //     Function: SheetNode::CData::make_copy
00038 //       Access: Public, Virtual
00039 //  Description:
00040 ////////////////////////////////////////////////////////////////////
00041 CycleData *SheetNode::CData::
00042 make_copy() const {
00043   return new CData(*this);
00044 }
00045 
00046 ////////////////////////////////////////////////////////////////////
00047 //     Function: SheetNode::CData::write_datagram
00048 //       Access: Public, Virtual
00049 //  Description: Writes the contents of this object to the datagram
00050 //               for shipping out to a Bam file.
00051 ////////////////////////////////////////////////////////////////////
00052 void SheetNode::CData::
00053 write_datagram(BamWriter *writer, Datagram &dg) const {
00054   // For now, we write a NULL pointer.  Eventually we will write out
00055   // the NurbsSurfaceEvaluator pointer.
00056   writer->write_pointer(dg, (TypedWritable *)NULL);
00057 }
00058 
00059 ////////////////////////////////////////////////////////////////////
00060 //     Function: SheetNode::CData::fillin
00061 //       Access: Public, Virtual
00062 //  Description: This internal function is called by make_from_bam to
00063 //               read in all of the relevant data from the BamFile for
00064 //               the new SheetNode.
00065 ////////////////////////////////////////////////////////////////////
00066 void SheetNode::CData::
00067 fillin(DatagramIterator &scan, BamReader *reader) {
00068   // For now, we skip over the NULL pointer that we wrote out.
00069   reader->skip_pointer(scan);
00070   _surface.clear();
00071 }
00072 
00073 ////////////////////////////////////////////////////////////////////
00074 //     Function: SheetNode::Constructor
00075 //       Access: Public
00076 //  Description:
00077 ////////////////////////////////////////////////////////////////////
00078 SheetNode::
00079 SheetNode(const string &name) :
00080   PandaNode(name)
00081 {
00082   set_cull_callback();
00083 }
00084 
00085 ////////////////////////////////////////////////////////////////////
00086 //     Function: SheetNode::Copy Constructor
00087 //       Access: Protected
00088 //  Description:
00089 ////////////////////////////////////////////////////////////////////
00090 SheetNode::
00091 SheetNode(const SheetNode &copy) :
00092   PandaNode(copy),
00093   _cycler(copy._cycler)
00094 {
00095 }
00096 
00097 ////////////////////////////////////////////////////////////////////
00098 //     Function: SheetNode::make_copy
00099 //       Access: Public, Virtual
00100 //  Description: Returns a newly-allocated Node that is a shallow copy
00101 //               of this one.  It will be a different Node pointer,
00102 //               but its internal data may or may not be shared with
00103 //               that of the original Node.
00104 ////////////////////////////////////////////////////////////////////
00105 PandaNode *SheetNode::
00106 make_copy() const {
00107   return new SheetNode(*this);
00108 }
00109 
00110 ////////////////////////////////////////////////////////////////////
00111 //     Function: SheetNode::safe_to_transform
00112 //       Access: Public, Virtual
00113 //  Description: Returns true if it is generally safe to transform
00114 //               this particular kind of Node by calling the xform()
00115 //               method, false otherwise.  For instance, it's usually
00116 //               a bad idea to attempt to xform a SheetNode.
00117 ////////////////////////////////////////////////////////////////////
00118 bool SheetNode::
00119 safe_to_transform() const {
00120   return false;
00121 }
00122 
00123 ////////////////////////////////////////////////////////////////////
00124 //     Function: SheetNode::cull_callback
00125 //       Access: Public, Virtual
00126 //  Description: This function will be called during the cull
00127 //               traversal to perform any additional operations that
00128 //               should be performed at cull time.  This may include
00129 //               additional manipulation of render state or additional
00130 //               visible/invisible decisions, or any other arbitrary
00131 //               operation.
00132 //
00133 //               Note that this function will *not* be called unless
00134 //               set_cull_callback() is called in the constructor of
00135 //               the derived class.  It is necessary to call
00136 //               set_cull_callback() to indicated that we require
00137 //               cull_callback() to be called.
00138 //
00139 //               By the time this function is called, the node has
00140 //               already passed the bounding-volume test for the
00141 //               viewing frustum, and the node's transform and state
00142 //               have already been applied to the indicated
00143 //               CullTraverserData object.
00144 //
00145 //               The return value is true if this node should be
00146 //               visible, or false if it should be culled.
00147 ////////////////////////////////////////////////////////////////////
00148 bool SheetNode::
00149 cull_callback(CullTraverser *trav, CullTraverserData &data) {
00150   // Statistics
00151   PStatTimer timer(_sheet_node_pcollector);
00152 
00153   // Create some geometry on-the-fly to render the sheet.
00154   if (get_num_u_subdiv() > 0 && get_num_v_subdiv() > 0) {
00155     NurbsSurfaceEvaluator *surface = get_surface();
00156     if (surface != (NurbsSurfaceEvaluator *)NULL) {
00157       PT(NurbsSurfaceResult) result = surface->evaluate(data._node_path.get_node_path());
00158       
00159       if (result->get_num_u_segments() > 0 && result->get_num_v_segments() > 0) {
00160         render_sheet(trav, data, result);
00161       }
00162     }
00163   }
00164   
00165   return true;
00166 }
00167 
00168 ////////////////////////////////////////////////////////////////////
00169 //     Function: SheetNode::is_renderable
00170 //       Access: Public, Virtual
00171 //  Description: Returns true if there is some value to visiting this
00172 //               particular node during the cull traversal for any
00173 //               camera, false otherwise.  This will be used to
00174 //               optimize the result of get_net_draw_show_mask(), so
00175 //               that any subtrees that contain only nodes for which
00176 //               is_renderable() is false need not be visited.
00177 ////////////////////////////////////////////////////////////////////
00178 bool SheetNode::
00179 is_renderable() const {
00180   return true;
00181 }
00182 
00183 ////////////////////////////////////////////////////////////////////
00184 //     Function: SheetNode::output
00185 //       Access: Public, Virtual
00186 //  Description: 
00187 ////////////////////////////////////////////////////////////////////
00188 void SheetNode::
00189 output(ostream &out) const {
00190   PandaNode::output(out);
00191   NurbsSurfaceEvaluator *surface = get_surface();
00192   if (surface != (NurbsSurfaceEvaluator *)NULL) {
00193     out << " " << *surface;
00194   } else {
00195     out << " (no surface)";
00196   }
00197 }
00198 
00199 ////////////////////////////////////////////////////////////////////
00200 //     Function: SheetNode::write
00201 //       Access: Public, Virtual
00202 //  Description: 
00203 ////////////////////////////////////////////////////////////////////
00204 void SheetNode::
00205 write(ostream &out, int indent_level) const {
00206   PandaNode::write(out, indent_level);
00207   NurbsSurfaceEvaluator *surface = get_surface();
00208   if (surface != (NurbsSurfaceEvaluator *)NULL) {
00209     indent(out, indent_level + 2) << *surface << "\n";
00210   } else {
00211     indent(out, indent_level + 2) << "(no surface)\n";
00212   }
00213 }
00214 
00215 ////////////////////////////////////////////////////////////////////
00216 //     Function: SheetNode::reset_bound
00217 //       Access: Published
00218 //  Description: Recomputes the bounding volume.  This is normally
00219 //               called automatically, but it must occasionally be
00220 //               called explicitly when the surface has changed
00221 //               properties outside of this node's knowledge.
00222 ////////////////////////////////////////////////////////////////////
00223 void SheetNode::
00224 reset_bound(const NodePath &rel_to) {
00225   Thread *current_thread = Thread::get_current_thread();
00226   int pipeline_stage = current_thread->get_pipeline_stage();
00227   do_recompute_bounds(rel_to, pipeline_stage, current_thread);
00228   mark_internal_bounds_stale(current_thread);
00229 }
00230 
00231 ////////////////////////////////////////////////////////////////////
00232 //     Function: SheetNode::compute_internal_bounds
00233 //       Access: Protected, Virtual
00234 //  Description: Called when needed to recompute the node's
00235 //               _internal_bound object.  Nodes that contain anything
00236 //               of substance should redefine this to do the right
00237 //               thing.
00238 ////////////////////////////////////////////////////////////////////
00239 void SheetNode::
00240 compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
00241                         int &internal_vertices,
00242                         int pipeline_stage,
00243                         Thread *current_thread) const {
00244   PT(BoundingVolume) bounds = 
00245     do_recompute_bounds(NodePath((PandaNode *)this), pipeline_stage, 
00246                         current_thread);
00247 
00248   internal_bounds = bounds;
00249   internal_vertices = 0;  // TODO--estimate this better.
00250 }
00251 
00252 ////////////////////////////////////////////////////////////////////
00253 //     Function: SheetNode::do_recompute_bounds
00254 //       Access: Private
00255 //  Description: Does the actual internal recompute.
00256 ////////////////////////////////////////////////////////////////////
00257 PT(BoundingVolume) SheetNode::
00258 do_recompute_bounds(const NodePath &rel_to, int pipeline_stage, 
00259                     Thread *current_thread) const {
00260   // TODO: fix the bounds so that it properly reflects the indicated
00261   // pipeline stage.  At the moment, we cheat and get some of the
00262   // properties from the current pipeline stage, the lazy way.
00263 
00264   // First, get ourselves a fresh, empty bounding volume.
00265   PT(BoundingVolume) bound = new BoundingSphere;
00266   
00267   NurbsSurfaceEvaluator *surface = get_surface();
00268   if (surface != (NurbsSurfaceEvaluator *)NULL) {
00269     NurbsSurfaceEvaluator::Vert3Array verts;
00270     get_surface()->get_vertices(verts, rel_to);
00271     
00272     GeometricBoundingVolume *gbv;
00273     DCAST_INTO_R(gbv, bound, bound);
00274     gbv->around(&verts[0], &verts[0] + verts.size());
00275   }
00276   return bound;
00277 }
00278 
00279 ////////////////////////////////////////////////////////////////////
00280 //     Function: SheetNode::render_sheet
00281 //       Access: Private
00282 //  Description: Draws the sheet as a series of tristrips along its
00283 //               length.
00284 ////////////////////////////////////////////////////////////////////
00285 void SheetNode::
00286 render_sheet(CullTraverser *trav, CullTraverserData &data, 
00287              NurbsSurfaceResult *result) {
00288   bool use_vertex_color = get_use_vertex_color();
00289 
00290   int num_u_segments = result->get_num_u_segments();
00291   int num_v_segments = result->get_num_v_segments();
00292   int num_u_verts = get_num_u_subdiv() + 1;
00293   int num_v_verts = get_num_v_subdiv() + 1;
00294 
00295   CPT(GeomVertexFormat) format;
00296   if (use_vertex_color) {
00297     format = GeomVertexFormat::get_v3n3cpt2();
00298   } else {
00299     format = GeomVertexFormat::get_v3n3t2();
00300   }
00301   PT(GeomVertexData) vdata = new GeomVertexData
00302     ("sheet", format, Geom::UH_stream);
00303   int expected_num_vertices = num_u_segments * (num_u_verts + 1) * num_v_segments * num_v_verts;
00304   vdata->reserve_num_rows(expected_num_vertices);
00305 
00306   GeomVertexWriter vertex(vdata, InternalName::get_vertex());
00307   GeomVertexWriter normal(vdata, InternalName::get_normal());
00308   GeomVertexWriter color(vdata, InternalName::get_color());
00309   GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
00310 
00311   for (int ui = 0; ui < num_u_segments; ui++) {
00312     for (int uni = 0; uni <= num_u_verts; uni++) {
00313       PN_stdfloat u0 = (PN_stdfloat)uni / (PN_stdfloat)num_u_verts;
00314       PN_stdfloat u0_tc = result->get_segment_u(ui, u0);
00315       
00316       for (int vi = 0; vi < num_v_segments; vi++) {
00317         for (int vni = 0; vni < num_v_verts; vni++) {
00318           PN_stdfloat v = (PN_stdfloat)vni / (PN_stdfloat)(num_v_verts - 1);
00319           PN_stdfloat v_tc = result->get_segment_v(vi, v);
00320           
00321           LPoint3 point;
00322           LVector3 norm;
00323           result->eval_segment_point(ui, vi, u0, v, point);
00324           result->eval_segment_normal(ui, vi, u0, v, norm);
00325           vertex.add_data3(point);
00326           normal.add_data3(norm);
00327           texcoord.add_data2(u0_tc, v_tc);
00328           
00329           if (use_vertex_color) {
00330             LColor c0;
00331             result->eval_segment_extended_points(ui, vi, u0, v, 0, &c0[0], 4);
00332             color.add_data4(c0);
00333           }
00334         }
00335       }
00336     }
00337   }
00338   nassertv(vdata->get_num_rows() == expected_num_vertices);
00339   
00340   PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_stream);
00341 
00342   int expected_num_tristrips = num_u_segments * num_u_verts * num_v_segments;
00343   int expected_verts_per_tristrip = num_v_verts * 2;
00344 
00345   int expected_prim_vertices = (expected_num_tristrips - 1) * (expected_verts_per_tristrip + strip->get_num_unused_vertices_per_primitive()) + expected_verts_per_tristrip;
00346 
00347   strip->reserve_num_vertices(expected_prim_vertices);
00348 
00349   int verts_per_row = num_v_segments * num_v_verts;
00350 
00351   for (int ui = 0; ui < num_u_segments; ui++) {
00352     for (int uni = 0; uni < num_u_verts; uni++) {
00353       int row_start_index = ((ui * (num_u_verts + 1)) + uni) * verts_per_row;
00354 
00355       for (int vi = 0; vi < num_v_segments; vi++) {
00356         for (int vni = 0; vni < num_v_verts; vni++) {
00357           int vert_index_0 = row_start_index + (vi * num_v_verts) + vni;
00358           int vert_index_1 = vert_index_0 + verts_per_row;
00359           strip->add_vertex(vert_index_0);
00360           strip->add_vertex(vert_index_1);
00361         }
00362         strip->close_primitive();
00363       }
00364     }
00365   }
00366   nassertv(strip->get_num_vertices() == expected_prim_vertices);
00367   
00368   PT(Geom) geom = new Geom(vdata);
00369   geom->add_primitive(strip);
00370 
00371   CPT(RenderState) state = data._state;
00372   if (use_vertex_color) {
00373     state = state->add_attrib(ColorAttrib::make_vertex());
00374   }
00375   
00376   CullableObject *object = 
00377     new CullableObject(geom, state,
00378                        data.get_net_transform(trav),
00379                        data.get_modelview_transform(trav),
00380                        trav->get_gsg());
00381   trav->get_cull_handler()->record_object(object, trav);
00382 }
00383 
00384 ////////////////////////////////////////////////////////////////////
00385 //     Function: SheetNode::register_with_read_factory
00386 //       Access: Public, Static
00387 //  Description: Tells the BamReader how to create objects of type
00388 //               SheetNode.
00389 ////////////////////////////////////////////////////////////////////
00390 void SheetNode::
00391 register_with_read_factory() {
00392   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00393 }
00394 
00395 ////////////////////////////////////////////////////////////////////
00396 //     Function: SheetNode::write_datagram
00397 //       Access: Public, Virtual
00398 //  Description: Writes the contents of this object to the datagram
00399 //               for shipping out to a Bam file.
00400 ////////////////////////////////////////////////////////////////////
00401 void SheetNode::
00402 write_datagram(BamWriter *manager, Datagram &dg) {
00403   PandaNode::write_datagram(manager, dg);
00404   manager->write_cdata(dg, _cycler);
00405 }
00406 
00407 ////////////////////////////////////////////////////////////////////
00408 //     Function: SheetNode::make_from_bam
00409 //       Access: Protected, Static
00410 //  Description: This function is called by the BamReader's factory
00411 //               when a new object of type SheetNode is encountered
00412 //               in the Bam file.  It should create the SheetNode
00413 //               and extract its information from the file.
00414 ////////////////////////////////////////////////////////////////////
00415 TypedWritable *SheetNode::
00416 make_from_bam(const FactoryParams &params) {
00417   SheetNode *node = new SheetNode("");
00418   DatagramIterator scan;
00419   BamReader *manager;
00420 
00421   parse_params(params, scan, manager);
00422   node->fillin(scan, manager);
00423 
00424   return node;
00425 }
00426 
00427 ////////////////////////////////////////////////////////////////////
00428 //     Function: SheetNode::fillin
00429 //       Access: Protected
00430 //  Description: This internal function is called by make_from_bam to
00431 //               read in all of the relevant data from the BamFile for
00432 //               the new SheetNode.
00433 ////////////////////////////////////////////////////////////////////
00434 void SheetNode::
00435 fillin(DatagramIterator &scan, BamReader *manager) {
00436   PandaNode::fillin(scan, manager);
00437   manager->read_cdata(scan, _cycler);
00438 }
 All Classes Functions Variables Enumerations