2#include "ExtensionRegistry.h"
3#include "Systems/Core/TransformSystem.h"
4#include "Resources/DataFetcherManager.h"
5#include "Resources/MaterialManager.h"
6#include "Resources/TextureManager.h"
7#include "Services/Time.h"
9#include "Foundation/Logging/Logger.h"
11#include "Rendering/ICapabilities.h"
12#include "Rendering/IGraphicsDevice.h"
14#include "Image360System.h"
18 using namespace Cogs::Core::Image360;
24 renderer->releaseRenderingResources(data.rendererData);
26 assert(data.state == Image360Data::State::Uninitialized);
31 system = ExtensionRegistry::getExtensionSystem<Image360System>(context);
40 LOG_DEBUG(logger,
"[instance=%u] Failed to lookup instance.", instanceId);
46 assert(data.state == Image360Data::State::Uninitialized);
49 if (data.source.empty())
return;
51 data.config.instanceId = system->instanceCounter++;
52 if (data.config.instanceId == 0) {
53 data.config.instanceId = system->instanceCounter++;
56 auto handler = [context, instanceId = data.config.instanceId](std::unique_ptr<Cogs::FileContents> contents)
58 auto task = [context, instanceId, contents = contents.release()]
63 if (!lookupAndCheckForStaleness(context, system, comp, data, instanceId)) {
64 LOG_WARNING(logger,
"Ignoring stale json file");
66 else if(data->state != Image360Data::State::WaitingForJson) {
67 LOG_WARNING(logger,
"Ignoring unexpected json file");
70 LOG_ERROR(logger,
"Failed to fetch json file");
71 data->state = Image360Data::State::Error;
73 else if (!data->config.parseConfigJson(contents)) {
74 LOG_ERROR(logger,
"Failed to parse json file (source=%.*s)", StringViewFormat(contents->origin()));
75 data->state = Image360Data::State::Error;
78 LOG_DEBUG(logger,
"json file parsed successfully (source=%.*s)", StringViewFormat(contents->origin()));
79 data->state = Image360Data::State::JsonParsed;
82 context->
engine->setDirty();
84 context->
engine->runTaskInMainThread(std::move(task));
87 LOG_DEBUG(logger,
"Fetching json %s", data.source.c_str());
88 data.state = Image360Data::State::WaitingForJson;
89 DataFetcherManager::fetchAsync(context, data.source, handler);
94Cogs::Core::Image360System::~Image360System()
102 if (pool.size() == 0) {
105 material = context->materialManager->loadMaterial(
"Materials/Image360.material");
106 context->materialManager->processLoading();
115 context->
bounds->addBoundsExtension(bounds);
121 LOG_DEBUG(logger,
"First component created, registered image 360 renderer, bounds and raypick extensions");
133 resetComponentData( renderer, im360Data);
136 if (pool.size() == 0) {
145 context->
bounds->removeBoundsExtension(bounds);
154 LOG_DEBUG(logger,
"Last component destroyed, unregistered image 360 renderer, bounds and raypick extensions");
161 base::initialize(context);
166 CpuInstrumentationScope(SCOPE_POTREE,
"Image360System::update");
173 uint32_t cacheMaxCount = 0x8000u >> 3u;
175 if (
const Variable* var = context->
variables->get(
"image360.cacheMaxCount"); !var->isEmpty()) {
176 cacheMaxCount = std::min(cacheMaxCount, uint32_t(std::max(6, var->getInt())));
179 context->
variables->set(
"image360.cacheMaxCount",
int(cacheMaxCount));
183 if (
const Variable* var = context->
variables->get(
"image360.treeMaxSize"); !var->isEmpty()) {
184 treeMaxSize = std::min(treeMaxSize, uint32_t(std::max(6, var->getInt())));
187 context->
variables->set(
"image360.treeMaxSize",
int(treeMaxSize));
190 uint32_t maxConcurrent = 2;
191 if (
const Variable* var = context->
variables->get(
"image360.maxConcurrentRequests"); !var->isEmpty()) {
192 maxConcurrent = uint32_t(std::max(1, var->getInt()));
195 context->
variables->set(
"image360.maxConcurrentRequests",
int(maxConcurrent));
204 im360Data.config.treeMaxSize = treeMaxSize;
207 im360Data.config.cacheMaxCount = 0;
208 im360Data.config.treeMaxSize = 0;
210 im360Data.config.maxConcurrent = maxConcurrent;
212 if (!im360Comp.isVisible()) {
213 if (im360Data.state != Image360Data::State::Uninitialized) {
214 resetComponentData(renderer, im360Data);
215 assert(im360Data.state == Image360Data::State::Uninitialized);
220 if ((im360Data.valueChannel != im360Comp.valueChannel) ||
221 (im360Data.hasDepth != im360Comp.hasDepth) ||
222 (im360Data.source != im360Comp.source))
224 if (im360Data.state != Image360Data::State::Uninitialized) {
225 resetComponentData(renderer, im360Data);
226 assert(im360Data.state == Image360Data::State::Uninitialized);
228 im360Data.valueChannel = im360Comp.valueChannel;
229 im360Data.hasDepth = im360Comp.hasDepth;
230 im360Data.source = im360Comp.source;
231 issueFetchJson(context,
this, im360Comp, im360Data);
235 if (im360Comp.hasChanged()) {
238 im360Data.materialInstance->setVariant(
"DebugColors", im360Comp.debugColors);
239 im360Data.materialInstance->setVariant(
"DebugDepth", im360Comp.debugDepth);
243 const uint32_t currentFrame = context->
time->getFrame();
244 im360Data.fetcher.processLoadItems(context, im360Comp, im360Data.cache, im360Data.config, currentFrame);
246 if (im360Data.state == Image360Data::State::JsonParsed) {
248 im360Data.materialInstance = context->materialInstanceManager->createMaterialInstance(material);
249 im360Data.materialInstance->setVariant(
"DebugColors", im360Comp.debugColors);
250 im360Data.materialInstance->setVariant(
"TreeDepth",
int(im360Data.config.
treeDepth));
252 im360Data.materialInstance->setVariant(
"HasGradient",
HandleIsValid(im360Comp.gradient));
255 im360Data.config.
valueChannel = im360Comp.valueChannel < im360Data.config.
channels.size() ? uint8_t(im360Comp.valueChannel) : 0;
258 case Config::Channel::DataType::SRGB8_JPEG: [[fallthrough]];
259 case Config::Channel::DataType::SRGB8_PNG:
260 im360Data.materialInstance->setVariant(
"ValueType",
"srgb");
262 case Config::Channel::DataType::SRGBA8_PNG:
263 im360Data.materialInstance->setVariant(
"ValueType",
"srgb");
265 case Config::Channel::DataType::U16: [[fallthrough]];
266 case Config::Channel::DataType::U16_ZST:
267 im360Data.materialInstance->setVariant(
"ValueType",
"uint");
276 im360Data.materialInstance->setVariant(
"HasDepth",
true);
277 im360Data.materialInstance->setVariant(
"DiscardNoDepth", im360Data.config.
discardNoDepth);
278 im360Data.materialInstance->setVariant(
"DebugDepth", im360Comp.debugDepth);
282 im360Data.materialInstance->setVariant(
"HasDepth",
false);
285 im360Data.cache.init(im360Data.config);
286 im360Data.state = Image360Data::State::WaitingForBaseLevel;
289 if (im360Data.state == Image360Data::State::WaitingForBaseLevel) {
291 for (
size_t i = 0; i < 6; i++) {
292 if (im360Data.cache.isQuadInCache(context, im360Data.fetcher, im360Comp, im360Data.config, currentFrame, 0, i) < 0) {
297 LOG_DEBUG(logger,
"Base level in cache");
299 im360Data.state = Image360Data::State::Running;
304 if (im360Data.state == Image360Data::State::Running && !im360Comp.disableLodUpdates) {
305 im360Data.lodTree.update(context, im360Data.rendererData, im360Data.fetcher, im360Data.cache, im360Comp, im360Data.config, currentFrame, im360Comp);
306 im360Data.cache.updateLeastRecentlyUsedList(currentFrame);
virtual ComponentHandle createComponent()
Create a new component instance.
virtual void destroyComponent(ComponentHandle)
Destroy the component held by the given handle.
void update()
Updates the system state to that of the current frame.
ComponentPool< ComponentType > pool
Pool of components managed by the system.
A Context instance contains all the services, systems and runtime components needed to use Cogs.
class IRenderer * renderer
Renderer.
std::unique_ptr< class Bounds > bounds
Bounds service instance.
std::unique_ptr< class RayPicking > rayPicking
RayPicking service instance.
std::unique_ptr< class Variables > variables
Variables service instance.
std::unique_ptr< class Time > time
Time service instance.
std::unique_ptr< class Engine > engine
Engine instance.
virtual IGraphicsDevice * getDevice()=0
Get the graphics device used by the renderer.
virtual void registerExtension(IRendererExtension *extension)=0
Register an extension with the renderer.
virtual void unregisterExtension(IRendererExtension *extension)=0
Unregister an extension with the renderer.
virtual ICapabilities * getCapabilities()=0
Get a pointer to the capability management interface used to query the graphics device capability fla...
Log implementation class.
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
@ Ready
All 6 baselayers are fully loaded, instance will begin rendering.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Handle to a Component instance.
COGSFOUNDATION_API class Component * resolve() const
Resolve the handle, returning a pointer to the held Component instance.
std::string source
URL of json describing image pyramid.
void initialize(Context *context) override
Initialize the system.
ComponentHandle createComponent() override
void destroyComponent(ComponentHandle component) override
uint32_t instanceId
Component instance id.
uint32_t baseSize
Base image size of a cached tile. From json.
uint8_t valueChannel
Data channel to be used as value data. From component.
uint32_t treeDepth
Depth of tile hierarchy. From json.
uint8_t depthChannel
Data channel that contains depth data. From json.
std::vector< Channel > channels
Data channels to use. From json.
bool discardNoDepth
Discard pixels with no depth data.
bool hasDepth
If data has depth and component wants depth.
void setTextureProperty(const StringView &key, TextureHandle value)
Set the texture property with the given key to the texture resource held by value.
MaterialOptions options
Material rendering options used by this instance.
bool depthTestEnabled
If depth testing should be enabled rendering the geometry with the material instance.
static const ResourceHandle_t NoHandle
Handle representing a default (or none if default not present) resource.
Runtime control variable.
Contains device capabilities.
uint32_t MaxTexture2DSize
Using D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION as default.
uint32_t MaxTextureArrayLayers
Using D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION as default.
virtual const GraphicsDeviceCapabilities & getDeviceCapabilities() const
Gets the device capabilities in a structure.