Skip to content
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
d79a536
Set up surprise checking for new camera input option
emily-howell Jul 16, 2025
e9ed8e0
Merge branch 'develop' of github.com:Alpine-DAV/ascent into task/7_15…
emily-howell Jul 16, 2025
8ddb69f
Adding a test for the ascent camera format
emily-howell Jul 16, 2025
c6cda28
Fetting test passing and adding some rough tests for the visit case a…
emily-howell Jul 16, 2025
8dc4da2
Successfully got something that looks the same in ascent for both cam…
emily-howell Jul 17, 2025
17a6124
Checkpoint with functional positioning and zoom. However, clipping is…
emily-howell Jul 31, 2025
05d5c30
Merge branch 'develop' of github.com:Alpine-DAV/ascent into task/7_15…
emily-howell Jul 31, 2025
dcd5e76
Cleaning up the tests so that they pass. Still have clipping plane issue
emily-howell Aug 1, 2025
00272a3
Adding 2d as valid path for ascent camera definition
emily-howell Aug 1, 2025
3c47319
Adding some infos for the users to help with confusion?
emily-howell Aug 7, 2025
d631424
Cleaning up the tests a smidge
emily-howell Aug 7, 2025
e80b65b
switching all visit parameter variable names to snake case
emily-howell Aug 12, 2025
9c8fe60
Merge branch 'develop' of github.com:Alpine-DAV/ascent into task/7_15…
emily-howell Aug 12, 2025
6caff07
Adding documentation about rendering camera parameters
emily-howell Aug 13, 2025
ec94407
Making the unsupported visit camera parameters clearer
emily-howell Aug 13, 2025
82e0149
Merge branch 'develop' of github.com:Alpine-DAV/ascent into task/7_15…
emily-howell Aug 13, 2025
077d4c9
Merge branch 'develop' of github.com:Alpine-DAV/ascent into task/7_15…
emily-howell Aug 19, 2025
3a9ae24
Trying clearning up the tests to see if that helps?
emily-howell Aug 19, 2025
1dc5d7b
Seeing if modifying the rendering helps?
emily-howell Aug 19, 2025
91afd7c
Using a better pi
emily-howell Aug 19, 2025
e93c4f1
Putting my tests back
emily-howell Aug 19, 2025
dd893c4
Updating clipping planes in tests
emily-howell Aug 21, 2025
4483305
Merge branch 'develop' of github.com:Alpine-DAV/ascent into task/7_15…
emily-howell Oct 21, 2025
87b12bd
Addressing MR feedback :) (thank you Justin)
emily-howell Oct 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,24 @@ Notable changes to Ascent are documented in this file. This changelog started on
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project aspires to adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.9.5]
### Preferred dependency versions for ascent@develop
- [email protected] or newer
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]

### Added
- Added ability to define cameras for rendering using visit camera view parameters

### Changed

### Fixed

## [0.9.4] - Released 2025-07-18
### Preferred dependency versions for ascent@develop
- [email protected] or newer
Expand Down
57 changes: 57 additions & 0 deletions src/docs/sphinx/Actions/Scenes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,63 @@ Now we add a second render to the same example using every available parameter:
near_plane: 0.1
far_plane: 100.1

Rendering Camera Configuration
------------------------------
Ascent supports two primary methods for defining the rendering camera:
the Ascent native (VTKm style) camera, which is camera-centric, and the VisIt style camera, which is view-centric.
Both formats provide control over how scenes are rendered, but they differ in terminology, orientation, and internal computation of the view matrix.

Ascent Native (VTKm Style) Camera
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The native Ascent camera follows the VTKm camera model which focuses on defining the camera's physical parameters and orientation in 3D space.
This camera-centric approach specifies where the camera is located, what it is looking at, and how it is oriented.
The following parameters are supported:

