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