color attribute system.
This commit removes sculpt colors from experimental
status and unifies it with vertex colors. It
introduces the concept of "color attributes", which
are any attributes that represents colors. Color
attributes can be represented with byte or floating-point
numbers and can be stored in either vertices or
face corners.
Color attributes share a common namespace
(so you can no longer have a floating-point
sculpt color attribute and a byte vertex color
attribute with the same name).
Note: this commit does not include vertex paint mode,
which is a separate patch, see:
https://developer.blender.org/D14179
Differential Revision: https://developer.blender.org/D12587
Ref D12587
344 lines
11 KiB
C
344 lines
11 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later
|
|
* Copyright 2019 Blender Foundation. */
|
|
|
|
/** \file
|
|
* \ingroup draw
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
struct DRWSubdivCache;
|
|
struct MeshRenderData;
|
|
struct TaskGraph;
|
|
|
|
#include "DNA_customdata_types.h"
|
|
|
|
#include "BKE_attribute.h"
|
|
#include "BKE_object.h"
|
|
|
|
#include "GPU_batch.h"
|
|
#include "GPU_index_buffer.h"
|
|
#include "GPU_vertex_buffer.h"
|
|
|
|
/* Vertex Group Selection and display options */
|
|
typedef 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;
|
|
|
|
/* 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),
|
|
};
|
|
|
|
typedef struct DRW_MeshCDMask {
|
|
uint32_t uv : 8;
|
|
uint32_t tan : 8;
|
|
uint32_t vcol : 8;
|
|
uint32_t orco : 1;
|
|
uint32_t tan_orco : 1;
|
|
uint32_t sculpt_overlays : 1;
|
|
/** Edit uv layer is from the base edit mesh as
|
|
* modifiers could remove it. (see T68857) */
|
|
uint32_t edit_uv : 1;
|
|
} DRW_MeshCDMask;
|
|
/* Keep `DRW_MeshCDMask` struct within an `uint32_t`.
|
|
* bit-wise and atomic operations are used to compare and update the struct.
|
|
* See `mesh_cd_layers_type_*` functions. */
|
|
BLI_STATIC_ASSERT(sizeof(DRW_MeshCDMask) <= sizeof(uint32_t), "DRW_MeshCDMask exceeds 32 bits")
|
|
typedef enum eMRIterType {
|
|
MR_ITER_LOOPTRI = 1 << 0,
|
|
MR_ITER_POLY = 1 << 1,
|
|
MR_ITER_LEDGE = 1 << 2,
|
|
MR_ITER_LVERT = 1 << 3,
|
|
} eMRIterType;
|
|
ENUM_OPERATORS(eMRIterType, MR_ITER_LVERT)
|
|
|
|
typedef struct DRW_AttributeRequest {
|
|
CustomDataType cd_type;
|
|
int layer_index;
|
|
AttributeDomain domain;
|
|
} DRW_AttributeRequest;
|
|
|
|
typedef struct DRW_MeshAttributes {
|
|
DRW_AttributeRequest requests[GPU_MAX_ATTR];
|
|
int num_requests;
|
|
} DRW_MeshAttributes;
|
|
|
|
typedef 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,
|
|
} eMRDataType;
|
|
ENUM_OPERATORS(eMRDataType, MR_DATA_POLYS_SORTED)
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
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 MAX2(1, editmesh_eval_final->totcol);
|
|
}
|
|
}
|
|
return MAX2(1, me->totcol);
|
|
}
|
|
|
|
typedef struct MeshBufferList {
|
|
/* Every VBO below contains at least enough
|
|
* data for every loops 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 *vcol;
|
|
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];
|
|
} vbo;
|
|
/* Index Buffers:
|
|
* Only need to be updated when topology changes. */
|
|
struct {
|
|
/* Indices to vloops. */
|
|
GPUIndexBuf *tris; /* Ordered per material. */
|
|
GPUIndexBuf *lines; /* Loose edges last. */
|
|
GPUIndexBuf *lines_loose; /* sub buffer of `lines` only containing the loose edges. */
|
|
GPUIndexBuf *points;
|
|
GPUIndexBuf *fdots;
|
|
/* 3D overlays. */
|
|
GPUIndexBuf *lines_paint_mask; /* no loose edges. */
|
|
GPUIndexBuf *lines_adjacency;
|
|
/* Uv overlays. (visibility can differ from 3D view) */
|
|
GPUIndexBuf *edituv_tris;
|
|
GPUIndexBuf *edituv_lines;
|
|
GPUIndexBuf *edituv_points;
|
|
GPUIndexBuf *edituv_fdots;
|
|
} ibo;
|
|
} MeshBufferList;
|
|
|
|
typedef 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;
|
|
GPUBatch *wire_edges; /* Individual edges with face normals. */
|
|
GPUBatch *wire_loops; /* Loops around faces. no edges between selected faces */
|
|
GPUBatch *wire_loops_uvs; /* Same as wire_loops but only has uvs. */
|
|
GPUBatch *sculpt_overlays;
|
|
} MeshBatchList;
|
|
|
|
#define MBC_BATCH_LEN (sizeof(MeshBatchList) / sizeof(void *))
|
|
#define MBC_VBO_LEN (sizeof(((MeshBufferList){0}).vbo) / sizeof(void *))
|
|
#define MBC_IBO_LEN (sizeof(((MeshBufferList){0}).ibo) / sizeof(void *))
|
|
|
|
#define MBC_BATCH_INDEX(batch) (offsetof(MeshBatchList, batch) / sizeof(void *))
|
|
|
|
typedef 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)),
|
|
} DRWBatchFlag;
|
|
|
|
BLI_STATIC_ASSERT(MBC_BATCH_LEN < 32, "Number of batches exceeded the limit of bit fields");
|
|
|
|
typedef struct MeshExtractLooseGeom {
|
|
int edge_len;
|
|
int vert_len;
|
|
int *verts;
|
|
int *edges;
|
|
} MeshExtractLooseGeom;
|
|
|
|
/**
|
|
* Data that are kept around between extractions to reduce rebuilding time.
|
|
*
|
|
* - Loose geometry.
|
|
*/
|
|
typedef struct MeshBufferCache {
|
|
MeshBufferList buff;
|
|
|
|
MeshExtractLooseGeom loose_geom;
|
|
|
|
struct {
|
|
int *tri_first_index;
|
|
int *mat_tri_len;
|
|
int visible_tri_len;
|
|
} poly_sorted;
|
|
} MeshBufferCache;
|
|
|
|
#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))
|
|
|
|
typedef 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;
|
|
|
|
struct DRWSubdivCache *subdiv_cache;
|
|
|
|
DRWBatchFlag batch_requested; /* DRWBatchFlag */
|
|
DRWBatchFlag batch_ready; /* DRWBatchFlag */
|
|
|
|
/* settings to determine if cache is invalid */
|
|
int edge_len;
|
|
int tri_len;
|
|
int poly_len;
|
|
int vert_len;
|
|
int mat_len;
|
|
bool is_dirty; /* Instantly invalidates cache, skipping mesh check */
|
|
bool is_editmode;
|
|
bool is_uvsyncsel;
|
|
|
|
struct DRW_MeshWeightState weight_state;
|
|
|
|
DRW_MeshCDMask cd_used, cd_needed, cd_used_over_time;
|
|
|
|
DRW_MeshAttributes 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;
|
|
} MeshBatchCache;
|
|
|
|
#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)
|
|
|
|
void mesh_buffer_cache_create_requested(struct 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,
|
|
bool use_subsurf_fdots,
|
|
const Scene *scene,
|
|
const struct ToolSettings *ts,
|
|
bool use_hide);
|
|
|
|
void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache,
|
|
MeshBufferCache *mbc,
|
|
struct DRWSubdivCache *subdiv_cache,
|
|
struct MeshRenderData *mr);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|