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
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/blender/src
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/blender/src')
-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
3 files changed, 271 insertions, 1 deletions
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;
}