diff options
Diffstat (limited to 'source/gameengine/Converter/BL_ArmatureObject.cpp')
-rw-r--r-- | source/gameengine/Converter/BL_ArmatureObject.cpp | 691 |
1 files changed, 0 insertions, 691 deletions
diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp deleted file mode 100644 index 049fd49cab9..00000000000 --- a/source/gameengine/Converter/BL_ArmatureObject.cpp +++ /dev/null @@ -1,691 +0,0 @@ -/* - * ***** 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_ArmatureObject.cpp - * \ingroup bgeconv - */ - - -#include "BL_ArmatureObject.h" -#include "BL_ActionActuator.h" -#include "BL_Action.h" -#include "KX_BlenderSceneConverter.h" -#include "MEM_guardedalloc.h" -#include "BLI_blenlib.h" -#include "BLI_math.h" -#include "BLI_utildefines.h" -#include "BLI_ghash.h" -#include "BIK_api.h" -#include "BKE_action.h" -#include "BKE_armature.h" -#include "BKE_object.h" -#include "BKE_library.h" -#include "BKE_global.h" - -extern "C" { -#include "BKE_animsys.h" -} - -#include "BKE_constraint.h" -#include "CTR_Map.h" -#include "CTR_HashedPtr.h" -#include "MEM_guardedalloc.h" -#include "DNA_action_types.h" -#include "DNA_armature_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" -#include "DNA_constraint_types.h" -#include "RNA_access.h" -#include "KX_PythonInit.h" -#include "KX_KetsjiEngine.h" - -#include "EXP_ListWrapper.h" - -#include "MT_Matrix4x4.h" - -/** - * Move here pose function for game engine so that we can mix with GE objects - * Principle is as follow: - * Use Blender structures so that BKE_pose_where_is can be used unchanged - * Copy the constraint so that they can be enabled/disabled/added/removed at runtime - * Don't copy the constraints for the pose used by the Action actuator, it does not need them. - * Scan the constraint structures so that the KX equivalent of target objects are identified and - * stored in separate list. - * When it is about to evaluate the pose, set the KX object position in the obmat of the corresponding - * Blender objects and restore after the evaluation. - */ -static void game_copy_pose(bPose **dst, bPose *src, int copy_constraint) -{ - bPose *out; - bPoseChannel *pchan, *outpchan; - GHash *ghash; - - /* the game engine copies the current armature pose and then swaps - * the object pose pointer. this makes it possible to change poses - * without affecting the original blender data. */ - - if (!src) { - *dst=NULL; - return; - } - else if (*dst==src) { - printf("game_copy_pose source and target are the same\n"); - *dst=NULL; - return; - } - - out= (bPose*)MEM_dupallocN(src); - out->chanhash = NULL; - out->agroups.first= out->agroups.last= NULL; - out->ikdata = NULL; - out->ikparam = MEM_dupallocN(src->ikparam); - out->flag |= POSE_GAME_ENGINE; - BLI_duplicatelist(&out->chanbase, &src->chanbase); - - /* remap pointers */ - ghash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "game_copy_pose gh"); - - pchan= (bPoseChannel *)src->chanbase.first; - outpchan= (bPoseChannel *)out->chanbase.first; - for (; pchan; pchan=pchan->next, outpchan=outpchan->next) - BLI_ghash_insert(ghash, pchan, outpchan); - - for (pchan = (bPoseChannel *)out->chanbase.first; pchan; pchan = pchan->next) { - pchan->parent= (bPoseChannel *)BLI_ghash_lookup(ghash, pchan->parent); - pchan->child= (bPoseChannel *)BLI_ghash_lookup(ghash, pchan->child); - - if (copy_constraint) { - ListBase listb; - // copy all constraint for backward compatibility - // BKE_constraints_copy NULLs listb, no need to make extern for this operation. - BKE_constraints_copy(&listb, &pchan->constraints, false); - pchan->constraints= listb; - } - else { - BLI_listbase_clear(&pchan->constraints); - } - - if (pchan->custom) { - id_us_plus(&pchan->custom->id); - } - - // fails to link, props are not used in the BGE yet. -#if 0 - if (pchan->prop) - pchan->prop= IDP_CopyProperty(pchan->prop); -#endif - pchan->prop = NULL; - pchan->draw_data = NULL; - } - - BLI_ghash_free(ghash, NULL, NULL); - // set acceleration structure for channel lookup - BKE_pose_channels_hash_make(out); - *dst=out; -} - - - -/* Only allowed for Poses with identical channels */ -static void game_blend_poses(bPose *dst, bPose *src, float srcweight, short mode) -{ - bPoseChannel *dchan; - const bPoseChannel *schan; - bConstraint *dcon, *scon; - float dstweight; - int i; - - if (mode == BL_Action::ACT_BLEND_BLEND) - { - dstweight = 1.0f - srcweight; - } else if (mode == BL_Action::ACT_BLEND_ADD) - { - dstweight = 1.0f; - } else { - dstweight = 1.0f; - } - - schan= (bPoseChannel *)src->chanbase.first; - for (dchan = (bPoseChannel *)dst->chanbase.first; dchan; dchan=(bPoseChannel *)dchan->next, schan= (bPoseChannel *)schan->next) { - // always blend on all channels since we don't know which one has been set - /* quat interpolation done separate */ - if (schan->rotmode == ROT_MODE_QUAT) { - float dquat[4], squat[4]; - - copy_qt_qt(dquat, dchan->quat); - copy_qt_qt(squat, schan->quat); - // Normalize quaternions so that interpolation/multiplication result is correct. - normalize_qt(dquat); - normalize_qt(squat); - - if (mode==BL_Action::ACT_BLEND_BLEND) - interp_qt_qtqt(dchan->quat, dquat, squat, srcweight); - else { - mul_fac_qt_fl(squat, srcweight); - mul_qt_qtqt(dchan->quat, dquat, squat); - } - - normalize_qt(dchan->quat); - } - - for (i=0; i<3; i++) { - /* blending for loc and scale are pretty self-explanatory... */ - dchan->loc[i] = (dchan->loc[i]*dstweight) + (schan->loc[i]*srcweight); - dchan->size[i] = 1.0f + ((dchan->size[i]-1.0f)*dstweight) + ((schan->size[i]-1.0f)*srcweight); - - /* euler-rotation interpolation done here instead... */ - // FIXME: are these results decent? - if (schan->rotmode) - dchan->eul[i] = (dchan->eul[i]*dstweight) + (schan->eul[i]*srcweight); - } - for (dcon= (bConstraint *)dchan->constraints.first, scon= (bConstraint *)schan->constraints.first; - dcon && scon; - dcon = dcon->next, scon = scon->next) - { - /* no 'add' option for constraint blending */ - dcon->enforce= dcon->enforce*(1.0f-srcweight) + scon->enforce*srcweight; - } - } - - /* this pose is now in src time */ - dst->ctime= src->ctime; -} - -BL_ArmatureObject::BL_ArmatureObject( - void* sgReplicationInfo, - SG_Callbacks callbacks, - Object *armature, - Scene *scene, - int vert_deform_type) - -: KX_GameObject(sgReplicationInfo,callbacks), - m_controlledConstraints(), - m_poseChannels(), - m_scene(scene), // maybe remove later. needed for BKE_pose_where_is - m_lastframe(0.0), - m_timestep(0.040), - m_vert_deform_type(vert_deform_type), - m_constraintNumber(0), - m_channelNumber(0), - m_lastapplyframe(0.0) -{ - m_origObjArma = armature; // Keep a copy of the original armature so we can fix drivers later - m_objArma = BKE_object_copy(G.main, armature); - m_objArma->data = BKE_armature_copy(G.main, (bArmature *)armature->data); - // During object replication ob->data is increase, we decrease it now because we get a copy. - id_us_min(&((bArmature *)m_origObjArma->data)->id); - m_pose = m_objArma->pose; - // need this to get iTaSC working ok in the BGE - m_pose->flag |= POSE_GAME_ENGINE; - memcpy(m_obmat, m_objArma->obmat, sizeof(m_obmat)); - - // The side-effect of this method registers this object as "animatable" with the KX_Scene. - GetActionManager(); -} - -BL_ArmatureObject::~BL_ArmatureObject() -{ - BL_ArmatureConstraint* constraint; - while ((constraint = m_controlledConstraints.Remove()) != NULL) { - delete constraint; - } - BL_ArmatureChannel* channel; - while ((channel = static_cast<BL_ArmatureChannel*>(m_poseChannels.Remove())) != NULL) { - delete channel; - } - - if (m_objArma) { - BKE_libblock_free(G.main, m_objArma->data); - BKE_libblock_free(G.main, m_objArma); - } -} - - -void BL_ArmatureObject::LoadConstraints(KX_BlenderSceneConverter* converter) -{ - // first delete any existing constraint (should not have any) - while (!m_controlledConstraints.Empty()) { - BL_ArmatureConstraint* constraint = m_controlledConstraints.Remove(); - delete constraint; - } - m_constraintNumber = 0; - - // list all the constraint and convert them to BL_ArmatureConstraint - // get the persistent pose structure - bPoseChannel* pchan; - bConstraint* pcon; - const bConstraintTypeInfo* cti; - Object* blendtarget; - KX_GameObject* gametarget; - KX_GameObject* gamesubtarget; - - // and locate the constraint - for (pchan = (bPoseChannel *)m_pose->chanbase.first; pchan; pchan = pchan->next) { - for (pcon = (bConstraint *)pchan->constraints.first; pcon; pcon = pcon->next) { - if (pcon->flag & CONSTRAINT_DISABLE) - continue; - // which constraint should we support? - switch (pcon->type) { - case CONSTRAINT_TYPE_TRACKTO: - case CONSTRAINT_TYPE_DAMPTRACK: - case CONSTRAINT_TYPE_KINEMATIC: - case CONSTRAINT_TYPE_ROTLIKE: - case CONSTRAINT_TYPE_LOCLIKE: - case CONSTRAINT_TYPE_MINMAX: - case CONSTRAINT_TYPE_SIZELIKE: - case CONSTRAINT_TYPE_LOCKTRACK: - case CONSTRAINT_TYPE_STRETCHTO: - case CONSTRAINT_TYPE_CLAMPTO: - case CONSTRAINT_TYPE_TRANSFORM: - case CONSTRAINT_TYPE_DISTLIMIT: - case CONSTRAINT_TYPE_TRANSLIKE: - cti = BKE_constraint_typeinfo_get(pcon); - gametarget = gamesubtarget = NULL; - if (cti && cti->get_constraint_targets) { - ListBase listb = { NULL, NULL }; - cti->get_constraint_targets(pcon, &listb); - if (listb.first) { - bConstraintTarget* target = (bConstraintTarget*)listb.first; - if (target->tar && target->tar != m_objArma) { - // only remember external objects, self target is handled automatically - blendtarget = target->tar; - gametarget = converter->FindGameObject(blendtarget); - } - if (target->next != NULL) { - // secondary target - target = target->next; - if (target->tar && target->tar != m_objArma) { - // only track external object - blendtarget = target->tar; - gamesubtarget = converter->FindGameObject(blendtarget); - } - } - } - if (cti->flush_constraint_targets) - cti->flush_constraint_targets(pcon, &listb, 1); - } - BL_ArmatureConstraint* constraint = new BL_ArmatureConstraint(this, pchan, pcon, gametarget, gamesubtarget); - m_controlledConstraints.AddBack(constraint); - m_constraintNumber++; - } - } - } - - // If we have constraints, make sure we get treated as an "animated" object - if (m_constraintNumber > 0) - GetActionManager(); -} - -BL_ArmatureConstraint* BL_ArmatureObject::GetConstraint(const char* posechannel, const char* constraintname) -{ - SG_DList::iterator<BL_ArmatureConstraint> cit(m_controlledConstraints); - for (cit.begin(); !cit.end(); ++cit) { - BL_ArmatureConstraint* constraint = *cit; - if (constraint->Match(posechannel, constraintname)) - return constraint; - } - return NULL; -} - -BL_ArmatureConstraint* BL_ArmatureObject::GetConstraint(const char* posechannelconstraint) -{ - // performance: use hash string instead of plain string compare - SG_DList::iterator<BL_ArmatureConstraint> cit(m_controlledConstraints); - for (cit.begin(); !cit.end(); ++cit) { - BL_ArmatureConstraint* constraint = *cit; - if (!strcmp(constraint->GetName(), posechannelconstraint)) - return constraint; - } - return NULL; -} - -BL_ArmatureConstraint* BL_ArmatureObject::GetConstraint(int index) -{ - SG_DList::iterator<BL_ArmatureConstraint> cit(m_controlledConstraints); - for (cit.begin(); !cit.end() && index; ++cit, --index); - return (cit.end()) ? NULL : *cit; -} - -/* this function is called to populate the m_poseChannels list */ -void BL_ArmatureObject::LoadChannels() -{ - if (m_poseChannels.Empty()) { - bPoseChannel* pchan; - BL_ArmatureChannel* proxy; - - m_channelNumber = 0; - for (pchan = (bPoseChannel *)m_pose->chanbase.first; pchan; pchan=(bPoseChannel *)pchan->next) { - proxy = new BL_ArmatureChannel(this, pchan); - m_poseChannels.AddBack(proxy); - m_channelNumber++; - } - } -} - -BL_ArmatureChannel* BL_ArmatureObject::GetChannel(bPoseChannel* pchan) -{ - LoadChannels(); - SG_DList::iterator<BL_ArmatureChannel> cit(m_poseChannels); - for (cit.begin(); !cit.end(); ++cit) - { - BL_ArmatureChannel* channel = *cit; - if (channel->m_posechannel == pchan) - return channel; - } - return NULL; -} - -BL_ArmatureChannel* BL_ArmatureObject::GetChannel(const char* str) -{ - LoadChannels(); - SG_DList::iterator<BL_ArmatureChannel> cit(m_poseChannels); - for (cit.begin(); !cit.end(); ++cit) - { - BL_ArmatureChannel* channel = *cit; - if (!strcmp(channel->m_posechannel->name, str)) - return channel; - } - return NULL; -} - -BL_ArmatureChannel* BL_ArmatureObject::GetChannel(int index) -{ - LoadChannels(); - if (index < 0 || index >= m_channelNumber) - return NULL; - SG_DList::iterator<BL_ArmatureChannel> cit(m_poseChannels); - for (cit.begin(); !cit.end() && index; ++cit, --index); - return (cit.end()) ? NULL : *cit; -} - -CValue* BL_ArmatureObject::GetReplica() -{ - BL_ArmatureObject* replica = new BL_ArmatureObject(*this); - replica->ProcessReplica(); - return replica; -} - -void BL_ArmatureObject::ProcessReplica() -{ - KX_GameObject::ProcessReplica(); - - bArmature* tmp = (bArmature*)m_objArma->data; - m_objArma = BKE_object_copy(G.main, m_objArma); - m_objArma->data = BKE_armature_copy(G.main, tmp); - m_pose = m_objArma->pose; -} - -void BL_ArmatureObject::ReParentLogic() -{ - SG_DList::iterator<BL_ArmatureConstraint> cit(m_controlledConstraints); - for (cit.begin(); !cit.end(); ++cit) { - (*cit)->ReParent(this); - } - KX_GameObject::ReParentLogic(); -} - -void BL_ArmatureObject::Relink(CTR_Map<CTR_HashedPtr, void*> *obj_map) -{ - SG_DList::iterator<BL_ArmatureConstraint> cit(m_controlledConstraints); - for (cit.begin(); !cit.end(); ++cit) { - (*cit)->Relink(obj_map); - } - KX_GameObject::Relink(obj_map); -} - -bool BL_ArmatureObject::UnlinkObject(SCA_IObject* clientobj) -{ - // clientobj is being deleted, make sure we don't hold any reference to it - bool res = false; - SG_DList::iterator<BL_ArmatureConstraint> cit(m_controlledConstraints); - for (cit.begin(); !cit.end(); ++cit) { - res |= (*cit)->UnlinkObject(clientobj); - } - return res; -} - -void BL_ArmatureObject::ApplyPose() -{ - /* TODO: This doesn't work currently because of eval_ctx. */ -#if 0 - m_armpose = m_objArma->pose; - m_objArma->pose = m_pose; - // in the GE, we use ctime to store the timestep - m_pose->ctime = (float)m_timestep; - //m_scene->r.cfra++; - if (m_lastapplyframe != m_lastframe) { - // update the constraint if any, first put them all off so that only the active ones will be updated - SG_DList::iterator<BL_ArmatureConstraint> cit(m_controlledConstraints); - for (cit.begin(); !cit.end(); ++cit) { - (*cit)->UpdateTarget(); - } - // update ourself - UpdateBlenderObjectMatrix(m_objArma); - BKE_pose_where_is(m_scene, m_objArma); // XXX - // restore ourself - memcpy(m_objArma->obmat, m_obmat, sizeof(m_obmat)); - // restore active targets - for (cit.begin(); !cit.end(); ++cit) { - (*cit)->RestoreTarget(); - } - m_lastapplyframe = m_lastframe; - } -#endif -} - -void BL_ArmatureObject::RestorePose() -{ - m_objArma->pose = m_armpose; - m_armpose = NULL; -} - -void BL_ArmatureObject::SetPose(bPose *pose) -{ - extract_pose_from_pose(m_pose, pose); - m_lastapplyframe = -1.0; -} - -void BL_ArmatureObject::SetPoseByAction(bAction *action, float localtime) -{ - Object *arm = GetArmatureObject(); - - PointerRNA ptrrna; - RNA_id_pointer_create(&arm->id, &ptrrna); - - animsys_evaluate_action(&ptrrna, action, NULL, localtime); -} - -void BL_ArmatureObject::BlendInPose(bPose *blend_pose, float weight, short mode) -{ - game_blend_poses(m_pose, blend_pose, weight, mode); -} - -bool BL_ArmatureObject::UpdateTimestep(double curtime) -{ - if (curtime != m_lastframe) { - // compute the timestep for the underlying IK algorithm - m_timestep = curtime-m_lastframe; - m_lastframe= curtime; - } - - return false; -} - -void BL_ArmatureObject::GetPose(bPose **pose) -{ - /* If the caller supplies a null pose, create a new one. */ - /* Otherwise, copy the armature's pose channels into the caller-supplied pose */ - - if (!*pose) { - /* probably not to good of an idea to - * duplicate everything, but it clears up - * a crash and memory leakage when - * &BL_ActionActuator::m_pose is freed - */ - game_copy_pose(pose, m_pose, 0); - } - else { - if (*pose == m_pose) - // no need to copy if the pointers are the same - return; - - extract_pose_from_pose(*pose, m_pose); - } -} - -double BL_ArmatureObject::GetLastFrame() -{ - return m_lastframe; -} - -bool BL_ArmatureObject::GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix) -{ - bPoseChannel *pchan; - - ApplyPose(); - pchan = BKE_pose_channel_find_name(m_objArma->pose, bone->name); - if (pchan) - matrix.setValue(&pchan->pose_mat[0][0]); - RestorePose(); - - return (pchan != NULL); -} - -float BL_ArmatureObject::GetBoneLength(Bone* bone) const -{ - return (float)(MT_Point3(bone->head) - MT_Point3(bone->tail)).length(); -} - -#ifdef WITH_PYTHON - -// PYTHON - -PyTypeObject BL_ArmatureObject::Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "BL_ArmatureObject", - sizeof(PyObjectPlus_Proxy), - 0, - py_base_dealloc, - 0, - 0, - 0, - 0, - py_base_repr, - 0, - &KX_GameObject::Sequence, - &KX_GameObject::Mapping, - 0,0,0, - NULL, - NULL, - 0, - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - 0,0,0,0,0,0,0, - Methods, - 0, - 0, - &KX_GameObject::Type, - 0,0,0,0,0,0, - py_base_new -}; - -PyMethodDef BL_ArmatureObject::Methods[] = { - KX_PYMETHODTABLE_NOARGS(BL_ArmatureObject, update), - {NULL,NULL} //Sentinel -}; - -PyAttributeDef BL_ArmatureObject::Attributes[] = { - - KX_PYATTRIBUTE_RO_FUNCTION("constraints", BL_ArmatureObject, pyattr_get_constraints), - KX_PYATTRIBUTE_RO_FUNCTION("channels", BL_ArmatureObject, pyattr_get_channels), - {NULL} //Sentinel -}; - -static int bl_armature_object_get_constraints_size_cb(void *self_v) -{ - return ((BL_ArmatureObject *)self_v)->GetConstraintNumber(); -} - -static PyObject *bl_armature_object_get_constraints_item_cb(void *self_v, int index) -{ - return ((BL_ArmatureObject *)self_v)->GetConstraint(index)->GetProxy(); -} - -static const char *bl_armature_object_get_constraints_item_name_cb(void *self_v, int index) -{ - return ((BL_ArmatureObject *)self_v)->GetConstraint(index)->GetName(); -} - -PyObject *BL_ArmatureObject::pyattr_get_constraints(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ - return (new CListWrapper(self_v, - ((BL_ArmatureObject *)self_v)->GetProxy(), - NULL, - bl_armature_object_get_constraints_size_cb, - bl_armature_object_get_constraints_item_cb, - bl_armature_object_get_constraints_item_name_cb, - NULL))->NewProxy(true); -} - -static int bl_armature_object_get_channels_size_cb(void *self_v) -{ - return ((BL_ArmatureObject *)self_v)->GetChannelNumber(); -} - -static PyObject *bl_armature_object_get_channels_item_cb(void *self_v, int index) -{ - return ((BL_ArmatureObject *)self_v)->GetChannel(index)->GetProxy(); -} - -static const char *bl_armature_object_get_channels_item_name_cb(void *self_v, int index) -{ - return ((BL_ArmatureObject *)self_v)->GetChannel(index)->GetName(); -} - -PyObject *BL_ArmatureObject::pyattr_get_channels(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ - BL_ArmatureObject *self = static_cast<BL_ArmatureObject *>(self_v); - self->LoadChannels(); // make sure we have the channels - return (new CListWrapper(self_v, - self->GetProxy(), - NULL, - bl_armature_object_get_channels_size_cb, - bl_armature_object_get_channels_item_cb, - bl_armature_object_get_channels_item_name_cb, - NULL))->NewProxy(true); -} - -KX_PYMETHODDEF_DOC_NOARGS(BL_ArmatureObject, update, - "update()\n" - "Make sure that the armature will be updated on next graphic frame.\n" - "This is automatically done if a KX_ArmatureActuator with mode run is active\n" - "or if an action is playing. This function is useful in other cases.\n") -{ - UpdateTimestep(KX_GetActiveEngine()->GetFrameTime()); - Py_RETURN_NONE; -} - -#endif // WITH_PYTHON |