[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [21918] branches/soc-2009-chingachgook/ source/blender/collada/DocumentImporter.cpp: COLLADA importer:

Arystanbek Dyussenov arystan.d at gmail.com
Sun Jul 26 11:29:26 CEST 2009


Revision: 21918
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=21918
Author:   kazanbas
Date:     2009-07-26 11:29:25 +0200 (Sun, 26 Jul 2009)

Log Message:
-----------
COLLADA importer:
- splitted code into separate classes: ArmatureImporter, MeshImporter
- commented out texture-to-mesh binding code which was difficult to comprehend, Chingiz will re-think/re-write

Modified Paths:
--------------
    branches/soc-2009-chingachgook/source/blender/collada/DocumentImporter.cpp

Modified: branches/soc-2009-chingachgook/source/blender/collada/DocumentImporter.cpp
===================================================================
--- branches/soc-2009-chingachgook/source/blender/collada/DocumentImporter.cpp	2009-07-26 09:28:33 UTC (rev 21917)
+++ branches/soc-2009-chingachgook/source/blender/collada/DocumentImporter.cpp	2009-07-26 09:29:25 UTC (rev 21918)
@@ -121,55 +121,46 @@
 	return "UNKNOWN";
 }
 
-/*
+class UnitConverter
+{
+private:
+	COLLADAFW::FileInfo::Unit unit;
+	COLLADAFW::FileInfo::UpAxisType up_axis;
 
-  COLLADA Importer limitations:
+public:
 
-  - no multiple scene import, all objects are added to active scene
+	UnitConverter() : unit(), up_axis(COLLADAFW::FileInfo::Z_UP) {}
 
- */
-/** Class that needs to be implemented by a writer. 
-	IMPORTANT: The write functions are called in arbitrary order.*/
-class Writer: public COLLADAFW::IWriter
+	void read_asset(const COLLADAFW::FileInfo* asset)
+	{
+	}
+
+	// TODO
+	// convert vector vec from COLLADA format to Blender
+	void convertVec3(float *vec)
+	{
+	}
+		
+	// TODO need also for angle conversion, time conversion...
+
+	void mat4_from_dae_mat4(float out[][4], const COLLADABU::Math::Matrix4& in) {
+		// in DAE, matrices use columns vectors, (see comments in COLLADABUMathMatrix4.h)
+		// so here, to make a blender matrix, we simply swap columns and rows
+		for (int i = 0; i < 4; i++) {
+			for (int j = 0; j < 4; j++) {
+				out[i][j] = in[j][i];
+			}
+		}
+	}
+};
+
+class ArmatureImporter
 {
 private:
-	std::string mFilename;
-	
-	bContext *mContext;
+	Scene *scene;
+	UnitConverter *unit_converter;
 
-	std::map<COLLADAFW::UniqueId, Mesh*> uid_mesh_map; // geometry unique id-to-mesh map
-	std::map<COLLADAFW::UniqueId, Image*> uid_image_map;
-	std::map<COLLADAFW::UniqueId, Material*> uid_material_map;
-	std::map<COLLADAFW::UniqueId, Material*> uid_effect_map;
-	std::map<COLLADAFW::UniqueId, Camera*> uid_camera_map;
-	std::map<COLLADAFW::UniqueId, Lamp*> uid_lamp_map;
-	std::map<COLLADAFW::UniqueId, COLLADAFW::UniqueId> skinid_meshid_map;
-	// maps for assigning textures to uv layers
-	//std::map<COLLADAFW::TextureMapId, char*> set_layername_map;
-	std::map<COLLADAFW::TextureMapId, std::vector<MTex*> > index_mtex_map;
-	// this structure is used to assign material indices to faces
-	// when materials are assigned to an object
-	struct Primitive {
-		MFace *mface;
-		unsigned int totface;
-	};
-	typedef std::map<COLLADAFW::MaterialId, std::vector<Primitive> > MaterialIdPrimitiveArrayMap;
-	// amazing name!
-	std::map<COLLADAFW::UniqueId, MaterialIdPrimitiveArrayMap> geom_uid_mat_mapping_map;
-	// maps for animation
-	std::map<COLLADAFW::UniqueId, std::vector<FCurve*> > uid_fcurve_map;
-	struct AnimatedTransform {
-		Object *ob;
-		// COLLADAFW::Node *node;
-		COLLADAFW::Transformation *tm; // which transform is animated by an AnimationList->id
-	};
-	// Nodes don't share AnimationLists (Arystan)
-	std::map<COLLADAFW::UniqueId, AnimatedTransform> uid_animated_map; // AnimationList->uniqueId to AnimatedObject map
-
-	// ----------------------------------------------------------------------
-	// Armature and related
-
-	// to build armature bones form inverse bind matrices
+	// to build armature bones from inverse bind matrices
 	struct JointData {
 		float inv_bind_mat[4][4]; // joint inverse bind matrix
 		Object *ob_arm;			  // armature object
@@ -177,34 +168,202 @@
 	std::map<int, JointData> joint_index_to_joint_info_map;
 	std::map<COLLADAFW::UniqueId, int> joint_id_to_joint_index_map;
 
+	/*
 	struct ArmatureData {
 		bArmature *arm;
 		COLLADAFW::SkinController *controller;
 	};
 	std::map<COLLADAFW::UniqueId, ArmatureData> controller_id_to_arm_info_map;
+	*/
 
 	std::vector<COLLADAFW::Node*> root_joints;
+	std::map<COLLADAFW::UniqueId, COLLADAFW::UniqueId> controller_id_to_geom_id_map;
 
-	class UnitConverter
+	JointData *get_joint_data(COLLADAFW::Node *node)
 	{
-	private:
-		COLLADAFW::FileInfo::Unit mUnit;
-		COLLADAFW::FileInfo::UpAxisType mUpAxis;
-	public:
-		UnitConverter(COLLADAFW::FileInfo::UpAxisType upAxis, COLLADAFW::FileInfo::Unit& unit) :
-			mUpAxis(upAxis), mUnit(unit)
-		{
+		const COLLADAFW::UniqueId& joint_id = node->getUniqueId();
+
+		if (joint_id_to_joint_index_map.find(joint_id) == joint_id_to_joint_index_map.end()) {
+			fprintf(stderr, "Cannot find a joint index by joint id for %s.\n",
+					node->getOriginalId().c_str());
+			return NULL;
 		}
 
-		// TODO
-		// convert vector vec from COLLADA format to Blender
-		void convertVec3(float *vec)
-		{
+		int joint_index = joint_id_to_joint_index_map[joint_id];
+
+		return &joint_index_to_joint_info_map[joint_index];
+	}
+
+	void create_bone(COLLADAFW::Node *node, EditBone *parent, bArmature *arm)
+	{
+		JointData* jd = get_joint_data(node);
+
+		if (jd) {
+			float mat[4][4];
+
+			// get original world-space matrix
+			Mat4Invert(mat, jd->inv_bind_mat);
+
+			// TODO rename from Node "name" attrs later
+			EditBone *bone = addEditBone(arm, "Bone");
+
+			if (parent) bone->parent = parent;
+
+			// set head
+			VecCopyf(bone->head, mat[3]);
+
+			// set tail, can't set it to head because 0-length bones are not allowed
+			float vec[3] = {0.0f, 0.5f, 0.0f};
+			VecAddf(bone->tail, bone->head, vec);
+
+			// set parent tail
+			if (parent)
+				VecCopyf(parent->tail, bone->head);
+
+			COLLADAFW::NodePointerArray& children = node->getChildNodes();
+			for (int i = 0; i < children.getCount(); i++) {
+				create_bone(children[i], bone, arm);
+			}
 		}
+	}
+
+	void create_bone_branch(COLLADAFW::Node *root)
+	{
+		JointData* jd = get_joint_data(root);
+		if (!jd) return;
+
+		Object *ob_arm = jd->ob_arm;
 		
-		// TODO need also for angle conversion, time conversion...
+		// enter armature edit mode
+		ED_armature_to_edit(ob_arm);
+
+		COLLADAFW::NodePointerArray& children = root->getChildNodes();
+		for (int i = 0; i < children.getCount(); i++) {
+			create_bone(children[i], NULL, (bArmature*)ob_arm->data);
+		}
+
+		// exit armature edit mode
+		ED_armature_from_edit(scene, ob_arm);
+	}
+
+public:
+
+	ArmatureImporter(UnitConverter *conv, Scene *sce) : unit_converter(conv), scene(sce) {}
+
+	void add_root_joint(COLLADAFW::Node *node)
+	{
+		root_joints.push_back(node);
+	}
+
+	bool has_root_joints()
+	{
+		return root_joints.size() > 0;
+	}
+
+	// here we add bones to armature, having armatures previously created in write_controller
+	void build_armatures()
+	{
+		this->scene = scene;
+		std::vector<COLLADAFW::Node*>::iterator it;
+		for (it = root_joints.begin(); it != root_joints.end(); it++) {
+			create_bone_branch(*it);
+		}
+	}
+
+	bool write_skin_controller_data(const COLLADAFW::SkinControllerData* skin)
+	{
+		// use inverse bind matrices to construct armature
+		// it is safe to invert them to get the original matrices
+		// because if they are inverse matrices, they can be inverted
+
+		// just do like so:
+		// - create armature
+		// - enter editmode
+		// - add edit bones and head/tail properties using matrices and parent-child info
+		// - exit edit mode
+
+		// store join inv bind matrix to use it later in armature construction
+		const COLLADAFW::Matrix4Array& inv_bind_mats = skin->getInverseBindMatrices();
+		int i;
+		for (i = 0; i < skin->getJointsCount(); i++) {
+			JointData jd;
+			unit_converter->mat4_from_dae_mat4(jd.inv_bind_mat, inv_bind_mats[i]);
+			joint_index_to_joint_info_map[i] = jd;
+		}
+
+		return true;
+	}
+
+	bool write_controller(const COLLADAFW::Controller* controller)
+	{
+		// here we:
+		// - create armature
+		// - create EditBones, not setting parent-child relationships
+		// - store armature
+
+		const COLLADAFW::UniqueId& skin_id = controller->getUniqueId();
+
+		if (controller->getControllerType() == COLLADAFW::Controller::CONTROLLER_TYPE_SKIN) {
+
+			Object *ob_arm = add_object(this->scene, OB_ARMATURE);
+
+			COLLADAFW::SkinController *skinco = (COLLADAFW::SkinController*)controller;
+			const COLLADAFW::UniqueId& id = skinco->getSkinControllerData();
+
+			// to find geom id by controller id
+			this->controller_id_to_geom_id_map[skin_id] = skinco->getSource();
+			
+			// "Node" ids
+			const COLLADAFW::UniqueIdArray& joint_ids = skinco->getJoints();
+
+			int i;
+			for (i = 0; i < joint_ids.getCount(); i++) {
+
+				// store armature pointer
+				JointData& jd = joint_index_to_joint_info_map[i];
+				jd.ob_arm = ob_arm;
+
+				// now we'll be able to get inv bind matrix from joint id
+				joint_id_to_joint_index_map[joint_ids[i]] = i;
+			}
+		}
+		// morph controller
+		else {
+		}
+
+		return true;
+	}
+
+	COLLADAFW::UniqueId *get_geometry_uid(const COLLADAFW::UniqueId& controller_uid)
+	{
+		if (controller_id_to_geom_id_map.find(controller_uid) == controller_id_to_geom_id_map.end())
+			return NULL;
+
+		return &controller_id_to_geom_id_map[controller_uid];
+	}
+};
+
+class MeshImporter
+{
+private:
+
+	Scene *scene;
+	ArmatureImporter *armature_importer;
+
+	std::map<COLLADAFW::UniqueId, Mesh*> uid_mesh_map; // geometry unique id-to-mesh map
+	// this structure is used to assign material indices to faces
+	// it holds a portion of Mesh faces and corresponds to a DAE primitive list (<triangles>, <polylist>, etc.)
+	struct Primitive {
+		MFace *mface;
+		unsigned int totface;
 	};
+	typedef std::map<COLLADAFW::MaterialId, std::vector<Primitive> > MaterialIdPrimitiveArrayMap;
+	std::map<COLLADAFW::UniqueId, MaterialIdPrimitiveArrayMap> geom_uid_mat_mapping_map; // crazy name!
 
+	// maps for assigning textures to uv layers
+	//std::map<COLLADAFW::TextureMapId, char*> set_layername_map;
+	std::map<COLLADAFW::TextureMapId, std::vector<MTex*> > index_mtex_map;
+
 	class UVDataWrapper
 	{
 		COLLADAFW::MeshVertexData *mVData;
@@ -248,125 +407,347 @@
 		}
 	};
 
-public:
+	void set_face_indices(MFace *mface, unsigned int *indices, bool quad)
+	{
+		mface->v1 = indices[0];
+		mface->v2 = indices[1];
+		mface->v3 = indices[2];
+		if (quad) mface->v4 = indices[3];
+	}
 
-	/** Constructor. */
-	Writer(bContext *C, const char *filename) : mContext(C), mFilename(filename) {};
+	// change face indices order so that v4 is not 0
+	void rotate_face_indices(MFace *mface) {
+		mface->v4 = mface->v1;
+		mface->v1 = mface->v2;
+		mface->v2 = mface->v3;
+		mface->v3 = 0;
+	}
 
-	/** Destructor. */
-	~Writer() {};
-
-	bool write()
+	void set_face_uv(MTFace *mtface, UVDataWrapper &uvs, int uv_set_index,
+					COLLADAFW::IndexList& index_list, int index, bool quad)
 	{
-		COLLADASaxFWL::Loader loader;
-		COLLADAFW::Root root(&loader, this);
+		int uv_indices[4][2];
 
-		// XXX report error

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list