views:

31

answers:

1

I am new to OpenGL. I am using JOGL.

I downloaded this model. It has a bunch of textures. I'm trying to apply "truck_color-blue.jpg" here, but I'm not sure I'm doing it right. This is what I'm seeing:

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

Essentially, what I am doing is recording all the vt, v, and vn entries, then using the f lines to index into them. This is the code that makes the glTexCoord*() call:

           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);

I suspect that I'm not correctly matching up the texture coords to the vertices. The model says that it is UV mapped. Does that mean I need to do textures differently?

My code to read .obj files:

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));
    }
}

class Polygon represents a line like 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);
}

}

class FacePoint represents a face point, like 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);
        }
    }
}
A: 

In OpenGL, the texture origin is at the bottom left as opposed to the top left. This could be messing up your textures. If this is the issue, a simple fix is to subtract the the y texture coordinate from 1: glTexCoord2f(texCoords.x, 1.0f - texCoords.y). (This is the same as flipping the texture vertically.)

Gumgo