OBJ渲染不正确的纹理坐标

问题描述 投票:1回答:1

我在GoLang中编写了一个obj loader,正在尝试渲染一个多维数据集。多维数据集已经预先进行了三角测量,在导出之前,我已经确保在搅拌器中正确设置了UV。问题是纹理无法在多维数据集上正确呈现,我不确定是什么原因造成的。我首先按索引对纹理坐标和法线进行排序。我目前得到的是:Cube SideCube 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))
}
go opengl rendering .obj
1个回答
0
投票

结果是,当我读取人脸时,我正在对纹理坐标进行排序,而OpenGL试图根据其顶点索引来渲染UV。修复它就像对顶点排序一样简单,然后创建一个新的Indices数组,该数组从0开始到顶点的长度,因为现在所有数据都已正确排序。

© www.soinside.com 2019 - 2024. All rights reserved.