New branch to fix multires topology editing. WIP

Changes:
* Brought back bmesh_mdisps_space_set, written from scratch using
  subdiv api, not ccg.
* Wrote a function to smooth multigres grids from within bmesh.  I might
  not need it; unless anyone thinks of a use for it I'll go ahead and
  delete it.

Todo:
* Purge code of all usages of CCG for multires.

This commit:
* Wrote a utility function to dump multires displacements into a (new)
  scene object.
* Consequently, I now know that the CCG_based multires code is not
  compatible with the OpenSubdiv based code.  The former produces gaps
  between grids when converting displacements to object space.
This commit is contained in:
Joseph Eagar 2020-10-17 15:11:02 -07:00
parent 4659855b0f
commit 64c7bad391
16 changed files with 399 additions and 145 deletions

@ -1 +1 @@
Subproject commit 8ad9de7c1e1022dee907ddce78f4c357111fc09e
Subproject commit a1f229202345c5e705f3035e2ff418bc3a9fe669

@ -1 +1 @@
Subproject commit 26a8b2eadc7abb2a30fac50eb5505aa24daf5785
Subproject commit eae381b698248e70e4a3c62bdf239f9d5a0470a9

View File

@ -41,6 +41,7 @@ struct MultiresModifierData;
struct Object;
struct Scene;
struct SubdivCCG;
struct BMesh;
struct MLoop;
struct MLoopTri;
@ -229,6 +230,8 @@ BLI_INLINE void BKE_multires_construct_tangent_matrix(float tangent_matrix[3][3]
const float dPdv[3],
const int corner);
void BKE_multires_bmesh_space_set(struct Object *ob, struct BMesh *bm, int mode);
#ifdef __cplusplus
}
#endif

View File

@ -59,7 +59,6 @@ Mesh *BKE_mesh_mirror_bisect_on_mirror_plane(MirrorModifierData *mmd,
BMVert *v, *v_next;
bm = BKE_mesh_to_bmesh_ex(mesh,
NULL,
&(struct BMeshCreateParams){0},
&(struct BMeshFromMeshParams){
.calc_face_normal = true,

View File

@ -33,26 +33,32 @@
#include "BLI_bitmap.h"
#include "BLI_blenlib.h"
#include "BLI_edgehash.h"
#include "BLI_math.h"
#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "BKE_ccg.h"
#include "BKE_collection.h"
#include "BKE_layer.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_context.h"
#include "BKE_editmesh.h"
#include "BKE_mesh.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
#include "BKE_multires.h"
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
#include "BKE_scene.h"
#include "BKE_subdiv.h"
#include "BKE_subdiv_ccg.h"
#include "BKE_subdiv_eval.h"
#include "BKE_subsurf.h"
#include "BKE_subdiv.h"
#include "BKE_object.h"
@ -60,9 +66,9 @@
#include "DEG_depsgraph_query.h"
#include "multires_reshape.h"
#include "multires_inline.h"
#include "bmesh.h"
#include "multires_inline.h"
#include "multires_reshape.h"
#include <math.h>
#include <string.h>
@ -962,20 +968,36 @@ void multiresModifier_subdivide_legacy(
static void grid_tangent(const CCGKey *key, int x, int y, int axis, CCGElem *grid, float t[3])
{
if (axis == 0) {
if (x == 0) {
sub_v3_v3v3(t, CCG_grid_elem_co(key, grid, x+1, y), CCG_grid_elem_co(key, grid, x, y));
} else {
sub_v3_v3v3(t, CCG_grid_elem_co(key, grid, x, y), CCG_grid_elem_co(key, grid, x-1, y));
if (x == key->grid_size - 1) {
if (y == key->grid_size - 1) {
sub_v3_v3v3(
t, CCG_grid_elem_co(key, grid, x, y - 1), CCG_grid_elem_co(key, grid, x - 1, y - 1));
}
else {
sub_v3_v3v3(t, CCG_grid_elem_co(key, grid, x, y), CCG_grid_elem_co(key, grid, x - 1, y));
}
}
} else if (axis == 1) {
if (y == 0) {
sub_v3_v3v3(t, CCG_grid_elem_co(key, grid, x, y+1), CCG_grid_elem_co(key, grid, x, y));
} else {
sub_v3_v3v3(t, CCG_grid_elem_co(key, grid, x, y), CCG_grid_elem_co(key, grid, x, y-1));
else {
sub_v3_v3v3(t, CCG_grid_elem_co(key, grid, x + 1, y), CCG_grid_elem_co(key, grid, x, y));
}
}
else if (axis == 1) {
if (y == key->grid_size - 1) {
if (x == key->grid_size - 1) {
sub_v3_v3v3(
t, CCG_grid_elem_co(key, grid, x - 1, y), CCG_grid_elem_co(key, grid, x - 1, (y - 1)));
}
else {
sub_v3_v3v3(t, CCG_grid_elem_co(key, grid, x, y), CCG_grid_elem_co(key, grid, x, (y - 1)));
}
}
else {
sub_v3_v3v3(t, CCG_grid_elem_co(key, grid, x, (y + 1)), CCG_grid_elem_co(key, grid, x, y));
}
}
}
/* Construct 3x3 tangent-space matrix in 'mat' */
static void grid_tangent_matrix(float mat[3][3], const CCGKey *key, int x, int y, CCGElem *grid)
{
@ -1006,9 +1028,206 @@ typedef struct MultiresThreadedData {
float (*smat)[3];
} MultiresThreadedData;
Object *multires_dump_grids_bmesh(BMesh *bm)
{
if (!CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
printf("multires_dump_grids_bmesh: error: no multires grids\n");
return;
}
bool spaceset = false;
if (bm->multiresSpace != MULTIRES_SPACE_ABSOLUTE) {
BKE_multires_bmesh_space_set(NULL, bm, MULTIRES_SPACE_ABSOLUTE);
spaceset = true;
}
Main *bmain = G.main;
char *name = "multires_dump";
bContext *ctx = CTX_create();
CTX_data_main_set(ctx, bmain);
CTX_wm_manager_set(ctx, G.main->wm.first);
CTX_data_scene_set(ctx, G.main->scenes.first);
Scene *scene = CTX_data_scene(ctx);
ViewLayer *view_layer = CTX_data_view_layer(ctx);
Object *ob = BKE_object_add_only_object(bmain, OB_MESH, name);
Base *base;
LayerCollection *layer_collection;
ob->data = BKE_object_obdata_add_from_type(bmain, OB_MESH, name);
DEG_id_tag_update_ex(
bmain, &ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
//DEG_id_tag_update_ex(
// bmain, &ob->data, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
layer_collection = BKE_layer_collection_get_active(view_layer);
BKE_collection_object_add(bmain, layer_collection->collection, ob);
DEG_id_type_tag(bmain, ID_OB);
DEG_relations_tag_update(bmain);
if (ob->data != NULL) {
DEG_id_tag_update_ex(bmain, (ID *)ob->data, ID_RECALC_EDITORS);
}
ob->modifiers.first = ob->modifiers.last = NULL;
zero_v3(ob->loc);
printf("users: %d\n", ob->id.us);
Mesh *me = ob->data;
BMIter iter;
BMVert *v;
BMEdge *e;
BMFace *f;
int cd_mdisp_off = CustomData_get_offset(&bm->ldata, CD_MDISPS);
int dimen = 0;
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
BMLoop *l = f->l_first;
MDisps *md = BM_ELEM_CD_GET_VOID_P(l, cd_mdisp_off);
dimen = (int)floor(sqrt(md->totdisp) + 0.00001);
break;
}
if (!dimen) {
printf("multires_dump_grids_bmesh: error: corrupted multires data\n");
return;
}
int totvert = bm->totloop * dimen * dimen;
int totface = bm->totloop * (dimen - 1) * (dimen - 1);
int totloop = totface * 4;
CustomData_free(&me->vdata, me->totvert);
CustomData_free(&me->edata, me->totedge);
CustomData_free(&me->fdata, me->totface);
CustomData_free(&me->ldata, me->totloop);
CustomData_free(&me->pdata, me->totpoly);
me->totvert = totvert;
me->totpoly = totface;
me->totloop = totloop;
me->totedge = totvert + totface;
me->totface = 0;
me->act_face = -1;
EdgeHash *eh = BLI_edgehash_new_ex("multires_dump_bmesh", me->totedge);
MVert *mvert = me->totvert ?
MEM_callocN(sizeof(MVert) * me->totvert, "multires_dump_grids_bmesh.vert") :
NULL;
MEdge *medge = me->totedge ?
MEM_callocN(sizeof(MEdge) * me->totedge, "multires_dump_grids_bmesh.edge") :
NULL;
MLoop *mloop = me->totloop ?
MEM_callocN(sizeof(MLoop) * me->totloop, "multires_dump_grids_bmesh.loop") :
NULL;
MPoly *mpoly = me->totpoly ?
MEM_callocN(sizeof(MPoly) * me->totpoly, "multires_dump_grids_bmesh.poly") :
NULL;
me->cd_flag = 0;
CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, mvert, me->totvert);
CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, me->totedge);
CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, mloop, me->totloop);
CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, mpoly, me->totpoly);
BKE_mesh_update_customdata_pointers(me, 0);
int loopi = 0;
int outli = 0;
int medi = 0;
#define VINDEX(i, j) (loopi * dimen * dimen + ((j)*dimen + (i)))
// CustomData_daata_
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
BMLoop *l = f->l_first;
do {
MDisps *md = BM_ELEM_CD_GET_VOID_P(l, cd_mdisp_off);
for (int i = 0; i < dimen; i++) {
for (int j = 0; j < dimen; j++) {
int vidx = loopi * dimen * dimen + (j * dimen + i);
int idx = j * dimen + i;
float *co = md->disps[idx];
MVert *mv = mvert + vidx;
copy_v3_v3(mv->co, co);
}
}
for (int i = 0; i < dimen-1; i++) {
for (int j = 0; j < dimen-1; j++) {
// do face
int fidx = loopi * (dimen - 1) * (dimen - 1) + (j * (dimen - 1) + i);
MPoly *mp = mpoly + fidx;
mp->totloop = 4;
mp->loopstart = outli;
MLoop *ml = mloop + outli;
ml[0].v = VINDEX(i, j);
ml[1].v = VINDEX(i, j + 1);
ml[2].v = VINDEX(i + 1, j + 1);
ml[3].v = VINDEX(i + 1, j);
for (int i2=0; i2<4; i2++) {
int a = ml[i2].v, b = ml[(i2+1) % 4].v;
int e;
if (!BLI_edgehash_haskey(eh, a, b)) {
BLI_edgehash_insert(eh, a, b, (void*)medi);
e = medi;
MEdge *med = medge + medi;
med->v1 = a;
med->v2 = b;
medi++;
} else {
e = (int)BLI_edgehash_lookup(eh, a, b);
}
ml[i2].e = e;
}
outli += 4;
}
}
loopi++;
l = l->next;
} while (l != f->l_first);
}
for (int i=0; i<me->totpoly; i++) {
if (!mpoly[i].totloop) {
printf("error 1! %d %d\n", i, me->totpoly);
}
if (mpoly[i].loopstart >= me->totloop) {
printf("error 2! %d %d l: %d totl: %d\n", i, me->totpoly, mpoly[i].loopstart, mpoly[i].totloop);
}
}
if (spaceset) {
BKE_multires_bmesh_space_set(NULL, bm, MULTIRES_SPACE_TANGENT);
}
BKE_mesh_calc_normals(me);
BKE_mesh_tessface_calc(me);
}
static void multires_bmesh_space_set_cb(void *__restrict userdata,
const int pidx,
const TaskParallelTLS *__restrict UNUSED(tls))
const int pidx,
const TaskParallelTLS *__restrict UNUSED(tls))
{
MultiresThreadedData *tdata = userdata;
@ -1047,10 +1266,10 @@ static void multires_bmesh_space_set_cb(void *__restrict userdata,
l = f->l_first;
S = 0;
do {
//for (S = 0; S < numVerts; S++, gIndex++) {
// for (S = 0; S < numVerts; S++, gIndex++) {
GridPaintMask *gpm = grid_paint_mask ? &grid_paint_mask[gIndex] : NULL;
MDisps *mdisp = BM_ELEM_CD_GET_VOID_P(l, cd_mdisps_off); //&mdisps[mpoly[pidx].loopstart + S];
MDisps *mdisp = BM_ELEM_CD_GET_VOID_P(l, cd_mdisps_off); //&mdisps[mpoly[pidx].loopstart + S];
CCGElem *grid = gridData[gIndex];
CCGElem *subgrid = subGridData[gIndex];
float(*dispgrid)[3] = NULL;
@ -1059,86 +1278,62 @@ static void multires_bmesh_space_set_cb(void *__restrict userdata,
float quad[4][3];
//copy_v3_v3(quad[0], cent);
//interp_v3_v3v3(quad[1], l->v->co, l->next->v->co, 0.5);
//copy_v3_v3(quad[2], l->v->co);
//interp_v3_v3v3(quad[3], l->v->co, l->prev->v->co, 0.5);
float maxlen = len_v3v3(l->v->co, cent)*15.0f;
// copy_v3_v3(quad[0], cent);
// interp_v3_v3v3(quad[1], l->v->co, l->next->v->co, 0.5);
// copy_v3_v3(quad[2], l->v->co);
// interp_v3_v3v3(quad[3], l->v->co, l->prev->v->co, 0.5);
float maxlen = len_v3v3(l->v->co, cent) * 15.0f;
maxlen = MAX2(maxlen, 0.00001f);
for (y = 0; y < gridSize; y++) {
for (x = 0; x < gridSize; x++) {
//float *sco = CCG_grid_elem_co(key, grid, x, y);
//float *sco = CCG_grid_elem_co(key, subgrid, x, y);
// float *sco = CCG_grid_elem_co(key, grid, x, y);
// float *sco = CCG_grid_elem_co(key, subgrid, x, y);
float sco[8], udv[3], vdv[3];
float *data = dispgrid[dGridSize * y * dSkip + x * dSkip];
float mat[3][3], disp[3], d[3], mask;
//float baseco[3];
// float baseco[3];
float grid_u = (float)x / (float)(dGridSize-1);
float grid_v = (float)y / (float)(dGridSize-1);
float grid_u = (float)x / (float)(dGridSize - 1);
float grid_v = (float)y / (float)(dGridSize - 1);
float u, v;
int corner = l->head.index - f->head.index;
int corner = S;
if (f->len == 4) {
BKE_subdiv_rotate_grid_to_quad(corner, grid_u, grid_v, &u, &v);
//continue;
} else {
// continue;
}
else {
u = 1.0 - grid_v;
v = 1.0 - grid_u;
}
BKE_subdiv_eval_limit_point_and_derivatives(tdata->sd, l->head.index, u, v, sco, udv, vdv);
//float tan[3];
//grid_tangent(key, x, y, 1, grid, tan);
//negate_v3(udv);
//normalize_v3(tan);
//normalize_v3(vdv);
//printf("%.4f\n", len_v3v3(tan, vdv));
//printf(" %.3f %.3f %.3f\n", tan[0], tan[1], tan[2]);
//printf(" %.3f %.3f %.3f\n", vdv[0], vdv[1], vdv[2]);
//negate_v3(udv);
//negate_v3(vdv);
BKE_multires_construct_tangent_matrix(mat, udv, vdv, corner);
//BKE_subdiv_eval_limit_point_and_derivatives(subdiv, ptex_face_index, u, v, dummy_P, dPdu, dPdv);
//interp_bilinear_quad_v3(quad, (float)x/(float)gridSize, (float)y/(float)gridSize, baseco);
/* construct tangent space matrix */
//grid_tangent_matrix(mat, key, x, y, grid);
//copy_v3_v3(sco, CCG_grid_elem_co(key, grid, x, y));
//sub_v3_v3(sco, CCG_grid_elem_co(key, grid, x, y));
//oprintf("%.3f %.3f %.3f\n", sco[0], sco[1], sco[2]);
//copy_v3_v3(sco, CCG_grid_elem_co(key, grid, x, y));
BKE_multires_construct_tangent_matrix(mat, udv, vdv, f->len == 4 ? corner : 0);
copy_v3_v3(disp, data);
switch (op) {
case MULTIRES_SPACE_ABSOLUTE:
/* Convert displacement to object space
* and add to grid points */
mul_v3_m3v3(disp, mat, data);
add_v3_v3v3(data, disp, sco);
break;
case MULTIRES_SPACE_TANGENT:
/* Calculate displacement between new and old
* grid points and convert to tangent space */
invert_m3(mat);
case MULTIRES_SPACE_ABSOLUTE:
/* Convert displacement to object space
* and add to grid points */
mul_v3_m3v3(disp, mat, data);
add_v3_v3v3(data, disp, sco);
//copy_v3_v3(data, sco);
break;
case MULTIRES_SPACE_TANGENT:
/* Calculate displacement between new and old
* grid points and convert to tangent space */
invert_m3(mat);
sub_v3_v3v3(disp, data, sco);
mul_v3_m3v3(data, mat, disp);
sub_v3_v3v3(disp, data, sco);
mul_v3_m3v3(data, mat, disp);
//float len = len_v3(data);
//if (len > maxlen) {
// mul_v3_fl(data, maxlen/len);
//}
break;
// float len = len_v3(data);
// if (len > maxlen) {
// mul_v3_fl(data, maxlen/len);
//}
break;
}
}
}
@ -1150,8 +1345,8 @@ static void multires_bmesh_space_set_cb(void *__restrict userdata,
}
/* XXX WARNING: subsurf elements from dm and oldGridData *must* be of the same format (size),
* because this code uses CCGKey's info from dm to access oldGridData's normals
* (through the call to grid_tangent_matrix())! */
* because this code uses CCGKey's info from dm to access oldGridData's normals
* (through the call to grid_tangent_matrix())! */
void BKE_multires_bmesh_space_set(Object *ob, BMesh *bm, int mode)
{
if (!bm->totface || !CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
@ -1168,7 +1363,6 @@ void BKE_multires_bmesh_space_set(Object *ob, BMesh *bm, int mode)
return;
}
Mesh _me, *me = &_me;
memset(me, 0, sizeof(Mesh));
CustomData_reset(&me->vdata);
@ -1180,17 +1374,18 @@ void BKE_multires_bmesh_space_set(Object *ob, BMesh *bm, int mode)
CustomData_MeshMasks extra = CD_MASK_DERIVEDMESH;
extra.lmask |= CD_MASK_MDISPS;
//CustomData_MeshMasks extra = {0};
// CustomData_MeshMasks extra = {0};
BM_mesh_bm_to_me_for_eval(bm, me, &extra);
DerivedMesh *cddm = CDDM_from_mesh(me);
//cddm->dm.
// cddm->dm.
SubdivSettings settings2;
//cddm ignores MDISPS layer. this turns out to be a good thing.
//CustomData_reset(&cddm->loopData);
//CustomData_merge(&me->ldata, &cddm->loopData, CD_MASK_MESH.lmask & ~CD_MASK_MDISPS, CD_REFERENCE, me->totloop);
// cddm ignores MDISPS layer. this turns out to be a good thing.
// CustomData_reset(&cddm->loopData);
// CustomData_merge(&me->ldata, &cddm->loopData, CD_MASK_MESH.lmask & ~CD_MASK_MDISPS,
// CD_REFERENCE, me->totloop);
//ensure we control the level
// ensure we control the level
MultiresModifierData mmdcpy = *mmd;
mmdcpy.lvl = mmdcpy.sculptlvl = mmdcpy.renderlvl = mmdcpy.totlvl;
@ -1202,24 +1397,27 @@ void BKE_multires_bmesh_space_set(Object *ob, BMesh *bm, int mode)
if (ob) {
fakeob = *ob;
fakeob.sculpt = NULL;
} else {
}
else {
memset(&fakeob, 0, sizeof(fakeob));
fakeob.data = me;
BLI_addtail(&fakeob.modifiers, &mmdcpy);
}
//MULTIRES_USE_LOCAL_MMD
//CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) multires_make_derived_from_derived(cddm, &mmdcpy, NULL, &fakeob, MULTIRES_IGNORE_SIMPLIFY|MULTIRES_USE_LOCAL_MMD);
CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) subsurf_dm_create_local(NULL,
&fakeob,
cddm,
mmd->totlvl,
mmd->simple,
0,
mmd->uv_smooth == SUBSURF_UV_SMOOTH_NONE,
false,
false,
SUBSURF_IGNORE_SIMPLIFY);
// MULTIRES_USE_LOCAL_MMD
// CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) multires_make_derived_from_derived(cddm, &mmdcpy,
// NULL, &fakeob, MULTIRES_IGNORE_SIMPLIFY|MULTIRES_USE_LOCAL_MMD);
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)subsurf_dm_create_local(NULL,
&fakeob,
cddm,
mmd->totlvl,
mmd->simple,
0,
mmd->uv_smooth ==
SUBSURF_UV_SMOOTH_NONE,
false,
false,
0);
CCGElem **gridData, **subGridData;
CCGKey key;
@ -1228,12 +1426,12 @@ void BKE_multires_bmesh_space_set(Object *ob, BMesh *bm, int mode)
int i, gridSize, dGridSize, dSkip;
int totpoly = bm->totface;
//paranoia recalc of indices/tables
bm->elem_index_dirty |= BM_FACE|BM_VERT;
bm->elem_table_dirty |= BM_FACE|BM_VERT;
// paranoia recalc of indices/tables
bm->elem_index_dirty |= BM_FACE | BM_VERT;
bm->elem_table_dirty |= BM_FACE | BM_VERT;
BM_mesh_elem_index_ensure(bm, BM_FACE|BM_VERT);
BM_mesh_elem_table_ensure(bm, BM_FACE|BM_VERT);
BM_mesh_elem_index_ensure(bm, BM_FACE | BM_VERT);
BM_mesh_elem_table_ensure(bm, BM_FACE | BM_VERT);
/*numGrids = dm->getNumGrids(dm);*/ /*UNUSED*/
gridSize = ccgdm->dm.getGridSize(&ccgdm->dm);
@ -1257,22 +1455,22 @@ void BKE_multires_bmesh_space_set(Object *ob, BMesh *bm, int mode)
BMIter iter;
i = 0;
int i2 = 0;
BM_ITER_MESH(f, &iter, bm, BM_FACES_OF_MESH) {
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
BMIter iter2;
BMLoop *l;
f->head.index = i;
BM_ITER_ELEM(l, &iter2, f, BM_LOOPS_OF_FACE) {
BM_ITER_ELEM (l, &iter2, f, BM_LOOPS_OF_FACE) {
MDisps *mdisp = BM_ELEM_CD_GET_VOID_P(l, cd_disp_off);
if (!mdisp->disps) {
multires_reallocate_mdisps(1, mdisp, mmd->totlvl);
}
l->head.index = i;
if (f->len != 4) {
l->head.index = i++;
} else {
l->head.index = i;
i++;
}
}
@ -1286,27 +1484,27 @@ void BKE_multires_bmesh_space_set(Object *ob, BMesh *bm, int mode)
settings.min_iter_per_thread = CCG_TASK_LIMIT;
MultiresThreadedData data = {
.bmop = mode,
.sd = sd,
.gridData = gridData,
.subGridData = subGridData,
.key = &key,
.lvl = mmd->totlvl,
.bm = bm,
.cd_mdisps_off = cd_disp_off,
.grid_paint_mask = grid_paint_mask,
.gridOffset = gridOffset,
.gridSize = gridSize,
.dGridSize = dGridSize,
.dSkip = dSkip,
.bmop = mode,
.sd = sd,
.gridData = gridData,
.subGridData = subGridData,
.key = &key,
.lvl = mmd->totlvl,
.bm = bm,
.cd_mdisps_off = cd_disp_off,
.grid_paint_mask = grid_paint_mask,
.gridOffset = gridOffset,
.gridSize = gridSize,
.dGridSize = dGridSize,
.dSkip = dSkip,
};
BLI_task_parallel_range(0, totpoly, &data, multires_bmesh_space_set_cb, &settings);
//MDisps = CustomData_get
//if (mode == MULTIRES_SPACE_TANGENT) {
//ccgSubSurf_stitchFaces(ccgdm->ss, 0, NULL, 0);
//ccgSubSurf_updateNormals(ccgdm->ss, NULL, 0);
// MDisps = CustomData_get
// if (mode == MULTIRES_SPACE_TANGENT) {
// ccgSubSurf_stitchFaces(ccgdm->ss, 0, NULL, 0);
// ccgSubSurf_updateNormals(ccgdm->ss, NULL, 0);
//}
ccgdm->dm.release(&ccgdm->dm);
@ -1354,7 +1552,7 @@ static void multires_disp_run_cb(void *__restrict userdata,
}
gpm->data = MEM_calloc_arrayN(key->grid_area, sizeof(float), "gpm.data");
}
for (y = 0; y < gridSize; y++) {
for (x = 0; x < gridSize; x++) {
float *co = CCG_grid_elem_co(key, grid, x, y);
@ -1491,8 +1689,8 @@ static void multiresModifier_disp_run(
BLI_task_parallel_range(0, totpoly, &data, multires_disp_run_cb, &settings);
if (op == APPLY_DISPLACEMENTS) {
//ccgSubSurf_stitchFaces(ccgdm->ss, 0, NULL, 0);
//ccgSubSurf_updateNormals(ccgdm->ss, NULL, 0);
// ccgSubSurf_stitchFaces(ccgdm->ss, 0, NULL, 0);
// ccgSubSurf_updateNormals(ccgdm->ss, NULL, 0);
}
}
@ -1657,7 +1855,7 @@ void multires_modifier_update_hidden(DerivedMesh *dm)
void multires_stitch_grids(Object *ob)
{
return; //XXX
return; // XXX
if (ob == NULL) {
return;
}
@ -1678,7 +1876,7 @@ void multires_stitch_grids(Object *ob)
int num_faces;
BKE_pbvh_get_grid_updates(pbvh, false, (void ***)&faces, &num_faces);
if (num_faces) {
//XXX BKE_subdiv_ccg_average_stitch_faces(subdiv_ccg, faces, num_faces);
// XXX BKE_subdiv_ccg_average_stitch_faces(subdiv_ccg, faces, num_faces);
MEM_freeN(faces);
}
}

View File

@ -5735,6 +5735,61 @@ static int edbm_mres_test_exec(bContext *C, wmOperator *op)
}
extern Object *multires_dump_grids_bmesh(BMesh *bm);
static int edbm_dump_mres_grids_exec(bContext *C, wmOperator *op)
{
const bool use_face_split = RNA_boolean_get(op->ptr, "use_face_split");
const bool use_boundary_tear = RNA_boolean_get(op->ptr, "use_boundary_tear");
ViewLayer *view_layer = CTX_data_view_layer(C);
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
view_layer, CTX_wm_view3d(C), &objects_len);
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
BMEditMesh *em = BKE_editmesh_from_object(obedit);
multires_dump_grids_bmesh(em->bm);
}
WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, CTX_data_scene(C));
MEM_freeN(objects);
return OPERATOR_FINISHED;
}
static bool mres_test_poll(bContext *C)
{
Object *obedit = CTX_data_edit_object(C);
if (obedit && obedit->type == OB_MESH) {
BMEditMesh *em = BKE_editmesh_from_object(obedit);
if (!em || !CustomData_has_layer(&em->bm->ldata, CD_MDISPS)) {
return false;
}
return true;
}
return false;
}
void MESH_OT_dump_mres_grids(wmOperatorType *ot) {
/* identifiers */
ot->name = "Dump Multires Grids";
ot->description = "Dump Multires Grids";
ot->idname = "MESH_OT_dump_mres_grids";
/* api callbacks */
ot->exec = edbm_dump_mres_grids_exec;
ot->poll = mres_test_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void MESH_OT_mres_test(wmOperatorType *ot)
{
/* identifiers */
@ -5744,13 +5799,10 @@ void MESH_OT_mres_test(wmOperatorType *ot)
/* api callbacks */
ot->exec = edbm_mres_test_exec;
ot->poll = ED_operator_editmesh;
ot->poll = mres_test_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
edbm_dissolve_prop__use_face_split(ot);
edbm_dissolve_prop__use_boundary_tear(ot);
}

View File

@ -286,3 +286,4 @@ void MESH_OT_customdata_skin_add(struct wmOperatorType *ot);
void MESH_OT_customdata_skin_clear(struct wmOperatorType *ot);
void MESH_OT_customdata_custom_splitnormals_add(struct wmOperatorType *ot);
void MESH_OT_customdata_custom_splitnormals_clear(struct wmOperatorType *ot);
void MESH_OT_dump_mres_grids(struct wmOperatorType *ot);

View File

@ -209,6 +209,7 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_smooth_normals);
WM_operatortype_append(MESH_OT_mod_weighted_strength);
WM_operatortype_append(MESH_OT_mres_test);
WM_operatortype_append(MESH_OT_dump_mres_grids);
}

View File

@ -2851,7 +2851,7 @@ void ED_uvedit_add_simple_uvs(Main *bmain, const Scene *scene, Object *ob)
/* set the margin really quickly before the packing operation*/
scene->toolsettings->uvcalc_margin = 0.001f;
uvedit_pack_islands(scene, ob, bm);
BM_mesh_bm_to_me(bmain, bm, me, (&(struct BMeshToMeshParams){0}));
BM_mesh_bm_to_me(bmain, NULL, bm, me, (&(struct BMeshToMeshParams){0}));
BM_mesh_free(bm);
if (sync_selection) {

View File

@ -454,7 +454,7 @@ void bc_triangulate_mesh(Mesh *me)
BMeshToMeshParams bm_to_me_params = {0};
bm_to_me_params.calc_object_remap = false;
BM_mesh_bm_to_me(NULL, bm, me, &bm_to_me_params);
BM_mesh_bm_to_me(NULL, NULL, bm, me, &bm_to_me_params);
BM_mesh_free(bm);
}

View File

@ -122,7 +122,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
const float spread = bmd->spread;
const bool invert_vgroup = (bmd->flags & MOD_BEVEL_INVERT_VGROUP) != 0;
bm = BKE_mesh_to_bmesh_ex(mesh, NULL,
bm = BKE_mesh_to_bmesh_ex(mesh,
&(struct BMeshCreateParams){0},
&(struct BMeshFromMeshParams){
.calc_face_normal = true,

View File

@ -171,7 +171,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
}
}
bm = BKE_mesh_to_bmesh_ex(mesh, NULL,
bm = BKE_mesh_to_bmesh_ex(mesh,
&(struct BMeshCreateParams){0},
&(struct BMeshFromMeshParams){
.calc_face_normal = calc_face_normal,

View File

@ -65,7 +65,7 @@ static Mesh *doEdgeSplit(Mesh *mesh, EdgeSplitModifierData *emd)
const bool do_split_all = do_split_angle && emd->split_angle < FLT_EPSILON;
const bool calc_face_normals = do_split_angle && !do_split_all;
bm = BKE_mesh_to_bmesh_ex(mesh, NULL,
bm = BKE_mesh_to_bmesh_ex(mesh,
&(struct BMeshCreateParams){0},
&(struct BMeshFromMeshParams){
.calc_face_normal = calc_face_normals,

View File

@ -70,7 +70,7 @@ static Mesh *triangulate_mesh(Mesh *mesh,
cd_mask_extra.lmask |= CD_MASK_NORMAL;
}
bm = BKE_mesh_to_bmesh_ex(mesh, NULL,
bm = BKE_mesh_to_bmesh_ex(mesh,
&((struct BMeshCreateParams){0}),
&((struct BMeshFromMeshParams){
.calc_face_normal = true,

View File

@ -78,7 +78,7 @@ static Mesh *WireframeModifier_do(WireframeModifierData *wmd, Object *ob, Mesh *
const int defgrp_index = BKE_object_defgroup_name_index(ob, wmd->defgrp_name);
bm = BKE_mesh_to_bmesh_ex(mesh, NULL,
bm = BKE_mesh_to_bmesh_ex(mesh,
&(struct BMeshCreateParams){0},
&(struct BMeshFromMeshParams){
.calc_face_normal = true,

View File

@ -1056,7 +1056,7 @@ static PyObject *bpy_bmesh_to_mesh(BPy_BMesh *self, PyObject *args)
params.calc_object_remap = true;
}
BM_mesh_bm_to_me(bmain, bm, me, &params);
BM_mesh_bm_to_me(bmain, NULL, bm, me, &params);
/* we could have the user do this but if they forget blender can easy crash
* since the references arrays for the objects derived meshes are now invalid */