Changed a bit of code structure to make method optimization easier

This commit is contained in:
Andre Susano Pinto
2008-04-30 17:55:26 +00:00
parent 928b676b99
commit 29f0f74b05
2 changed files with 132 additions and 85 deletions

View File

@@ -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

View File

@@ -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
}
}
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;
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;
float orig[3], final[3]; //Coords relative to target
float normal[3];
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;
if(weight == 0.0f) continue; //Skip vertexs where we have no influence
VecMat4MulVecfl(orig, calc->local2target, vert[i].co);
VECCOPY(final, orig);
//We also need to apply the rotation to normal
if(calc->smd->shrinkType == MOD_SHRINKWRAP_NORMAL)
{
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
VecMat4MulVecfl(vert[i].co, calc->target2local, final);
}
}
/* Main shrinkwrap function */
DerivedMesh *shrinkwrapModifier_do(ShrinkwrapModifierData *smd, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc)
{
DerivedMesh *result = CDDM_copy(dm);
ShrinkwrapCalcData calc;
//Init Shrinkwrap calc data
calc.smd = smd;
calc.original = dm;
calc.final = CDDM_copy(calc.original);
//Projecting target defined - lets work!
if(smd->target)
{
int i, j;
calc.target = (DerivedMesh *)smd->target->derivedFinal;
int vgroup = get_named_vertexgroup_num(ob, smd->vgroup_name);
int numVerts = 0;
MDeformVert *dvert = NULL;
MVert *vert = NULL;
DerivedMesh *target_dm = NULL;
float local2target[4][4], target2local[4][4];
numVerts = result->getNumVerts(result);
dvert = result->getVertDataArray(result, CD_MDEFORMVERT);
vert = result->getVertDataArray(result, CD_MVERT);
target_dm = (DerivedMesh *)smd->target->derivedFinal;
if(!target_dm)
if(!calc.target)
{
printf("Target derived mesh is null! :S\n");
}
//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);
//Shrink (calculate each vertex final position)
for(i = 0; i<numVerts; i++)
{
float weight;
float orig[3], final[3]; //Coords relative to target_dm
float normal[3];
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;
if(weight == 0.0f) continue; //Skip vertexs where we have no influence
VecMat4MulVecfl(orig, local2target, vert[i].co);
VECCOPY(final, orig);
//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?)
}
switch(smd->shrinkType)
{
case MOD_SHRINKWRAP_NEAREST_SURFACE:
shrinkwrap_calc_nearest_surface_point(target_dm, final, normal);
break;
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;
}
VecLerpf(final, orig, final, weight); //linear interpolation
VecMat4MulVecfl(vert[i].co, target2local, final);
}
//Destroy faces, edges and stuff
//Since we aren't yet constructing/destructing geom nothing todo for now
CDDM_calc_normals(result);
Mat4MulSerie(calc.local2target, smd->target->imat, ob->obmat, 0, 0, 0, 0, 0, 0);
Mat4Invert(calc.target2local, calc.local2target);
}
return result;
calc.moved = NULL;
//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
if(calc.moved)
{
//TODO
}
CDDM_calc_normals(calc.final);
return calc.final;
}