gpt4 book ai didi

c++ - 从Assimp加载Collada(dae)模型显示不正确的法线

转载 作者:行者123 更新时间:2023-12-02 10:21:52 25 4
gpt4 key购买 nike

解决方案:

感谢Rabbid76,我需要使用模型矩阵更新顶点着色器中的Normal vector 。更新了顶点着色器:

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;

out vec3 FragPos;
out vec3 Normal;

uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;

uniform float scale;

void main()
{
FragPos = vec3(model * vec4(aPos, 1.0));
Normal = vec3(model * vec4(aNormal, 0.0));
gl_Position = projection * view * vec4(FragPos, 1.0);
}

enter image description here

问题

我试图在Assimp中正确加载collada(dae)文件,但法线似乎出了错。我想帮助您解决这个问题。我感觉这与我处理转换矩阵的方式有关。例如,这是加载obj文件的OpenGL应用程序的屏幕截图:

enter image description here

在上面的屏幕截图中,灯光位于x = 0和z = 0处的模型正上方。法线显示正确。加载dae文件时,得到以下信息:

enter image description here

轻的位置似乎来自-z一侧。

这是我当前必须加载模型的代码:
  • 加载模型文件,并调用包括processNode()aiMatrix4x4()方法
  • void Model::loadModel(std::string filename)
    {
    Assimp::Importer importer;
    const aiScene *scene = importer.ReadFile(filename, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace | aiProcess_GenBoundingBoxes);

    if (!scene || !scene->mRootNode) {
    std::cout << "ERROR::ASSIMP Could not load model: " << importer.GetErrorString() << std::endl;
    }
    else {
    this->directory = filename.substr(0, filename.find_last_of('/'));

    this->processNode(scene->mRootNode, scene, aiMatrix4x4());
    }
    }

  • processNode()是一种递归方法,主要对node->mMeshes进行迭代(再乘以转换)。
  • void Model::processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 transformation)
    {
    for (unsigned int i = 0; i < node->mNumMeshes; i++) {
    aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];

    // only apply transformation on meshs not entities such as lights or camera.
    transformation *= node->mTransformation;

    this->meshes.push_back(processMesh(mesh, scene, transformation));
    }

    for (unsigned int i = 0; i < node->mNumChildren; i++)
    {
    processNode(node->mChildren[i], scene, transformation);
    }
    }
  • processMesh()处理收集所有网格数据(顶点,索引等)
  • Mesh Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 transformation)
    {
    glm::vec3 extents;
    glm::vec3 origin;

    std::vector<Vertex> vertices = this->vertices(mesh, extents, origin, transformation);
    std::vector<unsigned int> indices = this->indices(mesh);
    std::vector<Texture> textures = this->textures(mesh, scene);

    return Mesh(
    vertices,
    indices,
    textures,
    extents,
    origin,
    mesh->mName
    );
    }
  • 接下来,调用vertices()方法以获取所有顶点。它通过转换矩阵。在这里,我将顶点与矩阵(transformation * mesh->mVertices[i];)相乘。我有一种强烈的感觉,就是我不在这里做某事,而我正在错过某件事。
  • std::vector<Vertex> Model::vertices(aiMesh* mesh, glm::vec3& extents, glm::vec3 &origin, aiMatrix4x4 transformation)
    {
    std::vector<Vertex> vertices;

    for (unsigned int i = 0; i < mesh->mNumVertices; i++) {
    Vertex vertex;

    glm::vec3 vector3;

    aiVector3D v = transformation * mesh->mVertices[i];

    // Vertices
    vector3.x = v.x;
    vector3.y = v.y;
    vector3.z = v.z;

    vertex.position = vector3;

    // Normals
    if (mesh->mNormals) {
    vector3.x = mesh->mNormals[i].x;
    vector3.y = mesh->mNormals[i].y;
    vector3.z = mesh->mNormals[i].z;
    vertex.normal = vector3;
    }


    // Texture coordinates
    if (mesh->mTextureCoords[0]) {
    glm::vec2 vector2;

    vector2.x = mesh->mTextureCoords[0][i].x;
    vector2.y = mesh->mTextureCoords[0][i].y;
    vertex.texCoord = vector2;
    }
    else {
    vertex.texCoord = glm::vec2(0, 0);
    }

    if (mesh->mTangents) {
    vector3.x = mesh->mTangents[i].x;
    vector3.y = mesh->mTangents[i].y;
    vector3.z = mesh->mTangents[i].z;
    vertex.tangent = vector3;
    }

    // Bitangent
    if (mesh->mBitangents) {
    vector3.x = mesh->mBitangents[i].x;
    vector3.y = mesh->mBitangents[i].y;
    vector3.z = mesh->mBitangents[i].z;
    vertex.bitangent = vector3;
    }


    vertices.push_back(vertex);
    }

    glm::vec3 min = glm::vec3(mesh->mAABB.mMin.x, mesh->mAABB.mMin.y, mesh->mAABB.mMin.z);
    glm::vec3 max = glm::vec3(mesh->mAABB.mMax.x, mesh->mAABB.mMax.y, mesh->mAABB.mMax.z);

    extents = (max - min) * 0.5f;
    origin = glm::vec3((min.x + max.x) / 2.0f, (min.y + max.y) / 2.0f, (min.z + max.z) / 2.0f);

    printf("%f,%f,%f\n", origin.x, origin.y, origin.z);

    return vertices;
    }

    作为补充说明,如果有帮助,这是我在模型上使用的片段着色器:
    #version 330 core
    out vec4 FragColor;

    in vec3 Normal;
    in vec3 FragPos;

    uniform vec3 lightPos;
    uniform vec3 viewPos;

    vec3 lightColor = vec3(1,1,1);
    vec3 objectColor = vec3(0.6, 0.6, 0.6);
    uniform float shininess = 32.0f;
    uniform vec3 material_specular = vec3(0.1f, 0.1f, 0.1f);
    uniform vec3 light_specular = vec3(0.5f, 0.5f, 0.5f);

    void main()
    {
    // ambient
    float ambientStrength = 0.2;
    vec3 ambient = ambientStrength * lightColor;

    // diffuse
    vec3 norm = normalize(Normal);
    vec3 lightDir = normalize(lightPos - FragPos);
    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = diff * lightColor;

    // specular
    vec3 viewDir = normalize(viewPos - FragPos);
    vec3 reflectDir = reflect(-lightDir, norm);
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), shininess);
    vec3 specular = light_specular * (spec * material_specular);

    vec3 result = (ambient + diffuse + specular) * objectColor;
    FragColor = vec4(result, 1.0);
    }

    这是顶点着色器:
    #version 330 core
    layout (location = 0) in vec3 aPos;
    layout (location = 1) in vec3 aNormal;

    out vec3 FragPos;
    out vec3 Normal;

    uniform mat4 projection;
    uniform mat4 view;
    uniform mat4 model;

    uniform float scale;

    void main()
    {
    FragPos = vec3(model * vec4(aPos, 1.0));
    Normal = aNormal;
    gl_Position = projection * view * vec4(FragPos, 1.0);
    }

    最佳答案

    FragPos是世界空间中的一个位置,因为它是由模型矩阵转换的顶点位置。 lightPosviewPos似乎也位于世界空间中。
    因此,也必须将法线 vector aNormal从模型空间转换为世界空间。

    您必须通过4 * 4模型矩阵左上3 * 3的 换位来变换法线 vector :

    Normal = transpose(inverse(mat3(model))) * aNormal;

    可能足以将4 * 4模型矩阵的左上3 * 3进行变换:
    (请参阅 In which cases is the inverse matrix equal to the transpose?)

    Normal = mat3(model) * aNormal;


    也可以看看:
    Why is the transposed inverse of the model view matrix used to transform the normal vectors?
    Why transforming normals with the transpose of the inverse of the modelview matrix?

    关于c++ - 从Assimp加载Collada(dae)模型显示不正确的法线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59833642/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com