00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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
00050
00051
00052
00053
00054
00055
00056
00057 OccluderNode::
00058 OccluderNode(const string &name) :
00059 PandaNode(name)
00060 {
00061 set_cull_callback();
00062
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
00074
00075
00076
00077 OccluderNode::
00078 OccluderNode(const OccluderNode ©) :
00079 PandaNode(copy),
00080 _double_sided(copy._double_sided),
00081 _min_coverage(copy._min_coverage),
00082 _vertices(copy._vertices)
00083 {
00084 }
00085
00086
00087
00088
00089
00090
00091 OccluderNode::
00092 ~OccluderNode() {
00093 }
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 PandaNode *OccluderNode::
00104 make_copy() const {
00105 return new OccluderNode(*this);
00106 }
00107
00108
00109
00110
00111
00112
00113
00114
00115 bool OccluderNode::
00116 preserve_name() const {
00117 return true;
00118 }
00119
00120
00121
00122
00123
00124
00125
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
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 bool OccluderNode::
00164 cull_callback(CullTraverser *trav, CullTraverserData &data) {
00165
00166
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
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
00184 return true;
00185 }
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 bool OccluderNode::
00198 is_renderable() const {
00199 return true;
00200 }
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211 void OccluderNode::
00212 output(ostream &out) const {
00213 PandaNode::output(out);
00214 }
00215
00216
00217
00218
00219
00220
00221
00222
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
00230 PT(BoundingVolume) bound = new BoundingSphere;
00231 GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, bound);
00232
00233
00234
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
00247
00248
00249
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
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
00310
00311
00312
00313 CPT(RenderState) OccluderNode::
00314 get_occluder_viz_state(CullTraverser *trav, CullTraverserData &data) {
00315 if (_viz_tex == NULL) {
00316
00317
00318
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
00350
00351
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
00368
00369
00370
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
00379
00380
00381
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
00397
00398
00399
00400
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
00411
00412
00413
00414
00415
00416
00417 TypedWritable *OccluderNode::
00418 make_from_bam(const FactoryParams ¶ms) {
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
00431
00432
00433
00434
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 }