Commit Graph

35 Commits

Author SHA1 Message Date
2995165148 Cleanup: simplify wrapping CurvesGeometry in C++ 2023-01-31 18:45:55 +01:00
Martijn Versteegh
6c774feba2 Mesh: Move UV layers to generic attributes
Currently the `MLoopUV` struct stores UV coordinates and flags related
to editing UV maps in the UV editor. This patch changes the coordinates
to use the generic 2D vector type, and moves the flags into three
separate boolean attributes. This follows the design in T95965, with
the ultimate intention of simplifying code and improving performance.

Importantly, the change allows exporters and renderers to use UVs
"touched" by geometry nodes, which only creates generic attributes.
It also allows geometry nodes to create "proper" UV maps from scratch,
though only with the Store Named Attribute node for now.

The new design considers any 2D vector attribute on the corner domain
to be a UV map. In the future, they might be distinguished from regular
2D vectors with attribute metadata, which may be helpful because they
are often interpolated differently.

Most of the code changes deal with passing around UV BMesh custom data
offsets and tracking the boolean "sublayers". The boolean layers are
use the following prefixes for attribute names: vert selection: `.vs.`,
edge selection: `.es.`, pinning: `.pn.`. Currently these are short to
avoid using up the maximum length of attribute names. To accommodate
for these 4 extra characters, the name length limit is enlarged to 68
bytes, while the maximum user settable name length is still 64 bytes.

Unfortunately Python/RNA API access to the UV flag data becomes slower.
Accessing the boolean layers directly is be better for performance in
general.

Like the other mesh SoA refactors, backward and forward compatibility
aren't affected, and won't be changed until 4.0. We pay for that by
making mesh reading and writing more expensive with conversions.

Resolves T85962

Differential Revision: https://developer.blender.org/D14365
2023-01-10 01:01:43 -05:00
1af62cb3bf 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
08b2d04021 Cleanup: Use std::swap instead of macro in C++ code 2023-01-09 11:30:36 -05:00
6514bb05ea Mesh: Store active & default color attributes with strings
Attributes are unifying around a name-based API, and we would like to
be able to move away from CustomData in the future. This patch moves
the identification of active and fallback (render) color attributes
to strings on the mesh from flags on CustomDataLayer. This also
removes some ugliness used to retrieve these attributes and maintain
the active status.

The design is described more here: T98366

The patch keeps forward compatibility working until 4.0 with
the same method as the mesh struct of array refactors (T95965).

The strings are allowed to not correspond to an attribute, to allow
setting the active/default attribute independently of actually filling
its data. When applying a modifier, if the strings don't match an
attribute, they will be removed.

The realize instances / join node and join operator take the names from
the first / active input mesh. While other heuristics may be helpful
(and could be a future improvement), just using the first is simple
and predictable.

Differential Revision: https://developer.blender.org/D15169
2022-12-15 14:21:35 -06:00
ca1642cd0c Cleanup: Use string argument for attribute API function
Instead of CustomDataLayer, which exposes the internal implementation
more than necessary, and requires that the layer is always available,
which isn't always true.
2022-11-10 15:29:21 -06:00
f68cfd6bb0 Cleanup: replace C-style casts with functional casts for numeric types 2022-09-25 20:17:08 +10:00
c7b247a118 Cleanup: replace static_casts with functional casts for numeric types 2022-09-25 18:31:10 +10:00
d5df23d758 Cleanup: Rename attribute required functions
Avoid "customdata" in the name, since that's an implementation detail
in this context.
2022-09-15 13:14:31 -05:00
d593497421 Cleanup: Use C++ methods to retrieve attribute accessors
Replace `mesh_attributes`, `mesh_attributes_for_write` and the point
cloud versions with methods on the `Mesh` and `PointCloud` types.
This makes them friendlier to use and improves readability.

Differential Revision: https://developer.blender.org/D15907
2022-09-07 21:41:39 -05:00
9c4c9a889d Cleanup: use 'continue' in customdata for loop, reduce right shift 2022-09-07 09:02:59 +10:00
6602f30225 Cleanup: early exit when the active layer disallows procedural access
Once the active layer index is reached, there is no need to keep
searching. Return early instead.
2022-09-06 17:16:04 +10:00
4b818b1513 Merge branch 'blender-v3.3-release' 2022-09-03 11:43:15 +02:00
a50ca6a1cd Fix T100687: Geometry Attribute Convert crashes in sculpt mode
Since above commit, `BKE_id_attributes_active_get` would also return
"internal" attributes like ".hide_poly" or ".hide_vert".
As a consequence, a couple of poll functions dont return false anymore
(attribute remove, attribute convert), allowing these operators to
execute, but acting on this "internal" layers is just asking for
trouble.

