Panda3D
eggPrimitive.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 eggPrimitive.cxx
10  * @author drose
11  * @date 1999-01-16
12  */
13 
14 #include "eggPrimitive.h"
15 #include "eggVertexPool.h"
16 #include "eggMiscFuncs.h"
17 #include "eggTextureCollection.h"
18 #include "lexerDefs.h"
19 #include "config_egg.h"
20 
21 #include "indent.h"
22 #include "vector_int.h"
23 
24 TypeHandle EggPrimitive::_type_handle;
25 
26 
27 /**
28  * Walks back up the hierarchy, looking for an EggGroup or EggPrimitive or
29  * some such object at this level or above this primitive that has an
30  * alpha_mode other than AM_unspecified. Returns a valid EggRenderMode
31  * pointer if one is found, or NULL otherwise.
32  */
35  if (get_alpha_mode() != AM_unspecified) {
36  return this;
37  }
38 
40  if (result == nullptr) {
41  int num_textures = get_num_textures();
42  for (int i = 0; i < num_textures && result == nullptr; i++) {
43  EggTexture *egg_tex = get_texture(i);
44 
45  // We only want to consider the alpha mode on those textures that can
46  // affect the transparency of the polygon. This mostly depends on the
47  // envtype flag.
48  if (egg_tex->affects_polygon_alpha()) {
49  // This texture might affect the polygon alpha, so it gets to decide
50  // the polygon transparency mode.
51  if (egg_tex->get_alpha_mode() != AM_unspecified) {
52  result = get_texture(i);
53  }
54  }
55  }
56  }
57  return result;
58 }
59 
60 /**
61  * Walks back up the hierarchy, looking for an EggGroup or EggPrimitive or
62  * some such object at this level or above this node that has a
63  * depth_write_mode other than DWM_unspecified. Returns a valid EggRenderMode
64  * pointer if one is found, or NULL otherwise.
65  */
68  if (get_depth_write_mode() != DWM_unspecified) {
69  return this;
70  }
71 
73  if (result == nullptr) {
74  int num_textures = get_num_textures();
75  for (int i = 0; i < num_textures && result == nullptr; i++) {
76  if (get_texture(i)->get_depth_write_mode() != DWM_unspecified) {
77  result = get_texture(i);
78  }
79  }
80  }
81  return result;
82 }
83 
84 /**
85  * Walks back up the hierarchy, looking for an EggGroup or EggPrimitive or
86  * some such object at this level or above this node that has a
87  * depth_test_mode other than DTM_unspecified. Returns a valid EggRenderMode
88  * pointer if one is found, or NULL otherwise.
89  */
92  if (get_depth_test_mode() != DTM_unspecified) {
93  return this;
94  }
95 
97  if (result == nullptr) {
98  int num_textures = get_num_textures();
99  for (int i = 0; i < num_textures && result == nullptr; i++) {
100  if (get_texture(i)->get_depth_test_mode() != DTM_unspecified) {
101  result = get_texture(i);
102  }
103  }
104  }
105  return result;
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  * visibility_mode other than VM_unspecified. Returns a valid EggRenderMode
112  * pointer if one is found, or NULL otherwise.
113  */
116  if (get_visibility_mode() != VM_unspecified) {
117  return this;
118  }
119 
121  if (result == nullptr) {
122  int num_textures = get_num_textures();
123  for (int i = 0; i < num_textures && result == nullptr; i++) {
124  if (get_texture(i)->get_visibility_mode() != VM_unspecified) {
125  result = get_texture(i);
126  }
127  }
128  }
129  return result;
130 }
131 
132 /**
133  * Walks back up the hierarchy, looking for an EggGroup or EggPrimitive or
134  * some such object at this level or above this primitive that has a
135  * depth_offset specified. Returns a valid EggRenderMode pointer if one is
136  * found, or NULL otherwise.
137  */
140  if (has_depth_offset()) {
141  return this;
142  }
143 
145  if (result == nullptr) {
146  int num_textures = get_num_textures();
147  for (int i = 0; i < num_textures && result == nullptr; i++) {
148  if (get_texture(i)->has_depth_offset()) {
149  result = get_texture(i);
150  }
151  }
152  }
153  return result;
154 }
155 
156 /**
157  * Walks back up the hierarchy, looking for an EggGroup or EggPrimitive or
158  * some such object at this level or above this primitive that has a
159  * draw_order specified. Returns a valid EggRenderMode pointer if one is
160  * found, or NULL otherwise.
161  */
164  if (has_draw_order()) {
165  return this;
166  }
167 
169  if (result == nullptr) {
170  int num_textures = get_num_textures();
171  for (int i = 0; i < num_textures && result == nullptr; i++) {
172  if (get_texture(i)->has_draw_order()) {
173  result = get_texture(i);
174  }
175  }
176  }
177  return result;
178 }
179 
180 /**
181  * Walks back up the hierarchy, looking for an EggGroup or EggPrimitive or
182  * some such object at this level or above this primitive that has a bin
183  * specified. Returns a valid EggRenderMode pointer if one is found, or NULL
184  * otherwise.
185  */
187 determine_bin() {
188  if (has_bin()) {
189  return this;
190  }
191 
193  if (result == nullptr) {
194  int num_textures = get_num_textures();
195  for (int i = 0; i < num_textures && result == nullptr; i++) {
196  if (get_texture(i)->has_bin()) {
197  result = get_texture(i);
198  }
199  }
200  }
201  return result;
202 }
203 
204 
205 /**
206  * Returns the shading properties apparent on this particular primitive. This
207  * returns S_per_vertex if the vertices have colors or normals (and they are
208  * not all the same values), or for a simple primitive, S_overall otherwise.
209  * A composite primitive may also return S_per_face if the individual
210  * component primitives have colors or normals that are not all the same
211  * values.
212  *
213  * To get the most accurate results, you should call clear_shading() on all
214  * connected primitives (or on all primitives in the egg file), followed by
215  * get_shading() on each primitive. You may find it easiest to call these
216  * methods on the EggData root node (they are defined on EggGroupNode).
217  */
218 EggPrimitive::Shading EggPrimitive::
219 get_shading() const {
220  if (empty()) {
221  return S_overall;
222  }
223 
224  if (has_vertex_normal()) {
225  // Check if the vertices all have the same normal.
226  const EggAttributes *first_vertex = get_vertex(0);
227  if (!first_vertex->has_normal()) {
228  first_vertex = this;
229  }
230  for (size_t i = 1; i < get_num_vertices(); ++i) {
231  const EggAttributes *vertex = get_vertex(i);
232  if (!vertex->has_normal()) {
233  vertex = this;
234  }
235  if (!vertex->matches_normal(*first_vertex)) {
236  return S_per_vertex;
237  }
238  }
239  }
240 
241  if (has_vertex_color()) {
242  // Check if the vertices all have the same color.
243  const EggAttributes *first_vertex = get_vertex(0);
244  if (!first_vertex->has_color()) {
245  first_vertex = this;
246  }
247  for (size_t i = 1; i < get_num_vertices(); ++i) {
248  const EggAttributes *vertex = get_vertex(i);
249  if (!vertex->has_color()) {
250  vertex = this;
251  }
252  if (!vertex->matches_color(*first_vertex)) {
253  return S_per_vertex;
254  }
255  }
256  }
257 
258  return S_overall;
259 }
260 
261 /**
262  * Copies the rendering attributes from the indicated primitive.
263  */
265 copy_attributes(const EggAttributes &other) {
266  EggAttributes::operator = (other);
267 }
268 
269 /**
270  * Copies the rendering attributes from the indicated primitive.
271  */
273 copy_attributes(const EggPrimitive &other) {
274  EggAttributes::operator = (other);
275  _textures = other._textures;
276  set_material(other.get_material());
278 }
279 
280 /**
281  * Returns true if any vertex on the primitive has a specific normal set,
282  * false otherwise.
283  *
284  * If you call unify_attributes() first, this will also return false even if
285  * all the vertices were set to the same value (since unify_attributes()
286  * removes redundant vertex properties).
287  */
289 has_vertex_normal() const {
290  Vertices::const_iterator vi;
291  for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) {
292  if ((*vi)->has_normal()) {
293  return true;
294  }
295  }
296  return false;
297 }
298 
299 /**
300  * Returns true if any vertex on the primitive has a specific color set, false
301  * otherwise.
302  *
303  * If you call unify_attributes() first, this will also return false even if
304  * all the vertices were set to the same value (since unify_attributes()
305  * removes redundant vertex properties).
306  */
308 has_vertex_color() const {
309  Vertices::const_iterator vi;
310  for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) {
311  if ((*vi)->has_color()) {
312  return true;
313  }
314  }
315  return false;
316 }
317 
318 /**
319  * If the shading property is S_per_vertex, ensures that all vertices have a
320  * normal and a color, and the overall primitive does not.
321  *
322  * If the shading property is S_per_face, and this is a composite primitive,
323  * ensures that all components have a normal and a color, and the vertices and
324  * overall primitive do not. (If this is a simple primitive, S_per_face works
325  * the same as S_overall, below).
326  *
327  * If the shading property is S_overall, ensures that no vertices or
328  * components have a normal or a color, and the overall primitive does (if any
329  * exists at all).
330  *
331  * After this call, either the primitive will have normals or its vertices
332  * will, but not both. Ditto for colors.
333  *
334  * This may create redundant vertices in the vertex pool.
335  */
337 unify_attributes(EggPrimitive::Shading shading) {
338  if (shading == S_unknown) {
339  shading = get_shading();
340  }
341 
342  // Does the primitive have an explicit color?
343  if (!has_color() && shading != S_overall) {
344  if (shading != S_per_vertex) {
345  // If there is no color set, first we check the vertices. If the
346  // vertices have a color, we inherit the color from there.
347  iterator pi;
348  for (pi = begin(); pi != end() && !has_color(); ++pi) {
349  EggVertex *vertex = (*pi);
350  if (vertex->has_color()) {
351  set_color(vertex->get_color());
352  }
353  }
354  }
355  if (!has_color()) {
356  // If we still don't have a color, the implicit color is white.
357  set_color(LColor(1.0f, 1.0f, 1.0f, 1.0f));
358  }
359  }
360 
361  switch (shading) {
362  case S_per_vertex:
363  // Propagate everything to the vertices.
364  {
365  iterator pi;
366  for (pi = begin(); pi != end(); ++pi) {
367  EggVertex *orig_vertex = (*pi);
368  PT(EggVertex) vertex = new EggVertex(*orig_vertex);
369  if (!vertex->has_normal() && has_normal()) {
370  vertex->copy_normal(*this);
371  }
372  if (!vertex->has_color() && has_color()) {
373  vertex->copy_color(*this);
374  }
375 
376  EggVertexPool *vertex_pool = orig_vertex->get_pool();
377  nassertv(vertex_pool != nullptr);
378  vertex = vertex_pool->create_unique_vertex(*vertex);
379  vertex->copy_grefs_from(*orig_vertex);
380  replace(pi, vertex);
381  }
382  clear_normal();
383  clear_color();
384  }
385  break;
386 
387  case S_per_face:
388  case S_overall:
389  // Remove everything from the vertices.
390  {
391  iterator pi;
392  for (pi = begin(); pi != end(); ++pi) {
393  EggVertex *orig_vertex = (*pi);
394  PT(EggVertex) vertex = new EggVertex(*orig_vertex);
395  if (vertex->has_normal()) {
396  if (!has_normal()) {
397  copy_normal(*vertex);
398  }
399  vertex->clear_normal();
400  }
401  if (vertex->has_color()) {
402  if (!has_color()) {
403  copy_color(*vertex);
404  }
405  vertex->clear_color();
406  }
407 
408  EggVertexPool *vertex_pool = orig_vertex->get_pool();
409  nassertv(vertex_pool != nullptr);
410  vertex = vertex_pool->create_unique_vertex(*vertex);
411  vertex->copy_grefs_from(*orig_vertex);
412  replace(pi, vertex);
413  }
414  }
415  break;
416 
417  case S_unknown:
418  break;
419  }
420 
421  if (!has_color() && shading == S_overall) {
422  set_color(LColor(1.0f, 1.0f, 1.0f, 1.0f));
423  }
424 }
425 
426 /**
427  * Sets the last vertex of the triangle (or each component) to the primitive
428  * normal and/or color, if the primitive is flat-shaded. This reflects the
429  * OpenGL convention of storing flat-shaded properties on the last vertex,
430  * although it is not usually a convention in Egg.
431  *
432  * This may introduce redundant vertices to the vertex pool.
433  */
436  if (!empty()) {
437  do_apply_flat_attribute(size() - 1, this);
438  }
439 }
440 
441 /**
442  * Sets the first vertex of the triangle (or each component) to the primitive
443  * normal and/or color, if the primitive is flat-shaded. This reflects the
444  * DirectX convention of storing flat-shaded properties on the first vertex,
445  * although it is not usually a convention in Egg.
446  *
447  * This may introduce redundant vertices to the vertex pool.
448  */
451  if (!empty()) {
452  do_apply_flat_attribute(0, this);
453  }
454 }
455 
456 /**
457  * Intended as a followup to apply_last_attribute(), this also sets an
458  * attribute on the first vertices of the primitive, if they don't already
459  * have an attribute set, just so they end up with *something*.
460  */
463  if (!empty()) {
464  for (EggVertex *vertex : _vertices) {
465  // Use set_normal() instead of copy_normal(), to avoid getting the
466  // morphs--we don't want them here, since we're just putting a bogus
467  // value on the normal anyway.
468 
469  if (has_normal() && !vertex->has_normal()) {
470  vertex->set_normal(get_normal());
471  }
472  if (has_color() && !vertex->has_color()) {
473  vertex->set_color(get_color());
474  }
475  }
476  }
477 }
478 
479 /**
480  * Reverses the ordering of the vertices in this primitive, if appropriate, in
481  * order to change the direction the polygon appears to be facing. Does not
482  * adjust the surface normal, if any.
483  */
486  // This really only makes sense for polygons. Lights don't care about
487  // vertex ordering, and NURBS surfaces have to do a bit more work in
488  // addition to this.
489  reverse(_vertices.begin(), _vertices.end());
490 }
491 
492 /**
493  * Cleans up modeling errors in whatever context this makes sense. For
494  * instance, for a polygon, this calls remove_doubled_verts(true). For a
495  * point, it calls remove_nonunique_verts(). Returns true if the primitive is
496  * valid, or false if it is degenerate.
497  */
499 cleanup() {
500  return !empty();
501 }
502 
503 /**
504  * Certain kinds of primitives, particularly polygons, don't like to have the
505  * same vertex repeated consecutively. Unfortunately, some modeling programs
506  * (like MultiGen) make this an easy mistake to make.
507  *
508  * It's handy to have a function to remove these redundant vertices. If
509  * closed is true, it also checks that the first and last vertices are not the
510  * same.
511  *
512  * This function identifies repeated vertices by position only; it does not
513  * consider any other properties, such as color or UV, significant in
514  * differentiating vertices.
515  */
517 remove_doubled_verts(bool closed) {
518  if (!_vertices.empty()) {
519  Vertices new_vertices;
520  Vertices::iterator vi, vlast;
521  vi = _vertices.begin();
522  new_vertices.push_back(*vi);
523  int num_removed = 0;
524 
525  vlast = vi;
526  ++vi;
527  while (vi != _vertices.end()) {
528  if ((*vi)->get_pos4() != (*vlast)->get_pos4()) {
529  new_vertices.push_back(*vi);
530  } else {
531  prepare_remove_vertex(*vi, vi - _vertices.begin() - num_removed,
532  _vertices.size() - num_removed);
533  num_removed++;
534  }
535  vlast = vi;
536  ++vi;
537  }
538  _vertices.swap(new_vertices);
539  }
540 
541  if (closed) {
542  // Then, if this is a polygon (which will be closed anyway), remove the
543  // vertex from the end if it's a repeat of the beginning.
544  while (_vertices.size() > 1 &&
545  _vertices.back()->get_pos4() == _vertices.front()->get_pos4()) {
546  prepare_remove_vertex(_vertices.back(), _vertices.size() - 1,
547  _vertices.size());
548  _vertices.pop_back();
549  }
550  }
551 }
552 
553 /**
554  * Removes any multiple appearances of the same vertex from the primitive.
555  * This primarily makes sense for a point primitive, which is really a
556  * collection of points and which doesn't make sense to include the same point
557  * twice, in any order.
558  */
561  Vertices::iterator vi;
562  Vertices new_vertices;
563  int num_removed = 0;
564 
565  pset<EggVertex *> unique_vertices;
566  for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) {
567  bool inserted = unique_vertices.insert(*vi).second;
568  if (inserted) {
569  new_vertices.push_back(*vi);
570  } else {
571  prepare_remove_vertex(*vi, vi - _vertices.begin() - num_removed,
572  _vertices.size() - num_removed);
573  num_removed++;
574  }
575  }
576 
577  _vertices.swap(new_vertices);
578 }
579 
580 /**
581  * Returns true if there are any primitives (e.g. polygons) defined within
582  * this group or below, false otherwise.
583  */
585 has_primitives() const {
586  return true;
587 }
588 
589 /**
590  * Returns true if there are any primitives (e.g. polygons) defined within
591  * this group or below, but the search does not include nested joints.
592  */
594 joint_has_primitives() const {
595  return true;
596 }
597 
598 /**
599  * Returns true if any of the primitives (e.g. polygons) defined within this
600  * group or below have either face or vertex normals defined, false otherwise.
601  */
603 has_normals() const {
604  if (has_normal()) {
605  return true;
606  }
607 
608  const_iterator vi;
609  for (vi = begin(); vi != end(); ++vi) {
610  if ((*vi)->has_normal()) {
611  return true;
612  }
613  }
614 
615  return false;
616 }
617 
618 
619 /**
620  * Part of the implementaion of the EggPrimitive as an STL container. Most of
621  * the rest of these functions are inline and declared in EggPrimitive.I.
622  */
623 EggPrimitive::iterator EggPrimitive::
624 erase(iterator first, iterator last) {
625  iterator i;
626  int num_removed = 0;
627  for (i = first; i != last; ++i) {
628  prepare_remove_vertex(*i, first - _vertices.begin(),
629  _vertices.size() - num_removed);
630  num_removed++;
631  }
632  iterator result = _vertices.erase((Vertices::iterator &)first,
633  (Vertices::iterator &)last);
634  test_vref_integrity();
635  return result;
636 }
637 
638 /**
639  * Returns the iterator pointing to the indicated vertex, or end() if the
640  * vertex is not part of the primitive.
641  */
642 EggPrimitive::iterator EggPrimitive::
643 find(EggVertex *vertex) {
644  PT_EggVertex vpt = vertex;
645  return std::find(begin(), end(), vpt);
646 }
647 
648 
649 /**
650  * Adds the indicated vertex to the end of the primitive's list of vertices,
651  * and returns it.
652  */
654 add_vertex(EggVertex *vertex) {
655  prepare_add_vertex(vertex, _vertices.size(), _vertices.size() + 1);
656  _vertices.push_back(vertex);
657 
658  vertex->test_pref_integrity();
659  test_vref_integrity();
660 
661  return vertex;
662 }
663 
664 /**
665  * Removes the indicated vertex from the primitive and returns it. If the
666  * vertex was not already in the primitive, does nothing and returns NULL.
667  */
669 remove_vertex(EggVertex *vertex) {
670  PT_EggVertex vpt = vertex;
671  iterator i = std::find(begin(), end(), vpt);
672  if (i == end()) {
673  return PT_EggVertex();
674  } else {
675  // erase() calls prepare_remove_vertex().
676  erase(i);
677 
678  vertex->test_pref_integrity();
679  test_vref_integrity();
680 
681  return vertex;
682  }
683 }
684 
685 /**
686  * Removes the indicated vertex from the primitive.
687  */
688 void EggPrimitive::
689 remove_vertex(size_t index) {
690  nassertv(index < size());
691  iterator i = begin() + index;
692 
693  // erase() calls prepare_remove_vertex().
694  erase(i);
695 
696  test_vref_integrity();
697 }
698 
699 /**
700  * Replaces the current primitive's list of vertices with a copy of the list
701  * of vertices on the other primitive.
702  */
704 copy_vertices(const EggPrimitive &other) {
705  clear();
706  _vertices.reserve(other.size());
707 
708  iterator vi;
709  for (vi = other.begin(); vi != other.end(); ++vi) {
710  add_vertex(*vi);
711  }
712 
713  test_vref_integrity();
714  other.test_vref_integrity();
715 }
716 
717 #ifdef _DEBUG
718 
719 /**
720  * Verifies that each vertex in the primitive exists and that it knows it is
721  * referenced by the primitive.
722  */
723 void EggPrimitive::
724 test_vref_integrity() const {
726 
727  if ((int)size() <= egg_test_vref_integrity) {
728  // First, we need to know how many times each vertex appears. Usually,
729  // this will be only one, but it's possible for a vertex to appear more
730  // than once.
731  typedef pmap<const EggVertex *, int> VertexCount;
732  VertexCount _count;
733 
734  // Now count up the vertices.
735  iterator vi;
736  for (vi = begin(); vi != end(); ++vi) {
737  const EggVertex *vert = *vi;
738  vert->test_ref_count_integrity();
739 
740  VertexCount::iterator vci = _count.find(vert);
741  if (vci == _count.end()) {
742  _count[vert] = 1;
743  } else {
744  (*vci).second++;
745  }
746  }
747 
748  // Ok, now walk through the vertices found and make sure the vertex has
749  // the proper number of entries of this primitive in its pref.
750  VertexCount::iterator vci;
751  for (vci = _count.begin(); vci != _count.end(); ++vci) {
752  const EggVertex *vert = (*vci).first;
753 
754  int count = (*vci).second;
755  int vert_count = vert->has_pref(this);
756 
757  nassertv(count == vert_count);
758  }
759  }
760 }
761 
762 #endif // _DEBUG
763 
764 /**
765  * Marks the vertex as belonging to the primitive. This is an internal
766  * function called by the STL-like functions push_back() and insert(), in
767  * preparation for actually adding the vertex.
768  *
769  * i indicates the new position of the vertex in the list; n indicates the new
770  * number of vertices after the operation has completed.
771  */
772 void EggPrimitive::
773 prepare_add_vertex(EggVertex *vertex, int i, int n) {
774  // We can't test integrity within this function, because it might be called
775  // when the primitive is in an incomplete state.
776 
777  // The vertex must have the same vertex pool as the vertices already added.
778  nassertv(empty() || vertex->get_pool() == get_pool());
779 
780  // Since a given vertex might appear more than once in a particular
781  // primitive, we can't conclude anything about data integrity by inspecting
782  // the return value of insert(). (In fact, the vertex's pref is a multiset,
783  // so the insert() will always succeed.)
784 
785  vertex->_pref.insert(this);
786 }
787 
788 
789 /**
790  * Marks the vertex as removed from the primitive. This is an internal
791  * function called by the STL-like functions pop_back() and erase(), in
792  * preparation for actually doing the removal.
793  *
794  * i indicates the former position of the vertex in the list; n indicates the
795  * current number of vertices before the operation has completed.
796  *
797  * It is an error to attempt to remove a vertex that is not already a vertex
798  * of this primitive.
799  */
800 void EggPrimitive::
801 prepare_remove_vertex(EggVertex *vertex, int i, int n) {
802  // We can't test integrity within this function, because it might be called
803  // when the primitive is in an incomplete state.
804 
805  // Now we must remove the primitive from the vertex's pref. We can't just
806  // use the simple erase() function, since that will remove all instances of
807  // this primitive from the pref; instead, we must find one instance and
808  // remove that.
809 
810  EggVertex::PrimitiveRef::iterator pri = vertex->_pref.find(this);
811 
812  // We should have found the primitive in the vertex's pref. If we did not,
813  // something's out of sync internally.
814  nassertv(pri != vertex->_pref.end());
815 
816  vertex->_pref.erase(pri);
817 }
818 
819 /**
820  * Writes the attributes and the vertices referenced by the primitive to the
821  * indicated output stream in Egg format.
822  */
823 void EggPrimitive::
824 write_body(std::ostream &out, int indent_level) const {
825  test_vref_integrity();
826 
827  EggAttributes::write(out, indent_level);
828  EggRenderMode::write(out, indent_level);
829 
830  int num_textures = get_num_textures();
831  for (int i = 0; i < num_textures; i++) {
832  EggTexture *texture = get_texture(i);
833 
834  indent(out, indent_level) << "<TRef> { ";
835  enquote_string(out, texture->get_name())
836  << " }\n";
837  }
838 
839  if (has_material()) {
840  EggMaterial *material = get_material();
841 
842  indent(out, indent_level) << "<MRef> { ";
843  enquote_string(out, material->get_name())
844  << " }\n";
845  }
846 
847  if (get_bface_flag()) {
848  indent(out, indent_level) << "<BFace> { 1 }\n";
849  }
850 
851  if (!empty()) {
852  EggVertexPool *pool = get_pool();
853 
854  // Make sure the vertices belong to some vertex pool.
855  nassertv(pool != nullptr);
856 
857  // Make sure the vertex pool is named.
858  nassertv(pool->has_name());
859 
860  if ((int)size() < 10) {
861  // A simple primitive gets all its vertex indices written on one line.
862  indent(out, indent_level) << "<VertexRef> {";
863  const_iterator i;
864  for (i = begin(); i != end(); ++i) {
865  EggVertex *vert = *i;
866  vert->test_pref_integrity();
867 
868  // Make sure each vertex belongs to the same pool.
869  nassertv(vert->get_pool() == pool);
870 
871  out << " " << vert->get_index();
872  }
873  out << " <Ref> { ";
874  enquote_string(out, pool->get_name()) << " } }\n";
875 
876  } else {
877 
878  // A larger primitive gets its vertex indices written as multiple lines.
879  vector_int indices;
880  const_iterator i;
881  for (i = begin(); i != end(); ++i) {
882  EggVertex *vert = *i;
883  vert->test_pref_integrity();
884 
885  // Make sure each vertex belongs to the same pool.
886  nassertv(vert->get_pool() == pool);
887 
888  indices.push_back(vert->get_index());
889  }
890 
891  indent(out, indent_level) << "<VertexRef> {\n";
892  write_long_list(out, indent_level+2, indices.begin(), indices.end(),
893  "", "", 72);
894  indent(out, indent_level+2) << "<Ref> { ";
895  enquote_string(out, pool->get_name()) << " }\n";
896  indent(out, indent_level) << "}\n";
897  }
898  }
899 }
900 
901 /**
902  * This function is called within parse_egg(). It should call the appropriate
903  * function on the lexer to initialize the parser into the state associated
904  * with this object. If the object cannot be parsed into directly, it should
905  * return false.
906  */
907 bool EggPrimitive::
908 egg_start_parse_body() {
909  egg_start_primitive_body();
910  return true;
911 }
912 
913 /**
914  * This is called from within the egg code by transform(). It applies a
915  * transformation matrix to the current node in some sensible way, then
916  * continues down the tree.
917  *
918  * The first matrix is the transformation to apply; the second is its inverse.
919  * The third parameter is the coordinate system we are changing to, or
920  * CS_default if we are not changing coordinate systems.
921  */
922 void EggPrimitive::
923 r_transform(const LMatrix4d &mat, const LMatrix4d &, CoordinateSystem) {
925 }
926 
927 /**
928  * The recursive implementation of flatten_transforms().
929  */
930 void EggPrimitive::
931 r_flatten_transforms() {
932  if (is_local_coord()) {
933  LMatrix4d mat = get_vertex_frame();
935 
936  // Transform each vertex by duplicating it in the vertex pool.
937  size_t num_vertices = size();
938  for (size_t i = 0; i < num_vertices; i++) {
939  EggVertex *vertex = get_vertex(i);
940  EggVertexPool *pool = vertex->get_pool();
941 
942  EggVertex new_vertex(*vertex);
943  new_vertex.transform(mat);
944  EggVertex *unique = pool->create_unique_vertex(new_vertex);
945  unique->copy_grefs_from(*vertex);
946 
947  set_vertex(i, unique);
948  }
949  }
950 }
951 
952 /**
953  * The recursive implementation of apply_texmats().
954  */
955 void EggPrimitive::
956 r_apply_texmats(EggTextureCollection &textures) {
957  Textures new_textures;
958  Textures::const_iterator ti;
959  for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
960  EggTexture *texture = (*ti);
961 
962  if (!texture->has_transform()) {
963  new_textures.push_back(texture);
964 
965  } else if (texture->transform_is_identity()) {
966  // Now, what's the point of a texture with an identity transform?
967  texture->clear_transform();
968  new_textures.push_back(texture);
969 
970  } else {
971 
972  // We've got a texture with a matrix applied. Save the matrix, and get
973  // a new texture without the matrix.
974  LMatrix4d mat = texture->get_transform3d();
975  EggTexture new_texture(*texture);
976  new_texture.clear_transform();
977  EggTexture *unique = textures.create_unique_texture(new_texture, ~0);
978 
979  new_textures.push_back(unique);
980  std::string uv_name = unique->get_uv_name();
981 
982  // Now apply the matrix to the vertex UV's. Create new vertices as
983  // necessary.
984  size_t num_vertices = size();
985  for (size_t i = 0; i < num_vertices; i++) {
986  EggVertex *vertex = get_vertex(i);
987 
988  const EggVertexUV *uv_obj = vertex->get_uv_obj(uv_name);
989  if (uv_obj != nullptr) {
990  EggVertex new_vertex(*vertex);
991  PT(EggVertexUV) new_uv_obj = new EggVertexUV(*uv_obj);
992  LTexCoord3d uvw = uv_obj->get_uvw() * mat;
993  if (uv_obj->has_w() || texture->has_transform3d()) {
994  new_uv_obj->set_uvw(uvw);
995  } else {
996  new_uv_obj->set_uv(LTexCoordd(uvw[0], uvw[1]));
997  }
998  new_vertex.set_uv_obj(new_uv_obj);
999 
1000  EggVertexPool *pool = vertex->get_pool();
1001  EggVertex *unique = pool->create_unique_vertex(new_vertex);
1002  unique->copy_grefs_from(*vertex);
1003 
1004  set_vertex(i, unique);
1005  }
1006  }
1007  }
1008  }
1009 
1010  _textures.swap(new_textures);
1011 }
1012 
1013 /**
1014  * This is used to implement apply_first_attribute() and
1015  * apply_last_attribute(). It copies the indicated attributes to the
1016  * specified vertex.
1017  */
1018 void EggPrimitive::
1019 do_apply_flat_attribute(int vertex_index, EggAttributes *attrib) {
1020  // The significant_change flag is set if we have changed the vertex in some
1021  // important way, that will invalidate it for other primitives that might
1022  // share it. We don't consider *adding* a normal where there wasn't one
1023  // before to be significant, but we do consider it significant to change a
1024  // vertex's normal to something different. Similarly for color.
1025  bool significant_change = false;
1026 
1027  EggVertex *orig_vertex = get_vertex(vertex_index);
1028  PT(EggVertex) new_vertex = new EggVertex(*orig_vertex);
1029 
1030  if (attrib->has_normal()) {
1031  new_vertex->copy_normal(*attrib);
1032 
1033  if (orig_vertex->has_normal() &&
1034  !orig_vertex->matches_normal(*new_vertex)) {
1035  significant_change = true;
1036  }
1037  } else if (has_normal()) {
1038  new_vertex->copy_normal(*this);
1039 
1040  if (orig_vertex->has_normal() &&
1041  !orig_vertex->matches_normal(*new_vertex)) {
1042  significant_change = true;
1043  }
1044  }
1045 
1046  if (attrib->has_color()) {
1047  new_vertex->copy_color(*attrib);
1048 
1049  if (orig_vertex->has_color() &&
1050  !orig_vertex->matches_color(*new_vertex)) {
1051  significant_change = true;
1052  }
1053  } else if (has_color()) {
1054  new_vertex->copy_color(*this);
1055 
1056  if (orig_vertex->has_color() &&
1057  !orig_vertex->matches_color(*new_vertex)) {
1058  significant_change = true;
1059  }
1060  }
1061 
1062  if (significant_change) {
1063  new_vertex = get_pool()->create_unique_vertex(*new_vertex);
1064  new_vertex->copy_grefs_from(*orig_vertex);
1065  set_vertex(vertex_index, new_vertex);
1066  } else {
1067  // Just copy the new attributes back into the pool.
1068  ((EggAttributes *)orig_vertex)->operator = (*new_vertex);
1069  }
1070 }
1071 
1072 /**
1073  * Recursively updates the connected_shading member in all connected
1074  * primitives.
1075  */
1076 void EggPrimitive::
1077 set_connected_shading(EggPrimitive::Shading shading,
1078  const EggAttributes *neighbor) {
1079  ConnectedShadingNodes connected_nodes;
1080 
1081  r_set_connected_shading(0, shading, neighbor, connected_nodes);
1082 
1083  // Pick up any additional nodes we couldn't visit because of the stack depth
1084  // restrictions.
1085  while (!connected_nodes.empty()) {
1086  ConnectedShadingNodes next_nodes;
1087  next_nodes.swap(connected_nodes);
1088 
1089  ConnectedShadingNodes::iterator ni;
1090  for (ni = next_nodes.begin(); ni != next_nodes.end(); ++ni) {
1091  r_set_connected_shading(0, (*ni)._shading, (*ni)._neighbor, connected_nodes);
1092  }
1093  }
1094 }
1095 
1096 /**
1097  * Implements set_connected_shading, with some restrictions to prevent stack
1098  * overflow.
1099  */
1100 void EggPrimitive::
1101 r_set_connected_shading(int stack_depth, EggPrimitive::Shading shading,
1102  const EggAttributes *neighbor,
1103  ConnectedShadingNodes &next_nodes) {
1104  if (stack_depth > egg_recursion_limit) {
1105  // Too deep. Limit recursion.
1106  ConnectedShadingNode next;
1107  next._shading = shading;
1108  next._neighbor = neighbor;
1109  next_nodes.push_back(next);
1110  return;
1111  }
1112 
1113  bool propagate = false;
1114 
1115  if (_connected_shading == S_unknown) {
1116  // We haven't visited this node before; propagate now.
1117  _connected_shading = get_shading();
1118  propagate = true;
1119  }
1120 
1121  if (shading > _connected_shading) {
1122  // More specific information just came in. Save it, and propagate it to
1123  // all connected primitives.
1124  _connected_shading = shading;
1125  propagate = true;
1126 
1127  } else if (shading == S_overall && _connected_shading == S_overall) {
1128  // If both neighbors are overall shaded, check if the two neighbors have
1129  // different properties. If they do, elevate to per_face.
1130  bool matches_normal = this->matches_normal(*neighbor);
1131  bool matches_color = this->matches_color(*neighbor);
1132 
1133  if (!matches_color) {
1134  // Make a special case for not having an overall color: that's
1135  // implicitly white.
1136  if (!neighbor->has_color() && has_color() && _drgbas.empty() &&
1137  get_color() == LColor(1.0f, 1.0f, 1.0f, 1.0f)) {
1138  matches_color = true;
1139  } else if (!has_color() && neighbor->has_color() && neighbor->_drgbas.empty() &&
1140  neighbor->get_color() == LColor(1.0f, 1.0f, 1.0f, 1.0f)) {
1141  matches_color = true;
1142  }
1143  }
1144  if (!matches_normal || !matches_color) {
1145  _connected_shading = S_per_face;
1146  propagate = true;
1147  }
1148  }
1149 
1150  if (propagate) {
1151  Vertices::const_iterator vi;
1152  for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) {
1153  EggVertex *vertex = (*vi);
1154  EggVertex::PrimitiveRef::const_iterator pi;
1155  for (pi = vertex->pref_begin();
1156  pi != vertex->pref_end();
1157  ++pi) {
1158  (*pi)->r_set_connected_shading(stack_depth + 1, _connected_shading, this,
1159  next_nodes);
1160  }
1161  }
1162  }
1163 }
EggPrimitive::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: eggPrimitive.cxx:91
EggVertex::pref_begin
PrimitiveRef::const_iterator pref_begin() const
Returns an iterator that can, in conjunction with pref_end(), be used to traverse the entire set of p...
Definition: eggVertex.cxx:793
EggVertex::get_index
int get_index() const
Returns the index number of the vertex within its pool.
Definition: eggVertex.I:277
indent
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition: indent.cxx:20
EggVertexUV::get_uvw
const LTexCoord3d & get_uvw() const
Returns the texture coordinate triple, if get_num_dimensions() is 3.
Definition: eggVertexUV.I:68
EggPrimitive::unify_attributes
virtual void unify_attributes(Shading shading)
If the shading property is S_per_vertex, ensures that all vertices have a normal and a color,...
Definition: eggPrimitive.cxx:337
EggPrimitive::has_vertex_normal
bool has_vertex_normal() const
Returns true if any vertex on the primitive has a specific normal set, false otherwise.
Definition: eggPrimitive.cxx:289
eggVertexPool.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggPrimitive::get_num_textures
get_num_textures
Returns the number of textures applied to the primitive.
Definition: eggPrimitive.h:100
eggPrimitive.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggPrimitive::get_texture
get_texture
Returns the first texture on the primitive, if any, or NULL if there are no textures on the primitive...
Definition: eggPrimitive.h:100
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
EggVertex::pref_end
PrimitiveRef::const_iterator pref_end() const
Returns an iterator that can, in conjunction with pref_begin(), be used to traverse the entire set of...
Definition: eggVertex.cxx:805
vector_int.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggVertex::has_pref
int has_pref(const EggPrimitive *prim) const
Returns the number of times the vertex appears in the indicated primitive, or 0 if it does not appear...
Definition: eggVertex.cxx:824
EggAttributes::copy_normal
void copy_normal(const EggAttributes &other)
Sets this normal to be the same as the other's, include morphs.
Definition: eggAttributes.I:69
EggPrimitive::get_shading
get_shading
Returns the shading properties apparent on this particular primitive.
Definition: eggPrimitive.h:111
EggPrimitive::cleanup
virtual bool cleanup()
Cleans up modeling errors in whatever context this makes sense.
Definition: eggPrimitive.cxx:499
pmap
This is our own Panda specialization on the default STL map.
Definition: pmap.h:49
EggTransform::get_transform3d
const LMatrix4d & get_transform3d() const
Returns the overall transform as a 4x4 matrix.
Definition: eggTransform.I:212
EggNode::get_vertex_frame
const LMatrix4d & get_vertex_frame() const
Returns the coordinate frame of the vertices referenced by primitives at or under this node.
Definition: eggNode.I:108
EggTransform::transform_is_identity
bool transform_is_identity() const
Returns true if the described transform is identity, false otherwise.
Definition: eggTransform.I:220
EggMaterial
Definition: eggMaterial.h:26
enquote_string
ostream & enquote_string(ostream &out, const string &str, int indent_level, bool always_quote)
Writes the string to the indicated output stream.
Definition: eggMiscFuncs.cxx:30
EggPrimitive::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: eggPrimitive.cxx:139
EggNode::is_local_coord
bool is_local_coord() const
Returns true if this node's vertices are not in the global coordinate space.
Definition: eggNode.I:87
EggRenderMode::has_depth_offset
bool has_depth_offset() const
Returns true if the depth-offset flag has been set for this particular object.
Definition: eggRenderMode.I:128
EggPrimitive::set_bface_flag
set_bface_flag
Sets the backfacing flag of the polygon.
Definition: eggPrimitive.h:116
EggPrimitive
A base class for any of a number of kinds of geometry primitives: polygons, point lights,...
Definition: eggPrimitive.h:49
EggAttributes::matches_normal
bool matches_normal(const EggAttributes &other) const
Returns true if this normal matches that of the other EggAttributes object, include the morph list.
Definition: eggAttributes.I:53
EggAttributes::transform
void transform(const LMatrix4d &mat)
Applies the indicated transformation matrix to the attributes.
Definition: eggAttributes.cxx:132
EggPrimitive::apply_first_attribute
virtual void apply_first_attribute()
Sets the first vertex of the triangle (or each component) to the primitive normal and/or color,...
Definition: eggPrimitive.cxx:450
EggRenderMode::write
void write(std::ostream &out, int indent_level) const
Writes the attributes to the indicated output stream in Egg format.
Definition: eggRenderMode.cxx:60
EggPrimitive::clear
void clear()
Removes all of the vertices from the primitive.
Definition: eggPrimitive.I:352
EggRenderMode::get_alpha_mode
AlphaMode get_alpha_mode() const
Returns the alpha mode that was set, or AM_unspecified if nothing was set.
Definition: eggRenderMode.I:98
EggPrimitive::has_material
has_material
Returns true if the primitive is materiald (and get_material() will return a real pointer),...
Definition: eggPrimitive.h:115
EggPrimitive::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: eggPrimitive.cxx:67
EggPrimitive::joint_has_primitives
virtual bool joint_has_primitives() const
Returns true if there are any primitives (e.g.
Definition: eggPrimitive.cxx:594
EggVertex::get_uv_obj
const EggVertexUV * get_uv_obj(const std::string &name) const
Returns the named EggVertexUV object, which defines both the UV coordinate pair for this name and the...
Definition: eggVertex.cxx:245
EggAttributes::get_color
LColor get_color() const
Returns the color set on this particular attribute.
Definition: eggAttributes.I:91
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.
EggVertexUV::has_w
bool has_w() const
Returns true if the texture coordinate has a third, w component, false if it is just a normal 2-d tex...
Definition: eggVertexUV.I:49
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
EggPrimitive::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: eggPrimitive.cxx:187
EggPrimitive::has_primitives
virtual bool has_primitives() const
Returns true if there are any primitives (e.g.
Definition: eggPrimitive.cxx:585
EggPrimitive::has_normals
virtual bool has_normals() const
Returns true if any of the primitives (e.g.
Definition: eggPrimitive.cxx:603
EggTransform::has_transform3d
bool has_transform3d() const
Returns true if the transform is specified as a 3-d transform, e.g.
Definition: eggTransform.I:179
EggVertex
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal.
Definition: eggVertex.h:39
EggPrimitive::set_material
set_material
Applies the indicated material to the primitive.
Definition: eggPrimitive.h:115
EggPrimitive::remove_vertex
remove_vertex
Removes the indicated vertex from the primitive and returns it.
Definition: eggPrimitive.h:191
EggVertexUV
The set of UV's that may or may not be assigned to a vertex.
Definition: eggVertexUV.h:29
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
EggPrimitive::get_bface_flag
get_bface_flag
Retrieves the backfacing flag of the polygon.
Definition: eggPrimitive.h:116
EggTexture::get_uv_name
get_uv_name
Returns the texcoord name that has been specified for this texture, or the empty string if no texcoor...
Definition: eggTexture.h:340
Namable::has_name
bool has_name() const
Returns true if the Namable has a nonempty name set, false if the name is empty.
Definition: namable.I:44
EggPrimitive::get_vertex
get_vertex
Returns a particular index based on its index number.
Definition: eggPrimitive.h:187
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
EggVertex::copy_grefs_from
void copy_grefs_from(const EggVertex &other)
Copies all the group references from the other vertex onto this one.
Definition: eggVertex.cxx:747
EggPrimitive::replace
void replace(iterator position, EggVertex *vertex)
Replaces the vertex at the indicated position with the indicated vertex.
Definition: eggPrimitive.I:335
EggPrimitive::get_material
get_material
Returns a pointer to the applied material, or NULL if there is no material applied.
Definition: eggPrimitive.h:115
EggPrimitive::remove_nonunique_verts
void remove_nonunique_verts()
Removes any multiple appearances of the same vertex from the primitive.
Definition: eggPrimitive.cxx:560
EggRenderMode::has_bin
bool has_bin() const
Returns true if a bin name has been set for this particular object.
Definition: eggRenderMode.I:207
EggPrimitive::add_vertex
EggVertex * add_vertex(EggVertex *vertex)
Adds the indicated vertex to the end of the primitive's list of vertices, and returns it.
Definition: eggPrimitive.cxx:654
EggRenderMode::get_depth_test_mode
DepthTestMode get_depth_test_mode() const
Returns the depth_test mode that was set, or DTM_unspecified if nothing was set.
Definition: eggRenderMode.I:55
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
EggPrimitive::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: eggPrimitive.cxx:163
EggPrimitive::set_vertex
set_vertex
Replaces a particular vertex based on its index number in the list of vertices.
Definition: eggPrimitive.h:191
EggVertex::get_pool
EggVertexPool * get_pool() const
Returns the vertex pool this vertex belongs in.
Definition: eggVertex.I:19
EggAttributes::write
void write(std::ostream &out, int indent_level) const
Writes the attributes to the indicated output stream in Egg format.
Definition: eggAttributes.cxx:65
EggPrimitive::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: eggPrimitive.cxx:34
EggPrimitive::copy_attributes
void copy_attributes(const EggAttributes &other)
Copies the rendering attributes from the indicated primitive.
Definition: eggPrimitive.cxx:265
EggTextureCollection::create_unique_texture
EggTexture * create_unique_texture(const EggTexture &copy, int eq)
Creates a new texture if there is not already one equivalent (according to eq, see EggTexture::is_equ...
Definition: eggTextureCollection.cxx:432
EggPrimitive::apply_last_attribute
virtual void apply_last_attribute()
Sets the last vertex of the triangle (or each component) to the primitive normal and/or color,...
Definition: eggPrimitive.cxx:435
eggMiscFuncs.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
write_long_list
void write_long_list(std::ostream &out, int indent_level, InputIterator ifirst, InputIterator ilast, std::string first_prefix="", std::string later_prefix="", int max_col=72)
Writes a list of things to the indicated output stream, with a space separating each item.
Definition: indent.I:22
EggPrimitive::reverse_vertex_ordering
virtual void reverse_vertex_ordering()
Reverses the ordering of the vertices in this primitive, if appropriate, in order to change the direc...
Definition: eggPrimitive.cxx:485
EggPrimitive::remove_doubled_verts
void remove_doubled_verts(bool closed)
Certain kinds of primitives, particularly polygons, don't like to have the same vertex repeated conse...
Definition: eggPrimitive.cxx:517
EggPrimitive::post_apply_flat_attribute
virtual void post_apply_flat_attribute()
Intended as a followup to apply_last_attribute(), this also sets an attribute on the first vertices o...
Definition: eggPrimitive.cxx:462
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
EggAttributes::copy_color
void copy_color(const EggAttributes &other)
Sets this color to be the same as the other's, include morphs.
Definition: eggAttributes.I:137
EggTexture
Defines a texture map that may be applied to geometry.
Definition: eggTexture.h:30
EggTransform::has_transform
bool has_transform() const
Returns true if the transform is nonempty, false if it is empty (no transform components have been ad...
Definition: eggTransform.I:143
EggRenderMode::has_draw_order
bool has_draw_order() const
Returns true if the draw-order flag has been set for this particular object.
Definition: eggRenderMode.I:168
EggPrimitive::has_vertex_color
bool has_vertex_color() const
Returns true if any vertex on the primitive has a specific color set, false otherwise.
Definition: eggPrimitive.cxx:308
EggVertexPool::create_unique_vertex
EggVertex * create_unique_vertex(const EggVertex &copy)
Creates a new vertex in the pool that is a copy of the indicated one and returns it.
Definition: eggVertexPool.cxx:472
EggVertexPool
A collection of vertices.
Definition: eggVertexPool.h:41
EggPrimitive::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: eggPrimitive.cxx:115
indent.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggPrimitive::copy_vertices
void copy_vertices(const EggPrimitive &other)
Replaces the current primitive's list of vertices with a copy of the list of vertices on the other pr...
Definition: eggPrimitive.cxx:704
EggAttributes::matches_color
bool matches_color(const EggAttributes &other) const
Returns true if this color matches that of the other EggAttributes object, include the morph list.
Definition: eggAttributes.I:121
EggRenderMode::get_depth_write_mode
DepthWriteMode get_depth_write_mode() const
Returns the depth_write mode that was set, or DWM_unspecified if nothing was set.
Definition: eggRenderMode.I:36
EggTransform::clear_transform
void clear_transform()
Resets the transform to empty, identity.
Definition: eggTransform.I:114
config_egg.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggTexture::affects_polygon_alpha
bool affects_polygon_alpha() const
Returns true if this texture's environment type or combine mode allows the texture to have an effect ...
Definition: eggTexture.cxx:543
EggRenderMode::get_visibility_mode
VisibilityMode get_visibility_mode() const
Returns the visibility mode that was set, or VM_unspecified if nothing was set.
Definition: eggRenderMode.I:75
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
EggAttributes
The set of attributes that may be applied to vertices as well as polygons, such as surface normal and...
Definition: eggAttributes.h:33
EggPrimitive::get_pool
get_pool
Returns the vertex pool associated with the vertices of the primitive, or NULL if the primitive has n...
Definition: eggPrimitive.h:192
EggPrimitive::find
iterator find(EggVertex *vertex)
Returns the iterator pointing to the indicated vertex, or end() if the vertex is not part of the prim...
Definition: eggPrimitive.cxx:643
pset
This is our own Panda specialization on the default STL set.
Definition: pset.h:49