[SOLVED AGAIN] Where are the texture coordinates going wrong?

So I am making a game engine, and fairly early on I came across a problem that is really boggling me. I have a test sphere implemented in-game by a class called “StaticMesh”, which contains a model parsed from an obj file and a texture. This sphere was created and exported in blender (where it looked fine), but when I attach a texture to the static mesh the texture coordinates just break.

EDIT: With help form StrideColossus I fixed the previous problem, and I thought I’d fixed the problem after that, but now it appears as though I haven’t. I used slick’s “flip” option on one of my school computers (a mac) and it solved the problem, but when I took my project back home to my computer (windows) the “flip” option ceased to work. I tried it again yesterday on a mac at school and the code is still good, but sure enough, when I take it home we’re back to “flip” not working. I’d assume this is a system related issue, but maybe there’s a fix?

This is what it looked like in blender (the black lines mark the seams)

And this is what it looks like in my engine

I’ve combed over the code, and can’t find any reason as to why it would act like this, but maybe some fresh eyes can spot a problem. Here’s the “StaticMesh” class


package neatEngine.game;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;
import neatEngine.Console;
import neatEngine.graphics.Polygon;
import neatEngine.graphics.TextureImage;
import neatEngine.math.Vector2f;
import neatEngine.math.Vector3f;
import static org.lwjgl.opengl.GL11.*;

/*
 * An environment component that has static geometry.
 * <p>
 * The static mesh should be used for models who's geometry and textures don't
 * change.
 * 
 * @author Kwauhn (Quinn Desforge-Major)
 * @version 0.01
 */
public class StaticMesh {
	private Vector3f p;
	private List<Vector3f> v;
	private List<Vector3f> n;
	private List<Vector2f> t;
	private List<Polygon> f;
	private TextureImage ti;
	
	/*
	 * Creates a new static mesh from the specified resource at the specified
	 * position.
	 * 
	 * @param r the resource file containing the mesh information
	 * @param tir the resource file containing the texture image
	 * @param p the vector representing the position of this static mesh
	 */
	public StaticMesh(String r, String tir, Vector3f p){
		this.p = p;
		v = new ArrayList<Vector3f>();
		n = new ArrayList<Vector3f>();
		t = new ArrayList<Vector2f>();
		f = new ArrayList<Polygon>();
		ti = new TextureImage(tir);
		
		int lineNumber = 0;
		try{
			BufferedReader reader = new BufferedReader(new FileReader(new File(r)));
			String line;
			while((line = reader.readLine()) != null){
				if(line.startsWith("v ")){
					String[] indices = line.split(" ");
					v.add(new Vector3f(Float.valueOf(indices[1]), Float.valueOf(indices[2]), Float.valueOf(indices[3])));
				}else if(line.startsWith("vn ")){
					String[] indices = line.split(" ");
					n.add(new Vector3f(Float.valueOf(indices[1]), Float.valueOf(indices[2]), Float.valueOf(indices[3])));
				}else if(line.startsWith("vt ")){
					String[] indices = line.split(" ");
					t.add(new Vector2f(Float.valueOf(indices[1]), Float.valueOf(indices[2])));
				}else if(line.startsWith("f ")){
					String[] points = line.split(" ");
					String[] point1 = points[1].split("/");
					String[] point2 = points[2].split("/");
					String[] point3 = points[3].split("/");
					Vector3f vertexIndices = new Vector3f(Integer.valueOf(point1[0]), Integer.valueOf(point2[0]), Integer.valueOf(point3[0]));
					Vector3f normalIndices = new Vector3f(Integer.valueOf(point1[2]), Integer.valueOf(point2[2]), Integer.valueOf(point3[2]));
					Vector3f textureIndices = new Vector3f(Integer.valueOf(point1[1]), Integer.valueOf(point2[1]), Integer.valueOf(point3[1]));
					f.add(new Polygon(vertexIndices, normalIndices, textureIndices));
				}
				lineNumber++;
			}
			reader.close();
		}catch(Exception e){
			Console.logError(e, "Could not load static mesh file: Error at " + lineNumber);
			e.printStackTrace();
		}
	}
	
