Added control over distance to kept form target mesh

Quad bug was fixed by splitting the quads that are feed to RayTree
This commit is contained in:
Andre Susano Pinto
2008-05-02 22:09:01 +00:00
parent 9026559ded
commit 2b5432e6bb
5 changed files with 60 additions and 23 deletions

View File

@@ -48,6 +48,7 @@ typedef struct ShrinkwrapCalcData
float local2target[4][4];
float target2local[4][4];
float keptDist; //Distance to kept from target (units are in local space)
//float *weights; //weights of vertexs
unsigned char *moved; //boolean indicating if vertex has moved (TODO use bitmaps)

View File

@@ -6978,6 +6978,8 @@ static void shrinkwrapModifier_initData(ModifierData *md)
{
ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
smd->shrinkType = MOD_SHRINKWRAP_NEAREST_SURFACE;
smd->shrinkOpts = MOD_SHRINKWRAP_ALLOW_DEFAULT_NORMAL;
smd->keptDist = 0.0f;
}
static void shrinkwrapModifier_copyData(ModifierData *md, ModifierData *target)

View File

@@ -102,14 +102,15 @@ static float vertexgroup_get_weight(MDeformVert *dvert, int index, int vgroup)
if(dvert[index].dw[j].def_nr == vgroup)
return dvert[index].dw[j].weight;
}
return -1;
return 1.0;
}
/*
* Raytree from mesh
*/
static MVert *raytree_from_mesh_verts = NULL;
static float raytree_from_mesh_start[3] = { 1e10f, 1e10f, 1e10f };
static MFace *raytree_from_mesh_faces = NULL;
//static float raytree_from_mesh_start[3] = { 0.0f, 0.0f, 0.0f };
static int raytree_check_always(Isect *is, int ob, RayFace *face)
{
return TRUE;
@@ -117,21 +118,33 @@ static int raytree_check_always(Isect *is, int ob, RayFace *face)
static void raytree_from_mesh_get_coords(RayFace *face, float **v1, float **v2, float **v3, float **v4)
{
MFace *mface= (MFace*)face;
MFace *mface= raytree_from_mesh_faces + (int)face/2 - 1 ;
if(mface == NULL)
if(face == (RayFace*)(-1))
{
*v1 = raytree_from_mesh_start;
*v2 = raytree_from_mesh_start;
*v3 = raytree_from_mesh_start;
*v1 = NULL; //raytree_from_mesh_start;
*v2 = NULL; //raytree_from_mesh_start;
*v3 = NULL; //raytree_from_mesh_start;
*v4 = NULL;
return;
}
*v1= raytree_from_mesh_verts[mface->v1].co;
*v2= raytree_from_mesh_verts[mface->v2].co;
*v3= raytree_from_mesh_verts[mface->v3].co;
*v4= (mface->v4)? raytree_from_mesh_verts[mface->v4].co: NULL;
//Nasty quad splitting
if(((int)face) & 1) //we want the 2 triangle of the quad
{
assert(mface->v4);
*v1= raytree_from_mesh_verts[mface->v1].co;
*v2= raytree_from_mesh_verts[mface->v4].co;
*v3= raytree_from_mesh_verts[mface->v3].co;
*v4= NULL;
}
else
{
*v1= raytree_from_mesh_verts[mface->v1].co;
*v2= raytree_from_mesh_verts[mface->v2].co;
*v3= raytree_from_mesh_verts[mface->v3].co;
*v4= NULL;
}
}
/*
@@ -152,7 +165,10 @@ static RayTree* raytree_create_from_mesh(DerivedMesh *mesh)
int numFaces= mesh->getNumFaces(mesh);
MFace *face = mesh->getFaceDataArray(mesh, CD_MFACE);
int numVerts= mesh->getNumVerts(mesh);
//Initialize static vars
raytree_from_mesh_verts = mesh->getVertDataArray(mesh, CD_MVERT);
raytree_from_mesh_faces = face;
//calculate bounding box
@@ -165,9 +181,16 @@ static RayTree* raytree_create_from_mesh(DerivedMesh *mesh)
if(tree == NULL)
return NULL;
//Add faces to the RayTree
for(i=0; i<numFaces; i++)
RE_ray_tree_add_face(tree, 0, (RayFace*)(face+i));
//Add faces to the RayTree (RayTree uses face=0, with some special value to setup things)
for(i=1; i<=numFaces; i++)
{
RE_ray_tree_add_face(tree, 0, (RayFace*)(i*2) );
//Theres some nasty thing with non-coplanar quads (that I can't find the issue)
//so we split quads (an odd numbered face represents the second triangle of the quad)
if(face[i-1].v4)
RE_ray_tree_add_face(tree, 0, i*2+1);
}
RE_ray_tree_done(tree);
@@ -193,7 +216,7 @@ static float raytree_cast_ray(RayTree *tree, const float *coord, const float *di
isec.mode = RE_RAY_MIRROR; //We want closest intersection
isec.lay = -1;
isec.face_last = NULL;
isec.faceorig = NULL;
isec.faceorig = (RayFace*)(-1);
isec.labda = 1e10f;
VECCOPY(isec.start, coord);
@@ -429,6 +452,7 @@ static void shrinkwrap_calc_foreach_vertex(ShrinkwrapCalcData *calc, Shrinkwrap_
float orig[3], final[3]; //Coords relative to target
float normal[3];
float dist;
if(weight == 0.0f) continue; //Skip vertexs where we have no influence
@@ -444,9 +468,11 @@ static void shrinkwrap_calc_foreach_vertex(ShrinkwrapCalcData *calc, Shrinkwrap_
}
(callback)(calc->target, final, normal);
VecLerpf(final, orig, final, weight); //linear interpolation
VecMat4MulVecfl(final, calc->target2local, final);
VecMat4MulVecfl(vert[i].co, calc->target2local, final);
dist = VecLenf(vert[i].co, final);
if(dist > 1e-5) weight *= (dist - calc->keptDist)/dist;
VecLerpf(vert[i].co, vert[i].co, final, weight); //linear interpolation
}
}
@@ -484,7 +510,8 @@ DerivedMesh *shrinkwrapModifier_do(ShrinkwrapModifierData *smd, Object *ob, Deri
Mat4Invert (smd->target->imat, smd->target->obmat); //inverse is outdated
Mat4MulSerie(calc.local2target, smd->target->imat, ob->obmat, 0, 0, 0, 0, 0, 0);
Mat4Invert(calc.target2local, calc.local2target);
calc.keptDist = smd->keptDist; //TODO: smd->keptDist is in global units.. must change to local
}
calc.moved = NULL;
@@ -588,9 +615,11 @@ void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
if(t != -1)
{
float weight = 1.0f;
float dist;
VecMat4MulVecfl(nearest.co, calc->target2local, nearest.co);
dist = VecLenf(vert[i].co, tmp_co);
if(dist > 1e-5) weight *= (dist - calc->keptDist)/dist;
VecLerpf(vert[i].co, vert[i].co, nearest.co, weight); //linear interpolation
if(calc->moved)
@@ -643,8 +672,7 @@ void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc)
{
float dist = FLT_MAX;
float weight = vertexgroup_get_weight(dvert, i, vgroup);
// if(weight == 0.0f) continue;
weight = 1.0;
if(weight == 0.0f) continue;
//Transform coordinates local->target
VecMat4MulVecfl(tmp_co, calc->local2target, vert[i].co);
@@ -680,8 +708,13 @@ void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc)
if(ABS(dist) != FLT_MAX)
{
float dist_t;
VECADDFAC(tmp_co, tmp_co, tmp_no, dist);
VecMat4MulVecfl(tmp_co, calc->target2local, tmp_co);
dist_t = VecLenf(vert[i].co, tmp_co);
if(dist_t > 1e-5) weight *= (dist_t - calc->keptDist)/dist_t;
VecLerpf(vert[i].co, vert[i].co, tmp_co, weight); //linear interpolation
if(calc->moved)

View File

@@ -494,9 +494,9 @@ typedef struct ShrinkwrapModifierData {
struct Object *target; /* shrink target */
char vgroup_name[32]; /* optional vertexgroup name */
float keptDist; /* distance offset from mesh/projection point */
short shrinkType; /* shrink type projection */
short shrinkOpts; /* shrink options */
short pad[2];
} ShrinkwrapModifierData;
/* Shrinkwrap->shrinkType */

View File

@@ -1822,7 +1822,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
height = 94;
} else if (md->type==eModifierType_Shrinkwrap) {
ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
height = 67;
height = 86;
if (smd->shrinkType == MOD_SHRINKWRAP_NORMAL)
height += 19*2;
}
@@ -2452,6 +2452,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &smd->target, "Target to shrink to");
uiDefButF(block, NUM, B_MODIFIER_RECALC, "Offset:", lx,(cy-=19),buttonWidth,19, &smd->keptDist, 0.0f, 100.0f, 1.0f, 0, "Specify distance to kept from the target");
}
uiBlockEndAlign(block);