Compare commits
33 Commits
temp-llvm-
...
soc-2021-p
Author | SHA1 | Date | |
---|---|---|---|
f35e15647b | |||
3e0f60d91e | |||
dc8bc59e2a | |||
cec2aecd18 | |||
0d2d027df0 | |||
60f0364fb8 | |||
07aa277973 | |||
8ffe20ffc9 | |||
986bf72c44 | |||
3a65475338 | |||
621b2bd410 | |||
569bbdec76 | |||
63260db4a0 | |||
8a5fcaf8c6 | |||
6a62487f83 | |||
04ba70cc7f | |||
ac7163311d | |||
0f20476116 | |||
9eb502ee9c | |||
b60fa77678 | |||
4de8acc88d | |||
7df84749ad | |||
20d2c92119 | |||
239bf16cc7 | |||
529913b2df | |||
2c6aeb6240 | |||
9503e34e99 | |||
096d6017cc | |||
18f45f874c | |||
607119dd3f | |||
d777efbf5c | |||
7425af128f | |||
9823ac0767 |
@@ -557,6 +557,7 @@ geometry_node_categories = [
|
|||||||
NodeItem("GeometryNodeSeparateComponents"),
|
NodeItem("GeometryNodeSeparateComponents"),
|
||||||
NodeItem("GeometryNodeSetPosition"),
|
NodeItem("GeometryNodeSetPosition"),
|
||||||
NodeItem("GeometryNodeRealizeInstances"),
|
NodeItem("GeometryNodeRealizeInstances"),
|
||||||
|
NodeItem("GeometryNodeMergeByDistance"),
|
||||||
]),
|
]),
|
||||||
GeometryNodeCategory("GEO_INPUT", "Input", items=[
|
GeometryNodeCategory("GEO_INPUT", "Input", items=[
|
||||||
NodeItem("FunctionNodeLegacyRandomFloat", poll=geometry_nodes_legacy_poll),
|
NodeItem("FunctionNodeLegacyRandomFloat", poll=geometry_nodes_legacy_poll),
|
||||||
|
@@ -119,6 +119,7 @@ add_subdirectory(blenloader)
|
|||||||
add_subdirectory(depsgraph)
|
add_subdirectory(depsgraph)
|
||||||
add_subdirectory(ikplugin)
|
add_subdirectory(ikplugin)
|
||||||
add_subdirectory(simulation)
|
add_subdirectory(simulation)
|
||||||
|
add_subdirectory(geometry)
|
||||||
add_subdirectory(gpu)
|
add_subdirectory(gpu)
|
||||||
add_subdirectory(imbuf)
|
add_subdirectory(imbuf)
|
||||||
add_subdirectory(nodes)
|
add_subdirectory(nodes)
|
||||||
|
@@ -1515,6 +1515,8 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
|
|||||||
#define GEO_NODE_CURVE_SET_HANDLES 1100
|
#define GEO_NODE_CURVE_SET_HANDLES 1100
|
||||||
#define GEO_NODE_POINTS_TO_VOLUME 1101
|
#define GEO_NODE_POINTS_TO_VOLUME 1101
|
||||||
#define GEO_NODE_CURVE_HANDLE_TYPE_SELECTION 1102
|
#define GEO_NODE_CURVE_HANDLE_TYPE_SELECTION 1102
|
||||||
|
#define GEO_NODE_MERGE_BY_DISTANCE 1103
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
|
@@ -5778,6 +5778,7 @@ static void registerGeometryNodes()
|
|||||||
register_node_type_geo_material_assign();
|
register_node_type_geo_material_assign();
|
||||||
register_node_type_geo_material_replace();
|
register_node_type_geo_material_replace();
|
||||||
register_node_type_geo_material_selection();
|
register_node_type_geo_material_selection();
|
||||||
|
register_node_type_geo_merge_by_distance();
|
||||||
register_node_type_geo_mesh_primitive_circle();
|
register_node_type_geo_mesh_primitive_circle();
|
||||||
register_node_type_geo_mesh_primitive_cone();
|
register_node_type_geo_mesh_primitive_cone();
|
||||||
register_node_type_geo_mesh_primitive_cube();
|
register_node_type_geo_mesh_primitive_cube();
|
||||||
|
@@ -144,6 +144,14 @@ template<typename Key, typename Value> class MultiValueMap {
|
|||||||
return map_.keys();
|
return map_.keys();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return how many keys are currently stored in the Map.
|
||||||
|
*/
|
||||||
|
int64_t size() const
|
||||||
|
{
|
||||||
|
return std::distance(this->keys().begin(), this->keys().end());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: This signature will change when the implementation changes.
|
* NOTE: This signature will change when the implementation changes.
|
||||||
*/
|
*/
|
||||||
|
47
source/blender/geometry/CMakeLists.txt
Normal file
47
source/blender/geometry/CMakeLists.txt
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# ***** 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) 2006, Blender Foundation
|
||||||
|
# All rights reserved.
|
||||||
|
# ***** END GPL LICENSE BLOCK *****
|
||||||
|
|
||||||
|
set(INC
|
||||||
|
.
|
||||||
|
../blenfont
|
||||||
|
../blenkernel
|
||||||
|
../blenlib
|
||||||
|
../blentranslation
|
||||||
|
../functions
|
||||||
|
../makesdna
|
||||||
|
../makesrna
|
||||||
|
../../../intern/guardedalloc
|
||||||
|
../makesdna/intern
|
||||||
|
${CMAKE_BINARY_DIR}/source/blender/makesdna/intern
|
||||||
|
)
|
||||||
|
|
||||||
|
set(SRC
|
||||||
|
intern/mesh_merge_by_distance.cc
|
||||||
|
intern/pointcloud_merge_by_distance.cc
|
||||||
|
GEO_mesh_merge_by_distance.hh
|
||||||
|
GEO_pointcloud_merge_by_distance.hh
|
||||||
|
)
|
||||||
|
|
||||||
|
set(LIB
|
||||||
|
bf_blenkernel
|
||||||
|
bf_blenlib
|
||||||
|
)
|
||||||
|
|
||||||
|
blender_add_lib(bf_geometry "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
37
source/blender/geometry/GEO_mesh_merge_by_distance.hh
Normal file
37
source/blender/geometry/GEO_mesh_merge_by_distance.hh
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup geo
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "BLI_span.hh"
|
||||||
|
|
||||||
|
namespace blender::geometry {
|
||||||
|
|
||||||
|
enum class WeldMode {
|
||||||
|
all = 0,
|
||||||
|
connected = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Mesh *mesh_merge_by_distance(struct Mesh *mesh,
|
||||||
|
const Span<bool> mask,
|
||||||
|
const float merge_distance,
|
||||||
|
const WeldMode weld_mode);
|
||||||
|
|
||||||
|
} // namespace blender::geometry
|
29
source/blender/geometry/GEO_pointcloud_merge_by_distance.hh
Normal file
29
source/blender/geometry/GEO_pointcloud_merge_by_distance.hh
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup geo
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "BKE_geometry_set.hh"
|
||||||
|
|
||||||
|
namespace blender::geometry {
|
||||||
|
PointCloud *pointcloud_merge_by_distance(PointCloudComponent &pointcloud_component,
|
||||||
|
const float merge_threshold,
|
||||||
|
blender::Span<bool> selection);
|
||||||
|
}
|
@@ -12,19 +12,6 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \ingroup modifiers
|
|
||||||
*
|
|
||||||
* Weld modifier: Remove doubles.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* TODOs:
|
|
||||||
* - Review weight and vertex color interpolation.;
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//#define USE_WELD_DEBUG
|
//#define USE_WELD_DEBUG
|
||||||
@@ -36,38 +23,21 @@
|
|||||||
#include "BLI_utildefines.h"
|
#include "BLI_utildefines.h"
|
||||||
|
|
||||||
#include "BLI_alloca.h"
|
#include "BLI_alloca.h"
|
||||||
#include "BLI_bitmap.h"
|
|
||||||
#include "BLI_kdtree.h"
|
#include "BLI_kdtree.h"
|
||||||
#include "BLI_math.h"
|
#include "BLI_math.h"
|
||||||
|
|
||||||
#include "BLT_translation.h"
|
|
||||||
|
|
||||||
#include "DNA_defaults.h"
|
|
||||||
#include "DNA_mesh_types.h"
|
#include "DNA_mesh_types.h"
|
||||||
#include "DNA_meshdata_types.h"
|
#include "DNA_meshdata_types.h"
|
||||||
#include "DNA_modifier_types.h"
|
|
||||||
#include "DNA_object_types.h"
|
|
||||||
#include "DNA_screen_types.h"
|
|
||||||
|
|
||||||
#ifdef USE_BVHTREEKDOP
|
#ifdef USE_BVHTREEKDOP
|
||||||
# include "BKE_bvhutils.h"
|
# include "BKE_bvhutils.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "BKE_context.h"
|
#include "BKE_context.h"
|
||||||
#include "BKE_deform.h"
|
|
||||||
#include "BKE_mesh.h"
|
#include "BKE_mesh.h"
|
||||||
#include "BKE_modifier.h"
|
#include "BKE_modifier.h"
|
||||||
#include "BKE_screen.h"
|
|
||||||
|
|
||||||
#include "UI_interface.h"
|
#include "GEO_mesh_merge_by_distance.hh"
|
||||||
#include "UI_resources.h"
|
|
||||||
|
|
||||||
#include "RNA_access.h"
|
|
||||||
|
|
||||||
#include "DEG_depsgraph.h"
|
|
||||||
|
|
||||||
#include "MOD_modifiertypes.h"
|
|
||||||
#include "MOD_ui_common.h"
|
|
||||||
|
|
||||||
/* Indicates when the element was not computed. */
|
/* Indicates when the element was not computed. */
|
||||||
#define OUT_OF_CONTEXT (uint)(-1)
|
#define OUT_OF_CONTEXT (uint)(-1)
|
||||||
@@ -379,7 +349,7 @@ static void weld_vert_ctx_alloc_and_setup(const uint mvert_len,
|
|||||||
uint wvert_len = 0;
|
uint wvert_len = 0;
|
||||||
|
|
||||||
WeldVert *wvert, *wv;
|
WeldVert *wvert, *wv;
|
||||||
wvert = MEM_mallocN(sizeof(*wvert) * mvert_len, __func__);
|
wvert = (WeldVert *)MEM_mallocN(sizeof(*wvert) * mvert_len, __func__);
|
||||||
wv = &wvert[0];
|
wv = &wvert[0];
|
||||||
|
|
||||||
uint *v_dest_iter = &r_vert_dest_map[0];
|
uint *v_dest_iter = &r_vert_dest_map[0];
|
||||||
@@ -392,7 +362,7 @@ static void weld_vert_ctx_alloc_and_setup(const uint mvert_len,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*r_wvert = MEM_reallocN(wvert, sizeof(*wvert) * wvert_len);
|
*r_wvert = (WeldVert *)MEM_reallocN(wvert, sizeof(*wvert) * wvert_len);
|
||||||
*r_wvert_len = wvert_len;
|
*r_wvert_len = wvert_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -425,7 +395,7 @@ static void weld_vert_groups_setup(const uint mvert_len,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WeldGroup *wgroups = MEM_callocN(sizeof(*wgroups) * wgroups_len, __func__);
|
struct WeldGroup *wgroups = (WeldGroup *)MEM_callocN(sizeof(*wgroups) * wgroups_len, __func__);
|
||||||
|
|
||||||
const WeldVert *wv = &wvert[0];
|
const WeldVert *wv = &wvert[0];
|
||||||
for (uint i = wvert_len; i--; wv++) {
|
for (uint i = wvert_len; i--; wv++) {
|
||||||
@@ -442,7 +412,7 @@ static void weld_vert_groups_setup(const uint mvert_len,
|
|||||||
|
|
||||||
BLI_assert(ofs == wvert_len);
|
BLI_assert(ofs == wvert_len);
|
||||||
|
|
||||||
uint *groups_buffer = MEM_mallocN(sizeof(*groups_buffer) * ofs, __func__);
|
uint *groups_buffer = (uint *)MEM_mallocN(sizeof(*groups_buffer) * ofs, __func__);
|
||||||
wv = &wvert[0];
|
wv = &wvert[0];
|
||||||
for (uint i = wvert_len; i--; wv++) {
|
for (uint i = wvert_len; i--; wv++) {
|
||||||
uint group_index = r_vert_groups_map[wv->vert_dest];
|
uint group_index = r_vert_groups_map[wv->vert_dest];
|
||||||
@@ -505,7 +475,7 @@ static void weld_edge_ctx_setup(const uint mvert_len,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (link_len) {
|
if (link_len) {
|
||||||
uint *link_edge_buffer = MEM_mallocN(sizeof(*link_edge_buffer) * link_len, __func__);
|
uint *link_edge_buffer = (uint *)MEM_mallocN(sizeof(*link_edge_buffer) * link_len, __func__);
|
||||||
|
|
||||||
we = &r_wedge[0];
|
we = &r_wedge[0];
|
||||||
for (uint i = 0; i < wedge_len; i++, we++) {
|
for (uint i = 0; i < wedge_len; i++, we++) {
|
||||||
@@ -596,11 +566,11 @@ static void weld_edge_ctx_alloc(const MEdge *medge,
|
|||||||
uint *r_wedge_len)
|
uint *r_wedge_len)
|
||||||
{
|
{
|
||||||
/* Edge Context. */
|
/* Edge Context. */
|
||||||
uint *edge_map = MEM_mallocN(sizeof(*edge_map) * medge_len, __func__);
|
uint *edge_map = (uint *)MEM_mallocN(sizeof(*edge_map) * medge_len, __func__);
|
||||||
uint wedge_len = 0;
|
uint wedge_len = 0;
|
||||||
|
|
||||||
WeldEdge *wedge, *we;
|
WeldEdge *wedge, *we;
|
||||||
wedge = MEM_mallocN(sizeof(*wedge) * medge_len, __func__);
|
wedge = (WeldEdge *)MEM_mallocN(sizeof(*wedge) * medge_len, __func__);
|
||||||
we = &wedge[0];
|
we = &wedge[0];
|
||||||
|
|
||||||
const MEdge *me = &medge[0];
|
const MEdge *me = &medge[0];
|
||||||
@@ -626,7 +596,7 @@ static void weld_edge_ctx_alloc(const MEdge *medge,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*r_wedge = MEM_reallocN(wedge, sizeof(*wedge) * wedge_len);
|
*r_wedge = (WeldEdge *)MEM_reallocN(wedge, sizeof(*wedge) * wedge_len);
|
||||||
*r_wedge_len = wedge_len;
|
*r_wedge_len = wedge_len;
|
||||||
*r_edge_ctx_map = edge_map;
|
*r_edge_ctx_map = edge_map;
|
||||||
}
|
}
|
||||||
@@ -646,7 +616,7 @@ static void weld_edge_groups_setup(const uint medge_len,
|
|||||||
struct WeldGroupEdge *wegroups, *wegrp_iter;
|
struct WeldGroupEdge *wegroups, *wegrp_iter;
|
||||||
|
|
||||||
uint wgroups_len = wedge_len - edge_kill_len;
|
uint wgroups_len = wedge_len - edge_kill_len;
|
||||||
wegroups = MEM_callocN(sizeof(*wegroups) * wgroups_len, __func__);
|
wegroups = (WeldGroupEdge *)MEM_callocN(sizeof(*wegroups) * wgroups_len, __func__);
|
||||||
wegrp_iter = &wegroups[0];
|
wegrp_iter = &wegroups[0];
|
||||||
|
|
||||||
wgroups_len = 0;
|
wgroups_len = 0;
|
||||||
@@ -693,7 +663,7 @@ static void weld_edge_groups_setup(const uint medge_len,
|
|||||||
ofs += wegrp_iter->group.len;
|
ofs += wegrp_iter->group.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint *groups_buffer = MEM_mallocN(sizeof(*groups_buffer) * ofs, __func__);
|
uint *groups_buffer = (uint *)MEM_mallocN(sizeof(*groups_buffer) * ofs, __func__);
|
||||||
we = &wedge[0];
|
we = &wedge[0];
|
||||||
for (uint i = wedge_len; i--; we++) {
|
for (uint i = wedge_len; i--; we++) {
|
||||||
if (we->flag == ELEM_COLLAPSED) {
|
if (we->flag == ELEM_COLLAPSED) {
|
||||||
@@ -832,18 +802,18 @@ static void weld_poly_loop_ctx_alloc(const MPoly *mpoly,
|
|||||||
WeldMesh *r_weld_mesh)
|
WeldMesh *r_weld_mesh)
|
||||||
{
|
{
|
||||||
/* Loop/Poly Context. */
|
/* Loop/Poly Context. */
|
||||||
uint *loop_map = MEM_mallocN(sizeof(*loop_map) * mloop_len, __func__);
|
uint *loop_map = (uint *)MEM_mallocN(sizeof(*loop_map) * mloop_len, __func__);
|
||||||
uint *poly_map = MEM_mallocN(sizeof(*poly_map) * mpoly_len, __func__);
|
uint *poly_map = (uint *)MEM_mallocN(sizeof(*poly_map) * mpoly_len, __func__);
|
||||||
uint wloop_len = 0;
|
uint wloop_len = 0;
|
||||||
uint wpoly_len = 0;
|
uint wpoly_len = 0;
|
||||||
uint max_ctx_poly_len = 4;
|
uint max_ctx_poly_len = 4;
|
||||||
|
|
||||||
WeldLoop *wloop, *wl;
|
WeldLoop *wloop, *wl;
|
||||||
wloop = MEM_mallocN(sizeof(*wloop) * mloop_len, __func__);
|
wloop = (WeldLoop *)MEM_mallocN(sizeof(*wloop) * mloop_len, __func__);
|
||||||
wl = &wloop[0];
|
wl = &wloop[0];
|
||||||
|
|
||||||
WeldPoly *wpoly, *wp;
|
WeldPoly *wpoly, *wp;
|
||||||
wpoly = MEM_mallocN(sizeof(*wpoly) * mpoly_len, __func__);
|
wpoly = (WeldPoly *)MEM_mallocN(sizeof(*wpoly) * mpoly_len, __func__);
|
||||||
wp = &wpoly[0];
|
wp = &wpoly[0];
|
||||||
|
|
||||||
uint maybe_new_poly = 0;
|
uint maybe_new_poly = 0;
|
||||||
@@ -910,14 +880,15 @@ static void weld_poly_loop_ctx_alloc(const MPoly *mpoly,
|
|||||||
|
|
||||||
if (mpoly_len < (wpoly_len + maybe_new_poly)) {
|
if (mpoly_len < (wpoly_len + maybe_new_poly)) {
|
||||||
WeldPoly *wpoly_tmp = wpoly;
|
WeldPoly *wpoly_tmp = wpoly;
|
||||||
wpoly = MEM_mallocN(sizeof(*wpoly) * ((size_t)wpoly_len + maybe_new_poly), __func__);
|
wpoly = (WeldPoly *)MEM_mallocN(sizeof(*wpoly) * ((size_t)wpoly_len + maybe_new_poly),
|
||||||
|
__func__);
|
||||||
memcpy(wpoly, wpoly_tmp, sizeof(*wpoly) * wpoly_len);
|
memcpy(wpoly, wpoly_tmp, sizeof(*wpoly) * wpoly_len);
|
||||||
MEM_freeN(wpoly_tmp);
|
MEM_freeN(wpoly_tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
WeldPoly *poly_new = &wpoly[wpoly_len];
|
WeldPoly *poly_new = &wpoly[wpoly_len];
|
||||||
|
|
||||||
r_weld_mesh->wloop = MEM_reallocN(wloop, sizeof(*wloop) * wloop_len);
|
r_weld_mesh->wloop = (WeldLoop *)MEM_reallocN(wloop, sizeof(*wloop) * wloop_len);
|
||||||
r_weld_mesh->wpoly = wpoly;
|
r_weld_mesh->wpoly = wpoly;
|
||||||
r_weld_mesh->wpoly_new = poly_new;
|
r_weld_mesh->wpoly_new = poly_new;
|
||||||
r_weld_mesh->wloop_len = wloop_len;
|
r_weld_mesh->wloop_len = wloop_len;
|
||||||
@@ -1189,7 +1160,7 @@ static void weld_poly_loop_ctx_setup(const MLoop *mloop,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (link_len) {
|
if (link_len) {
|
||||||
uint *link_poly_buffer = MEM_mallocN(sizeof(*link_poly_buffer) * link_len, __func__);
|
uint *link_poly_buffer = (uint *)MEM_mallocN(sizeof(*link_poly_buffer) * link_len, __func__);
|
||||||
|
|
||||||
wp = &wpoly[0];
|
wp = &wpoly[0];
|
||||||
for (uint i = 0; i < wpoly_and_new_len; i++, wp++) {
|
for (uint i = 0; i < wpoly_and_new_len; i++, wp++) {
|
||||||
@@ -1331,8 +1302,8 @@ static void weld_mesh_context_create(const Mesh *mesh,
|
|||||||
const uint mloop_len = mesh->totloop;
|
const uint mloop_len = mesh->totloop;
|
||||||
const uint mpoly_len = mesh->totpoly;
|
const uint mpoly_len = mesh->totpoly;
|
||||||
|
|
||||||
uint *edge_dest_map = MEM_mallocN(sizeof(*edge_dest_map) * medge_len, __func__);
|
uint *edge_dest_map = (uint *)MEM_mallocN(sizeof(*edge_dest_map) * medge_len, __func__);
|
||||||
struct WeldGroup *v_links = MEM_callocN(sizeof(*v_links) * mvert_len, __func__);
|
struct WeldGroup *v_links = (WeldGroup *)MEM_callocN(sizeof(*v_links) * mvert_len, __func__);
|
||||||
|
|
||||||
WeldVert *wvert;
|
WeldVert *wvert;
|
||||||
uint wvert_len;
|
uint wvert_len;
|
||||||
@@ -1545,10 +1516,6 @@ static void customdata_weld(
|
|||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
|
||||||
/** \name Weld Modifier Main
|
|
||||||
* \{ */
|
|
||||||
|
|
||||||
#ifdef USE_BVHTREEKDOP
|
#ifdef USE_BVHTREEKDOP
|
||||||
struct WeldOverlapData {
|
struct WeldOverlapData {
|
||||||
const MVert *mvert;
|
const MVert *mvert;
|
||||||
@@ -1573,15 +1540,15 @@ struct WeldVertexCluster {
|
|||||||
uint merged_verts;
|
uint merged_verts;
|
||||||
};
|
};
|
||||||
|
|
||||||
static Mesh *weldModifier_doWeld(WeldModifierData *wmd,
|
namespace blender::geometry {
|
||||||
const ModifierEvalContext *UNUSED(ctx),
|
|
||||||
Mesh *mesh)
|
Mesh *mesh_merge_by_distance(Mesh *mesh,
|
||||||
|
const Span<bool> mask,
|
||||||
|
const float merge_distance,
|
||||||
|
const WeldMode weld_mode)
|
||||||
{
|
{
|
||||||
Mesh *result = mesh;
|
Mesh *result = mesh;
|
||||||
|
|
||||||
BLI_bitmap *v_mask = NULL;
|
|
||||||
int v_mask_act = 0;
|
|
||||||
|
|
||||||
const MVert *mvert;
|
const MVert *mvert;
|
||||||
const MLoop *mloop;
|
const MLoop *mloop;
|
||||||
const MPoly *mpoly, *mp;
|
const MPoly *mpoly, *mp;
|
||||||
@@ -1591,29 +1558,12 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd,
|
|||||||
totvert = mesh->totvert;
|
totvert = mesh->totvert;
|
||||||
|
|
||||||
/* Vertex Group. */
|
/* Vertex Group. */
|
||||||
const int defgrp_index = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name);
|
|
||||||
if (defgrp_index != -1) {
|
|
||||||
MDeformVert *dvert, *dv;
|
|
||||||
dvert = CustomData_get_layer(&mesh->vdata, CD_MDEFORMVERT);
|
|
||||||
if (dvert) {
|
|
||||||
const bool invert_vgroup = (wmd->flag & MOD_WELD_INVERT_VGROUP) != 0;
|
|
||||||
dv = &dvert[0];
|
|
||||||
v_mask = BLI_BITMAP_NEW(totvert, __func__);
|
|
||||||
for (uint i = 0; i < totvert; i++, dv++) {
|
|
||||||
const bool found = BKE_defvert_find_weight(dv, defgrp_index) > 0.0f;
|
|
||||||
if (found != invert_vgroup) {
|
|
||||||
BLI_BITMAP_ENABLE(v_mask, i);
|
|
||||||
v_mask_act++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* From the original index of the vertex.
|
/* From the original index of the vertex.
|
||||||
* This indicates which vert it is or is going to be merged. */
|
* This indicates which vert it is or is going to be merged. */
|
||||||
uint *vert_dest_map = MEM_malloc_arrayN(totvert, sizeof(*vert_dest_map), __func__);
|
uint *vert_dest_map = (uint *)MEM_malloc_arrayN(totvert, sizeof(*vert_dest_map), __func__);
|
||||||
uint vert_kill_len = 0;
|
uint vert_kill_len = 0;
|
||||||
if (wmd->mode == MOD_WELD_MODE_ALL)
|
if (weld_mode == WeldMode::all)
|
||||||
#ifdef USE_BVHTREEKDOP
|
#ifdef USE_BVHTREEKDOP
|
||||||
{
|
{
|
||||||
/* Get overlap map. */
|
/* Get overlap map. */
|
||||||
@@ -1624,7 +1574,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd,
|
|||||||
false,
|
false,
|
||||||
v_mask,
|
v_mask,
|
||||||
v_mask_act,
|
v_mask_act,
|
||||||
wmd->merge_dist / 2,
|
merge_distance / 2,
|
||||||
2,
|
2,
|
||||||
6,
|
6,
|
||||||
0,
|
0,
|
||||||
@@ -1634,7 +1584,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd,
|
|||||||
if (bvhtree) {
|
if (bvhtree) {
|
||||||
struct WeldOverlapData data;
|
struct WeldOverlapData data;
|
||||||
data.mvert = mvert;
|
data.mvert = mvert;
|
||||||
data.merge_dist_sq = square_f(wmd->merge_dist);
|
data.merge_dist_sq = square_f(merge_distance);
|
||||||
|
|
||||||
uint overlap_len;
|
uint overlap_len;
|
||||||
BVHTreeOverlap *overlap = BLI_bvhtree_overlap_ex(bvhtree,
|
BVHTreeOverlap *overlap = BLI_bvhtree_overlap_ex(bvhtree,
|
||||||
@@ -1695,9 +1645,9 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd,
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
KDTree_3d *tree = BLI_kdtree_3d_new(v_mask ? v_mask_act : totvert);
|
KDTree_3d *tree = BLI_kdtree_3d_new(totvert);
|
||||||
for (uint i = 0; i < totvert; i++) {
|
for (uint i = 0; i < totvert; i++) {
|
||||||
if (!v_mask || BLI_BITMAP_TEST(v_mask, i)) {
|
if (mask.size() == 0 || mask[i]) {
|
||||||
BLI_kdtree_3d_insert(tree, i, mvert[i].co);
|
BLI_kdtree_3d_insert(tree, i, mvert[i].co);
|
||||||
}
|
}
|
||||||
vert_dest_map[i] = OUT_OF_CONTEXT;
|
vert_dest_map[i] = OUT_OF_CONTEXT;
|
||||||
@@ -1705,12 +1655,12 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd,
|
|||||||
|
|
||||||
BLI_kdtree_3d_balance(tree);
|
BLI_kdtree_3d_balance(tree);
|
||||||
vert_kill_len = BLI_kdtree_3d_calc_duplicates_fast(
|
vert_kill_len = BLI_kdtree_3d_calc_duplicates_fast(
|
||||||
tree, wmd->merge_dist, false, (int *)vert_dest_map);
|
tree, merge_distance, false, (int *)vert_dest_map);
|
||||||
BLI_kdtree_3d_free(tree);
|
BLI_kdtree_3d_free(tree);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else {
|
else {
|
||||||
BLI_assert(wmd->mode == MOD_WELD_MODE_CONNECTED);
|
BLI_assert(weld_mode == WeldMode::connected);
|
||||||
|
|
||||||
MEdge *medge, *me;
|
MEdge *medge, *me;
|
||||||
|
|
||||||
@@ -1718,14 +1668,14 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd,
|
|||||||
totvert = mesh->totvert;
|
totvert = mesh->totvert;
|
||||||
totedge = mesh->totedge;
|
totedge = mesh->totedge;
|
||||||
|
|
||||||
struct WeldVertexCluster *vert_clusters = MEM_malloc_arrayN(
|
struct WeldVertexCluster *vert_clusters = (WeldVertexCluster *)MEM_malloc_arrayN(
|
||||||
totvert, sizeof(*vert_clusters), __func__);
|
totvert, sizeof(*vert_clusters), __func__);
|
||||||
struct WeldVertexCluster *vc = &vert_clusters[0];
|
struct WeldVertexCluster *vc = &vert_clusters[0];
|
||||||
for (uint i = 0; i < totvert; i++, vc++) {
|
for (uint i = 0; i < totvert; i++, vc++) {
|
||||||
copy_v3_v3(vc->co, mvert[i].co);
|
copy_v3_v3(vc->co, mvert[i].co);
|
||||||
vc->merged_verts = 0;
|
vc->merged_verts = 0;
|
||||||
}
|
}
|
||||||
const float merge_dist_sq = square_f(wmd->merge_dist);
|
const float merge_dist_sq = square_f(merge_distance);
|
||||||
|
|
||||||
range_vn_u(vert_dest_map, totvert, 0);
|
range_vn_u(vert_dest_map, totvert, 0);
|
||||||
|
|
||||||
@@ -1735,9 +1685,6 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd,
|
|||||||
uint v1 = me->v1;
|
uint v1 = me->v1;
|
||||||
uint v2 = me->v2;
|
uint v2 = me->v2;
|
||||||
|
|
||||||
if (wmd->flag & MOD_WELD_LOOSE_EDGES && (me->flag & ME_LOOSEEDGE) == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
while (v1 != vert_dest_map[v1]) {
|
while (v1 != vert_dest_map[v1]) {
|
||||||
v1 = vert_dest_map[v1];
|
v1 = vert_dest_map[v1];
|
||||||
}
|
}
|
||||||
@@ -1747,7 +1694,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd,
|
|||||||
if (v1 == v2) {
|
if (v1 == v2) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (v_mask && (!BLI_BITMAP_TEST(v_mask, v1) || !BLI_BITMAP_TEST(v_mask, v2))) {
|
if (mask.size() > 0 && (!mask[v1] || !mask[v2])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (v1 > v2) {
|
if (v1 > v2) {
|
||||||
@@ -1787,10 +1734,6 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v_mask) {
|
|
||||||
MEM_freeN(v_mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vert_kill_len) {
|
if (vert_kill_len) {
|
||||||
WeldMesh weld_mesh;
|
WeldMesh weld_mesh;
|
||||||
weld_mesh_context_create(mesh, vert_dest_map, vert_kill_len, &weld_mesh);
|
weld_mesh_context_create(mesh, vert_dest_map, vert_kill_len, &weld_mesh);
|
||||||
@@ -1987,93 +1930,4 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd,
|
|||||||
MEM_freeN(vert_dest_map);
|
MEM_freeN(vert_dest_map);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
} // namespace blender::geometry
|
||||||
static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
|
|
||||||
{
|
|
||||||
WeldModifierData *wmd = (WeldModifierData *)md;
|
|
||||||
return weldModifier_doWeld(wmd, ctx, mesh);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void initData(ModifierData *md)
|
|
||||||
{
|
|
||||||
WeldModifierData *wmd = (WeldModifierData *)md;
|
|
||||||
|
|
||||||
BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(wmd, modifier));
|
|
||||||
|
|
||||||
MEMCPY_STRUCT_AFTER(wmd, DNA_struct_default_get(WeldModifierData), modifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void requiredDataMask(Object *UNUSED(ob),
|
|
||||||
ModifierData *md,
|
|
||||||
CustomData_MeshMasks *r_cddata_masks)
|
|
||||||
{
|
|
||||||
WeldModifierData *wmd = (WeldModifierData *)md;
|
|
||||||
|
|
||||||
/* Ask for vertexgroups if we need them. */
|
|
||||||
if (wmd->defgrp_name[0] != '\0') {
|
|
||||||
r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
|
|
||||||
{
|
|
||||||
uiLayout *layout = panel->layout;
|
|
||||||
|
|
||||||
PointerRNA ob_ptr;
|
|
||||||
PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr);
|
|
||||||
int weld_mode = RNA_enum_get(ptr, "mode");
|
|
||||||
|
|
||||||
uiLayoutSetPropSep(layout, true);
|
|
||||||
|
|
||||||
uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE);
|
|
||||||
uiItemR(layout, ptr, "merge_threshold", 0, IFACE_("Distance"), ICON_NONE);
|
|
||||||
if (weld_mode == MOD_WELD_MODE_CONNECTED) {
|
|
||||||
uiItemR(layout, ptr, "loose_edges", 0, NULL, ICON_NONE);
|
|
||||||
}
|
|
||||||
modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
|
|
||||||
|
|
||||||
modifier_panel_end(layout, ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void panelRegister(ARegionType *region_type)
|
|
||||||
{
|
|
||||||
modifier_panel_register(region_type, eModifierType_Weld, panel_draw);
|
|
||||||
}
|
|
||||||
|
|
||||||
ModifierTypeInfo modifierType_Weld = {
|
|
||||||
/* name */ "Weld",
|
|
||||||
/* structName */ "WeldModifierData",
|
|
||||||
/* structSize */ sizeof(WeldModifierData),
|
|
||||||
/* srna */ &RNA_WeldModifier,
|
|
||||||
/* type */ eModifierTypeType_Constructive,
|
|
||||||
/* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping |
|
|
||||||
eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode |
|
|
||||||
eModifierTypeFlag_AcceptsCVs,
|
|
||||||
/* icon */ ICON_AUTOMERGE_OFF, /* TODO: Use correct icon. */
|
|
||||||
|
|
||||||
/* copyData */ BKE_modifier_copydata_generic,
|
|
||||||
|
|
||||||
/* deformVerts */ NULL,
|
|
||||||
/* deformMatrices */ NULL,
|
|
||||||
/* deformVertsEM */ NULL,
|
|
||||||
/* deformMatricesEM */ NULL,
|
|
||||||
/* modifyMesh */ modifyMesh,
|
|
||||||
/* modifyHair */ NULL,
|
|
||||||
/* modifyGeometrySet */ NULL,
|
|
||||||
|
|
||||||
/* initData */ initData,
|
|
||||||
/* requiredDataMask */ requiredDataMask,
|
|
||||||
/* freeData */ NULL,
|
|
||||||
/* isDisabled */ NULL,
|
|
||||||
/* updateDepsgraph */ NULL,
|
|
||||||
/* dependsOnTime */ NULL,
|
|
||||||
/* dependsOnNormals */ NULL,
|
|
||||||
/* foreachIDLink */ NULL,
|
|
||||||
/* foreachTexLink */ NULL,
|
|
||||||
/* freeRuntimeData */ NULL,
|
|
||||||
/* panelRegister */ panelRegister,
|
|
||||||
/* blendWrite */ NULL,
|
|
||||||
/* blendRead */ NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
/** \} */
|
|
157
source/blender/geometry/intern/pointcloud_merge_by_distance.cc
Normal file
157
source/blender/geometry/intern/pointcloud_merge_by_distance.cc
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "BKE_attribute_math.hh"
|
||||||
|
#include "BKE_geometry_set.hh"
|
||||||
|
#include "BKE_pointcloud.h"
|
||||||
|
|
||||||
|
#include "BLI_array.hh"
|
||||||
|
#include "BLI_float3.hh"
|
||||||
|
#include "BLI_kdtree.h"
|
||||||
|
#include "BLI_multi_value_map.hh"
|
||||||
|
#include "BLI_span.hh"
|
||||||
|
#include "BLI_vector.hh"
|
||||||
|
|
||||||
|
#include "DNA_pointcloud_types.h"
|
||||||
|
|
||||||
|
#include "GEO_pointcloud_merge_by_distance.hh"
|
||||||
|
|
||||||
|
#include "FN_generic_span.hh"
|
||||||
|
|
||||||
|
using blender::MutableSpan;
|
||||||
|
|
||||||
|
namespace blender::geometry {
|
||||||
|
const static int POINT_NOT_MERGED = -1;
|
||||||
|
|
||||||
|
static KDTree_3d *build_kdtree(Span<float3> positions, Span<bool> selection)
|
||||||
|
{
|
||||||
|
BLI_assert(positions.size() == selection.size());
|
||||||
|
|
||||||
|
KDTree_3d *kdtree = BLI_kdtree_3d_new(selection.size());
|
||||||
|
|
||||||
|
for (const int i : positions.index_range()) {
|
||||||
|
if (selection[i]) {
|
||||||
|
BLI_kdtree_3d_insert(kdtree, i, positions[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BLI_kdtree_3d_balance(kdtree);
|
||||||
|
return kdtree;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void build_merge_map(Span<float3> positions,
|
||||||
|
MutableSpan<int> merge_map,
|
||||||
|
const float merge_threshold,
|
||||||
|
Span<bool> selection)
|
||||||
|
{
|
||||||
|
KDTree_3d *kdtree = build_kdtree(positions, selection);
|
||||||
|
|
||||||
|
for (int i : positions.index_range()) {
|
||||||
|
struct CallbackData {
|
||||||
|
int index;
|
||||||
|
MutableSpan<int> merge_map;
|
||||||
|
Span<bool> selection;
|
||||||
|
} callback_data = {i, merge_map, selection};
|
||||||
|
|
||||||
|
BLI_kdtree_3d_range_search_cb(
|
||||||
|
kdtree,
|
||||||
|
positions[i],
|
||||||
|
merge_threshold,
|
||||||
|
[](void *user_data,
|
||||||
|
int source_point_index,
|
||||||
|
const float *UNUSED(co),
|
||||||
|
float UNUSED(distance_squared)) {
|
||||||
|
CallbackData &callback_data = *static_cast<CallbackData *>(user_data);
|
||||||
|
int target_point_index = callback_data.index;
|
||||||
|
if (source_point_index != target_point_index &&
|
||||||
|
callback_data.merge_map[source_point_index] == POINT_NOT_MERGED &&
|
||||||
|
callback_data.merge_map[target_point_index] == POINT_NOT_MERGED &&
|
||||||
|
callback_data.selection[source_point_index] &&
|
||||||
|
callback_data.selection[target_point_index]) {
|
||||||
|
callback_data.merge_map[source_point_index] = target_point_index;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
&callback_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
BLI_kdtree_3d_free(kdtree);
|
||||||
|
}
|
||||||
|
|
||||||
|
PointCloud *pointcloud_merge_by_distance(PointCloudComponent &pointcloud_component,
|
||||||
|
const float merge_threshold,
|
||||||
|
Span<bool> selection)
|
||||||
|
{
|
||||||
|
const PointCloud &src_pointcloud = *pointcloud_component.get_for_read();
|
||||||
|
Array<int> merge_map(src_pointcloud.totpoint, POINT_NOT_MERGED);
|
||||||
|
Span<float3> positions((const float3 *)src_pointcloud.co, src_pointcloud.totpoint);
|
||||||
|
|
||||||
|
build_merge_map(positions, merge_map, merge_threshold, selection);
|
||||||
|
|
||||||
|
MultiValueMap<int, int> copy_map;
|
||||||
|
for (const int i : merge_map.index_range()) {
|
||||||
|
if (merge_map[i] != POINT_NOT_MERGED) {
|
||||||
|
copy_map.add(merge_map[i], i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PointCloud *pointcloud = BKE_pointcloud_new_nomain(copy_map.size());
|
||||||
|
PointCloudComponent dst_component;
|
||||||
|
dst_component.replace(pointcloud, GeometryOwnershipType::Editable);
|
||||||
|
|
||||||
|
pointcloud_component.attribute_foreach(
|
||||||
|
[&](const bke::AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) {
|
||||||
|
fn::GVArrayPtr read_attribute = pointcloud_component.attribute_get_for_read(
|
||||||
|
attribute_id, meta_data.domain, meta_data.data_type);
|
||||||
|
|
||||||
|
if (!dst_component.attribute_exists(attribute_id) &&
|
||||||
|
!dst_component.attribute_try_create(
|
||||||
|
attribute_id, meta_data.domain, meta_data.data_type, AttributeInitDefault())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bke::OutputAttribute target_attribute = dst_component.attribute_try_get_for_output_only(
|
||||||
|
attribute_id, meta_data.domain, meta_data.data_type);
|
||||||
|
|
||||||
|
blender::attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) {
|
||||||
|
using T = decltype(dummy);
|
||||||
|
const fn::GVArray_Typed<T> src_span = read_attribute->typed<T>();
|
||||||
|
|
||||||
|
attribute_math::DefaultMixer<T> mixer(target_attribute.as_span<T>());
|
||||||
|
|
||||||
|
int index_new = 0;
|
||||||
|
for (const int index_old : copy_map.keys()) {
|
||||||
|
Span<int> merged_points = copy_map.lookup(index_old);
|
||||||
|
if (merged_points.size() > 0) {
|
||||||
|
float weight = 1.0f / (float(merged_points.size() + 1.0f));
|
||||||
|
mixer.mix_in(index_new, src_span[index_old], weight);
|
||||||
|
for (const int j : merged_points) {
|
||||||
|
mixer.mix_in(index_new, src_span[j], weight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
index_new++;
|
||||||
|
}
|
||||||
|
mixer.finalize();
|
||||||
|
});
|
||||||
|
|
||||||
|
target_attribute.save();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
return pointcloud;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace blender::geometry
|
@@ -27,7 +27,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "BLI_utildefines.h"
|
#include "BLI_utildefines.h"
|
||||||
|
|
||||||
#include "dna_type_offsets.h"
|
#include "dna_type_offsets.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@@ -801,7 +801,7 @@
|
|||||||
#define _DNA_DEFAULT_WeldModifierData \
|
#define _DNA_DEFAULT_WeldModifierData \
|
||||||
{ \
|
{ \
|
||||||
.merge_dist = 0.001f, \
|
.merge_dist = 0.001f, \
|
||||||
.mode = MOD_WELD_MODE_ALL, \
|
.mode = 0, \
|
||||||
.defgrp_name = "", \
|
.defgrp_name = "", \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2051,12 +2051,6 @@ enum {
|
|||||||
MOD_WELD_LOOSE_EDGES = (1 << 1),
|
MOD_WELD_LOOSE_EDGES = (1 << 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
/* #WeldModifierData.mode */
|
|
||||||
enum {
|
|
||||||
MOD_WELD_MODE_ALL = 0,
|
|
||||||
MOD_WELD_MODE_CONNECTED = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct DataTransferModifierData {
|
typedef struct DataTransferModifierData {
|
||||||
ModifierData modifier;
|
ModifierData modifier;
|
||||||
|
|
||||||
|
@@ -382,6 +382,7 @@ blender_include_dirs(
|
|||||||
../../bmesh
|
../../bmesh
|
||||||
../../depsgraph
|
../../depsgraph
|
||||||
../../draw
|
../../draw
|
||||||
|
../../geometry
|
||||||
../../gpu
|
../../gpu
|
||||||
../../ikplugin
|
../../ikplugin
|
||||||
../../imbuf
|
../../imbuf
|
||||||
|
@@ -6172,17 +6172,17 @@ static void rna_def_modifier_laplaciandeform(BlenderRNA *brna)
|
|||||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const EnumPropertyItem rna_enum_modifier_weld_mode_items[] = {
|
||||||
|
{0, "ALL", 0, "All", "Full merge by distance"},
|
||||||
|
{1, "CONNECTED", 0, "Connected", "Only merge along the edges"},
|
||||||
|
{0, NULL, 0, NULL, NULL},
|
||||||
|
};
|
||||||
|
|
||||||
static void rna_def_modifier_weld(BlenderRNA *brna)
|
static void rna_def_modifier_weld(BlenderRNA *brna)
|
||||||
{
|
{
|
||||||
StructRNA *srna;
|
StructRNA *srna;
|
||||||
PropertyRNA *prop;
|
PropertyRNA *prop;
|
||||||
|
|
||||||
static const EnumPropertyItem mode_items[] = {
|
|
||||||
{MOD_WELD_MODE_ALL, "ALL", 0, "All", "Full merge by distance"},
|
|
||||||
{MOD_WELD_MODE_CONNECTED, "CONNECTED", 0, "Connected", "Only merge along the edges"},
|
|
||||||
{0, NULL, 0, NULL, NULL},
|
|
||||||
};
|
|
||||||
|
|
||||||
srna = RNA_def_struct(brna, "WeldModifier", "Modifier");
|
srna = RNA_def_struct(brna, "WeldModifier", "Modifier");
|
||||||
RNA_def_struct_ui_text(srna, "Weld Modifier", "Weld modifier");
|
RNA_def_struct_ui_text(srna, "Weld Modifier", "Weld modifier");
|
||||||
RNA_def_struct_sdna(srna, "WeldModifierData");
|
RNA_def_struct_sdna(srna, "WeldModifierData");
|
||||||
@@ -6191,7 +6191,7 @@ static void rna_def_modifier_weld(BlenderRNA *brna)
|
|||||||
RNA_define_lib_overridable(true);
|
RNA_define_lib_overridable(true);
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
|
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
|
||||||
RNA_def_property_enum_items(prop, mode_items);
|
RNA_def_property_enum_items(prop, rna_enum_modifier_weld_mode_items);
|
||||||
RNA_def_property_ui_text(prop, "Mode", "Mode defines the merge rule");
|
RNA_def_property_ui_text(prop, "Mode", "Mode defines the merge rule");
|
||||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
@@ -10754,6 +10754,23 @@ static void def_geo_string_to_curves(StructRNA *srna)
|
|||||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void def_geo_merge_by_distance(StructRNA *srna)
|
||||||
|
{
|
||||||
|
static const EnumPropertyItem rna_enum_geometry_nodes_weld_mode_items[] = {
|
||||||
|
{0, "ALL", 0, "All", "Full merge by distance."},
|
||||||
|
{1, "CONNECTED", 0, "Connected", "Only merge along the edges"},
|
||||||
|
{0, NULL, 0, NULL, NULL},
|
||||||
|
};
|
||||||
|
|
||||||
|
PropertyRNA *prop;
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "merge_mode", PROP_ENUM, PROP_NONE);
|
||||||
|
RNA_def_property_enum_sdna(prop, NULL, "custom1");
|
||||||
|
RNA_def_property_enum_items(prop, rna_enum_geometry_nodes_weld_mode_items);
|
||||||
|
RNA_def_property_ui_text(
|
||||||
|
prop, "Mode", "Mode defines the merge rule. Only used when welding mesh data.");
|
||||||
|
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||||
|
}
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static void rna_def_shader_node(BlenderRNA *brna)
|
static void rna_def_shader_node(BlenderRNA *brna)
|
||||||
|
@@ -30,6 +30,7 @@ set(INC
|
|||||||
../depsgraph
|
../depsgraph
|
||||||
../editors/include
|
../editors/include
|
||||||
../functions
|
../functions
|
||||||
|
../geometry
|
||||||
../makesdna
|
../makesdna
|
||||||
../makesrna
|
../makesrna
|
||||||
../nodes
|
../nodes
|
||||||
@@ -113,7 +114,7 @@ set(SRC
|
|||||||
intern/MOD_weightvgedit.c
|
intern/MOD_weightvgedit.c
|
||||||
intern/MOD_weightvgmix.c
|
intern/MOD_weightvgmix.c
|
||||||
intern/MOD_weightvgproximity.c
|
intern/MOD_weightvgproximity.c
|
||||||
intern/MOD_weld.c
|
intern/MOD_weld.cc
|
||||||
intern/MOD_wireframe.c
|
intern/MOD_wireframe.c
|
||||||
|
|
||||||
MOD_modifiertypes.h
|
MOD_modifiertypes.h
|
||||||
@@ -129,6 +130,7 @@ set(SRC
|
|||||||
set(LIB
|
set(LIB
|
||||||
bf_blenkernel
|
bf_blenkernel
|
||||||
bf_blenlib
|
bf_blenlib
|
||||||
|
bf_geometry
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WITH_ALEMBIC)
|
if(WITH_ALEMBIC)
|
||||||
|
206
source/blender/modifiers/intern/MOD_weld.cc
Normal file
206
source/blender/modifiers/intern/MOD_weld.cc
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup modifiers
|
||||||
|
*
|
||||||
|
* Weld modifier: Remove doubles.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* TODOs:
|
||||||
|
* - Review weight and vertex color interpolation.;
|
||||||
|
*/
|
||||||
|
|
||||||
|
//#define USE_WELD_DEBUG
|
||||||
|
//#define USE_WELD_NORMALS
|
||||||
|
//#define USE_BVHTREEKDOP
|
||||||
|
|
||||||
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
|
#include "BLI_array.hh"
|
||||||
|
#include "BLI_math.h"
|
||||||
|
#include "BLI_utildefines.h"
|
||||||
|
#include "BLT_translation.h"
|
||||||
|
|
||||||
|
#include "DNA_defaults.h"
|
||||||
|
#include "DNA_mesh_types.h"
|
||||||
|
#include "DNA_meshdata_types.h"
|
||||||
|
#include "DNA_modifier_types.h"
|
||||||
|
#include "DNA_object_types.h"
|
||||||
|
#include "DNA_screen_types.h"
|
||||||
|
|
||||||
|
#ifdef USE_BVHTREEKDOP
|
||||||
|
# include "BKE_bvhutils.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "BKE_context.h"
|
||||||
|
#include "BKE_deform.h"
|
||||||
|
#include "BKE_modifier.h"
|
||||||
|
#include "BKE_screen.h"
|
||||||
|
|
||||||
|
#include "GEO_mesh_merge_by_distance.hh"
|
||||||
|
|
||||||
|
#include "UI_interface.h"
|
||||||
|
#include "UI_resources.h"
|
||||||
|
|
||||||
|
#include "RNA_access.h"
|
||||||
|
|
||||||
|
#include "MOD_ui_common.h"
|
||||||
|
using blender::geometry::WeldMode;
|
||||||
|
|
||||||
|
static WeldMode weld_mode_from_int(const short type)
|
||||||
|
{
|
||||||
|
switch (static_cast<WeldMode>(type)) {
|
||||||
|
case WeldMode::all:
|
||||||
|
return WeldMode::all;
|
||||||
|
case WeldMode::connected:
|
||||||
|
return WeldMode::connected;
|
||||||
|
}
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
return WeldMode::all;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int16_t weld_mode_to_int(const WeldMode weld_mode)
|
||||||
|
{
|
||||||
|
switch (weld_mode) {
|
||||||
|
case WeldMode::all:
|
||||||
|
return static_cast<int16_t>(WeldMode::all);
|
||||||
|
case WeldMode::connected:
|
||||||
|
return static_cast<int16_t>(WeldMode::connected);
|
||||||
|
}
|
||||||
|
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
return static_cast<int16_t>(WeldMode::all);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh)
|
||||||
|
{
|
||||||
|
WeldModifierData *wmd = (WeldModifierData *)md;
|
||||||
|
|
||||||
|
uint totvert = mesh->totvert;
|
||||||
|
blender::Array<bool> mask(totvert);
|
||||||
|
const int defgrp_index = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name);
|
||||||
|
if (defgrp_index != -1) {
|
||||||
|
MDeformVert *dvert, *dv;
|
||||||
|
dvert = (MDeformVert *)CustomData_get_layer(&mesh->vdata, CD_MDEFORMVERT);
|
||||||
|
if (dvert) {
|
||||||
|
const bool invert_vgroup = (wmd->flag & MOD_WELD_INVERT_VGROUP) != 0;
|
||||||
|
dv = &dvert[0];
|
||||||
|
for (uint i = 0; i < totvert; i++, dv++) {
|
||||||
|
const bool found = BKE_defvert_find_weight(dv, defgrp_index) > 0.0f;
|
||||||
|
mask[i] = found != invert_vgroup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (int i = 0; i < totvert; i++) {
|
||||||
|
mask[i] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Mesh *result = blender::geometry::mesh_merge_by_distance(
|
||||||
|
mesh, mask, wmd->merge_dist, weld_mode_from_int(wmd->mode));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void initData(ModifierData *md)
|
||||||
|
{
|
||||||
|
WeldModifierData *wmd = (WeldModifierData *)md;
|
||||||
|
|
||||||
|
BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(wmd, modifier));
|
||||||
|
|
||||||
|
MEMCPY_STRUCT_AFTER(wmd, DNA_struct_default_get(WeldModifierData), modifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void requiredDataMask(Object *UNUSED(ob),
|
||||||
|
ModifierData *md,
|
||||||
|
CustomData_MeshMasks *r_cddata_masks)
|
||||||
|
{
|
||||||
|
WeldModifierData *wmd = (WeldModifierData *)md;
|
||||||
|
|
||||||
|
/* Ask for vertexgroups if we need them. */
|
||||||
|
if (wmd->defgrp_name[0] != '\0') {
|
||||||
|
r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
|
||||||
|
{
|
||||||
|
uiLayout *layout = panel->layout;
|
||||||
|
|
||||||
|
PointerRNA ob_ptr;
|
||||||
|
PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr);
|
||||||
|
int weld_mode = RNA_enum_get(ptr, "mode");
|
||||||
|
|
||||||
|
uiLayoutSetPropSep(layout, true);
|
||||||
|
|
||||||
|
uiItemR(layout, ptr, "mode", 0, nullptr, ICON_NONE);
|
||||||
|
uiItemR(layout, ptr, "merge_threshold", 0, IFACE_("Distance"), ICON_NONE);
|
||||||
|
if (weld_mode_from_int(weld_mode) == blender::geometry::WeldMode::connected) {
|
||||||
|
uiItemR(layout, ptr, "loose_edges", 0, nullptr, ICON_NONE);
|
||||||
|
}
|
||||||
|
modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", nullptr);
|
||||||
|
|
||||||
|
modifier_panel_end(layout, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void panelRegister(ARegionType *region_type)
|
||||||
|
{
|
||||||
|
modifier_panel_register(region_type, eModifierType_Weld, panel_draw);
|
||||||
|
}
|
||||||
|
|
||||||
|
ModifierTypeInfo modifierType_Weld = {
|
||||||
|
/* name */ "Weld",
|
||||||
|
/* structName */ "WeldModifierData",
|
||||||
|
/* structSize */ sizeof(WeldModifierData),
|
||||||
|
/* srna */ &RNA_WeldModifier,
|
||||||
|
/* type */ eModifierTypeType_Constructive,
|
||||||
|
/* flags */
|
||||||
|
(ModifierTypeFlag)(eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping |
|
||||||
|
eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode |
|
||||||
|
eModifierTypeFlag_AcceptsCVs),
|
||||||
|
/* icon */ ICON_AUTOMERGE_OFF, /* TODO: Use correct icon. */
|
||||||
|
|
||||||
|
/* copyData */ BKE_modifier_copydata_generic,
|
||||||
|
|
||||||
|
/* deformVerts */ nullptr,
|
||||||
|
/* deformMatrices */ nullptr,
|
||||||
|
/* deformVertsEM */ nullptr,
|
||||||
|
/* deformMatricesEM */ nullptr,
|
||||||
|
/* modifyMesh */ modifyMesh,
|
||||||
|
/* modifyHair */ nullptr,
|
||||||
|
/* modifyGeometrySet */ nullptr,
|
||||||
|
|
||||||
|
/* initData */ initData,
|
||||||
|
/* requiredDataMask */ requiredDataMask,
|
||||||
|
/* freeData */ nullptr,
|
||||||
|
/* isDisabled */ nullptr,
|
||||||
|
/* updateDepsgraph */ nullptr,
|
||||||
|
/* dependsOnTime */ nullptr,
|
||||||
|
/* dependsOnNormals */ nullptr,
|
||||||
|
/* foreachIDLink */ nullptr,
|
||||||
|
/* foreachTexLink */ nullptr,
|
||||||
|
/* freeRuntimeData */ nullptr,
|
||||||
|
/* panelRegister */ panelRegister,
|
||||||
|
/* blendWrite */ nullptr,
|
||||||
|
/* blendRead */ nullptr,
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \} */
|
@@ -33,6 +33,7 @@ set(INC
|
|||||||
../bmesh
|
../bmesh
|
||||||
../depsgraph
|
../depsgraph
|
||||||
../functions
|
../functions
|
||||||
|
../geometry
|
||||||
../gpu
|
../gpu
|
||||||
../imbuf
|
../imbuf
|
||||||
../makesdna
|
../makesdna
|
||||||
@@ -239,6 +240,7 @@ set(SRC
|
|||||||
geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc
|
geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc
|
||||||
geometry/nodes/node_geo_mesh_subdivide.cc
|
geometry/nodes/node_geo_mesh_subdivide.cc
|
||||||
geometry/nodes/node_geo_mesh_to_points.cc
|
geometry/nodes/node_geo_mesh_to_points.cc
|
||||||
|
geometry/nodes/node_geo_merge_by_distance.cc
|
||||||
geometry/nodes/node_geo_object_info.cc
|
geometry/nodes/node_geo_object_info.cc
|
||||||
geometry/nodes/node_geo_points_to_vertices.cc
|
geometry/nodes/node_geo_points_to_vertices.cc
|
||||||
geometry/nodes/node_geo_points_to_volume.cc
|
geometry/nodes/node_geo_points_to_volume.cc
|
||||||
@@ -423,6 +425,7 @@ set(SRC
|
|||||||
set(LIB
|
set(LIB
|
||||||
bf_bmesh
|
bf_bmesh
|
||||||
bf_functions
|
bf_functions
|
||||||
|
bf_geometry
|
||||||
bf_intern_sky
|
bf_intern_sky
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -99,6 +99,7 @@ void register_node_type_geo_join_geometry(void);
|
|||||||
void register_node_type_geo_material_assign(void);
|
void register_node_type_geo_material_assign(void);
|
||||||
void register_node_type_geo_material_replace(void);
|
void register_node_type_geo_material_replace(void);
|
||||||
void register_node_type_geo_material_selection(void);
|
void register_node_type_geo_material_selection(void);
|
||||||
|
void register_node_type_geo_merge_by_distance(void);
|
||||||
void register_node_type_geo_mesh_primitive_circle(void);
|
void register_node_type_geo_mesh_primitive_circle(void);
|
||||||
void register_node_type_geo_mesh_primitive_cone(void);
|
void register_node_type_geo_mesh_primitive_cone(void);
|
||||||
void register_node_type_geo_mesh_primitive_cube(void);
|
void register_node_type_geo_mesh_primitive_cube(void);
|
||||||
|
@@ -357,6 +357,7 @@ DefNode(GeometryNode, GEO_NODE_JOIN_GEOMETRY, 0, "JOIN_GEOMETRY", JoinGeometry,
|
|||||||
DefNode(GeometryNode, GEO_NODE_MATERIAL_ASSIGN, 0, "MATERIAL_ASSIGN", MaterialAssign, "Material Assign", "")
|
DefNode(GeometryNode, GEO_NODE_MATERIAL_ASSIGN, 0, "MATERIAL_ASSIGN", MaterialAssign, "Material Assign", "")
|
||||||
DefNode(GeometryNode, GEO_NODE_MATERIAL_REPLACE, 0, "MATERIAL_REPLACE", MaterialReplace, "Material Replace", "")
|
DefNode(GeometryNode, GEO_NODE_MATERIAL_REPLACE, 0, "MATERIAL_REPLACE", MaterialReplace, "Material Replace", "")
|
||||||
DefNode(GeometryNode, GEO_NODE_MATERIAL_SELECTION, 0, "MATERIAL_SELECTION", MaterialSelection, "Material Selection", "")
|
DefNode(GeometryNode, GEO_NODE_MATERIAL_SELECTION, 0, "MATERIAL_SELECTION", MaterialSelection, "Material Selection", "")
|
||||||
|
DefNode(GeometryNode, GEO_NODE_MERGE_BY_DISTANCE, def_geo_merge_by_distance, "MERGE_BY_DISTANCE", MergeByDistance, "Merge by Distance", "")
|
||||||
DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CIRCLE, def_geo_mesh_circle, "MESH_PRIMITIVE_CIRCLE", MeshCircle, "Mesh Circle", "")
|
DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CIRCLE, def_geo_mesh_circle, "MESH_PRIMITIVE_CIRCLE", MeshCircle, "Mesh Circle", "")
|
||||||
DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CONE, def_geo_mesh_cone, "MESH_PRIMITIVE_CONE", MeshCone, "Cone", "")
|
DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CONE, def_geo_mesh_cone, "MESH_PRIMITIVE_CONE", MeshCone, "Cone", "")
|
||||||
DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CUBE, 0, "MESH_PRIMITIVE_CUBE", MeshCube, "Cube", "")
|
DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CUBE, 0, "MESH_PRIMITIVE_CUBE", MeshCube, "Cube", "")
|
||||||
|
@@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "BKE_pointcloud.h"
|
||||||
|
|
||||||
|
#include "BLI_float3.hh"
|
||||||
|
#include "BLI_span.hh"
|
||||||
|
#include "BLI_task.hh"
|
||||||
|
|
||||||
|
#include "DNA_mesh_types.h"
|
||||||
|
#include "DNA_pointcloud_types.h"
|
||||||
|
|
||||||
|
#include "GEO_mesh_merge_by_distance.hh"
|
||||||
|
#include "GEO_pointcloud_merge_by_distance.hh"
|
||||||
|
|
||||||
|
#include "UI_interface.h"
|
||||||
|
#include "UI_resources.h"
|
||||||
|
|
||||||
|
#include "node_geometry_util.hh"
|
||||||
|
|
||||||
|
using blender::Array;
|
||||||
|
using blender::float3;
|
||||||
|
using blender::Span;
|
||||||
|
using blender::Vector;
|
||||||
|
using blender::geometry::WeldMode;
|
||||||
|
|
||||||
|
static WeldMode weld_mode_from_int(const short type)
|
||||||
|
{
|
||||||
|
switch (static_cast<WeldMode>(type)) {
|
||||||
|
case WeldMode::all:
|
||||||
|
return WeldMode::all;
|
||||||
|
case WeldMode::connected:
|
||||||
|
return WeldMode::connected;
|
||||||
|
}
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
return WeldMode::all;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int16_t weld_mode_to_int(const WeldMode weld_mode)
|
||||||
|
{
|
||||||
|
switch (weld_mode) {
|
||||||
|
case WeldMode::all:
|
||||||
|
return static_cast<int16_t>(WeldMode::all);
|
||||||
|
case WeldMode::connected:
|
||||||
|
return static_cast<int16_t>(WeldMode::connected);
|
||||||
|
}
|
||||||
|
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
return static_cast<int16_t>(WeldMode::all);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace blender::nodes {
|
||||||
|
|
||||||
|
static void geo_node_merge_by_distance_declare(NodeDeclarationBuilder &b)
|
||||||
|
{
|
||||||
|
b.add_input<decl::Geometry>("Geometry");
|
||||||
|
b.add_input<decl::Float>("Distance").min(0.0f).max(10000.0f).subtype(PROP_DISTANCE);
|
||||||
|
b.add_input<decl::Bool>("Selection").default_value(true).hide_value().supports_field();
|
||||||
|
|
||||||
|
b.add_output<decl::Geometry>("Geometry");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void geo_node_merge_by_distance_layout(uiLayout *layout,
|
||||||
|
bContext *UNUSED(C),
|
||||||
|
PointerRNA *ptr)
|
||||||
|
{
|
||||||
|
uiItemR(layout, ptr, "merge_mode", 0, "", ICON_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void geo_merge_by_distance_init(bNodeTree *UNUSED(ntree), bNode *node)
|
||||||
|
{
|
||||||
|
node->custom1 = weld_mode_to_int(WeldMode::all);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void process_mesh(GeoNodeExecParams ¶ms,
|
||||||
|
const WeldMode weld_mode,
|
||||||
|
const float distance,
|
||||||
|
GeometrySet &geometry_set)
|
||||||
|
{
|
||||||
|
MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
|
||||||
|
Mesh *input_mesh = mesh_component.get_for_write();
|
||||||
|
|
||||||
|
GeometryComponentFieldContext field_context{mesh_component, ATTR_DOMAIN_POINT};
|
||||||
|
const Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
|
||||||
|
fn::FieldEvaluator selection_evaluator{field_context, input_mesh->totvert};
|
||||||
|
selection_evaluator.add(selection_field);
|
||||||
|
selection_evaluator.evaluate();
|
||||||
|
const VArray_Span<bool> selection = selection_evaluator.get_evaluated<bool>(0);
|
||||||
|
|
||||||
|
Mesh *result = geometry::mesh_merge_by_distance(input_mesh, selection, distance, weld_mode);
|
||||||
|
if (result != input_mesh) {
|
||||||
|
geometry_set.replace_mesh(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void process_pointcloud(GeoNodeExecParams ¶ms,
|
||||||
|
const float distance,
|
||||||
|
GeometrySet &geometry_set)
|
||||||
|
{
|
||||||
|
PointCloudComponent &pointcloud_component =
|
||||||
|
geometry_set.get_component_for_write<PointCloudComponent>();
|
||||||
|
const PointCloud &pointcloud = *pointcloud_component.get_for_read();
|
||||||
|
|
||||||
|
GeometryComponentFieldContext field_context{pointcloud_component, ATTR_DOMAIN_POINT};
|
||||||
|
const Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
|
||||||
|
fn::FieldEvaluator selection_evaluator{field_context, pointcloud.totpoint};
|
||||||
|
selection_evaluator.add(selection_field);
|
||||||
|
selection_evaluator.evaluate();
|
||||||
|
const VArray_Span<bool> selection = selection_evaluator.get_evaluated<bool>(0);
|
||||||
|
|
||||||
|
pointcloud_component.replace(
|
||||||
|
geometry::pointcloud_merge_by_distance(pointcloud_component, distance, selection));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void geo_node_merge_by_distance_exec(GeoNodeExecParams params)
|
||||||
|
{
|
||||||
|
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
|
||||||
|
|
||||||
|
const geometry::WeldMode weld_mode = weld_mode_from_int(params.node().custom1);
|
||||||
|
const float distance = params.extract_input<float>("Distance");
|
||||||
|
|
||||||
|
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
|
||||||
|
if (geometry_set.has_mesh()) {
|
||||||
|
process_mesh(params, weld_mode, distance, geometry_set);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (geometry_set.has_pointcloud()) {
|
||||||
|
process_pointcloud(params, distance, geometry_set);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
params.set_output("Geometry", std::move(geometry_set));
|
||||||
|
}
|
||||||
|
} // namespace blender::nodes
|
||||||
|
|
||||||
|
void register_node_type_geo_merge_by_distance()
|
||||||
|
{
|
||||||
|
static bNodeType ntype;
|
||||||
|
geo_node_type_base(
|
||||||
|
&ntype, GEO_NODE_MERGE_BY_DISTANCE, "Merge By Distance", NODE_CLASS_GEOMETRY, 0);
|
||||||
|
node_type_init(&ntype, blender::nodes::geo_merge_by_distance_init);
|
||||||
|
ntype.declare = blender::nodes::geo_node_merge_by_distance_declare;
|
||||||
|
ntype.geometry_node_execute = blender::nodes::geo_node_merge_by_distance_exec;
|
||||||
|
ntype.draw_buttons = blender::nodes::geo_node_merge_by_distance_layout;
|
||||||
|
nodeRegisterType(&ntype);
|
||||||
|
}
|
Reference in New Issue
Block a user