Made armatures evaluation safe for threading

Apparently, some routines in armature deformation code
were using static arrays. This is probably just an
optimization thing, but it's very bad for threading.

Now made it so bbone matrices array is allocating in
callee function stack. This required exposing
MAX_BBONE_SUBDIV to an external API, This is not so
much crappy from code side, and it shall be the same
fast as before.

--
svn merge -r58278:58279 ^/branches/soc-2013-depsgraph_mt
This commit is contained in:
Sergey Sharybin 2013-08-19 10:14:22 +00:00
parent c46cbc602e
commit 36ffc7accd
4 changed files with 23 additions and 19 deletions

View File

@ -124,11 +124,13 @@ void BKE_pchan_to_pose_mat(struct bPoseChannel *pchan, float rotscale_mat[4][4],
void BKE_rotMode_change_values(float quat[4], float eul[3], float axis[3], float *angle, short oldMode, short newMode);
/* B-Bone support */
#define MAX_BBONE_SUBDIV 32
typedef struct Mat4 {
float mat[4][4];
} Mat4;
Mat4 *b_bone_spline_setup(struct bPoseChannel *pchan, int rest);
void b_bone_spline_setup(struct bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BBONE_SUBDIV]);
/* like EBONE_VISIBLE */
#define PBONE_VISIBLE(arm, bone) ( \

View File

@ -381,8 +381,6 @@ int bone_autoside_name(char name[MAXBONENAME], int UNUSED(strip_number), short a
/* ************* B-Bone support ******************* */
#define MAX_BBONE_SUBDIV 32
/* data has MAX_BBONE_SUBDIV+1 interpolated points, will become desired amount with equal distances */
static void equalize_bezier(float *data, int desired)
{
@ -426,11 +424,8 @@ static void equalize_bezier(float *data, int desired)
/* returns pointer to static array, filled with desired amount of bone->segments elements */
/* this calculation is done within unit bone space */
Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest)
void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BBONE_SUBDIV])
{
static Mat4 bbone_array[MAX_BBONE_SUBDIV];
static Mat4 bbone_rest_array[MAX_BBONE_SUBDIV];
Mat4 *result_array = (rest) ? bbone_rest_array : bbone_array;
bPoseChannel *next, *prev;
Bone *bone = pchan->bone;
float h1[3], h2[3], scale[3], length, hlength1, hlength2, roll1 = 0.0f, roll2;
@ -587,8 +582,6 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest)
mul_serie_m4(result_array[a].mat, iscalemat, result_array[a].mat, scalemat, NULL, NULL, NULL, NULL, NULL);
}
}
return result_array;
}
/* ************ Armature Deform ******************* */
@ -602,13 +595,15 @@ typedef struct bPoseChanDeform {
static void pchan_b_bone_defmats(bPoseChannel *pchan, bPoseChanDeform *pdef_info, int use_quaternion)
{
Bone *bone = pchan->bone;
Mat4 *b_bone = b_bone_spline_setup(pchan, 0);
Mat4 *b_bone_rest = b_bone_spline_setup(pchan, 1);
Mat4 b_bone[MAX_BBONE_SUBDIV], b_bone_rest[MAX_BBONE_SUBDIV];
Mat4 *b_bone_mats;
DualQuat *b_bone_dual_quats = NULL;
float tmat[4][4] = MAT4_UNITY;
int a;
b_bone_spline_setup(pchan, 0, b_bone);
b_bone_spline_setup(pchan, 1, b_bone_rest);
/* allocate b_bone matrices and dual quats */
b_bone_mats = MEM_mallocN((1 + bone->segments) * sizeof(Mat4), "BBone defmats");
pdef_info->b_bone_mats = b_bone_mats;

View File

@ -255,7 +255,7 @@ static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob,
bDeformGroup *dgroup;
bPoseChannel *pchan;
Mesh *mesh;
Mat4 *bbone = NULL;
Mat4 bbone_array[MAX_BBONE_SUBDIV], *bbone = NULL;
float (*root)[3], (*tip)[3], (*verts)[3];
int *selected;
int numbones, vertsfilled = 0, i, j, segments = 0;
@ -309,7 +309,8 @@ static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob,
if ((par->pose) && (pchan = BKE_pose_channel_find_name(par->pose, bone->name))) {
if (bone->segments > 1) {
segments = bone->segments;
bbone = b_bone_spline_setup(pchan, 1);
b_bone_spline_setup(pchan, 1, bbone_array);
bbone = bbone_array;
}
}
}

View File

@ -34,6 +34,7 @@
#include <string.h>
#include <math.h>
#include "MEM_guardedalloc.h"
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
@ -1099,12 +1100,14 @@ static void draw_b_bone_boxes(const short dt, bPoseChannel *pchan, float xwidth,
if ((segments > 1) && (pchan)) {
float dlen = length / (float)segments;
Mat4 *bbone = b_bone_spline_setup(pchan, 0);
Mat4 bbone[MAX_BBONE_SUBDIV];
int a;
for (a = 0; a < segments; a++, bbone++) {
b_bone_spline_setup(pchan, 0, bbone);
for (a = 0; a < segments; a++) {
glPushMatrix();
glMultMatrixf(bbone->mat);
glMultMatrixf(bbone[a].mat);
if (dt == OB_SOLID) drawsolidcube_size(xwidth, dlen, zwidth);
else drawcube_size(xwidth, dlen, zwidth);
glPopMatrix();
@ -1235,6 +1238,7 @@ static void draw_wire_bone_segments(bPoseChannel *pchan, Mat4 *bbones, float len
static void draw_wire_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id,
bPoseChannel *pchan, EditBone *ebone)
{
Mat4 bbones_array[MAX_BBONE_SUBDIV];
Mat4 *bbones = NULL;
int segments = 0;
float length;
@ -1243,8 +1247,10 @@ static void draw_wire_bone(const short dt, int armflag, int boneflag, short cons
segments = pchan->bone->segments;
length = pchan->bone->length;
if (segments > 1)
bbones = b_bone_spline_setup(pchan, 0);
if (segments > 1) {
b_bone_spline_setup(pchan, 0, bbones_array);
bbones = bbones_array;
}
}
else
length = ebone->length;