Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/gameengine')
-rw-r--r--source/gameengine/Converter/BL_ActionActuator.cpp13
-rw-r--r--source/gameengine/Converter/BL_ActionActuator.h3
-rw-r--r--source/gameengine/Converter/BL_ArmatureActuator.cpp2
-rw-r--r--source/gameengine/Converter/BL_ArmatureObject.cpp127
-rw-r--r--source/gameengine/Converter/BL_ArmatureObject.h24
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp21
-rw-r--r--source/gameengine/Converter/BL_ShapeDeformer.cpp29
-rw-r--r--source/gameengine/Converter/BL_ShapeDeformer.h2
-rw-r--r--source/gameengine/Converter/BL_SkinDeformer.cpp88
-rw-r--r--source/gameengine/Ketsji/BL_Action.cpp57
-rw-r--r--source/gameengine/Ketsji/BL_Action.h2
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.cpp6
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.h6
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp92
14 files changed, 225 insertions, 247 deletions
diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp
index a28906254a1..34d36846968 100644
--- a/source/gameengine/Converter/BL_ActionActuator.cpp
+++ b/source/gameengine/Converter/BL_ActionActuator.cpp
@@ -93,9 +93,6 @@ BL_ActionActuator::BL_ActionActuator(SCA_IObject *gameobj,
m_priority(priority),
m_layer(layer),
m_ipo_flags(ipo_flags),
- m_pose(NULL),
- m_blendpose(NULL),
- m_userpose(NULL),
m_action(action),
m_propname(propname),
m_framepropname(framepropname)
@@ -106,20 +103,12 @@ BL_ActionActuator::BL_ActionActuator(SCA_IObject *gameobj,
BL_ActionActuator::~BL_ActionActuator()
{
- if (m_pose)
- game_free_pose(m_pose);
- if (m_userpose)
- game_free_pose(m_userpose);
- if (m_blendpose)
- game_free_pose(m_blendpose);
}
void BL_ActionActuator::ProcessReplica()
{
SCA_IActuator::ProcessReplica();
-
- m_pose = NULL;
- m_blendpose = NULL;
+
m_localtime=m_startframe;
m_lastUpdate=-1;
diff --git a/source/gameengine/Converter/BL_ActionActuator.h b/source/gameengine/Converter/BL_ActionActuator.h
index 4579a21f554..f488b0c76a6 100644
--- a/source/gameengine/Converter/BL_ActionActuator.h
+++ b/source/gameengine/Converter/BL_ActionActuator.h
@@ -134,9 +134,6 @@ protected:
short m_priority;
short m_layer;
short m_ipo_flags;
- struct bPose* m_pose;
- struct bPose* m_blendpose;
- struct bPose* m_userpose;
struct bAction *m_action;
STR_String m_propname;
STR_String m_framepropname;
diff --git a/source/gameengine/Converter/BL_ArmatureActuator.cpp b/source/gameengine/Converter/BL_ArmatureActuator.cpp
index f0c4b3d32bb..e38cb6eadaf 100644
--- a/source/gameengine/Converter/BL_ArmatureActuator.cpp
+++ b/source/gameengine/Converter/BL_ArmatureActuator.cpp
@@ -155,7 +155,7 @@ bool BL_ArmatureActuator::Update(double curtime, bool frame)
switch (m_type) {
case ACT_ARM_RUN:
result = true;
- obj->SetActiveAction(NULL, 0, curtime);
+ obj->UpdateTimestep(curtime);
break;
case ACT_ARM_ENABLE:
if (m_constraint)
diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp
index 619797a8c69..3eb782961e3 100644
--- a/source/gameengine/Converter/BL_ArmatureObject.cpp
+++ b/source/gameengine/Converter/BL_ArmatureObject.cpp
@@ -42,7 +42,13 @@
#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"
@@ -53,6 +59,7 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_constraint_types.h"
+#include "RNA_access.h"
#include "KX_PythonSeq.h"
#include "KX_PythonInit.h"
#include "KX_KetsjiEngine.h"
@@ -70,7 +77,7 @@
* 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.
*/
-void game_copy_pose(bPose **dst, bPose *src, int copy_constraint)
+static void game_copy_pose(bPose **dst, bPose *src, int copy_constraint)
{
bPose *out;
bPoseChannel *pchan, *outpchan;
@@ -85,7 +92,7 @@ void game_copy_pose(bPose **dst, bPose *src, int copy_constraint)
return;
}
else if (*dst==src) {
- printf("BKE_pose_copy_data source and target are the same\n");
+ printf("game_copy_pose source and target are the same\n");
*dst=NULL;
return;
}
@@ -142,7 +149,7 @@ void game_copy_pose(bPose **dst, bPose *src, int copy_constraint)
/* Only allowed for Poses with identical channels */
-void game_blend_poses(bPose *dst, bPose *src, float srcweight, short mode)
+static void game_blend_poses(bPose *dst, bPose *src, float srcweight, short mode)
{
bPoseChannel *dchan;
const bPoseChannel *schan;
@@ -202,23 +209,6 @@ void game_blend_poses(bPose *dst, bPose *src, float srcweight, short mode)
dst->ctime= src->ctime;
}
-void game_free_pose(bPose *pose)
-{
- if (pose) {
- /* free pose-channels and constraints */
- BKE_pose_channels_free(pose);
-
- /* free IK solver state */
- BIK_clear_data(pose);
-
- /* free IK solver param */
- if (pose->ikparam)
- MEM_freeN(pose->ikparam);
-
- MEM_freeN(pose);
- }
-}
-
BL_ArmatureObject::BL_ArmatureObject(
void* sgReplicationInfo,
SG_Callbacks callbacks,
@@ -229,26 +219,18 @@ BL_ArmatureObject::BL_ArmatureObject(
: KX_GameObject(sgReplicationInfo,callbacks),
m_controlledConstraints(),
m_poseChannels(),
- m_objArma(armature),
- m_framePose(NULL),
m_scene(scene), // maybe remove later. needed for BKE_pose_where_is
m_lastframe(0.0),
m_timestep(0.040),
- m_activeAct(NULL),
- m_activePriority(999),
m_vert_deform_type(vert_deform_type),
m_constraintNumber(0),
m_channelNumber(0),
m_lastapplyframe(0.0)
{
- m_armature = (bArmature *)armature->data;
-
- /* we make a copy of blender object's pose, and then always swap it with
- * the original pose before calling into blender functions, to deal with
- * replica's or other objects using the same blender object */
- m_pose = NULL;
- game_copy_pose(&m_pose, m_objArma->pose, 1);
- // store the original armature object matrix
+ m_origObjArma = armature; // Keep a copy of the original armature so we can fix drivers later
+ m_objArma = BKE_object_copy(armature);
+ m_objArma->data = BKE_armature_copy((bArmature *)armature->data);
+ m_pose = m_objArma->pose;
memcpy(m_obmat, m_objArma->obmat, sizeof(m_obmat));
}
@@ -262,10 +244,9 @@ BL_ArmatureObject::~BL_ArmatureObject()
while ((channel = static_cast<BL_ArmatureChannel*>(m_poseChannels.Remove())) != NULL) {
delete channel;
}
- if (m_pose)
- game_free_pose(m_pose);
- if (m_framePose)
- game_free_pose(m_framePose);
+
+ if (m_objArma)
+ BKE_libblock_free(G.main, m_objArma);
}
@@ -431,12 +412,12 @@ CValue* BL_ArmatureObject::GetReplica()
void BL_ArmatureObject::ProcessReplica()
{
- bPose *pose= m_pose;
KX_GameObject::ProcessReplica();
- m_pose = NULL;
- m_framePose = NULL;
- game_copy_pose(&m_pose, pose, 1);
+ bArmature* tmp = (bArmature*)m_objArma->data;
+ m_objArma = BKE_object_copy(m_objArma);
+ m_objArma->data = BKE_armature_copy(tmp);
+ m_pose = m_objArma->pose;
}
void BL_ArmatureObject::ReParentLogic()
@@ -506,48 +487,32 @@ void BL_ArmatureObject::SetPose(bPose *pose)
m_lastapplyframe = -1.0;
}
-bool BL_ArmatureObject::SetActiveAction(BL_ActionActuator *act, short priority, double curtime)
+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) {
- m_activePriority = 9999;
// compute the timestep for the underlying IK algorithm
m_timestep = curtime-m_lastframe;
m_lastframe= curtime;
- m_activeAct = NULL;
- // remember the pose at the start of the frame
- GetPose(&m_framePose);
}
- if (act)
- {
- if (priority<=m_activePriority)
- {
- if (priority<m_activePriority) {
- // this action overwrites the previous ones, start from initial pose to cancel their effects
- SetPose(m_framePose);
- if (m_activeAct && (m_activeAct!=act))
- /* Reset the blend timer since this new action cancels the old one */
- m_activeAct->SetBlendTime(0.0);
- }
- m_activeAct = act;
- m_activePriority = priority;
- m_lastframe = curtime;
-
- return true;
- }
- else {
- act->SetBlendTime(0.0);
- return false;
- }
- }
return false;
}
-BL_ActionActuator * BL_ArmatureObject::GetActiveAction()
-{
- return m_activeAct;
-}
-
void BL_ArmatureObject::GetPose(bPose **pose)
{
/* If the caller supplies a null pose, create a new one. */
@@ -570,22 +535,6 @@ void BL_ArmatureObject::GetPose(bPose **pose)
}
}
-void BL_ArmatureObject::GetMRDPose(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)
- game_copy_pose(pose, m_pose, 0);
- else
- extract_pose_from_pose(*pose, m_pose);
-}
-
-short BL_ArmatureObject::GetActivePriority()
-{
- return m_activePriority;
-}
-
double BL_ArmatureObject::GetLastFrame()
{
return m_lastframe;
@@ -671,7 +620,7 @@ KX_PYMETHODDEF_DOC_NOARGS(BL_ArmatureObject, update,
"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")
{
- SetActiveAction(NULL, 0, KX_GetActiveEngine()->GetFrameTime());
+ UpdateTimestep(KX_GetActiveEngine()->GetFrameTime());
Py_RETURN_NONE;
}
diff --git a/source/gameengine/Converter/BL_ArmatureObject.h b/source/gameengine/Converter/BL_ArmatureObject.h
index 81388355fc4..691e73d6bde 100644
--- a/source/gameengine/Converter/BL_ArmatureObject.h
+++ b/source/gameengine/Converter/BL_ArmatureObject.h
@@ -55,14 +55,11 @@ class BL_ArmatureObject : public KX_GameObject
public:
double GetLastFrame ();
- short GetActivePriority();
virtual void ProcessReplica();
virtual void ReParentLogic();
virtual void Relink(CTR_Map<CTR_HashedPtr, void*> *obj_map);
virtual bool UnlinkObject(SCA_IObject* clientobj);
- class BL_ActionActuator * GetActiveAction();
-
BL_ArmatureObject(
void* sgReplicationInfo,
SG_Callbacks callbacks,
@@ -73,21 +70,23 @@ public:
virtual ~BL_ArmatureObject();
virtual CValue* GetReplica();
- void GetMRDPose(struct bPose **pose);
void GetPose(struct bPose **pose);
void SetPose (struct bPose *pose);
struct bPose *GetOrigPose() {return m_pose;} // never edit this, only for accessing names
void ApplyPose();
+ void SetPoseByAction(struct bAction* action, float localtime);
+ void BlendInPose(struct bPose *blend_pose, float weight, short mode);
void RestorePose();
- bool SetActiveAction(class BL_ActionActuator *act, short priority, double curtime);
+ bool UpdateTimestep(double curtime);
- struct bArmature *GetArmature() { return m_armature; }
- const struct bArmature * GetArmature() const { return m_armature; }
+ struct bArmature *GetArmature() { return (bArmature*)m_objArma->data; }
+ const struct bArmature * GetArmature() const { return (bArmature*)m_objArma->data; }
const struct Scene * GetScene() const { return m_scene; }
Object* GetArmatureObject() {return m_objArma;}
+ Object* GetOrigArmatureObject() {return m_origObjArma;}
int GetVertDeformType() {return m_vert_deform_type;}
@@ -128,15 +127,12 @@ protected:
/* list element: BL_ArmatureChannel. Use SG_DList to avoid list replication */
SG_DList m_poseChannels;
Object *m_objArma;
- struct bArmature *m_armature;
+ Object *m_origObjArma;
struct bPose *m_pose;
struct bPose *m_armpose;
- struct bPose *m_framePose;
struct Scene *m_scene; // need for BKE_pose_where_is
double m_lastframe;
double m_timestep; // delta since last pose evaluation.
- class BL_ActionActuator *m_activeAct;
- short m_activePriority;
int m_vert_deform_type;
size_t m_constraintNumber;
size_t m_channelNumber;
@@ -146,10 +142,4 @@ protected:
double m_lastapplyframe;
};
-/* Pose function specific to the game engine */
-void game_blend_poses(struct bPose *dst, struct bPose *src, float srcweight, short mode); /* was blend_poses */
-//void extract_pose_from_pose(struct bPose *pose, const struct bPose *src);
-void game_copy_pose(struct bPose **dst, struct bPose *src, int copy_con);
-void game_free_pose(struct bPose *pose);
-
#endif /* __BL_ARMATUREOBJECT_H__ */
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index 4b55d73178c..b283330266f 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -1937,15 +1937,11 @@ static KX_GameObject *gameobject_from_blenderobject(
BL_ModifierDeformer *dcont = new BL_ModifierDeformer((BL_DeformableGameObject *)gameobj,
kxscene->GetBlenderScene(), ob, meshobj);
((BL_DeformableGameObject*)gameobj)->SetDeformer(dcont);
- if (bHasShapeKey && bHasArmature)
- dcont->LoadShapeDrivers(ob->parent);
} else if (bHasShapeKey) {
// not that we can have shape keys without dvert!
BL_ShapeDeformer *dcont = new BL_ShapeDeformer((BL_DeformableGameObject*)gameobj,
ob, meshobj);
((BL_DeformableGameObject*)gameobj)->SetDeformer(dcont);
- if (bHasArmature)
- dcont->LoadShapeDrivers(ob->parent);
} else if (bHasArmature) {
BL_SkinDeformer *dcont = new BL_SkinDeformer((BL_DeformableGameObject*)gameobj,
ob, meshobj);
@@ -2640,12 +2636,25 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
gameobj->GetDeformer()->UpdateBuckets();
}
- // Set up armature constraints
+ // Set up armature constraints and shapekey drivers
for (i=0;i<sumolist->GetCount();++i)
{
KX_GameObject* gameobj = (KX_GameObject*) sumolist->GetValue(i);
if (gameobj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
- ((BL_ArmatureObject*)gameobj)->LoadConstraints(converter);
+ {
+ BL_ArmatureObject *armobj = (BL_ArmatureObject*)gameobj;
+ armobj->LoadConstraints(converter);
+
+ CListValue *children = armobj->GetChildren();
+ for (int j=0; j<children->GetCount();++j)
+ {
+ BL_ShapeDeformer *deform = dynamic_cast<BL_ShapeDeformer*>(((KX_GameObject*)children->GetValue(j))->GetDeformer());
+ if (deform)
+ deform->LoadShapeDrivers(armobj);
+ }
+
+ children->Release();
+ }
}
bool processCompoundChildren = false;
diff --git a/source/gameengine/Converter/BL_ShapeDeformer.cpp b/source/gameengine/Converter/BL_ShapeDeformer.cpp
index ca5b26079b1..43f719d80c4 100644
--- a/source/gameengine/Converter/BL_ShapeDeformer.cpp
+++ b/source/gameengine/Converter/BL_ShapeDeformer.cpp
@@ -51,6 +51,7 @@
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_key.h"
+#include "BKE_fcurve.h"
#include "BKE_ipo.h"
#include "BKE_library.h"
#include "MT_Point3.h"
@@ -119,8 +120,29 @@ void BL_ShapeDeformer::ProcessReplica()
m_key = BKE_key_copy(m_key);
}
-bool BL_ShapeDeformer::LoadShapeDrivers(Object* arma)
+bool BL_ShapeDeformer::LoadShapeDrivers(KX_GameObject* parent)
{
+ // Fix drivers since BL_ArmatureObject makes copies
+ if (parent->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE) {
+ BL_ArmatureObject *arma = (BL_ArmatureObject*)parent;
+ FCurve *fcu;
+
+ for (fcu = (FCurve*)GetKey()->adt->drivers.first; fcu; fcu = (FCurve*)fcu->next) {
+
+ DriverVar *dvar;
+ for (dvar = (DriverVar*)fcu->driver->variables.first; dvar; dvar = (DriverVar*)dvar->next) {
+ DRIVER_TARGETS_USED_LOOPER(dvar)
+ {
+ if (dtar->id) {
+ if ((Object*)dtar->id == arma->GetOrigArmatureObject())
+ dtar->id = (ID*)arma->GetArmatureObject();
+ }
+ }
+ DRIVER_TARGETS_LOOPER_END
+ }
+ }
+ }
+
// This used to check if we had drivers from this armature,
// now we just assume we want to use shape drivers
// and let the animsys handle things.
@@ -132,15 +154,10 @@ bool BL_ShapeDeformer::LoadShapeDrivers(Object* arma)
bool BL_ShapeDeformer::ExecuteShapeDrivers(void)
{
if (m_useShapeDrivers && PoseUpdated()) {
- // the shape drivers use the bone matrix as input. Must
- // update the matrix now
- m_armobj->ApplyPose();
-
// We don't need an actual time, just use 0
BKE_animsys_evaluate_animdata(NULL, &GetKey()->id, GetKey()->adt, 0.f, ADT_RECALC_DRIVERS);
ForceUpdate();
- m_armobj->RestorePose();
m_bDynamic = true;
return true;
}
diff --git a/source/gameengine/Converter/BL_ShapeDeformer.h b/source/gameengine/Converter/BL_ShapeDeformer.h
index a506fb9c7f6..f6746dd2302 100644
--- a/source/gameengine/Converter/BL_ShapeDeformer.h
+++ b/source/gameengine/Converter/BL_ShapeDeformer.h
@@ -61,7 +61,7 @@ public:
virtual ~BL_ShapeDeformer();
bool Update (void);
- bool LoadShapeDrivers(Object* arma);
+ bool LoadShapeDrivers(KX_GameObject* parent);
bool ExecuteShapeDrivers(void);
struct Key *GetKey();
diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp
index e068a91bf7e..8e1f51238d5 100644
--- a/source/gameengine/Converter/BL_SkinDeformer.cpp
+++ b/source/gameengine/Converter/BL_SkinDeformer.cpp
@@ -152,44 +152,8 @@ void BL_SkinDeformer::Relink(CTR_Map<class CTR_HashedPtr, void*>*map)
bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat)
{
- RAS_MeshSlot::iterator it;
- RAS_MeshMaterial *mmat;
- RAS_MeshSlot *slot;
- size_t i, nmat, imat;
-
- // update the vertex in m_transverts
- if (!Update())
- return false;
-
- if (m_transverts) {
- // the vertex cache is unique to this deformer, no need to update it
- // if it wasn't updated! We must update all the materials at once
- // because we will not get here again for the other material
- nmat = m_pMeshObject->NumMaterials();
- for (imat=0; imat<nmat; imat++) {
- mmat = m_pMeshObject->GetMeshMaterial(imat);
- if (!mmat->m_slots[(void*)m_gameobj])
- continue;
-
- slot = *mmat->m_slots[(void*)m_gameobj];
-
- // for each array
- for (slot->begin(it); !slot->end(it); slot->next(it)) {
- // for each vertex
- // copy the untransformed data from the original mvert
- for (i=it.startvertex; i<it.endvertex; i++) {
- RAS_TexVert& v = it.vertex[i];
- v.SetXYZ(m_transverts[v.getOrigIndex()]);
- if (m_copyNormals)
- v.SetNormal(m_transnors[v.getOrigIndex()]);
- }
- }
- }
-
- if (m_copyNormals)
- m_copyNormals = false;
- }
- return true;
+ // We do everything in UpdateInternal() now so we can thread it.
+ return false;
}
RAS_Deformer *BL_SkinDeformer::GetReplica()
@@ -331,7 +295,7 @@ bool BL_SkinDeformer::UpdateInternal(bool shape_applied)
if (!shape_applied) {
/* store verts locally */
VerifyStorage();
-
+
/* duplicate */
for (int v =0; v<m_bmesh->totvert; v++)
{
@@ -342,15 +306,10 @@ bool BL_SkinDeformer::UpdateInternal(bool shape_applied)
m_armobj->ApplyPose();
- switch (m_armobj->GetVertDeformType())
- {
- case ARM_VDEF_BGE_CPU:
- BGEDeformVerts();
- break;
- case ARM_VDEF_BLENDER:
- default:
- BlenderDeformVerts();
- }
+ if (m_armobj->GetVertDeformType() == ARM_VDEF_BGE_CPU)
+ BGEDeformVerts();
+ else
+ BlenderDeformVerts();
/* Update the current frame */
m_lastArmaUpdate=m_armobj->GetLastFrame();
@@ -359,6 +318,39 @@ bool BL_SkinDeformer::UpdateInternal(bool shape_applied)
/* dynamic vertex, cannot use display list */
m_bDynamic = true;
/* indicate that the m_transverts and normals are up to date */
+ RAS_MeshSlot::iterator it;
+ RAS_MeshMaterial *mmat;
+ RAS_MeshSlot *slot;
+ size_t i, nmat, imat;
+
+ if (m_transverts) {
+ // the vertex cache is unique to this deformer, no need to update it
+ // if it wasn't updated! We must update all the materials at once
+ // because we will not get here again for the other material
+ nmat = m_pMeshObject->NumMaterials();
+ for (imat=0; imat<nmat; imat++) {
+ mmat = m_pMeshObject->GetMeshMaterial(imat);
+ if (!mmat->m_slots[(void*)m_gameobj])
+ continue;
+
+ slot = *mmat->m_slots[(void*)m_gameobj];
+
+ // for each array
+ for (slot->begin(it); !slot->end(it); slot->next(it)) {
+ // for each vertex
+ // copy the untransformed data from the original mvert
+ for (i=it.startvertex; i<it.endvertex; i++) {
+ RAS_TexVert& v = it.vertex[i];
+ v.SetXYZ(m_transverts[v.getOrigIndex()]);
+ if (m_copyNormals)
+ v.SetNormal(m_transnors[v.getOrigIndex()]);
+ }
+ }
+ }
+
+ if (m_copyNormals)
+ m_copyNormals = false;
+ }
return true;
}
diff --git a/source/gameengine/Ketsji/BL_Action.cpp b/source/gameengine/Ketsji/BL_Action.cpp
index a974ffbf672..e4ab2d5ce28 100644
--- a/source/gameengine/Ketsji/BL_Action.cpp
+++ b/source/gameengine/Ketsji/BL_Action.cpp
@@ -51,10 +51,14 @@ extern "C" {
#include "DNA_material_types.h"
}
+#include "MEM_guardedalloc.h"
+#include "BKE_library.h"
+#include "BKE_global.h"
+
BL_Action::BL_Action(class KX_GameObject* gameobj)
:
m_action(NULL),
- m_pose(NULL),
+ m_tmpaction(NULL),
m_blendpose(NULL),
m_blendinpose(NULL),
m_obj(gameobj),
@@ -77,13 +81,16 @@ BL_Action::BL_Action(class KX_GameObject* gameobj)
BL_Action::~BL_Action()
{
- if (m_pose)
- game_free_pose(m_pose);
if (m_blendpose)
- game_free_pose(m_blendpose);
+ BKE_pose_free(m_blendpose);
if (m_blendinpose)
- game_free_pose(m_blendinpose);
+ BKE_pose_free(m_blendinpose);
ClearControllerList();
+
+ if (m_tmpaction) {
+ BKE_libblock_free(G.main, m_tmpaction);
+ m_tmpaction = NULL;
+ }
}
void BL_Action::ClearControllerList()
@@ -139,6 +146,13 @@ bool BL_Action::Play(const char* name,
&& m_priority == priority && m_speed == playback_speed)
return false;
+ // Keep a copy of the action for threading purposes
+ if (m_tmpaction) {
+ BKE_libblock_free(G.main, m_tmpaction);
+ m_tmpaction = NULL;
+ }
+ m_tmpaction = BKE_action_copy(m_action);
+
// First get rid of any old controllers
ClearControllerList();
@@ -208,7 +222,7 @@ bool BL_Action::Play(const char* name,
if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
{
BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj;
- obj->GetMRDPose(&m_blendinpose);
+ obj->GetPose(&m_blendinpose);
}
else
{
@@ -402,22 +416,12 @@ void BL_Action::Update(float curtime)
if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
{
BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj;
- obj->GetPose(&m_pose);
-
- // Extract the pose from the action
- {
- Object *arm = obj->GetArmatureObject();
- bPose *temp = arm->pose;
-
- arm->pose = m_pose;
- PointerRNA ptrrna;
- RNA_id_pointer_create(&arm->id, &ptrrna);
-
- animsys_evaluate_action(&ptrrna, m_action, NULL, m_localtime);
+ if (m_layer_weight >= 0)
+ obj->GetPose(&m_blendpose);
- arm->pose = temp;
- }
+ // Extract the pose from the action
+ obj->SetPoseByAction(m_tmpaction, m_localtime);
// Handle blending between armature actions
if (m_blendin && m_blendframe<m_blendin)
@@ -428,20 +432,15 @@ void BL_Action::Update(float curtime)
float weight = 1.f - (m_blendframe/m_blendin);
// Blend the poses
- game_blend_poses(m_pose, m_blendinpose, weight, ACT_BLEND_BLEND);
+ obj->BlendInPose(m_blendinpose, weight, ACT_BLEND_BLEND);
}
// Handle layer blending
if (m_layer_weight >= 0)
- {
- obj->GetMRDPose(&m_blendpose);
- game_blend_poses(m_pose, m_blendpose, m_layer_weight, m_blendmode);
- }
-
- obj->SetPose(m_pose);
+ obj->BlendInPose(m_blendpose, m_layer_weight, m_blendmode);
- obj->SetActiveAction(NULL, 0, curtime);
+ obj->UpdateTimestep(curtime);
}
else
{
@@ -456,7 +455,7 @@ void BL_Action::Update(float curtime)
PointerRNA ptrrna;
RNA_id_pointer_create(&key->id, &ptrrna);
- animsys_evaluate_action(&ptrrna, m_action, NULL, m_localtime);
+ animsys_evaluate_action(&ptrrna, m_tmpaction, NULL, m_localtime);
// Handle blending between shape actions
if (m_blendin && m_blendframe < m_blendin)
diff --git a/source/gameengine/Ketsji/BL_Action.h b/source/gameengine/Ketsji/BL_Action.h
index e9d09916517..463d177c876 100644
--- a/source/gameengine/Ketsji/BL_Action.h
+++ b/source/gameengine/Ketsji/BL_Action.h
@@ -38,7 +38,7 @@ class BL_Action
{
private:
struct bAction* m_action;
- struct bPose* m_pose;
+ struct bAction* m_tmpaction;
struct bPose* m_blendpose;
struct bPose* m_blendinpose;
std::vector<class SG_Controller*> m_sg_contr_list;
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
index 231590cde83..96a3845a439 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
@@ -37,6 +37,8 @@
#include <iostream>
#include <stdio.h>
+#include "BLI_task.h"
+
#include "KX_KetsjiEngine.h"
#include "ListValue.h"
@@ -185,6 +187,7 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system)
m_pyprofiledict = PyDict_New();
#endif
+ m_taskscheduler = BLI_task_scheduler_create(TASK_SCHEDULER_AUTO_THREADS);
}
@@ -201,6 +204,9 @@ KX_KetsjiEngine::~KX_KetsjiEngine()
#ifdef WITH_PYTHON
Py_CLEAR(m_pyprofiledict);
#endif
+
+ if (m_taskscheduler)
+ BLI_task_scheduler_free(m_taskscheduler);
}
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h
index 85cd8bba2de..9e5d1893320 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.h
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h
@@ -42,6 +42,7 @@
#include "KX_WorldInfo.h"
#include <vector>
+struct TaskScheduler;
class KX_TimeCategoryLogger;
#define LEFT_EYE 1
@@ -195,6 +196,9 @@ private:
/** Settings that doesn't go away with Game Actuator */
GlobalSettings m_globalsettings;
+ /** Task scheduler for multi-threading */
+ TaskScheduler* m_taskscheduler;
+
void RenderFrame(KX_Scene* scene, KX_Camera* cam);
void PostRenderScene(KX_Scene* scene);
void RenderDebugProperties();
@@ -225,6 +229,8 @@ public:
SCA_IInputDevice* GetKeyboardDevice() { return m_keyboarddevice; }
SCA_IInputDevice* GetMouseDevice() { return m_mousedevice; }
+ TaskScheduler* GetTaskScheduler() { return m_taskscheduler; }
+
/// Dome functions
void InitDome(short res, short mode, short angle, float resbuf, short tilt, struct Text* text);
void EndDome();
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index a9ac13c755f..fbd9eeba8ed 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -102,6 +102,8 @@
#include <stdio.h>
+#include "BLI_task.h"
+
static void *KX_SceneReplicationFunc(SG_IObject* node,void* gameobj,void* scene)
{
KX_GameObject* replica = ((KX_Scene*)scene)->AddNodeReplicaObject(node,(KX_GameObject*)gameobj);
@@ -1196,7 +1198,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj, bool use_gfx, bool u
static_cast<BL_ArmatureObject*>( parentobj )
);
releaseParent= false;
- modifierDeformer->LoadShapeDrivers(blendobj->parent);
+ modifierDeformer->LoadShapeDrivers(parentobj);
}
else
{
@@ -1224,7 +1226,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj, bool use_gfx, bool u
static_cast<BL_ArmatureObject*>( parentobj )
);
releaseParent= false;
- shapeDeformer->LoadShapeDrivers(blendobj->parent);
+ shapeDeformer->LoadShapeDrivers(parentobj);
}
else
{
@@ -1596,52 +1598,74 @@ void KX_Scene::AddAnimatedObject(CValue* gameobj)
m_animatedlist->Add(gameobj);
}
-void KX_Scene::UpdateAnimations(double curtime)
+static void update_anim_thread_func(TaskPool *pool, void *taskdata, int UNUSED(threadid))
{
- KX_GameObject *gameobj;
+ KX_GameObject *gameobj, *child;
+ CListValue *children;
bool needs_update;
+ double curtime = *(double*)BLI_task_pool_userdata(pool);
- for (int i=0; i<m_animatedlist->GetCount(); ++i) {
- gameobj = (KX_GameObject*)m_animatedlist->GetValue(i);
-
- // Non-armature updates are fast enough, so just update them
- needs_update = gameobj->GetGameObjectType() != SCA_IObject::OBJ_ARMATURE;
+ gameobj = (KX_GameObject*)taskdata;
- if (!needs_update) {
- // If we got here, we're looking to update an armature, so check its children meshes
- // to see if we need to bother with a more expensive pose update
- CListValue *children = gameobj->GetChildren();
- KX_GameObject *child;
+ // Non-armature updates are fast enough, so just update them
+ needs_update = gameobj->GetGameObjectType() != SCA_IObject::OBJ_ARMATURE;
- bool has_mesh = false, has_non_mesh = false;
+ if (!needs_update) {
+ // If we got here, we're looking to update an armature, so check its children meshes
+ // to see if we need to bother with a more expensive pose update
+ children = gameobj->GetChildren();
- // Check for meshes that haven't been culled
- for (int j=0; j<children->GetCount(); ++j) {
- child = (KX_GameObject*)children->GetValue(j);
+ bool has_mesh = false, has_non_mesh = false;
- if (!child->GetCulled()) {
- needs_update = true;
- break;
- }
+ // Check for meshes that haven't been culled
+ for (int j=0; j<children->GetCount(); ++j) {
+ child = (KX_GameObject*)children->GetValue(j);
- if (child->GetMeshCount() == 0)
- has_non_mesh = true;
- else
- has_mesh = true;
+ if (!child->GetCulled()) {
+ needs_update = true;
+ break;
}
- // If we didn't find a non-culled mesh, check to see
- // if we even have any meshes, and update if this
- // armature has only non-mesh children.
- if (!needs_update && !has_mesh && has_non_mesh)
- needs_update = true;
+ if (child->GetMeshCount() == 0)
+ has_non_mesh = true;
+ else
+ has_mesh = true;
+ }
+
+ // If we didn't find a non-culled mesh, check to see
+ // if we even have any meshes, and update if this
+ // armature has only non-mesh children.
+ if (!needs_update && !has_mesh && has_non_mesh)
+ needs_update = true;
- children->Release();
+ children->Release();
+ }
+
+ if (needs_update) {
+ gameobj->UpdateActionManager(curtime);
+ children = gameobj->GetChildren();
+
+ for (int j=0; j<children->GetCount(); ++j) {
+ child = (KX_GameObject*)children->GetValue(j);
+
+ if (child->GetDeformer())
+ child->GetDeformer()->Update();
}
- if (needs_update)
- gameobj->UpdateActionManager(curtime);
+ children->Release();
+ }
+}
+
+void KX_Scene::UpdateAnimations(double curtime)
+{
+ TaskPool *pool = BLI_task_pool_create(KX_GetActiveEngine()->GetTaskScheduler(), &curtime);
+
+ for (int i=0; i<m_animatedlist->GetCount(); ++i) {
+ BLI_task_pool_push(pool, update_anim_thread_func, m_animatedlist->GetValue(i), false, TASK_PRIORITY_LOW);
}
+
+ BLI_task_pool_work_and_wait(pool);
+ BLI_task_pool_free(pool);
}
void KX_Scene::LogicUpdateFrame(double curtime, bool frame)