Panda3D
Loading...
Searching...
No Matches
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"
18#include "fltTransformPut.h"
21#include "fltTransformScale.h"
24#include "config_flt.h"
25
26#include "dcast.h"
27
28#include <assert.h>
29
30TypeHandle FltBead::_type_handle;
31
32/**
33 *
34 */
35FltBead::
36FltBead(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 */
48has_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 */
57const LMatrix4d &FltBead::
58get_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 */
68set_transform(const LMatrix4d &mat) {
71 step->set_matrix(mat);
73}
74
75/**
76 * Removes any transform matrix and all transform steps on this bead.
77 */
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 */
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 */
101get_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 */
112get_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 */
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 */
141get_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 */
151set_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 */
160bool FltBead::
161extract_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 */
173bool FltBead::
174extract_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 */
231bool FltBead::
232build_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 */
243FltError FltBead::
244write_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 */
267bool FltBead::
268extract_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 */
290bool FltBead::
291extract_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 */
305FltError FltBead::
306write_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 */
341FltError FltBead::
342write_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}
A class to retrieve the individual data elements previously stored in a Datagram.
void skip_bytes(size_t size)
Skips over the indicated number of bytes in the datagram.
PN_float32 get_be_float32()
Extracts a 32-bit big-endian single-precision floating-point number.
int16_t get_be_int16()
Extracts a signed 16-bit big-endian integer.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition datagram.h:38
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
void add_be_int16(int16_t value)
Adds a signed 16-bit big-endian integer to the datagram.
Definition datagram.I:145
void pad_bytes(size_t size)
Adds the indicated number of zero bytes to the datagram.
Definition datagram.cxx:99
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
void clear_transform()
Removes any transform matrix and all transform steps on this bead.
Definition fltBead.cxx:79
int get_replicate_count() const
Returns the replicate count of this bead.
Definition fltBead.cxx:141
void add_transform_step(FltTransformRecord *record)
Applies the indicated transform step to the net transformation applied to the bead.
Definition fltBead.cxx:123
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
void set_transform(const LMatrix4d &mat)
Replaces the transform matrix on this bead.
Definition fltBead.cxx:68
void set_replicate_count(int count)
Changes the replicate count of this bead.
Definition fltBead.cxx:151
bool has_transform() const
Returns true if the bead has been transformed, false otherwise.
Definition fltBead.cxx:48
This is the first bead in the file, the top of the bead hierarchy, and the primary interface to readi...
Definition fltHeader.h:44
This class turns an istream into a sequence of FltRecords by reading a sequence of Datagrams and extr...
FltOpcode get_opcode() const
Returns the opcode associated with the current record.
DatagramIterator & get_iterator()
Returns an iterator suitable for extracting data from the current record.
This class writes a sequence of FltRecords to an ostream, handling opcode and size counts properly.
void set_opcode(FltOpcode opcode)
Sets the opcode associated with the current record.
FltError advance()
Writes the current record to the flt file, and resets the current record to receive new data.
Datagram & update_datagram()
Returns a modifiable reference to the datagram associated with the current record.
The base class for all kinds of records in a MultiGen OpenFlight file.
Definition fltRecord.h:36
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.
void set_matrix(const LMatrix4d &matrix)
Directly sets the general matrix.
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.
A transformation that rotates about a particular axis in space, defined by a point and vector.
A combination rotation and scale.
A transformation that applies a (possibly nonuniform) scale.
A transformation that applies a translation.
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.