tofu

Making something with OpenGL in Go
Log | Files | Refs

commit a2419b804ccf86a284bda8279f5be739d549db78
parent 7ee1a21d4944ed1d8810757b52d8bc3b1611859e
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Sat, 16 Nov 2024 17:52:01 +0900

load obj file

Diffstat:
Mcmd/sample/main.go | 17++++++++++++++++-
Mobject.go | 94+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 108 insertions(+), 3 deletions(-)

diff --git a/cmd/sample/main.go b/cmd/sample/main.go @@ -3,6 +3,7 @@ package main import ( "log" "math" + "os" "path/filepath" "runtime" "time" @@ -75,7 +76,9 @@ func watchCursor(app *App) { } } -var object = tofu.Object{ +var teapot *tofu.Object + +var object = &tofu.Object{ Vertices: []tofu.Vec3{ tofu.Vec3{0.5, 0.5, -0.5}, tofu.Vec3{0.5, -0.5, -0.5}, @@ -192,6 +195,7 @@ func (app *App) Update() error { app.program.SetMat4("model", model) object.Draw() } + teapot.Draw() app.lightProgram.Use() app.program.SetMat4("view", view) @@ -228,6 +232,17 @@ func main() { lightFpath := filepath.Join(filepath.Dir(f), "light_fragment.glsl") texturePath := filepath.Join(filepath.Dir(f), "container2.png") specularMapPath := filepath.Join(filepath.Dir(f), "container2_specular.png") + teapotPath := filepath.Join(filepath.Dir(f), "teapot.obj") + + tf, err := os.Open(teapotPath) + if err != nil { + log.Fatal(err) + } + teapot, err = tofu.DecodeObject(tf) + if err != nil { + log.Fatal(err) + } + teapot.Load() app.program, err = tofu.NewProgram(vpath, fpath) if err != nil { diff --git a/object.go b/object.go @@ -1,21 +1,109 @@ package tofu import ( - "image/color" + "fmt" + "io" + "log" "math" + "strconv" + "text/scanner" "github.com/go-gl/gl/v3.3-core/gl" ) type Object struct { Vertices []Vec3 - Colors []color.Color TexCoords []Vec2 Normals []Vec3 Faces []Face vao *VAO } +func DecodeObject(r io.Reader) (*Object, error) { + obj := new(Object) + s := new(scanner.Scanner) + s.Init(r) + for { + t := s.Scan() + if t == scanner.EOF { + break + } + if t != scanner.Ident { + log.Println(t) + return nil, fmt.Errorf("unwanted token: %s, want Ident", s.TokenText()) + } + switch ident := s.TokenText(); ident { + case "v": + if err := obj.addVertex(s); err != nil { + return nil, err + } + case "f": + if err := obj.addFace(s); err != nil { + return nil, err + } + default: + log.Println("ident %s not implemented. ignoring.", ident) + } + } + return obj, nil +} + +func (obj *Object) addVertex(s *scanner.Scanner) error { + var v Vec3 + for i := 0; i < 3; i++ { + t := s.Scan() + switch t { + case scanner.Float, scanner.Int, '-': + sign := float32(1) + if t == '-' { + sign = -1 + t = s.Scan() + if t != scanner.Float && t != scanner.Int { + return fmt.Errorf("unwanted token %q of type %d. want vertex coordinate.", s.TokenText(), t) + } + } + x, err := strconv.ParseFloat(s.TokenText(), 64) + if err != nil { + return fmt.Errorf("parseFloat: %v", err) + } + v[i] = float32(x) * sign + default: + return fmt.Errorf("unwanted token %q of type %d. want vertex coordinate.", s.TokenText(), t) + } + } + obj.Vertices = append(obj.Vertices, v) + return nil +} + +func (obj *Object) addFace(s *scanner.Scanner) error { + var f Face + for i := 0; i < 3; i++ { + t := s.Scan() + switch t { + case scanner.Int, '-': + sign := int(1) + if t == '-' { + sign = -1 + t = s.Scan() + if t != scanner.Int { + return fmt.Errorf("unwanted token %q of type %d. face index", s.TokenText(), t) + } + } + x, err := strconv.Atoi(s.TokenText()) + if err != nil { + return fmt.Errorf("Atoi: %v", err) + } + f.I[i].V = x*sign - 1 + f.I[i].N = NoIndex + f.I[i].T = NoIndex + default: + return fmt.Errorf("unwanted token %q of type %d. want face index.", s.TokenText(), t) + } + } + obj.Faces = append(obj.Faces, f) + return nil +} + var NoIndex = math.MinInt type VertexIndex struct { @@ -85,6 +173,8 @@ func (obj *Object) Load() { } func (obj *Object) Draw() { + // TODO: performance? + obj.vao.bind() gl.DrawElements(gl.TRIANGLES, int32(obj.stride()*3*len(obj.Faces)), gl.UNSIGNED_INT, nil)