2017-01-25 09:16:29 +01:00
|
|
|
/*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2017 by Blender Foundation.
|
|
|
|
* All rights reserved.
|
|
|
|
*/
|
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
* \ingroup draw
|
2017-01-25 09:16:29 +01:00
|
|
|
*
|
|
|
|
* \brief Mesh API for render engines
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_alloca.h"
|
2019-07-01 23:20:36 +10:00
|
|
|
#include "BLI_bitmap.h"
|
2018-09-29 19:42:09 +02:00
|
|
|
#include "BLI_buffer.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_edgehash.h"
|
2020-04-03 17:38:58 +02:00
|
|
|
#include "BLI_listbase.h"
|
2017-06-28 13:38:24 +10:00
|
|
|
#include "BLI_math_bits.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_math_vector.h"
|
2017-05-01 17:58:15 +02:00
|
|
|
#include "BLI_string.h"
|
2020-06-02 15:07:17 +02:00
|
|
|
#include "BLI_task.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_utildefines.h"
|
2017-02-16 16:19:48 +01:00
|
|
|
|
2017-01-25 09:16:29 +01:00
|
|
|
#include "DNA_mesh_types.h"
|
|
|
|
#include "DNA_meshdata_types.h"
|
2017-05-03 18:55:40 +02:00
|
|
|
#include "DNA_object_types.h"
|
2018-12-17 23:00:05 +01:00
|
|
|
#include "DNA_scene_types.h"
|
2017-01-25 09:16:29 +01:00
|
|
|
|
|
|
|
#include "BKE_customdata.h"
|
2017-05-03 18:55:40 +02:00
|
|
|
#include "BKE_deform.h"
|
2017-01-25 09:16:29 +01:00
|
|
|
#include "BKE_editmesh.h"
|
2018-10-08 12:18:45 +11:00
|
|
|
#include "BKE_editmesh_cache.h"
|
2017-05-09 08:50:45 +10:00
|
|
|
#include "BKE_editmesh_tangent.h"
|
2017-01-25 09:16:29 +01:00
|
|
|
#include "BKE_mesh.h"
|
2018-10-11 15:07:29 +11:00
|
|
|
#include "BKE_mesh_runtime.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_mesh_tangent.h"
|
2019-07-07 18:58:11 +02:00
|
|
|
#include "BKE_modifier.h"
|
2018-12-17 23:00:05 +01:00
|
|
|
#include "BKE_object_deform.h"
|
2017-01-25 09:16:29 +01:00
|
|
|
|
2019-04-06 01:55:21 +02:00
|
|
|
#include "atomic_ops.h"
|
2018-12-17 17:01:06 +01:00
|
|
|
|
2017-02-23 11:54:40 +01:00
|
|
|
#include "bmesh.h"
|
|
|
|
|
2017-01-25 09:16:29 +01:00
|
|
|
#include "GPU_batch.h"
|
2017-06-28 13:38:24 +10:00
|
|
|
#include "GPU_material.h"
|
2018-05-19 13:31:44 +02:00
|
|
|
|
|
|
|
#include "DRW_render.h"
|
2017-01-25 09:16:29 +01:00
|
|
|
|
2018-09-29 19:42:09 +02:00
|
|
|
#include "ED_mesh.h"
|
|
|
|
#include "ED_uvedit.h"
|
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
#include "draw_cache_extract.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "draw_cache_inline.h"
|
2019-05-07 23:02:42 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
#include "draw_cache_impl.h" /* own include */
|
2018-12-03 14:58:29 +11:00
|
|
|
|
2017-04-21 21:14:11 +10:00
|
|
|
static void mesh_batch_cache_clear(Mesh *me);
|
|
|
|
|
2018-12-16 15:17:31 +01:00
|
|
|
/* Return true is all layers in _b_ are inside _a_. */
|
2019-04-06 01:55:21 +02:00
|
|
|
BLI_INLINE bool mesh_cd_layers_type_overlap(DRW_MeshCDMask a, DRW_MeshCDMask b)
|
2018-12-16 15:17:31 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
return (*((uint32_t *)&a) & *((uint32_t *)&b)) == *((uint32_t *)&b);
|
2018-12-16 15:17:31 +01:00
|
|
|
}
|
|
|
|
|
2019-04-19 02:22:22 +02:00
|
|
|
BLI_INLINE bool mesh_cd_layers_type_equal(DRW_MeshCDMask a, DRW_MeshCDMask b)
|
|
|
|
{
|
|
|
|
return *((uint32_t *)&a) == *((uint32_t *)&b);
|
|
|
|
}
|
|
|
|
|
2019-04-06 01:55:21 +02:00
|
|
|
BLI_INLINE void mesh_cd_layers_type_merge(DRW_MeshCDMask *a, DRW_MeshCDMask b)
|
2018-12-16 15:17:31 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
atomic_fetch_and_or_uint32((uint32_t *)a, *(uint32_t *)&b);
|
2019-04-06 01:55:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
BLI_INLINE void mesh_cd_layers_type_clear(DRW_MeshCDMask *a)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
*((uint32_t *)a) = 0;
|
2018-12-16 15:17:31 +01:00
|
|
|
}
|
2017-04-18 23:29:55 +10:00
|
|
|
|
2019-10-08 18:35:57 +02:00
|
|
|
static void mesh_cd_calc_edit_uv_layer(const Mesh *UNUSED(me), DRW_MeshCDMask *cd_used)
|
|
|
|
{
|
|
|
|
cd_used->edit_uv = 1;
|
|
|
|
}
|
|
|
|
|
2020-05-25 20:16:42 +10:00
|
|
|
BLI_INLINE const CustomData *mesh_cd_ldata_get_from_mesh(const Mesh *me)
|
|
|
|
{
|
|
|
|
switch ((eMeshWrapperType)me->runtime.wrapper_type) {
|
|
|
|
case ME_WRAPPER_TYPE_MDATA:
|
|
|
|
return &me->ldata;
|
|
|
|
break;
|
|
|
|
case ME_WRAPPER_TYPE_BMESH:
|
|
|
|
return &me->edit_mesh->bm->ldata;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_assert(0);
|
|
|
|
return &me->ldata;
|
|
|
|
}
|
|
|
|
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
BLI_INLINE const CustomData *mesh_cd_vdata_get_from_mesh(const Mesh *me)
|
|
|
|
{
|
|
|
|
switch ((eMeshWrapperType)me->runtime.wrapper_type) {
|
|
|
|
case ME_WRAPPER_TYPE_MDATA:
|
|
|
|
return &me->vdata;
|
|
|
|
break;
|
|
|
|
case ME_WRAPPER_TYPE_BMESH:
|
|
|
|
return &me->edit_mesh->bm->vdata;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_assert(0);
|
|
|
|
return &me->vdata;
|
|
|
|
}
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
static void mesh_cd_calc_active_uv_layer(const Mesh *me, DRW_MeshCDMask *cd_used)
|
2018-12-17 11:37:27 +01:00
|
|
|
{
|
2019-10-08 18:35:57 +02:00
|
|
|
const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me;
|
2020-05-25 20:16:42 +10:00
|
|
|
const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final);
|
2019-04-17 06:17:24 +02:00
|
|
|
int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
|
|
|
|
if (layer != -1) {
|
|
|
|
cd_used->uv |= (1 << layer);
|
|
|
|
}
|
2018-12-17 11:37:27 +01:00
|
|
|
}
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
static void mesh_cd_calc_active_mask_uv_layer(const Mesh *me, DRW_MeshCDMask *cd_used)
|
2019-03-21 16:44:01 +01:00
|
|
|
{
|
2019-10-08 18:35:57 +02:00
|
|
|
const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me;
|
2020-05-25 20:16:42 +10:00
|
|
|
const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final);
|
2019-04-17 06:17:24 +02:00
|
|
|
int layer = CustomData_get_stencil_layer(cd_ldata, CD_MLOOPUV);
|
|
|
|
if (layer != -1) {
|
|
|
|
cd_used->uv |= (1 << layer);
|
|
|
|
}
|
2019-03-21 16:44:01 +01:00
|
|
|
}
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
static void mesh_cd_calc_active_vcol_layer(const Mesh *me, DRW_MeshCDMask *cd_used)
|
2018-12-18 02:18:55 +01:00
|
|
|
{
|
2019-10-08 18:35:57 +02:00
|
|
|
const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me;
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
const CustomData *cd_vdata = mesh_cd_vdata_get_from_mesh(me_final);
|
|
|
|
|
|
|
|
int layer = CustomData_get_active_layer(cd_vdata, CD_PROP_COLOR);
|
|
|
|
if (layer != -1) {
|
|
|
|
cd_used->sculpt_vcol |= (1 << layer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void mesh_cd_calc_active_mloopcol_layer(const Mesh *me, DRW_MeshCDMask *cd_used)
|
|
|
|
{
|
|
|
|
const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me;
|
|
|
|
const CustomData *cd_ldata = &me_final->ldata;
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL);
|
|
|
|
if (layer != -1) {
|
|
|
|
cd_used->vcol |= (1 << layer);
|
|
|
|
}
|
2018-12-18 02:18:55 +01:00
|
|
|
}
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me,
|
|
|
|
struct GPUMaterial **gpumat_array,
|
|
|
|
int gpumat_array_len)
|
2017-06-28 13:38:24 +10:00
|
|
|
{
|
2019-10-08 16:59:29 +02:00
|
|
|
const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me;
|
2020-05-25 20:16:42 +10:00
|
|
|
const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final);
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
const CustomData *cd_vdata = mesh_cd_vdata_get_from_mesh(me_final);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
|
|
|
/* See: DM_vertex_attributes_from_gpu for similar logic */
|
|
|
|
DRW_MeshCDMask cd_used;
|
|
|
|
mesh_cd_layers_type_clear(&cd_used);
|
|
|
|
|
|
|
|
for (int i = 0; i < gpumat_array_len; i++) {
|
|
|
|
GPUMaterial *gpumat = gpumat_array[i];
|
|
|
|
if (gpumat) {
|
2020-02-14 10:47:20 +01:00
|
|
|
ListBase gpu_attrs = GPU_material_attributes(gpumat);
|
2020-04-03 19:15:01 +02:00
|
|
|
LISTBASE_FOREACH (GPUMaterialAttribute *, gpu_attr, &gpu_attrs) {
|
2020-02-14 10:47:20 +01:00
|
|
|
const char *name = gpu_attr->name;
|
|
|
|
int type = gpu_attr->type;
|
2019-04-17 06:17:24 +02:00
|
|
|
int layer = -1;
|
|
|
|
|
|
|
|
if (type == CD_AUTO_FROM_NAME) {
|
|
|
|
/* We need to deduct what exact layer is used.
|
|
|
|
*
|
|
|
|
* We do it based on the specified name.
|
|
|
|
*/
|
|
|
|
if (name[0] != '\0') {
|
|
|
|
layer = CustomData_get_named_layer(cd_ldata, CD_MLOOPUV, name);
|
|
|
|
type = CD_MTFACE;
|
|
|
|
|
|
|
|
if (layer == -1) {
|
|
|
|
layer = CustomData_get_named_layer(cd_ldata, CD_MLOOPCOL, name);
|
|
|
|
type = CD_MCOL;
|
|
|
|
}
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
|
|
|
|
if (layer == -1) {
|
|
|
|
layer = CustomData_get_named_layer(cd_vdata, CD_PROP_COLOR, name);
|
|
|
|
type = CD_PROP_COLOR;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
#if 0 /* Tangents are always from UV's - this will never happen. */
|
|
|
|
if (layer == -1) {
|
|
|
|
layer = CustomData_get_named_layer(cd_ldata, CD_TANGENT, name);
|
|
|
|
type = CD_TANGENT;
|
|
|
|
}
|
2017-06-29 15:23:47 +10:00
|
|
|
#endif
|
2019-04-17 06:17:24 +02:00
|
|
|
if (layer == -1) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* Fall back to the UV layer, which matches old behavior. */
|
|
|
|
type = CD_MTFACE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case CD_MTFACE: {
|
|
|
|
if (layer == -1) {
|
|
|
|
layer = (name[0] != '\0') ? CustomData_get_named_layer(cd_ldata, CD_MLOOPUV, name) :
|
2019-07-08 13:35:55 +02:00
|
|
|
CustomData_get_render_layer(cd_ldata, CD_MLOOPUV);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
if (layer != -1) {
|
|
|
|
cd_used.uv |= (1 << layer);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CD_TANGENT: {
|
|
|
|
if (layer == -1) {
|
|
|
|
layer = (name[0] != '\0') ? CustomData_get_named_layer(cd_ldata, CD_MLOOPUV, name) :
|
2019-07-08 13:35:55 +02:00
|
|
|
CustomData_get_render_layer(cd_ldata, CD_MLOOPUV);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
|
|
|
/* Only fallback to orco (below) when we have no UV layers, see: T56545 */
|
|
|
|
if (layer == -1 && name[0] != '\0') {
|
2019-07-08 13:35:55 +02:00
|
|
|
layer = CustomData_get_render_layer(cd_ldata, CD_MLOOPUV);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (layer != -1) {
|
|
|
|
cd_used.tan |= (1 << layer);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* no UV layers at all => requesting orco */
|
|
|
|
cd_used.tan_orco = 1;
|
|
|
|
cd_used.orco = 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
case CD_PROP_COLOR: {
|
|
|
|
/* Sculpt Vertex Colors */
|
|
|
|
if (layer == -1) {
|
|
|
|
layer = (name[0] != '\0') ?
|
|
|
|
CustomData_get_named_layer(cd_vdata, CD_PROP_COLOR, name) :
|
|
|
|
CustomData_get_render_layer(cd_vdata, CD_PROP_COLOR);
|
|
|
|
}
|
|
|
|
if (layer != -1) {
|
|
|
|
cd_used.sculpt_vcol |= (1 << layer);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
case CD_MCOL: {
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
/* Vertex Color Data */
|
2019-04-17 06:17:24 +02:00
|
|
|
if (layer == -1) {
|
|
|
|
layer = (name[0] != '\0') ? CustomData_get_named_layer(cd_ldata, CD_MLOOPCOL, name) :
|
2019-07-08 13:35:55 +02:00
|
|
|
CustomData_get_render_layer(cd_ldata, CD_MLOOPCOL);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
if (layer != -1) {
|
|
|
|
cd_used.vcol |= (1 << layer);
|
|
|
|
}
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CD_ORCO: {
|
|
|
|
cd_used.orco = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return cd_used;
|
2017-06-28 13:38:24 +10:00
|
|
|
}
|
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
/** \} */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
/** \name Vertex Group Selection
|
|
|
|
* \{ */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
/** Reset the selection structure, deallocating heap memory as appropriate. */
|
|
|
|
static void drw_mesh_weight_state_clear(struct DRW_MeshWeightState *wstate)
|
|
|
|
{
|
|
|
|
MEM_SAFE_FREE(wstate->defgroup_sel);
|
2018-10-07 18:25:51 +03:00
|
|
|
MEM_SAFE_FREE(wstate->defgroup_locked);
|
|
|
|
MEM_SAFE_FREE(wstate->defgroup_unlocked);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
memset(wstate, 0, sizeof(*wstate));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
wstate->defgroup_active = -1;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
/** Copy selection data from one structure to another, including heap memory. */
|
|
|
|
static void drw_mesh_weight_state_copy(struct DRW_MeshWeightState *wstate_dst,
|
|
|
|
const struct DRW_MeshWeightState *wstate_src)
|
|
|
|
{
|
|
|
|
MEM_SAFE_FREE(wstate_dst->defgroup_sel);
|
2018-10-07 18:25:51 +03:00
|
|
|
MEM_SAFE_FREE(wstate_dst->defgroup_locked);
|
|
|
|
MEM_SAFE_FREE(wstate_dst->defgroup_unlocked);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
memcpy(wstate_dst, wstate_src, sizeof(*wstate_dst));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
if (wstate_src->defgroup_sel) {
|
|
|
|
wstate_dst->defgroup_sel = MEM_dupallocN(wstate_src->defgroup_sel);
|
|
|
|
}
|
2018-10-07 18:25:51 +03:00
|
|
|
if (wstate_src->defgroup_locked) {
|
|
|
|
wstate_dst->defgroup_locked = MEM_dupallocN(wstate_src->defgroup_locked);
|
|
|
|
}
|
|
|
|
if (wstate_src->defgroup_unlocked) {
|
|
|
|
wstate_dst->defgroup_unlocked = MEM_dupallocN(wstate_src->defgroup_unlocked);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool drw_mesh_flags_equal(const bool *array1, const bool *array2, int size)
|
|
|
|
{
|
|
|
|
return ((!array1 && !array2) ||
|
|
|
|
(array1 && array2 && memcmp(array1, array2, size * sizeof(bool)) == 0));
|
2019-07-14 16:49:44 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
/** Compare two selection structures. */
|
|
|
|
static bool drw_mesh_weight_state_compare(const struct DRW_MeshWeightState *a,
|
|
|
|
const struct DRW_MeshWeightState *b)
|
|
|
|
{
|
|
|
|
return a->defgroup_active == b->defgroup_active && a->defgroup_len == b->defgroup_len &&
|
|
|
|
a->flags == b->flags && a->alert_mode == b->alert_mode &&
|
|
|
|
a->defgroup_sel_count == b->defgroup_sel_count &&
|
2018-10-07 18:25:51 +03:00
|
|
|
drw_mesh_flags_equal(a->defgroup_sel, b->defgroup_sel, a->defgroup_len) &&
|
|
|
|
drw_mesh_flags_equal(a->defgroup_locked, b->defgroup_locked, a->defgroup_len) &&
|
|
|
|
drw_mesh_flags_equal(a->defgroup_unlocked, b->defgroup_unlocked, a->defgroup_len);
|
2019-07-14 16:49:44 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
static void drw_mesh_weight_state_extract(Object *ob,
|
|
|
|
Mesh *me,
|
|
|
|
const ToolSettings *ts,
|
|
|
|
bool paint_mode,
|
|
|
|
struct DRW_MeshWeightState *wstate)
|
|
|
|
{
|
|
|
|
/* Extract complete vertex weight group selection state and mode flags. */
|
|
|
|
memset(wstate, 0, sizeof(*wstate));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
wstate->defgroup_active = ob->actdef - 1;
|
|
|
|
wstate->defgroup_len = BLI_listbase_count(&ob->defbase);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
wstate->alert_mode = ts->weightuser;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
if (paint_mode && ts->multipaint) {
|
2020-05-28 16:42:31 +10:00
|
|
|
/* Multi-paint needs to know all selected bones, not just the active group.
|
2019-07-14 16:49:44 +02:00
|
|
|
* This is actually a relatively expensive operation, but caching would be difficult. */
|
|
|
|
wstate->defgroup_sel = BKE_object_defgroup_selected_get(
|
|
|
|
ob, wstate->defgroup_len, &wstate->defgroup_sel_count);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
if (wstate->defgroup_sel_count > 1) {
|
|
|
|
wstate->flags |= DRW_MESH_WEIGHT_STATE_MULTIPAINT |
|
|
|
|
(ts->auto_normalize ? DRW_MESH_WEIGHT_STATE_AUTO_NORMALIZE : 0);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
if (me->editflag & ME_EDIT_MIRROR_X) {
|
|
|
|
BKE_object_defgroup_mirror_selection(ob,
|
|
|
|
wstate->defgroup_len,
|
|
|
|
wstate->defgroup_sel,
|
|
|
|
wstate->defgroup_sel,
|
|
|
|
&wstate->defgroup_sel_count);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
}
|
2019-07-14 16:49:44 +02:00
|
|
|
/* With only one selected bone Multipaint reverts to regular mode. */
|
|
|
|
else {
|
|
|
|
wstate->defgroup_sel_count = 0;
|
|
|
|
MEM_SAFE_FREE(wstate->defgroup_sel);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
}
|
2018-10-07 18:25:51 +03:00
|
|
|
|
|
|
|
if (paint_mode && ts->wpaint_lock_relative) {
|
|
|
|
/* Set of locked vertex groups for the lock relative mode. */
|
|
|
|
wstate->defgroup_locked = BKE_object_defgroup_lock_flags_get(ob, wstate->defgroup_len);
|
|
|
|
wstate->defgroup_unlocked = BKE_object_defgroup_validmap_get(ob, wstate->defgroup_len);
|
|
|
|
|
|
|
|
/* Check that a deform group is active, and none of selected groups are locked. */
|
|
|
|
if (BKE_object_defgroup_check_lock_relative(
|
|
|
|
wstate->defgroup_locked, wstate->defgroup_unlocked, wstate->defgroup_active) &&
|
|
|
|
BKE_object_defgroup_check_lock_relative_multi(wstate->defgroup_len,
|
|
|
|
wstate->defgroup_locked,
|
|
|
|
wstate->defgroup_sel,
|
|
|
|
wstate->defgroup_sel_count)) {
|
|
|
|
wstate->flags |= DRW_MESH_WEIGHT_STATE_LOCK_RELATIVE;
|
|
|
|
|
|
|
|
/* Compute the set of locked and unlocked deform vertex groups. */
|
|
|
|
BKE_object_defgroup_split_locked_validmap(wstate->defgroup_len,
|
|
|
|
wstate->defgroup_locked,
|
|
|
|
wstate->defgroup_unlocked,
|
|
|
|
wstate->defgroup_locked, /* out */
|
|
|
|
wstate->defgroup_unlocked);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
MEM_SAFE_FREE(wstate->defgroup_unlocked);
|
|
|
|
MEM_SAFE_FREE(wstate->defgroup_locked);
|
|
|
|
}
|
|
|
|
}
|
2019-07-14 16:49:44 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
/** \} */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
/** \name Mesh GPUBatch Cache
|
|
|
|
* \{ */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
BLI_INLINE void mesh_batch_cache_add_request(MeshBatchCache *cache, DRWBatchFlag new_flag)
|
|
|
|
{
|
|
|
|
atomic_fetch_and_or_uint32((uint32_t *)(&cache->batch_requested), *(uint32_t *)&new_flag);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
/* GPUBatch cache management. */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
static bool mesh_batch_cache_valid(Mesh *me)
|
|
|
|
{
|
|
|
|
MeshBatchCache *cache = me->runtime.batch_cache;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
if (cache == NULL) {
|
|
|
|
return false;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
if (cache->is_editmode != (me->edit_mesh != NULL)) {
|
|
|
|
return false;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
if (cache->is_dirty) {
|
|
|
|
return false;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
if (cache->mat_len != mesh_render_mat_len_get(me)) {
|
|
|
|
return false;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
return true;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
static void mesh_batch_cache_init(Mesh *me)
|
|
|
|
{
|
|
|
|
MeshBatchCache *cache = me->runtime.batch_cache;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
if (!cache) {
|
|
|
|
cache = me->runtime.batch_cache = MEM_callocN(sizeof(*cache), __func__);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
memset(cache, 0, sizeof(*cache));
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
cache->is_editmode = me->edit_mesh != NULL;
|
2017-05-25 02:31:39 +10:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
if (cache->is_editmode == false) {
|
|
|
|
// cache->edge_len = mesh_render_edges_len_get(me);
|
|
|
|
// cache->tri_len = mesh_render_looptri_len_get(me);
|
|
|
|
// cache->poly_len = mesh_render_polys_len_get(me);
|
|
|
|
// cache->vert_len = mesh_render_verts_len_get(me);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
cache->mat_len = mesh_render_mat_len_get(me);
|
|
|
|
cache->surface_per_mat = MEM_callocN(sizeof(*cache->surface_per_mat) * cache->mat_len, __func__);
|
2017-05-01 17:58:15 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
cache->is_dirty = false;
|
|
|
|
cache->batch_ready = 0;
|
|
|
|
cache->batch_requested = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
drw_mesh_weight_state_clear(&cache->weight_state);
|
2018-05-19 13:31:44 +02:00
|
|
|
}
|
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
void DRW_mesh_batch_cache_validate(Mesh *me)
|
2018-12-18 16:34:32 +01:00
|
|
|
{
|
2019-07-14 16:49:44 +02:00
|
|
|
if (!mesh_batch_cache_valid(me)) {
|
|
|
|
mesh_batch_cache_clear(me);
|
|
|
|
mesh_batch_cache_init(me);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2018-12-18 16:34:32 +01:00
|
|
|
}
|
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
static MeshBatchCache *mesh_batch_cache_get(Mesh *me)
|
2018-12-17 23:00:05 +01:00
|
|
|
{
|
2019-07-14 16:49:44 +02:00
|
|
|
return me->runtime.batch_cache;
|
2018-12-17 23:00:05 +01:00
|
|
|
}
|
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
static void mesh_batch_cache_check_vertex_group(MeshBatchCache *cache,
|
|
|
|
const struct DRW_MeshWeightState *wstate)
|
2019-02-12 23:22:36 +01:00
|
|
|
{
|
2019-07-14 16:49:44 +02:00
|
|
|
if (!drw_mesh_weight_state_compare(&cache->weight_state, wstate)) {
|
2020-03-27 11:16:17 +11:00
|
|
|
FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) {
|
2019-07-14 16:49:44 +02:00
|
|
|
GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.weights);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-07-14 16:49:44 +02:00
|
|
|
GPU_BATCH_CLEAR_SAFE(cache->batch.surface_weights);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
cache->batch_ready &= ~MBC_SURFACE_WEIGHTS;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
drw_mesh_weight_state_clear(&cache->weight_state);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-07-01 12:43:07 +02:00
|
|
|
}
|
|
|
|
|
2019-10-09 18:11:10 +02:00
|
|
|
static void mesh_batch_cache_discard_shaded_batches(MeshBatchCache *cache)
|
|
|
|
{
|
|
|
|
if (cache->surface_per_mat) {
|
|
|
|
for (int i = 0; i < cache->mat_len; i++) {
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->surface_per_mat[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cache->batch_ready &= ~MBC_SURF_PER_MAT;
|
|
|
|
}
|
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
static void mesh_batch_cache_discard_shaded_tri(MeshBatchCache *cache)
|
2019-07-01 12:43:07 +02:00
|
|
|
{
|
2020-03-27 11:16:17 +11:00
|
|
|
FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) {
|
2019-07-14 16:49:44 +02:00
|
|
|
GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.pos_nor);
|
2019-08-14 22:43:44 +02:00
|
|
|
GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.uv);
|
|
|
|
GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.tan);
|
2019-07-14 16:49:44 +02:00
|
|
|
GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.vcol);
|
|
|
|
GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.orco);
|
2019-07-01 12:43:07 +02:00
|
|
|
}
|
2019-10-09 18:11:10 +02:00
|
|
|
mesh_batch_cache_discard_shaded_batches(cache);
|
|
|
|
mesh_cd_layers_type_clear(&cache->cd_used);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
MEM_SAFE_FREE(cache->surface_per_mat);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
cache->mat_len = 0;
|
2018-12-18 21:45:46 +01:00
|
|
|
}
|
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
static void mesh_batch_cache_discard_uvedit(MeshBatchCache *cache)
|
2017-04-25 18:46:59 +02:00
|
|
|
{
|
2020-03-27 11:16:17 +11:00
|
|
|
FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) {
|
2019-07-14 16:49:44 +02:00
|
|
|
GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.stretch_angle);
|
|
|
|
GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.stretch_area);
|
2019-08-14 22:43:44 +02:00
|
|
|
GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.uv);
|
2019-07-14 16:49:44 +02:00
|
|
|
GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.edituv_data);
|
|
|
|
GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.fdots_uv);
|
|
|
|
GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.fdots_edituv_data);
|
|
|
|
GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.edituv_tris);
|
|
|
|
GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.edituv_lines);
|
|
|
|
GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.edituv_points);
|
|
|
|
GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.edituv_fdots);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-09-03 13:42:11 +02:00
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces_stretch_area);
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces_stretch_angle);
|
2019-07-14 16:49:44 +02:00
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces);
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_edges);
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_verts);
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_fdots);
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.wire_loops_uvs);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-09-03 13:42:11 +02:00
|
|
|
cache->tot_area = 0.0f;
|
|
|
|
cache->tot_uv_area = 0.0f;
|
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
cache->batch_ready &= ~MBC_EDITUV;
|
2019-10-07 19:20:52 +02:00
|
|
|
|
2019-10-09 18:11:10 +02:00
|
|
|
/* We discarded the vbo.uv so we need to reset the cd_used flag. */
|
|
|
|
cache->cd_used.uv = 0;
|
|
|
|
cache->cd_used.edit_uv = 0;
|
|
|
|
|
|
|
|
/* Discard other batches that uses vbo.uv */
|
|
|
|
mesh_batch_cache_discard_shaded_batches(cache);
|
|
|
|
|
2019-10-07 19:20:52 +02:00
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.surface);
|
2019-10-09 18:11:10 +02:00
|
|
|
cache->batch_ready &= ~MBC_SURFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void mesh_batch_cache_discard_uvedit_select(MeshBatchCache *cache)
|
|
|
|
{
|
2020-03-27 11:16:17 +11:00
|
|
|
FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) {
|
2019-10-09 18:11:10 +02:00
|
|
|
GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.edituv_data);
|
|
|
|
GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.fdots_edituv_data);
|
|
|
|
GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.edituv_tris);
|
|
|
|
GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.edituv_lines);
|
|
|
|
GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.edituv_points);
|
|
|
|
GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.edituv_fdots);
|
|
|
|
}
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces_stretch_area);
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces_stretch_angle);
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces);
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_edges);
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_verts);
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_fdots);
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.wire_loops_uvs);
|
|
|
|
cache->batch_ready &= ~MBC_EDITUV;
|
2017-04-25 18:46:59 +02:00
|
|
|
}
|
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode)
|
2018-12-22 23:57:12 +01:00
|
|
|
{
|
2019-07-14 16:49:44 +02:00
|
|
|
MeshBatchCache *cache = me->runtime.batch_cache;
|
|
|
|
if (cache == NULL) {
|
|
|
|
return;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-07-14 16:49:44 +02:00
|
|
|
switch (mode) {
|
|
|
|
case BKE_MESH_BATCH_DIRTY_SELECT:
|
2020-03-27 11:16:17 +11:00
|
|
|
FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) {
|
2019-07-14 16:49:44 +02:00
|
|
|
GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.edit_data);
|
|
|
|
GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.fdots_nor);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-07-14 16:49:44 +02:00
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edit_triangles);
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edit_vertices);
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edit_edges);
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edit_fdots);
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edit_selection_verts);
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edit_selection_edges);
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edit_selection_faces);
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edit_selection_fdots);
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edit_mesh_analysis);
|
|
|
|
cache->batch_ready &= ~(MBC_EDIT_TRIANGLES | MBC_EDIT_VERTICES | MBC_EDIT_EDGES |
|
|
|
|
MBC_EDIT_FACEDOTS | MBC_EDIT_SELECTION_FACEDOTS |
|
|
|
|
MBC_EDIT_SELECTION_FACES | MBC_EDIT_SELECTION_EDGES |
|
|
|
|
MBC_EDIT_SELECTION_VERTS | MBC_EDIT_MESH_ANALYSIS);
|
2019-10-09 18:11:10 +02:00
|
|
|
/* Because visible UVs depends on edit mode selection, discard topology. */
|
|
|
|
mesh_batch_cache_discard_uvedit_select(cache);
|
2019-07-14 16:49:44 +02:00
|
|
|
break;
|
|
|
|
case BKE_MESH_BATCH_DIRTY_SELECT_PAINT:
|
2020-04-03 16:59:34 +11:00
|
|
|
/* Paint mode selection flag is packed inside the nor attribute.
|
2019-07-14 16:49:44 +02:00
|
|
|
* Note that it can be slow if auto smooth is enabled. (see T63946) */
|
2020-03-27 11:16:17 +11:00
|
|
|
FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) {
|
2019-07-14 16:49:44 +02:00
|
|
|
GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.lines_paint_mask);
|
|
|
|
GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.pos_nor);
|
2019-08-26 18:43:46 +02:00
|
|
|
GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.lnor);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-07-14 16:49:44 +02:00
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.surface);
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.wire_loops);
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.wire_edges);
|
|
|
|
if (cache->surface_per_mat) {
|
|
|
|
for (int i = 0; i < cache->mat_len; i++) {
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->surface_per_mat[i]);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
}
|
2019-07-14 16:49:44 +02:00
|
|
|
cache->batch_ready &= ~(MBC_SURFACE | MBC_WIRE_EDGES | MBC_WIRE_LOOPS | MBC_SURF_PER_MAT);
|
|
|
|
break;
|
|
|
|
case BKE_MESH_BATCH_DIRTY_ALL:
|
|
|
|
cache->is_dirty = true;
|
|
|
|
break;
|
|
|
|
case BKE_MESH_BATCH_DIRTY_SHADING:
|
|
|
|
mesh_batch_cache_discard_shaded_tri(cache);
|
|
|
|
mesh_batch_cache_discard_uvedit(cache);
|
|
|
|
break;
|
|
|
|
case BKE_MESH_BATCH_DIRTY_UVEDIT_ALL:
|
|
|
|
mesh_batch_cache_discard_uvedit(cache);
|
|
|
|
break;
|
|
|
|
case BKE_MESH_BATCH_DIRTY_UVEDIT_SELECT:
|
2020-03-27 11:16:17 +11:00
|
|
|
FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) {
|
2019-07-14 16:49:44 +02:00
|
|
|
GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.edituv_data);
|
|
|
|
GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.fdots_edituv_data);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-09-03 13:42:11 +02:00
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces_stretch_area);
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces_stretch_angle);
|
2019-07-14 16:49:44 +02:00
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces);
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_edges);
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_verts);
|
|
|
|
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_fdots);
|
|
|
|
cache->batch_ready &= ~MBC_EDITUV;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
BLI_assert(0);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2018-12-22 23:57:12 +01:00
|
|
|
}
|
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
static void mesh_batch_cache_clear(Mesh *me)
|
2018-12-22 23:57:12 +01:00
|
|
|
{
|
2019-07-14 16:49:44 +02:00
|
|
|
MeshBatchCache *cache = me->runtime.batch_cache;
|
|
|
|
if (!cache) {
|
|
|
|
return;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2020-03-27 11:16:17 +11:00
|
|
|
FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) {
|
2019-07-14 16:49:44 +02:00
|
|
|
GPUVertBuf **vbos = (GPUVertBuf **)&mbufcache->vbo;
|
|
|
|
GPUIndexBuf **ibos = (GPUIndexBuf **)&mbufcache->ibo;
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int i = 0; i < sizeof(mbufcache->vbo) / sizeof(void *); i++) {
|
2019-07-14 16:49:44 +02:00
|
|
|
GPU_VERTBUF_DISCARD_SAFE(vbos[i]);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int i = 0; i < sizeof(mbufcache->ibo) / sizeof(void *); i++) {
|
2019-07-14 16:49:44 +02:00
|
|
|
GPU_INDEXBUF_DISCARD_SAFE(ibos[i]);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
}
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); i++) {
|
2019-07-14 16:49:44 +02:00
|
|
|
GPUBatch **batch = (GPUBatch **)&cache->batch;
|
|
|
|
GPU_BATCH_DISCARD_SAFE(batch[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
mesh_batch_cache_discard_shaded_tri(cache);
|
|
|
|
|
|
|
|
mesh_batch_cache_discard_uvedit(cache);
|
|
|
|
|
|
|
|
cache->batch_ready = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
drw_mesh_weight_state_clear(&cache->weight_state);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DRW_mesh_batch_cache_free(Mesh *me)
|
|
|
|
{
|
|
|
|
mesh_batch_cache_clear(me);
|
|
|
|
MEM_SAFE_FREE(me->runtime.batch_cache);
|
2018-12-22 23:57:12 +01:00
|
|
|
}
|
|
|
|
|
2017-05-05 05:07:52 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
/** \name Public API
|
|
|
|
* \{ */
|
|
|
|
|
2018-12-18 21:03:47 +01:00
|
|
|
static void texpaint_request_active_uv(MeshBatchCache *cache, Mesh *me)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
DRW_MeshCDMask cd_needed;
|
|
|
|
mesh_cd_layers_type_clear(&cd_needed);
|
|
|
|
mesh_cd_calc_active_uv_layer(me, &cd_needed);
|
2019-04-06 01:55:21 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
BLI_assert(cd_needed.uv != 0 &&
|
|
|
|
"No uv layer available in texpaint, but batches requested anyway!");
|
2019-04-06 01:55:21 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
mesh_cd_calc_active_mask_uv_layer(me, &cd_needed);
|
|
|
|
mesh_cd_layers_type_merge(&cache->cd_needed, cd_needed);
|
2018-12-18 21:03:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void texpaint_request_active_vcol(MeshBatchCache *cache, Mesh *me)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
DRW_MeshCDMask cd_needed;
|
|
|
|
mesh_cd_layers_type_clear(&cd_needed);
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
mesh_cd_calc_active_mloopcol_layer(me, &cd_needed);
|
2019-04-06 01:55:21 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
BLI_assert(cd_needed.vcol != 0 &&
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
"No MLOOPCOL layer available in vertpaint, but batches requested anyway!");
|
|
|
|
|
|
|
|
mesh_cd_layers_type_merge(&cache->cd_needed, cd_needed);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sculpt_request_active_vcol(MeshBatchCache *cache, Mesh *me)
|
|
|
|
{
|
|
|
|
DRW_MeshCDMask cd_needed;
|
|
|
|
mesh_cd_layers_type_clear(&cd_needed);
|
|
|
|
mesh_cd_calc_active_vcol_layer(me, &cd_needed);
|
|
|
|
|
|
|
|
BLI_assert(cd_needed.sculpt_vcol != 0 &&
|
|
|
|
"No MPropCol layer available in Sculpt, but batches requested anyway!");
|
2019-04-06 01:55:21 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
mesh_cd_layers_type_merge(&cache->cd_needed, cd_needed);
|
2018-12-18 21:03:47 +01:00
|
|
|
}
|
|
|
|
|
2018-12-17 21:24:43 +01:00
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_all_verts(Mesh *me)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2019-05-08 00:12:24 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_ALL_VERTS);
|
2019-04-17 06:17:24 +02:00
|
|
|
return DRW_batch_request(&cache->batch.all_verts);
|
2018-12-17 21:24:43 +01:00
|
|
|
}
|
|
|
|
|
2018-07-18 00:12:21 +02:00
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_all_edges(Mesh *me)
|
2017-01-25 09:16:29 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2019-05-08 00:12:24 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_ALL_EDGES);
|
2019-04-17 06:17:24 +02:00
|
|
|
return DRW_batch_request(&cache->batch.all_edges);
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
2018-12-18 17:10:38 +01:00
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_surface(Mesh *me)
|
2017-02-15 13:32:35 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2019-05-08 00:12:24 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_SURFACE);
|
2019-04-17 06:17:24 +02:00
|
|
|
return DRW_batch_request(&cache->batch.surface);
|
2017-03-09 01:29:58 +01:00
|
|
|
}
|
2017-02-16 16:19:48 +01:00
|
|
|
|
2018-12-18 17:10:38 +01:00
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_loose_edges(Mesh *me)
|
2018-06-01 11:35:51 +02:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2019-05-08 00:12:24 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_LOOSE_EDGES);
|
2019-06-18 22:25:37 +02:00
|
|
|
if (cache->no_loose_wire) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return DRW_batch_request(&cache->batch.loose_edges);
|
|
|
|
}
|
2018-06-01 11:35:51 +02:00
|
|
|
}
|
|
|
|
|
2018-12-18 17:10:38 +01:00
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_surface_weights(Mesh *me)
|
2017-05-03 18:55:40 +02:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2019-05-10 15:03:18 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_SURFACE_WEIGHTS);
|
2019-04-17 06:17:24 +02:00
|
|
|
return DRW_batch_request(&cache->batch.surface_weights);
|
2017-05-03 18:55:40 +02:00
|
|
|
}
|
|
|
|
|
2018-07-18 00:12:21 +02:00
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_edge_detection(Mesh *me, bool *r_is_manifold)
|
2018-05-19 13:31:44 +02:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2019-05-08 00:12:24 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_EDGE_DETECTION);
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Even if is_manifold is not correct (not updated),
|
|
|
|
* the default (not manifold) is just the worst case. */
|
|
|
|
if (r_is_manifold) {
|
|
|
|
*r_is_manifold = cache->is_manifold;
|
|
|
|
}
|
|
|
|
return DRW_batch_request(&cache->batch.edge_detection);
|
2018-05-19 13:31:44 +02:00
|
|
|
}
|
|
|
|
|
2018-12-07 05:03:01 +01:00
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_wireframes_face(Mesh *me)
|
2018-05-31 18:43:19 +02:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2019-05-08 00:12:24 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_WIRE_EDGES);
|
2019-04-17 06:17:24 +02:00
|
|
|
return DRW_batch_request(&cache->batch.wire_edges);
|
2018-05-31 18:43:19 +02:00
|
|
|
}
|
|
|
|
|
2019-04-18 08:00:59 +02:00
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_edit_mesh_analysis(Mesh *me)
|
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2019-05-08 00:12:24 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_EDIT_MESH_ANALYSIS);
|
2019-04-18 08:00:59 +02:00
|
|
|
return DRW_batch_request(&cache->batch.edit_mesh_analysis);
|
|
|
|
}
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(Mesh *me,
|
|
|
|
struct GPUMaterial **gpumat_array,
|
2020-01-17 16:05:19 +01:00
|
|
|
uint gpumat_array_len)
|
2018-12-18 21:03:47 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
DRW_MeshCDMask cd_needed = mesh_cd_calc_used_gpu_layers(me, gpumat_array, gpumat_array_len);
|
|
|
|
|
|
|
|
BLI_assert(gpumat_array_len == cache->mat_len);
|
|
|
|
|
2019-04-18 17:25:04 +02:00
|
|
|
mesh_cd_layers_type_merge(&cache->cd_needed, cd_needed);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-08 00:12:24 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_SURF_PER_MAT);
|
|
|
|
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int i = 0; i < cache->mat_len; i++) {
|
2019-07-14 16:49:44 +02:00
|
|
|
DRW_batch_request(&cache->surface_per_mat[i]);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-07-14 16:49:44 +02:00
|
|
|
return cache->surface_per_mat;
|
2018-12-18 21:03:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
GPUBatch **DRW_mesh_batch_cache_get_surface_texpaint(Mesh *me)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2019-05-08 00:12:24 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_SURF_PER_MAT);
|
2019-04-17 06:17:24 +02:00
|
|
|
texpaint_request_active_uv(cache, me);
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int i = 0; i < cache->mat_len; i++) {
|
2019-07-14 16:49:44 +02:00
|
|
|
DRW_batch_request(&cache->surface_per_mat[i]);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-07-14 16:49:44 +02:00
|
|
|
return cache->surface_per_mat;
|
2018-12-18 21:03:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_surface_texpaint_single(Mesh *me)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
texpaint_request_active_uv(cache, me);
|
2019-05-08 00:12:24 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_SURFACE);
|
2019-04-17 06:17:24 +02:00
|
|
|
return DRW_batch_request(&cache->batch.surface);
|
2018-12-18 21:03:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_surface_vertpaint(Mesh *me)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
texpaint_request_active_vcol(cache, me);
|
2019-05-08 00:12:24 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_SURFACE);
|
2019-04-17 06:17:24 +02:00
|
|
|
return DRW_batch_request(&cache->batch.surface);
|
2018-12-18 21:03:47 +01:00
|
|
|
}
|
|
|
|
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_surface_sculpt(Mesh *me)
|
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
sculpt_request_active_vcol(cache, me);
|
|
|
|
mesh_batch_cache_add_request(cache, MBC_SURFACE);
|
|
|
|
return DRW_batch_request(&cache->batch.surface);
|
|
|
|
}
|
|
|
|
|
2020-01-28 16:39:33 +01:00
|
|
|
int DRW_mesh_material_count_get(Mesh *me)
|
|
|
|
{
|
|
|
|
return mesh_render_mat_len_get(me);
|
|
|
|
}
|
|
|
|
|
2018-12-18 21:03:47 +01:00
|
|
|
/** \} */
|
|
|
|
|
2019-02-04 01:13:51 +01:00
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
/** \name Edit Mode API
|
|
|
|
* \{ */
|
2020-06-19 17:02:55 +02:00
|
|
|
|
|
|
|
GPUVertBuf *DRW_mesh_batch_cache_pos_vertbuf_get(Mesh *me)
|
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
/* Request surface to trigger the vbo filling. Otherwise it may do nothing. */
|
|
|
|
mesh_batch_cache_add_request(cache, MBC_SURFACE);
|
|
|
|
DRW_batch_request(&cache->batch.surface);
|
|
|
|
|
|
|
|
DRW_vbo_request(NULL, &cache->final.vbo.pos_nor);
|
|
|
|
return cache->final.vbo.pos_nor;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
/** \name Edit Mode API
|
|
|
|
* \{ */
|
2019-02-04 01:13:51 +01:00
|
|
|
|
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_edit_triangles(Mesh *me)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2019-05-08 00:12:24 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_EDIT_TRIANGLES);
|
2019-04-17 06:17:24 +02:00
|
|
|
return DRW_batch_request(&cache->batch.edit_triangles);
|
2019-02-04 01:13:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_edit_edges(Mesh *me)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2019-05-08 00:12:24 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_EDIT_EDGES);
|
2019-04-17 06:17:24 +02:00
|
|
|
return DRW_batch_request(&cache->batch.edit_edges);
|
2019-02-04 01:13:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_edit_vertices(Mesh *me)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2019-05-08 00:12:24 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_EDIT_VERTICES);
|
2019-04-17 06:17:24 +02:00
|
|
|
return DRW_batch_request(&cache->batch.edit_vertices);
|
2019-02-04 01:13:51 +01:00
|
|
|
}
|
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_edit_vnors(Mesh *me)
|
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
mesh_batch_cache_add_request(cache, MBC_EDIT_VNOR);
|
|
|
|
return DRW_batch_request(&cache->batch.edit_vnor);
|
|
|
|
}
|
|
|
|
|
2019-02-04 01:13:51 +01:00
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_edit_lnors(Mesh *me)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2019-05-08 00:12:24 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_EDIT_LNOR);
|
2019-04-17 06:17:24 +02:00
|
|
|
return DRW_batch_request(&cache->batch.edit_lnor);
|
2019-02-04 01:13:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_edit_facedots(Mesh *me)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2019-05-08 00:12:24 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_EDIT_FACEDOTS);
|
2019-07-14 16:49:44 +02:00
|
|
|
return DRW_batch_request(&cache->batch.edit_fdots);
|
2019-02-04 01:13:51 +01:00
|
|
|
}
|
|
|
|
|
2019-10-15 01:49:53 +02:00
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_edit_skin_roots(Mesh *me)
|
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
mesh_batch_cache_add_request(cache, MBC_SKIN_ROOTS);
|
|
|
|
return DRW_batch_request(&cache->batch.edit_skin_roots);
|
|
|
|
}
|
|
|
|
|
2019-02-04 01:13:51 +01:00
|
|
|
/** \} */
|
|
|
|
|
2018-12-18 21:03:47 +01:00
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
/** \name Edit Mode selection API
|
|
|
|
* \{ */
|
|
|
|
|
2018-12-22 23:57:12 +01:00
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_triangles_with_select_id(Mesh *me)
|
2018-12-18 21:03:47 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2019-05-08 00:12:24 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_EDIT_SELECTION_FACES);
|
2019-04-17 06:17:24 +02:00
|
|
|
return DRW_batch_request(&cache->batch.edit_selection_faces);
|
2018-12-18 21:03:47 +01:00
|
|
|
}
|
|
|
|
|
2018-12-22 23:57:12 +01:00
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_facedots_with_select_id(Mesh *me)
|
2017-08-17 01:38:07 +10:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2019-05-08 00:12:24 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_EDIT_SELECTION_FACEDOTS);
|
2019-07-14 16:49:44 +02:00
|
|
|
return DRW_batch_request(&cache->batch.edit_selection_fdots);
|
2017-08-17 01:38:07 +10:00
|
|
|
}
|
|
|
|
|
2018-12-22 23:57:12 +01:00
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_edges_with_select_id(Mesh *me)
|
2017-08-17 01:38:07 +10:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2019-05-08 00:12:24 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_EDIT_SELECTION_EDGES);
|
2019-04-17 06:17:24 +02:00
|
|
|
return DRW_batch_request(&cache->batch.edit_selection_edges);
|
2017-08-17 01:38:07 +10:00
|
|
|
}
|
|
|
|
|
2018-12-22 23:57:12 +01:00
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_verts_with_select_id(Mesh *me)
|
2017-08-17 01:38:07 +10:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2019-05-08 00:12:24 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_EDIT_SELECTION_VERTS);
|
2019-04-17 06:17:24 +02:00
|
|
|
return DRW_batch_request(&cache->batch.edit_selection_verts);
|
2017-03-02 01:07:03 +01:00
|
|
|
}
|
|
|
|
|
2018-12-18 21:03:47 +01:00
|
|
|
/** \} */
|
2017-05-22 23:31:46 +10:00
|
|
|
|
2018-12-18 21:03:47 +01:00
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
/** \name UV Image editor API
|
|
|
|
* \{ */
|
2018-12-18 02:18:55 +01:00
|
|
|
|
2019-10-08 18:35:57 +02:00
|
|
|
static void edituv_request_active_uv(MeshBatchCache *cache, Mesh *me)
|
|
|
|
{
|
|
|
|
DRW_MeshCDMask cd_needed;
|
|
|
|
mesh_cd_layers_type_clear(&cd_needed);
|
2020-01-06 14:39:15 +01:00
|
|
|
mesh_cd_calc_active_uv_layer(me, &cd_needed);
|
2019-10-08 18:35:57 +02:00
|
|
|
mesh_cd_calc_edit_uv_layer(me, &cd_needed);
|
|
|
|
|
2019-10-10 20:16:14 +02:00
|
|
|
BLI_assert(cd_needed.edit_uv != 0 &&
|
2019-10-08 18:35:57 +02:00
|
|
|
"No uv layer available in edituv, but batches requested anyway!");
|
|
|
|
|
|
|
|
mesh_cd_calc_active_mask_uv_layer(me, &cd_needed);
|
|
|
|
mesh_cd_layers_type_merge(&cache->cd_needed, cd_needed);
|
|
|
|
}
|
|
|
|
|
2019-09-03 13:42:11 +02:00
|
|
|
/* Creates the GPUBatch for drawing the UV Stretching Area Overlay.
|
|
|
|
* Optional retrieves the total area or total uv area of the mesh.
|
|
|
|
*
|
|
|
|
* The `cache->tot_area` and cache->tot_uv_area` update are calculation are
|
|
|
|
* only valid after calling `DRW_mesh_batch_cache_create_requested`. */
|
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_stretch_area(Mesh *me,
|
2019-09-27 16:40:18 +02:00
|
|
|
float **tot_area,
|
|
|
|
float **tot_uv_area)
|
2019-01-09 22:56:27 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2019-10-08 18:35:57 +02:00
|
|
|
edituv_request_active_uv(cache, me);
|
2019-09-03 13:42:11 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_EDITUV_FACES_STRETCH_AREA);
|
|
|
|
|
|
|
|
if (tot_area != NULL) {
|
2019-09-27 16:40:18 +02:00
|
|
|
*tot_area = &cache->tot_area;
|
2019-09-03 13:42:11 +02:00
|
|
|
}
|
|
|
|
if (tot_uv_area != NULL) {
|
2019-09-27 16:40:18 +02:00
|
|
|
*tot_uv_area = &cache->tot_uv_area;
|
2019-09-03 13:42:11 +02:00
|
|
|
}
|
|
|
|
return DRW_batch_request(&cache->batch.edituv_faces_stretch_area);
|
2019-01-09 22:56:27 +01:00
|
|
|
}
|
|
|
|
|
2019-09-03 13:42:11 +02:00
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_stretch_angle(Mesh *me)
|
2019-01-09 22:56:27 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2019-10-08 18:35:57 +02:00
|
|
|
edituv_request_active_uv(cache, me);
|
2019-09-03 13:42:11 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_EDITUV_FACES_STRETCH_ANGLE);
|
|
|
|
return DRW_batch_request(&cache->batch.edituv_faces_stretch_angle);
|
2019-01-09 22:56:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_edituv_faces(Mesh *me)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2019-10-08 18:35:57 +02:00
|
|
|
edituv_request_active_uv(cache, me);
|
2019-05-08 00:12:24 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_EDITUV_FACES);
|
2019-04-17 06:17:24 +02:00
|
|
|
return DRW_batch_request(&cache->batch.edituv_faces);
|
2019-01-09 22:56:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_edituv_edges(Mesh *me)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2019-10-08 18:35:57 +02:00
|
|
|
edituv_request_active_uv(cache, me);
|
2019-05-08 00:12:24 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_EDITUV_EDGES);
|
2019-04-17 06:17:24 +02:00
|
|
|
return DRW_batch_request(&cache->batch.edituv_edges);
|
2019-01-09 22:56:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_edituv_verts(Mesh *me)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2019-10-08 18:35:57 +02:00
|
|
|
edituv_request_active_uv(cache, me);
|
2019-05-08 00:12:24 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_EDITUV_VERTS);
|
2019-04-17 06:17:24 +02:00
|
|
|
return DRW_batch_request(&cache->batch.edituv_verts);
|
2019-01-09 22:56:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_edituv_facedots(Mesh *me)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2019-10-08 18:35:57 +02:00
|
|
|
edituv_request_active_uv(cache, me);
|
2019-05-08 00:12:24 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_EDITUV_FACEDOTS);
|
2019-07-14 16:49:44 +02:00
|
|
|
return DRW_batch_request(&cache->batch.edituv_fdots);
|
2019-01-09 22:56:27 +01:00
|
|
|
}
|
|
|
|
|
2019-01-10 22:22:42 +01:00
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_uv_edges(Mesh *me)
|
2018-10-01 14:55:35 +02:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2019-10-08 18:35:57 +02:00
|
|
|
edituv_request_active_uv(cache, me);
|
2019-05-08 00:12:24 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_WIRE_LOOPS_UVS);
|
2019-04-17 06:17:24 +02:00
|
|
|
return DRW_batch_request(&cache->batch.wire_loops_uvs);
|
2018-10-01 14:55:35 +02:00
|
|
|
}
|
|
|
|
|
2018-12-18 17:10:38 +01:00
|
|
|
GPUBatch *DRW_mesh_batch_cache_get_surface_edges(Mesh *me)
|
2017-05-03 18:55:40 +02:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2019-07-14 16:49:44 +02:00
|
|
|
texpaint_request_active_uv(cache, me);
|
2019-05-08 00:12:24 +02:00
|
|
|
mesh_batch_cache_add_request(cache, MBC_WIRE_LOOPS);
|
2019-04-17 06:17:24 +02:00
|
|
|
return DRW_batch_request(&cache->batch.wire_loops);
|
2017-05-03 18:55:40 +02:00
|
|
|
}
|
|
|
|
|
2017-05-05 05:07:52 +10:00
|
|
|
/** \} */
|
2018-12-08 20:10:20 +01:00
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
/** \name Grouped batch generation
|
|
|
|
* \{ */
|
|
|
|
|
2019-04-19 02:22:22 +02:00
|
|
|
/* Thread safety need to be assured by caller. Don't call this during drawing.
|
|
|
|
* Note: For now this only free the shading batches / vbo if any cd layers is
|
|
|
|
* not needed anymore. */
|
2019-04-19 18:52:38 +02:00
|
|
|
void DRW_mesh_batch_cache_free_old(Mesh *me, int ctime)
|
2019-04-19 02:22:22 +02:00
|
|
|
{
|
|
|
|
MeshBatchCache *cache = me->runtime.batch_cache;
|
|
|
|
|
2019-04-22 12:20:14 +10:00
|
|
|
if (cache == NULL) {
|
2019-04-19 02:22:22 +02:00
|
|
|
return;
|
2019-04-22 12:20:14 +10:00
|
|
|
}
|
2019-04-19 02:22:22 +02:00
|
|
|
|
2019-04-19 18:52:38 +02:00
|
|
|
if (mesh_cd_layers_type_equal(cache->cd_used_over_time, cache->cd_used)) {
|
|
|
|
cache->lastmatch = ctime;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ctime - cache->lastmatch > U.vbotimeout) {
|
2019-04-19 02:22:22 +02:00
|
|
|
mesh_batch_cache_discard_shaded_tri(cache);
|
|
|
|
}
|
2019-04-19 18:52:38 +02:00
|
|
|
|
2019-04-19 02:22:22 +02:00
|
|
|
mesh_cd_layers_type_clear(&cache->cd_used_over_time);
|
|
|
|
}
|
|
|
|
|
2018-12-14 15:23:13 +01:00
|
|
|
/* Can be called for any surface type. Mesh *me is the final mesh. */
|
2020-06-02 15:07:17 +02:00
|
|
|
void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
|
|
|
|
Object *ob,
|
|
|
|
Mesh *me,
|
|
|
|
const Scene *scene,
|
|
|
|
const bool is_paint_mode,
|
|
|
|
const bool use_hide)
|
|
|
|
{
|
|
|
|
BLI_assert(task_graph);
|
2019-08-19 17:02:21 +02:00
|
|
|
GPUIndexBuf **saved_elem_ranges = NULL;
|
2019-08-15 11:39:45 +02:00
|
|
|
const ToolSettings *ts = NULL;
|
|
|
|
if (scene) {
|
|
|
|
ts = scene->toolsettings;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2020-01-13 17:29:31 +01:00
|
|
|
bool cd_uv_update = false;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-08 00:12:24 +02:00
|
|
|
/* Early out */
|
2019-05-11 13:16:57 +02:00
|
|
|
if (cache->batch_requested == 0) {
|
2019-05-08 22:01:34 +02:00
|
|
|
#ifdef DEBUG
|
|
|
|
goto check;
|
2020-02-11 12:01:29 +11:00
|
|
|
#else
|
2019-05-08 00:12:24 +02:00
|
|
|
return;
|
2020-02-11 12:01:29 +11:00
|
|
|
#endif
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
2020-01-08 22:20:45 +11:00
|
|
|
/* Sanity check. */
|
|
|
|
if ((me->edit_mesh != NULL) && (ob->mode & OB_MODE_EDIT)) {
|
|
|
|
BLI_assert(me->edit_mesh->mesh_eval_final != NULL);
|
|
|
|
}
|
|
|
|
|
2020-02-03 08:16:38 +01:00
|
|
|
const bool is_editmode = (me->edit_mesh != NULL) && DRW_object_is_in_edit_mode(ob);
|
2020-01-08 22:20:45 +11:00
|
|
|
|
2019-05-11 13:10:28 +02:00
|
|
|
DRWBatchFlag batch_requested = cache->batch_requested;
|
|
|
|
cache->batch_requested = 0;
|
|
|
|
|
|
|
|
if (batch_requested & MBC_SURFACE_WEIGHTS) {
|
2019-05-08 00:12:24 +02:00
|
|
|
/* Check vertex weights. */
|
2019-05-10 15:03:18 +02:00
|
|
|
if ((cache->batch.surface_weights != NULL) && (ts != NULL)) {
|
2019-05-08 00:12:24 +02:00
|
|
|
struct DRW_MeshWeightState wstate;
|
|
|
|
BLI_assert(ob->type == OB_MESH);
|
|
|
|
drw_mesh_weight_state_extract(ob, me, ts, is_paint_mode, &wstate);
|
|
|
|
mesh_batch_cache_check_vertex_group(cache, &wstate);
|
|
|
|
drw_mesh_weight_state_copy(&cache->weight_state, &wstate);
|
|
|
|
drw_mesh_weight_state_clear(&wstate);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-23 11:02:58 +02:00
|
|
|
/* HACK: if MBC_SURF_PER_MAT is requested and ibo.tris is already available, it won't have it's
|
|
|
|
* index ranges initialized. So discard ibo.tris in order to recreate it.
|
|
|
|
* This needs to happen before saved_elem_ranges is populated. */
|
|
|
|
if ((batch_requested & MBC_SURF_PER_MAT) != 0 && (cache->batch_ready & MBC_SURF_PER_MAT) == 0) {
|
2020-03-27 11:16:17 +11:00
|
|
|
FOREACH_MESH_BUFFER_CACHE (cache, mbuffercache) {
|
2019-09-23 11:02:58 +02:00
|
|
|
GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.tris);
|
|
|
|
}
|
|
|
|
/* Clear all batches that reference ibo.tris. */
|
|
|
|
GPU_BATCH_CLEAR_SAFE(cache->batch.surface);
|
|
|
|
GPU_BATCH_CLEAR_SAFE(cache->batch.surface_weights);
|
|
|
|
GPU_BATCH_CLEAR_SAFE(cache->batch.edit_mesh_analysis);
|
|
|
|
GPU_BATCH_CLEAR_SAFE(cache->batch.edit_triangles);
|
|
|
|
GPU_BATCH_CLEAR_SAFE(cache->batch.edit_lnor);
|
|
|
|
GPU_BATCH_CLEAR_SAFE(cache->batch.edit_selection_faces);
|
2019-09-27 19:45:19 +02:00
|
|
|
for (int i = 0; i < cache->mat_len; i++) {
|
|
|
|
GPU_BATCH_CLEAR_SAFE(cache->surface_per_mat[i]);
|
|
|
|
}
|
2019-09-23 11:02:58 +02:00
|
|
|
|
|
|
|
cache->batch_ready &= ~(MBC_SURFACE | MBC_SURFACE_WEIGHTS | MBC_EDIT_MESH_ANALYSIS |
|
|
|
|
MBC_EDIT_TRIANGLES | MBC_EDIT_LNOR | MBC_EDIT_SELECTION_FACES);
|
|
|
|
}
|
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
if (batch_requested &
|
2019-09-03 13:42:11 +02:00
|
|
|
(MBC_SURFACE | MBC_SURF_PER_MAT | MBC_WIRE_LOOPS_UVS | MBC_EDITUV_FACES_STRETCH_AREA |
|
|
|
|
MBC_EDITUV_FACES_STRETCH_ANGLE | MBC_EDITUV_FACES | MBC_EDITUV_EDGES | MBC_EDITUV_VERTS)) {
|
2019-06-13 20:22:10 +02:00
|
|
|
/* Modifiers will only generate an orco layer if the mesh is deformed. */
|
2019-05-08 00:12:24 +02:00
|
|
|
if (cache->cd_needed.orco != 0) {
|
2019-09-28 00:19:30 +02:00
|
|
|
/* Orco is always extracted from final mesh. */
|
|
|
|
Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me;
|
|
|
|
if (CustomData_get_layer(&me_final->vdata, CD_ORCO) == NULL) {
|
2019-07-14 16:49:44 +02:00
|
|
|
/* Skip orco calculation */
|
2019-05-08 00:12:24 +02:00
|
|
|
cache->cd_needed.orco = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Verify that all surface batches have needed attribute layers.
|
|
|
|
*/
|
|
|
|
/* TODO(fclem): We could be a bit smarter here and only do it per
|
|
|
|
* material. */
|
|
|
|
bool cd_overlap = mesh_cd_layers_type_overlap(cache->cd_used, cache->cd_needed);
|
|
|
|
if (cd_overlap == false) {
|
2020-03-27 11:16:17 +11:00
|
|
|
FOREACH_MESH_BUFFER_CACHE (cache, mbuffercache) {
|
2019-08-14 22:43:44 +02:00
|
|
|
if ((cache->cd_used.uv & cache->cd_needed.uv) != cache->cd_needed.uv) {
|
|
|
|
GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.uv);
|
2020-01-13 17:29:31 +01:00
|
|
|
cd_uv_update = true;
|
2019-08-14 22:43:44 +02:00
|
|
|
}
|
|
|
|
if ((cache->cd_used.tan & cache->cd_needed.tan) != cache->cd_needed.tan ||
|
2019-07-14 16:49:44 +02:00
|
|
|
cache->cd_used.tan_orco != cache->cd_needed.tan_orco) {
|
2019-08-14 22:43:44 +02:00
|
|
|
GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.tan);
|
2019-07-14 16:49:44 +02:00
|
|
|
}
|
|
|
|
if (cache->cd_used.orco != cache->cd_needed.orco) {
|
|
|
|
GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.orco);
|
|
|
|
}
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
if (((cache->cd_used.vcol & cache->cd_needed.vcol) != cache->cd_needed.vcol) ||
|
|
|
|
((cache->cd_used.sculpt_vcol & cache->cd_needed.sculpt_vcol) !=
|
|
|
|
cache->cd_needed.sculpt_vcol)) {
|
2019-07-14 16:49:44 +02:00
|
|
|
GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.vcol);
|
|
|
|
}
|
2019-05-08 00:12:24 +02:00
|
|
|
}
|
2019-08-19 17:02:21 +02:00
|
|
|
/* XXX save element buffer to avoid recreating them.
|
|
|
|
* This is only if the cd_needed changes so it is ok to keep them.*/
|
2019-08-19 18:08:27 +02:00
|
|
|
if (cache->surface_per_mat[0] && cache->surface_per_mat[0]->elem) {
|
2019-08-19 17:02:21 +02:00
|
|
|
saved_elem_ranges = MEM_callocN(sizeof(saved_elem_ranges) * cache->mat_len, __func__);
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int i = 0; i < cache->mat_len; i++) {
|
2019-08-19 17:02:21 +02:00
|
|
|
saved_elem_ranges[i] = cache->surface_per_mat[i]->elem;
|
|
|
|
/* Avoid deletion as the batch is owner. */
|
|
|
|
cache->surface_per_mat[i]->elem = NULL;
|
|
|
|
cache->surface_per_mat[i]->owns_flag &= ~GPU_BATCH_OWNS_INDEX;
|
|
|
|
}
|
|
|
|
}
|
2019-05-08 00:12:24 +02:00
|
|
|
/* We can't discard batches at this point as they have been
|
|
|
|
* referenced for drawing. Just clear them in place. */
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int i = 0; i < cache->mat_len; i++) {
|
2019-07-14 16:49:44 +02:00
|
|
|
GPU_BATCH_CLEAR_SAFE(cache->surface_per_mat[i]);
|
2019-05-08 00:12:24 +02:00
|
|
|
}
|
|
|
|
GPU_BATCH_CLEAR_SAFE(cache->batch.surface);
|
2019-05-08 22:01:34 +02:00
|
|
|
cache->batch_ready &= ~(MBC_SURFACE | MBC_SURF_PER_MAT);
|
2019-05-08 00:12:24 +02:00
|
|
|
|
|
|
|
mesh_cd_layers_type_merge(&cache->cd_used, cache->cd_needed);
|
|
|
|
}
|
|
|
|
mesh_cd_layers_type_merge(&cache->cd_used_over_time, cache->cd_needed);
|
|
|
|
mesh_cd_layers_type_clear(&cache->cd_needed);
|
|
|
|
}
|
|
|
|
|
2019-05-11 13:10:28 +02:00
|
|
|
if (batch_requested & MBC_EDITUV) {
|
2019-05-08 00:12:24 +02:00
|
|
|
/* Discard UV batches if sync_selection changes */
|
2020-01-13 17:29:31 +01:00
|
|
|
const bool is_uvsyncsel = ts && (ts->uv_flag & UV_SYNC_SELECTION);
|
|
|
|
if (cd_uv_update || (cache->is_uvsyncsel != is_uvsyncsel)) {
|
|
|
|
cache->is_uvsyncsel = is_uvsyncsel;
|
2020-03-27 11:16:17 +11:00
|
|
|
FOREACH_MESH_BUFFER_CACHE (cache, mbuffercache) {
|
2020-01-13 17:29:31 +01:00
|
|
|
GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.edituv_data);
|
|
|
|
GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.fdots_uv);
|
|
|
|
GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.edituv_tris);
|
|
|
|
GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.edituv_lines);
|
|
|
|
GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.edituv_points);
|
2019-05-08 00:12:24 +02:00
|
|
|
}
|
2020-01-13 17:29:31 +01:00
|
|
|
/* We only clear the batches as they may already have been
|
|
|
|
* referenced. */
|
|
|
|
GPU_BATCH_CLEAR_SAFE(cache->batch.wire_loops_uvs);
|
|
|
|
GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces_stretch_area);
|
|
|
|
GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces_stretch_angle);
|
|
|
|
GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces);
|
|
|
|
GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_edges);
|
|
|
|
GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_verts);
|
|
|
|
GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_fdots);
|
|
|
|
cache->batch_ready &= ~MBC_EDITUV;
|
2019-05-08 00:12:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Second chance to early out */
|
2019-05-11 13:10:28 +02:00
|
|
|
if ((batch_requested & ~cache->batch_ready) == 0) {
|
2019-05-08 22:01:34 +02:00
|
|
|
#ifdef DEBUG
|
|
|
|
goto check;
|
2020-02-11 12:01:29 +11:00
|
|
|
#else
|
2019-05-08 00:12:24 +02:00
|
|
|
return;
|
2020-02-11 12:01:29 +11:00
|
|
|
#endif
|
2019-04-18 17:25:04 +02:00
|
|
|
}
|
|
|
|
|
2019-05-11 13:10:28 +02:00
|
|
|
cache->batch_ready |= batch_requested;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-01-08 22:20:45 +11:00
|
|
|
const bool do_cage = (is_editmode &&
|
2019-07-14 16:49:44 +02:00
|
|
|
(me->edit_mesh->mesh_eval_final != me->edit_mesh->mesh_eval_cage));
|
|
|
|
|
2020-01-08 22:20:45 +11:00
|
|
|
const bool do_uvcage = is_editmode && !me->edit_mesh->mesh_eval_final->runtime.is_original;
|
2019-07-14 16:49:44 +02:00
|
|
|
|
|
|
|
MeshBufferCache *mbufcache = &cache->final;
|
|
|
|
|
2020-04-03 16:59:34 +11:00
|
|
|
/* Initialize batches and request VBO's & IBO's. */
|
2019-04-17 06:17:24 +02:00
|
|
|
if (DRW_batch_requested(cache->batch.surface, GPU_PRIM_TRIS)) {
|
2019-07-14 16:49:44 +02:00
|
|
|
DRW_ibo_request(cache->batch.surface, &mbufcache->ibo.tris);
|
2020-04-03 16:59:34 +11:00
|
|
|
/* Order matters. First ones override latest VBO's attributes. */
|
2019-07-14 16:49:44 +02:00
|
|
|
DRW_vbo_request(cache->batch.surface, &mbufcache->vbo.lnor);
|
|
|
|
DRW_vbo_request(cache->batch.surface, &mbufcache->vbo.pos_nor);
|
2019-04-17 06:17:24 +02:00
|
|
|
if (cache->cd_used.uv != 0) {
|
2019-08-14 22:43:44 +02:00
|
|
|
DRW_vbo_request(cache->batch.surface, &mbufcache->vbo.uv);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
if (cache->cd_used.vcol != 0 || cache->cd_used.sculpt_vcol != 0) {
|
2019-07-14 16:49:44 +02:00
|
|
|
DRW_vbo_request(cache->batch.surface, &mbufcache->vbo.vcol);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (DRW_batch_requested(cache->batch.all_verts, GPU_PRIM_POINTS)) {
|
2019-07-14 16:49:44 +02:00
|
|
|
DRW_vbo_request(cache->batch.all_verts, &mbufcache->vbo.pos_nor);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
if (DRW_batch_requested(cache->batch.all_edges, GPU_PRIM_LINES)) {
|
2019-07-14 16:49:44 +02:00
|
|
|
DRW_ibo_request(cache->batch.all_edges, &mbufcache->ibo.lines);
|
|
|
|
DRW_vbo_request(cache->batch.all_edges, &mbufcache->vbo.pos_nor);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
if (DRW_batch_requested(cache->batch.loose_edges, GPU_PRIM_LINES)) {
|
2019-12-03 08:27:55 +01:00
|
|
|
DRW_ibo_request(NULL, &mbufcache->ibo.lines);
|
|
|
|
DRW_ibo_request(cache->batch.loose_edges, &mbufcache->ibo.lines_loose);
|
2019-07-14 16:49:44 +02:00
|
|
|
DRW_vbo_request(cache->batch.loose_edges, &mbufcache->vbo.pos_nor);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
if (DRW_batch_requested(cache->batch.edge_detection, GPU_PRIM_LINES_ADJ)) {
|
2019-07-14 16:49:44 +02:00
|
|
|
DRW_ibo_request(cache->batch.edge_detection, &mbufcache->ibo.lines_adjacency);
|
|
|
|
DRW_vbo_request(cache->batch.edge_detection, &mbufcache->vbo.pos_nor);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
if (DRW_batch_requested(cache->batch.surface_weights, GPU_PRIM_TRIS)) {
|
2019-07-14 16:49:44 +02:00
|
|
|
DRW_ibo_request(cache->batch.surface_weights, &mbufcache->ibo.tris);
|
|
|
|
DRW_vbo_request(cache->batch.surface_weights, &mbufcache->vbo.pos_nor);
|
|
|
|
DRW_vbo_request(cache->batch.surface_weights, &mbufcache->vbo.weights);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-07-01 12:43:07 +02:00
|
|
|
if (DRW_batch_requested(cache->batch.wire_loops, GPU_PRIM_LINES)) {
|
2019-07-14 16:49:44 +02:00
|
|
|
DRW_ibo_request(cache->batch.wire_loops, &mbufcache->ibo.lines_paint_mask);
|
2020-04-03 16:59:34 +11:00
|
|
|
/* Order matters. First ones override latest VBO's attributes. */
|
2019-08-26 18:43:46 +02:00
|
|
|
DRW_vbo_request(cache->batch.wire_loops, &mbufcache->vbo.lnor);
|
2019-07-14 16:49:44 +02:00
|
|
|
DRW_vbo_request(cache->batch.wire_loops, &mbufcache->vbo.pos_nor);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
if (DRW_batch_requested(cache->batch.wire_edges, GPU_PRIM_LINES)) {
|
2019-07-14 16:49:44 +02:00
|
|
|
DRW_ibo_request(cache->batch.wire_edges, &mbufcache->ibo.lines);
|
|
|
|
DRW_vbo_request(cache->batch.wire_edges, &mbufcache->vbo.pos_nor);
|
|
|
|
DRW_vbo_request(cache->batch.wire_edges, &mbufcache->vbo.edge_fac);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-07-14 16:49:44 +02:00
|
|
|
if (DRW_batch_requested(cache->batch.wire_loops_uvs, GPU_PRIM_LINES)) {
|
|
|
|
DRW_ibo_request(cache->batch.wire_loops_uvs, &mbufcache->ibo.edituv_lines);
|
2019-04-17 06:17:24 +02:00
|
|
|
/* For paint overlay. Active layer should have been queried. */
|
|
|
|
if (cache->cd_used.uv != 0) {
|
2019-08-14 22:43:44 +02:00
|
|
|
DRW_vbo_request(cache->batch.wire_loops_uvs, &mbufcache->vbo.uv);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
}
|
2019-04-18 08:00:59 +02:00
|
|
|
if (DRW_batch_requested(cache->batch.edit_mesh_analysis, GPU_PRIM_TRIS)) {
|
2019-07-14 16:49:44 +02:00
|
|
|
DRW_ibo_request(cache->batch.edit_mesh_analysis, &mbufcache->ibo.tris);
|
|
|
|
DRW_vbo_request(cache->batch.edit_mesh_analysis, &mbufcache->vbo.pos_nor);
|
|
|
|
DRW_vbo_request(cache->batch.edit_mesh_analysis, &mbufcache->vbo.mesh_analysis);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Per Material */
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int i = 0; i < cache->mat_len; i++) {
|
2019-07-14 16:49:44 +02:00
|
|
|
if (DRW_batch_requested(cache->surface_per_mat[i], GPU_PRIM_TRIS)) {
|
2019-08-19 17:02:21 +02:00
|
|
|
if (saved_elem_ranges && saved_elem_ranges[i]) {
|
|
|
|
/* XXX assign old element buffer range (it did not change).*/
|
|
|
|
GPU_batch_elembuf_set(cache->surface_per_mat[i], saved_elem_ranges[i], true);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
DRW_ibo_request(cache->surface_per_mat[i], &mbufcache->ibo.tris);
|
|
|
|
}
|
2020-04-03 16:59:34 +11:00
|
|
|
/* Order matters. First ones override latest VBO's attributes. */
|
2019-07-14 16:49:44 +02:00
|
|
|
DRW_vbo_request(cache->surface_per_mat[i], &mbufcache->vbo.lnor);
|
|
|
|
DRW_vbo_request(cache->surface_per_mat[i], &mbufcache->vbo.pos_nor);
|
2019-08-14 22:43:44 +02:00
|
|
|
if (cache->cd_used.uv != 0) {
|
|
|
|
DRW_vbo_request(cache->surface_per_mat[i], &mbufcache->vbo.uv);
|
|
|
|
}
|
|
|
|
if ((cache->cd_used.tan != 0) || (cache->cd_used.tan_orco != 0)) {
|
|
|
|
DRW_vbo_request(cache->surface_per_mat[i], &mbufcache->vbo.tan);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
if (cache->cd_used.vcol != 0 || cache->cd_used.sculpt_vcol != 0) {
|
2019-07-14 16:49:44 +02:00
|
|
|
DRW_vbo_request(cache->surface_per_mat[i], &mbufcache->vbo.vcol);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
if (cache->cd_used.orco != 0) {
|
2019-07-14 16:49:44 +02:00
|
|
|
DRW_vbo_request(cache->surface_per_mat[i], &mbufcache->vbo.orco);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-19 17:02:21 +02:00
|
|
|
MEM_SAFE_FREE(saved_elem_ranges);
|
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
mbufcache = (do_cage) ? &cache->cage : &cache->final;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
/* Edit Mesh */
|
|
|
|
if (DRW_batch_requested(cache->batch.edit_triangles, GPU_PRIM_TRIS)) {
|
|
|
|
DRW_ibo_request(cache->batch.edit_triangles, &mbufcache->ibo.tris);
|
|
|
|
DRW_vbo_request(cache->batch.edit_triangles, &mbufcache->vbo.pos_nor);
|
|
|
|
DRW_vbo_request(cache->batch.edit_triangles, &mbufcache->vbo.edit_data);
|
2019-07-01 12:43:07 +02:00
|
|
|
}
|
2019-07-14 16:49:44 +02:00
|
|
|
if (DRW_batch_requested(cache->batch.edit_vertices, GPU_PRIM_POINTS)) {
|
|
|
|
DRW_ibo_request(cache->batch.edit_vertices, &mbufcache->ibo.points);
|
|
|
|
DRW_vbo_request(cache->batch.edit_vertices, &mbufcache->vbo.pos_nor);
|
|
|
|
DRW_vbo_request(cache->batch.edit_vertices, &mbufcache->vbo.edit_data);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-07-14 16:49:44 +02:00
|
|
|
if (DRW_batch_requested(cache->batch.edit_edges, GPU_PRIM_LINES)) {
|
|
|
|
DRW_ibo_request(cache->batch.edit_edges, &mbufcache->ibo.lines);
|
|
|
|
DRW_vbo_request(cache->batch.edit_edges, &mbufcache->vbo.pos_nor);
|
|
|
|
DRW_vbo_request(cache->batch.edit_edges, &mbufcache->vbo.edit_data);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-07-14 16:49:44 +02:00
|
|
|
if (DRW_batch_requested(cache->batch.edit_vnor, GPU_PRIM_POINTS)) {
|
|
|
|
DRW_ibo_request(cache->batch.edit_vnor, &mbufcache->ibo.points);
|
|
|
|
DRW_vbo_request(cache->batch.edit_vnor, &mbufcache->vbo.pos_nor);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-07-14 16:49:44 +02:00
|
|
|
if (DRW_batch_requested(cache->batch.edit_lnor, GPU_PRIM_POINTS)) {
|
|
|
|
DRW_ibo_request(cache->batch.edit_lnor, &mbufcache->ibo.tris);
|
|
|
|
DRW_vbo_request(cache->batch.edit_lnor, &mbufcache->vbo.pos_nor);
|
|
|
|
DRW_vbo_request(cache->batch.edit_lnor, &mbufcache->vbo.lnor);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-07-14 16:49:44 +02:00
|
|
|
if (DRW_batch_requested(cache->batch.edit_fdots, GPU_PRIM_POINTS)) {
|
|
|
|
DRW_ibo_request(cache->batch.edit_fdots, &mbufcache->ibo.fdots);
|
|
|
|
DRW_vbo_request(cache->batch.edit_fdots, &mbufcache->vbo.fdots_pos);
|
|
|
|
DRW_vbo_request(cache->batch.edit_fdots, &mbufcache->vbo.fdots_nor);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-12-02 01:40:58 +01:00
|
|
|
if (DRW_batch_requested(cache->batch.edit_skin_roots, GPU_PRIM_POINTS)) {
|
2019-10-15 01:49:53 +02:00
|
|
|
DRW_vbo_request(cache->batch.edit_skin_roots, &mbufcache->vbo.skin_roots);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
/* Selection */
|
|
|
|
if (DRW_batch_requested(cache->batch.edit_selection_verts, GPU_PRIM_POINTS)) {
|
|
|
|
DRW_ibo_request(cache->batch.edit_selection_verts, &mbufcache->ibo.points);
|
|
|
|
DRW_vbo_request(cache->batch.edit_selection_verts, &mbufcache->vbo.pos_nor);
|
|
|
|
DRW_vbo_request(cache->batch.edit_selection_verts, &mbufcache->vbo.vert_idx);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-07-14 16:49:44 +02:00
|
|
|
if (DRW_batch_requested(cache->batch.edit_selection_edges, GPU_PRIM_LINES)) {
|
|
|
|
DRW_ibo_request(cache->batch.edit_selection_edges, &mbufcache->ibo.lines);
|
|
|
|
DRW_vbo_request(cache->batch.edit_selection_edges, &mbufcache->vbo.pos_nor);
|
|
|
|
DRW_vbo_request(cache->batch.edit_selection_edges, &mbufcache->vbo.edge_idx);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-07-14 16:49:44 +02:00
|
|
|
if (DRW_batch_requested(cache->batch.edit_selection_faces, GPU_PRIM_TRIS)) {
|
|
|
|
DRW_ibo_request(cache->batch.edit_selection_faces, &mbufcache->ibo.tris);
|
|
|
|
DRW_vbo_request(cache->batch.edit_selection_faces, &mbufcache->vbo.pos_nor);
|
|
|
|
DRW_vbo_request(cache->batch.edit_selection_faces, &mbufcache->vbo.poly_idx);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-07-14 16:49:44 +02:00
|
|
|
if (DRW_batch_requested(cache->batch.edit_selection_fdots, GPU_PRIM_POINTS)) {
|
|
|
|
DRW_ibo_request(cache->batch.edit_selection_fdots, &mbufcache->ibo.fdots);
|
|
|
|
DRW_vbo_request(cache->batch.edit_selection_fdots, &mbufcache->vbo.fdots_pos);
|
|
|
|
DRW_vbo_request(cache->batch.edit_selection_fdots, &mbufcache->vbo.fdot_idx);
|
2019-04-18 08:00:59 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* TODO: The code and data structure is ready to support modified UV display
|
|
|
|
* but the selection code for UVs needs to support it first. So for now, only
|
|
|
|
* display the cage in all cases.
|
|
|
|
*/
|
2019-07-14 16:49:44 +02:00
|
|
|
mbufcache = (do_uvcage) ? &cache->uv_cage : &cache->final;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
/* Edit UV */
|
|
|
|
if (DRW_batch_requested(cache->batch.edituv_faces, GPU_PRIM_TRIS)) {
|
|
|
|
DRW_ibo_request(cache->batch.edituv_faces, &mbufcache->ibo.edituv_tris);
|
2019-08-14 22:43:44 +02:00
|
|
|
DRW_vbo_request(cache->batch.edituv_faces, &mbufcache->vbo.uv);
|
2019-07-14 16:49:44 +02:00
|
|
|
DRW_vbo_request(cache->batch.edituv_faces, &mbufcache->vbo.edituv_data);
|
|
|
|
}
|
2019-09-03 13:42:11 +02:00
|
|
|
if (DRW_batch_requested(cache->batch.edituv_faces_stretch_area, GPU_PRIM_TRIS)) {
|
|
|
|
DRW_ibo_request(cache->batch.edituv_faces_stretch_area, &mbufcache->ibo.edituv_tris);
|
|
|
|
DRW_vbo_request(cache->batch.edituv_faces_stretch_area, &mbufcache->vbo.uv);
|
|
|
|
DRW_vbo_request(cache->batch.edituv_faces_stretch_area, &mbufcache->vbo.edituv_data);
|
|
|
|
DRW_vbo_request(cache->batch.edituv_faces_stretch_area, &mbufcache->vbo.stretch_area);
|
|
|
|
}
|
|
|
|
if (DRW_batch_requested(cache->batch.edituv_faces_stretch_angle, GPU_PRIM_TRIS)) {
|
|
|
|
DRW_ibo_request(cache->batch.edituv_faces_stretch_angle, &mbufcache->ibo.edituv_tris);
|
|
|
|
DRW_vbo_request(cache->batch.edituv_faces_stretch_angle, &mbufcache->vbo.uv);
|
|
|
|
DRW_vbo_request(cache->batch.edituv_faces_stretch_angle, &mbufcache->vbo.edituv_data);
|
|
|
|
DRW_vbo_request(cache->batch.edituv_faces_stretch_angle, &mbufcache->vbo.stretch_angle);
|
2019-07-14 16:49:44 +02:00
|
|
|
}
|
|
|
|
if (DRW_batch_requested(cache->batch.edituv_edges, GPU_PRIM_LINES)) {
|
|
|
|
DRW_ibo_request(cache->batch.edituv_edges, &mbufcache->ibo.edituv_lines);
|
2019-08-14 22:43:44 +02:00
|
|
|
DRW_vbo_request(cache->batch.edituv_edges, &mbufcache->vbo.uv);
|
2019-07-14 16:49:44 +02:00
|
|
|
DRW_vbo_request(cache->batch.edituv_edges, &mbufcache->vbo.edituv_data);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-07-14 16:49:44 +02:00
|
|
|
if (DRW_batch_requested(cache->batch.edituv_verts, GPU_PRIM_POINTS)) {
|
|
|
|
DRW_ibo_request(cache->batch.edituv_verts, &mbufcache->ibo.edituv_points);
|
2019-08-14 22:43:44 +02:00
|
|
|
DRW_vbo_request(cache->batch.edituv_verts, &mbufcache->vbo.uv);
|
2019-07-14 16:49:44 +02:00
|
|
|
DRW_vbo_request(cache->batch.edituv_verts, &mbufcache->vbo.edituv_data);
|
|
|
|
}
|
|
|
|
if (DRW_batch_requested(cache->batch.edituv_fdots, GPU_PRIM_POINTS)) {
|
|
|
|
DRW_ibo_request(cache->batch.edituv_fdots, &mbufcache->ibo.edituv_fdots);
|
|
|
|
DRW_vbo_request(cache->batch.edituv_fdots, &mbufcache->vbo.fdots_uv);
|
|
|
|
DRW_vbo_request(cache->batch.edituv_fdots, &mbufcache->vbo.fdots_edituv_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Meh loose Scene const correctness here. */
|
2020-05-08 19:02:03 +10:00
|
|
|
const bool use_subsurf_fdots = scene ? BKE_modifiers_uses_subsurf_facedots((Scene *)scene, ob) :
|
|
|
|
false;
|
2019-07-14 16:49:44 +02:00
|
|
|
|
|
|
|
if (do_uvcage) {
|
2020-06-02 15:07:17 +02:00
|
|
|
mesh_buffer_cache_create_requested(task_graph,
|
|
|
|
cache,
|
2020-01-08 22:20:45 +11:00
|
|
|
cache->uv_cage,
|
|
|
|
me,
|
|
|
|
is_editmode,
|
2020-04-04 11:14:45 +02:00
|
|
|
is_paint_mode,
|
2020-01-08 22:20:45 +11:00
|
|
|
ob->obmat,
|
|
|
|
false,
|
|
|
|
true,
|
|
|
|
false,
|
|
|
|
&cache->cd_used,
|
2020-02-19 01:44:52 +01:00
|
|
|
scene,
|
2020-01-08 22:20:45 +11:00
|
|
|
ts,
|
|
|
|
true);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
if (do_cage) {
|
2020-06-02 15:07:17 +02:00
|
|
|
mesh_buffer_cache_create_requested(task_graph,
|
|
|
|
cache,
|
2020-01-07 14:06:33 +11:00
|
|
|
cache->cage,
|
|
|
|
me,
|
2020-01-08 22:20:45 +11:00
|
|
|
is_editmode,
|
2020-04-04 11:14:45 +02:00
|
|
|
is_paint_mode,
|
2020-01-07 14:06:33 +11:00
|
|
|
ob->obmat,
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
use_subsurf_fdots,
|
|
|
|
&cache->cd_used,
|
2020-02-19 01:44:52 +01:00
|
|
|
scene,
|
2020-01-07 14:06:33 +11:00
|
|
|
ts,
|
|
|
|
true);
|
|
|
|
}
|
|
|
|
|
2020-06-02 15:07:17 +02:00
|
|
|
mesh_buffer_cache_create_requested(task_graph,
|
|
|
|
cache,
|
2020-01-07 14:06:33 +11:00
|
|
|
cache->final,
|
|
|
|
me,
|
2020-01-08 22:20:45 +11:00
|
|
|
is_editmode,
|
2020-04-04 11:14:45 +02:00
|
|
|
is_paint_mode,
|
2020-01-07 14:06:33 +11:00
|
|
|
ob->obmat,
|
|
|
|
true,
|
|
|
|
false,
|
|
|
|
use_subsurf_fdots,
|
|
|
|
&cache->cd_used,
|
2020-02-19 01:44:52 +01:00
|
|
|
scene,
|
2020-01-07 14:06:33 +11:00
|
|
|
ts,
|
|
|
|
use_hide);
|
2018-12-16 15:17:31 +01:00
|
|
|
#ifdef DEBUG
|
2019-05-08 22:01:34 +02:00
|
|
|
check:
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Make sure all requested batches have been setup. */
|
2020-06-02 15:07:17 +02:00
|
|
|
/* TODO(jbakker): we should move this to the draw_manager but that needs refactoring and
|
|
|
|
* additional looping.*/
|
|
|
|
BLI_task_graph_work_and_wait(task_graph);
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); i++) {
|
2019-04-17 06:17:24 +02:00
|
|
|
BLI_assert(!DRW_batch_requested(((GPUBatch **)&cache->batch)[i], 0));
|
|
|
|
}
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int i = 0; i < sizeof(cache->final.vbo) / sizeof(void *); i++) {
|
2019-07-14 16:49:44 +02:00
|
|
|
BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->final.vbo)[i]));
|
|
|
|
}
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int i = 0; i < sizeof(cache->final.ibo) / sizeof(void *); i++) {
|
2019-07-14 16:49:44 +02:00
|
|
|
BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->final.ibo)[i]));
|
|
|
|
}
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int i = 0; i < sizeof(cache->cage.vbo) / sizeof(void *); i++) {
|
2019-07-14 16:49:44 +02:00
|
|
|
BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->cage.vbo)[i]));
|
|
|
|
}
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int i = 0; i < sizeof(cache->cage.ibo) / sizeof(void *); i++) {
|
2019-07-14 16:49:44 +02:00
|
|
|
BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->cage.ibo)[i]));
|
|
|
|
}
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int i = 0; i < sizeof(cache->uv_cage.vbo) / sizeof(void *); i++) {
|
2019-07-14 16:49:44 +02:00
|
|
|
BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->uv_cage.vbo)[i]));
|
|
|
|
}
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int i = 0; i < sizeof(cache->uv_cage.ibo) / sizeof(void *); i++) {
|
2019-07-14 16:49:44 +02:00
|
|
|
BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->uv_cage.ibo)[i]));
|
|
|
|
}
|
2018-12-16 15:17:31 +01:00
|
|
|
#endif
|
2018-12-08 20:10:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/** \} */
|