2023-08-16 00:20:26 +10:00
|
|
|
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
2023-05-31 16:19:06 +02:00
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2018-05-08 17:44:54 +02:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup bke
|
2018-05-08 17:44:54 +02:00
|
|
|
*/
|
|
|
|
|
|
2019-02-01 12:44:19 +11:00
|
|
|
#include "CLG_log.h"
|
2018-05-08 19:09:35 +02:00
|
|
|
|
2018-05-08 17:44:54 +02:00
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "DNA_curve_types.h"
|
2018-06-01 17:05:21 +02:00
|
|
|
#include "DNA_key_types.h"
|
2018-05-08 17:44:54 +02:00
|
|
|
#include "DNA_material_types.h"
|
|
|
|
|
#include "DNA_meta_types.h"
|
|
|
|
|
#include "DNA_object_types.h"
|
2020-04-09 18:49:40 +02:00
|
|
|
#include "DNA_pointcloud_types.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "DNA_scene_types.h"
|
2018-05-08 17:44:54 +02:00
|
|
|
|
Refactor: Move normals out of MVert, lazy calculation
As described in T91186, this commit moves mesh vertex normals into a
contiguous array of float vectors in a custom data layer, how face
normals are currently stored.
The main interface is documented in `BKE_mesh.h`. Vertex and face
normals are now calculated on-demand and cached, retrieved with an
"ensure" function. Since the logical state of a mesh is now "has
normals when necessary", they can be retrieved from a `const` mesh.
The goal is to use on-demand calculation for all derived data, but
leave room for eager calculation for performance purposes (modifier
evaluation is threaded, but viewport data generation is not).
**Benefits**
This moves us closer to a SoA approach rather than the current AoS
paradigm. Accessing a contiguous `float3` is much more efficient than
retrieving data from a larger struct. The memory requirements for
accessing only normals or vertex locations are smaller, and at the
cost of more memory usage for just normals, they now don't have to
be converted between float and short, which also simplifies code
In the future, the remaining items can be removed from `MVert`,
leaving only `float3`, which has similar benefits (see T93602).
Removing the combination of derived and original data makes it
conceptually simpler to only calculate normals when necessary.
This is especially important now that we have more opportunities
for temporary meshes in geometry nodes.
**Performance**
In addition to the theoretical future performance improvements by
making `MVert == float3`, I've done some basic performance testing
on this patch directly. The data is fairly rough, but it gives an idea
about where things stand generally.
- Mesh line primitive 4m Verts: 1.16x faster (36 -> 31 ms),
showing that accessing just `MVert` is now more efficient.
- Spring Splash Screen: 1.03-1.06 -> 1.06-1.11 FPS, a very slight
change that at least shows there is no regression.
- Sprite Fright Snail Smoosh: 3.30-3.40 -> 3.42-3.50 FPS, a small
but observable speedup.
- Set Position Node with Scaled Normal: 1.36x faster (53 -> 39 ms),
shows that using normals in geometry nodes is faster.
- Normal Calculation 1.6m Vert Cube: 1.19x faster (25 -> 21 ms),
shows that calculating normals is slightly faster now.
- File Size of 1.6m Vert Cube: 1.03x smaller (214.7 -> 208.4 MB),
Normals are not saved in files, which can help with large meshes.
As for memory usage, it may be slightly more in some cases, but
I didn't observe any difference in the production files I tested.
**Tests**
Some modifiers and cycles test results need to be updated with this
commit, for two reasons:
- The subdivision surface modifier is not responsible for calculating
normals anymore. In master, the modifier creates different normals
than the result of the `Mesh` normal calculation, so this is a bug
fix.
- There are small differences in the results of some modifiers that
use normals because they are not converted to and from `short`
anymore.
**Future improvements**
- Remove `ModifierTypeInfo::dependsOnNormals`. Code in each modifier
already retrieves normals if they are needed anyway.
- Copy normals as part of a better CoW system for attributes.
- Make more areas use lazy instead of eager normal calculation.
- Remove `BKE_mesh_normals_tag_dirty` in more places since that is
now the default state of a new mesh.
- Possibly apply a similar change to derived face corner normals.
Differential Revision: https://developer.blender.org/D12770
2022-01-13 14:37:58 -06:00
|
|
|
#include "BLI_index_range.hh"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_listbase.h"
|
2022-08-11 13:09:55 -04:00
|
|
|
#include "BLI_span.hh"
|
2019-05-16 17:59:45 +02:00
|
|
|
#include "BLI_string.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_utildefines.h"
|
2018-05-08 17:44:54 +02:00
|
|
|
|
2024-02-09 18:59:42 +01:00
|
|
|
#include "BLT_translation.hh"
|
2022-12-16 09:47:21 +09:00
|
|
|
|
2022-04-15 10:14:54 -05:00
|
|
|
#include "BKE_curves.hh"
|
2024-01-29 18:57:16 -05:00
|
|
|
#include "BKE_deform.hh"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_displist.h"
|
2023-11-16 11:41:55 +01:00
|
|
|
#include "BKE_editmesh.hh"
|
2021-09-23 11:41:46 -05:00
|
|
|
#include "BKE_geometry_set.hh"
|
2023-05-30 14:33:00 -04:00
|
|
|
#include "BKE_geometry_set_instances.hh"
|
2024-01-30 14:42:07 -05:00
|
|
|
#include "BKE_key.hh"
|
2024-01-15 12:44:04 -05:00
|
|
|
#include "BKE_lib_id.hh"
|
2024-01-18 12:20:42 +01:00
|
|
|
#include "BKE_lib_query.hh"
|
2023-12-01 19:43:16 +01:00
|
|
|
#include "BKE_main.hh"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_material.h"
|
2024-01-24 11:33:47 -05:00
|
|
|
#include "BKE_mball.hh"
|
2023-03-12 22:29:15 +01:00
|
|
|
#include "BKE_mesh.hh"
|
2023-08-02 22:14:18 +02:00
|
|
|
#include "BKE_mesh_runtime.hh"
|
|
|
|
|
#include "BKE_mesh_wrapper.hh"
|
2023-11-14 09:30:40 +01:00
|
|
|
#include "BKE_modifier.hh"
|
2023-11-15 18:46:07 +01:00
|
|
|
#include "BKE_object_types.hh"
|
2018-05-08 19:09:35 +02:00
|
|
|
/* these 2 are only used by conversion functions */
|
2023-11-16 11:41:55 +01:00
|
|
|
#include "BKE_curve.hh"
|
2018-05-08 17:44:54 +02:00
|
|
|
/* -- */
|
2023-10-09 23:41:53 +02:00
|
|
|
#include "BKE_object.hh"
|
2020-04-09 18:49:40 +02:00
|
|
|
/* -- */
|
2024-01-11 10:54:47 +01:00
|
|
|
#include "BKE_pointcloud.hh"
|
2018-05-08 17:44:54 +02:00
|
|
|
|
2021-09-23 11:41:46 -05:00
|
|
|
#include "BKE_curve_to_mesh.hh"
|
|
|
|
|
|
2023-09-22 03:18:17 +02:00
|
|
|
#include "DEG_depsgraph.hh"
|
|
|
|
|
#include "DEG_depsgraph_query.hh"
|
2018-05-08 17:44:54 +02:00
|
|
|
|
2022-09-09 08:24:31 -05:00
|
|
|
using blender::float3;
|
Refactor: Move normals out of MVert, lazy calculation
As described in T91186, this commit moves mesh vertex normals into a
contiguous array of float vectors in a custom data layer, how face
normals are currently stored.
The main interface is documented in `BKE_mesh.h`. Vertex and face
normals are now calculated on-demand and cached, retrieved with an
"ensure" function. Since the logical state of a mesh is now "has
normals when necessary", they can be retrieved from a `const` mesh.
The goal is to use on-demand calculation for all derived data, but
leave room for eager calculation for performance purposes (modifier
evaluation is threaded, but viewport data generation is not).
**Benefits**
This moves us closer to a SoA approach rather than the current AoS
paradigm. Accessing a contiguous `float3` is much more efficient than
retrieving data from a larger struct. The memory requirements for
accessing only normals or vertex locations are smaller, and at the
cost of more memory usage for just normals, they now don't have to
be converted between float and short, which also simplifies code
In the future, the remaining items can be removed from `MVert`,
leaving only `float3`, which has similar benefits (see T93602).
Removing the combination of derived and original data makes it
conceptually simpler to only calculate normals when necessary.
This is especially important now that we have more opportunities
for temporary meshes in geometry nodes.
**Performance**
In addition to the theoretical future performance improvements by
making `MVert == float3`, I've done some basic performance testing
on this patch directly. The data is fairly rough, but it gives an idea
about where things stand generally.
- Mesh line primitive 4m Verts: 1.16x faster (36 -> 31 ms),
showing that accessing just `MVert` is now more efficient.
- Spring Splash Screen: 1.03-1.06 -> 1.06-1.11 FPS, a very slight
change that at least shows there is no regression.
- Sprite Fright Snail Smoosh: 3.30-3.40 -> 3.42-3.50 FPS, a small
but observable speedup.
- Set Position Node with Scaled Normal: 1.36x faster (53 -> 39 ms),
shows that using normals in geometry nodes is faster.
- Normal Calculation 1.6m Vert Cube: 1.19x faster (25 -> 21 ms),
shows that calculating normals is slightly faster now.
- File Size of 1.6m Vert Cube: 1.03x smaller (214.7 -> 208.4 MB),
Normals are not saved in files, which can help with large meshes.
As for memory usage, it may be slightly more in some cases, but
I didn't observe any difference in the production files I tested.
**Tests**
Some modifiers and cycles test results need to be updated with this
commit, for two reasons:
- The subdivision surface modifier is not responsible for calculating
normals anymore. In master, the modifier creates different normals
than the result of the `Mesh` normal calculation, so this is a bug
fix.
- There are small differences in the results of some modifiers that
use normals because they are not converted to and from `short`
anymore.
**Future improvements**
- Remove `ModifierTypeInfo::dependsOnNormals`. Code in each modifier
already retrieves normals if they are needed anyway.
- Copy normals as part of a better CoW system for attributes.
- Make more areas use lazy instead of eager normal calculation.
- Remove `BKE_mesh_normals_tag_dirty` in more places since that is
now the default state of a new mesh.
- Possibly apply a similar change to derived face corner normals.
Differential Revision: https://developer.blender.org/D12770
2022-01-13 14:37:58 -06:00
|
|
|
using blender::IndexRange;
|
2022-08-11 13:09:55 -04:00
|
|
|
using blender::MutableSpan;
|
|
|
|
|
using blender::Span;
|
2022-09-09 08:24:31 -05:00
|
|
|
using blender::StringRefNull;
|
Refactor: Move normals out of MVert, lazy calculation
As described in T91186, this commit moves mesh vertex normals into a
contiguous array of float vectors in a custom data layer, how face
normals are currently stored.
The main interface is documented in `BKE_mesh.h`. Vertex and face
normals are now calculated on-demand and cached, retrieved with an
"ensure" function. Since the logical state of a mesh is now "has
normals when necessary", they can be retrieved from a `const` mesh.
The goal is to use on-demand calculation for all derived data, but
leave room for eager calculation for performance purposes (modifier
evaluation is threaded, but viewport data generation is not).
**Benefits**
This moves us closer to a SoA approach rather than the current AoS
paradigm. Accessing a contiguous `float3` is much more efficient than
retrieving data from a larger struct. The memory requirements for
accessing only normals or vertex locations are smaller, and at the
cost of more memory usage for just normals, they now don't have to
be converted between float and short, which also simplifies code
In the future, the remaining items can be removed from `MVert`,
leaving only `float3`, which has similar benefits (see T93602).
Removing the combination of derived and original data makes it
conceptually simpler to only calculate normals when necessary.
This is especially important now that we have more opportunities
for temporary meshes in geometry nodes.
**Performance**
In addition to the theoretical future performance improvements by
making `MVert == float3`, I've done some basic performance testing
on this patch directly. The data is fairly rough, but it gives an idea
about where things stand generally.
- Mesh line primitive 4m Verts: 1.16x faster (36 -> 31 ms),
showing that accessing just `MVert` is now more efficient.
- Spring Splash Screen: 1.03-1.06 -> 1.06-1.11 FPS, a very slight
change that at least shows there is no regression.
- Sprite Fright Snail Smoosh: 3.30-3.40 -> 3.42-3.50 FPS, a small
but observable speedup.
- Set Position Node with Scaled Normal: 1.36x faster (53 -> 39 ms),
shows that using normals in geometry nodes is faster.
- Normal Calculation 1.6m Vert Cube: 1.19x faster (25 -> 21 ms),
shows that calculating normals is slightly faster now.
- File Size of 1.6m Vert Cube: 1.03x smaller (214.7 -> 208.4 MB),
Normals are not saved in files, which can help with large meshes.
As for memory usage, it may be slightly more in some cases, but
I didn't observe any difference in the production files I tested.
**Tests**
Some modifiers and cycles test results need to be updated with this
commit, for two reasons:
- The subdivision surface modifier is not responsible for calculating
normals anymore. In master, the modifier creates different normals
than the result of the `Mesh` normal calculation, so this is a bug
fix.
- There are small differences in the results of some modifiers that
use normals because they are not converted to and from `short`
anymore.
**Future improvements**
- Remove `ModifierTypeInfo::dependsOnNormals`. Code in each modifier
already retrieves normals if they are needed anyway.
- Copy normals as part of a better CoW system for attributes.
- Make more areas use lazy instead of eager normal calculation.
- Remove `BKE_mesh_normals_tag_dirty` in more places since that is
now the default state of a new mesh.
- Possibly apply a similar change to derived face corner normals.
Differential Revision: https://developer.blender.org/D12770
2022-01-13 14:37:58 -06:00
|
|
|
|
2019-02-01 12:44:19 +11:00
|
|
|
static CLG_LogRef LOG = {"bke.mesh_convert"};
|
|
|
|
|
|
2022-08-11 13:09:55 -04:00
|
|
|
static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispbase)
|
2018-05-08 17:44:54 +02:00
|
|
|
{
|
2023-07-09 20:00:17 -04:00
|
|
|
using namespace blender;
|
2022-08-31 09:09:01 -05:00
|
|
|
using namespace blender::bke;
|
2022-12-30 23:52:44 -05:00
|
|
|
int a, b, ofs;
|
2019-09-12 18:58:43 +10:00
|
|
|
const bool conv_polys = (
|
2021-09-23 15:02:10 +10:00
|
|
|
/* 2D polys are filled with #DispList.type == #DL_INDEX3. */
|
2019-09-12 18:58:43 +10:00
|
|
|
(CU_DO_2DFILL(cu) == false) ||
|
|
|
|
|
/* surf polys are never filled */
|
2021-07-19 21:19:59 -04:00
|
|
|
BKE_curve_type_get(cu) == OB_SURF);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-08 17:44:54 +02:00
|
|
|
/* count */
|
2022-12-30 23:52:44 -05:00
|
|
|
int totvert = 0;
|
|
|
|
|
int totedge = 0;
|
2023-07-24 22:06:55 +02:00
|
|
|
int faces_num = 0;
|
2022-12-30 23:52:44 -05:00
|
|
|
int totloop = 0;
|
2021-06-28 13:47:48 -05:00
|
|
|
LISTBASE_FOREACH (const DispList *, dl, dispbase) {
|
2018-05-08 17:44:54 +02:00
|
|
|
if (dl->type == DL_SEGM) {
|
|
|
|
|
totvert += dl->parts * dl->nr;
|
|
|
|
|
totedge += dl->parts * (dl->nr - 1);
|
|
|
|
|
}
|
|
|
|
|
else if (dl->type == DL_POLY) {
|
|
|
|
|
if (conv_polys) {
|
|
|
|
|
totvert += dl->parts * dl->nr;
|
|
|
|
|
totedge += dl->parts * dl->nr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (dl->type == DL_SURF) {
|
2020-07-30 17:37:35 +10:00
|
|
|
if (dl->parts != 0) {
|
|
|
|
|
int tot;
|
|
|
|
|
totvert += dl->parts * dl->nr;
|
|
|
|
|
tot = (((dl->flag & DL_CYCL_U) ? 1 : 0) + (dl->nr - 1)) *
|
|
|
|
|
(((dl->flag & DL_CYCL_V) ? 1 : 0) + (dl->parts - 1));
|
2023-07-24 22:06:55 +02:00
|
|
|
faces_num += tot;
|
2020-07-30 17:37:35 +10:00
|
|
|
totloop += tot * 4;
|
|
|
|
|
}
|
2018-05-08 17:44:54 +02:00
|
|
|
}
|
|
|
|
|
else if (dl->type == DL_INDEX3) {
|
|
|
|
|
int tot;
|
|
|
|
|
totvert += dl->nr;
|
|
|
|
|
tot = dl->parts;
|
2023-07-24 22:06:55 +02:00
|
|
|
faces_num += tot;
|
2018-05-08 17:44:54 +02:00
|
|
|
totloop += tot * 3;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-08 17:44:54 +02:00
|
|
|
if (totvert == 0) {
|
2023-02-27 11:09:26 -05:00
|
|
|
return BKE_mesh_new_nomain(0, 0, 0, 0);
|
2018-05-08 17:44:54 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-07-24 22:06:55 +02:00
|
|
|
Mesh *mesh = BKE_mesh_new_nomain(totvert, totedge, faces_num, totloop);
|
Mesh: Move positions to a generic attribute
**Changes**
As described in T93602, this patch removes all use of the `MVert`
struct, replacing it with a generic named attribute with the name
`"position"`, consistent with other geometry types.
Variable names have been changed from `verts` to `positions`, to align
with the attribute name and the more generic design (positions are not
vertices, they are just an attribute stored on the point domain).
This change is made possible by previous commits that moved all other
data out of `MVert` to runtime data or other generic attributes. What
remains is mostly a simple type change. Though, the type still shows up
859 times, so the patch is quite large.
One compromise is that now `CD_MASK_BAREMESH` now contains
`CD_PROP_FLOAT3`. With the general move towards generic attributes
over custom data types, we are removing use of these type masks anyway.
**Benefits**
The most obvious benefit is reduced memory usage and the benefits
that brings in memory-bound situations. `float3` is only 3 bytes, in
comparison to `MVert` which was 4. When there are millions of vertices
this starts to matter more.
The other benefits come from using a more generic type. Instead of
writing algorithms specifically for `MVert`, code can just use arrays
of vectors. This will allow eliminating many temporary arrays or
wrappers used to extract positions.
Many possible improvements aren't implemented in this patch, though
I did switch simplify or remove the process of creating temporary
position arrays in a few places.
The design clarity that "positions are just another attribute" brings
allows removing explicit copying of vertices in some procedural
operations-- they are just processed like most other attributes.
**Performance**
This touches so many areas that it's hard to benchmark exhaustively,
but I observed some areas as examples.
* The mesh line node with 4 million count was 1.5x (8ms to 12ms) faster.
* The Spring splash screen went from ~4.3 to ~4.5 fps.
* The subdivision surface modifier/node was slightly faster
RNA access through Python may be slightly slower, since now we need
a name lookup instead of just a custom data type lookup for each index.
**Future Improvements**
* Remove uses of "vert_coords" functions:
* `BKE_mesh_vert_coords_alloc`
* `BKE_mesh_vert_coords_get`
* `BKE_mesh_vert_coords_apply{_with_mat4}`
* Remove more hidden copying of positions
* General simplification now possible in many areas
* Convert more code to C++ to use `float3` instead of `float[3]`
* Currently `reinterpret_cast` is used for those C-API functions
Differential Revision: https://developer.blender.org/D15982
2023-01-10 00:10:43 -05:00
|
|
|
MutableSpan<float3> positions = mesh->vert_positions_for_write();
|
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
|
|
|
MutableSpan<blender::int2> edges = mesh->edges_for_write();
|
2023-07-24 22:06:55 +02:00
|
|
|
MutableSpan<int> face_offsets = mesh->face_offsets_for_write();
|
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
|
|
|
MutableSpan<int> corner_verts = mesh->corner_verts_for_write();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-07 21:41:39 -05:00
|
|
|
MutableAttributeAccessor attributes = mesh->attributes_for_write();
|
2022-08-31 09:09:01 -05:00
|
|
|
SpanAttributeWriter<int> material_indices = attributes.lookup_or_add_for_write_only_span<int>(
|
2023-12-20 13:13:16 -05:00
|
|
|
"material_index", AttrDomain::Face);
|
Mesh: Move face shade smooth flag to a generic attribute
Currently the shade smooth status for mesh faces is stored as part of
`MPoly::flag`. As described in #95967, this moves that information
to a separate boolean attribute. It also flips its status, so the
attribute is now called `sharp_face`, which mirrors the existing
`sharp_edge` attribute. The attribute doesn't need to be allocated
when all faces are smooth. Forward compatibility is kept until
4.0 like the other mesh refactors.
This will reduce memory bandwidth requirements for some operations,
since the array of booleans uses 12 times less memory than `MPoly`.
It also allows faces to be stored more efficiently in the future, since
the flag is now unused. It's also possible to use generic functions to
process the values. For example, finding whether there is a sharp face
is just `sharp_faces.contains(true)`.
The `shade_smooth` attribute is no longer accessible with geometry nodes.
Since there were dedicated accessor nodes for that data, that shouldn't
be a problem. That's difficult to version automatically since the named
attribute nodes could be used in arbitrary combinations.
**Implementation notes:**
- The attribute and array variables in the code use the `sharp_faces`
term, to be consistent with the user-facing "sharp faces" wording,
and to avoid requiring many renames when #101689 is implemented.
- Cycles now accesses smooth face status with the generic attribute,
to avoid overhead.
- Changing the zero-value from "smooth" to "flat" takes some care to
make sure defaults are the same.
- Versioning for the edge mode extrude node is particularly complex.
New nodes are added by versioning to propagate the attribute in its
old inverted state.
- A lot of access is still done through the `CustomData` API rather
than the attribute API because of a few functions. That can be
cleaned up easily in the future.
- In the future we would benefit from a way to store attributes as a
single value for when all faces are sharp.
Pull Request: https://projects.blender.org/blender/blender/pulls/104422
2023-03-08 15:36:18 +01:00
|
|
|
SpanAttributeWriter<bool> sharp_faces = attributes.lookup_or_add_for_write_span<bool>(
|
2023-12-20 13:13:16 -05:00
|
|
|
"sharp_face", AttrDomain::Face);
|
2023-07-09 20:00:17 -04:00
|
|
|
SpanAttributeWriter<float2> uv_attribute = attributes.lookup_or_add_for_write_span<float2>(
|
2023-12-20 13:13:16 -05:00
|
|
|
DATA_("UVMap"), AttrDomain::Corner);
|
2023-07-09 20:00:17 -04:00
|
|
|
MutableSpan<float2> uv_map = uv_attribute.span;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-12-30 23:52:44 -05:00
|
|
|
int dst_vert = 0;
|
|
|
|
|
int dst_edge = 0;
|
|
|
|
|
int dst_poly = 0;
|
|
|
|
|
int dst_loop = 0;
|
2021-06-28 13:47:48 -05:00
|
|
|
LISTBASE_FOREACH (const DispList *, dl, dispbase) {
|
2018-05-08 17:44:54 +02:00
|
|
|
const bool is_smooth = (dl->rt & CU_SMOOTH) != 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-08 17:44:54 +02:00
|
|
|
if (dl->type == DL_SEGM) {
|
2022-12-30 23:52:44 -05:00
|
|
|
const int startvert = dst_vert;
|
2018-05-08 17:44:54 +02:00
|
|
|
a = dl->parts * dl->nr;
|
2022-12-30 23:52:44 -05:00
|
|
|
const float *data = dl->verts;
|
2018-05-08 17:44:54 +02:00
|
|
|
while (a--) {
|
Mesh: Move positions to a generic attribute
**Changes**
As described in T93602, this patch removes all use of the `MVert`
struct, replacing it with a generic named attribute with the name
`"position"`, consistent with other geometry types.
Variable names have been changed from `verts` to `positions`, to align
with the attribute name and the more generic design (positions are not
vertices, they are just an attribute stored on the point domain).
This change is made possible by previous commits that moved all other
data out of `MVert` to runtime data or other generic attributes. What
remains is mostly a simple type change. Though, the type still shows up
859 times, so the patch is quite large.
One compromise is that now `CD_MASK_BAREMESH` now contains
`CD_PROP_FLOAT3`. With the general move towards generic attributes
over custom data types, we are removing use of these type masks anyway.
**Benefits**
The most obvious benefit is reduced memory usage and the benefits
that brings in memory-bound situations. `float3` is only 3 bytes, in
comparison to `MVert` which was 4. When there are millions of vertices
this starts to matter more.
The other benefits come from using a more generic type. Instead of
writing algorithms specifically for `MVert`, code can just use arrays
of vectors. This will allow eliminating many temporary arrays or
wrappers used to extract positions.
Many possible improvements aren't implemented in this patch, though
I did switch simplify or remove the process of creating temporary
position arrays in a few places.
The design clarity that "positions are just another attribute" brings
allows removing explicit copying of vertices in some procedural
operations-- they are just processed like most other attributes.
**Performance**
This touches so many areas that it's hard to benchmark exhaustively,
but I observed some areas as examples.
* The mesh line node with 4 million count was 1.5x (8ms to 12ms) faster.
* The Spring splash screen went from ~4.3 to ~4.5 fps.
* The subdivision surface modifier/node was slightly faster
RNA access through Python may be slightly slower, since now we need
a name lookup instead of just a custom data type lookup for each index.
**Future Improvements**
* Remove uses of "vert_coords" functions:
* `BKE_mesh_vert_coords_alloc`
* `BKE_mesh_vert_coords_get`
* `BKE_mesh_vert_coords_apply{_with_mat4}`
* Remove more hidden copying of positions
* General simplification now possible in many areas
* Convert more code to C++ to use `float3` instead of `float[3]`
* Currently `reinterpret_cast` is used for those C-API functions
Differential Revision: https://developer.blender.org/D15982
2023-01-10 00:10:43 -05:00
|
|
|
copy_v3_v3(positions[dst_vert], data);
|
2018-05-08 17:44:54 +02:00
|
|
|
data += 3;
|
2022-12-30 23:52:44 -05:00
|
|
|
dst_vert++;
|
2018-05-08 17:44:54 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-08 17:44:54 +02:00
|
|
|
for (a = 0; a < dl->parts; a++) {
|
|
|
|
|
ofs = a * dl->nr;
|
|
|
|
|
for (b = 1; b < dl->nr; b++) {
|
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
|
|
|
edges[dst_edge][0] = startvert + ofs + b - 1;
|
|
|
|
|
edges[dst_edge][1] = startvert + ofs + b;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-12-30 23:52:44 -05:00
|
|
|
dst_edge++;
|
2018-05-08 17:44:54 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2018-05-08 17:44:54 +02:00
|
|
|
}
|
|
|
|
|
else if (dl->type == DL_POLY) {
|
|
|
|
|
if (conv_polys) {
|
2022-12-30 23:52:44 -05:00
|
|
|
const int startvert = dst_vert;
|
2018-05-08 17:44:54 +02:00
|
|
|
a = dl->parts * dl->nr;
|
2022-12-30 23:52:44 -05:00
|
|
|
const float *data = dl->verts;
|
2018-05-08 17:44:54 +02:00
|
|
|
while (a--) {
|
Mesh: Move positions to a generic attribute
**Changes**
As described in T93602, this patch removes all use of the `MVert`
struct, replacing it with a generic named attribute with the name
`"position"`, consistent with other geometry types.
Variable names have been changed from `verts` to `positions`, to align
with the attribute name and the more generic design (positions are not
vertices, they are just an attribute stored on the point domain).
This change is made possible by previous commits that moved all other
data out of `MVert` to runtime data or other generic attributes. What
remains is mostly a simple type change. Though, the type still shows up
859 times, so the patch is quite large.
One compromise is that now `CD_MASK_BAREMESH` now contains
`CD_PROP_FLOAT3`. With the general move towards generic attributes
over custom data types, we are removing use of these type masks anyway.
**Benefits**
The most obvious benefit is reduced memory usage and the benefits
that brings in memory-bound situations. `float3` is only 3 bytes, in
comparison to `MVert` which was 4. When there are millions of vertices
this starts to matter more.
The other benefits come from using a more generic type. Instead of
writing algorithms specifically for `MVert`, code can just use arrays
of vectors. This will allow eliminating many temporary arrays or
wrappers used to extract positions.
Many possible improvements aren't implemented in this patch, though
I did switch simplify or remove the process of creating temporary
position arrays in a few places.
The design clarity that "positions are just another attribute" brings
allows removing explicit copying of vertices in some procedural
operations-- they are just processed like most other attributes.
**Performance**
This touches so many areas that it's hard to benchmark exhaustively,
but I observed some areas as examples.
* The mesh line node with 4 million count was 1.5x (8ms to 12ms) faster.
* The Spring splash screen went from ~4.3 to ~4.5 fps.
* The subdivision surface modifier/node was slightly faster
RNA access through Python may be slightly slower, since now we need
a name lookup instead of just a custom data type lookup for each index.
**Future Improvements**
* Remove uses of "vert_coords" functions:
* `BKE_mesh_vert_coords_alloc`
* `BKE_mesh_vert_coords_get`
* `BKE_mesh_vert_coords_apply{_with_mat4}`
* Remove more hidden copying of positions
* General simplification now possible in many areas
* Convert more code to C++ to use `float3` instead of `float[3]`
* Currently `reinterpret_cast` is used for those C-API functions
Differential Revision: https://developer.blender.org/D15982
2023-01-10 00:10:43 -05:00
|
|
|
copy_v3_v3(positions[dst_vert], data);
|
2018-05-08 17:44:54 +02:00
|
|
|
data += 3;
|
2022-12-30 23:52:44 -05:00
|
|
|
dst_vert++;
|
2018-05-08 17:44:54 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-08 17:44:54 +02:00
|
|
|
for (a = 0; a < dl->parts; a++) {
|
|
|
|
|
ofs = a * dl->nr;
|
|
|
|
|
for (b = 0; b < dl->nr; b++) {
|
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
|
|
|
edges[dst_edge][0] = startvert + ofs + b;
|
2019-04-22 09:39:35 +10:00
|
|
|
if (b == dl->nr - 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
|
|
|
edges[dst_edge][1] = startvert + ofs;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
else {
|
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
|
|
|
edges[dst_edge][1] = startvert + ofs + b + 1;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2022-12-30 23:52:44 -05:00
|
|
|
dst_edge++;
|
2018-05-08 17:44:54 +02:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
2018-05-08 17:44:54 +02:00
|
|
|
else if (dl->type == DL_INDEX3) {
|
2022-12-30 23:52:44 -05:00
|
|
|
const int startvert = dst_vert;
|
2018-05-08 17:44:54 +02:00
|
|
|
a = dl->nr;
|
2022-12-30 23:52:44 -05:00
|
|
|
const float *data = dl->verts;
|
2018-05-08 17:44:54 +02:00
|
|
|
while (a--) {
|
Mesh: Move positions to a generic attribute
**Changes**
As described in T93602, this patch removes all use of the `MVert`
struct, replacing it with a generic named attribute with the name
`"position"`, consistent with other geometry types.
Variable names have been changed from `verts` to `positions`, to align
with the attribute name and the more generic design (positions are not
vertices, they are just an attribute stored on the point domain).
This change is made possible by previous commits that moved all other
data out of `MVert` to runtime data or other generic attributes. What
remains is mostly a simple type change. Though, the type still shows up
859 times, so the patch is quite large.
One compromise is that now `CD_MASK_BAREMESH` now contains
`CD_PROP_FLOAT3`. With the general move towards generic attributes
over custom data types, we are removing use of these type masks anyway.
**Benefits**
The most obvious benefit is reduced memory usage and the benefits
that brings in memory-bound situations. `float3` is only 3 bytes, in
comparison to `MVert` which was 4. When there are millions of vertices
this starts to matter more.
The other benefits come from using a more generic type. Instead of
writing algorithms specifically for `MVert`, code can just use arrays
of vectors. This will allow eliminating many temporary arrays or
wrappers used to extract positions.
Many possible improvements aren't implemented in this patch, though
I did switch simplify or remove the process of creating temporary
position arrays in a few places.
The design clarity that "positions are just another attribute" brings
allows removing explicit copying of vertices in some procedural
operations-- they are just processed like most other attributes.
**Performance**
This touches so many areas that it's hard to benchmark exhaustively,
but I observed some areas as examples.
* The mesh line node with 4 million count was 1.5x (8ms to 12ms) faster.
* The Spring splash screen went from ~4.3 to ~4.5 fps.
* The subdivision surface modifier/node was slightly faster
RNA access through Python may be slightly slower, since now we need
a name lookup instead of just a custom data type lookup for each index.
**Future Improvements**
* Remove uses of "vert_coords" functions:
* `BKE_mesh_vert_coords_alloc`
* `BKE_mesh_vert_coords_get`
* `BKE_mesh_vert_coords_apply{_with_mat4}`
* Remove more hidden copying of positions
* General simplification now possible in many areas
* Convert more code to C++ to use `float3` instead of `float[3]`
* Currently `reinterpret_cast` is used for those C-API functions
Differential Revision: https://developer.blender.org/D15982
2023-01-10 00:10:43 -05:00
|
|
|
copy_v3_v3(positions[dst_vert], data);
|
2018-05-08 17:44:54 +02:00
|
|
|
data += 3;
|
2022-12-30 23:52:44 -05:00
|
|
|
dst_vert++;
|
2018-05-08 17:44:54 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-08 17:44:54 +02:00
|
|
|
a = dl->parts;
|
2022-12-30 23:52:44 -05:00
|
|
|
const int *index = dl->index;
|
2018-05-08 17:44:54 +02:00
|
|
|
while (a--) {
|
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
|
|
|
corner_verts[dst_loop + 0] = startvert + index[0];
|
|
|
|
|
corner_verts[dst_loop + 1] = startvert + index[2];
|
|
|
|
|
corner_verts[dst_loop + 2] = startvert + index[1];
|
2023-07-24 22:06:55 +02:00
|
|
|
face_offsets[dst_poly] = dst_loop;
|
2022-12-30 23:52:44 -05:00
|
|
|
material_indices.span[dst_poly] = dl->col;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-07-09 20:00:17 -04:00
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
|
uv_map[dst_loop + i][0] = (corner_verts[dst_loop + i] - startvert) / float(dl->nr - 1);
|
|
|
|
|
uv_map[dst_loop + i][1] = 0.0f;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
Mesh: Move face shade smooth flag to a generic attribute
Currently the shade smooth status for mesh faces is stored as part of
`MPoly::flag`. As described in #95967, this moves that information
to a separate boolean attribute. It also flips its status, so the
attribute is now called `sharp_face`, which mirrors the existing
`sharp_edge` attribute. The attribute doesn't need to be allocated
when all faces are smooth. Forward compatibility is kept until
4.0 like the other mesh refactors.
This will reduce memory bandwidth requirements for some operations,
since the array of booleans uses 12 times less memory than `MPoly`.
It also allows faces to be stored more efficiently in the future, since
the flag is now unused. It's also possible to use generic functions to
process the values. For example, finding whether there is a sharp face
is just `sharp_faces.contains(true)`.
The `shade_smooth` attribute is no longer accessible with geometry nodes.
Since there were dedicated accessor nodes for that data, that shouldn't
be a problem. That's difficult to version automatically since the named
attribute nodes could be used in arbitrary combinations.
**Implementation notes:**
- The attribute and array variables in the code use the `sharp_faces`
term, to be consistent with the user-facing "sharp faces" wording,
and to avoid requiring many renames when #101689 is implemented.
- Cycles now accesses smooth face status with the generic attribute,
to avoid overhead.
- Changing the zero-value from "smooth" to "flat" takes some care to
make sure defaults are the same.
- Versioning for the edge mode extrude node is particularly complex.
New nodes are added by versioning to propagate the attribute in its
old inverted state.
- A lot of access is still done through the `CustomData` API rather
than the attribute API because of a few functions. That can be
cleaned up easily in the future.
- In the future we would benefit from a way to store attributes as a
single value for when all faces are sharp.
Pull Request: https://projects.blender.org/blender/blender/pulls/104422
2023-03-08 15:36:18 +01:00
|
|
|
sharp_faces.span[dst_poly] = !is_smooth;
|
2022-12-30 23:52:44 -05:00
|
|
|
dst_poly++;
|
|
|
|
|
dst_loop += 3;
|
2018-05-08 17:44:54 +02:00
|
|
|
index += 3;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2018-05-08 17:44:54 +02:00
|
|
|
else if (dl->type == DL_SURF) {
|
2022-12-30 23:52:44 -05:00
|
|
|
const int startvert = dst_vert;
|
2018-05-08 17:44:54 +02:00
|
|
|
a = dl->parts * dl->nr;
|
2022-12-30 23:52:44 -05:00
|
|
|
const float *data = dl->verts;
|
2018-05-08 17:44:54 +02:00
|
|
|
while (a--) {
|
Mesh: Move positions to a generic attribute
**Changes**
As described in T93602, this patch removes all use of the `MVert`
struct, replacing it with a generic named attribute with the name
`"position"`, consistent with other geometry types.
Variable names have been changed from `verts` to `positions`, to align
with the attribute name and the more generic design (positions are not
vertices, they are just an attribute stored on the point domain).
This change is made possible by previous commits that moved all other
data out of `MVert` to runtime data or other generic attributes. What
remains is mostly a simple type change. Though, the type still shows up
859 times, so the patch is quite large.
One compromise is that now `CD_MASK_BAREMESH` now contains
`CD_PROP_FLOAT3`. With the general move towards generic attributes
over custom data types, we are removing use of these type masks anyway.
**Benefits**
The most obvious benefit is reduced memory usage and the benefits
that brings in memory-bound situations. `float3` is only 3 bytes, in
comparison to `MVert` which was 4. When there are millions of vertices
this starts to matter more.
The other benefits come from using a more generic type. Instead of
writing algorithms specifically for `MVert`, code can just use arrays
of vectors. This will allow eliminating many temporary arrays or
wrappers used to extract positions.
Many possible improvements aren't implemented in this patch, though
I did switch simplify or remove the process of creating temporary
position arrays in a few places.
The design clarity that "positions are just another attribute" brings
allows removing explicit copying of vertices in some procedural
operations-- they are just processed like most other attributes.
**Performance**
This touches so many areas that it's hard to benchmark exhaustively,
but I observed some areas as examples.
* The mesh line node with 4 million count was 1.5x (8ms to 12ms) faster.
* The Spring splash screen went from ~4.3 to ~4.5 fps.
* The subdivision surface modifier/node was slightly faster
RNA access through Python may be slightly slower, since now we need
a name lookup instead of just a custom data type lookup for each index.
**Future Improvements**
* Remove uses of "vert_coords" functions:
* `BKE_mesh_vert_coords_alloc`
* `BKE_mesh_vert_coords_get`
* `BKE_mesh_vert_coords_apply{_with_mat4}`
* Remove more hidden copying of positions
* General simplification now possible in many areas
* Convert more code to C++ to use `float3` instead of `float[3]`
* Currently `reinterpret_cast` is used for those C-API functions
Differential Revision: https://developer.blender.org/D15982
2023-01-10 00:10:43 -05:00
|
|
|
copy_v3_v3(positions[dst_vert], data);
|
2018-05-08 17:44:54 +02:00
|
|
|
data += 3;
|
2022-12-30 23:52:44 -05:00
|
|
|
dst_vert++;
|
2018-05-08 17:44:54 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-08 17:44:54 +02:00
|
|
|
for (a = 0; a < dl->parts; a++) {
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if ((dl->flag & DL_CYCL_V) == 0 && a == dl->parts - 1) {
|
2018-05-08 17:44:54 +02:00
|
|
|
break;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-12-30 23:52:44 -05:00
|
|
|
int p1, p2, p3, p4;
|
2018-05-08 17:44:54 +02:00
|
|
|
if (dl->flag & DL_CYCL_U) { /* p2 -> p1 -> */
|
|
|
|
|
p1 = startvert + dl->nr * a; /* p4 -> p3 -> */
|
|
|
|
|
p2 = p1 + dl->nr - 1; /* -----> next row */
|
|
|
|
|
p3 = p1 + dl->nr;
|
|
|
|
|
p4 = p2 + dl->nr;
|
|
|
|
|
b = 0;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
p2 = startvert + dl->nr * a;
|
|
|
|
|
p1 = p2 + 1;
|
|
|
|
|
p4 = p2 + dl->nr;
|
|
|
|
|
p3 = p1 + dl->nr;
|
|
|
|
|
b = 1;
|
|
|
|
|
}
|
|
|
|
|
if ((dl->flag & DL_CYCL_V) && a == dl->parts - 1) {
|
|
|
|
|
p3 -= dl->parts * dl->nr;
|
|
|
|
|
p4 -= dl->parts * dl->nr;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-08 17:44:54 +02:00
|
|
|
for (; b < dl->nr; b++) {
|
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
|
|
|
corner_verts[dst_loop + 0] = p1;
|
|
|
|
|
corner_verts[dst_loop + 1] = p3;
|
|
|
|
|
corner_verts[dst_loop + 2] = p4;
|
|
|
|
|
corner_verts[dst_loop + 3] = p2;
|
2023-07-24 22:06:55 +02:00
|
|
|
face_offsets[dst_poly] = dst_loop;
|
2022-12-30 23:52:44 -05:00
|
|
|
material_indices.span[dst_poly] = dl->col;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-07-09 20:00:17 -04:00
|
|
|
int orco_sizeu = dl->nr - 1;
|
|
|
|
|
int orco_sizev = dl->parts - 1;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-07-09 20:00:17 -04:00
|
|
|
/* exception as handled in convertblender.c too */
|
|
|
|
|
if (dl->flag & DL_CYCL_U) {
|
|
|
|
|
orco_sizeu++;
|
|
|
|
|
if (dl->flag & DL_CYCL_V) {
|
2018-05-08 17:44:54 +02:00
|
|
|
orco_sizev++;
|
|
|
|
|
}
|
2023-07-09 20:00:17 -04:00
|
|
|
}
|
|
|
|
|
else if (dl->flag & DL_CYCL_V) {
|
|
|
|
|
orco_sizev++;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-07-09 20:00:17 -04:00
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
|
/* find uv based on vertex index into grid array */
|
|
|
|
|
int v = corner_verts[dst_loop + i] - startvert;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-07-09 20:00:17 -04:00
|
|
|
uv_map[dst_loop + i][0] = (v / dl->nr) / float(orco_sizev);
|
|
|
|
|
uv_map[dst_loop + i][1] = (v % dl->nr) / float(orco_sizeu);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-07-09 20:00:17 -04:00
|
|
|
/* cyclic correction */
|
|
|
|
|
if (ELEM(i, 1, 2) && uv_map[dst_loop + i][0] == 0.0f) {
|
|
|
|
|
uv_map[dst_loop + i][0] = 1.0f;
|
|
|
|
|
}
|
|
|
|
|
if (ELEM(i, 0, 1) && uv_map[dst_loop + i][1] == 0.0f) {
|
|
|
|
|
uv_map[dst_loop + i][1] = 1.0f;
|
2018-05-08 17:44:54 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
Mesh: Move face shade smooth flag to a generic attribute
Currently the shade smooth status for mesh faces is stored as part of
`MPoly::flag`. As described in #95967, this moves that information
to a separate boolean attribute. It also flips its status, so the
attribute is now called `sharp_face`, which mirrors the existing
`sharp_edge` attribute. The attribute doesn't need to be allocated
when all faces are smooth. Forward compatibility is kept until
4.0 like the other mesh refactors.
This will reduce memory bandwidth requirements for some operations,
since the array of booleans uses 12 times less memory than `MPoly`.
It also allows faces to be stored more efficiently in the future, since
the flag is now unused. It's also possible to use generic functions to
process the values. For example, finding whether there is a sharp face
is just `sharp_faces.contains(true)`.
The `shade_smooth` attribute is no longer accessible with geometry nodes.
Since there were dedicated accessor nodes for that data, that shouldn't
be a problem. That's difficult to version automatically since the named
attribute nodes could be used in arbitrary combinations.
**Implementation notes:**
- The attribute and array variables in the code use the `sharp_faces`
term, to be consistent with the user-facing "sharp faces" wording,
and to avoid requiring many renames when #101689 is implemented.
- Cycles now accesses smooth face status with the generic attribute,
to avoid overhead.
- Changing the zero-value from "smooth" to "flat" takes some care to
make sure defaults are the same.
- Versioning for the edge mode extrude node is particularly complex.
New nodes are added by versioning to propagate the attribute in its
old inverted state.
- A lot of access is still done through the `CustomData` API rather
than the attribute API because of a few functions. That can be
cleaned up easily in the future.
- In the future we would benefit from a way to store attributes as a
single value for when all faces are sharp.
Pull Request: https://projects.blender.org/blender/blender/pulls/104422
2023-03-08 15:36:18 +01:00
|
|
|
sharp_faces.span[dst_poly] = !is_smooth;
|
2022-12-30 23:52:44 -05:00
|
|
|
dst_poly++;
|
|
|
|
|
dst_loop += 4;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-08 17:44:54 +02:00
|
|
|
p4 = p3;
|
|
|
|
|
p3++;
|
|
|
|
|
p2 = p1;
|
|
|
|
|
p1++;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
2018-05-08 17:44:54 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-07-24 22:06:55 +02:00
|
|
|
if (faces_num) {
|
2023-12-20 17:47:10 -05:00
|
|
|
mesh_calc_edges(*mesh, true, false);
|
2018-05-08 17:44:54 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-08-31 09:09:01 -05:00
|
|
|
material_indices.finish();
|
Mesh: Move face shade smooth flag to a generic attribute
Currently the shade smooth status for mesh faces is stored as part of
`MPoly::flag`. As described in #95967, this moves that information
to a separate boolean attribute. It also flips its status, so the
attribute is now called `sharp_face`, which mirrors the existing
`sharp_edge` attribute. The attribute doesn't need to be allocated
when all faces are smooth. Forward compatibility is kept until
4.0 like the other mesh refactors.
This will reduce memory bandwidth requirements for some operations,
since the array of booleans uses 12 times less memory than `MPoly`.
It also allows faces to be stored more efficiently in the future, since
the flag is now unused. It's also possible to use generic functions to
process the values. For example, finding whether there is a sharp face
is just `sharp_faces.contains(true)`.
The `shade_smooth` attribute is no longer accessible with geometry nodes.
Since there were dedicated accessor nodes for that data, that shouldn't
be a problem. That's difficult to version automatically since the named
attribute nodes could be used in arbitrary combinations.
**Implementation notes:**
- The attribute and array variables in the code use the `sharp_faces`
term, to be consistent with the user-facing "sharp faces" wording,
and to avoid requiring many renames when #101689 is implemented.
- Cycles now accesses smooth face status with the generic attribute,
to avoid overhead.
- Changing the zero-value from "smooth" to "flat" takes some care to
make sure defaults are the same.
- Versioning for the edge mode extrude node is particularly complex.
New nodes are added by versioning to propagate the attribute in its
old inverted state.
- A lot of access is still done through the `CustomData` API rather
than the attribute API because of a few functions. That can be
cleaned up easily in the future.
- In the future we would benefit from a way to store attributes as a
single value for when all faces are sharp.
Pull Request: https://projects.blender.org/blender/blender/pulls/104422
2023-03-08 15:36:18 +01:00
|
|
|
sharp_faces.finish();
|
2023-07-09 20:00:17 -04:00
|
|
|
uv_attribute.finish();
|
2022-08-31 09:09:01 -05:00
|
|
|
|
2022-08-11 13:09:55 -04:00
|
|
|
return mesh;
|
2018-05-08 17:44:54 +02:00
|
|
|
}
|
|
|
|
|
|
Geometry Nodes: Support modifier on curve objects
With this commit, curve objects support the geometry nodes modifier.
Curves objects now evaluate to `CurveEval` unless there was a previous
implicit conversion (tessellating modifiers, mesh modifiers, or the
settings in the curve "Geometry" panel). In the new code, curves are
only considered to be the wire edges-- any generated surface is a mesh
instead, stored in the evaluated geometry set.
The consolidation of concepts mentioned above allows remove a lot of
code that had to do with maintaining the `DispList` type temporarily
for modifiers and rendering. Instead, render engines see a separate
object for the mesh from the mesh geometry component, and when the
curve object evaluates to a curve, the `CurveEval` is always used for
drawing wire edges.
However, currently the `DispList` type is still maintained and used as
an intermediate step in implicit mesh conversion. In the future, more
uses of it could be changed to use `CurveEval` and `Mesh` instead.
This is mostly not changed behavior, it is just a formalization of
existing logic after recent fixes for 2.8 versions last year and two
years ago. Also, in the future more functionality can be converted
to nodes, removing cases of implicit conversions. For more discussion
on that topic, see T89676.
The `use_fill_deform` option is removed. It has not worked properly
since 2.62, and the choice for filling a curve before or after
deformation will work much better and be clearer with a node system.
Applying the geometry nodes modifier to generate a curve is not
implemented with this commit, so applying the modifier won't work
at all. This is a separate technical challenge, and should be solved
in a separate step.
Differential Revision: https://developer.blender.org/D11597
2021-09-11 13:54:40 -05:00
|
|
|
/**
|
|
|
|
|
* Copy evaluated texture space from curve to mesh.
|
|
|
|
|
*
|
|
|
|
|
* \note We disable auto texture space feature since that will cause texture space to evaluate
|
|
|
|
|
* differently for curve and mesh, since curves use control points and handles to calculate the
|
|
|
|
|
* bounding box, and mesh uses the tessellated curve.
|
|
|
|
|
*/
|
2023-12-08 16:40:06 -05:00
|
|
|
static void mesh_copy_texture_space_from_curve_type(const Curve *cu, Mesh *mesh)
|
Geometry Nodes: Support modifier on curve objects
With this commit, curve objects support the geometry nodes modifier.
Curves objects now evaluate to `CurveEval` unless there was a previous
implicit conversion (tessellating modifiers, mesh modifiers, or the
settings in the curve "Geometry" panel). In the new code, curves are
only considered to be the wire edges-- any generated surface is a mesh
instead, stored in the evaluated geometry set.
The consolidation of concepts mentioned above allows remove a lot of
code that had to do with maintaining the `DispList` type temporarily
for modifiers and rendering. Instead, render engines see a separate
object for the mesh from the mesh geometry component, and when the
curve object evaluates to a curve, the `CurveEval` is always used for
drawing wire edges.
However, currently the `DispList` type is still maintained and used as
an intermediate step in implicit mesh conversion. In the future, more
uses of it could be changed to use `CurveEval` and `Mesh` instead.
This is mostly not changed behavior, it is just a formalization of
existing logic after recent fixes for 2.8 versions last year and two
years ago. Also, in the future more functionality can be converted
to nodes, removing cases of implicit conversions. For more discussion
on that topic, see T89676.
The `use_fill_deform` option is removed. It has not worked properly
since 2.62, and the choice for filling a curve before or after
deformation will work much better and be clearer with a node system.
Applying the geometry nodes modifier to generate a curve is not
implemented with this commit, so applying the modifier won't work
at all. This is a separate technical challenge, and should be solved
in a separate step.
Differential Revision: https://developer.blender.org/D11597
2021-09-11 13:54:40 -05:00
|
|
|
{
|
2023-12-08 16:40:06 -05:00
|
|
|
mesh->texspace_flag = cu->texspace_flag & ~CU_TEXSPACE_FLAG_AUTO;
|
|
|
|
|
copy_v3_v3(mesh->texspace_location, cu->texspace_location);
|
|
|
|
|
copy_v3_v3(mesh->texspace_size, cu->texspace_size);
|
|
|
|
|
BKE_mesh_texspace_calc(mesh);
|
Geometry Nodes: Support modifier on curve objects
With this commit, curve objects support the geometry nodes modifier.
Curves objects now evaluate to `CurveEval` unless there was a previous
implicit conversion (tessellating modifiers, mesh modifiers, or the
settings in the curve "Geometry" panel). In the new code, curves are
only considered to be the wire edges-- any generated surface is a mesh
instead, stored in the evaluated geometry set.
The consolidation of concepts mentioned above allows remove a lot of
code that had to do with maintaining the `DispList` type temporarily
for modifiers and rendering. Instead, render engines see a separate
object for the mesh from the mesh geometry component, and when the
curve object evaluates to a curve, the `CurveEval` is always used for
drawing wire edges.
However, currently the `DispList` type is still maintained and used as
an intermediate step in implicit mesh conversion. In the future, more
uses of it could be changed to use `CurveEval` and `Mesh` instead.
This is mostly not changed behavior, it is just a formalization of
existing logic after recent fixes for 2.8 versions last year and two
years ago. Also, in the future more functionality can be converted
to nodes, removing cases of implicit conversions. For more discussion
on that topic, see T89676.
The `use_fill_deform` option is removed. It has not worked properly
since 2.62, and the choice for filling a curve before or after
deformation will work much better and be clearer with a node system.
Applying the geometry nodes modifier to generate a curve is not
implemented with this commit, so applying the modifier won't work
at all. This is a separate technical challenge, and should be solved
in a separate step.
Differential Revision: https://developer.blender.org/D11597
2021-09-11 13:54:40 -05:00
|
|
|
}
|
|
|
|
|
|
2021-06-28 13:47:48 -05:00
|
|
|
Mesh *BKE_mesh_new_nomain_from_curve_displist(const Object *ob, const ListBase *dispbase)
|
2018-05-08 19:09:35 +02:00
|
|
|
{
|
2021-09-16 15:44:43 -05:00
|
|
|
const Curve *cu = (const Curve *)ob->data;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-08-11 13:09:55 -04:00
|
|
|
Mesh *mesh = mesh_nurbs_displist_to_mesh(cu, dispbase);
|
Geometry Nodes: Support modifier on curve objects
With this commit, curve objects support the geometry nodes modifier.
Curves objects now evaluate to `CurveEval` unless there was a previous
implicit conversion (tessellating modifiers, mesh modifiers, or the
settings in the curve "Geometry" panel). In the new code, curves are
only considered to be the wire edges-- any generated surface is a mesh
instead, stored in the evaluated geometry set.
The consolidation of concepts mentioned above allows remove a lot of
code that had to do with maintaining the `DispList` type temporarily
for modifiers and rendering. Instead, render engines see a separate
object for the mesh from the mesh geometry component, and when the
curve object evaluates to a curve, the `CurveEval` is always used for
drawing wire edges.
However, currently the `DispList` type is still maintained and used as
an intermediate step in implicit mesh conversion. In the future, more
uses of it could be changed to use `CurveEval` and `Mesh` instead.
This is mostly not changed behavior, it is just a formalization of
existing logic after recent fixes for 2.8 versions last year and two
years ago. Also, in the future more functionality can be converted
to nodes, removing cases of implicit conversions. For more discussion
on that topic, see T89676.
The `use_fill_deform` option is removed. It has not worked properly
since 2.62, and the choice for filling a curve before or after
deformation will work much better and be clearer with a node system.
Applying the geometry nodes modifier to generate a curve is not
implemented with this commit, so applying the modifier won't work
at all. This is a separate technical challenge, and should be solved
in a separate step.
Differential Revision: https://developer.blender.org/D11597
2021-09-11 13:54:40 -05:00
|
|
|
mesh_copy_texture_space_from_curve_type(cu, mesh);
|
|
|
|
|
mesh->mat = (Material **)MEM_dupallocN(cu->mat);
|
|
|
|
|
mesh->totcol = cu->totcol;
|
|
|
|
|
|
2018-05-08 19:09:35 +02:00
|
|
|
return mesh;
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-19 21:19:59 -04:00
|
|
|
Mesh *BKE_mesh_new_nomain_from_curve(const Object *ob)
|
2018-05-08 19:09:35 +02:00
|
|
|
{
|
2021-09-16 15:44:43 -05:00
|
|
|
ListBase disp = {nullptr, nullptr};
|
2018-05-08 19:09:35 +02:00
|
|
|
|
2023-11-15 18:46:07 +01:00
|
|
|
if (ob->runtime->curve_cache) {
|
|
|
|
|
disp = ob->runtime->curve_cache->disp;
|
2018-05-08 19:09:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return BKE_mesh_new_nomain_from_curve_displist(ob, &disp);
|
|
|
|
|
}
|
2018-05-08 17:44:54 +02:00
|
|
|
|
2021-09-16 15:44:43 -05:00
|
|
|
struct EdgeLink {
|
2023-06-03 08:36:28 +10:00
|
|
|
EdgeLink *next, *prev;
|
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 void *edge;
|
2021-09-16 15:44:43 -05:00
|
|
|
};
|
2018-05-08 17:44:54 +02:00
|
|
|
|
2021-09-16 15:44:43 -05:00
|
|
|
struct VertLink {
|
2018-05-08 17:44:54 +02:00
|
|
|
Link *next, *prev;
|
2021-06-18 14:27:41 +10:00
|
|
|
uint index;
|
2021-09-16 15:44:43 -05:00
|
|
|
};
|
2018-05-08 17:44:54 +02:00
|
|
|
|
2021-06-18 14:27:41 +10:00
|
|
|
static void prependPolyLineVert(ListBase *lb, uint index)
|
2018-05-08 17:44:54 +02:00
|
|
|
{
|
2021-12-24 22:17:49 -05:00
|
|
|
VertLink *vl = MEM_cnew<VertLink>("VertLink");
|
2018-05-08 17:44:54 +02:00
|
|
|
vl->index = index;
|
|
|
|
|
BLI_addhead(lb, vl);
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-18 14:27:41 +10:00
|
|
|
static void appendPolyLineVert(ListBase *lb, uint index)
|
2018-05-08 17:44:54 +02:00
|
|
|
{
|
2021-12-24 22:17:49 -05:00
|
|
|
VertLink *vl = MEM_cnew<VertLink>("VertLink");
|
2018-05-08 17:44:54 +02:00
|
|
|
vl->index = index;
|
|
|
|
|
BLI_addtail(lb, vl);
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-08 16:40:06 -05:00
|
|
|
void BKE_mesh_to_curve_nurblist(const Mesh *mesh, ListBase *nurblist, const int edge_users_test)
|
2018-05-08 17:44:54 +02:00
|
|
|
{
|
2023-12-08 16:40:06 -05:00
|
|
|
const Span<float3> positions = mesh->vert_positions();
|
|
|
|
|
const Span<blender::int2> mesh_edges = mesh->edges();
|
|
|
|
|
const blender::OffsetIndices polys = mesh->faces();
|
|
|
|
|
const Span<int> corner_edges = mesh->corner_edges();
|
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
|
|
|
|
2018-05-08 17:44:54 +02:00
|
|
|
/* only to detect edge polylines */
|
|
|
|
|
int *edge_users;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-09-16 15:44:43 -05:00
|
|
|
ListBase edges = {nullptr, nullptr};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-08 17:44:54 +02:00
|
|
|
/* get boundary edges */
|
2023-03-03 10:50:54 -05:00
|
|
|
edge_users = (int *)MEM_calloc_arrayN(mesh_edges.size(), sizeof(int), __func__);
|
|
|
|
|
for (const int 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])) {
|
|
|
|
|
edge_users[edge]++;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2018-05-08 17:44:54 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-08 17:44:54 +02:00
|
|
|
/* create edges from all faces (so as to find edges not in any faces) */
|
2023-03-03 10:50:54 -05:00
|
|
|
for (const int i : mesh_edges.index_range()) {
|
2018-05-08 17:44:54 +02:00
|
|
|
if (edge_users[i] == edge_users_test) {
|
2021-12-24 22:17:49 -05:00
|
|
|
EdgeLink *edl = MEM_cnew<EdgeLink>("EdgeLink");
|
2023-03-03 10:50:54 -05:00
|
|
|
edl->edge = &mesh_edges[i];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-08 17:44:54 +02:00
|
|
|
BLI_addtail(&edges, edl);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2018-05-08 17:44:54 +02:00
|
|
|
}
|
|
|
|
|
MEM_freeN(edge_users);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-08 17:44:54 +02:00
|
|
|
if (edges.first) {
|
|
|
|
|
while (edges.first) {
|
|
|
|
|
/* each iteration find a polyline and add this as a nurbs poly spline */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-09-16 15:44:43 -05:00
|
|
|
ListBase polyline = {nullptr, nullptr}; /* store a list of VertLink's */
|
2018-05-08 17:44:54 +02:00
|
|
|
bool closed = false;
|
2023-07-24 22:06:55 +02:00
|
|
|
int faces_num = 0;
|
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
|
|
|
blender::int2 &edge_current = *(blender::int2 *)((EdgeLink *)edges.last)->edge;
|
|
|
|
|
uint startVert = edge_current[0];
|
|
|
|
|
uint endVert = edge_current[1];
|
2018-05-08 17:44:54 +02:00
|
|
|
bool ok = true;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-08 17:44:54 +02:00
|
|
|
appendPolyLineVert(&polyline, startVert);
|
2023-07-24 22:06:55 +02:00
|
|
|
faces_num++;
|
2018-05-08 17:44:54 +02:00
|
|
|
appendPolyLineVert(&polyline, endVert);
|
2023-07-24 22:06:55 +02:00
|
|
|
faces_num++;
|
2018-05-08 17:44:54 +02:00
|
|
|
BLI_freelinkN(&edges, edges.last);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-08 17:44:54 +02:00
|
|
|
while (ok) { /* while connected edges are found... */
|
2021-09-16 15:44:43 -05:00
|
|
|
EdgeLink *edl = (EdgeLink *)edges.last;
|
2018-05-08 17:44:54 +02:00
|
|
|
ok = false;
|
|
|
|
|
while (edl) {
|
|
|
|
|
EdgeLink *edl_prev = edl->prev;
|
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
|
|
|
const blender::int2 &edge = *(blender::int2 *)edl->edge;
|
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
|
|
|
if (edge[0] == endVert) {
|
|
|
|
|
endVert = edge[1];
|
2023-03-18 03:49:25 +01:00
|
|
|
appendPolyLineVert(&polyline, endVert);
|
2023-07-24 22:06:55 +02:00
|
|
|
faces_num++;
|
2018-05-08 17:44:54 +02:00
|
|
|
BLI_freelinkN(&edges, edl);
|
|
|
|
|
ok = true;
|
|
|
|
|
}
|
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
|
|
|
else if (edge[1] == endVert) {
|
|
|
|
|
endVert = edge[0];
|
2018-05-08 17:44:54 +02:00
|
|
|
appendPolyLineVert(&polyline, endVert);
|
2023-07-24 22:06:55 +02:00
|
|
|
faces_num++;
|
2018-05-08 17:44:54 +02:00
|
|
|
BLI_freelinkN(&edges, edl);
|
|
|
|
|
ok = true;
|
|
|
|
|
}
|
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
|
|
|
else if (edge[0] == startVert) {
|
|
|
|
|
startVert = edge[1];
|
2018-05-08 17:44:54 +02:00
|
|
|
prependPolyLineVert(&polyline, startVert);
|
2023-07-24 22:06:55 +02:00
|
|
|
faces_num++;
|
2018-05-08 17:44:54 +02:00
|
|
|
BLI_freelinkN(&edges, edl);
|
|
|
|
|
ok = true;
|
|
|
|
|
}
|
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
|
|
|
else if (edge[1] == startVert) {
|
|
|
|
|
startVert = edge[0];
|
2018-05-08 17:44:54 +02:00
|
|
|
prependPolyLineVert(&polyline, startVert);
|
2023-07-24 22:06:55 +02:00
|
|
|
faces_num++;
|
2018-05-08 17:44:54 +02:00
|
|
|
BLI_freelinkN(&edges, edl);
|
|
|
|
|
ok = true;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-08 17:44:54 +02:00
|
|
|
edl = edl_prev;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2018-05-08 17:44:54 +02:00
|
|
|
/* Now we have a polyline, make into a curve */
|
|
|
|
|
if (startVert == endVert) {
|
|
|
|
|
BLI_freelinkN(&polyline, polyline.last);
|
2023-07-24 22:06:55 +02:00
|
|
|
faces_num--;
|
2018-05-08 17:44:54 +02:00
|
|
|
closed = true;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-08 17:44:54 +02:00
|
|
|
/* --- nurbs --- */
|
|
|
|
|
{
|
|
|
|
|
Nurb *nu;
|
|
|
|
|
BPoint *bp;
|
|
|
|
|
VertLink *vl;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-08 17:44:54 +02:00
|
|
|
/* create new 'nurb' within the curve */
|
2024-07-09 18:20:08 +02:00
|
|
|
nu = static_cast<Nurb *>(MEM_callocN(sizeof(Nurb), __func__));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-07-24 22:06:55 +02:00
|
|
|
nu->pntsu = faces_num;
|
2018-05-08 17:44:54 +02:00
|
|
|
nu->pntsv = 1;
|
|
|
|
|
nu->orderu = 4;
|
|
|
|
|
nu->flagu = CU_NURB_ENDPOINT | (closed ? CU_NURB_CYCLIC : 0); /* endpoint */
|
|
|
|
|
nu->resolu = 12;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-07-24 22:06:55 +02:00
|
|
|
nu->bp = (BPoint *)MEM_calloc_arrayN(faces_num, sizeof(BPoint), "bpoints");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-08 17:44:54 +02:00
|
|
|
/* add points */
|
2021-09-16 15:44:43 -05:00
|
|
|
vl = (VertLink *)polyline.first;
|
2023-03-03 10:50:54 -05:00
|
|
|
int i;
|
2023-07-24 22:06:55 +02:00
|
|
|
for (i = 0, bp = nu->bp; i < faces_num; i++, bp++, vl = (VertLink *)vl->next) {
|
Mesh: Move positions to a generic attribute
**Changes**
As described in T93602, this patch removes all use of the `MVert`
struct, replacing it with a generic named attribute with the name
`"position"`, consistent with other geometry types.
Variable names have been changed from `verts` to `positions`, to align
with the attribute name and the more generic design (positions are not
vertices, they are just an attribute stored on the point domain).
This change is made possible by previous commits that moved all other
data out of `MVert` to runtime data or other generic attributes. What
remains is mostly a simple type change. Though, the type still shows up
859 times, so the patch is quite large.
One compromise is that now `CD_MASK_BAREMESH` now contains
`CD_PROP_FLOAT3`. With the general move towards generic attributes
over custom data types, we are removing use of these type masks anyway.
**Benefits**
The most obvious benefit is reduced memory usage and the benefits
that brings in memory-bound situations. `float3` is only 3 bytes, in
comparison to `MVert` which was 4. When there are millions of vertices
this starts to matter more.
The other benefits come from using a more generic type. Instead of
writing algorithms specifically for `MVert`, code can just use arrays
of vectors. This will allow eliminating many temporary arrays or
wrappers used to extract positions.
Many possible improvements aren't implemented in this patch, though
I did switch simplify or remove the process of creating temporary
position arrays in a few places.
The design clarity that "positions are just another attribute" brings
allows removing explicit copying of vertices in some procedural
operations-- they are just processed like most other attributes.
**Performance**
This touches so many areas that it's hard to benchmark exhaustively,
but I observed some areas as examples.
* The mesh line node with 4 million count was 1.5x (8ms to 12ms) faster.
* The Spring splash screen went from ~4.3 to ~4.5 fps.
* The subdivision surface modifier/node was slightly faster
RNA access through Python may be slightly slower, since now we need
a name lookup instead of just a custom data type lookup for each index.
**Future Improvements**
* Remove uses of "vert_coords" functions:
* `BKE_mesh_vert_coords_alloc`
* `BKE_mesh_vert_coords_get`
* `BKE_mesh_vert_coords_apply{_with_mat4}`
* Remove more hidden copying of positions
* General simplification now possible in many areas
* Convert more code to C++ to use `float3` instead of `float[3]`
* Currently `reinterpret_cast` is used for those C-API functions
Differential Revision: https://developer.blender.org/D15982
2023-01-10 00:10:43 -05:00
|
|
|
copy_v3_v3(bp->vec, positions[vl->index]);
|
2018-05-08 17:44:54 +02:00
|
|
|
bp->f1 = SELECT;
|
|
|
|
|
bp->radius = bp->weight = 1.0;
|
|
|
|
|
}
|
|
|
|
|
BLI_freelistN(&polyline);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-08 17:44:54 +02:00
|
|
|
/* add nurb to curve */
|
|
|
|
|
BLI_addtail(nurblist, nu);
|
|
|
|
|
}
|
|
|
|
|
/* --- done with nurbs --- */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-03 17:37:25 -05:00
|
|
|
void BKE_mesh_to_curve(Main *bmain, Depsgraph *depsgraph, Scene * /*scene*/, Object *ob)
|
2018-05-08 17:44:54 +02:00
|
|
|
{
|
2023-05-30 22:25:06 +02:00
|
|
|
const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
|
|
|
|
|
if (!ob_eval) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2024-03-11 11:21:12 -04:00
|
|
|
const Mesh *mesh_eval = BKE_object_get_evaluated_mesh_no_subsurf(ob_eval);
|
|
|
|
|
if (!mesh_eval) {
|
2023-05-30 22:25:06 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-16 15:44:43 -05:00
|
|
|
ListBase nurblist = {nullptr, nullptr};
|
2018-05-08 17:44:54 +02:00
|
|
|
|
2024-03-11 11:21:12 -04:00
|
|
|
BKE_mesh_to_curve_nurblist(mesh_eval, &nurblist, 0);
|
|
|
|
|
BKE_mesh_to_curve_nurblist(mesh_eval, &nurblist, 1);
|
2018-05-08 17:44:54 +02:00
|
|
|
|
|
|
|
|
if (nurblist.first) {
|
2022-02-18 09:50:29 -06:00
|
|
|
Curve *cu = BKE_curve_add(bmain, ob->id.name + 2, OB_CURVES_LEGACY);
|
2018-05-08 17:44:54 +02:00
|
|
|
cu->flag |= CU_3D;
|
|
|
|
|
|
|
|
|
|
cu->nurb = nurblist;
|
|
|
|
|
|
|
|
|
|
id_us_min(&((Mesh *)ob->data)->id);
|
|
|
|
|
ob->data = cu;
|
2022-02-18 09:50:29 -06:00
|
|
|
ob->type = OB_CURVES_LEGACY;
|
2018-05-08 17:44:54 +02:00
|
|
|
|
2018-06-22 16:58:44 +02:00
|
|
|
BKE_object_free_derived_caches(ob);
|
2018-05-08 17:44:54 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-03 17:37:25 -05:00
|
|
|
void BKE_mesh_to_pointcloud(Main *bmain, Depsgraph *depsgraph, Scene * /*scene*/, Object *ob)
|
2020-04-09 18:49:40 +02:00
|
|
|
{
|
|
|
|
|
BLI_assert(ob->type == OB_MESH);
|
2023-05-30 22:25:06 +02:00
|
|
|
const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
|
|
|
|
|
if (!ob_eval) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval);
|
|
|
|
|
if (!mesh_eval) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-04-09 18:49:40 +02:00
|
|
|
|
2021-09-16 15:44:43 -05:00
|
|
|
PointCloud *pointcloud = (PointCloud *)BKE_pointcloud_add(bmain, ob->id.name + 2);
|
2020-04-09 18:49:40 +02:00
|
|
|
|
2023-05-26 16:25:50 -04:00
|
|
|
CustomData_free(&pointcloud->pdata, pointcloud->totpoint);
|
2023-12-20 02:21:48 +01:00
|
|
|
pointcloud->totpoint = mesh_eval->verts_num;
|
2023-07-25 15:23:56 -04:00
|
|
|
CustomData_merge(
|
2023-12-20 02:21:48 +01:00
|
|
|
&mesh_eval->vert_data, &pointcloud->pdata, CD_MASK_PROP_ALL, mesh_eval->verts_num);
|
2020-04-09 18:49:40 +02:00
|
|
|
|
|
|
|
|
BKE_id_materials_copy(bmain, (ID *)ob->data, (ID *)pointcloud);
|
|
|
|
|
|
|
|
|
|
id_us_min(&((Mesh *)ob->data)->id);
|
|
|
|
|
ob->data = pointcloud;
|
|
|
|
|
ob->type = OB_POINTCLOUD;
|
|
|
|
|
|
|
|
|
|
BKE_object_free_derived_caches(ob);
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-03 17:37:25 -05:00
|
|
|
void BKE_pointcloud_to_mesh(Main *bmain, Depsgraph *depsgraph, Scene * /*scene*/, Object *ob)
|
2020-04-09 18:49:40 +02:00
|
|
|
{
|
|
|
|
|
BLI_assert(ob->type == OB_POINTCLOUD);
|
|
|
|
|
|
2023-05-30 14:33:00 -04:00
|
|
|
const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
|
2023-06-15 22:18:28 +02:00
|
|
|
const blender::bke::GeometrySet geometry = blender::bke::object_get_evaluated_geometry_set(
|
|
|
|
|
*ob_eval);
|
2020-04-09 18:49:40 +02:00
|
|
|
|
2023-05-26 16:25:50 -04:00
|
|
|
Mesh *mesh = BKE_mesh_add(bmain, ob->id.name + 2);
|
2020-04-09 18:49:40 +02:00
|
|
|
|
2023-08-03 17:09:18 +02:00
|
|
|
if (const PointCloud *points = geometry.get_pointcloud()) {
|
2023-12-20 02:21:48 +01:00
|
|
|
mesh->verts_num = points->totpoint;
|
2023-07-25 21:15:52 +02:00
|
|
|
CustomData_merge(&points->pdata, &mesh->vert_data, CD_MASK_PROP_ALL, points->totpoint);
|
2023-05-30 14:33:00 -04:00
|
|
|
}
|
2020-04-09 18:49:40 +02:00
|
|
|
|
2023-05-26 16:25:50 -04:00
|
|
|
BKE_id_materials_copy(bmain, (ID *)ob->data, (ID *)mesh);
|
2020-04-09 18:49:40 +02:00
|
|
|
|
|
|
|
|
id_us_min(&((PointCloud *)ob->data)->id);
|
2023-05-26 16:25:50 -04:00
|
|
|
ob->data = mesh;
|
2020-04-09 18:49:40 +02:00
|
|
|
ob->type = OB_MESH;
|
|
|
|
|
|
|
|
|
|
BKE_object_free_derived_caches(ob);
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-23 11:41:46 -05:00
|
|
|
/* Create a temporary object to be used for nurbs-to-mesh conversion. */
|
|
|
|
|
static Object *object_for_curve_to_mesh_create(const Object *object)
|
2018-05-08 17:44:54 +02:00
|
|
|
{
|
2021-09-23 11:41:46 -05:00
|
|
|
const Curve *curve = (const Curve *)object->data;
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
|
2021-09-24 11:31:23 +10:00
|
|
|
/* Create a temporary object which can be evaluated and modified by generic
|
|
|
|
|
* curve evaluation (hence the #LIB_ID_COPY_SET_COPIED_ON_WRITE flag). */
|
2021-09-16 15:44:43 -05:00
|
|
|
Object *temp_object = (Object *)BKE_id_copy_ex(
|
2021-09-23 11:41:46 -05:00
|
|
|
nullptr, &object->id, nullptr, LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_SET_COPIED_ON_WRITE);
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
|
|
|
|
|
/* Remove all modifiers, since we don't want them to be applied. */
|
|
|
|
|
BKE_object_free_modifiers(temp_object, LIB_ID_CREATE_NO_USER_REFCOUNT);
|
|
|
|
|
|
2021-09-23 11:41:46 -05:00
|
|
|
/* Need to create copy of curve itself as well, since it will be changed by the curve evaluation
|
2021-09-24 11:31:23 +10:00
|
|
|
* process. NOTE: Copies the data, but not the shape-keys. */
|
2021-09-23 11:41:46 -05:00
|
|
|
temp_object->data = BKE_id_copy_ex(nullptr,
|
|
|
|
|
(const ID *)object->data,
|
|
|
|
|
nullptr,
|
|
|
|
|
LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_SET_COPIED_ON_WRITE);
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
Curve *temp_curve = (Curve *)temp_object->data;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
/* Make sure texture space is calculated for a copy of curve, it will be used for the final
|
|
|
|
|
* result. */
|
|
|
|
|
BKE_curve_texspace_calc(temp_curve);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-09-24 11:31:23 +10:00
|
|
|
/* Temporarily set edit so we get updates from edit mode, but also because for text data-blocks
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
* copying it while in edit mode gives invalid data structures. */
|
|
|
|
|
temp_curve->editfont = curve->editfont;
|
|
|
|
|
temp_curve->editnurb = curve->editnurb;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
return temp_object;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-12-29 16:53:02 -06:00
|
|
|
static void object_for_curve_to_mesh_free(Object *temp_object)
|
|
|
|
|
{
|
|
|
|
|
/* Clear edit mode pointers that were explicitly copied to the temporary curve. */
|
|
|
|
|
ID *final_object_data = static_cast<ID *>(temp_object->data);
|
2022-02-18 09:50:29 -06:00
|
|
|
if (GS(final_object_data->name) == ID_CU_LEGACY) {
|
2021-12-29 16:53:02 -06:00
|
|
|
Curve &curve = *reinterpret_cast<Curve *>(final_object_data);
|
|
|
|
|
curve.editfont = nullptr;
|
|
|
|
|
curve.editnurb = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-19 11:10:17 +02:00
|
|
|
/* Only free the final object data if it is *not* stored in the #data_eval field. This is still
|
|
|
|
|
* necessary because #temp_object's data could be replaced by a #Curve data-block that isn't also
|
|
|
|
|
* assigned to #data_eval. */
|
2023-11-15 18:46:07 +01:00
|
|
|
const bool object_data_stored_in_data_eval = final_object_data ==
|
|
|
|
|
temp_object->runtime->data_eval;
|
2022-05-19 11:10:17 +02:00
|
|
|
|
2021-12-29 16:53:02 -06:00
|
|
|
BKE_id_free(nullptr, temp_object);
|
2022-05-19 11:10:17 +02:00
|
|
|
if (!object_data_stored_in_data_eval) {
|
|
|
|
|
BKE_id_free(nullptr, final_object_data);
|
|
|
|
|
}
|
2021-12-29 16:53:02 -06:00
|
|
|
}
|
|
|
|
|
|
2021-05-05 08:05:10 +10:00
|
|
|
/**
|
2023-11-15 18:46:07 +01:00
|
|
|
* Populate `object->runtime->curve_cache` which is then used to create the mesh.
|
2021-05-05 08:05:10 +10:00
|
|
|
*/
|
2021-09-23 11:41:46 -05:00
|
|
|
static void curve_to_mesh_eval_ensure(Object &object)
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
{
|
2022-02-18 09:50:29 -06:00
|
|
|
BLI_assert(GS(static_cast<ID *>(object.data)->name) == ID_CU_LEGACY);
|
2021-09-23 11:41:46 -05:00
|
|
|
Curve &curve = *static_cast<Curve *>(object.data);
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
/* Clear all modifiers for the bevel object.
|
|
|
|
|
*
|
|
|
|
|
* This is because they can not be reliably evaluated for an original object (at least because
|
|
|
|
|
* the state of dependencies is not know).
|
|
|
|
|
*
|
|
|
|
|
* So we create temporary copy of the object which will use same data as the original bevel, but
|
|
|
|
|
* will have no modifiers. */
|
2022-03-31 10:06:33 +02:00
|
|
|
Object bevel_object = blender::dna::shallow_zero_initialize();
|
2023-11-15 18:46:07 +01:00
|
|
|
blender::bke::ObjectRuntime bevel_runtime;
|
2021-09-23 11:41:46 -05:00
|
|
|
if (curve.bevobj != nullptr) {
|
2022-03-29 10:06:34 +02:00
|
|
|
bevel_object = blender::dna::shallow_copy(*curve.bevobj);
|
2023-11-15 18:46:07 +01:00
|
|
|
bevel_runtime = *curve.bevobj->runtime;
|
|
|
|
|
bevel_object.runtime = &bevel_runtime;
|
|
|
|
|
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
BLI_listbase_clear(&bevel_object.modifiers);
|
2021-04-30 16:22:51 +10:00
|
|
|
BKE_object_runtime_reset(&bevel_object);
|
2021-09-23 11:41:46 -05:00
|
|
|
curve.bevobj = &bevel_object;
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
/* Same thing for taper. */
|
2022-03-31 10:06:33 +02:00
|
|
|
Object taper_object = blender::dna::shallow_zero_initialize();
|
2023-11-15 18:46:07 +01:00
|
|
|
blender::bke::ObjectRuntime taper_runtime;
|
2021-09-23 11:41:46 -05:00
|
|
|
if (curve.taperobj != nullptr) {
|
2022-03-29 10:06:34 +02:00
|
|
|
taper_object = blender::dna::shallow_copy(*curve.taperobj);
|
2023-11-15 18:46:07 +01:00
|
|
|
taper_runtime = *curve.taperobj->runtime;
|
|
|
|
|
taper_object.runtime = &taper_runtime;
|
|
|
|
|
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
BLI_listbase_clear(&taper_object.modifiers);
|
2021-04-30 16:22:51 +10:00
|
|
|
BKE_object_runtime_reset(&taper_object);
|
2021-09-23 11:41:46 -05:00
|
|
|
curve.taperobj = &taper_object;
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-09-16 15:44:43 -05:00
|
|
|
/* NOTE: We don't have dependency graph or scene here, so we pass nullptr. This is all fine since
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
* they are only used for modifier stack, which we have explicitly disabled for all objects.
|
|
|
|
|
*
|
|
|
|
|
* TODO(sergey): This is a very fragile logic, but proper solution requires re-writing quite a
|
2021-09-23 11:41:46 -05:00
|
|
|
* bit of internal functions (#BKE_mesh_nomain_to_mesh) and also Mesh From Curve operator.
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
* Brecht says hold off with that. */
|
2021-09-23 11:41:46 -05:00
|
|
|
BKE_displist_make_curveTypes(nullptr, nullptr, &object, true);
|
2019-06-09 21:11:37 +02:00
|
|
|
|
2023-12-04 19:14:50 -05:00
|
|
|
if (bevel_object.runtime) {
|
|
|
|
|
BKE_object_runtime_free_data(&bevel_object);
|
|
|
|
|
}
|
|
|
|
|
if (taper_object.runtime) {
|
|
|
|
|
BKE_object_runtime_free_data(&taper_object);
|
|
|
|
|
}
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-02-28 10:46:34 -05:00
|
|
|
static const Curves *get_evaluated_curves_from_object(const Object *object)
|
2021-09-23 11:41:46 -05:00
|
|
|
{
|
2023-11-15 18:46:07 +01:00
|
|
|
if (blender::bke::GeometrySet *geometry_set_eval = object->runtime->geometry_set_eval) {
|
2023-08-03 17:09:18 +02:00
|
|
|
return geometry_set_eval->get_curves();
|
2021-09-23 11:41:46 -05:00
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static Mesh *mesh_new_from_evaluated_curve_type_object(const Object *evaluated_object)
|
|
|
|
|
{
|
2022-05-19 14:08:54 +02:00
|
|
|
if (const Mesh *mesh = BKE_object_get_evaluated_mesh(evaluated_object)) {
|
2024-05-20 13:18:24 -04:00
|
|
|
return BKE_mesh_copy_for_eval(*mesh);
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
}
|
2022-05-19 14:08:54 +02:00
|
|
|
if (const Curves *curves = get_evaluated_curves_from_object(evaluated_object)) {
|
2024-09-05 11:33:35 +02:00
|
|
|
return blender::bke::curve_to_wire_mesh(curves->geometry.wrap());
|
2021-09-23 11:41:46 -05:00
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-09-23 11:41:46 -05:00
|
|
|
static Mesh *mesh_new_from_curve_type_object(const Object *object)
|
|
|
|
|
{
|
|
|
|
|
/* If the object is evaluated, it should either have an evaluated mesh or curve data already.
|
|
|
|
|
* The mesh can be duplicated, or the curve converted to wire mesh edges. */
|
|
|
|
|
if (DEG_is_evaluated_object(object)) {
|
|
|
|
|
return mesh_new_from_evaluated_curve_type_object(object);
|
|
|
|
|
}
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
|
2021-09-23 11:41:46 -05:00
|
|
|
/* Otherwise, create a temporary "fake" evaluated object and try again. This might have
|
|
|
|
|
* different results, since in order to avoid having adverse affects to other original objects,
|
|
|
|
|
* modifiers are cleared. An alternative would be to create a temporary depsgraph only for this
|
|
|
|
|
* object and its dependencies. */
|
|
|
|
|
Object *temp_object = object_for_curve_to_mesh_create(object);
|
|
|
|
|
ID *temp_data = static_cast<ID *>(temp_object->data);
|
|
|
|
|
curve_to_mesh_eval_ensure(*temp_object);
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
|
2021-09-23 11:41:46 -05:00
|
|
|
/* If evaluating the curve replaced object data with different data, free the original data. */
|
|
|
|
|
if (temp_data != temp_object->data) {
|
2022-08-09 17:49:41 -05:00
|
|
|
if (GS(temp_data->name) == ID_CU_LEGACY) {
|
|
|
|
|
/* Clear edit mode pointers that were explicitly copied to the temporary curve. */
|
|
|
|
|
Curve *curve = reinterpret_cast<Curve *>(temp_data);
|
|
|
|
|
curve->editfont = nullptr;
|
|
|
|
|
curve->editnurb = nullptr;
|
|
|
|
|
}
|
2021-09-23 11:41:46 -05:00
|
|
|
BKE_id_free(nullptr, temp_data);
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-09-23 11:41:46 -05:00
|
|
|
Mesh *mesh = mesh_new_from_evaluated_curve_type_object(temp_object);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-12-29 16:53:02 -06:00
|
|
|
object_for_curve_to_mesh_free(temp_object);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-09-23 11:41:46 -05:00
|
|
|
return mesh;
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-16 13:49:21 +02:00
|
|
|
static Mesh *mesh_new_from_mball_object(Object *object)
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
{
|
|
|
|
|
/* NOTE: We can only create mesh for a polygonized meta ball. This figures out all original meta
|
|
|
|
|
* balls and all evaluated child meta balls (since polygonization is only stored in the mother
|
|
|
|
|
* ball).
|
|
|
|
|
*
|
2021-09-22 14:48:01 +10:00
|
|
|
* Create empty mesh so script-authors don't run into None objects. */
|
2022-08-17 10:20:25 -04:00
|
|
|
if (!DEG_is_evaluated_object(object)) {
|
2021-09-16 15:44:43 -05:00
|
|
|
return (Mesh *)BKE_id_new_nomain(ID_ME, ((ID *)object->data)->name + 2);
|
2018-05-08 17:44:54 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-08-17 10:20:25 -04:00
|
|
|
const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(object);
|
|
|
|
|
if (mesh_eval == nullptr) {
|
|
|
|
|
return (Mesh *)BKE_id_new_nomain(ID_ME, ((ID *)object->data)->name + 2);
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-05-20 13:18:24 -04:00
|
|
|
return BKE_mesh_copy_for_eval(*mesh_eval);
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-03-28 18:57:57 -04:00
|
|
|
static Mesh *mesh_new_from_mesh(Object *object, const Mesh *mesh)
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
{
|
2020-05-25 20:16:42 +10:00
|
|
|
/* While we could copy this into the new mesh,
|
|
|
|
|
* add the data to 'mesh' so future calls to this function don't need to re-convert the data. */
|
2022-10-12 20:55:26 -05:00
|
|
|
if (mesh->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH) {
|
2024-03-28 18:57:57 -04:00
|
|
|
BKE_mesh_wrapper_ensure_mdata(const_cast<Mesh *>(mesh));
|
2022-02-14 16:35:25 +01:00
|
|
|
}
|
|
|
|
|
else {
|
2024-03-28 18:57:57 -04:00
|
|
|
mesh = BKE_mesh_wrapper_ensure_subdivision(const_cast<Mesh *>(mesh));
|
2022-02-14 16:35:25 +01:00
|
|
|
}
|
2020-05-25 20:16:42 +10:00
|
|
|
|
2020-10-07 14:27:33 +02:00
|
|
|
Mesh *mesh_result = (Mesh *)BKE_id_copy_ex(
|
2021-09-16 15:44:43 -05:00
|
|
|
nullptr, &mesh->id, nullptr, LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT);
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
/* NOTE: Materials should already be copied. */
|
2019-05-16 17:59:45 +02:00
|
|
|
/* Copy original mesh name. This is because edit meshes might not have one properly set name. */
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(mesh_result->id.name, ((ID *)object->data)->name);
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
return mesh_result;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-05-12 23:14:58 +02:00
|
|
|
static Mesh *mesh_new_from_mesh_object_with_layers(Depsgraph *depsgraph,
|
|
|
|
|
Object *object,
|
|
|
|
|
const bool preserve_origindex)
|
2019-05-24 14:37:47 +02:00
|
|
|
{
|
|
|
|
|
if (DEG_is_original_id(&object->id)) {
|
|
|
|
|
return mesh_new_from_mesh(object, (Mesh *)object->data);
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-16 15:44:43 -05:00
|
|
|
if (depsgraph == nullptr) {
|
|
|
|
|
return nullptr;
|
2019-05-24 14:37:47 +02:00
|
|
|
}
|
|
|
|
|
|
2022-03-29 10:06:34 +02:00
|
|
|
Object object_for_eval = blender::dna::shallow_copy(*object);
|
2023-11-15 18:46:07 +01:00
|
|
|
blender::bke::ObjectRuntime runtime = *object->runtime;
|
|
|
|
|
object_for_eval.runtime = &runtime;
|
|
|
|
|
|
|
|
|
|
if (object_for_eval.runtime->data_orig != nullptr) {
|
|
|
|
|
object_for_eval.data = object_for_eval.runtime->data_orig;
|
2019-05-24 14:37:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Scene *scene = DEG_get_evaluated_scene(depsgraph);
|
|
|
|
|
CustomData_MeshMasks mask = CD_MASK_MESH;
|
2021-05-12 23:14:58 +02:00
|
|
|
if (preserve_origindex) {
|
|
|
|
|
mask.vmask |= CD_MASK_ORIGINDEX;
|
|
|
|
|
mask.emask |= CD_MASK_ORIGINDEX;
|
|
|
|
|
mask.lmask |= CD_MASK_ORIGINDEX;
|
|
|
|
|
mask.pmask |= CD_MASK_ORIGINDEX;
|
|
|
|
|
}
|
2024-05-20 12:26:07 -04:00
|
|
|
Mesh *result = blender::bke::mesh_create_eval_final(depsgraph, scene, &object_for_eval, &mask);
|
2022-06-24 16:16:43 -05:00
|
|
|
return BKE_mesh_wrapper_ensure_subdivision(result);
|
2019-05-24 14:37:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static Mesh *mesh_new_from_mesh_object(Depsgraph *depsgraph,
|
|
|
|
|
Object *object,
|
2021-05-12 23:14:58 +02:00
|
|
|
const bool preserve_all_data_layers,
|
|
|
|
|
const bool preserve_origindex)
|
2019-05-24 14:37:47 +02:00
|
|
|
{
|
2024-08-16 16:56:18 +02:00
|
|
|
/* This function tries to reevaluate the object from the original data. If the original object
|
|
|
|
|
* was not a mesh object, this won't work because it uses mesh object evaluation which assumes
|
|
|
|
|
* the type of the original object data. */
|
|
|
|
|
if (!(object->runtime->data_orig && GS(object->runtime->data_orig->name) != ID_ME) &&
|
|
|
|
|
(preserve_all_data_layers || preserve_origindex))
|
|
|
|
|
{
|
2021-05-12 23:14:58 +02:00
|
|
|
return mesh_new_from_mesh_object_with_layers(depsgraph, object, preserve_origindex);
|
2019-05-24 14:37:47 +02:00
|
|
|
}
|
2024-03-28 18:57:57 -04:00
|
|
|
const Mesh *mesh_input = (const Mesh *)object->data;
|
2019-05-24 14:37:47 +02:00
|
|
|
/* If we are in edit mode, use evaluated mesh from edit structure, matching to what
|
|
|
|
|
* viewport is using for visualization. */
|
2024-03-21 23:18:49 +01:00
|
|
|
if (mesh_input->runtime->edit_mesh != nullptr) {
|
2024-03-28 18:57:57 -04:00
|
|
|
if (const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(object)) {
|
2022-01-11 15:42:07 +01:00
|
|
|
mesh_input = editmesh_eval_final;
|
|
|
|
|
}
|
2019-05-24 14:37:47 +02:00
|
|
|
}
|
|
|
|
|
return mesh_new_from_mesh(object, mesh_input);
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-12 23:14:58 +02:00
|
|
|
Mesh *BKE_mesh_new_from_object(Depsgraph *depsgraph,
|
|
|
|
|
Object *object,
|
|
|
|
|
const bool preserve_all_data_layers,
|
|
|
|
|
const bool preserve_origindex)
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
{
|
2021-09-16 15:44:43 -05:00
|
|
|
Mesh *new_mesh = nullptr;
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
switch (object->type) {
|
|
|
|
|
case OB_FONT:
|
2022-02-18 09:50:29 -06:00
|
|
|
case OB_CURVES_LEGACY:
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
case OB_SURF:
|
2019-05-16 13:49:21 +02:00
|
|
|
new_mesh = mesh_new_from_curve_type_object(object);
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
break;
|
|
|
|
|
case OB_MBALL:
|
2019-05-16 13:49:21 +02:00
|
|
|
new_mesh = mesh_new_from_mball_object(object);
|
2018-05-08 17:44:54 +02:00
|
|
|
break;
|
|
|
|
|
case OB_MESH:
|
2021-05-12 23:14:58 +02:00
|
|
|
new_mesh = mesh_new_from_mesh_object(
|
|
|
|
|
depsgraph, object, preserve_all_data_layers, preserve_origindex);
|
2018-05-08 17:44:54 +02:00
|
|
|
break;
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
default:
|
|
|
|
|
/* Object does not have geometry data. */
|
2021-09-16 15:44:43 -05:00
|
|
|
return nullptr;
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
}
|
2021-09-16 15:44:43 -05:00
|
|
|
if (new_mesh == nullptr) {
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
/* Happens in special cases like request of mesh for non-mother meta ball. */
|
2021-09-16 15:44:43 -05:00
|
|
|
return nullptr;
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
}
|
2020-04-07 11:36:59 +02:00
|
|
|
|
2019-05-16 13:49:21 +02:00
|
|
|
/* The result must have 0 users, since it's just a mesh which is free-dangling data-block.
|
|
|
|
|
* All the conversion functions are supposed to ensure mesh is not counted. */
|
|
|
|
|
BLI_assert(new_mesh->id.us == 0);
|
2020-04-07 11:36:59 +02:00
|
|
|
|
|
|
|
|
/* It is possible that mesh came from modifier stack evaluation, which preserves edit_mesh
|
|
|
|
|
* pointer (which allows draw manager to access edit mesh when drawing). Normally this does
|
|
|
|
|
* not cause ownership problems because evaluated object runtime is keeping track of the real
|
|
|
|
|
* ownership.
|
|
|
|
|
*
|
2020-04-08 10:33:56 +10:00
|
|
|
* Here we are constructing a mesh which is supposed to be independent, which means no shared
|
2021-09-16 15:44:43 -05:00
|
|
|
* ownership is allowed, so we make sure edit mesh is reset to nullptr (which is similar to as if
|
2020-04-07 11:36:59 +02:00
|
|
|
* one duplicates the objects and applies all the modifiers). */
|
2024-03-21 23:18:49 +01:00
|
|
|
new_mesh->runtime->edit_mesh = nullptr;
|
2020-04-07 11:36:59 +02:00
|
|
|
|
Dependency graph API changes
Main goal here is to make it obvious and predictable about
what is going on.
Summary of changes.
- Access to dependency graph is now only possible to a fully evaluated
graph. This is now done via context.evaluated_depsgraph_get().
The call will ensure both relations and datablocks are updated.
This way we don't allow access to some known bad state of the graph,
and also making explicit that getting update dependency graph is not
cheap.
- Access to evaluated ID is now possible via id.evaluated_get().
It was already possible to get evaluated ID via dependency graph,
but that was a bit confusing why access to original is done via ID
and to evaluated via depsgraph.
If datablock is not covered by dependency graph it will be returned
as-is.
- Similarly, request for original from an ID which is not evaluated
will return ID as-is.
- Removed scene.update().
This is very expensive to update all the view layers.
- Added depsgraph.update().
Now when temporary changes to objects are to be done, this is to
happen on original object and then dependency graph is to be
updated.
- Changed object.to_mesh() to behave the following way:
* When is used for original object modifiers are ignored.
For meshes this acts similar to mesh-copy, not very useful but
allows to keep code paths similar (i.e. for exporter which has
Apply Modifiers option it's only matter choosing between original
and evaluated object, the to_mesh() part can stay the same).
For curves this gives a mesh which is constructed from displist
without taking own modifiers and modifiers of bevel/taper objects
into account.
For metaballs this gives empty mesh.
Polygonization of metaball is not possible from a single object.
* When is used for evaluated object modifiers are always applied.
In fact, no evaluation is happening, the mesh is either copied
as-is, or constructed from current state of curve cache.
Arguments to apply modifiers and calculate original coordinates (ORCO,
aka undeformed coordinates) are removed. The ORCO is to be calculated
as part of dependency graph evaluation.
File used to regression-test (a packed Python script into .blend):
{F7033464}
Patch to make addons tests to pass:
{F7033466}
NOTE: I've included changes to FBX exporter, and those are addressing
report T63689.
NOTE: All the enabled-by-default addons are to be ported still, but
first want to have agreement on this part of changes.
NOTE: Also need to work on documentation for Python API, but, again,
better be done after having agreement on this work.
Reviewers: brecht, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D4834
2019-05-09 11:26:49 +02:00
|
|
|
return new_mesh;
|
2018-05-08 17:44:54 +02:00
|
|
|
}
|
2018-06-01 17:05:21 +02:00
|
|
|
|
2020-02-13 12:56:10 +01:00
|
|
|
static int foreach_libblock_make_original_callback(LibraryIDLinkCallbackData *cb_data)
|
2019-05-16 13:49:21 +02:00
|
|
|
{
|
2020-02-13 12:56:10 +01:00
|
|
|
ID **id_p = cb_data->id_pointer;
|
2021-09-16 15:44:43 -05:00
|
|
|
if (*id_p == nullptr) {
|
2019-05-16 13:49:21 +02:00
|
|
|
return IDWALK_RET_NOP;
|
|
|
|
|
}
|
|
|
|
|
*id_p = DEG_get_original_id(*id_p);
|
2019-05-27 16:46:45 +02:00
|
|
|
|
2019-06-03 20:59:13 +02:00
|
|
|
return IDWALK_RET_NOP;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-13 12:56:10 +01:00
|
|
|
static int foreach_libblock_make_usercounts_callback(LibraryIDLinkCallbackData *cb_data)
|
2019-06-03 20:59:13 +02:00
|
|
|
{
|
2020-02-13 12:56:10 +01:00
|
|
|
ID **id_p = cb_data->id_pointer;
|
2021-09-16 15:44:43 -05:00
|
|
|
if (*id_p == nullptr) {
|
2019-06-03 20:59:13 +02:00
|
|
|
return IDWALK_RET_NOP;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-13 12:56:10 +01:00
|
|
|
const int cb_flag = cb_data->cb_flag;
|
2019-05-27 16:46:45 +02:00
|
|
|
if (cb_flag & IDWALK_CB_USER) {
|
|
|
|
|
id_us_plus(*id_p);
|
|
|
|
|
}
|
|
|
|
|
else if (cb_flag & IDWALK_CB_USER_ONE) {
|
2021-07-03 23:08:40 +10:00
|
|
|
/* NOTE: in that context, that one should not be needed (since there should be at least already
|
2019-05-27 16:46:45 +02:00
|
|
|
* one USER_ONE user of that ID), but better be consistent. */
|
|
|
|
|
id_us_ensure_real(*id_p);
|
|
|
|
|
}
|
2019-05-16 13:49:21 +02:00
|
|
|
return IDWALK_RET_NOP;
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-24 14:37:47 +02:00
|
|
|
Mesh *BKE_mesh_new_from_object_to_bmain(Main *bmain,
|
|
|
|
|
Depsgraph *depsgraph,
|
|
|
|
|
Object *object,
|
|
|
|
|
bool preserve_all_data_layers)
|
2019-05-16 13:49:21 +02:00
|
|
|
{
|
2022-02-18 09:50:29 -06:00
|
|
|
BLI_assert(ELEM(object->type, OB_FONT, OB_CURVES_LEGACY, OB_SURF, OB_MBALL, OB_MESH));
|
2019-08-02 17:45:32 +02:00
|
|
|
|
2021-05-12 23:14:58 +02:00
|
|
|
Mesh *mesh = BKE_mesh_new_from_object(depsgraph, object, preserve_all_data_layers, false);
|
2021-09-16 15:44:43 -05:00
|
|
|
if (mesh == nullptr) {
|
2019-08-02 17:45:32 +02:00
|
|
|
/* Unable to convert the object to a mesh, return an empty one. */
|
|
|
|
|
Mesh *mesh_in_bmain = BKE_mesh_add(bmain, ((ID *)object->data)->name + 2);
|
|
|
|
|
id_us_min(&mesh_in_bmain->id);
|
|
|
|
|
return mesh_in_bmain;
|
2019-07-10 12:58:39 +02:00
|
|
|
}
|
2019-05-16 13:49:21 +02:00
|
|
|
|
2024-04-10 16:06:34 -04:00
|
|
|
/* Make sure mesh only points to original data-blocks. Also increase user count of materials and
|
|
|
|
|
* other possibly referenced data-blocks.
|
2019-05-16 13:49:21 +02:00
|
|
|
*
|
2024-04-10 16:06:34 -04:00
|
|
|
* Changing to original data-blocks is required to have bmain in a consistent state, where
|
2019-05-16 13:49:21 +02:00
|
|
|
* everything is only allowed to reference original data-blocks.
|
|
|
|
|
*
|
2024-04-10 16:06:34 -04:00
|
|
|
* Note that user-count updates have to be done *after* the mesh has been transferred to Main
|
|
|
|
|
* database (since doing reference-counting on non-Main IDs is forbidden). */
|
2019-05-16 13:49:21 +02:00
|
|
|
BKE_library_foreach_ID_link(
|
2021-09-16 15:44:43 -05:00
|
|
|
nullptr, &mesh->id, foreach_libblock_make_original_callback, nullptr, IDWALK_NOP);
|
2019-05-16 13:49:21 +02:00
|
|
|
|
2024-04-10 16:06:34 -04:00
|
|
|
/* Add the mesh to 'bmain'. We do it in a bit longer way since there is no simple and clear way
|
|
|
|
|
* of adding existing data-blocks to the 'bmain'. So we create new empty mesh (which guarantees
|
|
|
|
|
* all the naming and order and flags) and move the temporary mesh in place there. */
|
2019-05-16 13:49:21 +02:00
|
|
|
Mesh *mesh_in_bmain = BKE_mesh_add(bmain, mesh->id.name + 2);
|
2019-05-17 18:23:06 +02:00
|
|
|
|
2024-04-10 16:06:34 -04:00
|
|
|
/* NOTE: BKE_mesh_nomain_to_mesh() does not copy materials and instead preserves them in the
|
2023-06-14 09:45:20 -04:00
|
|
|
* destination mesh. So we "steal" materials before calling it.
|
2019-05-17 18:23:06 +02:00
|
|
|
*
|
2024-04-10 16:06:34 -04:00
|
|
|
* TODO(sergey): We really ought to have a function which gets an ID and accepts it into #Main.
|
2019-05-17 18:23:06 +02:00
|
|
|
*/
|
|
|
|
|
mesh_in_bmain->mat = mesh->mat;
|
|
|
|
|
mesh_in_bmain->totcol = mesh->totcol;
|
2021-09-16 15:44:43 -05:00
|
|
|
mesh->mat = nullptr;
|
2019-05-17 18:23:06 +02:00
|
|
|
|
2022-09-09 08:24:31 -05:00
|
|
|
BKE_mesh_nomain_to_mesh(mesh, mesh_in_bmain, nullptr);
|
2019-05-16 13:49:21 +02:00
|
|
|
|
2022-02-16 15:58:27 +01:00
|
|
|
/* Anonymous attributes shouldn't exist on original data. */
|
2022-09-07 21:41:39 -05:00
|
|
|
mesh_in_bmain->attributes_for_write().remove_anonymous();
|
2022-02-16 15:58:27 +01:00
|
|
|
|
2019-06-03 20:59:13 +02:00
|
|
|
/* User-count is required because so far mesh was in a limbo, where library management does
|
|
|
|
|
* not perform any user management (i.e. copy of a mesh will not increase users of materials). */
|
|
|
|
|
BKE_library_foreach_ID_link(
|
2021-09-16 15:44:43 -05:00
|
|
|
nullptr, &mesh_in_bmain->id, foreach_libblock_make_usercounts_callback, nullptr, IDWALK_NOP);
|
2019-06-03 20:59:13 +02:00
|
|
|
|
2019-05-16 13:49:21 +02:00
|
|
|
/* Make sure user count from BKE_mesh_add() is the one we expect here and bring it down to 0. */
|
|
|
|
|
BLI_assert(mesh_in_bmain->id.us == 1);
|
|
|
|
|
id_us_min(&mesh_in_bmain->id);
|
|
|
|
|
|
|
|
|
|
return mesh_in_bmain;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-20 13:25:29 -05:00
|
|
|
static void copy_loose_vert_hint(const Mesh &src, Mesh &dst)
|
|
|
|
|
{
|
|
|
|
|
const auto &src_cache = src.runtime->loose_verts_cache;
|
|
|
|
|
if (src_cache.is_cached() && src_cache.data().count == 0) {
|
|
|
|
|
dst.tag_loose_verts_none();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void copy_loose_edge_hint(const Mesh &src, Mesh &dst)
|
|
|
|
|
{
|
|
|
|
|
const auto &src_cache = src.runtime->loose_edges_cache;
|
|
|
|
|
if (src_cache.is_cached() && src_cache.data().count == 0) {
|
|
|
|
|
dst.tag_loose_edges_none();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void copy_overlapping_hint(const Mesh &src, Mesh &dst)
|
|
|
|
|
{
|
|
|
|
|
if (src.no_overlapping_topology()) {
|
|
|
|
|
dst.tag_overlapping_none();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-09 08:24:31 -05:00
|
|
|
static KeyBlock *keyblock_ensure_from_uid(Key &key, const int uid, const StringRefNull name)
|
2018-06-01 17:05:21 +02:00
|
|
|
{
|
2022-09-09 08:24:31 -05:00
|
|
|
if (KeyBlock *kb = BKE_keyblock_find_uid(&key, uid)) {
|
|
|
|
|
return kb;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2022-09-09 08:24:31 -05:00
|
|
|
KeyBlock *kb = BKE_keyblock_add(&key, name.c_str());
|
|
|
|
|
kb->uid = uid;
|
|
|
|
|
return kb;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-09 08:24:31 -05:00
|
|
|
static int find_object_active_key_uid(const Key &key, const Object &object)
|
|
|
|
|
{
|
|
|
|
|
const int active_kb_index = object.shapenr - 1;
|
|
|
|
|
const KeyBlock *kb = (const KeyBlock *)BLI_findlink(&key.block, active_kb_index);
|
|
|
|
|
if (!kb) {
|
|
|
|
|
CLOG_ERROR(&LOG, "Could not find object's active shapekey %d", active_kb_index);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return kb->uid;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-10-04 12:09:44 -05:00
|
|
|
static void move_shapekey_layers_to_keyblocks(const Mesh &mesh,
|
2023-06-30 11:49:14 -04:00
|
|
|
const CustomData &custom_data,
|
2022-10-04 12:09:44 -05:00
|
|
|
Key &key_dst,
|
|
|
|
|
const int actshape_uid)
|
2022-09-09 08:24:31 -05:00
|
|
|
{
|
|
|
|
|
using namespace blender::bke;
|
2022-10-04 12:09:44 -05:00
|
|
|
for (const int i : IndexRange(CustomData_number_of_layers(&custom_data, CD_SHAPEKEY))) {
|
|
|
|
|
const int layer_index = CustomData_get_layer_index_n(&custom_data, CD_SHAPEKEY, i);
|
2023-06-30 11:49:14 -04:00
|
|
|
const CustomDataLayer &layer = custom_data.layers[layer_index];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-09 08:24:31 -05:00
|
|
|
KeyBlock *kb = keyblock_ensure_from_uid(key_dst, layer.uid, layer.name);
|
|
|
|
|
MEM_SAFE_FREE(kb->data);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-12-20 02:21:48 +01:00
|
|
|
kb->totelem = mesh.verts_num;
|
2023-06-30 11:49:14 -04:00
|
|
|
kb->data = MEM_malloc_arrayN(kb->totelem, sizeof(float3), __func__);
|
|
|
|
|
MutableSpan<float3> kb_coords(static_cast<float3 *>(kb->data), kb->totelem);
|
2018-06-01 17:05:21 +02:00
|
|
|
if (kb->uid == actshape_uid) {
|
2023-04-19 11:21:06 +02:00
|
|
|
mesh.attributes().lookup<float3>("position").varray.materialize(kb_coords);
|
2018-06-01 17:05:21 +02:00
|
|
|
}
|
|
|
|
|
else {
|
2023-12-20 02:21:48 +01:00
|
|
|
kb_coords.copy_from({static_cast<const float3 *>(layer.data), mesh.verts_num});
|
2018-06-01 17:05:21 +02:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-09 08:24:31 -05:00
|
|
|
LISTBASE_FOREACH (KeyBlock *, kb, &key_dst.block) {
|
2023-12-20 02:21:48 +01:00
|
|
|
if (kb->totelem != mesh.verts_num) {
|
2022-09-09 08:24:31 -05:00
|
|
|
MEM_SAFE_FREE(kb->data);
|
2023-12-20 02:21:48 +01:00
|
|
|
kb->totelem = mesh.verts_num;
|
2022-10-04 12:09:44 -05:00
|
|
|
kb->data = MEM_cnew_array<float3>(kb->totelem, __func__);
|
|
|
|
|
CLOG_ERROR(&LOG, "Data for shape key '%s' on mesh missing from evaluated mesh ", kb->name);
|
2018-06-01 17:05:21 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-09 08:24:31 -05:00
|
|
|
void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob)
|
2018-06-01 17:05:21 +02:00
|
|
|
{
|
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
|
|
|
using namespace blender::bke;
|
2024-08-07 12:12:17 +02:00
|
|
|
BLI_assert(mesh_src->id.tag & ID_TAG_NO_MAIN);
|
2018-06-01 17:05:21 +02:00
|
|
|
if (ob) {
|
2022-09-09 08:24:31 -05:00
|
|
|
BLI_assert(mesh_dst == ob->data);
|
2018-06-01 17:05:21 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-09-17 17:22:54 +10:00
|
|
|
const bool verts_num_changed = mesh_dst->verts_num != mesh_src->verts_num;
|
|
|
|
|
|
2023-04-12 11:27:52 -04:00
|
|
|
BKE_mesh_clear_geometry_and_metadata(mesh_dst);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-12-20 02:21:48 +01:00
|
|
|
mesh_dst->verts_num = mesh_src->verts_num;
|
|
|
|
|
mesh_dst->edges_num = mesh_src->edges_num;
|
2023-07-24 22:06:55 +02:00
|
|
|
mesh_dst->faces_num = mesh_src->faces_num;
|
2023-12-20 02:21:48 +01:00
|
|
|
mesh_dst->corners_num = mesh_src->corners_num;
|
2020-11-05 16:10:30 +11:00
|
|
|
|
2022-09-09 08:24:31 -05:00
|
|
|
/* Using #CD_MASK_MESH ensures that only data that should exist in Main meshes is moved. */
|
|
|
|
|
const CustomData_MeshMasks mask = CD_MASK_MESH;
|
2024-08-26 19:11:02 +02:00
|
|
|
CustomData_init_from(
|
|
|
|
|
&mesh_src->vert_data, &mesh_dst->vert_data, mask.vmask, mesh_src->verts_num);
|
|
|
|
|
CustomData_init_from(
|
|
|
|
|
&mesh_src->edge_data, &mesh_dst->edge_data, mask.emask, mesh_src->edges_num);
|
|
|
|
|
CustomData_init_from(
|
|
|
|
|
&mesh_src->face_data, &mesh_dst->face_data, mask.pmask, mesh_src->faces_num);
|
|
|
|
|
CustomData_init_from(
|
2023-12-19 20:38:59 -05:00
|
|
|
&mesh_src->corner_data, &mesh_dst->corner_data, mask.lmask, mesh_src->corners_num);
|
2023-07-24 22:06:55 +02:00
|
|
|
std::swap(mesh_dst->face_offset_indices, mesh_src->face_offset_indices);
|
|
|
|
|
std::swap(mesh_dst->runtime->face_offsets_sharing_info,
|
|
|
|
|
mesh_src->runtime->face_offsets_sharing_info);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-04-12 15:08:15 -04:00
|
|
|
/* Make sure attribute names are moved. */
|
|
|
|
|
std::swap(mesh_dst->active_color_attribute, mesh_src->active_color_attribute);
|
|
|
|
|
std::swap(mesh_dst->default_color_attribute, mesh_src->default_color_attribute);
|
|
|
|
|
std::swap(mesh_dst->vertex_group_names, mesh_src->vertex_group_names);
|
2022-09-09 08:24:31 -05:00
|
|
|
|
|
|
|
|
BKE_mesh_copy_parameters(mesh_dst, mesh_src);
|
|
|
|
|
|
|
|
|
|
/* For original meshes, shape key data is stored in the #Key data-block, so it
|
|
|
|
|
* must be moved from the storage in #CustomData layers used for evaluation. */
|
|
|
|
|
if (Key *key_dst = mesh_dst->key) {
|
2023-07-25 21:15:52 +02:00
|
|
|
if (CustomData_has_layer(&mesh_src->vert_data, CD_SHAPEKEY)) {
|
2022-09-09 08:24:31 -05:00
|
|
|
/* If no object, set to -1 so we don't mess up any shapekey layers. */
|
|
|
|
|
const int uid_active = ob ? find_object_active_key_uid(*key_dst, *ob) : -1;
|
2023-07-25 21:15:52 +02:00
|
|
|
move_shapekey_layers_to_keyblocks(*mesh_dst, mesh_src->vert_data, *key_dst, uid_active);
|
2022-09-09 08:24:31 -05:00
|
|
|
}
|
2022-10-18 15:57:47 -05:00
|
|
|
else if (verts_num_changed) {
|
|
|
|
|
CLOG_WARN(&LOG, "Shape key data lost when replacing mesh '%s' in Main", mesh_src->id.name);
|
|
|
|
|
id_us_min(&mesh_dst->key->id);
|
|
|
|
|
mesh_dst->key = nullptr;
|
2018-06-01 17:05:21 +02:00
|
|
|
}
|
|
|
|
|
}
|
Refactor: Move normals out of MVert, lazy calculation
As described in T91186, this commit moves mesh vertex normals into a
contiguous array of float vectors in a custom data layer, how face
normals are currently stored.
The main interface is documented in `BKE_mesh.h`. Vertex and face
normals are now calculated on-demand and cached, retrieved with an
"ensure" function. Since the logical state of a mesh is now "has
normals when necessary", they can be retrieved from a `const` mesh.
The goal is to use on-demand calculation for all derived data, but
leave room for eager calculation for performance purposes (modifier
evaluation is threaded, but viewport data generation is not).
**Benefits**
This moves us closer to a SoA approach rather than the current AoS
paradigm. Accessing a contiguous `float3` is much more efficient than
retrieving data from a larger struct. The memory requirements for
accessing only normals or vertex locations are smaller, and at the
cost of more memory usage for just normals, they now don't have to
be converted between float and short, which also simplifies code
In the future, the remaining items can be removed from `MVert`,
leaving only `float3`, which has similar benefits (see T93602).
Removing the combination of derived and original data makes it
conceptually simpler to only calculate normals when necessary.
This is especially important now that we have more opportunities
for temporary meshes in geometry nodes.
**Performance**
In addition to the theoretical future performance improvements by
making `MVert == float3`, I've done some basic performance testing
on this patch directly. The data is fairly rough, but it gives an idea
about where things stand generally.
- Mesh line primitive 4m Verts: 1.16x faster (36 -> 31 ms),
showing that accessing just `MVert` is now more efficient.
- Spring Splash Screen: 1.03-1.06 -> 1.06-1.11 FPS, a very slight
change that at least shows there is no regression.
- Sprite Fright Snail Smoosh: 3.30-3.40 -> 3.42-3.50 FPS, a small
but observable speedup.
- Set Position Node with Scaled Normal: 1.36x faster (53 -> 39 ms),
shows that using normals in geometry nodes is faster.
- Normal Calculation 1.6m Vert Cube: 1.19x faster (25 -> 21 ms),
shows that calculating normals is slightly faster now.
- File Size of 1.6m Vert Cube: 1.03x smaller (214.7 -> 208.4 MB),
Normals are not saved in files, which can help with large meshes.
As for memory usage, it may be slightly more in some cases, but
I didn't observe any difference in the production files I tested.
**Tests**
Some modifiers and cycles test results need to be updated with this
commit, for two reasons:
- The subdivision surface modifier is not responsible for calculating
normals anymore. In master, the modifier creates different normals
than the result of the `Mesh` normal calculation, so this is a bug
fix.
- There are small differences in the results of some modifiers that
use normals because they are not converted to and from `short`
anymore.
**Future improvements**
- Remove `ModifierTypeInfo::dependsOnNormals`. Code in each modifier
already retrieves normals if they are needed anyway.
- Copy normals as part of a better CoW system for attributes.
- Make more areas use lazy instead of eager normal calculation.
- Remove `BKE_mesh_normals_tag_dirty` in more places since that is
now the default state of a new mesh.
- Possibly apply a similar change to derived face corner normals.
Differential Revision: https://developer.blender.org/D12770
2022-01-13 14:37:58 -06:00
|
|
|
|
2023-11-27 09:37:29 +11:00
|
|
|
/* Caches can have a large memory impact and aren't necessarily used, so don't indiscriminately
|
2023-11-20 13:25:29 -05:00
|
|
|
* store all of them in the #Main data-base mesh. However, some caches are quite small and
|
|
|
|
|
* copying them is "free" relative to how much work would be required if the data was needed. */
|
|
|
|
|
copy_loose_vert_hint(*mesh_src, *mesh_dst);
|
|
|
|
|
copy_loose_edge_hint(*mesh_src, *mesh_dst);
|
|
|
|
|
copy_overlapping_hint(*mesh_src, *mesh_dst);
|
|
|
|
|
|
2022-09-09 08:24:31 -05:00
|
|
|
BKE_id_free(nullptr, mesh_src);
|
2018-06-01 17:05:21 +02:00
|
|
|
}
|
|
|
|
|
|
2018-06-06 10:30:24 +02:00
|
|
|
void BKE_mesh_nomain_to_meshkey(Mesh *mesh_src, Mesh *mesh_dst, KeyBlock *kb)
|
2018-06-01 17:05:21 +02:00
|
|
|
{
|
2024-08-07 12:12:17 +02:00
|
|
|
BLI_assert(mesh_src->id.tag & ID_TAG_NO_MAIN);
|
2020-03-13 17:16:38 +01:00
|
|
|
|
2023-12-20 02:21:48 +01:00
|
|
|
const int totvert = mesh_src->verts_num;
|
2018-06-01 17:05:21 +02:00
|
|
|
|
2023-12-20 02:21:48 +01:00
|
|
|
if (totvert == 0 || mesh_dst->verts_num == 0 || mesh_dst->verts_num != totvert) {
|
2018-06-01 17:05:21 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (kb->data) {
|
2018-06-01 17:05:21 +02:00
|
|
|
MEM_freeN(kb->data);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2023-12-20 02:21:48 +01:00
|
|
|
kb->data = MEM_malloc_arrayN(mesh_dst->key->elemsize, mesh_dst->verts_num, "kb->data");
|
2018-06-01 17:05:21 +02:00
|
|
|
kb->totelem = totvert;
|
Mesh: Move positions to a generic attribute
**Changes**
As described in T93602, this patch removes all use of the `MVert`
struct, replacing it with a generic named attribute with the name
`"position"`, consistent with other geometry types.
Variable names have been changed from `verts` to `positions`, to align
with the attribute name and the more generic design (positions are not
vertices, they are just an attribute stored on the point domain).
This change is made possible by previous commits that moved all other
data out of `MVert` to runtime data or other generic attributes. What
remains is mostly a simple type change. Though, the type still shows up
859 times, so the patch is quite large.
One compromise is that now `CD_MASK_BAREMESH` now contains
`CD_PROP_FLOAT3`. With the general move towards generic attributes
over custom data types, we are removing use of these type masks anyway.
**Benefits**
The most obvious benefit is reduced memory usage and the benefits
that brings in memory-bound situations. `float3` is only 3 bytes, in
comparison to `MVert` which was 4. When there are millions of vertices
this starts to matter more.
The other benefits come from using a more generic type. Instead of
writing algorithms specifically for `MVert`, code can just use arrays
of vectors. This will allow eliminating many temporary arrays or
wrappers used to extract positions.
Many possible improvements aren't implemented in this patch, though
I did switch simplify or remove the process of creating temporary
position arrays in a few places.
The design clarity that "positions are just another attribute" brings
allows removing explicit copying of vertices in some procedural
operations-- they are just processed like most other attributes.
**Performance**
This touches so many areas that it's hard to benchmark exhaustively,
but I observed some areas as examples.
* The mesh line node with 4 million count was 1.5x (8ms to 12ms) faster.
* The Spring splash screen went from ~4.3 to ~4.5 fps.
* The subdivision surface modifier/node was slightly faster
RNA access through Python may be slightly slower, since now we need
a name lookup instead of just a custom data type lookup for each index.
**Future Improvements**
* Remove uses of "vert_coords" functions:
* `BKE_mesh_vert_coords_alloc`
* `BKE_mesh_vert_coords_get`
* `BKE_mesh_vert_coords_apply{_with_mat4}`
* Remove more hidden copying of positions
* General simplification now possible in many areas
* Convert more code to C++ to use `float3` instead of `float[3]`
* Currently `reinterpret_cast` is used for those C-API functions
Differential Revision: https://developer.blender.org/D15982
2023-01-10 00:10:43 -05:00
|
|
|
MutableSpan(static_cast<float3 *>(kb->data), kb->totelem).copy_from(mesh_src->vert_positions());
|
2018-06-01 17:05:21 +02:00
|
|
|
}
|