移位uv坐标

时间:2018-01-14 19:50:58

标签: c++ blender directx-11

我正在尝试为我的游戏引擎创建一个模型加载器,它接受一个.obj目标文件(来自blender)并将其转换为带索引和顶点的模型,但是uv坐标似乎已经移位且非常不正确。

以下是模型加载器的代码:

bool RawModel::LoadModel(std::string fileName)
{

    m_name = fileName;

    int pos = m_name.find_last_of("\\");
    if (pos >= 0)
    {
        m_name = m_name.substr(pos + 1, m_name.length());
    }

    //Load vertices:

    m_vertices.clear();
    m_indices.clear();

    std::ifstream objFile(fileName);
    if (!objFile.is_open())
    {
        std::cout << "Could not open file: " << fileName << std::endl;
        return false;
    }

    std::string currentLine;

    std::vector<Vector3> vertices;
    std::vector<Vector2> uvs;
    std::vector<Vector3> normals;

    while (objFile.good())
    {
        std::getline(objFile, currentLine);
        if (currentLine.find("v ") != std::string::npos) //Vertex
        {
            std::stringstream streamedLine(currentLine);
            float x, y, z;
            std::string temps;
            streamedLine >> temps;
            streamedLine >> x;
            streamedLine >> y;
            streamedLine >> z;
            vertices.push_back(Vector3(x, y, z));
        }
        else if (currentLine.find("vt ") != std::string::npos) //Uv
        {
            std::stringstream streamedLine(currentLine);
            float x, y;
            std::string temps;
            streamedLine >> temps;
            streamedLine >> x;
            streamedLine >> y;
            uvs.push_back(Vector2(x, 1-y)); //-y because top is 0y not 1y as in normal coordinate space
        }
        else if (currentLine.find("vn ") != std::string::npos) //Normal
        {
            std::stringstream streamedLine(currentLine);
            float x, y, z;
            std::string temps;
            streamedLine >> temps;
            streamedLine >> x;
            streamedLine >> y;
            streamedLine >> z;
            vertices.push_back(Vector3(x, y, z));
        }
        else if (currentLine.find("f ") != std::string::npos)
        {
            m_vertices.resize(vertices.size());

            std::stringstream streamedLine(currentLine);
            std::string segment;
            streamedLine >> segment;
            std::vector<std::string> indices;

            indices.reserve(3);

            //getting the triangulated face to a array
            while (streamedLine >> segment)
                indices.push_back(segment);

            for (int i = 0; i < indices.size(); i++) //Loop all indices in the face
            {
                std::stringstream streamedIndex(indices[i]);
                std::vector<int> vertex;//0 = vertexPos, 1 = uv, 2 = normal
                indices.reserve(3);

                while (std::getline(streamedIndex, segment, '/')) //x3
                {
                    vertex.push_back(stoi(segment)-1);
                }
                m_vertices[vertex[0]] = VertexType(vertices[vertex[0]], uvs[vertex[1]]);
                m_indices.emplace_back(vertex[0]);

            }

        }
    }
    return true;
}

VertexType是一个结构,它是顶点的结构。顶点是建立起来的,定义如下:

struct VertexType
{
    D3DXVECTOR3 position;
    D3DXVECTOR2 uv;
    D3DXVECTOR3 normal;
    VertexType() : position(0, 0, 0), uv(0, 0) {};
    VertexType(D3DXVECTOR3 position, D3DXVECTOR2 uv, D3DXVECTOR3 normal) :position(position), uv(uv), normal(normal) {};
    VertexType(Vector3 position, Vector2 uv) :position(position.D3DXVECTOR()), uv(uv.D3DXVECTOR()) {};
};

这是正常工作时的样子

BlenderPreview

这就是它在我的游戏引擎中的样子:

Game engine

我怀疑模型的错误,因为它在统一和混合器中使用相同的纹理(绿色和红色在uv坐标之外,根据uv布局,透明部分通常应该是绿色和红色的轻松。)(纹理底部为红色,顶部为绿色)

这是两种情况下使用的纹理。 The used texture in both cases

1 个答案:

答案 0 :(得分:0)

加载OBJ文件后,我记得这个问题。我在C#中的修复,我相信你可以在这里申请。

vp.SetTextureUV(result.Textures[TextureIndex].X, -result.Textures[TextureIndex].Y);

当您设置UV的V分量时,我不得不在格式中出于某种原因否定该值,以使其与我的纹理一起使用。我希望这也能解决你的问题。从截图中,我认为它会。

您可以在Y轴上翻转纹理,这也应该可以解决问题。