SceneCamera provides camera movement and view/projection matrices for Go 3D applications. It supports museum, first-person, and real-time strategy movement, plus side-by-side stereo rendering.
It is designed for OpenGL but only depends on mathgl. The returned matrices can be copied into another graphics library's matrix format.
go get github.com/donomii/sceneCamera@latest
package main
import (
"fmt"
sceneCamera "github.com/donomii/sceneCamera"
)
func main() {
camera := sceneCamera.New(2)
camera.Move(0, 0.5)
viewMatrix := camera.ViewMatrix()
fmt.Println(viewMatrix)
}Modes are selected when creating a camera:
sceneCamera.New(1)— museum mode, which orbits a target and zooms in or out.sceneCamera.New(2)— FPS/flight mode, with translation, pitch, and yaw. Roll inputs are ignored.sceneCamera.New(3)— RTS mode, which moves over a ground plane and orbits a point on that plane.
Move takes a direction and an amount. Translation amounts use world units; rotation amounts use radians.
| Direction | Operation |
|---|---|
0 |
Forward |
1 |
Backward |
2 |
Left |
3 |
Right |
4 |
Up |
5 |
Down |
6 |
Pitch up |
7 |
Pitch down |
8 |
Yaw left |
9 |
Yaw right |
10 |
Roll left |
11 |
Roll right |
Each mode applies only the operations that make sense for that camera style.
SceneCamera returns separate view and projection matrices for each eye without taking control of rendering:
func RenderStereoFrame(state *State) {
// Set the inter-pupillary distance in world units.
camera.SetIPD(2.0)
width, height := MainWin.GetSize()
camera.Screenwidth = float32(width) / 2
camera.Screenheight = float32(height)
leftViewMatrix := camera.LeftEyeViewMatrix()
leftProjectionMatrix := camera.LeftEyeFrustum()
gl.Viewport(0, 0, int32(width/2), int32(height))
RenderFrame(state, leftViewMatrix, leftProjectionMatrix)
rightViewMatrix := camera.RightEyeViewMatrix()
rightProjectionMatrix := camera.RightEyeFrustum()
gl.Viewport(int32(width/2), 0, int32(width/2), int32(height))
RenderFrame(state, rightViewMatrix, rightProjectionMatrix)
gl.Viewport(0, 0, int32(width), int32(height))
}Museum and FPS cameras start at (0, 0, 5), looking at the origin, with positive Y as up.
RTS cameras start at (5, 5, 5), looking at the origin, with positive Z as up. The default ground plane is z=0, with the normal (0, 0, 1).
These settings can be changed through the camera fields and setter methods.
The example directory contains an OpenGL application:
cd example
go run .
Run either no-argument launcher from the example directory:
./record-rts-demo.sh
./record-flight-demo.sh
Each launcher renders a deterministic 480×270 animation with 72 frames over 5.04 seconds and replaces its corresponding GIF in the repository root.


