BL_ArmatureChannel.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. /*
  2. * ***** BEGIN GPL LICENSE BLOCK *****
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation; either version 2
  7. * of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software Foundation,
  16. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  17. *
  18. * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  19. * All rights reserved.
  20. *
  21. * The Original Code is: all of this file.
  22. *
  23. * Contributor(s): none yet.
  24. *
  25. * ***** END GPL LICENSE BLOCK *****
  26. */
  27. /** \file gameengine/Converter/BL_ArmatureChannel.cpp
  28. * \ingroup bgeconv
  29. */
  30. #include "DNA_armature_types.h"
  31. #include "BL_ArmatureChannel.h"
  32. #include "BL_ArmatureObject.h"
  33. #include "BL_ArmatureConstraint.h"
  34. #include "BLI_math.h"
  35. #include "BLI_string.h"
  36. #include <stddef.h>
  37. #ifdef WITH_PYTHON
  38. PyTypeObject BL_ArmatureChannel::Type = {
  39. PyVarObject_HEAD_INIT(NULL, 0)
  40. "BL_ArmatureChannel",
  41. sizeof(PyObjectPlus_Proxy),
  42. 0,
  43. py_base_dealloc,
  44. 0,
  45. 0,
  46. 0,
  47. 0,
  48. py_base_repr,
  49. 0,0,0,0,0,0,0,0,0,
  50. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
  51. 0,0,0,0,0,0,0,
  52. Methods,
  53. 0,
  54. 0,
  55. &CValue::Type,
  56. 0,0,0,0,0,0,
  57. py_base_new
  58. };
  59. PyObject *BL_ArmatureChannel::py_repr(void)
  60. {
  61. return PyUnicode_FromString(m_posechannel->name);
  62. }
  63. PyObject *BL_ArmatureChannel::GetProxy()
  64. {
  65. return GetProxyPlus_Ext(this, &Type, m_posechannel);
  66. }
  67. PyObject *BL_ArmatureChannel::NewProxy(bool py_owns)
  68. {
  69. return NewProxyPlus_Ext(this, &Type, m_posechannel, py_owns);
  70. }
  71. #endif // WITH_PYTHON
  72. BL_ArmatureChannel::BL_ArmatureChannel(
  73. BL_ArmatureObject *armature,
  74. bPoseChannel *posechannel)
  75. : PyObjectPlus(), m_posechannel(posechannel), m_armature(armature)
  76. {
  77. }
  78. BL_ArmatureChannel::~BL_ArmatureChannel()
  79. {
  80. }
  81. #ifdef WITH_PYTHON
  82. // PYTHON
  83. PyMethodDef BL_ArmatureChannel::Methods[] = {
  84. {NULL,NULL} //Sentinel
  85. };
  86. // order of definition of attributes, must match Attributes[] array
  87. #define BCA_BONE 0
  88. #define BCA_PARENT 1
  89. PyAttributeDef BL_ArmatureChannel::Attributes[] = {
  90. // Keep these attributes in order of BCA_ defines!!! used by py_attr_getattr and py_attr_setattr
  91. KX_PYATTRIBUTE_RO_FUNCTION("bone",BL_ArmatureChannel,py_attr_getattr),
  92. KX_PYATTRIBUTE_RO_FUNCTION("parent",BL_ArmatureChannel,py_attr_getattr),
  93. { NULL } //Sentinel
  94. };
  95. /* attributes directly taken from bPoseChannel */
  96. PyAttributeDef BL_ArmatureChannel::AttributesPtr[] = {
  97. KX_PYATTRIBUTE_CHAR_RO("name",bPoseChannel,name),
  98. KX_PYATTRIBUTE_FLAG_RO("has_ik",bPoseChannel,flag, POSE_CHAIN),
  99. KX_PYATTRIBUTE_FLAG_NEGATIVE_RO("ik_dof_x",bPoseChannel,ikflag, BONE_IK_NO_XDOF),
  100. KX_PYATTRIBUTE_FLAG_NEGATIVE_RO("ik_dof_y",bPoseChannel,ikflag, BONE_IK_NO_YDOF),
  101. KX_PYATTRIBUTE_FLAG_NEGATIVE_RO("ik_dof_z",bPoseChannel,ikflag, BONE_IK_NO_ZDOF),
  102. KX_PYATTRIBUTE_FLAG_RO("ik_limit_x",bPoseChannel,ikflag, BONE_IK_XLIMIT),
  103. KX_PYATTRIBUTE_FLAG_RO("ik_limit_y",bPoseChannel,ikflag, BONE_IK_YLIMIT),
  104. KX_PYATTRIBUTE_FLAG_RO("ik_limit_z",bPoseChannel,ikflag, BONE_IK_ZLIMIT),
  105. KX_PYATTRIBUTE_FLAG_RO("ik_rot_control",bPoseChannel,ikflag, BONE_IK_ROTCTL),
  106. KX_PYATTRIBUTE_FLAG_RO("ik_lin_control",bPoseChannel,ikflag, BONE_IK_LINCTL),
  107. KX_PYATTRIBUTE_FLOAT_VECTOR_RW("location",-FLT_MAX,FLT_MAX,bPoseChannel,loc,3),
  108. KX_PYATTRIBUTE_FLOAT_VECTOR_RW("scale",-FLT_MAX,FLT_MAX,bPoseChannel,size,3),
  109. KX_PYATTRIBUTE_FLOAT_VECTOR_RW("rotation_quaternion",-1.0f,1.0f,bPoseChannel,quat,4),
  110. KX_PYATTRIBUTE_FLOAT_VECTOR_RW("rotation_euler",-10.f,10.f,bPoseChannel,eul,3),
  111. KX_PYATTRIBUTE_SHORT_RW("rotation_mode",ROT_MODE_MIN,ROT_MODE_MAX,false,bPoseChannel,rotmode),
  112. KX_PYATTRIBUTE_FLOAT_MATRIX_RO("channel_matrix",bPoseChannel,chan_mat,4),
  113. KX_PYATTRIBUTE_FLOAT_MATRIX_RO("pose_matrix",bPoseChannel,pose_mat,4),
  114. KX_PYATTRIBUTE_FLOAT_VECTOR_RO("pose_head",bPoseChannel,pose_head,3),
  115. KX_PYATTRIBUTE_FLOAT_VECTOR_RO("pose_tail",bPoseChannel,pose_tail,3),
  116. KX_PYATTRIBUTE_FLOAT_RO("ik_min_x",bPoseChannel,limitmin[0]),
  117. KX_PYATTRIBUTE_FLOAT_RO("ik_max_x",bPoseChannel,limitmax[0]),
  118. KX_PYATTRIBUTE_FLOAT_RO("ik_min_y",bPoseChannel,limitmin[1]),
  119. KX_PYATTRIBUTE_FLOAT_RO("ik_max_y",bPoseChannel,limitmax[1]),
  120. KX_PYATTRIBUTE_FLOAT_RO("ik_min_z",bPoseChannel,limitmin[2]),
  121. KX_PYATTRIBUTE_FLOAT_RO("ik_max_z",bPoseChannel,limitmax[2]),
  122. KX_PYATTRIBUTE_FLOAT_RO("ik_stiffness_x",bPoseChannel,stiffness[0]),
  123. KX_PYATTRIBUTE_FLOAT_RO("ik_stiffness_y",bPoseChannel,stiffness[1]),
  124. KX_PYATTRIBUTE_FLOAT_RO("ik_stiffness_z",bPoseChannel,stiffness[2]),
  125. KX_PYATTRIBUTE_FLOAT_RO("ik_stretch",bPoseChannel,ikstretch),
  126. KX_PYATTRIBUTE_FLOAT_RW("ik_rot_weight",0,1.0f,bPoseChannel,ikrotweight),
  127. KX_PYATTRIBUTE_FLOAT_RW("ik_lin_weight",0,1.0f,bPoseChannel,iklinweight),
  128. KX_PYATTRIBUTE_RW_FUNCTION("joint_rotation",BL_ArmatureChannel,py_attr_get_joint_rotation,py_attr_set_joint_rotation),
  129. { NULL } //Sentinel
  130. };
  131. PyObject *BL_ArmatureChannel::py_attr_getattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef)
  132. {
  133. BL_ArmatureChannel* self = static_cast<BL_ArmatureChannel*>(self_v);
  134. bPoseChannel* channel = self->m_posechannel;
  135. int attr_order = attrdef-Attributes;
  136. if (!channel) {
  137. PyErr_SetString(PyExc_AttributeError, "channel is NULL");
  138. return NULL;
  139. }
  140. switch (attr_order) {
  141. case BCA_BONE:
  142. // bones are standalone proxy
  143. return NewProxyPlus_Ext(NULL,&BL_ArmatureBone::Type,channel->bone,false);
  144. case BCA_PARENT:
  145. {
  146. BL_ArmatureChannel* parent = self->m_armature->GetChannel(channel->parent);
  147. if (parent)
  148. return parent->GetProxy();
  149. else
  150. Py_RETURN_NONE;
  151. }
  152. }
  153. PyErr_SetString(PyExc_AttributeError, "channel unknown attribute");
  154. return NULL;
  155. }
  156. int BL_ArmatureChannel::py_attr_setattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
  157. {
  158. BL_ArmatureChannel* self = static_cast<BL_ArmatureChannel*>(self_v);
  159. bPoseChannel* channel = self->m_posechannel;
  160. int attr_order = attrdef-Attributes;
  161. // int ival;
  162. // double dval;
  163. // char* sval;
  164. // KX_GameObject *oval;
  165. if (!channel) {
  166. PyErr_SetString(PyExc_AttributeError, "channel is NULL");
  167. return PY_SET_ATTR_FAIL;
  168. }
  169. switch (attr_order) {
  170. default:
  171. break;
  172. }
  173. PyErr_SetString(PyExc_AttributeError, "channel unknown attribute");
  174. return PY_SET_ATTR_FAIL;
  175. }
  176. PyObject *BL_ArmatureChannel::py_attr_get_joint_rotation(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef)
  177. {
  178. bPoseChannel* pchan = static_cast<bPoseChannel*>(self_v);
  179. // decompose the pose matrix in euler rotation
  180. float rest_mat[3][3];
  181. float pose_mat[3][3];
  182. float joint_mat[3][3];
  183. float joints[3];
  184. float norm;
  185. double sa, ca;
  186. // get rotation in armature space
  187. copy_m3_m4(pose_mat, pchan->pose_mat);
  188. normalize_m3(pose_mat);
  189. if (pchan->parent) {
  190. // bone has a parent, compute the rest pose of the bone taking actual pose of parent
  191. mul_m3_m3m4(rest_mat, pchan->parent->pose_mat, pchan->bone->bone_mat);
  192. normalize_m3(rest_mat);
  193. } else {
  194. // otherwise, the bone matrix in armature space is the rest pose
  195. copy_m3_m4(rest_mat, pchan->bone->arm_mat);
  196. }
  197. // remove the rest pose to get the joint movement
  198. transpose_m3(rest_mat);
  199. mul_m3_m3m3(joint_mat, rest_mat, pose_mat);
  200. joints[0] = joints[1] = joints[2] = 0.f;
  201. // returns a 3 element list that gives corresponding joint
  202. int flag = 0;
  203. if (!(pchan->ikflag & BONE_IK_NO_XDOF))
  204. flag |= 1;
  205. if (!(pchan->ikflag & BONE_IK_NO_YDOF))
  206. flag |= 2;
  207. if (!(pchan->ikflag & BONE_IK_NO_ZDOF))
  208. flag |= 4;
  209. switch (flag) {
  210. case 0: // fixed joint
  211. break;
  212. case 1: // X only
  213. mat3_to_eulO( joints, EULER_ORDER_XYZ,joint_mat);
  214. joints[1] = joints[2] = 0.f;
  215. break;
  216. case 2: // Y only
  217. mat3_to_eulO( joints, EULER_ORDER_XYZ,joint_mat);
  218. joints[0] = joints[2] = 0.f;
  219. break;
  220. case 3: // X+Y
  221. mat3_to_eulO( joints, EULER_ORDER_ZYX,joint_mat);
  222. joints[2] = 0.f;
  223. break;
  224. case 4: // Z only
  225. mat3_to_eulO( joints, EULER_ORDER_XYZ,joint_mat);
  226. joints[0] = joints[1] = 0.f;
  227. break;
  228. case 5: // X+Z
  229. // decompose this as an equivalent rotation vector in X/Z plane
  230. joints[0] = joint_mat[1][2];
  231. joints[2] = -joint_mat[1][0];
  232. norm = normalize_v3(joints);
  233. if (norm < FLT_EPSILON) {
  234. norm = (joint_mat[1][1] < 0.0f) ? (float)M_PI : 0.0f;
  235. } else {
  236. norm = acos(joint_mat[1][1]);
  237. }
  238. mul_v3_fl(joints, norm);
  239. break;
  240. case 6: // Y+Z
  241. mat3_to_eulO( joints, EULER_ORDER_XYZ,joint_mat);
  242. joints[0] = 0.f;
  243. break;
  244. case 7: // X+Y+Z
  245. // equivalent axis
  246. joints[0] = (joint_mat[1][2]-joint_mat[2][1])*0.5f;
  247. joints[1] = (joint_mat[2][0]-joint_mat[0][2])*0.5f;
  248. joints[2] = (joint_mat[0][1]-joint_mat[1][0])*0.5f;
  249. sa = len_v3(joints);
  250. ca = (joint_mat[0][0]+joint_mat[1][1]+joint_mat[1][1]-1.0f)*0.5f;
  251. if (sa > (double)FLT_EPSILON) {
  252. norm = atan2(sa,ca)/sa;
  253. } else {
  254. if (ca < 0.0) {
  255. norm = M_PI;
  256. mul_v3_fl(joints,0.f);
  257. if (joint_mat[0][0] > 0.f) {
  258. joints[0] = 1.0f;
  259. } else if (joint_mat[1][1] > 0.f) {
  260. joints[1] = 1.0f;
  261. } else {
  262. joints[2] = 1.0f;
  263. }
  264. } else {
  265. norm = 0.0;
  266. }
  267. }
  268. mul_v3_fl(joints,norm);
  269. break;
  270. }
  271. return Vector_CreatePyObject(joints, 3, NULL);
  272. }
  273. int BL_ArmatureChannel::py_attr_set_joint_rotation(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
  274. {
  275. BL_ArmatureChannel* self = static_cast<BL_ArmatureChannel*>(self_v);
  276. bPoseChannel* pchan = self->m_posechannel;
  277. PyObject *item;
  278. float joints[3];
  279. float quat[4];
  280. if (!PySequence_Check(value) || PySequence_Size(value) != 3) {
  281. PyErr_SetString(PyExc_AttributeError, "expected a sequence of 3 floats");
  282. return PY_SET_ATTR_FAIL;
  283. }
  284. for (int i=0; i<3; i++) {
  285. item = PySequence_GetItem(value, i); /* new ref */
  286. joints[i] = PyFloat_AsDouble(item);
  287. Py_DECREF(item);
  288. if (joints[i] == -1.0f && PyErr_Occurred()) {
  289. PyErr_SetString(PyExc_AttributeError, "expected a sequence of 3 floats");
  290. return PY_SET_ATTR_FAIL;
  291. }
  292. }
  293. int flag = 0;
  294. if (!(pchan->ikflag & BONE_IK_NO_XDOF))
  295. flag |= 1;
  296. if (!(pchan->ikflag & BONE_IK_NO_YDOF))
  297. flag |= 2;
  298. if (!(pchan->ikflag & BONE_IK_NO_ZDOF))
  299. flag |= 4;
  300. unit_qt(quat);
  301. switch (flag) {
  302. case 0: // fixed joint
  303. break;
  304. case 1: // X only
  305. joints[1] = joints[2] = 0.f;
  306. eulO_to_quat( quat,joints, EULER_ORDER_XYZ);
  307. break;
  308. case 2: // Y only
  309. joints[0] = joints[2] = 0.f;
  310. eulO_to_quat( quat,joints, EULER_ORDER_XYZ);
  311. break;
  312. case 3: // X+Y
  313. joints[2] = 0.f;
  314. eulO_to_quat( quat,joints, EULER_ORDER_ZYX);
  315. break;
  316. case 4: // Z only
  317. joints[0] = joints[1] = 0.f;
  318. eulO_to_quat( quat,joints, EULER_ORDER_XYZ);
  319. break;
  320. case 5: // X+Z
  321. // X and Z are components of an equivalent rotation axis
  322. joints[1] = 0;
  323. axis_angle_to_quat( quat,joints, len_v3(joints));
  324. break;
  325. case 6: // Y+Z
  326. joints[0] = 0.f;
  327. eulO_to_quat( quat,joints, EULER_ORDER_XYZ);
  328. break;
  329. case 7: // X+Y+Z
  330. // equivalent axis
  331. axis_angle_to_quat( quat,joints, len_v3(joints));
  332. break;
  333. }
  334. if (pchan->rotmode > 0) {
  335. quat_to_eulO( joints, pchan->rotmode,quat);
  336. copy_v3_v3(pchan->eul, joints);
  337. } else
  338. copy_qt_qt(pchan->quat, quat);
  339. return PY_SET_ATTR_SUCCESS;
  340. }
  341. // *************************
  342. // BL_ArmatureBone
  343. //
  344. // Access to Bone structure
  345. PyTypeObject BL_ArmatureBone::Type = {
  346. PyVarObject_HEAD_INIT(NULL, 0)
  347. "BL_ArmatureBone",
  348. sizeof(PyObjectPlus_Proxy),
  349. 0,
  350. py_base_dealloc,
  351. 0,
  352. 0,
  353. 0,
  354. 0,
  355. py_bone_repr,
  356. 0,0,0,0,0,0,0,0,0,
  357. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
  358. 0,0,0,0,0,0,0,
  359. Methods,
  360. 0,
  361. 0,
  362. &CValue::Type,
  363. 0,0,0,0,0,0,
  364. py_base_new
  365. };
  366. // not used since this class is never instantiated
  367. PyObject *BL_ArmatureBone::GetProxy()
  368. {
  369. return NULL;
  370. }
  371. PyObject *BL_ArmatureBone::NewProxy(bool py_owns)
  372. {
  373. return NULL;
  374. }
  375. PyObject *BL_ArmatureBone::py_bone_repr(PyObject *self)
  376. {
  377. Bone* bone = static_cast<Bone*>BGE_PROXY_PTR(self);
  378. return PyUnicode_FromString(bone->name);
  379. }
  380. PyMethodDef BL_ArmatureBone::Methods[] = {
  381. {NULL,NULL} //Sentinel
  382. };
  383. /* no attributes on C++ class since it is never instantiated */
  384. PyAttributeDef BL_ArmatureBone::Attributes[] = {
  385. { NULL } //Sentinel
  386. };
  387. // attributes that work on proxy ptr (points to a Bone structure)
  388. PyAttributeDef BL_ArmatureBone::AttributesPtr[] = {
  389. KX_PYATTRIBUTE_CHAR_RO("name",Bone,name),
  390. KX_PYATTRIBUTE_FLAG_RO("connected",Bone,flag, BONE_CONNECTED),
  391. KX_PYATTRIBUTE_FLAG_RO("hinge",Bone,flag, BONE_HINGE),
  392. KX_PYATTRIBUTE_FLAG_NEGATIVE_RO("inherit_scale",Bone,flag, BONE_NO_SCALE),
  393. KX_PYATTRIBUTE_SHORT_RO("bbone_segments",Bone,segments),
  394. KX_PYATTRIBUTE_FLOAT_RO("roll",Bone,roll),
  395. KX_PYATTRIBUTE_FLOAT_VECTOR_RO("head",Bone,head,3),
  396. KX_PYATTRIBUTE_FLOAT_VECTOR_RO("tail",Bone,tail,3),
  397. KX_PYATTRIBUTE_FLOAT_RO("length",Bone,length),
  398. KX_PYATTRIBUTE_FLOAT_VECTOR_RO("arm_head",Bone,arm_head,3),
  399. KX_PYATTRIBUTE_FLOAT_VECTOR_RO("arm_tail",Bone,arm_tail,3),
  400. KX_PYATTRIBUTE_FLOAT_MATRIX_RO("arm_mat",Bone,arm_mat,4),
  401. KX_PYATTRIBUTE_FLOAT_MATRIX_RO("bone_mat",Bone,bone_mat,3),
  402. KX_PYATTRIBUTE_RO_FUNCTION("parent",BL_ArmatureBone,py_bone_get_parent),
  403. KX_PYATTRIBUTE_RO_FUNCTION("children",BL_ArmatureBone,py_bone_get_children),
  404. { NULL } //Sentinel
  405. };
  406. PyObject *BL_ArmatureBone::py_bone_get_parent(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
  407. {
  408. Bone* bone = reinterpret_cast<Bone*>(self);
  409. if (bone->parent) {
  410. // create a proxy unconnected to any GE object
  411. return NewProxyPlus_Ext(NULL,&Type,bone->parent,false);
  412. }
  413. Py_RETURN_NONE;
  414. }
  415. PyObject *BL_ArmatureBone::py_bone_get_children(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
  416. {
  417. Bone* bone = reinterpret_cast<Bone*>(self);
  418. Bone* child;
  419. int count = 0;
  420. for (child = (Bone *)bone->childbase.first; child; child = child->next)
  421. count++;
  422. PyObject *childrenlist = PyList_New(count);
  423. for (count = 0, child = (Bone *)bone->childbase.first; child; child = child->next, ++count)
  424. PyList_SET_ITEM(childrenlist,count,NewProxyPlus_Ext(NULL,&Type,child,false));
  425. return childrenlist;
  426. }
  427. #endif // WITH_PYTHON