Table of Contents

Hosting DispEngine in a Rendering Canvas

A rendering canvas is the UI component your application puts on screen to display and interact with 3D content. This section explains the contract it has with the DispEngine: what the engine expects from the host control, and what the host gets back.

Overview

HiAPI does not ship a rendering canvas — your application owns it. Up to HiNc 3.2.31 the Hi.WinForm and Hi.WpfPlus packages carried ready-made ones; both were retired, so a Windows application now hosts DispEngine in a control of its own. Building Your Own Rendering Canvas walks the implementation end to end and keeps a frozen copy of the Windows Forms and WPF versions as a worked reference.

What follows is framework-independent: the engine/displayee relationship, the operations a canvas exposes, and the input it has to forward. Whatever UI toolkit hosts it — Windows Forms, WPF, Avalonia, a browser surface — the architecture below is the same.

Core Concept: DispEngine and IDisplayee

At the heart of the rendering system is the relationship between DispEngine and IDisplayee:

  • DispEngine: The rendering engine that manages the OpenGL context and handles user interaction. IsGlAvailable reports whether the process obtained a usable context; a host must not obtain a DispEngine while it is false — NC play, physics and training still run in that state, rendering does not
  • IDisplayee: The interface that defines objects that can be rendered by the DispEngine

This relationship is fundamental - the purpose of DispEngine is to render IDisplayee objects.

graph TD
    A[IDisplayee Objects] -->|Rendered by| B
    B[DispEngine] <--> C[RenderingCanvas UI Component]

Working with IDisplayee

Objects implementing IDisplayee define what gets rendered. Typically, you'll use Drawing objects or compose multiple IDisplayee objects together:

// Create a composite displayee
public class MyCompositeDisplayee : IDisplayee
{
    private List<IDisplayee> _displayees = new List<IDisplayee>();
    
    public MyCompositeDisplayee()
    {
        // Add various displayees
        _displayees.Add(new AxesDisplayee());
        _displayees.Add(new ModelDisplayee());
    }
    
    public void Display(Bind bind)
    {
        // Render all contained displayees
        foreach (var displayee in _displayees)
        {
            displayee.Display(bind);
        }
    }
    
    public void ExpandToBox3d(ref box3d_t box)
    {
        // Update bounding box based on all displayees
        foreach (var displayee in _displayees)
        {
            displayee.ExpandToBox3d(ref box);
        }
    }
}

For more detailed information on creating displayees with Drawing, see the Drawing section.

Basic Usage

Your canvas owns a DispEngine and exposes it, so the rest of the application talks to the engine rather than to the control. Both shapes below are in use — take a displayee in the constructor, or let the caller assign one afterwards:

Windows Forms

// The canvas type is yours -- see Building Your Own Rendering Canvas.
var displayee = new MyCompositeDisplayee();

// Initialize the canvas with the displayee
var canvas = new MyRenderingCanvas(displayee);

// Access the DispEngine for direct manipulation
DispEngine engine = canvas.DispEngine;

// Add to a form
myForm.Controls.Add(canvas);

WPF

var displayee = new MyCompositeDisplayee();

// Initialize the canvas
var canvas = new MyRenderingCanvas();

// Set displayee objects through the DispEngine
canvas.DispEngine.Displayee = displayee;

// Add to a container
myGrid.Children.Add(canvas);

Switching Displayees at Runtime

You can dynamically change what's being displayed:

// Switch to a different displayee
renderingCanvas.DispEngine.Displayee = alternativeDisplayee;

// Or update a DispList
var displayList = new DispList();
if (showModel) displayList.Add(modelDisplayee);
if (showGrid) displayList.Add(gridDisplayee);
renderingCanvas.DispEngine.Displayee = displayList;

Key Features of DispEngine

The DispEngine provides cross-platform support for:

  • Handles buffer swapping and image generation
  • Mouse/pointer events
  • Keyboard navigation
  • Touch gestures
  • Zoom, pan, and rotate operations
  • Resize and Visibility changed.
  • Camera positioning and orientation
  • Standard views (front, top, isometric, etc.)
  • Renders IDisplayee implementations

Touch and Gesture Support

The DispEngine centralizes touch handling across all platforms with a unified API that supports:

  • Single-finger pan
  • Two-finger rotate and scale
  • Multi-finger specialized operations

The touch API is designed to be simple for UI implementations to use. Platform-specific UI components only need to capture touch events and forward them to the DispEngine.

Common Operations

// Accessing DispEngine (works on all platforms)
var engine = renderingCanvas.DispEngine;

// Set to standard views
engine.SetViewToHomeView();
engine.SetViewToFrontView();

// Manual camera manipulation
engine.Translate(dx, dy);
engine.Rotate(deltaX, deltaY);

// Resize handling
engine.Resize(width, height);

Implementation Details

For detailed implementation information, including:

  • Full source code examples
  • Implementation details for each platform
  • Advanced touch handling
  • Custom implementation guidance

See the Building Your Own Rendering Canvas guide.

See Also