Orientation Gizmo¶
This example adds a small orientation widget to a 3D panel.
Preview¶
Run And Adapt¶
Commands below assume a Datoviz source checkout and start at the repository root. Use your configured build environment; Python routes additionally require local bindings.
| Route | Availability | Command or action |
|---|---|---|
| C | Canonical native source | just example-c features/orientation_gizmo (build and run), or rerun ./build/examples/c/features/orientation_gizmo |
| Python | Available; direct-engine adaptation | python3 -m examples.python.gallery.features.orientation_gizmo |
| Browser | Live WebGPU route | Open live example |
This example is approved as a starting point for user code and coding agents. Keep the object lifetimes and data shapes intact while adapting the data and styling.
What To Look For¶
The main scene is a lit cube controlled by an arcball, and the orientation gizmo is placed in the panel's bottom-right corner with a fixed screen size. Rotate the live cube and compare the cube faces with the gizmo axes; the widget helps users keep track of 3D orientation when inspecting volumes, meshes, or spatial point clouds.
Source¶
#!/usr/bin/env python3
"""3D cube with an arcball controller and a passive orientation gizmo."""
from __future__ import annotations
import ctypes
import datoviz as dvz
from examples.python.gallery import common as ex
def _add_reference_grid(panel) -> None:
desc = dvz.dvz_reference_grid_desc()
desc.plane = dvz.DVZ_REFERENCE_GRID_XZ
desc.origin[1] = -0.59
desc.size[:] = (7.0, 7.0)
desc.spacing = 0.25
desc.major_every = 4
desc.minor_color = dvz.DvzColor(74, 86, 98, 95)
desc.major_color = dvz.DvzColor(116, 132, 148, 145)
desc.axis_color = dvz.DvzColor(176, 190, 204, 185)
desc.depth_test = True
grid = dvz.dvz_reference_grid(panel, ctypes.byref(desc))
if not grid:
raise RuntimeError("dvz_reference_grid() failed")
def _add_orientation_gizmo(panel) -> None:
desc = dvz.dvz_orientation_gizmo_desc()
desc.placement = dvz.dvz_placement_panel_corner(
dvz.DVZ_HORIZONTAL_ANCHOR_RIGHT,
dvz.DVZ_VERTICAL_ANCHOR_BOTTOM,
150.0,
150.0,
-18.0,
-18.0,
)
gizmo = dvz.dvz_orientation_gizmo(panel, ctypes.byref(desc))
if not gizmo:
raise RuntimeError("dvz_orientation_gizmo() failed")
def _add_scene(scene, panel) -> None:
ex.manual_camera(panel)
_add_reference_grid(panel)
ex.add_cube_mesh(scene, panel, size=1.18)
_add_orientation_gizmo(panel)
def main() -> None:
scene, figure, panel = ex.scene_panel()
_add_scene(scene, panel)
def configure(view) -> None:
arcball = dvz.dvz_view_arcball(view, panel, None)
if not arcball:
raise RuntimeError("dvz_view_arcball() failed")
angles = (ctypes.c_float * 3)(0.0, 0.0, 0.0)
if dvz.dvz_arcball_set(arcball, angles) != 0:
raise RuntimeError("dvz_arcball_set() failed")
ex.run_with_view(scene, figure, "Orientation Gizmo", configure)
if __name__ == "__main__":
main()
/*
* Copyright (c) 2021 Cyrille Rossant and contributors. All rights reserved.
* Licensed under the MIT license. See LICENSE file in the project root for details.
* SPDX-License-Identifier: MIT
*/
/* This example adds a small orientation widget to a 3D panel.
*
* What to look for: the main scene is a lit cube controlled by an arcball, and the orientation
* gizmo is placed in the panel's bottom-right corner with a fixed screen size. Rotate the live
* cube and compare the cube faces with the gizmo axes; the widget helps users keep track of 3D
* orientation when inspecting volumes, meshes, or spatial point clouds.
*
* Scenario: features_orientation_gizmo
* Style: features, graphite_cyan, 1280x720 window target
*
* Build: just example-c features/orientation_gizmo
* Run: ./build/examples/c/features/orientation_gizmo --live
* Smoke: ./build/examples/c/features/orientation_gizmo --png
*/
/*************************************************************************************************/
/* Includes */
/*************************************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "_alloc.h"
#include "datoviz/geom.h"
#include "datoviz/scene.h"
#include "example_common.h"
#include "example_controller_preview.h"
#include "example_style.h"
#include "runner/scenario_runner.h"
/*************************************************************************************************/
/* Constants */
/*************************************************************************************************/
#define WIDTH EXAMPLE_WINDOW_WIDTH
#define HEIGHT EXAMPLE_WINDOW_HEIGHT
DvzScenarioSpec dvz_example_orientation_gizmo_scenario(void);
/*************************************************************************************************/
/* Structs */
/*************************************************************************************************/
typedef struct OrientationGizmoState
{
DvzGeometry* geometry;
DvzArcball* arcball;
} OrientationGizmoState;
/*************************************************************************************************/
/* Scenario callbacks */
/*************************************************************************************************/
/**
* Initialize the orientation-gizmo feature scenario.
*
* @param ctx scenario context
* @param out_user scenario state output
* @return true on success
*/
static bool _scenario_init(DvzScenarioContext* ctx, void** out_user)
{
if (ctx == NULL)
return false;
if (out_user != NULL)
*out_user = NULL;
OrientationGizmoState* state = (OrientationGizmoState*)dvz_calloc(1, sizeof(*state));
if (state == NULL)
return false;
if (out_user != NULL)
*out_user = state;
ctx->figure = dvz_figure(ctx->scene, ctx->width, ctx->height, 0);
if (ctx->figure == NULL)
return false;
DvzPanel* panel = dvz_panel_full(ctx->figure);
if (panel == NULL)
return false;
example_graphite_cyan_set_panel_background(panel);
if (example_set_default_3d_camera(panel, 1.0f) == NULL)
return false;
if (!example_add_graphite_cyan_xz_reference_grid(panel, -0.59f, true))
return false;
if (!example_add_graphite_cyan_cube_mesh(ctx->scene, panel, 1.18, NULL, &state->geometry))
return false;
DvzController* controller = dvz_arcball(ctx->scene, NULL);
if (controller == NULL)
return false;
DvzArcball* arcball = dvz_controller_arcball(controller);
if (arcball == NULL)
return false;
state->arcball = arcball;
if (dvz_scenario_bind_controller(ctx, panel, controller, DVZ_DIM_MASK_XYZ) != 0)
return false;
DvzOrientationGizmoDesc gizmo = dvz_orientation_gizmo_desc();
gizmo.placement = dvz_placement_panel_corner(
DVZ_HORIZONTAL_ANCHOR_RIGHT, DVZ_VERTICAL_ANCHOR_BOTTOM, 150, 150, -18, -18);
return dvz_orientation_gizmo(panel, &gizmo) != NULL;
}
/**
* Apply deterministic preview motion for generated gallery media.
*
* @param ctx scenario context
* @param user scenario state
*/
static void _scenario_frame(DvzScenarioContext* ctx, void* user)
{
if (ctx == NULL || !ctx->preview_mode || user == NULL)
return;
OrientationGizmoState* state = (OrientationGizmoState*)user;
ExamplePreviewArcballDesc desc = example_preview_arcball_cube_desc();
example_preview_arcball(
state->arcball, ctx->preview_frame_index, ctx->preview_frame_count, &desc);
}
/**
* Destroy the orientation-gizmo feature scenario state.
*
* @param ctx scenario context
* @param user scenario state
*/
static void _scenario_destroy(DvzScenarioContext* ctx, void* user)
{
(void)ctx;
OrientationGizmoState* state = (OrientationGizmoState*)user;
if (state == NULL)
return;
if (state->geometry != NULL)
dvz_geometry_destroy(state->geometry);
dvz_free(state);
}
/**
* Return the orientation-gizmo scenario specification.
*
* @return scenario specification
*/
DvzScenarioSpec dvz_example_orientation_gizmo_scenario(void)
{
return (DvzScenarioSpec){
.id = "features_orientation_gizmo",
.title = "Orientation Gizmo",
.width = WIDTH,
.height = HEIGHT,
.fps = 60.0,
.requirements = DVZ_SCENARIO_REQ_MESH_VISUAL | DVZ_SCENARIO_REQ_CONTROLLER |
DVZ_SCENARIO_REQ_ARCBALL,
.init = _scenario_init,
.frame = _scenario_frame,
.destroy = _scenario_destroy,
};
}
/*************************************************************************************************/
/* Functions */
/*************************************************************************************************/
/**
* Run the orientation-gizmo feature example through the native scenario runner.
*
* @param argc command-line argument count
* @param argv command-line argument vector
* @return process exit code
*/
#ifndef DVZ_EXAMPLE_NO_MAIN
int main(int argc, char** argv)
{
DvzScenarioSpec spec = dvz_example_orientation_gizmo_scenario();
return dvz_scenario_run_native_cli(&spec, argc, argv) == 0 ? 0 : 1;
}
#endif
Example details
- ID:
features_orientation_gizmo - Category:
feature - Lane:
features - Status:
supported - Source:
examples/c/features/orientation_gizmo.c - Approved adaptation starter:
yes - Python source:
examples/python/gallery/features/orientation_gizmo.py - Python adaptation: Available; direct-engine adaptation
- Browser support: Live in browser
- WebGPU live route:
examples/webgpu/live.html?id=features_orientation_gizmo - Browser capability tags:
orientation-gizmo,overlay,mesh,controller - Validation:
smoke+interaction+screenshot
Data
| Field | Value |
|---|---|
kind |
synthetic |