Snappiness merged from trunk:

15455
	15323
	15322
	15279
	15243
	15235
	15180
	15179
	15178
	15177
	15176
This commit is contained in:
Martin Poirier 2008-07-10 00:09:43 +00:00
parent da2fbc1a54
commit c4f8536ec7
17 changed files with 3006 additions and 2429 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

View File

@ -108,6 +108,7 @@ void object_boundbox_flag(struct Object *ob, int flag, int set);
void minmax_object(struct Object *ob, float *min, float *max);
void minmax_object_duplis(struct Object *ob, float *min, float *max);
void solve_tracking (struct Object *ob, float targetmat[][4]);
int ray_hit_boundbox(struct BoundBox *bb, float ray_start[3], float ray_normal[3]);
void object_handle_update(struct Object *ob);

View File

@ -2382,3 +2382,31 @@ int give_obdata_texspace(Object *ob, int **texflag, float **loc, float **size, f
}
return 1;
}
/*
* Test a bounding box for ray intersection
* assumes the ray is already local to the boundbox space
*/
int ray_hit_boundbox(struct BoundBox *bb, float ray_start[3], float ray_normal[3])
{
static int triangle_indexes[12][3] = {{0, 1, 2}, {0, 2, 3},
{3, 2, 6}, {3, 6, 7},
{1, 2, 6}, {1, 6, 5},
{5, 6, 7}, {4, 5, 7},
{0, 3, 7}, {0, 4, 7},
{0, 1, 5}, {0, 4, 5}};
int result = 0;
int i;
for (i = 0; i < 12 && result == 0; i++)
{
float lambda;
int v1, v2, v3;
v1 = triangle_indexes[i][0];
v2 = triangle_indexes[i][1];
v3 = triangle_indexes[i][2];
result = RayIntersectsTriangle(ray_start, ray_normal, bb->vec[v1], bb->vec[v2], bb->vec[v3], &lambda, NULL);
}
return result;
}

View File

