Mesh: Draw: Replace extractor abstraction for edit data buffer
Part of #116901. Due to the BMesh data format, there is less optimization possible here.
This commit is contained in:
@@ -644,7 +644,6 @@ void mesh_buffer_cache_create_requested(TaskGraph &task_graph,
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
EXTRACT_ADD_REQUESTED(vbo, edituv_data);
|
||||
EXTRACT_ADD_REQUESTED(vbo, fdots_edituv_data);
|
||||
for (int i = 0; i < GPU_MAX_ATTR; i++) {
|
||||
EXTRACT_ADD_REQUESTED(vbo, attr[i]);
|
||||
@@ -670,6 +669,7 @@ void mesh_buffer_cache_create_requested(TaskGraph &task_graph,
|
||||
!DRW_vbo_requested(buffers.vbo.weights) && !DRW_vbo_requested(buffers.vbo.fdots_uv) &&
|
||||
!DRW_vbo_requested(buffers.vbo.uv) && !DRW_vbo_requested(buffers.vbo.edituv_stretch_area) &&
|
||||
!DRW_vbo_requested(buffers.vbo.edituv_stretch_angle) &&
|
||||
!DRW_vbo_requested(buffers.vbo.edituv_data) &&
|
||||
!DRW_ibo_requested(buffers.ibo.lines_paint_mask) &&
|
||||
!DRW_ibo_requested(buffers.ibo.lines_adjacency) &&
|
||||
!DRW_vbo_requested(buffers.vbo.skin_roots) && !DRW_vbo_requested(buffers.vbo.sculpt_data) &&
|
||||
@@ -1009,6 +1009,21 @@ void mesh_buffer_cache_create_requested(TaskGraph &task_graph,
|
||||
[](void *task_data) { delete static_cast<TaskData *>(task_data); });
|
||||
BLI_task_graph_edge_create(task_node_mesh_render_data, task_node);
|
||||
}
|
||||
if (DRW_vbo_requested(buffers.vbo.edituv_data)) {
|
||||
struct TaskData {
|
||||
MeshRenderData &mr;
|
||||
MeshBufferList &buffers;
|
||||
};
|
||||
TaskNode *task_node = BLI_task_graph_node_create(
|
||||
&task_graph,
|
||||
[](void *__restrict task_data) {
|
||||
const TaskData &data = *static_cast<TaskData *>(task_data);
|
||||
extract_edituv_data(data.mr, *data.buffers.vbo.edituv_data);
|
||||
},
|
||||
new TaskData{*mr, buffers},
|
||||
[](void *task_data) { delete static_cast<TaskData *>(task_data); });
|
||||
BLI_task_graph_edge_create(task_node_mesh_render_data, task_node);
|
||||
}
|
||||
if (DRW_ibo_requested(buffers.ibo.lines_paint_mask)) {
|
||||
struct TaskData {
|
||||
MeshRenderData &mr;
|
||||
@@ -1197,7 +1212,6 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache,
|
||||
EXTRACT_ADD_REQUESTED(ibo, edituv_points);
|
||||
EXTRACT_ADD_REQUESTED(ibo, edituv_tris);
|
||||
EXTRACT_ADD_REQUESTED(ibo, edituv_lines);
|
||||
EXTRACT_ADD_REQUESTED(vbo, edituv_data);
|
||||
|
||||
#undef EXTRACT_ADD_REQUESTED
|
||||
|
||||
@@ -1212,6 +1226,7 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache,
|
||||
!DRW_vbo_requested(buffers.vbo.fdots_pos) && !DRW_ibo_requested(buffers.ibo.fdots) &&
|
||||
!DRW_vbo_requested(buffers.vbo.uv) && !DRW_vbo_requested(buffers.vbo.edituv_stretch_area) &&
|
||||
!DRW_vbo_requested(buffers.vbo.edituv_stretch_angle) &&
|
||||
!DRW_vbo_requested(buffers.vbo.edituv_data) &&
|
||||
!DRW_ibo_requested(buffers.ibo.lines_paint_mask) &&
|
||||
!DRW_ibo_requested(buffers.ibo.lines_adjacency) &&
|
||||
!DRW_vbo_requested(buffers.vbo.sculpt_data))
|
||||
@@ -1289,6 +1304,9 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache,
|
||||
extract_edituv_stretch_angle_subdiv(
|
||||
mr, subdiv_cache, cache, *buffers.vbo.edituv_stretch_angle);
|
||||
}
|
||||
if (DRW_vbo_requested(buffers.vbo.edituv_data)) {
|
||||
extract_edituv_data_subdiv(mr, subdiv_cache, *buffers.vbo.edituv_data);
|
||||
}
|
||||
|
||||
void *data_stack = MEM_mallocN(extractors.data_size_total(), __func__);
|
||||
uint32_t data_offset = 0;
|
||||
|
||||
@@ -470,6 +470,10 @@ void extract_edituv_stretch_angle_subdiv(const MeshRenderData &mr,
|
||||
const DRWSubdivCache &subdiv_cache,
|
||||
const MeshBatchCache &cache,
|
||||
gpu::VertBuf &vbo);
|
||||
void extract_edituv_data(const MeshRenderData &mr, gpu::VertBuf &vbo);
|
||||
void extract_edituv_data_subdiv(const MeshRenderData &mr,
|
||||
const DRWSubdivCache &subdiv_cache,
|
||||
gpu::VertBuf &vbo);
|
||||
|
||||
void extract_skin_roots(const MeshRenderData &mr, gpu::VertBuf &vbo);
|
||||
|
||||
@@ -486,7 +490,6 @@ extern const MeshExtract extract_edituv_tris;
|
||||
extern const MeshExtract extract_edituv_lines;
|
||||
extern const MeshExtract extract_edituv_points;
|
||||
extern const MeshExtract extract_edituv_fdots;
|
||||
extern const MeshExtract extract_edituv_data;
|
||||
extern const MeshExtract extract_fdots_edituv_data;
|
||||
extern const MeshExtract extract_attr[GPU_MAX_ATTR];
|
||||
extern const MeshExtract extract_attr_viewer;
|
||||
|
||||
@@ -20,15 +20,7 @@ namespace blender::draw {
|
||||
/** \name Extract Edit UV Data / Flags
|
||||
* \{ */
|
||||
|
||||
struct MeshExtract_EditUVData_Data {
|
||||
EditLoopData *vbo_data;
|
||||
BMUVOffsets offsets;
|
||||
};
|
||||
|
||||
static void extract_edituv_data_init_common(const MeshRenderData &mr,
|
||||
gpu::VertBuf *vbo,
|
||||
MeshExtract_EditUVData_Data *data,
|
||||
uint loop_len)
|
||||
static const GPUVertFormat &edituv_data_format()
|
||||
{
|
||||
static GPUVertFormat format = {0};
|
||||
if (format.attr_len == 0) {
|
||||
@@ -36,98 +28,96 @@ static void extract_edituv_data_init_common(const MeshRenderData &mr,
|
||||
GPU_vertformat_attr_add(&format, "data", GPU_COMP_U8, 4, GPU_FETCH_INT);
|
||||
GPU_vertformat_alias_add(&format, "flag");
|
||||
}
|
||||
|
||||
GPU_vertbuf_init_with_format(vbo, &format);
|
||||
GPU_vertbuf_data_alloc(vbo, loop_len);
|
||||
|
||||
data->vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo);
|
||||
data->offsets = BM_uv_map_get_offsets(mr.bm);
|
||||
return format;
|
||||
}
|
||||
|
||||
static void extract_edituv_data_init(const MeshRenderData &mr,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void *buf,
|
||||
void *tls_data)
|
||||
static void extract_edituv_data_bm(const MeshRenderData &mr, MutableSpan<EditLoopData> vbo_data)
|
||||
{
|
||||
gpu::VertBuf *vbo = static_cast<gpu::VertBuf *>(buf);
|
||||
MeshExtract_EditUVData_Data *data = static_cast<MeshExtract_EditUVData_Data *>(tls_data);
|
||||
extract_edituv_data_init_common(mr, vbo, data, mr.corners_num);
|
||||
}
|
||||
|
||||
static void extract_edituv_data_iter_face_bm(const MeshRenderData &mr,
|
||||
const BMFace *f,
|
||||
const int /*f_index*/,
|
||||
void *_data)
|
||||
{
|
||||
BMLoop *l_iter, *l_first;
|
||||
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
|
||||
do {
|
||||
const int l_index = BM_elem_index_get(l_iter);
|
||||
MeshExtract_EditUVData_Data *data = static_cast<MeshExtract_EditUVData_Data *>(_data);
|
||||
EditLoopData *eldata = &data->vbo_data[l_index];
|
||||
memset(eldata, 0x0, sizeof(*eldata));
|
||||
mesh_render_data_loop_flag(mr, l_iter, data->offsets, *eldata);
|
||||
mesh_render_data_face_flag(mr, f, data->offsets, *eldata);
|
||||
mesh_render_data_loop_edge_flag(mr, l_iter, data->offsets, *eldata);
|
||||
} while ((l_iter = l_iter->next) != l_first);
|
||||
}
|
||||
|
||||
static void extract_edituv_data_iter_face_mesh(const MeshRenderData &mr,
|
||||
const int face_index,
|
||||
void *_data)
|
||||
{
|
||||
MeshExtract_EditUVData_Data *data = static_cast<MeshExtract_EditUVData_Data *>(_data);
|
||||
const IndexRange face = mr.faces[face_index];
|
||||
for (const int corner : face) {
|
||||
EditLoopData *eldata = &data->vbo_data[corner];
|
||||
memset(eldata, 0x0, sizeof(*eldata));
|
||||
BMFace *efa = bm_original_face_get(mr, face_index);
|
||||
if (efa) {
|
||||
BMVert *eve = bm_original_vert_get(mr, mr.corner_verts[corner]);
|
||||
BMEdge *eed = bm_original_edge_get(mr, mr.corner_edges[corner]);
|
||||
if (eed && eve) {
|
||||
/* Loop on an edge endpoint. */
|
||||
BMLoop *l = BM_face_edge_share_loop(efa, eed);
|
||||
mesh_render_data_loop_flag(mr, l, data->offsets, *eldata);
|
||||
mesh_render_data_loop_edge_flag(mr, l, data->offsets, *eldata);
|
||||
const BMesh &bm = *mr.bm;
|
||||
const BMUVOffsets offsets = BM_uv_map_get_offsets(&bm);
|
||||
threading::parallel_for(IndexRange(bm.totface), 2048, [&](const IndexRange range) {
|
||||
for (const int face_index : range) {
|
||||
const BMFace &face = *BM_face_at_index(&const_cast<BMesh &>(bm), face_index);
|
||||
const BMLoop *loop = BM_FACE_FIRST_LOOP(&face);
|
||||
for ([[maybe_unused]] const int i : IndexRange(face.len)) {
|
||||
const int index = BM_elem_index_get(loop);
|
||||
EditLoopData &value = vbo_data[index];
|
||||
value = {};
|
||||
mesh_render_data_loop_flag(mr, loop, offsets, value);
|
||||
mesh_render_data_face_flag(mr, &face, offsets, value);
|
||||
mesh_render_data_loop_edge_flag(mr, loop, offsets, value);
|
||||
loop = loop->next;
|
||||
}
|
||||
else {
|
||||
if (eed == nullptr) {
|
||||
/* Find if the loop's vert is not part of an edit edge.
|
||||
* For this, we check if the previous loop was on an edge. */
|
||||
const int corner_prev = bke::mesh::face_corner_prev(face, corner);
|
||||
eed = bm_original_edge_get(mr, mr.corner_edges[corner_prev]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void extract_edituv_data_mesh(const MeshRenderData &mr, MutableSpan<EditLoopData> vbo_data)
|
||||
{
|
||||
const BMesh &bm = *mr.bm;
|
||||
const BMUVOffsets offsets = BM_uv_map_get_offsets(&bm);
|
||||
const OffsetIndices faces = mr.faces;
|
||||
const Span<int> corner_verts = mr.corner_verts;
|
||||
const Span<int> corner_edges = mr.corner_edges;
|
||||
threading::parallel_for(faces.index_range(), 2048, [&](const IndexRange range) {
|
||||
for (const int face_index : range) {
|
||||
const IndexRange face = faces[face_index];
|
||||
BMFace *face_orig = bm_original_face_get(mr, face_index);
|
||||
if (!face_orig) {
|
||||
vbo_data.slice(face).fill({});
|
||||
continue;
|
||||
}
|
||||
for (const int corner : face) {
|
||||
EditLoopData &value = vbo_data[corner];
|
||||
value = {};
|
||||
BMVert *vert = bm_original_vert_get(mr, corner_verts[corner]);
|
||||
BMEdge *edge = bm_original_edge_get(mr, corner_edges[corner]);
|
||||
if (edge && vert) {
|
||||
/* Loop on an edge endpoint. */
|
||||
BMLoop *l = BM_face_edge_share_loop(face_orig, edge);
|
||||
mesh_render_data_loop_flag(mr, l, offsets, value);
|
||||
mesh_render_data_loop_edge_flag(mr, l, offsets, value);
|
||||
}
|
||||
if (eed) {
|
||||
/* Mapped points on an edge between two edit verts. */
|
||||
BMLoop *l = BM_face_edge_share_loop(efa, eed);
|
||||
mesh_render_data_loop_edge_flag(mr, l, data->offsets, *eldata);
|
||||
else {
|
||||
if (edge == nullptr) {
|
||||
/* Find if the loop's vert is not part of an edit edge.
|
||||
* For this, we check if the previous loop was on an edge. */
|
||||
const int corner_prev = bke::mesh::face_corner_prev(face, corner);
|
||||
edge = bm_original_edge_get(mr, corner_edges[corner_prev]);
|
||||
}
|
||||
if (edge) {
|
||||
/* Mapped points on an edge between two edit verts. */
|
||||
BMLoop *l = BM_face_edge_share_loop(face_orig, edge);
|
||||
mesh_render_data_loop_edge_flag(mr, l, offsets, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void extract_edituv_data(const MeshRenderData &mr, gpu::VertBuf &vbo)
|
||||
{
|
||||
GPU_vertbuf_init_with_format(&vbo, &edituv_data_format());
|
||||
GPU_vertbuf_data_alloc(&vbo, mr.corners_num);
|
||||
MutableSpan vbo_data(static_cast<EditLoopData *>(GPU_vertbuf_get_data(&vbo)), mr.corners_num);
|
||||
|
||||
if (mr.extract_type == MR_EXTRACT_BMESH) {
|
||||
extract_edituv_data_bm(mr, vbo_data);
|
||||
}
|
||||
else {
|
||||
extract_edituv_data_mesh(mr, vbo_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_edituv_data_init_subdiv(const DRWSubdivCache &subdiv_cache,
|
||||
const MeshRenderData &mr,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void *buf,
|
||||
void *tls_data)
|
||||
static void extract_edituv_data_iter_subdiv_bm(const MeshRenderData &mr,
|
||||
const BMUVOffsets offsets,
|
||||
const Span<int> subdiv_loop_vert_index,
|
||||
const Span<int> subdiv_loop_edge_index,
|
||||
const int subdiv_quad_index,
|
||||
const BMFace *coarse_quad,
|
||||
MutableSpan<EditLoopData> vbo_data)
|
||||
{
|
||||
gpu::VertBuf *vbo = static_cast<gpu::VertBuf *>(buf);
|
||||
MeshExtract_EditUVData_Data *data = static_cast<MeshExtract_EditUVData_Data *>(tls_data);
|
||||
extract_edituv_data_init_common(mr, vbo, data, subdiv_cache.num_subdiv_loops);
|
||||
}
|
||||
|
||||
static void extract_edituv_data_iter_subdiv_bm(const DRWSubdivCache &subdiv_cache,
|
||||
const MeshRenderData &mr,
|
||||
void *_data,
|
||||
uint subdiv_quad_index,
|
||||
const BMFace *coarse_quad)
|
||||
{
|
||||
MeshExtract_EditUVData_Data *data = static_cast<MeshExtract_EditUVData_Data *>(_data);
|
||||
int *subdiv_loop_vert_index = (int *)GPU_vertbuf_get_data(subdiv_cache.verts_orig_index);
|
||||
int *subdiv_loop_edge_index = (int *)GPU_vertbuf_get_data(subdiv_cache.edges_orig_index);
|
||||
|
||||
uint start_loop_idx = subdiv_quad_index * 4;
|
||||
uint end_loop_idx = (subdiv_quad_index + 1) * 4;
|
||||
@@ -135,15 +125,15 @@ static void extract_edituv_data_iter_subdiv_bm(const DRWSubdivCache &subdiv_cach
|
||||
const int vert_origindex = subdiv_loop_vert_index[i];
|
||||
int edge_origindex = subdiv_loop_edge_index[i];
|
||||
|
||||
EditLoopData *edit_loop_data = &data->vbo_data[i];
|
||||
EditLoopData *edit_loop_data = &vbo_data[i];
|
||||
memset(edit_loop_data, 0, sizeof(EditLoopData));
|
||||
|
||||
if (vert_origindex != -1 && edge_origindex != -1) {
|
||||
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->offsets, *edit_loop_data);
|
||||
mesh_render_data_loop_edge_flag(mr, l, data->offsets, *edit_loop_data);
|
||||
mesh_render_data_loop_flag(mr, l, offsets, *edit_loop_data);
|
||||
mesh_render_data_loop_edge_flag(mr, l, offsets, *edit_loop_data);
|
||||
}
|
||||
else {
|
||||
if (edge_origindex == -1) {
|
||||
@@ -156,42 +146,83 @@ static void extract_edituv_data_iter_subdiv_bm(const DRWSubdivCache &subdiv_cach
|
||||
/* Mapped points on an edge between two edit verts. */
|
||||
BMEdge *eed = BM_edge_at_index(mr.bm, edge_origindex);
|
||||
BMLoop *l = BM_face_edge_share_loop(const_cast<BMFace *>(coarse_quad), eed);
|
||||
mesh_render_data_loop_edge_flag(mr, l, data->offsets, *edit_loop_data);
|
||||
mesh_render_data_loop_edge_flag(mr, l, offsets, *edit_loop_data);
|
||||
}
|
||||
}
|
||||
|
||||
mesh_render_data_face_flag(mr, coarse_quad, data->offsets, *edit_loop_data);
|
||||
mesh_render_data_face_flag(mr, coarse_quad, offsets, *edit_loop_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_edituv_data_iter_subdiv_mesh(const DRWSubdivCache &subdiv_cache,
|
||||
const MeshRenderData &mr,
|
||||
void *_data,
|
||||
uint subdiv_quad_index,
|
||||
const int coarse_quad_index)
|
||||
static void extract_edituv_subdiv_data_bm(const MeshRenderData &mr,
|
||||
const DRWSubdivCache &subdiv_cache,
|
||||
MutableSpan<EditLoopData> vbo_data)
|
||||
{
|
||||
BMFace *coarse_quad_bm = bm_original_face_get(mr, coarse_quad_index);
|
||||
extract_edituv_data_iter_subdiv_bm(subdiv_cache, mr, _data, subdiv_quad_index, coarse_quad_bm);
|
||||
const int corners_num = subdiv_cache.num_subdiv_loops;
|
||||
const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index, corners_num);
|
||||
const Span<int> subdiv_loop_vert_index(
|
||||
static_cast<const int *>(GPU_vertbuf_get_data(subdiv_cache.verts_orig_index)), corners_num);
|
||||
/* NOTE: #subdiv_loop_edge_index already has the origindex layer baked in. */
|
||||
const Span<int> subdiv_loop_edge_index(
|
||||
static_cast<const int *>(GPU_vertbuf_get_data(subdiv_cache.edges_orig_index)), corners_num);
|
||||
|
||||
const BMUVOffsets offsets = BM_uv_map_get_offsets(mr.bm);
|
||||
threading::parallel_for(IndexRange(subdiv_cache.num_subdiv_quads), 2048, [&](IndexRange range) {
|
||||
for (const int subdiv_quad : range) {
|
||||
const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4];
|
||||
extract_edituv_data_iter_subdiv_bm(mr,
|
||||
offsets,
|
||||
subdiv_loop_vert_index,
|
||||
subdiv_loop_edge_index,
|
||||
subdiv_quad,
|
||||
BM_face_at_index(mr.bm, coarse_face),
|
||||
vbo_data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
constexpr MeshExtract create_extractor_edituv_data()
|
||||
static void extract_edituv_subdiv_data_mesh(const MeshRenderData &mr,
|
||||
const DRWSubdivCache &subdiv_cache,
|
||||
MutableSpan<EditLoopData> vbo_data)
|
||||
{
|
||||
MeshExtract extractor = {nullptr};
|
||||
extractor.init = extract_edituv_data_init;
|
||||
extractor.iter_face_bm = extract_edituv_data_iter_face_bm;
|
||||
extractor.iter_face_mesh = extract_edituv_data_iter_face_mesh;
|
||||
extractor.init_subdiv = extract_edituv_data_init_subdiv;
|
||||
extractor.iter_subdiv_bm = extract_edituv_data_iter_subdiv_bm;
|
||||
extractor.iter_subdiv_mesh = extract_edituv_data_iter_subdiv_mesh;
|
||||
extractor.data_type = MR_DATA_NONE;
|
||||
extractor.data_size = sizeof(MeshExtract_EditUVData_Data);
|
||||
extractor.use_threading = true;
|
||||
extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.edituv_data);
|
||||
return extractor;
|
||||
const int corners_num = subdiv_cache.num_subdiv_loops;
|
||||
const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index, corners_num);
|
||||
const Span<int> subdiv_loop_vert_index(
|
||||
static_cast<const int *>(GPU_vertbuf_get_data(subdiv_cache.verts_orig_index)), corners_num);
|
||||
/* NOTE: #subdiv_loop_edge_index already has the origindex layer baked in. */
|
||||
const Span<int> subdiv_loop_edge_index(
|
||||
static_cast<const int *>(GPU_vertbuf_get_data(subdiv_cache.edges_orig_index)), corners_num);
|
||||
|
||||
const BMUVOffsets offsets = BM_uv_map_get_offsets(mr.bm);
|
||||
threading::parallel_for(IndexRange(subdiv_cache.num_subdiv_quads), 2048, [&](IndexRange range) {
|
||||
for (const int subdiv_quad : range) {
|
||||
const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4];
|
||||
extract_edituv_data_iter_subdiv_bm(mr,
|
||||
offsets,
|
||||
subdiv_loop_vert_index,
|
||||
subdiv_loop_edge_index,
|
||||
subdiv_quad,
|
||||
bm_original_face_get(mr, coarse_face),
|
||||
vbo_data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** \} */
|
||||
void extract_edituv_data_subdiv(const MeshRenderData &mr,
|
||||
const DRWSubdivCache &subdiv_cache,
|
||||
gpu::VertBuf &vbo)
|
||||
{
|
||||
GPU_vertbuf_init_with_format(&vbo, &edituv_data_format());
|
||||
const int size = subdiv_cache.num_subdiv_loops;
|
||||
GPU_vertbuf_data_alloc(&vbo, size);
|
||||
MutableSpan vbo_data(static_cast<EditLoopData *>(GPU_vertbuf_get_data(&vbo)), size);
|
||||
|
||||
const MeshExtract extract_edituv_data = create_extractor_edituv_data();
|
||||
if (mr.extract_type == MR_EXTRACT_BMESH) {
|
||||
extract_edituv_subdiv_data_bm(mr, subdiv_cache, vbo_data);
|
||||
}
|
||||
else {
|
||||
extract_edituv_subdiv_data_mesh(mr, subdiv_cache, vbo_data);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::draw
|
||||
|
||||
Reference in New Issue
Block a user