From 042439a72b08864cb2c518d95e3c45fc71e26390 Mon Sep 17 00:00:00 2001 From: Nick Fisher Date: Sat, 19 Aug 2023 13:52:57 +0800 Subject: [PATCH] add method for setting material color --- example/lib/main.dart | 3 + ios/Classes/SwiftPolyvoxFilamentPlugin.swift | 13 +- ios/include/AssetManager.hpp | 1 + ios/include/PolyvoxFilamentApi.h | 1 + ios/src/AssetManager.cpp | 1536 +++++++++--------- ios/src/PolyvoxFilamentApi.cpp | 4 + lib/filament_controller.dart | 19 +- 7 files changed, 823 insertions(+), 754 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 205a38fe..44b35fae 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -218,6 +218,9 @@ class _ExampleWidgetState extends State { .build(); _filamentController.setMorphAnimationData(_cube!, animation); }, "animate morph weights #3 and #4"), + _item(() { + _filamentController.setMaterialColor(_cube!, "Cone", 0, Colors.purple); + }, "set cone material color to purple") ]; if (_animations != null) { children.addAll(_animations!.map((a) => _item(() { diff --git a/ios/Classes/SwiftPolyvoxFilamentPlugin.swift b/ios/Classes/SwiftPolyvoxFilamentPlugin.swift index 9757bdb7..e57e03c8 100644 --- a/ios/Classes/SwiftPolyvoxFilamentPlugin.swift +++ b/ios/Classes/SwiftPolyvoxFilamentPlugin.swift @@ -615,7 +615,18 @@ public class SwiftPolyvoxFilamentPlugin: NSObject, FlutterPlugin, FlutterTexture case "setCameraFocusDistance": set_camera_focus_distance(viewer, call.arguments as! Float) result(true) - + case "setMaterialColor": + guard let args = call.arguments as? [Any], args.count == 5, + let assetManager = args[0] as? Int64, + let asset = args[1] as? EntityId, + let meshName = args[2] as? String, + let materialIndex = args[3] as? Int32, + let color = args[4] as? [Double] else { + result(FlutterError(code: "INVALID_ARGUMENTS", message: "Expected correct arguments for setMaterialColor", details: nil)) + return + } + set_material_color(unsafeBitCast(assetManager, to:UnsafeMutableRawPointer.self), asset, meshName, materialIndex, Float(color[0]), Float(color[1]), Float(color[2]), Float(color[3])) + result(true) case "hideMesh": guard let args = call.arguments as? [Any], args.count == 3, diff --git a/ios/include/AssetManager.hpp b/ios/include/AssetManager.hpp index ae20a260..a446a511 100644 --- a/ios/include/AssetManager.hpp +++ b/ios/include/AssetManager.hpp @@ -40,6 +40,7 @@ namespace polyvox { const utils::Entity* getLightEntities(EntityId e) const noexcept; size_t getLightEntityCount(EntityId e) const noexcept; void updateAnimations(); + bool setMaterialColor(EntityId e, const char* meshName, int materialInstance, const float r, const float g, const float b, const float a); bool setMorphAnimationBuffer( EntityId entityId, diff --git a/ios/include/PolyvoxFilamentApi.h b/ios/include/PolyvoxFilamentApi.h index 06a248b5..93363ef4 100644 --- a/ios/include/PolyvoxFilamentApi.h +++ b/ios/include/PolyvoxFilamentApi.h @@ -82,6 +82,7 @@ void remove_asset(const void* const viewer, EntityId asset); void clear_assets(const void* const viewer); void load_texture(void* assetManager, EntityId asset, const char *assetPath, int renderableIndex); void set_texture(void* assetManager, EntityId asset); +bool set_material_color(void* assetManager, EntityId asset, const char* meshName, int materialIndex, const float r, const float g, const float b, const float a); void transform_to_unit_cube(void* assetManager, EntityId asset); void set_position(void* assetManager, EntityId asset, float x, float y, float z); void set_rotation(void* assetManager, EntityId asset, float rads, float x, float y, float z); diff --git a/ios/src/AssetManager.cpp b/ios/src/AssetManager.cpp index 34e7963e..642a2264 100644 --- a/ios/src/AssetManager.cpp +++ b/ios/src/AssetManager.cpp @@ -24,8 +24,8 @@ #include "gltfio/materials/uberarchive.h" extern "C" { - #include "material/image.h" - #include "material/unlit_opaque.h" +#include "material/image.h" +#include "material/unlit_opaque.h" } namespace polyvox { @@ -38,835 +38,869 @@ using namespace filament; using namespace filament::gltfio; AssetManager::AssetManager(const ResourceLoaderWrapper* const resourceLoaderWrapper, - NameComponentManager *ncm, - Engine *engine, - Scene *scene) - : _resourceLoaderWrapper(resourceLoaderWrapper), - _ncm(ncm), - _engine(engine), - _scene(scene) { - - _stbDecoder = createStbProvider(_engine); - _ktxDecoder = createKtx2Provider(_engine); - - _gltfResourceLoader = new ResourceLoader({.engine = _engine, - .normalizeSkinningWeights = true }); - _ubershaderProvider = gltfio::createUbershaderProvider( - _engine, UBERARCHIVE_DEFAULT_DATA, UBERARCHIVE_DEFAULT_SIZE); - EntityManager &em = EntityManager::get(); - - //_unlitProvider = new UnlitMaterialProvider(_engine); - - // auto rb = _resourceLoaderWrapper->load("file:///mnt/hdd_2tb/home/hydroxide/projects/polyvox/flutter/polyvox_filament/materials/toon.filamat"); - // auto toonProvider = new FileMaterialProvider(_engine, rb.data, (size_t) rb.size); - - _assetLoader = AssetLoader::create({_engine, _ubershaderProvider, _ncm, &em }); - _gltfResourceLoader->addTextureProvider("image/ktx2", _ktxDecoder); - _gltfResourceLoader->addTextureProvider("image/png", _stbDecoder); - _gltfResourceLoader->addTextureProvider("image/jpeg", _stbDecoder); - } + NameComponentManager *ncm, + Engine *engine, + Scene *scene) +: _resourceLoaderWrapper(resourceLoaderWrapper), +_ncm(ncm), +_engine(engine), +_scene(scene) { + + _stbDecoder = createStbProvider(_engine); + _ktxDecoder = createKtx2Provider(_engine); + + _gltfResourceLoader = new ResourceLoader({.engine = _engine, + .normalizeSkinningWeights = true }); + _ubershaderProvider = gltfio::createUbershaderProvider( + _engine, UBERARCHIVE_DEFAULT_DATA, UBERARCHIVE_DEFAULT_SIZE); + EntityManager &em = EntityManager::get(); + + //_unlitProvider = new UnlitMaterialProvider(_engine); + + // auto rb = _resourceLoaderWrapper->load("file:///mnt/hdd_2tb/home/hydroxide/projects/polyvox/flutter/polyvox_filament/materials/toon.filamat"); + // auto toonProvider = new FileMaterialProvider(_engine, rb.data, (size_t) rb.size); + + _assetLoader = AssetLoader::create({_engine, _ubershaderProvider, _ncm, &em }); + _gltfResourceLoader->addTextureProvider("image/ktx2", _ktxDecoder); + _gltfResourceLoader->addTextureProvider("image/png", _stbDecoder); + _gltfResourceLoader->addTextureProvider("image/jpeg", _stbDecoder); +} AssetManager::~AssetManager() { - _gltfResourceLoader->asyncCancelLoad(); - _ubershaderProvider->destroyMaterials(); - //_unlitProvider->destroyMaterials(); - destroyAll(); - AssetLoader::destroy(&_assetLoader); - + _gltfResourceLoader->asyncCancelLoad(); + _ubershaderProvider->destroyMaterials(); + //_unlitProvider->destroyMaterials(); + destroyAll(); + AssetLoader::destroy(&_assetLoader); + } EntityId AssetManager::loadGltf(const char *uri, - const char *relativeResourcePath) { - ResourceBuffer rbuf = _resourceLoaderWrapper->load(uri); - - // Parse the glTF file and create Filament entities. - FilamentAsset *asset = - _assetLoader->createAsset((uint8_t *)rbuf.data, rbuf.size); - - if (!asset) { - Log("Unable to parse asset"); - return 0; - } - - const char *const *const resourceUris = asset->getResourceUris(); - const size_t resourceUriCount = asset->getResourceUriCount(); - - for (size_t i = 0; i < resourceUriCount; i++) { - string uri = + const char *relativeResourcePath) { + ResourceBuffer rbuf = _resourceLoaderWrapper->load(uri); + + // Parse the glTF file and create Filament entities. + FilamentAsset *asset = + _assetLoader->createAsset((uint8_t *)rbuf.data, rbuf.size); + + if (!asset) { + Log("Unable to parse asset"); + return 0; + } + + const char *const *const resourceUris = asset->getResourceUris(); + const size_t resourceUriCount = asset->getResourceUriCount(); + + for (size_t i = 0; i < resourceUriCount; i++) { + string uri = string(relativeResourcePath) + string("/") + string(resourceUris[i]); - ResourceBuffer buf = _resourceLoaderWrapper->load(uri.c_str()); - - ResourceLoader::BufferDescriptor b(buf.data, buf.size); - _gltfResourceLoader->addResourceData(resourceUris[i], std::move(b)); - _resourceLoaderWrapper->free(buf); - } - - _gltfResourceLoader->loadResources(asset); - const utils::Entity *entities = asset->getEntities(); - RenderableManager &rm = _engine->getRenderableManager(); - for (int i = 0; i < asset->getEntityCount(); i++) { - auto inst = rm.getInstance(entities[i]); - rm.setCulling(inst, false); - } - - FilamentInstance* inst = asset->getInstance(); - inst->getAnimator()->updateBoneMatrices(); - inst->recomputeBoundingBoxes(); - - _scene->addEntities(asset->getEntities(), asset->getEntityCount()); - - asset->releaseSourceData(); - - Log("Load complete for GLTF at URI %s", uri); - SceneAsset sceneAsset(asset); - - - utils::Entity e = EntityManager::get().create(); - - EntityId eid = Entity::smuggle(e); - - _entityIdLookup.emplace(eid, _assets.size()); - _assets.push_back(sceneAsset); - - return eid; + ResourceBuffer buf = _resourceLoaderWrapper->load(uri.c_str()); + + ResourceLoader::BufferDescriptor b(buf.data, buf.size); + _gltfResourceLoader->addResourceData(resourceUris[i], std::move(b)); + _resourceLoaderWrapper->free(buf); + } + + _gltfResourceLoader->loadResources(asset); + const utils::Entity *entities = asset->getEntities(); + RenderableManager &rm = _engine->getRenderableManager(); + for (int i = 0; i < asset->getEntityCount(); i++) { + auto inst = rm.getInstance(entities[i]); + rm.setCulling(inst, false); + } + + FilamentInstance* inst = asset->getInstance(); + inst->getAnimator()->updateBoneMatrices(); + inst->recomputeBoundingBoxes(); + + _scene->addEntities(asset->getEntities(), asset->getEntityCount()); + + asset->releaseSourceData(); + + Log("Load complete for GLTF at URI %s", uri); + SceneAsset sceneAsset(asset); + + + utils::Entity e = EntityManager::get().create(); + + EntityId eid = Entity::smuggle(e); + + _entityIdLookup.emplace(eid, _assets.size()); + _assets.push_back(sceneAsset); + + return eid; } EntityId AssetManager::loadGlb(const char *uri, bool unlit) { - - Log("Loading GLB at URI %s", uri); - - ResourceBuffer rbuf = _resourceLoaderWrapper->load(uri); - - FilamentAsset *asset = _assetLoader->createAsset( - (const uint8_t *)rbuf.data, rbuf.size); - - if (!asset) { - Log("Unknown error loading GLB asset."); - return 0; - } - - int entityCount = asset->getEntityCount(); - - _scene->addEntities(asset->getEntities(), entityCount); - - _gltfResourceLoader->loadResources(asset); - - const Entity *entities = asset->getEntities(); - - auto lights = asset->getLightEntities(); - _scene->addEntities(lights, asset->getLightEntityCount()); - - FilamentInstance* inst = asset->getInstance(); - - inst->getAnimator()->updateBoneMatrices(); - - inst->recomputeBoundingBoxes(); - - asset->releaseSourceData(); - - _resourceLoaderWrapper->free(rbuf); - - SceneAsset sceneAsset(asset); - - utils::Entity e = EntityManager::get().create(); - EntityId eid = Entity::smuggle(e); - - _entityIdLookup.emplace(eid, _assets.size()); - _assets.push_back(sceneAsset); - - return eid; + + Log("Loading GLB at URI %s", uri); + + ResourceBuffer rbuf = _resourceLoaderWrapper->load(uri); + + FilamentAsset *asset = _assetLoader->createAsset( + (const uint8_t *)rbuf.data, rbuf.size); + + if (!asset) { + Log("Unknown error loading GLB asset."); + return 0; + } + + int entityCount = asset->getEntityCount(); + + _scene->addEntities(asset->getEntities(), entityCount); + + _gltfResourceLoader->loadResources(asset); + + const Entity *entities = asset->getEntities(); + + auto lights = asset->getLightEntities(); + _scene->addEntities(lights, asset->getLightEntityCount()); + + FilamentInstance* inst = asset->getInstance(); + + inst->getAnimator()->updateBoneMatrices(); + + inst->recomputeBoundingBoxes(); + + asset->releaseSourceData(); + + _resourceLoaderWrapper->free(rbuf); + + SceneAsset sceneAsset(asset); + + utils::Entity e = EntityManager::get().create(); + EntityId eid = Entity::smuggle(e); + + _entityIdLookup.emplace(eid, _assets.size()); + _assets.push_back(sceneAsset); + + return eid; } bool AssetManager::hide(EntityId entityId, const char* meshName) { - - auto asset = getAssetByEntityId(entityId); - if(!asset) { - return false; - } - - auto entity = findEntityByName(asset, meshName); - - if(entity.isNull()) { - Log("Mesh %s could not be found", meshName); - return false; - } - _scene->remove(entity); - return true; + + auto asset = getAssetByEntityId(entityId); + if(!asset) { + return false; + } + + auto entity = findEntityByName(asset, meshName); + + if(entity.isNull()) { + Log("Mesh %s could not be found", meshName); + return false; + } + _scene->remove(entity); + return true; } bool AssetManager::reveal(EntityId entityId, const char* meshName) { - auto asset = getAssetByEntityId(entityId); - if(!asset) { - Log("No asset found under entity ID"); - return false; - } - - auto entity = findEntityByName(asset, meshName); - - RenderableManager &rm = _engine->getRenderableManager(); - - if(entity.isNull()) { - Log("Mesh %s could not be found", meshName); - return false; - } - _scene->addEntity(entity); - return true; + auto asset = getAssetByEntityId(entityId); + if(!asset) { + Log("No asset found under entity ID"); + return false; + } + + auto entity = findEntityByName(asset, meshName); + + RenderableManager &rm = _engine->getRenderableManager(); + + if(entity.isNull()) { + Log("Mesh %s could not be found", meshName); + return false; + } + _scene->addEntity(entity); + return true; } void AssetManager::destroyAll() { - for (auto& asset : _assets) { - _scene->removeEntities(asset.mAsset->getEntities(), - asset.mAsset->getEntityCount()); - - _scene->removeEntities(asset.mAsset->getLightEntities(), - asset.mAsset->getLightEntityCount()); - - _gltfResourceLoader->evictResourceData(); - _assetLoader->destroyAsset(asset.mAsset); - } - _assets.clear(); + for (auto& asset : _assets) { + _scene->removeEntities(asset.mAsset->getEntities(), + asset.mAsset->getEntityCount()); + + _scene->removeEntities(asset.mAsset->getLightEntities(), + asset.mAsset->getLightEntityCount()); + + _gltfResourceLoader->evictResourceData(); + _assetLoader->destroyAsset(asset.mAsset); + } + _assets.clear(); } FilamentAsset* AssetManager::getAssetByEntityId(EntityId entityId) { - const auto& pos = _entityIdLookup.find(entityId); - if(pos == _entityIdLookup.end()) { - return nullptr; - } - return _assets[pos->second].mAsset; + const auto& pos = _entityIdLookup.find(entityId); + if(pos == _entityIdLookup.end()) { + return nullptr; + } + return _assets[pos->second].mAsset; } void AssetManager::updateAnimations() { - - auto now = high_resolution_clock::now(); - - RenderableManager &rm = _engine->getRenderableManager(); - - for (auto& asset : _assets) { - vector completed; - for(auto& anim : asset.mAnimations) { - - auto elapsed = float(std::chrono::duration_cast(now - anim.mStart).count()) / 1000.0f; - - if(anim.mLoop || elapsed < anim.mDuration) { - - switch(anim.type) { - case AnimationType::GLTF: { - asset.mAnimator->applyAnimation(anim.gltfIndex, elapsed); - if(asset.fadeGltfAnimationIndex != -1 && elapsed < asset.fadeDuration) { - // cross-fade - auto fadeFromTime = asset.fadeOutAnimationStart + elapsed; - auto alpha = elapsed / asset.fadeDuration; - asset.mAnimator->applyCrossFade(asset.fadeGltfAnimationIndex, fadeFromTime, alpha); - } - break; - } - case AnimationType::MORPH: { - int lengthInFrames = static_cast( - anim.mDuration * 1000.0f / - asset.mMorphAnimationBuffer.mFrameLengthInMs - ); - int frameNumber = static_cast(elapsed * 1000.0f / asset.mMorphAnimationBuffer.mFrameLengthInMs) % lengthInFrames; - // offset from the end if reverse - if(anim.mReverse) { - frameNumber = lengthInFrames - frameNumber; - } - auto baseOffset = frameNumber * asset.mMorphAnimationBuffer.mMorphIndices.size(); - for(auto morphIndex : asset.mMorphAnimationBuffer.mMorphIndices) { - // set the weights appropriately - rm.setMorphWeights( - rm.getInstance(asset.mMorphAnimationBuffer.mMeshTarget), - asset.mMorphAnimationBuffer.mFrameData.data() + baseOffset + morphIndex, - 1, - morphIndex - ); - } - break; - } - case AnimationType::BONE: { - int lengthInFrames = static_cast( - anim.mDuration * 1000.0f / - asset.mBoneAnimationBuffer.mFrameLengthInMs - ); - int frameNumber = static_cast(elapsed * 1000.0f / asset.mBoneAnimationBuffer.mFrameLengthInMs) % lengthInFrames; + auto now = high_resolution_clock::now(); + + RenderableManager &rm = _engine->getRenderableManager(); + + for (auto& asset : _assets) { + + vector completed; + for(auto& anim : asset.mAnimations) { + + auto elapsed = float(std::chrono::duration_cast(now - anim.mStart).count()) / 1000.0f; + + if(anim.mLoop || elapsed < anim.mDuration) { - // offset from the end if reverse - if(anim.mReverse) { - frameNumber = lengthInFrames - frameNumber; + switch(anim.type) { + case AnimationType::GLTF: { + asset.mAnimator->applyAnimation(anim.gltfIndex, elapsed); + if(asset.fadeGltfAnimationIndex != -1 && elapsed < asset.fadeDuration) { + // cross-fade + auto fadeFromTime = asset.fadeOutAnimationStart + elapsed; + auto alpha = elapsed / asset.fadeDuration; + asset.mAnimator->applyCrossFade(asset.fadeGltfAnimationIndex, fadeFromTime, alpha); + } + break; + } + case AnimationType::MORPH: { + int lengthInFrames = static_cast( + anim.mDuration * 1000.0f / + asset.mMorphAnimationBuffer.mFrameLengthInMs + ); + int frameNumber = static_cast(elapsed * 1000.0f / asset.mMorphAnimationBuffer.mFrameLengthInMs) % lengthInFrames; + // offset from the end if reverse + if(anim.mReverse) { + frameNumber = lengthInFrames - frameNumber; + } + auto baseOffset = frameNumber * asset.mMorphAnimationBuffer.mMorphIndices.size(); + for(int i = 0; i < asset.mMorphAnimationBuffer.mMorphIndices.size(); i++) { + auto morphIndex = asset.mMorphAnimationBuffer.mMorphIndices[i]; + // set the weights appropriately + rm.setMorphWeights( + rm.getInstance(asset.mMorphAnimationBuffer.mMeshTarget), + asset.mMorphAnimationBuffer.mFrameData.data() + baseOffset + i, + 1, + morphIndex + ); + } + break; + } + case AnimationType::BONE: { + int lengthInFrames = static_cast( + anim.mDuration * 1000.0f / + asset.mBoneAnimationBuffer.mFrameLengthInMs + ); + int frameNumber = static_cast(elapsed * 1000.0f / asset.mBoneAnimationBuffer.mFrameLengthInMs) % lengthInFrames; + + // offset from the end if reverse + if(anim.mReverse) { + frameNumber = lengthInFrames - frameNumber; + } + setBoneTransform( + asset, + frameNumber + ); + break; + } } - setBoneTransform( - asset, - frameNumber - ); - break; + // animation has completed + } else { + completed.push_back(anim); + asset.fadeGltfAnimationIndex = -1; } + asset.mAnimator->updateBoneMatrices(); } - // animation has completed - } else { - completed.push_back(anim); - asset.fadeGltfAnimationIndex = -1; - } - asset.mAnimator->updateBoneMatrices(); } - } } - void AssetManager::setBoneTransform(SceneAsset& asset, int frameNumber) { - - RenderableManager& rm = _engine->getRenderableManager(); - - const auto& filamentInstance = asset.mAsset->getInstance(); - - TransformManager &transformManager = _engine->getTransformManager(); - - int skinIndex = 0; - - for(int i = 0; i < asset.mBoneAnimationBuffer.mBones.size(); i++) { - auto mBoneIndex = asset.mBoneAnimationBuffer.mBones[i]; - auto frameDataOffset = (frameNumber * asset.mBoneAnimationBuffer.mBones.size() * 7) + (i * 7); - - utils::Entity joint = filamentInstance->getJointsAt(skinIndex)[mBoneIndex]; - if(joint.isNull()) { - Log("ERROR : joint not found"); - continue; - } - - vector& fd = asset.mBoneAnimationBuffer.mFrameData; - - math::mat4f localTransform(math::quatf { - fd[frameDataOffset+3], - fd[frameDataOffset+4], - fd[frameDataOffset+5], - fd[frameDataOffset+6], - }); - - auto jointInstance = transformManager.getInstance(joint); - - auto xform = asset.mBoneAnimationBuffer.mBaseTransforms[i]; - - transformManager.setTransform(jointInstance, xform * localTransform); - - } +void AssetManager::setBoneTransform(SceneAsset& asset, int frameNumber) { + + RenderableManager& rm = _engine->getRenderableManager(); + + const auto& filamentInstance = asset.mAsset->getInstance(); + + TransformManager &transformManager = _engine->getTransformManager(); + + int skinIndex = 0; + + for(int i = 0; i < asset.mBoneAnimationBuffer.mBones.size(); i++) { + auto mBoneIndex = asset.mBoneAnimationBuffer.mBones[i]; + auto frameDataOffset = (frameNumber * asset.mBoneAnimationBuffer.mBones.size() * 7) + (i * 7); + + utils::Entity joint = filamentInstance->getJointsAt(skinIndex)[mBoneIndex]; + if(joint.isNull()) { + Log("ERROR : joint not found"); + continue; + } + + vector& fd = asset.mBoneAnimationBuffer.mFrameData; + + math::mat4f localTransform(math::quatf { + fd[frameDataOffset+3], + fd[frameDataOffset+4], + fd[frameDataOffset+5], + fd[frameDataOffset+6], + }); + + auto jointInstance = transformManager.getInstance(joint); + + auto xform = asset.mBoneAnimationBuffer.mBaseTransforms[i]; + + transformManager.setTransform(jointInstance, xform * localTransform); + + } } void AssetManager::remove(EntityId entityId) { - const auto& pos = _entityIdLookup.find(entityId); - if(pos == _entityIdLookup.end()) { - Log("Couldn't find asset under specified entity id."); - return; - } - SceneAsset& sceneAsset = _assets[pos->second]; - - _scene->removeEntities(sceneAsset.mAsset->getEntities(), - sceneAsset.mAsset->getEntityCount()); - - _scene->removeEntities(sceneAsset.mAsset->getLightEntities(), - sceneAsset.mAsset->getLightEntityCount()); - - _assetLoader->destroyAsset(sceneAsset.mAsset); - - if(sceneAsset.mTexture) { - _engine->destroy(sceneAsset.mTexture); - } - EntityManager& em = EntityManager::get(); - em.destroy(Entity::import(entityId)); - sceneAsset.mAsset = nullptr; // still need to remove sceneAsset somewhere... + const auto& pos = _entityIdLookup.find(entityId); + if(pos == _entityIdLookup.end()) { + Log("Couldn't find asset under specified entity id."); + return; + } + SceneAsset& sceneAsset = _assets[pos->second]; + + _scene->removeEntities(sceneAsset.mAsset->getEntities(), + sceneAsset.mAsset->getEntityCount()); + + _scene->removeEntities(sceneAsset.mAsset->getLightEntities(), + sceneAsset.mAsset->getLightEntityCount()); + + _assetLoader->destroyAsset(sceneAsset.mAsset); + + if(sceneAsset.mTexture) { + _engine->destroy(sceneAsset.mTexture); + } + EntityManager& em = EntityManager::get(); + em.destroy(Entity::import(entityId)); + sceneAsset.mAsset = nullptr; // still need to remove sceneAsset somewhere... } void AssetManager::setMorphTargetWeights(EntityId entityId, const char* const entityName, const float* const weights, const int count) { - const auto& pos = _entityIdLookup.find(entityId); - if(pos == _entityIdLookup.end()) { - Log("ERROR: asset not found for entity."); - return; - } - auto& asset = _assets[pos->second]; - - auto entity = findEntityByName(asset, entityName); - if(!entity) { - Log("Warning: failed to find entity %s", entityName); - return; - } - - RenderableManager &rm = _engine->getRenderableManager(); - - rm.setMorphWeights( - rm.getInstance(entity), - weights, - count - ); + const auto& pos = _entityIdLookup.find(entityId); + if(pos == _entityIdLookup.end()) { + Log("ERROR: asset not found for entity."); + return; + } + auto& asset = _assets[pos->second]; + + auto entity = findEntityByName(asset, entityName); + if(!entity) { + Log("Warning: failed to find entity %s", entityName); + return; + } + + RenderableManager &rm = _engine->getRenderableManager(); + + rm.setMorphWeights( + rm.getInstance(entity), + weights, + count + ); } utils::Entity AssetManager::findEntityByName(SceneAsset asset, const char* entityName) { - utils::Entity entity; - for (size_t i = 0, c = asset.mAsset->getEntityCount(); i != c; ++i) { - auto entity = asset.mAsset->getEntities()[i]; - auto nameInstance = _ncm->getInstance(entity); - if(!nameInstance.isValid()) { - continue; - } - auto name = _ncm->getName(nameInstance); - if(!name) { - continue; - } - if(strcmp(entityName,name)==0) { - return entity; - } - } - return entity; + utils::Entity entity; + for (size_t i = 0, c = asset.mAsset->getEntityCount(); i != c; ++i) { + auto entity = asset.mAsset->getEntities()[i]; + auto nameInstance = _ncm->getInstance(entity); + if(!nameInstance.isValid()) { + continue; + } + auto name = _ncm->getName(nameInstance); + if(!name) { + continue; + } + if(strcmp(entityName,name)==0) { + return entity; + } + } + return entity; } bool AssetManager::setMorphAnimationBuffer( - EntityId entityId, - const char* entityName, - const float* const morphData, - const int* const morphIndices, - int numMorphTargets, - int numFrames, - float frameLengthInMs) { - - const auto& pos = _entityIdLookup.find(entityId); - if(pos == _entityIdLookup.end()) { - Log("ERROR: asset not found for entity."); - return false; - } - auto& asset = _assets[pos->second]; - - auto entity = findEntityByName(asset, entityName); - if(!entity) { - Log("Warning: failed to find entity %s", entityName); - return false; - } - - asset.mMorphAnimationBuffer.mMeshTarget = entity; - asset.mMorphAnimationBuffer.mFrameData.clear(); - asset.mMorphAnimationBuffer.mFrameData.insert( - asset.mMorphAnimationBuffer.mFrameData.begin(), - morphData, - morphData + (numFrames * numMorphTargets) - ); - asset.mMorphAnimationBuffer.mFrameLengthInMs = frameLengthInMs; - asset.mMorphAnimationBuffer.mMorphIndices.resize(numMorphTargets); - for(int i =0; i< numMorphTargets; i++) { - asset.mMorphAnimationBuffer.mMorphIndices[i] = morphIndices[i]; - } - - AnimationStatus animation; - animation.mDuration = (frameLengthInMs * numFrames) / 1000.0f; - animation.mStart = high_resolution_clock::now(); - animation.type = AnimationType::MORPH; - asset.mAnimations.push_back(animation); - return true; + EntityId entityId, + const char* entityName, + const float* const morphData, + const int* const morphIndices, + int numMorphTargets, + int numFrames, + float frameLengthInMs) { + + const auto& pos = _entityIdLookup.find(entityId); + if(pos == _entityIdLookup.end()) { + Log("ERROR: asset not found for entity."); + return false; + } + auto& asset = _assets[pos->second]; + + auto entity = findEntityByName(asset, entityName); + if(!entity) { + Log("Warning: failed to find entity %s", entityName); + return false; + } + + asset.mMorphAnimationBuffer.mMeshTarget = entity; + asset.mMorphAnimationBuffer.mFrameData.clear(); + asset.mMorphAnimationBuffer.mFrameData.insert( + asset.mMorphAnimationBuffer.mFrameData.begin(), + morphData, + morphData + (numFrames * numMorphTargets) + ); + asset.mMorphAnimationBuffer.mFrameLengthInMs = frameLengthInMs; + asset.mMorphAnimationBuffer.mMorphIndices.resize(numMorphTargets); + for(int i =0; i< numMorphTargets; i++) { + asset.mMorphAnimationBuffer.mMorphIndices[i] = morphIndices[i]; + } + + AnimationStatus animation; + animation.mDuration = (frameLengthInMs * numFrames) / 1000.0f; + animation.mStart = high_resolution_clock::now(); + animation.type = AnimationType::MORPH; + asset.mAnimations.push_back(animation); + return true; } -bool AssetManager::setBoneAnimationBuffer( - EntityId entityId, - const float* const frameData, - int numFrames, - int numBones, - const char** const boneNames, - const char** const meshNames, - int numMeshTargets, - float frameLengthInMs) { - - const auto& pos = _entityIdLookup.find(entityId); - if(pos == _entityIdLookup.end()) { - Log("ERROR: asset not found for entity."); - return false; - } - auto& asset = _assets[pos->second]; - auto filamentInstance = asset.mAsset->getInstance(); - - size_t skinCount = filamentInstance->getSkinCount(); - - if(skinCount > 1) { - Log("WARNING - skin count > 1 not currently implemented. This will probably not work"); - } - - TransformManager &transformManager = _engine->getTransformManager(); - - int skinIndex = 0; - const utils::Entity* joints = filamentInstance->getJointsAt(skinIndex); - size_t numJoints = filamentInstance->getJointCountAt(skinIndex); - - BoneAnimationBuffer& animationBuffer = asset.mBoneAnimationBuffer; - - // if an animation has already been set, reset the transform for the respective bones - for(int i = 0; i < animationBuffer.mBones.size(); i++) { - auto boneIndex = animationBuffer.mBones[i]; - auto jointInstance = transformManager.getInstance(joints[boneIndex]); - transformManager.setTransform(jointInstance, animationBuffer.mBaseTransforms[i]); - } - - asset.mAnimator->resetBoneMatrices(); - - animationBuffer.mBones.resize(numBones); - animationBuffer.mBaseTransforms.resize(numBones); - - for(int i = 0; i < numBones; i++) { - for(int j = 0; j < numJoints; j++) { - const char* jointName = _ncm->getName(_ncm->getInstance(joints[j])); - if(strcmp(jointName, boneNames[i]) == 0) { - auto jointInstance = transformManager.getInstance(joints[j]); - // auto currentXform = ; - auto baseTransform = transformManager.getTransform(jointInstance); // inverse(filamentInstance->getInverseBindMatricesAt(skinIndex)[j]); - animationBuffer.mBaseTransforms[i] = baseTransform; - animationBuffer.mBones[i] = j; - break; - } - } - } - - if(animationBuffer.mBones.size() != numBones) { - Log("Failed to find one or more bone indices"); - return false; - } - - animationBuffer.mFrameData.clear(); - // 7 == locX, locY, locZ, rotW, rotX, rotY, rotZ - animationBuffer.mFrameData.resize(numFrames * numBones * 7); - animationBuffer.mFrameData.insert( - animationBuffer.mFrameData.begin(), - frameData, - frameData + numFrames * numBones * 7 - ); - - animationBuffer.mFrameLengthInMs = frameLengthInMs; - animationBuffer.mNumFrames = numFrames; +bool AssetManager::setMaterialColor(EntityId entityId, const char* meshName, int materialIndex, const float r, const float g, const float b, const float a) { - animationBuffer.mMeshTargets.clear(); - for(int i = 0; i < numMeshTargets; i++) { - auto entity = findEntityByName(asset, meshNames[i]); - if(!entity) { - Log("Mesh target %s for bone animation could not be found", meshNames[i]); - return false; + const auto& pos = _entityIdLookup.find(entityId); + if(pos == _entityIdLookup.end()) { + Log("ERROR: asset not found for entity."); + return false; } - Log("Added mesh target %s", meshNames[i]); - animationBuffer.mMeshTargets.push_back(entity); - } + auto& asset = _assets[pos->second]; + auto entity = findEntityByName(asset, meshName); + + RenderableManager& rm = _engine->getRenderableManager(); + + auto renderable = rm.getInstance(entity); + + if(!renderable.isValid()) { + return false; + } + + MaterialInstance* mi = rm.getMaterialInstanceAt(renderable, materialIndex); + + if(!mi) { + Log("ERROR: material index must be less than number of material instances"); + return false; + } + mi->setParameter("baseColorFactor", RgbaType::sRGB, math::float4(r, g, b, a)); + return true; +} - AnimationStatus animation; - animation.mStart = std::chrono::high_resolution_clock::now(); - animation.mReverse = false; - animation.mDuration = (frameLengthInMs * numFrames) / 1000.0f; - animation.type = AnimationType::BONE; - asset.mAnimations.push_back(animation); - return true; +bool AssetManager::setBoneAnimationBuffer( + EntityId entityId, + const float* const frameData, + int numFrames, + int numBones, + const char** const boneNames, + const char** const meshNames, + int numMeshTargets, + float frameLengthInMs) { + + const auto& pos = _entityIdLookup.find(entityId); + if(pos == _entityIdLookup.end()) { + Log("ERROR: asset not found for entity."); + return false; + } + auto& asset = _assets[pos->second]; + auto filamentInstance = asset.mAsset->getInstance(); + + size_t skinCount = filamentInstance->getSkinCount(); + + if(skinCount > 1) { + Log("WARNING - skin count > 1 not currently implemented. This will probably not work"); + } + + TransformManager &transformManager = _engine->getTransformManager(); + + int skinIndex = 0; + const utils::Entity* joints = filamentInstance->getJointsAt(skinIndex); + size_t numJoints = filamentInstance->getJointCountAt(skinIndex); + + BoneAnimationBuffer& animationBuffer = asset.mBoneAnimationBuffer; + + // if an animation has already been set, reset the transform for the respective bones + for(int i = 0; i < animationBuffer.mBones.size(); i++) { + auto boneIndex = animationBuffer.mBones[i]; + auto jointInstance = transformManager.getInstance(joints[boneIndex]); + transformManager.setTransform(jointInstance, animationBuffer.mBaseTransforms[i]); + } + + asset.mAnimator->resetBoneMatrices(); + + animationBuffer.mBones.resize(numBones); + animationBuffer.mBaseTransforms.resize(numBones); + + for(int i = 0; i < numBones; i++) { + for(int j = 0; j < numJoints; j++) { + const char* jointName = _ncm->getName(_ncm->getInstance(joints[j])); + if(strcmp(jointName, boneNames[i]) == 0) { + auto jointInstance = transformManager.getInstance(joints[j]); + // auto currentXform = ; + auto baseTransform = transformManager.getTransform(jointInstance); // inverse(filamentInstance->getInverseBindMatricesAt(skinIndex)[j]); + animationBuffer.mBaseTransforms[i] = baseTransform; + animationBuffer.mBones[i] = j; + break; + } + } + } + + if(animationBuffer.mBones.size() != numBones) { + Log("Failed to find one or more bone indices"); + return false; + } + + animationBuffer.mFrameData.clear(); + // 7 == locX, locY, locZ, rotW, rotX, rotY, rotZ + animationBuffer.mFrameData.resize(numFrames * numBones * 7); + animationBuffer.mFrameData.insert( + animationBuffer.mFrameData.begin(), + frameData, + frameData + numFrames * numBones * 7 + ); + + animationBuffer.mFrameLengthInMs = frameLengthInMs; + animationBuffer.mNumFrames = numFrames; + + animationBuffer.mMeshTargets.clear(); + for(int i = 0; i < numMeshTargets; i++) { + auto entity = findEntityByName(asset, meshNames[i]); + if(!entity) { + Log("Mesh target %s for bone animation could not be found", meshNames[i]); + return false; + } + Log("Added mesh target %s", meshNames[i]); + animationBuffer.mMeshTargets.push_back(entity); + } + + AnimationStatus animation; + animation.mStart = std::chrono::high_resolution_clock::now(); + animation.mReverse = false; + animation.mDuration = (frameLengthInMs * numFrames) / 1000.0f; + animation.type = AnimationType::BONE; + asset.mAnimations.push_back(animation); + + return true; } void AssetManager::playAnimation(EntityId e, int index, bool loop, bool reverse, bool replaceActive, float crossfade) { - const auto& pos = _entityIdLookup.find(e); - if(pos == _entityIdLookup.end()) { - Log("ERROR: asset not found for entity."); - return; - } - auto& asset = _assets[pos->second]; - - if(replaceActive) { - vector active; - for(int i = 0; i < asset.mAnimations.size(); i++) { - if(asset.mAnimations[i].type == AnimationType::GLTF) { - active.push_back(i); - } + if(index < 0) { + Log("ERROR: glTF animation index must be greater than zero."); + return; } - if(active.size() > 0) { - auto& last = asset.mAnimations[active.back()]; - asset.fadeGltfAnimationIndex = last.gltfIndex; - asset.fadeDuration = crossfade; - auto now = high_resolution_clock::now(); - auto elapsed = float(std::chrono::duration_cast(now - last.mStart).count()) / 1000.0f; - asset.fadeOutAnimationStart = elapsed; - for(int j = active.size() - 1; j >= 0; j--) { - asset.mAnimations.erase(asset.mAnimations.begin() + active[j]); - } + const auto& pos = _entityIdLookup.find(e); + if(pos == _entityIdLookup.end()) { + Log("ERROR: asset not found for entity."); + return; + } + auto& asset = _assets[pos->second]; + + if(replaceActive) { + vector active; + for(int i = 0; i < asset.mAnimations.size(); i++) { + if(asset.mAnimations[i].type == AnimationType::GLTF) { + active.push_back(i); + } + } + if(active.size() > 0) { + auto& last = asset.mAnimations[active.back()]; + asset.fadeGltfAnimationIndex = last.gltfIndex; + asset.fadeDuration = crossfade; + auto now = high_resolution_clock::now(); + auto elapsed = float(std::chrono::duration_cast(now - last.mStart).count()) / 1000.0f; + asset.fadeOutAnimationStart = elapsed; + for(int j = active.size() - 1; j >= 0; j--) { + asset.mAnimations.erase(asset.mAnimations.begin() + active[j]); + } + } else { + asset.fadeGltfAnimationIndex = -1; + asset.fadeDuration = 0.0f; + } + } else if(crossfade > 0) { + Log("ERROR: crossfade only supported when replaceActive is true."); + return; } else { - asset.fadeGltfAnimationIndex = -1; - asset.fadeDuration = 0.0f; + asset.fadeGltfAnimationIndex = -1; + asset.fadeDuration = 0.0f; } - } else if(crossfade > 0) { - Log("ERROR: crossfade only supported when replaceActive is true."); - return; - } else { - asset.fadeGltfAnimationIndex = -1; - asset.fadeDuration = 0.0f; - } - - AnimationStatus animation; - animation.gltfIndex = index; - animation.mStart = std::chrono::high_resolution_clock::now(); - animation.mLoop = loop; - animation.mReverse = reverse; - animation.type = AnimationType::GLTF; - animation.mDuration = asset.mAnimator->getAnimationDuration(index); - - asset.mAnimations.push_back(animation); + + AnimationStatus animation; + animation.gltfIndex = index; + animation.mStart = std::chrono::high_resolution_clock::now(); + animation.mLoop = loop; + animation.mReverse = reverse; + animation.type = AnimationType::GLTF; + animation.mDuration = asset.mAnimator->getAnimationDuration(index); + + asset.mAnimations.push_back(animation); } void AssetManager::stopAnimation(EntityId entityId, int index) { - const auto& pos = _entityIdLookup.find(entityId); - if(pos == _entityIdLookup.end()) { - Log("ERROR: asset not found for entity."); - return; - } - auto& asset = _assets[pos->second]; - - asset.mAnimations.erase(std::remove_if(asset.mAnimations.begin(), - asset.mAnimations.end(), - [=](AnimationStatus& anim) { return anim.gltfIndex == index; }), - asset.mAnimations.end()); - + const auto& pos = _entityIdLookup.find(entityId); + if(pos == _entityIdLookup.end()) { + Log("ERROR: asset not found for entity."); + return; + } + auto& asset = _assets[pos->second]; + + asset.mAnimations.erase(std::remove_if(asset.mAnimations.begin(), + asset.mAnimations.end(), + [=](AnimationStatus& anim) { return anim.gltfIndex == index; }), + asset.mAnimations.end()); + } void AssetManager::loadTexture(EntityId entity, const char* resourcePath, int renderableIndex) { - - const auto& pos = _entityIdLookup.find(entity); - if(pos == _entityIdLookup.end()) { - Log("ERROR: asset not found for entity."); - return; - } - auto& asset = _assets[pos->second]; - - Log("Loading texture at %s for renderableIndex %d", resourcePath, renderableIndex); - - string rp(resourcePath); - - if(asset.mTexture) { - _engine->destroy(asset.mTexture); - asset.mTexture = nullptr; - } - - ResourceBuffer imageResource = _resourceLoaderWrapper->load(rp.c_str()); - - StreamBufferAdapter sb((char *)imageResource.data, (char *)imageResource.data + imageResource.size); - - istream *inputStream = new std::istream(&sb); - - LinearImage *image = new LinearImage(ImageDecoder::decode( - *inputStream, rp.c_str(), ImageDecoder::ColorSpace::SRGB)); - - if (!image->isValid()) { - Log("Invalid image : %s", rp.c_str()); - delete inputStream; - _resourceLoaderWrapper->free(imageResource); - return; - } - - uint32_t channels = image->getChannels(); - uint32_t w = image->getWidth(); - uint32_t h = image->getHeight(); - asset.mTexture = Texture::Builder() - .width(w) - .height(h) - .levels(0xff) - .format(channels == 3 ? Texture::InternalFormat::RGB16F - : Texture::InternalFormat::RGBA16F) - .sampler(Texture::Sampler::SAMPLER_2D) - .build(*_engine); - - Texture::PixelBufferDescriptor::Callback freeCallback = [](void *buf, size_t, - void *data) { - delete reinterpret_cast(data); - }; - - Texture::PixelBufferDescriptor buffer( - image->getPixelRef(), size_t(w * h * channels * sizeof(float)), - channels == 3 ? Texture::Format::RGB : Texture::Format::RGBA, - Texture::Type::FLOAT, freeCallback); - - asset.mTexture->setImage(*_engine, 0, std::move(buffer)); - MaterialInstance* const* inst = asset.mAsset->getInstance()->getMaterialInstances(); - size_t mic = asset.mAsset->getInstance()->getMaterialInstanceCount(); - Log("Material instance count : %d", mic); - auto sampler = TextureSampler(); - inst[0]->setParameter("baseColorIndex",0); - inst[0]->setParameter("baseColorMap",asset.mTexture,sampler); - delete inputStream; - - _resourceLoaderWrapper->free(imageResource); - + const auto& pos = _entityIdLookup.find(entity); + if(pos == _entityIdLookup.end()) { + Log("ERROR: asset not found for entity."); + return; + } + auto& asset = _assets[pos->second]; + + Log("Loading texture at %s for renderableIndex %d", resourcePath, renderableIndex); + + string rp(resourcePath); + + if(asset.mTexture) { + _engine->destroy(asset.mTexture); + asset.mTexture = nullptr; + } + + ResourceBuffer imageResource = _resourceLoaderWrapper->load(rp.c_str()); + + StreamBufferAdapter sb((char *)imageResource.data, (char *)imageResource.data + imageResource.size); + + istream *inputStream = new std::istream(&sb); + + LinearImage *image = new LinearImage(ImageDecoder::decode( + *inputStream, rp.c_str(), ImageDecoder::ColorSpace::SRGB)); + + if (!image->isValid()) { + Log("Invalid image : %s", rp.c_str()); + delete inputStream; + _resourceLoaderWrapper->free(imageResource); + return; + } + + uint32_t channels = image->getChannels(); + uint32_t w = image->getWidth(); + uint32_t h = image->getHeight(); + asset.mTexture = Texture::Builder() + .width(w) + .height(h) + .levels(0xff) + .format(channels == 3 ? Texture::InternalFormat::RGB16F + : Texture::InternalFormat::RGBA16F) + .sampler(Texture::Sampler::SAMPLER_2D) + .build(*_engine); + + Texture::PixelBufferDescriptor::Callback freeCallback = [](void *buf, size_t, + void *data) { + delete reinterpret_cast(data); + }; + + Texture::PixelBufferDescriptor buffer( + image->getPixelRef(), size_t(w * h * channels * sizeof(float)), + channels == 3 ? Texture::Format::RGB : Texture::Format::RGBA, + Texture::Type::FLOAT, freeCallback); + + asset.mTexture->setImage(*_engine, 0, std::move(buffer)); + MaterialInstance* const* inst = asset.mAsset->getInstance()->getMaterialInstances(); + size_t mic = asset.mAsset->getInstance()->getMaterialInstanceCount(); + Log("Material instance count : %d", mic); + + auto sampler = TextureSampler(); + inst[0]->setParameter("baseColorIndex",0); + inst[0]->setParameter("baseColorMap",asset.mTexture,sampler); + delete inputStream; + + _resourceLoaderWrapper->free(imageResource); + } void AssetManager::setAnimationFrame(EntityId entity, int animationIndex, int animationFrame) { - const auto& pos = _entityIdLookup.find(entity); - if(pos == _entityIdLookup.end()) { - Log("ERROR: asset not found for entity."); - return; - } - auto& asset = _assets[pos->second]; - auto offset = 60 * animationFrame * 1000; // TODO - don't hardcore 60fps framerate - asset.mAnimator->applyAnimation(animationIndex, offset); - asset.mAnimator->updateBoneMatrices(); + const auto& pos = _entityIdLookup.find(entity); + if(pos == _entityIdLookup.end()) { + Log("ERROR: asset not found for entity."); + return; + } + auto& asset = _assets[pos->second]; + auto offset = 60 * animationFrame * 1000; // TODO - don't hardcore 60fps framerate + asset.mAnimator->applyAnimation(animationIndex, offset); + asset.mAnimator->updateBoneMatrices(); } float AssetManager::getAnimationDuration(EntityId entity, int animationIndex) { const auto& pos = _entityIdLookup.find(entity); - - unique_ptr> names = make_unique>(); - - if(pos == _entityIdLookup.end()) { - Log("ERROR: asset not found for entity id."); - return -1.0f; - } - - auto& asset = _assets[pos->second]; - return asset.mAnimator->getAnimationDuration(animationIndex); + + unique_ptr> names = make_unique>(); + + if(pos == _entityIdLookup.end()) { + Log("ERROR: asset not found for entity id."); + return -1.0f; + } + + auto& asset = _assets[pos->second]; + return asset.mAnimator->getAnimationDuration(animationIndex); } unique_ptr> AssetManager::getAnimationNames(EntityId entity) { - - const auto& pos = _entityIdLookup.find(entity); - - unique_ptr> names = make_unique>(); - - if(pos == _entityIdLookup.end()) { - Log("ERROR: asset not found for entity id."); + + const auto& pos = _entityIdLookup.find(entity); + + unique_ptr> names = make_unique>(); + + if(pos == _entityIdLookup.end()) { + Log("ERROR: asset not found for entity id."); + return names; + } + auto& asset = _assets[pos->second]; + + size_t count = asset.mAnimator->getAnimationCount(); + + + for (size_t i = 0; i < count; i++) { + names->push_back(asset.mAnimator->getAnimationName(i)); + } + return names; - } - auto& asset = _assets[pos->second]; - - size_t count = asset.mAnimator->getAnimationCount(); - - - for (size_t i = 0; i < count; i++) { - names->push_back(asset.mAnimator->getAnimationName(i)); - } - - return names; } unique_ptr> AssetManager::getMorphTargetNames(EntityId entity, const char *meshName) { - - unique_ptr> names = make_unique>(); - - const auto& pos = _entityIdLookup.find(entity); - if(pos == _entityIdLookup.end()) { - Log("ERROR: asset not found for entity."); - return names; - } - auto& asset = _assets[pos->second]; - - const utils::Entity *entities = asset.mAsset->getEntities(); - - for (int i = 0; i < asset.mAsset->getEntityCount(); i++) { - utils::Entity e = entities[i]; - auto inst = _ncm->getInstance(e); - const char *name = _ncm->getName(inst); - - if (name && strcmp(name, meshName) == 0) { - size_t count = asset.mAsset->getMorphTargetCountAt(e); - for (int j = 0; j < count; j++) { - const char *morphName = asset.mAsset->getMorphTargetNameAt(e, j); - names->push_back(morphName); - } - break; + + unique_ptr> names = make_unique>(); + + const auto& pos = _entityIdLookup.find(entity); + if(pos == _entityIdLookup.end()) { + Log("ERROR: asset not found for entity."); + return names; } - } - return names; + auto& asset = _assets[pos->second]; + + const utils::Entity *entities = asset.mAsset->getEntities(); + + for (int i = 0; i < asset.mAsset->getEntityCount(); i++) { + utils::Entity e = entities[i]; + auto inst = _ncm->getInstance(e); + const char *name = _ncm->getName(inst); + + if (name && strcmp(name, meshName) == 0) { + size_t count = asset.mAsset->getMorphTargetCountAt(e); + for (int j = 0; j < count; j++) { + const char *morphName = asset.mAsset->getMorphTargetNameAt(e, j); + names->push_back(morphName); + } + break; + } + } + return names; } void AssetManager::transformToUnitCube(EntityId entity) { - const auto& pos = _entityIdLookup.find(entity); - if(pos == _entityIdLookup.end()) { - Log("ERROR: asset not found for entity."); - return; - } - auto& asset = _assets[pos->second]; - - Log("Transforming asset to unit cube."); - auto &tm = _engine->getTransformManager(); - FilamentInstance* inst = asset.mAsset->getInstance(); - auto aabb = inst->getBoundingBox(); - auto center = aabb.center(); - auto halfExtent = aabb.extent(); - auto maxExtent = max(halfExtent) * 2; - auto scaleFactor = 2.0f / maxExtent; - auto transform = - math::mat4f::scaling(scaleFactor) * math::mat4f::translation(-center); - tm.setTransform(tm.getInstance(inst->getRoot()), transform); + const auto& pos = _entityIdLookup.find(entity); + if(pos == _entityIdLookup.end()) { + Log("ERROR: asset not found for entity."); + return; + } + auto& asset = _assets[pos->second]; + + Log("Transforming asset to unit cube."); + auto &tm = _engine->getTransformManager(); + FilamentInstance* inst = asset.mAsset->getInstance(); + auto aabb = inst->getBoundingBox(); + auto center = aabb.center(); + auto halfExtent = aabb.extent(); + auto maxExtent = max(halfExtent) * 2; + auto scaleFactor = 2.0f / maxExtent; + auto transform = + math::mat4f::scaling(scaleFactor) * math::mat4f::translation(-center); + tm.setTransform(tm.getInstance(inst->getRoot()), transform); } void AssetManager::updateTransform(SceneAsset& asset) { - auto &tm = _engine->getTransformManager(); - auto transform = - asset.mPosition * asset.mRotation * math::mat4f::scaling(asset.mScale); - tm.setTransform(tm.getInstance(asset.mAsset->getRoot()), transform); + auto &tm = _engine->getTransformManager(); + auto transform = + asset.mPosition * asset.mRotation * math::mat4f::scaling(asset.mScale); + tm.setTransform(tm.getInstance(asset.mAsset->getRoot()), transform); } void AssetManager::setScale(EntityId entity, float scale) { - const auto& pos = _entityIdLookup.find(entity); - if(pos == _entityIdLookup.end()) { - Log("ERROR: asset not found for entity."); - return; - } - auto& asset = _assets[pos->second]; - asset.mScale = scale; - updateTransform(asset); + const auto& pos = _entityIdLookup.find(entity); + if(pos == _entityIdLookup.end()) { + Log("ERROR: asset not found for entity."); + return; + } + auto& asset = _assets[pos->second]; + asset.mScale = scale; + updateTransform(asset); } void AssetManager::setPosition(EntityId entity, float x, float y, float z) { - const auto& pos = _entityIdLookup.find(entity); - if(pos == _entityIdLookup.end()) { - Log("ERROR: asset not found for entity."); - return; - } - auto& asset = _assets[pos->second]; - asset.mPosition = math::mat4f::translation(math::float3(x,y,z)); - updateTransform(asset); + const auto& pos = _entityIdLookup.find(entity); + if(pos == _entityIdLookup.end()) { + Log("ERROR: asset not found for entity."); + return; + } + auto& asset = _assets[pos->second]; + asset.mPosition = math::mat4f::translation(math::float3(x,y,z)); + updateTransform(asset); } void AssetManager::setRotation(EntityId entity, float rads, float x, float y, float z) { - const auto& pos = _entityIdLookup.find(entity); - if(pos == _entityIdLookup.end()) { - Log("ERROR: asset not found for entity."); - return; - } - auto& asset = _assets[pos->second]; - asset.mRotation = math::mat4f::rotation(rads, math::float3(x,y,z)); - updateTransform(asset); + const auto& pos = _entityIdLookup.find(entity); + if(pos == _entityIdLookup.end()) { + Log("ERROR: asset not found for entity."); + return; + } + auto& asset = _assets[pos->second]; + asset.mRotation = math::mat4f::rotation(rads, math::float3(x,y,z)); + updateTransform(asset); } const utils::Entity *AssetManager::getCameraEntities(EntityId entity) { - const auto& pos = _entityIdLookup.find(entity); - if(pos == _entityIdLookup.end()) { - Log("ERROR: asset not found for entity."); - return nullptr; - } - auto& asset = _assets[pos->second]; - return asset.mAsset->getCameraEntities(); + const auto& pos = _entityIdLookup.find(entity); + if(pos == _entityIdLookup.end()) { + Log("ERROR: asset not found for entity."); + return nullptr; + } + auto& asset = _assets[pos->second]; + return asset.mAsset->getCameraEntities(); } size_t AssetManager::getCameraEntityCount(EntityId entity) { - const auto& pos = _entityIdLookup.find(entity); - if(pos == _entityIdLookup.end()) { - Log("ERROR: asset not found for entity."); - return 0; - } - auto& asset = _assets[pos->second]; - return asset.mAsset->getCameraEntityCount(); + const auto& pos = _entityIdLookup.find(entity); + if(pos == _entityIdLookup.end()) { + Log("ERROR: asset not found for entity."); + return 0; + } + auto& asset = _assets[pos->second]; + return asset.mAsset->getCameraEntityCount(); } const utils::Entity* AssetManager::getLightEntities(EntityId entity) const noexcept { - const auto& pos = _entityIdLookup.find(entity); - if(pos == _entityIdLookup.end()) { - Log("ERROR: asset not found for entity."); - return nullptr; - } - auto& asset = _assets[pos->second]; - return asset.mAsset->getLightEntities(); + const auto& pos = _entityIdLookup.find(entity); + if(pos == _entityIdLookup.end()) { + Log("ERROR: asset not found for entity."); + return nullptr; + } + auto& asset = _assets[pos->second]; + return asset.mAsset->getLightEntities(); } size_t AssetManager::getLightEntityCount(EntityId entity) const noexcept { - const auto& pos = _entityIdLookup.find(entity); - if(pos == _entityIdLookup.end()) { - Log("ERROR: asset not found for entity."); - return 0; - } - auto& asset = _assets[pos->second]; - return asset.mAsset->getLightEntityCount(); + const auto& pos = _entityIdLookup.find(entity); + if(pos == _entityIdLookup.end()) { + Log("ERROR: asset not found for entity."); + return 0; + } + auto& asset = _assets[pos->second]; + return asset.mAsset->getLightEntityCount(); } @@ -875,36 +909,36 @@ size_t AssetManager::getLightEntityCount(EntityId entity) const noexcept { // auto& inverseBindMatrix = filamentInstance->getInverseBindMatricesAt(skinIndex)[mBoneIndex]; - // auto globalJointTransform = transformManager.getWorldTransform(jointInstance); +// auto globalJointTransform = transformManager.getWorldTransform(jointInstance); - // for(auto& target : asset.mBoneAnimationBuffer.mMeshTargets) { - - // auto inverseGlobalTransform = inverse( - // transformManager.getWorldTransform( - // transformManager.getInstance(target) - // ) - // ); +// for(auto& target : asset.mBoneAnimationBuffer.mMeshTargets) { - // auto boneTransform = inverseGlobalTransform * globalJointTransform * localTransform * inverseBindMatrix; - // auto renderable = rm.getInstance(target); - // rm.setBones( - // renderable, - // &boneTransform, - // 1, - // mBoneIndex - // ); - // } +// auto inverseGlobalTransform = inverse( +// transformManager.getWorldTransform( +// transformManager.getInstance(target) +// ) +// ); + +// auto boneTransform = inverseGlobalTransform * globalJointTransform * localTransform * inverseBindMatrix; +// auto renderable = rm.getInstance(target); +// rm.setBones( +// renderable, +// &boneTransform, +// 1, +// mBoneIndex +// ); +// } - // 1.0f, 0.0f, 0.0f, 0.0f, - // 0.0f, 0.0f, 1.0f, 0.0f, - // 0.0f, -1.0f, 0.0f, 0.0f, - // 0.0f, 0.0f, 0.0f, 1.0f - // }; - // Log("TRANSFORM"); - // Log("%f %f %f %f", localTransform[0][0], localTransform[1][0], localTransform[2][0], localTransform[3][0] ) ; - // Log("%f %f %f %f", localTransform[0][1], localTransform[1][1], localTransform[2][1], localTransform[3][1] ) ; - // Log("%f %f %f %f", localTransform[0][2], localTransform[1][2], localTransform[2][2], localTransform[3][2] ) ; - // Log("%f %f %f %f", localTransform[0][3], localTransform[1][3], localTransform[2][3], localTransform[3][3] ) ; - // transformManager.getTransform(jointInstance); +// 1.0f, 0.0f, 0.0f, 0.0f, +// 0.0f, 0.0f, 1.0f, 0.0f, +// 0.0f, -1.0f, 0.0f, 0.0f, +// 0.0f, 0.0f, 0.0f, 1.0f +// }; +// Log("TRANSFORM"); +// Log("%f %f %f %f", localTransform[0][0], localTransform[1][0], localTransform[2][0], localTransform[3][0] ) ; +// Log("%f %f %f %f", localTransform[0][1], localTransform[1][1], localTransform[2][1], localTransform[3][1] ) ; +// Log("%f %f %f %f", localTransform[0][2], localTransform[1][2], localTransform[2][2], localTransform[3][2] ) ; +// Log("%f %f %f %f", localTransform[0][3], localTransform[1][3], localTransform[2][3], localTransform[3][3] ) ; +// transformManager.getTransform(jointInstance); diff --git a/ios/src/PolyvoxFilamentApi.cpp b/ios/src/PolyvoxFilamentApi.cpp index 1d4062de..446aaf69 100644 --- a/ios/src/PolyvoxFilamentApi.cpp +++ b/ios/src/PolyvoxFilamentApi.cpp @@ -337,6 +337,10 @@ extern "C" { // ((AssetManager*)assetManager)->setTexture(); } + bool set_material_color(void* assetManager, EntityId asset, const char* meshName, int materialIndex, const float r, const float g, const float b, const float a) { + return ((AssetManager*)assetManager)->setMaterialColor(asset, meshName, materialIndex, r, g, b, a); + } + FLUTTER_PLUGIN_EXPORT void transform_to_unit_cube(void* assetManager, EntityId asset) { ((AssetManager*)assetManager)->transformToUnitCube(asset); } diff --git a/lib/filament_controller.dart b/lib/filament_controller.dart index dca93c3d..28811e32 100644 --- a/lib/filament_controller.dart +++ b/lib/filament_controller.dart @@ -260,13 +260,12 @@ class FilamentController { /// void setMorphAnimationData( FilamentEntity asset, MorphAnimationData animation) async { - print("SETTING animation with ${animation.data}"); await _channel.invokeMethod("setMorphAnimation", [ _assetManager, asset, animation.meshName, animation.data, - animation.morphIndices, + animation.animatedMorphIndices, animation.numMorphTargets, animation.numFrames, animation.frameLengthInMs @@ -402,6 +401,22 @@ class FilamentController { await _channel.invokeMethod("setTexture", [_assetManager, asset]); } + void setMaterialColor(FilamentEntity asset, String meshName, + int materialIndex, Color color) async { + await _channel.invokeMethod("setMaterialColor", [ + _assetManager, + asset, + meshName, + materialIndex, + [ + color.red.toDouble() / 255.0, + color.green.toDouble() / 255.0, + color.blue.toDouble() / 255.0, + color.alpha.toDouble() / 255.0 + ] + ]); + } + void transformToUnitCube(FilamentEntity asset) async { await _channel.invokeMethod("transformToUnitCube", [_assetManager, asset]); }