From 570b13fbba045b047174d499343eaabcb5820b08 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 4 Jan 2012 14:42:11 +0000 Subject: update UV project modifier to use MLoopUV's rather then tessface UV's --- source/blender/blenkernel/BKE_mesh.h | 3 + source/blender/blenkernel/intern/mesh.c | 78 +++++++++++++++++++++++++ source/blender/modifiers/intern/MOD_uvproject.c | 70 ++++++++++++---------- 3 files changed, 120 insertions(+), 31 deletions(-) diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 744e0e56ab6..9172ad86fee 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -86,6 +86,9 @@ int mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata, void mesh_calc_poly_normal(struct MPoly *mpoly, struct MLoop *loopstart, struct MVert *mvarray, float no[3]); +void mesh_calc_poly_normal_coords(struct MPoly *mpoly, struct MLoop *loopstart, + const float (*vertex_coords)[3], float no[3]); + void mesh_calc_poly_center(struct MPoly *mpoly, struct MLoop *loopstart, struct MVert *mvarray, float cent[3]); diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index d0c61655da3..4f5a42a50ce 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -2600,6 +2600,84 @@ void mesh_calc_poly_normal(MPoly *mpoly, MLoop *loopstart, no[2] = 1.0; } } +/* duplicate of function above _but_ takes coords rather then mverts */ +static void mesh_calc_ngon_normal_coords(MPoly *mpoly, MLoop *loopstart, + const float (*vertex_coords)[3], float normal[3]) +{ + + float *v1, *v2, *v3; + double u[3], v[3], w[3]; + double n[3] = {0.0, 0.0, 0.0}, l; + int i; + + for(i = 0; i < mpoly->totloop; i++){ + v1 = vertex_coords + loopstart[i].v; + v2 = vertex_coords + loopstart[(i+1)%mpoly->totloop].v; + v3 = vertex_coords + loopstart[(i+2)%mpoly->totloop].v; + + VECCOPY(u, v1); + VECCOPY(v, v2); + VECCOPY(w, v3); + + /*this fixes some weird numerical error*/ + if (i==0) { + u[0] += 0.0001f; + u[1] += 0.0001f; + u[2] += 0.0001f; + } + + n[0] += (u[1] - v[1]) * (u[2] + v[2]); + n[1] += (u[2] - v[2]) * (u[0] + v[0]); + n[2] += (u[0] - v[0]) * (u[1] + v[1]); + } + + l = n[0]*n[0]+n[1]*n[1]+n[2]*n[2]; + l = sqrt(l); + + if (l == 0.0) { + normal[0] = 0.0f; + normal[1] = 0.0f; + normal[2] = 1.0f; + + return; + } else l = 1.0f / l; + + n[0] *= l; + n[1] *= l; + n[2] *= l; + + normal[0] = (float) n[0]; + normal[1] = (float) n[1]; + normal[2] = (float) n[2]; +} + +void mesh_calc_poly_normal_coords(MPoly *mpoly, MLoop *loopstart, + const float (*vertex_coords)[3], float no[3]) +{ + if (mpoly->totloop > 4) { + mesh_calc_ngon_normal_coords(mpoly, loopstart, vertex_coords, no); + } + else if (mpoly->totloop == 3){ + normal_tri_v3(no, + vertex_coords[loopstart[0].v], + vertex_coords[loopstart[1].v], + vertex_coords[loopstart[2].v] + ); + } + else if (mpoly->totloop == 4) { + normal_quad_v3(no, + vertex_coords[loopstart[0].v], + vertex_coords[loopstart[1].v], + vertex_coords[loopstart[2].v], + vertex_coords[loopstart[3].v] + ); + } + else { /* horrible, two sided face! */ + no[0] = 0.0; + no[1] = 0.0; + no[2] = 1.0; + } +} static void mesh_calc_ngon_center(MPoly *mpoly, MLoop *loopstart, MVert *mvert, float cent[3]) diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c index 2aed6f05277..47c8e2a7d05 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.c +++ b/source/blender/modifiers/intern/MOD_uvproject.c @@ -47,6 +47,7 @@ #include "BKE_camera.h" +#include "BKE_mesh.h" #include "BKE_DerivedMesh.h" #include "MOD_modifiertypes.h" @@ -147,10 +148,12 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, Object *ob, DerivedMesh *dm) { float (*coords)[3], (*co)[3]; - MTFace *tface; - int i, numVerts, numFaces; + MLoopUV *mloop_uv; + MTexPoly *mtexpoly, *mt; + int i, numVerts, numPolys, numLoops; Image *image = umd->image; - MFace *mface, *mf; + MPoly *mpoly, *mp; + MLoop *mloop; int override_image = ((umd->flags & MOD_UVPROJECT_OVERRIDEIMAGE) != 0); Projector projectors[MOD_UVPROJECT_MAXPROJECTORS]; int num_projectors = 0; @@ -172,10 +175,10 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, /* make sure there are UV Maps available */ - if(!CustomData_has_layer(&dm->faceData, CD_MTFACE)) return dm; + if(!CustomData_has_layer(&dm->loopData, CD_MLOOPUV)) return dm; /* make sure we're using an existing layer */ - CustomData_validate_layer_name(&dm->faceData, CD_MTFACE, umd->uvlayer_name, uvname); + CustomData_validate_layer_name(&dm->loopData, CD_MLOOPUV, umd->uvlayer_name, uvname); /* calculate a projection matrix and normal for each projector */ for(i = 0; i < num_projectors; ++i) { @@ -259,11 +262,16 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, mul_mat3_m4_v3(projectors[i].ob->obmat, projectors[i].normal); } - numFaces = dm->getNumTessFaces(dm); + numPolys = dm->getNumPolys(dm); + numLoops = dm->getNumLoops(dm); /* make sure we are not modifying the original UV map */ - tface = CustomData_duplicate_referenced_layer_named(&dm->faceData, - CD_MTFACE, uvname, numFaces); + mloop_uv = CustomData_duplicate_referenced_layer_named(&dm->loopData, + CD_MLOOPUV, uvname, numLoops); + + /* can be NULL */ + mtexpoly = CustomData_duplicate_referenced_layer_named(&dm->polyData, + CD_MTEXPOLY, uvname, numPolys); numVerts = dm->getNumVerts(dm); @@ -280,26 +288,28 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, for(i = 0, co = coords; i < numVerts; ++i, ++co) mul_project_m4_v3(projectors[0].projmat, *co); - mface = dm->getTessFaceArray(dm); - numFaces = dm->getNumTessFaces(dm); + mpoly = dm->getPolyArray(dm); + mloop = dm->getLoopArray(dm); /* apply coords as UVs, and apply image if tfaces are new */ - for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tface) { - if(override_image || !image || tface->tpage == image) { + for(i = 0, mp = mpoly; i < numPolys; ++i, ++mp, ++mt) { + if(override_image || !image || (mtexpoly == NULL || mt->tpage == image)) { if(num_projectors == 1) { if(projectors[0].uci) { - unsigned int fidx= mf->v4 ? 3:2; + unsigned int fidx= mp->totloop - 1; do { - unsigned int vidx= *(&mf->v1 + fidx); - project_from_camera(tface->uv[fidx], coords[vidx], projectors[0].uci); + unsigned int lidx= mp->loopstart + fidx; + unsigned int vidx= mloop[lidx].v; + project_from_camera(mloop_uv[lidx].uv, coords[vidx], projectors[0].uci); } while (fidx--); } else { /* apply transformed coords as UVs */ - unsigned int fidx= mf->v4 ? 3:2; + unsigned int fidx= mp->totloop - 1; do { - unsigned int vidx= *(&mf->v1 + fidx); - copy_v2_v2(tface->uv[fidx], coords[vidx]); + unsigned int lidx= mp->loopstart + fidx; + unsigned int vidx= mloop[lidx].v; + copy_v2_v2(mloop_uv[lidx].uv, coords[vidx]); } while (fidx--); } } else { @@ -312,11 +322,7 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, float best_dot; /* get the untransformed face normal */ - if(mf->v4) { - normal_quad_v3(face_no, coords[mf->v1], coords[mf->v2], coords[mf->v3], coords[mf->v4]); - } else { - normal_tri_v3(face_no, coords[mf->v1], coords[mf->v2], coords[mf->v3]); - } + mesh_calc_poly_normal_coords(mp, mloop + mp->loopstart, (const float (*)[3])coords, face_no); /* find the projector which the face points at most directly * (projector normal with largest dot product is best) @@ -334,29 +340,31 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, } if(best_projector->uci) { - unsigned int fidx= mf->v4 ? 3:2; + unsigned int fidx= mp->totloop - 1; do { - unsigned int vidx= *(&mf->v1 + fidx); - project_from_camera(tface->uv[fidx], coords[vidx], best_projector->uci); + unsigned int lidx= mp->loopstart + fidx; + unsigned int vidx= mloop[lidx].v; + project_from_camera(mloop_uv[lidx].uv, coords[vidx], best_projector->uci); } while (fidx--); } else { - unsigned int fidx= mf->v4 ? 3:2; + unsigned int fidx= mp->totloop - 1; do { - unsigned int vidx= *(&mf->v1 + fidx); + unsigned int lidx= mp->loopstart + fidx; + unsigned int vidx= mloop[lidx].v; float tco[3]; copy_v3_v3(tco, coords[vidx]); mul_project_m4_v3(best_projector->projmat, tco); - copy_v2_v2(tface->uv[fidx], tco); + copy_v2_v2(mloop_uv[lidx].uv, tco); } while (fidx--); } } } - if(override_image) { - tface->tpage = image; + if(override_image && mtexpoly) { + mt->tpage = image; } } -- cgit v1.2.3