Sculpt Dyntopo: fix bug in dyntopo brush spacing.
This commit is contained in:
parent
17d4c7abb1
commit
d293de425f
|
@ -817,7 +817,7 @@ BMVert *BKE_pbvh_vert_create_bmesh(
|
|||
|
||||
PBVHNode *BKE_pbvh_node_from_face_bmesh(PBVH *pbvh, BMFace *f)
|
||||
{
|
||||
return BM_ELEM_CD_GET_INT(f, pbvh->cd_face_node_offset);
|
||||
return pbvh->nodes + BM_ELEM_CD_GET_INT(f, pbvh->cd_face_node_offset);
|
||||
}
|
||||
|
||||
BMFace *BKE_pbvh_face_create_bmesh(PBVH *pbvh,
|
||||
|
@ -1537,7 +1537,7 @@ typedef struct EdgeQueueThreadData {
|
|||
int size;
|
||||
} EdgeQueueThreadData;
|
||||
|
||||
void edge_thread_data_insert(EdgeQueueThreadData *tdata, BMEdge *e)
|
||||
static void edge_thread_data_insert(EdgeQueueThreadData *tdata, BMEdge *e)
|
||||
{
|
||||
if (tdata->size <= tdata->totedge) {
|
||||
tdata->size = (tdata->totedge + 1) << 1;
|
||||
|
@ -1859,9 +1859,9 @@ static void long_edge_queue_edge_add_recursive_2(EdgeQueueThreadData *tdata,
|
|||
}
|
||||
}
|
||||
|
||||
void long_edge_queue_task_cb(void *__restrict userdata,
|
||||
const int n,
|
||||
const TaskParallelTLS *__restrict tls)
|
||||
static void long_edge_queue_task_cb(void *__restrict userdata,
|
||||
const int n,
|
||||
const TaskParallelTLS *__restrict tls)
|
||||
{
|
||||
EdgeQueueThreadData *tdata = ((EdgeQueueThreadData *)userdata) + n;
|
||||
PBVHNode *node = tdata->node;
|
||||
|
@ -2246,16 +2246,6 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx,
|
|||
mv_new->flag |= DYNVERT_BOUNDARY;
|
||||
}
|
||||
|
||||
/* update paint mask */
|
||||
if (eq_ctx->cd_dyn_vert != -1) {
|
||||
float mask_v1 = DYNTOPO_MASK(eq_ctx->cd_dyn_vert, e->v1);
|
||||
float mask_v2 = DYNTOPO_MASK(eq_ctx->cd_dyn_vert, e->v2);
|
||||
|
||||
float mask_v_new = 0.5f * (mask_v1 + mask_v2);
|
||||
|
||||
// BM_ELEM_CD_SET_FLOAT(v_new, eq_ctx->cd_vert_mask_offset, mask_v_new);
|
||||
}
|
||||
|
||||
/* For each face, add two new triangles and delete the original */
|
||||
for (int i = 0; i < (int)edge_loops->count; i++) {
|
||||
BMLoop *l_adj = BLI_buffer_at(edge_loops, BMLoop *, i);
|
||||
|
@ -2850,7 +2840,7 @@ static bool pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx,
|
|||
GHash *deleted_verts = BLI_ghash_ptr_new("deleted_verts");
|
||||
|
||||
double time = PIL_check_seconds_timer();
|
||||
RNG *rng = BLI_rng_new(time * 1000.0f);
|
||||
RNG *rng = BLI_rng_new((unsigned int)(time * 1000.0f));
|
||||
|
||||
//#define TEST_COLLAPSE
|
||||
#ifdef TEST_COLLAPSE
|
||||
|
@ -3637,26 +3627,33 @@ bool BKE_pbvh_bmesh_update_topology_nodes(PBVH *pbvh,
|
|||
return modified;
|
||||
}
|
||||
|
||||
static bool cleanup_valence_3_4(PBVH *pbvh,
|
||||
const float center[3],
|
||||
const float view_normal[3],
|
||||
float radius,
|
||||
const bool use_frontface,
|
||||
const bool use_projected)
|
||||
// this function is being buggy under clang's optimizer, at least on windows
|
||||
#ifdef __clang__
|
||||
# define CLANG_OPT_BUG __attribute__((optnone))
|
||||
#else
|
||||
# define CLANG_OPT_BUG
|
||||
#endif
|
||||
|
||||
CLANG_OPT_BUG static bool cleanup_valence_3_4(PBVH *pbvh,
|
||||
const float center[3],
|
||||
const float view_normal[3],
|
||||
float radius,
|
||||
const bool use_frontface,
|
||||
const bool use_projected)
|
||||
{
|
||||
bool modified = false;
|
||||
BMVert **relink_verts = NULL;
|
||||
BLI_array_staticdeclare(relink_verts, 1024);
|
||||
|
||||
float radius2 = radius * 1.25;
|
||||
float rsqr = radius2 * radius2;
|
||||
|
||||
GSet *vset = BLI_gset_ptr_new("vset");
|
||||
|
||||
for (int n = 0; n < pbvh->totnode; n++) {
|
||||
PBVHNode *node = pbvh->nodes + n;
|
||||
|
||||
/* Check leaf nodes marked for topology update */
|
||||
bool ok = (node->flag & PBVH_Leaf) && (node->flag & PBVH_UpdateTopology);
|
||||
ok = ok && !(node->flag & PBVH_FullyHidden);
|
||||
ok = ok && !(node->flag & (PBVH_FullyHidden | PBVH_Delete));
|
||||
|
||||
if (!ok) {
|
||||
continue;
|
||||
|
@ -3665,12 +3662,12 @@ static bool cleanup_valence_3_4(PBVH *pbvh,
|
|||
BMVert *v;
|
||||
|
||||
TGSET_ITER (v, node->bm_unique_verts) {
|
||||
if (len_squared_v3v3(v->co, center) >= rsqr) {
|
||||
if (len_squared_v3v3(v->co, center) >= rsqr || !v->e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const int val = BM_vert_edge_count(v);
|
||||
if (val < 3 || val > 4) {
|
||||
if (val != 4 && val != 3) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -3678,7 +3675,6 @@ static bool cleanup_valence_3_4(PBVH *pbvh,
|
|||
BMLoop *l;
|
||||
BMLoop *ls[4];
|
||||
BMVert *vs[4];
|
||||
BMEdge *es[4];
|
||||
|
||||
l = v->e->l;
|
||||
|
||||
|
@ -3729,14 +3725,12 @@ static bool cleanup_valence_3_4(PBVH *pbvh,
|
|||
continue;
|
||||
}
|
||||
|
||||
pbvh_bmesh_vert_remove(pbvh, v);
|
||||
BM_log_vert_removed(pbvh->bm_log, v, pbvh->cd_vert_mask_offset);
|
||||
|
||||
BLI_array_clear(relink_verts);
|
||||
|
||||
BMFace *f;
|
||||
BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
|
||||
int ni2 = BM_ELEM_CD_GET_INT(f, pbvh->cd_face_node_offset);
|
||||
|
||||
if (ni2 != DYNTOPO_NODE_NONE) {
|
||||
PBVHNode *node2 = pbvh->nodes + ni2;
|
||||
|
||||
|
@ -3747,6 +3741,8 @@ static bool cleanup_valence_3_4(PBVH *pbvh,
|
|||
}
|
||||
}
|
||||
|
||||
// pbvh_bmesh_vert_remove(pbvh, v);
|
||||
|
||||
modified = true;
|
||||
|
||||
l = v->e->l;
|
||||
|
@ -3761,6 +3757,9 @@ static bool cleanup_valence_3_4(PBVH *pbvh,
|
|||
normal_tri_v3(
|
||||
f1->no, f1->l_first->v->co, f1->l_first->next->v->co, f1->l_first->prev->v->co);
|
||||
}
|
||||
else {
|
||||
printf("eek!\n");
|
||||
}
|
||||
|
||||
if (val == 4 && vs[0] != vs[2] && vs[2] != vs[3] && vs[0] != vs[3]) {
|
||||
vs[0] = ls[0]->v;
|
||||
|
@ -3779,6 +3778,9 @@ static bool cleanup_valence_3_4(PBVH *pbvh,
|
|||
f2->no, f2->l_first->v->co, f2->l_first->next->v->co, f2->l_first->prev->v->co);
|
||||
BM_log_face_added(pbvh->bm_log, f2);
|
||||
}
|
||||
else {
|
||||
printf("eek2!\n");
|
||||
}
|
||||
|
||||
if (f1) {
|
||||
SWAP(void *, f1->l_first->head.data, ls[0]->head.data);
|
||||
|
@ -3789,23 +3791,11 @@ static bool cleanup_valence_3_4(PBVH *pbvh,
|
|||
}
|
||||
|
||||
BM_vert_kill(pbvh->bm, v);
|
||||
#if 0
|
||||
for (int j = 0; j < pbvh->totnode; j++) {
|
||||
PBVHNode *node2 = pbvh->nodes + j;
|
||||
|
||||
if (!node2->bm_unique_verts || !node2->bm_other_verts) { //(node2->flag & PBVH_Leaf)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BLI_table_gset_remove(node2->bm_unique_verts, v, NULL);
|
||||
BLI_table_gset_remove(node2->bm_other_verts, v, NULL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
TGSET_ITER_END
|
||||
}
|
||||
|
||||
BLI_array_free(relink_verts);
|
||||
BLI_gset_free(vset, NULL);
|
||||
|
||||
if (modified) {
|
||||
pbvh->bm->elem_index_dirty |= BM_VERT | BM_FACE | BM_EDGE;
|
||||
|
@ -4308,7 +4298,6 @@ static void pbvh_bmesh_join_subnodes(PBVH *pbvh, PBVHNode *node, PBVHNode *paren
|
|||
static void BKE_pbvh_bmesh_correct_tree(PBVH *pbvh, PBVHNode *node, PBVHNode *parent)
|
||||
{
|
||||
const int size_lower = pbvh->leaf_limit - (pbvh->leaf_limit >> 1);
|
||||
const int size_higher = pbvh->leaf_limit + (pbvh->leaf_limit >> 1);
|
||||
|
||||
if (node->flag & PBVH_Leaf) {
|
||||
// pbvh_bmesh_node_limit_ensure(pbvh, (int)(node - pbvh->nodes));
|
||||
|
@ -4524,8 +4513,6 @@ static void pbvh_bmesh_join_nodes(PBVH *bvh)
|
|||
|
||||
bvh->totnode = j;
|
||||
|
||||
BMVert *v;
|
||||
|
||||
// set vert/face node indices again
|
||||
for (int i = 0; i < bvh->totnode; i++) {
|
||||
PBVHNode *n = bvh->nodes + i;
|
||||
|
|
|
@ -68,9 +68,7 @@ typedef struct BMThreadData {
|
|||
|
||||
# define ELEM_NEXT(type, ptr, size) ((type *)(((char *)ptr) + size))
|
||||
|
||||
ATTR_NO_OPT void bm_vert_task(void *__restrict userdata,
|
||||
const int n,
|
||||
const TaskParallelTLS *__restrict tls)
|
||||
void bm_vert_task(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls)
|
||||
{
|
||||
BMThreadData *data = userdata;
|
||||
BMesh *bm = data->bm;
|
||||
|
@ -306,10 +304,10 @@ static void bm_mesh_cd_flag_apply(BMesh *bm, const char cd_flag)
|
|||
}
|
||||
}
|
||||
|
||||
ATTR_NO_OPT BMesh *BM_mesh_bm_from_me_threaded(BMesh *bm,
|
||||
Object *ob,
|
||||
const Mesh *me,
|
||||
const struct BMeshFromMeshParams *params)
|
||||
BMesh *BM_mesh_bm_from_me_threaded(BMesh *bm,
|
||||
Object *ob,
|
||||
const Mesh *me,
|
||||
const struct BMeshFromMeshParams *params)
|
||||
{
|
||||
if (!bm) {
|
||||
bm = MEM_callocN(sizeof(BMesh), "BM_mesh_bm_from_me_threaded bm");
|
||||
|
|
|
@ -846,14 +846,14 @@ static bool modifier_apply_obdata(
|
|||
return true;
|
||||
}
|
||||
|
||||
ATTR_NO_OPT bool ED_object_modifier_apply(Main *bmain,
|
||||
ReportList *reports,
|
||||
Depsgraph *depsgraph,
|
||||
Scene *scene,
|
||||
Object *ob,
|
||||
ModifierData *md,
|
||||
int mode,
|
||||
bool keep_modifier)
|
||||
bool ED_object_modifier_apply(Main *bmain,
|
||||
ReportList *reports,
|
||||
Depsgraph *depsgraph,
|
||||
Scene *scene,
|
||||
Object *ob,
|
||||
ModifierData *md,
|
||||
int mode,
|
||||
bool keep_modifier)
|
||||
{
|
||||
if (BKE_object_is_in_editmode(ob)) {
|
||||
BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in edit mode");
|
||||
|
@ -1395,8 +1395,7 @@ void OBJECT_OT_modifier_move_to_index(wmOperatorType *ot)
|
|||
/** \name Apply Modifier Operator
|
||||
* \{ */
|
||||
|
||||
#include "BLI_compiler_attrs.h"
|
||||
ATTR_NO_OPT static bool modifier_apply_poll_ex(bContext *C, bool allow_shared)
|
||||
static bool modifier_apply_poll_ex(bContext *C, bool allow_shared)
|
||||
{
|
||||
if (!edit_modifier_poll_generic(C, &RNA_Modifier, 0, false, false)) {
|
||||
return false;
|
||||
|
|
|
@ -718,6 +718,58 @@ static float paint_stroke_integrate_overlap(Brush *br, float factor)
|
|||
return 1.0f / max;
|
||||
}
|
||||
|
||||
static float paint_space_get_final_size_intern(
|
||||
bContext *C, const Scene *scene, PaintStroke *stroke, float pressure, float dpressure)
|
||||
{
|
||||
ePaintMode mode = BKE_paintmode_get_active_from_context(C);
|
||||
float size = BKE_brush_size_get(scene, stroke->brush) * pressure;
|
||||
|
||||
if (paint_stroke_use_scene_spacing(stroke->brush, mode)) {
|
||||
if (!BKE_brush_use_locked_size(scene, stroke->brush)) {
|
||||
float last_object_space_position[3];
|
||||
mul_v3_m4v3(
|
||||
last_object_space_position, stroke->vc.obact->imat, stroke->last_world_space_position);
|
||||
size = paint_calc_object_space_radius(&stroke->vc, last_object_space_position, size);
|
||||
}
|
||||
else {
|
||||
size = BKE_brush_unprojected_radius_get(scene, stroke->brush) * pressure;
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static float paint_space_get_final_size(bContext *C,
|
||||
const Scene *scene,
|
||||
PaintStroke *stroke,
|
||||
float pressure,
|
||||
float dpressure,
|
||||
float length)
|
||||
{
|
||||
if (BKE_brush_use_size_pressure(stroke->brush)) {
|
||||
/* use pressure to modify size. set spacing so that at 100%, the circles
|
||||
* are aligned nicely with no overlap. for this the spacing needs to be
|
||||
* the average of the previous and next size. */
|
||||
float s = paint_space_stroke_spacing(C, scene, stroke, 1.0f, pressure);
|
||||
float q = s * dpressure / (2.0f * length);
|
||||
float pressure_fac = (1.0f + q) / (1.0f - q);
|
||||
|
||||
float last_size_pressure = stroke->last_pressure;
|
||||
float new_size_pressure = stroke->last_pressure * pressure_fac;
|
||||
|
||||
/* average spacing */
|
||||
float last_size = paint_space_get_final_size_intern(
|
||||
C, scene, stroke, last_size_pressure, pressure);
|
||||
float new_size = paint_space_get_final_size_intern(
|
||||
C, scene, stroke, new_size_pressure, pressure);
|
||||
|
||||
return 0.5f * (last_size + new_size);
|
||||
}
|
||||
else {
|
||||
return paint_space_get_final_size_intern(C, scene, stroke, 1.0, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
static float paint_space_stroke_spacing_variable(bContext *C,
|
||||
const Scene *scene,
|
||||
PaintStroke *stroke,
|
||||
|
@ -748,6 +800,8 @@ static float paint_space_stroke_spacing_variable(bContext *C,
|
|||
return paint_space_stroke_spacing(C, scene, stroke, 1.0f, pressure);
|
||||
}
|
||||
|
||||
#include "BLI_compiler_attrs.h"
|
||||
|
||||
/* For brushes with stroke spacing enabled, moves mouse in steps
|
||||
* towards the final mouse location. */
|
||||
static int paint_space_stroke(bContext *C,
|
||||
|
@ -817,9 +871,16 @@ static int paint_space_stroke(bContext *C,
|
|||
|
||||
ups->overlap_factor = paint_stroke_integrate_overlap(stroke->brush,
|
||||
spacing / no_pressure_spacing);
|
||||
if (use_scene_spacing) {
|
||||
float size = paint_space_get_final_size(C, scene, stroke, pressure, dpressure, length);
|
||||
|
||||
stroke->stroke_distance += spacing / stroke->zoom_2d;
|
||||
stroke->stroke_distance_t += (spacing / stroke->zoom_2d) / stroke->ups->pixel_radius;
|
||||
stroke->stroke_distance += stroke->ups->pixel_radius * spacing / size;
|
||||
stroke->stroke_distance_t += spacing / size;
|
||||
}
|
||||
else {
|
||||
stroke->stroke_distance += spacing / stroke->zoom_2d;
|
||||
stroke->stroke_distance_t += (spacing / stroke->zoom_2d) / stroke->ups->pixel_radius;
|
||||
}
|
||||
|
||||
paint_brush_stroke_add_step(C, op, mouse, pressure);
|
||||
|
||||
|
|
|
@ -6658,7 +6658,7 @@ typedef struct DynTopoAutomaskState {
|
|||
SculptSession *ss;
|
||||
} DynTopoAutomaskState;
|
||||
|
||||
ATTR_NO_OPT static float sculpt_topology_automasking_cb(SculptVertRef vertex, void *vdata)
|
||||
static float sculpt_topology_automasking_cb(SculptVertRef vertex, void *vdata)
|
||||
{
|
||||
DynTopoAutomaskState *state = (DynTopoAutomaskState *)vdata;
|
||||
float mask = SCULPT_automasking_factor_get(state->cache, state->ss, vertex);
|
||||
|
@ -6667,7 +6667,7 @@ ATTR_NO_OPT static float sculpt_topology_automasking_cb(SculptVertRef vertex, vo
|
|||
return mask * mask2;
|
||||
}
|
||||
|
||||
ATTR_NO_OPT static float sculpt_topology_automasking_mask_cb(SculptVertRef vertex, void *vdata)
|
||||
static float sculpt_topology_automasking_mask_cb(SculptVertRef vertex, void *vdata)
|
||||
{
|
||||
DynTopoAutomaskState *state = (DynTopoAutomaskState *)vdata;
|
||||
return 1.0f - SCULPT_vertex_mask_get(state->ss, vertex);
|
||||
|
|
|
@ -148,9 +148,9 @@ static bool SCULPT_automasking_needs_factors_cache(const Sculpt *sd, const Brush
|
|||
return false;
|
||||
}
|
||||
|
||||
ATTR_NO_OPT float SCULPT_automasking_factor_get(AutomaskingCache *automasking,
|
||||
SculptSession *ss,
|
||||
SculptVertRef vert)
|
||||
float SCULPT_automasking_factor_get(AutomaskingCache *automasking,
|
||||
SculptSession *ss,
|
||||
SculptVertRef vert)
|
||||
{
|
||||
float mask = 1.0f;
|
||||
bool do_concave;
|
||||
|
@ -453,7 +453,7 @@ static void SCULPT_concavity_automasking_init(Object *ob,
|
|||
// BKE_pbvh_vertex_iter_begin
|
||||
}
|
||||
|
||||
ATTR_NO_OPT AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, Brush *brush, Object *ob)
|
||||
AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, Brush *brush, Object *ob)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
const int totvert = SCULPT_vertex_count_get(ss);
|
||||
|
|
|
@ -239,10 +239,10 @@ static int gpu_comp_map[] = {
|
|||
4 // GPU_COMP_I10,
|
||||
};
|
||||
|
||||
ATTR_NO_OPT static void convert_gpu_data(void *src,
|
||||
void *dst,
|
||||
GPUVertCompType srcType,
|
||||
GPUVertCompType dstType)
|
||||
static void convert_gpu_data(void *src,
|
||||
void *dst,
|
||||
GPUVertCompType srcType,
|
||||
GPUVertCompType dstType)
|
||||
{
|
||||
if (srcType == dstType) {
|
||||
memcpy(dst, src, gpu_comp_map[(int)srcType]);
|
||||
|
@ -309,7 +309,7 @@ ATTR_NO_OPT static void convert_gpu_data(void *src,
|
|||
GPU_vertbuf_attr_set(vert_buf, g_vbo_id.pos, v_index, v->co);
|
||||
*/
|
||||
|
||||
ATTR_NO_OPT static void set_cd_data_bmesh(
|
||||
static void set_cd_data_bmesh(
|
||||
GPUVertBuf *vert_buf, CDAttrLayers *attr_array, int attr_array_len, BMElem *elem, int vertex)
|
||||
{
|
||||
for (int i = 0; i < attr_array_len; i++) {
|
||||
|
|
Loading…
Reference in New Issue