diff --git a/.gitignore b/.gitignore
index 95faf6f6a0..591a846c12 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,3 +19,4 @@ ospray-doc
!/modules
/modules/*
!/modules/mpi
+!/modules/pluggableGeometryExample
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 7ad2034226..a2db8d48ea 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -16,6 +16,7 @@ build-centos6-gcc:
build-centos6-icc:
type: build
script:
+ - module load gcc/4.9.3
- module load intel
- export CC=icc
- export CXX=icpc
@@ -25,6 +26,19 @@ build-centos6-icc:
- icc
- build
+build-centos6-icc15:
+ type: build
+ script:
+ - module load gcc/4.9.3
+ - module load intel/2015
+ - export CC=icc
+ - export CXX=icpc
+ - scripts/build_gitlab/linux.sh
+ tags:
+ - centos6
+ - icc
+ - build
+
build-centos7-gcc:
type: build
script:
@@ -71,15 +85,6 @@ build-ubuntu1404-gcc:
- gcc
- build
-build-sles-gcc:
- type: build
- script:
- - scripts/build_gitlab/linux.sh
- tags:
- - sles
- - gcc
- - build
-
build-debug:
type: build
script:
@@ -96,6 +101,7 @@ build-mpi:
tags:
- linux
- mpi
+ - gcc
- build
build-osx-clang:
@@ -125,6 +131,15 @@ build-windows-msvc14:
- build
- win7
+build-windows-msvc15:
+ type: build
+ script:
+ - call scripts\build_gitlab\win.bat "Visual Studio 15 2017 Win64" "v141"
+ tags:
+ - msvc15
+ - build
+ - win7
+
build-windows-icc:
type: build
script:
@@ -136,37 +151,15 @@ build-windows-icc:
### RELEASE JOBS ###
-# NOTE(jda) - Current CentOS 6 release machine needs gcc environment
-# debugged
-#release-linux-gcc:
-# type: deploy
-# script:
-# - module load gcc
-# - export CC=gcc
-# - export CXX=g++
-# - export OSPRAY_RELEASE_NO_VERIFY=1
-# - scripts/release/linux.sh
-# tags:
-# - gcc
-# - release
-# - centos6
-# only:
-# - devel
-# - master
-# - release-1.0
-# artifacts:
-# paths:
-# - build_release/*.gz
-
release-linux-icc:
type: deploy
script:
- module load cmake
- - module load gcc
+ - module load gcc/4.9.3
- module load intel
- - module load qt
- export CC=icc
- export CXX=icpc
+ - export OSPRAY_RELEASE_NO_VERIFY=1 #NOTE: temporary until lib/apps split in release
- scripts/release/linux.sh
tags:
- icc
@@ -176,7 +169,7 @@ release-linux-icc:
only:
- devel
- master
- - release-1.2.x
+ - release-1.3.x
artifacts:
paths:
- build_release/*.gz
@@ -195,7 +188,7 @@ release-osx-clang:
only:
- devel
- master
- - release-1.2.x
+ - release-1.3.x
artifacts:
paths:
- build_release/*.gz
@@ -213,7 +206,7 @@ release-windows:
only:
- devel
- master
- - release-1.2.x
+ - release-1.3.x
artifacts:
paths:
- build_release\ospray*.zip
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 76f4c157c5..37423682b8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,10 +1,52 @@
Version History
---------------
+### Changes in v1.3.0:
+
+- New MPI distributed device to support MPI distributed applications
+ using OSPRay collectively for "in-situ" rendering (currently in "alpha")
+ - Enabled via new `mpi_distributed` device type
+ - Currently only supports `raycast` renderer, other renderers will be
+ supported in the future
+ - All API calls are expected to be exactly replicated (object instances
+ and parameters) except scene data (geometries and volumes)
+ - The original MPI device is now called the `mpi_offload` device to
+ differentiate between the two implementations
+- Support of Intel® AVX-512 for next generation Intel® Xeon® processor
+ (codename Skylake), thus new minimum ISPC version is 1.9.1
+- Thread affinity of OSPRay's tasking system can now be controlled via
+ either device parameter `setAffinity`, or commandline parameter
+ `osp:setaffinity`, or environment variable `OSPRAY_SET_AFFINITY`
+- Changed behavior of the background color in the SciVis renderer:
+ `bgColor` now includes alpha and is always blended (no
+ `backgroundEnabled` anymore). To disable the background don't set
+ bgColor, or set it to transparent black (0, 0, 0, 0)
+- Geometries "`spheres`" and "`cylinders`" now support texture
+ coordinates
+- The GLUT- and Qt-based demo viewer applications have been replaced
+ by an example viewer with minimal dependencies
+ - Building the sample applications now requires GCC 4.9 (previously
+ 4.8) for features used in the C++ standard library; OSPRay
+ itself can still be built with GCC 4.8
+ - The new example viewer based on `ospray::sg` (called
+ `ospExampleViewerSg`) is the single application we are
+ consolidating to, `ospExampleViewer` will remain only as a
+ deprecated viewer for compatibility with the old `ospGlutViewer`
+ application
+- Deprecated `ospCreateDevice()`; use `ospNewDevice()` instead
+- Improved error handling
+ - Various API functions now return an `OSPError` value
+ - `ospDeviceSetStatusFunc` replaces the deprecated
+ `ospDeviceSetErrorMsgFunc`
+ - New API functions to query the last error
+ (`ospDeviceGetLastErrorCode()` and `ospDeviceGetLastErrorMsg()`)
+ or to register an error callback with `ospDeviceSetErrorFunc()`
+ - Fixed bug where exceptions could leak to C applications
+
### Changes in v1.2.1:
- Various bugfixes related to MPI distributed rendering, ISPC issues
- on Windows, and other build related issues.
+ on Windows, and other build related issues
### Changes in v1.2.0:
@@ -23,7 +65,7 @@ Version History
via new material "`Luminous`"
- Lights can optionally made invisible by using the new parameter
`isVisible` (only relevant for path tracer)
-- OSPRay Devices are now extendable through modules and the SDK.
+- OSPRay Devices are now extendable through modules and the SDK
- Devices can be created and set current, creating an alternative
method for initializing the API
- New API functions for committing parameters on Devices
@@ -130,7 +172,7 @@ Version History
- GLUT viewer now supports volume rendering
- Command mode with preliminary scripting capabilities,
enabled by pressing '`:`' key (not available when using
- Intel C++ compiler (icc))
+ Intel C++ Compiler (icc))
- Enhanced support of sample applications on Windows
- New minimum ISPC version is 1.9.0
- Support of Intel® AVX-512 for second generation Intel Xeon Phi
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b2e6ea232d..7f5a12e02a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -95,7 +95,6 @@ ENDIF()
ADD_SUBDIRECTORY(modules)
-
# create a configure file that both ospray and ispc can read the cmake config
# from needs to be at the end, after all cache variables have been set
CONFIGURE_FILE(ospray/common/OSPConfig.h.in OSPConfig.h)
diff --git a/README.md b/README.md
index a0644eeccb..0d7ad43e1d 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
OSPRay
======
-This is release v1.2.1 of OSPRay. For changes and new features see the
+This is release v1.3.0 of OSPRay. For changes and new features see the
[changelog](CHANGELOG.md). Also visit http://www.ospray.org for more
information.
@@ -65,11 +65,10 @@ before you can build OSPRay you need the following prerequisites:
- To build OSPRay you need [CMake](http://www.cmake.org), any form of
C++11 compiler (we recommend using GCC, but also support Clang and
- the [Intel® C++ compiler
- (ICC)](https://software.intel.com/en-us/c-compilers)), and standard
- Linux development tools. To build the demo viewers, you should also
- have some version of OpenGL and the GL Utility Toolkit (GLUT or
- freeglut), as well as Qt 4.6 or higher.
+ the [Intel® C++ Compiler
+ (icc)](https://software.intel.com/en-us/c-compilers)), and standard
+ Linux development tools. To build the example viewers, you should
+ also have some version of OpenGL.
- Additionally you require a copy of the [Intel® SPMD Program Compiler
(ISPC)](http://ispc.github.io). Please obtain a copy of the latest
binary release of ISPC (currently 1.9.1) from the [ISPC downloads
@@ -94,20 +93,16 @@ Type the following to install the dependencies using `yum`:
sudo yum install cmake.x86_64
sudo yum install tbb.x86_64 tbb-devel.x86_64
- sudo yum install freeglut.x86_64 freeglut-devel.x86_64
- sudo yum install qt-devel.x86_64
Type the following to install the dependencies using `apt-get`:
sudo apt-get install cmake-curses-gui
sudo apt-get install libtbb-dev
- sudo apt-get install freeglut3-dev
- sudo apt-get install libqt4-dev
Under Mac OS X these dependencies can be installed using
[MacPorts](http://www.macports.org/):
- sudo port install cmake tbb freeglut qt4
+ sudo port install cmake tbb
Compiling OSPRay
----------------
@@ -147,8 +142,8 @@ CMake is easy:
user@mymachine[~/Projects/ospray/release]: make
-- You should now have `libospray.so` as well as a set of sample
- viewers. You can test your version of OSPRay using any of the
+- You should now have `libospray.so` as well as a set of example
+ application. You can test your version of OSPRay using any of the
examples on the [OSPRay Demos and
Examples](http://www.ospray.org/demos.html) page.
@@ -156,9 +151,9 @@ Documentation
=============
The following [API
-documentation](http://www.sdvis.org/ospray/download/OSPRay_readme.pdf "OSPRay Documentation")
+documentation](http://www.sdvis.org/ospray/download/OSPRay_readme_devel.pdf "OSPRay Documentation")
of OSPRay can also be found as a [pdf
-document](http://www.sdvis.org/ospray/download/OSPRay_readme.pdf "OSPRay Documentation")
+document](http://www.sdvis.org/ospray/download/OSPRay_readme_devel.pdf "OSPRay Documentation")
(2.6MB).
For a deeper explanation of the concepts, design, features and
@@ -196,19 +191,22 @@ The first is to do so by giving OSPRay the command line from `main()` by
calling
``` {.cpp}
-void ospInit(int *argc, const char **argv);
+OSPError ospInit(int *argc, const char **argv);
```
OSPRay parses (and removes) its known command line parameters from your
application's `main` function. For an example see the
-[tutorial](#tutorial). The following parameters (which are prefixed by
-convention with "`--osp:`") are understood:
+[tutorial](#tutorial). For possible error codes see section [Error
+Handling and Status Messages](#error-handling-and-status-messages). It
+is important to note that the arguments passed to `ospInit()` are
+prcessed in order they are listed. The following parameters (which are
+prefixed by convention with "`--osp:`") are understood:
-
+
Command line parameters accepted by OSPRay's ospInit
.
-
-
+
+
+--osp:module:<name> |
+load a module during initialization; equivalent to calling ospLoadModule(name) |
+
+
--osp:mpi |
-enables MPI mode for parallel rendering, to be used in conjunction with mpirun |
+enables MPI mode for parallel rendering with the mpi_offload device, to be used in conjunction with mpirun ; this will automatically load the "mpi" module if it is not yet loaded or linked |
+
+
+--osp:mpi-offload |
+same as --osp:mpi |
---osp:logoutput |
-convenience for setting where error/status messages go; valid values are cerr and cout |
+--osp:mpi-distributed |
+same as --osp:mpi , but will create an mpi_distributed device instead; Note that this will likely require application changes to work properly |
+--osp:logoutput <dst> |
+convenience for setting where error/status messages go; valid values for dst are cerr and cout |
+
+
--osp:device:<name> |
-use name as the type of device for OSPRay to create; e.g. --osp:device:default gives you the default local device and --osp:device:mpi gives you the MPI device |
+use name as the type of device for OSPRay to create; e.g. --osp:device:default gives you the default local device; Note if the device to be used is defined in a module, remember to pass --osp:module:<name> first |
+
+
+--osp:setaffinity <n> |
+if 1 , bind software threads to hardware threads; 0 disables binding; default is 1 on KNL and 0 otherwise |
@@ -258,18 +272,20 @@ convention with "`--osp:`") are understood:
The second method of initialization is to explicitly create the device
yourself, and possibly set parameters. This method looks almost
-identical to how other objects are created and used by OSPRay (described
-in later sections). The first step is to create the device with
+identical to how other [objects](#objects) are created and used by
+OSPRay (described in later sections). The first step is to create the
+device with
``` {.cpp}
-OSPDevice ospCreateDevice(const char *type);
+OSPDevice ospNewDevice(const char *type);
```
where the `type` string maps to a specific device implementation. OSPRay
always provides the "`default`" device, which maps to a local CPU
rendering device. If it is enabled in the build, you can also use
-"`mpi`" to access the MPI multi-node rendering device. Once a device is
-created, you can call
+"`mpi`" to access the MPI multi-node rendering device (see [Parallel
+Rendering with MPI](#parallel-rendering-with-mpi) section for more
+info). Once a device is created, you can call
``` {.cpp}
void ospDeviceSet1i(OSPDevice, const char *id, int val);
@@ -284,11 +300,12 @@ void ospDeviceSetString(OSPDevice, const char *id, const char *val);
to set parameters on the device. The following parameters can be set on
all devices:
-| Type | Name | Description |
-|:-----|:-----------|:----------------------------------------------------------|
-| int | numThreads | number of threads which OSPRay should use |
-| int | logLevel | logging level |
-| int | debug | set debug mode; equivalent to logLevel=2 and numThreads=1 |
+| Type | Name | Description |
+|:-----|:------------|:------------------------------------------------------------------------------------------------------------------------|
+| int | numThreads | number of threads which OSPRay should use |
+| int | logLevel | logging level |
+| int | debug | set debug mode; equivalent to logLevel=2 and numThreads=1 |
+| int | setAffinity | bind software threads to hardware threads if set to 1; 0 disables binding omitting the parameter will let OSPRay choose |
: Parameters shared by all devices.
@@ -327,29 +344,77 @@ environment variables for easy changes to OSPRay's behavior without
needing to change the application (variables are prefixed by convention
with "`OSPRAY_`"):
-| Variable | Description |
-|:--------------------|:---------------------------------|
-| OSPRAY\_THREADS | equivalent to `--osp:numthreads` |
-| OSPRAY\_LOG\_LEVEL | equivalent to `--osp:loglevel` |
-| OSPRAY\_LOG\_OUTPUT | equivalent to `--osp:logoutput` |
-| OSPRAY\_DEBUG | equivalent to `--osp:debug` |
+| Variable | Description |
+|:----------------------|:----------------------------------|
+| OSPRAY\_THREADS | equivalent to `--osp:numthreads` |
+| OSPRAY\_LOG\_LEVEL | equivalent to `--osp:loglevel` |
+| OSPRAY\_LOG\_OUTPUT | equivalent to `--osp:logoutput` |
+| OSPRAY\_DEBUG | equivalent to `--osp:debug` |
+| OSPRAY\_SET\_AFFINITY | equivalent to `--osp:setaffinity` |
: Environment variables interpreted by OSPRay.
-### Handling Error and Status Messages from OSPRay
+### Error Handling and Status Messages
+
+The following errors are currently used by OSPRay:
+
+| Name | Description |
+|:------------------------|:------------------------------------------------------|
+| OSP\_NO\_ERROR | no error occured |
+| OSP\_UNKNOWN\_ERROR | an unknown error occured |
+| OSP\_INVALID\_ARGUMENT | an invalid argument was specified |
+| OSP\_INVALID\_OPERATION | the operation is not allowed for the specified object |
+| OSP\_OUT\_OF\_MEMORY | there is not enough memory to execute the command |
+| OSP\_UNSUPPORTED\_CPU | the CPU is not supported (minimum ISA is SSE4.1) |
+
+: Possible error codes, i.e. valid named constants of type `OSPError`.
+
+These error codes are either directly return by some API functions, or
+are recorded to be later queried by the application via
+
+``` {.cpp}
+OSPError ospDeviceGetLastErrorCode(OSPDevice);
+```
+
+A more descriptive error message can be queried by calling
+
+``` {.cpp}
+const char* ospDeviceGetLastErrorMsg(OSPDevice);
+```
+
+Alternatively, the application can also register a callback function of
+type
+
+``` {.cpp}
+typedef void (*OSPErrorFunc)(OSPError, const char* errorDetails);
+```
+
+via
+
+``` {.cpp}
+void ospDeviceSetErrorFunc(OSPDevice, OSPErrorFunc);
+```
+
+to get notified when errors occur.
Applications may be interested in messages which OSPRay emits, whether
for debugging or logging events. Applications can call
``` {.cpp}
-void ospDeviceSetErrorMsgFunc(OSPDevice, OSPErrorMsgFunc callback);
+void ospDeviceSetStatusFunc(OSPDevice, OSPStatusFunc);
+```
+
+in order to register a callback function of type
+
+``` {.cpp}
+typedef void (*OSPStatusFunc)(const char* messageText);
```
-in order to set the callback OSPRay will use to emit error messages. By
-default, OSPRay uses a callback which does nothing, so any output
-desired by an application will require that a callback be provided. Note
-that callbacks for C++ std::cout and std::cerr can be alternatively set
-through ospInit() or OSPRAY\_LOG\_OUTPUT environment variable.
+which OSPRay will use to emit status messages. By default, OSPRay uses a
+callback which does nothing, so any output desired by an application
+will require that a callback is provided. Note that callbacks for C++
+`std::cout` and `std::cerr` can be alternatively set through `ospInit()`
+or the `OSPRAY_LOG_OUTPUT` environment variable.
### Loading OSPRay Extensions at Runtime
@@ -359,12 +424,12 @@ implemented in shared libraries. To load plugin `name` from
`ospray_module_.dll` (on Windows) use
``` {.cpp}
-int32_t ospLoadModule(const char *name);
+OSPError ospLoadModule(const char *name);
```
Modules are searched in OS-dependent paths, which include the
-application directory. `ospLoadModule` returns `0` if the plugin could
-be loaded and an error code `> 0` otherwise.
+application directory. `ospLoadModule` returns `OSP_NO_ERROR` if the
+plugin could be successfully loaded.
Objects
-------
@@ -561,9 +626,9 @@ rearrangement of voxel data it cannot be shared the with the application
anymore, but has to be transferred to OSPRay via
``` {.cpp}
-int ospSetRegion(OSPVolume, void *source,
- const vec3i ®ionCoords,
- const vec3i ®ionSize);
+OSPError ospSetRegion(OSPVolume, void *source,
+ const vec3i ®ionCoords,
+ const vec3i ®ionSize);
```
The voxel data pointed to by `source` is copied into the given volume
@@ -571,10 +636,9 @@ starting at position `regionCoords`, must be of size `regionSize` and be
placed in memory in XYZ order. Note that OSPRay distinguishes between
volume data and volume parameters. This function must be called only
after all volume parameters (in particular `dimensions` and `voxelType`,
-see below) have been set and *before* `ospCommit(volume)` is called.
-Memory for the volume is allocated on the first call to this function.
-If allocation is unsuccessful or the region size is invalid, the return
-value is `0`, and non-zero otherwise.
+see below) have been set and *before* `ospCommit(volume)` is called. If
+necessary then memory for the volume is allocated on the first call to
+this function.
The common parameters understood by both structured volume variants are
summarized in the table below. If `voxelRange` is not provided for a
@@ -653,13 +717,13 @@ A traditional triangle mesh (indexed face set) geometry is created by
calling `ospNewGeometry` with type string "`triangles`". Once created, a
triangle mesh recognizes the following parameters:
-| Type | Name | Description |
-|:---------------------|:----------------|:---------------------------------------------------------|
-| vec3f(a)\[\] | vertex | [data](#data) array of vertex positions |
-| vec3f(a)\[\] | vertex.normal | [data](#data) array of vertex normals |
-| vec4f\[\]/vec3fa\[\] | vertex.color | [data](#data) array of vertex colors (RGBA/RGB) |
-| vec2f\[\] | vertex.texcoord | [data](#data) array of vertex texture coordinates |
-| vec3i(a)\[\] | index | [data](#data) array of triangle indices (into vertex.\*) |
+| Type | Name | Description |
+|:-----------------------|:----------------|:---------------------------------------------------------|
+| vec3f(a)\[\] | vertex | [data](#data) array of vertex positions |
+| vec3f(a)\[\] | vertex.normal | [data](#data) array of vertex normals |
+| vec4f\[\] / vec3fa\[\] | vertex.color | [data](#data) array of vertex colors (RGBA/RGB) |
+| vec2f\[\] | vertex.texcoord | [data](#data) array of vertex texture coordinates |
+| vec3i(a)\[\] | index | [data](#data) array of triangle indices (into vertex.\*) |
: Parameters defining a triangle mesh geometry.
@@ -676,10 +740,10 @@ of specifying the data of center position and radius within a
Parameters defining a spheres geometry.
-
-
-
-
+
+
+
+
int |
@@ -720,6 +784,18 @@ of specifying the data of center position and radius within a
-1 |
offset (in bytes) of each sphere's "float radius" within the spheres array (-1 means disabled and use radius ) |
+
+vec4f[] / vec3f(a)[] |
+color |
+NULL |
+data array of colors (RGBA/RGB), color is constant for each sphere |
+
+
+vec2f[] |
+texcoord |
+NULL |
+data array of texture coordinates, coordinate is constant for each sphere |
+
@@ -739,10 +815,10 @@ listed in the table below.
Parameters defining a cylinders geometry.
-
+
-
-
+
+
int |
bytes_per_cylinder |
-28 |
+24 |
size (in bytes) of each cylinder within the cylinders array |
@@ -789,11 +865,27 @@ listed in the table below.
-1 |
offset (in bytes) of each cylinder's "float radius" within the cylinders array (-1 means disabled and use radius instead) |
+
+vec4f[] / vec3f(a)[] |
+color |
+NULL |
+data array of colors (RGBA/RGB), color is constant for each cylinder |
+
+
+OSPData |
+texcoord |
+NULL |
+data array of texture coordinates, in pairs (each a vec2f at vertex v0 and v1) |
+
: Parameters defining a cylinders geometry.
+For texturing each cylinder is seen as a 1D primitive, i.e. a line
+segment: the 2D texture coordinates at its vertices v0 and v1 are
+linearly interpolated.
+
### Streamlines
A geometry consisting of multiple stream lines of constant radius is
@@ -915,10 +1007,10 @@ special parameters:
Special parameters understood by the SciVis renderer.
-
+
-
-
+
+
-vec3f |
+float / vec3f / vec4f |
bgColor |
-white |
-background color (RGB) |
+black, transparent |
+background color and alpha (RGBA) |
-bool |
-backgroundEnabled |
-true |
-whether to color the background with bgColor |
-
-
OSPTexture2D |
maxDepthTexture |
NULL |
@@ -986,6 +1072,13 @@ Note that the intensity (and color) of AO is controlled via an [ambient
light](#ambient-light). If `aoSamples` is zero (the default) then
ambient lights cause ambient illumination (without occlusion).
+Per default the background of the rendered image will be transparent
+black, i.e. the alpha channel holds the opacity of the rendered objects.
+This facilitates transparency-aware blending of the image with an
+arbitraty background image by the application. The parameter `bgColor`
+can be used to already blend with a constant background color (and
+alpha) during rendering.
+
The SciVis renderer supports depth composition with images of other
renderers, for example to incorporate help geometries of a 3D UI that
were rendered with OpenGL. The screen-sized [texture](#texture)
@@ -1589,7 +1682,7 @@ values of `OSPFrameBufferChannel` listed in the table below.
| Name | Description |
|:------------------|:--------------------------------------------------------------|
| OSP\_FB\_COLOR | RGB color including alpha |
-| OSP\_FB\_DEPTH | Euclidean distance to the camera (*not* to the image plane) |
+| OSP\_FB\_DEPTH | euclidean distance to the camera (*not* to the image plane) |
| OSP\_FB\_ACCUM | accumulation buffer for progressive refinement |
| OSP\_FB\_VARIANCE | estimate of the current variance, see [rendering](#rendering) |
@@ -1625,8 +1718,8 @@ void ospFreeFrameBuffer(OSPFrameBuffer);
Because OSPRay uses reference counting internally the framebuffer may
not immediately be deleted at this time.
-The application can map the given channel of a framebuffer -- and thus
-access the stored pixel information -- via
+The application can map the given channel of a framebuffer – and thus
+access the stored pixel information – via
``` {.cpp}
const void *ospMapFrameBuffer(OSPFrameBuffer,
@@ -1698,6 +1791,136 @@ rendered image, otherwise `inf` is returned. The estimated variance can
be used by the application as a quality indicator and thus to decide
whether to stop or to continue progressive rendering.
+Parallel Rendering with MPI
+===========================
+
+OSPRay has the ability to scale to multiple nodes in a cluster via MPI.
+This enables applications to take advantage of larger compute and memory
+resources when available.
+
+Prerequisites for MPI Mode
+--------------------------
+
+In addition to the standard build requirements of OSPRay, you must have
+the following items available in your environment in order to build&run
+OSPRay in MPI mode:
+
+- An MPI enabled multi-node environment, such as an HPC cluster
+- An MPI implementation you can build against (i.e. Intel MPI,
+ MVAPICH2, etc...)
+
+Enabling the MPI module in your build
+-------------------------------------
+
+To build the MPI module the CMake variable `OSPRAY_MODULE_MPI` must be
+enabled, which can be done directly on the command line (with `-D...`)
+or through a configuration dialog (`ccmake`, `cmake-gui`), see also
+\[Compiling OSPRay\].
+
+This will trigger CMake to go look for an MPI implementation in your
+environment. You can then inspect the CMake value of `MPI_LIBRARY` to
+make sure that CMake found your MPI build environment correctly.
+
+This will result in an OSPRay module being built. To enable using it,
+applications will need to either link `libospray_module_mpi`, or call
+
+``` {.cpp}
+ospLoadModule("mpi");
+```
+
+before initializing OSPRay.
+
+Modes of using OSPRay's MPI features
+------------------------------------
+
+OSPRay provides two ways of using MPI to scale up rendering: offload and
+distributed.
+
+The "offload" rendering mode is where a single (not-distributed) calling
+application treats the OSPRay API the same as with local rendering.
+However, OSPRay uses multiple MPI connected nodes to evenly distribute
+frame rendering work, where each node contains a full copy of all scene
+data. This method is most effective for scenes which can fit into
+memory, but are very expensive to render: for example, path tracing with
+many samples-per-pixel is very compute heavy, making it a good situation
+to use the offload feature. This can be done with any application which
+already uses OSPRay for local rendering without the need for any code
+changes.
+
+The "distributed" rendering mode is where a MPI distributed application
+(such as a scientific simulation) uses OSPRay collectively to render
+frames. In this case, the API expects all calls (both created objects
+and parameters) to be the same on every application rank, except each
+rank can specify arbitrary geometries and volumes. Each renderer will
+have its own limitations on the topology of the data (i.e. overlapping
+data regions, concave data, etc.), but the API calls will only differ
+for scene objects. Thus all other calls (i.e. setting camera, creating
+framebuffer, rendering frame, etc.) will all be assumed to be identical,
+but only rendering a frame and committing the model must be in
+lock-step. This mode targets using all available aggregate memory for
+very large scenes and for "in-situ" visualization where the data is
+already distributed by a simulation app.
+
+Running an application with the "offload" device
+------------------------------------------------
+
+As an example, our sample viewer can be run as a single application
+which offloads rendering work to multiple MPI processes running on
+multiple machines.
+
+The example apps are setup to be launched in two different setups. In
+either setup, the application must initialize OSPRay with the offload
+device. This can be done by creating an "`mpi_offload`" device and
+setting it as the current device (via the `ospSetCurrentDevice()`
+function), or passing either "`--osp:mpi`" or "`--osp:mpi-offload`" as a
+command line parameter to `ospInit()`. Note that passing a command line
+parameter will automatically call `ospLoadModule("mpi")` to load the MPI
+module, while the application will have to load the module explicitly if
+using `ospNewDevice()`.
+
+**Option 1: single MPI launch**
+
+OSPRay is initialized with the `ospInit()` function call which takes
+command line arguments in and configures OSPRay based on what it finds.
+In this setup, the app is launched across all ranks, but workers will
+never return from `ospInit()`, essentially turning the application into
+a worker process for OSPRay. Here's an example of running the
+ospVolumeViewer data-replicated, using `c1`-`c4` as compute nodes and
+`localhost` the process running the viewer itself:
+
+``` {.cpp}
+% mpirun -perhost 1 -hosts localhost,c1,c2,c3,c4 ./ospExampleViewer [scene_file] --osp:mpi
+```
+
+**Option 2: separate app/worker launches**
+
+The second option is to explicitly launch the app on rank 0 and worker
+ranks on the other nodes. This is done by running `ospray_mpi_worker` on
+worker nodes and the application on the display node. Here's the same
+example above using this syntax:
+
+``` {.cpp}
+% mpirun -perhost 1 -hosts localhost ./ospExampleViewer [scene_file] --osp:mpi \
+ : -hosts c1,c2,c3,c4 ./ospray_mpi_worker --osp:mpi
+```
+
+This method of launching the application and OSPRay worker separately
+works best for applications which do not immediately call `ospInit()` in
+thier `main()` function, or for environments where application
+dependencies (such as GUI libraries) may not be available on compute
+nodes.
+
+Running an application with the "distributed" device
+----------------------------------------------------
+
+Applications using the new distributed device should initialize OSPRay
+by creating (and setting current) an "`mpi_distributed`" device or pass
+`"--osp:mpi-distributed"` as a command line argument to `ospInit()`.
+Note that due to the semantic differences the distributed device gives
+the OSPRay API, it is not expected for applications which can already
+use the offload device to correctly use the distributed device without
+changes to the application.
+
Examples
========
@@ -1705,7 +1928,7 @@ Tutorial
--------
A minimal working example demonstrating how to use OSPRay can be found
-at `apps/ospTutorial.cpp`[^6]. On Linux build it in the build\_directory
+at `apps/ospTutorial.cpp`[^6]. On Linux build it in the build directory
with
g++ ../apps/ospTutorial.cpp -I ../ospray/include -I .. ./libospray.so -Wl,-rpath,. -o ospTutorial
@@ -1717,7 +1940,7 @@ On Windows build it in the build\_directory\\\$Configuration with
Running `ospTutorial` will create two images of two triangles, rendered
with the Scientific Visualization renderer with full Ambient Occlusion.
The first image `firstFrame.ppm` shows the result after one call to
-`ospRenderFrame` -- jagged edges and noise in the shadow can be seen.
+`ospRenderFrame` – jagged edges and noise in the shadow can be seen.
Calling `ospRenderFrame` multiple times enables progressive refinement,
resulting in antialiased edges and converged shadows, shown after ten
frames in the second image `accumulatedFrames.png`.
@@ -1727,23 +1950,26 @@ frames in the second image `accumulatedFrames.png`.
![After accumulating ten
frames.](https://ospray.github.io/images/tutorial_accumulatedframe.png)
-Qt Viewer
----------
-
-OSPRay also includes a demo viewer application `ospQtViewer`, showcasing
-all features of OSPRay.
-
-![Screenshot of
-`ospQtViewer`.](https://ospray.github.io/images/QtViewer.jpg)
+Example Viewer
+--------------
-Volume Viewer
--------------
+OSPRay also includes an exemplary viewer application
+`ospExampleViewerSg`, showcasing all features of OSPRay. The Example
+Viewer uses the ImGui library for user interface controls. The viewer is
+based on a prototype OSPRay scenegraph interface where its nodes are
+displayed in the GUI and can be manipulated interactively. For instance,
+simply run it as `ospExampleViewerSg teapot.obj`.
-Additionally, OSPRay includes a demo viewer application
-`ospVolumeViewer`, which is specifically tailored for volume rendering.
+This application also functions as an OSPRay state debugger – invalid
+values will be shown in red up the hierarchy and won't change the viewer
+until corrected. You can also add new nodes where appropriate: for
+example, when "lights" is expanded right clicking on "lights" and typing
+in a light type, such as "point", will add it to the scene. Similarly,
+right clicking on "world" and creating an "Importer" node will add a new
+scene importer from a file. Changing the filename to an appropriate file
+will load the scene and propagate the resulting state.
-![Screenshot of
-`ospVolumeViewer`.](https://ospray.github.io/images/VolumeViewer.png)
+
Demos
-----
@@ -1753,8 +1979,7 @@ at the [OSPRay Demos and Examples](http://www.ospray.org/demos.html)
page.
[^1]: For example, if OSPRay is in `~/Projects/ospray`, ISPC will also
- be searched in `~/Projects/ispc-v1.9.1-linux` and
- `~/Projects/ispc-v1.9.0-linux`
+ be searched in `~/Projects/ispc-v1.9.1-linux`
[^2]: The [HDRI Light](#hdri-light) is an exception, it knows about
`intensity`, but not about `color`.
diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt
index aa515bdf42..01fda20b69 100644
--- a/apps/CMakeLists.txt
+++ b/apps/CMakeLists.txt
@@ -21,6 +21,7 @@ INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}
${CMAKE_CURRENT_LIST_DIR}
common
+ common/boost.any
)
# common utilities
@@ -50,42 +51,7 @@ IF(OSPRAY_APPS_ENABLE_SCRIPTING)
ADD_SUBDIRECTORY(common/script)
ENDIF()
-# mini-scene graph viewer implemented with GLUT
-OPTION(OSPRAY_APPS_GLUTVIEWER "Build ospGlutViewer application." ON)
-
-IF(OSPRAY_APPS_GLUTVIEWER)
- INCLUDE(glut)
- # common utility classes for GLUT-based 3D viewer widget
- ADD_SUBDIRECTORY(common/widgets)
- ADD_SUBDIRECTORY(glutViewer)
-ENDIF()
-
-# NOTE(jda) - Disable Qt based viewers when on OS X using ICC due to
-# unresolved issues
-# qt-based viewer for geometry (and soon volumes)
-IF(NOT (APPLE AND OSPRAY_COMPILER_ICC) AND NOT WIN32)
- OPTION(OSPRAY_APPS_QTVIEWER "Build ospQtViewer (Qt-based model viewer)" ON)
- IF (OSPRAY_APPS_QTVIEWER)
- ADD_SUBDIRECTORY(qtViewer)
- ENDIF()
-ENDIF()
-
-# volume viewer application
-IF(NOT (APPLE AND OSPRAY_COMPILER_ICC))
- OPTION(OSPRAY_APPS_VOLUMEVIEWER "Build ospVolumeViewer application." ON)
- IF(OSPRAY_APPS_VOLUMEVIEWER)
- ADD_SUBDIRECTORY(volumeViewer)
- ENDIF()
-ENDIF()
-
-# -------------------------------------------------------
-# redistribute QT on Windows
-# -------------------------------------------------------
-IF (OSPRAY_INSTALL_DEPENDENCIES AND WIN32 AND
- (OSPRAY_APPS_QTVIEWER OR OSPRAY_APPS_VOLUMEVIEWER))
- FOREACH(QT_COMPONENT QTCORE QTGUI QTOPENGL)
- STRING(REGEX REPLACE lib$ dll QT_DLL ${QT_${QT_COMPONENT}_LIBRARY_RELEASE})
- INSTALL(PROGRAMS ${QT_DLL}
- DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT redist)
- ENDFOREACH()
+OPTION(OSPRAY_APPS_EXAMPLEVIEWER "Build example viewer apps" ON)
+IF (OSPRAY_APPS_EXAMPLEVIEWER)
+ ADD_SUBDIRECTORY(exampleViewer)
ENDIF()
diff --git a/apps/bench/BenchScriptHandler.cpp b/apps/bench/BenchScriptHandler.cpp
index b250bdec22..13829e434e 100644
--- a/apps/bench/BenchScriptHandler.cpp
+++ b/apps/bench/BenchScriptHandler.cpp
@@ -30,6 +30,8 @@
#include "BenchScriptHandler.h"
+namespace bench {
+
BenchScriptHandler::BenchScriptHandler(std::shared_ptr &fixture)
: OSPRayScriptHandler(fixture->model.handle(), fixture->renderer.handle(), fixture->camera.handle())
{
@@ -128,6 +130,8 @@ void BenchScriptHandler::registerScriptTypes() {
chai.add(m);
}
+}
+
#endif
diff --git a/apps/bench/BenchScriptHandler.h b/apps/bench/BenchScriptHandler.h
index 5c82ec714b..bb5f2bb70c 100644
--- a/apps/bench/BenchScriptHandler.h
+++ b/apps/bench/BenchScriptHandler.h
@@ -22,6 +22,8 @@
#include "common/script/OSPRayScriptHandler.h"
#include "OSPRayFixture.h"
+namespace bench {
+
class BenchScriptHandler : public ospray::OSPRayScriptHandler {
public:
BenchScriptHandler(std::shared_ptr &fixture);
@@ -33,5 +35,7 @@ class BenchScriptHandler : public ospray::OSPRayScriptHandler {
using BenchStats = pico_bench::Statistics;
};
+}
+
#endif
diff --git a/apps/bench/OSPRayFixture.cpp b/apps/bench/OSPRayFixture.cpp
index 4710beb25d..7e8547a050 100644
--- a/apps/bench/OSPRayFixture.cpp
+++ b/apps/bench/OSPRayFixture.cpp
@@ -46,7 +46,6 @@ void writePPM(const std::string &fileName, const int sizeX, const int sizeY,
fprintf(file, "\n");
fclose(file);
}
-}
OSPRayFixture::OSPRayFixture(cpp::Renderer r, cpp::Camera c, cpp::Model m)
: renderer(r), camera(c), model(m), width(DEFAULT_WIDTH), height(DEFAULT_HEIGHT),
@@ -58,6 +57,7 @@ OSPRayFixture::OSPRayFixture(cpp::Renderer r, cpp::Camera c, cpp::Model m)
renderer.set("camera", camera);
renderer.commit();
}
+
pico_bench::Statistics
OSPRayFixture::benchmark(const size_t warmUpFrames, const size_t benchFrames) {
const size_t warmup = warmUpFrames == 0 ? defaultWarmupFrames : warmUpFrames;
@@ -74,16 +74,18 @@ OSPRayFixture::benchmark(const size_t warmUpFrames, const size_t benchFrames) {
stats.time_suffix = " ms";
return stats;
}
+
void OSPRayFixture::saveImage(const std::string &fname) {
auto *lfb = (uint32_t*)fb.map(OSP_FB_COLOR);
bench::writePPM(fname + ".ppm", width, height, lfb);
fb.unmap(lfb);
}
+
void OSPRayFixture::setFrameBuffer(const int w, const int h, const int fbFlags) {
width = w > 0 ? w : width;
height = h > 0 ? h : height;
- fb = cpp::FrameBuffer(osp::vec2i{width, height}, OSP_FB_SRGBA, fbFlags);
+ fb = cpp::FrameBuffer(vec2i{width, height}, OSP_FB_SRGBA, fbFlags);
fb.clear(fbFlags);
framebufferFlags = fbFlags;
@@ -91,3 +93,4 @@ void OSPRayFixture::setFrameBuffer(const int w, const int h, const int fbFlags)
camera.commit();
}
+}
diff --git a/apps/bench/OSPRayFixture.h b/apps/bench/OSPRayFixture.h
index 41991db8a3..aa78526266 100644
--- a/apps/bench/OSPRayFixture.h
+++ b/apps/bench/OSPRayFixture.h
@@ -28,7 +28,6 @@
namespace bench {
void writePPM(const std::string &fileName, const int sizeX, const int sizeY,
const uint32_t *pixel);
-}
struct OSPRayFixture {
using Millis = std::chrono::duration>;
@@ -68,3 +67,4 @@ struct OSPRayFixture {
int framebufferFlags;
};
+}// ::bench
diff --git a/apps/bench/bench.cpp b/apps/bench/bench.cpp
index 294d8b6e7f..8e75845f55 100644
--- a/apps/bench/bench.cpp
+++ b/apps/bench/bench.cpp
@@ -22,225 +22,236 @@
#include "commandline/Utility.h"
#include "pico_bench/pico_bench.h"
-using std::cout;
-using std::endl;
-using std::string;
-
-void printUsageAndExit()
-{
- cout << "Usage: ospBenchmark [options] model_file" << endl;
-
- cout << endl << "Args:" << endl;
-
- cout << endl;
- cout << " model_file --> Scene used for benchmarking, supported types"
- << " are:" << endl;
- cout << " stl, msg, tri, xml, obj, hbp, x3d" << endl;
-
- cout << endl;
- cout << "Options:" << endl;
-
- cout << endl;
- cout << "**generic rendering options**" << endl;
-
- cout << endl;
- cout << " -i | --image --> Specify the base filename to write the"
- << " framebuffer to a file." << endl;
- cout << " If ommitted, no file will be written." << endl;
- cout << " NOTE: this option adds '.ppm' to the end of the"
- << " filename" << endl;
-
- cout << endl;
- cout << " -w | --width --> Specify the width of the benchmark frame"
- << endl;
- cout << " default: 1024" << endl;
-
- cout << endl;
- cout << " -h | --height --> Specify the height of the benchmark frame"
- << endl;
- cout << " default: 1024" << endl;
-
- cout << endl;
- cout << " -r | --renderer --> Specify the renderer to be benchmarked."
- << endl;
- cout << " Ex: -r pathtracer" << endl;
- cout << " default: ao1" << endl;
-
- /*
- * TODO: This was never used anyway?
- cout << endl;
- cout << " -bg | --background --> Specify the background color: R G B"
- << endl;
- */
-
- cout << endl;
- cout << " -wf | --warmup --> Specify the number of warmup frames: N"
- << endl;
- cout << " default: 10" << endl;
-
- cout << endl;
- cout << " -bf | --bench --> Specify the number of benchmark frames: N"
- << endl;
- cout << " default: 100" << endl;
-
- cout << endl;
- cout << " -lft | --log-frame-times --> Log frame time in ms for every frame rendered"
- << endl;
-
- cout << endl;
- cout << "**camera rendering options**" << endl;
-
- cout << endl;
- cout << " -vp | --eye --> Specify the camera eye as: ex ey ez " << endl;
-
- cout << endl;
- cout << " -vi | --gaze --> Specify the camera gaze point as: ix iy iz "
- << endl;
-
- cout << endl;
- cout << " -vu | --up --> Specify the camera up as: ux uy uz " << endl;
-
-
- cout << endl;
- cout << "**volume rendering options**" << endl;
-
- cout << endl;
- cout << " -s | --sampling-rate --> Specify the sampling rate for volumes."
- << endl;
- cout << " default: 0.125" << endl;
-
- cout << endl;
- cout << " -dr | --data-range --> Specify the data range for volumes."
- << " If not specified, then the min and max data" << endl
- << " values will be used when reading the data into memory." << endl;
- cout << " Format: low high" << endl;
-
- cout << endl;
- cout << " -tfc | --tf-color --> Specify the next color to in the transfer"
- << " function for volumes. Each entry will add to the total list of"
- << " colors in the order they are specified." << endl;
- cout << " Format: R G B A" << endl;
- cout << " Value Range: [0,1]" << endl;
-
- cout << " -tfs | --tf-scale --> Specify the opacity the transfer function"
- << " will scale to: [0,x] where x is the input value." << endl;
- cout << " default: 1.0" << endl;
-
- cout << " -tff | --tf-file --> Specify the transfer function file to use"
- << endl;
-
- cout << endl;
- cout << " -is | --surface --> Specify an isosurface at value: val "
- << endl;
-
- cout << endl;
- cout << " --help --> Print this help text" << endl;
+namespace bench {
+
+ using std::cout;
+ using std::endl;
+ using std::string;
+
+ using namespace commandline;
+
+ void printUsageAndExit()
+ {
+ cout << "Usage: ospBenchmark [options] model_file" << endl;
+
+ cout << endl << "Args:" << endl;
+
+ cout << endl;
+ cout << " model_file --> Scene used for benchmarking, supported types"
+ << " are:" << endl;
+ cout << " stl, msg, tri, xml, obj, hbp, x3d" << endl;
+
+ cout << endl;
+ cout << "Options:" << endl;
+
+ cout << endl;
+ cout << "**generic rendering options**" << endl;
+
+ cout << endl;
+ cout << " -i | --image --> Specify the base filename to write the"
+ << " framebuffer to a file." << endl;
+ cout << " If ommitted, no file will be written." << endl;
+ cout << " NOTE: this option adds '.ppm' to the end of the"
+ << " filename" << endl;
+
+ cout << endl;
+ cout << " -w | --width --> Specify the width of the benchmark frame"
+ << endl;
+ cout << " default: 1024" << endl;
+
+ cout << endl;
+ cout << " -h | --height --> Specify the height of the benchmark frame"
+ << endl;
+ cout << " default: 1024" << endl;
+
+ cout << endl;
+ cout << " -r | --renderer --> Specify the renderer to be benchmarked."
+ << endl;
+ cout << " Ex: -r pathtracer" << endl;
+ cout << " default: ao1" << endl;
+
+ /*
+ * TODO: This was never used anyway?
+ cout << endl;
+ cout << " -bg | --background --> Specify the background color: R G B"
+ << endl;
+ */
+
+ cout << endl;
+ cout << " -wf | --warmup --> Specify the number of warmup frames: N"
+ << endl;
+ cout << " default: 10" << endl;
+
+ cout << endl;
+ cout << " -bf | --bench --> Specify the number of benchmark frames: N"
+ << endl;
+ cout << " default: 100" << endl;
+
+ cout << endl;
+ cout << " -lft | --log-frame-times --> Log frame time in ms for every frame rendered"
+ << endl;
+
+ cout << endl;
+ cout << "**camera rendering options**" << endl;
+
+ cout << endl;
+ cout << " -vp | --eye --> Specify the camera eye as: ex ey ez " << endl;
+
+ cout << endl;
+ cout << " -vi | --gaze --> Specify the camera gaze point as: ix iy iz "
+ << endl;
+
+ cout << endl;
+ cout << " -vu | --up --> Specify the camera up as: ux uy uz " << endl;
+
+
+ cout << endl;
+ cout << "**volume rendering options**" << endl;
+
+ cout << endl;
+ cout << " -s | --sampling-rate --> Specify the sampling rate for volumes."
+ << endl;
+ cout << " default: 0.125" << endl;
+
+ cout << endl;
+ cout << " -dr | --data-range --> Specify the data range for volumes."
+ << " If not specified, then the min and max data" << endl
+ << " values will be used when reading the data into memory." << endl;
+ cout << " Format: low high" << endl;
+
+ cout << endl;
+ cout << " -tfc | --tf-color --> Specify the next color to in the transfer"
+ << " function for volumes. Each entry will add to the total list of"
+ << " colors in the order they are specified." << endl;
+ cout << " Format: R G B A" << endl;
+ cout << " Value Range: [0,1]" << endl;
+
+ cout << " -tfs | --tf-scale --> Specify the opacity the transfer function"
+ << " will scale to: [0,x] where x is the input value." << endl;
+ cout << " default: 1.0" << endl;
+
+ cout << " -tff | --tf-file --> Specify the transfer function file to use"
+ << endl;
+
+ cout << endl;
+ cout << " -is | --surface --> Specify an isosurface at value: val "
+ << endl;
+
+ cout << endl;
+ cout << " --help --> Print this help text" << endl;
#ifdef OSPRAY_APPS_ENABLE_SCRIPTING
- cout << endl;
- cout << " --script --> Specify a script file to drive the benchmarker.\n"
- << " In a script you can access the parsed world and command\n"
- << " line benchmark configuration via the following variables:\n"
- << " defaultFixture -> benchmark settings from the commandline\n"
- << " m -> world model parsed from command line scene args\n"
- << " c -> camera set from command line args\n"
- << " r -> renderer set from command line args\n";
+ cout << endl;
+ cout << " --script --> Specify a script file to drive the benchmarker.\n"
+ << " In a script you can access the parsed world and command\n"
+ << " line benchmark configuration via the following variables:\n"
+ << " defaultFixture -> benchmark settings from the commandline\n"
+ << " m -> world model parsed from command line scene args\n"
+ << " c -> camera set from command line args\n"
+ << " r -> renderer set from command line args\n";
#endif
- exit(0);
-}
-
-std::string imageOutputFile = "";
-std::string scriptFile = "";
-size_t numWarmupFrames = 0;
-size_t numBenchFrames = 0;
-bool logFrameTimes = false;
-// This is the fixture setup by the command line arguments
-std::shared_ptr cmdlineFixture;
-
-void parseCommandLine(int argc, const char *argv[])
-{
- using namespace ospcommon;
- using namespace ospray::cpp;
- if (argc <= 1) {
- printUsageAndExit();
+ exit(0);
}
- int width = 0;
- int height = 0;
- for (int i = 1; i < argc; ++i) {
- string arg = argv[i];
- if (arg == "--help") {
+ std::string imageOutputFile = "";
+ std::string scriptFile = "";
+ size_t numWarmupFrames = 0;
+ size_t numBenchFrames = 0;
+ bool logFrameTimes = false;
+ // This is the fixture setup by the command line arguments
+ std::shared_ptr cmdlineFixture;
+
+ void parseCommandLine(int argc, const char *argv[])
+ {
+ using namespace ospcommon;
+ using namespace ospray::cpp;
+ if (argc <= 1) {
printUsageAndExit();
- } else if (arg == "-i" || arg == "--image") {
- imageOutputFile = argv[++i];
- } else if (arg == "-w" || arg == "--width") {
- width = atoi(argv[++i]);
- } else if (arg == "-h" || arg == "--height") {
- height = atoi(argv[++i]);
- } else if (arg == "-wf" || arg == "--warmup") {
- numWarmupFrames = atoi(argv[++i]);
- } else if (arg == "-bf" || arg == "--bench") {
- numBenchFrames = atoi(argv[++i]);
- } else if (arg == "-lft" || arg == "--log-frame-times") {
- logFrameTimes = true;
- } else if (arg == "--script") {
- scriptFile = argv[++i];
}
- }
- auto ospObjs = parseWithDefaultParsers(argc, argv);
+ int width = 0;
+ int height = 0;
+ for (int i = 1; i < argc; ++i) {
+ string arg = argv[i];
+ if (arg == "--help") {
+ printUsageAndExit();
+ } else if (arg == "-i" || arg == "--image") {
+ imageOutputFile = argv[++i];
+ } else if (arg == "-w" || arg == "--width") {
+ width = atoi(argv[++i]);
+ } else if (arg == "-h" || arg == "--height") {
+ height = atoi(argv[++i]);
+ } else if (arg == "-wf" || arg == "--warmup") {
+ numWarmupFrames = atoi(argv[++i]);
+ } else if (arg == "-bf" || arg == "--bench") {
+ numBenchFrames = atoi(argv[++i]);
+ } else if (arg == "-lft" || arg == "--log-frame-times") {
+ logFrameTimes = true;
+ } else if (arg == "--script") {
+ scriptFile = argv[++i];
+ }
+ }
- std::deque model;
- Renderer renderer;
- Camera camera;
- std::tie(std::ignore, model, renderer, camera) = ospObjs;
- cmdlineFixture = std::make_shared(renderer, camera, model[0]);
- if (width > 0 || height > 0) {
- cmdlineFixture->setFrameBuffer(width, height);
- }
- // Set the default warm up and bench frames
- if (numWarmupFrames > 0) {
- cmdlineFixture->defaultWarmupFrames = numWarmupFrames;
- }
- if (numBenchFrames > 0){
- cmdlineFixture->defaultBenchFrames = numBenchFrames;
+ auto ospObjs = parseWithDefaultParsers(argc, argv);
+
+ std::deque model;
+ Renderer renderer;
+ Camera camera;
+ std::tie(std::ignore, model, renderer, camera) = ospObjs;
+
+ cmdlineFixture = std::make_shared(renderer, camera, model[0]);
+ if (width > 0 || height > 0) {
+ cmdlineFixture->setFrameBuffer(width, height);
+ }
+ // Set the default warm up and bench frames
+ if (numWarmupFrames > 0) {
+ cmdlineFixture->defaultWarmupFrames = numWarmupFrames;
+ }
+ if (numBenchFrames > 0){
+ cmdlineFixture->defaultBenchFrames = numBenchFrames;
+ }
}
-}
-int main(int argc, const char *argv[]) {
- ospInit(&argc, argv);
- parseCommandLine(argc, argv);
-
- if (scriptFile.empty()) {
- // If we don't have a script do this, otherwise run the script
- // and let it setup bench scenes and benchmrk them and so on
- auto stats = cmdlineFixture->benchmark();
- if (logFrameTimes) {
- for (size_t i = 0; i < stats.size(); ++i) {
- std::cout << stats[i].count() << stats.time_suffix << "\n";
- }
+ extern "C" int main(int argc, const char *argv[]) {
+ int init_error = ospInit(&argc, argv);
+ if (init_error != OSP_NO_ERROR) {
+ std::cerr << "FATAL ERROR DURING INITIALIZATION!" << std::endl;
+ return init_error;
}
- std::cout << "Frame Time " << stats << "\n"
- << "FPS Statistics:\n"
- << "\tmax: " << 1000.0 / stats.min().count() << " fps\n"
- << "\tmin: " << 1000.0 / stats.max().count() << " fps\n"
- << "\tmedian: " << 1000.0 / stats.median().count() << " fps\n"
- << "\tmean: " << 1000.0 / stats.mean().count() << " fps\n";
- } else {
+
+ parseCommandLine(argc, argv);
+
+ if (scriptFile.empty()) {
+ // If we don't have a script do this, otherwise run the script
+ // and let it setup bench scenes and benchmrk them and so on
+ auto stats = cmdlineFixture->benchmark();
+ if (logFrameTimes) {
+ for (size_t i = 0; i < stats.size(); ++i) {
+ std::cout << stats[i].count() << stats.time_suffix << "\n";
+ }
+ }
+ std::cout << "Frame Time " << stats << "\n"
+ << "FPS Statistics:\n"
+ << "\tmax: " << 1000.0 / stats.min().count() << " fps\n"
+ << "\tmin: " << 1000.0 / stats.max().count() << " fps\n"
+ << "\tmedian: " << 1000.0 / stats.median().count() << " fps\n"
+ << "\tmean: " << 1000.0 / stats.mean().count() << " fps\n";
+ } else {
#ifdef OSPRAY_APPS_ENABLE_SCRIPTING
- // The script will be responsible for setting up the benchmark config
- // and calling `benchmark(N)` to benchmark the scene
- BenchScriptHandler scriptHandler(cmdlineFixture);
- scriptHandler.runScriptFromFile(scriptFile);
+ // The script will be responsible for setting up the benchmark config
+ // and calling `benchmark(N)` to benchmark the scene
+ BenchScriptHandler scriptHandler(cmdlineFixture);
+ scriptHandler.runScriptFromFile(scriptFile);
#else
- throw std::runtime_error("You must build with OSPRAY_APPS_ENABLE_SCRIPTING=ON "
- "to use scripting");
+ throw std::runtime_error("You must build with OSPRAY_APPS_ENABLE_SCRIPTING=ON "
+ "to use scripting");
#endif
- }
+ }
- if (!imageOutputFile.empty()) {
- cmdlineFixture->saveImage(imageOutputFile);
+ if (!imageOutputFile.empty()) {
+ cmdlineFixture->saveImage(imageOutputFile);
+ }
+ return 0;
}
- return 0;
-}
+}
diff --git a/apps/common/commandline/LightsParser.cpp b/apps/common/commandline/LightsParser.cpp
index ee9bb798d8..f019bf324b 100644
--- a/apps/common/commandline/LightsParser.cpp
+++ b/apps/common/commandline/LightsParser.cpp
@@ -15,56 +15,55 @@
// ======================================================================== //
#include "LightsParser.h"
-
#include
-
#include
-
#include
-using namespace ospcommon;
+namespace commandline {
-DefaultLightsParser::DefaultLightsParser(ospray::cpp::Renderer renderer) :
- renderer(renderer),
- defaultDirLight_direction(.3, -1, -.2), defaultDirLight_intensity(3.14f)
-{
-}
+ using namespace ospcommon;
-bool DefaultLightsParser::parse(int ac, const char **&av)
-{
- std::vector lights;
+ DefaultLightsParser::DefaultLightsParser(ospray::cpp::Renderer renderer) :
+ renderer(renderer),
+ defaultDirLight_direction(.3, -1, -.2), defaultDirLight_intensity(3.14f)
+ {
+ }
+
+ bool DefaultLightsParser::parse(int ac, const char **&av)
+ {
+ std::vector lights;
- int HDRI_up = 1;//y
- float HDRI_intensity = 0.f;
- const char * HDRI_file_name;
- vec4f ambient(.85,.9,1,.2*3.14);
+ int HDRI_up = 1;//y
+ float HDRI_intensity = 0.f;
+ const char * HDRI_file_name;
+ vec4f ambient(.85,.9,1,.2*3.14);
- for (int i = 1; i < ac; i++) {
- const std::string arg = av[i];
- if (arg == "--sun-dir") {
- if (!strcmp(av[i+1],"none")) {
- ++i;
- defaultDirLight_direction = vec3f(0.f);
- } else {
- defaultDirLight_direction.x = atof(av[++i]);
- defaultDirLight_direction.y = atof(av[++i]);
- defaultDirLight_direction.z = atof(av[++i]);
- }
- } else if (arg == "--sun-int") {
+ for (int i = 1; i < ac; i++) {
+ const std::string arg = av[i];
+ if (arg == "--sun-dir") {
+ if (!strcmp(av[i+1],"none")) {
+ ++i;
+ defaultDirLight_direction = vec3f(0.f);
+ } else {
+ defaultDirLight_direction.x = atof(av[++i]);
+ defaultDirLight_direction.y = atof(av[++i]);
+ defaultDirLight_direction.z = atof(av[++i]);
+ }
+ } else if (arg == "--sun-int") {
defaultDirLight_intensity = atof(av[++i]);
- } else if (arg == "--ambient") {
+ } else if (arg == "--ambient") {
ambient.x = atof(av[++i]);
ambient.y = atof(av[++i]);
ambient.z = atof(av[++i]);
ambient.w = atof(av[++i]);
- } else if (arg == "--hdri-light") {
+ } else if (arg == "--hdri-light") {
if (i+2 >= ac)
throw std::runtime_error("Not enough arguments! Usage:\n\t"
- "--hdri-light .(pfm|ppm)");
+ "--hdri-light .(pfm|ppm)");
HDRI_intensity = atof(av[++i]);
HDRI_file_name = av[++i];
- } else if (arg == "--backplate") {
+ } else if (arg == "--backplate") {
FileName imageFile(av[++i]);
ospray::miniSG::Texture2D *backplate = ospray::miniSG::loadTexture(imageFile.path(), imageFile.base());
if (backplate == NULL){
@@ -72,86 +71,88 @@ bool DefaultLightsParser::parse(int ac, const char **&av)
}
OSPTexture2D ospBackplate = ospray::miniSG::createTexture2D(backplate);
renderer.set("backplate", ospBackplate);
- } else if (arg == "--hdri-up") {
- if (!strcmp(av[i+1],"x") || !strcmp(av[i+1],"X")) {
- HDRI_up = 0;
- } else if (!strcmp(av[i+1],"y") || !strcmp(av[i+1],"Y")) {
- HDRI_up = 1;
- } else if (!strcmp(av[i+1],"z") || !strcmp(av[i+1],"Z")) {
- HDRI_up = 2;
- } else {
- printf("--hdri-up must be x, y, or z.\n");
+ } else if (arg == "--hdri-up") {
+ if (!strcmp(av[i+1],"x") || !strcmp(av[i+1],"X")) {
+ HDRI_up = 0;
+ } else if (!strcmp(av[i+1],"y") || !strcmp(av[i+1],"Y")) {
+ HDRI_up = 1;
+ } else if (!strcmp(av[i+1],"z") || !strcmp(av[i+1],"Z")) {
+ HDRI_up = 2;
+ } else {
+ printf("--hdri-up must be x, y, or z.\n");
+ }
}
- }
- }// Done reading commandline args.
+ }// Done reading commandline args.
- // HDRI environment light.
- if (HDRI_intensity > 0.f) {
- auto ospHdri = renderer.newLight("hdri");
- ospHdri.set("name", "hdri light");
- if (HDRI_up == 0) {// up = x
- ospHdri.set("up", 1.f, 0.f, 0.f);
- ospHdri.set("dir", 0.f, 0.f, 1.0f);
- } else if (HDRI_up == 1) {// up = y
- ospHdri.set("up", 0.f, 1.f, 0.f);
- ospHdri.set("dir", 1.f, 0.f, 0.0f);
- } else if (HDRI_up == 2) {// up = z
- ospHdri.set("up", 0.f, 0.f, 1.f);
- ospHdri.set("dir", 0.f, 1.f, 0.0f);
- }
- ospHdri.set( "intensity", HDRI_intensity);
- FileName imageFile(HDRI_file_name);
- ospray::miniSG::Texture2D *lightMap = ospray::miniSG::loadTexture(imageFile.path(), imageFile.base());
- if (lightMap == NULL){
- std::cout << "Failed to load hdri-light texture '" << imageFile << "'" << std::endl;
- } else {
- std::cout << "Successfully loaded hdri-light texture '" << imageFile << "'" << std::endl;
- OSPTexture2D ospLightMap = ospray::miniSG::createTexture2D(lightMap);
- ospHdri.set( "map", ospLightMap);
- ospHdri.commit();
- lights.push_back(ospHdri.handle());
+ // HDRI environment light.
+ if (HDRI_intensity > 0.f) {
+ auto ospHdri = renderer.newLight("hdri");
+ ospHdri.set("name", "hdri light");
+ if (HDRI_up == 0) {// up = x
+ ospHdri.set("up", 1.f, 0.f, 0.f);
+ ospHdri.set("dir", 0.f, 0.f, 1.0f);
+ } else if (HDRI_up == 1) {// up = y
+ ospHdri.set("up", 0.f, 1.f, 0.f);
+ ospHdri.set("dir", 1.f, 0.f, 0.0f);
+ } else if (HDRI_up == 2) {// up = z
+ ospHdri.set("up", 0.f, 0.f, 1.f);
+ ospHdri.set("dir", 0.f, 1.f, 0.0f);
+ }
+ ospHdri.set( "intensity", HDRI_intensity);
+ FileName imageFile(HDRI_file_name);
+ ospray::miniSG::Texture2D *lightMap = ospray::miniSG::loadTexture(imageFile.path(), imageFile.base());
+ if (lightMap == NULL){
+ std::cout << "Failed to load hdri-light texture '" << imageFile << "'" << std::endl;
+ } else {
+ std::cout << "Successfully loaded hdri-light texture '" << imageFile << "'" << std::endl;
+ OSPTexture2D ospLightMap = ospray::miniSG::createTexture2D(lightMap);
+ ospHdri.set( "map", ospLightMap);
+ ospHdri.commit();
+ lights.push_back(ospHdri.handle());
+ }
}
- }
- //TODO: Need to figure out where we're going to read lighting data from
+ //TODO: Need to figure out where we're going to read lighting data from
- if (defaultDirLight_direction != vec3f(0.f)
- && defaultDirLight_intensity > 0.f) {
- auto ospLight = renderer.newLight("directional");
- if (ospLight.handle() == nullptr) {
- throw std::runtime_error("Failed to create a 'DirectionalLight'!");
+ if (defaultDirLight_direction != vec3f(0.f)
+ && defaultDirLight_intensity > 0.f) {
+ auto ospLight = renderer.newLight("directional");
+ if (ospLight.handle() == nullptr) {
+ throw std::runtime_error("Failed to create a 'DirectionalLight'!");
+ }
+ ospLight.set("name", "sun");
+ ospLight.set("color", 1.f, .94f, .88f);
+ ospLight.set("direction", defaultDirLight_direction);
+ ospLight.set("intensity", defaultDirLight_intensity);
+ ospLight.set("angularDiameter", 0.53f);
+ ospLight.commit();
+ lights.push_back(ospLight.handle());
}
- ospLight.set("name", "sun");
- ospLight.set("color", 1.f, .94f, .88f);
- ospLight.set("direction", defaultDirLight_direction);
- ospLight.set("intensity", defaultDirLight_intensity);
- ospLight.set("angularDiameter", 0.53f);
- ospLight.commit();
- lights.push_back(ospLight.handle());
- }
- if (ambient.w > 0.f && reduce_max(ambient) > 0.f) {
- auto ospLight = renderer.newLight("ambient");
- if (ospLight.handle() == nullptr) {
- throw std::runtime_error("Failed to create a 'AmbientLight'!");
+ if (ambient.w > 0.f && reduce_max(ambient) > 0.f) {
+ auto ospLight = renderer.newLight("ambient");
+ if (ospLight.handle() == nullptr) {
+ throw std::runtime_error("Failed to create a 'AmbientLight'!");
+ }
+ ospLight.set("name", "ambient");
+ ospLight.set("color", ambient.x, ambient.y, ambient.z);
+ ospLight.set("intensity", ambient.w);
+ ospLight.commit();
+ lights.push_back(ospLight.handle());
}
- ospLight.set("name", "ambient");
- ospLight.set("color", ambient.x, ambient.y, ambient.z);
- ospLight.set("intensity", ambient.w);
- ospLight.commit();
- lights.push_back(ospLight.handle());
- }
- auto lightArray = ospray::cpp::Data(lights.size(), OSP_OBJECT, lights.data());
- //lightArray.commit();
- renderer.set("lights", lightArray);
+ auto lightArray = ospray::cpp::Data(lights.size(), OSP_OBJECT, lights.data());
+ //lightArray.commit();
+ renderer.set("lights", lightArray);
- finalize();
+ finalize();
- return true;
-}
+ return true;
+ }
-void DefaultLightsParser::finalize()
-{
+ void DefaultLightsParser::finalize()
+ {
+ }
+
}
diff --git a/apps/common/commandline/LightsParser.h b/apps/common/commandline/LightsParser.h
index 5188259b34..0130c53e5f 100644
--- a/apps/common/commandline/LightsParser.h
+++ b/apps/common/commandline/LightsParser.h
@@ -22,27 +22,31 @@
#include
#include
-class OSPRAY_COMMANDLINE_INTERFACE LightsParser : public CommandLineParser
-{
-public:
- virtual ~LightsParser() = default;
-};
-
-class OSPRAY_COMMANDLINE_INTERFACE DefaultLightsParser : public LightsParser
-{
-public:
- DefaultLightsParser(ospray::cpp::Renderer renderer);
- bool parse(int ac, const char **&av) override;
-
-protected:
-
- ospray::cpp::Renderer renderer;
-
- /*! when using the OBJ renderer, we create a automatic dirlight with this
- * direction; use ''--sun-dir x y z' to change */
- ospcommon::vec3f defaultDirLight_direction;
- float defaultDirLight_intensity;
-private:
-
- void finalize();
-};
+namespace commandline {
+
+ class OSPRAY_COMMANDLINE_INTERFACE LightsParser : public CommandLineParser
+ {
+ public:
+ virtual ~LightsParser() = default;
+ };
+
+ class OSPRAY_COMMANDLINE_INTERFACE DefaultLightsParser : public LightsParser
+ {
+ public:
+ DefaultLightsParser(ospray::cpp::Renderer renderer);
+ bool parse(int ac, const char **&av) override;
+
+ protected:
+
+ ospray::cpp::Renderer renderer;
+
+ /*! when using the OBJ renderer, we create a automatic dirlight with this
+ * direction; use ''--sun-dir x y z' to change */
+ ospcommon::vec3f defaultDirLight_direction;
+ float defaultDirLight_intensity;
+ private:
+
+ void finalize();
+ };
+
+}
diff --git a/apps/common/commandline/RendererParser.cpp b/apps/common/commandline/RendererParser.cpp
index 8d2a0e85a8..9fda389aff 100644
--- a/apps/common/commandline/RendererParser.cpp
+++ b/apps/common/commandline/RendererParser.cpp
@@ -16,51 +16,60 @@
#include "RendererParser.h"
-bool DefaultRendererParser::parse(int ac, const char **&av)
-{
- for (int i = 1; i < ac; i++) {
- const std::string arg = av[i];
- if (arg == "--renderer" || arg == "-r") {
- assert(i+1 < ac);
- rendererType = av[++i];
- } else if (arg == "--spp" || arg == "-spp") {
- spp = atoi(av[++i]);
- } else if (arg == "--noshadows" || arg == "-ns") {
- shadows = 0;
- } else if (arg == "--ao-samples" || arg == "-ao") {
- aoSamples = atoi(av[++i]);
- } else if (arg == "--max-depth") {
- maxDepth = atoi(av[++i]);
+namespace commandline {
+
+ bool DefaultRendererParser::parse(int ac, const char **&av)
+ {
+ for (int i = 1; i < ac; i++) {
+ const std::string arg = av[i];
+ if (arg == "--renderer" || arg == "-r") {
+ assert(i+1 < ac);
+ rendererType = av[++i];
+ } else if (arg == "--spp" || arg == "-spp") {
+ spp = atoi(av[++i]);
+ } else if (arg == "--noshadows" || arg == "-ns") {
+ shadows = 0;
+ } else if (arg == "--ao-samples" || arg == "-ao") {
+ aoSamples = atoi(av[++i]);
+ } else if (arg == "--max-depth") {
+ maxDepth = atoi(av[++i]);
+ }
}
+
+ // iw - moved finalize into create() so we can create multiple
+ // renderers from one parsed set of settings
+ // finalize();
+
+ return true;
}
- finalize();
+ ospray::cpp::Renderer DefaultRendererParser::create()
+ {
+ // iw - moved finalize into create() so we can create multiple
+ // renderers from one parsed set of settings
+ finalize();
+ return parsedRenderer;
+ }
- return true;
-}
+ void DefaultRendererParser::finalize()
+ {
+ if (rendererType.empty())
+ rendererType = "scivis";
-ospray::cpp::Renderer DefaultRendererParser::renderer()
-{
- return parsedRenderer;
-}
+ parsedRenderer = ospray::cpp::Renderer(rendererType.c_str());
-void DefaultRendererParser::finalize()
-{
- if (rendererType.empty())
- rendererType = "scivis";
+ // Set renderer defaults (if not using 'aoX' renderers)
+ if (rendererType[0] != 'a' && rendererType[1] != 'o')
+ {
+ parsedRenderer.set("aoSamples", aoSamples);
+ parsedRenderer.set("shadowsEnabled", shadows);
+ parsedRenderer.set("aoTransparencyEnabled", 1);
+ }
- parsedRenderer = ospray::cpp::Renderer(rendererType.c_str());
+ parsedRenderer.set("spp", spp);
+ parsedRenderer.set("maxDepth", maxDepth);
- // Set renderer defaults (if not using 'aoX' renderers)
- if (rendererType[0] != 'a' && rendererType[1] != 'o')
- {
- parsedRenderer.set("aoSamples", aoSamples);
- parsedRenderer.set("shadowsEnabled", shadows);
- parsedRenderer.set("aoTransparencyEnabled", 1);
+ parsedRenderer.commit();
}
- parsedRenderer.set("spp", spp);
- parsedRenderer.set("maxDepth", maxDepth);
-
- parsedRenderer.commit();
}
diff --git a/apps/common/commandline/RendererParser.h b/apps/common/commandline/RendererParser.h
index ec3790a272..6ac1b14308 100644
--- a/apps/common/commandline/RendererParser.h
+++ b/apps/common/commandline/RendererParser.h
@@ -22,31 +22,33 @@
#include
-class OSPRAY_COMMANDLINE_INTERFACE RendererParser : public CommandLineParser
-{
-public:
- virtual ~RendererParser() = default;
- virtual ospray::cpp::Renderer renderer() = 0;
-};
-
-class OSPRAY_COMMANDLINE_INTERFACE DefaultRendererParser : public RendererParser
-{
-public:
- DefaultRendererParser() = default;
- bool parse(int ac, const char **&av) override;
- ospray::cpp::Renderer renderer() override;
-
-protected:
-
- std::string rendererType;
- ospray::cpp::Renderer parsedRenderer;
-
- int spp{1};
- int maxDepth{5};
- int shadows{1};
- int aoSamples{1};
-
-private:
-
- void finalize();
-};
+namespace commandline {
+ class OSPRAY_COMMANDLINE_INTERFACE RendererParser : public CommandLineParser
+ {
+ public:
+ virtual ~RendererParser() = default;
+ virtual ospray::cpp::Renderer create() = 0;
+ };
+
+ class OSPRAY_COMMANDLINE_INTERFACE DefaultRendererParser : public RendererParser
+ {
+ public:
+ DefaultRendererParser() = default;
+ bool parse(int ac, const char **&av) override;
+ ospray::cpp::Renderer create() override;
+
+ protected:
+
+ std::string rendererType;
+ ospray::cpp::Renderer parsedRenderer;
+
+ int spp{1};
+ int maxDepth{5};
+ int shadows{1};
+ int aoSamples{1};
+
+ private:
+
+ void finalize();
+ };
+}
diff --git a/apps/common/commandline/SceneParser/MultiSceneParser.cpp b/apps/common/commandline/SceneParser/MultiSceneParser.cpp
index 31eb5aff1d..8801026ff9 100644
--- a/apps/common/commandline/SceneParser/MultiSceneParser.cpp
+++ b/apps/common/commandline/SceneParser/MultiSceneParser.cpp
@@ -26,70 +26,100 @@
# include "volume/VolumeSceneParser.h"
#endif
-using namespace ospray;
-using namespace ospcommon;
+namespace commandline {
-MultiSceneParser::MultiSceneParser(cpp::Renderer renderer) :
- renderer(renderer)
-{
-}
+ using namespace ospray;
+ using namespace ospcommon;
-bool MultiSceneParser::parse(int ac, const char **&av)
-{
- TriangleMeshSceneParser triangleMeshParser(renderer);
+ MultiSceneParser::MultiSceneParser(cpp::Renderer renderer)
+ : renderer(renderer)
+ {
+ }
+
+ bool MultiSceneParser::parse(int ac, const char **&av)
+ {
+ TriangleMeshSceneParser triangleMeshParser(renderer);
#ifdef OSPRAY_TACHYON_SUPPORT
- TachyonSceneParser tachyonParser(renderer);
+ TachyonSceneParser tachyonParser(renderer);
#endif
- ParticleSceneParser particleParser(renderer);
- StreamLineSceneParser streamlineParser(renderer);
+ ParticleSceneParser particleParser(renderer);
+ StreamLineSceneParser streamlineParser(renderer);
#ifndef _WIN32
- VolumeSceneParser volumeParser(renderer);
+ VolumeSceneParser volumeParser(renderer);
#endif
- bool gotTriangleMeshScene = triangleMeshParser.parse(ac, av);
+ bool gotTriangleMeshScene = triangleMeshParser.parse(ac, av);
#ifdef OSPRAY_TACHYON_SUPPORT
- bool gotTachyonScene = tachyonParser.parse(ac, av);
+ bool gotTachyonScene = tachyonParser.parse(ac, av);
#endif
- bool gotParticleScene = particleParser.parse(ac, av);
- bool gotStreamLineScene = streamlineParser.parse(ac, av);
+ bool gotParticleScene = particleParser.parse(ac, av);
+ bool gotStreamLineScene = streamlineParser.parse(ac, av);
#ifndef _WIN32
- bool gotVolumeScene = volumeParser.parse(ac, av);
+ bool gotVolumeScene = volumeParser.parse(ac, av);
#endif
- SceneParser *parser = nullptr;
+ SceneParser *parser = nullptr;
- if (gotTriangleMeshScene)
- parser = &triangleMeshParser;
+ if (gotTriangleMeshScene)
+ parser = &triangleMeshParser;
#ifdef OSPRAY_TACHYON_SUPPORT
- else if (gotTachyonScene)
- parser = &tachyonParser;
+ else if (gotTachyonScene)
+ parser = &tachyonParser;
#endif
- else if (gotParticleScene)
- parser = &particleParser;
- else if (gotStreamLineScene)
- parser = &streamlineParser;
+ else if (gotParticleScene)
+ parser = &particleParser;
+ else if (gotStreamLineScene)
+ parser = &streamlineParser;
#ifndef _WIN32
- else if (gotVolumeScene)
- parser = &volumeParser;
+ else if (gotVolumeScene)
+ parser = &volumeParser;
#endif
- if (parser) {
- sceneModels = parser->model();
- sceneBboxes = parser->bbox();
- } else {
- sceneModels.push_back(cpp::Model());
- sceneModels[0].commit();
+
+ if (parser) {
+ sceneModels = parser->model();
+ sceneBboxes = parser->bbox();
+ } else {
+ sceneModels.push_back(cpp::Model());
+ sceneModels[0].commit();
+ }
+
+ /* iw, mar 17 - since the above code creates a single model for
+ every file it loads we here merge them all together; the bette
+ way would be to have a single model to contain several meshes -
+ that would be faster _and_ cleaner - but that requires
+ significant changes to how above code works ... */
+ if (sceneModels.size() > 1) {
+ std::cout << "#msp: forced merging of multiple input models into a single model" << std::endl;
+ ospray::cpp::Model jointModel;
+ for (int i=0;i 1) {
+ box3f mergedBounds = ospcommon::empty;
+ for (auto box : sceneBboxes)
+ mergedBounds.extend(box);
+ sceneBboxes.clear();
+ sceneBboxes.push_back(mergedBounds);
+ }
+
+ return parser != nullptr;
}
- return parser != nullptr;
-}
+ std::deque MultiSceneParser::model() const
+ {
+ return sceneModels;
+ }
-std::deque MultiSceneParser::model() const
-{
- return sceneModels;
-}
+ std::deque MultiSceneParser::bbox() const
+ {
+ return sceneBboxes;
+ }
-std::deque MultiSceneParser::bbox() const
-{
- return sceneBboxes;
-}
\ No newline at end of file
+} // ::commandline
diff --git a/apps/common/commandline/SceneParser/MultiSceneParser.h b/apps/common/commandline/SceneParser/MultiSceneParser.h
index ffcf4f1812..467767d93d 100644
--- a/apps/common/commandline/SceneParser/MultiSceneParser.h
+++ b/apps/common/commandline/SceneParser/MultiSceneParser.h
@@ -20,23 +20,27 @@
#include
#include
-class OSPRAY_COMMANDLINE_INTERFACE MultiSceneParser : public SceneParser
-{
-public:
- MultiSceneParser(ospray::cpp::Renderer);
+namespace commandline {
- bool parse(int ac, const char **&av) override;
+ class OSPRAY_COMMANDLINE_INTERFACE MultiSceneParser : public SceneParser
+ {
+ public:
+ MultiSceneParser(ospray::cpp::Renderer);
- std::deque model() const override;
- std::deque bbox() const override;
+ bool parse(int ac, const char **&av) override;
-protected:
+ std::deque model() const override;
+ std::deque bbox() const override;
- ospray::cpp::Renderer renderer;
- std::deque sceneModels;
- std::deque sceneBboxes;
+ protected:
-private:
+ ospray::cpp::Renderer renderer;
+ std::deque sceneModels;
+ std::deque sceneBboxes;
- void finalize();
-};
+ private:
+
+ void finalize();
+ };
+
+} // ::commandline
diff --git a/apps/common/commandline/SceneParser/SceneParser.h b/apps/common/commandline/SceneParser/SceneParser.h
index 157b4a20b0..5e8d1a6d3c 100644
--- a/apps/common/commandline/SceneParser/SceneParser.h
+++ b/apps/common/commandline/SceneParser/SceneParser.h
@@ -22,10 +22,14 @@
#include
#include
-class OSPRAY_COMMANDLINE_INTERFACE SceneParser : public CommandLineParser
-{
-public:
- virtual ~SceneParser() = default;
- virtual std::deque model() const = 0;
- virtual std::deque bbox() const = 0;
-};
+namespace commandline {
+
+ class OSPRAY_COMMANDLINE_INTERFACE SceneParser : public CommandLineParser
+ {
+ public:
+ virtual ~SceneParser() = default;
+ virtual std::deque model() const = 0;
+ virtual std::deque bbox() const = 0;
+ };
+
+} // ::commandline
diff --git a/apps/common/commandline/SceneParser/particle/Model.cpp b/apps/common/commandline/SceneParser/particle/Model.cpp
index a524a45ddc..802f44346d 100644
--- a/apps/common/commandline/SceneParser/particle/Model.cpp
+++ b/apps/common/commandline/SceneParser/particle/Model.cpp
@@ -123,7 +123,9 @@ namespace ospray {
if (!fgets(line,10000,file))
throw std::runtime_error("could not fgets");
- std::cout << "#" << fileName << " (.dat.xyz format): expecting " << numAtoms << " atoms" << std::endl;
+ std::cout << "#" << fileName << " (.dat.xyz format): expecting "
+ << numAtoms << " atoms" << std::endl;
+
for (int i=0;iradius;
+ if (a.radius == 0.f)
+ a.radius = defaultRadius;
+ if (a.radius == 0.f)
+ throw std::runtime_error("particle has invalid radius. Either "
+ "specify proper radius in the def file, or "
+ "use '--radius' cmdline parameter to set a "
+ "valid radius");
+ atom.push_back(a);
+ }
+ }
+
box3f Model::getBBox() const
{
box3f bbox = empty;
diff --git a/apps/common/commandline/SceneParser/particle/Model.h b/apps/common/commandline/SceneParser/particle/Model.h
index 2d224d7334..e6fcd0abf1 100644
--- a/apps/common/commandline/SceneParser/particle/Model.h
+++ b/apps/common/commandline/SceneParser/particle/Model.h
@@ -58,6 +58,7 @@ namespace ospray {
/*! load xyz files in which there is *no* atom count, but just a
list of "type x y z" lines */
void loadXYZ2(const std::string &fileName);
+ void loadXYZ3(const std::string &fileName);
box3f getBBox() const;
diff --git a/apps/common/commandline/SceneParser/particle/ParticleSceneParser.cpp b/apps/common/commandline/SceneParser/particle/ParticleSceneParser.cpp
index 4a13b480d0..6962c3383a 100644
--- a/apps/common/commandline/SceneParser/particle/ParticleSceneParser.cpp
+++ b/apps/common/commandline/SceneParser/particle/ParticleSceneParser.cpp
@@ -22,108 +22,115 @@
#include
-using namespace ospray;
-using namespace ospcommon;
-
-// TODO: Need to convert ospray.h calls to ospray::cpp objects!
-
-// Helper functions ///////////////////////////////////////////////////////////
-
-particle::Model *createTestCube(int numPerSide)
-{
- particle::Model *m = new particle::Model;
- int type = m->getAtomType("testParticle");
- for (int z=0;zatom.push_back(a);
- }
- return m;
-}
+namespace commandline {
+
+ using namespace ospray;
+ using namespace ospcommon;
+
+ // TODO: Need to convert ospray.h calls to ospray::cpp objects!
+
+ // Helper functions ///////////////////////////////////////////////////////////
+
+ particle::Model *createTestCube(int numPerSide)
+ {
+ particle::Model *m = new particle::Model;
+ int type = m->getAtomType("testParticle");
+ for (int z=0;zatom.push_back(a);
+ }
+ return m;
+ }
-OSPData makeMaterials(OSPRenderer renderer, particle::Model *model)
-{
- int numMaterials = model->atomType.size();
- std::vector matArray(numMaterials);
- for (int i = 0; i < numMaterials; i++) {
- OSPMaterial mat = ospNewMaterial(renderer,"OBJMaterial");
- assert(mat);
- ospSet3fv(mat,"kd",&model->atomType[i]->color.x);
- ospCommit(mat);
- matArray[i] = mat;
+ OSPData makeMaterials(OSPRenderer renderer, particle::Model *model)
+ {
+ int numMaterials = model->atomType.size();
+ std::vector matArray(numMaterials);
+ for (int i = 0; i < numMaterials; i++) {
+ OSPMaterial mat = ospNewMaterial(renderer,"OBJMaterial");
+ assert(mat);
+ ospSet3fv(mat,"kd",&model->atomType[i]->color.x);
+ ospCommit(mat);
+ matArray[i] = mat;
+ }
+ OSPData data = ospNewData(numMaterials,OSP_OBJECT,matArray.data());
+ ospCommit(data);
+ return data;
}
- OSPData data = ospNewData(numMaterials,OSP_OBJECT,matArray.data());
- ospCommit(data);
- return data;
-}
-// Helper types ///////////////////////////////////////////////////////////////
+ // Helper types ///////////////////////////////////////////////////////////////
-struct DeferredLoadJob {
- DeferredLoadJob(particle::Model *model,
- const FileName &xyzFileName,
- const FileName &defFileName)
- : model(model), xyzFileName(xyzFileName), defFileName(defFileName)
- {}
+ struct DeferredLoadJob {
+ DeferredLoadJob(particle::Model *model,
+ const FileName &xyzFileName,
+ const FileName &defFileName)
+ : model(model), xyzFileName(xyzFileName), defFileName(defFileName)
+ {}
- //! the mode we still have to load
- particle::Model *model;
- //! file name of xyz file to be loaded into this model
- FileName xyzFileName;
- //! name of atom type defintion file active when this xyz file was added
- FileName defFileName;
-};
+ //! the mode we still have to load
+ particle::Model *model;
+ //! file name of xyz file to be loaded into this model
+ FileName xyzFileName;
+ //! name of atom type defintion file active when this xyz file was added
+ FileName defFileName;
+ };
-// Class definitions //////////////////////////////////////////////////////////
+ // Class definitions //////////////////////////////////////////////////////////
-ParticleSceneParser::ParticleSceneParser(cpp::Renderer renderer) :
- renderer(renderer)
-{
-}
+ ParticleSceneParser::ParticleSceneParser(cpp::Renderer renderer) :
+ renderer(renderer)
+ {
+ }
-bool ParticleSceneParser::parse(int ac, const char **&av)
-{
- bool loadedScene = false;
- std::vector particleModel;
- std::vector deferredLoadingListXYZ;
- FileName defFileName = "";
- int timeStep = 0;
-
- for (int i = 1; i < ac; i++) {
- const std::string arg = av[i];
- if (arg == "--radius") {
- ospray::particle::Model::defaultRadius = atof(av[++i]);
- } else if (arg == "--atom-defs") {
- defFileName = av[++i];
- } else if (arg == "--particle-timestep") {
- timeStep = atoi(av[++i]);
- } else {
- FileName fn = arg;
- if (fn.str() == "___CUBE_TEST___") {
- int numPerSide = atoi(av[++i]);
- particle::Model *m = createTestCube(numPerSide);
- particleModel.push_back(m);
- loadedScene = true;
- } else if (fn.ext() == "xyz") {
- particle::Model *m = new particle::Model;
- deferredLoadingListXYZ.push_back(new DeferredLoadJob(m,fn,defFileName));
- particleModel.push_back(m);
- loadedScene = true;
- } else if (fn.ext() == "xyz2") {
- particle::Model *m = new particle::Model;
- m->loadXYZ2(fn);
- particleModel.push_back(m);
- loadedScene = true;
+ bool ParticleSceneParser::parse(int ac, const char **&av)
+ {
+ bool loadedScene = false;
+ std::vector particleModel;
+ std::vector deferredLoadingListXYZ;
+ FileName defFileName = "";
+ int timeStep = 0;
+
+ for (int i = 1; i < ac; i++) {
+ const std::string arg = av[i];
+ if (arg == "--radius") {
+ ospray::particle::Model::defaultRadius = atof(av[++i]);
+ } else if (arg == "--atom-defs") {
+ defFileName = av[++i];
+ } else if (arg == "--particle-timestep") {
+ timeStep = atoi(av[++i]);
+ } else {
+ FileName fn = arg;
+ if (fn.str() == "___CUBE_TEST___") {
+ int numPerSide = atoi(av[++i]);
+ particle::Model *m = createTestCube(numPerSide);
+ particleModel.push_back(m);
+ loadedScene = true;
+ } else if (fn.ext() == "xyz") {
+ particle::Model *m = new particle::Model;
+ deferredLoadingListXYZ.push_back(new DeferredLoadJob(m,fn,defFileName));
+ particleModel.push_back(m);
+ loadedScene = true;
+ } else if (fn.ext() == "xyz2") {
+ particle::Model *m = new particle::Model;
+ m->loadXYZ2(fn);
+ particleModel.push_back(m);
+ loadedScene = true;
+ } else if (fn.ext() == "xyz3") {
+ particle::Model *m = new particle::Model;
+ m->loadXYZ3(fn);
+ particleModel.push_back(m);
+ loadedScene = true;
#if 1 // NOTE(jda) - The '.xml' file extension conflicts with RIVL files in
// TriangleMeshSceneParser...disabling here for now until the
// the problem requires a solution.
- }
+ }
#else
} else if (fn.ext() == "xml") {
particle::Model *m = particle::parse__Uintah_timestep_xml(fn);
@@ -184,3 +191,5 @@ std::deque ParticleSceneParser::bbox() const
boxes.push_back(sceneBbox);
return boxes;
}
+
+} // ::commandline
diff --git a/apps/common/commandline/SceneParser/particle/ParticleSceneParser.h b/apps/common/commandline/SceneParser/particle/ParticleSceneParser.h
index 044a3152d4..1b964b3e20 100644
--- a/apps/common/commandline/SceneParser/particle/ParticleSceneParser.h
+++ b/apps/common/commandline/SceneParser/particle/ParticleSceneParser.h
@@ -20,20 +20,24 @@
#include
#include
-class OSPRAY_COMMANDLINE_INTERFACE ParticleSceneParser : public SceneParser
-{
-public:
- ParticleSceneParser(ospray::cpp::Renderer);
+namespace commandline {
- bool parse(int ac, const char **&av) override;
+ class OSPRAY_COMMANDLINE_INTERFACE ParticleSceneParser : public SceneParser
+ {
+ public:
+ ParticleSceneParser(ospray::cpp::Renderer);
- std::deque model() const override;
- std::deque bbox() const override;
+ bool parse(int ac, const char **&av) override;
-private:
+ std::deque model() const override;
+ std::deque bbox() const override;
- ospray::cpp::Renderer renderer;
- ospcommon::box3f sceneBbox;
+ private:
- std::deque modelTimeStep;
-};
+ ospray::cpp::Renderer renderer;
+ ospcommon::box3f sceneBbox;
+
+ std::deque modelTimeStep;
+ };
+
+} // ::commandline
diff --git a/apps/common/commandline/SceneParser/streamlines/StreamLineSceneParser.cpp b/apps/common/commandline/SceneParser/streamlines/StreamLineSceneParser.cpp
index eb5645e506..28b09e5f0a 100644
--- a/apps/common/commandline/SceneParser/streamlines/StreamLineSceneParser.cpp
+++ b/apps/common/commandline/SceneParser/streamlines/StreamLineSceneParser.cpp
@@ -18,578 +18,584 @@
#include "common/xml/XML.h"
-using namespace ospray;
-using namespace ospcommon;
-
#include
-using std::cout;
-using std::endl;
-// Helper types ///////////////////////////////////////////////////////////////
+namespace commandline {
-struct Triangles {
- std::vector vertex;
- std::vector color; // vertex color, from sv's 'v' value
- std::vector index;
+ using namespace ospray;
+ using namespace ospcommon;
- struct SVVertex {
- float v;
- vec3f pos;
- };
- struct SVTriangle {
- SVVertex vertex[3];
- };
+ using std::cout;
+ using std::endl;
- vec3f lerpf(float x, float x0, float x1, vec3f y0, vec3f y1)
- {
- float f = (x-x0)/(x1-x0);
- return f*y1+(1-f)*y0;
- }
-
- vec4f colorOf(const float f)
- {
- if (f < .5f)
- return vec4f(lerpf(f, 0.f,.5f,vec3f(0),vec3f(0,1,0)), 1.f);
- else
- return vec4f(lerpf(f, .5f,1.f,vec3f(0,1,0),vec3f(1,0,0)), 1.f);
- }
- void parseSV(const FileName &fn)
- {
- FILE *file = fopen(fn.str().c_str(),"rb");
- if (!file) return;
- SVTriangle triangle;
- while (fread(&triangle,sizeof(triangle),1,file)) {
- index.push_back(vec3i(0,1,2)+vec3i(vertex.size()));
- vertex.push_back(vec3fa(triangle.vertex[0].pos));
- vertex.push_back(vec3fa(triangle.vertex[1].pos));
- vertex.push_back(vec3fa(triangle.vertex[2].pos));
- color.push_back(colorOf(triangle.vertex[0].v));
- color.push_back(colorOf(triangle.vertex[1].v));
- color.push_back(colorOf(triangle.vertex[2].v));
- }
- fclose(file);
- }
+ // Helper types ///////////////////////////////////////////////////////////////
- box3f getBounds() const
- {
- box3f bounds = empty;
- for (const auto &v : vertex)
- bounds.extend(v);
- return bounds;
- }
-};
+ struct Triangles {
+ std::vector vertex;
+ std::vector color; // vertex color, from sv's 'v' value
+ std::vector index;
-struct StreamLines {
- std::vector vertex;
- std::vector index;
- float radius {0.001f};
+ struct SVVertex {
+ float v;
+ vec3f pos;
+ };
- void parsePNT(const FileName &fn)
- {
- FILE *file = fopen(fn.c_str(),"r");
- if (!file) {
- cout << "WARNING: could not open file " << fn << endl;
- return;
+ struct SVTriangle {
+ SVVertex vertex[3];
+ };
+
+ vec3f lerpf(float x, float x0, float x1, vec3f y0, vec3f y1)
+ {
+ float f = (x-x0)/(x1-x0);
+ return f*y1+(1-f)*y0;
}
- vec3fa pnt;
- static size_t totalSegments = 0;
- size_t segments = 0;
- // cout << "parsing file " << fn << ":" << std::flush;
- int rc = fscanf(file,"%f %f %f\n",&pnt.x,&pnt.y,&pnt.z);
- vertex.push_back(pnt);
- Assert(rc == 3);
- while ((rc = fscanf(file,"%f %f %f\n",&pnt.x,&pnt.y,&pnt.z)) == 3) {
- index.push_back(vertex.size()-1);
- vertex.push_back(pnt);
- segments++;
+
+ vec4f colorOf(const float f)
+ {
+ if (f < .5f)
+ return vec4f(lerpf(f, 0.f,.5f,vec3f(0),vec3f(0,1,0)), 1.f);
+ else
+ return vec4f(lerpf(f, .5f,1.f,vec3f(0,1,0),vec3f(1,0,0)), 1.f);
+ }
+ void parseSV(const FileName &fn)
+ {
+ FILE *file = fopen(fn.str().c_str(),"rb");
+ if (!file) return;
+ SVTriangle triangle;
+ while (fread(&triangle,sizeof(triangle),1,file)) {
+ index.push_back(vec3i(0,1,2)+vec3i(vertex.size()));
+ vertex.push_back(vec3fa(triangle.vertex[0].pos));
+ vertex.push_back(vec3fa(triangle.vertex[1].pos));
+ vertex.push_back(vec3fa(triangle.vertex[2].pos));
+ color.push_back(colorOf(triangle.vertex[0].v));
+ color.push_back(colorOf(triangle.vertex[1].v));
+ color.push_back(colorOf(triangle.vertex[2].v));
+ }
+ fclose(file);
}
- totalSegments += segments;
- fclose(file);
- }
+ box3f getBounds() const
+ {
+ box3f bounds = empty;
+ for (const auto &v : vertex)
+ bounds.extend(v);
+ return bounds;
+ }
+ };
- void parsePNTlist(const FileName &fn)
- {
- FILE *file = fopen(fn.c_str(),"r");
- Assert(file);
- for (char line[10000]; fgets(line,10000,file) && !feof(file); ) {
- char *eol = strstr(line,"\n"); if (eol) *eol = 0;
- parsePNT(line);
+ struct StreamLines {
+ std::vector vertex;
+ std::vector index;
+ float radius {0.001f};
+
+ void parsePNT(const FileName &fn)
+ {
+ FILE *file = fopen(fn.c_str(),"r");
+ if (!file) {
+ cout << "WARNING: could not open file " << fn << endl;
+ return;
+ }
+ vec3fa pnt;
+ static size_t totalSegments = 0;
+ size_t segments = 0;
+ // cout << "parsing file " << fn << ":" << std::flush;
+ int rc = fscanf(file,"%f %f %f\n",&pnt.x,&pnt.y,&pnt.z);
+ vertex.push_back(pnt);
+ Assert(rc == 3);
+ while ((rc = fscanf(file,"%f %f %f\n",&pnt.x,&pnt.y,&pnt.z)) == 3) {
+ index.push_back(vertex.size()-1);
+ vertex.push_back(pnt);
+ segments++;
+ }
+ totalSegments += segments;
+ fclose(file);
}
- fclose(file);
- }
- void parseSLRAW(const FileName &fn)
- {
- FILE *file = fopen(fn.c_str(),"rb");
- if (!file) {
- cout << "WARNING: could not open file " << fn << endl;
- return;
+ void parsePNTlist(const FileName &fn)
+ {
+ FILE *file = fopen(fn.c_str(),"r");
+ Assert(file);
+ for (char line[10000]; fgets(line,10000,file) && !feof(file); ) {
+ char *eol = strstr(line,"\n"); if (eol) *eol = 0;
+ parsePNT(line);
+ }
+ fclose(file);
}
- int numStreamlines;
- int rc = fread(&numStreamlines, sizeof(int), 1, file);
- (void)rc;
- Assert(rc == 1);
+ void parseSLRAW(const FileName &fn)
+ {
+ FILE *file = fopen(fn.c_str(),"rb");
- for(int s=0; s filePoints;
-
- FILE *file = fopen(fn.c_str(),"r");
- Assert(file);
- radius = 99.f;
- for (char line[10000]; fgets(line,10000,file) && !feof(file); ) {
- if (line[0] == '#') continue;
-
- vec3fa v; float f1; int ID, i, j;
- sscanf(line,"%i %i %f %f %f %f %i\n",&ID,&i,&v.x,&v.y,&v.z,&f1,&j);
- if (f1 < radius)
- radius = f1;
- filePoints.push_back(v);
-
- index.push_back(vertex.size());
- vertex.push_back(v);
- vertex.push_back(filePoints[j-1]);
- }
- fclose(file);
- }
+ void parseSWC(const FileName &fn)
+ {
+ std::vector filePoints;
- void parse(const FileName &fn)
- {
- if (fn.ext() == "pnt")
- parsePNT(fn);
- else if (fn.ext() == "pntlist") {
FILE *file = fopen(fn.c_str(),"r");
Assert(file);
+ radius = 99.f;
for (char line[10000]; fgets(line,10000,file) && !feof(file); ) {
- char *eol = strstr(line,"\n"); if (eol) *eol = 0;
- parsePNT(line);
+ if (line[0] == '#') continue;
+
+ vec3fa v; float f1; int ID, i, j;
+ sscanf(line,"%i %i %f %f %f %f %i\n",&ID,&i,&v.x,&v.y,&v.z,&f1,&j);
+ if (f1 < radius)
+ radius = f1;
+ filePoints.push_back(v);
+
+ index.push_back(vertex.size());
+ vertex.push_back(v);
+ vertex.push_back(filePoints[j-1]);
}
fclose(file);
- } else if (fn.ext() == "slraw") {
- parseSLRAW(fn);
- } else
- throw std::runtime_error("unknown input file format "+fn.str());
- }
- box3f getBounds() const
- {
- box3f bounds = empty;
- for (const auto &v : vertex)
- bounds.extend(v);
- return bounds;
- }
-};
+ }
-struct StockleyWhealCannon {
- struct Cylinder {
- vec3f v0;
- vec3f v1;
- float r;
- };
- struct Sphere {
- vec3f v;
- float r;
+ void parse(const FileName &fn)
+ {
+ if (fn.ext() == "pnt")
+ parsePNT(fn);
+ else if (fn.ext() == "pntlist") {
+ FILE *file = fopen(fn.c_str(),"r");
+ Assert(file);
+ for (char line[10000]; fgets(line,10000,file) && !feof(file); ) {
+ char *eol = strstr(line,"\n"); if (eol) *eol = 0;
+ parsePNT(line);
+ }
+ fclose(file);
+ } else if (fn.ext() == "slraw") {
+ parseSLRAW(fn);
+ } else
+ throw std::runtime_error("unknown input file format "+fn.str());
+ }
+ box3f getBounds() const
+ {
+ box3f bounds = empty;
+ for (const auto &v : vertex)
+ bounds.extend(v);
+ return bounds;
+ }
};
- std::vector spheres[3];
- std::vector cylinders[3];
- box3f bounds;
+ struct StockleyWhealCannon {
+ struct Cylinder {
+ vec3f v0;
+ vec3f v1;
+ float r;
+ };
+ struct Sphere {
+ vec3f v;
+ float r;
+ };
+
+ std::vector spheres[3];
+ std::vector cylinders[3];
+ box3f bounds;
+
+ void parse(const FileName &fn)
+ {
+ std::vector filePoints;
- void parse(const FileName &fn)
- {
- std::vector filePoints;
-
- FILE *file = fopen(fn.c_str(),"r");
- Assert(file);
- bounds = empty;
- for (char line[10000]; fgets(line,10000,file) && !feof(file); ) {
- if (line[0] == '#') continue;
-
- vec3f v; float radius; int id, parent, type;
- sscanf(line,"%i %i %f %f %f %f %i\n",
- &id, &type, &v.x, &v.y, &v.z, &radius, &parent);
- filePoints.push_back(v);
- Assert(filePoints.size() == id); // assumes index-1==id
- bounds.extend(v); // neglects radius
-
- if (parent == -1) // root soma, just one sphere
- spheres[0].push_back(Sphere{v, radius});
- else { // cylinder with sphere at end
- int idx;
- switch (type) {
- case 3: idx = 1; break; // basal dendrite
- case 4: idx = 2; break; // apical dendrite
- default: idx = 0; break; // soma / axon
+ FILE *file = fopen(fn.c_str(),"r");
+ Assert(file);
+ bounds = empty;
+ for (char line[10000]; fgets(line,10000,file) && !feof(file); ) {
+ if (line[0] == '#') continue;
+
+ vec3f v; float radius; int id, parent, type;
+ sscanf(line,"%i %i %f %f %f %f %i\n",
+ &id, &type, &v.x, &v.y, &v.z, &radius, &parent);
+ filePoints.push_back(v);
+ Assert(filePoints.size() == id); // assumes index-1==id
+ bounds.extend(v); // neglects radius
+
+ if (parent == -1) // root soma, just one sphere
+ spheres[0].push_back(Sphere{v, radius});
+ else { // cylinder with sphere at end
+ int idx;
+ switch (type) {
+ case 3: idx = 1; break; // basal dendrite
+ case 4: idx = 2; break; // apical dendrite
+ default: idx = 0; break; // soma / axon
+ }
+ spheres[idx].push_back(Sphere{v, radius});
+ cylinders[idx].push_back(Cylinder{filePoints[parent-1], v, radius});
}
- spheres[idx].push_back(Sphere{v, radius});
- cylinders[idx].push_back(Cylinder{filePoints[parent-1], v, radius});
}
+ fclose(file);
}
- fclose(file);
- }
- box3f getBounds() const
+ box3f getBounds() const
+ {
+ return bounds;
+ }
+ };
+
+ static const char *delim = "\n\t\r ";
+
+ void osxParseInts(std::vector &vec, const std::string &content)
{
- return bounds;
+ char *s = strdup(content.c_str());
+ char *tok = strtok(s,delim);
+ while (tok) {
+ vec.push_back(atol(tok));
+ tok = strtok(NULL,delim);
+ }
+ free(s);
}
-};
-static const char *delim = "\n\t\r ";
+ template T ato(const char *);
+ template<> inline int ato(const char *s) { return atol(s); }
+ template<> inline float ato(const char *s) { return atof(s); }
+
+ template
+ vec_t osxParseVec3(char * &tok) {
+ vec_t v;
+
+ assert(tok);
+ v.x = ato(tok);
+ tok = strtok(NULL,delim);
+
+ assert(tok);
+ v.y = ato(tok);
+ tok = strtok(NULL,delim);
-void osxParseInts(std::vector &vec, const std::string &content)
-{
- char *s = strdup(content.c_str());
- char *tok = strtok(s,delim);
- while (tok) {
- vec.push_back(atol(tok));
+ assert(tok);
+ v.z = ato(tok);
tok = strtok(NULL,delim);
+
+ return v;
}
- free(s);
-}
-
-template T ato(const char *);
-template<> inline int ato(const char *s) { return atol(s); }
-template<> inline float ato(const char *s) { return atof(s); }
-
-template
-vec_t osxParseVec3(char * &tok) {
- vec_t v;
-
- assert(tok);
- v.x = ato(tok);
- tok = strtok(NULL,delim);
-
- assert(tok);
- v.y = ato(tok);
- tok = strtok(NULL,delim);
-
- assert(tok);
- v.z = ato(tok);
- tok = strtok(NULL,delim);
-
- return v;
-}
-
-void osxParseVec3is(std::vector &vec, const std::string &content)
-{
- char *s = strdup(content.c_str());
- char *tok = strtok(s,delim);
- while (tok)
- vec.push_back(osxParseVec3(tok));
- free(s);
-}
-
-void osxParseVec3fas(std::vector &vec, const std::string &content)
-{
- char *s = strdup(content.c_str());
- char *tok = strtok(s,delim);
- while (tok)
- vec.push_back(osxParseVec3(tok));
- free(s);
-}
-
-void osxParseColors(std::vector &vec, const std::string &content)
-{
- char *s = strdup(content.c_str());
- char *tok = strtok(s,delim);
- while (tok)
- vec.push_back(vec4f(osxParseVec3(tok), 1.f));
- free(s);
-}
-
-/*! parse ospray xml file */
-void parseOSX(StreamLines *streamLines,
- Triangles *triangles,
- const std::string &fn)
-{
- std::shared_ptr doc = xml::readXML(fn);
- assert(doc);
- if (doc->child.size() != 1 || doc->child[0]->name != "OSPRay")
- throw std::runtime_error("could not parse osx file: Not in OSPRay format!?");
- const xml::Node &root_element = *doc->child[0];
- xml::for_each_child_of(root_element,[&](const xml::Node &node){
- if (node.name == "Info") {
- // ignore
- }
- else if (node.name == "Model") {
- const xml::Node &model_node = node;
- xml::for_each_child_of(model_node,[&](const xml::Node &node){
- if (node.name == "StreamLines") {
- const xml::Node &sl_node = node;
- xml::for_each_child_of(sl_node,[&](const xml::Node &node){
- if (node.name == "vertex") {
- osxParseVec3fas(streamLines->vertex,node.content);
- }
- else if (node.name == "index") {
- osxParseInts(streamLines->index,node.content);
- };
- });
- }
- else if (node.name == "TriangleMesh") {
- const xml::Node &tris_node = node;
- xml::for_each_child_of(tris_node,[&](const xml::Node &node){
- if (node.name == "vertex") {
- osxParseVec3fas(triangles->vertex,node.content);
- }
- else if (node.name == "color") {
- osxParseColors(triangles->color,node.content);
- }
- else if (node.name == "index") {
- osxParseVec3is(triangles->index,node.content);
- }
- });
- }
- });
- }
- });
-}
-
-void exportOSX(const char *fn,StreamLines *streamLines, Triangles *triangles)
-{
- FILE *file = fopen(fn,"w");
- fprintf(file,"\n\n");
- fprintf(file,"\n");
+
+ void osxParseVec3is(std::vector &vec, const std::string &content)
+ {
+ char *s = strdup(content.c_str());
+ char *tok = strtok(s,delim);
+ while (tok)
+ vec.push_back(osxParseVec3(tok));
+ free(s);
+ }
+
+ void osxParseVec3fas(std::vector &vec, const std::string &content)
+ {
+ char *s = strdup(content.c_str());
+ char *tok = strtok(s,delim);
+ while (tok)
+ vec.push_back(osxParseVec3(tok));
+ free(s);
+ }
+
+ void osxParseColors(std::vector &vec, const std::string &content)
+ {
+ char *s = strdup(content.c_str());
+ char *tok = strtok(s,delim);
+ while (tok)
+ vec.push_back(vec4f(osxParseVec3(tok), 1.f));
+ free(s);
+ }
+
+ /*! parse ospray xml file */
+ void parseOSX(StreamLines *streamLines,
+ Triangles *triangles,
+ const std::string &fn)
{
- fprintf(file,"\n");
+ std::shared_ptr doc = xml::readXML(fn);
+ assert(doc);
+ if (doc->child.size() != 1 || doc->child[0]->name != "OSPRay")
+ throw std::runtime_error("could not parse osx file: Not in OSPRay format!?");
+ const xml::Node &root_element = *doc->child[0];
+ xml::for_each_child_of(root_element,[&](const xml::Node &node){
+ if (node.name == "Info") {
+ // ignore
+ }
+ else if (node.name == "Model") {
+ const xml::Node &model_node = node;
+ xml::for_each_child_of(model_node,[&](const xml::Node &node){
+ if (node.name == "StreamLines") {
+ const xml::Node &sl_node = node;
+ xml::for_each_child_of(sl_node,[&](const xml::Node &node){
+ if (node.name == "vertex") {
+ osxParseVec3fas(streamLines->vertex,node.content);
+ }
+ else if (node.name == "index") {
+ osxParseInts(streamLines->index,node.content);
+ };
+ });
+ }
+ else if (node.name == "TriangleMesh") {
+ const xml::Node &tris_node = node;
+ xml::for_each_child_of(tris_node,[&](const xml::Node &node){
+ if (node.name == "vertex") {
+ osxParseVec3fas(triangles->vertex,node.content);
+ }
+ else if (node.name == "color") {
+ osxParseColors(triangles->color,node.content);
+ }
+ else if (node.name == "index") {
+ osxParseVec3is(triangles->index,node.content);
+ }
+ });
+ }
+ });
+ }
+ });
+ }
+
+ void exportOSX(const char *fn,StreamLines *streamLines, Triangles *triangles)
+ {
+ FILE *file = fopen(fn,"w");
+ fprintf(file,"\n\n");
+ fprintf(file,"\n");
{
- fprintf(file,"\n");
+ fprintf(file,"\n");
{
- fprintf(file,"\n");
- for (const auto &v : streamLines->vertex)
- fprintf(file,"%f %f %f\n", v.x, v.y, v.z);
- fprintf(file,"\n");
-
- fprintf(file,"\n");
- for (const auto & i : streamLines->index)
- fprintf(file,"%i ",i);
- fprintf(file,"\n\n");
- }
- fprintf(file,"\n");
+ fprintf(file,"\n");
+ {
+ fprintf(file,"\n");
+ for (const auto &v : streamLines->vertex)
+ fprintf(file,"%f %f %f\n", v.x, v.y, v.z);
+ fprintf(file,"\n");
+
+ fprintf(file,"\n");
+ for (const auto & i : streamLines->index)
+ fprintf(file,"%i ",i);
+ fprintf(file,"\n\n");
+ }
+ fprintf(file,"\n");
- fprintf(file,"\n");
- {
- fprintf(file,"\n");
- for (const auto &v : triangles->vertex)
- fprintf(file,"%f %f %f\n", v.x, v.y, v.z);
- fprintf(file,"\n");
+ fprintf(file,"\n");
+ {
+ fprintf(file,"\n");
+ for (const auto &v : triangles->vertex)
+ fprintf(file,"%f %f %f\n", v.x, v.y, v.z);
+ fprintf(file,"\n");
- fprintf(file,"\n");
- for (const auto &c : triangles->color)
- fprintf(file,"%f %f %f\n", c.x, c.y, c.z);
- fprintf(file,"\n");
+ fprintf(file,"\n");
+ for (const auto &c : triangles->color)
+ fprintf(file,"%f %f %f\n", c.x, c.y, c.z);
+ fprintf(file,"\n");
- fprintf(file,"\n");
- for (const auto &i : triangles->index)
- fprintf(file,"%i %i %i\n", i.x, i.y, i.z);
- fprintf(file,"\n");
+ fprintf(file,"\n");
+ for (const auto &i : triangles->index)
+ fprintf(file,"%i %i %i\n", i.x, i.y, i.z);
+ fprintf(file,"\n");
+ }
+ fprintf(file,"\n");
}
- fprintf(file,"\n");
- }
- fprintf(file,"\n");
- }
- fprintf(file,"\n");
- fclose(file);
-}
-
-// Class definitions //////////////////////////////////////////////////////////
-
-StreamLineSceneParser::StreamLineSceneParser(cpp::Renderer renderer) :
- renderer(renderer)
-{
-}
-
-bool StreamLineSceneParser::parse(int ac, const char **&av)
-{
- bool loadedScene = false;
-
- StreamLines *streamLines = nullptr;//new StreamLines;
- Triangles *triangles = nullptr;//new Triangles;
- StockleyWhealCannon *swc = nullptr;//new StockleyWhealCannon;
-
- for (int i = 1; i < ac; i++) {
- std::string arg = av[i];
- if (arg[0] != '-') {
- const FileName fn = arg;
- if (fn.ext() == "osx") {
- streamLines = new StreamLines;
- triangles = new Triangles;
- parseOSX(streamLines, triangles, fn);
- loadedScene = true;
- }
- else if (fn.ext() == "pnt") {
- streamLines = new StreamLines;
- streamLines->parsePNT(fn);
- loadedScene = true;
- }
- else if (fn.ext() == "swc") {
- swc = new StockleyWhealCannon;
- swc->parse(fn);
- loadedScene = true;
- }
- else if (fn.ext() == "pntlist") {
- streamLines = new StreamLines;
- streamLines->parsePNTlist(fn);
- loadedScene = true;
- }
- else if (fn.ext() == "slraw") {
- streamLines = new StreamLines;
- streamLines->parseSLRAW(fn);
- loadedScene = true;
- }
- else if (fn.ext() == "sv") {
- triangles = new Triangles;
- triangles->parseSV(fn);
- loadedScene = true;
- }
- } else if (arg == "--streamline-radius") {
- streamLines->radius = atof(av[++i]);
-#if 0
- } else if (arg == "--streamline-export") {
- exportOSX(av[++i], streamLines, triangles);
-#endif
+ fprintf(file,"\n");
}
+ fprintf(file,"\n");
+ fclose(file);
}
- if (loadedScene) {
- sceneModel = make_unique();
+ // Class definitions //////////////////////////////////////////////////////////
- auto &model = *sceneModel;
+ StreamLineSceneParser::StreamLineSceneParser(cpp::Renderer renderer) :
+ renderer(renderer)
+ {
+ }
- OSPMaterial mat = ospNewMaterial(renderer.handle(), "default");
- if (mat) {
- ospSet3f(mat, "kd", .7, .7, .7);
- ospCommit(mat);
+ bool StreamLineSceneParser::parse(int ac, const char **&av)
+ {
+ bool loadedScene = false;
+
+ StreamLines *streamLines = nullptr;//new StreamLines;
+ Triangles *triangles = nullptr;//new Triangles;
+ StockleyWhealCannon *swc = nullptr;//new StockleyWhealCannon;
+
+ for (int i = 1; i < ac; i++) {
+ std::string arg = av[i];
+ if (arg[0] != '-') {
+ const FileName fn = arg;
+ if (fn.ext() == "osx") {
+ streamLines = new StreamLines;
+ triangles = new Triangles;
+ parseOSX(streamLines, triangles, fn);
+ loadedScene = true;
+ }
+ else if (fn.ext() == "pnt") {
+ streamLines = new StreamLines;
+ streamLines->parsePNT(fn);
+ loadedScene = true;
+ }
+ else if (fn.ext() == "swc") {
+ swc = new StockleyWhealCannon;
+ swc->parse(fn);
+ loadedScene = true;
+ }
+ else if (fn.ext() == "pntlist") {
+ streamLines = new StreamLines;
+ streamLines->parsePNTlist(fn);
+ loadedScene = true;
+ }
+ else if (fn.ext() == "slraw") {
+ streamLines = new StreamLines;
+ streamLines->parseSLRAW(fn);
+ loadedScene = true;
+ }
+ else if (fn.ext() == "sv") {
+ triangles = new Triangles;
+ triangles->parseSV(fn);
+ loadedScene = true;
+ }
+ } else if (arg == "--streamline-radius") {
+ streamLines->radius = atof(av[++i]);
+#if 0
+ } else if (arg == "--streamline-export") {
+ exportOSX(av[++i], streamLines, triangles);
+#endif
+ }
}
- box3f bounds(empty);
-
- if (streamLines && !streamLines->index.empty()) {
- OSPGeometry geom = ospNewGeometry("streamlines");
- Assert(geom);
- OSPData vertex = ospNewData(streamLines->vertex.size(),
- OSP_FLOAT3A, &streamLines->vertex[0]);
- OSPData index = ospNewData(streamLines->index.size(),
- OSP_UINT, &streamLines->index[0]);
- ospSetObject(geom,"vertex",vertex);
- ospSetObject(geom,"index",index);
- ospSet1f(geom,"radius",streamLines->radius);
- if (mat)
- ospSetMaterial(geom,mat);
- ospCommit(geom);
- ospAddGeometry(model.handle(), geom);
- bounds.extend(streamLines->getBounds());
- }
+ if (loadedScene) {
+ sceneModel = make_unique();
- if (triangles && !triangles->index.empty()) {
- OSPGeometry geom = ospNewGeometry("triangles");
- Assert(geom);
- OSPData vertex = ospNewData(triangles->vertex.size(),
- OSP_FLOAT3A, &triangles->vertex[0]);
- OSPData index = ospNewData(triangles->index.size(),
- OSP_INT3, &triangles->index[0]);
- OSPData color = ospNewData(triangles->color.size(),
- OSP_FLOAT4, &triangles->color[0]);
- ospSetObject(geom, "vertex", vertex);
- ospSetObject(geom, "index", index);
- ospSetObject(geom, "vertex.color", color);
- ospSetMaterial(geom, mat);
- ospCommit(geom);
- ospAddGeometry(model.handle(), geom);
- bounds.extend(triangles->getBounds());
- }
+ auto &model = *sceneModel;
- if (swc && !swc->bounds.empty()) {
- OSPMaterial material[3];
- material[0] = mat;
- material[1] = ospNewMaterial(renderer.handle(), "default");
- if (material[1]) {
- ospSet3f(material[1], "kd", .0, .7, .0); // OBJ renderer, green
- ospCommit(material[1]);
+ OSPMaterial mat = ospNewMaterial(renderer.handle(), "default");
+ if (mat) {
+ ospSet3f(mat, "kd", .7, .7, .7);
+ ospCommit(mat);
}
- material[2] = ospNewMaterial(renderer.handle(), "default");
- if (material[2]) {
- ospSet3f(material[2], "kd", .7, .0, .7); // OBJ renderer, magenta
- ospCommit(material[2]);
+
+ box3f bounds(empty);
+
+ if (streamLines && !streamLines->index.empty()) {
+ OSPGeometry geom = ospNewGeometry("streamlines");
+ Assert(geom);
+ OSPData vertex = ospNewData(streamLines->vertex.size(),
+ OSP_FLOAT3A, &streamLines->vertex[0]);
+ OSPData index = ospNewData(streamLines->index.size(),
+ OSP_UINT, &streamLines->index[0]);
+ ospSetObject(geom,"vertex",vertex);
+ ospSetObject(geom,"index",index);
+ ospSet1f(geom,"radius",streamLines->radius);
+ if (mat)
+ ospSetMaterial(geom,mat);
+ ospCommit(geom);
+ ospAddGeometry(model.handle(), geom);
+ bounds.extend(streamLines->getBounds());
+ }
+
+ if (triangles && !triangles->index.empty()) {
+ OSPGeometry geom = ospNewGeometry("triangles");
+ Assert(geom);
+ OSPData vertex = ospNewData(triangles->vertex.size(),
+ OSP_FLOAT3A, &triangles->vertex[0]);
+ OSPData index = ospNewData(triangles->index.size(),
+ OSP_INT3, &triangles->index[0]);
+ OSPData color = ospNewData(triangles->color.size(),
+ OSP_FLOAT4, &triangles->color[0]);
+ ospSetObject(geom, "vertex", vertex);
+ ospSetObject(geom, "index", index);
+ ospSetObject(geom, "vertex.color", color);
+ ospSetMaterial(geom, mat);
+ ospCommit(geom);
+ ospAddGeometry(model.handle(), geom);
+ bounds.extend(triangles->getBounds());
}
- OSPGeometry spheres[3], cylinders[3];
- for (int i = 0; i < 3; i++) {
- spheres[i] = ospNewGeometry("spheres");
- Assert(spheres[i]);
+ if (swc && !swc->bounds.empty()) {
+ OSPMaterial material[3];
+ material[0] = mat;
+ material[1] = ospNewMaterial(renderer.handle(), "default");
+ if (material[1]) {
+ ospSet3f(material[1], "kd", .0, .7, .0); // OBJ renderer, green
+ ospCommit(material[1]);
+ }
+ material[2] = ospNewMaterial(renderer.handle(), "default");
+ if (material[2]) {
+ ospSet3f(material[2], "kd", .7, .0, .7); // OBJ renderer, magenta
+ ospCommit(material[2]);
+ }
+
+ OSPGeometry spheres[3], cylinders[3];
+ for (int i = 0; i < 3; i++) {
+ spheres[i] = ospNewGeometry("spheres");
+ Assert(spheres[i]);
+
+ OSPData data = ospNewData(swc->spheres[i].size(), OSP_FLOAT4,
+ &swc->spheres[i][0]);
+ ospSetObject(spheres[i], "spheres", data);
+ ospSet1i(spheres[i], "offset_radius", 3*sizeof(float));
- OSPData data = ospNewData(swc->spheres[i].size(), OSP_FLOAT4,
- &swc->spheres[i][0]);
- ospSetObject(spheres[i], "spheres", data);
- ospSet1i(spheres[i], "offset_radius", 3*sizeof(float));
+ if (material[i])
+ ospSetMaterial(spheres[i], material[i]);
- if (material[i])
- ospSetMaterial(spheres[i], material[i]);
+ ospCommit(spheres[i]);
+ ospAddGeometry(model.handle(), spheres[i]);
- ospCommit(spheres[i]);
- ospAddGeometry(model.handle(), spheres[i]);
+ cylinders[i] = ospNewGeometry("cylinders");
+ Assert(cylinders[i]);
- cylinders[i] = ospNewGeometry("cylinders");
- Assert(cylinders[i]);
+ data = ospNewData(swc->cylinders[i].size()*7, OSP_FLOAT,
+ &swc->cylinders[i][0]);
+ ospSetObject(cylinders[i], "cylinders", data);
- data = ospNewData(swc->cylinders[i].size()*7, OSP_FLOAT,
- &swc->cylinders[i][0]);
- ospSetObject(cylinders[i], "cylinders", data);
+ if (material[i])
+ ospSetMaterial(cylinders[i], material[i]);
- if (material[i])
- ospSetMaterial(cylinders[i], material[i]);
+ ospCommit(cylinders[i]);
+ ospAddGeometry(model.handle(), cylinders[i]);
+ }
- ospCommit(cylinders[i]);
- ospAddGeometry(model.handle(), cylinders[i]);
+ bounds.extend(swc->getBounds());
}
- bounds.extend(swc->getBounds());
+ model.commit();
+ sceneBbox = bounds;
}
- model.commit();
- sceneBbox = bounds;
+ if (streamLines) delete streamLines;
+ if (triangles) delete triangles;
+ if (swc) delete swc;
+
+ return loadedScene;
+ }
+
+ std::deque StreamLineSceneParser::model() const
+ {
+ std::deque models;
+ models.push_back(sceneModel.get() == nullptr ? cpp::Model() : *sceneModel);
+ return models;
+ }
+
+ std::deque StreamLineSceneParser::bbox() const
+ {
+ std::deque boxes;
+ boxes.push_back(sceneBbox);
+ return boxes;
}
- if (streamLines) delete streamLines;
- if (triangles) delete triangles;
- if (swc) delete swc;
-
- return loadedScene;
-}
-
-std::deque StreamLineSceneParser::model() const
-{
- std::deque models;
- models.push_back(sceneModel.get() == nullptr ? cpp::Model() : *sceneModel);
- return models;
-}
-
-std::deque StreamLineSceneParser::bbox() const
-{
- std::deque boxes;
- boxes.push_back(sceneBbox);
- return boxes;
-}
+} // ::commandline
diff --git a/apps/common/commandline/SceneParser/streamlines/StreamLineSceneParser.h b/apps/common/commandline/SceneParser/streamlines/StreamLineSceneParser.h
index 7ebc7d23eb..b02afa5fc6 100644
--- a/apps/common/commandline/SceneParser/streamlines/StreamLineSceneParser.h
+++ b/apps/common/commandline/SceneParser/streamlines/StreamLineSceneParser.h
@@ -20,21 +20,25 @@
#include
#include
-class OSPRAY_COMMANDLINE_INTERFACE StreamLineSceneParser : public SceneParser
-{
-public:
- StreamLineSceneParser(ospray::cpp::Renderer);
+namespace commandline {
- bool parse(int ac, const char **&av) override;
+ class OSPRAY_COMMANDLINE_INTERFACE StreamLineSceneParser : public SceneParser
+ {
+ public:
+ StreamLineSceneParser(ospray::cpp::Renderer);
- std::deque model() const override;
- std::deque bbox() const override;
+ bool parse(int ac, const char **&av) override;
-private:
+ std::deque model() const override;
+ std::deque bbox() const override;
- std::unique_ptr sceneModel;
- ospray::cpp::Renderer renderer;
- ospcommon::box3f sceneBbox;
+ private:
- void finalize();
-};
+ std::unique_ptr sceneModel;
+ ospray::cpp::Renderer renderer;
+ ospcommon::box3f sceneBbox;
+
+ void finalize();
+ };
+
+} // ::commandline
diff --git a/apps/common/commandline/SceneParser/tachyon/TachyonSceneParser.h b/apps/common/commandline/SceneParser/tachyon/TachyonSceneParser.h
index 3fec53c6ab..478d230466 100644
--- a/apps/common/commandline/SceneParser/tachyon/TachyonSceneParser.h
+++ b/apps/common/commandline/SceneParser/tachyon/TachyonSceneParser.h
@@ -17,7 +17,7 @@
#pragma once
#include
-#include
+#include
class TachyonSceneParser : public SceneParser
{
diff --git a/apps/common/commandline/SceneParser/trianglemesh/TriangleMeshSceneParser.cpp b/apps/common/commandline/SceneParser/trianglemesh/TriangleMeshSceneParser.cpp
index fbbda22b90..b610e5b459 100644
--- a/apps/common/commandline/SceneParser/trianglemesh/TriangleMeshSceneParser.cpp
+++ b/apps/common/commandline/SceneParser/trianglemesh/TriangleMeshSceneParser.cpp
@@ -19,426 +19,433 @@
#include
#include
-using namespace ospray;
-using namespace ospcommon;
-
#include
#include
-using std::cerr;
-using std::endl;
-// Static local helper functions //////////////////////////////////////////////
+namespace commandline {
+
+ using namespace ospray;
+ using namespace ospcommon;
+
+ using std::cerr;
+ using std::endl;
-static void warnMaterial(const std::string &type)
-{
- static std::map numOccurances;
- if (numOccurances[type] == 0)
+ // Static local helper functions //////////////////////////////////////////////
+
+ static void warnMaterial(const std::string &type)
{
- cerr << "could not create material type '"<< type <<
- "'. Replacing with default material." << endl;
- }
- numOccurances[type]++;
-}
-
-// SceneParser definitions ////////////////////////////////////////////////////
-
-TriangleMeshSceneParser::TriangleMeshSceneParser(cpp::Renderer renderer,
- std::string geometryType) :
- renderer(renderer),
- geometryType(geometryType),
- alpha(false),
- shouldCreateDefaultMaterial(true),
- maxObjectsToConsider((uint32_t)-1),
- forceInstancing(false),
- forceNoInstancing(false),
- msgModel(new miniSG::Model)
-{
-}
-
-bool TriangleMeshSceneParser::parse(int ac, const char **&av)
-{
- bool total_loadedScene = false;
-
- for (int i = 1; i < ac; i++) {
- bool loadedScene = false;
- const std::string arg = av[i];
- if (arg == "--max-objects") {
- maxObjectsToConsider = atoi(av[++i]);
- } else if (arg == "--force-instancing") {
- forceInstancing = true;
- } else if (arg == "--force-no-instancing") {
- forceNoInstancing = true;
- } else if (arg == "--alpha") {
- alpha = true;
- } else if (arg == "--no-default-material") {
- shouldCreateDefaultMaterial = false;
- } else if (arg == "--trianglemesh-type") {
- geometryType = av[++i];
- } else {
- FileName fn = arg;
- if (fn.ext() == "stl") {
- miniSG::importSTL(*msgModel,fn);
- loadedScene = true;
- } else if (fn.ext() == "msg") {
- miniSG::importMSG(*msgModel,fn);
- loadedScene = true;
- } else if (fn.ext() == "tri") {
- miniSG::importTRI(*msgModel,fn);
- loadedScene = true;
- } else if (fn.ext() == "xml") {
- miniSG::importRIVL(*msgModel,fn);
- loadedScene = true;
- } else if (fn.ext() == "obj") {
- miniSG::importOBJ(*msgModel,fn);
- loadedScene = true;
- } else if (fn.ext() == "hbp") {
- miniSG::importHBP(*msgModel,fn);
- loadedScene = true;
- } else if (fn.ext() == "x3d") {
- miniSG::importX3D(*msgModel,fn);
- loadedScene = true;
- } else if (fn.ext() == "astl") {
- miniSG::importSTL(msgAnimation,fn);
- loadedScene = true;
+ static std::map numOccurances;
+ if (numOccurances[type] == 0)
+ {
+ cerr << "could not create material type '"<< type <<
+ "'. Replacing with default material." << endl;
}
- }
- if (loadedScene)
- {
- msgModels.push_back(msgModel);
- sceneModels.push_back(cpp::Model());
- msgModel = new miniSG::Model;
- total_loadedScene = true;
- }
+ numOccurances[type]++;
}
- if (total_loadedScene) {
- finalize();
+ // SceneParser definitions ////////////////////////////////////////////////////
+
+ TriangleMeshSceneParser::TriangleMeshSceneParser(cpp::Renderer renderer,
+ std::string geometryType)
+ : renderer(renderer),
+ geometryType(geometryType),
+ alpha(false),
+ shouldCreateDefaultMaterial(true),
+ maxObjectsToConsider((uint32_t)-1),
+ forceInstancing(false),
+ forceNoInstancing(false),
+ msgModel(new miniSG::Model)
+ {
}
- return total_loadedScene;
-}
+ bool TriangleMeshSceneParser::parse(int ac, const char **&av)
+ {
+ bool total_loadedScene = false;
+
+ for (int i = 1; i < ac; i++) {
+ bool loadedScene = false;
+ const std::string arg = av[i];
+ if (arg == "--max-objects") {
+ maxObjectsToConsider = atoi(av[++i]);
+ } else if (arg == "--force-instancing") {
+ forceInstancing = true;
+ } else if (arg == "--force-no-instancing") {
+ forceNoInstancing = true;
+ } else if (arg == "--alpha") {
+ alpha = true;
+ } else if (arg == "--no-default-material") {
+ shouldCreateDefaultMaterial = false;
+ } else if (arg == "--trianglemesh-type") {
+ geometryType = av[++i];
+ } else {
+ FileName fn = arg;
+ if (fn.ext() == "stl") {
+ miniSG::importSTL(*msgModel,fn);
+ loadedScene = true;
+ } else if (fn.ext() == "msg") {
+ miniSG::importMSG(*msgModel,fn);
+ loadedScene = true;
+ } else if (fn.ext() == "tri") {
+ miniSG::importTRI_xyz(*msgModel,fn);
+ loadedScene = true;
+ } else if (fn.ext() == "xyzs") {
+ miniSG::importTRI_xyzs(*msgModel,fn);
+ loadedScene = true;
+ } else if (fn.ext() == "xml") {
+ miniSG::importRIVL(*msgModel,fn);
+ loadedScene = true;
+ } else if (fn.ext() == "obj") {
+ miniSG::importOBJ(*msgModel,fn);
+ loadedScene = true;
+ } else if (fn.ext() == "hbp") {
+ miniSG::importHBP(*msgModel,fn);
+ loadedScene = true;
+ } else if (fn.ext() == "x3d") {
+ miniSG::importX3D(*msgModel,fn);
+ loadedScene = true;
+ } else if (fn.ext() == "astl") {
+ miniSG::importSTL(msgAnimation,fn);
+ loadedScene = true;
+ }
+ }
-std::deque TriangleMeshSceneParser::model() const
-{
- return sceneModels;
-}
+ if (loadedScene) {
+ msgModels.push_back(msgModel);
+ sceneModels.push_back(cpp::Model());
+ msgModel = new miniSG::Model;
+ total_loadedScene = true;
+ }
+ }
-std::deque TriangleMeshSceneParser::bbox() const
-{
- std::deque bboxes;
- for(auto model : msgModels)
- bboxes.push_back(model.ptr->getBBox());
- return bboxes;
-}
+ if (total_loadedScene)
+ finalize();
-cpp::Material
-TriangleMeshSceneParser::createDefaultMaterial(cpp::Renderer ren)
-{
- if(!shouldCreateDefaultMaterial) return nullptr;
+ return total_loadedScene;
+ }
- static auto ospMat = cpp::Material(nullptr);
+ std::deque TriangleMeshSceneParser::model() const
+ {
+ return sceneModels;
+ }
- if (ospMat.handle()) return ospMat;
+ std::deque TriangleMeshSceneParser::bbox() const
+ {
+ std::deque bboxes;
+ for(auto model : msgModels)
+ bboxes.push_back(model.ptr->getBBox());
+ return bboxes;
+ }
- ospMat = ren.newMaterial("OBJMaterial");
+ cpp::Material
+ TriangleMeshSceneParser::createDefaultMaterial(cpp::Renderer ren)
+ {
+ if(!shouldCreateDefaultMaterial) return nullptr;
- ospMat.set("Kd", .8f, 0.f, 0.f);
- ospMat.commit();
- return ospMat;
-}
+ static auto ospMat = cpp::Material(nullptr);
-cpp::Material TriangleMeshSceneParser::createMaterial(cpp::Renderer ren,
- miniSG::Material *mat)
-{
- if (mat == nullptr) return createDefaultMaterial(ren);
+ if (ospMat.handle()) return ospMat;
- static std::map alreadyCreatedMaterials;
+ ospMat = ren.newMaterial("OBJMaterial");
- if (alreadyCreatedMaterials.find(mat) != alreadyCreatedMaterials.end()) {
- return alreadyCreatedMaterials[mat];
+ ospMat.set("Kd", .8f, 0.f, 0.f);
+ ospMat.commit();
+ return ospMat;
}
- const char *type = mat->getParam("type", "OBJMaterial");
- assert(type);
+ cpp::Material TriangleMeshSceneParser::createMaterial(cpp::Renderer ren,
+ miniSG::Material *mat)
+ {
+ if (mat == nullptr) return createDefaultMaterial(ren);
- cpp::Material ospMat;
- try {
- ospMat = alreadyCreatedMaterials[mat] = ren.newMaterial(type);
- } catch (const std::runtime_error &/*e*/) {
- warnMaterial(type);
- return createDefaultMaterial(ren);
- }
+ static std::map alreadyCreatedMaterials;
+
+ if (alreadyCreatedMaterials.find(mat) != alreadyCreatedMaterials.end()) {
+ return alreadyCreatedMaterials[mat];
+ }
+
+ const char *type = mat->getParam("type", "OBJMaterial");
+ assert(type);
+
+ cpp::Material ospMat;
+ try {
+ ospMat = alreadyCreatedMaterials[mat] = ren.newMaterial(type);
+ } catch (const std::runtime_error &/*e*/) {
+ warnMaterial(type);
+ return createDefaultMaterial(ren);
+ }
- const bool isOBJMaterial = !strcmp(type, "OBJMaterial");
- bool workaround3DMax = false;
- float Tf_prime = 0.f;
-
- // workaround strange behavior of 3DMax exporter (fully transparent scenes)
- // detect d==Tf==1-Tr, correct to d'=1, Tf'=1-d
- if (isOBJMaterial) {
- auto itTr = mat->params.find("Tr");
- auto end = mat->params.end();
- if (itTr != end) {
- auto itd = mat->params.find("d");
- auto itTf = mat->params.find("Tf");
- if (itTf != end && itd != end) {
- const miniSG::Material::Param *pd = itd->second.ptr;
- const miniSG::Material::Param *pTr = itTr->second.ptr;
- const miniSG::Material::Param *pTf = itTf->second.ptr;
- if (pd->type == miniSG::Material::Param::FLOAT &&
- pTf->type == miniSG::Material::Param::FLOAT_3 &&
- pTr->type == miniSG::Material::Param::FLOAT) {
- float d(pd->f[0]);
- vec3f Tf(pTf->f[0], pTf->f[1], pTf->f[2]);
- float Tr(pTr->f[0]);
- if (reduce_max(abs(Tf + Tr - 1.0f)) < 1e-6f &&
- reduce_max(abs(Tf - d)) < 1e-6f) {
- workaround3DMax = true;
- Tf_prime = 1.f - d;
+ const bool isOBJMaterial = !strcmp(type, "OBJMaterial");
+ bool workaround3DMax = false;
+ float Tf_prime = 0.f;
+
+ // workaround strange behavior of 3DMax exporter (fully transparent scenes)
+ // detect d==Tf==1-Tr, correct to d'=1, Tf'=1-d
+ if (isOBJMaterial) {
+ auto itTr = mat->params.find("Tr");
+ auto end = mat->params.end();
+ if (itTr != end) {
+ auto itd = mat->params.find("d");
+ auto itTf = mat->params.find("Tf");
+ if (itTf != end && itd != end) {
+ const miniSG::Material::Param *pd = itd->second.ptr;
+ const miniSG::Material::Param *pTr = itTr->second.ptr;
+ const miniSG::Material::Param *pTf = itTf->second.ptr;
+ if (pd->type == miniSG::Material::Param::FLOAT &&
+ pTf->type == miniSG::Material::Param::FLOAT_3 &&
+ pTr->type == miniSG::Material::Param::FLOAT) {
+ float d(pd->f[0]);
+ vec3f Tf(pTf->f[0], pTf->f[1], pTf->f[2]);
+ float Tr(pTr->f[0]);
+ if (reduce_max(abs(Tf + Tr - 1.0f)) < 1e-6f &&
+ reduce_max(abs(Tf - d)) < 1e-6f) {
+ workaround3DMax = true;
+ Tf_prime = 1.f - d;
+ }
}
}
}
}
- }
- for (auto it = mat->params.begin(); it != mat->params.end(); ++it) {
- const char *name = it->first.c_str();
- const miniSG::Material::Param *p = it->second.ptr;
-
- switch(p->type) {
- case miniSG::Material::Param::INT:
- ospMat.set(name, p->i[0]);
- break;
- case miniSG::Material::Param::FLOAT: {
- float f = p->f[0];
- /* many mtl materials of obj models wrongly store the phong exponent
- 'Ns' in range [0..1], whereas OSPRay's material implementations
- correctly interpret it to be in [0..inf), thus we map ranges here */
- if (isOBJMaterial &&
- (!strcmp(name, "Ns") || !strcmp(name, "ns")) &&
- f < 1.f) {
- f = 1.f/(1.f - f) - 1.f;
- }
- if (workaround3DMax && !strcmp(name, "d"))
- f = 1.0f;
- ospMat.set(name, f);
- } break;
- case miniSG::Material::Param::FLOAT_3:
- if (workaround3DMax && !strcmp(name, "Tf"))
- ospMat.set(name, Tf_prime, Tf_prime, Tf_prime);
- else
- ospMat.set(name, p->f[0], p->f[1], p->f[2]);
- break;
- case miniSG::Material::Param::STRING:
- ospMat.set(name, p->s);
- break;
- case miniSG::Material::Param::TEXTURE:
- {
- miniSG::Texture2D *tex = (miniSG::Texture2D*)p->ptr;
- if (tex) {
- OSPTexture2D ospTex = miniSG::createTexture2D(tex);
- assert(ospTex);
- ospCommit(ospTex);
- ospMat.set(name, ospTex);
- }
- break;
+ for (auto it = mat->params.begin(); it != mat->params.end(); ++it) {
+ const char *name = it->first.c_str();
+ const miniSG::Material::Param *p = it->second.ptr;
+
+ switch(p->type) {
+ case miniSG::Material::Param::INT:
+ ospMat.set(name, p->i[0]);
+ break;
+ case miniSG::Material::Param::FLOAT: {
+ float f = p->f[0];
+ /* many mtl materials of obj models wrongly store the phong exponent
+ 'Ns' in range [0..1], whereas OSPRay's material implementations
+ correctly interpret it to be in [0..inf), thus we map ranges here */
+ if (isOBJMaterial &&
+ (!strcmp(name, "Ns") || !strcmp(name, "ns")) &&
+ f < 1.f) {
+ f = 1.f/(1.f - f) - 1.f;
+ }
+ if (workaround3DMax && !strcmp(name, "d"))
+ f = 1.0f;
+ ospMat.set(name, f);
+ } break;
+ case miniSG::Material::Param::FLOAT_3:
+ if (workaround3DMax && !strcmp(name, "Tf"))
+ ospMat.set(name, Tf_prime, Tf_prime, Tf_prime);
+ else
+ ospMat.set(name, p->f[0], p->f[1], p->f[2]);
+ break;
+ case miniSG::Material::Param::STRING:
+ ospMat.set(name, p->s);
+ break;
+ case miniSG::Material::Param::TEXTURE:
+ {
+ miniSG::Texture2D *tex = (miniSG::Texture2D*)p->ptr;
+ if (tex) {
+ OSPTexture2D ospTex = miniSG::createTexture2D(tex);
+ assert(ospTex);
+ ospCommit(ospTex);
+ ospMat.set(name, ospTex);
+ }
+ break;
+ }
+ default:
+ throw std::runtime_error("unknown material parameter type");
+ };
}
- default:
- throw std::runtime_error("unknown material parameter type");
- };
- }
- ospMat.commit();
- return ospMat;
-}
-
-cpp::Geometry
-TriangleMeshSceneParser::createOSPRayGeometry(miniSG::Model *msgModel,
- miniSG::Mesh *msgMesh)
-{
- // create ospray mesh
- auto ospMesh = alpha ? cpp::Geometry("alpha_aware_triangle_mesh") :
- cpp::Geometry(geometryType);
-
- // add position array to mesh
- OSPData position = ospNewData(msgMesh->position.size(),
- OSP_FLOAT3A,
- &msgMesh->position[0]);
- ospMesh.set("position", position);
-
- // add triangle index array to mesh
- if (!msgMesh->triangleMaterialId.empty()) {
- OSPData primMatID = ospNewData(msgMesh->triangleMaterialId.size(),
- OSP_INT,
- &msgMesh->triangleMaterialId[0]);
- ospMesh.set("prim.materialID", primMatID);
+ ospMat.commit();
+ return ospMat;
}
- // add triangle index array to mesh
- OSPData index = ospNewData(msgMesh->triangle.size(),
- OSP_INT3,
- &msgMesh->triangle[0]);
- assert(msgMesh->triangle.size() > 0);
- ospMesh.set("index", index);
-
- // add normal array to mesh
- if (!msgMesh->normal.empty()) {
- OSPData normal = ospNewData(msgMesh->normal.size(),
- OSP_FLOAT3A,
- &msgMesh->normal[0]);
- assert(msgMesh->normal.size() > 0);
- ospMesh.set("vertex.normal", normal);
- }
+ cpp::Geometry
+ TriangleMeshSceneParser::createOSPRayGeometry(miniSG::Model *msgModel,
+ miniSG::Mesh *msgMesh)
+ {
+ // create ospray mesh
+ auto ospMesh = alpha ? cpp::Geometry("alpha_aware_triangle_mesh") :
+ cpp::Geometry(geometryType);
+
+ // add position array to mesh
+ OSPData position = ospNewData(msgMesh->position.size(),
+ OSP_FLOAT3A,
+ &msgMesh->position[0]);
+ ospMesh.set("position", position);
+
+ // add triangle index array to mesh
+ if (!msgMesh->triangleMaterialId.empty()) {
+ OSPData primMatID = ospNewData(msgMesh->triangleMaterialId.size(),
+ OSP_INT,
+ &msgMesh->triangleMaterialId[0]);
+ ospMesh.set("prim.materialID", primMatID);
+ }
- // add color array to mesh
- if (!msgMesh->color.empty()) {
- OSPData color = ospNewData(msgMesh->color.size(),
- OSP_FLOAT4,
- &msgMesh->color[0]);
- assert(msgMesh->color.size() > 0);
- ospMesh.set("vertex.color", color);
- }
+ // add triangle index array to mesh
+ OSPData index = ospNewData(msgMesh->triangle.size(),
+ OSP_INT3,
+ &msgMesh->triangle[0]);
+ assert(msgMesh->triangle.size() > 0);
+ ospMesh.set("index", index);
+
+ // add normal array to mesh
+ if (!msgMesh->normal.empty()) {
+ OSPData normal = ospNewData(msgMesh->normal.size(),
+ OSP_FLOAT3A,
+ &msgMesh->normal[0]);
+ assert(msgMesh->normal.size() > 0);
+ ospMesh.set("vertex.normal", normal);
+ }
- // add texcoord array to mesh
- if (!msgMesh->texcoord.empty()) {
- OSPData texcoord = ospNewData(msgMesh->texcoord.size(),
- OSP_FLOAT2,
- &msgMesh->texcoord[0]);
- assert(msgMesh->texcoord.size() > 0);
- ospMesh.set("vertex.texcoord", texcoord);
- }
+ // add color array to mesh
+ if (!msgMesh->color.empty()) {
+ OSPData color = ospNewData(msgMesh->color.size(),
+ OSP_FLOAT4,
+ &msgMesh->color[0]);
+ assert(msgMesh->color.size() > 0);
+ ospMesh.set("vertex.color", color);
+ }
- ospMesh.set("alpha_type", 0);
- ospMesh.set("alpha_component", 4);
-
- // add triangle material id array to mesh
- if (msgMesh->materialList.empty()) {
- // we have a single material for this mesh...
- auto singleMaterial = createMaterial(renderer, msgMesh->material.ptr);
- ospMesh.setMaterial(singleMaterial);
- } else {
- // we have an entire material list, assign that list
- std::vector materialList;
- std::vector alphaMaps;
- std::vector alphas;
- for (size_t i = 0; i < msgMesh->materialList.size(); i++) {
- auto m = createMaterial(renderer, msgMesh->materialList[i].ptr);
- auto handle = m.handle();
- materialList.push_back(handle);
-
- for (auto it = msgMesh->materialList[i]->params.begin();
- it != msgMesh->materialList[i]->params.end();
- it++) {
- const char *name = it->first.c_str();
- const miniSG::Material::Param *p = it->second.ptr;
- if(p->type == miniSG::Material::Param::TEXTURE) {
- if(!strcmp(name, "map_kd") || !strcmp(name, "map_Kd")) {
- miniSG::Texture2D *tex = (miniSG::Texture2D*)p->ptr;
- OSPTexture2D ospTex = createTexture2D(tex);
- ospCommit(ospTex);
- alphaMaps.push_back(ospTex);
+ // add texcoord array to mesh
+ if (!msgMesh->texcoord.empty()) {
+ OSPData texcoord = ospNewData(msgMesh->texcoord.size(),
+ OSP_FLOAT2,
+ &msgMesh->texcoord[0]);
+ assert(msgMesh->texcoord.size() > 0);
+ ospMesh.set("vertex.texcoord", texcoord);
+ }
+
+ ospMesh.set("alpha_type", 0);
+ ospMesh.set("alpha_component", 4);
+
+ // add triangle material id array to mesh
+ if (msgMesh->materialList.empty()) {
+ // we have a single material for this mesh...
+ auto singleMaterial = createMaterial(renderer, msgMesh->material.ptr);
+ ospMesh.setMaterial(singleMaterial);
+ } else {
+ // we have an entire material list, assign that list
+ std::vector materialList;
+ std::vector alphaMaps;
+ std::vector alphas;
+ for (size_t i = 0; i < msgMesh->materialList.size(); i++) {
+ auto m = createMaterial(renderer, msgMesh->materialList[i].ptr);
+ auto handle = m.handle();
+ materialList.push_back(handle);
+
+ for (auto it = msgMesh->materialList[i]->params.begin();
+ it != msgMesh->materialList[i]->params.end();
+ it++) {
+ const char *name = it->first.c_str();
+ const miniSG::Material::Param *p = it->second.ptr;
+ if(p->type == miniSG::Material::Param::TEXTURE) {
+ if(!strcmp(name, "map_kd") || !strcmp(name, "map_Kd")) {
+ miniSG::Texture2D *tex = (miniSG::Texture2D*)p->ptr;
+ OSPTexture2D ospTex = createTexture2D(tex);
+ ospCommit(ospTex);
+ alphaMaps.push_back(ospTex);
+ }
+ } else if(p->type == miniSG::Material::Param::FLOAT) {
+ if(!strcmp(name, "d")) alphas.push_back(p->f[0]);
}
- } else if(p->type == miniSG::Material::Param::FLOAT) {
- if(!strcmp(name, "d")) alphas.push_back(p->f[0]);
}
- }
- while(materialList.size() > alphaMaps.size()) {
- alphaMaps.push_back(nullptr);
- }
- while(materialList.size() > alphas.size()) {
- alphas.push_back(0.f);
+ while(materialList.size() > alphaMaps.size()) {
+ alphaMaps.push_back(nullptr);
+ }
+ while(materialList.size() > alphas.size()) {
+ alphas.push_back(0.f);
+ }
}
- }
- auto ospMaterialList = cpp::Data(materialList.size(),
- OSP_OBJECT,
- &materialList[0]);
- ospMesh.set("materialList", ospMaterialList);
-
- if(alpha) {
- auto ospAlphaMapList = cpp::Data(alphaMaps.size(),
+ auto ospMaterialList = cpp::Data(materialList.size(),
OSP_OBJECT,
- &alphaMaps[0]);
- ospMesh.set("alpha_maps", ospAlphaMapList);
-
- auto ospAlphaList = cpp::Data(alphas.size(),
- OSP_OBJECT,
- &alphas[0]);
- ospMesh.set("alphas", ospAlphaList);
+ &materialList[0]);
+ ospMesh.set("materialList", ospMaterialList);
+
+ if(alpha) {
+ auto ospAlphaMapList = cpp::Data(alphaMaps.size(),
+ OSP_OBJECT,
+ &alphaMaps[0]);
+ ospMesh.set("alpha_maps", ospAlphaMapList);
+
+ auto ospAlphaList = cpp::Data(alphas.size(),
+ OSP_OBJECT,
+ &alphas[0]);
+ ospMesh.set("alphas", ospAlphaList);
+ }
}
- }
-
- ospMesh.commit();
- return ospMesh;
-}
+ ospMesh.commit();
-void TriangleMeshSceneParser::finalize()
-{
- if (forceInstancing && forceNoInstancing) {
- throw std::runtime_error("You can't force BOTH instancing and"
- " no-instancing!");
+ return ospMesh;
}
- for (size_t modeli = 0; modeli < msgModels.size(); modeli++)
+ void TriangleMeshSceneParser::finalize()
{
- ospcommon::Ref msgModel = msgModels[modeli];
- ospray::cpp::Model* sceneModel = &sceneModels[modeli];
- // code does not yet do instancing ... check that the model doesn't
- // contain instances
- bool doesInstancing = forceInstancing ||
- (msgModel->instance.size() > msgModel->mesh.size()
- && !forceNoInstancing);
-
- if (msgModel->instance.size() > maxObjectsToConsider)
- msgModel->instance.resize(maxObjectsToConsider);
-
- if (!doesInstancing) {
- for (size_t i = 0; i < msgModel->instance.size(); i++) {
- auto &msgInstance = msgModel->instance[i];
- auto &msgMesh = msgModel->mesh[msgInstance.meshID];
-
- // check if we have to transform the vertices:
- if (msgInstance != miniSG::Instance(i)) {
- auto positionCopy = msgMesh->position;
-
- for (size_t vID = 0; vID < msgMesh->position.size(); vID++) {
- msgMesh->position[vID] = xfmPoint(msgModel->instance[i].xfm,
- msgMesh->position[vID]);
- }
-
- sceneModel->addGeometry(createOSPRayGeometry(msgModel.ptr,
- msgMesh.ptr).handle());
+ if (forceInstancing && forceNoInstancing) {
+ throw std::runtime_error("You can't force BOTH instancing and"
+ " no-instancing!");
+ }
- msgMesh->position = positionCopy;
+ for (size_t modeli = 0; modeli < msgModels.size(); modeli++)
+ {
+ ospcommon::Ref msgModel = msgModels[modeli];
+ ospray::cpp::Model* sceneModel = &sceneModels[modeli];
+ // code does not yet do instancing ... check that the model doesn't
+ // contain instances
+ bool doesInstancing = forceInstancing ||
+ (msgModel->instance.size() > msgModel->mesh.size()
+ && !forceNoInstancing);
+
+ if (msgModel->instance.size() > maxObjectsToConsider)
+ msgModel->instance.resize(maxObjectsToConsider);
+
+ if (!doesInstancing) {
+ for (size_t i = 0; i < msgModel->instance.size(); i++) {
+ auto &msgInstance = msgModel->instance[i];
+ auto &msgMesh = msgModel->mesh[msgInstance.meshID];
+
+ // check if we have to transform the vertices:
+ if (msgInstance != miniSG::Instance(i)) {
+ auto positionCopy = msgMesh->position;
+
+ for (size_t vID = 0; vID < msgMesh->position.size(); vID++) {
+ msgMesh->position[vID] = xfmPoint(msgModel->instance[i].xfm,
+ msgMesh->position[vID]);
+ }
+
+ sceneModel->addGeometry(createOSPRayGeometry(msgModel.ptr,
+ msgMesh.ptr).handle());
+
+ msgMesh->position = positionCopy;
+ } else {
+ sceneModel->addGeometry(createOSPRayGeometry(msgModel.ptr,
+ msgMesh.ptr).handle());
+ }
+ }
} else {
- sceneModel->addGeometry(createOSPRayGeometry(msgModel.ptr,
- msgMesh.ptr).handle());
- }
- }
- } else {
- std::vector instanceModels;
+ std::vector instanceModels;
- for (size_t i = 0; i < msgModel->mesh.size(); i++) {
- Ref msgMesh = msgModel->mesh[i];
+ for (size_t i = 0; i < msgModel->mesh.size(); i++) {
+ Ref msgMesh = msgModel->mesh[i];
- auto ospMesh = createOSPRayGeometry(msgModel.ptr, msgMesh.ptr);
+ auto ospMesh = createOSPRayGeometry(msgModel.ptr, msgMesh.ptr);
- cpp::Model model_i;
- model_i.addGeometry(ospMesh);
- model_i.commit();
- instanceModels.push_back(model_i.handle());
- }
+ cpp::Model model_i;
+ model_i.addGeometry(ospMesh);
+ model_i.commit();
+ instanceModels.push_back(model_i.handle());
+ }
- for (size_t i = 0; i < msgModel->instance.size(); i++) {
- OSPGeometry inst =
- ospNewInstance(instanceModels[msgModel->instance[i].meshID],
- reinterpret_cast(msgModel->instance[i].xfm));
- sceneModel->addGeometry(inst);
- }
- }
+ for (size_t i = 0; i < msgModel->instance.size(); i++) {
+ OSPGeometry inst =
+ ospNewInstance(instanceModels[msgModel->instance[i].meshID],
+ reinterpret_cast(msgModel->instance[i].xfm));
+ sceneModel->addGeometry(inst);
+ }
+ }
- sceneModel->commit();
+ sceneModel->commit();
+ }
}
-}
+
+} // ::commandline
diff --git a/apps/common/commandline/SceneParser/trianglemesh/TriangleMeshSceneParser.h b/apps/common/commandline/SceneParser/trianglemesh/TriangleMeshSceneParser.h
index de30bd22e5..e5e199b840 100644
--- a/apps/common/commandline/SceneParser/trianglemesh/TriangleMeshSceneParser.h
+++ b/apps/common/commandline/SceneParser/trianglemesh/TriangleMeshSceneParser.h
@@ -21,43 +21,47 @@
#include
#include
-class OSPRAY_COMMANDLINE_INTERFACE TriangleMeshSceneParser : public SceneParser
-{
-public:
- TriangleMeshSceneParser(ospray::cpp::Renderer renderer,
- std::string geometryType = "triangles");
+namespace commandline {
- bool parse(int ac, const char **&av) override;
+ class OSPRAY_COMMANDLINE_INTERFACE TriangleMeshSceneParser : public SceneParser
+ {
+ public:
+ TriangleMeshSceneParser(ospray::cpp::Renderer renderer,
+ std::string geometryType = "triangles");
- std::deque model() const override;
- std::deque bbox() const override;
- ospray::cpp::Geometry createOSPRayGeometry(ospray::miniSG::Model *msgModel,
- ospray::miniSG::Mesh *msgMesh);
+ bool parse(int ac, const char **&av) override;
-private:
+ std::deque model() const override;
+ std::deque bbox() const override;
+ ospray::cpp::Geometry createOSPRayGeometry(ospray::miniSG::Model *msgModel,
+ ospray::miniSG::Mesh *msgMesh);
- ospray::cpp::Material createDefaultMaterial(ospray::cpp::Renderer renderer);
- ospray::cpp::Material createMaterial(ospray::cpp::Renderer renderer,
- ospray::miniSG::Material *mat);
+ private:
- ospray::cpp::Renderer renderer;
+ ospray::cpp::Material createDefaultMaterial(ospray::cpp::Renderer renderer);
+ ospray::cpp::Material createMaterial(ospray::cpp::Renderer renderer,
+ ospray::miniSG::Material *mat);
- std::deque sceneModels;
+ ospray::cpp::Renderer renderer;
- std::string geometryType;
+ std::deque sceneModels;
- bool alpha;
- bool shouldCreateDefaultMaterial;
- unsigned int maxObjectsToConsider;
+ std::string geometryType;
- // if turned on, we'll put each triangle mesh into its own instance,
- // no matter what
- bool forceInstancing;
- bool forceNoInstancing;
+ bool alpha;
+ bool shouldCreateDefaultMaterial;
+ unsigned int maxObjectsToConsider;
- ospcommon::Ref msgModel;
- std::deque > msgModels;
- std::vector msgAnimation;
+ // if turned on, we'll put each triangle mesh into its own instance,
+ // no matter what
+ bool forceInstancing;
+ bool forceNoInstancing;
- void finalize();
-};
+ ospcommon::Ref msgModel;
+ std::deque > msgModels;
+ std::vector msgAnimation;
+
+ void finalize();
+ };
+
+} // ::commandline
diff --git a/apps/common/commandline/SceneParser/volume/VolumeSceneParser.cpp b/apps/common/commandline/SceneParser/volume/VolumeSceneParser.cpp
index 1db1be8e4b..7f2facba1e 100644
--- a/apps/common/commandline/SceneParser/volume/VolumeSceneParser.cpp
+++ b/apps/common/commandline/SceneParser/volume/VolumeSceneParser.cpp
@@ -18,250 +18,254 @@
#include
-using namespace ospray;
-using namespace ospcommon;
-
#include "common/importer/Importer.h"
#include "common/tfn_lib/tfn_lib.h"
#include
-using std::cerr;
-using std::endl;
-
#include
-// SceneParser definitions ////////////////////////////////////////////////////
-
-VolumeSceneParser::VolumeSceneParser(cpp::Renderer renderer) :
- renderer(renderer)
-{
-}
-
-bool VolumeSceneParser::parse(int ac, const char **&av)
-{
- bool loadedScene = false;
- bool loadedTransferFunction = false;
-
- FileName scene;
-
- for (int i = 1; i < ac; i++) {
- const std::string arg = av[i];
- if (arg == "-s" || arg == "--sampling-rate") {
- samplingRate = atof(av[++i]);
- } else if (arg == "-tfc" || arg == "--tf-color") {
- ospcommon::vec4f color;
- color.x = atof(av[++i]);
- color.y = atof(av[++i]);
- color.z = atof(av[++i]);
- color.w = atof(av[++i]);
- tf_colors.push_back(color);
- } else if (arg == "-tfs" || arg == "--tf-scale") {
- tf_scale = atof(av[++i]);
- } else if (arg == "-tff" || arg == "--tf-file") {
- importTransferFunction(std::string(av[++i]));
- loadedTransferFunction = true;
- } else if (arg == "-is" || arg == "--surface") {
- isosurfaces.push_back(atof(av[++i]));
- } else {
- FileName fn = arg;
- if (fn.ext() == "osp") {
- scene = arg;
- loadedScene = true;
+namespace commandline {
+
+ using namespace ospray;
+ using namespace ospcommon;
+
+ using std::cerr;
+ using std::endl;
+
+ // SceneParser definitions ////////////////////////////////////////////////////
+
+ VolumeSceneParser::VolumeSceneParser(cpp::Renderer renderer) :
+ renderer(renderer)
+ {
+ }
+
+ bool VolumeSceneParser::parse(int ac, const char **&av)
+ {
+ bool loadedScene = false;
+ bool loadedTransferFunction = false;
+
+ FileName scene;
+
+ for (int i = 1; i < ac; i++) {
+ const std::string arg = av[i];
+ if (arg == "-s" || arg == "--sampling-rate") {
+ samplingRate = atof(av[++i]);
+ } else if (arg == "-tfc" || arg == "--tf-color") {
+ ospcommon::vec4f color;
+ color.x = atof(av[++i]);
+ color.y = atof(av[++i]);
+ color.z = atof(av[++i]);
+ color.w = atof(av[++i]);
+ tf_colors.push_back(color);
+ } else if (arg == "-tfs" || arg == "--tf-scale") {
+ tf_scale = atof(av[++i]);
+ } else if (arg == "-tff" || arg == "--tf-file") {
+ importTransferFunction(std::string(av[++i]));
+ loadedTransferFunction = true;
+ } else if (arg == "-is" || arg == "--surface") {
+ isosurfaces.push_back(atof(av[++i]));
+ } else {
+ FileName fn = arg;
+ if (fn.ext() == "osp") {
+ scene = arg;
+ loadedScene = true;
+ }
}
}
- }
- if (loadedScene) {
- sceneModel = make_unique();
- if (!loadedTransferFunction) {
- createDefaultTransferFunction();
+ if (loadedScene) {
+ sceneModel = make_unique();
+ if (!loadedTransferFunction) {
+ createDefaultTransferFunction();
+ }
+ importObjectsFromFile(scene, loadedTransferFunction);
}
- importObjectsFromFile(scene, loadedTransferFunction);
+
+ return loadedScene;
+ }
+
+ std::deque VolumeSceneParser::model() const
+ {
+ std::deque models;
+ models.push_back(sceneModel == nullptr ? cpp::Model() : *sceneModel);
+ return models;
+ // return sceneModel.get() == nullptr ? cpp::Model() : *sceneModel;
}
- return loadedScene;
-}
-
-std::deque VolumeSceneParser::model() const
-{
- std::deque models;
- models.push_back(sceneModel == nullptr ? cpp::Model() : *sceneModel);
- return models;
- // return sceneModel.get() == nullptr ? cpp::Model() : *sceneModel;
-}
-
-std::deque VolumeSceneParser::bbox() const
-{
- std::deque boxes;
- boxes.push_back(sceneBbox);
- return boxes;
-}
-
-void VolumeSceneParser::importObjectsFromFile(const std::string &filename,
- bool loadedTransferFunction)
-{
- auto &model = *sceneModel;
-
- // Load OSPRay objects from a file.
- ospray::importer::Group *imported = ospray::importer::import(filename);
-
- // Iterate over geometries
- for (size_t i = 0; i < imported->geometry.size(); i++) {
- auto geometry = ospray::cpp::Geometry(imported->geometry[i]->handle);
- geometry.commit();
- model.addGeometry(geometry);
+ std::deque VolumeSceneParser::bbox() const
+ {
+ std::deque boxes;
+ boxes.push_back(sceneBbox);
+ return boxes;
}
- // Iterate over volumes
- for (size_t i = 0 ; i < imported->volume.size(); i++) {
- ospray::importer::Volume *vol = imported->volume[i];
- auto volume = ospray::cpp::Volume(vol->handle);
-
- // For now we set the same transfer function on all volumes.
- volume.set("transferFunction", transferFunction);
- volume.set("samplingRate", samplingRate);
- volume.commit();
-
- // Add the loaded volume(s) to the model.
- model.addVolume(volume);
-
- // Set the minimum and maximum values in the domain for both color and
- // opacity components of the transfer function if we didn't load a transfer
- // function for a file (in that case this is already set)
- if (!loadedTransferFunction) {
- transferFunction.set("valueRange", vol->voxelRange.x, vol->voxelRange.y);
- transferFunction.commit();
+ void VolumeSceneParser::importObjectsFromFile(const std::string &filename,
+ bool loadedTransferFunction)
+ {
+ auto &model = *sceneModel;
+
+ // Load OSPRay objects from a file.
+ ospray::importer::Group *imported = ospray::importer::import(filename);
+
+ // Iterate over geometries
+ for (size_t i = 0; i < imported->geometry.size(); i++) {
+ auto geometry = ospray::cpp::Geometry(imported->geometry[i]->handle);
+ geometry.commit();
+ model.addGeometry(geometry);
}
- //sceneBbox.extend(vol->bounds);
- sceneBbox = vol->bounds;
+ // Iterate over volumes
+ for (size_t i = 0 ; i < imported->volume.size(); i++) {
+ ospray::importer::Volume *vol = imported->volume[i];
+ auto volume = ospray::cpp::Volume(vol->handle);
+
+ // For now we set the same transfer function on all volumes.
+ volume.set("transferFunction", transferFunction);
+ volume.set("samplingRate", samplingRate);
+ volume.commit();
+
+ // Add the loaded volume(s) to the model.
+ model.addVolume(volume);
+
+ // Set the minimum and maximum values in the domain for both color and
+ // opacity components of the transfer function if we didn't load a transfer
+ // function for a file (in that case this is already set)
+ if (!loadedTransferFunction) {
+ transferFunction.set("valueRange", vol->voxelRange.x, vol->voxelRange.y);
+ transferFunction.commit();
+ }
+
+ //sceneBbox.extend(vol->bounds);
+ sceneBbox = vol->bounds;
- // Create any specified isosurfaces
- if (!isosurfaces.empty()) {
- auto isoValueData = ospray::cpp::Data(isosurfaces.size(), OSP_FLOAT,
- isosurfaces.data());
- auto isoGeometry = ospray::cpp::Geometry("isosurfaces");
+ // Create any specified isosurfaces
+ if (!isosurfaces.empty()) {
+ auto isoValueData = ospray::cpp::Data(isosurfaces.size(), OSP_FLOAT,
+ isosurfaces.data());
+ auto isoGeometry = ospray::cpp::Geometry("isosurfaces");
- isoGeometry.set("isovalues", isoValueData);
- isoGeometry.set("volume", volume);
- isoGeometry.commit();
+ isoGeometry.set("isovalues", isoValueData);
+ isoGeometry.set("volume", volume);
+ isoGeometry.commit();
- model.addGeometry(isoGeometry);
+ model.addGeometry(isoGeometry);
+ }
}
- }
- model.commit();
-}
+ model.commit();
+ }
-void VolumeSceneParser::importTransferFunction(const std::string &filename)
-{
- tfn::TransferFunction fcn(filename);
- auto colorsData = ospray::cpp::Data(fcn.rgbValues.size(), OSP_FLOAT3,
- fcn.rgbValues.data());
- auto tfFromEnv = getEnvVar("OSPRAY_USE_TF_TYPE");
+ void VolumeSceneParser::importTransferFunction(const std::string &filename)
+ {
+ tfn::TransferFunction fcn(filename);
+ auto colorsData = ospray::cpp::Data(fcn.rgbValues.size(), OSP_FLOAT3,
+ fcn.rgbValues.data());
+ auto tfFromEnv = getEnvVar("OSPRAY_USE_TF_TYPE");
- if (tfFromEnv.first) {
- transferFunction = cpp::TransferFunction(tfFromEnv.second);
- } else {
- transferFunction = cpp::TransferFunction("piecewise_linear");
- }
- transferFunction.set("colors", colorsData);
-
- tf_scale = fcn.opacityScaling;
- // Sample the opacity values, taking 256 samples to match the volume viewer
- // the volume viewer does the sampling a bit differently so we match that
- // instead of what's done in createDefault
- std::vector opacityValues;
- const int N_OPACITIES = 256;
- size_t lo = 0;
- size_t hi = 1;
- for (int i = 0; i < N_OPACITIES; ++i) {
- const float x = float(i) / float(N_OPACITIES - 1);
- float opacity = 0;
- if (i == 0) {
- opacity = fcn.opacityValues[0].y;
- } else if (i == N_OPACITIES - 1) {
- opacity = fcn.opacityValues.back().y;
+ if (tfFromEnv.first) {
+ transferFunction = cpp::TransferFunction(tfFromEnv.second);
} else {
- // If we're over this val, find the next segment
- if (x > fcn.opacityValues[lo].x) {
- for (size_t j = lo; j < fcn.opacityValues.size() - 1; ++j) {
- if (x <= fcn.opacityValues[j + 1].x) {
- lo = j;
- hi = j + 1;
- break;
+ transferFunction = cpp::TransferFunction("piecewise_linear");
+ }
+ transferFunction.set("colors", colorsData);
+
+ tf_scale = fcn.opacityScaling;
+ // Sample the opacity values, taking 256 samples to match the volume viewer
+ // the volume viewer does the sampling a bit differently so we match that
+ // instead of what's done in createDefault
+ std::vector opacityValues;
+ const int N_OPACITIES = 256;
+ size_t lo = 0;
+ size_t hi = 1;
+ for (int i = 0; i < N_OPACITIES; ++i) {
+ const float x = float(i) / float(N_OPACITIES - 1);
+ float opacity = 0;
+ if (i == 0) {
+ opacity = fcn.opacityValues[0].y;
+ } else if (i == N_OPACITIES - 1) {
+ opacity = fcn.opacityValues.back().y;
+ } else {
+ // If we're over this val, find the next segment
+ if (x > fcn.opacityValues[lo].x) {
+ for (size_t j = lo; j < fcn.opacityValues.size() - 1; ++j) {
+ if (x <= fcn.opacityValues[j + 1].x) {
+ lo = j;
+ hi = j + 1;
+ break;
+ }
}
}
+ const float delta = x - fcn.opacityValues[lo].x;
+ const float interval = fcn.opacityValues[hi].x - fcn.opacityValues[lo].x;
+ if (delta == 0 || interval == 0) {
+ opacity = fcn.opacityValues[lo].y;
+ } else {
+ opacity = fcn.opacityValues[lo].y + delta / interval
+ * (fcn.opacityValues[hi].y - fcn.opacityValues[lo].y);
+ }
}
- const float delta = x - fcn.opacityValues[lo].x;
- const float interval = fcn.opacityValues[hi].x - fcn.opacityValues[lo].x;
- if (delta == 0 || interval == 0) {
- opacity = fcn.opacityValues[lo].y;
- } else {
- opacity = fcn.opacityValues[lo].y + delta / interval
- * (fcn.opacityValues[hi].y - fcn.opacityValues[lo].y);
- }
+ opacityValues.push_back(tf_scale * opacity);
}
- opacityValues.push_back(tf_scale * opacity);
- }
- auto opacityValuesData = ospray::cpp::Data(opacityValues.size(),
- OSP_FLOAT,
- opacityValues.data());
- transferFunction.set("opacities", opacityValuesData);
- transferFunction.set("valueRange", vec2f(fcn.dataValueMin, fcn.dataValueMax));
-
- // Commit transfer function
- transferFunction.commit();
-}
-void VolumeSceneParser::createDefaultTransferFunction()
-{
- auto tfFromEnv = getEnvVar("OSPRAY_USE_TF_TYPE");
-
- if (tfFromEnv.first) {
- transferFunction = cpp::TransferFunction(tfFromEnv.second);
- } else {
- transferFunction = cpp::TransferFunction("piecewise_linear");
- }
+ auto opacityValuesData = ospray::cpp::Data(opacityValues.size(),
+ OSP_FLOAT,
+ opacityValues.data());
+ transferFunction.set("opacities", opacityValuesData);
+ transferFunction.set("valueRange", vec2f(fcn.dataValueMin, fcn.dataValueMax));
- // Add colors
- std::vector colors;
- if (tf_colors.empty()) {
- colors.emplace_back(0.f, 0.f, 0.f, 0.f);
- colors.emplace_back(0.9f, 0.9f, 0.9f, 1.f);
- } else {
- colors = tf_colors;
+ // Commit transfer function
+ transferFunction.commit();
}
- std::vector colorsAsVec3;
- for (auto &c : colors) colorsAsVec3.emplace_back(c.x, c.y, c.z);
- auto colorsData = ospray::cpp::Data(colors.size(), OSP_FLOAT3,
- colorsAsVec3.data());
- transferFunction.set("colors", colorsData);
-
- // Add opacities
- std::vector opacityValues;
-
- const int N_OPACITIES = 64;//NOTE(jda) - This affects image quality and
- // performance!
- const int N_INTERVALS = colors.size() - 1;
- const float OPACITIES_PER_INTERVAL = N_OPACITIES / float(N_INTERVALS);
- for (int i = 0; i < N_OPACITIES; ++i) {
- int lcolor = static_cast(i/OPACITIES_PER_INTERVAL);
- int hcolor = lcolor + 1;
-
- float v0 = colors[lcolor].w;
- float v1 = colors[hcolor].w;
- float t = (i / OPACITIES_PER_INTERVAL) - lcolor;
-
- float opacity = (1-t)*v0 + t*v1;
- if (opacity > 1.f) opacity = 1.f;
- opacityValues.push_back(tf_scale*opacity);
+ void VolumeSceneParser::createDefaultTransferFunction()
+ {
+ auto tfFromEnv = getEnvVar("OSPRAY_USE_TF_TYPE");
+
+ if (tfFromEnv.first) {
+ transferFunction = cpp::TransferFunction(tfFromEnv.second);
+ } else {
+ transferFunction = cpp::TransferFunction("piecewise_linear");
+ }
+
+ // Add colors
+ std::vector colors;
+ if (tf_colors.empty()) {
+ colors.emplace_back(0.f, 0.f, 0.f, 0.f);
+ colors.emplace_back(0.9f, 0.9f, 0.9f, 1.f);
+ } else {
+ colors = tf_colors;
+ }
+ std::vector colorsAsVec3;
+ for (auto &c : colors) colorsAsVec3.emplace_back(c.x, c.y, c.z);
+ auto colorsData = ospray::cpp::Data(colors.size(), OSP_FLOAT3,
+ colorsAsVec3.data());
+ transferFunction.set("colors", colorsData);
+
+ // Add opacities
+ std::vector opacityValues;
+
+ const int N_OPACITIES = 64;//NOTE(jda) - This affects image quality and
+ // performance!
+ const int N_INTERVALS = colors.size() - 1;
+ const float OPACITIES_PER_INTERVAL = N_OPACITIES / float(N_INTERVALS);
+ for (int i = 0; i < N_OPACITIES; ++i) {
+ int lcolor = static_cast(i/OPACITIES_PER_INTERVAL);
+ int hcolor = lcolor + 1;
+
+ float v0 = colors[lcolor].w;
+ float v1 = colors[hcolor].w;
+ float t = (i / OPACITIES_PER_INTERVAL) - lcolor;
+
+ float opacity = (1-t)*v0 + t*v1;
+ if (opacity > 1.f) opacity = 1.f;
+ opacityValues.push_back(tf_scale*opacity);
+ }
+ auto opacityValuesData = ospray::cpp::Data(opacityValues.size(),
+ OSP_FLOAT,
+ opacityValues.data());
+ transferFunction.set("opacities", opacityValuesData);
+
+ // Commit transfer function
+ transferFunction.commit();
}
- auto opacityValuesData = ospray::cpp::Data(opacityValues.size(),
- OSP_FLOAT,
- opacityValues.data());
- transferFunction.set("opacities", opacityValuesData);
-
- // Commit transfer function
- transferFunction.commit();
-}
+
+} // ::commandline
diff --git a/apps/common/commandline/SceneParser/volume/VolumeSceneParser.h b/apps/common/commandline/SceneParser/volume/VolumeSceneParser.h
index 278203706a..1630be817e 100644
--- a/apps/common/commandline/SceneParser/volume/VolumeSceneParser.h
+++ b/apps/common/commandline/SceneParser/volume/VolumeSceneParser.h
@@ -26,37 +26,41 @@
#include
#include
-class OSPRAY_COMMANDLINE_INTERFACE VolumeSceneParser : public SceneParser
-{
-public:
- VolumeSceneParser(ospray::cpp::Renderer);
+namespace commandline {
- bool parse(int ac, const char **&av) override;
+ class OSPRAY_COMMANDLINE_INTERFACE VolumeSceneParser : public SceneParser
+ {
+ public:
+ VolumeSceneParser(ospray::cpp::Renderer);
- std::deque model() const override;
- std::deque bbox() const override;
+ bool parse(int ac, const char **&av) override;
-private:
+ std::deque model() const override;
+ std::deque bbox() const override;
- // Helper functions //
+ private:
- void importObjectsFromFile(const std::string &filename,
- bool loadedTransferFunction);
- void importTransferFunction(const std::string &filename);
- void createDefaultTransferFunction();
+ // Helper functions //
- // Data //
+ void importObjectsFromFile(const std::string &filename,
+ bool loadedTransferFunction);
+ void importTransferFunction(const std::string &filename);
+ void createDefaultTransferFunction();
- ospray::cpp::Renderer renderer;
- ospcommon::box3f sceneBbox;
+ // Data //
- std::unique_ptr sceneModel;
+ ospray::cpp::Renderer renderer;
+ ospcommon::box3f sceneBbox;
- float samplingRate{0.125f};
+ std::unique_ptr sceneModel;
- float tf_scale{1.f};
- std::vector tf_colors;
- std::vector isosurfaces;
+ float samplingRate{0.125f};
- ospray::cpp::TransferFunction transferFunction;
-};
+ float tf_scale{1.f};
+ std::vector tf_colors;
+ std::vector isosurfaces;
+
+ ospray::cpp::TransferFunction transferFunction;
+ };
+
+} // ::commandline
diff --git a/apps/common/commandline/Utility.h b/apps/common/commandline/Utility.h
index ae2f0b7f18..6123907e07 100644
--- a/apps/common/commandline/Utility.h
+++ b/apps/common/commandline/Utility.h
@@ -28,59 +28,117 @@
#include
#include
-inline void parseForLoadingModules(int ac, const char**& av)
-{
- for (int i = 1; i < ac; i++) {
- const std::string arg = av[i];
- if (arg == "--module" || arg == "-m") {
- ospLoadModule(av[++i]);
+namespace commandline {
+
+ inline void parseForLoadingModules(int ac, const char**& av)
+ {
+ for (int i = 1; i < ac; i++) {
+ const std::string arg = av[i];
+ if (arg == "--module" || arg == "-m") {
+ ospLoadModule(av[++i]);
+ }
}
}
-}
-
-using ParsedOSPObjects = std::tuple,
- std::deque,
- ospray::cpp::Renderer,
- ospray::cpp::Camera>;
-
-template
-inline ParsedOSPObjects parseCommandLine(int ac, const char **&av)
-{
- static_assert(std::is_base_of::value,
- "RendererParser_T is not a subclass of RendererParser.");
- static_assert(std::is_base_of::value,
- "CameraParser_T is not a subclass of CameraParser.");
- static_assert(std::is_base_of::value,
- "SceneParser_T is not a subclass of SceneParser.");
- static_assert(std::is_base_of::value,
- "LightsParser_T is not a subclass of LightsParser.");
-
- parseForLoadingModules(ac, av);
-
- CameraParser_T cameraParser;
- cameraParser.parse(ac, av);
- auto camera = cameraParser.camera();
-
- RendererParser_T rendererParser;
- rendererParser.parse(ac, av);
- auto renderer = rendererParser.renderer();
-
- SceneParser_T sceneParser{rendererParser.renderer()};
- sceneParser.parse(ac, av);
- auto model = sceneParser.model();
- auto bbox = sceneParser.bbox();
-
- LightsParser_T lightsParser(renderer);
- lightsParser.parse(ac, av);
-
- return std::make_tuple(bbox, model, renderer, camera);
-}
-
-inline ParsedOSPObjects parseWithDefaultParsers(int ac, const char**& av)
-{
- return parseCommandLine(ac, av);
-}
+
+ using ParsedOSPObjects = std::tuple,
+ std::deque,
+ ospray::cpp::Renderer,
+ ospray::cpp::Camera>;
+
+ template
+ inline ParsedOSPObjects parseCommandLine(int ac, const char **&av)
+ {
+ static_assert(std::is_base_of::value,
+ "RendererParser_T is not a subclass of RendererParser.");
+ static_assert(std::is_base_of::value,
+ "CameraParser_T is not a subclass of CameraParser.");
+ static_assert(std::is_base_of::value,
+ "SceneParser_T is not a subclass of SceneParser.");
+ static_assert(std::is_base_of::value,
+ "LightsParser_T is not a subclass of LightsParser.");
+
+ parseForLoadingModules(ac, av);
+
+ CameraParser_T cameraParser;
+ cameraParser.parse(ac, av);
+ auto camera = cameraParser.camera();
+
+ RendererParser_T rendererParser;
+ rendererParser.parse(ac, av);
+ auto renderer = rendererParser.create();
+
+ SceneParser_T sceneParser{renderer};
+ sceneParser.parse(ac, av);
+ auto model = sceneParser.model();
+ auto bbox = sceneParser.bbox();
+
+ LightsParser_T lightsParser(renderer);
+ lightsParser.parse(ac, av);
+
+ return std::make_tuple(bbox, model, renderer, camera);
+ }
+
+ inline ParsedOSPObjects parseWithDefaultParsers(int ac, const char**& av)
+ {
+ return parseCommandLine(ac, av);
+ }
+
+ // Display Wall versions ////////////////////////////////////////////////////
+
+ using ParsedOSPObjectsDW = std::tuple,
+ std::deque,
+ ospray::cpp::Renderer,
+ ospray::cpp::Renderer,
+ ospray::cpp::Camera>;
+
+ template
+ inline ParsedOSPObjectsDW parseCommandLineDW(int ac, const char **&av)
+ {
+ static_assert(std::is_base_of::value,
+ "RendererParser_T is not a subclass of RendererParser.");
+ static_assert(std::is_base_of::value,
+ "CameraParser_T is not a subclass of CameraParser.");
+ static_assert(std::is_base_of::value,
+ "SceneParser_T is not a subclass of SceneParser.");
+ static_assert(std::is_base_of::value,
+ "LightsParser_T is not a subclass of LightsParser.");
+
+ parseForLoadingModules(ac, av);
+
+ CameraParser_T cameraParser;
+ cameraParser.parse(ac, av);
+ auto camera = cameraParser.camera();
+
+ RendererParser_T rendererParser;
+ rendererParser.parse(ac, av);
+ auto renderer = rendererParser.create();
+ auto rendererDW = rendererParser.create();
+
+ SceneParser_T sceneParser{renderer};
+ sceneParser.parse(ac, av);
+ auto model = sceneParser.model();
+ auto bbox = sceneParser.bbox();
+
+ LightsParser_T lightsParser(renderer);
+ lightsParser.parse(ac, av);
+
+ LightsParser_T lightsParserDW(rendererDW);
+ lightsParserDW.parse(ac, av);
+
+ return std::make_tuple(bbox, model, renderer, rendererDW, camera);
+ }
+
+ inline ParsedOSPObjectsDW parseWithDefaultParsersDW(int ac, const char**& av)
+ {
+ return parseCommandLineDW(ac, av);
+ }
+
+} // ::commandline
diff --git a/apps/common/importer/CMakeLists.txt b/apps/common/importer/CMakeLists.txt
index 63254907b1..451e9a6576 100644
--- a/apps/common/importer/CMakeLists.txt
+++ b/apps/common/importer/CMakeLists.txt
@@ -18,7 +18,6 @@ INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}/ospray/include
${CMAKE_SOURCE_DIR}/ospray
${CMAKE_SOURCE_DIR}
- ${CMAKE_SOURCE_DIR}/apps/qtViewer
)
OSPRAY_CREATE_LIBRARY(ospray_importer
@@ -28,7 +27,5 @@ OSPRAY_CREATE_LIBRARY(ospray_importer
Importer.cpp
TinyXML2.cpp
LINK
- ospray_common
- ospray
ospray_sg
)
diff --git a/apps/common/importer/Importer.cpp b/apps/common/importer/Importer.cpp
index c36dc048fe..099d5718af 100644
--- a/apps/common/importer/Importer.cpp
+++ b/apps/common/importer/Importer.cpp
@@ -38,46 +38,32 @@ namespace ospray {
Group *group = existingGroupToAddTo;
if (!group) group = new Group;
- if (fileName.ext() == "osp") {
- importOSP(fn, group);
-#if 0 // NOTE(jda) - this can only be re-enabled once the importer stuff is off of Ref<>
-//#ifndef _WIN32
- } else if (fileName.ext() == "osg") {
- Ref world = new sg::World;
- world = sg::loadOSG(fn);
- Ref volumeNode;
- for (auto node : world.ptr->node)
- {
- std::cout << "found node: " << node.ptr->toString() << std::endl;
- if (node->toString().find("Chombo") != std::string::npos)
- volumeNode = Ref((sg::Volume*)node.ptr);
+ if (fileName.ext() == "osp" || fileName.ext() == "osg") {
+ std::shared_ptr world;;
+ std::cout << "loading osp file: \n";
+ world = sg::loadOSP(fn);
+ std::shared_ptr volumeNode;
+ for (auto &node : world->children()) {
+ if (node->type().find("Volume") != std::string::npos)
+ volumeNode = std::dynamic_pointer_cast(node);
}
- if (!volumeNode)
- {
- throw std::runtime_error("#ospray:importer: no volume found in osg file");
+ if (!volumeNode) {
+ throw std::runtime_error("#ospray:importer: no volume found "
+ "in osp file");
}
sg::RenderContext ctx;
- Ref integrator;
- integrator = new sg::Integrator("scivis");
- ctx.integrator = integrator.ptr;
- integrator->commit();
- assert(ctx.world);
- if (!world) {
- std::cout << "#osp:qtv: no world defined. exiting." << std::endl;
- exit(1);
- }
-
- world->render(ctx);
- assert(world->ospModel);
+ world->traverse(ctx, "verify");
+ world->traverse(ctx, "print");
+ world->traverse(ctx, "commit");
OSPVolume volume = volumeNode->volume;
- assert(volume);
Volume* msgVolume = new Volume;
- msgVolume->bounds = volumeNode->getBounds();
+ msgVolume->bounds = volumeNode->bounds();
msgVolume->handle = volumeNode->volume;
+ assert(msgVolume->handle);
+ msgVolume->voxelRange = volumeNode->child("voxelRange").valueAs();
group->volume.push_back(msgVolume);
-#endif
} else if (fileName.ext() == "bob") {
importRM(fn, group);
} else {
@@ -88,5 +74,5 @@ namespace ospray {
return group;
}
- }
-}
+ } // ::ospray::importer
+} // ::ospray
diff --git a/apps/common/importer/Importer.h b/apps/common/importer/Importer.h
index fde35a2331..6db34dfaa5 100644
--- a/apps/common/importer/Importer.h
+++ b/apps/common/importer/Importer.h
@@ -123,7 +123,7 @@ namespace ospray {
OSPIMPORTER_INTERFACE Group *import(const std::string &fileName,
Group *existingGroupToAddTo=nullptr);
- }
+ } // ::ospray::importer
//! Print an error message.
inline void emitMessage(const std::string &kind, const std::string &message)
@@ -151,4 +151,4 @@ namespace ospray {
}
#endif
-}
+} // ::ospray
diff --git a/apps/common/importer/TinyXML2.h b/apps/common/importer/TinyXML2.h
index 9545deb3b3..fa6ce1a775 100644
--- a/apps/common/importer/TinyXML2.h
+++ b/apps/common/importer/TinyXML2.h
@@ -351,14 +351,14 @@ class MemPoolT : public MemPool
}
}
- virtual int ItemSize() const {
+ virtual int ItemSize() const override {
return SIZE;
}
- int CurrentAllocs() const {
+ int CurrentAllocs() const {
return _currentAllocs;
}
- virtual void* Alloc() {
+ virtual void* Alloc() override {
if ( !_root ) {
// Need a new block.
Block* block = new Block();
@@ -381,7 +381,7 @@ class MemPoolT : public MemPool
_nUntracked++;
return result;
}
- virtual void Free( void* mem ) {
+ virtual void Free( void* mem ) override {
if ( !mem ) {
return;
}
@@ -398,7 +398,7 @@ class MemPoolT : public MemPool
name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
}
- void SetTracked() {
+ void SetTracked() override {
_nUntracked--;
}
@@ -883,12 +883,12 @@ class TINYXML2_LIB XMLText : public XMLNode
friend class XMLBase;
friend class XMLDocument;
public:
- virtual bool Accept( XMLVisitor* visitor ) const;
+ virtual bool Accept( XMLVisitor* visitor ) const override;
- virtual XMLText* ToText() {
+ virtual XMLText* ToText() override {
return this;
}
- virtual const XMLText* ToText() const {
+ virtual const XMLText* ToText() const override {
return this;
}
@@ -901,9 +901,9 @@ class TINYXML2_LIB XMLText : public XMLNode
return _isCData;
}
- char* ParseDeep( char*, StrPair* endTag );
- virtual XMLNode* ShallowClone( XMLDocument* document ) const;
- virtual bool ShallowEqual( const XMLNode* compare ) const;
+ char* ParseDeep( char*, StrPair* endTag ) override;
+ virtual XMLNode* ShallowClone( XMLDocument* document ) const override;
+ virtual bool ShallowEqual( const XMLNode* compare ) const override;
protected:
XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
@@ -921,18 +921,18 @@ class TINYXML2_LIB XMLComment : public XMLNode
{
friend class XMLDocument;
public:
- virtual XMLComment* ToComment() {
+ virtual XMLComment* ToComment() override {
return this;
}
- virtual const XMLComment* ToComment() const {
+ virtual const XMLComment* ToComment() const override {
return this;
}
- virtual bool Accept( XMLVisitor* visitor ) const;
+ virtual bool Accept( XMLVisitor* visitor ) const override;
- char* ParseDeep( char*, StrPair* endTag );
- virtual XMLNode* ShallowClone( XMLDocument* document ) const;
- virtual bool ShallowEqual( const XMLNode* compare ) const;
+ char* ParseDeep( char*, StrPair* endTag ) override;
+ virtual XMLNode* ShallowClone( XMLDocument* document ) const override;
+ virtual bool ShallowEqual( const XMLNode* compare ) const override;
protected:
XMLComment( XMLDocument* doc );
@@ -959,18 +959,18 @@ class TINYXML2_LIB XMLDeclaration : public XMLNode
{
friend class XMLDocument;
public:
- virtual XMLDeclaration* ToDeclaration() {
+ virtual XMLDeclaration* ToDeclaration() override {
return this;
}
- virtual const XMLDeclaration* ToDeclaration() const {
+ virtual const XMLDeclaration* ToDeclaration() const override {
return this;
}
- virtual bool Accept( XMLVisitor* visitor ) const;
+ virtual bool Accept( XMLVisitor* visitor ) const override;
- char* ParseDeep( char*, StrPair* endTag );
- virtual XMLNode* ShallowClone( XMLDocument* document ) const;
- virtual bool ShallowEqual( const XMLNode* compare ) const;
+ char* ParseDeep( char*, StrPair* endTag ) override;
+ virtual XMLNode* ShallowClone( XMLDocument* document ) const override;
+ virtual bool ShallowEqual( const XMLNode* compare ) const override;
protected:
XMLDeclaration( XMLDocument* doc );
@@ -991,18 +991,18 @@ class TINYXML2_LIB XMLUnknown : public XMLNode
{
friend class XMLDocument;
public:
- virtual XMLUnknown* ToUnknown() {
+ virtual XMLUnknown* ToUnknown() override {
return this;
}
- virtual const XMLUnknown* ToUnknown() const {
+ virtual const XMLUnknown* ToUnknown() const override {
return this;
}
- virtual bool Accept( XMLVisitor* visitor ) const;
+ virtual bool Accept( XMLVisitor* visitor ) const override;
- char* ParseDeep( char*, StrPair* endTag );
- virtual XMLNode* ShallowClone( XMLDocument* document ) const;
- virtual bool ShallowEqual( const XMLNode* compare ) const;
+ char* ParseDeep( char*, StrPair* endTag ) override;
+ virtual XMLNode* ShallowClone( XMLDocument* document ) const override;
+ virtual bool ShallowEqual( const XMLNode* compare ) const override;
protected:
XMLUnknown( XMLDocument* doc );
@@ -1159,13 +1159,13 @@ class TINYXML2_LIB XMLElement : public XMLNode
SetValue( str, staticMem );
}
- virtual XMLElement* ToElement() {
+ virtual XMLElement* ToElement() override {
return this;
}
- virtual const XMLElement* ToElement() const {
+ virtual const XMLElement* ToElement() const override {
return this;
}
- virtual bool Accept( XMLVisitor* visitor ) const;
+ virtual bool Accept( XMLVisitor* visitor ) const override;
/** Given an attribute name, Attribute() returns the value
for the attribute of that name, or null if none
@@ -1482,9 +1482,9 @@ class TINYXML2_LIB XMLElement : public XMLNode
int ClosingType() const {
return _closingType;
}
- char* ParseDeep( char* p, StrPair* endTag );
- virtual XMLNode* ShallowClone( XMLDocument* document ) const;
- virtual bool ShallowEqual( const XMLNode* compare ) const;
+ char* ParseDeep( char* p, StrPair* endTag ) override;
+ virtual XMLNode* ShallowClone( XMLDocument* document ) const override;
+ virtual bool ShallowEqual( const XMLNode* compare ) const override;
private:
XMLElement( XMLDocument* doc );
@@ -1525,10 +1525,10 @@ class TINYXML2_LIB XMLDocument : public XMLNode
XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
~XMLDocument();
- virtual XMLDocument* ToDocument() {
+ virtual XMLDocument* ToDocument() override {
return this;
}
- virtual const XMLDocument* ToDocument() const {
+ virtual const XMLDocument* ToDocument() const override {
return this;
}
@@ -1620,7 +1620,7 @@ class TINYXML2_LIB XMLDocument : public XMLNode
@endverbatim
*/
void Print( XMLPrinter* streamer=0 ) const;
- virtual bool Accept( XMLVisitor* visitor ) const;
+ virtual bool Accept( XMLVisitor* visitor ) const override;
/**
Create a new Element associated with
@@ -1694,10 +1694,10 @@ class TINYXML2_LIB XMLDocument : public XMLNode
// internal
char* Identify( char* p, XMLNode** node );
- virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
+ virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const override {
return 0;
}
- virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
+ virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const override {
return false;
}
@@ -2012,18 +2012,19 @@ class TINYXML2_LIB XMLPrinter : public XMLVisitor
void PushDeclaration( const char* value );
void PushUnknown( const char* value );
- virtual bool VisitEnter( const XMLDocument& /*doc*/ );
- virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
+ virtual bool VisitEnter( const XMLDocument& /*doc*/ ) override;
+ virtual bool VisitExit( const XMLDocument& /*doc*/ ) override {
return true;
}
- virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
- virtual bool VisitExit( const XMLElement& element );
+ virtual bool VisitEnter( const XMLElement& element,
+ const XMLAttribute* attribute ) override;
+ virtual bool VisitExit( const XMLElement& element ) override;
- virtual bool Visit( const XMLText& text );
- virtual bool Visit( const XMLComment& comment );
- virtual bool Visit( const XMLDeclaration& declaration );
- virtual bool Visit( const XMLUnknown& unknown );
+ virtual bool Visit( const XMLText& text ) override;
+ virtual bool Visit( const XMLComment& comment ) override;
+ virtual bool Visit( const XMLDeclaration& declaration ) override;
+ virtual bool Visit( const XMLUnknown& unknown ) override;
/**
If in print to memory mode, return a pointer to
diff --git a/apps/common/miniSG/importRIVL.cpp b/apps/common/miniSG/importRIVL.cpp
index 226c987c63..0c5e0f468a 100644
--- a/apps/common/miniSG/importRIVL.cpp
+++ b/apps/common/miniSG/importRIVL.cpp
@@ -72,42 +72,53 @@ namespace ospray {
/*! Abstraction for a 'material' that a renderer can query from
any geometry (it's up to the renderer to know what to do with
the respective mateiral type) */
- struct RIVLMaterial : public miniSG::Node {
- virtual string toString() const { return "ospray::miniSG::RIVLMaterial"; }
+ struct RIVLMaterial : public miniSG::Node
+ {
+ virtual string toString() const override
+ { return "ospray::miniSG::RIVLMaterial"; }
Ref general;
};
- struct RIVLCamera : public miniSG::Node {
- virtual string toString() const { return "ospray::miniSG::RIVLCamera"; }
+ struct RIVLCamera : public miniSG::Node
+ {
+ virtual string toString() const override
+ { return "ospray::miniSG::RIVLCamera"; }
vec3f from, at, up;
};
/*! Scene graph grouping node */
- struct Group : public miniSG::Node {
- virtual string toString() const;
+ struct Group : public miniSG::Node
+ {
+ virtual string toString() const override;
std::vector[ > child;
};
/*! scene graph node that contains an ospray geometry type (i.e.,
anything that defines some sort of geometric surface */
- struct Geometry : public miniSG::Node {
- std::vector][ > material;
- virtual string toString() const { return "ospray::miniSG::Geometry"; }
+ struct Geometry : public miniSG::Node
+ {
+ std::vector][> material;
+ virtual string toString() const override
+ { return "ospray::miniSG::Geometry"; }
};
/*! scene graph node that contains an ospray geometry type (i.e.,
anything that defines some sort of geometric surface */
- struct RIVLTexture : public miniSG::Node {
- virtual string toString() const { return "ospray::miniSG::Texture"; }
+ struct RIVLTexture : public miniSG::Node
+ {
+ virtual string toString() const override
+ { return "ospray::miniSG::Texture"; }
Ref texData;
};
/*! scene graph node that contains an ospray geometry type (i.e.,
anything that defines some sort of geometric surface */
- struct Transform : public miniSG::Node {
+ struct Transform : public miniSG::Node
+ {
Ref child;
affine3f xfm;
- virtual string toString() const { return "ospray::miniSG::Transform"; }
+ virtual string toString() const override
+ { return "ospray::miniSG::Transform"; }
};
/*! a triangle mesh with 3 floats and 3 ints for vertex and index
@@ -116,8 +127,9 @@ namespace ospray {
// typename vtx_t=ospray::vec3f,
// typename nor_t=ospray::vec3f,
// typename txt_t=ospray::vec2f>
- struct TriangleMesh : public miniSG::Geometry {
- virtual string toString() const;
+ struct TriangleMesh : public miniSG::Geometry
+ {
+ virtual string toString() const override;
TriangleMesh();
// /*! \brief data handle to vertex data array.
@@ -177,7 +189,6 @@ namespace ospray {
return ss.str();
}
-
std::string Group::toString() const
{
std::stringstream ss;
@@ -206,11 +217,11 @@ namespace ospray {
txt.ptr->texData = new miniSG::Texture2D;
nodeList.push_back(txt.ptr);
- int height = std::stol(node.getProp("height"));
- int width = std::stol(node.getProp("width"));
- int ofs = std::stol(node.getProp("ofs"));
- int channels = std::stol(node.getProp("channels"));
- int depth = std::stol(node.getProp("depth"));
+ size_t height = std::stoll(node.getProp("height"));
+ size_t width = std::stoll(node.getProp("width"));
+ size_t ofs = std::stoll(node.getProp("ofs"));
+ size_t channels = std::stoll(node.getProp("channels"));
+ size_t depth = std::stoll(node.getProp("depth"));
std::string format = node.getProp("format");
txt.ptr->texData->channels = channels;
@@ -248,6 +259,7 @@ namespace ospray {
std::string name = node.getProp("name","");
std::string type = node.getProp("type");
+ mat->setParam("type",strdup(type.c_str()));
xml::for_each_child_of(node,[&](const xml::Node &child){
std::string childNodeType = child.name;
@@ -312,14 +324,17 @@ namespace ospray {
s = NEXT_TOK;
int32_t w = atol(s);
mat->setParam(childName.c_str(), vec4i(x,y,z,w));
+ } else if (!childType.compare("texture")) {
+ std::cout << "not yet handling 'texture' fields in rivl files" << std::endl;
+ } else if (!childType.compare("material")) {
+ std::cout << "not yet handling 'material' fields in rivl files" << std::endl;
} else {
//error!
throw std::runtime_error("unknown parameter type '" + childType + "' when parsing RIVL materials.");
}
free(value);
} else if (!childNodeType.compare("textures")) {
- int num = std::stoll(child.getProp("num","-1"));
-
+ size_t num = std::stoll(child.getProp("num","-1"));
if (child.content == "") {
} else {
char *tokenBuffer = strdup(child.content.c_str());
diff --git a/apps/common/miniSG/importTRI.cpp b/apps/common/miniSG/importTRI.cpp
index 1676a56b74..9d517e0524 100644
--- a/apps/common/miniSG/importTRI.cpp
+++ b/apps/common/miniSG/importTRI.cpp
@@ -22,30 +22,64 @@ namespace ospray {
using std::cout;
using std::endl;
- void importTRI(Model &model,
+ /*! NASA 'tri' format, with three vec3f vertices per triangle (no
+ indices in file) */
+ void importTRI_xyz(Model &model,
const ospcommon::FileName &fileName)
{
FILE *file = fopen(fileName.c_str(),"rb");
if (!file) error("could not open input file");
- int32_t numVertices;
- auto rc = fread(&numVertices,1,sizeof(numVertices),file);
-
Mesh *mesh = new Mesh;
+
+ vec3f tri[3];
+ while (fread(&tri,sizeof(vec3f),3,file) == 3) {
+ mesh->position.push_back(tri[0]);
+ mesh->position.push_back(tri[1]);
+ mesh->position.push_back(tri[2]);
+ }
+ for (size_t i = 0; i < mesh->position.size()/3; i++) {
+ mesh->triangle.push_back(Triangle(vec3i(3*i)+vec3i(0,1,2)));
+ }
+ mesh->material = new Material;
+ mesh->material->name = "OBJ";
+ mesh->material->setParam("Kd", vec3f(.7f));
+
+ model.instance.push_back(Instance(model.mesh.size()));
model.mesh.push_back(mesh);
+ std::cout << "#msg: loaded .tri file of " << mesh->triangle.size()
+ << " triangles" << std::endl;
+ }
+
+ /*! NASA 'tri' format, with three vec3fa vertices per triangle (no
+ indices in file); fourth component per vertex is typically a
+ scalar used for coloring - we ignore that for now */
+ void importTRI_xyzs(Model &model,
+ const ospcommon::FileName &fileName)
+ {
+ FILE *file = fopen(fileName.c_str(),"rb");
+ if (!file) error("could not open input file");
+
+ Mesh *mesh = new Mesh;
- mesh->position.resize(numVertices);
- mesh->normal.resize(numVertices);
- mesh->triangle.resize(numVertices/3);
- rc = fread(&mesh->position[0],numVertices,4*sizeof(float),file);
- rc = fread(&mesh->normal[0],numVertices,4*sizeof(float),file);
- (void)rc;
- for (int i=0;itriangle[i].v0 = 3*i+0;
- mesh->triangle[i].v1 = 3*i+1;
- mesh->triangle[i].v2 = 3*i+2;
+ vec3fa tri[3];
+ while (fread(&tri,sizeof(vec3f),3,file) == 3) {
+ mesh->position.push_back(tri[0]);
+ mesh->position.push_back(tri[1]);
+ mesh->position.push_back(tri[2]);
}
- model.instance.push_back(Instance(0));
+ for (size_t i = 0; i < mesh->position.size()/3; i++) {
+ mesh->triangle.push_back(Triangle(vec3i(3*i)+vec3i(0,1,2)));
+ }
+
+ mesh->material = new Material;
+ mesh->material->name = "OBJ";
+ mesh->material->setParam("Kd", vec3f(.7f));
+
+ model.instance.push_back(Instance(model.mesh.size()));
+ model.mesh.push_back(mesh);
+ std::cout << "#msg: loaded .tri file of " << mesh->triangle.size()
+ << " triangles" << std::endl;
}
} // ::ospray::minisg
diff --git a/apps/common/miniSG/miniSG.h b/apps/common/miniSG/miniSG.h
index 508b2ac37f..a36ad8f652 100644
--- a/apps/common/miniSG/miniSG.h
+++ b/apps/common/miniSG/miniSG.h
@@ -187,6 +187,13 @@ namespace ospray {
};
struct Triangle {
+ Triangle() {}
+ Triangle(uint32_t v0, uint32_t v1, uint32_t v2)
+ : v0(v0), v1(v1), v2(v2)
+ {}
+ Triangle(const vec3i &idx)
+ : v0(idx.x), v1(idx.y), v2(idx.z)
+ {}
uint32_t v0, v1, v2;
};
@@ -261,7 +268,9 @@ namespace ospray {
OSPMINISG_INTERFACE void importHBP(Model &model, const FileName &fileName);
/*! import a TRI file (format:vec3fa[3][numTris]), and add it to the specified model */
- OSPMINISG_INTERFACE void importTRI(Model &model, const FileName &fileName);
+ OSPMINISG_INTERFACE void importTRI_xyz(Model &model, const FileName &fileName);
+ /*! import a TRI file (format:vec3fa[3][numTris]), and add it to the specified model */
+ OSPMINISG_INTERFACE void importTRI_xyzs(Model &model, const FileName &fileName);
/*! import a wavefront OBJ file, and add it to the specified model */
OSPMINISG_INTERFACE void importRIVL(Model &model, const FileName &fileName);
diff --git a/apps/common/script/chaiscript/chaiscript_defines.hpp b/apps/common/script/chaiscript/chaiscript_defines.hpp
index f558847646..edf21dd345 100644
--- a/apps/common/script/chaiscript/chaiscript_defines.hpp
+++ b/apps/common/script/chaiscript/chaiscript_defines.hpp
@@ -75,12 +75,12 @@
#ifdef CHAISCRIPT_HAS_DECLSPEC
#define CHAISCRIPT_MODULE_EXPORT extern "C" __declspec(dllexport)
#else
-#define CHAISCRIPT_MODULE_EXPORT extern "C"
+#define CHAISCRIPT_MODULE_EXPORT extern "C"
#endif
#ifdef CHAISCRIPT_MSVC_12
#define CHAISCRIPT_NOEXCEPT throw()
-#define CHAISCRIPT_CONSTEXPR
+#define CHAISCRIPT_CONSTEXPR
#else
#define CHAISCRIPT_NOEXCEPT noexcept
#define CHAISCRIPT_CONSTEXPR constexpr
diff --git a/apps/common/sg/CMakeLists.txt b/apps/common/sg/CMakeLists.txt
index a3043c7aa5..1e6d8582c1 100644
--- a/apps/common/sg/CMakeLists.txt
+++ b/apps/common/sg/CMakeLists.txt
@@ -21,21 +21,26 @@ OSPRAY_CREATE_LIBRARY(ospray_sg SHARED
SceneGraph.cpp
Renderer.cpp
+ geometry/Geometry.h
geometry/Spheres.cpp
geometry/TriangleMesh.cpp
+ camera/Camera.h
camera/PerspectiveCamera.cpp
- common/Serialization.cpp
common/Common.cpp
+ common/Data.h
+ common/FrameBuffer.cpp
+ common/Light.cpp
+ common/Material.cpp
common/Node.cpp
- common/Integrator.cpp
- common/World.cpp
+ common/RenderContext.h
+ common/Serialization.cpp
+ common/TimeStamp.cpp
common/Texture2D.cpp
- common/Material.cpp
common/Transform.cpp
- common/FrameBuffer.cpp
-
+ common/World.cpp
+
transferFunction/TransferFunction.cpp
volume/Volume.cpp
@@ -45,8 +50,9 @@ OSPRAY_CREATE_LIBRARY(ospray_sg SHARED
# scene graph importers
importer/Importer.cpp
+ importer/importPoints.cpp
+# all these should be lower-case: they're functions, not classes
importer/ImportOSP.cpp
-# importer/ImportOSG.cpp
importer/ImportOBJ.cpp
importer/ImportPLY.cpp
importer/ImportRIVL.cpp
@@ -54,4 +60,5 @@ LINK
ospray
ospray_common
ospray_xml
+ ospray_minisg
)
diff --git a/apps/common/sg/Renderer.cpp b/apps/common/sg/Renderer.cpp
index ed81b83cba..fd5c4e0891 100644
--- a/apps/common/sg/Renderer.cpp
+++ b/apps/common/sg/Renderer.cpp
@@ -20,150 +20,168 @@
namespace ospray {
namespace sg {
- using std::cout;
- using std::endl;
Renderer::Renderer()
- // : ospFrameBuffer(NULL)
- {}
-
- int Renderer::renderFrame()
- {
- if (!integrator) return 1;
- if (!frameBuffer) return 2;
- if (!camera) return 3;
- if (!world) return 4;
-
- assert(integrator->ospRenderer);
-
- if (!world->ospModel) {
- RenderContext rootContext;
- // geometries need the integrator to create materials
- rootContext.integrator = integrator;
- world->render(rootContext);
- assert(world->ospModel);
- }
-
- integrator->setWorld(world);
- integrator->setCamera(camera);
- integrator->commit();
- camera->commit();
-
- ospSet1f(camera->ospCamera,"aspect",frameBuffer->getSize().x/float(frameBuffer->getSize().y));
- ospCommit(camera->ospCamera);
- ospRenderFrame(frameBuffer->getOSPHandle(),
- integrator->getOSPHandle(),
- OSP_FB_COLOR|OSP_FB_ACCUM);
- accumID++;
-
- return 0;
- }
-
- /*! re-start accumulation (for progressive rendering). make sure
- that this function gets called at lesat once every time that
- anything changes that might change the appearance of the
- converged image (e.g., camera position, scene, frame size,
- etc) */
- void Renderer::resetAccumulation()
{
- if (accumID == 0) {
- // cout << "accumID already 0..." << endl;
- } else {
- accumID = 0;
- // cout << "resetting accum" << endl;
- if (frameBuffer)
- frameBuffer->clear();
- }
+ createChild("bounds", "box3f");
+ createChild("rendererType", "string", std::string("scivis"),
+ NodeFlags::required |
+ NodeFlags::valid_whitelist |
+ NodeFlags::gui_combo,
+ "scivis: standard whitted style ray tracer. "
+ "pathtracer/pt: photo-realistic path tracer");
+ child("rendererType").setWhiteList({std::string("scivis"),
+ std::string("sv"),
+ std::string("raytracer"),
+ std::string("rt"),
+ std::string("ao"),
+ std::string("ao1"),
+ std::string("ao2"),
+ std::string("ao4"),
+ std::string("ao8"),
+ std::string("ao16"),
+ std::string("dvr"),
+ std::string("pathtracer"),
+ std::string("pt")});
+ createChild("world",
+ "World").setDocumentation("model containing scene objects");
+ createChild("camera", "PerspectiveCamera");
+ createChild("frameBuffer", "FrameBuffer");
+ createChild("lights");
+
+ createChild("bgColor", "vec3f", vec3f(0.9f, 0.9f, 0.9f),
+ NodeFlags::required |
+ NodeFlags::valid_min_max |
+ NodeFlags::gui_color);
+
+ createChild("spp", "int", 1,
+ NodeFlags::required | NodeFlags::gui_slider,
+ "the number of samples rendered per pixel. The higher "
+ "the number, the smoother the resulting image.");
+ child("spp").setMinMax(-8,128);
+
+ createChild("varianceThreshold", "float", 0.f,
+ NodeFlags::required |
+ NodeFlags::valid_min_max |
+ NodeFlags::gui_slider,
+ "the percent (%) threshold of pixel difference to enable"
+ " tile rendering early termination.");
+ child("varianceThreshold").setMinMax(0.f, 25.f);
+
+ //TODO: move these to seperate SciVisRenderer
+ createChild("shadowsEnabled", "bool", true);
+ createChild("maxDepth", "int", 5,
+ NodeFlags::required | NodeFlags::valid_min_max,
+ "maximum number of ray bounces").setMinMax(0,999);
+ createChild("aoSamples", "int", 1,
+ NodeFlags::required |
+ NodeFlags::valid_min_max |
+ NodeFlags::gui_slider,
+ "AO samples per frame.").setMinMax(0,128);
+
+ createChild("aoDistance", "float", 10000.f,
+ NodeFlags::required | NodeFlags::valid_min_max,
+ "maximum distance ao rays will trace to."
+ " Useful if you do not want a large interior of a"
+ " building to be completely black from occlusion.");
+ child("aoDistance").setMinMax(1e-20f, 1e20f);
+
+ createChild("oneSidedLighting", "bool", true, NodeFlags::required);
+ createChild("aoTransparency", "bool", true, NodeFlags::required);
}
- //! create a default camera
- std::shared_ptr Renderer::createDefaultCamera(vec3f up)
+ void Renderer::traverse(RenderContext &ctx, const std::string& operation)
{
- // create a default camera
- std::shared_ptr camera = std::make_shared();
- if (world) {
-
- // now, determine world bounds to automatically focus the camera
- box3f worldBounds = world->getBounds();
- if (worldBounds == box3f(empty)) {
- cout << "#osp:qtv: world bounding box is empty, using default camera pose" << endl;
- } else {
- cout << "#osp:qtv: found world bounds " << worldBounds << endl;
- cout << "#osp:qtv: focussing default camera on world bounds" << endl;
-
- camera->setAt(center(worldBounds));
- if (up == vec3f(0,0,0))
- up = vec3f(0,1,0);
- camera->setUp(up);
- camera->setFrom(center(worldBounds) + .3f*vec3f(-1,+3,+1.5)*worldBounds.size());
- }
+ if (operation == "render")
+ {
+ preRender(ctx);
+ postRender(ctx);
}
- camera->commit();
- return std::dynamic_pointer_cast(camera);
+ else
+ Node::traverse(ctx,operation);
}
- void Renderer::setCamera(const std::shared_ptr &camera)
+ void Renderer::postRender(RenderContext &ctx)
{
- this->camera = camera;
- if (camera)
- this->camera->commit();
- // if (this->camera) {
- // this->camera->commit();
- // }
- if (integrator)
- integrator->setCamera(camera);
-// camera && integrator && integrator->ospRenderer) {
-// ospSetObject(integrator->ospRenderer,"camera",camera->ospCamera);
-// ospCommit(integrator->ospRenderer);
-// }
- resetAccumulation();
- }
-
- void Renderer::setIntegrator(const std::shared_ptr &integrator)
- {
- this->integrator = integrator;
- if (integrator) {
- integrator->commit();
- }
- resetAccumulation();
+ auto fb = (OSPFrameBuffer)child("frameBuffer").valueAs();
+ ospRenderFrame(fb,
+ ospRenderer,
+ OSP_FB_COLOR | OSP_FB_ACCUM);
}
- void Renderer::setWorld(const std::shared_ptr &world)
+ void Renderer::preRender(RenderContext& ctx)
{
- this->world = world;
- allNodes.clear();
- uniqueNodes.clear();
- if (world) {
- allNodes.serialize(world,sg::Serialization::DONT_FOLLOW_INSTANCES);
- uniqueNodes.serialize(world,sg::Serialization::DO_FOLLOW_INSTANCES);
- } else
- std::cout << "#osp:sg:renderer: no world defined, yet\n#ospQTV: (did you forget to pass a scene file name on the command line?)" << std::endl;
-
- resetAccumulation();
- std::cout << "#osp:sg:renderer: new world with " << world->nodes.size() << " nodes" << endl;
+ ctx.ospRenderer = ospRenderer;
}
- //! find the last camera in the scene graph
- std::shared_ptr Renderer::getLastDefinedCamera() const
+ void Renderer::preCommit(RenderContext &ctx)
{
- std::shared_ptr lastCamera;
- for (std::shared_ptr obj : uniqueNodes.object) {
- std::shared_ptr asCamera = std::dynamic_pointer_cast(obj->node);
- if (asCamera) lastCamera = asCamera;
+ if (child("frameBuffer")["size"].lastModified() >
+ child("camera")["aspect"].lastCommitted()) {
+
+ child("camera")["aspect"].setValue(
+ child("frameBuffer")["size"].valueAs().x /
+ float(child("frameBuffer")["size"].valueAs().y)
+ );
}
- return lastCamera;
+ auto rendererType = child("rendererType").valueAs();
+ if (!ospRenderer || rendererType != createdType) {
+ traverse(ctx, "modified");
+ ospRenderer = ospNewRenderer(rendererType.c_str());
+ assert(ospRenderer);
+ createdType = rendererType;
+ ospCommit(ospRenderer);
+ setValue((OSPObject)ospRenderer);
+ }
+ ctx.ospRenderer = ospRenderer;
}
-
- //! find the last integrator in the scene graph
- std::shared_ptr Renderer::getLastDefinedIntegrator() const
+
+ void Renderer::postCommit(RenderContext &ctx)
{
- std::shared_ptr lastIntegrator;
- for (std::shared_ptr obj : uniqueNodes.object) {
- std::shared_ptr asIntegrator = std::dynamic_pointer_cast(obj->node);
- if (asIntegrator) lastIntegrator = asIntegrator;
+ if (child("camera").childrenLastModified() > frameMTime
+ || child("lights").childrenLastModified() > frameMTime
+ || lastModified() > frameMTime
+ || child("shadowsEnabled").lastModified() > frameMTime
+ || child("aoSamples").lastModified() > frameMTime
+ || child("spp").lastModified() > frameMTime
+ || child("world").childrenLastModified() > frameMTime
+ )
+ {
+ ospFrameBufferClear(
+ (OSPFrameBuffer)child("frameBuffer").valueAs(),
+ OSP_FB_COLOR | OSP_FB_ACCUM
+ );
+
+ if (lightsData == nullptr ||
+ lightsBuildTime < child("lights").childrenLastModified())
+ {
+ // create and setup light for Ambient Occlusion
+ std::vector lights;
+ for(auto &lightNode : child("lights").children())
+ lights.push_back((OSPLight)lightNode->valueAs());
+
+ if (lightsData)
+ ospRelease(lightsData);
+ lightsData = ospNewData(lights.size(), OSP_LIGHT, &lights[0]);
+ ospCommit(lightsData);
+ lightsBuildTime = TimeStamp();
+ }
+
+ // complete setup of renderer
+ ospSetObject(ospRenderer,"camera", child("camera").valueAs());
+ ospSetObject(ospRenderer, "lights", lightsData);
+ if (child("world").childrenLastModified() > frameMTime)
+ {
+ child("world").traverse(ctx, "render");
+ ospSetObject(ospRenderer, "model", child("world").valueAs());
+ }
+ ospCommit(ospRenderer);
+ frameMTime = TimeStamp();
}
- return lastIntegrator;
+
}
-
- }
-}
+
+ OSP_REGISTER_SG_NODE(Renderer);
+
+ } // ::ospray::sg
+} // ::ospray
diff --git a/apps/common/sg/Renderer.h b/apps/common/sg/Renderer.h
index 31471f21be..90f4ab0d2a 100644
--- a/apps/common/sg/Renderer.h
+++ b/apps/common/sg/Renderer.h
@@ -20,59 +20,32 @@
namespace ospray {
namespace sg {
- class FrameBuffer;
- struct Renderer {
- Renderer();
-
- /*! re-start accumulation (for progressive rendering). make sure
- that this function gets called at lesat once every time that
- anything changes that might change the appearance of the
- converged image (e.g., camera position, scene, frame size,
- etc) */
- void resetAccumulation();
-
- void setWorld(const std::shared_ptr &world);
- void setCamera(const std::shared_ptr &camera);
- void setIntegrator(const std::shared_ptr &integrator);
- // -------------------------------------------------------
- // query functions
- // -------------------------------------------------------
-
- //! find the last camera in the scene graph
- std::shared_ptr getLastDefinedCamera() const;
- //! find the last integrator in the scene graph
- std::shared_ptr getLastDefinedIntegrator() const;
-
- //! create a default camera
- std::shared_ptr createDefaultCamera(vec3f up=vec3f(0,1,0));
+ class FrameBuffer;
- // //! set a default camera
- // void setDefaultCamera() { setCamera(createDefaultCamera()); }
+ struct Renderer : public Renderable
+ {
+ Renderer();
- /*! render a frame. return 0 if successful, any non-zero number if not */
- virtual int renderFrame();
+ // renderer renders the scene into the framebuffer on render call.
+ // It will call render on model when commit when model modified
+ virtual void traverse(RenderContext &ctx, const std::string& operation) override;
+ void preRender(RenderContext &ctx) override;
+ void postRender(RenderContext &ctx) override;
+ void preCommit(RenderContext &ctx) override;
+ void postCommit(RenderContext &ctx) override;
- // =======================================================
- // state variables
- // =======================================================
- std::shared_ptr world;
- std::shared_ptr camera;
- std::shared_ptr frameBuffer;
- std::shared_ptr integrator;
- // std::shared_ptr frame;
+ private:
- // state variables
- /*! all _unique_ nodes (i.e, even instanced nodes are listed
- only once */
- Serialization uniqueNodes;
- /*! _all_ nodes (i.e, instanced nodes are listed once for each
- time they are instanced */
- Serialization allNodes;
+ // Data members //
- //! accumulation ID
- size_t accumID;
+ OSPRenderer ospRenderer {nullptr};
+ OSPData lightsData {nullptr};
+ TimeStamp lightsBuildTime;
+ TimeStamp frameMTime;
+ std::string createdType = "none";
};
- }
-}
+
+ } // ::ospray::sg
+} // ::ospray
diff --git a/apps/common/sg/SceneGraph.cpp b/apps/common/sg/SceneGraph.cpp
index 04e24a89e4..1d852dcc14 100644
--- a/apps/common/sg/SceneGraph.cpp
+++ b/apps/common/sg/SceneGraph.cpp
@@ -25,28 +25,32 @@ namespace ospray {
namespace sg {
/*! 'render' the nodes */
- void Group::render(RenderContext &ctx)
+ std::string Group::toString() const
{
- for (auto child : children) {
- assert(child);
- child->render(ctx);
- }
+ return "ospray::sg::Group";
}
-
- box3f Group::getBounds()
+
+ std::string Info::toString() const
{
- box3f bounds = empty;
- for (auto child : children) {
- assert(child);
- bounds.extend(child->getBounds());
- }
- return bounds;
+ return "ospray::sg::Info";
}
- void Node::serialize(sg::Serialization::State &state)
- {
- state.serialization->object.push_back(std::make_shared(shared_from_this(),state.instantiation));
+ GenericGeometry::GenericGeometry(const std::string &type)
+ : Geometry(type)
+ {
+ }
+
+ std::string GenericGeometry::toString() const
+ {
+ return "ospray::sg::GenericGeometry";
}
+ box3f GenericGeometry::bounds() const
+ {
+ return _bounds;
+ }
+
+ OSP_REGISTER_SG_NODE(Group);
+
} // ::ospray::sg
} // ::ospray
diff --git a/apps/common/sg/SceneGraph.h b/apps/common/sg/SceneGraph.h
index 09a3350bf1..66a922a9f4 100644
--- a/apps/common/sg/SceneGraph.h
+++ b/apps/common/sg/SceneGraph.h
@@ -16,12 +16,18 @@
#pragma once
-// std
-#include ]