Sculpt dyntopo: fix various faceset init operator bugs

that crept in.
This commit is contained in:
Joseph Eagar 2021-08-16 16:34:35 -07:00
parent fb463a13cd
commit dcaba4c5e3
2 changed files with 121 additions and 43 deletions

View File

@ -24,6 +24,8 @@
#include "MEM_guardedalloc.h"
#include "BLI_alloca.h"
#include "BLI_array.h"
#include "BLI_blenlib.h"
#include "BLI_dial_2d.h"
#include "BLI_ghash.h"
@ -151,15 +153,35 @@ bool SCULPT_calc_principle_curvatures(SculptSession *ss,
SCULPT_vertex_normal_get(ss, vertex, no);
normal_covariance(nmat, no);
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) {
SCULPT_vertex_normal_get(ss, ni.vertex, no2);
sub_v3_v3(no2, no);
if (useAccurateSolver) {
int val = SCULPT_vertex_valence_get(ss, vertex);
float *ws = BLI_array_alloca(ws, val);
float *cot1 = BLI_array_alloca(cot1, val);
float *cot2 = BLI_array_alloca(cot2, val);
float *areas = BLI_array_alloca(areas, val);
float totarea = 0.0f;
normal_covariance(nmat2, no2);
SCULPT_get_cotangents(ss, vertex, ws, cot1, cot2, areas, &totarea);
add_m3_m3m3(nmat, nmat, nmat2);
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) {
SCULPT_vertex_normal_get(ss, ni.vertex, no2);
sub_v3_v3(no2, no);
normal_covariance(nmat2, no2);
madd_m3_m3m3fl(nmat, nmat, nmat2, ws[ni.i]);
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
}
else {
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) {
SCULPT_vertex_normal_get(ss, ni.vertex, no2);
sub_v3_v3(no2, no);
normal_covariance(nmat2, no2);
add_m3_m3m3(nmat, nmat, nmat2);
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
if (!useAccurateSolver || !BLI_eigen_solve_selfadjoint_m3(nmat, out->ks, out->principle)) {
// do simple power solve in one direction

View File

@ -51,6 +51,7 @@
#include "BKE_paint.h"
#include "BKE_pbvh.h"
#include "BKE_scene.h"
#include "BKE_subdiv_ccg.h"
#include "DEG_depsgraph.h"
@ -74,14 +75,37 @@
#include <math.h>
#include <stdlib.h>
int SCULPT_face_set_get(SculptSession *ss, SculptFaceRef face)
static int sculpt_face_material_get(SculptSession *ss, SculptFaceRef face)
{
if (ss->bm) {
BMFace *f = (BMFace *)face.i;
return BM_ELEM_CD_GET_INT(f, ss->cd_faceset_offset);
int ret = 0;
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_BMESH: {
BMFace *f = (BMFace *)face.i;
return f->mat_nr;
}
case PBVH_GRIDS:
case PBVH_FACES:
return ss->mpoly[face.i].mat_nr;
}
return ss->face_sets[face.i];
return -1;
}
int SCULPT_face_set_get(SculptSession *ss, SculptFaceRef face)
{
int ret = 0;
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_BMESH: {
BMFace *f = (BMFace *)face.i;
return BM_ELEM_CD_GET_INT(f, ss->cd_faceset_offset);
}
case PBVH_GRIDS:
case PBVH_FACES:
return ss->face_sets[face.i];
}
return -1;
}
// returns previous face set
@ -89,15 +113,19 @@ int SCULPT_face_set_set(SculptSession *ss, SculptFaceRef face, int fset)
{
int ret = 0;
if (ss->bm) {
BMFace *f = (BMFace *)face.i;
ret = BM_ELEM_CD_GET_INT(f, ss->cd_faceset_offset);
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_BMESH: {
BMFace *f = (BMFace *)face.i;
ret = BM_ELEM_CD_GET_INT(f, ss->cd_faceset_offset);
BM_ELEM_CD_SET_INT(f, ss->cd_faceset_offset, fset);
}
else {
ret = ss->face_sets[face.i];
ss->face_sets[face.i] = fset;
BM_ELEM_CD_SET_INT(f, ss->cd_faceset_offset, fset);
break;
}
case PBVH_FACES:
case PBVH_GRIDS:
ret = ss->face_sets[face.i];
ss->face_sets[face.i] = fset;
break;
}
return ret;
@ -793,30 +821,58 @@ static void sculpt_face_sets_init_loop(Object *ob, const int mode)
{
Mesh *mesh = ob->data;
SculptSession *ss = ob->sculpt;
BMesh *bm = sculpt_faceset_bm_begin(ss, mesh);
BMIter iter;
BMFace *f;
SCULPT_face_random_access_ensure(ss);
const int cd_fmaps_offset = CustomData_get_offset(&bm->pdata, CD_FACEMAP);
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
SculptFaceRef fref = {(intptr_t)f};
if (mode == SCULPT_FACE_SETS_FROM_MATERIALS) {
SCULPT_face_set_set(ss, fref, (int)(f->mat_nr + 1));
}
else if (mode == SCULPT_FACE_SETS_FROM_FACE_MAPS) {
if (cd_fmaps_offset != -1) {
SCULPT_face_set_set(ss, fref, BM_ELEM_CD_GET_INT(f, cd_fmaps_offset) + 2);
}
else {
SCULPT_face_set_set(ss, fref, 1);
}
}
int cd_fmaps_offset = -1;
if (ss->bm) {
cd_fmaps_offset = CustomData_get_offset(&ss->bm->pdata, CD_FACEMAP);
}
sculpt_faceset_bm_end(ss, bm);
Mesh *me = NULL;
int *fmaps = NULL;
if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
me = ob->data;
fmaps = CustomData_get_layer(&me->pdata, CD_FACEMAP);
}
else if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
fmaps = CustomData_get_layer(ss->pdata, CD_FACEMAP);
}
for (int i = 0; i < ss->totfaces; i++) {
SculptFaceRef fref = BKE_pbvh_table_index_to_face(ss->pbvh, i);
if (mode == SCULPT_FACE_SETS_FROM_MATERIALS) {
SCULPT_face_set_set(ss, fref, (int)(sculpt_face_material_get(ss, fref) + 1));
}
else if (mode == SCULPT_FACE_SETS_FROM_FACE_MAPS) {
int fmap = 1;
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_BMESH: {
BMFace *f = (BMFace *)fref.i;
if (cd_fmaps_offset >= 0) {
fmap = BM_ELEM_CD_GET_INT(f, cd_fmaps_offset) + 2;
}
break;
}
case PBVH_FACES:
case PBVH_GRIDS: {
int f_i = fref.i;
if (fmaps) {
fmap = fmaps[i] + 2;
}
break;
}
}
SCULPT_face_set_set(ss, fref, fmap);
}
}
}
static int sculpt_face_set_init_exec(bContext *C, wmOperator *op)
@ -1095,8 +1151,8 @@ static int sculpt_face_sets_change_visibility_invoke(bContext *C,
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
/* Update the active vertex and Face Set using the cursor position to avoid relying on the paint
* cursor updates. */
/* Update the active vertex and Face Set using the cursor position to avoid relying on the
* paint cursor updates. */
SculptCursorGeometryInfo sgi;
float mouse[2];
mouse[0] = event->mval[0];
@ -1578,8 +1634,8 @@ static bool sculpt_face_set_edit_is_operation_valid(SculptSession *ss,
if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
/* Modification of base mesh geometry requires special remapping of multires displacement,
* which does not happen here.
* Disable delete operation. It can be supported in the future by doing similar displacement
* data remapping as what happens in the mesh edit mode. */
* Disable delete operation. It can be supported in the future by doing similar
* displacement data remapping as what happens in the mesh edit mode. */
return false;
}
if (check_single_face_set(ss, !modify_hidden)) {