partial bugfix [#24425] Blender 2.54 Beta crashes when starting rendering
authorCampbell Barton <ideasman42@gmail.com>
Thu, 28 Oct 2010 10:12:57 +0000 (10:12 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Thu, 28 Oct 2010 10:12:57 +0000 (10:12 +0000)
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.

source/blender/blenkernel/intern/armature.c
source/blender/makesdna/DNA_action_types.h

index b44bf75..3bec79e 100644 (file)
@@ -577,7 +577,13 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest)
 
 /* ************ 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 @@ static void pchan_b_bone_defmats(bPoseChannel *pchan, int use_quaternion)
        
        /* 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 pchan_b_bone_defmats(bPoseChannel *pchan, int use_quaternion)
        }
 }
 
-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 @@ static void b_bone_deform(bPoseChannel *pchan, Bone *bone, float *co, DualQuat *
        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 @@ static void pchan_deform_mat_add(bPoseChannel *pchan, float weight, float bbonem
        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 @@ static float dist_bone_deform(bPoseChannel *pchan, float *vec, DualQuat *dq, flo
                        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 @@ static float dist_bone_deform(bPoseChannel *pchan, float *vec, DualQuat *dq, flo
                        }
                        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 @@ static float dist_bone_deform(bPoseChannel *pchan, float *vec, DualQuat *dq, flo
        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 @@ static void pchan_bone_deform(bPoseChannel *pchan, float weight, float *vec, Dua
        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 @@ static void pchan_bone_deform(bPoseChannel *pchan, float weight, float *vec, Dua
        }
        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 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm,
                                                   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 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm,
        /* 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 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm,
                        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 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm,
                        
                        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 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm,
                                                                                                         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 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm,
 
        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 ******************* */
index f7bbf92..6f6e497 100644 (file)
@@ -203,12 +203,10 @@ typedef struct bPoseChannel {
        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 @@ typedef struct bPoseChannel {
        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;