Transform stuff

Cleanup in transform.c: removed uneeded includes and removed REPEAT experiment.

Split off manipulator init function, no need to resort on hacks to setup stuff before starting transform anymore.

Fix0r3d single axis projection for constraints. It deals with perspective correctly now (as much as planar constraints).
This commit is contained in:
Martin Poirier 2005-06-28 07:58:16 +00:00
parent 12d10f45ea
commit a344dca9cf
4 changed files with 165 additions and 235 deletions

@ -37,7 +37,6 @@
/* MODE AND NUMINPUT FLAGS */
#define TFM_INIT -1
#define TFM_REPEAT 0
#define TFM_TRANSLATION 1
#define TFM_ROTATION 2
#define TFM_RESIZE 3
@ -77,7 +76,8 @@ void BIF_drawPropCircle(void);
void BIF_TransformSetUndo(char *str);
/* view3d manipulators */
void ManipulatorTransform(int mode);
void initManipulator(int mode);
void ManipulatorTransform();
int BIF_do_manipulator(struct ScrArea *sa);
void BIF_draw_manipulator(struct ScrArea *sa);

@ -46,65 +46,28 @@
#include "MEM_guardedalloc.h"
#include "DNA_action_types.h"
#include "DNA_armature_types.h"
#include "DNA_camera_types.h"
#include "DNA_curve_types.h"
#include "DNA_effect_types.h"
#include "DNA_ika_types.h"
#include "DNA_image_types.h"
#include "DNA_ipo_types.h"
#include "DNA_key_types.h"
#include "DNA_lamp_types.h"
#include "DNA_lattice_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_meta_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_texture_types.h"
#include "DNA_view3d_types.h"
#include "DNA_world_types.h"
#include "DNA_listBase.h"
#include "DNA_userdef_types.h"
#include "DNA_property_types.h"
#include "DNA_vfont_types.h"
#include "DNA_constraint_types.h"
#include "DNA_scene_types.h" /* PET modes */
#include "DNA_screen_types.h" /* area dimensions */
#include "DNA_object_types.h"
#include "DNA_view3d_types.h"
#include "DNA_ipo_types.h" /* some silly ipo flag */
#include "BIF_editview.h"
#include "BIF_resources.h"
#include "BIF_mywindow.h"
#include "BIF_gl.h"
#include "BIF_editlattice.h"
#include "BIF_editarmature.h"
#include "BIF_editmesh.h"
#include "BIF_editview.h" /* arrows_move_cursor */
#include "BIF_screen.h"
#include "BIF_space.h"
#include "BIF_toets.h"
#include "BIF_toolbox.h"
#include "BIF_space.h" /* undo */
#include "BIF_toets.h" /* persptoetsen */
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_blender.h"
#include "BKE_curve.h"
#include "BKE_displist.h"
#include "BKE_effect.h"
#include "BKE_global.h"
#include "BKE_ipo.h"
#include "BKE_lattice.h"
#include "BKE_mball.h"
#include "BKE_object.h"
#include "BKE_utildefines.h"
#include "BDR_editobject.h"
#include "BSE_view.h"
#include "BSE_edit.h"
#include "BSE_editipo.h"
#include "BSE_editipo_types.h"
#include "BDR_editobject.h" // reset_slowparents()
#include "BLI_arithb.h"
#include "BLI_editVert.h"
#include "BLI_ghash.h"
#include "PIL_time.h"
@ -112,9 +75,6 @@
#include "mydevice.h"
extern ListBase editNurb;
extern ListBase editelems;
extern void helpline(float *vec);
@ -122,12 +82,14 @@ extern void helpline(float *vec);
/* GLOBAL VARIABLE THAT SHOULD MOVED TO SCREEN MEMBER OR SOMETHING */
TransInfo Trans = {TFM_INIT, 0}; // enforce init on first usage
int LastMode = TFM_TRANSLATION;
ListBase CSpaces = {0,0};
float MatSpace[3][3];
/* ************************** TRANSFORMATIONS **************************** */
static void view_editmove(unsigned short event)
{
int refresh = 0;
/* Regular: Zoom in */
/* Shift: Scroll up */
/* Ctrl: Scroll right */
@ -158,6 +120,7 @@ static void view_editmove(unsigned short event)
else
persptoetsen(PADPLUSKEY);
refresh = 1;
break;
case WHEELDOWNMOUSE:
if( G.qual & LR_SHIFTKEY ) {
@ -181,8 +144,15 @@ static void view_editmove(unsigned short event)
else
persptoetsen(PADMINUS);
refresh = 1;
break;
}
if (refresh) {
Mat4CpyMat4(Trans.viewmat, G.vd->viewmat);
Mat4CpyMat4(Trans.viewinv, G.vd->viewinv);
Mat4CpyMat4(Trans.persinv, G.vd->persinv);
}
}
static char *transform_to_undostr(TransInfo *t)
@ -217,15 +187,16 @@ static char *transform_to_undostr(TransInfo *t)
/* ************************************************* */
void checkFirstTime() {
if(Trans.mode==TFM_INIT)
if(Trans.mode==TFM_INIT) {
memset(&Trans, 0, sizeof(TransInfo));
Trans.propsize = 1.0;
Mat3One(MatSpace);
}
}
static void transformEvent(unsigned short event, short val) {
float mati[3][3];
float mati[3][3] = {1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f};
char cmode = constraintModeToChar(&Trans);
Mat3One(mati);
if (val) {
switch (event){
@ -260,7 +231,7 @@ static void transformEvent(unsigned short event, short val) {
stopConstraint(&Trans);
}
else {
initSelectConstraint(&Trans, mati);
initSelectConstraint(&Trans, MatSpace);
postSelectConstraint(&Trans);
}
}
@ -454,20 +425,6 @@ void initTransform(int mode, int context) {
Trans.state = TRANS_RUNNING;
/* stupid PET initialisation code */
/* START */
if (Trans.propsize == 0.0f) {
Trans.propsize = 1.0;
}
/* END */
if (mode == TFM_REPEAT) {
mode = LastMode;
}
else {
LastMode = mode;
}
Trans.context = context;
initTrans(&Trans); // internal data, mouse, vectors
@ -542,7 +499,7 @@ void Transform()
event= extern_qread(&val);
}
Trans.redraw = 1;
Trans.redraw = 1; /* initial draw */
while (Trans.state == TRANS_RUNNING) {
@ -609,21 +566,10 @@ void Transform()
scrarea_queue_headredraw(curarea);
}
void ManipulatorTransform(int mode)
void initManipulator(int mode)
{
int mouse_moved = 0;
short pmval[2] = {0, 0}, mval[2], val;
unsigned short event;
Trans.state = TRANS_RUNNING;
/* stupid PET initialisation code */
/* START */
if (Trans.propsize == 0.0f) {
Trans.propsize = 1.0;
}
/* END */
Trans.context = CTX_NONE;
initTrans(&Trans); // internal data, mouse, vectors
@ -658,10 +604,20 @@ void ManipulatorTransform(int mode)
break;
}
initConstraint(&Trans);
Trans.flag |= T_USES_MANIPULATOR;
Trans.redraw = 1;
initConstraint(&Trans);
}
void ManipulatorTransform()
{
int mouse_moved = 0;
short pmval[2] = {0, 0}, mval[2], val;
unsigned short event;
if (Trans.total == 0)
return;
Trans.redraw = 1; /* initial draw */
while (Trans.state == TRANS_RUNNING) {
@ -758,8 +714,8 @@ void ManipulatorTransform(int mode)
{
char cmode='g';
if(mode==TFM_RESIZE) cmode= 's';
else if(mode==TFM_ROTATION) cmode= 'r';
if(Trans.mode==TFM_RESIZE) cmode= 's';
else if(Trans.mode==TFM_ROTATION) cmode= 'r';
/* aftertrans does displists, ipos and action channels */
/* 7 = keyflags, meaning do loc/rot/scale ipos. Not sure if I like the old method to detect what changed (ton) */
special_aftertrans_update(cmode, 0, (short)(Trans.state == TRANS_CANCEL), 7);

@ -32,7 +32,6 @@
#include <stdlib.h>
#include <string.h>
#include <math.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
@ -44,58 +43,24 @@
#include <io.h>
#endif
#include "MEM_guardedalloc.h"
#include "DNA_action_types.h"
#include "DNA_armature_types.h"
#include "DNA_camera_types.h"
#include "DNA_curve_types.h"
#include "DNA_effect_types.h"
#include "DNA_ika_types.h"
#include "DNA_image_types.h"
#include "DNA_ipo_types.h"
#include "DNA_key_types.h"
#include "DNA_lamp_types.h"
#include "DNA_lattice_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_meta_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_texture_types.h"
#include "DNA_view3d_types.h"
#include "DNA_world_types.h"
#include "DNA_userdef_types.h"
#include "DNA_property_types.h"
#include "DNA_vfont_types.h"
#include "DNA_constraint_types.h"
#include "BIF_screen.h"
#include "BIF_space.h"
#include "BIF_editview.h"
#include "BIF_resources.h"
#include "BIF_mywindow.h"
#include "BIF_gl.h"
#include "BIF_editlattice.h"
#include "BIF_editarmature.h"
#include "BIF_editmesh.h"
#include "BKE_global.h"
#include "BKE_object.h"
#include "BKE_utildefines.h"
#include "BKE_lattice.h"
#include "BKE_armature.h"
#include "BKE_curve.h"
#include "BKE_displist.h"
#include "BSE_view.h"
#include "BSE_edit.h"
#include "BLI_arithb.h"
#include "BLI_editVert.h"
#include "BDR_drawobject.h"
#include "BDR_drawobject.h" /* drawcircball */
#include "blendef.h"
@ -188,22 +153,12 @@ static void postConstraintChecks(TransInfo *t, float vec[3], float pvec[3]) {
static void axisProjection(TransInfo *t, float axis[3], float in[3], float out[3]) {
float norm[3], n[3], vec[3], factor;
VecAddf(vec, in, t->con.center);
getViewVector(vec, norm);
Normalise(axis);
VECCOPY(n, axis);
Mat4MulVecfl(t->viewmat, n);
n[2] = t->viewmat[3][2];
Mat4MulVecfl(t->viewinv, n);
float norm[3], n[3], n2[3], vec[3], factor;
/* For when view is parallel to constraint... will cause NaNs otherwise
So we take vertical motion in 3D space and apply it to the
constraint axis. Nice for camera grab + MMB */
if(n[0]*n[0] + n[1]*n[1] + n[2]*n[2] < 0.000001f) {
if(1.0f - Inpf(axis, t->viewinv[2]) < 0.000001f) {
Projf(vec, in, t->viewinv[1]);
factor = Inpf(t->viewinv[1], vec) * 2.0f;
/* since camera distance is quite relative, use quadratic relationship. holding shift can compensate */
@ -217,11 +172,24 @@ static void axisProjection(TransInfo *t, float axis[3], float in[3], float out[3
else {
// prevent division by zero, happens on constrainting without initial delta transform */
if(in[0]!=0.0f || in[1]!=0.0f || in[2]!=0.0) {
Projf(vec, in, n);
factor = Normalise(vec);
// prevent NaN for 0.0/0.0
if(factor!=0.0f)
factor /= Inpf(axis, vec);
/* project axis on viewplane */
Projf(vec, axis, t->viewinv[2]);
VecSubf(vec, axis, vec);
/* project input on the new axis */
Projf(vec, in, vec);
/* get view vector on that point (account for perspective) */
VecAddf(vec, vec, t->con.center);
getViewVector(vec, norm);
/* cross product twice to get a full space definition */
Crossf(n, axis, norm);
Crossf(n2, norm, n);
/* Project input on plane perpendicular to the axis (as drawn on screen) */
Projf(vec, in, n2);
/* Adjust output */
factor = Inpf(vec, vec) / Inpf(axis, vec);
VecMulf(axis, factor);
VECCOPY(out, axis);
@ -230,23 +198,19 @@ static void axisProjection(TransInfo *t, float axis[3], float in[3], float out[3
}
static void planeProjection(TransInfo *t, float in[3], float out[3]) {
float vec[3], factor, angle, norm[3];
float vec[3], factor, norm[3];
VecAddf(vec, in, t->con.center);
getViewVector(vec, norm);
VecSubf(vec, out, in);
factor = Normalise(vec);
angle = Inpf(vec, norm);
if (angle * angle >= 0.000001f) {
factor /= angle;
factor = Inpf(vec, vec) / Inpf(vec, norm);
VECCOPY(vec, norm);
VecMulf(vec, factor);
VECCOPY(vec, norm);
VecMulf(vec, factor);
VecAddf(out, in, vec);
}
VecAddf(out, in, vec);
}
/*
@ -326,6 +290,18 @@ static void applyObjectConstraintVec(TransInfo *t, TransData *td, float in[3], f
VECCOPY(out, pvec);
}
else {
int i=0;
out[0] = out[1] = out[2] = 0.0f;
if (t->con.mode & CON_AXIS0) {
out[0] = in[i++];
}
if (t->con.mode & CON_AXIS1) {
out[1] = in[i++];
}
if (t->con.mode & CON_AXIS2) {
out[2] = in[i++];
}
Mat3MulVecfl(td->axismtx, out);
}
}

@ -1493,90 +1493,88 @@ int BIF_do_manipulator(ScrArea *sa)
// drawflags still global, for drawing call above
drawflags= manipulator_selectbuf(sa, 0.2f*(float)U.tw_hotspot);
if(drawflags==0) drawflags= val;
switch(drawflags) {
case MAN_TRANS_C:
ManipulatorTransform(TFM_TRANSLATION);
break;
case MAN_TRANS_X:
if(G.qual & LR_SHIFTKEY) {
drawflags= MAN_TRANS_Y|MAN_TRANS_Z;
BIF_setDualAxisConstraint(v3d->twmat[1], v3d->twmat[2], " Y+Z");
if (drawflags & MAN_TRANS_C) {
initManipulator(TFM_TRANSLATION);
switch(drawflags) {
case MAN_TRANS_C:
break;
case MAN_TRANS_X:
if(G.qual & LR_SHIFTKEY) {
drawflags= MAN_TRANS_Y|MAN_TRANS_Z;
BIF_setDualAxisConstraint(v3d->twmat[1], v3d->twmat[2], " Y+Z");
}
else
BIF_setSingleAxisConstraint(v3d->twmat[0], " X");
break;
case MAN_TRANS_Y:
if(G.qual & LR_SHIFTKEY) {
drawflags= MAN_TRANS_X|MAN_TRANS_Z;
BIF_setDualAxisConstraint(v3d->twmat[0], v3d->twmat[2], " X+Z");
}
else
BIF_setSingleAxisConstraint(v3d->twmat[1], " Y");
break;
case MAN_TRANS_Z:
if(G.qual & LR_SHIFTKEY) {
drawflags= MAN_TRANS_X|MAN_TRANS_Y;
BIF_setDualAxisConstraint(v3d->twmat[0], v3d->twmat[1], " X+Y");
}
else
BIF_setSingleAxisConstraint(v3d->twmat[2], " Z");
break;
}
else
BIF_setSingleAxisConstraint(v3d->twmat[0], " X");
ManipulatorTransform(TFM_TRANSLATION);
break;
case MAN_TRANS_Y:
if(G.qual & LR_SHIFTKEY) {
drawflags= MAN_TRANS_X|MAN_TRANS_Z;
BIF_setDualAxisConstraint(v3d->twmat[0], v3d->twmat[2], " X+Z");
}
else
BIF_setSingleAxisConstraint(v3d->twmat[1], " Y");
ManipulatorTransform(TFM_TRANSLATION);
break;
case MAN_TRANS_Z:
if(G.qual & LR_SHIFTKEY) {
drawflags= MAN_TRANS_X|MAN_TRANS_Y;
BIF_setDualAxisConstraint(v3d->twmat[0], v3d->twmat[1], " X+Y");
}
else
BIF_setSingleAxisConstraint(v3d->twmat[2], " Z");
ManipulatorTransform(TFM_TRANSLATION);
break;
case MAN_SCALE_C:
ManipulatorTransform(TFM_RESIZE);
break;
case MAN_SCALE_X:
if(G.qual & LR_SHIFTKEY) {
drawflags= MAN_SCALE_Y|MAN_SCALE_Z;
BIF_setDualAxisConstraint(v3d->twmat[1], v3d->twmat[2], " Y+Z");
}
else
BIF_setSingleAxisConstraint(v3d->twmat[0], " X");
ManipulatorTransform(TFM_RESIZE);
break;
case MAN_SCALE_Y:
if(G.qual & LR_SHIFTKEY) {
drawflags= MAN_SCALE_X|MAN_SCALE_Z;
BIF_setDualAxisConstraint(v3d->twmat[0], v3d->twmat[2], " X+Z");
}
else
BIF_setSingleAxisConstraint(v3d->twmat[1], " Y");
ManipulatorTransform(TFM_RESIZE);
break;
case MAN_SCALE_Z:
if(G.qual & LR_SHIFTKEY) {
drawflags= MAN_SCALE_X|MAN_SCALE_Y;
BIF_setDualAxisConstraint(v3d->twmat[0], v3d->twmat[1], " X+Y");
}
else
BIF_setSingleAxisConstraint(v3d->twmat[2], " Z");
ManipulatorTransform(TFM_RESIZE);
break;
case MAN_ROT_X:
BIF_setSingleAxisConstraint(v3d->twmat[0], " X");
ManipulatorTransform(TFM_ROTATION);
break;
case MAN_ROT_Y:
BIF_setSingleAxisConstraint(v3d->twmat[1], " Y");
ManipulatorTransform(TFM_ROTATION);
break;
case MAN_ROT_Z:
BIF_setSingleAxisConstraint(v3d->twmat[2], " Z");
ManipulatorTransform(TFM_ROTATION);
break;
case MAN_ROT_T:
ManipulatorTransform(TFM_TRACKBALL);
break;
case MAN_ROT_V:
ManipulatorTransform(TFM_ROTATION);
break;
ManipulatorTransform();
}
else if (drawflags & MAN_SCALE_C) {
initManipulator(TFM_RESIZE);
switch(drawflags) {
case MAN_SCALE_X:
if(G.qual & LR_SHIFTKEY) {
drawflags= MAN_SCALE_Y|MAN_SCALE_Z;
BIF_setDualAxisConstraint(v3d->twmat[1], v3d->twmat[2], " Y+Z");
}
else
BIF_setSingleAxisConstraint(v3d->twmat[0], " X");
break;
case MAN_SCALE_Y:
if(G.qual & LR_SHIFTKEY) {
drawflags= MAN_SCALE_X|MAN_SCALE_Z;
BIF_setDualAxisConstraint(v3d->twmat[0], v3d->twmat[2], " X+Z");
}
else
BIF_setSingleAxisConstraint(v3d->twmat[1], " Y");
break;
case MAN_SCALE_Z:
if(G.qual & LR_SHIFTKEY) {
drawflags= MAN_SCALE_X|MAN_SCALE_Y;
BIF_setDualAxisConstraint(v3d->twmat[0], v3d->twmat[1], " X+Y");
}
else
BIF_setSingleAxisConstraint(v3d->twmat[2], " Z");
break;
}
ManipulatorTransform();
}
else if (drawflags == MAN_ROT_T) { /* trackbal need special case, init is different */
initManipulator(TFM_TRACKBALL);
ManipulatorTransform();
}
else if (drawflags & MAN_ROT_C) {
initManipulator(TFM_ROTATION);
switch(drawflags) {
case MAN_ROT_X:
BIF_setSingleAxisConstraint(v3d->twmat[0], " X");
break;
case MAN_ROT_Y:
BIF_setSingleAxisConstraint(v3d->twmat[1], " Y");
break;
case MAN_ROT_Z:
BIF_setSingleAxisConstraint(v3d->twmat[2], " Z");
break;
}
ManipulatorTransform();
}
}
/* after transform, restore drawflags */
drawflags= 0xFFFF;