Converted shrinkwrap to a DeformOnly modifier
*the options "remove faces", "merge" points were removed *made shrinkwrap work with CVs (curves and nurbs surfaces) *cleanup shrinkwrap code.. (removed bruteforces and raytree methods)
This commit is contained in:
@@ -53,7 +53,8 @@ typedef struct SpaceTransform
|
||||
|
||||
} SpaceTransform;
|
||||
|
||||
void space_transform_setup(SpaceTransform *data, struct Object *local, struct Object *target);
|
||||
void space_transform_from_matrixs(SpaceTransform *data, float local[][4], float target[][4]);
|
||||
#define space_transform_setup(data, local, target) space_transform_from_matrixs(data, (local)->obmat, (target)->obmat)
|
||||
|
||||
void space_transform_apply (const SpaceTransform *data, float *co);
|
||||
void space_transform_invert(const SpaceTransform *data, float *co);
|
||||
@@ -93,8 +94,7 @@ struct BVHTree* bvhtree_from_mesh_verts(struct BVHTreeFromMesh *data, struct Der
|
||||
// Builds a bvh tree where nodes are the faces of the given mesh. And configures BVHMesh if one is given.
|
||||
struct BVHTree* bvhtree_from_mesh_faces(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
|
||||
|
||||
|
||||
|
||||
int normal_projection_project_vertex(char options, const float *vert, const float *dir, const SpaceTransform *transf, BVHTree *tree, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata);
|
||||
|
||||
/* Shrinkwrap stuff */
|
||||
struct Object;
|
||||
@@ -109,18 +109,15 @@ typedef struct ShrinkwrapCalcData
|
||||
ShrinkwrapModifierData *smd; //shrinkwrap modifier data
|
||||
|
||||
struct Object *ob; //object we are applying shrinkwrap to
|
||||
struct DerivedMesh *original; //mesh before shrinkwrap (TODO clean this variable.. we don't really need it)
|
||||
struct BVHTree *original_tree; //BVHTree build with the original mesh (to be used on kept volume)
|
||||
struct BVHMeshCallbackUserdata *callback;
|
||||
struct DerivedMesh *original; //mesh before shrinkwrap
|
||||
|
||||
struct DerivedMesh *final; //initially a copy of original mesh.. mesh thats going to be shrinkwrapped
|
||||
float (*vertexCos)[3]; //vertexs being shrinkwraped
|
||||
int numVerts;
|
||||
|
||||
struct DerivedMesh *target; //mesh we are shrinking to
|
||||
|
||||
SpaceTransform local2target;
|
||||
struct DerivedMesh *target; //mesh we are shrinking to
|
||||
SpaceTransform local2target; //transform to move bettwem local and target space
|
||||
|
||||
float keptDist; //Distance to kept from target (units are in local space)
|
||||
//float *weights; //weights of vertexs
|
||||
BitSet moved; //BitSet indicating if vertex has moved
|
||||
|
||||
} ShrinkwrapCalcData;
|
||||
@@ -130,6 +127,7 @@ void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *data);
|
||||
void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *data);
|
||||
|
||||
struct DerivedMesh *shrinkwrapModifier_do(struct ShrinkwrapModifierData *smd, struct Object *ob, struct DerivedMesh *dm, int useRenderParams, int isFinalCalc);
|
||||
void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd, struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3], int numVerts);
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -7198,7 +7198,6 @@ static void shrinkwrapModifier_initData(ModifierData *md)
|
||||
smd->shrinkType = MOD_SHRINKWRAP_NEAREST_SURFACE;
|
||||
smd->shrinkOpts = MOD_SHRINKWRAP_ALLOW_DEFAULT_NORMAL;
|
||||
smd->keptDist = 0.0f;
|
||||
smd->mergeDist = 0.0f;
|
||||
|
||||
smd->target = 0;
|
||||
smd->cutPlane = 0;
|
||||
@@ -7213,7 +7212,6 @@ static void shrinkwrapModifier_copyData(ModifierData *md, ModifierData *target)
|
||||
tsmd->cutPlane = smd->cutPlane;
|
||||
strcpy(tsmd->vgroup_name, smd->vgroup_name);
|
||||
tsmd->keptDist = smd->keptDist;
|
||||
tsmd->mergeDist = smd->mergeDist;
|
||||
tsmd->shrinkType = smd->shrinkType;
|
||||
tsmd->shrinkOpts = smd->shrinkOpts;
|
||||
}
|
||||
@@ -7243,7 +7241,7 @@ static void shrinkwrapModifier_foreachObjectLink(ModifierData *md, Object *ob, O
|
||||
walk(userData, ob, &smd->target);
|
||||
walk(userData, ob, &smd->cutPlane);
|
||||
}
|
||||
|
||||
/*
|
||||
static DerivedMesh *shrinkwrapModifier_applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData, int useRenderParams, int isFinalCalc)
|
||||
{
|
||||
return shrinkwrapModifier_do((ShrinkwrapModifierData*)md,ob,derivedData,useRenderParams,isFinalCalc);
|
||||
@@ -7253,6 +7251,26 @@ static DerivedMesh *shrinkwrapModifier_applyModifierEM(ModifierData *md, Object
|
||||
{
|
||||
return shrinkwrapModifier_do((ShrinkwrapModifierData*)md,ob,derivedData,0,0);
|
||||
}
|
||||
*/
|
||||
static void shrinkwrapModifier_deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
|
||||
{
|
||||
shrinkwrapModifier_deform((ShrinkwrapModifierData*)md, ob, derivedData, vertexCos, numVerts);
|
||||
}
|
||||
|
||||
static void shrinkwrapModifier_deformVertsEM(ModifierData *md, Object *ob, EditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
|
||||
{
|
||||
DerivedMesh *dm;
|
||||
|
||||
if(!derivedData && ob->type == OB_MESH)
|
||||
dm = CDDM_from_editmesh(editData, ob->data);
|
||||
else
|
||||
dm = CDDM_copy(derivedData); //TODO: this is only needed if derevedData doenst supports getVertexArray
|
||||
|
||||
shrinkwrapModifier_deform((ShrinkwrapModifierData*)md, ob, dm, vertexCos, numVerts);
|
||||
|
||||
if(dm != derivedData)
|
||||
dm->release(dm);
|
||||
}
|
||||
|
||||
static void shrinkwrapModifier_updateDepgraph(ModifierData *md, DagForest *forest, Object *ob, DagNode *obNode)
|
||||
{
|
||||
@@ -7645,8 +7663,9 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
|
||||
mti->applyModifier = explodeModifier_applyModifier;
|
||||
|
||||
mti = INIT_TYPE(Shrinkwrap);
|
||||
mti->type = eModifierTypeType_Nonconstructive;
|
||||
mti->type = eModifierTypeType_OnlyDeform;
|
||||
mti->flags = eModifierTypeFlag_AcceptsMesh
|
||||
| eModifierTypeFlag_AcceptsCVs
|
||||
| eModifierTypeFlag_SupportsEditmode
|
||||
| eModifierTypeFlag_EnableInEditmode;
|
||||
|
||||
@@ -7655,8 +7674,8 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
|
||||
mti->requiredDataMask = shrinkwrapModifier_requiredDataMask;
|
||||
mti->isDisabled = shrinkwrapModifier_isDisabled;
|
||||
mti->foreachObjectLink = shrinkwrapModifier_foreachObjectLink;
|
||||
mti->applyModifier = shrinkwrapModifier_applyModifier;
|
||||
mti->applyModifierEM = shrinkwrapModifier_applyModifierEM;
|
||||
mti->deformVerts = shrinkwrapModifier_deformVerts;
|
||||
mti->deformVertsEM = shrinkwrapModifier_deformVertsEM;
|
||||
mti->updateDepgraph = shrinkwrapModifier_updateDepgraph;
|
||||
|
||||
mti = INIT_TYPE(SimpleDeform);
|
||||
|
@@ -136,10 +136,11 @@ static float sphereray_tri_intersection(const BVHTreeRay *ray, float radius, con
|
||||
}
|
||||
|
||||
/* Space transform */
|
||||
void space_transform_setup(SpaceTransform *data, struct Object *local, struct Object *target)
|
||||
void space_transform_from_matrixs(SpaceTransform *data, float local[4][4], float target[4][4])
|
||||
{
|
||||
Mat4Invert(target->imat, target->obmat); //Invserse might be outdated
|
||||
Mat4MulSerie(data->local2target, target->imat, local->obmat, 0, 0, 0, 0, 0, 0);
|
||||
float itarget[4][4];
|
||||
Mat4Invert(itarget, target); //Invserse might be outdated
|
||||
Mat4MulSerie(data->local2target, itarget, local, 0, 0, 0, 0, 0, 0);
|
||||
Mat4Invert(data->target2local, data->local2target);
|
||||
}
|
||||
|
||||
@@ -348,142 +349,9 @@ static void mesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *r
|
||||
t3 = NULL;
|
||||
|
||||
} while(t2);
|
||||
|
||||
//return hit->dist;
|
||||
}
|
||||
|
||||
/*
|
||||
* Raytree from mesh
|
||||
*/
|
||||
static MVert *raytree_from_mesh_verts = NULL;
|
||||
static MFace *raytree_from_mesh_faces = NULL;
|
||||
|
||||
static int raytree_check_always(Isect *is, int ob, RayFace *face)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void raytree_from_mesh_get_coords(RayFace *face, float **v1, float **v2, float **v3, float **v4)
|
||||
{
|
||||
MFace *mface= raytree_from_mesh_faces + (int)face/2 - 1 ;
|
||||
|
||||
if(face == (RayFace*)(-1))
|
||||
{
|
||||
*v1 = NULL;
|
||||
*v2 = NULL;
|
||||
*v3 = NULL;
|
||||
*v4 = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
//Nasty quad splitting
|
||||
if(((int)face) & 1) // we want the 2 triangle of the quad
|
||||
{
|
||||
*v1= raytree_from_mesh_verts[mface->v1].co;
|
||||
*v2= raytree_from_mesh_verts[mface->v3].co;
|
||||
*v3= raytree_from_mesh_verts[mface->v4].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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a raytree from the given mesh
|
||||
* No copy of the mesh is done, so it must exist and remain
|
||||
* imutable as long the tree is intended to be used
|
||||
*
|
||||
* No more than 1 raytree can exist.. since this code uses a static variable
|
||||
* to pass data to raytree_from_mesh_get_coords
|
||||
*/
|
||||
static RayTree* raytree_create_from_mesh(DerivedMesh *mesh)
|
||||
{
|
||||
int i;
|
||||
float min[3], max[3];
|
||||
|
||||
RayTree*tree= NULL;
|
||||
|
||||
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
|
||||
INIT_MINMAX(min, max);
|
||||
|
||||
for(i=0; i<numVerts; i++)
|
||||
DO_MINMAX(raytree_from_mesh_verts[i].co, min, max);
|
||||
|
||||
tree = RE_ray_tree_create(64, numFaces, min, max, raytree_from_mesh_get_coords, raytree_check_always, NULL, NULL);
|
||||
if(tree == NULL)
|
||||
return NULL;
|
||||
|
||||
//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, (RayFace*)(i*2+1));
|
||||
}
|
||||
|
||||
RE_ray_tree_done(tree);
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
static void free_raytree_from_mesh(RayTree *tree)
|
||||
{
|
||||
raytree_from_mesh_verts = NULL;
|
||||
RE_ray_tree_free(tree);
|
||||
}
|
||||
|
||||
/*
|
||||
* Cast a ray on the specified direction
|
||||
* Returns the distance the ray must travel until intersect something
|
||||
* Returns FLT_MAX in case of nothing intersection
|
||||
* if facenormal is given, it will be overwritted with the normal of the face the ray collided with
|
||||
*/
|
||||
static float raytree_cast_ray(RayTree *tree, const float *coord, const float *direction, float *facenormal)
|
||||
{
|
||||
Isect isec;
|
||||
float *v1, *v2, *v3, *v4;
|
||||
|
||||
/* Setup intersection */
|
||||
isec.mode = RE_RAY_MIRROR; /* We want closest intersection */
|
||||
isec.lay = -1;
|
||||
isec.face_last = NULL;
|
||||
isec.faceorig = (RayFace*)(-1);
|
||||
isec.labda = 1e10f;
|
||||
|
||||
VECCOPY(isec.start, coord);
|
||||
VECCOPY(isec.vec, direction);
|
||||
VECADDFAC(isec.end, isec.start, isec.vec, isec.labda);
|
||||
|
||||
if(!RE_ray_tree_intersect(tree, &isec))
|
||||
return FLT_MAX;
|
||||
|
||||
if(facenormal)
|
||||
{
|
||||
raytree_from_mesh_get_coords( isec.face, &v1, &v2, &v3, &v4);
|
||||
CalcNormFloat(v1, v2, v3, facenormal);
|
||||
}
|
||||
|
||||
isec.labda = ABS(isec.labda);
|
||||
VECADDFAC(isec.end, isec.start, isec.vec, isec.labda);
|
||||
return VecLenf((float*)coord, (float*)isec.end);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the squared distance between two given points
|
||||
@@ -760,174 +628,6 @@ static float nearest_point_in_tri_surface(const float *point, const float *v0, c
|
||||
return plane_sdist + normal_dist*normal_dist;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Shrink to nearest surface point on target mesh
|
||||
*/
|
||||
static void bruteforce_shrinkwrap_calc_nearest_surface_point(DerivedMesh *target, float *co, float *unused)
|
||||
{
|
||||
float minDist = FLT_MAX;
|
||||
float orig_co[3];
|
||||
|
||||
int i;
|
||||
int numFaces = target->getNumFaces(target);
|
||||
MVert *vert = target->getVertDataArray(target, CD_MVERT);
|
||||
MFace *face = target->getFaceDataArray(target, CD_MFACE);
|
||||
|
||||
VECCOPY(orig_co, co);
|
||||
|
||||
for (i = 0; i < numFaces; i++)
|
||||
{
|
||||
float *v0, *v1, *v2, *v3;
|
||||
|
||||
v0 = vert[ face[i].v1 ].co;
|
||||
v1 = vert[ face[i].v2 ].co;
|
||||
v2 = vert[ face[i].v3 ].co;
|
||||
v3 = face[i].v4 ? vert[ face[i].v4 ].co : 0;
|
||||
|
||||
while(v2)
|
||||
{
|
||||
float dist;
|
||||
float tmp[3];
|
||||
|
||||
dist = nearest_point_in_tri_surface(orig_co, v0, v1, v2, tmp);
|
||||
|
||||
if(dist < minDist)
|
||||
{
|
||||
minDist = dist;
|
||||
VECCOPY(co, tmp);
|
||||
}
|
||||
|
||||
v1 = v2;
|
||||
v2 = v3;
|
||||
v3 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Projects the vertex on the normal direction over the target mesh
|
||||
*/
|
||||
static void bruteforce_shrinkwrap_calc_normal_projection(DerivedMesh *target, float *co, float *vnormal)
|
||||
{
|
||||
//TODO: this should use raycast code probably existent in blender
|
||||
float minDist = FLT_MAX;
|
||||
float orig_co[3];
|
||||
|
||||
int i;
|
||||
int numFaces = target->getNumFaces(target);
|
||||
MVert *vert = target->getVertDataArray(target, CD_MVERT);
|
||||
MFace *face = target->getFaceDataArray(target, CD_MFACE);
|
||||
|
||||
VECCOPY(orig_co, co);
|
||||
|
||||
for (i = 0; i < numFaces; i++)
|
||||
{
|
||||
float *v0, *v1, *v2, *v3;
|
||||
|
||||
v0 = vert[ face[i].v1 ].co;
|
||||
v1 = vert[ face[i].v2 ].co;
|
||||
v2 = vert[ face[i].v3 ].co;
|
||||
v3 = face[i].v4 ? vert[ face[i].v4 ].co : 0;
|
||||
|
||||
while(v2)
|
||||
{
|
||||
float dist;
|
||||
float pnormal[3];
|
||||
|
||||
CalcNormFloat(v0, v1, v2, pnormal);
|
||||
dist = ray_intersect_plane(orig_co, vnormal, v0, pnormal);
|
||||
|
||||
if(fabs(dist) < minDist)
|
||||
{
|
||||
float tmp[3], nearest[3];
|
||||
VECADDFAC(tmp, orig_co, vnormal, dist);
|
||||
|
||||
if( fabs(nearest_point_in_tri_surface(tmp, v0, v1, v2, nearest)) < 0.0001)
|
||||
{
|
||||
minDist = fabs(dist);
|
||||
VECCOPY(co, nearest);
|
||||
}
|
||||
}
|
||||
v1 = v2;
|
||||
v2 = v3;
|
||||
v3 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Shrink to nearest vertex on target mesh
|
||||
*/
|
||||
static void bruteforce_shrinkwrap_calc_nearest_vertex(DerivedMesh *target, float *co, float *unused)
|
||||
{
|
||||
float minDist = FLT_MAX;
|
||||
float orig_co[3];
|
||||
|
||||
int i;
|
||||
int numVerts = target->getNumVerts(target);
|
||||
MVert *vert = target->getVertDataArray(target, CD_MVERT);
|
||||
|
||||
VECCOPY(orig_co, co);
|
||||
|
||||
for (i = 0; i < numVerts; i++)
|
||||
{
|
||||
float sdist = squared_dist( orig_co, vert[i].co);
|
||||
|
||||
if(sdist < minDist)
|
||||
{
|
||||
minDist = sdist;
|
||||
VECCOPY(co, vert[i].co);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void shrinkwrap_calc_foreach_vertex(ShrinkwrapCalcData *calc, Shrinkwrap_ForeachVertexCallback callback)
|
||||
{
|
||||
int i;
|
||||
int vgroup = get_named_vertexgroup_num(calc->ob, calc->smd->vgroup_name);
|
||||
int numVerts = 0;
|
||||
|
||||
MDeformVert *dvert = NULL;
|
||||
MVert *vert = NULL;
|
||||
|
||||
numVerts = calc->final->getNumVerts(calc->final);
|
||||
dvert = calc->final->getVertDataArray(calc->final, CD_MDEFORMVERT);
|
||||
vert = calc->final->getVertDataArray(calc->final, CD_MVERT);
|
||||
|
||||
//Shrink (calculate each vertex final position)
|
||||
for(i = 0; i<numVerts; i++)
|
||||
{
|
||||
float weight = vertexgroup_get_vertex_weight(dvert, i, vgroup);
|
||||
|
||||
float final[3]; //Coords relative to target
|
||||
float normal[3];
|
||||
float dist;
|
||||
|
||||
if(weight == 0.0f) continue; //Skip vertexs where we have no influence
|
||||
|
||||
VECCOPY(final, vert[i].co);
|
||||
space_transform_apply(&calc->local2target, final);
|
||||
|
||||
//We also need to apply the rotation to normal
|
||||
if(calc->smd->shrinkType == MOD_SHRINKWRAP_NORMAL)
|
||||
{
|
||||
NormalShortToFloat(normal, vert[i].no);
|
||||
space_transform_apply_normal(&calc->local2target, normal);
|
||||
}
|
||||
(callback)(calc->target, final, normal);
|
||||
|
||||
space_transform_invert(&calc->local2target, 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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function removes Unused faces, vertexs and edges from calc->target
|
||||
*
|
||||
@@ -936,6 +636,7 @@ static void shrinkwrap_calc_foreach_vertex(ShrinkwrapCalcData *calc, Shrinkwrap_
|
||||
* In case it creates a new DerivedMesh, the old calc->final is freed
|
||||
*/
|
||||
//TODO memory checks on allocs
|
||||
/*
|
||||
static void shrinkwrap_removeUnused(ShrinkwrapCalcData *calc)
|
||||
{
|
||||
int i, t;
|
||||
@@ -1001,7 +702,7 @@ static void shrinkwrap_removeUnused(ShrinkwrapCalcData *calc)
|
||||
face[i].v4 = 0; //this quad turned on a tri
|
||||
}
|
||||
|
||||
/*
|
||||
#if 0
|
||||
if(face[i].v4 && res == 3)
|
||||
{
|
||||
if(!bitset_get(moved_verts, face[i].v1))
|
||||
@@ -1020,7 +721,7 @@ static void shrinkwrap_removeUnused(ShrinkwrapCalcData *calc)
|
||||
|
||||
face[i].v4 = 0; //this quad turned on a tri
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
|
||||
bitset_set(used_faces, i); //Mark face to maintain
|
||||
numUsedFaces++;
|
||||
@@ -1159,9 +860,10 @@ void shrinkwrap_projectToCutPlane(ShrinkwrapCalcData *calc_data)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
/* Main shrinkwrap function */
|
||||
/*
|
||||
DerivedMesh *shrinkwrapModifier_do(ShrinkwrapModifierData *smd, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc)
|
||||
{
|
||||
|
||||
@@ -1265,7 +967,76 @@ DerivedMesh *shrinkwrapModifier_do(ShrinkwrapModifierData *smd, Object *ob, Deri
|
||||
|
||||
return calc.final;
|
||||
}
|
||||
*/
|
||||
|
||||
/* Main shrinkwrap function */
|
||||
void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts)
|
||||
{
|
||||
|
||||
ShrinkwrapCalcData calc;
|
||||
memset(&calc, 0, sizeof(calc));
|
||||
|
||||
//Init Shrinkwrap calc data
|
||||
calc.smd = smd;
|
||||
|
||||
calc.ob = ob;
|
||||
calc.original = dm;
|
||||
|
||||
calc.numVerts = numVerts;
|
||||
calc.vertexCos = vertexCos;
|
||||
|
||||
//remove loop dependencies on derived meshs (TODO should this be done elsewhere?)
|
||||
if(smd->target == ob) smd->target = NULL;
|
||||
if(smd->cutPlane == ob) smd->cutPlane = NULL;
|
||||
|
||||
|
||||
if(smd->target)
|
||||
{
|
||||
//TODO currently we need a copy in case object_get_derived_final returns an emDM that does not defines getVertArray or getFace array
|
||||
calc.target = CDDM_copy( object_get_derived_final(smd->target, CD_MASK_BAREMESH) );
|
||||
|
||||
if(!calc.target)
|
||||
{
|
||||
printf("Target derived mesh is null! :S\n");
|
||||
}
|
||||
|
||||
//TODO there might be several "bugs" on non-uniform scales matrixs.. because it will no longer be nearest surface, not sphere projection
|
||||
//because space has been deformed
|
||||
space_transform_setup(&calc.local2target, ob, smd->target);
|
||||
|
||||
calc.keptDist = smd->keptDist; //TODO: smd->keptDist is in global units.. must change to local
|
||||
}
|
||||
|
||||
//Projecting target defined - lets work!
|
||||
if(calc.target)
|
||||
{
|
||||
|
||||
printf("Shrinkwrap (%s)%d over (%s)%d\n",
|
||||
calc.ob->id.name, calc.numVerts,
|
||||
calc.smd->target->id.name, calc.target->getNumVerts(calc.target)
|
||||
);
|
||||
|
||||
|
||||
switch(smd->shrinkType)
|
||||
{
|
||||
case MOD_SHRINKWRAP_NEAREST_SURFACE:
|
||||
shrinkwrap_calc_nearest_surface_point(&calc);
|
||||
break;
|
||||
|
||||
case MOD_SHRINKWRAP_NORMAL:
|
||||
shrinkwrap_calc_normal_projection(&calc);
|
||||
break;
|
||||
|
||||
case MOD_SHRINKWRAP_NEAREST_VERTEX:
|
||||
shrinkwrap_calc_nearest_vertex(&calc);
|
||||
break;
|
||||
}
|
||||
|
||||
//free derived mesh
|
||||
calc.target->release( calc.target );
|
||||
calc.target = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Shrinkwrap to the nearest vertex
|
||||
@@ -1277,15 +1048,12 @@ void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
|
||||
{
|
||||
int i;
|
||||
int vgroup = get_named_vertexgroup_num(calc->ob, calc->smd->vgroup_name);
|
||||
float tmp_co[3];
|
||||
float *co;
|
||||
|
||||
BVHTreeFromMesh treeData;
|
||||
BVHTreeNearest nearest;
|
||||
|
||||
int numVerts;
|
||||
MVert *vert = NULL;
|
||||
MDeformVert *dvert = NULL;
|
||||
|
||||
MDeformVert *dvert = calc->original ? calc->original->getVertDataArray(calc->original, CD_MDEFORMVERT) : NULL;
|
||||
|
||||
|
||||
bvhtree_from_mesh_verts(&treeData, calc->target, 0.0, 2, 6);
|
||||
@@ -1295,26 +1063,21 @@ void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
|
||||
nearest.index = -1;
|
||||
nearest.dist = FLT_MAX;
|
||||
|
||||
|
||||
//Find the nearest vertex
|
||||
numVerts= calc->final->getNumVerts(calc->final);
|
||||
vert = calc->final->getVertDataArray(calc->final, CD_MVERT);
|
||||
dvert = calc->final->getVertDataArray(calc->final, CD_MDEFORMVERT);
|
||||
|
||||
for(i=0; i<numVerts; i++)
|
||||
for(co = calc->vertexCos[i=0]; i<calc->numVerts; co = calc->vertexCos[++i])
|
||||
{
|
||||
int index;
|
||||
float tmp_co[3];
|
||||
float weight = vertexgroup_get_vertex_weight(dvert, i, vgroup);
|
||||
if(weight == 0.0f) continue;
|
||||
|
||||
VECCOPY(tmp_co, vert[i].co);
|
||||
VECCOPY(tmp_co, co);
|
||||
space_transform_apply(&calc->local2target, tmp_co);
|
||||
|
||||
//Use local proximity heuristics (to reduce the nearest search)
|
||||
if(nearest.index != -1)
|
||||
{
|
||||
nearest.dist = squared_dist(tmp_co, nearest.co);
|
||||
}
|
||||
else nearest.dist = FLT_MAX;
|
||||
else
|
||||
nearest.dist = FLT_MAX;
|
||||
|
||||
index = BLI_bvhtree_find_nearest(treeData.tree, tmp_co, &nearest, treeData.nearest_callback, &treeData);
|
||||
|
||||
@@ -1323,113 +1086,16 @@ void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
|
||||
float dist;
|
||||
VECCOPY(tmp_co, nearest.co);
|
||||
space_transform_invert(&calc->local2target, tmp_co);
|
||||
dist = VecLenf(vert[i].co, tmp_co);
|
||||
|
||||
dist = VecLenf(co, tmp_co);
|
||||
if(dist > 1e-5) weight *= (dist - calc->keptDist)/dist;
|
||||
VecLerpf(vert[i].co, vert[i].co, tmp_co, weight); //linear interpolation
|
||||
VecLerpf(co, co, tmp_co, weight); //linear interpolation
|
||||
}
|
||||
}
|
||||
|
||||
BLI_bvhtree_free(treeData.tree);
|
||||
}
|
||||
|
||||
/*
|
||||
* Shrinkwrap projecting vertexs allong their normals over the target
|
||||
*
|
||||
* it builds a RayTree from the target mesh and then performs a
|
||||
* raycast for each vertex (ray direction = normal)
|
||||
*/
|
||||
/*
|
||||
void shrinkwrap_calc_normal_projection_raytree(ShrinkwrapCalcData *calc)
|
||||
{
|
||||
int i;
|
||||
int vgroup = get_named_vertexgroup_num(calc->ob, calc->smd->vgroup_name);
|
||||
char use_normal = calc->smd->shrinkOpts;
|
||||
RayTree *target = NULL;
|
||||
|
||||
int numVerts;
|
||||
MVert *vert = NULL;
|
||||
MDeformVert *dvert = NULL;
|
||||
float tmp_co[3], tmp_no[3];
|
||||
|
||||
if( (use_normal & (MOD_SHRINKWRAP_ALLOW_INVERTED_NORMAL | MOD_SHRINKWRAP_ALLOW_DEFAULT_NORMAL)) == 0)
|
||||
return; //Nothing todo
|
||||
|
||||
//setup raytracing
|
||||
BENCH(target = raytree_create_from_mesh(calc->target));
|
||||
if(target == NULL) return OUT_OF_MEMORY();
|
||||
|
||||
|
||||
|
||||
//Project each vertex along normal
|
||||
numVerts= calc->final->getNumVerts(calc->final);
|
||||
vert = calc->final->getVertDataArray(calc->final, CD_MVERT);
|
||||
dvert = calc->final->getVertDataArray(calc->final, CD_MDEFORMVERT);
|
||||
|
||||
for(i=0; i<numVerts; i++)
|
||||
{
|
||||
float dist = FLT_MAX;
|
||||
float weight = vertexgroup_get_vertex_weight(dvert, i, vgroup);
|
||||
float face_normal[3];
|
||||
if(weight == 0.0f) continue;
|
||||
|
||||
//Transform coordinates local->target
|
||||
VecMat4MulVecfl(tmp_co, calc->local2target, vert[i].co);
|
||||
|
||||
NormalShortToFloat(tmp_no, vert[i].no);
|
||||
Mat4Mul3Vecfl(calc->local2target, tmp_no); //Watch out for scaling on normal
|
||||
Normalize(tmp_no); //(TODO: do we really needed a unit-len normal? and we could know the scale factor before hand?)
|
||||
|
||||
if(use_normal & MOD_SHRINKWRAP_ALLOW_DEFAULT_NORMAL)
|
||||
{
|
||||
dist = raytree_cast_ray(target, tmp_co, tmp_no, face_normal);
|
||||
|
||||
if((calc->smd->shrinkOpts & MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE) && INPR(tmp_no, face_normal) < 0)
|
||||
dist = FLT_MAX;
|
||||
if((calc->smd->shrinkOpts & MOD_SHRINKWRAP_CULL_TARGET_BACKFACE) && INPR(tmp_no, face_normal) > 0)
|
||||
dist = FLT_MAX;
|
||||
}
|
||||
|
||||
if(use_normal & MOD_SHRINKWRAP_ALLOW_INVERTED_NORMAL)
|
||||
{
|
||||
float inv[3]; // = {-tmp_no[0], -tmp_no[1], -tmp_no[2]};
|
||||
float tdist;
|
||||
|
||||
inv[0] = -tmp_no[0];
|
||||
inv[1] = -tmp_no[1];
|
||||
inv[2] = -tmp_no[2];
|
||||
|
||||
tdist = raytree_cast_ray(target, tmp_co, inv, 0);
|
||||
|
||||
if((calc->smd->shrinkOpts & MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE) && INPR(tmp_no, face_normal) < 0)
|
||||
tdist = FLT_MAX;
|
||||
if((calc->smd->shrinkOpts & MOD_SHRINKWRAP_CULL_TARGET_BACKFACE) && INPR(tmp_no, face_normal) > 0)
|
||||
tdist = FLT_MAX;
|
||||
|
||||
if(ABS(tdist) < ABS(dist))
|
||||
dist = -tdist;
|
||||
}
|
||||
|
||||
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)
|
||||
bitset_set(calc->moved, i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
free_raytree_from_mesh(target);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
* This function raycast a single vertex and updates the hit if the "hit" is considered valid.
|
||||
* Returns TRUE if "hit" was updated.
|
||||
@@ -1438,7 +1104,7 @@ void shrinkwrap_calc_normal_projection_raytree(ShrinkwrapCalcData *calc)
|
||||
* MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE (front faces hits are ignored)
|
||||
* MOD_SHRINKWRAP_CULL_TARGET_BACKFACE (back faces hits are ignored)
|
||||
*/
|
||||
static int normal_projection_project_vertex(char options, const float *vert, const float *dir, const SpaceTransform *transf, BVHTree *tree, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata)
|
||||
int normal_projection_project_vertex(char options, const float *vert, const float *dir, const SpaceTransform *transf, BVHTree *tree, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata)
|
||||
{
|
||||
float tmp_co[3], tmp_no[3];
|
||||
const float *co, *no;
|
||||
@@ -1498,30 +1164,34 @@ void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc)
|
||||
int i;
|
||||
int vgroup = get_named_vertexgroup_num(calc->ob, calc->smd->vgroup_name);
|
||||
char use_normal = calc->smd->shrinkOpts;
|
||||
float *co;
|
||||
|
||||
//setup raytracing
|
||||
BVHTreeFromMesh treeData;
|
||||
BVHTreeRayHit hit;
|
||||
|
||||
|
||||
/*
|
||||
//cutTree
|
||||
DerivedMesh * limit_mesh = NULL;
|
||||
BVHTreeFromMesh limitData;
|
||||
SpaceTransform local2cut;
|
||||
*/
|
||||
|
||||
int numVerts;
|
||||
MVert *vert = NULL;
|
||||
MDeformVert *dvert = NULL;
|
||||
MVert *vert = calc->original ? calc->original->getVertDataArray(calc->original, CD_MVERT) : NULL; //Needed because of vertex normal
|
||||
MDeformVert *dvert = calc->original ? calc->original->getVertDataArray(calc->original, CD_MDEFORMVERT) : NULL;
|
||||
|
||||
if( (use_normal & (MOD_SHRINKWRAP_ALLOW_INVERTED_NORMAL | MOD_SHRINKWRAP_ALLOW_DEFAULT_NORMAL)) == 0)
|
||||
if(vert == NULL)
|
||||
{
|
||||
printf("Shrinkwrap cant normal project witouth normal information");
|
||||
return;
|
||||
}
|
||||
if((use_normal & (MOD_SHRINKWRAP_ALLOW_INVERTED_NORMAL | MOD_SHRINKWRAP_ALLOW_DEFAULT_NORMAL)) == 0)
|
||||
return; //Nothing todo
|
||||
|
||||
CDDM_calc_normals(calc->original); //Normals maybe arent yet calculated
|
||||
|
||||
bvhtree_from_mesh_faces(&treeData, calc->target, calc->keptDist, 4, 6);
|
||||
if(treeData.tree == NULL) return OUT_OF_MEMORY();
|
||||
|
||||
/*
|
||||
|
||||
if(calc->smd->cutPlane)
|
||||
{
|
||||
space_transform_setup( &local2cut, calc->ob, calc->smd->cutPlane);
|
||||
@@ -1533,14 +1203,8 @@ void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc)
|
||||
else
|
||||
printf("CutPlane finalDerived mesh is null\n");
|
||||
}
|
||||
*/
|
||||
|
||||
//Project each vertex along normal
|
||||
numVerts= calc->final->getNumVerts(calc->final);
|
||||
vert = calc->final->getVertDataArray(calc->final, CD_MVERT);
|
||||
dvert = calc->final->getVertDataArray(calc->final, CD_MDEFORMVERT);
|
||||
|
||||
for(i=0; i<numVerts; i++)
|
||||
for(co = calc->vertexCos[i=0]; i<calc->numVerts; co = calc->vertexCos[++i])
|
||||
{
|
||||
float tmp_co[3], tmp_no[3];
|
||||
float lim = 1000; //TODO: we should use FLT_MAX here, but sweepsphere code isnt prepared for that
|
||||
@@ -1549,7 +1213,7 @@ void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc)
|
||||
|
||||
if(weight == 0.0f) continue;
|
||||
|
||||
VECCOPY(tmp_co, vert[i].co);
|
||||
VECCOPY(tmp_co, co);
|
||||
NormalShortToFloat(tmp_no, vert[i].no);
|
||||
|
||||
|
||||
@@ -1559,10 +1223,9 @@ void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc)
|
||||
|
||||
if(use_normal & MOD_SHRINKWRAP_ALLOW_DEFAULT_NORMAL)
|
||||
{
|
||||
/*
|
||||
if(limit_tree)
|
||||
normal_projection_project_vertex(0, tmp_co, tmp_no, &local2cut, limit_tree, &hit, limit_callback, &limit_userdata);
|
||||
*/
|
||||
|
||||
if(limitData.tree)
|
||||
normal_projection_project_vertex(0, tmp_co, tmp_no, &local2cut, limitData.tree, &hit, limitData.raycast_callback, &limitData);
|
||||
|
||||
if(normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, tmp_no, &calc->local2target, treeData.tree, &hit, treeData.raycast_callback, &treeData))
|
||||
moved = TRUE;
|
||||
@@ -1573,10 +1236,10 @@ void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc)
|
||||
{
|
||||
float inv_no[3] = { -tmp_no[0], -tmp_no[1], -tmp_no[2] };
|
||||
|
||||
/*
|
||||
if(limit_tree)
|
||||
normal_projection_project_vertex(0, tmp_co, inv_no, &local2cut, limit_tree, &hit, limit_callback, &limit_userdata);
|
||||
*/
|
||||
|
||||
if(limitData.tree)
|
||||
normal_projection_project_vertex(0, tmp_co, inv_no, &local2cut, limitData.tree, &hit, limitData.raycast_callback, &limitData);
|
||||
|
||||
if(normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, inv_no, &calc->local2target, treeData.tree, &hit, treeData.raycast_callback, &treeData))
|
||||
moved = TRUE;
|
||||
}
|
||||
@@ -1584,7 +1247,7 @@ void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc)
|
||||
|
||||
if(hit.index != -1)
|
||||
{
|
||||
VecLerpf(vert[i].co, vert[i].co, hit.co, weight);
|
||||
VecLerpf(co, co, hit.co, weight);
|
||||
|
||||
if(moved && calc->moved)
|
||||
bitset_set(calc->moved, i);
|
||||
@@ -1593,13 +1256,12 @@ void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc)
|
||||
|
||||
BLI_bvhtree_free(treeData.tree);
|
||||
|
||||
/*
|
||||
|
||||
if(limitData.tree)
|
||||
BLI_bvhtree_free(limitData.tree);
|
||||
|
||||
if(limit_mesh)
|
||||
limit_mesh->release(limit_mesh);
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1612,14 +1274,12 @@ void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
|
||||
{
|
||||
int i;
|
||||
int vgroup = get_named_vertexgroup_num(calc->ob, calc->smd->vgroup_name);
|
||||
float tmp_co[3];
|
||||
float *co;
|
||||
|
||||
BVHTreeFromMesh treeData;
|
||||
BVHTreeNearest nearest;
|
||||
|
||||
int numVerts;
|
||||
MVert *vert = NULL;
|
||||
MDeformVert *dvert = NULL;
|
||||
MDeformVert *dvert = calc->original ? calc->original->getVertDataArray(calc->original, CD_MDEFORMVERT) : NULL;
|
||||
|
||||
|
||||
//Create a bvh-tree of the given target
|
||||
@@ -1632,17 +1292,14 @@ void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
|
||||
|
||||
|
||||
//Find the nearest vertex
|
||||
numVerts= calc->final->getNumVerts(calc->final);
|
||||
vert = calc->final->getVertDataArray(calc->final, CD_MVERT);
|
||||
dvert = calc->final->getVertDataArray(calc->final, CD_MDEFORMVERT);
|
||||
|
||||
for(i=0; i<numVerts; i++)
|
||||
for(co = calc->vertexCos[i=0]; i<calc->numVerts; co = calc->vertexCos[++i])
|
||||
{
|
||||
int index;
|
||||
float tmp_co[3];
|
||||
float weight = vertexgroup_get_vertex_weight(dvert, i, vgroup);
|
||||
if(weight == 0.0f) continue;
|
||||
|
||||
VECCOPY(tmp_co, vert[i].co);
|
||||
VECCOPY(tmp_co, co);
|
||||
space_transform_apply(&calc->local2target, tmp_co);
|
||||
|
||||
if(nearest.index != -1)
|
||||
@@ -1665,7 +1322,7 @@ void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
|
||||
VecLerpf(tmp_co, tmp_co, nearest.co, (dist - calc->keptDist)/dist); //linear interpolation
|
||||
}
|
||||
space_transform_invert(&calc->local2target, tmp_co);
|
||||
VecLerpf(vert[i].co, vert[i].co, tmp_co, weight); //linear interpolation
|
||||
VecLerpf(co, co, tmp_co, weight); //linear interpolation
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -499,11 +499,9 @@ typedef struct ShrinkwrapModifierData {
|
||||
struct Object *cutPlane;/* shrink target */
|
||||
char vgroup_name[32]; /* optional vertexgroup name */
|
||||
float keptDist; /* distance offset from mesh/projection point */
|
||||
float mergeDist; /* distance to merge vertexs */
|
||||
short shrinkType; /* shrink type projection */
|
||||
short shrinkOpts; /* shrink options */
|
||||
|
||||
int pad;
|
||||
} ShrinkwrapModifierData;
|
||||
|
||||
/* Shrinkwrap->shrinkType */
|
||||
@@ -514,7 +512,7 @@ typedef struct ShrinkwrapModifierData {
|
||||
/* Shrinkwrap->shrinkOpts */
|
||||
#define MOD_SHRINKWRAP_ALLOW_DEFAULT_NORMAL (1<<0)
|
||||
#define MOD_SHRINKWRAP_ALLOW_INVERTED_NORMAL (1<<1)
|
||||
#define MOD_SHRINKWRAP_REMOVE_UNPROJECTED_FACES (1<<2)
|
||||
/* #define MOD_SHRINKWRAP_REMOVE_UNPROJECTED_FACES (1<<2) / * Currently dropped to make shrinkwrap a deform only modifier */
|
||||
|
||||
#define MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE (1<<3)
|
||||
#define MOD_SHRINKWRAP_CULL_TARGET_BACKFACE (1<<4)
|
||||
|
@@ -1903,9 +1903,9 @@ 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 = 86;
|
||||
height = 86 + 3;
|
||||
if (smd->shrinkType == MOD_SHRINKWRAP_NORMAL)
|
||||
height += 19*5;
|
||||
height += 19*3;
|
||||
else if (smd->shrinkType == MOD_SHRINKWRAP_NEAREST_SURFACE)
|
||||
height += 19;
|
||||
|
||||
@@ -2535,31 +2535,35 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
|
||||
ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
|
||||
|
||||
char shrinktypemenu[]="Shrinkwrap type%t|nearest surface point %x0|normal projection %x1|nearest vertex %x2";
|
||||
uiDefButS(block, MENU, B_MODIFIER_RECALC, shrinktypemenu, lx,(cy-=19),buttonWidth,19, &smd->shrinkType, 0, 0, 0, 0, "Selects type of shrinkwrap algorithm for target position.");
|
||||
|
||||
uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &smd->target, "Target to shrink to");
|
||||
|
||||
but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", lx, (cy-=19), buttonWidth,19, &smd->vgroup_name, 0, 31, 0, 0, "Vertex Group name");
|
||||
uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
|
||||
|
||||
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");
|
||||
|
||||
cy -= 3;
|
||||
uiDefButS(block, MENU, B_MODIFIER_RECALC, shrinktypemenu, lx,(cy-=19),buttonWidth,19, &smd->shrinkType, 0, 0, 0, 0, "Selects type of shrinkwrap algorithm for target position.");
|
||||
if (smd->shrinkType == MOD_SHRINKWRAP_NORMAL){
|
||||
|
||||
uiDefButBitS(block, TOG, MOD_SHRINKWRAP_ALLOW_DEFAULT_NORMAL, B_MODIFIER_RECALC, "Default normal", lx,(cy-=19),buttonWidth/2,19, &smd->shrinkOpts, 0, 0, 0, 0, "Allows vertices to move in the normal direction");
|
||||
uiDefButBitS(block, TOG, MOD_SHRINKWRAP_ALLOW_INVERTED_NORMAL, B_MODIFIER_RECALC, "Invert normal", lx + buttonWidth/2,cy,buttonWidth/2,19, &smd->shrinkOpts, 0, 0, 0, 0, "Allows vertices to move in the inverse direction of their normal");
|
||||
|
||||
uiDefButBitS(block, TOG, MOD_SHRINKWRAP_REMOVE_UNPROJECTED_FACES, B_MODIFIER_RECALC, "Remove faces", lx,(cy-=19),buttonWidth,19, &smd->shrinkOpts, 0, 0, 0, 0, "Remove faces where all vertices haven't been projected");
|
||||
/* uiDefButBitS(block, TOG, MOD_SHRINKWRAP_REMOVE_UNPROJECTED_FACES, B_MODIFIER_RECALC, "Remove faces", lx,(cy-=19),buttonWidth,19, &smd->shrinkOpts, 0, 0, 0, 0, "Remove faces where all vertices haven't been projected"); */
|
||||
|
||||
uiDefButBitS(block, TOG, MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE, B_MODIFIER_RECALC, "Cull frontfaces",lx,(cy-=19),buttonWidth/2,19, &smd->shrinkOpts, 0, 0, 0, 0, "Controls whether a vertex can be projected to a front face on target");
|
||||
uiDefButBitS(block, TOG, MOD_SHRINKWRAP_CULL_TARGET_BACKFACE, B_MODIFIER_RECALC, "Cull backfaces", lx+buttonWidth/2,cy,buttonWidth/2,19, &smd->shrinkOpts, 0, 0, 0, 0, "Controls whether a vertex can be projected to a back face on target");
|
||||
|
||||
uiDefButF(block, NUM, B_MODIFIER_RECALC, "Merge Dist:", lx,(cy-=19),buttonWidth,19, &smd->mergeDist, 0.0f, 0.01f, 0.01f, 0.01f, "Specify merge distance");
|
||||
uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob2: ", lx, (cy-=19), buttonWidth,19, &smd->cutPlane, "Target to project points that didn't got projected over target");
|
||||
/* uiDefButF(block, NUM, B_MODIFIER_RECALC, "Merge Dist:", lx,(cy-=19),buttonWidth,19, &smd->mergeDist, 0.0f, 0.01f, 0.01f, 0.01f, "Specify merge distance"); */
|
||||
uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob2: ", lx, (cy-=19), buttonWidth,19, &smd->cutPlane, "Aditional mesh to project over");
|
||||
}
|
||||
else if (smd->shrinkType == MOD_SHRINKWRAP_NEAREST_SURFACE){
|
||||
uiDefButBitS(block, TOG, MOD_SHRINKWRAP_KEPT_ABOVE_SURFACE, B_MODIFIER_RECALC, "Above surface", lx,(cy-=19),buttonWidth,19, &smd->shrinkOpts, 0, 0, 0, 0, "Vertices are kept on the front side of faces");
|
||||
}
|
||||
|
||||
but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", lx, (cy-=19), buttonWidth,19, &smd->vgroup_name, 0, 31, 0, 0, "Vertex Group name");
|
||||
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);
|
||||
|
||||
} else if (md->type==eModifierType_SimpleDeform) {
|
||||
SimpleDeformModifierData *smd = (SimpleDeformModifierData*) md;
|
||||
|
||||
|
Reference in New Issue
Block a user