First version of visualizing the DoF (french degrees!) for Pose-bones. It

now only draws the limits for X and Z rotations (Y is bone axis itself).

Quick snaphsots (links will disappear):
http://www.blender.org/bf/rt6.jpg
http://www.blender.org/bf/rt7.jpg

It only draws for selected Bones that are part of IK, and have limits set.
Most work was getting code OK to setup drawing this 'DoF space', so now
experiments can be done with more drawing types.

ALso; Buttons for DoFs now only draw if the pose-bones are part of an IK
chain.
This commit is contained in:
2005-08-29 17:02:24 +00:00
parent a07394ef2c
commit fa63c6a7e1
4 changed files with 201 additions and 40 deletions

View File

@@ -44,6 +44,7 @@ void exit_posemode(void);
void set_pose_keys(struct Object *ob); void set_pose_keys(struct Object *ob);
struct bPoseChannel *get_active_posechannel (struct Object *ob); struct bPoseChannel *get_active_posechannel (struct Object *ob);
int pose_channel_in_IK_chain(struct Object *ob, struct bPoseChannel *pchan);
/* tools */ /* tools */
void pose_select_constraint_target(void); void pose_select_constraint_target(void);

View File

@@ -98,6 +98,7 @@
#include "BIF_interface.h" #include "BIF_interface.h"
#include "BIF_meshtools.h" #include "BIF_meshtools.h"
#include "BIF_mywindow.h" #include "BIF_mywindow.h"
#include "BIF_poseobject.h"
#include "BIF_renderwin.h" #include "BIF_renderwin.h"
#include "BIF_resources.h" #include "BIF_resources.h"
#include "BIF_screen.h" #include "BIF_screen.h"
@@ -2345,53 +2346,60 @@ static void editing_panel_pose_bones(Object *ob, bArmature *arm)
uiDefButBitI(block, TOG, BONE_HIDDEN_P, REDRAWVIEW3D, "Hide", bx+245,by-38,88,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in Pose Mode"); uiDefButBitI(block, TOG, BONE_HIDDEN_P, REDRAWVIEW3D, "Hide", bx+245,by-38,88,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in Pose Mode");
uiBlockEndAlign(block); uiBlockEndAlign(block);
/* DOFs only for IK chains */
zerodof = 1; zerodof = 1;
zerolimit = 1; zerolimit = 1;
if(pose_channel_in_IK_chain(ob, pchan)) {
uiBlockBeginAlign(block);
uiDefButBitS(block, TOG, BONE_IK_NO_XDOF, B_ARM_RECALCDATA, "Lock X Rot", bx-10,by-60,114,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Disable X DoF for IK"); uiBlockBeginAlign(block);
if ((pchan->ikflag & BONE_IK_NO_XDOF)==0) { uiDefButBitS(block, TOG, BONE_IK_NO_XDOF, B_ARM_RECALCDATA, "Lock X Rot", bx-10,by-60,114,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Disable X DoF for IK");
uiDefButF(block, NUM, B_ARM_RECALCDATA, "Stiff X:", bx-10, by-80, 114, 19, &pchan->stiffness[0], 0.0, 0.99, 1.0, 0.0, "Resistance to bending for X axis"); if ((pchan->ikflag & BONE_IK_NO_XDOF)==0) {
uiDefButBitS(block, TOG, BONE_IK_XLIMIT, B_ARM_RECALCDATA, "Limit X", bx-10,by-100,114,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Limit rotation over X axis"); uiDefButF(block, NUM, B_ARM_RECALCDATA, "Stiff X:", bx-10, by-80, 114, 19, &pchan->stiffness[0], 0.0, 0.99, 1.0, 0.0, "Resistance to bending for X axis");
if ((pchan->ikflag & BONE_IK_XLIMIT)) { uiDefButBitS(block, TOG, BONE_IK_XLIMIT, B_ARM_RECALCDATA, "Limit X", bx-10,by-100,114,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Limit rotation over X axis");
uiDefButF(block, NUM, B_ARM_RECALCDATA, "Min X:", bx-10, by-120, 114, 19, &pchan->limitmin[0], -180.0f, pchan->limitmax[0], 10, 2, "Minimum X limit"); if ((pchan->ikflag & BONE_IK_XLIMIT)) {
uiDefButF(block, NUM, B_ARM_RECALCDATA, "Max X:", bx-10, by-140, 114, 19, &pchan->limitmax[0], pchan->limitmin[0], 180.0f, 10, 2, "Maximum X limit"); uiDefButF(block, NUM, B_ARM_RECALCDATA, "Min X:", bx-10, by-120, 114, 19, &pchan->limitmin[0], -180.0f, pchan->limitmax[0], 1000, 1, "Minimum X limit");
zerolimit = 0; uiDefButF(block, NUM, B_ARM_RECALCDATA, "Max X:", bx-10, by-140, 114, 19, &pchan->limitmax[0], pchan->limitmin[0], 180.0f, 1000, 1, "Maximum X limit");
zerolimit = 0;
}
zerodof = 0;
} }
zerodof = 0; uiBlockEndAlign(block);
}
uiBlockEndAlign(block); uiBlockBeginAlign(block);
uiDefButBitS(block, TOG, BONE_IK_NO_YDOF, B_ARM_RECALCDATA, "Lock Y Rot", bx+104,by-60,113,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Disable Y DoF for IK");
uiBlockBeginAlign(block); if ((pchan->ikflag & BONE_IK_NO_YDOF)==0) {
uiDefButBitS(block, TOG, BONE_IK_NO_YDOF, B_ARM_RECALCDATA, "Lock Y Rot", bx+104,by-60,113,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Disable Y DoF for IK"); uiDefButF(block, NUM, B_ARM_RECALCDATA, "Stiff Y:", bx+104, by-80, 114, 19, &pchan->stiffness[1], 0.0, 0.99, 1.0, 0.0, "Resistance to bending for Y axis");
if ((pchan->ikflag & BONE_IK_NO_YDOF)==0) { uiDefButBitS(block, TOG, BONE_IK_YLIMIT, B_ARM_RECALCDATA, "Limit Y", bx+104,by-100,113,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Limit rotation over Y axis");
uiDefButF(block, NUM, B_ARM_RECALCDATA, "Stiff Y:", bx+104, by-80, 114, 19, &pchan->stiffness[1], 0.0, 0.99, 1.0, 0.0, "Resistance to bending for Y axis"); if ((pchan->ikflag & BONE_IK_YLIMIT)) {
uiDefButBitS(block, TOG, BONE_IK_YLIMIT, B_ARM_RECALCDATA, "Limit Y", bx+104,by-100,113,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Limit rotation over Y axis"); uiDefButF(block, NUM, B_ARM_RECALCDATA, "Min Y:", bx+104, by-120, 113, 19, &pchan->limitmin[1], -180.0f, pchan->limitmax[1], 1000, 1, "Minimum Y limit");
if ((pchan->ikflag & BONE_IK_YLIMIT)) { uiDefButF(block, NUM, B_ARM_RECALCDATA, "Max Y:", bx+104, by-140, 113, 19, &pchan->limitmax[1], pchan->limitmin[1], 180.0f, 1000, 1, "Maximum Y limit");
uiDefButF(block, NUM, B_ARM_RECALCDATA, "Min Y:", bx+104, by-120, 113, 19, &pchan->limitmin[1], -180.0f, pchan->limitmax[1], 10, 2, "Minimum Y limit"); zerolimit = 0;
uiDefButF(block, NUM, B_ARM_RECALCDATA, "Max Y:", bx+104, by-140, 113, 19, &pchan->limitmax[1], pchan->limitmin[1], 180.0f, 10, 2, "Maximum Y limit"); }
zerolimit = 0; zerodof = 0;
} }
zerodof = 0; uiBlockEndAlign(block);
}
uiBlockEndAlign(block); uiBlockBeginAlign(block);
uiDefButBitS(block, TOG, BONE_IK_NO_ZDOF, B_ARM_RECALCDATA, "Lock Z Rot", bx+217,by-60,113,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Disable Z DoF for IK");
uiBlockBeginAlign(block); if ((pchan->ikflag & BONE_IK_NO_ZDOF)==0) {
uiDefButBitS(block, TOG, BONE_IK_NO_ZDOF, B_ARM_RECALCDATA, "Lock Z Rot", bx+217,by-60,113,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Disable Z DoF for IK"); uiDefButF(block, NUM, B_ARM_RECALCDATA, "Stiff Z:", bx+217, by-80, 114, 19, &pchan->stiffness[2], 0.0, 0.99, 1.0, 0.0, "Resistance to bending for Z axis");
if ((pchan->ikflag & BONE_IK_NO_ZDOF)==0) { uiDefButBitS(block, TOG, BONE_IK_ZLIMIT, B_ARM_RECALCDATA, "Limit Z", bx+217,by-100,113,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Limit rotation over Z axis");
uiDefButF(block, NUM, B_ARM_RECALCDATA, "Stiff Z:", bx+217, by-80, 114, 19, &pchan->stiffness[2], 0.0, 0.99, 1.0, 0.0, "Resistance to bending for Z axis"); if ((pchan->ikflag & BONE_IK_ZLIMIT)) {
uiDefButBitS(block, TOG, BONE_IK_ZLIMIT, B_ARM_RECALCDATA, "Limit Z", bx+217,by-100,113,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Limit rotation over Z axis"); uiDefButF(block, NUM, B_ARM_RECALCDATA, "Min Z:", bx+217, by-120, 113, 19, &pchan->limitmin[2], -180.0f, pchan->limitmax[2], 1000, 1, "Minimum Z limit");
if ((pchan->ikflag & BONE_IK_ZLIMIT)) { uiDefButF(block, NUM, B_ARM_RECALCDATA, "Max Z:", bx+217, by-140, 113, 19, &pchan->limitmax[2], pchan->limitmin[2], 180.0f, 1000, 1, "Maximum Z limit");
uiDefButF(block, NUM, B_ARM_RECALCDATA, "Min Z:", bx+217, by-120, 113, 19, &pchan->limitmin[2], -180.0f, pchan->limitmax[2], 10, 2, "Minimum Z limit"); zerolimit = 0;
uiDefButF(block, NUM, B_ARM_RECALCDATA, "Max Z:", bx+217, by-140, 113, 19, &pchan->limitmax[2], pchan->limitmin[2], 180.0f, 10, 2, "Maximum Z limit"); }
zerolimit = 0; zerodof = 0;
} }
zerodof = 0; uiBlockEndAlign(block);
}
else {
uiDefBut(block, LABEL, 0, "(DoF options only for IK chains)", bx-10,by-60, 300, 20, 0, 0, 0, 0, 0, "");
} }
uiBlockEndAlign(block);
by -= (zerodof)? 82: (zerolimit)? 122: 162; by -= (zerodof)? 82: (zerolimit)? 122: 162;
if(by < -200) break; // for time being... extreme long panels are very slow if(by < -200) break; // for time being... extreme long panels are very slow
} }
} }

View File

@@ -1100,6 +1100,140 @@ static void pchan_draw_IK_root_lines(bPoseChannel *pchan)
} }
} }
static void draw_pose_dofs(Object *ob)
{
bPoseChannel *pchan;
Bone *bone;
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
if(pchan->ikflag & (BONE_IK_XLIMIT|BONE_IK_ZLIMIT)) {
bone= pchan->bone;
if(bone && !(bone->flag & BONE_HIDDEN_P)) {
if(bone->flag & BONE_SELECTED) {
if(pose_channel_in_IK_chain(ob, pchan)) {
float corner[4][3], vec[4][3], handle1[3], handle2[3];
float mat[4][4];
float phi=0.0f, theta=0.0f;
int a, i;
/* in parent-bone pose, but own restspace */
glPushMatrix();
if(pchan->parent) {
glMultMatrixf(pchan->parent->pose_mat);
glTranslatef(0.0f, bone->parent->length, 0.0f);
}
glTranslatef(bone->head[0], bone->head[1], bone->head[2]);
Mat4CpyMat3(mat, pchan->bone->bone_mat);
glMultMatrixf(mat);
/* center of the cone */
if(pchan->ikflag & BONE_IK_XLIMIT)
phi= 0.5*( pchan->limitmin[0]+pchan->limitmax[0]);
if(pchan->ikflag & BONE_IK_ZLIMIT)
theta= 0.5*(pchan->limitmin[2]+pchan->limitmax[2]);
/* now move to cone space */
glRotatef(phi, 1.0f, 0.0f, 0.0f);
glRotatef(theta, 0.0f, 0.0f, 1.0f);
/* arcs */
if(pchan->ikflag & BONE_IK_ZLIMIT) {
glColor3ub(50, 50, 255); // blue, Z axis limit
glBegin(GL_LINE_STRIP);
for(a=-16; a<=16; a++) {
float fac= ((float)a)/16.0f;
phi= fac*(M_PI/360.0f)*(pchan->limitmax[2]-pchan->limitmin[2]);
if(a==-16) i= 0; else i= 1;
corner[i][0]= bone->length*sin(phi);
corner[i][1]= bone->length*cos(phi);
corner[i][2]= 0.0f;
glVertex3fv(corner[i]);
}
glEnd();
}
if(pchan->ikflag & BONE_IK_XLIMIT) {
glColor3ub(255, 50, 50); // Red, X axis limit
glBegin(GL_LINE_STRIP);
for(a=-16; a<=16; a++) {
float fac= ((float)a)/16.0f;
phi= 0.5f*M_PI + fac*(M_PI/360.0f)*(pchan->limitmax[0]-pchan->limitmin[0]);
if(a==-16) i= 2; else i= 3;
corner[i][0]= 0.0f;
corner[i][1]= bone->length*sin(phi);
corner[i][2]= bone->length*cos(phi);
glVertex3fv(corner[i]);
}
glEnd();
}
if(pchan->ikflag & BONE_IK_XLIMIT) {
if(pchan->ikflag & BONE_IK_ZLIMIT) {
/* using corners to draw the influence area */
/* we set up beziers for it */
VecSubf(handle1, corner[2], corner[3]);
VecMulf(handle1, 0.27614f); // 0.5 * kappa, 0.5522847498
VecSubf(handle2, corner[0], corner[1]);
VecMulf(handle2, 0.27614f);
cpack(0x0);
glEnable(GL_MAP1_VERTEX_3);
/* bezier part */
VECCOPY(vec[0], corner[0]); // 0 and 3 are cv's, 1 and 2 handles
VecAddf(vec[1], corner[0], handle1);
VecAddf(vec[2], corner[2], handle2);
VECCOPY(vec[3], corner[2]);
glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, vec[0]);
glBegin(GL_LINE_STRIP);
for(a=0; a<=16; a++) glEvalCoord1f((float)a/16.0);
glEnd();
/* bezier part */
VECCOPY(vec[0], corner[2]); // 0 and 3 are cv's, 1 and 2 handles
VecSubf(vec[1], corner[2], handle2);
VecAddf(vec[2], corner[1], handle1);
VECCOPY(vec[3], corner[1]);
glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, vec[0]);
glBegin(GL_LINE_STRIP);
for(a=0; a<=16; a++) glEvalCoord1f((float)a/16.0);
glEnd();
/* bezier part */
VECCOPY(vec[0], corner[1]); // 0 and 3 are cv's, 1 and 2 handles
VecSubf(vec[1], corner[1], handle1);
VecSubf(vec[2], corner[3], handle2);
VECCOPY(vec[3], corner[3]);
glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, vec[0]);
glBegin(GL_LINE_STRIP);
for(a=0; a<=16; a++) glEvalCoord1f((float)a/16.0);
glEnd();
/* bezier part */
VECCOPY(vec[0], corner[3]); // 0 and 3 are cv's, 1 and 2 handles
VecAddf(vec[1], corner[3], handle2);
VecSubf(vec[2], corner[0], handle1);
VECCOPY(vec[3], corner[0]);
glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, vec[0]);
glBegin(GL_LINE_STRIP);
for(a=0; a<=16; a++) glEvalCoord1f((float)a/16.0);
glEnd();
}
}
glPopMatrix(); // out of cone, out of bone
}
}
}
}
}
}
/* assumes object is Armature with pose */ /* assumes object is Armature with pose */
static void draw_pose_channels(Base *base, int dt) static void draw_pose_channels(Base *base, int dt)
@@ -1265,6 +1399,10 @@ static void draw_pose_channels(Base *base, int dt)
/* restore */ /* restore */
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
/* draw DoFs */
if (arm->flag & ARM_POSEMODE)
draw_pose_dofs(ob);
/* finally names and axes */ /* finally names and axes */
if(arm->flag & (ARM_DRAWNAMES|ARM_DRAWAXES)) { if(arm->flag & (ARM_DRAWNAMES|ARM_DRAWAXES)) {

View File

@@ -162,7 +162,21 @@ bPoseChannel *get_active_posechannel (Object *ob)
return NULL; return NULL;
} }
int pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan)
{
bConstraint *con;
Bone *bone;
for(con= pchan->constraints.first; con; con= con->next) {
if(con->type==CONSTRAINT_TYPE_KINEMATIC) return 1;
}
for(bone= pchan->bone->childbase.first; bone; bone= bone->next) {
pchan= get_pose_channel(ob->pose, bone->name);
if(pchan && pose_channel_in_IK_chain(ob, pchan))
return 1;
}
return 0;
}
void pose_select_constraint_target(void) void pose_select_constraint_target(void)
{ {