- ``2d`` : Enables 2D rendering mode.
- ``look_at`` : A 3-element array [x, y, z] indicating the point the camera is directed toward.
- ``position`` : A 3-element array [x, y, z] indicating the camera's position in space.
- ``up`` : A 3-element vector that defines the up direction of the camera.
- ``fov`` : Field of view in degrees for perspective projection.
- ``xpan`` : Pan offset in the horizontal direction.
- ``ypan`` : Pan offset in the vertical direction.
- ``zoom`` : Uniform zoom factor applied to the view.
- ``near_plane`` : Distance from the camera to the near clipping plane.
- ``far_plane`` : Distance from the camera to the far clipping plane.
- ``azimuth`` : Rotates the camera around the up axis.
- ``elevation`` : Rotates the camera around the right axis.

VisIt Style Camera
^^^^^^^^^^^^^^^^^^
Alternatively, the camera can be defined using the VisIt camera parameters which follows a view centric approach.
Instead of positioning the camera explicitly, it defines the view using vectors like ``view_normal`` and ``view_up``, which describe the direction and orientation of the camera relative to a focal point.
The following parameters are supported:

- ``view_normal`` : A vector [x, y, z] indicating the direction from the camera toward the scene.
- ``focus`` : A 3D point [x, y, z] indicating the point of focus in the scene.
- ``view_up`` : A vector indicating which direction is up in the rendered view.
- ``view_angle`` : Field of view angle in degrees.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- ``view_angle`` : Field of view angle in degrees.
- ``view_angle`` : Field of view angle in degrees for perspective projection.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the VisIt view_angle parameter is half the VTKm fov parameter, so maybe the description here could be different.

- ``parallel_scale`` : Scale used for parallel (orthographic) projections.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could add that parallel_scale is half of the image height in world space.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is used beyond orthographic projections, its a general param.
The name is strange, but Justin's description describes what it is.

- ``near_plane`` : Distance from the ``focus`` point along the ``view_normal`` to the near clipping plane.
- ``far_plane`` : Distance from the ``focus`` point along the ``view_normal`` to the far clipping plane.
- ``image_pan`` : A 2-element array [x, y] specifying image-space panning.
- ``image_zoom`` : Zoom factor for the image.


Unsupported VisIt Camera Parameters
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In addition to the above supported VisIt camera parameters, there are a number of VisIt camera parameters that are not completely translatable to the VTKm style camera and are therefore currently ignored
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In addition to the above supported VisIt camera parameters, there are a number of VisIt camera parameters that are not completely translatable to the VTKm style camera and are therefore currently ignored
In addition to the above supported VisIt camera parameters, there are a number of VisIt camera parameters that are not completely translatable to the VTKm style camera and are therefore currently ignored.


.. Note::
These parameters are safely ignored if provided. They will not influence the rendered image but also will not produce errors.

- ``perspective`` : Boolean flag (true/false) indicating whether to use perspective (true) or parallel (false) projection. In Ascent, only perspective projection is currently used so this flag is ignored.
- ``eye_angle`` : Used in stereo rendering to control the eye separation angle. Ascent does not currently support stereo rendering, so this has no effect.
- ``center_of_rotation_set`` : Boolean flag indicating whether center_of_rotation has been explicitly set. Not used in Ascent.
- ``center_of_rotation`` : A 3D point used as the pivot for interactive rotation in VisIt. Ascent does not support interactive camera manipulation, so this is ignored.
- ``axis_3d_scale_flag`` : Boolean flag that enables non-uniform axis scaling (e.g., X:Y:Z aspect ratios). Not supported in Ascent.
- ``axis_3d_scale`` : A 3D vector specifying per-axis scaling for non-uniform visualizations. No effect in Ascent.
- ``shear`` : A 3-element array used to apply a shear transformation to the view. Not currently implemented.
- ``window_valid`` : Internal VisIt flag to indicate whether the current window setup is valid. Irrelevant in Ascent and ignored.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docs look great!

Additional Render Options
-------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@ parse_camera(const conduit::Node camera_node, vtkm::rendering::Camera &camera)
// Get the optional camera parameters
//

// check for 2d mode first
// -------------------- //
// 2D camera parameters //
// -------------------- //
if(camera_node.has_child("2d"))
{
// camera:
Expand All @@ -114,6 +116,9 @@ parse_camera(const conduit::Node camera_node, vtkm::rendering::Camera &camera)
view_vals[3]);
}

