Preparte curvature fairing and Fairing edit mode operator
This commit is contained in:
parent
f32d3f7b06
commit
ac8c589b7c
|
@ -3624,6 +3624,8 @@ class VIEW3D_MT_edit_mesh(Menu):
|
|||
if with_bullet:
|
||||
layout.operator("mesh.convex_hull")
|
||||
|
||||
layout.operator("mesh.fair_vertices", text="Fair")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("mesh.symmetrize")
|
||||
|
|
|
@ -36,6 +36,7 @@ extern "C" {
|
|||
typedef enum eMeshFairingDepth {
|
||||
MESH_FAIRING_DEPTH_POSITION = 1,
|
||||
MESH_FAIRING_DEPTH_TANGENCY = 2,
|
||||
MESH_FAIRING_DEPTH_CURVATURE = 3,
|
||||
} eMeshFairingDepth;
|
||||
|
||||
/* affect_vertices is used to define the fairing area. Indexed by vertex index, set to true when
|
||||
|
|
|
@ -67,6 +67,9 @@ class FairingContext {
|
|||
/* Get the other vertex index for a loop. */
|
||||
virtual int other_vertex_index_from_loop(const int loop, const unsigned int v) = 0;
|
||||
|
||||
virtual int vertex_index_from_loop(const int loop) = 0;
|
||||
virtual float cotangent_loop_weight_get(const int loop) = 0;
|
||||
|
||||
int vertex_count_get()
|
||||
{
|
||||
return totvert_;
|
||||
|
@ -74,7 +77,7 @@ class FairingContext {
|
|||
|
||||
int loop_count_get()
|
||||
{
|
||||
return totvert_;
|
||||
return totloop_;
|
||||
}
|
||||
|
||||
MeshElemMap *vertex_loop_map_get(const int v)
|
||||
|
@ -219,6 +222,15 @@ class MeshFairingContext : public FairingContext {
|
|||
mesh->totpoly,
|
||||
mesh->totloop);
|
||||
|
||||
BKE_mesh_edge_loop_map_create(&elmap_,
|
||||
&elmap_mem_,
|
||||
mesh->medge,
|
||||
mesh->totedge,
|
||||
mesh->mpoly,
|
||||
mesh->totpoly,
|
||||
mesh->mloop,
|
||||
mesh->totloop);
|
||||
|
||||
/* Deformation coords. */
|
||||
co_.reserve(mesh->totvert);
|
||||
if (deform_mverts) {
|
||||
|
@ -244,6 +256,8 @@ class MeshFairingContext : public FairingContext {
|
|||
{
|
||||
MEM_SAFE_FREE(vlmap_);
|
||||
MEM_SAFE_FREE(vlmap_mem_);
|
||||
MEM_SAFE_FREE(elmap_);
|
||||
MEM_SAFE_FREE(elmap_mem_);
|
||||
}
|
||||
|
||||
void adjacents_coords_from_loop(const int loop,
|
||||
|
@ -266,12 +280,26 @@ class MeshFairingContext : public FairingContext {
|
|||
return e->v1;
|
||||
}
|
||||
|
||||
int vertex_index_from_loop(const int loop) override
|
||||
{
|
||||
return mloop_[loop].v;
|
||||
}
|
||||
|
||||
float cotangent_loop_weight_get(const int UNUSED(loop)) override
|
||||
{
|
||||
/* TODO: Implement cotangent loop weights for meshes. */
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
protected:
|
||||
Mesh *mesh_;
|
||||
MLoop *mloop_;
|
||||
MPoly *mpoly_;
|
||||
MEdge *medge_;
|
||||
Vector<int> loop_to_poly_map_;
|
||||
|
||||
MeshElemMap *elmap_;
|
||||
int *elmap_mem_;
|
||||
};
|
||||
|
||||
class BMeshFairingContext : public FairingContext {
|
||||
|
@ -307,6 +335,7 @@ class BMeshFairingContext : public FairingContext {
|
|||
int loop_count = 0;
|
||||
const int vert_index = BM_elem_index_get(v);
|
||||
vlmap_[vert_index].indices = &vlmap_mem_[index_iter];
|
||||
|
||||
BM_ITER_ELEM (l, &loop_iter, v, BM_LOOPS_OF_VERT) {
|
||||
const int loop_index = BM_elem_index_get(l);
|
||||
bmloop_[loop_index] = l;
|
||||
|
@ -340,6 +369,47 @@ class BMeshFairingContext : public FairingContext {
|
|||
return BM_elem_index_get(bm_other_vert);
|
||||
}
|
||||
|
||||
int vertex_index_from_loop(const int loop) override
|
||||
{
|
||||
return BM_elem_index_get(bmloop_[loop]->v);
|
||||
}
|
||||
|
||||
float cotangent_loop_weight_get(const int loop) override
|
||||
{
|
||||
return 1.0f;
|
||||
|
||||
/* TODO: enable this when it works. */
|
||||
BMLoop *l = bmloop_[loop];
|
||||
float *co_c[2];
|
||||
int co_c_count = 1;
|
||||
|
||||
float *co_a = l->v->co;
|
||||
float *co_b = l->next->v->co;
|
||||
co_c[0] = l->prev->v->co;
|
||||
if (!BM_edge_is_boundary(l->e)) {
|
||||
co_c_count = 2;
|
||||
co_c[1] = l->radial_next->next->next->v->co;
|
||||
}
|
||||
|
||||
float weight = 0.0f;
|
||||
for (int c = 0; c < co_c_count; c++) {
|
||||
float v1[3];
|
||||
float v2[3];
|
||||
sub_v3_v3v3(v1, co_a, co_c[c]);
|
||||
sub_v3_v3v3(v2, co_b, co_c[c]);
|
||||
const float angle = angle_v3v3(v1, v2);
|
||||
const float tangent = tan(angle);
|
||||
if (tangent != 0) {
|
||||
weight += 1.0f / tangent;
|
||||
}
|
||||
else {
|
||||
weight += 1e-4;
|
||||
}
|
||||
}
|
||||
weight *= 0.5f;
|
||||
return weight;
|
||||
}
|
||||
|
||||
protected:
|
||||
BMesh *bm;
|
||||
Vector<BMLoop *> bmloop_;
|
||||
|
@ -464,6 +534,27 @@ class UniformLoopWeight : public LoopWeight {
|
|||
}
|
||||
};
|
||||
|
||||
class CotangentLoopWeight : public LoopWeight {
|
||||
public:
|
||||
CotangentLoopWeight(FairingContext *fairing_context)
|
||||
{
|
||||
const int totloop = fairing_context->loop_count_get();
|
||||
loop_weights_.reserve(totloop);
|
||||
for (int i = 0; i < totloop; i++) {
|
||||
loop_weights_[i] = fairing_context->cotangent_loop_weight_get(i);
|
||||
}
|
||||
}
|
||||
~CotangentLoopWeight() = default;
|
||||
|
||||
float weight_at_index(const int index) override
|
||||
{
|
||||
return loop_weights_[index];
|
||||
}
|
||||
|
||||
private:
|
||||
Vector<float> loop_weights_;
|
||||
};
|
||||
|
||||
static void prefair_and_fair_vertices(FairingContext *fairing_context,
|
||||
bool *affected_vertices,
|
||||
const eMeshFairingDepth depth)
|
||||
|
@ -471,18 +562,22 @@ static void prefair_and_fair_vertices(FairingContext *fairing_context,
|
|||
/* Prefair. */
|
||||
UniformVertexWeight *uniform_vertex_weights = new UniformVertexWeight(fairing_context);
|
||||
UniformLoopWeight *uniform_loop_weights = new UniformLoopWeight();
|
||||
fairing_context->fair_vertices(
|
||||
affected_vertices, depth, uniform_vertex_weights, uniform_loop_weights);
|
||||
fairing_context->fair_vertices(affected_vertices,
|
||||
MESH_FAIRING_DEPTH_POSITION,
|
||||
uniform_vertex_weights,
|
||||
uniform_loop_weights);
|
||||
|
||||
delete uniform_vertex_weights;
|
||||
delete uniform_loop_weights;
|
||||
|
||||
/* Fair. */
|
||||
VoronoiVertexWeight *voronoi_vertex_weights = new VoronoiVertexWeight(fairing_context);
|
||||
/* TODO: Implemente cotangent loop weights. */
|
||||
CotangentLoopWeight *cotangent_loop_weights = new CotangentLoopWeight(fairing_context);
|
||||
fairing_context->fair_vertices(
|
||||
affected_vertices, depth, voronoi_vertex_weights, uniform_loop_weights);
|
||||
affected_vertices, depth, voronoi_vertex_weights, cotangent_loop_weights);
|
||||
|
||||
delete uniform_loop_weights;
|
||||
delete voronoi_vertex_weights;
|
||||
delete cotangent_loop_weights;
|
||||
}
|
||||
|
||||
void BKE_mesh_prefair_and_fair_vertices(struct Mesh *mesh,
|
||||
|
|
|
@ -46,6 +46,7 @@ set(SRC
|
|||
editmesh_extrude_screw.c
|
||||
editmesh_extrude_spin.c
|
||||
editmesh_extrude_spin_gizmo.c
|
||||
editmesh_fair.c
|
||||
editmesh_inset.c
|
||||
editmesh_intersect.c
|
||||
editmesh_knife.c
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2020 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup edmesh
|
||||
*
|
||||
* Interactive editmesh knife tool.
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define _USE_MATH_DEFINES
|
||||
#endif
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "BLI_alloca.h"
|
||||
#include "BLI_array.h"
|
||||
#include "BLI_linklist.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_memarena.h"
|
||||
#include "BLI_smallhash.h"
|
||||
#include "BLI_string.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "BKE_bvhutils.h"
|
||||
#include "BKE_mesh_fair.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_editmesh.h"
|
||||
#include "BKE_layer.h"
|
||||
#include "BKE_editmesh_bvh.h"
|
||||
#include "BKE_report.h"
|
||||
|
||||
#include "ED_mesh.h"
|
||||
#include "ED_screen.h"
|
||||
#include "ED_space_api.h"
|
||||
#include "ED_view3d.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_define.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
#include "mesh_intern.h" /* own include */
|
||||
|
||||
static EnumPropertyItem prop_edit_mesh_fair_selection_mode_items[] = {
|
||||
{
|
||||
MESH_FAIRING_DEPTH_POSITION,
|
||||
"POSITION",
|
||||
0,
|
||||
"Position",
|
||||
"Fair positions",
|
||||
},
|
||||
{
|
||||
MESH_FAIRING_DEPTH_TANGENCY,
|
||||
"TANGENCY",
|
||||
0,
|
||||
"Tangency",
|
||||
"Fair tangency",
|
||||
},
|
||||
/*
|
||||
{
|
||||
MESH_FAIRING_DEPTH_CURVATURE,
|
||||
"CURVATURE",
|
||||
0,
|
||||
"Curvature",
|
||||
"Fair curvature",
|
||||
},
|
||||
*/
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
static int edbm_fair_vertices_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
const int mode = RNA_enum_get(op->ptr, "mode");
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
uint objects_len = 0;
|
||||
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
||||
view_layer, CTX_wm_view3d(C), &objects_len);
|
||||
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||
Object *obedit = objects[ob_index];
|
||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||
if ((em->bm->totvertsel == 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BMesh *bm = em->bm;
|
||||
BMVert *v;
|
||||
BMIter iter;
|
||||
int i;
|
||||
bool *fairing_mask = MEM_calloc_arrayN(bm->totvert, sizeof(bool), "fairing mask");
|
||||
BM_ITER_MESH_INDEX(v, &iter, bm, BM_VERTS_OF_MESH, i) {
|
||||
if (!BM_elem_flag_test(v, BM_ELEM_SELECT)) {
|
||||
continue;
|
||||
}
|
||||
if (BM_vert_is_boundary(v)) {
|
||||
continue;
|
||||
}
|
||||
if (!BM_vert_is_manifold(v)) {
|
||||
continue;
|
||||
}
|
||||
fairing_mask[i] = true;
|
||||
}
|
||||
BKE_bmesh_prefair_and_fair_vertices(bm, fairing_mask, mode);
|
||||
MEM_freeN(fairing_mask);
|
||||
|
||||
EDBM_mesh_normals_update(em);
|
||||
EDBM_update_generic(obedit->data, true, true);
|
||||
}
|
||||
|
||||
MEM_freeN(objects);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void MESH_OT_fair_vertices(wmOperatorType *ot)
|
||||
{
|
||||
/* description */
|
||||
ot->name = "Fair Vertices";
|
||||
ot->idname = "MESH_OT_fair_vertices";
|
||||
ot->description = "Create a smooth as possible geometry patch";
|
||||
|
||||
/* callbacks */
|
||||
ot->exec = edbm_fair_vertices_exec;
|
||||
ot->poll = ED_operator_editmesh;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
/* properties */
|
||||
RNA_def_enum(
|
||||
ot->srna, "mode", prop_edit_mesh_fair_selection_mode_items, MESH_FAIRING_DEPTH_POSITION, "Mode", "");
|
||||
|
||||
}
|
||||
|
|
@ -265,6 +265,9 @@ void MESH_OT_paint_mask_extract(struct wmOperatorType *ot);
|
|||
void MESH_OT_face_set_extract(struct wmOperatorType *ot);
|
||||
void MESH_OT_paint_mask_slice(struct wmOperatorType *ot);
|
||||
|
||||
/* *** editmesh_fair.c *** */
|
||||
void MESH_OT_fair_vertices(struct wmOperatorType *ot);
|
||||
|
||||
struct wmKeyMap *point_normals_modal_keymap(wmKeyConfig *keyconf);
|
||||
|
||||
#ifdef WITH_FREESTYLE
|
||||
|
|
|
@ -178,6 +178,8 @@ void ED_operatortypes_mesh(void)
|
|||
|
||||
WM_operatortype_append(MESH_OT_bevel);
|
||||
|
||||
WM_operatortype_append(MESH_OT_fair_vertices);
|
||||
|
||||
WM_operatortype_append(MESH_OT_bridge_edge_loops);
|
||||
WM_operatortype_append(MESH_OT_inset);
|
||||
WM_operatortype_append(MESH_OT_offset_edge_loops);
|
||||
|
|
|
@ -1027,10 +1027,7 @@ typedef enum eSculptFaceSetEditMode {
|
|||
SCULPT_FACE_SET_EDIT_DELETE_GEOMETRY = 2,
|
||||
SCULPT_FACE_SET_EDIT_FAIR_POSITIONS = 3,
|
||||
SCULPT_FACE_SET_EDIT_FAIR_TANGENCY = 4,
|
||||
/* TODO(pablodp606): enable this after supporting cotangent weights in fairing. */
|
||||
/*
|
||||
SCULPT_FACE_SET_EDIT_FAIR_CURVATURE = 5,
|
||||
*/
|
||||
SCULPT_FACE_SET_EDIT_FILL_COMPONENT = 6,
|
||||
} eSculptFaceSetEditMode;
|
||||
|
||||
|
@ -1072,6 +1069,16 @@ static EnumPropertyItem prop_sculpt_face_sets_edit_types[] = {
|
|||
"Creates a smooth as possible geometry patch from the Face Set minimizing changes in "
|
||||
"vertex tangents",
|
||||
},
|
||||
/*
|
||||
{
|
||||
SCULPT_FACE_SET_EDIT_FAIR_CURVATURE,
|
||||
"FAIR_CURVATURE",
|
||||
0,
|
||||
"Fair Curvature",
|
||||
"Creates a smooth as possible geometry patch from the Face Set minimizing changes in "
|
||||
"surface curvature",
|
||||
},
|
||||
*/
|
||||
{
|
||||
SCULPT_FACE_SET_EDIT_FILL_COMPONENT,
|
||||
"FILL_COMPONENT",
|
||||
|
@ -1300,6 +1307,9 @@ static void sculpt_face_set_apply_edit(Object *ob,
|
|||
case SCULPT_FACE_SET_EDIT_FAIR_TANGENCY:
|
||||
sculpt_face_set_edit_fair_face_set(ob, active_face_set_id, MESH_FAIRING_DEPTH_TANGENCY);
|
||||
break;
|
||||
case SCULPT_FACE_SET_EDIT_FAIR_CURVATURE:
|
||||
sculpt_face_set_edit_fair_face_set(ob, active_face_set_id, MESH_FAIRING_DEPTH_CURVATURE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1456,6 +1466,7 @@ static int sculpt_face_set_edit_invoke(bContext *C, wmOperator *op, const wmEven
|
|||
break;
|
||||
case SCULPT_FACE_SET_EDIT_FAIR_POSITIONS:
|
||||
case SCULPT_FACE_SET_EDIT_FAIR_TANGENCY:
|
||||
case SCULPT_FACE_SET_EDIT_FAIR_CURVATURE:
|
||||
sculpt_face_set_edit_modify_coordinates(C, ob, active_face_set, mode);
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue