15 #include "daeToEggConverter.h" 16 #include "fcollada_utils.h" 17 #include "config_daeegg.h" 18 #include "daeCharacter.h" 20 #include "string_utils.h" 22 #include "eggPrimitive.h" 24 #include "eggPolygon.h" 25 #include "eggTriangleFan.h" 26 #include "eggTriangleStrip.h" 28 #include "eggXfmSAnim.h" 29 #include "eggSAnimData.h" 30 #include "pt_EggVertex.h" 32 #include "FCDocument/FCDAsset.h" 33 #include "FCDocument/FCDocumentTools.h" 34 #include "FCDocument/FCDSceneNode.h" 35 #include "FCDocument/FCDSceneNodeTools.h" 36 #include "FCDocument/FCDGeometry.h" 37 #include "FCDocument/FCDGeometryInstance.h" 38 #include "FCDocument/FCDGeometryPolygons.h" 39 #include "FCDocument/FCDGeometrySource.h" 40 #include "FCDocument/FCDSkinController.h" 41 #include "FCDocument/FCDController.h" 42 #include "FCDocument/FCDControllerInstance.h" 43 #include "FCDocument/FCDMorphController.h" 44 #include "FCDocument/FCDMaterialInstance.h" 45 #include "FCDocument/FCDExtra.h" 46 #include "FCDocument/FCDEffect.h" 47 #include "FCDocument/FCDEffectStandard.h" 48 #if FCOLLADA_VERSION >= 0x00030005 49 #include "FCDocument/FCDGeometryPolygonsInput.h" 63 _error_handler = NULL;
64 _invert_transparency =
false;
84 ~DAEToEggConverter() {
85 if (_error_handler != NULL) {
86 delete _error_handler;
135 if (_error_handler == NULL) {
136 _error_handler =
new FUErrorSimpleHandler;
140 if (_egg_data->get_coordinate_system() == CS_default) {
141 _egg_data->set_coordinate_system(CS_yup_right);
145 FCollada::Initialize();
146 _document = FCollada::LoadDocument(filename.
to_os_specific().c_str());
147 if (_document == NULL) {
148 daeegg_cat.error() <<
"Failed to load document: " << _error_handler->GetErrorString() << endl;
153 if (_document->GetAsset() != NULL) {
154 FCDocumentTools::StandardizeUpAxisAndLength(_document);
160 string model_name = _character_name;
162 FCDSceneNode* visual_scene = _document->GetVisualSceneInstance();
163 if (visual_scene != NULL) {
164 if (model_name.empty()) {
166 model_name = FROM_FSTRING(visual_scene->GetName());
168 scene_group =
new EggGroup(model_name);
169 _egg_data->add_child(scene_group);
171 for (
size_t ch = 0; ch < visual_scene->GetChildrenCount(); ++ch) {
172 process_node(scene_group, visual_scene->GetChild(ch));
176 <<
"No visual scene instance found in COLLADA document.\n";
182 Characters::iterator it;
184 for (it = _characters.begin(); it != _characters.end(); ++it) {
189 const FCDGeometryMesh *mesh = character->_skin_mesh;
193 daeegg_cat.spam() <<
"Processing mesh for controller\n";
194 process_mesh(character->_node_group, mesh, materials, character);
200 for (
size_t ch = 0; ch < visual_scene->GetChildrenCount(); ++ch) {
204 if (scene_group != NULL) {
207 _egg_data->remove_child(scene_group);
209 scene_group->set_dart_type(EggGroup::DT_default);
215 _table->set_table_type(EggTable::TT_table);
216 _egg_data->add_child(_table);
219 bundle->set_table_type(EggTable::TT_bundle);
220 _table->add_child(bundle);
223 skeleton->set_table_type(EggTable::TT_table);
224 bundle->add_child(skeleton);
228 Characters::iterator it;
230 for (it = _characters.begin(); it != _characters.end(); ++it) {
240 if (_frame_inc != 0.0) {
244 if (_end_frame != _start_frame) {
245 start = _start_frame;
249 start = *keys.begin();
250 end = *keys.rbegin();
254 for (
float t = start; t <= end; t += _frame_inc) {
261 if (_end_frame != 0.0) {
263 float end = _end_frame;
265 for (ki = keys.begin(); ki != keys.end(); ++ki) {
266 if (*ki > end && !IS_THRESHOLD_EQUAL(*ki, end, 0.001)) {
267 keys.erase(ki, keys.end());
272 if (_start_frame != 0.0) {
274 float start = _start_frame;
276 for (ki = keys.begin(); ki != keys.end(); ++ki) {
277 if (*ki > start && !IS_THRESHOLD_EQUAL(*ki, start, 0.001)) {
278 keys.erase(keys.begin(), ki);
287 if (ki != keys.end()) {
291 for (++ki; ki != keys.end(); ++ki) {
292 if (diff != 0 && !IS_THRESHOLD_EQUAL((*ki - last), diff, 0.001)) {
294 <<
"This does not appear to be a sampled animation.\n" 295 <<
"Specify the -sf, -ef and -if options to indicate how the " 296 <<
"animations should be sampled.\n";
307 for (
size_t ch = 0; ch < visual_scene->GetChildrenCount(); ++ch) {
308 character->
build_table(skeleton, visual_scene->GetChild(ch), keys);
314 SAFE_DELETE(visual_scene);
315 SAFE_DELETE(_document);
331 if (IS_NEARLY_EQUAL(_unit_meters, 0.001)) {
332 return DU_millimeters;
334 if (IS_NEARLY_EQUAL(_unit_meters, 0.01)) {
335 return DU_centimeters;
337 if (IS_NEARLY_EQUAL(_unit_meters, 1.0)) {
340 if (IS_NEARLY_EQUAL(_unit_meters, 1000.0)) {
341 return DU_kilometers;
343 if (IS_NEARLY_EQUAL(_unit_meters, 3.0 * 12.0 * 0.0254)) {
346 if (IS_NEARLY_EQUAL(_unit_meters, 12.0 * 0.0254)) {
349 if (IS_NEARLY_EQUAL(_unit_meters, 0.0254)) {
352 if (IS_NEARLY_EQUAL(_unit_meters, 1852.0)) {
353 return DU_nautical_miles;
355 if (IS_NEARLY_EQUAL(_unit_meters, 5280.0 * 12.0 * 0.0254)) {
356 return DU_statute_miles;
363 void DAEToEggConverter::
365 const FCDAsset *asset = _document->GetAsset();
366 if (_document->GetAsset() == NULL) {
370 _unit_name = FROM_FSTRING(asset->GetUnitName());
371 _unit_meters = asset->GetUnitConversionFactor();
374 FMVector3 up_axis = asset->GetUpAxis();
376 if (up_axis == FMVector3(0, 1, 0)) {
377 _egg_data->set_coordinate_system(CS_yup_right);
379 }
else if (up_axis == FMVector3(0, 0, 1)) {
380 _egg_data->set_coordinate_system(CS_zup_right);
383 _egg_data->set_coordinate_system(CS_invalid);
384 daeegg_cat.warning() <<
"Unrecognized coordinate system!\n";
389 void DAEToEggConverter::
390 process_node(
EggGroupNode *parent,
const FCDSceneNode* node,
bool forced) {
391 nassertv(node != NULL);
392 string node_id = FROM_FSTRING(node->GetDaeId());
393 daeegg_cat.spam() <<
"Processing node with ID '" << node_id <<
"'" << endl;
397 process_extra(node_group, node->GetExtra());
401 if (node->IsJoint()) {
402 string sid = FROM_FSTRING(node->GetSubId());
403 node_group->set_group_type(EggGroup::GT_joint);
405 if (!_joints.insert(DaeCharacter::JointMap::value_type(sid,
408 <<
"Joint with sid " << sid <<
" occurs more than once!\n";
413 for (
size_t tr = node->GetTransformCount(); tr > 0; --tr) {
414 apply_transform(node_group, node->GetTransform(tr - 1));
419 for (
size_t in = 0; in < node->GetInstanceCount(); ++in) {
420 process_instance(node_group, node->GetInstance(in));
424 for (
size_t ch = 0; ch < node->GetChildrenCount(); ++ch) {
425 process_node(DCAST(
EggGroupNode, node_group), node->GetChild(ch));
429 for (
size_t in = 0; in < node->GetInstanceCount(); ++in) {
430 const FCDEntity *entity = node->GetInstance(in)->GetEntity();
431 if (entity && entity->GetType() == FCDEntity::SCENE_NODE) {
432 process_node(node_group, (
const FCDSceneNode*) entity);
437 void DAEToEggConverter::
438 process_instance(
EggGroup *parent,
const FCDEntityInstance* instance) {
439 nassertv(instance != NULL);
440 nassertv(instance->GetEntity() != NULL);
442 switch (instance->GetType()) {
443 case FCDEntityInstance::GEOMETRY:
446 const FCDGeometry* geometry = (
const FCDGeometry*) instance->GetEntity();
447 assert(geometry != NULL);
448 if (geometry->IsMesh()) {
450 process_mesh(parent, geometry->GetMesh(),
new DaeMaterials((
const FCDGeometryInstance*) instance));
452 if (geometry->IsSpline()) {
453 process_spline(parent, FROM_FSTRING(geometry->GetName()), const_cast<FCDGeometrySpline*> (geometry->GetSpline()));
459 case FCDEntityInstance::CONTROLLER:
462 process_controller(parent, (
const FCDControllerInstance*) instance);
465 case FCDEntityInstance::MATERIAL:
469 case FCDEntityInstance::SIMPLE:
472 const FCDEntity* entity = instance->GetEntity();
473 if (entity->GetType() != FCDEntity::SCENE_NODE) {
474 daeegg_cat.warning() <<
"Unsupported entity type found" << endl;
480 daeegg_cat.warning() <<
"Unsupported instance type found" << endl;
485 void DAEToEggConverter::
486 process_mesh(
EggGroup *parent,
const FCDGeometryMesh* mesh,
489 nassertv(mesh != NULL);
490 daeegg_cat.debug() <<
"Processing mesh with id " << FROM_FSTRING(mesh->GetDaeId()) << endl;
496 mesh_group->add_child(mesh_pool);
499 if (mesh->GetSourceCount() == 0) {
500 daeegg_cat.debug() <<
"Mesh with id " << FROM_FSTRING(mesh->GetDaeId()) <<
" has no sources" << endl;
503 const FCDGeometrySource* vsource = mesh->FindSourceByType(FUDaeGeometryInput::POSITION);
504 if (vsource == NULL) {
505 daeegg_cat.debug() <<
"Mesh with id " << FROM_FSTRING(mesh->GetDaeId()) <<
" has no source for POSITION data" << endl;
510 daeegg_cat.spam() <<
"Mesh with id " << FROM_FSTRING(mesh->GetDaeId()) <<
" has " << mesh->GetPolygonsCount() <<
" polygon groups" << endl;
511 if (mesh->GetPolygonsCount() == 0)
return;
514 PT(
EggGroup) *primitive_holders =
new PT(
EggGroup) [mesh->GetPolygonsCount()];
515 for (
size_t gr = 0; gr < mesh->GetPolygonsCount(); ++gr) {
516 const FCDGeometryPolygons* polygons = mesh->GetPolygons(gr);
517 string material_semantic = FROM_FSTRING(polygons->GetMaterialSemantic());
522 if (materials != NULL && (!polygons->GetMaterialSemantic().empty()) && mesh->GetPolygonsCount() > 1) {
527 primitiveholder = mesh_group;
529 primitive_holders[gr] = primitiveholder;
531 if (materials != NULL) {
532 materials->
apply_to_group(material_semantic, primitiveholder, _invert_transparency);
535 const FCDGeometryPolygonsInput* pinput = polygons->FindInput(FUDaeGeometryInput::POSITION);
536 assert(pinput != NULL);
537 const uint32* indices = pinput->GetIndices();
539 const FCDGeometrySource* nsource = mesh->FindSourceByType(FUDaeGeometryInput::NORMAL);
540 const FCDGeometryPolygonsInput* ninput = polygons->FindInput(FUDaeGeometryInput::NORMAL);
541 const uint32* nindices;
542 if (ninput != NULL) nindices = ninput->GetIndices();
544 const FCDGeometrySource* tcsource = mesh->FindSourceByType(FUDaeGeometryInput::TEXCOORD);
545 const FCDGeometryPolygonsInput* tcinput = polygons->FindInput(FUDaeGeometryInput::TEXCOORD);
546 const uint32* tcindices;
547 if (tcinput != NULL) tcindices = tcinput->GetIndices();
549 const FCDGeometrySource* csource = mesh->FindSourceByType(FUDaeGeometryInput::COLOR);
550 const FCDGeometryPolygonsInput* cinput = polygons->FindInput(FUDaeGeometryInput::COLOR);
551 const uint32* cindices;
552 if (cinput != NULL) cindices = cinput->GetIndices();
554 const FCDGeometrySource* bsource = mesh->FindSourceByType(FUDaeGeometryInput::TEXBINORMAL);
555 const FCDGeometryPolygonsInput* binput = polygons->FindInput(FUDaeGeometryInput::TEXBINORMAL);
556 const uint32* bindices;
557 if (binput != NULL) bindices = binput->GetIndices();
559 const FCDGeometrySource* tsource = mesh->FindSourceByType(FUDaeGeometryInput::TEXTANGENT);
560 const FCDGeometryPolygonsInput* tinput = polygons->FindInput(FUDaeGeometryInput::TEXTANGENT);
561 const uint32* tindices;
562 if (tinput != NULL) tindices = tinput->GetIndices();
565 if (materials != NULL && tcinput != NULL) {
566 if (daeegg_cat.is_debug()) {
568 <<
"Assigning texcoord set " << tcinput->GetSet()
569 <<
" to semantic '" << material_semantic <<
"'\n";
572 FUDaeGeometryInput::TEXCOORD, tcinput->GetSet());
575 if (materials != NULL && binput != NULL) {
576 if (daeegg_cat.is_debug()) {
578 <<
"Assigning texbinormal set " << binput->GetSet()
579 <<
" to semantic '" << material_semantic <<
"'\n";
582 FUDaeGeometryInput::TEXBINORMAL, binput->GetSet());
585 if (materials != NULL && tinput != NULL) {
586 if (daeegg_cat.is_debug()) {
588 <<
"Assigning textangent set " << tinput->GetSet()
589 <<
" to semantic '" << material_semantic <<
"'\n";
592 FUDaeGeometryInput::TEXTANGENT, tinput->GetSet());
595 for (
size_t ix = 0; ix < pinput->GetIndexCount(); ++ix) {
596 PT_EggVertex vertex = mesh_pool->make_new_vertex();
597 const float* data = &vsource->GetData()[indices[ix]*3];
598 vertex->set_pos(
LPoint3d(data[0], data[1], data[2]));
600 if (character != NULL) {
606 if (nsource != NULL && ninput != NULL) {
607 assert(nsource->GetStride() == 3);
608 data = &nsource->GetData()[nindices[ix]*3];
609 vertex->set_normal(
LVecBase3d(data[0], data[1], data[2]));
612 if (tcsource != NULL && tcinput != NULL) {
613 assert(tcsource->GetStride() == 2 || tcsource->GetStride() == 3);
614 data = &tcsource->GetData()[tcindices[ix]*tcsource->GetStride()];
615 if (tcsource->GetStride() == 2) {
616 vertex->set_uv(tcsetname,
LPoint2d(data[0], data[1]));
618 vertex->set_uvw(tcsetname,
LPoint3d(data[0], data[1], data[2]));
622 if (csource != NULL && cinput != NULL) {
623 assert(csource->GetStride() == 3 || csource->GetStride() == 4);
624 if (csource->GetStride() == 3) {
625 data = &csource->GetData()[cindices[ix]*3];
626 vertex->set_color(
LColor(data[0], data[1], data[2], 1.0f));
628 data = &csource->GetData()[cindices[ix]*4];
629 vertex->set_color(
LColor(data[0], data[1], data[2], data[3]));
633 if ((bsource != NULL && binput != NULL) || (tsource != NULL && tinput != NULL)) {
634 if (bsource != NULL && binput != NULL) {
635 assert(bsource->GetStride() == 3);
636 data = &bsource->GetData()[bindices[ix]*3];
637 PT(
EggVertexUV) uv_obj = vertex->modify_uv_obj(tbsetname);
638 if (uv_obj == NULL) {
641 uv_obj->set_binormal(
LVecBase3d(data[0], data[1], data[2]));
643 if (tsource != NULL && tinput != NULL) {
644 assert(tsource->GetStride() == 3);
645 data = &tsource->GetData()[tindices[ix]*3];
646 PT(
EggVertexUV) uv_obj = vertex->modify_uv_obj(ttsetname);
647 if (uv_obj == NULL) {
650 uv_obj->set_tangent(
LVecBase3d(data[0], data[1], data[2]));
657 for (
size_t gr = 0; gr < mesh->GetPolygonsCount(); ++gr) {
658 const FCDGeometryPolygons* polygons = mesh->GetPolygons(gr);
661 for (
size_t fa = 0; fa < polygons->GetFaceVertexCountCount(); ++fa) {
664 switch (polygons->GetPrimitiveType()) {
665 case FCDGeometryPolygons::LINES:
668 case FCDGeometryPolygons::POLYGONS:
671 case FCDGeometryPolygons::TRIANGLE_FANS:
674 case FCDGeometryPolygons::TRIANGLE_STRIPS:
677 case FCDGeometryPolygons::POINTS:
680 case FCDGeometryPolygons::LINE_STRIPS:
681 daeegg_cat.warning() <<
"Linestrips not yet supported!" << endl;
684 daeegg_cat.warning() <<
"Unsupported primitive type found!" << endl;
686 if (primitive != NULL) {
687 primitive_holders[gr]->add_child(primitive);
688 if (materials != NULL) {
689 materials->
apply_to_primitive(FROM_FSTRING(polygons->GetMaterialSemantic()), primitive);
691 for (
size_t ve = 0; ve < polygons->GetFaceVertexCount(fa); ++ve) {
692 assert(mesh_pool->has_vertex(ve + polygons->GetFaceVertexOffset() + offset));
693 primitive->add_vertex(mesh_pool->get_vertex(ve + polygons->GetFaceVertexOffset() + offset));
696 offset += polygons->GetFaceVertexCount(fa);
699 delete[] primitive_holders;
702 void DAEToEggConverter::
703 process_spline(
EggGroup *parent,
const string group_name, FCDGeometrySpline* geometry_spline) {
704 assert(geometry_spline != NULL);
708 if (geometry_spline->GetType() != FUDaeSplineType::NURBS) {
709 daeegg_cat.warning() <<
"Only NURBS curves are supported (yet)!" << endl;
712 for (
size_t sp = 0; sp < geometry_spline->GetSplineCount(); ++sp) {
713 process_spline(result, geometry_spline->GetSpline(sp));
718 void DAEToEggConverter::
719 process_spline(
EggGroup *parent,
const FCDSpline* spline) {
720 assert(spline != NULL);
721 nassertv(spline->GetSplineType() == FUDaeSplineType::NURBS);
726 nurbs_curve->setup(0, ((
const FCDNURBSSpline*) spline)->GetKnotCount());
727 for (
size_t kn = 0; kn < ((
const FCDNURBSSpline*) spline)->GetKnotCount(); ++kn) {
728 const float* knot = ((
const FCDNURBSSpline*) spline)->GetKnot(kn);
729 assert(knot != NULL);
730 nurbs_curve->set_knot(kn, *knot);
732 for (
size_t cv = 0; cv < spline->GetCVCount(); ++cv) {
734 c_vtx->set_pos(TO_VEC3(*spline->GetCV(cv)));
736 nurbs_curve->add_vertex(c_vtx);
740 void DAEToEggConverter::
741 process_controller(
EggGroup *parent,
const FCDControllerInstance *instance) {
742 assert(instance != NULL);
743 const FCDController* controller = (
const FCDController *)instance->GetEntity();
744 assert(controller != NULL);
748 const FCDGeometryMesh *mesh = controller->GetBaseGeometry()->GetMesh();
751 daeegg_cat.spam() <<
"Processing mesh for controller\n";
752 process_mesh(parent, mesh, materials);
757 _characters.push_back(character);
760 if (controller->IsMorph()) {
761 assert(controller != NULL);
762 const FCDMorphController* morph_controller = controller->GetMorphController();
763 assert(morph_controller != NULL);
765 bundle->set_table_type(EggTable::TT_bundle);
767 morph->set_table_type(EggTable::TT_table);
768 bundle->add_child(morph);
770 for (
size_t mt = 0; mt < morph_controller->GetTargetCount(); ++mt) {
771 const FCDMorphTarget* morph_target = morph_controller->GetTarget(mt);
772 assert(morph_target != NULL);
774 if (morph_target->IsAnimated()) {
777 target->add_data(morph_target->GetWeight());
779 morph->add_child(target);
784 void DAEToEggConverter::
785 process_extra(
EggGroup *group,
const FCDExtra* extra) {
789 nassertv(group != NULL);
791 const FCDEType* etype = extra->GetDefaultType();
796 const FCDENode* enode = (
const FCDENode*) etype->FindTechnique(
"PANDA3D");
802 enode->FindChildrenNodes(
"param", tags);
803 for (FCDENodeList::iterator it = tags.begin(); it != tags.end(); ++it) {
804 const FCDEAttribute* attr = (*it)->FindAttribute(
"sid");
806 group->
set_tag(FROM_FSTRING(attr->GetValue()), (*it)->GetContent());
812 convert_matrix(
const FMMatrix44 &matrix) {
814 matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],
815 matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],
816 matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],
817 matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]);
820 void DAEToEggConverter::
821 apply_transform(
EggGroup *to,
const FCDTransform* from) {
822 assert(from != NULL);
825 switch (from->GetType()) {
826 case FCDTransform::TRANSLATION:
828 const FCDTTranslation *trans = (
const FCDTTranslation *)from;
833 case FCDTransform::ROTATION:
835 const FCDTRotation *rot = (
const FCDTRotation *)from;
836 to->
add_rotate3d(rot->GetAngle(), TO_VEC3(rot->GetAxis()));
840 case FCDTransform::SCALE:
842 const FCDTScale *scale = (
const FCDTScale *)from;
A base class for any of a number of kinds of geometry primitives: polygons, point lights...
The set of UV's that may or may not be assigned to a vertex.
virtual string get_name() const
Returns the English name of the file type this converter supports.
This is a 4-by-4 transform matrix.
A line segment, or a series of connected line segments, defined by a <Line> entry.
virtual SomethingToEggConverter * make_copy()
Allocates and returns a new copy of the converter.
A base class for nodes in the hierarchy that are not leaf nodes.
A connected fan of triangles.
Corresponding to an <S$Anim> entry, this stores a single column of numbers, for instance for a morph ...
This is a two-component point in space.
virtual bool convert_file(const Filename &filename)
Handles the reading of the input file and converting it to egg.
A single point, or a collection of points as defined by a single <PointLight> entry.
Class representing an animated character.
This class is seperated from the converter file because otherwise it would get too big and needlessly...
This class supervises the construction of an EggData structure from a DAE file.
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
void clear_error()
Resets the error flag to the no-error state.
The name of a file, such as a texture file or an Egg file.
void influence_vertex(int index, EggVertex *vertex)
Adds the influences for the given vertex.
static const LMatrix4d & ident_mat()
Returns an identity matrix.
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal...
AnimationConvert get_animation_convert() const
Returns how source animation will be converted into egg structures.
void bind_joints(JointMap &joint_map)
Binds the joints to the character.
virtual DistanceUnit get_input_units()
This may be called after convert_file() has been called and returned true, indicating a successful co...
void apply_to_group(const string semantic, const PT(EggGroup) to, bool invert_transparency=false)
Applies the colorblend stuff to the given EggGroup.
const LMatrix4d & get_node_to_vertex() const
Returns the transformation matrix suitable for converting vertices in the coordinate space of the nod...
A parametric NURBS curve.
This is the base class for all three-component vectors and points.
void set_tag(const string &key, const string &value)
Associates a user-defined value with a user-defined key which is stored on the node.
This is the base class for all three-component vectors and points.
virtual string get_extension() const
Returns the common extension of the file type this converter supports.
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
EggNode * add_child(EggNode *node)
Adds the indicated child to the group and returns it.
This is our own Panda specialization on the default STL set.
const string get_uvset_name(const string semantic, FUDaeGeometryInput::Semantic input_semantic, int32 input_set)
Returns the semantic of the uvset with the specified input set, or an empty string if the given mater...
void build_table(EggTable *parent, FCDSceneNode *node, const pset< float > &keys)
Processes a joint node and its transforms.
A connected strip of triangles.
string to_os_specific() const
Converts the filename from our generic Unix-like convention (forward slashes starting with the root a...
This is a base class for a family of converter classes that manage a conversion from some file type t...
void apply_to_primitive(const string semantic, const PT(EggPrimitive) to)
Applies the stuff to the given EggPrimitive.
void collect_keys(pset< float > &keys)
Collects all animation keys of animations applied to this character.
A collection of vertices.
void adjust_joints(FCDSceneNode *node, const JointMap &joint_map, const LMatrix4d &transform=LMatrix4d::ident_mat())
Traverses through the character hierarchy in order to bind the mesh to the character.