我在GoLang中编写了一个obj loader,并尝试呈现一个多维数据集。多维数据集已经预先进行了三角测量,在导出之前,我已确保在搅拌器中正确设置了UV。问题是纹理无法在多维数据集上正确呈现,我不确定是什么原因造成的。我首先按索引对纹理坐标和法线进行排序。 我目前得到的是: Cube Side Cube Front
我希望得到什么: Expected
代码 (Here's a Gist link to if that makes it)
package obj
import (
"bytes"
"fmt"
"github.com/go-gl/mathgl/mgl32"
"io"
"kami/render/models"
"kami/util"
)
func LoadModel(file string) models.Model {
objData := util.ReadAsset(file)
objReader := bytes.NewReader(objData)
modelPart := models.ModelPart{}
var x, y, z float32
var textureCoords []mgl32.Vec2
var normals []mgl32.Vec3
for {
var lineType string
_, err := fmt.Fscanf(objReader, "%s", &lineType)
if err != nil {
if err == io.EOF {
break
}
}
switch lineType {
// VERTICES.
case "v":
fmt.Fscanf(objReader, "%f %f %f\n", &x, &y, &z)
modelPart.Vertices = append(modelPart.Vertices, x, y, z)
// NORMALS.
case "vn":
fmt.Fscanf(objReader, "%f %f %f\n", &x, &y, &z)
normals = append(normals, mgl32.Vec3{x, y, z})
// TEXTURE VERTICES.
case "vt":
fmt.Fscanf(objReader, "%f %f\n", &x, &y)
textureCoords = append(textureCoords, mgl32.Vec2{x, y})
// INDICES.
case "f":
norm := make([]float32, 4)
indices := make([]float32, 4)
uv := make([]float32, 4)
matches, _ := fmt.Fscanf(objReader, "%f/%f/%f %f/%f/%f %f/%f/%f %f/%f/%f\n", &indices[0], &uv[0], &norm[0], &indices[1], &uv[1], &norm[1], &indices[2], &uv[2], &norm[2], &indices[3], &uv[3], &norm[3])
if (matches != 9 && matches != 12) || textureCoords == nil || normals == nil {
panic("Cannot read OBJ file")
}
modelPart.Indices = append(modelPart.Indices, uint32(indices[0]-1))
modelPart.Indices = append(modelPart.Indices, uint32(indices[1]-1))
modelPart.Indices = append(modelPart.Indices, uint32(indices[2]-1))
modelPart.TextureCoords = append(modelPart.TextureCoords, textureCoords[int(uv[0]) -1].X(), 1 - textureCoords[int(uv[0]) -1].Y())
modelPart.TextureCoords = append(modelPart.TextureCoords, textureCoords[int(uv[1]) -1].X(), 1 - textureCoords[int(uv[1]) -1].Y())
modelPart.TextureCoords = append(modelPart.TextureCoords, textureCoords[int(uv[2]) -1].X(), 1 - textureCoords[int(uv[2]) -1].Y())
modelPart.Normals = append(modelPart.Normals, normals[int(norm[0]) - 1].X(), normals[int(norm[0]) - 1].Y(), normals[int(norm[0]) - 1].Z())
modelPart.Normals = append(modelPart.Normals, normals[int(norm[1]) - 1].X(), normals[int(norm[1]) - 1].Y(), normals[int(norm[1]) - 1].Z())
modelPart.Normals = append(modelPart.Normals, normals[int(norm[2]) - 1].X(), normals[int(norm[2]) - 1].Y(), normals[int(norm[2]) - 1].Z())
//Triangulate if face is a Quad
if matches == 12 {
modelPart.Indices = append(modelPart.Indices, uint32(indices[0]-1), uint32(indices[2]-1), uint32(indices[3]-1))
modelPart.TextureCoords = append(modelPart.TextureCoords, textureCoords[int(uv[0]) -1].X(), 1 - textureCoords[int(uv[0]) -1].Y())
modelPart.TextureCoords = append(modelPart.TextureCoords, textureCoords[int(uv[2]) -1].X(), 1 - textureCoords[int(uv[2]) -1].Y())
modelPart.TextureCoords = append(modelPart.TextureCoords, textureCoords[int(uv[3]) -1].X(), 1 - textureCoords[int(uv[3]) -1].Y())
modelPart.Normals = append(modelPart.Normals, normals[int(norm[0]) - 1].X(), normals[int(norm[0]) - 1].Y(), normals[int(norm[0]) - 1].Z())
modelPart.Normals = append(modelPart.Normals, normals[int(norm[2]) - 1].X(), normals[int(norm[2]) - 1].Y(), normals[int(norm[2]) - 1].Z())
modelPart.Normals = append(modelPart.Normals, normals[int(norm[3]) - 1].X(), normals[int(norm[3]) - 1].Y(), normals[int(norm[3]) - 1].Z())
}
}
}
modelPart.GenerateModelVAO()
return models.Model{Parts:[]models.ModelPart{modelPart}}
}
对于实际渲染模型,我简单地绑定纹理,创建转换矩阵,绑定之前生成的VAO,然后绘制元素
gl.ActiveTexture(gl.TEXTURE0)
gl.BindTexture(gl.TEXTURE_2D, texture)
rotation := mgl32.AnglesToQuat(0, 0, 0, mgl32.XYZ)
transformMatrix := render.CreateTransformMatrix(mgl32.Vec3{0, 0, -10}, rotation, 1)
for _, element := range cubeModel.Parts {
element.Vao.Bind()
gl.UniformMatrix4fv(transformationMatrixUniform, 1, false, &transformMatrix[0])
gl.DrawElements(gl.TRIANGLES, int32(len(element.Indices)), gl.UNSIGNED_INT, gl.Ptr(element.Indices))
}
答案 0 :(得分:1)
事实证明,问题是我在读取面部时正在对纹理坐标进行排序,而OpenGL试图根据其顶点索引来渲染UV。 修复它就像对顶点进行排序一样简单,然后创建一个新的索引数组,该数组从0开始到顶点的长度,因为现在所有数据都已正确排序。