Mesh: Draw: Replace extractor abstraction for facedot normals buffer
Part of #116901. Also allows removing the "extractor overrides" code and deduplicating the handling of high quality normals with templates.
This commit is contained in:
@@ -531,7 +531,7 @@ static void mesh_extract_render_data_node_exec(void *__restrict task_data)
|
||||
MeshBufferList &buffers = update_task_data->cache->buff;
|
||||
|
||||
const bool request_face_normals = DRW_vbo_requested(buffers.vbo.nor) ||
|
||||
DRW_vbo_requested(buffers.vbo.tan) ||
|
||||
DRW_vbo_requested(buffers.vbo.fdots_nor) ||
|
||||
(data_flag & (MR_DATA_POLY_NOR | MR_DATA_LOOP_NOR)) != 0;
|
||||
const bool request_corner_normals = DRW_vbo_requested(buffers.vbo.nor) ||
|
||||
(data_flag & MR_DATA_LOOP_NOR) != 0;
|
||||
@@ -636,8 +636,7 @@ void mesh_buffer_cache_create_requested(TaskGraph &task_graph,
|
||||
#define EXTRACT_ADD_REQUESTED(type, name) \
|
||||
do { \
|
||||
if (DRW_##type##_requested(buffers.type.name)) { \
|
||||
const MeshExtract *extractor = mesh_extract_override_get(&extract_##name, do_hq_normals); \
|
||||
extractors.append(extractor); \
|
||||
extractors.append(&extract_##name); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
@@ -651,7 +650,6 @@ void mesh_buffer_cache_create_requested(TaskGraph &task_graph,
|
||||
EXTRACT_ADD_REQUESTED(vbo, edituv_stretch_angle);
|
||||
EXTRACT_ADD_REQUESTED(vbo, mesh_analysis);
|
||||
EXTRACT_ADD_REQUESTED(vbo, fdots_pos);
|
||||
EXTRACT_ADD_REQUESTED(vbo, fdots_nor);
|
||||
EXTRACT_ADD_REQUESTED(vbo, fdots_uv);
|
||||
EXTRACT_ADD_REQUESTED(vbo, fdots_edituv_data);
|
||||
EXTRACT_ADD_REQUESTED(vbo, face_idx);
|
||||
@@ -678,7 +676,8 @@ void mesh_buffer_cache_create_requested(TaskGraph &task_graph,
|
||||
!DRW_ibo_requested(buffers.ibo.lines_loose) && !DRW_ibo_requested(buffers.ibo.tris) &&
|
||||
!DRW_ibo_requested(buffers.ibo.points) && !DRW_vbo_requested(buffers.vbo.pos) &&
|
||||
!DRW_vbo_requested(buffers.vbo.nor) && !DRW_vbo_requested(buffers.vbo.vnor) &&
|
||||
!DRW_vbo_requested(buffers.vbo.tan) && !DRW_vbo_requested(buffers.vbo.edit_data))
|
||||
!DRW_vbo_requested(buffers.vbo.fdots_nor) && !DRW_vbo_requested(buffers.vbo.tan) &&
|
||||
!DRW_vbo_requested(buffers.vbo.edit_data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -760,6 +759,22 @@ 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.fdots_nor)) {
|
||||
struct TaskData {
|
||||
MeshRenderData &mr;
|
||||
MeshBufferCache &mbc;
|
||||
bool do_hq_normals;
|
||||
};
|
||||
TaskNode *task_node = BLI_task_graph_node_create(
|
||||
&task_graph,
|
||||
[](void *__restrict task_data) {
|
||||
const TaskData &data = *static_cast<TaskData *>(task_data);
|
||||
extract_face_dot_normals(data.mr, data.do_hq_normals, *data.mbc.buff.vbo.fdots_nor);
|
||||
},
|
||||
new TaskData{*mr, mbc, do_hq_normals},
|
||||
[](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.tris)) {
|
||||
struct TaskData {
|
||||
MeshRenderData &mr;
|
||||
|
||||
@@ -44,30 +44,6 @@ eMRIterType mesh_extract_iter_type(const MeshExtract *ext)
|
||||
return type;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/** \name Override extractors
|
||||
* Extractors can be overridden. When overridden a specialized version is used. The next functions
|
||||
* would check for any needed overrides and usage of the specialized version.
|
||||
* \{ */
|
||||
|
||||
static const MeshExtract *mesh_extract_override_hq_normals(const MeshExtract *extractor)
|
||||
{
|
||||
if (extractor == &extract_fdots_nor) {
|
||||
return &extract_fdots_nor_hq;
|
||||
}
|
||||
return extractor;
|
||||
}
|
||||
|
||||
const MeshExtract *mesh_extract_override_get(const MeshExtract *extractor,
|
||||
const bool do_hq_normals)
|
||||
{
|
||||
if (do_hq_normals) {
|
||||
extractor = mesh_extract_override_hq_normals(extractor);
|
||||
}
|
||||
|
||||
return extractor;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
@@ -312,7 +312,6 @@ struct EditLoopData {
|
||||
|
||||
void *mesh_extract_buffer_get(const MeshExtract *extractor, MeshBufferList *mbuflist);
|
||||
eMRIterType mesh_extract_iter_type(const MeshExtract *ext);
|
||||
const MeshExtract *mesh_extract_override_get(const MeshExtract *extractor, bool do_hq_normals);
|
||||
void mesh_render_data_face_flag(const MeshRenderData &mr,
|
||||
const BMFace *efa,
|
||||
BMUVOffsets offsets,
|
||||
@@ -326,6 +325,20 @@ void mesh_render_data_loop_edge_flag(const MeshRenderData &mr,
|
||||
BMUVOffsets offsets,
|
||||
EditLoopData &eattr);
|
||||
|
||||
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> void convert_normals(Span<float3> src, MutableSpan<GPUType> dst);
|
||||
|
||||
template<typename T>
|
||||
@@ -354,6 +367,7 @@ void extract_normals_subdiv(const DRWSubdivCache &subdiv_cache,
|
||||
gpu::VertBuf &pos_nor,
|
||||
gpu::VertBuf &lnor);
|
||||
void extract_vert_normals(const MeshRenderData &mr, gpu::VertBuf &vbo);
|
||||
void extract_face_dot_normals(const MeshRenderData &mr, const bool use_hq, gpu::VertBuf &vbo);
|
||||
|
||||
void extract_tris(const MeshRenderData &mr,
|
||||
const SortedFaceData &face_sorted,
|
||||
@@ -409,8 +423,6 @@ extern const MeshExtract extract_edituv_stretch_area;
|
||||
extern const MeshExtract extract_edituv_stretch_angle;
|
||||
extern const MeshExtract extract_mesh_analysis;
|
||||
extern const MeshExtract extract_fdots_pos;
|
||||
extern const MeshExtract extract_fdots_nor;
|
||||
extern const MeshExtract extract_fdots_nor_hq;
|
||||
extern const MeshExtract extract_fdots_uv;
|
||||
extern const MeshExtract extract_fdots_edituv_data;
|
||||
extern const MeshExtract extract_skin_roots;
|
||||
|
||||
@@ -10,172 +10,85 @@
|
||||
|
||||
namespace blender::draw {
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/** \name Extract Face-dots Normal and edit flag
|
||||
* \{ */
|
||||
|
||||
#define NOR_AND_FLAG_DEFAULT 0
|
||||
#define NOR_AND_FLAG_SELECT 1
|
||||
#define NOR_AND_FLAG_ACTIVE -1
|
||||
#define NOR_AND_FLAG_HIDDEN -2
|
||||
|
||||
static void extract_fdots_nor_init(const MeshRenderData &mr,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void *buf,
|
||||
void * /*tls_data*/)
|
||||
template<typename GPUType>
|
||||
static void extract_face_dot_normals_mesh(const MeshRenderData &mr, MutableSpan<GPUType> normals)
|
||||
{
|
||||
gpu::VertBuf *vbo = static_cast<gpu::VertBuf *>(buf);
|
||||
static GPUVertFormat format = {0};
|
||||
if (format.attr_len == 0) {
|
||||
GPU_vertformat_attr_add(&format, "norAndFlag", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
|
||||
}
|
||||
|
||||
GPU_vertbuf_init_with_format(vbo, &format);
|
||||
GPU_vertbuf_data_alloc(vbo, mr.faces_num);
|
||||
convert_normals(mr.face_normals, normals);
|
||||
const GPUType invalid_normal = convert_normal<GPUType>(float3(0));
|
||||
threading::parallel_for(IndexRange(mr.faces_num), 4096, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
const BMFace *face = bm_original_face_get(mr, i);
|
||||
if (!face || BM_elem_flag_test(face, BM_ELEM_HIDDEN)) {
|
||||
normals[i] = invalid_normal;
|
||||
normals[i].w = NOR_AND_FLAG_HIDDEN;
|
||||
}
|
||||
else if (BM_elem_flag_test(face, BM_ELEM_SELECT)) {
|
||||
normals[i].w = (face == mr.efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void extract_fdots_nor_finish(const MeshRenderData &mr,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void *buf,
|
||||
void * /*data*/)
|
||||
template<typename GPUType>
|
||||
void extract_face_dot_normals_bm(const MeshRenderData &mr, MutableSpan<GPUType> normals)
|
||||
{
|
||||
gpu::VertBuf *vbo = static_cast<gpu::VertBuf *>(buf);
|
||||
static float invalid_normal[3] = {0.0f, 0.0f, 0.0f};
|
||||
GPUPackedNormal *nor = (GPUPackedNormal *)GPU_vertbuf_get_data(vbo);
|
||||
BMFace *efa;
|
||||
|
||||
/* Quicker than doing it for each loop. */
|
||||
if (mr.extract_type == MR_EXTRACT_BMESH) {
|
||||
for (int f = 0; f < mr.faces_num; f++) {
|
||||
efa = BM_face_at_index(mr.bm, f);
|
||||
const bool is_face_hidden = BM_elem_flag_test(efa, BM_ELEM_HIDDEN);
|
||||
if (is_face_hidden || (mr.orig_index_face && mr.orig_index_face[f] == ORIGINDEX_NONE)) {
|
||||
nor[f] = GPU_normal_convert_i10_v3(invalid_normal);
|
||||
nor[f].w = NOR_AND_FLAG_HIDDEN;
|
||||
const GPUType invalid_normal = convert_normal<GPUType>(float3(0));
|
||||
threading::parallel_for(IndexRange(mr.faces_num), 4096, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
BMFace *face = BM_face_at_index(mr.bm, i);
|
||||
if (BM_elem_flag_test(face, BM_ELEM_HIDDEN)) {
|
||||
normals[i] = invalid_normal;
|
||||
normals[i].w = NOR_AND_FLAG_HIDDEN;
|
||||
}
|
||||
else {
|
||||
nor[f] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, efa));
|
||||
/* Select / Active Flag. */
|
||||
nor[f].w = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ?
|
||||
((efa == mr.efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) :
|
||||
NOR_AND_FLAG_DEFAULT);
|
||||
normals[i] = convert_normal<GPUType>(bm_face_no_get(mr, face));
|
||||
normals[i].w = (BM_elem_flag_test(face, BM_ELEM_SELECT) ?
|
||||
((face == mr.efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) :
|
||||
NOR_AND_FLAG_DEFAULT);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void extract_face_dot_normals(const MeshRenderData &mr, const bool use_hq, gpu::VertBuf &vbo)
|
||||
{
|
||||
if (use_hq) {
|
||||
static GPUVertFormat format = {0};
|
||||
if (format.attr_len == 0) {
|
||||
GPU_vertformat_attr_add(&format, "norAndFlag", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
|
||||
}
|
||||
GPU_vertbuf_init_with_format(&vbo, &format);
|
||||
GPU_vertbuf_data_alloc(&vbo, mr.faces_num);
|
||||
MutableSpan vbo_data(static_cast<short4 *>(GPU_vertbuf_get_data(&vbo)), mr.faces_num);
|
||||
|
||||
if (mr.extract_type == MR_EXTRACT_MESH) {
|
||||
extract_face_dot_normals_mesh(mr, vbo_data);
|
||||
}
|
||||
else {
|
||||
extract_face_dot_normals_bm(mr, vbo_data);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int f = 0; f < mr.faces_num; f++) {
|
||||
efa = bm_original_face_get(mr, f);
|
||||
const bool is_face_hidden = efa && BM_elem_flag_test(efa, BM_ELEM_HIDDEN);
|
||||
if (is_face_hidden || (mr.orig_index_face && mr.orig_index_face[f] == ORIGINDEX_NONE)) {
|
||||
nor[f] = GPU_normal_convert_i10_v3(invalid_normal);
|
||||
nor[f].w = NOR_AND_FLAG_HIDDEN;
|
||||
}
|
||||
else {
|
||||
nor[f] = GPU_normal_convert_i10_v3(mr.face_normals[f]);
|
||||
/* Select / Active Flag. */
|
||||
nor[f].w = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ?
|
||||
((efa == mr.efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) :
|
||||
NOR_AND_FLAG_DEFAULT);
|
||||
}
|
||||
static GPUVertFormat format = {0};
|
||||
if (format.attr_len == 0) {
|
||||
GPU_vertformat_attr_add(&format, "norAndFlag", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
|
||||
}
|
||||
GPU_vertbuf_init_with_format(&vbo, &format);
|
||||
GPU_vertbuf_data_alloc(&vbo, mr.faces_num);
|
||||
MutableSpan vbo_data(static_cast<GPUPackedNormal *>(GPU_vertbuf_get_data(&vbo)), mr.faces_num);
|
||||
|
||||
if (mr.extract_type == MR_EXTRACT_MESH) {
|
||||
extract_face_dot_normals_mesh(mr, vbo_data);
|
||||
}
|
||||
else {
|
||||
extract_face_dot_normals_bm(mr, vbo_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constexpr MeshExtract create_extractor_fdots_nor()
|
||||
{
|
||||
MeshExtract extractor = {nullptr};
|
||||
extractor.init = extract_fdots_nor_init;
|
||||
extractor.finish = extract_fdots_nor_finish;
|
||||
extractor.data_type = MR_DATA_LOOP_NOR;
|
||||
extractor.data_size = 0;
|
||||
extractor.use_threading = false;
|
||||
extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.fdots_nor);
|
||||
return extractor;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/** \name Extract Face-dots High Quality Normal and edit flag
|
||||
* \{ */
|
||||
|
||||
static void extract_fdots_nor_hq_init(const MeshRenderData &mr,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void *buf,
|
||||
void * /*tls_data*/)
|
||||
{
|
||||
gpu::VertBuf *vbo = static_cast<gpu::VertBuf *>(buf);
|
||||
static GPUVertFormat format = {0};
|
||||
if (format.attr_len == 0) {
|
||||
GPU_vertformat_attr_add(&format, "norAndFlag", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
|
||||
}
|
||||
|
||||
GPU_vertbuf_init_with_format(vbo, &format);
|
||||
GPU_vertbuf_data_alloc(vbo, mr.faces_num);
|
||||
}
|
||||
|
||||
static void extract_fdots_nor_hq_finish(const MeshRenderData &mr,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void *buf,
|
||||
void * /*data*/)
|
||||
{
|
||||
gpu::VertBuf *vbo = static_cast<gpu::VertBuf *>(buf);
|
||||
static float invalid_normal[3] = {0.0f, 0.0f, 0.0f};
|
||||
short *nor = (short *)GPU_vertbuf_get_data(vbo);
|
||||
BMFace *efa;
|
||||
|
||||
/* Quicker than doing it for each loop. */
|
||||
if (mr.extract_type == MR_EXTRACT_BMESH) {
|
||||
for (int f = 0; f < mr.faces_num; f++) {
|
||||
efa = BM_face_at_index(mr.bm, f);
|
||||
const bool is_face_hidden = BM_elem_flag_test(efa, BM_ELEM_HIDDEN);
|
||||
if (is_face_hidden || (mr.orig_index_face && mr.orig_index_face[f] == ORIGINDEX_NONE)) {
|
||||
normal_float_to_short_v3(&nor[f * 4], invalid_normal);
|
||||
nor[f * 4 + 3] = NOR_AND_FLAG_HIDDEN;
|
||||
}
|
||||
else {
|
||||
normal_float_to_short_v3(&nor[f * 4], bm_face_no_get(mr, efa));
|
||||
/* Select / Active Flag. */
|
||||
nor[f * 4 + 3] = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ?
|
||||
((efa == mr.efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) :
|
||||
NOR_AND_FLAG_DEFAULT);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int f = 0; f < mr.faces_num; f++) {
|
||||
efa = bm_original_face_get(mr, f);
|
||||
const bool is_face_hidden = efa && BM_elem_flag_test(efa, BM_ELEM_HIDDEN);
|
||||
if (is_face_hidden || (mr.orig_index_face && mr.orig_index_face[f] == ORIGINDEX_NONE)) {
|
||||
normal_float_to_short_v3(&nor[f * 4], invalid_normal);
|
||||
nor[f * 4 + 3] = NOR_AND_FLAG_HIDDEN;
|
||||
}
|
||||
else {
|
||||
normal_float_to_short_v3(&nor[f * 4], bm_face_no_get(mr, efa));
|
||||
/* Select / Active Flag. */
|
||||
nor[f * 4 + 3] = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ?
|
||||
((efa == mr.efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) :
|
||||
NOR_AND_FLAG_DEFAULT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constexpr MeshExtract create_extractor_fdots_nor_hq()
|
||||
{
|
||||
MeshExtract extractor = {nullptr};
|
||||
extractor.init = extract_fdots_nor_hq_init;
|
||||
extractor.finish = extract_fdots_nor_hq_finish;
|
||||
extractor.data_type = MR_DATA_LOOP_NOR;
|
||||
extractor.data_size = 0;
|
||||
extractor.use_threading = false;
|
||||
extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.fdots_nor);
|
||||
return extractor;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
const MeshExtract extract_fdots_nor = create_extractor_fdots_nor();
|
||||
const MeshExtract extract_fdots_nor_hq = create_extractor_fdots_nor_hq();
|
||||
|
||||
} // namespace blender::draw
|
||||
|
||||
@@ -14,20 +14,6 @@
|
||||
|
||||
namespace blender::draw {
|
||||
|
||||
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 convert_normals_impl(const Span<float3> src, MutableSpan<GPUType> dst)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user