Merging volume embedding and transform snapping.
- Volume embed is available as a transform snap option (need new icon). Not as "continuous" as stroke embed, will have to be fixed somehow. - Transform snaps work in armature edit mode (only snap to mesh, not other armatures, for now). Adding to other edit data type should be easy. - Strokes can use all the transform snap options plus volume embed. Bug fix: added small threshold to face snap (and volume embed) to prevent slipping in cracks between faces. More tweaking needed but this now takes care of all the worst cases.
This commit is contained in:
@@ -394,6 +394,7 @@ int LineIntersectLine(float v1[3], float v2[3], float v3[3], float v4[3], float
|
||||
int LineIntersectLineStrict(float v1[3], float v2[3], float v3[3], float v4[3], float vi[3], float *lambda);
|
||||
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 RayIntersectsTriangleThreshold(float p1[3], float d[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv, float threshold);
|
||||
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]);
|
||||
|
||||
@@ -3896,6 +3896,57 @@ int RayIntersectsTriangle(float p1[3], float d[3], float v0[3], float v1[3], flo
|
||||
return 1;
|
||||
}
|
||||
|
||||
int RayIntersectsTriangleThreshold(float p1[3], float d[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv, float threshold)
|
||||
{
|
||||
float p[3], s[3], e1[3], e2[3], q[3];
|
||||
float a, f, u, v;
|
||||
float du = 0, dv = 0;
|
||||
|
||||
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);
|
||||
v = f * Inpf(d, q);
|
||||
|
||||
if (u < 0) du = u;
|
||||
if (u > 1) du = u - 1;
|
||||
if (v < 0) dv = v;
|
||||
if (v > 1) dv = v - 1;
|
||||
if (u > 0 && v > 0 && u + v > 1)
|
||||
{
|
||||
float t = u + v - 1;
|
||||
du = u - t/2;
|
||||
dv = v - t/2;
|
||||
}
|
||||
|
||||
VecMulf(e1, du);
|
||||
VecMulf(e2, dv);
|
||||
|
||||
if (Inpf(e1, e1) + Inpf(e2, e2) > threshold * threshold)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(uv) {
|
||||
uv[0]= u;
|
||||
uv[1]= v;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Adapted from the paper by Kasper Fauerby */
|
||||
/* "Improved Collision detection and Response" */
|
||||
static int getLowestRoot(float a, float b, float c, float maxR, float* root)
|
||||
|
||||
@@ -86,6 +86,7 @@ struct TransInfo;
|
||||
struct ScrArea;
|
||||
struct Base;
|
||||
struct Scene;
|
||||
struct Object;
|
||||
|
||||
struct TransInfo * BIF_GetTransInfo(void);
|
||||
void BIF_setSingleAxisConstraint(float vec[3], char *text);
|
||||
@@ -125,5 +126,30 @@ void ManipulatorTransform();
|
||||
int BIF_do_manipulator(struct ScrArea *sa);
|
||||
void BIF_draw_manipulator(struct ScrArea *sa);
|
||||
|
||||
/* Snapping */
|
||||
|
||||
|
||||
typedef struct DepthPeel
|
||||
{
|
||||
struct DepthPeel *next, *prev;
|
||||
|
||||
float depth;
|
||||
float p[3];
|
||||
float no[3];
|
||||
struct Object *ob;
|
||||
int flag;
|
||||
} DepthPeel;
|
||||
|
||||
struct ListBase;
|
||||
|
||||
typedef enum SnapMode
|
||||
{
|
||||
NOT_SELECTED = 0,
|
||||
NOT_ACTIVE = 1
|
||||
} SnapMode;
|
||||
|
||||
int snapObjects(int *dist, float *loc, float *no, SnapMode mode);
|
||||
int peelObjects(struct ListBase *depth_peels, short mval[2]);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -752,6 +752,7 @@ typedef struct Scene {
|
||||
#define SCE_SNAP_MODE_VERTEX 0
|
||||
#define SCE_SNAP_MODE_EDGE 1
|
||||
#define SCE_SNAP_MODE_FACE 2
|
||||
#define SCE_SNAP_MODE_VOLUME 3
|
||||
|
||||
/* sce->selectmode */
|
||||
#define SCE_SELECT_VERTEX 1 /* for mesh */
|
||||
|
||||
@@ -57,6 +57,8 @@
|
||||
#include "BIF_generate.h"
|
||||
#include "BIF_interface.h"
|
||||
|
||||
#include "BIF_transform.h"
|
||||
|
||||
#include "blendef.h"
|
||||
#include "mydevice.h"
|
||||
#include "reeb.h"
|
||||
@@ -418,224 +420,6 @@ void BIF_setTemplate(int index)
|
||||
}
|
||||
}
|
||||
|
||||
/******************** PEELING *********************************/
|
||||
|
||||
typedef struct SK_DepthPeel
|
||||
{
|
||||
struct SK_DepthPeel *next, *prev;
|
||||
|
||||
float depth;
|
||||
float p[3];
|
||||
float no[3];
|
||||
Object *ob;
|
||||
int flag;
|
||||
} SK_DepthPeel;
|
||||
|
||||
int cmpPeel(void *arg1, void *arg2)
|
||||
{
|
||||
SK_DepthPeel *p1 = arg1;
|
||||
SK_DepthPeel *p2 = arg2;
|
||||
int val = 0;
|
||||
|
||||
if (p1->depth < p2->depth)
|
||||
{
|
||||
val = -1;
|
||||
}
|
||||
else if (p1->depth > p2->depth)
|
||||
{
|
||||
val = 1;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void addDepthPeel(ListBase *depth_peels, float depth, float p[3], float no[3], Object *ob)
|
||||
{
|
||||
SK_DepthPeel *peel = MEM_callocN(sizeof(SK_DepthPeel), "DepthPeel");
|
||||
|
||||
peel->depth = depth;
|
||||
peel->ob = ob;
|
||||
VECCOPY(peel->p, p);
|
||||
VECCOPY(peel->no, no);
|
||||
|
||||
BLI_addtail(depth_peels, peel);
|
||||
|
||||
peel->flag = 0;
|
||||
}
|
||||
|
||||
int peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], ListBase *depth_peels)
|
||||
{
|
||||
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) {
|
||||
MVert *verts = dm->getVertArray(dm);
|
||||
MFace *faces = dm->getFaceArray(dm);
|
||||
int i;
|
||||
|
||||
for( i = 0; i < totface; i++) {
|
||||
MFace *f = faces + i;
|
||||
float lambda;
|
||||
int result;
|
||||
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
Mat3MulVecfl(timat, normal);
|
||||
Normalize(normal);
|
||||
|
||||
addDepthPeel(depth_peels, new_depth, location, normal, ob);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
Mat3MulVecfl(timat, normal);
|
||||
Normalize(normal);
|
||||
|
||||
addDepthPeel(depth_peels, new_depth, location, normal, ob);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int peelObjects(ListBase *depth_peels, short mval[2])
|
||||
{
|
||||
Base *base;
|
||||
int retval = 0;
|
||||
float ray_start[3], ray_normal[3];
|
||||
|
||||
viewray(mval, ray_start, ray_normal);
|
||||
|
||||
base= FIRSTBASE;
|
||||
for ( base = FIRSTBASE; base != NULL; base = base->next ) {
|
||||
if ( BASE_SELECTABLE(base) ) {
|
||||
Object *ob = base->object;
|
||||
|
||||
if (ob->transflag & OB_DUPLI)
|
||||
{
|
||||
DupliObject *dupli_ob;
|
||||
ListBase *lb = object_duplilist(G.scene, ob);
|
||||
|
||||
for(dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next)
|
||||
{
|
||||
Object *ob = dupli_ob->ob;
|
||||
|
||||
if (ob->type == OB_MESH) {
|
||||
DerivedMesh *dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH);
|
||||
int val;
|
||||
|
||||
val = peelDerivedMesh(ob, dm, dupli_ob->mat, ray_start, ray_normal, mval, depth_peels);
|
||||
|
||||
retval = retval || val;
|
||||
|
||||
dm->release(dm);
|
||||
}
|
||||
}
|
||||
|
||||
free_object_duplilist(lb);
|
||||
}
|
||||
|
||||
if (ob->type == OB_MESH) {
|
||||
DerivedMesh *dm = NULL;
|
||||
int val;
|
||||
|
||||
if (ob != G.obedit)
|
||||
{
|
||||
dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH);
|
||||
|
||||
val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels);
|
||||
}
|
||||
else
|
||||
{
|
||||
dm = editmesh_get_derived_cage(CD_MASK_BAREMESH);
|
||||
|
||||
val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels);
|
||||
}
|
||||
|
||||
retval = retval || val;
|
||||
|
||||
dm->release(dm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BLI_sortlist(depth_peels, cmpPeel);
|
||||
|
||||
return retval;
|
||||
}
|
||||
/*********************** CONVERSION ***************************/
|
||||
|
||||
void sk_autoname(ReebArc *arc)
|
||||
@@ -1087,6 +871,8 @@ void sk_filterStroke(SK_Stroke *stk, int start, int end)
|
||||
int nb_points = stk->nb_points;
|
||||
int i, j;
|
||||
|
||||
return;
|
||||
|
||||
if (start == -1)
|
||||
{
|
||||
start = 0;
|
||||
@@ -1783,99 +1569,120 @@ int sk_addStrokeSnapPoint(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
|
||||
|
||||
int sk_getStrokeEmbedPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
|
||||
{
|
||||
ListBase depth_peels;
|
||||
SK_DepthPeel *p1, *p2;
|
||||
float *last_p = NULL;
|
||||
float dist = FLT_MAX;
|
||||
float p[3];
|
||||
int point_added = 0;
|
||||
|
||||
depth_peels.first = depth_peels.last = NULL;
|
||||
|
||||
peelObjects(&depth_peels, dd->mval);
|
||||
|
||||
if (stk->nb_points > 0 && stk->points[stk->nb_points - 1].type == PT_CONTINUOUS)
|
||||
{
|
||||
last_p = stk->points[stk->nb_points - 1].p;
|
||||
}
|
||||
else if (LAST_SNAP_POINT_VALID)
|
||||
{
|
||||
last_p = LAST_SNAP_POINT;
|
||||
}
|
||||
|
||||
|
||||
for (p1 = depth_peels.first; p1; p1 = p1->next)
|
||||
{
|
||||
if (p1->flag == 0)
|
||||
{
|
||||
float vec[3];
|
||||
float new_dist;
|
||||
|
||||
p2 = NULL;
|
||||
p1->flag = 1;
|
||||
|
||||
/* if peeling objects, take the first and last from each object */
|
||||
if (G.scene->snap_flag & SCE_SNAP_PEEL_OBJECT)
|
||||
if (G.scene->snap_mode == SCE_SNAP_MODE_VOLUME)
|
||||
{
|
||||
ListBase depth_peels;
|
||||
DepthPeel *p1, *p2;
|
||||
float *last_p = NULL;
|
||||
float dist = FLT_MAX;
|
||||
float p[3];
|
||||
|
||||
depth_peels.first = depth_peels.last = NULL;
|
||||
|
||||
peelObjects(&depth_peels, dd->mval);
|
||||
|
||||
if (stk->nb_points > 0 && stk->points[stk->nb_points - 1].type == PT_CONTINUOUS)
|
||||
{
|
||||
last_p = stk->points[stk->nb_points - 1].p;
|
||||
}
|
||||
else if (LAST_SNAP_POINT_VALID)
|
||||
{
|
||||
last_p = LAST_SNAP_POINT;
|
||||
}
|
||||
|
||||
|
||||
for (p1 = depth_peels.first; p1; p1 = p1->next)
|
||||
{
|
||||
if (p1->flag == 0)
|
||||
{
|
||||
SK_DepthPeel *peel;
|
||||
for (peel = p1->next; peel; peel = peel->next)
|
||||
float vec[3];
|
||||
float new_dist;
|
||||
|
||||
p2 = NULL;
|
||||
p1->flag = 1;
|
||||
|
||||
/* if peeling objects, take the first and last from each object */
|
||||
if (G.scene->snap_flag & SCE_SNAP_PEEL_OBJECT)
|
||||
{
|
||||
if (peel->ob == p1->ob)
|
||||
DepthPeel *peel;
|
||||
for (peel = p1->next; peel; peel = peel->next)
|
||||
{
|
||||
peel->flag = 1;
|
||||
p2 = peel;
|
||||
if (peel->ob == p1->ob)
|
||||
{
|
||||
peel->flag = 1;
|
||||
p2 = peel;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* otherwise, pair first with second and so on */
|
||||
else
|
||||
{
|
||||
for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next)
|
||||
/* otherwise, pair first with second and so on */
|
||||
else
|
||||
{
|
||||
/* nothing to do here */
|
||||
for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next)
|
||||
{
|
||||
/* nothing to do here */
|
||||
}
|
||||
}
|
||||
|
||||
if (p2)
|
||||
{
|
||||
p2->flag = 1;
|
||||
|
||||
VecAddf(vec, p1->p, p2->p);
|
||||
VecMulf(vec, 0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
VECCOPY(vec, p1->p);
|
||||
}
|
||||
|
||||
if (last_p == NULL)
|
||||
{
|
||||
VECCOPY(p, vec);
|
||||
dist = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
new_dist = VecLenf(last_p, vec);
|
||||
|
||||
if (new_dist < dist)
|
||||
{
|
||||
VECCOPY(p, vec);
|
||||
dist = new_dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dist != FLT_MAX)
|
||||
{
|
||||
pt->type = dd->type;
|
||||
pt->mode = PT_EMBED;
|
||||
VECCOPY(pt->p, p);
|
||||
|
||||
if (p2)
|
||||
{
|
||||
p2->flag = 1;
|
||||
|
||||
VecAddf(vec, p1->p, p2->p);
|
||||
VecMulf(vec, 0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
VECCOPY(vec, p1->p);
|
||||
}
|
||||
point_added = 1;
|
||||
}
|
||||
|
||||
BLI_freelistN(&depth_peels);
|
||||
}
|
||||
else
|
||||
{
|
||||
float vec[3];
|
||||
float no[3];
|
||||
int found = 0;
|
||||
int dist = 40; // Use a user defined value here
|
||||
|
||||
found = snapObjects(&dist, vec, no, NOT_SELECTED);
|
||||
if (found == 1)
|
||||
{
|
||||
pt->type = dd->type;
|
||||
pt->mode = PT_EMBED;
|
||||
VECCOPY(pt->p, vec);
|
||||
|
||||
if (last_p == NULL)
|
||||
{
|
||||
VECCOPY(p, vec);
|
||||
dist = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
new_dist = VecLenf(last_p, vec);
|
||||
|
||||
if (new_dist < dist)
|
||||
{
|
||||
VECCOPY(p, vec);
|
||||
dist = new_dist;
|
||||
}
|
||||
point_added = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (dist != FLT_MAX)
|
||||
{
|
||||
pt->type = dd->type;
|
||||
pt->mode = PT_EMBED;
|
||||
VECCOPY(pt->p, p);
|
||||
|
||||
point_added = 1;
|
||||
}
|
||||
|
||||
BLI_freelistN(&depth_peels);
|
||||
|
||||
return point_added;
|
||||
}
|
||||
|
||||
|
||||
@@ -5218,6 +5218,7 @@ static char *snapmode_pup(void)
|
||||
str += sprintf(str, "%s", "|Vertex%x0");
|
||||
str += sprintf(str, "%s", "|Edge%x1");
|
||||
str += sprintf(str, "%s", "|Face%x2");
|
||||
str += sprintf(str, "%s", "|Volume%x3");
|
||||
return string;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_editVert.h"
|
||||
#include "BLI_blenlib.h"
|
||||
|
||||
#include "BDR_drawobject.h"
|
||||
|
||||
@@ -57,6 +58,8 @@
|
||||
#include "BIF_drawimage.h"
|
||||
#include "BIF_editmesh.h"
|
||||
|
||||
#include "BIF_transform.h"
|
||||
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_utildefines.h"
|
||||
#include "BKE_DerivedMesh.h"
|
||||
@@ -91,11 +94,6 @@ float RotationBetween(TransInfo *t, float p1[3], float p2[3]);
|
||||
float TranslationBetween(TransInfo *t, float p1[3], float p2[3]);
|
||||
float ResizeBetween(TransInfo *t, float p1[3], float p2[3]);
|
||||
|
||||
/* Modes */
|
||||
#define NOT_SELECTED 0
|
||||
#define NOT_ACTIVE 1
|
||||
int snapObjects(int *dist, float *loc, float *no, int mode);
|
||||
|
||||
|
||||
/****************** IMPLEMENTATIONS *********************/
|
||||
|
||||
@@ -103,7 +101,7 @@ int BIF_snappingSupported(void)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
if (G.obedit == NULL || G.obedit->type==OB_MESH) /* only support object or mesh */
|
||||
if (G.obedit == NULL || ELEM(G.obedit->type, OB_MESH, OB_ARMATURE)) /* only support object, mesh, armature */
|
||||
{
|
||||
status = 1;
|
||||
}
|
||||
@@ -277,7 +275,7 @@ void initSnapping(TransInfo *t)
|
||||
/* Edit mode */
|
||||
if (t->tsnap.applySnap != NULL && // A snapping function actually exist
|
||||
(G.scene->snap_flag & SCE_SNAP) && // Only if the snap flag is on
|
||||
(G.obedit != NULL && G.obedit->type==OB_MESH) && // Temporary limited to edit mode meshes
|
||||
(G.obedit != NULL && ELEM(G.obedit->type, OB_MESH, OB_ARMATURE)) && // Temporary limited to edit mode meshes and armatures
|
||||
((t->flag & T_PROP_EDIT) == 0) ) // No PET, obviously
|
||||
{
|
||||
t->tsnap.status |= SNAP_ON;
|
||||
@@ -481,87 +479,167 @@ void CalcSnapGrid(TransInfo *t, float *vec)
|
||||
|
||||
void CalcSnapGeometry(TransInfo *t, float *vec)
|
||||
{
|
||||
/* Object mode */
|
||||
if (G.obedit == NULL)
|
||||
if (t->spacetype == SPACE_VIEW3D)
|
||||
{
|
||||
if (t->spacetype == SPACE_VIEW3D)
|
||||
float loc[3];
|
||||
float no[3];
|
||||
int found = 0;
|
||||
int dist = 40; // Use a user defined value here
|
||||
SnapMode mode;
|
||||
|
||||
if (G.scene->snap_mode == SCE_SNAP_MODE_VOLUME)
|
||||
{
|
||||
float vec[3];
|
||||
float no[3];
|
||||
int found = 0;
|
||||
int dist = 40; // Use a user defined value here
|
||||
ListBase depth_peels;
|
||||
DepthPeel *p1, *p2;
|
||||
float *last_p = NULL;
|
||||
float dist = FLT_MAX;
|
||||
float p[3];
|
||||
short mval[2];
|
||||
|
||||
getmouseco_areawin(mval);
|
||||
|
||||
found = snapObjects(&dist, vec, no, NOT_SELECTED);
|
||||
if (found == 1)
|
||||
depth_peels.first = depth_peels.last = NULL;
|
||||
|
||||
peelObjects(&depth_peels, mval);
|
||||
|
||||
// if (stk->nb_points > 0 && stk->points[stk->nb_points - 1].type == PT_CONTINUOUS)
|
||||
// {
|
||||
// last_p = stk->points[stk->nb_points - 1].p;
|
||||
// }
|
||||
// else if (LAST_SNAP_POINT_VALID)
|
||||
// {
|
||||
// last_p = LAST_SNAP_POINT;
|
||||
// }
|
||||
|
||||
|
||||
for (p1 = depth_peels.first; p1; p1 = p1->next)
|
||||
{
|
||||
float tangent[3];
|
||||
|
||||
VecSubf(tangent, vec, t->tsnap.snapPoint);
|
||||
tangent[2] = 0;
|
||||
|
||||
if (Inpf(tangent, tangent) > 0)
|
||||
if (p1->flag == 0)
|
||||
{
|
||||
VECCOPY(t->tsnap.snapTangent, tangent);
|
||||
float vec[3];
|
||||
float new_dist;
|
||||
|
||||
p2 = NULL;
|
||||
p1->flag = 1;
|
||||
|
||||
/* if peeling objects, take the first and last from each object */
|
||||
if (G.scene->snap_flag & SCE_SNAP_PEEL_OBJECT)
|
||||
{
|
||||
DepthPeel *peel;
|
||||
for (peel = p1->next; peel; peel = peel->next)
|
||||
{
|
||||
if (peel->ob == p1->ob)
|
||||
{
|
||||
peel->flag = 1;
|
||||
p2 = peel;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* otherwise, pair first with second and so on */
|
||||
else
|
||||
{
|
||||
for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next)
|
||||
{
|
||||
/* nothing to do here */
|
||||
}
|
||||
}
|
||||
|
||||
if (p2)
|
||||
{
|
||||
p2->flag = 1;
|
||||
|
||||
VecAddf(vec, p1->p, p2->p);
|
||||
VecMulf(vec, 0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
VECCOPY(vec, p1->p);
|
||||
}
|
||||
|
||||
if (last_p == NULL)
|
||||
{
|
||||
VECCOPY(p, vec);
|
||||
dist = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
new_dist = VecLenf(last_p, vec);
|
||||
|
||||
if (new_dist < dist)
|
||||
{
|
||||
VECCOPY(p, vec);
|
||||
dist = new_dist;
|
||||
}
|
||||
}
|
||||
|
||||
VECCOPY(t->tsnap.snapPoint, vec);
|
||||
VECCOPY(t->tsnap.snapNormal, no);
|
||||
|
||||
t->tsnap.status |= POINT_INIT;
|
||||
}
|
||||
|
||||
if (dist != FLT_MAX)
|
||||
{
|
||||
VECCOPY(loc, p);
|
||||
found = 1;
|
||||
}
|
||||
|
||||
BLI_freelistN(&depth_peels);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (G.obedit == NULL)
|
||||
{
|
||||
mode = NOT_SELECTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
t->tsnap.status &= ~POINT_INIT;
|
||||
mode = NOT_ACTIVE;
|
||||
}
|
||||
|
||||
found = snapObjects(&dist, loc, no, NOT_SELECTED);
|
||||
}
|
||||
|
||||
if (found == 1)
|
||||
{
|
||||
float tangent[3];
|
||||
|
||||
VecSubf(tangent, loc, t->tsnap.snapPoint);
|
||||
tangent[2] = 0;
|
||||
|
||||
if (Inpf(tangent, tangent) > 0)
|
||||
{
|
||||
VECCOPY(t->tsnap.snapTangent, tangent);
|
||||
}
|
||||
|
||||
VECCOPY(t->tsnap.snapPoint, loc);
|
||||
VECCOPY(t->tsnap.snapNormal, no);
|
||||
|
||||
t->tsnap.status |= POINT_INIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
t->tsnap.status &= ~POINT_INIT;
|
||||
}
|
||||
}
|
||||
/* Mesh edit mode */
|
||||
else if (G.obedit != NULL && G.obedit->type==OB_MESH)
|
||||
{
|
||||
if (t->spacetype == SPACE_VIEW3D)
|
||||
else if (t->spacetype == SPACE_IMAGE && G.obedit != NULL && G.obedit->type==OB_MESH)
|
||||
{ /* same as above but for UV's */
|
||||
MTFace *nearesttf=NULL;
|
||||
float aspx, aspy;
|
||||
int face_corner;
|
||||
|
||||
find_nearest_uv(&nearesttf, NULL, NULL, &face_corner);
|
||||
|
||||
if (nearesttf != NULL)
|
||||
{
|
||||
float vec[3];
|
||||
float no[3];
|
||||
int found = 0;
|
||||
int dist = 40; // Use a user defined value here
|
||||
VECCOPY2D(t->tsnap.snapPoint, nearesttf->uv[face_corner]);
|
||||
|
||||
found = snapObjects(&dist, vec, no, NOT_ACTIVE);
|
||||
if (found == 1)
|
||||
{
|
||||
VECCOPY(t->tsnap.snapPoint, vec);
|
||||
VECCOPY(t->tsnap.snapNormal, no);
|
||||
|
||||
t->tsnap.status |= POINT_INIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
t->tsnap.status &= ~POINT_INIT;
|
||||
}
|
||||
}
|
||||
else if (t->spacetype == SPACE_IMAGE)
|
||||
{ /* same as above but for UV's */
|
||||
MTFace *nearesttf=NULL;
|
||||
float aspx, aspy;
|
||||
int face_corner;
|
||||
transform_aspect_ratio_tface_uv(&aspx, &aspy);
|
||||
t->tsnap.snapPoint[0] *= aspx;
|
||||
t->tsnap.snapPoint[1] *= aspy;
|
||||
|
||||
//Mat4MulVecfl(G.obedit->obmat, t->tsnap.snapPoint);
|
||||
|
||||
find_nearest_uv(&nearesttf, NULL, NULL, &face_corner);
|
||||
|
||||
if (nearesttf != NULL)
|
||||
{
|
||||
VECCOPY2D(t->tsnap.snapPoint, nearesttf->uv[face_corner]);
|
||||
|
||||
transform_aspect_ratio_tface_uv(&aspx, &aspy);
|
||||
t->tsnap.snapPoint[0] *= aspx;
|
||||
t->tsnap.snapPoint[1] *= aspy;
|
||||
|
||||
//Mat4MulVecfl(G.obedit->obmat, t->tsnap.snapPoint);
|
||||
|
||||
t->tsnap.status |= POINT_INIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
t->tsnap.status &= ~POINT_INIT;
|
||||
}
|
||||
t->tsnap.status |= POINT_INIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
t->tsnap.status &= ~POINT_INIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -824,7 +902,7 @@ int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta
|
||||
|
||||
if (test)
|
||||
{
|
||||
result = RayIntersectsTriangle(ray_start_local, ray_normal_local, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, &lambda, NULL);
|
||||
result = RayIntersectsTriangleThreshold(ray_start_local, ray_normal_local, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, &lambda, NULL, 0.001);
|
||||
|
||||
if (result) {
|
||||
float location[3], normal[3];
|
||||
@@ -868,7 +946,7 @@ int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta
|
||||
|
||||
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);
|
||||
result = RayIntersectsTriangleThreshold(ray_start_local, ray_normal_local, verts[f->v3].co, verts[f->v4].co, verts[f->v1].co, &lambda, NULL, 0.001);
|
||||
|
||||
if (result) {
|
||||
float location[3], normal[3];
|
||||
@@ -1149,7 +1227,7 @@ int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta
|
||||
return retval;
|
||||
}
|
||||
|
||||
int snapObjects(int *dist, float *loc, float *no, int mode) {
|
||||
int snapObjects(int *dist, float *loc, float *no, SnapMode mode) {
|
||||
Base *base;
|
||||
float depth = FLT_MAX;
|
||||
int retval = 0;
|
||||
@@ -1164,11 +1242,14 @@ int snapObjects(int *dist, float *loc, float *no, int mode) {
|
||||
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);
|
||||
if (ob->type == OB_MESH)
|
||||
{
|
||||
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;
|
||||
@@ -1227,6 +1308,238 @@ int snapObjects(int *dist, float *loc, float *no, int mode) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
/******************** PEELING *********************************/
|
||||
|
||||
|
||||
int cmpPeel(void *arg1, void *arg2)
|
||||
{
|
||||
DepthPeel *p1 = arg1;
|
||||
DepthPeel *p2 = arg2;
|
||||
int val = 0;
|
||||
|
||||
if (p1->depth < p2->depth)
|
||||
{
|
||||
val = -1;
|
||||
}
|
||||
else if (p1->depth > p2->depth)
|
||||
{
|
||||
val = 1;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void removeDoublesPeel(ListBase *depth_peels)
|
||||
{
|
||||
DepthPeel *peel;
|
||||
|
||||
for (peel = depth_peels->first; peel; peel = peel->next)
|
||||
{
|
||||
DepthPeel *next_peel = peel->next;
|
||||
|
||||
if (peel && next_peel && ABS(peel->depth - next_peel->depth) < 0.0015)
|
||||
{
|
||||
peel->next = next_peel->next;
|
||||
|
||||
if (next_peel->next)
|
||||
{
|
||||
next_peel->next->prev = peel;
|
||||
}
|
||||
|
||||
MEM_freeN(next_peel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void addDepthPeel(ListBase *depth_peels, float depth, float p[3], float no[3], Object *ob)
|
||||
{
|
||||
DepthPeel *peel = MEM_callocN(sizeof(DepthPeel), "DepthPeel");
|
||||
|
||||
peel->depth = depth;
|
||||
peel->ob = ob;
|
||||
VECCOPY(peel->p, p);
|
||||
VECCOPY(peel->no, no);
|
||||
|
||||
BLI_addtail(depth_peels, peel);
|
||||
|
||||
peel->flag = 0;
|
||||
}
|
||||
|
||||
int peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], ListBase *depth_peels)
|
||||
{
|
||||
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) {
|
||||
MVert *verts = dm->getVertArray(dm);
|
||||
MFace *faces = dm->getFaceArray(dm);
|
||||
int i;
|
||||
|
||||
for( i = 0; i < totface; i++) {
|
||||
MFace *f = faces + i;
|
||||
float lambda;
|
||||
int result;
|
||||
|
||||
|
||||
result = RayIntersectsTriangleThreshold(ray_start_local, ray_normal_local, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, &lambda, NULL, 0.001);
|
||||
|
||||
if (result) {
|
||||
float location[3], normal[3];
|
||||
float intersect[3];
|
||||
float new_depth;
|
||||
|
||||
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);
|
||||
|
||||
Mat3MulVecfl(timat, normal);
|
||||
Normalize(normal);
|
||||
|
||||
addDepthPeel(depth_peels, new_depth, location, normal, ob);
|
||||
}
|
||||
|
||||
if (f->v4 && result == 0)
|
||||
{
|
||||
result = RayIntersectsTriangleThreshold(ray_start_local, ray_normal_local, verts[f->v3].co, verts[f->v4].co, verts[f->v1].co, &lambda, NULL, 0.001);
|
||||
|
||||
if (result) {
|
||||
float location[3], normal[3];
|
||||
float intersect[3];
|
||||
float new_depth;
|
||||
|
||||
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);
|
||||
|
||||
Mat3MulVecfl(timat, normal);
|
||||
Normalize(normal);
|
||||
|
||||
addDepthPeel(depth_peels, new_depth, location, normal, ob);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int peelObjects(ListBase *depth_peels, short mval[2])
|
||||
{
|
||||
Base *base;
|
||||
int retval = 0;
|
||||
float ray_start[3], ray_normal[3];
|
||||
|
||||
viewray(mval, ray_start, ray_normal);
|
||||
|
||||
base= FIRSTBASE;
|
||||
for ( base = FIRSTBASE; base != NULL; base = base->next ) {
|
||||
if ( BASE_SELECTABLE(base) ) {
|
||||
Object *ob = base->object;
|
||||
|
||||
if (ob->transflag & OB_DUPLI)
|
||||
{
|
||||
DupliObject *dupli_ob;
|
||||
ListBase *lb = object_duplilist(G.scene, ob);
|
||||
|
||||
for(dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next)
|
||||
{
|
||||
Object *ob = dupli_ob->ob;
|
||||
|
||||
if (ob->type == OB_MESH) {
|
||||
DerivedMesh *dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH);
|
||||
int val;
|
||||
|
||||
val = peelDerivedMesh(ob, dm, dupli_ob->mat, ray_start, ray_normal, mval, depth_peels);
|
||||
|
||||
retval = retval || val;
|
||||
|
||||
dm->release(dm);
|
||||
}
|
||||
}
|
||||
|
||||
free_object_duplilist(lb);
|
||||
}
|
||||
|
||||
if (ob->type == OB_MESH) {
|
||||
DerivedMesh *dm = NULL;
|
||||
int val;
|
||||
|
||||
if (ob != G.obedit)
|
||||
{
|
||||
dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH);
|
||||
|
||||
val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels);
|
||||
}
|
||||
else
|
||||
{
|
||||
dm = editmesh_get_derived_cage(CD_MASK_BAREMESH);
|
||||
|
||||
val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels);
|
||||
}
|
||||
|
||||
retval = retval || val;
|
||||
|
||||
dm->release(dm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BLI_sortlist(depth_peels, cmpPeel);
|
||||
removeDoublesPeel(depth_peels);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*================================================================*/
|
||||
|
||||
static void applyGrid(TransInfo *t, float *val, int max_index, float fac[3], GearsType action);
|
||||
|
||||
Reference in New Issue
Block a user