Panda3D
fltToEggLevelState.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 fltToEggLevelState.cxx
10  * @author drose
11  * @date 2001-04-18
12  */
13 
14 #include "fltToEggLevelState.h"
15 #include "fltToEggConverter.h"
16 #include "fltTransformTranslate.h"
19 #include "fltTransformScale.h"
20 #include "fltTransformPut.h"
21 #include "eggGroup.h"
22 #include "dcast.h"
23 #include "look_at.h"
24 
25 
26 /**
27  *
28  */
29 FltToEggLevelState::
30 ~FltToEggLevelState() {
31  Parents::iterator pi;
32  for (pi = _parents.begin(); pi != _parents.end(); ++pi) {
33  delete (*pi).second;
34  }
35 }
36 
37 /**
38  *
39  */
40 FltToEggLevelState::ParentNodes::
41 ParentNodes() {
42  _axial_billboard = nullptr;
43  _point_billboard = nullptr;
44  _plain = nullptr;
45 }
46 
47 /**
48  * Sometimes it is necessary to synthesize a group within a particular
49  * EggGroup, for instance to insert a transform or billboard flag. This
50  * function will synthesize a group as needed, or return an existing group (if
51  * the group need not be synthesized, or if a matching group was previously
52  * synthesized).
53  *
54  * This collects together polygons that share the same billboard axis and/or
55  * transform space into the same group, rather than wastefully creating a
56  * group per polygon.
57  */
59 get_synthetic_group(const std::string &name,
60  const FltBead *transform_bead,
61  FltGeometry::BillboardType type) {
62  LMatrix4d transform = transform_bead->get_transform();
63  bool is_identity = transform.almost_equal(LMatrix4d::ident_mat());
64  if (is_identity &&
65  (type != FltGeometry::BT_axial &&
66  type != FltGeometry::BT_point)) {
67  // Trivial case: the primitive belongs directly in its parent group node.
68  return _egg_parent;
69  }
70 
71  // For other cases, we may have to create a subgroup to put the primitive
72  // into.
73  Parents::iterator pi;
74  pi = _parents.find(transform);
75  ParentNodes *nodes;
76  if (pi != _parents.end()) {
77  nodes = (*pi).second;
78  } else {
79  nodes = new ParentNodes;
80  _parents.insert(Parents::value_type(transform, nodes));
81  }
82 
83  switch (type) {
84  case FltGeometry::BT_axial:
85  if (nodes->_axial_billboard == nullptr) {
86  nodes->_axial_billboard = new EggGroup(name);
87  _egg_parent->add_child(nodes->_axial_billboard);
88  nodes->_axial_billboard->set_billboard_type(EggGroup::BT_axis);
89  if (!is_identity) {
90  set_transform(transform_bead, nodes->_axial_billboard);
91  nodes->_axial_billboard->set_group_type(EggGroup::GT_instance);
92  }
93  }
94  return nodes->_axial_billboard;
95 
96  case FltGeometry::BT_point:
97  if (nodes->_point_billboard == nullptr) {
98  nodes->_point_billboard = new EggGroup(name);
99  _egg_parent->add_child(nodes->_point_billboard);
100  nodes->_point_billboard->set_billboard_type(EggGroup::BT_point_world_relative);
101  if (!is_identity) {
102  set_transform(transform_bead, nodes->_point_billboard);
103  nodes->_point_billboard->set_group_type(EggGroup::GT_instance);
104  }
105  }
106  return nodes->_point_billboard;
107 
108  default: // Normally, BT_none, although we've occasionally seen a
109  // value of 3 come in here, whatever that's supposed to mean.
110  if (nodes->_plain == nullptr) {
111  nodes->_plain = new EggGroup(name);
112  _egg_parent->add_child(nodes->_plain);
113  if (!is_identity) {
114  set_transform(transform_bead, nodes->_plain);
115  nodes->_plain->set_group_type(EggGroup::GT_instance);
116  }
117  }
118  return nodes->_plain;
119  }
120 }
121 
122 /**
123  * Sets up the group to reflect the transform indicated by the given record,
124  * if any.
125  */
127 set_transform(const FltBead *flt_bead, EggGroup *egg_group) {
128  if (flt_bead->has_transform()) {
129  egg_group->set_group_type(EggGroup::GT_instance);
130 
131  int num_steps = flt_bead->get_num_transform_steps();
132  bool componentwise_ok = !_converter->_compose_transforms;
133 
134  if (num_steps == 0) {
135  componentwise_ok = false;
136  } else {
137  // Walk through each transform step and store the individual components
138  // in the egg file. If we come across a step we don't know how to
139  // interpret, just store the whole transform matrix in the egg file.
140  egg_group->clear_transform();
141  for (int i = num_steps -1; i >= 0 && componentwise_ok; i--) {
142  const FltTransformRecord *step = flt_bead->get_transform_step(i);
143  if (step->is_exact_type(FltTransformTranslate::get_class_type())) {
144  const FltTransformTranslate *trans;
145  DCAST_INTO_V(trans, step);
146  if (!trans->get_delta().almost_equal(LVector3d::zero())) {
147  egg_group->add_translate3d(trans->get_delta());
148  }
149 
150  } else if (step->is_exact_type(FltTransformRotateAboutPoint::get_class_type())) {
151  const FltTransformRotateAboutPoint *rap;
152  DCAST_INTO_V(rap, step);
153  if (!IS_NEARLY_ZERO(rap->get_angle())) {
154  if (!rap->get_center().almost_equal(LVector3d::zero())) {
155  egg_group->add_translate3d(-rap->get_center());
156  }
157  LVector3d axis = LCAST(double, rap->get_axis());
158  egg_group->add_rotate3d(rap->get_angle(), axis);
159  if (!rap->get_center().almost_equal(LVector3d::zero())) {
160  egg_group->add_translate3d(rap->get_center());
161  }
162  }
163 
164  } else if (step->is_exact_type(FltTransformRotateAboutEdge::get_class_type())) {
165  const FltTransformRotateAboutEdge *rae;
166  DCAST_INTO_V(rae, step);
167  if (!IS_NEARLY_ZERO(rae->get_angle())) {
168  if (!rae->get_point_a().almost_equal(LVector3d::zero())) {
169  egg_group->add_translate3d(-rae->get_point_a());
170  }
171  LVector3d axis = rae->get_point_b() - rae->get_point_a();
172  egg_group->add_rotate3d(rae->get_angle(), axis);
173  if (!rae->get_point_a().almost_equal(LVector3d::zero())) {
174  egg_group->add_translate3d(rae->get_point_a());
175  }
176  }
177 
178  } else if (step->is_exact_type(FltTransformScale::get_class_type())) {
179  const FltTransformScale *scale;
180  DCAST_INTO_V(scale, step);
181  if (!scale->get_scale().almost_equal(LVecBase3(1.0f, 1.0f, 1.0f))) {
182  if (scale->has_center() &&
183  !scale->get_center().almost_equal(LVector3d::zero())) {
184  egg_group->add_translate3d(-scale->get_center());
185  }
186  egg_group->add_scale3d(LCAST(double, scale->get_scale()));
187  if (scale->has_center() &&
188  !scale->get_center().almost_equal(LVector3d::zero())) {
189  egg_group->add_translate3d(scale->get_center());
190  }
191  }
192 
193  } else if (step->is_exact_type(FltTransformPut::get_class_type())) {
194  const FltTransformPut *put;
195  DCAST_INTO_V(put, step);
196 
197  if (!put->get_from_origin().almost_equal(LVector3d::zero())) {
198  egg_group->add_translate3d(-put->get_from_origin());
199  }
200  LQuaterniond q1, q2;
201  look_at(q1, put->get_from_align() - put->get_from_origin(),
202  put->get_from_track() - put->get_from_origin(),
203  CS_zup_right);
204  look_at(q2, put->get_to_align() - put->get_to_origin(),
205  put->get_to_track() - put->get_to_origin(),
206  CS_zup_right);
207 
208  LQuaterniond q = invert(q1) * q2;
209 
210  if (!q.is_identity()) {
211  egg_group->add_rotate3d(q);
212  }
213  if (!put->get_to_origin().almost_equal(LVector3d::zero())) {
214  egg_group->add_translate3d(put->get_to_origin());
215  }
216 
217  } else {
218  // Here's a transform component we haven't implemented here. Give
219  // up on storing the componentwise transform.
220  componentwise_ok = false;
221  }
222  }
223  }
224 
225  if (!componentwise_ok) {
226  egg_group->set_transform3d(flt_bead->get_transform());
227  }
228  }
229 }
A base class for nodes in the hierarchy that are not leaf nodes.
Definition: eggGroupNode.h:46
EggNode * add_child(EggNode *node)
Adds the indicated child to the group and returns it.
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
Definition: eggGroup.h:34
void clear_transform()
Resets the transform to empty, identity.
Definition: eggTransform.I:114
void add_scale3d(const LVecBase3d &scale)
Appends a possibly non-uniform scale to the current transform.
void set_transform3d(const LMatrix4d &mat)
Sets the overall transform as a 4x4 matrix.
Definition: eggTransform.I:188
void add_translate3d(const LVector3d &translate)
Appends a 3-d translation operation to the current transform.
void add_rotate3d(double angle, const LVector3d &axis)
Appends a 3-d rotation about an arbitrary axis to the current transform.
A base class for any of a broad family of flt records that represent particular beads in the hierarch...
Definition: fltBead.h:29
int get_num_transform_steps() const
Returns the number of individual steps that define the net transform on this bead as returned by set_...
Definition: fltBead.cxx:92
FltTransformRecord * get_transform_step(int n)
Returns the nth individual step that defines the net transform on this bead.
Definition: fltBead.cxx:101
const LMatrix4d & get_transform() const
Returns the single-precision 4x4 matrix that represents the transform applied to this bead,...
Definition: fltBead.cxx:58
bool has_transform() const
Returns true if the bead has been transformed, false otherwise.
Definition: fltBead.cxx:48
EggGroupNode * get_synthetic_group(const std::string &name, const FltBead *transform_bead, FltGeometry::BillboardType type=FltGeometry::BT_none)
Sometimes it is necessary to synthesize a group within a particular EggGroup, for instance to insert ...
void set_transform(const FltBead *flt_bead, EggGroup *egg_group)
Sets up the group to reflect the transform indicated by the given record, if any.
A "put", which is a MultiGen concept of defining a transformation by mapping three arbitrary points t...
A base class for a number of types of ancillary records that follow beads and indicate some kind of a...
A transformation that rotates about a particular axis in space, defined by two endpoints.
PN_stdfloat get_angle() const
Returns the angle of rotation, in degrees counterclockwise about the axis as seen from point a.
A transformation that rotates about a particular axis in space, defined by a point and vector.
PN_stdfloat get_angle() const
Returns the angle of rotation, in degrees counterclockwise about the axis.
A transformation that applies a (possibly nonuniform) scale.
A transformation that applies a translation.
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
Definition: typedObject.I:38
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.