Revision: 32750
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=32750
Author:   campbellbarton
Date:     2010-10-28 12:12:57 +0200 (Thu, 28 Oct 2010)

Log Message:
-----------
partial bugfix [#24425] Blender 2.54 Beta crashes when starting rendering
Fix for one of the causes of crashing.
Applying armature deform wasn't thread safe since the pose bones had deform 
data written into them when deforming a mesh.

This fixes crashing immediately, on every render for me but blender still 
crashes calculating the subsurf sometimes.

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/intern/armature.c
    trunk/blender/source/blender/makesdna/DNA_action_types.h

Modified: trunk/blender/source/blender/blenkernel/intern/armature.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/armature.c   2010-10-28 
08:48:28 UTC (rev 32749)
+++ trunk/blender/source/blender/blenkernel/intern/armature.c   2010-10-28 
10:12:57 UTC (rev 32750)
@@ -577,7 +577,13 @@
 
 /* ************ Armature Deform ******************* */
 
-static void pchan_b_bone_defmats(bPoseChannel *pchan, int use_quaternion)
+typedef struct bPoseChanDeform {
+       Mat4            *b_bone_mats;   
+       DualQuat        *dual_quat;
+       DualQuat        *b_bone_dual_quats;
+} 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);
@@ -589,11 +595,11 @@
        
        /* allocate b_bone matrices and dual quats */
        b_bone_mats= MEM_mallocN((1+bone->segments)*sizeof(Mat4), "BBone 
defmats");
-       pchan->b_bone_mats= b_bone_mats;
+       pdef_info->b_bone_mats= b_bone_mats;
 
        if(use_quaternion) {
                b_bone_dual_quats= 
MEM_mallocN((bone->segments)*sizeof(DualQuat), "BBone dqs");
-               pchan->b_bone_dual_quats= b_bone_dual_quats;
+               pdef_info->b_bone_dual_quats= b_bone_dual_quats;
        }
        
        /* first matrix is the inverse arm_mat, to bring points in local bone 
space
@@ -618,9 +624,9 @@
        }
 }
 
-static void b_bone_deform(bPoseChannel *pchan, Bone *bone, float *co, DualQuat 
*dq, float defmat[][3])
+static void b_bone_deform(bPoseChanDeform *pdef_info, Bone *bone, float *co, 
DualQuat *dq, float defmat[][3])
 {
-       Mat4 *b_bone= pchan->b_bone_mats;
+       Mat4 *b_bone= pdef_info->b_bone_mats;
        float (*mat)[4]= b_bone[0].mat;
        float segment, y;
        int a;
@@ -637,7 +643,7 @@
        CLAMP(a, 0, bone->segments-1);
 
        if(dq) {
-               copy_dq_dq(dq, &((DualQuat*)pchan->b_bone_dual_quats)[a]);
+               copy_dq_dq(dq, &(pdef_info->b_bone_dual_quats)[a]);
        }
        else {
                mul_m4_v3(b_bone[a+1].mat, co);
@@ -711,7 +717,7 @@
        add_m3_m3m3(mat, mat, wmat);
 }
 
-static float dist_bone_deform(bPoseChannel *pchan, float *vec, DualQuat *dq, 
float mat[][3], float *co)
+static float dist_bone_deform(bPoseChannel *pchan, bPoseChanDeform *pdef_info, 
float *vec, DualQuat *dq, float mat[][3], float *co)
 {
        Bone *bone= pchan->bone;
        float fac, contrib=0.0;
@@ -732,7 +738,7 @@
                        if(vec) {
                                if(bone->segments>1)
                                        // applies on cop and bbonemat
-                                       b_bone_deform(pchan, bone, cop, NULL, 
(mat)?bbonemat:NULL);
+                                       b_bone_deform(pdef_info, bone, cop, 
NULL, (mat)?bbonemat:NULL);
                                else
                                        mul_m4_v3(pchan->chan_mat, cop);
 
@@ -745,11 +751,11 @@
                        }
                        else {
                                if(bone->segments>1) {
-                                       b_bone_deform(pchan, bone, cop, 
&bbonedq, NULL);
+                                       b_bone_deform(pdef_info, bone, cop, 
&bbonedq, NULL);
                                        add_weighted_dq_dq(dq, &bbonedq, fac);
                                }
                                else
-                                       add_weighted_dq_dq(dq, 
pchan->dual_quat, fac);
+                                       add_weighted_dq_dq(dq, 
pdef_info->dual_quat, fac);
                        }
                }
        }
@@ -757,7 +763,7 @@
        return contrib;
 }
 
-static void pchan_bone_deform(bPoseChannel *pchan, float weight, float *vec, 
DualQuat *dq, float mat[][3], float *co, float *contrib)
+static void pchan_bone_deform(bPoseChannel *pchan, bPoseChanDeform *pdef_info, 
float weight, float *vec, DualQuat *dq, float mat[][3], float *co, float 
*contrib)
 {
        float cop[3], bbonemat[3][3];
        DualQuat bbonedq;
@@ -770,7 +776,7 @@
        if(vec) {
                if(pchan->bone->segments>1)
                        // applies on cop and bbonemat
-                       b_bone_deform(pchan, pchan->bone, cop, NULL, 
(mat)?bbonemat:NULL);
+                       b_bone_deform(pdef_info, pchan->bone, cop, NULL, 
(mat)?bbonemat:NULL);
                else
                        mul_m4_v3(pchan->chan_mat, cop);
                
@@ -783,11 +789,11 @@
        }
        else {
                if(pchan->bone->segments>1) {
-                       b_bone_deform(pchan, pchan->bone, cop, &bbonedq, NULL);
+                       b_bone_deform(pdef_info, pchan->bone, cop, &bbonedq, 
NULL);
                        add_weighted_dq_dq(dq, &bbonedq, weight);
                }
                else
-                       add_weighted_dq_dq(dq, pchan->dual_quat, weight);
+                       add_weighted_dq_dq(dq, pdef_info->dual_quat, weight);
        }
 
        (*contrib)+=weight;
@@ -798,8 +804,11 @@
                                                   int numVerts, int 
deformflag, 
                                                   float (*prevCos)[3], const 
char *defgrp_name)
 {
+       bPoseChanDeform *pdef_info_array;
+       bPoseChanDeform *pdef_info= NULL;
        bArmature *arm= armOb->data;
        bPoseChannel *pchan, **defnrToPC = NULL;
+       int *defnrToPCIndex= NULL;
        MDeformVert *dverts = NULL;
        bDeformGroup *dg;
        DualQuat *dualquats= NULL;
@@ -823,20 +832,24 @@
        /* bone defmats are already in the channels, chan_mat */
        
        /* initialize B_bone matrices and dual quaternions */
+       totchan= BLI_countlist(&armOb->pose->chanbase);
+
        if(use_quaternion) {
-               totchan= BLI_countlist(&armOb->pose->chanbase);
                dualquats= MEM_callocN(sizeof(DualQuat)*totchan, "dualquats");
        }
+       
+       pdef_info_array= MEM_callocN(sizeof(bPoseChanDeform)*totchan, 
"bPoseChanDeform");
 
        totchan= 0;
-       for(pchan = armOb->pose->chanbase.first; pchan; pchan = pchan->next) {
+       pdef_info= pdef_info_array;
+       for(pchan= armOb->pose->chanbase.first; pchan; pchan= pchan->next, 
pdef_info++) {
                if(!(pchan->bone->flag & BONE_NO_DEFORM)) {
                        if(pchan->bone->segments > 1)
-                               pchan_b_bone_defmats(pchan, use_quaternion);
+                               pchan_b_bone_defmats(pchan, pdef_info, 
use_quaternion);
 
                        if(use_quaternion) {
-                               pchan->dual_quat= &dualquats[totchan++];
-                               mat4_to_dquat( 
pchan->dual_quat,pchan->bone->arm_mat, pchan->chan_mat);
+                               pdef_info->dual_quat= &dualquats[totchan++];
+                               mat4_to_dquat( 
pdef_info->dual_quat,pchan->bone->arm_mat, pchan->chan_mat);
                        }
                }
        }
@@ -872,15 +885,19 @@
                        else if(dverts) use_dverts = 1;
 
                        if(use_dverts) {
-                               defnrToPC = MEM_callocN(sizeof(*defnrToPC) * 
numGroups,
-                                                                               
"defnrToBone");
+                               defnrToPC = MEM_callocN(sizeof(*defnrToPC) * 
numGroups, "defnrToBone");
+                               defnrToPCIndex = 
MEM_callocN(sizeof(*defnrToPCIndex) * numGroups, "defnrToIndex");
                                for(i = 0, dg = target->defbase.first; dg;
                                        i++, dg = dg->next) {
                                        defnrToPC[i] = 
get_pose_channel(armOb->pose, dg->name);
                                        /* exclude non-deforming bones */
                                        if(defnrToPC[i]) {
-                                               if(defnrToPC[i]->bone->flag & 
BONE_NO_DEFORM)
+                                               if(defnrToPC[i]->bone->flag & 
BONE_NO_DEFORM) {
                                                        defnrToPC[i]= NULL;
+                                               }
+                                               else {
+                                                       defnrToPCIndex[i]= 
BLI_findindex(&armOb->pose->chanbase, defnrToPC[i]);
+                                               }
                                        }
                                }
                        }
@@ -951,10 +968,10 @@
                        
                        for(j = 0; j < dvert->totweight; j++){
                                int index = dvert->dw[j].def_nr;
-                               pchan = index < numGroups?defnrToPC[index]:NULL;
-                               if(pchan) {
+                               if(index < numGroups && (pchan= 
defnrToPC[index])) {
                                        float weight = dvert->dw[j].weight;
-                                       Bone *bone = pchan->bone;
+                                       Bone *bone= pchan->bone;
+                                       pdef_info= pdef_info_array + 
defnrToPCIndex[index];
 
                                        deformed = 1;
                                        
@@ -965,25 +982,27 @@
                                                                                
                         bone->rad_tail,
                                                                                
                         bone->dist);
                                        }
-                                       pchan_bone_deform(pchan, weight, vec, 
dq, smat, co, &contrib);
+                                       pchan_bone_deform(pchan, pdef_info, 
weight, vec, dq, smat, co, &contrib);
                                }
                        }
                        /* if there are vertexgroups but not groups with bones
                         * (like for softbody groups)
                         */
                        if(deformed == 0 && use_envelope) {
-                               for(pchan = armOb->pose->chanbase.first; pchan;
-                                       pchan = pchan->next) {
+                               pdef_info= pdef_info_array;
+                               for(pchan= armOb->pose->chanbase.first; pchan;
+                                       pchan= pchan->next, pdef_info++) {
                                        if(!(pchan->bone->flag & 
BONE_NO_DEFORM))
-                                               contrib += 
dist_bone_deform(pchan, vec, dq, smat, co);
+                                               contrib += 
dist_bone_deform(pchan, pdef_info, vec, dq, smat, co);
                                }
                        }
                }
                else if(use_envelope) {
+                       pdef_info= pdef_info_array;
                        for(pchan = armOb->pose->chanbase.first; pchan;
-                               pchan = pchan->next) {
+                               pchan = pchan->next, pdef_info++) {
                                if(!(pchan->bone->flag & BONE_NO_DEFORM))
-                                       contrib += dist_bone_deform(pchan, vec, 
dq, smat, co);
+                                       contrib += dist_bone_deform(pchan, 
pdef_info, vec, dq, smat, co);
                        }
                }
 
@@ -1039,20 +1058,20 @@
 
        if(dualquats) MEM_freeN(dualquats);
        if(defnrToPC) MEM_freeN(defnrToPC);
-       
+       if(defnrToPCIndex) MEM_freeN(defnrToPCIndex);
+
        /* free B_bone matrices */
-       for(pchan = armOb->pose->chanbase.first; pchan; pchan = pchan->next) {
-               if(pchan->b_bone_mats) {
-                       MEM_freeN(pchan->b_bone_mats);
-                       pchan->b_bone_mats = NULL;
+       pdef_info= pdef_info_array;
+       for(pchan = armOb->pose->chanbase.first; pchan; pchan = pchan->next, 
pdef_info++) {
+               if(pdef_info->b_bone_mats) {
+                       MEM_freeN(pdef_info->b_bone_mats);
                }
-               if(pchan->b_bone_dual_quats) {
-                       MEM_freeN(pchan->b_bone_dual_quats);
-                       pchan->b_bone_dual_quats = NULL;
+               if(pdef_info->b_bone_dual_quats) {
+                       MEM_freeN(pdef_info->b_bone_dual_quats);
                }
+       }
 
-               pchan->dual_quat = NULL;
-       }
+       MEM_freeN(pdef_info_array);
 }
 
 /* ************ END Armature Deform ******************* */

Modified: trunk/blender/source/blender/makesdna/DNA_action_types.h
===================================================================
--- trunk/blender/source/blender/makesdna/DNA_action_types.h    2010-10-28 
08:48:28 UTC (rev 32749)
+++ trunk/blender/source/blender/makesdna/DNA_action_types.h    2010-10-28 
10:12:57 UTC (rev 32750)
@@ -203,12 +203,10 @@
        struct bPoseChannel *child;             /* set on read file or rebuild 
pose, the 'ik' child, for b-bones */
        struct ListBase          iktree;                /* only while 
evaluating pose */
        
-       /* only while deform, stores precalculated b_bone deform mats,
-          dual quaternions */
-       void                            *b_bone_mats;   
-       void                            *dual_quat;
-       void                            *b_bone_dual_quats;
-       
+       bMotionPath *mpath;                             /* motion path cache 
for this bone */
+       struct Object *custom;                  /* draws custom object instead 
of default bone shape */
+       struct bPoseChannel *custom_tx; /* odd feature, display with another 
bones transform. needed in rare cases for advanced rigs, since the alternative 
is highly complicated - campbell */
+
                /* transforms - written in by actions or transform */
        float           loc[3];                         
        float           size[3];
@@ -234,9 +232,6 @@
        float           iklinweight;            /* weight of joint stretch 
constraint */
 
        float           *path;                          /* totpath x 3 x float 
*/               // XXX depreceated... old animation system (armature only viz)
-       bMotionPath *mpath;                             /* motion path cache 
for this bone */
-       struct Object *custom;                  /* draws custom object instead 
of default bone shape */
-       struct bPoseChannel *custom_tx; /* odd feature, display with another 
bones transform. needed in rare cases for advanced rigs, since the alternative 
is highly complicated - campbell */
 } bPoseChannel;
 
 


_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to