【问题标题】:Can't texture model properly无法正确纹理模型
【发布时间】:2014-10-24 13:29:23
【问题描述】:

我的 Blender 3D 对象以三角面导出并写入 UV 未正确应用纹理。

看起来像这样:

我的渲染代码:

    Color.white.bind();
    texture.bind();
    glBegin(GL_TRIANGLES);
    for(ObjFace face : model.faces){
        float[] vertex1 = model.vertices[face.indices[0]-1];
        float[] vertex2 = model.vertices[face.indices[1]-1];
        float[] vertex3 = model.vertices[face.indices[2]-1];
        float[] normal1 = model.normals[face.normals[0]-1];
        float[] normal2 = model.normals[face.normals[1]-1];
        float[] normal3 = model.normals[face.normals[2]-1];
        float[] tex1 = model.texCoords[face.texCoords[0]-1];
        float[] tex2 = model.texCoords[face.texCoords[1]-1];
        float[] tex3 = model.texCoords[face.texCoords[2]-1];
        glNormal3f(normal1[0], normal1[1], normal1[2]);
        glTexCoord2f(tex1[0], tex1[1]);
        glVertex3f(vertex1[0], vertex1[1], vertex1[2]);
        glNormal3f(normal2[0], normal2[1], normal2[2]);
        glTexCoord2f(tex2[0], tex2[1]);
        glVertex3f(vertex2[0], vertex2[1], vertex2[2]);
        glNormal3f(normal3[0], normal3[1], normal3[2]);
        glTexCoord2f(tex3[0], tex3[1]);
        glVertex3f(vertex3[0], vertex3[1], vertex3[2]);
    }
    glEnd();

解析代码:

    for (int i = 0; i < lines.length; ++i) {
        String[] spaced = lines[i].split(" ");
        if (lines[i].startsWith("v ")) {
            float[] vertices = new float[3];
            vertices[0] = parseFloat(spaced[1]);
            vertices[1] = parseFloat(spaced[2]);
            vertices[2] = parseFloat(spaced[3]);
            verticesArray.add(vertices);
        } else if (lines[i].startsWith("vn ")) {
            float[] normals = new float[3];
            normals[0] = parseFloat(spaced[1]);
            normals[1] = parseFloat(spaced[2]);
            normals[2] = parseFloat(spaced[3]);
            normalsArray.add(normals);
        } else if (lines[i].startsWith("vt ")) {
            float[] texCoords = new float[2];
            texCoords[0] = parseFloat(spaced[1]);
            texCoords[1] = parseFloat(spaced[2]);
            texCoordsArray.add(texCoords);
        } else if (lines[i].startsWith("f ")) {
            int[] faceIndices = new int[3];
            int[] faceNormals = new int[3];
            int[] faceTextureCoords = new int[3];
            faceIndices[0] = parseInt(spaced[1].split("/")[0]);
            faceIndices[1] = parseInt(spaced[2].split("/")[0]);
            faceIndices[2] = parseInt(spaced[3].split("/")[0]);
            faceNormals[0] = parseInt(spaced[1].split("/")[2]);
            faceNormals[1] = parseInt(spaced[2].split("/")[2]);
            faceNormals[2] = parseInt(spaced[3].split("/")[2]);
            faceTextureCoords[0] = parseInt(spaced[1].split("/")[1]);
            faceTextureCoords[1] = parseInt(spaced[2].split("/")[1]);
            faceTextureCoords[2] = parseInt(spaced[3].split("/")[1]);
            faceArray.add(new ObjFace(faceIndices, faceNormals, faceTextureCoords));
        }
    }

虽然我不确定这是否是我的 Blender 导出的问题。

谢谢。

编辑:在我将纹理图像的宽度和高度设为 2 次方后更新了图片。

编辑 2:我尝试了一个简单的盒子来确保不是模型搞砸了并测试了面部剔除。在盒子上,剔除背面在一定程度上解决了这个问题,但在杯子上几乎没有什么区别。

编辑 3:我添加了一个视频来演示我认为的问题所在。我认为三角形故障是由重叠的三角形引起的,例如手柄在实际杯子的前面。 youtube vid

【问题讨论】:

  • 你能在你的 OBJ 文件中展示一些人脸(“f”)记录的例子吗?您的解析代码假定每个面只有 3 个顶点,但它们可以具有 OBJ 格式的任意数量的顶点。如果导出应用程序只生成具有 3 个顶点的面,那没问题。否则,你就有问题了。
  • 是的,我使用 Blender 导出 OBJ 并检查了三角面选项。无论如何,这是 OBJ 的内容(杯子):link
  • 我用我最近写的一个加载器尝试了那个cup.obj模型。它主要看起来不错。手柄底部有一个小孔,底部内侧有一些文物。我看不出您发布的代码有任何明显错误。你能显示ObjFace 类,尤其是构造函数吗?
  • 这里是:pastebin.com/UELC31D4 虽然它几乎只是将数组分配给对象内部的数组。

标签: java opengl 3d lwjgl blender


【解决方案1】:

这是另一个“大小不是 2 次方的纹理”问题的实例吗? lwjgl 会将您的纹理扩展到 2 的幂,这意味着您的 [0...1] 的 UV 坐标将是错误的,它们应该是 [0 ... 0.5783] 因为其余的是 lwjgl 填充以达到 2 的幂. 找不到参考...

【讨论】:

  • 我猜这是问题的一部分,因为不再显示任何黑色位。所以谢谢你!但是仍然存在一些部分透明的问题。我更新了我的帖子,添加了一张新照片,展示了它之后的样子。
【解决方案2】:

IIRC,在 GLES20 中,三角形的法线由绕组指示(顺时针或逆时针)。我不确定如果您为每个顶点设置法线(用于照明)而为三角形设置一个法线,GL 会理解什么。我不确定您是否可以为三角形设置一个,这意味着它将根据顶点位置+绕组计算。让我觉得这是个问题的原因是你所有的四边形都是半渲染的(一个三角形分成两个)。

【讨论】:

  • 我认为你对四边形渲染一半是正确的。该模型是从 Blender 导出的,带有三角面和 UV 写入。此外,我还没有对此进行任何照明,所以即使我根本不包括法线,这个问题仍然存在。我认为 Blender 正确设置了顶点、法线和纹理坐标的顺序/方向。
  • 法线和绕线顺序是分开的。法线用于照明,缠绕顺序用于背面剔除(如果启用)。
  • 也许它正在为 TRIANGLE_STRIP 调用排序顶点。无论如何,从第二个茶壶和盒子来看,您的法线似乎有问题。您可以计算三角形法线并确保它指向其顶点的方向,或者以某种方式向 Blender 询问面法线并确保您的订单反映了它。
  • 但是我没有使用任何光照...我根本无法包含法线,这种效果仍然存在。
  • 我的意思是,对于一个三角形,您有顶点的法线(角如何捕捉光线)和三角形的法线(内部和外部的位置,用于可见性剔除)。您可以轻松找到三角形法线的方向(使用叉积),但根据取叉积的顺序,它将指向一个方向或其完全相反的方向,这是有道理的,因为 3d 空间中的三角形有两张脸,哪一张是前面哪一张是后面,由你决定。
猜你喜欢
  • 2015-12-22
  • 1970-01-01
  • 1970-01-01
  • 2014-04-03
  • 2021-11-08
  • 2019-11-24
  • 1970-01-01
  • 2020-07-25
相关资源
最近更新 更多