00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "geomNode.h"
00020 #include "geomTransformer.h"
00021 #include "sceneGraphReducer.h"
00022 #include "accumulatedAttribs.h"
00023 #include "bamReader.h"
00024 #include "bamWriter.h"
00025 #include "datagram.h"
00026 #include "datagramIterator.h"
00027 #include "indent.h"
00028
00029 TypeHandle GeomNode::_type_handle;
00030
00031
00032
00033
00034
00035
00036 GeomNode::CData::
00037 CData(const GeomNode::CData ©) :
00038 _geoms(copy._geoms)
00039 {
00040 }
00041
00042
00043
00044
00045
00046
00047 CycleData *GeomNode::CData::
00048 make_copy() const {
00049 return new CData(*this);
00050 }
00051
00052
00053
00054
00055
00056
00057
00058 void GeomNode::CData::
00059 write_datagram(BamWriter *manager, Datagram &dg) const {
00060 int num_geoms = _geoms.size();
00061 nassertv(num_geoms == (int)(PN_uint16)num_geoms);
00062 dg.add_uint16(num_geoms);
00063
00064 Geoms::const_iterator gi;
00065 for (gi = _geoms.begin(); gi != _geoms.end(); ++gi) {
00066 const GeomEntry &entry = (*gi);
00067 manager->write_pointer(dg, entry._geom);
00068 manager->write_pointer(dg, entry._state);
00069 }
00070 }
00071
00072
00073
00074
00075
00076
00077
00078
00079 int GeomNode::CData::
00080 complete_pointers(TypedWritable **p_list, BamReader *manager) {
00081 int pi = CycleData::complete_pointers(p_list, manager);
00082
00083
00084 Geoms::iterator gi;
00085 for (gi = _geoms.begin(); gi != _geoms.end(); ++gi) {
00086 GeomEntry &entry = (*gi);
00087 entry._geom = DCAST(Geom, p_list[pi++]);
00088 entry._state = DCAST(RenderState, p_list[pi++]);
00089 }
00090
00091 return pi;
00092 }
00093
00094
00095
00096
00097
00098
00099
00100
00101 void GeomNode::CData::
00102 fillin(DatagramIterator &scan, BamReader *manager) {
00103 int num_geoms = scan.get_uint16();
00104
00105 _geoms.reserve(num_geoms);
00106 for (int i = 0; i < num_geoms; i++) {
00107 manager->read_pointer(scan);
00108 manager->read_pointer(scan);
00109 _geoms.push_back(GeomEntry(NULL, NULL));
00110 }
00111 }
00112
00113
00114
00115
00116
00117
00118 GeomNode::
00119 GeomNode(const string &name) :
00120 PandaNode(name)
00121 {
00122 }
00123
00124
00125
00126
00127
00128
00129 GeomNode::
00130 GeomNode(const GeomNode ©) :
00131 PandaNode(copy),
00132 _cycler(copy._cycler)
00133 {
00134 }
00135
00136
00137
00138
00139
00140
00141 GeomNode::
00142 ~GeomNode() {
00143 }
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 PandaNode *GeomNode::
00155 make_copy() const {
00156 return new GeomNode(*this);
00157 }
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 void GeomNode::
00172 apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
00173 GeomTransformer &transformer) {
00174 if (pgraph_cat.is_debug()) {
00175 pgraph_cat.debug()
00176 << "Transforming geometry.\n";
00177 }
00178
00179 if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
00180 if (!attribs._transform->is_identity()) {
00181 transformer.transform_vertices(this, attribs._transform->get_mat());
00182 }
00183 }
00184 if ((attrib_types & SceneGraphReducer::TT_color) != 0) {
00185 if (attribs._color != (const RenderAttrib *)NULL) {
00186 const ColorAttrib *ca = DCAST(ColorAttrib, attribs._color);
00187 if (ca->get_color_type() == ColorAttrib::T_flat) {
00188 transformer.set_color(this, ca->get_color());
00189 }
00190 }
00191 }
00192 if ((attrib_types & SceneGraphReducer::TT_color_scale) != 0) {
00193 if (attribs._color_scale != (const RenderAttrib *)NULL) {
00194 const ColorScaleAttrib *csa = DCAST(ColorScaleAttrib, attribs._color_scale);
00195 if (csa->get_scale() != LVecBase4f(1.0f, 1.0f, 1.0f, 1.0f)) {
00196 transformer.transform_colors(this, csa->get_scale());
00197 }
00198 }
00199 }
00200 if ((attrib_types & SceneGraphReducer::TT_tex_matrix) != 0) {
00201 if (attribs._tex_matrix != (const RenderAttrib *)NULL) {
00202 const TexMatrixAttrib *tma = DCAST(TexMatrixAttrib, attribs._tex_matrix);
00203 if (tma->get_mat() != LMatrix4f::ident_mat()) {
00204 transformer.transform_texcoords(this, tma->get_mat());
00205 }
00206 }
00207 }
00208 if ((attrib_types & SceneGraphReducer::TT_other) != 0) {
00209 if (!attribs._other->is_empty()) {
00210 transformer.apply_state(this, attribs._other);
00211 }
00212 }
00213 }
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 void GeomNode::
00228 xform(const LMatrix4f &mat) {
00229 GeomTransformer transformer;
00230 transformer.transform_vertices(this, mat);
00231 }
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248 PandaNode *GeomNode::
00249 combine_with(PandaNode *other) {
00250 if (is_exact_type(get_class_type()) &&
00251 other->is_exact_type(get_class_type())) {
00252
00253 GeomNode *gother = DCAST(GeomNode, other);
00254 add_geoms_from(gother);
00255 return this;
00256 }
00257
00258 return PandaNode::combine_with(other);
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 CPT(TransformState) GeomNode::
00278 calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, bool &found_any,
00279 const TransformState *transform) const {
00280 CPT(TransformState) next_transform =
00281 PandaNode::calc_tight_bounds(min_point, max_point, found_any, transform);
00282
00283 const LMatrix4f &mat = next_transform->get_mat();
00284 int num_geoms = get_num_geoms();
00285 for (int i = 0; i < num_geoms; i++) {
00286 Geom *geom = get_geom(i);
00287 Geom::VertexIterator vi = geom->make_vertex_iterator();
00288 int num_prims = geom->get_num_prims();
00289
00290 for (int p = 0; p < num_prims; p++) {
00291 int length = geom->get_length(p);
00292 for (int v = 0; v < length; v++) {
00293 Vertexf vertex = geom->get_next_vertex(vi) * mat;
00294
00295 if (found_any) {
00296 min_point.set(min(min_point[0], vertex[0]),
00297 min(min_point[1], vertex[1]),
00298 min(min_point[2], vertex[2]));
00299 max_point.set(max(max_point[0], vertex[0]),
00300 max(max_point[1], vertex[1]),
00301 max(max_point[2], vertex[2]));
00302 } else {
00303 min_point = vertex;
00304 max_point = vertex;
00305 found_any = true;
00306 }
00307 }
00308 }
00309 }
00310
00311 return next_transform;
00312 }
00313
00314
00315
00316
00317
00318
00319
00320 void GeomNode::
00321 add_geoms_from(const GeomNode *other) {
00322 CDReader cdata_other(other->_cycler);
00323 CDWriter cdata(_cycler);
00324
00325 Geoms::const_iterator gi;
00326 for (gi = cdata_other->_geoms.begin();
00327 gi != cdata_other->_geoms.end();
00328 ++gi) {
00329 const GeomEntry &entry = (*gi);
00330 cdata->_geoms.push_back(entry);
00331 }
00332 mark_bound_stale();
00333 }
00334
00335
00336
00337
00338
00339
00340
00341 void GeomNode::
00342 write_geoms(ostream &out, int indent_level) const {
00343 CDReader cdata(_cycler);
00344 write(out, indent_level);
00345 Geoms::const_iterator gi;
00346 for (gi = cdata->_geoms.begin(); gi != cdata->_geoms.end(); ++gi) {
00347 const GeomEntry &entry = (*gi);
00348 indent(out, indent_level + 2)
00349 << *entry._geom << " " << *entry._state << "\n";
00350 }
00351 }
00352
00353
00354
00355
00356
00357
00358
00359 void GeomNode::
00360 write_verbose(ostream &out, int indent_level) const {
00361 CDReader cdata(_cycler);
00362 write(out, indent_level);
00363 Geoms::const_iterator gi;
00364 for (gi = cdata->_geoms.begin(); gi != cdata->_geoms.end(); ++gi) {
00365 const GeomEntry &entry = (*gi);
00366 indent(out, indent_level + 2)
00367 << *entry._geom << " " << *entry._state << "\n";
00368 entry._geom->write_verbose(out, indent_level + 4);
00369 }
00370 }
00371
00372
00373
00374
00375
00376
00377 void GeomNode::
00378 output(ostream &out) const {
00379 PandaNode::output(out);
00380 out << " (" << get_num_geoms() << " geoms)";
00381 }
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 bool GeomNode::
00395 is_geom_node() const {
00396 return true;
00397 }
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 BoundingVolume *GeomNode::
00408 recompute_internal_bound() {
00409
00410 BoundingVolume *bound = PandaNode::recompute_internal_bound();
00411 nassertr(bound != (BoundingVolume *)NULL, bound);
00412
00413
00414
00415 pvector<const BoundingVolume *> child_volumes;
00416
00417 CDReader cdata(_cycler);
00418 Geoms::const_iterator gi;
00419 for (gi = cdata->_geoms.begin(); gi != cdata->_geoms.end(); ++gi) {
00420 const GeomEntry &entry = (*gi);
00421 child_volumes.push_back(&entry._geom->get_bound());
00422 }
00423
00424 const BoundingVolume **child_begin = &child_volumes[0];
00425 const BoundingVolume **child_end = child_begin + child_volumes.size();
00426
00427 bound->around(child_begin, child_end);
00428 return bound;
00429 }
00430
00431
00432
00433
00434
00435
00436
00437 void GeomNode::
00438 register_with_read_factory() {
00439 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00440 }
00441
00442
00443
00444
00445
00446
00447
00448 void GeomNode::
00449 write_datagram(BamWriter *manager, Datagram &dg) {
00450 PandaNode::write_datagram(manager, dg);
00451 manager->write_cdata(dg, _cycler);
00452 }
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 TypedWritable *GeomNode::
00463 make_from_bam(const FactoryParams ¶ms) {
00464 GeomNode *node = new GeomNode("");
00465 DatagramIterator scan;
00466 BamReader *manager;
00467
00468 parse_params(params, scan, manager);
00469 node->fillin(scan, manager);
00470
00471 return node;
00472 }
00473
00474
00475
00476
00477
00478
00479
00480
00481 void GeomNode::
00482 fillin(DatagramIterator &scan, BamReader *manager) {
00483 PandaNode::fillin(scan, manager);
00484 manager->read_cdata(scan, _cycler);
00485 }