OpenGL:我的纹理是错的吗?

时间:2010-09-24 21:33:58

标签: java opengl graphics jogl

我是OpenGL的新手。我正在使用JOGL。

我下载了这个model。它有一堆纹理。我正在尝试在这里申请“truck_color-blue.jpg”,但我不确定我做得对。这就是我所看到的:

Side by side: by texture and the site's demo

基本上,我正在做的是记录所有vtvvn条目,然后使用f行索引它们。这是进行glTexCoord*()调用的代码:

           if (facePoint.textureIndex != null) {
                Vector2f texCoords = getTexture(facePoint.textureIndex);
                gl.glTexCoord2f(texCoords.x, texCoords.y);
            }

            // ...

            Point3f vertex = getVertex(facePoint.vertexIndex);
            gl.glVertex3f(vertex.x, vertex.y, vertex.z);

我怀疑我没有正确地将纹理坐标与顶点匹配。该模型表示它是UV映射的。这是否意味着我需要以不同的方式做纹理?

我的代码来读取.obj文件:

public class ObjModel extends WorldEntity {

    // ...

    @Override
    protected void buildDrawList() {
        startDrawList();

        for (Polygon poly : polygons) {

            if (poly.getFaces().size() == 4) {
                gl.glBegin(GL2.GL_QUADS);
            } else {
                gl.glBegin(GL2.GL_POLYGON);
            }

            for (FacePoint facePoint : poly.getFaces()) {
                if (facePoint.vertexIndex == null) {
                    throw new RuntimeException("Why was there a face with no vertex?");
                }

                if (facePoint.textureIndex != null) {
                    Vector2f texCoords = getTexture(facePoint.textureIndex);
                    gl.glTexCoord2f(texCoords.x, texCoords.y);
                }

                if (facePoint.normalIndex != null) { 
                    // why use both Vector3f and Point3f?
                    Vector3f normal = getNormal(facePoint.normalIndex);
                    gl.glNormal3f(normal.x, normal.y, normal.z);
                }

                Point3f vertex = getVertex(facePoint.vertexIndex);
                gl.glVertex3f(vertex.x, vertex.y, vertex.z);
            }
            gl.glEnd();
        }

        endDrawList();
    }

    private Point3f getVertex(int index) {
        if (index >= 0) {
            // -1 is necessary b/c .obj is 1 indexed, but vertices is 0 indexed.
            return vertices.get(index - 1);
        } else {
            return vertices.get(vertices.size() + index);
        }
    }

    private Vector3f getNormal(int index) {
        if (index >= 0) {
            return normals.get(index - 1);
        } else {
            return normals.get(normals.size() + index);
        }
    }

    private Vector2f getTexture(int index) {
        if (index >= 0) {
            return textures.get(index - 1);
        } else {
            return textures.get(textures.size() + index);
        }
    }

    private void readFile(String fileName) {
        try {
            BufferedReader input = new BufferedReader(new FileReader(fileName));
            try {
                String currLine = null;
                while ((currLine = input.readLine()) != null) {

                    int indVn = currLine.indexOf("vn ");
                    if (indVn != -1) {
                        readNormal(currLine);
                        continue;
                    }

                    int indV = currLine.indexOf("v ");
                    if (indV != -1) {
                        readVertex(currLine);
                        continue;
                    }

                    int indF = currLine.indexOf("f ");
                    if (indF != -1) {
                        readPolygon(currLine);
                        continue;
                    }

                    int indVt = currLine.indexOf("vt ");
                    if (indVt != -1) {
                        readTexture(currLine);
                        continue;
                    }
                }
            } finally {
                input.close();
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    private void readVertex(String newLine) {
        String pieces[] = newLine.split("\\s+");
        Point3f vertex = new Point3f(Float.parseFloat(pieces[1]), Float.parseFloat(pieces[2]), Float.parseFloat(pieces[3]));
        vertices.add(vertex);
    }

    private void readNormal(String newLine) {
        String pieces[] = newLine.split("\\s+");
        Vector3f norm = new Vector3f(Float.parseFloat(pieces[1]), Float.parseFloat(pieces[2]), Float.parseFloat(pieces[3]));
        normals.add(norm);
    }

    private void readTexture(String newLine) {
        String pieces[] = newLine.split("\\s+");
        Vector2f tex = new Vector2f(Float.parseFloat(pieces[1]), Float.parseFloat(pieces[2]));
        textures.add(tex);
    }

    private void readPolygon(String newLine) {
        polygons.add(new Polygon(newLine));
    }
}

类多边形表示类似f 1/2/3 4/5/6 7/8/9的行。

public class Polygon {     private List faces = new ArrayList();

public Polygon(String line) {
    if (line.charAt(0) != 'f') {
        throw new IllegalArgumentException(String.format("Line must be a face definition, but was: '%s'", line));
    }

    String[] facePointDefs = line.split("\\s+");

    // ignore the first piece - it will be "f ". 
    for (int i = 1; i < facePointDefs.length; i++) {
        faces.add(new FacePoint(facePointDefs[i]));
    }
}

public List<FacePoint> getFaces() {
    return Collections.unmodifiableList(faces);
}

}

类FacePoint 表示面部点,例如21/342/231

public class FacePoint {

    private static final String FACE_POINT_REGEX = "^(\\d+)\\/(\\d+)?(\\/(\\d+))?$";

    public Integer vertexIndex;
    public Integer textureIndex;
    public Integer normalIndex;

    public FacePoint(String facePointDef) {
        Matcher matcher = Pattern.compile(FACE_POINT_REGEX).matcher(facePointDef);

        if (!matcher.find()) {
            throw new IllegalArgumentException(String.format("facePointDef is invalid: '%s'", facePointDef));
        }

        String vertexMatch = matcher.group(1);
        if (vertexMatch == null) {
            throw new IllegalArgumentException(String.format("The face point definition didn't contain a vertex: '%s'",
                    facePointDef));
        }
        vertexIndex = Integer.parseInt(vertexMatch);

        String texMatch = matcher.group(2);
        if (texMatch != null) {
            textureIndex = Integer.parseInt(texMatch);
        }

        String normalMatch = matcher.group(4);
        if (normalMatch != null) {
            normalIndex = Integer.parseInt(normalMatch);
        }
    }
}

1 个答案:

答案 0 :(得分:0)

在OpenGL中,纹理原点位于左下方而不是左上方。这可能会弄乱你的纹理。如果这是问题,一个简单的解决方法是从1:glTexCoord2f(texCoords.x, 1.0f - texCoords.y)中减去y纹理坐标。 (这与垂直翻转纹理相同。)