[Bf-blender-cvs] [473cea6f0a0] soc-2017-sculpting_improvements: Added edge border calculation. Cut edge for the part is now being calculated. Added some Macros for dynamic memory allocation.
Sebastian Witt
noreply at git.blender.org
Wed Aug 2 11:42:39 CEST 2017
Commit: 473cea6f0a0fd6b5f700f5717c9667bf59a1f2d2
Author: Sebastian Witt
Date: Wed Aug 2 11:39:59 2017 +0200
Branches: soc-2017-sculpting_improvements
https://developer.blender.org/rB473cea6f0a0fd6b5f700f5717c9667bf59a1f2d2
Added edge border calculation. Cut edge for the part is now being calculated. Added some Macros for dynamic memory allocation.
===================================================================
M source/blender/editors/sculpt_paint/sculpt.c
M source/blender/editors/space_view3d/view3d_draw.c
===================================================================
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index fc3e3bd79e6..c9089fe5dd6 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -118,8 +118,13 @@
#include "BLI_alloca.h"
#include "BLI_array.h"
-#define SILHOUETTE_STROKE_STORE_CHUNK 512
-/*#define DEBUG_DRAW*/
+#define SIL_STROKE_STORE_CHUNK 512
+/* Fillet Blur determines the fuzziness wether a vert is intersecting or not.
+ * Important for example if two shapes with the same thickness intersect. */
+#define SIL_FILLET_BLUR_MAX 0.3f
+#define SIL_FILLET_BLUR_MIN 0.001f
+
+#define DEBUG_DRAW
#ifdef DEBUG_DRAW
/* static void bl_debug_draw(void);*/
/* add these locally when using these functions for testing */
@@ -182,6 +187,7 @@ typedef struct SilhouetteData {
int resolution; /* Subdivision of the shape*/
float anchor[3]; /* Origin point of the reference plane */
float z_vec[3]; /* Orientation of the reference plane */
+ MeshElemMap *emap; /* Original Mesh vert -> edges map */
} SilhouetteData;
/** \name Tool Capabilities
@@ -5098,10 +5104,10 @@ static void silhouette_stroke_free(SilhouetteStroke *stroke)
static SilhouetteStroke *silhouette_stroke_new()
{
SilhouetteStroke *stroke = MEM_callocN(sizeof(SilhouetteStroke), "SilhouetteStroke");
- stroke->points = MEM_callocN(sizeof(float) * 3 * SILHOUETTE_STROKE_STORE_CHUNK,"SilhouetteStrokePoints");
- stroke->points_v2 = MEM_callocN(sizeof(float) * 2 * SILHOUETTE_STROKE_STORE_CHUNK,"SilhouetteStrokePoints");
+ stroke->points = MEM_callocN(sizeof(float) * 3 * SIL_STROKE_STORE_CHUNK,"SilhouetteStrokePoints");
+ stroke->points_v2 = MEM_callocN(sizeof(float) * 2 * SIL_STROKE_STORE_CHUNK,"SilhouetteStrokePoints");
stroke->totvert = 0;
- stroke->max_verts = SILHOUETTE_STROKE_STORE_CHUNK;
+ stroke->max_verts = SIL_STROKE_STORE_CHUNK;
BB_reset(&stroke->bb);
return stroke;
}
@@ -5157,7 +5163,7 @@ static void silhoute_stroke_point_to_3d(SilhouetteData *sil, int point, float r_
static void silhouette_stroke_add_3Dpoint(SilhouetteStroke *stroke, float point[3])
{
if (stroke->totvert >= stroke->max_verts) {
- stroke->max_verts += SILHOUETTE_STROKE_STORE_CHUNK;
+ stroke->max_verts += SIL_STROKE_STORE_CHUNK;
stroke->points = MEM_reallocN(stroke->points, sizeof(float) * 3 * stroke->max_verts);
stroke->points_v2 = MEM_reallocN(stroke->points_v2, sizeof(float) * 2 * stroke->max_verts);
}
@@ -5170,7 +5176,7 @@ static void silhouette_stroke_add_3Dpoint(SilhouetteStroke *stroke, float point[
static void silhouette_stroke_add_point(SilhouetteData *sil, SilhouetteStroke *stroke, float point[2])
{
if (stroke->totvert >= stroke->max_verts) {
- stroke->max_verts += SILHOUETTE_STROKE_STORE_CHUNK;
+ stroke->max_verts += SIL_STROKE_STORE_CHUNK;
stroke->points = MEM_reallocN(stroke->points, sizeof(float) * 3 * stroke->max_verts);
stroke->points_v2 = MEM_reallocN(stroke->points_v2, sizeof(float) * 2 * stroke->max_verts);
}
@@ -7031,46 +7037,175 @@ static void stroke_smooth_cap(SilhouetteData *sil, SilhouetteStroke *stroke, flo
}
}
+static void remove_connected_from_edgehash(MeshElemMap *emap, GHash *edgeHash, int v) {
+ for (int e = 0; e < emap[v].count; e++) {
+ BLI_ghash_remove(edgeHash, emap[v].indices[e], NULL, NULL);
+ }
+}
+
+static bool has_cross_border_neighbour(Mesh *me, GHash *vertHash, GHash *edgeHash, MeshElemMap *emap, int edge, int l_v_edge, int depth) {
+ int v_edge;
+
+ v_edge = me->medge[edge].v1 == l_v_edge ? me->medge[edge].v2 : me->medge[edge].v1;
+
+ if (depth == 0) {
+ return BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(v_edge));
+ } else {
+ if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(v_edge))){
+ for (int e = 0; e < emap[v_edge].count; e++) {
+ if(emap[v_edge].indices[e] != edge) {
+ if(has_cross_border_neighbour(me, vertHash, edgeHash, emap, emap[v_edge].indices[e], v_edge, depth - 1)){
+ return true;
+ }
+ }
+ }
+ } else {
+ BLI_ghash_remove(edgeHash, edge, NULL, NULL);
+ }
+ }
+ return false;
+}
+
+/* Get the adjacent edge which connects the edges within the edgeHash. Used to create multiple ordered loops
+ * v_edge is the endpoint off curr_edge from which to branch off
+ * TODO: One wide strips might get cutoff */
+static int get_adjacent_edge(Mesh *me, MeshElemMap *emap, int curr_edge, int v_edge, GHash *edgeHash, GHash *vertHash)
+{
+ for (int e = 0; e < emap[v_edge].count; e++) {
+ if(emap[v_edge].indices[e] != curr_edge && has_cross_border_neighbour(me, vertHash, edgeHash, emap, emap[v_edge].indices[e], v_edge, 1)) {
+ return emap[v_edge].indices[e];
+ }
+ }
+ for (int e = 0; e < emap[v_edge].count; e++) {
+ if(emap[v_edge].indices[e] != curr_edge && has_cross_border_neighbour(me, vertHash, edgeHash, emap, emap[v_edge].indices[e], v_edge, 2)) {
+ return emap[v_edge].indices[e];
+ }
+ }
+ /*End Of Loop. Shouldn't happen with two manifold meshes*/
+ return -1;
+}
+
/* Calculate the intersections with existing geometry. Used to connect the new Silhouette to the old mesh
* Fillets are the smooth transition from one part to another.
*/
-static void do_calc_fillet_line_task_cb_ex(
- void *userdata, void *UNUSED(userdata_chunk), const int n, const int UNUSED(thread_id))
+static void do_calc_fillet_line_task_cb_ex(void *userdata, void *UNUSED(userdata_chunk), const int n, const int UNUSED(thread_id))
{
SculptThreadedTaskData *data = userdata;
SculptSession *ss = data->ob->sculpt;
SilhouetteData *sil = data->sil;
+ Mesh *me = data->ob->data;
+ PBVHNode *curr_node = data->nodes[n];
PBVHVertexIter vd;
- float (*proxy)[3];
float point[2];
float sil_plane[4];
+ float fuzz;
+ MEdge e_comp;
+ int v_i, vd_i;
+ GHash *vertHash = BLI_ghash_int_new("vertices within intersection");
+ GHash *edgeHash = BLI_ghash_int_new("edges on the intersection");
+ int *edge_ring_fillet = NULL;
+ BLI_array_declare(edge_ring_fillet);
+ int comp_v;
+
+ /*GHashIterState state;*/
+ GHashIterator gh_iter;
+ int curr_edge = -1, last_edge = -1, start_edge = -1, tmp_curr_edge = -1;
plane_from_point_normal_v3(sil_plane, sil->anchor, sil->z_vec);
- proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
-
- BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ /* TODO: Is this a unique vert iteration? If not edges might be added twice by different threads */
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, curr_node, vd, PBVH_ITER_UNIQUE)
{
/* get the interior vertices of the 2d drawn silhouette and all relevant vertices
* Ignores smoothness, assuming the smoothness blures the fillets anyways it should be ok. */
- if (dist_squared_to_plane_v3(vd.co, sil_plane) <= sil->depth) {
- ED_view3d_project_float_v2_m4(sil->ar, vd.co, point, data->mat);
- if (isect_point_poly_v2(point, (float(*)[2])sil->current_stroke->points_v2, sil->current_stroke->totvert, false)){
- #ifdef DEBUG_DRAW
- bl_debug_color_set(0xff0000);
- bl_debug_draw_point(vd.co, 0.2f);
- bl_debug_color_set(0x000000);
- #endif
+ fuzz = SIL_FILLET_BLUR_MIN + sil->smoothness * 0.01f * SIL_FILLET_BLUR_MAX;
+ if (dist_squared_to_plane_v3(vd.co, sil_plane) <= sil->depth + fuzz) {
+ if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(vd.vert_indices[vd.i]))) {
+ ED_view3d_project_float_v2_m4(sil->ar, vd.co, point, data->mat);
+ if (isect_point_poly_v2(point, (float(*)[2])sil->current_stroke->points_v2, sil->current_stroke->totvert, false)){
+ if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(vd.vert_indices[vd.i]))) {
+ BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(vd.vert_indices[vd.i]), SET_INT_IN_POINTER(vd.vert_indices[vd.i]));
+ vd_i = vd.vert_indices[vd.i];
+ for (int e = 0; e < sil->emap[vd_i].count; e++){
+ e_comp = me->medge[sil->emap[vd_i].indices[e]];
+ v_i = e_comp.v1 == vd_i ? e_comp.v2 : e_comp.v1;
+ if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(v_i)))
+ {
+ ED_view3d_project_float_v2_m4(sil->ar, me->mvert[v_i].co, point, data->mat);
+ if (!isect_point_poly_v2(point, (float(*)[2])sil->current_stroke->points_v2, sil->current_stroke->totvert, false) || dist_squared_to_plane_v3(me->mvert[v_i].co, sil_plane) > sil->depth + fuzz) {
+ BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(sil->emap[vd_i].indices[e]), SET_INT_IN_POINTER(sil->emap[vd_i].indices[e]));
+ }
+ }
+ }
+ }
+ }
}
}
}
BKE_pbvh_vertex_iter_end;
+
+ /* TODO: Workaround, do a BLI_ghash_pop style while loop
+ * TODO: A adjacency search might fail if there is not a single path to be searched, shouldn't be a problem on first thought though.
+ * Breaker is a anti crash method in case the algorithm gets caught in an endless loop. Shouldn't happen!*/
+ int breaker;
+ do {
+ breaker = me->totedge;
+ BLI_ghashIterator_init(&gh_iter, edgeHash);
+ if(!BLI_ghashIterator_done(&gh_iter)){
+ start_edge = BLI_ghashIterator_getValue(&gh_iter);
+ BLI_ghash_remove(edgeHash, start_edge, NULL, NULL);
+ comp_v = BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->medge[start_edge].v1)) ? me->medge[start_edge].v2 : me->medge[start_edge].v1;
+ BLI_assert(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(comp_v)));
+ start_edge = get_adjacent_edge(me, sil->emap, start_edge, comp_v, edgeHash, vertHash);
+ if(start_edge >= 0) {
+ curr_edge = start_edge;
+ last_edge = -1;
+
+ while(!(curr_edge == start_edge && last_edge != -1) && curr_edge != -1 && breaker > 0) {
+ BLI_array_append(edge_ring_fillet, curr_edge);
+ if(last_edge == -1) {
+ comp_v = me->medge[start_edge].v1;
+ } else {
+ if (me->medge[curr_edge].v1 == me->medge[last_edge].v1 || me->medge[curr_edge].v1 == me->medge[last_edge].v2) {
+ comp_v = me->medge[curr_edge].v2;
+ } else {
+ comp_v = me->medge[curr_edge].v1;
+ }
+ }
+ remove_connected_from_edgehash(sil->emap, edgeHash, comp_v);
+ tmp_curr_edge = get_adjacent_edge(me, sil->emap, curr_edge, comp_v, edgeHash, vertHash);
+ last_edge = curr_edge;
+ curr_edge = tmp_curr_edge;
+ breaker --;
+ }
+ BLI_assert(breaker > 0);
+ }
+ }
+ printf("Found a cut loop!\n");
+ } while (!
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list