Panda3D
 All Classes Functions Variables Enumerations
fltBead.cxx
00001 // Filename: fltBead.cxx
00002 // Created by:  drose (24Aug00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "fltBead.h"
00016 #include "fltRecordReader.h"
00017 #include "fltRecordWriter.h"
00018 #include "fltTransformGeneralMatrix.h"
00019 #include "fltTransformPut.h"
00020 #include "fltTransformRotateAboutEdge.h"
00021 #include "fltTransformRotateAboutPoint.h"
00022 #include "fltTransformScale.h"
00023 #include "fltTransformTranslate.h"
00024 #include "fltTransformRotateScale.h"
00025 #include "config_flt.h"
00026 
00027 #include "dcast.h"
00028 
00029 #include <assert.h>
00030 
00031 TypeHandle FltBead::_type_handle;
00032 
00033 ////////////////////////////////////////////////////////////////////
00034 //     Function: FltBead::Constructor
00035 //       Access: Public
00036 //  Description:
00037 ////////////////////////////////////////////////////////////////////
00038 FltBead::
00039 FltBead(FltHeader *header) : FltRecord(header) {
00040   _has_transform = false;
00041   _transform = LMatrix4d::ident_mat();
00042   _replicate_count = 0;
00043 }
00044 
00045 ////////////////////////////////////////////////////////////////////
00046 //     Function: FltBead::has_transform
00047 //       Access: Public
00048 //  Description: Returns true if the bead has been transformed, false
00049 //               otherwise.  If this returns true, get_transform()
00050 //               will return the single-precision net transformation,
00051 //               and get_num_transform_steps() will return nonzero.
00052 ////////////////////////////////////////////////////////////////////
00053 bool FltBead::
00054 has_transform() const {
00055   return _has_transform;
00056 }
00057 
00058 ////////////////////////////////////////////////////////////////////
00059 //     Function: FltBead::get_transform
00060 //       Access: Public
00061 //  Description: Returns the single-precision 4x4 matrix that
00062 //               represents the transform applied to this bead, or the
00063 //               identity matrix if the bead has not been transformed.
00064 ////////////////////////////////////////////////////////////////////
00065 const LMatrix4d &FltBead::
00066 get_transform() const {
00067   return _has_transform ? _transform : LMatrix4d::ident_mat();
00068 }
00069 
00070 ////////////////////////////////////////////////////////////////////
00071 //     Function: FltBead::set_transform
00072 //       Access: Public
00073 //  Description: Replaces the transform matrix on this bead.  This
00074 //               implicitly removes all of the transform steps added
00075 //               previously, and replaces them with a single 4x4
00076 //               general matrix transform step.
00077 ////////////////////////////////////////////////////////////////////
00078 void FltBead::
00079 set_transform(const LMatrix4d &mat) {
00080   clear_transform();
00081   FltTransformGeneralMatrix *step = new FltTransformGeneralMatrix(_header);
00082   step->set_matrix(mat);
00083   add_transform_step(step);
00084 }
00085 
00086 ////////////////////////////////////////////////////////////////////
00087 //     Function: FltBead::clear_transform
00088 //       Access: Public
00089 //  Description: Removes any transform matrix and all transform steps
00090 //               on this bead.
00091 ////////////////////////////////////////////////////////////////////
00092 void FltBead::
00093 clear_transform() {
00094   _has_transform = false;
00095   _transform = LMatrix4d::ident_mat();
00096   _transform_steps.clear();
00097 }
00098 
00099 ////////////////////////////////////////////////////////////////////
00100 //     Function: FltBead::get_num_transform_steps
00101 //       Access: Public
00102 //  Description: Returns the number of individual steps that define
00103 //               the net transform on this bead as returned by
00104 //               set_transform().  Each step is a single
00105 //               transformation; the concatenation of all
00106 //               transformations will produce the matrix represented
00107 //               by set_transform().
00108 ////////////////////////////////////////////////////////////////////
00109 int FltBead::
00110 get_num_transform_steps() const {
00111   return _transform_steps.size();
00112 }
00113 
00114 ////////////////////////////////////////////////////////////////////
00115 //     Function: FltBead::get_transform_step
00116 //       Access: Public
00117 //  Description: Returns the nth individual step that defines
00118 //               the net transform on this bead.  See
00119 //               get_num_transform_steps().
00120 ////////////////////////////////////////////////////////////////////
00121 FltTransformRecord *FltBead::
00122 get_transform_step(int n) {
00123   nassertr(n >= 0 && n < (int)_transform_steps.size(),
00124            (FltTransformRecord *)NULL);
00125   return _transform_steps[n];
00126 }
00127 
00128 ////////////////////////////////////////////////////////////////////
00129 //     Function: FltBead::get_transform_step
00130 //       Access: Public
00131 //  Description: Returns the nth individual step that defines
00132 //               the net transform on this bead.  See
00133 //               get_num_transform_steps().
00134 ////////////////////////////////////////////////////////////////////
00135 const FltTransformRecord *FltBead::
00136 get_transform_step(int n) const {
00137   nassertr(n >= 0 && n < (int)_transform_steps.size(),
00138            (const FltTransformRecord *)NULL);
00139   return _transform_steps[n];
00140 }
00141 
00142 ////////////////////////////////////////////////////////////////////
00143 //     Function: FltBead::add_transform_step
00144 //       Access: Public
00145 //  Description: Applies the indicated transform step to the net
00146 //               transformation applied to the bead.
00147 ////////////////////////////////////////////////////////////////////
00148 void FltBead::
00149 add_transform_step(FltTransformRecord *record) {
00150   if (!_has_transform) {
00151     _has_transform = true;
00152     _transform = record->get_matrix();
00153   } else {
00154     _transform = record->get_matrix() * _transform;
00155   }
00156   _transform_steps.push_back(record);
00157 }
00158 
00159 ////////////////////////////////////////////////////////////////////
00160 //     Function: FltBead::get_replicate_count
00161 //       Access: Public
00162 //  Description: Returns the replicate count of this bead.  If this is
00163 //               nonzero, it means that the bead is implicitly copied
00164 //               this number of additional times (for replicate_count
00165 //               + 1 total copies), applying the transform on this
00166 //               bead for each copy.  In this case, the transform does
00167 //               *not* apply to the initial copy of the bead.
00168 ////////////////////////////////////////////////////////////////////
00169 int FltBead::
00170 get_replicate_count() const {
00171   return _replicate_count;
00172 }
00173 
00174 ////////////////////////////////////////////////////////////////////
00175 //     Function: FltBead::set_replicate_count
00176 //       Access: Public
00177 //  Description: Changes the replicate count of this bead.  If you are
00178 //               setting the replicate count to some nonzero number,
00179 //               you must also set a transform on the bead.  See
00180 //               set_replicate_count().
00181 ////////////////////////////////////////////////////////////////////
00182 void FltBead::
00183 set_replicate_count(int count) {
00184   _replicate_count = count;
00185 }
00186 
00187 ////////////////////////////////////////////////////////////////////
00188 //     Function: FltBead::extract_record
00189 //       Access: Protected, Virtual
00190 //  Description: Fills in the information in this bead based on the
00191 //               information given in the indicated datagram, whose
00192 //               opcode has already been read.  Returns true on
00193 //               success, false if the datagram is invalid.
00194 ////////////////////////////////////////////////////////////////////
00195 bool FltBead::
00196 extract_record(FltRecordReader &reader) {
00197   if (!FltRecord::extract_record(reader)) {
00198     return false;
00199   }
00200   return true;
00201 }
00202 
00203 ////////////////////////////////////////////////////////////////////
00204 //     Function: FltBead::extract_ancillary
00205 //       Access: Protected, Virtual
00206 //  Description: Checks whether the given bead, which follows this
00207 //               bead sequentially in the file, is an ancillary record
00208 //               of this bead.  If it is, extracts the relevant
00209 //               information and returns true; otherwise, leaves it
00210 //               alone and returns false.
00211 ////////////////////////////////////////////////////////////////////
00212 bool FltBead::
00213 extract_ancillary(FltRecordReader &reader) {
00214   FltTransformRecord *step = (FltTransformRecord *)NULL;
00215 
00216   switch (reader.get_opcode()) {
00217   case FO_transform_matrix:
00218     return extract_transform_matrix(reader);
00219 
00220   case FO_general_matrix:
00221     step = new FltTransformGeneralMatrix(_header);
00222     break;
00223 
00224   case FO_put:
00225     step = new FltTransformPut(_header);
00226     break;
00227 
00228   case FO_rotate_about_edge:
00229     step = new FltTransformRotateAboutEdge(_header);
00230     break;
00231 
00232   case FO_rotate_about_point:
00233     step = new FltTransformRotateAboutPoint(_header);
00234     break;
00235 
00236   case FO_scale:
00237     step = new FltTransformScale(_header);
00238     break;
00239 
00240   case FO_translate:
00241     step = new FltTransformTranslate(_header);
00242     break;
00243 
00244   case FO_rotate_and_scale:
00245     step = new FltTransformRotateScale(_header);
00246     break;
00247 
00248   case FO_replicate:
00249     return extract_replicate_count(reader);
00250 
00251   default:
00252     return FltRecord::extract_ancillary(reader);
00253   }
00254 
00255   // A transform step.
00256   nassertr(step != (FltTransformRecord *)NULL, false);
00257   if (!step->extract_record(reader)) {
00258     return false;
00259   }
00260   _transform_steps.push_back(DCAST(FltTransformRecord, step));
00261 
00262   return true;
00263 }
00264 
00265 ////////////////////////////////////////////////////////////////////
00266 //     Function: FltBead::build_record
00267 //       Access: Protected, Virtual
00268 //  Description: Fills up the current record on the FltRecordWriter with
00269 //               data for this record, but does not advance the
00270 //               writer.  Returns true on success, false if there is
00271 //               some error.
00272 ////////////////////////////////////////////////////////////////////
00273 bool FltBead::
00274 build_record(FltRecordWriter &writer) const {
00275   if (!FltRecord::build_record(writer)) {
00276     return false;
00277   }
00278   return true;
00279 }
00280 
00281 ////////////////////////////////////////////////////////////////////
00282 //     Function: FltBead::write_ancillary
00283 //       Access: Protected, Virtual
00284 //  Description: Writes whatever ancillary records are required for
00285 //               this record.  Returns FE_ok on success, or something
00286 //               else if there is some error.
00287 ////////////////////////////////////////////////////////////////////
00288 FltError FltBead::
00289 write_ancillary(FltRecordWriter &writer) const {
00290   if (_has_transform) {
00291     FltError result = write_transform(writer);
00292     if (result != FE_ok) {
00293       return result;
00294     }
00295   }
00296   if (_replicate_count != 0) {
00297     FltError result = write_replicate_count(writer);
00298     if (result != FE_ok) {
00299       return result;
00300     }
00301   }
00302 
00303 
00304   return FltRecord::write_ancillary(writer);
00305 }
00306 
00307 ////////////////////////////////////////////////////////////////////
00308 //     Function: FltBead::extract_transform_matrix
00309 //       Access: Private
00310 //  Description: Reads a transform matrix ancillary bead.  This
00311 //               defines the net transformation that has been applied
00312 //               to the bead, and precedes the set of individual
00313 //               transform steps that define how this net transform
00314 //               was computed.
00315 ////////////////////////////////////////////////////////////////////
00316 bool FltBead::
00317 extract_transform_matrix(FltRecordReader &reader) {
00318   nassertr(reader.get_opcode() == FO_transform_matrix, false);
00319   DatagramIterator &iterator = reader.get_iterator();
00320 
00321   LMatrix4d matrix;
00322   for (int r = 0; r < 4; r++) {
00323     for (int c = 0; c < 4; c++) {
00324       matrix(r, c) = iterator.get_be_float32();
00325     }
00326   }
00327   check_remaining_size(iterator);
00328 
00329   _transform_steps.clear();
00330   _has_transform = true;
00331   _transform = matrix;
00332 
00333   return true;
00334 }
00335 
00336 ////////////////////////////////////////////////////////////////////
00337 //     Function: FltBead::extract_replicate_count
00338 //       Access: Private
00339 //  Description: Reads a replicate count ancillary bead.
00340 ////////////////////////////////////////////////////////////////////
00341 bool FltBead::
00342 extract_replicate_count(FltRecordReader &reader) {
00343   nassertr(reader.get_opcode() == FO_replicate, false);
00344   DatagramIterator &iterator = reader.get_iterator();
00345 
00346   _replicate_count = iterator.get_be_int16();
00347   iterator.skip_bytes(2);
00348 
00349   check_remaining_size(iterator);
00350   return true;
00351 }
00352 
00353 ////////////////////////////////////////////////////////////////////
00354 //     Function: FltBead::write_transform
00355 //       Access: Private
00356 //  Description: Writes out the transformation and all of its defining
00357 //               steps.
00358 ////////////////////////////////////////////////////////////////////
00359 FltError FltBead::
00360 write_transform(FltRecordWriter &writer) const {
00361   // First, write out the initial transform indication.
00362   writer.set_opcode(FO_transform_matrix);
00363   Datagram &datagram = writer.update_datagram();
00364 
00365   for (int r = 0; r < 4; r++) {
00366     for (int c = 0; c < 4; c++) {
00367       datagram.add_be_float32(_transform(r, c));
00368     }
00369   }
00370 
00371   FltError result = writer.advance();
00372   if (result != FE_ok) {
00373     return result;
00374   }
00375 
00376   // Now, write out each of the steps of the transform.
00377   Transforms::const_iterator ti;
00378   for (ti = _transform_steps.begin(); ti != _transform_steps.end(); ++ti) {
00379     if (!(*ti)->build_record(writer)) {
00380       assert(!flt_error_abort);
00381       return FE_invalid_record;
00382     }
00383     FltError result = writer.advance();
00384     if (result != FE_ok) {
00385       return result;
00386     }
00387   }
00388 
00389   return FE_ok;
00390 }
00391 
00392 ////////////////////////////////////////////////////////////////////
00393 //     Function: FltBead::write_replicate_count
00394 //       Access: Private
00395 //  Description: Writes out the replicate count, if needed.
00396 ////////////////////////////////////////////////////////////////////
00397 FltError FltBead::
00398 write_replicate_count(FltRecordWriter &writer) const {
00399   if (_replicate_count != 0) {
00400     writer.set_opcode(FO_replicate);
00401     Datagram &datagram = writer.update_datagram();
00402 
00403     datagram.add_be_int16(_replicate_count);
00404     datagram.pad_bytes(2);
00405 
00406     FltError result = writer.advance();
00407     if (result != FE_ok) {
00408       return result;
00409     }
00410   }
00411 
00412   return FE_ok;
00413 }
 All Classes Functions Variables Enumerations