Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorAndre Susano Pinto <andresusanopinto@gmail.com>2008-07-25 22:48:24 +0400
committerAndre Susano Pinto <andresusanopinto@gmail.com>2008-07-25 22:48:24 +0400
commit1537e75cba4df5604b695be54bbae724df5d4095 (patch)
treeae4dfe556f4d0a952a03dd453a8d66debb83aed6 /source
parentaec6b78deda32d7aa1631ec76efda5bcea83a8c9 (diff)
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)
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_shrinkwrap.h20
-rw-r--r--source/blender/blenkernel/intern/modifier.c31
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c581
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h4
-rw-r--r--source/blender/src/buttons_editing.c26
5 files changed, 169 insertions, 493 deletions
diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h
index f84b8fb6ec4..739027fc95f 100644
--- a/source/blender/blenkernel/BKE_shrinkwrap.h
+++ b/source/blender/blenkernel/BKE_shrinkwrap.h
@@ -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
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 124474ca09c..502be6b3af3 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -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);
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index 648071b2c9f..53051b3cfd7 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -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,8 +967,77 @@ 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,9 +1086,10 @@ 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
}
}
@@ -1333,104 +1097,6 @@ void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
}
/*
- * 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.
* Opts control whether an hit is valid or not
@@ -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
}
}
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 40c3b223e01..44a7017158b 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -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)
diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c
index 235463d5a75..d0b970bf5c6 100644
--- a/source/blender/src/buttons_editing.c
+++ b/source/blender/src/buttons_editing.c
@@ -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;