210 lines
4.9 KiB
Go
210 lines
4.9 KiB
Go
package globject
|
|
|
|
import (
|
|
"git.wisellama.rocks/Wisellama/carpy-breakout/pkg/glshader"
|
|
gl "github.com/go-gl/gl/v3.1/gles2"
|
|
"github.com/go-gl/mathgl/mgl32"
|
|
)
|
|
|
|
type Box struct {
|
|
baseAABB *AABB
|
|
|
|
Material *Material
|
|
Faces []*Face
|
|
VertexArray []float32
|
|
Translation mgl32.Vec3
|
|
Velocity mgl32.Vec3
|
|
Rotation mgl32.Vec3
|
|
RotationVelocity mgl32.Vec3
|
|
Size int32
|
|
Width float32
|
|
Height float32
|
|
Depth float32
|
|
GLProgram uint32
|
|
GLVertexArrayID uint32
|
|
GLVertexBufferID uint32
|
|
Wireframe bool
|
|
}
|
|
|
|
func NewBox(
|
|
width, height, depth float32,
|
|
position mgl32.Vec3, material *Material) *Box {
|
|
// depth = z axis (towards)
|
|
// width = x axis (right)
|
|
// height = y axis (up)
|
|
|
|
box := Box{
|
|
Size: 6,
|
|
Width: width,
|
|
Depth: depth,
|
|
Height: height,
|
|
Translation: position,
|
|
Material: material,
|
|
RotationVelocity: mgl32.Vec3{0, 0, 0},
|
|
}
|
|
|
|
topPos := mgl32.Vec3{0, height / 2.0, 0}
|
|
top := NewFace(width, depth, topPos, mgl32.Vec3{0, 1, 0}, material)
|
|
|
|
bottomPos := mgl32.Vec3{0, -height / 2.0, 0}
|
|
bottom := NewFace(width, depth, bottomPos, mgl32.Vec3{0, -1, 0}, material)
|
|
|
|
frontPos := mgl32.Vec3{0, 0, depth / 2.0}
|
|
front := NewFace(width, height, frontPos, mgl32.Vec3{0, 0, 1}, material)
|
|
|
|
backPos := mgl32.Vec3{0, 0, -depth / 2.0}
|
|
back := NewFace(width, height, backPos, mgl32.Vec3{0, 0, -1}, material)
|
|
|
|
rightPos := mgl32.Vec3{width / 2.0, 0, 0}
|
|
right := NewFace(height, depth, rightPos, mgl32.Vec3{1, 0, 0}, material)
|
|
|
|
leftPos := mgl32.Vec3{-width / 2.0, 0, 0}
|
|
left := NewFace(height, depth, leftPos, mgl32.Vec3{-1, 0, 0}, material)
|
|
|
|
box.Faces = []*Face{
|
|
top,
|
|
bottom,
|
|
front,
|
|
back,
|
|
right,
|
|
left,
|
|
}
|
|
|
|
box.VertexArray = box.GetVertexArray()
|
|
|
|
box.baseAABB = NewAABBFromBox(&box)
|
|
|
|
return &box
|
|
}
|
|
|
|
func (b *Box) GLInit(glProgram uint32) {
|
|
b.GLProgram = glProgram
|
|
gl.GenVertexArrays(1, &b.GLVertexArrayID)
|
|
gl.BindVertexArray(b.GLVertexArrayID)
|
|
|
|
gl.GenBuffers(1, &b.GLVertexBufferID)
|
|
gl.BindBuffer(gl.ARRAY_BUFFER, b.GLVertexBufferID)
|
|
sizeOfFloat := 4
|
|
gl.BufferData(gl.ARRAY_BUFFER, len(b.VertexArray)*sizeOfFloat, gl.Ptr(b.VertexArray), gl.STATIC_DRAW)
|
|
|
|
for _, face := range b.Faces {
|
|
face.GLInit(b.GLProgram)
|
|
}
|
|
}
|
|
|
|
func (b *Box) Update() {
|
|
b.Rotation = b.Rotation.Add(b.RotationVelocity)
|
|
b.Translation = b.Translation.Add(b.Velocity)
|
|
}
|
|
|
|
// GetModelMatrix applies the current rotation and translation to give you a model matrix.
|
|
// Multiplying the original positions by this matrix will give you the new position.
|
|
// It is also used in the OpenGL shaders directly.
|
|
func (b *Box) GetModelMatrix() *mgl32.Mat4 {
|
|
if b.Rotation.LenSqr() == 0 && b.Translation.LenSqr() == 0 {
|
|
model := mgl32.Ident4()
|
|
return &model
|
|
}
|
|
|
|
// Apply rotation
|
|
rotate := b.GetRotationMatrix()
|
|
|
|
// Apply translation
|
|
translate := mgl32.Translate3D(b.Translation.X(), b.Translation.Y(), b.Translation.Z())
|
|
|
|
model := translate.Mul4(*rotate)
|
|
|
|
return &model
|
|
}
|
|
|
|
func (b *Box) GetRotationMatrix() *mgl32.Mat4 {
|
|
rotateX := mgl32.HomogRotate3D(b.Rotation.X(), mgl32.Vec3{1, 0, 0})
|
|
rotateY := mgl32.HomogRotate3D(b.Rotation.Y(), mgl32.Vec3{0, 1, 0})
|
|
rotateZ := mgl32.HomogRotate3D(b.Rotation.Z(), mgl32.Vec3{0, 0, 1})
|
|
rotate := rotateX.Mul4(rotateY)
|
|
rotate = rotate.Mul4(rotateZ)
|
|
|
|
return &rotate
|
|
}
|
|
|
|
func (b *Box) GLDraw() {
|
|
model := b.GetModelMatrix()
|
|
|
|
glshader.SetUniformMatrix4f(b.GLProgram, "model", model)
|
|
|
|
b.Material.GLDraw(b.GLProgram)
|
|
|
|
if b.Wireframe {
|
|
b.glDrawLineLoop()
|
|
} else {
|
|
b.glDrawTriangles()
|
|
}
|
|
}
|
|
|
|
func (b *Box) glDrawTriangles() {
|
|
glshader.SetUniformInt(b.GLProgram, "lightsOn", 1)
|
|
|
|
gl.BindVertexArray(b.GLVertexArrayID)
|
|
gl.BindBuffer(gl.ARRAY_BUFFER, b.GLVertexBufferID)
|
|
|
|
if b.Material.TextureOn {
|
|
gl.ActiveTexture(gl.TEXTURE0)
|
|
gl.BindTexture(gl.TEXTURE_2D, b.Material.TextureID)
|
|
}
|
|
|
|
glshader.UpdateVertexAttribs(b.GLProgram, VertexSize)
|
|
gl.DrawArrays(gl.TRIANGLES, 0, 6*2*3) // 6 sides, 2 triangles, 3 points each
|
|
}
|
|
|
|
func (b *Box) glDrawLineLoop() {
|
|
glshader.SetUniformInt(b.GLProgram, "lightsOn", 0)
|
|
for _, face := range b.Faces {
|
|
face.GLDrawLineLoop(b.GLProgram)
|
|
}
|
|
}
|
|
|
|
func (b *Box) GetVertexArray() []float32 {
|
|
// Boxes have 6 faces, 2 triangles per face, 3 vertices per triangle
|
|
// (technically 2 vertices overlap in a face, but ignore that for now)
|
|
totalVertices := 6 * 2 * 3 * VertexSize
|
|
a := make([]float32, totalVertices)
|
|
|
|
i := 0
|
|
for _, face := range b.Faces {
|
|
for _, triangle := range face.Triangles {
|
|
for _, vertex := range triangle.Vertices {
|
|
for _, elem := range vertex.GetVertexArray() {
|
|
a[i] = elem
|
|
i++
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return a
|
|
}
|
|
|
|
func (b *Box) ToggleWireframe() {
|
|
b.Wireframe = !b.Wireframe
|
|
}
|
|
|
|
func (b *Box) SetXVelocity(v float32) {
|
|
b.Velocity[0] = v
|
|
}
|
|
|
|
func (b *Box) SetYVelocity(v float32) {
|
|
b.Velocity[1] = v
|
|
}
|
|
|
|
func (b *Box) SetZVelocity(v float32) {
|
|
b.Velocity[2] = v
|
|
}
|
|
|
|
func (b *Box) SetYRotationVelocity(v float32) {
|
|
b.RotationVelocity[1] = v
|
|
}
|
|
|
|
func (b *Box) GetAABB() *AABB {
|
|
return NewAABBFromBox(b)
|
|
}
|