From b80680fe4dcd538b0e292b65c5c8897639d32895 Mon Sep 17 00:00:00 2001 From: Martin Gerhardy Date: Sat, 12 Sep 2020 19:35:58 +0200 Subject: [PATCH] VOXELWORLDRENDER: prepare to readd plant support --- .../flower001.qb => models/plants/1.qb} | Bin .../flower002.qb => models/plants/2.qb} | Bin .../flower003.qb => models/plants/3.qb} | Bin .../plant001.qb => models/plants/4.qb} | Bin src/client/Client.cpp | 24 ++++++--- src/client/Client.h | 4 +- src/modules/frontend/ClientEntityRenderer.cpp | 2 +- src/modules/frontend/ClientEntityRenderer.h | 4 +- .../voxelworldrender/AssetVolumeCache.cpp | 51 ++++++++++++++++++ .../voxelworldrender/AssetVolumeCache.h | 42 +++++++++++++++ src/modules/voxelworldrender/CMakeLists.txt | 6 +++ .../voxelworldrender/WorldRenderer.cpp | 14 +++-- src/modules/voxelworldrender/WorldRenderer.h | 6 ++- src/tools/mapview/MapView.cpp | 24 ++++++--- src/tools/mapview/MapView.h | 5 +- 15 files changed, 159 insertions(+), 23 deletions(-) rename data/voxel/{assets/flower001.qb => models/plants/1.qb} (100%) rename data/voxel/{assets/flower002.qb => models/plants/2.qb} (100%) rename data/voxel/{assets/flower003.qb => models/plants/3.qb} (100%) rename data/voxel/{assets/plant001.qb => models/plants/4.qb} (100%) create mode 100644 src/modules/voxelworldrender/AssetVolumeCache.cpp create mode 100644 src/modules/voxelworldrender/AssetVolumeCache.h diff --git a/data/voxel/assets/flower001.qb b/data/voxel/models/plants/1.qb similarity index 100% rename from data/voxel/assets/flower001.qb rename to data/voxel/models/plants/1.qb diff --git a/data/voxel/assets/flower002.qb b/data/voxel/models/plants/2.qb similarity index 100% rename from data/voxel/assets/flower002.qb rename to data/voxel/models/plants/2.qb diff --git a/data/voxel/assets/flower003.qb b/data/voxel/models/plants/3.qb similarity index 100% rename from data/voxel/assets/flower003.qb rename to data/voxel/models/plants/3.qb diff --git a/data/voxel/assets/plant001.qb b/data/voxel/models/plants/4.qb similarity index 100% rename from data/voxel/assets/plant001.qb rename to data/voxel/models/plants/4.qb diff --git a/src/client/Client.cpp b/src/client/Client.cpp index 481c414e6..284e9853a 100644 --- a/src/client/Client.cpp +++ b/src/client/Client.cpp @@ -48,11 +48,13 @@ Client::Client(const metric::MetricPtr& metric, const animation::AnimationCacheP const video::TexturePoolPtr& texturePool, const voxelrender::CachedMeshRendererPtr& meshRenderer, const video::TextureAtlasRendererPtr& textureAtlasRenderer, - const audio::SoundManagerPtr& soundManager) : - Super(metric, filesystem, eventBus, timeProvider, texturePool, meshRenderer, textureAtlasRenderer), _animationCache(animationCache), - _network(network), _worldMgr(world), _clientPager(worldPager), _messageSender(messageSender), _movement(soundManager), - _stockDataProvider(stockDataProvider), _volumeCache(volumeCache), - _meshCache(meshCache), _camera(_worldRenderer), _soundManager(soundManager) { + const audio::SoundManagerPtr& soundManager, + const voxelworldrender::AssetVolumeCachePtr& assetVolumeCache) : + Super(metric, filesystem, eventBus, timeProvider, texturePool, meshRenderer, textureAtlasRenderer), + _animationCache(animationCache), _network(network), _worldMgr(world), _clientPager(worldPager), + _messageSender(messageSender), _worldRenderer(assetVolumeCache), _movement(soundManager), + _stockDataProvider(stockDataProvider), _volumeCache(volumeCache), _meshCache(meshCache), + _camera(_worldRenderer), _soundManager(soundManager) { init(ORGANISATION, "client"); } @@ -124,6 +126,7 @@ app::AppState Client::onConstruct() { _action.construct(); _camera.construct(); _meshCache->construct(); + _assetVolumeCache->construct(); core::Var::get(cfg::ClientPort, SERVER_PORT, "Server port"); core::Var::get(cfg::ClientHost, SERVER_HOST, "Server hostname or ip"); @@ -229,6 +232,11 @@ app::AppState Client::onInit() { return app::AppState::InitFailure; } + if (!_assetVolumeCache->init()) { + Log::error("Failed to init asset volume cache"); + return app::AppState::InitFailure; + } + if (!_worldMgr->init()) { Log::error("Failed to initialize world manager"); return app::AppState::InitFailure; @@ -345,7 +353,8 @@ app::AppState Client::onCleanup() { _action.shutdown(); _camera.shutdown(); _meshCache->shutdown(); - Log::info("shutting down the volume cache"); + Log::info("shutting down the volume caches"); + _assetVolumeCache->shutdown(); _volumeCache->shutdown(); compute::shutdown(); Log::info("everything was shut down"); @@ -451,8 +460,9 @@ int main(int argc, char *argv[]) { const stock::StockDataProviderPtr& stockDataProvider = std::make_shared(); const video::TexturePoolPtr& texturePool = std::make_shared(filesystem); const audio::SoundManagerPtr& soundMgr = core::make_shared(filesystem); + const voxelworldrender::AssetVolumeCachePtr& assetVolumeCache = core::make_shared(volumeCache); Client app(metric, animationCache, stockDataProvider, network, world, pager, messageSender, eventBus, timeProvider, filesystem, volumeCache, meshCache, texturePool, meshRenderer, textureAtlasRenderer, - soundMgr); + soundMgr, assetVolumeCache); return app.startMainLoop(argc, argv); } diff --git a/src/client/Client.h b/src/client/Client.h index 911755d37..70e809907 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -54,6 +54,7 @@ protected: voxelformat::MeshCachePtr _meshCache; voxelworldrender::PlayerCamera _camera; audio::SoundManagerPtr _soundManager; + voxelworldrender::AssetVolumeCachePtr _assetVolumeCache; frontend::ClientEntityId id() const; @@ -78,7 +79,8 @@ public: const video::TexturePoolPtr& texturePool, const voxelrender::CachedMeshRendererPtr& meshRenderer, const video::TextureAtlasRendererPtr& textureAtlasRenderer, - const audio::SoundManagerPtr& soundManager); + const audio::SoundManagerPtr& soundManager, + const voxelworldrender::AssetVolumeCachePtr& assetVolumeCache); ~Client(); app::AppState onConstruct() override; diff --git a/src/modules/frontend/ClientEntityRenderer.cpp b/src/modules/frontend/ClientEntityRenderer.cpp index 9bb3e646c..a1ed08900 100644 --- a/src/modules/frontend/ClientEntityRenderer.cpp +++ b/src/modules/frontend/ClientEntityRenderer.cpp @@ -86,7 +86,7 @@ void ClientEntityRenderer::shutdown() { _animationSystem.shutdown(); } -void ClientEntityRenderer::update(const glm::vec3& focusPos, float seconds) { +void ClientEntityRenderer::update(const glm::vec3& focusPos, double seconds) { _focusPos = focusPos; _seconds = seconds; } diff --git a/src/modules/frontend/ClientEntityRenderer.h b/src/modules/frontend/ClientEntityRenderer.h index cdd129196..c3fe25764 100644 --- a/src/modules/frontend/ClientEntityRenderer.h +++ b/src/modules/frontend/ClientEntityRenderer.h @@ -39,7 +39,7 @@ private: float _viewDistance = 0.0f; float _fogRange = 0.0f; - float _seconds = 0.0f; + double _seconds = 0.0; glm::vec3 _focusPos { 0.0f }; @@ -52,7 +52,7 @@ public: bool init() override; void shutdown() override; - void update(const glm::vec3& focusPos, float seconds); + void update(const glm::vec3& focusPos, double seconds); void bindEntitiesDepthBuffer(video::TextureUnit texunit); diff --git a/src/modules/voxelworldrender/AssetVolumeCache.cpp b/src/modules/voxelworldrender/AssetVolumeCache.cpp new file mode 100644 index 000000000..fdf222a27 --- /dev/null +++ b/src/modules/voxelworldrender/AssetVolumeCache.cpp @@ -0,0 +1,51 @@ +/** + * @file + */ + +#include "AssetVolumeCache.h" +#include "app/App.h" +#include "core/Log.h" +#include "core/StringUtil.h" +#include "voxelformat/VolumeFormat.h" +#include "io/Filesystem.h" +#include +#include + +namespace voxelworldrender { + +AssetVolumeCache::AssetVolumeCache(const voxelformat::VolumeCachePtr& volumeCache) : + _volumeCache(volumeCache) { +} + +bool AssetVolumeCache::init() { + Log::debug("Initialize the asset volume cache"); + for (const char **ext = voxelformat::SUPPORTED_VOXEL_FORMATS_LOAD_LIST; *ext; ++ext) { + core::DynamicArray files; + if (!io::filesystem()->list("models/plants/", files, core::string::format("*.%s", *ext))) { + Log::warn("Failed to list assets from models/plants/"); + break; + } + _plantCount += (int)files.size(); + } + Log::debug("Found %i plants", _plantCount); + return true; +} + +void AssetVolumeCache::shutdown() { + _volumeCache = voxelformat::VolumeCachePtr(); +} + +voxel::RawVolume* AssetVolumeCache::loadPlant(const glm::ivec3& pos) { + if (_plantCount <= 0) { + return nullptr; + } + const int index = 1 + (glm::abs(pos.x + pos.z) % _plantCount); + char filename[64]; + if (!core::string::formatBuf(filename, sizeof(filename), "models/plants/%i", index)) { + Log::error("Failed to assemble plant path"); + return nullptr; + } + return _volumeCache->loadVolume(filename); +} + +} diff --git a/src/modules/voxelworldrender/AssetVolumeCache.h b/src/modules/voxelworldrender/AssetVolumeCache.h new file mode 100644 index 000000000..647217a70 --- /dev/null +++ b/src/modules/voxelworldrender/AssetVolumeCache.h @@ -0,0 +1,42 @@ +/** + * @file + */ + +#pragma once + +#include "core/IComponent.h" +#include "core/SharedPtr.h" +#include "voxelformat/VolumeCache.h" +#include "core/collection/StringMap.h" +#include + +namespace voxelworldrender { + +/** + * @brief This cache is for volume models that are not part of the world volumes. + * They can be used to only render them (e.g. plants) or to let the player interact + * with them (e.g. a chest entity) + * @sa voxelworld::TreeVolumeCache + */ +class AssetVolumeCache : public core::IComponent { +private: + voxelformat::VolumeCachePtr _volumeCache; + int _plantCount = 0; +public: + AssetVolumeCache(const voxelformat::VolumeCachePtr& volumeCache); + + bool init() override; + void shutdown() override; + + /** + * @brief Ensure that the same volume is returned for the same input parameters. + * @param[in] pos world position + * @return voxel::RawVolume or @c nullptr if no suitable plant was found. + * @note Plants are stored by index in @c models/plants/ + */ + voxel::RawVolume* loadPlant(const glm::ivec3& pos); +}; + +typedef core::SharedPtr AssetVolumeCachePtr; + +} diff --git a/src/modules/voxelworldrender/CMakeLists.txt b/src/modules/voxelworldrender/CMakeLists.txt index bfb332484..feeea9cd2 100644 --- a/src/modules/voxelworldrender/CMakeLists.txt +++ b/src/modules/voxelworldrender/CMakeLists.txt @@ -1,6 +1,7 @@ set(LIB voxelworldrender) set(SRCS WorldRenderer.h WorldRenderer.cpp + AssetVolumeCache.h AssetVolumeCache.cpp PlayerCamera.cpp PlayerCamera.h worldrenderer/WorldChunkMgr.h worldrenderer/WorldChunkMgr.cpp @@ -21,6 +22,11 @@ set(FILES sky/sky_up.png shared/water-distortion.png shared/water-normal.png + + voxel/models/plants/1.qb + voxel/models/plants/2.qb + voxel/models/plants/3.qb + voxel/models/plants/4.qb ) engine_add_module(TARGET ${LIB} SRCS ${SRCS} ${SRCS_SHADERS} FILES ${FILES} DEPENDENCIES frontend voxelrender) generate_shaders(${LIB} world water postprocess) diff --git a/src/modules/voxelworldrender/WorldRenderer.cpp b/src/modules/voxelworldrender/WorldRenderer.cpp index b55ae8f24..01a768f1f 100644 --- a/src/modules/voxelworldrender/WorldRenderer.cpp +++ b/src/modules/voxelworldrender/WorldRenderer.cpp @@ -43,8 +43,9 @@ alignas(16) static constexpr glm::vec2 waterPlaneVecs[] = { { -1.0f, 1.0f} }; -WorldRenderer::WorldRenderer() : - _threadPool(1, "WorldRenderer"), _worldChunkMgr(_threadPool), _shadowMapShader(shader::ShadowmapShader::getInstance()) { +WorldRenderer::WorldRenderer(const AssetVolumeCachePtr& assetVolumeCache) : + _threadPool(1, "WorldRenderer"), _worldChunkMgr(_threadPool), _assetVolumeCache(assetVolumeCache), + _shadowMapShader(shader::ShadowmapShader::getInstance()) { setViewDistance(800.0f); } @@ -239,7 +240,7 @@ int WorldRenderer::renderTerrain(const glm::mat4& viewProjectionMatrix, const gl } _worldShader.setFocuspos(_focusPos); _worldShader.setLightdir(_shadow.sunDirection()); - _worldShader.setTime(_seconds); + _worldShader.setTime((float)_seconds); _worldShader.setFogrange(_fogRange); _worldShader.setClipplane(clipPlane); _worldShader.setViewprojection(viewProjectionMatrix); @@ -314,6 +315,7 @@ int WorldRenderer::renderAll(const video::Camera& camera) { const glm::mat4& vpmat = camera.viewProjectionMatrix(); drawCallsWorld += renderTerrain(vpmat, ignoreClipPlane); drawCallsWorld += renderEntities(vpmat, ignoreClipPlane); + drawCallsWorld += renderPlants(vpmat, ignoreClipPlane); drawCallsWorld += renderEntityDetails(camera); drawCallsWorld += renderWater(camera, ignoreClipPlane); _skybox.render(camera); @@ -324,6 +326,12 @@ int WorldRenderer::renderEntitiesToDepthMap(const video::Camera& camera) { return _entityRenderer.renderEntitiesToDepthMap(_entityMgr.visibleEntities(), camera.viewProjectionMatrix()); } +int WorldRenderer::renderPlants(const glm::mat4& viewProjectionMatrix, const glm::vec4& clipPlane) { + // TODO: instanced volume rendering + // place plants to chunk in WorldChunkMgr and use the positions for the instanced rendering here. + return 0; +} + int WorldRenderer::renderEntities(const glm::mat4& viewProjectionMatrix, const glm::vec4& clipPlane) { return _entityRenderer.renderEntities(_entityMgr.visibleEntities(), viewProjectionMatrix, clipPlane, _shadow); } diff --git a/src/modules/voxelworldrender/WorldRenderer.h b/src/modules/voxelworldrender/WorldRenderer.h index 948a4a786..8d07e7520 100644 --- a/src/modules/voxelworldrender/WorldRenderer.h +++ b/src/modules/voxelworldrender/WorldRenderer.h @@ -7,6 +7,7 @@ #include "RenderShaders.h" #include "AnimationShaders.h" #include "VoxelworldrenderShaders.h" +#include "voxelworldrender/AssetVolumeCache.h" #include "worldrenderer/WorldChunkMgr.h" #include "core/Color.h" #include "core/GLM.h" @@ -46,6 +47,7 @@ protected: video::TexturePtr _normalTexture; render::Skybox _skybox; frontend::ClientEntityRenderer _entityRenderer; + AssetVolumeCachePtr _assetVolumeCache; video::FrameBuffer _frameBuffer; video::FrameBuffer _reflectionBuffer; @@ -92,9 +94,9 @@ protected: int renderAll(const video::Camera& camera); int renderTerrain(const glm::mat4& viewProjectionMatrix, const glm::vec4& clipPlane); int renderEntities(const glm::mat4& viewProjectionMatrix, const glm::vec4& clipPlane); + int renderPlants(const glm::mat4& viewProjectionMatrix, const glm::vec4& clipPlane); int renderEntityDetails(const video::Camera& camera); int renderWater(const video::Camera& camera, const glm::vec4& clipPlane); - /** * @brief 2-pass render of the reflection and the refraction buffers */ @@ -104,7 +106,7 @@ protected: */ int renderPostProcessEffects(const video::Camera& camera); public: - WorldRenderer(); + WorldRenderer(const AssetVolumeCachePtr& assetVolumeCache); ~WorldRenderer(); void reset(); diff --git a/src/tools/mapview/MapView.cpp b/src/tools/mapview/MapView.cpp index 628978d37..1dc3096e4 100644 --- a/src/tools/mapview/MapView.cpp +++ b/src/tools/mapview/MapView.cpp @@ -23,6 +23,7 @@ #include "attrib/Attributes.h" #include "attrib/ContainerProvider.h" #include "audio/SoundManager.h" +#include "voxelworldrender/AssetVolumeCache.h" #include #define GLM_ENABLE_EXPERIMENTAL #include @@ -35,11 +36,13 @@ MapView::MapView(const metric::MetricPtr& metric, const animation::AnimationCach const voxelworld::WorldPagerPtr& worldPager, const voxelformat::VolumeCachePtr& volumeCache, const voxelformat::MeshCachePtr& meshCache, - const audio::SoundManagerPtr& soundManager) : + const audio::SoundManagerPtr& soundManager, + const voxelworldrender::AssetVolumeCachePtr& assetVolumeCache) : Super(metric, filesystem, eventBus, timeProvider), - _animationCache(animationCache), _worldMgr(worldMgr), _worldPager(worldPager), _movement(soundManager), - _stockDataProvider(stockDataProvider), _volumeCache(volumeCache), _meshCache(meshCache), - _camera(_worldRenderer), _soundManager(soundManager) { + _animationCache(animationCache), _worldRenderer(assetVolumeCache), _worldMgr(worldMgr), + _worldPager(worldPager), _movement(soundManager), _stockDataProvider(stockDataProvider), + _volumeCache(volumeCache), _meshCache(meshCache), _camera(_worldRenderer), + _soundManager(soundManager), _assetVolumeCache(assetVolumeCache) { init(ORGANISATION, "mapview"); } @@ -51,6 +54,8 @@ app::AppState MapView::onConstruct() { _rotationSpeed = core::Var::getSafe(cfg::ClientMouseRotationSpeed); + _assetVolumeCache->construct(); + _movement.construct(); _action.construct(); _camera.construct(); @@ -107,6 +112,11 @@ app::AppState MapView::onInit() { return app::AppState::InitFailure; } + if (!_assetVolumeCache->init()) { + Log::error("Failed to init asset volume cache"); + return app::AppState::InitFailure; + } + if (!_movement.init()) { Log::error("Failed to init movement"); return app::AppState::InitFailure; @@ -192,7 +202,7 @@ bool MapView::changeEntityType(const glm::vec3& pos, const network::EntityType e attrib::Attributes attributes; attributes.add(attribContainer); attributes.update(0l); - const float speed = attributes.max(attrib::Type::SPEED); + const double speed = attributes.max(attrib::Type::SPEED); _entity->attrib().setCurrent(attrib::Type::SPEED, speed); _worldRenderer.entityMgr().removeEntity(_entity->id()); if (!_worldRenderer.entityMgr().addEntity(_entity)) { @@ -421,6 +431,7 @@ app::AppState MapView::onCleanup() { _stockDataProvider->shutdown(); _animationCache->shutdown(); _worldRenderer.shutdown(); + _assetVolumeCache->shutdown(); _volumeCache->shutdown(); _depthBufferRenderer.shutdown(); _axis.shutdown(); @@ -462,7 +473,8 @@ int main(int argc, char *argv[]) { const metric::MetricPtr& metric = std::make_shared(); const stock::StockDataProviderPtr& stockDataProvider = std::make_shared(); const audio::SoundManagerPtr& soundMgr = core::make_shared(filesystem); + const voxelworldrender::AssetVolumeCachePtr& assetVolumeCache = core::make_shared(volumeCache); MapView app(metric, animationCache, stockDataProvider, filesystem, eventBus, timeProvider, - worldMgr, worldPager, volumeCache, meshCache, soundMgr); + worldMgr, worldPager, volumeCache, meshCache, soundMgr, assetVolumeCache); return app.startMainLoop(argc, argv); } diff --git a/src/tools/mapview/MapView.h b/src/tools/mapview/MapView.h index 0f18f457a..9fd0be583 100644 --- a/src/tools/mapview/MapView.h +++ b/src/tools/mapview/MapView.h @@ -6,6 +6,7 @@ #include "ui/imgui/IMGUIApp.h" #include "RenderShaders.h" +#include "voxelworldrender/AssetVolumeCache.h" #include "voxelworldrender/WorldRenderer.h" #include "voxelworldrender/PlayerCamera.h" #include "frontend/ClientEntity.h" @@ -48,6 +49,7 @@ protected: testcore::DepthBufferRenderer _depthBufferRenderer; voxelworld::CachedFloorResolver _floorResolver; audio::SoundManagerPtr _soundManager; + voxelworldrender::AssetVolumeCachePtr _assetVolumeCache; bool _lineModeRendering = false; bool _freelook = false; @@ -80,7 +82,8 @@ public: const voxelworld::WorldPagerPtr& worldPager, const voxelformat::VolumeCachePtr& volumeCache, const voxelformat::MeshCachePtr& meshCache, - const audio::SoundManagerPtr& soundManager); + const audio::SoundManagerPtr& soundManager, + const voxelworldrender::AssetVolumeCachePtr& assetVolumeCache); ~MapView(); app::AppState onConstruct() override;