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:
authorChris Want <cwant@ualberta.ca>2004-01-03 06:53:18 +0300
committerChris Want <cwant@ualberta.ca>2004-01-03 06:53:18 +0300
commitd311e9617468beb507202e4c92017703bc11feb3 (patch)
treed4ab64d160b682e31e55cdd4d827faa0effa9576 /source
parentde21846e690dd5a4606a42b776d55f119e5620d7 (diff)
Armature speed ups, Part III
---------------------------- Another (major) armature speed up for bones with many constraints. When tranform()-ing, figure out which bones need to be recalculated beforehand and only update those bones.
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/intern/armature.c18
-rw-r--r--source/blender/include/BIF_editconstraint.h3
-rw-r--r--source/blender/makesdna/DNA_armature_types.h9
-rw-r--r--source/blender/src/buttons_editing.c11
-rw-r--r--source/blender/src/editconstraint.c60
-rw-r--r--source/blender/src/editobject.c201
6 files changed, 292 insertions, 10 deletions
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index e5f57e2e213..b16d2143edf 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -297,11 +297,6 @@ void where_is_bone1_time (Object *ob, Bone *bone, float ctime)
where_is_bone_time (ob, bone->parent, ctime);
}
- /* Build the parent matrix : Depreciated */
-// if (bone->parent)
-// Mat4MulMat4(bone->parmat, bone->parent->obmat, bone->parent->parmat);
-// else
-// Mat4One (bone->parmat);
#endif
if (arm){
@@ -312,6 +307,13 @@ void where_is_bone1_time (Object *ob, Bone *bone, float ctime)
}
}
+ /* If the bone has been flagged as 'no calc', let's not
+ * bother calculating it.
+ */
+ if (bone->flag & BONE_NOCALC) {
+ return;
+ }
+
if (bone->flag & BONE_IK_TOPARENT){
bone->loc[0]=bone->loc[1]=bone->loc[2]=0.0F;
}
@@ -839,8 +841,10 @@ static void apply_pose_bonechildren (Bone* bone, bPose* pose, int doit)
// Ensure there is a channel for this bone
chan = verify_pose_channel (pose, bone->name);
- if (chan) {
- // Search the pose for a channel with the same name
+ /* Only do this crazy stuff if the no calc flag
+ * is cleared for this bone.
+ */
+ if (chan && (~bone->flag & BONE_NOCALC)) {
if (chan->flag & POSE_LOC)
memcpy (bone->loc, chan->loc, sizeof (bone->loc));
if (chan->flag & POSE_SIZE)
diff --git a/source/blender/include/BIF_editconstraint.h b/source/blender/include/BIF_editconstraint.h
index 963b9fb4e08..0c7742323c0 100644
--- a/source/blender/include/BIF_editconstraint.h
+++ b/source/blender/include/BIF_editconstraint.h
@@ -56,6 +56,9 @@ struct ListBase *get_constraint_client_channels (int forcevalid);
struct ListBase *get_constraint_client(char *name, short *clienttype, void** clientdata);
int test_constraints (struct Object *owner, const char *substring, int disable);
void test_scene_constraints (void);
+
+char *get_con_subtarget_name(struct bConstraint *constraint,
+ struct Object *target);
struct Object *get_con_target(struct bConstraint *constraint);
#endif
diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h
index b808249ace0..5124716bc51 100644
--- a/source/blender/makesdna/DNA_armature_types.h
+++ b/source/blender/makesdna/DNA_armature_types.h
@@ -110,7 +110,11 @@ enum {
BONE_DONE = 0x00000080, /* For detecting cyclic dependancies */
BONE_ISEMPTY = 0x00000100,
- BONE_ISMUSCLE = 0x00000200
+ BONE_ISMUSCLE = 0x00000200,
+ BONE_NOCALC = 0x00000400 /* Don't calculate bone
+ * transformation, when flagged
+ * (note: this is a temporary flag)
+ */
};
enum {
@@ -122,7 +126,8 @@ enum {
BONE_QUATROTBIT,
BONE_HIDDENBIT,
BONE_ISEMPTYBIT,
- BONE_ISMUSCLEBIT
+ BONE_ISMUSCLEBIT,
+ BONE_NOCALCBIT
};
enum {
diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c
index 22d17f43c19..915f4ef456e 100644
--- a/source/blender/src/buttons_editing.c
+++ b/source/blender/src/buttons_editing.c
@@ -1318,16 +1318,25 @@ static void validate_editbonebutton_cb(void *bonev, void *arg2_unused)
validate_editbonebutton(curBone);
}
+static void armature_rest_pos_func(void *notused1, void *notused2) {
+ clear_object_constraint_status(OBACT);
+ make_displists_by_armature(OBACT);
+}
static void editing_panel_armature_type(Object *ob, bArmature *arm)
{
uiBlock *block;
+ uiBut *but;
int bx=148, by=100;
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;
- uiDefButI(block, TOG|BIT|ARM_RESTPOSBIT,REDRAWVIEW3D, "Rest Pos", bx,by,97,20, &arm->flag, 0, 0, 0, 0, "Disable all animation for this object");
+ but = uiDefButI(block, TOG|BIT|ARM_RESTPOSBIT,REDRAWVIEW3D,
+ "Rest Pos", bx,by,97,20, &arm->flag, 0, 0, 0, 0,
+ "Disable all animation for this object");
+ uiButSetFunc(but, armature_rest_pos_func, NULL, NULL);
+
uiBlockBeginAlign(block);
uiDefButI(block, TOG|BIT|ARM_DRAWAXESBIT,REDRAWVIEW3D, "Draw Axes", bx,by-46,97,20, &arm->flag, 0, 0, 0, 0, "Draw bone axes");
uiDefButI(block, TOG|BIT|ARM_DRAWNAMESBIT,REDRAWVIEW3D, "Draw Names", bx,by-69,97,20, &arm->flag, 0, 0, 0, 0, "Draw bone names");
diff --git a/source/blender/src/editconstraint.c b/source/blender/src/editconstraint.c
index be74c045074..571eb2b8eb4 100644
--- a/source/blender/src/editconstraint.c
+++ b/source/blender/src/editconstraint.c
@@ -774,6 +774,66 @@ void add_influence_key_to_constraint (bConstraint *con){
printf("doesn't do anything yet\n");
}
+char *get_con_subtarget_name(bConstraint *constraint, Object *target)
+{
+ /*
+ * If the target for this constraint is target, return a pointer
+ * to the name for this constraints subtarget ... NULL otherwise
+ */
+ switch (constraint->type) {
+
+ case CONSTRAINT_TYPE_ACTION:
+ {
+ bActionConstraint *data = constraint->data;
+ if (data->tar==target) return data->subtarget;
+ }
+ break;
+ case CONSTRAINT_TYPE_LOCLIKE:
+ {
+ bLocateLikeConstraint *data = constraint->data;
+ if (data->tar==target) return data->subtarget;
+ }
+ break;
+ case CONSTRAINT_TYPE_ROTLIKE:
+ {
+ bRotateLikeConstraint *data = constraint->data;
+ if (data->tar==target) return data->subtarget;
+ }
+ break;
+ case CONSTRAINT_TYPE_KINEMATIC:
+ {
+ bKinematicConstraint *data = constraint->data;
+ if (data->tar==target) return data->subtarget;
+ }
+ break;
+ case CONSTRAINT_TYPE_TRACKTO:
+ {
+ bTrackToConstraint *data = constraint->data;
+ if (data->tar==target) return data->subtarget;
+ }
+ break;
+ case CONSTRAINT_TYPE_LOCKTRACK:
+ {
+ bLockTrackConstraint *data = constraint->data;
+ if (data->tar==target) return data->subtarget;
+ }
+ break;
+ case CONSTRAINT_TYPE_FOLLOWPATH:
+ /* wonder if this is relevent, since this constraint
+ * cannot have a subtarget - theeth
+ */
+ {
+ /*
+ * bFollowPathConstraint *data = constraint->data;
+ */
+ return NULL;
+ }
+ break;
+ }
+
+ return NULL;
+}
+
Object *get_con_target(bConstraint *constraint)
{
/*
diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c
index 64359091ef5..14221e8f840 100644
--- a/source/blender/src/editobject.c
+++ b/source/blender/src/editobject.c
@@ -2669,6 +2669,199 @@ static int pose_do_update_flag(Object *ob) {
return do_update;
}
+int clear_bone_nocalc(Object *ob, Bone *bone, void *ptr) {
+ /* When we aren't transform()-ing, we'll want to turn off
+ * the no calc flag for bone bone in case the frame changes,
+ * or something
+ */
+ bone->flag &= ~BONE_NOCALC;
+
+ return 0;
+}
+
+
+static void clear_bone_nocalc_ob(Object *ob) {
+ /* Let's clear no calc for all of the bones in the whole darn armature
+ */
+ bArmature *arm;
+ arm = get_armature(ob);
+ if (arm) {
+ bone_looper(ob, arm->bonebase.first, NULL,
+ clear_bone_nocalc);
+ }
+
+}
+
+int set_bone_nocalc(Object *ob, Bone *bone, void *ptr) {
+ /* Calculating bone transformation makes thins slow ...
+ * lets set the no calc flag for a bone by default
+ */
+ bone->flag |= BONE_NOCALC;
+
+ return 0;
+}
+
+int selected_bone_docalc(Object *ob, Bone *bone, void *ptr) {
+ /* Let's clear the no calc flag for selected bones.
+ * This function always returns 1 for non-no calc bones
+ * (a.k.a., the 'do calc' bones) so that the bone_looper
+ * will count these
+ */
+ if (bone->flag & BONE_NOCALC) {
+ if ( (bone->flag & BONE_SELECTED) ) {
+ bone->flag &= ~BONE_NOCALC;
+ return 1;
+ }
+
+ }
+ else {
+ return 1;
+ }
+ return 0;
+}
+
+static int is_ik_root_docalc(Bone *bone) {
+ Bone *rootBone;
+
+ /* The parents */
+ for (rootBone = bone; rootBone; rootBone=rootBone->parent) {
+ if (!rootBone->parent)
+ break;
+ else if (!(rootBone->flag & BONE_IK_TOPARENT))
+ break;
+ }
+
+ if (~rootBone->flag & BONE_NOCALC)
+ return 1;
+
+ return 0;
+}
+
+static void ik_chain_docalc(Bone *bone) {
+ /* Let's clear the no calc flag for an entire IK chain
+ */
+ Bone *curBone;
+
+ /* This bone */
+ bone->flag &= ~BONE_NOCALC;
+
+ /* The parents */
+ for (curBone = bone; curBone; curBone=curBone->parent) {
+ if (!curBone->parent)
+ break;
+ else if (!(curBone->flag & BONE_IK_TOPARENT))
+ break;
+ curBone->parent->flag &= ~BONE_NOCALC;
+ }
+
+ /* The children */
+ for (curBone = bone->childbase.first; curBone; curBone=curBone->next){
+ if (curBone->flag & BONE_IK_TOPARENT) {
+ curBone->flag &= ~BONE_NOCALC;
+ }
+ }
+}
+
+static void figure_bone_nocalc_constraint(Bone *conbone, bConstraint *con,
+ Object *ob, bArmature *arm) {
+ /* If this bone has a constraint with a subtarget that has
+ * the nocalc flag cleared, then we better clear the no calc flag
+ * on this bone too (and the whole IK chain if this is an IK
+ * constraint).
+ *
+ * Conversly, if this bone has an IK constraint and the root of
+ * the chain has the no calc flag cleared, we had best clear that
+ * flag for the whole chain.
+ */
+ Bone *subtarbone;
+ char *subtar;
+
+ subtar = get_con_subtarget_name(con, ob);
+
+ if (subtar) {
+ if ( (subtarbone = get_named_bone(arm, subtar)) ) {
+ if (~subtarbone->flag & BONE_NOCALC) {
+ if (con->type == CONSTRAINT_TYPE_KINEMATIC)
+ ik_chain_docalc(conbone);
+ else
+ conbone->flag &= ~BONE_NOCALC;
+ }
+ else {
+ if (is_ik_root_docalc(conbone)) {
+ if (con->type == CONSTRAINT_TYPE_KINEMATIC)
+ ik_chain_docalc(conbone);
+ else
+ conbone->flag &= ~BONE_NOCALC;
+ }
+ }
+ }
+ }
+ else {
+ /* no subtarget ... target is regular object */
+ if (is_ik_root_docalc(conbone)) {
+ if (con->type == CONSTRAINT_TYPE_KINEMATIC)
+ ik_chain_docalc(conbone);
+ else
+ conbone->flag &= ~BONE_NOCALC;
+ }
+ }
+
+}
+
+static void figure_bone_nocalc(Object *ob) {
+ /* Let's figure out which bones need to be recalculated,
+ * and which don't. Calculations are based on which bones
+ * are selected, and the constraints that love them.
+ */
+ bArmature *arm;
+ bPoseChannel *chan;
+ bConstraint *con;
+ Bone *conbone;
+
+ int numbones, oldnumbones, iterations;
+
+ arm = get_armature(ob);
+ if (!arm) return;
+
+ if (arm->flag & ARM_RESTPOS) return;
+
+ /* Set no calc for all bones
+ */
+ bone_looper(ob, arm->bonebase.first, NULL,
+ set_bone_nocalc);
+
+ oldnumbones = -1;
+ numbones = 0;
+ iterations = 0;
+
+ /* O.K., lets loop until we don't clear any more no calc bones
+ */
+ while (oldnumbones != numbones) {
+ /* I wonder if this will ever get executed? */
+ if ( (++iterations) == 1000) {
+ printf("figurin' nocalc is talking too long\n");
+ break;
+ }
+
+ oldnumbones = numbones;
+
+ /* clear no calc for selected bones and count */
+ numbones = bone_looper(ob, arm->bonebase.first, NULL,
+ selected_bone_docalc);
+
+ if (ob->pose) {
+ for (chan = ob->pose->chanbase.first; chan; chan=chan->next){
+ conbone = get_named_bone(arm, chan->name);
+ if (conbone) {
+ for (con = chan->constraints.first; con; con=con->next) {
+ figure_bone_nocalc_constraint(conbone, con, ob, arm);
+ }
+ }
+ }
+ }
+ }
+}
+
/*** POSE FIGURIN' -- END ***/
@@ -3430,6 +3623,12 @@ void special_aftertrans_update(char mode, int flip, short canceled, int keyflags
bPose *pose;
bPoseChannel *pchan;
+ /* we had better clear the no calc flags on the bones
+ * ... else things won't look too good when changing
+ * frames, etc.
+ */
+ clear_bone_nocalc_ob(G.obpose);
+
if (U.uiflag & KEYINSERTACT && !canceled){
act=G.obpose->action;
pose=G.obpose->pose;
@@ -4144,6 +4343,8 @@ void transform(int mode)
switch (G.obpose->type) {
case OB_ARMATURE:
+ /* figure out which bones need calculating */
+ figure_bone_nocalc(G.obpose);
make_trans_bones(mode);
break;
}