[Bf-blender-cvs] [350e783668d] temp_bmesh_multires: Add skeletal beginnings of C++ sculpt refactor design study (note that it's #ifdef'd out).
Joseph Eagar
noreply at git.blender.org
Thu Sep 16 00:06:32 CEST 2021
Commit: 350e783668d67592472246bc43e71693b1080820
Author: Joseph Eagar
Date: Wed Sep 15 14:56:19 2021 -0700
Branches: temp_bmesh_multires
https://developer.blender.org/rB350e783668d67592472246bc43e71693b1080820
Add skeletal beginnings of C++ sculpt refactor
design study (note that it's #ifdef'd out).
Basic idea is to put all the sculpt brush code
in a single large template. This template
takes a PBVH adaptor class (of which there
would be three, one per PBVH_XXX type)
as a template argument.
Basically we're using the compiler to generate
three complete copies of every brush implementation.
C++20 concepts are used to validate the pbvh classes.
An example brush implementation:
pbvh->forVertsInRange(
{
.brush = ss->cache->brush,
.radius = radius,
.use_threads = true,
.use_original = false
},
[&offset](auto viter, int node_i, void *userdata) {
//add offset to vertex coordinates
madd_v3_v3fl(viter.co, offset, viter.fade);
},
[](PBVHNode *node, int node_i, void *userdata) {
BKE_pbvh_node_mark_update(node);
});
===================================================================
M source/blender/editors/sculpt_paint/CMakeLists.txt
A source/blender/editors/sculpt_paint/sculpt.cc
A source/blender/editors/sculpt_paint/sculpt.hh
===================================================================
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index c316ae34e6a..b795103839f 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -81,6 +81,9 @@ set(SRC
sculpt_displacement.h
sculpt_replay.c
+ sculpt.cc
+ sculpt.hh
+
paint_intern.h
sculpt_intern.h
)
diff --git a/source/blender/editors/sculpt_paint/sculpt.cc b/source/blender/editors/sculpt_paint/sculpt.cc
new file mode 100644
index 00000000000..adfe2a1c8b1
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/sculpt.cc
@@ -0,0 +1,20 @@
+#if 0
+# include "sculpt.hh"
+
+typedef blender::sculpt::SculptImpl<BMVert *,
+ BMEdge *,
+ BMFace *,
+ blender::sculpt::BMeshBackend,
+ blender::sculpt::BMeshPBVH>
+ BMeshSculpt;
+
+BMeshSculpt *sculpt = new BMeshSculpt(NULL, NULL);
+
+void test_cxsculpt()
+{
+ float dir[3] = {1.0f, 2.0f, 3.0f};
+ float cent[3] = {0.0f, 0.0f, 0.0f};
+
+ sculpt->moveVerts(cent, 5.0f, dir);
+}
+#endif
diff --git a/source/blender/editors/sculpt_paint/sculpt.hh b/source/blender/editors/sculpt_paint/sculpt.hh
new file mode 100644
index 00000000000..ca144ea6391
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/sculpt.hh
@@ -0,0 +1,474 @@
+#if 0
+# pragma once
+
+/*
+
+This is a proof of concept of how a C++ sculpt system could work.
+
+We can't really use virtual-based polymorphism for performance reasons,
+so the idea is to use templates and C++20's concepts instead.
+
+*/
+
+# include "BKE_pbvh.h"
+# include "BLI_bitmap.h"
+# include "BLI_map.hh"
+# include "BLI_math.h"
+# include "BLI_mempool.h"
+# include "BLI_task.hh"
+# include "MEM_guardedalloc.h"
+
+# include "DNA_brush_enums.h"
+# include "DNA_brush_types.h"
+# include "DNA_mesh_types.h"
+# include "DNA_meshdata_types.h"
+# include "DNA_scene_types.h"
+
+# include "BKE_brush.h"
+# include "BKE_mesh.h"
+# include "BKE_object.h"
+# include "BKE_paint.h"
+# include "BKE_pbvh.h"
+
+# include "sculpt_intern.h"
+
+# include "bmesh.h"
+# include <concepts>
+# include <functional>
+# include <iterator>
+
+/* clang-format off */
+#include "../../blenkernel/intern/pbvh_intern.h"
+/* clang-format on */
+
+extern PBVHNode *the_fake_node;
+
+namespace blender {
+namespace sculpt {
+
+typedef struct BrushSearchArgs {
+ float *center;
+ float radius;
+ bool use_threads;
+ bool use_original;
+ void *userdata;
+ const Brush *brush;
+ SculptBrushTest *test; // may be NULL, will be pulled from brush
+ SculptBrushTestFn test_func;
+} BrushSearchArgs;
+
+class BMeshPBVH {
+ public:
+ BMeshPBVH()
+ {
+ }
+
+ struct unique_verts_iter : public std::iterator<std::forward_iterator_tag, BMVert> {
+ public:
+ ~unique_verts_iter(){};
+
+ unique_verts_iter(PBVHNode *node) : _node(node)
+ {
+ i = _i = 0;
+
+ while (_i < _node->bm_unique_verts->length && _node->bm_unique_verts->elems[_i] == nullptr) {
+ _i++;
+ }
+ }
+
+ unique_verts_iter(const unique_verts_iter &a)
+ {
+ i = a.i;
+ _i = a._i;
+ index = a.index;
+ vertex = a.vertex;
+ co = a.co;
+ no = a.no;
+ mask = a.mask;
+ color = a.color;
+ }
+
+ unique_verts_iter(bool is_end_iter)
+ {
+ i = _i = index = 0;
+ vertex = nullptr;
+ co = nullptr;
+ no = nullptr;
+ mask = nullptr;
+ color = nullptr;
+ }
+
+ unique_verts_iter()
+ {
+ i = _i = index = 0;
+ vertex = nullptr;
+ co = nullptr;
+ no = nullptr;
+ mask = nullptr;
+ color = nullptr;
+ }
+
+ inline unique_verts_iter &operator++()
+ {
+ i++;
+ _i++;
+
+ while (i < _node->bm_unique_verts->length && _node->bm_unique_verts->elems[_i] == nullptr) {
+ _i++;
+ }
+
+ if (_i >= _node->bm_unique_verts->length) {
+ vertex = NULL;
+ }
+ else {
+ vertex = reinterpret_cast<BMVert *>(_node->bm_unique_verts->elems + _i);
+ }
+
+ if (vertex) {
+ deprecated_vertref.i = reinterpret_cast<intptr_t>(vertex);
+ co = vertex->co;
+ no = vertex->no;
+ }
+
+ return *this;
+ }
+
+ inline unique_verts_iter operator++(int)
+ {
+ unique_verts_iter tmp(*this);
+ operator++();
+ return tmp;
+ }
+
+ inline void reset()
+ {
+ _i = i = 0;
+ while (_i < _node->bm_unique_verts->length && _node->bm_unique_verts->elems[_i] == nullptr) {
+ _i++;
+ }
+ }
+
+ inline unique_verts_iter begin()
+ {
+ unique_verts_iter ret = *this;
+
+ ret.reset();
+
+ return ret;
+ }
+
+ inline unique_verts_iter end()
+ {
+ return unique_verts_iter(true);
+ }
+
+ inline bool operator==(const unique_verts_iter &b)
+ {
+ // detect comparison with end iterator
+ return (!vertex && !b.vertex) || (_node == b._node && i == b.i);
+ }
+
+ inline bool operator!=(const unique_verts_iter &b)
+ {
+ return !(*this == b);
+ }
+
+ inline unique_verts_iter operator*()
+ {
+ return *this;
+ }
+
+ SculptVertRef deprecated_vertref;
+
+ int i;
+ int index;
+ BMVert *vertex;
+ float *co;
+ float *no;
+ float *mask;
+ float *color;
+
+ private:
+ PBVHNode *_node;
+ int _i;
+ };
+
+ struct brush_verts_iter : unique_verts_iter {
+ public:
+ ~brush_verts_iter(){};
+
+ brush_verts_iter(SculptSession *ss,
+ PBVHNode *node,
+ SculptBrushTest *test,
+ SculptBrushTestFn test_func,
+ const Brush *brush,
+ float *center,
+ float radius,
+ int thread_id)
+ : _node(node),
+ brush(brush),
+ radius_scale(radius_scale),
+ test(*test),
+ test_func(test_func),
+ _ss(ss),
+ _thread_id(thread_id)
+ {
+ copy_v3_v3(this->center, center);
+ this->radius = radius;
+ this->radius_squared = radius * radius;
+ }
+
+ brush_verts_iter(const brush_verts_iter &a)
+ {
+ copy_v3_v3(center, a.center);
+ radius = a.radius;
+ radius_squared = a.radius_squared;
+ _node = a._node;
+ brush = a.brush;
+
+ _ss = a._ss;
+ }
+
+ brush_verts_iter(bool is_end)
+ {
+ brush = nullptr;
+ }
+
+ brush_verts_iter begin()
+ {
+ brush_verts_iter ret = *this;
+ unique_verts_iter &viter = static_cast<unique_verts_iter &>(ret);
+
+ viter.reset();
+
+ return ret;
+ }
+
+ brush_verts_iter end()
+ {
+ return brush_verts_iter(true);
+ }
+
+ inline brush_verts_iter &operator++()
+ {
+ unique_verts_iter::operator++();
+
+ skip_outside();
+
+ if (!vertex) {
+ brush = nullptr;
+ }
+
+ fade = SCULPT_brush_strength_factor(
+ _ss, brush, co, 3, NULL, no, mask ? *mask : 0.0f, deprecated_vertref, _thread_id);
+
+ return *this;
+ }
+
+ inline bool operator==(const brush_verts_iter &b)
+ {
+ // detect comparison with end iterator
+ if (!brush && !b.brush) {
+ return true;
+ }
+
+ return unique_verts_iter::operator==(static_cast<const unique_verts_iter &>(b));
+ }
+
+ inline bool operator!=(const brush_verts_iter &b)
+ {
+ return !(*this == b);
+ }
+
+ inline brush_verts_iter &operator*()
+ {
+ return *this;
+ }
+
+ const Brush *brush;
+ float center[3];
+ float radius;
+ float radius_scale;
+ float radius_squared;
+
+ float fade;
+
+ SculptBrushTest test;
+ SculptBrushTestFn test_func;
+
+ unique_verts_iter viter;
+
+ private:
+ inline void skip_outside()
+ {
+ while (vertex && !test_func(&test, co)) {
+ unique_verts_iter::operator*();
+ }
+ }
+
+ SculptSession *_ss;
+ PBVHNode *_node;
+ int _thread_id;
+ };
+
+ inline unique_verts_iter forAllUniqueVerts(PBVHNode *node)
+ {
+ unique_verts_iter ret(node);
+
+ return ret;
+ }
+
+ inline float *getVertexCo(BMVert *v)
+ {
+ return v->co;
+ }
+
+ const inline float *getVertexNormal(BMVert *v)
+ {
+ return v->no;
+ }
+
+ inline void setVertexNormal(BMVert *v, float *no)
+ {
+ }
+
+ /*
+ * SculptSession *ss,
+ PBVHNode *node,
+ SculptBrushTest test,
+ SculptBrushTestFn test_func,
+ Brush *brush,
+ float center[3],
+ float radius,
+ int thread_id)
+ */
+ void forVertsInRange(
+ BrushSearchArgs args,
+ std::function<void(brush_verts_iter biter, int node_i, void *userdata)> callback,
+ std::function<void(PBVHNode *node, int node_i, void *userdata)> node_callback)
+ {
+ PBVHNode **nodes = NULL;
+ int totnode = 0;
+
+ SculptBrushTest default_test;
+
+ if (!args.test) {
+ args.test = &default_test;
+ args.test_func = SCULPT_brush_test_init_with_falloff_shape(
+ _ss, &default_test, args.brush->falloff_shape);
+ }
+
+ SculptSearchSphereData data = {.ss = _ss,
+ .sd = _sd,
+ .radius_squared = args.radius * args.radius,
+ .original = args.use_original,
+ .center = args.center};
+
+ BKE_pbvh_search_gather(_pbvh, SCULPT_search_sphere_cb, &data, &nodes, &totnode);
+
+ SculptSession *ss = _ss;
+
+ /*SculptSession *ss,
+ PBVHNode *node,
+ SculptBrushTest test,
+ SculptBrushTestFn test_func,
+ Brush *brush,
+ float *center,
+ float radius,
+ int thread_id)
+ */
+
+ blender::IndexRange range(0, totnode);
+ blender::threading::parallel_for(
+ range, 1, [&args, &nodes, &ss, &callback, &node_callback](blender::IndexRange &subrange) {
+ for (auto i : subrange) {
+ brus
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list