Sculpt dyntopo:
* Fixed multires apply base feeding bad original coordinates to deform modifiers. * Roughed out some code for cache performance testing. * Wrote skeleton code for a PBVH texel API; hasn't been tested yet and may be removed.
This commit is contained in:
parent
de1f2c41fa
commit
0d542db1e1
|
@ -642,7 +642,7 @@ void BKE_mesh_calc_edges_tessface(struct Mesh *mesh);
|
|||
|
||||
/* In DerivedMesh.cc */
|
||||
void BKE_mesh_wrapper_deferred_finalize(struct Mesh *me_eval,
|
||||
const CustomData_MeshMasks *cd_mask_finalize);
|
||||
const struct CustomData_MeshMasks *cd_mask_finalize);
|
||||
|
||||
/* **** Depsgraph evaluation **** */
|
||||
|
||||
|
|
|
@ -41,6 +41,12 @@ typedef struct SculptFaceRef {
|
|||
intptr_t i;
|
||||
} SculptFaceRef;
|
||||
|
||||
#if 0
|
||||
typedef struct SculptLoopRef {
|
||||
intptr_t i;
|
||||
} SculptLoopRef;
|
||||
#endif
|
||||
|
||||
BLI_INLINE SculptVertRef BKE_pbvh_make_vref(intptr_t i)
|
||||
{
|
||||
SculptVertRef ret = {i};
|
||||
|
@ -745,6 +751,97 @@ void BKE_pbvh_update_vert_boundary(int cd_dyn_vert, int cd_faceset_offset, struc
|
|||
|
||||
PBVHNode *BKE_pbvh_get_node_leaf_safe(PBVH *pbvh, int i);
|
||||
|
||||
#if 0
|
||||
typedef enum {
|
||||
SCULPT_TEXTURE_UV = 1 << 0, // per-uv
|
||||
// SCULPT_TEXTURE_PTEX?
|
||||
} SculptTextureType;
|
||||
|
||||
typedef int TexLayerRef;
|
||||
|
||||
/*
|
||||
Texture points are texels projected into 3d.
|
||||
*/
|
||||
typedef intptr_t TexPointRef;
|
||||
|
||||
void *BKE_pbvh_get_tex_settings(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm);
|
||||
void *BKE_pbvh_get_tex_data(PBVH *pbvh, PBVHNode *node, TexPointRef vdm);
|
||||
|
||||
typedef struct SculptTextureDef {
|
||||
SculptTextureType type;
|
||||
int settings_size;
|
||||
|
||||
void (*build_begin)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm);
|
||||
|
||||
/*vdms can cache data per node, which is freed to maintain memory limit.
|
||||
they store cache in the same structure they return in buildNodeData.*/
|
||||
void (*freeCachedData)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm);
|
||||
void (*ensuredCachedData)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm);
|
||||
|
||||
/*builds all data that isn't cached.*/
|
||||
void *(*buildNodeData)(PBVH *pbvh, PBVHNode *node);
|
||||
bool (*validate)(PBVH *pbvh, TexLayerRef vdm);
|
||||
|
||||
void (*getPointsFromNode)(PBVH *pbvh,
|
||||
PBVHNode *node,
|
||||
TexLayerRef vdm,
|
||||
TexPointRef **r_ids,
|
||||
float ***r_cos,
|
||||
float ***r_nos,
|
||||
int *r_totpoint);
|
||||
void (*releaseNodePoints)(
|
||||
PBVH *pbvh, PBVHNode *node, TexLayerRef vdm, TexPointRef *ids, float **cos, float **nos);
|
||||
|
||||
# if 0
|
||||
int (*getTrisFromNode)(PBVH *pbvh,
|
||||
PBVHNode *node,
|
||||
TexLayerRef vdm,
|
||||
TexPointRef *((*r_tris)[3]),
|
||||
TexPointRef **r_ids,
|
||||
int tottri,
|
||||
int totid);
|
||||
void (*getTriInterpWeightsFromNode)(PBVH *pbvh,
|
||||
PBVHNode *node,
|
||||
TexLayerRef vdm,
|
||||
float *((*r_tris)[3]),
|
||||
SculptLoopRef ***r_src_loops,
|
||||
int tottri,
|
||||
int totloop);
|
||||
int (*getTriCount)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm);
|
||||
# endif
|
||||
|
||||
void (*getPointNeighbors)(PBVH *pbvh,
|
||||
PBVHNode *node,
|
||||
TexLayerRef vdm,
|
||||
TexPointRef id,
|
||||
TexPointRef **r_neighbor_ids,
|
||||
int *r_totneighbor,
|
||||
int maxneighbors,
|
||||
TexPointRef **r_duplicates_id,
|
||||
int r_totduplicate,
|
||||
int maxduplicates);
|
||||
void (*getPointValence)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm, TexPointRef id);
|
||||
void (*freeNodeData)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm, void *settings);
|
||||
|
||||
void (*getPointsFromIds)(
|
||||
PBVH *pbvh, PBVHNode *node, TexLayerRef vdm, TexPointRef *ids, int totid);
|
||||
|
||||
/*displacement texture stuff*/
|
||||
// can be tangent, object space displacement, whatever
|
||||
void (*worldToDelta)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm, TexPointRef *ids, int totid);
|
||||
void (*deltaToWorld)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm, TexPointRef *ids, int totid);
|
||||
} SculptDisplacementDef;
|
||||
|
||||
typedef struct SculptLayerEntry {
|
||||
char name[64];
|
||||
int type;
|
||||
void *settings;
|
||||
float factor;
|
||||
struct SculptLayerEntry *parent;
|
||||
} SculptLayerEntry;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -235,6 +235,7 @@ set(SRC
|
|||
intern/particle_system.c
|
||||
intern/pbvh.c
|
||||
intern/pbvh_bmesh.c
|
||||
intern/pbvh_displacement.c
|
||||
intern/pointcache.c
|
||||
intern/pointcloud.cc
|
||||
intern/preferences.c
|
||||
|
@ -792,3 +793,74 @@ if(WITH_GTESTS)
|
|||
include(GTestTesting)
|
||||
blender_add_test_lib(bf_blenkernel_tests "${TEST_SRC}" "${INC};${TEST_INC}" "${INC_SYS}" "${LIB}")
|
||||
endif()
|
||||
|
||||
|
||||
set(PBVH_CACHE_TEST_INC
|
||||
.
|
||||
../blenfont
|
||||
../blenlib
|
||||
../blenloader
|
||||
../blentranslation
|
||||
../bmesh
|
||||
../depsgraph
|
||||
../draw
|
||||
../functions
|
||||
../gpencil_modifiers
|
||||
../gpu
|
||||
../ikplugin
|
||||
../imbuf
|
||||
../makesdna
|
||||
../makesrna
|
||||
../modifiers
|
||||
../nodes
|
||||
../render
|
||||
../sequencer
|
||||
../shader_fx
|
||||
../simulation
|
||||
../../../intern/eigen
|
||||
../../../intern/ghost
|
||||
../../../intern/glew-mx
|
||||
../../../intern/guardedalloc
|
||||
../../../intern/iksolver/extern
|
||||
../../../intern/atomic
|
||||
../../../intern/clog
|
||||
../../../intern/libmv
|
||||
../../../intern/mantaflow/extern
|
||||
../../../intern/memutil
|
||||
../../../intern/mikktspace
|
||||
../../../intern/opensubdiv
|
||||
../../../extern/curve_fit_nd
|
||||
)
|
||||
|
||||
set(PBVH_CACHE_TEST_SRC
|
||||
intern/pbvh_cache_test_main.c
|
||||
)
|
||||
|
||||
setup_libdirs()
|
||||
|
||||
add_executable(pbvh_cache_test ${PBVH_CACHE_TEST_SRC} ${PBVH_CACHE_TEST_INC})
|
||||
setup_platform_linker_flags(pbvh_cache_test)
|
||||
|
||||
target_link_libraries(pbvh_cache_test bf_blenkernel bf_bmesh bf_intern_ghost bf_blenlib bf_intern_guardedalloc)
|
||||
|
||||
if(WIN32)
|
||||
set_target_properties(pbvh_cache_test PROPERTIES VS_GLOBAL_VcpkgEnabled "false")
|
||||
set_target_properties(pbvh_cache_test PROPERTIES
|
||||
PDB_NAME "pbvh_cache_test_private"
|
||||
PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>")
|
||||
if(WITH_WINDOWS_PDB AND WITH_WINDOWS_STRIPPED_PDB)
|
||||
# This is slightly messy, but single target generators like ninja will not have the
|
||||
# CMAKE_CFG_INTDIR variable and multitarget generators like msbuild will not have
|
||||
# CMAKE_BUILD_TYPE. This can be simplified by target_link_options and the $<CONFIG>
|
||||
# generator expression in newer cmake (2.13+) but until that time this fill have suffice.
|
||||
if(CMAKE_BUILD_TYPE)
|
||||
set_property(TARGET pbvh_cache_test APPEND_STRING PROPERTY LINK_FLAGS " /PDBSTRIPPED:${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/pbvh_cache_test_public.pdb")
|
||||
else()
|
||||
set_property(TARGET pbvh_cache_test APPEND_STRING PROPERTY LINK_FLAGS " /PDBSTRIPPED:${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/pbvh_cache_test_public.pdb")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(pbvh_cache_test Vfw32.lib Imm32.lib Version.lib Comctl32.lib Shcore.lib Pathcch.lib)
|
||||
endif()
|
||||
|
|
|
@ -292,6 +292,12 @@ void multiresModifier_base_apply(struct Depsgraph *depsgraph,
|
|||
multires_reshape_apply_base_update_mesh_coords(&reshape_context);
|
||||
multires_reshape_apply_base_refit_base_mesh(&reshape_context);
|
||||
|
||||
/**
|
||||
* Tag update so deform modifiers (e.g. smooth corrective)
|
||||
* get updated original coordinates
|
||||
*/
|
||||
DEG_id_tag_update((ID *)object, ID_RECALC_GEOMETRY);
|
||||
|
||||
/* Reshape to the stored final state.
|
||||
* Not that the base changed, so the subdiv is to be refined to the new positions. Unfortunately,
|
||||
* this can not be done foe entirely cheap: if there were deformation modifiers prior to the
|
||||
|
|
|
@ -315,6 +315,8 @@ void multires_reshape_free_original_grids(MultiresReshapeContext *reshape_contex
|
|||
|
||||
void multires_reshape_context_free(MultiresReshapeContext *reshape_context)
|
||||
{
|
||||
ModifierData *md;
|
||||
|
||||
if (reshape_context->need_free_subdiv) {
|
||||
BKE_subdiv_free(reshape_context->subdiv);
|
||||
}
|
||||
|
|
|
@ -3395,3 +3395,190 @@ BMesh *BKE_pbvh_reorder_bmesh1(PBVH *pbvh)
|
|||
|
||||
return pbvh->bm;
|
||||
}
|
||||
|
||||
// only floats! and 8 byte aligned!
|
||||
typedef struct CacheParams {
|
||||
float vchunk, echunk, lchunk, pchunk;
|
||||
int cluster_steps, cluster_size;
|
||||
} CacheParams;
|
||||
|
||||
typedef struct CacheParamDef {
|
||||
char name[32];
|
||||
float defvalue, min, max;
|
||||
} CacheParamDef;
|
||||
|
||||
CacheParamDef pbvh_bmesh_cache_param_def[] = {{"vchunk", 512.0f, 256.0f, 1024.0f * 12.0f},
|
||||
{"echunk", 512.0f, 256.0f, 1024.0f * 12.0f},
|
||||
{"lchunk", 512.0f, 256.0f, 1024.0f * 12.0f},
|
||||
{"pchunk", 512.0f, 256.0f, 1024.0f * 12.0f},
|
||||
{"cluster_steps", 512.0f, 1.0f, 256.0f},
|
||||
{"cluster_size", 512.0f, 1.0f, 8192.0f * 32.0f}};
|
||||
|
||||
int pbvh_bmesh_cache_test_totparams()
|
||||
{
|
||||
return sizeof(pbvh_bmesh_cache_param_def) / sizeof(*pbvh_bmesh_cache_param_def);
|
||||
}
|
||||
|
||||
void pbvh_bmesh_cache_test_default_params(CacheParams *params)
|
||||
{
|
||||
float *fparams = (float *)params;
|
||||
int totparam = pbvh_bmesh_cache_test_totparams();
|
||||
|
||||
for (int i = 0; i < totparam; i++) {
|
||||
fparams[i] = pbvh_bmesh_cache_param_def[i].defvalue;
|
||||
}
|
||||
}
|
||||
|
||||
static void *hashco(float fx, float fy, float fz, float fdimen)
|
||||
{
|
||||
double x = (double)fx;
|
||||
double y = (double)fy;
|
||||
double z = (double)fz;
|
||||
double dimen = (double)dimen;
|
||||
|
||||
return (void *)((intptr_t)(z * dimen * dimen + y * dimen + x));
|
||||
}
|
||||
|
||||
void pbvh_bmesh_cache_test(CacheParams *params, BMesh **r_bm, PBVH **r_pbvh_out)
|
||||
{
|
||||
// build mesh
|
||||
const int steps = 256;
|
||||
|
||||
BMAllocTemplate templ = {0, 0, 0, 0};
|
||||
|
||||
BMesh *bm = BM_mesh_create(&templ,
|
||||
&((struct BMeshCreateParams){.use_id_elem_mask = BM_VERT | BM_FACE,
|
||||
.use_id_map = true,
|
||||
.use_unique_ids = true}));
|
||||
|
||||
// reinit pools
|
||||
BLI_mempool_destroy(bm->vpool);
|
||||
BLI_mempool_destroy(bm->epool);
|
||||
BLI_mempool_destroy(bm->lpool);
|
||||
BLI_mempool_destroy(bm->fpool);
|
||||
|
||||
bm->vpool = BLI_mempool_create(sizeof(BMVert), 0, (int)params->vchunk, BLI_MEMPOOL_ALLOW_ITER);
|
||||
bm->epool = BLI_mempool_create(sizeof(BMEdge), 0, (int)params->vchunk, BLI_MEMPOOL_ALLOW_ITER);
|
||||
bm->lpool = BLI_mempool_create(sizeof(BMLoop), 0, (int)params->vchunk, BLI_MEMPOOL_ALLOW_ITER);
|
||||
bm->fpool = BLI_mempool_create(sizeof(BMFace), 0, (int)params->vchunk, BLI_MEMPOOL_ALLOW_ITER);
|
||||
|
||||
GHash *vhash = BLI_ghash_ptr_new("vhash");
|
||||
|
||||
float df = 1.0f / (float)steps;
|
||||
float u, v;
|
||||
|
||||
int hashdimen = steps * 8;
|
||||
|
||||
BMVert **grid = MEM_malloc_arrayN(steps * steps, sizeof(*grid), "bmvert grid");
|
||||
|
||||
BM_data_layer_add_named(bm, &bm->vdata, CD_PROP_INT32, "__dyntopo_vert_node");
|
||||
BM_data_layer_add_named(bm, &bm->vdata, CD_PROP_INT32, "__dyntopo_face_node");
|
||||
BM_data_layer_add(bm, &bm->vdata, CD_SCULPT_FACE_SETS);
|
||||
BM_data_layer_add(bm, &bm->vdata, CD_PAINT_MASK);
|
||||
BM_data_layer_add(bm, &bm->vdata, CD_DYNTOPO_VERT);
|
||||
BM_data_layer_add(bm, &bm->vdata, CD_PROP_COLOR);
|
||||
|
||||
for (int side = 0; side < 6; side++) {
|
||||
int axis = side > 3 ? side - 3 : side;
|
||||
float sign = side > 3 ? -1.0f : 1.0f;
|
||||
|
||||
for (int i = 0, u = 0; i < steps; i++, u += df) {
|
||||
for (int j = 0, v = 0; j < steps; j++, v += df) {
|
||||
float co[3];
|
||||
|
||||
co[axis] = u;
|
||||
co[(axis + 1) % 3] = v;
|
||||
co[(axis + 2) % 3] = sign;
|
||||
|
||||
// turn into sphere
|
||||
normalize_v3(co);
|
||||
|
||||
void *key = hashco(co[0], co[1], co[2], hashdimen);
|
||||
void **val = NULL;
|
||||
|
||||
if (!BLI_ghash_ensure_p(vhash, key, &val)) {
|
||||
BMVert *v = BM_vert_create(bm, co, NULL, BM_CREATE_NOP);
|
||||
|
||||
*val = (void *)v;
|
||||
}
|
||||
|
||||
BMVert *v = (BMVert *)*val;
|
||||
int idx = j * steps + i;
|
||||
|
||||
grid[idx] = v;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < steps - 1; i++) {
|
||||
for (int j = 0; j < steps - 1; j++) {
|
||||
int idx1 = j * steps + i;
|
||||
int idx2 = (j + 1) * steps + i;
|
||||
int idx3 = (j + 1) * steps + i + 1;
|
||||
int idx4 = j * steps + i + 1;
|
||||
|
||||
BMVert *v1 = grid[idx1];
|
||||
BMVert *v2 = grid[idx2];
|
||||
BMVert *v3 = grid[idx3];
|
||||
BMVert *v4 = grid[idx4];
|
||||
|
||||
if (sign < 0) {
|
||||
BMVert *vs[4] = {v4, v3, v2, v1};
|
||||
BM_face_create_verts(bm, vs, 4, NULL, BM_CREATE_NOP, true);
|
||||
}
|
||||
else {
|
||||
BMVert *vs[4] = {v1, v2, v3, v4};
|
||||
BM_face_create_verts(bm, vs, 4, NULL, BM_CREATE_NOP, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BLI_ghash_free(vhash, NULL, NULL);
|
||||
MEM_SAFE_FREE(grid);
|
||||
|
||||
printf("totvert: %d, totface: %d, tottri: %d\n", bm->totvert, bm->totface, bm->totface * 2);
|
||||
|
||||
int cd_vert_node = CustomData_get_named_layer_index(
|
||||
&bm->vdata, CD_PROP_INT32, "__dyntopo_vert_node");
|
||||
int cd_face_node = CustomData_get_named_layer_index(
|
||||
&bm->vdata, CD_PROP_INT32, "__dyntopo_face_node");
|
||||
|
||||
cd_vert_node = bm->vdata.layers[cd_vert_node].offset;
|
||||
cd_face_node = bm->vdata.layers[cd_face_node].offset;
|
||||
|
||||
const int cd_fset = CustomData_get_offset(&bm->vdata, CD_SCULPT_FACE_SETS);
|
||||
const int cd_dyn_vert = CustomData_get_offset(&bm->vdata, CD_DYNTOPO_VERT);
|
||||
const int cd_mask = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
|
||||
const int cd_vcol = CustomData_get_offset(&bm->vdata, CD_PROP_COLOR);
|
||||
BMLog *bmlog = BM_log_create(bm, cd_dyn_vert);
|
||||
|
||||
PBVH *pbvh = BKE_pbvh_new();
|
||||
|
||||
BKE_pbvh_build_bmesh(pbvh, bm, false, bmlog, cd_vert_node, cd_face_node, cd_dyn_vert, false);
|
||||
BKE_pbvh_reorder_bmesh(pbvh);
|
||||
|
||||
if (r_bm) {
|
||||
*r_bm = bm;
|
||||
}
|
||||
else {
|
||||
BM_mesh_free(bm);
|
||||
}
|
||||
|
||||
if (r_pbvh_out) {
|
||||
*r_pbvh_out = pbvh;
|
||||
}
|
||||
else {
|
||||
BKE_pbvh_free(pbvh);
|
||||
}
|
||||
}
|
||||
|
||||
ATTR_NO_OPT void pbvh_bmesh_do_cache_test()
|
||||
{
|
||||
BMesh *bm;
|
||||
PBVH *pbvh;
|
||||
|
||||
CacheParams params;
|
||||
|
||||
pbvh_bmesh_cache_test_default_params(¶ms);
|
||||
pbvh_bmesh_cache_test(¶ms, &bm, &pbvh);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_compiler_compat.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_pbvh.h"
|
||||
|
||||
#include "DNA_customdata_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
|
||||
#include "bmesh.h"
|
||||
#include "pbvh_intern.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
void pbvh_bmesh_do_cache_test(void);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
printf("argc: %d\n", argc);
|
||||
|
||||
pbvh_bmesh_do_cache_test();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,266 @@
|
|||
#if 0
|
||||
# include "MEM_guardedalloc.h"
|
||||
|
||||
# include "BLI_alloca.h"
|
||||
# include "BLI_array.h"
|
||||
# include "BLI_compiler_attrs.h"
|
||||
# include "BLI_compiler_compat.h"
|
||||
# include "BLI_ghash.h"
|
||||
# include "BLI_linklist.h"
|
||||
# include "BLI_math.h"
|
||||
# include "BLI_memarena.h"
|
||||
# include "BLI_memblock.h"
|
||||
# include "BLI_mempool.h"
|
||||
# include "BLI_utildefines.h"
|
||||
|
||||
# include "BLI_hash.h"
|
||||
|
||||
# include "BKE_context.h"
|
||||
# include "BKE_global.h"
|
||||
# include "BKE_image.h"
|
||||
# include "BKE_mesh.h"
|
||||
# include "BKE_multires.h"
|
||||
# include "BKE_object.h"
|
||||
# include "BKE_pbvh.h"
|
||||
# include "BKE_scene.h"
|
||||
|
||||
# include "BLI_bitmap.h"
|
||||
# include "DNA_customdata_types.h"
|
||||
# include "DNA_image_types.h"
|
||||
# include "DNA_material_types.h"
|
||||
# include "DNA_mesh_types.h"
|
||||
# include "DNA_meshdata_types.h"
|
||||
# include "DNA_object_types.h"
|
||||
# include "DNA_scene_types.h"
|
||||
|
||||
# include "pbvh_intern.h"
|
||||
|
||||
# include "bmesh.h"
|
||||
|
||||
void *BKE_pbvh_get_tex_settings(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm)
|
||||
{
|
||||
return NULL; // implement me!
|
||||
}
|
||||
|
||||
void *BKE_pbvh_get_tex_data(PBVH *pbvh, PBVHNode *node, TexPointRef vdm)
|
||||
{
|
||||
return NULL; // implement me!
|
||||
}
|
||||
|
||||
typedef union TexelKey {
|
||||
struct {
|
||||
int idx; // index in image
|
||||
int co_key; // used to differentiate same texel used in different 3d points in space
|
||||
} key;
|
||||
intptr_t i;
|
||||
} TexelKey;
|
||||
|
||||
BLI_INLINE int calc_co_key(const float *co)
|
||||
{
|
||||
const int mul = 65535;
|
||||
const int mask = 65535;
|
||||
|
||||
int x = (int)co[0] + (((int)co[0] * mul) & mask);
|
||||
int y = (int)co[0] + (((int)co[0] * mul) & mask);
|
||||
int z = (int)co[0] + (((int)co[0] * mul) & mask);
|
||||
|
||||
return BLI_hash_int_3d(x, y, z);
|
||||
}
|
||||
|
||||
typedef struct TextureVDMSettings {
|
||||
ImageUser ima_user;
|
||||
ID *image;
|
||||
bool tangent_space;
|
||||
|
||||
char uv_layer[64];
|
||||
|
||||
// used by texture_vdm_get_points
|
||||
// BLI_bitmap *texel_used_map;
|
||||
GSet *texel_used_map;
|
||||
|
||||
int width, height;
|
||||
bool invalid;
|
||||
} TextureVDMSettings;
|
||||
|
||||
typedef struct TextureNodeData {
|
||||
TexPointRef *point_ids;
|
||||
float (*point_cos)[3];
|
||||
float (*point_uvs)[2];
|
||||
float **point_cos_ptrs;
|
||||
int totpoint;
|
||||
} TextureNodeData;
|
||||
|
||||
void texture_vdm_begin(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm)
|
||||
{
|
||||
TextureVDMSettings *settings = BKE_pbvh_get_tex_settings(pbvh, node, vdm);
|
||||
|
||||
if (!settings->image) {
|
||||
return;
|
||||
}
|
||||
|
||||
Image *image = (Image *)settings->image;
|
||||
|
||||
int w = 0, h = 0;
|
||||
BKE_image_get_size(image, &settings->ima_user, &w, &h);
|
||||
|
||||
// Image *image = settings->image.
|
||||
settings->width = w;
|
||||
settings->height = h;
|
||||
// settings->texel_used_map = BLI_BITMAP_NEW(w * h, "texel_used_map");
|
||||
settings->texel_used_map = BLI_gset_ptr_new("texel_used_map");
|
||||
}
|
||||
|
||||
void texture_vdm_build_points(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm)
|
||||
{
|
||||
TextureVDMSettings *settings = BKE_pbvh_get_tex_settings(pbvh, node, vdm);
|
||||
TextureNodeData *data = BKE_pbvh_get_tex_data(pbvh, node, vdm);
|
||||
|
||||
int idx;
|
||||
|
||||
if (!settings->uv_layer[0]) {
|
||||
idx = CustomData_get_layer_index(&pbvh->bm->ldata, CD_MLOOPUV);
|
||||
}
|
||||
else {
|
||||
idx = CustomData_get_named_layer_index(&pbvh->bm->ldata, CD_MLOOPUV, settings->uv_layer);
|
||||
}
|
||||
|
||||
if (idx < 0) {
|
||||
settings->invalid = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const int cd_uv = pbvh->bm->ldata.layers[idx].offset;
|
||||
const int w = settings->width, h = settings->height;
|
||||
|
||||
float **point_cos_ptrs = NULL;
|
||||
float *uvs = NULL;
|
||||
float *cos = NULL;
|
||||
TexPointRef *ids = NULL;
|
||||
|
||||
BLI_array_declare(point_cos_ptrs);
|
||||
BLI_array_declare(uvs);
|
||||
BLI_array_declare(cos);
|
||||
BLI_array_declare(ids);
|
||||
|
||||
for (int i = 0; i < node->tribuf->tottri; i++) {
|
||||
PBVHTri *tri = node->tribuf->tris + i;
|
||||
|
||||
BMLoop *ls[3] = {(BMLoop *)tri->l[0], (BMLoop *)tri->l[1], (BMLoop *)tri->l[2]};
|
||||
float min[2] = {FLT_MAX, FLT_MAX}, max[2] = {FLT_MIN, FLT_MIN};
|
||||
|
||||
float tricos[3][3];
|
||||
|
||||
copy_v3_v3(tricos[0], ls[0]->v->co);
|
||||
copy_v3_v3(tricos[1], ls[1]->v->co);
|
||||
copy_v3_v3(tricos[2], ls[2]->v->co);
|
||||
|
||||
for (int j = 0; j < 3; j++) {
|
||||
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(ls[j], cd_uv);
|
||||
minmax_v2v2_v2(min, max, luv->uv);
|
||||
}
|
||||
|
||||
int dw = (int)((max[0] - min[0]) * (float)w + 0.000001f);
|
||||
int dh = (int)((max[1] - min[1]) * (float)h + 0.000001f);
|
||||
|
||||
dw = MAX2(dw, 1);
|
||||
dh = MAX2(dh, 1);
|
||||
|
||||
float du = (max[0] - min[0]) / dw;
|
||||
float dv = (max[1] - min[1]) / dh;
|
||||
|
||||
float u = min[0], v = min[1];
|
||||
for (int y = 0; y < dh; y++, v += dv) {
|
||||
u = min[0];
|
||||
|
||||
for (int x = 0; x < dw; x++, u += du) {
|
||||
int idx = y * w + x;
|
||||
float co[3];
|
||||
|
||||
interp_barycentric_tri_v3(tricos, u, v, co);
|
||||
|
||||
TexelKey key;
|
||||
key.key.idx = idx;
|
||||
key.key.co_key = calc_co_key(co);
|
||||
|
||||
if (BLI_gset_haskey(settings->texel_used_map, (void *)key.i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BLI_gset_insert(settings->texel_used_map, (void *)key.i);
|
||||
|
||||
BLI_array_append(uvs, u);
|
||||
BLI_array_append(uvs, v);
|
||||
|
||||
BLI_array_append(cos, co[0]);
|
||||
BLI_array_append(cos, co[1]);
|
||||
BLI_array_append(cos, co[2]);
|
||||
BLI_array_append(ids, (TexPointRef)key.i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
settings->invalid = false;
|
||||
MEM_SAFE_FREE(data->point_cos);
|
||||
MEM_SAFE_FREE(data->point_ids);
|
||||
MEM_SAFE_FREE(data->point_uvs);
|
||||
MEM_SAFE_FREE(data->point_cos_ptrs);
|
||||
|
||||
int totpoint = BLI_array_len(ids);
|
||||
|
||||
data->totpoint = totpoint;
|
||||
|
||||
data->point_cos_ptrs = MEM_malloc_arrayN(totpoint, sizeof(void *), "point_cos_ptrs");
|
||||
|
||||
// dumb casting trick
|
||||
union {
|
||||
float *cos;
|
||||
float (*cos3)[3];
|
||||
} castcos;
|
||||
|
||||
union {
|
||||
float *uvs;
|
||||
float (*uvs2)[2];
|
||||
} castuvs;
|
||||
|
||||
castcos.cos = cos;
|
||||
castuvs.uvs = uvs;
|
||||
|
||||
data->point_cos = castcos.cos3;
|
||||
data->point_ids = ids;
|
||||
data->point_uvs = castuvs.uvs2;
|
||||
|
||||
for (int i = 0; i < totpoint; i++) {
|
||||
data->point_cos_ptrs[i] = cos + i * 3;
|
||||
}
|
||||
}
|
||||
|
||||
void texture_vdm_get_points(PBVH *pbvh,
|
||||
PBVHNode *node,
|
||||
TexLayerRef vdm,
|
||||
TexPointRef **r_ids,
|
||||
float ***r_cos,
|
||||
float ***r_nos,
|
||||
int *r_totpoint)
|
||||
{
|
||||
TextureVDMSettings *settings = BKE_pbvh_get_tex_settings(pbvh, node, vdm);
|
||||
TextureNodeData *data = BKE_pbvh_get_tex_data(pbvh, node, vdm);
|
||||
|
||||
if (r_totpoint) {
|
||||
*r_totpoint = data->totpoint;
|
||||
}
|
||||
|
||||
if (r_cos) {
|
||||
*r_cos = data->point_cos_ptrs;
|
||||
}
|
||||
|
||||
if (r_ids) {
|
||||
*r_ids = data->point_ids;
|
||||
}
|
||||
}
|
||||
|
||||
static SculptDisplacementDef texture_vdm = {
|
||||
.type = SCULPT_TEXTURE_UV,
|
||||
.settings_size = sizeof(TextureNodeData),
|
||||
.getPointsFromNode = texture_vdm_get_points,
|
||||
};
|
||||
#endif
|
|
@ -77,6 +77,8 @@ set(SRC
|
|||
sculpt_transform.c
|
||||
sculpt_undo.c
|
||||
sculpt_uv.c
|
||||
sculpt_displacement.c
|
||||
sculpt_displacement.h
|
||||
|
||||
paint_intern.h
|
||||
sculpt_intern.h
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1 @@
|
|||
#pragma once
|
|
@ -614,13 +614,13 @@ static void calc_deltas(CorrectiveSmoothModifierData *csmd,
|
|||
MEM_freeN(smooth_vertex_coords);
|
||||
}
|
||||
|
||||
static void correctivesmooth_modifier_do(ModifierData *md,
|
||||
Depsgraph *depsgraph,
|
||||
Object *ob,
|
||||
Mesh *mesh,
|
||||
float (*vertexCos)[3],
|
||||
uint numVerts,
|
||||
struct BMEditMesh *em)
|
||||
ATTR_NO_OPT static void correctivesmooth_modifier_do(ModifierData *md,
|
||||
Depsgraph *depsgraph,
|
||||
Object *ob,
|
||||
Mesh *mesh,
|
||||
float (*vertexCos)[3],
|
||||
uint numVerts,
|
||||
struct BMEditMesh *em)
|
||||
{
|
||||
CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)md;
|
||||
|
||||
|
|
|
@ -200,6 +200,16 @@ static void bpy_msgbus_subscribe_value_free_data(struct wmMsgSubscribeKey *UNUSE
|
|||
|
||||
/** \} */
|
||||
|
||||
extern void pbvh_bmesh_do_cache_test();
|
||||
|
||||
PyDoc_STRVAR(exec_bmesh_cache_test_doc, "internal development function\n");
|
||||
static PyObject *exec_bmesh_cache_test(PyObject *self)
|
||||
{
|
||||
pbvh_bmesh_do_cache_test();
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Public Message Bus API
|
||||
* \{ */
|
||||
|
@ -378,6 +388,10 @@ static struct PyMethodDef BPy_msgbus_methods[] = {
|
|||
(PyCFunction)bpy_msgbus_clear_by_owner,
|
||||
METH_O,
|
||||
bpy_msgbus_clear_by_owner_doc},
|
||||
{"pbvh_bmesh_do_cache_test",
|
||||
(PyCFunction)exec_bmesh_cache_test,
|
||||
METH_NOARGS,
|
||||
exec_bmesh_cache_test_doc},
|
||||
{NULL, NULL, 0, NULL},
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue