|
Blender
V2.59
|
00001 /* 00002 * $Id: BL_ArmatureChannel.cpp 35904 2011-03-30 16:14:54Z campbellbarton $ 00003 * ***** BEGIN GPL LICENSE BLOCK ***** 00004 * 00005 * This program is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU General Public License 00007 * as published by the Free Software Foundation; either version 2 00008 * of the License, or (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software Foundation, 00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 * 00019 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00020 * All rights reserved. 00021 * 00022 * The Original Code is: all of this file. 00023 * 00024 * Contributor(s): none yet. 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 */ 00028 00034 #include "DNA_armature_types.h" 00035 #include "BL_ArmatureChannel.h" 00036 #include "BL_ArmatureObject.h" 00037 #include "BL_ArmatureConstraint.h" 00038 #include "BLI_math.h" 00039 #include "BLI_string.h" 00040 #include <stddef.h> 00041 00042 #ifdef WITH_PYTHON 00043 00044 PyTypeObject BL_ArmatureChannel::Type = { 00045 PyVarObject_HEAD_INIT(NULL, 0) 00046 "BL_ArmatureChannel", 00047 sizeof(PyObjectPlus_Proxy), 00048 0, 00049 py_base_dealloc, 00050 0, 00051 0, 00052 0, 00053 0, 00054 py_base_repr, 00055 0,0,0,0,0,0,0,0,0, 00056 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, 00057 0,0,0,0,0,0,0, 00058 Methods, 00059 0, 00060 0, 00061 &CValue::Type, 00062 0,0,0,0,0,0, 00063 py_base_new 00064 }; 00065 00066 PyObject* BL_ArmatureChannel::py_repr(void) 00067 { 00068 return PyUnicode_FromString(m_posechannel->name); 00069 } 00070 00071 PyObject *BL_ArmatureChannel::GetProxy() 00072 { 00073 return GetProxyPlus_Ext(this, &Type, m_posechannel); 00074 } 00075 00076 PyObject *BL_ArmatureChannel::NewProxy(bool py_owns) 00077 { 00078 return NewProxyPlus_Ext(this, &Type, m_posechannel, py_owns); 00079 } 00080 00081 #endif // WITH_PYTHON 00082 00083 BL_ArmatureChannel::BL_ArmatureChannel( 00084 BL_ArmatureObject *armature, 00085 bPoseChannel *posechannel) 00086 : PyObjectPlus(), m_posechannel(posechannel), m_armature(armature) 00087 { 00088 } 00089 00090 BL_ArmatureChannel::~BL_ArmatureChannel() 00091 { 00092 } 00093 00094 #ifdef WITH_PYTHON 00095 00096 // PYTHON 00097 00098 PyMethodDef BL_ArmatureChannel::Methods[] = { 00099 {NULL,NULL} //Sentinel 00100 }; 00101 00102 // order of definition of attributes, must match Attributes[] array 00103 #define BCA_BONE 0 00104 #define BCA_PARENT 1 00105 00106 PyAttributeDef BL_ArmatureChannel::Attributes[] = { 00107 // Keep these attributes in order of BCA_ defines!!! used by py_attr_getattr and py_attr_setattr 00108 KX_PYATTRIBUTE_RO_FUNCTION("bone",BL_ArmatureChannel,py_attr_getattr), 00109 KX_PYATTRIBUTE_RO_FUNCTION("parent",BL_ArmatureChannel,py_attr_getattr), 00110 00111 { NULL } //Sentinel 00112 }; 00113 00114 /* attributes directly taken from bPoseChannel */ 00115 PyAttributeDef BL_ArmatureChannel::AttributesPtr[] = { 00116 KX_PYATTRIBUTE_CHAR_RO("name",bPoseChannel,name), 00117 KX_PYATTRIBUTE_FLAG_RO("has_ik",bPoseChannel,flag, POSE_CHAIN), 00118 KX_PYATTRIBUTE_FLAG_NEGATIVE_RO("ik_dof_x",bPoseChannel,ikflag, BONE_IK_NO_XDOF), 00119 KX_PYATTRIBUTE_FLAG_NEGATIVE_RO("ik_dof_y",bPoseChannel,ikflag, BONE_IK_NO_YDOF), 00120 KX_PYATTRIBUTE_FLAG_NEGATIVE_RO("ik_dof_z",bPoseChannel,ikflag, BONE_IK_NO_ZDOF), 00121 KX_PYATTRIBUTE_FLAG_RO("ik_limit_x",bPoseChannel,ikflag, BONE_IK_XLIMIT), 00122 KX_PYATTRIBUTE_FLAG_RO("ik_limit_y",bPoseChannel,ikflag, BONE_IK_YLIMIT), 00123 KX_PYATTRIBUTE_FLAG_RO("ik_limit_z",bPoseChannel,ikflag, BONE_IK_ZLIMIT), 00124 KX_PYATTRIBUTE_FLAG_RO("ik_rot_control",bPoseChannel,ikflag, BONE_IK_ROTCTL), 00125 KX_PYATTRIBUTE_FLAG_RO("ik_lin_control",bPoseChannel,ikflag, BONE_IK_LINCTL), 00126 KX_PYATTRIBUTE_FLOAT_VECTOR_RW("location",-FLT_MAX,FLT_MAX,bPoseChannel,loc,3), 00127 KX_PYATTRIBUTE_FLOAT_VECTOR_RW("scale",-FLT_MAX,FLT_MAX,bPoseChannel,size,3), 00128 KX_PYATTRIBUTE_FLOAT_VECTOR_RW("rotation_quaternion",-1.0f,1.0f,bPoseChannel,quat,4), 00129 KX_PYATTRIBUTE_FLOAT_VECTOR_RW("rotation_euler",-10.f,10.f,bPoseChannel,eul,3), 00130 KX_PYATTRIBUTE_SHORT_RW("rotation_mode",ROT_MODE_MIN,ROT_MODE_MAX,false,bPoseChannel,rotmode), 00131 KX_PYATTRIBUTE_FLOAT_MATRIX_RO("channel_matrix",bPoseChannel,chan_mat,4), 00132 KX_PYATTRIBUTE_FLOAT_MATRIX_RO("pose_matrix",bPoseChannel,pose_mat,4), 00133 KX_PYATTRIBUTE_FLOAT_VECTOR_RO("pose_head",bPoseChannel,pose_head,3), 00134 KX_PYATTRIBUTE_FLOAT_VECTOR_RO("pose_tail",bPoseChannel,pose_tail,3), 00135 KX_PYATTRIBUTE_FLOAT_RO("ik_min_x",bPoseChannel,limitmin[0]), 00136 KX_PYATTRIBUTE_FLOAT_RO("ik_max_x",bPoseChannel,limitmax[0]), 00137 KX_PYATTRIBUTE_FLOAT_RO("ik_min_y",bPoseChannel,limitmin[1]), 00138 KX_PYATTRIBUTE_FLOAT_RO("ik_max_y",bPoseChannel,limitmax[1]), 00139 KX_PYATTRIBUTE_FLOAT_RO("ik_min_z",bPoseChannel,limitmin[2]), 00140 KX_PYATTRIBUTE_FLOAT_RO("ik_max_z",bPoseChannel,limitmax[2]), 00141 KX_PYATTRIBUTE_FLOAT_RO("ik_stiffness_x",bPoseChannel,stiffness[0]), 00142 KX_PYATTRIBUTE_FLOAT_RO("ik_stiffness_y",bPoseChannel,stiffness[1]), 00143 KX_PYATTRIBUTE_FLOAT_RO("ik_stiffness_z",bPoseChannel,stiffness[2]), 00144 KX_PYATTRIBUTE_FLOAT_RO("ik_stretch",bPoseChannel,ikstretch), 00145 KX_PYATTRIBUTE_FLOAT_RW("ik_rot_weight",0,1.0f,bPoseChannel,ikrotweight), 00146 KX_PYATTRIBUTE_FLOAT_RW("ik_lin_weight",0,1.0f,bPoseChannel,iklinweight), 00147 KX_PYATTRIBUTE_RW_FUNCTION("joint_rotation",BL_ArmatureChannel,py_attr_get_joint_rotation,py_attr_set_joint_rotation), 00148 { NULL } //Sentinel 00149 }; 00150 00151 PyObject* BL_ArmatureChannel::py_attr_getattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef) 00152 { 00153 BL_ArmatureChannel* self= static_cast<BL_ArmatureChannel*>(self_v); 00154 bPoseChannel* channel = self->m_posechannel; 00155 int attr_order = attrdef-Attributes; 00156 00157 if (!channel) { 00158 PyErr_SetString(PyExc_AttributeError, "channel is NULL"); 00159 return NULL; 00160 } 00161 00162 switch (attr_order) { 00163 case BCA_BONE: 00164 // bones are standalone proxy 00165 return NewProxyPlus_Ext(NULL,&BL_ArmatureBone::Type,channel->bone,false); 00166 case BCA_PARENT: 00167 { 00168 BL_ArmatureChannel* parent = self->m_armature->GetChannel(channel->parent); 00169 if (parent) 00170 return parent->GetProxy(); 00171 else 00172 Py_RETURN_NONE; 00173 } 00174 } 00175 PyErr_SetString(PyExc_AttributeError, "channel unknown attribute"); 00176 return NULL; 00177 } 00178 00179 int BL_ArmatureChannel::py_attr_setattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 00180 { 00181 BL_ArmatureChannel* self= static_cast<BL_ArmatureChannel*>(self_v); 00182 bPoseChannel* channel = self->m_posechannel; 00183 int attr_order = attrdef-Attributes; 00184 00185 // int ival; 00186 // double dval; 00187 // char* sval; 00188 // KX_GameObject *oval; 00189 00190 if (!channel) { 00191 PyErr_SetString(PyExc_AttributeError, "channel is NULL"); 00192 return PY_SET_ATTR_FAIL; 00193 } 00194 00195 switch (attr_order) { 00196 default: 00197 break; 00198 } 00199 00200 PyErr_SetString(PyExc_AttributeError, "channel unknown attribute"); 00201 return PY_SET_ATTR_FAIL; 00202 } 00203 00204 PyObject* BL_ArmatureChannel::py_attr_get_joint_rotation(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef) 00205 { 00206 bPoseChannel* pchan = static_cast<bPoseChannel*>(self_v); 00207 // decompose the pose matrix in euler rotation 00208 float rest_mat[3][3]; 00209 float pose_mat[3][3]; 00210 float joint_mat[3][3]; 00211 float joints[3]; 00212 float norm; 00213 double sa, ca; 00214 // get rotation in armature space 00215 copy_m3_m4(pose_mat, pchan->pose_mat); 00216 normalize_m3(pose_mat); 00217 if (pchan->parent) { 00218 // bone has a parent, compute the rest pose of the bone taking actual pose of parent 00219 mul_m3_m3m4(rest_mat, pchan->bone->bone_mat, pchan->parent->pose_mat); 00220 normalize_m3(rest_mat); 00221 } else { 00222 // otherwise, the bone matrix in armature space is the rest pose 00223 copy_m3_m4(rest_mat, pchan->bone->arm_mat); 00224 } 00225 // remove the rest pose to get the joint movement 00226 transpose_m3(rest_mat); 00227 mul_m3_m3m3(joint_mat, rest_mat, pose_mat); 00228 joints[0] = joints[1] = joints[2] = 0.f; 00229 // returns a 3 element list that gives corresponding joint 00230 int flag = 0; 00231 if (!(pchan->ikflag & BONE_IK_NO_XDOF)) 00232 flag |= 1; 00233 if (!(pchan->ikflag & BONE_IK_NO_YDOF)) 00234 flag |= 2; 00235 if (!(pchan->ikflag & BONE_IK_NO_ZDOF)) 00236 flag |= 4; 00237 switch (flag) { 00238 case 0: // fixed joint 00239 break; 00240 case 1: // X only 00241 mat3_to_eulO( joints, EULER_ORDER_XYZ,joint_mat); 00242 joints[1] = joints[2] = 0.f; 00243 break; 00244 case 2: // Y only 00245 mat3_to_eulO( joints, EULER_ORDER_XYZ,joint_mat); 00246 joints[0] = joints[2] = 0.f; 00247 break; 00248 case 3: // X+Y 00249 mat3_to_eulO( joints, EULER_ORDER_ZYX,joint_mat); 00250 joints[2] = 0.f; 00251 break; 00252 case 4: // Z only 00253 mat3_to_eulO( joints, EULER_ORDER_XYZ,joint_mat); 00254 joints[0] = joints[1] = 0.f; 00255 break; 00256 case 5: // X+Z 00257 // decompose this as an equivalent rotation vector in X/Z plane 00258 joints[0] = joint_mat[1][2]; 00259 joints[2] = -joint_mat[1][0]; 00260 norm = normalize_v3(joints); 00261 if (norm < FLT_EPSILON) { 00262 norm = (joint_mat[1][1] < 0.f) ? M_PI : 0.f; 00263 } else { 00264 norm = acos(joint_mat[1][1]); 00265 } 00266 mul_v3_fl(joints, norm); 00267 break; 00268 case 6: // Y+Z 00269 mat3_to_eulO( joints, EULER_ORDER_XYZ,joint_mat); 00270 joints[0] = 0.f; 00271 break; 00272 case 7: // X+Y+Z 00273 // equivalent axis 00274 joints[0] = (joint_mat[1][2]-joint_mat[2][1])*0.5f; 00275 joints[1] = (joint_mat[2][0]-joint_mat[0][2])*0.5f; 00276 joints[2] = (joint_mat[0][1]-joint_mat[1][0])*0.5f; 00277 sa = len_v3(joints); 00278 ca = (joint_mat[0][0]+joint_mat[1][1]+joint_mat[1][1]-1.0f)*0.5f; 00279 if (sa > FLT_EPSILON) { 00280 norm = atan2(sa,ca)/sa; 00281 } else { 00282 if (ca < 0.0) { 00283 norm = M_PI; 00284 mul_v3_fl(joints,0.f); 00285 if (joint_mat[0][0] > 0.f) { 00286 joints[0] = 1.0f; 00287 } else if (joint_mat[1][1] > 0.f) { 00288 joints[1] = 1.0f; 00289 } else { 00290 joints[2] = 1.0f; 00291 } 00292 } else { 00293 norm = 0.0; 00294 } 00295 } 00296 mul_v3_fl(joints,norm); 00297 break; 00298 } 00299 return newVectorObject(joints, 3, Py_NEW, NULL); 00300 } 00301 00302 int BL_ArmatureChannel::py_attr_set_joint_rotation(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 00303 { 00304 BL_ArmatureChannel* self= static_cast<BL_ArmatureChannel*>(self_v); 00305 bPoseChannel* pchan = self->m_posechannel; 00306 PyObject *item; 00307 float joints[3]; 00308 float quat[4]; 00309 00310 if (!PySequence_Check(value) || PySequence_Size(value) != 3) { 00311 PyErr_SetString(PyExc_AttributeError, "expected a sequence of [3] floats"); 00312 return PY_SET_ATTR_FAIL; 00313 } 00314 for (int i=0; i<3; i++) { 00315 item = PySequence_GetItem(value, i); /* new ref */ 00316 joints[i] = PyFloat_AsDouble(item); 00317 Py_DECREF(item); 00318 if (joints[i] == -1.0f && PyErr_Occurred()) { 00319 PyErr_SetString(PyExc_AttributeError, "expected a sequence of [3] floats"); 00320 return PY_SET_ATTR_FAIL; 00321 } 00322 } 00323 00324 int flag = 0; 00325 if (!(pchan->ikflag & BONE_IK_NO_XDOF)) 00326 flag |= 1; 00327 if (!(pchan->ikflag & BONE_IK_NO_YDOF)) 00328 flag |= 2; 00329 if (!(pchan->ikflag & BONE_IK_NO_ZDOF)) 00330 flag |= 4; 00331 unit_qt(quat); 00332 switch (flag) { 00333 case 0: // fixed joint 00334 break; 00335 case 1: // X only 00336 joints[1] = joints[2] = 0.f; 00337 eulO_to_quat( quat,joints, EULER_ORDER_XYZ); 00338 break; 00339 case 2: // Y only 00340 joints[0] = joints[2] = 0.f; 00341 eulO_to_quat( quat,joints, EULER_ORDER_XYZ); 00342 break; 00343 case 3: // X+Y 00344 joints[2] = 0.f; 00345 eulO_to_quat( quat,joints, EULER_ORDER_ZYX); 00346 break; 00347 case 4: // Z only 00348 joints[0] = joints[1] = 0.f; 00349 eulO_to_quat( quat,joints, EULER_ORDER_XYZ); 00350 break; 00351 case 5: // X+Z 00352 // X and Z are components of an equivalent rotation axis 00353 joints[1] = 0; 00354 axis_angle_to_quat( quat,joints, len_v3(joints)); 00355 break; 00356 case 6: // Y+Z 00357 joints[0] = 0.f; 00358 eulO_to_quat( quat,joints, EULER_ORDER_XYZ); 00359 break; 00360 case 7: // X+Y+Z 00361 // equivalent axis 00362 axis_angle_to_quat( quat,joints, len_v3(joints)); 00363 break; 00364 } 00365 if (pchan->rotmode > 0) { 00366 quat_to_eulO( joints, pchan->rotmode,quat); 00367 copy_v3_v3(pchan->eul, joints); 00368 } else 00369 copy_qt_qt(pchan->quat, quat); 00370 return PY_SET_ATTR_SUCCESS; 00371 } 00372 00373 // ************************* 00374 // BL_ArmatureBone 00375 // 00376 // Access to Bone structure 00377 PyTypeObject BL_ArmatureBone::Type = { 00378 PyVarObject_HEAD_INIT(NULL, 0) 00379 "BL_ArmatureBone", 00380 sizeof(PyObjectPlus_Proxy), 00381 0, 00382 py_base_dealloc, 00383 0, 00384 0, 00385 0, 00386 0, 00387 py_bone_repr, 00388 0,0,0,0,0,0,0,0,0, 00389 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, 00390 0,0,0,0,0,0,0, 00391 Methods, 00392 0, 00393 0, 00394 &CValue::Type, 00395 0,0,0,0,0,0, 00396 py_base_new 00397 }; 00398 00399 // not used since this class is never instantiated 00400 PyObject *BL_ArmatureBone::GetProxy() 00401 { 00402 return NULL; 00403 } 00404 PyObject *BL_ArmatureBone::NewProxy(bool py_owns) 00405 { 00406 return NULL; 00407 } 00408 00409 PyObject *BL_ArmatureBone::py_bone_repr(PyObject *self) 00410 { 00411 Bone* bone = static_cast<Bone*>BGE_PROXY_PTR(self); 00412 return PyUnicode_FromString(bone->name); 00413 } 00414 00415 PyMethodDef BL_ArmatureBone::Methods[] = { 00416 {NULL,NULL} //Sentinel 00417 }; 00418 00419 /* no attributes on C++ class since it is never instantiated */ 00420 PyAttributeDef BL_ArmatureBone::Attributes[] = { 00421 { NULL } //Sentinel 00422 }; 00423 00424 // attributes that work on proxy ptr (points to a Bone structure) 00425 PyAttributeDef BL_ArmatureBone::AttributesPtr[] = { 00426 KX_PYATTRIBUTE_CHAR_RO("name",Bone,name), 00427 KX_PYATTRIBUTE_FLAG_RO("connected",Bone,flag, BONE_CONNECTED), 00428 KX_PYATTRIBUTE_FLAG_RO("hinge",Bone,flag, BONE_HINGE), 00429 KX_PYATTRIBUTE_FLAG_NEGATIVE_RO("inherit_scale",Bone,flag, BONE_NO_SCALE), 00430 KX_PYATTRIBUTE_SHORT_RO("bbone_segments",Bone,segments), 00431 KX_PYATTRIBUTE_FLOAT_RO("roll",Bone,roll), 00432 KX_PYATTRIBUTE_FLOAT_VECTOR_RO("head",Bone,head,3), 00433 KX_PYATTRIBUTE_FLOAT_VECTOR_RO("tail",Bone,tail,3), 00434 KX_PYATTRIBUTE_FLOAT_RO("length",Bone,length), 00435 KX_PYATTRIBUTE_FLOAT_VECTOR_RO("arm_head",Bone,arm_head,3), 00436 KX_PYATTRIBUTE_FLOAT_VECTOR_RO("arm_tail",Bone,arm_tail,3), 00437 KX_PYATTRIBUTE_FLOAT_MATRIX_RO("arm_mat",Bone,arm_mat,4), 00438 KX_PYATTRIBUTE_FLOAT_MATRIX_RO("bone_mat",Bone,bone_mat,4), 00439 KX_PYATTRIBUTE_RO_FUNCTION("parent",BL_ArmatureBone,py_bone_get_parent), 00440 KX_PYATTRIBUTE_RO_FUNCTION("children",BL_ArmatureBone,py_bone_get_children), 00441 { NULL } //Sentinel 00442 }; 00443 00444 PyObject *BL_ArmatureBone::py_bone_get_parent(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) 00445 { 00446 Bone* bone = reinterpret_cast<Bone*>(self); 00447 if (bone->parent) { 00448 // create a proxy unconnected to any GE object 00449 return NewProxyPlus_Ext(NULL,&Type,bone->parent,false); 00450 } 00451 Py_RETURN_NONE; 00452 } 00453 00454 PyObject *BL_ArmatureBone::py_bone_get_children(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) 00455 { 00456 Bone* bone = reinterpret_cast<Bone*>(self); 00457 Bone* child; 00458 int count = 0; 00459 for (child=(Bone*)bone->childbase.first; child; child=(Bone*)child->next) 00460 count++; 00461 00462 PyObject* childrenlist = PyList_New(count); 00463 00464 for (count = 0, child=(Bone*)bone->childbase.first; child; child=(Bone*)child->next, ++count) 00465 PyList_SET_ITEM(childrenlist,count,NewProxyPlus_Ext(NULL,&Type,child,false)); 00466 00467 return childrenlist; 00468 } 00469 00470 #endif // WITH_PYTHON