123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470 |
- /*
- * ***** 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.
- *
- * 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 *****
- */
- /** \file gameengine/Converter/BL_ArmatureChannel.cpp
- * \ingroup bgeconv
- */
- #include "DNA_armature_types.h"
- #include "BL_ArmatureChannel.h"
- #include "BL_ArmatureObject.h"
- #include "BL_ArmatureConstraint.h"
- #include "BLI_math.h"
- #include "BLI_string.h"
- #include <stddef.h>
- #ifdef WITH_PYTHON
- 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);
- }
- #endif // WITH_PYTHON
- BL_ArmatureChannel::BL_ArmatureChannel(
- BL_ArmatureObject *armature,
- bPoseChannel *posechannel)
- : PyObjectPlus(), m_posechannel(posechannel), m_armature(armature)
- {
- }
- BL_ArmatureChannel::~BL_ArmatureChannel()
- {
- }
- #ifdef WITH_PYTHON
- // 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),
- KX_PYATTRIBUTE_FLAG_RO("has_ik",bPoseChannel,flag, POSE_CHAIN),
- 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),
- 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),
- 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),
- KX_PYATTRIBUTE_FLOAT_VECTOR_RW("rotation_quaternion",-1.0f,1.0f,bPoseChannel,quat,4),
- KX_PYATTRIBUTE_FLOAT_VECTOR_RW("rotation_euler",-10.f,10.f,bPoseChannel,eul,3),
- KX_PYATTRIBUTE_SHORT_RW("rotation_mode",ROT_MODE_MIN,ROT_MODE_MAX,false,bPoseChannel,rotmode),
- 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),
- KX_PYATTRIBUTE_FLOAT_RW("ik_rot_weight",0,1.0f,bPoseChannel,ikrotweight),
- KX_PYATTRIBUTE_FLOAT_RW("ik_lin_weight",0,1.0f,bPoseChannel,iklinweight),
- 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;
- // int ival;
- // double dval;
- // char* sval;
- // KX_GameObject *oval;
- 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)
- {
- bPoseChannel* pchan = static_cast<bPoseChannel*>(self_v);
- // 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
- copy_m3_m4(pose_mat, pchan->pose_mat);
- normalize_m3(pose_mat);
- if (pchan->parent) {
- // bone has a parent, compute the rest pose of the bone taking actual pose of parent
- mul_m3_m3m4(rest_mat, pchan->parent->pose_mat, pchan->bone->bone_mat);
- normalize_m3(rest_mat);
- } else {
- // otherwise, the bone matrix in armature space is the rest pose
- copy_m3_m4(rest_mat, pchan->bone->arm_mat);
- }
- // remove the rest pose to get the joint movement
- transpose_m3(rest_mat);
- mul_m3_m3m3(joint_mat, rest_mat, pose_mat);
- 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
- mat3_to_eulO( joints, EULER_ORDER_XYZ,joint_mat);
- joints[1] = joints[2] = 0.f;
- break;
- case 2: // Y only
- mat3_to_eulO( joints, EULER_ORDER_XYZ,joint_mat);
- joints[0] = joints[2] = 0.f;
- break;
- case 3: // X+Y
- mat3_to_eulO( joints, EULER_ORDER_ZYX,joint_mat);
- joints[2] = 0.f;
- break;
- case 4: // Z only
- mat3_to_eulO( joints, EULER_ORDER_XYZ,joint_mat);
- 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];
- norm = normalize_v3(joints);
- if (norm < FLT_EPSILON) {
- norm = (joint_mat[1][1] < 0.0f) ? (float)M_PI : 0.0f;
- } else {
- norm = acos(joint_mat[1][1]);
- }
- mul_v3_fl(joints, norm);
- break;
- case 6: // Y+Z
- mat3_to_eulO( joints, EULER_ORDER_XYZ,joint_mat);
- 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;
- sa = len_v3(joints);
- ca = (joint_mat[0][0]+joint_mat[1][1]+joint_mat[1][1]-1.0f)*0.5f;
- if (sa > (double)FLT_EPSILON) {
- norm = atan2(sa,ca)/sa;
- } else {
- 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;
- }
- }
- mul_v3_fl(joints,norm);
- break;
- }
- return Vector_CreatePyObject(joints, 3, NULL);
- }
- 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) {
- PyErr_SetString(PyExc_AttributeError, "expected a sequence of 3 floats");
- 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()) {
- PyErr_SetString(PyExc_AttributeError, "expected a sequence of 3 floats");
- 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;
- unit_qt(quat);
- switch (flag) {
- case 0: // fixed joint
- break;
- case 1: // X only
- joints[1] = joints[2] = 0.f;
- eulO_to_quat( quat,joints, EULER_ORDER_XYZ);
- break;
- case 2: // Y only
- joints[0] = joints[2] = 0.f;
- eulO_to_quat( quat,joints, EULER_ORDER_XYZ);
- break;
- case 3: // X+Y
- joints[2] = 0.f;
- eulO_to_quat( quat,joints, EULER_ORDER_ZYX);
- break;
- case 4: // Z only
- joints[0] = joints[1] = 0.f;
- eulO_to_quat( quat,joints, EULER_ORDER_XYZ);
- break;
- case 5: // X+Z
- // X and Z are components of an equivalent rotation axis
- joints[1] = 0;
- axis_angle_to_quat( quat,joints, len_v3(joints));
- break;
- case 6: // Y+Z
- joints[0] = 0.f;
- eulO_to_quat( quat,joints, EULER_ORDER_XYZ);
- break;
- case 7: // X+Y+Z
- // equivalent axis
- axis_angle_to_quat( quat,joints, len_v3(joints));
- break;
- }
- if (pchan->rotmode > 0) {
- quat_to_eulO( joints, pchan->rotmode,quat);
- copy_v3_v3(pchan->eul, joints);
- } else
- copy_qt_qt(pchan->quat, quat);
- 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),
- KX_PYATTRIBUTE_FLOAT_MATRIX_RO("bone_mat",Bone,bone_mat,3),
- KX_PYATTRIBUTE_RO_FUNCTION("parent",BL_ArmatureBone,py_bone_get_parent),
- KX_PYATTRIBUTE_RO_FUNCTION("children",BL_ArmatureBone,py_bone_get_children),
- { NULL } //Sentinel
- };
- PyObject *BL_ArmatureBone::py_bone_get_parent(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
- {
- Bone* bone = reinterpret_cast<Bone*>(self);
- 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)
- {
- Bone* bone = reinterpret_cast<Bone*>(self);
- Bone* child;
- int count = 0;
- for (child = (Bone *)bone->childbase.first; child; child = child->next)
- count++;
- PyObject *childrenlist = PyList_New(count);
- for (count = 0, child = (Bone *)bone->childbase.first; child; child = child->next, ++count)
- PyList_SET_ITEM(childrenlist,count,NewProxyPlus_Ext(NULL,&Type,child,false));
- return childrenlist;
- }
- #endif // WITH_PYTHON
|