3dmax模型导出Obj文件的时候顶点坐标发生变化的问题?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3dmax模型导出Obj文件的时候顶点坐标发生变化的问题?相关的知识,希望对你有一定的参考价值。

我要获取模型上某个固定位置的坐标,然后在程序中添加标注。

但是我在3dmax中获取这个位置的坐标,导出Obj之后的那个点的坐标好像发生了变化,因为在程序中添加标注牛头不对马嘴,相差很大:

1、我不确定模型在3dmax中导出obj文件之后,顶点的坐标位置是否会发生变化;
2、不管发没发生变化,如何获取正确的obj中那个位置的正确3d坐标呢?

1 不会发生变化 如果你是导出后再导入的位置不会变
2 MAX中要导出OBJ的物体打一次组 根据组的XYZ坐标确定位置
参考技术A 坐标变化无所谓,整体变化不会影响模型效果,楼下说的很对,比如多边形要是加了曲面细分,一定要塌陷在导出,或去掉细分勾选

obj 模型加载纹理坐标和顶点位置未正确加载

【中文标题】obj 模型加载纹理坐标和顶点位置未正确加载【英文标题】:obj model loading texture coords and vertex position not loaded correctly 【发布时间】:2016-10-25 11:17:25 【问题描述】:

我正在将 3d .obj 模型加载到我的游戏中,但现在是这样的:3d model

这绝对不是它想象中的样子。我想也许是我连接索引的方式是错误的,但我就是找不到问题

这是我的代码:

 char lineHeader[128];
FILE * file = fopen(fileName, "r");

if (file == NULL) 
    printf("Impossible to open the file !\n");


vector <vec3> positionVec;
vector <vec2> texCoordVec;
vector <vec3> normalVec;
vector <GLuint> vertexIndices;
vector <GLuint> uvIndices;
vector <GLuint> normalIndices;

while (true) 
    char lineHeader[128];
    int res = fscanf(file, "%s", lineHeader);

    if (res == EOF) 
        break;
    

        if (strcmp(lineHeader, "v") == 0) 
            glm::vec3 vertex;
            fscanf(file, "%f %f %f\n", &vertex.x, &vertex.y, &vertex.z);
            positionVec.push_back(vertex);
        
        else if (strcmp(lineHeader, "vt") == 0) 
            glm::vec2 uv;
            fscanf(file, "%f %f\n", &uv.x, &uv.y);
            texCoordVec.push_back(uv);
        
        else if (strcmp(lineHeader, "vn") == 0) 
            glm::vec3 normal;
            fscanf(file, "%f %f %f\n", &normal.x, &normal.y, &normal.z);
            normalVec.push_back(normal);
        
        else if (strcmp(lineHeader, "f") == 0) 
            int vertexIndex1, vertexIndex2, vertexIndex3, uvIndex1, uvIndex2, uvIndex3, normalIndex1, normalIndex2, normalIndex3;
            fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", &vertexIndex1, &uvIndex1, &normalIndex1, &vertexIndex2, &uvIndex2, &normalIndex2, &vertexIndex3, &uvIndex3, &normalIndex3);
            vertexIndices.push_back(vertexIndex1);
            vertexIndices.push_back(vertexIndex2);
            vertexIndices.push_back(vertexIndex3);
            uvIndices.push_back(uvIndex1);
            uvIndices.push_back(uvIndex2);
            uvIndices.push_back(uvIndex3);
            normalIndices.push_back(normalIndex1);
            normalIndices.push_back(normalIndex2);
            normalIndices.push_back(normalIndex3);
        
    

vector <vec3> vertexPositions;
vector <vec2> textureCoords;
vector <vec3> normals;

for (unsigned int i = 0; i < vertexIndices.size(); i++) 
    vertexIndices[i] = vertexIndices[i] - 1;


for (unsigned int i = 0; i < uvIndices.size(); i++) 
    unsigned int index = uvIndices[i];
    vec2 uv = texCoordVec[index - 1];
    textureCoords.push_back(uv);
 

for (unsigned int i = 0; i < normalIndices.size(); i++) 
    unsigned int index = normalIndices[i];
    vec3 normal = normalVec[index - 1];
    normals.push_back(normal);
 

    GLuint modelVertecesBuffer;
    glGenBuffers(1, &modelVertecesBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, modelVertecesBuffer);
    glBufferData(GL_ARRAY_BUFFER, positionVec.size() * sizeof(glm::vec3), &positionVec[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

    GLuint modelTextureCoordBuffer;
    glGenBuffers(1, &modelTextureCoordBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, modelTextureCoordBuffer);
    glBufferData(GL_ARRAY_BUFFER, texCoordVec.size() * sizeof(vec2), &texCoordVec[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(2);
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, 0);

    GLuint modelNormalBuffer;
    glGenBuffers(1, &modelNormalBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, modelNormalBuffer);
    glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(vec3), &normals[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);

    GLuint positionIndicesBuffer;
    glGenBuffers(1, &positionIndicesBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, positionIndicesBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, vertexIndices.size() * sizeof(int), &vertexIndices[0], GL_STATIC_DRAW); 

【问题讨论】:

在minimal reproducible example 中编辑。随意使用this 作为基础。 【参考方案1】:

有几点:

OBJ 模型中的索引是从 1 开始的。您在填充向量vertexPositions 等时会考虑这一点。但之后您不再使用这些向量。直接使用来自 OBJ 的索引作为索引缓冲区是行不通的。你必须减去一个。正如 cmets 中提到的 genpfault ,对于相对引用,索引甚至可以是负数。

OBJ 中的面顶点可能引用不同的位置和法线 ID(以及纹理坐标 ID)。这是您无法在 OpenGL 中表示的内容,您需要复制一些数据。所以这种方法只有在引用的 id 都相同的情况下才有效。

【讨论】:

OBJ 指数也可以是负数。 @genpfault 谢谢,已添加到答案中。 @NicoSchertler 感谢您的帮助,我修复了位置索引,因此模型现在看起来正确,但它的纹理仍然一团糟,您对还有什么问题有任何想法吗? (我更新了代码) 不过,OBJ 可能使用不同的索引来表示位置和纹理坐标。除了复制一些顶点之外,您对此无能为力。

以上是关于3dmax模型导出Obj文件的时候顶点坐标发生变化的问题?的主要内容,如果未能解决你的问题,请参考以下文章

为啥maya绑定的模型导出fbx会丢失顶点法线信息?

我把3dmax模型导出成OBJ,然后导入bodypoint3d,但是打开在bodypoint3d里看不到模型,之前都可以啊

3Dmax导出FBX格式 原模型是dds的贴图

3dmax中三维模型如何等比缩放??

3DMAX导出到Unity坐标轴转换问题

3D模型文件 OBJ格式模型详细介绍