Transcript Document

FunWorlds
the story continues..
Fp group, 04/07/2002
work-in-progress overview
Claus Reinke
Background & Goals
• turn computers into expressive tools..
• create a platform for functional graphics
• look at language design issues at the
borders between
– functional programming
– 3d graphics & animation (HCIs)
– concurrent systems
• Input from: Fran, VRML, process
calculi,..
The story so far..
• Various works on functional graphics..
• Fran (Elliot et.al.) – functional reactive
animation as a DSL embedded in
Haskell
• FunWorlds/VRML (myself) –
experiments in merging ideas from Fran
and VRML; realized as an embedded
compiler generating
VRML+ECMAScript from programs in
another Haskell DSEL
VRML'97
Transform/group
• Declarative description
of static scene graphs,
combined with sensor
Script
nodes and event routing
• Imperative script nodes
sensor
and external authoring
interface for complex
scenes and animations
geometry
(Java, ECMAScript)
• Authoring tools
routes
generate complex
eventIns
eventOuts scene elements
External authoring
Fran
fp
predicate
a
a
until/then
t
t
snapshot
stepper
• Behaviour a
continuous time
dependent values
• Event a
streams of timestamped values
• Mutually recursive
integral equations,
interspersed with
reactivity and with fp
Problems with Fran?
• Focus on combinators & 2d graphics – 3d
shapes can be imported and animated by
external transformation behaviours, but they
don't behave themselves
• Monolithic approach to behaviours and
events (functions from times to values,
streams of all events) – leads to lots of lowlevel trickery
– the history of functional i/o taught us to first to hide
stream-plumbing, then to dump monolithic/global
approaches in favour of stepwise/local ones
• There is definitely something fishy going on
with user arguments and integral start times
Opportunities for Fran?
• It gets a lot of things right, but it makes
you feel as if it tried to make too many
things look the same, being too abstract
for its own good
– not everything is best expressed as an
eternal set of mutually recursive integral
equations in global time
– concurrency & communication!
– reactivity? progress/change (without u)?
Where to, then?
• more clearly distinguish behaviour
descriptions from their evaluation
• Move away from monolithic/global
descriptions in favour of stepwise/local ones
• use ideas from process calculi to specify
concurrency and communication
• get rid of global time in favour of local clocks
(keep implicitly globally synchronized
evaluation for now)
• drop idealised continuity in favour of stepped
approximations (or: let's be practical;-)
Interlude - OpenGL
• OpenGL is a widely implemented industry
standard for 2d/3d graphics
• Software implementation possible, but more
typically, it's the API by which to program
special-purpose graphics boards
• A rare occasion of special-purpose hardware
paying off – two separate processors in your
machine! Good graphics engines get
impressive results, bad ones the CPU won't
rescue ..
• The API is thoroughly imperative, and close to
the metal; you set state elements, then keep
throwing vectors at the pipeline, grouped into
The OpenGL rendering
pipeline
Source: The Design of the OpenGL Graphics Interface
Mark Segal Kurt Akeley
Silicon Graphics Computer Systems
2011 N. Shoreline Blvd., Mountain View, CA 94039
http://www.opengl.org/developers/documentation/white_papers/opengl/
The OpenGL rendering state
• Rendering pipeline is modal, with results
depending on setable/getable internal state
• Current colour; Lighting on/off
• Shading flat/smooth (shading, not shadows!)
• Depth-buffering; blending; texturing; ..
• Matrix stack
– Model-view matrices (transform the scene or the
"camera" position)
– Projection matrix (project the scene onto viewport)
– Texture matrix
/* Copyright (c) 1993-1999, Silicon Graphics, void reshape (int w, int h)
Inc. .. OpenGL(R) is a registered trademark of { glViewport (0, 0, (GLsizei) w, (GLsizei) h);
Silicon Graphics, Inc. */
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
#include <GL/glut.h>
gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);
#include <stdlib.h>
glMatrixMode(GL_MODELVIEW);
static int year = 0, day = 0;
glLoadIdentity();
void init(void)
gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);}
{
glClearColor (0.0, 0.0, 0.0, 0.0);
void keyboard (unsigned char key, int x, int y)
glShadeModel (GL_FLAT);
{ switch (key) {
}
case 'd': day = (day + 10) % 360;
glutPostRedisplay(); break; ...
void display(void)
case 27: exit(0); break; default: break; }}
{
glClear (GL_COLOR_BUFFER_BIT);
int main(int argc, char** argv)
glColor3f (1.0, 1.0, 1.0);
{ glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
glPushMatrix();
glutInitWindowSize (500, 500);
glutWireSphere(1.0, 20, 16); /* sun */
glutInitWindowPosition (100, 100);
glRotatef ((GLfloat) year, 0.0, 1.0, 0.0);
glutCreateWindow (argv[0]);
glTranslatef (2.0, 0.0, 0.0);
init ();
glRotatef ((GLfloat) day, 0.0, 1.0, 0.0);
glutDisplayFunc(display);
glutWireSphere(0.2, 10, 8); /* smaller planet */ glutReshapeFunc(reshape);
glPopMatrix();
glutKeyboardFunc(keyboard);
glutSwapBuffers();
glutMainLoop();
}
return 0;}
Interlude - HOpenGL
• Sven Panne's Haskell binding to OpenGL
– on windows systems, grab ghc-5.02.3, recent
greencard and cygwin, and HOpenGL1.2;
straightforward installation and use as a new ghc
package; includes bindings to GLU and GLUT; get
it from www.haskell.org/HOpenGL/
– comes with no docs, but with all examples from
the OpenGL programming guide (in both Haskell
and C forms); the API is a slightly sanitized
version of the original, so the original docs apply
(see www.opengl.org for specs, docs, tutorials,
stories..)
– OpenGL is available on most platforms, typically
with hw-support; HOpenGL is currently limited to
GHC, but is expected to switch to the new FFI
{- Planet.hs .. Copyright(C) 2000 Sven Panne..-} reshape :: ReshapeAction
reshape screenSize@(WindowSize w h) = do
import IOExts(IORef, newIORef, readIORef,
viewport (WindowPosition 0 0) screenSize
writeIORef)
matrixMode Projection
import System(ExitCode(..), exitWith)
loadIdentity
import GL
perspective 60.0 (fromIntegral w/fromIntegral h) 1.0 20.0
import GLU
matrixMode Modelview
import GLUT
loadIdentity
lookAt (0.0, 0.0, 5.0) (0.0, 0.0, 0.0) (0.0, 1.0, 0.0)
myInit :: IO ()
..
keyboard :: IORef Int -> IORef Int -> KeyboardAction
myInit = do
keyboard day _ 'd' _ = do
clearColor (Color4 0.0 0.0 0.0 0.0)
updateIORef day (\d -> (d+10) `mod` 360);
shadeModel GL.Flat
postRedisplay ..
keyboard _ _ '\27' _ = exitWith ExitSuccess
display :: IORef Int->IORef Int->DisplayAction
keyboard _ _ _ _ = return ()
display day year = do
clear [ColorBufferBit]
main = do
color (Color3 1.0 1.0 1.0 :: Color3 GLfloat)
(progName, _args) <- GLUT.init Nothing
pushMatrix
day <- newIORef 0
year <- newIORef 0
wireSphere 1.0 20 16 -- draw sun
createWindow progName (display day year)
y <- readIORef year
[GLUT.Double, GLUT.Rgb ]
rotate (fromIntegral y::GLfloat) (Vector3 0 1 0)
(Just (WindowPosition 100 100))
translate (Vector3 2 0 0 :: Vector3 GLfloat)
(Just (WindowSize 500 500))
d <- readIORef day
myInit
rotate (fromIntegral d::GLfloat) (Vector3 0 1 0) reshapeFunc (Just reshape)
wireSphere 0.2 10 8 -- draw smaller planet
keyboardFunc (Just (keyboard day year))
popMatrix
mainLoop
swapBuffers
•
•
•
•
•
•
FunWorlds as a scene graph
library
Who wants to bother with those details?
Let users specify scene graphs, a la VRML
Add behaviours, a la Fran
Add communication a la process calculi
Fiddle with design until satisfied (never!-)
Translate the resulting "communicating
concurrent behavioural scene graphs" or
whatever into GLUT callbacks and
instructions for the OpenGL rendering
pipeline..
module Main where
import Behavior
import Scene
import FunWorlds
main :: IO ()
main = start (KeyBoard scene)
year, day :: Beh GLdouble
year = integral (ifB (keyPressed (=='y')) 5
(ifB (keyPressed (=='Y')) (-5)
0))
day = integral (ifB (keyPressed (=='d')) 10
(ifB (keyPressed (=='D')) (-10)
0))
scene keyb =
Group [ Appearance{material=colored $
Color4 1 1 1 1}
, sun, planet ]
where
sun = Sphere 1
planet = Rotate (R year (Vector3 0 1 0)) $
Translate (Vector3 2 0 0) $
Rotate (R day (Vector3 0 1 0)) $
Sphere 0.2
key = Observe Nothing keyb
keyPressed p = lift1 (maybe False p) key
Use the source, Luke!-)
• From here, it's source code, examples,
whiteboard, and hand-waving..