Sfoglia il codice sorgente

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 anni fa
parent
commit
8fcc04524f
2 ha cambiato i file con 70 aggiunte e 12 eliminazioni
  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
 		return nil
 	}
 	}
 	switch ltype {
 	switch ltype {
+	// Material library
 	case "mtllib":
 	case "mtllib":
 		return dec.parseMatlib(fields[1:])
 		return dec.parseMatlib(fields[1:])
+	// Object name
 	case "o":
 	case "o":
 		return dec.parseObject(fields[1:])
 		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":
 	case "v":
 		return dec.parseVertex(fields[1:])
 		return dec.parseVertex(fields[1:])
+	// Vertex normal coordinate
 	case "vn":
 	case "vn":
 		return dec.parseNormal(fields[1:])
 		return dec.parseNormal(fields[1:])
+	// Vertex texture coordinate
 	case "vt":
 	case "vt":
 		return dec.parseTex(fields[1:])
 		return dec.parseTex(fields[1:])
+	// Face vertex
 	case "f":
 	case "f":
 		return dec.parseFace(fields[1:])
 		return dec.parseFace(fields[1:])
+	// Use material
 	case "usemtl":
 	case "usemtl":
 		return dec.parseUsemtl(fields[1:])
 		return dec.parseUsemtl(fields[1:])
+	// Smooth
 	case "s":
 	case "s":
 		return dec.parseSmooth(fields[1:])
 		return dec.parseSmooth(fields[1:])
 	default:
 	default:
@@ -393,6 +405,11 @@ func (dec *Decoder) parseTex(fields []string) error {
 // f v1[/vt1][/vn1] v2[/vt2][/vn2] v3[/vt3][/vn3] ...
 // f v1[/vt1][/vn1] v2[/vt2][/vn2] v3[/vt3][/vn3] ...
 func (dec *Decoder) parseFace(fields []string) error {
 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 {
 	if len(fields) < 3 {
 		return dec.formatError("Face line with less 3 fields")
 		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.Normals = make([]int, len(fields))
 	face.Material = dec.matCurrent.Name
 	face.Material = dec.matCurrent.Name
 	face.Smooth = dec.smoothCurrent
 	face.Smooth = dec.smoothCurrent
+
 	for pos, f := range fields {
 	for pos, f := range fields {
+
 		// Separate the current field in its components: v vt vn
 		// Separate the current field in its components: v vt vn
 		vfields := strings.Split(f, "/")
 		vfields := strings.Split(f, "/")
 		if len(vfields) < 1 {
 		if len(vfields) < 1 {
 			return dec.formatError("Face field with no parts")
 			return dec.formatError("Face field with no parts")
 		}
 		}
+
 		// Get the index of this vertex position (must always exist)
 		// 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 {
 		if err != nil {
 			return err
 			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)
 		// Get the index of this vertex UV coordinate (optional)
 		if len(vfields) > 1 && len(vfields[1]) > 0 {
 		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 {
 			if err != nil {
 				return err
 				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 {
 		} else {
 			face.Uvs[pos] = invINDEX
 			face.Uvs[pos] = invINDEX
 		}
 		}
+
 		// Get the index of this vertex normal (optional)
 		// Get the index of this vertex normal (optional)
 		if len(vfields) >= 3 {
 		if len(vfields) >= 3 {
-			val, err = strconv.ParseUint(vfields[2], 10, 32)
+			val, err = strconv.ParseInt(vfields[2], 10, 32)
 			if err != nil {
 			if err != nil {
 				return err
 				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 {
 		} else {
 			face.Normals[pos] = invINDEX
 			face.Normals[pos] = invINDEX
 		}
 		}