mirror of
https://github.com/Kugelschieber/go-game.git
synced 2026-01-18 14:50:28 +00:00
194 lines
4.2 KiB
Go
194 lines
4.2 KiB
Go
package goga
|
|
|
|
import (
|
|
"github.com/go-gl/gl/v3.2-core/gl"
|
|
)
|
|
|
|
const (
|
|
model_renderer_name = "modelRenderer"
|
|
)
|
|
|
|
// Component representing a 3D mesh.
|
|
type Mesh struct {
|
|
Index, Vertex, TexCoord *VBO
|
|
Vao *VAO
|
|
}
|
|
|
|
// Model is an actor having a 3D position, a texture and a 3D mesh.
|
|
type Model struct {
|
|
*Actor
|
|
*Pos3D
|
|
*Tex
|
|
*Mesh
|
|
}
|
|
|
|
// The model renderer is a system rendering models.
|
|
// It has a 3D position component, to move all models at once.
|
|
type ModelRenderer struct {
|
|
Pos3D
|
|
|
|
Shader *Shader
|
|
Camera *Camera
|
|
ortho bool
|
|
|
|
models []Model
|
|
}
|
|
|
|
// Creates a new mesh with given GL buffers.
|
|
// The VAO must be prepared by ModelRenderer.
|
|
func NewMesh(index, vertex, texcoord *VBO) *Mesh {
|
|
mesh := &Mesh{}
|
|
mesh.Index = index
|
|
mesh.Vertex = vertex
|
|
mesh.TexCoord = texcoord
|
|
|
|
CheckGLError()
|
|
|
|
return mesh
|
|
}
|
|
|
|
// Drops the VBOs and VAO contained in mesh.
|
|
// This must not be done, if mesh was filled from outer source (like a ply file).
|
|
func (m *Mesh) Drop() {
|
|
m.Index.Drop()
|
|
m.Vertex.Drop()
|
|
m.TexCoord.Drop()
|
|
m.Vao.Drop()
|
|
}
|
|
|
|
// Creates a new model with given mesh and texture.
|
|
func NewModel(mesh *Mesh, tex *Tex) *Model {
|
|
model := &Model{}
|
|
model.Actor = NewActor()
|
|
model.Pos3D = NewPos3D()
|
|
model.Tex = tex
|
|
model.Mesh = mesh
|
|
model.Size = Vec3{1, 1, 1}
|
|
model.Scale = Vec3{1, 1, 1}
|
|
model.Visible = true
|
|
|
|
CheckGLError()
|
|
|
|
return model
|
|
}
|
|
|
|
// Creates a new model renderer using given shader and camera.
|
|
// If shader and/or camera are nil, the default one will be used.
|
|
// Orth can be set to true, to use orthogonal projection.
|
|
func NewModelRenderer(shader *Shader, camera *Camera, ortho bool) *ModelRenderer {
|
|
if shader == nil {
|
|
shader = Default3DShader
|
|
}
|
|
|
|
if camera == nil {
|
|
camera = DefaultCamera
|
|
}
|
|
|
|
renderer := &ModelRenderer{}
|
|
renderer.Shader = shader
|
|
renderer.Camera = camera
|
|
renderer.ortho = ortho
|
|
renderer.models = make([]Model, 0)
|
|
renderer.Size = Vec3{1, 1, 1}
|
|
renderer.Scale = Vec3{1, 1, 1}
|
|
|
|
CheckGLError()
|
|
|
|
return renderer
|
|
}
|
|
|
|
func (s *ModelRenderer) Cleanup() {}
|
|
|
|
// Prepares a model to be rendered by setting up its VAO.
|
|
func (s *ModelRenderer) Prepare(model *Model) {
|
|
model.Vao = NewVAO()
|
|
model.Vao.Bind()
|
|
s.Shader.EnableVertexAttribArrays()
|
|
model.Index.Bind()
|
|
model.Vertex.Bind()
|
|
model.Vertex.AttribPointer(s.Shader.GetAttribLocation(Default_shader_3D_vertex_attrib), 3, gl.FLOAT, false, 0)
|
|
model.TexCoord.Bind()
|
|
model.TexCoord.AttribPointer(s.Shader.GetAttribLocation(Default_shader_3D_texcoord_attrib), 2, gl.FLOAT, false, 0)
|
|
model.Vao.Unbind()
|
|
}
|
|
|
|
// Adds model to the renderer.
|
|
// Perpare it first!
|
|
func (s *ModelRenderer) Add(actor *Actor, pos *Pos3D, tex *Tex, mesh *Mesh) bool {
|
|
id := actor.GetId()
|
|
|
|
for _, model := range s.models {
|
|
if id == model.Actor.GetId() {
|
|
return false
|
|
}
|
|
}
|
|
|
|
s.models = append(s.models, Model{actor, pos, tex, mesh})
|
|
|
|
return true
|
|
}
|
|
|
|
// Removes model from renderer.
|
|
func (s *ModelRenderer) Remove(actor *Actor) bool {
|
|
return s.RemoveById(actor.GetId())
|
|
}
|
|
|
|
// Removes model from renderer by ID.
|
|
func (s *ModelRenderer) RemoveById(id ActorId) bool {
|
|
for i, model := range s.models {
|
|
if model.Actor.GetId() == id {
|
|
s.models = append(s.models[:i], s.models[i+1:]...)
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// Removes all sprites.
|
|
func (s *ModelRenderer) RemoveAll() {
|
|
s.models = make([]Model, 0)
|
|
}
|
|
|
|
// Returns number of sprites.
|
|
func (s *ModelRenderer) Len() int {
|
|
return len(s.models)
|
|
}
|
|
|
|
func (s *ModelRenderer) GetName() string {
|
|
return model_renderer_name
|
|
}
|
|
|
|
// Render models.
|
|
func (s *ModelRenderer) Update(delta float64) {
|
|
s.Shader.Bind()
|
|
s.Shader.SendUniform1i(Default_shader_3D_tex, 0)
|
|
|
|
if s.ortho {
|
|
s.Shader.SendMat4(Default_shader_3D_pv, *MultMat4(s.Camera.CalcOrtho3D(), s.CalcModel()))
|
|
} else {
|
|
pv := s.Camera.CalcProjection()
|
|
pv.Mult(s.Camera.CalcView())
|
|
s.Shader.SendMat4(Default_shader_3D_pv, *pv)
|
|
}
|
|
|
|
var tid uint32
|
|
|
|
for i := range s.models {
|
|
if !s.models[i].Visible {
|
|
continue
|
|
}
|
|
|
|
s.Shader.SendMat4(Default_shader_3D_model, *s.models[i].CalcModel())
|
|
s.models[i].Vao.Bind()
|
|
|
|
// prevent texture switching when not neccessary
|
|
if tid != s.models[i].Tex.GetId() {
|
|
tid = s.models[i].Tex.GetId()
|
|
s.models[i].Tex.Bind()
|
|
}
|
|
|
|
gl.DrawElements(gl.TRIANGLES, s.models[i].Index.Size(), gl.UNSIGNED_INT, nil)
|
|
}
|
|
}
|