In the UI, we dont see these attributes, because `MESH_UL_attributes`
checks `is_internal`, same thing we do now in
`BKE_id_attributes_active_get`.

Maniphest Tasks: T100687

Differential Revision: https://developer.blender.org/D15833
2022-09-03 11:30:51 +02:00
70035e6473 Cleanup: break before the default case in switch statements
While missing the break before a default that only breaks isn't
an error, it means adding new cases needs to remember to add the
break for an existing case, changing the default case will also
result in an unintended fall-through.

Also avoid `default:;` and add an explicit break.
2022-08-31 16:01:29 +10:00
25237d2625 Attributes: Improve custom data initialization options
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.

The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
  * Usually zeroes, but for colors this is white (how it was before).
  * Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
  * Only necessary or defined for non-trivial types like vertex groups.
  * Doesn't do anything for trivial types like `int` or `float3`.
  * Should be used every other time, when all values will be set.

The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.

Differential Revision: https://developer.blender.org/D15617
2022-08-30 14:56:05 -05:00
6577d2df8c Cleanup: Use const for custom data layers 2022-08-29 17:00:46 -05:00
Tom Edwards
35df9f80b9 Fix T99576: Guard against empty names when removing attributes
It's possible for misbehaving scripts written before 3.3 to reach
this state and crash Blender. With this change, the error is reduced
to a Python exception.

Differential Revision: https://developer.blender.org/D15724
2022-08-29 14:45:55 -05:00
Ethan-Hall
177bc80748 Fix: add attribute with empty string name crash
Due to a recent change, empty strings are unhandled. This results
in Blender crashing.

This patch fixes the crash but a discrepancy still exists...
Prior to the regression, the empty string would be replaced by the
name of the data type. This patch uses "Attribute" for the default
name regardless of type. Restoring the previous behavior would
require making and/or modifying API methods.

Regression introduced in: rBeae36be372a6

Reviewed By: Joseph Eagar & Campbell Barton
Differential Revision: https://developer.blender.org/D14734
Ref D14734
2022-08-03 15:16:46 -07:00
d567785658 Fix T99816: renaming attribute works incorrectly
This fixes two issues:
* There was a crash when the new attribute name was empty.
* The attribute name was incremented (e.g. "Attribute.001") when
  the old and new name were the same.
2022-07-25 13:16:59 +02:00
31365c6b9e Attributes: Use new API for C-API functions
Use the C++ API to implement more of the existing C functions.
This corrects the cases where one tries to add a builtin attribute
with the wrong domain or type on curves, though a better warning
message would be helpful in the future, and also reduces duplication
of the internal logic. Not much more is possible without changing
the interface.
2022-07-24 12:46:28 -05:00
c94c0d988a Fix: Removing attributes from UI invalidates caches
Use the new attribute API to implement the attribute remove function
used by RNA, except for BMesh attributes. Currently, removing curve
attributes from the panel in the property editor does not mark the
relevant caches dirty (for example, the cache of curve type counts),
because that behavior is implemented with the new attribute API.
Also, eventually we want to merge the two APIs, and removing an
attribute is the first function that can be partially implemented
with the new API.

Differential Revision: https://developer.blender.org/D15495
2022-07-23 19:59:59 -05:00
b876ce2a4a Geometry Nodes: new geometry attribute API
Currently, there are two attribute API. The first, defined in `BKE_attribute.h` is
accessible from RNA and C code. The second is implemented with `GeometryComponent`
and is only accessible in C++ code. The second is widely used, but only being
accessible through the `GeometrySet` API makes it awkward to use, and even impossible
for types that don't correspond directly to a geometry component like `CurvesGeometry`.

This patch adds a new attribute API, designed to replace the `GeometryComponent`
attribute API now, and to eventually replace or be the basis of the other one.

The basic idea is that there is an `AttributeAccessor` class that allows code to
interact with a set of attributes owned by some geometry. The accessor itself has
no ownership. `AttributeAccessor` is a simple type that can be passed around by
value. That makes it easy to return it from functions and to store it in containers.

For const-correctness, there is also a `MutableAttributeAccessor` that allows
changing individual and can add or remove attributes.

