1OSPRay v2.0 Porting Guide 2========================= 3 4OSPRay v2.0.0 introduces a number of new features and updates, as well 5as some API changes. This guide is intended as an introduction to the 6new features and the concepts behind them, and as a guide to porting 7applications using OSPRay v1.8.x to v2.0.0. 8 9Parameters 10---------- 11 12### Setting parameters 13 14OSPRay traded having a limited number of parameter types (with a unique 15function signature for each type) by instead having a single generic 16function that takes any type found in the `OSPDataType` enum. The new 17function signature is as follows: 18 19 void ospSetParam(OSPObject, const char *name, OSPDataType type, const void *mem) 20 21This function takes the address of the value being set, where care 22should be taken when setting pointer-based types. For example, consider 23the following C-array: 24 25 float myValues[] = {0.f, 1.f, 2.f} 26 27If the application wants to set these values as an OSP_VEC3F, note that 28the `const void *mem` parameter to `ospSetParam` should point to what is 29the address of what would be a `vec3f`. Thus either of the following are 30valid: 31 32 void ospSetParam(object, "some_parameter", OSP_VEC3F, &myValues[0]); 33 34or 35 36 void ospSetParam(object, "some_parameter", OSP_VEC3F, myValues); 37 38The second variant relies on implicit casting from `float[]` to 39`float *`, which will point to the address of the first value. This then 40gets casted to a `vec3f` to be set on the target `object`. 41 42Some of the `ospSet*` functions were preserved as utility wrapper 43functions outlined later in this document (and can be found in 44`ospray_util.h`). 45 46### OSPDataType type checking 47 48Where it was previously accepted to create data of generic type 49`OSP_OBJECT` to represent a list of any object type, the `OSPDataType` 50must now match the object(s) it contains. 51 52Objects 53------- 54 55### New Object Hierarchy 56 57OSPRay objects, such as `OSPGeometry` and `OSPVolume`, have a new 58hierarchy that affords more control over geometry and volume 59transformation and instancing in the scene. 60 61Previously, the workflow was to create an object, fill it with the 62necessary parameters, and then place the object into an `OSPModel` via, 63for example, `ospAddGeometry`. An example is shown below using the C 64API. 65 66 OSPGeometry mesh = ospNewGeometry("triangles"); 67 // set parameters on mesh 68 ospCommit(mesh); 69 70 OSPModel world = ospNewModel(); 71 ospAddGeometry(world, mesh); 72 ospRelease(mesh); 73 ospCommit(world); 74 75In OSPRay v2.0.0, there is now an `OSPWorld`, which effectively replaces 76the old `OSPModel`. In addition, there are now 3 new objects that exist 77"in between" the geometry and the world: `OSPGeometricModel`, 78`OSPGroup`, and `OSPInstance`. There is also an `OSPVolumetricModel` 79equivalent for working with `OSPVolume` objects. 80 81The new workflow is shown below. Note that calls to `ospRelease()` have 82been removed for brevity. 83 84 // create a geometry 85 OSPGeometry mesh = ospNewGeometry("triangles"); 86 // set parameters on mesh 87 ospCommit(mesh); 88 89 // put the geometry in a model (a geometry can exist in more than one model) 90 OSPGeometricModel model = ospNewGeometricModel(mesh); 91 ospCommit(model); 92 93 // put the geometric model(s) in a group 94 OSPGroup group = ospNewGroup(); 95 OSPData geometricModels = ospNewSharedData1D(&model, OSP_GEOMETRIC_MODEL, 1); 96 ospSetObject(group, "geometry", geometricModels); 97 ospCommit(group); 98 99 // put the group in an instance (a group can be instanced more than once) 100 OSPInstance = ospNewInstance(group); 101 ospCommit(instance); 102 103 // put the instance in the world 104 OSPWorld world = ospNewWorld(); 105 OSPData instances = ospNewSharedData1D(&instance, OSP_INSTANCE, 1); 106 ospSetObject(world, "instance", instances); 107 ospCommit(world); 108 109While this looks more complex at first, the new hierarchy structure 110provides more fine control over appearance information and instance 111transformations. 112 113In OSPRay v1.x, geometries and volumes contained both structural and 114appearance information which limited their reuse in other objets. For 115example, the volume's transfer function can now be different between an 116isosurface, slice, and rendered volume all in the same scene without 117duplicating the actual volume itself. 118 119#### OSPGeometry and OSPVolume 120 121`OSPGeometry` and `OSPVolume` contain the physical data represented by 122the object. For geometries, this is the intersectable surface. For 123volumes, it is the scalar field to be sampled. 124 125#### OSPGeometricModel and OSPVolumetricModel 126 127`OSPGeometricModel` and `OSPVolumetricModel` contain appearance 128information about the geometry or volume that they hold. They have a 129one-to-N relationship with `OSPGeometry` and `OSPVolume` objects (i.e. a 130geometry or volume can exist in more than one model), but commonly exist 131as one-to-one. This could be used to create multiple copies of a 132geometry with different materials, for example. 133 134`OSPGeometricModel`s can hold primitive color information (e.g. the 135color used for each sphere in a `Spheres` geometry), a material or list 136of materials, and primitive material IDs (i.e. indexes into the list of 137materials if it is used). 138 139`OSPVolumetricModel`s can hold transfer functions. 140 141#### OSPGroup 142 143`OSPGroup` objects contain zero or more `OSPGeometricModel` and 144`OSPVolumetricModel` objects. They can hold geometries and volumes 145simultaneously. 146 147This is useful to collect together any objects that are logically 148grouped together in the scene. 149 150#### OSPInstance 151 152`OSPInstance` contains transformation information on an `OSPGroup` 153object. It has a one-to-one relationship with `OSPGroup`. 154 155This means that each `OSPInstance` contains exactly one `OSPGroup`. 156Similar to models and groups, a single `OSPGroup` may be placed into 157multiple `OSPInstace` objects. This allows for *instancing* of multiple 158objects throughout the scene, each with different transformations. 159 160`OSPInstance` objects holds an affine transformation matrix that is 161applied to all objects in its group. 162 163#### OSPWorld 164 165`OSPWorld` is the final container for all `OSPInstance` and `OSPLight` 166objects. It can contain one or more instances and lights. The world is 167passed along with a renderer, camera, and framebuffer to 168`ospRenderFrame` to generate an image. 169 170### void ospRetain(OSPObject) 171 172To allow the user greater control over the lifetime of objects, a new 173API `ospRetain` has been introduced. This call increments an object's 174reference count, and can delay automatic deletion. 175 176Updated Public Parameter Names 177------------------------------ 178 179OSPRay v2.0.0 has updated public parameter names (the strings used in 180`ospSetParam`) to a more consistent naming convention. OSPRay now will 181print a warning (visible if debug logs are enabled) if a parameter 182provided by the user is not used by an object. This can help catch cases 183where applications are using parameter names from OSPRay v1.8.5 or 184mistyped names. Some objects have required parameters. In these cases, 185OSPRay will invoke the error callback indicating which object and 186which parameter. 187 188OSPRay now universally uses the camelCase naming convention for all object 189types and parameter names. Furthermore, parameter names which are data 190arrays now use singular names to indicate what the elements are, and parameters 191which form a logical "struture-of-arrays" are communicated via the 192`"[structure_name].[member_name]"` naming convention. 193 194For example, the `"opacities"` array for `linear` transfer functions is now 195named `"opacity"`. 196 197Finally, some parameters have changed from being string-based to enum-based. 198All enums can be found in `OSPEnums.h`, where their usage can be found in 199the main API documentation. 200 201ospRenderFrame 202-------------- 203 204`ospRenderFrame` has changed in two ways. The signature has changed 205from: 206 207 float ospRenderFrame(OSPFrameBuffer, OSPRenderer, 208 const uint32_t frameBufferChannels = OSP_FB_COLOR); 209 210to 211 212 OSPFuture ospRenderFrame(OSPFrameBuffer, OSPRenderer, OSPCamera, OSPWorld); 213 214And, notably, it is no longer blocking. Two new calls `ospIsReady`, and 215`ospWait` are available to manage synchronization. 216 217Utility Library 218--------------- 219 220As a convenience, a lightweight utility library has been provided to 221help users port from the previous versions and reduce boilerplate code. 222This set of additional API calls are all implemented in terms of the 223core API found in `ospray.h`, where they can be found in 224`ospray_util.h`. Their definitions are compiled into `libospray` (the 225`ospray::ospray` CMake target) and are compatible with any valid device 226implementation. 227 228### OSPData and Parameter helpers 229 230The core OSPRay API has been simplified by removing many of the type 231specializations from the data and parameter set calls. The utility library 232provides wrappers to the familiar calls listed below: 233 234 ospSetString(OSPObject, const char *n, const char *s); 235 ospSetObject(OSPObject, const char *n, OSPObject obj); 236 237 ospSetBool(OSPObject, const char *n, int x); 238 ospSetFloat(OSPObject, const char *n, float x); 239 ospSetInt(OSPObject, const char *n, int x); 240 241 ospSetVec2f(OSPObject, const char *n, float x, float y); 242 ospSetVec3f(OSPObject, const char *n, float x, float y, float z); 243 ospSetVec4f(OSPObject, const char *n, float x, float y, float z, float w); 244 245 ospSetVec2i(OSPObject, const char *n, int x, int y); 246 ospSetVec3i(OSPObject, const char *n, int x, int y, int z); 247 ospSetVec4i(OSPObject, const char *n, int x, int y, int z, int w); 248 249 ospSetObjectAsData(OSPObject, const char *n, OSPDataType type, OSPObject obj); 250 251OSPRay v1.x calls to `ospSetData` have been replaced with `ospSetObject`. 252Convenience wrappers have also been provided to specialize `ospNewData`, and the 253new `ospNewSharedData` and `ospCopyData` APIs. 254 255 ospNewSharedData1D(const void *sharedData, OSPDataType type, uint32_t numItems); 256 ospNewSharedData1DStride(const void *sharedData, OSPDataType type, uint32_t numItems, int64_t byteStride); 257 ospNewSharedData2D(const void *sharedData, OSPDataType type, uint32_t numItems1, uint32_t numItems2); 258 ospNewSharedData2DStride(const void *sharedData, OSPDataType type, uint32_t numItems1, int64_t byteStride1, uint32_t numItems2, int64_t byteStride2); 259 ospNewSharedData3D(const void *sharedData, OSPDataType type, uint32_t numItems1, uint32_t numItems2, uint32_t numItems3); 260 261 ospNewData1D(OSPDataType type, uint32_t numItems); 262 ospNewData2D(OSPDataType type, uint32_t numItems1, uint32_t numItems2); 263 264 ospCopyData1D(const OSPData source, OSPData destination, uint32_t destinationIndex); 265 ospCopyData2D(const OSPData source, OSPData destination, uint32_t destinationIndex1, uint32_t destinationIndex2); 266 267### Object Usage Simplification 268 269To simplify setting data onto an object, if there is only a single data 270item, the wrapper `ospSetObjectAsData` permits the user to assign this 271item without first creating a data object containing that item. 272 273For example: 274 275 OSPData geometricModels = ospNewSharedData1D(&model, OSP_GEOMETRIC_MODEL, 1); 276 ospSetObject(group, "geometry", geometricModels); 277 ospRelease(geometricModels); 278 279simply becomes: 280 281 ospSetObjectAsData(group, "geometry", OSP_GEOMETRIC_MODEL, model); 282 283### Rendering helpers 284 285While `ospRenderFrame` is now asynchronous, some users will prefer the 286original blocking behavior that returns the frame variance. The utility 287library provides a wrapper to this functionality: 288 289 float ospRenderFrameBlocking(OSPFrameBuffer fb, 290 OSPRenderer renderer, 291 OSPCamera camera, 292 OSPWorld world) 293 294