Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorTon Roosendaal <ton@blender.org>2005-08-21 15:26:53 +0400
committerTon Roosendaal <ton@blender.org>2005-08-21 15:26:53 +0400
commit9a105042fc468a4c6dc7a3e4a72fe6c9826ec02d (patch)
treea564871786b853673dbc9fe2b59e8c028e7063f0 /source
parent4d58808512d2e92afd1d4822a494a40f5ca916a3 (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.h1
-rw-r--r--source/blender/blenkernel/intern/armature.c93
-rw-r--r--source/blender/include/butspace.h4
-rw-r--r--source/blender/makesdna/DNA_action_types.h1
-rw-r--r--source/blender/src/butspace.c3
-rw-r--r--source/blender/src/buttons_editing.c48
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);