diff options
author | Ton Roosendaal <ton@blender.org> | 2005-08-21 15:26:53 +0400 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2005-08-21 15:26:53 +0400 |
commit | 9a105042fc468a4c6dc7a3e4a72fe6c9826ec02d (patch) | |
tree | a564871786b853673dbc9fe2b59e8c028e7063f0 /source | |
parent | 4d58808512d2e92afd1d4822a494a40f5ca916a3 (diff) |
At last! B-bones now deform. :)
This works pretty nice for better control over the curvature of any bone
deform. No need to give Bones (vgroups) large influence, just add a coupleof B-bone segments.
Two notes;
- The Bone property "Segments" defines if a deform happens as a 'B-bone'.
The drawtype B-bone is just for display in 3d window.
- A B-bone also deforms (bends) in Rest-position, if there's a joint that
creates a curved Bone. Therefore, best results you get by creating a
rest-position with straight joints. Or, if you prefer a slightly bended
restposition (for a spine or so), make sure the Mesh model is *not*
curved, the B-bone will do this for you.
Also added: proper events on changing buttons for Bones, like "Segm" or
"Dist" etc.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_armature.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/armature.c | 93 | ||||
-rw-r--r-- | source/blender/include/butspace.h | 4 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_action_types.h | 1 | ||||
-rw-r--r-- | source/blender/src/butspace.c | 3 | ||||
-rw-r--r-- | source/blender/src/buttons_editing.c | 48 |
6 files changed, 99 insertions, 51 deletions
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 9c674971bbf..d177edfce09 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -74,7 +74,6 @@ void make_local_armature(struct bArmature *arm); struct bArmature *copy_armature(struct bArmature *arm); void bone_flip_name (char *name, int strip_number); -void init_armature_deform(struct Object *parent, struct Object *ob); struct bArmature* get_armature (struct Object* ob); struct Bone *get_named_bone (struct bArmature *arm, const char *name); diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index ec1ad7548b1..27e06590670 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -69,11 +69,6 @@ #include <config.h> #endif -/* ugly Globals */ -static float g_premat[4][4]; -static float g_postmat[4][4]; -static Object *g_deform; - /* **************** Generic Functions, data level *************** */ bArmature *get_armature(Object *ob) @@ -421,7 +416,7 @@ 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 pchan pose_mat space */ +/* this calculation is done within unit bone space */ Mat4 *b_bone_spline_setup(bPoseChannel *pchan) { static Mat4 bbone_array[MAX_BBONE_SUBDIV]; @@ -517,24 +512,44 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan) /* ************ Armature Deform ******************* */ -void init_armature_deform(Object *parent, Object *ob) +static void pchan_b_bone_defmats(bPoseChannel *pchan) { - bArmature *arm; - float obinv[4][4]; - - arm = get_armature(parent); - if (!arm) - return; - - g_deform = parent; - - Mat4Invert(obinv, ob->obmat); - Mat4CpyMat4(g_premat, ob->obmat); - Mat4MulMat4(g_postmat, parent->obmat, obinv); + Bone *bone= pchan->bone; + Mat4 *b_bone= b_bone_spline_setup(pchan); + Mat4 *b_bone_mats; + int a; + + pchan->b_bone_mats=b_bone_mats= MEM_mallocN((1+bone->segments)*sizeof(Mat4), "BBone defmats"); + + /* first matrix is the inverse arm_mat, to bring points in local bone space */ + Mat4Invert(b_bone_mats[0].mat, bone->arm_mat); + + /* then we multiply the bbone_mats with arm_mat */ + for(a=0; a<bone->segments; a++) { + Mat4MulMat4(b_bone_mats[a+1].mat, b_bone[a].mat, bone->arm_mat); + } +} - Mat4Invert (g_premat, g_postmat); +static void b_bone_deform(bPoseChannel *pchan, Bone *bone, float *defpos) +{ + Mat4 *b_bone= pchan->b_bone_mats; + float segment; + int a; + + /* need to transform defpos back to bonespace */ + Mat4MulVecfl(b_bone[0].mat, defpos); + + /* now calculate which of the b_bones are deforming this */ + segment= bone->length/((float)bone->segments); + a= (int) (defpos[1]/segment); + + /* note; by clamping it extends deform at endpoints, goes best with straight joints in restpos. */ + CLAMP(a, 0, bone->segments-1); - /* bone defmats are already in the channels, chan_mat */ + /* since the bbone mats translate from (0.0.0) on the curve, we subtract */ + defpos[1] -= ((float)a)*segment; + + Mat4MulVecfl(b_bone[a+1].mat, defpos); } /* using vec with dist to bone b1 - b2 */ @@ -609,6 +624,9 @@ static float dist_bone_deform(bPoseChannel *pchan, float *vec, float *co) VECCOPY (cop, co); + if(bone->segments>1) + b_bone_deform(pchan, bone, cop); // applies on cop + Mat4MulVecfl(pchan->chan_mat, cop); VecSubf (cop, cop, co); // Make this a delta from the base position @@ -629,6 +647,9 @@ static void pchan_bone_deform(bPoseChannel *pchan, float weight, float *vec, flo VECCOPY (cop, co); + if(pchan->bone->segments>1) + b_bone_deform(pchan, pchan->bone, cop); // applies on cop + Mat4MulVecfl(pchan->chan_mat, cop); vec[0]+=(cop[0]-co[0])*weight; @@ -640,7 +661,7 @@ static void pchan_bone_deform(bPoseChannel *pchan, float weight, float *vec, flo void armature_deform_verts(Object *armOb, Object *target, float (*vertexCos)[3], int numVerts) { - bPoseChannel **defnrToPC = NULL; + bPoseChannel *pchan, **defnrToPC = NULL; MDeformVert *dverts; float obinv[4][4], premat[4][4], postmat[4][4]; int i; @@ -651,7 +672,14 @@ void armature_deform_verts(Object *armOb, Object *target, float (*vertexCos)[3], Mat4Invert(premat, postmat); - /* bone defmats are already in the channels, chan_mat */ + /* bone defmats are already in the channels, chan_mat */ + + /* initialize B_bone matrices */ + for(pchan= armOb->pose->chanbase.first; pchan; pchan= pchan->next) { + //if(pchan->bone->boneclass==BONE_SKINNABLE) // not yet... for vgroups this is ignored + if(pchan->bone->segments>1) + pchan_b_bone_defmats(pchan); + } if (target->type==OB_MESH){ int numGroups = BLI_countlist(&target->defbase); @@ -670,7 +698,6 @@ void armature_deform_verts(Object *armOb, Object *target, float (*vertexCos)[3], } for(i=0; i<numVerts; i++) { - bPoseChannel *pchan; float *co = vertexCos[i]; float vec[3]; float contrib=0.0; @@ -686,7 +713,8 @@ void armature_deform_verts(Object *armOb, Object *target, float (*vertexCos)[3], for (j=0; j<dvert->totweight; j++){ pchan = defnrToPC[dvert->dw[j].def_nr]; - if (pchan) pchan_bone_deform(pchan, dvert->dw[j].weight, vec, co, &contrib); + if (pchan) + pchan_bone_deform(pchan, dvert->dw[j].weight, vec, co, &contrib); } } else { @@ -707,6 +735,15 @@ void armature_deform_verts(Object *armOb, Object *target, float (*vertexCos)[3], } if (defnrToPC) MEM_freeN(defnrToPC); + + /* 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; + } + } + } /* ************ END Armature Deform ******************* */ @@ -1300,6 +1337,12 @@ void where_is_pose (Object *ob) /* ****************** Game Blender functions, called by engine ************** */ +/* NOTE: doesn't work at the moment!!! (ton) */ + +/* ugly Globals */ +static float g_premat[4][4]; +static float g_postmat[4][4]; + void GB_build_mats (float parmat[][4], float obmat[][4], float premat[][4], float postmat[][4]) { float obinv[4][4]; diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index f3a4b4cad4c..4a87125f504 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -78,6 +78,8 @@ extern void do_mballbuts(unsigned short event); extern void do_latticebuts(unsigned short event); extern void do_fpaintbuts(unsigned short event); extern void do_cambuts(unsigned short event); +extern void do_armbuts(unsigned short event); + extern char *get_vertexgroup_menustr(struct Object *ob); // used in object buttons /* shading */ @@ -404,7 +406,9 @@ enum { #define B_STYLETOSEL 2212 /* *********************** */ +#define B_ARMBUTS 2400 +#define B_ARM_RECALCDATA 2301 /* *********************** */ #define B_CAMBUTS 2500 diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 7a5d7520fca..844b1d638fe 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -53,6 +53,7 @@ typedef struct bPoseChannel { struct bPoseChannel *parent; /* set on read file or rebuild pose */ struct bPoseChannel *child; /* set on read file or rebuild pose, the 'ik' child, for b-bones */ struct ListBase chain; /* only while evaluating pose */ + void *b_bone_mats; /* only while deform, stores precalculated b_bone deform mats */ float loc[3]; /* written in by actions or transform */ float size[3]; diff --git a/source/blender/src/butspace.c b/source/blender/src/butspace.c index bee0798ee10..d9c7b7684e4 100644 --- a/source/blender/src/butspace.c +++ b/source/blender/src/butspace.c @@ -287,6 +287,9 @@ void do_butspace(unsigned short event) else if(event<=B_FONTBUTS) { do_fontbuts(event); } + else if(event<=B_ARMBUTS) { + do_armbuts(event); + } else if(event<=B_CAMBUTS) { do_cambuts(event); } diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 7d68f1bec8a..9a8b9149053 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -2042,7 +2042,14 @@ static void editing_panel_lattice_type(Object *ob, Lattice *lt) /* *************************** ARMATURE ******************************** */ - +void do_armbuts(unsigned short event) +{ + switch(event) { + case B_ARM_RECALCDATA: + DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA); + allqueue(REDRAWVIEW3D, 1); + } +} static int editbone_to_parnr (EditBone *bone) { @@ -2161,25 +2168,17 @@ static void validate_posebonebutton_cb(void *bonev, void *namev) allqueue(REDRAWALL, 0); } -static void armature_recalc_func(void *obp, void *pointer2) -{ - Object *ob= obp; - - DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); -} - static void editing_panel_armature_type(Object *ob, bArmature *arm) { uiBlock *block; - uiBut *but; block= uiNewBlock(&curarea->uiblocks, "editing_panel_armature_type", UI_EMBOSS, UI_HELV, curarea->win); if(uiNewPanel(curarea, block, "Armature", "Editing", 320, 0, 318, 204)==0) return; uiBlockBeginAlign(block); - but = uiDefButBitI(block, TOG, ARM_RESTPOS, REDRAWVIEW3D, + uiDefButBitI(block, TOG, ARM_RESTPOS, B_ARM_RECALCDATA, "Rest Position", 10,180,150,20, &arm->flag, 0, 0, 0, 0, "Disable all animation for this object"); - uiButSetFunc(but, armature_recalc_func, ob, NULL); + uiDefButBitI(block, TOG, ARM_DELAYDEFORM, REDRAWVIEW3D, "Delay Deform", 160, 180,150,20, &arm->flag, 0, 0, 0, 0, "Don't deform children when manipulating bones in pose mode"); uiBlockBeginAlign(block); uiDefButI(block, ROW, REDRAWVIEW3D, "Octahedron", 10, 140,75,20, &arm->drawtype, 0, ARM_OCTA, 0, 0, "Draw bones as octahedra"); @@ -2238,19 +2237,19 @@ static void editing_panel_armature_bones(Object *ob, bArmature *arm) /* IK to parent flag */ if (curBone->parent){ - but=uiDefButBitI(block, TOG, BONE_IK_TOPARENT, REDRAWVIEW3D, "IK", bx+300,by,32,18, &curBone->flag, 0.0, 0.0, 0.0, 0.0, "IK link to parent"); + but=uiDefButBitI(block, TOG, BONE_IK_TOPARENT, B_ARM_RECALCDATA, "IK", bx+300,by,32,18, &curBone->flag, 0.0, 0.0, 0.0, 0.0, "IK link to parent"); uiButSetFunc(but, attach_bone_to_parent_cb, curBone, NULL); } /* Segment, dist and weight buttons */ uiBlockBeginAlign(block); - uiDefButS(block, NUM, REDRAWVIEW3D, "Segm: ", bx-10,by-19,117,18, &curBone->segments, 1.0, 32.0, 0.0, 0.0, "Subdivisions for B-bones"); - uiDefButF(block, NUM,REDRAWVIEW3D, "Dist:", bx+110, by-19, 105, 18, &curBone->dist, 0.0, 1000.0, 10.0, 0.0, "Bone deformation distance"); - uiDefButF(block, NUM,REDRAWVIEW3D, "Weight:", bx+223, by-19,110, 18, &curBone->weight, 0.0F, 1000.0F, 10.0F, 0.0F, "Bone deformation weight"); + uiDefButS(block, NUM, B_ARM_RECALCDATA, "Segm: ", bx-10,by-19,117,18, &curBone->segments, 1.0, 32.0, 0.0, 0.0, "Subdivisions for B-bones"); + uiDefButF(block, NUM,B_ARM_RECALCDATA, "Dist:", bx+110, by-19, 105, 18, &curBone->dist, 0.0, 1000.0, 10.0, 0.0, "Bone deformation distance"); + uiDefButF(block, NUM,B_ARM_RECALCDATA, "Weight:", bx+223, by-19,110, 18, &curBone->weight, 0.0F, 1000.0F, 10.0F, 0.0F, "Bone deformation weight"); /* bone types */ - uiDefButBitI(block, TOG, BONE_HINGE, REDRAWVIEW3D, "Hinge", bx-10,by-38,117,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit rotation or scale from parent Bone"); - uiDefButBitS(block, TOGN, 1,REDRAWVIEW3D, "Skinnable", bx+110, by-38, 105, 18, &curBone->boneclass, 0.0, 0.0, 0.0, 0.0, "Indicate if Bone is included in automatic creation of vertex groups"); + uiDefButBitI(block, TOG, BONE_HINGE, B_ARM_RECALCDATA, "Hinge", bx-10,by-38,117,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit rotation or scale from parent Bone"); + uiDefButBitS(block, TOGN, 1,B_ARM_RECALCDATA, "Skinnable", bx+110, by-38, 105, 18, &curBone->boneclass, 0.0, 0.0, 0.0, 0.0, "Indicate if Bone is included in automatic creation of vertex groups"); /* Hide in posemode flag */ uiDefButBitI(block, TOG, BONE_HIDDEN_A, REDRAWVIEW3D, "Hide", bx+223,by-38,110,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in Edit Mode"); @@ -2297,20 +2296,19 @@ static void editing_panel_pose_bones(Object *ob, bArmature *arm) uiButSetFunc(but, validate_posebonebutton_cb, curBone, NULL); /* Dist and weight buttons */ - uiDefButF(block, NUM,REDRAWVIEW3D, "Dist:", bx+107, by, 105, 18, &curBone->dist, 0.0, 1000.0, 10.0, 0.0, "Bone deformation distance"); - uiDefButF(block, NUM,REDRAWVIEW3D, "Weight:", bx+220, by, 110, 18, &curBone->weight, 0.0F, 1000.0F, 10.0F, 0.0F, "Bone deformation weight"); + uiDefButF(block, NUM,B_ARM_RECALCDATA, "Dist:", bx+107, by, 105, 18, &curBone->dist, 0.0, 1000.0, 10.0, 0.0, "Bone deformation distance"); + uiDefButF(block, NUM,B_ARM_RECALCDATA, "Weight:", bx+220, by, 110, 18, &curBone->weight, 0.0F, 1000.0F, 10.0F, 0.0F, "Bone deformation weight"); /* Segment, ease in/out buttons */ uiBlockBeginAlign(block); - uiDefButS(block, NUM, REDRAWVIEW3D, "Segm: ", bx-10,by-19,117,19, &curBone->segments, 1.0, 32.0, 0.0, 0.0, "Subdivisions for B-bones"); - uiDefButF(block, NUM,REDRAWVIEW3D, "In:", bx+107, by-19,105, 19, &curBone->ease1, 0.0, 2.0, 10.0, 0.0, "First length of Bezier handle"); - uiDefButF(block, NUM,REDRAWVIEW3D, "Out:", bx+220, by-19, 110, 19, &curBone->ease2, 0.0, 2.0, 10.0, 0.0, "Second length of Bezier handle"); + uiDefButS(block, NUM, B_ARM_RECALCDATA, "Segm: ", bx-10,by-19,117,19, &curBone->segments, 1.0, 32.0, 0.0, 0.0, "Subdivisions for B-bones"); + uiDefButF(block, NUM,B_ARM_RECALCDATA, "In:", bx+107, by-19,105, 19, &curBone->ease1, 0.0, 2.0, 10.0, 0.0, "First length of Bezier handle"); + uiDefButF(block, NUM,B_ARM_RECALCDATA, "Out:", bx+220, by-19, 110, 19, &curBone->ease2, 0.0, 2.0, 10.0, 0.0, "Second length of Bezier handle"); /* bone types */ - but= uiDefButBitI(block, TOG, BONE_HINGE, REDRAWVIEW3D, "Hinge", bx-10,by-38,117,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit rotation or scale from parent Bone"); - uiButSetFunc(but, armature_recalc_func, ob, NULL); - uiDefButBitS(block, TOGN, 1,REDRAWVIEW3D, "Skinnable", bx+110, by-38, 105, 18, &curBone->boneclass, 0.0, 0.0, 0.0, 0.0, "Indicate if Bone is included in automatic creation of vertex groups"); + uiDefButBitI(block, TOG, BONE_HINGE, B_ARM_RECALCDATA, "Hinge", bx-10,by-38,117,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit rotation or scale from parent Bone"); + uiDefButBitS(block, TOGN, 1,B_ARM_RECALCDATA, "Skinnable", bx+110, by-38, 105, 18, &curBone->boneclass, 0.0, 0.0, 0.0, 0.0, "Indicate if Bone is included in automatic creation of vertex groups"); /* Hide in posemode flag */ uiDefButBitI(block, TOG, BONE_HIDDEN_P, REDRAWVIEW3D, "Hide", bx+223,by-38,110,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in posemode"); uiBlockEndAlign(block); |