From 9633d198fbe4ca0f27b8d955ccd29d473364ce6e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 14 Dec 2009 23:35:13 +0000 Subject: solidify from 2.4x (ported from python to C) - shell_angle_to_dist() was using degrees --- source/blender/editors/include/ED_mesh.h | 3 + source/blender/editors/mesh/editmesh_lib.c | 147 ++++++++++++++++++++++++++++ source/blender/editors/mesh/editmesh_mods.c | 43 ++++++++ source/blender/editors/mesh/mesh_intern.h | 2 + source/blender/editors/mesh/mesh_ops.c | 2 + 5 files changed, 197 insertions(+) (limited to 'source/blender/editors') diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 58f4a566ff7..aab364bf686 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -147,6 +147,9 @@ void EM_free_uv_vert_map(struct UvVertMap *vmap); void EM_add_data_layer(struct EditMesh *em, struct CustomData *data, int type); void EM_free_data_layer(struct EditMesh *em, struct CustomData *data, int type); +void EM_make_hq_normals(struct EditMesh *em); +void EM_solidify(struct EditMesh *em, float dist); + /* editmesh_mods.c */ extern unsigned int em_vertoffs, em_solidoffs, em_wireoffs; diff --git a/source/blender/editors/mesh/editmesh_lib.c b/source/blender/editors/mesh/editmesh_lib.c index 544dd790dc8..89b6abb14f0 100644 --- a/source/blender/editors/mesh/editmesh_lib.c +++ b/source/blender/editors/mesh/editmesh_lib.c @@ -49,6 +49,7 @@ editmesh_lib: generic (no UI, no menus) operations/evaluators for editmesh data #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_editVert.h" +#include "BLI_edgehash.h" #include "BKE_customdata.h" #include "BKE_context.h" @@ -2287,3 +2288,149 @@ int EM_view3d_poll(bContext *C) return 1; return 0; } + +/* higher quality normals */ + +/* NormalCalc */ +/* NormalCalc modifier: calculates higher quality normals +*/ + +/* each edge uses this to */ +typedef struct EdgeFaceRef { + int f1; /* init as -1 */ + int f2; +} EdgeFaceRef; + +void EM_make_hq_normals(EditMesh *em) +{ + EditFace *efa; + EditVert *eve; + int i; + + EdgeHash *edge_hash = BLI_edgehash_new(); + EdgeHashIterator *edge_iter; + int edge_ref_count = 0; + int ed_v1, ed_v2; /* use when getting the key */ + EdgeFaceRef *edge_ref_array = MEM_callocN(em->totedge * sizeof(EdgeFaceRef), "Edge Connectivity"); + EdgeFaceRef *edge_ref; + float edge_normal[3]; + + EM_init_index_arrays(em, 1, 1, 1); + + for(eve= em->verts.first, i=0; eve; eve= eve->next, i++) { + zero_v3(eve->no); + eve->tmp.l= i; + } + + /* This function adds an edge hash if its not there, and adds the face index */ +#define NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(EDV1, EDV2); \ + edge_ref = (EdgeFaceRef *)BLI_edgehash_lookup(edge_hash, EDV1, EDV2); \ + if (!edge_ref) { \ + edge_ref = &edge_ref_array[edge_ref_count]; edge_ref_count++; \ + edge_ref->f1=i; \ + edge_ref->f2=-1; \ + BLI_edgehash_insert(edge_hash, EDV1, EDV2, edge_ref); \ + } else { \ + edge_ref->f2=i; \ + } + + + efa= em->faces.first; + for(i = 0; i < em->totface; i++, efa= efa->next) { + if(efa->v4) { + NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v1->tmp.l, efa->v2->tmp.l); + NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v2->tmp.l, efa->v3->tmp.l); + NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v3->tmp.l, efa->v4->tmp.l); + NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v4->tmp.l, efa->v1->tmp.l); + } else { + NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v1->tmp.l, efa->v2->tmp.l); + NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v2->tmp.l, efa->v3->tmp.l); + NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v3->tmp.l, efa->v1->tmp.l); + } + } + +#undef NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE + + + for(edge_iter = BLI_edgehashIterator_new(edge_hash); !BLI_edgehashIterator_isDone(edge_iter); BLI_edgehashIterator_step(edge_iter)) { + /* Get the edge vert indicies, and edge value (the face indicies that use it)*/ + BLI_edgehashIterator_getKey(edge_iter, (int*)&ed_v1, (int*)&ed_v2); + edge_ref = BLI_edgehashIterator_getValue(edge_iter); + + if (edge_ref->f2 != -1) { + /* We have 2 faces using this edge, calculate the edges normal + * using the angle between the 2 faces as a weighting */ + add_v3_v3v3(edge_normal, EM_get_face_for_index(edge_ref->f1)->n, EM_get_face_for_index(edge_ref->f2)->n); + normalize_v3(edge_normal); + mul_v3_fl(edge_normal, angle_normalized_v3v3(EM_get_face_for_index(edge_ref->f1)->n, EM_get_face_for_index(edge_ref->f2)->n)); + } else { + /* only one face attached to that edge */ + /* an edge without another attached- the weight on this is + * undefined, M_PI/2 is 90d in radians and that seems good enough */ + VECCOPY(edge_normal, EM_get_face_for_index(edge_ref->f1)->n) + mul_v3_fl(edge_normal, M_PI/2); + } + add_v3_v3(EM_get_vert_for_index(ed_v1)->no, edge_normal ); + add_v3_v3(EM_get_vert_for_index(ed_v2)->no, edge_normal ); + + + } + BLI_edgehashIterator_free(edge_iter); + BLI_edgehash_free(edge_hash, NULL); + MEM_freeN(edge_ref_array); + + /* normalize vertex normals and assign */ + for(eve= em->verts.first; eve; eve= eve->next) + normalize_v3(eve->no); + + EM_free_index_arrays(); +} + +#define FLT_EPSILON 0.00001 +void EM_solidify(EditMesh *em, float dist) +{ + EditFace *efa; + EditVert *eve; + int *vert_users= MEM_callocN(sizeof(int) * em->totvert, "EM_offset"); + float *vert_angles= MEM_callocN(sizeof(float) * em->totvert, "EM_offset"); + float angle; + int i; + + for(eve= em->verts.first, i=0; eve; eve= eve->next, i++) { + eve->tmp.l= i; + } + + efa= em->faces.first; + for(i = 0; i < em->totface; i++, efa= efa->next) { + + if(!(efa->f & SELECT)) + continue; + + angle= angle_normalized_v3v3(efa->v1->no, efa->n); + vert_angles[efa->v1->tmp.l]+= shell_angle_to_dist(angle); + vert_users[efa->v1->tmp.l]++; + + angle= angle_normalized_v3v3(efa->v2->no, efa->n); + vert_angles[efa->v2->tmp.l]+= shell_angle_to_dist(angle); + vert_users[efa->v2->tmp.l]++; + + angle= angle_normalized_v3v3(efa->v3->no, efa->n); + vert_angles[efa->v3->tmp.l]+= shell_angle_to_dist(angle); + vert_users[efa->v3->tmp.l]++; + + if(efa->v4) { + angle= angle_normalized_v3v3(efa->v4->no, efa->n); + vert_angles[efa->v4->tmp.l]+= shell_angle_to_dist(angle); + vert_users[efa->v4->tmp.l]++; + } + } + + for(eve= em->verts.first, i=0; eve; eve= eve->next, i++) { + if(vert_users[i]) { /* zero if unselected */ + madd_v3_v3fl(eve->co, eve->no, dist * (vert_angles[i] / (float)vert_users[i])); + } + } + + MEM_freeN(vert_users); + MEM_freeN(vert_angles); +} diff --git a/source/blender/editors/mesh/editmesh_mods.c b/source/blender/editors/mesh/editmesh_mods.c index 30dc6114097..1d8b2b05592 100644 --- a/source/blender/editors/mesh/editmesh_mods.c +++ b/source/blender/editors/mesh/editmesh_mods.c @@ -4542,3 +4542,46 @@ void MESH_OT_flip_normals(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } + +static int solidify_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + Object *obedit= CTX_data_edit_object(C); + EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); + float nor[3] = {0,0,1}; + + float thickness= RNA_float_get(op->ptr, "thickness"); + + extrudeflag(obedit, em, SELECT, nor); + EM_make_hq_normals(em); + EM_solidify(em, thickness); + + + /* update vertex normals too */ + recalc_editnormals(em); + + BKE_mesh_end_editmesh(obedit->data, em); + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + + +void MESH_OT_solidify(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Solidify"; + ot->description= "Make the mesh solid."; + ot->idname= "MESH_OT_solidify"; + + /* api callbacks */ + ot->exec= solidify_exec; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_float(ot->srna, "thickness", 0.1f, -FLT_MAX, FLT_MAX, "thickness", "", -10.0f, 10.0f); +} diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 4ce9afaf237..226cfe875d7 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -164,6 +164,8 @@ void MESH_OT_mark_seam(struct wmOperatorType *ot); void MESH_OT_mark_sharp(struct wmOperatorType *ot); void MESH_OT_vertices_smooth(struct wmOperatorType *ot); void MESH_OT_flip_normals(struct wmOperatorType *ot); +void MESH_OT_solidify(struct wmOperatorType *ot); + extern EditEdge *findnearestedge(ViewContext *vc, int *dist); extern void EM_automerge(Scene *scene, Object *obedit, int update); diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 5f54aa041e3..b067f894050 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -151,6 +151,8 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_edgering_select); WM_operatortype_append(MESH_OT_loopcut); + + WM_operatortype_append(MESH_OT_solidify); } int ED_operator_editmesh_face_select(bContext *C) -- cgit v1.2.3