Files
test2/source/blender/blenkernel/BKE_mesh_legacy_convert.h
Hans Goudey 5876573e14 Mesh: Move face shade smooth flag to a generic attribute
Currently the shade smooth status for mesh faces is stored as part of
`MPoly::flag`. As described in #95967, this moves that information
to a separate boolean attribute. It also flips its status, so the
attribute is now called `sharp_face`, which mirrors the existing
`sharp_edge` attribute. The attribute doesn't need to be allocated
when all faces are smooth. Forward compatibility is kept until
4.0 like the other mesh refactors.

This will reduce memory bandwidth requirements for some operations,
since the array of booleans uses 12 times less memory than `MPoly`.
It also allows faces to be stored more efficiently in the future, since
the flag is now unused. It's also possible to use generic functions to
process the values. For example, finding whether there is a sharp face
is just `sharp_faces.contains(true)`.

The `shade_smooth` attribute is no longer accessible with geometry nodes.
Since there were dedicated accessor nodes for that data, that shouldn't
be a problem. That's difficult to version automatically since the named
attribute nodes could be used in arbitrary combinations.

**Implementation notes:**
- The attribute and array variables in the code use the `sharp_faces`
  term, to be consistent with the user-facing "sharp faces" wording,
  and to avoid requiring many renames when #101689 is implemented.
- Cycles now accesses smooth face status with the generic attribute,
  to avoid overhead.
- Changing the zero-value from "smooth" to "flat" takes some care to
  make sure defaults are the same.
  - Versioning for the edge mode extrude node is particularly complex.
    New nodes are added by versioning to propagate the attribute in its
    old inverted state.
- A lot of access is still done through the `CustomData` API rather
  than the attribute API because of a few functions. That can be
  cleaned up easily in the future.
- In the future we would benefit from a way to store attributes as a
  single value for when all faces are sharp.

Pull Request: https://projects.blender.org/blender/blender/pulls/104422
2023-03-08 15:36:18 +01:00

173 lines
5.6 KiB
C

