D11591: Alembic: import arbitrary attributes adds arbitrary attribute import to the Alembic importer, which allows for attributes other than UVs, vertex colors, and generated coordinates to be imported.
It also introduces a remapping system whose main purpose is to fix data exported by external software who:
- may not be in the right type: we may have a vec3 (float3) attribute that is not typed as such, but as a flat array of floats that is 3 times the size of the expected domain (a popular node based software does this a lot)
- may be set in a domain that Blender does not support for the type: we may also have a UV map that is set on the vertex domain, but we only allow for face corner domain
- may have an ambiguous or unknown domain, where two potential domains have the same size: e.g. a torus has the same number of faces and vertices, so we need to know where to load the data, there are cases in the current code where this fails
The second point is an extension and replacement of rB3385c04598f2: Alembic: support reading per-vertex UV sets.
Scope ambiguity
Alembic actually has some ambiguous scope enumeration, that may be interpreted or used differently:
- kVaryingScope is left to interpretation. Is it varying over the faces, vertices, or something else?
- kUniformScope should be for the entire object (i.e. a single value, that could be loaded as IDProperty), but some use it with kVaryingScope to differentiate between vertices/points and face corners
- kFacevaryingScope is face corners, but can be used to say that the data is for this domain, but written in another domain (likely point domain)
Without remapping, the patch already tries a little to salvage the data when these are used by trying different domains. E.g. for kFacevaryingScope, if face corner is not matching, we try point instead. Although, without a user defined mapping, those checks expect the data size to match.
Another dimension to the problem, is that in Alembic, arrays can have optional index buffers which should be used to determine the actual scope. If there is an index buffer, then surely the data must be the right type, and not some flattened vector.
Limitations
The remapping system only allows to change the type of an attribute if the data size matches (see first point above) and if the domain allows it. For example, a vec2 (float2 in Blender) can be converted to UV map. But we can not convert a float3 to a UV map with it. These types of processing are better left to Geometry Nodes.
Essentially, the remapping system places the burder of telling to Blender what the data is supposed to be on the users so Blender does not have to make wild guesses.
Implementation details.
Attributes are read during import, and during modifier evaluation if they are animated or if the modifiers' or cache file's settings for attributes are modified. Those settings include the already existing read flags (which affect UVs), the standard name of the velocity attribute, and the newly introduced attribute remappings. These settings, along with the output for error messages, are stored in some AttributeReadHelper class to keep them together, and to avoid having too many parameters to functions. Since settings can change, AttributeReadHelper are temporary objects which are created during import and modifier evaluation.
Attributes from the Alembic schemas are analyzed and only attributes which are supposed to be read given the settings (excluding remappings at this step) stored in AttributeReadHelper are considered for import/streaming. Then, we verify if the attribute can be actually loaded to its target destination (e.g. that vertex attributes map to vertices). For this, we use CacheAttributeMappings. If there is no user supplied mapping for the current attribute (looked up via AttributeReadHelper), we create a default one given what we expect the attribute to be and on which domain it should be read. If reading the attribute given this mapping fails, we skip it, an error is printed in the console, and users are notified via a note on the modifiers' UI.