2023-08-16 00:20:26 +10:00
|
|
|
/* SPDX-FileCopyrightText: 2006 Blender Authors
|
2023-05-31 16:19:06 +02:00
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2011-02-27 20:40:57 +00:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup bke
|
2022-02-09 16:00:03 +11:00
|
|
|
* Implementation of CustomData.
|
|
|
|
|
*
|
2023-11-16 11:41:55 +01:00
|
|
|
* BKE_customdata.hh contains the function prototypes for this file.
|
2011-02-27 20:40:57 +00:00
|
|
|
*/
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2009-11-25 14:27:50 +00:00
|
|
|
#include "MEM_guardedalloc.h"
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2019-07-03 15:43:05 +02:00
|
|
|
/* Since we have versioning code here (CustomData_verify_versions()). */
|
|
|
|
|
#define DNA_DEPRECATED_ALLOW
|
|
|
|
|
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "DNA_ID.h"
|
2017-03-24 20:06:43 -03:00
|
|
|
#include "DNA_customdata_types.h"
|
2006-08-28 01:12:36 +00:00
|
|
|
#include "DNA_meshdata_types.h"
|
|
|
|
|
|
2023-07-14 17:12:49 +02:00
|
|
|
#include "BLI_bit_vector.hh"
|
2020-08-28 14:30:19 +02:00
|
|
|
#include "BLI_bitmap.h"
|
2022-03-19 10:57:40 +01:00
|
|
|
#include "BLI_color.hh"
|
2020-08-28 14:30:19 +02:00
|
|
|
#include "BLI_endian_switch.h"
|
2022-06-07 18:00:18 +02:00
|
|
|
#include "BLI_index_range.hh"
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
#include "BLI_math_color_blend.h"
|
2024-02-13 18:59:36 +01:00
|
|
|
#include "BLI_math_matrix.hh"
|
2023-06-12 15:49:50 +02:00
|
|
|
#include "BLI_math_quaternion_types.hh"
|
2022-03-19 10:57:40 +01:00
|
|
|
#include "BLI_math_vector.hh"
|
2009-11-25 14:27:50 +00:00
|
|
|
#include "BLI_mempool.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_path_util.h"
|
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
2022-08-11 12:54:24 -04:00
|
|
|
#include "BLI_set.hh"
|
2022-05-29 11:02:10 +02:00
|
|
|
#include "BLI_span.hh"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_string.h"
|
2022-06-07 18:00:18 +02:00
|
|
|
#include "BLI_string_ref.hh"
|
2023-05-13 17:38:48 +10:00
|
|
|
#include "BLI_string_utf8.h"
|
2023-10-18 17:15:30 +02:00
|
|
|
#include "BLI_string_utils.hh"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_utildefines.h"
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2022-01-19 15:09:48 +11:00
|
|
|
#ifndef NDEBUG
|
|
|
|
|
# include "BLI_dynstr.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
2024-02-09 18:59:42 +01:00
|
|
|
#include "BLT_translation.hh"
|
2013-03-25 08:29:06 +00:00
|
|
|
|
2023-01-05 14:05:30 +01:00
|
|
|
#include "BKE_anonymous_attribute_id.hh"
|
2023-11-16 11:41:55 +01:00
|
|
|
#include "BKE_customdata.hh"
|
2009-12-10 14:26:06 +00:00
|
|
|
#include "BKE_customdata_file.h"
|
2024-01-29 18:57:16 -05:00
|
|
|
#include "BKE_deform.hh"
|
2023-12-01 19:43:16 +01:00
|
|
|
#include "BKE_main.hh"
|
2023-08-02 22:14:18 +02:00
|
|
|
#include "BKE_mesh_mapping.hh"
|
|
|
|
|
#include "BKE_mesh_remap.hh"
|
|
|
|
|
#include "BKE_multires.hh"
|
|
|
|
|
#include "BKE_subsurf.hh"
|
2020-08-28 14:30:19 +02:00
|
|
|
|
2023-08-28 15:01:05 +02:00
|
|
|
#include "BLO_read_write.hh"
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2023-12-05 23:01:12 +01:00
|
|
|
#include "bmesh.hh"
|
2009-06-23 05:35:49 +00:00
|
|
|
|
2019-02-01 12:44:19 +11:00
|
|
|
#include "CLG_log.h"
|
|
|
|
|
|
2017-03-27 09:14:40 +11:00
|
|
|
/* only for customdata_data_transfer_interp_normal_normals */
|
|
|
|
|
#include "data_transfer_intern.h"
|
|
|
|
|
|
2023-12-09 05:37:37 +01:00
|
|
|
using blender::Array;
|
2023-07-14 17:12:49 +02:00
|
|
|
using blender::BitVector;
|
Mesh: Move UV layers to generic attributes
Currently the `MLoopUV` struct stores UV coordinates and flags related
to editing UV maps in the UV editor. This patch changes the coordinates
to use the generic 2D vector type, and moves the flags into three
separate boolean attributes. This follows the design in T95965, with
the ultimate intention of simplifying code and improving performance.
Importantly, the change allows exporters and renderers to use UVs
"touched" by geometry nodes, which only creates generic attributes.
It also allows geometry nodes to create "proper" UV maps from scratch,
though only with the Store Named Attribute node for now.
The new design considers any 2D vector attribute on the corner domain
to be a UV map. In the future, they might be distinguished from regular
2D vectors with attribute metadata, which may be helpful because they
are often interpolated differently.
Most of the code changes deal with passing around UV BMesh custom data
offsets and tracking the boolean "sublayers". The boolean layers are
use the following prefixes for attribute names: vert selection: `.vs.`,
edge selection: `.es.`, pinning: `.pn.`. Currently these are short to
avoid using up the maximum length of attribute names. To accommodate
for these 4 extra characters, the name length limit is enlarged to 68
bytes, while the maximum user settable name length is still 64 bytes.
Unfortunately Python/RNA API access to the UV flag data becomes slower.
Accessing the boolean layers directly is be better for performance in
general.
Like the other mesh SoA refactors, backward and forward compatibility
aren't affected, and won't be changed until 4.0. We pay for that by
making mesh reading and writing more expensive with conversions.
Resolves T85962
Differential Revision: https://developer.blender.org/D14365
2023-01-10 00:47:04 -05:00
|
|
|
using blender::float2;
|
2023-04-13 14:57:57 +02:00
|
|
|
using blender::ImplicitSharingInfo;
|
2022-05-31 19:23:52 +02:00
|
|
|
using blender::IndexRange;
|
2023-12-05 17:41:48 -05:00
|
|
|
using blender::MutableSpan;
|
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
2022-08-11 12:54:24 -04:00
|
|
|
using blender::Set;
|
2022-05-29 11:02:10 +02:00
|
|
|
using blender::Span;
|
2022-06-07 18:00:18 +02:00
|
|
|
using blender::StringRef;
|
2022-05-29 11:02:10 +02:00
|
|
|
using blender::Vector;
|
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* number of layers to add when growing a CustomData object */
|
|
|
|
|
#define CUSTOMDATA_GROW 5
|
|
|
|
|
|
2012-10-25 04:44:46 +00:00
|
|
|
/* ensure typemap size is ok */
|
2023-05-23 09:21:45 +02:00
|
|
|
BLI_STATIC_ASSERT(BOUNDED_ARRAY_TYPE_SIZE<decltype(CustomData::typemap)>() == CD_NUMTYPES,
|
|
|
|
|
"size mismatch");
|
2012-10-25 04:44:46 +00:00
|
|
|
|
2019-02-01 12:44:19 +11:00
|
|
|
static CLG_LogRef LOG = {"bke.customdata"};
|
2012-10-25 04:44:46 +00:00
|
|
|
|
2022-03-25 12:49:01 +11:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Mesh Mask Utilities
|
|
|
|
|
* \{ */
|
|
|
|
|
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
void CustomData_MeshMasks_update(CustomData_MeshMasks *mask_dst,
|
|
|
|
|
const CustomData_MeshMasks *mask_src)
|
|
|
|
|
{
|
|
|
|
|
mask_dst->vmask |= mask_src->vmask;
|
|
|
|
|
mask_dst->emask |= mask_src->emask;
|
|
|
|
|
mask_dst->fmask |= mask_src->fmask;
|
|
|
|
|
mask_dst->pmask |= mask_src->pmask;
|
|
|
|
|
mask_dst->lmask |= mask_src->lmask;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CustomData_MeshMasks_are_matching(const CustomData_MeshMasks *mask_ref,
|
|
|
|
|
const CustomData_MeshMasks *mask_required)
|
|
|
|
|
{
|
|
|
|
|
return (((mask_required->vmask & mask_ref->vmask) == mask_required->vmask) &&
|
|
|
|
|
((mask_required->emask & mask_ref->emask) == mask_required->emask) &&
|
|
|
|
|
((mask_required->fmask & mask_ref->fmask) == mask_required->fmask) &&
|
|
|
|
|
((mask_required->pmask & mask_ref->pmask) == mask_required->pmask) &&
|
|
|
|
|
((mask_required->lmask & mask_ref->lmask) == mask_required->lmask));
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-25 12:49:01 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
2023-07-09 21:40:17 +10:00
|
|
|
/** \name Layer Type Information Struct
|
2022-03-25 12:49:01 +11:00
|
|
|
* \{ */
|
|
|
|
|
|
2021-12-25 14:28:22 -06:00
|
|
|
struct LayerTypeInfo {
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
int size; /* the memory size of one element of this layer's data */
|
2024-02-13 18:59:36 +01:00
|
|
|
int alignment;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-10-31 11:45:41 +00:00
|
|
|
/** name of the struct used, for file writing */
|
2012-10-30 19:20:17 +00:00
|
|
|
const char *structname;
|
2012-10-31 11:45:41 +00:00
|
|
|
/** number of structs per element, for file writing */
|
2012-10-30 19:20:17 +00:00
|
|
|
int structnum;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-24 17:01:35 +00:00
|
|
|
/**
|
|
|
|
|
* default layer name.
|
2021-07-03 23:08:40 +10:00
|
|
|
*
|
2021-12-25 14:28:22 -06:00
|
|
|
* \note when null this is a way to ensure there is only ever one item
|
2021-07-03 23:08:40 +10:00
|
|
|
* see: CustomData_layertype_is_singleton().
|
|
|
|
|
*/
|
2012-04-30 18:54:14 +00:00
|
|
|
const char *defaultname;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-24 17:01:35 +00:00
|
|
|
/**
|
|
|
|
|
* a function to copy count elements of this layer's data
|
2006-08-28 01:12:36 +00:00
|
|
|
* (deep copy if appropriate)
|
2021-12-25 14:28:22 -06:00
|
|
|
* if null, memcpy is used
|
2006-08-28 01:12:36 +00:00
|
|
|
*/
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
cd_copy copy;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-24 17:01:35 +00:00
|
|
|
/**
|
|
|
|
|
* a function to free any dynamically allocated components of this
|
2006-08-28 01:12:36 +00:00
|
|
|
* layer's data (note the data pointer itself should not be freed)
|
|
|
|
|
* size should be the size of one element of this layer's data (e.g.
|
|
|
|
|
* LayerTypeInfo.size)
|
|
|
|
|
*/
|
2023-12-09 05:37:37 +01:00
|
|
|
cd_free free;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-24 17:01:35 +00:00
|
|
|
/**
|
|
|
|
|
* a function to interpolate between count source elements of this
|
2006-08-28 01:12:36 +00:00
|
|
|
* layer's data and store the result in dest
|
2021-12-25 14:28:22 -06:00
|
|
|
* if weights == null or sub_weights == null, they should default to 1
|
2006-08-28 01:12:36 +00:00
|
|
|
*
|
|
|
|
|
* weights gives the weight for each element in sources
|
|
|
|
|
* sub_weights gives the sub-element weights for each element in sources
|
|
|
|
|
* (there should be (sub element count)^2 weights per element)
|
|
|
|
|
* count gives the number of elements in sources
|
2012-08-24 17:01:35 +00:00
|
|
|
*
|
2024-01-14 11:48:51 +11:00
|
|
|
* \note in some cases `dest` pointer is in `sources` so all functions have to take this
|
|
|
|
|
* into account and delay applying changes while reading from sources. See #32395.
|
2006-08-28 01:12:36 +00:00
|
|
|
*/
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
cd_interp interp;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-24 17:01:35 +00:00
|
|
|
/** a function to swap the data in corners of the element */
|
2010-04-10 22:12:10 +00:00
|
|
|
void (*swap)(void *data, const int *corner_indices);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-24 17:01:35 +00:00
|
|
|
/**
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
* Set values to the type's default. If undefined, the default is assumed to be zeroes.
|
|
|
|
|
* Memory pointed to by #data is expected to be uninitialized.
|
|
|
|
|
*/
|
2023-12-09 05:37:37 +01:00
|
|
|
cd_set_default_value set_default_value;
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
/**
|
|
|
|
|
* Construct and fill a valid value for the type. Necessary for non-trivial types.
|
|
|
|
|
* Memory pointed to by #data is expected to be uninitialized.
|
|
|
|
|
*/
|
|
|
|
|
void (*construct)(void *data, int count);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-12-03 16:19:08 +01:00
|
|
|
/** A function used by mesh validating code, must ensures passed item has valid data. */
|
|
|
|
|
cd_validate validate;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-24 17:01:35 +00:00
|
|
|
/** functions necessary for geometry collapse */
|
2014-09-09 16:12:07 +10:00
|
|
|
bool (*equal)(const void *data1, const void *data2);
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
void (*multiply)(void *data, float fac);
|
|
|
|
|
void (*initminmax)(void *min, void *max);
|
2014-09-09 16:12:07 +10:00
|
|
|
void (*add)(void *data1, const void *data2);
|
|
|
|
|
void (*dominmax)(const void *data1, void *min, void *max);
|
2022-08-03 11:58:52 -05:00
|
|
|
void (*copyvalue)(const void *source, void *dest, int mixmode, const float mixfactor);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-24 17:01:35 +00:00
|
|
|
/** a function to read data from a cdf file */
|
2020-09-02 19:10:18 +02:00
|
|
|
bool (*read)(CDataFile *cdf, void *data, int count);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-24 17:01:35 +00:00
|
|
|
/** a function to write data to a cdf file */
|
2020-09-02 19:10:18 +02:00
|
|
|
bool (*write)(CDataFile *cdf, const void *data, int count);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-24 17:01:35 +00:00
|
|
|
/** a function to determine file size */
|
2014-09-09 16:12:07 +10:00
|
|
|
size_t (*filesize)(CDataFile *cdf, const void *data, int count);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-27 12:07:07 +10:00
|
|
|
/** a function to determine max allowed number of layers,
|
2021-12-25 14:28:22 -06:00
|
|
|
* should be null or return -1 if no limit */
|
|
|
|
|
int (*layers_max)();
|
|
|
|
|
};
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2022-03-25 12:49:01 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Callbacks for (#MDeformVert, #CD_MDEFORMVERT)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static void layerCopy_mdeformvert(const void *source, void *dest, const int count)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2006-12-12 21:29:09 +00:00
|
|
|
int i, size = sizeof(MDeformVert);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
|
memcpy(dest, source, count * size);
|
|
|
|
|
|
2019-09-08 00:12:26 +10:00
|
|
|
for (i = 0; i < count; i++) {
|
2021-12-25 14:28:22 -06:00
|
|
|
MDeformVert *dvert = static_cast<MDeformVert *>(POINTER_OFFSET(dest, i * size));
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (dvert->totweight) {
|
2021-12-25 14:28:22 -06:00
|
|
|
MDeformWeight *dw = static_cast<MDeformWeight *>(
|
|
|
|
|
MEM_malloc_arrayN(dvert->totweight, sizeof(*dw), __func__));
|
2008-04-15 18:07:04 +00:00
|
|
|
|
|
|
|
|
memcpy(dw, dvert->dw, dvert->totweight * sizeof(*dw));
|
|
|
|
|
dvert->dw = dw;
|
|
|
|
|
}
|
2019-04-22 09:39:35 +10:00
|
|
|
else {
|
2021-12-25 14:28:22 -06:00
|
|
|
dvert->dw = nullptr;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-05 17:41:48 -05:00
|
|
|
static void layerFree_mdeformvert(void *data, const int count)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2023-12-05 17:41:48 -05:00
|
|
|
for (MDeformVert &dvert : MutableSpan(static_cast<MDeformVert *>(data), count)) {
|
|
|
|
|
if (dvert.dw) {
|
|
|
|
|
MEM_freeN(dvert.dw);
|
|
|
|
|
dvert.dw = nullptr;
|
|
|
|
|
dvert.totweight = 0;
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 13:51:55 +11:00
|
|
|
static void layerInterp_mdeformvert(const void **sources,
|
|
|
|
|
const float *weights,
|
2022-10-03 17:37:25 -05:00
|
|
|
const float * /*sub_weights*/,
|
2022-08-03 11:58:52 -05:00
|
|
|
const int count,
|
2015-02-23 13:51:55 +11:00
|
|
|
void *dest)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2023-02-03 12:41:01 +11:00
|
|
|
/* A single linked list of #MDeformWeight's.
|
|
|
|
|
* use this to avoid double allocations (which #LinkNode would do). */
|
2013-07-22 18:01:27 +00:00
|
|
|
struct MDeformWeight_Link {
|
2023-06-03 08:36:28 +10:00
|
|
|
MDeformWeight_Link *next;
|
2013-07-22 18:01:27 +00:00
|
|
|
MDeformWeight dw;
|
|
|
|
|
};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-12-25 14:28:22 -06:00
|
|
|
MDeformVert *dvert = static_cast<MDeformVert *>(dest);
|
2022-06-04 13:31:30 +02:00
|
|
|
MDeformWeight_Link *dest_dwlink = nullptr;
|
|
|
|
|
MDeformWeight_Link *node;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* build a list of unique def_nrs for dest */
|
2021-01-26 09:21:42 -06:00
|
|
|
int totweight = 0;
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
2021-12-25 14:28:22 -06:00
|
|
|
const MDeformVert *source = static_cast<const MDeformVert *>(sources[i]);
|
2020-10-05 18:50:38 +02:00
|
|
|
float interp_weight = weights[i];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-01-26 09:21:42 -06:00
|
|
|
for (int j = 0; j < source->totweight; j++) {
|
2006-08-28 01:12:36 +00:00
|
|
|
MDeformWeight *dw = &source->dw[j];
|
2013-05-14 16:22:53 +00:00
|
|
|
float weight = dw->weight * interp_weight;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (weight == 0.0f) {
|
2013-05-14 16:22:53 +00:00
|
|
|
continue;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-07-22 18:01:27 +00:00
|
|
|
for (node = dest_dwlink; node; node = node->next) {
|
|
|
|
|
MDeformWeight *tmp_dw = &node->dw;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (tmp_dw->def_nr == dw->def_nr) {
|
2013-05-14 16:22:53 +00:00
|
|
|
tmp_dw->weight += weight;
|
2006-08-28 01:12:36 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* if this def_nr is not in the list, add it */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!node) {
|
2022-06-04 13:31:30 +02:00
|
|
|
MDeformWeight_Link *tmp_dwlink = static_cast<MDeformWeight_Link *>(
|
2021-12-25 14:28:22 -06:00
|
|
|
alloca(sizeof(*tmp_dwlink)));
|
2013-07-22 18:01:27 +00:00
|
|
|
tmp_dwlink->dw.def_nr = dw->def_nr;
|
|
|
|
|
tmp_dwlink->dw.weight = weight;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-01-06 13:54:52 +11:00
|
|
|
/* Inline linked-list. */
|
2013-07-22 18:01:27 +00:00
|
|
|
tmp_dwlink->next = dest_dwlink;
|
|
|
|
|
dest_dwlink = tmp_dwlink;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
totweight++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-17 00:54:22 +10:00
|
|
|
/* Delay writing to the destination in case dest is in sources. */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* now we know how many unique deform weights there are, so realloc */
|
2013-07-22 18:01:27 +00:00
|
|
|
if (dvert->dw && (dvert->totweight == totweight)) {
|
2020-07-07 12:44:47 +10:00
|
|
|
/* pass (fast-path if we don't need to realloc). */
|
2013-07-22 18:01:27 +00:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (dvert->dw) {
|
|
|
|
|
MEM_freeN(dvert->dw);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-07-22 18:01:27 +00:00
|
|
|
if (totweight) {
|
2021-12-25 14:28:22 -06:00
|
|
|
dvert->dw = static_cast<MDeformWeight *>(
|
|
|
|
|
MEM_malloc_arrayN(totweight, sizeof(*dvert->dw), __func__));
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2013-07-22 18:01:27 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (totweight) {
|
2006-11-11 23:23:15 +00:00
|
|
|
dvert->totweight = totweight;
|
2021-01-26 09:21:42 -06:00
|
|
|
int i = 0;
|
|
|
|
|
for (node = dest_dwlink; node; node = node->next, i++) {
|
2020-04-10 10:59:27 -04:00
|
|
|
if (node->dw.weight > 1.0f) {
|
|
|
|
|
node->dw.weight = 1.0f;
|
|
|
|
|
}
|
2013-07-22 18:01:27 +00:00
|
|
|
dvert->dw[i] = node->dw;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2013-07-22 18:01:27 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2006-11-11 23:23:15 +00:00
|
|
|
memset(dvert, 0, sizeof(*dvert));
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2013-07-22 18:01:27 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
static void layerConstruct_mdeformvert(void *data, const int count)
|
|
|
|
|
{
|
|
|
|
|
memset(data, 0, sizeof(MDeformVert) * count);
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-25 12:49:01 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Callbacks for (#vec3f, #CD_NORMAL)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2015-02-23 13:51:55 +11:00
|
|
|
static void layerInterp_normal(const void **sources,
|
|
|
|
|
const float *weights,
|
2022-10-03 17:37:25 -05:00
|
|
|
const float * /*sub_weights*/,
|
2022-08-03 11:58:52 -05:00
|
|
|
const int count,
|
2015-02-23 13:51:55 +11:00
|
|
|
void *dest)
|
2015-02-05 14:38:59 +01:00
|
|
|
{
|
2021-07-03 23:08:40 +10:00
|
|
|
/* NOTE: This is linear interpolation, which is not optimal for vectors.
|
2019-04-27 12:07:07 +10:00
|
|
|
* Unfortunately, spherical interpolation of more than two values is hairy,
|
|
|
|
|
* so for now it will do... */
|
2015-02-05 14:38:59 +01:00
|
|
|
float no[3] = {0.0f};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
for (const int i : IndexRange(count)) {
|
|
|
|
|
madd_v3_v3fl(no, (const float *)sources[i], weights[i]);
|
2015-02-05 14:38:59 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-10-16 21:52:50 +02:00
|
|
|
/* Weighted sum of normalized vectors will **not** be normalized, even if weights are. */
|
|
|
|
|
normalize_v3_v3((float *)dest, no);
|
2015-02-05 14:38:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void layerCopyValue_normal(const void *source,
|
|
|
|
|
void *dest,
|
|
|
|
|
const int mixmode,
|
|
|
|
|
const float mixfactor)
|
|
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
const float *no_src = (const float *)source;
|
|
|
|
|
float *no_dst = (float *)dest;
|
2015-02-05 14:38:59 +01:00
|
|
|
float no_tmp[3];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-02-05 14:38:59 +01:00
|
|
|
if (ELEM(mixmode,
|
|
|
|
|
CDT_MIX_NOMIX,
|
|
|
|
|
CDT_MIX_REPLACE_ABOVE_THRESHOLD,
|
2024-01-02 18:12:54 +01:00
|
|
|
CDT_MIX_REPLACE_BELOW_THRESHOLD))
|
|
|
|
|
{
|
2015-02-05 14:38:59 +01:00
|
|
|
/* Above/below threshold modes are not supported here, fallback to nomix (just in case). */
|
|
|
|
|
copy_v3_v3(no_dst, no_src);
|
|
|
|
|
}
|
|
|
|
|
else { /* Modes that support 'real' mix factor. */
|
|
|
|
|
/* Since we normalize in the end, MIX and ADD are the same op here. */
|
|
|
|
|
if (ELEM(mixmode, CDT_MIX_MIX, CDT_MIX_ADD)) {
|
|
|
|
|
add_v3_v3v3(no_tmp, no_dst, no_src);
|
|
|
|
|
normalize_v3(no_tmp);
|
|
|
|
|
}
|
|
|
|
|
else if (mixmode == CDT_MIX_SUB) {
|
|
|
|
|
sub_v3_v3v3(no_tmp, no_dst, no_src);
|
|
|
|
|
normalize_v3(no_tmp);
|
|
|
|
|
}
|
|
|
|
|
else if (mixmode == CDT_MIX_MUL) {
|
|
|
|
|
mul_v3_v3v3(no_tmp, no_dst, no_src);
|
|
|
|
|
normalize_v3(no_tmp);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
copy_v3_v3(no_tmp, no_src);
|
|
|
|
|
}
|
|
|
|
|
interp_v3_v3v3_slerp_safe(no_dst, no_dst, no_tmp, mixfactor);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-25 12:49:01 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Callbacks for (#MTFace, #CD_MTFACE)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static void layerCopy_tface(const void *source, void *dest, const int count)
|
2006-11-11 16:38:37 +00:00
|
|
|
{
|
2012-05-12 16:11:34 +00:00
|
|
|
const MTFace *source_tf = (const MTFace *)source;
|
|
|
|
|
MTFace *dest_tf = (MTFace *)dest;
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < count; i++) {
|
2006-11-11 16:38:37 +00:00
|
|
|
dest_tf[i] = source_tf[i];
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2006-11-11 16:38:37 +00:00
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static void layerInterp_tface(const void **sources,
|
|
|
|
|
const float *weights,
|
|
|
|
|
const float *sub_weights,
|
|
|
|
|
const int count,
|
|
|
|
|
void *dest)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
MTFace *tf = static_cast<MTFace *>(dest);
|
2011-12-29 11:18:12 +00:00
|
|
|
float uv[4][2] = {{0.0f}};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-01-26 09:21:42 -06:00
|
|
|
const float *sub_weight = sub_weights;
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
2020-10-05 18:50:38 +02:00
|
|
|
const float interp_weight = weights[i];
|
2021-12-25 14:28:22 -06:00
|
|
|
const MTFace *src = static_cast<const MTFace *>(sources[i]);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-01-26 09:21:42 -06:00
|
|
|
for (int j = 0; j < 4; j++) {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (sub_weights) {
|
2021-01-26 09:21:42 -06:00
|
|
|
for (int k = 0; k < 4; k++, sub_weight++) {
|
2020-10-05 18:50:38 +02:00
|
|
|
madd_v2_v2fl(uv[j], src->uv[k], (*sub_weight) * interp_weight);
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
2011-12-29 11:18:12 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2020-10-05 18:50:38 +02:00
|
|
|
madd_v2_v2fl(uv[j], src->uv[j], interp_weight);
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-17 00:54:22 +10:00
|
|
|
/* Delay writing to the destination in case dest is in sources. */
|
2011-12-29 11:18:12 +00:00
|
|
|
*tf = *(MTFace *)(*sources);
|
|
|
|
|
memcpy(tf->uv, uv, sizeof(tf->uv));
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
}
|
|
|
|
|
|
2010-04-10 22:12:10 +00:00
|
|
|
static void layerSwap_tface(void *data, const int *corner_indices)
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
MTFace *tf = static_cast<MTFace *>(data);
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
float uv[4][2];
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2021-01-26 09:21:42 -06:00
|
|
|
for (int j = 0; j < 4; j++) {
|
2011-12-29 11:18:12 +00:00
|
|
|
const int source_index = corner_indices[j];
|
|
|
|
|
copy_v2_v2(uv[j], tf->uv[source_index]);
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
|
|
|
|
|
memcpy(tf->uv, uv, sizeof(tf->uv));
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static void layerDefault_tface(void *data, const int count)
|
2006-11-11 16:38:37 +00:00
|
|
|
{
|
2017-05-25 00:34:14 +10:00
|
|
|
static MTFace default_tf = {{{0, 0}, {1, 0}, {1, 1}, {0, 1}}};
|
2012-05-12 16:11:34 +00:00
|
|
|
MTFace *tf = (MTFace *)data;
|
2006-11-11 16:38:37 +00:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < count; i++) {
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
tf[i] = default_tf;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2006-11-11 16:38:37 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-25 14:28:22 -06:00
|
|
|
static int layerMaxNum_tface()
|
2014-10-21 17:01:56 +02:00
|
|
|
{
|
|
|
|
|
return MAX_MTFACE;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-25 12:49:01 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Callbacks for (#MFloatProperty, #CD_PROP_FLOAT)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static void layerCopy_propFloat(const void *source, void *dest, const int count)
|
2011-04-16 13:00:41 +00:00
|
|
|
{
|
2012-05-12 16:11:34 +00:00
|
|
|
memcpy(dest, source, sizeof(MFloatProperty) * count);
|
2011-04-16 13:00:41 +00:00
|
|
|
}
|
|
|
|
|
|
2021-02-16 14:25:35 +01:00
|
|
|
static void layerInterp_propFloat(const void **sources,
|
|
|
|
|
const float *weights,
|
2022-10-03 17:37:25 -05:00
|
|
|
const float * /*sub_weights*/,
|
2022-08-03 11:58:52 -05:00
|
|
|
const int count,
|
2021-02-16 14:25:35 +01:00
|
|
|
void *dest)
|
|
|
|
|
{
|
|
|
|
|
float result = 0.0f;
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
|
|
const float interp_weight = weights[i];
|
|
|
|
|
const float src = *(const float *)sources[i];
|
|
|
|
|
result += src * interp_weight;
|
|
|
|
|
}
|
|
|
|
|
*(float *)dest = result;
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-03 16:19:08 +01:00
|
|
|
static bool layerValidate_propFloat(void *data, const uint totitems, const bool do_fixes)
|
|
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
MFloatProperty *fp = static_cast<MFloatProperty *>(data);
|
2018-12-03 16:19:08 +01:00
|
|
|
bool has_errors = false;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < totitems; i++, fp++) {
|
|
|
|
|
if (!isfinite(fp->f)) {
|
|
|
|
|
if (do_fixes) {
|
|
|
|
|
fp->f = 0.0f;
|
|
|
|
|
}
|
|
|
|
|
has_errors = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return has_errors;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-25 12:49:01 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Callbacks for (#MIntProperty, #CD_PROP_INT32)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2022-05-31 19:23:52 +02:00
|
|
|
static void layerInterp_propInt(const void **sources,
|
|
|
|
|
const float *weights,
|
2022-10-03 17:37:25 -05:00
|
|
|
const float * /*sub_weights*/,
|
2022-08-03 11:58:52 -05:00
|
|
|
const int count,
|
2022-05-31 19:23:52 +02:00
|
|
|
void *dest)
|
|
|
|
|
{
|
|
|
|
|
float result = 0.0f;
|
|
|
|
|
for (const int i : IndexRange(count)) {
|
|
|
|
|
const float weight = weights[i];
|
|
|
|
|
const float src = *static_cast<const int *>(sources[i]);
|
|
|
|
|
result += src * weight;
|
|
|
|
|
}
|
2022-09-25 18:30:50 +10:00
|
|
|
const int rounded_result = int(round(result));
|
2022-05-31 19:23:52 +02:00
|
|
|
*static_cast<int *>(dest) = rounded_result;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-25 12:49:01 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Callbacks for (#MStringProperty, #CD_PROP_STRING)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static void layerCopy_propString(const void *source, void *dest, const int count)
|
2011-04-16 13:00:41 +00:00
|
|
|
{
|
2012-05-12 16:11:34 +00:00
|
|
|
memcpy(dest, source, sizeof(MStringProperty) * count);
|
2011-04-16 13:00:41 +00:00
|
|
|
}
|
|
|
|
|
|
2022-03-25 12:49:01 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Callbacks for (#OrigSpaceFace, #CD_ORIGSPACE)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static void layerCopy_origspace_face(const void *source, void *dest, const int count)
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
{
|
2012-05-12 16:11:34 +00:00
|
|
|
const OrigSpaceFace *source_tf = (const OrigSpaceFace *)source;
|
|
|
|
|
OrigSpaceFace *dest_tf = (OrigSpaceFace *)dest;
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < count; i++) {
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
dest_tf[i] = source_tf[i];
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static void layerInterp_origspace_face(const void **sources,
|
|
|
|
|
const float *weights,
|
|
|
|
|
const float *sub_weights,
|
|
|
|
|
const int count,
|
|
|
|
|
void *dest)
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
OrigSpaceFace *osf = static_cast<OrigSpaceFace *>(dest);
|
2011-12-29 11:18:12 +00:00
|
|
|
float uv[4][2] = {{0.0f}};
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
|
2021-01-26 09:21:42 -06:00
|
|
|
const float *sub_weight = sub_weights;
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
2020-10-05 18:50:38 +02:00
|
|
|
const float interp_weight = weights[i];
|
2021-12-25 14:28:22 -06:00
|
|
|
const OrigSpaceFace *src = static_cast<const OrigSpaceFace *>(sources[i]);
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
|
2021-01-26 09:21:42 -06:00
|
|
|
for (int j = 0; j < 4; j++) {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (sub_weights) {
|
2021-01-26 09:21:42 -06:00
|
|
|
for (int k = 0; k < 4; k++, sub_weight++) {
|
2020-10-05 18:50:38 +02:00
|
|
|
madd_v2_v2fl(uv[j], src->uv[k], (*sub_weight) * interp_weight);
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2020-10-05 18:50:38 +02:00
|
|
|
madd_v2_v2fl(uv[j], src->uv[j], interp_weight);
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-17 00:54:22 +10:00
|
|
|
/* Delay writing to the destination in case dest is in sources. */
|
2011-12-29 11:18:12 +00:00
|
|
|
memcpy(osf->uv, uv, sizeof(osf->uv));
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
}
|
|
|
|
|
|
2010-04-10 22:12:10 +00:00
|
|
|
static void layerSwap_origspace_face(void *data, const int *corner_indices)
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
OrigSpaceFace *osf = static_cast<OrigSpaceFace *>(data);
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
float uv[4][2];
|
|
|
|
|
|
2021-01-26 09:21:42 -06:00
|
|
|
for (int j = 0; j < 4; j++) {
|
2011-12-29 11:18:12 +00:00
|
|
|
copy_v2_v2(uv[j], osf->uv[corner_indices[j]]);
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
}
|
|
|
|
|
memcpy(osf->uv, uv, sizeof(osf->uv));
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static void layerDefault_origspace_face(void *data, const int count)
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
{
|
|
|
|
|
static OrigSpaceFace default_osf = {{{0, 0}, {1, 0}, {1, 1}, {0, 1}}};
|
2012-05-12 16:11:34 +00:00
|
|
|
OrigSpaceFace *osf = (OrigSpaceFace *)data;
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < count; i++) {
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
osf[i] = default_osf;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
}
|
2009-01-06 18:59:03 +00:00
|
|
|
|
2022-03-25 12:49:01 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Callbacks for (#MDisps, #CD_MDISPS)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2010-04-17 15:47:00 +00:00
|
|
|
static void layerSwap_mdisps(void *data, const int *ci)
|
2009-01-06 18:59:03 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
MDisps *s = static_cast<MDisps *>(data);
|
2009-01-06 18:59:03 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (s->disps) {
|
2012-05-12 16:11:34 +00:00
|
|
|
int nverts = (ci[1] == 3) ? 4 : 3; /* silly way to know vertex count of face */
|
2021-01-26 09:21:42 -06:00
|
|
|
int corners = multires_mdisp_corners(s);
|
|
|
|
|
int cornersize = s->totdisp / corners;
|
2009-01-06 18:59:03 +00:00
|
|
|
|
2012-05-12 16:11:34 +00:00
|
|
|
if (corners != nverts) {
|
2010-10-16 20:43:16 +00:00
|
|
|
/* happens when face changed vertex count in edit mode
|
2012-03-03 20:19:11 +00:00
|
|
|
* if it happened, just forgot displacement */
|
2009-01-06 18:59:03 +00:00
|
|
|
|
2012-01-25 20:18:12 +00:00
|
|
|
MEM_freeN(s->disps);
|
2012-05-12 16:11:34 +00:00
|
|
|
s->totdisp = (s->totdisp / corners) * nverts;
|
2021-12-25 14:28:22 -06:00
|
|
|
s->disps = (float(*)[3])MEM_calloc_arrayN(s->totdisp, sizeof(float[3]), "mdisp swap");
|
2010-10-16 20:43:16 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-25 14:28:22 -06:00
|
|
|
float(*d)[3] = (float(*)[3])MEM_calloc_arrayN(s->totdisp, sizeof(float[3]), "mdisps swap");
|
2009-01-06 18:59:03 +00:00
|
|
|
|
2021-01-26 09:21:42 -06:00
|
|
|
for (int S = 0; S < corners; S++) {
|
2020-08-08 13:29:21 +10:00
|
|
|
memcpy(d + cornersize * S, s->disps + cornersize * ci[S], sizeof(float[3]) * cornersize);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2012-01-25 20:18:12 +00:00
|
|
|
MEM_freeN(s->disps);
|
2012-05-12 16:11:34 +00:00
|
|
|
s->disps = d;
|
2010-09-30 22:27:37 +00:00
|
|
|
}
|
2009-01-06 18:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static void layerCopy_mdisps(const void *source, void *dest, const int count)
|
2009-01-06 18:59:03 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
const MDisps *s = static_cast<const MDisps *>(source);
|
|
|
|
|
MDisps *d = static_cast<MDisps *>(dest);
|
2009-01-06 18:59:03 +00:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < count; i++) {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (s[i].disps) {
|
2021-12-25 14:28:22 -06:00
|
|
|
d[i].disps = static_cast<float(*)[3]>(MEM_dupallocN(s[i].disps));
|
2022-09-25 17:04:52 +10:00
|
|
|
d[i].hidden = static_cast<uint *>(MEM_dupallocN(s[i].hidden));
|
2009-01-06 18:59:03 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2021-12-25 14:28:22 -06:00
|
|
|
d[i].disps = nullptr;
|
|
|
|
|
d[i].hidden = nullptr;
|
2009-01-06 18:59:03 +00:00
|
|
|
}
|
2013-11-26 17:09:15 +01:00
|
|
|
|
|
|
|
|
/* still copy even if not in memory, displacement can be external */
|
|
|
|
|
d[i].totdisp = s[i].totdisp;
|
|
|
|
|
d[i].level = s[i].level;
|
2009-01-06 18:59:03 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-05 17:41:48 -05:00
|
|
|
static void layerFree_mdisps(void *data, const int count)
|
2009-01-06 18:59:03 +00:00
|
|
|
{
|
2023-12-05 17:41:48 -05:00
|
|
|
for (MDisps &d : MutableSpan(static_cast<MDisps *>(data), count)) {
|
|
|
|
|
MEM_SAFE_FREE(d.disps);
|
|
|
|
|
MEM_SAFE_FREE(d.hidden);
|
|
|
|
|
d.totdisp = 0;
|
|
|
|
|
d.level = 0;
|
2009-01-06 18:59:03 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
static void layerConstruct_mdisps(void *data, const int count)
|
|
|
|
|
{
|
|
|
|
|
memset(data, 0, sizeof(MDisps) * count);
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static bool layerRead_mdisps(CDataFile *cdf, void *data, const int count)
|
2009-11-25 14:27:50 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
MDisps *d = static_cast<MDisps *>(data);
|
2009-11-25 14:27:50 +00:00
|
|
|
|
2020-09-02 19:10:18 +02:00
|
|
|
for (int i = 0; i < count; i++) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!d[i].disps) {
|
2021-12-25 14:28:22 -06:00
|
|
|
d[i].disps = (float(*)[3])MEM_calloc_arrayN(d[i].totdisp, sizeof(float[3]), "mdisps read");
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2009-11-25 14:27:50 +00:00
|
|
|
|
2020-08-08 13:29:21 +10:00
|
|
|
if (!cdf_read_data(cdf, sizeof(float[3]) * d[i].totdisp, d[i].disps)) {
|
2019-02-01 12:44:19 +11:00
|
|
|
CLOG_ERROR(&LOG, "failed to read multires displacement %d/%d %d", i, count, d[i].totdisp);
|
2021-12-25 14:28:22 -06:00
|
|
|
return false;
|
2009-11-25 14:27:50 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-02 19:10:18 +02:00
|
|
|
return true;
|
2009-11-25 14:27:50 +00:00
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static bool layerWrite_mdisps(CDataFile *cdf, const void *data, const int count)
|
2009-11-25 14:27:50 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
const MDisps *d = static_cast<const MDisps *>(data);
|
2009-11-25 14:27:50 +00:00
|
|
|
|
2020-09-02 19:10:18 +02:00
|
|
|
for (int i = 0; i < count; i++) {
|
2020-08-08 13:29:21 +10:00
|
|
|
if (!cdf_write_data(cdf, sizeof(float[3]) * d[i].totdisp, d[i].disps)) {
|
2019-02-01 12:44:19 +11:00
|
|
|
CLOG_ERROR(&LOG, "failed to write multires displacement %d/%d %d", i, count, d[i].totdisp);
|
2021-12-25 14:28:22 -06:00
|
|
|
return false;
|
2009-11-25 14:27:50 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-02 19:10:18 +02:00
|
|
|
return true;
|
2009-11-25 14:27:50 +00:00
|
|
|
}
|
|
|
|
|
|
2022-10-03 17:37:25 -05:00
|
|
|
static size_t layerFilesize_mdisps(CDataFile * /*cdf*/, const void *data, const int count)
|
2009-12-10 14:26:06 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
const MDisps *d = static_cast<const MDisps *>(data);
|
2009-12-10 14:26:06 +00:00
|
|
|
size_t size = 0;
|
|
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < count; i++) {
|
2020-08-08 13:29:21 +10:00
|
|
|
size += sizeof(float[3]) * d[i].totdisp;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2009-12-10 14:26:06 +00:00
|
|
|
|
|
|
|
|
return size;
|
|
|
|
|
}
|
2022-03-25 12:49:01 +11:00
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
2022-08-03 13:19:43 -05:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Callbacks for (#CD_BM_ELEM_PYPTR)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
/* copy just zeros in this case */
|
2022-10-03 17:37:25 -05:00
|
|
|
static void layerCopy_bmesh_elem_py_ptr(const void * /*source*/, void *dest, const int count)
|
2022-08-03 13:19:43 -05:00
|
|
|
{
|
|
|
|
|
const int size = sizeof(void *);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
|
|
void **ptr = (void **)POINTER_OFFSET(dest, i * size);
|
|
|
|
|
*ptr = nullptr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifndef WITH_PYTHON
|
2022-10-03 17:37:25 -05:00
|
|
|
void bpy_bm_generic_invalidate(struct BPy_BMGeneric * /*self*/)
|
2022-08-03 13:19:43 -05:00
|
|
|
{
|
|
|
|
|
/* dummy */
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2023-12-05 17:41:48 -05:00
|
|
|
static void layerFree_bmesh_elem_py_ptr(void *data, const int count)
|
2022-08-03 13:19:43 -05:00
|
|
|
{
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
2023-12-05 17:41:48 -05:00
|
|
|
void **ptr = (void **)POINTER_OFFSET(data, i * sizeof(void *));
|
2022-08-03 13:19:43 -05:00
|
|
|
if (*ptr) {
|
|
|
|
|
bpy_bm_generic_invalidate(static_cast<BPy_BMGeneric *>(*ptr));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
2022-03-25 12:49:01 +11:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Callbacks for (#GridPaintMask, #CD_GRID_PAINT_MASK)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static void layerCopy_grid_paint_mask(const void *source, void *dest, const int count)
|
2012-05-10 20:33:24 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
const GridPaintMask *s = static_cast<const GridPaintMask *>(source);
|
|
|
|
|
GridPaintMask *d = static_cast<GridPaintMask *>(dest);
|
2012-05-10 20:33:24 +00:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < count; i++) {
|
2012-05-12 16:11:34 +00:00
|
|
|
if (s[i].data) {
|
2021-12-25 14:28:22 -06:00
|
|
|
d[i].data = static_cast<float *>(MEM_dupallocN(s[i].data));
|
2012-05-10 20:33:24 +00:00
|
|
|
d[i].level = s[i].level;
|
|
|
|
|
}
|
|
|
|
|
else {
|
2021-12-25 14:28:22 -06:00
|
|
|
d[i].data = nullptr;
|
2012-05-10 20:33:24 +00:00
|
|
|
d[i].level = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-05 17:41:48 -05:00
|
|
|
static void layerFree_grid_paint_mask(void *data, const int count)
|
2012-05-10 20:33:24 +00:00
|
|
|
{
|
2023-12-05 17:41:48 -05:00
|
|
|
for (GridPaintMask &gpm : MutableSpan(static_cast<GridPaintMask *>(data), count)) {
|
|
|
|
|
MEM_SAFE_FREE(gpm.data);
|
|
|
|
|
gpm.level = 0;
|
2012-05-10 20:33:24 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
static void layerConstruct_grid_paint_mask(void *data, const int count)
|
|
|
|
|
{
|
|
|
|
|
memset(data, 0, sizeof(GridPaintMask) * count);
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-25 16:34:03 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Callbacks for (#MLoopCol, #CD_PROP_BYTE_COLOR)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
static void layerCopyValue_mloopcol(const void *source,
|
|
|
|
|
void *dest,
|
|
|
|
|
const int mixmode,
|
|
|
|
|
const float mixfactor)
|
2009-08-12 03:51:28 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
const MLoopCol *m1 = static_cast<const MLoopCol *>(source);
|
|
|
|
|
MLoopCol *m2 = static_cast<MLoopCol *>(dest);
|
2022-09-25 17:04:52 +10:00
|
|
|
uchar tmp_col[4];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
if (ELEM(mixmode,
|
|
|
|
|
CDT_MIX_NOMIX,
|
|
|
|
|
CDT_MIX_REPLACE_ABOVE_THRESHOLD,
|
2024-01-02 18:12:54 +01:00
|
|
|
CDT_MIX_REPLACE_BELOW_THRESHOLD))
|
|
|
|
|
{
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
/* Modes that do a full copy or nothing. */
|
|
|
|
|
if (ELEM(mixmode, CDT_MIX_REPLACE_ABOVE_THRESHOLD, CDT_MIX_REPLACE_BELOW_THRESHOLD)) {
|
|
|
|
|
/* TODO: Check for a real valid way to get 'factor' value of our dest color? */
|
2022-09-25 18:33:28 +10:00
|
|
|
const float f = (float(m2->r) + float(m2->g) + float(m2->b)) / 3.0f;
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
if (mixmode == CDT_MIX_REPLACE_ABOVE_THRESHOLD && f < mixfactor) {
|
|
|
|
|
return; /* Do Nothing! */
|
|
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
if (mixmode == CDT_MIX_REPLACE_BELOW_THRESHOLD && f > mixfactor) {
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
return; /* Do Nothing! */
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
m2->r = m1->r;
|
|
|
|
|
m2->g = m1->g;
|
|
|
|
|
m2->b = m1->b;
|
2020-10-27 13:55:10 +01:00
|
|
|
m2->a = m1->a;
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
}
|
|
|
|
|
else { /* Modes that support 'real' mix factor. */
|
2022-09-25 17:04:52 +10:00
|
|
|
uchar src[4] = {m1->r, m1->g, m1->b, m1->a};
|
|
|
|
|
uchar dst[4] = {m2->r, m2->g, m2->b, m2->a};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
if (mixmode == CDT_MIX_MIX) {
|
|
|
|
|
blend_color_mix_byte(tmp_col, dst, src);
|
|
|
|
|
}
|
|
|
|
|
else if (mixmode == CDT_MIX_ADD) {
|
|
|
|
|
blend_color_add_byte(tmp_col, dst, src);
|
|
|
|
|
}
|
|
|
|
|
else if (mixmode == CDT_MIX_SUB) {
|
|
|
|
|
blend_color_sub_byte(tmp_col, dst, src);
|
|
|
|
|
}
|
|
|
|
|
else if (mixmode == CDT_MIX_MUL) {
|
|
|
|
|
blend_color_mul_byte(tmp_col, dst, src);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
memcpy(tmp_col, src, sizeof(tmp_col));
|
|
|
|
|
}
|
2020-10-27 13:55:10 +01:00
|
|
|
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
blend_color_interpolate_byte(dst, dst, tmp_col, mixfactor);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-25 18:33:28 +10:00
|
|
|
m2->r = char(dst[0]);
|
|
|
|
|
m2->g = char(dst[1]);
|
|
|
|
|
m2->b = char(dst[2]);
|
|
|
|
|
m2->a = char(dst[3]);
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
}
|
2009-08-12 03:51:28 +00:00
|
|
|
}
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
|
2014-09-09 16:12:07 +10:00
|
|
|
static bool layerEqual_mloopcol(const void *data1, const void *data2)
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
const MLoopCol *m1 = static_cast<const MLoopCol *>(data1);
|
|
|
|
|
const MLoopCol *m2 = static_cast<const MLoopCol *>(data2);
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
float r, g, b, a;
|
|
|
|
|
|
|
|
|
|
r = m1->r - m2->r;
|
|
|
|
|
g = m1->g - m2->g;
|
|
|
|
|
b = m1->b - m2->b;
|
|
|
|
|
a = m1->a - m2->a;
|
|
|
|
|
|
2012-05-03 21:35:04 +00:00
|
|
|
return r * r + g * g + b * b + a * a < 0.001f;
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static void layerMultiply_mloopcol(void *data, const float fac)
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
MLoopCol *m = static_cast<MLoopCol *>(data);
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
|
2022-09-25 18:33:28 +10:00
|
|
|
m->r = float(m->r) * fac;
|
|
|
|
|
m->g = float(m->g) * fac;
|
|
|
|
|
m->b = float(m->b) * fac;
|
|
|
|
|
m->a = float(m->a) * fac;
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
}
|
|
|
|
|
|
2014-09-09 16:12:07 +10:00
|
|
|
static void layerAdd_mloopcol(void *data1, const void *data2)
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
MLoopCol *m = static_cast<MLoopCol *>(data1);
|
|
|
|
|
const MLoopCol *m2 = static_cast<const MLoopCol *>(data2);
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
|
|
|
|
|
m->r += m2->r;
|
|
|
|
|
m->g += m2->g;
|
|
|
|
|
m->b += m2->b;
|
|
|
|
|
m->a += m2->a;
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-09 16:12:07 +10:00
|
|
|
static void layerDoMinMax_mloopcol(const void *data, void *vmin, void *vmax)
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
const MLoopCol *m = static_cast<const MLoopCol *>(data);
|
|
|
|
|
MLoopCol *min = static_cast<MLoopCol *>(vmin);
|
|
|
|
|
MLoopCol *max = static_cast<MLoopCol *>(vmax);
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (m->r < min->r) {
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
min->r = m->r;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (m->g < min->g) {
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
min->g = m->g;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (m->b < min->b) {
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
min->b = m->b;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (m->a < min->a) {
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
min->a = m->a;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (m->r > max->r) {
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
max->r = m->r;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (m->g > max->g) {
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
max->g = m->g;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (m->b > max->b) {
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
max->b = m->b;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (m->a > max->a) {
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
max->a = m->a;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void layerInitMinMax_mloopcol(void *vmin, void *vmax)
|
|
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
MLoopCol *min = static_cast<MLoopCol *>(vmin);
|
|
|
|
|
MLoopCol *max = static_cast<MLoopCol *>(vmax);
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
|
|
|
|
|
min->r = 255;
|
|
|
|
|
min->g = 255;
|
|
|
|
|
min->b = 255;
|
|
|
|
|
min->a = 255;
|
|
|
|
|
|
|
|
|
|
max->r = 0;
|
|
|
|
|
max->g = 0;
|
|
|
|
|
max->b = 0;
|
|
|
|
|
max->a = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static void layerDefault_mloopcol(void *data, const int count)
|
2008-07-08 02:22:37 +00:00
|
|
|
{
|
2012-04-29 15:47:02 +00:00
|
|
|
MLoopCol default_mloopcol = {255, 255, 255, 255};
|
2012-05-12 16:11:34 +00:00
|
|
|
MLoopCol *mlcol = (MLoopCol *)data;
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < count; i++) {
|
2008-07-08 02:22:37 +00:00
|
|
|
mlcol[i] = default_mloopcol;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2008-07-08 02:22:37 +00:00
|
|
|
}
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
|
2020-10-05 18:50:38 +02:00
|
|
|
static void layerInterp_mloopcol(const void **sources,
|
|
|
|
|
const float *weights,
|
2022-10-03 17:37:25 -05:00
|
|
|
const float * /*sub_weights*/,
|
2020-10-05 18:50:38 +02:00
|
|
|
int count,
|
|
|
|
|
void *dest)
|
2008-07-08 02:22:37 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
MLoopCol *mc = static_cast<MLoopCol *>(dest);
|
2008-07-08 02:22:37 +00:00
|
|
|
struct {
|
|
|
|
|
float a;
|
|
|
|
|
float r;
|
|
|
|
|
float g;
|
|
|
|
|
float b;
|
2017-03-24 04:06:30 -03:00
|
|
|
} col = {0};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int i = 0; i < count; i++) {
|
2020-10-05 18:50:38 +02:00
|
|
|
const float interp_weight = weights[i];
|
2021-12-25 14:28:22 -06:00
|
|
|
const MLoopCol *src = static_cast<const MLoopCol *>(sources[i]);
|
2020-10-05 18:50:38 +02:00
|
|
|
col.r += src->r * interp_weight;
|
|
|
|
|
col.g += src->g * interp_weight;
|
|
|
|
|
col.b += src->b * interp_weight;
|
|
|
|
|
col.a += src->a * interp_weight;
|
2008-07-08 02:22:37 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-06-08 20:08:19 +00:00
|
|
|
/* Subdivide smooth or fractal can cause problems without clamping
|
|
|
|
|
* although weights should also not cause this situation */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-17 00:54:22 +10:00
|
|
|
/* Also delay writing to the destination in case dest is in sources. */
|
2017-09-18 21:11:41 +10:00
|
|
|
mc->r = round_fl_to_uchar_clamp(col.r);
|
|
|
|
|
mc->g = round_fl_to_uchar_clamp(col.g);
|
|
|
|
|
mc->b = round_fl_to_uchar_clamp(col.b);
|
|
|
|
|
mc->a = round_fl_to_uchar_clamp(col.a);
|
2008-07-08 02:22:37 +00:00
|
|
|
}
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
|
2022-04-25 16:34:03 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
Mesh: Move UV layers to generic attributes
Currently the `MLoopUV` struct stores UV coordinates and flags related
to editing UV maps in the UV editor. This patch changes the coordinates
to use the generic 2D vector type, and moves the flags into three
separate boolean attributes. This follows the design in T95965, with
the ultimate intention of simplifying code and improving performance.
Importantly, the change allows exporters and renderers to use UVs
"touched" by geometry nodes, which only creates generic attributes.
It also allows geometry nodes to create "proper" UV maps from scratch,
though only with the Store Named Attribute node for now.
The new design considers any 2D vector attribute on the corner domain
to be a UV map. In the future, they might be distinguished from regular
2D vectors with attribute metadata, which may be helpful because they
are often interpolated differently.
Most of the code changes deal with passing around UV BMesh custom data
offsets and tracking the boolean "sublayers". The boolean layers are
use the following prefixes for attribute names: vert selection: `.vs.`,
edge selection: `.es.`, pinning: `.pn.`. Currently these are short to
avoid using up the maximum length of attribute names. To accommodate
for these 4 extra characters, the name length limit is enlarged to 68
bytes, while the maximum user settable name length is still 64 bytes.
Unfortunately Python/RNA API access to the UV flag data becomes slower.
Accessing the boolean layers directly is be better for performance in
general.
Like the other mesh SoA refactors, backward and forward compatibility
aren't affected, and won't be changed until 4.0. We pay for that by
making mesh reading and writing more expensive with conversions.
Resolves T85962
Differential Revision: https://developer.blender.org/D14365
2023-01-10 00:47:04 -05:00
|
|
|
/** \name Callbacks for #OrigSpaceLoop
|
2022-04-25 16:34:03 +10:00
|
|
|
* \{ */
|
|
|
|
|
|
2023-03-27 12:08:14 +11:00
|
|
|
/* origspace is almost exact copy of #MLoopUV, keep in sync. */
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
static void layerCopyValue_mloop_origspace(const void *source,
|
|
|
|
|
void *dest,
|
2022-10-03 17:37:25 -05:00
|
|
|
const int /*mixmode*/,
|
|
|
|
|
const float /*mixfactor*/)
|
2012-02-05 11:30:26 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
const OrigSpaceLoop *luv1 = static_cast<const OrigSpaceLoop *>(source);
|
|
|
|
|
OrigSpaceLoop *luv2 = static_cast<OrigSpaceLoop *>(dest);
|
2012-02-05 11:30:26 +00:00
|
|
|
|
|
|
|
|
copy_v2_v2(luv2->uv, luv1->uv);
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-09 16:12:07 +10:00
|
|
|
static bool layerEqual_mloop_origspace(const void *data1, const void *data2)
|
2012-02-05 11:30:26 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
const OrigSpaceLoop *luv1 = static_cast<const OrigSpaceLoop *>(data1);
|
|
|
|
|
const OrigSpaceLoop *luv2 = static_cast<const OrigSpaceLoop *>(data2);
|
2012-02-05 11:30:26 +00:00
|
|
|
|
|
|
|
|
return len_squared_v2v2(luv1->uv, luv2->uv) < 0.00001f;
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static void layerMultiply_mloop_origspace(void *data, const float fac)
|
2012-02-05 11:30:26 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
OrigSpaceLoop *luv = static_cast<OrigSpaceLoop *>(data);
|
2012-02-05 11:30:26 +00:00
|
|
|
|
|
|
|
|
mul_v2_fl(luv->uv, fac);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void layerInitMinMax_mloop_origspace(void *vmin, void *vmax)
|
|
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
OrigSpaceLoop *min = static_cast<OrigSpaceLoop *>(vmin);
|
|
|
|
|
OrigSpaceLoop *max = static_cast<OrigSpaceLoop *>(vmax);
|
2012-02-05 11:30:26 +00:00
|
|
|
|
|
|
|
|
INIT_MINMAX2(min->uv, max->uv);
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-09 16:12:07 +10:00
|
|
|
static void layerDoMinMax_mloop_origspace(const void *data, void *vmin, void *vmax)
|
2012-02-05 11:30:26 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
const OrigSpaceLoop *luv = static_cast<const OrigSpaceLoop *>(data);
|
|
|
|
|
OrigSpaceLoop *min = static_cast<OrigSpaceLoop *>(vmin);
|
|
|
|
|
OrigSpaceLoop *max = static_cast<OrigSpaceLoop *>(vmax);
|
2012-02-05 11:30:26 +00:00
|
|
|
|
2012-11-15 22:20:18 +00:00
|
|
|
minmax_v2v2_v2(min->uv, max->uv, luv->uv);
|
2012-02-05 11:30:26 +00:00
|
|
|
}
|
|
|
|
|
|
2014-09-09 16:12:07 +10:00
|
|
|
static void layerAdd_mloop_origspace(void *data1, const void *data2)
|
2012-02-05 11:30:26 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
OrigSpaceLoop *l1 = static_cast<OrigSpaceLoop *>(data1);
|
|
|
|
|
const OrigSpaceLoop *l2 = static_cast<const OrigSpaceLoop *>(data2);
|
2012-02-05 11:30:26 +00:00
|
|
|
|
|
|
|
|
add_v2_v2(l1->uv, l2->uv);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-05 18:50:38 +02:00
|
|
|
static void layerInterp_mloop_origspace(const void **sources,
|
|
|
|
|
const float *weights,
|
2022-10-03 17:37:25 -05:00
|
|
|
const float * /*sub_weights*/,
|
2020-10-05 18:50:38 +02:00
|
|
|
int count,
|
|
|
|
|
void *dest)
|
2012-02-05 11:30:26 +00:00
|
|
|
{
|
2012-08-24 17:01:35 +00:00
|
|
|
float uv[2];
|
2012-02-05 11:30:26 +00:00
|
|
|
zero_v2(uv);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-10-05 18:50:38 +02:00
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
|
|
const float interp_weight = weights[i];
|
2021-12-25 14:28:22 -06:00
|
|
|
const OrigSpaceLoop *src = static_cast<const OrigSpaceLoop *>(sources[i]);
|
2020-10-05 18:50:38 +02:00
|
|
|
madd_v2_v2fl(uv, src->uv, interp_weight);
|
2012-02-05 11:30:26 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-17 00:54:22 +10:00
|
|
|
/* Delay writing to the destination in case dest is in sources. */
|
2012-08-24 17:01:35 +00:00
|
|
|
copy_v2_v2(((OrigSpaceLoop *)dest)->uv, uv);
|
2012-02-05 11:30:26 +00:00
|
|
|
}
|
|
|
|
|
/* --- end copy */
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static void layerInterp_mcol(const void **sources,
|
|
|
|
|
const float *weights,
|
|
|
|
|
const float *sub_weights,
|
|
|
|
|
const int count,
|
|
|
|
|
void *dest)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
MCol *mc = static_cast<MCol *>(dest);
|
2006-08-28 01:12:36 +00:00
|
|
|
struct {
|
|
|
|
|
float a;
|
|
|
|
|
float r;
|
|
|
|
|
float g;
|
|
|
|
|
float b;
|
2011-12-29 11:18:12 +00:00
|
|
|
} col[4] = {{0.0f}};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
const float *sub_weight = sub_weights;
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
2020-10-05 18:50:38 +02:00
|
|
|
const float interp_weight = weights[i];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int j = 0; j < 4; j++) {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (sub_weights) {
|
2021-12-25 14:28:22 -06:00
|
|
|
const MCol *src = static_cast<const MCol *>(sources[i]);
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int k = 0; k < 4; k++, sub_weight++, src++) {
|
2020-10-05 18:50:38 +02:00
|
|
|
const float w = (*sub_weight) * interp_weight;
|
2011-12-29 11:18:12 +00:00
|
|
|
col[j].a += src->a * w;
|
|
|
|
|
col[j].r += src->r * w;
|
|
|
|
|
col[j].g += src->g * w;
|
|
|
|
|
col[j].b += src->b * w;
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2021-12-25 14:28:22 -06:00
|
|
|
const MCol *src = static_cast<const MCol *>(sources[i]);
|
2020-10-05 18:50:38 +02:00
|
|
|
col[j].a += src[j].a * interp_weight;
|
|
|
|
|
col[j].r += src[j].r * interp_weight;
|
|
|
|
|
col[j].g += src[j].g * interp_weight;
|
|
|
|
|
col[j].b += src[j].b * interp_weight;
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-17 00:54:22 +10:00
|
|
|
/* Delay writing to the destination in case dest is in sources. */
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int j = 0; j < 4; j++) {
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-06-08 20:08:19 +00:00
|
|
|
/* Subdivide smooth or fractal can cause problems without clamping
|
|
|
|
|
* although weights should also not cause this situation */
|
2017-09-18 21:11:41 +10:00
|
|
|
mc[j].a = round_fl_to_uchar_clamp(col[j].a);
|
|
|
|
|
mc[j].r = round_fl_to_uchar_clamp(col[j].r);
|
|
|
|
|
mc[j].g = round_fl_to_uchar_clamp(col[j].g);
|
|
|
|
|
mc[j].b = round_fl_to_uchar_clamp(col[j].b);
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-10 22:12:10 +00:00
|
|
|
static void layerSwap_mcol(void *data, const int *corner_indices)
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
MCol *mcol = static_cast<MCol *>(data);
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
MCol col[4];
|
|
|
|
|
|
2021-01-26 09:21:42 -06:00
|
|
|
for (int j = 0; j < 4; j++) {
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
col[j] = mcol[corner_indices[j]];
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
|
|
|
|
|
memcpy(mcol, col, sizeof(col));
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static void layerDefault_mcol(void *data, const int count)
|
2006-11-11 16:38:37 +00:00
|
|
|
{
|
|
|
|
|
static MCol default_mcol = {255, 255, 255, 255};
|
2012-05-12 16:11:34 +00:00
|
|
|
MCol *mcol = (MCol *)data;
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < 4 * count; i++) {
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
mcol[i] = default_mcol;
|
2011-12-28 13:11:46 +00:00
|
|
|
}
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
}
|
2006-11-11 16:38:37 +00:00
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static void layerDefault_origindex(void *data, const int count)
|
2013-09-24 03:58:19 +00:00
|
|
|
{
|
2015-05-05 17:08:29 +10:00
|
|
|
copy_vn_i((int *)data, count, ORIGINDEX_NONE);
|
2013-09-24 03:58:19 +00:00
|
|
|
}
|
|
|
|
|
|
2015-02-23 13:51:55 +11:00
|
|
|
static void layerInterp_shapekey(const void **sources,
|
|
|
|
|
const float *weights,
|
2022-10-03 17:37:25 -05:00
|
|
|
const float * /*sub_weights*/,
|
2015-02-23 13:51:55 +11:00
|
|
|
int count,
|
|
|
|
|
void *dest)
|
2009-11-01 00:06:53 +00:00
|
|
|
{
|
2011-05-09 14:32:55 +00:00
|
|
|
float **in = (float **)sources;
|
2008-07-08 02:22:37 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (count <= 0) {
|
2012-03-24 06:18:31 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2009-11-01 00:06:53 +00:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
float co[3];
|
2011-12-28 13:11:46 +00:00
|
|
|
zero_v3(co);
|
|
|
|
|
|
2020-10-05 18:50:38 +02:00
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
|
|
const float interp_weight = weights[i];
|
|
|
|
|
madd_v3_v3fl(co, in[i], interp_weight);
|
2009-11-01 00:06:53 +00:00
|
|
|
}
|
2012-08-24 17:01:35 +00:00
|
|
|
|
2019-08-17 00:54:22 +10:00
|
|
|
/* Delay writing to the destination in case dest is in sources. */
|
2012-08-24 17:01:35 +00:00
|
|
|
copy_v3_v3((float *)dest, co);
|
2009-11-01 00:06:53 +00:00
|
|
|
}
|
2008-07-08 02:22:37 +00:00
|
|
|
|
2022-03-25 12:49:01 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Callbacks for (#MVertSkin, #CD_MVERT_SKIN)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static void layerDefault_mvert_skin(void *data, const int count)
|
2012-05-22 15:18:43 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
MVertSkin *vs = static_cast<MVertSkin *>(data);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < count; i++) {
|
2012-05-22 15:18:43 +00:00
|
|
|
copy_v3_fl(vs[i].radius, 0.25f);
|
|
|
|
|
vs[i].flag = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-05-22 22:03:41 +00:00
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static void layerCopy_mvert_skin(const void *source, void *dest, const int count)
|
2018-12-12 15:06:39 +01:00
|
|
|
{
|
2018-12-13 12:30:38 +11:00
|
|
|
memcpy(dest, source, sizeof(MVertSkin) * count);
|
2018-12-12 15:06:39 +01:00
|
|
|
}
|
|
|
|
|
|
2015-02-23 13:51:55 +11:00
|
|
|
static void layerInterp_mvert_skin(const void **sources,
|
|
|
|
|
const float *weights,
|
2022-10-03 17:37:25 -05:00
|
|
|
const float * /*sub_weights*/,
|
2015-02-23 13:51:55 +11:00
|
|
|
int count,
|
|
|
|
|
void *dest)
|
2012-05-22 15:18:43 +00:00
|
|
|
{
|
2020-09-09 15:43:09 +02:00
|
|
|
float radius[3];
|
2012-05-22 15:18:43 +00:00
|
|
|
zero_v3(radius);
|
2020-09-09 15:43:09 +02:00
|
|
|
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
2020-10-05 18:50:38 +02:00
|
|
|
const float interp_weight = weights[i];
|
2021-12-25 14:28:22 -06:00
|
|
|
const MVertSkin *vs_src = static_cast<const MVertSkin *>(sources[i]);
|
2012-05-22 15:18:43 +00:00
|
|
|
|
2020-10-05 18:50:38 +02:00
|
|
|
madd_v3_v3fl(radius, vs_src->radius, interp_weight);
|
2012-05-22 15:18:43 +00:00
|
|
|
}
|
|
|
|
|
|
2019-08-17 00:54:22 +10:00
|
|
|
/* Delay writing to the destination in case dest is in sources. */
|
2021-12-25 14:28:22 -06:00
|
|
|
MVertSkin *vs_dst = static_cast<MVertSkin *>(dest);
|
2015-02-23 13:51:55 +11:00
|
|
|
copy_v3_v3(vs_dst->radius, radius);
|
|
|
|
|
vs_dst->flag &= ~MVERT_SKIN_ROOT;
|
2012-05-22 15:18:43 +00:00
|
|
|
}
|
|
|
|
|
|
2022-03-25 12:49:01 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Callbacks for (`short[4][3]`, #CD_TESSLOOPNORMAL)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2014-04-16 16:51:49 +02:00
|
|
|
static void layerSwap_flnor(void *data, const int *corner_indices)
|
|
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
short(*flnors)[4][3] = static_cast<short(*)[4][3]>(data);
|
2014-04-16 16:51:49 +02:00
|
|
|
short nors[4][3];
|
|
|
|
|
int i = 4;
|
|
|
|
|
|
|
|
|
|
while (i--) {
|
|
|
|
|
copy_v3_v3_short(nors[i], (*flnors)[corner_indices[i]]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memcpy(flnors, nors, sizeof(nors));
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-25 12:49:01 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Callbacks for (#MPropCol, #CD_PROP_COLOR)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2020-05-27 20:04:09 +02:00
|
|
|
static void layerCopyValue_propcol(const void *source,
|
|
|
|
|
void *dest,
|
|
|
|
|
const int mixmode,
|
|
|
|
|
const float mixfactor)
|
|
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
const MPropCol *m1 = static_cast<const MPropCol *>(source);
|
|
|
|
|
MPropCol *m2 = static_cast<MPropCol *>(dest);
|
2020-05-27 20:04:09 +02:00
|
|
|
float tmp_col[4];
|
|
|
|
|
|
|
|
|
|
if (ELEM(mixmode,
|
|
|
|
|
CDT_MIX_NOMIX,
|
|
|
|
|
CDT_MIX_REPLACE_ABOVE_THRESHOLD,
|
2024-01-02 18:12:54 +01:00
|
|
|
CDT_MIX_REPLACE_BELOW_THRESHOLD))
|
|
|
|
|
{
|
2020-05-27 20:04:09 +02:00
|
|
|
/* Modes that do a full copy or nothing. */
|
|
|
|
|
if (ELEM(mixmode, CDT_MIX_REPLACE_ABOVE_THRESHOLD, CDT_MIX_REPLACE_BELOW_THRESHOLD)) {
|
|
|
|
|
/* TODO: Check for a real valid way to get 'factor' value of our dest color? */
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
const float f = (m2->color[0] + m2->color[1] + m2->color[2]) / 3.0f;
|
2020-05-27 20:04:09 +02:00
|
|
|
if (mixmode == CDT_MIX_REPLACE_ABOVE_THRESHOLD && f < mixfactor) {
|
|
|
|
|
return; /* Do Nothing! */
|
|
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
if (mixmode == CDT_MIX_REPLACE_BELOW_THRESHOLD && f > mixfactor) {
|
2020-05-27 20:04:09 +02:00
|
|
|
return; /* Do Nothing! */
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-10-27 13:55:10 +01:00
|
|
|
copy_v4_v4(m2->color, m1->color);
|
2020-05-27 20:04:09 +02:00
|
|
|
}
|
|
|
|
|
else { /* Modes that support 'real' mix factor. */
|
|
|
|
|
if (mixmode == CDT_MIX_MIX) {
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
blend_color_mix_float(tmp_col, m2->color, m1->color);
|
2020-05-27 20:04:09 +02:00
|
|
|
}
|
|
|
|
|
else if (mixmode == CDT_MIX_ADD) {
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
blend_color_add_float(tmp_col, m2->color, m1->color);
|
2020-05-27 20:04:09 +02:00
|
|
|
}
|
|
|
|
|
else if (mixmode == CDT_MIX_SUB) {
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
blend_color_sub_float(tmp_col, m2->color, m1->color);
|
2020-05-27 20:04:09 +02:00
|
|
|
}
|
|
|
|
|
else if (mixmode == CDT_MIX_MUL) {
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
blend_color_mul_float(tmp_col, m2->color, m1->color);
|
2020-05-27 20:04:09 +02:00
|
|
|
}
|
|
|
|
|
else {
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
memcpy(tmp_col, m1->color, sizeof(tmp_col));
|
2020-05-27 20:04:09 +02:00
|
|
|
}
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
blend_color_interpolate_float(m2->color, m2->color, tmp_col, mixfactor);
|
2020-05-27 20:04:09 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool layerEqual_propcol(const void *data1, const void *data2)
|
|
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
const MPropCol *m1 = static_cast<const MPropCol *>(data1);
|
|
|
|
|
const MPropCol *m2 = static_cast<const MPropCol *>(data2);
|
2020-05-27 20:04:09 +02:00
|
|
|
float tot = 0;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 4; i++) {
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
float c = (m1->color[i] - m2->color[i]);
|
2020-05-27 20:04:09 +02:00
|
|
|
tot += c * c;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return tot < 0.001f;
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static void layerMultiply_propcol(void *data, const float fac)
|
2020-05-27 20:04:09 +02:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
MPropCol *m = static_cast<MPropCol *>(data);
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
mul_v4_fl(m->color, fac);
|
2020-05-27 20:04:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void layerAdd_propcol(void *data1, const void *data2)
|
|
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
MPropCol *m = static_cast<MPropCol *>(data1);
|
|
|
|
|
const MPropCol *m2 = static_cast<const MPropCol *>(data2);
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
add_v4_v4(m->color, m2->color);
|
2020-05-27 20:04:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void layerDoMinMax_propcol(const void *data, void *vmin, void *vmax)
|
|
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
const MPropCol *m = static_cast<const MPropCol *>(data);
|
|
|
|
|
MPropCol *min = static_cast<MPropCol *>(vmin);
|
|
|
|
|
MPropCol *max = static_cast<MPropCol *>(vmax);
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
minmax_v4v4_v4(min->color, max->color, m->color);
|
2020-05-27 20:04:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void layerInitMinMax_propcol(void *vmin, void *vmax)
|
|
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
MPropCol *min = static_cast<MPropCol *>(vmin);
|
|
|
|
|
MPropCol *max = static_cast<MPropCol *>(vmax);
|
2020-05-27 20:04:09 +02:00
|
|
|
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
copy_v4_fl(min->color, FLT_MAX);
|
|
|
|
|
copy_v4_fl(max->color, FLT_MIN);
|
2020-05-27 20:04:09 +02:00
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static void layerDefault_propcol(void *data, const int count)
|
2020-05-27 20:04:09 +02:00
|
|
|
{
|
|
|
|
|
/* Default to white, full alpha. */
|
2020-05-28 14:33:37 +10:00
|
|
|
MPropCol default_propcol = {{1.0f, 1.0f, 1.0f, 1.0f}};
|
2020-05-27 20:04:09 +02:00
|
|
|
MPropCol *pcol = (MPropCol *)data;
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < count; i++) {
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
copy_v4_v4(pcol[i].color, default_propcol.color);
|
2020-05-27 20:04:09 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-05 18:50:38 +02:00
|
|
|
static void layerInterp_propcol(const void **sources,
|
|
|
|
|
const float *weights,
|
2022-10-03 17:37:25 -05:00
|
|
|
const float * /*sub_weights*/,
|
2020-10-05 18:50:38 +02:00
|
|
|
int count,
|
|
|
|
|
void *dest)
|
2020-05-27 20:04:09 +02:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
MPropCol *mc = static_cast<MPropCol *>(dest);
|
2020-05-27 20:04:09 +02:00
|
|
|
float col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
2020-10-05 18:50:38 +02:00
|
|
|
const float interp_weight = weights[i];
|
2021-12-25 14:28:22 -06:00
|
|
|
const MPropCol *src = static_cast<const MPropCol *>(sources[i]);
|
2020-10-05 18:50:38 +02:00
|
|
|
madd_v4_v4fl(col, src->color, interp_weight);
|
2020-05-27 20:04:09 +02:00
|
|
|
}
|
Sculpt Vertex Colors: Initial implementation
Sculpt Vertex Colors is a painting system that runs inside sculpt mode, reusing all its tools and optimizations. This provides much better performance, easier to maintain code and more advanced features (new brush engine, filters, symmetry options, masks and face sets compatibility...). This is also the initial step for future features like vertex painting in Multires and brushes that can sculpt and paint at the same time.
This commit includes:
- SCULPT_UNDO_COLOR for undo support in sculpt mode
- SCULPT_UPDATE_COLOR and PBVH flags and rendering
- Sculpt Color API functions
- Sculpt capability for sculpt tools (only enabled in the Paint Brush for now)
- Rendering support in workbench (default to Sculpt Vertex Colors except in Vertex Paint)
- Conversion operator between MPropCol (Sculpt Vertex Colors) and MLoopCol (Vertex Paint)
- Remesher reprojection in the Voxel Remehser
- Paint Brush and Smear Brush with color smoothing in alt-smooth mode
- Parameters for the new brush engine (density, opacity, flow, wet paint mixing, tip scale) implemented in Sculpt Vertex Colors
- Color Filter
- Color picker (uses S shortcut, replaces smooth)
- Color selector in the top bar
Reviewed By: brecht
Maniphest Tasks: T72866
Differential Revision: https://developer.blender.org/D5975
2020-06-22 20:05:28 +02:00
|
|
|
copy_v4_v4(mc->color, col);
|
2020-05-27 20:04:09 +02:00
|
|
|
}
|
|
|
|
|
|
2022-03-25 12:49:01 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Callbacks for (#vec3f, #CD_PROP_FLOAT3)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2020-10-05 18:50:38 +02:00
|
|
|
static void layerInterp_propfloat3(const void **sources,
|
|
|
|
|
const float *weights,
|
2022-10-03 17:37:25 -05:00
|
|
|
const float * /*sub_weights*/,
|
2020-10-05 18:50:38 +02:00
|
|
|
int count,
|
|
|
|
|
void *dest)
|
2020-07-15 16:42:17 +02:00
|
|
|
{
|
|
|
|
|
vec3f result = {0.0f, 0.0f, 0.0f};
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
2020-10-05 18:50:38 +02:00
|
|
|
const float interp_weight = weights[i];
|
2021-12-25 14:28:22 -06:00
|
|
|
const vec3f *src = static_cast<const vec3f *>(sources[i]);
|
2020-10-05 18:50:38 +02:00
|
|
|
madd_v3_v3fl(&result.x, &src->x, interp_weight);
|
2020-07-15 16:42:17 +02:00
|
|
|
}
|
|
|
|
|
copy_v3_v3((float *)dest, &result.x);
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static void layerMultiply_propfloat3(void *data, const float fac)
|
2020-07-15 16:42:17 +02:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
vec3f *vec = static_cast<vec3f *>(data);
|
2020-07-15 16:42:17 +02:00
|
|
|
vec->x *= fac;
|
|
|
|
|
vec->y *= fac;
|
|
|
|
|
vec->z *= fac;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void layerAdd_propfloat3(void *data1, const void *data2)
|
|
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
vec3f *vec1 = static_cast<vec3f *>(data1);
|
|
|
|
|
const vec3f *vec2 = static_cast<const vec3f *>(data2);
|
2020-07-15 16:42:17 +02:00
|
|
|
vec1->x += vec2->x;
|
|
|
|
|
vec1->y += vec2->y;
|
|
|
|
|
vec1->z += vec2->z;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool layerValidate_propfloat3(void *data, const uint totitems, const bool do_fixes)
|
|
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
float *values = static_cast<float *>(data);
|
2020-07-15 16:42:17 +02:00
|
|
|
bool has_errors = false;
|
|
|
|
|
for (int i = 0; i < totitems * 3; i++) {
|
|
|
|
|
if (!isfinite(values[i])) {
|
|
|
|
|
if (do_fixes) {
|
|
|
|
|
values[i] = 0.0f;
|
|
|
|
|
}
|
|
|
|
|
has_errors = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return has_errors;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-25 12:49:01 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Callbacks for (#vec2f, #CD_PROP_FLOAT2)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2020-10-05 18:50:38 +02:00
|
|
|
static void layerInterp_propfloat2(const void **sources,
|
|
|
|
|
const float *weights,
|
2022-10-03 17:37:25 -05:00
|
|
|
const float * /*sub_weights*/,
|
2020-10-05 18:50:38 +02:00
|
|
|
int count,
|
|
|
|
|
void *dest)
|
2020-07-15 16:42:17 +02:00
|
|
|
{
|
2020-07-15 18:14:03 +02:00
|
|
|
vec2f result = {0.0f, 0.0f};
|
2020-07-15 16:42:17 +02:00
|
|
|
for (int i = 0; i < count; i++) {
|
2020-10-05 18:50:38 +02:00
|
|
|
const float interp_weight = weights[i];
|
2021-12-25 14:28:22 -06:00
|
|
|
const vec2f *src = static_cast<const vec2f *>(sources[i]);
|
2020-10-05 18:50:38 +02:00
|
|
|
madd_v2_v2fl(&result.x, &src->x, interp_weight);
|
2020-07-15 16:42:17 +02:00
|
|
|
}
|
|
|
|
|
copy_v2_v2((float *)dest, &result.x);
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static void layerMultiply_propfloat2(void *data, const float fac)
|
2020-07-15 16:42:17 +02:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
vec2f *vec = static_cast<vec2f *>(data);
|
2020-07-15 16:42:17 +02:00
|
|
|
vec->x *= fac;
|
|
|
|
|
vec->y *= fac;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void layerAdd_propfloat2(void *data1, const void *data2)
|
|
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
vec2f *vec1 = static_cast<vec2f *>(data1);
|
|
|
|
|
const vec2f *vec2 = static_cast<const vec2f *>(data2);
|
2020-07-15 16:42:17 +02:00
|
|
|
vec1->x += vec2->x;
|
|
|
|
|
vec1->y += vec2->y;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool layerValidate_propfloat2(void *data, const uint totitems, const bool do_fixes)
|
|
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
float *values = static_cast<float *>(data);
|
2020-07-15 16:42:17 +02:00
|
|
|
bool has_errors = false;
|
|
|
|
|
for (int i = 0; i < totitems * 2; i++) {
|
|
|
|
|
if (!isfinite(values[i])) {
|
|
|
|
|
if (do_fixes) {
|
|
|
|
|
values[i] = 0.0f;
|
|
|
|
|
}
|
|
|
|
|
has_errors = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return has_errors;
|
|
|
|
|
}
|
|
|
|
|
|
Mesh: Move UV layers to generic attributes
Currently the `MLoopUV` struct stores UV coordinates and flags related
to editing UV maps in the UV editor. This patch changes the coordinates
to use the generic 2D vector type, and moves the flags into three
separate boolean attributes. This follows the design in T95965, with
the ultimate intention of simplifying code and improving performance.
Importantly, the change allows exporters and renderers to use UVs
"touched" by geometry nodes, which only creates generic attributes.
It also allows geometry nodes to create "proper" UV maps from scratch,
though only with the Store Named Attribute node for now.
The new design considers any 2D vector attribute on the corner domain
to be a UV map. In the future, they might be distinguished from regular
2D vectors with attribute metadata, which may be helpful because they
are often interpolated differently.
Most of the code changes deal with passing around UV BMesh custom data
offsets and tracking the boolean "sublayers". The boolean layers are
use the following prefixes for attribute names: vert selection: `.vs.`,
edge selection: `.es.`, pinning: `.pn.`. Currently these are short to
avoid using up the maximum length of attribute names. To accommodate
for these 4 extra characters, the name length limit is enlarged to 68
bytes, while the maximum user settable name length is still 64 bytes.
Unfortunately Python/RNA API access to the UV flag data becomes slower.
Accessing the boolean layers directly is be better for performance in
general.
Like the other mesh SoA refactors, backward and forward compatibility
aren't affected, and won't be changed until 4.0. We pay for that by
making mesh reading and writing more expensive with conversions.
Resolves T85962
Differential Revision: https://developer.blender.org/D14365
2023-01-10 00:47:04 -05:00
|
|
|
static bool layerEqual_propfloat2(const void *data1, const void *data2)
|
|
|
|
|
{
|
|
|
|
|
const float2 &a = *static_cast<const float2 *>(data1);
|
|
|
|
|
const float2 &b = *static_cast<const float2 *>(data2);
|
|
|
|
|
return blender::math::distance_squared(a, b) < 0.00001f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void layerInitMinMax_propfloat2(void *vmin, void *vmax)
|
|
|
|
|
{
|
|
|
|
|
float2 &min = *static_cast<float2 *>(vmin);
|
|
|
|
|
float2 &max = *static_cast<float2 *>(vmax);
|
|
|
|
|
INIT_MINMAX2(min, max);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void layerDoMinMax_propfloat2(const void *data, void *vmin, void *vmax)
|
|
|
|
|
{
|
|
|
|
|
const float2 &value = *static_cast<const float2 *>(data);
|
|
|
|
|
float2 &a = *static_cast<float2 *>(vmin);
|
|
|
|
|
float2 &b = *static_cast<float2 *>(vmax);
|
|
|
|
|
blender::math::min_max(value, a, b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void layerCopyValue_propfloat2(const void *source,
|
|
|
|
|
void *dest,
|
|
|
|
|
const int mixmode,
|
|
|
|
|
const float mixfactor)
|
|
|
|
|
{
|
|
|
|
|
const float2 &a = *static_cast<const float2 *>(source);
|
|
|
|
|
float2 &b = *static_cast<float2 *>(dest);
|
|
|
|
|
|
|
|
|
|
/* We only support a limited subset of advanced mixing here-
|
|
|
|
|
* namely the mixfactor interpolation. */
|
|
|
|
|
if (mixmode == CDT_MIX_NOMIX) {
|
|
|
|
|
b = a;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
b = blender::math::interpolate(b, a, mixfactor);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-25 12:49:01 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Callbacks for (`bool`, #CD_PROP_BOOL)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
Attributes: Implement CustomData interpolation for boolean data type
This commit fixes an issue, where for instance, when merging vertices
with the "Merge by Distance" geometry node, the resulting vertices had
their boolean attributes set unpredictably.
Boolean attributes are implemented as custom data, and when welding
vertices, the custom data for the resulting vertices comes from
interpolating the custom data of the source vertices.
This commit implements the missing interpolation function for the
boolean custom data type. This interpolation function is implemented in
terms of the logical or operation, that is to say, if any of the source
vertices (with a weight greater than zero) have the boolean set, the
boolean will also be set on the resulting vertex.
This logic matches 95981c9876483256b28.
In geometry nodes, attribute interpolation generally does not use the
CustomData API for performance reasons, but other areas of Blender
still do.
Differential Revision: https://developer.blender.org/D14172
2022-03-08 15:51:53 -06:00
|
|
|
static void layerInterp_propbool(const void **sources,
|
|
|
|
|
const float *weights,
|
2022-10-03 17:37:25 -05:00
|
|
|
const float * /*sub_weights*/,
|
Attributes: Implement CustomData interpolation for boolean data type
This commit fixes an issue, where for instance, when merging vertices
with the "Merge by Distance" geometry node, the resulting vertices had
their boolean attributes set unpredictably.
Boolean attributes are implemented as custom data, and when welding
vertices, the custom data for the resulting vertices comes from
interpolating the custom data of the source vertices.
This commit implements the missing interpolation function for the
boolean custom data type. This interpolation function is implemented in
terms of the logical or operation, that is to say, if any of the source
vertices (with a weight greater than zero) have the boolean set, the
boolean will also be set on the resulting vertex.
This logic matches 95981c9876483256b28.
In geometry nodes, attribute interpolation generally does not use the
CustomData API for performance reasons, but other areas of Blender
still do.
Differential Revision: https://developer.blender.org/D14172
2022-03-08 15:51:53 -06:00
|
|
|
int count,
|
|
|
|
|
void *dest)
|
|
|
|
|
{
|
|
|
|
|
bool result = false;
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
|
|
const float interp_weight = weights[i];
|
|
|
|
|
const bool src = *(const bool *)sources[i];
|
|
|
|
|
result |= src && (interp_weight > 0.0f);
|
|
|
|
|
}
|
|
|
|
|
*(bool *)dest = result;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-12 11:36:49 -04:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Callbacks for (#math::Quaternion, #CD_PROP_QUATERNION)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
static void layerDefault_propquaternion(void *data, const int count)
|
|
|
|
|
{
|
|
|
|
|
using namespace blender;
|
|
|
|
|
MutableSpan(static_cast<math::Quaternion *>(data), count).fill(math::Quaternion::identity());
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-13 18:59:36 +01:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Callbacks for (#math::Quaternion, #CD_PROP_FLOAT4X4)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
static void layerDefault_propfloat4x4(void *data, const int count)
|
|
|
|
|
{
|
|
|
|
|
using namespace blender;
|
|
|
|
|
MutableSpan(static_cast<float4x4 *>(data), count).fill(float4x4::identity());
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-12 11:36:49 -04:00
|
|
|
/** \} */
|
|
|
|
|
|
2023-07-09 21:40:17 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Layer Type Information (#LAYERTYPEINFO)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2011-02-13 10:52:18 +00:00
|
|
|
static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
Mesh: Move positions to a generic attribute
**Changes**
As described in T93602, this patch removes all use of the `MVert`
struct, replacing it with a generic named attribute with the name
`"position"`, consistent with other geometry types.
Variable names have been changed from `verts` to `positions`, to align
with the attribute name and the more generic design (positions are not
vertices, they are just an attribute stored on the point domain).
This change is made possible by previous commits that moved all other
data out of `MVert` to runtime data or other generic attributes. What
remains is mostly a simple type change. Though, the type still shows up
859 times, so the patch is quite large.
One compromise is that now `CD_MASK_BAREMESH` now contains
`CD_PROP_FLOAT3`. With the general move towards generic attributes
over custom data types, we are removing use of these type masks anyway.
**Benefits**
The most obvious benefit is reduced memory usage and the benefits
that brings in memory-bound situations. `float3` is only 3 bytes, in
comparison to `MVert` which was 4. When there are millions of vertices
this starts to matter more.
The other benefits come from using a more generic type. Instead of
writing algorithms specifically for `MVert`, code can just use arrays
of vectors. This will allow eliminating many temporary arrays or
wrappers used to extract positions.
Many possible improvements aren't implemented in this patch, though
I did switch simplify or remove the process of creating temporary
position arrays in a few places.
The design clarity that "positions are just another attribute" brings
allows removing explicit copying of vertices in some procedural
operations-- they are just processed like most other attributes.
**Performance**
This touches so many areas that it's hard to benchmark exhaustively,
but I observed some areas as examples.
* The mesh line node with 4 million count was 1.5x (8ms to 12ms) faster.
* The Spring splash screen went from ~4.3 to ~4.5 fps.
* The subdivision surface modifier/node was slightly faster
RNA access through Python may be slightly slower, since now we need
a name lookup instead of just a custom data type lookup for each index.
**Future Improvements**
* Remove uses of "vert_coords" functions:
* `BKE_mesh_vert_coords_alloc`
* `BKE_mesh_vert_coords_get`
* `BKE_mesh_vert_coords_apply{_with_mat4}`
* Remove more hidden copying of positions
* General simplification now possible in many areas
* Convert more code to C++ to use `float3` instead of `float[3]`
* Currently `reinterpret_cast` is used for those C-API functions
Differential Revision: https://developer.blender.org/D15982
2023-01-10 00:10:43 -05:00
|
|
|
/* 0: CD_MVERT */ /* DEPRECATED */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(MVert),
|
|
|
|
|
alignof(MVert),
|
|
|
|
|
"MVert",
|
|
|
|
|
1,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr},
|
2012-09-21 11:37:51 +00:00
|
|
|
/* 1: CD_MSTICKY */ /* DEPRECATED */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(float[2]),
|
|
|
|
|
alignof(float2),
|
|
|
|
|
"",
|
|
|
|
|
1,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr},
|
2011-09-03 08:18:43 +00:00
|
|
|
/* 2: CD_MDEFORMVERT */
|
2006-12-21 13:47:27 +00:00
|
|
|
{sizeof(MDeformVert),
|
2024-02-13 18:59:36 +01:00
|
|
|
alignof(MDeformVert),
|
2006-12-21 13:47:27 +00:00
|
|
|
"MDeformVert",
|
|
|
|
|
1,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
2006-12-21 13:47:27 +00:00
|
|
|
layerCopy_mdeformvert,
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
layerFree_mdeformvert,
|
|
|
|
|
layerInterp_mdeformvert,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
2022-09-01 08:23:57 -05:00
|
|
|
nullptr,
|
|
|
|
|
layerConstruct_mdeformvert},
|
Mesh: Move edges to a generic attribute
Implements #95966, as the final step of #95965.
This commit changes the storage of mesh edge vertex indices from the
`MEdge` type to the generic `int2` attribute type. This follows the
general design for geometry and the attribute system, where the data
storage type and the usage semantics are separated.
The main benefit of the change is reduced memory usage-- the
requirements of storing mesh edges is reduced by 1/3. For example,
this saves 8MB on a 1 million vertex grid. This also gives performance
benefits to any memory-bound mesh processing algorithm that uses edges.
Another benefit is that all of the edge's vertex indices are
contiguous. In a few cases, it's helpful to process all of them as
`Span<int>` rather than `Span<int2>`. Similarly, the type is more
likely to match a generic format used by a library, or code that
shouldn't know about specific Blender `Mesh` types.
Various Notes:
- The `.edge_verts` name is used to reflect a mapping between domains,
similar to `.corner_verts`, etc. The period means that it the data
shouldn't change arbitrarily by the user or procedural operations.
- `edge[0]` is now used instead of `edge.v1`
- Signed integers are used instead of unsigned to reduce the mixing
of signed-ness, which can be error prone.
- All of the previously used core mesh data types (`MVert`, `MEdge`,
`MLoop`, `MPoly` are now deprecated. Only generic types are used).
- The `vec2i` DNA type is used in the few C files where necessary.
Pull Request: https://projects.blender.org/blender/blender/pulls/106638
2023-04-17 13:47:41 +02:00
|
|
|
/* 3: CD_MEDGE */ /* DEPRECATED */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(MEdge),
|
|
|
|
|
alignof(MEdge),
|
|
|
|
|
"MEdge",
|
|
|
|
|
1,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr},
|
2011-09-03 08:18:43 +00:00
|
|
|
/* 4: CD_MFACE */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(MFace),
|
|
|
|
|
alignof(MFace),
|
|
|
|
|
"MFace",
|
|
|
|
|
1,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr},
|
2011-09-03 08:18:43 +00:00
|
|
|
/* 5: CD_MTFACE */
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
{sizeof(MTFace),
|
2024-02-13 18:59:36 +01:00
|
|
|
alignof(MTFace),
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
"MTFace",
|
|
|
|
|
1,
|
|
|
|
|
N_("UVMap"),
|
|
|
|
|
layerCopy_tface,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
layerInterp_tface,
|
|
|
|
|
layerSwap_tface,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
layerDefault_tface,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
layerMaxNum_tface},
|
|
|
|
|
/* 6: CD_MCOL */
|
|
|
|
|
/* 4 MCol structs per face */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(MCol[4]),
|
|
|
|
|
alignof(MCol[4]),
|
|
|
|
|
"MCol",
|
|
|
|
|
4,
|
|
|
|
|
N_("Col"),
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
layerInterp_mcol,
|
|
|
|
|
layerSwap_mcol,
|
|
|
|
|
layerDefault_mcol},
|
2011-09-03 08:18:43 +00:00
|
|
|
/* 7: CD_ORIGINDEX */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(int),
|
|
|
|
|
alignof(int),
|
|
|
|
|
"",
|
|
|
|
|
0,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
layerDefault_origindex},
|
2011-09-03 08:18:43 +00:00
|
|
|
/* 8: CD_NORMAL */
|
2006-11-11 16:38:37 +00:00
|
|
|
/* 3 floats per normal vector */
|
2020-08-08 13:29:21 +10:00
|
|
|
{sizeof(float[3]),
|
2024-02-13 18:59:36 +01:00
|
|
|
alignof(blender::float3),
|
2015-02-05 14:38:59 +01:00
|
|
|
"vec3f",
|
|
|
|
|
1,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
2015-02-05 14:38:59 +01:00
|
|
|
layerInterp_normal,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
Refactor: Move normals out of MVert, lazy calculation
As described in T91186, this commit moves mesh vertex normals into a
contiguous array of float vectors in a custom data layer, how face
normals are currently stored.
The main interface is documented in `BKE_mesh.h`. Vertex and face
normals are now calculated on-demand and cached, retrieved with an
"ensure" function. Since the logical state of a mesh is now "has
normals when necessary", they can be retrieved from a `const` mesh.
The goal is to use on-demand calculation for all derived data, but
leave room for eager calculation for performance purposes (modifier
evaluation is threaded, but viewport data generation is not).
**Benefits**
This moves us closer to a SoA approach rather than the current AoS
paradigm. Accessing a contiguous `float3` is much more efficient than
retrieving data from a larger struct. The memory requirements for
accessing only normals or vertex locations are smaller, and at the
cost of more memory usage for just normals, they now don't have to
be converted between float and short, which also simplifies code
In the future, the remaining items can be removed from `MVert`,
leaving only `float3`, which has similar benefits (see T93602).
Removing the combination of derived and original data makes it
conceptually simpler to only calculate normals when necessary.
This is especially important now that we have more opportunities
for temporary meshes in geometry nodes.
**Performance**
In addition to the theoretical future performance improvements by
making `MVert == float3`, I've done some basic performance testing
on this patch directly. The data is fairly rough, but it gives an idea
about where things stand generally.
- Mesh line primitive 4m Verts: 1.16x faster (36 -> 31 ms),
showing that accessing just `MVert` is now more efficient.
- Spring Splash Screen: 1.03-1.06 -> 1.06-1.11 FPS, a very slight
change that at least shows there is no regression.
- Sprite Fright Snail Smoosh: 3.30-3.40 -> 3.42-3.50 FPS, a small
but observable speedup.
- Set Position Node with Scaled Normal: 1.36x faster (53 -> 39 ms),
shows that using normals in geometry nodes is faster.
- Normal Calculation 1.6m Vert Cube: 1.19x faster (25 -> 21 ms),
shows that calculating normals is slightly faster now.
- File Size of 1.6m Vert Cube: 1.03x smaller (214.7 -> 208.4 MB),
Normals are not saved in files, which can help with large meshes.
As for memory usage, it may be slightly more in some cases, but
I didn't observe any difference in the production files I tested.
**Tests**
Some modifiers and cycles test results need to be updated with this
commit, for two reasons:
- The subdivision surface modifier is not responsible for calculating
normals anymore. In master, the modifier creates different normals
than the result of the `Mesh` normal calculation, so this is a bug
fix.
- There are small differences in the results of some modifiers that
use normals because they are not converted to and from `short`
anymore.
**Future improvements**
- Remove `ModifierTypeInfo::dependsOnNormals`. Code in each modifier
already retrieves normals if they are needed anyway.
- Copy normals as part of a better CoW system for attributes.
- Make more areas use lazy instead of eager normal calculation.
- Remove `BKE_mesh_normals_tag_dirty` in more places since that is
now the default state of a new mesh.
- Possibly apply a similar change to derived face corner normals.
Differential Revision: https://developer.blender.org/D12770
2022-01-13 14:37:58 -06:00
|
|
|
nullptr,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
nullptr,
|
2018-12-03 16:19:08 +01:00
|
|
|
layerCopyValue_normal},
|
2023-06-09 13:54:52 +02:00
|
|
|
/* 9: CD_FACEMAP */ /* DEPRECATED */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(int), alignof(int), ""},
|
2020-06-10 15:47:31 +02:00
|
|
|
/* 10: CD_PROP_FLOAT */
|
2018-12-03 16:19:08 +01:00
|
|
|
{sizeof(MFloatProperty),
|
2024-02-13 18:59:36 +01:00
|
|
|
alignof(float),
|
2018-12-03 16:19:08 +01:00
|
|
|
"MFloatProperty",
|
|
|
|
|
1,
|
|
|
|
|
N_("Float"),
|
|
|
|
|
layerCopy_propFloat,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
2021-02-16 14:25:35 +01:00
|
|
|
layerInterp_propFloat,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
nullptr,
|
2018-12-03 16:19:08 +01:00
|
|
|
layerValidate_propFloat},
|
2020-06-10 15:47:31 +02:00
|
|
|
/* 11: CD_PROP_INT32 */
|
2021-12-25 14:28:22 -06:00
|
|
|
{sizeof(MIntProperty),
|
2024-02-13 18:59:36 +01:00
|
|
|
alignof(int),
|
2021-12-25 14:28:22 -06:00
|
|
|
"MIntProperty",
|
|
|
|
|
1,
|
|
|
|
|
N_("Int"),
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
nullptr,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
2022-05-31 19:23:52 +02:00
|
|
|
layerInterp_propInt,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr},
|
2020-06-10 15:47:31 +02:00
|
|
|
/* 12: CD_PROP_STRING */
|
2013-03-25 08:29:06 +00:00
|
|
|
{sizeof(MStringProperty),
|
2024-02-13 18:59:36 +01:00
|
|
|
alignof(MStringProperty),
|
2013-03-25 08:29:06 +00:00
|
|
|
"MStringProperty",
|
|
|
|
|
1,
|
|
|
|
|
N_("String"),
|
|
|
|
|
layerCopy_propString,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr},
|
2011-09-03 08:18:43 +00:00
|
|
|
/* 13: CD_ORIGSPACE */
|
2013-03-25 08:29:06 +00:00
|
|
|
{sizeof(OrigSpaceFace),
|
2024-02-13 18:59:36 +01:00
|
|
|
alignof(OrigSpaceFace),
|
2013-03-25 08:29:06 +00:00
|
|
|
"OrigSpaceFace",
|
|
|
|
|
1,
|
|
|
|
|
N_("UVMap"),
|
|
|
|
|
layerCopy_origspace_face,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
layerInterp_origspace_face,
|
|
|
|
|
layerSwap_origspace_face,
|
|
|
|
|
layerDefault_origspace_face},
|
2011-09-03 08:18:43 +00:00
|
|
|
/* 14: CD_ORCO */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(float[3]),
|
|
|
|
|
alignof(blender::float3),
|
|
|
|
|
"",
|
|
|
|
|
0,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr},
|
2017-05-25 15:11:00 +10:00
|
|
|
/* 15: CD_MTEXPOLY */ /* DEPRECATED */
|
2021-07-03 23:08:40 +10:00
|
|
|
/* NOTE: when we expose the UV Map / TexFace split to the user,
|
2019-04-27 12:07:07 +10:00
|
|
|
* change this back to face Texture. */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(int), alignof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
Mesh: Move UV layers to generic attributes
Currently the `MLoopUV` struct stores UV coordinates and flags related
to editing UV maps in the UV editor. This patch changes the coordinates
to use the generic 2D vector type, and moves the flags into three
separate boolean attributes. This follows the design in T95965, with
the ultimate intention of simplifying code and improving performance.
Importantly, the change allows exporters and renderers to use UVs
"touched" by geometry nodes, which only creates generic attributes.
It also allows geometry nodes to create "proper" UV maps from scratch,
though only with the Store Named Attribute node for now.
The new design considers any 2D vector attribute on the corner domain
to be a UV map. In the future, they might be distinguished from regular
2D vectors with attribute metadata, which may be helpful because they
are often interpolated differently.
Most of the code changes deal with passing around UV BMesh custom data
offsets and tracking the boolean "sublayers". The boolean layers are
use the following prefixes for attribute names: vert selection: `.vs.`,
edge selection: `.es.`, pinning: `.pn.`. Currently these are short to
avoid using up the maximum length of attribute names. To accommodate
for these 4 extra characters, the name length limit is enlarged to 68
bytes, while the maximum user settable name length is still 64 bytes.
Unfortunately Python/RNA API access to the UV flag data becomes slower.
Accessing the boolean layers directly is be better for performance in
general.
Like the other mesh SoA refactors, backward and forward compatibility
aren't affected, and won't be changed until 4.0. We pay for that by
making mesh reading and writing more expensive with conversions.
Resolves T85962
Differential Revision: https://developer.blender.org/D14365
2023-01-10 00:47:04 -05:00
|
|
|
/* 16: CD_MLOOPUV */ /* DEPRECATED */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(MLoopUV), alignof(MLoopUV), "MLoopUV", 1, N_("UVMap")},
|
2022-04-20 09:10:10 -05:00
|
|
|
/* 17: CD_PROP_BYTE_COLOR */
|
2013-03-25 08:29:06 +00:00
|
|
|
{sizeof(MLoopCol),
|
2024-02-13 18:59:36 +01:00
|
|
|
alignof(MLoopCol),
|
2013-03-25 08:29:06 +00:00
|
|
|
"MLoopCol",
|
|
|
|
|
1,
|
|
|
|
|
N_("Col"),
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
2013-03-25 08:29:06 +00:00
|
|
|
layerInterp_mloopcol,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
2018-12-03 16:19:08 +01:00
|
|
|
layerDefault_mloopcol,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
nullptr,
|
2018-12-03 16:19:08 +01:00
|
|
|
layerEqual_mloopcol,
|
|
|
|
|
layerMultiply_mloopcol,
|
2014-10-21 17:01:56 +02:00
|
|
|
layerInitMinMax_mloopcol,
|
|
|
|
|
layerAdd_mloopcol,
|
|
|
|
|
layerDoMinMax_mloopcol,
|
2009-01-06 18:59:03 +00:00
|
|
|
layerCopyValue_mloopcol,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
2022-08-31 08:26:57 -07:00
|
|
|
nullptr},
|
2015-07-10 16:47:39 +10:00
|
|
|
/* 18: CD_TANGENT */
|
2024-04-01 13:38:01 -04:00
|
|
|
{sizeof(float[4]),
|
|
|
|
|
alignof(float[4]),
|
2024-02-13 18:59:36 +01:00
|
|
|
"",
|
|
|
|
|
0,
|
|
|
|
|
N_("Tangent"),
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr},
|
2011-09-03 08:18:43 +00:00
|
|
|
/* 19: CD_MDISPS */
|
2015-07-10 16:47:39 +10:00
|
|
|
{sizeof(MDisps),
|
2024-02-13 18:59:36 +01:00
|
|
|
alignof(MDisps),
|
2009-01-06 18:59:03 +00:00
|
|
|
"MDisps",
|
2019-04-17 06:17:24 +02:00
|
|
|
1,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
2015-07-10 16:47:39 +10:00
|
|
|
layerCopy_mdisps,
|
2012-02-21 17:24:21 +00:00
|
|
|
layerFree_mdisps,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
2012-02-21 17:24:21 +00:00
|
|
|
layerSwap_mdisps,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
layerConstruct_mdisps,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
2012-02-21 17:24:21 +00:00
|
|
|
layerRead_mdisps,
|
2011-12-28 13:11:46 +00:00
|
|
|
layerWrite_mdisps,
|
2012-02-21 17:24:21 +00:00
|
|
|
layerFilesize_mdisps},
|
2011-12-28 13:11:46 +00:00
|
|
|
/* 20: CD_PREVIEW_MCOL */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(blender::float4x4),
|
|
|
|
|
alignof(blender::float4x4),
|
|
|
|
|
"mat4x4f",
|
|
|
|
|
1,
|
|
|
|
|
N_("4 by 4 Float Matrix"),
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
layerDefault_propfloat4x4},
|
2011-12-28 13:11:46 +00:00
|
|
|
/* 21: CD_ID_MCOL */ /* DEPRECATED */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(MCol[4]),
|
|
|
|
|
alignof(MCol[4]),
|
|
|
|
|
"",
|
|
|
|
|
0,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr},
|
2011-12-28 13:11:46 +00:00
|
|
|
/* 22: CD_TEXTURE_MCOL */
|
2020-08-08 13:29:21 +10:00
|
|
|
{sizeof(MCol[4]),
|
2024-02-13 18:59:36 +01:00
|
|
|
alignof(MCol[4]),
|
2013-03-25 08:29:06 +00:00
|
|
|
"MCol",
|
|
|
|
|
4,
|
|
|
|
|
N_("TexturedCol"),
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
2013-03-25 08:29:06 +00:00
|
|
|
layerInterp_mcol,
|
2010-04-10 22:12:10 +00:00
|
|
|
layerSwap_mcol,
|
2013-03-25 08:29:06 +00:00
|
|
|
layerDefault_mcol},
|
2012-05-12 16:11:34 +00:00
|
|
|
/* 23: CD_CLOTH_ORCO */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(float[3]),
|
|
|
|
|
alignof(float[3]),
|
|
|
|
|
"",
|
|
|
|
|
0,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr},
|
2012-05-12 16:11:34 +00:00
|
|
|
/* 24: CD_RECAST */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(MRecast),
|
|
|
|
|
alignof(MRecast),
|
|
|
|
|
"MRecast",
|
|
|
|
|
1,
|
|
|
|
|
N_("Recast"),
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr},
|
Mesh: Replace MPoly struct with offset indices
Implements #95967.
Currently the `MPoly` struct is 12 bytes, and stores the index of a
face's first corner and the number of corners/verts/edges. Polygons
and corners are always created in order by Blender, meaning each
face's corners will be after the previous face's corners. We can take
advantage of this fact and eliminate the redundancy in mesh face
storage by only storing a single integer corner offset for each face.
The size of the face is then encoded by the offset of the next face.
The size of a single integer is 4 bytes, so this reduces memory
usage by 3 times.
The same method is used for `CurvesGeometry`, so Blender already has
an abstraction to simplify using these offsets called `OffsetIndices`.
This class is used to easily retrieve a range of corner indices for
each face. This also gives the opportunity for sharing some logic with
curves.
Another benefit of the change is that the offsets and sizes stored in
`MPoly` can no longer disagree with each other. Storing faces in the
order of their corners can simplify some code too.
Face/polygon variables now use the `IndexRange` type, which comes with
quite a few utilities that can simplify code.
Some:
- The offset integer array has to be one longer than the face count to
avoid a branch for every face, which means the data is no longer part
of the mesh's `CustomData`.
- We lose the ability to "reference" an original mesh's offset array
until more reusable CoW from #104478 is committed. That will be added
in a separate commit.
- Since they aren't part of `CustomData`, poly offsets often have to be
copied manually.
- To simplify using `OffsetIndices` in many places, some functions and
structs in headers were moved to only compile in C++.
- All meshes created by Blender use the same order for faces and face
corners, but just in case, meshes with mismatched order are fixed by
versioning code.
- `MeshPolygon.totloop` is no longer editable in RNA. This API break is
necessary here unfortunately. It should be worth it in 3.6, since
that's the best way to allow loading meshes from 4.0, which is
important for an LTS version.
Pull Request: https://projects.blender.org/blender/blender/pulls/105938
2023-04-04 20:39:28 +02:00
|
|
|
/* 25: CD_MPOLY */ /* DEPRECATED */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(MPoly),
|
|
|
|
|
alignof(MPoly),
|
|
|
|
|
"MPoly",
|
|
|
|
|
1,
|
|
|
|
|
N_("NGon Face"),
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr},
|
2023-09-14 13:25:24 +10:00
|
|
|
/* 26: CD_MLOOP */ /* DEPRECATED */
|
2021-12-25 14:28:22 -06:00
|
|
|
{sizeof(MLoop),
|
2024-02-13 18:59:36 +01:00
|
|
|
alignof(MLoop),
|
2021-12-25 14:28:22 -06:00
|
|
|
"MLoop",
|
|
|
|
|
1,
|
|
|
|
|
N_("NGon Face-Vertex"),
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr},
|
2011-12-28 13:11:46 +00:00
|
|
|
/* 27: CD_SHAPE_KEYINDEX */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(int), alignof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
2011-12-28 13:11:46 +00:00
|
|
|
/* 28: CD_SHAPEKEY */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(float[3]),
|
|
|
|
|
alignof(float[3]),
|
|
|
|
|
"",
|
|
|
|
|
0,
|
|
|
|
|
N_("ShapeKey"),
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
layerInterp_shapekey},
|
2023-06-13 20:23:39 +02:00
|
|
|
/* 29: CD_BWEIGHT */ /* DEPRECATED */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(MFloatProperty), alignof(MFloatProperty), "MFloatProperty", 1},
|
2023-06-13 20:23:39 +02:00
|
|
|
/* 30: CD_CREASE */ /* DEPRECATED */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(float), alignof(float), ""},
|
2012-05-01 17:51:03 +00:00
|
|
|
/* 31: CD_ORIGSPACE_MLOOP */
|
2018-12-03 16:19:08 +01:00
|
|
|
{sizeof(OrigSpaceLoop),
|
2024-02-13 18:59:36 +01:00
|
|
|
alignof(OrigSpaceLoop),
|
2018-12-03 16:19:08 +01:00
|
|
|
"OrigSpaceLoop",
|
|
|
|
|
1,
|
|
|
|
|
N_("OS Loop"),
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
2018-12-03 16:19:08 +01:00
|
|
|
layerInterp_mloop_origspace,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
nullptr,
|
2012-02-05 11:30:26 +00:00
|
|
|
layerEqual_mloop_origspace,
|
|
|
|
|
layerMultiply_mloop_origspace,
|
|
|
|
|
layerInitMinMax_mloop_origspace,
|
|
|
|
|
layerAdd_mloop_origspace,
|
|
|
|
|
layerDoMinMax_mloop_origspace,
|
|
|
|
|
layerCopyValue_mloop_origspace},
|
2023-12-05 09:30:13 -05:00
|
|
|
/* 32: CD_PREVIEW_MLOOPCOL */ /* DEPRECATED */ /* UNUSED */
|
|
|
|
|
{},
|
2012-02-22 16:08:30 +00:00
|
|
|
/* 33: CD_BM_ELEM_PYPTR */
|
|
|
|
|
{sizeof(void *),
|
2024-02-13 18:59:36 +01:00
|
|
|
alignof(void *),
|
2012-02-22 16:08:30 +00:00
|
|
|
"",
|
|
|
|
|
1,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
2012-02-22 16:08:30 +00:00
|
|
|
layerCopy_bmesh_elem_py_ptr,
|
|
|
|
|
layerFree_bmesh_elem_py_ptr,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr},
|
2023-11-20 17:42:01 +01:00
|
|
|
/* 34: CD_PAINT_MASK */ /* DEPRECATED */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(float), alignof(float), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
2012-05-10 20:33:24 +00:00
|
|
|
/* 35: CD_GRID_PAINT_MASK */
|
|
|
|
|
{sizeof(GridPaintMask),
|
2024-02-13 18:59:36 +01:00
|
|
|
alignof(GridPaintMask),
|
2012-05-10 20:33:24 +00:00
|
|
|
"GridPaintMask",
|
|
|
|
|
1,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
2012-05-10 20:33:24 +00:00
|
|
|
layerCopy_grid_paint_mask,
|
2012-05-22 15:18:43 +00:00
|
|
|
layerFree_grid_paint_mask,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
nullptr,
|
|
|
|
|
layerConstruct_grid_paint_mask},
|
2015-11-03 14:50:27 +01:00
|
|
|
/* 36: CD_MVERT_SKIN */
|
2018-12-12 15:06:39 +01:00
|
|
|
{sizeof(MVertSkin),
|
2024-02-13 18:59:36 +01:00
|
|
|
alignof(MVertSkin),
|
2018-12-12 15:06:39 +01:00
|
|
|
"MVertSkin",
|
|
|
|
|
1,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
2018-12-12 15:06:39 +01:00
|
|
|
layerCopy_mvert_skin,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
2013-03-13 06:44:43 +00:00
|
|
|
layerInterp_mvert_skin,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
2013-03-13 06:44:43 +00:00
|
|
|
layerDefault_mvert_skin},
|
|
|
|
|
/* 37: CD_FREESTYLE_EDGE */
|
2021-12-25 14:28:22 -06:00
|
|
|
{sizeof(FreestyleEdge),
|
2024-02-13 18:59:36 +01:00
|
|
|
alignof(FreestyleEdge),
|
2021-12-25 14:28:22 -06:00
|
|
|
"FreestyleEdge",
|
|
|
|
|
1,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr},
|
2013-03-13 06:44:43 +00:00
|
|
|
/* 38: CD_FREESTYLE_FACE */
|
2021-12-25 14:28:22 -06:00
|
|
|
{sizeof(FreestyleFace),
|
2024-02-13 18:59:36 +01:00
|
|
|
alignof(FreestyleFace),
|
2021-12-25 14:28:22 -06:00
|
|
|
"FreestyleFace",
|
|
|
|
|
1,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr},
|
2014-01-11 11:31:44 +01:00
|
|
|
/* 39: CD_MLOOPTANGENT */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(float[4]),
|
|
|
|
|
alignof(float[4]),
|
|
|
|
|
"",
|
|
|
|
|
0,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr},
|
2014-04-13 12:18:51 +02:00
|
|
|
/* 40: CD_TESSLOOPNORMAL */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(short[4][3]),
|
|
|
|
|
alignof(short[4][3]),
|
|
|
|
|
"",
|
|
|
|
|
0,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
layerSwap_flnor,
|
|
|
|
|
nullptr},
|
Add Custom Loop Normals.
This is the core code for it, tools (datatransfer and modifier) will come in next commits).
RNA api is already there, though.
See the code for details, but basically, we define, for each 'smooth fan'
(which is a set of adjacent loops around a same vertex that are smooth, i.e. have a single same normal),
a 'loop normal space' (or lnor space), using auto-computed normal and relevant edges, and store
custom normal as two angular factors inside that space. This allows to have custom normals
'following' deformations of the geometry, and to only save two shorts per loop in new clnor CDLayer.
Normal manipulation (editing, mixing, interpolating, etc.) shall always happen with plain 3D vectors normals,
and be converted back into storage format at the end.
Clnor computation has also been threaded (at least for Mesh case, not for BMesh), since the process can
be rather heavy with high poly meshes.
Also, bumping subversion, and fix mess in 2.70 versioning code.
2015-02-05 14:24:48 +01:00
|
|
|
/* 41: CD_CUSTOMLOOPNORMAL */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(short[2]),
|
|
|
|
|
alignof(short[2]),
|
|
|
|
|
"vec2s",
|
|
|
|
|
1,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr},
|
2022-09-23 08:19:40 -05:00
|
|
|
/* 42: CD_SCULPT_FACE_SETS */ /* DEPRECATED */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(int), alignof(int), ""},
|
2020-03-17 14:41:48 +01:00
|
|
|
/* 43: CD_LOCATION */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(float[3]),
|
|
|
|
|
alignof(float[3]),
|
|
|
|
|
"vec3f",
|
|
|
|
|
1,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr},
|
2020-03-17 14:41:48 +01:00
|
|
|
/* 44: CD_RADIUS */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(float),
|
|
|
|
|
alignof(float),
|
|
|
|
|
"MFloatProperty",
|
|
|
|
|
1,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr},
|
2022-02-04 10:29:11 -06:00
|
|
|
/* 45: CD_PROP_INT8 */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(int8_t),
|
|
|
|
|
alignof(int8_t),
|
|
|
|
|
"MInt8Property",
|
|
|
|
|
1,
|
|
|
|
|
N_("Int8"),
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr},
|
2023-04-14 16:08:05 +02:00
|
|
|
/* 46: CD_PROP_INT32_2D */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(blender::int2),
|
|
|
|
|
alignof(blender::int2),
|
|
|
|
|
"vec2i",
|
|
|
|
|
1,
|
|
|
|
|
N_("Int 2D"),
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr},
|
2020-06-09 16:23:15 +02:00
|
|
|
/* 47: CD_PROP_COLOR */
|
2020-05-27 20:04:09 +02:00
|
|
|
{sizeof(MPropCol),
|
2024-02-13 18:59:36 +01:00
|
|
|
alignof(MPropCol),
|
2020-05-29 17:57:58 +02:00
|
|
|
"MPropCol",
|
2020-05-27 20:04:09 +02:00
|
|
|
1,
|
2020-06-24 14:17:44 +02:00
|
|
|
N_("Color"),
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
2020-05-27 20:04:09 +02:00
|
|
|
layerInterp_propcol,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
2020-05-27 20:04:09 +02:00
|
|
|
layerDefault_propcol,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
nullptr,
|
2020-05-27 20:04:09 +02:00
|
|
|
layerEqual_propcol,
|
|
|
|
|
layerMultiply_propcol,
|
|
|
|
|
layerInitMinMax_propcol,
|
|
|
|
|
layerAdd_propcol,
|
|
|
|
|
layerDoMinMax_propcol,
|
|
|
|
|
layerCopyValue_propcol,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
2022-08-31 08:26:57 -07:00
|
|
|
nullptr},
|
2020-07-15 16:42:17 +02:00
|
|
|
/* 48: CD_PROP_FLOAT3 */
|
|
|
|
|
{sizeof(float[3]),
|
2024-02-13 18:59:36 +01:00
|
|
|
alignof(blender::float3),
|
2020-07-15 16:42:17 +02:00
|
|
|
"vec3f",
|
|
|
|
|
1,
|
|
|
|
|
N_("Float3"),
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
2020-07-15 16:42:17 +02:00
|
|
|
layerInterp_propfloat3,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
nullptr,
|
2020-07-15 16:42:17 +02:00
|
|
|
layerValidate_propfloat3,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
2020-07-15 16:42:17 +02:00
|
|
|
layerMultiply_propfloat3,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
2020-07-15 16:42:17 +02:00
|
|
|
layerAdd_propfloat3},
|
|
|
|
|
/* 49: CD_PROP_FLOAT2 */
|
|
|
|
|
{sizeof(float[2]),
|
2024-02-13 18:59:36 +01:00
|
|
|
alignof(float2),
|
2020-07-15 16:42:17 +02:00
|
|
|
"vec2f",
|
|
|
|
|
1,
|
|
|
|
|
N_("Float2"),
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
2020-07-15 16:42:17 +02:00
|
|
|
layerInterp_propfloat2,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
nullptr,
|
2020-07-15 16:42:17 +02:00
|
|
|
layerValidate_propfloat2,
|
Mesh: Move UV layers to generic attributes
Currently the `MLoopUV` struct stores UV coordinates and flags related
to editing UV maps in the UV editor. This patch changes the coordinates
to use the generic 2D vector type, and moves the flags into three
separate boolean attributes. This follows the design in T95965, with
the ultimate intention of simplifying code and improving performance.
Importantly, the change allows exporters and renderers to use UVs
"touched" by geometry nodes, which only creates generic attributes.
It also allows geometry nodes to create "proper" UV maps from scratch,
though only with the Store Named Attribute node for now.
The new design considers any 2D vector attribute on the corner domain
to be a UV map. In the future, they might be distinguished from regular
2D vectors with attribute metadata, which may be helpful because they
are often interpolated differently.
Most of the code changes deal with passing around UV BMesh custom data
offsets and tracking the boolean "sublayers". The boolean layers are
use the following prefixes for attribute names: vert selection: `.vs.`,
edge selection: `.es.`, pinning: `.pn.`. Currently these are short to
avoid using up the maximum length of attribute names. To accommodate
for these 4 extra characters, the name length limit is enlarged to 68
bytes, while the maximum user settable name length is still 64 bytes.
Unfortunately Python/RNA API access to the UV flag data becomes slower.
Accessing the boolean layers directly is be better for performance in
general.
Like the other mesh SoA refactors, backward and forward compatibility
aren't affected, and won't be changed until 4.0. We pay for that by
making mesh reading and writing more expensive with conversions.
Resolves T85962
Differential Revision: https://developer.blender.org/D14365
2023-01-10 00:47:04 -05:00
|
|
|
layerEqual_propfloat2,
|
2020-07-15 16:42:17 +02:00
|
|
|
layerMultiply_propfloat2,
|
Mesh: Move UV layers to generic attributes
Currently the `MLoopUV` struct stores UV coordinates and flags related
to editing UV maps in the UV editor. This patch changes the coordinates
to use the generic 2D vector type, and moves the flags into three
separate boolean attributes. This follows the design in T95965, with
the ultimate intention of simplifying code and improving performance.
Importantly, the change allows exporters and renderers to use UVs
"touched" by geometry nodes, which only creates generic attributes.
It also allows geometry nodes to create "proper" UV maps from scratch,
though only with the Store Named Attribute node for now.
The new design considers any 2D vector attribute on the corner domain
to be a UV map. In the future, they might be distinguished from regular
2D vectors with attribute metadata, which may be helpful because they
are often interpolated differently.
Most of the code changes deal with passing around UV BMesh custom data
offsets and tracking the boolean "sublayers". The boolean layers are
use the following prefixes for attribute names: vert selection: `.vs.`,
edge selection: `.es.`, pinning: `.pn.`. Currently these are short to
avoid using up the maximum length of attribute names. To accommodate
for these 4 extra characters, the name length limit is enlarged to 68
bytes, while the maximum user settable name length is still 64 bytes.
Unfortunately Python/RNA API access to the UV flag data becomes slower.
Accessing the boolean layers directly is be better for performance in
general.
Like the other mesh SoA refactors, backward and forward compatibility
aren't affected, and won't be changed until 4.0. We pay for that by
making mesh reading and writing more expensive with conversions.
Resolves T85962
Differential Revision: https://developer.blender.org/D14365
2023-01-10 00:47:04 -05:00
|
|
|
layerInitMinMax_propfloat2,
|
|
|
|
|
layerAdd_propfloat2,
|
|
|
|
|
layerDoMinMax_propfloat2,
|
|
|
|
|
layerCopyValue_propfloat2},
|
2021-01-04 15:52:11 +11:00
|
|
|
/* 50: CD_PROP_BOOL */
|
2020-12-16 12:33:13 -06:00
|
|
|
{sizeof(bool),
|
2024-02-13 18:59:36 +01:00
|
|
|
alignof(bool),
|
2020-12-16 12:33:13 -06:00
|
|
|
"bool",
|
|
|
|
|
1,
|
|
|
|
|
N_("Boolean"),
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
Attributes: Implement CustomData interpolation for boolean data type
This commit fixes an issue, where for instance, when merging vertices
with the "Merge by Distance" geometry node, the resulting vertices had
their boolean attributes set unpredictably.
Boolean attributes are implemented as custom data, and when welding
vertices, the custom data for the resulting vertices comes from
interpolating the custom data of the source vertices.
This commit implements the missing interpolation function for the
boolean custom data type. This interpolation function is implemented in
terms of the logical or operation, that is to say, if any of the source
vertices (with a weight greater than zero) have the boolean set, the
boolean will also be set on the resulting vertex.
This logic matches 95981c9876483256b28.
In geometry nodes, attribute interpolation generally does not use the
CustomData API for performance reasons, but other areas of Blender
still do.
Differential Revision: https://developer.blender.org/D14172
2022-03-08 15:51:53 -06:00
|
|
|
layerInterp_propbool,
|
2021-12-25 14:28:22 -06:00
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr},
|
2023-06-28 17:17:31 +02:00
|
|
|
/* 51: CD_HAIRLENGTH */ /* DEPRECATED */ /* UNUSED */
|
2024-02-13 18:59:36 +01:00
|
|
|
{sizeof(float),
|
|
|
|
|
alignof(float),
|
|
|
|
|
"float",
|
|
|
|
|
1,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr},
|
2023-06-12 15:49:50 +02:00
|
|
|
/* 52: CD_PROP_QUATERNION */
|
2023-06-12 11:36:49 -04:00
|
|
|
{sizeof(float[4]),
|
2024-02-13 18:59:36 +01:00
|
|
|
alignof(blender::float4),
|
2023-06-12 11:36:49 -04:00
|
|
|
"vec4f",
|
|
|
|
|
1,
|
|
|
|
|
N_("Quaternion"),
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
layerDefault_propquaternion},
|
2020-07-15 16:42:17 +02:00
|
|
|
};
|
2006-11-11 16:38:37 +00:00
|
|
|
|
2011-02-13 10:52:18 +00:00
|
|
|
static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
|
2011-12-28 13:11:46 +00:00
|
|
|
/* 0-4 */ "CDMVert",
|
|
|
|
|
"CDMSticky",
|
|
|
|
|
"CDMDeformVert",
|
|
|
|
|
"CDMEdge",
|
|
|
|
|
"CDMFace",
|
2017-05-31 00:18:20 +10:00
|
|
|
/* 5-9 */ "CDMTFace",
|
|
|
|
|
"CDMCol",
|
|
|
|
|
"CDOrigIndex",
|
|
|
|
|
"CDNormal",
|
|
|
|
|
"CDFaceMap",
|
2012-04-29 15:47:02 +00:00
|
|
|
/* 10-14 */ "CDMFloatProperty",
|
|
|
|
|
"CDMIntProperty",
|
|
|
|
|
"CDMStringProperty",
|
|
|
|
|
"CDOrigSpace",
|
|
|
|
|
"CDOrco",
|
2011-12-28 13:11:46 +00:00
|
|
|
/* 15-19 */ "CDMTexPoly",
|
|
|
|
|
"CDMLoopUV",
|
|
|
|
|
"CDMloopCol",
|
|
|
|
|
"CDTangent",
|
|
|
|
|
"CDMDisps",
|
2012-05-12 16:11:34 +00:00
|
|
|
/* 20-24 */ "CDPreviewMCol",
|
|
|
|
|
"CDIDMCol",
|
|
|
|
|
"CDTextureMCol",
|
|
|
|
|
"CDClothOrco",
|
|
|
|
|
"CDMRecast",
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-12-28 13:11:46 +00:00
|
|
|
/* BMESH ONLY */
|
|
|
|
|
/* 25-29 */ "CDMPoly",
|
|
|
|
|
"CDMLoop",
|
|
|
|
|
"CDShapeKeyIndex",
|
|
|
|
|
"CDShapeKey",
|
|
|
|
|
"CDBevelWeight",
|
2012-05-10 20:33:24 +00:00
|
|
|
/* 30-34 */ "CDSubSurfCrease",
|
|
|
|
|
"CDOrigSpaceLoop",
|
|
|
|
|
"CDPreviewLoopCol",
|
|
|
|
|
"CDBMElemPyPtr",
|
|
|
|
|
"CDPaintMask",
|
2013-03-13 06:44:43 +00:00
|
|
|
/* 35-36 */ "CDGridPaintMask",
|
|
|
|
|
"CDMVertSkin",
|
Add Custom Loop Normals.
This is the core code for it, tools (datatransfer and modifier) will come in next commits).
RNA api is already there, though.
See the code for details, but basically, we define, for each 'smooth fan'
(which is a set of adjacent loops around a same vertex that are smooth, i.e. have a single same normal),
a 'loop normal space' (or lnor space), using auto-computed normal and relevant edges, and store
custom normal as two angular factors inside that space. This allows to have custom normals
'following' deformations of the geometry, and to only save two shorts per loop in new clnor CDLayer.
Normal manipulation (editing, mixing, interpolating, etc.) shall always happen with plain 3D vectors normals,
and be converted back into storage format at the end.
Clnor computation has also been threaded (at least for Mesh case, not for BMesh), since the process can
be rather heavy with high poly meshes.
Also, bumping subversion, and fix mess in 2.70 versioning code.
2015-02-05 14:24:48 +01:00
|
|
|
/* 37-38 */ "CDFreestyleEdge",
|
|
|
|
|
"CDFreestyleFace",
|
2020-03-17 14:41:48 +01:00
|
|
|
/* 39-42 */ "CDMLoopTangent",
|
Add Custom Loop Normals.
This is the core code for it, tools (datatransfer and modifier) will come in next commits).
RNA api is already there, though.
See the code for details, but basically, we define, for each 'smooth fan'
(which is a set of adjacent loops around a same vertex that are smooth, i.e. have a single same normal),
a 'loop normal space' (or lnor space), using auto-computed normal and relevant edges, and store
custom normal as two angular factors inside that space. This allows to have custom normals
'following' deformations of the geometry, and to only save two shorts per loop in new clnor CDLayer.
Normal manipulation (editing, mixing, interpolating, etc.) shall always happen with plain 3D vectors normals,
and be converted back into storage format at the end.
Clnor computation has also been threaded (at least for Mesh case, not for BMesh), since the process can
be rather heavy with high poly meshes.
Also, bumping subversion, and fix mess in 2.70 versioning code.
2015-02-05 14:24:48 +01:00
|
|
|
"CDTessLoopNormal",
|
|
|
|
|
"CDCustomLoopNormal",
|
2020-03-05 14:53:23 +01:00
|
|
|
"CDSculptFaceGroups",
|
2020-03-17 14:41:48 +01:00
|
|
|
/* 43-46 */ "CDHairPoint",
|
2022-02-04 10:29:11 -06:00
|
|
|
"CDPropInt8",
|
2020-03-17 14:41:48 +01:00
|
|
|
"CDHairMapping",
|
|
|
|
|
"CDPoint",
|
2020-05-27 20:04:09 +02:00
|
|
|
"CDPropCol",
|
2020-07-15 18:14:03 +02:00
|
|
|
"CDPropFloat3",
|
|
|
|
|
"CDPropFloat2",
|
2020-12-16 12:33:13 -06:00
|
|
|
"CDPropBoolean",
|
2021-09-24 07:42:36 +02:00
|
|
|
"CDHairLength",
|
2023-06-12 11:36:49 -04:00
|
|
|
"CDPropQuaternion",
|
2010-05-27 08:42:59 +00:00
|
|
|
};
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
const CustomData_MeshMasks CD_MASK_BAREMESH = {
|
2023-01-16 12:41:11 +11:00
|
|
|
/*vmask*/ CD_MASK_PROP_FLOAT3,
|
Mesh: Move edges to a generic attribute
Implements #95966, as the final step of #95965.
This commit changes the storage of mesh edge vertex indices from the
`MEdge` type to the generic `int2` attribute type. This follows the
general design for geometry and the attribute system, where the data
storage type and the usage semantics are separated.
The main benefit of the change is reduced memory usage-- the
requirements of storing mesh edges is reduced by 1/3. For example,
this saves 8MB on a 1 million vertex grid. This also gives performance
benefits to any memory-bound mesh processing algorithm that uses edges.
Another benefit is that all of the edge's vertex indices are
contiguous. In a few cases, it's helpful to process all of them as
`Span<int>` rather than `Span<int2>`. Similarly, the type is more
likely to match a generic format used by a library, or code that
shouldn't know about specific Blender `Mesh` types.
Various Notes:
- The `.edge_verts` name is used to reflect a mapping between domains,
similar to `.corner_verts`, etc. The period means that it the data
shouldn't change arbitrarily by the user or procedural operations.
- `edge[0]` is now used instead of `edge.v1`
- Signed integers are used instead of unsigned to reduce the mixing
of signed-ness, which can be error prone.
- All of the previously used core mesh data types (`MVert`, `MEdge`,
`MLoop`, `MPoly` are now deprecated. Only generic types are used).
- The `vec2i` DNA type is used in the few C files where necessary.
Pull Request: https://projects.blender.org/blender/blender/pulls/106638
2023-04-17 13:47:41 +02:00
|
|
|
/*emask*/ CD_MASK_PROP_INT32_2D,
|
2023-01-16 12:41:11 +11:00
|
|
|
/*fmask*/ 0,
|
2023-06-09 13:54:52 +02:00
|
|
|
/*pmask*/ 0,
|
Mesh: Replace MLoop struct with generic attributes
Implements #102359.
Split the `MLoop` struct into two separate integer arrays called
`corner_verts` and `corner_edges`, referring to the vertex each corner
is attached to and the next edge around the face at each corner. These
arrays can be sliced to give access to the edges or vertices in a face.
Then they are often referred to as "poly_verts" or "poly_edges".
The main benefits are halving the necessary memory bandwidth when only
one array is used and simplifications from using regular integer indices
instead of a special-purpose struct.
The commit also starts a renaming from "loop" to "corner" in mesh code.
Like the other mesh struct of array refactors, forward compatibility is
kept by writing files with the older format. This will be done until 4.0
to ease the transition process.
Looking at a small portion of the patch should give a good impression
for the rest of the changes. I tried to make the changes as small as
possible so it's easy to tell the correctness from the diff. Though I
found Blender developers have been very inventive over the last decade
when finding different ways to loop over the corners in a face.
For performance, nearly every piece of code that deals with `Mesh` is
slightly impacted. Any algorithm that is memory bottle-necked should
see an improvement. For example, here is a comparison of interpolating
a vertex float attribute to face corners (Ryzen 3700x):
**Before** (Average: 3.7 ms, Min: 3.4 ms)
```
threading::parallel_for(loops.index_range(), 4096, [&](IndexRange range) {
for (const int64_t i : range) {
dst[i] = src[loops[i].v];
}
});
```
**After** (Average: 2.9 ms, Min: 2.6 ms)
```
array_utils::gather(src, corner_verts, dst);
```
That's an improvement of 28% to the average timings, and it's also a
simplification, since an index-based routine can be used instead.
For more examples using the new arrays, see the design task.
Pull Request: https://projects.blender.org/blender/blender/pulls/104424
2023-03-20 15:55:13 +01:00
|
|
|
/*lmask*/ CD_MASK_PROP_INT32,
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
};
|
|
|
|
|
const CustomData_MeshMasks CD_MASK_BAREMESH_ORIGINDEX = {
|
2023-01-16 12:41:11 +11:00
|
|
|
/*vmask*/ CD_MASK_PROP_FLOAT3 | CD_MASK_ORIGINDEX,
|
Mesh: Move edges to a generic attribute
Implements #95966, as the final step of #95965.
This commit changes the storage of mesh edge vertex indices from the
`MEdge` type to the generic `int2` attribute type. This follows the
general design for geometry and the attribute system, where the data
storage type and the usage semantics are separated.
The main benefit of the change is reduced memory usage-- the
requirements of storing mesh edges is reduced by 1/3. For example,
this saves 8MB on a 1 million vertex grid. This also gives performance
benefits to any memory-bound mesh processing algorithm that uses edges.
Another benefit is that all of the edge's vertex indices are
contiguous. In a few cases, it's helpful to process all of them as
`Span<int>` rather than `Span<int2>`. Similarly, the type is more
likely to match a generic format used by a library, or code that
shouldn't know about specific Blender `Mesh` types.
Various Notes:
- The `.edge_verts` name is used to reflect a mapping between domains,
similar to `.corner_verts`, etc. The period means that it the data
shouldn't change arbitrarily by the user or procedural operations.
- `edge[0]` is now used instead of `edge.v1`
- Signed integers are used instead of unsigned to reduce the mixing
of signed-ness, which can be error prone.
- All of the previously used core mesh data types (`MVert`, `MEdge`,
`MLoop`, `MPoly` are now deprecated. Only generic types are used).
- The `vec2i` DNA type is used in the few C files where necessary.
Pull Request: https://projects.blender.org/blender/blender/pulls/106638
2023-04-17 13:47:41 +02:00
|
|
|
/*emask*/ CD_MASK_PROP_INT32_2D | CD_MASK_ORIGINDEX,
|
2023-01-16 12:41:11 +11:00
|
|
|
/*fmask*/ 0,
|
2023-06-09 13:54:52 +02:00
|
|
|
/*pmask*/ CD_MASK_ORIGINDEX,
|
Mesh: Replace MLoop struct with generic attributes
Implements #102359.
Split the `MLoop` struct into two separate integer arrays called
`corner_verts` and `corner_edges`, referring to the vertex each corner
is attached to and the next edge around the face at each corner. These
arrays can be sliced to give access to the edges or vertices in a face.
Then they are often referred to as "poly_verts" or "poly_edges".
The main benefits are halving the necessary memory bandwidth when only
one array is used and simplifications from using regular integer indices
instead of a special-purpose struct.
The commit also starts a renaming from "loop" to "corner" in mesh code.
Like the other mesh struct of array refactors, forward compatibility is
kept by writing files with the older format. This will be done until 4.0
to ease the transition process.
Looking at a small portion of the patch should give a good impression
for the rest of the changes. I tried to make the changes as small as
possible so it's easy to tell the correctness from the diff. Though I
found Blender developers have been very inventive over the last decade
when finding different ways to loop over the corners in a face.
For performance, nearly every piece of code that deals with `Mesh` is
slightly impacted. Any algorithm that is memory bottle-necked should
see an improvement. For example, here is a comparison of interpolating
a vertex float attribute to face corners (Ryzen 3700x):
**Before** (Average: 3.7 ms, Min: 3.4 ms)
```
threading::parallel_for(loops.index_range(), 4096, [&](IndexRange range) {
for (const int64_t i : range) {
dst[i] = src[loops[i].v];
}
});
```
**After** (Average: 2.9 ms, Min: 2.6 ms)
```
array_utils::gather(src, corner_verts, dst);
```
That's an improvement of 28% to the average timings, and it's also a
simplification, since an index-based routine can be used instead.
For more examples using the new arrays, see the design task.
Pull Request: https://projects.blender.org/blender/blender/pulls/104424
2023-03-20 15:55:13 +01:00
|
|
|
/*lmask*/ CD_MASK_PROP_INT32,
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
};
|
|
|
|
|
const CustomData_MeshMasks CD_MASK_MESH = {
|
2023-11-20 17:42:01 +01:00
|
|
|
/*vmask*/ (CD_MASK_PROP_FLOAT3 | CD_MASK_MDEFORMVERT | CD_MASK_MVERT_SKIN | CD_MASK_PROP_ALL),
|
2023-01-16 12:41:11 +11:00
|
|
|
/*emask*/
|
2023-06-13 20:23:39 +02:00
|
|
|
(CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL),
|
2023-01-16 12:41:11 +11:00
|
|
|
/*fmask*/ 0,
|
|
|
|
|
/*pmask*/
|
2023-06-09 13:54:52 +02:00
|
|
|
(CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
|
2023-01-16 12:41:11 +11:00
|
|
|
/*lmask*/
|
Mesh: Replace MLoop struct with generic attributes
Implements #102359.
Split the `MLoop` struct into two separate integer arrays called
`corner_verts` and `corner_edges`, referring to the vertex each corner
is attached to and the next edge around the face at each corner. These
arrays can be sliced to give access to the edges or vertices in a face.
Then they are often referred to as "poly_verts" or "poly_edges".
The main benefits are halving the necessary memory bandwidth when only
one array is used and simplifications from using regular integer indices
instead of a special-purpose struct.
The commit also starts a renaming from "loop" to "corner" in mesh code.
Like the other mesh struct of array refactors, forward compatibility is
kept by writing files with the older format. This will be done until 4.0
to ease the transition process.
Looking at a small portion of the patch should give a good impression
for the rest of the changes. I tried to make the changes as small as
possible so it's easy to tell the correctness from the diff. Though I
found Blender developers have been very inventive over the last decade
when finding different ways to loop over the corners in a face.
For performance, nearly every piece of code that deals with `Mesh` is
slightly impacted. Any algorithm that is memory bottle-necked should
see an improvement. For example, here is a comparison of interpolating
a vertex float attribute to face corners (Ryzen 3700x):
**Before** (Average: 3.7 ms, Min: 3.4 ms)
```
threading::parallel_for(loops.index_range(), 4096, [&](IndexRange range) {
for (const int64_t i : range) {
dst[i] = src[loops[i].v];
}
});
```
**After** (Average: 2.9 ms, Min: 2.6 ms)
```
array_utils::gather(src, corner_verts, dst);
```
That's an improvement of 28% to the average timings, and it's also a
simplification, since an index-based routine can be used instead.
For more examples using the new arrays, see the design task.
Pull Request: https://projects.blender.org/blender/blender/pulls/104424
2023-03-20 15:55:13 +01:00
|
|
|
(CD_MASK_MDISPS | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
};
|
|
|
|
|
const CustomData_MeshMasks CD_MASK_DERIVEDMESH = {
|
2023-01-16 12:41:11 +11:00
|
|
|
/*vmask*/ (CD_MASK_ORIGINDEX | CD_MASK_MDEFORMVERT | CD_MASK_SHAPEKEY | CD_MASK_MVERT_SKIN |
|
2023-11-20 17:42:01 +01:00
|
|
|
CD_MASK_ORCO | CD_MASK_CLOTH_ORCO | CD_MASK_PROP_ALL),
|
2023-01-16 12:41:11 +11:00
|
|
|
/*emask*/
|
2023-06-13 20:23:39 +02:00
|
|
|
(CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL),
|
2023-12-05 09:30:13 -05:00
|
|
|
/*fmask*/ (CD_MASK_ORIGINDEX | CD_MASK_ORIGSPACE | CD_MASK_TANGENT),
|
2023-01-16 12:41:11 +11:00
|
|
|
/*pmask*/
|
2023-06-09 13:54:52 +02:00
|
|
|
(CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
|
2023-01-16 12:41:11 +11:00
|
|
|
/*lmask*/
|
2023-12-05 09:30:13 -05:00
|
|
|
(CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_ORIGSPACE_MLOOP |
|
2023-01-16 12:41:11 +11:00
|
|
|
CD_MASK_PROP_ALL), /* XXX: MISSING #CD_MASK_MLOOPTANGENT ? */
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
};
|
|
|
|
|
const CustomData_MeshMasks CD_MASK_BMESH = {
|
2023-05-19 14:31:31 +02:00
|
|
|
/*vmask*/ (CD_MASK_MDEFORMVERT | CD_MASK_MVERT_SKIN | CD_MASK_SHAPEKEY |
|
2023-11-20 17:42:01 +01:00
|
|
|
CD_MASK_SHAPE_KEYINDEX | CD_MASK_PROP_ALL),
|
2023-06-13 20:23:39 +02:00
|
|
|
/*emask*/ (CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL),
|
2023-01-16 12:41:11 +11:00
|
|
|
/*fmask*/ 0,
|
|
|
|
|
/*pmask*/
|
2023-06-09 13:54:52 +02:00
|
|
|
(CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
|
2023-01-16 12:41:11 +11:00
|
|
|
/*lmask*/
|
Mesh: Move UV layers to generic attributes
Currently the `MLoopUV` struct stores UV coordinates and flags related
to editing UV maps in the UV editor. This patch changes the coordinates
to use the generic 2D vector type, and moves the flags into three
separate boolean attributes. This follows the design in T95965, with
the ultimate intention of simplifying code and improving performance.
Importantly, the change allows exporters and renderers to use UVs
"touched" by geometry nodes, which only creates generic attributes.
It also allows geometry nodes to create "proper" UV maps from scratch,
though only with the Store Named Attribute node for now.
The new design considers any 2D vector attribute on the corner domain
to be a UV map. In the future, they might be distinguished from regular
2D vectors with attribute metadata, which may be helpful because they
are often interpolated differently.
Most of the code changes deal with passing around UV BMesh custom data
offsets and tracking the boolean "sublayers". The boolean layers are
use the following prefixes for attribute names: vert selection: `.vs.`,
edge selection: `.es.`, pinning: `.pn.`. Currently these are short to
avoid using up the maximum length of attribute names. To accommodate
for these 4 extra characters, the name length limit is enlarged to 68
bytes, while the maximum user settable name length is still 64 bytes.
Unfortunately Python/RNA API access to the UV flag data becomes slower.
Accessing the boolean layers directly is be better for performance in
general.
Like the other mesh SoA refactors, backward and forward compatibility
aren't affected, and won't be changed until 4.0. We pay for that by
making mesh reading and writing more expensive with conversions.
Resolves T85962
Differential Revision: https://developer.blender.org/D14365
2023-01-10 00:47:04 -05:00
|
|
|
(CD_MASK_MDISPS | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
};
|
|
|
|
|
const CustomData_MeshMasks CD_MASK_EVERYTHING = {
|
2023-05-19 14:31:31 +02:00
|
|
|
/*vmask*/ (CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_MDEFORMVERT |
|
2023-01-16 12:41:11 +11:00
|
|
|
CD_MASK_MVERT_SKIN | CD_MASK_ORCO | CD_MASK_CLOTH_ORCO | CD_MASK_SHAPEKEY |
|
2023-11-20 17:42:01 +01:00
|
|
|
CD_MASK_SHAPE_KEYINDEX | CD_MASK_PROP_ALL),
|
2023-01-16 12:41:11 +11:00
|
|
|
/*emask*/
|
2023-06-13 20:23:39 +02:00
|
|
|
(CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL),
|
2023-01-16 12:41:11 +11:00
|
|
|
/*fmask*/
|
2021-12-25 14:28:22 -06:00
|
|
|
(CD_MASK_MFACE | CD_MASK_ORIGINDEX | CD_MASK_NORMAL | CD_MASK_MTFACE | CD_MASK_MCOL |
|
2023-12-05 09:30:13 -05:00
|
|
|
CD_MASK_ORIGSPACE | CD_MASK_TANGENT | CD_MASK_TESSLOOPNORMAL | CD_MASK_PROP_ALL),
|
2023-01-16 12:41:11 +11:00
|
|
|
/*pmask*/
|
2023-06-09 13:54:52 +02:00
|
|
|
(CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
|
2023-01-16 12:41:11 +11:00
|
|
|
/*lmask*/
|
Mesh: Replace MLoop struct with generic attributes
Implements #102359.
Split the `MLoop` struct into two separate integer arrays called
`corner_verts` and `corner_edges`, referring to the vertex each corner
is attached to and the next edge around the face at each corner. These
arrays can be sliced to give access to the edges or vertices in a face.
Then they are often referred to as "poly_verts" or "poly_edges".
The main benefits are halving the necessary memory bandwidth when only
one array is used and simplifications from using regular integer indices
instead of a special-purpose struct.
The commit also starts a renaming from "loop" to "corner" in mesh code.
Like the other mesh struct of array refactors, forward compatibility is
kept by writing files with the older format. This will be done until 4.0
to ease the transition process.
Looking at a small portion of the patch should give a good impression
for the rest of the changes. I tried to make the changes as small as
possible so it's easy to tell the correctness from the diff. Though I
found Blender developers have been very inventive over the last decade
when finding different ways to loop over the corners in a face.
For performance, nearly every piece of code that deals with `Mesh` is
slightly impacted. Any algorithm that is memory bottle-necked should
see an improvement. For example, here is a comparison of interpolating
a vertex float attribute to face corners (Ryzen 3700x):
**Before** (Average: 3.7 ms, Min: 3.4 ms)
```
threading::parallel_for(loops.index_range(), 4096, [&](IndexRange range) {
for (const int64_t i : range) {
dst[i] = src[loops[i].v];
}
});
```
**After** (Average: 2.9 ms, Min: 2.6 ms)
```
array_utils::gather(src, corner_verts, dst);
```
That's an improvement of 28% to the average timings, and it's also a
simplification, since an index-based routine can be used instead.
For more examples using the new arrays, see the design task.
Pull Request: https://projects.blender.org/blender/blender/pulls/104424
2023-03-20 15:55:13 +01:00
|
|
|
(CD_MASK_BM_ELEM_PYPTR | CD_MASK_MDISPS | CD_MASK_NORMAL | CD_MASK_CUSTOMLOOPNORMAL |
|
2023-12-05 09:30:13 -05:00
|
|
|
CD_MASK_MLOOPTANGENT | CD_MASK_ORIGSPACE_MLOOP | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
};
|
2008-07-08 02:22:37 +00:00
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
static const LayerTypeInfo *layerType_getInfo(const eCustomDataType type)
|
2006-11-11 16:38:37 +00:00
|
|
|
{
|
2019-04-22 09:39:35 +10:00
|
|
|
if (type < 0 || type >= CD_NUMTYPES) {
|
2021-12-25 14:28:22 -06:00
|
|
|
return nullptr;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2006-11-11 16:38:37 +00:00
|
|
|
|
|
|
|
|
return &LAYERTYPEINFO[type];
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
static const char *layerType_getName(const eCustomDataType type)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2019-04-22 09:39:35 +10:00
|
|
|
if (type < 0 || type >= CD_NUMTYPES) {
|
2021-12-25 14:28:22 -06:00
|
|
|
return nullptr;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
|
|
|
|
|
return LAYERTYPENAMES[type];
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
void customData_mask_layers__print(const CustomData_MeshMasks *mask)
|
2012-05-28 21:02:44 +00:00
|
|
|
{
|
2021-06-18 14:27:39 +10:00
|
|
|
printf("verts mask=0x%" PRIx64 ":\n", mask->vmask);
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < CD_NUMTYPES; i++) {
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
if (mask->vmask & CD_TYPE_AS_MASK(i)) {
|
2023-03-29 17:10:49 +02:00
|
|
|
printf(" %s\n", layerType_getName(eCustomDataType(i)));
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-06-18 14:27:39 +10:00
|
|
|
printf("edges mask=0x%" PRIx64 ":\n", mask->emask);
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < CD_NUMTYPES; i++) {
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
if (mask->emask & CD_TYPE_AS_MASK(i)) {
|
2023-03-29 17:10:49 +02:00
|
|
|
printf(" %s\n", layerType_getName(eCustomDataType(i)));
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-06-18 14:27:39 +10:00
|
|
|
printf("faces mask=0x%" PRIx64 ":\n", mask->fmask);
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < CD_NUMTYPES; i++) {
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
if (mask->fmask & CD_TYPE_AS_MASK(i)) {
|
2023-03-29 17:10:49 +02:00
|
|
|
printf(" %s\n", layerType_getName(eCustomDataType(i)));
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-06-18 14:27:39 +10:00
|
|
|
printf("loops mask=0x%" PRIx64 ":\n", mask->lmask);
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < CD_NUMTYPES; i++) {
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
if (mask->lmask & CD_TYPE_AS_MASK(i)) {
|
2023-03-29 17:10:49 +02:00
|
|
|
printf(" %s\n", layerType_getName(eCustomDataType(i)));
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-06-18 14:27:39 +10:00
|
|
|
printf("polys mask=0x%" PRIx64 ":\n", mask->pmask);
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < CD_NUMTYPES; i++) {
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
if (mask->pmask & CD_TYPE_AS_MASK(i)) {
|
2023-03-29 17:10:49 +02:00
|
|
|
printf(" %s\n", layerType_getName(eCustomDataType(i)));
|
2012-05-28 21:25:17 +00:00
|
|
|
}
|
2012-05-28 21:02:44 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-25 12:49:01 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name CustomData Functions
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2006-12-12 21:29:09 +00:00
|
|
|
static void customData_update_offsets(CustomData *data);
|
2006-11-11 16:38:37 +00:00
|
|
|
|
2023-04-13 14:57:57 +02:00
|
|
|
static CustomDataLayer *customData_add_layer__internal(
|
|
|
|
|
CustomData *data,
|
|
|
|
|
eCustomDataType type,
|
|
|
|
|
std::optional<eCDAllocType> alloctype,
|
|
|
|
|
void *layer_data_to_assign,
|
|
|
|
|
const ImplicitSharingInfo *sharing_info_to_assign,
|
|
|
|
|
int totelem,
|
2024-02-08 16:56:42 +01:00
|
|
|
const StringRef name);
|
2006-11-11 16:38:37 +00:00
|
|
|
|
2011-05-11 02:14:43 +00:00
|
|
|
void CustomData_update_typemap(CustomData *data)
|
2009-09-15 15:32:09 +00:00
|
|
|
{
|
2021-01-26 09:21:42 -06:00
|
|
|
int lasttype = -1;
|
2009-09-15 15:32:09 +00:00
|
|
|
|
2021-01-26 09:21:42 -06:00
|
|
|
for (int i = 0; i < CD_NUMTYPES; i++) {
|
2009-09-15 15:32:09 +00:00
|
|
|
data->typemap[i] = -1;
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-26 09:21:42 -06:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2023-03-29 17:10:49 +02:00
|
|
|
const eCustomDataType type = eCustomDataType(data->layers[i].type);
|
2015-07-20 17:28:29 +02:00
|
|
|
if (type != lasttype) {
|
|
|
|
|
data->typemap[type] = i;
|
|
|
|
|
lasttype = type;
|
2009-09-15 15:32:09 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-04 16:20:39 +00:00
|
|
|
/* currently only used in BLI_assert */
|
|
|
|
|
#ifndef NDEBUG
|
2014-02-05 22:36:15 +11:00
|
|
|
static bool customdata_typemap_is_valid(const CustomData *data)
|
2012-10-31 09:50:24 +00:00
|
|
|
{
|
|
|
|
|
CustomData data_copy = *data;
|
|
|
|
|
CustomData_update_typemap(&data_copy);
|
|
|
|
|
return (memcmp(data->typemap, data_copy.typemap, sizeof(data->typemap)) == 0);
|
|
|
|
|
}
|
2013-02-04 16:20:39 +00:00
|
|
|
#endif
|
2012-10-31 09:50:24 +00:00
|
|
|
|
2023-04-13 14:57:57 +02:00
|
|
|
static void *copy_layer_data(const eCustomDataType type, const void *data, const int totelem)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2023-04-13 14:57:57 +02:00
|
|
|
const LayerTypeInfo &type_info = *layerType_getInfo(type);
|
2024-02-13 18:59:36 +01:00
|
|
|
const int64_t size_in_bytes = int64_t(totelem) * type_info.size;
|
|
|
|
|
void *new_data = MEM_mallocN_aligned(size_in_bytes, type_info.alignment, __func__);
|
2023-04-13 14:57:57 +02:00
|
|
|
if (type_info.copy) {
|
|
|
|
|
type_info.copy(data, new_data, totelem);
|
|
|
|
|
}
|
2024-02-13 18:59:36 +01:00
|
|
|
else {
|
|
|
|
|
memcpy(new_data, data, size_in_bytes);
|
|
|
|
|
}
|
|
|
|
|
return new_data;
|
2023-04-13 14:57:57 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-04-13 14:57:57 +02:00
|
|
|
static void free_layer_data(const eCustomDataType type, const void *data, const int totelem)
|
|
|
|
|
{
|
|
|
|
|
const LayerTypeInfo &type_info = *layerType_getInfo(type);
|
|
|
|
|
if (type_info.free) {
|
2023-12-05 17:41:48 -05:00
|
|
|
type_info.free(const_cast<void *>(data), totelem);
|
2023-04-13 14:57:57 +02:00
|
|
|
}
|
|
|
|
|
MEM_freeN(const_cast<void *>(data));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool customdata_merge_internal(const CustomData *source,
|
|
|
|
|
CustomData *dest,
|
|
|
|
|
const eCustomDataMask mask,
|
|
|
|
|
const std::optional<eCDAllocType> alloctype,
|
|
|
|
|
const int totelem)
|
|
|
|
|
{
|
|
|
|
|
bool changed = false;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-04-13 14:57:57 +02:00
|
|
|
int last_type = -1;
|
|
|
|
|
int last_active = 0;
|
|
|
|
|
int last_render = 0;
|
|
|
|
|
int last_clone = 0;
|
|
|
|
|
int last_mask = 0;
|
|
|
|
|
int current_type_layer_count = 0;
|
|
|
|
|
int max_current_type_layer_count = -1;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-04-13 14:57:57 +02:00
|
|
|
for (int i = 0; i < source->totlayer; i++) {
|
|
|
|
|
const CustomDataLayer &src_layer = source->layers[i];
|
|
|
|
|
const eCustomDataType type = eCustomDataType(src_layer.type);
|
|
|
|
|
const int src_layer_flag = src_layer.flag;
|
|
|
|
|
|
|
|
|
|
if (type != last_type) {
|
2023-08-30 10:57:12 +10:00
|
|
|
/* Don't exceed layer count on destination. */
|
2023-08-29 18:02:36 +02:00
|
|
|
const int layernum_dst = CustomData_number_of_layers(dest, type);
|
|
|
|
|
current_type_layer_count = layernum_dst;
|
2023-04-13 14:57:57 +02:00
|
|
|
max_current_type_layer_count = CustomData_layertype_layers_max(type);
|
|
|
|
|
last_active = src_layer.active;
|
|
|
|
|
last_render = src_layer.active_rnd;
|
|
|
|
|
last_clone = src_layer.active_clone;
|
|
|
|
|
last_mask = src_layer.active_mask;
|
|
|
|
|
last_type = type;
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
}
|
2019-04-22 09:39:35 +10:00
|
|
|
else {
|
2023-04-13 14:57:57 +02:00
|
|
|
current_type_layer_count++;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-04-13 14:57:57 +02:00
|
|
|
if (src_layer_flag & CD_FLAG_NOCOPY) {
|
|
|
|
|
/* Don't merge this layer because it's not supposed to leave the source data. */
|
2015-07-20 16:20:48 +02:00
|
|
|
continue;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
if (!(mask & CD_TYPE_AS_MASK(type))) {
|
2023-04-13 14:57:57 +02:00
|
|
|
/* Don't merge this layer because it does not match the type mask. */
|
2014-10-21 17:01:56 +02:00
|
|
|
continue;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2023-04-13 14:57:57 +02:00
|
|
|
if ((max_current_type_layer_count != -1) &&
|
|
|
|
|
(current_type_layer_count >= max_current_type_layer_count))
|
|
|
|
|
{
|
|
|
|
|
/* Don't merge this layer because the maximum amount of layers of this type is reached. */
|
2013-09-21 05:42:34 +00:00
|
|
|
continue;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2023-04-13 14:57:57 +02:00
|
|
|
if (CustomData_get_named_layer_index(dest, type, src_layer.name) != -1) {
|
|
|
|
|
/* Don't merge this layer because it exists in the destination already. */
|
2015-02-19 00:00:23 +05:00
|
|
|
continue;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-04-13 14:57:57 +02:00
|
|
|
void *layer_data_to_assign = nullptr;
|
|
|
|
|
const ImplicitSharingInfo *sharing_info_to_assign = nullptr;
|
|
|
|
|
if (!alloctype.has_value()) {
|
|
|
|
|
if (src_layer.data != nullptr) {
|
|
|
|
|
if (src_layer.sharing_info == nullptr) {
|
|
|
|
|
/* Can't share the layer, duplicate it instead. */
|
|
|
|
|
layer_data_to_assign = copy_layer_data(type, src_layer.data, totelem);
|
2022-09-09 08:24:31 -05:00
|
|
|
}
|
|
|
|
|
else {
|
2023-04-13 14:57:57 +02:00
|
|
|
/* Share the layer. */
|
|
|
|
|
layer_data_to_assign = src_layer.data;
|
|
|
|
|
sharing_info_to_assign = src_layer.sharing_info;
|
2022-09-09 08:24:31 -05:00
|
|
|
}
|
|
|
|
|
}
|
2023-04-13 14:57:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CustomDataLayer *new_layer = customData_add_layer__internal(dest,
|
|
|
|
|
type,
|
|
|
|
|
alloctype,
|
|
|
|
|
layer_data_to_assign,
|
|
|
|
|
sharing_info_to_assign,
|
|
|
|
|
totelem,
|
|
|
|
|
src_layer.name);
|
|
|
|
|
|
|
|
|
|
new_layer->uid = src_layer.uid;
|
|
|
|
|
new_layer->flag |= src_layer_flag & (CD_FLAG_EXTERNAL | CD_FLAG_IN_MEMORY);
|
|
|
|
|
new_layer->active = last_active;
|
|
|
|
|
new_layer->active_rnd = last_render;
|
|
|
|
|
new_layer->active_clone = last_clone;
|
|
|
|
|
new_layer->active_mask = last_mask;
|
|
|
|
|
changed = true;
|
|
|
|
|
|
|
|
|
|
if (src_layer.anonymous_id != nullptr) {
|
|
|
|
|
new_layer->anonymous_id = src_layer.anonymous_id;
|
|
|
|
|
new_layer->anonymous_id->add_user();
|
2007-05-02 00:01:23 +00:00
|
|
|
}
|
2006-12-12 21:29:09 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-05-11 02:14:43 +00:00
|
|
|
CustomData_update_typemap(dest);
|
2013-11-26 06:39:14 +11:00
|
|
|
return changed;
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
|
2023-04-13 14:57:57 +02:00
|
|
|
bool CustomData_merge(const CustomData *source,
|
|
|
|
|
CustomData *dest,
|
|
|
|
|
eCustomDataMask mask,
|
|
|
|
|
int totelem)
|
|
|
|
|
{
|
|
|
|
|
return customdata_merge_internal(source, dest, mask, std::nullopt, totelem);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CustomData_merge_layout(const CustomData *source,
|
|
|
|
|
CustomData *dest,
|
|
|
|
|
const eCustomDataMask mask,
|
|
|
|
|
const eCDAllocType alloctype,
|
|
|
|
|
const int totelem)
|
|
|
|
|
{
|
|
|
|
|
return customdata_merge_internal(source, dest, mask, alloctype, totelem);
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-13 12:42:12 -05:00
|
|
|
CustomData CustomData_shallow_copy_remove_non_bmesh_attributes(const CustomData *src,
|
|
|
|
|
const eCustomDataMask mask)
|
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
2022-08-11 12:54:24 -04:00
|
|
|
{
|
|
|
|
|
Vector<CustomDataLayer> dst_layers;
|
2022-10-13 12:42:12 -05:00
|
|
|
for (const CustomDataLayer &layer : Span<CustomDataLayer>{src->layers, src->totlayer}) {
|
2023-02-10 13:16:10 +01:00
|
|
|
if (BM_attribute_stored_in_bmesh_builtin(layer.name)) {
|
2022-10-13 12:42:12 -05:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (!(mask & CD_TYPE_AS_MASK(layer.type))) {
|
|
|
|
|
continue;
|
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
2022-08-11 12:54:24 -04:00
|
|
|
}
|
2022-10-13 12:42:12 -05:00
|
|
|
dst_layers.append(layer);
|
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
2022-08-11 12:54:24 -04:00
|
|
|
}
|
|
|
|
|
|
2022-10-13 12:42:12 -05:00
|
|
|
CustomData dst = *src;
|
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
2022-08-11 12:54:24 -04:00
|
|
|
dst.layers = static_cast<CustomDataLayer *>(
|
|
|
|
|
MEM_calloc_arrayN(dst_layers.size(), sizeof(CustomDataLayer), __func__));
|
Mesh: Move UV layers to generic attributes
Currently the `MLoopUV` struct stores UV coordinates and flags related
to editing UV maps in the UV editor. This patch changes the coordinates
to use the generic 2D vector type, and moves the flags into three
separate boolean attributes. This follows the design in T95965, with
the ultimate intention of simplifying code and improving performance.
Importantly, the change allows exporters and renderers to use UVs
"touched" by geometry nodes, which only creates generic attributes.
It also allows geometry nodes to create "proper" UV maps from scratch,
though only with the Store Named Attribute node for now.
The new design considers any 2D vector attribute on the corner domain
to be a UV map. In the future, they might be distinguished from regular
2D vectors with attribute metadata, which may be helpful because they
are often interpolated differently.
Most of the code changes deal with passing around UV BMesh custom data
offsets and tracking the boolean "sublayers". The boolean layers are
use the following prefixes for attribute names: vert selection: `.vs.`,
edge selection: `.es.`, pinning: `.pn.`. Currently these are short to
avoid using up the maximum length of attribute names. To accommodate
for these 4 extra characters, the name length limit is enlarged to 68
bytes, while the maximum user settable name length is still 64 bytes.
Unfortunately Python/RNA API access to the UV flag data becomes slower.
Accessing the boolean layers directly is be better for performance in
general.
Like the other mesh SoA refactors, backward and forward compatibility
aren't affected, and won't be changed until 4.0. We pay for that by
making mesh reading and writing more expensive with conversions.
Resolves T85962
Differential Revision: https://developer.blender.org/D14365
2023-01-10 00:47:04 -05:00
|
|
|
dst.maxlayer = dst.totlayer = dst_layers.size();
|
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
2022-08-11 12:54:24 -04:00
|
|
|
memcpy(dst.layers, dst_layers.data(), dst_layers.as_span().size_in_bytes());
|
|
|
|
|
|
|
|
|
|
CustomData_update_typemap(&dst);
|
|
|
|
|
|
|
|
|
|
return dst;
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-13 14:57:57 +02:00
|
|
|
/**
|
|
|
|
|
* An #ImplicitSharingInfo that knows how to free the entire referenced custom data layer
|
|
|
|
|
* (including potentially separately allocated chunks like for vertex groups).
|
|
|
|
|
*/
|
|
|
|
|
class CustomDataLayerImplicitSharing : public ImplicitSharingInfo {
|
|
|
|
|
private:
|
|
|
|
|
const void *data_;
|
BLI: support weak users and version in implicit sharing info
The main goal of these changes is to support checking if some data has
been changed over time. This is used by the WIP simulation nodes during
baking to detect which attributes have to be stored in every frame because
they have changed.
By using a combination of a weak user count and a version counter, it is
possible to detect that an attribute (or any data controlled by implicit
sharing) has not been changed with O(1) memory and time. It's still
possible that the data has been changed multiple times and is the same
in the end and beginning of course. That wouldn't be detected using this
mechanism.
The `ImplicitSharingInfo` struct has a new weak user count. A weak
reference is one that does not keep the referenced data alive, but makes sure
that the `ImplicitSharingInfo` itself is not deleted. If some piece of
data has one strong and multiple weak users, it is still mutable. If the
strong user count goes down to zero, the referenced data is freed.
Remaining weak users can check for this condition using `is_expired`.
This is a bit similar to `std::weak_ptr` but there is an important difference:
a weak user can not become a strong user while one can create a `shared_ptr`
from a `weak_ptr`. This restriction is necessary, because some code might
be changing the referenced data assuming that it is the only owner. If
another thread suddenly adds a new owner, the data would be shared again
and the first thread would not have been allowed to modify the data in
the first place.
There is also a new integer version counter in `ImplicitSharingInfo`.
It is incremented whenever some code wants to modify the referenced data.
Obviously, this can only be done when the data is not shared because then
it would be immutable. By comparing an old and new version number of the
same sharing info, one can check if the data has been modified. One has
to keep a weak reference to the sharing info together with the old version
number to ensure that the new sharing info is still the same as the old one.
Without this, it can happen that the sharing info was freed and a new
one was allocated at the same pointer address. Using a strong reference
for this purpose does not work, because then the data would never be
modified because it's shared.
2023-04-28 12:03:42 +02:00
|
|
|
int totelem_;
|
2023-04-13 14:57:57 +02:00
|
|
|
const eCustomDataType type_;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
CustomDataLayerImplicitSharing(const void *data, const int totelem, const eCustomDataType type)
|
BLI: support weak users and version in implicit sharing info
The main goal of these changes is to support checking if some data has
been changed over time. This is used by the WIP simulation nodes during
baking to detect which attributes have to be stored in every frame because
they have changed.
By using a combination of a weak user count and a version counter, it is
possible to detect that an attribute (or any data controlled by implicit
sharing) has not been changed with O(1) memory and time. It's still
possible that the data has been changed multiple times and is the same
in the end and beginning of course. That wouldn't be detected using this
mechanism.
The `ImplicitSharingInfo` struct has a new weak user count. A weak
reference is one that does not keep the referenced data alive, but makes sure
that the `ImplicitSharingInfo` itself is not deleted. If some piece of
data has one strong and multiple weak users, it is still mutable. If the
strong user count goes down to zero, the referenced data is freed.
Remaining weak users can check for this condition using `is_expired`.
This is a bit similar to `std::weak_ptr` but there is an important difference:
a weak user can not become a strong user while one can create a `shared_ptr`
from a `weak_ptr`. This restriction is necessary, because some code might
be changing the referenced data assuming that it is the only owner. If
another thread suddenly adds a new owner, the data would be shared again
and the first thread would not have been allowed to modify the data in
the first place.
There is also a new integer version counter in `ImplicitSharingInfo`.
It is incremented whenever some code wants to modify the referenced data.
Obviously, this can only be done when the data is not shared because then
it would be immutable. By comparing an old and new version number of the
same sharing info, one can check if the data has been modified. One has
to keep a weak reference to the sharing info together with the old version
number to ensure that the new sharing info is still the same as the old one.
Without this, it can happen that the sharing info was freed and a new
one was allocated at the same pointer address. Using a strong reference
for this purpose does not work, because then the data would never be
modified because it's shared.
2023-04-28 12:03:42 +02:00
|
|
|
: ImplicitSharingInfo(), data_(data), totelem_(totelem), type_(type)
|
2023-04-13 14:57:57 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
void delete_self_with_data() override
|
|
|
|
|
{
|
BLI: support weak users and version in implicit sharing info
The main goal of these changes is to support checking if some data has
been changed over time. This is used by the WIP simulation nodes during
baking to detect which attributes have to be stored in every frame because
they have changed.
By using a combination of a weak user count and a version counter, it is
possible to detect that an attribute (or any data controlled by implicit
sharing) has not been changed with O(1) memory and time. It's still
possible that the data has been changed multiple times and is the same
in the end and beginning of course. That wouldn't be detected using this
mechanism.
The `ImplicitSharingInfo` struct has a new weak user count. A weak
reference is one that does not keep the referenced data alive, but makes sure
that the `ImplicitSharingInfo` itself is not deleted. If some piece of
data has one strong and multiple weak users, it is still mutable. If the
strong user count goes down to zero, the referenced data is freed.
Remaining weak users can check for this condition using `is_expired`.
This is a bit similar to `std::weak_ptr` but there is an important difference:
a weak user can not become a strong user while one can create a `shared_ptr`
from a `weak_ptr`. This restriction is necessary, because some code might
be changing the referenced data assuming that it is the only owner. If
another thread suddenly adds a new owner, the data would be shared again
and the first thread would not have been allowed to modify the data in
the first place.
There is also a new integer version counter in `ImplicitSharingInfo`.
It is incremented whenever some code wants to modify the referenced data.
Obviously, this can only be done when the data is not shared because then
it would be immutable. By comparing an old and new version number of the
same sharing info, one can check if the data has been modified. One has
to keep a weak reference to the sharing info together with the old version
number to ensure that the new sharing info is still the same as the old one.
Without this, it can happen that the sharing info was freed and a new
one was allocated at the same pointer address. Using a strong reference
for this purpose does not work, because then the data would never be
modified because it's shared.
2023-04-28 12:03:42 +02:00
|
|
|
if (data_ != nullptr) {
|
|
|
|
|
free_layer_data(type_, data_, totelem_);
|
|
|
|
|
}
|
2023-04-13 14:57:57 +02:00
|
|
|
MEM_delete(this);
|
|
|
|
|
}
|
BLI: support weak users and version in implicit sharing info
The main goal of these changes is to support checking if some data has
been changed over time. This is used by the WIP simulation nodes during
baking to detect which attributes have to be stored in every frame because
they have changed.
By using a combination of a weak user count and a version counter, it is
possible to detect that an attribute (or any data controlled by implicit
sharing) has not been changed with O(1) memory and time. It's still
possible that the data has been changed multiple times and is the same
in the end and beginning of course. That wouldn't be detected using this
mechanism.
The `ImplicitSharingInfo` struct has a new weak user count. A weak
reference is one that does not keep the referenced data alive, but makes sure
that the `ImplicitSharingInfo` itself is not deleted. If some piece of
data has one strong and multiple weak users, it is still mutable. If the
strong user count goes down to zero, the referenced data is freed.
Remaining weak users can check for this condition using `is_expired`.
This is a bit similar to `std::weak_ptr` but there is an important difference:
a weak user can not become a strong user while one can create a `shared_ptr`
from a `weak_ptr`. This restriction is necessary, because some code might
be changing the referenced data assuming that it is the only owner. If
another thread suddenly adds a new owner, the data would be shared again
and the first thread would not have been allowed to modify the data in
the first place.
There is also a new integer version counter in `ImplicitSharingInfo`.
It is incremented whenever some code wants to modify the referenced data.
Obviously, this can only be done when the data is not shared because then
it would be immutable. By comparing an old and new version number of the
same sharing info, one can check if the data has been modified. One has
to keep a weak reference to the sharing info together with the old version
number to ensure that the new sharing info is still the same as the old one.
Without this, it can happen that the sharing info was freed and a new
one was allocated at the same pointer address. Using a strong reference
for this purpose does not work, because then the data would never be
modified because it's shared.
2023-04-28 12:03:42 +02:00
|
|
|
|
|
|
|
|
void delete_data_only() override
|
|
|
|
|
{
|
|
|
|
|
free_layer_data(type_, data_, totelem_);
|
|
|
|
|
data_ = nullptr;
|
|
|
|
|
totelem_ = 0;
|
|
|
|
|
}
|
2023-04-13 14:57:57 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/** Create a #ImplicitSharingInfo that takes ownership of the data. */
|
2023-04-20 23:31:32 +02:00
|
|
|
static const ImplicitSharingInfo *make_implicit_sharing_info_for_layer(const eCustomDataType type,
|
|
|
|
|
const void *data,
|
|
|
|
|
const int totelem)
|
2023-04-13 14:57:57 +02:00
|
|
|
{
|
|
|
|
|
return MEM_new<CustomDataLayerImplicitSharing>(__func__, data, totelem, type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* If the layer data is currently shared (hence it is immutable), create a copy that can be edited.
|
|
|
|
|
*/
|
|
|
|
|
static void ensure_layer_data_is_mutable(CustomDataLayer &layer, const int totelem)
|
|
|
|
|
{
|
|
|
|
|
if (layer.data == nullptr) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (layer.sharing_info == nullptr) {
|
|
|
|
|
/* Can not be shared without implicit-sharing data. */
|
|
|
|
|
return;
|
|
|
|
|
}
|
BLI: support weak users and version in implicit sharing info
The main goal of these changes is to support checking if some data has
been changed over time. This is used by the WIP simulation nodes during
baking to detect which attributes have to be stored in every frame because
they have changed.
By using a combination of a weak user count and a version counter, it is
possible to detect that an attribute (or any data controlled by implicit
sharing) has not been changed with O(1) memory and time. It's still
possible that the data has been changed multiple times and is the same
in the end and beginning of course. That wouldn't be detected using this
mechanism.
The `ImplicitSharingInfo` struct has a new weak user count. A weak
reference is one that does not keep the referenced data alive, but makes sure
that the `ImplicitSharingInfo` itself is not deleted. If some piece of
data has one strong and multiple weak users, it is still mutable. If the
strong user count goes down to zero, the referenced data is freed.
Remaining weak users can check for this condition using `is_expired`.
This is a bit similar to `std::weak_ptr` but there is an important difference:
a weak user can not become a strong user while one can create a `shared_ptr`
from a `weak_ptr`. This restriction is necessary, because some code might
be changing the referenced data assuming that it is the only owner. If
another thread suddenly adds a new owner, the data would be shared again
and the first thread would not have been allowed to modify the data in
the first place.
There is also a new integer version counter in `ImplicitSharingInfo`.
It is incremented whenever some code wants to modify the referenced data.
Obviously, this can only be done when the data is not shared because then
it would be immutable. By comparing an old and new version number of the
same sharing info, one can check if the data has been modified. One has
to keep a weak reference to the sharing info together with the old version
number to ensure that the new sharing info is still the same as the old one.
Without this, it can happen that the sharing info was freed and a new
one was allocated at the same pointer address. Using a strong reference
for this purpose does not work, because then the data would never be
modified because it's shared.
2023-04-28 12:03:42 +02:00
|
|
|
if (layer.sharing_info->is_mutable()) {
|
|
|
|
|
layer.sharing_info->tag_ensured_mutable();
|
|
|
|
|
}
|
|
|
|
|
else {
|
2023-04-13 14:57:57 +02:00
|
|
|
const eCustomDataType type = eCustomDataType(layer.type);
|
|
|
|
|
const void *old_data = layer.data;
|
|
|
|
|
/* Copy the layer before removing the user because otherwise the data might be freed while
|
|
|
|
|
* we're still copying from it here. */
|
|
|
|
|
layer.data = copy_layer_data(type, old_data, totelem);
|
|
|
|
|
layer.sharing_info->remove_user_and_delete_if_last();
|
|
|
|
|
layer.sharing_info = make_implicit_sharing_info_for_layer(type, layer.data, totelem);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-11 12:49:42 +02:00
|
|
|
[[maybe_unused]] static bool layer_is_mutable(CustomDataLayer &layer)
|
2023-10-11 11:34:29 +02:00
|
|
|
{
|
|
|
|
|
if (layer.sharing_info == nullptr) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return layer.sharing_info->is_mutable();
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-12 13:03:01 +02:00
|
|
|
void CustomData_ensure_data_is_mutable(CustomDataLayer *layer, const int totelem)
|
|
|
|
|
{
|
|
|
|
|
ensure_layer_data_is_mutable(*layer, totelem);
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-07 11:31:07 +11:00
|
|
|
void CustomData_ensure_layers_are_mutable(CustomData *data, int totelem)
|
2023-10-11 11:34:29 +02:00
|
|
|
{
|
|
|
|
|
for (const int i : IndexRange(data->totlayer)) {
|
|
|
|
|
ensure_layer_data_is_mutable(data->layers[i], totelem);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-16 18:41:07 +02:00
|
|
|
void CustomData_realloc(CustomData *data,
|
|
|
|
|
const int old_size,
|
|
|
|
|
const int new_size,
|
|
|
|
|
const eCDAllocType alloctype)
|
2015-08-25 10:29:40 +02:00
|
|
|
{
|
2022-09-12 11:35:33 -05:00
|
|
|
BLI_assert(new_size >= 0);
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2015-08-25 10:29:40 +02:00
|
|
|
CustomDataLayer *layer = &data->layers[i];
|
2023-03-29 17:10:49 +02:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
|
2022-09-12 11:35:33 -05:00
|
|
|
const int64_t old_size_in_bytes = int64_t(old_size) * typeInfo->size;
|
|
|
|
|
const int64_t new_size_in_bytes = int64_t(new_size) * typeInfo->size;
|
2023-04-13 14:57:57 +02:00
|
|
|
|
2024-02-13 18:59:36 +01:00
|
|
|
void *new_layer_data = MEM_mallocN_aligned(new_size_in_bytes, typeInfo->alignment, __func__);
|
2023-04-13 14:57:57 +02:00
|
|
|
/* Copy data to new array. */
|
|
|
|
|
if (old_size_in_bytes) {
|
2022-09-12 11:35:33 -05:00
|
|
|
if (typeInfo->copy) {
|
2023-04-13 14:57:57 +02:00
|
|
|
typeInfo->copy(layer->data, new_layer_data, std::min(old_size, new_size));
|
2022-09-12 11:35:33 -05:00
|
|
|
}
|
|
|
|
|
else {
|
2023-04-13 14:57:57 +02:00
|
|
|
BLI_assert(layer->data != nullptr);
|
|
|
|
|
memcpy(new_layer_data, layer->data, std::min(old_size_in_bytes, new_size_in_bytes));
|
2022-09-12 11:35:33 -05:00
|
|
|
}
|
|
|
|
|
}
|
2023-04-13 14:57:57 +02:00
|
|
|
/* Remove ownership of old array */
|
|
|
|
|
if (layer->sharing_info) {
|
|
|
|
|
layer->sharing_info->remove_user_and_delete_if_last();
|
|
|
|
|
layer->sharing_info = nullptr;
|
|
|
|
|
}
|
|
|
|
|
/* Take ownership of new array. */
|
|
|
|
|
layer->data = new_layer_data;
|
|
|
|
|
if (layer->data) {
|
|
|
|
|
layer->sharing_info = make_implicit_sharing_info_for_layer(
|
|
|
|
|
eCustomDataType(layer->type), layer->data, new_size);
|
2022-09-12 11:35:33 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (new_size > old_size) {
|
2023-10-16 18:41:07 +02:00
|
|
|
const int new_elements_num = new_size - old_size;
|
|
|
|
|
void *new_elements_begin = POINTER_OFFSET(layer->data, old_size_in_bytes);
|
|
|
|
|
switch (alloctype) {
|
|
|
|
|
case CD_CONSTRUCT: {
|
|
|
|
|
/* Initialize new values for non-trivial types. */
|
|
|
|
|
if (typeInfo->construct) {
|
|
|
|
|
typeInfo->construct(new_elements_begin, new_elements_num);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CD_SET_DEFAULT: {
|
|
|
|
|
if (typeInfo->set_default_value) {
|
|
|
|
|
typeInfo->set_default_value(new_elements_begin, new_elements_num);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
memset(new_elements_begin, 0, typeInfo->size * new_elements_num);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2022-09-12 11:35:33 -05:00
|
|
|
}
|
2015-08-25 10:29:40 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-13 14:57:57 +02:00
|
|
|
void CustomData_copy(const CustomData *source, CustomData *dest, eCustomDataMask mask, int totelem)
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
{
|
2012-10-31 09:50:24 +00:00
|
|
|
CustomData_reset(dest);
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (source->external) {
|
2021-12-25 14:28:22 -06:00
|
|
|
dest->external = static_cast<CustomDataExternal *>(MEM_dupallocN(source->external));
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2010-03-30 12:01:17 +00:00
|
|
|
|
2023-04-13 14:57:57 +02:00
|
|
|
CustomData_merge(source, dest, mask, totelem);
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
void CustomData_copy_layout(const CustomData *source,
|
|
|
|
|
CustomData *dest,
|
2023-04-13 14:57:57 +02:00
|
|
|
eCustomDataMask mask,
|
|
|
|
|
eCDAllocType alloctype,
|
|
|
|
|
int totelem)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2023-04-13 14:57:57 +02:00
|
|
|
CustomData_reset(dest);
|
|
|
|
|
|
|
|
|
|
if (source->external) {
|
|
|
|
|
dest->external = static_cast<CustomDataExternal *>(MEM_dupallocN(source->external));
|
|
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2023-04-13 14:57:57 +02:00
|
|
|
CustomData_merge_layout(source, dest, mask, alloctype, totelem);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void customData_free_layer__internal(CustomDataLayer *layer, const int totelem)
|
|
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
if (layer->anonymous_id != nullptr) {
|
2023-03-28 13:57:51 +02:00
|
|
|
layer->anonymous_id->remove_user_and_delete_if_last();
|
2021-12-25 14:28:22 -06:00
|
|
|
layer->anonymous_id = nullptr;
|
2021-09-09 12:54:20 +02:00
|
|
|
}
|
2023-04-13 14:57:57 +02:00
|
|
|
const eCustomDataType type = eCustomDataType(layer->type);
|
|
|
|
|
if (layer->sharing_info == nullptr) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (layer->data) {
|
2023-04-13 14:57:57 +02:00
|
|
|
free_layer_data(type, layer->data, totelem);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
2023-04-13 14:57:57 +02:00
|
|
|
else {
|
|
|
|
|
layer->sharing_info->remove_user_and_delete_if_last();
|
|
|
|
|
layer->sharing_info = nullptr;
|
|
|
|
|
}
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2009-11-25 14:27:50 +00:00
|
|
|
static void CustomData_external_free(CustomData *data)
|
|
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
if (data->external) {
|
2009-11-25 14:27:50 +00:00
|
|
|
MEM_freeN(data->external);
|
2021-12-25 14:28:22 -06:00
|
|
|
data->external = nullptr;
|
2009-11-25 14:27:50 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-31 09:50:24 +00:00
|
|
|
void CustomData_reset(CustomData *data)
|
|
|
|
|
{
|
|
|
|
|
memset(data, 0, sizeof(*data));
|
2015-05-05 17:08:29 +10:00
|
|
|
copy_vn_i(data->typemap, CD_NUMTYPES, -1);
|
2012-10-31 09:50:24 +00:00
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
void CustomData_free(CustomData *data, const int totelem)
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
{
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2006-12-12 21:29:09 +00:00
|
|
|
customData_free_layer__internal(&data->layers[i], totelem);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (data->layers) {
|
2006-08-28 01:12:36 +00:00
|
|
|
MEM_freeN(data->layers);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2009-11-25 14:27:50 +00:00
|
|
|
CustomData_external_free(data);
|
2012-10-31 09:50:24 +00:00
|
|
|
CustomData_reset(data);
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
void CustomData_free_typemask(CustomData *data, const int totelem, eCustomDataMask mask)
|
2015-02-19 00:00:23 +05:00
|
|
|
{
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2015-02-19 00:00:23 +05:00
|
|
|
CustomDataLayer *layer = &data->layers[i];
|
|
|
|
|
if (!(mask & CD_TYPE_AS_MASK(layer->type))) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
customData_free_layer__internal(layer, totelem);
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (data->layers) {
|
2015-02-19 00:00:23 +05:00
|
|
|
MEM_freeN(data->layers);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2015-02-19 00:00:23 +05:00
|
|
|
|
|
|
|
|
CustomData_external_free(data);
|
|
|
|
|
CustomData_reset(data);
|
|
|
|
|
}
|
|
|
|
|
|
2006-12-12 21:29:09 +00:00
|
|
|
static void customData_update_offsets(CustomData *data)
|
|
|
|
|
{
|
|
|
|
|
const LayerTypeInfo *typeInfo;
|
2020-09-09 15:43:09 +02:00
|
|
|
int offset = 0;
|
2006-12-12 21:29:09 +00:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2023-03-29 17:10:49 +02:00
|
|
|
typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
|
2006-12-12 21:29:09 +00:00
|
|
|
data->layers[i].offset = offset;
|
|
|
|
|
offset += typeInfo->size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data->totsize = offset;
|
2011-05-11 02:14:43 +00:00
|
|
|
CustomData_update_typemap(data);
|
2006-12-12 21:29:09 +00:00
|
|
|
}
|
|
|
|
|
|
2012-10-31 09:50:24 +00:00
|
|
|
/* to use when we're in the middle of modifying layers */
|
2023-03-29 17:10:49 +02:00
|
|
|
static int CustomData_get_layer_index__notypemap(const CustomData *data,
|
|
|
|
|
const eCustomDataType type)
|
2006-11-11 16:38:37 +00:00
|
|
|
{
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (data->layers[i].type == type) {
|
2006-12-12 21:29:09 +00:00
|
|
|
return i;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2006-11-11 16:38:37 +00:00
|
|
|
|
2006-12-12 21:29:09 +00:00
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-31 09:50:24 +00:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/* index values to access the layers (offset from the layer start) */
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
int CustomData_get_layer_index(const CustomData *data, const eCustomDataType type)
|
2012-10-31 09:50:24 +00:00
|
|
|
{
|
|
|
|
|
BLI_assert(customdata_typemap_is_valid(data));
|
|
|
|
|
return data->typemap[type];
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
int CustomData_get_layer_index_n(const CustomData *data, const eCustomDataType type, const int n)
|
2009-11-02 06:31:23 +00:00
|
|
|
{
|
2020-09-15 13:17:19 +10:00
|
|
|
BLI_assert(n >= 0);
|
2011-11-20 16:19:56 +00:00
|
|
|
int i = CustomData_get_layer_index(data, type);
|
2009-11-02 06:31:23 +00:00
|
|
|
|
2011-11-20 16:19:56 +00:00
|
|
|
if (i != -1) {
|
2023-08-04 20:55:53 +03:00
|
|
|
/* If the value of n goes past the block of layers of the correct type, return -1. */
|
|
|
|
|
i = (i + n < data->totlayer && data->layers[i + n].type == type) ? (i + n) : (-1);
|
2011-11-20 16:19:56 +00:00
|
|
|
}
|
2009-11-02 06:31:23 +00:00
|
|
|
|
2011-11-20 16:19:56 +00:00
|
|
|
return i;
|
2009-11-02 06:31:23 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
int CustomData_get_named_layer_index(const CustomData *data,
|
|
|
|
|
const eCustomDataType type,
|
2024-02-08 16:56:42 +01:00
|
|
|
const StringRef name)
|
2006-12-23 23:33:03 +00:00
|
|
|
{
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (data->layers[i].type == type) {
|
2024-02-08 16:56:42 +01:00
|
|
|
if (data->layers[i].name == name) {
|
2013-09-21 05:42:34 +00:00
|
|
|
return i;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2006-12-23 23:33:03 +00:00
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-08 16:56:42 +01:00
|
|
|
int CustomData_get_named_layer_index_notype(const CustomData *data, const StringRef name)
|
Mesh: Move UV layers to generic attributes
Currently the `MLoopUV` struct stores UV coordinates and flags related
to editing UV maps in the UV editor. This patch changes the coordinates
to use the generic 2D vector type, and moves the flags into three
separate boolean attributes. This follows the design in T95965, with
the ultimate intention of simplifying code and improving performance.
Importantly, the change allows exporters and renderers to use UVs
"touched" by geometry nodes, which only creates generic attributes.
It also allows geometry nodes to create "proper" UV maps from scratch,
though only with the Store Named Attribute node for now.
The new design considers any 2D vector attribute on the corner domain
to be a UV map. In the future, they might be distinguished from regular
2D vectors with attribute metadata, which may be helpful because they
are often interpolated differently.
Most of the code changes deal with passing around UV BMesh custom data
offsets and tracking the boolean "sublayers". The boolean layers are
use the following prefixes for attribute names: vert selection: `.vs.`,
edge selection: `.es.`, pinning: `.pn.`. Currently these are short to
avoid using up the maximum length of attribute names. To accommodate
for these 4 extra characters, the name length limit is enlarged to 68
bytes, while the maximum user settable name length is still 64 bytes.
Unfortunately Python/RNA API access to the UV flag data becomes slower.
Accessing the boolean layers directly is be better for performance in
general.
Like the other mesh SoA refactors, backward and forward compatibility
aren't affected, and won't be changed until 4.0. We pay for that by
making mesh reading and writing more expensive with conversions.
Resolves T85962
Differential Revision: https://developer.blender.org/D14365
2023-01-10 00:47:04 -05:00
|
|
|
{
|
|
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2024-02-08 16:56:42 +01:00
|
|
|
if (data->layers[i].name == name) {
|
Mesh: Move UV layers to generic attributes
Currently the `MLoopUV` struct stores UV coordinates and flags related
to editing UV maps in the UV editor. This patch changes the coordinates
to use the generic 2D vector type, and moves the flags into three
separate boolean attributes. This follows the design in T95965, with
the ultimate intention of simplifying code and improving performance.
Importantly, the change allows exporters and renderers to use UVs
"touched" by geometry nodes, which only creates generic attributes.
It also allows geometry nodes to create "proper" UV maps from scratch,
though only with the Store Named Attribute node for now.
The new design considers any 2D vector attribute on the corner domain
to be a UV map. In the future, they might be distinguished from regular
2D vectors with attribute metadata, which may be helpful because they
are often interpolated differently.
Most of the code changes deal with passing around UV BMesh custom data
offsets and tracking the boolean "sublayers". The boolean layers are
use the following prefixes for attribute names: vert selection: `.vs.`,
edge selection: `.es.`, pinning: `.pn.`. Currently these are short to
avoid using up the maximum length of attribute names. To accommodate
for these 4 extra characters, the name length limit is enlarged to 68
bytes, while the maximum user settable name length is still 64 bytes.
Unfortunately Python/RNA API access to the UV flag data becomes slower.
Accessing the boolean layers directly is be better for performance in
general.
Like the other mesh SoA refactors, backward and forward compatibility
aren't affected, and won't be changed until 4.0. We pay for that by
making mesh reading and writing more expensive with conversions.
Resolves T85962
Differential Revision: https://developer.blender.org/D14365
2023-01-10 00:47:04 -05:00
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
int CustomData_get_active_layer_index(const CustomData *data, const eCustomDataType type)
|
2006-12-12 21:29:09 +00:00
|
|
|
{
|
2012-10-31 09:50:24 +00:00
|
|
|
const int layer_index = data->typemap[type];
|
|
|
|
|
BLI_assert(customdata_typemap_is_valid(data));
|
2014-01-12 22:27:55 +11:00
|
|
|
return (layer_index != -1) ? layer_index + data->layers[layer_index].active : -1;
|
2006-11-11 16:38:37 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
int CustomData_get_render_layer_index(const CustomData *data, const eCustomDataType type)
|
2007-05-02 00:01:23 +00:00
|
|
|
{
|
2012-10-31 09:50:24 +00:00
|
|
|
const int layer_index = data->typemap[type];
|
|
|
|
|
BLI_assert(customdata_typemap_is_valid(data));
|
|
|
|
|
return (layer_index != -1) ? layer_index + data->layers[layer_index].active_rnd : -1;
|
2007-05-02 00:01:23 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
int CustomData_get_clone_layer_index(const CustomData *data, const eCustomDataType type)
|
2008-12-14 17:32:24 +00:00
|
|
|
{
|
2012-10-31 09:50:24 +00:00
|
|
|
const int layer_index = data->typemap[type];
|
|
|
|
|
BLI_assert(customdata_typemap_is_valid(data));
|
|
|
|
|
return (layer_index != -1) ? layer_index + data->layers[layer_index].active_clone : -1;
|
2008-12-14 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
int CustomData_get_stencil_layer_index(const CustomData *data, const eCustomDataType type)
|
2008-12-14 17:32:24 +00:00
|
|
|
{
|
2012-10-31 09:50:24 +00:00
|
|
|
const int layer_index = data->typemap[type];
|
|
|
|
|
BLI_assert(customdata_typemap_is_valid(data));
|
|
|
|
|
return (layer_index != -1) ? layer_index + data->layers[layer_index].active_mask : -1;
|
|
|
|
|
}
|
2008-12-14 17:32:24 +00:00
|
|
|
|
2012-10-31 09:50:24 +00:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/* index values per layer type */
|
2008-12-14 17:32:24 +00:00
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
int CustomData_get_named_layer(const CustomData *data,
|
|
|
|
|
const eCustomDataType type,
|
2024-02-08 16:56:42 +01:00
|
|
|
const StringRef name)
|
2013-03-24 12:13:13 +00:00
|
|
|
{
|
|
|
|
|
const int named_index = CustomData_get_named_layer_index(data, type, name);
|
|
|
|
|
const int layer_index = data->typemap[type];
|
|
|
|
|
BLI_assert(customdata_typemap_is_valid(data));
|
|
|
|
|
return (named_index != -1) ? named_index - layer_index : -1;
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
int CustomData_get_active_layer(const CustomData *data, const eCustomDataType type)
|
2007-09-18 19:39:25 +00:00
|
|
|
{
|
2012-10-31 09:50:24 +00:00
|
|
|
const int layer_index = data->typemap[type];
|
|
|
|
|
BLI_assert(customdata_typemap_is_valid(data));
|
|
|
|
|
return (layer_index != -1) ? data->layers[layer_index].active : -1;
|
2007-09-18 19:39:25 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
int CustomData_get_render_layer(const CustomData *data, const eCustomDataType type)
|
2007-09-18 19:39:25 +00:00
|
|
|
{
|
2012-10-31 09:50:24 +00:00
|
|
|
const int layer_index = data->typemap[type];
|
|
|
|
|
BLI_assert(customdata_typemap_is_valid(data));
|
|
|
|
|
return (layer_index != -1) ? data->layers[layer_index].active_rnd : -1;
|
2007-09-18 19:39:25 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
int CustomData_get_clone_layer(const CustomData *data, const eCustomDataType type)
|
2008-12-14 17:32:24 +00:00
|
|
|
{
|
2012-10-31 09:50:24 +00:00
|
|
|
const int layer_index = data->typemap[type];
|
|
|
|
|
BLI_assert(customdata_typemap_is_valid(data));
|
|
|
|
|
return (layer_index != -1) ? data->layers[layer_index].active_clone : -1;
|
2008-12-14 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
int CustomData_get_stencil_layer(const CustomData *data, const eCustomDataType type)
|
2008-12-14 17:32:24 +00:00
|
|
|
{
|
2012-10-31 09:50:24 +00:00
|
|
|
const int layer_index = data->typemap[type];
|
|
|
|
|
BLI_assert(customdata_typemap_is_valid(data));
|
|
|
|
|
return (layer_index != -1) ? data->layers[layer_index].active_mask : -1;
|
2008-12-14 17:32:24 +00:00
|
|
|
}
|
2007-09-18 19:39:25 +00:00
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
const char *CustomData_get_active_layer_name(const CustomData *data, const eCustomDataType type)
|
USD Preview Surface material export.
Add `USD Preview Surface From Nodes` export option, to convert a
Principled BSDF material node network to an approximate USD Preview
Surface shader representation. If this option is disabled, the original
material export behavior is maintained, where viewport setting are saved
to the Preview Surface shader.
Also added the following options for texture export.
- `Export Textures`: If converting Preview Surface, export textures
referenced by shader nodes to a 'textures' directory which is a
sibling of the USD file.
- `Overwrite Textures`: Allow overwriting existing texture files when
exporting textures (this option is off by default).
- `Relative Texture Paths`: Make texture asset paths relative to the
USD.
The entry point for the new functionality is
`create_usd_preview_surface_material()`, called from
`USDAbstractWriter::ensure_usd_material()`. The material conversion
currently handles a small subset of Blender shading nodes,
`BSDF_DIFFUSE`, `BSDF_PRINCIPLED`, `TEX_IMAGE` and `UVMAP`.
Texture export is handled by copying texture files from their original
location to a `textures` folder in the same directory as the USD.
In-memory and packed textures are saved directly to the textures folder.
This patch is based, in part, on code in Tangent Animation's USD
exporter branch.
Reviewed By: sybren, HooglyBoogly
Differential Revision: https://developer.blender.org/D13647
2022-01-27 15:43:14 +01:00
|
|
|
{
|
|
|
|
|
/* Get the layer index of the active layer of this type. */
|
|
|
|
|
const int layer_index = CustomData_get_active_layer_index(data, type);
|
2022-02-03 18:27:42 -06:00
|
|
|
return layer_index < 0 ? nullptr : data->layers[layer_index].name;
|
USD Preview Surface material export.
Add `USD Preview Surface From Nodes` export option, to convert a
Principled BSDF material node network to an approximate USD Preview
Surface shader representation. If this option is disabled, the original
material export behavior is maintained, where viewport setting are saved
to the Preview Surface shader.
Also added the following options for texture export.
- `Export Textures`: If converting Preview Surface, export textures
referenced by shader nodes to a 'textures' directory which is a
sibling of the USD file.
- `Overwrite Textures`: Allow overwriting existing texture files when
exporting textures (this option is off by default).
- `Relative Texture Paths`: Make texture asset paths relative to the
USD.
The entry point for the new functionality is
`create_usd_preview_surface_material()`, called from
`USDAbstractWriter::ensure_usd_material()`. The material conversion
currently handles a small subset of Blender shading nodes,
`BSDF_DIFFUSE`, `BSDF_PRINCIPLED`, `TEX_IMAGE` and `UVMAP`.
Texture export is handled by copying texture files from their original
location to a `textures` folder in the same directory as the USD.
In-memory and packed textures are saved directly to the textures folder.
This patch is based, in part, on code in Tangent Animation's USD
exporter branch.
Reviewed By: sybren, HooglyBoogly
Differential Revision: https://developer.blender.org/D13647
2022-01-27 15:43:14 +01:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
const char *CustomData_get_render_layer_name(const CustomData *data, const eCustomDataType type)
|
2022-08-26 11:15:32 -05:00
|
|
|
{
|
|
|
|
|
const int layer_index = CustomData_get_render_layer_index(data, type);
|
|
|
|
|
return layer_index < 0 ? nullptr : data->layers[layer_index].name;
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
void CustomData_set_layer_active(CustomData *data, const eCustomDataType type, const int n)
|
2006-12-12 21:29:09 +00:00
|
|
|
{
|
2023-03-23 13:55:51 +11:00
|
|
|
#ifndef NDEBUG
|
|
|
|
|
const int layer_num = CustomData_number_of_layers(data, type);
|
|
|
|
|
#endif
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (data->layers[i].type == type) {
|
2023-03-23 13:55:51 +11:00
|
|
|
BLI_assert(uint(n) < uint(layer_num));
|
2006-12-12 21:29:09 +00:00
|
|
|
data->layers[i].active = n;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2006-12-12 21:29:09 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
void CustomData_set_layer_render(CustomData *data, const eCustomDataType type, const int n)
|
2007-05-02 00:01:23 +00:00
|
|
|
{
|
2023-03-23 13:55:51 +11:00
|
|
|
#ifndef NDEBUG
|
|
|
|
|
const int layer_num = CustomData_number_of_layers(data, type);
|
|
|
|
|
#endif
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (data->layers[i].type == type) {
|
2023-03-23 13:55:51 +11:00
|
|
|
BLI_assert(uint(n) < uint(layer_num));
|
2007-05-02 00:01:23 +00:00
|
|
|
data->layers[i].active_rnd = n;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2007-05-02 00:01:23 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
void CustomData_set_layer_clone(CustomData *data, const eCustomDataType type, const int n)
|
2008-12-14 17:32:24 +00:00
|
|
|
{
|
2023-03-23 13:55:51 +11:00
|
|
|
#ifndef NDEBUG
|
|
|
|
|
const int layer_num = CustomData_number_of_layers(data, type);
|
|
|
|
|
#endif
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (data->layers[i].type == type) {
|
2023-03-23 13:55:51 +11:00
|
|
|
BLI_assert(uint(n) < uint(layer_num));
|
2008-12-14 17:32:24 +00:00
|
|
|
data->layers[i].active_clone = n;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2008-12-14 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
void CustomData_set_layer_stencil(CustomData *data, const eCustomDataType type, const int n)
|
2008-12-14 17:32:24 +00:00
|
|
|
{
|
2023-03-23 13:55:51 +11:00
|
|
|
#ifndef NDEBUG
|
|
|
|
|
const int layer_num = CustomData_number_of_layers(data, type);
|
|
|
|
|
#endif
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (data->layers[i].type == type) {
|
2023-03-23 13:55:51 +11:00
|
|
|
BLI_assert(uint(n) < uint(layer_num));
|
2008-12-14 17:32:24 +00:00
|
|
|
data->layers[i].active_mask = n;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2008-12-14 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
void CustomData_set_layer_active_index(CustomData *data, const eCustomDataType type, const int n)
|
2007-09-12 02:13:35 +00:00
|
|
|
{
|
2023-03-23 13:55:51 +11:00
|
|
|
#ifndef NDEBUG
|
|
|
|
|
const int layer_num = CustomData_number_of_layers(data, type);
|
|
|
|
|
#endif
|
|
|
|
|
const int layer_index = n - data->typemap[type];
|
2022-05-16 16:32:41 +02:00
|
|
|
BLI_assert(customdata_typemap_is_valid(data));
|
|
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (data->layers[i].type == type) {
|
2023-03-23 13:55:51 +11:00
|
|
|
BLI_assert(uint(layer_index) < uint(layer_num));
|
|
|
|
|
data->layers[i].active = layer_index;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2007-09-12 02:13:35 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
void CustomData_set_layer_render_index(CustomData *data, const eCustomDataType type, const int n)
|
2007-09-12 02:13:35 +00:00
|
|
|
{
|
2023-03-23 13:55:51 +11:00
|
|
|
#ifndef NDEBUG
|
|
|
|
|
const int layer_num = CustomData_number_of_layers(data, type);
|
|
|
|
|
#endif
|
|
|
|
|
const int layer_index = n - data->typemap[type];
|
2022-05-16 16:32:41 +02:00
|
|
|
BLI_assert(customdata_typemap_is_valid(data));
|
|
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (data->layers[i].type == type) {
|
2023-03-23 13:55:51 +11:00
|
|
|
BLI_assert(uint(layer_index) < uint(layer_num));
|
|
|
|
|
data->layers[i].active_rnd = layer_index;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2007-09-12 02:13:35 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
void CustomData_set_layer_clone_index(CustomData *data, const eCustomDataType type, const int n)
|
2008-12-14 17:32:24 +00:00
|
|
|
{
|
2023-03-23 13:55:51 +11:00
|
|
|
#ifndef NDEBUG
|
|
|
|
|
const int layer_num = CustomData_number_of_layers(data, type);
|
|
|
|
|
#endif
|
|
|
|
|
const int layer_index = n - data->typemap[type];
|
2022-05-20 09:36:30 +02:00
|
|
|
BLI_assert(customdata_typemap_is_valid(data));
|
|
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (data->layers[i].type == type) {
|
2023-03-23 13:55:51 +11:00
|
|
|
BLI_assert(uint(layer_index) < uint(layer_num));
|
|
|
|
|
data->layers[i].active_clone = layer_index;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2008-12-14 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
void CustomData_set_layer_stencil_index(CustomData *data, const eCustomDataType type, const int n)
|
2008-12-14 17:32:24 +00:00
|
|
|
{
|
2023-03-23 13:55:51 +11:00
|
|
|
#ifndef NDEBUG
|
|
|
|
|
const int layer_num = CustomData_number_of_layers(data, type);
|
|
|
|
|
#endif
|
|
|
|
|
const int layer_index = n - data->typemap[type];
|
2022-05-20 09:36:30 +02:00
|
|
|
BLI_assert(customdata_typemap_is_valid(data));
|
|
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (data->layers[i].type == type) {
|
2023-03-23 13:55:51 +11:00
|
|
|
BLI_assert(uint(layer_index) < uint(layer_num));
|
|
|
|
|
data->layers[i].active_mask = layer_index;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2008-12-14 17:32:24 +00:00
|
|
|
}
|
2007-05-02 00:01:23 +00:00
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
void CustomData_set_layer_flag(CustomData *data, const eCustomDataType type, const int flag)
|
2006-12-12 21:29:09 +00:00
|
|
|
{
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (data->layers[i].type == type) {
|
2006-12-12 21:29:09 +00:00
|
|
|
data->layers[i].flag |= flag;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2006-12-12 21:29:09 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
void CustomData_clear_layer_flag(CustomData *data, const eCustomDataType type, const int flag)
|
2019-02-28 18:03:01 +01:00
|
|
|
{
|
|
|
|
|
const int nflag = ~flag;
|
|
|
|
|
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2019-02-28 18:03:01 +01:00
|
|
|
if (data->layers[i].type == type) {
|
|
|
|
|
data->layers[i].flag &= nflag;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
bool CustomData_layer_is_anonymous(const CustomData *data, eCustomDataType type, int n)
|
2023-03-17 09:41:52 +01:00
|
|
|
{
|
|
|
|
|
const int layer_index = CustomData_get_layer_index_n(data, type, n);
|
|
|
|
|
|
|
|
|
|
BLI_assert(layer_index >= 0);
|
|
|
|
|
|
|
|
|
|
return data->layers[layer_index].anonymous_id != nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-08 13:09:30 +02:00
|
|
|
static void customData_resize(CustomData *data, const int grow_amount)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2023-04-08 13:09:30 +02:00
|
|
|
data->layers = static_cast<CustomDataLayer *>(
|
|
|
|
|
MEM_reallocN(data->layers, (data->maxlayer + grow_amount) * sizeof(CustomDataLayer)));
|
|
|
|
|
data->maxlayer += grow_amount;
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-04-13 14:57:57 +02:00
|
|
|
static CustomDataLayer *customData_add_layer__internal(
|
|
|
|
|
CustomData *data,
|
|
|
|
|
const eCustomDataType type,
|
|
|
|
|
const std::optional<eCDAllocType> alloctype,
|
|
|
|
|
void *layer_data_to_assign,
|
|
|
|
|
const ImplicitSharingInfo *sharing_info_to_assign,
|
|
|
|
|
const int totelem,
|
2024-02-08 16:56:42 +01:00
|
|
|
StringRef name)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2023-04-13 14:57:57 +02:00
|
|
|
const LayerTypeInfo &type_info = *layerType_getInfo(type);
|
2022-08-03 11:58:52 -05:00
|
|
|
int flag = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-11-11 09:07:54 -06:00
|
|
|
/* Some layer types only support a single layer. */
|
2023-04-13 14:57:57 +02:00
|
|
|
if (!type_info.defaultname && CustomData_has_layer(data, type)) {
|
2022-11-11 09:07:54 -06:00
|
|
|
/* This function doesn't support dealing with existing layer data for these layer types when
|
|
|
|
|
* the layer already exists. */
|
2023-04-13 14:57:57 +02:00
|
|
|
BLI_assert(layer_data_to_assign == nullptr);
|
2022-11-11 09:07:54 -06:00
|
|
|
return &data->layers[CustomData_get_layer_index(data, type)];
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
int index = data->totlayer;
|
2012-03-24 06:18:31 +00:00
|
|
|
if (index >= data->maxlayer) {
|
2023-04-08 13:09:30 +02:00
|
|
|
customData_resize(data, CUSTOMDATA_GROW);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2006-12-21 13:47:27 +00:00
|
|
|
data->totlayer++;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-04-13 14:57:57 +02:00
|
|
|
/* Keep layers ordered by type. */
|
2019-09-08 00:12:26 +10:00
|
|
|
for (; index > 0 && data->layers[index - 1].type > type; index--) {
|
2006-08-28 01:12:36 +00:00
|
|
|
data->layers[index] = data->layers[index - 1];
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
CustomDataLayer &new_layer = data->layers[index];
|
|
|
|
|
|
2021-10-13 15:36:52 +02:00
|
|
|
/* Clear remaining data on the layer. The original data on the layer has been moved to another
|
|
|
|
|
* index. Without this, it can happen that information from the previous layer at that index
|
|
|
|
|
* leaks into the new layer. */
|
2022-08-03 11:58:52 -05:00
|
|
|
memset(&new_layer, 0, sizeof(CustomDataLayer));
|
2021-10-13 15:36:52 +02:00
|
|
|
|
2024-02-13 18:59:36 +01:00
|
|
|
const int64_t size_in_bytes = int64_t(totelem) * type_info.size;
|
|
|
|
|
const char *alloc_name = layerType_getName(type);
|
|
|
|
|
|
2023-04-13 14:57:57 +02:00
|
|
|
if (alloctype.has_value()) {
|
|
|
|
|
switch (*alloctype) {
|
|
|
|
|
case CD_SET_DEFAULT: {
|
|
|
|
|
if (totelem > 0) {
|
2024-02-13 18:59:36 +01:00
|
|
|
new_layer.data = MEM_mallocN_aligned(size_in_bytes, type_info.alignment, alloc_name);
|
2023-04-13 14:57:57 +02:00
|
|
|
if (type_info.set_default_value) {
|
|
|
|
|
type_info.set_default_value(new_layer.data, totelem);
|
|
|
|
|
}
|
|
|
|
|
else {
|
2024-02-13 18:59:36 +01:00
|
|
|
/* Alternatively, #MEM_calloc_arrayN is faster, but has no aligned version. */
|
|
|
|
|
memset(new_layer.data, 0, size_in_bytes);
|
2023-04-13 14:57:57 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CD_CONSTRUCT: {
|
|
|
|
|
if (totelem > 0) {
|
2024-02-13 18:59:36 +01:00
|
|
|
new_layer.data = MEM_mallocN_aligned(size_in_bytes, type_info.alignment, alloc_name);
|
2023-04-13 14:57:57 +02:00
|
|
|
if (type_info.construct) {
|
|
|
|
|
type_info.construct(new_layer.data, totelem);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (totelem == 0 && sharing_info_to_assign == nullptr) {
|
|
|
|
|
MEM_SAFE_FREE(layer_data_to_assign);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
new_layer.data = layer_data_to_assign;
|
|
|
|
|
new_layer.sharing_info = sharing_info_to_assign;
|
|
|
|
|
if (new_layer.sharing_info) {
|
|
|
|
|
new_layer.sharing_info->add_user();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (new_layer.data != nullptr && new_layer.sharing_info == nullptr) {
|
|
|
|
|
/* Make layer data shareable. */
|
|
|
|
|
new_layer.sharing_info = make_implicit_sharing_info_for_layer(type, new_layer.data, totelem);
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
new_layer.type = type;
|
|
|
|
|
new_layer.flag = flag;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-11-24 19:21:35 +01:00
|
|
|
/* Set default name if none exists. Note we only call DATA_() once
|
|
|
|
|
* we know there is a default name, to avoid overhead of locale lookups
|
|
|
|
|
* in the depsgraph. */
|
2024-02-08 16:56:42 +01:00
|
|
|
if (name.is_empty() && type_info.defaultname) {
|
2023-04-13 14:57:57 +02:00
|
|
|
name = DATA_(type_info.defaultname);
|
2018-11-24 19:21:35 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-02-08 16:56:42 +01:00
|
|
|
if (!name.is_empty()) {
|
|
|
|
|
name.copy(new_layer.name);
|
2006-12-21 13:47:27 +00:00
|
|
|
CustomData_set_layer_unique_name(data, index);
|
|
|
|
|
}
|
2019-04-22 09:39:35 +10:00
|
|
|
else {
|
2022-08-03 11:58:52 -05:00
|
|
|
new_layer.name[0] = '\0';
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-12 16:11:34 +00:00
|
|
|
if (index > 0 && data->layers[index - 1].type == type) {
|
2022-08-03 11:58:52 -05:00
|
|
|
new_layer.active = data->layers[index - 1].active;
|
|
|
|
|
new_layer.active_rnd = data->layers[index - 1].active_rnd;
|
|
|
|
|
new_layer.active_clone = data->layers[index - 1].active_clone;
|
|
|
|
|
new_layer.active_mask = data->layers[index - 1].active_mask;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2022-08-03 11:58:52 -05:00
|
|
|
new_layer.active = 0;
|
|
|
|
|
new_layer.active_rnd = 0;
|
|
|
|
|
new_layer.active_clone = 0;
|
|
|
|
|
new_layer.active_mask = 0;
|
2007-05-02 00:01:23 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2006-12-12 21:29:09 +00:00
|
|
|
customData_update_offsets(data);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2006-12-12 21:29:09 +00:00
|
|
|
return &data->layers[index];
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
|
2023-04-13 14:57:57 +02:00
|
|
|
void *CustomData_add_layer(CustomData *data,
|
|
|
|
|
const eCustomDataType type,
|
|
|
|
|
eCDAllocType alloctype,
|
|
|
|
|
const int totelem)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2012-05-12 16:11:34 +00:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2021-01-26 09:21:42 -06:00
|
|
|
CustomDataLayer *layer = customData_add_layer__internal(
|
2023-04-13 14:57:57 +02:00
|
|
|
data, type, alloctype, nullptr, nullptr, totelem, typeInfo->defaultname);
|
2011-05-11 02:14:43 +00:00
|
|
|
CustomData_update_typemap(data);
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (layer) {
|
2006-12-12 21:29:09 +00:00
|
|
|
return layer->data;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2021-12-25 14:28:22 -06:00
|
|
|
return nullptr;
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-14 15:30:26 +01:00
|
|
|
const void *CustomData_add_layer_with_data(CustomData *data,
|
|
|
|
|
const eCustomDataType type,
|
|
|
|
|
void *layer_data,
|
2023-04-13 14:57:57 +02:00
|
|
|
const int totelem,
|
|
|
|
|
const ImplicitSharingInfo *sharing_info)
|
2023-03-14 15:30:26 +01:00
|
|
|
{
|
2023-04-13 14:57:57 +02:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
2023-03-14 15:30:26 +01:00
|
|
|
|
2021-01-26 09:21:42 -06:00
|
|
|
CustomDataLayer *layer = customData_add_layer__internal(
|
2023-04-13 14:57:57 +02:00
|
|
|
data, type, std::nullopt, layer_data, sharing_info, totelem, typeInfo->defaultname);
|
2011-05-11 02:14:43 +00:00
|
|
|
CustomData_update_typemap(data);
|
2006-12-24 11:15:54 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (layer) {
|
2006-12-24 11:15:54 +00:00
|
|
|
return layer->data;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2006-12-24 11:15:54 +00:00
|
|
|
|
2021-12-25 14:28:22 -06:00
|
|
|
return nullptr;
|
2006-12-24 11:15:54 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-14 15:30:26 +01:00
|
|
|
void *CustomData_add_layer_named(CustomData *data,
|
|
|
|
|
const eCustomDataType type,
|
|
|
|
|
const eCDAllocType alloctype,
|
|
|
|
|
const int totelem,
|
2024-02-08 16:56:42 +01:00
|
|
|
const StringRef name)
|
2023-03-14 15:30:26 +01:00
|
|
|
{
|
2023-04-13 14:57:57 +02:00
|
|
|
CustomDataLayer *layer = customData_add_layer__internal(
|
|
|
|
|
data, type, alloctype, nullptr, nullptr, totelem, name);
|
|
|
|
|
CustomData_update_typemap(data);
|
|
|
|
|
|
|
|
|
|
if (layer) {
|
|
|
|
|
return layer->data;
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
2023-03-14 15:30:26 +01:00
|
|
|
}
|
|
|
|
|
|
2023-04-13 14:57:57 +02:00
|
|
|
const void *CustomData_add_layer_named_with_data(CustomData *data,
|
|
|
|
|
eCustomDataType type,
|
|
|
|
|
void *layer_data,
|
|
|
|
|
int totelem,
|
2024-02-08 16:56:42 +01:00
|
|
|
const StringRef name,
|
2023-04-13 14:57:57 +02:00
|
|
|
const ImplicitSharingInfo *sharing_info)
|
2023-03-14 15:30:26 +01:00
|
|
|
{
|
2023-04-13 14:57:57 +02:00
|
|
|
CustomDataLayer *layer = customData_add_layer__internal(
|
|
|
|
|
data, type, std::nullopt, layer_data, sharing_info, totelem, name);
|
|
|
|
|
CustomData_update_typemap(data);
|
|
|
|
|
|
|
|
|
|
if (layer) {
|
|
|
|
|
return layer->data;
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
2023-03-14 15:30:26 +01:00
|
|
|
}
|
|
|
|
|
|
2022-06-04 13:31:30 +02:00
|
|
|
void *CustomData_add_layer_anonymous(CustomData *data,
|
2023-03-29 17:10:49 +02:00
|
|
|
const eCustomDataType type,
|
2022-08-03 11:58:52 -05:00
|
|
|
const eCDAllocType alloctype,
|
|
|
|
|
const int totelem,
|
2023-01-05 14:05:30 +01:00
|
|
|
const AnonymousAttributeIDHandle *anonymous_id)
|
2021-09-09 12:54:20 +02:00
|
|
|
{
|
2024-02-08 16:56:42 +01:00
|
|
|
const StringRef name = anonymous_id->name().c_str();
|
2021-09-09 12:54:20 +02:00
|
|
|
CustomDataLayer *layer = customData_add_layer__internal(
|
2023-04-13 14:57:57 +02:00
|
|
|
data, type, alloctype, nullptr, nullptr, totelem, name);
|
2021-09-09 12:54:20 +02:00
|
|
|
CustomData_update_typemap(data);
|
|
|
|
|
|
2021-12-25 14:28:22 -06:00
|
|
|
if (layer == nullptr) {
|
|
|
|
|
return nullptr;
|
2021-09-09 12:54:20 +02:00
|
|
|
}
|
|
|
|
|
|
2023-03-28 13:57:51 +02:00
|
|
|
anonymous_id->add_user();
|
2021-09-09 12:54:20 +02:00
|
|
|
layer->anonymous_id = anonymous_id;
|
|
|
|
|
return layer->data;
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-13 14:57:57 +02:00
|
|
|
const void *CustomData_add_layer_anonymous_with_data(
|
|
|
|
|
CustomData *data,
|
|
|
|
|
const eCustomDataType type,
|
|
|
|
|
const AnonymousAttributeIDHandle *anonymous_id,
|
|
|
|
|
const int totelem,
|
|
|
|
|
void *layer_data,
|
|
|
|
|
const ImplicitSharingInfo *sharing_info)
|
|
|
|
|
{
|
2024-02-08 16:56:42 +01:00
|
|
|
const StringRef name = anonymous_id->name().c_str();
|
2023-04-13 14:57:57 +02:00
|
|
|
CustomDataLayer *layer = customData_add_layer__internal(
|
|
|
|
|
data, type, std::nullopt, layer_data, sharing_info, totelem, name);
|
|
|
|
|
CustomData_update_typemap(data);
|
|
|
|
|
|
|
|
|
|
if (layer == nullptr) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
anonymous_id->add_user();
|
|
|
|
|
layer->anonymous_id = anonymous_id;
|
|
|
|
|
return layer->data;
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
bool CustomData_free_layer(CustomData *data,
|
|
|
|
|
const eCustomDataType type,
|
|
|
|
|
const int totelem,
|
|
|
|
|
const int index)
|
2006-11-11 16:38:37 +00:00
|
|
|
{
|
2017-05-26 23:19:33 +10:00
|
|
|
const int index_first = CustomData_get_layer_index(data, type);
|
|
|
|
|
const int n = index - index_first;
|
2006-11-11 16:38:37 +00:00
|
|
|
|
2017-05-27 14:03:15 +10:00
|
|
|
BLI_assert(index >= index_first);
|
|
|
|
|
if ((index_first == -1) || (n < 0)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
BLI_assert(data->layers[index].type == type);
|
|
|
|
|
|
2006-12-12 21:29:09 +00:00
|
|
|
customData_free_layer__internal(&data->layers[index], totelem);
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = index + 1; i < data->totlayer; i++) {
|
2012-05-12 16:11:34 +00:00
|
|
|
data->layers[i - 1] = data->layers[i];
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2006-11-11 16:38:37 +00:00
|
|
|
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
data->totlayer--;
|
2006-11-11 16:38:37 +00:00
|
|
|
|
2006-12-12 21:29:09 +00:00
|
|
|
/* if layer was last of type in array, set new active layer */
|
2020-09-09 15:43:09 +02:00
|
|
|
int i = CustomData_get_layer_index__notypemap(data, type);
|
2013-07-15 06:29:09 +00:00
|
|
|
|
|
|
|
|
if (i != -1) {
|
2013-07-15 09:03:28 +00:00
|
|
|
/* don't decrement zero index */
|
2013-11-29 15:23:22 +11:00
|
|
|
const int index_nonzero = n ? n : 1;
|
2013-07-15 06:29:09 +00:00
|
|
|
CustomDataLayer *layer;
|
2013-07-15 09:03:28 +00:00
|
|
|
|
2013-07-15 06:29:09 +00:00
|
|
|
for (layer = &data->layers[i]; i < data->totlayer && layer->type == type; i++, layer++) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (layer->active >= index_nonzero) {
|
2013-07-15 09:03:28 +00:00
|
|
|
layer->active--;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (layer->active_rnd >= index_nonzero) {
|
2013-07-15 09:03:28 +00:00
|
|
|
layer->active_rnd--;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (layer->active_clone >= index_nonzero) {
|
2013-07-15 09:03:28 +00:00
|
|
|
layer->active_clone--;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (layer->active_mask >= index_nonzero) {
|
2013-07-15 09:03:28 +00:00
|
|
|
layer->active_mask--;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2006-12-12 21:29:09 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2006-12-12 21:29:09 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (data->totlayer <= data->maxlayer - CUSTOMDATA_GROW) {
|
2006-11-11 16:38:37 +00:00
|
|
|
customData_resize(data, -CUSTOMDATA_GROW);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2006-11-11 16:38:37 +00:00
|
|
|
|
2006-12-12 21:29:09 +00:00
|
|
|
customData_update_offsets(data);
|
2006-11-11 16:38:37 +00:00
|
|
|
|
2014-12-01 17:11:18 +01:00
|
|
|
return true;
|
2006-11-11 16:38:37 +00:00
|
|
|
}
|
|
|
|
|
|
2024-02-08 16:56:42 +01:00
|
|
|
bool CustomData_free_layer_named(CustomData *data, const StringRef name, const int totelem)
|
2022-06-07 18:00:18 +02:00
|
|
|
{
|
|
|
|
|
for (const int i : IndexRange(data->totlayer)) {
|
|
|
|
|
const CustomDataLayer &layer = data->layers[i];
|
|
|
|
|
if (StringRef(layer.name) == name) {
|
2023-03-29 17:10:49 +02:00
|
|
|
CustomData_free_layer(data, eCustomDataType(layer.type), totelem, i);
|
2022-06-07 18:00:18 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
bool CustomData_free_layer_active(CustomData *data, const eCustomDataType type, const int totelem)
|
2006-12-23 17:07:02 +00:00
|
|
|
{
|
2020-09-09 15:43:09 +02:00
|
|
|
const int index = CustomData_get_active_layer_index(data, type);
|
2019-04-22 09:39:35 +10:00
|
|
|
if (index == -1) {
|
2014-12-01 17:11:18 +01:00
|
|
|
return false;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2006-12-23 17:07:02 +00:00
|
|
|
return CustomData_free_layer(data, type, totelem, index);
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
void CustomData_free_layers(CustomData *data, const eCustomDataType type, const int totelem)
|
2006-12-12 21:29:09 +00:00
|
|
|
{
|
2017-05-26 23:19:33 +10:00
|
|
|
const int index = CustomData_get_layer_index(data, type);
|
|
|
|
|
while (CustomData_free_layer(data, type, totelem, index)) {
|
|
|
|
|
/* pass */
|
|
|
|
|
}
|
2006-12-12 21:29:09 +00:00
|
|
|
}
|
|
|
|
|
|
2023-05-17 16:16:54 -04:00
|
|
|
bool CustomData_has_layer_named(const CustomData *data,
|
|
|
|
|
const eCustomDataType type,
|
2024-02-08 16:56:42 +01:00
|
|
|
const StringRef name)
|
2023-05-17 16:16:54 -04:00
|
|
|
{
|
|
|
|
|
return CustomData_get_named_layer_index(data, type, name) != -1;
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
bool CustomData_has_layer(const CustomData *data, const eCustomDataType type)
|
2006-11-11 16:38:37 +00:00
|
|
|
{
|
2006-12-12 21:29:09 +00:00
|
|
|
return (CustomData_get_layer_index(data, type) != -1);
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
int CustomData_number_of_layers(const CustomData *data, const eCustomDataType type)
|
2006-12-12 21:29:09 +00:00
|
|
|
{
|
2020-09-09 15:43:09 +02:00
|
|
|
int number = 0;
|
2006-12-12 21:29:09 +00:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (data->layers[i].type == type) {
|
2006-12-12 21:29:09 +00:00
|
|
|
number++;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2006-12-12 21:29:09 +00:00
|
|
|
return number;
|
2006-11-11 16:38:37 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
int CustomData_number_of_anonymous_layers(const CustomData *data, const eCustomDataType type)
|
2023-02-20 11:51:16 +01:00
|
|
|
{
|
|
|
|
|
int number = 0;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
|
|
|
|
if (data->layers[i].type == type && data->layers[i].anonymous_id != nullptr) {
|
|
|
|
|
number++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return number;
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
int CustomData_number_of_layers_typemask(const CustomData *data, const eCustomDataMask mask)
|
2013-05-09 10:41:05 +00:00
|
|
|
{
|
2020-09-09 15:43:09 +02:00
|
|
|
int number = 0;
|
2013-05-09 10:41:05 +00:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (mask & CD_TYPE_AS_MASK(data->layers[i].type)) {
|
2013-05-09 10:41:05 +00:00
|
|
|
number++;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2013-05-09 10:41:05 +00:00
|
|
|
|
|
|
|
|
return number;
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
void CustomData_set_only_copy(const CustomData *data, const eCustomDataMask mask)
|
2006-12-05 17:42:03 +00:00
|
|
|
{
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!(mask & CD_TYPE_AS_MASK(data->layers[i].type))) {
|
2006-12-05 17:42:03 +00:00
|
|
|
data->layers[i].flag |= CD_FLAG_NOCOPY;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2006-12-05 17:42:03 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
void CustomData_copy_elements(const eCustomDataType type,
|
2022-08-03 11:58:52 -05:00
|
|
|
void *src_data_ofs,
|
|
|
|
|
void *dst_data_ofs,
|
|
|
|
|
const int count)
|
2009-08-18 20:05:08 +00:00
|
|
|
{
|
|
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
|
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (typeInfo->copy) {
|
2015-02-23 13:43:09 +11:00
|
|
|
typeInfo->copy(src_data_ofs, dst_data_ofs, count);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2022-09-25 18:33:28 +10:00
|
|
|
memcpy(dst_data_ofs, src_data_ofs, size_t(count) * typeInfo->size);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2009-08-18 20:05:08 +00:00
|
|
|
}
|
|
|
|
|
|
2021-02-21 17:57:03 -05:00
|
|
|
void CustomData_copy_data_layer(const CustomData *source,
|
|
|
|
|
CustomData *dest,
|
2022-08-03 11:58:52 -05:00
|
|
|
const int src_layer_index,
|
|
|
|
|
const int dst_layer_index,
|
|
|
|
|
const int src_index,
|
|
|
|
|
const int dst_index,
|
|
|
|
|
const int count)
|
2015-08-06 12:34:31 +10:00
|
|
|
{
|
2013-09-21 05:42:34 +00:00
|
|
|
const LayerTypeInfo *typeInfo;
|
|
|
|
|
|
2023-10-11 11:34:29 +02:00
|
|
|
BLI_assert(layer_is_mutable(dest->layers[dst_layer_index]));
|
|
|
|
|
|
2021-02-22 09:28:00 -06:00
|
|
|
const void *src_data = source->layers[src_layer_index].data;
|
|
|
|
|
void *dst_data = dest->layers[dst_layer_index].data;
|
2013-09-21 05:42:34 +00:00
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
typeInfo = layerType_getInfo(eCustomDataType(source->layers[src_layer_index].type));
|
2013-09-21 05:42:34 +00:00
|
|
|
|
2022-09-25 18:33:28 +10:00
|
|
|
const size_t src_offset = size_t(src_index) * typeInfo->size;
|
|
|
|
|
const size_t dst_offset = size_t(dst_index) * typeInfo->size;
|
2013-09-21 05:42:34 +00:00
|
|
|
|
2015-07-30 22:06:05 +10:00
|
|
|
if (!count || !src_data || !dst_data) {
|
2021-12-25 14:28:22 -06:00
|
|
|
if (count && !(src_data == nullptr && dst_data == nullptr)) {
|
2019-02-01 12:44:19 +11:00
|
|
|
CLOG_WARN(&LOG,
|
|
|
|
|
"null data for %s type (%p --> %p), skipping",
|
2023-03-29 17:10:49 +02:00
|
|
|
layerType_getName(eCustomDataType(source->layers[src_layer_index].type)),
|
2019-03-15 08:53:22 +11:00
|
|
|
(void *)src_data,
|
|
|
|
|
(void *)dst_data);
|
2013-10-05 19:56:32 +00:00
|
|
|
}
|
2013-09-21 05:42:34 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-17 03:01:32 +10:00
|
|
|
if (typeInfo->copy) {
|
2015-02-23 13:51:55 +11:00
|
|
|
typeInfo->copy(
|
|
|
|
|
POINTER_OFFSET(src_data, src_offset), POINTER_OFFSET(dst_data, dst_offset), count);
|
2016-05-17 03:01:32 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2015-02-23 13:43:09 +11:00
|
|
|
memcpy(POINTER_OFFSET(dst_data, dst_offset),
|
2015-02-23 13:51:55 +11:00
|
|
|
POINTER_OFFSET(src_data, src_offset),
|
2022-09-25 18:33:28 +10:00
|
|
|
size_t(count) * typeInfo->size);
|
2016-05-17 03:01:32 +10:00
|
|
|
}
|
2013-09-21 05:42:34 +00:00
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
void CustomData_copy_data_named(const CustomData *source,
|
|
|
|
|
CustomData *dest,
|
|
|
|
|
const int source_index,
|
|
|
|
|
const int dest_index,
|
|
|
|
|
const int count)
|
2013-09-21 05:42:34 +00:00
|
|
|
{
|
|
|
|
|
/* copies a layer at a time */
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int src_i = 0; src_i < source->totlayer; src_i++) {
|
2013-09-21 05:42:34 +00:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
int dest_i = CustomData_get_named_layer_index(
|
2023-03-29 17:10:49 +02:00
|
|
|
dest, eCustomDataType(source->layers[src_i].type), source->layers[src_i].name);
|
2013-09-21 05:42:34 +00:00
|
|
|
|
|
|
|
|
/* if we found a matching layer, copy the data */
|
2014-02-01 01:45:09 +11:00
|
|
|
if (dest_i != -1) {
|
2013-09-21 05:42:34 +00:00
|
|
|
CustomData_copy_data_layer(source, dest, src_i, dest_i, source_index, dest_index, count);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
void CustomData_copy_data(const CustomData *source,
|
|
|
|
|
CustomData *dest,
|
|
|
|
|
const int source_index,
|
|
|
|
|
const int dest_index,
|
|
|
|
|
const int count)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
|
|
|
|
/* copies a layer at a time */
|
2020-09-09 15:43:09 +02:00
|
|
|
int dest_i = 0;
|
|
|
|
|
for (int src_i = 0; src_i < source->totlayer; src_i++) {
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
|
/* find the first dest layer with type >= the source type
|
|
|
|
|
* (this should work because layers are ordered by type)
|
|
|
|
|
*/
|
2012-04-21 15:11:03 +00:00
|
|
|
while (dest_i < dest->totlayer && dest->layers[dest_i].type < source->layers[src_i].type) {
|
2012-08-18 13:07:48 +00:00
|
|
|
dest_i++;
|
2012-04-21 15:11:03 +00:00
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
|
/* if there are no more dest layers, we're done */
|
2019-04-22 09:39:35 +10:00
|
|
|
if (dest_i >= dest->totlayer) {
|
2012-03-24 06:18:31 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
|
/* if we found a matching layer, copy the data */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (dest->layers[dest_i].type == source->layers[src_i].type) {
|
2013-09-21 05:42:34 +00:00
|
|
|
CustomData_copy_data_layer(source, dest, src_i, dest_i, source_index, dest_index, count);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* if there are multiple source & dest layers of the same type,
|
|
|
|
|
* we don't want to copy all source layers to the same dest, so
|
|
|
|
|
* increment dest_i
|
|
|
|
|
*/
|
2012-08-18 13:07:48 +00:00
|
|
|
dest_i++;
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-25 12:27:43 +02:00
|
|
|
void CustomData_copy_layer_type_data(const CustomData *source,
|
|
|
|
|
CustomData *destination,
|
2023-03-29 17:10:49 +02:00
|
|
|
const eCustomDataType type,
|
2018-09-25 12:27:43 +02:00
|
|
|
int source_index,
|
|
|
|
|
int destination_index,
|
|
|
|
|
int count)
|
|
|
|
|
{
|
|
|
|
|
const int source_layer_index = CustomData_get_layer_index(source, type);
|
|
|
|
|
if (source_layer_index == -1) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const int destinaiton_layer_index = CustomData_get_layer_index(destination, type);
|
|
|
|
|
if (destinaiton_layer_index == -1) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
CustomData_copy_data_layer(source,
|
|
|
|
|
destination,
|
|
|
|
|
source_layer_index,
|
|
|
|
|
destinaiton_layer_index,
|
|
|
|
|
source_index,
|
|
|
|
|
destination_index,
|
|
|
|
|
count);
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
void CustomData_free_elem(CustomData *data, const int index, const int count)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2023-04-13 14:57:57 +02:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2023-04-13 14:57:57 +02:00
|
|
|
if (typeInfo->free) {
|
|
|
|
|
size_t offset = size_t(index) * typeInfo->size;
|
2023-10-11 11:34:29 +02:00
|
|
|
BLI_assert(layer_is_mutable(data->layers[i]));
|
2006-08-28 01:12:36 +00:00
|
|
|
|
2023-12-05 17:41:48 -05:00
|
|
|
typeInfo->free(POINTER_OFFSET(data->layers[i].data, offset), count);
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define SOURCE_BUF_SIZE 100
|
|
|
|
|
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
void CustomData_interp(const CustomData *source,
|
|
|
|
|
CustomData *dest,
|
2016-05-17 03:07:40 +10:00
|
|
|
const int *src_indices,
|
|
|
|
|
const float *weights,
|
|
|
|
|
const float *sub_weights,
|
2012-05-12 16:11:34 +00:00
|
|
|
int count,
|
|
|
|
|
int dest_index)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2020-10-05 18:50:38 +02:00
|
|
|
if (count <= 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 13:51:55 +11:00
|
|
|
const void *source_buf[SOURCE_BUF_SIZE];
|
|
|
|
|
const void **sources = source_buf;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-17 00:54:22 +10:00
|
|
|
/* Slow fallback in case we're interpolating a ridiculous number of elements. */
|
2019-04-22 09:39:35 +10:00
|
|
|
if (count > SOURCE_BUF_SIZE) {
|
2021-12-25 14:28:22 -06:00
|
|
|
sources = static_cast<const void **>(MEM_malloc_arrayN(count, sizeof(*sources), __func__));
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-10-05 18:50:38 +02:00
|
|
|
/* If no weights are given, generate default ones to produce an average result. */
|
|
|
|
|
float default_weights_buf[SOURCE_BUF_SIZE];
|
2021-12-25 14:28:22 -06:00
|
|
|
float *default_weights = nullptr;
|
|
|
|
|
if (weights == nullptr) {
|
2020-10-05 18:50:38 +02:00
|
|
|
default_weights = (count > SOURCE_BUF_SIZE) ?
|
2021-12-25 14:28:22 -06:00
|
|
|
static_cast<float *>(
|
2022-09-25 18:33:28 +10:00
|
|
|
MEM_mallocN(sizeof(*weights) * size_t(count), __func__)) :
|
2020-10-05 18:50:38 +02:00
|
|
|
default_weights_buf;
|
|
|
|
|
copy_vn_fl(default_weights, count, 1.0f / count);
|
|
|
|
|
weights = default_weights;
|
|
|
|
|
}
|
|
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* interpolates a layer at a time */
|
2020-09-09 15:43:09 +02:00
|
|
|
int dest_i = 0;
|
|
|
|
|
for (int src_i = 0; src_i < source->totlayer; src_i++) {
|
2023-03-29 17:10:49 +02:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(source->layers[src_i].type));
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!typeInfo->interp) {
|
2012-03-24 06:18:31 +00:00
|
|
|
continue;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2006-12-12 21:29:09 +00:00
|
|
|
/* find the first dest layer with type >= the source type
|
|
|
|
|
* (this should work because layers are ordered by type)
|
|
|
|
|
*/
|
2012-04-21 15:11:03 +00:00
|
|
|
while (dest_i < dest->totlayer && dest->layers[dest_i].type < source->layers[src_i].type) {
|
2012-08-18 13:07:48 +00:00
|
|
|
dest_i++;
|
2012-04-21 15:11:03 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2006-12-12 21:29:09 +00:00
|
|
|
/* if there are no more dest layers, we're done */
|
2019-04-22 09:39:35 +10:00
|
|
|
if (dest_i >= dest->totlayer) {
|
2012-10-01 14:15:05 +00:00
|
|
|
break;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2006-12-12 21:29:09 +00:00
|
|
|
/* if we found a matching layer, copy the data */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (dest->layers[dest_i].type == source->layers[src_i].type) {
|
2006-12-12 21:29:09 +00:00
|
|
|
void *src_data = source->layers[src_i].data;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int j = 0; j < count; j++) {
|
2022-09-25 18:33:28 +10:00
|
|
|
sources[j] = POINTER_OFFSET(src_data, size_t(src_indices[j]) * typeInfo->size);
|
2012-08-23 17:16:11 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2006-12-12 21:29:09 +00:00
|
|
|
typeInfo->interp(
|
|
|
|
|
sources,
|
|
|
|
|
weights,
|
|
|
|
|
sub_weights,
|
|
|
|
|
count,
|
2022-09-25 18:33:28 +10:00
|
|
|
POINTER_OFFSET(dest->layers[dest_i].data, size_t(dest_index) * typeInfo->size));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2006-12-12 21:29:09 +00:00
|
|
|
/* if there are multiple source & dest layers of the same type,
|
|
|
|
|
* we don't want to copy all source layers to the same dest, so
|
|
|
|
|
* increment dest_i
|
|
|
|
|
*/
|
2012-08-18 13:07:48 +00:00
|
|
|
dest_i++;
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (count > SOURCE_BUF_SIZE) {
|
2015-04-19 22:03:42 +10:00
|
|
|
MEM_freeN((void *)sources);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2021-12-25 14:28:22 -06:00
|
|
|
if (!ELEM(default_weights, nullptr, default_weights_buf)) {
|
2020-10-05 18:50:38 +02:00
|
|
|
MEM_freeN(default_weights);
|
|
|
|
|
}
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
void CustomData_swap_corners(CustomData *data, const int index, const int *corner_indices)
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
{
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2023-03-29 17:10:49 +02:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (typeInfo->swap) {
|
2022-09-25 18:33:28 +10:00
|
|
|
const size_t offset = size_t(index) * typeInfo->size;
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
|
2015-02-23 13:51:55 +11:00
|
|
|
typeInfo->swap(POINTER_OFFSET(data->layers[i].data, offset), corner_indices);
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
}
|
|
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
void *CustomData_get_for_write(CustomData *data,
|
|
|
|
|
const int index,
|
|
|
|
|
const eCustomDataType type,
|
|
|
|
|
int totelem)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2013-07-10 05:38:36 +00:00
|
|
|
BLI_assert(index >= 0);
|
2023-01-13 17:21:20 -06:00
|
|
|
void *layer_data = CustomData_get_layer_for_write(data, type, totelem);
|
2022-09-28 22:49:49 -05:00
|
|
|
if (!layer_data) {
|
2021-12-25 14:28:22 -06:00
|
|
|
return nullptr;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2022-09-28 22:49:49 -05:00
|
|
|
return POINTER_OFFSET(layer_data, size_t(index) * layerType_getInfo(type)->size);
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
|
|
|
|
|
2023-01-13 17:21:20 -06:00
|
|
|
void *CustomData_get_n_for_write(
|
2023-03-29 17:10:49 +02:00
|
|
|
CustomData *data, const eCustomDataType type, const int index, const int n, int totelem)
|
2009-05-16 16:18:08 +00:00
|
|
|
{
|
2022-09-28 22:49:49 -05:00
|
|
|
BLI_assert(index >= 0);
|
2023-01-13 17:21:20 -06:00
|
|
|
void *layer_data = CustomData_get_layer_n_for_write(data, type, n, totelem);
|
2022-09-28 22:49:49 -05:00
|
|
|
if (!layer_data) {
|
2021-12-25 14:28:22 -06:00
|
|
|
return nullptr;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-11-20 16:19:56 +00:00
|
|
|
|
2022-09-28 22:49:49 -05:00
|
|
|
return POINTER_OFFSET(layer_data, size_t(index) * layerType_getInfo(type)->size);
|
2009-05-16 16:18:08 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
const void *CustomData_get_layer(const CustomData *data, const eCustomDataType type)
|
2006-08-28 01:12:36 +00:00
|
|
|
{
|
2006-12-12 21:29:09 +00:00
|
|
|
int layer_index = CustomData_get_active_layer_index(data, type);
|
2019-04-22 09:39:35 +10:00
|
|
|
if (layer_index == -1) {
|
2021-12-25 14:28:22 -06:00
|
|
|
return nullptr;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
|
|
|
|
|
return data->layers[layer_index].data;
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
void *CustomData_get_layer_for_write(CustomData *data,
|
|
|
|
|
const eCustomDataType type,
|
|
|
|
|
const int totelem)
|
2023-01-13 17:21:20 -06:00
|
|
|
{
|
|
|
|
|
const int layer_index = CustomData_get_active_layer_index(data, type);
|
2023-04-13 14:57:57 +02:00
|
|
|
if (layer_index == -1) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
CustomDataLayer &layer = data->layers[layer_index];
|
|
|
|
|
ensure_layer_data_is_mutable(layer, totelem);
|
|
|
|
|
return layer.data;
|
2023-01-13 17:21:20 -06:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
const void *CustomData_get_layer_n(const CustomData *data, const eCustomDataType type, const int n)
|
2006-12-12 21:29:09 +00:00
|
|
|
{
|
2011-11-20 16:19:56 +00:00
|
|
|
int layer_index = CustomData_get_layer_index_n(data, type, n);
|
2019-04-22 09:39:35 +10:00
|
|
|
if (layer_index == -1) {
|
2021-12-25 14:28:22 -06:00
|
|
|
return nullptr;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-11-20 16:19:56 +00:00
|
|
|
return data->layers[layer_index].data;
|
2006-12-12 21:29:09 +00:00
|
|
|
}
|
|
|
|
|
|
2023-01-13 17:21:20 -06:00
|
|
|
void *CustomData_get_layer_n_for_write(CustomData *data,
|
2023-03-29 17:10:49 +02:00
|
|
|
const eCustomDataType type,
|
2023-01-13 17:21:20 -06:00
|
|
|
const int n,
|
|
|
|
|
const int totelem)
|
|
|
|
|
{
|
|
|
|
|
const int layer_index = CustomData_get_layer_index_n(data, type, n);
|
2023-04-13 14:57:57 +02:00
|
|
|
if (layer_index == -1) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
CustomDataLayer &layer = data->layers[layer_index];
|
|
|
|
|
ensure_layer_data_is_mutable(layer, totelem);
|
|
|
|
|
return layer.data;
|
2023-01-13 17:21:20 -06:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
const void *CustomData_get_layer_named(const CustomData *data,
|
|
|
|
|
const eCustomDataType type,
|
2024-02-08 16:56:42 +01:00
|
|
|
const StringRef name)
|
2007-01-29 15:10:55 +00:00
|
|
|
{
|
|
|
|
|
int layer_index = CustomData_get_named_layer_index(data, type, name);
|
2019-04-22 09:39:35 +10:00
|
|
|
if (layer_index == -1) {
|
2021-12-25 14:28:22 -06:00
|
|
|
return nullptr;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2007-01-29 15:10:55 +00:00
|
|
|
return data->layers[layer_index].data;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-13 17:21:20 -06:00
|
|
|
void *CustomData_get_layer_named_for_write(CustomData *data,
|
2023-03-29 17:10:49 +02:00
|
|
|
const eCustomDataType type,
|
2024-02-08 16:56:42 +01:00
|
|
|
const StringRef name,
|
2023-01-13 17:21:20 -06:00
|
|
|
const int totelem)
|
|
|
|
|
{
|
|
|
|
|
const int layer_index = CustomData_get_named_layer_index(data, type, name);
|
2023-04-13 14:57:57 +02:00
|
|
|
if (layer_index == -1) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
CustomDataLayer &layer = data->layers[layer_index];
|
|
|
|
|
ensure_layer_data_is_mutable(layer, totelem);
|
|
|
|
|
return layer.data;
|
2023-01-13 17:21:20 -06:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
int CustomData_get_offset(const CustomData *data, const eCustomDataType type)
|
2013-01-10 04:43:31 +00:00
|
|
|
{
|
2013-01-11 01:41:27 +00:00
|
|
|
int layer_index = CustomData_get_active_layer_index(data, type);
|
2019-04-22 09:39:35 +10:00
|
|
|
if (layer_index == -1) {
|
2014-02-01 01:45:09 +11:00
|
|
|
return -1;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-01-10 04:43:31 +00:00
|
|
|
return data->layers[layer_index].offset;
|
|
|
|
|
}
|
2011-05-10 17:01:26 +00:00
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
int CustomData_get_n_offset(const CustomData *data, const eCustomDataType type, const int n)
|
2013-01-10 12:07:01 +00:00
|
|
|
{
|
|
|
|
|
int layer_index = CustomData_get_layer_index_n(data, type, n);
|
2019-04-22 09:39:35 +10:00
|
|
|
if (layer_index == -1) {
|
2014-02-01 01:45:09 +11:00
|
|
|
return -1;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-01-10 12:07:01 +00:00
|
|
|
|
|
|
|
|
return data->layers[layer_index].offset;
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
int CustomData_get_offset_named(const CustomData *data,
|
|
|
|
|
const eCustomDataType type,
|
2024-02-08 16:56:42 +01:00
|
|
|
const StringRef name)
|
2013-01-10 12:07:01 +00:00
|
|
|
{
|
2022-08-04 13:48:41 -05:00
|
|
|
int layer_index = CustomData_get_named_layer_index(data, type, name);
|
2019-04-22 09:39:35 +10:00
|
|
|
if (layer_index == -1) {
|
2014-02-01 01:45:09 +11:00
|
|
|
return -1;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-01-10 12:07:01 +00:00
|
|
|
|
|
|
|
|
return data->layers[layer_index].offset;
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
bool CustomData_set_layer_name(CustomData *data,
|
|
|
|
|
const eCustomDataType type,
|
|
|
|
|
const int n,
|
2024-02-08 16:56:42 +01:00
|
|
|
const StringRef name)
|
2011-05-10 17:01:26 +00:00
|
|
|
{
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
const int layer_index = CustomData_get_layer_index_n(data, type, n);
|
2024-02-08 16:56:42 +01:00
|
|
|
if (layer_index == -1) {
|
2014-12-01 17:11:18 +01:00
|
|
|
return false;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2024-02-08 16:56:42 +01:00
|
|
|
name.copy(data->layers[layer_index].name);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-05-08 12:57:18 +00:00
|
|
|
return true;
|
2011-05-10 17:01:26 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
const char *CustomData_get_layer_name(const CustomData *data,
|
|
|
|
|
const eCustomDataType type,
|
|
|
|
|
const int n)
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
{
|
|
|
|
|
const int layer_index = CustomData_get_layer_index_n(data, type, n);
|
|
|
|
|
|
2021-12-25 14:28:22 -06:00
|
|
|
return (layer_index == -1) ? nullptr : data->layers[layer_index].name;
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
}
|
|
|
|
|
|
2012-08-17 14:43:20 +00:00
|
|
|
/* BMesh functions */
|
2021-12-07 17:19:15 +11:00
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
void CustomData_bmesh_init_pool(CustomData *data, const int totelem, const char htype)
|
2011-11-07 09:02:10 +00:00
|
|
|
{
|
2012-03-01 22:17:04 +00:00
|
|
|
int chunksize;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-10-26 13:24:58 +00:00
|
|
|
/* Dispose old pools before calling here to avoid leaks */
|
2021-12-25 14:28:22 -06:00
|
|
|
BLI_assert(data->pool == nullptr);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-01 22:17:04 +00:00
|
|
|
switch (htype) {
|
2012-03-01 23:59:34 +00:00
|
|
|
case BM_VERT:
|
|
|
|
|
chunksize = bm_mesh_chunksize_default.totvert;
|
|
|
|
|
break;
|
|
|
|
|
case BM_EDGE:
|
|
|
|
|
chunksize = bm_mesh_chunksize_default.totedge;
|
|
|
|
|
break;
|
|
|
|
|
case BM_LOOP:
|
|
|
|
|
chunksize = bm_mesh_chunksize_default.totloop;
|
|
|
|
|
break;
|
|
|
|
|
case BM_FACE:
|
|
|
|
|
chunksize = bm_mesh_chunksize_default.totface;
|
2019-04-17 06:17:24 +02:00
|
|
|
break;
|
2012-03-01 22:17:04 +00:00
|
|
|
default:
|
2022-05-17 15:08:18 +02:00
|
|
|
BLI_assert_unreachable();
|
2012-03-01 22:17:04 +00:00
|
|
|
chunksize = 512;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-10-26 13:24:58 +00:00
|
|
|
/* If there are no layers, no pool is needed just yet */
|
|
|
|
|
if (data->totlayer) {
|
2014-04-05 10:57:32 +11:00
|
|
|
data->pool = BLI_mempool_create(data->totsize, totelem, chunksize, BLI_MEMPOOL_NOP);
|
2008-07-08 02:22:37 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2023-04-13 14:57:57 +02:00
|
|
|
bool CustomData_bmesh_merge_layout(const CustomData *source,
|
|
|
|
|
CustomData *dest,
|
|
|
|
|
eCustomDataMask mask,
|
|
|
|
|
eCDAllocType alloctype,
|
|
|
|
|
BMesh *bm,
|
|
|
|
|
const char htype)
|
2009-06-23 05:35:49 +00:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-05-09 10:41:05 +00:00
|
|
|
if (CustomData_number_of_layers_typemask(source, mask) == 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-04-09 02:14:55 +00:00
|
|
|
/* copy old layer description so that old data can be copied into
|
2012-04-22 11:54:53 +00:00
|
|
|
* the new allocation */
|
2020-09-09 15:43:09 +02:00
|
|
|
CustomData destold = *dest;
|
2013-01-07 15:35:20 +00:00
|
|
|
if (destold.layers) {
|
2021-12-25 14:28:22 -06:00
|
|
|
destold.layers = static_cast<CustomDataLayer *>(MEM_dupallocN(destold.layers));
|
2013-01-07 15:35:20 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-04-13 14:57:57 +02:00
|
|
|
if (CustomData_merge_layout(source, dest, mask, alloctype, 0) == false) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (destold.layers) {
|
2013-05-09 10:41:05 +00:00
|
|
|
MEM_freeN(destold.layers);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-05-09 10:41:05 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-12-09 05:37:37 +01:00
|
|
|
const BMCustomDataCopyMap map = CustomData_bmesh_copy_map_calc(destold, *dest);
|
|
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
int iter_type;
|
|
|
|
|
int totelem;
|
2012-03-01 22:17:04 +00:00
|
|
|
switch (htype) {
|
2009-06-23 05:35:49 +00:00
|
|
|
case BM_VERT:
|
2013-01-07 15:35:20 +00:00
|
|
|
iter_type = BM_VERTS_OF_MESH;
|
|
|
|
|
totelem = bm->totvert;
|
|
|
|
|
break;
|
2009-06-23 05:35:49 +00:00
|
|
|
case BM_EDGE:
|
2013-01-07 15:35:20 +00:00
|
|
|
iter_type = BM_EDGES_OF_MESH;
|
|
|
|
|
totelem = bm->totedge;
|
|
|
|
|
break;
|
2009-06-23 05:35:49 +00:00
|
|
|
case BM_LOOP:
|
2013-01-07 15:35:20 +00:00
|
|
|
iter_type = BM_LOOPS_OF_FACE;
|
|
|
|
|
totelem = bm->totloop;
|
|
|
|
|
break;
|
2009-06-23 05:35:49 +00:00
|
|
|
case BM_FACE:
|
2013-01-07 15:35:20 +00:00
|
|
|
iter_type = BM_FACES_OF_MESH;
|
|
|
|
|
totelem = bm->totface;
|
|
|
|
|
break;
|
2011-05-10 23:48:09 +00:00
|
|
|
default: /* should never happen */
|
2021-07-15 18:23:28 +10:00
|
|
|
BLI_assert_msg(0, "invalid type given");
|
2013-01-07 15:35:20 +00:00
|
|
|
iter_type = BM_VERTS_OF_MESH;
|
2013-01-11 03:21:24 +00:00
|
|
|
totelem = bm->totvert;
|
2013-07-21 08:16:37 +00:00
|
|
|
break;
|
2009-06-23 05:35:49 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-12-25 14:28:22 -06:00
|
|
|
dest->pool = nullptr;
|
2013-01-07 15:35:20 +00:00
|
|
|
CustomData_bmesh_init_pool(dest, totelem, htype);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-01-07 15:35:20 +00:00
|
|
|
if (iter_type != BM_LOOPS_OF_FACE) {
|
2020-09-09 15:43:09 +02:00
|
|
|
BMHeader *h;
|
|
|
|
|
BMIter iter;
|
2021-06-26 21:35:18 +10:00
|
|
|
/* Ensure all current elements follow new customdata layout. */
|
2013-01-07 15:35:20 +00:00
|
|
|
BM_ITER_MESH (h, &iter, bm, iter_type) {
|
2021-12-25 14:28:22 -06:00
|
|
|
void *tmp = nullptr;
|
2023-12-09 05:37:37 +01:00
|
|
|
CustomData_bmesh_copy_block(*dest, map, h->data, &tmp);
|
2009-06-23 05:35:49 +00:00
|
|
|
CustomData_bmesh_free_block(&destold, &h->data);
|
|
|
|
|
h->data = tmp;
|
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2009-06-23 05:35:49 +00:00
|
|
|
BMFace *f;
|
|
|
|
|
BMLoop *l;
|
2020-09-09 15:43:09 +02:00
|
|
|
BMIter iter;
|
2009-06-23 05:35:49 +00:00
|
|
|
BMIter liter;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-06-26 21:35:18 +10:00
|
|
|
/* Ensure all current elements follow new customdata layout. */
|
2012-04-19 13:47:58 +00:00
|
|
|
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
|
|
|
|
|
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
|
2021-12-25 14:28:22 -06:00
|
|
|
void *tmp = nullptr;
|
2023-12-09 05:37:37 +01:00
|
|
|
CustomData_bmesh_copy_block(*dest, map, l->head.data, &tmp);
|
2009-08-12 03:51:28 +00:00
|
|
|
CustomData_bmesh_free_block(&destold, &l->head.data);
|
|
|
|
|
l->head.data = tmp;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2009-06-23 05:35:49 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (destold.pool) {
|
2009-06-23 05:35:49 +00:00
|
|
|
BLI_mempool_destroy(destold.pool);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (destold.layers) {
|
2012-04-09 02:14:55 +00:00
|
|
|
MEM_freeN(destold.layers);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-05-09 10:41:05 +00:00
|
|
|
return true;
|
2009-06-23 05:35:49 +00:00
|
|
|
}
|
|
|
|
|
|
2008-07-04 17:59:16 +00:00
|
|
|
void CustomData_bmesh_free_block(CustomData *data, void **block)
|
|
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
if (*block == nullptr) {
|
2012-10-10 23:44:07 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2012-10-10 23:44:07 +00:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2023-04-13 14:57:57 +02:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
|
2008-07-04 17:59:16 +00:00
|
|
|
|
2023-04-13 14:57:57 +02:00
|
|
|
if (typeInfo->free) {
|
|
|
|
|
int offset = data->layers[i].offset;
|
2023-12-05 17:41:48 -05:00
|
|
|
typeInfo->free(POINTER_OFFSET(*block, offset), 1);
|
2010-03-22 09:30:00 +00:00
|
|
|
}
|
|
|
|
|
}
|
2008-07-04 17:59:16 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (data->totsize) {
|
2010-07-14 22:06:10 +00:00
|
|
|
BLI_mempool_free(data->pool, *block);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2010-07-14 22:06:10 +00:00
|
|
|
|
2021-12-25 14:28:22 -06:00
|
|
|
*block = nullptr;
|
2008-07-04 17:59:16 +00:00
|
|
|
}
|
|
|
|
|
|
2014-09-24 18:50:29 +10:00
|
|
|
void CustomData_bmesh_free_block_data(CustomData *data, void *block)
|
2013-05-08 13:00:25 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
if (block == nullptr) {
|
2013-05-08 13:00:25 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-11-26 16:19:56 +11:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2023-04-13 14:57:57 +02:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
|
|
|
|
|
if (typeInfo->free) {
|
|
|
|
|
const size_t offset = data->layers[i].offset;
|
2023-12-05 17:41:48 -05:00
|
|
|
typeInfo->free(POINTER_OFFSET(block, offset), 1);
|
2013-05-08 13:00:25 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-22 09:39:35 +10:00
|
|
|
if (data->totsize) {
|
2014-09-24 18:50:29 +10:00
|
|
|
memset(block, 0, data->totsize);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-05-08 13:00:25 +00:00
|
|
|
}
|
|
|
|
|
|
2023-02-13 20:52:02 +01:00
|
|
|
void CustomData_bmesh_alloc_block(CustomData *data, void **block)
|
2008-07-04 17:59:16 +00:00
|
|
|
{
|
2019-04-22 09:39:35 +10:00
|
|
|
if (*block) {
|
2008-07-04 17:59:16 +00:00
|
|
|
CustomData_bmesh_free_block(data, block);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2008-07-04 17:59:16 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (data->totsize > 0) {
|
2010-07-14 22:06:10 +00:00
|
|
|
*block = BLI_mempool_alloc(data->pool);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2021-12-25 14:28:22 -06:00
|
|
|
*block = nullptr;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2008-07-04 17:59:16 +00:00
|
|
|
}
|
|
|
|
|
|
2019-11-26 16:19:56 +11:00
|
|
|
void CustomData_bmesh_free_block_data_exclude_by_type(CustomData *data,
|
|
|
|
|
void *block,
|
2022-06-01 14:38:06 +10:00
|
|
|
const eCustomDataMask mask_exclude)
|
2019-11-26 16:19:56 +11:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
if (block == nullptr) {
|
2019-11-26 16:19:56 +11:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
|
|
|
|
if ((CD_TYPE_AS_MASK(data->layers[i].type) & mask_exclude) == 0) {
|
2023-03-29 17:10:49 +02:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
|
2019-11-26 16:19:56 +11:00
|
|
|
const size_t offset = data->layers[i].offset;
|
2023-04-13 14:57:57 +02:00
|
|
|
if (typeInfo->free) {
|
2023-12-05 17:41:48 -05:00
|
|
|
typeInfo->free(POINTER_OFFSET(block, offset), 1);
|
2019-11-26 16:19:56 +11:00
|
|
|
}
|
|
|
|
|
memset(POINTER_OFFSET(block, offset), 0, typeInfo->size);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
void CustomData_data_set_default_value(const eCustomDataType type, void *elem)
|
2019-06-17 19:05:41 +02:00
|
|
|
{
|
2023-02-13 20:52:02 +01:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
if (typeInfo->set_default_value) {
|
2023-02-13 20:52:02 +01:00
|
|
|
typeInfo->set_default_value(elem, 1);
|
2019-06-17 19:05:41 +02:00
|
|
|
}
|
|
|
|
|
else {
|
2023-02-13 20:52:02 +01:00
|
|
|
memset(elem, 0, typeInfo->size);
|
2019-06-17 19:05:41 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-13 20:52:02 +01:00
|
|
|
static void CustomData_bmesh_set_default_n(CustomData *data, void **block, const int n)
|
|
|
|
|
{
|
|
|
|
|
const int offset = data->layers[n].offset;
|
2023-03-29 17:10:49 +02:00
|
|
|
CustomData_data_set_default_value(eCustomDataType(data->layers[n].type),
|
|
|
|
|
POINTER_OFFSET(*block, offset));
|
2023-02-13 20:52:02 +01:00
|
|
|
}
|
|
|
|
|
|
2019-06-17 19:05:41 +02:00
|
|
|
void CustomData_bmesh_set_default(CustomData *data, void **block)
|
|
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
if (*block == nullptr) {
|
2019-06-17 19:05:41 +02:00
|
|
|
CustomData_bmesh_alloc_block(data, block);
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2019-06-17 19:05:41 +02:00
|
|
|
CustomData_bmesh_set_default_n(data, block, i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-09 05:37:37 +01:00
|
|
|
BMCustomDataCopyMap CustomData_bmesh_copy_map_calc(const CustomData &src,
|
|
|
|
|
const CustomData &dst,
|
|
|
|
|
const eCustomDataMask mask_exclude)
|
2023-07-14 17:12:49 +02:00
|
|
|
{
|
2023-12-09 05:37:37 +01:00
|
|
|
BMCustomDataCopyMap map;
|
|
|
|
|
for (const CustomDataLayer &layer_dst : Span(dst.layers, dst.totlayer)) {
|
|
|
|
|
const int dst_offset = layer_dst.offset;
|
|
|
|
|
const eCustomDataType dst_type = eCustomDataType(layer_dst.type);
|
|
|
|
|
const LayerTypeInfo &type_info = *layerType_getInfo(dst_type);
|
2023-07-14 17:12:49 +02:00
|
|
|
|
2023-12-09 05:37:37 +01:00
|
|
|
const int src_offset = CustomData_get_offset_named(&src, dst_type, layer_dst.name);
|
|
|
|
|
if (src_offset == -1 || CD_TYPE_AS_MASK(dst_type) & mask_exclude) {
|
|
|
|
|
if (type_info.set_default_value) {
|
|
|
|
|
map.defaults.append({type_info.set_default_value, dst_offset});
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2023-12-09 05:37:37 +01:00
|
|
|
else {
|
|
|
|
|
map.trivial_defaults.append({type_info.size, dst_offset});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (type_info.copy) {
|
|
|
|
|
map.copies.append({type_info.copy, src_offset, dst_offset});
|
2023-07-14 17:12:49 +02:00
|
|
|
}
|
|
|
|
|
else {
|
2023-12-09 05:37:37 +01:00
|
|
|
/* NOTE: A way to improve performance of copies (by reducing the number of `memcpy`
|
|
|
|
|
* calls) would be combining contiguous in the source and result format. */
|
|
|
|
|
map.trivial_copies.append({type_info.size, src_offset, dst_offset});
|
2023-07-14 17:12:49 +02:00
|
|
|
}
|
2008-07-04 17:59:16 +00:00
|
|
|
}
|
2019-06-17 19:05:41 +02:00
|
|
|
|
2023-12-09 05:37:37 +01:00
|
|
|
if (type_info.free) {
|
|
|
|
|
map.free.append({type_info.free, dst_offset});
|
2023-07-14 17:12:49 +02:00
|
|
|
}
|
2019-06-17 19:05:41 +02:00
|
|
|
}
|
2023-12-09 05:37:37 +01:00
|
|
|
return map;
|
2008-07-04 17:59:16 +00:00
|
|
|
}
|
|
|
|
|
|
2023-12-09 05:37:37 +01:00
|
|
|
void CustomData_bmesh_copy_block(CustomData &dst_data,
|
|
|
|
|
const BMCustomDataCopyMap ©_map,
|
|
|
|
|
const void *src_block,
|
|
|
|
|
void **dst_block)
|
2019-11-26 16:19:56 +11:00
|
|
|
{
|
2023-12-09 05:37:37 +01:00
|
|
|
if (*dst_block) {
|
|
|
|
|
for (const BMCustomDataCopyMap::Free &info : copy_map.free) {
|
|
|
|
|
info.fn(POINTER_OFFSET(*dst_block, info.dst_offset), 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (dst_data.totsize == 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
*dst_block = BLI_mempool_alloc(dst_data.pool);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const BMCustomDataCopyMap::TrivialCopy &info : copy_map.trivial_copies) {
|
|
|
|
|
memcpy(POINTER_OFFSET(*dst_block, info.dst_offset),
|
|
|
|
|
POINTER_OFFSET(src_block, info.src_offset),
|
|
|
|
|
info.size);
|
|
|
|
|
}
|
|
|
|
|
for (const BMCustomDataCopyMap::Copy &info : copy_map.copies) {
|
|
|
|
|
info.fn(POINTER_OFFSET(src_block, info.src_offset),
|
|
|
|
|
POINTER_OFFSET(*dst_block, info.dst_offset),
|
|
|
|
|
1);
|
|
|
|
|
}
|
|
|
|
|
for (const BMCustomDataCopyMap::TrivialDefault &info : copy_map.trivial_defaults) {
|
|
|
|
|
memset(POINTER_OFFSET(*dst_block, info.dst_offset), 0, info.size);
|
|
|
|
|
}
|
|
|
|
|
for (const BMCustomDataCopyMap::Default &info : copy_map.defaults) {
|
|
|
|
|
info.fn(POINTER_OFFSET(*dst_block, info.dst_offset), 1);
|
|
|
|
|
}
|
2019-11-26 16:19:56 +11:00
|
|
|
}
|
|
|
|
|
|
BMesh: Improve performance when copying attributes in same mesh
When the BMesh source and result arguments are the same, restore
performance lost by 9175d9b7c27b191ea94a, which made copying layers
have quadratic time complexity. When we know the custom data format
is the same between the source and result, the copying can be much
simpler, so it's worth specializing this case. There is still more
to be done, because often we only know that the two meshes are the
same at runtime. A followup commit will add that check.
The quadratic runtime means performance is fine for low layer counts,
and terrible with higher layer counts. For example, in my testing with
47 boolean attributes, copying 250k vertices went from 2.3 seconds to
316 ms.
The implementation uses a new CustomData function that copies an entire
BMesh custom data block, called by a function in the BMesh module
overloaded for every BMesh element type. That handles the extra data
like flags, normals, and material indices.
Related to #115776
2023-12-05 20:26:28 -05:00
|
|
|
void CustomData_bmesh_copy_block(CustomData &data, void *src_block, void **dst_block)
|
|
|
|
|
{
|
|
|
|
|
if (*dst_block) {
|
|
|
|
|
for (const CustomDataLayer &layer : Span(data.layers, data.totlayer)) {
|
|
|
|
|
const LayerTypeInfo &info = *layerType_getInfo(eCustomDataType(layer.type));
|
|
|
|
|
if (info.free) {
|
|
|
|
|
info.free(POINTER_OFFSET(*dst_block, layer.offset), 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (data.totsize == 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
*dst_block = BLI_mempool_alloc(data.pool);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const CustomDataLayer &layer : Span(data.layers, data.totlayer)) {
|
|
|
|
|
const int offset = layer.offset;
|
|
|
|
|
const LayerTypeInfo &info = *layerType_getInfo(eCustomDataType(layer.type));
|
|
|
|
|
if (info.copy) {
|
|
|
|
|
info.copy(POINTER_OFFSET(src_block, offset), POINTER_OFFSET(*dst_block, offset), 1);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
memcpy(POINTER_OFFSET(*dst_block, offset), POINTER_OFFSET(src_block, offset), info.size);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
void *CustomData_bmesh_get(const CustomData *data, void *block, const eCustomDataType type)
|
2008-07-04 17:59:16 +00:00
|
|
|
{
|
2020-09-09 15:43:09 +02:00
|
|
|
int layer_index = CustomData_get_active_layer_index(data, type);
|
2019-04-22 09:39:35 +10:00
|
|
|
if (layer_index == -1) {
|
2021-12-25 14:28:22 -06:00
|
|
|
return nullptr;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2008-07-04 17:59:16 +00:00
|
|
|
|
2015-02-23 13:51:55 +11:00
|
|
|
return POINTER_OFFSET(block, data->layers[layer_index].offset);
|
2008-07-04 17:59:16 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
void *CustomData_bmesh_get_n(const CustomData *data,
|
|
|
|
|
void *block,
|
|
|
|
|
const eCustomDataType type,
|
|
|
|
|
const int n)
|
2008-07-04 17:59:16 +00:00
|
|
|
{
|
2020-09-09 15:43:09 +02:00
|
|
|
int layer_index = CustomData_get_layer_index(data, type);
|
2019-04-22 09:39:35 +10:00
|
|
|
if (layer_index == -1) {
|
2021-12-25 14:28:22 -06:00
|
|
|
return nullptr;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2008-07-04 17:59:16 +00:00
|
|
|
|
2015-02-23 13:51:55 +11:00
|
|
|
return POINTER_OFFSET(block, data->layers[layer_index + n].offset);
|
2008-07-04 17:59:16 +00:00
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
void *CustomData_bmesh_get_layer_n(const CustomData *data, void *block, const int n)
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
{
|
2019-04-22 09:39:35 +10:00
|
|
|
if (n < 0 || n >= data->totlayer) {
|
2021-12-25 14:28:22 -06:00
|
|
|
return nullptr;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
|
2015-02-23 13:51:55 +11:00
|
|
|
return POINTER_OFFSET(block, data->layers[n].offset);
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
bool CustomData_layer_has_math(const CustomData *data, const int layer_n)
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
{
|
2023-03-29 17:10:49 +02:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[layer_n].type));
|
2018-06-17 17:05:51 +02:00
|
|
|
|
|
|
|
|
if (typeInfo->equal && typeInfo->add && typeInfo->multiply && typeInfo->initminmax &&
|
2012-04-28 06:31:57 +00:00
|
|
|
typeInfo->dominmax)
|
|
|
|
|
{
|
2013-05-08 12:57:18 +00:00
|
|
|
return true;
|
2012-04-28 06:31:57 +00:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-05-08 12:57:18 +00:00
|
|
|
return false;
|
2012-10-20 17:31:07 +00:00
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
bool CustomData_layer_has_interp(const CustomData *data, const int layer_n)
|
2012-10-20 17:39:56 +00:00
|
|
|
{
|
2023-03-29 17:10:49 +02:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[layer_n].type));
|
2012-10-20 17:39:56 +00:00
|
|
|
|
|
|
|
|
if (typeInfo->interp) {
|
2013-05-08 12:57:18 +00:00
|
|
|
return true;
|
2012-10-20 17:39:56 +00:00
|
|
|
}
|
|
|
|
|
|
2013-05-08 12:57:18 +00:00
|
|
|
return false;
|
2012-10-20 17:39:56 +00:00
|
|
|
}
|
|
|
|
|
|
2022-06-04 13:31:30 +02:00
|
|
|
bool CustomData_has_math(const CustomData *data)
|
2012-10-20 17:31:07 +00:00
|
|
|
{
|
|
|
|
|
/* interpolates a layer at a time */
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2012-10-20 17:31:07 +00:00
|
|
|
if (CustomData_layer_has_math(data, i)) {
|
2013-05-08 12:57:18 +00:00
|
|
|
return true;
|
2012-10-20 17:31:07 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-08 12:57:18 +00:00
|
|
|
return false;
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
}
|
|
|
|
|
|
2022-06-04 13:31:30 +02:00
|
|
|
bool CustomData_bmesh_has_free(const CustomData *data)
|
2013-05-08 12:59:56 +00:00
|
|
|
{
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2023-04-13 14:57:57 +02:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
|
|
|
|
|
if (typeInfo->free) {
|
|
|
|
|
return true;
|
2013-05-08 12:59:56 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-04 13:31:30 +02:00
|
|
|
bool CustomData_has_interp(const CustomData *data)
|
2012-10-20 17:39:56 +00:00
|
|
|
{
|
|
|
|
|
/* interpolates a layer at a time */
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2012-10-20 17:39:56 +00:00
|
|
|
if (CustomData_layer_has_interp(data, i)) {
|
2013-05-08 12:57:18 +00:00
|
|
|
return true;
|
2012-10-20 17:39:56 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-08 12:57:18 +00:00
|
|
|
return false;
|
2012-10-20 17:39:56 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
void CustomData_data_copy_value(const eCustomDataType type, const void *source, void *dest)
|
2009-08-12 03:51:28 +00:00
|
|
|
{
|
|
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
|
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!dest) {
|
2012-03-24 06:18:31 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2009-08-12 03:51:28 +00:00
|
|
|
|
2023-02-13 20:52:02 +01:00
|
|
|
if (typeInfo->copy) {
|
|
|
|
|
typeInfo->copy(source, dest, 1);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2009-08-12 03:51:28 +00:00
|
|
|
memcpy(dest, source, typeInfo->size);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2009-08-12 03:51:28 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
void CustomData_data_mix_value(const eCustomDataType type,
|
|
|
|
|
const void *source,
|
|
|
|
|
void *dest,
|
|
|
|
|
const int mixmode,
|
|
|
|
|
const float mixfactor)
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
{
|
|
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
|
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!dest) {
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
|
|
|
|
|
if (typeInfo->copyvalue) {
|
|
|
|
|
typeInfo->copyvalue(source, dest, mixmode, mixfactor);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* Mere copy if no advanced interpolation is supported. */
|
|
|
|
|
memcpy(dest, source, typeInfo->size);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
bool CustomData_data_equals(const eCustomDataType type, const void *data1, const void *data2)
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
{
|
|
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
|
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (typeInfo->equal) {
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
return typeInfo->equal(data1, data2);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
|
|
|
|
|
return !memcmp(data1, data2, typeInfo->size);
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
void CustomData_data_initminmax(const eCustomDataType type, void *min, void *max)
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
{
|
|
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
|
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (typeInfo->initminmax) {
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
typeInfo->initminmax(min, max);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
void CustomData_data_dominmax(const eCustomDataType type, const void *data, void *min, void *max)
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
{
|
|
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
|
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (typeInfo->dominmax) {
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
typeInfo->dominmax(data, min, max);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
void CustomData_data_multiply(const eCustomDataType type, void *data, const float fac)
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
{
|
|
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
|
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (typeInfo->multiply) {
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
typeInfo->multiply(data, fac);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
void CustomData_data_add(const eCustomDataType type, void *data1, const void *data2)
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
{
|
|
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
|
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (typeInfo->add) {
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
typeInfo->add(data1, data2);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
void CustomData_bmesh_set_n(
|
2023-03-29 17:10:49 +02:00
|
|
|
CustomData *data, void *block, const eCustomDataType type, const int n, const void *source)
|
2008-07-04 17:59:16 +00:00
|
|
|
{
|
|
|
|
|
void *dest = CustomData_bmesh_get_n(data, block, type, n);
|
|
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
|
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!dest) {
|
2012-03-24 06:18:31 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2008-07-04 17:59:16 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (typeInfo->copy) {
|
2008-07-04 17:59:16 +00:00
|
|
|
typeInfo->copy(source, dest, 1);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2008-07-04 17:59:16 +00:00
|
|
|
memcpy(dest, source, typeInfo->size);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2008-07-04 17:59:16 +00:00
|
|
|
}
|
|
|
|
|
|
2015-02-23 13:51:55 +11:00
|
|
|
void CustomData_bmesh_interp_n(CustomData *data,
|
2015-02-23 13:43:09 +11:00
|
|
|
const void **src_blocks_ofs,
|
2015-02-23 13:51:55 +11:00
|
|
|
const float *weights,
|
|
|
|
|
const float *sub_weights,
|
2015-02-23 13:43:09 +11:00
|
|
|
int count,
|
|
|
|
|
void *dst_block_ofs,
|
|
|
|
|
int n)
|
2013-01-08 16:39:36 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
BLI_assert(weights != nullptr);
|
2020-10-05 18:50:38 +02:00
|
|
|
BLI_assert(count > 0);
|
|
|
|
|
|
2013-01-08 16:39:36 +00:00
|
|
|
CustomDataLayer *layer = &data->layers[n];
|
2023-03-29 17:10:49 +02:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-02-23 13:43:09 +11:00
|
|
|
typeInfo->interp(src_blocks_ofs, weights, sub_weights, count, dst_block_ofs);
|
2013-01-08 16:39:36 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-02-23 13:51:55 +11:00
|
|
|
void CustomData_bmesh_interp(CustomData *data,
|
|
|
|
|
const void **src_blocks,
|
|
|
|
|
const float *weights,
|
|
|
|
|
const float *sub_weights,
|
2015-02-23 13:43:09 +11:00
|
|
|
int count,
|
|
|
|
|
void *dst_block)
|
2008-07-04 17:59:16 +00:00
|
|
|
{
|
2020-10-05 18:50:38 +02:00
|
|
|
if (count <= 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-04 17:59:16 +00:00
|
|
|
void *source_buf[SOURCE_BUF_SIZE];
|
2015-02-23 13:51:55 +11:00
|
|
|
const void **sources = (const void **)source_buf;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-17 00:54:22 +10:00
|
|
|
/* Slow fallback in case we're interpolating a ridiculous number of elements. */
|
2019-04-22 09:39:35 +10:00
|
|
|
if (count > SOURCE_BUF_SIZE) {
|
2021-12-25 14:28:22 -06:00
|
|
|
sources = (const void **)MEM_malloc_arrayN(count, sizeof(*sources), __func__);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-10-05 18:50:38 +02:00
|
|
|
/* If no weights are given, generate default ones to produce an average result. */
|
|
|
|
|
float default_weights_buf[SOURCE_BUF_SIZE];
|
2021-12-25 14:28:22 -06:00
|
|
|
float *default_weights = nullptr;
|
|
|
|
|
if (weights == nullptr) {
|
2020-10-05 18:50:38 +02:00
|
|
|
default_weights = (count > SOURCE_BUF_SIZE) ?
|
2022-09-25 20:27:46 +10:00
|
|
|
(float *)MEM_mallocN(sizeof(*weights) * size_t(count), __func__) :
|
2020-10-05 18:50:38 +02:00
|
|
|
default_weights_buf;
|
|
|
|
|
copy_vn_fl(default_weights, count, 1.0f / count);
|
|
|
|
|
weights = default_weights;
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-04 17:59:16 +00:00
|
|
|
/* interpolates a layer at a time */
|
2021-01-26 09:21:42 -06:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2008-07-04 17:59:16 +00:00
|
|
|
CustomDataLayer *layer = &data->layers[i];
|
2023-03-29 17:10:49 +02:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
|
2012-03-24 06:18:31 +00:00
|
|
|
if (typeInfo->interp) {
|
2021-01-26 09:21:42 -06:00
|
|
|
for (int j = 0; j < count; j++) {
|
2015-02-23 13:51:55 +11:00
|
|
|
sources[j] = POINTER_OFFSET(src_blocks[j], layer->offset);
|
2012-08-23 17:16:11 +00:00
|
|
|
}
|
2015-02-23 13:43:09 +11:00
|
|
|
CustomData_bmesh_interp_n(
|
|
|
|
|
data, sources, weights, sub_weights, count, POINTER_OFFSET(dst_block, layer->offset), i);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2008-07-04 17:59:16 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (count > SOURCE_BUF_SIZE) {
|
2015-02-23 13:51:55 +11:00
|
|
|
MEM_freeN((void *)sources);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2021-12-25 14:28:22 -06:00
|
|
|
if (!ELEM(default_weights, nullptr, default_weights_buf)) {
|
2020-10-05 18:50:38 +02:00
|
|
|
MEM_freeN(default_weights);
|
|
|
|
|
}
|
2008-07-04 17:59:16 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
void CustomData_file_write_info(const eCustomDataType type,
|
|
|
|
|
const char **r_struct_name,
|
|
|
|
|
int *r_struct_num)
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
{
|
2006-12-12 21:29:09 +00:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
|
2016-05-17 03:07:40 +10:00
|
|
|
*r_struct_name = typeInfo->structname;
|
|
|
|
|
*r_struct_num = typeInfo->structnum;
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
}
|
|
|
|
|
|
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
2022-08-11 12:54:24 -04:00
|
|
|
void CustomData_blend_write_prepare(CustomData &data,
|
|
|
|
|
Vector<CustomDataLayer, 16> &layers_to_write,
|
2022-08-23 13:50:47 -04:00
|
|
|
const Set<std::string> &skip_names)
|
2015-07-21 12:02:11 +02:00
|
|
|
{
|
2022-05-29 11:02:10 +02:00
|
|
|
for (const CustomDataLayer &layer : Span(data.layers, data.totlayer)) {
|
|
|
|
|
if (layer.flag & CD_FLAG_NOCOPY) {
|
|
|
|
|
continue;
|
2015-07-21 12:02:11 +02:00
|
|
|
}
|
2022-05-29 11:02:10 +02:00
|
|
|
if (layer.anonymous_id != nullptr) {
|
|
|
|
|
continue;
|
2015-07-21 12:02:11 +02:00
|
|
|
}
|
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
2022-08-11 12:54:24 -04:00
|
|
|
if (skip_names.contains(layer.name)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2022-05-29 11:02:10 +02:00
|
|
|
layers_to_write.append(layer);
|
2015-07-21 12:02:11 +02:00
|
|
|
}
|
2022-05-29 11:02:10 +02:00
|
|
|
data.totlayer = layers_to_write.size();
|
|
|
|
|
data.maxlayer = data.totlayer;
|
2023-04-07 02:02:20 +02:00
|
|
|
|
2023-07-20 09:40:32 +10:00
|
|
|
/* NOTE: `data->layers` may be null, this happens when adding
|
|
|
|
|
* a legacy #MPoly struct to a mesh with no other face attributes.
|
2023-04-07 02:02:20 +02:00
|
|
|
* This leaves us with no unique ID for DNA to identify the old
|
2023-07-20 09:40:32 +10:00
|
|
|
* data with when loading the file. */
|
2023-04-07 02:02:20 +02:00
|
|
|
if (!data.layers && layers_to_write.size() > 0) {
|
|
|
|
|
/* We just need an address that's unique. */
|
|
|
|
|
data.layers = reinterpret_cast<CustomDataLayer *>(&data.layers);
|
|
|
|
|
}
|
2015-07-21 12:02:11 +02:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
int CustomData_sizeof(const eCustomDataType type)
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
{
|
2006-12-12 21:29:09 +00:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
|
2006-12-12 21:29:09 +00:00
|
|
|
return typeInfo->size;
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
}
|
2006-12-05 17:42:03 +00:00
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
const char *CustomData_layertype_name(const eCustomDataType type)
|
2006-12-05 17:42:03 +00:00
|
|
|
{
|
|
|
|
|
return layerType_getName(type);
|
|
|
|
|
}
|
2006-12-21 13:47:27 +00:00
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
bool CustomData_layertype_is_singleton(const eCustomDataType type)
|
2012-04-30 18:54:14 +00:00
|
|
|
{
|
|
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
2021-12-25 14:28:22 -06:00
|
|
|
return typeInfo->defaultname == nullptr;
|
2012-04-30 18:54:14 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
bool CustomData_layertype_is_dynamic(const eCustomDataType type)
|
2021-02-12 00:09:48 +11:00
|
|
|
{
|
|
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
|
|
|
|
|
2021-12-25 14:28:22 -06:00
|
|
|
return (typeInfo->free != nullptr);
|
2021-02-12 00:09:48 +11:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
int CustomData_layertype_layers_max(const eCustomDataType type)
|
2014-10-21 17:01:56 +02:00
|
|
|
{
|
|
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
|
|
|
|
|
|
|
|
|
/* Same test as for singleton above. */
|
2021-12-25 14:28:22 -06:00
|
|
|
if (typeInfo->defaultname == nullptr) {
|
2014-10-21 17:01:56 +02:00
|
|
|
return 1;
|
|
|
|
|
}
|
2021-12-25 14:28:22 -06:00
|
|
|
if (typeInfo->layers_max == nullptr) {
|
2014-10-21 17:01:56 +02:00
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return typeInfo->layers_max();
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
static bool cd_layer_find_dupe(CustomData *data,
|
2024-02-08 16:56:42 +01:00
|
|
|
const StringRef name,
|
2023-03-29 17:10:49 +02:00
|
|
|
const eCustomDataType type,
|
|
|
|
|
const int index)
|
2006-12-21 13:47:27 +00:00
|
|
|
{
|
|
|
|
|
/* see if there is a duplicate */
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (i != index) {
|
2012-05-12 16:11:34 +00:00
|
|
|
CustomDataLayer *layer = &data->layers[i];
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2020-07-03 15:30:04 +02:00
|
|
|
if (CD_TYPE_AS_MASK(type) & CD_MASK_PROP_ALL) {
|
2024-02-08 16:56:42 +01:00
|
|
|
if ((CD_TYPE_AS_MASK(layer->type) & CD_MASK_PROP_ALL) && layer->name == name) {
|
2013-03-04 19:27:51 +00:00
|
|
|
return true;
|
2010-11-01 07:19:41 +00:00
|
|
|
}
|
2007-06-04 19:18:19 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else {
|
2024-02-08 16:56:42 +01:00
|
|
|
if (i != index && layer->type == type && layer->name == name) {
|
2013-03-04 19:27:51 +00:00
|
|
|
return true;
|
2010-11-01 07:19:41 +00:00
|
|
|
}
|
2007-06-04 19:18:19 +00:00
|
|
|
}
|
2006-12-21 13:47:27 +00:00
|
|
|
}
|
|
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-03-04 19:27:51 +00:00
|
|
|
return false;
|
2010-11-01 07:19:41 +00:00
|
|
|
}
|
2006-12-21 13:47:27 +00:00
|
|
|
|
2021-12-25 14:28:22 -06:00
|
|
|
struct CustomDataUniqueCheckData {
|
|
|
|
|
CustomData *data;
|
2023-03-29 17:10:49 +02:00
|
|
|
eCustomDataType type;
|
2021-12-25 14:28:22 -06:00
|
|
|
int index;
|
|
|
|
|
};
|
|
|
|
|
|
2013-03-04 19:27:51 +00:00
|
|
|
static bool customdata_unique_check(void *arg, const char *name)
|
2010-11-01 07:19:41 +00:00
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
CustomDataUniqueCheckData *data_arg = static_cast<CustomDataUniqueCheckData *>(arg);
|
2010-11-07 08:49:07 +00:00
|
|
|
return cd_layer_find_dupe(data_arg->data, name, data_arg->type, data_arg->index);
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-10 17:21:24 +10:00
|
|
|
int CustomData_name_maxncpy_calc(const blender::StringRef name)
|
Mesh: Move UV layers to generic attributes
Currently the `MLoopUV` struct stores UV coordinates and flags related
to editing UV maps in the UV editor. This patch changes the coordinates
to use the generic 2D vector type, and moves the flags into three
separate boolean attributes. This follows the design in T95965, with
the ultimate intention of simplifying code and improving performance.
Importantly, the change allows exporters and renderers to use UVs
"touched" by geometry nodes, which only creates generic attributes.
It also allows geometry nodes to create "proper" UV maps from scratch,
though only with the Store Named Attribute node for now.
The new design considers any 2D vector attribute on the corner domain
to be a UV map. In the future, they might be distinguished from regular
2D vectors with attribute metadata, which may be helpful because they
are often interpolated differently.
Most of the code changes deal with passing around UV BMesh custom data
offsets and tracking the boolean "sublayers". The boolean layers are
use the following prefixes for attribute names: vert selection: `.vs.`,
edge selection: `.es.`, pinning: `.pn.`. Currently these are short to
avoid using up the maximum length of attribute names. To accommodate
for these 4 extra characters, the name length limit is enlarged to 68
bytes, while the maximum user settable name length is still 64 bytes.
Unfortunately Python/RNA API access to the UV flag data becomes slower.
Accessing the boolean layers directly is be better for performance in
general.
Like the other mesh SoA refactors, backward and forward compatibility
aren't affected, and won't be changed until 4.0. We pay for that by
making mesh reading and writing more expensive with conversions.
Resolves T85962
Differential Revision: https://developer.blender.org/D14365
2023-01-10 00:47:04 -05:00
|
|
|
{
|
|
|
|
|
if (name.startswith(".")) {
|
|
|
|
|
return MAX_CUSTOMDATA_LAYER_NAME_NO_PREFIX;
|
|
|
|
|
}
|
|
|
|
|
for (const blender::StringRef prefix :
|
|
|
|
|
{"." UV_VERTSEL_NAME, UV_EDGESEL_NAME ".", UV_PINNED_NAME "."})
|
|
|
|
|
{
|
|
|
|
|
if (name.startswith(prefix)) {
|
|
|
|
|
return MAX_CUSTOMDATA_LAYER_NAME;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return MAX_CUSTOMDATA_LAYER_NAME_NO_PREFIX;
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
void CustomData_set_layer_unique_name(CustomData *data, const int index)
|
2018-06-17 17:05:51 +02:00
|
|
|
{
|
2012-05-12 16:11:34 +00:00
|
|
|
CustomDataLayer *nlayer = &data->layers[index];
|
2023-03-29 17:10:49 +02:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(nlayer->type));
|
2006-12-21 13:47:27 +00:00
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
CustomDataUniqueCheckData data_arg{data, eCustomDataType(nlayer->type), index};
|
2010-11-07 08:49:07 +00:00
|
|
|
|
2018-11-24 19:21:35 +01:00
|
|
|
if (!typeInfo->defaultname) {
|
2010-11-01 07:19:41 +00:00
|
|
|
return;
|
2018-11-24 19:21:35 +01:00
|
|
|
}
|
|
|
|
|
|
2023-06-10 17:21:24 +10:00
|
|
|
const int name_maxncpy = CustomData_name_maxncpy_calc(nlayer->name);
|
Mesh: Move UV layers to generic attributes
Currently the `MLoopUV` struct stores UV coordinates and flags related
to editing UV maps in the UV editor. This patch changes the coordinates
to use the generic 2D vector type, and moves the flags into three
separate boolean attributes. This follows the design in T95965, with
the ultimate intention of simplifying code and improving performance.
Importantly, the change allows exporters and renderers to use UVs
"touched" by geometry nodes, which only creates generic attributes.
It also allows geometry nodes to create "proper" UV maps from scratch,
though only with the Store Named Attribute node for now.
The new design considers any 2D vector attribute on the corner domain
to be a UV map. In the future, they might be distinguished from regular
2D vectors with attribute metadata, which may be helpful because they
are often interpolated differently.
Most of the code changes deal with passing around UV BMesh custom data
offsets and tracking the boolean "sublayers". The boolean layers are
use the following prefixes for attribute names: vert selection: `.vs.`,
edge selection: `.es.`, pinning: `.pn.`. Currently these are short to
avoid using up the maximum length of attribute names. To accommodate
for these 4 extra characters, the name length limit is enlarged to 68
bytes, while the maximum user settable name length is still 64 bytes.
Unfortunately Python/RNA API access to the UV flag data becomes slower.
Accessing the boolean layers directly is be better for performance in
general.
Like the other mesh SoA refactors, backward and forward compatibility
aren't affected, and won't be changed until 4.0. We pay for that by
making mesh reading and writing more expensive with conversions.
Resolves T85962
Differential Revision: https://developer.blender.org/D14365
2023-01-10 00:47:04 -05:00
|
|
|
|
2018-11-24 19:21:35 +01:00
|
|
|
/* Set default name if none specified. Note we only call DATA_() when
|
|
|
|
|
* needed to avoid overhead of locale lookups in the depsgraph. */
|
|
|
|
|
if (nlayer->name[0] == '\0') {
|
2023-05-13 17:38:48 +10:00
|
|
|
STRNCPY_UTF8(nlayer->name, DATA_(typeInfo->defaultname));
|
2018-11-24 19:21:35 +01:00
|
|
|
}
|
2013-03-25 08:29:06 +00:00
|
|
|
|
2023-05-03 10:23:00 +10:00
|
|
|
const char *defname = ""; /* Dummy argument, never used as `name` is never zero length. */
|
2023-06-10 17:21:24 +10:00
|
|
|
BLI_uniquename_cb(customdata_unique_check, &data_arg, defname, '.', nlayer->name, name_maxncpy);
|
2006-12-21 13:47:27 +00:00
|
|
|
}
|
|
|
|
|
|
2012-08-03 22:12:57 +00:00
|
|
|
void CustomData_validate_layer_name(const CustomData *data,
|
2023-03-29 17:10:49 +02:00
|
|
|
const eCustomDataType type,
|
2024-02-08 16:56:42 +01:00
|
|
|
const StringRef name,
|
2012-08-03 22:12:57 +00:00
|
|
|
char *outname)
|
2011-10-13 20:00:22 +00:00
|
|
|
{
|
|
|
|
|
int index = -1;
|
|
|
|
|
|
|
|
|
|
/* if a layer name was given, try to find that layer */
|
2024-02-22 18:01:06 +01:00
|
|
|
if (!name.is_empty()) {
|
2011-10-13 20:00:22 +00:00
|
|
|
index = CustomData_get_named_layer_index(data, type, name);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-10-13 20:00:22 +00:00
|
|
|
|
2014-02-01 01:45:09 +11:00
|
|
|
if (index == -1) {
|
2011-10-13 20:00:22 +00:00
|
|
|
/* either no layer was specified, or the layer we want has been
|
2012-03-03 20:19:11 +00:00
|
|
|
* deleted, so assign the active layer to name
|
|
|
|
|
*/
|
2011-10-13 20:00:22 +00:00
|
|
|
index = CustomData_get_active_layer_index(data, type);
|
2023-05-13 17:38:48 +10:00
|
|
|
BLI_strncpy_utf8(outname, data->layers[index].name, MAX_CUSTOMDATA_LAYER_NAME);
|
2012-12-16 08:43:05 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2024-02-08 16:56:42 +01:00
|
|
|
char name_c_str[MAX_CUSTOMDATA_LAYER_NAME];
|
|
|
|
|
name.copy(name_c_str);
|
|
|
|
|
BLI_strncpy_utf8(outname, name_c_str, MAX_CUSTOMDATA_LAYER_NAME);
|
2011-10-13 20:00:22 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
bool CustomData_verify_versions(CustomData *data, const int index)
|
2007-01-06 20:16:06 +00:00
|
|
|
{
|
|
|
|
|
const LayerTypeInfo *typeInfo;
|
|
|
|
|
CustomDataLayer *layer = &data->layers[index];
|
2013-05-08 12:57:18 +00:00
|
|
|
bool keeplayer = true;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2007-01-06 20:16:06 +00:00
|
|
|
if (layer->type >= CD_NUMTYPES) {
|
2013-05-08 12:57:18 +00:00
|
|
|
keeplayer = false; /* unknown layer type from future version */
|
2007-01-06 20:16:06 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2023-03-29 17:10:49 +02:00
|
|
|
typeInfo = layerType_getInfo(eCustomDataType(layer->type));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-12 16:11:34 +00:00
|
|
|
if (!typeInfo->defaultname && (index > 0) && data->layers[index - 1].type == layer->type) {
|
2013-05-08 12:57:18 +00:00
|
|
|
keeplayer = false; /* multiple layers of which we only support one */
|
2012-04-28 06:31:57 +00:00
|
|
|
}
|
2019-08-28 01:55:43 +10:00
|
|
|
/* This is a preemptive fix for cases that should not happen
|
2019-04-27 12:07:07 +10:00
|
|
|
* (layers that should not be written in .blend files),
|
2023-02-12 14:37:16 +11:00
|
|
|
* but can happen due to bugs (see e.g. #62318).
|
2019-04-27 12:07:07 +10:00
|
|
|
* Also for forward compatibility, in future,
|
|
|
|
|
* we may put into `.blend` file some currently un-written data types,
|
2019-03-08 17:01:18 +01:00
|
|
|
* this should cover that case as well.
|
|
|
|
|
* Better to be safe here, and fix issue on the fly rather than crash... */
|
|
|
|
|
/* 0 structnum is used in writing code to tag layer types that should not be written. */
|
|
|
|
|
else if (typeInfo->structnum == 0 &&
|
2019-07-03 15:43:05 +02:00
|
|
|
/* XXX Not sure why those three are exception, maybe that should be fixed? */
|
Subdivision: add support for vertex creasing
This adds vertex creasing support for OpenSubDiv for modeling, rendering,
Alembic and USD I/O.
For modeling, vertex creasing follows the edge creasing implementation with an
operator accessible through the Vertex menu in Edit Mode, and some parameter in
the properties panel. The option in the Subsurf and Multires to use edge
creasing also affects vertex creasing.
The vertex crease data is stored as a CustomData layer, unlike edge creases
which for now are stored in `MEdge`, but will in the future also be moved to
a `CustomData` layer. See comments for details on the difference in behavior
for the `CD_CREASE` layer between egdes and vertices.
For Cycles this adds sockets on the Mesh node to hold data about which vertices
are creased (one socket for the indices, one for the weigths).
Viewport rendering of vertex creasing reuses the same color scheme as for edges
and creased vertices are drawn bigger than uncreased vertices.
For Alembic and USD, vertex crease support follows the edge crease
implementation, they are always read, but only exported if a `Subsurf` modifier
is present on the Mesh.
Reviewed By: brecht, fclem, sergey, sybren, campbellbarton
Differential Revision: https://developer.blender.org/D10145
2022-01-20 12:20:30 +01:00
|
|
|
!ELEM(layer->type,
|
|
|
|
|
CD_PAINT_MASK,
|
|
|
|
|
CD_FACEMAP,
|
|
|
|
|
CD_MTEXPOLY,
|
|
|
|
|
CD_SCULPT_FACE_SETS,
|
|
|
|
|
CD_CREASE))
|
|
|
|
|
{
|
2019-03-08 17:01:18 +01:00
|
|
|
keeplayer = false;
|
|
|
|
|
CLOG_WARN(&LOG, ".blend file read: removing a data layer that should not have been written");
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-03-08 17:01:18 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2007-01-06 20:16:06 +00:00
|
|
|
if (!keeplayer) {
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = index + 1; i < data->totlayer; i++) {
|
2012-05-12 16:11:34 +00:00
|
|
|
data->layers[i - 1] = data->layers[i];
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2007-01-06 20:16:06 +00:00
|
|
|
data->totlayer--;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2007-01-06 20:16:06 +00:00
|
|
|
return keeplayer;
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-21 15:15:38 +12:00
|
|
|
static bool CustomData_layer_ensure_data_exists(CustomDataLayer *layer, size_t count)
|
|
|
|
|
{
|
|
|
|
|
BLI_assert(layer);
|
2023-03-29 17:10:49 +02:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
|
2022-07-21 15:15:38 +12:00
|
|
|
BLI_assert(typeInfo);
|
|
|
|
|
|
|
|
|
|
if (layer->data || count == 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (layer->type) {
|
|
|
|
|
/* When more instances of corrupt files are found, add them here. */
|
2023-02-12 14:37:16 +11:00
|
|
|
case CD_PROP_BOOL: /* See #84935. */
|
|
|
|
|
case CD_MLOOPUV: /* See #90620. */
|
|
|
|
|
case CD_PROP_FLOAT2: /* See #90620. */
|
2023-03-29 17:10:49 +02:00
|
|
|
layer->data = MEM_calloc_arrayN(
|
|
|
|
|
count, typeInfo->size, layerType_getName(eCustomDataType(layer->type)));
|
2022-07-21 15:15:38 +12:00
|
|
|
BLI_assert(layer->data);
|
Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:54:53 -05:00
|
|
|
if (typeInfo->set_default_value) {
|
|
|
|
|
typeInfo->set_default_value(layer->data, count);
|
2022-07-21 15:15:38 +12:00
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
break;
|
|
|
|
|
|
2022-07-21 16:25:01 +12:00
|
|
|
case CD_MTEXPOLY:
|
|
|
|
|
/* TODO: Investigate multiple test failures on cycles, e.g. cycles_shadow_catcher_cpu. */
|
|
|
|
|
break;
|
|
|
|
|
|
2022-07-21 15:15:38 +12:00
|
|
|
default:
|
|
|
|
|
/* Log an error so we can collect instances of bad files. */
|
2023-06-04 18:35:12 +10:00
|
|
|
CLOG_WARN(&LOG, "CustomDataLayer->data is null for type %d.", layer->type);
|
2022-07-21 15:15:38 +12:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-03 16:19:08 +01:00
|
|
|
bool CustomData_layer_validate(CustomDataLayer *layer, const uint totitems, const bool do_fixes)
|
|
|
|
|
{
|
2022-07-21 15:15:38 +12:00
|
|
|
BLI_assert(layer);
|
2023-03-29 17:10:49 +02:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
|
2022-07-21 15:15:38 +12:00
|
|
|
BLI_assert(typeInfo);
|
|
|
|
|
|
|
|
|
|
if (do_fixes) {
|
|
|
|
|
CustomData_layer_ensure_data_exists(layer, totitems);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLI_assert((totitems == 0) || layer->data);
|
|
|
|
|
BLI_assert(MEM_allocN_len(layer->data) >= totitems * typeInfo->size);
|
2018-12-03 16:19:08 +01:00
|
|
|
|
2021-12-25 14:28:22 -06:00
|
|
|
if (typeInfo->validate != nullptr) {
|
2018-12-03 16:19:08 +01:00
|
|
|
return typeInfo->validate(layer->data, totitems, do_fixes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-25 12:49:01 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name External Files
|
|
|
|
|
* \{ */
|
2009-11-25 14:27:50 +00:00
|
|
|
|
2022-03-25 12:04:22 +11:00
|
|
|
static void customdata_external_filename(char filepath[FILE_MAX],
|
2009-12-10 14:26:06 +00:00
|
|
|
ID *id,
|
|
|
|
|
CustomDataExternal *external)
|
2009-11-25 14:27:50 +00:00
|
|
|
{
|
2022-03-25 12:04:22 +11:00
|
|
|
BLI_strncpy(filepath, external->filepath, FILE_MAX);
|
|
|
|
|
BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(id));
|
2009-11-25 14:27:50 +00:00
|
|
|
}
|
|
|
|
|
|
2022-10-03 17:37:25 -05:00
|
|
|
void CustomData_external_reload(CustomData *data, ID * /*id*/, eCustomDataMask mask, int totelem)
|
2010-06-01 19:26:35 +00:00
|
|
|
{
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
|
|
|
|
CustomDataLayer *layer = &data->layers[i];
|
2023-03-29 17:10:49 +02:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
|
2010-06-01 19:26:35 +00:00
|
|
|
|
2012-10-07 09:48:59 +00:00
|
|
|
if (!(mask & CD_TYPE_AS_MASK(layer->type))) {
|
|
|
|
|
/* pass */
|
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else if ((layer->flag & CD_FLAG_EXTERNAL) && (layer->flag & CD_FLAG_IN_MEMORY)) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (typeInfo->free) {
|
2023-12-05 17:41:48 -05:00
|
|
|
typeInfo->free(layer->data, totelem);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2010-06-01 19:26:35 +00:00
|
|
|
layer->flag &= ~CD_FLAG_IN_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-11-25 14:27:50 +00:00
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
void CustomData_external_read(CustomData *data, ID *id, eCustomDataMask mask, const int totelem)
|
2009-11-25 14:27:50 +00:00
|
|
|
{
|
2012-05-12 16:11:34 +00:00
|
|
|
CustomDataExternal *external = data->external;
|
2009-11-25 14:27:50 +00:00
|
|
|
CustomDataLayer *layer;
|
2022-03-25 12:04:22 +11:00
|
|
|
char filepath[FILE_MAX];
|
2020-09-09 15:43:09 +02:00
|
|
|
int update = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!external) {
|
2009-11-25 14:27:50 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2009-11-25 14:27:50 +00:00
|
|
|
layer = &data->layers[i];
|
2023-03-29 17:10:49 +02:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-10-07 09:48:59 +00:00
|
|
|
if (!(mask & CD_TYPE_AS_MASK(layer->type))) {
|
|
|
|
|
/* pass */
|
|
|
|
|
}
|
|
|
|
|
else if (layer->flag & CD_FLAG_IN_MEMORY) {
|
|
|
|
|
/* pass */
|
|
|
|
|
}
|
|
|
|
|
else if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->read) {
|
2012-05-12 16:11:34 +00:00
|
|
|
update = 1;
|
2012-10-07 09:48:59 +00:00
|
|
|
}
|
2009-11-25 14:27:50 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!update) {
|
2009-11-25 14:27:50 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-03-25 12:04:22 +11:00
|
|
|
customdata_external_filename(filepath, id, external);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-01-26 09:21:42 -06:00
|
|
|
CDataFile *cdf = cdf_create(CDF_TYPE_MESH);
|
2022-03-25 12:04:22 +11:00
|
|
|
if (!cdf_read_open(cdf, filepath)) {
|
2016-04-06 16:14:30 +10:00
|
|
|
cdf_free(cdf);
|
2023-03-29 17:10:49 +02:00
|
|
|
CLOG_ERROR(&LOG,
|
|
|
|
|
"Failed to read %s layer from %s.",
|
|
|
|
|
layerType_getName(eCustomDataType(layer->type)),
|
|
|
|
|
filepath);
|
2009-11-25 14:27:50 +00:00
|
|
|
return;
|
2010-01-19 15:15:48 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2009-11-25 14:27:50 +00:00
|
|
|
layer = &data->layers[i];
|
2023-03-29 17:10:49 +02:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-10-07 09:48:59 +00:00
|
|
|
if (!(mask & CD_TYPE_AS_MASK(layer->type))) {
|
|
|
|
|
/* pass */
|
|
|
|
|
}
|
|
|
|
|
else if (layer->flag & CD_FLAG_IN_MEMORY) {
|
|
|
|
|
/* pass */
|
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->read) {
|
2024-03-28 20:57:47 +11:00
|
|
|
const CDataFileLayer *blay = cdf_layer_find(cdf, layer->type, layer->name);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (blay) {
|
|
|
|
|
if (cdf_read_layer(cdf, blay)) {
|
2012-10-07 09:48:59 +00:00
|
|
|
if (typeInfo->read(cdf, layer->data, totelem)) {
|
|
|
|
|
/* pass */
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
2009-11-25 14:27:50 +00:00
|
|
|
layer->flag |= CD_FLAG_IN_MEMORY;
|
|
|
|
|
}
|
2019-04-22 09:39:35 +10:00
|
|
|
else {
|
2009-11-25 14:27:50 +00:00
|
|
|
break;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2009-11-25 14:27:50 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-12-10 14:26:06 +00:00
|
|
|
cdf_read_close(cdf);
|
|
|
|
|
cdf_free(cdf);
|
2009-11-25 14:27:50 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-12-10 14:26:06 +00:00
|
|
|
void CustomData_external_write(
|
2022-08-03 11:58:52 -05:00
|
|
|
CustomData *data, ID *id, eCustomDataMask mask, const int totelem, const int free)
|
2009-11-25 14:27:50 +00:00
|
|
|
{
|
2012-05-12 16:11:34 +00:00
|
|
|
CustomDataExternal *external = data->external;
|
2020-09-09 15:43:09 +02:00
|
|
|
int update = 0;
|
2022-03-25 12:04:22 +11:00
|
|
|
char filepath[FILE_MAX];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!external) {
|
2009-11-25 14:27:50 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-01-19 15:15:48 +00:00
|
|
|
/* test if there is anything to write */
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2021-01-26 09:21:42 -06:00
|
|
|
CustomDataLayer *layer = &data->layers[i];
|
2023-03-29 17:10:49 +02:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-10-07 09:48:59 +00:00
|
|
|
if (!(mask & CD_TYPE_AS_MASK(layer->type))) {
|
|
|
|
|
/* pass */
|
|
|
|
|
}
|
|
|
|
|
else if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) {
|
2012-05-12 16:11:34 +00:00
|
|
|
update = 1;
|
2012-10-07 09:48:59 +00:00
|
|
|
}
|
2009-11-25 14:27:50 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!update) {
|
2009-11-25 14:27:50 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-01-19 15:15:48 +00:00
|
|
|
/* make sure data is read before we try to write */
|
2009-12-10 14:26:06 +00:00
|
|
|
CustomData_external_read(data, id, mask, totelem);
|
2022-03-25 12:04:22 +11:00
|
|
|
customdata_external_filename(filepath, id, external);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-01-26 09:21:42 -06:00
|
|
|
CDataFile *cdf = cdf_create(CDF_TYPE_MESH);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < data->totlayer; i++) {
|
2021-01-26 09:21:42 -06:00
|
|
|
CustomDataLayer *layer = &data->layers[i];
|
2023-03-29 17:10:49 +02:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->filesize) {
|
|
|
|
|
if (layer->flag & CD_FLAG_IN_MEMORY) {
|
2010-01-19 15:15:48 +00:00
|
|
|
cdf_layer_add(
|
2012-05-12 16:11:34 +00:00
|
|
|
cdf, layer->type, layer->name, typeInfo->filesize(cdf, layer->data, totelem));
|
2010-01-19 15:15:48 +00:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
cdf_free(cdf);
|
|
|
|
|
return; /* read failed for a layer! */
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2010-01-19 15:15:48 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-03-25 12:04:22 +11:00
|
|
|
if (!cdf_write_open(cdf, filepath)) {
|
|
|
|
|
CLOG_ERROR(&LOG, "Failed to open %s for writing.", filepath);
|
2016-01-11 13:14:30 +11:00
|
|
|
cdf_free(cdf);
|
2009-11-25 14:27:50 +00:00
|
|
|
return;
|
2010-01-19 15:15:48 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
int i;
|
2012-05-12 16:11:34 +00:00
|
|
|
for (i = 0; i < data->totlayer; i++) {
|
2021-01-26 09:21:42 -06:00
|
|
|
CustomDataLayer *layer = &data->layers[i];
|
2023-03-29 17:10:49 +02:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) {
|
2021-01-26 09:21:42 -06:00
|
|
|
CDataFileLayer *blay = cdf_layer_find(cdf, layer->type, layer->name);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (cdf_write_layer(cdf, blay)) {
|
2012-10-07 09:48:59 +00:00
|
|
|
if (typeInfo->write(cdf, layer->data, totelem)) {
|
|
|
|
|
/* pass */
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2012-10-07 09:48:59 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2009-11-25 14:27:50 +00:00
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2012-10-07 09:48:59 +00:00
|
|
|
}
|
2009-11-25 14:27:50 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (i != data->totlayer) {
|
2022-03-25 12:04:22 +11:00
|
|
|
CLOG_ERROR(&LOG, "Failed to write data to %s.", filepath);
|
2016-01-11 13:14:30 +11:00
|
|
|
cdf_write_close(cdf);
|
2009-12-10 14:26:06 +00:00
|
|
|
cdf_free(cdf);
|
2009-11-25 14:27:50 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-12 16:11:34 +00:00
|
|
|
for (i = 0; i < data->totlayer; i++) {
|
2021-01-26 09:21:42 -06:00
|
|
|
CustomDataLayer *layer = &data->layers[i];
|
2023-03-29 17:10:49 +02:00
|
|
|
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) {
|
|
|
|
|
if (free) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (typeInfo->free) {
|
2023-12-05 17:41:48 -05:00
|
|
|
typeInfo->free(layer->data, totelem);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2009-11-25 14:27:50 +00:00
|
|
|
layer->flag &= ~CD_FLAG_IN_MEMORY;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
2009-11-25 14:27:50 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-12-10 14:26:06 +00:00
|
|
|
cdf_write_close(cdf);
|
|
|
|
|
cdf_free(cdf);
|
2009-11-25 14:27:50 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
void CustomData_external_add(CustomData *data,
|
|
|
|
|
ID * /*id*/,
|
|
|
|
|
const eCustomDataType type,
|
|
|
|
|
const int /*totelem*/,
|
|
|
|
|
const char *filepath)
|
2009-11-25 14:27:50 +00:00
|
|
|
{
|
2012-05-12 16:11:34 +00:00
|
|
|
CustomDataExternal *external = data->external;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-01-26 09:21:42 -06:00
|
|
|
int layer_index = CustomData_get_active_layer_index(data, type);
|
2019-04-22 09:39:35 +10:00
|
|
|
if (layer_index == -1) {
|
2014-02-01 01:45:09 +11:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-01-26 09:21:42 -06:00
|
|
|
CustomDataLayer *layer = &data->layers[layer_index];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (layer->flag & CD_FLAG_EXTERNAL) {
|
2009-11-25 14:27:50 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!external) {
|
2021-12-25 14:28:22 -06:00
|
|
|
external = MEM_cnew<CustomDataExternal>(__func__);
|
2012-05-12 16:11:34 +00:00
|
|
|
data->external = external;
|
2009-11-25 14:27:50 +00:00
|
|
|
}
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(external->filepath, filepath);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-12 16:11:34 +00:00
|
|
|
layer->flag |= CD_FLAG_EXTERNAL | CD_FLAG_IN_MEMORY;
|
2009-11-25 14:27:50 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
void CustomData_external_remove(CustomData *data,
|
|
|
|
|
ID *id,
|
|
|
|
|
const eCustomDataType type,
|
|
|
|
|
const int totelem)
|
2009-11-25 14:27:50 +00:00
|
|
|
{
|
2012-05-12 16:11:34 +00:00
|
|
|
CustomDataExternal *external = data->external;
|
2009-11-25 14:27:50 +00:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
int layer_index = CustomData_get_active_layer_index(data, type);
|
2019-04-22 09:39:35 +10:00
|
|
|
if (layer_index == -1) {
|
2014-02-01 01:45:09 +11:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2009-11-25 14:27:50 +00:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
CustomDataLayer *layer = &data->layers[layer_index];
|
2009-11-25 14:27:50 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!external) {
|
2009-11-25 14:27:50 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2009-11-25 14:27:50 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (layer->flag & CD_FLAG_EXTERNAL) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!(layer->flag & CD_FLAG_IN_MEMORY)) {
|
2011-12-23 20:30:23 +00:00
|
|
|
CustomData_external_read(data, id, CD_TYPE_AS_MASK(layer->type), totelem);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2009-11-25 14:27:50 +00:00
|
|
|
|
|
|
|
|
layer->flag &= ~CD_FLAG_EXTERNAL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-29 17:10:49 +02:00
|
|
|
bool CustomData_external_test(CustomData *data, const eCustomDataType type)
|
2009-11-25 14:27:50 +00:00
|
|
|
{
|
2020-09-09 15:43:09 +02:00
|
|
|
int layer_index = CustomData_get_active_layer_index(data, type);
|
2019-04-22 09:39:35 +10:00
|
|
|
if (layer_index == -1) {
|
2014-02-01 01:45:09 +11:00
|
|
|
return false;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2009-11-25 14:27:50 +00:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
CustomDataLayer *layer = &data->layers[layer_index];
|
2013-05-08 12:57:18 +00:00
|
|
|
return (layer->flag & CD_FLAG_EXTERNAL) != 0;
|
2009-11-25 14:27:50 +00:00
|
|
|
}
|
|
|
|
|
|
2022-03-25 12:49:01 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Mesh-to-Mesh Data Transfer
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2015-02-23 13:51:55 +11:00
|
|
|
static void copy_bit_flag(void *dst, const void *src, const size_t data_size, const uint64_t flag)
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
{
|
|
|
|
|
#define COPY_BIT_FLAG(_type, _dst, _src, _f) \
|
|
|
|
|
{ \
|
2023-05-02 20:09:09 +10:00
|
|
|
const _type _val = *((_type *)(_src)) & (_type)(_f); \
|
|
|
|
|
*((_type *)(_dst)) &= ~(_type)(_f); \
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
*((_type *)(_dst)) |= _val; \
|
|
|
|
|
} \
|
|
|
|
|
(void)0
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
switch (data_size) {
|
|
|
|
|
case 1:
|
|
|
|
|
COPY_BIT_FLAG(uint8_t, dst, src, flag);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
COPY_BIT_FLAG(uint16_t, dst, src, flag);
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
COPY_BIT_FLAG(uint32_t, dst, src, flag);
|
|
|
|
|
break;
|
|
|
|
|
case 8:
|
|
|
|
|
COPY_BIT_FLAG(uint64_t, dst, src, flag);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2019-05-01 11:09:22 +10:00
|
|
|
// CLOG_ERROR(&LOG, "Unknown flags-container size (%zu)", datasize);
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#undef COPY_BIT_FLAG
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 13:51:55 +11:00
|
|
|
static bool check_bit_flag(const void *data, const size_t data_size, const uint64_t flag)
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
{
|
|
|
|
|
switch (data_size) {
|
|
|
|
|
case 1:
|
2022-09-25 20:27:46 +10:00
|
|
|
return ((*((uint8_t *)data) & uint8_t(flag)) != 0);
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
case 2:
|
2022-09-25 20:27:46 +10:00
|
|
|
return ((*((uint16_t *)data) & uint16_t(flag)) != 0);
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
case 4:
|
2022-09-25 20:27:46 +10:00
|
|
|
return ((*((uint32_t *)data) & uint32_t(flag)) != 0);
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
case 8:
|
2022-09-25 20:27:46 +10:00
|
|
|
return ((*((uint64_t *)data) & uint64_t(flag)) != 0);
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
default:
|
2019-05-01 11:09:22 +10:00
|
|
|
// CLOG_ERROR(&LOG, "Unknown flags-container size (%zu)", datasize);
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-02-23 13:51:55 +11:00
|
|
|
static void customdata_data_transfer_interp_generic(const CustomDataTransferLayerMap *laymap,
|
|
|
|
|
void *data_dst,
|
|
|
|
|
const void **sources,
|
|
|
|
|
const float *weights,
|
|
|
|
|
const int count,
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
const float mix_factor)
|
|
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
BLI_assert(weights != nullptr);
|
2020-10-05 18:50:38 +02:00
|
|
|
BLI_assert(count > 0);
|
|
|
|
|
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
/* Fake interpolation, we actually copy highest weighted source to dest.
|
2019-04-27 12:07:07 +10:00
|
|
|
* Note we also handle bitflags here,
|
|
|
|
|
* in which case we rather choose to transfer value of elements totaling
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
* more than 0.5 of weight. */
|
|
|
|
|
int best_src_idx = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-06-09 11:10:40 -04:00
|
|
|
const int data_type = laymap->data_type;
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
const int mix_mode = laymap->mix_mode;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
size_t data_size;
|
|
|
|
|
const uint64_t data_flag = laymap->data_flag;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-12-25 14:28:22 -06:00
|
|
|
cd_interp interp_cd = nullptr;
|
|
|
|
|
cd_copy copy_cd = nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
if (!sources) {
|
|
|
|
|
/* Not supported here, abort. */
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-04-05 14:23:54 +10:00
|
|
|
if (int(data_type) & CD_FAKE) {
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
data_size = laymap->data_size;
|
|
|
|
|
}
|
|
|
|
|
else {
|
2023-06-09 11:10:40 -04:00
|
|
|
const LayerTypeInfo *type_info = layerType_getInfo(eCustomDataType(data_type));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-25 20:27:46 +10:00
|
|
|
data_size = size_t(type_info->size);
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
interp_cd = type_info->interp;
|
|
|
|
|
copy_cd = type_info->copy;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-01-26 09:21:42 -06:00
|
|
|
void *tmp_dst = MEM_mallocN(data_size, __func__);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
if (count > 1 && !interp_cd) {
|
|
|
|
|
if (data_flag) {
|
2019-04-27 12:07:07 +10:00
|
|
|
/* Boolean case, we can 'interpolate' in two groups,
|
|
|
|
|
* and choose value from highest weighted group. */
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
float tot_weight_true = 0.0f;
|
|
|
|
|
int item_true_idx = -1, item_false_idx = -1;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < count; i++) {
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
if (check_bit_flag(sources[i], data_size, data_flag)) {
|
|
|
|
|
tot_weight_true += weights[i];
|
|
|
|
|
item_true_idx = i;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
item_false_idx = i;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
best_src_idx = (tot_weight_true >= 0.5f) ? item_true_idx : item_false_idx;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* We just choose highest weighted source. */
|
|
|
|
|
float max_weight = 0.0f;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < count; i++) {
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
if (weights[i] > max_weight) {
|
|
|
|
|
max_weight = weights[i];
|
|
|
|
|
best_src_idx = i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
BLI_assert(best_src_idx >= 0);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
if (interp_cd) {
|
2021-12-25 14:28:22 -06:00
|
|
|
interp_cd(sources, weights, nullptr, count, tmp_dst);
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
}
|
|
|
|
|
else if (data_flag) {
|
|
|
|
|
copy_bit_flag(tmp_dst, sources[best_src_idx], data_size, data_flag);
|
|
|
|
|
}
|
|
|
|
|
/* No interpolation, just copy highest weight source element's data. */
|
|
|
|
|
else if (copy_cd) {
|
2015-02-23 13:51:55 +11:00
|
|
|
copy_cd(sources[best_src_idx], tmp_dst, 1);
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
memcpy(tmp_dst, sources[best_src_idx], data_size);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
if (data_flag) {
|
2019-04-27 12:07:07 +10:00
|
|
|
/* Bool flags, only copy if dest data is set (resp. unset) -
|
|
|
|
|
* only 'advanced' modes we can support here! */
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
if (mix_factor >= 0.5f && ((mix_mode == CDT_MIX_TRANSFER) ||
|
|
|
|
|
(mix_mode == CDT_MIX_REPLACE_ABOVE_THRESHOLD &&
|
|
|
|
|
check_bit_flag(data_dst, data_size, data_flag)) ||
|
|
|
|
|
(mix_mode == CDT_MIX_REPLACE_BELOW_THRESHOLD &&
|
|
|
|
|
!check_bit_flag(data_dst, data_size, data_flag))))
|
|
|
|
|
{
|
|
|
|
|
copy_bit_flag(data_dst, tmp_dst, data_size, data_flag);
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-04-05 14:23:54 +10:00
|
|
|
else if (!(int(data_type) & CD_FAKE)) {
|
2023-06-09 11:10:40 -04:00
|
|
|
CustomData_data_mix_value(eCustomDataType(data_type), tmp_dst, data_dst, mix_mode, mix_factor);
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
}
|
|
|
|
|
/* Else we can do nothing by default, needs custom interp func!
|
|
|
|
|
* Note this is here only for sake of consistency, not expected to be used much actually? */
|
|
|
|
|
else {
|
|
|
|
|
if (mix_factor >= 0.5f) {
|
|
|
|
|
memcpy(data_dst, tmp_dst, data_size);
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
MEM_freeN(tmp_dst);
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-16 21:28:22 +02:00
|
|
|
void customdata_data_transfer_interp_normal_normals(const CustomDataTransferLayerMap *laymap,
|
|
|
|
|
void *data_dst,
|
|
|
|
|
const void **sources,
|
|
|
|
|
const float *weights,
|
|
|
|
|
const int count,
|
|
|
|
|
const float mix_factor)
|
|
|
|
|
{
|
2021-12-25 14:28:22 -06:00
|
|
|
BLI_assert(weights != nullptr);
|
2020-10-05 18:50:38 +02:00
|
|
|
BLI_assert(count > 0);
|
|
|
|
|
|
2023-06-09 11:10:40 -04:00
|
|
|
const eCustomDataType data_type = eCustomDataType(laymap->data_type);
|
|
|
|
|
BLI_assert(data_type == CD_NORMAL);
|
2015-10-16 21:28:22 +02:00
|
|
|
const int mix_mode = laymap->mix_mode;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-12-25 14:28:22 -06:00
|
|
|
SpaceTransform *space_transform = static_cast<SpaceTransform *>(laymap->interp_data);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-10-16 21:28:22 +02:00
|
|
|
const LayerTypeInfo *type_info = layerType_getInfo(data_type);
|
|
|
|
|
cd_interp interp_cd = type_info->interp;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-10-16 21:28:22 +02:00
|
|
|
float tmp_dst[3];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-10-16 21:28:22 +02:00
|
|
|
if (!sources) {
|
|
|
|
|
/* Not supported here, abort. */
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-12-25 14:28:22 -06:00
|
|
|
interp_cd(sources, weights, nullptr, count, tmp_dst);
|
2015-10-16 21:28:22 +02:00
|
|
|
if (space_transform) {
|
|
|
|
|
/* tmp_dst is in source space so far, bring it back in destination space. */
|
|
|
|
|
BLI_space_transform_invert_normal(space_transform, tmp_dst);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-10-16 21:28:22 +02:00
|
|
|
CustomData_data_mix_value(data_type, tmp_dst, data_dst, mix_mode, mix_factor);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
void CustomData_data_transfer(const MeshPairRemap *me_remap,
|
|
|
|
|
const CustomDataTransferLayerMap *laymap)
|
|
|
|
|
{
|
|
|
|
|
MeshPairRemapItem *mapit = me_remap->items;
|
|
|
|
|
const int totelem = me_remap->items_num;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-06-09 11:10:40 -04:00
|
|
|
const int data_type = laymap->data_type;
|
2015-02-23 13:51:55 +11:00
|
|
|
const void *data_src = laymap->data_src;
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
void *data_dst = laymap->data_dst;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
size_t data_step;
|
|
|
|
|
size_t data_size;
|
|
|
|
|
size_t data_offset;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-12-25 14:28:22 -06:00
|
|
|
cd_datatransfer_interp interp = nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
size_t tmp_buff_size = 32;
|
2021-12-25 14:28:22 -06:00
|
|
|
const void **tmp_data_src = nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-12-25 14:28:22 -06:00
|
|
|
/* NOTE: null data_src may happen and be valid (see vgroups...). */
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
if (!data_dst) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
if (data_src) {
|
2021-12-25 14:28:22 -06:00
|
|
|
tmp_data_src = (const void **)MEM_malloc_arrayN(
|
|
|
|
|
tmp_buff_size, sizeof(*tmp_data_src), __func__);
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-04-05 14:23:54 +10:00
|
|
|
if (int(data_type) & CD_FAKE) {
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
data_step = laymap->elem_size;
|
|
|
|
|
data_size = laymap->data_size;
|
|
|
|
|
data_offset = laymap->data_offset;
|
|
|
|
|
}
|
|
|
|
|
else {
|
2023-06-09 11:10:40 -04:00
|
|
|
const LayerTypeInfo *type_info = layerType_getInfo(eCustomDataType(data_type));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Mesh: Move bevel weight out of MVert and MEdge
As described in T95966, the goal is to move to a "struct of arrays"
approach rather than gathering an arbitrary set of data in hard-coded
structs. This has performance benefits, but also code complexity
benefits (this patch removes plenty of code, though the boilerplate
for the new operators outweighs that here).
To mirror the internal change, the options for storing mesh bevel
weights are converted into operators that add or remove the layer,
like for some other layers.
The most complex change is to the solidify modifier, where bevel
weights had special handling. Other than that, most changes are
removing clearing of the weights, boilerplate for the add/remove
operators, and removing the manual transfer of bevel weights
in bmesh - mesh conversion.
Eventually bevel weights can become a fully generic attribute,
but for now this patch aims to avoid most functional changes.
Bevel weights are still written and read from the mesh in the old way,
so neither forward nor backward compatibility are affected. As described
in T95965, writing in the old format will be done until 4.0.
Differential Revision: https://developer.blender.org/D14077
2022-09-09 08:29:07 -05:00
|
|
|
/* NOTE: we can use 'fake' CDLayers for crease :/. */
|
2022-09-25 20:27:46 +10:00
|
|
|
data_size = size_t(type_info->size);
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
data_step = laymap->elem_size ? laymap->elem_size : data_size;
|
|
|
|
|
data_offset = laymap->data_offset;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
interp = laymap->interp ? laymap->interp : customdata_data_transfer_interp_generic;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int i = 0; i < totelem; i++, data_dst = POINTER_OFFSET(data_dst, data_step), mapit++) {
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
const int sources_num = mapit->sources_num;
|
2019-08-01 16:00:37 +02:00
|
|
|
const float mix_factor = laymap->mix_factor *
|
|
|
|
|
(laymap->mix_weights ? laymap->mix_weights[i] : 1.0f);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
if (!sources_num) {
|
|
|
|
|
/* No sources for this element, skip it. */
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
if (tmp_data_src) {
|
|
|
|
|
if (UNLIKELY(sources_num > tmp_buff_size)) {
|
2022-09-25 20:27:46 +10:00
|
|
|
tmp_buff_size = size_t(sources_num);
|
2021-12-25 14:28:22 -06:00
|
|
|
tmp_data_src = (const void **)MEM_reallocN((void *)tmp_data_src,
|
|
|
|
|
sizeof(*tmp_data_src) * tmp_buff_size);
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-09-09 15:43:09 +02:00
|
|
|
for (int j = 0; j < sources_num; j++) {
|
2022-09-25 20:27:46 +10:00
|
|
|
const size_t src_idx = size_t(mapit->indices_src[j]);
|
2015-02-23 13:51:55 +11:00
|
|
|
tmp_data_src[j] = POINTER_OFFSET(data_src, (data_step * src_idx) + data_offset);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-02-23 13:51:55 +11:00
|
|
|
interp(laymap,
|
|
|
|
|
POINTER_OFFSET(data_dst, data_offset),
|
|
|
|
|
tmp_data_src,
|
|
|
|
|
mapit->weights_src,
|
|
|
|
|
sources_num,
|
|
|
|
|
mix_factor);
|
Transfer Data: add main core code and operators.
This add code needed to map a CD data layout from source mesh towards destination one,
and code needed to actually transfer data, using BKE's mesh remap generated data.
This allows to transfer most CD layers (vgroups, vcols, uvs...) as well as fake, boolean ones
(like smooth/sharp edges/faces, etc.). Some types are not yet transferable, mainly
shape keys, this is known TODO.
Data transfer can also use some advanced mixing in some cases (mostly, vgroups and vcols).
Notes:
* New transfer operators transfer data from active object towards selected ones.
* Modifier will be committed separately.
* Old weight transfer code (for vgroups) is kept for now, mostly because it is the only
usable one in weightpaint mode (it transfers from selected object to active one,
this is not sensible in Object mode, but needed in WeightPaint one). This will be addressed soon.
Again, heavily reviewed and enhanced by Campbell, thanks!
2015-01-09 19:11:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MEM_SAFE_FREE(tmp_data_src);
|
|
|
|
|
}
|
2020-08-28 14:30:19 +02:00
|
|
|
|
2022-03-25 12:49:01 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Custom Data IO
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static void write_mdisps(BlendWriter *writer,
|
|
|
|
|
const int count,
|
|
|
|
|
const MDisps *mdlist,
|
|
|
|
|
const int external)
|
2020-08-28 14:30:19 +02:00
|
|
|
{
|
|
|
|
|
if (mdlist) {
|
|
|
|
|
BLO_write_struct_array(writer, MDisps, count, mdlist);
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
2022-05-22 20:26:25 +02:00
|
|
|
const MDisps *md = &mdlist[i];
|
2020-08-28 14:30:19 +02:00
|
|
|
if (md->disps) {
|
|
|
|
|
if (!external) {
|
|
|
|
|
BLO_write_float3_array(writer, md->totdisp, &md->disps[0][0]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (md->hidden) {
|
2024-04-24 17:01:22 +02:00
|
|
|
BLO_write_int8_array(writer,
|
|
|
|
|
BLI_BITMAP_SIZE(md->totdisp) * sizeof(BLI_bitmap),
|
|
|
|
|
reinterpret_cast<const int8_t *>(md->hidden));
|
2020-08-28 14:30:19 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-22 20:06:24 +02:00
|
|
|
static void write_grid_paint_mask(BlendWriter *writer,
|
|
|
|
|
int count,
|
|
|
|
|
const GridPaintMask *grid_paint_mask)
|
2020-08-28 14:30:19 +02:00
|
|
|
{
|
|
|
|
|
if (grid_paint_mask) {
|
|
|
|
|
BLO_write_struct_array(writer, GridPaintMask, count, grid_paint_mask);
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
2022-05-22 20:06:24 +02:00
|
|
|
const GridPaintMask *gpm = &grid_paint_mask[i];
|
2020-08-28 14:30:19 +02:00
|
|
|
if (gpm->data) {
|
|
|
|
|
const int gridsize = BKE_ccg_gridsize(gpm->level);
|
|
|
|
|
BLO_write_raw(writer, sizeof(*gpm->data) * gridsize * gridsize, gpm->data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-29 14:06:51 +01:00
|
|
|
static void blend_write_layer_data(BlendWriter *writer,
|
|
|
|
|
const CustomDataLayer &layer,
|
|
|
|
|
const int count)
|
|
|
|
|
{
|
|
|
|
|
switch (layer.type) {
|
|
|
|
|
case CD_MDEFORMVERT:
|
|
|
|
|
BKE_defvert_blend_write(writer, count, static_cast<const MDeformVert *>(layer.data));
|
|
|
|
|
break;
|
|
|
|
|
case CD_MDISPS:
|
|
|
|
|
write_mdisps(
|
|
|
|
|
writer, count, static_cast<const MDisps *>(layer.data), layer.flag & CD_FLAG_EXTERNAL);
|
|
|
|
|
break;
|
|
|
|
|
case CD_PAINT_MASK:
|
|
|
|
|
BLO_write_raw(writer, sizeof(float) * count, static_cast<const float *>(layer.data));
|
|
|
|
|
break;
|
|
|
|
|
case CD_GRID_PAINT_MASK:
|
|
|
|
|
write_grid_paint_mask(writer, count, static_cast<const GridPaintMask *>(layer.data));
|
|
|
|
|
break;
|
|
|
|
|
case CD_PROP_BOOL:
|
|
|
|
|
BLO_write_raw(writer, sizeof(bool) * count, static_cast<const bool *>(layer.data));
|
|
|
|
|
break;
|
|
|
|
|
default: {
|
|
|
|
|
const char *structname;
|
|
|
|
|
int structnum;
|
|
|
|
|
CustomData_file_write_info(eCustomDataType(layer.type), &structname, &structnum);
|
|
|
|
|
if (structnum) {
|
|
|
|
|
int datasize = structnum * count;
|
|
|
|
|
BLO_write_struct_array_by_name(writer, structname, datasize, layer.data);
|
|
|
|
|
}
|
|
|
|
|
else if (!BLO_write_is_undo(writer)) { /* Do not warn on undo. */
|
|
|
|
|
printf("%s error: layer '%s':%d - can't be written to file\n",
|
|
|
|
|
__func__,
|
|
|
|
|
structname,
|
|
|
|
|
layer.type);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-09 20:38:33 +10:00
|
|
|
void CustomData_blend_write(BlendWriter *writer,
|
|
|
|
|
CustomData *data,
|
2022-05-29 11:02:10 +02:00
|
|
|
Span<CustomDataLayer> layers_to_write,
|
2020-09-09 20:38:33 +10:00
|
|
|
int count,
|
2022-06-01 14:38:06 +10:00
|
|
|
eCustomDataMask cddata_mask,
|
2020-09-09 20:38:33 +10:00
|
|
|
ID *id)
|
2020-08-28 14:30:19 +02:00
|
|
|
{
|
|
|
|
|
/* write external customdata (not for undo) */
|
|
|
|
|
if (data->external && !BLO_write_is_undo(writer)) {
|
|
|
|
|
CustomData_external_write(data, id, cddata_mask, count, 0);
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-29 11:02:10 +02:00
|
|
|
BLO_write_struct_array_at_address(
|
|
|
|
|
writer, CustomDataLayer, data->totlayer, data->layers, layers_to_write.data());
|
2020-08-28 14:30:19 +02:00
|
|
|
|
2022-05-29 11:02:10 +02:00
|
|
|
for (const CustomDataLayer &layer : layers_to_write) {
|
2024-02-29 17:14:58 +01:00
|
|
|
const size_t size_in_bytes = CustomData_sizeof(eCustomDataType(layer.type)) * count;
|
|
|
|
|
BLO_write_shared(writer, layer.data, size_in_bytes, layer.sharing_info, [&]() {
|
|
|
|
|
blend_write_layer_data(writer, layer, count);
|
|
|
|
|
});
|
2020-08-28 14:30:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (data->external) {
|
|
|
|
|
BLO_write_struct(writer, CustomDataExternal, data->external);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
static void blend_read_mdisps(BlendDataReader *reader,
|
|
|
|
|
const int count,
|
|
|
|
|
MDisps *mdisps,
|
|
|
|
|
const int external)
|
2020-08-28 14:30:19 +02:00
|
|
|
{
|
|
|
|
|
if (mdisps) {
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
2024-04-24 17:01:22 +02:00
|
|
|
MDisps &md = mdisps[i];
|
2020-08-28 14:30:19 +02:00
|
|
|
|
2024-04-24 17:01:22 +02:00
|
|
|
BLO_read_float3_array(reader, md.totdisp, reinterpret_cast<float **>(&md.disps));
|
|
|
|
|
BLO_read_int8_array(reader,
|
|
|
|
|
BLI_BITMAP_SIZE(md.totdisp) * sizeof(BLI_bitmap),
|
|
|
|
|
reinterpret_cast<int8_t **>(&md.hidden));
|
|
|
|
|
|
|
|
|
|
if (md.totdisp && !md.level) {
|
2020-08-28 14:30:19 +02:00
|
|
|
/* this calculation is only correct for loop mdisps;
|
|
|
|
|
* if loading pre-BMesh face mdisps this will be
|
|
|
|
|
* overwritten with the correct value in
|
2023-07-31 11:50:54 +10:00
|
|
|
* #bm_corners_to_loops() */
|
2024-04-24 17:01:22 +02:00
|
|
|
float gridsize = sqrtf(md.totdisp);
|
|
|
|
|
md.level = int(logf(gridsize - 1.0f) / float(M_LN2)) + 1;
|
2020-08-28 14:30:19 +02:00
|
|
|
}
|
|
|
|
|
|
2024-04-24 17:01:22 +02:00
|
|
|
if (!external && !md.disps) {
|
|
|
|
|
md.totdisp = 0;
|
2020-08-28 14:30:19 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void blend_read_paint_mask(BlendDataReader *reader,
|
|
|
|
|
int count,
|
|
|
|
|
GridPaintMask *grid_paint_mask)
|
|
|
|
|
{
|
|
|
|
|
if (grid_paint_mask) {
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
|
|
GridPaintMask *gpm = &grid_paint_mask[i];
|
|
|
|
|
if (gpm->data) {
|
2024-04-24 17:01:22 +02:00
|
|
|
const int gridsize = BKE_ccg_gridsize(gpm->level);
|
|
|
|
|
BLO_read_float_array(reader, gridsize * gridsize, &gpm->data);
|
2020-08-28 14:30:19 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-29 14:15:04 +01:00
|
|
|
static void blend_read_layer_data(BlendDataReader *reader, CustomDataLayer &layer, const int count)
|
|
|
|
|
{
|
2024-04-24 17:01:22 +02:00
|
|
|
const size_t elem_size = CustomData_sizeof(eCustomDataType(layer.type));
|
|
|
|
|
BLO_read_struct_array(reader, char, elem_size *count, &layer.data);
|
2024-02-29 14:15:04 +01:00
|
|
|
if (CustomData_layer_ensure_data_exists(&layer, count)) {
|
|
|
|
|
/* Under normal operations, this shouldn't happen, but...
|
|
|
|
|
* For a CD_PROP_BOOL example, see #84935.
|
|
|
|
|
* For a CD_MLOOPUV example, see #90620. */
|
|
|
|
|
CLOG_WARN(&LOG,
|
|
|
|
|
"Allocated custom data layer that was not saved correctly for layer.type = %d.",
|
|
|
|
|
layer.type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (layer.type == CD_MDISPS) {
|
|
|
|
|
blend_read_mdisps(
|
|
|
|
|
reader, count, static_cast<MDisps *>(layer.data), layer.flag & CD_FLAG_EXTERNAL);
|
|
|
|
|
}
|
|
|
|
|
else if (layer.type == CD_GRID_PAINT_MASK) {
|
|
|
|
|
blend_read_paint_mask(reader, count, static_cast<GridPaintMask *>(layer.data));
|
|
|
|
|
}
|
|
|
|
|
else if (layer.type == CD_MDEFORMVERT) {
|
|
|
|
|
BKE_defvert_blend_read(reader, count, static_cast<MDeformVert *>(layer.data));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-03 11:58:52 -05:00
|
|
|
void CustomData_blend_read(BlendDataReader *reader, CustomData *data, const int count)
|
2020-08-28 14:30:19 +02:00
|
|
|
{
|
2024-04-24 17:01:22 +02:00
|
|
|
BLO_read_struct_array(reader, CustomDataLayer, data->totlayer, &data->layers);
|
2020-08-28 14:30:19 +02:00
|
|
|
|
2023-02-12 14:37:16 +11:00
|
|
|
/* Annoying workaround for bug #31079 loading legacy files with
|
2020-09-30 20:09:02 +10:00
|
|
|
* no polygons _but_ have stale custom-data. */
|
2021-12-25 14:28:22 -06:00
|
|
|
if (UNLIKELY(count == 0 && data->layers == nullptr && data->totlayer != 0)) {
|
2020-08-28 14:30:19 +02:00
|
|
|
CustomData_reset(data);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-24 17:01:22 +02:00
|
|
|
BLO_read_struct(reader, CustomDataExternal, &data->external);
|
2020-08-28 14:30:19 +02:00
|
|
|
|
2024-03-02 20:10:34 +01:00
|
|
|
blender::Map<void *, const ImplicitSharingInfo *> sharing_info_by_data;
|
|
|
|
|
|
2020-08-28 14:30:19 +02:00
|
|
|
int i = 0;
|
|
|
|
|
while (i < data->totlayer) {
|
|
|
|
|
CustomDataLayer *layer = &data->layers[i];
|
|
|
|
|
|
|
|
|
|
if (layer->flag & CD_FLAG_EXTERNAL) {
|
|
|
|
|
layer->flag &= ~CD_FLAG_IN_MEMORY;
|
|
|
|
|
}
|
2023-04-13 14:57:57 +02:00
|
|
|
layer->sharing_info = nullptr;
|
2020-08-28 14:30:19 +02:00
|
|
|
|
|
|
|
|
if (CustomData_verify_versions(data, i)) {
|
2024-03-02 20:20:26 +01:00
|
|
|
layer->sharing_info = BLO_read_shared(
|
|
|
|
|
reader, &layer->data, [&]() -> const ImplicitSharingInfo * {
|
|
|
|
|
blend_read_layer_data(reader, *layer, count);
|
|
|
|
|
if (layer->data == nullptr) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
const ImplicitSharingInfo *sharing_info = sharing_info_by_data.lookup_default(
|
|
|
|
|
layer->data, nullptr);
|
|
|
|
|
if (sharing_info != nullptr) {
|
|
|
|
|
sharing_info->add_user();
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
sharing_info = make_implicit_sharing_info_for_layer(
|
|
|
|
|
eCustomDataType(layer->type), layer->data, count);
|
|
|
|
|
sharing_info_by_data.add(layer->data, sharing_info);
|
|
|
|
|
}
|
|
|
|
|
return sharing_info;
|
|
|
|
|
});
|
2020-08-28 14:30:19 +02:00
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-29 09:19:52 -05:00
|
|
|
/* Ensure allocated size is set to the size of the read array. While this should always be the
|
|
|
|
|
* case (see #CustomData_blend_write_prepare), there can be some corruption in rare cases (e.g.
|
|
|
|
|
* files saved between ff3d535bc2a63092 and 945f32e66d6ada2a). */
|
|
|
|
|
data->maxlayer = data->totlayer;
|
|
|
|
|
|
2020-08-28 14:30:19 +02:00
|
|
|
CustomData_update_typemap(data);
|
|
|
|
|
}
|
2022-01-19 15:09:48 +11:00
|
|
|
|
2022-03-25 12:49:01 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Custom Data Debugging
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2022-01-19 15:09:48 +11:00
|
|
|
#ifndef NDEBUG
|
|
|
|
|
|
|
|
|
|
void CustomData_debug_info_from_layers(const CustomData *data, const char *indent, DynStr *dynstr)
|
|
|
|
|
{
|
2023-03-29 17:10:49 +02:00
|
|
|
for (eCustomDataType type = eCustomDataType(0); type < CD_NUMTYPES;
|
|
|
|
|
type = eCustomDataType(type + 1))
|
|
|
|
|
{
|
2022-01-19 15:09:48 +11:00
|
|
|
if (CustomData_has_layer(data, type)) {
|
|
|
|
|
/* NOTE: doesn't account for multiple layers. */
|
2024-02-08 12:21:33 -05:00
|
|
|
const char *name = CustomData_layertype_name(type);
|
2022-01-19 15:09:48 +11:00
|
|
|
const int size = CustomData_sizeof(type);
|
|
|
|
|
const void *pt = CustomData_get_layer(data, type);
|
2023-01-11 13:03:53 +11:00
|
|
|
const int pt_size = pt ? int(MEM_allocN_len(pt) / size) : 0;
|
2022-01-19 15:09:48 +11:00
|
|
|
const char *structname;
|
|
|
|
|
int structnum;
|
|
|
|
|
CustomData_file_write_info(type, &structname, &structnum);
|
|
|
|
|
BLI_dynstr_appendf(
|
|
|
|
|
dynstr,
|
|
|
|
|
"%sdict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n",
|
|
|
|
|
indent,
|
|
|
|
|
name,
|
|
|
|
|
structname,
|
|
|
|
|
type,
|
|
|
|
|
(const void *)pt,
|
|
|
|
|
size,
|
|
|
|
|
pt_size);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-07 10:35:23 +11:00
|
|
|
#endif /* !NDEBUG */
|
2022-03-19 10:57:40 +01:00
|
|
|
|
2022-03-25 12:49:01 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
2022-03-19 10:57:40 +01:00
|
|
|
namespace blender::bke {
|
|
|
|
|
|
2022-03-25 12:49:01 +11:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Custom Data C++ API
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2023-12-20 22:33:17 +01:00
|
|
|
std::optional<VolumeGridType> custom_data_type_to_volume_grid_type(const eCustomDataType type)
|
|
|
|
|
{
|
|
|
|
|
switch (type) {
|
|
|
|
|
case CD_PROP_FLOAT:
|
|
|
|
|
return VOLUME_GRID_FLOAT;
|
|
|
|
|
case CD_PROP_FLOAT3:
|
|
|
|
|
return VOLUME_GRID_VECTOR_FLOAT;
|
|
|
|
|
case CD_PROP_INT32:
|
|
|
|
|
return VOLUME_GRID_INT;
|
|
|
|
|
case CD_PROP_BOOL:
|
|
|
|
|
return VOLUME_GRID_BOOLEAN;
|
|
|
|
|
default:
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-22 17:58:09 +01:00
|
|
|
std::optional<eCustomDataType> volume_grid_type_to_custom_data_type(const VolumeGridType type)
|
|
|
|
|
{
|
|
|
|
|
switch (type) {
|
|
|
|
|
case VOLUME_GRID_FLOAT:
|
|
|
|
|
return CD_PROP_FLOAT;
|
|
|
|
|
case VOLUME_GRID_VECTOR_FLOAT:
|
|
|
|
|
return CD_PROP_FLOAT3;
|
|
|
|
|
case VOLUME_GRID_INT:
|
|
|
|
|
return CD_PROP_INT32;
|
|
|
|
|
case VOLUME_GRID_BOOLEAN:
|
|
|
|
|
return CD_PROP_BOOL;
|
|
|
|
|
default:
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-25 12:49:01 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
2022-03-19 10:57:40 +01:00
|
|
|
} // namespace blender::bke
|
2022-09-16 12:20:28 -07:00
|
|
|
|
2023-02-14 12:24:39 +11:00
|
|
|
size_t CustomData_get_elem_size(const CustomDataLayer *layer)
|
2022-09-16 12:20:28 -07:00
|
|
|
{
|
|
|
|
|
return LAYERTYPEINFO[layer->type].size;
|
|
|
|
|
}
|