From f7a5111106dc336234e57cf570ab1bf446dbc896 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 | 174 +++++++++--------- 19 files changed, 284 insertions(+), 356 deletions(-) diff --git a/android/filament-android/src/main/cpp/RenderableManager.cpp b/android/filament-android/src/main/cpp/RenderableManager.cpp index db0255d414..4f38e46f82 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 f82ca4780b..619870d372 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 class MorphTargetBuffer { * * @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 dfce1af4a1..0da9a0d6e7 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 class RenderableManager { * * @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 class RenderableManager { * * @see Builder#morphing */ - public void setMorphTargetBufferAt(@EntityInstance int i, + public void setMorphTargetBufferOffsetAt(@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, - @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 class RenderableManager { 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 class RenderableManager { 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 363ef2d7c1..2c227e0c64 100644 --- a/filament/include/filament/RenderableManager.h +++ b/filament/include/filament/RenderableManager.h @@ -489,43 +489,20 @@ public: * 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 @@ public: /** * 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 ee5092370d..cc892b910d 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 07d7431f02..a8600dd3a6 100644 --- a/filament/src/RenderPrimitive.h +++ b/filament/src/RenderPrimitive.h @@ -56,6 +56,7 @@ public: 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 @@ public: 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 @@ private: 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 9550197acf..87ea0d0e46 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 596cd8e7fe..cdadc4e35e 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) { +void FRenderableManager::setMorphTargetBufferOffsetAt(Instance instance, uint8_t level, + size_t primitiveIndex, + size_t offset) { 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 }; + assert_invariant(mManager[instance].morphTargetBuffer); + Slice& primitives = mManager[instance].primitives; + if (primitiveIndex < primitives.size()) { + primitives[primitiveIndex].setMorphingBufferOffset(offset); } } } -void FRenderableManager::setMorphTargetBufferAt(Instance instance, uint8_t level, - size_t primitiveIndex, size_t offset, size_t count) { +MorphTargetBuffer* FRenderableManager::getMorphTargetBuffer(Instance instance) const noexcept { if (instance) { - Slice& morphTargets = getMorphTargets(instance, level); - if (primitiveIndex < morphTargets.size()) { - setMorphTargetBufferAt(instance, level, - primitiveIndex, morphTargets[primitiveIndex].buffer, offset, count); - } - } -} - -MorphTargetBuffer* FRenderableManager::getMorphTargetBufferAt(Instance instance, uint8_t level, - size_t primitiveIndex) 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 0fa44c83e7..649d38829d 100644 --- a/filament/src/components/RenderableManager.h +++ b/filament/src/components/RenderableManager.h @@ -80,12 +80,6 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ private: 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 @@ private: Visibility, // VISIBILITY utils::Slice, // PRIMITIVES Bones, // BONES - utils::Slice // MORPH_TARGETS + FMorphTargetBuffer* // MORPHTARGET_BUFFER >; struct Sim : public Base { @@ -289,7 +277,7 @@ private: 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 50e8fc92b9..b1d45b2e2e 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 @@ public: 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 19aa85e3a6..7a8138392e 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 6ee6a9d059..a1401c37cc 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 9b077e9435..6676de3146 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 43011e25c5..6aeed1ea3b 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 7cb4fb3230..17a2a672fc 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 ae921d6940..6ce83d8f97 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 44b7d99e22..239edbaae0 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 6bd418cf43..54ce244984 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 8ae6d3f966..a2da0b1b5b 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) + 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) + .boneIndicesAndWeights(0, boneDataArray, + 3 * app.bonesPerVertex, app.bonesPerVertex) + .boneIndicesAndWeights(1, app.boneDataPerPrimitive) + .boneIndicesAndWeights(2, app.boneDataPerPrimitive) - .morphing(3) - .morphing(0, 2, app.mt) + .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]);