Mesh: Move hide flags to generic attributes

This commit moves the hide status of mesh vertices, edges, and faces
from the `ME_FLAG` to optional generic boolean attributes. Storing this
data as generic attributes can significantly simplify and improve code,
as described in T95965.

The attributes are called `.hide_vert`, `.hide_edge`, and `.hide_poly`,
using the attribute name semantics discussed in T97452. The `.` prefix
means they are "UI attributes", so they still contain original data
edited by users, but they aren't meant to be accessed procedurally by
the user in arbitrary situations. They are also be hidden in the
spreadsheet and the attribute list by default,

Until 4.0, the attributes are still written to and read from the mesh
in the old way, so neither forward nor backward compatibility are
affected. This means memory requirements will be increased by one byte
per element when the hide status is used. When the flags are removed
completely, requirements will decrease when hiding is unused.

Further notes:
 * Some code can be further simplified to skip some processing when the
   hide attributes don't exist.
 * The data is still stored in flags for `BMesh`, necessitating some
   complexity in the conversion to and from `Mesh`.
 * Access to the "hide" property of mesh elements in RNA is slower.
   The separate boolean arrays should be used where possible.

Ref T95965

Differential Revision: https://developer.blender.org/D14685
This commit is contained in:
Hans Goudey 2022-08-11 12:54:24 -04:00
parent 5cbfdaccd0
commit 2480b55f21
Notes: blender-bot 2023-02-13 16:56:59 +01:00
Referenced by commit 12becbf0df, Mesh: Move selection flags to generic attributes
Referenced by commit ee23f0f3fb, Sculpt: Separate hide status from face sets, use generic attribute
Referenced by commit 043f59cb3b, Fix weight paint smoothing with vertex selection.
Referenced by commit a6056b870b, Fix T100494: Broken sculpt hide status undo/redo
Referenced by commit 74d716ce23, Fix error/crash in hidden edge drawing after recent changes
Referenced by commit 64f0c25a46, Fix: Incorrect access of mesh hide layers
Referenced by commit 282a861e11, Fix incorrect custom-data layer access for hide layers
Referenced by commit 344919240c, Fix: Broken mesh hide status RNA accessors
Referenced by commit 2fc7e15164, Fix: Use of uninitialized variable in recent commit
Referenced by issue #100494, Regression: Erratic undo behaviors with hidden faces in Sculpt and Vertex/Weight Paint modes
Referenced by issue #100482, Regression: Face Set visibility is reset after saving
Referenced by issue #100480, Regression: Hiding face sets in sculpt mode doesn't work with modifiers
Referenced by issue #95965, Mesh Struct of Arrays Refactor
Referenced by issue #95966, Struct of Arrays Refactor for Mesh Edges
Referenced by issue #95967, Struct of Arrays Refactor for Mesh Polygons
Referenced by issue #93602, Struct of Arrays Refactor for Mesh Vertices
50 changed files with 929 additions and 346 deletions

View File

