Commit: b535223b2913aea15d1c1fe7024d6bc8f295a8a2 Author: YimingWu Date: Sun Aug 11 11:07:11 2019 +0800 Branches: soc-2019-npr https://developer.blender.org/rBb535223b2913aea15d1c1fe7024d6bc8f295a8a2
LANPR: Smooth contour modifier file. =================================================================== A source/blender/modifiers/intern/MOD_smoothcontour.c =================================================================== diff --git a/source/blender/modifiers/intern/MOD_smoothcontour.c b/source/blender/modifiers/intern/MOD_smoothcontour.c new file mode 100644 index 00000000000..40d08043a29 --- /dev/null +++ b/source/blender/modifiers/intern/MOD_smoothcontour.c @@ -0,0 +1,4799 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +/** \file blender/modifiers/intern/MOD_mybmesh.c + * \ingroup modifiers + */ + +/* This code is based of the tessellation part of the paper + * "Computing Smooth Surface Contours with Accurate Topology" + * (Pierre Bénard, Aaron Hertzmann, Michael Kass). + * Currently available at: + * http://www.labri.fr/perso/pbenard/publications/contours.html + * + * The numbers in the comments refers to the chapters in the paper. + */ + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" +#include "BLI_string.h" +#include "BLI_utildefines.h" +#include "BLI_buffer.h" +#include "BLI_alloca.h" +#include "BLI_ghash.h" +#include "BLI_gsqueue.h" +#include "BLI_memarena.h" +#include "BLI_rand.h" +#include "BLI_listbase.h" +#include "BLI_threads.h" + +#include "BKE_library_query.h" +#include "BKE_modifier.h" +#include "BKE_mesh.h" +#include "BKE_mesh_mapping.h" +#include "BKE_deform.h" + +#include "bmesh.h" +#include "bmesh_tools.h" + +#include "MOD_util.h" +#include "MOD_modifiertypes.h" + +#include "DEG_depsgraph_build.h" + +// BMesh intern +#include "../../bmesh/intern/bmesh_private.h" + +// TODO this modifier depends on OpenSubDiv. So if it's not compiled in, remove this modifier + +#include "../../../../intern/opensubdiv/opensubdiv_capi.h" +#include "../../../../intern/opensubdiv/opensubdiv_converter_capi.h" +#include "../../../../intern/opensubdiv/opensubdiv_evaluator_capi.h" +#include "../../../../intern/opensubdiv/opensubdiv_topology_refiner_capi.h" + +#include "../../blenkernel/intern/subdiv_converter.h" + +#include "PIL_time.h" +#include "PIL_time_utildefines.h" + +struct OpenSubdiv_Evaluator; + +typedef struct { + BMVert *vert; // Only used for shifted verts + BMEdge *orig_edge; + BMFace *orig_face; + float u, v; +} Vert_buf; + +typedef struct { + BMEdge *cusp_e; + BMFace *orig_face; + float cusp_co[3]; + float cusp_no[3]; + + float u, v; +} Cusp; + +typedef struct { + bool b_arr[3]; + bool kr_arr[3]; + float co_arr[3][3]; + float u_arr[3]; + float v_arr[3]; +} Cusp_triang; + +typedef struct { + BMVert *vert; + BMVert *C_vert; + // Can we extend this radial vert? + bool extendable; + bool is_B; + float radi_plane_no[3]; +} Radi_vert; + +typedef struct { + BMFace *face; + // Should be front or back facing? + bool back_f; +} IncoFace; + +typedef struct { + BMesh *bm; + BMesh *bm_orig; + + float cam_loc[3]; + + GHash *vert_hash; + + BLI_Buffer *new_vert_buffer; + BLI_Buffer *shifted_verts; + BLI_Buffer *cusp_edges; + BLI_Buffer *C_verts; + BLI_Buffer *cusp_verts; + BLI_Buffer *radi_vert_buffer; + // Idx of next inserted vert + int new_vert_idx; + // Radial edge vert start idx + int radi_start_idx; + + struct OpenSubdiv_Evaluator *eval; +} MeshData; + +// TODO for Kr look in subdiv.cpp in coutours source code (II) + +// TODO dynamic arrays, use BLI_stack, BLI_buffer, BLI_mempool, BLI_memarena. + +static void verts_to_limit(BMesh *bm, struct OpenSubdiv_Evaluator *eval) +{ + + int i, j; + + BMIter iter_v, iter_f; + BMVert *vert; + BMFace *f; + + // TODO is it possible to only get non adjusted verts? + // IE not moving a vert more than once. + + BM_ITER_MESH_INDEX (f, &iter_f, bm, BM_FACES_OF_MESH, i) { + BM_ITER_ELEM_INDEX (vert, &iter_v, f, BM_VERTS_OF_FACE, j) { + float u, v, du[3], dv[3]; + switch (j) { + case 1: + u = 1, v = 0; + break; + case 2: + u = v = 1; + break; + case 3: + u = 0, v = 1; + break; + default: + u = v = 0; + break; + } + eval->evaluateLimit(eval, i, u, v, vert->co, du, dv); + // Adjust vert normal to the limit normal + cross_v3_v3v3(vert->no, du, dv); + normalize_v3(vert->no); + // printf("j: %d\n",j); + } + // printf("i: %d\n",i); + // printf("face i: %d\n", BM_elem_index_get(f)); + } +} + +static Vert_buf *get_shift_vert(BMVert *vert, MeshData *m_d) +{ + int vert_i; + + // check if vert is in the buffer + for (vert_i = 0; vert_i < m_d->shifted_verts->count; vert_i++) { + Vert_buf *buf = &BLI_buffer_at(m_d->shifted_verts, Vert_buf, vert_i); + if (vert == buf->vert) { + return buf; + } + } + return NULL; +} + +static void add_shifted_vert(BMVert *vert, BMFace *orig_face, float uv[2], MeshData *m_d) +{ + Vert_buf *buf = get_shift_vert(vert, m_d); + + if (buf != NULL) { + buf->orig_face = orig_face; + buf->u = uv[0]; + buf->v = uv[1]; + return; + } + + int orig_verts = BM_mesh_elem_count(m_d->bm_orig, BM_VERT); + int v_idx = BM_elem_index_get(vert); + if ((v_idx + 1) > orig_verts) { + // If this is a non original vert, just update the data instead + Vert_buf *v_buf = &BLI_buffer_at(m_d->new_vert_buffer, Vert_buf, v_idx - orig_verts); + v_buf->orig_face = orig_face; + v_buf->orig_edge = NULL; + v_buf->u = uv[0]; + v_buf->v = uv[1]; + } + else { + Vert_buf new_buf; + new_buf.orig_face = orig_face; + new_buf.vert = vert; + new_buf.u = uv[0]; + new_buf.v = uv[1]; + BLI_buffer_append(m_d->shifted_verts, Vert_buf, new_buf); + } +} + +static bool calc_if_B(const float cam_loc[3], + const float P[3], + const float du[3], + const float dv[3]) +{ + // Is the point back facing? + float nor[3], view_vec[3]; + + cross_v3_v3v3(nor, du, dv); + // TODO normalization is probably not needed + normalize_v3(nor); + sub_v3_v3v3(view_vec, cam_loc, P); + + return (dot_v3v3(nor, view_vec) < 0); +} + +static bool calc_if_B_nor(const float cam_loc[3], const float P[3], const float nor[3]) +{ + // Is the point back facing? + float view_vec[3]; + + sub_v3_v3v3(view_vec, cam_loc, P); + + return (dot_v3v3(nor, view_vec) < 0); +} + +static float get_facing_dir(const float cam_loc[3], + const float P[3], + const float du[3], + const float dv[3]) +{ + // Get if point is back facing (-) or front facing (+). Zero if it's directly on the contour + float nor[3], view_vec[3]; + + cross_v3_v3v3(nor, du, dv); + normalize_v3(nor); + sub_v3_v3v3(view_vec, cam_loc, P); + normalize_v3(view_vec); + + return dot_v3v3(nor, view_vec); +} + +static float get_facing_dir_nor(const float cam_loc[3], const float P[3], const float nor[3]) +{ + // Get if point is back facing (-) or front facing (+). Zero if it's directly on the contour + float view_vec[3]; + + sub_v3_v3v3(view_vec, cam_loc, P); + normalize_v3(view_vec); + + return dot_v3v3(nor, view_vec); +} + +static BMVert *split_edge_and_move_nor( + MeshData *m_d, BMesh *bm, BMEdge *edge, const float new_pos[3], const float new_no[3]) +{ + // Split edge one time and move the created vert to new_pos + BMVert *vert; + int face_count = BM_edge_face_count(edge); + BMFace **face_arr = BLI_array_alloca(face_arr, face_count); + + BMIter iter; + BMFace *face; + int i; + + // Save the connected faces for triangulation later + BM_ITER_ELEM_INDEX (face, &iter, edge, BM_FACES_OF_EDGE, i) { + face_arr[i] = face; + } + + if (i > 2) { + print_v3("deg coord", edge->v1->co); + printf("Deg face!\n"); + } + + // printf("Split edge!\n"); + + // TODO perhaps use BM_edge_split instead? + vert = bmesh_kernel_split_edge_make_vert(bm, edge->v1, edge, NULL); + if (m_d != NULL) { + BM_elem_index_set(vert, m_d->new_vert_idx++); + } + + /*{ + MemArena *pf_arena; + pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__); + LinkNode *faces_double = NULL; + BM_face_triangulate( + bm, face_arr[0], + NULL, NULL, + NULL, NULL, + &faces_double, + MOD_TRIANGULATE_QUAD_FIXED, + 0,false, + pf_arena, + NULL, NULL); + + BM_face_triangulate( + bm, face_arr[1], + NULL, NULL, + NULL, NULL, + &faces_double, + MOD_TRIANGULATE_QUAD_FIXED, + 0,false, + pf_arena, + NULL, NULL); + + while (faces_double) { + LinkNode *next = faces_double->next; + BM_face_kill(bm, faces_double->link); + MEM_freeN(faces_double); + faces_double = next; + } + BLI_memarena_free(pf_arena); + }*/ + + // Triangulate the faces connected to the new vert + { + BMLoop *start; + BMLoop *end; + + BMFace *new_f; + + for (int j = 0; j < i; j++) { + start = BM_face_vert_share_loop(face_arr[j], vert); + end = (start->next)->next; + + // TODO maybe use bmesh_sfme instead? + new_f = BM_face_split(bm, face_arr[j], start, end, NULL, NULL, false); + + BM_face_normal_update(face_arr[j]); + BM_face_normal_update(new_f); + } + } + + copy_v3_v3(vert->co, new_pos); + // Adjust vert normal to the limit normal + copy_v3_v3(vert->no, new_no); + normalize_v3(vert->no); + + return vert; +} + +static BMVert *split_edge_and_move_vert(MeshData *m_d, + BMesh *bm, + BMEdge *edge, + @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list [email protected] https://lists.blender.org/mailman/listinfo/bf-blender-cvs
