Skip to content

Mesh

This example renders a lit indexed cube mesh in a 3D scene.

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 visuals/mesh (build and run), or rerun ./build/examples/c/visuals/mesh
Python Available; manually maintained direct-engine example python3 -m examples.python.gallery.visuals.mesh
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 cube geometry supplies vertices, indices, normals, and per-face colors to the mesh visual through dvz_mesh_set_geometry(). Rotate the live view or compare the screenshot faces to see how indexed geometry, lighting normals, and an arcball camera make a compact 3D object readable.

Source

#!/usr/bin/env python3
"""Indexed colored cube mesh."""

from __future__ import annotations

import numpy as np

import datoviz as dvz

from examples.python.gallery import common as ex


def main() -> None:
    scene, figure, panel = ex.scene_panel()

    positions = np.array(
        [
            [-0.55, -0.55, -0.55],
            [0.55, -0.55, -0.55],
            [0.55, 0.55, -0.55],
            [-0.55, 0.55, -0.55],
            [-0.55, -0.55, 0.55],
            [0.55, -0.55, 0.55],
            [0.55, 0.55, 0.55],
            [-0.55, 0.55, 0.55],
        ],
        dtype=np.float32,
    )
    colors = ex.color_array(
        ex.CYAN, ex.GREEN, ex.YELLOW, ex.RED, ex.BLUE, ex.CYAN, ex.GREEN, ex.WHITE
    )
    indices = np.array(
        [
            0, 1, 2, 2, 3, 0,
            4, 6, 5, 6, 4, 7,
            0, 4, 5, 5, 1, 0,
            1, 5, 6, 6, 2, 1,
            2, 6, 7, 7, 3, 2,
            3, 7, 4, 4, 0, 3,
        ],
        dtype=np.uint32,
    )

    mesh = dvz.dvz_mesh(scene, 0)
    if not mesh:
        raise RuntimeError("dvz_mesh() failed")
    dvz.dvz_visual_set_data_many(mesh, {"position": positions, "color": colors})
    dvz.dvz_visual_set_index_data(mesh, indices)
    ex.add_visual(panel, mesh)

    ex.run(scene, figure, "Mesh")


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
 */

/* mesh - This example renders a lit indexed cube mesh in a 3D scene.
 *
 * What to look for: the cube geometry supplies vertices, indices, normals, and per-face colors to
 * the mesh visual through dvz_mesh_set_geometry(). Rotate the live view or compare the screenshot
 * faces to see how indexed geometry, lighting normals, and an arcball camera make a compact 3D
 * object readable.
 *
 * Scenario: visuals_mesh
 * Style: visuals, graphite_cyan, 1280x720 window target
 *
 * Build:  just example-c visuals/mesh
 * Run:    ./build/examples/c/visuals/mesh --live
 * Smoke:  ./build/examples/c/visuals/mesh --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_style.h"
#include "runner/scenario_runner.h"



/*************************************************************************************************/
/*  Constants                                                                                    */
/*************************************************************************************************/

#define WIDTH  EXAMPLE_WINDOW_WIDTH
#define HEIGHT EXAMPLE_WINDOW_HEIGHT



/*************************************************************************************************/
/*  Forward declarations                                                                         */
/*************************************************************************************************/

DvzScenarioSpec dvz_visual_mesh_scenario(void);



/*************************************************************************************************/
/*  Helpers                                                                                      */
/*************************************************************************************************/

/**
 * Add one retained lit cube mesh visual to the panel.
 *
 * @param scene scene owning the visual
 * @param panel panel receiving the visual
 * @param out_geometry geometry handle for cleanup on failure before upload completes
 * @return true when the visual was added
 */
