| 
									
										
										
										
											2011-02-23 10:52:22 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2010-10-05 00:05:14 +00:00
										 |  |  |  * ***** BEGIN GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Nathan Letwory. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ***** END GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-27 20:30:35 +00:00
										 |  |  | /** \file blender/collada/collada_utils.cpp
 | 
					
						
							|  |  |  |  *  \ingroup collada | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-12 06:25:04 +00:00
										 |  |  | /* COLLADABU_ASSERT, may be able to remove later */ | 
					
						
							|  |  |  | #include "COLLADABUPlatform.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-05 00:05:14 +00:00
										 |  |  | #include "COLLADAFWGeometry.h"
 | 
					
						
							|  |  |  | #include "COLLADAFWMeshPrimitive.h"
 | 
					
						
							|  |  |  | #include "COLLADAFWMeshVertexData.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-12 21:25:29 +00:00
										 |  |  | #include "collada_utils.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-15 22:00:25 +00:00
										 |  |  | extern "C" { | 
					
						
							| 
									
										
										
										
											2012-06-07 17:55:26 +00:00
										 |  |  | #include "DNA_modifier_types.h"
 | 
					
						
							| 
									
										
										
										
											2010-10-05 00:05:14 +00:00
										 |  |  | #include "DNA_customdata_types.h"
 | 
					
						
							|  |  |  | #include "DNA_object_types.h"
 | 
					
						
							| 
									
										
										
										
											2012-06-07 17:55:26 +00:00
										 |  |  | #include "DNA_mesh_types.h"
 | 
					
						
							| 
									
										
										
										
											2012-05-03 21:32:49 +00:00
										 |  |  | #include "DNA_scene_types.h"
 | 
					
						
							| 
									
										
										
										
											2012-06-15 22:00:25 +00:00
										 |  |  | #include "DNA_armature_types.h"
 | 
					
						
							| 
									
										
										
										
											2010-10-05 00:05:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_math.h"
 | 
					
						
							| 
									
										
										
										
											2012-11-01 15:34:38 +00:00
										 |  |  | #include "BLI_linklist.h"
 | 
					
						
							| 
									
										
										
										
											2013-03-03 01:24:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-05 00:05:14 +00:00
										 |  |  | #include "BKE_context.h"
 | 
					
						
							|  |  |  | #include "BKE_customdata.h"
 | 
					
						
							|  |  |  | #include "BKE_depsgraph.h"
 | 
					
						
							|  |  |  | #include "BKE_object.h"
 | 
					
						
							| 
									
										
										
										
											2013-02-05 13:16:21 +00:00
										 |  |  | #include "BKE_global.h"
 | 
					
						
							| 
									
										
										
										
											2012-06-07 17:55:26 +00:00
										 |  |  | #include "BKE_mesh.h"
 | 
					
						
							| 
									
										
										
										
											2012-05-03 21:32:49 +00:00
										 |  |  | #include "BKE_scene.h"
 | 
					
						
							| 
									
										
										
										
											2012-06-07 17:55:26 +00:00
										 |  |  | #include "BKE_DerivedMesh.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-05 00:05:14 +00:00
										 |  |  | #include "WM_api.h" // XXX hrm, see if we can do without this
 | 
					
						
							|  |  |  | #include "WM_types.h"
 | 
					
						
							| 
									
										
										
										
											2013-03-03 01:24:09 +00:00
										 |  |  | #include "bmesh.h"
 | 
					
						
							| 
									
										
										
										
											2012-06-15 22:00:25 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2010-10-05 00:05:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigned int index) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (index >= array.getValuesCount()) | 
					
						
							|  |  |  | 		return 0.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (array.getType() == COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT) | 
					
						
							|  |  |  | 		return array.getFloatValues()->getData()[index]; | 
					
						
							|  |  |  | 	else  | 
					
						
							|  |  |  | 		return array.getDoubleValues()->getData()[index]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // copied from /editors/object/object_relations.c
 | 
					
						
							|  |  |  | int bc_test_parent_loop(Object *par, Object *ob) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* test if 'ob' is a parent somewhere in par's parents */ | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-03-24 07:52:14 +00:00
										 |  |  | 	if (par == NULL) return 0; | 
					
						
							|  |  |  | 	if (ob == par) return 1; | 
					
						
							| 
									
										
										
										
											2010-10-05 00:05:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	return bc_test_parent_loop(par->parent, ob); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // a shortened version of parent_set_exec()
 | 
					
						
							|  |  |  | // if is_parent_space is true then ob->obmat will be multiplied by par->obmat before parenting
 | 
					
						
							|  |  |  | int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Object workob; | 
					
						
							|  |  |  | 	Scene *sce = CTX_data_scene(C); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (!par || bc_test_parent_loop(par, ob)) | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ob->parent = par; | 
					
						
							|  |  |  | 	ob->partype = PAROBJECT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ob->parsubstr[0] = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (is_parent_space) { | 
					
						
							|  |  |  | 		float mat[4][4]; | 
					
						
							|  |  |  | 		// calc par->obmat
 | 
					
						
							| 
									
										
										
										
											2012-05-05 14:03:12 +00:00
										 |  |  | 		BKE_object_where_is_calc(sce, par); | 
					
						
							| 
									
										
										
										
											2010-10-05 00:05:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// move child obmat into world space
 | 
					
						
							| 
									
										
										
											
												Math lib: matrix multiplication order fix for two functions that were
inconsistent with similar functions & math notation:
mul_m4_m4m4(R, B, A) => mult_m4_m4m4(R, A, B)
mul_m3_m3m4(R, B, A) => mult_m3_m3m4(R, A, B)
For branch maintainers, it should be relatively simple to fix things manually,
it's also possible run this script after merging to do automatic replacement:
http://www.pasteall.org/27459/python
											
										 
											2011-12-16 19:53:12 +00:00
										 |  |  | 		mult_m4_m4m4(mat, par->obmat, ob->obmat); | 
					
						
							| 
									
										
										
										
											2010-10-05 00:05:14 +00:00
										 |  |  | 		copy_m4_m4(ob->obmat, mat); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// apply child obmat (i.e. decompose it into rot/loc/size)
 | 
					
						
							| 
									
										
										
										
											2012-05-05 14:03:12 +00:00
										 |  |  | 	BKE_object_apply_mat4(ob, ob->obmat, 0, 0); | 
					
						
							| 
									
										
										
										
											2010-10-05 00:05:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// compute parentinv
 | 
					
						
							| 
									
										
										
										
											2012-05-05 14:03:12 +00:00
										 |  |  | 	BKE_object_workob_calc_parent(sce, ob, &workob); | 
					
						
							| 
									
										
										
										
											2010-10-05 00:05:14 +00:00
										 |  |  | 	invert_m4_m4(ob->parentinv, workob.obmat); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-21 19:33:04 +00:00
										 |  |  | 	DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); | 
					
						
							|  |  |  | 	DAG_id_tag_update(&par->id, OB_RECALC_OB); | 
					
						
							| 
									
										
										
										
											2010-10-05 00:05:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 14:47:49 +00:00
										 |  |  | 	/** done once after import */ | 
					
						
							|  |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2013-02-21 19:33:04 +00:00
										 |  |  | 	DAG_relations_tag_update(bmain); | 
					
						
							| 
									
										
										
										
											2012-06-12 22:05:33 +00:00
										 |  |  | 	WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); | 
					
						
							| 
									
										
										
										
											2013-03-05 14:47:49 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-10-05 00:05:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-03 21:32:49 +00:00
										 |  |  | Object *bc_add_object(Scene *scene, int type, const char *name) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-02-05 13:16:21 +00:00
										 |  |  | 	Object *ob = BKE_object_add_only_object(G.main, type, name); | 
					
						
							| 
									
										
										
										
											2012-05-03 21:32:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-12 22:05:33 +00:00
										 |  |  | 	ob->data = BKE_object_obdata_add_from_type(type); | 
					
						
							|  |  |  | 	ob->lay = scene->lay; | 
					
						
							| 
									
										
										
										
											2013-02-21 19:33:04 +00:00
										 |  |  | 	DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); | 
					
						
							| 
									
										
										
										
											2012-05-03 21:32:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-05 14:33:36 +00:00
										 |  |  | 	BKE_scene_base_select(scene, BKE_scene_base_add(scene, ob)); | 
					
						
							| 
									
										
										
										
											2012-05-03 21:32:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return ob; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-02 15:58:13 +00:00
										 |  |  | Mesh *bc_get_mesh_copy(Scene *scene, Object *ob, BC_export_mesh_type export_mesh_type, bool apply_modifiers, bool triangulate) | 
					
						
							| 
									
										
										
										
											2012-06-07 17:55:26 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	Mesh *tmpmesh; | 
					
						
							|  |  |  | 	CustomDataMask mask = CD_MASK_MESH; | 
					
						
							| 
									
										
										
										
											2012-12-02 16:01:06 +00:00
										 |  |  | 	DerivedMesh *dm = NULL; | 
					
						
							| 
									
										
										
										
											2013-03-18 18:25:05 +00:00
										 |  |  | 	if (apply_modifiers) { | 
					
						
							| 
									
										
										
										
											2013-03-02 15:58:13 +00:00
										 |  |  | 		switch (export_mesh_type) { | 
					
						
							|  |  |  | 			case BC_MESH_TYPE_VIEW: { | 
					
						
							|  |  |  | 				dm = mesh_create_derived_view(scene, ob, mask); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			case BC_MESH_TYPE_RENDER: { | 
					
						
							|  |  |  | 				dm = mesh_create_derived_render(scene, ob, mask); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-06-16 23:35:53 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-03-02 15:58:13 +00:00
										 |  |  | 	else { | 
					
						
							|  |  |  | 		dm = mesh_create_derived((Mesh *)ob->data, ob, NULL); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-06-16 23:35:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-05 13:04:01 +00:00
										 |  |  | 	tmpmesh = BKE_mesh_add(G.main, "ColladaMesh"); // name is not important here
 | 
					
						
							| 
									
										
										
										
											2012-06-07 17:55:26 +00:00
										 |  |  | 	DM_to_mesh(dm, tmpmesh, ob); | 
					
						
							|  |  |  | 	dm->release(dm); | 
					
						
							| 
									
										
										
										
											2013-03-02 15:58:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (triangulate) { | 
					
						
							|  |  |  | 		bc_triangulate_mesh(tmpmesh); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// XXX Not sure if we need that for ngon_export as well.
 | 
					
						
							|  |  |  | 	BKE_mesh_tessface_ensure(tmpmesh); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-07 17:55:26 +00:00
										 |  |  | 	return tmpmesh; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Object *bc_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 { | 
					
						
							| 
									
										
										
										
											2012-06-12 22:05:33 +00:00
										 |  |  | 		ModifierData *mod; | 
					
						
							|  |  |  | 		for (mod = (ModifierData *)ob->modifiers.first; mod; mod = mod->next) { | 
					
						
							| 
									
										
										
										
											2012-06-07 17:55:26 +00:00
										 |  |  | 			if (mod->type == eModifierType_Armature) { | 
					
						
							| 
									
										
										
										
											2012-06-12 22:05:33 +00:00
										 |  |  | 				ob_arm = ((ArmatureModifierData *)mod)->object; | 
					
						
							| 
									
										
										
										
											2012-06-07 17:55:26 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ob_arm; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-12 21:25:29 +00:00
										 |  |  | // Returns the highest selected ancestor
 | 
					
						
							|  |  |  | // returns NULL if no ancestor is selected
 | 
					
						
							|  |  |  | // IMPORTANT: This function expects that
 | 
					
						
							|  |  |  | // all exported objects have set:
 | 
					
						
							|  |  |  | // ob->id.flag & LIB_DOIT
 | 
					
						
							|  |  |  | Object *bc_get_highest_selected_ancestor_or_self(LinkNode *export_set, Object *ob)  | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Object *ancestor = ob; | 
					
						
							| 
									
										
										
										
											2012-06-27 18:29:47 +00:00
										 |  |  | 	while (ob->parent && bc_is_marked(ob->parent)) { | 
					
						
							| 
									
										
										
										
											2012-06-12 21:25:29 +00:00
										 |  |  | 		ob = ob->parent; | 
					
						
							|  |  |  | 		ancestor = ob; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return ancestor; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-15 22:00:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-12 21:25:29 +00:00
										 |  |  | bool bc_is_base_node(LinkNode *export_set, Object *ob) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Object *root = bc_get_highest_selected_ancestor_or_self(export_set, ob); | 
					
						
							|  |  |  | 	return (root == ob); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool bc_is_in_Export_set(LinkNode *export_set, Object *ob) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-06-16 09:16:24 +00:00
										 |  |  | 	return (BLI_linklist_index(export_set, ob) != -1); | 
					
						
							| 
									
										
										
										
											2012-06-12 21:25:29 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool bc_has_object_type(LinkNode *export_set, short obtype) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-06-16 09:16:24 +00:00
										 |  |  | 	LinkNode *node; | 
					
						
							| 
									
										
										
										
											2012-06-12 21:25:29 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-06-16 09:16:24 +00:00
										 |  |  | 	for (node = export_set; node; node = node->next) { | 
					
						
							| 
									
										
										
										
											2012-06-12 21:25:29 +00:00
										 |  |  | 		Object *ob = (Object *)node->link; | 
					
						
							| 
									
										
										
										
											2012-06-16 09:16:24 +00:00
										 |  |  | 		/* XXX - why is this checking for ob->data? - we could be looking for empties */ | 
					
						
							| 
									
										
										
										
											2012-06-12 21:25:29 +00:00
										 |  |  | 		if (ob->type == obtype && ob->data) { | 
					
						
							|  |  |  | 			return true; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int bc_is_marked(Object *ob) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return ob && (ob->id.flag & LIB_DOIT); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void bc_remove_mark(Object *ob) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ob->id.flag &= ~LIB_DOIT; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-06-14 10:38:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-12 17:13:07 +00:00
										 |  |  | void bc_set_mark(Object *ob) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ob->id.flag |= LIB_DOIT; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-14 10:38:39 +00:00
										 |  |  | // Use bubble sort algorithm for sorting the export set
 | 
					
						
							|  |  |  | void bc_bubble_sort_by_Object_name(LinkNode *export_set) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-06-14 14:48:52 +00:00
										 |  |  | 	bool sorted = false; | 
					
						
							|  |  |  | 	LinkNode *node; | 
					
						
							| 
									
										
										
										
											2012-06-16 09:16:24 +00:00
										 |  |  | 	for (node = export_set; node->next && !sorted; node = node->next) { | 
					
						
							| 
									
										
										
										
											2012-06-14 10:38:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-14 14:48:52 +00:00
										 |  |  | 		sorted = true; | 
					
						
							| 
									
										
										
										
											2012-06-14 10:38:39 +00:00
										 |  |  | 		 | 
					
						
							| 
									
										
										
										
											2012-06-14 14:48:52 +00:00
										 |  |  | 		LinkNode *current; | 
					
						
							| 
									
										
										
										
											2012-06-16 09:16:24 +00:00
										 |  |  | 		for (current = export_set; current->next; current = current->next) { | 
					
						
							| 
									
										
										
										
											2012-06-14 10:38:39 +00:00
										 |  |  | 			Object *a = (Object *)current->link; | 
					
						
							|  |  |  | 			Object *b = (Object *)current->next->link; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-16 09:16:24 +00:00
										 |  |  | 			if (strcmp(a->id.name, b->id.name) > 0) { | 
					
						
							| 
									
										
										
										
											2012-06-14 10:38:39 +00:00
										 |  |  | 				current->link       = b; | 
					
						
							|  |  |  | 				current->next->link = a; | 
					
						
							| 
									
										
										
										
											2012-06-14 14:48:52 +00:00
										 |  |  | 				sorted = false; | 
					
						
							| 
									
										
										
										
											2012-06-14 10:38:39 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-06-15 02:21:07 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2012-06-15 22:00:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Check if a bone is the top most exportable bone in the bone hierarchy. 
 | 
					
						
							|  |  |  |  * When deform_bones_only == false, then only bones with NO parent  | 
					
						
							|  |  |  |  * can be root bones. Otherwise the top most deform bones in the hierarchy | 
					
						
							|  |  |  |  * are root bones. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-06-20 16:43:48 +00:00
										 |  |  | bool bc_is_root_bone(Bone *aBone, bool deform_bones_only) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-06-16 09:16:24 +00:00
										 |  |  | 	if (deform_bones_only) { | 
					
						
							| 
									
										
										
										
											2012-06-15 22:00:25 +00:00
										 |  |  | 		Bone *root = NULL; | 
					
						
							|  |  |  | 		Bone *bone = aBone; | 
					
						
							|  |  |  | 		while (bone) { | 
					
						
							|  |  |  | 			if (!(bone->flag & BONE_NO_DEFORM)) | 
					
						
							|  |  |  | 				root = bone; | 
					
						
							|  |  |  | 			bone = bone->parent; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-06-16 09:16:24 +00:00
										 |  |  | 		return (aBone == root); | 
					
						
							| 
									
										
										
										
											2012-06-15 22:00:25 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		return !(aBone->parent); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-06-22 16:16:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | int bc_get_active_UVLayer(Object *ob) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Mesh *me = (Mesh *)ob->data; | 
					
						
							|  |  |  | 	return CustomData_get_active_layer_index(&me->fdata, CD_MTFACE); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-02-09 00:23:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 14:47:49 +00:00
										 |  |  | std::string bc_url_encode(std::string data) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-02-09 00:23:59 +00:00
										 |  |  | 	/* XXX We probably do not need to do a full encoding.
 | 
					
						
							| 
									
										
										
										
											2013-03-05 14:47:49 +00:00
										 |  |  | 	 * But in case that is necessary,then it can be added here. | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2013-02-09 00:23:59 +00:00
										 |  |  | 	return bc_replace_string(data,"#", "%23"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | std::string bc_replace_string(std::string data, const std::string& pattern, | 
					
						
							| 
									
										
										
										
											2013-03-05 14:47:49 +00:00
										 |  |  |                               const std::string& replacement) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-02-10 17:06:05 +00:00
										 |  |  | 	size_t pos = 0; | 
					
						
							| 
									
										
										
										
											2013-02-10 22:14:56 +00:00
										 |  |  | 	while((pos = data.find(pattern, pos)) != std::string::npos) { | 
					
						
							| 
									
										
										
										
											2013-02-10 17:06:05 +00:00
										 |  |  | 		data.replace(pos, pattern.length(), replacement); | 
					
						
							|  |  |  | 		pos += replacement.length(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return data; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-02-10 22:14:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2013-03-05 14:47:49 +00:00
										 |  |  |  * Calculate a rescale factor such that the imported scene's scale | 
					
						
							|  |  |  |  * is preserved. I.e. 1 meter in the import will also be | 
					
						
							|  |  |  |  * 1 meter in the current scene. | 
					
						
							|  |  |  |  * XXX : I am not sure if it is correct to map 1 Blender Unit | 
					
						
							|  |  |  |  * to 1 Meter for unit type NONE. But it looks reasonable to me. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2013-02-10 22:14:56 +00:00
										 |  |  | void bc_match_scale(std::vector<Object *> *objects_done,  | 
					
						
							| 
									
										
										
										
											2013-03-05 14:47:49 +00:00
										 |  |  |                     Scene &sce, | 
					
						
							| 
									
										
										
										
											2013-03-25 02:41:30 +00:00
										 |  |  |                     UnitConverter &bc_unit) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-02-10 22:14:56 +00:00
										 |  |  | 	Object *ob = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	PointerRNA scene_ptr, unit_settings; | 
					
						
							|  |  |  | 	PropertyRNA *system_ptr, *scale_ptr; | 
					
						
							|  |  |  | 	RNA_id_pointer_create(&sce.id, &scene_ptr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	unit_settings = RNA_pointer_get(&scene_ptr, "unit_settings"); | 
					
						
							|  |  |  | 	system_ptr = RNA_struct_find_property(&unit_settings, "system"); | 
					
						
							|  |  |  | 	scale_ptr = RNA_struct_find_property(&unit_settings, "scale_length"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int   type  = RNA_property_enum_get(&unit_settings, system_ptr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	float bl_scale; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2013-02-11 00:49:00 +00:00
										 |  |  | 	switch (type) { | 
					
						
							|  |  |  | 		case USER_UNIT_NONE: | 
					
						
							|  |  |  | 			bl_scale = 1.0; // map 1 Blender unit to 1 Meter
 | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2013-02-11 11:12:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-11 00:49:00 +00:00
										 |  |  | 		case USER_UNIT_METRIC: | 
					
						
							|  |  |  | 			bl_scale = RNA_property_float_get(&unit_settings, scale_ptr); | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2013-02-11 11:12:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		default : | 
					
						
							| 
									
										
										
										
											2013-02-11 00:49:00 +00:00
										 |  |  | 			bl_scale = RNA_property_float_get(&unit_settings, scale_ptr); | 
					
						
							|  |  |  | 			// it looks like the conversion to Imperial is done implicitly.
 | 
					
						
							|  |  |  | 			// So nothing to do here.
 | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2013-02-10 22:14:56 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2013-02-11 11:12:44 +00:00
										 |  |  | 	float scale_conv = bc_unit.getLinearMeter() / bl_scale; | 
					
						
							| 
									
										
										
										
											2013-02-10 22:14:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	float rescale[3]; | 
					
						
							|  |  |  | 	rescale[0] = rescale[1] = rescale[2] = scale_conv; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-11 11:12:44 +00:00
										 |  |  | 	float size_mat4[4][4]; | 
					
						
							| 
									
										
										
										
											2013-02-15 15:36:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	float axis_mat4[4][4]; | 
					
						
							|  |  |  | 	unit_m4(axis_mat4); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-11 11:12:44 +00:00
										 |  |  | 	size_to_mat4(size_mat4, rescale); | 
					
						
							| 
									
										
										
										
											2013-02-10 22:14:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-11 11:12:44 +00:00
										 |  |  | 	for (std::vector<Object *>::iterator it = objects_done->begin(); | 
					
						
							|  |  |  | 			it != objects_done->end(); | 
					
						
							|  |  |  | 			++it)  | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2013-02-10 22:14:56 +00:00
										 |  |  | 		ob = *it; | 
					
						
							| 
									
										
										
										
											2013-02-11 11:12:44 +00:00
										 |  |  | 		mult_m4_m4m4(ob->obmat, size_mat4, ob->obmat); | 
					
						
							| 
									
										
										
										
											2013-02-15 15:36:02 +00:00
										 |  |  | 		mult_m4_m4m4(ob->obmat, bc_unit.get_rotation(), ob->obmat); | 
					
						
							| 
									
										
										
										
											2013-02-10 22:14:56 +00:00
										 |  |  | 		BKE_object_apply_mat4(ob, ob->obmat, 0, 0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-21 19:33:04 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2013-03-02 15:58:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | void bc_triangulate_mesh(Mesh *me) { | 
					
						
							|  |  |  | 	bool use_beauty = false; | 
					
						
							|  |  |  | 	bool tag_only   = false; | 
					
						
							| 
									
										
										
										
											2013-03-03 01:24:09 +00:00
										 |  |  | 	  | 
					
						
							| 
									
										
										
										
											2013-03-02 15:58:13 +00:00
										 |  |  | 	BMesh *bm = BM_mesh_create(&bm_mesh_allocsize_default); | 
					
						
							|  |  |  | 	BM_mesh_bm_from_me(bm, me, FALSE, 0); | 
					
						
							|  |  |  | 	BM_mesh_triangulate(bm, use_beauty, tag_only, NULL, NULL); | 
					
						
							|  |  |  | 	BM_mesh_bm_to_me(bm, me, FALSE); | 
					
						
							|  |  |  | 	BM_mesh_free(bm); | 
					
						
							|  |  |  | } |