Cleanup: Use Array and Span for mesh draw buffer cache data
Use C++ types for more automatic memory management, simpler code, and easier potential performance improvements. Also document each item in the cache and access a named struct by pointer for the "poly sorted" instead of using an identical unnamed struct.
This commit is contained in:
@@ -222,10 +222,19 @@ ENUM_OPERATORS(DRWBatchFlag, MBC_SURFACE_PER_MAT);
|
||||
BLI_STATIC_ASSERT(MBC_BATCH_LEN < 32, "Number of batches exceeded the limit of bit fields");
|
||||
|
||||
struct MeshExtractLooseGeom {
|
||||
int edge_len;
|
||||
int vert_len;
|
||||
int *verts;
|
||||
int *edges;
|
||||
/** Indices of all vertices not used by edges in the #Mesh or #BMesh. */
|
||||
blender::Array<int> verts;
|
||||
/** Indices of all edges not used by faces in the #Mesh or #BMesh. */
|
||||
blender::Array<int> edges;
|
||||
};
|
||||
|
||||
struct SortedPolyData {
|
||||
/** The first triangle index for each polygon, sorted into slices by material. */
|
||||
blender::Array<int> tri_first_index;
|
||||
/** The number of visible triangles assigned to each material. */
|
||||
blender::Array<int> mat_tri_len;
|
||||
/* The total number of visible triangles (a sum of the values in #mat_tri_len). */
|
||||
int visible_tri_len;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -238,11 +247,7 @@ struct MeshBufferCache {
|
||||
|
||||
MeshExtractLooseGeom loose_geom;
|
||||
|
||||
struct {
|
||||
int *tri_first_index;
|
||||
int *mat_tri_len;
|
||||
int visible_tri_len;
|
||||
} poly_sorted;
|
||||
SortedPolyData poly_sorted;
|
||||
};
|
||||
|
||||
#define FOREACH_MESH_BUFFER_CACHE(batch_cache, mbc) \
|
||||
|
||||
@@ -397,13 +397,13 @@ BLI_INLINE void extract_task_range_run_iter(const MeshRenderData *mr,
|
||||
stop = mr->poly_len;
|
||||
break;
|
||||
case MR_ITER_LEDGE:
|
||||
range_data.loose_elems = mr->ledges;
|
||||
range_data.loose_elems = mr->ledges.data();
|
||||
range_data.elems = is_mesh ? mr->edges.data() : (void *)mr->bm->etable;
|
||||
func = is_mesh ? extract_range_iter_ledge_mesh : extract_range_iter_ledge_bm;
|
||||
stop = mr->edge_loose_len;
|
||||
break;
|
||||
case MR_ITER_LVERT:
|
||||
range_data.loose_elems = mr->lverts;
|
||||
range_data.loose_elems = mr->lverts.data();
|
||||
range_data.elems = is_mesh ? mr->vert_positions.data() : (void *)mr->bm->vtable;
|
||||
func = is_mesh ? extract_range_iter_lvert_mesh : extract_range_iter_lvert_bm;
|
||||
stop = mr->vert_loose_len;
|
||||
|
||||
@@ -39,21 +39,11 @@ static void mesh_render_data_ledges_bm(const MeshRenderData *mr,
|
||||
static void mesh_render_data_loose_geom_mesh(const MeshRenderData *mr, MeshBufferCache *cache);
|
||||
static void mesh_render_data_loose_geom_build(const MeshRenderData *mr, MeshBufferCache *cache);
|
||||
|
||||
static void mesh_render_data_loose_geom_load(MeshRenderData *mr, MeshBufferCache *cache)
|
||||
{
|
||||
mr->ledges = cache->loose_geom.edges;
|
||||
mr->lverts = cache->loose_geom.verts;
|
||||
mr->vert_loose_len = cache->loose_geom.vert_len;
|
||||
mr->edge_loose_len = cache->loose_geom.edge_len;
|
||||
|
||||
mr->loop_loose_len = mr->vert_loose_len + (mr->edge_loose_len * 2);
|
||||
}
|
||||
|
||||
static void mesh_render_data_loose_geom_ensure(const MeshRenderData *mr, MeshBufferCache *cache)
|
||||
{
|
||||
/* Early exit: Are loose geometry already available.
|
||||
* Only checking for loose verts as loose edges and verts are calculated at the same time. */
|
||||
if (cache->loose_geom.verts) {
|
||||
if (!cache->loose_geom.verts.is_empty()) {
|
||||
return;
|
||||
}
|
||||
mesh_render_data_loose_geom_build(mr, cache);
|
||||
@@ -61,9 +51,6 @@ static void mesh_render_data_loose_geom_ensure(const MeshRenderData *mr, MeshBuf
|
||||
|
||||
static void mesh_render_data_loose_geom_build(const MeshRenderData *mr, MeshBufferCache *cache)
|
||||
{
|
||||
cache->loose_geom.vert_len = 0;
|
||||
cache->loose_geom.edge_len = 0;
|
||||
|
||||
if (mr->extract_type != MR_EXTRACT_BMESH) {
|
||||
/* Mesh */
|
||||
mesh_render_data_loose_geom_mesh(mr, cache);
|
||||
@@ -83,14 +70,13 @@ static void mesh_render_data_loose_geom_mesh(const MeshRenderData *mr, MeshBuffe
|
||||
|
||||
const bke::LooseEdgeCache &loose_edges = mr->me->loose_edges();
|
||||
if (loose_edges.count > 0) {
|
||||
cache->loose_geom.edges = static_cast<int *>(
|
||||
MEM_malloc_arrayN(loose_edges.count, sizeof(int), __func__));
|
||||
cache->loose_geom.edges.reinitialize(loose_edges.count);
|
||||
|
||||
cache->loose_geom.edge_len = 0;
|
||||
int count = 0;
|
||||
for (const int64_t i : loose_edges.is_loose_bits.index_range()) {
|
||||
if (loose_edges.is_loose_bits[i]) {
|
||||
cache->loose_geom.edges[cache->loose_geom.edge_len] = int(i);
|
||||
cache->loose_geom.edge_len++;
|
||||
cache->loose_geom.edges[count] = int(i);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -101,16 +87,19 @@ static void mesh_render_data_loose_geom_mesh(const MeshRenderData *mr, MeshBuffe
|
||||
BLI_BITMAP_ENABLE(lvert_map, edge.v2);
|
||||
}
|
||||
|
||||
cache->loose_geom.verts = static_cast<int *>(
|
||||
MEM_mallocN(mr->vert_len * sizeof(*cache->loose_geom.verts), __func__));
|
||||
int count = 0;
|
||||
Array<int> loose_verts(mr->vert_len);
|
||||
for (int v = 0; v < mr->vert_len; v++) {
|
||||
if (!BLI_BITMAP_TEST(lvert_map, v)) {
|
||||
cache->loose_geom.verts[cache->loose_geom.vert_len++] = v;
|
||||
loose_verts[count] = v;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (cache->loose_geom.vert_len < mr->vert_len) {
|
||||
cache->loose_geom.verts = static_cast<int *>(MEM_reallocN(
|
||||
cache->loose_geom.verts, cache->loose_geom.vert_len * sizeof(*cache->loose_geom.verts)));
|
||||
if (count < mr->vert_len) {
|
||||
cache->loose_geom.verts = loose_verts.as_span().take_front(count);
|
||||
}
|
||||
else {
|
||||
cache->loose_geom.verts = std::move(loose_verts);
|
||||
}
|
||||
|
||||
MEM_freeN(lvert_map);
|
||||
@@ -118,37 +107,45 @@ static void mesh_render_data_loose_geom_mesh(const MeshRenderData *mr, MeshBuffe
|
||||
|
||||
static void mesh_render_data_lverts_bm(const MeshRenderData *mr, MeshBufferCache *cache, BMesh *bm)
|
||||
{
|
||||
using namespace blender;
|
||||
int elem_id;
|
||||
BMIter iter;
|
||||
BMVert *eve;
|
||||
cache->loose_geom.verts = static_cast<int *>(
|
||||
MEM_mallocN(mr->vert_len * sizeof(*cache->loose_geom.verts), __func__));
|
||||
int count = 0;
|
||||
Array<int> loose_verts(mr->vert_len);
|
||||
BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, elem_id) {
|
||||
if (eve->e == nullptr) {
|
||||
cache->loose_geom.verts[cache->loose_geom.vert_len++] = elem_id;
|
||||
loose_verts[count] = elem_id;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (cache->loose_geom.vert_len < mr->vert_len) {
|
||||
cache->loose_geom.verts = static_cast<int *>(MEM_reallocN(
|
||||
cache->loose_geom.verts, cache->loose_geom.vert_len * sizeof(*cache->loose_geom.verts)));
|
||||
if (count < mr->vert_len) {
|
||||
cache->loose_geom.verts = loose_verts.as_span().take_front(count);
|
||||
}
|
||||
else {
|
||||
cache->loose_geom.verts = std::move(loose_verts);
|
||||
}
|
||||
}
|
||||
|
||||
static void mesh_render_data_ledges_bm(const MeshRenderData *mr, MeshBufferCache *cache, BMesh *bm)
|
||||
{
|
||||
using namespace blender;
|
||||
int elem_id;
|
||||
BMIter iter;
|
||||
BMEdge *ede;
|
||||
cache->loose_geom.edges = static_cast<int *>(
|
||||
MEM_mallocN(mr->edge_len * sizeof(*cache->loose_geom.edges), __func__));
|
||||
int count = 0;
|
||||
Array<int> loose_edges(mr->edge_len);
|
||||
BM_ITER_MESH_INDEX (ede, &iter, bm, BM_EDGES_OF_MESH, elem_id) {
|
||||
if (ede->l == nullptr) {
|
||||
cache->loose_geom.edges[cache->loose_geom.edge_len++] = elem_id;
|
||||
loose_edges[count] = elem_id;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (cache->loose_geom.edge_len < mr->edge_len) {
|
||||
cache->loose_geom.edges = static_cast<int *>(MEM_reallocN(
|
||||
cache->loose_geom.edges, cache->loose_geom.edge_len * sizeof(*cache->loose_geom.edges)));
|
||||
if (count < mr->edge_len) {
|
||||
cache->loose_geom.edges = loose_edges.as_span().take_front(count);
|
||||
}
|
||||
else {
|
||||
cache->loose_geom.edges = std::move(loose_edges);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,7 +156,12 @@ void mesh_render_data_update_loose_geom(MeshRenderData *mr,
|
||||
{
|
||||
if ((iter_type & (MR_ITER_LEDGE | MR_ITER_LVERT)) || (data_flag & MR_DATA_LOOSE_GEOM)) {
|
||||
mesh_render_data_loose_geom_ensure(mr, cache);
|
||||
mesh_render_data_loose_geom_load(mr, cache);
|
||||
mr->ledges = cache->loose_geom.edges;
|
||||
mr->lverts = cache->loose_geom.verts;
|
||||
mr->vert_loose_len = cache->loose_geom.verts.size();
|
||||
mr->edge_loose_len = cache->loose_geom.edges.size();
|
||||
|
||||
mr->loop_loose_len = mr->vert_loose_len + (mr->edge_loose_len * 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,10 +173,10 @@ void mesh_render_data_update_loose_geom(MeshRenderData *mr,
|
||||
* Contains polygon indices sorted based on their material.
|
||||
* \{ */
|
||||
|
||||
static void mesh_render_data_polys_sorted_load(MeshRenderData *mr, const MeshBufferCache *cache);
|
||||
static void mesh_render_data_polys_sorted_ensure(MeshRenderData *mr, MeshBufferCache *cache);
|
||||
static void mesh_render_data_polys_sorted_build(MeshRenderData *mr, MeshBufferCache *cache);
|
||||
static int *mesh_render_data_mat_tri_len_build(MeshRenderData *mr);
|
||||
static void mesh_render_data_mat_tri_len_build(MeshRenderData *mr,
|
||||
blender::MutableSpan<int> mat_tri_len);
|
||||
|
||||
void mesh_render_data_update_polys_sorted(MeshRenderData *mr,
|
||||
MeshBufferCache *cache,
|
||||
@@ -182,20 +184,13 @@ void mesh_render_data_update_polys_sorted(MeshRenderData *mr,
|
||||
{
|
||||
if (data_flag & MR_DATA_POLYS_SORTED) {
|
||||
mesh_render_data_polys_sorted_ensure(mr, cache);
|
||||
mesh_render_data_polys_sorted_load(mr, cache);
|
||||
mr->poly_sorted = &cache->poly_sorted;
|
||||
}
|
||||
}
|
||||
|
||||
static void mesh_render_data_polys_sorted_load(MeshRenderData *mr, const MeshBufferCache *cache)
|
||||
{
|
||||
mr->poly_sorted.tri_first_index = cache->poly_sorted.tri_first_index;
|
||||
mr->poly_sorted.mat_tri_len = cache->poly_sorted.mat_tri_len;
|
||||
mr->poly_sorted.visible_tri_len = cache->poly_sorted.visible_tri_len;
|
||||
}
|
||||
|
||||
static void mesh_render_data_polys_sorted_ensure(MeshRenderData *mr, MeshBufferCache *cache)
|
||||
{
|
||||
if (cache->poly_sorted.tri_first_index) {
|
||||
if (!cache->poly_sorted.tri_first_index.is_empty()) {
|
||||
return;
|
||||
}
|
||||
mesh_render_data_polys_sorted_build(mr, cache);
|
||||
@@ -203,9 +198,12 @@ static void mesh_render_data_polys_sorted_ensure(MeshRenderData *mr, MeshBufferC
|
||||
|
||||
static void mesh_render_data_polys_sorted_build(MeshRenderData *mr, MeshBufferCache *cache)
|
||||
{
|
||||
int *tri_first_index = static_cast<int *>(
|
||||
MEM_mallocN(sizeof(*tri_first_index) * mr->poly_len, __func__));
|
||||
int *mat_tri_len = mesh_render_data_mat_tri_len_build(mr);
|
||||
using namespace blender;
|
||||
cache->poly_sorted.tri_first_index.reinitialize(mr->poly_len);
|
||||
cache->poly_sorted.mat_tri_len.reinitialize(mr->mat_len);
|
||||
|
||||
mesh_render_data_mat_tri_len_build(mr, cache->poly_sorted.mat_tri_len);
|
||||
const Span<int> mat_tri_len = cache->poly_sorted.mat_tri_len;
|
||||
|
||||
/* Apply offset. */
|
||||
int visible_tri_len = 0;
|
||||
@@ -216,6 +214,9 @@ static void mesh_render_data_polys_sorted_build(MeshRenderData *mr, MeshBufferCa
|
||||
visible_tri_len += mat_tri_len[i];
|
||||
}
|
||||
}
|
||||
cache->poly_sorted.visible_tri_len = visible_tri_len;
|
||||
|
||||
MutableSpan<int> tri_first_index = cache->poly_sorted.tri_first_index;
|
||||
|
||||
/* Sort per material. */
|
||||
int mat_last = mr->mat_len - 1;
|
||||
@@ -247,10 +248,6 @@ static void mesh_render_data_polys_sorted_build(MeshRenderData *mr, MeshBufferCa
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cache->poly_sorted.tri_first_index = tri_first_index;
|
||||
cache->poly_sorted.mat_tri_len = mat_tri_len;
|
||||
cache->poly_sorted.visible_tri_len = visible_tri_len;
|
||||
}
|
||||
|
||||
static void mesh_render_data_mat_tri_len_bm_range_fn(void *__restrict userdata,
|
||||
@@ -296,35 +293,33 @@ static void mesh_render_data_mat_tri_len_reduce_fn(const void *__restrict userda
|
||||
}
|
||||
}
|
||||
|
||||
static int *mesh_render_data_mat_tri_len_build_threaded(MeshRenderData *mr,
|
||||
static void mesh_render_data_mat_tri_len_build_threaded(MeshRenderData *mr,
|
||||
int face_len,
|
||||
TaskParallelRangeFunc range_func)
|
||||
TaskParallelRangeFunc range_func,
|
||||
blender::MutableSpan<int> mat_tri_len)
|
||||
{
|
||||
/* Extending the #MatOffsetUserData with an int per material slot. */
|
||||
size_t mat_tri_len_size = sizeof(int) * mr->mat_len;
|
||||
int *mat_tri_len = static_cast<int *>(MEM_callocN(mat_tri_len_size, __func__));
|
||||
|
||||
TaskParallelSettings settings;
|
||||
BLI_parallel_range_settings_defaults(&settings);
|
||||
settings.userdata_chunk = mat_tri_len;
|
||||
settings.userdata_chunk_size = mat_tri_len_size;
|
||||
settings.userdata_chunk = mat_tri_len.data();
|
||||
settings.userdata_chunk_size = mat_tri_len.as_span().size_in_bytes();
|
||||
settings.min_iter_per_thread = MIN_RANGE_LEN;
|
||||
settings.func_reduce = mesh_render_data_mat_tri_len_reduce_fn;
|
||||
BLI_task_parallel_range(0, face_len, mr, range_func, &settings);
|
||||
|
||||
return mat_tri_len;
|
||||
}
|
||||
|
||||
/* Count how many triangles for each material. */
|
||||
static int *mesh_render_data_mat_tri_len_build(MeshRenderData *mr)
|
||||
static void mesh_render_data_mat_tri_len_build(MeshRenderData *mr,
|
||||
blender::MutableSpan<int> mat_tri_len)
|
||||
{
|
||||
if (mr->extract_type == MR_EXTRACT_BMESH) {
|
||||
BMesh *bm = mr->bm;
|
||||
return mesh_render_data_mat_tri_len_build_threaded(
|
||||
mr, bm->totface, mesh_render_data_mat_tri_len_bm_range_fn);
|
||||
mesh_render_data_mat_tri_len_build_threaded(
|
||||
mr, bm->totface, mesh_render_data_mat_tri_len_bm_range_fn, mat_tri_len);
|
||||
}
|
||||
else {
|
||||
mesh_render_data_mat_tri_len_build_threaded(
|
||||
mr, mr->poly_len, mesh_render_data_mat_tri_len_mesh_range_fn, mat_tri_len);
|
||||
}
|
||||
return mesh_render_data_mat_tri_len_build_threaded(
|
||||
mr, mr->poly_len, mesh_render_data_mat_tri_len_mesh_range_fn);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
@@ -594,11 +589,6 @@ MeshRenderData *mesh_render_data_create(Object *object,
|
||||
|
||||
void mesh_render_data_free(MeshRenderData *mr)
|
||||
{
|
||||
|
||||
/* Loose geometry are owned by #MeshBufferCache. */
|
||||
mr->ledges = nullptr;
|
||||
mr->lverts = nullptr;
|
||||
|
||||
MEM_delete(mr);
|
||||
}
|
||||
|
||||
|
||||
@@ -575,15 +575,13 @@ static bool mesh_batch_cache_valid(Object *object, Mesh *me)
|
||||
|
||||
static void mesh_batch_cache_init(Object *object, Mesh *me)
|
||||
{
|
||||
MeshBatchCache *cache = static_cast<MeshBatchCache *>(me->runtime->batch_cache);
|
||||
|
||||
if (!cache) {
|
||||
me->runtime->batch_cache = MEM_cnew<MeshBatchCache>(__func__);
|
||||
cache = static_cast<MeshBatchCache *>(me->runtime->batch_cache);
|
||||
if (!me->runtime->batch_cache) {
|
||||
me->runtime->batch_cache = MEM_new<MeshBatchCache>(__func__);
|
||||
}
|
||||
else {
|
||||
memset(cache, 0, sizeof(*cache));
|
||||
*static_cast<MeshBatchCache *>(me->runtime->batch_cache) = {};
|
||||
}
|
||||
MeshBatchCache *cache = static_cast<MeshBatchCache *>(me->runtime->batch_cache);
|
||||
|
||||
cache->is_editmode = me->edit_mesh != nullptr;
|
||||
|
||||
@@ -798,14 +796,8 @@ static void mesh_buffer_cache_clear(MeshBufferCache *mbc)
|
||||
{
|
||||
mesh_buffer_list_clear(&mbc->buff);
|
||||
|
||||
MEM_SAFE_FREE(mbc->loose_geom.verts);
|
||||
MEM_SAFE_FREE(mbc->loose_geom.edges);
|
||||
mbc->loose_geom.edge_len = 0;
|
||||
mbc->loose_geom.vert_len = 0;
|
||||
|
||||
MEM_SAFE_FREE(mbc->poly_sorted.tri_first_index);
|
||||
MEM_SAFE_FREE(mbc->poly_sorted.mat_tri_len);
|
||||
mbc->poly_sorted.visible_tri_len = 0;
|
||||
mbc->loose_geom = {};
|
||||
mbc->poly_sorted = {};
|
||||
}
|
||||
|
||||
static void mesh_batch_cache_free_subdiv_cache(MeshBatchCache *cache)
|
||||
@@ -846,10 +838,9 @@ static void mesh_batch_cache_clear(MeshBatchCache *cache)
|
||||
|
||||
void DRW_mesh_batch_cache_free(void *batch_cache)
|
||||
{
|
||||
if (batch_cache) {
|
||||
mesh_batch_cache_clear(static_cast<MeshBatchCache *>(batch_cache));
|
||||
MEM_freeN(batch_cache);
|
||||
}
|
||||
MeshBatchCache *cache = static_cast<MeshBatchCache *>(batch_cache);
|
||||
mesh_batch_cache_clear(cache);
|
||||
MEM_delete(cache);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
@@ -2188,8 +2188,8 @@ static bool draw_subdiv_create_requested_buffers(Object *ob,
|
||||
|
||||
void DRW_subdivide_loose_geom(DRWSubdivCache *subdiv_cache, MeshBufferCache *cache)
|
||||
{
|
||||
const int coarse_loose_vert_len = cache->loose_geom.vert_len;
|
||||
const int coarse_loose_edge_len = cache->loose_geom.edge_len;
|
||||
const int coarse_loose_vert_len = cache->loose_geom.verts.size();
|
||||
const int coarse_loose_edge_len = cache->loose_geom.edges.size();
|
||||
|
||||
if (coarse_loose_vert_len == 0 && coarse_loose_edge_len == 0) {
|
||||
/* Nothing to do. */
|
||||
|
||||
@@ -97,16 +97,13 @@ struct MeshRenderData {
|
||||
const bool *select_poly;
|
||||
const bool *sharp_faces;
|
||||
blender::Array<blender::float3> loop_normals;
|
||||
int *lverts, *ledges;
|
||||
|
||||
blender::Span<int> lverts;
|
||||
blender::Span<int> ledges;
|
||||
const SortedPolyData *poly_sorted;
|
||||
|
||||
const char *active_color_name;
|
||||
const char *default_color_name;
|
||||
|
||||
struct {
|
||||
int *tri_first_index;
|
||||
int *mat_tri_len;
|
||||
int visible_tri_len;
|
||||
} poly_sorted;
|
||||
};
|
||||
|
||||
BLI_INLINE const Mesh *editmesh_final_or_this(const Object *object, const Mesh *me)
|
||||
|
||||
@@ -30,7 +30,7 @@ static void extract_tris_init(const MeshRenderData *mr,
|
||||
void *tls_data)
|
||||
{
|
||||
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(tls_data);
|
||||
GPU_indexbuf_init(elb, GPU_PRIM_TRIS, mr->poly_sorted.visible_tri_len, mr->loop_len);
|
||||
GPU_indexbuf_init(elb, GPU_PRIM_TRIS, mr->poly_sorted->visible_tri_len, mr->loop_len);
|
||||
}
|
||||
|
||||
static void extract_tris_iter_poly_bm(const MeshRenderData *mr,
|
||||
@@ -38,7 +38,7 @@ static void extract_tris_iter_poly_bm(const MeshRenderData *mr,
|
||||
const int f_index,
|
||||
void *_data)
|
||||
{
|
||||
int tri_first_index = mr->poly_sorted.tri_first_index[f_index];
|
||||
int tri_first_index = mr->poly_sorted->tri_first_index[f_index];
|
||||
if (tri_first_index == -1) {
|
||||
return;
|
||||
}
|
||||
@@ -64,7 +64,7 @@ static void extract_tris_iter_poly_mesh(const MeshRenderData *mr,
|
||||
const int poly_index,
|
||||
void *_data)
|
||||
{
|
||||
int tri_first_index = mr->poly_sorted.tri_first_index[poly_index];
|
||||
int tri_first_index = mr->poly_sorted->tri_first_index[poly_index];
|
||||
if (tri_first_index == -1) {
|
||||
return;
|
||||
}
|
||||
@@ -99,7 +99,7 @@ static void extract_tris_finish(const MeshRenderData *mr,
|
||||
if (cache->tris_per_mat[i] == nullptr) {
|
||||
cache->tris_per_mat[i] = GPU_indexbuf_calloc();
|
||||
}
|
||||
const int mat_tri_len = mr->poly_sorted.mat_tri_len[i];
|
||||
const int mat_tri_len = mr->poly_sorted->mat_tri_len[i];
|
||||
/* Multiply by 3 because these are triangle indices. */
|
||||
const int start = mat_start * 3;
|
||||
const int len = mat_tri_len * 3;
|
||||
|
||||
Reference in New Issue
Block a user