Panda3D
eggNode.cxx
1 // Filename: eggNode.cxx
2 // Created by: drose (16Jan99)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "eggNode.h"
16 #include "eggGroupNode.h"
17 #include "lightMutexHolder.h"
18 #include "config_egg.h"
19 #include "eggTextureCollection.h"
20 #include "dcast.h"
21 
22 #include <algorithm>
23 
24 extern int eggyyparse();
25 #include "parserDefs.h"
26 #include "lexerDefs.h"
27 
28 TypeHandle EggNode::_type_handle;
29 
30 
31 ////////////////////////////////////////////////////////////////////
32 // Function: EggNode::rename_node
33 // Access: Published
34 // Description: Rename by stripping out the prefix
35 ////////////////////////////////////////////////////////////////////
36 int EggNode::
37 rename_node(vector_string strip_prefix) {
38  int num_renamed = 0;
39  for (unsigned int ni = 0; ni < strip_prefix.size(); ++ni) {
40  string axe_name = strip_prefix[ni];
41  if (this->get_name().substr(0, axe_name.size()) == axe_name) {
42  string new_name = this->get_name().substr(axe_name.size());
43  //cout << "renaming " << this->get_name() << "->" << new_name << endl;
44  this->set_name(new_name);
45  num_renamed += 1;
46  }
47  }
48  return num_renamed;
49 }
50 
51 ////////////////////////////////////////////////////////////////////
52 // Function: EggNode::apply_texmats
53 // Access: Public
54 // Description: Applies the texture matrices to the UV's of the
55 // vertices that reference them, and then removes the
56 // texture matrices from the textures themselves.
57 ////////////////////////////////////////////////////////////////////
58 void EggNode::
60  EggTextureCollection textures;
61  textures.find_used_textures(this);
62  r_apply_texmats(textures);
63 }
64 
65 ////////////////////////////////////////////////////////////////////
66 // Function: EggNode::is_joint
67 // Access: Public, Virtual
68 // Description: Returns true if this particular node represents a
69 // <Joint> entry or not. This is a handy thing to know
70 // since Joints are sorted to the end of their sibling
71 // list when writing an egg file. See
72 // EggGroupNode::write().
73 ////////////////////////////////////////////////////////////////////
74 bool EggNode::
75 is_joint() const {
76  return false;
77 }
78 
79 ////////////////////////////////////////////////////////////////////
80 // Function: EggNode::is_anim_matrix
81 // Access: Public, Virtual
82 // Description: Returns true if this node represents a table of
83 // animation transformation data, false otherwise.
84 ////////////////////////////////////////////////////////////////////
85 bool EggNode::
86 is_anim_matrix() const {
87  return false;
88 }
89 
90 ////////////////////////////////////////////////////////////////////
91 // Function: EggNode::determine_alpha_mode
92 // Access: Public, Virtual
93 // Description: Walks back up the hierarchy, looking for an EggGroup
94 // or EggPrimitive or some such object at this level or
95 // above this node that has an alpha_mode other than
96 // AM_unspecified. Returns a valid EggRenderMode pointer
97 // if one is found, or NULL otherwise.
98 ////////////////////////////////////////////////////////////////////
101  if (_parent == (EggGroupNode *)NULL) {
102  // Too bad; we're done.
103  return (EggRenderMode *)NULL;
104  }
105  return _parent->determine_alpha_mode();
106 }
107 
108 ////////////////////////////////////////////////////////////////////
109 // Function: EggNode::determine_depth_write_mode
110 // Access: Public, Virtual
111 // Description: Walks back up the hierarchy, looking for an EggGroup
112 // or EggPrimitive or some such object at this level or
113 // above this node that has a depth_write_mode other than
114 // DWM_unspecified. Returns a valid EggRenderMode pointer
115 // if one is found, or NULL otherwise.
116 ////////////////////////////////////////////////////////////////////
119  if (_parent == (EggGroupNode *)NULL) {
120  // Too bad; we're done.
121  return (EggRenderMode *)NULL;
122  }
123  return _parent->determine_depth_write_mode();
124 }
125 
126 ////////////////////////////////////////////////////////////////////
127 // Function: EggNode::determine_depth_test_mode
128 // Access: Public, Virtual
129 // Description: Walks back up the hierarchy, looking for an EggGroup
130 // or EggPrimitive or some such object at this level or
131 // above this node that has a depth_test_mode other than
132 // DTM_unspecified. Returns a valid EggRenderMode pointer
133 // if one is found, or NULL otherwise.
134 ////////////////////////////////////////////////////////////////////
137  if (_parent == (EggGroupNode *)NULL) {
138  // Too bad; we're done.
139  return (EggRenderMode *)NULL;
140  }
141  return _parent->determine_depth_test_mode();
142 }
143 
144 ////////////////////////////////////////////////////////////////////
145 // Function: EggNode::determine_visibility_mode
146 // Access: Public, Virtual
147 // Description: Walks back up the hierarchy, looking for an EggGroup
148 // or EggPrimitive or some such object at this level or
149 // above this node that has a visibility_mode other than
150 // VM_unspecified. Returns a valid EggRenderMode pointer
151 // if one is found, or NULL otherwise.
152 ////////////////////////////////////////////////////////////////////
155  if (_parent == (EggGroupNode *)NULL) {
156  // Too bad; we're done.
157  return (EggRenderMode *)NULL;
158  }
159  return _parent->determine_visibility_mode();
160 }
161 
162 ////////////////////////////////////////////////////////////////////
163 // Function: EggNode::determine_depth_offset
164 // Access: Public, Virtual
165 // Description: Walks back up the hierarchy, looking for an EggGroup
166 // or EggPrimitive or some such object at this level or
167 // above this node that has a depth_offset specified.
168 // Returns a valid EggRenderMode pointer if one is found,
169 // or NULL otherwise.
170 ////////////////////////////////////////////////////////////////////
173  if (_parent == (EggGroupNode *)NULL) {
174  // Too bad; we're done.
175  return (EggRenderMode *)NULL;
176  }
177  return _parent->determine_depth_offset();
178 }
179 
180 ////////////////////////////////////////////////////////////////////
181 // Function: EggNode::determine_draw_order
182 // Access: Public, Virtual
183 // Description: Walks back up the hierarchy, looking for an EggGroup
184 // or EggPrimitive or some such object at this level or
185 // above this node that has a draw_order specified.
186 // Returns a valid EggRenderMode pointer if one is found,
187 // or NULL otherwise.
188 ////////////////////////////////////////////////////////////////////
191  if (_parent == (EggGroupNode *)NULL) {
192  // Too bad; we're done.
193  return (EggRenderMode *)NULL;
194  }
195  return _parent->determine_draw_order();
196 }
197 
198 ////////////////////////////////////////////////////////////////////
199 // Function: EggNode::determine_bin
200 // Access: Public, Virtual
201 // Description: Walks back up the hierarchy, looking for an EggGroup
202 // or EggPrimitive or some such object at this level or
203 // above this node that has a bin specified. Returns a
204 // valid EggRenderMode pointer if one is found, or NULL
205 // otherwise.
206 ////////////////////////////////////////////////////////////////////
209  if (_parent == (EggGroupNode *)NULL) {
210  // Too bad; we're done.
211  return (EggRenderMode *)NULL;
212  }
213  return _parent->determine_bin();
214 }
215 
216 ////////////////////////////////////////////////////////////////////
217 // Function: EggNode::determine_indexed
218 // Access: Public, Virtual
219 // Description: Walks back up the hierarchy, looking for an EggGroup
220 // at this level or above that has the "indexed" scalar
221 // set. Returns the value of the indexed scalar if it
222 // is found, or false if it is not.
223 //
224 // In other words, returns true if the "indexed" flag is
225 // in effect for the indicated node, false otherwise.
226 ////////////////////////////////////////////////////////////////////
227 bool EggNode::
229  if (_parent == (EggGroupNode *)NULL) {
230  // Too bad; we're done.
231  return false;
232  }
233  return _parent->determine_indexed();
234 }
235 
236 ////////////////////////////////////////////////////////////////////
237 // Function: EggNode::determine_decal
238 // Access: Public, Virtual
239 // Description: Walks back up the hierarchy, looking for an EggGroup
240 // at this level or above that has the "decal" flag
241 // set. Returns the value of the decal flag if it
242 // is found, or false if it is not.
243 //
244 // In other words, returns true if the "decal" flag is
245 // in effect for the indicated node, false otherwise.
246 ////////////////////////////////////////////////////////////////////
247 bool EggNode::
249  if (_parent == (EggGroupNode *)NULL) {
250  // Too bad; we're done.
251  return false;
252  }
253  return _parent->determine_decal();
254 }
255 
256 
257 ////////////////////////////////////////////////////////////////////
258 // Function: EggNode::parse_egg
259 // Access: Public
260 // Description: Parses the egg syntax given in the indicate string as
261 // if it had been read from the egg file within this
262 // object's definition. Updates the object accordingly.
263 // Returns true if successful, false if there was some
264 // parse error or if the object does not support this
265 // functionality.
266 ////////////////////////////////////////////////////////////////////
267 bool EggNode::
268 parse_egg(const string &egg_syntax) {
269  EggGroupNode *group = get_parent();
270  if (is_of_type(EggGroupNode::get_class_type())) {
271  DCAST_INTO_R(group, this, false);
272  }
273 
274  istringstream in(egg_syntax);
275 
276  LightMutexHolder holder(egg_lock);
277 
278  egg_init_parser(in, "", this, group);
279 
280  if (!egg_start_parse_body()) {
281  egg_cleanup_parser();
282  return false;
283  }
284 
285  eggyyparse();
286  egg_cleanup_parser();
287 
288  return (egg_error_count() == 0);
289 }
290 
291 #ifdef _DEBUG
292 
293 ////////////////////////////////////////////////////////////////////
294 // Function: EggNode::test_under_integrity
295 // Access: Public
296 // Description: Recursively checks the integrity of the _under_flags,
297 // _parent, and _depth members of this node and all of
298 // its ancestors.
299 ////////////////////////////////////////////////////////////////////
300 void EggNode::
301 test_under_integrity() const {
302  if (_parent == NULL) {
303  // If we have no parent, everything should be zero.
304  nassertv(_depth == 0);
305  nassertv(_under_flags == 0);
306  } else {
307  // Otherwise, make sure we're consistent with our parent.
308  _parent->test_ref_count_integrity();
309 
310  nassertv(_depth == _parent->_depth + 1);
311 
312  // We can't perform too much checking on the under_flags, since we
313  // don't know which bits should have been added for this node.
314  // We'll verify that at least we didn't accidentally take some
315  // bits away.
316  nassertv((_under_flags & _parent->_under_flags) == _parent->_under_flags);
317 
318  // Make sure we're mentioned in our parent's children list.
319  EggGroupNode::iterator ci;
320  ci = find(_parent->begin(), _parent->end(), this);
321  nassertv(ci != _parent->end());
322 
323  // Now recurse up our parent.
324  _parent->test_under_integrity();
325  }
326 }
327 
328 #endif // _DEBUG
329 
330 
331 ////////////////////////////////////////////////////////////////////
332 // Function: EggNode::egg_start_parse_body
333 // Access: Protected, Virtual
334 // Description: This function is called within parse_egg(). It
335 // should call the appropriate function on the lexer to
336 // initialize the parser into the state associated with
337 // this object. If the object cannot be parsed into
338 // directly, it should return false.
339 ////////////////////////////////////////////////////////////////////
340 bool EggNode::
341 egg_start_parse_body() {
342  return false;
343 }
344 
345 ////////////////////////////////////////////////////////////////////
346 // Function: EggNode::update_under
347 // Access: Protected, Virtual
348 // Description: This function is called from within EggGroupNode
349 // whenever the parentage of the node has changed. It
350 // should update the depth and under_instance flags
351 // accordingly.
352 //
353 // depth_offset is the difference between the old depth
354 // value and the new value. It should be consistent
355 // with the supplied depth value. If it is not, we have
356 // some error.
357 ////////////////////////////////////////////////////////////////////
358 void EggNode::
359 update_under(int depth_offset) {
360  int depth;
361  if (_parent == NULL) {
362  depth = 0;
363  _under_flags = 0;
364  _vertex_frame = NULL;
365  _node_frame = NULL;
366  _vertex_frame_inv = NULL;
367  _node_frame_inv = NULL;
368  _vertex_to_node = NULL;
369  _node_to_vertex = NULL;
370  } else {
371  _parent->test_ref_count_integrity();
372  depth = _parent->_depth + 1;
373  _under_flags = _parent->_under_flags;
374  _vertex_frame = _parent->_vertex_frame;
375  _node_frame = _parent->_node_frame;
376  _vertex_frame_inv = _parent->_vertex_frame_inv;
377  _node_frame_inv = _parent->_node_frame_inv;
378  _vertex_to_node = _parent->_vertex_to_node;
379  _node_to_vertex = _parent->_node_to_vertex;
380  }
381 
382  if (depth - _depth != depth_offset) {
383  egg_cat.error() << "Cycle in egg graph or invalid egg pointer!\n";
384  return;
385  }
386  _depth = depth;
387 
388  adjust_under();
389 }
390 
391 ////////////////////////////////////////////////////////////////////
392 // Function: EggNode::adjust_under
393 // Access: Protected, Virtual
394 // Description: This is called within update_under() after all the
395 // various under settings have been inherited directly
396 // from the parent node. It is responsible for
397 // adjusting these settings to reflect states local to
398 // the current node; for instance, an <Instance> node
399 // will force the UF_under_instance bit on.
400 ////////////////////////////////////////////////////////////////////
401 void EggNode::
402 adjust_under() {
403 }
404 
405 ////////////////////////////////////////////////////////////////////
406 // Function: EggNode::has_primitives
407 // Access: Protected, Virtual
408 // Description: Returns true if there are any primitives
409 // (e.g. polygons) defined within this group or below,
410 // false otherwise.
411 ////////////////////////////////////////////////////////////////////
412 bool EggNode::
413 has_primitives() const {
414  return false;
415 }
416 
417 ////////////////////////////////////////////////////////////////////
418 // Function: EggNode::joint_has_primitives
419 // Access: Protected, Virtual
420 // Description: Returns true if there are any primitives
421 // (e.g. polygons) defined within this group or below,
422 // but the search does not include nested joints.
423 ////////////////////////////////////////////////////////////////////
424 bool EggNode::
425 joint_has_primitives() const {
426  return false;
427 }
428 
429 ////////////////////////////////////////////////////////////////////
430 // Function: EggNode::has_normals
431 // Access: Published, Virtual
432 // Description: Returns true if any of the primitives (e.g. polygons)
433 // defined within this group or below have either face
434 // or vertex normals defined, false otherwise.
435 ////////////////////////////////////////////////////////////////////
436 bool EggNode::
437 has_normals() const {
438  return false;
439 }
440 
441 
442 ////////////////////////////////////////////////////////////////////
443 // Function: EggNode::r_transform
444 // Access: Protected, Virtual
445 // Description: This is called from within the egg code by
446 // transform(). It applies a transformation matrix
447 // to the current node in some sensible way, then
448 // continues down the tree.
449 //
450 // The first matrix is the transformation to apply; the
451 // second is its inverse. The third parameter is the
452 // coordinate system we are changing to, or CS_default
453 // if we are not changing coordinate systems.
454 ////////////////////////////////////////////////////////////////////
455 void EggNode::
456 r_transform(const LMatrix4d &, const LMatrix4d &, CoordinateSystem) {
457 }
458 
459 ////////////////////////////////////////////////////////////////////
460 // Function: EggNode::r_transform_vertices
461 // Access: Protected, Virtual
462 // Description: This is called from within the egg code by
463 // transform_vertices_only()(). It applies a
464 // transformation matrix to the current node in some
465 // sensible way (if the current node is a vertex pool
466 // with vertices), then continues down the tree.
467 ////////////////////////////////////////////////////////////////////
468 void EggNode::
469 r_transform_vertices(const LMatrix4d &) {
470 }
471 
472 ////////////////////////////////////////////////////////////////////
473 // Function: EggNode::r_mark_coordsys
474 // Access: Protected, Virtual
475 // Description: This is only called immediately after loading an egg
476 // file from disk, to propagate the value found in the
477 // CoordinateSystem entry (or the default Y-up
478 // coordinate system) to all nodes that care about what
479 // the coordinate system is.
480 ////////////////////////////////////////////////////////////////////
481 void EggNode::
482 r_mark_coordsys(CoordinateSystem) {
483 }
484 
485 ////////////////////////////////////////////////////////////////////
486 // Function: EggNode::r_flatten_transforms
487 // Access: Protected, Virtual
488 // Description: The recursive implementation of flatten_transforms().
489 ////////////////////////////////////////////////////////////////////
490 void EggNode::
491 r_flatten_transforms() {
492 }
493 
494 ////////////////////////////////////////////////////////////////////
495 // Function: EggNode::r_apply_texmats
496 // Access: Protected, Virtual
497 // Description: The recursive implementation of apply_texmats().
498 ////////////////////////////////////////////////////////////////////
499 void EggNode::
500 r_apply_texmats(EggTextureCollection &textures) {
501 }
virtual bool determine_indexed()
Walks back up the hierarchy, looking for an EggGroup at this level or above that has the "indexed" sc...
Definition: eggNode.cxx:228
bool parse_egg(const string &egg_syntax)
Parses the egg syntax given in the indicate string as if it had been read from the egg file within th...
Definition: eggNode.cxx:268
This is a 4-by-4 transform matrix.
Definition: lmatrix.h:4716
void apply_texmats()
Applies the texture matrices to the UV&#39;s of the vertices that reference them, and then removes the te...
Definition: eggNode.cxx:59
A base class for nodes in the hierarchy that are not leaf nodes.
Definition: eggGroupNode.h:51
virtual EggRenderMode * determine_draw_order()
Walks back up the hierarchy, looking for an EggGroup or EggPrimitive or some such object at this leve...
Definition: eggNode.cxx:190
virtual EggRenderMode * determine_depth_test_mode()
Walks back up the hierarchy, looking for an EggGroup or EggPrimitive or some such object at this leve...
Definition: eggNode.cxx:136
bool test_ref_count_integrity() const
Does some easy checks to make sure that the reference count isn&#39;t completely bogus.
This is a collection of textures by TRef name.
This class stores miscellaneous rendering properties that is associated with geometry, and which may be set on the geometry primitive level, on the group above it, or indirectly via a texture.
Definition: eggRenderMode.h:36
virtual bool determine_decal()
Walks back up the hierarchy, looking for an EggGroup at this level or above that has the "decal" flag...
Definition: eggNode.cxx:248
virtual EggRenderMode * determine_visibility_mode()
Walks back up the hierarchy, looking for an EggGroup or EggPrimitive or some such object at this leve...
Definition: eggNode.cxx:154
Similar to MutexHolder, but for a light mutex.
virtual bool is_anim_matrix() const
Returns true if this node represents a table of animation transformation data, false otherwise...
Definition: eggNode.cxx:86
virtual EggRenderMode * determine_depth_write_mode()
Walks back up the hierarchy, looking for an EggGroup or EggPrimitive or some such object at this leve...
Definition: eggNode.cxx:118
virtual EggRenderMode * determine_alpha_mode()
Walks back up the hierarchy, looking for an EggGroup or EggPrimitive or some such object at this leve...
Definition: eggNode.cxx:100
virtual bool is_joint() const
Returns true if this particular node represents a <Joint> entry or not.
Definition: eggNode.cxx:75
int find_used_textures(EggNode *node)
Walks the egg hierarchy beginning at the indicated node, looking for textures that are referenced by ...
virtual EggRenderMode * determine_bin()
Walks back up the hierarchy, looking for an EggGroup or EggPrimitive or some such object at this leve...
Definition: eggNode.cxx:208
int rename_node(vector_string strip_prefix)
Rename by stripping out the prefix.
Definition: eggNode.cxx:37
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:63
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
virtual EggRenderMode * determine_depth_offset()
Walks back up the hierarchy, looking for an EggGroup or EggPrimitive or some such object at this leve...
Definition: eggNode.cxx:172