Currently, `AttributeAccessor` is composed of two pointers. The first is a pointer
to the owner of the attribute data. The second is a pointer to a struct with
function pointers, that is similar to a virtual function table. The functions
know how to access attributes on the owner.

The actual attribute access for geometries is still implemented with the `AttributeProvider`
pattern, which makes it easy to support different sources of attributes on a
geometry and simplifies dealing with built-in attributes.

There are different ways to get an attribute accessor for a geometry:
* `GeometryComponent.attributes()`
* `CurvesGeometry.attributes()`
* `bke::mesh_attributes(const Mesh &)`
* `bke::pointcloud_attributes(const PointCloud &)`

All of these also have a `_for_write` variant that returns a `MutabelAttributeAccessor`.

Differential Revision: https://developer.blender.org/D15280
2022-07-08 16:16:56 +02:00
f5e7221fbd Cleanup: Fix const correctness of attribute search function
Retrieving a mutable custom data layer from a const ID
should not be possible.
2022-06-14 17:26:07 +02:00
58a67e6fb6 Attributes: Adjustments to duplicate attribute API function
Use a name argument, for the same reasons as 6eea5f70e3.
Also reuse the layer and unique name creation in `BKE_id_attribute_new`
instead of reimplementing it. Also include a few miscellaneous cleanups
like using const variables and `std::string`.
2022-06-14 16:41:43 +02:00
Dennis Ranish
9c28f0eb37 D14823: Adds operator to duplicate the active color attribute layer
Fixes T97706

Adds operator to duplicate the active color attribute layer.
Adds `"Color Attribute Specials"` menu to color attribute ui to access the `"geometry.color_attribute_duplicate"` operator.
Internally adds a function that duplicates a referenced CustomDataLayer
- `BKE_id_attribute_duplicate` mostly copies the existing `BKE_id_attribute_new`
- but gets the type and domain from the referenced layer
- and copies the data from the old layer into the new layer

Reviewed By: Joseph Eagar & Hans Goudey & Julien Kaspar
Differential Revision: https://developer.blender.org/D14823
Ref D14823
2022-06-08 12:10:32 -07:00
6eea5f70e3 Attributes: Use names instead of layers for some functions
This mirrors the C++ attribute API better, separates the implementation
of attributes from CustomData slightly, and makes functions simpler,
clearer, and safer.

Also fix an issue with removing an attribute caused by 97712b018d
meant the first attribute with the given type was removed instead of
the attribute with the given name.
2022-06-08 10:48:19 +02:00
9fda233897 Cleanup: Use const pointers in attribute API 2022-06-07 18:55:56 +02:00
d39e0f9616 Fix: Incorrect logic in attribute search function
If a geometry does not have CustomData for a certain domain,
it may still have CustomData on other domains. In that case
we need to continue to the other domains instead of returning.
This worked for meshes because the domains are all at the
start of the `info` array. It didn't work for curves.
2022-06-07 18:38:39 +02:00
Martijn Versteegh
1203bd58be Fix: Make renaming attributes check uniqueness on all domains
This function only checked for uniqueness in the current domain,
while attribute names should be unique among all domains within
a geometry.

Differential Revision: https://developer.blender.org/D15144
2022-06-07 14:52:27 +02:00
44bac4c8cc Cleanup: use 'e' prefix for enum types
- CustomDataType -> eCustomDataType
- CustomDataMask -> eCustomDataMask
- AttributeDomain -> eAttrDomain
- NamedAttributeUsage -> eNamedAttrUsage
2022-06-01 15:38:48 +10:00
0e8d6c2828 Cleanup: conversion from enum/int warning 2022-06-01 14:30:57 +10:00
b38a59881b Merge branch 'blender-v3.2-release' 2022-05-31 16:35:22 -07:00
4669178fc3 Attributes: Hide internal UI attributes and disallow procedural access
This commit hides "UI attributes" described in T97452 from the UI lists
in mesh, curve, and point cloud properties, and disallow accessing them
in geometry nodes.

Internal UI attributes like selection and hiding values should use the
attribute system for simplicity and performance, but we don't want to
expose those attributes in the attribute panel, which is meant for
regular user interaction. Procedural access may be misleading or cause
problems, as described in the design task above.

These attributes are added by two upcoming patches: D14934, D14685

Differential Revision: https://developer.blender.org/D15069
2022-05-31 13:20:16 +02:00
b24e091c5a Cleanup: Move attribute.c to C++ 2022-05-30 18:06:39 +02:00