[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [14572] branches/soc-2008-jaguarandi/ source/blender: Implemented shrink modes are now:
André Pinto
andresusanopinto at gmail.com
Sun Apr 27 21:29:40 CEST 2008
Revision: 14572
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=14572
Author: jaguarandi
Date: 2008-04-27 21:29:40 +0200 (Sun, 27 Apr 2008)
Log Message:
-----------
Implemented shrink modes are now:
+ Nearest surface point
+ Normal projection
+ Nearest vertex (gives similar results to nearest surface if the target mesh has many vertexs and is a lot faster to calculate)
^^ all bruteforce calculation for now
+ fixed matrix order multiplication
+ request for CD_MDEDEFORMVERT
Modified Paths:
--------------
branches/soc-2008-jaguarandi/source/blender/blenkernel/intern/modifier.c
branches/soc-2008-jaguarandi/source/blender/blenkernel/intern/shrinkwrap.c
branches/soc-2008-jaguarandi/source/blender/makesdna/DNA_modifier_types.h
branches/soc-2008-jaguarandi/source/blender/src/buttons_editing.c
Modified: branches/soc-2008-jaguarandi/source/blender/blenkernel/intern/modifier.c
===================================================================
--- branches/soc-2008-jaguarandi/source/blender/blenkernel/intern/modifier.c 2008-04-27 19:20:35 UTC (rev 14571)
+++ branches/soc-2008-jaguarandi/source/blender/blenkernel/intern/modifier.c 2008-04-27 19:29:40 UTC (rev 14572)
@@ -6977,7 +6977,7 @@
static void shrinkwrapModifier_initData(ModifierData *md)
{
ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
- smd->shrinkType = MOD_SHRINKWRAP_NEAREST;
+ smd->shrinkType = MOD_SHRINKWRAP_NEAREST_SURFACE;
}
static void shrinkwrapModifier_copyData(ModifierData *md, ModifierData *target)
@@ -6985,6 +6985,17 @@
memcpy(target, md, sizeof(MeshDeformModifierData));
}
+CustomDataMask shrinkwrapModifier_requiredDataMask(ModifierData *md)
+{
+ ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md;
+ CustomDataMask dataMask = 0;
+
+ /* ask for vertexgroups if we need them */
+ if(smd->vgroup_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
+
+ return dataMask;
+}
+
static void shrinkwrapModifier_foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
{
ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
@@ -7333,9 +7344,9 @@
mti = INIT_TYPE(Shrinkwrap);
mti->type = eModifierTypeType_Nonconstructive;
mti->flags = eModifierTypeFlag_AcceptsMesh;
- /*| eModifierTypeFlag_SupportsMapping; Not yet X'D */
mti->initData = shrinkwrapModifier_initData;
mti->copyData = shrinkwrapModifier_copyData;
+ mti->requiredDataMask = shrinkwrapModifier_requiredDataMask;
mti->foreachObjectLink = shrinkwrapModifier_foreachObjectLink;
mti->applyModifier = shrinkwrapModifier_applyModifier;
mti->updateDepgraph = shrinkwrapModifier_updateDepgraph;
Modified: branches/soc-2008-jaguarandi/source/blender/blenkernel/intern/shrinkwrap.c
===================================================================
--- branches/soc-2008-jaguarandi/source/blender/blenkernel/intern/shrinkwrap.c 2008-04-27 19:20:35 UTC (rev 14571)
+++ branches/soc-2008-jaguarandi/source/blender/blenkernel/intern/shrinkwrap.c 2008-04-27 19:29:40 UTC (rev 14572)
@@ -28,6 +28,8 @@
*/
#include <string.h>
#include <float.h>
+#include <math.h>
+#include <stdio.h>
#include <assert.h>
//TODO: its late and I don't fill like adding ifs() printfs (I'll remove them on end)
@@ -40,22 +42,200 @@
#include "BKE_utildefines.h"
#include "BKE_deform.h"
#include "BKE_cdderivedmesh.h"
+#include "BKE_global.h"
#include "BLI_arithb.h"
-/* Projects the vertex on the normal direction over the target mesh */
-static void shrinkwrap_calc_normal_projection(DerivedMesh *target, float *co, short *no)
+#define CONST
+
+static void normal_short2float(CONST short *ns, float *nf)
{
+ nf[0] = ns[0] / 32767.0f;
+ nf[1] = ns[1] / 32767.0f;
+ nf[2] = ns[2] / 32767.0f;
}
-/* Nearest surface point on target mesh */
-static void shrinkwrap_calc_nearest_point(DerivedMesh *target, float *co, short *no)
+/*
+ * This calculates the distance (in dir units) that the ray must travel to intersect plane
+ * It can return negative values
+ *
+ * TODO theres probably something like this on blender code
+ *
+ * Returns FLT_MIN in parallel case
+ */
+static float ray_intersect_plane(CONST float *point, CONST float *dir, CONST float *plane_point, CONST float *plane_normal)
{
- //TODO: For now its only doing a nearest vertex on target mesh (just for testing other things)
+ float pp[3];
+ float a, pp_dist;
+
+ a = INPR(dir, plane_normal);
+
+ if(fabs(a) < 1e-5f) return FLT_MIN;
+
+ VecSubf(pp, point, plane_point);
+ pp_dist = INPR(pp, plane_normal);
+
+ return -pp_dist/a;
+}
+
+/*
+ * Returns the minimum distance between the point and a triangle surface
+ * Writes the nearest surface point in the given nearest
+ */
+static float nearest_point_in_tri_surface(CONST float *co, CONST float *v0, CONST float *v1, CONST float *v2, float *nearest)
+{
+ //TODO: make this efficient (probably this can be made with something like 3 point_in_slice())
+ if(point_in_tri_prism(co, v0, v1, v2))
+ {
+ float normal[3];
+ float dist;
+
+ CalcNormFloat(v0, v1, v2, normal);
+ dist = ray_intersect_plane(co, normal, v0, normal);
+
+ VECADDFAC(nearest, co, normal, dist);
+ return fabs(dist);
+ }
+ else
+ {
+ float dist = FLT_MAX, tdist;
+ float closest[3];
+
+ PclosestVL3Dfl(closest, co, v0, v1);
+ tdist = VecLenf(co, closest);
+ if(tdist < dist)
+ {
+ dist = tdist;
+ VECCOPY(nearest, closest);
+ }
+
+ PclosestVL3Dfl(closest, co, v1, v2);
+ tdist = VecLenf(co, closest);
+ if(tdist < dist)
+ {
+ dist = tdist;
+ VECCOPY(nearest, closest);
+ }
+
+ PclosestVL3Dfl(closest, co, v2, v0);
+ tdist = VecLenf(co, closest);
+ if(tdist < dist)
+ {
+ dist = tdist;
+ VECCOPY(nearest, closest);
+ }
+
+ return dist;
+ }
+}
+
+
+
+/*
+ * Shrink to nearest surface point on target mesh
+ */
+static void 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;
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 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 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);
@@ -65,7 +245,7 @@
{
float diff[3], sdist;
VECSUB(diff, orig_co, vert[i].co);
- sdist = Inpf(diff, diff);
+ sdist = INPR(diff, diff);
if(sdist < minDist)
{
@@ -75,6 +255,7 @@
}
}
+/* Main shrinkwrap function */
DerivedMesh *shrinkwrapModifier_do(ShrinkwrapModifierData *smd, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc)
{
@@ -90,38 +271,36 @@
MDeformVert *dvert = NULL;
MVert *vert = NULL;
+ DerivedMesh *target_dm = NULL;
float local2target[4][4], target2local[4][4];
- DerivedMesh *target_dm = (DerivedMesh *)smd->target->derivedFinal;
-
numVerts = result->getNumVerts(result);
- dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); //TODO: cddm doens't supports vertex groups :S
+ dvert = result->getVertDataArray(result, CD_MDEFORMVERT);
vert = result->getVertDataArray(result, CD_MVERT);
- /* TODO: Check about editMesh stuff :S */
- /*
- if(G.obedit && G.editMesh)
- target_dm = CDDM_from_editmesh(G.editMesh, smd->target->data); // Needs release before returning
- else
- */
+ target_dm = (DerivedMesh *)smd->target->derivedFinal;
+ if(!target_dm)
+ {
+ 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
- //Update inverse matrixs
- Mat4Invert (ob->imat, ob->obmat);
- Mat4Invert (smd->target->imat, smd->target->obmat);
+ Mat4MulSerie(local2target, smd->target->imat, ob->obmat, 0, 0, 0, 0, 0, 0);
+ Mat4Invert(target2local, local2target);
- Mat4MulSerie(local2target, ob->obmat, smd->target->imat, 0, 0, 0, 0, 0, 0);
- Mat4MulSerie(target2local, smd->target->obmat, ob->imat, 0, 0, 0, 0, 0, 0);
-
//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)
{
@@ -135,23 +314,45 @@
}
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);
- shrinkwrap_calc_nearest_point(target_dm, final, vert[i].no);
- //TODO linear interpolation: theres probably somewhere a function for this
- final[0] = orig[0] + weight * (final[0] - orig[0]);
- final[1] = orig[1] + weight * (final[1] - orig[1]);
- final[2] = orig[2] + weight * (final[2] - orig[2]);
+ //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:
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list