@ -261,6 +261,7 @@ void Vec2Addf(float *v, float *v1, float *v2);
void Vec2Subf(float *v, float *v1, float *v2);
void Vec2Copyf(float *v1, float *v2);
void AxisAngleToQuat(float *q, float *axis, float angle);
void vectoquat(float *vec, short axis, short upflag, float *q);
float VecAngle2(float *v1, float *v2);
@ -272,6 +273,8 @@ float NormalizedVecAngle2_2D(float *v1, float *v2);
void euler_rot(float *beul, float ang, char axis);
void NormalShortToFloat(float *out, short *in);
void NormalFloatToShort(short *out, float *in);
float DistVL2Dfl(float *v1, float *v2, float *v3);
float PdistVL2Dfl(float *v1, float *v2, float *v3);
@ -374,7 +377,9 @@ void LocQuatSizeToMat4(float mat[][4], float loc[3], float quat[4], float size[3
void tubemap(float x, float y, float z, float *u, float *v);
void spheremap(float x, float y, float z, float *u, float *v);
int LineIntersectLine(float v1[3], float v2[3], float v3[3], float v4[3], float i1[3], float i2[3]);
int LineIntersectsTriangle(float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv);
int RayIntersectsTriangle(float p1[3], float d[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv);
int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, float v0[3], float v1[3], float v2[3], float *lambda, float *ipoint);
int AxialLineIntersectsTriangle(int axis, float co1[3], float co2[3], float v0[3], float v1[3], float v2[3], float *lambda);
int AabbIntersectAabb(float min1[3], float max1[3], float min2[3], float max2[3]);

View File

@ -1335,6 +1335,22 @@ void NormalQuat(float *q)
}
}
void AxisAngleToQuat(float *q, float *axis, float angle)
{
float nor[3];
float si;
VecCopyf(nor, axis);
Normalize(nor);
angle /= 2;
si = (float)sin(angle);
q[0] = (float)cos(angle);
q[1] = nor[0] * si;
q[2] = nor[1] * si;
q[3] = nor[2] * si;
}
void vectoquat(float *vec, short axis, short upflag, float *q)
{
float q2[4], nor[3], *fp, mat[3][3], angle, si, co, x2, y2, z2, len1;
@ -2258,6 +2274,20 @@ double Sqrt3d(double d)
else return exp(log(d)/3);
}
void NormalShortToFloat(float *out, short *in)
{
out[0] = in[0] / 32767.0;
out[1] = in[1] / 32767.0;
out[2] = in[2] / 32767.0;
}
void NormalFloatToShort(short *out, float *in)
{
out[0] = (short)(in[0] * 32767.0);
out[1] = (short)(in[1] * 32767.0);
out[2] = (short)(in[2] * 32767.0);
}
/* distance v1 to line v2-v3 */
/* using Hesse formula, NO LINE PIECE! */
float DistVL2Dfl( float *v1, float *v2, float *v3) {
@ -3671,6 +3701,43 @@ int LineIntersectsTriangle(float p1[3], float p2[3], float v0[3], float v1[3], f
return 1;
}
/* moved from effect.c
test if the ray starting at p1 going in d direction intersects the triangle v0..v2
return non zero if it does
*/
int RayIntersectsTriangle(float p1[3], float d[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv)
{
float p[3], s[3], e1[3], e2[3], q[3];
float a, f, u, v;
VecSubf(e1, v1, v0);
VecSubf(e2, v2, v0);
Crossf(p, d, e2);
a = Inpf(e1, p);
if ((a > -0.000001) && (a < 0.000001)) return 0;
f = 1.0f/a;
VecSubf(s, p1, v0);
Crossf(q, s, e1);
*lambda = f * Inpf(e2, q);
if ((*lambda < 0.0)) return 0;
u = f * Inpf(s, p);
if ((u < 0.0)||(u > 1.0)) return 0;
v = f * Inpf(d, q);
if ((v < 0.0)||((u + v) > 1.0)) return 0;
if(uv) {
uv[0]= u;
uv[1]= v;
}
return 1;
}
/* Adapted from the paper by Kasper Fauerby */
/* "Improved Collision detection and Response" */
int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, float v0[3], float v1[3], float v2[3], float *lambda, float *ipoint)
@ -3965,6 +4032,74 @@ int AxialLineIntersectsTriangle(int axis, float p1[3], float p2[3], float v0[3],
return 1;
}
/* Returns the number of point of interests
* 0 - lines are colinear
* 1 - lines are coplanar, i1 is set to intersection
* 2 - i1 and i2 are the nearest points on line 1 (v1, v2) and line 2 (v3, v4) respectively
* */
int LineIntersectLine(float v1[3], float v2[3], float v3[3], float v4[3], float i1[3], float i2[3])
{
float a[3], b[3], c[3], ab[3], cb[3], dir1[3], dir2[3];
float d;
VecSubf(c, v3, v1);
VecSubf(a, v2, v1);
VecSubf(b, v4, v3);
VecCopyf(dir1, a);
Normalize(dir1);
VecCopyf(dir2, b);
Normalize(dir2);
d = Inpf(dir1, dir2);
if (d == 1.0f || d == -1.0f) {
/* colinear */
return 0;
}
Crossf(ab, a, b);
d = Inpf(c, ab);
/* test if the two lines are coplanar */
if (d > -0.000001f && d < 0.000001f) {
Crossf(cb, c, b);
VecMulf(a, Inpf(cb, ab) / Inpf(ab, ab));
VecAddf(i1, v1, a);
VecCopyf(i2, i1);
return 1; /* one intersection only */
}
/* if not */
else {
float n[3], t[3];
float v3t[3], v4t[3];
VecSubf(t, v1, v3);
/* offset between both plane where the lines lies */
Crossf(n, a, b);
Projf(t, t, n);
/* for the first line, offset the second line until it is coplanar */
VecAddf(v3t, v3, t);
VecAddf(v4t, v4, t);
VecSubf(c, v3t, v1);
VecSubf(a, v2, v1);
VecSubf(b, v4t, v3);
Crossf(ab, a, b);
Crossf(cb, c, b);
VecMulf(a, Inpf(cb, ab) / Inpf(ab, ab));
VecAddf(i1, v1, a);
/* for the second line, just substract the offset from the first intersection point */
VecSubf(i2, i1, t);
return 2; /* two nearest points */
}
}
int AabbIntersectAabb(float min1[3], float max1[3], float min2[3], float max2[3])
{
return (min1[0]<max2[0] && min1[1]<max2[1] && min1[2]<max2[2] &&

View File

@ -293,7 +293,7 @@ typedef enum {
ICON_ARMATURE_DEHLT,
ICON_SNAP_GEAR,
ICON_SNAP_GEO,
ICON_BLANK41,
ICON_SNAP_NORMAL,
ICON_BLANK42,
ICON_SMOOTHCURVE,

View File

@ -66,6 +66,8 @@ void project_int(float *vec, int *adr);
void project_int_noclip(float *vec, int *adr);
void project_float(float *vec, float *adr);
void project_float_noclip(float *vec, float *adr);
void viewray(short mval[2], float ray_start[3], float ray_normal[3]);
void viewline(short mval[2], float ray_start[3], float ray_end[3]);
int boundbox_clip(float obmat[][4], struct BoundBox *bb);
void fdrawline(float x1, float y1, float x2, float y2);

View File

@ -75,6 +75,8 @@ typedef struct TransSnap {
int status;
float snapPoint[3];
float snapTarget[3];
float snapNormal[3];
float snapTangent[3];
float dist; // Distance from snapPoint to snapTarget
double last;
void (*applySnap)(struct TransInfo *, float *);
@ -457,6 +459,8 @@ void applySnapping(TransInfo *t, float *vec);
void resetSnapping(TransInfo *t);
int handleSnapping(TransInfo *t, int event);
void drawSnapping(TransInfo *t);
int usingSnappingNormal(TransInfo *t);
int validSnappingNormal(TransInfo *t);
/*********************** Generics ********************************/
@ -487,6 +491,7 @@ void calculateCenterCursor2D(TransInfo *t);
void calculatePropRatio(TransInfo *t);
void getViewVector(float coord[3], float vec[3]);
void getViewRay(short mval[2], float p[3], float d[3]);
TransInfo * BIF_GetTransInfo(void);

View File

@ -543,8 +543,8 @@ typedef struct Scene {
ListBase markers;
ListBase transform_spaces;
short jumpframe, pad1;
short snap_flag, snap_target;
short jumpframe;
short snap_mode, snap_flag, snap_target;
/* none of the dependancy graph vars is mean to be saved */
struct DagForest *theDag;
@ -707,11 +707,16 @@ typedef struct Scene {
/* scene->snap_flag */
#define SCE_SNAP 1
#define SCE_SNAP_ROTATE 2
/* scene->snap_target */
#define SCE_SNAP_TARGET_CLOSEST 0
#define SCE_SNAP_TARGET_CENTER 1
#define SCE_SNAP_TARGET_MEDIAN 2
#define SCE_SNAP_TARGET_ACTIVE 3
/* scene->snap_mode */
#define SCE_SNAP_MODE_VERTEX 0
#define SCE_SNAP_MODE_EDGE 1
#define SCE_SNAP_MODE_FACE 2
/* sce->selectmode */
#define SCE_SELECT_VERTEX 1 /* for mesh */

View File

@ -1447,8 +1447,8 @@ PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args )
"vectors must be of the same size\n" ) );
if( vec1->size == 3 || vec1->size == 2) {
float a[3], b[3], c[3], ab[3], cb[3], dir1[3], dir2[3];
float d;
int result;
if (vec1->size == 3) {
VECCOPY(v1, vec1->vec);
VECCOPY(v2, vec2->vec);
@ -1472,63 +1472,19 @@ PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args )
v4[1] = vec4->vec[1];
v4[2] = 0.0f;
}
result = LineIntersectLine(v1, v2, v3, v4, i1, i2);
VecSubf(c, v3, v1);
VecSubf(a, v2, v1);
VecSubf(b, v4, v3);
VECCOPY(dir1, a);
Normalize(dir1);
VECCOPY(dir2, b);
Normalize(dir2);
d = Inpf(dir1, dir2);
if (d == 1.0f || d == -1.0f) {
if (result == 0) {
/* colinear */
return EXPP_incr_ret( Py_None );
}
Crossf(ab, a, b);
d = Inpf(c, ab);
/* test if the two lines are coplanar */
if (d > -0.000001f && d < 0.000001f) {
Crossf(cb, c, b);
VecMulf(a, Inpf(cb, ab) / Inpf(ab, ab));
VecAddf(i1, v1, a);
VECCOPY(i2, i1);
}
/* if not */
else {
float n[3], t[3];
VecSubf(t, v1, v3);
/* offset between both plane where the lines lies */
Crossf(n, a, b);
Projf(t, t, n);
/* for the first line, offset the second line until it is coplanar */
VecAddf(v3, v3, t);
VecAddf(v4, v4, t);
VecSubf(c, v3, v1);
VecSubf(a, v2, v1);
VecSubf(b, v4, v3);
Crossf(ab, a, b);
Crossf(cb, c, b);
VecMulf(a, Inpf(cb, ab) / Inpf(ab, ab));
VecAddf(i1, v1, a);
/* for the second line, just substract the offset from the first intersection point */
VecSubf(i2, i1, t);
tuple = PyTuple_New( 2 );
PyTuple_SetItem( tuple, 0, newVectorObject(i1, vec1->size, Py_NEW) );
PyTuple_SetItem( tuple, 1, newVectorObject(i2, vec1->size, Py_NEW) );
return tuple;
}
tuple = PyTuple_New( 2 );
PyTuple_SetItem( tuple, 0, newVectorObject(i1, vec1->size, Py_NEW) );
PyTuple_SetItem( tuple, 1, newVectorObject(i2, vec1->size, Py_NEW) );
return tuple;
}
else {
return ( EXPP_ReturnPyObjError( PyExc_TypeError,

File diff suppressed because it is too large Load Diff

View File

@ -2273,9 +2273,9 @@ static void brush_add(Object *ob, ParticleSystem *psys, short *mval, short numbe
ParticleEditSettings *pset= PE_settings();
ParticleEdit *edit = psys->edit;
int i, k, n = 0, totpart = psys->totpart;
short mco[2];
short dmx = 0, dmy = 0;
short mx = mval[0] - curarea->winx / 2, my = mval[1] - curarea->winy / 2;
float co1[3], co2[3], vec[4], min_d, imat[4][4];
float co1[3], co2[3], min_d, imat[4][4];
float framestep, timestep = psys_get_timestep(psys->part);
short size = pset->brush[PE_BRUSH_ADD].size;
short size2 = size*size;
@ -2302,35 +2302,9 @@ static void brush_add(Object *ob, ParticleSystem *psys, short *mval, short numbe
}
}
/* create intersection coordinates in view Z direction at mouse coordinates */
/* Thanks to who ever wrote the "Mouse Location 3D Space" tutorial in "Blender 3D: Blending Into Python/Cookbook". */
if(G.vd->persp != V3D_ORTHO){
vec[0]= (2.0f*(mx+dmx)/curarea->winx);
vec[1]= (2.0f*(my+dmy)/curarea->winy);
vec[2]= -1.0f;
vec[3]= 1.0f;
Mat4MulVec4fl(G.vd->persinv, vec);
VecMulf(vec, 1.0f/vec[3]);
VECCOPY(co1, G.vd->viewinv[3]);
VECSUB(vec, vec, co1);
Normalize(vec);
VECADDFAC(co1, G.vd->viewinv[3], vec, G.vd->near);
VECADDFAC(co2, G.vd->viewinv[3], vec, G.vd->far);
}
else {
vec[0] = 2.0f*(mx+dmx)/curarea->winx;
vec[1] = 2.0f*(my+dmy)/curarea->winy;
vec[2] = 0.0f;
vec[3] = 1.0f;
Mat4MulVec4fl(G.vd->persinv,vec);
VECADDFAC(co1,vec,G.vd->viewinv[2],1000.0f);
VECADDFAC(co2,vec,G.vd->viewinv[2],-1000.0f);
}
mco[0] = mval[0] + dmx;
mco[1] = mval[1] + dmy;
viewline(mco, co1, co2);
Mat4MulVecfl(imat,co1);
Mat4MulVecfl(imat,co2);

View File

@ -5071,6 +5071,18 @@ static char *ndof_pup(void)
}
static char *snapmode_pup(void)
{
static char string[512];
char *str = string;
str += sprintf(str, "%s", "Snap Mode: %t");
str += sprintf(str, "%s", "|Vertex%x0");
str += sprintf(str, "%s", "|Edge%x1");
str += sprintf(str, "%s", "|Face%x2");
return string;
}
static char *propfalloff_pup(void)
{
static char string[512];
@ -5698,6 +5710,10 @@ void view3d_buttons(void)
if (G.scene->snap_flag & SCE_SNAP) {
uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEO,xco,0,XIC,YIC, &G.scene->snap_flag, 0, 0, 0, 0, "Use Snap or Grid (Shift Tab)");
xco+= XIC;
uiDefIconButBitS(block, TOG, SCE_SNAP_ROTATE, B_REDR, ICON_SNAP_NORMAL,xco,0,XIC,YIC, &G.scene->snap_flag, 0, 0, 0, 0, "Align rotation with the snapping target");
xco+= XIC;
uiDefIconTextButS(block, ICONTEXTROW,B_REDR, ICON_VERTEXSEL, snapmode_pup(), xco,0,XIC+10,YIC, &(G.scene->snap_mode), 0.0, 0.0, 0, 0, "Snapping mode");
xco+= XIC;
uiDefButS(block, MENU, B_NOP, "Mode%t|Closest%x0|Center%x1|Median%x2|Active%x3",xco,0,70,YIC, &G.scene->snap_target, 0, 0, 0, 0, "Snap Target Mode");
xco+= 70;
} else {

View File

@ -2412,18 +2412,32 @@ void initRotation(TransInfo *t)
t->flag |= T_NO_CONSTRAINT;
}
static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3]) {
static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short around) {
float vec[3], totmat[3][3], smat[3][3];
float eul[3], fmat[3][3], quat[4];
float *center = t->center;
/* local constraint shouldn't alter center */
if (around == V3D_LOCAL) {
if (t->flag & (T_OBJECT|T_POSE)) {
center = td->center;
}
else {
/* !TODO! Make this if not rely on G */
if(around==V3D_LOCAL && (G.scene->selectmode & SCE_SELECT_FACE)) {
center = td->center;
}
}
}
if (t->flag & T_POINTS) {
Mat3MulMat3(totmat, mat, td->mtx);
Mat3MulMat3(smat, td->smtx, totmat);
VecSubf(vec, td->iloc, t->center);
VecSubf(vec, td->iloc, center);
Mat3MulVecfl(smat, vec);
VecAddf(td->loc, vec, t->center);
VecAddf(td->loc, vec, center);
VecSubf(vec,td->loc,td->iloc);
protectedTransBits(td->protectflag, vec);
@ -2460,13 +2474,13 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3]) {
Mat3CpyMat4(pmtx, t->poseobj->obmat);
Mat3Inv(imtx, pmtx);
VecSubf(vec, td->center, t->center);
VecSubf(vec, td->center, center);
Mat3MulVecfl(pmtx, vec); // To Global space
Mat3MulVecfl(mat, vec); // Applying rotation
Mat3MulVecfl(imtx, vec); // To Local space
VecAddf(vec, vec, t->center);
VecAddf(vec, vec, center);
/* vec now is the location where the object has to be */
VecSubf(vec, vec, td->center); // Translation needed from the initial location
@ -2495,9 +2509,9 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3]) {
}
else {
/* translation */
VecSubf(vec, td->center, t->center);
VecSubf(vec, td->center, center);
Mat3MulVecfl(mat, vec);
VecAddf(vec, vec, t->center);
VecAddf(vec, vec, center);
/* vec now is the location where the object has to be */
VecSubf(vec, vec, td->center);
Mat3MulVecfl(td->smtx, vec);
@ -2586,17 +2600,9 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3]) {
static void applyRotation(TransInfo *t, float angle, float axis[3])
{
TransData *td = t->data;
float mat[3][3], center[3];
float mat[3][3];
int i;
/* saving original center */
if (t->around == V3D_LOCAL) {
VECCOPY(center, t->center);
}
else {
center[0] = center[1] = center[2] = 0.0f;
}
VecRotToMat3(axis, angle, mat);
for(i = 0 ; i < t->total; i++, td++) {
@ -2607,18 +2613,6 @@ static void applyRotation(TransInfo *t, float angle, float axis[3])
if (td->flag & TD_SKIP)
continue;
/* local constraint shouldn't alter center */
if (t->around == V3D_LOCAL) {
if (t->flag & (T_OBJECT|T_POSE)) {
VECCOPY(t->center, td->center);
}
else {
if(G.vd->around==V3D_LOCAL && (G.scene->selectmode & SCE_SELECT_FACE)) {
VECCOPY(t->center, td->center);
}
}
}
if (t->con.applyRot) {
t->con.applyRot(t, td, axis, NULL);
VecRotToMat3(axis, angle * td->factor, mat);
@ -2627,12 +2621,7 @@ static void applyRotation(TransInfo *t, float angle, float axis[3])
VecRotToMat3(axis, angle * td->factor, mat);
}
ElementRotation(t, td, mat);
}
/* restoring original center */
if (t->around == V3D_LOCAL) {
VECCOPY(t->center, center);
ElementRotation(t, td, mat, t->around);
}
}
@ -2730,7 +2719,6 @@ static void applyTrackball(TransInfo *t, float axis1[3], float axis2[3], float a
{
TransData *td = t->data;
float mat[3][3], smat[3][3], totmat[3][3];
float center[3];
int i;
VecRotToMat3(axis1, angles[0], smat);
@ -2745,20 +2733,6 @@ static void applyTrackball(TransInfo *t, float axis1[3], float axis2[3], float a
if (td->flag & TD_SKIP)
continue;
VECCOPY(center, t->center);
if (t->around == V3D_LOCAL) {
/* local-mode shouldn't change center */
if (t->flag & (T_OBJECT|T_POSE)) {
VECCOPY(t->center, td->center);
}
else {
if(G.vd->around==V3D_LOCAL && (G.scene->selectmode & SCE_SELECT_FACE)) {
VECCOPY(t->center, td->center);
}
}
}
if (t->flag & T_PROP_EDIT) {
VecRotToMat3(axis1, td->factor * angles[0], smat);
VecRotToMat3(axis2, td->factor * angles[1], totmat);
@ -2766,9 +2740,7 @@ static void applyTrackball(TransInfo *t, float axis1[3], float axis2[3], float a
Mat3MulMat3(mat, smat, totmat);
}
ElementRotation(t, td, mat);
VECCOPY(t->center, center);
ElementRotation(t, td, mat, t->around);
}
}
@ -2943,6 +2915,36 @@ static void applyTranslation(TransInfo *t, float vec[3]) {
if (td->flag & TD_SKIP)
continue;
/* handle snapping rotation before doing the translation */
if (usingSnappingNormal(t))
{
if (validSnappingNormal(t))
{
float *original_normal = td->axismtx[2];
float axis[3];
float quat[4];
float mat[3][3];
float angle;
Crossf(axis, original_normal, t->tsnap.snapNormal);
angle = saacos(Inpf(original_normal, t->tsnap.snapNormal));
AxisAngleToQuat(quat, axis, angle);
QuatToMat3(quat, mat);
ElementRotation(t, td, mat, V3D_LOCAL);
}
else
{
float mat[3][3];
Mat3One(mat);
ElementRotation(t, td, mat, V3D_LOCAL);
}
}
if (t->con.applyVec) {
float pvec[3];
t->con.applyVec(t, td, vec, tvec, pvec);
@ -4157,7 +4159,7 @@ int Align(TransInfo *t, short mval[2])
Mat3MulMat3(mat, t->spacemtx, invmat);
ElementRotation(t, td, mat);
ElementRotation(t, td, mat, t->around);
}
/* restoring original center */

View File

@ -113,7 +113,6 @@ extern TransInfo Trans; /* From transform.c */
/* ************************** Functions *************************** */
void getViewVector(float coord[3], float vec[3])
{
TransInfo *t = BIF_GetTransInfo();

View File

@ -55,11 +55,13 @@
#include "BIF_screen.h"
#include "BIF_editsima.h"
#include "BIF_drawimage.h"
#include "BIF_editmesh.h"
#include "BKE_global.h"
#include "BKE_utildefines.h"
#include "BKE_DerivedMesh.h"
#include "BKE_object.h"
#include "BKE_anim.h" /* for duplis */
#include "BSE_view.h"
@ -92,7 +94,8 @@ float ResizeBetween(TransInfo *t, float p1[3], float p2[3]);
/* Modes */
#define NOT_SELECTED 0
#define NOT_ACTIVE 1
int findNearestVertFromObjects(int *dist, float *loc, int mode);
int snapObjects(int *dist, float *loc, float *no, int mode);
/****************** IMPLEMENTATIONS *********************/
@ -131,6 +134,15 @@ void drawSnapping(TransInfo *t)
glTranslatef(t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], t->tsnap.snapPoint[2]);
/* draw normal if needed */
if (usingSnappingNormal(t) && validSnappingNormal(t))
{
glBegin(GL_LINES);
glVertex3f(0, 0, 0);
glVertex3f(t->tsnap.snapNormal[0], t->tsnap.snapNormal[1], t->tsnap.snapNormal[2]);
glEnd();
}
/* sets view screen aligned */
glRotatef( -360.0f*saacos(G.vd->viewquat[0])/(float)M_PI, G.vd->viewquat[1], G.vd->viewquat[2], G.vd->viewquat[3]);
@ -201,7 +213,8 @@ void applySnapping(TransInfo *t, float *vec)
double current = PIL_check_seconds_timer();
// Time base quirky code to go around findnearest slowness
if (current - t->tsnap.last >= 0.25)
/* !TODO! add exception for object mode, no need to slow it down then */
if (current - t->tsnap.last >= 0.1)
{
t->tsnap.calcSnap(t, vec);
t->tsnap.targetSnap(t);
@ -222,6 +235,35 @@ void resetSnapping(TransInfo *t)
t->tsnap.modeTarget = 0;
t->tsnap.last = 0;
t->tsnap.applySnap = NULL;
t->tsnap.snapNormal[0] = 0;
t->tsnap.snapNormal[1] = 0;
t->tsnap.snapNormal[2] = 0;
}
int usingSnappingNormal(TransInfo *t)
{
if (G.scene->snap_flag & SCE_SNAP_ROTATE)
{
return 1;
}
else
{
return 0;
}
}
int validSnappingNormal(TransInfo *t)
{
if ((t->tsnap.status & (POINT_INIT|TARGET_INIT)) == (POINT_INIT|TARGET_INIT))
{
if (Inpf(t->tsnap.snapNormal, t->tsnap.snapNormal) > 0)
{
return 1;
}
}
return 0;
}
void initSnapping(TransInfo *t)
@ -445,14 +487,26 @@ void CalcSnapGeometry(TransInfo *t, float *vec)
if (t->spacetype == SPACE_VIEW3D)
{
float vec[3];
float no[3];
int found = 0;
int dist = 40; // Use a user defined value here
found = findNearestVertFromObjects(&dist, vec, NOT_SELECTED);
found = snapObjects(&dist, vec, no, NOT_SELECTED);
if (found == 1)
{
VECCOPY(t->tsnap.snapPoint, vec);
float tangent[3];
VecSubf(tangent, vec, t->tsnap.snapPoint);
tangent[2] = 0;
if (Inpf(tangent, tangent) > 0)
{
VECCOPY(t->tsnap.snapTangent, tangent);
}
VECCOPY(t->tsnap.snapPoint, vec);
VECCOPY(t->tsnap.snapNormal, no);
t->tsnap.status |= POINT_INIT;
}
else
@ -464,31 +518,18 @@ void CalcSnapGeometry(TransInfo *t, float *vec)
/* Mesh edit mode */
else if (G.obedit != NULL && G.obedit->type==OB_MESH)
{
/*if (G.scene->selectmode & B_SEL_VERT)*/
if (t->spacetype == SPACE_VIEW3D)
{
EditVert *nearest=NULL;
float vec[3];
float no[3];
int found = 0;
int dist = 40; // Use a user defined value here
// use findnearestverts in vert mode, others in other modes
nearest = findnearestvert(&dist, SELECT, 1);
found = findNearestVertFromObjects(&dist, vec, NOT_ACTIVE);
found = snapObjects(&dist, vec, no, NOT_ACTIVE);
if (found == 1)
{
VECCOPY(t->tsnap.snapPoint, vec);
t->tsnap.status |= POINT_INIT;
}
/* If there's no outside vertex nearer, but there's one in this mesh
*/
else if (nearest != NULL)
{
VECCOPY(t->tsnap.snapPoint, nearest->co);
Mat4MulVecfl(G.obedit->obmat, t->tsnap.snapPoint);
VECCOPY(t->tsnap.snapNormal, no);
t->tsnap.status |= POINT_INIT;
}
@ -522,33 +563,6 @@ void CalcSnapGeometry(TransInfo *t, float *vec)
t->tsnap.status &= ~POINT_INIT;
}
}
/*
if (G.scene->selectmode & B_SEL_EDGE)
{
EditEdge *nearest=NULL;
int dist = 50; // Use a user defined value here
// use findnearestverts in vert mode, others in other modes
nearest = findnearestedge(&dist);
if (nearest != NULL)
{
VecAddf(t->tsnap.snapPoint, nearest->v1->co, nearest->v2->co);
VecMulf(t->tsnap.snapPoint, 0.5f);
Mat4MulVecfl(G.obedit->obmat, t->tsnap.snapPoint);
t->tsnap.status |= POINT_INIT;
}
else
{
t->tsnap.status &= ~POINT_INIT;
}
}
*/
}
}
@ -723,101 +737,478 @@ void TargetSnapClosest(TransInfo *t)
}
/*================================================================*/
int findNearestVertFromObjects(int *dist, float *loc, int mode) {
int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], float *loc, float *no, int *dist, float *depth, short EditMesh)
{
int retval = 0;
int totvert = dm->getNumVerts(dm);
int totface = dm->getNumFaces(dm);
if (totvert > 0) {
float imat[4][4];
float timat[3][3]; /* transpose inverse matrix for normals */
float ray_start_local[3], ray_normal_local[3];
int test = 1;
Mat4Invert(imat, obmat);
Mat3CpyMat4(timat, imat);
Mat3Transp(timat);
VECCOPY(ray_start_local, ray_start);
VECCOPY(ray_normal_local, ray_normal);
Mat4MulVecfl(imat, ray_start_local);
Mat4Mul3Vecfl(imat, ray_normal_local);
/* If number of vert is more than an arbitrary limit,
* test against boundbox first
* */
if (totface > 16) {
struct BoundBox *bb = object_get_boundbox(ob);
test = ray_hit_boundbox(bb, ray_start_local, ray_normal_local);
}
if (test == 1) {
switch (G.scene->snap_mode)
{
case SCE_SNAP_MODE_FACE:
{
MVert *verts = dm->getVertArray(dm);
MFace *faces = dm->getFaceArray(dm);
int *index_array = NULL;
int index = 0;
int i;
if (EditMesh)
{
index_array = dm->getFaceDataArray(dm, CD_ORIGINDEX);
EM_init_index_arrays(0, 0, 1);
}
for( i = 0; i < totface; i++) {
EditFace *efa = NULL;
MFace *f = faces + i;
float lambda;
int result;
test = 1; /* reset for every face */
if (EditMesh)
{
if (index_array)
{
index = index_array[i];
}
else
{
index = i;
}
if (index == ORIGINDEX_NONE)
{
test = 0;
}
else
{
efa = EM_get_face_for_index(index);
if (efa && ((efa->v1->f & SELECT) || (efa->v2->f & SELECT) || (efa->v3->f & SELECT) || (efa->v4 && efa->v4->f & SELECT)))
{
test = 0;
}
}
}
if (test)
{
result = RayIntersectsTriangle(ray_start_local, ray_normal_local, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, &lambda, NULL);
if (result) {
float location[3], normal[3];
float intersect[3];
float new_depth;
int screen_loc[2];
int new_dist;
VECCOPY(intersect, ray_normal_local);
VecMulf(intersect, lambda);
VecAddf(intersect, intersect, ray_start_local);
VECCOPY(location, intersect);
if (f->v4)
CalcNormFloat4(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, verts[f->v4].co, normal);
else
CalcNormFloat(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, normal);
Mat4MulVecfl(obmat, location);
new_depth = VecLenf(location, ray_start);
project_int(location, screen_loc);
new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]);
if (new_dist <= *dist && new_depth < *depth)
{
*depth = new_depth;
retval = 1;
VECCOPY(loc, location);
VECCOPY(no, normal);
Mat3MulVecfl(timat, no);
Normalize(no);
*dist = new_dist;
}
}
if (f->v4 && result == 0)
{
result = RayIntersectsTriangle(ray_start_local, ray_normal_local, verts[f->v3].co, verts[f->v4].co, verts[f->v1].co, &lambda, NULL);
if (result) {
float location[3], normal[3];
float intersect[3];
float new_depth;
int screen_loc[2];
int new_dist;
VECCOPY(intersect, ray_normal_local);
VecMulf(intersect, lambda);
VecAddf(intersect, intersect, ray_start_local);
VECCOPY(location, intersect);
if (f->v4)
CalcNormFloat4(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, verts[f->v4].co, normal);
else
CalcNormFloat(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, normal);
Mat4MulVecfl(obmat, location);
new_depth = VecLenf(location, ray_start);
project_int(location, screen_loc);
new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]);
if (new_dist <= *dist && new_depth < *depth)
{
*depth = new_depth;
retval = 1;
VECCOPY(loc, location);
VECCOPY(no, normal);
Mat3MulVecfl(timat, no);
Normalize(no);
*dist = new_dist;
}
}
}
}
}
if (EditMesh)
{
EM_free_index_arrays();
}
break;
}
case SCE_SNAP_MODE_VERTEX:
{
MVert *verts = dm->getVertArray(dm);
int *index_array = NULL;
int index = 0;
int i;
if (EditMesh)
{
index_array = dm->getVertDataArray(dm, CD_ORIGINDEX);
EM_init_index_arrays(1, 0, 0);
}
for( i = 0; i < totvert; i++) {
EditVert *eve = NULL;
MVert *v = verts + i;
test = 1; /* reset for every vert */
if (EditMesh)
{
if (index_array)
{
index = index_array[i];
}
else
{
index = i;
}
if (index == ORIGINDEX_NONE)
{
test = 0;
}
else
{
eve = EM_get_vert_for_index(index);
if (eve && eve->f & SELECT)
{
test = 0;
}
}
}
if (test)
{
float dvec[3];
VecSubf(dvec, v->co, ray_start_local);
if (Inpf(ray_normal_local, dvec) > 0)
{
float location[3];
float new_depth;
int screen_loc[2];
int new_dist;
VECCOPY(location, v->co);
Mat4MulVecfl(obmat, location);
new_depth = VecLenf(location, ray_start);
project_int(location, screen_loc);
new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]);
if (new_dist <= *dist && new_depth < *depth)
{
*depth = new_depth;
retval = 1;
VECCOPY(loc, location);
NormalShortToFloat(no, v->no);
Mat3MulVecfl(timat, no);
Normalize(no);
*dist = new_dist;
}
}
}
}
if (EditMesh)
{
EM_free_index_arrays();
}
break;
}
case SCE_SNAP_MODE_EDGE:
{
MVert *verts = dm->getVertArray(dm);
MEdge *edges = dm->getEdgeArray(dm);
int totedge = dm->getNumEdges(dm);
int *index_array = NULL;
int index = 0;
int i;
if (EditMesh)
{
index_array = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
EM_init_index_arrays(0, 1, 0);
}
for( i = 0; i < totedge; i++) {
EditEdge *eed = NULL;
MEdge *e = edges + i;
test = 1; /* reset for every vert */
if (EditMesh)
{
if (index_array)
{
index = index_array[i];
}
else
{
index = i;
}
if (index == ORIGINDEX_NONE)
{
test = 0;
}
else
{
eed = EM_get_edge_for_index(index);
if (eed && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)))
{
test = 0;
}
}
}
if (test)
{
float intersect[3] = {0, 0, 0}, ray_end[3], dvec[3];
int result;
VECCOPY(ray_end, ray_normal_local);
VecMulf(ray_end, 2000);
VecAddf(ray_end, ray_start_local, ray_end);
result = LineIntersectLine(verts[e->v1].co, verts[e->v2].co, ray_start_local, ray_end, intersect, dvec); /* dvec used but we don't care about result */
if (result)
{
float edge_loc[3], vec[3];
float mul;
/* check for behind ray_start */
VecSubf(dvec, intersect, ray_start_local);
VecSubf(edge_loc, verts[e->v1].co, verts[e->v2].co);
VecSubf(vec, intersect, verts[e->v2].co);
mul = Inpf(vec, edge_loc) / Inpf(edge_loc, edge_loc);
if (mul > 1) {
mul = 1;
VECCOPY(intersect, verts[e->v1].co);
}
else if (mul < 0) {
mul = 0;
VECCOPY(intersect, verts[e->v2].co);
}
if (Inpf(ray_normal_local, dvec) > 0)
{
float location[3];
float new_depth;
int screen_loc[2];
int new_dist;
VECCOPY(location, intersect);
Mat4MulVecfl(obmat, location);
new_depth = VecLenf(location, ray_start);
project_int(location, screen_loc);
new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]);
if (new_dist <= *dist && new_depth < *depth)
{
float n1[3], n2[3];
*depth = new_depth;
retval = 1;
VecSubf(edge_loc, verts[e->v1].co, verts[e->v2].co);
VecSubf(vec, intersect, verts[e->v2].co);
mul = Inpf(vec, edge_loc) / Inpf(edge_loc, edge_loc);
NormalShortToFloat(n1, verts[e->v1].no);
NormalShortToFloat(n2, verts[e->v2].no);
VecLerpf(no, n2, n1, mul);
Normalize(no);
VECCOPY(loc, location);
Mat3MulVecfl(timat, no);
Normalize(no);
*dist = new_dist;
}
}
}
}
}
if (EditMesh)
{
EM_free_index_arrays();
}
break;
}
}
}
}
return retval;
}
int snapObjects(int *dist, float *loc, float *no, int mode) {
Base *base;
float depth = FLT_MAX;
int retval = 0;
short mval[2];
float ray_start[3], ray_normal[3];
getmouseco_areawin(mval);
viewray(mval, ray_start, ray_normal);
if (mode == NOT_ACTIVE)
{
DerivedMesh *dm;
Object *ob = G.obedit;
dm = editmesh_get_derived_cage(CD_MASK_BAREMESH);
retval = snapDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, loc, no, dist, &depth, 1);
dm->release(dm);
}
base= FIRSTBASE;
for ( base = FIRSTBASE; base != NULL; base = base->next ) {
if ( BASE_SELECTABLE(base) && ((mode == NOT_SELECTED && (base->flag & SELECT) == 0) || (mode == NOT_ACTIVE && base != BASACT)) ) {
Object *ob = base->object;
if (ob->type == OB_MESH) {
Mesh *me = ob->data;
if (ob->transflag & OB_DUPLI)
{
DupliObject *dupli_ob;
ListBase *lb = object_duplilist(G.scene, ob);
if (me->totvert > 0) {
int test = 1;
int i;
for(dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next)
{
Object *ob = dupli_ob->ob;
/* If number of vert is more than an arbitrary limit,
* test against boundbox first
* */
if (me->totvert > 16) {
struct BoundBox *bb = object_get_boundbox(ob);
if (ob->type == OB_MESH) {
DerivedMesh *dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH);
int val;
int minx = 0, miny = 0, maxx = 0, maxy = 0;
int i;
for (i = 0; i < 8; i++) {
float gloc[3];
int sloc[2];
VECCOPY(gloc, bb->vec[i]);
Mat4MulVecfl(ob->obmat, gloc);
project_int(gloc, sloc);
if (i == 0) {
minx = maxx = sloc[0];
miny = maxy = sloc[1];
}
else {
if (minx > sloc[0]) minx = sloc[0];
else if (maxx < sloc[0]) maxx = sloc[0];
if (miny > sloc[1]) miny = sloc[1];
else if (maxy < sloc[1]) maxy = sloc[1];
}
}
/* Pad with distance */
val = snapDerivedMesh(ob, dm, dupli_ob->mat, ray_start, ray_normal, mval, loc, no, dist, &depth, 0);
minx -= *dist;
miny -= *dist;
maxx += *dist;
maxy += *dist;
if (mval[0] > maxx || mval[0] < minx ||
mval[1] > maxy || mval[1] < miny) {
test = 0;
}
}
if (test == 1) {
float *verts = mesh_get_mapped_verts_nors(ob);
if (verts != NULL) {
float *fp;
fp = verts;
for( i = 0; i < me->totvert; i++, fp += 6) {
float gloc[3];
int sloc[2];
int curdist;
VECCOPY(gloc, fp);
Mat4MulVecfl(ob->obmat, gloc);
project_int(gloc, sloc);
sloc[0] -= mval[0];
sloc[1] -= mval[1];
curdist = abs(sloc[0]) + abs(sloc[1]);
if (curdist < *dist) {
*dist = curdist;
retval = 1;
VECCOPY(loc, gloc);
}
}
}
MEM_freeN(verts);
retval = retval || val;
dm->release(dm);
}
}
free_object_duplilist(lb);
}
if (ob->type == OB_MESH) {
DerivedMesh *dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH);
int val;
val = snapDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, loc, no, dist, &depth, 0);
retval = retval || val;
dm->release(dm);
}
}
}

