From 7245280f6c9c797e92d51bd10fc1d1127efdd394 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Wed, 6 Oct 2010 11:02:44 +0000 Subject: COLLADA: Split ArmatureExporter, InstanceWriter and TransformWriter into separate files. --- source/blender/collada/DocumentExporter.cpp | 567 +--------------------------- 1 file changed, 9 insertions(+), 558 deletions(-) (limited to 'source/blender/collada/DocumentExporter.cpp') diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp index 0a3166c37c3..ad85a81c6f8 100644 --- a/source/blender/collada/DocumentExporter.cpp +++ b/source/blender/collada/DocumentExporter.cpp @@ -34,8 +34,6 @@ extern "C" #include "DNA_image_types.h" #include "DNA_material_types.h" #include "DNA_texture_types.h" -//#include "DNA_camera_types.h" -//#include "DNA_lamp_types.h" #include "DNA_anim_types.h" #include "DNA_action_types.h" #include "DNA_curve_types.h" @@ -74,7 +72,6 @@ extern char build_rev[]; #include "COLLADASWAsset.h" #include "COLLADASWLibraryVisualScenes.h" #include "COLLADASWNode.h" -//#include "COLLADASWLibraryGeometries.h" #include "COLLADASWSource.h" #include "COLLADASWInstanceGeometry.h" #include "COLLADASWInputList.h" @@ -95,11 +92,8 @@ extern char build_rev[]; #include "COLLADASWTexture.h" #include "COLLADASWLibraryMaterials.h" #include "COLLADASWBindMaterial.h" -//#include "COLLADASWLibraryCameras.h" -//#include "COLLADASWLibraryLights.h" #include "COLLADASWInstanceCamera.h" #include "COLLADASWInstanceLight.h" -//#include "COLLADASWCameraOptic.h" #include "COLLADASWConstants.h" #include "COLLADASWLibraryControllers.h" #include "COLLADASWInstanceController.h" @@ -108,14 +102,19 @@ extern char build_rev[]; #include "collada_internal.h" #include "DocumentExporter.h" +#include "ArmatureExporter.h" #include "CameraExporter.h" -#include "LightExporter.h" #include "GeometryExporter.h" +#include "LightExporter.h" + +// can probably go after refactor is complete +#include "InstanceWriter.h" +#include "TransformWriter.h" #include #include // std::find -char *CustomData_get_layer_name(const struct CustomData *data, int type, int n) +char *bc_CustomData_get_layer_name(const struct CustomData *data, int type, int n) { int layer_index = CustomData_get_layer_index(data, type); if(layer_index < 0) return NULL; @@ -123,7 +122,7 @@ char *CustomData_get_layer_name(const struct CustomData *data, int type, int n) return data->layers[layer_index+n].name; } -char *CustomData_get_active_layer_name(const CustomData *data, int type) +char *bc_CustomData_get_active_layer_name(const CustomData *data, int type) { /* get the layer index of the active layer of type */ int layer_index = CustomData_get_active_layer_index(data, type); @@ -133,7 +132,6 @@ char *CustomData_get_active_layer_name(const CustomData *data, int type) } - /* Utilities to avoid code duplication. Definition can take some time to understand, but they should be useful. @@ -198,558 +196,11 @@ std::string getActiveUVLayerName(Object *ob) int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE); if (num_layers) - return std::string(CustomData_get_active_layer_name(&me->fdata, CD_MTFACE)); + return std::string(bc_CustomData_get_active_layer_name(&me->fdata, CD_MTFACE)); return ""; } - -class TransformWriter : protected TransformBase -{ -protected: - void add_node_transform(COLLADASW::Node& node, float mat[][4], float parent_mat[][4]) - { - float loc[3], rot[3], scale[3]; - float local[4][4]; - - if (parent_mat) { - float invpar[4][4]; - invert_m4_m4(invpar, parent_mat); - mul_m4_m4m4(local, mat, invpar); - } - else { - copy_m4_m4(local, mat); - } - - TransformBase::decompose(local, loc, rot, NULL, scale); - - add_transform(node, loc, rot, scale); - } - - void add_node_transform_ob(COLLADASW::Node& node, Object *ob) - { - float rot[3], loc[3], scale[3]; - - if (ob->parent) { - float C[4][4], tmat[4][4], imat[4][4], mat[4][4]; - - // factor out scale from obmat - - copy_v3_v3(scale, ob->size); - - ob->size[0] = ob->size[1] = ob->size[2] = 1.0f; - object_to_mat4(ob, C); - copy_v3_v3(ob->size, scale); - - mul_serie_m4(tmat, ob->parent->obmat, ob->parentinv, C, NULL, NULL, NULL, NULL, NULL); - - // calculate local mat - - invert_m4_m4(imat, ob->parent->obmat); - mul_m4_m4m4(mat, tmat, imat); - - // done - - mat4_to_eul(rot, mat); - copy_v3_v3(loc, mat[3]); - } - else { - copy_v3_v3(loc, ob->loc); - copy_v3_v3(rot, ob->rot); - copy_v3_v3(scale, ob->size); - } - - add_transform(node, loc, rot, scale); - } - - void add_node_transform_identity(COLLADASW::Node& node) - { - float loc[] = {0.0f, 0.0f, 0.0f}, scale[] = {1.0f, 1.0f, 1.0f}, rot[] = {0.0f, 0.0f, 0.0f}; - add_transform(node, loc, rot, scale); - } - -private: - void add_transform(COLLADASW::Node& node, float loc[3], float rot[3], float scale[3]) - { - node.addTranslate("location", loc[0], loc[1], loc[2]); - node.addRotateZ("rotationZ", COLLADABU::Math::Utils::radToDegF(rot[2])); - node.addRotateY("rotationY", COLLADABU::Math::Utils::radToDegF(rot[1])); - node.addRotateX("rotationX", COLLADABU::Math::Utils::radToDegF(rot[0])); - node.addScale("scale", scale[0], scale[1], scale[2]); - } -}; - -class InstanceWriter -{ -protected: - void add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob) - { - for(int a = 0; a < ob->totcol; a++) { - Material *ma = give_current_material(ob, a+1); - - COLLADASW::InstanceMaterialList& iml = bind_material.getInstanceMaterialList(); - - if (ma) { - std::string matid(id_name(ma)); - matid = translate_id(matid); - COLLADASW::InstanceMaterial im(matid, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, matid)); - - // create for each uv layer - Mesh *me = (Mesh*)ob->data; - int totlayer = CustomData_number_of_layers(&me->fdata, CD_MTFACE); - - for (int b = 0; b < totlayer; b++) { - char *name = CustomData_get_layer_name(&me->fdata, CD_MTFACE, b); - im.push_back(COLLADASW::BindVertexInput(name, "TEXCOORD", b)); - } - - iml.push_back(im); - } - } - } -}; - -// XXX exporter writes wrong data for shared armatures. A separate -// controller should be written for each armature-mesh binding how do -// we make controller ids then? -class ArmatureExporter: public COLLADASW::LibraryControllers, protected TransformWriter, protected InstanceWriter -{ -private: - Scene *scene; - -public: - ArmatureExporter(COLLADASW::StreamWriter *sw) : COLLADASW::LibraryControllers(sw) {} - - // write bone nodes - void add_armature_bones(Object *ob_arm, Scene *sce) - { - // write bone nodes - bArmature *arm = (bArmature*)ob_arm->data; - for (Bone *bone = (Bone*)arm->bonebase.first; bone; bone = bone->next) { - // start from root bones - if (!bone->parent) - add_bone_node(bone, ob_arm); - } - } - - bool is_skinned_mesh(Object *ob) - { - return get_assigned_armature(ob) != NULL; - } - - void add_instance_controller(Object *ob) - { - Object *ob_arm = get_assigned_armature(ob); - bArmature *arm = (bArmature*)ob_arm->data; - - const std::string& controller_id = get_controller_id(ob_arm, ob); - - COLLADASW::InstanceController ins(mSW); - ins.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, controller_id)); - - // write root bone URLs - Bone *bone; - for (bone = (Bone*)arm->bonebase.first; bone; bone = bone->next) { - if (!bone->parent) - ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_joint_id(bone, ob_arm))); - } - - InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob); - - ins.add(); - } - - void export_controllers(Scene *sce) - { - scene = sce; - - openLibrary(); - - GeometryFunctor gf; - gf.forEachMeshObjectInScene(sce, *this); - - closeLibrary(); - } - - void operator()(Object *ob) - { - Object *ob_arm = get_assigned_armature(ob); - - if (ob_arm /*&& !already_written(ob_arm)*/) - export_controller(ob, ob_arm); - } - -private: - - UnitConverter converter; - -#if 0 - std::vector written_armatures; - - bool already_written(Object *ob_arm) - { - return std::find(written_armatures.begin(), written_armatures.end(), ob_arm) != written_armatures.end(); - } - - void wrote(Object *ob_arm) - { - written_armatures.push_back(ob_arm); - } - - void find_objects_using_armature(Object *ob_arm, std::vector& objects, Scene *sce) - { - objects.clear(); - - Base *base= (Base*) sce->base.first; - while(base) { - Object *ob = base->object; - - if (ob->type == OB_MESH && get_assigned_armature(ob) == ob_arm) { - objects.push_back(ob); - } - - base= base->next; - } - } -#endif - - Object *get_assigned_armature(Object *ob) - { - Object *ob_arm = NULL; - - if (ob->parent && ob->partype == PARSKEL && ob->parent->type == OB_ARMATURE) { - ob_arm = ob->parent; - } - else { - ModifierData *mod = (ModifierData*)ob->modifiers.first; - while (mod) { - if (mod->type == eModifierType_Armature) { - ob_arm = ((ArmatureModifierData*)mod)->object; - } - - mod = mod->next; - } - } - - return ob_arm; - } - - std::string get_joint_sid(Bone *bone, Object *ob_arm) - { - return get_joint_id(bone, ob_arm); - } - - // parent_mat is armature-space - void add_bone_node(Bone *bone, Object *ob_arm) - { - std::string node_id = get_joint_id(bone, ob_arm); - std::string node_name = std::string(bone->name); - std::string node_sid = get_joint_sid(bone, ob_arm); - - COLLADASW::Node node(mSW); - - node.setType(COLLADASW::Node::JOINT); - node.setNodeId(node_id); - node.setNodeName(node_name); - node.setNodeSid(node_sid); - - node.start(); - - add_bone_transform(ob_arm, bone, node); - - for (Bone *child = (Bone*)bone->childbase.first; child; child = child->next) { - add_bone_node(child, ob_arm); - } - - node.end(); - } - - void add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node& node) - { - bPoseChannel *pchan = get_pose_channel(ob_arm->pose, bone->name); - - float mat[4][4]; - - if (bone->parent) { - // get bone-space matrix from armature-space - bPoseChannel *parchan = get_pose_channel(ob_arm->pose, bone->parent->name); - - float invpar[4][4]; - invert_m4_m4(invpar, parchan->pose_mat); - mul_m4_m4m4(mat, pchan->pose_mat, invpar); - } - else { - // get world-space from armature-space - mul_m4_m4m4(mat, pchan->pose_mat, ob_arm->obmat); - } - - TransformWriter::add_node_transform(node, mat, NULL); - } - - std::string get_controller_id(Object *ob_arm, Object *ob) - { - return translate_id(id_name(ob_arm)) + "_" + translate_id(id_name(ob)) + SKIN_CONTROLLER_ID_SUFFIX; - } - - // ob should be of type OB_MESH - // both args are required - void export_controller(Object* ob, Object *ob_arm) - { - // joint names - // joint inverse bind matrices - // vertex weights - - // input: - // joint names: ob -> vertex group names - // vertex group weights: me->dvert -> groups -> index, weight - - /* - me->dvert: - - typedef struct MDeformVert { - struct MDeformWeight *dw; - int totweight; - int flag; // flag only in use for weightpaint now - } MDeformVert; - - typedef struct MDeformWeight { - int def_nr; - float weight; - } MDeformWeight; - */ - - Mesh *me = (Mesh*)ob->data; - if (!me->dvert) return; - - std::string controller_name = id_name(ob_arm); - std::string controller_id = get_controller_id(ob_arm, ob); - - openSkin(controller_id, controller_name, - COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob))); - - add_bind_shape_mat(ob); - - std::string joints_source_id = add_joints_source(ob_arm, &ob->defbase, controller_id); - std::string inv_bind_mat_source_id = add_inv_bind_mats_source(ob_arm, &ob->defbase, controller_id); - std::string weights_source_id = add_weights_source(me, controller_id); - - add_joints_element(&ob->defbase, joints_source_id, inv_bind_mat_source_id); - add_vertex_weights_element(weights_source_id, joints_source_id, me, ob_arm, &ob->defbase); - - closeSkin(); - closeController(); - } - - void add_joints_element(ListBase *defbase, - const std::string& joints_source_id, const std::string& inv_bind_mat_source_id) - { - COLLADASW::JointsElement joints(mSW); - COLLADASW::InputList &input = joints.getInputList(); - - input.push_back(COLLADASW::Input(COLLADASW::JOINT, // constant declared in COLLADASWInputList.h - COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id))); - input.push_back(COLLADASW::Input(COLLADASW::BINDMATRIX, - COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, inv_bind_mat_source_id))); - joints.add(); - } - - void add_bind_shape_mat(Object *ob) - { - double bind_mat[4][4]; - - converter.mat4_to_dae_double(bind_mat, ob->obmat); - - addBindShapeTransform(bind_mat); - } - - std::string add_joints_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id) - { - std::string source_id = controller_id + JOINTS_SOURCE_ID_SUFFIX; - - int totjoint = 0; - bDeformGroup *def; - for (def = (bDeformGroup*)defbase->first; def; def = def->next) { - if (is_bone_defgroup(ob_arm, def)) - totjoint++; - } - - COLLADASW::NameSource source(mSW); - source.setId(source_id); - source.setArrayId(source_id + ARRAY_ID_SUFFIX); - source.setAccessorCount(totjoint); - source.setAccessorStride(1); - - COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - param.push_back("JOINT"); - - source.prepareToAppendValues(); - - for (def = (bDeformGroup*)defbase->first; def; def = def->next) { - Bone *bone = get_bone_from_defgroup(ob_arm, def); - if (bone) - source.appendValues(get_joint_sid(bone, ob_arm)); - } - - source.finish(); - - return source_id; - } - - std::string add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id) - { - std::string source_id = controller_id + BIND_POSES_SOURCE_ID_SUFFIX; - - COLLADASW::FloatSourceF source(mSW); - source.setId(source_id); - source.setArrayId(source_id + ARRAY_ID_SUFFIX); - source.setAccessorCount(BLI_countlist(defbase)); - source.setAccessorStride(16); - - source.setParameterTypeName(&COLLADASW::CSWC::CSW_VALUE_TYPE_FLOAT4x4); - COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - param.push_back("TRANSFORM"); - - source.prepareToAppendValues(); - - bPose *pose = ob_arm->pose; - bArmature *arm = (bArmature*)ob_arm->data; - - int flag = arm->flag; - - // put armature in rest position - if (!(arm->flag & ARM_RESTPOS)) { - arm->flag |= ARM_RESTPOS; - where_is_pose(scene, ob_arm); - } - - for (bDeformGroup *def = (bDeformGroup*)defbase->first; def; def = def->next) { - if (is_bone_defgroup(ob_arm, def)) { - - bPoseChannel *pchan = get_pose_channel(pose, def->name); - - float mat[4][4]; - float world[4][4]; - float inv_bind_mat[4][4]; - - // make world-space matrix, pose_mat is armature-space - mul_m4_m4m4(world, pchan->pose_mat, ob_arm->obmat); - - invert_m4_m4(mat, world); - converter.mat4_to_dae(inv_bind_mat, mat); - - source.appendValues(inv_bind_mat); - } - } - - // back from rest positon - if (!(flag & ARM_RESTPOS)) { - arm->flag = flag; - where_is_pose(scene, ob_arm); - } - - source.finish(); - - return source_id; - } - - Bone *get_bone_from_defgroup(Object *ob_arm, bDeformGroup* def) - { - bPoseChannel *pchan = get_pose_channel(ob_arm->pose, def->name); - return pchan ? pchan->bone : NULL; - } - - bool is_bone_defgroup(Object *ob_arm, bDeformGroup* def) - { - return get_bone_from_defgroup(ob_arm, def) != NULL; - } - - std::string add_weights_source(Mesh *me, const std::string& controller_id) - { - std::string source_id = controller_id + WEIGHTS_SOURCE_ID_SUFFIX; - - int i; - int totweight = 0; - - for (i = 0; i < me->totvert; i++) { - totweight += me->dvert[i].totweight; - } - - COLLADASW::FloatSourceF source(mSW); - source.setId(source_id); - source.setArrayId(source_id + ARRAY_ID_SUFFIX); - source.setAccessorCount(totweight); - source.setAccessorStride(1); - - COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - param.push_back("WEIGHT"); - - source.prepareToAppendValues(); - - // NOTE: COLLADA spec says weights should be normalized - - for (i = 0; i < me->totvert; i++) { - MDeformVert *vert = &me->dvert[i]; - for (int j = 0; j < vert->totweight; j++) { - source.appendValues(vert->dw[j].weight); - } - } - - source.finish(); - - return source_id; - } - - void add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id, Mesh *me, - Object *ob_arm, ListBase *defbase) - { - COLLADASW::VertexWeightsElement weights(mSW); - COLLADASW::InputList &input = weights.getInputList(); - - int offset = 0; - input.push_back(COLLADASW::Input(COLLADASW::JOINT, // constant declared in COLLADASWInputList.h - COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id), offset++)); - input.push_back(COLLADASW::Input(COLLADASW::WEIGHT, - COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, weights_source_id), offset++)); - - weights.setCount(me->totvert); - - // write number of deformers per vertex - COLLADASW::PrimitivesBase::VCountList vcount; - int i; - for (i = 0; i < me->totvert; i++) { - vcount.push_back(me->dvert[i].totweight); - } - - weights.prepareToAppendVCountValues(); - weights.appendVertexCount(vcount); - - // def group index -> joint index - std::map joint_index_by_def_index; - bDeformGroup *def; - int j; - for (def = (bDeformGroup*)defbase->first, i = 0, j = 0; def; def = def->next, i++) { - if (is_bone_defgroup(ob_arm, def)) - joint_index_by_def_index[i] = j++; - else - joint_index_by_def_index[i] = -1; - } - - weights.CloseVCountAndOpenVElement(); - - // write deformer index - weight index pairs - int weight_index = 0; - for (i = 0; i < me->totvert; i++) { - MDeformVert *dvert = &me->dvert[i]; - for (int j = 0; j < dvert->totweight; j++) { - weights.appendValues(joint_index_by_def_index[dvert->dw[j].def_nr]); - weights.appendValues(weight_index++); - } - } - - weights.finish(); - } -}; - class SceneExporter: COLLADASW::LibraryVisualScenes, protected TransformWriter, protected InstanceWriter { ArmatureExporter *arm_exporter; -- cgit v1.2.3