From 788399df7346eddd1e6c80393da44770bc75873b Mon Sep 17 00:00:00 2001 From: Marvin Blum Date: Thu, 5 May 2016 00:00:00 +0200 Subject: [PATCH] Moved all into one package, added png loader. --- ToDo.md | 4 +++ gl/drop.go => drop.go | 2 +- gl/fbo.go => fbo.go | 2 +- game.go | 21 ++++++++++++- loader.go | 58 ++++++++++++++++++++++++++++++++++++ geo/mat3.go => mat3.go | 2 +- geo/mat4.go => mat4.go | 2 +- res.go | 61 +++++++++++++++++++------------------- gl/shader.go => shader.go | 7 ++--- test/gopher.png | Bin 0 -> 41276 bytes gl/tex.go => tex.go | 46 +++++++++++++++++++++++----- gl/types.go => types.go | 2 +- geo/util.go => util.go | 2 +- gl/vao.go => vao.go | 2 +- gl/vbo.go => vbo.go | 2 +- geo/vec2.go => vec2.go | 2 +- geo/vec3.go => vec3.go | 2 +- geo/vec4.go => vec4.go | 2 +- 18 files changed, 165 insertions(+), 54 deletions(-) create mode 100644 ToDo.md rename gl/drop.go => drop.go (95%) rename gl/fbo.go => fbo.go (99%) create mode 100644 loader.go rename geo/mat3.go => mat3.go (99%) rename geo/mat4.go => mat4.go (99%) rename gl/shader.go => shader.go (98%) create mode 100644 test/gopher.png rename gl/tex.go => tex.go (78%) rename gl/types.go => types.go (70%) rename geo/util.go => util.go (97%) rename gl/vao.go => vao.go (97%) rename gl/vbo.go => vbo.go (99%) rename geo/vec2.go => vec2.go (98%) rename geo/vec3.go => vec3.go (99%) rename geo/vec4.go => vec4.go (99%) diff --git a/ToDo.md b/ToDo.md new file mode 100644 index 0000000..9db4b59 --- /dev/null +++ b/ToDo.md @@ -0,0 +1,4 @@ +# ToDo + +* cleanup resources +* more logging diff --git a/gl/drop.go b/drop.go similarity index 95% rename from gl/drop.go rename to drop.go index 6e9d6a3..345b3cf 100644 --- a/gl/drop.go +++ b/drop.go @@ -1,4 +1,4 @@ -package gl +package goga // The dropable interface is used to clean up GL objects. // Use the Drop() function to drop a range of objects. diff --git a/gl/fbo.go b/fbo.go similarity index 99% rename from gl/fbo.go rename to fbo.go index 527e183..07c76c7 100644 --- a/gl/fbo.go +++ b/fbo.go @@ -1,4 +1,4 @@ -package gl +package goga import ( "github.com/go-gl/gl/v4.5-core/gl" diff --git a/game.go b/game.go index 1b4a127..7615ec3 100644 --- a/game.go +++ b/game.go @@ -1,7 +1,9 @@ package goga import ( + "github.com/go-gl/gl/v4.5-core/gl" "github.com/go-gl/glfw/v3.1/glfw" + "log" "math" "time" ) @@ -35,6 +37,8 @@ var ( // This function will panic on error. func Run(game Game, options *RunOptions) { // init glfw + log.Print("Initializing GLFW") + if err := glfw.Init(); err != nil { panic("Error initializing GLFW: " + err.Error()) } @@ -42,6 +46,7 @@ func Run(game Game, options *RunOptions) { defer glfw.Terminate() // create window + log.Print("Creating window") width := default_width height := default_height title := default_title @@ -60,8 +65,13 @@ func Run(game Game, options *RunOptions) { panic("Error creating GLFW window: " + err.Error()) } - // start and loop + // init go-game + log.Print("Initializing goga") wnd.MakeContextCurrent() + initGoga() + + // start and loop + log.Print("Starting main loop") delta := time.Duration(0) var deltaSec float64 @@ -86,16 +96,25 @@ func Run(game Game, options *RunOptions) { // Stops the game and closes the window. func Stop() { + log.Print("Stopping main loop") running = false } +func initGoga() { + AddLoader(&PngLoader{gl.LINEAR, false}) +} + func cleanup() { // cleanup scenes + log.Print("Cleaning up scenes") + for _, scene := range scenes { scene.Cleanup() } // cleanup systems + log.Print("Cleaning up systems") + for _, system := range systems { system.Cleanup() } diff --git a/loader.go b/loader.go new file mode 100644 index 0000000..b1ba7ce --- /dev/null +++ b/loader.go @@ -0,0 +1,58 @@ +package goga + +import ( + "github.com/go-gl/gl/v4.5-core/gl" + "image" + "image/draw" + "image/png" + "os" +) + +// Loads textures from png files. +// If keepData is set to true, +// pixel data will be stored inside the texture +// (additionally to VRAM). +type PngLoader struct { + Filter int32 + KeepData bool +} + +func (p *PngLoader) Load(file string) (Res, error) { + // load texture + imgFile, err := os.Open(file) + + if err != nil { + return nil, err + } + + img, err := png.Decode(imgFile) + + if err != nil { + return nil, err + } + + rgba := image.NewRGBA(img.Bounds()) + draw.Draw(rgba, rgba.Bounds(), img, image.Point{0, 0}, draw.Src) + + // create GL texture + tex := NewTex(gl.TEXTURE_2D) + tex.Bind() + tex.SetDefaultParams(p.Filter) + tex.Texture2D(0, + gl.RGBA, + int32(rgba.Rect.Size().X), + int32(rgba.Rect.Size().Y), + gl.RGBA, + gl.UNSIGNED_BYTE, + rgba.Pix) + + if p.KeepData { + tex.SetRGBA(rgba) + } + + return tex, nil +} + +func (p *PngLoader) Ext() string { + return "png" +} diff --git a/geo/mat3.go b/mat3.go similarity index 99% rename from geo/mat3.go rename to mat3.go index 0e7080c..300803b 100644 --- a/geo/mat3.go +++ b/mat3.go @@ -1,4 +1,4 @@ -package geo +package goga import ( "math" diff --git a/geo/mat4.go b/mat4.go similarity index 99% rename from geo/mat4.go rename to mat4.go index ab66255..aa5263f 100644 --- a/geo/mat4.go +++ b/mat4.go @@ -1,4 +1,4 @@ -package geo +package goga import ( "math" diff --git a/res.go b/res.go index e79059e..9adee5a 100644 --- a/res.go +++ b/res.go @@ -10,38 +10,26 @@ import ( // A generic resource. // Must be cast to appropriate type. // The name is the file name and must be unique. -type Res struct { - name string - path string - ext string -} - -// Returns the file name of actual resource. -func (r *Res) GetName() string { - return r.name -} - -// Returns the file path (as passed in) of actual resource. -func (r *Res) GetPath() string { - return r.path -} - -// Returns the file extension of actual resource. -func (r *Res) GetExt() string { - return r.ext +type Res interface { + GetName() string + SetName(string) + GetPath() string + SetPath(string) + GetExt() string + SetExt(string) } // Resource loader interface. // The loader accepts files by file extension. // and loads them if accepted. type ResLoader interface { - Load(string) (*Res, error) + Load(string) (Res, error) Ext() string } var ( resloader []ResLoader - resources []*Res + resources []Res ) // Adds a loader. @@ -110,8 +98,15 @@ func GetLoaderByExt(ext string) ResLoader { // Loads a resource by file path. // If no loader is present for given file, an error will be returned. // If the loader fails to load the resource, an error will be returned. -func LoadRes(path string) (*Res, error) { +// If the resource name exists already, an error AND the resource will be returned. +// This is allows to cleanup on failure. +func LoadRes(path string) (Res, error) { ext := filepath.Ext(path) + + if len(ext) > 0 { + ext = ext[1:] + } + loader := GetLoaderByExt(ext) if loader == nil { @@ -124,9 +119,13 @@ func LoadRes(path string) (*Res, error) { return nil, err } + res.SetName(filepath.Base(path)) + res.SetPath(path) + res.SetExt(ext) + for _, r := range resources { - if r.name == res.name { - return nil, errors.New("Resource with file name " + res.name + " exists already") + if r.GetName() == res.GetName() { + return res, errors.New("Resource with file name " + res.GetName() + " exists already") } } @@ -159,9 +158,9 @@ func LoadResFromFolder(path string) error { } // Returns a resource by name or nil, if not found. -func GetResByName(name string) *Res { +func GetResByName(name string) Res { for _, r := range resources { - if r.name == name { + if r.GetName() == name { return r } } @@ -170,9 +169,9 @@ func GetResByName(name string) *Res { } // Returns a resource by path or nil, if not found. -func GetResByPath(path string) *Res { +func GetResByPath(path string) Res { for _, r := range resources { - if r.path == path { + if r.GetPath() == path { return r } } @@ -184,7 +183,7 @@ func GetResByPath(path string) *Res { // Returns false if resource could not be found. func RemoveResByName(name string) bool { for i, r := range resources { - if r.name == name { + if r.GetName() == name { resources = append(resources[:i], resources[i+1:]...) return true } @@ -197,7 +196,7 @@ func RemoveResByName(name string) bool { // Returns false if resource could not be found. func RemoveResByPath(path string) bool { for i, r := range resources { - if r.path == path { + if r.GetPath() == path { resources = append(resources[:i], resources[i+1:]...) return true } @@ -208,5 +207,5 @@ func RemoveResByPath(path string) bool { // Removes all resources. func RemoveAllRes() { - resources = make([]*Res, 0) + resources = make([]Res, 0) } diff --git a/gl/shader.go b/shader.go similarity index 98% rename from gl/shader.go rename to shader.go index beefae2..b6e21c6 100644 --- a/gl/shader.go +++ b/shader.go @@ -1,8 +1,7 @@ -package gl +package goga import ( "errors" - "geo" "github.com/go-gl/gl/v4.5-core/gl" "strings" ) @@ -277,7 +276,7 @@ func (s *Shader) SendUniform4x3(name string, data *float32, count int32, transpo gl.UniformMatrix4x3fv(s.GetUniformLocation(name), count, transpose, data) } -func (s *Shader) SendMat3(name string, m geo.Mat3) { +func (s *Shader) SendMat3(name string, m Mat3) { var data [9]float32 for i := 0; i < 9; i++ { @@ -287,7 +286,7 @@ func (s *Shader) SendMat3(name string, m geo.Mat3) { gl.UniformMatrix3fv(s.GetUniformLocation(name), 1, false, &data[0]) } -func (s *Shader) SendMat4(name string, m geo.Mat4) { +func (s *Shader) SendMat4(name string, m Mat4) { var data [16]float32 for i := 0; i < 16; i++ { diff --git a/test/gopher.png b/test/gopher.png new file mode 100644 index 0000000000000000000000000000000000000000..cb5e2e19f150d8b131819b069bbfa40b86e458dc GIT binary patch literal 41276 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 IM6N<$g3C<*5&!@I literal 0 HcmV?d00001 diff --git a/gl/tex.go b/tex.go similarity index 78% rename from gl/tex.go rename to tex.go index 30ff61d..4e82f5c 100644 --- a/gl/tex.go +++ b/tex.go @@ -1,17 +1,19 @@ -package gl +package goga import ( - "geo" "github.com/go-gl/gl/v4.5-core/gl" "image" ) // Texture object. type Tex struct { + name string + path string + ext string id uint32 target uint32 activeTexture uint32 - size geo.Vec3 + size Vec3 rgba *image.RGBA // optional, most of the time nil } @@ -30,6 +32,36 @@ func (t *Tex) Drop() { gl.DeleteBuffers(1, &t.id) } +// Returns the name of this resource. +func (t *Tex) GetName() string { + return t.name +} + +// Sets the name of this resource. +func (t *Tex) SetName(name string) { + t.name = name +} + +// Returns the path of this resource. +func (t *Tex) GetPath() string { + return t.path +} + +// Sets the path of this resource. +func (t *Tex) SetPath(path string) { + t.path = path +} + +// Returns the file extension of this resource. +func (t *Tex) GetExt() string { + return t.ext +} + +// Sets the file extension of this resource. +func (t *Tex) SetExt(ext string) { + t.ext = ext +} + // Binds the texture for rendering. func (t *Tex) Bind() { gl.ActiveTexture(t.activeTexture) @@ -51,7 +83,7 @@ func (t *Tex) SetDefaultParams(filter int32) { // Creates a new 1D texture. func (t *Tex) Texture1D(level, internalFormat, width int32, format, ttype uint32, data []uint8) { - t.size = geo.Vec3{float64(width), 0, 0} + t.size = Vec3{float64(width), 0, 0} t.Bind() if data != nil { @@ -63,7 +95,7 @@ func (t *Tex) Texture1D(level, internalFormat, width int32, format, ttype uint32 // Creates a new 2D texture. func (t *Tex) Texture2D(level, internalFormat, width, height int32, format, ttype uint32, data []uint8) { - t.size = geo.Vec3{float64(width), float64(height), 0} + t.size = Vec3{float64(width), float64(height), 0} t.Bind() if data != nil { @@ -75,7 +107,7 @@ func (t *Tex) Texture2D(level, internalFormat, width, height int32, format, ttyp // Creates a new 3D texture. func (t *Tex) Texture3D(level, internalFormat, width, height, depth int32, format, ttype uint32, data []uint8) { - t.size = geo.Vec3{float64(width), float64(height), float64(depth)} + t.size = Vec3{float64(width), float64(height), float64(depth)} t.Bind() if data != nil { @@ -122,7 +154,7 @@ func (t *Tex) getActiveTexture() uint32 { } // Returns the size of this texture. -func (t *Tex) GetSize() geo.Vec3 { +func (t *Tex) GetSize() Vec3 { return t.size } diff --git a/gl/types.go b/types.go similarity index 70% rename from gl/types.go rename to types.go index 4452c0a..8677d6d 100644 --- a/gl/types.go +++ b/types.go @@ -1,3 +1,3 @@ -package gl +package goga const NullTerminator = "\x00" diff --git a/geo/util.go b/util.go similarity index 97% rename from geo/util.go rename to util.go index 826eae9..fa9a18d 100644 --- a/geo/util.go +++ b/util.go @@ -1,4 +1,4 @@ -package geo +package goga import ( "math" diff --git a/gl/vao.go b/vao.go similarity index 97% rename from gl/vao.go rename to vao.go index 49fde63..92995af 100644 --- a/gl/vao.go +++ b/vao.go @@ -1,4 +1,4 @@ -package gl +package goga import ( "github.com/go-gl/gl/v4.5-core/gl" diff --git a/gl/vbo.go b/vbo.go similarity index 99% rename from gl/vbo.go rename to vbo.go index 6bb4c92..1445ec2 100644 --- a/gl/vbo.go +++ b/vbo.go @@ -1,4 +1,4 @@ -package gl +package goga import ( "github.com/go-gl/gl/v4.5-core/gl" diff --git a/geo/vec2.go b/vec2.go similarity index 98% rename from geo/vec2.go rename to vec2.go index 13fa064..a94be5a 100644 --- a/geo/vec2.go +++ b/vec2.go @@ -1,4 +1,4 @@ -package geo +package goga import ( "math" diff --git a/geo/vec3.go b/vec3.go similarity index 99% rename from geo/vec3.go rename to vec3.go index f925da6..ea51831 100644 --- a/geo/vec3.go +++ b/vec3.go @@ -1,4 +1,4 @@ -package geo +package goga import ( "math" diff --git a/geo/vec4.go b/vec4.go similarity index 99% rename from geo/vec4.go rename to vec4.go index c5a027d..7980fb1 100644 --- a/geo/vec4.go +++ b/vec4.go @@ -1,4 +1,4 @@ -package geo +package goga import ( "math"