2016-11-23 07:03:23 -06:00
|
|
|
package pixelgl
|
|
|
|
|
2016-11-23 11:06:55 -06:00
|
|
|
import (
|
2016-12-18 13:16:27 -06:00
|
|
|
"runtime"
|
2016-12-30 18:33:53 -06:00
|
|
|
"unsafe"
|
2016-12-18 13:16:27 -06:00
|
|
|
|
2016-11-23 11:06:55 -06:00
|
|
|
"github.com/go-gl/gl/v3.3-core/gl"
|
2016-12-01 09:44:54 -06:00
|
|
|
"github.com/go-gl/mathgl/mgl32"
|
2016-11-23 11:06:55 -06:00
|
|
|
"github.com/pkg/errors"
|
|
|
|
)
|
2016-11-23 08:59:21 -06:00
|
|
|
|
|
|
|
// VertexArray is an OpenGL vertex array object that also holds it's own vertex buffer object.
|
|
|
|
// From the user's points of view, VertexArray is an array of vertices that can be drawn.
|
|
|
|
type VertexArray struct {
|
2016-12-21 15:29:23 -06:00
|
|
|
vao, vbo, ebo binder
|
|
|
|
numVertices, numIndices int
|
|
|
|
format AttrFormat
|
|
|
|
stride int
|
|
|
|
offset map[string]int
|
2016-11-23 08:59:21 -06:00
|
|
|
}
|
|
|
|
|
2016-12-30 18:33:53 -06:00
|
|
|
// NewVertexArray creates a new empty vertex array.
|
2016-12-08 08:25:00 -06:00
|
|
|
//
|
2016-12-30 10:53:47 -06:00
|
|
|
// You cannot specify vertex attributes in this constructor, only their count. Use
|
|
|
|
// SetVertexAttribute* methods to set the vertex attributes. Use indices to specify how you
|
|
|
|
// want to combine vertices into triangles.
|
2016-12-30 18:33:53 -06:00
|
|
|
func NewVertexArray(shader *Shader, numVertices int, indices []int) (*VertexArray, error) {
|
2016-11-23 08:59:21 -06:00
|
|
|
va := &VertexArray{
|
2016-12-14 09:24:31 -06:00
|
|
|
vao: binder{
|
|
|
|
restoreLoc: gl.VERTEX_ARRAY_BINDING,
|
|
|
|
bindFunc: func(obj uint32) {
|
|
|
|
gl.BindVertexArray(obj)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
vbo: binder{
|
|
|
|
restoreLoc: gl.ARRAY_BUFFER_BINDING,
|
|
|
|
bindFunc: func(obj uint32) {
|
|
|
|
gl.BindBuffer(gl.ARRAY_BUFFER, obj)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
ebo: binder{
|
|
|
|
restoreLoc: gl.ELEMENT_ARRAY_BUFFER_BINDING,
|
|
|
|
bindFunc: func(obj uint32) {
|
|
|
|
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, obj)
|
|
|
|
},
|
|
|
|
},
|
2016-12-21 15:29:23 -06:00
|
|
|
numVertices: numVertices,
|
2016-12-30 18:33:53 -06:00
|
|
|
format: shader.VertexFormat(),
|
|
|
|
stride: shader.VertexFormat().Size(),
|
2016-12-21 15:29:23 -06:00
|
|
|
offset: make(map[string]int),
|
2016-11-23 08:59:21 -06:00
|
|
|
}
|
2016-11-24 07:37:11 -06:00
|
|
|
|
2016-11-26 15:42:26 -06:00
|
|
|
offset := 0
|
2016-12-30 18:33:53 -06:00
|
|
|
for name, typ := range va.format {
|
2016-12-15 17:28:52 -06:00
|
|
|
switch typ {
|
2016-12-02 11:21:28 -06:00
|
|
|
case Float, Vec2, Vec3, Vec4:
|
2016-11-29 16:11:53 -06:00
|
|
|
default:
|
2016-12-30 18:33:53 -06:00
|
|
|
return nil, errors.New("failed to create vertex array: invalid attribute type")
|
2016-11-29 16:11:53 -06:00
|
|
|
}
|
2016-12-15 17:28:52 -06:00
|
|
|
va.offset[name] = offset
|
|
|
|
offset += typ.Size()
|
2016-11-26 15:42:26 -06:00
|
|
|
}
|
|
|
|
|
2016-12-30 18:33:53 -06:00
|
|
|
gl.GenVertexArrays(1, &va.vao.obj)
|
2016-11-25 15:49:56 -06:00
|
|
|
|
2016-12-30 18:33:53 -06:00
|
|
|
va.vao.bind()
|
|
|
|
|
|
|
|
gl.GenBuffers(1, &va.vbo.obj)
|
|
|
|
defer va.vbo.bind().restore()
|
|
|
|
|
|
|
|
emptyData := make([]byte, numVertices*va.stride)
|
|
|
|
gl.BufferData(gl.ARRAY_BUFFER, len(emptyData), gl.Ptr(emptyData), gl.DYNAMIC_DRAW)
|
|
|
|
|
|
|
|
gl.GenBuffers(1, &va.ebo.obj)
|
|
|
|
defer va.ebo.bind().restore()
|
|
|
|
|
|
|
|
for name, typ := range va.format {
|
|
|
|
loc := gl.GetAttribLocation(shader.ID(), gl.Str(name+"\x00"))
|
|
|
|
|
|
|
|
var size int32
|
|
|
|
switch typ {
|
|
|
|
case Float:
|
|
|
|
size = 1
|
|
|
|
case Vec2:
|
|
|
|
size = 2
|
|
|
|
case Vec3:
|
|
|
|
size = 3
|
|
|
|
case Vec4:
|
|
|
|
size = 4
|
|
|
|
}
|
|
|
|
|
|
|
|
gl.VertexAttribPointer(
|
|
|
|
uint32(loc),
|
|
|
|
size,
|
|
|
|
gl.FLOAT,
|
|
|
|
false,
|
|
|
|
int32(va.stride),
|
|
|
|
gl.PtrOffset(va.offset[name]),
|
|
|
|
)
|
|
|
|
gl.EnableVertexAttribArray(uint32(loc))
|
|
|
|
}
|
|
|
|
|
|
|
|
va.vao.restore()
|
2016-12-08 08:25:00 -06:00
|
|
|
|
|
|
|
va.SetIndices(indices)
|
2016-11-24 07:37:11 -06:00
|
|
|
|
2016-12-18 13:16:27 -06:00
|
|
|
runtime.SetFinalizer(va, (*VertexArray).delete)
|
|
|
|
|
2016-11-23 11:06:55 -06:00
|
|
|
return va, nil
|
2016-11-23 08:59:21 -06:00
|
|
|
}
|
|
|
|
|
2016-12-18 13:16:27 -06:00
|
|
|
func (va *VertexArray) delete() {
|
2016-12-18 18:11:34 -06:00
|
|
|
DoNoBlock(func() {
|
|
|
|
gl.DeleteVertexArrays(1, &va.vao.obj)
|
|
|
|
gl.DeleteBuffers(1, &va.vbo.obj)
|
|
|
|
gl.DeleteBuffers(1, &va.ebo.obj)
|
2016-11-23 13:06:34 -06:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-12-02 11:03:51 -06:00
|
|
|
// ID returns an OpenGL identifier of a vertex array.
|
|
|
|
func (va *VertexArray) ID() uint32 {
|
2016-12-14 09:24:31 -06:00
|
|
|
return va.vao.obj
|
2016-12-02 11:03:51 -06:00
|
|
|
}
|
|
|
|
|
2016-12-21 15:29:23 -06:00
|
|
|
// NumVertices returns the number of vertices in a vertex array.
|
|
|
|
func (va *VertexArray) NumVertices() int {
|
|
|
|
return va.numVertices
|
2016-11-29 16:11:53 -06:00
|
|
|
}
|
|
|
|
|
2016-11-23 08:59:21 -06:00
|
|
|
// VertexFormat returns the format of the vertices inside a vertex array.
|
|
|
|
//
|
|
|
|
// Do not change this format!
|
2016-12-15 17:28:52 -06:00
|
|
|
func (va *VertexArray) VertexFormat() AttrFormat {
|
2016-11-23 08:59:21 -06:00
|
|
|
return va.format
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw draws a vertex array.
|
2016-12-30 18:33:53 -06:00
|
|
|
//
|
|
|
|
// The vertex array must be bound before calling this method.
|
2016-11-23 08:59:21 -06:00
|
|
|
func (va *VertexArray) Draw() {
|
2016-12-30 18:33:53 -06:00
|
|
|
gl.DrawElements(gl.TRIANGLES, int32(va.numIndices), gl.UNSIGNED_INT, gl.PtrOffset(0))
|
2016-11-23 08:59:21 -06:00
|
|
|
}
|
|
|
|
|
2016-12-30 10:53:47 -06:00
|
|
|
// SetIndices sets the indices of triangles to be drawn. Triangles will be formed from the
|
|
|
|
// vertices of the array as defined by these indices. The first drawn triangle is specified by
|
|
|
|
// the first three indices, the second by the fourth through sixth and so on.
|
2016-12-30 18:33:53 -06:00
|
|
|
//
|
|
|
|
// The vertex array must be bound before calling this method.
|
2016-12-08 08:25:00 -06:00
|
|
|
func (va *VertexArray) SetIndices(indices []int) {
|
|
|
|
if len(indices)%3 != 0 {
|
|
|
|
panic("vertex array set indices: number of indices not divisible by 3")
|
|
|
|
}
|
|
|
|
indices32 := make([]uint32, len(indices))
|
|
|
|
for i := range indices32 {
|
|
|
|
indices32[i] = uint32(indices[i])
|
|
|
|
}
|
2016-12-21 15:29:23 -06:00
|
|
|
va.numIndices = len(indices32)
|
2016-12-30 18:33:53 -06:00
|
|
|
|
|
|
|
gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, 4*len(indices32), gl.Ptr(indices32), gl.DYNAMIC_DRAW)
|
2016-12-08 08:25:00 -06:00
|
|
|
}
|
|
|
|
|
2016-12-15 17:41:03 -06:00
|
|
|
// Indices returns the current indices of triangles to be drawn.
|
2016-12-30 18:33:53 -06:00
|
|
|
//
|
|
|
|
// The vertex array must be bound before calling this method.
|
2016-12-15 17:41:03 -06:00
|
|
|
func (va *VertexArray) Indices() []int {
|
2016-12-21 15:29:23 -06:00
|
|
|
indices32 := make([]uint32, va.numIndices)
|
2016-12-30 18:33:53 -06:00
|
|
|
|
|
|
|
gl.GetBufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, 4*len(indices32), gl.Ptr(indices32))
|
|
|
|
|
2016-12-15 17:41:03 -06:00
|
|
|
indices := make([]int, len(indices32))
|
|
|
|
for i := range indices {
|
|
|
|
indices[i] = int(indices32[i])
|
|
|
|
}
|
2016-12-30 18:33:53 -06:00
|
|
|
|
2016-12-15 17:41:03 -06:00
|
|
|
return indices
|
|
|
|
}
|
|
|
|
|
2016-12-13 09:46:19 -06:00
|
|
|
// SetVertexAttr sets the value of the specified vertex attribute of the specified vertex.
|
|
|
|
//
|
2016-12-30 10:53:47 -06:00
|
|
|
// If the vertex attribute does not exist, this method returns false. If the vertex is out of
|
|
|
|
// range, this method panics.
|
2016-12-13 09:46:19 -06:00
|
|
|
//
|
2016-12-30 10:53:47 -06:00
|
|
|
// Supplied value must correspond to the type of the attribute. Correct types are these
|
|
|
|
// (righ-hand is the type of the value):
|
2016-12-13 09:46:19 -06:00
|
|
|
// Attr{Type: Float}: float32
|
|
|
|
// Attr{Type: Vec2}: mgl32.Vec2
|
|
|
|
// Attr{Type: Vec3}: mgl32.Vec3
|
|
|
|
// Attr{Type: Vec4}: mgl32.Vec4
|
|
|
|
// No other types are supported.
|
2016-12-30 18:33:53 -06:00
|
|
|
//
|
|
|
|
// The vertex array must be bound before calling this method.
|
2016-12-13 09:46:19 -06:00
|
|
|
func (va *VertexArray) SetVertexAttr(vertex int, attr Attr, value interface{}) (ok bool) {
|
2016-12-21 15:29:23 -06:00
|
|
|
if vertex < 0 || vertex >= va.numVertices {
|
2016-12-13 09:46:19 -06:00
|
|
|
panic("set vertex attr: invalid vertex index")
|
2016-12-01 08:53:34 -06:00
|
|
|
}
|
|
|
|
|
2016-12-15 17:28:52 -06:00
|
|
|
if !va.format.Contains(attr) {
|
2016-12-01 08:53:34 -06:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2016-12-30 18:33:53 -06:00
|
|
|
offset := va.stride*vertex + va.offset[attr.Name]
|
|
|
|
|
|
|
|
switch attr.Type {
|
|
|
|
case Float:
|
|
|
|
value := value.(float32)
|
|
|
|
gl.BufferSubData(gl.ARRAY_BUFFER, offset, attr.Type.Size(), unsafe.Pointer(&value))
|
|
|
|
case Vec2:
|
|
|
|
value := value.(mgl32.Vec2)
|
|
|
|
gl.BufferSubData(gl.ARRAY_BUFFER, offset, attr.Type.Size(), unsafe.Pointer(&value))
|
|
|
|
case Vec3:
|
|
|
|
value := value.(mgl32.Vec3)
|
|
|
|
gl.BufferSubData(gl.ARRAY_BUFFER, offset, attr.Type.Size(), unsafe.Pointer(&value))
|
|
|
|
case Vec4:
|
|
|
|
value := value.(mgl32.Vec4)
|
|
|
|
gl.BufferSubData(gl.ARRAY_BUFFER, offset, attr.Type.Size(), unsafe.Pointer(&value))
|
|
|
|
default:
|
|
|
|
panic("set vertex attr: invalid attribute type")
|
|
|
|
}
|
2016-12-13 09:46:19 -06:00
|
|
|
|
2016-12-01 08:53:34 -06:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2016-12-13 09:46:19 -06:00
|
|
|
// VertexAttr returns the current value of the specified vertex attribute of the specified vertex.
|
2016-12-01 08:53:34 -06:00
|
|
|
//
|
2016-12-30 10:53:47 -06:00
|
|
|
// If the vertex attribute does not exist, this method returns nil and false. If the vertex is
|
|
|
|
// out of range, this method panics.
|
2016-12-13 09:46:19 -06:00
|
|
|
//
|
|
|
|
// The type of the returned value follows the same rules as with SetVertexAttr.
|
2016-12-30 18:33:53 -06:00
|
|
|
//
|
|
|
|
// The vertex array must be bound before calling this method.
|
2016-12-13 09:46:19 -06:00
|
|
|
func (va *VertexArray) VertexAttr(vertex int, attr Attr) (value interface{}, ok bool) {
|
2016-12-21 15:29:23 -06:00
|
|
|
if vertex < 0 || vertex >= va.numVertices {
|
2016-12-13 09:46:19 -06:00
|
|
|
panic("vertex attr: invalid vertex index")
|
2016-12-01 08:53:34 -06:00
|
|
|
}
|
|
|
|
|
2016-12-15 17:28:52 -06:00
|
|
|
if !va.format.Contains(attr) {
|
2016-12-13 09:46:19 -06:00
|
|
|
return nil, false
|
2016-11-26 15:51:20 -06:00
|
|
|
}
|
2016-12-13 09:46:19 -06:00
|
|
|
|
2016-12-30 18:33:53 -06:00
|
|
|
offset := va.stride*vertex + va.offset[attr.Name]
|
|
|
|
|
|
|
|
switch attr.Type {
|
|
|
|
case Float:
|
|
|
|
var data float32
|
|
|
|
gl.GetBufferSubData(gl.ARRAY_BUFFER, offset, attr.Type.Size(), unsafe.Pointer(&data))
|
|
|
|
value = data
|
|
|
|
case Vec2:
|
|
|
|
var data mgl32.Vec2
|
|
|
|
gl.GetBufferSubData(gl.ARRAY_BUFFER, offset, attr.Type.Size(), unsafe.Pointer(&data))
|
|
|
|
value = data
|
|
|
|
case Vec3:
|
|
|
|
var data mgl32.Vec3
|
|
|
|
gl.GetBufferSubData(gl.ARRAY_BUFFER, offset, attr.Type.Size(), unsafe.Pointer(&data))
|
|
|
|
value = data
|
|
|
|
case Vec4:
|
|
|
|
var data mgl32.Vec4
|
|
|
|
gl.GetBufferSubData(gl.ARRAY_BUFFER, offset, attr.Type.Size(), unsafe.Pointer(&data))
|
|
|
|
value = data
|
|
|
|
default:
|
|
|
|
panic("set vertex attr: invalid attribute type")
|
|
|
|
}
|
2016-12-13 09:46:19 -06:00
|
|
|
|
|
|
|
return value, true
|
2016-11-23 08:59:21 -06:00
|
|
|
}
|
|
|
|
|
2016-12-30 10:53:47 -06:00
|
|
|
// SetVertex sets values of the attributes specified in the supplied map. All other attributes
|
|
|
|
// will be set to zero.
|
2016-12-19 18:23:33 -06:00
|
|
|
//
|
|
|
|
// Not existing attributes are silently skipped.
|
2016-12-30 18:33:53 -06:00
|
|
|
//
|
|
|
|
// The vertex array must be bound before calling this method.
|
2016-12-19 18:23:33 -06:00
|
|
|
func (va *VertexArray) SetVertex(vertex int, values map[Attr]interface{}) {
|
2016-12-21 15:29:23 -06:00
|
|
|
if vertex < 0 || vertex >= va.numVertices {
|
2016-12-19 18:23:33 -06:00
|
|
|
panic("set vertex: invalid vertex index")
|
|
|
|
}
|
|
|
|
|
|
|
|
data := make([]float32, va.format.Size()/4)
|
|
|
|
|
|
|
|
for attr, value := range values {
|
|
|
|
if !va.format.Contains(attr) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
offset := va.offset[attr.Name]
|
|
|
|
|
|
|
|
switch attr.Type {
|
|
|
|
case Float:
|
2016-12-20 06:56:25 -06:00
|
|
|
data[offset/4] = value.(float32)
|
2016-12-19 18:23:33 -06:00
|
|
|
case Vec2:
|
|
|
|
value := value.(mgl32.Vec2)
|
|
|
|
copy(data[offset/4:offset/4+attr.Type.Size()/4], value[:])
|
|
|
|
case Vec3:
|
|
|
|
value := value.(mgl32.Vec3)
|
|
|
|
copy(data[offset/4:offset/4+attr.Type.Size()/4], value[:])
|
|
|
|
case Vec4:
|
|
|
|
value := value.(mgl32.Vec4)
|
|
|
|
copy(data[offset/4:offset/4+attr.Type.Size()/4], value[:])
|
|
|
|
default:
|
|
|
|
panic("set vertex: invalid attribute type")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-30 18:33:53 -06:00
|
|
|
offset := va.stride * vertex
|
|
|
|
gl.BufferSubData(gl.ARRAY_BUFFER, offset, len(data)*4, gl.Ptr(data))
|
2016-12-19 18:23:33 -06:00
|
|
|
}
|
|
|
|
|
2016-12-20 06:56:25 -06:00
|
|
|
// Vertex returns values of all vertex attributes of the specified vertex in a map.
|
2016-12-30 18:33:53 -06:00
|
|
|
//
|
|
|
|
// The vertex array must be bound before calling this method.
|
2016-12-20 06:56:25 -06:00
|
|
|
func (va *VertexArray) Vertex(vertex int) (values map[Attr]interface{}) {
|
2016-12-21 15:29:23 -06:00
|
|
|
if vertex < 0 || vertex >= va.numVertices {
|
2016-12-20 06:56:25 -06:00
|
|
|
panic("set vertex: invalid vertex index")
|
|
|
|
}
|
|
|
|
|
|
|
|
data := make([]float32, va.format.Size()/4)
|
|
|
|
|
2016-12-30 18:33:53 -06:00
|
|
|
offset := va.stride * vertex
|
|
|
|
gl.GetBufferSubData(gl.ARRAY_BUFFER, offset, len(data)*4, gl.Ptr(data))
|
2016-12-20 06:56:25 -06:00
|
|
|
|
|
|
|
values = make(map[Attr]interface{})
|
|
|
|
|
|
|
|
for name, typ := range va.format {
|
|
|
|
attr := Attr{name, typ}
|
|
|
|
offset := va.offset[attr.Name]
|
|
|
|
|
|
|
|
switch attr.Type {
|
|
|
|
case Float:
|
|
|
|
values[attr] = data[offset/4]
|
|
|
|
case Vec2:
|
|
|
|
var value mgl32.Vec2
|
|
|
|
copy(value[:], data[offset/4:offset/4+attr.Type.Size()/4])
|
|
|
|
values[attr] = value
|
|
|
|
case Vec3:
|
|
|
|
var value mgl32.Vec3
|
|
|
|
copy(value[:], data[offset/4:offset/4+attr.Type.Size()/4])
|
|
|
|
values[attr] = value
|
|
|
|
case Vec4:
|
|
|
|
var value mgl32.Vec4
|
|
|
|
copy(value[:], data[offset/4:offset/4+attr.Type.Size()/4])
|
|
|
|
values[attr] = value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return values
|
|
|
|
}
|
|
|
|
|
2016-12-30 10:53:47 -06:00
|
|
|
// SetVertices sets values of vertex attributes of all vertices as specified in the supplied
|
|
|
|
// slice of maps. If the length of vertices does not match the number of vertices in the vertex
|
|
|
|
// array, this method panics.
|
2016-12-19 18:23:33 -06:00
|
|
|
//
|
|
|
|
// Not existing attributes are silently skipped.
|
2016-12-30 18:33:53 -06:00
|
|
|
//
|
|
|
|
// The vertex array must be bound before calling this metod.
|
2016-12-20 06:56:25 -06:00
|
|
|
func (va *VertexArray) SetVertices(vertices []map[Attr]interface{}) {
|
2016-12-21 15:29:23 -06:00
|
|
|
if len(vertices) != va.numVertices {
|
2016-12-19 18:23:33 -06:00
|
|
|
panic("set vertex array: wrong number of supplied vertices")
|
|
|
|
}
|
|
|
|
|
2016-12-21 15:29:23 -06:00
|
|
|
data := make([]float32, va.numVertices*va.format.Size()/4)
|
2016-12-19 18:23:33 -06:00
|
|
|
|
|
|
|
for vertex := range vertices {
|
|
|
|
for attr, value := range vertices[vertex] {
|
|
|
|
if !va.format.Contains(attr) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
offset := va.stride*vertex + va.offset[attr.Name]
|
|
|
|
|
|
|
|
switch attr.Type {
|
|
|
|
case Float:
|
2016-12-20 06:56:25 -06:00
|
|
|
data[offset/4] = value.(float32)
|
2016-12-19 18:23:33 -06:00
|
|
|
case Vec2:
|
|
|
|
value := value.(mgl32.Vec2)
|
|
|
|
copy(data[offset/4:offset/4+attr.Type.Size()/4], value[:])
|
|
|
|
case Vec3:
|
|
|
|
value := value.(mgl32.Vec3)
|
|
|
|
copy(data[offset/4:offset/4+attr.Type.Size()/4], value[:])
|
|
|
|
case Vec4:
|
|
|
|
value := value.(mgl32.Vec4)
|
|
|
|
copy(data[offset/4:offset/4+attr.Type.Size()/4], value[:])
|
|
|
|
default:
|
|
|
|
panic("set vertex: invalid attribute type")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-30 18:33:53 -06:00
|
|
|
gl.BufferSubData(gl.ARRAY_BUFFER, 0, len(data)*4, gl.Ptr(data))
|
2016-12-20 06:56:25 -06:00
|
|
|
}
|
2016-12-19 18:23:33 -06:00
|
|
|
|
2016-12-30 10:53:47 -06:00
|
|
|
// Vertices returns values of vertex attributes of all vertices in a vertex array in a slice
|
|
|
|
// of maps.
|
2016-12-30 18:33:53 -06:00
|
|
|
//
|
|
|
|
// The vertex array must be bound before calling this metod.
|
2016-12-20 06:56:25 -06:00
|
|
|
func (va *VertexArray) Vertices() (vertices []map[Attr]interface{}) {
|
2016-12-21 15:29:23 -06:00
|
|
|
data := make([]float32, va.numVertices*va.format.Size()/4)
|
2016-12-20 06:56:25 -06:00
|
|
|
|
2016-12-30 18:33:53 -06:00
|
|
|
gl.GetBufferSubData(gl.ARRAY_BUFFER, 0, len(data)*4, gl.Ptr(data))
|
2016-12-20 06:56:25 -06:00
|
|
|
|
2016-12-21 15:29:23 -06:00
|
|
|
vertices = make([]map[Attr]interface{}, va.numVertices)
|
2016-12-20 06:56:25 -06:00
|
|
|
|
|
|
|
for vertex := range vertices {
|
|
|
|
values := make(map[Attr]interface{})
|
|
|
|
|
|
|
|
for name, typ := range va.format {
|
|
|
|
attr := Attr{name, typ}
|
|
|
|
offset := va.stride*vertex + va.offset[attr.Name]
|
|
|
|
|
|
|
|
switch attr.Type {
|
|
|
|
case Float:
|
|
|
|
values[attr] = data[offset/4]
|
|
|
|
case Vec2:
|
|
|
|
var value mgl32.Vec2
|
|
|
|
copy(value[:], data[offset/4:offset/4+attr.Type.Size()/4])
|
|
|
|
values[attr] = value
|
|
|
|
case Vec3:
|
|
|
|
var value mgl32.Vec3
|
|
|
|
copy(value[:], data[offset/4:offset/4+attr.Type.Size()/4])
|
|
|
|
values[attr] = value
|
|
|
|
case Vec4:
|
|
|
|
var value mgl32.Vec4
|
|
|
|
copy(value[:], data[offset/4:offset/4+attr.Type.Size()/4])
|
|
|
|
values[attr] = value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
vertices[vertex] = values
|
|
|
|
}
|
|
|
|
|
|
|
|
return vertices
|
2016-12-19 18:23:33 -06:00
|
|
|
}
|
|
|
|
|
2016-12-30 18:33:53 -06:00
|
|
|
// Begin binds a vertex array. This is neccessary before using the vertex array.
|
|
|
|
func (va *VertexArray) Begin() {
|
|
|
|
va.vao.bind()
|
|
|
|
va.vbo.bind()
|
|
|
|
va.ebo.bind()
|
|
|
|
}
|
|
|
|
|
|
|
|
// End unbinds a vertex array and restores the previous one.
|
|
|
|
func (va *VertexArray) End() {
|
|
|
|
va.ebo.restore()
|
|
|
|
va.vbo.restore()
|
|
|
|
va.vao.restore()
|
2016-11-23 08:59:21 -06:00
|
|
|
}
|