Transform Orientations

Edit Bone and Pose Bone can now be used as transform orientations

Also fix a bug with CTO comming from non-uniformally scaled meshes.
This commit is contained in:
Martin Poirier 2008-05-29 19:10:09 +00:00
parent fe7b591280
commit 8e46d777f3
3 changed files with 111 additions and 44 deletions

@ -515,6 +515,7 @@ int handleNDofInput(NDofInput *n, unsigned short event, short val);
int manageObjectSpace(int confirm, int set);
int manageMeshSpace(int confirm, int set);
int manageBoneSpace(int confirm, int set);
/* Those two fill in mat and return non-zero on success */
int createSpaceNormal(float mat[3][3], float normal[3]);

@ -158,7 +158,7 @@ static void protectflag_to_drawflags(short protectflag, short *drawflags)
}
/* for pose mode */
static void stats_pose(View3D *v3d, bPoseChannel *pchan, float *normal, float *plane)
static void stats_pose(View3D *v3d, bPoseChannel *pchan)
{
Bone *bone= pchan->bone;
@ -166,9 +166,6 @@ static void stats_pose(View3D *v3d, bPoseChannel *pchan, float *normal, float *p
if (bone->flag & BONE_TRANSFORM) {
calc_tw_center(pchan->pose_head);
protectflag_to_drawflags(pchan->protectflag, &v3d->twdrawflag);
VecAddf(normal, normal, pchan->pose_mat[2]);
VecAddf(plane, plane, pchan->pose_mat[1]);
}
}
}
@ -349,26 +346,24 @@ int calc_manipulator_stats(ScrArea *sa)
}
}
else if(ob && (ob->flag & OB_POSEMODE)) {
bArmature *arm= ob->data;
bArmature *arm = ob->data;
bPoseChannel *pchan;
int mode;
if((ob->lay & G.vd->lay)==0) return 0;
mode= Trans.mode;
Trans.mode= TFM_ROTATION; // mislead counting bones... bah
mode = Trans.mode;
Trans.mode = TFM_ROTATION; // mislead counting bones... bah
/* count total, we use same method as transform will do */
Trans.total= 0;
count_bone_select(&Trans, arm, &arm->bonebase, 1);
totsel= Trans.total;
totsel = Trans.total;
if(totsel) {
/* use channels to get stats */
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
stats_pose(v3d, pchan, normal, plane);
stats_pose(v3d, pchan);
}
//VecMulf(normal, -1.0);
VecMulf(plane, -1.0);
VecMulf(G.scene->twcent, 1.0f/(float)totsel); // centroid!
Mat4MulVecfl(ob->obmat, G.scene->twcent);
@ -376,7 +371,7 @@ int calc_manipulator_stats(ScrArea *sa)
Mat4MulVecfl(ob->obmat, G.scene->twmax);
}
/* restore, mode can be TFM_INIT */
Trans.mode= mode;
Trans.mode = mode;
}
else if(G.f & (G_VERTEXPAINT + G_TEXTUREPAINT + G_WEIGHTPAINT + G_SCULPTMODE)) {
;
@ -433,7 +428,7 @@ int calc_manipulator_stats(ScrArea *sa)
break;
case V3D_MANIP_NORMAL:
if(G.obedit) {
if(G.obedit || ob->flag & OB_POSEMODE) {
float mat[3][3];
int type;
@ -479,34 +474,6 @@ int calc_manipulator_stats(ScrArea *sa)
}
break;
}
/* pose mode is a bit weird, so keep it separated */
else if (ob->flag & OB_POSEMODE)
{
strcpy(t->spacename, "normal");
if(normal[0]!=0.0 || normal[1]!=0.0 || normal[2]!=0.0) {
float imat[3][3], mat[3][3];
/* we need the transpose of the inverse for a normal... */
Mat3CpyMat4(imat, ob->obmat);
Mat3Inv(mat, imat);
Mat3Transp(mat);
Mat3MulVecfl(mat, normal);
Mat3MulVecfl(mat, plane);
Normalize(normal);
if(0.0==Normalize(plane)) VECCOPY(plane, mat[1]);
VECCOPY(mat[2], normal);
Crossf(mat[0], normal, plane);
Crossf(mat[1], mat[2], mat[0]);
Mat4CpyMat3(v3d->twmat, mat);
Mat4Ortho(v3d->twmat);
break;
}
}
/* no break we define 'normal' as 'local' in Object mode */
case V3D_MANIP_LOCAL:
strcpy(t->spacename, "local");

@ -27,6 +27,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_armature_types.h"
#include "DNA_action_types.h"
#include "DNA_curve_types.h"
#include "DNA_listBase.h"
#include "DNA_object_types.h"
@ -68,11 +69,17 @@ void BIF_clearTransformOrientation(void)
}
void BIF_manageTransformOrientation(int confirm, int set) {
Object *ob = OBACT;
int index = -1;
if (G.obedit) {
if (G.obedit->type == OB_MESH)
index = manageMeshSpace(confirm, set);
else if (G.obedit->type == OB_ARMATURE)
index = manageBoneSpace(confirm, set);
}
else if (ob && (ob->flag & OB_POSEMODE)) {
index = manageBoneSpace(confirm, set);
}
else {
index = manageObjectSpace(confirm, set);
@ -122,6 +129,31 @@ int confirmSpace(int set, char text[])
}
}
int manageBoneSpace(int confirm, int set) {
float mat[3][3];
float normal[3], plane[3];
char name[36] = "";
int index;
getTransformOrientation(normal, plane, 0);
if (confirm == 0 && confirmSpace(set, "Bone") == 0) {
return -1;
}
if (createSpaceNormalTangent(mat, normal, plane) == 0) {
error("Cannot use zero-length bone");
return -1;
}
strcpy(name, "Bone");
/* Input name */
sbutton(name, 1, 35, "name: ");
index = addMatrixSpace(mat, name);
return index;
}
int manageMeshSpace(int confirm, int set) {
float mat[3][3];
@ -363,6 +395,29 @@ void applyTransformOrientation() {
}
}
static int count_bone_select(bArmature *arm, ListBase *lb, int do_it)
{
Bone *bone;
int do_next;
int total = 0;
for(bone= lb->first; bone; bone= bone->next) {
bone->flag &= ~BONE_TRANSFORM;
do_next = do_it;
if(do_it) {
if(bone->layer & arm->layer) {
if (bone->flag & BONE_SELECTED) {
bone->flag |= BONE_TRANSFORM;
total++;
do_next= 0; // no transform on children if one parent bone is selected
}
}
}
total += count_bone_select(arm, &bone->childbase, do_next);
}
return total;
}
int getTransformOrientation(float normal[3], float plane[3], int activeOnly)
{
@ -375,6 +430,14 @@ int getTransformOrientation(float normal[3], float plane[3], int activeOnly)
if(G.obedit)
{
float imat[3][3], mat[3][3];
/* we need the transpose of the inverse for a normal... */
Mat3CpyMat4(imat, ob->obmat);
Mat3Inv(mat, imat);
Mat3Transp(mat);
ob= G.obedit;
if(G.obedit->type==OB_MESH)
@ -640,11 +703,47 @@ int getTransformOrientation(float normal[3], float plane[3], int activeOnly)
}
Mat4Mul3Vecfl(G.obedit->obmat, plane);
Mat4Mul3Vecfl(G.obedit->obmat, normal);
/* Vectors from edges don't need the special transpose inverse multiplication */
if (result == ORIENTATION_EDGE)
{
Mat4Mul3Vecfl(ob->obmat, normal);
Mat4Mul3Vecfl(ob->obmat, plane);
}
else
{
Mat3MulVecfl(mat, normal);
Mat3MulVecfl(mat, plane);
}
}
else if(ob && (ob->flag & OB_POSEMODE))
{
bArmature *arm= ob->data;
bPoseChannel *pchan;
int totsel;
totsel = count_bone_select(arm, &arm->bonebase, 1);
if(totsel) {
float imat[3][3], mat[3][3];
/* use channels to get stats */
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
if (pchan->bone && pchan->bone->flag & BONE_TRANSFORM) {
VecAddf(normal, normal, pchan->pose_mat[2]);
VecAddf(plane, plane, pchan->pose_mat[1]);
}
}
VecMulf(plane, -1.0);
/* we need the transpose of the inverse for a normal... */
Mat3CpyMat4(imat, ob->obmat);
Mat3Inv(mat, imat);
Mat3Transp(mat);
Mat3MulVecfl(mat, normal);
Mat3MulVecfl(mat, plane);
result = ORIENTATION_EDGE;
}
}
else if(G.f & (G_VERTEXPAINT + G_TEXTUREPAINT + G_WEIGHTPAINT + G_SCULPTMODE))
{