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