diff --git a/android/filament-android/src/main/cpp/RenderableManager.cpp b/android/filament-android/src/main/cpp/RenderableManager.cpp index 493996696a..0e7953a3c2 100644 --- a/android/filament-android/src/main/cpp/RenderableManager.cpp +++ b/android/filament-android/src/main/cpp/RenderableManager.cpp @@ -209,9 +209,9 @@ Java_com_google_android_filament_RenderableManager_nBuilderSkinningBones(JNIEnv* extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_RenderableManager_nBuilderMorphing(JNIEnv*, jclass, - jlong nativeBuilder, jboolean enabled) { + jlong nativeBuilder, jint targetCount) { RenderableManager::Builder *builder = (RenderableManager::Builder *) nativeBuilder; - builder->morphing(enabled); + builder->morphing(targetCount); } extern "C" JNIEXPORT void JNICALL @@ -267,11 +267,11 @@ Java_com_google_android_filament_RenderableManager_nSetBonesAsQuaternions(JNIEnv extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_RenderableManager_nSetMorphWeights(JNIEnv* env, jclass, - jlong nativeRenderableManager, jint instance, jfloatArray weights) { + jlong nativeRenderableManager, jint instance, jfloatArray weights, jint offset) { RenderableManager *rm = (RenderableManager *) nativeRenderableManager; jfloat* vec = env->GetFloatArrayElements(weights, NULL); jsize count = env->GetArrayLength(weights); - rm->setMorphWeights((RenderableManager::Instance)instance, vec, count); + rm->setMorphWeights((RenderableManager::Instance)instance, vec, count, offset); env->ReleaseFloatArrayElements(weights, vec, JNI_ABORT); } @@ -282,8 +282,14 @@ Java_com_google_android_filament_RenderableManager_nSetMorphTargetBufferAt(JNIEn RenderableManager *rm = (RenderableManager *) nativeRenderableManager; MorphTargetBuffer *morphTargetBuffer = (MorphTargetBuffer *) nativeMorphTargetBuffer; rm->setMorphTargetBufferAt((RenderableManager::Instance) i, (uint8_t) level, - (size_t) primitiveIndex, morphTargetBuffer, - (size_t) offset, (size_t) count); + (size_t) primitiveIndex, morphTargetBuffer, (size_t) offset, (size_t) count); +} + +extern "C" JNIEXPORT jint JNICALL +Java_com_google_android_filament_RenderableManager_nGetMorphTargetCount(JNIEnv* env, jclass, + jlong nativeRenderableManager, jint instance) { + RenderableManager *rm = (RenderableManager *) nativeRenderableManager; + return rm->getMorphTargetCount((RenderableManager::Instance)instance); } extern "C" JNIEXPORT void JNICALL diff --git a/android/filament-android/src/main/java/com/google/android/filament/RenderableManager.java b/android/filament-android/src/main/java/com/google/android/filament/RenderableManager.java index 61291f038b..ab1478e6fa 100644 --- a/android/filament-android/src/main/java/com/google/android/filament/RenderableManager.java +++ b/android/filament-android/src/main/java/com/google/android/filament/RenderableManager.java @@ -400,14 +400,14 @@ public class RenderableManager { } /** - * Controls if the renderable has vertex morphing targets, false by default. + * Controls if the renderable has vertex morphing targets, zero by default. * *
See also {@link RenderableManager#setMorphWeights}, which can be called on a per-frame basis * to advance the animation.
*/ @NonNull - public Builder morphing(boolean enabled) { - nBuilderMorphing(mNativeBuilder, enabled); + public Builder morphing(@IntRange(from = 0, to = 125) int targetCount) { + nBuilderMorphing(mNativeBuilder, targetCount); return this; } @@ -498,8 +498,8 @@ public class RenderableManager { * * @see Builder#morphing */ - public void setMorphWeights(@EntityInstance int i, @NonNull float[] weights) { - nSetMorphWeights(mNativeObject, i, weights); + public void setMorphWeights(@EntityInstance int i, @NonNull float[] weights, @IntRange(from = 0) int offset) { + nSetMorphWeights(mNativeObject, i, weights, offset); } /** @@ -519,6 +519,14 @@ public class RenderableManager { morphTargetBuffer.getNativeObject(), offset, count); } + /** + * Gets the morph target count on a renderable. + */ + @IntRange(from = 0) + public int getMorphTargetCount(@EntityInstance int i) { + return nGetMorphTargetCount(mNativeObject, i); + } + /** * Changes the morph target buffer for the given primitive. * @@ -789,15 +797,16 @@ public class RenderableManager { private static native void nBuilderSkinning(long nativeBuilder, int boneCount); private static native int nBuilderSkinningBones(long nativeBuilder, int boneCount, Buffer bones, int remaining); private static native void nBuilderSkinningBuffer(long nativeBuilder, long nativeSkinningBuffer, int boneCount, int offset); - private static native void nBuilderMorphing(long nativeBuilder, boolean enabled); + private static native void nBuilderMorphing(long nativeBuilder, int targetCount); private static native void nEnableSkinningBuffers(long nativeBuilder, boolean enabled); private static native void nBuilderLightChannel(long nativeRenderableManager, int channel, boolean enable); private static native void nSetSkinningBuffer(long nativeObject, int i, long nativeSkinningBuffer, int count, int offset); private static native int nSetBonesAsMatrices(long nativeObject, int i, Buffer matrices, int remaining, int boneCount, int offset); private static native int nSetBonesAsQuaternions(long nativeObject, int i, Buffer quaternions, int remaining, int boneCount, int offset); - private static native void nSetMorphWeights(long nativeObject, int instance, float[] weights); + private static native void nSetMorphWeights(long nativeObject, int instance, float[] weights, int offset); private static native void nSetMorphTargetBufferAt(long nativeObject, int i, int level, int primitiveIndex, long nativeMorphTargetBuffer, int offset, int count); + private static native int nGetMorphTargetCount(long nativeObject, int i); private static native void nSetAxisAlignedBoundingBox(long nativeRenderableManager, int i, float cx, float cy, float cz, float ex, float ey, float ez); private static native void nSetLayerMask(long nativeRenderableManager, int i, int select, int value); private static native void nSetPriority(long nativeRenderableManager, int i, int priority); diff --git a/android/gltfio-android/src/main/cpp/FilamentAsset.cpp b/android/gltfio-android/src/main/cpp/FilamentAsset.cpp index d121cb474b..252af29582 100644 --- a/android/gltfio-android/src/main/cpp/FilamentAsset.cpp +++ b/android/gltfio-android/src/main/cpp/FilamentAsset.cpp @@ -208,14 +208,6 @@ Java_com_google_android_filament_gltfio_FilamentAsset_nGetAnimator(JNIEnv* , jcl return (jlong) asset->getAnimator(); } -extern "C" JNIEXPORT int JNICALL -Java_com_google_android_filament_gltfio_FilamentAsset_nGetMorphTargetCount(JNIEnv* , jclass, - jlong nativeAsset, int entityId) { - FilamentAsset* asset = (FilamentAsset*) nativeAsset; - Entity entity = Entity::import(entityId); - return asset->getMorphTargetCount(entity); -} - extern "C" JNIEXPORT jint JNICALL Java_com_google_android_filament_gltfio_FilamentAsset_nGetResourceUriCount(JNIEnv*, jclass, jlong 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 e24a2134ab..046431100b 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 @@ -216,14 +216,6 @@ public class FilamentAsset { return mAnimator; } - /** - * Gets the number of morphing in the given entity. - */ - @IntRange(from = 0) - public int getMorphTargetCount(@Entity int entity) { - return nGetMorphTargetCount(mNativeObject, entity); - } - /** * Gets resource URIs for all externally-referenced buffers. */ @@ -273,7 +265,6 @@ public class FilamentAsset { 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 int nGetMorphTargetCount(long nativeAsset, int entity); 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/filament/include/filament/RenderableManager.h b/filament/include/filament/RenderableManager.h index 5df4d183da..a77e1dea28 100644 --- a/filament/include/filament/RenderableManager.h +++ b/filament/include/filament/RenderableManager.h @@ -300,12 +300,12 @@ public: Builder& skinning(size_t boneCount) noexcept; //!< \overload /** - * Controls if the renderable has vertex morphing targets, false by default. + * Controls if the renderable has vertex morphing targets, zero by default. * * See also RenderableManager::setMorphWeights(), which can be called on a per-frame basis * to advance the animation. */ - Builder& morphing(bool enable) noexcept; + Builder& morphing(size_t targetCount) noexcept; /** * Sets an ordering index for blended primitives that all live at the same Z value. @@ -443,30 +443,41 @@ public: * Updates the bone transforms in the range [offset, offset + boneCount). * The bones must be pre-allocated using Builder::skinning(). */ - void setBones(Instance instance, Bone const* transforms, size_t boneCount = 1, size_t offset = 0) noexcept; - void setBones(Instance instance, math::mat4f const* transforms, size_t boneCount = 1, size_t offset = 0) noexcept; //!< \overload + void setBones(Instance instance, Bone const* transforms, size_t boneCount = 1, size_t offset = 0); + void setBones(Instance instance, math::mat4f const* transforms, size_t boneCount = 1, size_t offset = 0); //!< \overload /** * Associates a SkinningBuffer to a renderable instance */ void setSkinningBuffer(Instance instance, SkinningBuffer* skinningBuffer, - size_t count, size_t offset) noexcept; + size_t count, size_t offset); /** * Updates the vertex morphing weights on a renderable, all zeroes by default. * * The renderable must be built with morphing enabled, see Builder::morphing(). + * + * @param instance Instance of the component obtained from getInstance(). + * @param weights Pointer to morph target weights to be update. + * @param count Number of morph target weights. + * @param offset Index of the first first morph target weight to set at instance. */ - void setMorphWeights(Instance instance, float const* weights, size_t count) noexcept; - + void setMorphWeights(Instance instance, + float const* weights, size_t count, size_t offset = 0); /** * Associates a MorphTargetBuffer to the given primitive. */ void setMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex, - MorphTargetBuffer* morphTargetBuffer, size_t offset, size_t count) noexcept; + MorphTargetBuffer* morphTargetBuffer, size_t offset, size_t count); void setMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex, - MorphTargetBuffer* morphTargetBuffer, size_t count) noexcept; //!< \overload + MorphTargetBuffer* morphTargetBuffer, size_t count); //!< \overload + + /** + * Gets t + * number of morphing in the given entity. + */ + size_t getMorphTargetCount(Instance instance) const noexcept; /** * Gets the bounding box used for frustum culling. diff --git a/filament/src/components/RenderableManager.cpp b/filament/src/components/RenderableManager.cpp index 7ae6116433..ee1f39604c 100644 --- a/filament/src/components/RenderableManager.cpp +++ b/filament/src/components/RenderableManager.cpp @@ -53,9 +53,9 @@ struct RenderableManager::BuilderDetails { bool mCastShadows : 1; bool mReceiveShadows : 1; bool mScreenSpaceContactShadows : 1; - bool mMorphingEnabled : 1; bool mSkinningBufferMode : 1; size_t mSkinningBoneCount = 0; + size_t mMorphTargetCount = 0; Bone const* mUserBones = nullptr; mat4f const* mUserBoneMatrices = nullptr; FSkinningBuffer* mSkinningBuffer = nullptr; @@ -63,8 +63,7 @@ struct RenderableManager::BuilderDetails { explicit BuilderDetails(size_t count) : mEntries(count), mCulling(true), mCastShadows(false), mReceiveShadows(true), - mScreenSpaceContactShadows(false), mMorphingEnabled(false), - mSkinningBufferMode(false) { + mScreenSpaceContactShadows(false), mSkinningBufferMode(false) { } // this is only needed for the explicit instantiation below BuilderDetails() = default; @@ -193,8 +192,8 @@ RenderableManager::Builder& RenderableManager::Builder::enableSkinningBuffers(bo return *this; } -RenderableManager::Builder& RenderableManager::Builder::morphing(bool enable) noexcept { - mImpl->mMorphingEnabled = enable; +RenderableManager::Builder& RenderableManager::Builder::morphing(size_t targetCount) noexcept { + mImpl->mMorphTargetCount = targetCount; return *this; } @@ -318,10 +317,11 @@ void FRenderableManager::create( setScreenSpaceContactShadows(ci, builder->mScreenSpaceContactShadows); setCulling(ci, builder->mCulling); setSkinning(ci, false); - setMorphing(ci, builder->mMorphingEnabled); + setMorphing(ci, builder->mMorphTargetCount); mManager[ci].channels = builder->mChannels; const uint32_t boneCount = builder->mSkinningBoneCount; + const uint32_t targetCount = builder->mMorphTargetCount; if (builder->mSkinningBufferMode) { if (builder->mSkinningBuffer) { setSkinning(ci, boneCount > 0); @@ -333,7 +333,7 @@ void FRenderableManager::create( .skinningBufferMode = true }; } } else { - if (UTILS_UNLIKELY(boneCount > 0 || builder->mMorphingEnabled)) { + if (UTILS_UNLIKELY(boneCount > 0 || targetCount > 0)) { setSkinning(ci, boneCount > 0); Bones& bones = manager[ci].bones; // Note that we are sizing the bones UBO according to CONFIG_MAX_BONE_COUNT rather than @@ -378,7 +378,7 @@ void FRenderableManager::create( // Even morphing isn't enabled, we should create morphig resources. // Because morphing shader code is generated when skinning is enabled. // You can see more detail at Variant::SKINNING_OR_MORPHING. - if (UTILS_UNLIKELY(boneCount > 0 || builder->mMorphingEnabled)) { + if (UTILS_UNLIKELY(boneCount > 0 || targetCount > 0)) { // Instead of using a UBO per primitive, we could also have a single UBO for all primitives // and use bindUniformBufferRange which might be more efficient. MorphWeights& morphWeights = manager[ci].morphWeights; @@ -387,7 +387,7 @@ void FRenderableManager::create( sizeof(PerRenderableMorphingUib), BufferObjectBinding::UNIFORM, backend::BufferUsage::DYNAMIC), - .count = 0 }; + .count = targetCount }; } } engine.flushIfNeeded(); @@ -523,7 +523,7 @@ void FRenderableManager::setGeometryAt(Instance instance, uint8_t level, size_t } void FRenderableManager::setBones(Instance ci, - Bone const* UTILS_RESTRICT transforms, size_t boneCount, size_t offset) noexcept { + Bone const* UTILS_RESTRICT transforms, size_t boneCount, size_t offset) { if (ci) { Bones& bones = mManager[ci].bones; @@ -539,7 +539,7 @@ void FRenderableManager::setBones(Instance ci, } void FRenderableManager::setBones(Instance ci, - mat4f const* UTILS_RESTRICT transforms, size_t boneCount, size_t offset) noexcept { + mat4f const* UTILS_RESTRICT transforms, size_t boneCount, size_t offset) { if (ci) { Bones& bones = mManager[ci].bones; @@ -555,7 +555,7 @@ void FRenderableManager::setBones(Instance ci, } void FRenderableManager::setSkinningBuffer(FRenderableManager::Instance ci, - FSkinningBuffer* skinningBuffer, size_t count, size_t offset) noexcept { + FSkinningBuffer* skinningBuffer, size_t count, size_t offset) { Bones& bones = mManager[ci].bones; @@ -586,34 +586,41 @@ void FRenderableManager::setSkinningBuffer(FRenderableManager::Instance ci, } static void updateMorphWeights(FEngine& engine, backend::Handle