gltfio can now ask the material provider plugin which `Material` would
be used for a given set of requirements. Prior to this change, gltfio
could only create a new `MaterialInstance`.
This method is necessary to support an upcoming gltfio feature.
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
We still use resgen for convience, but the archive is now passed in
from the client application.
This will allow us to shrink the gltfio Android library (stay tuned).
- For completion, FilamentAsset now has getRenderableEntities(). This is
similar to sister methods getLightEntities() and getCameraEntities()
except there is no need to store a separate array.
- The web helmet demo does not need to enable shadows, they are already
enabled.
- The ViewerGui populateAsset() method was doing two things that are
now decoupled for clarity: setAsset() and populateAsset().
- The updateRootTransform() method is now called only when the autoscale
checkbox is toggled, instead of every frame.
- The getFooEntities() methods in Java now skip doing work for empty
lists. Actually these should not return arrays at all, but let's fix
that later, since it will break backwards compatibility.
This adds a new implementation of the TextureProvider interface called
Ktx2Provider.
Tested using the KTX2 variant of the StainedGlassLamp model in the
Khronos samples repo.
Tested on WebGL 2.0 (Chrome v100), Android (Pixel 6 Pro), and Desktop
(Metal, OpenGL, and Vulkan via MoltenVK).
This allows clients to provide their own asynchronous texture decoders
for various mime-typed images. This is a plug-in component for gltfio,
in some ways similar to MaterialProvider.
There are two motivations for this: to decouple gltfio from STB and
to make it easier to integrate support for BasisU textures.
This also has the side effect of simplifying ResourceLoader, since the
texture decoding jobs have been moved out.
As part of this work, I made the "stb" CMake target into a traditional
static library. Previously we had several files called `Image.cpp`
whose sole purpose was to enable STB_IMAGE_IMPLEMENTATION.
This is a gltfio API change (!)
Jave clients now need to call destroy on MaterialProvider.
Previously, the Java AssetLoader took over ownership of a native
material provider upon construction, but this was neither documented
nor consistent with the C++ layer. (This is historical; in the past we
did not expose MaterialProvider to Java.)
One motivation for this (aside from API consistency) is that users may
wish to preserve the material cache from one run to another.
Fixes#5132.
* Get the morph target count from the renderable
* Set the morph target count by Builder
* Update morph target weights partially
* Remove noexcept at functions could throw exceptions
* Update Java bindings at RenderableManager
* Add missing comments
* Update morph target weights from offset
Co-authored-by: Mathias Agopian <mathias@google.com>
This adds some significant JNI glue in order to make the Java API for
gltfio materials much more consistent with C++, and create feature
parity between the two languages.
The motivation is to allow Java clients to provide their own
ubershader-based solution or filamat-based solution.
- The `MaterialProvider` Java class is now an interface.
- The `UbershaderLoader` Java class is now a concrete implementation.
- Users can now write their own provider class using Java / Kotlin.
To streamline the amount of JNI work that occurs at run time, the
MaterialProvider Java interface uses ints in a couple spots instead
of enums. This sacrafices some readability for Java clients who wish
to write their own provider, but makes the JNI much simpler.
This replaces #3975.
This allows clients to obtain the extras strings for the asset and
for individual nodes. Note that extras for buffer views, accessors, etc
are not supported, although C++ clients can access the raw cgltf data
directly if they need to.
Tested in Android Studio by starting sample-gltf-viewer and typing the
following into the debugger:
modelViewer.asset!!.getFirstEntityByName("Drone_Body")
modelViewer.asset!!.getEntitiesByName("Drone_Body")
modelViewer.asset!!.getEntitiesByPrefix("Drone")
glTF assets are required to provide min/max attributes for POSITION,
so in theory we never need to compute the AABB. However the option is
still there.
This PR also makes it so that Java clients can choose this option,
previously it was hardcoded for all non-native clients.
Tested locally by hacking gltf-viewer on Android, added the following
lines to MainActivity:
```kotlin
for (mat in modelViewer.asset!!.materialInstances) {
Log.d("gltf-viewer", mat.name)
}
```
Static JNI lookups were causing issues with multiple libraries.
We now do the lookups when we need them as they are effectively
just hashmap lookups and we do them only in places where the
work we need to perform will be much larger than a simple hash
map lookup anyway.
This chane also manually registers filament-utils JNI bindings
to get rid of unnecessary symboles. We should do the same for
other Filament libraries (the symbols are pretty long and
we now have many of them).
For Android and wasm we do not use the filesystem and therefore do not
need `utils::Path`.
```
libgltfio-jni.so BEFORE 1.9 MB (693 KB gzipped)
libgltfio-jni.so AFTER 1.4 MB (542 KB gzipped)
```
This feature adds one new method to `FilamentAsset` and uses it in our
Kotlin, JavaScript, and C++ helpers:
utils::Entity popRenderable() noexcept;
This pops a ready renderable off an internal queue, or returns 0 if no
renderables have become ready. It provides a simple way for clients to
gradually add renderables to the scene as they become ready. Previously
clients could only get the entire list of entities, regardless of
whether they had Renderable components or complete textures.
To facilitate this feature, this PR adds a new internal-only class to
gltfio called `DependencyGraph`, which is a temporary object used for
bookkeeping during the asynchronous load.
`DependencyGraph` discovers ready-to-render entities by tracking the
textures that each entity depends on. This is a graph because
renderables connect to a set of material instances, which in turn
connect to a set of parameter names, which in turn connect to a set of
texture objects. These relationships are not easily inspectable using
the Filament API or ECS.
We were already using jobs for decoding PNG and JPEG files, but we were
doing a join. This add three methods to ResourceLoader that allow
clients to amortize the decoding process across multiple frames, even on
single-threaded platforms like WebGL.
This PR adds async loading to the following demos:
- samples/gltf_viewer (now shows a progress bar in the UI)
- android/sample-gltf-viewer
- web/samples/helmet.html
Fixes#1876.