tofu

Making something with OpenGL in Go
Log | Files | Refs

object.go (2353B)


      1 package tofu
      2 
      3 import (
      4 	"image/color"
      5 
      6 	"github.com/go-gl/gl/v3.3-core/gl"
      7 )
      8 
      9 type Point2D struct {
     10 	X, Y float32
     11 }
     12 
     13 type Point3D struct {
     14 	X, Y, Z float32
     15 }
     16 
     17 type Object struct {
     18 	Vertices  []Point3D
     19 	Colors    []color.Color
     20 	TexCoords []Point2D
     21 	Faces     [][3]uint32
     22 	vao       *VAO
     23 }
     24 
     25 func (obj Object) data() []float32 {
     26 	data := make([]float32, 8 * len(obj.Vertices))
     27 	for i := 0; i < len(obj.Vertices); i++ {
     28 		data[8 * i] = obj.Vertices[i].X
     29 		data[8 * i + 1] = obj.Vertices[i].Y
     30 		data[8 * i + 2] = obj.Vertices[i].Z
     31 		r, g, b, _ := obj.Colors[i].RGBA()
     32 		data[8 * i + 3] = float32(r)/0xffff
     33 		data[8 * i + 4] = float32(g)/0xffff
     34 		data[8 * i + 5] = float32(b)/0xffff
     35 		data[8 * i + 6] = obj.TexCoords[i].X
     36 		data[8 * i + 7] = obj.TexCoords[i].Y
     37 	}
     38 	return data
     39 }
     40 
     41 func (obj Object) faceData() []uint32 {
     42 	fdata := make([]uint32, 3 * len(obj.Faces))
     43 	for i, v := range obj.Faces {
     44 		fdata[3 * i] = v[0]
     45 		fdata[3 * i + 1] = v[1]
     46 		fdata[3 * i + 2] = v[2]
     47 	}
     48 	return fdata
     49 }
     50 
     51 // Load copies object data into the GPU.
     52 func (obj *Object) Load() {
     53 	obj.vao = newVAO(obj)
     54 }
     55 
     56 type VAO struct {
     57 	id uint32
     58 	vbo *Buffer
     59 	ebo *Buffer
     60 }
     61 
     62 const (
     63 	UniformVertex = iota
     64 	UniformColor
     65 	UniformTexCoords
     66 )
     67 
     68 func newVAO(obj *Object) *VAO {
     69 	var id uint32
     70 	gl.GenVertexArrays(1, &id)
     71 	vao := &VAO{id: id, vbo: newBuffer(), ebo: newBuffer()}
     72 	vao.bind()
     73 	data := obj.data()
     74 	vao.setData(data)
     75 	vao.setAttribute(UniformVertex, 3, 8, 0)
     76 	vao.setAttribute(UniformColor, 3, 8, 3)
     77 	vao.setAttribute(UniformTexCoords, 2, 8, 6)
     78 	fdata := obj.faceData()
     79 	vao.setFaces(fdata)
     80 	return vao
     81 }
     82 
     83 func (vao *VAO) bind() {
     84 	gl.BindVertexArray(vao.id)
     85 }
     86 
     87 func (vao *VAO) setAttribute(uniformNum uint32, size int, stride int, offset int) {
     88 	gl.VertexAttribPointerWithOffset(uniformNum, int32(size), gl.FLOAT,
     89 		false, int32(stride) * 4, uintptr(offset) * 4)
     90 	gl.EnableVertexAttribArray(uniformNum)
     91 }
     92 
     93 func (vao *VAO) setData(data []float32) {
     94 	gl.BindBuffer(gl.ARRAY_BUFFER, vao.vbo.id)
     95 	gl.BufferData(gl.ARRAY_BUFFER, len(data) * 4,
     96 		gl.Ptr(data), gl.STATIC_DRAW)
     97 }
     98 
     99 func (vao *VAO) setFaces(data []uint32) {
    100 	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, vao.ebo.id)
    101 	gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(data) * 4,
    102 		gl.Ptr(data), gl.STATIC_DRAW)
    103 }
    104 
    105 type Buffer struct {
    106 	id uint32
    107 }
    108 
    109 func newBuffer() *Buffer {
    110 	var id uint32
    111 	gl.GenBuffers(1, &id)
    112 	return &Buffer{id: id}
    113 }