Merge branch 'master' into asset-browser-grid-view
This commit is contained in:
commit
8f48dd8f72
|
@ -1485,7 +1485,8 @@ class CyclesPreferences(bpy.types.AddonPreferences):
|
|||
if sys.platform[:3] == "win":
|
||||
col.label(text="and AMD Radeon Pro 21.Q4 driver or newer", icon='BLANK1')
|
||||
elif device_type == 'METAL':
|
||||
col.label(text="Requires Apple Silicon and macOS 12.0 or newer", icon='BLANK1')
|
||||
col.label(text="Requires Apple Silicon with macOS 12.2 or newer", icon='BLANK1')
|
||||
col.label(text="or AMD with macOS 12.3 or newer", icon='BLANK1')
|
||||
return
|
||||
|
||||
for device in devices:
|
||||
|
|
|
@ -97,7 +97,10 @@ void Session::start()
|
|||
{
|
||||
/* Signal session thread to start rendering. */
|
||||
thread_scoped_lock session_thread_lock(session_thread_mutex_);
|
||||
assert(session_thread_state_ == SESSION_THREAD_WAIT);
|
||||
if (session_thread_state_ == SESSION_THREAD_RENDER) {
|
||||
/* Already rendering, nothing to do. */
|
||||
return;
|
||||
}
|
||||
session_thread_state_ = SESSION_THREAD_RENDER;
|
||||
}
|
||||
|
||||
|
|
|
@ -1696,10 +1696,12 @@ static bool lib_override_library_resync(Main *bmain,
|
|||
|
||||
BKE_id_multi_tagged_delete(bmain);
|
||||
|
||||
/* At this point, `id_root` has very likely been deleted, we need to update it to its new
|
||||
* version.
|
||||
/* At this point, `id_root` may have been resynced, therefore deleted. In that case we need to
|
||||
* update it to its new version.
|
||||
*/
|
||||
id_root = id_root_reference->newid;
|
||||
if (id_root_reference->newid != NULL) {
|
||||
id_root = id_root_reference->newid;
|
||||
}
|
||||
|
||||
if (user_edited_overrides_deletion_count > 0) {
|
||||
BKE_reportf(reports != NULL ? reports->reports : NULL,
|
||||
|
|
|
@ -1037,7 +1037,12 @@ static Mesh *mesh_new_from_mesh(Object *object, Mesh *mesh)
|
|||
{
|
||||
/* While we could copy this into the new mesh,
|
||||
* add the data to 'mesh' so future calls to this function don't need to re-convert the data. */
|
||||
BKE_mesh_wrapper_ensure_mdata(mesh);
|
||||
if (mesh->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) {
|
||||
BKE_mesh_wrapper_ensure_mdata(mesh);
|
||||
}
|
||||
else {
|
||||
BKE_mesh_wrapper_ensure_subdivision(object, mesh);
|
||||
}
|
||||
|
||||
Mesh *mesh_result = (Mesh *)BKE_id_copy_ex(
|
||||
nullptr, &mesh->id, nullptr, LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT);
|
||||
|
@ -1074,6 +1079,7 @@ static Mesh *mesh_new_from_mesh_object_with_layers(Depsgraph *depsgraph,
|
|||
mask.pmask |= CD_MASK_ORIGINDEX;
|
||||
}
|
||||
Mesh *result = mesh_create_eval_final(depsgraph, scene, &object_for_eval, &mask);
|
||||
BKE_mesh_wrapper_ensure_subdivision(object, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#pragma once
|
||||
|
||||
struct DRWSubdivCache;
|
||||
struct MeshRenderData;
|
||||
struct TaskGraph;
|
||||
|
||||
#include "DNA_customdata_types.h"
|
||||
|
@ -332,7 +333,7 @@ void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
|
|||
void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache,
|
||||
MeshBufferCache *mbc,
|
||||
struct DRWSubdivCache *subdiv_cache,
|
||||
const struct ToolSettings *ts);
|
||||
struct MeshRenderData *mr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -776,7 +776,7 @@ static void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
|
|||
static void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache,
|
||||
MeshBufferCache *mbc,
|
||||
DRWSubdivCache *subdiv_cache,
|
||||
const ToolSettings *ts)
|
||||
MeshRenderData *mr)
|
||||
{
|
||||
/* Create an array containing all the extractors that needs to be executed. */
|
||||
ExtractorRunDatas extractors;
|
||||
|
@ -832,10 +832,7 @@ static void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache,
|
|||
return;
|
||||
}
|
||||
|
||||
MeshRenderData mr;
|
||||
memset(&mr, 0, sizeof(MeshRenderData));
|
||||
draw_subdiv_init_mesh_render_data(subdiv_cache, &mr, ts);
|
||||
mesh_render_data_update_loose_geom(&mr, mbc, MR_ITER_LEDGE | MR_ITER_LVERT, MR_DATA_LOOSE_GEOM);
|
||||
mesh_render_data_update_loose_geom(mr, mbc, MR_ITER_LEDGE | MR_ITER_LVERT, MR_DATA_LOOSE_GEOM);
|
||||
|
||||
void *data_stack = MEM_mallocN(extractors.data_size_total(), __func__);
|
||||
uint32_t data_offset = 0;
|
||||
|
@ -844,17 +841,17 @@ static void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache,
|
|||
void *buffer = mesh_extract_buffer_get(extractor, mbuflist);
|
||||
void *data = POINTER_OFFSET(data_stack, data_offset);
|
||||
|
||||
extractor->init_subdiv(subdiv_cache, &mr, cache, buffer, data);
|
||||
extractor->init_subdiv(subdiv_cache, mr, cache, buffer, data);
|
||||
|
||||
if (extractor->iter_subdiv_mesh || extractor->iter_subdiv_bm) {
|
||||
int *subdiv_loop_poly_index = subdiv_cache->subdiv_loop_poly_index;
|
||||
if (subdiv_cache->bm) {
|
||||
if (mr->extract_type == MR_EXTRACT_BMESH) {
|
||||
for (uint i = 0; i < subdiv_cache->num_subdiv_quads; i++) {
|
||||
/* Multiply by 4 to have the start index of the quad's loop, as subdiv_loop_poly_index is
|
||||
* based on the subdivision loops. */
|
||||
const int poly_origindex = subdiv_loop_poly_index[i * 4];
|
||||
const BMFace *efa = bm_original_face_get(&mr, poly_origindex);
|
||||
extractor->iter_subdiv_bm(subdiv_cache, &mr, data, i, efa);
|
||||
const BMFace *efa = BM_face_at_index(mr->bm, poly_origindex);
|
||||
extractor->iter_subdiv_bm(subdiv_cache, mr, data, i, efa);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -862,18 +859,18 @@ static void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache,
|
|||
/* Multiply by 4 to have the start index of the quad's loop, as subdiv_loop_poly_index is
|
||||
* based on the subdivision loops. */
|
||||
const int poly_origindex = subdiv_loop_poly_index[i * 4];
|
||||
const MPoly *mp = &mr.mpoly[poly_origindex];
|
||||
extractor->iter_subdiv_mesh(subdiv_cache, &mr, data, i, mp);
|
||||
const MPoly *mp = &mr->mpoly[poly_origindex];
|
||||
extractor->iter_subdiv_mesh(subdiv_cache, mr, data, i, mp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (extractor->iter_loose_geom_subdiv) {
|
||||
extractor->iter_loose_geom_subdiv(subdiv_cache, &mr, &mbc->loose_geom, buffer, data);
|
||||
extractor->iter_loose_geom_subdiv(subdiv_cache, mr, &mbc->loose_geom, buffer, data);
|
||||
}
|
||||
|
||||
if (extractor->finish_subdiv) {
|
||||
extractor->finish_subdiv(subdiv_cache, &mr, cache, buffer, data);
|
||||
extractor->finish_subdiv(subdiv_cache, mr, cache, buffer, data);
|
||||
}
|
||||
}
|
||||
MEM_freeN(data_stack);
|
||||
|
@ -921,9 +918,9 @@ void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
|
|||
void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache,
|
||||
MeshBufferCache *mbc,
|
||||
DRWSubdivCache *subdiv_cache,
|
||||
const ToolSettings *ts)
|
||||
MeshRenderData *mr)
|
||||
{
|
||||
blender::draw::mesh_buffer_cache_create_requested_subdiv(cache, mbc, subdiv_cache, ts);
|
||||
blender::draw::mesh_buffer_cache_create_requested_subdiv(cache, mbc, subdiv_cache, mr);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
|
|
@ -2062,7 +2062,20 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
|
|||
}
|
||||
|
||||
if (do_subdivision) {
|
||||
DRW_create_subdivision(scene, ob, me, cache, &cache->final, ts);
|
||||
DRW_create_subdivision(scene,
|
||||
ob,
|
||||
me,
|
||||
cache,
|
||||
&cache->final,
|
||||
is_editmode,
|
||||
is_paint_mode,
|
||||
is_mode_active,
|
||||
ob->obmat,
|
||||
true,
|
||||
false,
|
||||
use_subsurf_fdots,
|
||||
ts,
|
||||
use_hide);
|
||||
}
|
||||
else {
|
||||
/* The subsurf modifier may have been recently removed, or another modifier was added after it,
|
||||
|
|
|
@ -552,7 +552,6 @@ void draw_subdiv_cache_free(DRWSubdivCache *cache)
|
|||
GPU_VERTBUF_DISCARD_SAFE(cache->extra_coarse_face_data);
|
||||
MEM_SAFE_FREE(cache->subdiv_loop_subdiv_vert_index);
|
||||
MEM_SAFE_FREE(cache->subdiv_loop_poly_index);
|
||||
MEM_SAFE_FREE(cache->point_indices);
|
||||
MEM_SAFE_FREE(cache->subdiv_polygon_offset);
|
||||
GPU_VERTBUF_DISCARD_SAFE(cache->subdiv_vertex_face_adjacency_offsets);
|
||||
GPU_VERTBUF_DISCARD_SAFE(cache->subdiv_vertex_face_adjacency);
|
||||
|
@ -593,7 +592,9 @@ void draw_subdiv_cache_free(DRWSubdivCache *cache)
|
|||
SUBDIV_COARSE_FACE_FLAG_ACTIVE) \
|
||||
<< SUBDIV_COARSE_FACE_FLAG_OFFSET)
|
||||
|
||||
static void draw_subdiv_cache_update_extra_coarse_face_data(DRWSubdivCache *cache, Mesh *mesh)
|
||||
static void draw_subdiv_cache_update_extra_coarse_face_data(DRWSubdivCache *cache,
|
||||
Mesh *mesh,
|
||||
MeshRenderData *mr)
|
||||
{
|
||||
if (cache->extra_coarse_face_data == nullptr) {
|
||||
cache->extra_coarse_face_data = GPU_vertbuf_calloc();
|
||||
|
@ -602,12 +603,14 @@ static void draw_subdiv_cache_update_extra_coarse_face_data(DRWSubdivCache *cach
|
|||
GPU_vertformat_attr_add(&format, "data", GPU_COMP_U32, 1, GPU_FETCH_INT);
|
||||
}
|
||||
GPU_vertbuf_init_with_format_ex(cache->extra_coarse_face_data, &format, GPU_USAGE_DYNAMIC);
|
||||
GPU_vertbuf_data_alloc(cache->extra_coarse_face_data, mesh->totpoly);
|
||||
GPU_vertbuf_data_alloc(cache->extra_coarse_face_data,
|
||||
mr->extract_type == MR_EXTRACT_BMESH ? cache->bm->totface :
|
||||
mesh->totpoly);
|
||||
}
|
||||
|
||||
uint32_t *flags_data = (uint32_t *)(GPU_vertbuf_get_data(cache->extra_coarse_face_data));
|
||||
|
||||
if (cache->bm) {
|
||||
if (mr->extract_type == MR_EXTRACT_BMESH) {
|
||||
BMesh *bm = cache->bm;
|
||||
BMFace *f;
|
||||
BMIter iter;
|
||||
|
@ -622,13 +625,34 @@ static void draw_subdiv_cache_update_extra_coarse_face_data(DRWSubdivCache *cach
|
|||
if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
|
||||
flag |= SUBDIV_COARSE_FACE_FLAG_SELECT;
|
||||
}
|
||||
if (f == bm->act_face) {
|
||||
if (f == mr->efa_act) {
|
||||
flag |= SUBDIV_COARSE_FACE_FLAG_ACTIVE;
|
||||
}
|
||||
const int loopstart = BM_elem_index_get(f->l_first);
|
||||
flags_data[index] = (uint)(loopstart) | (flag << SUBDIV_COARSE_FACE_FLAG_OFFSET);
|
||||
}
|
||||
}
|
||||
else if (mr->extract_type == MR_EXTRACT_MAPPED) {
|
||||
for (int i = 0; i < mesh->totpoly; i++) {
|
||||
BMFace *f = bm_original_face_get(mr, i);
|
||||
uint32_t flag = 0;
|
||||
|
||||
if (f) {
|
||||
if (BM_elem_flag_test(f, BM_ELEM_SMOOTH)) {
|
||||
flag |= SUBDIV_COARSE_FACE_FLAG_SMOOTH;
|
||||
}
|
||||
if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
|
||||
flag |= SUBDIV_COARSE_FACE_FLAG_SELECT;
|
||||
}
|
||||
if (f == mr->efa_act) {
|
||||
flag |= SUBDIV_COARSE_FACE_FLAG_ACTIVE;
|
||||
}
|
||||
const int loopstart = BM_elem_index_get(f->l_first);
|
||||
flag = (uint)(loopstart) | (flag << SUBDIV_COARSE_FACE_FLAG_OFFSET);
|
||||
}
|
||||
flags_data[i] = flag;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < mesh->totpoly; i++) {
|
||||
uint32_t flag = 0;
|
||||
|
@ -669,6 +693,7 @@ static DRWSubdivCache *mesh_batch_cache_ensure_subdiv_cache(MeshBatchCache *mbc)
|
|||
|
||||
struct DRWCacheBuildingContext {
|
||||
const Mesh *coarse_mesh;
|
||||
const Subdiv *subdiv;
|
||||
const SubdivToMeshSettings *settings;
|
||||
|
||||
DRWSubdivCache *cache;
|
||||
|
@ -679,7 +704,6 @@ struct DRWCacheBuildingContext {
|
|||
int *subdiv_loop_subdiv_vert_index;
|
||||
int *subdiv_loop_edge_index;
|
||||
int *subdiv_loop_poly_index;
|
||||
int *point_indices;
|
||||
|
||||
/* Temporary buffers used during traversal. */
|
||||
int *vert_origindex_map;
|
||||
|
@ -737,20 +761,12 @@ static bool draw_subdiv_topology_info_cb(const SubdivForeachContext *foreach_con
|
|||
cache->subdiv_loop_poly_index = static_cast<int *>(
|
||||
MEM_mallocN(cache->num_subdiv_loops * sizeof(int), "subdiv_loop_poly_index"));
|
||||
|
||||
const int num_coarse_vertices = ctx->coarse_mesh->totvert;
|
||||
cache->point_indices = static_cast<int *>(
|
||||
MEM_mallocN(num_coarse_vertices * sizeof(int), "point_indices"));
|
||||
for (int i = 0; i < num_coarse_vertices; i++) {
|
||||
cache->point_indices[i] = -1;
|
||||
}
|
||||
|
||||
/* Initialize context pointers and temporary buffers. */
|
||||
ctx->patch_coords = (CompressedPatchCoord *)GPU_vertbuf_get_data(cache->patch_coords);
|
||||
ctx->subdiv_loop_vert_index = (int *)GPU_vertbuf_get_data(cache->verts_orig_index);
|
||||
ctx->subdiv_loop_edge_index = (int *)GPU_vertbuf_get_data(cache->edges_orig_index);
|
||||
ctx->subdiv_loop_subdiv_vert_index = cache->subdiv_loop_subdiv_vert_index;
|
||||
ctx->subdiv_loop_poly_index = cache->subdiv_loop_poly_index;
|
||||
ctx->point_indices = cache->point_indices;
|
||||
|
||||
ctx->v_origindex = static_cast<int *>(
|
||||
CustomData_get_layer(&ctx->coarse_mesh->vdata, CD_ORIGINDEX));
|
||||
|
@ -839,17 +855,6 @@ static void draw_subdiv_loop_cb(const SubdivForeachContext *foreach_context,
|
|||
|
||||
int coarse_vertex_index = ctx->vert_origindex_map[subdiv_vertex_index];
|
||||
|
||||
if (coarse_vertex_index != -1) {
|
||||
if (ctx->v_origindex) {
|
||||
coarse_vertex_index = ctx->v_origindex[coarse_vertex_index];
|
||||
}
|
||||
|
||||
/* Double check as vorigindex may have modified the index. */
|
||||
if (coarse_vertex_index != -1) {
|
||||
ctx->point_indices[coarse_vertex_index] = subdiv_loop_index;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->subdiv_loop_subdiv_vert_index[subdiv_loop_index] = subdiv_vertex_index;
|
||||
/* For now index the subdiv_edge_index, it will be replaced by the actual coarse edge index
|
||||
* at the end of the traversal as some edges are only then traversed. */
|
||||
|
@ -1012,7 +1017,6 @@ static bool draw_subdiv_build_cache(DRWSubdivCache *cache,
|
|||
cache->face_ptex_offset_buffer = draw_subdiv_build_origindex_buffer(cache->face_ptex_offset,
|
||||
mesh_eval->totpoly + 1);
|
||||
cache->num_coarse_poly = mesh_eval->totpoly;
|
||||
cache->point_indices = cache_building_context.point_indices;
|
||||
|
||||
build_vertex_face_adjacency_maps(cache);
|
||||
|
||||
|
@ -1085,7 +1089,7 @@ static void draw_subdiv_init_ubo_storage(const DRWSubdivCache *cache,
|
|||
ubo->max_patch_face = cache->gpu_patch_map.max_patch_face;
|
||||
ubo->max_depth = cache->gpu_patch_map.max_depth;
|
||||
ubo->patches_are_triangular = cache->gpu_patch_map.patches_are_triangular;
|
||||
ubo->coarse_poly_count = cache->num_coarse_poly;
|
||||
ubo->coarse_poly_count = cache->bm ? cache->bm->totface : cache->num_coarse_poly;
|
||||
ubo->optimal_display = cache->optimal_display;
|
||||
ubo->num_subdiv_loops = cache->num_subdiv_loops;
|
||||
ubo->edge_loose_offset = cache->num_subdiv_loops * 2;
|
||||
|
@ -1649,50 +1653,6 @@ void draw_subdiv_build_edituv_stretch_angle_buffer(const DRWSubdivCache *cache,
|
|||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
void draw_subdiv_init_mesh_render_data(DRWSubdivCache *cache,
|
||||
MeshRenderData *mr,
|
||||
const ToolSettings *toolsettings)
|
||||
{
|
||||
Mesh *mesh = cache->mesh;
|
||||
|
||||
/* Setup required data for loose geometry. */
|
||||
mr->me = mesh;
|
||||
mr->medge = mesh->medge;
|
||||
mr->mvert = mesh->mvert;
|
||||
mr->mpoly = mesh->mpoly;
|
||||
mr->mloop = mesh->mloop;
|
||||
mr->vert_normals = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
mr->vert_len = mesh->totvert;
|
||||
mr->edge_len = mesh->totedge;
|
||||
mr->poly_len = mesh->totpoly;
|
||||
mr->loop_len = mesh->totloop;
|
||||
mr->extract_type = MR_EXTRACT_MESH;
|
||||
mr->toolsettings = toolsettings;
|
||||
mr->v_origindex = static_cast<int *>(CustomData_get_layer(&mr->me->vdata, CD_ORIGINDEX));
|
||||
mr->e_origindex = static_cast<int *>(CustomData_get_layer(&mr->me->edata, CD_ORIGINDEX));
|
||||
mr->p_origindex = static_cast<int *>(CustomData_get_layer(&mr->me->pdata, CD_ORIGINDEX));
|
||||
|
||||
/* MeshRenderData is only used for generating edit mode data here. */
|
||||
if (!cache->bm) {
|
||||
return;
|
||||
}
|
||||
|
||||
BMesh *bm = cache->bm;
|
||||
BM_mesh_elem_table_ensure(bm, BM_EDGE | BM_FACE | BM_VERT);
|
||||
|
||||
mr->bm = bm;
|
||||
mr->eed_act = BM_mesh_active_edge_get(bm);
|
||||
mr->efa_act = BM_mesh_active_face_get(bm, false, true);
|
||||
mr->eve_act = BM_mesh_active_vert_get(bm);
|
||||
mr->edge_crease_ofs = CustomData_get_offset(&bm->edata, CD_CREASE);
|
||||
mr->vert_crease_ofs = CustomData_get_offset(&bm->vdata, CD_CREASE);
|
||||
mr->bweight_ofs = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
|
||||
#ifdef WITH_FREESTYLE
|
||||
mr->freestyle_edge_ofs = CustomData_get_offset(&bm->edata, CD_FREESTYLE_EDGE);
|
||||
mr->freestyle_face_ofs = CustomData_get_offset(&bm->pdata, CD_FREESTYLE_FACE);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* For material assignments we want indices for triangles that share a common material to be laid
|
||||
* out contiguously in memory. To achieve this, we sort the indices based on which material the
|
||||
|
@ -1796,7 +1756,15 @@ static bool draw_subdiv_create_requested_buffers(const Scene *scene,
|
|||
Mesh *mesh,
|
||||
struct MeshBatchCache *batch_cache,
|
||||
MeshBufferCache *mbc,
|
||||
const ToolSettings *toolsettings,
|
||||
const bool is_editmode,
|
||||
const bool is_paint_mode,
|
||||
const bool is_mode_active,
|
||||
const float obmat[4][4],
|
||||
const bool do_final,
|
||||
const bool do_uvedit,
|
||||
const bool use_subsurf_fdots,
|
||||
const ToolSettings *ts,
|
||||
const bool use_hide,
|
||||
OpenSubdiv_EvaluatorCache *evaluator_cache)
|
||||
{
|
||||
SubsurfModifierData *smd = BKE_object_get_last_subsurf_modifier(ob);
|
||||
|
@ -1849,9 +1817,14 @@ static bool draw_subdiv_create_requested_buffers(const Scene *scene,
|
|||
draw_subdiv_cache_ensure_mat_offsets(draw_cache, mesh_eval, batch_cache->mat_len);
|
||||
}
|
||||
|
||||
draw_subdiv_cache_update_extra_coarse_face_data(draw_cache, mesh_eval);
|
||||
MeshRenderData *mr = mesh_render_data_create(
|
||||
ob, mesh, is_editmode, is_paint_mode, is_mode_active, obmat, do_final, do_uvedit, ts);
|
||||
|
||||
mesh_buffer_cache_create_requested_subdiv(batch_cache, mbc, draw_cache, toolsettings);
|
||||
draw_subdiv_cache_update_extra_coarse_face_data(draw_cache, mesh_eval, mr);
|
||||
|
||||
mesh_buffer_cache_create_requested_subdiv(batch_cache, mbc, draw_cache, mr);
|
||||
|
||||
mesh_render_data_free(mr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1863,7 +1836,15 @@ void DRW_create_subdivision(const Scene *scene,
|
|||
Mesh *mesh,
|
||||
struct MeshBatchCache *batch_cache,
|
||||
MeshBufferCache *mbc,
|
||||
const ToolSettings *toolsettings)
|
||||
const bool is_editmode,
|
||||
const bool is_paint_mode,
|
||||
const bool is_mode_active,
|
||||
const float obmat[4][4],
|
||||
const bool do_final,
|
||||
const bool do_uvedit,
|
||||
const bool use_subsurf_fdots,
|
||||
const ToolSettings *ts,
|
||||
const bool use_hide)
|
||||
{
|
||||
if (g_evaluator_cache == nullptr) {
|
||||
g_evaluator_cache = openSubdiv_createEvaluatorCache(OPENSUBDIV_EVALUATOR_GLSL_COMPUTE);
|
||||
|
@ -1875,8 +1856,21 @@ void DRW_create_subdivision(const Scene *scene,
|
|||
const double begin_time = PIL_check_seconds_timer();
|
||||
#endif
|
||||
|
||||
if (!draw_subdiv_create_requested_buffers(
|
||||
scene, ob, mesh, batch_cache, mbc, toolsettings, g_evaluator_cache)) {
|
||||
if (!draw_subdiv_create_requested_buffers(scene,
|
||||
ob,
|
||||
mesh,
|
||||
batch_cache,
|
||||
mbc,
|
||||
is_editmode,
|
||||
is_paint_mode,
|
||||
is_mode_active,
|
||||
obmat,
|
||||
do_final,
|
||||
do_uvedit,
|
||||
use_subsurf_fdots,
|
||||
ts,
|
||||
use_hide,
|
||||
g_evaluator_cache)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -128,7 +128,17 @@ void DRW_create_subdivision(const struct Scene *scene,
|
|||
struct Mesh *mesh,
|
||||
struct MeshBatchCache *batch_cache,
|
||||
struct MeshBufferCache *mbc,
|
||||
const struct ToolSettings *toolsettings);
|
||||
const bool is_editmode,
|
||||
const bool is_paint_mode,
|
||||
const bool is_mode_active,
|
||||
const float obmat[4][4],
|
||||
const bool do_final,
|
||||
const bool do_uvedit,
|
||||
const bool use_subsurf_fdots,
|
||||
const ToolSettings *ts,
|
||||
const bool use_hide);
|
||||
|
||||
void DRW_subdivide_loose_geom(DRWSubdivCache *subdiv_cache, struct MeshBufferCache *cache);
|
||||
|
||||
void DRW_subdiv_cache_free(struct Subdiv *subdiv);
|
||||
|
||||
|
|
|
@ -147,16 +147,55 @@ static void extract_points_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
|||
void *data)
|
||||
{
|
||||
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(data);
|
||||
/* Copy the points as the data upload will free them. */
|
||||
elb->data = (uint *)MEM_dupallocN(subdiv_cache->point_indices);
|
||||
elb->index_len = mr->vert_len;
|
||||
elb->index_min = 0;
|
||||
elb->index_max = subdiv_cache->num_subdiv_loops + mr->loop_loose_len;
|
||||
elb->prim_type = GPU_PRIM_POINTS;
|
||||
GPU_indexbuf_init(
|
||||
elb, GPU_PRIM_POINTS, mr->vert_len, subdiv_cache->num_subdiv_loops + mr->loop_loose_len);
|
||||
}
|
||||
|
||||
static void extract_points_iter_subdiv_common(GPUIndexBufBuilder *elb,
|
||||
const MeshRenderData *mr,
|
||||
const DRWSubdivCache *subdiv_cache,
|
||||
uint subdiv_quad_index)
|
||||
{
|
||||
int *subdiv_loop_vert_index = (int *)GPU_vertbuf_get_data(subdiv_cache->verts_orig_index);
|
||||
uint start_loop_idx = subdiv_quad_index * 4;
|
||||
uint end_loop_idx = (subdiv_quad_index + 1) * 4;
|
||||
for (uint i = start_loop_idx; i < end_loop_idx; i++) {
|
||||
int coarse_vertex_index = subdiv_loop_vert_index[i];
|
||||
|
||||
if (coarse_vertex_index == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mr->v_origindex && mr->v_origindex[coarse_vertex_index] == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
GPU_indexbuf_set_point_vert(elb, coarse_vertex_index, i);
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_points_iter_subdiv_bm(const DRWSubdivCache *subdiv_cache,
|
||||
const MeshRenderData *mr,
|
||||
void *_data,
|
||||
uint subdiv_quad_index,
|
||||
const BMFace *UNUSED(coarse_quad))
|
||||
{
|
||||
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_data);
|
||||
extract_points_iter_subdiv_common(elb, mr, subdiv_cache, subdiv_quad_index);
|
||||
}
|
||||
|
||||
static void extract_points_iter_subdiv_mesh(const DRWSubdivCache *subdiv_cache,
|
||||
const MeshRenderData *mr,
|
||||
void *_data,
|
||||
uint subdiv_quad_index,
|
||||
const MPoly *UNUSED(coarse_quad))
|
||||
{
|
||||
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_data);
|
||||
extract_points_iter_subdiv_common(elb, mr, subdiv_cache, subdiv_quad_index);
|
||||
}
|
||||
|
||||
static void extract_points_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
|
||||
const MeshRenderData *UNUSED(mr),
|
||||
const MeshRenderData *mr,
|
||||
const MeshExtractLooseGeom *loose_geom,
|
||||
void *UNUSED(buffer),
|
||||
void *data)
|
||||
|
@ -167,28 +206,38 @@ static void extract_points_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
|
|||
}
|
||||
|
||||
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(data);
|
||||
|
||||
const Mesh *coarse_mesh = subdiv_cache->mesh;
|
||||
const MEdge *coarse_edges = coarse_mesh->medge;
|
||||
|
||||
uint offset = subdiv_cache->num_subdiv_loops;
|
||||
|
||||
for (int i = 0; i < loose_geom->edge_len; i++) {
|
||||
const MEdge *loose_edge = &coarse_edges[loose_geom->edges[i]];
|
||||
if (elb->data[loose_edge->v1] == -1u) {
|
||||
GPU_indexbuf_set_point_vert(elb, loose_edge->v1, offset);
|
||||
}
|
||||
if (elb->data[loose_edge->v2] == -1u) {
|
||||
GPU_indexbuf_set_point_vert(elb, loose_edge->v2, offset + 1);
|
||||
}
|
||||
offset += 2;
|
||||
}
|
||||
if (mr->extract_type == MR_EXTRACT_MESH) {
|
||||
const Mesh *coarse_mesh = subdiv_cache->mesh;
|
||||
const MEdge *coarse_edges = coarse_mesh->medge;
|
||||
|
||||
for (int i = 0; i < loose_geom->vert_len; i++) {
|
||||
if (elb->data[loose_geom->verts[i]] == -1u) {
|
||||
GPU_indexbuf_set_point_vert(elb, loose_geom->verts[i], offset);
|
||||
for (int i = 0; i < loose_geom->edge_len; i++) {
|
||||
const MEdge *loose_edge = &coarse_edges[loose_geom->edges[i]];
|
||||
vert_set_mesh(elb, mr, loose_edge->v1, offset);
|
||||
vert_set_mesh(elb, mr, loose_edge->v2, offset + 1);
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
for (int i = 0; i < loose_geom->vert_len; i++) {
|
||||
vert_set_mesh(elb, mr, loose_geom->verts[i], offset);
|
||||
offset += 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
BMesh *bm = mr->bm;
|
||||
for (int i = 0; i < loose_geom->edge_len; i++) {
|
||||
const BMEdge *loose_edge = BM_edge_at_index(bm, loose_geom->edges[i]);
|
||||
vert_set_bm(elb, loose_edge->v1, offset);
|
||||
vert_set_bm(elb, loose_edge->v2, offset + 1);
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
for (int i = 0; i < loose_geom->vert_len; i++) {
|
||||
const BMVert *loose_vert = BM_vert_at_index(bm, loose_geom->verts[i]);
|
||||
vert_set_bm(elb, loose_vert, offset);
|
||||
offset += 1;
|
||||
}
|
||||
offset += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,6 +265,8 @@ constexpr MeshExtract create_extractor_points()
|
|||
extractor.task_reduce = extract_points_task_reduce;
|
||||
extractor.finish = extract_points_finish;
|
||||
extractor.init_subdiv = extract_points_init_subdiv;
|
||||
extractor.iter_subdiv_bm = extract_points_iter_subdiv_bm;
|
||||
extractor.iter_subdiv_mesh = extract_points_iter_subdiv_mesh;
|
||||
extractor.iter_loose_geom_subdiv = extract_points_loose_geom_subdiv;
|
||||
extractor.finish_subdiv = extract_points_finish_subdiv;
|
||||
extractor.use_threading = true;
|
||||
|
|
|
@ -272,21 +272,24 @@ static void extract_edit_data_iter_subdiv_bm(const DRWSubdivCache *subdiv_cache,
|
|||
memset(edit_loop_data, 0, sizeof(EditLoopData));
|
||||
|
||||
if (vert_origindex != -1) {
|
||||
const BMVert *eve = bm_original_vert_get(mr, vert_origindex);
|
||||
const BMVert *eve = mr->v_origindex ? bm_original_vert_get(mr, vert_origindex) :
|
||||
BM_vert_at_index(mr->bm, vert_origindex);
|
||||
if (eve) {
|
||||
mesh_render_data_vert_flag(mr, eve, edit_loop_data);
|
||||
}
|
||||
}
|
||||
|
||||
if (edge_origindex != -1) {
|
||||
const BMEdge *eed = bm_original_edge_get(mr, edge_origindex);
|
||||
if (eed) {
|
||||
mesh_render_data_edge_flag(mr, eed, edit_loop_data);
|
||||
}
|
||||
/* NOTE: #subdiv_loop_edge_index already has the origindex layer baked in. */
|
||||
const BMEdge *eed = BM_edge_at_index(mr->bm, edge_origindex);
|
||||
mesh_render_data_edge_flag(mr, eed, edit_loop_data);
|
||||
}
|
||||
|
||||
/* The -1 parameter is for edit_uvs, which we don't do here. */
|
||||
mesh_render_data_face_flag(mr, coarse_quad, -1, edit_loop_data);
|
||||
/* coarse_quad can be null when called by the mesh iteration below. */
|
||||
if (coarse_quad) {
|
||||
/* The -1 parameter is for edit_uvs, which we don't do here. */
|
||||
mesh_render_data_face_flag(mr, coarse_quad, -1, edit_loop_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -317,7 +320,9 @@ static void extract_edit_data_loose_geom_subdiv(const DRWSubdivCache *subdiv_cac
|
|||
const int offset = subdiv_cache->num_subdiv_loops + ledge_index * 2;
|
||||
EditLoopData *data = &vbo_data[offset];
|
||||
memset(data, 0, sizeof(EditLoopData));
|
||||
BMEdge *eed = bm_original_edge_get(mr, loose_geom->edges[ledge_index]);
|
||||
const int edge_index = loose_geom->edges[ledge_index];
|
||||
BMEdge *eed = mr->e_origindex ? bm_original_edge_get(mr, edge_index) :
|
||||
BM_edge_at_index(mr->bm, edge_index);
|
||||
mesh_render_data_edge_flag(mr, eed, &data[0]);
|
||||
data[1] = data[0];
|
||||
mesh_render_data_vert_flag(mr, eed->v1, &data[0]);
|
||||
|
|
|
@ -143,7 +143,7 @@ static void extract_edituv_data_iter_subdiv_bm(const DRWSubdivCache *subdiv_cach
|
|||
memset(edit_loop_data, 0, sizeof(EditLoopData));
|
||||
|
||||
if (vert_origindex != -1 && edge_origindex != -1) {
|
||||
BMEdge *eed = bm_original_edge_get(mr, edge_origindex);
|
||||
BMEdge *eed = BM_edge_at_index(mr->bm, edge_origindex);
|
||||
/* Loop on an edge endpoint. */
|
||||
BMLoop *l = BM_face_edge_share_loop(const_cast<BMFace *>(coarse_quad), eed);
|
||||
mesh_render_data_loop_flag(mr, l, data->cd_ofs, edit_loop_data);
|
||||
|
|
|
@ -249,9 +249,6 @@ static void extract_pos_nor_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache
|
|||
}
|
||||
|
||||
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer);
|
||||
const Mesh *coarse_mesh = subdiv_cache->mesh;
|
||||
const MEdge *coarse_edges = coarse_mesh->medge;
|
||||
const MVert *coarse_verts = coarse_mesh->mvert;
|
||||
uint offset = subdiv_cache->num_subdiv_loops;
|
||||
|
||||
/* TODO(@kevindietrich): replace this when compressed normals are supported. */
|
||||
|
@ -261,38 +258,75 @@ static void extract_pos_nor_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache
|
|||
float flag;
|
||||
};
|
||||
|
||||
SubdivPosNorLoop edge_data[2];
|
||||
for (int i = 0; i < loose_geom->edge_len; i++) {
|
||||
const MEdge *loose_edge = &coarse_edges[loose_geom->edges[i]];
|
||||
const MVert *loose_vert1 = &coarse_verts[loose_edge->v1];
|
||||
const MVert *loose_vert2 = &coarse_verts[loose_edge->v2];
|
||||
if (mr->extract_type == MR_EXTRACT_MESH) {
|
||||
const Mesh *coarse_mesh = subdiv_cache->mesh;
|
||||
const MEdge *coarse_edges = coarse_mesh->medge;
|
||||
const MVert *coarse_verts = coarse_mesh->mvert;
|
||||
|
||||
copy_v3_v3(edge_data[0].pos, loose_vert1->co);
|
||||
copy_v3_v3(edge_data[0].nor, mr->vert_normals[loose_edge->v1]);
|
||||
edge_data[0].flag = 0.0f;
|
||||
SubdivPosNorLoop edge_data[2];
|
||||
memset(&edge_data, 0, sizeof(SubdivPosNorLoop) * 2);
|
||||
for (int i = 0; i < loose_geom->edge_len; i++) {
|
||||
const MEdge *loose_edge = &coarse_edges[loose_geom->edges[i]];
|
||||
const MVert *loose_vert1 = &coarse_verts[loose_edge->v1];
|
||||
const MVert *loose_vert2 = &coarse_verts[loose_edge->v2];
|
||||
|
||||
copy_v3_v3(edge_data[1].pos, loose_vert2->co);
|
||||
copy_v3_v3(edge_data[1].nor, mr->vert_normals[loose_edge->v2]);
|
||||
edge_data[1].flag = 0.0f;
|
||||
copy_v3_v3(edge_data[0].pos, loose_vert1->co);
|
||||
copy_v3_v3(edge_data[1].pos, loose_vert2->co);
|
||||
|
||||
GPU_vertbuf_update_sub(
|
||||
vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop) * 2, &edge_data);
|
||||
GPU_vertbuf_update_sub(
|
||||
vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop) * 2, &edge_data);
|
||||
|
||||
offset += 2;
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
SubdivPosNorLoop vert_data;
|
||||
memset(&vert_data, 0, sizeof(SubdivPosNorLoop));
|
||||
for (int i = 0; i < loose_geom->vert_len; i++) {
|
||||
const MVert *loose_vertex = &coarse_verts[loose_geom->verts[i]];
|
||||
|
||||
copy_v3_v3(vert_data.pos, loose_vertex->co);
|
||||
|
||||
GPU_vertbuf_update_sub(
|
||||
vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop), &vert_data);
|
||||
|
||||
offset += 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
BMesh *bm = subdiv_cache->bm;
|
||||
|
||||
SubdivPosNorLoop vert_data;
|
||||
vert_data.flag = 0.0f;
|
||||
for (int i = 0; i < loose_geom->vert_len; i++) {
|
||||
const MVert *loose_vertex = &coarse_verts[loose_geom->verts[i]];
|
||||
SubdivPosNorLoop edge_data[2];
|
||||
memset(&edge_data, 0, sizeof(SubdivPosNorLoop) * 2);
|
||||
for (int i = 0; i < loose_geom->edge_len; i++) {
|
||||
const BMEdge *loose_edge = BM_edge_at_index(bm, loose_geom->edges[i]);
|
||||
const BMVert *loose_vert1 = loose_edge->v1;
|
||||
const BMVert *loose_vert2 = loose_edge->v2;
|
||||
|
||||
copy_v3_v3(vert_data.pos, loose_vertex->co);
|
||||
copy_v3_v3(vert_data.nor, mr->vert_normals[loose_geom->verts[i]]);
|
||||
copy_v3_v3(edge_data[0].pos, loose_vert1->co);
|
||||
copy_v3_v3(edge_data[0].nor, loose_vert1->no);
|
||||
|
||||
GPU_vertbuf_update_sub(
|
||||
vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop), &vert_data);
|
||||
copy_v3_v3(edge_data[1].pos, loose_vert2->co);
|
||||
copy_v3_v3(edge_data[1].nor, loose_vert2->no);
|
||||
|
||||
offset += 1;
|
||||
GPU_vertbuf_update_sub(
|
||||
vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop) * 2, &edge_data);
|
||||
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
SubdivPosNorLoop vert_data;
|
||||
memset(&vert_data, 0, sizeof(SubdivPosNorLoop));
|
||||
for (int i = 0; i < loose_geom->vert_len; i++) {
|
||||
const BMVert *loose_vertex = BM_vert_at_index(bm, loose_geom->verts[i]);
|
||||
|
||||
copy_v3_v3(vert_data.pos, loose_vertex->co);
|
||||
copy_v3_v3(vert_data.nor, loose_vertex->no);
|
||||
|
||||
GPU_vertbuf_update_sub(
|
||||
vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop), &vert_data);
|
||||
|
||||
offset += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -190,13 +190,28 @@ static void extract_vert_idx_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
|||
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
|
||||
/* Each element points to an element in the ibo.points. */
|
||||
draw_subdiv_init_origindex_buffer(vbo,
|
||||
subdiv_cache->subdiv_loop_subdiv_vert_index,
|
||||
(int *)GPU_vertbuf_get_data(subdiv_cache->verts_orig_index),
|
||||
subdiv_cache->num_subdiv_loops,
|
||||
mr->loop_loose_len);
|
||||
|
||||
if (!mr->v_origindex) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Remap the vertex indices to those pointed by the origin indices layer. At this point, the
|
||||
* VBO data is a copy of #verts_orig_index which contains the coarse vertices indices, so
|
||||
* the memory can both be accessed for lookup and immediately overwritten. */
|
||||
int *vbo_data = static_cast<int *>(GPU_vertbuf_get_data(vbo));
|
||||
for (int i = 0; i < subdiv_cache->num_subdiv_loops; i++) {
|
||||
if (vbo_data[i] == -1) {
|
||||
continue;
|
||||
}
|
||||
vbo_data[i] = mr->v_origindex[vbo_data[i]];
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_vert_idx_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
|
||||
const MeshRenderData *UNUSED(mr),
|
||||
const MeshRenderData *mr,
|
||||
const MeshExtractLooseGeom *loose_geom,
|
||||
void *buffer,
|
||||
void *UNUSED(data))
|
||||
|
@ -208,20 +223,37 @@ static void extract_vert_idx_loose_geom_subdiv(const DRWSubdivCache *subdiv_cach
|
|||
|
||||
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer);
|
||||
uint *vert_idx_data = (uint *)GPU_vertbuf_get_data(vbo);
|
||||
const Mesh *coarse_mesh = subdiv_cache->mesh;
|
||||
const MEdge *coarse_edges = coarse_mesh->medge;
|
||||
uint offset = subdiv_cache->num_subdiv_loops;
|
||||
|
||||
for (int i = 0; i < loose_geom->edge_len; i++) {
|
||||
const MEdge *loose_edge = &coarse_edges[loose_geom->edges[i]];
|
||||
vert_idx_data[offset] = loose_edge->v1;
|
||||
vert_idx_data[offset + 1] = loose_edge->v2;
|
||||
offset += 2;
|
||||
}
|
||||
if (mr->extract_type == MR_EXTRACT_MESH) {
|
||||
const Mesh *coarse_mesh = subdiv_cache->mesh;
|
||||
const MEdge *coarse_edges = coarse_mesh->medge;
|
||||
for (int i = 0; i < loose_geom->edge_len; i++) {
|
||||
const MEdge *loose_edge = &coarse_edges[loose_geom->edges[i]];
|
||||
vert_idx_data[offset] = loose_edge->v1;
|
||||
vert_idx_data[offset + 1] = loose_edge->v2;
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
for (int i = 0; i < loose_geom->vert_len; i++) {
|
||||
vert_idx_data[offset] = loose_geom->verts[i];
|
||||
offset += 1;
|
||||
for (int i = 0; i < loose_geom->vert_len; i++) {
|
||||
vert_idx_data[offset] = loose_geom->verts[i];
|
||||
offset += 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
BMesh *bm = mr->bm;
|
||||
for (int i = 0; i < loose_geom->edge_len; i++) {
|
||||
const BMEdge *loose_edge = BM_edge_at_index(bm, loose_geom->edges[i]);
|
||||
vert_idx_data[offset] = BM_elem_index_get(loose_edge->v1);
|
||||
vert_idx_data[offset + 1] = BM_elem_index_get(loose_edge->v2);
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
for (int i = 0; i < loose_geom->vert_len; i++) {
|
||||
const BMVert *loose_vert = BM_vert_at_index(bm, loose_geom->verts[i]);
|
||||
vert_idx_data[offset] = BM_elem_index_get(loose_vert);
|
||||
offset += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -262,7 +294,7 @@ static void extract_edge_idx_loose_geom_subdiv(const DRWSubdivCache *subdiv_cach
|
|||
}
|
||||
|
||||
static void extract_poly_idx_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
||||
const MeshRenderData *UNUSED(mr),
|
||||
const MeshRenderData *mr,
|
||||
MeshBatchCache *UNUSED(cache),
|
||||
void *buf,
|
||||
void *UNUSED(data))
|
||||
|
@ -270,6 +302,18 @@ static void extract_poly_idx_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
|||
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
|
||||
draw_subdiv_init_origindex_buffer(
|
||||
vbo, subdiv_cache->subdiv_loop_poly_index, subdiv_cache->num_subdiv_loops, 0);
|
||||
|
||||
if (!mr->p_origindex) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Remap the polygon indices to those pointed by the origin indices layer. At this point, the
|
||||
* VBO data is a copy of #subdiv_loop_poly_index which contains the coarse polygon indices, so
|
||||
* the memory can both be accessed for lookup and immediately overwritten. */
|
||||
int *vbo_data = static_cast<int *>(GPU_vertbuf_get_data(vbo));
|
||||
for (int i = 0; i < subdiv_cache->num_subdiv_loops; i++) {
|
||||
vbo_data[i] = mr->p_origindex[vbo_data[i]];
|
||||
}
|
||||
}
|
||||
|
||||
constexpr MeshExtract create_extractor_poly_idx()
|
||||
|
|
|
@ -1004,7 +1004,6 @@ static void gpencil_invert_image(tGPDfill *tgpf)
|
|||
ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
|
||||
|
||||
const int maxpixel = (ibuf->x * ibuf->y) - 1;
|
||||
const int center = ibuf->x / 2;
|
||||
|
||||
for (int v = maxpixel; v != 0; v--) {
|
||||
float color[4];
|
||||
|
@ -1016,15 +1015,6 @@ static void gpencil_invert_image(tGPDfill *tgpf)
|
|||
/* Red->Green */
|
||||
else if (color[0] == 1.0f) {
|
||||
set_pixel(ibuf, v, fill_col[1]);
|
||||
/* Add thickness of 2 pixels to avoid too thin lines, but avoid extremes of the pixel line.
|
||||
*/
|
||||
int row = v / ibuf->x;
|
||||
int lowpix = row * ibuf->x;
|
||||
int highpix = lowpix + ibuf->x - 1;
|
||||
if ((v > lowpix) && (v < highpix)) {
|
||||
int offset = (v % ibuf->x < center) ? 1 : -1;
|
||||
set_pixel(ibuf, v + offset, fill_col[1]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Set to Transparent. */
|
||||
|
@ -1120,11 +1110,14 @@ static void gpencil_erase_processed_area(tGPDfill *tgpf)
|
|||
*/
|
||||
static bool dilate_shape(ImBuf *ibuf)
|
||||
{
|
||||
#define IS_RED (color[0] == 1.0f)
|
||||
#define IS_GREEN (color[1] == 1.0f)
|
||||
|
||||
bool done = false;
|
||||
|
||||
BLI_Stack *stack = BLI_stack_new(sizeof(int), __func__);
|
||||
const float green[4] = {0.0f, 1.0f, 0.0f, 1.0f};
|
||||
// const int maxpixel = (ibuf->x * ibuf->y) - 1;
|
||||
const int max_size = (ibuf->x * ibuf->y) - 1;
|
||||
/* detect pixels and expand into red areas */
|
||||
for (int row = 0; row < ibuf->y; row++) {
|
||||
if (!is_row_filled(ibuf, row)) {
|
||||
|
@ -1137,7 +1130,7 @@ static bool dilate_shape(ImBuf *ibuf)
|
|||
float color[4];
|
||||
int index;
|
||||
get_pixel(ibuf, v, color);
|
||||
if (color[1] == 1.0f) {
|
||||
if (IS_GREEN) {
|
||||
int tp = 0;
|
||||
int bm = 0;
|
||||
int lt = 0;
|
||||
|
@ -1147,7 +1140,7 @@ static bool dilate_shape(ImBuf *ibuf)
|
|||
if (v - 1 >= 0) {
|
||||
index = v - 1;
|
||||
get_pixel(ibuf, index, color);
|
||||
if (color[0] == 1.0f) {
|
||||
if (IS_RED) {
|
||||
BLI_stack_push(stack, &index);
|
||||
lt = index;
|
||||
}
|
||||
|
@ -1156,25 +1149,25 @@ static bool dilate_shape(ImBuf *ibuf)
|
|||
if (v + 1 <= maxpixel) {
|
||||
index = v + 1;
|
||||
get_pixel(ibuf, index, color);
|
||||
if (color[0] == 1.0f) {
|
||||
if (IS_RED) {
|
||||
BLI_stack_push(stack, &index);
|
||||
rt = index;
|
||||
}
|
||||
}
|
||||
/* pixel top */
|
||||
if (v + (ibuf->x * 1) <= maxpixel) {
|
||||
index = v + (ibuf->x * 1);
|
||||
if (v + ibuf->x <= max_size) {
|
||||
index = v + ibuf->x;
|
||||
get_pixel(ibuf, index, color);
|
||||
if (color[0] == 1.0f) {
|
||||
if (IS_RED) {
|
||||
BLI_stack_push(stack, &index);
|
||||
tp = index;
|
||||
}
|
||||
}
|
||||
/* pixel bottom */
|
||||
if (v - (ibuf->x * 1) >= 0) {
|
||||
index = v - (ibuf->x * 1);
|
||||
if (v - ibuf->x >= 0) {
|
||||
index = v - ibuf->x;
|
||||
get_pixel(ibuf, index, color);
|
||||
if (color[0] == 1.0f) {
|
||||
if (IS_RED) {
|
||||
BLI_stack_push(stack, &index);
|
||||
bm = index;
|
||||
}
|
||||
|
@ -1183,7 +1176,7 @@ static bool dilate_shape(ImBuf *ibuf)
|
|||
if (tp && lt) {
|
||||
index = tp - 1;
|
||||
get_pixel(ibuf, index, color);
|
||||
if (color[0] == 1.0f) {
|
||||
if (IS_RED) {
|
||||
BLI_stack_push(stack, &index);
|
||||
}
|
||||
}
|
||||
|
@ -1191,7 +1184,7 @@ static bool dilate_shape(ImBuf *ibuf)
|
|||
if (tp && rt) {
|
||||
index = tp + 1;
|
||||
get_pixel(ibuf, index, color);
|
||||
if (color[0] == 1.0f) {
|
||||
if (IS_RED) {
|
||||
BLI_stack_push(stack, &index);
|
||||
}
|
||||
}
|
||||
|
@ -1199,7 +1192,7 @@ static bool dilate_shape(ImBuf *ibuf)
|
|||
if (bm && lt) {
|
||||
index = bm - 1;
|
||||
get_pixel(ibuf, index, color);
|
||||
if (color[0] == 1.0f) {
|
||||
if (IS_RED) {
|
||||
BLI_stack_push(stack, &index);
|
||||
}
|
||||
}
|
||||
|
@ -1207,7 +1200,7 @@ static bool dilate_shape(ImBuf *ibuf)
|
|||
if (bm && rt) {
|
||||
index = bm + 1;
|
||||
get_pixel(ibuf, index, color);
|
||||
if (color[0] == 1.0f) {
|
||||
if (IS_RED) {
|
||||
BLI_stack_push(stack, &index);
|
||||
}
|
||||
}
|
||||
|
@ -1224,6 +1217,88 @@ static bool dilate_shape(ImBuf *ibuf)
|
|||
BLI_stack_free(stack);
|
||||
|
||||
return done;
|
||||
|
||||
#undef IS_RED
|
||||
#undef IS_GREEN
|
||||
}
|
||||
|
||||
/**
|
||||
* Contract
|
||||
*
|
||||
* Contract green areas to scale down the size.
|
||||
* Using stack prevents creep when replacing colors directly.
|
||||
*/
|
||||
static bool contract_shape(ImBuf *ibuf)
|
||||
{
|
||||
#define IS_GREEN (color[1] == 1.0f)
|
||||
#define IS_NOT_GREEN (color[1] != 1.0f)
|
||||
|
||||
bool done = false;
|
||||
|
||||
BLI_Stack *stack = BLI_stack_new(sizeof(int), __func__);
|
||||
const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
const int max_size = (ibuf->x * ibuf->y) - 1;
|
||||
|
||||
/* Detect if pixel is near of no green pixels and mark green to be cleared. */
|
||||
for (int row = 0; row < ibuf->y; row++) {
|
||||
if (!is_row_filled(ibuf, row)) {
|
||||
continue;
|
||||
}
|
||||
int maxpixel = (ibuf->x * (row + 1)) - 1;
|
||||
int minpixel = ibuf->x * row;
|
||||
|
||||
for (int v = maxpixel; v != minpixel; v--) {
|
||||
float color[4];
|
||||
get_pixel(ibuf, v, color);
|
||||
if (IS_GREEN) {
|
||||
/* pixel left */
|
||||
if (v - 1 >= 0) {
|
||||
get_pixel(ibuf, v - 1, color);
|
||||
if (IS_NOT_GREEN) {
|
||||
BLI_stack_push(stack, &v);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* pixel right */
|
||||
if (v + 1 <= maxpixel) {
|
||||
get_pixel(ibuf, v + 1, color);
|
||||
if (IS_NOT_GREEN) {
|
||||
BLI_stack_push(stack, &v);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* pixel top */
|
||||
if (v + ibuf->x <= max_size) {
|
||||
get_pixel(ibuf, v + ibuf->x, color);
|
||||
if (IS_NOT_GREEN) {
|
||||
BLI_stack_push(stack, &v);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* pixel bottom */
|
||||
if (v - ibuf->x >= 0) {
|
||||
get_pixel(ibuf, v - ibuf->x, color);
|
||||
if (IS_NOT_GREEN) {
|
||||
BLI_stack_push(stack, &v);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Clear pixels. */
|
||||
while (!BLI_stack_is_empty(stack)) {
|
||||
int v;
|
||||
BLI_stack_pop(stack, &v);
|
||||
set_pixel(ibuf, v, clear);
|
||||
done = true;
|
||||
}
|
||||
BLI_stack_free(stack);
|
||||
|
||||
return done;
|
||||
|
||||
#undef IS_GREEN
|
||||
#undef IS_NOT_GREEN
|
||||
}
|
||||
|
||||
/* Get the outline points of a shape using Moore Neighborhood algorithm
|
||||
|
@ -1265,10 +1340,15 @@ static void gpencil_get_outline_points(tGPDfill *tgpf, const bool dilate)
|
|||
ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
|
||||
int imagesize = ibuf->x * ibuf->y;
|
||||
|
||||
/* Dilate. */
|
||||
/* Dilate or contract. */
|
||||
if (dilate) {
|
||||
for (int i = 0; i < brush->gpencil_settings->dilate_pixels; i++) {
|
||||
dilate_shape(ibuf);
|
||||
for (int i = 0; i < abs(brush->gpencil_settings->dilate_pixels); i++) {
|
||||
if (brush->gpencil_settings->dilate_pixels > 0) {
|
||||
dilate_shape(ibuf);
|
||||
}
|
||||
else {
|
||||
contract_shape(ibuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1975,6 +2055,24 @@ static void gpencil_zoom_level_set(tGPDfill *tgpf)
|
|||
}
|
||||
}
|
||||
|
||||
static bool gpencil_find_and_mark_empty_areas(tGPDfill *tgpf)
|
||||
{
|
||||
ImBuf *ibuf;
|
||||
void *lock;
|
||||
const float blue_col[4] = {0.0f, 0.0f, 1.0f, 1.0f};
|
||||
ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
|
||||
const int maxpixel = (ibuf->x * ibuf->y) - 1;
|
||||
float rgba[4];
|
||||
for (int i = 0; i < maxpixel; i++) {
|
||||
get_pixel(ibuf, i, rgba);
|
||||
if (rgba[3] == 0.0f) {
|
||||
set_pixel(ibuf, i, blue_col);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool gpencil_do_frame_fill(tGPDfill *tgpf, const bool is_inverted)
|
||||
{
|
||||
wmWindow *win = CTX_wm_window(tgpf->C);
|
||||
|
@ -1995,6 +2093,9 @@ static bool gpencil_do_frame_fill(tGPDfill *tgpf, const bool is_inverted)
|
|||
/* Invert direction if press Ctrl. */
|
||||
if (is_inverted) {
|
||||
gpencil_invert_image(tgpf);
|
||||
while (gpencil_find_and_mark_empty_areas(tgpf)) {
|
||||
gpencil_boundaryfill_area(tgpf);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clean borders to avoid infinite loops. */
|
||||
|
|
|
@ -6329,6 +6329,10 @@ void uiTemplateNodeSocket(uiLayout *layout, bContext *UNUSED(C), float color[4])
|
|||
|
||||
void uiTemplateCacheFileVelocity(uiLayout *layout, PointerRNA *fileptr)
|
||||
{
|
||||
if (RNA_pointer_is_null(fileptr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ensure that the context has a CacheFile as this may not be set inside of modifiers panels. */
|
||||
uiLayoutSetContextPointer(layout, "edit_cachefile", fileptr);
|
||||
|
||||
|
@ -6338,6 +6342,10 @@ void uiTemplateCacheFileVelocity(uiLayout *layout, PointerRNA *fileptr)
|
|||
|
||||
void uiTemplateCacheFileProcedural(uiLayout *layout, const bContext *C, PointerRNA *fileptr)
|
||||
{
|
||||
if (RNA_pointer_is_null(fileptr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ensure that the context has a CacheFile as this may not be set inside of modifiers panels. */
|
||||
uiLayoutSetContextPointer(layout, "edit_cachefile", fileptr);
|
||||
|
||||
|
@ -6384,6 +6392,10 @@ void uiTemplateCacheFileProcedural(uiLayout *layout, const bContext *C, PointerR
|
|||
|
||||
void uiTemplateCacheFileTimeSettings(uiLayout *layout, PointerRNA *fileptr)
|
||||
{
|
||||
if (RNA_pointer_is_null(fileptr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ensure that the context has a CacheFile as this may not be set inside of modifiers panels. */
|
||||
uiLayoutSetContextPointer(layout, "edit_cachefile", fileptr);
|
||||
|
||||
|
@ -6434,6 +6446,10 @@ uiListType *UI_UL_cache_file_layers()
|
|||
|
||||
void uiTemplateCacheFileLayers(uiLayout *layout, const bContext *C, PointerRNA *fileptr)
|
||||
{
|
||||
if (RNA_pointer_is_null(fileptr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ensure that the context has a CacheFile as this may not be set inside of modifiers panels. */
|
||||
uiLayoutSetContextPointer(layout, "edit_cachefile", fileptr);
|
||||
|
||||
|
|
|
@ -1615,12 +1615,13 @@ static void rna_def_gpencil_options(BlenderRNA *brna)
|
|||
prop, "Stroke Extension", "Strokes end extension for closing gaps, use zero to disable");
|
||||
RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
|
||||
|
||||
/* Number of pixels to dilate fill area. */
|
||||
/* Number of pixels to dilate fill area. Negative values contract the filled area. */
|
||||
prop = RNA_def_property(srna, "dilate", PROP_INT, PROP_PIXEL);
|
||||
RNA_def_property_int_sdna(prop, NULL, "dilate_pixels");
|
||||
RNA_def_property_range(prop, 0, 20);
|
||||
RNA_def_property_range(prop, -40, 40);
|
||||
RNA_def_property_int_default(prop, 1);
|
||||
RNA_def_property_ui_text(prop, "Dilate", "Number of pixels to dilate fill area");
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Dilate/Contract", "Number of pixels to expand or contract fill area");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
|
||||
|
||||
|
|
|
@ -331,6 +331,7 @@ const EnumPropertyItem rna_enum_object_axis_items[] = {
|
|||
# include "BKE_key.h"
|
||||
# include "BKE_material.h"
|
||||
# include "BKE_mesh.h"
|
||||
# include "BKE_mesh_wrapper.h"
|
||||
# include "BKE_modifier.h"
|
||||
# include "BKE_object.h"
|
||||
# include "BKE_particle.h"
|
||||
|
@ -510,6 +511,17 @@ void rna_Object_data_update(Main *bmain, Scene *scene, PointerRNA *ptr)
|
|||
rna_Object_internal_update_data_dependency(bmain, scene, ptr);
|
||||
}
|
||||
|
||||
static PointerRNA rna_Object_data_get(PointerRNA *ptr)
|
||||
{
|
||||
Object *ob = (Object *)ptr->data;
|
||||
if (ob->type == OB_MESH) {
|
||||
Mesh *me = (Mesh *)ob->data;
|
||||
me = BKE_mesh_wrapper_ensure_subdivision(ob, me);
|
||||
return rna_pointer_inherit_refine(ptr, &RNA_Mesh, me);
|
||||
}
|
||||
return rna_pointer_inherit_refine(ptr, &RNA_ID, ob->data);
|
||||
}
|
||||
|
||||
static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value, struct ReportList *reports)
|
||||
{
|
||||
Object *ob = (Object *)ptr->data;
|
||||
|
@ -3041,8 +3053,11 @@ static void rna_def_object(BlenderRNA *brna)
|
|||
|
||||
prop = RNA_def_property(srna, "data", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "ID");
|
||||
RNA_def_property_pointer_funcs(
|
||||
prop, NULL, "rna_Object_data_set", "rna_Object_data_typef", "rna_Object_data_poll");
|
||||
RNA_def_property_pointer_funcs(prop,
|
||||
"rna_Object_data_get",
|
||||
"rna_Object_data_set",
|
||||
"rna_Object_data_typef",
|
||||
"rna_Object_data_poll");
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
|
||||
RNA_def_property_ui_text(prop, "Data", "Object data");
|
||||
RNA_def_property_update(prop, 0, "rna_Object_data_update");
|
||||
|
|
|
@ -329,10 +329,6 @@ static void velocity_panel_draw(const bContext *UNUSED(C), Panel *panel)
|
|||
return;
|
||||
}
|
||||
|
||||
if (RNA_pointer_is_null(&fileptr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uiLayoutSetPropSep(layout, true);
|
||||
uiTemplateCacheFileVelocity(layout, &fileptr);
|
||||
uiItemR(layout, ptr, "velocity_scale", 0, NULL, ICON_NONE);
|
||||
|
@ -350,10 +346,6 @@ static void time_panel_draw(const bContext *UNUSED(C), Panel *panel)
|
|||
return;
|
||||
}
|
||||
|
||||
if (RNA_pointer_is_null(&fileptr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uiLayoutSetPropSep(layout, true);
|
||||
uiTemplateCacheFileTimeSettings(layout, &fileptr);
|
||||
}
|
||||
|
@ -370,10 +362,6 @@ static void render_procedural_panel_draw(const bContext *C, Panel *panel)
|
|||
return;
|
||||
}
|
||||
|
||||
if (RNA_pointer_is_null(&fileptr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uiLayoutSetPropSep(layout, true);
|
||||
uiTemplateCacheFileProcedural(layout, C, &fileptr);
|
||||
}
|
||||
|
@ -390,10 +378,6 @@ static void override_layers_panel_draw(const bContext *C, Panel *panel)
|
|||
return;
|
||||
}
|
||||
|
||||
if (RNA_pointer_is_null(&fileptr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uiLayoutSetPropSep(layout, true);
|
||||
uiTemplateCacheFileLayers(layout, C, &fileptr);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue