From bef004e1b0ff4fbf0ab9e9f6a688a15651d2f6f8 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Thu, 16 May 2024 16:36:52 -0700 Subject: [PATCH] switch to new morphing API - remove deprecated morphing APIs - repair gltfio, samples and tests The new API doesn't allow a MorphTargetBuffer per RenderPrimitive, instead the MorphTargetBuffer is specified per Renderable. gltfio separates RenderPrimitives from Renderables, in particular all RenderPrimitives are created before their Renderable; this was problematic for this change because all primitives must share a single MorphTargetBuffer living in the Renderable. To fix this, we're no longer initializing the morphing paramters at RenderPrimitive creation, instead we store a reference to the BufferSlot in the Primtive structure, so that later, when the Renderable is created we can finally retrieve the BufferSlot and initialize its morphing paramters, which are not available. The "morphing parameters" are now expanded to contain the MorphTargetBuffer as before (except now it's always the same for all the primitives of a Rendrable), as well as the offset within the buffer and the vertex count. --- .../src/main/cpp/RenderableManager.cpp | 26 +-- .../android/filament/MorphTargetBuffer.java | 2 +- .../android/filament/RenderableManager.java | 64 +------ filament/include/filament/RenderableManager.h | 47 +---- filament/src/RenderPass.cpp | 6 +- filament/src/RenderPrimitive.h | 6 + filament/src/RenderableManager.cpp | 18 +- filament/src/components/RenderableManager.cpp | 80 ++------ filament/src/components/RenderableManager.h | 40 +--- filament/src/details/MorphTargetBuffer.h | 18 +- libs/gltfio/src/AssetLoader.cpp | 93 +++++++-- libs/gltfio/src/FFilamentAsset.h | 8 +- libs/gltfio/src/ResourceLoader.cpp | 24 ++- libs/gltfio/src/TangentsJob.h | 1 + .../src/extended/AssetLoaderExtended.cpp | 20 +- .../src/extended/ResourceLoaderExtended.cpp | 5 +- libs/gltfio/test/gltfio_test.cpp | 2 +- samples/hellomorphing.cpp | 6 +- samples/skinningtest.cpp | 178 +++++++++--------- 19 files changed, 286 insertions(+), 358 deletions(-) diff --git a/android/filament-android/src/main/cpp/RenderableManager.cpp b/android/filament-android/src/main/cpp/RenderableManager.cpp index db0255d414e..4f38e46f82d 100644 --- a/android/filament-android/src/main/cpp/RenderableManager.cpp +++ b/android/filament-android/src/main/cpp/RenderableManager.cpp @@ -253,16 +253,10 @@ Java_com_google_android_filament_RenderableManager_nBuilderMorphingStandard(JNIE } extern "C" JNIEXPORT void JNICALL -Java_com_google_android_filament_RenderableManager_nBuilderSetMorphTargetBufferAt(JNIEnv*, jclass, - jlong nativeBuilder, int level, int primitiveIndex, jlong nativeMorphTargetBuffer, - int offset, int count) { +Java_com_google_android_filament_RenderableManager_nBuilderSetMorphTargetBufferOffsetAt(JNIEnv*, jclass, + jlong nativeBuilder, int level, int primitiveIndex, int offset) { RenderableManager::Builder *builder = (RenderableManager::Builder *) nativeBuilder; - if (nativeMorphTargetBuffer) { - MorphTargetBuffer *morphTargetBuffer = (MorphTargetBuffer *) nativeMorphTargetBuffer; - builder->morphing(level, primitiveIndex, morphTargetBuffer, offset, count); - } else { - builder->morphing(level, primitiveIndex, offset, count); - } + builder->morphing(level, primitiveIndex, offset); } extern "C" JNIEXPORT void JNICALL @@ -334,18 +328,12 @@ Java_com_google_android_filament_RenderableManager_nSetMorphWeights(JNIEnv* env, } extern "C" JNIEXPORT void JNICALL -Java_com_google_android_filament_RenderableManager_nSetMorphTargetBufferAt(JNIEnv*, +Java_com_google_android_filament_RenderableManager_nSetMorphTargetBufferOffsetAt(JNIEnv*, jclass, jlong nativeRenderableManager, jint i, int level, jint primitiveIndex, - jlong nativeMorphTargetBuffer, jint offset, jint count) { + jlong, jint offset) { RenderableManager *rm = (RenderableManager *) nativeRenderableManager; - if (nativeMorphTargetBuffer) { - MorphTargetBuffer *morphTargetBuffer = (MorphTargetBuffer *) nativeMorphTargetBuffer; - rm->setMorphTargetBufferAt((RenderableManager::Instance) i, (uint8_t) level, - (size_t) primitiveIndex, morphTargetBuffer, (size_t) offset, (size_t) count); - } else { - rm->setMorphTargetBufferAt((RenderableManager::Instance) i, (uint8_t) level, - (size_t) primitiveIndex, (size_t) offset, (size_t) count); - } + rm->setMorphTargetBufferOffsetAt((RenderableManager::Instance) i, (uint8_t) level, + (size_t) primitiveIndex, (size_t) offset); } extern "C" JNIEXPORT jint JNICALL diff --git a/android/filament-android/src/main/java/com/google/android/filament/MorphTargetBuffer.java b/android/filament-android/src/main/java/com/google/android/filament/MorphTargetBuffer.java index f82ca4780b0..619870d372d 100644 --- a/android/filament-android/src/main/java/com/google/android/filament/MorphTargetBuffer.java +++ b/android/filament-android/src/main/java/com/google/android/filament/MorphTargetBuffer.java @@ -74,7 +74,7 @@ public Builder count(@IntRange(from = 1) int count) { * * @exception IllegalStateException if the MorphTargetBuffer could not be created * - * @see #setMorphTargetBufferAt + * @see #setMorphTargetBufferOffsetAt */ @NonNull public MorphTargetBuffer build(@NonNull Engine engine) { 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 dfce1af4a16..0da9a0d6e79 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 @@ -569,40 +569,13 @@ public Builder morphing(@NonNull MorphTargetBuffer morphTargetBuffer) { * * @param level the level of detail (lod), only 0 can be specified * @param primitiveIndex zero-based index of the primitive, must be less than the count passed to Builder constructor - * @param morphTargetBuffer specifies the morph target buffer * @param offset specifies where in the morph target buffer to start reading (expressed as a number of vertices) - * @param count number of vertices in the morph target buffer to read, must equal the geometry's count (for triangles, this should be a multiple of 3) */ @NonNull public Builder morphing(@IntRange(from = 0) int level, @IntRange(from = 0) int primitiveIndex, - @IntRange(from = 0) int offset, - @IntRange(from = 0) int count) { - nBuilderSetMorphTargetBufferAt(mNativeBuilder, level, primitiveIndex, 0, offset, count); - return this; - } - - /** @deprecated */ - @Deprecated - @NonNull - public Builder morphing(@IntRange(from = 0) int level, - @IntRange(from = 0) int primitiveIndex, - @NonNull MorphTargetBuffer morphTargetBuffer, - @IntRange(from = 0) int offset, - @IntRange(from = 0) int count) { - nBuilderSetMorphTargetBufferAt(mNativeBuilder, level, primitiveIndex, - morphTargetBuffer.getNativeObject(), offset, count); - return this; - } - - /** @deprecated */ - @Deprecated - @NonNull - public Builder morphing(@IntRange(from = 0) int level, - @IntRange(from = 0) int primitiveIndex, - @NonNull MorphTargetBuffer morphTargetBuffer) { - nBuilderSetMorphTargetBufferAt(mNativeBuilder, level, primitiveIndex, - morphTargetBuffer.getNativeObject(), 0, morphTargetBuffer.getVertexCount()); + @IntRange(from = 0) int offset) { + nBuilderSetMorphTargetBufferOffsetAt(mNativeBuilder, level, primitiveIndex, offset); return this; } @@ -705,34 +678,11 @@ public void setMorphWeights(@EntityInstance int i, @NonNull float[] weights, @In * * @see Builder#morphing */ - public void setMorphTargetBufferAt(@EntityInstance int i, - @IntRange(from = 0) int level, - @IntRange(from = 0) int primitiveIndex, - @IntRange(from = 0) int offset, - @IntRange(from = 0) int count) { - nSetMorphTargetBufferAt(mNativeObject, i, level, primitiveIndex, 0, offset, count); - } - - /** @deprecated */ - @Deprecated - public void setMorphTargetBufferAt(@EntityInstance int i, - @IntRange(from = 0) int level, - @IntRange(from = 0) int primitiveIndex, - @NonNull MorphTargetBuffer morphTargetBuffer, - @IntRange(from = 0) int offset, - @IntRange(from = 0) int count) { - nSetMorphTargetBufferAt(mNativeObject, i, level, primitiveIndex, - morphTargetBuffer.getNativeObject(), offset, count); - } - - /** @deprecated */ - @Deprecated - public void setMorphTargetBufferAt(@EntityInstance int i, + public void setMorphTargetBufferOffsetAt(@EntityInstance int i, @IntRange(from = 0) int level, @IntRange(from = 0) int primitiveIndex, - @NonNull MorphTargetBuffer morphTargetBuffer) { - nSetMorphTargetBufferAt(mNativeObject, i, level, primitiveIndex, - morphTargetBuffer.getNativeObject(), 0, morphTargetBuffer.getVertexCount()); + @IntRange(from = 0) int offset) { + nSetMorphTargetBufferOffsetAt(mNativeObject, i, level, primitiveIndex, 0, offset); } /** @@ -1033,7 +983,7 @@ public long getNativeObject() { private static native void nBuilderSkinningBuffer(long nativeBuilder, long nativeSkinningBuffer, int boneCount, int offset); private static native void nBuilderMorphing(long nativeBuilder, int targetCount); private static native void nBuilderMorphingStandard(long nativeBuilder, long nativeMorphTargetBuffer); - private static native void nBuilderSetMorphTargetBufferAt(long nativeBuilder, int level, int primitiveIndex, long nativeMorphTargetBuffer, int offset, int count); + private static native void nBuilderSetMorphTargetBufferOffsetAt(long nativeBuilder, int level, int primitiveIndex, int offset); private static native void nBuilderEnableSkinningBuffers(long nativeBuilder, boolean enabled); private static native void nBuilderFog(long nativeBuilder, boolean enabled); private static native void nBuilderLightChannel(long nativeRenderableManager, int channel, boolean enable); @@ -1043,7 +993,7 @@ public long getNativeObject() { 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, int offset); - private static native void nSetMorphTargetBufferAt(long nativeObject, int i, int level, int primitiveIndex, long nativeMorphTargetBuffer, int offset, int count); + private static native void nSetMorphTargetBufferOffsetAt(long nativeObject, int i, int level, int primitiveIndex, long nativeMorphTargetBuffer, int offset); 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); diff --git a/filament/include/filament/RenderableManager.h b/filament/include/filament/RenderableManager.h index 363ef2d7c1f..2c227e0c644 100644 --- a/filament/include/filament/RenderableManager.h +++ b/filament/include/filament/RenderableManager.h @@ -489,43 +489,20 @@ class UTILS_PUBLIC RenderableManager : public FilamentAPI { * For standard morphing, A MorphTargetBuffer must be provided. * Standard morphing supports up to \c CONFIG_MAX_MORPH_TARGET_COUNT morph targets. * - * For legacy morphing, the attached VertexBuffer must provide data in the - * appropriate VertexAttribute slots (\c MORPH_POSITION_0 etc). Legacy morphing only - * supports up to 4 morph targets and will be deprecated in the future. Legacy morphing must - * be enabled on the material definition: either via the legacyMorphing material attribute - * or by calling filamat::MaterialBuilder::useLegacyMorphing(). - * * See also RenderableManager::setMorphWeights(), which can be called on a per-frame basis * to advance the animation. */ Builder& morphing(MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer) noexcept; - /** - * @deprecated Use morphing(uint8_t level, size_t primitiveIndex, size_t offset, size_t count) instead - */ - Builder& morphing(uint8_t level, size_t primitiveIndex, - MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer, - size_t offset, size_t count) noexcept; - - /** - * @deprecated Use morphing(uint8_t level, size_t primitiveIndex, size_t offset, size_t count) instead - */ - inline Builder& morphing(uint8_t level, size_t primitiveIndex, - MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer) noexcept { - return morphing(level, primitiveIndex, morphTargetBuffer, 0, - morphTargetBuffer->getVertexCount()); - } - /** * Specifies the the range of the MorphTargetBuffer to use with this primitive. * * @param level the level of detail (lod), only 0 can be specified * @param primitiveIndex zero-based index of the primitive, must be less than the count passed to Builder constructor * @param offset specifies where in the morph target buffer to start reading (expressed as a number of vertices) - * @param count number of vertices in the morph target buffer to read, must equal the geometry's count (for triangles, this should be a multiple of 3) */ - Builder& morphing(uint8_t level, size_t primitiveIndex, - size_t offset, size_t count) noexcept; + RenderableManager::Builder& morphing(uint8_t level, + size_t primitiveIndex, size_t offset) noexcept; /** @@ -786,25 +763,13 @@ class UTILS_PUBLIC RenderableManager : public FilamentAPI { /** * Associates a MorphTargetBuffer to the given primitive. */ - void setMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex, - size_t offset, size_t count); - - /** @deprecated */ - void setMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex, - MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer, size_t offset, size_t count); - - /** @deprecated */ - inline void setMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex, - MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer) { - setMorphTargetBufferAt(instance, level, primitiveIndex, morphTargetBuffer, 0, - morphTargetBuffer->getVertexCount()); - } + void setMorphTargetBufferOffsetAt(Instance instance, uint8_t level, size_t primitiveIndex, + size_t offset); /** - * Get a MorphTargetBuffer to the given primitive or null if it doesn't exist. + * Get a MorphTargetBuffer to the given renderable or null if it doesn't exist. */ - MorphTargetBuffer* UTILS_NULLABLE getMorphTargetBufferAt(Instance instance, - uint8_t level, size_t primitiveIndex) const noexcept; + MorphTargetBuffer* UTILS_NULLABLE getMorphTargetBuffer(Instance instance) const noexcept; /** * Gets the number of morphing in the given entity. diff --git a/filament/src/RenderPass.cpp b/filament/src/RenderPass.cpp index ee5092370d0..cc892b910d4 100644 --- a/filament/src/RenderPass.cpp +++ b/filament/src/RenderPass.cpp @@ -671,7 +671,6 @@ RenderPass::Command* RenderPass::generateCommandsImpl(RenderPass::CommandTypeFla */ for (size_t pi = 0, c = primitives.size(); pi < c; ++pi) { auto const& primitive = primitives[pi]; - auto const& morphTargets = morphing.targets[pi]; FMaterialInstance const* const mi = primitive.getMaterialInstance(); FMaterial const* const ma = mi->getMaterial(); @@ -684,8 +683,9 @@ RenderPass::Command* RenderPass::generateCommandsImpl(RenderPass::CommandTypeFla cmd.info.indexOffset = primitive.getIndexOffset(); cmd.info.indexCount = primitive.getIndexCount(); cmd.info.type = primitive.getPrimitiveType(); - cmd.info.morphTargetBuffer = morphTargets.buffer->getHwHandle(); - cmd.info.morphingOffset = morphTargets.offset; + cmd.info.morphTargetBuffer = morphing.morphTargetBuffer ? + morphing.morphTargetBuffer->getHwHandle() : SamplerGroupHandle{}; + cmd.info.morphingOffset = primitive.getMorphingBufferOffset(); if constexpr (isColorPass) { RenderPass::setupColorCommand(cmd, renderableVariant, mi, inverseFrontFaces); diff --git a/filament/src/RenderPrimitive.h b/filament/src/RenderPrimitive.h index 07d7431f021..a8600dd3a6f 100644 --- a/filament/src/RenderPrimitive.h +++ b/filament/src/RenderPrimitive.h @@ -56,6 +56,7 @@ class FRenderPrimitive { backend::VertexBufferInfoHandle getVertexBufferInfoHandle() const { return mVertexBufferInfoHandle; } uint32_t getIndexOffset() const noexcept { return mIndexOffset; } uint32_t getIndexCount() const noexcept { return mIndexCount; } + uint32_t getMorphingBufferOffset() const noexcept { return mMorphingBufferOffset; } backend::PrimitiveType getPrimitiveType() const noexcept { return mPrimitiveType; } AttributeBitset getEnabledAttributes() const noexcept { return mEnabledAttributes; } @@ -72,6 +73,10 @@ class FRenderPrimitive { mGlobalBlendOrderEnabled = enabled; } + void setMorphingBufferOffset(uint32_t offset) noexcept { + mMorphingBufferOffset = offset; + } + private: // These first fields are dereferences from PrimitiveInfo, keep them together struct { @@ -80,6 +85,7 @@ class FRenderPrimitive { backend::Handle mVertexBufferInfoHandle = {}; uint32_t mIndexOffset = 0; uint32_t mIndexCount = 0; + uint32_t mMorphingBufferOffset = 0; }; AttributeBitset mEnabledAttributes = {}; diff --git a/filament/src/RenderableManager.cpp b/filament/src/RenderableManager.cpp index 9550197acf0..87ea0d0e462 100644 --- a/filament/src/RenderableManager.cpp +++ b/filament/src/RenderableManager.cpp @@ -158,20 +158,14 @@ void RenderableManager::setMorphWeights(Instance instance, float const* weights, downcast(this)->setMorphWeights(instance, weights, count, offset); } -void RenderableManager::setMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex, - MorphTargetBuffer* morphTargetBuffer, size_t offset, size_t count) { - downcast(this)->setMorphTargetBufferAt(instance, level, primitiveIndex, - downcast(morphTargetBuffer), offset, count); +void RenderableManager::setMorphTargetBufferOffsetAt(Instance instance, uint8_t level, + size_t primitiveIndex, + size_t offset) { + downcast(this)->setMorphTargetBufferOffsetAt(instance, level, primitiveIndex, offset); } -void RenderableManager::setMorphTargetBufferAt( - Instance instance, uint8_t level, size_t primitiveIndex, size_t offset, size_t count) { - downcast(this)->setMorphTargetBufferAt(instance, level, primitiveIndex, offset, count); -} - -MorphTargetBuffer* RenderableManager::getMorphTargetBufferAt(Instance instance, uint8_t level, - size_t primitiveIndex) const noexcept { - return downcast(this)->getMorphTargetBufferAt(instance, level, primitiveIndex); +MorphTargetBuffer* RenderableManager::getMorphTargetBuffer(Instance instance) const noexcept { + return downcast(this)->getMorphTargetBuffer(instance); } size_t RenderableManager::getMorphTargetCount(Instance instance) const noexcept { diff --git a/filament/src/components/RenderableManager.cpp b/filament/src/components/RenderableManager.cpp index 596cd8e7fe7..cdadc4e35e0 100644 --- a/filament/src/components/RenderableManager.cpp +++ b/filament/src/components/RenderableManager.cpp @@ -281,19 +281,13 @@ RenderableManager::Builder& RenderableManager::Builder::morphing( return *this; } -RenderableManager::Builder& RenderableManager::Builder::morphing( - uint8_t level, size_t primitiveIndex, size_t offset, size_t count) noexcept { - return morphing(level, primitiveIndex, mImpl->mMorphTargetBuffer, offset, count); -} - -RenderableManager::Builder& RenderableManager::Builder::morphing(uint8_t, size_t primitiveIndex, - MorphTargetBuffer* morphTargetBuffer, size_t offset, size_t count) noexcept { - std::vector& entries = mImpl->mEntries; +RenderableManager::Builder& RenderableManager::Builder::morphing(uint8_t level, + size_t primitiveIndex, size_t offset) noexcept { + // the last parameter "count" is unused, because it must be equal to the primitive's vertex count + std::vector& entries = mImpl->mEntries; if (primitiveIndex < entries.size()) { auto& morphing = entries[primitiveIndex].morphing; - morphing.buffer = morphTargetBuffer; - morphing.offset = offset; - morphing.count = count; + morphing.offset = uint32_t(offset); } return *this; } @@ -668,13 +662,6 @@ void FRenderableManager::create( if (morphTargetBuffer == nullptr) { morphTargetBuffer = mEngine.getDummyMorphTargetBuffer(); } - MorphTargets* const morphTargets = new MorphTargets[entryCount]; - std::generate_n(morphTargets, entryCount, - [morphTargetBuffer]() -> MorphTargets { - return { morphTargetBuffer, 0, 0 }; - }); - - mManager[ci].morphTargets = { morphTargets, size_type(entryCount) }; // Always create skinning and morphing resources if one of them is enabled because // the shader always handles both. See Variant::SKINNING_OR_MORPHING. @@ -700,13 +687,13 @@ void FRenderableManager::create( backend::BufferUsage::DYNAMIC), .count = targetCount }; - for (size_t i = 0; i < entryCount; ++i) { - const auto& morphing = builder->mEntries[i].morphing; - if (!morphing.buffer) { - continue; + Slice& primitives = mManager[ci].primitives; + mManager[ci].morphTargetBuffer = morphTargetBuffer; + if (builder->mMorphTargetBuffer) { + for (size_t i = 0; i < entryCount; ++i) { + const auto& morphing = builder->mEntries[i].morphing; + primitives[i].setMorphingBufferOffset(morphing.offset); } - morphTargets[i] = { downcast(morphing.buffer), (uint32_t)morphing.offset, - (uint32_t)morphing.count }; } // When targetCount equal 0, boneCount>0 in this case, do an initialization for the @@ -762,7 +749,6 @@ void FRenderableManager::destroyComponent(Instance ci) noexcept { // See create(RenderableManager::Builder&, Entity) destroyComponentPrimitives(mHwRenderPrimitiveFactory, driver, manager[ci].primitives); - destroyComponentMorphTargets(engine, manager[ci].morphTargets); // destroy the bones structures if any Bones const& bones = manager[ci].bones; @@ -795,11 +781,6 @@ void FRenderableManager::destroyComponentPrimitives( delete[] primitives.data(); } -void FRenderableManager::destroyComponentMorphTargets(FEngine&, - utils::Slice& morphTargets) noexcept { - delete[] morphTargets.data(); -} - void FRenderableManager::setMaterialInstanceAt(Instance instance, uint8_t level, size_t primitiveIndex, FMaterialInstance const* mi) { if (instance) { @@ -968,42 +949,21 @@ void FRenderableManager::setMorphWeights(Instance instance, float const* weights } } -void FRenderableManager::setMorphTargetBufferAt(Instance instance, uint8_t level, - size_t primitiveIndex, FMorphTargetBuffer* morphTargetBuffer, size_t offset, size_t count) { - if (instance) { - assert_invariant(morphTargetBuffer); - - MorphWeights const& morphWeights = mManager[instance].morphWeights; - FILAMENT_CHECK_PRECONDITION(morphWeights.count == count) - << "Only " << morphWeights.count << " morph targets can be set (count=" << count - << ")"; - - Slice& morphTargets = getMorphTargets(instance, level); - if (primitiveIndex < morphTargets.size()) { - morphTargets[primitiveIndex] = { morphTargetBuffer, (uint32_t)offset, - (uint32_t)count }; - } - } -} - -void FRenderableManager::setMorphTargetBufferAt(Instance instance, uint8_t level, - size_t primitiveIndex, size_t offset, size_t count) { +void FRenderableManager::setMorphTargetBufferOffsetAt(Instance instance, uint8_t level, + size_t primitiveIndex, + size_t offset) { if (instance) { - Slice& morphTargets = getMorphTargets(instance, level); - if (primitiveIndex < morphTargets.size()) { - setMorphTargetBufferAt(instance, level, - primitiveIndex, morphTargets[primitiveIndex].buffer, offset, count); + assert_invariant(mManager[instance].morphTargetBuffer); + Slice& primitives = mManager[instance].primitives; + if (primitiveIndex < primitives.size()) { + primitives[primitiveIndex].setMorphingBufferOffset(offset); } } } -MorphTargetBuffer* FRenderableManager::getMorphTargetBufferAt(Instance instance, uint8_t level, - size_t primitiveIndex) const noexcept { +MorphTargetBuffer* FRenderableManager::getMorphTargetBuffer(Instance instance) const noexcept { if (instance) { - const Slice& morphTargets = getMorphTargets(instance, level); - if (primitiveIndex < morphTargets.size()) { - return morphTargets[primitiveIndex].buffer; - } + return mManager[instance].morphTargetBuffer; } return nullptr; } diff --git a/filament/src/components/RenderableManager.h b/filament/src/components/RenderableManager.h index 0fa44c83e77..649d38829d8 100644 --- a/filament/src/components/RenderableManager.h +++ b/filament/src/components/RenderableManager.h @@ -80,12 +80,6 @@ class FRenderableManager : public RenderableManager { static_assert(sizeof(Visibility) == sizeof(uint16_t), "Visibility should be 16 bits"); - struct MorphTargets { - FMorphTargetBuffer* buffer = nullptr; - uint32_t offset = 0; - uint32_t count = 0; - }; - explicit FRenderableManager(FEngine& engine) noexcept; ~FRenderableManager(); @@ -155,11 +149,9 @@ class FRenderableManager : public RenderableManager { inline void setMorphing(Instance instance, bool enable); void setMorphWeights(Instance instance, float const* weights, size_t count, size_t offset); - void setMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex, - FMorphTargetBuffer* morphTargetBuffer, size_t offset, size_t count); - void setMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex, - size_t offset, size_t count); - MorphTargetBuffer* getMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex) const noexcept; + void setMorphTargetBufferOffsetAt(Instance instance, uint8_t level, size_t primitiveIndex, + size_t offset); + MorphTargetBuffer* getMorphTargetBuffer(Instance instance) const noexcept; size_t getMorphTargetCount(Instance instance) const noexcept; void setLightChannel(Instance instance, unsigned int channel, bool enable) noexcept; @@ -189,7 +181,7 @@ class FRenderableManager : public RenderableManager { struct MorphingBindingInfo { backend::Handle handle; uint32_t count; - MorphTargets const* targets; // Pointer to Slice at a renderable. + FMorphTargetBuffer const* morphTargetBuffer; }; inline MorphingBindingInfo getMorphingBufferInfo(Instance instance) const noexcept; @@ -218,16 +210,12 @@ class FRenderableManager : public RenderableManager { AttributeBitset getEnabledAttributesAt(Instance instance, uint8_t level, size_t primitiveIndex) const noexcept; inline utils::Slice const& getRenderPrimitives(Instance instance, uint8_t level) const noexcept; inline utils::Slice& getRenderPrimitives(Instance instance, uint8_t level) noexcept; - inline utils::Slice const& getMorphTargets(Instance instance, uint8_t level) const noexcept; - inline utils::Slice& getMorphTargets(Instance instance, uint8_t level) noexcept; private: void destroyComponent(Instance ci) noexcept; static void destroyComponentPrimitives( HwRenderPrimitiveFactory& factory, backend::DriverApi& driver, utils::Slice& primitives) noexcept; - static void destroyComponentMorphTargets(FEngine& engine, - utils::Slice& morphTargets) noexcept; struct Bones { backend::Handle handle; @@ -254,7 +242,7 @@ class FRenderableManager : public RenderableManager { VISIBILITY, // user data PRIMITIVES, // user data BONES, // filament data, UBO storing a pointer to the bones information - MORPH_TARGETS + MORPHTARGET_BUFFER // morphtarget buffer for the component }; using Base = utils::SingleInstanceComponentManager< @@ -266,7 +254,7 @@ class FRenderableManager : public RenderableManager { Visibility, // VISIBILITY utils::Slice, // PRIMITIVES Bones, // BONES - utils::Slice // MORPH_TARGETS + FMorphTargetBuffer* // MORPHTARGET_BUFFER >; struct Sim : public Base { @@ -289,7 +277,7 @@ class FRenderableManager : public RenderableManager { Field visibility; Field primitives; Field bones; - Field morphTargets; + Field morphTargetBuffer; }; }; @@ -461,8 +449,8 @@ inline uint32_t FRenderableManager::getBoneCount(Instance instance) const noexce FRenderableManager::MorphingBindingInfo FRenderableManager::getMorphingBufferInfo(Instance instance) const noexcept { MorphWeights const& morphWeights = mManager[instance].morphWeights; - utils::Slice const& morphTargets = getMorphTargets(instance, 0); - return { morphWeights.handle, morphWeights.count, morphTargets.data() }; + FMorphTargetBuffer const* const buffer = mManager[instance].morphTargetBuffer; + return { morphWeights.handle, morphWeights.count, buffer }; } FRenderableManager::InstancesInfo @@ -480,16 +468,6 @@ utils::Slice& FRenderableManager::getRenderPrimitives( return mManager[instance].primitives; } -utils::Slice const& FRenderableManager::getMorphTargets( - Instance instance, UTILS_UNUSED uint8_t level) const noexcept { - return mManager[instance].morphTargets; -} - -utils::Slice& FRenderableManager::getMorphTargets( - Instance instance, UTILS_UNUSED uint8_t level) noexcept { - return mManager[instance].morphTargets; -} - } // namespace filament #endif // TNT_FILAMENT_COMPONENTS_RENDERABLEMANAGER_H diff --git a/filament/src/details/MorphTargetBuffer.h b/filament/src/details/MorphTargetBuffer.h index 50e8fc92b92..b1d45b2e2eb 100644 --- a/filament/src/details/MorphTargetBuffer.h +++ b/filament/src/details/MorphTargetBuffer.h @@ -29,7 +29,8 @@ #include -#include +#include +#include namespace filament { @@ -59,16 +60,21 @@ class FMorphTargetBuffer : public MorphTargetBuffer { inline size_t getVertexCount() const noexcept { return mVertexCount; } inline size_t getCount() const noexcept { return mCount; } -private: - friend class FView; - friend class RenderPass; + backend::TextureHandle getPositionsHandle() const noexcept { + return mPbHandle; + } + + backend::TextureHandle getTangentsHandle() const noexcept { + return mTbHandle; + } + + inline backend::Handle getHwHandle() const noexcept { return mSbHandle; } +private: void updateDataAt(backend::DriverApi& driver, backend::Handle handle, backend::PixelDataFormat format, backend::PixelDataType type, const char* out, size_t elementSize, size_t targetIndex, size_t count, size_t offset); - inline backend::Handle getHwHandle() const noexcept { return mSbHandle; } - backend::Handle mSbHandle; backend::Handle mPbHandle; backend::Handle mTbHandle; diff --git a/libs/gltfio/src/AssetLoader.cpp b/libs/gltfio/src/AssetLoader.cpp index 19aa85e3a6a..7a8138392e0 100644 --- a/libs/gltfio/src/AssetLoader.cpp +++ b/libs/gltfio/src/AssetLoader.cpp @@ -650,9 +650,6 @@ void FAssetLoader::createPrimitives(const cgltf_node* node, const char* name, if (outputPrim.indices) { fAsset->mIndexBuffers.push_back(outputPrim.indices); } - if (outputPrim.targets) { - fAsset->mMorphTargetBuffers.push_back(outputPrim.targets); - } } } else { // Create a Filament VertexBuffer and IndexBuffer for this prim if we haven't @@ -695,11 +692,11 @@ void FAssetLoader::createRenderable(const cgltf_node* node, Entity entity, const // glTF spec says that all primitives must have the same number of morph targets. const cgltf_size numMorphTargets = inputPrim ? inputPrim->targets_count : 0; RenderableManager::Builder builder(primitiveCount); - builder.morphing(numMorphTargets); // For each prim, create a Filament VertexBuffer, IndexBuffer, and MaterialInstance. // The VertexBuffer and IndexBuffer objects are cached for possible re-use, but MaterialInstance // is not. + size_t morphingVertexCount = 0; for (cgltf_size index = 0; index < primitiveCount; ++index, ++outputPrim, ++inputPrim) { RenderableManager::PrimitiveType primType; if (!getPrimitiveType(inputPrim->type, &primType)) { @@ -740,8 +737,78 @@ void FAssetLoader::createRenderable(const cgltf_node* node, Entity entity, const builder.geometry(index, primType, outputPrim->vertices, outputPrim->indices); if (numMorphTargets) { - assert_invariant(outputPrim->targets); - builder.morphing(0, index, outputPrim->targets); + outputPrim->morphTargetOffset = morphingVertexCount; // FIXME: can I do that here? + builder.morphing(0, index, morphingVertexCount); + morphingVertexCount += outputPrim->vertices->getVertexCount(); + } + } + + if (numMorphTargets) { + MorphTargetBuffer* morphTargetBuffer = MorphTargetBuffer::Builder() + .count(numMorphTargets) + .vertexCount(morphingVertexCount) + .build(mEngine); + + fAsset->mMorphTargetBuffers.push_back(morphTargetBuffer); + + builder.morphing(morphTargetBuffer); + + outputPrim = prims.data(); + inputPrim = &mesh->primitives[0]; + for (cgltf_size index = 0; index < primitiveCount; ++index, ++outputPrim, ++inputPrim) { + outputPrim->morphTargetBuffer = morphTargetBuffer; + + UTILS_UNUSED_IN_RELEASE cgltf_accessor const* previous = nullptr; + for (int tindex = 0; tindex < numMorphTargets; ++tindex) { + const cgltf_morph_target& inTarget = inputPrim->targets[tindex]; + for (cgltf_size aindex = 0; aindex < inTarget.attributes_count; ++aindex) { + const cgltf_attribute& attribute = inTarget.attributes[aindex]; + const cgltf_accessor* accessor = attribute.data; + const cgltf_attribute_type atype = attribute.type; + if (atype == cgltf_attribute_type_position) { + // All position attributes must have the same number of components. + assert_invariant(!previous || previous->type == accessor->type); + previous = accessor; + + assert_invariant(outputPrim->morphTargetBuffer); + + if (std::holds_alternative( + fAsset->mResourceInfo)) { + using BufferSlot = FFilamentAsset::ResourceInfo::BufferSlot; + auto& slots = std::get( + fAsset->mResourceInfo).mBufferSlots; + BufferSlot& slot = slots[outputPrim->slotIndices[tindex]]; + + assert_invariant(!slot.vertexBuffer); + assert_invariant(!slot.indexBuffer); + + slot.morphTargetBuffer = outputPrim->morphTargetBuffer; + slot.morphTargetOffset = outputPrim->morphTargetOffset; + slot.morphTargetCount = outputPrim->vertices->getVertexCount(); + slot.bufferIndex = tindex; + } + else if (std::holds_alternative( + fAsset->mResourceInfo)) + { + using BufferSlot = FFilamentAsset::ResourceInfoExtended::BufferSlot; + auto& slots = std::get( + fAsset->mResourceInfo).slots; + + BufferSlot& slot = slots[outputPrim->slotIndices[tindex]]; + + assert_invariant(slot.slot == tindex); + assert_invariant(!slot.vertices); + assert_invariant(!slot.indices); + + slot.target = outputPrim->morphTargetBuffer; + slot.offset = outputPrim->morphTargetOffset; + slot.count = outputPrim->vertices->getVertexCount(); + } + + break; + } + } + } } } @@ -753,7 +820,7 @@ void FAssetLoader::createRenderable(const cgltf_node* node, Entity entity, const nm.setMorphTargetNames(nm.getInstance(entity), std::move(morphTargetNames)); if (node->skin) { - builder.skinning(node->skin->joints_count); + builder.skinning(node->skin->joints_count); } // Per the spec, glTF models must have valid mix / max annotations for position attributes. @@ -825,7 +892,7 @@ bool FAssetLoader::createPrimitive(const cgltf_primitive& inPrim, const char* na // request from Google. // Create a little lambda that appends to the asset's vertex buffer slots. - auto slots = &std::get(fAsset->mResourceInfo).mBufferSlots; + auto* const slots = &std::get(fAsset->mResourceInfo).mBufferSlots; auto addBufferSlot = [slots](FFilamentAsset::ResourceInfo::BufferSlot entry) { slots->push_back(entry); }; @@ -1096,13 +1163,8 @@ bool FAssetLoader::createPrimitive(const cgltf_primitive& inPrim, const char* na } if (targetsCount > 0) { - MorphTargetBuffer* targets = MorphTargetBuffer::Builder() - .vertexCount(vertexCount) - .count(targetsCount) - .build(mEngine); - outPrim->targets = targets; - fAsset->mMorphTargetBuffers.push_back(targets); UTILS_UNUSED_IN_RELEASE cgltf_accessor const* previous = nullptr; + outPrim->slotIndices.resize(targetsCount); for (int tindex = 0; tindex < targetsCount; ++tindex) { const cgltf_morph_target& inTarget = inPrim.targets[tindex]; for (cgltf_size aindex = 0; aindex < inTarget.attributes_count; ++aindex) { @@ -1114,8 +1176,7 @@ bool FAssetLoader::createPrimitive(const cgltf_primitive& inPrim, const char* na assert_invariant(!previous || previous->type == accessor->type); previous = accessor; BufferSlot slot = { accessor }; - slot.morphTargetBuffer = targets; - slot.bufferIndex = tindex; + outPrim->slotIndices[tindex] = slots->size(); addBufferSlot(slot); break; } diff --git a/libs/gltfio/src/FFilamentAsset.h b/libs/gltfio/src/FFilamentAsset.h index 6ee6a9d0590..a1401c37ccb 100644 --- a/libs/gltfio/src/FFilamentAsset.h +++ b/libs/gltfio/src/FFilamentAsset.h @@ -96,7 +96,9 @@ struct Primitive { IndexBuffer* indices = nullptr; Aabb aabb; // object-space bounding box UvMap uvmap; // mapping from each glTF UV set to either UV0 or UV1 (8 bytes) - MorphTargetBuffer* targets = nullptr; + MorphTargetBuffer* morphTargetBuffer = nullptr; + uint32_t morphTargetOffset; + std::vector slotIndices; }; using MeshCache = utils::FixedCapacityVector>; @@ -329,6 +331,8 @@ struct FFilamentAsset : public FilamentAsset { VertexBuffer* vertexBuffer; IndexBuffer* indexBuffer; MorphTargetBuffer* morphTargetBuffer; + uint32_t morphTargetOffset; + uint32_t morphTargetCount; }; std::vector mBufferSlots; @@ -343,6 +347,8 @@ struct FFilamentAsset : public FilamentAsset { VertexBuffer* vertices = nullptr; IndexBuffer* indices = nullptr; MorphTargetBuffer* target = nullptr; + uint32_t offset = 0; + uint32_t count = 0; int slot = -1; size_t sizeInBytes = 0; diff --git a/libs/gltfio/src/ResourceLoader.cpp b/libs/gltfio/src/ResourceLoader.cpp index 9b077e94357..6676de31469 100644 --- a/libs/gltfio/src/ResourceLoader.cpp +++ b/libs/gltfio/src/ResourceLoader.cpp @@ -293,10 +293,13 @@ inline void uploadBuffers(FFilamentAsset* asset, Engine& engine, cgltf_accessor_unpack_floats(accessor, floatsData, floatsCount); if (accessor->type == cgltf_type_vec3) { slot.morphTargetBuffer->setPositionsAt(engine, slot.bufferIndex, - (const float3*) floatsData, slot.morphTargetBuffer->getVertexCount()); + (const float3*) floatsData, + slot.morphTargetCount, + slot.morphTargetOffset); } else { slot.morphTargetBuffer->setPositionsAt(engine, slot.bufferIndex, - (const float4*) data, slot.morphTargetBuffer->getVertexCount()); + (const float4*) data, slot.morphTargetBuffer->getVertexCount(), + slot.morphTargetOffset); } free(floatsData); continue; @@ -304,11 +307,13 @@ inline void uploadBuffers(FFilamentAsset* asset, Engine& engine, if (accessor->type == cgltf_type_vec3) { slot.morphTargetBuffer->setPositionsAt(engine, slot.bufferIndex, (const float3*) data, - slot.morphTargetBuffer->getVertexCount()); + slot.morphTargetCount, + slot.morphTargetOffset); } else { assert_invariant(accessor->type == cgltf_type_vec4); slot.morphTargetBuffer->setPositionsAt(engine, slot.bufferIndex, (const float4*) data, - slot.morphTargetBuffer->getVertexCount()); + slot.morphTargetCount, + slot.morphTargetOffset); } } } @@ -694,7 +699,7 @@ void ResourceLoader::Impl::computeTangents(FFilamentAsset* asset) { } auto iter = baseTangents.find(vb); if (iter != baseTangents.end()) { - jobParams.emplace_back(Params {{ prim }, {vb, nullptr, iter->second }}); + jobParams.emplace_back(Params {{ prim }, {vb, nullptr, 0, iter->second }}); } } @@ -707,7 +712,8 @@ void ResourceLoader::Impl::computeTangents(FFilamentAsset* asset) { } for (cgltf_size pindex = 0, pcount = mesh.primitives_count; pindex < pcount; ++pindex) { const cgltf_primitive& prim = mesh.primitives[pindex]; - MorphTargetBuffer* tb = prims[pindex].targets; + MorphTargetBuffer* const tb = prims[pindex].morphTargetBuffer; + uint32_t const morphTargetOffset = prims[pindex].morphTargetOffset; for (cgltf_size tindex = 0, tcount = prim.targets_count; tindex < tcount; ++tindex) { const cgltf_morph_target& target = prim.targets[tindex]; bool hasNormals = false; @@ -719,13 +725,13 @@ void ResourceLoader::Impl::computeTangents(FFilamentAsset* asset) { } hasNormals = true; jobParams.emplace_back(Params { { &prim, (int) tindex }, - { nullptr, tb, (uint8_t) pindex } }); + { nullptr, tb, morphTargetOffset, (uint8_t) pindex } }); break; } // Generate flat normals if necessary. if (!hasNormals && prim.material && !prim.material->unlit) { jobParams.emplace_back(Params { { &prim, (int) tindex }, - { nullptr, tb, (uint8_t) pindex } }); + { nullptr, tb, morphTargetOffset, (uint8_t) pindex } }); } } } @@ -752,7 +758,7 @@ void ResourceLoader::Impl::computeTangents(FFilamentAsset* asset) { } else { assert_invariant(params.context.tb); params.context.tb->setTangentsAt(*mEngine, params.in.morphTargetIndex, - params.out.results, params.out.vertexCount); + params.out.results, params.out.vertexCount, params.context.offset); free(params.out.results); } } diff --git a/libs/gltfio/src/TangentsJob.h b/libs/gltfio/src/TangentsJob.h index 43011e25c58..6aeed1ea3bf 100644 --- a/libs/gltfio/src/TangentsJob.h +++ b/libs/gltfio/src/TangentsJob.h @@ -47,6 +47,7 @@ struct TangentsJob { struct Context { VertexBuffer* const vb; MorphTargetBuffer* const tb; + uint32_t const offset; const uint8_t slot; }; diff --git a/libs/gltfio/src/extended/AssetLoaderExtended.cpp b/libs/gltfio/src/extended/AssetLoaderExtended.cpp index 7cb4fb32309..17a2a672fcc 100644 --- a/libs/gltfio/src/extended/AssetLoaderExtended.cpp +++ b/libs/gltfio/src/extended/AssetLoaderExtended.cpp @@ -288,14 +288,12 @@ std::vector computeGeometries(cgltf_primitive const* prim, uint8_t c } if (!morphTargets.empty()) { + UTILS_UNUSED_IN_RELEASE auto const vertexCount = morphTargetOuts[0].vertexCount; - MorphTargetBuffer* buffer = MorphTargetBuffer::Builder() - .count(morphTargets.size()) - .vertexCount(vertexCount) - .build(*engine); for (auto target: morphTargetOuts) { assert_invariant(target.vertexCount == vertexCount); - slots.push_back({.target = buffer, + slots.push_back({ + .offset = 0xdeadbeef, .slot = target.morphTarget, .targetData = { .tbn = target.tbn, @@ -536,7 +534,10 @@ bool AssetLoaderExtended::createPrimitive(Input* input, Output* out, auto slots = computeGeometries(prim, jobType, attributesMap, morphTargets, out->uvmap, mEngine); - for (auto slot: slots) { + out->slotIndices.resize(morphTargets.size()); + + for (size_t i = 0; i < slots.size(); i++) { + auto& slot = slots[i]; if (slot.vertices) { assert_invariant(!out->vertices || out->vertices == slot.vertices); out->vertices = slot.vertices; @@ -545,9 +546,10 @@ bool AssetLoaderExtended::createPrimitive(Input* input, Output* out, assert_invariant(!out->indices || out->indices == slot.indices); out->indices = slot.indices; } - if (slot.target) { - assert_invariant(!out->targets || out->targets == slot.target); - out->targets = slot.target; + if (slot.offset == 0xdeadbeef) { + // we can't fill this here, unfortunately, so this is done in + // FAssetLoader::createRenderable + out->slotIndices[slot.slot] = outSlots.size() + i; } } diff --git a/libs/gltfio/src/extended/ResourceLoaderExtended.cpp b/libs/gltfio/src/extended/ResourceLoaderExtended.cpp index ae921d6940f..6ce83d8f97e 100644 --- a/libs/gltfio/src/extended/ResourceLoaderExtended.cpp +++ b/libs/gltfio/src/extended/ResourceLoaderExtended.cpp @@ -48,9 +48,10 @@ void ResourceLoaderExtended::loadResources(std::vector const& slots, if (slot.target) { assert_invariant(slot.targetData.positions && slot.targetData.tbn); slot.target->setPositionsAt(*engine, slot.slot, - (float3 const*) slot.targetData.positions, slot.target->getVertexCount()); + (float3 const*) slot.targetData.positions, + slot.count, slot.offset); slot.target->setTangentsAt(*engine, slot.slot, (short4 const*) slot.targetData.tbn, - slot.target->getVertexCount()); + slot.count, slot.offset); free(slot.targetData.positions); free(slot.targetData.tbn); diff --git a/libs/gltfio/test/gltfio_test.cpp b/libs/gltfio/test/gltfio_test.cpp index 44b7d99e223..239edbaae09 100644 --- a/libs/gltfio/test/gltfio_test.cpp +++ b/libs/gltfio/test/gltfio_test.cpp @@ -228,7 +228,7 @@ TEST_F(glTFIOTest, AnimatedMorphCubeRenderables) { EXPECT_EQ(renderableManager.getMorphTargetCount(inst), 2u); // The 0-th MorphTargetBuffer holds both of the targets - auto const morphTargetBuffer = renderableManager.getMorphTargetBufferAt(inst, 0, 0); + auto const morphTargetBuffer = renderableManager.getMorphTargetBuffer(inst); EXPECT_EQ(morphTargetBuffer->getCount(), 2u); // The number of vertices for the morph target should be the face vertices in a cube => diff --git a/samples/hellomorphing.cpp b/samples/hellomorphing.cpp index 6bd418cf43c..54ce244984f 100644 --- a/samples/hellomorphing.cpp +++ b/samples/hellomorphing.cpp @@ -202,9 +202,9 @@ int main(int argc, char** argv) { .culling(false) .receiveShadows(false) .castShadows(false) - .morphing(3) - .morphing(0,0,app.mt1, 0, app.mt1->getCount()) - .morphing(0,1,app.mt1, 9, app.mt1->getCount()) + .morphing(app.mt1) + .morphing(0, 0, 0) + .morphing(0, 1, 9) .build(*engine, app.renderable); scene->addEntity(app.renderable); diff --git a/samples/skinningtest.cpp b/samples/skinningtest.cpp index 8ae6d3f9664..a2da0b1b5b5 100644 --- a/samples/skinningtest.cpp +++ b/samples/skinningtest.cpp @@ -511,26 +511,27 @@ int main(int argc, char** argv) { // primitive 2 = triangle, no skinning, no morph target, buffer objects enabled // primitive 3 = triangle, no skinning, morph target, buffer objects enabled app.renderables[0] = EntityManager::get().create(); - RenderableManager::Builder(4) - .boundingBox({{ -1, -1, -1}, { 1, 1, 1}}) - .material(0, app.mat->getDefaultInstance()) - .material(1, app.mat->getDefaultInstance()) - .material(2, app.mat->getDefaultInstance()) - .material(3, app.mat->getDefaultInstance()) - .geometry(0,RenderableManager::PrimitiveType::TRIANGLES, - app.vbs[0],app.ib,0,3) - .geometry(1,RenderableManager::PrimitiveType::TRIANGLES, - app.vbs[0],app.ib,0,3) - .geometry(2,RenderableManager::PrimitiveType::TRIANGLES, - app.vbs[1],app.ib,0,3) - .geometry(3,RenderableManager::PrimitiveType::TRIANGLES, - app.vbs[1],app.ib,0,3) - .culling(false) - .receiveShadows(false) - .castShadows(false) - .morphing(3) - .morphing(0,1,app.mt) - .morphing(0,3,app.mt) + RenderableManager::Builder(4) + .boundingBox({{ -1, -1, -1 }, + { 1, 1, 1 }}) + .material(0, app.mat->getDefaultInstance()) + .material(1, app.mat->getDefaultInstance()) + .material(2, app.mat->getDefaultInstance()) + .material(3, app.mat->getDefaultInstance()) + .geometry(0, RenderableManager::PrimitiveType::TRIANGLES, + app.vbs[0], app.ib, 0, 3) + .geometry(1, RenderableManager::PrimitiveType::TRIANGLES, + app.vbs[0], app.ib, 0, 3) + .geometry(2, RenderableManager::PrimitiveType::TRIANGLES, + app.vbs[1], app.ib, 0, 3) + .geometry(3, RenderableManager::PrimitiveType::TRIANGLES, + app.vbs[1], app.ib, 0, 3) + .culling(false) + .receiveShadows(false) + .castShadows(false) + .morphing(app.mt) + .morphing(0, 1, 0) + .morphing(0, 3, 0) .build(*engine, app.renderables[0]); // renderable 1: attribute bone data definitions skinning @@ -539,28 +540,29 @@ int main(int argc, char** argv) { // primitive 3 = triangle with skinning, bone data defined as vertex attributes (buffer object) // primitive 2 = triangle with skinning and with morphing, bone data defined as vertex attributes app.renderables[1] = EntityManager::get().create(); - RenderableManager::Builder(4) - .boundingBox({{ -1, -1, -1}, { 1, 1, 1}}) - .material(0, app.mat->getDefaultInstance()) - .material(1, app.mat->getDefaultInstance()) - .material(2, app.mat->getDefaultInstance()) - .material(3, app.mat->getDefaultInstance()) - .geometry(1,RenderableManager::PrimitiveType::TRIANGLES, - app.vbs[2],app.ib,0,3) - .geometry(2,RenderableManager::PrimitiveType::TRIANGLES, - app.vbs[2],app.ib,0,3) - .geometry(0,RenderableManager::PrimitiveType::TRIANGLES, - app.vbs[3],app.ib,0,3) - .geometry(3,RenderableManager::PrimitiveType::TRIANGLES, - app.vbs[3],app.ib,0,3) - .culling(false) - .receiveShadows(false) - .castShadows(false) - .enableSkinningBuffers(true) - .skinning(app.sb, 9, 0) - .morphing(3) - .morphing(0,2,app.mt) - .morphing(0,0,app.mt) + RenderableManager::Builder(4) + .boundingBox({{ -1, -1, -1 }, + { 1, 1, 1 }}) + .material(0, app.mat->getDefaultInstance()) + .material(1, app.mat->getDefaultInstance()) + .material(2, app.mat->getDefaultInstance()) + .material(3, app.mat->getDefaultInstance()) + .geometry(1, RenderableManager::PrimitiveType::TRIANGLES, + app.vbs[2], app.ib, 0, 3) + .geometry(2, RenderableManager::PrimitiveType::TRIANGLES, + app.vbs[2], app.ib, 0, 3) + .geometry(0, RenderableManager::PrimitiveType::TRIANGLES, + app.vbs[3], app.ib, 0, 3) + .geometry(3, RenderableManager::PrimitiveType::TRIANGLES, + app.vbs[3], app.ib, 0, 3) + .culling(false) + .receiveShadows(false) + .castShadows(false) + .enableSkinningBuffers(true) + .skinning(app.sb, 9, 0) + .morphing(app.mt) + .morphing(0, 2, 0) + .morphing(0, 0, 0) .build(*engine, app.renderables[1]); // renderable 2: various ways of skinning definitions @@ -569,30 +571,31 @@ int main(int argc, char** argv) { // primitive 2 = triangle with skinning and with morphing, advanced bone data // defined as vector per primitive app.renderables[2] = EntityManager::get().create(); - RenderableManager::Builder(3) - .boundingBox({{ -1, -1, -1}, { 1, 1, 1}}) - .material(0, app.mat->getDefaultInstance()) - .material(1, app.mat->getDefaultInstance()) - .material(2, app.mat->getDefaultInstance()) - .geometry(0,RenderableManager::PrimitiveType::TRIANGLES, - app.vbs[4], app.ib, 0, 3) - .geometry(1,RenderableManager::PrimitiveType::TRIANGLES, - app.vbs[5], app.ib, 0, 3) - .geometry(2,RenderableManager::PrimitiveType::TRIANGLES, - app.vbs[6], app.ib, 0, 3) - .culling(false) - .receiveShadows(false) - .castShadows(false) - .enableSkinningBuffers(true) - .skinning(app.sb, 9, 0) - - .boneIndicesAndWeights(0, boneDataArray, - 3 * app.bonesPerVertex, app.bonesPerVertex) - .boneIndicesAndWeights(1, app.boneDataPerPrimitive) - .boneIndicesAndWeights(2, app.boneDataPerPrimitive) - - .morphing(3) - .morphing(0, 2, app.mt) + RenderableManager::Builder(3) + .boundingBox({{ -1, -1, -1 }, + { 1, 1, 1 }}) + .material(0, app.mat->getDefaultInstance()) + .material(1, app.mat->getDefaultInstance()) + .material(2, app.mat->getDefaultInstance()) + .geometry(0, RenderableManager::PrimitiveType::TRIANGLES, + app.vbs[4], app.ib, 0, 3) + .geometry(1, RenderableManager::PrimitiveType::TRIANGLES, + app.vbs[5], app.ib, 0, 3) + .geometry(2, RenderableManager::PrimitiveType::TRIANGLES, + app.vbs[6], app.ib, 0, 3) + .culling(false) + .receiveShadows(false) + .castShadows(false) + .enableSkinningBuffers(true) + .skinning(app.sb, 9, 0) + + .boneIndicesAndWeights(0, boneDataArray, + 3 * app.bonesPerVertex, app.bonesPerVertex) + .boneIndicesAndWeights(1, app.boneDataPerPrimitive) + .boneIndicesAndWeights(2, app.boneDataPerPrimitive) + + .morphing(app.mt) + .morphing(0, 2, 0) .build(*engine, app.renderables[2]); // renderable 3: combination attribute and advance bone data @@ -602,27 +605,28 @@ int main(int argc, char** argv) { // primitive 2 = triangle with skinning and morphing, advanced bone data defined // as vector per primitive app.renderables[3] = EntityManager::get().create(); - RenderableManager::Builder(3) - .boundingBox({{ -1, -1, -1}, { 1, 1, 1}}) - .material(0, app.mat->getDefaultInstance()) - .material(1, app.mat->getDefaultInstance()) - .material(2, app.mat->getDefaultInstance()) - .geometry(0,RenderableManager::PrimitiveType::TRIANGLES, - app.vbs[2], app.ib, 0, 3) - .geometry(1,RenderableManager::PrimitiveType::TRIANGLES, - app.vbs[7], app.ib2, 0, 6) - .geometry(2,RenderableManager::PrimitiveType::TRIANGLES, - app.vbs[8], app.ib, 0, 3) - .culling(false) - .receiveShadows(false) - .castShadows(false) - .enableSkinningBuffers(true) - .skinning(app.sb, 9, 0) - .boneIndicesAndWeights(1, app.boneDataPerPrimitiveMulti) - .boneIndicesAndWeights(2, app.boneDataPerPrimitive) - .morphing(3) - .morphing(0,0,app.mt) - .morphing(0,2,app.mt) + RenderableManager::Builder(3) + .boundingBox({{ -1, -1, -1 }, + { 1, 1, 1 }}) + .material(0, app.mat->getDefaultInstance()) + .material(1, app.mat->getDefaultInstance()) + .material(2, app.mat->getDefaultInstance()) + .geometry(0, RenderableManager::PrimitiveType::TRIANGLES, + app.vbs[2], app.ib, 0, 3) + .geometry(1, RenderableManager::PrimitiveType::TRIANGLES, + app.vbs[7], app.ib2, 0, 6) + .geometry(2, RenderableManager::PrimitiveType::TRIANGLES, + app.vbs[8], app.ib, 0, 3) + .culling(false) + .receiveShadows(false) + .castShadows(false) + .enableSkinningBuffers(true) + .skinning(app.sb, 9, 0) + .boneIndicesAndWeights(1, app.boneDataPerPrimitiveMulti) + .boneIndicesAndWeights(2, app.boneDataPerPrimitive) + .morphing(app.mt) + .morphing(0, 0, 0) + .morphing(0, 2, 0) .build(*engine, app.renderables[3]); scene->addEntity(app.renderables[0]);