SceneGraph
From HaskellWiki
m |
(Initial version release to Hackage) |
||
| Line 5: | Line 5: | ||
component, it is not easy to extract a useful library. The project's aim is to provide such a library. | 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 version is available on [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/scenegraph Hackage] | |
| - | + | The library draws inspiration from the following Haskell projects: | |
| - | + | ||
| - | + | ||
* [[PolyFunViz]] | * [[PolyFunViz]] | ||
| Line 21: | Line 19: | ||
* [http://en.wikipedia.org/wiki/COLLADA COLLADA] | * [http://en.wikipedia.org/wiki/COLLADA COLLADA] | ||
| - | == | + | == Getting Started == |
| - | + | ||
| + | A scene is constructed using a set of combinators. The following creates a green cube | ||
<code><pre> | <code><pre> | ||
| - | + | cube 0.5 `colour` Green | |
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
</pre></code> | </pre></code> | ||
| - | '' | + | 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: |
| - | + | <code><pre> | |
| + | cube 0.5 `colour` Green `scale` v1x 40 | ||
| + | </pre></code> | ||
| - | + | 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: | |
| - | + | <code><pre> | |
| + | cube 0.5 `colour` Green `scale` v1x 40 `translate` vy 2 | ||
| + | </pre></code> | ||
| - | + | Finally our scene requires a camera and light to be specified: | |
| - | ''' | + | <code><pre> |
| + | cube 0.5 `colour` Green `scale` v1x 40 `translate` vy 2 <+> camera `translate` vy (-10) <+> light `translate` vz 10 | ||
| + | </pre></code> | ||
| + | |||
| + | 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. | ||
| + | |||
| + | <code><pre> | ||
| + | runScene $ osgt $ cube 0.5 `colour` Green `scale` v1x 40 `translate` vy 2 <+> camera `translate` vy (-10) <+> light `translate` vz 10 | ||
| + | </pre></code> | ||
| + | |||
| + | 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 independantly of the GUI and is made tangible by SceneGraph. | ||
| + | |||
| + | <code><pre> | ||
| + | calc = runSceneReactive calculator sceneButtonReactive | ||
| + | </pre></code> | ||
| + | |||
| + | calculator is the Scene representing the calculator. The button and display objects are labelled to allow event hanlders 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 [http://web.engr.oregonstate.edu/~erwig/fgl/haskell FGL]. So it remains to define a scene node to get things started: | ||
| + | |||
| + | <code><pre> | ||
| + | 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 | ||
| + | </pre></code> | ||
| + | |||
| + | '''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 | + | Note that the scene is defined as a graph but when the monad is run a tree is created. |
== Scene Graph Monad == | == Scene Graph Monad == | ||
| Line 82: | Line 141: | ||
</pre></code> | </pre></code> | ||
| - | The Monad can be run to extract the actual scene graph and then sent off for viewing | + | 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. | |
| - | + | ||
Revision as of 00:55, 1 June 2008
Contents |
1 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 version is available on Hackage
The library draws inspiration from the following Haskell projects:
and from the following non-Haskell work:
2 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
3 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 independantly 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 labelled to allow event hanlders to be applied during a second pass.
sceneButtonReactive is where the second pass is performed and this wires up the calculator.
4 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.
5 Scene Graph Monad
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.
6 Limitations
Currently, system is very fickle about light and camera. These need to be specified and need to be translated immediately.
7 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.
