# Difference between revisions of "SceneGraph"

## Introduction

The aim of the Haskell Scene Graph project is to provide a solid basis for the development of 3D applications. Other work which has 3D content has focused on an application or a research topic. Whilst these projects have a scene graph and/or 3D component, it is not easy to extract a useful library. The project's aim is to provide such a library.

Current Status: Initial 0.1.0.2 version is available on Hackage; last update was in June 2010, there is no maintainer. A version of scenegraph that compiles but is no longer able to render is available at https://github.com/homectl/lambdaray/tree/main/scenegraph.

The library draws inspiration from the following Haskell projects:

and from the following non-Haskell work:

## Getting Started

A scene is constructed using a set of combinators. The following creates a green cube

```cube 0.5 `colour` Green ```

To scale the cube we use the 'scale' function. This takes a vector indicating by how much to scale in X,Y and Z directions:

```cube 0.5 `colour` Green `scale` v1x 40 ```

v1x is a function that given a number n, returns the vector (n,1,1). This contributes to a concise specification of the scene.So here the cube is scale by 40 in the X direction.

To translate the scene we use a similar function to scale:

```cube 0.5 `colour` Green `scale` v1x 40 `translate` vy 2 ```

Finally our scene requires a camera and light to be specified:

```cube 0.5 `colour` Green `scale` v1x 40 `translate` vy 2 <+> camera `translate` vy (-10) <+> light `translate` vz 10 ```

In order to run the scene we use runScene. As the above scene has been constructed in a monad, we need to run the monad, to extract the actual Scene data structure.

```runScene \$ osgt \$ cube 0.5 `colour` Green `scale` v1x 40 `translate` vy 2 <+> camera `translate` vy (-10) <+> light `translate` vz 10 ```

To navigate the scene use the following:

• W - Move forward
• S - Move back
• A - Move left
• D - Move right
• Z - Move down
• X - Move up
• ESC - Exit

## Reactive Scenes

The module Graphics.SceneGraph.Reactive uses Reactive to enliven a scene. ExampleReactive.hs provides an example of this.This uses a calculator defined independently of the GUI and is made tangible by SceneGraph.

```calc = runSceneReactive calculator sceneButtonReactive ```

calculator is the Scene representing the calculator. The button and display objects are labeled to allow event handlers to be applied during a second pass.

sceneButtonReactive is where the second pass is performed and this wires up the calculator.

## Internals

The Scene Graph is built using FGL. So it remains to define a scene node to get things started:

```data SceneData = Group | Geode Geometry | LOD | MatrixTransform (MatrixD) | Switch Int | Material Phong | Handler (Maybe (ClickHandler, Sink ())) (Maybe (DragHandler, Sink GLdouble)) | Light | Camera | Texture String | Text String ```

Group - Supports grouping of nodes. Since the Graph will provide the links to children we don't need to have anything more.

Geode - Is where geometries shapes are specified. In theory these nodes should not have children. Geometries can be basic shapes (provided in GLUT.Objects) or meshes of some form.

LOD - Level of detail. Children of this would be representations of the same sub-scene at different level of detail. Choice of which child which depend on current viewing scale. (Currently not implemented).

MatrixTransform - Transform node.

Switch - Provides the ability to choose the sub-tree based on the integer value. One application of this is to provide a representation to be drawn when the object is selected. Some implementations suggest using a bit map across all the children.

Material - Sets the material for the tree starting at this node. Currently just Phong is shown.

Handler - Some form of event handler can be specified at this node. Two types are available - ClickHandler to handle mouse clicks on the object, and DragHandler to handle drag events on the object.

Light - Specifies a light at the origin.

Camera - Specifies a camera at the origin.

Texture- Named texture is applied to the sub-tree.

Text - Text object.

Note that the scene is defined as a graph but when the monad is run a tree is created.

Wrapping in Monad enables us to define a simple DSL for building Scene Graphs:

```type OSGT m = (StateT OSGState m) -- Append the two graphs parented at the supplied nodes (<+>) :: Monad m => OSGT m SceneNode -> OSGT m SceneNode -> OSGT m SceneNode -- Translate a node (and child graph) -- Rotate, scale and colour can be defined in similar ways translate :: Monad m => OSGT m SceneNode -> Vector3 Float -> OSGT m SceneNode -- Example ferris :: Float -> OSG SceneNode ferris theta = do let ring = torus 0.5 `colour` White --Blue axial1 = cube 0.5 `scale` v1x 40 `colour` Green axial2 = cube 0.5 `scale` v1z 40 `colour` Green axial = axial1 <+> axial2 root <- (ring `translate` vy 2 <+> ring `translate` vy (-2) <+> axial `translate` vy (-2) <+> axial `translate` vy 2 <+> crossbeams) `rotate` (theta , (vector3 0 1 0 )) return root ```

The Monad can be run to extract the actual scene graph and then sent off for viewing.

## Limitations

Currently, system is very fickle about light and camera. These need to be specified and need to be translated immediately.

## Further Work

Build an extended example that uses the library. A puzzle game of some sort.

Texture loading requires program to be run in root directory of package.