Panda3D
|
00001 // Filename: xFileToEggConverter.cxx 00002 // Created by: drose (21Jun01) 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 "xFileToEggConverter.h" 00016 #include "xFileMesh.h" 00017 #include "xFileMaterial.h" 00018 #include "xFileAnimationSet.h" 00019 #include "config_xfile.h" 00020 00021 #include "eggData.h" 00022 #include "eggGroup.h" 00023 #include "eggXfmSAnim.h" 00024 #include "eggGroupUniquifier.h" 00025 #include "datagram.h" 00026 #include "eggMaterialCollection.h" 00027 #include "eggTextureCollection.h" 00028 #include "dcast.h" 00029 00030 //////////////////////////////////////////////////////////////////// 00031 // Function: XFileToEggConverter::Constructor 00032 // Access: Public 00033 // Description: 00034 //////////////////////////////////////////////////////////////////// 00035 XFileToEggConverter:: 00036 XFileToEggConverter() { 00037 _make_char = false; 00038 _frame_rate = 0.0; 00039 _x_file = new XFile(true); 00040 _dart_node = NULL; 00041 } 00042 00043 //////////////////////////////////////////////////////////////////// 00044 // Function: XFileToEggConverter::Copy Constructor 00045 // Access: Public 00046 // Description: 00047 //////////////////////////////////////////////////////////////////// 00048 XFileToEggConverter:: 00049 XFileToEggConverter(const XFileToEggConverter ©) : 00050 SomethingToEggConverter(copy), 00051 _make_char(copy._make_char) 00052 { 00053 _x_file = new XFile(true); 00054 _dart_node = NULL; 00055 } 00056 00057 //////////////////////////////////////////////////////////////////// 00058 // Function: XFileToEggConverter::Destructor 00059 // Access: Public 00060 // Description: 00061 //////////////////////////////////////////////////////////////////// 00062 XFileToEggConverter:: 00063 ~XFileToEggConverter() { 00064 close(); 00065 } 00066 00067 //////////////////////////////////////////////////////////////////// 00068 // Function: XFileToEggConverter::make_copy 00069 // Access: Public, Virtual 00070 // Description: Allocates and returns a new copy of the converter. 00071 //////////////////////////////////////////////////////////////////// 00072 SomethingToEggConverter *XFileToEggConverter:: 00073 make_copy() { 00074 return new XFileToEggConverter(*this); 00075 } 00076 00077 00078 //////////////////////////////////////////////////////////////////// 00079 // Function: XFileToEggConverter::get_name 00080 // Access: Public, Virtual 00081 // Description: Returns the English name of the file type this 00082 // converter supports. 00083 //////////////////////////////////////////////////////////////////// 00084 string XFileToEggConverter:: 00085 get_name() const { 00086 return "DirectX"; 00087 } 00088 00089 //////////////////////////////////////////////////////////////////// 00090 // Function: XFileToEggConverter::get_extension 00091 // Access: Public, Virtual 00092 // Description: Returns the common extension of the file type this 00093 // converter supports. 00094 //////////////////////////////////////////////////////////////////// 00095 string XFileToEggConverter:: 00096 get_extension() const { 00097 return "x"; 00098 } 00099 00100 //////////////////////////////////////////////////////////////////// 00101 // Function: XFileToEggConverter::supports_compressed 00102 // Access: Published, Virtual 00103 // Description: Returns true if this file type can transparently load 00104 // compressed files (with a .pz extension), false 00105 // otherwise. 00106 //////////////////////////////////////////////////////////////////// 00107 bool XFileToEggConverter:: 00108 supports_compressed() const { 00109 return true; 00110 } 00111 00112 //////////////////////////////////////////////////////////////////// 00113 // Function: XFileToEggConverter::convert_file 00114 // Access: Public, Virtual 00115 // Description: Handles the reading of the input file and converting 00116 // it to egg. Returns true if successful, false 00117 // otherwise. 00118 // 00119 // This is designed to be as generic as possible, 00120 // generally in support of run-time loading. 00121 // Command-line converters may choose to use 00122 // convert_flt() instead, as it provides more control. 00123 //////////////////////////////////////////////////////////////////// 00124 bool XFileToEggConverter:: 00125 convert_file(const Filename &filename) { 00126 close(); 00127 clear_error(); 00128 00129 if (!_x_file->read(filename)) { 00130 nout << "Unable to open X file: " << filename << "\n"; 00131 return false; 00132 } 00133 00134 if (_char_name.empty()) { 00135 _char_name = filename.get_basename_wo_extension(); 00136 } 00137 00138 if (_egg_data->get_coordinate_system() == CS_default) { 00139 _egg_data->set_coordinate_system(CS_yup_left); 00140 } 00141 00142 if (!get_toplevel()) { 00143 return false; 00144 } 00145 00146 if (!create_polygons()) { 00147 return false; 00148 } 00149 00150 if (_make_char) { 00151 // Now make sure that each joint has a unique name. 00152 EggGroupUniquifier uniquifier(false); 00153 uniquifier.uniquify(_dart_node); 00154 } 00155 00156 if (!create_hierarchy()) { 00157 return false; 00158 } 00159 00160 if (_keep_model && !_keep_animation) { 00161 strip_nodes(EggTable::get_class_type()); 00162 } 00163 00164 if (_keep_animation && !_keep_model) { 00165 strip_nodes(EggGroup::get_class_type()); 00166 } 00167 00168 return !had_error(); 00169 } 00170 00171 //////////////////////////////////////////////////////////////////// 00172 // Function: XFileToEggConverter::close 00173 // Access: Public 00174 // Description: Finalizes and closes the file previously opened via 00175 // convert_file(). 00176 //////////////////////////////////////////////////////////////////// 00177 void XFileToEggConverter:: 00178 close() { 00179 _x_file->clear(); 00180 00181 // Clean up all the other stuff. 00182 Meshes::const_iterator mi; 00183 for (mi = _meshes.begin(); mi != _meshes.end(); ++mi) { 00184 delete (*mi); 00185 } 00186 _meshes.clear(); 00187 00188 AnimationSets::const_iterator asi; 00189 for (asi = _animation_sets.begin(); asi != _animation_sets.end(); ++asi) { 00190 delete (*asi); 00191 } 00192 _animation_sets.clear(); 00193 00194 _joints.clear(); 00195 } 00196 00197 //////////////////////////////////////////////////////////////////// 00198 // Function: XFileToEggConverter::strip_nodes 00199 // Access: Public 00200 // Description: Removes all groups of the given type. This is used 00201 // to implement the -anim and -model options. 00202 //////////////////////////////////////////////////////////////////// 00203 void XFileToEggConverter:: 00204 strip_nodes(TypeHandle t) { 00205 pvector <EggNode *> garbage; 00206 EggGroupNode::iterator i; 00207 for (i=_egg_data->begin(); i!=_egg_data->end(); ++i) { 00208 EggNode *node = (*i); 00209 if (node->is_of_type(t)) { 00210 garbage.push_back(node); 00211 } 00212 } 00213 for (int n=0; n<(int)garbage.size(); n++) { 00214 _egg_data->remove_child(garbage[n]); 00215 } 00216 } 00217 00218 //////////////////////////////////////////////////////////////////// 00219 // Function: XFileToEggConverter::get_dart_node 00220 // Access: Public 00221 // Description: Returns the root of the joint hierarchy, if 00222 // _make_char is true, or NULL otherwise. 00223 //////////////////////////////////////////////////////////////////// 00224 EggGroup *XFileToEggConverter:: 00225 get_dart_node() const { 00226 return _dart_node; 00227 } 00228 00229 //////////////////////////////////////////////////////////////////// 00230 // Function: XFileToEggConverter::create_unique_texture 00231 // Access: Public 00232 // Description: Returns an EggTexture pointer whose properties match 00233 // that of the the given EggTexture, except for the tref 00234 // name. 00235 //////////////////////////////////////////////////////////////////// 00236 EggTexture *XFileToEggConverter:: 00237 create_unique_texture(const EggTexture ©) { 00238 return _textures.create_unique_texture(copy, ~EggTexture::E_tref_name); 00239 } 00240 00241 //////////////////////////////////////////////////////////////////// 00242 // Function: XFileToEggConverter::create_unique_material 00243 // Access: Public 00244 // Description: Returns an EggMaterial pointer whose properties match 00245 // that of the the given EggMaterial, except for the mref 00246 // name. 00247 //////////////////////////////////////////////////////////////////// 00248 EggMaterial *XFileToEggConverter:: 00249 create_unique_material(const EggMaterial ©) { 00250 return _materials.create_unique_material(copy, ~EggMaterial::E_mref_name); 00251 } 00252 00253 //////////////////////////////////////////////////////////////////// 00254 // Function: XFileToEggConverter::find_joint 00255 // Access: Public 00256 // Description: This is called by set_animation_frame, for 00257 // the purposes of building the frame data for the 00258 // animation--it needs to know the original rest frame 00259 // transform. 00260 //////////////////////////////////////////////////////////////////// 00261 EggGroup *XFileToEggConverter:: 00262 find_joint(const string &joint_name) { 00263 Joints::iterator ji; 00264 ji = _joints.find(joint_name); 00265 if (ji != _joints.end()) { 00266 EggGroup *joint = (*ji).second; 00267 if (joint == (EggGroup *)NULL) { 00268 // An invalid joint detected earlier. 00269 return NULL; 00270 } 00271 00272 return joint; 00273 } 00274 00275 // Joint name is unknown. Issue a warning, then insert NULL into 00276 // the table so we don't get the same warning again with the next 00277 // polygon. 00278 if (_make_char) { 00279 xfile_cat.warning() 00280 << "Joint name " << joint_name << " in animation data is undefined.\n"; 00281 } 00282 _joints[joint_name] = NULL; 00283 00284 return NULL; 00285 } 00286 00287 //////////////////////////////////////////////////////////////////// 00288 // Function: XFileToEggConverter::get_toplevel 00289 // Access: Private 00290 // Description: Pulls off all of the top-level objects in the .x file 00291 // and converts them, and their descendents, to the 00292 // appropriate egg structures. 00293 //////////////////////////////////////////////////////////////////// 00294 bool XFileToEggConverter:: 00295 get_toplevel() { 00296 int num_objects = _x_file->get_num_objects(); 00297 int i; 00298 00299 _ticks_per_second = 4800; // X File default. 00300 00301 // First, make a pass through the toplevel objects and see if we 00302 // have frames and/or animation. 00303 _any_frames = false; 00304 _any_animation = false; 00305 for (i = 0; i < num_objects; i++) { 00306 XFileDataNode *child = _x_file->get_object(i); 00307 if (child->is_standard_object("Frame")) { 00308 _any_frames = true; 00309 } else if (child->is_standard_object("AnimationSet")) { 00310 _any_animation = true; 00311 } 00312 } 00313 00314 // If we have animation, assume we want to convert it as a character. 00315 if (_any_animation) { 00316 _make_char = true; 00317 } 00318 00319 EggGroupNode *egg_parent = _egg_data; 00320 00321 // If we are converting an animatable model, make an extra node to 00322 // represent the root of the hierarchy. 00323 if (_make_char) { 00324 _dart_node = new EggGroup(_char_name); 00325 egg_parent->add_child(_dart_node); 00326 _dart_node->set_dart_type(EggGroup::DT_default); 00327 egg_parent = _dart_node; 00328 } 00329 00330 // Now go back through and convert the objects. 00331 for (i = 0; i < num_objects; i++) { 00332 if (!convert_toplevel_object(_x_file->get_object(i), egg_parent)) { 00333 return false; 00334 } 00335 } 00336 00337 return true; 00338 } 00339 00340 //////////////////////////////////////////////////////////////////// 00341 // Function: XFileToEggConverter::convert_toplevel_object 00342 // Access: Private 00343 // Description: Converts the indicated object, encountered outside of 00344 // any Frames, to the appropriate egg structures. 00345 //////////////////////////////////////////////////////////////////// 00346 bool XFileToEggConverter:: 00347 convert_toplevel_object(XFileDataNode *obj, EggGroupNode *egg_parent) { 00348 if (obj->is_standard_object("Header")) { 00349 // Quietly ignore headers. 00350 00351 } else if (obj->is_standard_object("Material")) { 00352 // Quietly ignore toplevel materials. These will presumably be 00353 // referenced below. 00354 00355 } else if (obj->is_standard_object("Frame")) { 00356 if (!convert_frame(obj, egg_parent)) { 00357 return false; 00358 } 00359 00360 } else if (obj->is_standard_object("AnimationSet")) { 00361 if (!convert_animation_set(obj)) { 00362 return false; 00363 } 00364 00365 } else if (obj->is_standard_object("AnimTicksPerSecond")) { 00366 _ticks_per_second = (*obj)[0].i(); 00367 00368 } else if (obj->is_standard_object("Mesh")) { 00369 // If there are any Frames at all in the file, then assume a Mesh 00370 // at the toplevel is just present to define a reference that will 00371 // be included below--so we ignore it here. On the other hand, if 00372 // the file has no Frames, then a Mesh at the toplevel must be 00373 // actual geometry, so convert it now. 00374 if (!_any_frames) { 00375 if (!convert_mesh(obj, egg_parent)) { 00376 return false; 00377 } 00378 } 00379 00380 } else { 00381 if (xfile_cat.is_debug()) { 00382 xfile_cat.debug() 00383 << "Ignoring toplevel object of unknown type: " 00384 << obj->get_template_name() << "\n"; 00385 } 00386 } 00387 00388 return true; 00389 } 00390 00391 //////////////////////////////////////////////////////////////////// 00392 // Function: XFileToEggConverter::convert_object 00393 // Access: Private 00394 // Description: Converts the indicated object to the appropriate egg 00395 // structures. 00396 //////////////////////////////////////////////////////////////////// 00397 bool XFileToEggConverter:: 00398 convert_object(XFileDataNode *obj, EggGroupNode *egg_parent) { 00399 if (obj->is_standard_object("Header")) { 00400 // Quietly ignore headers. 00401 00402 } else if (obj->is_standard_object("Frame")) { 00403 if (!convert_frame(obj, egg_parent)) { 00404 return false; 00405 } 00406 00407 } else if (obj->is_standard_object("FrameTransformMatrix")) { 00408 if (!convert_transform(obj, egg_parent)) { 00409 return false; 00410 } 00411 00412 } else if (obj->is_standard_object("Mesh")) { 00413 if (!convert_mesh(obj, egg_parent)) { 00414 return false; 00415 } 00416 00417 } else { 00418 if (xfile_cat.is_debug()) { 00419 xfile_cat.debug() 00420 << "Ignoring object of unknown type: " 00421 << obj->get_template_name() << "\n"; 00422 } 00423 } 00424 00425 return true; 00426 } 00427 00428 //////////////////////////////////////////////////////////////////// 00429 // Function: XFileToEggConverter::convert_frame 00430 // Access: Private 00431 // Description: Converts the indicated frame to the appropriate egg 00432 // structures. 00433 //////////////////////////////////////////////////////////////////// 00434 bool XFileToEggConverter:: 00435 convert_frame(XFileDataNode *obj, EggGroupNode *egg_parent) { 00436 00437 string name = obj->get_name(); 00438 EggGroup *group = new EggGroup(name); 00439 egg_parent->add_child(group); 00440 00441 if (_make_char) { 00442 group->set_group_type(EggGroup::GT_joint); 00443 if (name.empty()) { 00444 // Make up a name for this unnamed joint. 00445 group->set_name("unnamed"); 00446 00447 } else { 00448 bool inserted = _joints.insert(Joints::value_type(name, group)).second; 00449 if (!inserted) { 00450 xfile_cat.warning() 00451 << "Nonunique Frame name " << name 00452 << " encountered; animation will be ambiguous.\n"; 00453 } 00454 } 00455 } 00456 00457 // Now walk through the children of the frame. 00458 int num_objects = obj->get_num_objects(); 00459 for (int i = 0; i < num_objects; i++) { 00460 if (!convert_object(obj->get_object(i), group)) { 00461 return false; 00462 } 00463 } 00464 00465 return true; 00466 } 00467 00468 //////////////////////////////////////////////////////////////////// 00469 // Function: XFileToEggConverter::convert_transform 00470 // Access: Private 00471 // Description: Reads a transform matrix, a child of a given frame, 00472 // and applies it to the node. Normally this can only 00473 // be done if the node in question is an EggGroup, which 00474 // should be the case if the transform was a child of a 00475 // frame. 00476 //////////////////////////////////////////////////////////////////// 00477 bool XFileToEggConverter:: 00478 convert_transform(XFileDataNode *obj, EggGroupNode *egg_parent) { 00479 LMatrix4d mat = (*obj)["frameMatrix"]["matrix"].mat4(); 00480 00481 if (egg_parent->is_of_type(EggGroup::get_class_type())) { 00482 EggGroup *egg_group = DCAST(EggGroup, egg_parent); 00483 egg_group->set_transform3d(mat); 00484 00485 } else { 00486 xfile_cat.error() 00487 << "Transform " << obj->get_name() 00488 << " encountered without frame!\n"; 00489 } 00490 00491 return true; 00492 } 00493 00494 //////////////////////////////////////////////////////////////////// 00495 // Function: XFileToEggConverter::convert_animation_set 00496 // Access: Private 00497 // Description: Begins an AnimationSet. This is the root of one 00498 // particular animation (table of frames per joint) to 00499 // be applied to the model within this file. 00500 //////////////////////////////////////////////////////////////////// 00501 bool XFileToEggConverter:: 00502 convert_animation_set(XFileDataNode *obj) { 00503 XFileAnimationSet *animation_set = new XFileAnimationSet(); 00504 animation_set->set_name(obj->get_name()); 00505 00506 _total_tick_deltas = 0; 00507 _num_ticks = 0; 00508 00509 // Now walk through the children of the set; each one animates a 00510 // different joint. 00511 int num_objects = obj->get_num_objects(); 00512 for (int i = 0; i < num_objects; i++) { 00513 if (!convert_animation_set_object(obj->get_object(i), *animation_set)) { 00514 return false; 00515 } 00516 } 00517 00518 animation_set->_frame_rate = _frame_rate; 00519 if (_num_ticks != 0 && _frame_rate == 0.0) { 00520 // Compute the frame rate from the timing information. 00521 double delta = (double)_total_tick_deltas / (double)_num_ticks; 00522 if (delta != 0.0) { 00523 animation_set->_frame_rate = (double)_ticks_per_second / delta; 00524 } 00525 } 00526 00527 _animation_sets.push_back(animation_set); 00528 00529 return true; 00530 } 00531 00532 //////////////////////////////////////////////////////////////////// 00533 // Function: XFileToEggConverter::convert_animation_set_object 00534 // Access: Private 00535 // Description: Converts the indicated object, a child of a 00536 // AnimationSet. 00537 //////////////////////////////////////////////////////////////////// 00538 bool XFileToEggConverter:: 00539 convert_animation_set_object(XFileDataNode *obj, 00540 XFileAnimationSet &animation_set) { 00541 if (obj->is_standard_object("Animation")) { 00542 if (!convert_animation(obj, animation_set)) { 00543 return false; 00544 } 00545 00546 } else { 00547 if (xfile_cat.is_debug()) { 00548 xfile_cat.debug() 00549 << "Ignoring animation set object of unknown type: " 00550 << obj->get_template_name() << "\n"; 00551 } 00552 } 00553 00554 return true; 00555 } 00556 00557 //////////////////////////////////////////////////////////////////// 00558 // Function: XFileToEggConverter::convert_animation 00559 // Access: Private 00560 // Description: Converts the indicated Animation template object. 00561 //////////////////////////////////////////////////////////////////// 00562 bool XFileToEggConverter:: 00563 convert_animation(XFileDataNode *obj, XFileAnimationSet &animation_set) { 00564 // Within an Animation template, we expect to find a reference to a 00565 // frame, possibly an AnimationOptions object, and one or more 00566 // AnimationKey objects. 00567 00568 // First, walk through the list of children, to find the one that is 00569 // the frame reference. We need to know this up front so we know 00570 // which table we should be building up. 00571 string frame_name; 00572 bool got_frame_name = false; 00573 00574 int num_objects = obj->get_num_objects(); 00575 int i; 00576 for (i = 0; i < num_objects; i++) { 00577 XFileDataNode *child = obj->get_object(i); 00578 if (child->is_reference() && child->is_standard_object("Frame")) { 00579 frame_name = child->get_name(); 00580 got_frame_name = true; 00581 } 00582 } 00583 00584 if (!got_frame_name) { 00585 xfile_cat.error() 00586 << "Animation " << obj->get_name() 00587 << " includes no reference to a frame.\n"; 00588 return false; 00589 } 00590 00591 FrameData &table = animation_set.create_frame_data(frame_name); 00592 00593 // Now go back again and get the actual data. 00594 for (i = 0; i < num_objects; i++) { 00595 if (!convert_animation_object(obj->get_object(i), frame_name, table)) { 00596 return false; 00597 } 00598 } 00599 00600 return true; 00601 } 00602 00603 //////////////////////////////////////////////////////////////////// 00604 // Function: XFileToEggConverter::convert_animation_object 00605 // Access: Private 00606 // Description: Converts the indicated object, a child of a 00607 // Animation. 00608 //////////////////////////////////////////////////////////////////// 00609 bool XFileToEggConverter:: 00610 convert_animation_object(XFileDataNode *obj, const string &joint_name, 00611 XFileToEggConverter::FrameData &table) { 00612 if (obj->is_standard_object("AnimationOptions")) { 00613 // Quietly ignore AnimationOptions. 00614 00615 } else if (obj->is_standard_object("Frame")) { 00616 // Quietly ignore frames, since we already got the frame name. 00617 00618 } else if (obj->is_standard_object("AnimationKey")) { 00619 if (!convert_animation_key(obj, joint_name, table)) { 00620 return false; 00621 } 00622 00623 } else { 00624 if (xfile_cat.is_debug()) { 00625 xfile_cat.debug() 00626 << "Ignoring animation object of unknown type: " 00627 << obj->get_template_name() << "\n"; 00628 } 00629 } 00630 00631 return true; 00632 } 00633 00634 //////////////////////////////////////////////////////////////////// 00635 // Function: XFileToEggConverter::convert_animation_key 00636 // Access: Private 00637 // Description: Converts the indicated AnimationKey template object. 00638 //////////////////////////////////////////////////////////////////// 00639 bool XFileToEggConverter:: 00640 convert_animation_key(XFileDataNode *obj, const string &joint_name, 00641 XFileToEggConverter::FrameData &table) { 00642 int key_type = (*obj)["keyType"].i(); 00643 00644 const XFileDataObject &keys = (*obj)["keys"]; 00645 00646 int last_time = 0; 00647 for (int i = 0; i < keys.size(); i++) { 00648 // The time value is problematic, since it allows x files to 00649 // specify keyframes of arbitrary duration. Panda doesn't support 00650 // this; all frames in Panda must be of a constant duration. 00651 // Thus, we largely ignore the time value, but we take the average 00652 // of all deltas as the duration. This will correctly handle .x 00653 // files with uniform keyframes, at least. 00654 00655 int this_time = keys[i]["time"].i(); 00656 if (i != 0) { 00657 int delta = this_time - last_time; 00658 _total_tick_deltas += delta; 00659 ++_num_ticks; 00660 } 00661 last_time = this_time; 00662 00663 const XFileDataObject &values = keys[i]["tfkeys"]["values"]; 00664 if (!set_animation_frame(joint_name, table, i, key_type, values)) { 00665 return false; 00666 } 00667 } 00668 00669 return true; 00670 } 00671 00672 //////////////////////////////////////////////////////////////////// 00673 // Function: XFileToEggConverter::set_animation_frame 00674 // Access: Private 00675 // Description: Sets a single frame of the animation data. 00676 //////////////////////////////////////////////////////////////////// 00677 bool XFileToEggConverter:: 00678 set_animation_frame(const string &joint_name, 00679 XFileToEggConverter::FrameData &table, int frame, 00680 int key_type, const XFileDataObject &values) { 00681 if ((int)table._entries.size() <= frame) { 00682 nassertr((int)table._entries.size() == frame, false); 00683 table._entries.push_back(XFileAnimationSet::FrameEntry()); 00684 } 00685 00686 XFileAnimationSet::FrameEntry &frame_entry = table._entries[frame]; 00687 00688 // Now modify the last row in the table. 00689 switch (key_type) { 00690 case 0: 00691 // Key type 0: rotation. 00692 // This appears to be a quaternion. Hope we get the coordinate 00693 // system right. 00694 if (values.size() != 4) { 00695 xfile_cat.error() 00696 << "Incorrect number of values in animation table: " 00697 << values.size() << " for rotation data.\n"; 00698 return false; 00699 } 00700 frame_entry._rot.invert_from(LQuaterniond(values.vec4())); 00701 table._flags |= XFileAnimationSet::FDF_rot; 00702 break; 00703 00704 case 1: 00705 if (values.size() != 3) { 00706 xfile_cat.error() 00707 << "Incorrect number of values in animation table: " 00708 << values.size() << " for scale data.\n"; 00709 return false; 00710 } 00711 frame_entry._scale = values.vec3(); 00712 table._flags |= XFileAnimationSet::FDF_scale; 00713 break; 00714 00715 case 2: 00716 // Key type 2: position 00717 if (values.size() != 3) { 00718 xfile_cat.error() 00719 << "Incorrect number of values in animation table: " 00720 << values.size() << " for position data.\n"; 00721 return false; 00722 } 00723 frame_entry._trans = values.vec3(); 00724 table._flags |= XFileAnimationSet::FDF_trans; 00725 break; 00726 00727 /* 00728 case 3: 00729 // Key type 3: ???? 00730 break; 00731 */ 00732 00733 case 4: 00734 // Key type 4: full matrix 00735 if (values.size() != 16) { 00736 xfile_cat.error() 00737 << "Incorrect number of values in animation table: " 00738 << values.size() << " for matrix data.\n"; 00739 return false; 00740 } 00741 frame_entry._mat = values.mat4(); 00742 table._flags |= XFileAnimationSet::FDF_mat; 00743 break; 00744 00745 default: 00746 xfile_cat.error() 00747 << "Unsupported key type " << key_type << " in animation table.\n"; 00748 return false; 00749 } 00750 00751 return true; 00752 } 00753 00754 //////////////////////////////////////////////////////////////////// 00755 // Function: XFileToEggConverter::convert_mesh 00756 // Access: Private 00757 // Description: Converts the indicated mesh to the appropriate egg 00758 // structures. 00759 //////////////////////////////////////////////////////////////////// 00760 bool XFileToEggConverter:: 00761 convert_mesh(XFileDataNode *obj, EggGroupNode *egg_parent) { 00762 XFileMesh *mesh = new XFileMesh(_egg_data->get_coordinate_system()); 00763 mesh->set_name(obj->get_name()); 00764 mesh->set_egg_parent(egg_parent); 00765 00766 if (!mesh->fill_mesh(obj)) { 00767 delete mesh; 00768 return false; 00769 } 00770 00771 _meshes.push_back(mesh); 00772 00773 return true; 00774 } 00775 00776 //////////////////////////////////////////////////////////////////// 00777 // Function: XFileToEggConverter::create_polygons 00778 // Access: Private 00779 // Description: Creates all the polygons associated with 00780 // previously-saved meshes. 00781 //////////////////////////////////////////////////////////////////// 00782 bool XFileToEggConverter:: 00783 create_polygons() { 00784 bool okflag = true; 00785 00786 Meshes::const_iterator mi; 00787 for (mi = _meshes.begin(); mi != _meshes.end(); ++mi) { 00788 if (!(*mi)->create_polygons(this)) { 00789 okflag = false; 00790 } 00791 delete (*mi); 00792 } 00793 _meshes.clear(); 00794 00795 return okflag; 00796 } 00797 00798 //////////////////////////////////////////////////////////////////// 00799 // Function: XFileToEggConverter::create_hierarchy 00800 // Access: Private 00801 // Description: Creates the animation table hierarchies for the 00802 // previously-saved animation sets. 00803 //////////////////////////////////////////////////////////////////// 00804 bool XFileToEggConverter:: 00805 create_hierarchy() { 00806 bool okflag = true; 00807 00808 AnimationSets::const_iterator asi; 00809 for (asi = _animation_sets.begin(); asi != _animation_sets.end(); ++asi) { 00810 if (_make_char) { 00811 if (!(*asi)->create_hierarchy(this)) { 00812 okflag = false; 00813 } 00814 } 00815 delete (*asi); 00816 } 00817 _animation_sets.clear(); 00818 00819 return okflag; 00820 }