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
 | 
						|
}
 |