@ -11,7 +11,9 @@
#include "BLI_sys_types.h"
#include "BLI_utildefines.h"
#ifdef __cplusplus
# include "BLI_set.hh"
# include "BLI_span.hh"
# include "BLI_string_ref.hh"
# include "BLI_vector.hh"
#endif
@ -141,6 +143,15 @@ void CustomData_copy(const struct CustomData *source,
eCDAllocType alloctype,
int totelem);
/**
* Like #CustomData_copy but skips copying layers that are stored as flags on #BMesh.
*/
void CustomData_copy_mesh_to_bmesh(const struct CustomData *source,
struct CustomData *dest,
eCustomDataMask mask,
eCDAllocType alloctype,
int totelem);
/* BMESH_TODO, not really a public function but readfile.c needs it */
void CustomData_update_typemap(struct CustomData *data);
@ -154,6 +165,15 @@ bool CustomData_merge(const struct CustomData *source,
eCDAllocType alloctype,
int totelem);
/**
* Like #CustomData_copy but skips copying layers that are stored as flags on #BMesh.
*/
bool CustomData_merge_mesh_to_bmesh(const struct CustomData *source,
struct CustomData *dest,
eCustomDataMask mask,
eCDAllocType alloctype,
int totelem);
/**
* Reallocate custom data to a new element count.
* Only affects on data layers which are owned by the CustomData itself,
@ -697,7 +717,8 @@ void CustomData_data_transfer(const struct MeshPairRemap *me_remap,
* the struct.
*/
void CustomData_blend_write_prepare(CustomData &data,
blender::Vector<CustomDataLayer, 16> &layers_to_write);
blender::Vector<CustomDataLayer, 16> &layers_to_write,
const blender::Set<blender::StringRef> &skip_names = {});
/**
* \param layers_to_write: Layers created by #CustomData_blend_write_prepare.

View File

@ -865,19 +865,7 @@ void BKE_mesh_merge_customdata_for_apply_modifier(struct Mesh *me);
/**
* Update the hide flag for edges and faces from the corresponding flag in verts.
*/
void BKE_mesh_flush_hidden_from_verts_ex(const struct MVert *mvert,
const struct MLoop *mloop,
struct MEdge *medge,
int totedge,
struct MPoly *mpoly,
int totpoly);
void BKE_mesh_flush_hidden_from_verts(struct Mesh *me);
void BKE_mesh_flush_hidden_from_polys_ex(struct MVert *mvert,
const struct MLoop *mloop,
struct MEdge *medge,
int totedge,
const struct MPoly *mpoly,
int totpoly);
void BKE_mesh_flush_hidden_from_polys(struct Mesh *me);
/**
* simple poly -> vert/edge selection.

View File

@ -17,6 +17,16 @@ struct CustomData;
struct Mesh;
struct MFace;
/**
* Convert the hidden element attributes to the old flag format for writing.
*/
void BKE_mesh_legacy_convert_hide_layers_to_flags(struct Mesh *mesh);
/**
* Convert the old hide flags (#ME_HIDE) to the hidden element attribute for reading.
* Only add the attributes when there are any elements in each domain hidden.
*/
void BKE_mesh_legacy_convert_flags_to_hide_layers(struct Mesh *mesh);
/**
* Recreate #MFace Tessellation.
*

View File

@ -92,6 +92,7 @@ typedef struct MeshElemMap {
/* mapping */
UvVertMap *BKE_mesh_uv_vert_map_create(const struct MPoly *mpoly,
const bool *hide_poly,
const struct MLoop *mloop,
const struct MLoopUV *mloopuv,
unsigned int totpoly,

View File

@ -213,7 +213,7 @@ bool BKE_paint_always_hide_test(struct Object *ob);
* Returns non-zero if any of the face's vertices are hidden, zero otherwise.
*/
bool paint_is_face_hidden(const struct MLoopTri *lt,
const struct MVert *mvert,
const bool *hide_vert,
const struct MLoop *mloop);
/**
* Returns non-zero if any of the corners of the grid

View File

@ -533,6 +533,7 @@ typedef struct PBVHVertexIter {
/* mesh */
struct MVert *mverts;
float (*vert_normals)[3];
const bool *hide_vert;
int totvert;
const int *vert_indices;
float *vmask;
@ -593,7 +594,7 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
else if (vi.mverts) { \
vi.mvert = &vi.mverts[vi.vert_indices[vi.gx]]; \
if (vi.respect_hide) { \
vi.visible = !(vi.mvert->flag & ME_HIDE); \
vi.visible = !(vi.hide_vert && vi.hide_vert[vi.vert_indices[vi.gx]]); \
if (mode == PBVH_ITER_UNIQUE && !vi.visible) { \
continue; \
} \
@ -667,6 +668,8 @@ void BKE_pbvh_parallel_range_settings(struct TaskParallelSettings *settings,
struct MVert *BKE_pbvh_get_verts(const PBVH *pbvh);
const float (*BKE_pbvh_get_vert_normals(const PBVH *pbvh))[3];
const bool *BKE_pbvh_get_vert_hide(const PBVH *pbvh);
bool *BKE_pbvh_get_vert_hide_for_write(PBVH *pbvh);
PBVHColorBufferNode *BKE_pbvh_node_color_buffer_get(PBVHNode *node);
void BKE_pbvh_node_color_buffer_free(PBVH *pbvh);

View File

@ -56,7 +56,7 @@ const char *no_procedural_access_message =
bool allow_procedural_attribute_access(StringRef attribute_name)
{
return !attribute_name.startswith(".selection");
return !attribute_name.startswith(".selection") && !attribute_name.startswith(".hide");
}
static int attribute_data_type_complexity(const eCustomDataType data_type)

View File

@ -27,6 +27,8 @@
#include "MEM_guardedalloc.h"
using blender::VArray;
/* -------------------------------------------------------------------- */
/** \name BVHCache
* \{ */
@ -1181,9 +1183,13 @@ static BLI_bitmap *loose_edges_map_get(const MEdge *medge,
}
static BLI_bitmap *looptri_no_hidden_map_get(const MPoly *mpoly,
const VArray<bool> &hide_poly,
const int looptri_len,
int *r_looptri_active_len)
{
if (hide_poly.is_single() && !hide_poly.get_internal_single()) {
return nullptr;
}
BLI_bitmap *looptri_mask = BLI_BITMAP_NEW(looptri_len, __func__);
int looptri_no_hidden_len = 0;
@ -1191,8 +1197,7 @@ static BLI_bitmap *looptri_no_hidden_map_get(const MPoly *mpoly,
int i_poly = 0;
while (looptri_iter != looptri_len) {
int mp_totlooptri = mpoly[i_poly].totloop - 2;
const MPoly &mp = mpoly[i_poly];
if (mp.flag & ME_HIDE) {
if (hide_poly[i_poly]) {
looptri_iter += mp_totlooptri;
}
else {
@ -1276,9 +1281,15 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
0.0f, tree_type, 6, mesh->mvert, mesh->mface, mesh->totface, nullptr, -1);
break;
case BVHTREE_FROM_LOOPTRI_NO_HIDDEN:
mask = looptri_no_hidden_map_get(mesh->mpoly, looptri_len, &mask_bits_act_len);
case BVHTREE_FROM_LOOPTRI_NO_HIDDEN: {
blender::bke::AttributeAccessor attributes = blender::bke::mesh_attributes(*mesh);
mask = looptri_no_hidden_map_get(
mesh->mpoly,
attributes.lookup_or_default(".hide_poly", ATTR_DOMAIN_FACE, false),
looptri_len,
&mask_bits_act_len);
ATTR_FALLTHROUGH;
}
case BVHTREE_FROM_LOOPTRI:
data->tree = bvhtree_from_mesh_looptri_create_tree(0.0f,
tree_type,

View File

@ -26,6 +26,7 @@
#include "BLI_math_vector.hh"
#include "BLI_mempool.h"
#include "BLI_path_util.h"
#include "BLI_set.hh"
#include "BLI_span.hh"
#include "BLI_string.h"
#include "BLI_string_ref.hh"
@ -58,6 +59,7 @@
#include "data_transfer_intern.h"
using blender::IndexRange;
using blender::Set;
using blender::Span;
using blender::StringRef;
using blender::Vector;
@ -2342,6 +2344,43 @@ bool CustomData_merge(const CustomData *source,
return changed;
}
static bool attribute_stored_in_bmesh_flag(const StringRef name)
{
return ELEM(name, ".hide_vert", ".hide_edge", ".hide_poly");
}
static CustomData shallow_copy_remove_non_bmesh_attributes(const CustomData &src)
{
Vector<CustomDataLayer> dst_layers;
for (const CustomDataLayer &layer : Span<CustomDataLayer>{src.layers, src.totlayer}) {
if (!attribute_stored_in_bmesh_flag(layer.name)) {
dst_layers.append(layer);
}
}
CustomData dst = src;
dst.layers = static_cast<CustomDataLayer *>(
MEM_calloc_arrayN(dst_layers.size(), sizeof(CustomDataLayer), __func__));
dst.totlayer = dst_layers.size();
memcpy(dst.layers, dst_layers.data(), dst_layers.as_span().size_in_bytes());
CustomData_update_typemap(&dst);
return dst;
}
bool CustomData_merge_mesh_to_bmesh(const CustomData *source,
CustomData *dest,
const eCustomDataMask mask,
const eCDAllocType alloctype,
const int totelem)
{
CustomData source_copy = shallow_copy_remove_non_bmesh_attributes(*source);
const bool result = CustomData_merge(&source_copy, dest, mask, alloctype, totelem);
MEM_SAFE_FREE(source_copy.layers);
return result;
}
void CustomData_realloc(CustomData *data, const int totelem)
{
BLI_assert(totelem >= 0);
@ -2373,6 +2412,17 @@ void CustomData_copy(const CustomData *source,
CustomData_merge(source, dest, mask, alloctype, totelem);
}
void CustomData_copy_mesh_to_bmesh(const CustomData *source,
CustomData *dest,
const eCustomDataMask mask,
const eCDAllocType alloctype,
const int totelem)
{
CustomData source_copy = shallow_copy_remove_non_bmesh_attributes(*source);
CustomData_copy(&source_copy, dest, mask, alloctype, totelem);
MEM_SAFE_FREE(source_copy.layers);
}
static void customData_free_layer__internal(CustomDataLayer *layer, const int totelem)
{
const LayerTypeInfo *typeInfo;
@ -4303,7 +4353,9 @@ void CustomData_file_write_info(int type, const char **r_struct_name, int *r_str
*r_struct_num = typeInfo->structnum;
}
void CustomData_blend_write_prepare(CustomData &data, Vector<CustomDataLayer, 16> &layers_to_write)
void CustomData_blend_write_prepare(CustomData &data,
Vector<CustomDataLayer, 16> &layers_to_write,
const Set<StringRef> &skip_names)
{
for (const CustomDataLayer &layer : Span(data.layers, data.totlayer)) {
if (layer.flag & CD_FLAG_NOCOPY) {
@ -4312,6 +4364,9 @@ void CustomData_blend_write_prepare(CustomData &data, Vector<CustomDataLayer, 16
if (layer.anonymous_id != nullptr) {
continue;
}
if (skip_names.contains(layer.name)) {
continue;
}
layers_to_write.append(layer);
}
data.totlayer = layers_to_write.size();

View File

@ -28,6 +28,7 @@
#include "BLI_math.h"
#include "BLI_math_vector.hh"
#include "BLI_memarena.h"
#include "BLI_span.hh"
#include "BLI_string.h"
#include "BLI_task.hh"
#include "BLI_utildefines.h"
@ -36,6 +37,7 @@
#include "BLT_translation.h"
#include "BKE_anim_data.h"
#include "BKE_attribute.hh"
#include "BKE_bpath.h"
#include "BKE_deform.h"
#include "BKE_editmesh.h"
@ -62,6 +64,8 @@
#include "BLO_read_write.h"
using blender::float3;
using blender::MutableSpan;
using blender::VArray;
using blender::Vector;
static void mesh_clear_geometry(Mesh *mesh);
@ -241,10 +245,14 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
memset(&mesh->pdata, 0, sizeof(mesh->pdata));
}
else {
CustomData_blend_write_prepare(mesh->vdata, vert_layers);
CustomData_blend_write_prepare(mesh->edata, edge_layers);
if (!BLO_write_is_undo(writer)) {
BKE_mesh_legacy_convert_hide_layers_to_flags(mesh);
}
CustomData_blend_write_prepare(mesh->vdata, vert_layers, {".hide_vert"});
CustomData_blend_write_prepare(mesh->edata, edge_layers, {".hide_edge"});
CustomData_blend_write_prepare(mesh->ldata, loop_layers);
CustomData_blend_write_prepare(mesh->pdata, poly_layers);
CustomData_blend_write_prepare(mesh->pdata, poly_layers, {".hide_poly"});
}
BLO_write_id_struct(writer, Mesh, id_address, &mesh->id);
@ -323,6 +331,10 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id)
}
}
if (!BLO_read_data_is_undo(reader)) {
BKE_mesh_legacy_convert_flags_to_hide_layers(mesh);
}
/* We don't expect to load normals from files, since they are derived data. */
BKE_mesh_normals_tag_dirty(mesh);
BKE_mesh_assert_normals_dirty_or_calculated(mesh);

View File

@ -22,15 +22,17 @@
#include "BLI_math.h"
#include "BLI_span.hh"
#include "BLI_utildefines.h"
#include "BLI_virtual_array.hh"
#include "BKE_customdata.h"
#include "BKE_attribute.hh"
#include "BKE_mesh.h"
#include "BKE_multires.h"
using blender::IndexRange;
using blender::MutableSpan;
using blender::Span;
using blender::VArray;
/* -------------------------------------------------------------------- */
/** \name Polygon Calculations
@ -732,75 +734,89 @@ void BKE_mesh_polygons_flip(MPoly *mpoly, MLoop *mloop, CustomData *ldata, int t
/** \name Mesh Flag Flushing
* \{ */
void BKE_mesh_flush_hidden_from_verts_ex(const MVert *mvert,
const MLoop *mloop,
MEdge *medge,
const int totedge,
MPoly *mpoly,
const int totpoly)
{
int i, j;
for (i = 0; i < totedge; i++) {
MEdge *e = &medge[i];
if (mvert[e->v1].flag & ME_HIDE || mvert[e->v2].flag & ME_HIDE) {
e->flag |= ME_HIDE;
}
else {
e->flag &= ~ME_HIDE;
}
}
for (i = 0; i < totpoly; i++) {
MPoly *p = &mpoly[i];
p->flag &= (char)~ME_HIDE;
for (j = 0; j < p->totloop; j++) {
if (mvert[mloop[p->loopstart + j].v].flag & ME_HIDE) {
p->flag |= ME_HIDE;
}
}
}
}
void BKE_mesh_flush_hidden_from_verts(Mesh *me)
{
BKE_mesh_flush_hidden_from_verts_ex(
me->mvert, me->mloop, me->medge, me->totedge, me->mpoly, me->totpoly);
using namespace blender;
using namespace blender::bke;
MutableAttributeAccessor attributes = mesh_attributes_for_write(*me);
const VArray<bool> hide_vert = attributes.lookup_or_default<bool>(
".hide_vert", ATTR_DOMAIN_POINT, false);
if (hide_vert.is_single() && !hide_vert.get_internal_single()) {
attributes.remove(".hide_edge");
attributes.remove(".hide_poly");
return;
}
const VArraySpan<bool> hide_vert_span{hide_vert};
const Span<MEdge> edges(me->medge, me->totedge);
const Span<MPoly> polys(me->mpoly, me->totpoly);
const Span<MLoop> loops(me->mloop, me->totloop);
/* Hide edges when either of their vertices are hidden. */
SpanAttributeWriter<bool> hide_edge = attributes.lookup_or_add_for_write_only_span<bool>(
".hide_edge", ATTR_DOMAIN_EDGE);
for (const int i : edges.index_range()) {
const MEdge &edge = edges[i];
hide_edge.span[i] = hide_vert_span[edge.v1] || hide_vert_span[edge.v2];
}
hide_edge.finish();
/* Hide faces when any of their vertices are hidden. */
SpanAttributeWriter<bool> hide_poly = attributes.lookup_or_add_for_write_only_span<bool>(
".hide_poly", ATTR_DOMAIN_FACE);
for (const int i : polys.index_range()) {
const MPoly &poly = polys[i];
const Span<MLoop> loops = loops.slice(poly.loopstart, poly.totloop);
hide_poly.span[i] = std::any_of(
loops.begin(), loops.end(), [&](const MLoop &loop) { return hide_vert_span[loop.v]; });
}
hide_poly.finish();
}
void BKE_mesh_flush_hidden_from_polys_ex(MVert *mvert,
const MLoop *mloop,
MEdge *medge,
const int UNUSED(totedge),
const MPoly *mpoly,
const int totpoly)
{
int i = totpoly;
for (const MPoly *mp = mpoly; i--; mp++) {
if (mp->flag & ME_HIDE) {
const MLoop *ml;
int j = mp->totloop;
for (ml = &mloop[mp->loopstart]; j--; ml++) {
mvert[ml->v].flag |= ME_HIDE;
medge[ml->e].flag |= ME_HIDE;
}
}
}
i = totpoly;
for (const MPoly *mp = mpoly; i--; mp++) {
if ((mp->flag & ME_HIDE) == 0) {
const MLoop *ml;
int j = mp->totloop;
for (ml = &mloop[mp->loopstart]; j--; ml++) {
mvert[ml->v].flag &= (char)~ME_HIDE;
medge[ml->e].flag &= (short)~ME_HIDE;
}
}
}
}
void BKE_mesh_flush_hidden_from_polys(Mesh *me)
{
BKE_mesh_flush_hidden_from_polys_ex(
me->mvert, me->mloop, me->medge, me->totedge, me->mpoly, me->totpoly);
using namespace blender;
using namespace blender::bke;
MutableAttributeAccessor attributes = mesh_attributes_for_write(*me);
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
if (hide_poly.is_single() && !hide_poly.get_internal_single()) {
attributes.remove(".hide_vert");
attributes.remove(".hide_edge");
return;
}
const VArraySpan<bool> hide_face_span{hide_poly};
const Span<MPoly> polys(me->mpoly, me->totpoly);
const Span<MLoop> loops(me->mloop, me->totloop);
SpanAttributeWriter<bool> hide_vert = attributes.lookup_or_add_for_write_only_span<bool>(
".hide_vert", ATTR_DOMAIN_POINT);
SpanAttributeWriter<bool> hide_edge = attributes.lookup_or_add_for_write_only_span<bool>(
".hide_edge", ATTR_DOMAIN_EDGE);
/* Hide all edges or vertices connected to hidden faces. */
for (const int i : polys.index_range()) {
if (hide_face_span[i]) {
const MPoly &poly = polys[i];
for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
hide_vert.span[loop.v] = true;
hide_edge.span[loop.e] = true;
}
}
}
/* Unhide vertices and edges connected to visible faces. */
for (const int i : polys.index_range()) {
if (!hide_face_span[i]) {
const MPoly &poly = polys[i];
for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
hide_vert.span[loop.v] = false;
hide_edge.span[loop.e] = false;
}
}
}
hide_vert.finish();
hide_edge.finish();
}
void BKE_mesh_flush_select_from_polys_ex(MVert *mvert,
@ -848,11 +864,13 @@ void BKE_mesh_flush_select_from_polys(Mesh *me)
static void mesh_flush_select_from_verts(const Span<MVert> verts,
const Span<MLoop> loops,
const VArray<bool> &hide_edge,
const VArray<bool> &hide_poly,
MutableSpan<MEdge> edges,
MutableSpan<MPoly> polys)
{
for (const int i : edges.index_range()) {
if ((edges[i].flag & ME_HIDE) == 0) {
if (!hide_edge[i]) {
MEdge &edge = edges[i];
if ((verts[edge.v1].flag & SELECT) && (verts[edge.v2].flag & SELECT)) {
edge.flag |= SELECT;
@ -864,7 +882,7 @@ static void mesh_flush_select_from_verts(const Span<MVert> verts,
}
for (const int i : polys.index_range()) {
if (polys[i].flag & ME_HIDE) {
if (hide_poly[i]) {
continue;
}
MPoly &poly = polys[i];
@ -885,10 +903,14 @@ static void mesh_flush_select_from_verts(const Span<MVert> verts,
void BKE_mesh_flush_select_from_verts(Mesh *me)
{
mesh_flush_select_from_verts({me->mvert, me->totvert},
{me->mloop, me->totloop},
{me->medge, me->totedge},
{me->mpoly, me->totpoly});
const blender::bke::AttributeAccessor attributes = blender::bke::mesh_attributes(*me);
mesh_flush_select_from_verts(
{me->mvert, me->totvert},
{me->mloop, me->totloop},
attributes.lookup_or_default<bool>(".hide_edge", ATTR_DOMAIN_EDGE, false),
attributes.lookup_or_default<bool>(".hide_poly", ATTR_DOMAIN_FACE, false),
{me->medge, me->totedge},
{me->mpoly, me->totpoly});
}
/** \} */

View File

@ -7,7 +7,7 @@
* Functions to convert mesh data to and from legacy formats like #MFace.
*/
// #include <climits>
#define DNA_DEPRECATED_ALLOW
#include "MEM_guardedalloc.h"
@ -18,8 +18,10 @@
#include "BLI_math.h"
#include "BLI_memarena.h"
#include "BLI_polyfill_2d.h"
#include "BLI_task.hh"
#include "BLI_utildefines.h"
#include "BKE_attribute.hh"
#include "BKE_customdata.h"
#include "BKE_mesh.h"
#include "BKE_mesh_legacy_convert.h"
@ -874,3 +876,91 @@ void BKE_mesh_add_mface_layers(CustomData *fdata, CustomData *ldata, int total)
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Hide Attribute and Legacy Flag Conversion
* \{ */
void BKE_mesh_legacy_convert_hide_layers_to_flags(Mesh *mesh)
{
using namespace blender;
using namespace blender::bke;
const AttributeAccessor attributes = mesh_attributes(*mesh);
MutableSpan<MVert> vertices(mesh->mvert, mesh->totvert);
const VArray<bool> hide_vert = attributes.lookup_or_default<bool>(
".hide_vert", ATTR_DOMAIN_POINT, false);
threading::parallel_for(vertices.index_range(), 4096, [&](IndexRange range) {
for (const int i : range) {
SET_FLAG_FROM_TEST(vertices[i].flag, hide_vert[i], ME_HIDE);
}
});
MutableSpan<MEdge> edges(mesh->medge, mesh->totedge);
const VArray<bool> hide_edge = attributes.lookup_or_default<bool>(
".hide_edge", ATTR_DOMAIN_EDGE, false);
threading::parallel_for(edges.index_range(), 4096, [&](IndexRange range) {
for (const int i : range) {
SET_FLAG_FROM_TEST(edges[i].flag, hide_edge[i], ME_HIDE);
}
});
MutableSpan<MPoly> polygons(mesh->mpoly, mesh->totpoly);
const VArray<bool> hide_face = attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
threading::parallel_for(polygons.index_range(), 4096, [&](IndexRange range) {
for (const int i : range) {
SET_FLAG_FROM_TEST(polygons[i].flag, hide_face[i], ME_HIDE);
}
});
}
void BKE_mesh_legacy_convert_flags_to_hide_layers(Mesh *mesh)
{
using namespace blender;
using namespace blender::bke;
MutableAttributeAccessor attributes = mesh_attributes_for_write(*mesh);
const Span<MVert> vertices(mesh->mvert, mesh->totvert);
if (std::any_of(vertices.begin(), vertices.end(), [](const MVert &vert) {
return vert.flag & ME_HIDE;
})) {
SpanAttributeWriter<bool> hide_vert = attributes.lookup_or_add_for_write_only_span<bool>(
".hide_vert", ATTR_DOMAIN_POINT);
threading::parallel_for(vertices.index_range(), 4096, [&](IndexRange range) {
for (const int i : range) {
hide_vert.span[i] = vertices[i].flag & ME_HIDE;
}
});
hide_vert.finish();
}
const Span<MEdge> edges(mesh->medge, mesh->totedge);
if (std::any_of(
edges.begin(), edges.end(), [](const MEdge &edge) { return edge.flag & ME_HIDE; })) {
SpanAttributeWriter<bool> hide_edge = attributes.lookup_or_add_for_write_only_span<bool>(
".hide_edge", ATTR_DOMAIN_EDGE);
threading::parallel_for(edges.index_range(), 4096, [&](IndexRange range) {
for (const int i : range) {
hide_edge.span[i] = edges[i].flag & ME_HIDE;
}
});
hide_edge.finish();
}
const Span<MPoly> polygons(mesh->mpoly, mesh->totpoly);
if (std::any_of(polygons.begin(), polygons.end(), [](const MPoly &poly) {
return poly.flag & ME_HIDE;
})) {
SpanAttributeWriter<bool> hide_face = attributes.lookup_or_add_for_write_only_span<bool>(
".hide_poly", ATTR_DOMAIN_FACE);
threading::parallel_for(polygons.index_range(), 4096, [&](IndexRange range) {
for (const int i : range) {
hide_face.span[i] = polygons[i].flag & ME_HIDE;
}
});
hide_face.finish();
}
}
/** \} */

View File

@ -29,6 +29,7 @@
/* ngon version wip, based on BM_uv_vert_map_create */
UvVertMap *BKE_mesh_uv_vert_map_create(const MPoly *mpoly,
const bool *hide_poly,
const MLoop *mloop,
const MLoopUV *mloopuv,
uint totpoly,
@ -51,7 +52,7 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const MPoly *mpoly,
/* generate UvMapVert array */
mp = mpoly;
for (a = 0; a < totpoly; a++, mp++) {
if (!selected || (!(mp->flag & ME_HIDE) && (mp->flag & ME_FACE_SEL))) {
if (!selected || (!(hide_poly && hide_poly[a]) && (mp->flag & ME_FACE_SEL))) {
totuv += mp->totloop;
}
}
@ -74,7 +75,7 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const MPoly *mpoly,
mp = mpoly;
for (a = 0; a < totpoly; a++, mp++) {
if (!selected || (!(mp->flag & ME_HIDE) && (mp->flag & ME_FACE_SEL))) {
if (!selected || (!(hide_poly && hide_poly[a]) && (mp->flag & ME_FACE_SEL))) {
float(*tf_uv)[2] = NULL;
if (use_winding) {

View File

@ -1243,11 +1243,13 @@ void BKE_paint_blend_read_lib(BlendLibReader *reader, Scene *sce, Paint *p)
}
}
bool paint_is_face_hidden(const MLoopTri *lt, const MVert *mvert, const MLoop *mloop)
bool paint_is_face_hidden(const MLoopTri *lt, const bool *hide_vert, const MLoop *mloop)
{
return ((mvert[mloop[lt->tri[0]].v].flag & ME_HIDE) ||
(mvert[mloop[lt->tri[1]].v].flag & ME_HIDE) ||
(mvert[mloop[lt->tri[2]].v].flag & ME_HIDE));
if (!hide_vert) {
return false;
}
return ((hide_vert[mloop[lt->tri[0]].v]) || (hide_vert[mloop[lt->tri[1]].v]) ||
(hide_vert[mloop[lt->tri[2]].v]));
}
bool paint_is_grid_face_hidden(const uint *grid_hidden, int gridsize, int x, int y)
@ -2068,9 +2070,11 @@ void BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(Mesh *mesh)
}
int *face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS);
const bool *hide_poly = (const bool *)CustomData_get_layer_named(
&mesh->pdata, CD_PROP_BOOL, ".hide_poly");
for (int i = 0; i < mesh->totpoly; i++) {
if (!(mesh->mpoly[i].flag & ME_HIDE)) {
if (!(hide_poly && hide_poly[i])) {
continue;
}
@ -2095,9 +2099,13 @@ void BKE_sculpt_sync_face_sets_visibility_to_base_mesh(Mesh *mesh)
return;
}
bool *hide_poly = (bool *)CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, ".hide_poly");
if (!hide_poly) {
return;
}
for (int i = 0; i < mesh->totpoly; i++) {
const bool is_face_set_visible = face_sets[i] >= 0;
SET_FLAG_FROM_TEST(mesh->mpoly[i].flag, !is_face_set_visible, ME_HIDE);
hide_poly[i] = face_sets[i] < 0;
}
BKE_mesh_flush_hidden_from_polys(mesh);

View File

@ -287,7 +287,7 @@ static void build_mesh_leaf_node(PBVH *pbvh, PBVHNode *node)
}
if (has_visible == false) {
if (!paint_is_face_hidden(lt, pbvh->verts, pbvh->mloop)) {
if (!paint_is_face_hidden(lt, pbvh->hide_vert, pbvh->mloop)) {
has_visible = true;
}
}
@ -562,6 +562,7 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
pbvh->verts = verts;
BKE_mesh_vertex_normals_ensure(mesh);
pbvh->vert_normals = BKE_mesh_vertex_normals_for_write(mesh);
pbvh->hide_vert = (bool *)CustomData_get_layer_named(&mesh->vdata, CD_PROP_BOOL, ".hide_vert");
pbvh->vert_bitmap = MEM_calloc_arrayN(totvert, sizeof(bool), "bvh->vert_bitmap");
pbvh->totvert = totvert;
pbvh->leaf_limit = LEAF_LIMIT;
@ -1316,7 +1317,6 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
case PBVH_FACES:
node->draw_buffers = GPU_pbvh_mesh_buffers_build(
pbvh->mesh,
pbvh->verts,
pbvh->looptri,
CustomData_get_layer(pbvh->pdata, CD_SCULPT_FACE_SETS),
node->prim_indices,
@ -1590,9 +1590,12 @@ static void pbvh_faces_node_visibility_update(PBVH *pbvh, PBVHNode *node)
BKE_pbvh_node_num_verts(pbvh, node, NULL, &totvert);
BKE_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert);
if (pbvh->hide_vert == NULL) {
BKE_pbvh_node_fully_hidden_set(node, false);
return;
}
for (i = 0; i < totvert; i++) {
MVert *v = &mvert[vert_indices[i]];
if (!(v->flag & ME_HIDE)) {
if (!(pbvh->hide_vert[vert_indices[i]])) {
BKE_pbvh_node_fully_hidden_set(node, false);
return;
}
@ -2291,7 +2294,7 @@ static bool pbvh_faces_node_raycast(PBVH *pbvh,
const MLoopTri *lt = &pbvh->looptri[faces[i]];
const int *face_verts = node->face_vert_indices[i];
if (pbvh->respect_hide && paint_is_face_hidden(lt, vert, mloop)) {
if (pbvh->respect_hide && paint_is_face_hidden(lt, pbvh->hide_vert, mloop)) {
continue;
}
@ -2600,7 +2603,7 @@ static bool pbvh_faces_node_nearest_to_ray(PBVH *pbvh,
const MLoopTri *lt = &pbvh->looptri[faces[i]];
const int *face_verts = node->face_vert_indices[i];
if (pbvh->respect_hide && paint_is_face_hidden(lt, vert, mloop)) {
if (pbvh->respect_hide && paint_is_face_hidden(lt, pbvh->hide_vert, mloop)) {
continue;
}
@ -3127,6 +3130,7 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
vi->mask = NULL;
if (pbvh->header.type == PBVH_FACES) {
vi->vert_normals = pbvh->vert_normals;
vi->hide_vert = pbvh->hide_vert;
vi->vmask = CustomData_get_layer(pbvh->vdata, CD_PAINT_MASK);
}
@ -3207,6 +3211,27 @@ const float (*BKE_pbvh_get_vert_normals(const PBVH *pbvh))[3]
return pbvh->vert_normals;
}
const bool *BKE_pbvh_get_vert_hide(const PBVH *pbvh)
{
BLI_assert(pbvh->header.type == PBVH_FACES);
return pbvh->hide_vert;
}
bool *BKE_pbvh_get_vert_hide_for_write(PBVH *pbvh)
{
BLI_assert(pbvh->header.type == PBVH_FACES);
if (pbvh->hide_vert) {
return pbvh->hide_vert;
}
pbvh->hide_vert = CustomData_get_layer_named(&pbvh->mesh->vdata, CD_PROP_BOOL, ".hide_vert");
if (pbvh->hide_vert) {
return pbvh->hide_vert;
}
pbvh->hide_vert = (bool *)CustomData_add_layer_named(
&pbvh->mesh->vdata, CD_PROP_BOOL, CD_CALLOC, NULL, pbvh->mesh->totvert, ".hide_vert");
return pbvh->hide_vert;
}
void BKE_pbvh_subdiv_cgg_set(PBVH *pbvh, SubdivCCG *subdiv_ccg)
{
pbvh->subdiv_ccg = subdiv_ccg;

View File

@ -144,10 +144,11 @@ struct PBVH {
int leaf_limit;
/* Mesh data */
const struct Mesh *mesh;
struct Mesh *mesh;
/* NOTE: Normals are not `const` because they can be updated for drawing by sculpt code. */
float (*vert_normals)[3];
bool *hide_vert;
struct MVert *verts;
const struct MPoly *mpoly;
const struct MLoop *mloop;

View File

@ -205,7 +205,15 @@ static void precalc_uv_layer(const OpenSubdiv_Converter *converter, const int la
mesh->totloop, sizeof(int), "loop uv vertex index");
}
UvVertMap *uv_vert_map = BKE_mesh_uv_vert_map_create(
mpoly, mloop, mloopuv, num_poly, num_vert, limit, false, true);
mpoly,
(const bool *)CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, ".hide_poly"),
mloop,
mloopuv,
num_poly,
num_vert,
limit,
false,
true);
/* NOTE: First UV vertex is supposed to be always marked as separate. */
storage->num_uv_coordinates = -1;
for (int vertex_index = 0; vertex_index < num_vert; vertex_index++) {

View File

@ -284,7 +284,8 @@ static int ss_sync_from_uv(CCGSubSurf *ss,
* UV map in really simple cases with mirror + subsurf, see second part of T44530.
* Also, initially intention is to treat merged vertices from mirror modifier as seams.
* This fixes a very old regression (2.49 was correct here) */
vmap = BKE_mesh_uv_vert_map_create(mpoly, mloop, mloopuv, totface, totvert, limit, false, true);
vmap = BKE_mesh_uv_vert_map_create(
mpoly, NULL, mloop, mloopuv, totface, totvert, limit, false, true);
if (!vmap) {
return 0;
}

View File

@ -512,16 +512,24 @@ void BM_mesh_copy_init_customdata_from_mesh_array(BMesh *bm_dst,
for (int i = 0; i < me_src_array_len; i++) {
const Mesh *me_src = me_src_array[i];
if (i == 0) {
CustomData_copy(&me_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_CALLOC, 0);
CustomData_copy(&me_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_CALLOC, 0);
CustomData_copy(&me_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_CALLOC, 0);
CustomData_copy(&me_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_CALLOC, 0);
CustomData_copy_mesh_to_bmesh(
&me_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_CALLOC, 0);
CustomData_copy_mesh_to_bmesh(
&me_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_CALLOC, 0);
CustomData_copy_mesh_to_bmesh(
&me_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_CALLOC, 0);
CustomData_copy_mesh_to_bmesh(
&me_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_CALLOC, 0);
}
else {
CustomData_merge(&me_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_CALLOC, 0);
CustomData_merge(&me_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_CALLOC, 0);
CustomData_merge(&me_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_CALLOC, 0);
CustomData_merge(&me_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_CALLOC, 0);
CustomData_merge_mesh_to_bmesh(
&me_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_CALLOC, 0);
CustomData_merge_mesh_to_bmesh(
&me_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_CALLOC, 0);
CustomData_merge_mesh_to_bmesh(
&me_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_CALLOC, 0);
CustomData_merge_mesh_to_bmesh(
&me_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_CALLOC, 0);
}
cd_flag |= me_src->cd_flag;
@ -714,26 +722,25 @@ BMesh *BM_mesh_copy(BMesh *bm_old)
char BM_vert_flag_from_mflag(const char mflag)
{
return (((mflag & SELECT) ? BM_ELEM_SELECT : 0) | ((mflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0));
return ((mflag & SELECT) ? BM_ELEM_SELECT : 0);
}
char BM_edge_flag_from_mflag(const short mflag)
{
return (((mflag & SELECT) ? BM_ELEM_SELECT : 0) | ((mflag & ME_SEAM) ? BM_ELEM_SEAM : 0) |
((mflag & ME_EDGEDRAW) ? BM_ELEM_DRAW : 0) |
((mflag & ME_SHARP) == 0 ? BM_ELEM_SMOOTH : 0) | /* invert */
((mflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0));
((mflag & ME_SHARP) == 0 ? BM_ELEM_SMOOTH : 0));
}
char BM_face_flag_from_mflag(const char mflag)
{
return (((mflag & ME_FACE_SEL) ? BM_ELEM_SELECT : 0) |
((mflag & ME_SMOOTH) ? BM_ELEM_SMOOTH : 0) | ((mflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0));
((mflag & ME_SMOOTH) ? BM_ELEM_SMOOTH : 0));
}
char BM_vert_flag_to_mflag(BMVert *v)
{
const char hflag = v->head.hflag;
return (((hflag & BM_ELEM_SELECT) ? SELECT : 0) | ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0));
return (((hflag & BM_ELEM_SELECT) ? SELECT : 0));
}
short BM_edge_flag_to_mflag(BMEdge *e)
@ -743,7 +750,6 @@ short BM_edge_flag_to_mflag(BMEdge *e)
return (((hflag & BM_ELEM_SELECT) ? SELECT : 0) | ((hflag & BM_ELEM_SEAM) ? ME_SEAM : 0) |
((hflag & BM_ELEM_DRAW) ? ME_EDGEDRAW : 0) |
((hflag & BM_ELEM_SMOOTH) == 0 ? ME_SHARP : 0) |
((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0) |
(BM_edge_is_wire(e) ? ME_LOOSEEDGE : 0) | /* not typical */
ME_EDGERENDER);
}
@ -752,5 +758,5 @@ char BM_face_flag_to_mflag(BMFace *f)
const char hflag = f->head.hflag;
return (((hflag & BM_ELEM_SELECT) ? ME_FACE_SEL : 0) |
((hflag & BM_ELEM_SMOOTH) ? ME_SMOOTH : 0) | ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0));
((hflag & BM_ELEM_SMOOTH) ? ME_SMOOTH : 0));
}

View File

@ -83,7 +83,10 @@
#include "BLI_listbase.h"
#include "BLI_math_vector.h"
#include "BLI_span.hh"
#include "BLI_string_ref.hh"
#include "BLI_task.hh"
#include "BKE_attribute.hh"
#include "BKE_customdata.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
@ -103,7 +106,9 @@ static CLG_LogRef LOG = {"bmesh.mesh.convert"};
using blender::Array;
using blender::IndexRange;
using blender::MutableSpan;
using blender::Span;
using blender::StringRef;
void BM_mesh_cd_flag_ensure(BMesh *bm, Mesh *mesh, const char cd_flag)
{
@ -212,10 +217,10 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
if (!me || !me->totvert) {
if (me && is_new) { /* No verts? still copy custom-data layout. */
CustomData_copy(&me->vdata, &bm->vdata, mask.vmask, CD_DEFAULT, 0);
CustomData_copy(&me->edata, &bm->edata, mask.emask, CD_DEFAULT, 0);
CustomData_copy(&me->ldata, &bm->ldata, mask.lmask, CD_DEFAULT, 0);
CustomData_copy(&me->pdata, &bm->pdata, mask.pmask, CD_DEFAULT, 0);
CustomData_copy_mesh_to_bmesh(&me->vdata, &bm->vdata, mask.vmask, CD_DEFAULT, 0);
CustomData_copy_mesh_to_bmesh(&me->edata, &bm->edata, mask.emask, CD_DEFAULT, 0);
CustomData_copy_mesh_to_bmesh(&me->ldata, &bm->ldata, mask.lmask, CD_DEFAULT, 0);
CustomData_copy_mesh_to_bmesh(&me->pdata, &bm->pdata, mask.pmask, CD_DEFAULT, 0);
CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT);
CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE);
@ -231,10 +236,10 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
}
if (is_new) {
CustomData_copy(&me->vdata, &bm->vdata, mask.vmask, CD_CALLOC, 0);
CustomData_copy(&me->edata, &bm->edata, mask.emask, CD_CALLOC, 0);
CustomData_copy(&me->ldata, &bm->ldata, mask.lmask, CD_CALLOC, 0);
CustomData_copy(&me->pdata, &bm->pdata, mask.pmask, CD_CALLOC, 0);
CustomData_copy_mesh_to_bmesh(&me->vdata, &bm->vdata, mask.vmask, CD_CALLOC, 0);
CustomData_copy_mesh_to_bmesh(&me->edata, &bm->edata, mask.emask, CD_CALLOC, 0);
CustomData_copy_mesh_to_bmesh(&me->ldata, &bm->ldata, mask.lmask, CD_CALLOC, 0);
CustomData_copy_mesh_to_bmesh(&me->pdata, &bm->pdata, mask.pmask, CD_CALLOC, 0);
}
else {
CustomData_bmesh_merge(&me->vdata, &bm->vdata, mask.vmask, CD_CALLOC, bm, BM_VERT);
@ -352,6 +357,13 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX) :
-1;
const bool *hide_vert = (const bool *)CustomData_get_layer_named(
&me->vdata, CD_PROP_BOOL, ".hide_vert");
const bool *hide_edge = (const bool *)CustomData_get_layer_named(
&me->edata, CD_PROP_BOOL, ".hide_edge");
const bool *hide_poly = (const bool *)CustomData_get_layer_named(
&me->pdata, CD_PROP_BOOL, ".hide_poly");
Span<MVert> mvert{me->mvert, me->totvert};
Array<BMVert *> vtable(me->totvert);
for (const int i : mvert.index_range()) {
@ -361,6 +373,9 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
/* Transfer flag. */
v->head.hflag = BM_vert_flag_from_mflag(mvert[i].flag & ~SELECT);
if (hide_vert && hide_vert[i]) {
BM_elem_flag_enable(v, BM_ELEM_HIDDEN);
}
/* This is necessary for selection counts to work properly. */
if (mvert[i].flag & SELECT) {
@ -404,6 +419,9 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
/* Transfer flags. */
e->head.hflag = BM_edge_flag_from_mflag(medge[i].flag & ~SELECT);
if (hide_edge && hide_edge[i]) {
BM_elem_flag_enable(e, BM_ELEM_HIDDEN);
}
/* This is necessary for selection counts to work properly. */
if (medge[i].flag & SELECT) {
@ -457,6 +475,9 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
/* Transfer flag. */
f->head.hflag = BM_face_flag_from_mflag(mpoly[i].flag & ~ME_FACE_SEL);
if (hide_poly && hide_poly[i]) {
BM_elem_flag_enable(f, BM_ELEM_HIDDEN);
}
/* This is necessary for selection counts to work properly. */
if (mpoly[i].flag & ME_FACE_SEL) {
@ -902,6 +923,63 @@ BLI_INLINE void bmesh_quick_edgedraw_flag(MEdge *med, BMEdge *e)
}
}
template<typename GetFn>
static void write_elem_flag_to_attribute(blender::bke::MutableAttributeAccessor &attributes,
const StringRef attribute_name,
const eAttrDomain domain,
const bool do_write,
const GetFn &get_fn)
{
using namespace blender;
if (do_write) {
bke::SpanAttributeWriter<bool> attribute = attributes.lookup_or_add_for_write_only_span<bool>(
attribute_name, domain);
threading::parallel_for(attribute.span.index_range(), 4096, [&](IndexRange range) {
for (const int i : range) {
attribute.span[i] = get_fn(i);
}
});
attribute.finish();
}
else {
/* To avoid overhead, remove the hide attribute if possible. */
attributes.remove(attribute_name);
}
}
static void convert_bmesh_hide_flags_to_mesh_attributes(BMesh &bm,
const bool need_hide_vert,
const bool need_hide_edge,
const bool need_hide_face,
Mesh &mesh)
{
using namespace blender;
/* The "hide" attributes are stored as flags on #BMesh. */
BLI_assert(CustomData_get_layer_named(&bm.vdata, CD_PROP_BOOL, ".hide_vert") == nullptr);
BLI_assert(CustomData_get_layer_named(&bm.edata, CD_PROP_BOOL, ".hide_edge") == nullptr);
BLI_assert(CustomData_get_layer_named(&bm.pdata, CD_PROP_BOOL, ".hide_poly") == nullptr);
if (!(need_hide_vert || need_hide_edge || need_hide_face)) {
return;
}
bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(mesh);
BM_mesh_elem_table_ensure(&bm, BM_VERT | BM_EDGE | BM_FACE);
write_elem_flag_to_attribute(
attributes, ".hide_vert", ATTR_DOMAIN_POINT, need_hide_vert, [&](const int i) {
return BM_elem_flag_test(BM_vert_at_index(&bm, i), BM_ELEM_HIDDEN);
});
write_elem_flag_to_attribute(
attributes, ".hide_edge", ATTR_DOMAIN_EDGE, need_hide_edge, [&](const int i) {
return BM_elem_flag_test(BM_edge_at_index(&bm, i), BM_ELEM_HIDDEN);
});
write_elem_flag_to_attribute(
attributes, ".hide_poly", ATTR_DOMAIN_FACE, need_hide_face, [&](const int i) {
return BM_elem_flag_test(BM_face_at_index(&bm, i), BM_ELEM_HIDDEN);
});
}
void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMeshParams *params)
{
MEdge *med;
@ -938,10 +1016,10 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
{
CustomData_MeshMasks mask = CD_MASK_MESH;
CustomData_MeshMasks_update(&mask, &params->cd_mask_extra);
CustomData_copy(&bm->vdata, &me->vdata, mask.vmask, CD_CALLOC, me->totvert);
CustomData_copy(&bm->edata, &me->edata, mask.emask, CD_CALLOC, me->totedge);
CustomData_copy(&bm->ldata, &me->ldata, mask.lmask, CD_CALLOC, me->totloop);
CustomData_copy(&bm->pdata, &me->pdata, mask.pmask, CD_CALLOC, me->totpoly);
CustomData_copy_mesh_to_bmesh(&bm->vdata, &me->vdata, mask.vmask, CD_CALLOC, me->totvert);
CustomData_copy_mesh_to_bmesh(&bm->edata, &me->edata, mask.emask, CD_CALLOC, me->totedge);
CustomData_copy_mesh_to_bmesh(&bm->ldata, &me->ldata, mask.lmask, CD_CALLOC, me->totloop);
CustomData_copy_mesh_to_bmesh(&bm->pdata, &me->pdata, mask.pmask, CD_CALLOC, me->totpoly);
}
MVert *mvert = bm->totvert ? (MVert *)MEM_callocN(sizeof(MVert) * bm->totvert, "bm_to_me.vert") :
@ -958,6 +1036,10 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, mloop, me->totloop);
CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, mpoly, me->totpoly);
bool need_hide_vert = false;
bool need_hide_edge = false;
bool need_hide_face = false;
/* Clear normals on the mesh completely, since the original vertex and polygon count might be
* different than the BMesh's. */
BKE_mesh_clear_derived_normals(me);
@ -972,6 +1054,9 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
copy_v3_v3(mvert->co, v->co);
mvert->flag = BM_vert_flag_to_mflag(v);
if (BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
need_hide_vert = true;
}
BM_elem_index_set(v, i); /* set_inline */
@ -996,6 +1081,9 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
med->v2 = BM_elem_index_get(e->v2);
med->flag = BM_edge_flag_to_mflag(e);
if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
need_hide_edge = true;
}
BM_elem_index_set(e, i); /* set_inline */
@ -1025,6 +1113,9 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
mpoly->totloop = f->len;
mpoly->mat_nr = f->mat_nr;
mpoly->flag = BM_face_flag_to_mflag(f);
if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
need_hide_face = true;
}
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
@ -1117,6 +1208,9 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
}
}
convert_bmesh_hide_flags_to_mesh_attributes(
*bm, need_hide_vert, need_hide_edge, need_hide_face, *me);
BKE_mesh_update_customdata_pointers(me, false);
{
@ -1210,6 +1304,10 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
bool need_hide_vert = false;
bool need_hide_edge = false;
bool need_hide_face = false;
/* Clear normals on the mesh completely, since the original vertex and polygon count might be
* different than the BMesh's. */
BKE_mesh_clear_derived_normals(me);
@ -1224,6 +1322,13 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
BM_elem_index_set(eve, i); /* set_inline */
mv->flag = BM_vert_flag_to_mflag(eve);
if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
need_hide_vert = true;
}
if (cd_vert_bweight_offset != -1) {
mv->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset);
}
if (cd_vert_bweight_offset != -1) {
mv->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset);
@ -1242,6 +1347,9 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
med->v2 = BM_elem_index_get(eed->v2);
med->flag = BM_edge_flag_to_mflag(eed);
if (BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
need_hide_edge = true;
}
/* Handle this differently to editmode switching,
* only enable draw for single user edges rather than calculating angle. */
@ -1272,6 +1380,10 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
mp->totloop = efa->len;
mp->flag = BM_face_flag_to_mflag(efa);
if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
need_hide_face = true;
}
mp->loopstart = j;
mp->mat_nr = efa->mat_nr;
@ -1291,5 +1403,8 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
}
bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP);
convert_bmesh_hide_flags_to_mesh_attributes(
*bm, need_hide_vert, need_hide_edge, need_hide_face, *me);
me->cd_flag = BM_mesh_cd_flag_from_bmesh(bm);
}

View File

@ -228,9 +228,9 @@ static void mesh_render_data_polys_sorted_build(MeshRenderData *mr, MeshBufferCa
}
}
else {
const MPoly *mp = &mr->mpoly[0];
for (int i = 0; i < mr->poly_len; i++, mp++) {
if (!(mr->use_hide && (mp->flag & ME_HIDE))) {
for (int i = 0; i < mr->poly_len; i++) {
if (!(mr->use_hide && mr->hide_poly && mr->hide_poly[i])) {
const MPoly *mp = &mr->mpoly[i];
const int mat = min_ii(mp->mat_nr, mat_last);
tri_first_index[i] = mat_tri_offs[mat];
mat_tri_offs[mat] += mp->totloop - 2;
@ -269,7 +269,7 @@ static void mesh_render_data_mat_tri_len_mesh_range_fn(void *__restrict userdata
int *mat_tri_len = static_cast<int *>(tls->userdata_chunk);
const MPoly *mp = &mr->mpoly[iter];
if (!(mr->use_hide && (mp->flag & ME_HIDE))) {
if (!(mr->use_hide && mr->hide_poly && mr->hide_poly[iter])) {
int mat = min_ii(mp->mat_nr, mr->mat_len - 1);
mat_tri_len[mat] += mp->totloop - 2;
}
@ -578,6 +578,13 @@ MeshRenderData *mesh_render_data_create(Object *object,
mr->v_origindex = static_cast<const int *>(CustomData_get_layer(&mr->me->vdata, CD_ORIGINDEX));
mr->e_origindex = static_cast<const int *>(CustomData_get_layer(&mr->me->edata, CD_ORIGINDEX));
mr->p_origindex = static_cast<const int *>(CustomData_get_layer(&mr->me->pdata, CD_ORIGINDEX));
mr->hide_vert = static_cast<const bool *>(
CustomData_get_layer_named(&me->vdata, CD_PROP_BOOL, ".hide_vert"));
mr->hide_edge = static_cast<const bool *>(
CustomData_get_layer_named(&me->edata, CD_PROP_BOOL, ".hide_edge"));
mr->hide_poly = static_cast<const bool *>(
CustomData_get_layer_named(&me->pdata, CD_PROP_BOOL, ".hide_poly"));
}
else {
/* #BMesh */

View File

@ -668,7 +668,9 @@ static void draw_subdiv_cache_extra_coarse_face_data_bm(BMesh *bm,
}
}
static void draw_subdiv_cache_extra_coarse_face_data_mesh(Mesh *mesh, uint32_t *flags_data)
static void draw_subdiv_cache_extra_coarse_face_data_mesh(const MeshRenderData *mr,
Mesh *mesh,
uint32_t *flags_data)
{
for (int i = 0; i < mesh->totpoly; i++) {
uint32_t flag = 0;
@ -678,7 +680,7 @@ static void draw_subdiv_cache_extra_coarse_face_data_mesh(Mesh *mesh, uint32_t *
if ((mesh->mpoly[i].flag & ME_FACE_SEL) != 0) {
flag |= SUBDIV_COARSE_FACE_FLAG_SELECT;
}
if ((mesh->mpoly[i].flag & ME_HIDE) != 0) {
if (mr->hide_poly && mr->hide_poly[i]) {
flag |= SUBDIV_COARSE_FACE_FLAG_HIDDEN;
}
flags_data[i] = (uint)(mesh->mpoly[i].loopstart) | (flag << SUBDIV_COARSE_FACE_FLAG_OFFSET);
@ -691,7 +693,7 @@ static void draw_subdiv_cache_extra_coarse_face_data_mapped(Mesh *mesh,
uint32_t *flags_data)
{
if (bm == nullptr) {
draw_subdiv_cache_extra_coarse_face_data_mesh(mesh, flags_data);
draw_subdiv_cache_extra_coarse_face_data_mesh(mr, mesh, flags_data);
return;
}
@ -726,7 +728,7 @@ static void draw_subdiv_cache_update_extra_coarse_face_data(DRWSubdivCache *cach
draw_subdiv_cache_extra_coarse_face_data_mapped(mesh, cache->bm, mr, flags_data);
}
else {
draw_subdiv_cache_extra_coarse_face_data_mesh(mesh, flags_data);
draw_subdiv_cache_extra_coarse_face_data_mesh(mr, mesh, flags_data);
}
/* Make sure updated data is re-uploaded. */

View File

@ -83,6 +83,9 @@ struct MeshRenderData {
MLoopTri *mlooptri;
const float (*vert_normals)[3];
const float (*poly_normals)[3];
const bool *hide_vert;
const bool *hide_edge;
const bool *hide_poly;
float (*loop_normals)[3];
int *lverts, *ledges;

View File

@ -61,7 +61,7 @@ static void extract_edituv_tris_iter_looptri_mesh(const MeshRenderData *mr,
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
const MPoly *mp = &mr->mpoly[mlt->poly];
edituv_tri_add(data,
(mp->flag & ME_HIDE) != 0,
mr->hide_poly && mr->hide_poly[mlt->poly],
(mp->flag & ME_FACE_SEL) != 0,
mlt->tri[0],
mlt->tri[1],
@ -117,7 +117,7 @@ static void extract_edituv_tris_iter_subdiv_bm(const DRWSubdivCache *UNUSED(subd
}
static void extract_edituv_tris_iter_subdiv_mesh(const DRWSubdivCache *UNUSED(subdiv_cache),
const MeshRenderData *UNUSED(mr),
const MeshRenderData *mr,
void *_data,
uint subdiv_quad_index,
const MPoly *coarse_quad)
@ -125,19 +125,13 @@ static void extract_edituv_tris_iter_subdiv_mesh(const DRWSubdivCache *UNUSED(su
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
const uint loop_idx = subdiv_quad_index * 4;
edituv_tri_add(data,
(coarse_quad->flag & ME_HIDE) != 0,
(coarse_quad->flag & ME_FACE_SEL) != 0,
loop_idx,
loop_idx + 1,
loop_idx + 2);
const bool hidden = mr->hide_poly && mr->hide_poly[coarse_quad - mr->mpoly];
edituv_tri_add(data,
(coarse_quad->flag & ME_HIDE) != 0,
(coarse_quad->flag & ME_FACE_SEL) != 0,
loop_idx,
loop_idx + 2,
loop_idx + 3);
edituv_tri_add(
data, hidden, (coarse_quad->flag & ME_FACE_SEL) != 0, loop_idx, loop_idx + 1, loop_idx + 2);
edituv_tri_add(
data, hidden, (coarse_quad->flag & ME_FACE_SEL) != 0, loop_idx, loop_idx + 2, loop_idx + 3);
}
static void extract_edituv_tris_finish_subdiv(const struct DRWSubdivCache *UNUSED(subdiv_cache),
@ -218,6 +212,8 @@ static void extract_edituv_lines_iter_poly_mesh(const MeshRenderData *mr,
void *_data)
{
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
const bool hidden = mr->hide_poly && mr->hide_poly[mp - mr->mpoly];
const MLoop *mloop = mr->mloop;
const int ml_index_end = mp->loopstart + mp->totloop;
for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
@ -227,11 +223,8 @@ static void extract_edituv_lines_iter_poly_mesh(const MeshRenderData *mr,
const int ml_index_next = (ml_index == ml_index_last) ? mp->loopstart : (ml_index + 1);
const bool real_edge = (mr->e_origindex == nullptr ||
mr->e_origindex[ml->e] != ORIGINDEX_NONE);
edituv_edge_add(data,
(mp->flag & ME_HIDE) != 0 || !real_edge,
(mp->flag & ME_FACE_SEL) != 0,
ml_index,
ml_index_next);
edituv_edge_add(
data, hidden || !real_edge, (mp->flag & ME_FACE_SEL) != 0, ml_index, ml_index_next);
}
}
@ -288,6 +281,8 @@ static void extract_edituv_lines_iter_subdiv_mesh(const DRWSubdivCache *subdiv_c
const MPoly *coarse_poly)
{
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
const bool hidden = mr->hide_poly && mr->hide_poly[coarse_poly - mr->mpoly];
int *subdiv_loop_edge_index = (int *)GPU_vertbuf_get_data(subdiv_cache->edges_orig_index);
uint start_loop_idx = subdiv_quad_index * 4;
@ -298,7 +293,7 @@ static void extract_edituv_lines_iter_subdiv_mesh(const DRWSubdivCache *subdiv_c
(mr->e_origindex == nullptr ||
mr->e_origindex[edge_origindex] != ORIGINDEX_NONE));
edituv_edge_add(data,
(coarse_poly->flag & ME_HIDE) != 0 || !real_edge,
hidden || !real_edge,
(coarse_poly->flag & ME_FACE_SEL) != 0,
loop_idx,
(loop_idx + 1 == end_loop_idx) ? start_loop_idx : (loop_idx + 1));
@ -382,14 +377,15 @@ static void extract_edituv_points_iter_poly_mesh(const MeshRenderData *mr,
void *_data)
{
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
const bool hidden = mr->hide_poly && mr->hide_poly[mp - mr->mpoly];
const MLoop *mloop = mr->mloop;
const int ml_index_end = mp->loopstart + mp->totloop;
for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
const MLoop *ml = &mloop[ml_index];
const bool real_vert = !mr->v_origindex || mr->v_origindex[ml->v] != ORIGINDEX_NONE;
edituv_point_add(
data, ((mp->flag & ME_HIDE) != 0) || !real_vert, (mp->flag & ME_FACE_SEL) != 0, ml_index);
edituv_point_add(data, hidden || !real_vert, (mp->flag & ME_FACE_SEL) != 0, ml_index);
}
}
@ -442,6 +438,7 @@ static void extract_edituv_points_iter_subdiv_mesh(const DRWSubdivCache *subdiv_
const MPoly *coarse_quad)
{
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
const bool hidden = mr->hide_poly && mr->hide_poly[coarse_quad - mr->mpoly];
int *subdiv_loop_vert_index = (int *)GPU_vertbuf_get_data(subdiv_cache->verts_orig_index);
uint start_loop_idx = subdiv_quad_index * 4;
@ -450,10 +447,7 @@ static void extract_edituv_points_iter_subdiv_mesh(const DRWSubdivCache *subdiv_
const int vert_origindex = subdiv_loop_vert_index[i];
const bool real_vert = !mr->v_origindex || (vert_origindex != -1 &&
mr->v_origindex[vert_origindex] != ORIGINDEX_NONE);
edituv_point_add(data,
((coarse_quad->flag & ME_HIDE) != 0) || !real_vert,
(coarse_quad->flag & ME_FACE_SEL) != 0,
i);
edituv_point_add(data, hidden || !real_vert, (coarse_quad->flag & ME_FACE_SEL) != 0, i);
}
}
@ -533,6 +527,8 @@ static void extract_edituv_fdots_iter_poly_mesh(const MeshRenderData *mr,
void *_data)
{
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
const bool hidden = mr->hide_poly && mr->hide_poly[mp - mr->mpoly];
if (mr->use_subsurf_fdots) {
const BLI_bitmap *facedot_tags = mr->me->runtime.subsurf_face_dot_tags;
@ -543,16 +539,13 @@ static void extract_edituv_fdots_iter_poly_mesh(const MeshRenderData *mr,
const bool real_fdot = !mr->p_origindex || (mr->p_origindex[mp_index] != ORIGINDEX_NONE);
const bool subd_fdot = BLI_BITMAP_TEST(facedot_tags, ml->v);
edituv_facedot_add(data,
((mp->flag & ME_HIDE) != 0) || !real_fdot || !subd_fdot,
(mp->flag & ME_FACE_SEL) != 0,
mp_index);
edituv_facedot_add(
data, hidden || !real_fdot || !subd_fdot, (mp->flag & ME_FACE_SEL) != 0, mp_index);
}
}
else {
const bool real_fdot = !mr->p_origindex || (mr->p_origindex[mp_index] != ORIGINDEX_NONE);
edituv_facedot_add(
data, ((mp->flag & ME_HIDE) != 0) || !real_fdot, (mp->flag & ME_FACE_SEL) != 0, mp_index);
edituv_facedot_add(data, hidden || !real_fdot, (mp->flag & ME_FACE_SEL) != 0, mp_index);
}
}

View File

@ -42,6 +42,8 @@ static void extract_fdots_iter_poly_mesh(const MeshRenderData *mr,
const int mp_index,
void *_userdata)
{
const bool hidden = mr->use_hide && mr->hide_poly && mr->hide_poly[mp - mr->mpoly];
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_userdata);
if (mr->use_subsurf_fdots) {
const BLI_bitmap *facedot_tags = mr->me->runtime.subsurf_face_dot_tags;
@ -50,7 +52,7 @@ static void extract_fdots_iter_poly_mesh(const MeshRenderData *mr,
const int ml_index_end = mp->loopstart + mp->totloop;
for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
const MLoop *ml = &mloop[ml_index];
if (BLI_BITMAP_TEST(facedot_tags, ml->v) && !(mr->use_hide && (mp->flag & ME_HIDE))) {
if (BLI_BITMAP_TEST(facedot_tags, ml->v) && !hidden) {
GPU_indexbuf_set_point_vert(elb, mp_index, mp_index);
return;
}
@ -58,7 +60,7 @@ static void extract_fdots_iter_poly_mesh(const MeshRenderData *mr,
GPU_indexbuf_set_point_restart(elb, mp_index);
}
else {
if (!(mr->use_hide && (mp->flag & ME_HIDE))) {
if (!hidden) {
GPU_indexbuf_set_point_vert(elb, mp_index, mp_index);
}
else {

View File

@ -58,14 +58,12 @@ static void extract_lines_iter_poly_mesh(const MeshRenderData *mr,
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(data);
/* Using poly & loop iterator would complicate accessing the adjacent loop. */
const MLoop *mloop = mr->mloop;
const MEdge *medge = mr->medge;
if (mr->use_hide || (mr->extract_type == MR_EXTRACT_MAPPED) || (mr->e_origindex != nullptr)) {
const int ml_index_last = mp->loopstart + (mp->totloop - 1);
int ml_index = ml_index_last, ml_index_next = mp->loopstart;
do {
const MLoop *ml = &mloop[ml_index];
const MEdge *med = &medge[ml->e];
if (!((mr->use_hide && (med->flag & ME_HIDE)) ||
if (!((mr->use_hide && mr->hide_edge && mr->hide_edge[ml->e]) ||
((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) &&
(mr->e_origindex[ml->e] == ORIGINDEX_NONE)))) {
GPU_indexbuf_set_line_verts(elb, ml->e, ml_index, ml_index_next);
@ -111,7 +109,7 @@ static void extract_lines_iter_ledge_mesh(const MeshRenderData *mr,
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(data);
const int l_index_offset = mr->edge_len + ledge_index;
const int e_index = mr->ledges[ledge_index];
if (!((mr->use_hide && (med->flag & ME_HIDE)) ||
if (!((mr->use_hide && mr->hide_edge && mr->hide_edge[med - mr->medge]) ||
((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) &&
(mr->e_origindex[e_index] == ORIGINDEX_NONE)))) {
const int l_index = mr->loop_len + ledge_index * 2;
@ -185,9 +183,14 @@ static void extract_lines_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
switch (mr->extract_type) {
case MR_EXTRACT_MESH: {
const MEdge *medge = mr->medge;
for (DRWSubdivLooseEdge edge : loose_edges) {
*flags_data++ = (medge[edge.coarse_edge_index].flag & ME_HIDE) != 0;
const bool *hide_vert = mr->hide_vert;
if (hide_vert) {
for (DRWSubdivLooseEdge edge : loose_edges) {
*flags_data++ = hide_vert[edge.coarse_edge_index];
}
}
else {
MutableSpan<uint>(flags_data, loose_edges.size()).fill(0);
}
break;
}
@ -199,18 +202,23 @@ static void extract_lines_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
}
}
else {
for (DRWSubdivLooseEdge edge : loose_edges) {
int e = edge.coarse_edge_index;
const bool *hide_vert = mr->hide_vert;
if (hide_vert) {
for (DRWSubdivLooseEdge edge : loose_edges) {
int e = edge.coarse_edge_index;
if (mr->e_origindex && mr->e_origindex[e] != ORIGINDEX_NONE) {
*flags_data++ = (mr->medge[mr->e_origindex[e]].flag & ME_HIDE) != 0;
}
else {
*flags_data++ = false;
if (mr->e_origindex && mr->e_origindex[e] != ORIGINDEX_NONE) {
*flags_data++ = hide_vert[edge.coarse_edge_index];
}
else {
*flags_data++ = false;
}
}
}
else {
MutableSpan<uint>(flags_data, loose_edges.size()).fill(0);
}
}
break;
}
case MR_EXTRACT_BMESH: {

View File

@ -119,16 +119,17 @@ static void extract_lines_adjacency_iter_looptri_mesh(const MeshRenderData *mr,
void *_data)
{
MeshExtract_LineAdjacency_Data *data = static_cast<MeshExtract_LineAdjacency_Data *>(_data);
const MPoly *mp = &mr->mpoly[mlt->poly];
if (!(mr->use_hide && (mp->flag & ME_HIDE))) {
lines_adjacency_triangle(mr->mloop[mlt->tri[0]].v,
mr->mloop[mlt->tri[1]].v,
mr->mloop[mlt->tri[2]].v,
mlt->tri[0],
mlt->tri[1],
mlt->tri[2],
data);
const bool hidden = mr->use_hide && mr->hide_poly && mr->hide_poly[mlt->poly];
if (hidden) {
return;
}
lines_adjacency_triangle(mr->mloop[mlt->tri[0]].v,
mr->mloop[mlt->tri[1]].v,
mr->mloop[mlt->tri[2]].v,
mlt->tri[0],
mlt->tri[1],
mlt->tri[2],
data);
}
static void extract_lines_adjacency_finish(const MeshRenderData *UNUSED(mr),

View File

@ -47,8 +47,7 @@ static void extract_lines_paint_mask_iter_poly_mesh(const MeshRenderData *mr,
const MLoop *ml = &mloop[ml_index];
const int e_index = ml->e;
const MEdge *me = &mr->medge[e_index];
if (!((mr->use_hide && (me->flag & ME_HIDE)) ||
if (!((mr->use_hide && mr->hide_edge && mr->hide_edge[e_index]) ||
((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) &&
(mr->e_origindex[e_index] == ORIGINDEX_NONE)))) {
@ -122,8 +121,7 @@ static void extract_lines_paint_mask_iter_subdiv_mesh(const DRWSubdivCache *subd
GPU_indexbuf_set_line_restart(&data->elb, subdiv_edge_index);
}
else {
const MEdge *me = &mr->medge[coarse_edge_index];
if (!((mr->use_hide && (me->flag & ME_HIDE)) ||
if (!((mr->use_hide && mr->hide_edge && mr->hide_edge[coarse_edge_index]) ||
((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) &&
(mr->e_origindex[coarse_edge_index] == ORIGINDEX_NONE)))) {
const uint ml_index_other = (loop_idx == (end_loop_idx - 1)) ? start_loop_idx :

View File

@ -43,10 +43,10 @@ BLI_INLINE void vert_set_mesh(GPUIndexBufBuilder *elb,
const int v_index,
const int l_index)
{
const MVert *mv = &mr->mvert[v_index];
if (!((mr->use_hide && (mv->flag & ME_HIDE)) ||
((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) &&
(mr->v_origindex[v_index] == ORIGINDEX_NONE)))) {
const bool hidden = mr->use_hide && mr->hide_vert && mr->hide_vert[v_index];
if (!(hidden || ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) &&
(mr->v_origindex[v_index] == ORIGINDEX_NONE)))) {
GPU_indexbuf_set_point_vert(elb, v_index, l_index);
}
else {
@ -181,8 +181,7 @@ static void extract_points_iter_subdiv_common(GPUIndexBufBuilder *elb,
}
}
else {
const MVert *mv = &mr->mvert[coarse_vertex_index];
if (mr->use_hide && (mv->flag & ME_HIDE)) {
if (mr->use_hide && mr->hide_vert && mr->hide_vert[coarse_vertex_index]) {
GPU_indexbuf_set_point_restart(elb, coarse_vertex_index);
continue;
}

View File

@ -189,12 +189,12 @@ static void extract_tris_single_mat_iter_looptri_mesh(const MeshRenderData *mr,
void *_data)
{
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_data);
const MPoly *mp = &mr->mpoly[mlt->poly];
if (!(mr->use_hide && (mp->flag & ME_HIDE))) {
GPU_indexbuf_set_tri_verts(elb, mlt_index, mlt->tri[0], mlt->tri[1], mlt->tri[2]);
const bool hidden = mr->use_hide && mr->hide_poly && mr->hide_poly[mlt->poly];
if (hidden) {
GPU_indexbuf_set_tri_restart(elb, mlt_index);
}
else {
GPU_indexbuf_set_tri_restart(elb, mlt_index);
GPU_indexbuf_set_tri_verts(elb, mlt_index, mlt->tri[0], mlt->tri[1], mlt->tri[2]);
}
}

View File

@ -62,6 +62,8 @@ static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr,
const int mp_index,
void *data)
{
const bool hidden = mr->hide_poly && mr->hide_poly[mp_index];
const MLoop *mloop = mr->mloop;
const int ml_index_end = mp->loopstart + mp->totloop;
for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
@ -80,8 +82,8 @@ static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr,
/* Flag for paint mode overlay.
* Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals.
* In paint mode it will use the un-mapped data to draw the wire-frame. */
if (mp->flag & ME_HIDE || (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED &&
(mr->v_origindex) && mr->v_origindex[ml->v] == ORIGINDEX_NONE)) {
if (hidden || (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) &&
mr->v_origindex[ml->v] == ORIGINDEX_NONE)) {
lnor_data->w = -1;
}
else if (mp->flag & ME_FACE_SEL) {
@ -185,6 +187,8 @@ static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr,
const int mp_index,
void *data)
{
const bool hidden = mr->hide_poly && mr->hide_poly[mp_index];
const MLoop *mloop = mr->mloop;
const int ml_index_end = mp->loopstart + mp->totloop;
for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
@ -203,8 +207,8 @@ static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr,
/* Flag for paint mode overlay.
* Only use #MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals.
* In paint mode it will use the un-mapped data to draw the wire-frame. */
if (mp->flag & ME_HIDE || (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED &&
(mr->v_origindex) && mr->v_origindex[ml->v] == ORIGINDEX_NONE)) {
if (hidden || (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) &&
mr->v_origindex[ml->v] == ORIGINDEX_NONE)) {
lnor_data->w = -1;
}
else if (mp->flag & ME_FACE_SEL) {

View File

@ -83,10 +83,11 @@ static void extract_pos_nor_iter_poly_bm(const MeshRenderData *mr,
static void extract_pos_nor_iter_poly_mesh(const MeshRenderData *mr,
const MPoly *mp,
const int UNUSED(mp_index),
const int mp_index,
void *_data)
{
MeshExtract_PosNor_Data *data = static_cast<MeshExtract_PosNor_Data *>(_data);
const bool face_hidden = mr->hide_poly && mr->hide_poly[mp_index];
const MLoop *mloop = mr->mloop;
const int ml_index_end = mp->loopstart + mp->totloop;
@ -95,10 +96,11 @@ static void extract_pos_nor_iter_poly_mesh(const MeshRenderData *mr,
PosNorLoop *vert = &data->vbo_data[ml_index];
const MVert *mv = &mr->mvert[ml->v];
const bool vert_hidden = mr->hide_vert && mr->hide_vert[ml->v];
copy_v3_v3(vert->pos, mv->co);
vert->nor = data->normals[ml->v].low;
/* Flag for paint mode overlay. */
if (mp->flag & ME_HIDE || mv->flag & ME_HIDE ||
if (face_hidden || vert_hidden ||
((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) &&
(mr->v_origindex[ml->v] == ORIGINDEX_NONE))) {
vert->nor.w = -1;
@ -432,18 +434,21 @@ static void extract_pos_nor_hq_iter_poly_mesh(const MeshRenderData *mr,
void *_data)
{
MeshExtract_PosNorHQ_Data *data = static_cast<MeshExtract_PosNorHQ_Data *>(_data);
const bool face_hidden = mr->hide_poly && mr->hide_poly[mp - mr->mpoly];
const MLoop *mloop = mr->mloop;
const int ml_index_end = mp->loopstart + mp->totloop;
for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
const MLoop *ml = &mloop[ml_index];
const bool vert_hidden = mr->hide_vert && mr->hide_vert[ml->v];
PosNorHQLoop *vert = &data->vbo_data[ml_index];
const MVert *mv = &mr->mvert[ml->v];
copy_v3_v3(vert->pos, mv->co);
copy_v3_v3_short(vert->nor, data->normals[ml->v].high);
/* Flag for paint mode overlay. */
if (mp->flag & ME_HIDE || mv->flag & ME_HIDE ||
if (face_hidden || vert_hidden ||
((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) &&
(mr->v_origindex[ml->v] == ORIGINDEX_NONE))) {
vert->nor[3] = -1;

View File

@ -390,7 +390,10 @@ void ED_keymap_mesh(struct wmKeyConfig *keyconf);
* Copy the face flags, most importantly selection from the mesh to the final derived mesh,
* use in object mode when selecting faces (while painting).
*/
void paintface_flush_flags(struct bContext *C, struct Object *ob, short flag);
void paintface_flush_flags(struct bContext *C,
struct Object *ob,
bool flush_selection,
bool flush_hidden);
/**
* \return True when pick finds an element or the selection changed.
*/

View File

@ -17,6 +17,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "BKE_attribute.hh"
#include "BKE_context.h"
#include "BKE_customdata.h"
#include "BKE_global.h"
@ -36,14 +37,18 @@
/* own include */
void paintface_flush_flags(bContext *C, Object *ob, short flag)
void paintface_flush_flags(bContext *C,
Object *ob,
const bool flush_selection,
const bool flush_hidden)
{
using namespace blender;
Mesh *me = BKE_mesh_from_object(ob);
MPoly *polys, *mp_orig;
const int *index_array = nullptr;
int totpoly;
BLI_assert((flag & ~(SELECT | ME_HIDE)) == 0);
BLI_assert(flush_selection || flush_hidden);
if (me == nullptr) {
return;
@ -53,7 +58,7 @@ void paintface_flush_flags(bContext *C, Object *ob, short flag)
/* we could call this directly in all areas that change selection,
* since this could become slow for realtime updates (circle-select for eg) */
if (flag & SELECT) {
if (flush_selection) {
BKE_mesh_flush_select_from_polys(me);
}
@ -64,8 +69,11 @@ void paintface_flush_flags(bContext *C, Object *ob, short flag)
return;
}
bke::AttributeAccessor attributes_me = bke::mesh_attributes(*me);
Mesh *me_orig = (Mesh *)ob_eval->runtime.data_orig;
bke::MutableAttributeAccessor attributes_orig = bke::mesh_attributes_for_write(*me_orig);
Mesh *me_eval = (Mesh *)ob_eval->runtime.data_eval;
bke::MutableAttributeAccessor attributes_eval = bke::mesh_attributes_for_write(*me_eval);
bool updated = false;
if (me_orig != nullptr && me_eval != nullptr && me_orig->totpoly == me->totpoly) {
@ -73,13 +81,17 @@ void paintface_flush_flags(bContext *C, Object *ob, short flag)
for (int i = 0; i < me->totpoly; i++) {
me_orig->mpoly[i].flag = me->mpoly[i].flag;
}
/* If the mesh has only deform modifiers, the evaluated mesh shares arrays. */
if (me_eval->mpoly == me_orig->mpoly) {
updated = true;
if (flush_hidden) {
const VArray<bool> hide_face_me = attributes_me.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
bke::SpanAttributeWriter<bool> hide_face_orig =
attributes_orig.lookup_or_add_for_write_only_span<bool>(".hide_poly", ATTR_DOMAIN_FACE);
hide_face_me.materialize(hide_face_orig.span);
hide_face_orig.finish();
}
/* Mesh polys => Final derived polys */
else if ((index_array = (const int *)CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX))) {
if ((index_array = (const int *)CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX))) {
polys = me_eval->mpoly;
totpoly = me_eval->totpoly;
@ -91,13 +103,24 @@ void paintface_flush_flags(bContext *C, Object *ob, short flag)
polys[i].flag = mp_orig->flag;
}
}
const VArray<bool> hide_face_orig = attributes_orig.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
bke::SpanAttributeWriter<bool> hide_face_eval =
attributes_eval.lookup_or_add_for_write_only_span<bool>(".hide_poly", ATTR_DOMAIN_FACE);
for (const int i : IndexRange(me_eval->totpoly)) {
const int orig_face_index = index_array[i];
if (orig_face_index != ORIGINDEX_NONE) {
hide_face_eval.span[i] = hide_face_orig[orig_face_index];
}
}
hide_face_eval.finish();
updated = true;
}
}
if (updated) {
if (flag & ME_HIDE) {
if (flush_hidden) {
BKE_mesh_batch_cache_dirty_tag(me_eval, BKE_MESH_BATCH_DIRTY_ALL);
}
else {
@ -115,59 +138,79 @@ void paintface_flush_flags(bContext *C, Object *ob, short flag)
void paintface_hide(bContext *C, Object *ob, const bool unselected)
{
using namespace blender;
Mesh *me = BKE_mesh_from_object(ob);
if (me == nullptr || me->totpoly == 0) {
return;
}
bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me);
bke::SpanAttributeWriter<bool> hide_poly = attributes.lookup_or_add_for_write_span<bool>(
".hide_poly", ATTR_DOMAIN_FACE);
for (int i = 0; i < me->totpoly; i++) {
MPoly *mpoly = &me->mpoly[i];
if ((mpoly->flag & ME_HIDE) == 0) {
if (!hide_poly.span[i]) {
if (((mpoly->flag & ME_FACE_SEL) == 0) == unselected) {
mpoly->flag |= ME_HIDE;
hide_poly.span[i] = true;
}
}
if (mpoly->flag & ME_HIDE) {
if (hide_poly.span[i]) {
mpoly->flag &= ~ME_FACE_SEL;
}
}
hide_poly.finish();
BKE_mesh_flush_hidden_from_polys(me);
paintface_flush_flags(C, ob, SELECT | ME_HIDE);
paintface_flush_flags(C, ob, true, true);
}
void paintface_reveal(bContext *C, Object *ob, const bool select)
{
using namespace blender;
Mesh *me = BKE_mesh_from_object(ob);
if (me == nullptr || me->totpoly == 0) {
return;
}
for (int i = 0; i < me->totpoly; i++) {
MPoly *mpoly = &me->mpoly[i];
if (mpoly->flag & ME_HIDE) {
SET_FLAG_FROM_TEST(mpoly->flag, select, ME_FACE_SEL);
mpoly->flag &= ~ME_HIDE;
bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me);
if (select) {
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
for (int i = 0; i < me->totpoly; i++) {
MPoly *mpoly = &me->mpoly[i];
if (hide_poly[i]) {
mpoly->flag |= ME_FACE_SEL;
}
}
}
attributes.remove(".hide_poly");
BKE_mesh_flush_hidden_from_polys(me);
paintface_flush_flags(C, ob, SELECT | ME_HIDE);
paintface_flush_flags(C, ob, true, true);
}
/* Set object-mode face selection seams based on edge data, uses hash table to find seam edges. */
static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bool select)
{
using namespace blender;
bool do_it = true;
bool mark = false;
BLI_bitmap *edge_tag = BLI_BITMAP_NEW(me->totedge, __func__);
BLI_bitmap *poly_tag = BLI_BITMAP_NEW(me->totpoly, __func__);
bke::AttributeAccessor attributes = bke::mesh_attributes(*me);
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
if (index != (uint)-1) {
/* only put face under cursor in array */
MPoly *mp = &me->mpoly[index];
@ -178,7 +221,7 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo
/* fill array by selection */
for (int i = 0; i < me->totpoly; i++) {
MPoly *mp = &me->mpoly[i];
if (mp->flag & ME_HIDE) {
if (hide_poly[i]) {
/* pass */
}
else if (mp->flag & ME_FACE_SEL) {
@ -194,7 +237,7 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo
/* expand selection */
for (int i = 0; i < me->totpoly; i++) {
MPoly *mp = &me->mpoly[i];
if (mp->flag & ME_HIDE) {
if (hide_poly[i]) {
continue;
}
@ -249,22 +292,27 @@ void paintface_select_linked(bContext *C, Object *ob, const int mval[2], const b
select_linked_tfaces_with_seams(me, index, select);
paintface_flush_flags(C, ob, SELECT);
paintface_flush_flags(C, ob, true, false);
}
bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool flush_flags)
{
using namespace blender;
Mesh *me = BKE_mesh_from_object(ob);
if (me == nullptr) {
return false;
}
bke::AttributeAccessor attributes = bke::mesh_attributes(*me);
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
for (int i = 0; i < me->totpoly; i++) {
MPoly *mpoly = &me->mpoly[i];
if ((mpoly->flag & ME_HIDE) == 0 && mpoly->flag & ME_FACE_SEL) {
if (!hide_poly[i] && mpoly->flag & ME_FACE_SEL) {
action = SEL_DESELECT;
break;
}
@ -275,7 +323,7 @@ bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool fl
for (int i = 0; i < me->totpoly; i++) {
MPoly *mpoly = &me->mpoly[i];
if ((mpoly->flag & ME_HIDE) == 0) {
if (!hide_poly[i]) {
switch (action) {
case SEL_SELECT:
if ((mpoly->flag & ME_FACE_SEL) == 0) {
@ -299,7 +347,7 @@ bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool fl
if (changed) {
if (flush_flags) {
paintface_flush_flags(C, ob, SELECT);
paintface_flush_flags(C, ob, true, false);
}
}
return changed;
@ -307,6 +355,7 @@ bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool fl
bool paintface_minmax(Object *ob, float r_min[3], float r_max[3])
{
using namespace blender;
bool ok = false;
float vec[3], bmat[3][3];
@ -318,9 +367,13 @@ bool paintface_minmax(Object *ob, float r_min[3], float r_max[3])
copy_m3_m4(bmat, ob->obmat);
bke::AttributeAccessor attributes = bke::mesh_attributes(*me);
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
for (int i = 0; i < me->totpoly; i++) {
MPoly *mp = &me->mpoly[i];
if (mp->flag & ME_HIDE || !(mp->flag & ME_FACE_SEL)) {
if (hide_poly[i] || !(mp->flag & ME_FACE_SEL)) {
continue;
}
@ -342,6 +395,7 @@ bool paintface_mouse_select(bContext *C,
const SelectPick_Params *params,
Object *ob)
{
using namespace blender;
MPoly *mpoly_sel = nullptr;
uint index;
bool changed = false;
@ -350,10 +404,14 @@ bool paintface_mouse_select(bContext *C,
/* Get the face under the cursor */
Mesh *me = BKE_mesh_from_object(ob);
bke::AttributeAccessor attributes = bke::mesh_attributes(*me);
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
if (ED_mesh_pick_face(C, ob, mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) {
if (index < me->totpoly) {
mpoly_sel = me->mpoly + index;
if ((mpoly_sel->flag & ME_HIDE) == 0) {
if (!hide_poly[index]) {
found = true;
}
}
@ -402,7 +460,7 @@ bool paintface_mouse_select(bContext *C,
/* image window redraw */
paintface_flush_flags(C, ob, SELECT);
paintface_flush_flags(C, ob, true, false);
ED_region_tag_redraw(CTX_wm_region(C)); /* XXX: should redraw all 3D views. */
changed = true;
}
@ -463,17 +521,24 @@ void paintvert_tag_select_update(bContext *C, Object *ob)
bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags)
{
using namespace blender;
Mesh *me = BKE_mesh_from_object(ob);
if (me == nullptr) {
return false;
}
bke::AttributeAccessor attributes = bke::mesh_attributes(*me);
const VArray<bool> hide_vert = attributes.lookup_or_default<bool>(
".hide_vert", ATTR_DOMAIN_POINT, false);
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
for (int i = 0; i < me->totvert; i++) {
MVert *mvert = &me->mvert[i];
if ((mvert->flag & ME_HIDE) == 0 && mvert->flag & SELECT) {
if (!hide_poly[i] && mvert->flag & SELECT) {
action = SEL_DESELECT;
break;
}
@ -483,7 +548,7 @@ bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags)
bool changed = false;
for (int i = 0; i < me->totvert; i++) {
MVert *mvert = &me->mvert[i];
if ((mvert->flag & ME_HIDE) == 0) {
if (!hide_vert[i]) {
switch (action) {
case SEL_SELECT:
if ((mvert->flag & SELECT) == 0) {
@ -526,6 +591,7 @@ bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags)
void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags)
{
using namespace blender;
Mesh *me = BKE_mesh_from_object(ob);
if (me == nullptr || me->dvert == nullptr) {
@ -536,10 +602,14 @@ void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags)
paintvert_deselect_all_visible(ob, SEL_DESELECT, false);
}
bke::AttributeAccessor attributes = bke::mesh_attributes(*me);
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
for (int i = 0; i < me->totvert; i++) {
MVert *mv = &me->mvert[i];
MDeformVert *dv = &me->dvert[i];
if ((mv->flag & ME_HIDE) == 0) {
if (!hide_poly[i]) {
if (dv->dw == nullptr) {
/* if null weight then not grouped */
mv->flag |= SELECT;
@ -554,25 +624,30 @@ void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags)
void paintvert_hide(bContext *C, Object *ob, const bool unselected)
{
Mesh *const me = BKE_mesh_from_object(ob);
if (me == nullptr || me->totvert == 0) {
using namespace blender;
Mesh *me = BKE_mesh_from_object(ob);
if (me == NULL || me->totvert == 0) {
return;
}
for (int i = 0; i < me->totvert; i++) {
MVert *const mvert = &me->mvert[i];
bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me);
bke::SpanAttributeWriter<bool> hide_vert = attributes.lookup_or_add_for_write_span<bool>(
".hide_vert", ATTR_DOMAIN_POINT);
MutableSpan<MVert> vertices(me->mvert, me->totvert);
if ((mvert->flag & ME_HIDE) == 0) {
if (((mvert->flag & SELECT) == 0) == unselected) {
mvert->flag |= ME_HIDE;
for (const int i : vertices.index_range()) {
MVert &vert = vertices[i];
if (!hide_vert.span[i]) {
if (((vert.flag & SELECT) == 0) == unselected) {
hide_vert.span[i] = true;
}
}
if (mvert->flag & ME_HIDE) {
mvert->flag &= ~SELECT;
if (hide_vert.span[i]) {
vert.flag &= ~SELECT;
}
}
hide_vert.finish();
BKE_mesh_flush_hidden_from_verts(me);
@ -582,21 +657,27 @@ void paintvert_hide(bContext *C, Object *ob, const bool unselected)
void paintvert_reveal(bContext *C, Object *ob, const bool select)
{
Mesh *const me = BKE_mesh_from_object(ob);
if (me == nullptr || me->totvert == 0) {
using namespace blender;
Mesh *me = BKE_mesh_from_object(ob);
if (me == NULL || me->totvert == 0) {
return;
}
for (int i = 0; i < me->totvert; i++) {
MVert *const mvert = &me->mvert[i];
bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me);
const VArray<bool> hide_vert = attributes.lookup_or_default<bool>(
".hide_vert", ATTR_DOMAIN_POINT, false);
MutableSpan<MVert> vertices(me->mvert, me->totvert);
if (mvert->flag & ME_HIDE) {
SET_FLAG_FROM_TEST(mvert->flag, select, SELECT);
mvert->flag &= ~ME_HIDE;
for (const int i : vertices.index_range()) {
MVert &vert = vertices[i];
if (hide_vert[i]) {
SET_FLAG_FROM_TEST(vert.flag, select, SELECT);
}
}
/* Remove the hide attribute to reveal all vertices. */
attributes.remove(".hide_vert");
BKE_mesh_flush_hidden_from_verts(me);
paintvert_flush_flags(ob);

View File

@ -594,6 +594,10 @@ static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key, Undo
/* Uncomment for troubleshooting. */
// BM_mesh_validate(em->bm);
/* Copy the ID name characters to the mesh so code that depends on accessing the ID type can work
* on it. Necessary to use the attribute API. */
strcpy(um->me.id.name, "MEundomesh_from_editmesh");
BM_mesh_bm_to_me(
NULL,
em->bm,

View File

@ -1329,6 +1329,7 @@ bool ED_mesh_pick_face_vert(
*/
struct VertPickData {
const MVert *mvert;
const bool *hide_vert;
const float *mval_f; /* [2] */
ARegion *region;
@ -1343,16 +1344,16 @@ static void ed_mesh_pick_vert__mapFunc(void *userData,
const float UNUSED(no[3]))
{
VertPickData *data = static_cast<VertPickData *>(userData);
if ((data->mvert[index].flag & ME_HIDE) == 0) {
float sco[2];
if (ED_view3d_project_float_object(data->region, co, sco, V3D_PROJ_TEST_CLIP_DEFAULT) ==
V3D_PROJ_RET_OK) {
const float len = len_manhattan_v2v2(data->mval_f, sco);
if (len < data->len_best) {
data->len_best = len;
data->v_idx_best = index;
}
if (data->hide_vert && data->hide_vert[index]) {
return;
}
float sco[2];
if (ED_view3d_project_float_object(data->region, co, sco, V3D_PROJ_TEST_CLIP_DEFAULT) ==
V3D_PROJ_RET_OK) {
const float len = len_manhattan_v2v2(data->mval_f, sco);
if (len < data->len_best) {
data->len_best = len;
data->v_idx_best = index;
}
}
}
@ -1416,6 +1417,8 @@ bool ED_mesh_pick_vert(
data.mval_f = mval_f;
data.len_best = FLT_MAX;
data.v_idx_best = -1;
data.hide_vert = (const bool *)CustomData_get_layer_named(
&me_eval->vdata, CD_PROP_BOOL, ".hide_vert");
BKE_mesh_foreach_mapped_vert(me_eval, ed_mesh_pick_vert__mapFunc, &data, MESH_FOREACH_NOP);

View File

@ -1034,6 +1034,7 @@ static void vgroup_select_verts(Object *ob, int select)
}
else {
if (me->dvert) {
const bool *hide_vert = CustomData_get_layer_named(&me->vdata, CD_PROP_BOOL, ".hide_vert");
MVert *mv;
MDeformVert *dv;
int i;
@ -1042,7 +1043,7 @@ static void vgroup_select_verts(Object *ob, int select)
dv = me->dvert;
for (i = 0; i < me->totvert; i++, mv++, dv++) {
if (!(mv->flag & ME_HIDE)) {
if (hide_vert != NULL && !hide_vert[i]) {
if (BKE_defvert_find_index(dv, def_nr)) {
if (select) {
mv->flag |= SELECT;
@ -1930,7 +1931,11 @@ static void vgroup_smooth_subset(Object *ob,
#define IS_BM_VERT_READ(v) (use_hide ? (BM_elem_flag_test(v, BM_ELEM_HIDDEN) == 0) : true)
#define IS_BM_VERT_WRITE(v) (use_select ? (BM_elem_flag_test(v, BM_ELEM_SELECT) != 0) : true)
#define IS_ME_VERT_READ(v) (use_hide ? (((v)->flag & ME_HIDE) == 0) : true)
const bool *hide_vert = me ? (const bool *)CustomData_get_layer_named(
&me->vdata, CD_PROP_BOOL, ".hide_vert") :
NULL;
#define IS_ME_VERT_READ(v) (use_hide ? (hide_vert && hide_vert[v]) : true)
#define IS_ME_VERT_WRITE(v) (use_select ? (((v)->flag & SELECT) != 0) : true)
/* initialize used verts */
@ -1956,8 +1961,8 @@ static void vgroup_smooth_subset(Object *ob,
if (IS_ME_VERT_WRITE(v)) {
for (int j = 0; j < emap[i].count; j++) {
const MEdge *e = &me->medge[emap[i].indices[j]];
const MVert *v_other = &me->mvert[(e->v1 == i) ? e->v2 : e->v1];
if (IS_ME_VERT_READ(v_other)) {
const int i_other = (e->v1 == i) ? e->v2 : e->v1;
if (IS_ME_VERT_READ(i_other)) {
STACK_PUSH(verts_used, i);
break;
}
@ -2031,9 +2036,7 @@ static void vgroup_smooth_subset(Object *ob,
for (j = 0; j < emap[i].count; j++) {
MEdge *e = &me->medge[emap[i].indices[j]];
const int i_other = (e->v1 == i ? e->v2 : e->v1);
MVert *v_other = &me->mvert[i_other];
if (IS_ME_VERT_READ(v_other)) {
if (IS_ME_VERT_READ(i_other)) {
WEIGHT_ACCUMULATE;
}
}

View File

@ -78,6 +78,12 @@ static void partialvis_update_mesh(Object *ob,
BKE_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert);
paint_mask = CustomData_get_layer(&me->vdata, CD_PAINT_MASK);
bool *hide_vert = CustomData_get_layer_named(&me->vdata, CD_PROP_BOOL, ".hide_vert");
if (hide_vert == NULL) {
hide_vert = CustomData_add_layer_named(
&me->vdata, CD_PROP_BOOL, CD_CALLOC, NULL, me->totvert, ".hide_vert");
}
SCULPT_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
for (i = 0; i < totvert; i++) {
@ -86,16 +92,11 @@ static void partialvis_update_mesh(Object *ob,
/* Hide vertex if in the hide volume. */
if (is_effected(area, planes, v->co, vmask)) {
if (action == PARTIALVIS_HIDE) {
v->flag |= ME_HIDE;
}
else {
v->flag &= ~ME_HIDE;
}
hide_vert[vert_indices[i]] = (action == PARTIALVIS_HIDE);
any_changed = true;
}
if (!(v->flag & ME_HIDE)) {
if (!hide_vert[vert_indices[i]]) {
any_visible = true;
}
}

View File

@ -344,9 +344,11 @@ int SCULPT_active_face_set_get(SculptSession *ss)
void SCULPT_vertex_visible_set(SculptSession *ss, PBVHVertRef vertex, bool visible)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
SET_FLAG_FROM_TEST(ss->mvert[vertex.i].flag, !visible, ME_HIDE);
case PBVH_FACES: {
bool *hide_vert = BKE_pbvh_get_vert_hide_for_write(ss->pbvh);
hide_vert[vertex.i] = visible;
break;
}
case PBVH_BMESH: {
BMVert *v = (BMVert *)vertex.i;
BM_elem_flag_set(v, BM_ELEM_HIDDEN, !visible);
@ -360,8 +362,10 @@ void SCULPT_vertex_visible_set(SculptSession *ss, PBVHVertRef vertex, bool visib
bool SCULPT_vertex_visible_get(SculptSession *ss, PBVHVertRef vertex)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
return !(ss->mvert[vertex.i].flag & ME_HIDE);
case PBVH_FACES: {
const bool *hide_vert = BKE_pbvh_get_vert_hide(ss->pbvh);
return hide_vert == NULL || !hide_vert[vertex.i];
}
case PBVH_BMESH:
return !BM_elem_flag_test((BMVert *)vertex.i, BM_ELEM_HIDDEN);
case PBVH_GRIDS: {

View File

@ -227,8 +227,9 @@ static void SCULPT_dynamic_topology_disable_ex(
me->face_sets_color_default = 1;
/* Sync the visibility to vertices manually as the pmap is still not initialized. */
for (int i = 0; i < me->totvert; i++) {
me->mvert[i].flag &= ~ME_HIDE;
bool *hide_vert = (bool *)CustomData_get_layer_named(&me->vdata, CD_PROP_BOOL, ".hide_vert");
if (hide_vert != NULL) {
memset(hide_vert, 0, sizeof(bool) * me->totvert);
}
}

View File

@ -346,14 +346,13 @@ static bool sculpt_undo_restore_hidden(bContext *C, SculptUndoNode *unode, bool
SculptSession *ss = ob->sculpt;
SubdivCCG *subdiv_ccg = ss->subdiv_ccg;
if (unode->maxvert) {
MVert *mvert = ss->mvert;
bool *hide_vert = BKE_pbvh_get_vert_hide_for_write(ss->pbvh);
if (unode->maxvert) {
for (int i = 0; i < unode->totvert; i++) {
MVert *v = &mvert[unode->index[i]];
if ((BLI_BITMAP_TEST(unode->vert_hidden, i) != 0) != ((v->flag & ME_HIDE) != 0)) {
if ((BLI_BITMAP_TEST(unode->vert_hidden, i) != 0) != hide_vert[i]) {
BLI_BITMAP_FLIP(unode->vert_hidden, i);
v->flag ^= ME_HIDE;
hide_vert[unode->index[i]] = !hide_vert[i];
modified_vertices[unode->index[i]] = true;
}
}
@ -1247,6 +1246,11 @@ static void sculpt_undo_store_hidden(Object *ob, SculptUndoNode *unode)
PBVH *pbvh = ob->sculpt->pbvh;
PBVHNode *node = unode->node;
const bool *hide_vert = BKE_pbvh_get_vert_hide(pbvh);
if (hide_vert == NULL) {
return;
}
if (unode->grids) {
/* Already stored during allocation. */
}
@ -1258,7 +1262,7 @@ static void sculpt_undo_store_hidden(Object *ob, SculptUndoNode *unode)
BKE_pbvh_node_num_verts(pbvh, node, NULL, &allvert);
BKE_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert);
for (int i = 0; i < allvert; i++) {
BLI_BITMAP_SET(unode->vert_hidden, i, mvert[vert_indices[i]].flag & ME_HIDE);
BLI_BITMAP_SET(unode->vert_hidden, i, hide_vert[vert_indices[i]]);
}
}
}

View File

@ -205,6 +205,7 @@ typedef struct foreachScreenObjectVert_userData {
void (*func)(void *userData, MVert *mv, const float screen_co[2], int index);
void *userData;
ViewContext vc;
const bool *hide_vert;
eV3DProjTest clip_flag;
} foreachScreenObjectVert_userData;
@ -262,18 +263,19 @@ static void meshobject_foreachScreenVert__mapFunc(void *userData,
const float UNUSED(no[3]))
{
foreachScreenObjectVert_userData *data = userData;
if (data->hide_vert && data->hide_vert[index]) {
return;
}
struct MVert *mv = &((Mesh *)(data->vc.obact->data))->mvert[index];
if (!(mv->flag & ME_HIDE)) {
float screen_co[2];
float screen_co[2];
if (ED_view3d_project_float_object(data->vc.region, co, screen_co, data->clip_flag) !=
V3D_PROJ_RET_OK) {
return;
}
data->func(data->userData, mv, screen_co, index);
if (ED_view3d_project_float_object(data->vc.region, co, screen_co, data->clip_flag) !=
V3D_PROJ_RET_OK) {
return;
}
data->func(data->userData, mv, screen_co, index);
}
void meshobject_foreachScreenVert(
@ -297,6 +299,8 @@ void meshobject_foreachScreenVert(
data.func = func;
data.userData = userData;
data.clip_flag = clip_flag;
data.hide_vert = (const bool *)CustomData_get_layer_named(
&me->vdata, CD_PROP_BOOL, ".hide_vert");
if (clip_flag & V3D_PROJ_TEST_CLIP_BB) {
ED_view3d_clipping_local(vc->rv3d, vc->obact->obmat);

View File

@ -335,14 +335,16 @@ static bool edbm_backbuf_check_and_select_verts_obmode(Mesh *me,
const eSelectOp sel_op)
{
MVert *mv = me->mvert;
uint index;
bool changed = false;
const BLI_bitmap *select_bitmap = esel->select_bitmap;
if (mv) {
for (index = 0; index < me->totvert; index++, mv++) {
if (!(mv->flag & ME_HIDE)) {
const bool *hide_vert = (const bool *)CustomData_get_layer_named(
&me->vdata, CD_PROP_BOOL, ".hide_vert");
for (int index = 0; index < me->totvert; index++, mv++) {
if (!(hide_vert && hide_vert[index])) {
const bool is_select = mv->flag & SELECT;
const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index);
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
@ -362,14 +364,16 @@ static bool edbm_backbuf_check_and_select_faces_obmode(Mesh *me,
const eSelectOp sel_op)
{
MPoly *mpoly = me->mpoly;
uint index;
bool changed = false;
const BLI_bitmap *select_bitmap = esel->select_bitmap;
if (mpoly) {
for (index = 0; index < me->totpoly; index++, mpoly++) {
if (!(mpoly->flag & ME_HIDE)) {
const bool *hide_poly = (const bool *)CustomData_get_layer_named(
&me->vdata, CD_PROP_BOOL, ".hide_poly");
for (int index = 0; index < me->totpoly; index++, mpoly++) {
if (!(hide_poly && hide_poly[index])) {
const bool is_select = mpoly->flag & ME_FACE_SEL;
const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index);
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
@ -1260,7 +1264,7 @@ static bool do_lasso_select_paintface(ViewContext *vc,
}
if (changed) {
paintface_flush_flags(vc->C, ob, SELECT);
paintface_flush_flags(vc->C, ob, true, false);
}
return changed;
}
@ -3192,7 +3196,7 @@ static bool do_paintface_box_select(ViewContext *vc,
}
if (changed) {
paintface_flush_flags(vc->C, vc->obact, SELECT);
paintface_flush_flags(vc->C, vc->obact, true, false);
}
return changed;
}
@ -4093,7 +4097,7 @@ static bool paint_facesel_circle_select(ViewContext *vc,
}
if (changed) {
paintface_flush_flags(vc->C, ob, SELECT);
paintface_flush_flags(vc->C, ob, true, false);
}
return changed;
}

View File

@ -48,7 +48,6 @@ typedef struct GPU_PBVH_Buffers GPU_PBVH_Buffers;
* Threaded: do not call any functions that use OpenGL calls!
*/
GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const struct Mesh *mesh,
const struct MVert *vertices,
const struct MLoopTri *looptri,
const int *sculpt_face_sets,
const int *face_indices,

View File

@ -211,11 +211,11 @@ static void gpu_pbvh_batch_init(GPU_PBVH_Buffers *buffers, GPUPrimType prim)
* \{ */
static bool gpu_pbvh_is_looptri_visible(const MLoopTri *lt,
const MVert *mvert,
const bool *hide_vert,
const MLoop *mloop,
const int *sculpt_face_sets)
{
return (!paint_is_face_hidden(lt, mvert, mloop) && sculpt_face_sets &&
return (!paint_is_face_hidden(lt, hide_vert, mloop) && sculpt_face_sets &&
sculpt_face_sets[lt->poly] > SCULPT_FACE_SET_NONE);
}
@ -233,6 +233,9 @@ void GPU_pbvh_mesh_buffers_update(PBVHGPUFormat *vbo_id,
GPUAttrRef vcol_refs[MAX_GPU_ATTR];
GPUAttrRef cd_uvs[MAX_GPU_ATTR];
const bool *hide_vert = (bool *)CustomData_get_layer_named(
&mesh->vdata, CD_PROP_BOOL, ".hide_vert");
const CustomDataLayer *actcol = BKE_id_attributes_active_color_get(&mesh->id);
eAttrDomain actcol_domain = actcol ? BKE_id_attribute_domain(&mesh->id, actcol) :
ATTR_DOMAIN_AUTO;
@ -310,7 +313,7 @@ void GPU_pbvh_mesh_buffers_update(PBVHGPUFormat *vbo_id,
for (uint i = 0; i < buffers->face_indices_len; i++) {
const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
if (!gpu_pbvh_is_looptri_visible(lt, mvert, buffers->mloop, sculpt_face_sets)) {
if (!gpu_pbvh_is_looptri_visible(lt, hide_vert, buffers->mloop, sculpt_face_sets)) {
continue;
}
@ -350,7 +353,7 @@ void GPU_pbvh_mesh_buffers_update(PBVHGPUFormat *vbo_id,
buffers->mloop[lt->tri[2]].v,
};
if (!gpu_pbvh_is_looptri_visible(lt, mvert, buffers->mloop, sculpt_face_sets)) {
if (!gpu_pbvh_is_looptri_visible(lt, hide_vert, buffers->mloop, sculpt_face_sets)) {
continue;
}
@ -390,7 +393,7 @@ void GPU_pbvh_mesh_buffers_update(PBVHGPUFormat *vbo_id,
buffers->mloop[lt->tri[2]].v,
};
if (!gpu_pbvh_is_looptri_visible(lt, mvert, buffers->mloop, sculpt_face_sets)) {
if (!gpu_pbvh_is_looptri_visible(lt, hide_vert, buffers->mloop, sculpt_face_sets)) {
continue;
}
@ -454,7 +457,6 @@ void GPU_pbvh_mesh_buffers_update(PBVHGPUFormat *vbo_id,
}
GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const Mesh *mesh,
const MVert *vertices,
const MLoopTri *looptri,
const int *sculpt_face_sets,
const int *face_indices,
@ -469,6 +471,9 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const Mesh *mesh,
buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers");
const bool *hide_vert = (bool *)CustomData_get_layer_named(
&mesh->vdata, CD_PROP_BOOL, ".hide_vert");
/* smooth or flat for all */
buffers->smooth = mpoly[looptri[face_indices[0]].poly].flag & ME_SMOOTH;
@ -477,7 +482,7 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const Mesh *mesh,
/* Count the number of visible triangles */
for (i = 0, tottri = 0; i < face_indices_len; i++) {
const MLoopTri *lt = &looptri[face_indices[i]];
if (gpu_pbvh_is_looptri_visible(lt, vertices, mloop, sculpt_face_sets)) {
if (gpu_pbvh_is_looptri_visible(lt, hide_vert, mloop, sculpt_face_sets)) {
int r_edges[3];
BKE_mesh_looptri_get_real_edges(mesh, lt, r_edges);
for (int j = 0; j < 3; j++) {
@ -510,7 +515,7 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const Mesh *mesh,
const MLoopTri *lt = &looptri[face_indices[i]];
/* Skip hidden faces */
if (!gpu_pbvh_is_looptri_visible(lt, vertices, mloop, sculpt_face_sets)) {
if (!gpu_pbvh_is_looptri_visible(lt, hide_vert, mloop, sculpt_face_sets)) {
continue;
}

View File

@ -137,7 +137,7 @@ eAttrDomain BKE_id_attribute_domain(const struct ID *UNUSED(id),
/** \name Stubs of BKE_paint.h
* \{ */
bool paint_is_face_hidden(const struct MLoopTri *UNUSED(lt),
const struct MVert *UNUSED(mvert),
const bool *UNUSED(hide_vert),
const struct MLoop *UNUSED(mloop))
{
BLI_assert_unreachable();

View File

@ -296,7 +296,7 @@ void OBJMesh::store_uv_coords_and_indices()
const float limit[2] = {STD_UV_CONNECT_LIMIT, STD_UV_CONNECT_LIMIT};
UvVertMap *uv_vert_map = BKE_mesh_uv_vert_map_create(
mpoly, mloop, mloopuv, totpoly, totvert, limit, false, false);
mpoly, nullptr, mloop, mloopuv, totpoly, totvert, limit, false, false);
uv_indices_.resize(totpoly);
/* At least total vertices of a mesh will be present in its texture map. So

View File

@ -30,10 +30,13 @@ typedef struct MVert {
} MVert;
/** #MVert.flag */
#ifdef DNA_DEPRECATED_ALLOW
enum {
/* SELECT = (1 << 0), */
ME_HIDE = (1 << 4),
};
#endif
/**
* Mesh Edges.
@ -351,7 +354,7 @@ typedef struct MDisps {
/**
* Used for hiding parts of a multires mesh.
* Essentially the multires equivalent of #MVert.flag's ME_HIDE bit.
* Essentially the multires equivalent of the mesh ".hide_vert" boolean layer.
*
* \note This is a bitmap, keep in sync with type used in BLI_bitmap.h
*/

View File

@ -356,6 +356,27 @@ static void rna_MeshVertex_normal_get(PointerRNA *ptr, float *value)
copy_v3_v3(value, vert_normals[index]);
}
static bool rna_MeshVertex_hide_get(PointerRNA *ptr)
{
const Mesh *mesh = rna_mesh(ptr);
const bool *hide_vert = (const bool *)CustomData_get_layer_named(
&mesh->vdata, CD_PROP_BOOL, ".hide_vert");
const int index = (const MVert *)ptr->data - mesh->mvert;
BLI_assert(index >= 0);
BLI_assert(index < mesh->totvert);
return hide_vert[index];
}
static void rna_MeshVertex_hide_set(PointerRNA *ptr, bool value)
{
Mesh *mesh = rna_mesh(ptr);
bool *hide_vert = (bool *)CustomData_get_layer_named(&mesh->vdata, CD_PROP_BOOL, ".hide_vert");
const int index = (const MVert *)ptr->data - mesh->mvert;
BLI_assert(index >= 0);
BLI_assert(index < mesh->totvert);
hide_vert[index] = value;
}
static float rna_MeshVertex_bevel_weight_get(PointerRNA *ptr)
{
MVert *mvert = (MVert *)ptr->data;
@ -464,6 +485,27 @@ static void rna_MeshPolygon_normal_get(PointerRNA *ptr, float *values)
BKE_mesh_calc_poly_normal(mp, me->mloop + mp->loopstart, me->mvert, values);
}
static bool rna_MeshPolygon_hide_get(PointerRNA *ptr)
{
const Mesh *mesh = rna_mesh(ptr);
const bool *hide_poly = (const bool *)CustomData_get_layer_named(
&mesh->pdata, CD_PROP_BOOL, ".hide_poly");
const int index = (const MPoly *)ptr->data - mesh->mpoly;
BLI_assert(index >= 0);
BLI_assert(index < mesh->totpoly);
return hide_poly[index];
}
static void rna_MeshPolygon_hide_set(PointerRNA *ptr, bool value)
{
Mesh *mesh = rna_mesh(ptr);
bool *hide_poly = (bool *)CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, ".hide_poly");
const int index = (const MPoly *)ptr->data - mesh->mpoly;
BLI_assert(index >= 0);
BLI_assert(index < mesh->totpoly);
hide_poly[index] = value;
}
static void rna_MeshPolygon_center_get(PointerRNA *ptr, float *values)
{
Mesh *me = rna_mesh(ptr);
@ -1188,6 +1230,27 @@ static int rna_MeshEdge_index_get(PointerRNA *ptr)
return (int)(edge - me->medge);
}
static bool rna_MeshEdge_hide_get(PointerRNA *ptr)
{
const Mesh *mesh = rna_mesh(ptr);
const bool *hide_edge = (const bool *)CustomData_get_layer_named(
&mesh->pdata, CD_PROP_BOOL, ".hide_edge");
const int index = (const MEdge *)ptr->data - mesh->medge;
BLI_assert(index >= 0);
BLI_assert(index < mesh->totedge);
return hide_edge[index];
}
static void rna_MeshEdge_hide_set(PointerRNA *ptr, bool value)
{
Mesh *mesh = rna_mesh(ptr);
bool *hide_edge = (bool *)CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, ".hide_edge");
const int index = (const MEdge *)ptr->data - mesh->medge;
BLI_assert(index >= 0);
BLI_assert(index < mesh->totedge);
hide_edge[index] = value;
}
static int rna_MeshLoopTriangle_index_get(PointerRNA *ptr)
{
Mesh *me = rna_mesh(ptr);
@ -1830,8 +1893,8 @@ static void rna_def_mvert(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Mesh_update_select");
prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_HIDE);
RNA_def_property_ui_text(prop, "Hide", "");
RNA_def_property_boolean_funcs(prop, "rna_MeshVertex_hide_get", "rna_MeshVertex_hide_set");
RNA_def_property_update(prop, 0, "rna_Mesh_update_select");
prop = RNA_def_property(srna, "bevel_weight", PROP_FLOAT, PROP_NONE);
@ -1906,8 +1969,8 @@ static void rna_def_medge(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Mesh_update_select");
prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_HIDE);
RNA_def_property_ui_text(prop, "Hide", "");
RNA_def_property_boolean_funcs(prop, "rna_MeshEdge_hide_get", "rna_MeshEdge_hide_set");
RNA_def_property_update(prop, 0, "rna_Mesh_update_select");
prop = RNA_def_property(srna, "use_seam", PROP_BOOLEAN, PROP_NONE);
@ -2119,8 +2182,8 @@ static void rna_def_mpolygon(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Mesh_update_select");
prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_HIDE);
RNA_def_property_ui_text(prop, "Hide", "");
RNA_def_property_boolean_funcs(prop, "rna_MeshPolygon_hide_get", "rna_MeshPolygon_hide_set");
RNA_def_property_update(prop, 0, "rna_Mesh_update_select");
prop = RNA_def_property(srna, "use_smooth", PROP_BOOLEAN, PROP_NONE);

View File

@ -201,11 +201,12 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
updateFaceCount(ctx, dmd, bm->totface);
result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, mesh);
/* make sure we never alloc'd these */
BLI_assert(bm->vtoolflagpool == NULL && bm->etoolflagpool == NULL && bm->ftoolflagpool == NULL);
BLI_assert(bm->vtable == NULL && bm->etable == NULL && bm->ftable == NULL);
result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, mesh);
BM_mesh_free(bm);
#ifdef USE_TIMEIT