/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2001-2002 NaN Holding BV. All rights reserved. */
#pragma once
/** \file
* \ingroup bke
*/
#include "BLI_utildefines.h"
#ifdef __cplusplus
# include "BLI_resource_scope.hh"
# include "BLI_span.hh"
# include "BLI_vector.hh"
# include "DNA_customdata_types.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
struct CustomData;
struct Mesh;
struct MFace;
#ifdef __cplusplus
void BKE_mesh_legacy_convert_uvs_to_struct(
Mesh *mesh,
blender::ResourceScope &temp_mloopuv_for_convert,
blender::Vector<CustomDataLayer, 16> &loop_layers_to_write);
void BKE_mesh_legacy_convert_uvs_to_generic(Mesh *mesh);
/**
* Move face sets to the legacy type from a generic type.
*/
void BKE_mesh_legacy_face_set_from_generic(
blender::MutableSpan<CustomDataLayer> poly_layers_to_write);
/**
* Copy face sets to the generic data type from the legacy type.
*/
void BKE_mesh_legacy_face_set_to_generic(struct Mesh *mesh);
/**
* Copy edge creases from a separate layer into edges.
*/
void BKE_mesh_legacy_edge_crease_from_layers(struct Mesh *mesh);
/**
* Copy edge creases from edges to a separate layer.
*/
void BKE_mesh_legacy_edge_crease_to_layers(struct Mesh *mesh);
/**
* Copy bevel weights from separate layers into vertices and edges.
*/
void BKE_mesh_legacy_bevel_weight_from_layers(struct Mesh *mesh);
/**
* Copy bevel weights from vertices and edges to separate layers.
*/
void BKE_mesh_legacy_bevel_weight_to_layers(struct Mesh *mesh);
/**
* 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);
/**
* Convert the selected element attributes to the old flag format for writing.
*/
void BKE_mesh_legacy_convert_selection_layers_to_flags(struct Mesh *mesh);
/**
* Convert the old selection flags (#SELECT/#ME_FACE_SEL) to the selected element attribute for
* reading. Only add the attributes when there are any elements in each domain selected.
*/
void BKE_mesh_legacy_convert_flags_to_selection_layers(struct Mesh *mesh);
/**
* Move material indices from a generic attribute to #MPoly.
*/
void BKE_mesh_legacy_convert_material_indices_to_mpoly(struct Mesh *mesh);
/**
* Move material indices from the #MPoly struct to a generic attributes.
* Only add the attribute when the indices are not all zero.
*/
void BKE_mesh_legacy_convert_mpoly_to_material_indices(struct Mesh *mesh);
/** Convert from runtime loose edge cache to legacy edge flag. */
void BKE_mesh_legacy_convert_loose_edges_to_flag(struct Mesh *mesh);
void BKE_mesh_legacy_attribute_flags_to_strings(struct Mesh *mesh);
void BKE_mesh_legacy_attribute_strings_to_flags(struct Mesh *mesh);
void BKE_mesh_legacy_sharp_faces_to_flags(struct Mesh *mesh);
void BKE_mesh_legacy_sharp_faces_from_flags(struct Mesh *mesh);
void BKE_mesh_legacy_sharp_edges_to_flags(struct Mesh *mesh);
void BKE_mesh_legacy_sharp_edges_from_flags(struct Mesh *mesh);
void BKE_mesh_legacy_uv_seam_to_flags(struct Mesh *mesh);
void BKE_mesh_legacy_uv_seam_from_flags(struct Mesh *mesh);
struct MVert *BKE_mesh_legacy_convert_positions_to_verts(
Mesh *mesh,
blender::ResourceScope &temp_arrays_for_convert,
blender::Vector<CustomDataLayer, 16> &vert_layers_to_write);
void BKE_mesh_legacy_convert_verts_to_positions(Mesh *mesh);
#endif
/**
* Recreate #MFace Tessellation.
*
* \note This doesn't use multi-threading like #BKE_mesh_recalc_looptri since
* it's not used in many places and #MFace should be phased out.
*/
void BKE_mesh_tessface_calc(struct Mesh *mesh);
void BKE_mesh_tessface_ensure(struct Mesh *mesh);
/**
* Rotates the vertices of a face in case v[2] or v[3] (vertex index) is = 0.
* this is necessary to make the if #MFace.v4 check for quads work.
*/
int BKE_mesh_mface_index_validate(struct MFace *mface,
struct CustomData *mfdata,
int mfindex,
int nr);
void BKE_mesh_convert_mfaces_to_mpolys(struct Mesh *mesh);
/**
* The same as #BKE_mesh_convert_mfaces_to_mpolys
* but oriented to be used in #do_versions from `readfile.c`
* the difference is how active/render/clone/stencil indices are handled here.
*
* normally they're being set from `pdata` which totally makes sense for meshes which are already
* converted to #BMesh structures, but when loading older files indices shall be updated in other
* way around, so newly added `pdata` and `ldata` would have this indices set
* based on `fdata` layer.
*
* this is normally only needed when reading older files,
* in all other cases #BKE_mesh_convert_mfaces_to_mpolys shall be always used.
*/
void BKE_mesh_do_versions_convert_mfaces_to_mpolys(struct Mesh *mesh);
void BKE_mesh_calc_edges_legacy(struct Mesh *me);
void BKE_mesh_do_versions_cd_flag_init(struct Mesh *mesh);
/* Inlines */
/* NOTE(@sybren): Instead of -1 that function uses ORIGINDEX_NONE as defined in BKE_customdata.h,
* but I don't want to force every user of BKE_mesh.h to also include that file. */
BLI_INLINE int BKE_mesh_origindex_mface_mpoly(const int *index_mf_to_mpoly,
const int *index_mp_to_orig,
const int i)
{
const int j = index_mf_to_mpoly[i];
return (j != -1) ? (index_mp_to_orig ? index_mp_to_orig[j] : j) : -1;
}
#ifdef __cplusplus
}
#endif