ViewerWidget Documentation

ViewerWidget is a simplified wrapper around the Thermion 3D viewer that makes it easy to display 3D models in your Flutter application.

Overview

ViewerWidget handles the setup and configuration of a Thermion viewer, including:

  • Loading 3D models (glTF assets)
  • Configuring skyboxes and image-based lighting
  • Setting up camera positions and manipulators
  • Managing the rendering lifecycle

Installation

First, make sure you have the Thermion Flutter plugin added to your dependencies:

dependencies:
  thermion_flutter: ^latest_version

Basic Usage

import 'package:flutter/material.dart';
import 'package:thermion_flutter/thermion_flutter.dart';
import 'path_to_your_viewer_widget.dart';

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: ViewerWidget(
          assetPath: 'assets/my_model.glb',
          initialCameraPosition: Vector3(0, 0, 5),
          manipulatorType: ManipulatorType.ORBIT,
        ),
      ),
    );
  }
}

Properties

PropertyTypeDefaultDescription
initialWidgetRed decorated boxWidget to display while the viewer is loading
initialCameraPositionVector3Vector3(0, 0, 5)The starting position for the camera (looking towards origin)
showFpsCounterboolfalseWhether to show an FPS counter overlay
assetPathString?nullPath to the glTF asset to load
skyboxPathString?nullPath to a KTX skybox image
iblPathString?nullPath to a KTX image for image-based lighting
directLightTypeLightType?nullType of direct light to add to the scene
transformToUnitCubebooltrueIf true, rescales the model to fit within a 1x1x1 cube
postProcessingbooltrueEnables ACES tone mapping and basic anti-aliasing
backgroundColor?nullBackground color (not visible when skybox is provided)
destroyEngineOnUnloadboolfalseIf true, disposes the engine when widget is disposed
manipulatorTypeManipulatorTypeORBITType of camera control to use
onViewerAvailableFuture Function(ThermionViewer)?nullCallback when viewer is ready

Camera Manipulators

ViewerWidget supports three different camera manipulation modes:

  • ManipulatorType.NONE: No camera controls, static view
  • ManipulatorType.ORBIT: Orbit controls (pinch to zoom, swipe to rotate)
  • ManipulatorType.FREE_FLIGHT: Free flight controls for unrestricted movement

Example:

ViewerWidget(
  assetPath: 'assets/model.glb',
  manipulatorType: ManipulatorType.FREE_FLIGHT,
)

Lighting

You can set up lighting in multiple ways:

Image-Based Lighting

ViewerWidget(
  assetPath: 'assets/model.glb',
  iblPath: 'assets/environment.ktx',
)

Direct Light

ViewerWidget(
  assetPath: 'assets/model.glb',
  directLightType: LightType.SUN,
)

Advanced Usage

Accessing the Viewer

You can get access to the underlying ThermionViewer object for more advanced control:

ViewerWidget(
  assetPath: 'assets/model.glb',
  onViewerAvailable: (viewer) async {
    // Now you can use the viewer directly
    final camera = await viewer.getActiveCamera();
    await camera.lookAt(Vector3(0, 1, 5));
    
    // Add custom lights, manipulate materials, etc.
  },
)

Changing Manipulator at Runtime

The manipulatorType is the only property that can be changed after the widget is created:

class _MyWidgetState extends State<MyWidget> {
  ManipulatorType _manipulatorType = ManipulatorType.ORBIT;
  
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Expanded(
          child: ViewerWidget(
            assetPath: 'assets/model.glb',
            manipulatorType: _manipulatorType,
          ),
        ),
        Row(
          children: [
            ElevatedButton(
              onPressed: () {
                setState(() {
                  _manipulatorType = ManipulatorType.ORBIT;
                });
              },
              child: Text('Orbit'),
            ),
            ElevatedButton(
              onPressed: () {
                setState(() {
                  _manipulatorType = ManipulatorType.FREE_FLIGHT;
                });
              },
              child: Text('Free Flight'),
            ),
          ],
        ),
      ],
    );
  }
}

Limitations

  • Only the manipulatorType property can be changed at runtime. For any other property changes, create a new widget.
  • The widget requires that you have the correct environment setup for Thermion (Flutter master channel with native assets enabled).

Example

Here's a complete example showing how to use ViewerWidget with multiple configuration options:

import 'package:flutter/material.dart';
import 'package:thermion_flutter/thermion_flutter.dart';
import 'package:vector_math/vector_math_64.dart';

class ModelViewer extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('3D Model Viewer')),
      body: ViewerWidget(
        assetPath: 'assets/robot.glb',
        skyboxPath: 'assets/studio_skybox.ktx',
        iblPath: 'assets/studio_ibl.ktx',
        initialCameraPosition: Vector3(0, 1.5, 3),
        manipulatorType: ManipulatorType.ORBIT,
        showFpsCounter: true,
        background: Colors.grey,
        postProcessing: true,
        transformToUnitCube: true,
        onViewerAvailable: (viewer) async {
          // You can perform additional setup here
          print('Viewer is ready!');
        },
      ),
    );
  }
}