112 lines
2.2 KiB
Go
112 lines
2.2 KiB
Go
|
|
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
|
||
|
|
}
|