	/*
	 * Renders this static mesh.
	 */
	public void render(){
		ti.bind();
		glPushMatrix();
		glTranslatef(p.getX(), p.getY(), p.getZ());
		glBegin(GL_TRIANGLES);
		{
			for(int i = 0; i < f.size(); i++){
				Vector3f v1 = v.get((int)(f.get(i).getVertexIndices().getX()) - 1);
				Vector3f v2 = v.get((int)(f.get(i).getVertexIndices().getY()) - 1);
				Vector3f v3 = v.get((int)(f.get(i).getVertexIndices().getZ()) - 1);
				Vector3f n1 = n.get((int)(f.get(i).getNormalIndices().getX()) - 1);
				Vector3f n2 = n.get((int)(f.get(i).getNormalIndices().getY()) - 1);
				Vector3f n3 = n.get((int)(f.get(i).getNormalIndices().getZ()) - 1);
				Vector2f t1 = t.get((int)(f.get(i).getTextureIndices().getX()) - 1);
				Vector2f t2 = t.get((int)(f.get(i).getTextureIndices().getY()) - 1);
				Vector2f t3 = t.get((int)(f.get(i).getTextureIndices().getZ()) - 1);
				
			    glNormal3f(n1.getX(), n1.getY(), n1.getZ());	glTexCoord2f(t1.getX(), t1.getY());	   glVertex3f(v1.getX(), v1.getY(), v1.getZ());
			    glNormal3f(n2.getX(), n2.getY(), n2.getZ());	glTexCoord2f(t2.getX(), t2.getY());	   glVertex3f(v2.getX(), v2.getY(), v2.getZ());
			    glNormal3f(n3.getX(), n3.getY(), n3.getZ());	glTexCoord2f(t3.getX(), t3.getY());    glVertex3f(v3.getX(), v3.getY(), v3.getZ());
			}
		}
		glEnd();
		glPopMatrix();
		glDisable(GL_TEXTURE_2D);
	}
	
	/*
	 * Returns the vector representing the position of this static mesh.
	 * 
	 * @return the vector representing the position of this static mesh
	 */
	public Vector3f getPosition(){
		return p;
	}
	
	/*
	 * Sets the current position vector to the one specified.
	 * 
	 * @param p the new position vector
	 */
	public void setPosition(Vector3f p){
		this.p = p;
	}
}

And here’s the “TextureImage” class


package neatEngine.graphics;

import java.io.File;
import java.io.FileInputStream;
import neatEngine.Console;
import org.newdawn.slick.opengl.*;

/*
 * This class makes texture handling easy and simple.
 * <p>
 * Texture Image uses the Slick Utility library to handle textures, and contains
 * some simple fail-safes to avoid fatal errors.
 * 
 * @author Kwauhn (Quinn Desforge-Major)
 * @version 0.01
 */
public class TextureImage {
	private Texture t;
	private String r;
	
	/*
	 * Creates a new Texture Image from the file with the provided path.
	 * 
	 * @param r the path of the image resource
	 */
	public TextureImage(String r){
		this.r = r;
		try{
			t = TextureLoader.getTexture("PNG", new FileInputStream(new File(r)), true);
		}catch(Exception e){
			Console.logError(e, "Could not load texture from \"" + r + "\"");
			t = null;
		}
	}
	
	/*
	 * Binds the texture for drawing with OpenGL.
	 */
	public void bind(){
		if(t != null){
			t.bind();
		}
	}
	
	/*
	 * Reloads the texture file (for runtime editing).
	 */
	public void reload(){
		try{
			t = TextureLoader.getTexture("PNG", new FileInputStream(new File(r)), true);
		}catch(Exception e){
			Console.logError(e, "Could not load texture from \"" + r + "\"");
			t = null;
		}
	}
}

Any help is appreciated. Staring at this code isn’t really helping the project get along, and there’s a lot to do! Thanks for reading :slight_smile: