Panda3D
Loading...
Searching...
No Matches
eggXfmAnimData.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 eggXfmAnimData.cxx
10 * @author drose
11 * @date 1999-02-19
12 */
13
14#include "eggXfmAnimData.h"
15#include "eggXfmSAnim.h"
16#include "eggSAnimData.h"
17#include "eggMiscFuncs.h"
18#include "config_egg.h"
19
20#include "indent.h"
21#include "luse.h"
22#include "lmatrix.h"
23#include "compose_matrix.h"
24#include "dcast.h"
25
26TypeHandle EggXfmAnimData::_type_handle;
27
28
29/**
30 * Converts the newer-style XfmSAnim table to the older-style XfmAnim table.
31 */
32EggXfmAnimData::
33EggXfmAnimData(const EggXfmSAnim &convert_from)
34 : EggAnimData(convert_from.get_name())
35{
36 if (convert_from.has_order()) {
37 set_order(convert_from.get_order());
38 }
39 if (convert_from.has_fps()) {
40 set_fps(convert_from.get_fps());
41 }
42 _coordsys = convert_from.get_coordinate_system();
43
44 // First, get the table names so we know how to build up our contents
45 // string. Also store up the SAnim tables themselves in a temporary vector
46 // for convenience.
47
49
50 EggXfmSAnim::const_iterator ci;
51 for (ci = convert_from.begin(); ci != convert_from.end(); ++ci) {
52 if ((*ci)->is_of_type(EggSAnimData::get_class_type())) {
53 EggSAnimData *sanim = DCAST(EggSAnimData, *ci);
54 nassertv(sanim->get_name().length() == 1);
55
56 if (sanim->get_num_rows() > 0) {
57 subtables.push_back(sanim);
58 _contents += sanim->get_name()[0];
59 }
60 }
61 }
62
63 // Now, go through and extract out all the data.
64 int num_rows = convert_from.get_num_rows();
65 for (int row = 0; row < num_rows; row++) {
66 for (int col = 0; col < (int)subtables.size(); col++) {
67 EggSAnimData *sanim = subtables[col];
68 if (sanim->get_num_rows() == 1) {
69 add_data(sanim->get_value(0));
70 } else {
71 nassertv(row < sanim->get_num_rows());
72 add_data(sanim->get_value(row));
73 }
74 }
75 }
76}
77
78
79/**
80 * Returns the value of the aggregate row of the table as a matrix. This is a
81 * convenience function that treats the 2-d table as if it were a single table
82 * of matrices.
83 */
85get_value(int row, LMatrix4d &mat) const {
86 LVector3d scale(1.0, 1.0, 1.0);
87 LVector3d shear(0.0, 0.0, 0.0);
88 LVector3d hpr(0.0, 0.0, 0.0);
89 LVector3d translate(0.0, 0.0, 0.0);
90
91 for (int col = 0; col < get_num_cols(); col++) {
92 double value = get_value(row, col);
93
94 switch (_contents[col]) {
95 case 'i':
96 scale[0] = value;
97 break;
98
99 case 'j':
100 scale[1] = value;
101 break;
102
103 case 'k':
104 scale[2] = value;
105 break;
106
107 case 'a':
108 shear[0] = value;
109 break;
110
111 case 'b':
112 shear[1] = value;
113 break;
114
115 case 'c':
116 shear[2] = value;
117 break;
118
119 case 'h':
120 hpr[0] = value;
121 break;
122
123 case 'p':
124 hpr[1] = value;
125 break;
126
127 case 'r':
128 hpr[2] = value;
129 break;
130
131 case 'x':
132 translate[0] = value;
133 break;
134
135 case 'y':
136 translate[1] = value;
137 break;
138
139 case 'z':
140 translate[2] = value;
141 break;
142
143 default:
144 // The contents string contained an invalid letter.
145 nassert_raise("invalid letter in contents string");
146 return;
147 }
148 }
149
150 // So now we've got the twelve components; build a matrix.
151 EggXfmSAnim::compose_with_order(mat, scale, shear, hpr, translate, get_order(),
152 _coordsys);
153}
154
155/**
156 * Returns true if this node represents a table of animation transformation
157 * data, false otherwise.
158 */
160is_anim_matrix() const {
161 return true;
162}
163
164/**
165 * Writes the data to the indicated output stream in Egg format.
166 */
168write(std::ostream &out, int indent_level) const {
169 write_header(out, indent_level, "<Xfm$Anim>");
170
171 if (has_fps()) {
172 indent(out, indent_level + 2)
173 << "<Scalar> fps { " << get_fps() << " }\n";
174 }
175
176 if (has_order()) {
177 indent(out, indent_level + 2)
178 << "<Char*> order { " << get_order() << " }\n";
179 }
180
181 if (has_contents()) {
182 indent(out, indent_level + 2)
183 << "<Char*> contents { " << get_contents() << " }\n";
184 }
185
186 indent(out, indent_level + 2) << "<V> {\n";
187 write_long_list(out, indent_level + 4, _data.begin(), _data.end(),
188 "", "", 72);
189 indent(out, indent_level + 2) << "}\n";
190 indent(out, indent_level) << "}\n";
191}
192
193/**
194 * Applies the indicated transform to all the rows of the table. This
195 * actually forces the generation of a totally new set of rows.
196 */
197void EggXfmAnimData::
198r_transform(const LMatrix4d &mat, const LMatrix4d &inv,
199 CoordinateSystem to_cs) {
200 // We need to build an inverse matrix that doesn't reflect the translation
201 // component.
202 LMatrix4d inv1 = inv;
203 inv1.set_row(3, LVector3d(0.0, 0.0, 0.0));
204
205 // Now we build a temporary copy of the table as an EggXfmSAnim. We do this
206 // because this kind of table is easier to build and optimize.
207
208 if (to_cs == CS_default) {
209 to_cs = _coordsys;
210 }
211
212 EggXfmSAnim new_table(get_name(), to_cs);
213 if (has_fps()) {
214 new_table.set_fps(get_fps());
215 }
216
217 // We insist on the standard order now.
218 new_table.set_order(get_standard_order());
219
220 // Now build up the data into the new table.
221 LMatrix4d orig_mat;
222 for (int r = 0; r < get_num_rows(); r++) {
223 get_value(r, orig_mat);
224 bool result = new_table.add_data(inv1 * orig_mat * mat);
225
226 if (!result) {
227 egg_cat.error()
228 << "Transform from " << _coordsys << " to " << to_cs
229 << " failed!\n";
230 LVector3d scale, shear, hpr, trans;
231 bool d = decompose_matrix(orig_mat, scale, shear, hpr, trans, _coordsys);
232 egg_cat.error(false)
233 << "orig:\n" << orig_mat
234 << "d = " << d
235 << "\n scale: " << scale
236 << "\n shear: " << shear
237 << "\n hpr: " << hpr
238 << "\n trans: " << trans << "\n";
239
240 LMatrix4d new_mat = inv1 * orig_mat * mat;
241 d = decompose_matrix(new_mat, scale, shear, hpr, trans, to_cs);
242 egg_cat.error(false)
243 << "new:\n" << new_mat
244 << "d = " << d
245 << "\n scale: " << scale
246 << "\n shear: " << shear
247 << "\n hpr: " << hpr
248 << "\n trans: " << trans << "\n";
249 }
250
251 // If this assertion fails, we attempted to transform by non-affine matrix
252 // or some such thing that cannot be represented in an anim file.
253 nassertv(result);
254 }
255
256 // Now clean out the redundant columns we created.
257 new_table.optimize();
258
259 // And copy that back into EggXfmAnimData table form.
260 EggXfmAnimData copy_table(new_table);
261 (*this) = copy_table;
262}
263
264/**
265 * This is only called immediately after loading an egg file from disk, to
266 * propagate the value found in the CoordinateSystem entry (or the default
267 * Y-up coordinate system) to all nodes that care about what the coordinate
268 * system is.
269 */
270void EggXfmAnimData::
271r_mark_coordsys(CoordinateSystem cs) {
272 _coordsys = cs;
273}
A base class for EggSAnimData and EggXfmAnimData, which contain rows and columns of numbers.
Definition eggAnimData.h:30
double get_fps() const
This is only valid if has_fps() returns true.
Definition eggAnimData.I:79
void add_data(double value)
Adds a single element to the table.
Definition eggAnimData.I:97
void write_header(std::ostream &out, int indent_level, const char *egg_keyword) const
Writes the first line of the egg object, e.g.
Corresponding to an entry, this stores a single column of numbers, for instance for a morph target,...
double get_value(int row) const
Returns the value at the indicated row.
int get_num_rows() const
Returns the number of rows in the table.
Corresponding to an <Xfm$Anim> entry, this stores a two-dimensional table with up to nine columns,...
static const std::string & get_standard_order()
Returns the standard order of matrix component composition.
int get_num_cols() const
Returns the number of columns in the table.
virtual void write(std::ostream &out, int indent_level) const
Writes the data to the indicated output stream in Egg format.
int get_num_rows() const
Returns the number of rows in the table.
double get_value(int row, int col) const
Returns the value at the indicated row.
virtual bool is_anim_matrix() const
Returns true if this node represents a table of animation transformation data, false otherwise.
This corresponds to an <Xfm$Anim_S$> entry, which is a collection of up to nine entries that specify...
Definition eggXfmSAnim.h:28
CoordinateSystem get_coordinate_system() const
Returns the coordinate system this table believes it is defined within.
int get_num_rows() const
Returns the effective number of rows in the table.
static void compose_with_order(LMatrix4d &mat, const LVecBase3d &scale, const LVecBase3d &shear, const LVecBase3d &hpr, const LVecBase3d &trans, const std::string &order, CoordinateSystem cs)
Composes a matrix out of the nine individual components, respecting the order string.
double get_fps() const
This is only valid if has_fps() returns true.
Definition eggXfmSAnim.I:82
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
This is our own Panda specialization on the default STL vector.
Definition pvector.h:42
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.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition indent.cxx:20
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.