/
mesh.go
105 lines (96 loc) · 2.61 KB
/
mesh.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package sge
import (
"reflect"
)
import (
"github.com/chsc/gogl/gl33"
)
type Mesh struct {
Attrs interface{}
Indicies []uint32
vao gl33.Uint
vertexBO *Buffer
indexBO *Buffer
}
type DefaultVertex struct {
Vertex [3]float32
Texcoords [2]float32
}
func NewMesh(attrs interface{}, indicies []uint32) *Mesh {
mesh := new(Mesh)
mesh.Attrs = attrs
mesh.Indicies = indicies
gl33.GenVertexArrays(1, &mesh.vao)
gl33.BindVertexArray(mesh.vao)
attrsValue := reflect.ValueOf(attrs)
mesh.vertexBO = NewBuffer(gl33.ARRAY_BUFFER, gl33.STATIC_DRAW, attrs)
vertexSpec := attrsValue.Type().Elem()
if vertexSpec.Kind() != reflect.Struct && vertexSpec.Kind() != reflect.Array {
panic("attrs is not a slice of structs or arrays")
}
var num int
if vertexSpec.Kind() == reflect.Struct {
num = vertexSpec.NumField()
} else {
num = vertexSpec.Len()
}
for i, offset := 0, uintptr(0); i < num; i++ {
var field reflect.Type
var type_ gl33.Enum
var dimensions int
if vertexSpec.Kind() == reflect.Struct {
field = vertexSpec.Field(i).Type
} else {
field = vertexSpec.Elem()
}
if field.Kind() == reflect.Array {
type_ = glType(field.Elem().Kind())
dimensions = field.Len()
} else {
type_ = glType(field.Kind())
dimensions = 1
}
setupAttrib(gl33.Uint(i), type_, dimensions, offset, int(vertexSpec.Size()))
offset += field.Size()
}
mesh.indexBO = NewBuffer(gl33.ELEMENT_ARRAY_BUFFER, gl33.STATIC_DRAW, indicies)
return mesh
}
func setupAttrib(location gl33.Uint, type_ gl33.Enum, dimensions int, offset uintptr, vertexSize int) {
gl33.EnableVertexAttribArray(location)
if type_ == gl33.FLOAT || type_ == gl33.DOUBLE {
gl33.VertexAttribPointer(location, gl33.Int(dimensions), type_, gl33.FALSE, gl33.Sizei(vertexSize), gl33.Pointer(offset))
} else {
gl33.VertexAttribIPointer(location, gl33.Int(dimensions), type_, gl33.Sizei(vertexSize), gl33.Pointer(offset))
}
}
func glType(data reflect.Kind) gl33.Enum {
switch data {
case reflect.Int8:
return gl33.BYTE
case reflect.Int16:
return gl33.SHORT
case reflect.Int32:
return gl33.INT
case reflect.Uint8:
return gl33.UNSIGNED_BYTE
case reflect.Uint16:
return gl33.UNSIGNED_SHORT
case reflect.Uint32:
return gl33.UNSIGNED_INT
case reflect.Float32:
return gl33.FLOAT
case reflect.Float64:
return gl33.DOUBLE
}
panic("Bad element type")
}
func (mesh *Mesh) Delete() {
gl33.DeleteVertexArrays(1, &mesh.vao)
mesh.vertexBO.Delete()
mesh.indexBO.Delete()
}
func (mesh *Mesh) Render() {
gl33.BindVertexArray(mesh.vao)
gl33.DrawElements(gl33.TRIANGLES, gl33.Sizei(len(mesh.Indicies)), gl33.UNSIGNED_INT, gl33.Pointer(uintptr(0)))
}