This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/draw/intern/draw_cache_extract.hh
Hans Goudey aa1fc6102f Cleanup: Avoid contractions for loose geometry variables
Saving five characters for these names doesn't have much benefit,
and using the full word avoids readers wondering what "l" is supposed
to mean.
2023-03-20 23:16:50 +01:00

336 lines
11 KiB
C++

/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2019 Blender Foundation. */
/** \file
* \ingroup draw
*/
#pragma once
#include <algorithm>
#include "BLI_utildefines.h"
#include "DNA_customdata_types.h"
#include "DNA_mesh_types.h"
#include "DNA_view3d_enums.h"
#include "BKE_attribute.h"
#include "BKE_object.h"
#include "GPU_batch.h"
#include "GPU_index_buffer.h"
#include "GPU_vertex_buffer.h"
#include "draw_attributes.hh"
struct DRWSubdivCache;
struct MeshRenderData;
struct TaskGraph;
/* Vertex Group Selection and display options */
struct DRW_MeshWeightState {
int defgroup_active;
int defgroup_len;
short flags;
char alert_mode;
/* Set of all selected bones for Multi-paint. */
bool *defgroup_sel; /* #defgroup_len */
int defgroup_sel_count;
/* Set of all locked and unlocked deform bones for Lock Relative mode. */
bool *defgroup_locked; /* #defgroup_len */
bool *defgroup_unlocked; /* #defgroup_len */
};
/* DRW_MeshWeightState.flags */
enum {
DRW_MESH_WEIGHT_STATE_MULTIPAINT = (1 << 0),
DRW_MESH_WEIGHT_STATE_AUTO_NORMALIZE = (1 << 1),
DRW_MESH_WEIGHT_STATE_LOCK_RELATIVE = (1 << 2),
};
enum eMRIterType {
MR_ITER_LOOPTRI = 1 << 0,
MR_ITER_POLY = 1 << 1,
MR_ITER_LOOSE_EDGE = 1 << 2,
MR_ITER_LOOSE_VERT = 1 << 3,
};
ENUM_OPERATORS(eMRIterType, MR_ITER_LOOSE_VERT)
enum eMRDataType {
MR_DATA_NONE = 0,
MR_DATA_POLY_NOR = 1 << 1,
MR_DATA_LOOP_NOR = 1 << 2,
MR_DATA_LOOPTRI = 1 << 3,
MR_DATA_LOOSE_GEOM = 1 << 4,
/** Force loop normals calculation. */
MR_DATA_TAN_LOOP_NOR = 1 << 5,
MR_DATA_POLYS_SORTED = 1 << 6,
};
ENUM_OPERATORS(eMRDataType, MR_DATA_POLYS_SORTED)
BLI_INLINE int mesh_render_mat_len_get(const Object *object, const Mesh *me)
{
if (me->edit_mesh != NULL) {
const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(object);
if (editmesh_eval_final != NULL) {
return std::max<int>(1, editmesh_eval_final->totcol);
}
}
return std::max<int>(1, me->totcol);
}
struct MeshBufferList {
/* Every VBO below contains at least enough data for every loop in the mesh
* (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 *edge_fac; /* extend */
GPUVertBuf *weights; /* extend */
GPUVertBuf *uv;
GPUVertBuf *tan;
GPUVertBuf *sculpt_data;
GPUVertBuf *orco;
/* Only for edit mode. */
GPUVertBuf *edit_data; /* extend */
GPUVertBuf *edituv_data;
GPUVertBuf *edituv_stretch_area;
GPUVertBuf *edituv_stretch_angle;
GPUVertBuf *mesh_analysis;
GPUVertBuf *fdots_pos;
GPUVertBuf *fdots_nor;
GPUVertBuf *fdots_uv;
// GPUVertBuf *fdots_edit_data; /* inside fdots_nor for now. */
GPUVertBuf *fdots_edituv_data;
GPUVertBuf *skin_roots;
/* Selection */
GPUVertBuf *vert_idx; /* extend */
GPUVertBuf *edge_idx; /* extend */
GPUVertBuf *poly_idx;
GPUVertBuf *fdot_idx;
GPUVertBuf *attr[GPU_MAX_ATTR];
GPUVertBuf *attr_viewer;
} vbo;
/* Index Buffers:
* Only need to be updated when topology changes. */
struct {
/* Indices to vloops. Ordered per material. */
GPUIndexBuf *tris;
/* Loose edges last. */
GPUIndexBuf *lines;
/* Sub buffer of `lines` only containing the loose edges. */
GPUIndexBuf *lines_loose;
GPUIndexBuf *points;
GPUIndexBuf *fdots;
/* 3D overlays. */
/* no loose edges. */
GPUIndexBuf *lines_paint_mask;
GPUIndexBuf *lines_adjacency;
/* Uv overlays. (visibility can differ from 3D view) */
GPUIndexBuf *edituv_tris;
GPUIndexBuf *edituv_lines;
GPUIndexBuf *edituv_points;
GPUIndexBuf *edituv_fdots;
} ibo;
};
struct MeshBatchList {
/* Surfaces / Render */
GPUBatch *surface;
GPUBatch *surface_weights;
/* Edit mode */
GPUBatch *edit_triangles;
GPUBatch *edit_vertices;
GPUBatch *edit_edges;
GPUBatch *edit_vnor;
GPUBatch *edit_lnor;
GPUBatch *edit_fdots;
GPUBatch *edit_mesh_analysis;
GPUBatch *edit_skin_roots;
/* Edit UVs */
GPUBatch *edituv_faces_stretch_area;
GPUBatch *edituv_faces_stretch_angle;
GPUBatch *edituv_faces;
GPUBatch *edituv_edges;
GPUBatch *edituv_verts;
GPUBatch *edituv_fdots;
/* Edit selection */
GPUBatch *edit_selection_verts;
GPUBatch *edit_selection_edges;
GPUBatch *edit_selection_faces;
GPUBatch *edit_selection_fdots;
/* Common display / Other */
GPUBatch *all_verts;
GPUBatch *all_edges;
GPUBatch *loose_edges;
GPUBatch *edge_detection;
/* Individual edges with face normals. */
GPUBatch *wire_edges;
/* Loops around faces. no edges between selected faces */
GPUBatch *wire_loops;
/* Same as wire_loops but only has uvs. */
GPUBatch *wire_loops_uvs;
GPUBatch *sculpt_overlays;
GPUBatch *surface_viewer_attribute;
};
#define MBC_BATCH_LEN (sizeof(MeshBatchList) / sizeof(void *))
#define MBC_VBO_LEN (sizeof(MeshBufferList::vbo) / sizeof(void *))
#define MBC_IBO_LEN (sizeof(MeshBufferList::ibo) / sizeof(void *))
#define MBC_BATCH_INDEX(batch) (offsetof(MeshBatchList, batch) / sizeof(void *))
enum DRWBatchFlag {
MBC_SURFACE = (1u << MBC_BATCH_INDEX(surface)),
MBC_SURFACE_WEIGHTS = (1u << MBC_BATCH_INDEX(surface_weights)),
MBC_EDIT_TRIANGLES = (1u << MBC_BATCH_INDEX(edit_triangles)),
MBC_EDIT_VERTICES = (1u << MBC_BATCH_INDEX(edit_vertices)),
MBC_EDIT_EDGES = (1u << MBC_BATCH_INDEX(edit_edges)),
MBC_EDIT_VNOR = (1u << MBC_BATCH_INDEX(edit_vnor)),
MBC_EDIT_LNOR = (1u << MBC_BATCH_INDEX(edit_lnor)),
MBC_EDIT_FACEDOTS = (1u << MBC_BATCH_INDEX(edit_fdots)),
MBC_EDIT_MESH_ANALYSIS = (1u << MBC_BATCH_INDEX(edit_mesh_analysis)),
MBC_SKIN_ROOTS = (1u << MBC_BATCH_INDEX(edit_skin_roots)),
MBC_EDITUV_FACES_STRETCH_AREA = (1u << MBC_BATCH_INDEX(edituv_faces_stretch_area)),
MBC_EDITUV_FACES_STRETCH_ANGLE = (1u << MBC_BATCH_INDEX(edituv_faces_stretch_angle)),
MBC_EDITUV_FACES = (1u << MBC_BATCH_INDEX(edituv_faces)),
MBC_EDITUV_EDGES = (1u << MBC_BATCH_INDEX(edituv_edges)),
MBC_EDITUV_VERTS = (1u << MBC_BATCH_INDEX(edituv_verts)),
MBC_EDITUV_FACEDOTS = (1u << MBC_BATCH_INDEX(edituv_fdots)),
MBC_EDIT_SELECTION_VERTS = (1u << MBC_BATCH_INDEX(edit_selection_verts)),
MBC_EDIT_SELECTION_EDGES = (1u << MBC_BATCH_INDEX(edit_selection_edges)),
MBC_EDIT_SELECTION_FACES = (1u << MBC_BATCH_INDEX(edit_selection_faces)),
MBC_EDIT_SELECTION_FACEDOTS = (1u << MBC_BATCH_INDEX(edit_selection_fdots)),
MBC_ALL_VERTS = (1u << MBC_BATCH_INDEX(all_verts)),
MBC_ALL_EDGES = (1u << MBC_BATCH_INDEX(all_edges)),
MBC_LOOSE_EDGES = (1u << MBC_BATCH_INDEX(loose_edges)),
MBC_EDGE_DETECTION = (1u << MBC_BATCH_INDEX(edge_detection)),
MBC_WIRE_EDGES = (1u << MBC_BATCH_INDEX(wire_edges)),
MBC_WIRE_LOOPS = (1u << MBC_BATCH_INDEX(wire_loops)),
MBC_WIRE_LOOPS_UVS = (1u << MBC_BATCH_INDEX(wire_loops_uvs)),
MBC_SCULPT_OVERLAYS = (1u << MBC_BATCH_INDEX(sculpt_overlays)),
MBC_VIEWER_ATTRIBUTE_OVERLAY = (1u << MBC_BATCH_INDEX(surface_viewer_attribute)),
MBC_SURFACE_PER_MAT = (1u << MBC_BATCH_LEN),
};
ENUM_OPERATORS(DRWBatchFlag, MBC_SURFACE_PER_MAT);
BLI_STATIC_ASSERT(MBC_BATCH_LEN < 32, "Number of batches exceeded the limit of bit fields");
struct MeshExtractLooseGeom {
/** Indices of all vertices not used by edges in the #Mesh or #BMesh. */
blender::Array<int> verts;
/** Indices of all edges not used by faces in the #Mesh or #BMesh. */
blender::Array<int> edges;
};
struct SortedPolyData {
/** The first triangle index for each polygon, sorted into slices by material. */
blender::Array<int> tri_first_index;
/** The number of visible triangles assigned to each material. */
blender::Array<int> mat_tri_len;
/* The total number of visible triangles (a sum of the values in #mat_tri_len). */
int visible_tri_len;
};
/**
* Data that are kept around between extractions to reduce rebuilding time.
*
* - Loose geometry.
*/
struct MeshBufferCache {
MeshBufferList buff;
MeshExtractLooseGeom loose_geom;
SortedPolyData poly_sorted;
};
#define FOREACH_MESH_BUFFER_CACHE(batch_cache, mbc) \
for (MeshBufferCache *mbc = &batch_cache->final; \
mbc == &batch_cache->final || mbc == &batch_cache->cage || mbc == &batch_cache->uv_cage; \
mbc = (mbc == &batch_cache->final) ? \
&batch_cache->cage : \
((mbc == &batch_cache->cage) ? &batch_cache->uv_cage : NULL))
struct MeshBatchCache {
MeshBufferCache final, cage, uv_cage;
MeshBatchList batch;
/* Index buffer per material. These are subranges of `ibo.tris` */
GPUIndexBuf **tris_per_mat;
GPUBatch **surface_per_mat;
DRWSubdivCache *subdiv_cache;
DRWBatchFlag batch_requested;
DRWBatchFlag batch_ready;
/* Settings to determine if cache is invalid. */
int edge_len;
int tri_len;
int poly_len;
int vert_len;
int mat_len;
/* Instantly invalidates cache, skipping mesh check */
bool is_dirty;
bool is_editmode;
bool is_uvsyncsel;
DRW_MeshWeightState weight_state;
DRW_MeshCDMask cd_used, cd_needed, cd_used_over_time;
DRW_Attributes attr_used, attr_needed, attr_used_over_time;
int lastmatch;
/* Valid only if edge_detection is up to date. */
bool is_manifold;
/* Total areas for drawing UV Stretching. Contains the summed area in mesh
* space (`tot_area`) and the summed area in uv space (`tot_uvarea`).
*
* Only valid after `DRW_mesh_batch_cache_create_requested` has been called. */
float tot_area, tot_uv_area;
bool no_loose_wire;
eV3DShadingColorType color_type;
bool pbvh_is_drawing;
};
#define MBC_EDITUV \
(MBC_EDITUV_FACES_STRETCH_AREA | MBC_EDITUV_FACES_STRETCH_ANGLE | MBC_EDITUV_FACES | \
MBC_EDITUV_EDGES | MBC_EDITUV_VERTS | MBC_EDITUV_FACEDOTS | MBC_WIRE_LOOPS_UVS)
namespace blender::draw {
void mesh_buffer_cache_create_requested(TaskGraph *task_graph,
MeshBatchCache *cache,
MeshBufferCache *mbc,
Object *object,
Mesh *me,
bool is_editmode,
bool is_paint_mode,
bool is_mode_active,
const float obmat[4][4],
bool do_final,
bool do_uvedit,
const Scene *scene,
const ToolSettings *ts,
bool use_hide);
void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache,
MeshBufferCache *mbc,
DRWSubdivCache *subdiv_cache,
MeshRenderData *mr);
} // namespace blender::draw