View File

@ -144,6 +144,48 @@ void persp(int a)
}
}
/* create intersection ray in view Z direction at mouse coordinates */
void viewray(short mval[2], float ray_start[3], float ray_normal[3])
{
float ray_end[3];
viewline(mval, ray_start, ray_end);
VecSubf(ray_normal, ray_end, ray_start);
Normalize(ray_normal);
}
/* create intersection coordinates in view Z direction at mouse coordinates */
void viewline(short mval[2], float ray_start[3], float ray_end[3])
{
float vec[3];
if(G.vd->persp != V3D_ORTHO){
vec[0]= 2.0f * mval[0] / curarea->winx - 1;
vec[1]= 2.0f * mval[1] / curarea->winy - 1;
vec[2]= -1.0f;
vec[3]= 1.0f;
Mat4MulVec4fl(G.vd->persinv, vec);
VecMulf(vec, 1.0f / vec[3]);
VECCOPY(ray_start, G.vd->viewinv[3]);
VECSUB(vec, vec, ray_start);
Normalize(vec);
VECADDFAC(ray_start, G.vd->viewinv[3], vec, G.vd->near);
VECADDFAC(ray_end, G.vd->viewinv[3], vec, G.vd->far);
}
else {
vec[0] = 2.0f * mval[0] / curarea->winx - 1;
vec[1] = 2.0f * mval[1] / curarea->winy - 1;
vec[2] = 0.0f;
vec[3] = 1.0f;
Mat4MulVec4fl(G.vd->persinv, vec);
VECADDFAC(ray_start, vec, G.vd->viewinv[2], 1000.0f);
VECADDFAC(ray_end, vec, G.vd->viewinv[2], -1000.0f);
}
}
void initgrabz(float x, float y, float z)
{