From ea75d552b731d34351c2dfad3f8ab9774e6d11ef Mon Sep 17 00:00:00 2001 From: Adrien4193 Date: Tue, 4 Jun 2024 15:41:40 +0200 Subject: [PATCH 1/7] Checkpoint. --- src/brayns/core/enginev2/Camera.cpp | 37 ++-- src/brayns/core/enginev2/Camera.h | 42 ++-- src/brayns/core/enginev2/Data.h | 37 +++- src/brayns/core/enginev2/Device.cpp | 45 ++++ src/brayns/core/enginev2/Device.h | 6 + src/brayns/core/enginev2/Engine.cpp | 88 -------- src/brayns/core/enginev2/Engine.h | 56 ----- src/brayns/core/enginev2/Framebuffer.cpp | 24 ++- src/brayns/core/enginev2/Framebuffer.h | 30 ++- src/brayns/core/enginev2/GeometricModel.cpp | 120 +++++++++++ src/brayns/core/enginev2/GeometricModel.h | 78 +++++++ src/brayns/core/enginev2/Geometry.cpp | 214 +++++++++++++------- src/brayns/core/enginev2/Geometry.h | 155 ++++++++------ src/brayns/core/enginev2/Light.h | 6 +- src/brayns/core/enginev2/Managed.h | 154 -------------- src/brayns/core/enginev2/Material.h | 6 +- src/brayns/core/enginev2/Object.h | 164 +++++++++++++++ src/brayns/core/enginev2/Render.h | 6 +- src/brayns/core/enginev2/Renderer.h | 6 +- src/brayns/core/enginev2/Volume.h | 14 +- src/brayns/core/enginev2/World.h | 20 +- src/brayns/core/utils/Math.h | 32 ++- 22 files changed, 810 insertions(+), 530 deletions(-) delete mode 100644 src/brayns/core/enginev2/Engine.cpp delete mode 100644 src/brayns/core/enginev2/Engine.h create mode 100644 src/brayns/core/enginev2/GeometricModel.cpp create mode 100644 src/brayns/core/enginev2/GeometricModel.h delete mode 100644 src/brayns/core/enginev2/Managed.h create mode 100644 src/brayns/core/enginev2/Object.h diff --git a/src/brayns/core/enginev2/Camera.cpp b/src/brayns/core/enginev2/Camera.cpp index f7815b00d..43cb09163 100644 --- a/src/brayns/core/enginev2/Camera.cpp +++ b/src/brayns/core/enginev2/Camera.cpp @@ -21,35 +21,34 @@ #include "Camera.h" -namespace brayns::experimental -{ -void Camera::setTransform(const Affine3 &transform) +namespace { - setParam("transform", transform); -} +using namespace brayns::experimental; -void Camera::setNearClip(float distance) +void loadCameraParams(OSPCamera handle, const CameraSettings &settings) { - setParam("nearClip", distance); + setObjectParam(handle, "position", settings.position); + setObjectParam(handle, "direction", settings.direction); + setObjectParam(handle, "up", settings.up); + setObjectParam(handle, "nearClip", settings.nearClippingDistance); } - -void PerspectiveCamera::setFovy(float degrees) -{ - setParam("fovy", degrees); } -void PerspectiveCamera::setAspectRatio(float aspect) +namespace brayns::experimental { - setParam("aspect", aspect); -} - -void OrthographicCamera::setHeight(float height) +void loadPerspectiveCameraParams(OSPCamera handle, const PerspectiveCameraSettings &settings) { - setParam("height", height); + loadCameraParams(handle, settings); + setObjectParam(handle, "fovy", settings.fovy); + setObjectParam(handle, "aspect", settings.aspectRatio); + commitObject(handle); } -void OrthographicCamera::setAspectRatio(float aspect) +void loadOrthographicCameraParams(OSPCamera handle, const OrthographicCameraSettings &settings) { - setParam("aspect", aspect); + loadCameraParams(handle, settings); + setObjectParam(handle, "height", settings.height); + setObjectParam(handle, "aspect", settings.aspectRatio); + commitObject(handle); } } diff --git a/src/brayns/core/enginev2/Camera.h b/src/brayns/core/enginev2/Camera.h index 461fca25c..aa3c44f54 100644 --- a/src/brayns/core/enginev2/Camera.h +++ b/src/brayns/core/enginev2/Camera.h @@ -21,45 +21,49 @@ #pragma once -#include "Managed.h" +#include "Object.h" namespace brayns::experimental { +struct CameraSettings +{ + Vector3 position = {0.0f, 0.0f, 0.0f}; + Vector3 direction = {0.0f, 0.0f, 1.0f}; + Vector3 up = {0.0f, 1.0f, 0.0f}; + float nearClippingDistance = 1.0e-6F; +}; + class Camera : public Managed { public: using Managed::Managed; +}; - void setTransform(const Affine3 &transform); - void setNearClip(float distance); +struct PerspectiveCameraSettings : CameraSettings +{ + float fovy = 60.0f; + float aspectRatio = 1.0f; }; class PerspectiveCamera : public Camera { public: - static inline const std::string name = "perspective"; - using Camera::Camera; +}; + +void loadPerspectiveCameraParams(OSPCamera handle, const PerspectiveCameraSettings &settings); - void setFovy(float degrees); - void setAspectRatio(float aspect); +struct OrthographicCameraSettings : CameraSettings +{ + float height = 1.0f; + float aspectRatio = 1.0f; }; +void loadOrthographicCameraParams(OSPCamera handle, const OrthographicCameraSettings &settings); + class OrthographicCamera : public Camera { public: - static inline const std::string name = "orthographic"; - using Camera::Camera; - - void setHeight(float height); - void setAspectRatio(float aspect); }; } - -namespace ospray -{ -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::Camera, OSP_CAMERA) -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::PerspectiveCamera, OSP_CAMERA) -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::OrthographicCamera, OSP_CAMERA) -} diff --git a/src/brayns/core/enginev2/Data.h b/src/brayns/core/enginev2/Data.h index fca481824..07718f834 100644 --- a/src/brayns/core/enginev2/Data.h +++ b/src/brayns/core/enginev2/Data.h @@ -23,16 +23,39 @@ #include -#include +#include "Object.h" namespace brayns::experimental { -template -using SharedArray = std::span; +using DataType = OSPDataType; -template -ospray::cpp::SharedData toSharedData(SharedArray data) +struct DataSettings { - return ospray::cpp::SharedData(data.data(), data.size()); -} + DataType type; + Size3 itemCount; + const void *data; + void (*deleter)(const void *, const void *) = nullptr; +}; + +class Data : public Managed +{ +public: + using Managed::Managed; +}; + +template +class DataND : public Data +{ +public: + using Data::Data; +}; + +template +using Data1D = DataND; + +template +using Data2D = DataND; + +template +using Data3D = DataND; } diff --git a/src/brayns/core/enginev2/Device.cpp b/src/brayns/core/enginev2/Device.cpp index 63af0abe4..e2f5c71fe 100644 --- a/src/brayns/core/enginev2/Device.cpp +++ b/src/brayns/core/enginev2/Device.cpp @@ -85,5 +85,50 @@ RenderTask Device::render(const RenderSettings &settings) void Device::Deleter::operator()(OSPDevice device) const { ospDeviceRelease(device); + ospShutdown(); +} + +Device createDevice(Logger &logger) +{ + auto error = ospLoadModule("cpu"); + + if (error != OSP_NO_ERROR) + { + auto message = fmt::format("Failed to load OSPRay CPU module (code = {})", static_cast(error)); + throw std::runtime_error(message); + } + + auto currentDevice = ospGetCurrentDevice(); + if (currentDevice != nullptr) + { + throw std::invalid_argument("OSPRay only accepts one device created at a time"); + } + + auto device = ospNewDevice(); + + auto logLevel = OSP_LOG_DEBUG; + ospDeviceSetParam(device, "logLevel", OSP_UINT, &logLevel); + + auto warnAsError = true; + ospDeviceSetParam(device, "warnAsError", OSP_BOOL, &warnAsError); + + auto errorCallback = [](auto *userData, auto code, const auto *message) + { + auto &logger = *static_cast(userData); + logger.error("Device error (code = {}): {}", static_cast(code), message); + }; + ospDeviceSetErrorCallback(device, errorCallback, &logger); + + auto statusCallback = [](auto *userData, const auto *message) + { + auto &logger = *static_cast(userData); + logger.debug("Device status: {}", message); + }; + ospDeviceSetStatusCallback(device, statusCallback, &logger); + + ospDeviceCommit(device); + ospSetCurrentDevice(device); + + return Device(device); } } diff --git a/src/brayns/core/enginev2/Device.h b/src/brayns/core/enginev2/Device.h index e29f62db0..e6d114c28 100644 --- a/src/brayns/core/enginev2/Device.h +++ b/src/brayns/core/enginev2/Device.h @@ -43,6 +43,10 @@ class Device public: explicit Device(OSPDevice handle); + OSPDevice getHandle() const; + + Spheres createSpheres(const SphereSettings &settings); + GeometricModel createGeometricModel(); VolumetricModel createVolumetricModel(); Group createGroup(); @@ -123,4 +127,6 @@ class Device std::unique_ptr _handle; }; + +Device createDevice(Logger &logger); } diff --git a/src/brayns/core/enginev2/Engine.cpp b/src/brayns/core/enginev2/Engine.cpp deleted file mode 100644 index 34e89ddd3..000000000 --- a/src/brayns/core/enginev2/Engine.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* Copyright (c) 2015-2024 EPFL/Blue Brain Project - * All rights reserved. Do not distribute without permission. - * - * Responsible Author: adrien.fleury@epfl.ch - * - * This file is part of Brayns - * - * This library is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License version 3.0 as published - * by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - * details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "Engine.h" - -#include - -namespace brayns::experimental -{ -Engine::Loader::~Loader() -{ - ospShutdown(); -} - -Engine::Engine(std::unique_ptr loader): - _loader(std::move(loader)) -{ -} - -Device Engine::createDevice(Logger &logger) -{ - auto currentDevice = ospGetCurrentDevice(); - if (currentDevice != nullptr) - { - throw std::invalid_argument("OSPRay only accepts one device created at a time"); - } - - auto device = ospNewDevice(); - - auto logLevel = OSP_LOG_DEBUG; - ospDeviceSetParam(device, "logLevel", OSP_UINT, &logLevel); - - auto warnAsError = true; - ospDeviceSetParam(device, "warnAsError", OSP_BOOL, &warnAsError); - - auto errorCallback = [](auto *userData, auto code, const auto *message) - { - auto &logger = *static_cast(userData); - logger.error("Device error (code = {}): {}", static_cast(code), message); - }; - ospDeviceSetErrorCallback(device, errorCallback, &logger); - - auto statusCallback = [](auto *userData, const auto *message) - { - auto &logger = *static_cast(userData); - logger.debug("Device status: {}", message); - }; - ospDeviceSetStatusCallback(device, statusCallback, &logger); - - ospDeviceCommit(device); - ospSetCurrentDevice(device); - - return Device(device); -} - -Engine loadEngine() -{ - auto error = ospLoadModule("cpu"); - - if (error != OSP_NO_ERROR) - { - auto message = fmt::format("Failed to load OSPRay CPU module (code = {})", static_cast(error)); - throw std::runtime_error(message); - } - - auto loader = std::make_unique(); - - return Engine(std::move(loader)); -} -} diff --git a/src/brayns/core/enginev2/Engine.h b/src/brayns/core/enginev2/Engine.h deleted file mode 100644 index cc938ea1a..000000000 --- a/src/brayns/core/enginev2/Engine.h +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright (c) 2015-2024 EPFL/Blue Brain Project - * All rights reserved. Do not distribute without permission. - * - * Responsible Author: adrien.fleury@epfl.ch - * - * This file is part of Brayns - * - * This library is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License version 3.0 as published - * by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - * details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#pragma once - -#include - -#include - -#include "Device.h" - -namespace brayns::experimental -{ -class Engine -{ -public: - class Loader - { - public: - Loader() = default; - ~Loader(); - - Loader(const Loader &other) = delete; - Loader(Loader &&other) = delete; - Loader &operator=(const Loader &other) = delete; - Loader &operator=(Loader &&other) = delete; - }; - - explicit Engine(std::unique_ptr loader); - - Device createDevice(Logger &logger); - -private: - std::unique_ptr _loader; -}; - -Engine loadEngine(); -} diff --git a/src/brayns/core/enginev2/Framebuffer.cpp b/src/brayns/core/enginev2/Framebuffer.cpp index 144fcd710..818ce9f06 100644 --- a/src/brayns/core/enginev2/Framebuffer.cpp +++ b/src/brayns/core/enginev2/Framebuffer.cpp @@ -23,6 +23,25 @@ namespace brayns::experimental { +void loadToneMapperParams(OSPImageOperation handle, const ToneMapperSettings &settings) +{ + setObjectParam(handle, "exposure", settings.exposure); + setObjectParam(handle, "contrast", settings.contrast); + setObjectParam(handle, "shoulder", settings.hightlightCompression); + setObjectParam(handle, "midIn", settings.midLevelAnchorInput); + setObjectParam(handle, "midOut", settings.midLevelAnchorOutput); + setObjectParam(handle, "acesColor", settings.aces); +} + +void loadFramebufferParams(OSPFrameBuffer handle, const FramebufferSettings &settings) +{ + if (settings.operations) + { + setObjectParam(handle, "imageOperation", *settings.operations); + } + commitObject(handle); +} + const void *Framebuffer::map(FramebufferChannel channel) { auto handle = getHandle(); @@ -46,9 +65,4 @@ float Framebuffer::getVariance() auto handle = getHandle(); return ospGetVariance(handle); } - -void Framebuffer::setImageOperations(SharedArray operations) -{ - setParam("imageOperation", toSharedData(operations)); -} } diff --git a/src/brayns/core/enginev2/Framebuffer.h b/src/brayns/core/enginev2/Framebuffer.h index 27e462f9e..724a16515 100644 --- a/src/brayns/core/enginev2/Framebuffer.h +++ b/src/brayns/core/enginev2/Framebuffer.h @@ -21,8 +21,10 @@ #pragma once +#include + #include "Data.h" -#include "Managed.h" +#include "Object.h" namespace brayns::experimental { @@ -32,14 +34,25 @@ class ImageOperation : public Managed using Managed::Managed; }; +struct ToneMapperSettings +{ + float exposure = 1.0; + float contrast = 1.6773; + float hightlightCompression = 0.9714; + float midLevelAnchorInput = 0.18; + float midLevelAnchorOutput = 0.18; + float maxHdr = 11.0785; + bool aces = true; +}; + class ToneMapper : public ImageOperation { public: - static inline const std::string name = "tonemapper"; - using ImageOperation::ImageOperation; }; +void loadToneMapperParams(OSPImageOperation handle, const ToneMapperSettings &settings); + enum class FramebufferFormat { Rgba8 = OSP_FB_RGBA8, @@ -66,8 +79,11 @@ struct FramebufferSettings std::size_t height; FramebufferFormat format = FramebufferFormat::Srgba8; std::vector channels = {FramebufferChannel::Color}; + std::optional> operations = std::nullopt; }; +void loadFramebufferParams(OSPFrameBuffer handle, const FramebufferSettings &settings); + class Framebuffer : public Managed { public: @@ -77,13 +93,5 @@ class Framebuffer : public Managed void unmap(const void *data); void resetAccumulation(); float getVariance(); - void setImageOperations(SharedArray operations); }; } - -namespace ospray -{ -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::ImageOperation, OSP_IMAGE_OPERATION) -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::ToneMapper, OSP_IMAGE_OPERATION) -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::Framebuffer, OSP_FRAMEBUFFER) -} diff --git a/src/brayns/core/enginev2/GeometricModel.cpp b/src/brayns/core/enginev2/GeometricModel.cpp new file mode 100644 index 000000000..dfd8c3864 --- /dev/null +++ b/src/brayns/core/enginev2/GeometricModel.cpp @@ -0,0 +1,120 @@ +/* Copyright (c) 2015-2024 EPFL/Blue Brain Project + * All rights reserved. Do not distribute without permission. + * + * Responsible Author: adrien.fleury@epfl.ch + * + * This file is part of Brayns + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "GeometricModel.h" + +namespace +{ +using brayns::Color4; +using namespace brayns::experimental; + +void setMaterialParam(OSPGeometricModel handle, const PrimitiveMaterials &materials) +{ + std::visit([=](const auto &value) { setObjectParam(handle, "material", value); }, materials); +} + +void setColorParam(OSPGeometricModel handle, std::monostate) +{ + removeObjectParam(handle, "color"); +} + +void setColorParam(OSPGeometricModel handle, const Data1D &colors) +{ + setObjectParam(handle, "color", colors); +} + +void setColorParam(OSPGeometricModel handle, const Color4 &color) +{ + setObjectParam(handle, "color", color); +} + +void setColorParams(OSPGeometricModel handle, const PrimitiveColors &colors) +{ + std::visit([&](const auto &value) { setColorParam(handle, value); }, colors); +} + +void setIndicesParam(OSPGeometricModel handle, const MaterialAndColorIndices &indices) +{ + if (!indices) + { + removeObjectParam(handle, "index"); + return; + } + setObjectParam(handle, "index", *indices); +} +} + +namespace brayns::experimental +{ +void loadGeometricModelParams(OSPGeometricModel handle, const GeometricModelSettings &settings) +{ + setObjectParam(handle, "geometry", settings.geometry); + setMaterialParam(handle, settings.materials); + setColorParams(handle, settings.colors); + setIndicesParam(handle, settings.indices); + setObjectParam(handle, "invertNormals", settings.invertedNormals); + setObjectParam(handle, "id", settings.id); + commitObject(handle); +} + +void GeometricModel::setMaterials(const PrimitiveMaterials &materials) +{ + auto handle = getHandle(); + setMaterialParam(handle, materials); + commitObject(handle); +} + +void GeometricModel::setColors(const PrimitiveColors &colors) +{ + auto handle = getHandle(); + setColorParams(handle, colors); + commitObject(handle); +} + +void GeometricModel::setIndices(const MaterialAndColorIndices &indices) +{ + auto handle = getHandle(); + setIndicesParam(handle, indices); + commitObject(handle); +} + +void GeometricModel::invertNormals(bool invert) +{ + auto handle = getHandle(); + setObjectParam(handle, "invertNormals", invert); + commitObject(handle); +} + +void loadClippingModelParams(OSPGeometricModel handle, const ClippingModelSettings &settings) +{ + setObjectParam(handle, "geometry", settings.geometry); + setObjectParam(handle, "invertNormals", settings.invertedNormals); + setObjectParam(handle, "id", settings.id); + commitObject(handle); +} + +void ClippingModel::invertNormals(bool invert) +{ + auto handle = getHandle(); + setObjectParam(handle, "invertNormals", invert); + commitObject(handle); +} +} diff --git a/src/brayns/core/enginev2/GeometricModel.h b/src/brayns/core/enginev2/GeometricModel.h new file mode 100644 index 000000000..bee4b7a5b --- /dev/null +++ b/src/brayns/core/enginev2/GeometricModel.h @@ -0,0 +1,78 @@ +/* Copyright (c) 2015-2024 EPFL/Blue Brain Project + * All rights reserved. Do not distribute without permission. + * + * Responsible Author: adrien.fleury@epfl.ch + * + * This file is part of Brayns + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +#include +#include + +#include "Data.h" +#include "Geometry.h" +#include "Object.h" + +namespace brayns::experimental +{ +using RendererIndex = std::uint32_t; +using PrimitiveMaterials = std::variant>; +using PrimitiveColors = std::variant>; +using UseGeometryColors = std::monostate; +using MaterialAndColorIndices = std::optional>; + +struct GeometricModelSettings +{ + Geometry geometry; + PrimitiveMaterials materials = RendererIndex(0); + PrimitiveColors colors = UseGeometryColors(); + MaterialAndColorIndices indices = std::nullopt; + bool invertedNormals = false; + std::uint32_t id = std::uint32_t(-1); +}; + +void loadGeometricModelParams(OSPGeometricModel handle, const GeometricModelSettings &settings); + +class GeometricModel : public Managed +{ +public: + using Managed::Managed; + + void setMaterials(const PrimitiveMaterials &materials); + void setColors(const PrimitiveColors &colors); + void setIndices(const MaterialAndColorIndices &indices); + void invertNormals(bool inverted); +}; + +struct ClippingModelSettings +{ + Geometry geometry; + bool invertedNormals = false; + std::uint32_t id = std::uint32_t(-1); +}; + +void loadClippingModelParams(OSPGeometricModel handle, const ClippingModelSettings &settings); + +class ClippingModel : public Managed +{ +public: + using Managed::Managed; + + void invertNormals(bool inverted); +}; +} diff --git a/src/brayns/core/enginev2/Geometry.cpp b/src/brayns/core/enginev2/Geometry.cpp index 6fb4102a6..de5507b9c 100644 --- a/src/brayns/core/enginev2/Geometry.cpp +++ b/src/brayns/core/enginev2/Geometry.cpp @@ -21,145 +21,211 @@ #include "Geometry.h" -namespace brayns::experimental -{ -void GeometricModel::setGeometry(const Geometry &geometry) -{ - setParam("geometry", geometry.getHandle()); -} +#include -void GeometricModel::setMaterial(std::uint32_t rendererIndex) +namespace { - setParam("material", rendererIndex); -} +using namespace brayns::experimental; -void GeometricModel::setPrimitiveMaterials(SharedArray rendererIndices) +void setMeshParams(OSPGeometry handle, const MeshSettings &settings) { - setParam("material", toSharedData(rendererIndices)); -} + setObjectParam(handle, "vertex.position", settings.positions); -void GeometricModel::setPrimitiveColors(SharedArray colors) -{ - setParam("color", toSharedData(colors)); -} + if (settings.normals) + { + setObjectParam(handle, "vertex.normal", *settings.normals); + } -void GeometricModel::setColor(const Color4 &color) -{ - setParam("color", color); -} + if (settings.colors) + { + setObjectParam(handle, "vertex.color", *settings.colors); + } -void GeometricModel::removeColors() -{ - removeParam("color"); + if (settings.uvs) + { + setObjectParam(handle, "vertex.texcoord", *settings.uvs); + } } -void GeometricModel::invertNormals(bool inverted) +void setSphereParams(OSPGeometry handle, const SphereSettings &settings) { - setParam("invertNormals", inverted); -} + setObjectParam(handle, "sphere.position", settings.positions); -void GeometricModel::setId(std::uint32_t id) -{ - setParam("id", id); -} + std::visit([=](const auto &radius) { setObjectParam(handle, "sphere.radius", radius); }, settings.radii); -void Mesh::setVertexPositions(SharedArray positions) -{ - setParam("vertex.position", toSharedData(positions)); + if (settings.uvs) + { + setObjectParam(handle, "sphere.texcoord", *settings.uvs); + } } -void Mesh::setVertexNormals(SharedArray normals) +void setCurveParams(OSPGeometry handle, const CylinderSettings &settings) { - setParam("vertex.normal", toSharedData(normals)); + setObjectParam(handle, "vertex.position_radius", settings.samples); + setObjectParam(handle, "index", settings.indices); + + if (settings.uvs) + { + setObjectParam(handle, "vertex.texcoord", *settings.uvs); + } + + if (settings.colors) + { + setObjectParam(handle, "vertex.color", *settings.colors); + } +} } -void Mesh::setVertexColors(SharedArray colors) +namespace brayns::experimental { - setParam("vertex.color", toSharedData(colors)); +void Mesh::setColors(const Data1D &colors) +{ + auto handle = getHandle(); + setObjectParam(handle, "vertex.color", colors); + commitObject(handle); } -void Mesh::setTriangleIndices(SharedArray indices) +void loadMeshParams(OSPGeometry handle, const TriangleMeshSettings &settings) { - setParam("index", toSharedData(indices)); + setMeshParams(handle, settings); + + if (settings.indices) + { + setObjectParam(handle, "index", *settings.indices); + } + + commitObject(handle); } -void Mesh::setQuadIndices(SharedArray indices) +void loadMeshParams(OSPGeometry handle, const QuadMeshSettings &settings) { - setParam("index", toSharedData(indices)); + setMeshParams(handle, settings); + + if (settings.indices) + { + setObjectParam(handle, "index", *settings.indices); + } + else + { + setObjectParam(handle, "quadSoup", true); + } + + commitObject(handle); } -void Mesh::setQuadSoup(bool quadSoup) +void loadSphereParams(OSPGeometry handle, const SphereSettings &settings) { - setParam("quadSoup", quadSoup); + setSphereParams(handle, settings); + commitObject(handle); } -void Spheres::setPositions(SharedArray positions) +void loadSphereParams(OSPGeometry handle, const DiscSettings &settings) { - setParam("sphere.position", toSharedData(positions)); + setSphereParams(handle, settings); + + auto type = settings.normals ? OSP_ORIENTED_DISC : OSP_DISC; + + setObjectParam(handle, "type", type); + + if (settings.normals) + { + setObjectParam(handle, "sphere.normal", *settings.normals); + } + + commitObject(handle); } -void Spheres::setRadii(SharedArray radii) +void Spheres::setRadii(const Data1D &radii) { - setParam("sphere.radius", toSharedData(radii)); + auto handle = getHandle(); + setObjectParam(handle, "sphere.radius", radii); + commitObject(handle); } void Spheres::setRadius(float radius) { - setParam("radius", radius); + auto handle = getHandle(); + setObjectParam(handle, "sphere.radius", radius); + commitObject(handle); } -void Curve::setVertexPositionsAndRadii(SharedArray positionsRadii) +void loadCurveParams(OSPGeometry handle, const CylinderSettings &settings) { - setParam("vertex.position_radius", toSharedData(positionsRadii)); + setCurveParams(handle, settings); + commitObject(handle); } -void Curve::setVertexColors(SharedArray colors) +void loadCurveParams(OSPGeometry handle, const CurveSettings &settings) { - setParam("vertex.color", toSharedData(colors)); + setCurveParams(handle, settings); + setObjectParam(handle, "type", static_cast(settings.type)); + setObjectParam(handle, "basis", static_cast(settings.basis)); + commitObject(handle); } -void Curve::setIndices(SharedArray indices) +void loadCurveParams(OSPGeometry handle, const RibbonCurveSettings &settings) { - setParam("index", toSharedData(indices)); -} + if (settings.basis == CurveBasis::Linear) + { + throw std::invalid_argument("Ribbon curve with linear basis not supported"); + } -void Curve::setType(CurveType type) -{ - setParam("type", static_cast(type)); -} + setCurveParams(handle, settings); -void Curve::setBasis(CurveBasis basis) -{ - setParam("basis", static_cast(basis)); + setObjectParam(handle, "vertex.normal", settings.normals); + setObjectParam(handle, "type", OSP_RIBBON); + setObjectParam(handle, "basis", static_cast(settings.basis)); + + commitObject(handle); } -void Boxes::setBoxes(SharedArray boxes) +void loadCurveParams(OSPGeometry handle, const HermiteCurveSettings &settings) { - setParam("box", toSharedData(boxes)); + setCurveParams(handle, settings); + setObjectParam(handle, "vertex.tangent", settings.tangents); + setObjectParam(handle, "type", static_cast(settings.type)); + setObjectParam(handle, "basis", OSP_HERMITE); + commitObject(handle); } -void Planes::setCoefficients(SharedArray coefficients) +void Curve::setSamples(const Data1D &samples) { - setParam("plane.coefficients", toSharedData(coefficients)); + auto handle = getHandle(); + setObjectParam(handle, "vertex.position_radius", samples); + commitObject(handle); } -void Planes::setBounds(SharedArray bounds) +void Curve::setColors(const Data1D &colors) { - setParam("plane.bounds", toSharedData(bounds)); + auto handle = getHandle(); + setObjectParam(handle, "vertex.color", colors); + commitObject(handle); } -void Isosurfaces::setVolume(const Volume &volume) +void loadBoxParams(OSPGeometry handle, const BoxSettings &settings) { - setParam("volume", volume.getHandle()); + setObjectParam(handle, "box", settings.boxes); + commitObject(handle); } -void Isosurfaces::setIsovalues(SharedArray values) +void loadPlaneParams(OSPGeometry handle, const PlaneSettings &settings) { - setParam("isovalue", toSharedData(values)); + setObjectParam(handle, "plane.coefficients", settings.coefficients); + + if (settings.bounds) + { + setObjectParam(handle, "plane.bounds", *settings.bounds); + } + + commitObject(handle); } -void Isosurfaces::setIsovalue(float value) +void loadIsosurfaceParams(OSPGeometry handle, const IsosurfaceSettings &settings) { - setParam("isovalue", value); + setObjectParam(handle, "volume", settings.volume); + + std::visit([=](const auto &isovalues) { setObjectParam(handle, "isovalue", isovalues); }, settings.isovalues); + + commitObject(handle); } } diff --git a/src/brayns/core/enginev2/Geometry.h b/src/brayns/core/enginev2/Geometry.h index 2598a8e8b..116b0db44 100644 --- a/src/brayns/core/enginev2/Geometry.h +++ b/src/brayns/core/enginev2/Geometry.h @@ -21,8 +21,11 @@ #pragma once +#include +#include + #include "Data.h" -#include "Managed.h" +#include "Object.h" #include "Volume.h" namespace brayns::experimental @@ -33,55 +36,64 @@ class Geometry : public Managed using Managed::Managed; }; -class GeometricModel : public Managed +struct MeshSettings { -public: - using Managed::Managed; + Data1D positions; + std::optional> normals = std::nullopt; + std::optional> colors = std::nullopt; + std::optional> uvs = std::nullopt; + std::optional> indices = std::nullopt; +}; + +struct TriangleMeshSettings : MeshSettings +{ + std::optional> indices = std::nullopt; +}; - void setGeometry(const Geometry &geometry); - void setMaterial(std::uint32_t rendererIndex); - void setPrimitiveMaterials(SharedArray rendererIndices); - void setPrimitiveColors(SharedArray colors); - void setColor(const Color4 &color); - void removeColors(); - void invertNormals(bool inverted); - void setId(std::uint32_t id); +struct QuadMeshSettings : MeshSettings +{ + std::optional> indices = std::nullopt; }; +void loadMeshParams(OSPGeometry handle, const TriangleMeshSettings &settings); +void loadMeshParams(OSPGeometry handle, const QuadMeshSettings &settings); + class Mesh : public Geometry { public: - static inline const std::string name = "mesh"; - using Geometry::Geometry; - void setVertexPositions(SharedArray positions); - void setVertexNormals(SharedArray normals); - void setVertexColors(SharedArray colors); - void setTriangleIndices(SharedArray indices); - void setQuadIndices(SharedArray indices); - void setQuadSoup(bool quadSoup); + void setColors(const Data1D &colors); }; +struct SphereSettings +{ + Data1D positions; + std::variant> radii; + std::optional> uvs = std::nullopt; +}; + +struct DiscSettings : SphereSettings +{ + std::optional> normals; +}; + +void loadSphereParams(OSPGeometry handle, const SphereSettings &settings); +void loadSphereParams(OSPGeometry handle, const DiscSettings &settings); + class Spheres : public Geometry { public: - static inline const std::string name = "sphere"; - using Geometry::Geometry; - void setPositions(SharedArray positions); - void setRadii(SharedArray radii); + void setRadii(const Data1D &radii); void setRadius(float radius); }; -using PositionRadius = Vector4; - enum class CurveType { Flat = OSP_FLAT, Round = OSP_ROUND, - Disjoint = OSP_DISJOINT, }; enum class CurveBasis @@ -89,64 +101,89 @@ enum class CurveBasis Linear = OSP_LINEAR, Bezier = OSP_BEZIER, Bspline = OSP_BSPLINE, + CatmullRom = OSP_CATMULL_ROM, }; +using PositionRadius = Vector4; + +struct CylinderSettings +{ + Data1D samples; + Data1D indices; + std::optional> colors = std::nullopt; + std::optional> uvs = std::nullopt; +}; + +struct CurveSettings : CylinderSettings +{ + CurveType type = CurveType::Round; + CurveBasis basis = CurveBasis::Linear; +}; + +struct RibbonCurveSettings : CylinderSettings +{ + CurveBasis basis = CurveBasis::Bezier; + Data1D normals; +}; + +struct HermiteCurveSettings : CylinderSettings +{ + CurveType type = CurveType::Round; + Data1D tangents; +}; + +void loadCurveParams(OSPGeometry handle, const CylinderSettings &settings); +void loadCurveParams(OSPGeometry handle, const CurveSettings &settings); +void loadCurveParams(OSPGeometry handle, const RibbonCurveSettings &settings); +void loadCurveParams(OSPGeometry handle, const HermiteCurveSettings &settings); + class Curve : public Geometry { public: - static inline const std::string name = "curve"; - using Geometry::Geometry; - void setVertexPositionsAndRadii(SharedArray positionsRadii); - void setVertexColors(SharedArray colors); - void setIndices(SharedArray indices); - void setType(CurveType type); - void setBasis(CurveBasis basis); + void setSamples(const Data1D &samples); + void setColors(const Data1D &colors); +}; + +struct BoxSettings +{ + Data1D boxes; }; +void loadBoxParams(OSPGeometry handle, const BoxSettings &settings); + class Boxes : public Geometry { public: - static inline const std::string name = "box"; - using Geometry::Geometry; +}; - void setBoxes(SharedArray boxes); +struct PlaneSettings +{ + Data1D coefficients; + std::optional> bounds; }; +void loadPlaneParams(OSPGeometry handle, const PlaneSettings &settings); + class Planes : public Geometry { public: - static inline const std::string name = "plane"; - using Geometry::Geometry; +}; - void setCoefficients(SharedArray coefficients); - void setBounds(SharedArray bounds); +struct IsosurfaceSettings +{ + Volume volume; + std::variant> isovalues; }; +void loadIsosurfaceParams(OSPGeometry handle, const IsosurfaceSettings &settings); + class Isosurfaces : public Geometry { public: - static inline const std::string name = "isosurface"; - using Geometry::Geometry; - - void setVolume(const Volume &volume); - void setIsovalues(SharedArray values); - void setIsovalue(float value); }; } - -namespace ospray -{ -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::Geometry, OSP_GEOMETRY) -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::GeometricModel, OSP_GEOMETRIC_MODEL) -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::Mesh, OSP_GEOMETRY) -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::Spheres, OSP_GEOMETRY) -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::Curve, OSP_GEOMETRY) -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::Boxes, OSP_GEOMETRY) -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::Planes, OSP_GEOMETRY) -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::Isosurfaces, OSP_GEOMETRY) -} diff --git a/src/brayns/core/enginev2/Light.h b/src/brayns/core/enginev2/Light.h index 9df0ded19..664df5f5e 100644 --- a/src/brayns/core/enginev2/Light.h +++ b/src/brayns/core/enginev2/Light.h @@ -21,14 +21,14 @@ #pragma once -#include "Managed.h" +#include "Object.h" namespace brayns::experimental { -class Light : public Managed +class Light : public Object { public: - using Managed::Managed; + using Object::Object; void setColor(const Color3 &color); void setIntensity(float intensity); diff --git a/src/brayns/core/enginev2/Managed.h b/src/brayns/core/enginev2/Managed.h deleted file mode 100644 index 4d0668f02..000000000 --- a/src/brayns/core/enginev2/Managed.h +++ /dev/null @@ -1,154 +0,0 @@ -/* Copyright (c) 2015-2024 EPFL/Blue Brain Project - * All rights reserved. Do not distribute without permission. - * - * Responsible Author: adrien.fleury@epfl.ch - * - * This file is part of Brayns - * - * This library is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License version 3.0 as published - * by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - * details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#pragma once - -#include -#include - -#include -#include - -#include - -namespace brayns::experimental -{ -template HandleType> -class Managed -{ -public: - using Handle = HandleType; - - explicit Managed(Handle handle): - _handle(handle) - { - } - - ~Managed() - { - ospRelease(_handle); - } - - Managed(const Managed &other): - _handle(other._handle) - { - retain(); - } - - Managed(Managed &&other) noexcept: - _handle(std::exchange(other._handle, nullptr)) - { - } - - template OtherHandleType> - Managed(const Managed &other): - _handle(other._handle) - { - retain(); - } - - template OtherHandleType> - Managed(Managed &&other) noexcept: - _handle(std::exchange(other._handle, nullptr)) - { - } - - Managed &operator=(const Managed &other) - { - releaseAndRetain(other._handle); - return *this; - } - - Managed &operator=(Managed &&other) noexcept - { - std::swap(_handle, other._handle); - return *this; - } - - template OtherHandleType> - Managed &operator=(const Managed &other) - { - releaseAndRetain(other._handle); - return *this; - } - - template OtherHandleType> - Managed &operator=(Managed &&other) noexcept - { - std::swap(_handle, other._handle); - return *this; - } - - Handle getHandle() const - { - return _handle; - } - - void commit() - { - ospCommit(_handle); - } - -protected: - Box3 getBounds() const - { - auto [lower, upper] = ospGetBounds(_handle); - return {{lower[0], lower[1], lower[2]}, {upper[0], upper[1], upper[2]}}; - } - - void removeParam(const char *id) - { - ospRemoveParam(_handle, id); - } - - template - void setParam(const char *id, const T &value) - { - constexpr auto type = ospray::OSPTypeFor::value; - ospSetParam(_handle, id, type, &value); - } - -private: - Handle _handle; - - void retain() - { - if (_handle) - { - ospRetain(_handle); - } - } - - void releaseAndRetain(Handle handle) - { - ospRelease(_handle); - _handle = handle; - retain(); - } -}; - -using Object = Managed; -} - -namespace ospray -{ -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::Object, OSP_OBJECT) -} diff --git a/src/brayns/core/enginev2/Material.h b/src/brayns/core/enginev2/Material.h index a2379788b..a958fbe1b 100644 --- a/src/brayns/core/enginev2/Material.h +++ b/src/brayns/core/enginev2/Material.h @@ -21,14 +21,14 @@ #pragma once -#include "Managed.h" +#include "Object.h" namespace brayns::experimental { -class Material : public Managed +class Material : public Object { public: - using Managed::Managed; + using Object::Object; }; class ObjMaterial : public Material diff --git a/src/brayns/core/enginev2/Object.h b/src/brayns/core/enginev2/Object.h new file mode 100644 index 000000000..fea295eed --- /dev/null +++ b/src/brayns/core/enginev2/Object.h @@ -0,0 +1,164 @@ +/* Copyright (c) 2015-2024 EPFL/Blue Brain Project + * All rights reserved. Do not distribute without permission. + * + * Responsible Author: adrien.fleury@epfl.ch + * + * This file is part of Brayns + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +#include +#include + +#include +#include + +#include + +namespace brayns::experimental +{ +class Object +{ +public: + using Handle = OSPObject; + + explicit Object(Handle handle): + _handle(handle) + { + } + + ~Object() + { + if (_handle) + { + ospRelease(_handle); + } + } + + Object(const Object &other): + _handle(other._handle) + { + if (_handle) + { + ospRetain(_handle); + } + } + + Object(Object &&other) noexcept: + _handle(other.release()) + { + } + + Object &operator=(const Object &other) + { + if (_handle) + { + ospRelease(_handle); + } + + _handle = other._handle; + + if (_handle) + { + ospRetain(_handle); + } + + return *this; + } + + Object &operator=(Object &&other) noexcept + { + std::swap(_handle, other._handle); + return *this; + } + + Handle getHandle() const + { + return _handle; + } + + Handle release() + { + return std::exchange(_handle, nullptr); + } + + template T> + T as() const + { + return T(static_cast(_handle)); + } + +private: + Handle _handle; +}; + +template HandleType> +class Managed : public Object +{ +public: + using Handle = HandleType; + + explicit Managed(Handle handle): + Object(handle) + { + } + + Handle getHandle() const + { + return static_cast(Object::getHandle()); + } +}; + +Box3 getObjectBounds(OSPObject handle) +{ + auto [lower, upper] = ospGetBounds(handle); + return {{lower[0], lower[1], lower[2]}, {upper[0], upper[1], upper[2]}}; +} + +void commitObject(OSPObject handle) +{ + ospCommit(handle); +} + +void removeObjectParam(OSPObject handle, const char *id) +{ + ospRemoveParam(handle, id); +} + +template +concept OsprayDataType = (ospray::OSPTypeFor::value != OSP_UNKNOWN); + +template +void setObjectParam(OSPObject handle, const char *id, const T &value) +{ + constexpr auto type = ospray::OSPTypeFor::value; + ospSetParam(handle, id, type, &value); +} +} + +namespace ospray +{ +template T> +struct OSPTypeFor +{ + using Handle = typename T::Handle; + + static_assert(sizeof(T) == sizeof(Handle), "Object and handle must have the same size"); + + static constexpr auto value = OSPTypeFor::value; +}; +} diff --git a/src/brayns/core/enginev2/Render.h b/src/brayns/core/enginev2/Render.h index f9024fdd5..b9b77994c 100644 --- a/src/brayns/core/enginev2/Render.h +++ b/src/brayns/core/enginev2/Render.h @@ -23,7 +23,7 @@ #include "Camera.h" #include "Framebuffer.h" -#include "Managed.h" +#include "Object.h" #include "Renderer.h" #include "World.h" @@ -37,10 +37,10 @@ struct RenderSettings World world; }; -class RenderTask : public Managed +class RenderTask : public Object { public: - using Managed::Managed; + using Object::Object; bool isReady() const; float getProgress() const; diff --git a/src/brayns/core/enginev2/Renderer.h b/src/brayns/core/enginev2/Renderer.h index de4b38321..6da10d0f0 100644 --- a/src/brayns/core/enginev2/Renderer.h +++ b/src/brayns/core/enginev2/Renderer.h @@ -22,8 +22,8 @@ #pragma once #include "Data.h" -#include "Managed.h" #include "Material.h" +#include "Object.h" namespace brayns::experimental { @@ -36,10 +36,10 @@ enum class PixelFilter BlackmanHarris = OSP_PIXELFILTER_BLACKMAN_HARRIS, }; -class Renderer : public Managed +class Renderer : public Object { public: - using Managed::Managed; + using Object::Object; void setPixelSamples(std::size_t count); void setMaxRayRecursion(std::size_t depth); diff --git a/src/brayns/core/enginev2/Volume.h b/src/brayns/core/enginev2/Volume.h index 4b4e0b8fe..ac289679d 100644 --- a/src/brayns/core/enginev2/Volume.h +++ b/src/brayns/core/enginev2/Volume.h @@ -22,14 +22,14 @@ #pragma once #include "Data.h" -#include "Managed.h" +#include "Object.h" namespace brayns::experimental { -class TransferFunction : public Managed +class TransferFunction : public Object { public: - using Managed::Managed; + using Object::Object; }; class LinearTransferFunction : public TransferFunction @@ -44,16 +44,16 @@ class LinearTransferFunction : public TransferFunction void setScalarRange(Box1 range); }; -class Volume : public Managed +class Volume : public Object { public: - using Managed::Managed; + using Object::Object; }; -class VolumetricModel : public Managed +class VolumetricModel : public Object { public: - using Managed::Managed; + using Object::Object; void setVolume(const Volume &volume); void setTransferFunction(const TransferFunction &function); diff --git a/src/brayns/core/enginev2/World.h b/src/brayns/core/enginev2/World.h index fc6a12e14..9c7fab6f4 100644 --- a/src/brayns/core/enginev2/World.h +++ b/src/brayns/core/enginev2/World.h @@ -24,16 +24,16 @@ #include "Data.h" #include "Geometry.h" #include "Light.h" -#include "Managed.h" +#include "Object.h" #include "Volume.h" namespace brayns::experimental { -class Group : public Managed +class Group : public Object { public: - using Managed::getBounds; - using Managed::Managed; + using Object::getBounds; + using Object::Object; void setVolumes(SharedArray models); void setGeometries(SharedArray models); @@ -41,22 +41,22 @@ class Group : public Managed void setLights(SharedArray lights); }; -class Instance : public Managed +class Instance : public Object { public: - using Managed::getBounds; - using Managed::Managed; + using Object::getBounds; + using Object::Object; void setGroup(const Group &group); void setTransform(const Affine3 &transform); void setId(std::uint32_t id); }; -class World : public Managed +class World : public Object { public: - using Managed::getBounds; - using Managed::Managed; + using Object::getBounds; + using Object::Object; void setInstances(SharedArray instances); }; diff --git a/src/brayns/core/utils/Math.h b/src/brayns/core/utils/Math.h index 208d04b29..b3d5020f7 100644 --- a/src/brayns/core/utils/Math.h +++ b/src/brayns/core/utils/Math.h @@ -28,26 +28,40 @@ namespace brayns { -using Index3 = rkcommon::math::vec3ui; -using Index4 = rkcommon::math::vec4ui; +template +using Vector = rkcommon::math::vec_t; -using Size3 = rkcommon::math::vec3ul; +using Index3 = Vector; +using Index4 = Vector; -using Vector2 = rkcommon::math::vec2f; -using Vector3 = rkcommon::math::vec3f; -using Vector4 = rkcommon::math::vec4f; +using Size2 = Vector; +using Size3 = Vector; -using Box1 = rkcommon::math::box1f; -using Box2 = rkcommon::math::box2f; -using Box3 = rkcommon::math::box3f; +using Vector2 = Vector; +using Vector3 = Vector; +using Vector4 = Vector; using Color3 = Vector3; using Color4 = Vector4; using Quaternion = rkcommon::math::quaternionf; +template +using Box = rkcommon::math::box_t; + +using Box1 = Box; +using Box2 = Box; +using Box3 = Box; + +using Affine2 = rkcommon::math::AffineSpace2f; using Affine3 = rkcommon::math::AffineSpace3f; +template +T reduceMultiply(const Vector &value) +{ + return rkcommon::math::reduce_mul(value); +} + struct Transform { Vector3 translation = {0, 0, 0}; From 0f218e7349f55da85a6fe37d49e646056b3dd323 Mon Sep 17 00:00:00 2001 From: Adrien4193 Date: Thu, 6 Jun 2024 08:56:02 +0200 Subject: [PATCH 2/7] Checkpoint. --- src/brayns/core/enginev2/Camera.cpp | 6 +- src/brayns/core/enginev2/Camera.h | 14 +- src/brayns/core/enginev2/Data.h | 45 +++--- src/brayns/core/enginev2/Framebuffer.cpp | 6 +- src/brayns/core/enginev2/Framebuffer.h | 30 ++-- src/brayns/core/enginev2/GeometricModel.cpp | 50 +------ src/brayns/core/enginev2/GeometricModel.h | 20 +-- src/brayns/core/enginev2/Geometry.cpp | 143 +++++--------------- src/brayns/core/enginev2/Geometry.h | 115 +++++++++------- src/brayns/core/enginev2/Light.cpp | 95 +++++-------- src/brayns/core/enginev2/Light.h | 85 ++++++------ src/brayns/core/enginev2/Material.cpp | 98 ++++++++++++-- src/brayns/core/enginev2/Material.h | 96 +++++++++++-- src/brayns/core/enginev2/Texture.cpp | 89 ++++++++++++ src/brayns/core/enginev2/Texture.h | 105 ++++++++++++++ src/brayns/core/utils/Math.h | 12 ++ 16 files changed, 621 insertions(+), 388 deletions(-) create mode 100644 src/brayns/core/enginev2/Texture.cpp create mode 100644 src/brayns/core/enginev2/Texture.h diff --git a/src/brayns/core/enginev2/Camera.cpp b/src/brayns/core/enginev2/Camera.cpp index 43cb09163..2fac5b195 100644 --- a/src/brayns/core/enginev2/Camera.cpp +++ b/src/brayns/core/enginev2/Camera.cpp @@ -25,7 +25,7 @@ namespace { using namespace brayns::experimental; -void loadCameraParams(OSPCamera handle, const CameraSettings &settings) +void setCameraParams(OSPCamera handle, const CameraSettings &settings) { setObjectParam(handle, "position", settings.position); setObjectParam(handle, "direction", settings.direction); @@ -38,7 +38,7 @@ namespace brayns::experimental { void loadPerspectiveCameraParams(OSPCamera handle, const PerspectiveCameraSettings &settings) { - loadCameraParams(handle, settings); + setCameraParams(handle, settings); setObjectParam(handle, "fovy", settings.fovy); setObjectParam(handle, "aspect", settings.aspectRatio); commitObject(handle); @@ -46,7 +46,7 @@ void loadPerspectiveCameraParams(OSPCamera handle, const PerspectiveCameraSettin void loadOrthographicCameraParams(OSPCamera handle, const OrthographicCameraSettings &settings) { - loadCameraParams(handle, settings); + setCameraParams(handle, settings); setObjectParam(handle, "height", settings.height); setObjectParam(handle, "aspect", settings.aspectRatio); commitObject(handle); diff --git a/src/brayns/core/enginev2/Camera.h b/src/brayns/core/enginev2/Camera.h index aa3c44f54..a1de56fcb 100644 --- a/src/brayns/core/enginev2/Camera.h +++ b/src/brayns/core/enginev2/Camera.h @@ -27,9 +27,9 @@ namespace brayns::experimental { struct CameraSettings { - Vector3 position = {0.0f, 0.0f, 0.0f}; - Vector3 direction = {0.0f, 0.0f, 1.0f}; - Vector3 up = {0.0f, 1.0f, 0.0f}; + Vector3 position = {0.0F, 0.0F, 0.0F}; + Vector3 direction = {0.0F, 0.0F, 1.0F}; + Vector3 up = {0.0F, 1.0F, 0.0F}; float nearClippingDistance = 1.0e-6F; }; @@ -41,8 +41,8 @@ class Camera : public Managed struct PerspectiveCameraSettings : CameraSettings { - float fovy = 60.0f; - float aspectRatio = 1.0f; + float fovy = 60.0F; + float aspectRatio = 1.0F; }; class PerspectiveCamera : public Camera @@ -55,8 +55,8 @@ void loadPerspectiveCameraParams(OSPCamera handle, const PerspectiveCameraSettin struct OrthographicCameraSettings : CameraSettings { - float height = 1.0f; - float aspectRatio = 1.0f; + float height = 1.0F; + float aspectRatio = 1.0F; }; void loadOrthographicCameraParams(OSPCamera handle, const OrthographicCameraSettings &settings); diff --git a/src/brayns/core/enginev2/Data.h b/src/brayns/core/enginev2/Data.h index 07718f834..76d708a08 100644 --- a/src/brayns/core/enginev2/Data.h +++ b/src/brayns/core/enginev2/Data.h @@ -27,35 +27,36 @@ namespace brayns::experimental { -using DataType = OSPDataType; - -struct DataSettings -{ - DataType type; - Size3 itemCount; - const void *data; - void (*deleter)(const void *, const void *) = nullptr; -}; - class Data : public Managed { public: using Managed::Managed; }; -template -class DataND : public Data +template +Data toSharedData(std::span items) { -public: - using Data::Data; -}; - -template -using Data1D = DataND; + auto data = items.data(); + auto type = ospray::OSPTypeFor::value; + auto size = items.size(); + auto handle = ospNewSharedData(data, type, size); + return Data(handle); +} -template -using Data2D = DataND; +template +void setObjectData(OSPObject handle, const char *id, std::span items) +{ + setObjectParam(handle, id, toSharedData(items)); +} -template -using Data3D = DataND; +template +void setObjectDataIfNotEmpty(OSPObject handle, const char *id, std::span items) +{ + if (items.empty()) + { + removeObjectParam(handle, id); + return; + } + setObjectData(handle, id, items); +} } diff --git a/src/brayns/core/enginev2/Framebuffer.cpp b/src/brayns/core/enginev2/Framebuffer.cpp index 818ce9f06..6e0a24dda 100644 --- a/src/brayns/core/enginev2/Framebuffer.cpp +++ b/src/brayns/core/enginev2/Framebuffer.cpp @@ -31,14 +31,12 @@ void loadToneMapperParams(OSPImageOperation handle, const ToneMapperSettings &se setObjectParam(handle, "midIn", settings.midLevelAnchorInput); setObjectParam(handle, "midOut", settings.midLevelAnchorOutput); setObjectParam(handle, "acesColor", settings.aces); + commitObject(handle); } void loadFramebufferParams(OSPFrameBuffer handle, const FramebufferSettings &settings) { - if (settings.operations) - { - setObjectParam(handle, "imageOperation", *settings.operations); - } + setObjectData(handle, "imageOperation", settings.operations); commitObject(handle); } diff --git a/src/brayns/core/enginev2/Framebuffer.h b/src/brayns/core/enginev2/Framebuffer.h index 724a16515..f271e1810 100644 --- a/src/brayns/core/enginev2/Framebuffer.h +++ b/src/brayns/core/enginev2/Framebuffer.h @@ -21,8 +21,6 @@ #pragma once -#include - #include "Data.h" #include "Object.h" @@ -36,12 +34,12 @@ class ImageOperation : public Managed struct ToneMapperSettings { - float exposure = 1.0; - float contrast = 1.6773; - float hightlightCompression = 0.9714; - float midLevelAnchorInput = 0.18; - float midLevelAnchorOutput = 0.18; - float maxHdr = 11.0785; + float exposure = 1.0F; + float contrast = 1.6773F; + float hightlightCompression = 0.9714F; + float midLevelAnchorInput = 0.18F; + float midLevelAnchorOutput = 0.18F; + float maxHdr = 11.0785F; bool aces = true; }; @@ -57,7 +55,7 @@ enum class FramebufferFormat { Rgba8 = OSP_FB_RGBA8, Srgba8 = OSP_FB_SRGBA, - Rgba32f = OSP_FB_RGBA32F, + Rgba32F = OSP_FB_RGBA32F, }; enum class FramebufferChannel @@ -73,13 +71,23 @@ enum class FramebufferChannel InstanceId = OSP_FB_ID_INSTANCE, }; +FramebufferChannel operator|(FramebufferChannel left, FramebufferChannel right) +{ + return static_cast(static_cast(left) | static_cast(right)); +} + +bool operator&(FramebufferChannel channels, FramebufferChannel channel) +{ + return static_cast(channels) & static_cast(channel) != 0; +} + struct FramebufferSettings { std::size_t width; std::size_t height; FramebufferFormat format = FramebufferFormat::Srgba8; - std::vector channels = {FramebufferChannel::Color}; - std::optional> operations = std::nullopt; + FramebufferChannel channels = FramebufferChannel::Color; + std::span operations = {}; }; void loadFramebufferParams(OSPFrameBuffer handle, const FramebufferSettings &settings); diff --git a/src/brayns/core/enginev2/GeometricModel.cpp b/src/brayns/core/enginev2/GeometricModel.cpp index dfd8c3864..62221b621 100644 --- a/src/brayns/core/enginev2/GeometricModel.cpp +++ b/src/brayns/core/enginev2/GeometricModel.cpp @@ -28,37 +28,9 @@ using namespace brayns::experimental; void setMaterialParam(OSPGeometricModel handle, const PrimitiveMaterials &materials) { - std::visit([=](const auto &value) { setObjectParam(handle, "material", value); }, materials); -} - -void setColorParam(OSPGeometricModel handle, std::monostate) -{ - removeObjectParam(handle, "color"); -} - -void setColorParam(OSPGeometricModel handle, const Data1D &colors) -{ - setObjectParam(handle, "color", colors); -} - -void setColorParam(OSPGeometricModel handle, const Color4 &color) -{ - setObjectParam(handle, "color", color); -} - -void setColorParams(OSPGeometricModel handle, const PrimitiveColors &colors) -{ - std::visit([&](const auto &value) { setColorParam(handle, value); }, colors); -} - -void setIndicesParam(OSPGeometricModel handle, const MaterialAndColorIndices &indices) -{ - if (!indices) - { - removeObjectParam(handle, "index"); - return; - } - setObjectParam(handle, "index", *indices); + setObjectData(handle, "material", materials.rendererIndices); + setObjectDataIfNotEmpty(handle, "color", materials.colors); + setObjectDataIfNotEmpty(handle, "index", materials.materialAndColorIndices); } } @@ -68,8 +40,6 @@ void loadGeometricModelParams(OSPGeometricModel handle, const GeometricModelSett { setObjectParam(handle, "geometry", settings.geometry); setMaterialParam(handle, settings.materials); - setColorParams(handle, settings.colors); - setIndicesParam(handle, settings.indices); setObjectParam(handle, "invertNormals", settings.invertedNormals); setObjectParam(handle, "id", settings.id); commitObject(handle); @@ -82,20 +52,6 @@ void GeometricModel::setMaterials(const PrimitiveMaterials &materials) commitObject(handle); } -void GeometricModel::setColors(const PrimitiveColors &colors) -{ - auto handle = getHandle(); - setColorParams(handle, colors); - commitObject(handle); -} - -void GeometricModel::setIndices(const MaterialAndColorIndices &indices) -{ - auto handle = getHandle(); - setIndicesParam(handle, indices); - commitObject(handle); -} - void GeometricModel::invertNormals(bool invert) { auto handle = getHandle(); diff --git a/src/brayns/core/enginev2/GeometricModel.h b/src/brayns/core/enginev2/GeometricModel.h index bee4b7a5b..05b25ae90 100644 --- a/src/brayns/core/enginev2/GeometricModel.h +++ b/src/brayns/core/enginev2/GeometricModel.h @@ -21,27 +21,23 @@ #pragma once -#include -#include - #include "Data.h" #include "Geometry.h" #include "Object.h" namespace brayns::experimental { -using RendererIndex = std::uint32_t; -using PrimitiveMaterials = std::variant>; -using PrimitiveColors = std::variant>; -using UseGeometryColors = std::monostate; -using MaterialAndColorIndices = std::optional>; +struct PrimitiveMaterials +{ + std::span rendererIndices; + std::span colors = {}; + std::span materialAndColorIndices = {}; +}; struct GeometricModelSettings { Geometry geometry; - PrimitiveMaterials materials = RendererIndex(0); - PrimitiveColors colors = UseGeometryColors(); - MaterialAndColorIndices indices = std::nullopt; + PrimitiveMaterials materials; bool invertedNormals = false; std::uint32_t id = std::uint32_t(-1); }; @@ -54,8 +50,6 @@ class GeometricModel : public Managed using Managed::Managed; void setMaterials(const PrimitiveMaterials &materials); - void setColors(const PrimitiveColors &colors); - void setIndices(const MaterialAndColorIndices &indices); void invertNormals(bool inverted); }; diff --git a/src/brayns/core/enginev2/Geometry.cpp b/src/brayns/core/enginev2/Geometry.cpp index de5507b9c..638c37208 100644 --- a/src/brayns/core/enginev2/Geometry.cpp +++ b/src/brayns/core/enginev2/Geometry.cpp @@ -21,79 +21,47 @@ #include "Geometry.h" -#include - namespace { using namespace brayns::experimental; void setMeshParams(OSPGeometry handle, const MeshSettings &settings) { - setObjectParam(handle, "vertex.position", settings.positions); - - if (settings.normals) - { - setObjectParam(handle, "vertex.normal", *settings.normals); - } - - if (settings.colors) - { - setObjectParam(handle, "vertex.color", *settings.colors); - } - - if (settings.uvs) - { - setObjectParam(handle, "vertex.texcoord", *settings.uvs); - } + setObjectData(handle, "vertex.position", settings.positions); + setObjectDataIfNotEmpty(handle, "vertex.normal", settings.normals); + setObjectDataIfNotEmpty(handle, "vertex.color", settings.colors); + setObjectDataIfNotEmpty(handle, "vertex.texcoord", settings.uvs); } void setSphereParams(OSPGeometry handle, const SphereSettings &settings) { - setObjectParam(handle, "sphere.position", settings.positions); - - std::visit([=](const auto &radius) { setObjectParam(handle, "sphere.radius", radius); }, settings.radii); - - if (settings.uvs) - { - setObjectParam(handle, "sphere.texcoord", *settings.uvs); - } + setObjectData(handle, "sphere.position", settings.positions); + setObjectData(handle, "sphere.radius", settings.radii); + setObjectDataIfNotEmpty(handle, "sphere.texcoord", settings.uvs); } void setCurveParams(OSPGeometry handle, const CylinderSettings &settings) { - setObjectParam(handle, "vertex.position_radius", settings.samples); - setObjectParam(handle, "index", settings.indices); - - if (settings.uvs) - { - setObjectParam(handle, "vertex.texcoord", *settings.uvs); - } - - if (settings.colors) - { - setObjectParam(handle, "vertex.color", *settings.colors); - } + setObjectData(handle, "vertex.position_radius", settings.samples); + setObjectData(handle, "index", settings.indices); + setObjectDataIfNotEmpty(handle, "vertex.texcoord", settings.uvs); + setObjectDataIfNotEmpty(handle, "vertex.color", settings.colors); } } namespace brayns::experimental { -void Mesh::setColors(const Data1D &colors) +void Mesh::setColors(std::span colors) { auto handle = getHandle(); - setObjectParam(handle, "vertex.color", colors); + setObjectDataIfNotEmpty(handle, "vertex.color", colors); commitObject(handle); } void loadMeshParams(OSPGeometry handle, const TriangleMeshSettings &settings) { setMeshParams(handle, settings); - - if (settings.indices) - { - setObjectParam(handle, "index", *settings.indices); - } - + setObjectDataIfNotEmpty(handle, "index", settings.indices); commitObject(handle); } @@ -101,9 +69,9 @@ void loadMeshParams(OSPGeometry handle, const QuadMeshSettings &settings) { setMeshParams(handle, settings); - if (settings.indices) + if (!settings.indices.empty()) { - setObjectParam(handle, "index", *settings.indices); + setObjectData(handle, "index", settings.indices); } else { @@ -119,39 +87,33 @@ void loadSphereParams(OSPGeometry handle, const SphereSettings &settings) commitObject(handle); } -void loadSphereParams(OSPGeometry handle, const DiscSettings &settings) +void loadDiscParams(OSPGeometry handle, const DiscSettings &settings) { setSphereParams(handle, settings); - auto type = settings.normals ? OSP_ORIENTED_DISC : OSP_DISC; - - setObjectParam(handle, "type", type); - - if (settings.normals) + if (settings.normals.empty()) + { + setObjectParam(handle, "type", OSP_DISC); + } + else { - setObjectParam(handle, "sphere.normal", *settings.normals); + setObjectParam(handle, "type", OSP_ORIENTED_DISC); + setObjectData(handle, "sphere.normal", settings.normals); } commitObject(handle); } -void Spheres::setRadii(const Data1D &radii) +void loadCylinderParams(OSPGeometry handle, const CylinderSettings &settings) { - auto handle = getHandle(); - setObjectParam(handle, "sphere.radius", radii); + setCurveParams(handle, settings); commitObject(handle); } -void Spheres::setRadius(float radius) +void Cylinders::setColors(std::span colors) { auto handle = getHandle(); - setObjectParam(handle, "sphere.radius", radius); - commitObject(handle); -} - -void loadCurveParams(OSPGeometry handle, const CylinderSettings &settings) -{ - setCurveParams(handle, settings); + setObjectDataIfNotEmpty(handle, "vertex.color", colors); commitObject(handle); } @@ -163,69 +125,32 @@ void loadCurveParams(OSPGeometry handle, const CurveSettings &settings) commitObject(handle); } -void loadCurveParams(OSPGeometry handle, const RibbonCurveSettings &settings) +void loadRibbonParams(OSPGeometry handle, const RibbonSettings &settings) { - if (settings.basis == CurveBasis::Linear) - { - throw std::invalid_argument("Ribbon curve with linear basis not supported"); - } - setCurveParams(handle, settings); - - setObjectParam(handle, "vertex.normal", settings.normals); + setObjectData(handle, "vertex.normal", settings.normals); setObjectParam(handle, "type", OSP_RIBBON); setObjectParam(handle, "basis", static_cast(settings.basis)); - - commitObject(handle); -} - -void loadCurveParams(OSPGeometry handle, const HermiteCurveSettings &settings) -{ - setCurveParams(handle, settings); - setObjectParam(handle, "vertex.tangent", settings.tangents); - setObjectParam(handle, "type", static_cast(settings.type)); - setObjectParam(handle, "basis", OSP_HERMITE); - commitObject(handle); -} - -void Curve::setSamples(const Data1D &samples) -{ - auto handle = getHandle(); - setObjectParam(handle, "vertex.position_radius", samples); - commitObject(handle); -} - -void Curve::setColors(const Data1D &colors) -{ - auto handle = getHandle(); - setObjectParam(handle, "vertex.color", colors); commitObject(handle); } void loadBoxParams(OSPGeometry handle, const BoxSettings &settings) { - setObjectParam(handle, "box", settings.boxes); + setObjectData(handle, "box", settings.boxes); commitObject(handle); } void loadPlaneParams(OSPGeometry handle, const PlaneSettings &settings) { - setObjectParam(handle, "plane.coefficients", settings.coefficients); - - if (settings.bounds) - { - setObjectParam(handle, "plane.bounds", *settings.bounds); - } - + setObjectData(handle, "plane.coefficients", settings.coefficients); + setObjectDataIfNotEmpty(handle, "plane.bounds", settings.bounds); commitObject(handle); } void loadIsosurfaceParams(OSPGeometry handle, const IsosurfaceSettings &settings) { setObjectParam(handle, "volume", settings.volume); - - std::visit([=](const auto &isovalues) { setObjectParam(handle, "isovalue", isovalues); }, settings.isovalues); - + setObjectData(handle, "isovalue", settings.isovalues); commitObject(handle); } } diff --git a/src/brayns/core/enginev2/Geometry.h b/src/brayns/core/enginev2/Geometry.h index 116b0db44..5a1244557 100644 --- a/src/brayns/core/enginev2/Geometry.h +++ b/src/brayns/core/enginev2/Geometry.h @@ -21,9 +21,6 @@ #pragma once -#include -#include - #include "Data.h" #include "Object.h" #include "Volume.h" @@ -38,24 +35,25 @@ class Geometry : public Managed struct MeshSettings { - Data1D positions; - std::optional> normals = std::nullopt; - std::optional> colors = std::nullopt; - std::optional> uvs = std::nullopt; - std::optional> indices = std::nullopt; + std::span positions; + std::span normals = {}; + std::span colors = {}; + std::span uvs = {}; + std::span indices = {}; }; struct TriangleMeshSettings : MeshSettings { - std::optional> indices = std::nullopt; + std::span indices = {}; }; +void loadMeshParams(OSPGeometry handle, const TriangleMeshSettings &settings); + struct QuadMeshSettings : MeshSettings { - std::optional> indices = std::nullopt; + std::span indices = {}; }; -void loadMeshParams(OSPGeometry handle, const TriangleMeshSettings &settings); void loadMeshParams(OSPGeometry handle, const QuadMeshSettings &settings); class Mesh : public Geometry @@ -63,31 +61,55 @@ class Mesh : public Geometry public: using Geometry::Geometry; - void setColors(const Data1D &colors); + void setColors(std::span colors); }; struct SphereSettings { - Data1D positions; - std::variant> radii; - std::optional> uvs = std::nullopt; + std::span positions; + std::span radii; + std::span uvs = {}; +}; + +void loadSphereParams(OSPGeometry handle, const SphereSettings &settings); + +class Spheres : public Geometry +{ +public: + using Geometry::Geometry; }; struct DiscSettings : SphereSettings { - std::optional> normals; + std::span normals; }; -void loadSphereParams(OSPGeometry handle, const SphereSettings &settings); -void loadSphereParams(OSPGeometry handle, const DiscSettings &settings); +void loadDiscParams(OSPGeometry handle, const DiscSettings &settings); -class Spheres : public Geometry +class Discs : public Geometry { public: using Geometry::Geometry; +}; - void setRadii(const Data1D &radii); - void setRadius(float radius); +using PositionRadius = Vector4; + +struct CylinderSettings +{ + std::span samples; + std::span indices; + std::span colors = {}; + std::span uvs = {}; +}; + +void loadCylinderParams(OSPGeometry handle, const CylinderSettings &settings); + +class Cylinders : public Geometry +{ +public: + using Geometry::Geometry; + + void setColors(std::span colors); }; enum class CurveType @@ -104,51 +126,44 @@ enum class CurveBasis CatmullRom = OSP_CATMULL_ROM, }; -using PositionRadius = Vector4; - -struct CylinderSettings -{ - Data1D samples; - Data1D indices; - std::optional> colors = std::nullopt; - std::optional> uvs = std::nullopt; -}; - struct CurveSettings : CylinderSettings { CurveType type = CurveType::Round; CurveBasis basis = CurveBasis::Linear; }; -struct RibbonCurveSettings : CylinderSettings +void loadCurveParams(OSPGeometry handle, const CurveSettings &settings); + +class Curve : public Cylinders +{ +public: + using Cylinders::Cylinders; +}; + +enum class RibbonBasis { - CurveBasis basis = CurveBasis::Bezier; - Data1D normals; + Bezier = OSP_BEZIER, + Bspline = OSP_BSPLINE, + CatmullRom = OSP_CATMULL_ROM, }; -struct HermiteCurveSettings : CylinderSettings +struct RibbonSettings : CylinderSettings { - CurveType type = CurveType::Round; - Data1D tangents; + RibbonBasis basis = RibbonBasis::Bezier; + std::span normals; }; -void loadCurveParams(OSPGeometry handle, const CylinderSettings &settings); -void loadCurveParams(OSPGeometry handle, const CurveSettings &settings); -void loadCurveParams(OSPGeometry handle, const RibbonCurveSettings &settings); -void loadCurveParams(OSPGeometry handle, const HermiteCurveSettings &settings); +void loadRibbonParams(OSPGeometry handle, const RibbonSettings &settings); -class Curve : public Geometry +class Ribbon : public Cylinders { public: - using Geometry::Geometry; - - void setSamples(const Data1D &samples); - void setColors(const Data1D &colors); + using Cylinders::Cylinders; }; struct BoxSettings { - Data1D boxes; + std::span boxes; }; void loadBoxParams(OSPGeometry handle, const BoxSettings &settings); @@ -161,8 +176,8 @@ class Boxes : public Geometry struct PlaneSettings { - Data1D coefficients; - std::optional> bounds; + std::span coefficients; + std::span bounds; }; void loadPlaneParams(OSPGeometry handle, const PlaneSettings &settings); @@ -176,7 +191,7 @@ class Planes : public Geometry struct IsosurfaceSettings { Volume volume; - std::variant> isovalues; + std::span isovalues; }; void loadIsosurfaceParams(OSPGeometry handle, const IsosurfaceSettings &settings); diff --git a/src/brayns/core/enginev2/Light.cpp b/src/brayns/core/enginev2/Light.cpp index c44150d32..8d41d42d5 100644 --- a/src/brayns/core/enginev2/Light.cpp +++ b/src/brayns/core/enginev2/Light.cpp @@ -21,85 +21,60 @@ #include "Light.h" -namespace brayns::experimental -{ -void Light::setColor(const Color3 &color) -{ - setParam("color", color); -} - -void Light::setIntensity(float intensity) +namespace { - setParam("intensity", intensity); -} +using namespace brayns::experimental; -void Light::setVisible(bool visible) +void setLightParams(OSPLight handle, const LightSettings &settings) { - setParam("visible", visible); + setObjectParam(handle, "color", settings.color); + setObjectParam(handle, "intensity", settings.intensity); + setObjectParam(handle, "visible", settings.visible); } - -void DistantLight::setDirection(const Vector3 &direction) -{ - setParam("direction", direction); } -void DistantLight::setAngularDiameter(float degrees) -{ - setParam("angularDiameter", degrees); -} - -void SphereLight::setPosition(const Vector3 &position) -{ - setParam("position", position); -} - -void SphereLight::setRadius(float radius) -{ - setParam("radius", radius); -} - -void SpotLight::setPosition(const Vector3 &position) -{ - setParam("position", position); -} - -void SpotLight::setDirection(const Vector3 &direction) -{ - setParam("direction", direction); -} - -void SpotLight::setOpeningAngle(float degrees) -{ - setParam("openingAngle", degrees); -} - -void SpotLight::setPenumbraAngle(float degrees) +namespace brayns::experimental { - setParam("penumbraAngle", degrees); -} - -void SpotLight::setOuterRadius(float radius) +void loadLightParams(OSPLight handle, const DistanceLightSettings &settings) { - setParam("radius", radius); + setLightParams(handle, settings); + setObjectParam(handle, "direction", settings.direction); + setObjectParam(handle, "angularDiameter", settings.angularDiameter); + commitObject(handle); } -void SpotLight::setInnerRadius(float radius) +void loadLightParams(OSPLight handle, const SphereLightSettings &settings) { - setParam("innerRadius", radius); + setLightParams(handle, settings); + setObjectParam(handle, "position", settings.position); + setObjectParam(handle, "radius", settings.radius); + commitObject(handle); } -void QuadLight::setPosition(const Vector3 &position) +void loadLightParams(OSPLight handle, const SpotLightSettings &settings) { - setParam("position", position); + setLightParams(handle, settings); + setObjectParam(handle, "position", settings.position); + setObjectParam(handle, "direction", settings.direction); + setObjectParam(handle, "openingAngle", settings.openingAngle); + setObjectParam(handle, "penumbraAngle", settings.penumbraAngle); + setObjectParam(handle, "radius", settings.outerRadius); + setObjectParam(handle, "innerRadius", settings.innerRadius); + commitObject(handle); } -void QuadLight::setEdge1(const Vector3 &edge) +void loadLightParams(OSPLight handle, const QuadLightSettings &settings) { - setParam("edge1", edge); + setLightParams(handle, settings); + setObjectParam(handle, "position", settings.position); + setObjectParam(handle, "edge1", settings.edge1); + setObjectParam(handle, "edge2", settings.edge2); + commitObject(handle); } -void QuadLight::setEdge2(const Vector3 &edge) +void loadLightParams(OSPLight handle, const AmbientLightSettings &settings) { - setParam("edge2", edge); + setLightParams(handle, settings); + commitObject(handle); } } diff --git a/src/brayns/core/enginev2/Light.h b/src/brayns/core/enginev2/Light.h index 664df5f5e..6310f9412 100644 --- a/src/brayns/core/enginev2/Light.h +++ b/src/brayns/core/enginev2/Light.h @@ -25,80 +25,89 @@ namespace brayns::experimental { -class Light : public Object +struct LightSettings +{ + Color3 color = {1.0F, 1.0F, 1.0F}; + float intensity = 1.0F; + bool visible = true; +}; + +class Light : public Managed { public: - using Object::Object; + using Managed::Managed; +}; - void setColor(const Color3 &color); - void setIntensity(float intensity); - void setVisible(bool visible); +struct DistanceLightSettings : LightSettings +{ + Vector3 direction = {0.0F, 0.0F, 1.0F}; + float angularDiameter = 0.0F; }; +void loadLightParams(OSPLight handle, const DistanceLightSettings &settings); + class DistantLight : public Light { public: - static inline const std::string name = "distant"; - using Light::Light; +}; - void setDirection(const Vector3 &direction); - void setAngularDiameter(float degrees); +struct SphereLightSettings : LightSettings +{ + Vector3 position = {0.0F, 0.0F, 0.0F}; + float radius = 0.0F; }; +void loadLightParams(OSPLight handle, const SphereLightSettings &settings); + class SphereLight : public Light { public: - static inline const std::string name = "sphere"; - using Light::Light; +}; - void setPosition(const Vector3 &position); - void setRadius(float radius); +struct SpotLightSettings : LightSettings +{ + Vector3 position = {0.0F, 0.0F, 0.0F}; + Vector3 direction = {0.0F, 0.0F, 1.0F}; + float openingAngle = 180.0F; + float penumbraAngle = 5.0F; + float outerRadius = 0.0F; + float innerRadius = 0.0F; }; +void loadLightParams(OSPLight handle, const SpotLightSettings &settings); + class SpotLight : public Light { public: - static inline const std::string name = "spot"; - using Light::Light; +}; - void setPosition(const Vector3 &position); - void setDirection(const Vector3 &direction); - void setOpeningAngle(float degrees); - void setPenumbraAngle(float degrees); - void setOuterRadius(float radius); - void setInnerRadius(float radius); +struct QuadLightSettings : LightSettings +{ + Vector3 position = {0.0F, 0.0F, 0.0F}; + Vector3 edge1 = {1.0F, 0.0F, 0.0F}; + Vector3 edge2 = {0.0F, 1.0F, 0.0F}; }; +void loadLightParams(OSPLight handle, const QuadLightSettings &settings); + class QuadLight : public Light { public: - static inline const std::string name = "quad"; - using Light::Light; +}; - void setPosition(const Vector3 &position); - void setEdge1(const Vector3 &edge); - void setEdge2(const Vector3 &edge); +struct AmbientLightSettings : LightSettings +{ }; +void loadLightParams(OSPLight handle, const AmbientLightSettings &settings); + class AmbientLight : public Light { public: - static inline const std::string name = "ambient"; - using Light::Light; }; } - -namespace ospray -{ -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::Light, OSP_LIGHT) -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::DistantLight, OSP_LIGHT) -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::SphereLight, OSP_LIGHT) -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::SpotLight, OSP_LIGHT) -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::QuadLight, OSP_LIGHT) -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::AmbientLight, OSP_LIGHT) -} diff --git a/src/brayns/core/enginev2/Material.cpp b/src/brayns/core/enginev2/Material.cpp index 28083fd3e..2083cccd0 100644 --- a/src/brayns/core/enginev2/Material.cpp +++ b/src/brayns/core/enginev2/Material.cpp @@ -21,30 +21,106 @@ #include "Material.h" -namespace brayns::experimental +#include + +namespace { -void ObjMaterial::setDiffuseColor(const Color3 &color) +using namespace brayns::experimental; + +void setTextureParam(OSPMaterial handle, const char *id, std::monostate) { - setParam("kd", color); + removeObjectParam(handle, id); } -void ObjMaterial::setSpecularColor(const Color3 &color) +void setTextureParam(OSPMaterial handle, const char *id, const MaterialTexture2D &texture) { - setParam("ks", color); + setObjectParam(handle, id, texture.value); + + auto name = std::string(id); + + auto rotation = name + ".rotation"; + auto scale = name + ".scale"; + auto translation = name + ".translation"; + + setObjectParam(handle, rotation.c_str(), texture.transform.rotation); + setObjectParam(handle, scale.c_str(), texture.transform.scale); + setObjectParam(handle, translation.c_str(), texture.transform.translation); } -void ObjMaterial::setShininess(float exponent) +void setTextureParam(OSPMaterial handle, const char *id, const MaterialVolumeTexture &texture) +{ + setObjectParam(handle, id, texture.value); + + auto name = std::string(id); + + auto transform = name + ".transform"; + + setObjectParam(handle, transform.c_str(), toAffine(texture.transform)); +} + +void setTextureParam(OSPMaterial handle, const char *id, const MaterialTexture &texture) +{ + std::visit([=](const auto &value) { setTextureParam(handle, id, value); }, texture); +} + +void setMaterialParams(OSPMaterial handle, const AmbientOcclusionMaterialSettings &settings) +{ + setObjectParam(handle, "kd", settings.diffuse); + setTextureParam(handle, "map_kd", settings.diffuseMap); + setObjectParam(handle, "d", settings.opacity); +} +} + +namespace brayns::experimental +{ +void loadMaterialParams(OSPMaterial handle, const AmbientOcclusionMaterialSettings &settings) { - setParam("ns", exponent); + setMaterialParams(handle, settings); + commitObject(handle); } -void ObjMaterial::setOpacity(float opacity) +void loadMaterialParams(OSPMaterial handle, const ScivisMaterialSettings &settings) { - setParam("d", opacity); + setMaterialParams(handle, settings); + setObjectParam(handle, "ks", settings.specular); + setObjectParam(handle, "ns", settings.shininess); + setObjectParam(handle, "tf", settings.transparencyFilter); + commitObject(handle); } -void ObjMaterial::setTransparencyFilter(const Color3 &color) +void loadMaterialParams(OSPMaterial handle, const PrincipledMaterialSettings &settings) { - setParam("tf", color); + setObjectParam(handle, "baseColor", settings.baseColor); + setTextureParam(handle, "map_baseColor", settings.baseColorMap); + setObjectParam(handle, "edgeColor", settings.edgeColor); + setObjectParam(handle, "metallic", settings.metallic); + setObjectParam(handle, "diffuse", settings.diffuse); + setObjectParam(handle, "specular", settings.specular); + setObjectParam(handle, "ior", settings.ior); + setObjectParam(handle, "transmission", settings.transmission); + setObjectParam(handle, "transmissionColor", settings.transmissionColor); + setObjectParam(handle, "transmissionDepth", settings.transmissionDepth); + setObjectParam(handle, "roughness", settings.roughness); + setObjectParam(handle, "anisotropy", settings.anisotropy); + setObjectParam(handle, "rotation", settings.rotation); + setObjectParam(handle, "normal", settings.normal); + setTextureParam(handle, "map_normal", settings.normalMap); + setObjectParam(handle, "baseNormal", settings.baseNormal); + setObjectParam(handle, "thin", settings.thin); + setObjectParam(handle, "thickness", settings.thickness); + setObjectParam(handle, "backlight", settings.backlight); + setObjectParam(handle, "coat", settings.coat); + setObjectParam(handle, "coatIor", settings.coatIor); + setObjectParam(handle, "coatColor", settings.coatColor); + setObjectParam(handle, "coatThickness", settings.coatThickness); + setObjectParam(handle, "coatRoughness", settings.coatRoughness); + setObjectParam(handle, "coatNormal", settings.coatNormal); + setObjectParam(handle, "sheen", settings.sheen); + setObjectParam(handle, "sheenColor", settings.sheenColor); + setObjectParam(handle, "sheenTint", settings.sheenTint); + setObjectParam(handle, "sheenRoughness", settings.sheenRoughness); + setObjectParam(handle, "opacity", settings.opacity); + setObjectParam(handle, "emissiveColor", settings.emissiveColor); + commitObject(handle); } } diff --git a/src/brayns/core/enginev2/Material.h b/src/brayns/core/enginev2/Material.h index a958fbe1b..103065ea2 100644 --- a/src/brayns/core/enginev2/Material.h +++ b/src/brayns/core/enginev2/Material.h @@ -21,33 +21,103 @@ #pragma once +#include + #include "Object.h" +#include "Texture.h" namespace brayns::experimental { -class Material : public Object +class Material : public Managed { public: - using Object::Object; + using Managed::Managed; +}; + +struct MaterialTexture2D +{ + Texture2D value; + TextureTransform transform = {}; +}; + +struct MaterialVolumeTexture +{ + VolumeTexture value; + Transform transform = {}; }; -class ObjMaterial : public Material +using MaterialTexture = std::variant; + +struct AmbientOcclusionMaterialSettings +{ + Color3 diffuse = {0.8F, 0.8F, 0.8F}; + MaterialTexture diffuseMap = {}; + float opacity = 1.0F; +}; + +void loadMaterialParams(OSPMaterial handle, const AmbientOcclusionMaterialSettings &settings); + +class AmbientOcclusionMaterial : public Material { public: - static inline const std::string name = "obj"; + using Material::Material; +}; +struct ScivisMaterialSettings : AmbientOcclusionMaterialSettings +{ + Color3 specular = {0.0F, 0.0F, 0.0F}; + float shininess = 10.0F; + Color3 transparencyFilter = {0.0F, 0.0F, 0.0F}; +}; + +void loadMaterialParams(OSPMaterial handle, const ScivisMaterialSettings &settings); + +class ScivisMaterial : public Material +{ +public: using Material::Material; +}; - void setDiffuseColor(const Color3 &color); - void setSpecularColor(const Color3 &color); - void setShininess(float exponent); - void setOpacity(float opacity); - void setTransparencyFilter(const Color3 &color); +struct PrincipledMaterialSettings +{ + Color3 baseColor = {0.8F, 0.8F, 0.8F}; + MaterialTexture baseColorMap = {}; + Color3 edgeColor = {1.0F, 1.0F, 1.0F}; + float metallic = 0.0F; + float diffuse = 1.0F; + float specular = 1.0F; + float ior = 1.0F; + float transmission = 0.0F; + Color3 transmissionColor = {1.0F, 1.0F, 1.0F}; + float transmissionDepth = 1.0F; + float roughness = 0.0F; + float anisotropy = 0.0F; + float rotation = 0.0F; + float normal = 1.0F; + MaterialTexture normalMap = {}; + float baseNormal = 1.0F; + bool thin = false; + float thickness = 1.0F; + float backlight = 0.0F; + float coat = 0.0F; + float coatIor = 1.5F; + Color3 coatColor = {1.0F, 1.0F, 1.0F}; + float coatThickness = 1.0F; + float coatRoughness = 0.0F; + float coatNormal = 1.0F; + float sheen = 0.0F; + Color3 sheenColor = {1.0F, 1.0F, 1.0F}; + float sheenTint = 0.0F; + float sheenRoughness = 0.2F; + float opacity = 1.0F; + Color3 emissiveColor = {0.0F, 0.0F, 0.0F}; }; -} -namespace ospray +void loadMaterialParams(OSPMaterial handle, const PrincipledMaterialSettings &settings); + +class PrincipledMaterial : public Material { -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::Material, OSP_MATERIAL) -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::ObjMaterial, OSP_MATERIAL) +public: + using Material::Material; +}; } diff --git a/src/brayns/core/enginev2/Texture.cpp b/src/brayns/core/enginev2/Texture.cpp new file mode 100644 index 000000000..d67dd0cc5 --- /dev/null +++ b/src/brayns/core/enginev2/Texture.cpp @@ -0,0 +1,89 @@ +/* Copyright (c) 2015-2024 EPFL/Blue Brain Project + * All rights reserved. Do not distribute without permission. + * + * Responsible Author: adrien.fleury@epfl.ch + * + * This file is part of Brayns + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "Texture.h" + +namespace +{ +using brayns::Size2; +using namespace brayns::experimental; + +OSPDataType getDataType(TextureFormat format) +{ + switch (format) + { + case TextureFormat::Rgba8: + case TextureFormat::Srgba8: + return OSP_UINT; + case TextureFormat::Rgba32F: + return OSP_VEC4F; + case TextureFormat::Rgb8: + case TextureFormat::Srgb8: + return OSP_VEC3UC; + case TextureFormat::Rgb32F: + return OSP_VEC3F; + case TextureFormat::R8: + case TextureFormat::L8: + return OSP_UCHAR; + case TextureFormat::Ra8: + case TextureFormat::La8: + return OSP_VEC2UC; + case TextureFormat::R32F: + return OSP_FLOAT; + case TextureFormat::Rgba16: + return OSP_VEC4US; + case TextureFormat::Rgb16: + return OSP_VEC3US; + case TextureFormat::Ra16: + return OSP_VEC2US; + case TextureFormat::R16: + return OSP_USHORT; + default: + throw std::invalid_argument("Invalid texture format"); + } +} + +Data toSharedData2D(const void *data, const Size2 &size, TextureFormat format) +{ + auto type = getDataType(format); + auto handle = ospNewSharedData(data, type, size[0], 0, size[1]); + return Data(handle); +} +} + +namespace brayns::experimental +{ +void loadTextureParams(OSPTexture handle, const Texture2DSettings &settings) +{ + setObjectParam(handle, "format", static_cast(settings.format)); + setObjectParam(handle, "filter", static_cast(settings.filter)); + setObjectParam(handle, "data", toSharedData2D(settings.data, settings.size, settings.format)); + setObjectParam(handle, "wrapMode", static_cast(settings.wrap)); + commitObject(handle); +} + +void loadTextureParams(OSPTexture handle, const VolumeTextureSettings &settings) +{ + setObjectParam(handle, "volume", settings.volume); + setObjectParam(handle, "transferFunction", settings.transferFunction); + commitObject(handle); +} +} diff --git a/src/brayns/core/enginev2/Texture.h b/src/brayns/core/enginev2/Texture.h new file mode 100644 index 000000000..1ba961cb9 --- /dev/null +++ b/src/brayns/core/enginev2/Texture.h @@ -0,0 +1,105 @@ +/* Copyright (c) 2015-2024 EPFL/Blue Brain Project + * All rights reserved. Do not distribute without permission. + * + * Responsible Author: adrien.fleury@epfl.ch + * + * This file is part of Brayns + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +#include "Data.h" +#include "Object.h" +#include "Volume.h" + +namespace brayns::experimental +{ +enum class TextureFormat +{ + Rgba8 = OSP_TEXTURE_RGBA8, + Srgba8 = OSP_TEXTURE_SRGBA, + Rgba32F = OSP_TEXTURE_RGBA32F, + Rgb8 = OSP_TEXTURE_RGB8, + Srgb8 = OSP_TEXTURE_SRGB, + Rgb32F = OSP_TEXTURE_RGB32F, + R8 = OSP_TEXTURE_R8, + Ra8 = OSP_TEXTURE_RA8, + L8 = OSP_TEXTURE_L8, + La8 = OSP_TEXTURE_LA8, + R32F = OSP_TEXTURE_R32F, + Rgba16 = OSP_TEXTURE_RGBA16, + Rgb16 = OSP_TEXTURE_RGB16, + Ra16 = OSP_TEXTURE_RA16, + R16 = OSP_TEXTURE_R16, +}; + +enum class TextureFilter +{ + Linear = OSP_TEXTURE_FILTER_LINEAR, + Nearest = OSP_TEXTURE_FILTER_NEAREST, +}; + +enum class TextureWrap +{ + Repeat = OSP_TEXTURE_WRAP_REPEAT, + MirroredRepeat = OSP_TEXTURE_WRAP_MIRRORED_REPEAT, + ClampToEdge = OSP_TEXTURE_WRAP_CLAMP_TO_EDGE, +}; + +class Texture : public Managed +{ +public: + using Managed::Managed; +}; + +struct Texture2DSettings +{ + const void *data; + Size2 size; + TextureFormat format; + TextureFilter filter = TextureFilter::Linear; + TextureWrap wrap = TextureWrap::Repeat; +}; + +void loadTextureParams(OSPTexture handle, const Texture2DSettings &settings); + +class Texture2D : public Texture +{ +public: + using Texture::Texture; +}; + +struct TextureTransform +{ + float rotation = 0.0F; + Vector2 scale = {1.0F, 1.0F}; + Vector2 translation = {0.0F, 0.0F}; +}; + +struct VolumeTextureSettings +{ + Volume volume; + TransferFunction transferFunction; +}; + +void loadTextureParams(OSPTexture handle, const VolumeTextureSettings &settings); + +class VolumeTexture : public Texture +{ +public: + using Texture::Texture; +}; +} diff --git a/src/brayns/core/utils/Math.h b/src/brayns/core/utils/Math.h index b3d5020f7..d31691725 100644 --- a/src/brayns/core/utils/Math.h +++ b/src/brayns/core/utils/Math.h @@ -78,4 +78,16 @@ inline Affine3 toAffine(const Transform &transform) auto scale = rkcommon::math::LinearSpace3f::scale(transform.scale); return Affine3(rotation * scale, translation); } + +template +T identity() +{ + return T(rkcommon::math::OneTy()); +} + +template +T zeros() +{ + return T(rkcommon::math::ZeroTy()); +} } From b1cb77a01d982bb6dd73a8365773890c608c8d17 Mon Sep 17 00:00:00 2001 From: Adrien4193 Date: Thu, 6 Jun 2024 13:52:33 +0200 Subject: [PATCH 3/7] Checkpoint all implemented. --- src/brayns/core/enginev2/Data.h | 6 +- src/brayns/core/enginev2/Framebuffer.h | 5 ++ src/brayns/core/enginev2/Render.h | 17 +++- src/brayns/core/enginev2/Renderer.cpp | 84 ++++++++----------- src/brayns/core/enginev2/Renderer.h | 72 +++++++++------- src/brayns/core/enginev2/Texture.cpp | 7 +- src/brayns/core/enginev2/Texture.h | 3 +- src/brayns/core/enginev2/TransferFunction.cpp | 33 ++++++++ src/brayns/core/enginev2/TransferFunction.h | 49 +++++++++++ src/brayns/core/enginev2/Volume.cpp | 63 ++++---------- src/brayns/core/enginev2/Volume.h | 78 ++++------------- src/brayns/core/enginev2/VolumetricModel.cpp | 35 ++++++++ src/brayns/core/enginev2/VolumetricModel.h | 46 ++++++++++ src/brayns/core/enginev2/World.cpp | 45 +++++----- src/brayns/core/enginev2/World.h | 63 ++++++++------ src/brayns/core/utils/Math.h | 14 +--- 16 files changed, 365 insertions(+), 255 deletions(-) create mode 100644 src/brayns/core/enginev2/TransferFunction.cpp create mode 100644 src/brayns/core/enginev2/TransferFunction.h create mode 100644 src/brayns/core/enginev2/VolumetricModel.cpp create mode 100644 src/brayns/core/enginev2/VolumetricModel.h diff --git a/src/brayns/core/enginev2/Data.h b/src/brayns/core/enginev2/Data.h index 76d708a08..d463f4b10 100644 --- a/src/brayns/core/enginev2/Data.h +++ b/src/brayns/core/enginev2/Data.h @@ -33,7 +33,7 @@ class Data : public Managed using Managed::Managed; }; -template +template Data toSharedData(std::span items) { auto data = items.data(); @@ -43,13 +43,13 @@ Data toSharedData(std::span items) return Data(handle); } -template +template void setObjectData(OSPObject handle, const char *id, std::span items) { setObjectParam(handle, id, toSharedData(items)); } -template +template void setObjectDataIfNotEmpty(OSPObject handle, const char *id, std::span items) { if (items.empty()) diff --git a/src/brayns/core/enginev2/Framebuffer.h b/src/brayns/core/enginev2/Framebuffer.h index f271e1810..0d51b4dfb 100644 --- a/src/brayns/core/enginev2/Framebuffer.h +++ b/src/brayns/core/enginev2/Framebuffer.h @@ -76,6 +76,11 @@ FramebufferChannel operator|(FramebufferChannel left, FramebufferChannel right) return static_cast(static_cast(left) | static_cast(right)); } +FramebufferChannel &operator|=(FramebufferChannel &left, FramebufferChannel right) +{ + return left = left | right; +} + bool operator&(FramebufferChannel channels, FramebufferChannel channel) { return static_cast(channels) & static_cast(channel) != 0; diff --git a/src/brayns/core/enginev2/Render.h b/src/brayns/core/enginev2/Render.h index b9b77994c..4cecdf519 100644 --- a/src/brayns/core/enginev2/Render.h +++ b/src/brayns/core/enginev2/Render.h @@ -37,14 +37,27 @@ struct RenderSettings World world; }; -class RenderTask : public Object +class RenderTask : public Managed { public: - using Object::Object; + using Managed::Managed; bool isReady() const; float getProgress() const; void cancel(); float waitAndGetDuration(); }; + +struct PickSettings : RenderSettings +{ + Vector2 normalizedScreenPosition; +}; + +struct PickResult +{ + Vector3 worldPosition; + Instance instance; + GeometricModel model; + std::uint32_t primitiveIndex; +}; } diff --git a/src/brayns/core/enginev2/Renderer.cpp b/src/brayns/core/enginev2/Renderer.cpp index a702be389..d241576d0 100644 --- a/src/brayns/core/enginev2/Renderer.cpp +++ b/src/brayns/core/enginev2/Renderer.cpp @@ -21,75 +21,65 @@ #include "Renderer.h" -namespace brayns::experimental -{ -void Renderer::setPixelSamples(std::size_t count) -{ - setParam("pixelSamples", static_cast(count)); -} - -void Renderer::setMaxRayRecursion(std::size_t depth) -{ - setParam("maxPathLength", static_cast(depth)); -} - -void Renderer::setMinSampleContribution(float intensity) -{ - setParam("minContribution", intensity); -} - -void Renderer::setVarianceThreshold(float threshold) +namespace { - setParam("varianceThreshold", threshold); -} - -void Renderer::setBackgroundColor(const Color4 &color) -{ - setParam("backgroundColor", color); -} +using brayns::Color4; +using namespace brayns::experimental; -void Renderer::setMaterials(SharedArray materials) +void setBackgroundParam(OSPRenderer handle, const Color4 &color) { - setParam("material", toSharedData(materials)); + setObjectParam(handle, "backgroundColor", color); } -void Renderer::setPixelFilter(PixelFilter filter) +void setBackgroundParam(OSPRenderer handle, const Texture2D &texture) { - setParam("pixelFilter", static_cast(filter)); + setObjectParam(handle, "map_backplate", texture); } -void AmbientOcclusionRenderer::setAoSamples(std::size_t count) +void setBackground(OSPRenderer handle, const Background &background) { - setParam("aoSamples", static_cast(count)); + std::visit([=](const auto &value) { setBackgroundParam(handle, value); }, background); } -void AmbientOcclusionRenderer::setAoDistance(float distance) +void setRendererParams(OSPRenderer handle, const RendererSettings &settings) { - setParam("aoDistance", distance); + setObjectParam(handle, "pixelSamples", settings.pixelSamples); + setObjectParam(handle, "maxPathLength", settings.maxRayRecursionDepth); + setObjectParam(handle, "minContribution", settings.minSampleContribution); + setObjectParam(handle, "varianceThreshold", settings.varianceThreshold); + setBackground(handle, settings.background); + setObjectData(handle, "material", settings.materials); + setObjectParam(handle, "pixelFilter", static_cast(settings.pixelFilter)); + commitObject(handle); } - -void AmbientOcclusionRenderer::setAoIntensity(float intensity) -{ - setParam("aoIntensity", intensity); } -void ScivisRenderer::enableShadows(bool enable) +namespace brayns::experimental { - setParam("shadows", enable); -} - -void ScivisRenderer::setAoSamples(std::size_t count) +void loadRendererParams(OSPRenderer handle, const AmbientOcclusionRendererSettings &settings) { - setParam("aoSamples", static_cast(count)); + setRendererParams(handle, settings); + setObjectParam(handle, "aoSamples", settings.aoSamples); + setObjectParam(handle, "aoDistance", settings.aoDistance); + setObjectParam(handle, "aoIntensity", settings.aoIntensity); + setObjectParam(handle, "volumeSamplingRate", settings.volumeSamplingRate); + commitObject(handle); } -void ScivisRenderer::setAoDistance(float distance) +void loadRendererParams(OSPRenderer handle, const ScivisRendererSettings &settings) { - setParam("aoDistance", distance); + setRendererParams(handle, settings); + setObjectParam(handle, "shadows", settings.shadows); + setObjectParam(handle, "aoSamples", settings.aoSamples); + setObjectParam(handle, "aoDistance", settings.aoDistance); + setObjectParam(handle, "volumeSamplingRate", settings.volumeSamplingRate); + setObjectParam(handle, "visibleLights", settings.showVisibleLights); + commitObject(handle); } -void ScivisRenderer::showLights(bool show) +void loadRendererParams(OSPRenderer handle, const PathTracerSettings &settings) { - setParam("visibleLights", show); + setRendererParams(handle, settings); + commitObject(handle); } } diff --git a/src/brayns/core/enginev2/Renderer.h b/src/brayns/core/enginev2/Renderer.h index 6da10d0f0..e985b4f86 100644 --- a/src/brayns/core/enginev2/Renderer.h +++ b/src/brayns/core/enginev2/Renderer.h @@ -21,9 +21,12 @@ #pragma once +#include + #include "Data.h" #include "Material.h" #include "Object.h" +#include "Texture.h" namespace brayns::experimental { @@ -36,58 +39,67 @@ enum class PixelFilter BlackmanHarris = OSP_PIXELFILTER_BLACKMAN_HARRIS, }; -class Renderer : public Object +using Background = std::variant; + +struct RendererSettings +{ + std::size_t pixelSamples = 1; + std::size_t maxRayRecursionDepth = 20; + float minSampleContribution = 0.001F; + float varianceThreshold = 0.0F; + Background background = Color4(0.0F, 0.0F, 0.0F, 0.0F); + std::span materials = {}; + PixelFilter pixelFilter = PixelFilter::Gauss; +}; + +class Renderer : public Managed { public: - using Object::Object; - - void setPixelSamples(std::size_t count); - void setMaxRayRecursion(std::size_t depth); - void setMinSampleContribution(float intensity); - void setVarianceThreshold(float threshold); - void setBackgroundColor(const Color4 &color); - void setMaterials(SharedArray materials); - void setPixelFilter(PixelFilter filter); + using Managed::Managed; }; +struct AmbientOcclusionRendererSettings : RendererSettings +{ + std::size_t aoSamples = 1; + float aoDistance = 1e20F; + float aoIntensity = 1.0F; + float volumeSamplingRate = 1.0F; +}; + +void loadRendererParams(OSPRenderer handle, const AmbientOcclusionRendererSettings &settings); + class AmbientOcclusionRenderer : public Renderer { public: - static inline const std::string name = "ao"; - using Renderer::Renderer; +}; - void setAoSamples(std::size_t count); - void setAoDistance(float distance); - void setAoIntensity(float intensity); +struct ScivisRendererSettings : RendererSettings +{ + bool shadows = false; + std::size_t aoSamples = 0; + float aoDistance = 1e20F; + float volumeSamplingRate = 1.0F; + bool showVisibleLights = false; }; +void loadRendererParams(OSPRenderer handle, const ScivisRendererSettings &settings); + class ScivisRenderer : public Renderer { public: - static inline const std::string name = "scivis"; - using Renderer::Renderer; +}; - void enableShadows(bool enable); - void setAoSamples(std::size_t count); - void setAoDistance(float distance); - void showLights(bool show); +struct PathTracerSettings : RendererSettings +{ }; class PathTracer : public Renderer { public: - static inline const std::string name = "pathtracer"; - using Renderer::Renderer; }; -} -namespace ospray -{ -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::Renderer, OSP_RENDERER) -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::AmbientOcclusionRenderer, OSP_RENDERER) -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::ScivisRenderer, OSP_RENDERER) -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::PathTracer, OSP_RENDERER) +void loadRendererParams(OSPRenderer handle, const PathTracerSettings &settings); } diff --git a/src/brayns/core/enginev2/Texture.cpp b/src/brayns/core/enginev2/Texture.cpp index d67dd0cc5..45f9f2da5 100644 --- a/src/brayns/core/enginev2/Texture.cpp +++ b/src/brayns/core/enginev2/Texture.cpp @@ -61,7 +61,7 @@ OSPDataType getDataType(TextureFormat format) } } -Data toSharedData2D(const void *data, const Size2 &size, TextureFormat format) +Data toSharedData2D(const void *data, TextureFormat format, const Size2 &size) { auto type = getDataType(format); auto handle = ospNewSharedData(data, type, size[0], 0, size[1]); @@ -73,10 +73,13 @@ namespace brayns::experimental { void loadTextureParams(OSPTexture handle, const Texture2DSettings &settings) { + auto data = toSharedData2D(settings.data, settings.format, settings.size); + setObjectParam(handle, "format", static_cast(settings.format)); setObjectParam(handle, "filter", static_cast(settings.filter)); - setObjectParam(handle, "data", toSharedData2D(settings.data, settings.size, settings.format)); + setObjectParam(handle, "data", data); setObjectParam(handle, "wrapMode", static_cast(settings.wrap)); + commitObject(handle); } diff --git a/src/brayns/core/enginev2/Texture.h b/src/brayns/core/enginev2/Texture.h index 1ba961cb9..bbc754f20 100644 --- a/src/brayns/core/enginev2/Texture.h +++ b/src/brayns/core/enginev2/Texture.h @@ -23,6 +23,7 @@ #include "Data.h" #include "Object.h" +#include "TransferFunction.h" #include "Volume.h" namespace brayns::experimental @@ -68,8 +69,8 @@ class Texture : public Managed struct Texture2DSettings { const void *data; - Size2 size; TextureFormat format; + Size2 size; TextureFilter filter = TextureFilter::Linear; TextureWrap wrap = TextureWrap::Repeat; }; diff --git a/src/brayns/core/enginev2/TransferFunction.cpp b/src/brayns/core/enginev2/TransferFunction.cpp new file mode 100644 index 000000000..89b7e311f --- /dev/null +++ b/src/brayns/core/enginev2/TransferFunction.cpp @@ -0,0 +1,33 @@ +/* Copyright (c) 2015-2024 EPFL/Blue Brain Project + * All rights reserved. Do not distribute without permission. + * + * Responsible Author: adrien.fleury@epfl.ch + * + * This file is part of Brayns + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "TransferFunction.h" + +namespace brayns::experimental +{ +void loadTransferFunctionParams(OSPTransferFunction handle, const LinearTransferFunctionSettings &settings) +{ + setObjectData(handle, "color", settings.colors); + setObjectData(handle, "opacity", settings.opacities); + setObjectParam(handle, "value", settings.scalarRange); + commitObject(handle); +} +} diff --git a/src/brayns/core/enginev2/TransferFunction.h b/src/brayns/core/enginev2/TransferFunction.h new file mode 100644 index 000000000..3adaf1894 --- /dev/null +++ b/src/brayns/core/enginev2/TransferFunction.h @@ -0,0 +1,49 @@ +/* Copyright (c) 2015-2024 EPFL/Blue Brain Project + * All rights reserved. Do not distribute without permission. + * + * Responsible Author: adrien.fleury@epfl.ch + * + * This file is part of Brayns + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +#include "Data.h" +#include "Object.h" + +namespace brayns::experimental +{ +class TransferFunction : public Managed +{ +public: + using Managed::Managed; +}; + +struct LinearTransferFunctionSettings +{ + std::span colors; + std::span opacities; + Box1 scalarRange; +}; + +void loadTransferFunctionParams(OSPTransferFunction handle, const LinearTransferFunctionSettings &settings); + +class LinearTransferFunction : public TransferFunction +{ +public: + using TransferFunction::TransferFunction; +}; +} diff --git a/src/brayns/core/enginev2/Volume.cpp b/src/brayns/core/enginev2/Volume.cpp index 5fd56d853..337203531 100644 --- a/src/brayns/core/enginev2/Volume.cpp +++ b/src/brayns/core/enginev2/Volume.cpp @@ -21,63 +21,30 @@ #include "Volume.h" -namespace brayns::experimental -{ -void LinearTransferFunction::setColors(SharedArray colors) -{ - setParam("color", toSharedData(colors)); -} - -void LinearTransferFunction::setOpacities(SharedArray opacities) -{ - setParam("opacity", toSharedData(opacities)); -} - -void LinearTransferFunction::setScalarRange(Box1 range) -{ - setParam("value", range); -} - -void VolumetricModel::setVolume(const Volume &volume) -{ - setParam("volume", volume.getHandle()); -} - -void VolumetricModel::setTransferFunction(const TransferFunction &function) +namespace { - setParam("transferFunction", function.getHandle()); -} +using brayns::Size3; +using namespace brayns::experimental; -void VolumetricModel::setId(std::uint32_t id) +Data toSharedData3D(const void *data, VoxelDataType voxelDataType, const Size3 &size) { - setParam("id", id); + auto type = static_cast(voxelDataType); + auto handle = ospNewSharedData(data, type, size[0], 0, size[1], 0, size[2]); + return Data(handle); } - -void StructuredRegularVolume::setData(const VolumeData &data) -{ - auto format = static_cast(data.type); - auto shared = ospray::cpp::SharedData(data.data, format, data.size); - setParam("data", shared); } -void StructuredRegularVolume::setStructure(VolumeStructure structure) +namespace brayns::experimental { - auto cellCentered = structure == VolumeStructure::CellCentered; - setParam("cellCentered", cellCentered); -} - -void StructuredRegularVolume::setOrigin(const Vector3 &origin) +void loadVolumeParams(OSPVolume handle, const RegularVolumeSettings &settings) { - setParam("gridOrigin", origin); -} + auto data = toSharedData3D(settings.data, settings.voxelDataType, settings.size); -void StructuredRegularVolume::setSpacing(const Vector3 &spacing) -{ - setParam("gridSpacing", spacing); -} + setObjectParam(handle, "data", data); + setObjectParam(handle, "cellCentered", settings.cellCentered); + setObjectParam(handle, "filter", static_cast(settings.filter)); + setObjectParam(handle, "background", settings.background); -void StructuredRegularVolume::setFilter(VolumeFilter filter) -{ - setParam("filter", static_cast(filter)); + commitObject(handle); } } diff --git a/src/brayns/core/enginev2/Volume.h b/src/brayns/core/enginev2/Volume.h index ac289679d..5f9008a3e 100644 --- a/src/brayns/core/enginev2/Volume.h +++ b/src/brayns/core/enginev2/Volume.h @@ -21,43 +21,17 @@ #pragma once +#include + #include "Data.h" #include "Object.h" namespace brayns::experimental { -class TransferFunction : public Object -{ -public: - using Object::Object; -}; - -class LinearTransferFunction : public TransferFunction -{ -public: - static inline const std::string name = "piecewiseLinear"; - - using TransferFunction::TransferFunction; - - void setColors(SharedArray colors); - void setOpacities(SharedArray opacities); - void setScalarRange(Box1 range); -}; - -class Volume : public Object -{ -public: - using Object::Object; -}; - -class VolumetricModel : public Object +class Volume : public Managed { public: - using Object::Object; - - void setVolume(const Volume &volume); - void setTransferFunction(const TransferFunction &function); - void setId(std::uint32_t id); + using Managed::Managed; }; enum class VoxelDataType @@ -70,19 +44,6 @@ enum class VoxelDataType Double = OSP_DOUBLE, }; -struct VolumeData -{ - const void *data; - VoxelDataType type; - Size3 size; -}; - -enum class VolumeStructure -{ - VertexCentered, - CellCentered, -}; - enum class VolumeFilter { Nearest = OSP_VOLUME_FILTER_NEAREST, @@ -90,26 +51,21 @@ enum class VolumeFilter Cubic = OSP_VOLUME_FILTER_CUBIC, }; -class StructuredRegularVolume : public Volume +struct RegularVolumeSettings { -public: - static inline const std::string name = "structuredRegular"; - - using Volume::Volume; - - void setData(const VolumeData &data); - void setStructure(VolumeStructure structure); - void setOrigin(const Vector3 &origin); - void setSpacing(const Vector3 &spacing); - void setFilter(VolumeFilter filter); + const void *data; + VoxelDataType voxelDataType; + Size3 size; + bool cellCentered = false; + VolumeFilter filter = VolumeFilter::Linear; + float background = std::numeric_limits::quiet_NaN(); }; -} -namespace ospray +void loadVolumeParams(OSPVolume handle, const RegularVolumeSettings &settings); + +class RegularVolume : public Volume { -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::TransferFunction, OSP_TRANSFER_FUNCTION) -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::LinearTransferFunction, OSP_TRANSFER_FUNCTION) -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::Volume, OSP_VOLUME) -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::VolumetricModel, OSP_VOLUMETRIC_MODEL) -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::StructuredRegularVolume, OSP_VOLUME) +public: + using Volume::Volume; +}; } diff --git a/src/brayns/core/enginev2/VolumetricModel.cpp b/src/brayns/core/enginev2/VolumetricModel.cpp new file mode 100644 index 000000000..85558b2c3 --- /dev/null +++ b/src/brayns/core/enginev2/VolumetricModel.cpp @@ -0,0 +1,35 @@ +/* Copyright (c) 2015-2024 EPFL/Blue Brain Project + * All rights reserved. Do not distribute without permission. + * + * Responsible Author: adrien.fleury@epfl.ch + * + * This file is part of Brayns + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "VolumetricModel.h" + +namespace brayns::experimental +{ +void loadVolumetricModelParams(OSPVolumetricModel handle, const VolumetricModelSettings &settings) +{ + setObjectParam(handle, "volume", settings.volume); + setObjectParam(handle, "transferFunction", settings.transferFunction); + setObjectParam(handle, "densityScale", settings.densityScale); + setObjectParam(handle, "anisotropy", settings.anisotropy); + setObjectParam(handle, "id", settings.id); + commitObject(handle); +} +} diff --git a/src/brayns/core/enginev2/VolumetricModel.h b/src/brayns/core/enginev2/VolumetricModel.h new file mode 100644 index 000000000..47f3a8c54 --- /dev/null +++ b/src/brayns/core/enginev2/VolumetricModel.h @@ -0,0 +1,46 @@ +/* Copyright (c) 2015-2024 EPFL/Blue Brain Project + * All rights reserved. Do not distribute without permission. + * + * Responsible Author: adrien.fleury@epfl.ch + * + * This file is part of Brayns + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +#include "Object.h" +#include "TransferFunction.h" +#include "Volume.h" + +namespace brayns::experimental +{ +struct VolumetricModelSettings +{ + Volume volume; + TransferFunction transferFunction; + float densityScale = 1.0F; + float anisotropy = 0.0F; + std::uint32_t id = std::uint32_t(-1); +}; + +void loadVolumetricModelParams(OSPVolumetricModel handle, const VolumetricModelSettings &settings); + +class VolumetricModel : public Managed +{ +public: + using Managed::Managed; +}; +} diff --git a/src/brayns/core/enginev2/World.cpp b/src/brayns/core/enginev2/World.cpp index 62056fdfa..39f8ebcf4 100644 --- a/src/brayns/core/enginev2/World.cpp +++ b/src/brayns/core/enginev2/World.cpp @@ -23,43 +23,44 @@ namespace brayns::experimental { -void Group::setVolumes(SharedArray models) +void loadGroupParams(OSPGroup handle, const GroupSettings &settings) { - setParam("volume", toSharedData(models)); + setObjectDataIfNotEmpty(handle, "geometry", settings.geometries); + setObjectDataIfNotEmpty(handle, "volume", settings.volumes); + setObjectDataIfNotEmpty(handle, "clippingGeometry", settings.clippingGeometries); + setObjectDataIfNotEmpty(handle, "light", settings.lights); + commitObject(handle); } -void Group::setGeometries(SharedArray models) +Box3 Group::getBounds() const { - setParam("geometry", toSharedData(models)); + auto handle = getHandle(); + return getObjectBounds(handle); } -void Group::setClippingGeometries(SharedArray models) +void loadInstanceParams(OSPInstance handle, const InstanceSettings &settings) { - setParam("clippingGeometry", toSharedData(models)); + setObjectParam(handle, "group", settings.group); + setObjectParam(handle, "transform", toAffine(settings.transform)); + setObjectParam(handle, "id", settings.id); + commitObject(handle); } -void Group::setLights(SharedArray lights) +Box3 Instance::getBounds() const { - setParam("light", toSharedData(lights)); + auto handle = getHandle(); + return getObjectBounds(handle); } -void Instance::setGroup(const Group &group) +void loadWorldParams(OSPWorld handle, const WorldSettings &settings) { - setParam("group", group.getHandle()); + setObjectData(handle, "instance", settings.instances); + commitObject(handle); } -void Instance::setTransform(const Affine3 &transform) +Box3 World::getBounds() const { - setParam("transform", transform); -} - -void Instance::setId(std::uint32_t id) -{ - setParam("id", id); -} - -void World::setInstances(SharedArray instances) -{ - setParam("instance", toSharedData(instances)); + auto handle = getHandle(); + return getObjectBounds(handle); } } diff --git a/src/brayns/core/enginev2/World.h b/src/brayns/core/enginev2/World.h index 9c7fab6f4..6b2fc4166 100644 --- a/src/brayns/core/enginev2/World.h +++ b/src/brayns/core/enginev2/World.h @@ -22,49 +22,60 @@ #pragma once #include "Data.h" -#include "Geometry.h" +#include "GeometricModel.h" #include "Light.h" #include "Object.h" -#include "Volume.h" +#include "VolumetricModel.h" namespace brayns::experimental { -class Group : public Object +struct GroupSettings { -public: - using Object::getBounds; - using Object::Object; - - void setVolumes(SharedArray models); - void setGeometries(SharedArray models); - void setClippingGeometries(SharedArray models); - void setLights(SharedArray lights); + std::span geometries = {}; + std::span volumes = {}; + std::span clippingGeometries = {}; + std::span lights = {}; }; -class Instance : public Object +void loadGroupParams(OSPGroup handle, const GroupSettings &settings); + +class Group : public Managed { public: - using Object::getBounds; - using Object::Object; + using Managed::Managed; + + Box3 getBounds() const; +}; - void setGroup(const Group &group); - void setTransform(const Affine3 &transform); - void setId(std::uint32_t id); +struct InstanceSettings +{ + Group group; + Transform transform; + std::uint32_t id = std::uint32_t(-1); }; -class World : public Object +void loadInstanceParams(OSPInstance handle, const InstanceSettings &settings); + +class Instance : public Managed { public: - using Object::getBounds; - using Object::Object; + using Managed::Managed; - void setInstances(SharedArray instances); + Box3 getBounds() const; }; -} -namespace ospray +struct WorldSettings { -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::Group, OSP_GROUP) -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::Instance, OSP_INSTANCE) -OSPTYPEFOR_SPECIALIZATION(brayns::experimental::World, OSP_WORLD) + std::span instances; +}; + +void loadWorldParams(OSPWorld handle, const WorldSettings &settings); + +class World : public Managed +{ +public: + using Managed::Managed; + + Box3 getBounds() const; +}; } diff --git a/src/brayns/core/utils/Math.h b/src/brayns/core/utils/Math.h index d31691725..48027a2b9 100644 --- a/src/brayns/core/utils/Math.h +++ b/src/brayns/core/utils/Math.h @@ -49,7 +49,7 @@ using Quaternion = rkcommon::math::quaternionf; template using Box = rkcommon::math::box_t; -using Box1 = Box; +using Box1 = rkcommon::math::box1f; using Box2 = Box; using Box3 = Box; @@ -78,16 +78,4 @@ inline Affine3 toAffine(const Transform &transform) auto scale = rkcommon::math::LinearSpace3f::scale(transform.scale); return Affine3(rotation * scale, translation); } - -template -T identity() -{ - return T(rkcommon::math::OneTy()); -} - -template -T zeros() -{ - return T(rkcommon::math::ZeroTy()); -} } From b56a715947c1f4a6e607f58ee376fb86acec66a3 Mon Sep 17 00:00:00 2001 From: Adrien4193 Date: Thu, 6 Jun 2024 17:09:15 +0200 Subject: [PATCH 4/7] Checkpoint. --- src/brayns/core/enginev2/Camera.cpp | 4 +- src/brayns/core/enginev2/Camera.h | 22 ++- src/brayns/core/enginev2/Device.cpp | 78 +++++++++- src/brayns/core/enginev2/Device.h | 103 ++++++++----- src/brayns/core/enginev2/Framebuffer.cpp | 15 +- src/brayns/core/enginev2/Framebuffer.h | 50 +------ src/brayns/core/enginev2/GeometricModel.cpp | 24 ++-- src/brayns/core/enginev2/GeometricModel.h | 7 +- src/brayns/core/enginev2/Geometry.cpp | 20 +-- src/brayns/core/enginev2/Geometry.h | 136 +++++++++++++++--- src/brayns/core/enginev2/ImageOperation.cpp | 36 +++++ src/brayns/core/enginev2/ImageOperation.h | 62 ++++++++ src/brayns/core/enginev2/Light.cpp | 10 +- src/brayns/core/enginev2/Light.h | 62 ++++++-- src/brayns/core/enginev2/Material.cpp | 6 +- src/brayns/core/enginev2/Material.h | 48 +++++-- src/brayns/core/enginev2/Object.h | 22 +++ src/brayns/core/enginev2/Renderer.cpp | 7 +- src/brayns/core/enginev2/Renderer.h | 34 ++++- src/brayns/core/enginev2/Texture.cpp | 4 +- src/brayns/core/enginev2/Texture.h | 38 +++-- src/brayns/core/enginev2/TransferFunction.cpp | 2 +- src/brayns/core/enginev2/TransferFunction.h | 12 +- src/brayns/core/enginev2/Volume.cpp | 2 +- src/brayns/core/enginev2/Volume.h | 12 +- src/brayns/core/enginev2/VolumetricModel.h | 4 +- src/brayns/core/enginev2/World.cpp | 36 ++--- src/brayns/core/enginev2/World.h | 10 +- 28 files changed, 635 insertions(+), 231 deletions(-) create mode 100644 src/brayns/core/enginev2/ImageOperation.cpp create mode 100644 src/brayns/core/enginev2/ImageOperation.h diff --git a/src/brayns/core/enginev2/Camera.cpp b/src/brayns/core/enginev2/Camera.cpp index 2fac5b195..b06b98e33 100644 --- a/src/brayns/core/enginev2/Camera.cpp +++ b/src/brayns/core/enginev2/Camera.cpp @@ -36,7 +36,7 @@ void setCameraParams(OSPCamera handle, const CameraSettings &settings) namespace brayns::experimental { -void loadPerspectiveCameraParams(OSPCamera handle, const PerspectiveCameraSettings &settings) +void ObjectReflector::loadParams(OSPCamera handle, const Settings &settings) { setCameraParams(handle, settings); setObjectParam(handle, "fovy", settings.fovy); @@ -44,7 +44,7 @@ void loadPerspectiveCameraParams(OSPCamera handle, const PerspectiveCameraSettin commitObject(handle); } -void loadOrthographicCameraParams(OSPCamera handle, const OrthographicCameraSettings &settings) +void ObjectReflector::loadParams(OSPCamera handle, const Settings &settings) { setCameraParams(handle, settings); setObjectParam(handle, "height", settings.height); diff --git a/src/brayns/core/enginev2/Camera.h b/src/brayns/core/enginev2/Camera.h index a1de56fcb..cc9ef86a1 100644 --- a/src/brayns/core/enginev2/Camera.h +++ b/src/brayns/core/enginev2/Camera.h @@ -51,7 +51,15 @@ class PerspectiveCamera : public Camera using Camera::Camera; }; -void loadPerspectiveCameraParams(OSPCamera handle, const PerspectiveCameraSettings &settings); +template<> +struct ObjectReflector +{ + using Settings = PerspectiveCameraSettings; + + static inline const std::string name = "perspective"; + + static void loadParams(OSPCamera handle, const Settings &settings); +}; struct OrthographicCameraSettings : CameraSettings { @@ -59,11 +67,19 @@ struct OrthographicCameraSettings : CameraSettings float aspectRatio = 1.0F; }; -void loadOrthographicCameraParams(OSPCamera handle, const OrthographicCameraSettings &settings); - class OrthographicCamera : public Camera { public: using Camera::Camera; }; + +template<> +struct ObjectReflector +{ + using Settings = OrthographicCameraSettings; + + static inline const std::string name = "orthographic"; + + static void loadParams(OSPCamera handle, const Settings &settings); +}; } diff --git a/src/brayns/core/enginev2/Device.cpp b/src/brayns/core/enginev2/Device.cpp index e2f5c71fe..933607dc4 100644 --- a/src/brayns/core/enginev2/Device.cpp +++ b/src/brayns/core/enginev2/Device.cpp @@ -28,33 +28,48 @@ Device::Device(OSPDevice handle): { } -GeometricModel Device::createGeometricModel() +OSPDevice Device::getHandle() const +{ + return _handle.get(); +} + +GeometricModel Device::createGeometricModel(const GeometricModelSettings &settings) { auto handle = ospNewGeometricModel(); + throwIfNull(handle); + loadGeometricModelParams(handle, settings); return GeometricModel(handle); } -VolumetricModel Device::createVolumetricModel() +VolumetricModel Device::createVolumetricModel(const VolumetricModelSettings &settings) { auto handle = ospNewVolumetricModel(); + throwIfNull(handle); + loadVolumetricModelParams(handle, settings); return VolumetricModel(handle); } -Group Device::createGroup() +Group Device::createGroup(const GroupSettings &settings) { auto handle = ospNewGroup(); + throwIfNull(handle); + loadGroupParams(handle, settings); return Group(handle); } -Instance Device::createInstance() +Instance Device::createInstance(const InstanceSettings &settings) { auto handle = ospNewInstance(); + throwIfNull(handle); + loadInstanceParams(handle, settings); return Instance(handle); } -World Device::createWorld() +World Device::createWorld(const WorldSettings &settings) { auto handle = ospNewWorld(); + throwIfNull(handle); + loadWorldParams(handle, settings); return World(handle); } @@ -64,11 +79,17 @@ Framebuffer Device::createFramebuffer(const FramebufferSettings &settings) auto height = static_cast(settings.height); auto format = static_cast(settings.format); auto channels = static_cast(OSP_FB_NONE); + for (auto channel : settings.channels) { channels |= static_cast(channel); } + auto handle = ospNewFrameBuffer(width, height, format, channels); + + throwIfNull(handle); + loadFramebufferParams(handle, settings); + return Framebuffer(handle); } @@ -78,16 +99,58 @@ RenderTask Device::render(const RenderSettings &settings) auto renderer = settings.renderer.getHandle(); auto camera = settings.camera.getHandle(); auto world = settings.world.getHandle(); + auto future = ospRenderFrame(framebuffer, renderer, camera, world); + throwIfNull(future); + return RenderTask(future); } +std::optional Device::pick(const PickSettings &settings) +{ + auto framebuffer = settings.framebuffer.getHandle(); + auto renderer = settings.renderer.getHandle(); + auto camera = settings.camera.getHandle(); + auto world = settings.world.getHandle(); + + const auto &position = settings.normalizedScreenPosition; + + auto result = OSPPickResult(); + ospPick(&result, framebuffer, renderer, camera, world, position.x, position.y); + + if (!result.hasHit) + { + return std::nullopt; + } + + auto [x, y, z] = result.worldPosition; + + return PickResult{ + .worldPosition = {x, y, z}, + .instance = Instance(result.instance), + .model = GeometricModel(result.model), + .primitiveIndex = result.primID, + }; +} + void Device::Deleter::operator()(OSPDevice device) const { ospDeviceRelease(device); ospShutdown(); } +void Device::throwIfNull(OSPObject object) const +{ + if (object != nullptr) + { + return; + } + + const auto *lastError = ospDeviceGetLastErrorMsg(_handle.get()); + + throw std::runtime_error(fmt::format("OSPRay internal error: '{}'", lastError)); +} + Device createDevice(Logger &logger) { auto error = ospLoadModule("cpu"); @@ -106,6 +169,11 @@ Device createDevice(Logger &logger) auto device = ospNewDevice(); + if (device == nullptr) + { + throw std::runtime_error("Failed to create device"); + } + auto logLevel = OSP_LOG_DEBUG; ospDeviceSetParam(device, "logLevel", OSP_UINT, &logLevel); diff --git a/src/brayns/core/enginev2/Device.h b/src/brayns/core/enginev2/Device.h index e6d114c28..82b069f76 100644 --- a/src/brayns/core/enginev2/Device.h +++ b/src/brayns/core/enginev2/Device.h @@ -23,99 +23,126 @@ #include #include +#include -#include +#include #include "Camera.h" #include "Framebuffer.h" +#include "GeometricModel.h" #include "Geometry.h" +#include "ImageOperation.h" #include "Light.h" #include "Material.h" +#include "Object.h" #include "Render.h" #include "Renderer.h" +#include "Texture.h" +#include "TransferFunction.h" #include "Volume.h" +#include "VolumetricModel.h" #include "World.h" namespace brayns::experimental { class Device { +private: + template + using SettingsOf = typename ObjectReflector::Settings; + + template + static constexpr auto nameOf = ObjectReflector::name.c_str(); + + template + static void loadParams(auto handle, const auto &settings) + { + throwIfNull(handle); + ObjectReflector::loadParams(handle, settings); + } + public: explicit Device(OSPDevice handle); OSPDevice getHandle() const; - - Spheres createSpheres(const SphereSettings &settings); - - GeometricModel createGeometricModel(); - VolumetricModel createVolumetricModel(); - Group createGroup(); - Instance createInstance(); - World createWorld(); + GeometricModel createGeometricModel(const GeometricModelSettings &settings); + VolumetricModel createVolumetricModel(const VolumetricModelSettings &settings); + Group createGroup(const GroupSettings &settings); + Instance createInstance(const InstanceSettings &settings); + World createWorld(const WorldSettings &settings); Framebuffer createFramebuffer(const FramebufferSettings &settings); RenderTask render(const RenderSettings &settings); + std::optional pick(const PickSettings &settings); template CameraType> - CameraType createCamera() + CameraType createCamera(const SettingsOf &settings) { - const auto &name = CameraType::name; - auto handle = ospNewCamera(name.c_str()); + auto handle = ospNewCamera(nameOf); + loadParams(handle, settings); return CameraType(handle); } - template ImageOperationType> - ImageOperationType createImageOperation() + template GeometryType> + GeometryType createGeometry(const SettingsOf &settings) { - const auto &name = ImageOperationType::name; - auto handle = ospNewImageOperation(name.c_str()); - return ImageOperationType(handle); + auto handle = ospNewGeometry(nameOf); + loadParams(handle, settings); + return GeometryType(handle); } - template GeometryType> - GeometryType createGeometry() + template ImageOperationType> + ImageOperationType createImageOperation(const SettingsOf &settings) { - const auto &name = GeometryType::name; - auto handle = ospNewGeometry(name.c_str()); - return GeometryType(handle); + auto handle = ospNewImageOperation(nameOf); + loadParams(handle, settings); + return ImageOperationType(handle); } template LightType> - LightType createLight() + LightType createLight(const SettingsOf &settings) { - const auto &name = LightType::name; - auto handle = ospNewLight(name.c_str()); + auto handle = ospNewLight(nameOf); + loadParams(handle, settings); return LightType(handle); } template MaterialType> - MaterialType createMaterial() + MaterialType createMaterial(const SettingsOf &settings) { - const auto &name = MaterialType::name; - auto handle = ospNewMaterial(name.c_str()); + auto handle = ospNewMaterial(nameOf); + loadParams(handle, settings); return MaterialType(handle); } template RendererType> - RendererType createRenderer() + RendererType createRenderer(const SettingsOf &settings) { - const auto &name = RendererType::name; - auto handle = ospNewRenderer(name.c_str()); + auto handle = ospNewRenderer(nameOf); + loadParams(handle, settings); return RendererType(handle); } + template TextureType> + TextureType createTexture(const SettingsOf &settings) + { + auto handle = ospNewTexture(nameOf); + loadParams(handle, settings); + return TextureType(handle); + } + template TransferFunctionType> - TransferFunctionType createTransferFunction() + TransferFunctionType createTransferFunction(const SettingsOf &settings) { - const auto &name = TransferFunctionType::name; - auto handle = ospNewTransferFunction(name.c_str()); + auto handle = ospNewTransferFunction(nameOf); + loadParams(handle, settings); return TransferFunctionType(handle); } template VolumeType> - VolumeType createVolume() + VolumeType createVolume(const SettingsOf &settings) { - const auto &name = VolumeType::name; - auto handle = ospNewVolume(name.c_str()); + auto handle = ospNewVolume(nameOf); + loadParams(handle, settings); return VolumeType(handle); } @@ -126,6 +153,8 @@ class Device }; std::unique_ptr _handle; + + void throwIfNull(OSPObject handle) const; }; Device createDevice(Logger &logger); diff --git a/src/brayns/core/enginev2/Framebuffer.cpp b/src/brayns/core/enginev2/Framebuffer.cpp index 6e0a24dda..8249dae2c 100644 --- a/src/brayns/core/enginev2/Framebuffer.cpp +++ b/src/brayns/core/enginev2/Framebuffer.cpp @@ -23,15 +23,14 @@ namespace brayns::experimental { -void loadToneMapperParams(OSPImageOperation handle, const ToneMapperSettings &settings) +int getFramebufferChannels(std::span channels) { - setObjectParam(handle, "exposure", settings.exposure); - setObjectParam(handle, "contrast", settings.contrast); - setObjectParam(handle, "shoulder", settings.hightlightCompression); - setObjectParam(handle, "midIn", settings.midLevelAnchorInput); - setObjectParam(handle, "midOut", settings.midLevelAnchorOutput); - setObjectParam(handle, "acesColor", settings.aces); - commitObject(handle); + auto flags = 0; + for (auto channel : channels) + { + flags |= static_cast(channel); + } + return flags; } void loadFramebufferParams(OSPFrameBuffer handle, const FramebufferSettings &settings) diff --git a/src/brayns/core/enginev2/Framebuffer.h b/src/brayns/core/enginev2/Framebuffer.h index 0d51b4dfb..b115f3d88 100644 --- a/src/brayns/core/enginev2/Framebuffer.h +++ b/src/brayns/core/enginev2/Framebuffer.h @@ -21,36 +21,14 @@ #pragma once +#include + #include "Data.h" +#include "ImageOperation.h" #include "Object.h" namespace brayns::experimental { -class ImageOperation : public Managed -{ -public: - using Managed::Managed; -}; - -struct ToneMapperSettings -{ - float exposure = 1.0F; - float contrast = 1.6773F; - float hightlightCompression = 0.9714F; - float midLevelAnchorInput = 0.18F; - float midLevelAnchorOutput = 0.18F; - float maxHdr = 11.0785F; - bool aces = true; -}; - -class ToneMapper : public ImageOperation -{ -public: - using ImageOperation::ImageOperation; -}; - -void loadToneMapperParams(OSPImageOperation handle, const ToneMapperSettings &settings); - enum class FramebufferFormat { Rgba8 = OSP_FB_RGBA8, @@ -71,32 +49,15 @@ enum class FramebufferChannel InstanceId = OSP_FB_ID_INSTANCE, }; -FramebufferChannel operator|(FramebufferChannel left, FramebufferChannel right) -{ - return static_cast(static_cast(left) | static_cast(right)); -} - -FramebufferChannel &operator|=(FramebufferChannel &left, FramebufferChannel right) -{ - return left = left | right; -} - -bool operator&(FramebufferChannel channels, FramebufferChannel channel) -{ - return static_cast(channels) & static_cast(channel) != 0; -} - struct FramebufferSettings { std::size_t width; std::size_t height; FramebufferFormat format = FramebufferFormat::Srgba8; - FramebufferChannel channels = FramebufferChannel::Color; + std::vector channels = {FramebufferChannel::Color}; std::span operations = {}; }; -void loadFramebufferParams(OSPFrameBuffer handle, const FramebufferSettings &settings); - class Framebuffer : public Managed { public: @@ -107,4 +68,7 @@ class Framebuffer : public Managed void resetAccumulation(); float getVariance(); }; + +int getFramebufferChannels(std::span channels); +void loadFramebufferParams(OSPFrameBuffer handle, const FramebufferSettings &settings); } diff --git a/src/brayns/core/enginev2/GeometricModel.cpp b/src/brayns/core/enginev2/GeometricModel.cpp index 62221b621..f3970b521 100644 --- a/src/brayns/core/enginev2/GeometricModel.cpp +++ b/src/brayns/core/enginev2/GeometricModel.cpp @@ -36,41 +36,41 @@ void setMaterialParam(OSPGeometricModel handle, const PrimitiveMaterials &materi namespace brayns::experimental { -void loadGeometricModelParams(OSPGeometricModel handle, const GeometricModelSettings &settings) +void GeometricModel::setMaterials(const PrimitiveMaterials &materials) { - setObjectParam(handle, "geometry", settings.geometry); - setMaterialParam(handle, settings.materials); - setObjectParam(handle, "invertNormals", settings.invertedNormals); - setObjectParam(handle, "id", settings.id); + auto handle = getHandle(); + setMaterialParam(handle, materials); commitObject(handle); } -void GeometricModel::setMaterials(const PrimitiveMaterials &materials) +void GeometricModel::invertNormals(bool invert) { auto handle = getHandle(); - setMaterialParam(handle, materials); + setObjectParam(handle, "invertNormals", invert); commitObject(handle); } -void GeometricModel::invertNormals(bool invert) +void ClippingModel::invertNormals(bool invert) { auto handle = getHandle(); setObjectParam(handle, "invertNormals", invert); commitObject(handle); } -void loadClippingModelParams(OSPGeometricModel handle, const ClippingModelSettings &settings) +void loadGeometricModelParams(OSPGeometricModel handle, const GeometricModelSettings &settings) { setObjectParam(handle, "geometry", settings.geometry); + setMaterialParam(handle, settings.materials); setObjectParam(handle, "invertNormals", settings.invertedNormals); setObjectParam(handle, "id", settings.id); commitObject(handle); } -void ClippingModel::invertNormals(bool invert) +void loadClippingModelParams(OSPGeometricModel handle, const ClippingModelSettings &settings) { - auto handle = getHandle(); - setObjectParam(handle, "invertNormals", invert); + setObjectParam(handle, "geometry", settings.geometry); + setObjectParam(handle, "invertNormals", settings.invertedNormals); + setObjectParam(handle, "id", settings.id); commitObject(handle); } } diff --git a/src/brayns/core/enginev2/GeometricModel.h b/src/brayns/core/enginev2/GeometricModel.h index 05b25ae90..1773f69df 100644 --- a/src/brayns/core/enginev2/GeometricModel.h +++ b/src/brayns/core/enginev2/GeometricModel.h @@ -42,8 +42,6 @@ struct GeometricModelSettings std::uint32_t id = std::uint32_t(-1); }; -void loadGeometricModelParams(OSPGeometricModel handle, const GeometricModelSettings &settings); - class GeometricModel : public Managed { public: @@ -60,8 +58,6 @@ struct ClippingModelSettings std::uint32_t id = std::uint32_t(-1); }; -void loadClippingModelParams(OSPGeometricModel handle, const ClippingModelSettings &settings); - class ClippingModel : public Managed { public: @@ -69,4 +65,7 @@ class ClippingModel : public Managed void invertNormals(bool inverted); }; + +void loadGeometricModelParams(OSPGeometricModel handle, const GeometricModelSettings &settings); +void loadClippingModelParams(OSPGeometricModel handle, const ClippingModelSettings &settings); } diff --git a/src/brayns/core/enginev2/Geometry.cpp b/src/brayns/core/enginev2/Geometry.cpp index 638c37208..c87b99f8d 100644 --- a/src/brayns/core/enginev2/Geometry.cpp +++ b/src/brayns/core/enginev2/Geometry.cpp @@ -58,14 +58,14 @@ void Mesh::setColors(std::span colors) commitObject(handle); } -void loadMeshParams(OSPGeometry handle, const TriangleMeshSettings &settings) +void ObjectReflector::loadParams(OSPGeometry handle, const Settings &settings) { setMeshParams(handle, settings); setObjectDataIfNotEmpty(handle, "index", settings.indices); commitObject(handle); } -void loadMeshParams(OSPGeometry handle, const QuadMeshSettings &settings) +void ObjectReflector::loadParams(OSPGeometry handle, const Settings &settings) { setMeshParams(handle, settings); @@ -81,13 +81,13 @@ void loadMeshParams(OSPGeometry handle, const QuadMeshSettings &settings) commitObject(handle); } -void loadSphereParams(OSPGeometry handle, const SphereSettings &settings) +void ObjectReflector::loadParams(OSPGeometry handle, const Settings &settings) { setSphereParams(handle, settings); commitObject(handle); } -void loadDiscParams(OSPGeometry handle, const DiscSettings &settings) +void ObjectReflector::loadParams(OSPGeometry handle, const Settings &settings) { setSphereParams(handle, settings); @@ -104,7 +104,7 @@ void loadDiscParams(OSPGeometry handle, const DiscSettings &settings) commitObject(handle); } -void loadCylinderParams(OSPGeometry handle, const CylinderSettings &settings) +void ObjectReflector::loadParams(OSPGeometry handle, const Settings &settings) { setCurveParams(handle, settings); commitObject(handle); @@ -117,7 +117,7 @@ void Cylinders::setColors(std::span colors) commitObject(handle); } -void loadCurveParams(OSPGeometry handle, const CurveSettings &settings) +void ObjectReflector::loadParams(OSPGeometry handle, const Settings &settings) { setCurveParams(handle, settings); setObjectParam(handle, "type", static_cast(settings.type)); @@ -125,7 +125,7 @@ void loadCurveParams(OSPGeometry handle, const CurveSettings &settings) commitObject(handle); } -void loadRibbonParams(OSPGeometry handle, const RibbonSettings &settings) +void ObjectReflector::loadParams(OSPGeometry handle, const Settings &settings) { setCurveParams(handle, settings); setObjectData(handle, "vertex.normal", settings.normals); @@ -134,20 +134,20 @@ void loadRibbonParams(OSPGeometry handle, const RibbonSettings &settings) commitObject(handle); } -void loadBoxParams(OSPGeometry handle, const BoxSettings &settings) +void ObjectReflector::loadParams(OSPGeometry handle, const Settings &settings) { setObjectData(handle, "box", settings.boxes); commitObject(handle); } -void loadPlaneParams(OSPGeometry handle, const PlaneSettings &settings) +void ObjectReflector::loadParams(OSPGeometry handle, const Settings &settings) { setObjectData(handle, "plane.coefficients", settings.coefficients); setObjectDataIfNotEmpty(handle, "plane.bounds", settings.bounds); commitObject(handle); } -void loadIsosurfaceParams(OSPGeometry handle, const IsosurfaceSettings &settings) +void ObjectReflector::loadParams(OSPGeometry handle, const Settings &settings) { setObjectParam(handle, "volume", settings.volume); setObjectData(handle, "isovalue", settings.isovalues); diff --git a/src/brayns/core/enginev2/Geometry.h b/src/brayns/core/enginev2/Geometry.h index 5a1244557..281e0a213 100644 --- a/src/brayns/core/enginev2/Geometry.h +++ b/src/brayns/core/enginev2/Geometry.h @@ -42,26 +42,54 @@ struct MeshSettings std::span indices = {}; }; +class Mesh : public Geometry +{ +public: + using Geometry::Geometry; + + void setColors(std::span colors); +}; + struct TriangleMeshSettings : MeshSettings { std::span indices = {}; }; -void loadMeshParams(OSPGeometry handle, const TriangleMeshSettings &settings); +class TriangleMesh : public Mesh +{ +public: + using Mesh::Mesh; +}; + +template<> +struct ObjectReflector +{ + using Settings = TriangleMeshSettings; + + static inline const std::string name = "mesh"; + + static void loadParams(OSPGeometry handle, const Settings &settings); +}; struct QuadMeshSettings : MeshSettings { std::span indices = {}; }; -void loadMeshParams(OSPGeometry handle, const QuadMeshSettings &settings); - -class Mesh : public Geometry +class QuadMesh : public Mesh { public: - using Geometry::Geometry; + using Mesh::Mesh; +}; - void setColors(std::span colors); +template<> +struct ObjectReflector +{ + using Settings = QuadMeshSettings; + + static inline const std::string name = "mesh"; + + static void loadParams(OSPGeometry handle, const Settings &settings); }; struct SphereSettings @@ -71,27 +99,43 @@ struct SphereSettings std::span uvs = {}; }; -void loadSphereParams(OSPGeometry handle, const SphereSettings &settings); - class Spheres : public Geometry { public: using Geometry::Geometry; }; +template<> +struct ObjectReflector +{ + using Settings = SphereSettings; + + static inline const std::string name = "sphere"; + + static void loadParams(OSPGeometry handle, const Settings &settings); +}; + struct DiscSettings : SphereSettings { std::span normals; }; -void loadDiscParams(OSPGeometry handle, const DiscSettings &settings); - class Discs : public Geometry { public: using Geometry::Geometry; }; +template<> +struct ObjectReflector +{ + using Settings = DiscSettings; + + static inline const std::string name = "sphere"; + + static void loadParams(OSPGeometry handle, const Settings &settings); +}; + using PositionRadius = Vector4; struct CylinderSettings @@ -102,8 +146,6 @@ struct CylinderSettings std::span uvs = {}; }; -void loadCylinderParams(OSPGeometry handle, const CylinderSettings &settings); - class Cylinders : public Geometry { public: @@ -112,6 +154,16 @@ class Cylinders : public Geometry void setColors(std::span colors); }; +template<> +struct ObjectReflector +{ + using Settings = CylinderSettings; + + static inline const std::string name = "curve"; + + static void loadParams(OSPGeometry handle, const Settings &settings); +}; + enum class CurveType { Flat = OSP_FLAT, @@ -132,14 +184,22 @@ struct CurveSettings : CylinderSettings CurveBasis basis = CurveBasis::Linear; }; -void loadCurveParams(OSPGeometry handle, const CurveSettings &settings); - class Curve : public Cylinders { public: using Cylinders::Cylinders; }; +template<> +struct ObjectReflector +{ + using Settings = CurveSettings; + + static inline const std::string name = "curve"; + + static void loadParams(OSPGeometry handle, const Settings &settings); +}; + enum class RibbonBasis { Bezier = OSP_BEZIER, @@ -153,52 +213,84 @@ struct RibbonSettings : CylinderSettings std::span normals; }; -void loadRibbonParams(OSPGeometry handle, const RibbonSettings &settings); - class Ribbon : public Cylinders { public: using Cylinders::Cylinders; }; +template<> +struct ObjectReflector +{ + using Settings = RibbonSettings; + + static inline const std::string name = "curve"; + + static void loadParams(OSPGeometry handle, const Settings &settings); +}; + struct BoxSettings { std::span boxes; }; -void loadBoxParams(OSPGeometry handle, const BoxSettings &settings); - class Boxes : public Geometry { public: using Geometry::Geometry; }; +template<> +struct ObjectReflector +{ + using Settings = BoxSettings; + + static inline const std::string name = "box"; + + static void loadParams(OSPGeometry handle, const Settings &settings); +}; + struct PlaneSettings { std::span coefficients; std::span bounds; }; -void loadPlaneParams(OSPGeometry handle, const PlaneSettings &settings); - class Planes : public Geometry { public: using Geometry::Geometry; }; +template<> +struct ObjectReflector +{ + using Settings = PlaneSettings; + + static inline const std::string name = "plane"; + + static void loadParams(OSPGeometry handle, const Settings &settings); +}; + struct IsosurfaceSettings { Volume volume; std::span isovalues; }; -void loadIsosurfaceParams(OSPGeometry handle, const IsosurfaceSettings &settings); - class Isosurfaces : public Geometry { public: using Geometry::Geometry; }; + +template<> +struct ObjectReflector +{ + using Settings = IsosurfaceSettings; + + static inline const std::string name = "isosurface"; + + static void loadParams(OSPGeometry handle, const Settings &settings); +}; } diff --git a/src/brayns/core/enginev2/ImageOperation.cpp b/src/brayns/core/enginev2/ImageOperation.cpp new file mode 100644 index 000000000..ff5c81fbc --- /dev/null +++ b/src/brayns/core/enginev2/ImageOperation.cpp @@ -0,0 +1,36 @@ +/* Copyright (c) 2015-2024 EPFL/Blue Brain Project + * All rights reserved. Do not distribute without permission. + * + * Responsible Author: adrien.fleury@epfl.ch + * + * This file is part of Brayns + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "ImageOperation.h" + +namespace brayns::experimental +{ +void ObjectReflector::loadParams(OSPImageOperation handle, const Settings &settings) +{ + setObjectParam(handle, "exposure", settings.exposure); + setObjectParam(handle, "contrast", settings.contrast); + setObjectParam(handle, "shoulder", settings.hightlightCompression); + setObjectParam(handle, "midIn", settings.midLevelAnchorInput); + setObjectParam(handle, "midOut", settings.midLevelAnchorOutput); + setObjectParam(handle, "acesColor", settings.aces); + commitObject(handle); +} +} diff --git a/src/brayns/core/enginev2/ImageOperation.h b/src/brayns/core/enginev2/ImageOperation.h new file mode 100644 index 000000000..c00e929e1 --- /dev/null +++ b/src/brayns/core/enginev2/ImageOperation.h @@ -0,0 +1,62 @@ +/* Copyright (c) 2015-2024 EPFL/Blue Brain Project + * All rights reserved. Do not distribute without permission. + * + * Responsible Author: adrien.fleury@epfl.ch + * + * This file is part of Brayns + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +#include "Data.h" +#include "Object.h" + +namespace brayns::experimental +{ +class ImageOperation : public Managed +{ +public: + using Managed::Managed; +}; + +struct ToneMapperSettings +{ + float exposure = 1.0F; + float contrast = 1.6773F; + float hightlightCompression = 0.9714F; + float midLevelAnchorInput = 0.18F; + float midLevelAnchorOutput = 0.18F; + float maxHdr = 11.0785F; + bool aces = true; +}; + +class ToneMapper : public ImageOperation +{ +public: + using ImageOperation::ImageOperation; +}; + +template<> +struct ObjectReflector +{ + using Settings = ToneMapperSettings; + + static inline const std::string name = "tonemapper"; + + static void loadParams(OSPImageOperation handle, const Settings &settings); +}; + +} diff --git a/src/brayns/core/enginev2/Light.cpp b/src/brayns/core/enginev2/Light.cpp index 8d41d42d5..a7ae74ba2 100644 --- a/src/brayns/core/enginev2/Light.cpp +++ b/src/brayns/core/enginev2/Light.cpp @@ -35,7 +35,7 @@ void setLightParams(OSPLight handle, const LightSettings &settings) namespace brayns::experimental { -void loadLightParams(OSPLight handle, const DistanceLightSettings &settings) +void ObjectReflector::loadParams(OSPLight handle, const Settings &settings) { setLightParams(handle, settings); setObjectParam(handle, "direction", settings.direction); @@ -43,7 +43,7 @@ void loadLightParams(OSPLight handle, const DistanceLightSettings &settings) commitObject(handle); } -void loadLightParams(OSPLight handle, const SphereLightSettings &settings) +void ObjectReflector::loadParams(OSPLight handle, const Settings &settings) { setLightParams(handle, settings); setObjectParam(handle, "position", settings.position); @@ -51,7 +51,7 @@ void loadLightParams(OSPLight handle, const SphereLightSettings &settings) commitObject(handle); } -void loadLightParams(OSPLight handle, const SpotLightSettings &settings) +void ObjectReflector::loadParams(OSPLight handle, const Settings &settings) { setLightParams(handle, settings); setObjectParam(handle, "position", settings.position); @@ -63,7 +63,7 @@ void loadLightParams(OSPLight handle, const SpotLightSettings &settings) commitObject(handle); } -void loadLightParams(OSPLight handle, const QuadLightSettings &settings) +void ObjectReflector::loadParams(OSPLight handle, const Settings &settings) { setLightParams(handle, settings); setObjectParam(handle, "position", settings.position); @@ -72,7 +72,7 @@ void loadLightParams(OSPLight handle, const QuadLightSettings &settings) commitObject(handle); } -void loadLightParams(OSPLight handle, const AmbientLightSettings &settings) +void ObjectReflector::loadParams(OSPLight handle, const Settings &settings) { setLightParams(handle, settings); commitObject(handle); diff --git a/src/brayns/core/enginev2/Light.h b/src/brayns/core/enginev2/Light.h index 6310f9412..dc579f1b5 100644 --- a/src/brayns/core/enginev2/Light.h +++ b/src/brayns/core/enginev2/Light.h @@ -38,34 +38,50 @@ class Light : public Managed using Managed::Managed; }; -struct DistanceLightSettings : LightSettings +struct DistantLightSettings : LightSettings { Vector3 direction = {0.0F, 0.0F, 1.0F}; float angularDiameter = 0.0F; }; -void loadLightParams(OSPLight handle, const DistanceLightSettings &settings); - class DistantLight : public Light { public: using Light::Light; }; +template<> +struct ObjectReflector +{ + using Settings = DistantLightSettings; + + static inline const std::string name = "distant"; + + static void loadParams(OSPLight handle, const Settings &settings); +}; + struct SphereLightSettings : LightSettings { Vector3 position = {0.0F, 0.0F, 0.0F}; float radius = 0.0F; }; -void loadLightParams(OSPLight handle, const SphereLightSettings &settings); - class SphereLight : public Light { public: using Light::Light; }; +template<> +struct ObjectReflector +{ + using Settings = SphereLightSettings; + + static inline const std::string name = "sphere"; + + static void loadParams(OSPLight handle, const Settings &settings); +}; + struct SpotLightSettings : LightSettings { Vector3 position = {0.0F, 0.0F, 0.0F}; @@ -76,14 +92,22 @@ struct SpotLightSettings : LightSettings float innerRadius = 0.0F; }; -void loadLightParams(OSPLight handle, const SpotLightSettings &settings); - class SpotLight : public Light { public: using Light::Light; }; +template<> +struct ObjectReflector +{ + using Settings = SpotLightSettings; + + static inline const std::string name = "spot"; + + static void loadParams(OSPLight handle, const Settings &settings); +}; + struct QuadLightSettings : LightSettings { Vector3 position = {0.0F, 0.0F, 0.0F}; @@ -91,23 +115,39 @@ struct QuadLightSettings : LightSettings Vector3 edge2 = {0.0F, 1.0F, 0.0F}; }; -void loadLightParams(OSPLight handle, const QuadLightSettings &settings); - class QuadLight : public Light { public: using Light::Light; }; -struct AmbientLightSettings : LightSettings +template<> +struct ObjectReflector { + using Settings = QuadLightSettings; + + static inline const std::string name = "quad"; + + static void loadParams(OSPLight handle, const Settings &settings); }; -void loadLightParams(OSPLight handle, const AmbientLightSettings &settings); +struct AmbientLightSettings : LightSettings +{ +}; class AmbientLight : public Light { public: using Light::Light; }; + +template<> +struct ObjectReflector +{ + using Settings = AmbientLightSettings; + + static inline const std::string name = "ambient"; + + static void loadParams(OSPLight handle, const Settings &settings); +}; } diff --git a/src/brayns/core/enginev2/Material.cpp b/src/brayns/core/enginev2/Material.cpp index 2083cccd0..950c4df37 100644 --- a/src/brayns/core/enginev2/Material.cpp +++ b/src/brayns/core/enginev2/Material.cpp @@ -73,13 +73,13 @@ void setMaterialParams(OSPMaterial handle, const AmbientOcclusionMaterialSetting namespace brayns::experimental { -void loadMaterialParams(OSPMaterial handle, const AmbientOcclusionMaterialSettings &settings) +void ObjectReflector::loadParams(OSPMaterial handle, const Settings &settings) { setMaterialParams(handle, settings); commitObject(handle); } -void loadMaterialParams(OSPMaterial handle, const ScivisMaterialSettings &settings) +void ObjectReflector::loadParams(OSPMaterial handle, const Settings &settings) { setMaterialParams(handle, settings); setObjectParam(handle, "ks", settings.specular); @@ -88,7 +88,7 @@ void loadMaterialParams(OSPMaterial handle, const ScivisMaterialSettings &settin commitObject(handle); } -void loadMaterialParams(OSPMaterial handle, const PrincipledMaterialSettings &settings) +void ObjectReflector::loadParams(OSPMaterial handle, const Settings &settings) { setObjectParam(handle, "baseColor", settings.baseColor); setTextureParam(handle, "map_baseColor", settings.baseColorMap); diff --git a/src/brayns/core/enginev2/Material.h b/src/brayns/core/enginev2/Material.h index 103065ea2..a75fdd3ac 100644 --- a/src/brayns/core/enginev2/Material.h +++ b/src/brayns/core/enginev2/Material.h @@ -28,12 +28,6 @@ namespace brayns::experimental { -class Material : public Managed -{ -public: - using Managed::Managed; -}; - struct MaterialTexture2D { Texture2D value; @@ -48,6 +42,12 @@ struct MaterialVolumeTexture using MaterialTexture = std::variant; +class Material : public Managed +{ +public: + using Managed::Managed; +}; + struct AmbientOcclusionMaterialSettings { Color3 diffuse = {0.8F, 0.8F, 0.8F}; @@ -55,14 +55,22 @@ struct AmbientOcclusionMaterialSettings float opacity = 1.0F; }; -void loadMaterialParams(OSPMaterial handle, const AmbientOcclusionMaterialSettings &settings); - class AmbientOcclusionMaterial : public Material { public: using Material::Material; }; +template<> +struct ObjectReflector +{ + using Settings = AmbientOcclusionMaterialSettings; + + static inline const std::string name = "obj"; + + static void loadParams(OSPMaterial handle, const Settings &settings); +}; + struct ScivisMaterialSettings : AmbientOcclusionMaterialSettings { Color3 specular = {0.0F, 0.0F, 0.0F}; @@ -70,14 +78,22 @@ struct ScivisMaterialSettings : AmbientOcclusionMaterialSettings Color3 transparencyFilter = {0.0F, 0.0F, 0.0F}; }; -void loadMaterialParams(OSPMaterial handle, const ScivisMaterialSettings &settings); - class ScivisMaterial : public Material { public: using Material::Material; }; +template<> +struct ObjectReflector +{ + using Settings = ScivisMaterialSettings; + + static inline const std::string name = "obj"; + + static void loadParams(OSPMaterial handle, const Settings &settings); +}; + struct PrincipledMaterialSettings { Color3 baseColor = {0.8F, 0.8F, 0.8F}; @@ -113,11 +129,19 @@ struct PrincipledMaterialSettings Color3 emissiveColor = {0.0F, 0.0F, 0.0F}; }; -void loadMaterialParams(OSPMaterial handle, const PrincipledMaterialSettings &settings); - class PrincipledMaterial : public Material { public: using Material::Material; }; + +template<> +struct ObjectReflector +{ + using Settings = PrincipledMaterialSettings; + + static inline const std::string name = "principled"; + + static void loadParams(OSPMaterial handle, const Settings &settings); +}; } diff --git a/src/brayns/core/enginev2/Object.h b/src/brayns/core/enginev2/Object.h index fea295eed..27f42c776 100644 --- a/src/brayns/core/enginev2/Object.h +++ b/src/brayns/core/enginev2/Object.h @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -148,6 +149,27 @@ void setObjectParam(OSPObject handle, const char *id, const T &value) constexpr auto type = ospray::OSPTypeFor::value; ospSetParam(handle, id, type, &value); } + +template +struct ObjectReflector +{ + using Settings = void; + using Handle = typename T::Handle; + + static inline const std::string name = ""; + + static void loadParams(Handle handle, const Settings &settings) + { + (void)handle; + (void)settings; + } + +private: + template + constexpr auto alwaysFalse = false; + + static_assert(alwaysFalse, "Unsupported device object"); +}; } namespace ospray diff --git a/src/brayns/core/enginev2/Renderer.cpp b/src/brayns/core/enginev2/Renderer.cpp index d241576d0..0da181bc8 100644 --- a/src/brayns/core/enginev2/Renderer.cpp +++ b/src/brayns/core/enginev2/Renderer.cpp @@ -50,13 +50,12 @@ void setRendererParams(OSPRenderer handle, const RendererSettings &settings) setBackground(handle, settings.background); setObjectData(handle, "material", settings.materials); setObjectParam(handle, "pixelFilter", static_cast(settings.pixelFilter)); - commitObject(handle); } } namespace brayns::experimental { -void loadRendererParams(OSPRenderer handle, const AmbientOcclusionRendererSettings &settings) +void ObjectReflector::loadParams(OSPRenderer handle, const Settings &settings) { setRendererParams(handle, settings); setObjectParam(handle, "aoSamples", settings.aoSamples); @@ -66,7 +65,7 @@ void loadRendererParams(OSPRenderer handle, const AmbientOcclusionRendererSettin commitObject(handle); } -void loadRendererParams(OSPRenderer handle, const ScivisRendererSettings &settings) +void ObjectReflector::loadParams(OSPRenderer handle, const Settings &settings) { setRendererParams(handle, settings); setObjectParam(handle, "shadows", settings.shadows); @@ -77,7 +76,7 @@ void loadRendererParams(OSPRenderer handle, const ScivisRendererSettings &settin commitObject(handle); } -void loadRendererParams(OSPRenderer handle, const PathTracerSettings &settings) +void ObjectReflector::loadParams(OSPRenderer handle, const Settings &settings) { setRendererParams(handle, settings); commitObject(handle); diff --git a/src/brayns/core/enginev2/Renderer.h b/src/brayns/core/enginev2/Renderer.h index e985b4f86..3a984e578 100644 --- a/src/brayns/core/enginev2/Renderer.h +++ b/src/brayns/core/enginev2/Renderer.h @@ -66,14 +66,22 @@ struct AmbientOcclusionRendererSettings : RendererSettings float volumeSamplingRate = 1.0F; }; -void loadRendererParams(OSPRenderer handle, const AmbientOcclusionRendererSettings &settings); - class AmbientOcclusionRenderer : public Renderer { public: using Renderer::Renderer; }; +template<> +struct ObjectReflector +{ + using Settings = AmbientOcclusionRendererSettings; + + static inline const std::string name = "ao"; + + static void loadParams(OSPRenderer handle, const Settings &settings); +}; + struct ScivisRendererSettings : RendererSettings { bool shadows = false; @@ -83,14 +91,22 @@ struct ScivisRendererSettings : RendererSettings bool showVisibleLights = false; }; -void loadRendererParams(OSPRenderer handle, const ScivisRendererSettings &settings); - class ScivisRenderer : public Renderer { public: using Renderer::Renderer; }; +template<> +struct ObjectReflector +{ + using Settings = ScivisRendererSettings; + + static inline const std::string name = "scivis"; + + static void loadParams(OSPRenderer handle, const Settings &settings); +}; + struct PathTracerSettings : RendererSettings { }; @@ -101,5 +117,13 @@ class PathTracer : public Renderer using Renderer::Renderer; }; -void loadRendererParams(OSPRenderer handle, const PathTracerSettings &settings); +template<> +struct ObjectReflector +{ + using Settings = PathTracerSettings; + + static inline const std::string name = "pathtracer"; + + static void loadParams(OSPRenderer handle, const Settings &settings); +}; } diff --git a/src/brayns/core/enginev2/Texture.cpp b/src/brayns/core/enginev2/Texture.cpp index 45f9f2da5..dd07c9df3 100644 --- a/src/brayns/core/enginev2/Texture.cpp +++ b/src/brayns/core/enginev2/Texture.cpp @@ -71,7 +71,7 @@ Data toSharedData2D(const void *data, TextureFormat format, const Size2 &size) namespace brayns::experimental { -void loadTextureParams(OSPTexture handle, const Texture2DSettings &settings) +void ObjectReflector::loadParams(OSPTexture handle, const Settings &settings) { auto data = toSharedData2D(settings.data, settings.format, settings.size); @@ -83,7 +83,7 @@ void loadTextureParams(OSPTexture handle, const Texture2DSettings &settings) commitObject(handle); } -void loadTextureParams(OSPTexture handle, const VolumeTextureSettings &settings) +void ObjectReflector::loadParams(OSPTexture handle, const Settings &settings) { setObjectParam(handle, "volume", settings.volume); setObjectParam(handle, "transferFunction", settings.transferFunction); diff --git a/src/brayns/core/enginev2/Texture.h b/src/brayns/core/enginev2/Texture.h index bbc754f20..f0ece0014 100644 --- a/src/brayns/core/enginev2/Texture.h +++ b/src/brayns/core/enginev2/Texture.h @@ -28,6 +28,12 @@ namespace brayns::experimental { +class Texture : public Managed +{ +public: + using Managed::Managed; +}; + enum class TextureFormat { Rgba8 = OSP_TEXTURE_RGBA8, @@ -60,10 +66,11 @@ enum class TextureWrap ClampToEdge = OSP_TEXTURE_WRAP_CLAMP_TO_EDGE, }; -class Texture : public Managed +struct TextureTransform { -public: - using Managed::Managed; + float rotation = 0.0F; + Vector2 scale = {1.0F, 1.0F}; + Vector2 translation = {0.0F, 0.0F}; }; struct Texture2DSettings @@ -75,19 +82,20 @@ struct Texture2DSettings TextureWrap wrap = TextureWrap::Repeat; }; -void loadTextureParams(OSPTexture handle, const Texture2DSettings &settings); - class Texture2D : public Texture { public: using Texture::Texture; }; -struct TextureTransform +template<> +struct ObjectReflector { - float rotation = 0.0F; - Vector2 scale = {1.0F, 1.0F}; - Vector2 translation = {0.0F, 0.0F}; + using Settings = Texture2DSettings; + + static inline const std::string name = "texture2D"; + + static void loadParams(OSPTexture handle, const Settings &settings); }; struct VolumeTextureSettings @@ -96,11 +104,19 @@ struct VolumeTextureSettings TransferFunction transferFunction; }; -void loadTextureParams(OSPTexture handle, const VolumeTextureSettings &settings); - class VolumeTexture : public Texture { public: using Texture::Texture; }; + +template<> +struct ObjectReflector +{ + using Settings = VolumeTextureSettings; + + static inline const std::string name = "volume"; + + static void loadParams(OSPTexture handle, const Settings &settings); +}; } diff --git a/src/brayns/core/enginev2/TransferFunction.cpp b/src/brayns/core/enginev2/TransferFunction.cpp index 89b7e311f..292976d9a 100644 --- a/src/brayns/core/enginev2/TransferFunction.cpp +++ b/src/brayns/core/enginev2/TransferFunction.cpp @@ -23,7 +23,7 @@ namespace brayns::experimental { -void loadTransferFunctionParams(OSPTransferFunction handle, const LinearTransferFunctionSettings &settings) +void ObjectReflector::loadParams(OSPTransferFunction handle, const Settings &settings) { setObjectData(handle, "color", settings.colors); setObjectData(handle, "opacity", settings.opacities); diff --git a/src/brayns/core/enginev2/TransferFunction.h b/src/brayns/core/enginev2/TransferFunction.h index 3adaf1894..df959eddb 100644 --- a/src/brayns/core/enginev2/TransferFunction.h +++ b/src/brayns/core/enginev2/TransferFunction.h @@ -39,11 +39,19 @@ struct LinearTransferFunctionSettings Box1 scalarRange; }; -void loadTransferFunctionParams(OSPTransferFunction handle, const LinearTransferFunctionSettings &settings); - class LinearTransferFunction : public TransferFunction { public: using TransferFunction::TransferFunction; }; + +template<> +struct ObjectReflector +{ + using Settings = LinearTransferFunctionSettings; + + static inline const std::string name = "piecewiseLinear"; + + static void loadParams(OSPTransferFunction handle, const Settings &settings); +}; } diff --git a/src/brayns/core/enginev2/Volume.cpp b/src/brayns/core/enginev2/Volume.cpp index 337203531..07034aedf 100644 --- a/src/brayns/core/enginev2/Volume.cpp +++ b/src/brayns/core/enginev2/Volume.cpp @@ -36,7 +36,7 @@ Data toSharedData3D(const void *data, VoxelDataType voxelDataType, const Size3 & namespace brayns::experimental { -void loadVolumeParams(OSPVolume handle, const RegularVolumeSettings &settings) +void ObjectReflector::loadParams(OSPVolume handle, const Settings &settings) { auto data = toSharedData3D(settings.data, settings.voxelDataType, settings.size); diff --git a/src/brayns/core/enginev2/Volume.h b/src/brayns/core/enginev2/Volume.h index 5f9008a3e..29caf42b6 100644 --- a/src/brayns/core/enginev2/Volume.h +++ b/src/brayns/core/enginev2/Volume.h @@ -61,11 +61,19 @@ struct RegularVolumeSettings float background = std::numeric_limits::quiet_NaN(); }; -void loadVolumeParams(OSPVolume handle, const RegularVolumeSettings &settings); - class RegularVolume : public Volume { public: using Volume::Volume; }; + +template<> +struct ObjectReflector +{ + using Settings = RegularVolumeSettings; + + static inline const std::string name = "structuredRegular"; + + static void loadParams(OSPVolume handle, const Settings &settings); +}; } diff --git a/src/brayns/core/enginev2/VolumetricModel.h b/src/brayns/core/enginev2/VolumetricModel.h index 47f3a8c54..550d6f451 100644 --- a/src/brayns/core/enginev2/VolumetricModel.h +++ b/src/brayns/core/enginev2/VolumetricModel.h @@ -36,11 +36,11 @@ struct VolumetricModelSettings std::uint32_t id = std::uint32_t(-1); }; -void loadVolumetricModelParams(OSPVolumetricModel handle, const VolumetricModelSettings &settings); - class VolumetricModel : public Managed { public: using Managed::Managed; }; + +void loadVolumetricModelParams(OSPVolumetricModel handle, const VolumetricModelSettings &settings); } diff --git a/src/brayns/core/enginev2/World.cpp b/src/brayns/core/enginev2/World.cpp index 39f8ebcf4..f9c4088a1 100644 --- a/src/brayns/core/enginev2/World.cpp +++ b/src/brayns/core/enginev2/World.cpp @@ -23,6 +23,24 @@ namespace brayns::experimental { +Box3 Group::getBounds() const +{ + auto handle = getHandle(); + return getObjectBounds(handle); +} + +Box3 Instance::getBounds() const +{ + auto handle = getHandle(); + return getObjectBounds(handle); +} + +Box3 World::getBounds() const +{ + auto handle = getHandle(); + return getObjectBounds(handle); +} + void loadGroupParams(OSPGroup handle, const GroupSettings &settings) { setObjectDataIfNotEmpty(handle, "geometry", settings.geometries); @@ -32,12 +50,6 @@ void loadGroupParams(OSPGroup handle, const GroupSettings &settings) commitObject(handle); } -Box3 Group::getBounds() const -{ - auto handle = getHandle(); - return getObjectBounds(handle); -} - void loadInstanceParams(OSPInstance handle, const InstanceSettings &settings) { setObjectParam(handle, "group", settings.group); @@ -46,21 +58,9 @@ void loadInstanceParams(OSPInstance handle, const InstanceSettings &settings) commitObject(handle); } -Box3 Instance::getBounds() const -{ - auto handle = getHandle(); - return getObjectBounds(handle); -} - void loadWorldParams(OSPWorld handle, const WorldSettings &settings) { setObjectData(handle, "instance", settings.instances); commitObject(handle); } - -Box3 World::getBounds() const -{ - auto handle = getHandle(); - return getObjectBounds(handle); -} } diff --git a/src/brayns/core/enginev2/World.h b/src/brayns/core/enginev2/World.h index 6b2fc4166..aa8c9f20a 100644 --- a/src/brayns/core/enginev2/World.h +++ b/src/brayns/core/enginev2/World.h @@ -37,8 +37,6 @@ struct GroupSettings std::span lights = {}; }; -void loadGroupParams(OSPGroup handle, const GroupSettings &settings); - class Group : public Managed { public: @@ -54,8 +52,6 @@ struct InstanceSettings std::uint32_t id = std::uint32_t(-1); }; -void loadInstanceParams(OSPInstance handle, const InstanceSettings &settings); - class Instance : public Managed { public: @@ -69,8 +65,6 @@ struct WorldSettings std::span instances; }; -void loadWorldParams(OSPWorld handle, const WorldSettings &settings); - class World : public Managed { public: @@ -78,4 +72,8 @@ class World : public Managed Box3 getBounds() const; }; + +void loadGroupParams(OSPGroup handle, const GroupSettings &settings); +void loadInstanceParams(OSPInstance handle, const InstanceSettings &settings); +void loadWorldParams(OSPWorld handle, const WorldSettings &settings); } From f218d5847cae7f2c715406f8e1a8d91f00035da2 Mon Sep 17 00:00:00 2001 From: Adrien4193 Date: Fri, 7 Jun 2024 16:55:25 +0200 Subject: [PATCH 5/7] Checkpoint simplified device. --- src/brayns/core/enginev2/Camera.cpp | 17 ++- src/brayns/core/enginev2/Camera.h | 8 +- src/brayns/core/enginev2/Device.cpp | 108 +----------------- src/brayns/core/enginev2/Device.h | 98 +--------------- src/brayns/core/enginev2/Framebuffer.cpp | 38 +++--- src/brayns/core/enginev2/Framebuffer.h | 9 +- src/brayns/core/enginev2/GeometricModel.cpp | 30 +++-- src/brayns/core/enginev2/GeometricModel.h | 20 +++- src/brayns/core/enginev2/Geometry.cpp | 88 +++++++++++--- src/brayns/core/enginev2/Geometry.h | 40 ++----- src/brayns/core/enginev2/ImageOperation.cpp | 8 +- src/brayns/core/enginev2/ImageOperation.h | 4 +- src/brayns/core/enginev2/Light.cpp | 44 ++++++- src/brayns/core/enginev2/Light.h | 20 +--- src/brayns/core/enginev2/Material.cpp | 25 +++- src/brayns/core/enginev2/Material.h | 12 +- src/brayns/core/enginev2/Object.h | 37 +++--- src/brayns/core/enginev2/Render.cpp | 49 +++++++- src/brayns/core/enginev2/Render.h | 8 +- src/brayns/core/enginev2/Renderer.cpp | 26 ++++- src/brayns/core/enginev2/Renderer.h | 12 +- src/brayns/core/enginev2/Texture.cpp | 15 ++- src/brayns/core/enginev2/Texture.h | 8 +- src/brayns/core/enginev2/TransferFunction.cpp | 8 +- src/brayns/core/enginev2/TransferFunction.h | 4 +- src/brayns/core/enginev2/Volume.cpp | 7 +- src/brayns/core/enginev2/Volume.h | 4 +- src/brayns/core/enginev2/VolumetricModel.cpp | 8 +- src/brayns/core/enginev2/VolumetricModel.h | 8 +- src/brayns/core/enginev2/World.cpp | 24 +++- src/brayns/core/enginev2/World.h | 26 ++++- tests/core/enginev2/TestRender.cpp | 31 ++--- 32 files changed, 449 insertions(+), 395 deletions(-) diff --git a/src/brayns/core/enginev2/Camera.cpp b/src/brayns/core/enginev2/Camera.cpp index b06b98e33..38500e238 100644 --- a/src/brayns/core/enginev2/Camera.cpp +++ b/src/brayns/core/enginev2/Camera.cpp @@ -36,19 +36,32 @@ void setCameraParams(OSPCamera handle, const CameraSettings &settings) namespace brayns::experimental { -void ObjectReflector::loadParams(OSPCamera handle, const Settings &settings) +OSPCamera ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewCamera("perspective"); + throwLastDeviceErrorIfNull(device, handle); + setCameraParams(handle, settings); + setObjectParam(handle, "fovy", settings.fovy); setObjectParam(handle, "aspect", settings.aspectRatio); + commitObject(handle); + + return handle; } -void ObjectReflector::loadParams(OSPCamera handle, const Settings &settings) +OSPCamera ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewCamera("perspective"); + throwLastDeviceErrorIfNull(device, handle); + setCameraParams(handle, settings); setObjectParam(handle, "height", settings.height); setObjectParam(handle, "aspect", settings.aspectRatio); + commitObject(handle); + + return handle; } } diff --git a/src/brayns/core/enginev2/Camera.h b/src/brayns/core/enginev2/Camera.h index cc9ef86a1..133b2f19f 100644 --- a/src/brayns/core/enginev2/Camera.h +++ b/src/brayns/core/enginev2/Camera.h @@ -56,9 +56,7 @@ struct ObjectReflector { using Settings = PerspectiveCameraSettings; - static inline const std::string name = "perspective"; - - static void loadParams(OSPCamera handle, const Settings &settings); + static OSPCamera createHandle(OSPDevice device, const Settings &settings); }; struct OrthographicCameraSettings : CameraSettings @@ -78,8 +76,6 @@ struct ObjectReflector { using Settings = OrthographicCameraSettings; - static inline const std::string name = "orthographic"; - - static void loadParams(OSPCamera handle, const Settings &settings); + static OSPCamera createHandle(OSPDevice device, const Settings &settings); }; } diff --git a/src/brayns/core/enginev2/Device.cpp b/src/brayns/core/enginev2/Device.cpp index 933607dc4..c4bb20082 100644 --- a/src/brayns/core/enginev2/Device.cpp +++ b/src/brayns/core/enginev2/Device.cpp @@ -33,104 +33,14 @@ OSPDevice Device::getHandle() const return _handle.get(); } -GeometricModel Device::createGeometricModel(const GeometricModelSettings &settings) +Future Device::render(const RenderSettings &settings) { - auto handle = ospNewGeometricModel(); - throwIfNull(handle); - loadGeometricModelParams(handle, settings); - return GeometricModel(handle); -} - -VolumetricModel Device::createVolumetricModel(const VolumetricModelSettings &settings) -{ - auto handle = ospNewVolumetricModel(); - throwIfNull(handle); - loadVolumetricModelParams(handle, settings); - return VolumetricModel(handle); -} - -Group Device::createGroup(const GroupSettings &settings) -{ - auto handle = ospNewGroup(); - throwIfNull(handle); - loadGroupParams(handle, settings); - return Group(handle); -} - -Instance Device::createInstance(const InstanceSettings &settings) -{ - auto handle = ospNewInstance(); - throwIfNull(handle); - loadInstanceParams(handle, settings); - return Instance(handle); -} - -World Device::createWorld(const WorldSettings &settings) -{ - auto handle = ospNewWorld(); - throwIfNull(handle); - loadWorldParams(handle, settings); - return World(handle); -} - -Framebuffer Device::createFramebuffer(const FramebufferSettings &settings) -{ - auto width = static_cast(settings.width); - auto height = static_cast(settings.height); - auto format = static_cast(settings.format); - auto channels = static_cast(OSP_FB_NONE); - - for (auto channel : settings.channels) - { - channels |= static_cast(channel); - } - - auto handle = ospNewFrameBuffer(width, height, format, channels); - - throwIfNull(handle); - loadFramebufferParams(handle, settings); - - return Framebuffer(handle); -} - -RenderTask Device::render(const RenderSettings &settings) -{ - auto framebuffer = settings.framebuffer.getHandle(); - auto renderer = settings.renderer.getHandle(); - auto camera = settings.camera.getHandle(); - auto world = settings.world.getHandle(); - - auto future = ospRenderFrame(framebuffer, renderer, camera, world); - throwIfNull(future); - - return RenderTask(future); + return startRendering(_handle.get(), settings); } std::optional Device::pick(const PickSettings &settings) { - auto framebuffer = settings.framebuffer.getHandle(); - auto renderer = settings.renderer.getHandle(); - auto camera = settings.camera.getHandle(); - auto world = settings.world.getHandle(); - - const auto &position = settings.normalizedScreenPosition; - - auto result = OSPPickResult(); - ospPick(&result, framebuffer, renderer, camera, world, position.x, position.y); - - if (!result.hasHit) - { - return std::nullopt; - } - - auto [x, y, z] = result.worldPosition; - - return PickResult{ - .worldPosition = {x, y, z}, - .instance = Instance(result.instance), - .model = GeometricModel(result.model), - .primitiveIndex = result.primID, - }; + return tryPick(_handle.get(), settings); } void Device::Deleter::operator()(OSPDevice device) const @@ -139,18 +49,6 @@ void Device::Deleter::operator()(OSPDevice device) const ospShutdown(); } -void Device::throwIfNull(OSPObject object) const -{ - if (object != nullptr) - { - return; - } - - const auto *lastError = ospDeviceGetLastErrorMsg(_handle.get()); - - throw std::runtime_error(fmt::format("OSPRay internal error: '{}'", lastError)); -} - Device createDevice(Logger &logger) { auto error = ospLoadModule("cpu"); diff --git a/src/brayns/core/enginev2/Device.h b/src/brayns/core/enginev2/Device.h index 82b069f76..1f78a1737 100644 --- a/src/brayns/core/enginev2/Device.h +++ b/src/brayns/core/enginev2/Device.h @@ -21,7 +21,6 @@ #pragma once -#include #include #include @@ -47,103 +46,18 @@ namespace brayns::experimental { class Device { -private: - template - using SettingsOf = typename ObjectReflector::Settings; - - template - static constexpr auto nameOf = ObjectReflector::name.c_str(); - - template - static void loadParams(auto handle, const auto &settings) - { - throwIfNull(handle); - ObjectReflector::loadParams(handle, settings); - } - public: explicit Device(OSPDevice handle); OSPDevice getHandle() const; - GeometricModel createGeometricModel(const GeometricModelSettings &settings); - VolumetricModel createVolumetricModel(const VolumetricModelSettings &settings); - Group createGroup(const GroupSettings &settings); - Instance createInstance(const InstanceSettings &settings); - World createWorld(const WorldSettings &settings); - Framebuffer createFramebuffer(const FramebufferSettings &settings); - RenderTask render(const RenderSettings &settings); + Future render(const RenderSettings &settings); std::optional pick(const PickSettings &settings); - template CameraType> - CameraType createCamera(const SettingsOf &settings) - { - auto handle = ospNewCamera(nameOf); - loadParams(handle, settings); - return CameraType(handle); - } - - template GeometryType> - GeometryType createGeometry(const SettingsOf &settings) - { - auto handle = ospNewGeometry(nameOf); - loadParams(handle, settings); - return GeometryType(handle); - } - - template ImageOperationType> - ImageOperationType createImageOperation(const SettingsOf &settings) + template + T create(const SettingsOf &settings) { - auto handle = ospNewImageOperation(nameOf); - loadParams(handle, settings); - return ImageOperationType(handle); - } - - template LightType> - LightType createLight(const SettingsOf &settings) - { - auto handle = ospNewLight(nameOf); - loadParams(handle, settings); - return LightType(handle); - } - - template MaterialType> - MaterialType createMaterial(const SettingsOf &settings) - { - auto handle = ospNewMaterial(nameOf); - loadParams(handle, settings); - return MaterialType(handle); - } - - template RendererType> - RendererType createRenderer(const SettingsOf &settings) - { - auto handle = ospNewRenderer(nameOf); - loadParams(handle, settings); - return RendererType(handle); - } - - template TextureType> - TextureType createTexture(const SettingsOf &settings) - { - auto handle = ospNewTexture(nameOf); - loadParams(handle, settings); - return TextureType(handle); - } - - template TransferFunctionType> - TransferFunctionType createTransferFunction(const SettingsOf &settings) - { - auto handle = ospNewTransferFunction(nameOf); - loadParams(handle, settings); - return TransferFunctionType(handle); - } - - template VolumeType> - VolumeType createVolume(const SettingsOf &settings) - { - auto handle = ospNewVolume(nameOf); - loadParams(handle, settings); - return VolumeType(handle); + auto handle = ObjectReflector::createHandle(_handle.get(), settings); + return T(handle); } private: @@ -153,8 +67,6 @@ class Device }; std::unique_ptr _handle; - - void throwIfNull(OSPObject handle) const; }; Device createDevice(Logger &logger); diff --git a/src/brayns/core/enginev2/Framebuffer.cpp b/src/brayns/core/enginev2/Framebuffer.cpp index 8249dae2c..4ae3681f5 100644 --- a/src/brayns/core/enginev2/Framebuffer.cpp +++ b/src/brayns/core/enginev2/Framebuffer.cpp @@ -23,22 +23,6 @@ namespace brayns::experimental { -int getFramebufferChannels(std::span channels) -{ - auto flags = 0; - for (auto channel : channels) - { - flags |= static_cast(channel); - } - return flags; -} - -void loadFramebufferParams(OSPFrameBuffer handle, const FramebufferSettings &settings) -{ - setObjectData(handle, "imageOperation", settings.operations); - commitObject(handle); -} - const void *Framebuffer::map(FramebufferChannel channel) { auto handle = getHandle(); @@ -62,4 +46,26 @@ float Framebuffer::getVariance() auto handle = getHandle(); return ospGetVariance(handle); } + +OSPFrameBuffer ObjectReflector::createHandle(OSPDevice device, const FramebufferSettings &settings) +{ + auto width = static_cast(settings.width); + auto height = static_cast(settings.height); + auto format = static_cast(settings.format); + auto channels = static_cast(OSP_FB_NONE); + + for (auto channel : settings.channels) + { + channels |= static_cast(channel); + } + + auto handle = ospNewFrameBuffer(width, height, format, channels); + throwLastDeviceErrorIfNull(device, handle); + + setObjectData(handle, "imageOperation", settings.operations); + + commitObject(handle); + + return handle; +} } diff --git a/src/brayns/core/enginev2/Framebuffer.h b/src/brayns/core/enginev2/Framebuffer.h index b115f3d88..c9041fbf9 100644 --- a/src/brayns/core/enginev2/Framebuffer.h +++ b/src/brayns/core/enginev2/Framebuffer.h @@ -69,6 +69,11 @@ class Framebuffer : public Managed float getVariance(); }; -int getFramebufferChannels(std::span channels); -void loadFramebufferParams(OSPFrameBuffer handle, const FramebufferSettings &settings); +template<> +struct ObjectReflector +{ + using Settings = FramebufferSettings; + + static OSPFrameBuffer createHandle(OSPDevice device, const Settings &settings); +}; } diff --git a/src/brayns/core/enginev2/GeometricModel.cpp b/src/brayns/core/enginev2/GeometricModel.cpp index f3970b521..6e428d2f1 100644 --- a/src/brayns/core/enginev2/GeometricModel.cpp +++ b/src/brayns/core/enginev2/GeometricModel.cpp @@ -30,7 +30,7 @@ void setMaterialParam(OSPGeometricModel handle, const PrimitiveMaterials &materi { setObjectData(handle, "material", materials.rendererIndices); setObjectDataIfNotEmpty(handle, "color", materials.colors); - setObjectDataIfNotEmpty(handle, "index", materials.materialAndColorIndices); + setObjectDataIfNotEmpty(handle, "index", materials.indices); } } @@ -50,27 +50,39 @@ void GeometricModel::invertNormals(bool invert) commitObject(handle); } -void ClippingModel::invertNormals(bool invert) +OSPGeometricModel ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { - auto handle = getHandle(); - setObjectParam(handle, "invertNormals", invert); - commitObject(handle); -} + auto handle = ospNewGeometricModel(); + throwLastDeviceErrorIfNull(device, handle); -void loadGeometricModelParams(OSPGeometricModel handle, const GeometricModelSettings &settings) -{ setObjectParam(handle, "geometry", settings.geometry); setMaterialParam(handle, settings.materials); setObjectParam(handle, "invertNormals", settings.invertedNormals); setObjectParam(handle, "id", settings.id); + + commitObject(handle); + + return handle; +} + +void ClippingModel::invertNormals(bool invert) +{ + auto handle = getHandle(); + setObjectParam(handle, "invertNormals", invert); commitObject(handle); } -void loadClippingModelParams(OSPGeometricModel handle, const ClippingModelSettings &settings) +OSPGeometricModel ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewGeometricModel(); + throwLastDeviceErrorIfNull(device, handle); + setObjectParam(handle, "geometry", settings.geometry); setObjectParam(handle, "invertNormals", settings.invertedNormals); setObjectParam(handle, "id", settings.id); + commitObject(handle); + + return handle; } } diff --git a/src/brayns/core/enginev2/GeometricModel.h b/src/brayns/core/enginev2/GeometricModel.h index 1773f69df..003e26f10 100644 --- a/src/brayns/core/enginev2/GeometricModel.h +++ b/src/brayns/core/enginev2/GeometricModel.h @@ -31,7 +31,7 @@ struct PrimitiveMaterials { std::span rendererIndices; std::span colors = {}; - std::span materialAndColorIndices = {}; + std::span indices = {}; }; struct GeometricModelSettings @@ -51,6 +51,14 @@ class GeometricModel : public Managed void invertNormals(bool inverted); }; +template<> +struct ObjectReflector +{ + using Settings = GeometricModelSettings; + + static OSPGeometricModel createHandle(OSPDevice device, const Settings &settings); +}; + struct ClippingModelSettings { Geometry geometry; @@ -66,6 +74,12 @@ class ClippingModel : public Managed void invertNormals(bool inverted); }; -void loadGeometricModelParams(OSPGeometricModel handle, const GeometricModelSettings &settings); -void loadClippingModelParams(OSPGeometricModel handle, const ClippingModelSettings &settings); +template<> +struct ObjectReflector +{ + using Settings = ClippingModelSettings; + + static OSPGeometricModel createHandle(OSPDevice device, const Settings &settings); +}; + } diff --git a/src/brayns/core/enginev2/Geometry.cpp b/src/brayns/core/enginev2/Geometry.cpp index c87b99f8d..f5dd29094 100644 --- a/src/brayns/core/enginev2/Geometry.cpp +++ b/src/brayns/core/enginev2/Geometry.cpp @@ -58,15 +58,24 @@ void Mesh::setColors(std::span colors) commitObject(handle); } -void ObjectReflector::loadParams(OSPGeometry handle, const Settings &settings) +OSPGeometry ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewGeometry("mesh"); + throwLastDeviceErrorIfNull(device, handle); + setMeshParams(handle, settings); setObjectDataIfNotEmpty(handle, "index", settings.indices); + commitObject(handle); + + return handle; } -void ObjectReflector::loadParams(OSPGeometry handle, const Settings &settings) +OSPGeometry ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewGeometry("mesh"); + throwLastDeviceErrorIfNull(device, handle); + setMeshParams(handle, settings); if (!settings.indices.empty()) @@ -79,16 +88,27 @@ void ObjectReflector::loadParams(OSPGeometry handle, const Settings &s } commitObject(handle); + + return handle; } -void ObjectReflector::loadParams(OSPGeometry handle, const Settings &settings) +OSPGeometry ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewGeometry("sphere"); + throwLastDeviceErrorIfNull(device, handle); + setSphereParams(handle, settings); + commitObject(handle); + + return handle; } -void ObjectReflector::loadParams(OSPGeometry handle, const Settings &settings) +OSPGeometry ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewGeometry("sphere"); + throwLastDeviceErrorIfNull(device, handle); + setSphereParams(handle, settings); if (settings.normals.empty()) @@ -102,12 +122,8 @@ void ObjectReflector::loadParams(OSPGeometry handle, const Settings &sett } commitObject(handle); -} -void ObjectReflector::loadParams(OSPGeometry handle, const Settings &settings) -{ - setCurveParams(handle, settings); - commitObject(handle); + return handle; } void Cylinders::setColors(std::span colors) @@ -117,40 +133,84 @@ void Cylinders::setColors(std::span colors) commitObject(handle); } -void ObjectReflector::loadParams(OSPGeometry handle, const Settings &settings) +OSPGeometry ObjectReflector::createHandle(OSPDevice device, const Settings &settings) +{ + auto handle = ospNewGeometry("curve"); + throwLastDeviceErrorIfNull(device, handle); + + setCurveParams(handle, settings); + + commitObject(handle); + + return handle; +} + +OSPGeometry ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewGeometry("curve"); + throwLastDeviceErrorIfNull(device, handle); + setCurveParams(handle, settings); + setObjectParam(handle, "type", static_cast(settings.type)); setObjectParam(handle, "basis", static_cast(settings.basis)); + commitObject(handle); + + return handle; } -void ObjectReflector::loadParams(OSPGeometry handle, const Settings &settings) +OSPGeometry ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewGeometry("curve"); + throwLastDeviceErrorIfNull(device, handle); + setCurveParams(handle, settings); + setObjectData(handle, "vertex.normal", settings.normals); setObjectParam(handle, "type", OSP_RIBBON); setObjectParam(handle, "basis", static_cast(settings.basis)); + commitObject(handle); + + return handle; } -void ObjectReflector::loadParams(OSPGeometry handle, const Settings &settings) +OSPGeometry ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewGeometry("box"); + throwLastDeviceErrorIfNull(device, handle); + setObjectData(handle, "box", settings.boxes); + commitObject(handle); + + return handle; } -void ObjectReflector::loadParams(OSPGeometry handle, const Settings &settings) +OSPGeometry ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewGeometry("plane"); + throwLastDeviceErrorIfNull(device, handle); + setObjectData(handle, "plane.coefficients", settings.coefficients); setObjectDataIfNotEmpty(handle, "plane.bounds", settings.bounds); + commitObject(handle); + + return handle; } -void ObjectReflector::loadParams(OSPGeometry handle, const Settings &settings) +OSPGeometry ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewGeometry("isosurface"); + throwLastDeviceErrorIfNull(device, handle); + setObjectParam(handle, "volume", settings.volume); setObjectData(handle, "isovalue", settings.isovalues); + commitObject(handle); + + return handle; } } diff --git a/src/brayns/core/enginev2/Geometry.h b/src/brayns/core/enginev2/Geometry.h index 281e0a213..b0728ae1f 100644 --- a/src/brayns/core/enginev2/Geometry.h +++ b/src/brayns/core/enginev2/Geometry.h @@ -66,9 +66,7 @@ struct ObjectReflector { using Settings = TriangleMeshSettings; - static inline const std::string name = "mesh"; - - static void loadParams(OSPGeometry handle, const Settings &settings); + static OSPGeometry createHandle(OSPDevice device, const Settings &settings); }; struct QuadMeshSettings : MeshSettings @@ -87,9 +85,7 @@ struct ObjectReflector { using Settings = QuadMeshSettings; - static inline const std::string name = "mesh"; - - static void loadParams(OSPGeometry handle, const Settings &settings); + static OSPGeometry createHandle(OSPDevice device, const Settings &settings); }; struct SphereSettings @@ -110,9 +106,7 @@ struct ObjectReflector { using Settings = SphereSettings; - static inline const std::string name = "sphere"; - - static void loadParams(OSPGeometry handle, const Settings &settings); + static OSPGeometry createHandle(OSPDevice device, const Settings &settings); }; struct DiscSettings : SphereSettings @@ -131,9 +125,7 @@ struct ObjectReflector { using Settings = DiscSettings; - static inline const std::string name = "sphere"; - - static void loadParams(OSPGeometry handle, const Settings &settings); + static OSPGeometry createHandle(OSPDevice device, const Settings &settings); }; using PositionRadius = Vector4; @@ -159,9 +151,7 @@ struct ObjectReflector { using Settings = CylinderSettings; - static inline const std::string name = "curve"; - - static void loadParams(OSPGeometry handle, const Settings &settings); + static OSPGeometry createHandle(OSPDevice device, const Settings &settings); }; enum class CurveType @@ -195,9 +185,7 @@ struct ObjectReflector { using Settings = CurveSettings; - static inline const std::string name = "curve"; - - static void loadParams(OSPGeometry handle, const Settings &settings); + static OSPGeometry createHandle(OSPDevice device, const Settings &settings); }; enum class RibbonBasis @@ -224,9 +212,7 @@ struct ObjectReflector { using Settings = RibbonSettings; - static inline const std::string name = "curve"; - - static void loadParams(OSPGeometry handle, const Settings &settings); + static OSPGeometry createHandle(OSPDevice device, const Settings &settings); }; struct BoxSettings @@ -245,9 +231,7 @@ struct ObjectReflector { using Settings = BoxSettings; - static inline const std::string name = "box"; - - static void loadParams(OSPGeometry handle, const Settings &settings); + static OSPGeometry createHandle(OSPDevice device, const Settings &settings); }; struct PlaneSettings @@ -267,9 +251,7 @@ struct ObjectReflector { using Settings = PlaneSettings; - static inline const std::string name = "plane"; - - static void loadParams(OSPGeometry handle, const Settings &settings); + static OSPGeometry createHandle(OSPDevice device, const Settings &settings); }; struct IsosurfaceSettings @@ -289,8 +271,6 @@ struct ObjectReflector { using Settings = IsosurfaceSettings; - static inline const std::string name = "isosurface"; - - static void loadParams(OSPGeometry handle, const Settings &settings); + static OSPGeometry createHandle(OSPDevice device, const Settings &settings); }; } diff --git a/src/brayns/core/enginev2/ImageOperation.cpp b/src/brayns/core/enginev2/ImageOperation.cpp index ff5c81fbc..889214a91 100644 --- a/src/brayns/core/enginev2/ImageOperation.cpp +++ b/src/brayns/core/enginev2/ImageOperation.cpp @@ -23,14 +23,20 @@ namespace brayns::experimental { -void ObjectReflector::loadParams(OSPImageOperation handle, const Settings &settings) +OSPImageOperation ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewImageOperation("tonemapper"); + throwLastDeviceErrorIfNull(device, handle); + setObjectParam(handle, "exposure", settings.exposure); setObjectParam(handle, "contrast", settings.contrast); setObjectParam(handle, "shoulder", settings.hightlightCompression); setObjectParam(handle, "midIn", settings.midLevelAnchorInput); setObjectParam(handle, "midOut", settings.midLevelAnchorOutput); setObjectParam(handle, "acesColor", settings.aces); + commitObject(handle); + + return handle; } } diff --git a/src/brayns/core/enginev2/ImageOperation.h b/src/brayns/core/enginev2/ImageOperation.h index c00e929e1..41da6e983 100644 --- a/src/brayns/core/enginev2/ImageOperation.h +++ b/src/brayns/core/enginev2/ImageOperation.h @@ -54,9 +54,7 @@ struct ObjectReflector { using Settings = ToneMapperSettings; - static inline const std::string name = "tonemapper"; - - static void loadParams(OSPImageOperation handle, const Settings &settings); + static OSPImageOperation createHandle(OSPDevice device, const Settings &settings); }; } diff --git a/src/brayns/core/enginev2/Light.cpp b/src/brayns/core/enginev2/Light.cpp index a7ae74ba2..12698de16 100644 --- a/src/brayns/core/enginev2/Light.cpp +++ b/src/brayns/core/enginev2/Light.cpp @@ -35,46 +35,80 @@ void setLightParams(OSPLight handle, const LightSettings &settings) namespace brayns::experimental { -void ObjectReflector::loadParams(OSPLight handle, const Settings &settings) +OSPLight ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewLight("distant"); + throwLastDeviceErrorIfNull(device, handle); + setLightParams(handle, settings); + setObjectParam(handle, "direction", settings.direction); setObjectParam(handle, "angularDiameter", settings.angularDiameter); + commitObject(handle); + + return handle; } -void ObjectReflector::loadParams(OSPLight handle, const Settings &settings) +OSPLight ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewLight("sphere"); + throwLastDeviceErrorIfNull(device, handle); + setLightParams(handle, settings); + setObjectParam(handle, "position", settings.position); setObjectParam(handle, "radius", settings.radius); + commitObject(handle); + + return handle; } -void ObjectReflector::loadParams(OSPLight handle, const Settings &settings) +OSPLight ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewLight("spot"); + throwLastDeviceErrorIfNull(device, handle); + setLightParams(handle, settings); + setObjectParam(handle, "position", settings.position); setObjectParam(handle, "direction", settings.direction); setObjectParam(handle, "openingAngle", settings.openingAngle); setObjectParam(handle, "penumbraAngle", settings.penumbraAngle); setObjectParam(handle, "radius", settings.outerRadius); setObjectParam(handle, "innerRadius", settings.innerRadius); + commitObject(handle); + + return handle; } -void ObjectReflector::loadParams(OSPLight handle, const Settings &settings) +OSPLight ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewLight("quad"); + throwLastDeviceErrorIfNull(device, handle); + setLightParams(handle, settings); + setObjectParam(handle, "position", settings.position); setObjectParam(handle, "edge1", settings.edge1); setObjectParam(handle, "edge2", settings.edge2); + commitObject(handle); + + return handle; } -void ObjectReflector::loadParams(OSPLight handle, const Settings &settings) +OSPLight ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewLight("ambient"); + throwLastDeviceErrorIfNull(device, handle); + setLightParams(handle, settings); + commitObject(handle); + + return handle; } } diff --git a/src/brayns/core/enginev2/Light.h b/src/brayns/core/enginev2/Light.h index dc579f1b5..89ff399b5 100644 --- a/src/brayns/core/enginev2/Light.h +++ b/src/brayns/core/enginev2/Light.h @@ -55,9 +55,7 @@ struct ObjectReflector { using Settings = DistantLightSettings; - static inline const std::string name = "distant"; - - static void loadParams(OSPLight handle, const Settings &settings); + static OSPLight createHandle(OSPDevice device, const Settings &settings); }; struct SphereLightSettings : LightSettings @@ -77,9 +75,7 @@ struct ObjectReflector { using Settings = SphereLightSettings; - static inline const std::string name = "sphere"; - - static void loadParams(OSPLight handle, const Settings &settings); + static OSPLight createHandle(OSPDevice device, const Settings &settings); }; struct SpotLightSettings : LightSettings @@ -103,9 +99,7 @@ struct ObjectReflector { using Settings = SpotLightSettings; - static inline const std::string name = "spot"; - - static void loadParams(OSPLight handle, const Settings &settings); + static OSPLight createHandle(OSPDevice device, const Settings &settings); }; struct QuadLightSettings : LightSettings @@ -126,9 +120,7 @@ struct ObjectReflector { using Settings = QuadLightSettings; - static inline const std::string name = "quad"; - - static void loadParams(OSPLight handle, const Settings &settings); + static OSPLight createHandle(OSPDevice device, const Settings &settings); }; struct AmbientLightSettings : LightSettings @@ -146,8 +138,6 @@ struct ObjectReflector { using Settings = AmbientLightSettings; - static inline const std::string name = "ambient"; - - static void loadParams(OSPLight handle, const Settings &settings); + static OSPLight createHandle(OSPDevice device, const Settings &settings); }; } diff --git a/src/brayns/core/enginev2/Material.cpp b/src/brayns/core/enginev2/Material.cpp index 950c4df37..42dcb59bf 100644 --- a/src/brayns/core/enginev2/Material.cpp +++ b/src/brayns/core/enginev2/Material.cpp @@ -73,23 +73,39 @@ void setMaterialParams(OSPMaterial handle, const AmbientOcclusionMaterialSetting namespace brayns::experimental { -void ObjectReflector::loadParams(OSPMaterial handle, const Settings &settings) +OSPMaterial ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewMaterial("obj"); + throwLastDeviceErrorIfNull(device, handle); + setMaterialParams(handle, settings); + commitObject(handle); + + return handle; } -void ObjectReflector::loadParams(OSPMaterial handle, const Settings &settings) +OSPMaterial ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewMaterial("obj"); + throwLastDeviceErrorIfNull(device, handle); + setMaterialParams(handle, settings); + setObjectParam(handle, "ks", settings.specular); setObjectParam(handle, "ns", settings.shininess); setObjectParam(handle, "tf", settings.transparencyFilter); + commitObject(handle); + + return handle; } -void ObjectReflector::loadParams(OSPMaterial handle, const Settings &settings) +OSPMaterial ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewMaterial("principled"); + throwLastDeviceErrorIfNull(device, handle); + setObjectParam(handle, "baseColor", settings.baseColor); setTextureParam(handle, "map_baseColor", settings.baseColorMap); setObjectParam(handle, "edgeColor", settings.edgeColor); @@ -121,6 +137,9 @@ void ObjectReflector::loadParams(OSPMaterial handle, const S setObjectParam(handle, "sheenRoughness", settings.sheenRoughness); setObjectParam(handle, "opacity", settings.opacity); setObjectParam(handle, "emissiveColor", settings.emissiveColor); + commitObject(handle); + + return handle; } } diff --git a/src/brayns/core/enginev2/Material.h b/src/brayns/core/enginev2/Material.h index a75fdd3ac..deca8d227 100644 --- a/src/brayns/core/enginev2/Material.h +++ b/src/brayns/core/enginev2/Material.h @@ -66,9 +66,7 @@ struct ObjectReflector { using Settings = AmbientOcclusionMaterialSettings; - static inline const std::string name = "obj"; - - static void loadParams(OSPMaterial handle, const Settings &settings); + static OSPMaterial createHandle(OSPDevice device, const Settings &settings); }; struct ScivisMaterialSettings : AmbientOcclusionMaterialSettings @@ -89,9 +87,7 @@ struct ObjectReflector { using Settings = ScivisMaterialSettings; - static inline const std::string name = "obj"; - - static void loadParams(OSPMaterial handle, const Settings &settings); + static OSPMaterial createHandle(OSPDevice device, const Settings &settings); }; struct PrincipledMaterialSettings @@ -140,8 +136,6 @@ struct ObjectReflector { using Settings = PrincipledMaterialSettings; - static inline const std::string name = "principled"; - - static void loadParams(OSPMaterial handle, const Settings &settings); + static OSPMaterial createHandle(OSPDevice device, const Settings &settings); }; } diff --git a/src/brayns/core/enginev2/Object.h b/src/brayns/core/enginev2/Object.h index 27f42c776..e7c04b224 100644 --- a/src/brayns/core/enginev2/Object.h +++ b/src/brayns/core/enginev2/Object.h @@ -150,26 +150,33 @@ void setObjectParam(OSPObject handle, const char *id, const T &value) ospSetParam(handle, id, type, &value); } -template -struct ObjectReflector +inline void throwLastDeviceErrorIfNull(OSPDevice device, OSPObject object) { - using Settings = void; - using Handle = typename T::Handle; - - static inline const std::string name = ""; - - static void loadParams(Handle handle, const Settings &settings) + if (object != nullptr) { - (void)handle; - (void)settings; + return; } -private: - template - constexpr auto alwaysFalse = false; + const auto *message = ospDeviceGetLastErrorMsg(device); - static_assert(alwaysFalse, "Unsupported device object"); -}; + throw std::runtime_error(message); +} + +template +struct ObjectReflector; + +template +concept ReflectedObjectSettings = requires { typename ObjectReflector::Settings; }; + +template +using SettingsOf = typename ObjectReflector::Settings; + +template +concept ReflectorObjectHandle = + requires(OSPDevice device, SettingsOf settings) { T(ObjectReflector::createHandle(device, settings)); }; + +template +concept ReflectedObject = ReflectedObjectSettings && ReflectorObjectHandle; } namespace ospray diff --git a/src/brayns/core/enginev2/Render.cpp b/src/brayns/core/enginev2/Render.cpp index 5cec1cdad..a503ef3f3 100644 --- a/src/brayns/core/enginev2/Render.cpp +++ b/src/brayns/core/enginev2/Render.cpp @@ -23,28 +23,69 @@ namespace brayns::experimental { -bool RenderTask::isReady() const +bool Future::isReady() const { auto handle = getHandle(); return ospIsReady(handle); } -float RenderTask::getProgress() const +float Future::getProgress() const { auto handle = getHandle(); return ospGetProgress(handle); } -void RenderTask::cancel() +void Future::cancel() { auto handle = getHandle(); ospCancel(handle); } -float RenderTask::waitAndGetDuration() +float Future::waitAndGetDuration() { auto handle = getHandle(); ospWait(handle); return ospGetTaskDuration(handle); } + +Future startRendering(OSPDevice device, const RenderSettings &settings) +{ + auto framebuffer = settings.framebuffer.getHandle(); + auto renderer = settings.renderer.getHandle(); + auto camera = settings.camera.getHandle(); + auto world = settings.world.getHandle(); + + auto handle = ospRenderFrame(framebuffer, renderer, camera, world); + throwLastDeviceErrorIfNull(device, handle); + + return Future(handle); +} + +std::optional tryPick(OSPDevice device, const PickSettings &settings) +{ + (void)device; + + auto framebuffer = settings.framebuffer.getHandle(); + auto renderer = settings.renderer.getHandle(); + auto camera = settings.camera.getHandle(); + auto world = settings.world.getHandle(); + auto [x, y] = settings.normalizedScreenPosition; + + auto result = OSPPickResult(); + ospPick(&result, framebuffer, renderer, camera, world, x, y); + + if (!result.hasHit) + { + return std::nullopt; + } + + auto [x, y, z] = result.worldPosition; + + return PickResult{ + .worldPosition = {x, y, z}, + .instance = Instance(result.instance), + .model = GeometricModel(result.model), + .primitiveIndex = result.primID, + }; +} } diff --git a/src/brayns/core/enginev2/Render.h b/src/brayns/core/enginev2/Render.h index 4cecdf519..4408d932d 100644 --- a/src/brayns/core/enginev2/Render.h +++ b/src/brayns/core/enginev2/Render.h @@ -21,6 +21,8 @@ #pragma once +#include + #include "Camera.h" #include "Framebuffer.h" #include "Object.h" @@ -37,7 +39,7 @@ struct RenderSettings World world; }; -class RenderTask : public Managed +class Future : public Managed { public: using Managed::Managed; @@ -48,6 +50,8 @@ class RenderTask : public Managed float waitAndGetDuration(); }; +Future startRendering(OSPDevice device, const RenderSettings &settings); + struct PickSettings : RenderSettings { Vector2 normalizedScreenPosition; @@ -60,4 +64,6 @@ struct PickResult GeometricModel model; std::uint32_t primitiveIndex; }; + +std::optional tryPick(OSPDevice device, const PickSettings &settings); } diff --git a/src/brayns/core/enginev2/Renderer.cpp b/src/brayns/core/enginev2/Renderer.cpp index 0da181bc8..e531c8422 100644 --- a/src/brayns/core/enginev2/Renderer.cpp +++ b/src/brayns/core/enginev2/Renderer.cpp @@ -55,30 +55,50 @@ void setRendererParams(OSPRenderer handle, const RendererSettings &settings) namespace brayns::experimental { -void ObjectReflector::loadParams(OSPRenderer handle, const Settings &settings) +OSPRenderer ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewRenderer("ao"); + throwLastDeviceErrorIfNull(device, handle); + setRendererParams(handle, settings); + setObjectParam(handle, "aoSamples", settings.aoSamples); setObjectParam(handle, "aoDistance", settings.aoDistance); setObjectParam(handle, "aoIntensity", settings.aoIntensity); setObjectParam(handle, "volumeSamplingRate", settings.volumeSamplingRate); + commitObject(handle); + + return handle; } -void ObjectReflector::loadParams(OSPRenderer handle, const Settings &settings) +OSPRenderer ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewRenderer("scivis"); + throwLastDeviceErrorIfNull(device, handle); + setRendererParams(handle, settings); + setObjectParam(handle, "shadows", settings.shadows); setObjectParam(handle, "aoSamples", settings.aoSamples); setObjectParam(handle, "aoDistance", settings.aoDistance); setObjectParam(handle, "volumeSamplingRate", settings.volumeSamplingRate); setObjectParam(handle, "visibleLights", settings.showVisibleLights); + commitObject(handle); + + return handle; } -void ObjectReflector::loadParams(OSPRenderer handle, const Settings &settings) +OSPRenderer ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewRenderer("pathtracer"); + throwLastDeviceErrorIfNull(device, handle); + setRendererParams(handle, settings); + commitObject(handle); + + return handle; } } diff --git a/src/brayns/core/enginev2/Renderer.h b/src/brayns/core/enginev2/Renderer.h index 3a984e578..75679a10f 100644 --- a/src/brayns/core/enginev2/Renderer.h +++ b/src/brayns/core/enginev2/Renderer.h @@ -77,9 +77,7 @@ struct ObjectReflector { using Settings = AmbientOcclusionRendererSettings; - static inline const std::string name = "ao"; - - static void loadParams(OSPRenderer handle, const Settings &settings); + static OSPRenderer createHandle(OSPDevice device, const Settings &settings); }; struct ScivisRendererSettings : RendererSettings @@ -102,9 +100,7 @@ struct ObjectReflector { using Settings = ScivisRendererSettings; - static inline const std::string name = "scivis"; - - static void loadParams(OSPRenderer handle, const Settings &settings); + static OSPRenderer createHandle(OSPDevice device, const Settings &settings); }; struct PathTracerSettings : RendererSettings @@ -122,8 +118,6 @@ struct ObjectReflector { using Settings = PathTracerSettings; - static inline const std::string name = "pathtracer"; - - static void loadParams(OSPRenderer handle, const Settings &settings); + static OSPRenderer createHandle(OSPDevice device, const Settings &settings); }; } diff --git a/src/brayns/core/enginev2/Texture.cpp b/src/brayns/core/enginev2/Texture.cpp index dd07c9df3..a12b1b879 100644 --- a/src/brayns/core/enginev2/Texture.cpp +++ b/src/brayns/core/enginev2/Texture.cpp @@ -71,8 +71,11 @@ Data toSharedData2D(const void *data, TextureFormat format, const Size2 &size) namespace brayns::experimental { -void ObjectReflector::loadParams(OSPTexture handle, const Settings &settings) +OSPTexture ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewTexture("texture2D"); + throwLastDeviceErrorIfNull(device, handle); + auto data = toSharedData2D(settings.data, settings.format, settings.size); setObjectParam(handle, "format", static_cast(settings.format)); @@ -81,12 +84,20 @@ void ObjectReflector::loadParams(OSPTexture handle, const Settings &s setObjectParam(handle, "wrapMode", static_cast(settings.wrap)); commitObject(handle); + + return handle; } -void ObjectReflector::loadParams(OSPTexture handle, const Settings &settings) +OSPTexture ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewTexture("volume"); + throwLastDeviceErrorIfNull(device, handle); + setObjectParam(handle, "volume", settings.volume); setObjectParam(handle, "transferFunction", settings.transferFunction); + commitObject(handle); + + return handle; } } diff --git a/src/brayns/core/enginev2/Texture.h b/src/brayns/core/enginev2/Texture.h index f0ece0014..edb2207e4 100644 --- a/src/brayns/core/enginev2/Texture.h +++ b/src/brayns/core/enginev2/Texture.h @@ -93,9 +93,7 @@ struct ObjectReflector { using Settings = Texture2DSettings; - static inline const std::string name = "texture2D"; - - static void loadParams(OSPTexture handle, const Settings &settings); + static OSPTexture createHandle(OSPDevice device, const Settings &settings); }; struct VolumeTextureSettings @@ -115,8 +113,6 @@ struct ObjectReflector { using Settings = VolumeTextureSettings; - static inline const std::string name = "volume"; - - static void loadParams(OSPTexture handle, const Settings &settings); + static OSPTexture createHandle(OSPDevice device, const Settings &settings); }; } diff --git a/src/brayns/core/enginev2/TransferFunction.cpp b/src/brayns/core/enginev2/TransferFunction.cpp index 292976d9a..87351eee6 100644 --- a/src/brayns/core/enginev2/TransferFunction.cpp +++ b/src/brayns/core/enginev2/TransferFunction.cpp @@ -23,11 +23,17 @@ namespace brayns::experimental { -void ObjectReflector::loadParams(OSPTransferFunction handle, const Settings &settings) +OSPTransferFunction ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewTransferFunction("piecewiseLinear"); + throwLastDeviceErrorIfNull(device, handle); + setObjectData(handle, "color", settings.colors); setObjectData(handle, "opacity", settings.opacities); setObjectParam(handle, "value", settings.scalarRange); + commitObject(handle); + + return handle; } } diff --git a/src/brayns/core/enginev2/TransferFunction.h b/src/brayns/core/enginev2/TransferFunction.h index df959eddb..172507bea 100644 --- a/src/brayns/core/enginev2/TransferFunction.h +++ b/src/brayns/core/enginev2/TransferFunction.h @@ -50,8 +50,6 @@ struct ObjectReflector { using Settings = LinearTransferFunctionSettings; - static inline const std::string name = "piecewiseLinear"; - - static void loadParams(OSPTransferFunction handle, const Settings &settings); + static OSPTransferFunction createHandle(OSPDevice device, const Settings &settings); }; } diff --git a/src/brayns/core/enginev2/Volume.cpp b/src/brayns/core/enginev2/Volume.cpp index 07034aedf..60d72238f 100644 --- a/src/brayns/core/enginev2/Volume.cpp +++ b/src/brayns/core/enginev2/Volume.cpp @@ -36,8 +36,11 @@ Data toSharedData3D(const void *data, VoxelDataType voxelDataType, const Size3 & namespace brayns::experimental { -void ObjectReflector::loadParams(OSPVolume handle, const Settings &settings) +OSPVolume ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewVolume("structuredRegular"); + throwLastDeviceErrorIfNull(device, handle); + auto data = toSharedData3D(settings.data, settings.voxelDataType, settings.size); setObjectParam(handle, "data", data); @@ -46,5 +49,7 @@ void ObjectReflector::loadParams(OSPVolume handle, const Settings setObjectParam(handle, "background", settings.background); commitObject(handle); + + return handle; } } diff --git a/src/brayns/core/enginev2/Volume.h b/src/brayns/core/enginev2/Volume.h index 29caf42b6..e23a27708 100644 --- a/src/brayns/core/enginev2/Volume.h +++ b/src/brayns/core/enginev2/Volume.h @@ -72,8 +72,6 @@ struct ObjectReflector { using Settings = RegularVolumeSettings; - static inline const std::string name = "structuredRegular"; - - static void loadParams(OSPVolume handle, const Settings &settings); + static OSPVolume createHandle(OSPDevice device, const Settings &settings); }; } diff --git a/src/brayns/core/enginev2/VolumetricModel.cpp b/src/brayns/core/enginev2/VolumetricModel.cpp index 85558b2c3..c7be07551 100644 --- a/src/brayns/core/enginev2/VolumetricModel.cpp +++ b/src/brayns/core/enginev2/VolumetricModel.cpp @@ -23,13 +23,19 @@ namespace brayns::experimental { -void loadVolumetricModelParams(OSPVolumetricModel handle, const VolumetricModelSettings &settings) +OSPVolumetricModel ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewVolumetricModel(); + throwLastDeviceErrorIfNull(device, handle); + setObjectParam(handle, "volume", settings.volume); setObjectParam(handle, "transferFunction", settings.transferFunction); setObjectParam(handle, "densityScale", settings.densityScale); setObjectParam(handle, "anisotropy", settings.anisotropy); setObjectParam(handle, "id", settings.id); + commitObject(handle); + + return handle; } } diff --git a/src/brayns/core/enginev2/VolumetricModel.h b/src/brayns/core/enginev2/VolumetricModel.h index 550d6f451..b0c11561a 100644 --- a/src/brayns/core/enginev2/VolumetricModel.h +++ b/src/brayns/core/enginev2/VolumetricModel.h @@ -42,5 +42,11 @@ class VolumetricModel : public Managed using Managed::Managed; }; -void loadVolumetricModelParams(OSPVolumetricModel handle, const VolumetricModelSettings &settings); +template<> +struct ObjectReflector +{ + using Settings = VolumetricModelSettings; + + static OSPVolumetricModel createHandle(OSPDevice device, const Settings &settings); +}; } diff --git a/src/brayns/core/enginev2/World.cpp b/src/brayns/core/enginev2/World.cpp index f9c4088a1..4ac41d59d 100644 --- a/src/brayns/core/enginev2/World.cpp +++ b/src/brayns/core/enginev2/World.cpp @@ -41,26 +41,44 @@ Box3 World::getBounds() const return getObjectBounds(handle); } -void loadGroupParams(OSPGroup handle, const GroupSettings &settings) +OSPGroup ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewGroup(); + throwLastDeviceErrorIfNull(device, handle); + setObjectDataIfNotEmpty(handle, "geometry", settings.geometries); setObjectDataIfNotEmpty(handle, "volume", settings.volumes); setObjectDataIfNotEmpty(handle, "clippingGeometry", settings.clippingGeometries); setObjectDataIfNotEmpty(handle, "light", settings.lights); + commitObject(handle); + + return handle; } -void loadInstanceParams(OSPInstance handle, const InstanceSettings &settings) +OSPInstance ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewInstance(); + throwLastDeviceErrorIfNull(device, handle); + setObjectParam(handle, "group", settings.group); setObjectParam(handle, "transform", toAffine(settings.transform)); setObjectParam(handle, "id", settings.id); + commitObject(handle); + + return handle; } -void loadWorldParams(OSPWorld handle, const WorldSettings &settings) +OSPWorld ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { + auto handle = ospNewWorld(); + throwLastDeviceErrorIfNull(device, handle); + setObjectData(handle, "instance", settings.instances); + commitObject(handle); + + return handle; } } diff --git a/src/brayns/core/enginev2/World.h b/src/brayns/core/enginev2/World.h index aa8c9f20a..55e1757d3 100644 --- a/src/brayns/core/enginev2/World.h +++ b/src/brayns/core/enginev2/World.h @@ -45,6 +45,14 @@ class Group : public Managed Box3 getBounds() const; }; +template<> +struct ObjectReflector +{ + using Settings = GroupSettings; + + static OSPGroup createHandle(OSPDevice device, const Settings &settings); +}; + struct InstanceSettings { Group group; @@ -60,6 +68,14 @@ class Instance : public Managed Box3 getBounds() const; }; +template<> +struct ObjectReflector +{ + using Settings = InstanceSettings; + + static OSPInstance createHandle(OSPDevice device, const Settings &settings); +}; + struct WorldSettings { std::span instances; @@ -73,7 +89,11 @@ class World : public Managed Box3 getBounds() const; }; -void loadGroupParams(OSPGroup handle, const GroupSettings &settings); -void loadInstanceParams(OSPInstance handle, const InstanceSettings &settings); -void loadWorldParams(OSPWorld handle, const WorldSettings &settings); +template<> +struct ObjectReflector +{ + using Settings = WorldSettings; + + static OSPWorld createHandle(OSPDevice device, const Settings &settings); +}; } diff --git a/tests/core/enginev2/TestRender.cpp b/tests/core/enginev2/TestRender.cpp index 43cbe827c..69b7b256d 100644 --- a/tests/core/enginev2/TestRender.cpp +++ b/tests/core/enginev2/TestRender.cpp @@ -25,7 +25,7 @@ #include -#include +#include using namespace brayns; using namespace brayns::experimental; @@ -38,45 +38,30 @@ TEST_CASE("Render") auto handler = [&](const auto &record) { error = record.message; }; auto logger = Logger("Test", level, handler); - auto engine = loadEngine(); - - auto device = engine.createDevice(logger); + auto device = createDevice(logger); auto width = 480; auto height = 360; - auto toneMapper = device.createImageOperation(); - toneMapper.commit(); + auto toneMapper = device.create({}); auto imageOperations = std::vector{toneMapper}; - auto framebuffer = device.createFramebuffer({ + auto framebuffer = device.create({ .width = std::size_t(width), .height = std::size_t(height), .format = FramebufferFormat::Srgba8, .channels = {FramebufferChannel::Color}, + .operations = imageOperations, }); - framebuffer.setImageOperations(imageOperations); - framebuffer.commit(); - auto material = device.createMaterial(); - material.setDiffuseColor({1, 1, 1}); - material.setSpecularColor({0, 0, 0}); - material.setTransparencyFilter({0, 0, 0}); - material.setShininess(10); - material.commit(); + auto material = device.create({}); auto materials = std::vector{material}; - auto renderer = device.createRenderer(); - renderer.setBackgroundColor({1, 1, 1, 1}); - renderer.enableShadows(true); - renderer.setPixelSamples(1); - renderer.setAoSamples(0); - renderer.setMaterials(materials); - renderer.commit(); + auto renderer = device.create(); - auto camera = device.createCamera(); + auto camera = device.create(); camera.setAspectRatio(float(width) / float(height)); camera.setFovy(45); camera.setTransform(toAffine({.translation = {0, 0, -1}})); From f275ad5f1767d8a52f2e3d807d4ac5f91ada2b5d Mon Sep 17 00:00:00 2001 From: Adrien4193 Date: Mon, 10 Jun 2024 15:03:31 +0200 Subject: [PATCH 6/7] Checkpoint all implemented. --- src/brayns/core/enginev2/Camera.cpp | 5 +- src/brayns/core/enginev2/Camera.h | 6 +- src/brayns/core/enginev2/Device.cpp | 4 +- src/brayns/core/enginev2/Device.h | 2 +- src/brayns/core/enginev2/Framebuffer.cpp | 2 +- src/brayns/core/enginev2/GeometricModel.cpp | 6 +- src/brayns/core/enginev2/Geometry.cpp | 130 ++++++++++++++------ src/brayns/core/enginev2/Geometry.h | 90 ++++++++------ src/brayns/core/enginev2/Light.cpp | 60 ++++++++- src/brayns/core/enginev2/Light.h | 84 ++++++++++++- src/brayns/core/enginev2/Material.cpp | 113 +++++++++-------- src/brayns/core/enginev2/Material.h | 82 ++++++------ src/brayns/core/enginev2/Object.h | 13 +- src/brayns/core/enginev2/Render.cpp | 22 ++-- src/brayns/core/enginev2/Render.h | 7 +- src/brayns/core/enginev2/Renderer.cpp | 12 +- src/brayns/core/enginev2/Renderer.h | 11 +- src/brayns/core/enginev2/Texture.cpp | 22 ++-- src/brayns/core/enginev2/Texture.h | 2 + src/brayns/core/utils/Math.h | 6 +- tests/core/enginev2/TestRender.cpp | 78 ++++-------- 21 files changed, 467 insertions(+), 290 deletions(-) diff --git a/src/brayns/core/enginev2/Camera.cpp b/src/brayns/core/enginev2/Camera.cpp index 38500e238..0c9e55318 100644 --- a/src/brayns/core/enginev2/Camera.cpp +++ b/src/brayns/core/enginev2/Camera.cpp @@ -41,7 +41,7 @@ OSPCamera ObjectReflector::createHandle(OSPDevice device, con auto handle = ospNewCamera("perspective"); throwLastDeviceErrorIfNull(device, handle); - setCameraParams(handle, settings); + setCameraParams(handle, settings.base); setObjectParam(handle, "fovy", settings.fovy); setObjectParam(handle, "aspect", settings.aspectRatio); @@ -56,7 +56,8 @@ OSPCamera ObjectReflector::createHandle(OSPDevice device, co auto handle = ospNewCamera("perspective"); throwLastDeviceErrorIfNull(device, handle); - setCameraParams(handle, settings); + setCameraParams(handle, settings.base); + setObjectParam(handle, "height", settings.height); setObjectParam(handle, "aspect", settings.aspectRatio); diff --git a/src/brayns/core/enginev2/Camera.h b/src/brayns/core/enginev2/Camera.h index 133b2f19f..1918c76d3 100644 --- a/src/brayns/core/enginev2/Camera.h +++ b/src/brayns/core/enginev2/Camera.h @@ -39,8 +39,9 @@ class Camera : public Managed using Managed::Managed; }; -struct PerspectiveCameraSettings : CameraSettings +struct PerspectiveCameraSettings { + CameraSettings base = {}; float fovy = 60.0F; float aspectRatio = 1.0F; }; @@ -59,8 +60,9 @@ struct ObjectReflector static OSPCamera createHandle(OSPDevice device, const Settings &settings); }; -struct OrthographicCameraSettings : CameraSettings +struct OrthographicCameraSettings { + CameraSettings base = {}; float height = 1.0F; float aspectRatio = 1.0F; }; diff --git a/src/brayns/core/enginev2/Device.cpp b/src/brayns/core/enginev2/Device.cpp index c4bb20082..2f4e9702a 100644 --- a/src/brayns/core/enginev2/Device.cpp +++ b/src/brayns/core/enginev2/Device.cpp @@ -33,9 +33,9 @@ OSPDevice Device::getHandle() const return _handle.get(); } -Future Device::render(const RenderSettings &settings) +Future Device::render(const Context &context) { - return startRendering(_handle.get(), settings); + return startRendering(_handle.get(), context); } std::optional Device::pick(const PickSettings &settings) diff --git a/src/brayns/core/enginev2/Device.h b/src/brayns/core/enginev2/Device.h index 1f78a1737..e9be6037b 100644 --- a/src/brayns/core/enginev2/Device.h +++ b/src/brayns/core/enginev2/Device.h @@ -50,7 +50,7 @@ class Device explicit Device(OSPDevice handle); OSPDevice getHandle() const; - Future render(const RenderSettings &settings); + Future render(const Context &context); std::optional pick(const PickSettings &settings); template diff --git a/src/brayns/core/enginev2/Framebuffer.cpp b/src/brayns/core/enginev2/Framebuffer.cpp index 4ae3681f5..ab4e17037 100644 --- a/src/brayns/core/enginev2/Framebuffer.cpp +++ b/src/brayns/core/enginev2/Framebuffer.cpp @@ -62,7 +62,7 @@ OSPFrameBuffer ObjectReflector::createHandle(OSPDevice device, cons auto handle = ospNewFrameBuffer(width, height, format, channels); throwLastDeviceErrorIfNull(device, handle); - setObjectData(handle, "imageOperation", settings.operations); + setObjectDataIfNotEmpty(handle, "imageOperation", settings.operations); commitObject(handle); diff --git a/src/brayns/core/enginev2/GeometricModel.cpp b/src/brayns/core/enginev2/GeometricModel.cpp index 6e428d2f1..6a7fd1ff9 100644 --- a/src/brayns/core/enginev2/GeometricModel.cpp +++ b/src/brayns/core/enginev2/GeometricModel.cpp @@ -26,7 +26,7 @@ namespace using brayns::Color4; using namespace brayns::experimental; -void setMaterialParam(OSPGeometricModel handle, const PrimitiveMaterials &materials) +void setMaterialParams(OSPGeometricModel handle, const PrimitiveMaterials &materials) { setObjectData(handle, "material", materials.rendererIndices); setObjectDataIfNotEmpty(handle, "color", materials.colors); @@ -39,7 +39,7 @@ namespace brayns::experimental void GeometricModel::setMaterials(const PrimitiveMaterials &materials) { auto handle = getHandle(); - setMaterialParam(handle, materials); + setMaterialParams(handle, materials); commitObject(handle); } @@ -56,7 +56,7 @@ OSPGeometricModel ObjectReflector::createHandle(OSPDevice device throwLastDeviceErrorIfNull(device, handle); setObjectParam(handle, "geometry", settings.geometry); - setMaterialParam(handle, settings.materials); + setMaterialParams(handle, settings.materials); setObjectParam(handle, "invertNormals", settings.invertedNormals); setObjectParam(handle, "id", settings.id); diff --git a/src/brayns/core/enginev2/Geometry.cpp b/src/brayns/core/enginev2/Geometry.cpp index f5dd29094..055ac38e9 100644 --- a/src/brayns/core/enginev2/Geometry.cpp +++ b/src/brayns/core/enginev2/Geometry.cpp @@ -21,31 +21,84 @@ #include "Geometry.h" +#include + namespace { +using brayns::Vector3; using namespace brayns::experimental; -void setMeshParams(OSPGeometry handle, const MeshSettings &settings) +void setMeshVerticesParams(OSPGeometry handle, const MeshVertices &vertices) { - setObjectData(handle, "vertex.position", settings.positions); - setObjectDataIfNotEmpty(handle, "vertex.normal", settings.normals); - setObjectDataIfNotEmpty(handle, "vertex.color", settings.colors); - setObjectDataIfNotEmpty(handle, "vertex.texcoord", settings.uvs); + setObjectData(handle, "vertex.position", vertices.positions); + setObjectDataIfNotEmpty(handle, "vertex.normal", vertices.normals); + setObjectDataIfNotEmpty(handle, "vertex.color", vertices.colors); + setObjectDataIfNotEmpty(handle, "vertex.texcoord", vertices.uvs); } -void setSphereParams(OSPGeometry handle, const SphereSettings &settings) +// TODO remove when OSPRay exposes sphere.position_radius to match embree internal layout +void setInterleavedSpheresParams(OSPGeometry handle, std::span points) { - setObjectData(handle, "sphere.position", settings.positions); - setObjectData(handle, "sphere.radius", settings.radii); - setObjectDataIfNotEmpty(handle, "sphere.texcoord", settings.uvs); + auto data = points.data(); + auto size = points.size(); + + constexpr auto stride = sizeof(PositionRadius); + constexpr auto radiusOffset = sizeof(PositionRadius) - sizeof(float); + + auto positions = Data(ospNewSharedData(data, OSP_VEC3F, size, stride)); + setObjectParam(handle, "sphere.position", positions); + + auto radii = Data(ospNewSharedData(data + radiusOffset, OSP_FLOAT, size, stride)); + setObjectParam(handle, "sphere.radius", radii); +} + +void setCurveVerticesParams(OSPGeometry handle, const CurveVertices &vertices) +{ + setObjectData(handle, "vertex.position_radius", vertices.points); + setObjectDataIfNotEmpty(handle, "vertex.texcoord", vertices.uvs); + setObjectDataIfNotEmpty(handle, "vertex.color", vertices.colors); +} + +void setCurveType(OSPGeometry handle, FlatCurve) +{ + setObjectParam(handle, "type", OSP_FLAT); +} + +void setCurveType(OSPGeometry handle, RoundCurve) +{ + setObjectParam(handle, "type", OSP_ROUND); +} + +void setCurveType(OSPGeometry handle, const RibbonCurve &curve) +{ + setObjectParam(handle, "type", OSP_RIBBON); + setObjectData(handle, "vertex.normal", curve.normals); +} + +void setCurveBasis(OSPGeometry handle, LinearCurve) +{ + setObjectParam(handle, "basis", OSP_LINEAR); +} + +void setCurveBasis(OSPGeometry handle, BezierCurve) +{ + setObjectParam(handle, "basis", OSP_BEZIER); +} + +void setCurveBasis(OSPGeometry handle, BsplineCurve) +{ + setObjectParam(handle, "basis", OSP_BSPLINE); } -void setCurveParams(OSPGeometry handle, const CylinderSettings &settings) +void setCurveBasis(OSPGeometry handle, const HermiteCurve &curve) { - setObjectData(handle, "vertex.position_radius", settings.samples); - setObjectData(handle, "index", settings.indices); - setObjectDataIfNotEmpty(handle, "vertex.texcoord", settings.uvs); - setObjectDataIfNotEmpty(handle, "vertex.color", settings.colors); + setObjectParam(handle, "basis", OSP_HERMITE); + setObjectData(handle, "vertex.tangent", curve.tangents); +} + +void setCurveBasis(OSPGeometry handle, CatmullRomCurve) +{ + setObjectParam(handle, "basis", OSP_CATMULL_ROM); } } @@ -63,7 +116,7 @@ OSPGeometry ObjectReflector::createHandle(OSPDevice device, const auto handle = ospNewGeometry("mesh"); throwLastDeviceErrorIfNull(device, handle); - setMeshParams(handle, settings); + setMeshVerticesParams(handle, settings.vertices); setObjectDataIfNotEmpty(handle, "index", settings.indices); commitObject(handle); @@ -76,15 +129,15 @@ OSPGeometry ObjectReflector::createHandle(OSPDevice device, const Sett auto handle = ospNewGeometry("mesh"); throwLastDeviceErrorIfNull(device, handle); - setMeshParams(handle, settings); + setMeshVerticesParams(handle, settings.vertices); - if (!settings.indices.empty()) + if (settings.indices.empty()) { - setObjectData(handle, "index", settings.indices); + setObjectParam(handle, "quadSoup", true); } else { - setObjectParam(handle, "quadSoup", true); + setObjectData(handle, "index", settings.indices); } commitObject(handle); @@ -97,7 +150,9 @@ OSPGeometry ObjectReflector::createHandle(OSPDevice device, const Setti auto handle = ospNewGeometry("sphere"); throwLastDeviceErrorIfNull(device, handle); - setSphereParams(handle, settings); + setInterleavedSpheresParams(handle, settings.points); + setObjectDataIfNotEmpty(handle, "sphere.texcoord", settings.uvs); + setObjectParam(handle, "type", OSP_SPHERE); commitObject(handle); @@ -109,7 +164,8 @@ OSPGeometry ObjectReflector::createHandle(OSPDevice device, const Setting auto handle = ospNewGeometry("sphere"); throwLastDeviceErrorIfNull(device, handle); - setSphereParams(handle, settings); + setInterleavedSpheresParams(handle, settings.points); + setObjectDataIfNotEmpty(handle, "sphere.texcoord", settings.uvs); if (settings.normals.empty()) { @@ -138,7 +194,11 @@ OSPGeometry ObjectReflector::createHandle(OSPDevice device, const Set auto handle = ospNewGeometry("curve"); throwLastDeviceErrorIfNull(device, handle); - setCurveParams(handle, settings); + setCurveVerticesParams(handle, settings.vertices); + setObjectData(handle, "indices", settings.indices); + + setObjectParam(handle, "type", OSP_DISJOINT); + setObjectParam(handle, "basis", OSP_LINEAR); commitObject(handle); @@ -147,29 +207,19 @@ OSPGeometry ObjectReflector::createHandle(OSPDevice device, const Set OSPGeometry ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { - auto handle = ospNewGeometry("curve"); - throwLastDeviceErrorIfNull(device, handle); - - setCurveParams(handle, settings); - - setObjectParam(handle, "type", static_cast(settings.type)); - setObjectParam(handle, "basis", static_cast(settings.basis)); - - commitObject(handle); - - return handle; -} + if (std::holds_alternative(settings.type) && std::holds_alternative(settings.basis)) + { + throw std::invalid_argument("OSPRay does not support ribbon curve with linear basis"); + } -OSPGeometry ObjectReflector::createHandle(OSPDevice device, const Settings &settings) -{ auto handle = ospNewGeometry("curve"); throwLastDeviceErrorIfNull(device, handle); - setCurveParams(handle, settings); + setCurveVerticesParams(handle, settings.vertices); + setObjectData(handle, "indices", settings.indices); - setObjectData(handle, "vertex.normal", settings.normals); - setObjectParam(handle, "type", OSP_RIBBON); - setObjectParam(handle, "basis", static_cast(settings.basis)); + std::visit([=](const auto &value) { setCurveType(handle, value); }, settings.type); + std::visit([=](const auto &value) { setCurveBasis(handle, value); }, settings.basis); commitObject(handle); diff --git a/src/brayns/core/enginev2/Geometry.h b/src/brayns/core/enginev2/Geometry.h index b0728ae1f..2020dd829 100644 --- a/src/brayns/core/enginev2/Geometry.h +++ b/src/brayns/core/enginev2/Geometry.h @@ -21,6 +21,8 @@ #pragma once +#include + #include "Data.h" #include "Object.h" #include "Volume.h" @@ -33,13 +35,12 @@ class Geometry : public Managed using Managed::Managed; }; -struct MeshSettings +struct MeshVertices { std::span positions; std::span normals = {}; std::span colors = {}; std::span uvs = {}; - std::span indices = {}; }; class Mesh : public Geometry @@ -50,8 +51,9 @@ class Mesh : public Geometry void setColors(std::span colors); }; -struct TriangleMeshSettings : MeshSettings +struct TriangleMeshSettings { + MeshVertices vertices; std::span indices = {}; }; @@ -69,8 +71,9 @@ struct ObjectReflector static OSPGeometry createHandle(OSPDevice device, const Settings &settings); }; -struct QuadMeshSettings : MeshSettings +struct QuadMeshSettings { + MeshVertices vertices; std::span indices = {}; }; @@ -88,10 +91,11 @@ struct ObjectReflector static OSPGeometry createHandle(OSPDevice device, const Settings &settings); }; +using PositionRadius = Vector4; + struct SphereSettings { - std::span positions; - std::span radii; + std::span points; std::span uvs = {}; }; @@ -109,9 +113,11 @@ struct ObjectReflector static OSPGeometry createHandle(OSPDevice device, const Settings &settings); }; -struct DiscSettings : SphereSettings +struct DiscSettings { - std::span normals; + std::span points; + std::span normals = {}; + std::span uvs = {}; }; class Discs : public Geometry @@ -128,14 +134,17 @@ struct ObjectReflector static OSPGeometry createHandle(OSPDevice device, const Settings &settings); }; -using PositionRadius = Vector4; +struct CurveVertices +{ + std::span points; + std::span colors = {}; + std::span uvs = {}; +}; struct CylinderSettings { - std::span samples; + CurveVertices vertices; std::span indices; - std::span colors = {}; - std::span uvs = {}; }; class Cylinders : public Geometry @@ -154,63 +163,62 @@ struct ObjectReflector static OSPGeometry createHandle(OSPDevice device, const Settings &settings); }; -enum class CurveType +struct FlatCurve { - Flat = OSP_FLAT, - Round = OSP_ROUND, }; -enum class CurveBasis +struct RoundCurve { - Linear = OSP_LINEAR, - Bezier = OSP_BEZIER, - Bspline = OSP_BSPLINE, - CatmullRom = OSP_CATMULL_ROM, }; -struct CurveSettings : CylinderSettings +struct RibbonCurve { - CurveType type = CurveType::Round; - CurveBasis basis = CurveBasis::Linear; + std::span normals; }; -class Curve : public Cylinders +using CurveType = std::variant; + +struct LinearCurve { -public: - using Cylinders::Cylinders; }; -template<> -struct ObjectReflector +struct BezierCurve { - using Settings = CurveSettings; +}; - static OSPGeometry createHandle(OSPDevice device, const Settings &settings); +struct BsplineCurve +{ }; -enum class RibbonBasis +struct HermiteCurve { - Bezier = OSP_BEZIER, - Bspline = OSP_BSPLINE, - CatmullRom = OSP_CATMULL_ROM, + std::span tangents; }; -struct RibbonSettings : CylinderSettings +struct CatmullRomCurve { - RibbonBasis basis = RibbonBasis::Bezier; - std::span normals; }; -class Ribbon : public Cylinders +using CurveBasis = std::variant; + +struct CurveSettings +{ + CurveVertices vertices; + std::span indices; + CurveType type = RoundCurve(); + CurveBasis basis = LinearCurve(); +}; + +class Curve : public Geometry { public: - using Cylinders::Cylinders; + using Geometry::Geometry; }; template<> -struct ObjectReflector +struct ObjectReflector { - using Settings = RibbonSettings; + using Settings = CurveSettings; static OSPGeometry createHandle(OSPDevice device, const Settings &settings); }; diff --git a/src/brayns/core/enginev2/Light.cpp b/src/brayns/core/enginev2/Light.cpp index 12698de16..d95d7f534 100644 --- a/src/brayns/core/enginev2/Light.cpp +++ b/src/brayns/core/enginev2/Light.cpp @@ -40,7 +40,7 @@ OSPLight ObjectReflector::createHandle(OSPDevice device, const Set auto handle = ospNewLight("distant"); throwLastDeviceErrorIfNull(device, handle); - setLightParams(handle, settings); + setLightParams(handle, settings.base); setObjectParam(handle, "direction", settings.direction); setObjectParam(handle, "angularDiameter", settings.angularDiameter); @@ -55,7 +55,7 @@ OSPLight ObjectReflector::createHandle(OSPDevice device, const Sett auto handle = ospNewLight("sphere"); throwLastDeviceErrorIfNull(device, handle); - setLightParams(handle, settings); + setLightParams(handle, settings.base); setObjectParam(handle, "position", settings.position); setObjectParam(handle, "radius", settings.radius); @@ -70,7 +70,7 @@ OSPLight ObjectReflector::createHandle(OSPDevice device, const Settin auto handle = ospNewLight("spot"); throwLastDeviceErrorIfNull(device, handle); - setLightParams(handle, settings); + setLightParams(handle, settings.base); setObjectParam(handle, "position", settings.position); setObjectParam(handle, "direction", settings.direction); @@ -89,7 +89,7 @@ OSPLight ObjectReflector::createHandle(OSPDevice device, const Settin auto handle = ospNewLight("quad"); throwLastDeviceErrorIfNull(device, handle); - setLightParams(handle, settings); + setLightParams(handle, settings.base); setObjectParam(handle, "position", settings.position); setObjectParam(handle, "edge1", settings.edge1); @@ -100,12 +100,62 @@ OSPLight ObjectReflector::createHandle(OSPDevice device, const Settin return handle; } +OSPLight ObjectReflector::createHandle(OSPDevice device, const Settings &settings) +{ + auto handle = ospNewLight("cylinder"); + throwLastDeviceErrorIfNull(device, handle); + + setLightParams(handle, settings.base); + + setObjectParam(handle, "position1", settings.start); + setObjectParam(handle, "position2", settings.end); + setObjectParam(handle, "radius", settings.radius); + + commitObject(handle); + + return handle; +} + +OSPLight ObjectReflector::createHandle(OSPDevice device, const Settings &settings) +{ + auto handle = ospNewLight("hdri"); + throwLastDeviceErrorIfNull(device, handle); + + setLightParams(handle, settings.base); + + setObjectParam(handle, "up", settings.up); + setObjectParam(handle, "direction", settings.direction); + setObjectParam(handle, "map", settings.map); + + commitObject(handle); + + return handle; +} + OSPLight ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { auto handle = ospNewLight("ambient"); throwLastDeviceErrorIfNull(device, handle); - setLightParams(handle, settings); + setLightParams(handle, settings.base); + + commitObject(handle); + + return handle; +} + +OSPLight ObjectReflector::createHandle(OSPDevice device, const Settings &settings) +{ + auto handle = ospNewLight("sunSky"); + throwLastDeviceErrorIfNull(device, handle); + + setLightParams(handle, settings.base); + + setObjectParam(handle, "up", settings.up); + setObjectParam(handle, "direction", settings.direction); + setObjectParam(handle, "turbidity", settings.turbidity); + setObjectParam(handle, "albedo", settings.albedo); + setObjectParam(handle, "horizonExtension", settings.horizonExtension); commitObject(handle); diff --git a/src/brayns/core/enginev2/Light.h b/src/brayns/core/enginev2/Light.h index 89ff399b5..0fd0a1a7a 100644 --- a/src/brayns/core/enginev2/Light.h +++ b/src/brayns/core/enginev2/Light.h @@ -22,6 +22,7 @@ #pragma once #include "Object.h" +#include "Texture.h" namespace brayns::experimental { @@ -38,8 +39,9 @@ class Light : public Managed using Managed::Managed; }; -struct DistantLightSettings : LightSettings +struct DistantLightSettings { + LightSettings base = {}; Vector3 direction = {0.0F, 0.0F, 1.0F}; float angularDiameter = 0.0F; }; @@ -58,8 +60,9 @@ struct ObjectReflector static OSPLight createHandle(OSPDevice device, const Settings &settings); }; -struct SphereLightSettings : LightSettings +struct SphereLightSettings { + LightSettings base = {}; Vector3 position = {0.0F, 0.0F, 0.0F}; float radius = 0.0F; }; @@ -78,8 +81,9 @@ struct ObjectReflector static OSPLight createHandle(OSPDevice device, const Settings &settings); }; -struct SpotLightSettings : LightSettings +struct SpotLightSettings { + LightSettings base = {}; Vector3 position = {0.0F, 0.0F, 0.0F}; Vector3 direction = {0.0F, 0.0F, 1.0F}; float openingAngle = 180.0F; @@ -102,8 +106,9 @@ struct ObjectReflector static OSPLight createHandle(OSPDevice device, const Settings &settings); }; -struct QuadLightSettings : LightSettings +struct QuadLightSettings { + LightSettings base = {}; Vector3 position = {0.0F, 0.0F, 0.0F}; Vector3 edge1 = {1.0F, 0.0F, 0.0F}; Vector3 edge2 = {0.0F, 1.0F, 0.0F}; @@ -123,8 +128,53 @@ struct ObjectReflector static OSPLight createHandle(OSPDevice device, const Settings &settings); }; -struct AmbientLightSettings : LightSettings +struct CylinderLightSettings { + LightSettings base = {}; + Vector3 start = {0.0F, 0.0F, 0.0F}; + Vector3 end = {0.0F, 0.0F, 1.0F}; + float radius = 1.0F; +}; + +class CylinderLight : public Light +{ +public: + using Light::Light; +}; + +template<> +struct ObjectReflector +{ + using Settings = CylinderLightSettings; + + static OSPLight createHandle(OSPDevice device, const Settings &settings); +}; + +struct HdriLightSettings +{ + Texture2D map; + LightSettings base = {}; + Vector3 up = {0.0F, 1.0F, 0.0F}; + Vector3 direction = {0.0F, 0.0F, 1.0F}; +}; + +class HdriLight : public Light +{ +public: + using Light::Light; +}; + +template<> +struct ObjectReflector +{ + using Settings = HdriLightSettings; + + static OSPLight createHandle(OSPDevice device, const Settings &settings); +}; + +struct AmbientLightSettings +{ + LightSettings base = {}; }; class AmbientLight : public Light @@ -140,4 +190,28 @@ struct ObjectReflector static OSPLight createHandle(OSPDevice device, const Settings &settings); }; + +struct SunSkyLightSettings +{ + LightSettings base = {}; + Vector3 up = {0.0F, 1.0F, 0.0F}; + Vector3 direction = {0.0F, -1.0F, 0.0F}; + float turbidity = 3.0F; + float albedo = 0.3F; + float horizonExtension = 0.01F; +}; + +class SunSkyLight : public Light +{ +public: + using Light::Light; +}; + +template<> +struct ObjectReflector +{ + using Settings = SunSkyLightSettings; + + static OSPLight createHandle(OSPDevice device, const Settings &settings); +}; } diff --git a/src/brayns/core/enginev2/Material.cpp b/src/brayns/core/enginev2/Material.cpp index 42dcb59bf..9d3d0c47b 100644 --- a/src/brayns/core/enginev2/Material.cpp +++ b/src/brayns/core/enginev2/Material.cpp @@ -27,47 +27,45 @@ namespace { using namespace brayns::experimental; -void setTextureParam(OSPMaterial handle, const char *id, std::monostate) +void setTextureParam(OSPMaterial handle, const std::string &id, std::monostate) { - removeObjectParam(handle, id); + removeObjectParam(handle, id.c_str()); } -void setTextureParam(OSPMaterial handle, const char *id, const MaterialTexture2D &texture) +void setTextureParam(OSPMaterial handle, const std::string &id, const MaterialTexture2D &texture) { - setObjectParam(handle, id, texture.value); - - auto name = std::string(id); - - auto rotation = name + ".rotation"; - auto scale = name + ".scale"; - auto translation = name + ".translation"; + setObjectParam(handle, id.c_str(), texture.value); + auto rotation = id + ".rotation"; setObjectParam(handle, rotation.c_str(), texture.transform.rotation); + + auto scale = id + ".scale"; setObjectParam(handle, scale.c_str(), texture.transform.scale); + + auto translation = id + ".translation"; setObjectParam(handle, translation.c_str(), texture.transform.translation); } -void setTextureParam(OSPMaterial handle, const char *id, const MaterialVolumeTexture &texture) +void setTextureParam(OSPMaterial handle, const std::string &id, const MaterialVolumeTexture &texture) { - setObjectParam(handle, id, texture.value); - - auto name = std::string(id); - - auto transform = name + ".transform"; + setObjectParam(handle, id.c_str(), texture.value); + auto transform = id + ".transform"; setObjectParam(handle, transform.c_str(), toAffine(texture.transform)); } -void setTextureParam(OSPMaterial handle, const char *id, const MaterialTexture &texture) +void setTextureParam(OSPMaterial handle, const std::string &id, const MaterialTexture &texture) { - std::visit([=](const auto &value) { setTextureParam(handle, id, value); }, texture); + std::visit([&](const auto &value) { setTextureParam(handle, id, value); }, texture); } -void setMaterialParams(OSPMaterial handle, const AmbientOcclusionMaterialSettings &settings) +template +void setMaterialParam(OSPMaterial handle, const char *id, const MaterialParam ¶m) { - setObjectParam(handle, "kd", settings.diffuse); - setTextureParam(handle, "map_kd", settings.diffuseMap); - setObjectParam(handle, "d", settings.opacity); + setObjectParam(handle, id, param.value); + + auto textureId = std::string("map_") + id; + setTextureParam(handle, textureId, param.texture); } } @@ -78,7 +76,8 @@ OSPMaterial ObjectReflector::createHandle(OSPDevice de auto handle = ospNewMaterial("obj"); throwLastDeviceErrorIfNull(device, handle); - setMaterialParams(handle, settings); + setMaterialParam(handle, "kd", settings.diffuse); + setMaterialParam(handle, "d", settings.opacity); commitObject(handle); @@ -90,10 +89,10 @@ OSPMaterial ObjectReflector::createHandle(OSPDevice device, cons auto handle = ospNewMaterial("obj"); throwLastDeviceErrorIfNull(device, handle); - setMaterialParams(handle, settings); - - setObjectParam(handle, "ks", settings.specular); - setObjectParam(handle, "ns", settings.shininess); + setMaterialParam(handle, "kd", settings.diffuse); + setMaterialParam(handle, "d", settings.opacity); + setMaterialParam(handle, "ks", settings.specular); + setMaterialParam(handle, "ns", settings.shininess); setObjectParam(handle, "tf", settings.transparencyFilter); commitObject(handle); @@ -106,37 +105,35 @@ OSPMaterial ObjectReflector::createHandle(OSPDevice device, auto handle = ospNewMaterial("principled"); throwLastDeviceErrorIfNull(device, handle); - setObjectParam(handle, "baseColor", settings.baseColor); - setTextureParam(handle, "map_baseColor", settings.baseColorMap); - setObjectParam(handle, "edgeColor", settings.edgeColor); - setObjectParam(handle, "metallic", settings.metallic); - setObjectParam(handle, "diffuse", settings.diffuse); - setObjectParam(handle, "specular", settings.specular); - setObjectParam(handle, "ior", settings.ior); - setObjectParam(handle, "transmission", settings.transmission); - setObjectParam(handle, "transmissionColor", settings.transmissionColor); - setObjectParam(handle, "transmissionDepth", settings.transmissionDepth); - setObjectParam(handle, "roughness", settings.roughness); - setObjectParam(handle, "anisotropy", settings.anisotropy); - setObjectParam(handle, "rotation", settings.rotation); - setObjectParam(handle, "normal", settings.normal); - setTextureParam(handle, "map_normal", settings.normalMap); - setObjectParam(handle, "baseNormal", settings.baseNormal); - setObjectParam(handle, "thin", settings.thin); - setObjectParam(handle, "thickness", settings.thickness); - setObjectParam(handle, "backlight", settings.backlight); - setObjectParam(handle, "coat", settings.coat); - setObjectParam(handle, "coatIor", settings.coatIor); - setObjectParam(handle, "coatColor", settings.coatColor); - setObjectParam(handle, "coatThickness", settings.coatThickness); - setObjectParam(handle, "coatRoughness", settings.coatRoughness); - setObjectParam(handle, "coatNormal", settings.coatNormal); - setObjectParam(handle, "sheen", settings.sheen); - setObjectParam(handle, "sheenColor", settings.sheenColor); - setObjectParam(handle, "sheenTint", settings.sheenTint); - setObjectParam(handle, "sheenRoughness", settings.sheenRoughness); - setObjectParam(handle, "opacity", settings.opacity); - setObjectParam(handle, "emissiveColor", settings.emissiveColor); + setMaterialParam(handle, "baseColor", settings.baseColor); + setMaterialParam(handle, "edgeColor", settings.edgeColor); + setMaterialParam(handle, "metallic", settings.metallic); + setMaterialParam(handle, "diffuse", settings.diffuse); + setMaterialParam(handle, "specular", settings.specular); + setMaterialParam(handle, "ior", settings.ior); + setMaterialParam(handle, "transmission", settings.transmission); + setMaterialParam(handle, "transmissionColor", settings.transmissionColor); + setMaterialParam(handle, "transmissionDepth", settings.transmissionDepth); + setMaterialParam(handle, "roughness", settings.roughness); + setMaterialParam(handle, "anisotropy", settings.anisotropy); + setMaterialParam(handle, "rotation", settings.rotation); + setMaterialParam(handle, "normal", settings.normal); + setMaterialParam(handle, "baseNormal", settings.baseNormal); + setMaterialParam(handle, "thin", settings.thin); + setMaterialParam(handle, "thickness", settings.thickness); + setMaterialParam(handle, "backlight", settings.backlight); + setMaterialParam(handle, "coat", settings.coat); + setMaterialParam(handle, "coatIor", settings.coatIor); + setMaterialParam(handle, "coatColor", settings.coatColor); + setMaterialParam(handle, "coatThickness", settings.coatThickness); + setMaterialParam(handle, "coatRoughness", settings.coatRoughness); + setMaterialParam(handle, "coatNormal", settings.coatNormal); + setMaterialParam(handle, "sheen", settings.sheen); + setMaterialParam(handle, "sheenColor", settings.sheenColor); + setMaterialParam(handle, "sheenTint", settings.sheenTint); + setMaterialParam(handle, "sheenRoughness", settings.sheenRoughness); + setMaterialParam(handle, "opacity", settings.opacity); + setMaterialParam(handle, "emissiveColor", settings.emissiveColor); commitObject(handle); diff --git a/src/brayns/core/enginev2/Material.h b/src/brayns/core/enginev2/Material.h index deca8d227..5f91f2f16 100644 --- a/src/brayns/core/enginev2/Material.h +++ b/src/brayns/core/enginev2/Material.h @@ -42,6 +42,13 @@ struct MaterialVolumeTexture using MaterialTexture = std::variant; +template +struct MaterialParam +{ + T value; + MaterialTexture texture = {}; +}; + class Material : public Managed { public: @@ -50,9 +57,8 @@ class Material : public Managed struct AmbientOcclusionMaterialSettings { - Color3 diffuse = {0.8F, 0.8F, 0.8F}; - MaterialTexture diffuseMap = {}; - float opacity = 1.0F; + MaterialParam diffuse = {{0.8F, 0.8F, 0.8F}}; + MaterialParam opacity = {1.0F}; }; class AmbientOcclusionMaterial : public Material @@ -69,10 +75,12 @@ struct ObjectReflector static OSPMaterial createHandle(OSPDevice device, const Settings &settings); }; -struct ScivisMaterialSettings : AmbientOcclusionMaterialSettings +struct ScivisMaterialSettings { - Color3 specular = {0.0F, 0.0F, 0.0F}; - float shininess = 10.0F; + MaterialParam diffuse = {{0.8F, 0.8F, 0.8F}}; + MaterialParam opacity = {1.0F}; + MaterialParam specular = {{0.0F, 0.0F, 0.0F}}; + MaterialParam shininess = {10.0F}; Color3 transparencyFilter = {0.0F, 0.0F, 0.0F}; }; @@ -92,37 +100,37 @@ struct ObjectReflector struct PrincipledMaterialSettings { - Color3 baseColor = {0.8F, 0.8F, 0.8F}; - MaterialTexture baseColorMap = {}; - Color3 edgeColor = {1.0F, 1.0F, 1.0F}; - float metallic = 0.0F; - float diffuse = 1.0F; - float specular = 1.0F; - float ior = 1.0F; - float transmission = 0.0F; - Color3 transmissionColor = {1.0F, 1.0F, 1.0F}; - float transmissionDepth = 1.0F; - float roughness = 0.0F; - float anisotropy = 0.0F; - float rotation = 0.0F; - float normal = 1.0F; - MaterialTexture normalMap = {}; - float baseNormal = 1.0F; - bool thin = false; - float thickness = 1.0F; - float backlight = 0.0F; - float coat = 0.0F; - float coatIor = 1.5F; - Color3 coatColor = {1.0F, 1.0F, 1.0F}; - float coatThickness = 1.0F; - float coatRoughness = 0.0F; - float coatNormal = 1.0F; - float sheen = 0.0F; - Color3 sheenColor = {1.0F, 1.0F, 1.0F}; - float sheenTint = 0.0F; - float sheenRoughness = 0.2F; - float opacity = 1.0F; - Color3 emissiveColor = {0.0F, 0.0F, 0.0F}; + MaterialParam baseColor = {{0.8F, 0.8F, 0.8F}}; + MaterialParam baseColorMap = {{}}; + MaterialParam edgeColor = {{1.0F, 1.0F, 1.0F}}; + MaterialParam metallic = {0.0F}; + MaterialParam diffuse = {1.0F}; + MaterialParam specular = {1.0F}; + MaterialParam ior = {1.0F}; + MaterialParam transmission = {0.0F}; + MaterialParam transmissionColor = {{1.0F, 1.0F, 1.0F}}; + MaterialParam transmissionDepth = {1.0F}; + MaterialParam roughness = {0.0F}; + MaterialParam anisotropy = {0.0F}; + MaterialParam rotation = {0.0F}; + MaterialParam normal = {1.0F}; + MaterialParam normalMap = {{}}; + MaterialParam baseNormal = {1.0F}; + MaterialParam thin = {false}; + MaterialParam thickness = {1.0F}; + MaterialParam backlight = {0.0F}; + MaterialParam coat = {0.0F}; + MaterialParam coatIor = {1.5F}; + MaterialParam coatColor = {{1.0F, 1.0F, 1.0F}}; + MaterialParam coatThickness = {1.0F}; + MaterialParam coatRoughness = {0.0F}; + MaterialParam coatNormal = {1.0F}; + MaterialParam sheen = {0.0F}; + MaterialParam sheenColor = {{1.0F, 1.0F, 1.0F}}; + MaterialParam sheenTint = {0.0F}; + MaterialParam sheenRoughness = {0.2F}; + MaterialParam opacity = {1.0F}; + MaterialParam emissiveColor = {{0.0F, 0.0F, 0.0F}}; }; class PrincipledMaterial : public Material diff --git a/src/brayns/core/enginev2/Object.h b/src/brayns/core/enginev2/Object.h index e7c04b224..41c6fda96 100644 --- a/src/brayns/core/enginev2/Object.h +++ b/src/brayns/core/enginev2/Object.h @@ -124,24 +124,29 @@ class Managed : public Object } }; -Box3 getObjectBounds(OSPObject handle) +inline Box3 getObjectBounds(OSPObject handle) { auto [lower, upper] = ospGetBounds(handle); return {{lower[0], lower[1], lower[2]}, {upper[0], upper[1], upper[2]}}; } -void commitObject(OSPObject handle) +inline void commitObject(OSPObject handle) { ospCommit(handle); } -void removeObjectParam(OSPObject handle, const char *id) +inline void removeObjectParam(OSPObject handle, const char *id) { ospRemoveParam(handle, id); } +using DataType = OSPDataType; + +template +constexpr auto dataTypeOf = ospray::OSPTypeFor::value; + template -concept OsprayDataType = (ospray::OSPTypeFor::value != OSP_UNKNOWN); +concept OsprayDataType = (dataTypeOf != OSP_UNKNOWN); template void setObjectParam(OSPObject handle, const char *id, const T &value) diff --git a/src/brayns/core/enginev2/Render.cpp b/src/brayns/core/enginev2/Render.cpp index a503ef3f3..76f70c7ec 100644 --- a/src/brayns/core/enginev2/Render.cpp +++ b/src/brayns/core/enginev2/Render.cpp @@ -48,12 +48,12 @@ float Future::waitAndGetDuration() return ospGetTaskDuration(handle); } -Future startRendering(OSPDevice device, const RenderSettings &settings) +Future startRendering(OSPDevice device, const Context &context) { - auto framebuffer = settings.framebuffer.getHandle(); - auto renderer = settings.renderer.getHandle(); - auto camera = settings.camera.getHandle(); - auto world = settings.world.getHandle(); + auto framebuffer = context.framebuffer.getHandle(); + auto renderer = context.renderer.getHandle(); + auto camera = context.camera.getHandle(); + auto world = context.world.getHandle(); auto handle = ospRenderFrame(framebuffer, renderer, camera, world); throwLastDeviceErrorIfNull(device, handle); @@ -65,14 +65,14 @@ std::optional tryPick(OSPDevice device, const PickSettings &settings { (void)device; - auto framebuffer = settings.framebuffer.getHandle(); - auto renderer = settings.renderer.getHandle(); - auto camera = settings.camera.getHandle(); - auto world = settings.world.getHandle(); - auto [x, y] = settings.normalizedScreenPosition; + auto framebuffer = settings.context.framebuffer.getHandle(); + auto renderer = settings.context.renderer.getHandle(); + auto camera = settings.context.camera.getHandle(); + auto world = settings.context.world.getHandle(); + auto [screenX, screenY] = settings.normalizedScreenPosition; auto result = OSPPickResult(); - ospPick(&result, framebuffer, renderer, camera, world, x, y); + ospPick(&result, framebuffer, renderer, camera, world, screenX, screenY); if (!result.hasHit) { diff --git a/src/brayns/core/enginev2/Render.h b/src/brayns/core/enginev2/Render.h index 4408d932d..fc9e6e27a 100644 --- a/src/brayns/core/enginev2/Render.h +++ b/src/brayns/core/enginev2/Render.h @@ -31,7 +31,7 @@ namespace brayns::experimental { -struct RenderSettings +struct Context { Framebuffer framebuffer; Renderer renderer; @@ -50,10 +50,11 @@ class Future : public Managed float waitAndGetDuration(); }; -Future startRendering(OSPDevice device, const RenderSettings &settings); +Future startRendering(OSPDevice device, const Context &context); -struct PickSettings : RenderSettings +struct PickSettings { + Context context; Vector2 normalizedScreenPosition; }; diff --git a/src/brayns/core/enginev2/Renderer.cpp b/src/brayns/core/enginev2/Renderer.cpp index e531c8422..d4840945b 100644 --- a/src/brayns/core/enginev2/Renderer.cpp +++ b/src/brayns/core/enginev2/Renderer.cpp @@ -48,6 +48,12 @@ void setRendererParams(OSPRenderer handle, const RendererSettings &settings) setObjectParam(handle, "minContribution", settings.minSampleContribution); setObjectParam(handle, "varianceThreshold", settings.varianceThreshold); setBackground(handle, settings.background); + + if (settings.maxDepth) + { + setObjectParam(handle, "maxDepth", *settings.maxDepth); + } + setObjectData(handle, "material", settings.materials); setObjectParam(handle, "pixelFilter", static_cast(settings.pixelFilter)); } @@ -60,7 +66,7 @@ OSPRenderer ObjectReflector::createHandle(OSPDevice de auto handle = ospNewRenderer("ao"); throwLastDeviceErrorIfNull(device, handle); - setRendererParams(handle, settings); + setRendererParams(handle, settings.base); setObjectParam(handle, "aoSamples", settings.aoSamples); setObjectParam(handle, "aoDistance", settings.aoDistance); @@ -77,7 +83,7 @@ OSPRenderer ObjectReflector::createHandle(OSPDevice device, cons auto handle = ospNewRenderer("scivis"); throwLastDeviceErrorIfNull(device, handle); - setRendererParams(handle, settings); + setRendererParams(handle, settings.base); setObjectParam(handle, "shadows", settings.shadows); setObjectParam(handle, "aoSamples", settings.aoSamples); @@ -95,7 +101,7 @@ OSPRenderer ObjectReflector::createHandle(OSPDevice device, const Se auto handle = ospNewRenderer("pathtracer"); throwLastDeviceErrorIfNull(device, handle); - setRendererParams(handle, settings); + setRendererParams(handle, settings.base); commitObject(handle); diff --git a/src/brayns/core/enginev2/Renderer.h b/src/brayns/core/enginev2/Renderer.h index 75679a10f..79632059b 100644 --- a/src/brayns/core/enginev2/Renderer.h +++ b/src/brayns/core/enginev2/Renderer.h @@ -21,6 +21,7 @@ #pragma once +#include #include #include "Data.h" @@ -48,6 +49,7 @@ struct RendererSettings float minSampleContribution = 0.001F; float varianceThreshold = 0.0F; Background background = Color4(0.0F, 0.0F, 0.0F, 0.0F); + std::optional maxDepth = std::nullopt; std::span materials = {}; PixelFilter pixelFilter = PixelFilter::Gauss; }; @@ -58,8 +60,9 @@ class Renderer : public Managed using Managed::Managed; }; -struct AmbientOcclusionRendererSettings : RendererSettings +struct AmbientOcclusionRendererSettings { + RendererSettings base = {}; std::size_t aoSamples = 1; float aoDistance = 1e20F; float aoIntensity = 1.0F; @@ -80,8 +83,9 @@ struct ObjectReflector static OSPRenderer createHandle(OSPDevice device, const Settings &settings); }; -struct ScivisRendererSettings : RendererSettings +struct ScivisRendererSettings { + RendererSettings base = {}; bool shadows = false; std::size_t aoSamples = 0; float aoDistance = 1e20F; @@ -103,8 +107,9 @@ struct ObjectReflector static OSPRenderer createHandle(OSPDevice device, const Settings &settings); }; -struct PathTracerSettings : RendererSettings +struct PathTracerSettings { + RendererSettings base = {}; }; class PathTracer : public Renderer diff --git a/src/brayns/core/enginev2/Texture.cpp b/src/brayns/core/enginev2/Texture.cpp index a12b1b879..ffd6a396e 100644 --- a/src/brayns/core/enginev2/Texture.cpp +++ b/src/brayns/core/enginev2/Texture.cpp @@ -26,7 +26,17 @@ namespace using brayns::Size2; using namespace brayns::experimental; -OSPDataType getDataType(TextureFormat format) +Data toSharedData2D(const void *data, TextureFormat format, const Size2 &size) +{ + auto type = getTextureDataType(format); + auto handle = ospNewSharedData(data, type, size[0], 0, size[1]); + return Data(handle); +} +} + +namespace brayns::experimental +{ +DataType getTextureDataType(TextureFormat format) { switch (format) { @@ -61,16 +71,6 @@ OSPDataType getDataType(TextureFormat format) } } -Data toSharedData2D(const void *data, TextureFormat format, const Size2 &size) -{ - auto type = getDataType(format); - auto handle = ospNewSharedData(data, type, size[0], 0, size[1]); - return Data(handle); -} -} - -namespace brayns::experimental -{ OSPTexture ObjectReflector::createHandle(OSPDevice device, const Settings &settings) { auto handle = ospNewTexture("texture2D"); diff --git a/src/brayns/core/enginev2/Texture.h b/src/brayns/core/enginev2/Texture.h index edb2207e4..84c55fc84 100644 --- a/src/brayns/core/enginev2/Texture.h +++ b/src/brayns/core/enginev2/Texture.h @@ -53,6 +53,8 @@ enum class TextureFormat R16 = OSP_TEXTURE_R16, }; +DataType getTextureDataType(TextureFormat format); + enum class TextureFilter { Linear = OSP_TEXTURE_FILTER_LINEAR, diff --git a/src/brayns/core/utils/Math.h b/src/brayns/core/utils/Math.h index 48027a2b9..9ff09dc44 100644 --- a/src/brayns/core/utils/Math.h +++ b/src/brayns/core/utils/Math.h @@ -47,11 +47,11 @@ using Color4 = Vector4; using Quaternion = rkcommon::math::quaternionf; template -using Box = rkcommon::math::box_t; +using BoxT = rkcommon::math::box_t; using Box1 = rkcommon::math::box1f; -using Box2 = Box; -using Box3 = Box; +using Box2 = BoxT; +using Box3 = BoxT; using Affine2 = rkcommon::math::AffineSpace2f; using Affine3 = rkcommon::math::AffineSpace3f; diff --git a/tests/core/enginev2/TestRender.cpp b/tests/core/enginev2/TestRender.cpp index 69b7b256d..938ca6006 100644 --- a/tests/core/enginev2/TestRender.cpp +++ b/tests/core/enginev2/TestRender.cpp @@ -59,89 +59,57 @@ TEST_CASE("Render") auto materials = std::vector{material}; - auto renderer = device.create(); + auto renderer = device.create({.base = {.materials = materials}}); - auto camera = device.create(); - camera.setAspectRatio(float(width) / float(height)); - camera.setFovy(45); - camera.setTransform(toAffine({.translation = {0, 0, -1}})); - camera.setNearClip(0); - camera.commit(); + auto camera = device.create({ + .base = {.position = {0, 0, -1}, .direction = {0, 0, 1}, .nearClippingDistance = 0}, + .fovy = 45.0F, + .aspectRatio = float(width) / float(height), + }); - auto positions = std::vector{{0, 0, 3}, {1, 0, 3}, {1, 1, 3}}; - auto radii = std::vector{0.25F, 0.25F, 0.25F}; + auto points = std::vector{{0, 0, 3, 0.25F}, {1, 0, 3, 0.25F}, {1, 1, 3, 0.25F}}; auto colors = std::vector{{1, 0, 0, 1}, {0, 0, 1, 1}, {0, 1, 0, 1}}; - auto spheres = device.createGeometry(); - spheres.setPositions(positions); - spheres.setRadii(radii); - spheres.commit(); + auto spheres = device.create({.points = points}); - auto model = device.createGeometricModel(); - model.setGeometry(spheres); - model.setPrimitiveColors(colors); - model.setMaterial(0); - model.setId(0); - model.commit(); + auto materialIndices = std::vector{0}; - auto models = std::vector{model}; + auto model = device.create({ + .geometry = spheres, + .materials = {.rendererIndices = materialIndices, .colors = colors}, + .id = 0, + }); - auto light = device.createLight(); - light.setIntensity(1); - light.setColor({1, 1, 1}); - light.setVisible(true); - light.commit(); + auto light = device.create({}); + auto models = std::vector{model}; auto lights = std::vector{light}; - auto group = device.createGroup(); - group.setGeometries(models); - group.setLights(lights); - group.commit(); + auto group = device.create({.geometries = models, .lights = lights}); - auto instance = device.createInstance(); - instance.setGroup(group); - instance.setTransform(toAffine({})); - instance.setId(0); - instance.commit(); + auto instance = device.create({.group = group, .transform = {}, .id = 0}); auto instances = std::vector{instance}; - auto world = device.createWorld(); - world.setInstances(instances); - world.commit(); + auto world = device.create({instances}); CHECK_EQ(world.getBounds(), instance.getBounds()); CHECK_EQ(world.getBounds(), group.getBounds()); - auto task = device.render({ + auto future = device.render({ .framebuffer = framebuffer, .renderer = renderer, .camera = camera, .world = world, }); - auto duration = task.waitAndGetDuration(); + auto duration = future.waitAndGetDuration(); CHECK(duration > 0); - CHECK(task.getProgress() == 1); + CHECK(future.getProgress() == 1); auto data = framebuffer.map(FramebufferChannel::Color); - /*rkcommon::utility::writePPM( - "test.ppm", - width, - height, - static_cast(data));*/ - - auto pixels = static_cast(data); - - auto sum = std::uint32_t(0); - for (auto i = 0; i < width * height; ++i) - { - sum += pixels[i]; - } - - CHECK(sum > 0); + rkcommon::utility::writePPM("test.ppm", width, height, static_cast(data)); framebuffer.unmap(data); From 6ce3be0951646efd0ac855c6c33a71fae89baf05 Mon Sep 17 00:00:00 2001 From: Adrien4193 Date: Mon, 10 Jun 2024 15:46:56 +0200 Subject: [PATCH 7/7] Fix bug. --- src/brayns/core/enginev2/Geometry.cpp | 15 ++++++++------- src/brayns/core/enginev2/Renderer.cpp | 8 ++++---- src/brayns/core/enginev2/World.h | 2 +- tests/core/enginev2/TestRender.cpp | 3 +-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/brayns/core/enginev2/Geometry.cpp b/src/brayns/core/enginev2/Geometry.cpp index 055ac38e9..87f83faad 100644 --- a/src/brayns/core/enginev2/Geometry.cpp +++ b/src/brayns/core/enginev2/Geometry.cpp @@ -39,17 +39,18 @@ void setMeshVerticesParams(OSPGeometry handle, const MeshVertices &vertices) // TODO remove when OSPRay exposes sphere.position_radius to match embree internal layout void setInterleavedSpheresParams(OSPGeometry handle, std::span points) { - auto data = points.data(); + constexpr auto stride = sizeof(PositionRadius); + auto size = points.size(); - constexpr auto stride = sizeof(PositionRadius); - constexpr auto radiusOffset = sizeof(PositionRadius) - sizeof(float); + const auto *positions = points.data(); + const auto *radii = &positions[0].w; - auto positions = Data(ospNewSharedData(data, OSP_VEC3F, size, stride)); - setObjectParam(handle, "sphere.position", positions); + auto positionData = Data(ospNewSharedData(positions, OSP_VEC3F, size, stride)); + setObjectParam(handle, "sphere.position", positionData); - auto radii = Data(ospNewSharedData(data + radiusOffset, OSP_FLOAT, size, stride)); - setObjectParam(handle, "sphere.radius", radii); + auto radiusData = Data(ospNewSharedData(radii, OSP_FLOAT, size, stride)); + setObjectParam(handle, "sphere.radius", radiusData); } void setCurveVerticesParams(OSPGeometry handle, const CurveVertices &vertices) diff --git a/src/brayns/core/enginev2/Renderer.cpp b/src/brayns/core/enginev2/Renderer.cpp index d4840945b..353468ca5 100644 --- a/src/brayns/core/enginev2/Renderer.cpp +++ b/src/brayns/core/enginev2/Renderer.cpp @@ -43,8 +43,8 @@ void setBackground(OSPRenderer handle, const Background &background) void setRendererParams(OSPRenderer handle, const RendererSettings &settings) { - setObjectParam(handle, "pixelSamples", settings.pixelSamples); - setObjectParam(handle, "maxPathLength", settings.maxRayRecursionDepth); + setObjectParam(handle, "pixelSamples", static_cast(settings.pixelSamples)); + setObjectParam(handle, "maxPathLength", static_cast(settings.maxRayRecursionDepth)); setObjectParam(handle, "minContribution", settings.minSampleContribution); setObjectParam(handle, "varianceThreshold", settings.varianceThreshold); setBackground(handle, settings.background); @@ -68,7 +68,7 @@ OSPRenderer ObjectReflector::createHandle(OSPDevice de setRendererParams(handle, settings.base); - setObjectParam(handle, "aoSamples", settings.aoSamples); + setObjectParam(handle, "aoSamples", static_cast(settings.aoSamples)); setObjectParam(handle, "aoDistance", settings.aoDistance); setObjectParam(handle, "aoIntensity", settings.aoIntensity); setObjectParam(handle, "volumeSamplingRate", settings.volumeSamplingRate); @@ -86,7 +86,7 @@ OSPRenderer ObjectReflector::createHandle(OSPDevice device, cons setRendererParams(handle, settings.base); setObjectParam(handle, "shadows", settings.shadows); - setObjectParam(handle, "aoSamples", settings.aoSamples); + setObjectParam(handle, "aoSamples", static_cast(settings.aoSamples)); setObjectParam(handle, "aoDistance", settings.aoDistance); setObjectParam(handle, "volumeSamplingRate", settings.volumeSamplingRate); setObjectParam(handle, "visibleLights", settings.showVisibleLights); diff --git a/src/brayns/core/enginev2/World.h b/src/brayns/core/enginev2/World.h index 55e1757d3..c28cfcc19 100644 --- a/src/brayns/core/enginev2/World.h +++ b/src/brayns/core/enginev2/World.h @@ -56,7 +56,7 @@ struct ObjectReflector struct InstanceSettings { Group group; - Transform transform; + Transform transform = {}; std::uint32_t id = std::uint32_t(-1); }; diff --git a/tests/core/enginev2/TestRender.cpp b/tests/core/enginev2/TestRender.cpp index 938ca6006..060578b6e 100644 --- a/tests/core/enginev2/TestRender.cpp +++ b/tests/core/enginev2/TestRender.cpp @@ -62,7 +62,6 @@ TEST_CASE("Render") auto renderer = device.create({.base = {.materials = materials}}); auto camera = device.create({ - .base = {.position = {0, 0, -1}, .direction = {0, 0, 1}, .nearClippingDistance = 0}, .fovy = 45.0F, .aspectRatio = float(width) / float(height), }); @@ -109,7 +108,7 @@ TEST_CASE("Render") auto data = framebuffer.map(FramebufferChannel::Color); - rkcommon::utility::writePPM("test.ppm", width, height, static_cast(data)); + /*rkcommon::utility::writePPM("test.ppm", width, height, static_cast(data));*/ framebuffer.unmap(data);