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"
18 #include "fltTransformPut.h"
21 #include "fltTransformScale.h"
22 #include "fltTransformTranslate.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) {
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::
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::
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  */
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  */
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::
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::
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::
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 }
A transformation that applies a (possibly nonuniform) scale.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A "put", which is a MultiGen concept of defining a transformation by mapping three arbitrary points t...
void set_transform(const LMatrix4d &mat)
Replaces the transform matrix on this bead.
Definition: fltBead.cxx:68
This class writes a sequence of FltRecords to an ostream, handling opcode and size counts properly.
This class turns an istream into a sequence of FltRecords by reading a sequence of Datagrams and extr...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
FltTransformRecord * get_transform_step(int n)
Returns the nth individual step that defines the net transform on this bead.
Definition: fltBead.cxx:101
void add_transform_step(FltTransformRecord *record)
Applies the indicated transform step to the net transformation applied to the bead.
Definition: fltBead.cxx:123
PN_float32 get_be_float32()
Extracts a 32-bit big-endian single-precision floating-point number.
const LMatrix4d & get_transform() const
Returns the single-precision 4x4 matrix that represents the transform applied to this bead,...
Definition: fltBead.cxx:58
A transformation that applies a translation.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
DatagramIterator & get_iterator()
Returns an iterator suitable for extracting data from the current record.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void pad_bytes(size_t size)
Adds the indicated number of zero bytes to the datagram.
Definition: datagram.cxx:99
This is the first bead in the file, the top of the bead hierarchy, and the primary interface to readi...
Definition: fltHeader.h:44
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void set_matrix(const LMatrix4d &matrix)
Directly sets the general matrix.
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
bool has_transform() const
Returns true if the bead has been transformed, false otherwise.
Definition: fltBead.cxx:48
The base class for all kinds of records in a MultiGen OpenFlight file.
Definition: fltRecord.h:36
void add_be_int16(int16_t value)
Adds a signed 16-bit big-endian integer to the datagram.
Definition: datagram.I:145
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void clear_transform()
Removes any transform matrix and all transform steps on this bead.
Definition: fltBead.cxx:79
FltError advance()
Writes the current record to the flt file, and resets the current record to receive new data.
FltOpcode get_opcode() const
Returns the opcode associated with the current record.
A base class for a number of types of ancillary records that follow beads and indicate some kind of a...
A combination rotation and scale.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A transformation that rotates about a particular axis in space, defined by two endpoints.
A class to retrieve the individual data elements previously stored in a Datagram.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
void set_replicate_count(int count)
Changes the replicate count of this bead.
Definition: fltBead.cxx:151
int get_replicate_count() const
Returns the replicate count of this bead.
Definition: fltBead.cxx:141
void set_opcode(FltOpcode opcode)
Sets the opcode associated with the current record.
Datagram & update_datagram()
Returns a modifiable reference to the datagram associated with the current record.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
A transformation that rotates about a particular axis in space, defined by a point and vector.