static bool _add_mesh(DvzScene* scene, DvzPanel* panel, DvzGeometry** out_geometry)
{
    const ExampleStyleColorRole face_roles[DVZ_GEOM_CUBE_FACE_COUNT] = {
        EXAMPLE_STYLE_COLOR_ACCENT_PRIMARY,
        EXAMPLE_STYLE_COLOR_ACCENT_SECONDARY,
        EXAMPLE_STYLE_COLOR_WARNING,
        EXAMPLE_STYLE_COLOR_ERROR,
        EXAMPLE_STYLE_COLOR_TEXT,
        EXAMPLE_STYLE_COLOR_ACCENT_PRIMARY,
    };
    DvzColor face_colors[DVZ_GEOM_CUBE_FACE_COUNT] = {0};
    for (uint32_t i = 0; i < DVZ_GEOM_CUBE_FACE_COUNT; i++)
        face_colors[i] = example_graphite_cyan_color(face_roles[i]);

    DvzGeometry* cube = dvz_geometry_cube(&(DvzGeometryCubeDesc){
        DVZ_STRUCT_INIT_FIELDS(DvzGeometryCubeDesc),
        .size = 1.18,
        .face_colors = face_colors,
        .face_color_count = DVZ_GEOM_CUBE_FACE_COUNT,
    });
    if (cube == NULL)
        return false;
    if (out_geometry != NULL)
        *out_geometry = cube;

    DvzVisual* visual = dvz_mesh(scene, 0);
    if (visual == NULL)
        return false;
    if (dvz_mesh_set_geometry(visual, cube) != 0)
        return false;
    dvz_geometry_destroy(cube);
    if (out_geometry != NULL)
        *out_geometry = NULL;

    return dvz_panel_add_visual(panel, visual, NULL) == 0;
}



typedef struct MeshState
{
    DvzGeometry* geometry;
} MeshState;



/*************************************************************************************************/
/*  Scenario callbacks                                                                           */
/*************************************************************************************************/

/**
 * Initialize the retained lit indexed mesh visual scenario.
 *
 * @param ctx scenario context
 * @param out_user scenario state output
 * @return whether initialization succeeded
 */
static bool _scenario_init(DvzScenarioContext* ctx, void** out_user)
{
    if (ctx == NULL)
        return false;
    if (out_user != NULL)
        *out_user = NULL;

    bool ok = false;
    MeshState* state = (MeshState*)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);
    EXAMPLE_CHECK(ctx->figure != NULL, "dvz_figure() failed");

    DvzPanel* panel = dvz_panel_full(ctx->figure);
    EXAMPLE_CHECK(panel != NULL, "dvz_panel_full() failed");
    example_graphite_cyan_set_panel_background(panel);

    EXAMPLE_CHECK(example_set_default_3d_camera(panel, 1.0f), "dvz_panel_set_camera_desc() failed");

    EXAMPLE_CHECK(_add_mesh(ctx->scene, panel, &state->geometry), "mesh visual setup failed");

    DvzController* arcball_controller = dvz_arcball(ctx->scene, NULL);
    EXAMPLE_CHECK(arcball_controller != NULL, "dvz_arcball() failed");
    EXAMPLE_CHECK(
        dvz_scenario_bind_controller(ctx, panel, arcball_controller, DVZ_DIM_MASK_XYZ) == 0,
        "dvz_scenario_bind_controller() failed");

    ok = true;
cleanup:
    return ok;
}



/**
 * Destroy the retained lit indexed mesh visual scenario state.
 *
 * @param ctx scenario context
 * @param user scenario state
 */
static void _scenario_destroy(DvzScenarioContext* ctx, void* user)
{
    (void)ctx;
    MeshState* state = (MeshState*)user;
    if (state == NULL)
        return;
    if (state->geometry != NULL)
        dvz_geometry_destroy(state->geometry);
    dvz_free(state);
}



/**
 * Return the retained lit indexed mesh visual scenario.
 *
 * @return scenario specification
 */
DvzScenarioSpec dvz_visual_mesh_scenario(void)
{
    return (DvzScenarioSpec){
        .id = "visuals_mesh",
        .title = "Mesh",
        .width = WIDTH,
        .height = HEIGHT,
        .fps = 60.0,
        .init = _scenario_init,
        .destroy = _scenario_destroy,
    };
}



/*************************************************************************************************/
/*  Functions                                                                                    */
/*************************************************************************************************/

/**
 * Run the retained lit indexed mesh visual 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_visual_mesh_scenario();
    return dvz_scenario_run_native_cli(&spec, argc, argv) == 0 ? 0 : 1;
}
#endif
Example details

Tags

mesh, indexed-geometry, arcball, capture

Data

Field Value
kind synthetic