Panda3D
eggBinner.cxx
1 // Filename: eggBinner.cxx
2 // Created by: drose (17Feb00)
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 "eggBinner.h"
16 #include "eggRenderState.h"
17 #include "eggPrimitive.h"
18 #include "eggNurbsSurface.h"
19 #include "eggNurbsCurve.h"
20 #include "eggPatch.h"
21 #include "eggSwitchCondition.h"
22 #include "eggGroup.h"
23 #include "dcast.h"
24 
25 ////////////////////////////////////////////////////////////////////
26 // Function: EggBinner::Constructor
27 // Access: Public
28 // Description:
29 ////////////////////////////////////////////////////////////////////
30 EggBinner::
31 EggBinner(EggLoader &loader) :
32  _loader(loader)
33 {
34 }
35 
36 ////////////////////////////////////////////////////////////////////
37 // Function: EggBinner::prepare_node
38 // Access: Public, Virtual
39 // Description: May be overridden in derived classes to perform some
40 // setup work as each node is encountered. This will be
41 // called once for each node in the egg hierarchy.
42 ////////////////////////////////////////////////////////////////////
43 void EggBinner::
45  if (node->is_of_type(EggPrimitive::get_class_type())) {
46  EggPrimitive *egg_prim = DCAST(EggPrimitive, node);
47  PT(EggRenderState) render_state = new EggRenderState(_loader);
48  render_state->fill_state(egg_prim);
49  egg_prim->set_user_data(render_state);
50  }
51 }
52 
53 ////////////////////////////////////////////////////////////////////
54 // Function: EggBinner::get_bin_number
55 // Access: Public, Virtual
56 // Description:
57 ////////////////////////////////////////////////////////////////////
58 int EggBinner::
59 get_bin_number(const EggNode *node) {
60  if (node->is_of_type(EggNurbsSurface::get_class_type())) {
61  return (int)BN_nurbs_surface;
62 
63  } else if (node->is_of_type(EggNurbsCurve::get_class_type())) {
64  return (int)BN_nurbs_curve;
65 
66  } else if (node->is_of_type(EggPatch::get_class_type())) {
67  return (int)BN_patches;
68 
69  } else if (node->is_of_type(EggPrimitive::get_class_type())) {
70  return (int)BN_polyset;
71 
72  } else if (node->is_of_type(EggGroup::get_class_type())) {
73  const EggGroup *group = DCAST(EggGroup, node);
74  if (group->has_lod()) {
75  return (int)BN_lod;
76  }
77  }
78 
79  return (int)BN_none;
80 }
81 
82 ////////////////////////////////////////////////////////////////////
83 // Function: EggBinner::get_bin_name
84 // Access: Public, Virtual
85 // Description: May be overridden in derived classes to define a name
86 // for each new bin, based on its bin number, and a
87 // sample child.
88 ////////////////////////////////////////////////////////////////////
89 string EggBinner::
90 get_bin_name(int bin_number, const EggNode *child) {
91  if (bin_number == BN_polyset || bin_number == BN_patches) {
92  return DCAST(EggPrimitive, child)->get_sort_name();
93  }
94 
95  return string();
96 }
97 
98 ////////////////////////////////////////////////////////////////////
99 // Function: EggBinner::sorts_less
100 // Access: Public, Virtual
101 // Description:
102 ////////////////////////////////////////////////////////////////////
103 bool EggBinner::
104 sorts_less(int bin_number, const EggNode *a, const EggNode *b) {
105  switch (bin_number) {
106  case BN_polyset:
107  case BN_patches:
108  {
109  const EggPrimitive *pa, *pb;
110  DCAST_INTO_R(pa, a, false);
111  DCAST_INTO_R(pb, b, false);
112 
113  // Different render states are binned separately.
114  const EggRenderState *rsa, *rsb;
115  DCAST_INTO_R(rsa, pa->get_user_data(EggRenderState::get_class_type()), false);
116  DCAST_INTO_R(rsb, pb->get_user_data(EggRenderState::get_class_type()), false);
117  int compare = rsa->compare_to(*rsb);
118  if (compare != 0) {
119  return (compare < 0);
120  }
121 
122  if (bin_number == BN_patches) {
123  // For patches only, we group together patches of similar size.
124  const EggPatch *patch_a, *patch_b;
125  DCAST_INTO_R(patch_a, a, false);
126  DCAST_INTO_R(patch_b, b, false);
127  if (patch_a->size() != patch_b->size()) {
128  return patch_a->size() < patch_b->size();
129  }
130  }
131 
132  // Also, if the primitive was given a name (that does not begin
133  // with a digit), it gets binned with similar-named primitives.
134  return pa->get_sort_name() < pb->get_sort_name();
135  }
136 
137  case BN_lod:
138  {
139  const EggGroup *ga = DCAST(EggGroup, a);
140  const EggGroup *gb = DCAST(EggGroup, b);
141 
142  const EggSwitchCondition &swa = ga->get_lod();
143  const EggSwitchCondition &swb = gb->get_lod();
144 
145  // For now, this is the only kind of switch condition there is.
146  const EggSwitchConditionDistance &swda =
147  *DCAST(EggSwitchConditionDistance, &swa);
148  const EggSwitchConditionDistance &swdb =
149  *DCAST(EggSwitchConditionDistance, &swb);
150 
151  // Group LOD nodes in order by switching center.
152  return (swda._center.compare_to(swdb._center) < 0);
153  }
154 
155  case BN_nurbs_surface:
156  case BN_nurbs_curve:
157  // Nurbs curves and surfaces are always binned individually.
158  return a < b;
159 
160  case BN_none:
161  break;
162  }
163 
164  // Shouldn't get here.
165  return false;
166 }
A base class for any of a number of kinds of geometry primitives: polygons, point lights...
Definition: eggPrimitive.h:51
virtual bool sorts_less(int bin_number, const EggNode *a, const EggNode *b)
May be overridden in derived classes to create additional bins within a particular bin number...
Definition: eggBinner.cxx:104
This class is used within this package only to record the render state that should be assigned to eac...
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
Definition: eggGroup.h:36
A single "patch", a special primitive to be rendered only with a tessellation shader.
Definition: eggPatch.h:27
EggUserData * get_user_data() const
Returns the user data pointer most recently stored on this object, or NULL if nothing was previously ...
Definition: eggObject.cxx:102
string get_sort_name() const
Returns the name of the primitive for the purposes of sorting primitives into different groups...
Definition: eggPrimitive.I:82
void set_user_data(EggUserData *user_data)
Sets the user data associated with this object.
Definition: eggObject.cxx:89
virtual void prepare_node(EggNode *node)
May be overridden in derived classes to perform some setup work as each node is encountered.
Definition: eggBinner.cxx:44
A base class for things that may be directly added into the egg hierarchy.
Definition: eggNode.h:38
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:63
int compare_to(const LVecBase3d &other) const
This flavor of compare_to uses a default threshold value based on the numeric type.
Definition: lvecBase3.h:2306
This corresponds to a <SwitchCondition> entry within a group.
virtual string get_bin_name(int bin_number, const EggNode *child)
May be overridden in derived classes to define a name for each new bin, based on its bin number...
Definition: eggBinner.cxx:90
A SwitchCondition that switches the levels-of-detail based on distance from the camera&#39;s eyepoint...
Converts an egg data structure, possibly read from an egg file but not necessarily, into a scene graph suitable for rendering.
Definition: eggLoader.h:70
int compare_to(const EggRenderState &other) const
Provides a unique ordering for different EggRenderState objects, so that primitives of similar state ...