Panda3D
|
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 }