From 29f0f74b05462e9bd0b641602b89fa1c39ed29c8 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Wed, 30 Apr 2008 17:55:26 +0000 Subject: Changed a bit of code structure to make method optimization easier --- source/blender/blenkernel/BKE_shrinkwrap.h | 24 ++++ source/blender/blenkernel/intern/shrinkwrap.c | 169 +++++++++++++++----------- 2 files changed, 120 insertions(+), 73 deletions(-) diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h index 4fd1ae354cd..0a302b21141 100644 --- a/source/blender/blenkernel/BKE_shrinkwrap.h +++ b/source/blender/blenkernel/BKE_shrinkwrap.h @@ -33,6 +33,30 @@ struct Object; struct DerivedMesh; struct ShrinkwrapModifierData; + +typedef struct ShrinkwrapCalcData +{ + ShrinkwrapModifierData *smd; //shrinkwrap modifier data + + struct Object *ob; //object we are applying shrinkwrap to + struct DerivedMesh *original; //mesh before shrinkwrap + struct DerivedMesh *final; //initially a copy of original mesh.. mesh thats going to be shrinkwrapped + + struct DerivedMesh *target; //mesh we are shrinking to + + //matrixs for local<->target space transform + float local2target[4][4]; + float target2local[4][4]; + + //float *weights; //weights of vertexs + unsigned char *moved; //boolean indicating if vertex has moved (TODO use bitmaps) + +} ShrinkwrapCalcData; + +void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *data); +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); #endif diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 74e105125ca..606f8938985 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -46,7 +46,10 @@ #include "BLI_arithb.h" + #define CONST +typedef void ( *Shrinkwrap_ForeachVertexCallback) (DerivedMesh *target, float *co, float *normal); + static void normal_short2float(CONST short *ns, float *nf) { @@ -55,6 +58,7 @@ static void normal_short2float(CONST short *ns, float *nf) nf[2] = ns[2] / 32767.0f; } + /* * This calculates the distance (in dir units) that the ray must travel to intersect plane * It can return negative values @@ -134,7 +138,7 @@ static float nearest_point_in_tri_surface(CONST float *co, CONST float *v0, CONS /* * Shrink to nearest surface point on target mesh */ -static void shrinkwrap_calc_nearest_surface_point(DerivedMesh *target, float *co, float *unused) +static void bruteforce_shrinkwrap_calc_nearest_surface_point(DerivedMesh *target, float *co, float *unused) { //TODO: this should use raycast code probably existent in blender float minDist = FLT_MAX; @@ -179,7 +183,7 @@ static void shrinkwrap_calc_nearest_surface_point(DerivedMesh *target, float *co /* * Projects the vertex on the normal direction over the target mesh */ -static void shrinkwrap_calc_normal_projection(DerivedMesh *target, float *co, float *vnormal) +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; @@ -230,7 +234,7 @@ static void shrinkwrap_calc_normal_projection(DerivedMesh *target, float *co, fl /* * Shrink to nearest vertex on target mesh */ -static void shrinkwrap_calc_nearest_vertex(DerivedMesh *target, float *co, float *unused) +static void bruteforce_shrinkwrap_calc_nearest_vertex(DerivedMesh *target, float *co, float *unused) { float minDist = FLT_MAX; float orig_co[3]; @@ -255,104 +259,123 @@ static void shrinkwrap_calc_nearest_vertex(DerivedMesh *target, float *co, float } } -/* Main shrinkwrap function */ -DerivedMesh *shrinkwrapModifier_do(ShrinkwrapModifierData *smd, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc) + +static void shrinkwrap_calc_foreach_vertex(ShrinkwrapCalcData *calc, Shrinkwrap_ForeachVertexCallback callback) { + int i, j; + int vgroup = get_named_vertexgroup_num(calc->ob, calc->smd->vgroup_name); + int numVerts = 0; - DerivedMesh *result = CDDM_copy(dm); + MDeformVert *dvert = NULL; + MVert *vert = NULL; - //Projecting target defined - lets work! - if(smd->target) + 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; ivgroup_name); - int numVerts = 0; + float orig[3], final[3]; //Coords relative to target + float normal[3]; - MDeformVert *dvert = NULL; - MVert *vert = NULL; - DerivedMesh *target_dm = NULL; + if(dvert && vgroup >= 0) + { + weight = 0.0f; + for(j = 0; j < dvert[i].totweight; j++) + if(dvert[i].dw[j].def_nr == vgroup) + { + weight = dvert[i].dw[j].weight; + break; + } + } + else weight = 1.0f; - float local2target[4][4], target2local[4][4]; + if(weight == 0.0f) continue; //Skip vertexs where we have no influence - numVerts = result->getNumVerts(result); - dvert = result->getVertDataArray(result, CD_MDEFORMVERT); - vert = result->getVertDataArray(result, CD_MVERT); + VecMat4MulVecfl(orig, calc->local2target, vert[i].co); + VECCOPY(final, orig); - target_dm = (DerivedMesh *)smd->target->derivedFinal; - if(!target_dm) + //We also need to apply the rotation to normal + if(calc->smd->shrinkType == MOD_SHRINKWRAP_NORMAL) { - printf("Target derived mesh is null! :S\n"); + normal_short2float(vert[i].no, normal); + Mat4Mul3Vecfl(calc->local2target, normal); + Normalize(normal); //Watch out for scaling (TODO: do we really needed a unit-len normal?) } + (callback)(calc->target, final, normal); + VecLerpf(final, orig, final, weight); //linear interpolation - //TODO should we reduce the number of matrix mults? by choosing applying matrixs to target or to derived mesh? - //Calculate matrixs for local <-> target - Mat4Invert (smd->target->imat, smd->target->obmat); //inverse is outdated - - Mat4MulSerie(local2target, smd->target->imat, ob->obmat, 0, 0, 0, 0, 0, 0); - Mat4Invert(target2local, local2target); - + VecMat4MulVecfl(vert[i].co, calc->target2local, final); + } +} - //Shrink (calculate each vertex final position) - for(i = 0; i= 0) - { - weight = 0.0f; - for(j = 0; j < dvert[i].totweight; j++) - if(dvert[i].dw[j].def_nr == vgroup) - { - weight = dvert[i].dw[j].weight; - break; - } - } - else weight = 1.0f; - if(weight == 0.0f) continue; //Skip vertexs where we have no influence + //Init Shrinkwrap calc data + calc.smd = smd; - VecMat4MulVecfl(orig, local2target, vert[i].co); - VECCOPY(final, orig); + calc.original = dm; + calc.final = CDDM_copy(calc.original); - //We also need to apply the rotation to normal - if(smd->shrinkType == MOD_SHRINKWRAP_NORMAL) - { - normal_short2float(vert[i].no, normal); - Mat4Mul3Vecfl(local2target, normal); - Normalize(normal); //Watch out for scaling (TODO: do we really needed a unit-len normal?) - } + if(smd->target) + { + calc.target = (DerivedMesh *)smd->target->derivedFinal; + if(!calc.target) + { + printf("Target derived mesh is null! :S\n"); + } - switch(smd->shrinkType) - { - case MOD_SHRINKWRAP_NEAREST_SURFACE: - shrinkwrap_calc_nearest_surface_point(target_dm, final, normal); - break; + //TODO should we reduce the number of matrix mults? by choosing applying matrixs to target or to derived mesh? + //Calculate matrixs for local <-> target + 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); - case MOD_SHRINKWRAP_NORMAL: - shrinkwrap_calc_normal_projection(target_dm, final, normal); - break; + } - case MOD_SHRINKWRAP_NEAREST_VERTEX: - shrinkwrap_calc_nearest_vertex(target_dm, final, normal); - break; - } + calc.moved = NULL; - VecLerpf(final, orig, final, weight); //linear interpolation - VecMat4MulVecfl(vert[i].co, target2local, final); + //Projecting target defined - lets work! + if(calc.target) + { + switch(smd->shrinkType) + { + case MOD_SHRINKWRAP_NEAREST_SURFACE: +// shrinkwrap_calc_nearest_vertex(&calc); + shrinkwrap_calc_foreach_vertex(&calc, bruteforce_shrinkwrap_calc_nearest_surface_point); + break; + + case MOD_SHRINKWRAP_NORMAL: + shrinkwrap_calc_foreach_vertex(&calc, bruteforce_shrinkwrap_calc_nearest_surface_point); + break; + + case MOD_SHRINKWRAP_NEAREST_VERTEX: + shrinkwrap_calc_foreach_vertex(&calc, bruteforce_shrinkwrap_calc_nearest_vertex); + break; } - //Destroy faces, edges and stuff - //Since we aren't yet constructing/destructing geom nothing todo for now - CDDM_calc_normals(result); + } + //Destroy faces, edges and stuff + if(calc.moved) + { + //TODO } - return result; + + CDDM_calc_normals(calc.final); + + return calc.final; } + -- cgit v1.2.3