diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2011-01-02 20:38:22 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2011-01-02 20:38:22 +0300 |
commit | 78162fa7936761ef0aafbc641f1a1b0d9a3fb1ec (patch) | |
tree | 0ad5774da06f36b2214d8368cf5172df57ec7665 /source | |
parent | 24e80665d8272198783cd6a634cb47a7d289fb1c (diff) |
Splitting quad into triangles and merging triangles into quad should
work correct with sculpting data now.
Joining two triangles could give incorrect sculpting result for
special topologies, but it's that case that can't be nicely handled
with our layers architecture.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_multires.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/customdata.c | 47 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/multires.c | 44 |
3 files changed, 88 insertions, 4 deletions
diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index b8131d69dfd..5bdea166cce 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -87,6 +87,7 @@ void mdisp_rot_crn_to_face(int S, int corners, int face_side, float x, float y, int mdisp_rot_face_to_crn(int corners, int face_side, float u, float v, float *x, float *y); void mdisp_apply_weight(int S, int corners, int x, int y, int face_side, float crn_weight[4][2], float *u_r, float *v_r); void mdisp_flip_disp(int S, int corners, float axis_x[2], float axis_y[2], float disp[3]); +void mdisp_join_tris(struct MDisps *dst, struct MDisps *tri1, struct MDisps *tri2); #endif diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 2d4e65f8f94..f7606a344c9 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -441,16 +441,55 @@ static void layerInterp_mdisps(void **sources, float *UNUSED(weights), int i, x, y; int side, S, dst_corners, src_corners; float crn_weight[4][2]; - float (*sw)[4] = NULL; + float (*sw)[4] = (void*)sub_weights; float (*disps)[3], (*out)[3]; s = sources[0]; dst_corners = multires_mdisp_corners(d); src_corners = multires_mdisp_corners(s); - /* XXX: For now, some restrictions on the input - should be implemented to allow quad<->tris face conversion */ - if(count != 1 || !sub_weights || dst_corners != src_corners) { + if(sub_weights && count == 2 && src_corners == 3) { + src_corners = multires_mdisp_corners(sources[1]); + + /* special case -- converting two triangles to quad */ + if(src_corners == 3 && dst_corners == 4) { + MDisps tris[2]; + int vindex[4] = {0}; + + S = 0; + for(i = 0; i < 2; i++) + for(y = 0; y < 4; y++) + for(x = 0; x < 4; x++) + if(sw[x+i*4][y]) + vindex[x] = y; + + for(i = 0; i < 2; i++) { + float sw[4][4] = {{0}}; + int a = 7 & ~(1 << vindex[i*2] | 1 << vindex[i*2+1]); + + sw[0][vindex[i*2+1]] = 1; + sw[1][vindex[i*2]] = 1; + + for(x = 0; x < 3; x++) + if(a & (1 << x)) + sw[2][x] = 1; + + tris[i] = *((MDisps*)sources[i]); + tris[i].disps = MEM_dupallocN(tris[i].disps); + layerInterp_mdisps(&sources[i], NULL, (float*)sw, 1, &tris[i]); + } + + mdisp_join_tris(d, &tris[0], &tris[1]); + + for(i = 0; i < 2; i++) + MEM_freeN(tris[i].disps); + + return; + } + } + + /* For now, some restrictions on the input */ + if(count != 1 || !sub_weights) { for(i = 0; i < d->totdisp; ++i) zero_v3(d->disps[i]); diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 68ee0d0d0cd..84350127968 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -1981,3 +1981,47 @@ void mdisp_flip_disp(int S, int corners, float axis_x[2], float axis_y[2], float disp[1] = 0; } } + +/* Join two triangular displacements into one quad + Corners mapping: + 2 -------- 3 + | \ tri2 | + | \ | + | tri1 \ | + 0 -------- 1 */ +void mdisp_join_tris(MDisps *dst, MDisps *tri1, MDisps *tri2) +{ + int side, st; + int S, x, y, crn; + float face_u, face_v, crn_u, crn_v; + float (*out)[3]; + MDisps *src; + + if(dst->disps) + MEM_freeN(dst->disps); + + side = sqrt(tri1->totdisp / 3); + st = (side<<1)-1; + + dst->totdisp = 4 * side * side; + out = dst->disps = MEM_callocN(3*dst->totdisp*sizeof(float), "join disps"); + + for(S = 0; S < 4; S++) + for(y = 0; y < side; ++y) + for(x = 0; x < side; ++x, ++out) { + mdisp_rot_crn_to_face(S, 4, st, x, y, &face_u, &face_v); + face_u = st - 1 - face_u; + + if(face_v > face_u) { + src = tri2; + face_u = st - 1 - face_u; + face_v = st - 1 - face_v; + } else src = tri1; + + crn = mdisp_rot_face_to_crn(3, st, face_u, face_v, &crn_u, &crn_v); + + old_mdisps_bilinear((*out), &src->disps[crn*side*side], side, crn_u, crn_v); + (*out)[0] = 0; + (*out)[1] = 0; + } +} |