[Bf-blender-cvs] [fe05f97] master: BGE: Multi-threading animation updates and skinning.

Mitchell Stokes noreply at git.blender.org
Mon Apr 7 01:46:23 CEST 2014


Commit: fe05f97841c0ee3e2a6e15f2252ad160fefc3509
Author: Mitchell Stokes
Date:   Sun Apr 6 16:30:59 2014 -0700
https://developer.blender.org/rBfe05f97841c0ee3e2a6e15f2252ad160fefc3509

BGE: Multi-threading animation updates and skinning.

This required BL_ArmatureObject to have tighter control over armatures and poses.
Also, (Blender) armature objects are now copied instead of shared between
BL_ArmatureObjects to avoid race conditions. Also, due to the armature copy,
shape key drivers need a bit of extra fiddling to get the correct armature copy.

Initially OpenMP was used for threading, but then BLI_task was used due to being
less compiler dependent.

This commit also places time spent on skinning updates in the Animation
profiler category (was previously under the Rasterizer category).

===================================================================

M	source/gameengine/Converter/BL_ActionActuator.cpp
M	source/gameengine/Converter/BL_ActionActuator.h
M	source/gameengine/Converter/BL_ArmatureActuator.cpp
M	source/gameengine/Converter/BL_ArmatureObject.cpp
M	source/gameengine/Converter/BL_ArmatureObject.h
M	source/gameengine/Converter/BL_BlenderDataConversion.cpp
M	source/gameengine/Converter/BL_ShapeDeformer.cpp
M	source/gameengine/Converter/BL_ShapeDeformer.h
M	source/gameengine/Converter/BL_SkinDeformer.cpp
M	source/gameengine/Ketsji/BL_Action.cpp
M	source/gameengine/Ketsji/BL_Action.h
M	source/gameengine/Ketsji/KX_KetsjiEngine.cpp
M	source/gameengine/Ketsji/KX_KetsjiEngine.h
M	source/gameengine/Ketsji/KX_Scene.cpp

===================================================================

diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp
index a289062..34d3684 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 4579a21..f488b0c 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 f0c4b3d..e38cb6e 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 619797a..3eb7829 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 8138835..691e73d 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

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list