Snappiness merged from trunk:
15455 15323 15322 15279 15243 15235 15180 15179 15178 15177 15176
This commit is contained in:
parent
da2fbc1a54
commit
c4f8536ec7
Binary file not shown.
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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] &&
|
||||
|
|
|
@ -293,7 +293,7 @@ typedef enum {
|
|||
ICON_ARMATURE_DEHLT,
|
||||
ICON_SNAP_GEAR,
|
||||
ICON_SNAP_GEO,
|
||||
ICON_BLANK41,
|
||||
ICON_SNAP_NORMAL,
|
||||
ICON_BLANK42,
|
||||
|
||||
ICON_SMOOTHCURVE,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -113,7 +113,6 @@ extern TransInfo Trans; /* From transform.c */
|
|||
|
||||
/* ************************** Functions *************************** */
|
||||
|
||||
|
||||
void getViewVector(float coord[3], float vec[3])
|
||||
{
|
||||
TransInfo *t = BIF_GetTransInfo();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue