package main // This reads obj files? import ( "bufio" "fmt" "io" "log" "math" "strings" ) type Vec3f struct { X, Y, Z float32 } type Vec2i struct { X, Y int } type Vec2f struct { X, Y float32 } type Facef [3]Vec3f type ObjModel struct { Vertices []Vec3f Faces []Facef } func (vi *Vec2i) ToF() Vec2f { return Vec2f{float32(vi.X), float32(vi.Y)} } func (vi *Vec3f) ToVec2i() Vec2i { return Vec2i{int(vi.X), int(vi.Y)} } func (v0 *Vec3f) Sub(v1 Vec3f) Vec3f { return Vec3f{ X: v0.X - v1.X, Y: v0.Y - v1.Y, Z: v0.Z - v1.Z, } } func (v0 *Vec3f) CrossProduct(v1 Vec3f) Vec3f { return Vec3f{ X: v0.Y*v1.Z - v0.Z*v1.Y, Y: v0.Z*v1.X - v0.X*v1.Z, Z: v0.X*v1.Y - v0.Y*v1.X, } } //func (v func (v *Vec3f) Normalize() Vec3f { l := float32(math.Sqrt(float64(v.MultSimp(v)))) return Vec3f{ X: v.X / l, Y: v.Y / l, Z: v.Z / l, } } func (v0 *Vec3f) MultSimp(v1 *Vec3f) float32 { return v0.X*v1.X + v0.Y*v1.Y + v0.Z*v1.Z } // Parse an obj file at the given reader. Only handles v and f right now func ParseObj(reader io.Reader) (*ObjModel, error) { result := ObjModel{ Vertices: make([]Vec3f, 0), Faces: make([]Facef, 0), } breader := bufio.NewReader(reader) done := false for !done { // Scan a line line, err := breader.ReadString('\n') if err != nil { if err == io.EOF { done = true } else { log.Printf("NOT EOF ERR?") return nil, err } } line = strings.Trim(line, " \t\n\r") if len(line) == 0 { continue } // Find the first "item", whatever that is. This also gets rid of comments // since we just don't use lines that start with # (no handler var t string _, err = fmt.Sscan(line, &t) if err != nil { log.Printf("SSCANF ERR") return nil, err } line = line[len(t):] if t == "v" { // Read a vertex, should be just three floats var vertex Vec3f _, err := fmt.Sscan(line, &vertex.X, &vertex.Y, &vertex.Z) if err != nil { return nil, err } result.Vertices = append(result.Vertices, vertex) } else if t == "f" { // Read a face; in our example, it's always three sets. // For THIS example, we throw away those other values var face Facef var vi [3]int var ti int _, err := fmt.Sscanf(line, "%d/%d/%d %d/%d/%d %d/%d/%d", &vi[0], &ti, &ti, &vi[1], &ti, &ti, &vi[2], &ti, &ti) if err != nil { return nil, err } for i := range 3 { if vi[i] > len(result.Vertices) || vi[i] < 1 { return nil, fmt.Errorf("Face vertex index out of bounds: %d", vi[i]) } face[i] = result.Vertices[vi[i]-1] } result.Faces = append(result.Faces, face) } } return &result, nil }