Panda3D
Loading...
Searching...
No Matches
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"
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 */
29FltToEggLevelState::
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 */
40FltToEggLevelState::ParentNodes::
41ParentNodes() {
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 */
59get_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 */
127set_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())) {
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())) {
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.
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.
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.
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.