diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 5fe74b5913..e647f364a2 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -6,6 +6,8 @@ A new header is inserted each time a *tag* is created.
## main branch
- engine: new feature level APIs, see `Engine::getSupportedFeatureLevel()`
+- gltfio: add unified `AssetLoader::createAsset()` method [⚠️ **API Change**]
+- gltfio: all assets are now "instanced" [⚠️ **API Change**]
## v1.25.6
diff --git a/android/filament-utils-android/src/main/java/com/google/android/filament/utils/ModelViewer.kt b/android/filament-utils-android/src/main/java/com/google/android/filament/utils/ModelViewer.kt
index 6e91620491..4b5c7f4e33 100644
--- a/android/filament-utils-android/src/main/java/com/google/android/filament/utils/ModelViewer.kt
+++ b/android/filament-utils-android/src/main/java/com/google/android/filament/utils/ModelViewer.kt
@@ -178,7 +178,7 @@ class ModelViewer(
*/
fun loadModelGlb(buffer: Buffer) {
destroyModel()
- asset = assetLoader.createAssetFromBinary(buffer)
+ asset = assetLoader.createAsset(buffer)
asset?.let { asset ->
resourceLoader.asyncBeginLoad(asset)
animator = asset.animator
@@ -193,7 +193,7 @@ class ModelViewer(
*/
fun loadModelGltf(buffer: Buffer, callback: (String) -> Buffer?) {
destroyModel()
- asset = assetLoader.createAssetFromJson(buffer)
+ asset = assetLoader.createAsset(buffer)
asset?.let { asset ->
for (uri in asset.resourceUris) {
val resourceBuffer = callback(uri)
@@ -216,7 +216,7 @@ class ModelViewer(
*/
fun loadModelGltfAsync(buffer: Buffer, callback: (String) -> Buffer) {
destroyModel()
- asset = assetLoader.createAssetFromJson(buffer)
+ asset = assetLoader.createAsset(buffer)
fetchResourcesJob = CoroutineScope(Dispatchers.IO).launch {
fetchResources(asset!!, callback)
}
diff --git a/android/gltfio-android/src/main/cpp/AssetLoader.cpp b/android/gltfio-android/src/main/cpp/AssetLoader.cpp
index 6f3f16b9a6..90690129f6 100644
--- a/android/gltfio-android/src/main/cpp/AssetLoader.cpp
+++ b/android/gltfio-android/src/main/cpp/AssetLoader.cpp
@@ -207,20 +207,11 @@ Java_com_google_android_filament_gltfio_AssetLoader_nDestroyAssetLoader(JNIEnv*,
}
extern "C" JNIEXPORT jlong JNICALL
-Java_com_google_android_filament_gltfio_AssetLoader_nCreateAssetFromBinary(JNIEnv* env, jclass,
+Java_com_google_android_filament_gltfio_AssetLoader_nCreateAsset(JNIEnv* env, jclass,
jlong nativeLoader, jobject javaBuffer, jint remaining) {
AssetLoader* loader = (AssetLoader*) nativeLoader;
AutoBuffer buffer(env, javaBuffer, remaining);
- return (jlong) loader->createAssetFromBinary((const uint8_t *) buffer.getData(),
- buffer.getSize());
-}
-
-extern "C" JNIEXPORT jlong JNICALL
-Java_com_google_android_filament_gltfio_AssetLoader_nCreateAssetFromJson(JNIEnv* env, jclass,
- jlong nativeLoader, jobject javaBuffer, jint remaining) {
- AssetLoader* loader = (AssetLoader*) nativeLoader;
- AutoBuffer buffer(env, javaBuffer, remaining);
- return (jlong) loader->createAssetFromJson((const uint8_t *) buffer.getData(),
+ return (jlong) loader->createAsset((const uint8_t *) buffer.getData(),
buffer.getSize());
}
diff --git a/android/gltfio-android/src/main/cpp/FilamentAsset.cpp b/android/gltfio-android/src/main/cpp/FilamentAsset.cpp
index 9721a1448c..f32ecebb9e 100644
--- a/android/gltfio-android/src/main/cpp/FilamentAsset.cpp
+++ b/android/gltfio-android/src/main/cpp/FilamentAsset.cpp
@@ -228,44 +228,6 @@ Java_com_google_android_filament_gltfio_FilamentAsset_nGetExtras(JNIEnv* env, jc
return val ? env->NewStringUTF(val) : nullptr;
}
-extern "C" JNIEXPORT jint JNICALL
-Java_com_google_android_filament_gltfio_FilamentAsset_nGetSkinCount(JNIEnv* , jclass,
- jlong nativeAsset) {
- FilamentAsset* asset = (FilamentAsset*) nativeAsset;
- return (jint) asset->getSkinCount();
-}
-
-extern "C" JNIEXPORT void JNICALL
-Java_com_google_android_filament_gltfio_FilamentAsset_nGetSkinNames(JNIEnv* env, jclass,
- jlong nativeAsset, jobjectArray result) {
- FilamentAsset* asset = (FilamentAsset*) nativeAsset;
- jsize available = env->GetArrayLength(result);
- for (int i = 0; i < available; ++i) {
- const char* name = asset->getSkinNameAt(i);
- if (name) {
- env->SetObjectArrayElement(result, (jsize) i, env->NewStringUTF(name));
- }
- }
-}
-
-extern "C" JNIEXPORT jint JNICALL
-Java_com_google_android_filament_gltfio_FilamentAsset_nGetJointCountAt(JNIEnv* , jclass,
- jlong nativeAsset, jint skinIndex) {
- FilamentAsset* asset = (FilamentAsset*) nativeAsset;
- return (jint) asset->getJointCountAt(skinIndex);
-}
-
-extern "C" JNIEXPORT void JNICALL
-Java_com_google_android_filament_gltfio_FilamentAsset_nGetJointsAt(JNIEnv* env, jclass,
- jlong nativeAsset, jint skinIndex, jintArray result) {
- FilamentAsset* asset = (FilamentAsset*) nativeAsset;
- jsize available = env->GetArrayLength(result);
- Entity* entities = (Entity*) env->GetIntArrayElements(result, nullptr);
- std::copy_n(asset->getJointsAt(skinIndex),
- std::min(available, (jsize) asset->getJointCountAt(skinIndex)), entities);
- env->ReleaseIntArrayElements(result, (jint*) entities, 0);
-}
-
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_gltfio_FilamentAsset_nGetAnimator(JNIEnv* , jclass,
jlong nativeAsset) {
@@ -340,19 +302,3 @@ Java_com_google_android_filament_gltfio_FilamentAsset_nReleaseSourceData(JNIEnv*
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
asset->releaseSourceData();
}
-
-extern "C" JNIEXPORT void JNICALL
-Java_com_google_android_filament_gltfio_FilamentAsset_nAttachSkin(JNIEnv* env, jclass,
- jlong nativeAsset, jint skinIndex, jint targetEntity) {
- FilamentAsset* asset = (FilamentAsset*) nativeAsset;
- Entity target = Entity::import(targetEntity);
- asset->attachSkin(skinIndex, target);
-}
-
-extern "C" JNIEXPORT void JNICALL
-Java_com_google_android_filament_gltfio_FilamentAsset_nDetachSkin(JNIEnv* env, jclass,
- jlong nativeAsset, jint skinIndex, jint targetEntity) {
- FilamentAsset* asset = (FilamentAsset*) nativeAsset;
- Entity target = Entity::import(targetEntity);
- asset->detachSkin(skinIndex, target);
-}
diff --git a/android/gltfio-android/src/main/cpp/FilamentInstance.cpp b/android/gltfio-android/src/main/cpp/FilamentInstance.cpp
index 62f9f7bbab..c35876681d 100644
--- a/android/gltfio-android/src/main/cpp/FilamentInstance.cpp
+++ b/android/gltfio-android/src/main/cpp/FilamentInstance.cpp
@@ -61,3 +61,57 @@ Java_com_google_android_filament_gltfio_FilamentInstance_nApplyMaterialVariant(J
FilamentInstance* instance = (FilamentInstance*) nativeInstance;
instance->applyMaterialVariant(variantIndex);
}
+
+extern "C" JNIEXPORT void JNICALL
+Java_com_google_android_filament_gltfio_FilamentInstance_nAttachSkin(JNIEnv* env, jclass,
+ jlong nativeInstance, jint skinIndex, jint targetEntity) {
+ FilamentInstance* instance = (FilamentInstance*) nativeInstance;
+ Entity target = Entity::import(targetEntity);
+ instance->attachSkin(skinIndex, target);
+}
+
+extern "C" JNIEXPORT void JNICALL
+Java_com_google_android_filament_gltfio_FilamentInstance_nDetachSkin(JNIEnv* env, jclass,
+ jlong nativeInstance, jint skinIndex, jint targetEntity) {
+ FilamentInstance* instance = (FilamentInstance*) nativeInstance;
+ Entity target = Entity::import(targetEntity);
+ instance->detachSkin(skinIndex, target);
+}
+
+extern "C" JNIEXPORT jint JNICALL
+Java_com_google_android_filament_gltfio_FilamentInstance_nGetSkinCount(JNIEnv* , jclass,
+ jlong nativeInstance) {
+ FilamentInstance* instance = (FilamentInstance*) nativeInstance;
+ return (jint) instance->getSkinCount();
+}
+
+extern "C" JNIEXPORT void JNICALL
+Java_com_google_android_filament_gltfio_FilamentInstance_nGetSkinNames(JNIEnv* env, jclass,
+ jlong nativeInstance, jobjectArray result) {
+ FilamentInstance* instance = (FilamentInstance*) nativeInstance;
+ jsize available = env->GetArrayLength(result);
+ for (int i = 0; i < available; ++i) {
+ const char* name = instance->getSkinNameAt(i);
+ if (name) {
+ env->SetObjectArrayElement(result, (jsize) i, env->NewStringUTF(name));
+ }
+ }
+}
+
+extern "C" JNIEXPORT jint JNICALL
+Java_com_google_android_filament_gltfio_FilamentInstance_nGetJointCountAt(JNIEnv* , jclass,
+ jlong nativeInstance, jint skinIndex) {
+ FilamentInstance* instance = (FilamentInstance*) nativeInstance;
+ return (jint) instance->getJointCountAt(skinIndex);
+}
+
+extern "C" JNIEXPORT void JNICALL
+Java_com_google_android_filament_gltfio_FilamentInstance_nGetJointsAt(JNIEnv* env, jclass,
+ jlong nativeInstance, jint skinIndex, jintArray result) {
+ FilamentInstance* instance = (FilamentInstance*) nativeInstance;
+ jsize available = env->GetArrayLength(result);
+ Entity* entities = (Entity*) env->GetIntArrayElements(result, nullptr);
+ std::copy_n(instance->getJointsAt(skinIndex),
+ std::min(available, (jsize) instance->getJointCountAt(skinIndex)), entities);
+ env->ReleaseIntArrayElements(result, (jint*) entities, 0);
+}
diff --git a/android/gltfio-android/src/main/java/com/google/android/filament/gltfio/AssetLoader.java b/android/gltfio-android/src/main/java/com/google/android/filament/gltfio/AssetLoader.java
index ea43967756..3a3fc81cbc 100644
--- a/android/gltfio-android/src/main/java/com/google/android/filament/gltfio/AssetLoader.java
+++ b/android/gltfio-android/src/main/java/com/google/android/filament/gltfio/AssetLoader.java
@@ -26,8 +26,8 @@ import java.nio.Buffer;
/**
* Consumes a blob of glTF 2.0 content (either JSON or GLB) and produces a {@link FilamentAsset}
- * object, which is a bundle of Filament entities, material instances, textures, vertex buffers,
- * and index buffers.
+ * object, which is a bundle of Filament textures, vertex buffers, index buffers, etc. An asset is
+ * composed of 1 or more FilamentInstance objects which contain entities and components.
*
*
AssetLoader does not fetch external buffer data or create textures on its own. Clients can use
* the provided {@link ResourceLoader} class for this, which obtains the URI list from the asset.
@@ -51,7 +51,7 @@ import java.nio.Buffer;
* filamentAsset = assets.open("models/lucy.gltf").use { input ->
* val bytes = ByteArray(input.available())
* input.read(bytes)
- * assetLoader.createAssetFromJson(ByteBuffer.wrap(bytes))!!
+ * assetLoader.createAsset(ByteBuffer.wrap(bytes))!!
* }
*
* val resourceLoader = ResourceLoader(engine)
@@ -115,20 +115,11 @@ public class AssetLoader {
}
/**
- * Creates a {@link FilamentAsset} from the contents of a GLB file.
+ * Creates a {@link FilamentAsset} from the contents of a GLB or GLTF file.
*/
@Nullable
- public FilamentAsset createAssetFromBinary(@NonNull Buffer buffer) {
- long nativeAsset = nCreateAssetFromBinary(mNativeObject, buffer, buffer.remaining());
- return nativeAsset != 0 ? new FilamentAsset(mEngine, nativeAsset) : null;
- }
-
- /**
- * Creates a {@link FilamentAsset} from the contents of a GLTF file.
- */
- @Nullable
- public FilamentAsset createAssetFromJson(@NonNull Buffer buffer) {
- long nativeAsset = nCreateAssetFromJson(mNativeObject, buffer, buffer.remaining());
+ public FilamentAsset createAsset(@NonNull Buffer buffer) {
+ long nativeAsset = nCreateAsset(mNativeObject, buffer, buffer.remaining());
return nativeAsset != 0 ? new FilamentAsset(mEngine, nativeAsset) : null;
}
@@ -158,7 +149,7 @@ public class AssetLoader {
}
/**
- * Adds a new instance to an instanced asset.
+ * Adds a new instance to the asset.
*
* Use this with caution. It is more efficient to pre-allocate a max number of instances, and
* gradually add them to the scene as needed. Instances can also be "recycled" by removing and
@@ -169,7 +160,6 @@ public class AssetLoader {
* create/destroy churn, as noted above.
*
* This cannot be called after FilamentAsset#releaseSourceData().
- * This cannot be called on a non-instanced asset.
* Animation is not supported in new instances.
* See also AssetLoader#createInstancedAsset().
*/
@@ -202,8 +192,7 @@ public class AssetLoader {
private static native long nCreateAssetLoader(long nativeEngine, Object provider,
long nativeEntities);
private static native void nDestroyAssetLoader(long nativeLoader);
- private static native long nCreateAssetFromBinary(long nativeLoader, Buffer buffer, int remaining);
- private static native long nCreateAssetFromJson(long nativeLoader, Buffer buffer, int remaining);
+ private static native long nCreateAsset(long nativeLoader, Buffer buffer, int remaining);
private static native long nCreateInstancedAsset(long nativeLoader, Buffer buffer, int remaining,
long[] nativeInstances);
private static native long nCreateInstance(long nativeLoader, long nativeAsset);
diff --git a/android/gltfio-android/src/main/java/com/google/android/filament/gltfio/FilamentAsset.java b/android/gltfio-android/src/main/java/com/google/android/filament/gltfio/FilamentAsset.java
index c314b500bd..a85d1303ef 100644
--- a/android/gltfio-android/src/main/java/com/google/android/filament/gltfio/FilamentAsset.java
+++ b/android/gltfio-android/src/main/java/com/google/android/filament/gltfio/FilamentAsset.java
@@ -225,58 +225,6 @@ public class FilamentAsset {
return mAnimator;
}
- /**
- * Gets the skin count of this asset.
- */
- public int getSkinCount() {
- return nGetSkinCount(getNativeObject());
- }
-
- /**
- * Gets the skin name at skin index in this asset.
- */
- public @NonNull String[] getSkinNames() {
- String[] result = new String[getSkinCount()];
- nGetSkinNames(getNativeObject(), result);
- return result;
- }
-
- /**
- * Attaches the given skin to the given node, which must have an associated mesh with
- * BONE_INDICES and BONE_WEIGHTS attributes.
- *
- * This is a no-op if the given skin index or target is invalid.
- */
- public void attachSkin(@IntRange(from = 0) int skinIndex, @Entity int target) {
- nAttachSkin(getNativeObject(), skinIndex, target);
- }
-
- /**
- * Attaches the given skin to the given node, which must have an associated mesh with
- * BONE_INDICES and BONE_WEIGHTS attributes.
- *
- * This is a no-op if the given skin index or target is invalid.
- */
- public void detachSkin(@IntRange(from = 0) int skinIndex, @Entity int target) {
- nDetachSkin(getNativeObject(), skinIndex, target);
- }
-
- /**
- * Gets the joint count at skin index in this asset.
- */
- public int getJointCountAt(@IntRange(from = 0) int skinIndex) {
- return nGetJointCountAt(getNativeObject(), skinIndex);
- }
-
- /**
- * Gets joints at skin index in this asset.
- */
- public @NonNull @Entity int[] getJointsAt(@IntRange(from = 0) int skinIndex) {
- int[] result = new int[getJointCountAt(skinIndex)];
- nGetJointsAt(getNativeObject(), skinIndex, result);
- return result;
- }
-
/**
* Gets the names of all morph targets in the given entity.
*/
@@ -365,18 +313,11 @@ public class FilamentAsset {
private static native int nGetMorphTargetCount(long nativeAsset, int entity);
private static native void nGetMorphTargetNames(long nativeAsset, int entity, String[] result);
- private static native void nAttachSkin(long nativeAsset, int skinIndex, int entity);
- private static native void nDetachSkin(long nativeAsset, int skinIndex, int entity);
-
private static native void nGetBoundingBox(long nativeAsset, float[] box);
private static native String nGetName(long nativeAsset, int entity);
private static native String nGetExtras(long nativeAsset, int entity);
private static native long nGetAnimator(long nativeAsset);
private static native void nApplyMaterialVariant(long nativeAsset, int variantIndex);
- private static native int nGetSkinCount(long nativeAsset);
- private static native void nGetSkinNames(long nativeAsset, String[] result);
- private static native int nGetJointCountAt(long nativeAsset, int skinIndex);
- private static native void nGetJointsAt(long nativeAsset, int skinIndex, int[] result);
private static native int nGetResourceUriCount(long nativeAsset);
private static native void nGetResourceUris(long nativeAsset, String[] result);
private static native void nReleaseSourceData(long nativeAsset);
diff --git a/android/gltfio-android/src/main/java/com/google/android/filament/gltfio/FilamentInstance.java b/android/gltfio-android/src/main/java/com/google/android/filament/gltfio/FilamentInstance.java
index be00ed8e05..48e288d4c1 100644
--- a/android/gltfio-android/src/main/java/com/google/android/filament/gltfio/FilamentInstance.java
+++ b/android/gltfio-android/src/main/java/com/google/android/filament/gltfio/FilamentInstance.java
@@ -85,6 +85,58 @@ public class FilamentInstance {
return mAnimator;
}
+ /**
+ * Gets the skin count of this instance.
+ */
+ public int getSkinCount() {
+ return nGetSkinCount(getNativeObject());
+ }
+
+ /**
+ * Gets the skin name at skin index in this instance.
+ */
+ public @NonNull String[] getSkinNames() {
+ String[] result = new String[getSkinCount()];
+ nGetSkinNames(getNativeObject(), result);
+ return result;
+ }
+
+ /**
+ * Attaches the given skin to the given node, which must have an associated mesh with
+ * BONE_INDICES and BONE_WEIGHTS attributes.
+ *
+ * This is a no-op if the given skin index or target is invalid.
+ */
+ public void attachSkin(@IntRange(from = 0) int skinIndex, @Entity int target) {
+ nAttachSkin(getNativeObject(), skinIndex, target);
+ }
+
+ /**
+ * Attaches the given skin to the given node, which must have an associated mesh with
+ * BONE_INDICES and BONE_WEIGHTS attributes.
+ *
+ * This is a no-op if the given skin index or target is invalid.
+ */
+ public void detachSkin(@IntRange(from = 0) int skinIndex, @Entity int target) {
+ nDetachSkin(getNativeObject(), skinIndex, target);
+ }
+
+ /**
+ * Gets the joint count at skin index in this instance.
+ */
+ public int getJointCountAt(@IntRange(from = 0) int skinIndex) {
+ return nGetJointCountAt(getNativeObject(), skinIndex);
+ }
+
+ /**
+ * Gets joints at skin index in this instance.
+ */
+ public @NonNull @Entity int[] getJointsAt(@IntRange(from = 0) int skinIndex) {
+ int[] result = new int[getJointCountAt(skinIndex)];
+ nGetJointsAt(getNativeObject(), skinIndex, result);
+ return result;
+ }
+
/**
* Applies the given material variant to all primitives in this instance.
*
@@ -94,9 +146,15 @@ public class FilamentInstance {
nApplyMaterialVariant(mNativeObject, variantIndex);
}
- private static native int nGetRoot(long nativeAsset);
- private static native int nGetEntityCount(long nativeAsset);
- private static native void nGetEntities(long nativeAsset, int[] result);
- private static native long nGetAnimator(long nativeAsset);
- private static native void nApplyMaterialVariant(long nativeAsset, int variantIndex);
+ private static native int nGetRoot(long nativeInstance);
+ private static native int nGetEntityCount(long nativeInstance);
+ private static native void nGetEntities(long nativeInstance, int[] result);
+ private static native long nGetAnimator(long nativeInstance);
+ private static native void nApplyMaterialVariant(long nativeInstance, int variantIndex);
+ private static native void nGetJointsAt(long nativeInstance, int skinIndex, int[] result);
+ private static native int nGetSkinCount(long nativeInstance);
+ private static native void nGetSkinNames(long nativeInstance, String[] result);
+ private static native int nGetJointCountAt(long nativeInstance, int skinIndex);
+ private static native void nAttachSkin(long nativeInstance, int skinIndex, int entity);
+ private static native void nDetachSkin(long nativeInstance, int skinIndex, int entity);
}
diff --git a/ios/samples/gltf-viewer/gltf-viewer/FILModelView.mm b/ios/samples/gltf-viewer/gltf-viewer/FILModelView.mm
index dedff5f543..d36e8b994e 100644
--- a/ios/samples/gltf-viewer/gltf-viewer/FILModelView.mm
+++ b/ios/samples/gltf-viewer/gltf-viewer/FILModelView.mm
@@ -198,7 +198,7 @@ const float kSensitivity = 100.0f;
- (void)loadModelGlb:(NSData*)buffer {
[self destroyModel];
- _asset = _assetLoader->createAssetFromBinary(
+ _asset = _assetLoader->createAsset(
static_cast(buffer.bytes), static_cast(buffer.length));
if (!_asset) {
@@ -213,7 +213,7 @@ const float kSensitivity = 100.0f;
- (void)loadModelGltf:(NSData*)buffer callback:(ResourceCallback)callback {
[self destroyModel];
- _asset = _assetLoader->createAssetFromJson(
+ _asset = _assetLoader->createAsset(
static_cast(buffer.bytes), static_cast(buffer.length));
if (!_asset) {
diff --git a/ios/samples/hello-gltf/hello-gltf/FilamentView/App.cpp b/ios/samples/hello-gltf/hello-gltf/FilamentView/App.cpp
index 8637acdbb8..2fcb918929 100644
--- a/ios/samples/hello-gltf/hello-gltf/FilamentView/App.cpp
+++ b/ios/samples/hello-gltf/hello-gltf/FilamentView/App.cpp
@@ -137,7 +137,7 @@ void App::setupMesh() {
std::cerr << "Unable to read glTF" << std::endl;
exit(1);
}
- app.asset = app.assetLoader->createAssetFromBinary(buffer.data(), static_cast(size));
+ app.asset = app.assetLoader->createAsset(buffer.data(), static_cast(size));
filament::gltfio::ResourceLoader({
.engine = engine,
diff --git a/libs/gltfio/include/gltfio/Animator.h b/libs/gltfio/include/gltfio/Animator.h
index 072d532a84..c8d3803f5f 100644
--- a/libs/gltfio/include/gltfio/Animator.h
+++ b/libs/gltfio/include/gltfio/Animator.h
@@ -104,6 +104,7 @@ private:
friend struct FFilamentInstance;
/*! \endcond */
+ // If "instance" is null, then this is the primary animator.
Animator(FFilamentAsset* asset, FFilamentInstance* instance);
~Animator();
diff --git a/libs/gltfio/include/gltfio/AssetLoader.h b/libs/gltfio/include/gltfio/AssetLoader.h
index 327e4c9bc7..7023c0638e 100644
--- a/libs/gltfio/include/gltfio/AssetLoader.h
+++ b/libs/gltfio/include/gltfio/AssetLoader.h
@@ -69,8 +69,8 @@ struct AssetConfiguration {
* \brief Consumes glTF content and produces FilamentAsset objects.
*
* AssetLoader consumes a blob of glTF 2.0 content (either JSON or GLB) and produces a FilamentAsset
- * object, which is a bundle of Filament entities, material instances, textures, vertex buffers,
- * and index buffers.
+ * object, which is a bundle of Filament textures, vertex buffers, index buffers, etc. An asset is
+ * composed of 1 or more FilamentInstance objects which contain entities and components.
*
* Clients must use AssetLoader to create and destroy FilamentAsset objects. This is similar to
* how filament::Engine is used to create and destroy core objects like VertexBuffer.
@@ -92,7 +92,7 @@ struct AssetConfiguration {
*
* // Parse the glTF content and create Filament entities.
* std::vector content(...);
- * FilamentAsset* asset = loader->createAssetFromJson(content.data(), content.size());
+ * FilamentAsset* asset = loader->createAsset(content.data(), content.size());
* content.clear();
*
* // Load buffers and textures from disk.
@@ -148,16 +148,10 @@ public:
static void destroy(AssetLoader** loader);
/**
- * Takes a pointer to the contents of a JSON-based glTF 2.0 file and returns a bundle
- * of Filament objects. Returns null on failure.
+ * Takes a pointer to the contents of a GLB or a JSON-based glTF 2.0 file and returns an asset
+ * with one instance, or null on failure.
*/
- FilamentAsset* createAssetFromJson(const uint8_t* bytes, uint32_t nbytes);
-
- /**
- * Takes a pointer to the contents of a GLB glTF 2.0 file and returns a bundle
- * of Filament objects. Returns null on failure.
- */
- FilamentAsset* createAssetFromBinary(const uint8_t* bytes, uint32_t nbytes);
+ FilamentAsset* createAsset(const uint8_t* bytes, uint32_t nbytes);
/**
* Consumes the contents of a glTF 2.0 file and produces a primary asset with one or more
@@ -186,7 +180,7 @@ public:
FilamentInstance** instances, size_t numInstances);
/**
- * Adds a new instance to an instanced asset.
+ * Adds a new instance to the asset.
*
* Use this with caution. It is more efficient to pre-allocate a max number of instances, and
* gradually add them to the scene as needed. Instances can also be "recycled" by removing and
@@ -197,7 +191,6 @@ public:
* create/destroy churn, as noted above.
*
* This cannot be called after FilamentAsset::releaseSourceData().
- * This cannot be called on a non-instanced asset.
* See also AssetLoader::createInstancedAsset().
*/
FilamentInstance* createInstance(FilamentAsset* primary);
diff --git a/libs/gltfio/include/gltfio/FilamentAsset.h b/libs/gltfio/include/gltfio/FilamentAsset.h
index 31318d8dd6..b8a299481a 100644
--- a/libs/gltfio/include/gltfio/FilamentAsset.h
+++ b/libs/gltfio/include/gltfio/FilamentAsset.h
@@ -218,41 +218,6 @@ public:
*/
Animator* getAnimator() const noexcept;
- /**
- * Gets the number of skins.
- */
- size_t getSkinCount() const noexcept;
-
- /**
- * Gets the skin name at skin index.
- */
- const char* getSkinNameAt(size_t skinIndex) const noexcept;
-
- /**
- * Gets the number of joints at skin index.
- */
- size_t getJointCountAt(size_t skinIndex) const noexcept;
-
- /**
- * Gets joints at skin index.
- */
- const Entity* getJointsAt(size_t skinIndex) const noexcept;
-
- /**
- * Attaches the given skin to the given node, which must have an associated mesh with
- * BONE_INDICES and BONE_WEIGHTS attributes.
- *
- * This is a no-op if the given skin index or target is invalid.
- */
- void attachSkin(size_t skinIndex, Entity target) noexcept;
-
- /**
- * Detaches the given skin from the given node.
- *
- * This is a no-op if the given skin index or target is invalid.
- */
- void detachSkin(size_t skinIndex, Entity target) noexcept;
-
/**
* Gets the morph target name at the given index in the given entity.
*/
diff --git a/libs/gltfio/include/gltfio/FilamentInstance.h b/libs/gltfio/include/gltfio/FilamentInstance.h
index 60d8e8d960..b6de4eeac2 100644
--- a/libs/gltfio/include/gltfio/FilamentInstance.h
+++ b/libs/gltfio/include/gltfio/FilamentInstance.h
@@ -74,6 +74,41 @@ public:
* The animator is owned by the asset and should not be manually deleted.
*/
Animator* getAnimator() noexcept;
+
+ /**
+ * Gets the number of skins.
+ */
+ size_t getSkinCount() const noexcept;
+
+ /**
+ * Gets the skin name at skin index.
+ */
+ const char* getSkinNameAt(size_t skinIndex) const noexcept;
+
+ /**
+ * Gets the number of joints at skin index.
+ */
+ size_t getJointCountAt(size_t skinIndex) const noexcept;
+
+ /**
+ * Gets joints at skin index.
+ */
+ const utils::Entity* getJointsAt(size_t skinIndex) const noexcept;
+
+ /**
+ * Attaches the given skin to the given node, which must have an associated mesh with
+ * BONE_INDICES and BONE_WEIGHTS attributes.
+ *
+ * This is a no-op if the given skin index or target is invalid.
+ */
+ void attachSkin(size_t skinIndex, utils::Entity target) noexcept;
+
+ /**
+ * Detaches the given skin from the given node.
+ *
+ * This is a no-op if the given skin index or target is invalid.
+ */
+ void detachSkin(size_t skinIndex, utils::Entity target) noexcept;
};
} // namespace filament::gltfio
diff --git a/libs/gltfio/src/Animator.cpp b/libs/gltfio/src/Animator.cpp
index d375675867..df0ae7dbef 100644
--- a/libs/gltfio/src/Animator.cpp
+++ b/libs/gltfio/src/Animator.cpp
@@ -217,8 +217,6 @@ Animator::Animator(FFilamentAsset* asset, FFilamentInstance* instance) {
// Import each glTF channel into a custom data structure.
if (instance) {
mImpl->addChannels(instance->nodeMap, srcAnim, dstAnim);
- } else if (!asset->isInstanced()) {
- mImpl->addChannels(asset->mNodeMap, srcAnim, dstAnim);
} else {
for (FFilamentInstance* instance : asset->mInstances) {
mImpl->addChannels(instance->nodeMap, srcAnim, dstAnim);
@@ -320,8 +318,6 @@ void Animator::resetBoneMatrices() {
if (mImpl->instance) {
update(mImpl->instance->skins, mImpl->boneMatrices);
- } else if (!mImpl->asset->isInstanced()) {
- update(mImpl->asset->mSkins, mImpl->boneMatrices);
} else {
for (FFilamentInstance* instance : mImpl->asset->mInstances) {
update(instance->skins, mImpl->boneMatrices);
@@ -363,8 +359,6 @@ void Animator::updateBoneMatrices() {
if (mImpl->instance) {
update(mImpl->instance->skins, mImpl->boneMatrices);
- } else if (!mImpl->asset->isInstanced()) {
- update(mImpl->asset->mSkins, mImpl->boneMatrices);
} else {
for (FFilamentInstance* instance : mImpl->asset->mInstances) {
update(instance->skins, mImpl->boneMatrices);
diff --git a/libs/gltfio/src/AssetLoader.cpp b/libs/gltfio/src/AssetLoader.cpp
index 5759ad8c12..6fd1f8371a 100644
--- a/libs/gltfio/src/AssetLoader.cpp
+++ b/libs/gltfio/src/AssetLoader.cpp
@@ -100,8 +100,7 @@ struct FAssetLoader : public AssetLoader {
mEngine(*config.engine),
mDefaultNodeName(config.defaultNodeName) {}
- FFilamentAsset* createAssetFromJson(const uint8_t* bytes, uint32_t nbytes);
- FFilamentAsset* createAssetFromBinary(const uint8_t* bytes, uint32_t nbytes);
+ FFilamentAsset* createAsset(const uint8_t* bytes, uint32_t nbytes);
FFilamentAsset* createInstancedAsset(const uint8_t* bytes, uint32_t numBytes,
FilamentInstance** instances, size_t numInstances);
FilamentInstance* createInstance(FFilamentAsset* primary);
@@ -172,8 +171,18 @@ struct FAssetLoader : public AssetLoader {
FILAMENT_UPCAST(AssetLoader)
-FFilamentAsset* FAssetLoader::createAssetFromJson(const uint8_t* bytes, uint32_t nbytes) {
- cgltf_options options { cgltf_file_type_invalid };
+FFilamentAsset* FAssetLoader::createAsset(const uint8_t* bytes, uint32_t byteCount) {
+ FilamentInstance* instances;
+ return createInstancedAsset(bytes, byteCount, &instances, 1);
+}
+
+FFilamentAsset* FAssetLoader::createInstancedAsset(const uint8_t* bytes, uint32_t byteCount,
+ FilamentInstance** instances, size_t numInstances) {
+ ASSERT_PRECONDITION(numInstances > 0, "Instance count must be 1 or more.");
+
+ // This method can be used to load JSON or GLB. By using a default options struct, we are asking
+ // cgltf to examine the magic identifier to determine which type of file is being loaded.
+ cgltf_options options {};
if constexpr (!GLTFIO_USE_FILESYSTEM) {
@@ -189,50 +198,6 @@ FFilamentAsset* FAssetLoader::createAssetFromJson(const uint8_t* bytes, uint32_t
options.file.release = [](const cgltf_memory_options*, const cgltf_file_options*, void*) {};
}
- cgltf_data* sourceAsset;
- cgltf_result result = cgltf_parse(&options, bytes, nbytes, &sourceAsset);
- if (result != cgltf_result_success) {
- slog.e << "Unable to parse JSON file." << io::endl;
- return nullptr;
- }
- createAsset(sourceAsset, 0);
- return mResult;
-}
-
-FFilamentAsset* FAssetLoader::createAssetFromBinary(const uint8_t* bytes, uint32_t byteCount) {
-
- // The cgltf library handles GLB efficiently by pointing all buffer views into the source data.
- // However, we wish our API to be simple and safe, allowing clients to free up their source blob
- // immediately, without worrying about when all the data has finished uploading asynchronously
- // to the GPU. To achieve this we create a copy of the source blob and stash it inside the
- // asset, asking cgltf to parse the copy. This allows us to free it at the correct time (i.e.
- // after all GPU uploads have completed). Although it incurs a copy, the added safety of this
- // API seems worthwhile.
- utils::FixedCapacityVector glbdata(byteCount);
- std::copy_n(bytes, byteCount, glbdata.data());
-
- cgltf_options options { cgltf_file_type_glb };
- cgltf_data* sourceAsset;
- cgltf_result result = cgltf_parse(&options, glbdata.data(), byteCount, &sourceAsset);
- if (result != cgltf_result_success) {
- slog.e << "Unable to parse glb file." << io::endl;
- return nullptr;
- }
- createAsset(sourceAsset, 0);
- if (mResult) {
- glbdata.swap(mResult->mSourceAsset->glbData);
- }
- return mResult;
-}
-
-FFilamentAsset* FAssetLoader::createInstancedAsset(const uint8_t* bytes, uint32_t byteCount,
- FilamentInstance** instances, size_t numInstances) {
- ASSERT_PRECONDITION(numInstances > 0, "Instance count must be 1 or more.");
-
- // This method can be used to load JSON or GLB. By using a default options struct, we are asking
- // cgltf to examine the magic identifier to determine which type of file is being loaded.
- cgltf_options options {};
-
// Clients can free up their source blob immediately, but cgltf has pointers into the data that
// need to stay valid. Therefore we create a copy of the source blob and stash it inside the
// asset.
@@ -258,10 +223,6 @@ FilamentInstance* FAssetLoader::createInstance(FFilamentAsset* primary) {
slog.e << "Source data has been released; asset is frozen." << io::endl;
return nullptr;
}
- if (!primary->isInstanced()) {
- slog.e << "Cannot add an instance to a non-instanced asset." << io::endl;
- return nullptr;
- }
const cgltf_data* srcAsset = primary->mSourceAsset->hierarchy;
if (srcAsset->scenes == nullptr) {
slog.e << "There is no scene in the asset." << io::endl;
@@ -345,20 +306,13 @@ void FAssetLoader::createAsset(const cgltf_data* srcAsset, size_t numInstances)
mResult->mRenderableCount = 0;
- if (numInstances == 0) {
- // For each scene root, recursively create all entities.
- for (const auto& pair : mRootNodes) {
- createEntity(srcAsset, pair.first, pair.second, mResult->mRoot, true, nullptr);
- }
- } else {
- // Create a separate entity hierarchy for each instance. Note that MeshCache (vertex
- // buffers and index buffers) and MatInstanceCache (materials and textures) help avoid
- // needless duplication of resources.
- for (size_t index = 0; index < numInstances; ++index) {
- if (createInstance(mResult, srcAsset) == nullptr) {
- mError = true;
- break;
- }
+ // Create a separate entity hierarchy for each instance. Note that MeshCache (vertex
+ // buffers and index buffers) and MatInstanceCache (materials and textures) help avoid
+ // needless duplication of resources.
+ for (size_t index = 0; index < numInstances; ++index) {
+ if (createInstance(mResult, srcAsset) == nullptr) {
+ mError = true;
+ break;
}
}
@@ -371,7 +325,7 @@ void FAssetLoader::createAsset(const cgltf_data* srcAsset, size_t numInstances)
// Find every unique resource URI and store a pointer to any of the cgltf-owned cstrings
// that match the URI. These strings get freed during releaseSourceData().
- tsl::robin_map resourceUris;
+ tsl::robin_map resourceUris;
auto addResourceUri = [&resourceUris](const char* uri) {
if (uri) {
resourceUris[uri] = uri;
@@ -454,12 +408,8 @@ void FAssetLoader::createEntity(const cgltf_data* srcAsset, const cgltf_node* no
// Update the asset's entity list and private node mapping.
mResult->mEntities.push_back(entity);
- if (instance) {
- instance->entities.push_back(entity);
- instance->nodeMap[node] = entity;
- } else {
- mResult->mNodeMap[node] = entity;
- }
+ instance->entities.push_back(entity);
+ instance->nodeMap[node] = entity;
const char* name = getNodeName(node, mDefaultNodeName);
@@ -644,11 +594,8 @@ void FAssetLoader::createMaterialVariants(const cgltf_data* srcAsset, const cglt
break;
}
mResult->mDependencyGraph.addEdge(entity, mi);
- if (instance) {
- instance->variants[variantIndex].mappings.push_back({entity, prim, mi});
- } else {
- mResult->mVariants[variantIndex].mappings.push_back({entity, prim, mi});
- }
+ instance->variants[variantIndex].mappings.push_back({entity, prim, mi});
+ mResult->mVariants[variantIndex].mappings.push_back({entity, prim, mi});
}
}
}
@@ -1430,12 +1377,8 @@ void AssetLoader::destroy(AssetLoader** loader) {
*loader = temp;
}
-FilamentAsset* AssetLoader::createAssetFromJson(uint8_t const* bytes, uint32_t nbytes) {
- return upcast(this)->createAssetFromJson(bytes, nbytes);
-}
-
-FilamentAsset* AssetLoader::createAssetFromBinary(uint8_t const* bytes, uint32_t nbytes) {
- return upcast(this)->createAssetFromBinary(bytes, nbytes);
+FilamentAsset* AssetLoader::createAsset(uint8_t const* bytes, uint32_t nbytes) {
+ return upcast(this)->createAsset(bytes, nbytes);
}
FilamentAsset* AssetLoader::createInstancedAsset(const uint8_t* bytes, uint32_t numBytes,
diff --git a/libs/gltfio/src/FFilamentAsset.h b/libs/gltfio/src/FFilamentAsset.h
index a2aee229a9..e4d8a3985c 100644
--- a/libs/gltfio/src/FFilamentAsset.h
+++ b/libs/gltfio/src/FFilamentAsset.h
@@ -210,18 +210,6 @@ struct FFilamentAsset : public FilamentAsset {
Animator* getAnimator() const noexcept { return mAnimator; }
- size_t getSkinCount() const noexcept;
-
- const char* getSkinNameAt(size_t skinIndex) const noexcept;
-
- size_t getJointCountAt(size_t skinIndex) const noexcept;
-
- const utils::Entity* getJointsAt(size_t skinIndex) const noexcept;
-
- void attachSkin(size_t skinIndex, Entity target) noexcept;
-
- void detachSkin(size_t skinIndex, Entity target) noexcept;
-
const char* getMorphTargetNameAt(utils::Entity entity, size_t targetIndex) const noexcept;
size_t getMorphTargetCountAt(utils::Entity entity) const noexcept;
@@ -281,10 +269,6 @@ struct FFilamentAsset : public FilamentAsset {
mDependencyGraph.addEdge(texture, tb.materialInstance, tb.materialParameter);
}
- bool isInstanced() const {
- return mInstances.size() > 0;
- }
-
void createAnimators();
filament::Engine* const mEngine;
@@ -306,7 +290,6 @@ struct FFilamentAsset : public FilamentAsset {
filament::Aabb mBoundingBox;
utils::Entity mRoot;
std::vector mInstances;
- SkinVector mSkins; // unused for instanced assets
Animator* mAnimator = nullptr;
Wireframe* mWireframe = nullptr;
@@ -341,7 +324,6 @@ struct FFilamentAsset : public FilamentAsset {
std::vector mBufferSlots;
std::vector mTextureSlots;
std::vector mResourceUris;
- NodeMap mNodeMap; // unused for instanced assets
std::vector > mPrimitives;
MatInstanceCache mMatInstanceCache;
MeshCache mMeshCache;
diff --git a/libs/gltfio/src/FFilamentInstance.h b/libs/gltfio/src/FFilamentInstance.h
index 805dc0d960..af9806528e 100644
--- a/libs/gltfio/src/FFilamentInstance.h
+++ b/libs/gltfio/src/FFilamentInstance.h
@@ -86,6 +86,8 @@ struct FFilamentInstance : public FilamentInstance {
const char* getSkinNameAt(size_t skinIndex) const noexcept;
size_t getJointCountAt(size_t skinIndex) const noexcept;
const utils::Entity* getJointsAt(size_t skinIndex) const noexcept;
+ void attachSkin(size_t skinIndex, utils::Entity target) noexcept;
+ void detachSkin(size_t skinIndex, utils::Entity target) noexcept;
void applyMaterialVariant(size_t variantIndex) noexcept;
};
diff --git a/libs/gltfio/src/FilamentAsset.cpp b/libs/gltfio/src/FilamentAsset.cpp
index bf95fcb1e7..ace4131ef7 100644
--- a/libs/gltfio/src/FilamentAsset.cpp
+++ b/libs/gltfio/src/FilamentAsset.cpp
@@ -105,45 +105,6 @@ void FFilamentAsset::createAnimators() {
}
}
-size_t FFilamentAsset::getSkinCount() const noexcept {
- return mSkins.size();
-}
-
-const char* FFilamentAsset::getSkinNameAt(size_t skinIndex) const noexcept {
- if (mSkins.size() <= skinIndex) {
- return nullptr;
- }
- return mSkins[skinIndex].name.c_str();
-}
-
-size_t FFilamentAsset::getJointCountAt(size_t skinIndex) const noexcept {
- if (mSkins.size() <= skinIndex) {
- return 0;
- }
- return mSkins[skinIndex].joints.size();
-}
-
-const utils::Entity* FFilamentAsset::getJointsAt(size_t skinIndex) const noexcept {
- if (mSkins.size() <= skinIndex) {
- return nullptr;
- }
- return mSkins[skinIndex].joints.data();
-}
-
-void FFilamentAsset::attachSkin(size_t skinIndex, Entity target) noexcept {
- if (UTILS_UNLIKELY(mSkins.size() <= skinIndex || target.isNull())) {
- return;
- }
- mSkins[skinIndex].targets.insert(target);
-}
-
-void FFilamentAsset::detachSkin(size_t skinIndex, Entity target) noexcept {
- if (UTILS_UNLIKELY(mSkins.size() <= skinIndex || target.isNull())) {
- return;
- }
- mSkins[skinIndex].targets.erase(target);
-}
-
const char* FFilamentAsset::getMorphTargetNameAt(utils::Entity entity,
size_t targetIndex) const noexcept {
if (!mResourcesLoaded) {
@@ -185,7 +146,7 @@ void FFilamentAsset::applyMaterialVariant(size_t variantIndex) noexcept {
const std::vector& mappings = mVariants[variantIndex].mappings;
RenderableManager& rm = mEngine->getRenderableManager();
for (const auto& mapping : mappings) {
- auto instance = rm.getInstance(mapping.renderable);
+ RenderableManager::Instance instance = rm.getInstance(mapping.renderable);
rm.setMaterialInstanceAt(instance, mapping.primitiveIndex, mapping.material);
}
}
@@ -204,7 +165,6 @@ void FFilamentAsset::releaseSourceData() noexcept {
mMatInstanceCache = {};
mMeshCache = {};
mResourceUris = {};
- mNodeMap = {};
mPrimitives = {};
mBufferSlots = {};
mTextureSlots = {};
@@ -397,30 +357,6 @@ Animator* FilamentAsset::getAnimator() const noexcept {
return upcast(this)->getAnimator();
}
-size_t FilamentAsset::getSkinCount() const noexcept {
- return upcast(this)->getSkinCount();
-}
-
-const char* FilamentAsset::getSkinNameAt(size_t skinIndex) const noexcept {
- return upcast(this)->getSkinNameAt(skinIndex);
-}
-
-size_t FilamentAsset::getJointCountAt(size_t skinIndex) const noexcept {
- return upcast(this)->getJointCountAt(skinIndex);
-}
-
-const utils::Entity* FilamentAsset::getJointsAt(size_t skinIndex) const noexcept {
- return upcast(this)->getJointsAt(skinIndex);
-}
-
-void FilamentAsset::attachSkin(size_t skinIndex, Entity target) noexcept {
- upcast(this)->attachSkin(skinIndex, target);
-}
-
-void FilamentAsset::detachSkin(size_t skinIndex, Entity target) noexcept {
- upcast(this)->detachSkin(skinIndex, target);
-}
-
const char* FilamentAsset::getMorphTargetNameAt(utils::Entity entity,
size_t targetIndex) const noexcept {
return upcast(this)->getMorphTargetNameAt(entity, targetIndex);
diff --git a/libs/gltfio/src/FilamentInstance.cpp b/libs/gltfio/src/FilamentInstance.cpp
index 82f9ee51ba..fccd3f8ec6 100644
--- a/libs/gltfio/src/FilamentInstance.cpp
+++ b/libs/gltfio/src/FilamentInstance.cpp
@@ -61,6 +61,20 @@ const utils::Entity* FFilamentInstance::getJointsAt(size_t skinIndex) const noex
return skins[skinIndex].joints.data();
}
+void FFilamentInstance::attachSkin(size_t skinIndex, Entity target) noexcept {
+ if (UTILS_UNLIKELY(skins.size() <= skinIndex || target.isNull())) {
+ return;
+ }
+ skins[skinIndex].targets.insert(target);
+}
+
+void FFilamentInstance::detachSkin(size_t skinIndex, Entity target) noexcept {
+ if (UTILS_UNLIKELY(skins.size() <= skinIndex || target.isNull())) {
+ return;
+ }
+ skins[skinIndex].targets.erase(target);
+}
+
void FFilamentInstance::applyMaterialVariant(size_t variantIndex) noexcept {
if (variantIndex >= variants.size()) {
return;
@@ -98,4 +112,29 @@ Animator* FilamentInstance::getAnimator() noexcept {
return upcast(this)->getAnimator();
}
+size_t FilamentInstance::getSkinCount() const noexcept {
+ return upcast(this)->getSkinCount();
+}
+
+const char* FilamentInstance::getSkinNameAt(size_t skinIndex) const noexcept {
+ return upcast(this)->getSkinNameAt(skinIndex);
+}
+
+size_t FilamentInstance::getJointCountAt(size_t skinIndex) const noexcept {
+ return upcast(this)->getJointCountAt(skinIndex);
+}
+
+const Entity* FilamentInstance::getJointsAt(size_t skinIndex) const noexcept {
+ return upcast(this)->getJointsAt(skinIndex);
+}
+
+void FilamentInstance::attachSkin(size_t skinIndex, Entity target) noexcept {
+ return upcast(this)->attachSkin(skinIndex, target);
+}
+
+void FilamentInstance::detachSkin(size_t skinIndex, Entity target) noexcept {
+ return upcast(this)->detachSkin(skinIndex, target);
+}
+
+
} // namespace filament::gltfio
diff --git a/libs/gltfio/src/ResourceLoader.cpp b/libs/gltfio/src/ResourceLoader.cpp
index 0d6f63a2f9..dc1d6cbc5d 100644
--- a/libs/gltfio/src/ResourceLoader.cpp
+++ b/libs/gltfio/src/ResourceLoader.cpp
@@ -75,9 +75,7 @@ struct ResourceLoader::Impl {
const bool mNormalizeSkinningWeights;
const bool mRecomputeBoundingBoxes;
const std::string mGltfPath;
-
- // TODO: this should be const
- bool mIgnoreBindTransform;
+ const bool mIgnoreBindTransform;
// User-provided resource data with URI string keys, populated with addResourceData().
// This is used on platforms without traditional file systems, such as Android, iOS, and WebGL.
@@ -442,22 +440,14 @@ bool ResourceLoader::loadResources(FFilamentAsset* asset, bool async) {
if (pImpl->mNormalizeSkinningWeights) {
normalizeSkinningWeights(asset);
}
- if (!asset->isInstanced()) {
- importSkins(gltf, asset->mNodeMap, asset->mSkins);
- } else {
- // NOTE: This takes care of up-front instances, but dynamically added instances also
- // need to import the skin data, which is done in AssetLoader.
- for (FFilamentInstance* instance : asset->mInstances) {
- importSkins(gltf, instance->nodeMap, instance->skins);
- }
+ // NOTE: This takes care of up-front instances, but dynamically added instances also
+ // need to import the skin data, which is done in AssetLoader.
+ for (FFilamentInstance* instance : asset->mInstances) {
+ importSkins(gltf, instance->nodeMap, instance->skins);
}
}
if (pImpl->mRecomputeBoundingBoxes) {
- // asset->mSkins is unused for instanced assets
- if (!pImpl->mIgnoreBindTransform) {
- pImpl->mIgnoreBindTransform = asset->isInstanced();
- }
updateBoundingBoxes(asset);
}
@@ -766,7 +756,7 @@ void ResourceLoader::Impl::computeTangents(FFilamentAsset* asset) {
}
}
// Create a job description for morph targets.
- NodeMap& nodeMap = asset->isInstanced() ? asset->mInstances[0]->nodeMap : asset->mNodeMap;
+ const NodeMap& nodeMap = asset->mInstances[0]->nodeMap;
for (auto iter : nodeMap) {
cgltf_node const* node = iter.first;
cgltf_mesh const* mesh = node->mesh;
@@ -869,7 +859,7 @@ void ResourceLoader::updateBoundingBoxes(FFilamentAsset* asset) const {
SYSTRACE_CALL();
auto& rm = pImpl->mEngine->getRenderableManager();
auto& tm = pImpl->mEngine->getTransformManager();
- NodeMap& nodeMap = asset->isInstanced() ? asset->mInstances[0]->nodeMap : asset->mNodeMap;
+ const NodeMap& nodeMap = asset->mInstances[0]->nodeMap;
// The purpose of the root node is to give the client a place for custom transforms.
// Since it is not part of the source model, it should be ignored when computing the
@@ -980,7 +970,7 @@ void ResourceLoader::updateBoundingBoxes(FFilamentAsset* asset) const {
primitives.push_back({&mesh->primitives[index], nullptr, iter.second});
}
if (cgltf_skin* const skin = iter.first->skin; skin) {
- primitives.back().skin = &asset->mSkins[skin - baseSkin];
+ primitives.back().skin = &asset->mInstances[0]->skins[skin - baseSkin];
}
}
}
diff --git a/samples/gltf_instances.cpp b/samples/gltf_instances.cpp
index 769f105cb8..828891c7fe 100644
--- a/samples/gltf_instances.cpp
+++ b/samples/gltf_instances.cpp
@@ -220,7 +220,11 @@ int main(int argc, char** argv) {
app.resourceLoader->addTextureProvider("image/jpeg", app.stbDecoder);
app.resourceLoader->addTextureProvider("image/ktx2", app.ktxDecoder);
}
- app.resourceLoader->asyncBeginLoad(app.asset);
+
+ if (!app.resourceLoader->asyncBeginLoad(app.asset)) {
+ std::cerr << "Unable to start loading resources for " << filename << std::endl;
+ exit(1);
+ }
// Load animation data.
app.asset->getAnimator();
diff --git a/samples/gltf_viewer.cpp b/samples/gltf_viewer.cpp
index dcba259552..0e85722232 100644
--- a/samples/gltf_viewer.cpp
+++ b/samples/gltf_viewer.cpp
@@ -413,11 +413,7 @@ int main(int argc, char** argv) {
}
// Parse the glTF file and create Filament entities.
- if (filename.getExtension() == "glb") {
- app.asset = app.assetLoader->createAssetFromBinary(buffer.data(), buffer.size());
- } else {
- app.asset = app.assetLoader->createAssetFromJson(buffer.data(), buffer.size());
- }
+ app.asset = app.assetLoader->createAsset(buffer.data(), buffer.size());
buffer.clear();
buffer.shrink_to_fit();
@@ -436,6 +432,7 @@ int main(int argc, char** argv) {
configuration.recomputeBoundingBoxes = app.recomputeAabb;
configuration.ignoreBindTransform = app.ignoreBindTransform;
configuration.normalizeSkinningWeights = true;
+
if (!app.resourceLoader) {
app.resourceLoader = new gltfio::ResourceLoader(configuration);
app.stbDecoder = createStbProvider(app.engine);
@@ -444,7 +441,12 @@ int main(int argc, char** argv) {
app.resourceLoader->addTextureProvider("image/jpeg", app.stbDecoder);
app.resourceLoader->addTextureProvider("image/ktx2", app.ktxDecoder);
}
- app.resourceLoader->asyncBeginLoad(app.asset);
+
+ if (!app.resourceLoader->asyncBeginLoad(app.asset)) {
+ std::cerr << "Unable to start loading resources for " << filename << std::endl;
+ exit(1);
+ }
+
app.asset->releaseSourceData();
auto ibl = FilamentApp::get().getIBL();
@@ -512,7 +514,7 @@ int main(int argc, char** argv) {
app.assetLoader = AssetLoader::create({engine, app.materials, app.names });
app.mainCamera = &view->getCamera();
if (filename.isEmpty()) {
- app.asset = app.assetLoader->createAssetFromBinary(
+ app.asset = app.assetLoader->createAsset(
GLTF_DEMO_DAMAGEDHELMET_DATA,
GLTF_DEMO_DAMAGEDHELMET_SIZE);
} else {
diff --git a/web/filament-js/extensions.js b/web/filament-js/extensions.js
index a111ddeb9b..1a7c0e6a8f 100644
--- a/web/filament-js/extensions.js
+++ b/web/filament-js/extensions.js
@@ -517,22 +517,9 @@ Filament.loadClassExtensions = function() {
return new Float32Array(arrayBuffer);
};
- Filament.gltfio$AssetLoader.prototype.createAssetFromJson = function(buffer) {
- if ('string' == typeof buffer && buffer.endsWith('.glb')) {
- console.error('Please use createAssetFromBinary for glb files.');
- }
+ Filament.gltfio$AssetLoader.prototype.createAsset = function(buffer) {
buffer = getBufferDescriptor(buffer);
- const result = this._createAssetFromJson(buffer);
- buffer.delete();
- return result;
- };
-
- Filament.gltfio$AssetLoader.prototype.createAssetFromBinary = function(buffer) {
- if ('string' == typeof buffer && buffer.endsWith('.gltf')) {
- console.error('Please use createAssetFromJson for gltf files.');
- }
- buffer = getBufferDescriptor(buffer);
- const result = this._createAssetFromBinary(buffer);
+ const result = this._createAsset(buffer);
buffer.delete();
return result;
};
diff --git a/web/filament-js/filament-viewer.js b/web/filament-js/filament-viewer.js
index 01439952f4..714b78fc17 100644
--- a/web/filament-js/filament-viewer.js
+++ b/web/filament-js/filament-viewer.js
@@ -287,7 +287,7 @@ class FilamentViewer extends LitElement {
// Dropping a glb file is simple because there are no external resources.
if (this.srcBlob && this.srcBlob.name.endsWith(".glb")) {
this.srcBlob.arrayBuffer().then(buffer => {
- this.asset = this.loader.createAssetFromBinary(new Uint8Array(buffer));
+ this.asset = this.loader.createAsset(new Uint8Array(buffer));
const aabb = this.asset.getBoundingBox();
this.assetRoot = this.asset.getRoot();
this.unitCubeTransform = Filament.fitIntoUnitCube(aabb, zoffset);
@@ -327,7 +327,7 @@ class FilamentViewer extends LitElement {
};
this.srcBlob.arrayBuffer().then(buffer => {
- this.asset = this.loader.createAssetFromJson(new Uint8Array(buffer));
+ this.asset = this.loader.createAsset(new Uint8Array(buffer));
const aabb = this.asset.getBoundingBox();
this.assetRoot = this.asset.getRoot();
this.unitCubeTransform = Filament.fitIntoUnitCube(aabb, zoffset);
@@ -367,12 +367,7 @@ class FilamentViewer extends LitElement {
return response.arrayBuffer();
}).then(arrayBuffer => {
const modelData = new Uint8Array(arrayBuffer);
- if (this.src.endsWith(".glb")) {
- this.asset = this.loader.createAssetFromBinary(modelData);
- } else {
- this.asset = this.loader.createAssetFromJson(modelData);
- }
-
+ this.asset = this.loader.createAsset(modelData);
const aabb = this.asset.getBoundingBox();
this.assetRoot = this.asset.getRoot();
this.unitCubeTransform = Filament.fitIntoUnitCube(aabb, zoffset);
diff --git a/web/filament-js/filament.d.ts b/web/filament-js/filament.d.ts
index 910b44c656..8fb78ba4ae 100644
--- a/web/filament-js/filament.d.ts
+++ b/web/filament-js/filament.d.ts
@@ -568,8 +568,7 @@ export class Ktx2Reader {
}
export class gltfio$AssetLoader {
- public createAssetFromJson(urlOrBuffer: BufferReference): gltfio$FilamentAsset;
- public createAssetFromBinary(urlOrBuffer: BufferReference): gltfio$FilamentAsset;
+ public createAsset(urlOrBuffer: BufferReference): gltfio$FilamentAsset;
public createInstancedAsset(urlOrBuffer: BufferReference,
instances: (gltfio$FilamentInstance | null)[]): gltfio$FilamentAsset;
public destroyAsset(asset: gltfio$FilamentAsset): void;
@@ -591,9 +590,6 @@ export class gltfio$FilamentAsset {
public popRenderable(): Entity;
public getMaterialInstances(): Vector;
public getResourceUris(): Vector;
- public getSkinNames(): Vector;
- public attachSkin(skinIndex: number, entity: Entity): void;
- public detachSkin(skinIndex: number, entity: Entity): void;
public getBoundingBox(): Aabb;
public getName(entity: Entity): string;
public getExtras(entity: Entity): string;
@@ -608,6 +604,9 @@ export class gltfio$FilamentInstance {
public getEntities(): Vector;
public getRoot(): Entity;
public getAnimator(): gltfio$Animator;
+ public getSkinNames(): Vector;
+ public attachSkin(skinIndex: number, entity: Entity): void;
+ public detachSkin(skinIndex: number, entity: Entity): void;
}
export class gltfio$Animator {
diff --git a/web/filament-js/jsbindings.cpp b/web/filament-js/jsbindings.cpp
index 6a6418592d..53be1a93a0 100644
--- a/web/filament-js/jsbindings.cpp
+++ b/web/filament-js/jsbindings.cpp
@@ -1785,17 +1785,6 @@ class_("gltfio$FilamentAsset")
return retval;
}), allow_raw_pointers())
- .function("getSkinNames", EMBIND_LAMBDA(std::vector, (FilamentAsset* self), {
- std::vector names(self->getSkinCount());
- for (size_t i = 0; i < names.size(); ++i) {
- names[i] = self->getSkinNameAt(i);
- }
- return names;
- }), allow_raw_pointers())
-
- .function("attachSkin", &FilamentAsset::attachSkin)
- .function("detachSkin", &FilamentAsset::detachSkin)
-
.function("getBoundingBox", &FilamentAsset::getBoundingBox)
.function("getName", EMBIND_LAMBDA(std::string, (FilamentAsset* self, utils::Entity entity), {
return std::string(self->getName(entity));
@@ -1816,7 +1805,18 @@ class_("gltfio$FilamentInstance")
}), allow_raw_pointers())
.function("getRoot", &FilamentInstance::getRoot)
.function("applyMaterialVariant", &FilamentInstance::applyMaterialVariant)
- .function("getAnimator", &FilamentInstance::getAnimator, allow_raw_pointers());
+ .function("getAnimator", &FilamentInstance::getAnimator, allow_raw_pointers())
+
+ .function("getSkinNames", EMBIND_LAMBDA(std::vector, (FilamentInstance* self), {
+ std::vector names(self->getSkinCount());
+ for (size_t i = 0; i < names.size(); ++i) {
+ names[i] = self->getSkinNameAt(i);
+ }
+ return names;
+ }), allow_raw_pointers())
+
+ .function("attachSkin", &FilamentInstance::attachSkin)
+ .function("detachSkin", &FilamentInstance::detachSkin);
// These little wrappers exist to get around RTTI requirements in embind.
@@ -1852,20 +1852,12 @@ class_("gltfio$AssetLoader")
return AssetLoader::create({ engine, materials.provider, names });
}), allow_raw_pointers())
- /// createAssetFromJson ::method::
+ /// createAsset ::method::
/// buffer ::argument:: asset string, or Uint8Array, or [Buffer]
/// ::retval:: an instance of [FilamentAsset]
- .function("_createAssetFromJson", EMBIND_LAMBDA(FilamentAsset*,
+ .function("_createAsset", EMBIND_LAMBDA(FilamentAsset*,
(AssetLoader* self, BufferDescriptor buffer), {
- return self->createAssetFromJson((const uint8_t*) buffer.bd->buffer, buffer.bd->size);
- }), allow_raw_pointers())
-
- /// createAssetFromBinary ::method::
- /// buffer ::argument:: asset string, or Uint8Array, or [Buffer]
- /// ::retval:: an instance of [FilamentAsset]
- .function("_createAssetFromBinary", EMBIND_LAMBDA(FilamentAsset*,
- (AssetLoader* self, BufferDescriptor buffer), {
- return self->createAssetFromBinary((const uint8_t*) buffer.bd->buffer, buffer.bd->size);
+ return self->createAsset((const uint8_t*) buffer.bd->buffer, buffer.bd->size);
}), allow_raw_pointers())
/// createInstancedAsset ::method::
diff --git a/web/samples/animation.html b/web/samples/animation.html
index b00ab8f008..a2c4409e4c 100644
--- a/web/samples/animation.html
+++ b/web/samples/animation.html
@@ -32,7 +32,7 @@ class App {
const scene = this.scene = engine.createScene();
const loader = engine.createAssetLoader();
- const asset = this.asset = loader.createAssetFromJson(mesh_url);
+ const asset = this.asset = loader.createAsset(mesh_url);
const sunlight = Filament.EntityManager.get().create();
Filament.LightManager.Builder(LightType.SUN).direction([0, 0, -1]).build(engine, sunlight);
diff --git a/web/samples/helmet.html b/web/samples/helmet.html
index 60b8751a3b..fe52f7eaf1 100644
--- a/web/samples/helmet.html
+++ b/web/samples/helmet.html
@@ -88,7 +88,7 @@ class App {
const loader = this.loader = engine.createAssetLoader();
this.allowRefresh = false;
- const asset = this.asset = loader.createAssetFromJson(mesh_url);
+ const asset = this.asset = loader.createAsset(mesh_url);
this.assetRoot = this.asset.getRoot();
// Crudely indicate progress by printing the URI of each resource as it is loaded.
@@ -138,7 +138,7 @@ class App {
this.allowRefresh = false;
this.scene.removeEntities(this.asset.getEntities());
this.loader.destroyAsset(this.asset);
- this.asset = this.loader.createAssetFromJson(mesh_url);
+ this.asset = this.loader.createAsset(mesh_url);
const onDone = () => { this.allowRefresh = true; }
this.asset.loadResources(onDone);
}
diff --git a/web/samples/morphing.html b/web/samples/morphing.html
index 6a5af723d9..2241b5df67 100644
--- a/web/samples/morphing.html
+++ b/web/samples/morphing.html
@@ -33,7 +33,7 @@ class App {
this.trackball = new Trackball(canvas, {startSpin: 0.035});
const loader = engine.createAssetLoader();
- const asset = this.asset = loader.createAssetFromBinary(mesh_url);
+ const asset = this.asset = loader.createAsset(mesh_url);
const onDone = () => {
loader.delete();