Seer User Guide

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 14

a framework for rapid development of interactive audio visual environments in Scala

Seer
Seer is a collection of code and modules that I've found helpful in developing interactive graphical worlds for artistic
installations and performances. Seer also enables the live development of worlds through on-the-fly compiliation of Scala
scripts.
Right now it is a simple collection of helper objects and libraries that provide tools for working with 3D environments,
meshes, shaders, audio, video, OSC, scheduable events, and live-coding. It is designed to be extensible with existing
modules for using openni, opencv, portaudio, osx trackpad, video, vrpn..
Seer currently uses libGDX as its application foundation, providing cross platform opengl and windowing backends for
desktop and mobile environments.
What is Seer?
Scala is a hybrid language combining object oriented programming and functional programming under one roof. Scala
aims to cut down on boilerplate code and provide an expressive experience.
I have found working in scala to be both productive and fun. As an artist and a programmer working on building
interactive audio visual environments, having a tool that is both fun and flexible is quite helpful.
Why Scala?
Make sure you have java installed, javac -version should return a version number. If not, install JDK 7 or OpenJDK 7.
You will also need git.
Getting Started
Prerequisites
Seer source code is available on github and can be dowloaded by running:
git clone https://github.com/fishuyo/seer.git
If you want to get started building your own project see using Seer Template Project below.
Download Seer
Seer uses sbt to build and run projects.
Sbt has an interactive mode, which lets you navigate different sub-projects of the build and run commands on them. To
launch sbt run from within the seer directory:
./sbt
The first time you run this it may take a few minutes to reach the sbt command prompt. This executes a script which when
run for the first time downloads sbt and some unmanaged dependencies necessary to build seer, and then launches sbt.
Once you reach the sbt prompt designated by a ">" try running the following commands:
project examples
run
The first command switches the currently selected project to the 'examples' project. The 'run' tells sbt to run the Main class
of the project, which first requires that all of the project's dependencies be fetched and successfully compiled.
If a project has more than one Main class it will ask you to enter a number to choose which one to run.
It is also possible to run commands without starting sbt in interactive mode. To build the basic examples try running the
following from within the seer directory:
./sbt 'project examples' run
Seer has a few different example subprojects to show how to use different modules of seer. Check them all out. Run ./sbt
projects to list all of the projects in the build.
To learn more about using sbt go here.
Building and Running Examples
If you want to make your own project that uses Seer and its modules you can get started quickly by cloning the seer-
template-project:
git clone https://github.com/fishuyo/seer-template-project.git project-name
After cloning, run ./init from inside the cloned project-name directory. This downloads Seer as a submodule.
Run the template projects example main with ./sbt run
Seer Template Project
To get started with your own code, see how to download seer-template-project in Getting Started, or simply add scala
files to the example directory of Seer and run them from the sbt example project.
Seer Tutorial
The most basic program in Scala looks like this:
package my.package.name
object Main extends App {
println("Hello World: " + args.mkString(" ")
}
But where is the main function? Our Main object inherits the App trait. There is a little bit of trickery in the App trait which is
actually hiding the main entry point, and ends up executing the body of our Main object. Our object also inherits a
member named args containing any command line arguments.
The most basic Seer program looks like this:
package my.package.name
import com.fishuyo.seer.SeerApp
object Main extends SeerApp {
println("Goodnight Moon: " + args.mkString(" ")
}
Here we have switched out the App trait for SeerApp. SeerApp does a little more than just hide the main function. It is also
hiding the initialization of a libGDX application, which handles the creation of a render window and and openGL context.
SeerApp does one more thing, it adds itself to the global SceneGraph. I will explain more about this later, but you can
think of it like this: anything in the SceneGraph will be drawn and animated every frame, meaning having its draw() and
animate(dt:Float) methods called, consequently anthing in the SceneGraph inherits the Animatable trait.
So lets draw something:
package my.package.name
import com.fishuyo.seer.SeerApp
import com.fishuyo.seer.graphics.Sphere
object Main extends SeerApp {
println("Goodnight Moon: " + args.mkString(" ")
val sphere:Model = Sphere()
override def draw(){
sphere.draw()
}
}
Notice that we've imported another object called Sphere. Sphere generates Models containing a generated sphere
Mesh. A Model is like an instance of a Mesh, with a Pose and Material, letting you change its position and orientation in
space and also how it is rendered by the default Shader.
You'll notice that this looks like simply a white circle, lets change the material to see the effects of the default lighting.
SeerApp
package my.package.name
import com.fishuyo.seer.SeerApp
import com.fishuyo.seer.graphics._
object Main extends SeerApp {
val sphere = Sphere()
sphere.material = Material.specular
sphere.material.color = RGB(1,0,0)
override def draw(){
sphere.draw()
}
}
Here we give the model a specular material and set its color to red.
Lets make a few more objects, and animate them:
package my.package.name
import com.fishuyo.seer.SeerApp
import com.fishuyo.seer.graphics._
object Main extends SeerApp {
val sphere = Sphere().translate(-2,0,-4)
val cube = Cube().translate(0,2,-4)
val tetra = Tetrahedron().translate(2,0,-4)
val quad = Plane().translate(0,-2,-4)
Shader.defaultMaterial = Material.specular
Shader.defaultMaterial.color = RGB(1,0,0)
override def draw(){
sphere.draw()
cube.draw()
tetra.draw()
quad.draw()
}
override def animate(dt:Float){
sphere.rotate(0.01f,0f,0)
cube.rotate(0.01f,0.02f,0)
tetra.rotate(0.02f,0.01f,0)
quad.rotate(0.01f,0.03f,0)
}
}
Here notice the addition of the animate method, which is called every frame, causing the models to be rotated. Also,
instead of setting the material for each model, we set the default material in the Shader object, which I'll explain later. We
also see a few other built in Model generators, and some transformation functions on the Model class.
Now lets make something a little more interesting:
package my.package.name
import com.fishuyo.seer.SeerApp
import com.fishuyo.seer.graphics._
object Main extends SeerApp {
val n = 30 // number of models to make
val s = 1.f / n // scale factor based on n
// generate a list of cubes using yield
// collecting what is returned from the block in this case c
val cubes = for(i <- 0 until n) yield {
val c = Cube().scale(1,s,1).translate(0, i*s - .5f, 0)
c.material = Material.specular
c.material.color = HSV(i*s, 0.7f, 0.7f)
c
}
override def draw(){
FPS.print // print current fps
cubes.foreach( _.draw ) // draw each cube
}
override def animate(dt:Float){
// rotate each cube based on its index in the list
cubes.zipWithIndex.foreach {
case(cube, idx) => cube.rotate(0,(idx+1)*s/100,0)
}
}
}
Here we use Scala's for comprehension and yield to generate a list of Models. We then rotate each model every frame at
a different rate corresponding to its index in the list.
Seer script is a way of having more immediate feedback as you are coding. Seer script is simply a way of monitoring a
scala file and compiling it when it is modified. If it compiles sucessfully it will be automatically added to the SceneGraph
and will start running. Everytime you make a change, the script is recompiled and re-run, replacing the previous Script in
the SceneGraph.
Here is an example SeerApp using a ScalaScriptLoader:
package tutorial
import com.fishuyo.seer._
import dynamic.SeerScriptLoader
object Main extends SeerApp {
val live = new SeerScriptLoader("scripts/live.scala")
}
That's it for the Main program, now make another scala file in a directory called "scripts" named "live.scala":
import com.fishuyo.seer._
import dynamic.SeerScript
import graphics._
object Script extends SeerScript {
override def draw(){
Sphere().draw()
}
override def animate(dt:Float){}
}
Script
A couple important things to note. First, this object extends SeerScript. Second, we return the object from our script in the
final line. These are necessary for your Script to run properly within the running context.
Now, any changes you make to the live.scala file will be compiled on the fly and show up. If they don't, check the console
to see if any compilation errors occured.
All for now, have fun!
Seer Script
Table of Contents
Introduction 2
Getting Started 4
Seer Tutorial 8

You might also like