Panda3D
|
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 ©) : 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 pvector<LPoint3f> 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 GeomVertexWriter vertex(vdata, InternalName::get_vertex()); 00304 GeomVertexWriter normal(vdata, InternalName::get_normal()); 00305 GeomVertexWriter color(vdata, InternalName::get_color()); 00306 GeomVertexWriter texcoord(vdata, InternalName::get_texcoord()); 00307 00308 PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_stream); 00309 for (int ui = 0; ui < num_u_segments; ui++) { 00310 for (int uni = 0; uni < num_u_verts; uni++) { 00311 float u0 = (float)uni / (float)num_u_verts; 00312 float u1 = (float)(uni + 1) / (float)num_u_verts; 00313 float u0_tc = result->get_segment_u(ui, u0); 00314 float u1_tc = result->get_segment_u(ui, u1); 00315 00316 for (int vi = 0; vi < num_v_segments; vi++) { 00317 for (int vni = 0; vni < num_v_verts; vni++) { 00318 float v = (float)vni / (float)(num_v_verts - 1); 00319 float v_tc = result->get_segment_v(vi, v); 00320 00321 LPoint3f point; 00322 LVector3f norm; 00323 result->eval_segment_point(ui, vi, u0, v, point); 00324 result->eval_segment_normal(ui, vi, u0, v, norm); 00325 vertex.add_data3f(point); 00326 normal.add_data3f(norm); 00327 texcoord.add_data2f(u0_tc, v_tc); 00328 00329 result->eval_segment_point(ui, vi, u1, v, point); 00330 result->eval_segment_normal(ui, vi, u1, v, norm); 00331 vertex.add_data3f(point); 00332 normal.add_data3f(norm); 00333 texcoord.add_data2f(u1_tc, v_tc); 00334 00335 if (use_vertex_color) { 00336 Colorf c0, c1; 00337 result->eval_segment_extended_points(ui, vi, u0, v, 0, &c0[0], 4); 00338 result->eval_segment_extended_points(ui, vi, u1, v, 0, &c1[0], 4); 00339 00340 color.add_data4f(c0); 00341 color.add_data4f(c1); 00342 } 00343 } 00344 strip->add_next_vertices(num_v_verts * 2); 00345 strip->close_primitive(); 00346 } 00347 } 00348 } 00349 00350 PT(Geom) geom = new Geom(vdata); 00351 geom->add_primitive(strip); 00352 00353 CPT(RenderState) state = data._state; 00354 if (use_vertex_color) { 00355 state = state->add_attrib(ColorAttrib::make_vertex()); 00356 } 00357 00358 CullableObject *object = 00359 new CullableObject(geom, state, 00360 data.get_net_transform(trav), 00361 data.get_modelview_transform(trav), 00362 trav->get_gsg()); 00363 trav->get_cull_handler()->record_object(object, trav); 00364 } 00365 00366 //////////////////////////////////////////////////////////////////// 00367 // Function: SheetNode::register_with_read_factory 00368 // Access: Public, Static 00369 // Description: Tells the BamReader how to create objects of type 00370 // SheetNode. 00371 //////////////////////////////////////////////////////////////////// 00372 void SheetNode:: 00373 register_with_read_factory() { 00374 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); 00375 } 00376 00377 //////////////////////////////////////////////////////////////////// 00378 // Function: SheetNode::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 SheetNode:: 00384 write_datagram(BamWriter *manager, Datagram &dg) { 00385 PandaNode::write_datagram(manager, dg); 00386 manager->write_cdata(dg, _cycler); 00387 } 00388 00389 //////////////////////////////////////////////////////////////////// 00390 // Function: SheetNode::make_from_bam 00391 // Access: Protected, Static 00392 // Description: This function is called by the BamReader's factory 00393 // when a new object of type SheetNode is encountered 00394 // in the Bam file. It should create the SheetNode 00395 // and extract its information from the file. 00396 //////////////////////////////////////////////////////////////////// 00397 TypedWritable *SheetNode:: 00398 make_from_bam(const FactoryParams ¶ms) { 00399 SheetNode *node = new SheetNode(""); 00400 DatagramIterator scan; 00401 BamReader *manager; 00402 00403 parse_params(params, scan, manager); 00404 node->fillin(scan, manager); 00405 00406 return node; 00407 } 00408 00409 //////////////////////////////////////////////////////////////////// 00410 // Function: SheetNode::fillin 00411 // Access: Protected 00412 // Description: This internal function is called by make_from_bam to 00413 // read in all of the relevant data from the BamFile for 00414 // the new SheetNode. 00415 //////////////////////////////////////////////////////////////////// 00416 void SheetNode:: 00417 fillin(DatagramIterator &scan, BamReader *manager) { 00418 PandaNode::fillin(scan, manager); 00419 manager->read_cdata(scan, _cycler); 00420 }