00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "portalNode.h"
00016
00017 #include "geomNode.h"
00018 #include "cullTraverserData.h"
00019 #include "cullTraverser.h"
00020 #include "renderState.h"
00021 #include "portalClipper.h"
00022 #include "transformState.h"
00023 #include "colorScaleAttrib.h"
00024 #include "transparencyAttrib.h"
00025 #include "datagram.h"
00026 #include "datagramIterator.h"
00027 #include "bamReader.h"
00028 #include "bamWriter.h"
00029
00030 #include "plane.h"
00031
00032 TypeHandle PortalNode::_type_handle;
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 PortalNode::
00044 PortalNode(const string &name) :
00045 PandaNode(name),
00046 _from_portal_mask(PortalMask::all_on()),
00047 _into_portal_mask(PortalMask::all_on()),
00048 _flags(0)
00049 {
00050 set_cull_callback();
00051
00052 _visible = false;
00053 _open = true;
00054 _clip_plane = false;
00055 _max_depth = 10;
00056 }
00057
00058
00059
00060
00061
00062
00063
00064 PortalNode::
00065 PortalNode(const string &name, LPoint3 pos, PN_stdfloat scale) :
00066 PandaNode(name),
00067 _from_portal_mask(PortalMask::all_on()),
00068 _into_portal_mask(PortalMask::all_on()),
00069 _flags(0)
00070 {
00071 set_cull_callback();
00072
00073 add_vertex(LPoint3(pos[0]-1.0*scale, pos[1], pos[2]-1.0*scale));
00074 add_vertex(LPoint3(pos[0]+1.0*scale, pos[1], pos[2]-1.0*scale));
00075 add_vertex(LPoint3(pos[0]+1.0*scale, pos[1], pos[2]+1.0*scale));
00076 add_vertex(LPoint3(pos[0]-1.0*scale, pos[1], pos[2]+1.0*scale));
00077
00078 _visible = false;
00079 _open = true;
00080 _clip_plane = false;
00081 _max_depth = 10;
00082 }
00083
00084
00085
00086
00087
00088
00089 PortalNode::
00090 PortalNode(const PortalNode ©) :
00091 PandaNode(copy),
00092 _from_portal_mask(copy._from_portal_mask),
00093 _into_portal_mask(copy._into_portal_mask),
00094 _flags(copy._flags),
00095 _vertices(copy._vertices),
00096 _cell_in(copy._cell_in),
00097 _cell_out(copy._cell_out),
00098 _clip_plane(copy._clip_plane),
00099 _visible(copy._visible),
00100 _open(copy._open),
00101 _max_depth(copy._max_depth)
00102 {
00103 }
00104
00105
00106
00107
00108
00109
00110 PortalNode::
00111 ~PortalNode() {
00112 }
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 PandaNode *PortalNode::
00123 make_copy() const {
00124 return new PortalNode(*this);
00125 }
00126
00127
00128
00129
00130
00131
00132
00133
00134 bool PortalNode::
00135 preserve_name() const {
00136 return true;
00137 }
00138
00139
00140
00141
00142
00143
00144 void PortalNode::
00145 enable_clipping_planes() {
00146 _top_plane_node = new PlaneNode("top");
00147 NodePath top_plane_np = NodePath(this).attach_new_node(_top_plane_node);
00148
00149 _bottom_plane_node = new PlaneNode("bottom");
00150 NodePath bottom_plane_np = NodePath(this).attach_new_node(_bottom_plane_node);
00151
00152 _left_plane_node = new PlaneNode("left");
00153 NodePath left_plane_np = NodePath(this).attach_new_node(_left_plane_node);
00154
00155 _right_plane_node = new PlaneNode("right");
00156 NodePath right_plane_np = NodePath(this).attach_new_node(_right_plane_node);
00157
00158 CPT(RenderAttrib) plane_attrib = ClipPlaneAttrib::make();
00159 plane_attrib = DCAST(ClipPlaneAttrib, plane_attrib)->add_on_plane(NodePath(top_plane_np));
00160 plane_attrib = DCAST(ClipPlaneAttrib, plane_attrib)->add_on_plane(NodePath(bottom_plane_np));
00161 plane_attrib = DCAST(ClipPlaneAttrib, plane_attrib)->add_on_plane(NodePath(left_plane_np));
00162 plane_attrib = DCAST(ClipPlaneAttrib, plane_attrib)->add_on_plane(NodePath(right_plane_np));
00163
00164 _clip_state = RenderState::make(plane_attrib);
00165 }
00166
00167
00168
00169
00170
00171
00172
00173
00174 void PortalNode::
00175 xform(const LMatrix4 &mat) {
00176 nassertv(!mat.is_nan());
00177
00178 }
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 PandaNode *PortalNode::
00196 combine_with(PandaNode *other) {
00197 if (is_exact_type(get_class_type()) &&
00198 other->is_exact_type(get_class_type())) {
00199
00200
00201 PortalNode *cother = DCAST(PortalNode, other);
00202 if (get_name() == cother->get_name()) {
00203 return this;
00204 }
00205
00206
00207 return (PandaNode *)NULL;
00208 }
00209
00210 return PandaNode::combine_with(other);
00211 }
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 bool PortalNode::
00227 cull_callback(CullTraverser *trav, CullTraverserData &data) {
00228 Thread *current_thread = trav->get_current_thread();
00229
00230 PortalClipper *portal_viewer = trav->get_portal_clipper();
00231 set_visible(false);
00232 if (is_open() && !_cell_out.is_empty() && portal_viewer && data._portal_depth <= _max_depth) {
00233 portal_cat.debug() << "checking portal node " << *this << endl;
00234 portal_cat.debug() << "portal_depth is " << data._portal_depth << endl;
00235 PT(GeometricBoundingVolume) vf = trav->get_view_frustum();
00236 PT(BoundingVolume) reduced_frustum;
00237
00238
00239 LPoint2 old_reduced_viewport_min, old_reduced_viewport_max;
00240 portal_viewer->get_reduced_viewport(old_reduced_viewport_min, old_reduced_viewport_max);
00241 PT(BoundingHexahedron) old_bh = portal_viewer->get_reduced_frustum();
00242
00243 if (portal_viewer->prepare_portal(data._node_path.get_node_path())) {
00244 if ((reduced_frustum = portal_viewer->get_reduced_frustum())) {
00245
00246 CPT(RenderState) old_clip_state = portal_viewer->get_clip_state();
00247
00248 set_visible(true);
00249
00250 vf = DCAST(GeometricBoundingVolume, reduced_frustum);
00251
00252
00253 PT(BoundingHexahedron) new_bh = DCAST(BoundingHexahedron, vf->make_copy());
00254
00255
00256 CPT(TransformState) cell_transform = _cell_out.get_net_transform();
00257 CPT(TransformState) frustum_transform = cell_transform ->invert_compose(portal_viewer->_scene_setup->get_cull_center().get_net_transform());
00258
00259
00260 new_bh->xform(frustum_transform->get_mat());
00261
00262 CPT(RenderState) next_state = data._state;
00263
00264
00265 if (_clip_plane) {
00266
00267 PT(BoundingHexahedron) temp_bh = DCAST(BoundingHexahedron, vf->make_copy());
00268 CPT(TransformState) temp_frustum_transform = data._node_path.get_node_path().get_net_transform()->invert_compose(portal_viewer->_scene_setup->get_cull_center().get_net_transform());
00269
00270 portal_cat.spam() << "clipping plane frustum transform " << *temp_frustum_transform << endl;
00271 portal_cat.spam() << "frustum before transform " << *temp_bh << endl;
00272
00273 temp_bh->xform(temp_frustum_transform->get_mat());
00274
00275 portal_cat.spam() << "frustum after transform " << *temp_bh << endl;
00276
00277 _left_plane_node->set_plane(-temp_bh->get_plane(4));
00278 _right_plane_node->set_plane(-temp_bh->get_plane(2));
00279 _top_plane_node->set_plane(-temp_bh->get_plane(3));
00280 _bottom_plane_node->set_plane(-temp_bh->get_plane(1));
00281
00282 portal_cat.spam() << "left plane " << *_left_plane_node << endl;
00283 portal_cat.spam() << "right plane " << *_right_plane_node << endl;
00284 portal_cat.spam() << "top plane " << *_top_plane_node << endl;
00285 portal_cat.spam() << "bottom plane " << *_bottom_plane_node << endl;
00286
00287
00288 portal_viewer->set_clip_state(_clip_state);
00289
00290 if (old_clip_state) {
00291 portal_cat.spam() << "parent clip state " << *old_clip_state << endl;
00292 } else {
00293 portal_cat.spam() << "parent clip state None" << endl;
00294 }
00295 portal_cat.spam() << "own clip state " << *_clip_state << endl;
00296 portal_cat.spam() << "next state " << *next_state << endl;
00297
00298
00299 if (old_clip_state != NULL) {
00300 next_state = old_clip_state->invert_compose(next_state);
00301 portal_cat.spam() << "next state after removing parent state " << *next_state << endl;
00302 }
00303 next_state = next_state->compose(_clip_state);
00304 portal_cat.spam() << "next state after composition " << *next_state << endl;
00305 }
00306
00307 CullTraverserData next_data(_cell_out,
00308 cell_transform,
00309 next_state, new_bh,
00310 current_thread);
00311 next_data._portal_depth = data._portal_depth + 1;
00312
00313 portal_viewer->set_reduced_frustum(new_bh);
00314 portal_cat.spam() << "cull_callback: before traversing " << _cell_out.get_name() << endl;
00315 trav->traverse_below(next_data);
00316 portal_cat.spam() << "cull_callback: after traversing " << _cell_out.get_name() << endl;
00317
00318
00319 portal_viewer->set_clip_state(old_clip_state);
00320 }
00321 }
00322
00323 portal_viewer->set_reduced_frustum(old_bh);
00324
00325 portal_viewer->set_reduced_viewport(old_reduced_viewport_min, old_reduced_viewport_max);
00326 }
00327
00328 return true;
00329 }
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341 bool PortalNode::
00342 is_renderable() const {
00343 return true;
00344 }
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 void PortalNode::
00356 output(ostream &out) const {
00357 PandaNode::output(out);
00358 }
00359
00360
00361
00362 // Function: PortalNode::draw
00363 // Access: Public
00364 // Description: Draws the vertices of this portal rectangle to the
00365 // screen with a line
00366
00367
00368 void PortalNode::
00369 draw() const {
00370 move_to(get_vertex(0));
00371 draw_to(get_vertex(1));
00372 draw_to(get_vertex(2));
00373 draw_to(get_vertex(3));
00374 }
00375 */
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385 void PortalNode::
00386 compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
00387 int &internal_vertices,
00388 int pipeline_stage,
00389 Thread *current_thread) const {
00390
00391 PT(BoundingVolume) bound = new BoundingSphere;
00392 GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, bound);
00393
00394
00395
00396
00397 const LPoint3 *vertices_begin = &_vertices[0];
00398 const LPoint3 *vertices_end = vertices_begin + _vertices.size();
00399
00400
00401 gbv->around(vertices_begin, vertices_end);
00402
00403 internal_bounds = bound;
00404 internal_vertices = 0;
00405 }
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415 CPT(RenderState) PortalNode::
00416 get_last_pos_state() {
00417
00418
00419 static CPT(RenderState) state = (const RenderState *)NULL;
00420 if (state == (const RenderState *)NULL) {
00421 state = RenderState::make
00422 (ColorScaleAttrib::make(LVecBase4(1.0f, 1.0f, 1.0f, 0.5f)),
00423 TransparencyAttrib::make(TransparencyAttrib::M_alpha));
00424 }
00425
00426 return state;
00427 }
00428
00429
00430
00431
00432
00433
00434
00435
00436 void PortalNode::
00437 register_with_read_factory() {
00438 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00439 }
00440
00441
00442
00443
00444
00445
00446
00447 void PortalNode::
00448 write_datagram(BamWriter *manager, Datagram &dg) {
00449 PandaNode::write_datagram(manager, dg);
00450
00451 dg.add_uint16(_vertices.size());
00452 for (Vertices::const_iterator vi = _vertices.begin();
00453 vi != _vertices.end();
00454 ++vi) {
00455 (*vi).write_datagram(dg);
00456 }
00457 }
00458
00459
00460
00461
00462
00463
00464
00465
00466 int PortalNode::
00467 complete_pointers(TypedWritable **p_list, BamReader *manager) {
00468 int pi = PandaNode::complete_pointers(p_list, manager);
00469
00470 return pi;
00471 }
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481 TypedWritable *PortalNode::
00482 make_from_bam(const FactoryParams ¶ms) {
00483 PortalNode *node = new PortalNode("");
00484 DatagramIterator scan;
00485 BamReader *manager;
00486
00487 parse_params(params, scan, manager);
00488 node->fillin(scan, manager);
00489
00490 return node;
00491 }
00492
00493
00494
00495
00496
00497
00498
00499
00500 void PortalNode::
00501 fillin(DatagramIterator &scan, BamReader *manager) {
00502 PandaNode::fillin(scan, manager);
00503
00504 int num_vertices = scan.get_uint16();
00505 _vertices.reserve(num_vertices);
00506 for (int i = 0; i < num_vertices; i++) {
00507 LPoint3 vertex;
00508 vertex.read_datagram(scan);
00509 _vertices.push_back(vertex);
00510 }
00511
00512
00513
00514
00515
00516
00517 }