Panda3D
|
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 ©) : 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 ¶ms) { 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 }