| 
									
										
										
										
											2011-02-23 10:52:22 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +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, | 
					
						
							| 
									
										
										
										
											2010-02-12 13:34:04 +00:00
										 |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is: all of this file. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Contributor(s): none yet. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ***** END GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-25 13:30:41 +00:00
										 |  |  | /** \file gameengine/Converter/BL_ArmatureChannel.cpp
 | 
					
						
							|  |  |  |  *  \ingroup bgeconv | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | #include "DNA_armature_types.h"
 | 
					
						
							|  |  |  | #include "BL_ArmatureChannel.h"
 | 
					
						
							|  |  |  | #include "BL_ArmatureObject.h"
 | 
					
						
							|  |  |  | #include "BL_ArmatureConstraint.h"
 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | #include "BLI_math.h"
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | #include "BLI_string.h"
 | 
					
						
							| 
									
										
										
										
											2011-03-30 16:14:54 +00:00
										 |  |  | #include <stddef.h>
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-31 04:11:39 +00:00
										 |  |  | #ifdef WITH_PYTHON
 | 
					
						
							| 
									
										
										
										
											2009-09-29 21:42:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | PyTypeObject BL_ArmatureChannel::Type = { | 
					
						
							|  |  |  | 	PyVarObject_HEAD_INIT(NULL, 0) | 
					
						
							|  |  |  | 	"BL_ArmatureChannel", | 
					
						
							|  |  |  | 	sizeof(PyObjectPlus_Proxy), | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 	py_base_dealloc, | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 	py_base_repr, | 
					
						
							|  |  |  | 	0,0,0,0,0,0,0,0,0, | 
					
						
							|  |  |  | 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, | 
					
						
							|  |  |  | 	0,0,0,0,0,0,0, | 
					
						
							|  |  |  | 	Methods, | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 	&CValue::Type, | 
					
						
							|  |  |  | 	0,0,0,0,0,0, | 
					
						
							|  |  |  | 	py_base_new | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject* BL_ArmatureChannel::py_repr(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return PyUnicode_FromString(m_posechannel->name); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject *BL_ArmatureChannel::GetProxy() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return GetProxyPlus_Ext(this, &Type, m_posechannel); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject *BL_ArmatureChannel::NewProxy(bool py_owns) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return NewProxyPlus_Ext(this, &Type, m_posechannel, py_owns); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-31 04:11:39 +00:00
										 |  |  | #endif // WITH_PYTHON
 | 
					
						
							| 
									
										
										
										
											2009-09-29 21:42:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | BL_ArmatureChannel::BL_ArmatureChannel( | 
					
						
							|  |  |  | 	BL_ArmatureObject *armature,  | 
					
						
							|  |  |  | 	bPoseChannel *posechannel) | 
					
						
							|  |  |  | 	: PyObjectPlus(), m_posechannel(posechannel), m_armature(armature) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BL_ArmatureChannel::~BL_ArmatureChannel() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-31 04:11:39 +00:00
										 |  |  | #ifdef WITH_PYTHON
 | 
					
						
							| 
									
										
										
										
											2009-09-29 21:42:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | // PYTHON
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyMethodDef BL_ArmatureChannel::Methods[] = { | 
					
						
							|  |  |  |   {NULL,NULL} //Sentinel
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // order of definition of attributes, must match Attributes[] array
 | 
					
						
							|  |  |  | #define BCA_BONE		0
 | 
					
						
							|  |  |  | #define BCA_PARENT		1
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyAttributeDef BL_ArmatureChannel::Attributes[] = { | 
					
						
							|  |  |  | 	// Keep these attributes in order of BCA_ defines!!! used by py_attr_getattr and py_attr_setattr
 | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_RO_FUNCTION("bone",BL_ArmatureChannel,py_attr_getattr),	 | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_RO_FUNCTION("parent",BL_ArmatureChannel,py_attr_getattr),	 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	{ NULL }	//Sentinel
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* attributes directly taken from bPoseChannel */ | 
					
						
							|  |  |  | PyAttributeDef BL_ArmatureChannel::AttributesPtr[] = { | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_CHAR_RO("name",bPoseChannel,name), | 
					
						
							| 
									
										
										
										
											2010-08-26 23:49:46 +00:00
										 |  |  | 	KX_PYATTRIBUTE_FLAG_RO("has_ik",bPoseChannel,flag, POSE_CHAIN), | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	KX_PYATTRIBUTE_FLAG_NEGATIVE_RO("ik_dof_x",bPoseChannel,ikflag, BONE_IK_NO_XDOF), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLAG_NEGATIVE_RO("ik_dof_y",bPoseChannel,ikflag, BONE_IK_NO_YDOF), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLAG_NEGATIVE_RO("ik_dof_z",bPoseChannel,ikflag, BONE_IK_NO_ZDOF), | 
					
						
							| 
									
										
										
										
											2010-08-26 23:49:46 +00:00
										 |  |  | 	KX_PYATTRIBUTE_FLAG_RO("ik_limit_x",bPoseChannel,ikflag, BONE_IK_XLIMIT), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLAG_RO("ik_limit_y",bPoseChannel,ikflag, BONE_IK_YLIMIT), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLAG_RO("ik_limit_z",bPoseChannel,ikflag, BONE_IK_ZLIMIT), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLAG_RO("ik_rot_control",bPoseChannel,ikflag, BONE_IK_ROTCTL), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLAG_RO("ik_lin_control",bPoseChannel,ikflag, BONE_IK_LINCTL), | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	KX_PYATTRIBUTE_FLOAT_VECTOR_RW("location",-FLT_MAX,FLT_MAX,bPoseChannel,loc,3), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLOAT_VECTOR_RW("scale",-FLT_MAX,FLT_MAX,bPoseChannel,size,3), | 
					
						
							| 
									
										
										
										
											2009-09-28 11:29:07 +00:00
										 |  |  | 	KX_PYATTRIBUTE_FLOAT_VECTOR_RW("rotation_quaternion",-1.0f,1.0f,bPoseChannel,quat,4), | 
					
						
							| 
									
										
										
										
											2010-07-30 04:57:27 +00:00
										 |  |  | 	KX_PYATTRIBUTE_FLOAT_VECTOR_RW("rotation_euler",-10.f,10.f,bPoseChannel,eul,3), | 
					
						
							| 
									
										
										
										
											2010-11-16 01:19:37 +00:00
										 |  |  | 	KX_PYATTRIBUTE_SHORT_RW("rotation_mode",ROT_MODE_MIN,ROT_MODE_MAX,false,bPoseChannel,rotmode), | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	KX_PYATTRIBUTE_FLOAT_MATRIX_RO("channel_matrix",bPoseChannel,chan_mat,4), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLOAT_MATRIX_RO("pose_matrix",bPoseChannel,pose_mat,4), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLOAT_VECTOR_RO("pose_head",bPoseChannel,pose_head,3), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLOAT_VECTOR_RO("pose_tail",bPoseChannel,pose_tail,3), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLOAT_RO("ik_min_x",bPoseChannel,limitmin[0]), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLOAT_RO("ik_max_x",bPoseChannel,limitmax[0]), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLOAT_RO("ik_min_y",bPoseChannel,limitmin[1]), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLOAT_RO("ik_max_y",bPoseChannel,limitmax[1]), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLOAT_RO("ik_min_z",bPoseChannel,limitmin[2]), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLOAT_RO("ik_max_z",bPoseChannel,limitmax[2]), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLOAT_RO("ik_stiffness_x",bPoseChannel,stiffness[0]), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLOAT_RO("ik_stiffness_y",bPoseChannel,stiffness[1]), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLOAT_RO("ik_stiffness_z",bPoseChannel,stiffness[2]), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLOAT_RO("ik_stretch",bPoseChannel,ikstretch), | 
					
						
							| 
									
										
										
										
											2010-08-26 23:49:46 +00:00
										 |  |  | 	KX_PYATTRIBUTE_FLOAT_RW("ik_rot_weight",0,1.0f,bPoseChannel,ikrotweight), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLOAT_RW("ik_lin_weight",0,1.0f,bPoseChannel,iklinweight), | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	KX_PYATTRIBUTE_RW_FUNCTION("joint_rotation",BL_ArmatureChannel,py_attr_get_joint_rotation,py_attr_set_joint_rotation), | 
					
						
							|  |  |  | 	{ NULL }	//Sentinel
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject* BL_ArmatureChannel::py_attr_getattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	BL_ArmatureChannel* self= static_cast<BL_ArmatureChannel*>(self_v); | 
					
						
							|  |  |  | 	bPoseChannel* channel = self->m_posechannel; | 
					
						
							|  |  |  | 	int attr_order = attrdef-Attributes; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!channel) { | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_AttributeError, "channel is NULL"); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (attr_order) { | 
					
						
							|  |  |  | 	case BCA_BONE: | 
					
						
							|  |  |  | 		// bones are standalone proxy
 | 
					
						
							|  |  |  | 		return NewProxyPlus_Ext(NULL,&BL_ArmatureBone::Type,channel->bone,false); | 
					
						
							|  |  |  | 	case BCA_PARENT: | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			BL_ArmatureChannel* parent = self->m_armature->GetChannel(channel->parent); | 
					
						
							|  |  |  | 			if (parent) | 
					
						
							|  |  |  | 				return parent->GetProxy(); | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				Py_RETURN_NONE; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	PyErr_SetString(PyExc_AttributeError, "channel unknown attribute"); | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int BL_ArmatureChannel::py_attr_setattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	BL_ArmatureChannel* self= static_cast<BL_ArmatureChannel*>(self_v); | 
					
						
							|  |  |  | 	bPoseChannel* channel = self->m_posechannel; | 
					
						
							|  |  |  | 	int attr_order = attrdef-Attributes; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 21:03:54 +00:00
										 |  |  | //	int ival;
 | 
					
						
							|  |  |  | //	double dval;
 | 
					
						
							|  |  |  | //	char* sval;
 | 
					
						
							|  |  |  | //	KX_GameObject *oval;
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!channel) { | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_AttributeError, "channel is NULL"); | 
					
						
							|  |  |  | 		return PY_SET_ATTR_FAIL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	switch (attr_order) { | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	PyErr_SetString(PyExc_AttributeError, "channel unknown attribute"); | 
					
						
							|  |  |  | 	return PY_SET_ATTR_FAIL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject* BL_ArmatureChannel::py_attr_get_joint_rotation(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-08-25 09:25:11 +00:00
										 |  |  | 	bPoseChannel* pchan = static_cast<bPoseChannel*>(self_v); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	// decompose the pose matrix in euler rotation
 | 
					
						
							|  |  |  | 	float rest_mat[3][3]; | 
					
						
							|  |  |  | 	float pose_mat[3][3]; | 
					
						
							|  |  |  | 	float joint_mat[3][3]; | 
					
						
							|  |  |  | 	float joints[3]; | 
					
						
							|  |  |  | 	float norm; | 
					
						
							|  |  |  | 	double sa, ca; | 
					
						
							|  |  |  | 	// get rotation in armature space
 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 	copy_m3_m4(pose_mat, pchan->pose_mat); | 
					
						
							|  |  |  | 	normalize_m3(pose_mat); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	if (pchan->parent) { | 
					
						
							|  |  |  | 		// bone has a parent, compute the rest pose of the bone taking actual pose of parent
 | 
					
						
							| 
									
										
										
											
												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_m3_m3m4(rest_mat, pchan->parent->pose_mat, pchan->bone->bone_mat); | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		normalize_m3(rest_mat); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		// otherwise, the bone matrix in armature space is the rest pose
 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		copy_m3_m4(rest_mat, pchan->bone->arm_mat); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	// remove the rest pose to get the joint movement
 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 	transpose_m3(rest_mat); | 
					
						
							|  |  |  | 	mul_m3_m3m3(joint_mat, rest_mat, pose_mat);		 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	joints[0] = joints[1] = joints[2] = 0.f; | 
					
						
							|  |  |  | 	// returns a 3 element list that gives corresponding joint
 | 
					
						
							|  |  |  | 	int flag = 0; | 
					
						
							|  |  |  | 	if (!(pchan->ikflag & BONE_IK_NO_XDOF)) | 
					
						
							|  |  |  | 		flag |= 1; | 
					
						
							|  |  |  | 	if (!(pchan->ikflag & BONE_IK_NO_YDOF)) | 
					
						
							|  |  |  | 		flag |= 2; | 
					
						
							|  |  |  | 	if (!(pchan->ikflag & BONE_IK_NO_ZDOF)) | 
					
						
							|  |  |  | 		flag |= 4; | 
					
						
							|  |  |  | 	switch (flag) { | 
					
						
							|  |  |  | 	case 0:	// fixed joint
 | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case 1:	// X only
 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		mat3_to_eulO( joints, EULER_ORDER_XYZ,joint_mat); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		joints[1] = joints[2] = 0.f; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case 2:	// Y only
 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		mat3_to_eulO( joints, EULER_ORDER_XYZ,joint_mat); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		joints[0] = joints[2] = 0.f; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case 3:	// X+Y
 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		mat3_to_eulO( joints, EULER_ORDER_ZYX,joint_mat); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		joints[2] = 0.f; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case 4:	// Z only
 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		mat3_to_eulO( joints, EULER_ORDER_XYZ,joint_mat); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		joints[0] = joints[1] = 0.f; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case 5:	// X+Z
 | 
					
						
							|  |  |  | 		// decompose this as an equivalent rotation vector in X/Z plane
 | 
					
						
							|  |  |  | 		joints[0] = joint_mat[1][2]; | 
					
						
							|  |  |  | 		joints[2] = -joint_mat[1][0]; | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		norm = normalize_v3(joints); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		if (norm < FLT_EPSILON) { | 
					
						
							|  |  |  | 			norm = (joint_mat[1][1] < 0.f) ? M_PI : 0.f; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			norm = acos(joint_mat[1][1]); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		mul_v3_fl(joints, norm); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case 6:	// Y+Z
 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		mat3_to_eulO( joints, EULER_ORDER_XYZ,joint_mat); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		joints[0] = 0.f; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case 7: // X+Y+Z
 | 
					
						
							|  |  |  | 		// equivalent axis
 | 
					
						
							|  |  |  | 		joints[0] = (joint_mat[1][2]-joint_mat[2][1])*0.5f; | 
					
						
							|  |  |  | 		joints[1] = (joint_mat[2][0]-joint_mat[0][2])*0.5f; | 
					
						
							|  |  |  | 		joints[2] = (joint_mat[0][1]-joint_mat[1][0])*0.5f; | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		sa = len_v3(joints); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		ca = (joint_mat[0][0]+joint_mat[1][1]+joint_mat[1][1]-1.0f)*0.5f; | 
					
						
							|  |  |  | 		if (sa > FLT_EPSILON) { | 
					
						
							|  |  |  | 			norm = atan2(sa,ca)/sa; | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2011-09-25 12:31:21 +00:00
										 |  |  | 			if (ca < 0.0) { | 
					
						
							|  |  |  | 				norm = M_PI; | 
					
						
							|  |  |  | 				mul_v3_fl(joints,0.f); | 
					
						
							|  |  |  | 				if (joint_mat[0][0] > 0.f) { | 
					
						
							|  |  |  | 					joints[0] = 1.0f; | 
					
						
							|  |  |  | 				} else if (joint_mat[1][1] > 0.f) { | 
					
						
							|  |  |  | 					joints[1] = 1.0f; | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					joints[2] = 1.0f; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				norm = 0.0; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		mul_v3_fl(joints,norm); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-11-24 04:45:36 +00:00
										 |  |  | 	return Vector_CreatePyObject(joints, 3, Py_NEW, NULL); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int BL_ArmatureChannel::py_attr_set_joint_rotation(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	BL_ArmatureChannel* self= static_cast<BL_ArmatureChannel*>(self_v); | 
					
						
							|  |  |  | 	bPoseChannel* pchan = self->m_posechannel; | 
					
						
							|  |  |  | 	PyObject *item; | 
					
						
							|  |  |  | 	float joints[3]; | 
					
						
							|  |  |  | 	float quat[4]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!PySequence_Check(value) || PySequence_Size(value) != 3) { | 
					
						
							| 
									
										
										
										
											2012-04-12 00:15:02 +00:00
										 |  |  | 		PyErr_SetString(PyExc_AttributeError, "expected a sequence of 3 floats"); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		return PY_SET_ATTR_FAIL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for (int i=0; i<3; i++) { | 
					
						
							|  |  |  | 		item = PySequence_GetItem(value, i); /* new ref */ | 
					
						
							|  |  |  | 		joints[i] = PyFloat_AsDouble(item); | 
					
						
							|  |  |  | 		Py_DECREF(item); | 
					
						
							|  |  |  | 		if (joints[i] == -1.0f && PyErr_Occurred()) { | 
					
						
							| 
									
										
										
										
											2012-04-12 00:15:02 +00:00
										 |  |  | 			PyErr_SetString(PyExc_AttributeError, "expected a sequence of 3 floats"); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			return PY_SET_ATTR_FAIL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int flag = 0; | 
					
						
							|  |  |  | 	if (!(pchan->ikflag & BONE_IK_NO_XDOF)) | 
					
						
							|  |  |  | 		flag |= 1; | 
					
						
							|  |  |  | 	if (!(pchan->ikflag & BONE_IK_NO_YDOF)) | 
					
						
							|  |  |  | 		flag |= 2; | 
					
						
							|  |  |  | 	if (!(pchan->ikflag & BONE_IK_NO_ZDOF)) | 
					
						
							|  |  |  | 		flag |= 4; | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 	unit_qt(quat); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	switch (flag) { | 
					
						
							|  |  |  | 	case 0:	// fixed joint
 | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case 1:	// X only
 | 
					
						
							|  |  |  | 		joints[1] = joints[2] = 0.f; | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		eulO_to_quat( quat,joints, EULER_ORDER_XYZ); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case 2:	// Y only
 | 
					
						
							|  |  |  | 		joints[0] = joints[2] = 0.f; | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		eulO_to_quat( quat,joints, EULER_ORDER_XYZ); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case 3:	// X+Y
 | 
					
						
							|  |  |  | 		joints[2] = 0.f; | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		eulO_to_quat( quat,joints, EULER_ORDER_ZYX); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case 4:	// Z only
 | 
					
						
							|  |  |  | 		joints[0] = joints[1] = 0.f; | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		eulO_to_quat( quat,joints, EULER_ORDER_XYZ); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case 5:	// X+Z
 | 
					
						
							|  |  |  | 		// X and Z are components of an equivalent rotation axis
 | 
					
						
							|  |  |  | 		joints[1] = 0; | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		axis_angle_to_quat( quat,joints, len_v3(joints)); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case 6:	// Y+Z
 | 
					
						
							|  |  |  | 		joints[0] = 0.f; | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		eulO_to_quat( quat,joints, EULER_ORDER_XYZ); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case 7: // X+Y+Z
 | 
					
						
							|  |  |  | 		// equivalent axis
 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		axis_angle_to_quat( quat,joints, len_v3(joints)); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (pchan->rotmode > 0) { | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		quat_to_eulO( joints, pchan->rotmode,quat); | 
					
						
							|  |  |  | 		copy_v3_v3(pchan->eul, joints); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	} else | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		copy_qt_qt(pchan->quat, quat); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	return PY_SET_ATTR_SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // *************************
 | 
					
						
							|  |  |  | // BL_ArmatureBone
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Access to Bone structure
 | 
					
						
							|  |  |  | PyTypeObject BL_ArmatureBone::Type = { | 
					
						
							|  |  |  | 	PyVarObject_HEAD_INIT(NULL, 0) | 
					
						
							|  |  |  | 	"BL_ArmatureBone", | 
					
						
							|  |  |  | 	sizeof(PyObjectPlus_Proxy), | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 	py_base_dealloc, | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 	py_bone_repr, | 
					
						
							|  |  |  | 	0,0,0,0,0,0,0,0,0, | 
					
						
							|  |  |  | 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, | 
					
						
							|  |  |  | 	0,0,0,0,0,0,0, | 
					
						
							|  |  |  | 	Methods, | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 	&CValue::Type, | 
					
						
							|  |  |  | 	0,0,0,0,0,0, | 
					
						
							|  |  |  | 	py_base_new | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // not used since this class is never instantiated
 | 
					
						
							|  |  |  | PyObject *BL_ArmatureBone::GetProxy()  | 
					
						
							|  |  |  | {  | 
					
						
							|  |  |  | 	return NULL;  | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | PyObject *BL_ArmatureBone::NewProxy(bool py_owns)  | 
					
						
							|  |  |  | {  | 
					
						
							|  |  |  | 	return NULL;  | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject *BL_ArmatureBone::py_bone_repr(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Bone* bone = static_cast<Bone*>BGE_PROXY_PTR(self); | 
					
						
							|  |  |  | 	return PyUnicode_FromString(bone->name); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyMethodDef BL_ArmatureBone::Methods[] = { | 
					
						
							|  |  |  | 	{NULL,NULL} //Sentinel
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* no attributes on C++ class since it is never instantiated */ | 
					
						
							|  |  |  | PyAttributeDef BL_ArmatureBone::Attributes[] = { | 
					
						
							|  |  |  | 	{ NULL }	//Sentinel
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // attributes that work on proxy ptr (points to a Bone structure)
 | 
					
						
							|  |  |  | PyAttributeDef BL_ArmatureBone::AttributesPtr[] = { | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_CHAR_RO("name",Bone,name), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLAG_RO("connected",Bone,flag, BONE_CONNECTED), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLAG_RO("hinge",Bone,flag, BONE_HINGE), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLAG_NEGATIVE_RO("inherit_scale",Bone,flag, BONE_NO_SCALE), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_SHORT_RO("bbone_segments",Bone,segments), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLOAT_RO("roll",Bone,roll), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLOAT_VECTOR_RO("head",Bone,head,3), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLOAT_VECTOR_RO("tail",Bone,tail,3), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLOAT_RO("length",Bone,length), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLOAT_VECTOR_RO("arm_head",Bone,arm_head,3), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLOAT_VECTOR_RO("arm_tail",Bone,arm_tail,3), | 
					
						
							|  |  |  | 	KX_PYATTRIBUTE_FLOAT_MATRIX_RO("arm_mat",Bone,arm_mat,4), | 
					
						
							| 
									
										
										
										
											2011-11-23 23:02:38 +00:00
										 |  |  | 	KX_PYATTRIBUTE_FLOAT_MATRIX_RO("bone_mat",Bone,bone_mat,3), | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	KX_PYATTRIBUTE_RO_FUNCTION("parent",BL_ArmatureBone,py_bone_get_parent), | 
					
						
							| 
									
										
										
										
											2010-07-24 09:26:05 +00:00
										 |  |  | 	KX_PYATTRIBUTE_RO_FUNCTION("children",BL_ArmatureBone,py_bone_get_children), | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	{ NULL }	//Sentinel
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject *BL_ArmatureBone::py_bone_get_parent(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-24 09:26:05 +00:00
										 |  |  | 	Bone* bone = reinterpret_cast<Bone*>(self); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	if (bone->parent) { | 
					
						
							|  |  |  | 		// create a proxy unconnected to any GE object
 | 
					
						
							|  |  |  | 		return NewProxyPlus_Ext(NULL,&Type,bone->parent,false); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject *BL_ArmatureBone::py_bone_get_children(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-24 09:26:05 +00:00
										 |  |  | 	Bone* bone = reinterpret_cast<Bone*>(self); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	Bone* child; | 
					
						
							|  |  |  | 	int count = 0; | 
					
						
							|  |  |  | 	for (child=(Bone*)bone->childbase.first; child; child=(Bone*)child->next) | 
					
						
							|  |  |  | 		count++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	PyObject* childrenlist = PyList_New(count); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (count = 0, child=(Bone*)bone->childbase.first; child; child=(Bone*)child->next, ++count) | 
					
						
							|  |  |  | 		PyList_SET_ITEM(childrenlist,count,NewProxyPlus_Ext(NULL,&Type,child,false)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return childrenlist; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-09-29 21:42:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-31 04:11:39 +00:00
										 |  |  | #endif // WITH_PYTHON
 |