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 }
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
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
A base class for nodes in the hierarchy that are not leaf nodes.
Definition: eggGroupNode.h:46
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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
bool test_ref_count_integrity() const
Does some easy checks to make sure that the reference count isn't completely bogus.
This is a collection of textures by TRef name.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
This class stores miscellaneous rendering properties that is associated with geometry,...
Definition: eggRenderMode.h:31
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
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
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:74
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
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
virtual bool is_joint() const
Returns true if this particular node represents a <Joint> entry or not.
Definition: eggNode.cxx:65
int find_used_textures(EggNode *node)
Walks the egg hierarchy beginning at the indicated node, looking for textures that are referenced by ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
int rename_node(vector_string strip_prefix)
Rename by stripping out the prefix.
Definition: eggNode.cxx:34
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:28
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.