diff --git a/apps/service.cpp b/apps/service.cpp index 4ba98996a..d3dd500d3 100644 --- a/apps/service.cpp +++ b/apps/service.cpp @@ -73,12 +73,12 @@ int main(int argc, const char **argv) } catch (const std::exception &e) { - brayns::Log::critical("Fatal error: '{}'.", e.what()); + brayns::Log::fatal("Fatal error: '{}'.", e.what()); return 1; } catch (...) { - brayns::Log::critical("Unknown fatal error."); + brayns::Log::fatal("Unknown fatal error."); return 1; } diff --git a/src/brayns/core/engine/components/Transform.cpp b/src/brayns/core/engine/components/Transform.cpp index dd8e82bab..d2449f534 100644 --- a/src/brayns/core/engine/components/Transform.cpp +++ b/src/brayns/core/engine/components/Transform.cpp @@ -22,18 +22,4 @@ namespace brayns { -TransformMatrix Transform::toMatrix() const noexcept -{ - return TransformMatrix(translation, rotation, scale); -} - -bool Transform::operator==(const Transform &other) const noexcept -{ - return translation == other.translation && rotation == other.rotation && scale == other.scale; -} - -bool Transform::operator!=(const Transform &other) const noexcept -{ - return !(*this == other); -} } // namespace brayns diff --git a/src/brayns/core/engine/components/Transform.h b/src/brayns/core/engine/components/Transform.h index 3110a11c3..9b57948af 100644 --- a/src/brayns/core/engine/components/Transform.h +++ b/src/brayns/core/engine/components/Transform.h @@ -24,18 +24,4 @@ namespace brayns { -/** - * @brief Defines the translation, rotation and scale parameters to be applied - * to a scene asset. - */ -struct Transform -{ - Vector3f translation = Vector3f(0.f, 0.f, 0.f); - Quaternion rotation = Quaternion(1, 0, 0, 0); - Vector3f scale = Vector3f(1.f, 1.f, 1.f); - - TransformMatrix toMatrix() const noexcept; - bool operator==(const Transform &other) const noexcept; - bool operator!=(const Transform &other) const noexcept; -}; } // namespace brayns diff --git a/src/brayns/core/engine/core/Engine.cpp b/src/brayns/core/engine/core/Engine.cpp index eeff27002..7d9fa7edc 100644 --- a/src/brayns/core/engine/core/Engine.cpp +++ b/src/brayns/core/engine/core/Engine.cpp @@ -40,7 +40,7 @@ class OsprayLogLevel { case brayns::LogLevel::Off: return OSPLogLevel::OSP_LOG_NONE; - case brayns::LogLevel::Critical: + case brayns::LogLevel::Fatal: case brayns::LogLevel::Error: return OSPLogLevel::OSP_LOG_ERROR; case brayns::LogLevel::Warn: @@ -49,7 +49,6 @@ class OsprayLogLevel return OSPLogLevel::OSP_LOG_INFO; case brayns::LogLevel::Debug: case brayns::LogLevel::Trace: - case brayns::LogLevel::Count: return OSPLogLevel::OSP_LOG_DEBUG; } diff --git a/src/brayns/core/engine/model/ModelInstance.cpp b/src/brayns/core/engine/model/ModelInstance.cpp index f96ad3d75..0e26244ca 100644 --- a/src/brayns/core/engine/model/ModelInstance.cpp +++ b/src/brayns/core/engine/model/ModelInstance.cpp @@ -130,16 +130,16 @@ bool ModelInstance::commit() TransformMatrix ModelInstance::_getFullTransform() const noexcept { - auto matrix = _transform.toMatrix(); + auto matrix = toAffine(_transform); auto &components = _model->getComponents(); auto baseTransform = components.find(); if (baseTransform) { - matrix = matrix * baseTransform->toMatrix(); + matrix = matrix * toAffine(*baseTransform); } - return matrix; + return TransformMatrix(matrix); } void ModelInstance::_updateTransform() diff --git a/src/brayns/core/rendering/Camera.cpp b/src/brayns/core/rendering/Camera.cpp new file mode 100644 index 000000000..f7815b00d --- /dev/null +++ b/src/brayns/core/rendering/Camera.cpp @@ -0,0 +1,55 @@ +/* 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 "Camera.h" + +namespace brayns::experimental +{ +void Camera::setTransform(const Affine3 &transform) +{ + setParam("transform", transform); +} + +void Camera::setNearClip(float distance) +{ + setParam("nearClip", distance); +} + +void PerspectiveCamera::setFovy(float degrees) +{ + setParam("fovy", degrees); +} + +void PerspectiveCamera::setAspectRatio(float aspect) +{ + setParam("aspect", aspect); +} + +void OrthographicCamera::setHeight(float height) +{ + setParam("height", height); +} + +void OrthographicCamera::setAspectRatio(float aspect) +{ + setParam("aspect", aspect); +} +} diff --git a/src/brayns/core/rendering/Camera.h b/src/brayns/core/rendering/Camera.h new file mode 100644 index 000000000..461fca25c --- /dev/null +++ b/src/brayns/core/rendering/Camera.h @@ -0,0 +1,65 @@ +/* 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 "Managed.h" + +namespace brayns::experimental +{ +class Camera : public Managed +{ +public: + using Managed::Managed; + + void setTransform(const Affine3 &transform); + void setNearClip(float distance); +}; + +class PerspectiveCamera : public Camera +{ +public: + static inline const std::string name = "perspective"; + + using Camera::Camera; + + void setFovy(float degrees); + void setAspectRatio(float aspect); +}; + +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/rendering/Data.h b/src/brayns/core/rendering/Data.h new file mode 100644 index 000000000..fca481824 --- /dev/null +++ b/src/brayns/core/rendering/Data.h @@ -0,0 +1,38 @@ +/* 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 + +namespace brayns::experimental +{ +template +using SharedArray = std::span; + +template +ospray::cpp::SharedData toSharedData(SharedArray data) +{ + return ospray::cpp::SharedData(data.data(), data.size()); +} +} diff --git a/src/brayns/core/rendering/Device.cpp b/src/brayns/core/rendering/Device.cpp new file mode 100644 index 000000000..63af0abe4 --- /dev/null +++ b/src/brayns/core/rendering/Device.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 "Device.h" + +namespace brayns::experimental +{ +Device::Device(OSPDevice handle): + _handle(handle) +{ +} + +GeometricModel Device::createGeometricModel() +{ + auto handle = ospNewGeometricModel(); + return GeometricModel(handle); +} + +VolumetricModel Device::createVolumetricModel() +{ + auto handle = ospNewVolumetricModel(); + return VolumetricModel(handle); +} + +Group Device::createGroup() +{ + auto handle = ospNewGroup(); + return Group(handle); +} + +Instance Device::createInstance() +{ + auto handle = ospNewInstance(); + return Instance(handle); +} + +World Device::createWorld() +{ + auto handle = ospNewWorld(); + 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); + 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); + return RenderTask(future); +} + +void Device::Deleter::operator()(OSPDevice device) const +{ + ospDeviceRelease(device); +} +} diff --git a/src/brayns/core/rendering/Device.h b/src/brayns/core/rendering/Device.h new file mode 100644 index 000000000..e29f62db0 --- /dev/null +++ b/src/brayns/core/rendering/Device.h @@ -0,0 +1,126 @@ +/* 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 "Camera.h" +#include "Framebuffer.h" +#include "Geometry.h" +#include "Light.h" +#include "Material.h" +#include "Render.h" +#include "Renderer.h" +#include "Volume.h" +#include "World.h" + +namespace brayns::experimental +{ +class Device +{ +public: + explicit Device(OSPDevice handle); + + GeometricModel createGeometricModel(); + VolumetricModel createVolumetricModel(); + Group createGroup(); + Instance createInstance(); + World createWorld(); + Framebuffer createFramebuffer(const FramebufferSettings &settings); + RenderTask render(const RenderSettings &settings); + + template CameraType> + CameraType createCamera() + { + const auto &name = CameraType::name; + auto handle = ospNewCamera(name.c_str()); + return CameraType(handle); + } + + template ImageOperationType> + ImageOperationType createImageOperation() + { + const auto &name = ImageOperationType::name; + auto handle = ospNewImageOperation(name.c_str()); + return ImageOperationType(handle); + } + + template GeometryType> + GeometryType createGeometry() + { + const auto &name = GeometryType::name; + auto handle = ospNewGeometry(name.c_str()); + return GeometryType(handle); + } + + template LightType> + LightType createLight() + { + const auto &name = LightType::name; + auto handle = ospNewLight(name.c_str()); + return LightType(handle); + } + + template MaterialType> + MaterialType createMaterial() + { + const auto &name = MaterialType::name; + auto handle = ospNewMaterial(name.c_str()); + return MaterialType(handle); + } + + template RendererType> + RendererType createRenderer() + { + const auto &name = RendererType::name; + auto handle = ospNewRenderer(name.c_str()); + return RendererType(handle); + } + + template TransferFunctionType> + TransferFunctionType createTransferFunction() + { + const auto &name = TransferFunctionType::name; + auto handle = ospNewTransferFunction(name.c_str()); + return TransferFunctionType(handle); + } + + template VolumeType> + VolumeType createVolume() + { + const auto &name = VolumeType::name; + auto handle = ospNewVolume(name.c_str()); + return VolumeType(handle); + } + +private: + struct Deleter + { + void operator()(OSPDevice device) const; + }; + + std::unique_ptr _handle; +}; +} diff --git a/src/brayns/core/rendering/Framebuffer.cpp b/src/brayns/core/rendering/Framebuffer.cpp new file mode 100644 index 000000000..144fcd710 --- /dev/null +++ b/src/brayns/core/rendering/Framebuffer.cpp @@ -0,0 +1,54 @@ +/* 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 "Framebuffer.h" + +namespace brayns::experimental +{ +const void *Framebuffer::map(FramebufferChannel channel) +{ + auto handle = getHandle(); + return ospMapFrameBuffer(handle, static_cast(channel)); +} + +void Framebuffer::unmap(const void *data) +{ + auto handle = getHandle(); + ospUnmapFrameBuffer(data, handle); +} + +void Framebuffer::resetAccumulation() +{ + auto handle = getHandle(); + ospResetAccumulation(handle); +} + +float Framebuffer::getVariance() +{ + auto handle = getHandle(); + return ospGetVariance(handle); +} + +void Framebuffer::setImageOperations(SharedArray operations) +{ + setParam("imageOperation", toSharedData(operations)); +} +} diff --git a/src/brayns/core/rendering/Framebuffer.h b/src/brayns/core/rendering/Framebuffer.h new file mode 100644 index 000000000..27e462f9e --- /dev/null +++ b/src/brayns/core/rendering/Framebuffer.h @@ -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. + */ + +#pragma once + +#include "Data.h" +#include "Managed.h" + +namespace brayns::experimental +{ +class ImageOperation : public Managed +{ +public: + using Managed::Managed; +}; + +class ToneMapper : public ImageOperation +{ +public: + static inline const std::string name = "tonemapper"; + + using ImageOperation::ImageOperation; +}; + +enum class FramebufferFormat +{ + Rgba8 = OSP_FB_RGBA8, + Srgba8 = OSP_FB_SRGBA, + Rgba32f = OSP_FB_RGBA32F, +}; + +enum class FramebufferChannel +{ + Color = OSP_FB_COLOR, + Depth = OSP_FB_DEPTH, + Accumulation = OSP_FB_ACCUM, + Variance = OSP_FB_VARIANCE, + Normal = OSP_FB_NORMAL, + Albedo = OSP_FB_ALBEDO, + PrimitiveId = OSP_FB_ID_PRIMITIVE, + ModelId = OSP_FB_ID_OBJECT, + InstanceId = OSP_FB_ID_INSTANCE, +}; + +struct FramebufferSettings +{ + std::size_t width; + std::size_t height; + FramebufferFormat format = FramebufferFormat::Srgba8; + std::vector channels = {FramebufferChannel::Color}; +}; + +class Framebuffer : public Managed +{ +public: + using Managed::Managed; + + const void *map(FramebufferChannel channel); + 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/rendering/Geometry.cpp b/src/brayns/core/rendering/Geometry.cpp new file mode 100644 index 000000000..6fb4102a6 --- /dev/null +++ b/src/brayns/core/rendering/Geometry.cpp @@ -0,0 +1,165 @@ +/* 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 "Geometry.h" + +namespace brayns::experimental +{ +void GeometricModel::setGeometry(const Geometry &geometry) +{ + setParam("geometry", geometry.getHandle()); +} + +void GeometricModel::setMaterial(std::uint32_t rendererIndex) +{ + setParam("material", rendererIndex); +} + +void GeometricModel::setPrimitiveMaterials(SharedArray rendererIndices) +{ + setParam("material", toSharedData(rendererIndices)); +} + +void GeometricModel::setPrimitiveColors(SharedArray colors) +{ + setParam("color", toSharedData(colors)); +} + +void GeometricModel::setColor(const Color4 &color) +{ + setParam("color", color); +} + +void GeometricModel::removeColors() +{ + removeParam("color"); +} + +void GeometricModel::invertNormals(bool inverted) +{ + setParam("invertNormals", inverted); +} + +void GeometricModel::setId(std::uint32_t id) +{ + setParam("id", id); +} + +void Mesh::setVertexPositions(SharedArray positions) +{ + setParam("vertex.position", toSharedData(positions)); +} + +void Mesh::setVertexNormals(SharedArray normals) +{ + setParam("vertex.normal", toSharedData(normals)); +} + +void Mesh::setVertexColors(SharedArray colors) +{ + setParam("vertex.color", toSharedData(colors)); +} + +void Mesh::setTriangleIndices(SharedArray indices) +{ + setParam("index", toSharedData(indices)); +} + +void Mesh::setQuadIndices(SharedArray indices) +{ + setParam("index", toSharedData(indices)); +} + +void Mesh::setQuadSoup(bool quadSoup) +{ + setParam("quadSoup", quadSoup); +} + +void Spheres::setPositions(SharedArray positions) +{ + setParam("sphere.position", toSharedData(positions)); +} + +void Spheres::setRadii(SharedArray radii) +{ + setParam("sphere.radius", toSharedData(radii)); +} + +void Spheres::setRadius(float radius) +{ + setParam("radius", radius); +} + +void Curve::setVertexPositionsAndRadii(SharedArray positionsRadii) +{ + setParam("vertex.position_radius", toSharedData(positionsRadii)); +} + +void Curve::setVertexColors(SharedArray colors) +{ + setParam("vertex.color", toSharedData(colors)); +} + +void Curve::setIndices(SharedArray indices) +{ + setParam("index", toSharedData(indices)); +} + +void Curve::setType(CurveType type) +{ + setParam("type", static_cast(type)); +} + +void Curve::setBasis(CurveBasis basis) +{ + setParam("basis", static_cast(basis)); +} + +void Boxes::setBoxes(SharedArray boxes) +{ + setParam("box", toSharedData(boxes)); +} + +void Planes::setCoefficients(SharedArray coefficients) +{ + setParam("plane.coefficients", toSharedData(coefficients)); +} + +void Planes::setBounds(SharedArray bounds) +{ + setParam("plane.bounds", toSharedData(bounds)); +} + +void Isosurfaces::setVolume(const Volume &volume) +{ + setParam("volume", volume.getHandle()); +} + +void Isosurfaces::setIsovalues(SharedArray values) +{ + setParam("isovalue", toSharedData(values)); +} + +void Isosurfaces::setIsovalue(float value) +{ + setParam("isovalue", value); +} +} diff --git a/src/brayns/core/rendering/Geometry.h b/src/brayns/core/rendering/Geometry.h new file mode 100644 index 000000000..2598a8e8b --- /dev/null +++ b/src/brayns/core/rendering/Geometry.h @@ -0,0 +1,152 @@ +/* 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 "Managed.h" +#include "Volume.h" + +namespace brayns::experimental +{ +class Geometry : public Managed +{ +public: + using Managed::Managed; +}; + +class GeometricModel : public Managed +{ +public: + using Managed::Managed; + + 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); +}; + +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); +}; + +class Spheres : public Geometry +{ +public: + static inline const std::string name = "sphere"; + + using Geometry::Geometry; + + void setPositions(SharedArray positions); + void setRadii(SharedArray radii); + void setRadius(float radius); +}; + +using PositionRadius = Vector4; + +enum class CurveType +{ + Flat = OSP_FLAT, + Round = OSP_ROUND, + Disjoint = OSP_DISJOINT, +}; + +enum class CurveBasis +{ + Linear = OSP_LINEAR, + Bezier = OSP_BEZIER, + Bspline = OSP_BSPLINE, +}; + +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); +}; + +class Boxes : public Geometry +{ +public: + static inline const std::string name = "box"; + + using Geometry::Geometry; + + void setBoxes(SharedArray boxes); +}; + +class Planes : public Geometry +{ +public: + static inline const std::string name = "plane"; + + using Geometry::Geometry; + + void setCoefficients(SharedArray coefficients); + void setBounds(SharedArray bounds); +}; + +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/rendering/GraphicsApi.cpp b/src/brayns/core/rendering/GraphicsApi.cpp new file mode 100644 index 000000000..c7e9a2d9a --- /dev/null +++ b/src/brayns/core/rendering/GraphicsApi.cpp @@ -0,0 +1,88 @@ +/* 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 "GraphicsApi.h" + +#include + +namespace brayns::experimental +{ +GraphicsApi::Loader::~Loader() +{ + ospShutdown(); +} + +GraphicsApi::GraphicsApi(std::unique_ptr loader): + _loader(std::move(loader)) +{ +} + +Device GraphicsApi::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); +} + +GraphicsApi loadGraphicsApi() +{ + 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 GraphicsApi(std::move(loader)); +} +} diff --git a/src/brayns/core/rendering/GraphicsApi.h b/src/brayns/core/rendering/GraphicsApi.h new file mode 100644 index 000000000..495f6d175 --- /dev/null +++ b/src/brayns/core/rendering/GraphicsApi.h @@ -0,0 +1,56 @@ +/* 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 GraphicsApi +{ +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 GraphicsApi(std::unique_ptr loader); + + Device createDevice(Logger &logger); + +private: + std::unique_ptr _loader; +}; + +GraphicsApi loadGraphicsApi(); +} diff --git a/src/brayns/core/rendering/Light.cpp b/src/brayns/core/rendering/Light.cpp new file mode 100644 index 000000000..c44150d32 --- /dev/null +++ b/src/brayns/core/rendering/Light.cpp @@ -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. + */ + +#include "Light.h" + +namespace brayns::experimental +{ +void Light::setColor(const Color3 &color) +{ + setParam("color", color); +} + +void Light::setIntensity(float intensity) +{ + setParam("intensity", intensity); +} + +void Light::setVisible(bool visible) +{ + setParam("visible", 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) +{ + setParam("penumbraAngle", degrees); +} + +void SpotLight::setOuterRadius(float radius) +{ + setParam("radius", radius); +} + +void SpotLight::setInnerRadius(float radius) +{ + setParam("innerRadius", radius); +} + +void QuadLight::setPosition(const Vector3 &position) +{ + setParam("position", position); +} + +void QuadLight::setEdge1(const Vector3 &edge) +{ + setParam("edge1", edge); +} + +void QuadLight::setEdge2(const Vector3 &edge) +{ + setParam("edge2", edge); +} +} diff --git a/src/brayns/core/rendering/Light.h b/src/brayns/core/rendering/Light.h new file mode 100644 index 000000000..9df0ded19 --- /dev/null +++ b/src/brayns/core/rendering/Light.h @@ -0,0 +1,104 @@ +/* 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 "Managed.h" + +namespace brayns::experimental +{ +class Light : public Managed +{ +public: + using Managed::Managed; + + void setColor(const Color3 &color); + void setIntensity(float intensity); + void setVisible(bool visible); +}; + +class DistantLight : public Light +{ +public: + static inline const std::string name = "distant"; + + using Light::Light; + + void setDirection(const Vector3 &direction); + void setAngularDiameter(float degrees); +}; + +class SphereLight : public Light +{ +public: + static inline const std::string name = "sphere"; + + using Light::Light; + + void setPosition(const Vector3 &position); + void setRadius(float radius); +}; + +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); +}; + +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); +}; + +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/rendering/Managed.h b/src/brayns/core/rendering/Managed.h new file mode 100644 index 000000000..4d0668f02 --- /dev/null +++ b/src/brayns/core/rendering/Managed.h @@ -0,0 +1,154 @@ +/* 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/rendering/Material.cpp b/src/brayns/core/rendering/Material.cpp new file mode 100644 index 000000000..28083fd3e --- /dev/null +++ b/src/brayns/core/rendering/Material.cpp @@ -0,0 +1,50 @@ +/* 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 "Material.h" + +namespace brayns::experimental +{ +void ObjMaterial::setDiffuseColor(const Color3 &color) +{ + setParam("kd", color); +} + +void ObjMaterial::setSpecularColor(const Color3 &color) +{ + setParam("ks", color); +} + +void ObjMaterial::setShininess(float exponent) +{ + setParam("ns", exponent); +} + +void ObjMaterial::setOpacity(float opacity) +{ + setParam("d", opacity); +} + +void ObjMaterial::setTransparencyFilter(const Color3 &color) +{ + setParam("tf", color); +} +} diff --git a/src/brayns/core/rendering/Material.h b/src/brayns/core/rendering/Material.h new file mode 100644 index 000000000..a2379788b --- /dev/null +++ b/src/brayns/core/rendering/Material.h @@ -0,0 +1,53 @@ +/* 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 "Managed.h" + +namespace brayns::experimental +{ +class Material : public Managed +{ +public: + using Managed::Managed; +}; + +class ObjMaterial : public Material +{ +public: + static inline const std::string name = "obj"; + + 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); +}; +} + +namespace ospray +{ +OSPTYPEFOR_SPECIALIZATION(brayns::experimental::Material, OSP_MATERIAL) +OSPTYPEFOR_SPECIALIZATION(brayns::experimental::ObjMaterial, OSP_MATERIAL) +} diff --git a/src/brayns/core/rendering/Render.cpp b/src/brayns/core/rendering/Render.cpp new file mode 100644 index 000000000..5cec1cdad --- /dev/null +++ b/src/brayns/core/rendering/Render.cpp @@ -0,0 +1,50 @@ +/* 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 "Render.h" + +namespace brayns::experimental +{ +bool RenderTask::isReady() const +{ + auto handle = getHandle(); + return ospIsReady(handle); +} + +float RenderTask::getProgress() const +{ + auto handle = getHandle(); + return ospGetProgress(handle); +} + +void RenderTask::cancel() +{ + auto handle = getHandle(); + ospCancel(handle); +} + +float RenderTask::waitAndGetDuration() +{ + auto handle = getHandle(); + ospWait(handle); + return ospGetTaskDuration(handle); +} +} diff --git a/src/brayns/core/rendering/Render.h b/src/brayns/core/rendering/Render.h new file mode 100644 index 000000000..f9024fdd5 --- /dev/null +++ b/src/brayns/core/rendering/Render.h @@ -0,0 +1,50 @@ +/* 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 "Camera.h" +#include "Framebuffer.h" +#include "Managed.h" +#include "Renderer.h" +#include "World.h" + +namespace brayns::experimental +{ +struct RenderSettings +{ + Framebuffer framebuffer; + Renderer renderer; + Camera camera; + World world; +}; + +class RenderTask : public Managed +{ +public: + using Managed::Managed; + + bool isReady() const; + float getProgress() const; + void cancel(); + float waitAndGetDuration(); +}; +} diff --git a/src/brayns/core/rendering/Renderer.cpp b/src/brayns/core/rendering/Renderer.cpp new file mode 100644 index 000000000..a702be389 --- /dev/null +++ b/src/brayns/core/rendering/Renderer.cpp @@ -0,0 +1,95 @@ +/* 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 "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) +{ + setParam("varianceThreshold", threshold); +} + +void Renderer::setBackgroundColor(const Color4 &color) +{ + setParam("backgroundColor", color); +} + +void Renderer::setMaterials(SharedArray materials) +{ + setParam("material", toSharedData(materials)); +} + +void Renderer::setPixelFilter(PixelFilter filter) +{ + setParam("pixelFilter", static_cast(filter)); +} + +void AmbientOcclusionRenderer::setAoSamples(std::size_t count) +{ + setParam("aoSamples", static_cast(count)); +} + +void AmbientOcclusionRenderer::setAoDistance(float distance) +{ + setParam("aoDistance", distance); +} + +void AmbientOcclusionRenderer::setAoIntensity(float intensity) +{ + setParam("aoIntensity", intensity); +} + +void ScivisRenderer::enableShadows(bool enable) +{ + setParam("shadows", enable); +} + +void ScivisRenderer::setAoSamples(std::size_t count) +{ + setParam("aoSamples", static_cast(count)); +} + +void ScivisRenderer::setAoDistance(float distance) +{ + setParam("aoDistance", distance); +} + +void ScivisRenderer::showLights(bool show) +{ + setParam("visibleLights", show); +} +} diff --git a/src/brayns/core/rendering/Renderer.h b/src/brayns/core/rendering/Renderer.h new file mode 100644 index 000000000..de4b38321 --- /dev/null +++ b/src/brayns/core/rendering/Renderer.h @@ -0,0 +1,93 @@ +/* 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 "Managed.h" +#include "Material.h" + +namespace brayns::experimental +{ +enum class PixelFilter +{ + Point = OSP_PIXELFILTER_POINT, + Box = OSP_PIXELFILTER_BOX, + Gauss = OSP_PIXELFILTER_GAUSS, + MitchellNetravali = OSP_PIXELFILTER_MITCHELL, + BlackmanHarris = OSP_PIXELFILTER_BLACKMAN_HARRIS, +}; + +class Renderer : public Managed +{ +public: + using Managed::Managed; + + 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); +}; + +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); +}; + +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); +}; + +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) +} diff --git a/src/brayns/core/rendering/Volume.cpp b/src/brayns/core/rendering/Volume.cpp new file mode 100644 index 000000000..5fd56d853 --- /dev/null +++ b/src/brayns/core/rendering/Volume.cpp @@ -0,0 +1,83 @@ +/* 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 "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) +{ + setParam("transferFunction", function.getHandle()); +} + +void VolumetricModel::setId(std::uint32_t id) +{ + setParam("id", id); +} + +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) +{ + auto cellCentered = structure == VolumeStructure::CellCentered; + setParam("cellCentered", cellCentered); +} + +void StructuredRegularVolume::setOrigin(const Vector3 &origin) +{ + setParam("gridOrigin", origin); +} + +void StructuredRegularVolume::setSpacing(const Vector3 &spacing) +{ + setParam("gridSpacing", spacing); +} + +void StructuredRegularVolume::setFilter(VolumeFilter filter) +{ + setParam("filter", static_cast(filter)); +} +} diff --git a/src/brayns/core/rendering/Volume.h b/src/brayns/core/rendering/Volume.h new file mode 100644 index 000000000..4b4e0b8fe --- /dev/null +++ b/src/brayns/core/rendering/Volume.h @@ -0,0 +1,115 @@ +/* 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 "Managed.h" + +namespace brayns::experimental +{ +class TransferFunction : public Managed +{ +public: + using Managed::Managed; +}; + +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 Managed +{ +public: + using Managed::Managed; +}; + +class VolumetricModel : public Managed +{ +public: + using Managed::Managed; + + void setVolume(const Volume &volume); + void setTransferFunction(const TransferFunction &function); + void setId(std::uint32_t id); +}; + +enum class VoxelDataType +{ + UChar = OSP_UCHAR, + Short = OSP_SHORT, + UShort = OSP_USHORT, + Half = OSP_HALF, + Float = OSP_FLOAT, + 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, + Linear = OSP_VOLUME_FILTER_LINEAR, + Cubic = OSP_VOLUME_FILTER_CUBIC, +}; + +class StructuredRegularVolume : public Volume +{ +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); +}; +} + +namespace ospray +{ +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) +} diff --git a/src/brayns/core/rendering/World.cpp b/src/brayns/core/rendering/World.cpp new file mode 100644 index 000000000..62056fdfa --- /dev/null +++ b/src/brayns/core/rendering/World.cpp @@ -0,0 +1,65 @@ +/* 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 "World.h" + +namespace brayns::experimental +{ +void Group::setVolumes(SharedArray models) +{ + setParam("volume", toSharedData(models)); +} + +void Group::setGeometries(SharedArray models) +{ + setParam("geometry", toSharedData(models)); +} + +void Group::setClippingGeometries(SharedArray models) +{ + setParam("clippingGeometry", toSharedData(models)); +} + +void Group::setLights(SharedArray lights) +{ + setParam("light", toSharedData(lights)); +} + +void Instance::setGroup(const Group &group) +{ + setParam("group", group.getHandle()); +} + +void Instance::setTransform(const Affine3 &transform) +{ + setParam("transform", transform); +} + +void Instance::setId(std::uint32_t id) +{ + setParam("id", id); +} + +void World::setInstances(SharedArray instances) +{ + setParam("instance", toSharedData(instances)); +} +} diff --git a/src/brayns/core/rendering/World.h b/src/brayns/core/rendering/World.h new file mode 100644 index 000000000..fc6a12e14 --- /dev/null +++ b/src/brayns/core/rendering/World.h @@ -0,0 +1,70 @@ +/* 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 "Geometry.h" +#include "Light.h" +#include "Managed.h" +#include "Volume.h" + +namespace brayns::experimental +{ +class Group : public Managed +{ +public: + using Managed::getBounds; + using Managed::Managed; + + void setVolumes(SharedArray models); + void setGeometries(SharedArray models); + void setClippingGeometries(SharedArray models); + void setLights(SharedArray lights); +}; + +class Instance : public Managed +{ +public: + using Managed::getBounds; + using Managed::Managed; + + void setGroup(const Group &group); + void setTransform(const Affine3 &transform); + void setId(std::uint32_t id); +}; + +class World : public Managed +{ +public: + using Managed::getBounds; + using Managed::Managed; + + void setInstances(SharedArray instances); +}; +} + +namespace ospray +{ +OSPTYPEFOR_SPECIALIZATION(brayns::experimental::Group, OSP_GROUP) +OSPTYPEFOR_SPECIALIZATION(brayns::experimental::Instance, OSP_INSTANCE) +OSPTYPEFOR_SPECIALIZATION(brayns::experimental::World, OSP_WORLD) +} diff --git a/src/brayns/core/utils/Log.cpp b/src/brayns/core/utils/Log.cpp index 794074cff..b57623ebb 100644 --- a/src/brayns/core/utils/Log.cpp +++ b/src/brayns/core/utils/Log.cpp @@ -23,25 +23,22 @@ #include -namespace brayns +namespace { -EnumMap EnumReflector::reflect() +using namespace brayns; + +Logger consoleLogger() { - return { - {"trace", LogLevel::Trace}, - {"debug", LogLevel::Debug}, - {"info", LogLevel::Info}, - {"warn", LogLevel::Warn}, - {"warning", LogLevel::Warn}, - {"error", LogLevel::Error}, - {"critical", LogLevel::Critical}, - {"off", LogLevel::Off}, - }; + auto handler = [](const auto &record) { std::cout << toString(record) << '\n'; }; + return Logger("Brayns", LogLevel::Info, handler); +} } +namespace brayns +{ void Log::setLevel(LogLevel level) { - _level = level; + _logger.setLevel(level); } void Log::disable() @@ -49,10 +46,5 @@ void Log::disable() setLevel(LogLevel::Off); } -void Log::_handleMessage(LogLevel level, std::string_view message) -{ - auto &levelName = EnumInfo::getName(level); - auto record = fmt::format("[Brayns][{}] {}", levelName, message); - std::cout << record << '\n'; -} +Logger Log::_logger = consoleLogger(); } // namespace brayns diff --git a/src/brayns/core/utils/Log.h b/src/brayns/core/utils/Log.h index 0d6640fe8..53eb5757e 100644 --- a/src/brayns/core/utils/Log.h +++ b/src/brayns/core/utils/Log.h @@ -21,37 +21,12 @@ #pragma once -#include -#include - #include -#include +#include "Logger.h" namespace brayns { -/** - * @brief Available log levels. - * - */ -enum class LogLevel -{ - Trace, - Debug, - Info, - Warn, - Error, - Critical, - Off, - Count, -}; - -template<> -struct EnumReflector -{ - static EnumMap reflect(); -}; - class Log { public: @@ -79,12 +54,7 @@ class Log template static void log(LogLevel level, fmt::format_string format, Args &&...args) { - if (level < _level) - { - return; - } - auto message = fmt::format(format, std::forward(args)...); - _handleMessage(level, message); + _logger.log(level, format, std::forward(args)...); } /** @@ -153,21 +123,19 @@ class Log } /** - * @brief Log the given message with optional arguments and critical level. + * @brief Log the given message with optional arguments and fatal level. * * @tparam Args Arguments types. * @param format Message format. * @param args Arguments to format. */ template - static void critical(fmt::format_string format, Args &&...args) + static void fatal(fmt::format_string format, Args &&...args) { - log(LogLevel::Critical, format, std::forward(args)...); + log(LogLevel::Fatal, format, std::forward(args)...); } private: - static inline LogLevel _level = LogLevel::Info; - - static void _handleMessage(LogLevel level, std::string_view message); + static Logger _logger; }; } // namespace brayns diff --git a/src/brayns/core/utils/Logger.cpp b/src/brayns/core/utils/Logger.cpp new file mode 100644 index 000000000..e38bf2fc3 --- /dev/null +++ b/src/brayns/core/utils/Logger.cpp @@ -0,0 +1,74 @@ +/* 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 "Logger.h" + +#include + +namespace brayns +{ +EnumMap EnumReflector::reflect() +{ + return { + {"trace", LogLevel::Trace}, + {"debug", LogLevel::Debug}, + {"info", LogLevel::Info}, + {"warn", LogLevel::Warn}, + {"warning", LogLevel::Warn}, + {"error", LogLevel::Error}, + {"fatal", LogLevel::Fatal}, + {"off", LogLevel::Off}, + }; +} + +std::string toString(const LogRecord &record) +{ + auto level = EnumInfo::getName(record.level); + return fmt::format("[{}][{}]: {}", record.name, level, record.message); +} + +Logger::Logger(std::string name, LogLevel level, LogHandler handler): + _name(std::move(name)), + _level(level), + _handler(std::move(handler)) +{ +} + +const std::string &Logger::getName() const +{ + return _name; +} + +LogLevel Logger::getLevel() const +{ + return _level; +} + +void Logger::setLevel(LogLevel level) +{ + _level = level; +} + +bool Logger::isEnabled(LogLevel level) const +{ + return level >= _level; +} +} diff --git a/src/brayns/core/utils/Logger.h b/src/brayns/core/utils/Logger.h new file mode 100644 index 000000000..d86c712e5 --- /dev/null +++ b/src/brayns/core/utils/Logger.h @@ -0,0 +1,125 @@ +/* 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 +{ +enum class LogLevel +{ + Trace, + Debug, + Info, + Warn, + Error, + Fatal, + Off, +}; + +template<> +struct EnumReflector +{ + static EnumMap reflect(); +}; + +struct LogRecord +{ + std::string_view name; + LogLevel level = LogLevel::Info; + std::string_view message; +}; + +std::string toString(const LogRecord &record); + +using LogHandler = std::function; + +class Logger +{ +public: + explicit Logger(std::string name, LogLevel level, LogHandler handler); + + const std::string &getName() const; + LogLevel getLevel() const; + void setLevel(LogLevel level); + bool isEnabled(LogLevel level) const; + + template + void log(LogLevel level, fmt::format_string format, Args &&...args) + { + if (!isEnabled(level)) + { + return; + } + auto message = fmt::format(format, std::forward(args)...); + auto record = LogRecord(_name, _level, message); + _handler(record); + } + + template + void trace(fmt::format_string format, Args &&...args) + { + log(LogLevel::Trace, format, std::forward(args)...); + } + + template + void debug(fmt::format_string format, Args &&...args) + { + log(LogLevel::Debug, format, std::forward(args)...); + } + + template + void info(fmt::format_string format, Args &&...args) + { + log(LogLevel::Info, format, std::forward(args)...); + } + + template + void warn(fmt::format_string format, Args &&...args) + { + log(LogLevel::Warn, format, std::forward(args)...); + } + + template + void error(fmt::format_string format, Args &&...args) + { + log(LogLevel::Error, format, std::forward(args)...); + } + + template + void fatal(fmt::format_string format, Args &&...args) + { + log(LogLevel::Fatal, format, std::forward(args)...); + } + +private: + std::string _name; + LogLevel _level; + LogHandler _handler; +}; +} diff --git a/src/brayns/core/utils/Math.h b/src/brayns/core/utils/Math.h new file mode 100644 index 000000000..208d04b29 --- /dev/null +++ b/src/brayns/core/utils/Math.h @@ -0,0 +1,67 @@ +/* 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 + +#define RKCOMMON_NO_SIMD +#include +#include +#include + +namespace brayns +{ +using Index3 = rkcommon::math::vec3ui; +using Index4 = rkcommon::math::vec4ui; + +using Size3 = rkcommon::math::vec3ul; + +using Vector2 = rkcommon::math::vec2f; +using Vector3 = rkcommon::math::vec3f; +using Vector4 = rkcommon::math::vec4f; + +using Box1 = rkcommon::math::box1f; +using Box2 = rkcommon::math::box2f; +using Box3 = rkcommon::math::box3f; + +using Color3 = Vector3; +using Color4 = Vector4; + +using Quaternion = rkcommon::math::quaternionf; + +using Affine3 = rkcommon::math::AffineSpace3f; + +struct Transform +{ + Vector3 translation = {0, 0, 0}; + Quaternion rotation = {1, 0, 0, 0}; + Vector3 scale = {1, 1, 1}; + + auto operator<=>(const Transform &other) const = default; +}; + +inline Affine3 toAffine(const Transform &transform) +{ + auto &translation = transform.translation; + auto rotation = rkcommon::math::LinearSpace3f(transform.rotation); + auto scale = rkcommon::math::LinearSpace3f::scale(transform.scale); + return Affine3(rotation * scale, translation); +} +} diff --git a/src/brayns/core/utils/MathTypes.h b/src/brayns/core/utils/MathTypes.h index 904d8107a..8062ade9f 100644 --- a/src/brayns/core/utils/MathTypes.h +++ b/src/brayns/core/utils/MathTypes.h @@ -20,15 +20,10 @@ #pragma once -// Rkcommon simd math code has big precission issues -// And previous math lib (glm) was being used without simd anyway -#define RKCOMMON_NO_SIMD -#include -#include -#include - #include +#include "Math.h" + namespace brayns { namespace math = rkcommon::math; @@ -36,25 +31,21 @@ namespace math = rkcommon::math; /** * Vector definitions */ +using Vector2ui = math::vec2ui; using Vector2i = math::vec2i; using Vector2l = math::vec2l; + +using Vector3ui = math::vec3ui; using Vector3i = math::vec3i; using Vector3l = math::vec3l; -using Vector2ui = math::vec2ui; using Vector2ul = math::vec2ul; -using Vector3ui = math::vec3ui; using Vector3ul = math::vec3ul; using Vector2f = math::vec2f; using Vector3f = math::vec3f; using Vector4f = math::vec4f; -/** - * Quaternion definitions - */ -using Quaternion = math::quaternionf; - /** * AABB definitions */ @@ -68,6 +59,11 @@ class TransformMatrix public: TransformMatrix() = default; + TransformMatrix(const math::AffineSpace3f &value): + affine(value) + { + } + TransformMatrix(const Vector3f &translation, const Quaternion &rotation, const Vector3f &scale): affine(math::LinearSpace3f(rotation) * math::LinearSpace3f::scale(scale), translation) { diff --git a/tests/core/engine/TestGeometry.cpp b/tests/core/engine/TestGeometry.cpp index 4091adb58..347cc0b5d 100644 --- a/tests/core/engine/TestGeometry.cpp +++ b/tests/core/engine/TestGeometry.cpp @@ -83,8 +83,10 @@ TEST_CASE("Geometry") CHECK(min == brayns::Vector3f(-10.f)); CHECK(max == brayns::Vector3f(10.f)); - auto transform = brayns::Transform{.translation = brayns::Vector3f(100.f, 0.f, 0.f)}.toMatrix(); - bounds = geometry.computeBounds(transform); + auto transform = brayns::Transform{.translation = brayns::Vector3f(100.f, 0.f, 0.f)}; + auto matrix = brayns::toAffine(transform); + + bounds = geometry.computeBounds(matrix); min = bounds.getMin(); max = bounds.getMax(); CHECK(min == brayns::Vector3f(90.f, -10.f, -10.f)); diff --git a/tests/core/engine/TestLight.cpp b/tests/core/engine/TestLight.cpp index 006011a25..90dd60a7b 100644 --- a/tests/core/engine/TestLight.cpp +++ b/tests/core/engine/TestLight.cpp @@ -41,7 +41,8 @@ TEST_CASE("Light bounds") BRAYNS_TESTS_PLACEHOLDER_ENGINE auto noTransform = brayns::TransformMatrix(); - auto transform = brayns::Transform{.translation = brayns::Vector3f(100.f, 0.f, 0.f)}.toMatrix(); + auto transform = brayns::Transform{.translation = brayns::Vector3f(100.f, 0.f, 0.f)}; + auto matrix = brayns::toAffine(transform); auto emptyBounds = brayns::Bounds(); @@ -51,7 +52,7 @@ TEST_CASE("Light bounds") auto ambientBounds = ambientLight.computeBounds(noTransform); CHECK(ambientBounds.getMax() == emptyBounds.getMax()); CHECK(ambientBounds.getMin() == emptyBounds.getMin()); - ambientBounds = ambientLight.computeBounds(transform); + ambientBounds = ambientLight.computeBounds(matrix); CHECK(ambientBounds.getMax() == emptyBounds.getMax()); CHECK(ambientBounds.getMin() == emptyBounds.getMin()); } @@ -61,7 +62,7 @@ TEST_CASE("Light bounds") auto directionalBounds = directionalLight.computeBounds(noTransform); CHECK(directionalBounds.getMax() == emptyBounds.getMax()); CHECK(directionalBounds.getMin() == emptyBounds.getMin()); - directionalBounds = directionalLight.computeBounds(transform); + directionalBounds = directionalLight.computeBounds(matrix); CHECK(directionalBounds.getMax() == emptyBounds.getMax()); CHECK(directionalBounds.getMin() == emptyBounds.getMin()); } @@ -71,7 +72,7 @@ TEST_CASE("Light bounds") auto quadBounds = quadLight.computeBounds(noTransform); CHECK(quadBounds.getMin() == brayns::Vector3f(0.f)); CHECK(quadBounds.getMax() == brayns::Vector3f(1.f, 0.f, 1.f)); - quadBounds = quadLight.computeBounds(transform); + quadBounds = quadLight.computeBounds(matrix); CHECK(quadBounds.getMin() == brayns::Vector3f(100.f, 0.f, 0.f)); CHECK(quadBounds.getMax() == brayns::Vector3f(101.f, 0.f, 1.f)); } diff --git a/tests/core/engine/TestSystems.cpp b/tests/core/engine/TestSystems.cpp index 3fbcda886..5b478ca65 100644 --- a/tests/core/engine/TestSystems.cpp +++ b/tests/core/engine/TestSystems.cpp @@ -105,7 +105,8 @@ TEST_CASE("Systems") auto systems = brayns::Systems(); systems.setBoundsSystem(); auto view = brayns::SystemsView(systems, components); - auto matrix = brayns::Transform{.translation = brayns::Vector3f(0.f, 0.f, 100.f)}.toMatrix(); + auto transform = brayns::Transform{.translation = brayns::Vector3f(0.f, 0.f, 100.f)}; + auto matrix = brayns::toAffine(transform); CHECK(!components.has()); diff --git a/tests/core/engine/TestVolume.cpp b/tests/core/engine/TestVolume.cpp index 87e3df027..71be9ce57 100644 --- a/tests/core/engine/TestVolume.cpp +++ b/tests/core/engine/TestVolume.cpp @@ -68,8 +68,9 @@ TEST_CASE("Volume") CHECK(min == brayns::Vector3f(0.f)); CHECK(max == brayns::Vector3f(5.f)); - auto transform = brayns::Transform{.translation = brayns::Vector3f(100.f, 0.f, 0.f)}.toMatrix(); - bounds = volume.computeBounds(transform); + auto transform = brayns::Transform{.translation = brayns::Vector3f(100.f, 0.f, 0.f)}; + auto matrix = brayns::toAffine(transform); + bounds = volume.computeBounds(matrix); min = bounds.getMin(); max = bounds.getMax(); CHECK(min == brayns::Vector3f(100.f, 0.f, 0.f)); diff --git a/tests/core/rendering/TestRender.cpp b/tests/core/rendering/TestRender.cpp new file mode 100644 index 000000000..fe031307e --- /dev/null +++ b/tests/core/rendering/TestRender.cpp @@ -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. + */ + +#include + +#include + +#include + +#include + +using namespace brayns; +using namespace brayns::experimental; + +TEST_CASE("Render") +{ + auto error = std::string(); + + auto level = LogLevel::Error; + auto handler = [&](const auto &record) { error = record.message; }; + auto logger = Logger("Test", level, handler); + + auto api = loadGraphicsApi(); + + auto device = api.createDevice(logger); + + auto width = 480; + auto height = 360; + + auto toneMapper = device.createImageOperation(); + toneMapper.commit(); + + auto imageOperations = std::vector{toneMapper}; + + auto framebuffer = device.createFramebuffer({ + .width = std::size_t(width), + .height = std::size_t(height), + .format = FramebufferFormat::Srgba8, + .channels = {FramebufferChannel::Color}, + }); + 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 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 camera = device.createCamera(); + camera.setAspectRatio(float(width) / float(height)); + camera.setFovy(45); + camera.setTransform(toAffine({.translation = {0, 0, -1}})); + camera.setNearClip(0); + camera.commit(); + + auto positions = std::vector{{0, 0, 3}, {1, 0, 3}, {1, 1, 3}}; + auto radii = std::vector{0.25F, 0.25F, 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 model = device.createGeometricModel(); + model.setGeometry(spheres); + model.setPrimitiveColors(colors); + model.setMaterial(0); + model.setId(0); + model.commit(); + + auto models = std::vector{model}; + + auto light = device.createLight(); + light.setIntensity(1); + light.setColor({1, 1, 1}); + light.setVisible(true); + light.commit(); + + auto lights = std::vector{light}; + + auto group = device.createGroup(); + group.setGeometries(models); + group.setLights(lights); + group.commit(); + + auto instance = device.createInstance(); + instance.setGroup(group); + instance.setTransform(toAffine({})); + instance.setId(0); + instance.commit(); + + auto instances = std::vector{instance}; + + auto world = device.createWorld(); + world.setInstances(instances); + world.commit(); + + CHECK_EQ(world.getBounds(), instance.getBounds()); + CHECK_EQ(world.getBounds(), group.getBounds()); + + auto task = device.render({ + .framebuffer = framebuffer, + .renderer = renderer, + .camera = camera, + .world = world, + }); + auto duration = task.waitAndGetDuration(); + + CHECK(duration > 0); + CHECK(task.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); + + framebuffer.unmap(data); + + CHECK(error.empty()); +}