2010-04-11 22:12:30 +00:00
|
|
|
/*
|
2011-10-23 17:52:20 +00:00
|
|
|
* ***** 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.
|
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2005 by the Blender Foundation.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s): Daniel Dunbar
|
|
|
|
* Ton Roosendaal,
|
|
|
|
* Ben Batt,
|
|
|
|
* Brecht Van Lommel,
|
|
|
|
* Campbell Barton
|
|
|
|
*
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
*
|
|
|
|
*/
|
2011-02-25 13:57:17 +00:00
|
|
|
|
|
|
|
/** \file blender/modifiers/intern/MOD_bevel.c
|
|
|
|
* \ingroup modifiers
|
|
|
|
*/
|
2018-06-17 17:04:27 +02:00
|
|
|
|
2018-06-23 01:46:42 +05:30
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
2018-05-02 11:39:23 +02:00
|
|
|
#include "DNA_mesh_types.h"
|
2018-06-22 15:52:14 +02:00
|
|
|
#include "DNA_meshdata_types.h"
|
|
|
|
#include "DNA_object_types.h"
|
2018-06-19 19:27:08 +05:30
|
|
|
#include "DNA_scene_types.h"
|
2011-02-25 13:57:17 +00:00
|
|
|
|
2011-01-07 18:36:47 +00:00
|
|
|
#include "BLI_utildefines.h"
|
2018-06-23 01:46:42 +05:30
|
|
|
#include "BLI_linklist_stack.h"
|
2011-11-28 04:19:44 +00:00
|
|
|
#include "BLI_math.h"
|
2011-10-20 13:50:24 +00:00
|
|
|
#include "BLI_string.h"
|
2011-01-07 18:36:47 +00:00
|
|
|
|
2013-02-21 17:29:35 +00:00
|
|
|
#include "BKE_deform.h"
|
2018-05-02 11:39:23 +02:00
|
|
|
#include "BKE_mesh.h"
|
2010-04-11 22:12:30 +00:00
|
|
|
#include "BKE_modifier.h"
|
2011-11-28 04:19:44 +00:00
|
|
|
|
2013-02-21 17:29:35 +00:00
|
|
|
#include "MOD_util.h"
|
2012-10-24 07:24:11 +00:00
|
|
|
|
2013-02-21 17:29:35 +00:00
|
|
|
#include "bmesh.h"
|
2013-08-23 04:22:07 +00:00
|
|
|
#include "bmesh_tools.h"
|
2010-04-11 22:12:30 +00:00
|
|
|
|
2018-07-03 19:01:20 +05:30
|
|
|
#include "DEG_depsgraph_query.h"
|
|
|
|
|
2010-04-11 22:12:30 +00:00
|
|
|
static void initData(ModifierData *md)
|
|
|
|
{
|
2012-05-06 13:38:33 +00:00
|
|
|
BevelModifierData *bmd = (BevelModifierData *) md;
|
2010-04-11 22:12:30 +00:00
|
|
|
|
|
|
|
bmd->value = 0.1f;
|
|
|
|
bmd->res = 1;
|
|
|
|
bmd->flags = 0;
|
2014-01-14 11:00:44 -05:00
|
|
|
bmd->val_flags = MOD_BEVEL_AMT_OFFSET;
|
2010-04-11 22:12:30 +00:00
|
|
|
bmd->lim_flags = 0;
|
|
|
|
bmd->e_flags = 0;
|
2018-06-04 15:13:54 +05:30
|
|
|
bmd->edge_flags = 0;
|
2014-07-17 09:20:22 -04:00
|
|
|
bmd->mat = -1;
|
2014-01-14 11:00:44 -05:00
|
|
|
bmd->profile = 0.5f;
|
Cleanup: Internal degrees removal.
This patch changes most of the reamining degrees usage in internal code into radians.
I let a few which I know off asside, for reasons explained below - and I'm not sure to have found out all of them.
WARNING: this introduces forward incompatibility, which means files saved from this version won't open 100% correctly
in previous versions (a few angle properties would use radians values as degrees...).
Details:
- Data:
-- Lamp.spotsize: Game engine exposed this setting in degrees, to not break the API here I kept it as such
(using getter/setter functions), still using radians internally.
-- Mesh.smoothresh: Didn't touch to this one, as we will hopefully replace it completely by loop normals currently in dev.
- Modifiers:
-- EdgeSplitModifierData.split_angle, BevelModifierData.bevel_angle: Done.
- Postprocessing:
-- WipeVars.angle (sequencer's effect), NodeBokehImage.angle, NodeBoxMask.rotation, NodeEllipseMask.rotation: Done.
- BGE:
-- bConstraintActuator: Orientation type done (the minloc[0] & maxloc[0] cases). Did not touch to 'limit location' type,
it can also limit rotation, but it exposes through RNA the same limit_min/limit_max, which hence
can be either distance or angle values, depending on the mode. Will leave this to BGE team.
-- bSoundActuator.cone_outer_angle_3d, bSoundActuator.cone_inner_angle_3d: Done (note I kept degrees in BGE itself,
as it seems this is the expected value here...).
-- bRadarSensor.angle: Done.
Reviewers: brecht, campbellbarton, sergey, gaiaclary, dfelinto, moguri, jbakker, lukastoenne, howardt
Reviewed By: brecht, campbellbarton, sergey, gaiaclary, moguri, jbakker, lukastoenne, howardt
Thanks to all!
Differential Revision: http://developer.blender.org/D59
2013-12-03 20:09:25 +01:00
|
|
|
bmd->bevel_angle = DEG2RADF(30.0f);
|
2010-04-11 22:12:30 +00:00
|
|
|
bmd->defgrp_name[0] = '\0';
|
2018-08-04 23:38:12 +05:30
|
|
|
bmd->hnmode = MOD_BEVEL_HN_NONE;
|
2018-07-10 22:21:28 +05:30
|
|
|
bmd->hn_strength = 0.5f;
|
2018-08-04 23:38:12 +05:30
|
|
|
bmd->clnordata.faceHash = NULL;
|
2010-04-11 22:12:30 +00:00
|
|
|
}
|
|
|
|
|
2010-10-14 06:29:17 +00:00
|
|
|
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
|
2010-04-11 22:12:30 +00:00
|
|
|
{
|
|
|
|
BevelModifierData *bmd = (BevelModifierData *)md;
|
|
|
|
CustomDataMask dataMask = 0;
|
|
|
|
|
|
|
|
/* ask for vertexgroups if we need them */
|
2012-03-24 06:24:53 +00:00
|
|
|
if (bmd->defgrp_name[0]) dataMask |= CD_MASK_MDEFORMVERT;
|
2010-04-11 22:12:30 +00:00
|
|
|
|
|
|
|
return dataMask;
|
|
|
|
}
|
|
|
|
|
2018-06-19 19:27:08 +05:30
|
|
|
static void bevel_set_weighted_normal_face_strength(BMesh *bm, Scene *scene)
|
|
|
|
{
|
|
|
|
BMFace *f;
|
|
|
|
BMIter fiter;
|
|
|
|
const char *wn_layer_id = MOD_WEIGHTEDNORMALS_FACEWEIGHT_CDLAYER_ID;
|
|
|
|
int cd_prop_int_idx = CustomData_get_named_layer_index(&bm->pdata, CD_PROP_INT, wn_layer_id);
|
|
|
|
|
|
|
|
if (cd_prop_int_idx == -1) {
|
|
|
|
BM_data_layer_add_named(bm, &bm->pdata, CD_PROP_INT, wn_layer_id);
|
|
|
|
cd_prop_int_idx = CustomData_get_named_layer_index(&bm->pdata, CD_PROP_INT, wn_layer_id);
|
|
|
|
}
|
|
|
|
cd_prop_int_idx -= CustomData_get_layer_index(&bm->pdata, CD_PROP_INT);
|
|
|
|
const int cd_prop_int_offset = CustomData_get_n_offset(&bm->pdata, CD_PROP_INT, cd_prop_int_idx);
|
|
|
|
|
|
|
|
const int face_strength = scene->toolsettings->face_strength;
|
|
|
|
|
|
|
|
BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
|
|
|
|
if (BM_elem_flag_test(f, BM_ELEM_TAG)) {
|
|
|
|
int *strength = BM_ELEM_CD_GET_VOID_P(f, cd_prop_int_offset);
|
|
|
|
*strength = face_strength;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-05 08:39:20 +05:30
|
|
|
static void bevel_mod_harden_normals(
|
2018-08-10 08:10:07 +10:00
|
|
|
BevelModifierData *bmd, BMesh *bm, const float hn_strength,
|
|
|
|
const int hnmode, MDeformVert *dvert, int vgroup)
|
2018-06-23 01:46:42 +05:30
|
|
|
{
|
2018-07-19 19:27:45 +05:30
|
|
|
if (bmd->res > 20 || bmd->value == 0)
|
2018-06-23 01:46:42 +05:30
|
|
|
return;
|
2018-07-03 21:51:01 +05:30
|
|
|
|
2018-06-23 01:46:42 +05:30
|
|
|
BM_mesh_normals_update(bm);
|
|
|
|
BM_lnorspace_update(bm);
|
|
|
|
BM_normals_loops_edges_tag(bm, true);
|
|
|
|
|
2018-07-03 21:51:01 +05:30
|
|
|
const bool vertex_only = (bmd->flags & MOD_BEVEL_VERT) != 0;
|
2018-07-19 19:27:45 +05:30
|
|
|
const int cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
|
|
|
|
const bool do_normal_to_recon = (hn_strength == 1.0f);
|
2018-06-23 01:46:42 +05:30
|
|
|
|
|
|
|
BMFace *f;
|
|
|
|
BMLoop *l, *l_cur, *l_first;
|
|
|
|
BMIter fiter;
|
2018-07-03 21:51:01 +05:30
|
|
|
GHash *faceHash = bmd->clnordata.faceHash;
|
2018-06-23 01:46:42 +05:30
|
|
|
|
2018-08-05 08:39:20 +05:30
|
|
|
/* Iterate throught all loops of a face */
|
2018-06-23 01:46:42 +05:30
|
|
|
BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
|
2018-07-19 19:27:45 +05:30
|
|
|
|
2018-06-23 01:46:42 +05:30
|
|
|
l_cur = l_first = BM_FACE_FIRST_LOOP(f);
|
|
|
|
do {
|
2018-08-05 08:39:20 +05:30
|
|
|
if ((!BM_elem_flag_test(l_cur->e, BM_ELEM_TAG)) ||
|
2018-08-10 08:10:07 +10:00
|
|
|
(!BM_elem_flag_test(l_cur, BM_ELEM_TAG) && BM_loop_check_cyclic_smooth_fan(l_cur)))
|
2018-08-05 08:39:20 +05:30
|
|
|
{
|
2018-06-23 01:46:42 +05:30
|
|
|
|
2018-08-05 08:39:20 +05:30
|
|
|
/* previous and next edge is sharp, accumulate face normals into loop */
|
2018-06-23 01:46:42 +05:30
|
|
|
if (!BM_elem_flag_test(l_cur->e, BM_ELEM_TAG) && !BM_elem_flag_test(l_cur->prev->e, BM_ELEM_TAG)) {
|
|
|
|
const int loop_index = BM_elem_index_get(l_cur);
|
|
|
|
short *clnors = BM_ELEM_CD_GET_VOID_P(l_cur, cd_clnors_offset);
|
|
|
|
BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[loop_index], f->no, clnors);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
BMVert *v_pivot = l_cur->v;
|
|
|
|
BMEdge *e_next;
|
|
|
|
const BMEdge *e_org = l_cur->e;
|
|
|
|
BMLoop *lfan_pivot, *lfan_pivot_next;
|
2018-08-01 14:29:36 +02:00
|
|
|
UNUSED_VARS_NDEBUG(v_pivot);
|
2018-06-23 01:46:42 +05:30
|
|
|
|
|
|
|
lfan_pivot = l_cur;
|
|
|
|
e_next = lfan_pivot->e;
|
|
|
|
BLI_SMALLSTACK_DECLARE(loops, BMLoop *);
|
|
|
|
float cn_wght[3] = { 0.0f, 0.0f, 0.0f };
|
2018-08-05 08:39:20 +05:30
|
|
|
int recon_face_count = 0; /* Counts number of reconstructed faces current vert is connected to */
|
|
|
|
BMFace *recon_face = NULL; /* Reconstructed face */
|
2018-06-23 01:46:42 +05:30
|
|
|
|
|
|
|
while (true) {
|
|
|
|
lfan_pivot_next = BM_vert_step_fan_loop(lfan_pivot, &e_next);
|
|
|
|
if (lfan_pivot_next) {
|
|
|
|
BLI_assert(lfan_pivot_next->v == v_pivot);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
e_next = (lfan_pivot->e == e_next) ? lfan_pivot->prev->e : lfan_pivot->e;
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_SMALLSTACK_PUSH(loops, lfan_pivot);
|
|
|
|
|
|
|
|
if (bmd->lim_flags & MOD_BEVEL_WEIGHT) {
|
|
|
|
int weight = BM_elem_float_data_get(&bm->edata, lfan_pivot->f, CD_BWEIGHT);
|
|
|
|
if (weight) {
|
2018-08-01 14:29:36 +02:00
|
|
|
if (hnmode == MOD_BEVEL_HN_FACE) {
|
2018-08-05 08:39:20 +05:30
|
|
|
float cur[3]; //Add area weighted face normals
|
2018-06-23 01:46:42 +05:30
|
|
|
mul_v3_v3fl(cur, lfan_pivot->f->no, BM_face_calc_area(lfan_pivot->f));
|
|
|
|
add_v3_v3(cn_wght, cur);
|
|
|
|
}
|
|
|
|
else
|
2018-08-05 08:39:20 +05:30
|
|
|
add_v3_v3(cn_wght, lfan_pivot->f->no); //Else simply add face normals
|
2018-06-23 01:46:42 +05:30
|
|
|
}
|
|
|
|
else
|
|
|
|
add_v3_v3(cn_wght, lfan_pivot->f->no);
|
|
|
|
|
|
|
|
}
|
|
|
|
else if (bmd->lim_flags & MOD_BEVEL_VGROUP) {
|
|
|
|
const bool has_vgroup = dvert != NULL;
|
2018-08-10 08:10:07 +10:00
|
|
|
const bool vert_of_group = (
|
|
|
|
has_vgroup &&
|
|
|
|
(defvert_find_index(&dvert[BM_elem_index_get(l->v)], vgroup) != NULL));
|
2018-08-05 08:39:20 +05:30
|
|
|
|
2018-08-01 14:29:36 +02:00
|
|
|
if (vert_of_group && hnmode == MOD_BEVEL_HN_FACE) {
|
2018-06-23 01:46:42 +05:30
|
|
|
float cur[3];
|
|
|
|
mul_v3_v3fl(cur, lfan_pivot->f->no, BM_face_calc_area(lfan_pivot->f));
|
|
|
|
add_v3_v3(cn_wght, cur);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
add_v3_v3(cn_wght, lfan_pivot->f->no);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
float cur[3];
|
|
|
|
mul_v3_v3fl(cur, lfan_pivot->f->no, BM_face_calc_area(lfan_pivot->f));
|
|
|
|
add_v3_v3(cn_wght, cur);
|
|
|
|
}
|
2018-07-12 23:30:29 +05:30
|
|
|
if (!BLI_ghash_haskey(faceHash, lfan_pivot->f)) {
|
2018-07-03 21:51:01 +05:30
|
|
|
recon_face = f;
|
|
|
|
recon_face_count++;
|
|
|
|
}
|
2018-07-04 00:04:03 +05:30
|
|
|
if (!BM_elem_flag_test(e_next, BM_ELEM_TAG) || (e_next == e_org)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
lfan_pivot = lfan_pivot_next;
|
2018-06-23 01:46:42 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
normalize_v3(cn_wght);
|
|
|
|
mul_v3_fl(cn_wght, hn_strength);
|
|
|
|
float n_final[3];
|
|
|
|
|
|
|
|
while ((l = BLI_SMALLSTACK_POP(loops))) {
|
|
|
|
const int l_index = BM_elem_index_get(l);
|
|
|
|
short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
|
2018-07-03 21:51:01 +05:30
|
|
|
|
2018-08-05 08:39:20 +05:30
|
|
|
/* If vertex is edge vert with 1 reconnected face */
|
2018-07-12 23:30:29 +05:30
|
|
|
if (recon_face_count == 1 || do_normal_to_recon) {
|
2018-08-10 08:10:07 +10:00
|
|
|
BKE_lnor_space_custom_normal_to_data(
|
|
|
|
bm->lnor_spacearr->lspacearr[l_index], recon_face->no, clnors);
|
2018-07-12 23:30:29 +05:30
|
|
|
}
|
|
|
|
else if (vertex_only == false || recon_face_count == 0) {
|
2018-07-03 21:51:01 +05:30
|
|
|
copy_v3_v3(n_final, l->f->no);
|
|
|
|
mul_v3_fl(n_final, 1.0f - hn_strength);
|
|
|
|
add_v3_v3(n_final, cn_wght);
|
|
|
|
normalize_v3(n_final);
|
2018-08-10 08:10:07 +10:00
|
|
|
BKE_lnor_space_custom_normal_to_data(
|
|
|
|
bm->lnor_spacearr->lspacearr[l_index], n_final, clnors);
|
|
|
|
}
|
|
|
|
else if (BLI_ghash_haskey(faceHash, l->f)) {
|
|
|
|
BKE_lnor_space_custom_normal_to_data(
|
|
|
|
bm->lnor_spacearr->lspacearr[l_index], l->v->no, clnors);
|
2018-07-03 21:51:01 +05:30
|
|
|
}
|
2018-06-23 01:46:42 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} while ((l_cur = l_cur->next) != l_first);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-02 22:55:33 +05:30
|
|
|
static void bevel_fix_normal_shading_continuity(BevelModifierData *bmd, BMesh *bm)
|
|
|
|
{
|
2018-07-19 19:27:45 +05:30
|
|
|
const bool vertex_only = (bmd->flags & MOD_BEVEL_VERT) != 0;
|
2018-08-01 14:20:04 +02:00
|
|
|
if (bmd->value == 0 || (bmd->clnordata.faceHash == NULL && vertex_only))
|
2018-07-19 19:27:45 +05:30
|
|
|
return;
|
|
|
|
|
2018-07-02 22:55:33 +05:30
|
|
|
BM_mesh_normals_update(bm);
|
|
|
|
BM_lnorspace_update(bm);
|
|
|
|
|
|
|
|
GHash *faceHash = bmd->clnordata.faceHash;
|
|
|
|
BMEdge *e;
|
|
|
|
BMLoop *l;
|
|
|
|
BMIter liter, eiter;
|
|
|
|
|
2018-07-19 19:27:45 +05:30
|
|
|
const int cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
|
2018-07-03 21:51:01 +05:30
|
|
|
const float hn_strength = bmd->hn_strength;
|
2018-07-02 22:55:33 +05:30
|
|
|
float ref = 10.0f;
|
|
|
|
|
|
|
|
BM_ITER_MESH(e, &eiter, bm, BM_EDGES_OF_MESH) {
|
|
|
|
BMFace *f_a, *f_b;
|
|
|
|
BM_edge_face_pair(e, &f_a, &f_b);
|
|
|
|
|
2018-07-19 19:27:45 +05:30
|
|
|
bool has_f_a = false, has_f_b = false;
|
2018-07-02 22:55:33 +05:30
|
|
|
if (f_a)
|
2018-07-19 19:27:45 +05:30
|
|
|
has_f_a = BLI_ghash_haskey(faceHash, f_a);
|
2018-07-02 22:55:33 +05:30
|
|
|
if (f_b)
|
2018-07-19 19:27:45 +05:30
|
|
|
has_f_b = BLI_ghash_haskey(faceHash, f_b);
|
|
|
|
if (has_f_a ^ has_f_b) {
|
2018-08-05 08:39:20 +05:30
|
|
|
/* If one of both faces is present in faceHash then we are at a border
|
|
|
|
* between new vmesh created and reconstructed face */
|
2018-07-02 22:55:33 +05:30
|
|
|
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
|
|
BMVert *v = (i == 0) ? e->v1 : e->v2;
|
|
|
|
BM_ITER_ELEM(l, &liter, v, BM_LOOPS_OF_VERT) {
|
|
|
|
|
|
|
|
if (l->f == f_a || l->f == f_b) {
|
|
|
|
const int l_index = BM_elem_index_get(l);
|
|
|
|
short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
|
|
|
|
float n_final[3], pow_a[3], pow_b[3];
|
|
|
|
|
|
|
|
zero_v3(n_final);
|
|
|
|
copy_v3_v3(pow_a, f_a->no);
|
|
|
|
copy_v3_v3(pow_b, f_b->no);
|
2018-07-19 19:27:45 +05:30
|
|
|
if (has_f_a) {
|
2018-07-02 22:55:33 +05:30
|
|
|
mul_v3_fl(pow_a, bmd->res / ref);
|
|
|
|
mul_v3_fl(pow_b, ref / bmd->res);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
mul_v3_fl(pow_b, bmd->res / ref);
|
|
|
|
mul_v3_fl(pow_a, ref / bmd->res);
|
|
|
|
}
|
|
|
|
add_v3_v3(n_final, pow_a);
|
|
|
|
add_v3_v3(n_final, pow_b);
|
|
|
|
normalize_v3(n_final);
|
|
|
|
|
|
|
|
BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[l_index], n_final, clnors);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-08-05 08:39:20 +05:30
|
|
|
else if (has_f_a == true && has_f_b == true) {
|
|
|
|
/* Else if both faces are present we assign clnor corresponding
|
|
|
|
* to vert normal and face normal */
|
2018-07-03 21:51:01 +05:30
|
|
|
for (int i = 0; i < 2; i++) {
|
|
|
|
BMVert *v = (i == 0) ? e->v1 : e->v2;
|
|
|
|
BM_ITER_ELEM(l, &liter, v, BM_LOOPS_OF_VERT) {
|
|
|
|
|
2018-08-05 08:39:20 +05:30
|
|
|
if (l->f == f_a || l->f == f_b) {
|
2018-07-03 21:51:01 +05:30
|
|
|
const int l_index = BM_elem_index_get(l);
|
|
|
|
short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
|
|
|
|
float n_final[3], cn_wght[3];
|
|
|
|
|
|
|
|
copy_v3_v3(n_final, v->no);
|
|
|
|
mul_v3_fl(n_final, hn_strength);
|
|
|
|
|
|
|
|
copy_v3_v3(cn_wght, l->f->no);
|
|
|
|
mul_v3_fl(cn_wght, 1.0f - hn_strength);
|
|
|
|
|
|
|
|
add_v3_v3(n_final, cn_wght);
|
|
|
|
normalize_v3(n_final);
|
|
|
|
BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[l_index], n_final, clnors);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-07-02 22:55:33 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-21 17:29:35 +00:00
|
|
|
/*
|
|
|
|
* This calls the new bevel code (added since 2.64)
|
2011-11-28 04:19:44 +00:00
|
|
|
*/
|
2018-05-02 11:39:23 +02:00
|
|
|
static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
|
2011-11-28 04:19:44 +00:00
|
|
|
{
|
2018-05-02 11:39:23 +02:00
|
|
|
Mesh *result;
|
2011-11-28 04:19:44 +00:00
|
|
|
BMesh *bm;
|
|
|
|
BMIter iter;
|
|
|
|
BMEdge *e;
|
2013-02-21 17:29:35 +00:00
|
|
|
BMVert *v;
|
2014-01-24 12:42:20 -05:00
|
|
|
float weight, weight2;
|
2013-02-21 17:29:35 +00:00
|
|
|
int vgroup = -1;
|
|
|
|
MDeformVert *dvert = NULL;
|
2012-05-06 13:38:33 +00:00
|
|
|
BevelModifierData *bmd = (BevelModifierData *) md;
|
Cleanup: Internal degrees removal.
This patch changes most of the reamining degrees usage in internal code into radians.
I let a few which I know off asside, for reasons explained below - and I'm not sure to have found out all of them.
WARNING: this introduces forward incompatibility, which means files saved from this version won't open 100% correctly
in previous versions (a few angle properties would use radians values as degrees...).
Details:
- Data:
-- Lamp.spotsize: Game engine exposed this setting in degrees, to not break the API here I kept it as such
(using getter/setter functions), still using radians internally.
-- Mesh.smoothresh: Didn't touch to this one, as we will hopefully replace it completely by loop normals currently in dev.
- Modifiers:
-- EdgeSplitModifierData.split_angle, BevelModifierData.bevel_angle: Done.
- Postprocessing:
-- WipeVars.angle (sequencer's effect), NodeBokehImage.angle, NodeBoxMask.rotation, NodeEllipseMask.rotation: Done.
- BGE:
-- bConstraintActuator: Orientation type done (the minloc[0] & maxloc[0] cases). Did not touch to 'limit location' type,
it can also limit rotation, but it exposes through RNA the same limit_min/limit_max, which hence
can be either distance or angle values, depending on the mode. Will leave this to BGE team.
-- bSoundActuator.cone_outer_angle_3d, bSoundActuator.cone_inner_angle_3d: Done (note I kept degrees in BGE itself,
as it seems this is the expected value here...).
-- bRadarSensor.angle: Done.
Reviewers: brecht, campbellbarton, sergey, gaiaclary, dfelinto, moguri, jbakker, lukastoenne, howardt
Reviewed By: brecht, campbellbarton, sergey, gaiaclary, moguri, jbakker, lukastoenne, howardt
Thanks to all!
Differential Revision: http://developer.blender.org/D59
2013-12-03 20:09:25 +01:00
|
|
|
const float threshold = cosf(bmd->bevel_angle + 0.000000175f);
|
2013-07-23 14:28:19 +00:00
|
|
|
const bool vertex_only = (bmd->flags & MOD_BEVEL_VERT) != 0;
|
|
|
|
const bool do_clamp = !(bmd->flags & MOD_BEVEL_OVERLAP_OK);
|
2014-01-14 11:00:44 -05:00
|
|
|
const int offset_type = bmd->val_flags;
|
2018-05-01 17:33:04 +02:00
|
|
|
const int mat = CLAMPIS(bmd->mat, -1, ctx->object->totcol - 1);
|
2015-07-05 13:31:26 -04:00
|
|
|
const bool loop_slide = (bmd->flags & MOD_BEVEL_EVEN_WIDTHS) == 0;
|
2018-06-04 15:13:54 +05:30
|
|
|
const bool mark_seam = (bmd->edge_flags & MOD_BEVEL_MARK_SEAM);
|
|
|
|
const bool mark_sharp = (bmd->edge_flags & MOD_BEVEL_MARK_SHARP);
|
2018-06-19 19:27:08 +05:30
|
|
|
const bool set_wn_strength = (bmd->flags & MOD_BEVEL_SET_WN_STR);
|
2011-11-28 04:19:44 +00:00
|
|
|
|
2018-07-03 19:01:20 +05:30
|
|
|
struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
|
|
|
|
|
2018-05-04 08:51:04 +02:00
|
|
|
bm = BKE_mesh_to_bmesh_ex(
|
|
|
|
mesh,
|
|
|
|
&(struct BMeshCreateParams){0},
|
|
|
|
&(struct BMeshFromMeshParams){
|
|
|
|
.calc_face_normal = true,
|
|
|
|
.add_key_index = false,
|
|
|
|
.use_shapekey = true,
|
|
|
|
.active_shapekey = ctx->object->shapenr,
|
|
|
|
});
|
2018-05-02 11:39:23 +02:00
|
|
|
|
2014-01-24 12:42:20 -05:00
|
|
|
if ((bmd->lim_flags & MOD_BEVEL_VGROUP) && bmd->defgrp_name[0])
|
2018-06-29 19:02:19 +02:00
|
|
|
MOD_get_vgroup(ctx->object, mesh, bmd->defgrp_name, &dvert, &vgroup);
|
2011-11-28 04:19:44 +00:00
|
|
|
|
2013-02-21 17:29:35 +00:00
|
|
|
if (vertex_only) {
|
2013-08-17 08:21:40 +00:00
|
|
|
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
|
2013-02-21 17:29:35 +00:00
|
|
|
if (!BM_vert_is_manifold(v))
|
|
|
|
continue;
|
2014-10-14 21:28:20 +02:00
|
|
|
if (bmd->lim_flags & MOD_BEVEL_WEIGHT) {
|
|
|
|
weight = BM_elem_float_data_get(&bm->vdata, v, CD_BWEIGHT);
|
|
|
|
if (weight == 0.0f)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (vgroup != -1) {
|
2013-02-21 17:29:35 +00:00
|
|
|
weight = defvert_array_find_weight_safe(dvert, BM_elem_index_get(v), vgroup);
|
2014-01-24 12:42:20 -05:00
|
|
|
/* Check is against 0.5 rather than != 0.0 because cascaded bevel modifiers will
|
|
|
|
* interpolate weights for newly created vertices, and may cause unexpected "selection" */
|
|
|
|
if (weight < 0.5f)
|
2013-02-21 17:29:35 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
BM_elem_flag_enable(v, BM_ELEM_TAG);
|
|
|
|
}
|
|
|
|
}
|
2013-07-23 14:28:19 +00:00
|
|
|
else if (bmd->lim_flags & MOD_BEVEL_ANGLE) {
|
2012-04-19 13:47:58 +00:00
|
|
|
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
|
2011-11-28 04:19:44 +00:00
|
|
|
/* check for 1 edge having 2 face users */
|
2012-11-18 10:17:07 +00:00
|
|
|
BMLoop *l_a, *l_b;
|
|
|
|
if (BM_edge_loop_pair(e, &l_a, &l_b)) {
|
|
|
|
if (dot_v3v3(l_a->f->no, l_b->f->no) < threshold) {
|
2012-11-18 08:56:47 +00:00
|
|
|
BM_elem_flag_enable(e, BM_ELEM_TAG);
|
|
|
|
BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
|
|
|
|
BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
|
2011-11-28 04:19:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* crummy, is there a way just to operator on all? - campbell */
|
2012-04-19 13:47:58 +00:00
|
|
|
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
|
2012-11-18 09:33:11 +00:00
|
|
|
if (BM_edge_is_manifold(e)) {
|
2013-07-23 14:28:19 +00:00
|
|
|
if (bmd->lim_flags & MOD_BEVEL_WEIGHT) {
|
2013-02-21 17:29:35 +00:00
|
|
|
weight = BM_elem_float_data_get(&bm->edata, e, CD_BWEIGHT);
|
|
|
|
if (weight == 0.0f)
|
|
|
|
continue;
|
|
|
|
}
|
2014-01-24 12:42:20 -05:00
|
|
|
else if (vgroup != -1) {
|
|
|
|
weight = defvert_array_find_weight_safe(dvert, BM_elem_index_get(e->v1), vgroup);
|
|
|
|
weight2 = defvert_array_find_weight_safe(dvert, BM_elem_index_get(e->v2), vgroup);
|
|
|
|
if (weight < 0.5f || weight2 < 0.5f)
|
|
|
|
continue;
|
|
|
|
}
|
2012-11-18 09:33:11 +00:00
|
|
|
BM_elem_flag_enable(e, BM_ELEM_TAG);
|
|
|
|
BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
|
|
|
|
BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
|
|
|
|
}
|
2011-11-28 04:19:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-14 11:00:44 -05:00
|
|
|
BM_mesh_bevel(bm, bmd->value, offset_type, bmd->res, bmd->profile,
|
2013-07-23 14:28:19 +00:00
|
|
|
vertex_only, bmd->lim_flags & MOD_BEVEL_WEIGHT, do_clamp,
|
2018-07-02 22:55:33 +05:30
|
|
|
dvert, vgroup, mat, loop_slide, mark_seam, mark_sharp, bmd->hnmode, &bmd->clnordata);
|
2011-11-28 04:19:44 +00:00
|
|
|
|
2018-07-19 19:27:45 +05:30
|
|
|
if (bmd->hnmode != BEVEL_HN_FIX_SHA && bmd->hnmode != MOD_BEVEL_HN_NONE) {
|
|
|
|
bevel_mod_harden_normals(bmd, bm, bmd->hn_strength, bmd->hnmode, dvert, vgroup);
|
2018-07-02 22:55:33 +05:30
|
|
|
}
|
2018-08-05 08:39:20 +05:30
|
|
|
if (bmd->hnmode == BEVEL_HN_FIX_SHA)
|
2018-07-19 19:27:45 +05:30
|
|
|
bevel_fix_normal_shading_continuity(bmd, bm);
|
2018-08-05 08:39:20 +05:30
|
|
|
if (set_wn_strength)
|
2018-07-03 19:01:20 +05:30
|
|
|
bevel_set_weighted_normal_face_strength(bm, scene);
|
2018-06-19 19:27:08 +05:30
|
|
|
|
2018-05-08 11:03:16 +02:00
|
|
|
result = BKE_bmesh_to_mesh_nomain(bm, &(struct BMeshToMeshParams){0});
|
2012-11-18 12:14:22 +00:00
|
|
|
|
2013-02-21 17:29:35 +00:00
|
|
|
BLI_assert(bm->vtoolflagpool == NULL &&
|
|
|
|
bm->etoolflagpool == NULL &&
|
|
|
|
bm->ftoolflagpool == NULL); /* make sure we never alloc'd these */
|
2012-10-24 07:24:11 +00:00
|
|
|
BM_mesh_free(bm);
|
2011-11-28 04:19:44 +00:00
|
|
|
|
2018-08-05 08:39:20 +05:30
|
|
|
if (bmd->clnordata.faceHash)
|
2018-07-03 19:01:20 +05:30
|
|
|
BLI_ghash_free(bmd->clnordata.faceHash, NULL, NULL);
|
2018-07-02 22:55:33 +05:30
|
|
|
|
2018-05-04 10:05:57 +02:00
|
|
|
result->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
|
|
|
|
|
2012-02-12 15:02:33 +00:00
|
|
|
return result;
|
2011-11-28 04:19:44 +00:00
|
|
|
}
|
|
|
|
|
2014-02-07 10:43:28 -05:00
|
|
|
static bool dependsOnNormals(ModifierData *UNUSED(md))
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-04-11 22:12:30 +00:00
|
|
|
ModifierTypeInfo modifierType_Bevel = {
|
2012-10-24 05:45:54 +00:00
|
|
|
/* name */ "Bevel",
|
|
|
|
/* structName */ "BevelModifierData",
|
|
|
|
/* structSize */ sizeof(BevelModifierData),
|
|
|
|
/* type */ eModifierTypeType_Constructive,
|
|
|
|
/* flags */ eModifierTypeFlag_AcceptsMesh |
|
|
|
|
eModifierTypeFlag_SupportsEditmode |
|
2018-07-11 22:36:44 +05:30
|
|
|
eModifierTypeFlag_EnableInEditmode |
|
2018-08-05 08:39:20 +05:30
|
|
|
eModifierTypeFlag_AcceptsCVs,
|
2018-08-10 08:10:07 +10:00
|
|
|
|
2018-05-08 15:04:10 +02:00
|
|
|
/* copyData */ modifier_copyData_generic,
|
2018-04-18 15:45:54 +02:00
|
|
|
|
|
|
|
/* deformVerts_DM */ NULL,
|
|
|
|
/* deformMatrices_DM */ NULL,
|
|
|
|
/* deformVertsEM_DM */ NULL,
|
|
|
|
/* deformMatricesEM_DM*/NULL,
|
2018-05-02 11:39:23 +02:00
|
|
|
/* applyModifier_DM */ NULL,
|
2018-04-18 15:45:54 +02:00
|
|
|
/* applyModifierEM_DM */NULL,
|
|
|
|
|
2012-10-24 05:45:54 +00:00
|
|
|
/* deformVerts */ NULL,
|
|
|
|
/* deformMatrices */ NULL,
|
|
|
|
/* deformVertsEM */ NULL,
|
|
|
|
/* deformMatricesEM */ NULL,
|
2018-05-02 11:39:23 +02:00
|
|
|
/* applyModifier */ applyModifier,
|
2013-05-02 14:42:05 +00:00
|
|
|
/* applyModifierEM */ NULL,
|
2018-04-18 15:45:54 +02:00
|
|
|
|
2012-10-24 05:45:54 +00:00
|
|
|
/* initData */ initData,
|
|
|
|
/* requiredDataMask */ requiredDataMask,
|
|
|
|
/* freeData */ NULL,
|
|
|
|
/* isDisabled */ NULL,
|
Depsgraph: New dependency graph integration commit
This commit integrates the work done so far on the new dependency graph system,
where goal was to replace legacy depsgraph with the new one, supporting loads of
neat features like:
- More granular dependency relation nature, which solves issues with fake cycles
in the dependencies.
- Move towards all-animatable, by better integration of drivers into the system.
- Lay down some basis for upcoming copy-on-write, overrides and so on.
The new system is living side-by-side with the previous one and disabled by
default, so nothing will become suddenly broken. The way to enable new depsgraph
is to pass `--new-depsgraph` command line argument.
It's a bit early to consider the system production-ready, there are some TODOs
and issues were discovered during the merge period, they'll be addressed ASAP.
But it's important to merge, because it's the only way to attract artists to
really start testing this system.
There are number of assorted documents related on the design of the new system:
* http://wiki.blender.org/index.php/User:Aligorith/GSoC2013_Depsgraph#Design_Documents
* http://wiki.blender.org/index.php/User:Nazg-gul/DependencyGraph
There are also some user-related information online:
* http://code.blender.org/2015/02/blender-dependency-graph-branch-for-users/
* http://code.blender.org/2015/03/more-dependency-graph-tricks/
Kudos to everyone who was involved into the project:
- Joshua "Aligorith" Leung -- design specification, initial code
- Lukas "lukas_t" Toenne -- integrating code into blender, with further fixes
- Sergey "Sergey" "Sharybin" -- some mocking around, trying to wrap up the
project and so
- Bassam "slikdigit" Kurdali -- stressing the new system, reporting all the
issues and recording/writing documentation.
- Everyone else who i forgot to mention here :)
2015-05-12 15:05:57 +05:00
|
|
|
/* updateDepsgraph */ NULL,
|
2012-10-24 05:45:54 +00:00
|
|
|
/* dependsOnTime */ NULL,
|
2014-02-07 10:43:28 -05:00
|
|
|
/* dependsOnNormals */ dependsOnNormals,
|
2011-03-05 10:29:10 +00:00
|
|
|
/* foreachObjectLink */ NULL,
|
2012-10-24 05:45:54 +00:00
|
|
|
/* foreachIDLink */ NULL,
|
|
|
|
/* foreachTexLink */ NULL,
|
2010-04-11 22:12:30 +00:00
|
|
|
};
|