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:
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)) {
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user