00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "texProjectorEffect.h"
00016 #include "cullTraverserData.h"
00017 #include "texMatrixAttrib.h"
00018 #include "lensNode.h"
00019 #include "config_pgraph.h"
00020 #include "nodePath.h"
00021 #include "bamReader.h"
00022 #include "bamWriter.h"
00023 #include "datagram.h"
00024 #include "datagramIterator.h"
00025
00026 CPT(RenderEffect) TexProjectorEffect::_empty_effect;
00027 TypeHandle TexProjectorEffect::_type_handle;
00028
00029
00030
00031
00032
00033
00034 TexProjectorEffect::
00035 ~TexProjectorEffect() {
00036 }
00037
00038
00039
00040
00041
00042
00043
00044 CPT(RenderEffect) TexProjectorEffect::
00045 make() {
00046
00047
00048 if (_empty_effect == (RenderEffect *)NULL) {
00049 _empty_effect = return_new(new TexProjectorEffect);
00050 }
00051
00052 return _empty_effect;
00053 }
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 CPT(RenderEffect) TexProjectorEffect::
00073 add_stage(TextureStage *stage, const NodePath &from, const NodePath &to, int lens_index) const {
00074 TexProjectorEffect *effect = new TexProjectorEffect(*this);
00075 StageDef &def = effect->_stages[stage];
00076 def.set_from(from);
00077 def.set_to(to);
00078 def.set_lens_index(lens_index);
00079 return return_new(effect);
00080 }
00081
00082
00083
00084
00085
00086
00087
00088 CPT(RenderEffect) TexProjectorEffect::
00089 remove_stage(TextureStage *stage) const {
00090 TexProjectorEffect *effect = new TexProjectorEffect(*this);
00091 effect->_stages.erase(stage);
00092 return return_new(effect);
00093 }
00094
00095
00096
00097
00098
00099
00100
00101 bool TexProjectorEffect::
00102 is_empty() const {
00103 return _stages.empty();
00104 }
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 bool TexProjectorEffect::
00115 has_stage(TextureStage *stage) const {
00116 Stages::const_iterator mi = _stages.find(stage);
00117 return (mi != _stages.end());
00118 }
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 NodePath TexProjectorEffect::
00130 get_from(TextureStage *stage) const {
00131 Stages::const_iterator mi = _stages.find(stage);
00132 nassertr(mi != _stages.end(), NodePath::fail());
00133 return (*mi).second._from;
00134 }
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 NodePath TexProjectorEffect::
00150 get_to(TextureStage *stage) const {
00151 Stages::const_iterator mi = _stages.find(stage);
00152 nassertr(mi != _stages.end(), NodePath::fail());
00153 return (*mi).second._to;
00154 }
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 int TexProjectorEffect::
00166 get_lens_index(TextureStage *stage) const {
00167 Stages::const_iterator mi = _stages.find(stage);
00168 nassertr(mi != _stages.end(), 0);
00169 return (*mi).second._lens_index;
00170 }
00171
00172
00173
00174
00175
00176
00177 void TexProjectorEffect::
00178 output(ostream &out) const {
00179 out << get_type() << ":";
00180
00181 Stages::const_iterator mi;
00182 for (mi = _stages.begin(); mi != _stages.end(); ++mi) {
00183 TextureStage *stage = (*mi).first;
00184 const StageDef &def = (*mi).second;
00185 out << " " << stage->get_name() << "(" << def._to
00186 << ", " << def._from << ", " << def._lens_index << ")";
00187 }
00188 }
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199 bool TexProjectorEffect::
00200 has_cull_callback() const {
00201 return !_stages.empty();
00202 }
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 void TexProjectorEffect::
00222 cull_callback(CullTraverser *trav, CullTraverserData &data,
00223 CPT(TransformState) &node_transform,
00224 CPT(RenderState) &node_state) const {
00225 CPT(TexMatrixAttrib) tex_matrix = DCAST(TexMatrixAttrib, TexMatrixAttrib::make());
00226
00227 Stages::const_iterator mi;
00228 for (mi = _stages.begin(); mi != _stages.end(); ++mi) {
00229 TextureStage *stage = (*mi).first;
00230 const StageDef &def = (*mi).second;
00231
00232 CPT(TransformState) transform = def._from.get_transform(def._to);
00233
00234 if (def._to_lens_node != (LensNode *)NULL &&
00235 def._to_lens_node->get_lens() != (Lens *)NULL) {
00236
00237
00238 Lens *lens = def._to_lens_node->get_lens(def._lens_index);
00239 if (lens != NULL) {
00240 CPT(TransformState) projmat = TransformState::make_mat(lens->get_projection_mat());
00241
00242
00243
00244
00245 static CPT(TransformState) fixmat;
00246 if (fixmat == (TransformState *)NULL) {
00247 fixmat = TransformState::make_pos_hpr_scale
00248 (LVecBase3(0.5f, 0.5f, 0.0f),
00249 LVecBase3(0.0f, 0.0f, 0.0f),
00250 LVecBase3(0.5f, 0.5f, 1.0f));
00251 }
00252
00253
00254 transform = fixmat->compose(projmat)->compose(transform);
00255 }
00256 }
00257
00258 if (!transform->is_identity()) {
00259 tex_matrix = DCAST(TexMatrixAttrib,
00260 tex_matrix->add_stage(stage, transform));
00261 }
00262 }
00263
00264 if (!tex_matrix->is_empty()) {
00265 node_state = node_state->compose(RenderState::make(tex_matrix));
00266 }
00267 }
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284 int TexProjectorEffect::
00285 compare_to_impl(const RenderEffect *other) const {
00286 const TexProjectorEffect *ta;
00287 DCAST_INTO_R(ta, other, 0);
00288
00289 Stages::const_iterator ai, bi;
00290 ai = _stages.begin();
00291 bi = ta->_stages.begin();
00292 while (ai != _stages.end() && bi != ta->_stages.end()) {
00293 if ((*ai).first < (*bi).first) {
00294
00295 return -1;
00296
00297 } else if ((*bi).first < (*ai).first) {
00298
00299 return 1;
00300
00301 } else {
00302
00303 int compare = (*ai).second.compare_to((*bi).second);
00304 if (compare != 0) {
00305 return compare;
00306 }
00307 ++ai;
00308 ++bi;
00309 }
00310 }
00311
00312 if (bi != ta->_stages.end()) {
00313
00314 return -1;
00315 }
00316
00317 if (ai != _stages.end()) {
00318
00319 return 1;
00320 }
00321
00322 return 0;
00323 }
00324
00325
00326
00327
00328
00329
00330
00331 void TexProjectorEffect::
00332 register_with_read_factory() {
00333 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00334 }
00335
00336
00337
00338
00339
00340
00341
00342 void TexProjectorEffect::
00343 write_datagram(BamWriter *manager, Datagram &dg) {
00344 RenderEffect::write_datagram(manager, dg);
00345
00346
00347
00348
00349 dg.add_uint16(0);
00350
00351
00352
00353
00354
00355
00356 }
00357
00358
00359
00360
00361
00362
00363
00364
00365 int TexProjectorEffect::
00366 complete_pointers(TypedWritable **p_list, BamReader *manager) {
00367 int pi = RenderEffect::complete_pointers(p_list, manager);
00368
00369 return pi;
00370 }
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380 TypedWritable *TexProjectorEffect::
00381 make_from_bam(const FactoryParams ¶ms) {
00382 TexProjectorEffect *effect = new TexProjectorEffect;
00383 DatagramIterator scan;
00384 BamReader *manager;
00385
00386 parse_params(params, scan, manager);
00387 effect->fillin(scan, manager);
00388
00389 return effect;
00390 }
00391
00392
00393
00394
00395
00396
00397
00398
00399 void TexProjectorEffect::
00400 fillin(DatagramIterator &scan, BamReader *manager) {
00401 RenderEffect::fillin(scan, manager);
00402
00403 size_t num_stages = scan.get_uint16();
00404
00405
00406
00407
00408
00409 nassertv(num_stages == 0);
00410 }
00411
00412
00413
00414
00415
00416
00417 void TexProjectorEffect::StageDef::
00418 set_to(const NodePath &to) {
00419 _to = to;
00420 if (!_to.is_empty() && _to.node()->is_of_type(LensNode::get_class_type())) {
00421 DCAST_INTO_V(_to_lens_node, _to.node());
00422 } else {
00423 _to_lens_node = (LensNode *)NULL;
00424 }
00425 }