Kaynağa Gözat

Added package logger and obj format decoding fixes

Parse the group name command ("g") the sames as object name ("o").
Consider the cases when the face indexes are negative.
Uses the last defined material for objects/groups that don't define a
material.
leonsal 8 yıl önce
ebeveyn
işleme
8fcc04524f
2 değiştirilmiş dosya ile 70 ekleme ve 12 silme
  1. 12 0
      loader/obj/logger.go
  2. 58 12
      loader/obj/obj.go

+ 12 - 0
loader/obj/logger.go

@@ -0,0 +1,12 @@
+// Copyright 2016 The G3N Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package obj
+
+import (
+	"github.com/g3n/engine/util/logger"
+)
+
+// Package logger
+var log = logger.New("OBJ", logger.Default)

+ 58 - 12
loader/obj/obj.go

@@ -289,20 +289,32 @@ func (dec *Decoder) parseObjLine(line string) error {
 		return nil
 	}
 	switch ltype {
+	// Material library
 	case "mtllib":
 		return dec.parseMatlib(fields[1:])
+	// Object name
 	case "o":
 		return dec.parseObject(fields[1:])
+	// Group names. We are considering "group" the same as "object"
+	// This may not be right
+	case "g":
+		return dec.parseObject(fields[1:])
+	// Vertex coordinate
 	case "v":
 		return dec.parseVertex(fields[1:])
+	// Vertex normal coordinate
 	case "vn":
 		return dec.parseNormal(fields[1:])
+	// Vertex texture coordinate
 	case "vt":
 		return dec.parseTex(fields[1:])
+	// Face vertex
 	case "f":
 		return dec.parseFace(fields[1:])
+	// Use material
 	case "usemtl":
 		return dec.parseUsemtl(fields[1:])
+	// Smooth
 	case "s":
 		return dec.parseSmooth(fields[1:])
 	default:
@@ -393,6 +405,11 @@ func (dec *Decoder) parseTex(fields []string) error {
 // f v1[/vt1][/vn1] v2[/vt2][/vn2] v3[/vt3][/vn3] ...
 func (dec *Decoder) parseFace(fields []string) error {
 
+	// If current object has no material, appends last material if defined
+	if len(dec.objCurrent.materials) == 0 && dec.matCurrent != nil {
+		dec.objCurrent.materials = append(dec.objCurrent.materials, dec.matCurrent.Name)
+	}
+
 	if len(fields) < 3 {
 		return dec.formatError("Face line with less 3 fields")
 	}
@@ -405,44 +422,73 @@ func (dec *Decoder) parseFace(fields []string) error {
 	face.Normals = make([]int, len(fields))
 	face.Material = dec.matCurrent.Name
 	face.Smooth = dec.smoothCurrent
+
 	for pos, f := range fields {
+
 		// Separate the current field in its components: v vt vn
 		vfields := strings.Split(f, "/")
 		if len(vfields) < 1 {
 			return dec.formatError("Face field with no parts")
 		}
+
 		// Get the index of this vertex position (must always exist)
-		val, err := strconv.ParseUint(vfields[0], 10, 32)
+		val, err := strconv.ParseInt(vfields[0], 10, 32)
 		if err != nil {
 			return err
 		}
-		if val < 1 {
-			return dec.formatError("Face vertex position index value less than 1")
+
+		// Positive index is an absolute vertex index
+		if val > 0 {
+			face.Vertices[pos] = int(val - 1)
+			// Negative vertex index is relative to the last parsed vertex
+		} else if val < 0 {
+			current := (len(dec.Vertices) / 3) - 1
+			face.Vertices[pos] = current + int(val) + 1
+			// Vertex index could never be 0
+		} else {
+			return dec.formatError("Face vertex index value equal to 0")
 		}
-		face.Vertices[pos] = int(val - 1)
+
 		// Get the index of this vertex UV coordinate (optional)
 		if len(vfields) > 1 && len(vfields[1]) > 0 {
-			val, err := strconv.ParseUint(vfields[1], 10, 32)
+			val, err := strconv.ParseInt(vfields[1], 10, 32)
 			if err != nil {
 				return err
 			}
-			if val < 1 {
-				return dec.formatError("Face uv index value less than 1")
+
+			// Positive index is an absolute UV index
+			if val > 0 {
+				face.Uvs[pos] = int(val - 1)
+				// Negative vertex index is relative to the last parsed uv
+			} else if val < 0 {
+				current := (len(dec.Uvs) / 2) - 1
+				face.Uvs[pos] = current + int(val) + 1
+				// UV index could never be 0
+			} else {
+				return dec.formatError("Face uv index value equal to 0")
 			}
-			face.Uvs[pos] = int(val - 1)
 		} else {
 			face.Uvs[pos] = invINDEX
 		}
+
 		// Get the index of this vertex normal (optional)
 		if len(vfields) >= 3 {
-			val, err = strconv.ParseUint(vfields[2], 10, 32)
+			val, err = strconv.ParseInt(vfields[2], 10, 32)
 			if err != nil {
 				return err
 			}
-			if val < 1 {
-				return dec.formatError("Face normal index value less than 1")
+
+			// Positive index is an absolute normal index
+			if val > 0 {
+				face.Normals[pos] = int(val - 1)
+				// Negative vertex index is relative to the last parsed normal
+			} else if val < 0 {
+				current := (len(dec.Normals) / 3) - 1
+				face.Normals[pos] = current + int(val) + 1
+				// Normal index could never be 0
+			} else {
+				return dec.formatError("Face normal index value equal to 0")
 			}
-			face.Normals[pos] = int(val - 1)
 		} else {
 			face.Normals[pos] = invINDEX
 		}