diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index a9d37e70..1e19898a 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -3,11 +3,11 @@
variables:
GIT_SUBMODULE_STRATEGY: recursive
- OSPRAY_VER: "2.7.1"
- RKCOMMON_VER: "1.7.0"
- PYTHON_VERSION: "3.7.10"
- PYTHON_ROOT_MACOS: "/NAS/packages/apps/python/$PYTHON_VERSION/macos"
- PYTHON_ROOT_WINDOWS: "N:/packages/apps/python/3.7.9/windows" ## python-3.7.10 currently not installed for windows
+ OSPRAY_VER: "2.8.0"
+ RKCOMMON_VER: "1.8.0"
+ PYTHON_VERSION: "3.9.7"
+ # PYTHON_ROOT_MACOS: "/NAS/packages/apps/python/$PYTHON_VERSION/macos"
+ PYTHON_ROOT_WINDOWS: "N:/packages/apps/python/$PYTHON_VERSION/windows"
stages:
- build
@@ -17,7 +17,7 @@ stages:
.centos7:
tags: [ build, docker, modules ]
- image: $DOCKER_REGISTRY/general:centos7-devel
+ image: $DOCKER_REGISTRY/centos:7
before_script:
- module load python/$PYTHON_VERSION
- echo $Python3_ROOT
@@ -25,14 +25,11 @@ stages:
.ubuntu18.04:
tags: [ build, docker, modules ]
- image: $DOCKER_REGISTRY/ospray/docker-images:ubuntu18.04-mod
+ image: $DOCKER_REGISTRY/ubuntu:18.04
before_script:
- - apt install -y xorg-dev
- # image: $DOCKER_REGISTRY/general:ubuntu18.04-devel
- # before_script:
- # - module load python/$PYTHON_VERSION
- # - echo $Python3_ROOT
- # - ls $Python3_ROOT
+ - module load python/$PYTHON_VERSION
+ - echo $Python3_ROOT
+ - ls $Python3_ROOT
.ubuntu20.04:
tags: [ build, docker ]
@@ -40,17 +37,9 @@ stages:
.macos:
tags: [ osx, clang ]
- before_script:
- - export Python3_ROOT=$PYTHON_ROOT_MACOS
- - echo $Python3_ROOT
- - ls $Python3_ROOT
.macos-sign:
tags: [ osx, clang, sign ]
- before_script:
- - export Python3_ROOT=$PYTHON_ROOT_MACOS
- - echo $Python3_ROOT
- - ls $Python3_ROOT
.windows:
tags: [ win, msvc15 ]
@@ -114,9 +103,6 @@ build-centos7:
- .centos7
- .linux-build-artifacts
script:
- - source $SPACK_SETUP_ENV
- - module load cmake/3.15.2
- - module load gcc/5.4.0
- module load intel/2020.1
- export CC=icc
- export CXX=icpc
@@ -274,9 +260,6 @@ release-centos7:
- .linux-release-artifacts
needs: [ test-run-centos7 ]
script:
- - source $SPACK_SETUP_ENV
- - module load cmake/3.15.2
- - module load gcc/5.4.0
- module load intel/2020.1
- export CC=icc
- export CXX=icpc
@@ -304,6 +287,7 @@ release-macos:
- master
- /^release-.*$/
- devel
+ - web
scan-bdba-bin:
stage: scan
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6e83070c..10bd52bb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,30 @@
Version History
---------------
+### Changes in OSPRay Studio v0.9.0
+
+- Compatible with OSPRay release v2.8.0
+
+- Features and Improvements
+ - Added initial EULUMDAT photometric light support to SpotLight
+ - Enabled alternate camera selection in glTF scenes
+ - Added ability for python scripts to define transfer functions and load Studio plugins
+ - Enabled .sg scene files can now contain an HDRI light
+ - Much improved command line parsing in all modes
+ - Added support for several new KHR_materials extentions
+ (`KHR_materials_volume`, `KHR_materials_specular`, `KHR_materials_ior`)
+ and `KHR_texture_transform`
+ - Improved UI controls for adjusting model transforms
+
+
+- Bug Fixes:
+ - Fixed high-DPI display issues
+ - Fixed bug causing model textures to be flipped if loading HDRI first
+ - Fixed crash when selecting non-default cameras in glTF scenes
+ - Fixed bug with macOS ARM build.
+ - Fixed `KHR_lights_punctual` light direction bug
+
+
### Changes in OSPRay Studio v0.8.1
- Compatible with OSPRay release v2.7.1
@@ -26,6 +50,7 @@ Version History
- Updated external 3rd party dependencies bringing in features and bug fixes
- Modified OBJ importer to parse and use quads and triangles
- Improved Arcball camera navigation with up-vector lock
+
- Bug Fixes
- Fixed materials after clearing scene
@@ -33,7 +58,7 @@ Version History
- Can no longer create a zero-dimension framebuffer
- Fixed instancing node-naming to allow for for many identical instances
- Fixed crash if optional glTF punctual light color was omitted
- - Fixed crash if isosuface geometry is used as clipping geometry when no other
+ - Fixed crash if isosurface geometry is used as clipping geometry when no other
geometries are in the scene
### Changes in OSPRay Studio v0.7.0
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 821c4403..c6d0adcf 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,7 +3,7 @@
cmake_minimum_required(VERSION 3.15)
-project(ospray_studio VERSION 0.8.1 LANGUAGES CXX)
+project(ospray_studio VERSION 0.9.0 LANGUAGES CXX)
include(GNUInstallDirs)
include(ProcessorCount)
diff --git a/README.md b/README.md
index 55b2a0e9..a6840d06 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,10 @@
# OSPRay Studio
-This is release v0.8.1 of Intel® OSPRay Studio. It is released under the
+This is release v0.9.0 of Intel® OSPRay Studio. It is released under the
Apache 2.0 license.
-Visit http://www.ospray.org/ospray_studio for more information.
+Visit [**OSPRay Studio**](http://www.ospray.org/ospray_studio)
+(http://www.ospray.org/ospray_studio) for more information.
See [what's
new](https://github.com/ospray/ospray_studio/blob/master/CHANGELOG.md)
@@ -12,10 +13,9 @@ in this release.
## Overview
Intel OSPRay Studio is an open source and interactive visualization and
-ray tracing application that leverages [Intel
-OSPRay](https://www.ospray.org) as its core rendering engine. It can be
-used to load complex scenes requiring high fidelity rendering or very
-large scenes requiring supercomputing resources.
+ray tracing application that leverages [Intel OSPRay](https://www.ospray.org)
+as its core rendering engine. It can be used to load complex scenes requiring
+high fidelity rendering or very large scenes requiring supercomputing resources.
The main control structure is a *scene graph* which allows users to
create an abstract scene in a *directed acyclical graph* manner. Scenes
@@ -30,27 +30,26 @@ OSPRay Studio has the following required and optional dependencies.
### Required dependencies
- [CMake](https://www.cmake.org) (v3.15+) and any C++14 compiler
-- Intel [OSPRay](https://www.github.com/ospray/ospray) (v2.7.1) and
+- Intel [OSPRay](https://www.github.com/ospray/ospray) (v2.8.0) and
its dependencies - OSPRay Studio builds on top of OSPRay.
Instructions on building OSPRay are provided
- [here](http://www.ospray.org/downloads.html#building-and-finding-ospray)
- - Intel [Open VKL](https://www.github.com/openvkl/openvkl) (v1.0.1)
+ [here](http://www.ospray.org/downloads.html#building-and-finding-ospray).
+ - Intel [Open VKL](https://www.github.com/openvkl/openvkl) (v1.0.1 or newer)
- Intel [Embree](https://www.github.com/embree/embree) (v3.13.1 or newer)
- Intel oneAPI Rendering Toolkit common library
- [rkcommon](https://www.github.com/ospray/rkcommon) (v1.7.0)
- - Intel [Threading Building
- Blocks](https://www.threadingbuildingblocks.org/)
-- OpenGL and [GLFW](https://www.glfw.org/) (v3.x) - for the windowing
- environment
+ [rkcommon](https://www.github.com/ospray/rkcommon) (v1.8.0)
+ - Intel [Threading Building Blocks](https://www.threadingbuildingblocks.org/)
+- OpenGL and [GLFW](https://www.glfw.org) (v3.3.4) - for the windowing environment
### Optional Dependencies
-- Intel [Open Image Denoise](https://openimagedenoise.github.io/) - (v1.2.3 or
+- Intel [Open Image Denoise](https://openimagedenoise.github.io) - (v1.2.3 or
newer) for denoising frames. To use with OSPRay Studio, OSPRay must be built
- with `-DBUILD_OIDN=ON` in CMake
-- [OpenImageIO]() and [OpenEXR]() - to support images in a variety of
- file formats. Set `OPENIMAGEIO_ROOT` and `OPENEXR_ROOT` to the
- respective install directories to use these libraries
+ with `-DBUILD_OIDN=ON` in CMake.
+- [OpenImageIO](http://openimageio.org/) and [OpenEXR](https://www.openexr.com/)
+ to support images in a variety of file formats. Set `OPENIMAGEIO_ROOT`
+ and `OPENEXR_ROOT` to the respective install directories to use these libraries.
+- [Python] (3.9.7) (https://python.org) for python bindings
### Building on Linux and macOS
@@ -66,6 +65,9 @@ OSPRay Studio has the following required and optional dependencies.
export rkcommon_DIR = ${RKCOMMON_INSTALL_LOCATION}
```
+ Alternatively, [CMAKE_PREFIX_PATH](https://cmake.org/cmake/help/latest/variable/CMAKE_PREFIX_PATH.html)
+ can be set to find the OSPRay install and other dependencies.
+
- Clone OSPRay Studio
``` bash
diff --git a/app/Batch.cpp b/app/Batch.cpp
index df2220a1..04ddaca1 100644
--- a/app/Batch.cpp
+++ b/app/Batch.cpp
@@ -16,6 +16,9 @@
#include "sg/JSONDefs.h"
#include "PluginManager.h"
+// CLI
+#include
+
static bool resetFileId = false;
BatchContext::BatchContext(StudioCommon &_common)
@@ -42,7 +45,7 @@ void BatchContext::start()
bool useCamera = refreshCamera(cameraDef);
if (useCamera) {
render();
- if (animate) {
+ if (fps) {
std::cout << "..rendering animation!" << std::endl;
renderAnimation();
} else if (!cameraStack.empty()) {
@@ -62,7 +65,7 @@ void BatchContext::start()
bool useCamera = refreshCamera(cameraIdx, true);
if (useCamera) {
render();
- if (animate) {
+ if (fps) {
std::cout << "..rendering animation!" << std::endl;
renderAnimation();
} else
@@ -76,220 +79,160 @@ void BatchContext::start()
}
}
-bool BatchContext::parseCommandLine()
-{
- int argc = studioCommon.argc;
- const char **argv = studioCommon.argv;
- int argIndex = 1;
-
- volumeParams = std::make_shared();
-
- auto argAvailability = [&](std::string switchArg, int nComp) {
- if (argc >= argIndex + nComp)
+void BatchContext::addToCommandLine(std::shared_ptr app) {
+ app->add_option(
+ "--cameraType",
+ optCameraTypeStr,
+ "Set the camera type"
+ )->check(CLI::IsMember({"perspective", "orthographic", "panoramic"}));
+ app->add_option(
+ "--position",
+ [&](const std::vector val) {
+ pos = vec3f(std::stof(val[0]), std::stof(val[1]), std::stof(val[2]));
+ cmdlCam = true;
return true;
- std::cout << "Missing argument value for : " << switchArg << std::endl;
- return false;
- };
-
- while (argIndex < argc) {
- std::string switchArg(argv[argIndex++]);
-
- if (switchArg == "--help") {
- printHelp();
- return 0;
- } else if (switchArg == "-r" || switchArg == "--renderer") {
- if (argAvailability(switchArg, 1))
- optRendererTypeStr = argv[argIndex++];
-
- } else if (switchArg == "-c" || switchArg == "--camera") {
- if (argAvailability(switchArg, 1))
- optCameraTypeStr = argv[argIndex++];
-
- } else if (switchArg == "-vp") {
- if (argAvailability(switchArg, 3)) {
- vec3f posVec;
- posVec.x = atof(argv[argIndex++]);
- posVec.y = atof(argv[argIndex++]);
- posVec.z = atof(argv[argIndex++]);
- pos = posVec;
- cmdlCam = true;
- }
-
- } else if (switchArg == "-vu") {
- if (argAvailability(switchArg, 3)) {
- vec3f upVec;
- upVec.x = atof(argv[argIndex++]);
- upVec.y = atof(argv[argIndex++]);
- upVec.z = atof(argv[argIndex++]);
- up = upVec;
- cmdlCam = true;
- }
-
- } else if (switchArg == "-f" || switchArg == "--format") {
- if (argAvailability(switchArg, 1))
- optImageFormat = argv[argIndex++];
-
- } else if (switchArg == "-i" || switchArg == "--image") {
- if (argAvailability(switchArg, 1))
- optImageName = argv[argIndex++];
-
- } else if (switchArg == "-vi") {
- if (argAvailability(switchArg, 3)) {
- vec3f gazeVec;
- gazeVec.x = atof(argv[argIndex++]);
- gazeVec.y = atof(argv[argIndex++]);
- gazeVec.z = atof(argv[argIndex++]);
- gaze = gazeVec;
- cmdlCam = true;
- }
-
- } else if (switchArg == "-id" || switchArg == "--interpupillaryDistance") {
- if (argAvailability(switchArg, 1))
- optInterpupillaryDistance = max(0.0, atof(argv[argIndex++]));
-
- } else if (switchArg == "-sm" || switchArg == "--stereoMode") {
- if (argAvailability(switchArg, 1))
- optStereoMode = max(0, atoi(argv[argIndex++]));
-
- } else if (switchArg == "-s" || switchArg == "--size") {
- if (argAvailability(switchArg, 2)) {
- auto x = max(0, atoi(argv[argIndex++]));
- auto y = max(0, atoi(argv[argIndex++]));
- optImageSize = vec2i(x, y);
- }
-
- } else if (switchArg == "-spp" || switchArg == "--samples") {
- if (argAvailability(switchArg, 1))
- optSPP = max(1, atoi(argv[argIndex++]));
-
- } else if (switchArg == "-vt" || switchArg == "--variance") {
- if (argAvailability(switchArg, 1))
- optVariance = max(0.0, atof(argv[argIndex++]));
-
- } else if (switchArg == "-pf" || switchArg == "--pixelfilter") {
- if (argAvailability(switchArg, 1))
- optPF = max(0, atoi(argv[argIndex++]));
-
- } else if (switchArg == "-oidn" || switchArg == "--denoiser") {
+ },
+ "Set the camera position"
+ )->expected(3);
+ app->add_option(
+ "--view",
+ [&](const std::vector val) {
+ gaze = vec3f(std::stof(val[0]), std::stof(val[1]), std::stof(val[2]));
+ cmdlCam = true;
+ return true;
+ },
+ "Set the camera view vector"
+ )->expected(3);
+ app->add_option(
+ "--up",
+ [&](const std::vector val) {
+ up = vec3f(std::stof(val[0]), std::stof(val[1]), std::stof(val[2]));
+ cmdlCam = true;
+ return true;
+ },
+ "Set the camera up vector"
+ );
+ app->add_option(
+ "--format",
+ optImageFormat,
+ "Set the image format"
+ )->check(CLI::IsMember({"png", "jpg", "ppm", "pfm", "exr", "hdr"}));
+ app->add_option(
+ "--image",
+ optImageName,
+ "Set the image name"
+ );
+ app->add_option(
+ "--interpupillaryDistance",
+ optInterpupillaryDistance,
+ "Set the interpupillary distance"
+ )->check(CLI::PositiveNumber);
+ app->add_option(
+ "--stereoMode",
+ optStereoMode,
+ "Set the stereo mode"
+ )->check(CLI::PositiveNumber);
+ app->add_option(
+ "--size",
+ [&](const std::vector val) {
+ optImageSize = vec2i(std::stoi(val[0]), std::stoi(val[1]));
+ return true;
+ },
+ "Set the image size"
+ )->expected(2)->check(CLI::PositiveNumber);
+ app->add_option_function(
+ "--denoiser",
+ [&](const int denoiser) {
if (studioCommon.denoiserAvailable) {
- if (argAvailability(switchArg, 1))
- optDenoiser = min(2, max(0, atoi(argv[argIndex++])));
- } else {
- std::cout << " Denoiser not enabled. Check OSPRay module.\n";
- argIndex++;
- }
- } else if (switchArg == "-g" || switchArg == "--grid") {
- if (argAvailability(switchArg, 3)) {
- auto x = max(0, atoi(argv[argIndex++]));
- auto y = max(0, atoi(argv[argIndex++]));
- auto z = max(0, atoi(argv[argIndex++]));
- optGridSize = vec3i(x, y, z);
- optGridEnable = true;
- }
- } else if (switchArg == "-a" || switchArg == "--albedo") {
- saveAlbedo = true;
- } else if (switchArg == "-d" || switchArg == "--depth") {
- saveDepth = true;
- } else if (switchArg == "-n" || switchArg == "--normal") {
- saveNormal = true;
- } else if (switchArg == "-l" || switchArg == "--layers") {
- saveLayers = true;
- } else if (switchArg == "-m" || switchArg == "--metadata") {
- saveMetaData = true;
- } else if (switchArg == "-fps" || switchArg == "--speed") {
- if (argAvailability(switchArg, 1))
- fps = atoi(argv[argIndex++]);
- animate = true;
- } else if (switchArg == "-fr" || switchArg == "--force") {
- forceRewrite = true;
- } else if (switchArg == "-cam" || switchArg == "--camera") {
- if (argAvailability(switchArg, 1)) {
- cameraDef = std::stoi(argv[argIndex++]);
- if (cameraDef < 0) {
- std::cout << "unsupported camera index specified " << std::endl;
- return false;
- }
- }
- if (!cameraDef)
- std::cout
- << "using default ospray camera, to use imported definition camera indices begins from 1"
- << std::endl;
- } else if (switchArg == "-cams" || switchArg == "--cameras") {
- if (argAvailability(switchArg, 2)) {
- auto x = atoi(argv[argIndex++]);
- auto y = atoi(argv[argIndex++]);
- cameraRange.lower = x;
- cameraRange.upper = y;
- useCameraRange = true;
- }
- if (!cameraRange.lower && !cameraRange.upper)
- std::cout
- << "using default ospray camera, to use imported definition camera indices begins from 1"
- << std::endl;
- } else if (switchArg == "-rn" || switchArg == "--range") {
- if (argAvailability(switchArg, 2)) {
- auto x = atoi(argv[argIndex++]);
- auto y = atoi(argv[argIndex++]);
- framesRange.lower = x;
- framesRange.upper = y;
- }
- }
- // volume parameters
- else if (switchArg == "--dimensions" || switchArg == "-dim") {
- if (argAvailability(switchArg, 3)) {
- const std::string dimX(argv[argIndex++]);
- const std::string dimY(argv[argIndex++]);
- const std::string dimZ(argv[argIndex++]);
- auto dimensions = vec3i(std::stoi(dimX), std::stoi(dimY), std::stoi(dimZ));
- volumeParams->createChild("dimensions", "vec3i", dimensions);
- }
- } else if (switchArg == "--gridSpacing" || switchArg == "-gs") {
- if (argAvailability(switchArg, 3)) {
- const std::string gridSpacingX(argv[argIndex++]);
- const std::string gridSpacingY(argv[argIndex++]);
- const std::string gridSpacingZ(argv[argIndex++]);
- auto gridSpacing =
- vec3f(stof(gridSpacingX), stof(gridSpacingY), stof(gridSpacingZ));
- volumeParams->createChild("gridSpacing", "vec3f", gridSpacing);
- }
- } else if (switchArg == "--gridOrigin" || switchArg == "-go") {
- if (argAvailability(switchArg, 3)) {
- const std::string gridOriginX(argv[argIndex++]);
- const std::string gridOriginY(argv[argIndex++]);
- const std::string gridOriginZ(argv[argIndex++]);
- auto gridOrigin =
- vec3f(stof(gridOriginX), stof(gridOriginY), stof(gridOriginZ));
- volumeParams->createChild("gridOrigin", "vec3f", gridOrigin);
- }
- } else if (switchArg == "--voxelType" || switchArg == "-vt") {
- if (argAvailability(switchArg, 1)) {
- auto voxelTypeStr = std::string(argv[argIndex++]);
- auto it = sg::volumeVoxelType.find(voxelTypeStr);
- if (it != sg::volumeVoxelType.end()) {
- auto voxelType = it->second;
- volumeParams->createChild("voxelType", "int", (int)voxelType);
- } else {
- throw std::runtime_error("improper -voxelType format requested");
- }
- }
- } else if (switchArg == "--sceneConfig" || switchArg == "-sc") {
- // valid values are dynamic, compact and robust
- if (argAvailability(switchArg, 1)) {
- const std::string sc(argv[argIndex++]);
- sceneConfig = sc;
- }
- } else if (switchArg == "--instanceConfig" || switchArg == "-ic") {
- // valid values are dynamic, compact and robust
- if (argAvailability(switchArg, 1)) {
- const std::string ic(argv[argIndex++]);
- instanceConfig = ic;
+ optDenoiser = denoiser;
+ return true;
}
- } else if (switchArg.front() == '-') {
- std::cout << " Unknown option: " << switchArg << std::endl;
- break;
- } else {
- filesToImport.push_back(switchArg);
- }
+ return false;
+ },
+ "Set the denoiser"
+ )->check(CLI::Range(0, 2+1));
+ app->add_option(
+ "--grid",
+ [&](const std::vector val) {
+ optGridSize = vec3i(std::stoi(val[0]), std::stoi(val[1]), std::stoi(val[2]));
+ optGridEnable = true;
+ return true;
+ },
+ "Set the camera position"
+ )->expected(3);
+ app->add_flag(
+ "--saveAlbedo",
+ saveAlbedo,
+ "Save albedo values"
+ );
+ app->add_flag(
+ "--saveDepth",
+ saveDepth,
+ "Save depth values"
+ );
+ app->add_flag(
+ "--saveNormal",
+ saveNormal,
+ "Save normal values"
+ );
+ app->add_flag(
+ "--saveLayers",
+ saveLayers,
+ "Save all layers"
+ );
+ app->add_flag(
+ "--saveMetadata",
+ saveMetaData,
+ "Save metadata"
+ );
+ app->add_option(
+ "--framesPerSecond",
+ fps,
+ "Set the number of frames per second (integer)"
+ );
+ app->add_flag(
+ "--forceRewrite",
+ forceRewrite,
+ "Force overwriting saved files if they exist"
+ );
+ app->add_option(
+ "--camera",
+ cameraDef,
+ "Set the camera index to use"
+ )->check(CLI::PositiveNumber);
+ app->add_option(
+ "--cameras",
+ [&](const std::vector val) {
+ cameraRange.lower = std::stoi(val[0]);
+ cameraRange.upper = std::stoi(val[1]);
+ useCameraRange = true;
+ return true;
+ },
+ "Set the camera range"
+ )->expected(2);
+ app->add_option(
+ "--frameRange",
+ [&](const std::vector val) {
+ framesRange.lower = std::stoi(val[0]);
+ framesRange.upper = std::stoi(val[1]);
+ return true;
+ },
+ "Set the frames range"
+ )->expected(2);
+}
+
+bool BatchContext::parseCommandLine()
+{
+ int ac = studioCommon.argc;
+ const char **av = studioCommon.argv;
+
+ std::shared_ptr app = std::make_shared("OSPRay Studio Batch");
+ StudioContext::addToCommandLine(app);
+ BatchContext::addToCommandLine(app);
+ try {
+ app->parse(ac, av);
+ } catch (const CLI::ParseError &e) {
+ exit(app->exit(e));
}
if (filesToImport.size() == 0) {
@@ -311,25 +254,59 @@ void BatchContext::refreshRenderer()
renderer.child("varianceThreshold").setValue(optVariance);
}
-bool BatchContext::refreshCamera(int cameraIdx, bool resetArcball)
+void BatchContext::reshape()
{
- if(frame->hasChild("camera"))
- frame->remove("camera");
+ auto fSize = frame->child("windowSize").valueAs();
+
+ if (lockAspectRatio) {
+ // Tell OSPRay to render the largest subset of the window that satisies the
+ // aspect ratio
+ float aspectCorrection = lockAspectRatio * static_cast(fSize.y)
+ / static_cast(fSize.x);
+ if (aspectCorrection > 1.f) {
+ fSize.y /= aspectCorrection;
+ } else {
+ fSize.x *= aspectCorrection;
+ }
+ if (frame->child("camera").hasChild("aspect"))
+ frame->child("camera")["aspect"] = static_cast(fSize.x) / fSize.y;
+ } else if (frame->child("camera").hasChild("aspect"))
+ frame->child("camera")["aspect"] = optImageSize.x / (float)optImageSize.y;
+ frame->child("windowSize") = fSize;
+ frame->currentAccum = 0;
+
+ // update camera
+ arcballCamera->updateWindowSize(fSize);
+}
+
+bool BatchContext::refreshCamera(int cameraIdx, bool resetArcball)
+{
if (resetArcball)
arcballCamera.reset(
new ArcballCamera(frame->child("world").bounds(), optImageSize));
+ int hasParents{0};
if (cameraIdx <= cameras.size() && cameraIdx > 0) {
std::cout << "Loading camera from index: " << std::to_string(cameraIdx)
<< std::endl;
selectedSceneCamera = cameras[cameraIdx - 1];
+ hasParents = selectedSceneCamera->parents().size();
+ frame->remove("camera");
+ frame->add(selectedSceneCamera);
- auto &camera = frame->createChildAs(
- "camera", selectedSceneCamera->subType());
-
- for (auto &c : selectedSceneCamera->children())
- camera.add(c.second);
+ // TODO: remove this Hack : for some reason the accumulated transform in
+ // transform node does not get updated for the BIT animation scene.
+ // Attempting to make transform modified so it picks up accumulated
+ // transform values made by renderScene
+ if (hasParents) {
+ auto cameraXfm = selectedSceneCamera->parents().front();
+ if (cameraXfm->valueAs() == affine3f(one))
+ cameraXfm->createChild("refresh", "bool");
+ }
+
+ if (selectedSceneCamera->hasChild("aspect"))
+ lockAspectRatio = selectedSceneCamera->child("aspect").valueAs();
// create unique cameraId for every camera
auto &cameraParents = selectedSceneCamera->parents();
@@ -350,11 +327,14 @@ bool BatchContext::refreshCamera(int cameraIdx, bool resetArcball)
} else {
std::cout << "No cameras imported or invalid camera index specified"
<< std::endl;
- selectedSceneCamera = createNode(
- "camera", "camera_" + optCameraTypeStr);
- frame->add(selectedSceneCamera);
+ std::cout << "using default camera..." << std::endl;
}
+ reshape(); // resets aspect
+
+ // if imported cameras don't have parent transform then use Arcball properties
+ if (!hasParents)
+ useArcball = true;
updateCamera();
return true;
@@ -362,10 +342,6 @@ bool BatchContext::refreshCamera(int cameraIdx, bool resetArcball)
void BatchContext::render()
{
-
- // Set the frame "windowSize", it will create the right sized framebuffer
- frame->child("windowSize") = optImageSize;
-
auto &frameBuffer = frame->childAs("framebuffer");
frameBuffer["floatFormat"] = true;
frameBuffer.commit();
@@ -414,14 +390,6 @@ void BatchContext::renderFrame()
frame->immediatelyWait = true;
frame->startNewFrame();
- if (selectedSceneCamera->nodeAs()->animate || cameraDef > 0) {
- auto newCS = selectedSceneCamera->nodeAs()->getState();
- arcballCamera->setState(*newCS);
- updateCamera();
- frame->cancelFrame();
- frame->startNewFrame();
- }
-
static int filenum;
if (resetFileId) {
filenum = framesRange.lower;
@@ -474,11 +442,11 @@ void BatchContext::refreshScene(bool resetCam)
// Check that the frame contains a world, if not create one
auto world = frame->hasChild("world") ? frame->childNodeAs("world")
: sg::createNode("world", "world");
- if (sceneConfig == "dynamic")
+ if (optSceneConfig == "dynamic")
world->child("dynamicScene").setValue(true);
- else if (sceneConfig == "compact")
+ else if (optSceneConfig == "compact")
world->child("compactMode").setValue(true);
- else if (sceneConfig == "robust")
+ else if (optSceneConfig == "robust")
world->child("robustMode").setValue(true);
world->createChild(
"materialref", "reference_to_material", defaultMaterialIdx);
@@ -509,12 +477,11 @@ void BatchContext::updateCamera()
frame->currentAccum = 0;
auto &camera = frame->child("camera");
- camera["position"] = arcballCamera->eyePos();
- camera["direction"] = arcballCamera->lookDir();
- camera["up"] = arcballCamera->upDir();
-
- if (camera.hasChild("aspect"))
- camera["aspect"] = optImageSize.x / (float)optImageSize.y;
+ if (useArcball) {
+ camera["position"] = arcballCamera->eyePos();
+ camera["direction"] = arcballCamera->lookDir();
+ camera["up"] = arcballCamera->upDir();
+ }
if (cmdlCam) {
camera["position"] = pos;
@@ -538,7 +505,7 @@ void BatchContext::importFiles(sg::NodePtr world)
{
importedModels = createNode("importXfm", "transform");
frame->child("world").add(importedModels);
- if (animate)
+ if (fps)
animationManager = std::shared_ptr(new AnimationManager);
for (auto file : filesToImport) {
@@ -558,6 +525,7 @@ void BatchContext::importFiles(sg::NodePtr world)
importer->setMaterialRegistry(baseMaterialRegistry);
importer->setCameraList(cameras);
importer->setLightsManager(lightsManager);
+ importer->setArguments(studioCommon.argc, (char**)studioCommon.argv);
if (volumeParams->children().size() > 0) {
auto vp = importer->getVolumeParams();
for (auto &c : volumeParams->children()) {
@@ -567,13 +535,13 @@ void BatchContext::importFiles(sg::NodePtr world)
}
if (animationManager)
importer->setAnimationList(animationManager->getAnimations());
- if (instanceConfig == "dynamic")
+ if (optInstanceConfig == "dynamic")
importer->setInstanceConfiguration(
sg::InstanceConfiguration::DYNAMIC);
- else if (instanceConfig == "compact")
+ else if (optInstanceConfig == "compact")
importer->setInstanceConfiguration(
sg::InstanceConfiguration::COMPACT);
- else if (instanceConfig == "robust")
+ else if (optInstanceConfig == "robust")
importer->setInstanceConfiguration(
sg::InstanceConfiguration::ROBUST);
importer->importScene();
@@ -592,65 +560,3 @@ void BatchContext::importFiles(sg::NodePtr world)
if (animationManager)
animationManager->init();
}
-
-void BatchContext::printHelp()
-{
- std::cout <<
- R"text(
-./ospStudio batch [parameters] [scene_files]
-
-ospStudio batch specific parameters:
- -fps --speed
- -fr --forceRewrite
- force rewrite on existing saved files
- -rn --range [start end] for eg : [10 20]
- range of frames to be rendered
- This should be determined by the user based on specified `fps` and total animation time.
- -cam --camera
- In case of mulitple imported cameras specify which camera definition to use, counting starts from 1
- 0 here would use default camera implementation
- -cams --cameras
- In case of mulitple imported cameras specify which camera-range to use, counting starts from 1
- for eg. a valid range would be [1 7]
- -a --albedo
- -d --depth
- -n --normal
- -m --metadata
- -l --layers
- -f --format (default png)
- format for saving the image
- (sg, exr, hdr, jpg, pfm,png, ppm)
- -i --image [baseFilename] (default 'ospBatch')
- base name of saved image
- -s --size [x y] (default 1024x768)
- image size
- -spp --samples [int] (default 32)
- samples per pixel
- -pf --pixelfilter (default gauss)
- (0=point, 1=box, 2=gauss, 3=mitchell, 4=blackman_harris)
- -r --renderer [type] (default "pathtracer")
- rendererType scivis, ao, or pathtracer
- -c --camera [type] (default "perspective")
- cameraType perspective or panoramic
- -vp [x y z] camera position
- -vu [x y z] camera up
- -vi [x y z] camera look-at
- -sm --stereoMode 0=none, 1=left, 2=right, 3=side-by-side, 4=top-bottom
- -id --interpupillaryDistance
- -g --grid [x y z] (default 1 1 1, single instance)
- instace a grid of models
- -sc --sceneConfig(default is the static BVH build of embree)
- set global scene configuration params
- valid values are dynamic, compact and robust
- -ic --instanceConfig(default is the static BVH build of embree)
- set instance scene configuration params
- valid values are dynamic, compact and robust)text"
- << std::endl;
- if (studioCommon.denoiserAvailable) {
- std::cout <<
- R"text(
- -oidn --denoiser [0,1,2] (default 0)
- image denoiser (0 = off, 1 = on, 2 = save both)
-)text" << std::endl;
- }
-}
diff --git a/app/Batch.h b/app/Batch.h
index f0bb7097..c0273835 100644
--- a/app/Batch.h
+++ b/app/Batch.h
@@ -26,6 +26,7 @@ class BatchContext : public StudioContext
~BatchContext() {}
void start() override;
+ void addToCommandLine(std::shared_ptr app) override;
bool parseCommandLine() override;
void importFiles(sg::NodePtr world) override;
void refreshRenderer();
@@ -36,6 +37,7 @@ class BatchContext : public StudioContext
void renderFrame();
void renderAnimation();
bool refreshCamera(int cameraIdx, bool resetArcball = false);
+ void reshape();
protected:
NodePtr importedModels;
@@ -47,11 +49,10 @@ class BatchContext : public StudioContext
bool saveLayers{false};
bool saveMetaData{true};
std::string optImageFormat{"png"};
- bool animate{false};
- int fps{24};
+
+ int fps{0};
bool forceRewrite{false};
range1i framesRange{0, 0};
- void printHelp() override;
int cameraDef{0};
range1i cameraRange{0, 0};
bool useCameraRange{false};
@@ -65,10 +66,6 @@ class BatchContext : public StudioContext
//camera animation
sg::NodePtr selectedSceneCamera;
- //Volume parameters
- sg::NodePtr volumeParams;
-
- // scene/instance configuration params
- std::string sceneConfig{""};
- std::string instanceConfig{""};
+ float lockAspectRatio = 0.0;
+ bool useArcball{false};
};
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index 6d7a257b..58903265 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -59,6 +59,7 @@ target_link_libraries(ospStudio
ospray_ui # Not all run modes should link against UI (ie batch).
ospray_sg
json
+ cli11
)
_target_strip_and_sign(ospStudio)
diff --git a/app/MainWindow.cpp b/app/MainWindow.cpp
index ec992a11..05962b0c 100644
--- a/app/MainWindow.cpp
+++ b/app/MainWindow.cpp
@@ -6,6 +6,7 @@
#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl2.h"
+#include "Proggy.h"
// std
#include
#include
@@ -23,6 +24,7 @@
#include "sg/visitors/PrintNodes.h"
#include "sg/visitors/Search.h"
#include "sg/visitors/SetParamByNode.h"
+#include "sg/visitors/CollectTransferFunctions.h"
#include "sg/scene/volume/Volume.h"
// rkcommon
#include "rkcommon/math/rkmath.h"
@@ -43,6 +45,9 @@
#include "widgets/PieMenu.h"
#include "widgets/Guizmo.h"
+// CLI
+#include
+
using namespace ospray_studio;
using namespace ospray;
@@ -51,7 +56,6 @@ static ImGuiWindowFlags g_imguiWindowFlags = ImGuiWindowFlags_AlwaysAutoResize;
static bool g_quitNextFrame = false;
static bool g_saveNextFrame = false;
static bool g_animatingPath = false;
-static bool g_animateCamera = false;
static bool g_clearSceneConfirm = false;
static const std::vector g_scenes = {"tutorial_scene",
@@ -174,6 +178,10 @@ MainWindow::MainWindow(StudioCommon &_common)
glfwWindowHint(GLFW_SRGB_CAPABLE, GLFW_TRUE);
+ // get primary monitor's display scaling
+ GLFWmonitor *primaryMonitor = glfwGetPrimaryMonitor();
+ glfwGetMonitorContentScale(primaryMonitor, &contentScale.x, &contentScale.y);
+
// create GLFW window
glfwWindow = glfwCreateWindow(
windowSize.x, windowSize.y, "OSPRay Studio", nullptr, nullptr);
@@ -382,6 +390,17 @@ MainWindow::MainWindow(StudioCommon &_common)
// Disable active viewports until users enables toggled in view menu
ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_ViewportsEnable;
+ // set ImGui font, scaled to display DPI
+ auto &io = ImGui::GetIO();
+ auto scaleFactor = std::max(contentScale.x, contentScale.y);
+ auto scaledFontSize = fontSize * scaleFactor;
+ ImVec2 imScale(contentScale.x, contentScale.y);
+
+ ImFont *font = io.Fonts->AddFontFromMemoryCompressedTTF(
+ ProggyClean_compressed_data, ProggyClean_compressed_size, scaledFontSize);
+ io.FontGlobalScale = 1.f / scaleFactor;
+ io.DisplayFramebufferScale = imScale;
+
// set initial OpenGL state
glEnable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
@@ -656,7 +675,7 @@ void MainWindow::motion(const vec2f &position)
if (frame->pauseRendering)
return;
- const vec2f mouse(position.x, position.y);
+ const vec2f mouse = position * contentScale;
if (previousMouse != vec2f(-1)) {
const bool leftDown =
glfwGetMouseButton(glfwWindow, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS;
@@ -672,10 +691,12 @@ void MainWindow::motion(const vec2f &position)
if (glfwGetKey(glfwWindow, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS)
sensitivity *= fineControl;
- const vec2f mouseFrom(clamp(prev.x * 2.f / windowSize.x - 1.f, -1.f, 1.f),
- clamp(prev.y * 2.f / windowSize.y - 1.f, -1.f, 1.f));
- const vec2f mouseTo(clamp(mouse.x * 2.f / windowSize.x - 1.f, -1.f, 1.f),
- clamp(mouse.y * 2.f / windowSize.y - 1.f, -1.f, 1.f));
+ auto displaySize = windowSize * contentScale;
+
+ const vec2f mouseFrom(clamp(prev.x * 2.f / displaySize.x - 1.f, -1.f, 1.f),
+ clamp(prev.y * 2.f / displaySize.y - 1.f, -1.f, 1.f));
+ const vec2f mouseTo(clamp(mouse.x * 2.f / displaySize.x - 1.f, -1.f, 1.f),
+ clamp(mouse.y * 2.f / displaySize.y - 1.f, -1.f, 1.f));
if (leftDown) {
arcballCamera->constrainedRotate(mouseFrom,
@@ -704,7 +725,8 @@ void MainWindow::mouseButton(const vec2f &position)
if (glfwGetKey(glfwWindow, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS
&& glfwGetMouseButton(glfwWindow, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS) {
- pickCenterOfRotation(position.x, position.y);
+ vec2f scaledPosition = position * contentScale;
+ pickCenterOfRotation(scaledPosition.x, scaledPosition.y);
}
}
@@ -737,7 +759,7 @@ void MainWindow::display()
{
static auto displayStart = std::chrono::high_resolution_clock::now();
- if (autorotate) {
+ if (optAutorotate) {
vec2f from(0.f, 0.f);
vec2f to(autorotateSpeed * 0.001f, 0.f);
arcballCamera->rotate(from, to);
@@ -763,17 +785,6 @@ void MainWindow::display()
}
}
- // Add new camera params
- if (g_animateCamera) {
- auto selectedCamera = g_selectedSceneCamera->nodeAs();
- auto cs = selectedCamera->getState();
-
- if (cs != nullptr) {
- arcballCamera->setState(*cs);
- updateCamera();
- }
- }
-
keyboardMotion();
if (displayCallback)
@@ -798,12 +809,12 @@ void MainWindow::display()
waitOnOSPRayFrame();
// Only enabled if they exist
- showAlbedo &= frameBuffer.hasAlbedoChannel();
- showDepth &= frameBuffer.hasDepthChannel();
+ optShowAlbedo &= frameBuffer.hasAlbedoChannel();
+ optShowDepth &= frameBuffer.hasDepthChannel();
- auto *mappedFB = (void *)frame->mapFrame(showDepth
+ auto *mappedFB = (void *)frame->mapFrame(optShowDepth
? OSP_FB_DEPTH
- : (showAlbedo ? OSP_FB_ALBEDO : OSP_FB_COLOR));
+ : (optShowAlbedo ? OSP_FB_ALBEDO : OSP_FB_COLOR));
// This needs to query the actual framebuffer format
const GLenum glType =
@@ -811,7 +822,7 @@ void MainWindow::display()
// Only create the copy if it's needed
float *pDepthCopy = nullptr;
- if (showDepth) {
+ if (optShowDepth) {
// Create a local copy and don't modify OSPRay buffer
const auto *mappedDepth = static_cast(mappedFB);
std::vector depthCopy(
@@ -832,7 +843,7 @@ void MainWindow::display()
const float rcpDepthRange = 1.f / (maxDepth - minDepth);
// Inverted depth (1.0 -> 0.0) may be more meaningful
- if (showDepthInvert)
+ if (optShowDepthInvert)
std::transform(depthCopy.begin(),
depthCopy.end(),
depthCopy.begin(),
@@ -849,13 +860,13 @@ void MainWindow::display()
glBindTexture(GL_TEXTURE_2D, framebufferTexture);
glTexImage2D(GL_TEXTURE_2D,
0,
- showAlbedo ? gl_rgb_format : gl_rgba_format,
+ optShowAlbedo ? gl_rgb_format : gl_rgba_format,
fbSize.x,
fbSize.y,
0,
- showDepth ? GL_LUMINANCE : (showAlbedo ? GL_RGB : GL_RGBA),
+ optShowDepth ? GL_LUMINANCE : (optShowAlbedo ? GL_RGB : GL_RGBA),
glType,
- showDepth ? pDepthCopy : mappedFB);
+ optShowDepth ? pDepthCopy : mappedFB);
frame->unmapFrame(mappedFB);
@@ -1032,11 +1043,11 @@ void MainWindow::refreshScene(bool resetCam)
// Check that the frame contains a world, if not create one
auto world = frame->hasChild("world") ? frame->childNodeAs("world")
: sg::createNode("world", "world");
- if (sceneConfig == "dynamic")
+ if (optSceneConfig == "dynamic")
world->child("dynamicScene").setValue(true);
- else if (sceneConfig == "compact")
+ else if (optSceneConfig == "compact")
world->child("compactMode").setValue(true);
- else if (sceneConfig == "robust")
+ else if (optSceneConfig == "robust")
world->child("robustMode").setValue(true);
world->createChild(
@@ -1072,76 +1083,36 @@ void MainWindow::refreshScene(bool resetCam)
fb.resetAccumulation();
}
+void MainWindow::addToCommandLine(std::shared_ptr app) {
+ app->add_flag(
+ "--animate",
+ optAnimate,
+ "enable loading glTF animations"
+ );
+}
+
bool MainWindow::parseCommandLine()
{
int ac = studioCommon.argc;
const char **av = studioCommon.argv;
- volumeParams = std::make_shared();
- for (int i = 1; i < ac; i++) {
- const auto arg = std::string(av[i]);
- if (arg.rfind("-", 0) != 0) {
- filesToImport.push_back(arg);
- } else if (arg == "-h" || arg == "--help") {
- printHelp();
- return false;
- } else if (arg == "-pf" || arg == "--pixelfilter") {
- optPF = max(0, atoi(av[i + 1]));
- rkcommon::removeArgs(ac, av, i, 2);
- --i;
- } else if (arg == "--animate" || arg == "-a") {
- animate = true;
- } else if (arg == "--dimensions" || arg == "-dim") {
- const std::string dimX(av[++i]);
- const std::string dimY(av[++i]);
- const std::string dimZ(av[++i]);
- auto dimensions = vec3i(std::stoi(dimX), std::stoi(dimY), std::stoi(dimZ));
- volumeParams->createChild("dimensions", "vec3i", dimensions);
- } else if (arg == "--gridSpacing" || arg == "-gs") {
- const std::string gridSpacingX(av[++i]);
- const std::string gridSpacingY(av[++i]);
- const std::string gridSpacingZ(av[++i]);
- auto gridSpacing =
- vec3f(stof(gridSpacingX), stof(gridSpacingY), stof(gridSpacingZ));
- volumeParams->createChild("gridSpacing", "vec3f", gridSpacing);
- } else if (arg == "--gridOrigin" || arg == "-go") {
- const std::string gridOriginX(av[++i]);
- const std::string gridOriginY(av[++i]);
- const std::string gridOriginZ(av[++i]);
- auto gridOrigin =
- vec3f(stof(gridOriginX), stof(gridOriginY), stof(gridOriginZ));
- volumeParams->createChild("gridOrigin", "vec3f", gridOrigin);
- } else if (arg == "--voxelType" || arg == "-vt") {
- auto voxelTypeStr = std::string(av[++i]);
- auto it = sg::volumeVoxelType.find(voxelTypeStr);
- if (it != sg::volumeVoxelType.end()) {
- auto voxelType = it->second;
- volumeParams->createChild("voxelType", "int", (int)voxelType);
- } else {
- throw std::runtime_error("improper -voxelType format requested");
- }
- } else if (arg == "--sceneConfig" || arg == "-sc") {
- // valid values are dynamic, compact and robust
- const std::string sc(av[++i]);
- sceneConfig = sc;
- } else if (arg == "--instanceConfig" || arg == "-ic") {
- // valid values are dynamic, compact and robust
- const std::string ic(av[++i]);
- instanceConfig = ic;
- } else if (arg == "--2160p")
- glfwSetWindowSize(glfwWindow, 3840, 2160);
- else if (arg == "--1440p")
- glfwSetWindowSize(glfwWindow, 2560, 1440);
- else if (arg == "--1080p")
- glfwSetWindowSize(glfwWindow, 1920, 1080);
- else if (arg == "--720p")
- glfwSetWindowSize(glfwWindow, 1280, 720);
- else if (arg == "--540p")
- glfwSetWindowSize(glfwWindow, 960, 540);
- else if (arg == "--270p")
- glfwSetWindowSize(glfwWindow, 480, 270);
- else if (arg == "--pointSize" || arg == "-ps")
- pointSize = std::stof(av[++i]);
+
+ std::shared_ptr app = std::make_shared("OSPRay Studio GUI");
+ StudioContext::addToCommandLine(app);
+ MainWindow::addToCommandLine(app);
+ try {
+ app->parse(ac, av);
+ } catch (const CLI::ParseError &e) {
+ exit(app->exit(e));
+ }
+
+ // XXX: changing windowSize here messes causes some display scaling issues
+ // because it desyncs window and framebuffer size with any scaling
+ if (optResolution.x != 0) {
+ windowSize = optResolution;
+ glfwSetWindowSize(glfwWindow, optResolution.x, optResolution.y);
+ reshape(windowSize);
}
+ rendererTypeStr = optRendererTypeStr;
if (!filesToImport.empty()) {
std::cout << "Import files from cmd line" << std::endl;
@@ -1155,7 +1126,7 @@ bool MainWindow::parseCommandLine()
void MainWindow::importFiles(sg::NodePtr world)
{
std::vector cameras;
- if (animate)
+ if (optAnimate)
animationManager = std::shared_ptr(new AnimationManager);
for (auto file : filesToImport) {
@@ -1184,15 +1155,16 @@ void MainWindow::importFiles(sg::NodePtr world)
importer->setMaterialRegistry(baseMaterialRegistry);
importer->setCameraList(cameras);
importer->setLightsManager(lightsManager);
+ importer->setArguments(studioCommon.argc, (char**)studioCommon.argv);
if (animationManager)
importer->setAnimationList(animationManager->getAnimations());
- if (instanceConfig == "dynamic")
+ if (optInstanceConfig == "dynamic")
importer->setInstanceConfiguration(
sg::InstanceConfiguration::DYNAMIC);
- else if (instanceConfig == "compact")
+ else if (optInstanceConfig == "compact")
importer->setInstanceConfiguration(
sg::InstanceConfiguration::COMPACT);
- else if (instanceConfig == "robust")
+ else if (optInstanceConfig == "robust")
importer->setInstanceConfiguration(
sg::InstanceConfiguration::ROBUST);
@@ -1216,19 +1188,13 @@ void MainWindow::importFiles(sg::NodePtr world)
}
if (cameras.size() > 0) {
- auto &mainCamera = frame->child("camera");
- auto defaultCamera =
- sg::createNode("default_camera", frame->child("camera").subType());
- for (auto &c : mainCamera.children()) {
- defaultCamera->createChild(
- c.first, c.second->subType(), c.second->value());
- }
-
- g_sceneCameras["default camera"] = defaultCamera;
+ auto mainCamera = frame->child("camera").nodeAs();
+ g_sceneCameras[mainCamera->child("uniqueCameraName")
+ .valueAs()] = mainCamera;
// populate cameras in camera editor in View menu
for (auto &c : cameras)
- g_sceneCameras[c->name()] = c;
+ g_sceneCameras[c->child("uniqueCameraName").valueAs()] = c;
}
}
@@ -1303,10 +1269,10 @@ void MainWindow::buildMainMenuFile()
if (ImGui::BeginMenu("File")) {
if (ImGui::MenuItem("Import ...", nullptr)) {
showImportFileBrowser = true;
- animate = false;
+ optAnimate = false;
} else if (ImGui::MenuItem("Import and animate ...", nullptr)) {
showImportFileBrowser = true;
- animate = true;
+ optAnimate = true;
}
if (ImGui::BeginMenu("Demo Scene")) {
for (size_t i = 0; i < g_scenes.size(); ++i) {
@@ -1530,8 +1496,8 @@ void MainWindow::buildMainMenuView()
ImGui::SetNextItemWidth(5 * ImGui::GetFontSize());
frame->childAs("renderer")["varianceThreshold"].
traverse(sg::TreeState::ROOTOPEN);
- ImGui::Checkbox("Auto rotate", &autorotate);
- if (autorotate) {
+ ImGui::Checkbox("Auto rotate", &optAutorotate);
+ if (optAutorotate) {
ImGui::SameLine();
ImGui::SetNextItemWidth(5 * ImGui::GetFontSize());
ImGui::SliderInt(" speed", &autorotateSpeed, 1, 100);
@@ -1796,21 +1762,21 @@ void MainWindow::buildWindowFrameBufferEditor()
switch (whichBuffer) {
case 0:
- showColor = true;
- showAlbedo = showDepth = showDepthInvert = false;
+ optShowColor = true;
+ optShowAlbedo = optShowDepth = optShowDepthInvert = false;
break;
case 1:
- showAlbedo = true;
- showColor = showDepth = showDepthInvert = false;
+ optShowAlbedo = true;
+ optShowColor = optShowDepth = optShowDepthInvert = false;
break;
case 2:
- showDepth = true;
- showColor = showAlbedo = showDepthInvert = false;
+ optShowDepth = true;
+ optShowColor = optShowAlbedo = optShowDepthInvert = false;
break;
case 3:
- showDepth = true;
- showDepthInvert = true;
- showColor = showAlbedo = false;
+ optShowDepth = true;
+ optShowDepthInvert = true;
+ optShowColor = optShowAlbedo = false;
break;
}
@@ -2172,9 +2138,7 @@ void MainWindow::buildWindowLightEditor()
if (lightsManager->addLight(lightName, lightType)) {
if (lightType == "hdri") {
auto &hdri = lightsManager->child(lightName);
- auto &hdriTex = hdri.createChild("map", "texture_2d");
- auto ast2d = hdriTex.nodeAs();
- ast2d->load(texFileName, false, false);
+ hdri["filename"] = texFileName.str();
}
// Select newly added light
whichLight = lights.size() - 1;
@@ -2206,34 +2170,35 @@ void MainWindow::buildWindowCameraEditor()
}
// Only present selector UI if more than one camera
- if (!g_sceneCameras.empty() &&
- ImGui::Combo("sceneCameras##whichCamera",
+ if (!g_sceneCameras.empty()
+ && ImGui::Combo("sceneCameras##whichCamera",
&whichCamera,
cameraUI_callback,
nullptr,
g_sceneCameras.size())) {
- if (whichCamera > -1 && whichCamera < (int) g_sceneCameras.size()) {
+ if (whichCamera > -1 && whichCamera < (int)g_sceneCameras.size()) {
auto &newCamera = g_sceneCameras.at_index(whichCamera);
g_selectedSceneCamera = newCamera.second;
- g_animateCamera = g_selectedSceneCamera->nodeAs()->animate;
-
- // Change the camera type, if the new camera is different.
- if (frame->childAs("camera").subType()
- != newCamera.second->subType()) {
- frame->createChildAs("camera",
- newCamera.second->subType());
+ auto hasParents = g_selectedSceneCamera->parents().size();
+ frame->remove("camera");
+ frame->add(g_selectedSceneCamera);
+
+ // TODO: remove this Hack : for some reason the accumulated transform in
+ // transform node does not get updated for the BIT animation scene.
+ // Attempting to make transform modified so it picks up accumulated
+ // transform values made by renderScene
+ if (hasParents) {
+ auto cameraXfm = g_selectedSceneCamera->parents().front();
+ if (cameraXfm->valueAs() == affine3f(one))
+ cameraXfm->createChild("refresh", "bool");
}
- // Add new camera params
- auto &camera = frame->childAs("camera");
- for (auto &c : g_selectedSceneCamera->children())
- camera.add(c.second);
-
- auto newCS = g_selectedSceneCamera->nodeAs()->getState();
- arcballCamera->setState(*newCS);
-
+ if (g_selectedSceneCamera->hasChild("aspect"))
+ lockAspectRatio =
+ g_selectedSceneCamera->child("aspect").valueAs();
reshape(windowSize); // resets aspect
- updateCamera();
+ if (!hasParents)
+ updateCamera();
}
}
@@ -2286,17 +2251,9 @@ void MainWindow::buildWindowTransferFunctionEditor()
}
// Gather all transfer functions in the scene
- std::map transferFunctions = {};
- for (auto &node : frame->child("world").children())
- if (node.second->type() == sg::NodeType::GENERATOR
- || node.second->type() == sg::NodeType::IMPORTER
- || node.second->type() == sg::NodeType::VOLUME) {
- auto tfn =
- findFirstNodeOfType(node.second, sg::NodeType::TRANSFER_FUNCTION);
- // node.first is a unique name. tfn->name() is always "transferFunction"
- if (tfn)
- transferFunctions[node.first] = tfn;
- }
+ sg::CollectTransferFunctions visitor;
+ frame->traverse(visitor);
+ auto &transferFunctions = visitor.transferFunctions;
if (transferFunctions.empty()) {
ImGui::Text("== empty == ");
@@ -2605,23 +2562,3 @@ void MainWindow::buildWindowRenderingStats()
ImGui::End();
}
-
-void MainWindow::printHelp()
-{
- const char *help = R"help(ospStudio gui [options] [file1 [file2 ...]]
-
- OPTIONS
- -h, --help this help message
- -pf N, --pixelfilter N set default pixel filter:
- 0 = point
- 1 = box
- 2 = Gaussian
- 3 = Mitchell-Netravali
- 4 = Blackman-Harris
- -a, --animate enable loading glTF animations
- --2160p, --1440p, set window/frame resolution
- --1080p, --720p,
- --540p, --270p
-)help";
- std::cerr << help;
-}
diff --git a/app/MainWindow.h b/app/MainWindow.h
index 56a3313f..b32a41e0 100644
--- a/app/MainWindow.h
+++ b/app/MainWindow.h
@@ -14,6 +14,7 @@
// std
#include
+#include