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]);