diff options
-rw-r--r-- | release/scripts/CreatePlane.py | 90 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_shrinkwrap.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/modifier.c | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/shrinkwrap.c | 158 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_modifier_types.h | 3 | ||||
-rw-r--r-- | source/blender/src/buttons_editing.c | 5 |
6 files changed, 198 insertions, 61 deletions
diff --git a/release/scripts/CreatePlane.py b/release/scripts/CreatePlane.py index 5b72c60f541..393a3a94e65 100644 --- a/release/scripts/CreatePlane.py +++ b/release/scripts/CreatePlane.py @@ -45,24 +45,23 @@ import Blender, bpy def matrix(dima, dimb): return [[0 for b in range(dimb)] for a in range(dima)] -def makelist(a): - res = [] - for i in a: - res.append(i) - return res - def dotProduct(a): - sum = 0.0 - for i in a: - sum += i*i - return sum + return reduce(lambda x, y: x + y*y, a) + +def manhattanDistance(a, b): + return reduce(lambda x, y: x + abs(y[0]-y[1]), zip(a, b), 0) + +def xrange_tuple(low, upper): + for i in xrange( low[0], upper[0]): + for j in xrange( low[1], upper[1]): + yield (i,j) + # For now simply decompose in a triangle fan def DecomposePolygon(poly): - for i in range(2, len(poly), 1): + for i in xrange(2, len(poly), 1): yield [ poly[0], poly[i-1], poly[i] ] - def Expand3dCoordsFrom2d(coords): for c in coords: yield ( c[0] , c[1], 0 ) @@ -76,34 +75,41 @@ def ExtractSections(image): mdim = max( image.size ) dx = float(image.size[0]) / x_samples dy = float(image.size[1]) / y_samples - ox = -float(x_samples)*0.5 - oy = -float(y_samples)*0.5 + + offset = [ -0.5*i for i in image.size] def scale(a): - return ( (a[0] + ox)*dx , (a[1] + oy)*dy ) - - used = matrix(x_samples, y_samples) - for a in range(x_samples): - for b in range(y_samples): - if dotProduct(image.getPixelHDR( (int)(a*dx), (int)(b*dy))) <= 1: - used[a][b] = 1 - - for a in range(x_samples-1): - for b in range(y_samples-1): - sum = used[a][b] + used[a+1][b] + used[a][b+1] + used[a+1][b+1] - - if sum == 4: - yield map( scale, [ (a,b) , (a+1,b), (a+1,b+1), (a,b+1) ] ) - elif sum == 3: - if not used[a][b]: - yield map( scale, [ (a+1,b), (a+1,b+1) , (a,b+1) ] ) - if not used[a+1][b]: - yield map( scale, [ (a,b), (a+1,b+1) , (a,b+1) ] ) - if not used[a][b+1]: - yield map( scale, [ (a,b), (a+1,b) , (a+1,b+1) ] ) - if not used[a+1][b+1]: - yield map( scale, [ (a,b), (a+1,b) , (a,b+1) ] ) - + return (a[0] + offset[0] , a[1] + offset[1]) + + sx = 0 +#(int) (float(image.size[0]) / (x_samples)) + sy = 0 +#(int) (float(image.size[1]) / (y_samples)) + + def get( center ): + best = None + for pos in xrange_tuple( (max(0, center[0]-sx),max(0, center[1]-sy)) , (min(image.size[0], center[0]+sx)+1, min(image.size[1], center[1]+sy)+1 )): + if dotProduct(image.getPixelHDR(pos[0],pos[1])) <= 1: + if best == None or manhattanDistance(center, pos) < manhattanDistance(center, best): + best = pos + return best + + + pos = matrix(x_samples, y_samples) + sdx = dx + sdy = dy + for a in xrange(x_samples): + for b in xrange(y_samples): + pos[a][b] = get(((int)(a*sdx),(int)(b*sdy))) + + for a in xrange(x_samples-1): + for b in xrange(y_samples-1): + arround = [ (a,b) , (a+1,b), (a+1,b+1), (a,b+1) ] + + valid = [ pos[c[0]][c[1]] for c in arround if pos[c[0]][c[1]] != None] + if len(valid) >= 3: + yield map( scale, valid ) + def ImportPlaneFromImage(image, mesh): @@ -134,8 +140,6 @@ def ImportPlaneFromImage(image, mesh): -#use the current image on the image editor? or ask the user what image to load -#image = Blender.Image.GetCurrent() def load_image(filename): print "Loading ",filename @@ -144,11 +148,13 @@ def load_image(filename): Blender.Scene.GetCurrent().objects.new(mesh) image = Blender.Image.Load(filename) - print image ImportPlaneFromImage(image, mesh) Blender.Redraw() -image = Blender.Window.FileSelector(load_image, "Load Image") +Blender.Window.FileSelector(load_image, "Load Image") +#use the current image on the image editor? or ask the user what image to load +#image = Blender.Image.GetCurrent() +#load_image("/home/darkaj/develop/blender/shrinkwrap/road.png") diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h index babdcd78261..3eb0b6fa579 100644 --- a/source/blender/blenkernel/BKE_shrinkwrap.h +++ b/source/blender/blenkernel/BKE_shrinkwrap.h @@ -39,6 +39,8 @@ typedef char* BitSet; #define bitset_get(set,index) ((set)[(index)>>3] & (1 << ((index)&0x7))) #define bitset_set(set,index) ((set)[(index)>>3] |= (1 << ((index)&0x7))) +#define bitset_unset(set,index) ((set)[(index)>>3] &= ~(1 << ((index)&0x7))) + struct Object; diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 63d2da31b20..cd65aace158 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -7021,6 +7021,7 @@ 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; } static void shrinkwrapModifier_copyData(ModifierData *md, ModifierData *target) diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 14ed29d0583..893cff3dd25 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -29,6 +29,7 @@ #include <string.h> #include <float.h> #include <math.h> +#include <memory.h> #include <stdio.h> #include <time.h> @@ -58,7 +59,7 @@ #define OUT_OF_MEMORY() ((void)printf("Shrinkwrap: Out of memory\n")) /* Benchmark macros */ -#if 1 +#if 0 #define BENCH(a) \ do { \ @@ -323,6 +324,82 @@ static float squared_dist(const float *a, const float *b) } /* + * + */ +static void derivedmesh_mergeNearestPoints(DerivedMesh *dm, float mdist, BitSet skipVert) +{ + if(mdist > 0.0f) + { + int i, j, merged; + int numVerts = dm->getNumVerts(dm); + int *translate_vert = MEM_mallocN( sizeof(int)*numVerts, "merge points array"); + + MVert *vert = dm->getVertDataArray(dm, CD_MVERT); + + if(!translate_vert) return; + + merged = 0; + for(i=0; i<numVerts; i++) + { + translate_vert[i] = i; + + if(skipVert && bitset_get(skipVert, i)) continue; + + for(j = 0; j<i; j++) + { + if(skipVert && bitset_get(skipVert, j)) continue; + if(squared_dist(vert[i].co, vert[j].co) < mdist) + { + translate_vert[i] = j; + merged++; + break; + } + } + } + + //some vertexs were merged.. recalculate structure (edges and faces) + if(merged > 0) + { + int numFaces = dm->getNumFaces(dm); + int freeVert; + MFace *face = dm->getFaceDataArray(dm, CD_MFACE); + + + //Adjust vertexs using the translation_table.. only translations to back indexs are allowed + //which means t[i] <= i must always verify + for(i=0, freeVert = 0; i<numVerts; i++) + { + if(translate_vert[i] == i) + { + memcpy(&vert[freeVert], &vert[i], sizeof(*vert)); + translate_vert[i] = freeVert++; + } + else translate_vert[i] = translate_vert[ translate_vert[i] ]; + } + + CDDM_lower_num_verts(dm, numVerts - merged); + + for(i=0; i<numFaces; i++) + { + MFace *f = face+i; + f->v1 = translate_vert[f->v1]; + f->v2 = translate_vert[f->v2]; + f->v3 = translate_vert[f->v3]; + //TODO be carefull with vertexs v4 being translated to 0 + f->v4 = translate_vert[f->v4]; + } + + //TODO: maybe update edges could be done outside this function + CDDM_calc_edges(dm); + //CDDM_calc_normals(dm); + } + + if(translate_vert) MEM_freeN( translate_vert ); + } +} + + +/* * This calculates the distance (in dir units) that the ray must travel to intersect plane * It can return negative values * @@ -703,25 +780,57 @@ static void shrinkwrap_removeUnused(ShrinkwrapCalcData *calc) BitSet used_faces = bitset_new(numFaces, "shrinkwrap used faces"); int numUsedFaces = 0; + + //calculate which vertexs need to be used + //even unmoved vertices might need to be used if theres a face that needs it //calc real number of faces, and vertices //Count used faces for(i=0; i<numFaces; i++) { - char res = bitset_get(moved_verts, face[i].v1) - | bitset_get(moved_verts, face[i].v2) - | bitset_get(moved_verts, face[i].v3) - | (face[i].v4 ? bitset_get(moved_verts, face[i].v4) : 0); + char res = 0; + if(bitset_get(moved_verts, face[i].v1)) res++; + if(bitset_get(moved_verts, face[i].v2)) res++; + if(bitset_get(moved_verts, face[i].v3)) res++; + if(face[i].v4 && bitset_get(moved_verts, face[i].v4)) res++; + + //Ignore a face were not a single vertice moved + if(res == 0) continue; - if(res) + //Only 1 vertice moved.. (if its a quad.. remove the vertice oposite to it) + if(res == 1 && face[i].v4) { - bitset_set(used_faces, i); //Mark face to maintain - numUsedFaces++; + if(bitset_get(moved_verts, face[i].v1)) + { + //remove vertex 3 + face[i].v3 = face[i].v4; + } + else if(bitset_get(moved_verts, face[i].v2)) + { + //remove vertex 4 + } + else if(bitset_get(moved_verts, face[i].v3)) + { + //remove vertex 1 + face[i].v1 = face[i].v4; + } + else if(bitset_get(moved_verts, face[i].v4)) + { + //remove vertex 2 + face[i].v2 = face[i].v3; + face[i].v3 = face[i].v4; + } - vert_index[face[i].v1] = 1; - vert_index[face[i].v2] = 1; - vert_index[face[i].v3] = 1; - if(face[i].v4) vert_index[face[i].v4] = 1; + face[i].v4 = 0; //this quad turned on a tri } + + bitset_set(used_faces, i); //Mark face to maintain + numUsedFaces++; + + //Mark vertices are needed + vert_index[face[i].v1] = 1; + vert_index[face[i].v2] = 1; + vert_index[face[i].v3] = 1; + if(face[i].v4) vert_index[face[i].v4] = 1; } //DP: Accumulate vertexs indexs.. (will calculate the new vertex index with a 1 offset) @@ -736,10 +845,16 @@ static void shrinkwrap_removeUnused(ShrinkwrapCalcData *calc) new_vert = new->getVertDataArray(new, CD_MVERT); for(i=0, t=0; i<numVerts; i++) { + if(vert_index[i] != t) { t = vert_index[i]; memcpy(new_vert++, vert+i, sizeof(MVert)); + + if(bitset_get(moved_verts, i)) + bitset_set(moved_verts, t-1); + else + bitset_unset(moved_verts, t-1); } } @@ -779,6 +894,7 @@ static void shrinkwrap_removeUnused(ShrinkwrapCalcData *calc) calc->final = new; } + /* Main shrinkwrap function */ DerivedMesh *shrinkwrapModifier_do(ShrinkwrapModifierData *smd, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc) { @@ -820,10 +936,12 @@ DerivedMesh *shrinkwrapModifier_do(ShrinkwrapModifierData *smd, Object *ob, Deri //Projecting target defined - lets work! if(calc.target) { +/* printf("Shrinkwrap (%s)%d over (%s)%d\n", calc.ob->id.name, calc.final->getNumVerts(calc.final), calc.smd->target->id.name, calc.target->getNumVerts(calc.target) ); +*/ switch(smd->shrinkType) { @@ -845,14 +963,21 @@ DerivedMesh *shrinkwrapModifier_do(ShrinkwrapModifierData *smd, Object *ob, Deri } - //Destroy faces, edges and stuff if(calc.moved) { + //Destroy faces, edges and stuff shrinkwrap_removeUnused(&calc); - bitset_free(calc.moved); + + if(calc.moved) + derivedmesh_mergeNearestPoints(calc.final, calc.smd->mergeDist, calc.moved); } - CDDM_calc_normals(calc.final); + CDDM_calc_normals(calc.final); + + //clean memory + if(calc.moved) + bitset_free(calc.moved); + return calc.final; } @@ -873,12 +998,11 @@ void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc) BVHTree *tree = NULL; BVHTreeNearest nearest; - BENCH_VAR(query); - int numVerts; MVert *vert = NULL; MDeformVert *dvert = NULL; + BENCH_VAR(query); BENCH(tree = bvhtree_from_mesh_verts(calc->target)); diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 7590cd0c3b9..25830321b93 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -495,8 +495,11 @@ typedef struct ShrinkwrapModifierData { struct Object *target; /* 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 */ diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 808a964019f..5e1cfbea183 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -1830,7 +1830,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md; height = 86; if (smd->shrinkType == MOD_SHRINKWRAP_NORMAL) - height += 19*5; + height += 19*6; } /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */ uiDefBut(block, ROUNDBOX, 0, "", x-10, y-height-2, width, height-2, NULL, 5.0, 0.0, 12, 40, ""); @@ -2461,9 +2461,10 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco uiDefButBitS(block, TOG, MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE, B_MODIFIER_RECALC, "Cull frontfaces", lx,(cy-=19),buttonWidth,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,(cy-=19),buttonWidth,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"); } - but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", lx, (cy-=19), buttonWidth,19, &smd->vgroup_name, 0.0, 31.0, 0, 0, "Vertex Group name"); + 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"); |