package objloader import ( "os" "zworld/library/zos" "zworld/plugin/math/vec3" ) type FByteView = zos.FByteView type FVertex struct { pos int32 nor int32 tex int32 } type FMesh struct { Positions []vec3.T Normals []vec3.T TexCoords []vec3.T Faces [][]FVertex Indices []uint16 } type FObjLoader struct { reader *zos.FReader mesh *FMesh } func (l *FObjLoader) GetTexCoord(bv *FByteView) error { x := bv.GetFloat() y := bv.GetFloat() if err := bv.Err(); err != nil { return err } w := bv.GetFloat() if bv.Err() != nil { w = 0 } v := vec3.T{X: x, Y: y, Z: w} l.mesh.TexCoords = append(l.mesh.TexCoords, v) return nil } func (l *FObjLoader) GetPosition(bv *FByteView) error { x := bv.GetFloat() y := bv.GetFloat() z := bv.GetFloat() if err := bv.Err(); err != nil { return err } v := vec3.T{X: x, Y: y, Z: z} l.mesh.Positions = append(l.mesh.Positions, v) return nil } func (l *FObjLoader) GetNormal(bv *FByteView) error { x := bv.GetFloat() y := bv.GetFloat() z := bv.GetFloat() if err := bv.Err(); err != nil { return err } v := vec3.T{X: x, Y: y, Z: z} l.mesh.Normals = append(l.mesh.Normals, v) return nil } func (l *FObjLoader) GetFace(b *FByteView) error { var faces []FVertex for i := 0; i < 3; i++ { line := b.GetToken() bv := zos.NewByteView(line) bv.SetSign('/') v := FVertex{} v.pos = bv.GetInt() if err := bv.Err(); err != nil { return err } v.nor = bv.GetInt() v.tex = bv.GetInt() faces = append(faces, v) } l.mesh.Faces = append(l.mesh.Faces, faces) return nil } func (l *FObjLoader) Parse() error { for line, err := l.reader.ReadLine(); err == nil; line, err = l.reader.ReadLine() { bv := zos.NewByteView(line) bv.SkipWhitespace() token := string(bv.ReadTokenBySpace()) //zlog.Infof("line {}", string(line)) switch token { case "v": err = l.GetPosition(bv) case "vt": err = l.GetTexCoord(bv) case "vn": err = l.GetNormal(bv) case "f": err = l.GetFace(bv) } if err != nil { return err } } return nil } func LoadObj(filename string) (err error, mesh *FMesh) { file, err := os.Open(filename) if err != nil { return err, nil } l := &FObjLoader{reader: zos.NewReader(file), mesh: &FMesh{}} err = l.Parse() return err, l.mesh }