* Recompute bounding boxes with morph targets
* Reduce the number of heap allocation while recomputing bounding boxes
Co-authored-by: Romain Guy <romainguy@curious-creature.com>
The immutable inverse bind matrices can be shared among instances, so
they are now stored in Asset, not in Instance.
Also, there are now two "load" phases for skinning data:
(1) storing the inverse bind matrices
(2) building the Entity mappings (for animation efficiency)
Phase 1 is done in `ResourceLoader` because inverse bind matrices can
live in an external bin file.
Phase 2 is done during Instance creation, because that's when entities
are created.
Prior to this change, `recomputeBoundingBoxes` was an opt-in config
parameter in ResourceLoader. It is now a method on FilamentInstance.
The old API did not work for dynamically created instances. Since this
is a relatively obscure feature, we considered removing it completely,
especially since the computation requires the presence of CPU-side
vertex data combined with the transform hierarchy.
Instead of removing the feature, we decided to move it to a better
place. This paves the way for some upcoming improvements, which include
reducing the memory footprint for assets. It also improves overall code
organization and separation of concerns.
This change was motivated by some internal work at Google and has the
benefit of simplifying the gltfio API and implementation. There are 2
major API changes:
(1) Consolidate separate loader entry points for GLB and GLTF.
The distinction between GLB and GLTF can be made from the file content
alone, because GLB has a 4-byte magic string in its header. There is no
need for separate entry points. Clients do not (and should not) need
to check the file name extension.
(2) Remove the distinction between "instanced" and "non-instanced"
glTF assets.
In the new scheme, all assets have at least 1 instance.
Broadly speaking, in gltfio an "asset" is a collection of Filament
objects like textures and vertex buffers, while an "instance" is a
collection of entities and components (e.g. the transform hierarchy).
This API change makes life easier for clients because they no longer
need to decide a priori if they will ever need to add instances.
This change also moves some public-facing methods from FilamentAsset to
FilamentInstance:
- getSkinCount, getSkinNameAt
- getJointCountAt, getJointsAt
- attachSkin, detachSkin
In the past there was an API gotcha because users had to "get" the
animator before releasing the glTF source data. This could have been
surprising because it was a getter method, not a factory method.
This was due to overeager optimization on my part, I wanted to avoid
animator overhead for non-animated models, when in fact it has very
little overhead.
Moreover, the animator is conceivably useful even when there are no
pre-supplied animations (e.g. for applying skins), so let's just create
it unconditionally.
Motivated by #5299.
The gltfio API allows users to destroy ResourceLoader or FilamentAsset
even when various asynchronous work (e.g. uploading buffers to the GPU)
has not yet been completed. This was achieved in an error-prone manner
using manual reference counting and an internal management object called
AssetPool.
This PR refactors gltfio by wrapping cgltf_data in shared_ptr, which I
usually try to avoid. However in this case it provides the precisely the
functionality that is needed.
I tested this PR for memory leaks and crashes by hacking gltf_viewer
and monitoring memory usage in Activity Monitor.
This fixes#3383 and makes it easier to implement some missing features,
such as animation support for instanced assets.
This adds createInstancedAsset() to AssetLoader, which creates a master
asset and a set of slave instances. Vertex buffers, index buffers,
textures, and material instances are shared. Entities and components are
duplicated.
Instances have their own API object that is very simple. Light sources
and material instances are not instanced, so are not accessible through
the instance API object.
The master-slave ownership model lets us avoid complex shared ownership
semantics. The existing cache structures in AssetLoader allow the
implementation of this feature to be fairly simple.
The master asset exposes the union of all entities and allows clients to
modify all instances en masse if they wish. This design also works
naturally with ResourceLoader, which does not need to know about
instancing. For example, asynchronous loading is completely unchanged;
the dependency graph simply contains the union of entities across all
instances.
Support for animation is added in a subsequent commit.
Fixes#1513.