00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "eggGroup.h"
00016 #include "eggMiscFuncs.h"
00017 #include "eggVertexPool.h"
00018 #include "eggBin.h"
00019 #include "lexerDefs.h"
00020
00021 #include "indent.h"
00022 #include "string_utils.h"
00023 #include "lmatrix.h"
00024 #include "dcast.h"
00025
00026
00027 TypeHandle EggGroup::_type_handle;
00028
00029
00030
00031
00032
00033
00034 EggGroup::
00035 EggGroup(const string &name) : EggGroupNode(name) {
00036 _flags = 0;
00037 _flags2 = 0;
00038 _fps = 0.0;
00039 _blend_mode = BM_unspecified;
00040 _blend_operand_a = BO_unspecified;
00041 _blend_operand_b = BO_unspecified;
00042 _blend_color = Colorf::zero();
00043 _u_speed = 0;
00044 _v_speed = 0;
00045 _r_speed = 0;
00046 }
00047
00048
00049
00050
00051
00052
00053 EggGroup::
00054 EggGroup(const EggGroup ©) {
00055 (*this) = copy;
00056 }
00057
00058
00059
00060
00061
00062
00063 EggGroup &EggGroup::
00064 operator = (const EggGroup ©) {
00065 EggTransform::operator = (copy);
00066 _flags = copy._flags;
00067 _flags2 = copy._flags2;
00068 _collide_mask = copy._collide_mask;
00069 _from_collide_mask = copy._from_collide_mask;
00070 _into_collide_mask = copy._into_collide_mask;
00071 _billboard_center = copy._billboard_center;
00072 _object_types = copy._object_types;
00073 _collision_name = copy._collision_name;
00074 _fps = copy._fps;
00075 _lod = copy._lod;
00076 _blend_mode = copy._blend_mode;
00077 _blend_operand_a = copy._blend_operand_a;
00078 _blend_operand_b = copy._blend_operand_b;
00079 _blend_color = copy._blend_color;
00080 _tag_data = copy._tag_data;
00081 _u_speed = copy._u_speed;
00082 _v_speed = copy._v_speed;
00083 _r_speed = copy._r_speed;
00084 _default_pose = copy._default_pose;
00085
00086 unref_all_vertices();
00087 _vref = copy._vref;
00088
00089
00090
00091 VertexRef::iterator vri;
00092 for (vri = _vref.begin(); vri != _vref.end(); ++vri) {
00093 EggVertex *vert = (*vri).first;
00094
00095 bool inserted = vert->_gref.insert(this).second;
00096
00097
00098
00099 nassertr(inserted, *this);
00100 }
00101
00102
00103
00104
00105 EggGroupNode::operator = (copy);
00106 EggRenderMode::operator = (copy);
00107
00108 return *this;
00109 }
00110
00111
00112
00113
00114
00115
00116
00117 EggGroup::
00118 ~EggGroup() {
00119 unref_all_vertices();
00120 }
00121
00122
00123
00124
00125
00126
00127 void EggGroup::
00128 set_group_type(GroupType type) {
00129 if (type != get_group_type()) {
00130 #ifndef NDEBUG
00131 if (type != GT_instance) {
00132
00133
00134 nassertv(_group_refs.empty());
00135 }
00136 #endif
00137
00138
00139 nassertv((type & ~F_group_type)==0);
00140 _flags = (_flags & ~F_group_type) | type;
00141
00142
00143
00144 update_under(0);
00145 }
00146 }
00147
00148
00149
00150
00151
00152
00153
00154 bool EggGroup::
00155 has_object_type(const string &object_type) const {
00156 vector_string::const_iterator oi;
00157 for (oi = _object_types.begin(); oi != _object_types.end(); ++oi) {
00158 if (cmp_nocase_uh((*oi), object_type) == 0) {
00159 return true;
00160 }
00161 }
00162 return false;
00163 }
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 bool EggGroup::
00174 remove_object_type(const string &object_type) {
00175 vector_string::iterator oi;
00176 for (oi = _object_types.begin(); oi != _object_types.end(); ++oi) {
00177 if (cmp_nocase_uh((*oi), object_type) == 0) {
00178 _object_types.erase(oi);
00179 return true;
00180 }
00181 }
00182 return false;
00183 }
00184
00185
00186
00187
00188
00189
00190
00191 void EggGroup::
00192 write(ostream &out, int indent_level) const {
00193 test_under_integrity();
00194
00195 switch (get_group_type()) {
00196 case GT_group:
00197 write_header(out, indent_level, "<Group>");
00198 break;
00199
00200 case GT_instance:
00201 write_header(out, indent_level, "<Instance>");
00202 break;
00203
00204 case GT_joint:
00205 write_header(out, indent_level, "<Joint>");
00206 break;
00207
00208 default:
00209
00210 nassertv(false);
00211 }
00212
00213 if (is_of_type(EggBin::get_class_type())) {
00214 indent(out, indent_level + 2)
00215 << "// Bin " << DCAST(EggBin, this)->get_bin_number() << "\n";
00216 }
00217
00218 if (has_lod()) {
00219 get_lod().write(out, indent_level + 2);
00220 }
00221
00222 write_billboard_flags(out, indent_level + 2);
00223 write_collide_flags(out, indent_level + 2);
00224 write_model_flags(out, indent_level + 2);
00225 write_switch_flags(out, indent_level + 2);
00226
00227 if (has_transform()) {
00228 EggTransform::write(out, indent_level + 2, "<Transform>");
00229 }
00230
00231 if (get_group_type() == GT_joint && _default_pose.has_transform()) {
00232 _default_pose.write(out, indent_level + 2, "<DefaultPose>");
00233 }
00234
00235 if(get_scroll_u() != 0) {
00236 indent(out, indent_level)
00237 << "<Scalar> scroll_u { " << get_scroll_u() << " }\n";
00238
00239 }
00240
00241 if(get_scroll_v() != 0) {
00242 indent(out, indent_level)
00243 << "<Scalar> scroll_v { " << get_scroll_v() << " }\n";
00244
00245 }
00246
00247 if(get_scroll_r() != 0) {
00248 indent(out, indent_level)
00249 << "<Scalar> scroll_r { " << get_scroll_r() << " }\n";
00250
00251 }
00252
00253
00254 write_object_types(out, indent_level + 2);
00255 write_decal_flags(out, indent_level + 2);
00256 write_tags(out, indent_level + 2);
00257 write_render_mode(out, indent_level + 2);
00258
00259 if (get_portal_flag()) {
00260 indent(out, indent_level) << "<Scalar> portal { 1 }\n";
00261 }
00262
00263 if (get_polylight_flag()) {
00264 indent(out, indent_level) << "<Scalar> polylight { 1 }\n";
00265 }
00266
00267 if (has_indexed_flag()) {
00268 indent(out, indent_level)
00269 << "<Scalar> indexed { " << get_indexed_flag() << " }\n";
00270 }
00271
00272 if (get_blend_mode() != BM_unspecified) {
00273 indent(out, indent_level)
00274 << "<Scalar> blend { " << get_blend_mode() << " }\n";
00275 }
00276
00277 if (get_blend_operand_a() != BO_unspecified) {
00278 indent(out, indent_level)
00279 << "<Scalar> blendop-a { " << get_blend_operand_a() << " }\n";
00280 }
00281
00282 if (get_blend_operand_b() != BO_unspecified) {
00283 indent(out, indent_level)
00284 << "<Scalar> blendop-b { " << get_blend_operand_b() << " }\n";
00285 }
00286
00287 if (has_blend_color()) {
00288 const Colorf &c = get_blend_color();
00289 indent(out, indent_level)
00290 << "<Scalar> blendr { " << c[0] << " }\n";
00291 indent(out, indent_level)
00292 << "<Scalar> blendg { " << c[1] << " }\n";
00293 indent(out, indent_level)
00294 << "<Scalar> blendb { " << c[2] << " }\n";
00295 indent(out, indent_level)
00296 << "<Scalar> blenda { " << c[3] << " }\n";
00297 }
00298
00299 GroupRefs::const_iterator gri;
00300 for (gri = _group_refs.begin(); gri != _group_refs.end(); ++gri) {
00301 EggGroup *group_ref = (*gri);
00302 indent(out, indent_level + 2)
00303 << "<Ref> { " << group_ref->get_name() << " }\n";
00304 }
00305
00306
00307
00308
00309 EggGroupNode::write(out, indent_level + 2);
00310 write_vertex_ref(out, indent_level + 2);
00311
00312 indent(out, indent_level) << "}\n";
00313 }
00314
00315
00316
00317
00318
00319
00320
00321 void EggGroup::
00322 write_billboard_flags(ostream &out, int indent_level) const {
00323 if (get_billboard_type() != BT_none) {
00324 indent(out, indent_level)
00325 << "<Billboard> { " << get_billboard_type() << " }\n";
00326 }
00327
00328 if (has_billboard_center()) {
00329 indent(out, indent_level)
00330 << "<BillboardCenter> { " << get_billboard_center() << " }\n";
00331 }
00332 }
00333
00334
00335
00336
00337
00338
00339
00340 void EggGroup::
00341 write_collide_flags(ostream &out, int indent_level) const {
00342 if (get_cs_type() != CST_none) {
00343 indent(out, indent_level) << "<Collide> ";
00344 if (has_collision_name()) {
00345 enquote_string(out, get_collision_name()) << " ";
00346 }
00347 out << "{ " << get_cs_type();
00348 if (get_collide_flags() != CF_none) {
00349 out << " " << get_collide_flags();
00350 }
00351 out << " }\n";
00352 }
00353
00354 if (has_collide_mask()) {
00355 indent(out, indent_level)
00356 << "<Scalar> collide-mask { 0x";
00357 get_collide_mask().output_hex(out, 0);
00358 out << " }\n";
00359 }
00360
00361 if (has_from_collide_mask()) {
00362 indent(out, indent_level)
00363 << "<Scalar> from-collide-mask { 0x";
00364 get_from_collide_mask().output_hex(out, 0);
00365 out << " }\n";
00366 }
00367
00368 if (has_into_collide_mask()) {
00369 indent(out, indent_level)
00370 << "<Scalar> into-collide-mask { 0x";
00371 get_into_collide_mask().output_hex(out, 0);
00372 out << " }\n";
00373 }
00374 }
00375
00376
00377
00378
00379
00380
00381
00382 void EggGroup::
00383 write_model_flags(ostream &out, int indent_level) const {
00384 if (get_dcs_type() != DC_unspecified) {
00385 indent(out, indent_level)
00386 << "<DCS> { " << get_dcs_type() << " }\n";
00387 }
00388
00389 if (get_dart_type() != DT_none) {
00390 indent(out, indent_level)
00391 << "<Dart> { " << get_dart_type() << " }\n";
00392 }
00393
00394 if (get_model_flag()) {
00395 indent(out, indent_level) << "<Model> { 1 }\n";
00396 }
00397
00398 if (get_texlist_flag()) {
00399 indent(out, indent_level) << "<TexList> { 1 }\n";
00400 }
00401
00402 if (get_direct_flag()) {
00403 indent(out, indent_level) << "<Scalar> direct { 1 }\n";
00404 }
00405 }
00406
00407
00408
00409
00410
00411
00412
00413 void EggGroup::
00414 write_switch_flags(ostream &out, int indent_level) const {
00415 if (get_switch_flag()) {
00416 indent(out, indent_level) << "<Switch> { 1 }\n";
00417 if (get_switch_fps() != 0.0) {
00418 indent(out, indent_level)
00419 << "<Scalar> fps { " << get_switch_fps() << " }\n";
00420 }
00421 }
00422 }
00423
00424
00425
00426
00427
00428
00429
00430 void EggGroup::
00431 write_object_types(ostream &out, int indent_level) const {
00432 vector_string::const_iterator oi;
00433 for (oi = _object_types.begin(); oi != _object_types.end(); ++oi) {
00434 indent(out, indent_level)
00435 << "<ObjectType> { ";
00436 enquote_string(out, (*oi)) << " }\n";
00437 }
00438 }
00439
00440
00441
00442
00443
00444
00445 void EggGroup::
00446 write_decal_flags(ostream &out, int indent_level) const {
00447 if (get_decal_flag()) {
00448 indent(out, indent_level) << "<Scalar> decal { 1 }\n";
00449 }
00450 }
00451
00452
00453
00454
00455
00456
00457
00458 void EggGroup::
00459 write_tags(ostream &out, int indent_level) const {
00460 TagData::const_iterator ti;
00461 for (ti = _tag_data.begin(); ti != _tag_data.end(); ++ti) {
00462 const string &key = (*ti).first;
00463 const string &value = (*ti).second;
00464
00465 indent(out, indent_level) << "<Tag> ";
00466 enquote_string(out, key) << " {\n";
00467 enquote_string(out, value, indent_level + 2) << "\n";
00468 indent(out, indent_level) << "}\n";
00469 }
00470 }
00471
00472
00473
00474
00475
00476
00477
00478 void EggGroup::
00479 write_render_mode(ostream &out, int indent_level) const {
00480 EggRenderMode::write(out, indent_level);
00481
00482 if (get_nofog_flag()) {
00483 indent(out, indent_level) << "<Scalar> no-fog { 1 }\n";
00484 }
00485 }
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496 bool EggGroup::
00497 is_joint() const {
00498 return (get_group_type() == GT_joint);
00499 }
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510 EggRenderMode *EggGroup::
00511 determine_alpha_mode() {
00512 if (get_alpha_mode() != AM_unspecified) {
00513 return this;
00514 }
00515 return EggGroupNode::determine_alpha_mode();
00516 }
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527 EggRenderMode *EggGroup::
00528 determine_depth_write_mode() {
00529 if (get_depth_write_mode() != DWM_unspecified) {
00530 return this;
00531 }
00532 return EggGroupNode::determine_depth_write_mode();
00533 }
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544 EggRenderMode *EggGroup::
00545 determine_depth_test_mode() {
00546 if (get_depth_test_mode() != DTM_unspecified) {
00547 return this;
00548 }
00549 return EggGroupNode::determine_depth_test_mode();
00550 }
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561 EggRenderMode *EggGroup::
00562 determine_visibility_mode() {
00563 if (get_visibility_mode() != VM_unspecified) {
00564 return this;
00565 }
00566 return EggGroupNode::determine_visibility_mode();
00567 }
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578 EggRenderMode *EggGroup::
00579 determine_depth_offset() {
00580 if (has_depth_offset()) {
00581 return this;
00582 }
00583 return EggGroupNode::determine_depth_offset();
00584 }
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595 EggRenderMode *EggGroup::
00596 determine_draw_order() {
00597 if (has_draw_order()) {
00598 return this;
00599 }
00600 return EggGroupNode::determine_draw_order();
00601 }
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612 EggRenderMode *EggGroup::
00613 determine_bin() {
00614 if (has_bin()) {
00615 return this;
00616 }
00617 return EggGroupNode::determine_bin();
00618 }
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631 bool EggGroup::
00632 determine_indexed() {
00633 if (has_indexed_flag()) {
00634 return get_indexed_flag();
00635 }
00636 return EggGroupNode::determine_indexed();
00637 }
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650 bool EggGroup::
00651 determine_decal() {
00652 if (get_decal_flag()) {
00653 return true;
00654 }
00655 return EggGroupNode::determine_decal();
00656 }
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666 void EggGroup::
00667 ref_vertex(EggVertex *vert, double membership) {
00668 VertexRef::iterator vri = _vref.find(vert);
00669
00670 if (vri != _vref.end()) {
00671
00672
00673 (*vri).second += membership;
00674
00675
00676 if ((*vri).second == 0.0) {
00677 unref_vertex(vert);
00678 }
00679
00680 } else {
00681
00682 if (membership != 0.0) {
00683 _vref[vert] = membership;
00684
00685 bool inserted = vert->_gref.insert(this).second;
00686
00687
00688
00689 nassertv(inserted);
00690 }
00691 }
00692 }
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702 void EggGroup::
00703 unref_vertex(EggVertex *vert) {
00704 VertexRef::iterator vri = _vref.find(vert);
00705
00706 if (vri != _vref.end()) {
00707 _vref.erase(vri);
00708 int count = vert->_gref.erase(this);
00709
00710
00711 nassertv(count == 1);
00712 }
00713 }
00714
00715
00716
00717
00718
00719
00720 void EggGroup::
00721 unref_all_vertices() {
00722
00723
00724 VertexRef::iterator vri;
00725 for (vri = _vref.begin(); vri != _vref.end(); ++vri) {
00726 EggVertex *vert = (*vri).first;
00727 int count = vert->_gref.erase(this);
00728
00729
00730 nassertv(count == 1);
00731 }
00732
00733 _vref.clear();
00734 }
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744 double EggGroup::
00745 get_vertex_membership(const EggVertex *vert) const {
00746 VertexRef::const_iterator vri = _vref.find((EggVertex *)vert);
00747
00748 if (vri != _vref.end()) {
00749 return (*vri).second;
00750 } else {
00751 return 0.0;
00752 }
00753 }
00754
00755
00756
00757
00758
00759
00760
00761 void EggGroup::
00762 set_vertex_membership(EggVertex *vert, double membership) {
00763 if (membership == 0.0) {
00764 unref_vertex(vert);
00765 return;
00766 }
00767
00768 VertexRef::iterator vri = _vref.find(vert);
00769
00770 if (vri != _vref.end()) {
00771
00772
00773 (*vri).second = membership;
00774
00775 } else {
00776
00777 _vref[vert] = membership;
00778
00779 bool inserted = vert->_gref.insert(this).second;
00780
00781
00782
00783 nassertv(inserted);
00784 }
00785 }
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795 void EggGroup::
00796 steal_vrefs(EggGroup *other) {
00797 nassertv(other != this);
00798 VertexRef::const_iterator vri;
00799 for (vri = other->vref_begin(); vri != other->vref_end(); ++vri) {
00800 EggVertex *vert = (*vri).first;
00801 double membership = (*vri).second;
00802 ref_vertex(vert, membership);
00803 }
00804 other->unref_all_vertices();
00805 }
00806
00807
00808 #ifndef NDEBUG
00809
00810
00811
00812
00813
00814
00815
00816 void EggGroup::
00817 test_vref_integrity() const {
00818 test_ref_count_integrity();
00819
00820 VertexRef::const_iterator vri;
00821 for (vri = vref_begin(); vri != vref_end(); ++vri) {
00822 const EggVertex *vert = (*vri).first;
00823 vert->test_ref_count_integrity();
00824
00825 nassertv(vert->has_gref(this));
00826 }
00827 }
00828
00829 #endif // NDEBUG
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839 void EggGroup::
00840 add_group_ref(EggGroup *group) {
00841 nassertv(get_group_type() == GT_instance);
00842 _group_refs.push_back(group);
00843 }
00844
00845
00846
00847
00848
00849
00850
00851 int EggGroup::
00852 get_num_group_refs() const {
00853 return _group_refs.size();
00854 }
00855
00856
00857
00858
00859
00860
00861
00862 EggGroup *EggGroup::
00863 get_group_ref(int n) const {
00864 nassertr(n >= 0 && n < (int)_group_refs.size(), NULL);
00865 return _group_refs[n];
00866 }
00867
00868
00869
00870
00871
00872
00873
00874 void EggGroup::
00875 remove_group_ref(int n) {
00876 nassertv(n >= 0 && n < (int)_group_refs.size());
00877 _group_refs.erase(_group_refs.begin() + n);
00878 }
00879
00880
00881
00882
00883
00884
00885
00886 void EggGroup::
00887 clear_group_refs() {
00888 _group_refs.clear();
00889 }
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900 EggGroup::GroupType EggGroup::
00901 string_group_type(const string &strval) {
00902 if (cmp_nocase_uh(strval, "group") == 0) {
00903 return GT_group;
00904 } else if (cmp_nocase_uh(strval, "instance") == 0) {
00905 return GT_instance;
00906 } else if (cmp_nocase_uh(strval, "joint") == 0) {
00907 return GT_joint;
00908 } else {
00909 return GT_invalid;
00910 }
00911 }
00912
00913
00914
00915
00916
00917
00918
00919
00920 EggGroup::DartType EggGroup::
00921 string_dart_type(const string &strval) {
00922 if (cmp_nocase_uh(strval, "sync") == 0) {
00923 return DT_sync;
00924 } else if (cmp_nocase_uh(strval, "nosync") == 0) {
00925 return DT_nosync;
00926 } else if (cmp_nocase_uh(strval, "default") == 0) {
00927 return DT_default;
00928 } else if (cmp_nocase_uh(strval, "structured") == 0) {
00929 return DT_structured;
00930 } else {
00931 return DT_none;
00932 }
00933 }
00934
00935
00936
00937
00938
00939
00940
00941
00942 EggGroup::DCSType EggGroup::
00943 string_dcs_type(const string &strval) {
00944 if (cmp_nocase_uh(strval, "none") == 0) {
00945 return DC_none;
00946 } else if (cmp_nocase_uh(strval, "local") == 0) {
00947 return DC_local;
00948 } else if (cmp_nocase_uh(strval, "net") == 0) {
00949 return DC_net;
00950 } else if (cmp_nocase_uh(strval, "no_touch") == 0) {
00951 return DC_no_touch;
00952 } else if (cmp_nocase_uh(strval, "default") == 0) {
00953 return DC_default;
00954 } else {
00955 return DC_unspecified;
00956 }
00957 }
00958
00959
00960
00961
00962
00963
00964
00965
00966 EggGroup::BillboardType EggGroup::
00967 string_billboard_type(const string &strval) {
00968 if (cmp_nocase_uh(strval, "axis") == 0) {
00969 return BT_axis;
00970 } else if (cmp_nocase_uh(strval, "point_eye") == 0) {
00971 return BT_point_camera_relative;
00972 } else if (cmp_nocase_uh(strval, "point_world") == 0) {
00973 return BT_point_world_relative;
00974 } else if (cmp_nocase_uh(strval, "point") == 0) {
00975 return BT_point_world_relative;
00976 } else {
00977 return BT_none;
00978 }
00979 }
00980
00981
00982
00983
00984
00985
00986
00987
00988 EggGroup::CollisionSolidType EggGroup::
00989 string_cs_type(const string &strval) {
00990 if (cmp_nocase_uh(strval, "plane") == 0) {
00991 return CST_plane;
00992 } else if (cmp_nocase_uh(strval, "polygon") == 0) {
00993 return CST_polygon;
00994 } else if (cmp_nocase_uh(strval, "polyset") == 0) {
00995 return CST_polyset;
00996 } else if (cmp_nocase_uh(strval, "sphere") == 0) {
00997 return CST_sphere;
00998 } else if (cmp_nocase_uh(strval, "inv-sphere") == 0 ||
00999 cmp_nocase_uh(strval, "invsphere") == 0) {
01000 return CST_inv_sphere;
01001 } else if (cmp_nocase_uh(strval, "tube") == 0) {
01002 return CST_tube;
01003 } else if (cmp_nocase_uh(strval, "floor-mesh") == 0) {
01004 return CST_floor_mesh;
01005 } else {
01006 return CST_none;
01007 }
01008 }
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019 EggGroup::CollideFlags EggGroup::
01020 string_collide_flags(const string &strval) {
01021 if (cmp_nocase_uh(strval, "intangible") == 0) {
01022 return CF_intangible;
01023 } else if (cmp_nocase_uh(strval, "event") == 0) {
01024 return CF_event;
01025 } else if (cmp_nocase_uh(strval, "descend") == 0) {
01026 return CF_descend;
01027 } else if (cmp_nocase_uh(strval, "keep") == 0) {
01028 return CF_keep;
01029 } else if (cmp_nocase_uh(strval, "solid") == 0) {
01030 return CF_solid;
01031 } else if (cmp_nocase_uh(strval, "center") == 0) {
01032 return CF_center;
01033 } else if (cmp_nocase_uh(strval, "turnstile") == 0) {
01034 return CF_turnstile;
01035 } else if (cmp_nocase_uh(strval, "level") == 0) {
01036 return CF_level;
01037 } else {
01038 return CF_none;
01039 }
01040 }
01041
01042
01043
01044
01045
01046
01047
01048
01049 EggGroup::BlendMode EggGroup::
01050 string_blend_mode(const string &strval) {
01051 if (cmp_nocase_uh(strval, "none") == 0) {
01052 return BM_none;
01053 } else if (cmp_nocase_uh(strval, "add") == 0) {
01054 return BM_add;
01055 } else if (cmp_nocase_uh(strval, "subtract") == 0) {
01056 return BM_subtract;
01057 } else if (cmp_nocase_uh(strval, "inv_subtract") == 0) {
01058 return BM_inv_subtract;
01059 } else if (cmp_nocase_uh(strval, "min") == 0) {
01060 return BM_min;
01061 } else if (cmp_nocase_uh(strval, "max") == 0) {
01062 return BM_max;
01063 } else {
01064 return BM_unspecified;
01065 }
01066 }
01067
01068
01069
01070
01071
01072
01073
01074
01075 EggGroup::BlendOperand EggGroup::
01076 string_blend_operand(const string &strval) {
01077 if (cmp_nocase_uh(strval, "zero") == 0) {
01078 return BO_zero;
01079 } else if (cmp_nocase_uh(strval, "one") == 0) {
01080 return BO_one;
01081 } else if (cmp_nocase_uh(strval, "incoming_color") == 0) {
01082 return BO_incoming_color;
01083 } else if (cmp_nocase_uh(strval, "one_minus_incoming_color") == 0) {
01084 return BO_one_minus_incoming_color;
01085 } else if (cmp_nocase_uh(strval, "fbuffer_color") == 0) {
01086 return BO_fbuffer_color;
01087 } else if (cmp_nocase_uh(strval, "one_minus_fbuffer_color") == 0) {
01088 return BO_one_minus_fbuffer_color;
01089 } else if (cmp_nocase_uh(strval, "incoming_alpha") == 0) {
01090 return BO_incoming_alpha;
01091 } else if (cmp_nocase_uh(strval, "one_minus_incoming_alpha") == 0) {
01092 return BO_one_minus_incoming_alpha;
01093 } else if (cmp_nocase_uh(strval, "fbuffer_alpha") == 0) {
01094 return BO_fbuffer_alpha;
01095 } else if (cmp_nocase_uh(strval, "one_minus_fbuffer_alpha") == 0) {
01096 return BO_one_minus_fbuffer_alpha;
01097 } else if (cmp_nocase_uh(strval, "constant_color") == 0) {
01098 return BO_constant_color;
01099 } else if (cmp_nocase_uh(strval, "one_minus_constant_color") == 0) {
01100 return BO_one_minus_constant_color;
01101 } else if (cmp_nocase_uh(strval, "constant_alpha") == 0) {
01102 return BO_constant_alpha;
01103 } else if (cmp_nocase_uh(strval, "one_minus_constant_alpha") == 0) {
01104 return BO_one_minus_constant_alpha;
01105 } else if (cmp_nocase_uh(strval, "incoming_color_saturate") == 0) {
01106 return BO_incoming_color_saturate;
01107 } else if (cmp_nocase_uh(strval, "color_scale") == 0) {
01108 return BO_color_scale;
01109 } else if (cmp_nocase_uh(strval, "one_minus_color_scale") == 0) {
01110 return BO_one_minus_color_scale;
01111 } else if (cmp_nocase_uh(strval, "alpha_scale") == 0) {
01112 return BO_alpha_scale;
01113 } else if (cmp_nocase_uh(strval, "one_minus_alpha_scale") == 0) {
01114 return BO_one_minus_alpha_scale;
01115 } else {
01116 return BO_unspecified;
01117 }
01118 }
01119
01120
01121
01122
01123
01124
01125
01126
01127 EggTransform *EggGroup::
01128 as_transform() {
01129 return this;
01130 }
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140 void EggGroup::
01141 write_vertex_ref(ostream &out, int indent_level) const {
01142
01143
01144
01145
01146
01147 typedef pset<int> Indices;
01148 typedef pmap<double, Indices> Memberships;
01149 typedef pmap<EggVertexPool *, Memberships> Pools;
01150
01151 Pools _entries;
01152 bool all_membership_one = true;
01153
01154 VertexRef::const_iterator vri;
01155 for (vri = _vref.begin(); vri != _vref.end(); ++vri) {
01156 EggVertex *vert = (*vri).first;
01157 double membership = (*vri).second;
01158
01159 if (membership != 1.0) {
01160 all_membership_one = false;
01161 }
01162
01163 _entries[vert->get_pool()][membership].insert(vert->get_index());
01164 }
01165
01166
01167
01168 Pools::const_iterator pi;
01169 for (pi = _entries.begin(); pi != _entries.end(); ++pi) {
01170 EggVertexPool *pool = (*pi).first;
01171 const Memberships &memberships = (*pi).second;
01172 Memberships::const_iterator mi;
01173 for (mi = memberships.begin(); mi != memberships.end(); ++mi) {
01174 double membership = (*mi).first;
01175 const Indices &indices = (*mi).second;
01176
01177 indent(out, indent_level)
01178 << "<VertexRef> {\n";
01179 write_long_list(out, indent_level+2, indices.begin(), indices.end(),
01180 "", "", 72);
01181
01182
01183
01184 if (!all_membership_one) {
01185 indent(out, indent_level + 2)
01186 << "<Scalar> membership { " << membership << " }\n";
01187 }
01188 if (pool == (EggVertexPool *)NULL) {
01189 indent(out, indent_level + 2)
01190 << "// Invalid NULL vertex pool.\n";
01191 } else {
01192 indent(out, indent_level + 2)
01193 << "<Ref> { " << pool->get_name() << " }\n";
01194 }
01195 indent(out, indent_level)
01196 << "}\n";
01197 }
01198 }
01199 }
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210 bool EggGroup::
01211 egg_start_parse_body() {
01212 egg_start_group_body();
01213 return true;
01214 }
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226 void EggGroup::
01227 adjust_under() {
01228
01229
01230
01231
01232
01233 if (has_transform()) {
01234 _under_flags |= UF_under_transform;
01235
01236
01237 _node_frame =
01238 new MatrixFrame(get_transform3d() * get_node_frame());
01239
01240
01241 LMatrix4d mat;
01242 bool invert_ok = mat.invert_from(get_node_frame());
01243 if (invert_ok) {
01244 _node_frame_inv =
01245 new MatrixFrame(mat);
01246 } else {
01247 _node_frame_inv = NULL;
01248 }
01249
01250 _vertex_to_node =
01251 new MatrixFrame(get_vertex_frame() * get_node_frame_inv());
01252 _node_to_vertex =
01253 new MatrixFrame(get_node_frame() * get_vertex_frame_inv());
01254
01255 }
01256
01257 if (is_instance_type()) {
01258 _under_flags |= UF_under_instance;
01259 if (_under_flags & UF_under_transform) {
01260
01261
01262
01263 _under_flags |= UF_local_coord;
01264 }
01265
01266
01267
01268
01269 _vertex_frame = _node_frame;
01270 _vertex_frame_inv = _node_frame_inv;
01271 _vertex_to_node = NULL;
01272 _node_to_vertex = NULL;
01273 }
01274 }
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289 void EggGroup::
01290 r_transform(const LMatrix4d &mat, const LMatrix4d &inv,
01291 CoordinateSystem to_cs) {
01292 if (has_transform() || get_group_type() == GT_joint) {
01293
01294
01295
01296
01297
01298
01299
01300
01301 LMatrix4d mat1 = mat;
01302 LMatrix4d inv1 = inv;
01303
01304
01305
01306
01307 mat1.set_row(3, LVector3d(0.0, 0.0, 0.0));
01308 inv1.set_row(3, LVector3d(0.0, 0.0, 0.0));
01309
01310 internal_set_transform(inv1 * get_transform3d() * mat);
01311
01312 if (_default_pose.has_transform()) {
01313 LMatrix4d t = _default_pose.get_transform3d();
01314 _default_pose.clear_transform();
01315 _default_pose.add_matrix4(inv1 * t * mat);
01316 }
01317
01318 EggGroupNode::r_transform(mat1, inv1, to_cs);
01319 } else {
01320 EggGroupNode::r_transform(mat, inv, to_cs);
01321 }
01322
01323
01324 if (has_lod()) {
01325 _lod->transform(mat);
01326 }
01327 if (has_billboard_center()) {
01328 _billboard_center = _billboard_center * mat;
01329 }
01330 }
01331
01332
01333
01334
01335
01336
01337 void EggGroup::
01338 r_flatten_transforms() {
01339 EggGroupNode::r_flatten_transforms();
01340
01341 if (is_local_coord()) {
01342 LMatrix4d mat = get_vertex_frame();
01343 if (has_lod()) {
01344 _lod->transform(mat);
01345 }
01346
01347 if (get_billboard_type() != BT_none && !has_billboard_center()) {
01348
01349
01350 set_billboard_center(LPoint3d(0.0, 0.0, 0.0) * mat);
01351
01352 } else if (has_billboard_center()) {
01353 _billboard_center = _billboard_center * mat;
01354 }
01355 }
01356
01357 if (get_group_type() == GT_instance) {
01358 set_group_type(GT_group);
01359 }
01360
01361 if (get_group_type() != GT_joint) {
01362 internal_clear_transform();
01363 }
01364 }
01365
01366
01367
01368
01369
01370
01371
01372
01373 void EggGroup::
01374 transform_changed() {
01375
01376
01377
01378
01379 update_under(0);
01380 }
01381
01382
01383
01384
01385
01386
01387
01388 ostream &operator << (ostream &out, EggGroup::GroupType t) {
01389 switch (t) {
01390 case EggGroup::GT_invalid:
01391 return out << "invalid group";
01392 case EggGroup::GT_group:
01393 return out << "group";
01394 case EggGroup::GT_instance:
01395 return out << "instance";
01396 case EggGroup::GT_joint:
01397 return out << "joint";
01398 }
01399
01400 nassertr(false, out);
01401 return out << "(**invalid**)";
01402 }
01403
01404
01405
01406
01407
01408 ostream &operator << (ostream &out, EggGroup::DartType t) {
01409 switch (t) {
01410 case EggGroup::DT_none:
01411 return out << "none";
01412 case EggGroup::DT_sync:
01413 return out << "sync";
01414 case EggGroup::DT_nosync:
01415 return out << "nosync";
01416 case EggGroup::DT_structured:
01417 return out << "structured";
01418 case EggGroup::DT_default:
01419 return out << "1";
01420 }
01421
01422 nassertr(false, out);
01423 return out << "(**invalid**)";
01424 }
01425
01426
01427
01428
01429
01430 ostream &operator << (ostream &out, EggGroup::DCSType t) {
01431 switch (t) {
01432 case EggGroup::DC_unspecified:
01433 return out << "unspecified";
01434 case EggGroup::DC_none:
01435 return out << "none";
01436 case EggGroup::DC_local:
01437 return out << "local";
01438 case EggGroup::DC_net:
01439 return out << "net";
01440 case EggGroup::DC_no_touch:
01441 return out << "no_touch";
01442 case EggGroup::DC_default:
01443 return out << "1";
01444 }
01445
01446 nassertr(false, out);
01447 return out << "(**invalid**)";
01448 }
01449
01450
01451
01452
01453
01454 ostream &operator << (ostream &out, EggGroup::BillboardType t) {
01455 switch (t) {
01456 case EggGroup::BT_none:
01457 return out << "none";
01458 case EggGroup::BT_axis:
01459 return out << "axis";
01460 case EggGroup::BT_point_camera_relative:
01461 return out << "point_eye";
01462 case EggGroup::BT_point_world_relative:
01463 return out << "point_world";
01464 }
01465
01466 nassertr(false, out);
01467 return out << "(**invalid**)";
01468 }
01469
01470
01471
01472
01473
01474 ostream &operator << (ostream &out, EggGroup::CollisionSolidType t) {
01475 switch (t) {
01476 case EggGroup::CST_none:
01477 return out << "None";
01478 case EggGroup::CST_plane:
01479 return out << "Plane";
01480 case EggGroup::CST_polygon:
01481 return out << "Polygon";
01482 case EggGroup::CST_polyset:
01483 return out << "Polyset";
01484 case EggGroup::CST_sphere:
01485 return out << "Sphere";
01486 case EggGroup::CST_inv_sphere:
01487 return out << "InvSphere";
01488 case EggGroup::CST_tube:
01489 return out << "Tube";
01490 }
01491
01492 nassertr(false, out);
01493 return out << "(**invalid**)";
01494 }
01495
01496
01497
01498
01499
01500 ostream &operator << (ostream &out, EggGroup::CollideFlags t) {
01501 if (t == EggGroup::CF_none) {
01502 return out << "none";
01503 }
01504 int bits = (int)t;
01505 const char *space = "";
01506
01507 if (bits & EggGroup::CF_intangible) {
01508 out << space << "intangible";
01509 space = " ";
01510 }
01511 if (bits & EggGroup::CF_event) {
01512 out << space << "event";
01513 space = " ";
01514 }
01515 if (bits & EggGroup::CF_descend) {
01516 out << space << "descend";
01517 space = " ";
01518 }
01519 if (bits & EggGroup::CF_keep) {
01520 out << space << "keep";
01521 space = " ";
01522 }
01523 if (bits & EggGroup::CF_solid) {
01524 out << space << "solid";
01525 space = " ";
01526 }
01527 if (bits & EggGroup::CF_center) {
01528 out << space << "center";
01529 space = " ";
01530 }
01531 if (bits & EggGroup::CF_turnstile) {
01532 out << space << "turnstile";
01533 space = " ";
01534 }
01535 if (bits & EggGroup::CF_level) {
01536 out << space << "level";
01537 space = " ";
01538 }
01539 return out;
01540 }
01541
01542
01543
01544
01545
01546 ostream &
01547 operator << (ostream &out, EggGroup::BlendMode t) {
01548 switch (t) {
01549 case EggGroup::BM_unspecified:
01550 return out << "unspecified";
01551
01552 case EggGroup::BM_none:
01553 return out << "none";
01554
01555 case EggGroup::BM_add:
01556 return out << "add";
01557
01558 case EggGroup::BM_subtract:
01559 return out << "subtract";
01560
01561 case EggGroup::BM_inv_subtract:
01562 return out << "inv_subtract";
01563
01564 case EggGroup::BM_min:
01565 return out << "min";
01566
01567 case EggGroup::BM_max:
01568 return out << "max";
01569 }
01570
01571 return out << "**invalid EggGroup::BlendMode(" << (int)t << ")**";
01572 }
01573
01574
01575
01576
01577
01578 ostream &
01579 operator << (ostream &out, EggGroup::BlendOperand t) {
01580 switch (t) {
01581 case EggGroup::BO_unspecified:
01582 return out << "unspecified";
01583
01584 case EggGroup::BO_zero:
01585 return out << "zero";
01586
01587 case EggGroup::BO_one:
01588 return out << "one";
01589
01590 case EggGroup::BO_incoming_color:
01591 return out << "incomfing_color";
01592
01593 case EggGroup::BO_one_minus_incoming_color:
01594 return out << "one_minus_incoming_color";
01595
01596 case EggGroup::BO_fbuffer_color:
01597 return out << "fbuffer_color";
01598
01599 case EggGroup::BO_one_minus_fbuffer_color:
01600 return out << "one_minus_fbuffer_color";
01601
01602 case EggGroup::BO_incoming_alpha:
01603 return out << "incoming_alpha";
01604
01605 case EggGroup::BO_one_minus_incoming_alpha:
01606 return out << "one_minus_incoming_alpha";
01607
01608 case EggGroup::BO_fbuffer_alpha:
01609 return out << "fbuffer_alpha";
01610
01611 case EggGroup::BO_one_minus_fbuffer_alpha:
01612 return out << "one_minus_fbuffer_alpha";
01613
01614 case EggGroup::BO_constant_color:
01615 return out << "constant_color";
01616
01617 case EggGroup::BO_one_minus_constant_color:
01618 return out << "one_minus_constant_color";
01619
01620 case EggGroup::BO_constant_alpha:
01621 return out << "constant_alpha";
01622
01623 case EggGroup::BO_one_minus_constant_alpha:
01624 return out << "one_minus_constant_alpha";
01625
01626 case EggGroup::BO_incoming_color_saturate:
01627 return out << "incoming_color_saturate";
01628
01629 case EggGroup::BO_color_scale:
01630 return out << "color_scale";
01631
01632 case EggGroup::BO_one_minus_color_scale:
01633 return out << "one_minus_color_scale";
01634
01635 case EggGroup::BO_alpha_scale:
01636 return out << "alpha_scale";
01637
01638 case EggGroup::BO_one_minus_alpha_scale:
01639 return out << "one_minus_alpha_scale";
01640 }
01641
01642 return out << "**invalid EggGroup::BlendOperand(" << (int)t << ")**";
01643 }