Non-Cartesian Coordinate Systems

Initial support for volume rendering of data defined in 3D non-cartesian coordinate systems was added in yt_idv 0.5.0 for block-AMR data in spherical coordinates. While not all rendering methods and annotations are supported for spherical coordinates, yt_idv can directly calculate maximum intensity projections, integrative projections and projection with custom transfer functions without any pre-interpolation or re-gridding.

_images/sph-vr-example.png

The approach for handling data defined in non-cartesian coordinates is to pre-calculate cartesian bounding boxes of the data blocks. The rendering pipeline then uses the cartesian bounding boxes to calculate ray entry/exit points during ray tracing. Between the entry/exit points, the cartesian coordinates of the ray position are converted to the native coordinates of the data, which is used to sample the texture maps (which are stored in native coordinates). The initial implementaiton of the algorithm uses the ray entry/exit points of the cartesian bounding boxes, and so not all points along the ray are gauranteed to lie within the bounds of the data – though these data points will be discarded during ray tracing, it does mean that a larger number of samples along the ray may be required to ensure the underlying non-cartesian element is properly sampled compared to the standard cartesian data ray tracing (this is controlled by the sample_factor attribute of the BlockRendering component).

At present, supported non-cartesian coordinate systems include Spherical Coordinates with (r, theta, phi), where r is radius, theta is co-latitude (between 0, pi) and phi is azimuth (between 0, 2pi), following yt conventions.

Notes on further development

Further contributions are welcome for adding support for the remaining 3d non-cartesian coordinate systems that yt supports that are not yet supported here (3d cylindrical, 3d geographic) as well as for adding support for non-cartesian coordinate systems in additional yt_idv components.

To add support for additional non-cartesian coordinate systems requires two steps:

  1. Add methods for calcualting cartesian bounding boxes

  2. Add support to the rendering pipeline

Add methods for calcualting cartesian bounding boxes

The cartesian bounding box methods are defined in yt_idv/coordinate_utilities.pyx. When adding support for a new coordiante system, implement a new MixedCoordBBox child class, following the SphericalMixedCoordBBox example. The main method is get_cartesian_bbox, which returns the cartesian bounding box for a single non-cartesian element. Once implemented, yt_idv.cartesian_bboxes can be used to calculate bounding boxes for arrays of elements.

Next, yt_idv.scene_data.block_collection.BlockCollection should be updated (mostly in add_data and _set_geometry_attributes) to handle the new coordinate system following the example for spherical coordinates.

These two steps will handle the CPU-side of the calculations, next you need to update the rendering pipeline.

Add support to the rendering pipeline

A number of changes are required related to the rendering pipeline for the block_rendering shader program. In order to avoid shader code duplication for different coordinate systems and also avoid overly branching code within the shader itself, pre-processor directives are used to provide switches between shader behavior for different coordinate systems.

The NONCARTESIAN_GEOM directive is for functionality that should cover shared behavior between all non-cartesian coordinate systems. For example, grid_position.vert.glsl, grid_expand.geom.glsl and ray_tracing.frag.glsl all use NONCARTESIAN_GEOM for passing along the additional vertex attributes related to the cartesian bounding boxes.

Functionality specific to a coordinate system should be defined with a new pre-processor directive flag. For spherical coordinates, this is SPHERICAL_GEOM, and is used in ray_tracing.frag.glsl for defining and using the functions for transforming from cartesian to spherical coordinates. To add a new one for use in the shaders, add a new entry to the yt_idv.scene_components.base_component._geom_directives dictionary and then wrap any functionality specific to your new coordinate system within pre-processor checks, for example:

#ifdef SPHERICAL_GEOM
vec3 cart_to_sphere_vec3(vec3 v) {
    // transform a single point in cartesian coords to spherical
    vec3 vout = vec3(0.,0.,0.);

    // ---- code trimmed for clarity ---- //

    return vout;

}
#endif

When the shader program compiles, the above function will only be defined for rendering data in spherical coordinates.

At a minimum, you will need to add a function to handle the coordinate conversion from the cartesian position of the ray to the native coordinates of your data.