tofu

Making something with OpenGL in Go
Log | Files | Refs

tofu.go (3910B)


      1 package tofu
      2 
      3 import (
      4 	"errors"
      5 	"fmt"
      6 	"log"
      7 	"unsafe"
      8 
      9 	"github.com/go-gl/gl/v3.3-core/gl"
     10 	"github.com/go-gl/glfw/v3.3/glfw"
     11 )
     12 
     13 type App interface {
     14 	Update() error
     15 }
     16 
     17 type Cursor struct {
     18 	X, Y int
     19 }
     20 
     21 type CursorApp interface {
     22 	App
     23 	CursorChan() chan<- Cursor
     24 }
     25 
     26 func watchCursor(c chan<- Cursor) {
     27 	callback := func(w *glfw.Window, x, y float64) {
     28 		c <- Cursor{X: int(x), Y: int(y)}
     29 	}
     30 	window.SetCursorPosCallback(callback)
     31 }
     32 
     33 type Scroll struct {
     34 	Dx, Dy float32
     35 }
     36 
     37 type ScrollApp interface {
     38 	App
     39 	ScrollChan() chan<- Scroll
     40 }
     41 
     42 func watchScroll(c chan<- Scroll) {
     43 	callback := func(w *glfw.Window, dx, dy float64) {
     44 		c <- Scroll{Dx: float32(dx), Dy: float32(dy)}
     45 	}
     46 	window.SetScrollCallback(callback)
     47 }
     48 
     49 var (
     50 	window      *glfw.Window
     51 	winW, winH  int    = 800, 600
     52 	winTitle    string = "Tofu"
     53 	keyCallback func(*glfw.Window)
     54 )
     55 
     56 func Init() error {
     57 	err := glfw.Init()
     58 	if err != nil {
     59 		return fmt.Errorf("init glfw: %v", err)
     60 	}
     61 	glfw.WindowHint(glfw.ContextVersionMajor, 3)
     62 	glfw.WindowHint(glfw.ContextVersionMinor, 3)
     63 	glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
     64 
     65 	window, err = glfw.CreateWindow(winW, winH, winTitle, nil, nil)
     66 	if err != nil {
     67 		return fmt.Errorf("create window: %v", err)
     68 	}
     69 	window.MakeContextCurrent()
     70 	if err = gl.Init(); err != nil {
     71 		return fmt.Errorf("init gl: %v", err)
     72 	}
     73 	gl.Viewport(0, 0, int32(winW), int32(winH))
     74 	gl.Enable(gl.DEBUG_OUTPUT)
     75 	gl.DebugMessageCallback(messageCallback, nil)
     76 	window.SetFramebufferSizeCallback(framebufferSizeCallback)
     77 
     78 	gl.Enable(gl.DEPTH_TEST)
     79 
     80 	window.SetInputMode(glfw.CursorMode, glfw.CursorDisabled)
     81 	return nil
     82 }
     83 
     84 func Run(app App) error {
     85 	if app, ok := app.(CursorApp); ok {
     86 		c := app.CursorChan()
     87 		watchCursor(c)
     88 		defer close(c)
     89 	}
     90 	if app, ok := app.(ScrollApp); ok {
     91 		c := app.ScrollChan()
     92 		watchScroll(c)
     93 		defer close(c)
     94 	}
     95 
     96 	for !window.ShouldClose() {
     97 		gl.ClearColor(0.3, 0.3, 0, 1.0)
     98 		gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
     99 		err := app.Update()
    100 		if err == Termination {
    101 			break
    102 		}
    103 		window.SwapBuffers()
    104 		glfw.PollEvents()
    105 	}
    106 	glfw.Terminate()
    107 	return nil
    108 }
    109 
    110 func messageCallback(source, gltype, id, severity uint32, length int32, message string, userProgram unsafe.Pointer) {
    111 	log.Printf("debug: type = 0x%x, severity = 0x%x, message = %s", gltype, severity, message)
    112 }
    113 
    114 func framebufferSizeCallback(w *glfw.Window, width int, height int) {
    115 	gl.Viewport(0, 0, int32(width), int32(height))
    116 }
    117 
    118 func SetFramebufferSizeCallback(f glfw.FramebufferSizeCallback) {
    119 }
    120 
    121 func SetWindowSize(w, h int) {
    122 	winW, winH = w, h
    123 }
    124 
    125 func SetWindowTitle(t string) {
    126 	winTitle = t
    127 }
    128 
    129 type Key int
    130 
    131 const (
    132 	KeyA         Key = Key(glfw.KeyA)
    133 	KeyB             = Key(glfw.KeyB)
    134 	KeyC             = Key(glfw.KeyC)
    135 	KeyD             = Key(glfw.KeyD)
    136 	KeyE             = Key(glfw.KeyE)
    137 	KeyF             = Key(glfw.KeyF)
    138 	KeyG             = Key(glfw.KeyG)
    139 	KeyH             = Key(glfw.KeyH)
    140 	KeyI             = Key(glfw.KeyI)
    141 	KeyJ             = Key(glfw.KeyJ)
    142 	KeyK             = Key(glfw.KeyK)
    143 	KeyL             = Key(glfw.KeyL)
    144 	KeyM             = Key(glfw.KeyM)
    145 	KeyN             = Key(glfw.KeyN)
    146 	KeyO             = Key(glfw.KeyO)
    147 	KeyP             = Key(glfw.KeyP)
    148 	KeyQ             = Key(glfw.KeyQ)
    149 	KeyR             = Key(glfw.KeyR)
    150 	KeyS             = Key(glfw.KeyS)
    151 	KeyT             = Key(glfw.KeyT)
    152 	KeyU             = Key(glfw.KeyU)
    153 	KeyV             = Key(glfw.KeyV)
    154 	KeyW             = Key(glfw.KeyW)
    155 	KeyX             = Key(glfw.KeyX)
    156 	KeyY             = Key(glfw.KeyY)
    157 	KeyZ             = Key(glfw.KeyZ)
    158 	KeySpace         = Key(glfw.KeySpace)
    159 	KeyLeftShift     = Key(glfw.KeyLeftShift)
    160 	KeyUp            = Key(glfw.KeyUp)
    161 	KeyDown          = Key(glfw.KeyDown)
    162 	KeyRight         = Key(glfw.KeyRight)
    163 	KeyLeft          = Key(glfw.KeyLeft)
    164 )
    165 
    166 var Termination error = errors.New("Termination")
    167 
    168 func IsKeyPressed(key Key) bool {
    169 	return window.GetKey(glfw.Key(key)) == glfw.Press
    170 }