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