2023-05-31 16:19:06 +02:00
|
|
|
/* SPDX-FileCopyrightText: 2005 Blender Foundation
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2015-03-29 04:44:05 +11:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup modifiers
|
2015-03-29 04:44:05 +11:00
|
|
|
*
|
|
|
|
|
* Method of smoothing deformation, also known as 'delta-mush'.
|
|
|
|
|
*/
|
|
|
|
|
|
2019-02-25 11:56:24 +01:00
|
|
|
#include "BLI_utildefines.h"
|
|
|
|
|
|
|
|
|
|
#include "BLI_math.h"
|
|
|
|
|
|
2020-06-05 10:41:03 -04:00
|
|
|
#include "BLT_translation.h"
|
|
|
|
|
|
2020-10-01 09:38:00 -05:00
|
|
|
#include "DNA_defaults.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "DNA_mesh_types.h"
|
2015-03-29 04:44:05 +11:00
|
|
|
#include "DNA_meshdata_types.h"
|
|
|
|
|
#include "DNA_object_types.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "DNA_scene_types.h"
|
2020-06-05 10:41:03 -04:00
|
|
|
#include "DNA_screen_types.h"
|
2015-03-29 04:44:05 +11:00
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
2020-06-05 10:41:03 -04:00
|
|
|
#include "BKE_context.h"
|
2015-03-29 04:44:05 +11:00
|
|
|
#include "BKE_deform.h"
|
|
|
|
|
#include "BKE_editmesh.h"
|
2020-02-10 12:58:59 +01:00
|
|
|
#include "BKE_lib_id.h"
|
2023-03-12 22:29:15 +01:00
|
|
|
#include "BKE_mesh.hh"
|
2020-06-10 22:32:06 +10:00
|
|
|
#include "BKE_mesh_wrapper.h"
|
2020-06-05 10:41:03 -04:00
|
|
|
#include "BKE_screen.h"
|
|
|
|
|
|
|
|
|
|
#include "UI_interface.h"
|
|
|
|
|
#include "UI_resources.h"
|
|
|
|
|
|
|
|
|
|
#include "RNA_access.h"
|
2022-03-14 16:54:46 +01:00
|
|
|
#include "RNA_prototypes.h"
|
2015-03-29 04:44:05 +11:00
|
|
|
|
2023-05-04 18:35:37 +02:00
|
|
|
#include "MOD_modifiertypes.hh"
|
|
|
|
|
#include "MOD_ui_common.hh"
|
|
|
|
|
#include "MOD_util.hh"
|
2015-03-29 04:44:05 +11:00
|
|
|
|
2020-06-23 16:42:00 +02:00
|
|
|
#include "BLO_read_write.h"
|
|
|
|
|
|
2019-04-04 14:42:33 +02:00
|
|
|
#include "DEG_depsgraph_query.h"
|
|
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
// #define DEBUG_TIME
|
|
|
|
|
|
|
|
|
|
#include "PIL_time.h"
|
|
|
|
|
#ifdef DEBUG_TIME
|
|
|
|
|
# include "PIL_time_utildefines.h"
|
|
|
|
|
|
2022-04-27 11:24:25 +10:00
|
|
|
#endif
|
2015-03-29 04:44:05 +11:00
|
|
|
|
2022-09-15 17:59:42 +10:00
|
|
|
#include "BLI_strict_flags.h"
|
|
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
static void initData(ModifierData *md)
|
|
|
|
|
{
|
|
|
|
|
CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)md;
|
|
|
|
|
|
2020-10-01 09:38:00 -05:00
|
|
|
BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(csmd, modifier));
|
2015-03-29 04:44:05 +11:00
|
|
|
|
2020-10-01 09:38:00 -05:00
|
|
|
MEMCPY_STRUCT_AFTER(csmd, DNA_struct_default_get(CorrectiveSmoothModifierData), modifier);
|
2015-03-29 04:44:05 +11:00
|
|
|
|
2023-01-19 15:54:47 -06:00
|
|
|
csmd->delta_cache.deltas = nullptr;
|
2015-03-29 04:44:05 +11:00
|
|
|
}
|
|
|
|
|
|
2018-07-04 12:45:30 +02:00
|
|
|
static void copyData(const ModifierData *md, ModifierData *target, const int flag)
|
2015-03-29 04:44:05 +11:00
|
|
|
{
|
2018-05-08 15:04:10 +02:00
|
|
|
const CorrectiveSmoothModifierData *csmd = (const CorrectiveSmoothModifierData *)md;
|
2015-03-29 04:44:05 +11:00
|
|
|
CorrectiveSmoothModifierData *tcsmd = (CorrectiveSmoothModifierData *)target;
|
|
|
|
|
|
2020-05-08 10:14:02 +02:00
|
|
|
BKE_modifier_copydata_generic(md, target, flag);
|
2015-03-29 04:44:05 +11:00
|
|
|
|
|
|
|
|
if (csmd->bind_coords) {
|
2023-01-19 15:54:47 -06:00
|
|
|
tcsmd->bind_coords = static_cast<float(*)[3]>(MEM_dupallocN(csmd->bind_coords));
|
2015-03-29 04:44:05 +11:00
|
|
|
}
|
|
|
|
|
|
2023-01-19 15:54:47 -06:00
|
|
|
tcsmd->delta_cache.deltas = nullptr;
|
2022-04-27 11:24:25 +10:00
|
|
|
tcsmd->delta_cache.deltas_num = 0;
|
2015-03-29 04:44:05 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void freeBind(CorrectiveSmoothModifierData *csmd)
|
|
|
|
|
{
|
|
|
|
|
MEM_SAFE_FREE(csmd->bind_coords);
|
2019-09-25 16:45:05 +02:00
|
|
|
MEM_SAFE_FREE(csmd->delta_cache.deltas);
|
2015-03-29 04:44:05 +11:00
|
|
|
|
|
|
|
|
csmd->bind_coords_num = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void freeData(ModifierData *md)
|
|
|
|
|
{
|
|
|
|
|
CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)md;
|
|
|
|
|
freeBind(csmd);
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-14 14:49:40 -05:00
|
|
|
static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
|
2015-03-29 04:44:05 +11:00
|
|
|
{
|
|
|
|
|
CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)md;
|
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
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
/* ask for vertex groups if we need them */
|
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 (csmd->defgrp_name[0] != '\0') {
|
|
|
|
|
r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
|
2015-03-29 04:44:05 +11:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* check individual weights for changes and cache values */
|
Mesh: Remove redundant custom data pointers
For copy-on-write, we want to share attribute arrays between meshes
where possible. Mutable pointers like `Mesh.mvert` make that difficult
by making ownership vague. They also make code more complex by adding
redundancy.
The simplest solution is just removing them and retrieving layers from
`CustomData` as needed. Similar changes have already been applied to
curves and point clouds (e9f82d3dc7ee, 410a6efb747f). Removing use of
the pointers generally makes code more obvious and more reusable.
Mesh data is now accessed with a C++ API (`Mesh::edges()` or
`Mesh::edges_for_write()`), and a C API (`BKE_mesh_edges(mesh)`).
The CoW changes this commit makes possible are described in T95845
and T95842, and started in D14139 and D14140. The change also simplifies
the ongoing mesh struct-of-array refactors from T95965.
**RNA/Python Access Performance**
Theoretically, accessing mesh elements with the RNA API may become
slower, since the layer needs to be found on every random access.
However, overhead is already high enough that this doesn't make a
noticible differenc, and performance is actually improved in some
cases. Random access can be up to 10% faster, but other situations
might be a bit slower. Generally using `foreach_get/set` are the best
way to improve performance. See the differential revision for more
discussion about Python performance.
Cycles has been updated to use raw pointers and the internal Blender
mesh types, mostly because there is no sense in having this overhead
when it's already compiled with Blender. In my tests this roughly
halves the Cycles mesh creation time (0.19s to 0.10s for a 1 million
face grid).
Differential Revision: https://developer.blender.org/D15488
2022-09-05 11:56:34 -05:00
|
|
|
static void mesh_get_weights(const MDeformVert *dvert,
|
2015-03-29 04:44:05 +11:00
|
|
|
const int defgrp_index,
|
2022-03-28 12:29:47 +11:00
|
|
|
const uint verts_num,
|
2015-03-29 04:44:05 +11:00
|
|
|
const bool use_invert_vgroup,
|
|
|
|
|
float *smooth_weights)
|
|
|
|
|
{
|
2019-09-19 13:32:36 +10:00
|
|
|
uint i;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-03-28 12:29:47 +11:00
|
|
|
for (i = 0; i < verts_num; i++, dvert++) {
|
2020-03-06 12:50:56 +11:00
|
|
|
const float w = BKE_defvert_find_weight(dvert, defgrp_index);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
if (use_invert_vgroup == false) {
|
|
|
|
|
smooth_weights[i] = w;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
smooth_weights[i] = 1.0f - w;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-11 11:20:44 +02:00
|
|
|
static void mesh_get_boundaries(Mesh *mesh, float *smooth_weights)
|
2015-03-29 04:44:05 +11:00
|
|
|
{
|
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
|
|
|
const blender::Span<blender::int2> edges = mesh->edges();
|
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
|
|
|
const blender::OffsetIndices polys = mesh->polys();
|
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
|
|
|
const blender::Span<int> corner_edges = mesh->corner_edges();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-15 16:42:37 +10:00
|
|
|
/* Flag boundary edges so only boundaries are set to 1. */
|
2023-01-19 15:54:47 -06:00
|
|
|
uint8_t *boundaries = static_cast<uint8_t *>(
|
2023-02-23 10:39:51 -05:00
|
|
|
MEM_calloc_arrayN(size_t(edges.size()), sizeof(*boundaries), __func__));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-02-23 10:39:51 -05:00
|
|
|
for (const int64_t i : polys.index_range()) {
|
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
|
|
|
for (const int edge : corner_edges.slice(polys[i])) {
|
|
|
|
|
uint8_t *e_value = &boundaries[edge];
|
2023-01-20 13:22:00 +11:00
|
|
|
*e_value |= uint8_t((*e_value) + 1);
|
2015-03-29 04:44:05 +11:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-02-23 10:39:51 -05:00
|
|
|
for (const int64_t i : edges.index_range()) {
|
2015-03-29 04:44:05 +11:00
|
|
|
if (boundaries[i] == 1) {
|
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
|
|
|
smooth_weights[edges[i][0]] = 0.0f;
|
|
|
|
|
smooth_weights[edges[i][1]] = 0.0f;
|
2015-03-29 04:44:05 +11:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
MEM_freeN(boundaries);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/* Simple Weighted Smoothing
|
|
|
|
|
*
|
|
|
|
|
* (average of surrounding verts)
|
|
|
|
|
*/
|
2018-05-11 11:20:44 +02:00
|
|
|
static void smooth_iter__simple(CorrectiveSmoothModifierData *csmd,
|
|
|
|
|
Mesh *mesh,
|
2015-03-29 04:44:05 +11:00
|
|
|
float (*vertexCos)[3],
|
2022-03-28 12:29:47 +11:00
|
|
|
uint verts_num,
|
2015-03-29 04:44:05 +11:00
|
|
|
const float *smooth_weights,
|
2019-09-19 13:32:36 +10:00
|
|
|
uint iterations)
|
2015-03-29 04:44:05 +11:00
|
|
|
{
|
|
|
|
|
const float lambda = csmd->lambda;
|
2019-09-19 13:32:36 +10:00
|
|
|
uint i;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-01-20 13:22:00 +11:00
|
|
|
const uint edges_num = uint(mesh->totedge);
|
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
|
|
|
const blender::Span<blender::int2> edges = mesh->edges();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
struct SmoothingData_Simple {
|
|
|
|
|
float delta[3];
|
2023-01-19 15:54:47 -06:00
|
|
|
};
|
|
|
|
|
SmoothingData_Simple *smooth_data = MEM_cnew_array<SmoothingData_Simple>(verts_num, __func__);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-01-19 15:54:47 -06:00
|
|
|
float *vertex_edge_count_div = static_cast<float *>(
|
|
|
|
|
MEM_calloc_arrayN(verts_num, sizeof(float), __func__));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
/* calculate as floats to avoid int->float conversion in #smooth_iter */
|
2022-03-28 12:29:47 +11:00
|
|
|
for (i = 0; i < edges_num; i++) {
|
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
|
|
|
vertex_edge_count_div[edges[i][0]] += 1.0f;
|
|
|
|
|
vertex_edge_count_div[edges[i][1]] += 1.0f;
|
2015-03-29 04:44:05 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
/* a little confusing, but we can include 'lambda' and smoothing weight
|
|
|
|
|
* here to avoid multiplying for every iteration */
|
2023-01-19 15:54:47 -06:00
|
|
|
if (smooth_weights == nullptr) {
|
2022-03-28 12:29:47 +11:00
|
|
|
for (i = 0; i < verts_num; i++) {
|
2015-03-29 04:44:05 +11:00
|
|
|
vertex_edge_count_div[i] = lambda * (vertex_edge_count_div[i] ?
|
|
|
|
|
(1.0f / vertex_edge_count_div[i]) :
|
|
|
|
|
1.0f);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2015-03-29 04:44:05 +11:00
|
|
|
else {
|
2022-03-28 12:29:47 +11:00
|
|
|
for (i = 0; i < verts_num; i++) {
|
2015-03-29 04:44:05 +11:00
|
|
|
vertex_edge_count_div[i] = smooth_weights[i] * lambda *
|
|
|
|
|
(vertex_edge_count_div[i] ? (1.0f / vertex_edge_count_div[i]) :
|
|
|
|
|
1.0f);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/* Main Smoothing Loop */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
while (iterations--) {
|
2022-03-28 12:29:47 +11:00
|
|
|
for (i = 0; i < edges_num; i++) {
|
2023-01-19 15:54:47 -06:00
|
|
|
SmoothingData_Simple *sd_v1;
|
|
|
|
|
SmoothingData_Simple *sd_v2;
|
2015-03-29 04:44:05 +11:00
|
|
|
float edge_dir[3];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
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
|
|
|
sub_v3_v3v3(edge_dir, vertexCos[edges[i][1]], vertexCos[edges[i][0]]);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
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
|
|
|
sd_v1 = &smooth_data[edges[i][0]];
|
|
|
|
|
sd_v2 = &smooth_data[edges[i][1]];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
add_v3_v3(sd_v1->delta, edge_dir);
|
|
|
|
|
sub_v3_v3(sd_v2->delta, edge_dir);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-03-28 12:29:47 +11:00
|
|
|
for (i = 0; i < verts_num; i++) {
|
2023-01-19 15:54:47 -06:00
|
|
|
SmoothingData_Simple *sd = &smooth_data[i];
|
2015-03-29 04:44:05 +11:00
|
|
|
madd_v3_v3fl(vertexCos[i], sd->delta, vertex_edge_count_div[i]);
|
|
|
|
|
/* zero for the next iteration (saves memset on entire array) */
|
|
|
|
|
memset(sd, 0, sizeof(*sd));
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
MEM_freeN(vertex_edge_count_div);
|
|
|
|
|
MEM_freeN(smooth_data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/* Edge-Length Weighted Smoothing
|
|
|
|
|
*/
|
|
|
|
|
static void smooth_iter__length_weight(CorrectiveSmoothModifierData *csmd,
|
2018-05-11 11:20:44 +02:00
|
|
|
Mesh *mesh,
|
2015-03-29 04:44:05 +11:00
|
|
|
float (*vertexCos)[3],
|
2022-03-28 12:29:47 +11:00
|
|
|
uint verts_num,
|
2015-03-29 04:44:05 +11:00
|
|
|
const float *smooth_weights,
|
2019-09-19 13:32:36 +10:00
|
|
|
uint iterations)
|
2015-03-29 04:44:05 +11:00
|
|
|
{
|
|
|
|
|
const float eps = FLT_EPSILON * 10.0f;
|
2023-01-20 13:22:00 +11:00
|
|
|
const uint edges_num = uint(mesh->totedge);
|
2021-07-03 23:08:40 +10:00
|
|
|
/* NOTE: the way this smoothing method works, its approx half as strong as the simple-smooth,
|
2015-03-29 04:44:05 +11:00
|
|
|
* and 2.0 rarely spikes, double the value for consistent behavior. */
|
|
|
|
|
const float lambda = csmd->lambda * 2.0f;
|
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
|
|
|
const blender::Span<blender::int2> edges = mesh->edges();
|
2019-09-19 13:32:36 +10:00
|
|
|
uint i;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
struct SmoothingData_Weighted {
|
|
|
|
|
float delta[3];
|
|
|
|
|
float edge_length_sum;
|
2023-01-19 15:54:47 -06:00
|
|
|
};
|
|
|
|
|
SmoothingData_Weighted *smooth_data = MEM_cnew_array<SmoothingData_Weighted>(verts_num,
|
|
|
|
|
__func__);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
/* calculate as floats to avoid int->float conversion in #smooth_iter */
|
2023-01-19 15:54:47 -06:00
|
|
|
float *vertex_edge_count = static_cast<float *>(
|
|
|
|
|
MEM_calloc_arrayN(verts_num, sizeof(float), __func__));
|
2022-03-28 12:29:47 +11:00
|
|
|
for (i = 0; i < edges_num; i++) {
|
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
|
|
|
vertex_edge_count[edges[i][0]] += 1.0f;
|
|
|
|
|
vertex_edge_count[edges[i][1]] += 1.0f;
|
2015-03-29 04:44:05 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/* Main Smoothing Loop */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
while (iterations--) {
|
2022-03-28 12:29:47 +11:00
|
|
|
for (i = 0; i < edges_num; i++) {
|
2023-01-19 15:54:47 -06:00
|
|
|
SmoothingData_Weighted *sd_v1;
|
|
|
|
|
SmoothingData_Weighted *sd_v2;
|
2015-03-29 04:44:05 +11:00
|
|
|
float edge_dir[3];
|
|
|
|
|
float edge_dist;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
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
|
|
|
sub_v3_v3v3(edge_dir, vertexCos[edges[i][1]], vertexCos[edges[i][0]]);
|
2015-03-29 04:44:05 +11:00
|
|
|
edge_dist = len_v3(edge_dir);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
/* weight by distance */
|
|
|
|
|
mul_v3_fl(edge_dir, edge_dist);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
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
|
|
|
sd_v1 = &smooth_data[edges[i][0]];
|
|
|
|
|
sd_v2 = &smooth_data[edges[i][1]];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
add_v3_v3(sd_v1->delta, edge_dir);
|
|
|
|
|
sub_v3_v3(sd_v2->delta, edge_dir);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
sd_v1->edge_length_sum += edge_dist;
|
|
|
|
|
sd_v2->edge_length_sum += edge_dist;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-01-19 15:54:47 -06:00
|
|
|
if (smooth_weights == nullptr) {
|
2015-03-29 04:44:05 +11:00
|
|
|
/* fast-path */
|
2022-03-28 12:29:47 +11:00
|
|
|
for (i = 0; i < verts_num; i++) {
|
2023-01-19 15:54:47 -06:00
|
|
|
SmoothingData_Weighted *sd = &smooth_data[i];
|
2019-08-04 12:51:44 +10:00
|
|
|
/* Divide by sum of all neighbor distances (weighted) and amount of neighbors,
|
2019-05-01 07:40:07 +10:00
|
|
|
* (mean average). */
|
2015-03-29 04:44:05 +11:00
|
|
|
const float div = sd->edge_length_sum * vertex_edge_count[i];
|
|
|
|
|
if (div > eps) {
|
|
|
|
|
#if 0
|
|
|
|
|
/* first calculate the new location */
|
|
|
|
|
mul_v3_fl(sd->delta, 1.0f / div);
|
|
|
|
|
/* then interpolate */
|
|
|
|
|
madd_v3_v3fl(vertexCos[i], sd->delta, lambda);
|
|
|
|
|
#else
|
|
|
|
|
/* do this in one step */
|
|
|
|
|
madd_v3_v3fl(vertexCos[i], sd->delta, lambda / div);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
/* zero for the next iteration (saves memset on entire array) */
|
|
|
|
|
memset(sd, 0, sizeof(*sd));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
2022-03-28 12:29:47 +11:00
|
|
|
for (i = 0; i < verts_num; i++) {
|
2023-01-19 15:54:47 -06:00
|
|
|
SmoothingData_Weighted *sd = &smooth_data[i];
|
2015-03-29 04:44:05 +11:00
|
|
|
const float div = sd->edge_length_sum * vertex_edge_count[i];
|
|
|
|
|
if (div > eps) {
|
|
|
|
|
const float lambda_w = lambda * smooth_weights[i];
|
|
|
|
|
madd_v3_v3fl(vertexCos[i], sd->delta, lambda_w / div);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
memset(sd, 0, sizeof(*sd));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
MEM_freeN(vertex_edge_count);
|
|
|
|
|
MEM_freeN(smooth_data);
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-11 11:20:44 +02:00
|
|
|
static void smooth_iter(CorrectiveSmoothModifierData *csmd,
|
|
|
|
|
Mesh *mesh,
|
2015-03-29 04:44:05 +11:00
|
|
|
float (*vertexCos)[3],
|
2022-03-28 12:29:47 +11:00
|
|
|
uint verts_num,
|
2015-03-29 04:44:05 +11:00
|
|
|
const float *smooth_weights,
|
2019-09-19 13:32:36 +10:00
|
|
|
uint iterations)
|
2015-03-29 04:44:05 +11:00
|
|
|
{
|
|
|
|
|
switch (csmd->smooth_type) {
|
|
|
|
|
case MOD_CORRECTIVESMOOTH_SMOOTH_LENGTH_WEIGHT:
|
2022-03-28 12:29:47 +11:00
|
|
|
smooth_iter__length_weight(csmd, mesh, vertexCos, verts_num, smooth_weights, iterations);
|
2015-03-29 04:44:05 +11:00
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
/* case MOD_CORRECTIVESMOOTH_SMOOTH_SIMPLE: */
|
|
|
|
|
default:
|
2022-03-28 12:29:47 +11:00
|
|
|
smooth_iter__simple(csmd, mesh, vertexCos, verts_num, smooth_weights, iterations);
|
2015-03-29 04:44:05 +11:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-11 11:20:44 +02:00
|
|
|
static void smooth_verts(CorrectiveSmoothModifierData *csmd,
|
|
|
|
|
Mesh *mesh,
|
Mesh: Remove redundant custom data pointers
For copy-on-write, we want to share attribute arrays between meshes
where possible. Mutable pointers like `Mesh.mvert` make that difficult
by making ownership vague. They also make code more complex by adding
redundancy.
The simplest solution is just removing them and retrieving layers from
`CustomData` as needed. Similar changes have already been applied to
curves and point clouds (e9f82d3dc7ee, 410a6efb747f). Removing use of
the pointers generally makes code more obvious and more reusable.
Mesh data is now accessed with a C++ API (`Mesh::edges()` or
`Mesh::edges_for_write()`), and a C API (`BKE_mesh_edges(mesh)`).
The CoW changes this commit makes possible are described in T95845
and T95842, and started in D14139 and D14140. The change also simplifies
the ongoing mesh struct-of-array refactors from T95965.
**RNA/Python Access Performance**
Theoretically, accessing mesh elements with the RNA API may become
slower, since the layer needs to be found on every random access.
However, overhead is already high enough that this doesn't make a
noticible differenc, and performance is actually improved in some
cases. Random access can be up to 10% faster, but other situations
might be a bit slower. Generally using `foreach_get/set` are the best
way to improve performance. See the differential revision for more
discussion about Python performance.
Cycles has been updated to use raw pointers and the internal Blender
mesh types, mostly because there is no sense in having this overhead
when it's already compiled with Blender. In my tests this roughly
halves the Cycles mesh creation time (0.19s to 0.10s for a 1 million
face grid).
Differential Revision: https://developer.blender.org/D15488
2022-09-05 11:56:34 -05:00
|
|
|
const MDeformVert *dvert,
|
2015-03-29 04:44:05 +11:00
|
|
|
const int defgrp_index,
|
|
|
|
|
float (*vertexCos)[3],
|
2022-03-28 12:29:47 +11:00
|
|
|
uint verts_num)
|
2015-03-29 04:44:05 +11:00
|
|
|
{
|
2023-01-19 15:54:47 -06:00
|
|
|
float *smooth_weights = nullptr;
|
2015-03-29 04:44:05 +11:00
|
|
|
|
|
|
|
|
if (dvert || (csmd->flag & MOD_CORRECTIVESMOOTH_PIN_BOUNDARY)) {
|
|
|
|
|
|
2023-01-19 15:54:47 -06:00
|
|
|
smooth_weights = static_cast<float *>(MEM_malloc_arrayN(verts_num, sizeof(float), __func__));
|
2015-03-29 04:44:05 +11:00
|
|
|
|
|
|
|
|
if (dvert) {
|
2018-05-11 11:20:44 +02:00
|
|
|
mesh_get_weights(dvert,
|
2015-03-29 04:44:05 +11:00
|
|
|
defgrp_index,
|
2022-03-28 12:29:47 +11:00
|
|
|
verts_num,
|
2015-03-29 04:44:05 +11:00
|
|
|
(csmd->flag & MOD_CORRECTIVESMOOTH_INVERT_VGROUP) != 0,
|
|
|
|
|
smooth_weights);
|
|
|
|
|
}
|
|
|
|
|
else {
|
2023-01-19 15:54:47 -06:00
|
|
|
copy_vn_fl(smooth_weights, int(verts_num), 1.0f);
|
2015-03-29 04:44:05 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (csmd->flag & MOD_CORRECTIVESMOOTH_PIN_BOUNDARY) {
|
2018-05-11 11:20:44 +02:00
|
|
|
mesh_get_boundaries(mesh, smooth_weights);
|
2015-03-29 04:44:05 +11:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-20 13:22:00 +11:00
|
|
|
smooth_iter(csmd, mesh, vertexCos, verts_num, smooth_weights, uint(csmd->repeat));
|
2015-03-29 04:44:05 +11:00
|
|
|
|
|
|
|
|
if (smooth_weights) {
|
|
|
|
|
MEM_freeN(smooth_weights);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2022-04-27 11:24:25 +10:00
|
|
|
* Calculate an orthogonal 3x3 matrix from 2 edge vectors.
|
|
|
|
|
* \return false if this loop should be ignored (have zero influence).
|
2015-03-29 04:44:05 +11:00
|
|
|
*/
|
2022-04-27 11:24:25 +10:00
|
|
|
static bool calc_tangent_loop(const float v_dir_prev[3],
|
|
|
|
|
const float v_dir_next[3],
|
|
|
|
|
float r_tspace[3][3])
|
2015-03-29 04:44:05 +11:00
|
|
|
{
|
2022-04-27 11:24:25 +10:00
|
|
|
if (UNLIKELY(compare_v3v3(v_dir_prev, v_dir_next, FLT_EPSILON * 10.0f))) {
|
|
|
|
|
/* As there are no weights, the value doesn't matter just initialize it. */
|
|
|
|
|
unit_m3(r_tspace);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
copy_v3_v3(r_tspace[0], v_dir_prev);
|
|
|
|
|
copy_v3_v3(r_tspace[1], v_dir_next);
|
|
|
|
|
|
|
|
|
|
cross_v3_v3v3(r_tspace[2], v_dir_prev, v_dir_next);
|
|
|
|
|
normalize_v3(r_tspace[2]);
|
|
|
|
|
|
|
|
|
|
/* Make orthogonal using `r_tspace[2]` as a basis.
|
|
|
|
|
*
|
|
|
|
|
* NOTE: while it seems more logical to use `v_dir_prev` & `v_dir_next` as separate X/Y axis
|
|
|
|
|
* (instead of combining them as is done here). It's not necessary as the directions of the
|
|
|
|
|
* axis aren't important as long as the difference between tangent matrices is equivalent.
|
2022-09-17 14:46:50 +10:00
|
|
|
* Some computations can be skipped by combining the two directions,
|
2022-04-27 11:24:25 +10:00
|
|
|
* using the cross product for the 3rd axes. */
|
|
|
|
|
add_v3_v3(r_tspace[0], r_tspace[1]);
|
|
|
|
|
normalize_v3(r_tspace[0]);
|
|
|
|
|
cross_v3_v3v3(r_tspace[1], r_tspace[2], r_tspace[0]);
|
|
|
|
|
|
|
|
|
|
return true;
|
2015-03-29 04:44:05 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2022-04-27 11:24:25 +10:00
|
|
|
* \param r_tangent_spaces: Loop aligned array of tangents.
|
2023-01-19 15:54:47 -06:00
|
|
|
* \param r_tangent_weights: Loop aligned array of weights (may be nullptr).
|
2022-04-27 11:24:25 +10:00
|
|
|
* \param r_tangent_weights_per_vertex: Vertex aligned array, accumulating weights for each loop
|
2023-01-19 15:54:47 -06:00
|
|
|
* (may be nullptr).
|
2015-03-29 04:44:05 +11:00
|
|
|
*/
|
2022-04-27 11:24:25 +10:00
|
|
|
static void calc_tangent_spaces(const Mesh *mesh,
|
|
|
|
|
const float (*vertexCos)[3],
|
|
|
|
|
float (*r_tangent_spaces)[3][3],
|
|
|
|
|
float *r_tangent_weights,
|
|
|
|
|
float *r_tangent_weights_per_vertex)
|
2015-03-29 04:44:05 +11:00
|
|
|
{
|
2023-01-20 13:22:00 +11:00
|
|
|
const uint mvert_num = uint(mesh->totvert);
|
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
|
|
|
const blender::OffsetIndices polys = mesh->polys();
|
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
|
|
|
blender::Span<int> corner_verts = mesh->corner_verts();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-01-19 15:54:47 -06:00
|
|
|
if (r_tangent_weights_per_vertex != nullptr) {
|
|
|
|
|
copy_vn_fl(r_tangent_weights_per_vertex, int(mvert_num), 0.0f);
|
2022-04-27 11:24:25 +10:00
|
|
|
}
|
|
|
|
|
|
2023-02-23 10:39:51 -05:00
|
|
|
for (const int64_t i : polys.index_range()) {
|
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
|
|
|
const blender::IndexRange poly = polys[i];
|
|
|
|
|
int next_corner = int(poly.start());
|
|
|
|
|
int term_corner = next_corner + int(poly.size());
|
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
|
|
|
int prev_corner = term_corner - 2;
|
|
|
|
|
int curr_corner = term_corner - 1;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
/* loop directions */
|
|
|
|
|
float v_dir_prev[3], v_dir_next[3];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
/* needed entering the loop */
|
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
|
|
|
sub_v3_v3v3(
|
|
|
|
|
v_dir_prev, vertexCos[corner_verts[prev_corner]], vertexCos[corner_verts[curr_corner]]);
|
2015-03-29 04:44:05 +11:00
|
|
|
normalize_v3(v_dir_prev);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
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
|
|
|
for (; next_corner != term_corner;
|
|
|
|
|
prev_corner = curr_corner, curr_corner = next_corner, next_corner++)
|
|
|
|
|
{
|
|
|
|
|
float(*ts)[3] = r_tangent_spaces[curr_corner];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
/* re-use the previous value */
|
|
|
|
|
#if 0
|
2023-07-12 14:18:59 +02:00
|
|
|
sub_v3_v3v3(
|
|
|
|
|
v_dir_prev, vertexCos[corner_verts[prev_corner]], vertexCos[corner_verts[curr_corner]]);
|
2015-03-29 04:44:05 +11:00
|
|
|
normalize_v3(v_dir_prev);
|
|
|
|
|
#endif
|
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
|
|
|
sub_v3_v3v3(
|
|
|
|
|
v_dir_next, vertexCos[corner_verts[curr_corner]], vertexCos[corner_verts[next_corner]]);
|
2015-03-29 04:44:05 +11:00
|
|
|
normalize_v3(v_dir_next);
|
|
|
|
|
|
2022-04-27 11:24:25 +10:00
|
|
|
if (calc_tangent_loop(v_dir_prev, v_dir_next, ts)) {
|
2023-01-19 15:54:47 -06:00
|
|
|
if (r_tangent_weights != nullptr) {
|
2022-04-27 11:24:25 +10:00
|
|
|
const float weight = fabsf(acosf(dot_v3v3(v_dir_next, v_dir_prev)));
|
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
|
|
|
r_tangent_weights[curr_corner] = weight;
|
|
|
|
|
r_tangent_weights_per_vertex[corner_verts[curr_corner]] += weight;
|
2022-04-27 11:24:25 +10:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
2023-01-19 15:54:47 -06:00
|
|
|
if (r_tangent_weights != nullptr) {
|
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
|
|
|
r_tangent_weights[curr_corner] = 0;
|
2022-04-27 11:24:25 +10:00
|
|
|
}
|
|
|
|
|
}
|
2015-03-29 04:44:05 +11:00
|
|
|
|
|
|
|
|
copy_v3_v3(v_dir_prev, v_dir_next);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-25 16:45:05 +02:00
|
|
|
static void store_cache_settings(CorrectiveSmoothModifierData *csmd)
|
|
|
|
|
{
|
|
|
|
|
csmd->delta_cache.lambda = csmd->lambda;
|
|
|
|
|
csmd->delta_cache.repeat = csmd->repeat;
|
|
|
|
|
csmd->delta_cache.flag = csmd->flag;
|
|
|
|
|
csmd->delta_cache.smooth_type = csmd->smooth_type;
|
|
|
|
|
csmd->delta_cache.rest_source = csmd->rest_source;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool cache_settings_equal(CorrectiveSmoothModifierData *csmd)
|
|
|
|
|
{
|
|
|
|
|
return (csmd->delta_cache.lambda == csmd->lambda && csmd->delta_cache.repeat == csmd->repeat &&
|
|
|
|
|
csmd->delta_cache.flag == csmd->flag &&
|
|
|
|
|
csmd->delta_cache.smooth_type == csmd->smooth_type &&
|
|
|
|
|
csmd->delta_cache.rest_source == csmd->rest_source);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
/**
|
|
|
|
|
* This calculates #CorrectiveSmoothModifierData.delta_cache
|
|
|
|
|
* It's not run on every update (during animation for example).
|
|
|
|
|
*/
|
2018-05-11 11:20:44 +02:00
|
|
|
static void calc_deltas(CorrectiveSmoothModifierData *csmd,
|
|
|
|
|
Mesh *mesh,
|
Mesh: Remove redundant custom data pointers
For copy-on-write, we want to share attribute arrays between meshes
where possible. Mutable pointers like `Mesh.mvert` make that difficult
by making ownership vague. They also make code more complex by adding
redundancy.
The simplest solution is just removing them and retrieving layers from
`CustomData` as needed. Similar changes have already been applied to
curves and point clouds (e9f82d3dc7ee, 410a6efb747f). Removing use of
the pointers generally makes code more obvious and more reusable.
Mesh data is now accessed with a C++ API (`Mesh::edges()` or
`Mesh::edges_for_write()`), and a C API (`BKE_mesh_edges(mesh)`).
The CoW changes this commit makes possible are described in T95845
and T95842, and started in D14139 and D14140. The change also simplifies
the ongoing mesh struct-of-array refactors from T95965.
**RNA/Python Access Performance**
Theoretically, accessing mesh elements with the RNA API may become
slower, since the layer needs to be found on every random access.
However, overhead is already high enough that this doesn't make a
noticible differenc, and performance is actually improved in some
cases. Random access can be up to 10% faster, but other situations
might be a bit slower. Generally using `foreach_get/set` are the best
way to improve performance. See the differential revision for more
discussion about Python performance.
Cycles has been updated to use raw pointers and the internal Blender
mesh types, mostly because there is no sense in having this overhead
when it's already compiled with Blender. In my tests this roughly
halves the Cycles mesh creation time (0.19s to 0.10s for a 1 million
face grid).
Differential Revision: https://developer.blender.org/D15488
2022-09-05 11:56:34 -05:00
|
|
|
const MDeformVert *dvert,
|
2015-03-29 04:44:05 +11:00
|
|
|
const int defgrp_index,
|
|
|
|
|
const float (*rest_coords)[3],
|
2022-03-28 12:29:47 +11:00
|
|
|
uint verts_num)
|
2015-03-29 04:44:05 +11:00
|
|
|
{
|
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
|
|
|
const blender::Span<int> corner_verts = mesh->corner_verts();
|
2022-04-27 11:24:25 +10:00
|
|
|
|
2023-01-19 15:54:47 -06:00
|
|
|
float(*smooth_vertex_coords)[3] = static_cast<float(*)[3]>(MEM_dupallocN(rest_coords));
|
2015-03-29 04:44:05 +11:00
|
|
|
|
2022-04-27 11:24:25 +10:00
|
|
|
uint l_index;
|
|
|
|
|
|
2023-01-19 15:54:47 -06:00
|
|
|
float(*tangent_spaces)[3][3] = static_cast<float(*)[3][3]>(
|
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
|
|
|
MEM_malloc_arrayN(size_t(corner_verts.size()), sizeof(float[3][3]), __func__));
|
2015-03-29 04:44:05 +11:00
|
|
|
|
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
|
|
|
if (csmd->delta_cache.deltas_num != uint(corner_verts.size())) {
|
2019-09-25 16:45:05 +02:00
|
|
|
MEM_SAFE_FREE(csmd->delta_cache.deltas);
|
2015-03-29 04:44:05 +11:00
|
|
|
}
|
|
|
|
|
|
2019-08-01 13:53:25 +10:00
|
|
|
/* allocate deltas if they have not yet been allocated, otherwise we will just write over them */
|
2019-09-25 16:45:05 +02:00
|
|
|
if (!csmd->delta_cache.deltas) {
|
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
|
|
|
csmd->delta_cache.deltas_num = uint(corner_verts.size());
|
2023-01-19 15:54:47 -06:00
|
|
|
csmd->delta_cache.deltas = static_cast<float(*)[3]>(
|
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
|
|
|
MEM_malloc_arrayN(size_t(corner_verts.size()), sizeof(float[3]), __func__));
|
2015-03-29 04:44:05 +11:00
|
|
|
}
|
|
|
|
|
|
2022-03-28 12:29:47 +11:00
|
|
|
smooth_verts(csmd, mesh, dvert, defgrp_index, smooth_vertex_coords, verts_num);
|
2015-03-29 04:44:05 +11:00
|
|
|
|
2023-01-19 15:54:47 -06:00
|
|
|
calc_tangent_spaces(mesh, smooth_vertex_coords, tangent_spaces, nullptr, nullptr);
|
2015-03-29 04:44:05 +11:00
|
|
|
|
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
|
|
|
copy_vn_fl(&csmd->delta_cache.deltas[0][0], int(corner_verts.size()) * 3, 0.0f);
|
2015-03-29 04:44:05 +11:00
|
|
|
|
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
|
|
|
for (l_index = 0; l_index < corner_verts.size(); l_index++) {
|
|
|
|
|
const int v_index = corner_verts[l_index];
|
2022-04-27 11:24:25 +10:00
|
|
|
float delta[3];
|
|
|
|
|
sub_v3_v3v3(delta, rest_coords[v_index], smooth_vertex_coords[v_index]);
|
2015-03-29 04:44:05 +11:00
|
|
|
|
2022-04-27 11:24:25 +10:00
|
|
|
float imat[3][3];
|
|
|
|
|
if (UNLIKELY(!invert_m3_m3(imat, tangent_spaces[l_index]))) {
|
|
|
|
|
transpose_m3_m3(imat, tangent_spaces[l_index]);
|
2015-03-29 04:44:05 +11:00
|
|
|
}
|
2022-04-27 11:24:25 +10:00
|
|
|
mul_v3_m3v3(csmd->delta_cache.deltas[l_index], imat, delta);
|
2015-03-29 04:44:05 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MEM_freeN(tangent_spaces);
|
|
|
|
|
MEM_freeN(smooth_vertex_coords);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void correctivesmooth_modifier_do(ModifierData *md,
|
2019-04-04 14:42:33 +02:00
|
|
|
Depsgraph *depsgraph,
|
|
|
|
|
Object *ob,
|
|
|
|
|
Mesh *mesh,
|
2015-03-29 04:44:05 +11:00
|
|
|
float (*vertexCos)[3],
|
2022-03-28 12:29:47 +11:00
|
|
|
uint verts_num,
|
2023-01-19 15:54:47 -06:00
|
|
|
BMEditMesh *em)
|
2015-03-29 04:44:05 +11:00
|
|
|
{
|
|
|
|
|
CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)md;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
const bool force_delta_cache_update =
|
2022-01-23 22:34:56 -06:00
|
|
|
/* XXX, take care! if mesh data itself changes we need to forcefully recalculate deltas */
|
2019-09-25 16:45:05 +02:00
|
|
|
!cache_settings_equal(csmd) ||
|
2015-03-29 04:44:05 +11:00
|
|
|
((csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_ORCO) &&
|
2018-12-06 17:52:37 +01:00
|
|
|
(((ID *)ob->data)->recalc & ID_RECALC_ALL));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
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
|
|
|
blender::Span<int> corner_verts = mesh->corner_verts();
|
2022-04-27 11:24:25 +10:00
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
bool use_only_smooth = (csmd->flag & MOD_CORRECTIVESMOOTH_ONLY_SMOOTH) != 0;
|
2023-01-19 15:54:47 -06:00
|
|
|
const MDeformVert *dvert = nullptr;
|
2015-03-29 04:44:05 +11:00
|
|
|
int defgrp_index;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-06-29 19:02:19 +02:00
|
|
|
MOD_get_vgroup(ob, mesh, csmd->defgrp_name, &dvert, &defgrp_index);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
/* if rest bind_coords not are defined, set them (only run during bind) */
|
|
|
|
|
if ((csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) &&
|
|
|
|
|
/* signal to recalculate, whoever sets MUST also free bind coords */
|
2023-01-20 13:22:00 +11:00
|
|
|
(csmd->bind_coords_num == uint(-1)))
|
|
|
|
|
{
|
2019-04-04 14:42:33 +02:00
|
|
|
if (DEG_is_active(depsgraph)) {
|
2023-01-19 15:54:47 -06:00
|
|
|
BLI_assert(csmd->bind_coords == nullptr);
|
|
|
|
|
csmd->bind_coords = static_cast<float(*)[3]>(MEM_dupallocN(vertexCos));
|
2022-03-28 12:29:47 +11:00
|
|
|
csmd->bind_coords_num = verts_num;
|
2023-01-19 15:54:47 -06:00
|
|
|
BLI_assert(csmd->bind_coords != nullptr);
|
2019-04-04 14:42:33 +02:00
|
|
|
/* Copy bound data to the original modifier. */
|
|
|
|
|
CorrectiveSmoothModifierData *csmd_orig = (CorrectiveSmoothModifierData *)
|
2022-02-02 12:20:03 +01:00
|
|
|
BKE_modifier_get_original(ob, &csmd->modifier);
|
2023-01-19 15:54:47 -06:00
|
|
|
csmd_orig->bind_coords = static_cast<float(*)[3]>(MEM_dupallocN(csmd->bind_coords));
|
2019-04-04 14:42:33 +02:00
|
|
|
csmd_orig->bind_coords_num = csmd->bind_coords_num;
|
|
|
|
|
}
|
|
|
|
|
else {
|
2020-10-26 17:07:58 +11:00
|
|
|
BKE_modifier_set_error(ob, md, "Attempt to bind from inactive dependency graph");
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-04-04 14:42:33 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
if (UNLIKELY(use_only_smooth)) {
|
2022-03-28 12:29:47 +11:00
|
|
|
smooth_verts(csmd, mesh, dvert, defgrp_index, vertexCos, verts_num);
|
2015-03-29 04:44:05 +11:00
|
|
|
return;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-01-19 15:54:47 -06:00
|
|
|
if ((csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) &&
|
|
|
|
|
(csmd->bind_coords == nullptr)) {
|
2020-10-26 17:07:58 +11:00
|
|
|
BKE_modifier_set_error(ob, md, "Bind data required");
|
2015-03-29 04:44:05 +11:00
|
|
|
goto error;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
/* If the number of verts has changed, the bind is invalid, so we do nothing */
|
|
|
|
|
if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) {
|
2022-03-28 12:29:47 +11:00
|
|
|
if (csmd->bind_coords_num != verts_num) {
|
2020-05-08 10:14:02 +02:00
|
|
|
BKE_modifier_set_error(
|
2022-03-28 12:29:47 +11:00
|
|
|
ob, md, "Bind vertex count mismatch: %u to %u", csmd->bind_coords_num, verts_num);
|
2015-03-29 04:44:05 +11:00
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* MOD_CORRECTIVESMOOTH_RESTSOURCE_ORCO */
|
|
|
|
|
if (ob->type != OB_MESH) {
|
2020-10-26 17:07:58 +11:00
|
|
|
BKE_modifier_set_error(ob, md, "Object is not a mesh");
|
2015-03-29 04:44:05 +11:00
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
else {
|
2023-01-20 13:22:00 +11:00
|
|
|
uint me_numVerts = uint((em) ? em->bm->totvert : ((Mesh *)ob->data)->totvert);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-03-28 12:29:47 +11:00
|
|
|
if (me_numVerts != verts_num) {
|
2020-05-08 19:02:03 +10:00
|
|
|
BKE_modifier_set_error(
|
2022-03-28 12:29:47 +11:00
|
|
|
ob, md, "Original vertex count mismatch: %u to %u", me_numVerts, verts_num);
|
2015-03-29 04:44:05 +11:00
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
/* check to see if our deltas are still valid */
|
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
|
|
|
if (!csmd->delta_cache.deltas || (csmd->delta_cache.deltas_num != corner_verts.size()) ||
|
2019-09-25 16:45:05 +02:00
|
|
|
force_delta_cache_update)
|
|
|
|
|
{
|
2015-03-29 04:44:05 +11:00
|
|
|
const float(*rest_coords)[3];
|
|
|
|
|
bool is_rest_coords_alloc = false;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-09-25 16:45:05 +02:00
|
|
|
store_cache_settings(csmd);
|
|
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) {
|
|
|
|
|
/* caller needs to do sanity check here */
|
2022-03-28 12:29:47 +11:00
|
|
|
csmd->bind_coords_num = verts_num;
|
2019-08-22 06:28:35 +10:00
|
|
|
rest_coords = csmd->bind_coords;
|
2015-03-29 04:44:05 +11:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
int me_numVerts;
|
2023-05-25 22:12:11 +02:00
|
|
|
if (em) {
|
|
|
|
|
rest_coords = BKE_editmesh_vert_coords_alloc_orco(em, &me_numVerts);
|
|
|
|
|
is_rest_coords_alloc = true;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
const Mesh *me = static_cast<const Mesh *>(ob->data);
|
2023-06-14 11:59:32 -04:00
|
|
|
rest_coords = reinterpret_cast<const float(*)[3]>(me->vert_positions().data());
|
2023-05-25 22:12:11 +02:00
|
|
|
me_numVerts = me->totvert;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-06-10 16:30:58 +10:00
|
|
|
BLI_assert(uint(me_numVerts) == verts_num);
|
2015-03-29 04:44:05 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG_TIME
|
|
|
|
|
TIMEIT_START(corrective_smooth_deltas);
|
|
|
|
|
#endif
|
|
|
|
|
|
2022-03-28 12:29:47 +11:00
|
|
|
calc_deltas(csmd, mesh, dvert, defgrp_index, rest_coords, verts_num);
|
2015-03-29 04:44:05 +11:00
|
|
|
|
|
|
|
|
#ifdef DEBUG_TIME
|
|
|
|
|
TIMEIT_END(corrective_smooth_deltas);
|
|
|
|
|
#endif
|
|
|
|
|
if (is_rest_coords_alloc) {
|
|
|
|
|
MEM_freeN((void *)rest_coords);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) {
|
|
|
|
|
/* this could be a check, but at this point it _must_ be valid */
|
2022-03-28 12:29:47 +11:00
|
|
|
BLI_assert(csmd->bind_coords_num == verts_num && csmd->delta_cache.deltas);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2015-03-29 04:44:05 +11:00
|
|
|
|
|
|
|
|
#ifdef DEBUG_TIME
|
|
|
|
|
TIMEIT_START(corrective_smooth);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* do the actual delta mush */
|
2022-03-28 12:29:47 +11:00
|
|
|
smooth_verts(csmd, mesh, dvert, defgrp_index, vertexCos, verts_num);
|
2015-03-29 04:44:05 +11:00
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
2020-03-10 12:47:43 +01:00
|
|
|
const float scale = csmd->scale;
|
2015-03-29 04:44:05 +11:00
|
|
|
|
2023-01-19 15:54:47 -06:00
|
|
|
float(*tangent_spaces)[3][3] = static_cast<float(*)[3][3]>(
|
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
|
|
|
MEM_malloc_arrayN(size_t(corner_verts.size()), sizeof(float[3][3]), __func__));
|
2023-01-19 15:54:47 -06:00
|
|
|
float *tangent_weights = static_cast<float *>(
|
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
|
|
|
MEM_malloc_arrayN(size_t(corner_verts.size()), sizeof(float), __func__));
|
2023-01-19 15:54:47 -06:00
|
|
|
float *tangent_weights_per_vertex = static_cast<float *>(
|
|
|
|
|
MEM_malloc_arrayN(verts_num, sizeof(float), __func__));
|
2015-03-29 04:44:05 +11:00
|
|
|
|
2022-04-27 11:24:25 +10:00
|
|
|
calc_tangent_spaces(
|
|
|
|
|
mesh, vertexCos, tangent_spaces, tangent_weights, tangent_weights_per_vertex);
|
2015-03-29 04:44:05 +11:00
|
|
|
|
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
|
|
|
for (const int64_t l_index : corner_verts.index_range()) {
|
|
|
|
|
const int v_index = corner_verts[l_index];
|
2022-04-27 11:24:25 +10:00
|
|
|
const float weight = tangent_weights[l_index] / tangent_weights_per_vertex[v_index];
|
|
|
|
|
if (UNLIKELY(!(weight > 0.0f))) {
|
|
|
|
|
/* Catches zero & divide by zero. */
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2015-03-29 04:44:05 +11:00
|
|
|
|
2022-04-27 11:24:25 +10:00
|
|
|
float delta[3];
|
|
|
|
|
mul_v3_m3v3(delta, tangent_spaces[l_index], csmd->delta_cache.deltas[l_index]);
|
|
|
|
|
mul_v3_fl(delta, weight);
|
|
|
|
|
madd_v3_v3fl(vertexCos[v_index], delta, scale);
|
2015-03-29 04:44:05 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MEM_freeN(tangent_spaces);
|
2022-04-27 11:24:25 +10:00
|
|
|
MEM_freeN(tangent_weights);
|
|
|
|
|
MEM_freeN(tangent_weights_per_vertex);
|
2015-03-29 04:44:05 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG_TIME
|
|
|
|
|
TIMEIT_END(corrective_smooth);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* when the modifier fails to execute */
|
|
|
|
|
error:
|
2019-09-25 16:45:05 +02:00
|
|
|
MEM_SAFE_FREE(csmd->delta_cache.deltas);
|
2022-04-27 11:24:25 +10:00
|
|
|
csmd->delta_cache.deltas_num = 0;
|
2015-03-29 04:44:05 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void deformVerts(ModifierData *md,
|
2018-05-11 11:20:44 +02:00
|
|
|
const ModifierEvalContext *ctx,
|
|
|
|
|
Mesh *mesh,
|
2018-05-01 17:33:04 +02:00
|
|
|
float (*vertexCos)[3],
|
2022-03-28 12:29:47 +11:00
|
|
|
int verts_num)
|
2015-03-29 04:44:05 +11:00
|
|
|
{
|
2019-04-04 14:42:33 +02:00
|
|
|
correctivesmooth_modifier_do(
|
2023-07-07 13:07:15 +02:00
|
|
|
md, ctx->depsgraph, ctx->object, mesh, vertexCos, uint(verts_num), nullptr);
|
2015-03-29 04:44:05 +11:00
|
|
|
}
|
|
|
|
|
|
2023-01-19 15:54:47 -06:00
|
|
|
static void panel_draw(const bContext * /*C*/, Panel *panel)
|
2020-06-05 10:41:03 -04:00
|
|
|
{
|
|
|
|
|
uiLayout *layout = panel->layout;
|
|
|
|
|
|
|
|
|
|
PointerRNA ob_ptr;
|
2020-09-02 14:13:26 -05:00
|
|
|
PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr);
|
2020-06-05 10:41:03 -04:00
|
|
|
|
|
|
|
|
uiLayoutSetPropSep(layout, true);
|
|
|
|
|
|
2020-09-02 14:13:26 -05:00
|
|
|
uiItemR(layout, ptr, "factor", 0, IFACE_("Factor"), ICON_NONE);
|
2023-01-19 15:54:47 -06:00
|
|
|
uiItemR(layout, ptr, "iterations", 0, nullptr, ICON_NONE);
|
|
|
|
|
uiItemR(layout, ptr, "scale", 0, nullptr, ICON_NONE);
|
|
|
|
|
uiItemR(layout, ptr, "smooth_type", 0, nullptr, ICON_NONE);
|
2020-06-05 10:41:03 -04:00
|
|
|
|
2023-01-19 15:54:47 -06:00
|
|
|
modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", nullptr);
|
2020-06-05 10:41:03 -04:00
|
|
|
|
2023-01-19 15:54:47 -06:00
|
|
|
uiItemR(layout, ptr, "use_only_smooth", 0, nullptr, ICON_NONE);
|
|
|
|
|
uiItemR(layout, ptr, "use_pin_boundary", 0, nullptr, ICON_NONE);
|
2020-06-05 10:41:03 -04:00
|
|
|
|
2023-01-19 15:54:47 -06:00
|
|
|
uiItemR(layout, ptr, "rest_source", 0, nullptr, ICON_NONE);
|
2020-09-02 14:13:26 -05:00
|
|
|
if (RNA_enum_get(ptr, "rest_source") == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) {
|
2020-06-05 10:41:03 -04:00
|
|
|
uiItemO(layout,
|
2020-09-02 14:13:26 -05:00
|
|
|
(RNA_boolean_get(ptr, "is_bind") ? IFACE_("Unbind") : IFACE_("Bind")),
|
2020-06-05 10:41:03 -04:00
|
|
|
ICON_NONE,
|
|
|
|
|
"OBJECT_OT_correctivesmooth_bind");
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-02 14:13:26 -05:00
|
|
|
modifier_panel_end(layout, ptr);
|
2020-06-05 10:41:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void panelRegister(ARegionType *region_type)
|
|
|
|
|
{
|
|
|
|
|
modifier_panel_register(region_type, eModifierType_CorrectiveSmooth, panel_draw);
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-16 16:53:26 +02:00
|
|
|
static void blendWrite(BlendWriter *writer, const ID *id_owner, const ModifierData *md)
|
2020-06-23 16:42:00 +02:00
|
|
|
{
|
2022-05-16 16:53:26 +02:00
|
|
|
CorrectiveSmoothModifierData csmd = *(const CorrectiveSmoothModifierData *)md;
|
2022-06-07 15:29:01 +02:00
|
|
|
const bool is_undo = BLO_write_is_undo(writer);
|
2022-05-16 16:53:26 +02:00
|
|
|
|
2022-06-07 15:29:01 +02:00
|
|
|
if (ID_IS_OVERRIDE_LIBRARY(id_owner) && !is_undo) {
|
2022-05-16 16:53:26 +02:00
|
|
|
BLI_assert(!ID_IS_LINKED(id_owner));
|
|
|
|
|
const bool is_local = (md->flag & eModifierFlag_OverrideLibrary_Local) != 0;
|
|
|
|
|
if (!is_local) {
|
2022-05-17 15:34:02 +10:00
|
|
|
/* Modifier coming from linked data cannot be bound from an override, so we can remove all
|
|
|
|
|
* binding data, can save a significant amount of memory. */
|
2022-05-16 16:53:26 +02:00
|
|
|
csmd.bind_coords_num = 0;
|
2023-01-19 15:54:47 -06:00
|
|
|
csmd.bind_coords = nullptr;
|
2022-05-16 16:53:26 +02:00
|
|
|
}
|
|
|
|
|
}
|
2020-06-23 16:42:00 +02:00
|
|
|
|
2022-05-16 16:53:26 +02:00
|
|
|
BLO_write_struct_at_address(writer, CorrectiveSmoothModifierData, md, &csmd);
|
2022-05-16 16:00:00 +02:00
|
|
|
|
2023-01-19 15:54:47 -06:00
|
|
|
if (csmd.bind_coords != nullptr) {
|
2022-05-16 16:53:26 +02:00
|
|
|
BLO_write_float3_array(writer, csmd.bind_coords_num, (float *)csmd.bind_coords);
|
2020-06-23 16:42:00 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void blendRead(BlendDataReader *reader, ModifierData *md)
|
|
|
|
|
{
|
|
|
|
|
CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)md;
|
|
|
|
|
|
|
|
|
|
if (csmd->bind_coords) {
|
2023-01-19 15:54:47 -06:00
|
|
|
BLO_read_float3_array(reader, int(csmd->bind_coords_num), (float **)&csmd->bind_coords);
|
2020-06-23 16:42:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* runtime only */
|
2023-01-19 15:54:47 -06:00
|
|
|
csmd->delta_cache.deltas = nullptr;
|
2022-04-27 11:24:25 +10:00
|
|
|
csmd->delta_cache.deltas_num = 0;
|
2020-06-23 16:42:00 +02:00
|
|
|
}
|
|
|
|
|
|
2015-03-29 04:44:05 +11:00
|
|
|
ModifierTypeInfo modifierType_CorrectiveSmooth = {
|
2023-01-16 12:41:11 +11:00
|
|
|
/*name*/ N_("CorrectiveSmooth"),
|
|
|
|
|
/*structName*/ "CorrectiveSmoothModifierData",
|
|
|
|
|
/*structSize*/ sizeof(CorrectiveSmoothModifierData),
|
|
|
|
|
/*srna*/ &RNA_CorrectiveSmoothModifier,
|
|
|
|
|
/*type*/ eModifierTypeType_OnlyDeform,
|
|
|
|
|
/*flags*/ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode,
|
|
|
|
|
/*icon*/ ICON_MOD_SMOOTH,
|
|
|
|
|
|
|
|
|
|
/*copyData*/ copyData,
|
|
|
|
|
|
|
|
|
|
/*deformVerts*/ deformVerts,
|
2023-01-19 15:54:47 -06:00
|
|
|
/*deformMatrices*/ nullptr,
|
2023-07-07 13:07:15 +02:00
|
|
|
/*deformVertsEM*/ nullptr,
|
2023-01-19 15:54:47 -06:00
|
|
|
/*deformMatricesEM*/ nullptr,
|
|
|
|
|
/*modifyMesh*/ nullptr,
|
|
|
|
|
/*modifyGeometrySet*/ nullptr,
|
2023-01-16 12:41:11 +11:00
|
|
|
|
|
|
|
|
/*initData*/ initData,
|
|
|
|
|
/*requiredDataMask*/ requiredDataMask,
|
|
|
|
|
/*freeData*/ freeData,
|
2023-01-19 15:54:47 -06:00
|
|
|
/*isDisabled*/ nullptr,
|
|
|
|
|
/*updateDepsgraph*/ nullptr,
|
|
|
|
|
/*dependsOnTime*/ nullptr,
|
|
|
|
|
/*dependsOnNormals*/ nullptr,
|
|
|
|
|
/*foreachIDLink*/ nullptr,
|
|
|
|
|
/*foreachTexLink*/ nullptr,
|
|
|
|
|
/*freeRuntimeData*/ nullptr,
|
2023-01-16 12:41:11 +11:00
|
|
|
/*panelRegister*/ panelRegister,
|
|
|
|
|
/*blendWrite*/ blendWrite,
|
|
|
|
|
/*blendRead*/ blendRead,
|
2015-03-29 04:44:05 +11:00
|
|
|
};
|