// ------------------------ //
// Ascent camera parameters //
// ------------------------ //
if(camera_node.has_child("look_at"))
{
conduit::Node n;
Expand Down Expand Up @@ -191,6 +196,124 @@ parse_camera(const conduit::Node camera_node, vtkm::rendering::Camera &camera)
vtkm::Float64 elevation = camera_node["elevation"].to_float64();
camera.Elevation(elevation);
}

// ----------------------- //
// Visit camera parameters //
// ----------------------- //
if(camera_node.has_child("focus"))
{
conduit::Node n;
camera_node["focus"].to_float64_array(n);
const float64 *coords = n.as_float64_ptr();
vtkmVec3f look_at(coords[0], coords[1], coords[2]);
camera.SetLookAt(look_at);
}

if(camera_node.has_child("view_normal") &&
camera_node.has_child("focus") &&
camera_node.has_child("view_angle") &&
camera_node.has_child("parallel_scale"))
{
conduit::Node view, focus;
camera_node["view_normal"].to_float64_array(view);
camera_node["focus"].to_float64_array(focus);

const conduit::float64 *v = view.value();
const conduit::float64 *fc = focus.value();

conduit::float64 view_angle = camera_node["view_angle"].to_float64() * (vtkm::Pi() / 360.0);
conduit::float64 parallel_scale = camera_node["parallel_scale"].to_float64();

// Compute camera distance using perspective projection formula
double distance = (parallel_scale) / std::tan(view_angle);

// Normalize viewNormal vector
conduit::float64 norm = std::sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
conduit::float64 v_norm[3] = { v[0]/norm, v[1]/norm, v[2]/norm };

conduit::float64 pos[3];
for(int i = 0; i < 3; ++i)
{
pos[i] = fc[i] + v_norm[i] * distance;
}

vtkmVec3f position(pos[0], pos[1], pos[2]);
camera.SetPosition(position);

// Clipping planes require positional information to be computed
if(camera_node.has_child("near_plane"))
{
vtkm::Range clipping_range = camera.GetClippingRange();
clipping_range.Min =std::max(0.001, distance + camera_node["near_plane"].to_float64());
camera.SetClippingRange(clipping_range);
}

if(camera_node.has_child("far_plane"))
{
vtkm::Range clipping_range = camera.GetClippingRange();
clipping_range.Max = distance + camera_node["far_plane"].to_float64();
camera.SetClippingRange(clipping_range);
}
}

if(camera_node.has_child("view_up"))
{
conduit::Node n;
camera_node["view_up"].to_float64_array(n);
const float64 *coords = n.as_float64_ptr();
vtkmVec3f up(coords[0], coords[1], coords[2]);
vtkm::Normalize(up);
camera.SetViewUp(up);
}

if(camera_node.has_child("image_pan"))
{
vtkm::Float64 xpan = 0.;
vtkm::Float64 ypan = 0.;

conduit::Node n;
camera_node["image_pan"].to_float64_array(n);
const float64 *pan_xy = n.as_float64_ptr();
camera.Pan(pan_xy[0], pan_xy[1]);
}

if(camera_node.has_child("image_zoom"))
{
double zoom = camera_node["image_zoom"].to_float64();
camera.Zoom(zoom_to_vtkm_zoom(zoom));
}

if(camera_node.has_child("perspective"))
{
ASCENT_INFO("Visit camera parameter \"perspective\" is recognized but currently has no effect");
}

if(camera_node.has_child("eye_angle"))
{
ASCENT_INFO("Visit camera parameter \"eye_angle\" is recognized but currently has no effect");
}

if(camera_node.has_child("center_of_rotation_set") ||
camera_node.has_child("center_of_rotation"))
{
ASCENT_INFO("Visit camera parameter \"center_of_rotation\" and \"center_of_rotation_set\" are recognized but currently have no effect");
}

if(camera_node.has_child("axis_3d_scale_flag") ||
camera_node.has_child("axis_3d_scale"))
{
ASCENT_INFO("Visit camera parameter \"axis_3d_scale\" and \"axis_3d_scale_flag\" are recognized but currently have no effect");
}

