commit multires patch

This commit is contained in:
Joseph Eagar 2020-10-17 01:24:34 -07:00
parent 7447eb7e74
commit 4659855b0f
38 changed files with 917 additions and 111 deletions

View File

@ -1016,6 +1016,7 @@ Mesh *BKE_mesh_copy_for_eval(struct Mesh *source, bool reference)
}
BMesh *BKE_mesh_to_bmesh_ex(const Mesh *me,
const Object *ob,
const struct BMeshCreateParams *create_params,
const struct BMeshFromMeshParams *convert_params)
{
@ -1023,7 +1024,7 @@ BMesh *BKE_mesh_to_bmesh_ex(const Mesh *me,
const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(me);
bm = BM_mesh_create(&allocsize, create_params);
BM_mesh_bm_from_me(bm, me, convert_params);
BM_mesh_bm_from_me(ob, bm, me, convert_params);
return bm;
}
@ -1034,6 +1035,7 @@ BMesh *BKE_mesh_to_bmesh(Mesh *me,
const struct BMeshCreateParams *params)
{
return BKE_mesh_to_bmesh_ex(me,
ob,
params,
&(struct BMeshFromMeshParams){
.calc_face_normal = false,
@ -1049,7 +1051,7 @@ Mesh *BKE_mesh_from_bmesh_nomain(BMesh *bm,
{
BLI_assert(params->calc_object_remap == false);
Mesh *mesh = BKE_id_new_nomain(ID_ME, NULL);
BM_mesh_bm_to_me(NULL, bm, mesh, params);
BM_mesh_bm_to_me(NULL, NULL, bm, mesh, params);
BKE_mesh_copy_settings(mesh, me_settings);
return mesh;
}

View File

@ -59,6 +59,7 @@ 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

@ -443,7 +443,7 @@ struct Mesh *BKE_mesh_remesh_voxel_fix_poles(struct Mesh *mesh)
.use_toolflags = true,
}));
BM_mesh_bm_from_me(bm,
BM_mesh_bm_from_me(NULL, bm,
mesh,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,

View File

@ -41,6 +41,7 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_editmesh.h"
#include "BKE_mesh.h"
#include "BKE_global.h"
#include "BKE_mesh_mapping.h"
#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
@ -49,7 +50,9 @@
#include "BKE_pbvh.h"
#include "BKE_scene.h"
#include "BKE_subdiv_ccg.h"
#include "BKE_subdiv_eval.h"
#include "BKE_subsurf.h"
#include "BKE_subdiv.h"
#include "BKE_object.h"
@ -58,6 +61,8 @@
#include "DEG_depsgraph_query.h"
#include "multires_reshape.h"
#include "multires_inline.h"
#include "bmesh.h"
#include <math.h>
#include <string.h>
@ -957,31 +962,16 @@ 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 == 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));
}
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));
}
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));
} 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));
}
}
}
@ -1000,21 +990,336 @@ static void grid_tangent_matrix(float mat[3][3], const CCGKey *key, int x, int y
typedef struct MultiresThreadedData {
DispOp op;
MultiResSpace bmop;
BMesh *bm;
int lvl;
CCGElem **gridData, **subGridData;
CCGKey *key;
CCGKey *sub_key;
Subdiv *sd;
MPoly *mpoly;
MDisps *mdisps;
GridPaintMask *grid_paint_mask;
int *gridOffset;
int cd_mdisps_off;
int gridSize, dGridSize, dSkip;
float (*smat)[3];
} MultiresThreadedData;
static void multires_bmesh_space_set_cb(void *__restrict userdata,
const int pidx,
const TaskParallelTLS *__restrict UNUSED(tls))
{
MultiresThreadedData *tdata = userdata;
int cd_mdisps_off = tdata->cd_mdisps_off;
BMesh *bm = tdata->bm;
MultiResSpace op = tdata->bmop;
CCGElem **gridData = tdata->gridData;
CCGElem **subGridData = tdata->subGridData;
CCGKey *key = tdata->key;
BMFace *f = bm->ftable[pidx];
MDisps *mdisps = tdata->mdisps;
GridPaintMask *grid_paint_mask = tdata->grid_paint_mask;
int *gridOffset = tdata->gridOffset;
int gridSize = tdata->gridSize;
int dGridSize = tdata->dGridSize;
int dSkip = tdata->dSkip;
int S, x, y, gIndex = gridOffset[pidx];
BMLoop *l = f->l_first;
float cent[3];
int tot = 0;
zero_v3(cent);
do {
add_v3_v3(cent, l->v->co);
tot++;
l = l->next;
} while (l != f->l_first);
mul_v3_fl(cent, 1.0f / (float)tot);
float simplemat[3][3];
l = f->l_first;
S = 0;
do {
//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];
CCGElem *grid = gridData[gIndex];
CCGElem *subgrid = subGridData[gIndex];
float(*dispgrid)[3] = NULL;
dispgrid = mdisp->disps;
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;
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[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 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;
if (f->len == 4) {
BKE_subdiv_rotate_grid_to_quad(corner, grid_u, grid_v, &u, &v);
//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));
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);
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;
}
}
}
S++;
gIndex++;
l = l->next;
} while (l != f->l_first);
}
/* 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())! */
void BKE_multires_bmesh_space_set(Object *ob, BMesh *bm, int mode)
{
if (!bm->totface || !CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
return;
}
MultiresModifierData *mmd = bm->haveMultiResSettings ? &bm->multires : NULL;
if (!mmd && ob) {
mmd = get_multires_modifier(NULL, ob, true);
}
if (!mmd || !CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
return;
}
Mesh _me, *me = &_me;
memset(me, 0, sizeof(Mesh));
CustomData_reset(&me->vdata);
CustomData_reset(&me->edata);
CustomData_reset(&me->ldata);
CustomData_reset(&me->fdata);
CustomData_reset(&me->pdata);
CustomData_MeshMasks extra = CD_MASK_DERIVEDMESH;
extra.lmask |= CD_MASK_MDISPS;
//CustomData_MeshMasks extra = {0};
BM_mesh_bm_to_me_for_eval(bm, me, &extra);
DerivedMesh *cddm = CDDM_from_mesh(me);
//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);
//ensure we control the level
MultiresModifierData mmdcpy = *mmd;
mmdcpy.lvl = mmdcpy.sculptlvl = mmdcpy.renderlvl = mmdcpy.totlvl;
BKE_multires_subdiv_settings_init(&settings2, &mmdcpy);
Subdiv *sd = BKE_subdiv_new_from_mesh(&settings2, me);
BKE_subdiv_eval_begin_from_mesh(sd, me, NULL);
Object fakeob;
if (ob) {
fakeob = *ob;
fakeob.sculpt = NULL;
} 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);
CCGElem **gridData, **subGridData;
CCGKey key;
GridPaintMask *grid_paint_mask = NULL;
int *gridOffset;
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;
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);
gridData = ccgdm->dm.getGridData(&ccgdm->dm);
gridOffset = ccgdm->dm.getGridOffset(&ccgdm->dm);
ccgdm->dm.getGridKey(&ccgdm->dm, &key);
subGridData = gridData;
dGridSize = multires_side_tot[mmd->totlvl];
dSkip = (dGridSize - 1) / (gridSize - 1);
/* multires paint masks */
if (key.has_mask) {
grid_paint_mask = CustomData_get_layer(&me->ldata, CD_GRID_PAINT_MASK);
}
/* when adding new faces in edit mode, need to allocate disps */
int cd_disp_off = CustomData_get_offset(&bm->ldata, CD_MDISPS);
BMFace *f;
BMIter iter;
i = 0;
int i2 = 0;
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) {
MDisps *mdisp = BM_ELEM_CD_GET_VOID_P(l, cd_disp_off);
if (!mdisp->disps) {
multires_reallocate_mdisps(1, mdisp, mmd->totlvl);
}
if (f->len != 4) {
l->head.index = i++;
} else {
l->head.index = i;
}
}
if (f->len == 4) {
i++;
}
}
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
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,
};
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);
//}
ccgdm->dm.release(&ccgdm->dm);
DM_release(cddm);
BKE_mesh_free(me);
BKE_subdiv_free(sd);
}
static void multires_disp_run_cb(void *__restrict userdata,
const int pidx,
const TaskParallelTLS *__restrict UNUSED(tls))
{
return;
MultiresThreadedData *tdata = userdata;
DispOp op = tdata->op;
@ -1049,7 +1354,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);
@ -1186,8 +1491,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);
}
}
@ -1352,6 +1657,7 @@ void multires_modifier_update_hidden(DerivedMesh *dm)
void multires_stitch_grids(Object *ob)
{
return; //XXX
if (ob == NULL) {
return;
}
@ -1372,7 +1678,7 @@ void multires_stitch_grids(Object *ob)
int num_faces;
BKE_pbvh_get_grid_updates(pbvh, false, (void ***)&faces, &num_faces);
if (num_faces) {
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);
}
}
@ -1491,7 +1797,7 @@ void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u,
urat = u - x;
vrat = v - y;
uopp = 1 - urat;
uopp = 1.0f - urat;
mul_v3_v3fl(d[0], disps[y * st + x], uopp);
mul_v3_v3fl(d[1], disps[y * st + x2], urat);
@ -1500,7 +1806,7 @@ void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u,
add_v3_v3v3(d2[0], d[0], d[1]);
add_v3_v3v3(d2[1], d[2], d[3]);
mul_v3_fl(d2[0], 1 - vrat);
mul_v3_fl(d2[0], 1.0f - vrat);
mul_v3_fl(d2[1], vrat);
add_v3_v3v3(out, d2[0], d2[1]);

View File

@ -881,7 +881,8 @@ static BMesh *get_bmesh_from_mesh(Mesh *mesh)
.use_toolflags = true,
}));
BM_mesh_bm_from_me(bm,
BM_mesh_bm_from_me(NULL,
bm,
mesh,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,
@ -1151,6 +1152,7 @@ bool multires_unsubdivide_to_basemesh(MultiresUnsubdivideContext *context)
/* Store the new base-mesh as a mesh in context, free bmesh. */
context->base_mesh = BKE_mesh_new_nomain(0, 0, 0, 0, 0);
BM_mesh_bm_to_me(NULL,
NULL,
bm_base_mesh,
context->base_mesh,
(&(struct BMeshToMeshParams){

View File

@ -1316,6 +1316,7 @@ static void sculptsession_bm_to_me_update_data_only(Object *ob, bool reorder)
BM_log_mesh_elems_reorder(ss->bm, ss->bm_log);
}
BM_mesh_bm_to_me(NULL,
NULL,
ss->bm,
ob->data,
(&(struct BMeshToMeshParams){

View File

@ -1453,6 +1453,7 @@ static void prepare_mesh_for_viewport_render(Main *bmain, const ViewLayer *view_
if (check_rendered_viewport_visible(bmain)) {
BMesh *bm = mesh->edit_mesh->bm;
BM_mesh_bm_to_me(bmain,
NULL,
bm,
mesh,
(&(struct BMeshToMeshParams){

View File

@ -986,6 +986,7 @@ static void subdiv_ccg_average_inner_face_grids(SubdivCCG *subdiv_ccg,
CCGKey *key,
SubdivCCGFace *face)
{
return; //XXX
CCGElem **grids = subdiv_ccg->grids;
const int num_face_grids = face->num_grids;
const int grid_size = subdiv_ccg->grid_size;
@ -1043,6 +1044,7 @@ static void subdiv_ccg_average_grids_boundary(SubdivCCG *subdiv_ccg,
SubdivCCGAdjacentEdge *adjacent_edge,
AverageGridsBoundariesTLSData *tls)
{
return; //XXXX
const int num_adjacent_faces = adjacent_edge->num_adjacent_faces;
const int grid_size2 = subdiv_ccg->grid_size * 2;
if (num_adjacent_faces == 1) {
@ -1106,6 +1108,7 @@ static void subdiv_ccg_average_grids_corners(SubdivCCG *subdiv_ccg,
CCGKey *key,
SubdivCCGAdjacentVertex *adjacent_vertex)
{
return;
const int num_adjacent_faces = adjacent_vertex->num_adjacent_faces;
if (num_adjacent_faces == 1) {
/* Nothing to average with. */
@ -1131,6 +1134,7 @@ static void subdiv_ccg_average_grids_corners_task(void *__restrict userdata_v,
const int adjacent_vertex_index,
const TaskParallelTLS *__restrict UNUSED(tls_v))
{
return;
AverageGridsCornerData *data = userdata_v;
SubdivCCG *subdiv_ccg = data->subdiv_ccg;
CCGKey *key = data->key;
@ -1140,6 +1144,7 @@ static void subdiv_ccg_average_grids_corners_task(void *__restrict userdata_v,
static void subdiv_ccg_average_all_boundaries(SubdivCCG *subdiv_ccg, CCGKey *key)
{
return;
TaskParallelSettings parallel_range_settings;
BLI_parallel_range_settings_defaults(&parallel_range_settings);
AverageGridsBoundariesData boundaries_data = {
@ -1159,6 +1164,7 @@ static void subdiv_ccg_average_all_boundaries(SubdivCCG *subdiv_ccg, CCGKey *key
static void subdiv_ccg_average_all_corners(SubdivCCG *subdiv_ccg, CCGKey *key)
{
return;
TaskParallelSettings parallel_range_settings;
BLI_parallel_range_settings_defaults(&parallel_range_settings);
AverageGridsCornerData corner_data = {
@ -1174,12 +1180,14 @@ static void subdiv_ccg_average_all_corners(SubdivCCG *subdiv_ccg, CCGKey *key)
static void subdiv_ccg_average_all_boundaries_and_corners(SubdivCCG *subdiv_ccg, CCGKey *key)
{
return;
subdiv_ccg_average_all_boundaries(subdiv_ccg, key);
subdiv_ccg_average_all_corners(subdiv_ccg, key);
}
void BKE_subdiv_ccg_average_grids(SubdivCCG *subdiv_ccg)
{
return;
CCGKey key;
BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg);
TaskParallelSettings parallel_range_settings;
@ -1190,6 +1198,7 @@ void BKE_subdiv_ccg_average_grids(SubdivCCG *subdiv_ccg)
.subdiv_ccg = subdiv_ccg,
.key = &key,
};
return;
BLI_task_parallel_range(0,
subdiv_ccg->num_faces,
&inner_data,
@ -1209,6 +1218,7 @@ static void subdiv_ccg_stitch_face_inner_grids_task(
const int face_index,
const TaskParallelTLS *__restrict UNUSED(tls_v))
{
return; //XXXX
StitchFacesInnerGridsData *data = userdata_v;
SubdivCCG *subdiv_ccg = data->subdiv_ccg;
CCGKey *key = data->key;
@ -1222,6 +1232,7 @@ void BKE_subdiv_ccg_average_stitch_faces(SubdivCCG *subdiv_ccg,
struct CCGFace **effected_faces,
int num_effected_faces)
{
return; //XXX
CCGKey key;
BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg);
StitchFacesInnerGridsData data = {

View File

@ -186,6 +186,7 @@ static void average_read_displacement_object(MultiresDisplacementData *data,
const int corner_index,
float r_D[3])
{
return;
const PolyCornerIndex *poly_corner = &data->ptex_poly_corner[ptex_face_index];
const MPoly *poly = &data->mpoly[poly_corner->poly_index];
/* Get (u, v) coordinate within the other ptex face which corresponds to
@ -231,6 +232,7 @@ static void average_with_other(SubdivDisplacement *displacement,
const int corner_delta,
float r_D[3])
{
return;
MultiresDisplacementData *data = displacement->user_data;
const MDisps *other_displacement_grid = displacement_get_other_grid(
displacement, ptex_face_index, corner, corner_delta);
@ -295,6 +297,7 @@ static void average_displacement(SubdivDisplacement *displacement,
const float grid_v,
float r_D[3])
{
return;
switch (average_with) {
case AVERAGE_WITH_ALL:
average_with_all(displacement, ptex_face_index, corner, grid_u, grid_v, r_D);
@ -360,8 +363,9 @@ static void eval_displacement(SubdivDisplacement *displacement,
BKE_multires_construct_tangent_matrix(tangent_matrix, dPdu, dPdv, corner_of_quad);
mul_v3_m3v3(r_D, tangent_matrix, tangent_D);
/* For the boundary points of grid average two (or all) neighbor grids. */
const int corner = displacement_get_face_corner(data, ptex_face_index, u, v);
average_displacement(displacement, average_with, ptex_face_index, corner, grid_u, grid_v, r_D);
//XXX
//const int corner = displacement_get_face_corner(data, ptex_face_index, u, v);
//average_displacement(displacement, average_with, ptex_face_index, corner, grid_u, grid_v, r_D);
}
static void free_displacement(SubdivDisplacement *displacement)

View File

@ -174,6 +174,11 @@ void BKE_subdiv_eval_limit_point(
BKE_subdiv_eval_limit_point_and_derivatives(subdiv, ptex_face_index, u, v, r_P, NULL, NULL);
}
static bool close_zero(float c[3]) {
const float eps = 0.00001;
return fabs(c[0]) < eps && fabs(c[1]) < eps && fabs(c[2]) < eps;
}
void BKE_subdiv_eval_limit_point_and_derivatives(Subdiv *subdiv,
const int ptex_face_index,
const float u,
@ -196,7 +201,7 @@ void BKE_subdiv_eval_limit_point_and_derivatives(Subdiv *subdiv,
* that giving totally unusable derivatives. */
if (r_dPdu != NULL && r_dPdv != NULL) {
if ((is_zero_v3(r_dPdu) || is_zero_v3(r_dPdv)) || equals_v3v3(r_dPdu, r_dPdv)) {
if ((close_zero(r_dPdu) || close_zero(r_dPdv)) || equals_v3v3(r_dPdu, r_dPdv)) {
subdiv->evaluator->evaluateLimit(subdiv->evaluator,
ptex_face_index,
u * 0.999f + 0.0005f,

View File

@ -182,9 +182,9 @@ set(LIB
extern_rangetree
)
if(MSVC AND NOT MSVC_CLANG)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX /wd4101")
endif()
#if(MSVC AND NOT MSVC_CLANG)
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX /wd4101")
#endif()
if(WITH_BULLET)
list(APPEND INC_SYS

View File

@ -16,6 +16,8 @@
#pragma once
#include "DNA_modifier_types.h"
/** \file
* \ingroup bmesh
*/
@ -266,6 +268,9 @@ typedef struct BMesh {
ListBase errorstack;
void *py_handle;
MultiresModifierData multires; //copy of multires settings
bool haveMultiResSettings;
int multiresSpace;
} BMesh;
/* BMHeader->htype (char) */

View File

@ -27,11 +27,13 @@
#include "DNA_meshdata_types.h"
#include "BLI_utildefines.h"
#include "BLI_alloca.h"
#include "BLI_linklist.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
#include "BLI_task.h"
#include "BLI_array.h"
#include "BKE_customdata.h"
#include "BKE_multires.h"
@ -314,17 +316,50 @@ static bool quad_co(const float v1[3],
/* rotate */
poly_rotate_plane(n, projverts, 5);
float projverts2[4][3];
/* subtract origin */
for (i = 0; i < 4; i++) {
sub_v2_v2(projverts[i], projverts[4]);
copy_v3_v3(projverts2[i], projverts[i]);
}
if (!isect_point_quad_v2(origin, projverts[0], projverts[1], projverts[2], projverts[3])) {
//expand quad a bit
#if 1
float eps = FLT_EPSILON * 400000;
float c[3];
mid_v3_v3v3v3v3(c, projverts[0], projverts[1], projverts[2], projverts[3]);
sub_v3_v3(projverts2[0], c);
sub_v3_v3(projverts2[1], c);
sub_v3_v3(projverts2[2], c);
sub_v3_v3(projverts2[3], c);
mul_v3_fl(projverts2[0], 1.0f + eps);
mul_v3_fl(projverts2[1], 1.0f + eps);
mul_v3_fl(projverts2[2], 1.0f + eps);
mul_v3_fl(projverts2[3], 1.0f + eps);
add_v3_v3(projverts2[0], c);
add_v3_v3(projverts2[1], c);
add_v3_v3(projverts2[2], c);
add_v3_v3(projverts2[3], c);
#endif
if (!isect_point_quad_v2(origin, projverts2[0], projverts2[1], projverts2[2], projverts2[3])) {
return false;
}
resolve_quad_uv_v2(r_uv, origin, projverts[0], projverts[3], projverts[2], projverts[1]);
//if (r_uv[0] < -eps || r_uv[1] < -eps || r_uv[0] > 1.0+eps || r_uv[1] > 1.0+eps) {
// return false;
//}
CLAMP(r_uv[0], 0.0f, 0.99999f);
CLAMP(r_uv[1], 0.0f, 0.99999f);
return true;
}
@ -353,8 +388,7 @@ static bool mdisp_in_mdispquad(BMLoop *l_src,
float r_axis_y[3],
float r_uv[2])
{
float v1[3], v2[3], c[3], v3[3], v4[3], e1[3], e2[3];
float eps = FLT_EPSILON * 4000;
float v1[3], v2[3], v3[3], v4[3], e1[3], e2[3];
if (is_zero_v3(l_src->v->no)) {
BM_vert_normal_update_all(l_src->v);
@ -366,6 +400,9 @@ static bool mdisp_in_mdispquad(BMLoop *l_src,
compute_mdisp_quad(l_dst, l_dst_f_center, v1, v2, v3, v4, e1, e2);
/* expand quad a bit */
#if 0
float c[3];
float eps = FLT_EPSILON * 400;
mid_v3_v3v3v3v3(c, v1, v2, v3, v4);
sub_v3_v3(v1, c);
@ -380,6 +417,7 @@ static bool mdisp_in_mdispquad(BMLoop *l_src,
add_v3_v3(v2, c);
add_v3_v3(v3, c);
add_v3_v3(v4, c);
#endif
if (!quad_co(v1, v2, v3, v4, p, l_src->v->no, r_uv)) {
return 0;
@ -447,8 +485,10 @@ typedef struct BMLoopInterpMultiresData {
BMLoop *l_src_first;
int cd_loop_mdisp_offset;
int space;
MDisps *md_dst;
const float *f_src_center;
const float *f_dst_center;
float *axis_x, *axis_y;
float *v1, *v4;
@ -467,6 +507,7 @@ static void loop_interp_multires_cb(void *__restrict userdata,
BMLoop *l_first = data->l_src_first;
BMLoop *l_dst = data->l_dst;
const int cd_loop_mdisp_offset = data->cd_loop_mdisp_offset;
int space = data->space;
MDisps *md_dst = data->md_dst;
const float *f_src_center = data->f_src_center;
@ -481,6 +522,19 @@ static void loop_interp_multires_cb(void *__restrict userdata,
const int res = data->res;
const float d = data->d;
float quad[4][3];
float n1[3], n2[3];
normal_tri_v3(n1, l_dst->v->co, l_dst->next->v->co, data->f_dst_center);
if (space == MULTIRES_SPACE_ABSOLUTE) {
BMLoop *l = l_dst;
copy_v3_v3(quad[0], data->f_dst_center);
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 x = d * ix, y;
int iy;
@ -492,24 +546,70 @@ static void loop_interp_multires_cb(void *__restrict userdata,
madd_v3_v3v3fl(co2, v4, e2, y);
interp_v3_v3v3(co, co1, co2, x);
float sum[3];
int tot = 0;
zero_v3(sum);
float mindis = 1e17;
float baseco[3];
if (space == MULTIRES_SPACE_ABSOLUTE) {
interp_bilinear_quad_v3(quad, x, y, baseco);
}
do {
MDisps *md_src;
float src_axis_x[3], src_axis_y[3];
float uv[2];
normal_tri_v3(n2, l_iter->v->co, l_iter->next->v->co, data->f_src_center);
float th = dot_v3v3(n1, n2);
if (th < 0.0f) {
negate_v3(n2);
}
th = acos(dot_v3v3(n1, n2)*0.999999f);
if (th > M_PI*0.1) {
continue;
}
md_src = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_mdisp_offset);
if (mdisp_in_mdispquad(l_dst, l_iter, f_src_center, co, res, src_axis_x, src_axis_y, uv)) {
old_mdisps_bilinear(md_dst->disps[iy * res + ix], md_src->disps, res, uv[0], uv[1]);
bm_loop_flip_disp(src_axis_x, src_axis_y, axis_x, axis_y, md_dst->disps[iy * res + ix]);
float disp[3];
copy_v3_v3(disp, md_dst->disps[iy * res + ix]);
break;
old_mdisps_bilinear(disp, md_src->disps, res, uv[0], uv[1]);
if (space == MULTIRES_SPACE_TANGENT) {
bm_loop_flip_disp(src_axis_x, src_axis_y, axis_x, axis_y, disp);
}
float l = len_v3v3(disp, baseco);
if (l < mindis) {
mindis = l;
//tot++;
//copy_v3_v3(sum, disp);
}
add_v3_v3(sum, disp);
tot++;
//break;
}
} while ((l_iter = l_iter->next) != l_first);
if (tot) {
mul_v3_fl(sum, 1.0 / (float)tot);
copy_v3_v3(md_dst->disps[iy * res + ix], sum);
} else {
//printf("failed to set disp: %f %f\n", x, y);
if (space == MULTIRES_SPACE_ABSOLUTE) {
//copy_v3_v3(md_dst->disps[iy * res + ix], baseco);
//copy_v3_v3(md_dst->disps[iy * res + ix], baseco);
}
}
}
}
void BM_loop_interp_multires_ex(BMesh *UNUSED(bm),
void BM_loop_interp_multires_ex(BMesh *bm,
BMLoop *l_dst,
const BMFace *f_src,
const float f_dst_center[3],
@ -551,7 +651,9 @@ void BM_loop_interp_multires_ex(BMesh *UNUSED(bm),
.cd_loop_mdisp_offset = cd_loop_mdisp_offset,
.md_dst = md_dst,
.f_src_center = f_src_center,
.f_dst_center = f_dst_center,
.axis_x = axis_x,
.space = bm->multiresSpace,
.axis_y = axis_y,
.v1 = v1,
.v4 = v4,
@ -597,6 +699,8 @@ void BM_face_interp_multires_ex(BMesh *bm,
BM_loop_interp_multires_ex(
bm, l_iter, f_src, f_dst_center, f_src_center, cd_loop_mdisp_offset);
} while ((l_iter = l_iter->next) != l_first);
BM_face_multires_bounds_smooth(bm, f_dst);
}
void BM_face_interp_multires(BMesh *bm, BMFace *f_dst, const BMFace *f_src)
@ -614,12 +718,247 @@ void BM_face_interp_multires(BMesh *bm, BMFace *f_dst, const BMFace *f_src)
}
}
void BM_multires_smooth(BMesh *bm, BMFace *f, bool no_boundary) {
const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
float (*orig)[3] = NULL;
BLI_array_staticdeclare(orig, 256*256);
if (cd_loop_mdisp_offset < 0) {
return;
}
float cent[3];
zero_v3(cent);
int ctot = 0;
BMLoop *cl = f->l_first;
do {
add_v3_v3(cent, cl->v->co);
cl = cl->next;
ctot++;
} while (cl != f->l_first);
mul_v3_fl(cent, 1.0f / (float)ctot);
const int offs[][2] = {
{0, 0},
// {-1, -1},
{-1, 0},
// {-1, 1},
{0, 1},
// {1, 1},
{1, 0},
// {1, -1},
{0, -1},
};
int totoff = sizeof(offs) / sizeof(*offs);
#ifndef ABS
#define ABS(a) ((a) < 0 ? -(a) : (a))
#endif
//int space = bm->multiresSpace;
BMLoop *l = f->l_first;
do {
MDisps *md = BM_ELEM_CD_GET_VOID_P(l, cd_loop_mdisp_offset);
if (!md->disps) continue;
int res = (int)floor(sqrt((double)md->totdisp) + 0.000001);
int start = no_boundary ? 1 : 0;
int end = no_boundary ? res-1 : res;
float df = 1.0f / (float)(res-1);
float u = 0.0;
BLI_array_clear(orig);
BLI_array_reserve(orig, md->totdisp*3);
memcpy(orig, md->disps, sizeof(float)*3*md->totdisp);
for (int x=start; x<end; x++, u += df) {
float v = 0.0;
/*x < 0, x >= res, y < 0, y >= res, winding_matches*/
for (int y=start; y<end; y++, v += df) {
float co[3];
float tot = 0.0f;
zero_v3(co);
int idx1 = y*res + x;
for (int oi=0; oi<totoff; oi++) {
int ox = x + offs[oi][0];
int oy = y + offs[oi][1];
MDisps *md2 = md;
if (1 && (ox < 0 || oy < 0 || ox >= res || oy >= res)) {
BMLoop *l2 = NULL;
BMLoop *ls = l;
if (ox < 0 && oy < 0) {
l2 = ls->next->next;
ox = ABS(ox);
oy = ABS(oy);
} else if (ox < 0 && oy >= 0 && oy < res-1) {
l2 = ls->prev;
int t = oy;
oy = -ox;
ox = t;
} else if (oy < 0 && ox >= 0 && ox < res-1) {
l2 = ls->next;
int t = oy;
oy = ox;
ox = -t;
} else if (ox >= res && oy >= 0 && oy < res) {
l2 = ls->radial_next;
if (ls->v != l2->v) {
l2 = l2->next;
int t = oy;
oy = 2*res - ox - 1;
ox = t;
} else {
ox = res - ox;
}
//XXX disables this branch
//ox = oy = -1;
} else if (ox >= res && oy < 0) {
l2 = ls->radial_next;
if (l2->v != ls->v) {
oy = -oy;
ox = 2*res - ox - 1;
} else {
l2 = l2->next;
int t = ox;
ox = -oy;
oy = 2*res - t - 1;
}
//XXX disables this branch
//ox = oy = -1;
} else if (oy >= res && ox >= 0 && ox < res) {
l2 = ls->prev->radial_next;
if (l2->v == ls->v) {
int t = ox;
ox = 2*res - oy - 1;
oy = t;
} else {
l2 = l2->next;
oy = 2*res - oy - 1;
}
//XXX disables this branch
//ox = oy = -1;
} else if (ox >= res && oy >= res) {
l2 = ls->prev->radial_next->prev->radial_prev;
if (l2->v == ls->v) {
int t = ox;
ox = oy;
oy = t;
ox = 2*res - ox - 1;
oy = 2*res - oy - 1;
//XXX disables this branch
//ox = oy = -1;
} else {
printf("ignoring non-4-valence multires corner");
l2 = NULL;
}
}
if (l2) {
//ox = res - ox - 1;
//oy = res - oy - 1;
md2 = BM_ELEM_CD_GET_VOID_P(l2, cd_loop_mdisp_offset);
}
}
if (!md2->disps || oy < 0 || oy >= res || ox < 0 || ox >= res) {
continue;
}
int idx2 = oy*res + ox;
float *oco2 = md == md2 ? orig[idx2] : md2->disps[idx2];
float co2[3];
copy_v3_v3(co2, oco2);
float dx = 0.5f*(float)offs[oi][0];
float dy = 0.5f*(float)offs[oi][1];
float w = M_SQRT2 - dx*dx + dy*dy;
if (no_boundary && (ox == 0 || oy == 0 || ox == res-1 || oy == res-1)) {
// w = 2.0;
} else if (ox == x && oy == y) {
// w = 1.0;
}
w = 1.0;
mul_v3_fl(co2, w);
tot += w;
add_v3_v3(co, co2);
}
/*
float vec[3];
copy_v3_v3(vec, f->no);
mul_v3_fl(vec, 0.4);
add_v3_v3(md->disps[idx1], vec);
sub_v3_v3(md->disps[idx1], cent);
mul_v3_fl(md->disps[idx1], 1.2);
add_v3_v3(md->disps[idx1], cent);
continue;
//*/
if (tot > 0.0f) {
mul_v3_fl(co, 1.0f / tot);
copy_v3_v3(md->disps[idx1], co);
}
}
}
l = l->next;
} while (l != f->l_first);
BLI_array_free(orig);
}
void bmo_test_mres_smooth_exec(BMesh *bm, BMOperator *op) {
BMIter iter;
BMFace *f;
if (!CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
return;
}
BM_ITER_MESH(f, &iter, bm, BM_FACES_OF_MESH) {
bool ok = !!BM_elem_flag_test(f, BM_ELEM_SELECT);
ok = ok && !BM_elem_flag_test(f, BM_ELEM_HIDDEN);
if (!ok) {
continue;
}
BM_multires_smooth(bm, f, false);
//BM_multires_smooth(bm, f, false);
//BM_multires_smooth(bm, f, false);
//BM_face_multires_bounds_smooth(bm, f);
}
}
/**
* smooths boundaries between multires grids,
* including some borders in adjacent faces
*/
void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f)
{
return;
const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
BMLoop *l;
BMIter liter;
@ -693,7 +1032,7 @@ void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f)
mdl2 = BM_ELEM_CD_GET_VOID_P(l->radial_next->next, cd_loop_mdisp_offset);
}
sides = (int)sqrt(mdl1->totdisp);
sides = (int)floor(sqrt(mdl1->totdisp)+FLT_EPSILON);
for (y = 0; y < sides; y++) {
int a1, a2, o1, o2;
@ -711,14 +1050,16 @@ void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f)
o2 = sides * y + sides - 1;
}
interp_v3_v3v3(co1, mdl1->disps[a1], mdl2->disps[a2], 0.5f);
interp_v3_v3v3(co2, mdl1->disps[o1], mdl2->disps[o2], 0.5f);
/* magic blending numbers, hardcoded! */
add_v3_v3v3(co1, mdl1->disps[a1], mdl2->disps[a2]);
mul_v3_fl(co1, 0.18);
//mul_v3_fl(co1, 0.18);
add_v3_v3v3(co2, mdl1->disps[o1], mdl2->disps[o2]);
mul_v3_fl(co2, 0.32);
//add_v3_v3v3(co2, mdl1->disps[o1], mdl2->disps[o2]);
//mul_v3_fl(co2, 0.32);
add_v3_v3v3(co, co1, co2);
interp_v3_v3v3(co, co1, co2, 0.5f);
//add_v3_v3v3(co, co1, co2);
copy_v3_v3(mdl1->disps[o1], co);
copy_v3_v3(mdl2->disps[o2], co);

View File

@ -1954,6 +1954,11 @@ void BM_custom_loop_normals_from_vector_layer(BMesh *bm, bool add_sharp_edges)
bm->spacearr_dirty &= ~(BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL);
}
static void bmesh_convert_space(BMesh *bm, MultiResSpace from, MultiResSpace to)
{
}
/**
* \brief BMesh Begin Edit
*
@ -1961,24 +1966,22 @@ void BM_custom_loop_normals_from_vector_layer(BMesh *bm, bool add_sharp_edges)
* the editing operations are done. These are called by the tools/operator
* API for each time a tool is executed.
*/
void bmesh_edit_begin(BMesh *UNUSED(bm), BMOpTypeFlag UNUSED(type_flag))
void bmesh_edit_begin(BMesh *bm, BMOpTypeFlag type_flag)
{
/* Most operators seem to be using BMO_OPTYPE_FLAG_UNTAN_MULTIRES to change the MDisps to
* absolute space during mesh edits. With this enabled, changes to the topology
* (loop cuts, edge subdivides, etc) are not reflected in the higher levels of
* the mesh at all, which doesn't seem right. Turning off completely for now,
* until this is shown to be better for certain types of mesh edits. */
#ifdef BMOP_UNTAN_MULTIRES_ENABLED
/* switch multires data out of tangent space */
if ((type_flag & BMO_OPTYPE_FLAG_UNTAN_MULTIRES) &&
CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
bmesh_mdisps_space_set(bm, MULTIRES_SPACE_TANGENT, MULTIRES_SPACE_ABSOLUTE);
//bmesh_mdisps_space_set(bm, MULTIRES_SPACE_TANGENT, MULTIRES_SPACE_ABSOLUTE);
BM_enter_multires_space(NULL, bm, MULTIRES_SPACE_ABSOLUTE);
/* ensure correct normals, if possible */
bmesh_rationalize_normals(bm, 0);
BM_mesh_normals_update(bm);
//bmesh_rationalize_normals(bm, 0);
//BM_mesh_normals_update(bm);
}
#endif
}
/**
@ -1989,17 +1992,10 @@ void bmesh_edit_end(BMesh *bm, BMOpTypeFlag type_flag)
ListBase select_history;
/* BMO_OPTYPE_FLAG_UNTAN_MULTIRES disabled for now, see comment above in bmesh_edit_begin. */
#ifdef BMOP_UNTAN_MULTIRES_ENABLED
/* switch multires data into tangent space */
if ((flag & BMO_OPTYPE_FLAG_UNTAN_MULTIRES) && CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
/* set normals to their previous winding */
bmesh_rationalize_normals(bm, 1);
bmesh_mdisps_space_set(bm, MULTIRES_SPACE_ABSOLUTE, MULTIRES_SPACE_TANGENT);
if ((type_flag & BMO_OPTYPE_FLAG_UNTAN_MULTIRES) && CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
BM_enter_multires_space(NULL, bm, MULTIRES_SPACE_TANGENT);
}
else if (flag & BMO_OP_FLAG_RATIONALIZE_NORMALS) {
bmesh_rationalize_normals(bm, 1);
}
#endif
/* compute normals, clear temp flags and flush selections */
if (type_flag & BMO_OPTYPE_FLAG_NORMALS_CALC) {

View File

@ -22,6 +22,11 @@
#include "bmesh_class.h"
typedef enum {
MULTIRES_SPACE_TANGENT, //convert absolute to tangent
MULTIRES_SPACE_ABSOLUTE //convert tangent to absolute
} MultiResSpace;
struct BMAllocTemplate;
struct BMLoopNorEditDataArray;
struct MLoopNorSpaceArray;

View File

@ -176,8 +176,27 @@ static BMFace *bm_face_create_from_mpoly(
return BM_face_create(bm, verts, edges, mp->totloop, NULL, BM_CREATE_SKIP_CD);
}
void BM_enter_multires_space(Object *ob, BMesh *bm, int space) {
if (!bm->haveMultiResSettings && ob) {
MultiresModifierData *mmd = get_multires_modifier(NULL, ob, true);
if (mmd) {
bm->multires = *mmd;
bm->haveMultiResSettings = true;
bm->multiresSpace = MULTIRES_SPACE_TANGENT;
}
}
if (!bm->haveMultiResSettings || !CustomData_has_layer(&bm->ldata, CD_MDISPS) || space == bm->multiresSpace) {
return;
}
BKE_multires_bmesh_space_set(ob, bm, space);
bm->multiresSpace = space;
}
/**
* \brief Mesh -> BMesh
* \param ob: object that owns bm, may be NULL (which will disable multires space change)
* \param bm: The mesh to write into, while this is typically a newly created BMesh,
* merging into existing data is supported.
* Note the custom-data layout isn't used.
@ -186,7 +205,7 @@ static BMFace *bm_face_create_from_mpoly(
*
* \warning This function doesn't calculate face normals.
*/
void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshParams *params)
void BM_mesh_bm_from_me(Object *ob, BMesh *bm, const Mesh *me, const struct BMeshFromMeshParams *params)
{
const bool is_new = !(bm->totvert || (bm->vdata.totlayer || bm->edata.totlayer ||
bm->pdata.totlayer || bm->ldata.totlayer));
@ -203,6 +222,15 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
CustomData_MeshMasks mask = CD_MASK_BMESH;
CustomData_MeshMasks_update(&mask, &params->cd_mask_extra);
MultiresModifierData *mmd = ob ? get_multires_modifier(NULL, ob, true) : NULL;
if (mmd) {
bm->multires = *mmd;
bm->haveMultiResSettings = true;
bm->multiresSpace = MULTIRES_SPACE_TANGENT;
} else {
bm->haveMultiResSettings = false;
}
if (!me || !me->totvert) {
if (me && is_new) { /* No verts? still copy custom-data layout. */
CustomData_copy(&me->vdata, &bm->vdata, mask.vmask, CD_ASSIGN, 0);
@ -568,7 +596,7 @@ BLI_INLINE void bmesh_quick_edgedraw_flag(MEdge *med, BMEdge *e)
*
* \param bmain: May be NULL in case \a calc_object_remap parameter option is not set.
*/
void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMeshParams *params)
void BM_mesh_bm_to_me(Main *bmain, Object *ob, BMesh *bm, Mesh *me, const struct BMeshToMeshParams *params)
{
MEdge *med;
BMVert *v, *eve;
@ -577,6 +605,11 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
BMIter iter;
int i, j;
//ensure multires space is correct
if (bm->haveMultiResSettings && bm->multiresSpace != MULTIRES_SPACE_TANGENT) {
BM_enter_multires_space(ob, bm, MULTIRES_SPACE_TANGENT);
}
const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);

View File

@ -43,7 +43,9 @@ struct BMeshFromMeshParams {
int active_shapekey;
struct CustomData_MeshMasks cd_mask_extra;
};
void BM_mesh_bm_from_me(BMesh *bm, const struct Mesh *me, const struct BMeshFromMeshParams *params)
struct Object;
void BM_mesh_bm_from_me(struct Object *ob, BMesh *bm, const struct Mesh *me, const struct BMeshFromMeshParams *params)
ATTR_NONNULL(1, 3);
struct BMeshToMeshParams {
@ -61,7 +63,11 @@ struct BMeshToMeshParams {
uint update_shapekey_indices : 1;
struct CustomData_MeshMasks cd_mask_extra;
};
void BM_enter_multires_space(struct Object *ob, struct BMesh *bm, int space);
void BM_mesh_bm_to_me(struct Main *bmain,
struct Object *ob,
BMesh *bm,
struct Mesh *me,
const struct BMeshToMeshParams *params) ATTR_NONNULL(2, 3, 4);

View File

@ -1064,6 +1064,21 @@ static BMOpDefine bmo_extrude_face_region_def = {
(BMO_OPTYPE_FLAG_NORMALS_CALC),
};
extern void bmo_test_mres_smooth_exec(BMesh *bm, BMOperator *op);
static BMOpDefine bmo_test_mres_smooth_def = {
"test_mres_smooth",
/* slots_in */
{{{'\0'}}}, /* no input */
{{{'\0'}}}, /* no output */
bmo_test_mres_smooth_exec,
(
BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
BMO_OPTYPE_FLAG_NORMALS_CALC |
BMO_OPTYPE_FLAG_SELECT_FLUSH |
BMO_OPTYPE_FLAG_SELECT_VALIDATE)
};
/*
* Dissolve Verts.
*/
@ -1911,7 +1926,7 @@ static BMOpDefine bmo_inset_individual_def = {
},
bmo_inset_individual_exec,
/* caller needs to handle BMO_OPTYPE_FLAG_SELECT_FLUSH */
(BMO_OPTYPE_FLAG_NORMALS_CALC),
(BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_UNTAN_MULTIRES),
};
/*
@ -1940,7 +1955,7 @@ static BMOpDefine bmo_inset_region_def = {
},
bmo_inset_region_exec,
(BMO_OPTYPE_FLAG_NORMALS_CALC |
BMO_OPTYPE_FLAG_SELECT_FLUSH),
BMO_OPTYPE_FLAG_SELECT_FLUSH | BMO_OPTYPE_FLAG_UNTAN_MULTIRES),
};
/*
@ -1961,7 +1976,7 @@ static BMOpDefine bmo_offset_edgeloops_def = {
},
bmo_offset_edgeloops_exec,
(BMO_OPTYPE_FLAG_NORMALS_CALC |
BMO_OPTYPE_FLAG_SELECT_FLUSH),
BMO_OPTYPE_FLAG_SELECT_FLUSH | BMO_OPTYPE_FLAG_UNTAN_MULTIRES),
};
/*
@ -2179,6 +2194,7 @@ const BMOpDefine *bmo_opdefines[] = {
&bmo_unsubdivide_def,
&bmo_weld_verts_def,
&bmo_wireframe_def,
&bmo_test_mres_smooth_def
};
const int bmo_opdefines_total = ARRAY_SIZE(bmo_opdefines);

View File

@ -39,7 +39,8 @@ void bmo_mesh_to_bmesh_exec(BMesh *bm, BMOperator *op)
Mesh *me = BMO_slot_ptr_get(op->slots_in, "mesh");
bool set_key = BMO_slot_bool_get(op->slots_in, "use_shapekey");
BM_mesh_bm_from_me(bm,
BM_mesh_bm_from_me(NULL,
bm,
me,
(&(struct BMeshFromMeshParams){
.use_shapekey = set_key,
@ -66,6 +67,7 @@ void bmo_bmesh_to_mesh_exec(BMesh *bm, BMOperator *op)
/* Object *ob = BMO_slot_ptr_get(op, "object"); */
BM_mesh_bm_to_me(G.main,
NULL,
bm,
me,
(&(struct BMeshToMeshParams){

View File

@ -116,7 +116,7 @@ static int geometry_extract_apply(bContext *C,
.use_toolflags = true,
}));
BM_mesh_bm_from_me(bm,
BM_mesh_bm_from_me(NULL, bm,
new_mesh,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,
@ -507,7 +507,7 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op)
.use_toolflags = true,
}));
BM_mesh_bm_from_me(bm,
BM_mesh_bm_from_me(NULL, bm,
new_mesh,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,
@ -538,7 +538,7 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op)
.use_toolflags = true,
}));
BM_mesh_bm_from_me(bm,
BM_mesh_bm_from_me(NULL, bm,
new_ob_mesh,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,

View File

@ -4205,7 +4205,7 @@ static Base *mesh_separate_tagged(
BM_mesh_normals_update(bm_new);
BM_mesh_bm_to_me(bmain, bm_new, base_new->object->data, (&(struct BMeshToMeshParams){0}));
BM_mesh_bm_to_me(bmain, base_new->object, bm_new, base_new->object->data, (&(struct BMeshToMeshParams){0}));
BM_mesh_free(bm_new);
((Mesh *)base_new->object->data)->edit_mesh = NULL;
@ -4266,7 +4266,7 @@ static Base *mesh_separate_arrays(Main *bmain,
BM_vert_kill(bm_old, verts[i]);
}
BM_mesh_bm_to_me(bmain, bm_new, base_new->object->data, (&(struct BMeshToMeshParams){0}));
BM_mesh_bm_to_me(bmain, base_new->object, bm_new, base_new->object->data, (&(struct BMeshToMeshParams){0}));
BM_mesh_free(bm_new);
((Mesh *)base_new->object->data)->edit_mesh = NULL;
@ -4449,7 +4449,7 @@ static bool mesh_separate_loose(
BM_mesh_elem_hflag_disable_all(bm_old, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
if (clear_object_data) {
BM_mesh_bm_to_me(NULL,
BM_mesh_bm_to_me(NULL, base_old->object,
bm_old,
me_old,
(&(struct BMeshToMeshParams){
@ -4536,7 +4536,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
.use_toolflags = true,
}));
BM_mesh_bm_from_me(bm_old, me, (&(struct BMeshFromMeshParams){0}));
BM_mesh_bm_from_me(NULL, bm_old, me, (&(struct BMeshFromMeshParams){0}));
switch (type) {
case MESH_SEPARATE_MATERIAL:
@ -4552,6 +4552,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
if (retval_iter) {
BM_mesh_bm_to_me(bmain,
ob,
bm_old,
me,
(&(struct BMeshToMeshParams){
@ -5699,7 +5700,7 @@ static void edbm_dissolve_prop__use_boundary_tear(wmOperatorType *ot)
"Split off face corners instead of merging faces");
}
static int edbm_dissolve_verts_exec(bContext *C, wmOperator *op)
static int edbm_mres_test_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");
@ -5721,10 +5722,64 @@ static int edbm_dissolve_verts_exec(bContext *C, wmOperator *op)
if (!EDBM_op_callf(em,
op,
"dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b",
BM_ELEM_SELECT,
use_face_split,
use_boundary_tear)) {
"test_mres_smooth")) {
continue;
}
BM_custom_loop_normals_from_vector_layer(em->bm, false);
EDBM_update_generic(obedit->data, true, true);
}
MEM_freeN(objects);
return OPERATOR_FINISHED;
}
void MESH_OT_mres_test(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Test Multires Boundary Smooth";
ot->description = "Test multires boundary smooth";
ot->idname = "MESH_OT_mres_test";
/* api callbacks */
ot->exec = edbm_mres_test_exec;
ot->poll = ED_operator_editmesh;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
edbm_dissolve_prop__use_face_split(ot);
edbm_dissolve_prop__use_boundary_tear(ot);
}
static int edbm_dissolve_verts_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);
if (em->bm->totvertsel == 0) {
continue;
}
BM_custom_loop_normals_to_vector_layer(em->bm);
if (!EDBM_op_callf(em,
op,
"dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b",
BM_ELEM_SELECT,
use_face_split,
use_boundary_tear)) {
continue;
}
@ -5737,6 +5792,7 @@ static int edbm_dissolve_verts_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
void MESH_OT_dissolve_verts(wmOperatorType *ot)
{
/* identifiers */

View File

@ -520,7 +520,7 @@ static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key)
/* BM_mesh_validate(em->bm); */ /* for troubleshooting */
BM_mesh_bm_to_me(
NULL,
NULL, NULL,
em->bm,
&um->me,
(&(struct BMeshToMeshParams){
@ -596,7 +596,7 @@ static void undomesh_to_editmesh(UndoMesh *um, Object *ob, BMEditMesh *em, Key *
.use_toolflags = true,
}));
BM_mesh_bm_from_me(bm,
BM_mesh_bm_from_me(NULL, bm,
&um->me,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,

View File

@ -352,6 +352,7 @@ void EDBM_mesh_load_ex(Main *bmain, Object *ob, bool free_data)
}
BM_mesh_bm_to_me(bmain,
ob,
bm,
me,
(&(struct BMeshToMeshParams){

View File

@ -259,6 +259,7 @@ void MESH_OT_set_normals_from_faces(struct wmOperatorType *ot);
void MESH_OT_average_normals(struct wmOperatorType *ot);
void MESH_OT_smooth_normals(struct wmOperatorType *ot);
void MESH_OT_mod_weighted_strength(struct wmOperatorType *ot);
void MESH_OT_mres_test(struct wmOperatorType *ot);
/* *** editmesh_mask_extract.c *** */
void MESH_OT_paint_mask_extract(struct wmOperatorType *ot);

View File

@ -208,6 +208,8 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_average_normals);
WM_operatortype_append(MESH_OT_smooth_normals);
WM_operatortype_append(MESH_OT_mod_weighted_strength);
WM_operatortype_append(MESH_OT_mres_test);
}
#if 0 /* UNUSED, remove? */

View File

@ -880,7 +880,7 @@ static void sculpt_gesture_trim_normals_update(SculptGestureContext *sgcontext)
.use_toolflags = true,
}));
BM_mesh_bm_from_me(bm,
BM_mesh_bm_from_me(NULL, bm,
trim_mesh,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,
@ -1089,13 +1089,15 @@ static void sculpt_gesture_apply_trim(SculptGestureContext *sgcontext)
.use_toolflags = false,
}));
BM_mesh_bm_from_me(bm,
BM_mesh_bm_from_me(NULL,
bm,
trim_mesh,
&((struct BMeshFromMeshParams){
.calc_face_normal = true,
}));
BM_mesh_bm_from_me(bm,
BM_mesh_bm_from_me(NULL,
bm,
sculpt_mesh,
&((struct BMeshFromMeshParams){
.calc_face_normal = true,

View File

@ -165,7 +165,8 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
.use_toolflags = false,
}));
BM_mesh_bm_from_me(ss->bm,
BM_mesh_bm_from_me(NULL,
ss->bm,
me,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,

View File

@ -382,7 +382,8 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
.use_toolflags = true,
}));
BM_mesh_bm_from_me(bm,
BM_mesh_bm_from_me(NULL,
bm,
mesh,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,
@ -561,7 +562,8 @@ static void sculpt_face_sets_init_flood_fill(Object *ob,
.use_toolflags = true,
}));
BM_mesh_bm_from_me(bm,
BM_mesh_bm_from_me(NULL,
bm,
mesh,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,
@ -634,7 +636,8 @@ static void sculpt_face_sets_init_loop(Object *ob, const int mode)
.use_toolflags = true,
}));
BM_mesh_bm_from_me(bm,
BM_mesh_bm_from_me(NULL,
bm,
mesh,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,

View File

@ -2839,7 +2839,8 @@ void ED_uvedit_add_simple_uvs(Main *bmain, const Scene *scene, Object *ob)
ED_mesh_uv_texture_ensure(me, NULL);
BM_mesh_bm_from_me(bm,
BM_mesh_bm_from_me(NULL,
bm,
me,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,

View File

@ -449,7 +449,7 @@ void bc_triangulate_mesh(Mesh *me)
BMesh *bm = BM_mesh_create(&bm_mesh_allocsize_default, &bm_create_params);
BMeshFromMeshParams bm_from_me_params = {0};
bm_from_me_params.calc_face_normal = true;
BM_mesh_bm_from_me(bm, me, &bm_from_me_params);
BM_mesh_bm_from_me(NULL, bm, me, &bm_from_me_params);
BM_mesh_triangulate(bm, quad_method, use_beauty, 4, tag_only, NULL, NULL, NULL);
BMeshToMeshParams bm_to_me_params = {0};

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,
bm = BKE_mesh_to_bmesh_ex(mesh, NULL,
&(struct BMeshCreateParams){0},
&(struct BMeshFromMeshParams){
.calc_face_normal = true,

View File

@ -250,7 +250,7 @@ static BMesh *BMD_mesh_bm_create(
.use_toolflags = false,
}));
BM_mesh_bm_from_me(bm,
BM_mesh_bm_from_me(NULL, bm,
mesh_operand_ob,
&((struct BMeshFromMeshParams){
.calc_face_normal = true,
@ -265,7 +265,7 @@ static BMesh *BMD_mesh_bm_create(
}
}
BM_mesh_bm_from_me(bm,
BM_mesh_bm_from_me(NULL, bm,
mesh,
&((struct BMeshFromMeshParams){
.calc_face_normal = true,
@ -457,7 +457,7 @@ static Mesh *collection_boolean_exact(BooleanModifierData *bmd,
Mesh *me = meshes[i];
Object *ob = objects[i];
/* Need normals for triangulation. */
BM_mesh_bm_from_me(bm,
BM_mesh_bm_from_me(NULL, bm,
me,
&((struct BMeshFromMeshParams){
.calc_face_normal = true,
@ -655,7 +655,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
BMD_mesh_intersection(bm, md, ctx, mesh_operand_ob, object, operand_ob, is_flip);
/* Needed for multiple objects to work. */
BM_mesh_bm_to_me(NULL,
BM_mesh_bm_to_me(NULL, NULL,
bm,
mesh,
(&(struct BMeshToMeshParams){

View File

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

View File

@ -251,7 +251,7 @@ static void deformVertsEM(ModifierData *md,
const bool do_temp_mesh = (mesh == NULL);
if (do_temp_mesh) {
mesh = BKE_id_new_nomain(ID_ME, ((ID *)ob->data)->name);
BM_mesh_bm_to_me(NULL, editData->bm, mesh, &((BMeshToMeshParams){0}));
BM_mesh_bm_to_me(NULL, NULL, editData->bm, mesh, &((BMeshToMeshParams){0}));
}
deformVerts(md, ob, mesh, vertexCos, numVerts);

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,
bm = BKE_mesh_to_bmesh_ex(mesh, NULL,
&((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,
bm = BKE_mesh_to_bmesh_ex(mesh, NULL,
&(struct BMeshCreateParams){0},
&(struct BMeshFromMeshParams){
.calc_face_normal = true,

View File

@ -1169,7 +1169,8 @@ static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args, PyObject
bm = self->bm;
BM_mesh_bm_from_me(bm,
BM_mesh_bm_from_me(NULL,
bm,
me_eval,
(&(struct BMeshFromMeshParams){
.calc_face_normal = use_fnorm,
@ -1226,7 +1227,8 @@ static PyObject *bpy_bmesh_from_mesh(BPy_BMesh *self, PyObject *args, PyObject *
bm = self->bm;
BM_mesh_bm_from_me(bm,
BM_mesh_bm_from_me(NULL,
bm,
me,
(&(struct BMeshFromMeshParams){
.calc_face_normal = use_fnorm,