Mesh: Improvements to position and normal draw extraction #116902
|
@ -63,6 +63,7 @@ set(SRC
|
|||
intern/mesh_extractors/extract_mesh_vbo_skin_roots.cc
|
||||
intern/mesh_extractors/extract_mesh_vbo_tan.cc
|
||||
intern/mesh_extractors/extract_mesh_vbo_uv.cc
|
||||
intern/mesh_extractors/extract_mesh_vbo_vnor.cc
|
||||
intern/mesh_extractors/extract_mesh_vbo_weights.cc
|
||||
intern/draw_attributes.cc
|
||||
intern/draw_cache_impl_curve.cc
|
||||
|
|
|
@ -74,8 +74,8 @@ struct MeshBufferList {
|
|||
* (except fdots and skin roots). For some VBOs, it extends to (in this exact order) :
|
||||
* loops + loose_edges * 2 + loose_verts */
|
||||
struct {
|
||||
GPUVertBuf *pos_nor; /* extend */
|
||||
GPUVertBuf *lnor; /* extend */
|
||||
GPUVertBuf *pos; /* extend */
|
||||
GPUVertBuf *nor; /* extend */
|
||||
GPUVertBuf *edge_fac; /* extend */
|
||||
GPUVertBuf *weights; /* extend */
|
||||
GPUVertBuf *uv;
|
||||
|
@ -101,6 +101,7 @@ struct MeshBufferList {
|
|||
GPUVertBuf *fdot_idx;
|
||||
GPUVertBuf *attr[GPU_MAX_ATTR];
|
||||
GPUVertBuf *attr_viewer;
|
||||
GPUVertBuf *vnor;
|
||||
} vbo;
|
||||
/* Index Buffers:
|
||||
* Only need to be updated when topology changes. */
|
||||
|
|
|
@ -627,8 +627,8 @@ void mesh_buffer_cache_create_requested(TaskGraph *task_graph,
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
EXTRACT_ADD_REQUESTED(vbo, pos_nor);
|
||||
EXTRACT_ADD_REQUESTED(vbo, lnor);
|
||||
EXTRACT_ADD_REQUESTED(vbo, pos);
|
||||
EXTRACT_ADD_REQUESTED(vbo, nor);
|
||||
EXTRACT_ADD_REQUESTED(vbo, uv);
|
||||
EXTRACT_ADD_REQUESTED(vbo, tan);
|
||||
EXTRACT_ADD_REQUESTED(vbo, sculpt_data);
|
||||
|
@ -653,6 +653,7 @@ void mesh_buffer_cache_create_requested(TaskGraph *task_graph,
|
|||
EXTRACT_ADD_REQUESTED(vbo, attr[i]);
|
||||
}
|
||||
EXTRACT_ADD_REQUESTED(vbo, attr_viewer);
|
||||
EXTRACT_ADD_REQUESTED(vbo, vnor);
|
||||
|
||||
EXTRACT_ADD_REQUESTED(ibo, tris);
|
||||
if (DRW_ibo_requested(mbuflist->ibo.lines_loose)) {
|
||||
|
@ -808,11 +809,11 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache,
|
|||
EXTRACT_ADD_REQUESTED(ibo, tris);
|
||||
|
||||
/* Orcos are extracted at the same time as positions. */
|
||||
if (DRW_vbo_requested(mbuflist->vbo.pos_nor) || DRW_vbo_requested(mbuflist->vbo.orco)) {
|
||||
extractors.append(&extract_pos_nor);
|
||||
if (DRW_vbo_requested(mbuflist->vbo.pos) || DRW_vbo_requested(mbuflist->vbo.orco)) {
|
||||
extractors.append(&extract_pos);
|
||||
}
|
||||
|
||||
EXTRACT_ADD_REQUESTED(vbo, lnor);
|
||||
EXTRACT_ADD_REQUESTED(vbo, nor);
|
||||
for (int i = 0; i < GPU_MAX_ATTR; i++) {
|
||||
EXTRACT_ADD_REQUESTED(vbo, attr[i]);
|
||||
}
|
||||
|
|
|
@ -678,13 +678,15 @@ MeshRenderData *mesh_render_data_create(Object *object,
|
|||
|
||||
mr->material_indices = *attributes.lookup<int>("material_index", bke::AttrDomain::Face);
|
||||
|
||||
mr->hide_vert = *attributes.lookup<bool>(".hide_vert", bke::AttrDomain::Point);
|
||||
mr->hide_edge = *attributes.lookup<bool>(".hide_edge", bke::AttrDomain::Edge);
|
||||
mr->hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
|
||||
if (is_mode_active || is_paint_mode) {
|
||||
mr->hide_vert = *attributes.lookup<bool>(".hide_vert", bke::AttrDomain::Point);
|
||||
mr->hide_edge = *attributes.lookup<bool>(".hide_edge", bke::AttrDomain::Edge);
|
||||
mr->hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
|
||||
|
||||
mr->select_vert = *attributes.lookup<bool>(".select_vert", bke::AttrDomain::Point);
|
||||
mr->select_edge = *attributes.lookup<bool>(".select_edge", bke::AttrDomain::Edge);
|
||||
mr->select_poly = *attributes.lookup<bool>(".select_poly", bke::AttrDomain::Face);
|
||||
mr->select_vert = *attributes.lookup<bool>(".select_vert", bke::AttrDomain::Point);
|
||||
mr->select_edge = *attributes.lookup<bool>(".select_edge", bke::AttrDomain::Edge);
|
||||
mr->select_poly = *attributes.lookup<bool>(".select_poly", bke::AttrDomain::Face);
|
||||
}
|
||||
|
||||
mr->sharp_faces = *attributes.lookup<bool>("sharp_face", bke::AttrDomain::Face);
|
||||
}
|
||||
|
|
|
@ -97,14 +97,14 @@ namespace blender::draw {
|
|||
static constexpr DRWBatchFlag batches_that_use_buffer(const int buffer_index)
|
||||
{
|
||||
switch (buffer_index) {
|
||||
case BUFFER_INDEX(vbo.pos_nor):
|
||||
case BUFFER_INDEX(vbo.pos):
|
||||
return MBC_SURFACE | MBC_SURFACE_WEIGHTS | MBC_EDIT_TRIANGLES | MBC_EDIT_VERTICES |
|
||||
MBC_EDIT_EDGES | MBC_EDIT_VNOR | MBC_EDIT_LNOR | MBC_EDIT_MESH_ANALYSIS |
|
||||
MBC_EDIT_SELECTION_VERTS | MBC_EDIT_SELECTION_EDGES | MBC_EDIT_SELECTION_FACES |
|
||||
MBC_ALL_VERTS | MBC_ALL_EDGES | MBC_LOOSE_EDGES | MBC_EDGE_DETECTION |
|
||||
MBC_WIRE_EDGES | MBC_WIRE_LOOPS | MBC_SCULPT_OVERLAYS | MBC_VIEWER_ATTRIBUTE_OVERLAY |
|
||||
MBC_SURFACE_PER_MAT;
|
||||
case BUFFER_INDEX(vbo.lnor):
|
||||
case BUFFER_INDEX(vbo.nor):
|
||||
return MBC_SURFACE | MBC_EDIT_LNOR | MBC_WIRE_LOOPS | MBC_SURFACE_PER_MAT;
|
||||
case BUFFER_INDEX(vbo.edge_fac):
|
||||
return MBC_WIRE_EDGES;
|
||||
|
@ -167,6 +167,8 @@ static constexpr DRWBatchFlag batches_that_use_buffer(const int buffer_index)
|
|||
return MBC_SURFACE | MBC_SURFACE_PER_MAT;
|
||||
case BUFFER_INDEX(vbo.attr_viewer):
|
||||
return MBC_VIEWER_ATTRIBUTE_OVERLAY;
|
||||
case BUFFER_INDEX(vbo.vnor):
|
||||
return MBC_EDIT_VNOR;
|
||||
case BUFFER_INDEX(ibo.tris):
|
||||
return MBC_SURFACE | MBC_SURFACE_WEIGHTS | MBC_EDIT_TRIANGLES | MBC_EDIT_LNOR |
|
||||
MBC_EDIT_MESH_ANALYSIS | MBC_EDIT_SELECTION_FACES | MBC_SCULPT_OVERLAYS |
|
||||
|
@ -748,10 +750,10 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *mesh, eMeshBatchDirtyMode mode)
|
|||
* Note that it can be slow if auto smooth is enabled. (see #63946) */
|
||||
FOREACH_MESH_BUFFER_CACHE (cache, mbc) {
|
||||
GPU_INDEXBUF_DISCARD_SAFE(mbc->buff.ibo.lines_paint_mask);
|
||||
GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.pos_nor);
|
||||
GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.lnor);
|
||||
GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.pos);
|
||||
GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.nor);
|
||||
}
|
||||
batch_map = BATCH_MAP(ibo.lines_paint_mask, vbo.pos_nor, vbo.lnor);
|
||||
batch_map = BATCH_MAP(ibo.lines_paint_mask, vbo.pos, vbo.nor);
|
||||
mesh_batch_cache_discard_batch(cache, batch_map);
|
||||
break;
|
||||
case BKE_MESH_BATCH_DIRTY_ALL:
|
||||
|
@ -1070,8 +1072,8 @@ GPUVertBuf *DRW_mesh_batch_cache_pos_vertbuf_get(Mesh *mesh)
|
|||
/* Request surface to trigger the vbo filling. Otherwise it may do nothing. */
|
||||
mesh_batch_cache_request_surface_batches(cache);
|
||||
|
||||
DRW_vbo_request(nullptr, &cache.final.buff.vbo.pos_nor);
|
||||
return cache.final.buff.vbo.pos_nor;
|
||||
DRW_vbo_request(nullptr, &cache.final.buff.vbo.pos);
|
||||
return cache.final.buff.vbo.pos;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -1525,8 +1527,8 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph *task_graph,
|
|||
/* Initialize batches and request VBO's & IBO's. */
|
||||
assert_deps_valid(MBC_SURFACE,
|
||||
{BUFFER_INDEX(ibo.tris),
|
||||
BUFFER_INDEX(vbo.lnor),
|
||||
BUFFER_INDEX(vbo.pos_nor),
|
||||
BUFFER_INDEX(vbo.nor),
|
||||
BUFFER_INDEX(vbo.pos),
|
||||
BUFFER_INDEX(vbo.uv),
|
||||
BUFFER_INDEX(vbo.attr[0]),
|
||||
BUFFER_INDEX(vbo.attr[1]),
|
||||
|
@ -1546,65 +1548,63 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph *task_graph,
|
|||
if (DRW_batch_requested(cache.batch.surface, GPU_PRIM_TRIS)) {
|
||||
DRW_ibo_request(cache.batch.surface, &mbuflist->ibo.tris);
|
||||
/* Order matters. First ones override latest VBO's attributes. */
|
||||
DRW_vbo_request(cache.batch.surface, &mbuflist->vbo.lnor);
|
||||
DRW_vbo_request(cache.batch.surface, &mbuflist->vbo.pos_nor);
|
||||
DRW_vbo_request(cache.batch.surface, &mbuflist->vbo.nor);
|
||||
DRW_vbo_request(cache.batch.surface, &mbuflist->vbo.pos);
|
||||
if (cache.cd_used.uv != 0) {
|
||||
DRW_vbo_request(cache.batch.surface, &mbuflist->vbo.uv);
|
||||
}
|
||||
drw_add_attributes_vbo(cache.batch.surface, mbuflist, &cache.attr_used);
|
||||
}
|
||||
assert_deps_valid(MBC_ALL_VERTS, {BUFFER_INDEX(vbo.pos_nor)});
|
||||
assert_deps_valid(MBC_ALL_VERTS, {BUFFER_INDEX(vbo.pos)});
|
||||
if (DRW_batch_requested(cache.batch.all_verts, GPU_PRIM_POINTS)) {
|
||||
DRW_vbo_request(cache.batch.all_verts, &mbuflist->vbo.pos_nor);
|
||||
DRW_vbo_request(cache.batch.all_verts, &mbuflist->vbo.pos);
|
||||
}
|
||||
assert_deps_valid(
|
||||
MBC_SCULPT_OVERLAYS,
|
||||
{BUFFER_INDEX(ibo.tris), BUFFER_INDEX(vbo.pos_nor), BUFFER_INDEX(vbo.sculpt_data)});
|
||||
{BUFFER_INDEX(ibo.tris), BUFFER_INDEX(vbo.pos), BUFFER_INDEX(vbo.sculpt_data)});
|
||||
if (DRW_batch_requested(cache.batch.sculpt_overlays, GPU_PRIM_TRIS)) {
|
||||
DRW_ibo_request(cache.batch.sculpt_overlays, &mbuflist->ibo.tris);
|
||||
DRW_vbo_request(cache.batch.sculpt_overlays, &mbuflist->vbo.pos_nor);
|
||||
DRW_vbo_request(cache.batch.sculpt_overlays, &mbuflist->vbo.pos);
|
||||
DRW_vbo_request(cache.batch.sculpt_overlays, &mbuflist->vbo.sculpt_data);
|
||||
}
|
||||
assert_deps_valid(MBC_ALL_EDGES, {BUFFER_INDEX(ibo.lines), BUFFER_INDEX(vbo.pos_nor)});
|
||||
assert_deps_valid(MBC_ALL_EDGES, {BUFFER_INDEX(ibo.lines), BUFFER_INDEX(vbo.pos)});
|
||||
if (DRW_batch_requested(cache.batch.all_edges, GPU_PRIM_LINES)) {
|
||||
DRW_ibo_request(cache.batch.all_edges, &mbuflist->ibo.lines);
|
||||
DRW_vbo_request(cache.batch.all_edges, &mbuflist->vbo.pos_nor);
|
||||
DRW_vbo_request(cache.batch.all_edges, &mbuflist->vbo.pos);
|
||||
}
|
||||
assert_deps_valid(MBC_LOOSE_EDGES, {BUFFER_INDEX(ibo.lines_loose), BUFFER_INDEX(vbo.pos_nor)});
|
||||
assert_deps_valid(MBC_LOOSE_EDGES, {BUFFER_INDEX(ibo.lines_loose), BUFFER_INDEX(vbo.pos)});
|
||||
if (DRW_batch_requested(cache.batch.loose_edges, GPU_PRIM_LINES)) {
|
||||
DRW_ibo_request(nullptr, &mbuflist->ibo.lines);
|
||||
DRW_ibo_request(cache.batch.loose_edges, &mbuflist->ibo.lines_loose);
|
||||
DRW_vbo_request(cache.batch.loose_edges, &mbuflist->vbo.pos_nor);
|
||||
DRW_vbo_request(cache.batch.loose_edges, &mbuflist->vbo.pos);
|
||||
}
|
||||
assert_deps_valid(MBC_EDGE_DETECTION,
|
||||
{BUFFER_INDEX(ibo.lines_adjacency), BUFFER_INDEX(vbo.pos_nor)});
|
||||
{BUFFER_INDEX(ibo.lines_adjacency), BUFFER_INDEX(vbo.pos)});
|
||||
if (DRW_batch_requested(cache.batch.edge_detection, GPU_PRIM_LINES_ADJ)) {
|
||||
DRW_ibo_request(cache.batch.edge_detection, &mbuflist->ibo.lines_adjacency);
|
||||
DRW_vbo_request(cache.batch.edge_detection, &mbuflist->vbo.pos_nor);
|
||||
DRW_vbo_request(cache.batch.edge_detection, &mbuflist->vbo.pos);
|
||||
}
|
||||
assert_deps_valid(
|
||||
MBC_SURFACE_WEIGHTS,
|
||||
{BUFFER_INDEX(ibo.tris), BUFFER_INDEX(vbo.pos_nor), BUFFER_INDEX(vbo.weights)});
|
||||
assert_deps_valid(MBC_SURFACE_WEIGHTS,
|
||||
{BUFFER_INDEX(ibo.tris), BUFFER_INDEX(vbo.pos), BUFFER_INDEX(vbo.weights)});
|
||||
if (DRW_batch_requested(cache.batch.surface_weights, GPU_PRIM_TRIS)) {
|
||||
DRW_ibo_request(cache.batch.surface_weights, &mbuflist->ibo.tris);
|
||||
DRW_vbo_request(cache.batch.surface_weights, &mbuflist->vbo.pos_nor);
|
||||
DRW_vbo_request(cache.batch.surface_weights, &mbuflist->vbo.pos);
|
||||
DRW_vbo_request(cache.batch.surface_weights, &mbuflist->vbo.weights);
|
||||
}
|
||||
assert_deps_valid(
|
||||
MBC_WIRE_LOOPS,
|
||||
{BUFFER_INDEX(ibo.lines_paint_mask), BUFFER_INDEX(vbo.lnor), BUFFER_INDEX(vbo.pos_nor)});
|
||||
{BUFFER_INDEX(ibo.lines_paint_mask), BUFFER_INDEX(vbo.nor), BUFFER_INDEX(vbo.pos)});
|
||||
if (DRW_batch_requested(cache.batch.wire_loops, GPU_PRIM_LINES)) {
|
||||
DRW_ibo_request(cache.batch.wire_loops, &mbuflist->ibo.lines_paint_mask);
|
||||
/* Order matters. First ones override latest VBO's attributes. */
|
||||
DRW_vbo_request(cache.batch.wire_loops, &mbuflist->vbo.lnor);
|
||||
DRW_vbo_request(cache.batch.wire_loops, &mbuflist->vbo.pos_nor);
|
||||
DRW_vbo_request(cache.batch.wire_loops, &mbuflist->vbo.nor);
|
||||
DRW_vbo_request(cache.batch.wire_loops, &mbuflist->vbo.pos);
|
||||
}
|
||||
assert_deps_valid(
|
||||
MBC_WIRE_EDGES,
|
||||
{BUFFER_INDEX(ibo.lines), BUFFER_INDEX(vbo.pos_nor), BUFFER_INDEX(vbo.edge_fac)});
|
||||
assert_deps_valid(MBC_WIRE_EDGES,
|
||||
{BUFFER_INDEX(ibo.lines), BUFFER_INDEX(vbo.pos), BUFFER_INDEX(vbo.edge_fac)});
|
||||
if (DRW_batch_requested(cache.batch.wire_edges, GPU_PRIM_LINES)) {
|
||||
DRW_ibo_request(cache.batch.wire_edges, &mbuflist->ibo.lines);
|
||||
DRW_vbo_request(cache.batch.wire_edges, &mbuflist->vbo.pos_nor);
|
||||
DRW_vbo_request(cache.batch.wire_edges, &mbuflist->vbo.pos);
|
||||
DRW_vbo_request(cache.batch.wire_edges, &mbuflist->vbo.edge_fac);
|
||||
}
|
||||
assert_deps_valid(MBC_WIRE_LOOPS_UVS, {BUFFER_INDEX(ibo.edituv_lines), BUFFER_INDEX(vbo.uv)});
|
||||
|
@ -1617,17 +1617,17 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph *task_graph,
|
|||
}
|
||||
assert_deps_valid(
|
||||
MBC_EDIT_MESH_ANALYSIS,
|
||||
{BUFFER_INDEX(ibo.tris), BUFFER_INDEX(vbo.pos_nor), BUFFER_INDEX(vbo.mesh_analysis)});
|
||||
{BUFFER_INDEX(ibo.tris), BUFFER_INDEX(vbo.pos), BUFFER_INDEX(vbo.mesh_analysis)});
|
||||
if (DRW_batch_requested(cache.batch.edit_mesh_analysis, GPU_PRIM_TRIS)) {
|
||||
DRW_ibo_request(cache.batch.edit_mesh_analysis, &mbuflist->ibo.tris);
|
||||
DRW_vbo_request(cache.batch.edit_mesh_analysis, &mbuflist->vbo.pos_nor);
|
||||
DRW_vbo_request(cache.batch.edit_mesh_analysis, &mbuflist->vbo.pos);
|
||||
DRW_vbo_request(cache.batch.edit_mesh_analysis, &mbuflist->vbo.mesh_analysis);
|
||||
}
|
||||
|
||||
/* Per Material */
|
||||
assert_deps_valid(
|
||||
MBC_SURFACE_PER_MAT,
|
||||
{BUFFER_INDEX(vbo.lnor), BUFFER_INDEX(vbo.pos_nor), BUFFER_INDEX(vbo.uv),
|
||||
{BUFFER_INDEX(vbo.nor), BUFFER_INDEX(vbo.pos), BUFFER_INDEX(vbo.uv),
|
||||
BUFFER_INDEX(vbo.tan), BUFFER_INDEX(vbo.orco), BUFFER_INDEX(vbo.attr[0]),
|
||||
BUFFER_INDEX(vbo.attr[1]), BUFFER_INDEX(vbo.attr[2]), BUFFER_INDEX(vbo.attr[3]),
|
||||
BUFFER_INDEX(vbo.attr[4]), BUFFER_INDEX(vbo.attr[5]), BUFFER_INDEX(vbo.attr[6]),
|
||||
|
@ -1639,8 +1639,8 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph *task_graph,
|
|||
if (DRW_batch_requested(cache.surface_per_mat[i], GPU_PRIM_TRIS)) {
|
||||
DRW_ibo_request(cache.surface_per_mat[i], &cache.tris_per_mat[i]);
|
||||
/* Order matters. First ones override latest VBO's attributes. */
|
||||
DRW_vbo_request(cache.surface_per_mat[i], &mbuflist->vbo.lnor);
|
||||
DRW_vbo_request(cache.surface_per_mat[i], &mbuflist->vbo.pos_nor);
|
||||
DRW_vbo_request(cache.surface_per_mat[i], &mbuflist->vbo.nor);
|
||||
DRW_vbo_request(cache.surface_per_mat[i], &mbuflist->vbo.pos);
|
||||
if (cache.cd_used.uv != 0) {
|
||||
DRW_vbo_request(cache.surface_per_mat[i], &mbuflist->vbo.uv);
|
||||
}
|
||||
|
@ -1657,41 +1657,44 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph *task_graph,
|
|||
mbuflist = (do_cage) ? &cache.cage.buff : &cache.final.buff;
|
||||
|
||||
/* Edit Mesh */
|
||||
assert_deps_valid(
|
||||
MBC_EDIT_TRIANGLES,
|
||||
{BUFFER_INDEX(ibo.tris), BUFFER_INDEX(vbo.pos_nor), BUFFER_INDEX(vbo.edit_data)});
|
||||
assert_deps_valid(MBC_EDIT_TRIANGLES,
|
||||
{BUFFER_INDEX(ibo.tris), BUFFER_INDEX(vbo.pos), BUFFER_INDEX(vbo.edit_data)});
|
||||
if (DRW_batch_requested(cache.batch.edit_triangles, GPU_PRIM_TRIS)) {
|
||||
DRW_ibo_request(cache.batch.edit_triangles, &mbuflist->ibo.tris);
|
||||
DRW_vbo_request(cache.batch.edit_triangles, &mbuflist->vbo.pos_nor);
|
||||
DRW_vbo_request(cache.batch.edit_triangles, &mbuflist->vbo.pos);
|
||||
DRW_vbo_request(cache.batch.edit_triangles, &mbuflist->vbo.edit_data);
|
||||
}
|
||||
assert_deps_valid(
|
||||
MBC_EDIT_VERTICES,
|
||||
{BUFFER_INDEX(ibo.points), BUFFER_INDEX(vbo.pos_nor), BUFFER_INDEX(vbo.edit_data)});
|
||||
{BUFFER_INDEX(ibo.points), BUFFER_INDEX(vbo.pos), BUFFER_INDEX(vbo.edit_data)});
|
||||
if (DRW_batch_requested(cache.batch.edit_vertices, GPU_PRIM_POINTS)) {
|
||||
DRW_ibo_request(cache.batch.edit_vertices, &mbuflist->ibo.points);
|
||||
DRW_vbo_request(cache.batch.edit_vertices, &mbuflist->vbo.pos_nor);
|
||||
DRW_vbo_request(cache.batch.edit_vertices, &mbuflist->vbo.pos);
|
||||
DRW_vbo_request(cache.batch.edit_vertices, &mbuflist->vbo.edit_data);
|
||||
}
|
||||
assert_deps_valid(
|
||||
MBC_EDIT_EDGES,
|
||||
{BUFFER_INDEX(ibo.lines), BUFFER_INDEX(vbo.pos_nor), BUFFER_INDEX(vbo.edit_data)});
|
||||
assert_deps_valid(MBC_EDIT_EDGES,
|
||||
{BUFFER_INDEX(ibo.lines), BUFFER_INDEX(vbo.pos), BUFFER_INDEX(vbo.edit_data)});
|
||||
if (DRW_batch_requested(cache.batch.edit_edges, GPU_PRIM_LINES)) {
|
||||
DRW_ibo_request(cache.batch.edit_edges, &mbuflist->ibo.lines);
|
||||
DRW_vbo_request(cache.batch.edit_edges, &mbuflist->vbo.pos_nor);
|
||||
DRW_vbo_request(cache.batch.edit_edges, &mbuflist->vbo.pos);
|
||||
DRW_vbo_request(cache.batch.edit_edges, &mbuflist->vbo.edit_data);
|
||||
}
|
||||
assert_deps_valid(MBC_EDIT_VNOR, {BUFFER_INDEX(ibo.points), BUFFER_INDEX(vbo.pos_nor)});
|
||||
assert_deps_valid(MBC_EDIT_VNOR,
|
||||
{BUFFER_INDEX(ibo.points), BUFFER_INDEX(vbo.pos), BUFFER_INDEX(vbo.vnor)});
|
||||
if (DRW_batch_requested(cache.batch.edit_vnor, GPU_PRIM_POINTS)) {
|
||||
DRW_ibo_request(cache.batch.edit_vnor, &mbuflist->ibo.points);
|
||||
DRW_vbo_request(cache.batch.edit_vnor, &mbuflist->vbo.pos_nor);
|
||||
DRW_vbo_request(cache.batch.edit_vnor, &mbuflist->vbo.pos);
|
||||
if (!do_subdivision) {
|
||||
/* For GPU subdivision, vertex normals are included in the `pos` VBO. */
|
||||
DRW_vbo_request(cache.batch.edit_vnor, &mbuflist->vbo.vnor);
|
||||
}
|
||||
}
|
||||
assert_deps_valid(MBC_EDIT_LNOR,
|
||||
{BUFFER_INDEX(ibo.tris), BUFFER_INDEX(vbo.pos_nor), BUFFER_INDEX(vbo.lnor)});
|
||||
{BUFFER_INDEX(ibo.tris), BUFFER_INDEX(vbo.pos), BUFFER_INDEX(vbo.nor)});
|
||||
if (DRW_batch_requested(cache.batch.edit_lnor, GPU_PRIM_POINTS)) {
|
||||
DRW_ibo_request(cache.batch.edit_lnor, &mbuflist->ibo.tris);
|
||||
DRW_vbo_request(cache.batch.edit_lnor, &mbuflist->vbo.pos_nor);
|
||||
DRW_vbo_request(cache.batch.edit_lnor, &mbuflist->vbo.lnor);
|
||||
DRW_vbo_request(cache.batch.edit_lnor, &mbuflist->vbo.pos);
|
||||
DRW_vbo_request(cache.batch.edit_lnor, &mbuflist->vbo.nor);
|
||||
}
|
||||
assert_deps_valid(
|
||||
MBC_EDIT_FACEDOTS,
|
||||
|
@ -1707,28 +1710,25 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph *task_graph,
|
|||
}
|
||||
|
||||
/* Selection */
|
||||
assert_deps_valid(
|
||||
MBC_EDIT_SELECTION_VERTS,
|
||||
{BUFFER_INDEX(ibo.points), BUFFER_INDEX(vbo.pos_nor), BUFFER_INDEX(vbo.vert_idx)});
|
||||
assert_deps_valid(MBC_EDIT_SELECTION_VERTS,
|
||||
{BUFFER_INDEX(ibo.points), BUFFER_INDEX(vbo.pos), BUFFER_INDEX(vbo.vert_idx)});
|
||||
if (DRW_batch_requested(cache.batch.edit_selection_verts, GPU_PRIM_POINTS)) {
|
||||
DRW_ibo_request(cache.batch.edit_selection_verts, &mbuflist->ibo.points);
|
||||
DRW_vbo_request(cache.batch.edit_selection_verts, &mbuflist->vbo.pos_nor);
|
||||
DRW_vbo_request(cache.batch.edit_selection_verts, &mbuflist->vbo.pos);
|
||||
DRW_vbo_request(cache.batch.edit_selection_verts, &mbuflist->vbo.vert_idx);
|
||||
}
|
||||
assert_deps_valid(
|
||||
MBC_EDIT_SELECTION_EDGES,
|
||||
{BUFFER_INDEX(ibo.lines), BUFFER_INDEX(vbo.pos_nor), BUFFER_INDEX(vbo.edge_idx)});
|
||||
assert_deps_valid(MBC_EDIT_SELECTION_EDGES,
|
||||
{BUFFER_INDEX(ibo.lines), BUFFER_INDEX(vbo.pos), BUFFER_INDEX(vbo.edge_idx)});
|
||||
if (DRW_batch_requested(cache.batch.edit_selection_edges, GPU_PRIM_LINES)) {
|
||||
DRW_ibo_request(cache.batch.edit_selection_edges, &mbuflist->ibo.lines);
|
||||
DRW_vbo_request(cache.batch.edit_selection_edges, &mbuflist->vbo.pos_nor);
|
||||
DRW_vbo_request(cache.batch.edit_selection_edges, &mbuflist->vbo.pos);
|
||||
DRW_vbo_request(cache.batch.edit_selection_edges, &mbuflist->vbo.edge_idx);
|
||||
}
|
||||
assert_deps_valid(
|
||||
MBC_EDIT_SELECTION_FACES,
|
||||
{BUFFER_INDEX(ibo.tris), BUFFER_INDEX(vbo.pos_nor), BUFFER_INDEX(vbo.face_idx)});
|
||||
assert_deps_valid(MBC_EDIT_SELECTION_FACES,
|
||||
{BUFFER_INDEX(ibo.tris), BUFFER_INDEX(vbo.pos), BUFFER_INDEX(vbo.face_idx)});
|
||||
if (DRW_batch_requested(cache.batch.edit_selection_faces, GPU_PRIM_TRIS)) {
|
||||
DRW_ibo_request(cache.batch.edit_selection_faces, &mbuflist->ibo.tris);
|
||||
DRW_vbo_request(cache.batch.edit_selection_faces, &mbuflist->vbo.pos_nor);
|
||||
DRW_vbo_request(cache.batch.edit_selection_faces, &mbuflist->vbo.pos);
|
||||
DRW_vbo_request(cache.batch.edit_selection_faces, &mbuflist->vbo.face_idx);
|
||||
}
|
||||
assert_deps_valid(
|
||||
|
@ -1805,10 +1805,10 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph *task_graph,
|
|||
}
|
||||
assert_deps_valid(
|
||||
MBC_VIEWER_ATTRIBUTE_OVERLAY,
|
||||
{BUFFER_INDEX(ibo.tris), BUFFER_INDEX(vbo.pos_nor), BUFFER_INDEX(vbo.attr_viewer)});
|
||||
{BUFFER_INDEX(ibo.tris), BUFFER_INDEX(vbo.pos), BUFFER_INDEX(vbo.attr_viewer)});
|
||||
if (DRW_batch_requested(cache.batch.surface_viewer_attribute, GPU_PRIM_TRIS)) {
|
||||
DRW_ibo_request(cache.batch.surface_viewer_attribute, &mbuflist->ibo.tris);
|
||||
DRW_vbo_request(cache.batch.surface_viewer_attribute, &mbuflist->vbo.pos_nor);
|
||||
DRW_vbo_request(cache.batch.surface_viewer_attribute, &mbuflist->vbo.pos);
|
||||
DRW_vbo_request(cache.batch.surface_viewer_attribute, &mbuflist->vbo.attr_viewer);
|
||||
}
|
||||
|
||||
|
@ -1817,8 +1817,8 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph *task_graph,
|
|||
BLI_assert(batches_that_use_buffer(buffer_index) ==
|
||||
batches_that_use_buffer_local.lookup(buffer_index));
|
||||
};
|
||||
assert_final_deps_valid(BUFFER_INDEX(vbo.lnor));
|
||||
assert_final_deps_valid(BUFFER_INDEX(vbo.pos_nor));
|
||||
assert_final_deps_valid(BUFFER_INDEX(vbo.nor));
|
||||
assert_final_deps_valid(BUFFER_INDEX(vbo.pos));
|
||||
assert_final_deps_valid(BUFFER_INDEX(vbo.uv));
|
||||
assert_final_deps_valid(BUFFER_INDEX(vbo.sculpt_data));
|
||||
assert_final_deps_valid(BUFFER_INDEX(vbo.weights));
|
||||
|
@ -1843,6 +1843,7 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph *task_graph,
|
|||
assert_final_deps_valid(BUFFER_INDEX(vbo.attr[i]));
|
||||
}
|
||||
assert_final_deps_valid(BUFFER_INDEX(vbo.attr_viewer));
|
||||
assert_final_deps_valid(BUFFER_INDEX(vbo.vnor));
|
||||
|
||||
assert_final_deps_valid(BUFFER_INDEX(ibo.tris));
|
||||
assert_final_deps_valid(BUFFER_INDEX(ibo.lines));
|
||||
|
|
|
@ -52,11 +52,8 @@ eMRIterType mesh_extract_iter_type(const MeshExtract *ext)
|
|||
|
||||
static const MeshExtract *mesh_extract_override_hq_normals(const MeshExtract *extractor)
|
||||
{
|
||||
if (extractor == &extract_pos_nor) {
|
||||
return &extract_pos_nor_hq;
|
||||
}
|
||||
if (extractor == &extract_lnor) {
|
||||
return &extract_lnor_hq;
|
||||
if (extractor == &extract_nor) {
|
||||
return &extract_nor_hq;
|
||||
}
|
||||
if (extractor == &extract_tan) {
|
||||
return &extract_tan_hq;
|
||||
|
|
|
@ -329,6 +329,9 @@ void mesh_render_data_loop_edge_flag(const MeshRenderData &mr,
|
|||
BMUVOffsets offsets,
|
||||
EditLoopData *eattr);
|
||||
|
||||
template<typename GPUType>
|
||||
void extract_vert_normals(const MeshRenderData &mr, MutableSpan<GPUType> normals);
|
||||
|
||||
extern const MeshExtract extract_tris;
|
||||
extern const MeshExtract extract_tris_single_mat;
|
||||
extern const MeshExtract extract_lines;
|
||||
|
@ -342,10 +345,9 @@ 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_pos_nor;
|
||||
extern const MeshExtract extract_pos_nor_hq;
|
||||
extern const MeshExtract extract_lnor_hq;
|
||||
extern const MeshExtract extract_lnor;
|
||||
extern const MeshExtract extract_pos;
|
||||
extern const MeshExtract extract_nor_hq;
|
||||
extern const MeshExtract extract_nor;
|
||||
extern const MeshExtract extract_uv;
|
||||
extern const MeshExtract extract_tan;
|
||||
extern const MeshExtract extract_tan_hq;
|
||||
|
@ -371,5 +373,6 @@ extern const MeshExtract extract_vert_idx;
|
|||
extern const MeshExtract extract_fdot_idx;
|
||||
extern const MeshExtract extract_attr[GPU_MAX_ATTR];
|
||||
extern const MeshExtract extract_attr_viewer;
|
||||
extern const MeshExtract extract_vnor;
|
||||
|
||||
} // namespace blender::draw
|
||||
|
|
|
@ -291,7 +291,7 @@ static void extract_edge_fac_init_subdiv(const DRWSubdivCache &subdiv_cache,
|
|||
GPU_vertbuf_init_build_on_device(
|
||||
vbo, get_subdiv_edge_fac_format(), subdiv_cache.num_subdiv_loops + loose_geom.loop_len);
|
||||
|
||||
GPUVertBuf *pos_nor = cache.final.buff.vbo.pos_nor;
|
||||
GPUVertBuf *pos_nor = cache.final.buff.vbo.pos;
|
||||
GPUVertBuf *poly_other_map = build_poly_other_map_vbo(subdiv_cache);
|
||||
|
||||
draw_subdiv_build_edge_fac_buffer(
|
||||
|
|
|
@ -233,7 +233,7 @@ static void extract_edituv_stretch_angle_init_subdiv(const DRWSubdivCache &subdi
|
|||
GPU_vertbuf_init_build_on_device(
|
||||
refined_vbo, get_edituv_stretch_angle_format_subdiv(), subdiv_cache.num_subdiv_loops);
|
||||
|
||||
GPUVertBuf *pos_nor = cache.final.buff.vbo.pos_nor;
|
||||
GPUVertBuf *pos_nor = cache.final.buff.vbo.pos;
|
||||
GPUVertBuf *uvs = cache.final.buff.vbo.uv;
|
||||
|
||||
/* It may happen that the data for the UV editor is requested before (as a separate draw update)
|
||||
|
@ -282,7 +282,7 @@ static void extract_edituv_stretch_angle_init_subdiv(const DRWSubdivCache &subdi
|
|||
draw_subdiv_build_edituv_stretch_angle_buffer(
|
||||
subdiv_cache, pos_nor, uvs, uvs_offset, refined_vbo);
|
||||
|
||||
if (!cache.final.buff.vbo.pos_nor) {
|
||||
if (!cache.final.buff.vbo.pos) {
|
||||
GPU_vertbuf_discard(pos_nor);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
* \ingroup draw
|
||||
*/
|
||||
|
||||
#include "BLI_array_utils.hh"
|
||||
|
||||
#include "extract_mesh.hh"
|
||||
|
||||
#include "draw_subdivision.hh"
|
||||
|
@ -16,6 +18,139 @@ namespace blender::draw {
|
|||
/** \name Extract Loop Normal
|
||||
* \{ */
|
||||
|
||||
template<typename GPUType> inline GPUType convert_normal(const float3 &src);
|
||||
|
||||
template<> inline GPUPackedNormal convert_normal(const float3 &src)
|
||||
{
|
||||
return GPU_normal_convert_i10_v3(src);
|
||||
}
|
||||
|
||||
template<> inline short4 convert_normal(const float3 &src)
|
||||
{
|
||||
short4 dst;
|
||||
normal_float_to_short_v3(dst, src);
|
||||
return dst;
|
||||
}
|
||||
|
||||
template<typename GPUType>
|
||||
static void extract_normals(const Span<float3> src, MutableSpan<GPUType> dst)
|
||||
{
|
||||
threading::parallel_for(src.index_range(), 2048, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
dst[i] = convert_normal<GPUType>(src[i]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
template<typename GPUType>
|
||||
static void extract_vert_normals_impl(const MeshRenderData &mr, MutableSpan<GPUType> normals)
|
||||
{
|
||||
Array<GPUType> vert_normals_converted(mr.vert_normals.size());
|
||||
extract_normals(mr.vert_normals, vert_normals_converted.as_mutable_span());
|
||||
array_utils::gather(vert_normals_converted.as_span(), mr.corner_verts, normals);
|
||||
}
|
||||
|
||||
template<>
|
||||
void extract_vert_normals(const MeshRenderData &mr, MutableSpan<GPUPackedNormal> normals)
|
||||
{
|
||||
extract_vert_normals_impl(mr, normals);
|
||||
}
|
||||
template<> void extract_vert_normals(const MeshRenderData &mr, MutableSpan<short4> normals)
|
||||
{
|
||||
extract_vert_normals_impl(mr, normals);
|
||||
}
|
||||
|
||||
template<typename GPUType>
|
||||
static void extract_face_normals(const MeshRenderData &mr, MutableSpan<GPUType> normals)
|
||||
{
|
||||
const OffsetIndices faces = mr.faces;
|
||||
const Span<float3> face_normals = mr.face_normals;
|
||||
threading::parallel_for(faces.index_range(), 4096, [&](const IndexRange range) {
|
||||
for (const int face : range) {
|
||||
normals.slice(faces[face]).fill(convert_normal<GPUType>(face_normals[face]));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
template<typename GPUType>
|
||||
static void extract_normals_mesh(const MeshRenderData &mr, MutableSpan<GPUType> normals)
|
||||
{
|
||||
if (mr.normals_domain == bke::MeshNormalDomain::Face) {
|
||||
extract_face_normals(mr, normals);
|
||||
}
|
||||
else if (mr.normals_domain == bke::MeshNormalDomain::Point) {
|
||||
extract_vert_normals(mr, normals);
|
||||
}
|
||||
else if (!mr.corner_normals.is_empty()) {
|
||||
extract_normals(mr.corner_normals, normals);
|
||||
}
|
||||
else if (mr.sharp_faces.is_empty()) {
|
||||
extract_vert_normals(mr, normals);
|
||||
}
|
||||
else {
|
||||
const OffsetIndices faces = mr.faces;
|
||||
const Span<int> corner_verts = mr.corner_verts;
|
||||
const Span<bool> sharp_faces = mr.sharp_faces;
|
||||
const Span<float3> vert_normals = mr.vert_normals;
|
||||
const Span<float3> face_normals = mr.face_normals;
|
||||
threading::parallel_for(faces.index_range(), 2048, [&](const IndexRange range) {
|
||||
for (const int face : range) {
|
||||
if (sharp_faces[face]) {
|
||||
normals.slice(faces[face]).fill(convert_normal<GPUType>(face_normals[face]));
|
||||
}
|
||||
else {
|
||||
for (const int corner : faces[face]) {
|
||||
normals[corner] = convert_normal<GPUType>(vert_normals[corner_verts[corner]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
template<typename GPUType>
|
||||
static void extract_paint_overlay_flags(const MeshRenderData &mr, MutableSpan<GPUType> normals)
|
||||
{
|
||||
if (mr.select_poly.is_empty() && mr.hide_poly.is_empty() && (!mr.edit_bmesh || !mr.v_origindex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
const OffsetIndices faces = mr.faces;
|
||||
threading::parallel_for(faces.index_range(), 1024, [&](const IndexRange range) {
|
||||
if (!mr.select_poly.is_empty()) {
|
||||
const Span<bool> select_poly = mr.select_poly;
|
||||
for (const int face : range) {
|
||||
if (select_poly[face]) {
|
||||
for (const int corner : faces[face]) {
|
||||
normals[corner].w = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!mr.hide_poly.is_empty()) {
|
||||
const Span<bool> hide_poly = mr.hide_poly;
|
||||
for (const int face : range) {
|
||||
if (hide_poly[face]) {
|
||||
for (const int corner : faces[face]) {
|
||||
normals[corner].w = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mr.edit_bmesh && mr.v_origindex) {
|
||||
const Span<int> corner_verts = mr.corner_verts;
|
||||
const Span<int> orig_indices(mr.v_origindex, mr.vert_len);
|
||||
for (const int face : range) {
|
||||
for (const int corner : faces[face]) {
|
||||
if (orig_indices[corner_verts[corner]] == ORIGINDEX_NONE) {
|
||||
normals[corner].w = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void extract_lnor_init(const MeshRenderData &mr,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void *buf,
|
||||
|
@ -30,76 +165,51 @@ static void extract_lnor_init(const MeshRenderData &mr,
|
|||
GPU_vertbuf_init_with_format(vbo, &format);
|
||||
GPU_vertbuf_data_alloc(vbo, mr.loop_len);
|
||||
|
||||
*(GPUPackedNormal **)tls_data = static_cast<GPUPackedNormal *>(GPU_vertbuf_get_data(vbo));
|
||||
if (mr.extract_type == MR_EXTRACT_MESH) {
|
||||
MutableSpan vbo_data(static_cast<GPUPackedNormal *>(GPU_vertbuf_get_data(vbo)), mr.loop_len);
|
||||
extract_normals_mesh(mr, vbo_data);
|
||||
extract_paint_overlay_flags(mr, vbo_data);
|
||||
}
|
||||
else {
|
||||
*static_cast<GPUPackedNormal **>(tls_data) = static_cast<GPUPackedNormal *>(
|
||||
GPU_vertbuf_get_data(vbo));
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_lnor_iter_face_bm(const MeshRenderData &mr,
|
||||
const BMFace *f,
|
||||
const int /*f_index*/,
|
||||
void *data)
|
||||
void *data_v)
|
||||
{
|
||||
GPUPackedNormal *data = *(GPUPackedNormal **)data_v;
|
||||
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);
|
||||
GPUPackedNormal *lnor_data = &(*(GPUPackedNormal **)data)[l_index];
|
||||
if (!mr.corner_normals.is_empty()) {
|
||||
*lnor_data = GPU_normal_convert_i10_v3(mr.corner_normals[l_index]);
|
||||
data[l_index] = GPU_normal_convert_i10_v3(mr.corner_normals[l_index]);
|
||||
}
|
||||
else {
|
||||
if (mr.normals_domain == bke::MeshNormalDomain::Face ||
|
||||
!BM_elem_flag_test(f, BM_ELEM_SMOOTH))
|
||||
{
|
||||
*lnor_data = GPU_normal_convert_i10_v3(bm_face_no_get(mr, f));
|
||||
data[l_index] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, f));
|
||||
}
|
||||
else {
|
||||
*lnor_data = GPU_normal_convert_i10_v3(bm_vert_no_get(mr, l_iter->v));
|
||||
data[l_index] = GPU_normal_convert_i10_v3(bm_vert_no_get(mr, l_iter->v));
|
||||
}
|
||||
}
|
||||
lnor_data->w = BM_elem_flag_test(f, BM_ELEM_HIDDEN) ? -1 : 0;
|
||||
data[l_index].w = BM_elem_flag_test(f, BM_ELEM_HIDDEN) ? -1 : 0;
|
||||
} while ((l_iter = l_iter->next) != l_first);
|
||||
}
|
||||
|
||||
static void extract_lnor_iter_face_mesh(const MeshRenderData &mr, const int face_index, void *data)
|
||||
{
|
||||
const bool hidden = !mr.hide_poly.is_empty() && mr.hide_poly[face_index];
|
||||
|
||||
for (const int corner : mr.faces[face_index]) {
|
||||
const int vert = mr.corner_verts[corner];
|
||||
GPUPackedNormal *lnor_data = &(*(GPUPackedNormal **)data)[corner];
|
||||
if (!mr.corner_normals.is_empty()) {
|
||||
*lnor_data = GPU_normal_convert_i10_v3(mr.corner_normals[corner]);
|
||||
}
|
||||
else if (mr.normals_domain == bke::MeshNormalDomain::Face ||
|
||||
(!mr.sharp_faces.is_empty() && mr.sharp_faces[face_index]))
|
||||
{
|
||||
*lnor_data = GPU_normal_convert_i10_v3(mr.face_normals[face_index]);
|
||||
}
|
||||
else {
|
||||
*lnor_data = GPU_normal_convert_i10_v3(mr.vert_normals[vert]);
|
||||
}
|
||||
|
||||
/* Flag for paint mode overlay.
|
||||
* Only use origindex in edit mode where it is used to display the edge-normals.
|
||||
* In paint mode it will use the un-mapped data to draw the wire-frame. */
|
||||
if (hidden || (mr.edit_bmesh && (mr.v_origindex) && mr.v_origindex[vert] == ORIGINDEX_NONE)) {
|
||||
lnor_data->w = -1;
|
||||
}
|
||||
else if (!mr.select_poly.is_empty() && mr.select_poly[face_index]) {
|
||||
lnor_data->w = 1;
|
||||
}
|
||||
else {
|
||||
lnor_data->w = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static GPUVertFormat *get_subdiv_lnor_format()
|
||||
{
|
||||
static GPUVertFormat format = {0};
|
||||
if (format.attr_len == 0) {
|
||||
GPU_vertformat_attr_add(&format, "nor", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
|
||||
GPU_vertformat_alias_add(&format, "lnor");
|
||||
GPU_vertformat_alias_add(&format, "vnor");
|
||||
}
|
||||
return &format;
|
||||
}
|
||||
|
@ -111,7 +221,7 @@ static void extract_lnor_init_subdiv(const DRWSubdivCache &subdiv_cache,
|
|||
void * /*data*/)
|
||||
{
|
||||
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer);
|
||||
GPUVertBuf *pos_nor = cache.final.buff.vbo.pos_nor;
|
||||
GPUVertBuf *pos_nor = cache.final.buff.vbo.pos;
|
||||
BLI_assert(pos_nor);
|
||||
GPU_vertbuf_init_build_on_device(vbo, get_subdiv_lnor_format(), subdiv_cache.num_subdiv_loops);
|
||||
draw_subdiv_build_lnor_buffer(subdiv_cache, pos_nor, vbo);
|
||||
|
@ -123,11 +233,10 @@ constexpr MeshExtract create_extractor_lnor()
|
|||
extractor.init = extract_lnor_init;
|
||||
extractor.init_subdiv = extract_lnor_init_subdiv;
|
||||
extractor.iter_face_bm = extract_lnor_iter_face_bm;
|
||||
extractor.iter_face_mesh = extract_lnor_iter_face_mesh;
|
||||
extractor.data_type = MR_DATA_LOOP_NOR;
|
||||
extractor.data_size = sizeof(GPUPackedNormal *);
|
||||
extractor.use_threading = true;
|
||||
extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.lnor);
|
||||
extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.nor);
|
||||
return extractor;
|
||||
}
|
||||
|
||||
|
@ -137,10 +246,6 @@ constexpr MeshExtract create_extractor_lnor()
|
|||
/** \name Extract HQ Loop Normal
|
||||
* \{ */
|
||||
|
||||
struct gpuHQNor {
|
||||
short x, y, z, w;
|
||||
};
|
||||
|
||||
static void extract_lnor_hq_init(const MeshRenderData &mr,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void *buf,
|
||||
|
@ -155,7 +260,14 @@ static void extract_lnor_hq_init(const MeshRenderData &mr,
|
|||
GPU_vertbuf_init_with_format(vbo, &format);
|
||||
GPU_vertbuf_data_alloc(vbo, mr.loop_len);
|
||||
|
||||
*(gpuHQNor **)tls_data = static_cast<gpuHQNor *>(GPU_vertbuf_get_data(vbo));
|
||||
if (mr.extract_type == MR_EXTRACT_MESH) {
|
||||
MutableSpan vbo_data(static_cast<short4 *>(GPU_vertbuf_get_data(vbo)), mr.loop_len);
|
||||
extract_normals_mesh(mr, vbo_data);
|
||||
extract_paint_overlay_flags(mr, vbo_data);
|
||||
}
|
||||
else {
|
||||
*(short4 **)tls_data = static_cast<short4 *>(GPU_vertbuf_get_data(vbo));
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_lnor_hq_iter_face_bm(const MeshRenderData &mr,
|
||||
|
@ -168,72 +280,35 @@ static void extract_lnor_hq_iter_face_bm(const MeshRenderData &mr,
|
|||
do {
|
||||
const int l_index = BM_elem_index_get(l_iter);
|
||||
if (!mr.corner_normals.is_empty()) {
|
||||
normal_float_to_short_v3(&(*(gpuHQNor **)data)[l_index].x, mr.corner_normals[l_index]);
|
||||
normal_float_to_short_v3(&(*(short4 **)data)[l_index].x, mr.corner_normals[l_index]);
|
||||
}
|
||||
else {
|
||||
if (BM_elem_flag_test(f, BM_ELEM_SMOOTH)) {
|
||||
normal_float_to_short_v3(&(*(gpuHQNor **)data)[l_index].x, bm_vert_no_get(mr, l_iter->v));
|
||||
normal_float_to_short_v3(&(*(short4 **)data)[l_index].x, bm_vert_no_get(mr, l_iter->v));
|
||||
}
|
||||
else {
|
||||
normal_float_to_short_v3(&(*(gpuHQNor **)data)[l_index].x, bm_face_no_get(mr, f));
|
||||
normal_float_to_short_v3(&(*(short4 **)data)[l_index].x, bm_face_no_get(mr, f));
|
||||
}
|
||||
}
|
||||
} while ((l_iter = l_iter->next) != l_first);
|
||||
}
|
||||
|
||||
static void extract_lnor_hq_iter_face_mesh(const MeshRenderData &mr,
|
||||
const int face_index,
|
||||
void *data)
|
||||
{
|
||||
const bool hidden = !mr.hide_poly.is_empty() && mr.hide_poly[face_index];
|
||||
|
||||
for (const int corner : mr.faces[face_index]) {
|
||||
const int vert = mr.corner_verts[corner];
|
||||
gpuHQNor *lnor_data = &(*(gpuHQNor **)data)[corner];
|
||||
if (!mr.corner_normals.is_empty()) {
|
||||
normal_float_to_short_v3(&lnor_data->x, mr.corner_normals[corner]);
|
||||
}
|
||||
else if (mr.normals_domain == bke::MeshNormalDomain::Face ||
|
||||
(!mr.sharp_faces.is_empty() && mr.sharp_faces[face_index]))
|
||||
{
|
||||
normal_float_to_short_v3(&lnor_data->x, mr.face_normals[face_index]);
|
||||
}
|
||||
else {
|
||||
normal_float_to_short_v3(&lnor_data->x, mr.vert_normals[vert]);
|
||||
}
|
||||
|
||||
/* Flag for paint mode overlay.
|
||||
* Only use origindex in edit mode where it is used to display the edge-normals.
|
||||
* In paint mode it will use the un-mapped data to draw the wire-frame. */
|
||||
if (hidden || (mr.edit_bmesh && (mr.v_origindex) && mr.v_origindex[vert] == ORIGINDEX_NONE)) {
|
||||
lnor_data->w = -1;
|
||||
}
|
||||
else if (!mr.select_poly.is_empty() && mr.select_poly[face_index]) {
|
||||
lnor_data->w = 1;
|
||||
}
|
||||
else {
|
||||
lnor_data->w = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constexpr MeshExtract create_extractor_lnor_hq()
|
||||
{
|
||||
MeshExtract extractor = {nullptr};
|
||||
extractor.init = extract_lnor_hq_init;
|
||||
extractor.init_subdiv = extract_lnor_init_subdiv;
|
||||
extractor.iter_face_bm = extract_lnor_hq_iter_face_bm;
|
||||
extractor.iter_face_mesh = extract_lnor_hq_iter_face_mesh;
|
||||
extractor.data_type = MR_DATA_LOOP_NOR;
|
||||
extractor.data_size = sizeof(gpuHQNor *);
|
||||
extractor.data_size = sizeof(short4 *);
|
||||
extractor.use_threading = true;
|
||||
extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.lnor);
|
||||
extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.nor);
|
||||
return extractor;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
const MeshExtract extract_lnor = create_extractor_lnor();
|
||||
const MeshExtract extract_lnor_hq = create_extractor_lnor_hq();
|
||||
const MeshExtract extract_nor = create_extractor_lnor();
|
||||
const MeshExtract extract_nor_hq = create_extractor_lnor_hq();
|
||||
|
||||
} // namespace blender::draw
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* \ingroup draw
|
||||
*/
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
#include "BLI_array_utils.hh"
|
||||
|
||||
#include "extract_mesh.hh"
|
||||
|
||||
|
@ -18,162 +18,84 @@ namespace blender::draw {
|
|||
/** \name Extract Position and Vertex Normal
|
||||
* \{ */
|
||||
|
||||
struct PosNorLoop {
|
||||
float pos[3];
|
||||
GPUPackedNormal nor;
|
||||
};
|
||||
static void extract_mesh_loose_edge_positions(const Span<float3> vert_positions,
|
||||
const Span<int2> edges,
|
||||
const Span<int> loose_edge_indices,
|
||||
MutableSpan<float3> positions)
|
||||
{
|
||||
threading::parallel_for(loose_edge_indices.index_range(), 4096, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
const int2 edge = edges[loose_edge_indices[i]];
|
||||
positions[i * 2 + 0] = vert_positions[edge[0]];
|
||||
positions[i * 2 + 1] = vert_positions[edge[1]];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
struct MeshExtract_PosNor_Data {
|
||||
PosNorLoop *vbo_data;
|
||||
GPUNormal *normals;
|
||||
};
|
||||
|
||||
static void extract_pos_nor_init(const MeshRenderData &mr,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void *buf,
|
||||
void *tls_data)
|
||||
static void extract_pos_init(const MeshRenderData &mr,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void *buf,
|
||||
void *tls_data)
|
||||
{
|
||||
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
|
||||
static GPUVertFormat format = {0};
|
||||
if (format.attr_len == 0) {
|
||||
/* WARNING Adjust #PosNorLoop struct accordingly. */
|
||||
GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
|
||||
GPU_vertformat_alias_add(&format, "vnor");
|
||||
}
|
||||
|
||||
GPU_vertbuf_init_with_format(vbo, &format);
|
||||
GPU_vertbuf_data_alloc(vbo, mr.loop_len + mr.loop_loose_len);
|
||||
|
||||
/* Pack normals per vert, reduce amount of computation. */
|
||||
MeshExtract_PosNor_Data *data = static_cast<MeshExtract_PosNor_Data *>(tls_data);
|
||||
data->vbo_data = static_cast<PosNorLoop *>(GPU_vertbuf_get_data(vbo));
|
||||
data->normals = (GPUNormal *)MEM_mallocN(sizeof(GPUNormal) * mr.vert_len, __func__);
|
||||
|
||||
/* Quicker than doing it for each loop. */
|
||||
if (mr.extract_type == MR_EXTRACT_BMESH) {
|
||||
BMIter iter;
|
||||
BMVert *eve;
|
||||
int v;
|
||||
BM_ITER_MESH_INDEX (eve, &iter, mr.bm, BM_VERTS_OF_MESH, v) {
|
||||
data->normals[v].low = GPU_normal_convert_i10_v3(bm_vert_no_get(mr, eve));
|
||||
}
|
||||
MutableSpan vbo_data(static_cast<float3 *>(GPU_vertbuf_get_data(vbo)),
|
||||
GPU_vertbuf_get_vertex_len(vbo));
|
||||
if (mr.extract_type == MR_EXTRACT_MESH) {
|
||||
array_utils::gather(
|
||||
mr.vert_positions, mr.corner_verts, vbo_data.take_front(mr.corner_verts.size()));
|
||||
extract_mesh_loose_edge_positions(mr.vert_positions,
|
||||
mr.edges,
|
||||
mr.loose_edges,
|
||||
vbo_data.slice(mr.loop_len, mr.loose_edges.size() * 2));
|
||||
array_utils::gather(
|
||||
mr.vert_positions, mr.loose_verts, vbo_data.take_back(mr.loose_verts.size()));
|
||||
}
|
||||
else {
|
||||
for (int v = 0; v < mr.vert_len; v++) {
|
||||
data->normals[v].low = GPU_normal_convert_i10_v3(mr.vert_normals[v]);
|
||||
}
|
||||
*static_cast<float3 **>(tls_data) = vbo_data.data();
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_pos_nor_iter_face_bm(const MeshRenderData &mr,
|
||||
const BMFace *f,
|
||||
const int /*f_index*/,
|
||||
void *_data)
|
||||
static void extract_pos_iter_face_bm(const MeshRenderData &mr,
|
||||
const BMFace *f,
|
||||
const int /*f_index*/,
|
||||
void *_data)
|
||||
{
|
||||
MeshExtract_PosNor_Data *data = static_cast<MeshExtract_PosNor_Data *>(_data);
|
||||
float3 *data = *static_cast<float3 **>(_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);
|
||||
PosNorLoop *vert = &data->vbo_data[l_index];
|
||||
copy_v3_v3(vert->pos, bm_vert_co_get(mr, l_iter->v));
|
||||
vert->nor = data->normals[BM_elem_index_get(l_iter->v)].low;
|
||||
vert->nor.w = BM_elem_flag_test(f, BM_ELEM_HIDDEN) ? -1 : 0;
|
||||
data[l_index] = bm_vert_co_get(mr, l_iter->v);
|
||||
} while ((l_iter = l_iter->next) != l_first);
|
||||
}
|
||||
|
||||
static void extract_pos_nor_iter_face_mesh(const MeshRenderData &mr,
|
||||
const int face_index,
|
||||
static void extract_pos_iter_loose_edge_bm(const MeshRenderData &mr,
|
||||
const BMEdge *eed,
|
||||
const int loose_edge_i,
|
||||
void *_data)
|
||||
{
|
||||
MeshExtract_PosNor_Data *data = static_cast<MeshExtract_PosNor_Data *>(_data);
|
||||
const bool poly_hidden = !mr.hide_poly.is_empty() && mr.hide_poly[face_index];
|
||||
|
||||
for (const int corner : mr.faces[face_index]) {
|
||||
const int vert_i = mr.corner_verts[corner];
|
||||
PosNorLoop *vert = &data->vbo_data[corner];
|
||||
const bool vert_hidden = !mr.hide_vert.is_empty() && mr.hide_vert[vert_i];
|
||||
copy_v3_v3(vert->pos, mr.vert_positions[vert_i]);
|
||||
vert->nor = data->normals[vert_i].low;
|
||||
/* Flag for paint mode overlay. */
|
||||
if (poly_hidden || vert_hidden ||
|
||||
((mr.v_origindex) && (mr.v_origindex[vert_i] == ORIGINDEX_NONE)))
|
||||
{
|
||||
vert->nor.w = -1;
|
||||
}
|
||||
else if (!mr.select_vert.is_empty() && mr.select_vert[vert_i]) {
|
||||
vert->nor.w = 1;
|
||||
}
|
||||
else {
|
||||
vert->nor.w = 0;
|
||||
}
|
||||
}
|
||||
float3 *data = *static_cast<float3 **>(_data);
|
||||
int index = mr.loop_len + loose_edge_i * 2;
|
||||
data[index + 0] = bm_vert_co_get(mr, eed->v1);
|
||||
data[index + 1] = bm_vert_co_get(mr, eed->v2);
|
||||
}
|
||||
|
||||
static void extract_pos_nor_iter_loose_edge_bm(const MeshRenderData &mr,
|
||||
const BMEdge *eed,
|
||||
const int loose_edge_i,
|
||||
void *_data)
|
||||
static void extract_pos_iter_loose_vert_bm(const MeshRenderData &mr,
|
||||
const BMVert *eve,
|
||||
const int loose_vert_i,
|
||||
void *_data)
|
||||
{
|
||||
MeshExtract_PosNor_Data *data = static_cast<MeshExtract_PosNor_Data *>(_data);
|
||||
|
||||
int l_index = mr.loop_len + loose_edge_i * 2;
|
||||
PosNorLoop *vert = &data->vbo_data[l_index];
|
||||
copy_v3_v3(vert[0].pos, bm_vert_co_get(mr, eed->v1));
|
||||
copy_v3_v3(vert[1].pos, bm_vert_co_get(mr, eed->v2));
|
||||
vert[0].nor = data->normals[BM_elem_index_get(eed->v1)].low;
|
||||
vert[1].nor = data->normals[BM_elem_index_get(eed->v2)].low;
|
||||
}
|
||||
|
||||
static void extract_pos_nor_iter_loose_edge_mesh(const MeshRenderData &mr,
|
||||
const int2 edge,
|
||||
const int loose_edge_i,
|
||||
void *_data)
|
||||
{
|
||||
MeshExtract_PosNor_Data *data = static_cast<MeshExtract_PosNor_Data *>(_data);
|
||||
const int index = mr.loop_len + loose_edge_i * 2;
|
||||
PosNorLoop *vert = &data->vbo_data[index];
|
||||
copy_v3_v3(vert[0].pos, mr.vert_positions[edge[0]]);
|
||||
copy_v3_v3(vert[1].pos, mr.vert_positions[edge[1]]);
|
||||
vert[0].nor = data->normals[edge[0]].low;
|
||||
vert[1].nor = data->normals[edge[1]].low;
|
||||
}
|
||||
|
||||
static void extract_pos_nor_iter_loose_vert_bm(const MeshRenderData &mr,
|
||||
const BMVert *eve,
|
||||
const int loose_vert_i,
|
||||
void *_data)
|
||||
{
|
||||
MeshExtract_PosNor_Data *data = static_cast<MeshExtract_PosNor_Data *>(_data);
|
||||
float3 *data = *static_cast<float3 **>(_data);
|
||||
const int offset = mr.loop_len + (mr.edge_loose_len * 2);
|
||||
|
||||
const int l_index = offset + loose_vert_i;
|
||||
PosNorLoop *vert = &data->vbo_data[l_index];
|
||||
copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve));
|
||||
vert->nor = data->normals[BM_elem_index_get(eve)].low;
|
||||
}
|
||||
|
||||
static void extract_pos_nor_iter_loose_vert_mesh(const MeshRenderData &mr,
|
||||
const int loose_vert_i,
|
||||
void *_data)
|
||||
{
|
||||
MeshExtract_PosNor_Data *data = static_cast<MeshExtract_PosNor_Data *>(_data);
|
||||
const int offset = mr.loop_len + (mr.edge_loose_len * 2);
|
||||
|
||||
const int index = offset + loose_vert_i;
|
||||
const int v_index = mr.loose_verts[loose_vert_i];
|
||||
PosNorLoop *vert = &data->vbo_data[index];
|
||||
copy_v3_v3(vert->pos, mr.vert_positions[v_index]);
|
||||
vert->nor = data->normals[v_index].low;
|
||||
}
|
||||
|
||||
static void extract_pos_nor_finish(const MeshRenderData & /*mr*/,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void * /*buf*/,
|
||||
void *_data)
|
||||
{
|
||||
MeshExtract_PosNor_Data *data = static_cast<MeshExtract_PosNor_Data *>(_data);
|
||||
MEM_freeN(data->normals);
|
||||
data[index] = bm_vert_co_get(mr, eve);
|
||||
}
|
||||
|
||||
static GPUVertFormat *get_normals_format()
|
||||
|
@ -214,11 +136,11 @@ static void extract_vertex_flags(const MeshRenderData &mr, char *flags)
|
|||
}
|
||||
}
|
||||
|
||||
static void extract_pos_nor_init_subdiv(const DRWSubdivCache &subdiv_cache,
|
||||
const MeshRenderData &mr,
|
||||
MeshBatchCache &cache,
|
||||
void *buffer,
|
||||
void * /*data*/)
|
||||
static void extract_pos_init_subdiv(const DRWSubdivCache &subdiv_cache,
|
||||
const MeshRenderData &mr,
|
||||
MeshBatchCache &cache,
|
||||
void *buffer,
|
||||
void * /*data*/)
|
||||
{
|
||||
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer);
|
||||
const DRWSubdivLooseGeom &loose_geom = subdiv_cache.loose_geom;
|
||||
|
@ -307,10 +229,10 @@ static void extract_pos_nor_init_subdiv(const DRWSubdivCache &subdiv_cache,
|
|||
GPU_vertbuf_discard(flags_buffer);
|
||||
}
|
||||
|
||||
static void extract_pos_nor_loose_geom_subdiv(const DRWSubdivCache &subdiv_cache,
|
||||
const MeshRenderData & /*mr*/,
|
||||
void *buffer,
|
||||
void * /*data*/)
|
||||
static void extract_pos_loose_geom_subdiv(const DRWSubdivCache &subdiv_cache,
|
||||
const MeshRenderData & /*mr*/,
|
||||
void *buffer,
|
||||
void * /*data*/)
|
||||
{
|
||||
const DRWSubdivLooseGeom &loose_geom = subdiv_cache.loose_geom;
|
||||
if (loose_geom.loop_len == 0) {
|
||||
|
@ -361,220 +283,24 @@ static void extract_pos_nor_loose_geom_subdiv(const DRWSubdivCache &subdiv_cache
|
|||
}
|
||||
}
|
||||
|
||||
constexpr MeshExtract create_extractor_pos_nor()
|
||||
constexpr MeshExtract create_extractor_pos()
|
||||
{
|
||||
MeshExtract extractor = {nullptr};
|
||||
extractor.init = extract_pos_nor_init;
|
||||
extractor.iter_face_bm = extract_pos_nor_iter_face_bm;
|
||||
extractor.iter_face_mesh = extract_pos_nor_iter_face_mesh;
|
||||
extractor.iter_loose_edge_bm = extract_pos_nor_iter_loose_edge_bm;
|
||||
extractor.iter_loose_edge_mesh = extract_pos_nor_iter_loose_edge_mesh;
|
||||
extractor.iter_loose_vert_bm = extract_pos_nor_iter_loose_vert_bm;
|
||||
extractor.iter_loose_vert_mesh = extract_pos_nor_iter_loose_vert_mesh;
|
||||
extractor.finish = extract_pos_nor_finish;
|
||||
extractor.init_subdiv = extract_pos_nor_init_subdiv;
|
||||
extractor.iter_loose_geom_subdiv = extract_pos_nor_loose_geom_subdiv;
|
||||
extractor.init = extract_pos_init;
|
||||
extractor.iter_face_bm = extract_pos_iter_face_bm;
|
||||
extractor.iter_loose_edge_bm = extract_pos_iter_loose_edge_bm;
|
||||
extractor.iter_loose_vert_bm = extract_pos_iter_loose_vert_bm;
|
||||
extractor.init_subdiv = extract_pos_init_subdiv;
|
||||
extractor.iter_loose_geom_subdiv = extract_pos_loose_geom_subdiv;
|
||||
extractor.data_type = MR_DATA_NONE;
|
||||
extractor.data_size = sizeof(MeshExtract_PosNor_Data);
|
||||
extractor.data_size = sizeof(float3 *);
|
||||
extractor.use_threading = true;
|
||||
extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.pos_nor);
|
||||
extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.pos);
|
||||
return extractor;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/** \name Extract Position and High Quality Vertex Normal
|
||||
* \{ */
|
||||
|
||||
struct PosNorHQLoop {
|
||||
float pos[3];
|
||||
short nor[4];
|
||||
};
|
||||
|
||||
struct MeshExtract_PosNorHQ_Data {
|
||||
PosNorHQLoop *vbo_data;
|
||||
GPUNormal *normals;
|
||||
};
|
||||
|
||||
static void extract_pos_nor_hq_init(const MeshRenderData &mr,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void *buf,
|
||||
void *tls_data)
|
||||
{
|
||||
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
|
||||
static GPUVertFormat format = {0};
|
||||
if (format.attr_len == 0) {
|
||||
/* WARNING Adjust #PosNorHQLoop struct accordingly. */
|
||||
GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
|
||||
GPU_vertformat_alias_add(&format, "vnor");
|
||||
}
|
||||
GPU_vertbuf_init_with_format(vbo, &format);
|
||||
GPU_vertbuf_data_alloc(vbo, mr.loop_len + mr.loop_loose_len);
|
||||
|
||||
/* Pack normals per vert, reduce amount of computation. */
|
||||
MeshExtract_PosNorHQ_Data *data = static_cast<MeshExtract_PosNorHQ_Data *>(tls_data);
|
||||
data->vbo_data = static_cast<PosNorHQLoop *>(GPU_vertbuf_get_data(vbo));
|
||||
data->normals = (GPUNormal *)MEM_mallocN(sizeof(GPUNormal) * mr.vert_len, __func__);
|
||||
|
||||
/* Quicker than doing it for each loop. */
|
||||
if (mr.extract_type == MR_EXTRACT_BMESH) {
|
||||
BMIter iter;
|
||||
BMVert *eve;
|
||||
int v;
|
||||
BM_ITER_MESH_INDEX (eve, &iter, mr.bm, BM_VERTS_OF_MESH, v) {
|
||||
normal_float_to_short_v3(data->normals[v].high, bm_vert_no_get(mr, eve));
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int v = 0; v < mr.vert_len; v++) {
|
||||
normal_float_to_short_v3(data->normals[v].high, mr.vert_normals[v]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_pos_nor_hq_iter_face_bm(const MeshRenderData &mr,
|
||||
const BMFace *f,
|
||||
const int /*f_index*/,
|
||||
void *_data)
|
||||
{
|
||||
MeshExtract_PosNorHQ_Data *data = static_cast<MeshExtract_PosNorHQ_Data *>(_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);
|
||||
PosNorHQLoop *vert = &data->vbo_data[l_index];
|
||||
copy_v3_v3(vert->pos, bm_vert_co_get(mr, l_iter->v));
|
||||
copy_v3_v3_short(vert->nor, data->normals[BM_elem_index_get(l_iter->v)].high);
|
||||
|
||||
vert->nor[3] = BM_elem_flag_test(f, BM_ELEM_HIDDEN) ? -1 : 0;
|
||||
} while ((l_iter = l_iter->next) != l_first);
|
||||
}
|
||||
|
||||
static void extract_pos_nor_hq_iter_face_mesh(const MeshRenderData &mr,
|
||||
const int face_index,
|
||||
void *_data)
|
||||
{
|
||||
MeshExtract_PosNorHQ_Data *data = static_cast<MeshExtract_PosNorHQ_Data *>(_data);
|
||||
const bool poly_hidden = !mr.hide_poly.is_empty() && mr.hide_poly[face_index];
|
||||
|
||||
for (const int corner : mr.faces[face_index]) {
|
||||
const int vert_i = mr.corner_verts[corner];
|
||||
|
||||
const bool vert_hidden = !mr.hide_vert.is_empty() && mr.hide_vert[vert_i];
|
||||
PosNorHQLoop *vert = &data->vbo_data[corner];
|
||||
copy_v3_v3(vert->pos, mr.vert_positions[vert_i]);
|
||||
copy_v3_v3_short(vert->nor, data->normals[vert_i].high);
|
||||
|
||||
/* Flag for paint mode overlay. */
|
||||
if (poly_hidden || vert_hidden ||
|
||||
((mr.v_origindex) && (mr.v_origindex[vert_i] == ORIGINDEX_NONE)))
|
||||
{
|
||||
vert->nor[3] = -1;
|
||||
}
|
||||
else if (!mr.select_vert.is_empty() && mr.select_vert[vert_i]) {
|
||||
vert->nor[3] = 1;
|
||||
}
|
||||
else {
|
||||
vert->nor[3] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_pos_nor_hq_iter_loose_edge_bm(const MeshRenderData &mr,
|
||||
const BMEdge *eed,
|
||||
const int loose_edge_i,
|
||||
void *_data)
|
||||
{
|
||||
MeshExtract_PosNorHQ_Data *data = static_cast<MeshExtract_PosNorHQ_Data *>(_data);
|
||||
int l_index = mr.loop_len + loose_edge_i * 2;
|
||||
PosNorHQLoop *vert = &data->vbo_data[l_index];
|
||||
copy_v3_v3(vert[0].pos, bm_vert_co_get(mr, eed->v1));
|
||||
copy_v3_v3(vert[1].pos, bm_vert_co_get(mr, eed->v2));
|
||||
copy_v3_v3_short(vert[0].nor, data->normals[BM_elem_index_get(eed->v1)].high);
|
||||
vert[0].nor[3] = 0;
|
||||
copy_v3_v3_short(vert[1].nor, data->normals[BM_elem_index_get(eed->v2)].high);
|
||||
vert[1].nor[3] = 0;
|
||||
}
|
||||
|
||||
static void extract_pos_nor_hq_iter_loose_edge_mesh(const MeshRenderData &mr,
|
||||
const int2 edge,
|
||||
const int loose_edge_i,
|
||||
void *_data)
|
||||
{
|
||||
MeshExtract_PosNorHQ_Data *data = static_cast<MeshExtract_PosNorHQ_Data *>(_data);
|
||||
const int index = mr.loop_len + loose_edge_i * 2;
|
||||
PosNorHQLoop *vert = &data->vbo_data[index];
|
||||
copy_v3_v3(vert[0].pos, mr.vert_positions[edge[0]]);
|
||||
copy_v3_v3(vert[1].pos, mr.vert_positions[edge[1]]);
|
||||
copy_v3_v3_short(vert[0].nor, data->normals[edge[0]].high);
|
||||
vert[0].nor[3] = 0;
|
||||
copy_v3_v3_short(vert[1].nor, data->normals[edge[1]].high);
|
||||
vert[1].nor[3] = 0;
|
||||
}
|
||||
|
||||
static void extract_pos_nor_hq_iter_loose_vert_bm(const MeshRenderData &mr,
|
||||
const BMVert *eve,
|
||||
const int loose_vert_i,
|
||||
void *_data)
|
||||
{
|
||||
MeshExtract_PosNorHQ_Data *data = static_cast<MeshExtract_PosNorHQ_Data *>(_data);
|
||||
const int offset = mr.loop_len + (mr.edge_loose_len * 2);
|
||||
|
||||
const int l_index = offset + loose_vert_i;
|
||||
PosNorHQLoop *vert = &data->vbo_data[l_index];
|
||||
copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve));
|
||||
copy_v3_v3_short(vert->nor, data->normals[BM_elem_index_get(eve)].high);
|
||||
vert->nor[3] = 0;
|
||||
}
|
||||
|
||||
static void extract_pos_nor_hq_iter_loose_vert_mesh(const MeshRenderData &mr,
|
||||
const int loose_vert_i,
|
||||
void *_data)
|
||||
{
|
||||
MeshExtract_PosNorHQ_Data *data = static_cast<MeshExtract_PosNorHQ_Data *>(_data);
|
||||
const int offset = mr.loop_len + (mr.edge_loose_len * 2);
|
||||
|
||||
const int index = offset + loose_vert_i;
|
||||
const int v_index = mr.loose_verts[loose_vert_i];
|
||||
PosNorHQLoop *vert = &data->vbo_data[index];
|
||||
copy_v3_v3(vert->pos, mr.vert_positions[v_index]);
|
||||
copy_v3_v3_short(vert->nor, data->normals[v_index].high);
|
||||
vert->nor[3] = 0;
|
||||
}
|
||||
|
||||
static void extract_pos_nor_hq_finish(const MeshRenderData & /*mr*/,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void * /*buf*/,
|
||||
void *_data)
|
||||
{
|
||||
MeshExtract_PosNorHQ_Data *data = static_cast<MeshExtract_PosNorHQ_Data *>(_data);
|
||||
MEM_freeN(data->normals);
|
||||
}
|
||||
|
||||
constexpr MeshExtract create_extractor_pos_nor_hq()
|
||||
{
|
||||
MeshExtract extractor = {nullptr};
|
||||
extractor.init = extract_pos_nor_hq_init;
|
||||
extractor.init_subdiv = extract_pos_nor_init_subdiv;
|
||||
extractor.iter_face_bm = extract_pos_nor_hq_iter_face_bm;
|
||||
extractor.iter_face_mesh = extract_pos_nor_hq_iter_face_mesh;
|
||||
extractor.iter_loose_edge_bm = extract_pos_nor_hq_iter_loose_edge_bm;
|
||||
extractor.iter_loose_edge_mesh = extract_pos_nor_hq_iter_loose_edge_mesh;
|
||||
extractor.iter_loose_vert_bm = extract_pos_nor_hq_iter_loose_vert_bm;
|
||||
extractor.iter_loose_vert_mesh = extract_pos_nor_hq_iter_loose_vert_mesh;
|
||||
extractor.finish = extract_pos_nor_hq_finish;
|
||||
extractor.data_type = MR_DATA_NONE;
|
||||
extractor.data_size = sizeof(MeshExtract_PosNorHQ_Data);
|
||||
extractor.use_threading = true;
|
||||
extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.pos_nor);
|
||||
return extractor;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
const MeshExtract extract_pos_nor = create_extractor_pos_nor();
|
||||
const MeshExtract extract_pos_nor_hq = create_extractor_pos_nor_hq();
|
||||
const MeshExtract extract_pos = create_extractor_pos();
|
||||
|
||||
} // namespace blender::draw
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/* SPDX-FileCopyrightText: 2021 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup draw
|
||||
*/
|
||||
|
||||
#include "extract_mesh.hh"
|
||||
|
||||
#include "draw_subdivision.hh"
|
||||
|
||||
namespace blender::draw {
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/** \name Extract Vertex Normal
|
||||
* \{ */
|
||||
|
||||
static void extract_vnor_init(const MeshRenderData &mr,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void *buf,
|
||||
void *tls_data)
|
||||
{
|
||||
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
|
||||
static GPUVertFormat format = {0};
|
||||
if (format.attr_len == 0) {
|
||||
GPU_vertformat_attr_add(&format, "vnor", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
|
||||
}
|
||||
GPU_vertbuf_init_with_format(vbo, &format);
|
||||
GPU_vertbuf_data_alloc(vbo, mr.loop_len);
|
||||
|
||||
if (mr.extract_type == MR_EXTRACT_MESH) {
|
||||
MutableSpan vbo_data(static_cast<GPUPackedNormal *>(GPU_vertbuf_get_data(vbo)), mr.loop_len);
|
||||
extract_vert_normals(mr, vbo_data);
|
||||
}
|
||||
else {
|
||||
*static_cast<GPUPackedNormal **>(tls_data) = static_cast<GPUPackedNormal *>(
|
||||
GPU_vertbuf_get_data(vbo));
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_vnor_iter_face_bm(const MeshRenderData &mr,
|
||||
const BMFace *face,
|
||||
const int /*f_index*/,
|
||||
void *data_v)
|
||||
{
|
||||
GPUPackedNormal *data = *static_cast<GPUPackedNormal **>(data_v);
|
||||
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);
|
||||
data[index] = GPU_normal_convert_i10_v3(bm_vert_no_get(mr, loop->v));
|
||||
loop = loop->next;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr MeshExtract create_extractor_vnor()
|
||||
{
|
||||
MeshExtract extractor = {nullptr};
|
||||
extractor.init = extract_vnor_init;
|
||||
extractor.iter_face_bm = extract_vnor_iter_face_bm;
|
||||
extractor.data_type = MR_DATA_LOOP_NOR;
|
||||
extractor.data_size = sizeof(GPUPackedNormal *);
|
||||
extractor.use_threading = true;
|
||||
extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.vnor);
|
||||
return extractor;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
const MeshExtract extract_vnor = create_extractor_vnor();
|
||||
|
||||
} // namespace blender::draw
|
Loading…
Reference in New Issue
vnor
should be kept as alias to vertex normal for edit mode. I don't know where this resides after this patch.Here, removing
GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
makes the aliasvnor
and alias ofpos
If
nor
is present in multiple VBO, the latest VBO in aGPUBatch
takes predecence.I guess this is no longer wanted after this patch, where only one of the normal (vnor/lnor) would be bound to a
GPUBatch
.