if(camera_node.has_child("shear"))
{
ASCENT_INFO("Visit camera parameter \"shear\" is recognized but currently has no effect");
}

if(camera_node.has_child("window_valid"))
{
ASCENT_INFO("Visit camera parameter \"window_valid\" is recognized but currently has no effect");
}
}

bool is_valid_name(const std::string &name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,17 +153,6 @@ check_renders_surprises(const conduit::Node &renders_node)
r_valid_paths.push_back("image_width");
r_valid_paths.push_back("image_height");
r_valid_paths.push_back("scene_bounds");
r_valid_paths.push_back("camera/look_at");
r_valid_paths.push_back("camera/position");
r_valid_paths.push_back("camera/up");
r_valid_paths.push_back("camera/fov");
r_valid_paths.push_back("camera/xpan");
r_valid_paths.push_back("camera/ypan");
r_valid_paths.push_back("camera/zoom");
r_valid_paths.push_back("camera/near_plane");
r_valid_paths.push_back("camera/far_plane");
r_valid_paths.push_back("camera/azimuth");
r_valid_paths.push_back("camera/elevation");
r_valid_paths.push_back("type");
r_valid_paths.push_back("phi");
r_valid_paths.push_back("phi_range");
Expand Down Expand Up @@ -200,6 +189,44 @@ check_renders_surprises(const conduit::Node &renders_node)

std::vector<std::string> r_ignore_paths;
r_ignore_paths.push_back("phi_theta_positions");
r_ignore_paths.push_back("camera");

// Valid Ascent input camera format
std::vector<std::string> c_ascent_valid_paths;
c_ascent_valid_paths.push_back("2d");
c_ascent_valid_paths.push_back("look_at");
c_ascent_valid_paths.push_back("position");
c_ascent_valid_paths.push_back("up");
c_ascent_valid_paths.push_back("fov");
c_ascent_valid_paths.push_back("xpan");
c_ascent_valid_paths.push_back("ypan");
c_ascent_valid_paths.push_back("zoom");
c_ascent_valid_paths.push_back("near_plane");
c_ascent_valid_paths.push_back("far_plane");
c_ascent_valid_paths.push_back("azimuth");
c_ascent_valid_paths.push_back("elevation");

// Valid Visit input camera format
std::vector<std::string> c_visit_valid_paths;
c_visit_valid_paths.push_back("view_normal");
c_visit_valid_paths.push_back("focus");
c_visit_valid_paths.push_back("view_up");
c_visit_valid_paths.push_back("view_angle");
c_visit_valid_paths.push_back("parallel_scale");
c_visit_valid_paths.push_back("near_plane");
c_visit_valid_paths.push_back("far_plane");
c_visit_valid_paths.push_back("image_pan");
c_visit_valid_paths.push_back("image_zoom");
c_visit_valid_paths.push_back("perspective");
c_visit_valid_paths.push_back("eye_angle");
c_visit_valid_paths.push_back("center_of_rotation_set");
c_visit_valid_paths.push_back("center_of_rotation");
c_visit_valid_paths.push_back("axis_3d_scale_flag");
c_visit_valid_paths.push_back("axis_3d_scale");
c_visit_valid_paths.push_back("shear");
c_visit_valid_paths.push_back("window_valid");

std::vector<std::string> c_ignore_paths;

for(int i = 0; i < num_renders; ++i)
{
Expand All @@ -223,6 +250,22 @@ check_renders_surprises(const conduit::Node &renders_node)
}
}
}

if(render_node.has_path("camera"))
{
const conduit::Node &camera_node = render_node["camera"];
std::string c_ascent_surprises = surprise_check(c_ascent_valid_paths, c_ignore_paths, camera_node);
std::string c_visit_surprises = surprise_check(c_visit_valid_paths, c_ignore_paths, camera_node);

if(!c_ascent_surprises.empty() && !c_visit_surprises.empty())
{
surprises += "Cameras must follow either an ascent format or a visit format, not both.\n";
surprises += "\nAscent camera surpises:\n";
surprises += c_ascent_surprises;
surprises += "\nVisit camera surprises:\n";
surprises += c_visit_surprises;
}
}
}
return surprises;
}
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading