Beispiel #1
0
Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Node *source_node, COLLADAFW::Node *instance_node, Scene *sce, bool is_library_node)
{
	fprintf(stderr, "create <instance_node> under node id=%s from node id=%s\n", instance_node ? instance_node->getOriginalId().c_str() : NULL, source_node ? source_node->getOriginalId().c_str() : NULL);

	Object *obn = BKE_object_copy(source_ob);
	DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
	BKE_scene_base_add(sce, obn);

	if (instance_node) {
		anim_importer.read_node_transform(instance_node, obn);
		// if we also have a source_node (always ;), take its
		// transformation matrix and apply it to the newly instantiated
		// object to account for node hierarchy transforms in
		// .dae
		if (source_node) {
			COLLADABU::Math::Matrix4 mat4 = source_node->getTransformationMatrix();
			COLLADABU::Math::Matrix4 bmat4 = mat4.transpose(); // transpose to get blender row-major order
			float mat[4][4];
			for (int i = 0; i < 4; i++) {
				for (int j = 0; j < 4; j++) {
					mat[i][j] = bmat4[i][j];
				}
			}
			// calc new matrix and apply
			mul_m4_m4m4(obn->obmat, obn->obmat, mat);
			BKE_object_apply_mat4(obn, obn->obmat, 0, 0);
		}
	}
	else {
		anim_importer.read_node_transform(source_node, obn);
	}

	/*DAG_relations_tag_update(CTX_data_main(mContext));*/

	COLLADAFW::NodePointerArray &children = source_node->getChildNodes();
	if (children.getCount()) {
		for (unsigned int i = 0; i < children.getCount(); i++) {
			COLLADAFW::Node *child_node = children[i];
			const COLLADAFW::UniqueId& child_id = child_node->getUniqueId();
			if (object_map.find(child_id) == object_map.end())
				continue;
			COLLADAFW::InstanceNodePointerArray &inodes = child_node->getInstanceNodes();
			Object *new_child = NULL;
			if (inodes.getCount()) { // \todo loop through instance nodes
				const COLLADAFW::UniqueId& id = inodes[0]->getInstanciatedObjectId();
				fprintf(stderr, "Doing %d child nodes\n", (int)node_map.count(id));
				new_child = create_instance_node(object_map.find(id)->second, node_map[id], child_node, sce, is_library_node);
			}
			else {
				new_child = create_instance_node(object_map.find(child_id)->second, child_node, NULL, sce, is_library_node);
			}
			bc_set_parent(new_child, obn, mContext, true);

			if (is_library_node)
				libnode_ob.push_back(new_child);
		}
	}

	return obn;
}
Beispiel #2
0
Object* DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Node *source_node, COLLADAFW::Node *instance_node, Scene *sce, Object *par_ob, bool is_library_node)
{
	Object *obn = copy_object(source_ob);
	obn->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
	scene_add_base(sce, obn);

	if (instance_node) {
		anim_importer.read_node_transform(instance_node, obn);
		// if we also have a source_node (always ;), take its
		// transformation matrix and apply it to the newly instantiated
		// object to account for node hierarchy transforms in
		// .dae
		if(source_node) {
			COLLADABU::Math::Matrix4 mat4 = source_node->getTransformationMatrix();
			COLLADABU::Math::Matrix4 bmat4 = mat4.transpose(); // transpose to get blender row-major order
			float mat[4][4];
			for (int i = 0; i < 4; i++) {
				for (int j = 0; j < 4; j++) {
					mat[i][j] = bmat4[i][j];
				}
			}
			// calc new matrix and apply
			mul_m4_m4m4(obn->obmat, mat, obn->obmat);
			object_apply_mat4(obn, obn->obmat, 0, 0);
		}
	}
	else {
		anim_importer.read_node_transform(source_node, obn);
	}

	DAG_scene_sort(CTX_data_main(mContext), sce);
	DAG_ids_flush_update(CTX_data_main(mContext), 0);

	COLLADAFW::NodePointerArray &children = source_node->getChildNodes();
	if (children.getCount()) {
		for (unsigned int i = 0; i < children.getCount(); i++) {
			COLLADAFW::Node *child_node = children[i];
			const COLLADAFW::UniqueId& child_id = child_node->getUniqueId();
			if (object_map.find(child_id) == object_map.end())
				continue;
			COLLADAFW::InstanceNodePointerArray &inodes = child_node->getInstanceNodes();
			Object *new_child = NULL;
			if (inodes.getCount()) { // \todo loop through instance nodes
				const COLLADAFW::UniqueId& id = inodes[0]->getInstanciatedObjectId();
				new_child = create_instance_node(object_map[id], node_map[id], child_node, sce, NULL, is_library_node);
			}
			else {
				new_child = create_instance_node(object_map[child_id], child_node, NULL, sce, NULL, is_library_node);
			}
			bc_set_parent(new_child, obn, mContext, true);

			if (is_library_node)
				libnode_ob.push_back(new_child);
		}
	}

	// when we have an instance_node, don't return the object, because otherwise
	// its correct location gets overwritten in write_node(). Fixes bug #26012.
	if(instance_node) {
		if (par_ob && obn)
			bc_set_parent(obn, par_ob, mContext);
		return NULL;
	}

	else return obn;
}
Beispiel #3
0
void DocumentImporter::write_node (COLLADAFW::Node *node, COLLADAFW::Node *parent_node, Scene *sce, Object *par, bool is_library_node)
{
	Object *ob = NULL;
	bool is_joint = node->getType() == COLLADAFW::Node::JOINT;

	if (is_joint) {
		if ( par ) {
		Object * empty = par;
		par = add_object(sce, OB_ARMATURE);
		bc_set_parent(par,empty->parent, mContext);
		//remove empty : todo
		object_map[parent_node->getUniqueId()] = par;
		}
		armature_importer.add_joint(node, parent_node == NULL || parent_node->getType() != COLLADAFW::Node::JOINT, par, sce);
	}
	else {
		COLLADAFW::InstanceGeometryPointerArray &geom = node->getInstanceGeometries();
		COLLADAFW::InstanceCameraPointerArray &camera = node->getInstanceCameras();
		COLLADAFW::InstanceLightPointerArray &lamp = node->getInstanceLights();
		COLLADAFW::InstanceControllerPointerArray &controller = node->getInstanceControllers();
		COLLADAFW::InstanceNodePointerArray &inst_node = node->getInstanceNodes();
		size_t geom_done = 0;
		size_t camera_done = 0;
		size_t lamp_done = 0;
		size_t controller_done = 0;
		size_t inst_done = 0;

		// XXX linking object with the first <instance_geometry>, though a node may have more of them...
		// maybe join multiple <instance_...> meshes into 1, and link object with it? not sure...
		// <instance_geometry>
		while (geom_done < geom.getCount()) {
			ob = mesh_importer.create_mesh_object(node, geom[geom_done], false, uid_material_map,
												  material_texture_mapping_map);
			++geom_done;
		}
		while (camera_done < camera.getCount()) {
			ob = create_camera_object(camera[camera_done], sce);
			++camera_done;
		}
		while (lamp_done < lamp.getCount()) {
			ob = create_lamp_object(lamp[lamp_done], sce);
			++lamp_done;
		}
		while (controller_done < controller.getCount()) {
			COLLADAFW::InstanceGeometry *geom = (COLLADAFW::InstanceGeometry*)controller[controller_done];
			ob = mesh_importer.create_mesh_object(node, geom, true, uid_material_map, material_texture_mapping_map);
			++controller_done;
		}
		// XXX instance_node is not supported yet
		while (inst_done < inst_node.getCount()) {
			const COLLADAFW::UniqueId& node_id = inst_node[inst_done]->getInstanciatedObjectId();
			if (object_map.find(node_id) == object_map.end()) {
				fprintf(stderr, "Cannot find node to instanciate.\n");
				ob = NULL;
			}
			else {
				Object *source_ob = object_map[node_id];
				COLLADAFW::Node *source_node = node_map[node_id];

				ob = create_instance_node(source_ob, source_node, node, sce, par, is_library_node);
			}
			++inst_done;
		}
		// if node is empty - create empty object
		// XXX empty node may not mean it is empty object, not sure about this
		if ( (geom_done + camera_done + lamp_done + controller_done + inst_done) < 1) {
			ob = add_object(sce, OB_EMPTY);
		}
		
		// check if object is not NULL
		if (!ob) return;
		
		std::string nodename = node->getName().size() ? node->getName() : node->getOriginalId();
		rename_id(&ob->id, (char*)nodename.c_str());

		object_map[node->getUniqueId()] = ob;
		node_map[node->getUniqueId()] = node;

		if (is_library_node)
			libnode_ob.push_back(ob);
	}

	anim_importer.read_node_transform(node, ob); // overwrites location set earlier

	if (!is_joint) {
		// if par was given make this object child of the previous 
		if (par && ob)
			bc_set_parent(ob, par, mContext);
	}

	// if node has child nodes write them
	COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes();
	for (unsigned int i = 0; i < child_nodes.getCount(); i++) {	
		write_node(child_nodes[i], node, sce, ob, is_library_node);
	}
}
Beispiel #4
0
void SkinInfo::link_armature(bContext *C, Object *ob, std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& joint_by_uid,
				   TransformReader *tm)
{
	Main *bmain = CTX_data_main(C);
	Scene *scene = CTX_data_scene(C);

	ModifierData *md = ED_object_modifier_add(NULL, bmain, scene, ob, NULL, eModifierType_Armature);
	((ArmatureModifierData *)md)->object = ob_arm;

	copy_m4_m4(ob->obmat, bind_shape_matrix);
	object_apply_mat4(ob, ob->obmat, 0, 0);
#if 1
	bc_set_parent(ob, ob_arm, C);
#else
	Object workob;
	ob->parent = ob_arm;
	ob->partype = PAROBJECT;

	what_does_parent(scene, ob, &workob);
	invert_m4_m4(ob->parentinv, workob.obmat);

	ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA;

	DAG_scene_sort(bmain, scene);
	DAG_ids_flush_update(bmain, 0);
	WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
#endif

	((bArmature*)ob_arm->data)->deformflag = ARM_DEF_VGROUP;

	// create all vertex groups
	std::vector<JointData>::iterator it;
	int joint_index;
	for (it = joint_data.begin(), joint_index = 0; it != joint_data.end(); it++, joint_index++) {
		const char *name = "Group";

		// skip joints that have invalid UID
		if ((*it).joint_uid == COLLADAFW::UniqueId::INVALID) continue;
		
		// name group by joint node name
		
		if (joint_by_uid.find((*it).joint_uid) != joint_by_uid.end()) {
			name = bc_get_joint_name(joint_by_uid[(*it).joint_uid]);
		}

		ED_vgroup_add_name(ob, (char*)name);
	}

	// <vcount> - number of joints per vertex - joints_per_vertex
	// <v> - [[bone index, weight index] * joints per vertex] * vertices - weight indices
	// ^ bone index can be -1 meaning weight toward bind shape, how to express this in Blender?

	// for each vertex in weight indices
	//	for each bone index in vertex
	//		add vertex to group at group index
	//		treat group index -1 specially

	// get def group by index with BLI_findlink

	for (unsigned int vertex = 0, weight = 0; vertex < joints_per_vertex.getCount(); vertex++) {

		unsigned int limit = weight + joints_per_vertex[vertex];
		for ( ; weight < limit; weight++) {
			int joint = joint_indices[weight], joint_weight = weight_indices[weight];

			// -1 means "weight towards the bind shape", we just don't assign it to any group
			if (joint != -1) {
				bDeformGroup *def = (bDeformGroup*)BLI_findlink(&ob->defbase, joint);

				ED_vgroup_vert_add(ob, def, vertex, weights[joint_weight], WEIGHT_REPLACE);
			}
		}
	}
}