Panda3D

fltBead.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 fltBead.cxx
10 * @author drose
11 * @date 2000-08-24
12 */
13
14 #include "fltBead.h"
15 #include "fltRecordReader.h"
16 #include "fltRecordWriter.h"
17 #include "fltTransformGeneralMatrix.h"
18 #include "fltTransformPut.h"
19 #include "fltTransformRotateAboutEdge.h"
20 #include "fltTransformRotateAboutPoint.h"
21 #include "fltTransformScale.h"
22 #include "fltTransformTranslate.h"
23 #include "fltTransformRotateScale.h"
24 #include "config_flt.h"
25
26 #include "dcast.h"
27
28 #include <assert.h>
29
30 TypeHandle FltBead::_type_handle;
31
32 /**
33 *
34 */
35 FltBead::
36 FltBead(FltHeader *header) : FltRecord(header) {
37 _has_transform = false;
38 _transform = LMatrix4d::ident_mat();
39 _replicate_count = 0;
40 }
41
42 /**
43 * Returns true if the bead has been transformed, false otherwise. If this
44 * returns true, get_transform() will return the single-precision net
45 * transformation, and get_num_transform_steps() will return nonzero.
46 */
47 bool FltBead::
48 has_transform() const {
49 return _has_transform;
50 }
51
52 /**
53 * Returns the single-precision 4x4 matrix that represents the transform
54 * applied to this bead, or the identity matrix if the bead has not been
55 * transformed.
56 */
57 const LMatrix4d &FltBead::
58 get_transform() const {
59 return _has_transform ? _transform : LMatrix4d::ident_mat();
60 }
61
62 /**
63 * Replaces the transform matrix on this bead. This implicitly removes all of
64 * the transform steps added previously, and replaces them with a single 4x4
65 * general matrix transform step.
66 */
67 void FltBead::
68 set_transform(const LMatrix4d &mat) {
69 clear_transform();
70 FltTransformGeneralMatrix *step = new FltTransformGeneralMatrix(_header);
71 step->set_matrix(mat);
72 add_transform_step(step);
73 }
74
75 /**
76 * Removes any transform matrix and all transform steps on this bead.
77 */
78 void FltBead::
79 clear_transform() {
80 _has_transform = false;
81 _transform = LMatrix4d::ident_mat();
82 _transform_steps.clear();
83 }
84
85 /**
86 * Returns the number of individual steps that define the net transform on
87 * this bead as returned by set_transform(). Each step is a single
88 * transformation; the concatenation of all transformations will produce the
89 * matrix represented by set_transform().
90 */
91 int FltBead::
92 get_num_transform_steps() const {
93 return _transform_steps.size();
94 }
95
96 /**
97 * Returns the nth individual step that defines the net transform on this
98 * bead. See get_num_transform_steps().
99 */
100 FltTransformRecord *FltBead::
101 get_transform_step(int n) {
102 nassertr(n >= 0 && n < (int)_transform_steps.size(),
103 nullptr);
104 return _transform_steps[n];
105 }
106
107 /**
108 * Returns the nth individual step that defines the net transform on this
109 * bead. See get_num_transform_steps().
110 */
111 const FltTransformRecord *FltBead::
112 get_transform_step(int n) const {
113 nassertr(n >= 0 && n < (int)_transform_steps.size(),
114 nullptr);
115 return _transform_steps[n];
116 }
117
118 /**
119 * Applies the indicated transform step to the net transformation applied to
120 * the bead.
121 */
122 void FltBead::
123 add_transform_step(FltTransformRecord *record) {
124 if (!_has_transform) {
125 _has_transform = true;
126 _transform = record->get_matrix();
127 } else {
128 _transform = record->get_matrix() * _transform;
129 }
130 _transform_steps.push_back(record);
131 }
132
133 /**
134 * Returns the replicate count of this bead. If this is nonzero, it means
135 * that the bead is implicitly copied this number of additional times (for
136 * replicate_count + 1 total copies), applying the transform on this bead for
137 * each copy. In this case, the transform does *not* apply to the initial
138 * copy of the bead.
139 */
140 int FltBead::
141 get_replicate_count() const {
142 return _replicate_count;
143 }
144
145 /**
146 * Changes the replicate count of this bead. If you are setting the replicate
147 * count to some nonzero number, you must also set a transform on the bead.
148 * See set_replicate_count().
149 */
150 void FltBead::
151 set_replicate_count(int count) {
152 _replicate_count = count;
153 }
154
155 /**
156 * Fills in the information in this bead based on the information given in the
157 * indicated datagram, whose opcode has already been read. Returns true on
158 * success, false if the datagram is invalid.
159 */
160 bool FltBead::
161 extract_record(FltRecordReader &reader) {
162 if (!FltRecord::extract_record(reader)) {
163 return false;
164 }
165 return true;
166 }
167
168 /**
169 * Checks whether the given bead, which follows this bead sequentially in the
170 * file, is an ancillary record of this bead. If it is, extracts the relevant
171 * information and returns true; otherwise, leaves it alone and returns false.
172 */
173 bool FltBead::
174 extract_ancillary(FltRecordReader &reader) {
175 FltTransformRecord *step = nullptr;
176
177 switch (reader.get_opcode()) {
178 case FO_transform_matrix:
179 return extract_transform_matrix(reader);
180
181 case FO_general_matrix:
182 step = new FltTransformGeneralMatrix(_header);
183 break;
184
185 case FO_put:
186 step = new FltTransformPut(_header);
187 break;
188
189 case FO_rotate_about_edge:
190 step = new FltTransformRotateAboutEdge(_header);
191 break;
192
193 case FO_rotate_about_point:
194 step = new FltTransformRotateAboutPoint(_header);
195 break;
196
197 case FO_scale:
198 step = new FltTransformScale(_header);
199 break;
200
201 case FO_translate:
202 step = new FltTransformTranslate(_header);
203 break;
204
205 case FO_rotate_and_scale:
206 step = new FltTransformRotateScale(_header);
207 break;
208
209 case FO_replicate:
210 return extract_replicate_count(reader);
211
212 default:
213 return FltRecord::extract_ancillary(reader);
214 }
215
216 // A transform step.
217 nassertr(step != nullptr, false);
218 if (!step->extract_record(reader)) {
219 return false;
220 }
221 _transform_steps.push_back(DCAST(FltTransformRecord, step));
222
223 return true;
224 }
225
226 /**
227 * Fills up the current record on the FltRecordWriter with data for this
228 * record, but does not advance the writer. Returns true on success, false if
229 * there is some error.
230 */
231 bool FltBead::
232 build_record(FltRecordWriter &writer) const {
233 if (!FltRecord::build_record(writer)) {
234 return false;
235 }
236 return true;
237 }
238
239 /**
240 * Writes whatever ancillary records are required for this record. Returns
241 * FE_ok on success, or something else if there is some error.
242 */
243 FltError FltBead::
244 write_ancillary(FltRecordWriter &writer) const {
245 if (_has_transform) {
246 FltError result = write_transform(writer);
247 if (result != FE_ok) {
248 return result;
249 }
250 }
251 if (_replicate_count != 0) {
252 FltError result = write_replicate_count(writer);
253 if (result != FE_ok) {
254 return result;
255 }
256 }
257
258
259 return FltRecord::write_ancillary(writer);
260 }
261
262 /**
263 * Reads a transform matrix ancillary bead. This defines the net
264 * transformation that has been applied to the bead, and precedes the set of
265 * individual transform steps that define how this net transform was computed.
266 */
267 bool FltBead::
268 extract_transform_matrix(FltRecordReader &reader) {
269 nassertr(reader.get_opcode() == FO_transform_matrix, false);
270 DatagramIterator &iterator = reader.get_iterator();
271
272 LMatrix4d matrix;
273 for (int r = 0; r < 4; r++) {
274 for (int c = 0; c < 4; c++) {
275 matrix(r, c) = iterator.get_be_float32();
276 }
277 }
278 check_remaining_size(iterator);
279
280 _transform_steps.clear();
281 _has_transform = true;
282 _transform = matrix;
283
284 return true;
285 }
286
287 /**
288 * Reads a replicate count ancillary bead.
289 */
290 bool FltBead::
291 extract_replicate_count(FltRecordReader &reader) {
292 nassertr(reader.get_opcode() == FO_replicate, false);
293 DatagramIterator &iterator = reader.get_iterator();
294
295 _replicate_count = iterator.get_be_int16();
296 iterator.skip_bytes(2);
297
298 check_remaining_size(iterator);
299 return true;
300 }
301
302 /**
303 * Writes out the transformation and all of its defining steps.
304 */
305 FltError FltBead::
306 write_transform(FltRecordWriter &writer) const {
307 // First, write out the initial transform indication.
308 writer.set_opcode(FO_transform_matrix);
309 Datagram &datagram = writer.update_datagram();
310
311 for (int r = 0; r < 4; r++) {
312 for (int c = 0; c < 4; c++) {
313 datagram.add_be_float32(_transform(r, c));
314 }
315 }
316
317 FltError result = writer.advance();
318 if (result != FE_ok) {
319 return result;
320 }
321
322 // Now, write out each of the steps of the transform.
323 Transforms::const_iterator ti;
324 for (ti = _transform_steps.begin(); ti != _transform_steps.end(); ++ti) {
325 if (!(*ti)->build_record(writer)) {
326 assert(!flt_error_abort);
327 return FE_invalid_record;
328 }
329 FltError result = writer.advance();
330 if (result != FE_ok) {
331 return result;
332 }
333 }
334
335 return FE_ok;
336 }
337
338 /**
339 * Writes out the replicate count, if needed.
340 */
341 FltError FltBead::
342 write_replicate_count(FltRecordWriter &writer) const {
343 if (_replicate_count != 0) {
344 writer.set_opcode(FO_replicate);
345 Datagram &datagram = writer.update_datagram();
346
347 datagram.add_be_int16(_replicate_count);
348 datagram.pad_bytes(2);
349
350 FltError result = writer.advance();
351 if (result != FE_ok) {
352 return result;
353 }
354 }
355
356 return FE_ok;
357 }
DatagramIterator
A class to retrieve the individual data elements previously stored in a Datagram.
Definition: datagramIterator.h:27
DatagramIterator::skip_bytes
void skip_bytes(size_t size)
Skips over the indicated number of bytes in the datagram.
Definition: datagramIterator.I:423
DatagramIterator::get_be_float32
PN_float32 get_be_float32()
Extracts a 32-bit big-endian single-precision floating-point number.
Definition: datagramIterator.I:369
DatagramIterator::get_be_int16
int16_t get_be_int16()
Extracts a signed 16-bit big-endian integer.
Definition: datagramIterator.I:255
Datagram
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
Datagram::add_be_float32
void add_be_float32(PN_float32 value)
Adds a 32-bit single-precision big-endian floating-point number to the datagram.
Definition: datagram.I:200
Datagram::add_be_int16
void add_be_int16(int16_t value)
Adds a signed 16-bit big-endian integer to the datagram.
Definition: datagram.I:145
Datagram::pad_bytes
void pad_bytes(size_t size)
Adds the indicated number of zero bytes to the datagram.
Definition: datagram.cxx:99
FltBead::get_num_transform_steps
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
FltBead::clear_transform
void clear_transform()
Removes any transform matrix and all transform steps on this bead.
Definition: fltBead.cxx:79
FltBead::get_replicate_count
int get_replicate_count() const
Returns the replicate count of this bead.
Definition: fltBead.cxx:141
FltBead::add_transform_step
void add_transform_step(FltTransformRecord *record)
Applies the indicated transform step to the net transformation applied to the bead.
Definition: fltBead.cxx:123
FltBead::get_transform_step
FltTransformRecord * get_transform_step(int n)
Returns the nth individual step that defines the net transform on this bead.
Definition: fltBead.cxx:101
FltBead::get_transform
const LMatrix4d & get_transform() const
Returns the single-precision 4x4 matrix that represents the transform applied to this bead,...
Definition: fltBead.cxx:58
FltBead::set_transform
void set_transform(const LMatrix4d &mat)
Replaces the transform matrix on this bead.
Definition: fltBead.cxx:68
FltBead::set_replicate_count
void set_replicate_count(int count)
Changes the replicate count of this bead.
Definition: fltBead.cxx:151
FltBead::has_transform
bool has_transform() const
Returns true if the bead has been transformed, false otherwise.
Definition: fltBead.cxx:48
FltHeader
This is the first bead in the file, the top of the bead hierarchy, and the primary interface to readi...
Definition: fltHeader.h:44
FltRecordReader
This class turns an istream into a sequence of FltRecords by reading a sequence of Datagrams and extr...
Definition: fltRecordReader.h:30
FltRecordReader::get_opcode
FltOpcode get_opcode() const
Returns the opcode associated with the current record.
Definition: fltRecordReader.cxx:55
FltRecordReader::get_iterator
DatagramIterator & get_iterator()
Returns an iterator suitable for extracting data from the current record.
Definition: fltRecordReader.cxx:64
FltRecordWriter
This class writes a sequence of FltRecords to an ostream, handling opcode and size counts properly.
Definition: fltRecordWriter.h:31
FltRecordWriter::set_opcode
void set_opcode(FltOpcode opcode)
Sets the opcode associated with the current record.
Definition: fltRecordWriter.cxx:47
FltRecordWriter::advance
FltError advance()
Writes the current record to the flt file, and resets the current record to receive new data.
Definition: fltRecordWriter.cxx:75
FltRecordWriter::update_datagram
Datagram & update_datagram()
Returns a modifiable reference to the datagram associated with the current record.
Definition: fltRecordWriter.cxx:66
FltRecord
The base class for all kinds of records in a MultiGen OpenFlight file.
Definition: fltRecord.h:36
FltRecord::check_remaining_size
void check_remaining_size(const DatagramIterator &di, const std::string &name=std::string()) const
Checks that the iterator has no bytes left, as it should at the end of a successfully read record.
Definition: fltRecord.cxx:254
FltTransformGeneralMatrix
A general 4x4 matrix.
Definition: fltTransformGeneralMatrix.h:25
FltTransformGeneralMatrix::set_matrix
void set_matrix(const LMatrix4d &matrix)
Directly sets the general matrix.
Definition: fltTransformGeneralMatrix.cxx:31
FltTransformPut
A "put", which is a MultiGen concept of defining a transformation by mapping three arbitrary points t...
Definition: fltTransformPut.h:25
FltTransformRecord
A base class for a number of types of ancillary records that follow beads and indicate some kind of a...
Definition: fltTransformRecord.h:28
FltTransformRotateAboutEdge
A transformation that rotates about a particular axis in space, defined by two endpoints.
Definition: fltTransformRotateAboutEdge.h:25
FltTransformRotateAboutPoint
A transformation that rotates about a particular axis in space, defined by a point and vector.
Definition: fltTransformRotateAboutPoint.h:25
FltTransformRotateScale
A combination rotation and scale.
Definition: fltTransformRotateScale.h:25
FltTransformScale
A transformation that applies a (possibly nonuniform) scale.
Definition: fltTransformScale.h:24
FltTransformTranslate
A transformation that applies a translation.
Definition: fltTransformTranslate.h:24
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
config_flt.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
dcast.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
fltBead.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
fltRecordReader.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
fltRecordWriter.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
fltTransformGeneralMatrix.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
fltTransformPut.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
fltTransformRotateAboutEdge.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
fltTransformRotateAboutPoint.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
fltTransformRotateScale.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
fltTransformScale.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
fltTransformTranslate.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.