00001 // Filename: eggNode.cxx 00002 // Created by: drose (16Jan99) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "eggNode.h" 00016 #include "eggGroupNode.h" 00017 #include "config_egg.h" 00018 #include "eggTextureCollection.h" 00019 #include "dcast.h" 00020 00021 #include <algorithm> 00022 00023 extern int eggyyparse(); 00024 #include "parserDefs.h" 00025 #include "lexerDefs.h" 00026 00027 TypeHandle EggNode::_type_handle; 00028 00029 00030 //////////////////////////////////////////////////////////////////// 00031 // Function: EggNode::rename_node 00032 // Access: Published 00033 // Description: Rename by stripping out the prefix 00034 //////////////////////////////////////////////////////////////////// 00035 int EggNode:: 00036 rename_node(vector_string strip_prefix) { 00037 int num_renamed = 0; 00038 for (unsigned int ni = 0; ni < strip_prefix.size(); ++ni) { 00039 string axe_name = strip_prefix[ni]; 00040 if (this->get_name().substr(0, axe_name.size()) == axe_name) { 00041 string new_name = this->get_name().substr(axe_name.size()); 00042 //cout << "renaming " << this->get_name() << "->" << new_name << endl; 00043 this->set_name(new_name); 00044 num_renamed += 1; 00045 } 00046 } 00047 return num_renamed; 00048 } 00049 00050 //////////////////////////////////////////////////////////////////// 00051 // Function: EggNode::apply_texmats 00052 // Access: Public 00053 // Description: Applies the texture matrices to the UV's of the 00054 // vertices that reference them, and then removes the 00055 // texture matrices from the textures themselves. 00056 //////////////////////////////////////////////////////////////////// 00057 void EggNode:: 00058 apply_texmats() { 00059 EggTextureCollection textures; 00060 textures.find_used_textures(this); 00061 r_apply_texmats(textures); 00062 } 00063 00064 //////////////////////////////////////////////////////////////////// 00065 // Function: EggNode::is_joint 00066 // Access: Public, Virtual 00067 // Description: Returns true if this particular node represents a 00068 // <Joint> entry or not. This is a handy thing to know 00069 // since Joints are sorted to the end of their sibling 00070 // list when writing an egg file. See 00071 // EggGroupNode::write(). 00072 //////////////////////////////////////////////////////////////////// 00073 bool EggNode:: 00074 is_joint() const { 00075 return false; 00076 } 00077 00078 //////////////////////////////////////////////////////////////////// 00079 // Function: EggNode::is_anim_matrix 00080 // Access: Public, Virtual 00081 // Description: Returns true if this node represents a table of 00082 // animation transformation data, false otherwise. 00083 //////////////////////////////////////////////////////////////////// 00084 bool EggNode:: 00085 is_anim_matrix() const { 00086 return false; 00087 } 00088 00089 //////////////////////////////////////////////////////////////////// 00090 // Function: EggNode::determine_alpha_mode 00091 // Access: Public, Virtual 00092 // Description: Walks back up the hierarchy, looking for an EggGroup 00093 // or EggPrimitive or some such object at this level or 00094 // above this node that has an alpha_mode other than 00095 // AM_unspecified. Returns a valid EggRenderMode pointer 00096 // if one is found, or NULL otherwise. 00097 //////////////////////////////////////////////////////////////////// 00098 EggRenderMode *EggNode:: 00099 determine_alpha_mode() { 00100 if (_parent == (EggGroupNode *)NULL) { 00101 // Too bad; we're done. 00102 return (EggRenderMode *)NULL; 00103 } 00104 return _parent->determine_alpha_mode(); 00105 } 00106 00107 //////////////////////////////////////////////////////////////////// 00108 // Function: EggNode::determine_depth_write_mode 00109 // Access: Public, Virtual 00110 // Description: Walks back up the hierarchy, looking for an EggGroup 00111 // or EggPrimitive or some such object at this level or 00112 // above this node that has a depth_write_mode other than 00113 // DWM_unspecified. Returns a valid EggRenderMode pointer 00114 // if one is found, or NULL otherwise. 00115 //////////////////////////////////////////////////////////////////// 00116 EggRenderMode *EggNode:: 00117 determine_depth_write_mode() { 00118 if (_parent == (EggGroupNode *)NULL) { 00119 // Too bad; we're done. 00120 return (EggRenderMode *)NULL; 00121 } 00122 return _parent->determine_depth_write_mode(); 00123 } 00124 00125 //////////////////////////////////////////////////////////////////// 00126 // Function: EggNode::determine_depth_test_mode 00127 // Access: Public, Virtual 00128 // Description: Walks back up the hierarchy, looking for an EggGroup 00129 // or EggPrimitive or some such object at this level or 00130 // above this node that has a depth_test_mode other than 00131 // DTM_unspecified. Returns a valid EggRenderMode pointer 00132 // if one is found, or NULL otherwise. 00133 //////////////////////////////////////////////////////////////////// 00134 EggRenderMode *EggNode:: 00135 determine_depth_test_mode() { 00136 if (_parent == (EggGroupNode *)NULL) { 00137 // Too bad; we're done. 00138 return (EggRenderMode *)NULL; 00139 } 00140 return _parent->determine_depth_test_mode(); 00141 } 00142 00143 //////////////////////////////////////////////////////////////////// 00144 // Function: EggNode::determine_visibility_mode 00145 // Access: Public, Virtual 00146 // Description: Walks back up the hierarchy, looking for an EggGroup 00147 // or EggPrimitive or some such object at this level or 00148 // above this node that has a visibility_mode other than 00149 // VM_unspecified. Returns a valid EggRenderMode pointer 00150 // if one is found, or NULL otherwise. 00151 //////////////////////////////////////////////////////////////////// 00152 EggRenderMode *EggNode:: 00153 determine_visibility_mode() { 00154 if (_parent == (EggGroupNode *)NULL) { 00155 // Too bad; we're done. 00156 return (EggRenderMode *)NULL; 00157 } 00158 return _parent->determine_visibility_mode(); 00159 } 00160 00161 //////////////////////////////////////////////////////////////////// 00162 // Function: EggNode::determine_depth_offset 00163 // Access: Public, Virtual 00164 // Description: Walks back up the hierarchy, looking for an EggGroup 00165 // or EggPrimitive or some such object at this level or 00166 // above this node that has a depth_offset specified. 00167 // Returns a valid EggRenderMode pointer if one is found, 00168 // or NULL otherwise. 00169 //////////////////////////////////////////////////////////////////// 00170 EggRenderMode *EggNode:: 00171 determine_depth_offset() { 00172 if (_parent == (EggGroupNode *)NULL) { 00173 // Too bad; we're done. 00174 return (EggRenderMode *)NULL; 00175 } 00176 return _parent->determine_depth_offset(); 00177 } 00178 00179 //////////////////////////////////////////////////////////////////// 00180 // Function: EggNode::determine_draw_order 00181 // Access: Public, Virtual 00182 // Description: Walks back up the hierarchy, looking for an EggGroup 00183 // or EggPrimitive or some such object at this level or 00184 // above this node that has a draw_order specified. 00185 // Returns a valid EggRenderMode pointer if one is found, 00186 // or NULL otherwise. 00187 //////////////////////////////////////////////////////////////////// 00188 EggRenderMode *EggNode:: 00189 determine_draw_order() { 00190 if (_parent == (EggGroupNode *)NULL) { 00191 // Too bad; we're done. 00192 return (EggRenderMode *)NULL; 00193 } 00194 return _parent->determine_draw_order(); 00195 } 00196 00197 //////////////////////////////////////////////////////////////////// 00198 // Function: EggNode::determine_bin 00199 // Access: Public, Virtual 00200 // Description: Walks back up the hierarchy, looking for an EggGroup 00201 // or EggPrimitive or some such object at this level or 00202 // above this node that has a bin specified. Returns a 00203 // valid EggRenderMode pointer if one is found, or NULL 00204 // otherwise. 00205 //////////////////////////////////////////////////////////////////// 00206 EggRenderMode *EggNode:: 00207 determine_bin() { 00208 if (_parent == (EggGroupNode *)NULL) { 00209 // Too bad; we're done. 00210 return (EggRenderMode *)NULL; 00211 } 00212 return _parent->determine_bin(); 00213 } 00214 00215 //////////////////////////////////////////////////////////////////// 00216 // Function: EggNode::determine_indexed 00217 // Access: Public, Virtual 00218 // Description: Walks back up the hierarchy, looking for an EggGroup 00219 // at this level or above that has the "indexed" scalar 00220 // set. Returns the value of the indexed scalar if it 00221 // is found, or false if it is not. 00222 // 00223 // In other words, returns true if the "indexed" flag is 00224 // in effect for the indicated node, false otherwise. 00225 //////////////////////////////////////////////////////////////////// 00226 bool EggNode:: 00227 determine_indexed() { 00228 if (_parent == (EggGroupNode *)NULL) { 00229 // Too bad; we're done. 00230 return false; 00231 } 00232 return _parent->determine_indexed(); 00233 } 00234 00235 //////////////////////////////////////////////////////////////////// 00236 // Function: EggNode::determine_decal 00237 // Access: Public, Virtual 00238 // Description: Walks back up the hierarchy, looking for an EggGroup 00239 // at this level or above that has the "decal" flag 00240 // set. Returns the value of the decal flag if it 00241 // is found, or false if it is not. 00242 // 00243 // In other words, returns true if the "decal" flag is 00244 // in effect for the indicated node, false otherwise. 00245 //////////////////////////////////////////////////////////////////// 00246 bool EggNode:: 00247 determine_decal() { 00248 if (_parent == (EggGroupNode *)NULL) { 00249 // Too bad; we're done. 00250 return false; 00251 } 00252 return _parent->determine_decal(); 00253 } 00254 00255 00256 //////////////////////////////////////////////////////////////////// 00257 // Function: EggNode::parse_egg 00258 // Access: Public 00259 // Description: Parses the egg syntax given in the indicate string as 00260 // if it had been read from the egg file within this 00261 // object's definition. Updates the object accordingly. 00262 // Returns true if successful, false if there was some 00263 // parse error or if the object does not support this 00264 // functionality. 00265 //////////////////////////////////////////////////////////////////// 00266 bool EggNode:: 00267 parse_egg(const string &egg_syntax) { 00268 EggGroupNode *group = get_parent(); 00269 if (is_of_type(EggGroupNode::get_class_type())) { 00270 DCAST_INTO_R(group, this, false); 00271 } 00272 00273 istringstream in(egg_syntax); 00274 00275 LightMutexHolder holder(egg_lock); 00276 00277 egg_init_parser(in, "", this, group); 00278 00279 if (!egg_start_parse_body()) { 00280 egg_cleanup_parser(); 00281 return false; 00282 } 00283 00284 eggyyparse(); 00285 egg_cleanup_parser(); 00286 00287 return (egg_error_count() == 0); 00288 } 00289 00290 #ifdef _DEBUG 00291 00292 //////////////////////////////////////////////////////////////////// 00293 // Function: EggNode::test_under_integrity 00294 // Access: Public 00295 // Description: Recursively checks the integrity of the _under_flags, 00296 // _parent, and _depth members of this node and all of 00297 // its ancestors. 00298 //////////////////////////////////////////////////////////////////// 00299 void EggNode:: 00300 test_under_integrity() const { 00301 if (_parent == NULL) { 00302 // If we have no parent, everything should be zero. 00303 nassertv(_depth == 0); 00304 nassertv(_under_flags == 0); 00305 } else { 00306 // Otherwise, make sure we're consistent with our parent. 00307 _parent->test_ref_count_integrity(); 00308 00309 nassertv(_depth == _parent->_depth + 1); 00310 00311 // We can't perform too much checking on the under_flags, since we 00312 // don't know which bits should have been added for this node. 00313 // We'll verify that at least we didn't accidentally take some 00314 // bits away. 00315 nassertv((_under_flags & _parent->_under_flags) == _parent->_under_flags); 00316 00317 // Make sure we're mentioned in our parent's children list. 00318 EggGroupNode::iterator ci; 00319 ci = find(_parent->begin(), _parent->end(), this); 00320 nassertv(ci != _parent->end()); 00321 00322 // Now recurse up our parent. 00323 _parent->test_under_integrity(); 00324 } 00325 } 00326 00327 #endif // _DEBUG 00328 00329 00330 //////////////////////////////////////////////////////////////////// 00331 // Function: EggNode::egg_start_parse_body 00332 // Access: Protected, Virtual 00333 // Description: This function is called within parse_egg(). It 00334 // should call the appropriate function on the lexer to 00335 // initialize the parser into the state associated with 00336 // this object. If the object cannot be parsed into 00337 // directly, it should return false. 00338 //////////////////////////////////////////////////////////////////// 00339 bool EggNode:: 00340 egg_start_parse_body() { 00341 return false; 00342 } 00343 00344 //////////////////////////////////////////////////////////////////// 00345 // Function: EggNode::update_under 00346 // Access: Protected, Virtual 00347 // Description: This function is called from within EggGroupNode 00348 // whenever the parentage of the node has changed. It 00349 // should update the depth and under_instance flags 00350 // accordingly. 00351 // 00352 // depth_offset is the difference between the old depth 00353 // value and the new value. It should be consistent 00354 // with the supplied depth value. If it is not, we have 00355 // some error. 00356 //////////////////////////////////////////////////////////////////// 00357 void EggNode:: 00358 update_under(int depth_offset) { 00359 int depth; 00360 if (_parent == NULL) { 00361 depth = 0; 00362 _under_flags = 0; 00363 _vertex_frame = NULL; 00364 _node_frame = NULL; 00365 _vertex_frame_inv = NULL; 00366 _node_frame_inv = NULL; 00367 _vertex_to_node = NULL; 00368 _node_to_vertex = NULL; 00369 } else { 00370 _parent->test_ref_count_integrity(); 00371 depth = _parent->_depth + 1; 00372 _under_flags = _parent->_under_flags; 00373 _vertex_frame = _parent->_vertex_frame; 00374 _node_frame = _parent->_node_frame; 00375 _vertex_frame_inv = _parent->_vertex_frame_inv; 00376 _node_frame_inv = _parent->_node_frame_inv; 00377 _vertex_to_node = _parent->_vertex_to_node; 00378 _node_to_vertex = _parent->_node_to_vertex; 00379 } 00380 00381 if (depth - _depth != depth_offset) { 00382 egg_cat.error() << "Cycle in egg graph or invalid egg pointer!\n"; 00383 return; 00384 } 00385 _depth = depth; 00386 00387 adjust_under(); 00388 } 00389 00390 //////////////////////////////////////////////////////////////////// 00391 // Function: EggNode::adjust_under 00392 // Access: Protected, Virtual 00393 // Description: This is called within update_under() after all the 00394 // various under settings have been inherited directly 00395 // from the parent node. It is responsible for 00396 // adjusting these settings to reflect states local to 00397 // the current node; for instance, an <Instance> node 00398 // will force the UF_under_instance bit on. 00399 //////////////////////////////////////////////////////////////////// 00400 void EggNode:: 00401 adjust_under() { 00402 } 00403 00404 //////////////////////////////////////////////////////////////////// 00405 // Function: EggNode::has_primitives 00406 // Access: Protected, Virtual 00407 // Description: Returns true if there are any primitives 00408 // (e.g. polygons) defined within this group or below, 00409 // false otherwise. 00410 //////////////////////////////////////////////////////////////////// 00411 bool EggNode:: 00412 has_primitives() const { 00413 return false; 00414 } 00415 00416 //////////////////////////////////////////////////////////////////// 00417 // Function: EggNode::joint_has_primitives 00418 // Access: Protected, Virtual 00419 // Description: Returns true if there are any primitives 00420 // (e.g. polygons) defined within this group or below, 00421 // but the search does not include nested joints. 00422 //////////////////////////////////////////////////////////////////// 00423 bool EggNode:: 00424 joint_has_primitives() const { 00425 return false; 00426 } 00427 00428 //////////////////////////////////////////////////////////////////// 00429 // Function: EggNode::has_normals 00430 // Access: Published, Virtual 00431 // Description: Returns true if any of the primitives (e.g. polygons) 00432 // defined within this group or below have either face 00433 // or vertex normals defined, false otherwise. 00434 //////////////////////////////////////////////////////////////////// 00435 bool EggNode:: 00436 has_normals() const { 00437 return false; 00438 } 00439 00440 00441 //////////////////////////////////////////////////////////////////// 00442 // Function: EggNode::r_transform 00443 // Access: Protected, Virtual 00444 // Description: This is called from within the egg code by 00445 // transform(). It applies a transformation matrix 00446 // to the current node in some sensible way, then 00447 // continues down the tree. 00448 // 00449 // The first matrix is the transformation to apply; the 00450 // second is its inverse. The third parameter is the 00451 // coordinate system we are changing to, or CS_default 00452 // if we are not changing coordinate systems. 00453 //////////////////////////////////////////////////////////////////// 00454 void EggNode:: 00455 r_transform(const LMatrix4d &, const LMatrix4d &, CoordinateSystem) { 00456 } 00457 00458 //////////////////////////////////////////////////////////////////// 00459 // Function: EggNode::r_transform_vertices 00460 // Access: Protected, Virtual 00461 // Description: This is called from within the egg code by 00462 // transform_vertices_only()(). It applies a 00463 // transformation matrix to the current node in some 00464 // sensible way (if the current node is a vertex pool 00465 // with vertices), then continues down the tree. 00466 //////////////////////////////////////////////////////////////////// 00467 void EggNode:: 00468 r_transform_vertices(const LMatrix4d &) { 00469 } 00470 00471 //////////////////////////////////////////////////////////////////// 00472 // Function: EggNode::r_mark_coordsys 00473 // Access: Protected, Virtual 00474 // Description: This is only called immediately after loading an egg 00475 // file from disk, to propagate the value found in the 00476 // CoordinateSystem entry (or the default Y-up 00477 // coordinate system) to all nodes that care about what 00478 // the coordinate system is. 00479 //////////////////////////////////////////////////////////////////// 00480 void EggNode:: 00481 r_mark_coordsys(CoordinateSystem) { 00482 } 00483 00484 //////////////////////////////////////////////////////////////////// 00485 // Function: EggNode::r_flatten_transforms 00486 // Access: Protected, Virtual 00487 // Description: The recursive implementation of flatten_transforms(). 00488 //////////////////////////////////////////////////////////////////// 00489 void EggNode:: 00490 r_flatten_transforms() { 00491 } 00492 00493 //////////////////////////////////////////////////////////////////// 00494 // Function: EggNode::r_apply_texmats 00495 // Access: Protected, Virtual 00496 // Description: The recursive implementation of apply_texmats(). 00497 //////////////////////////////////////////////////////////////////// 00498 void EggNode:: 00499 r_apply_texmats(EggTextureCollection &textures) { 00500 }