Not long ago, I create a nice OBJ loader that loads 3D Studio Max files. Only problem is, is that although it works and works great, I wasn't using Vertex Buffers. Now that I applied Vertex Buffers, it seems to only use the first color of the texture and spread it all across the poiygon. I examined my code over and over again, and the Vertex Buffer code is correct. But when I comment out all of my vertex buffer code, it works as intended. I practically given up on fixing it on my own, so hopefully you guys will be able to figure out what is wrong.
public static final int BYTES_PER_FLOAT = 4;
public static final int POSITION_COMPONENT_COUNT_3D = 4;
public static final int COLOR_COMPONENT_COUNT = 4;
public static final int TEXTURE_COORDINATES_COMPONENT_COUNT = 2;
public static final int NORMAL_COMPONENT_COUNT = 3;
public static final int POSITION_COMPONENT_STRIDE_2D = POSITION_COMPONENT_COUNT_2D * BYTES_PER_FLOAT;
public static final int POSITION_COMPONENT_STRIDE_3D = POSITION_COMPONENT_COUNT_3D * BYTES_PER_FLOAT;
public static final int COLOR_COMPONENT_STRIDE = COLOR_COMPONENT_COUNT * BYTES_PER_FLOAT;
public static final int TEXTURE_COORDINATE_COMPONENT_STRIDE = TEXTURE_COORDINATES_COMPONENT_COUNT * BYTES_PER_FLOAT;
public static final int NORMAL_COMPONENT_STRIDE = NORMAL_COMPONENT_COUNT * BYTES_PER_FLOAT;
int loadFile()
{
ArrayList<Vertex3D> tempVertexArrayList = new ArrayList<Vertex3D>();
ArrayList<TextureCoord2D> tempTextureCoordArrayList = new ArrayList<TextureCoord2D>();
ArrayList<Vector3D> tempNormalArrayList = new ArrayList<Vector3D>();
ArrayList<Face3D> tempFaceArrayList = new ArrayList<Face3D>();
StringBuilder body = new StringBuilder();
try {
InputStream inputStream = context.getResources().openRawResource(resourceID);
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String nextLine;
String subString;
String[] stringArray;
String[] stringArray2;
int[] indexNumberList = new int[3];
int[] textureCoordNumberList = new int[3];
int[] normalNumberList = new int[3];
int i = 0;
int j = 0;
int k = 0;
try {
while ((nextLine = bufferedReader.readLine()) != null) {
if (nextLine.startsWith("v ")) {
subString = nextLine.substring(1).trim();
stringArray = subString.split(" ");
try {
tempVertexArrayList.add(new Vertex3D(Float.parseFloat(stringArray[0]),
Float.parseFloat(stringArray[1]),
Float.parseFloat(stringArray[2]), 1f));
}
catch(NumberFormatException e){
Log.d(TAG, "Error: Invalid number format in loading vertex list");
return 0;
}
String x = String.valueOf(tempVertexArrayList.get(i).x);
String y = String.valueOf(tempVertexArrayList.get(i).y);
String z = String.valueOf(tempVertexArrayList.get(i).z);
//Log.d(TAG, "vertex " + String.valueOf(i) + ": " + x + ", " + y + ", " + z);
i++;
}
if (nextLine.startsWith("vn ")) {
subString = nextLine.substring(2).trim();
stringArray = subString.split(" ");
try {
if(reverseNormals){
tempNormalArrayList.add(new Vector3D(-Float.parseFloat(stringArray[0]),
-Float.parseFloat(stringArray[1]),
-Float.parseFloat(stringArray[2])));
}
else{
tempNormalArrayList.add(new Vector3D(Float.parseFloat(stringArray[0]),
Float.parseFloat(stringArray[1]),
Float.parseFloat(stringArray[2])));
}
}
catch(NumberFormatException e){
Log.d(TAG, "Error: Invalid number format in loading normal list");
return 0;
}
String nx = String.valueOf(tempNormalArrayList.get(j).x);
String ny = String.valueOf(tempNormalArrayList.get(j).y);
String nz = String.valueOf(tempNormalArrayList.get(j).z);
//Log.d(TAG, "normal " + String.valueOf(j) + ": " + nx + ", " + ny + ", " + nz);
j++;
}
if (nextLine.startsWith("vt ")) {
subString = nextLine.substring(2).trim();
stringArray = subString.split(" ");
try {
tempTextureCoordArrayList.add(new TextureCoord2D(Float.parseFloat(stringArray[0]),
Float.parseFloat(stringArray[1])));
}
catch(NumberFormatException e){
Log.d(TAG, "Error: Invalid number format in loading texture coordinate list");
return 0;
}
String tu = String.valueOf(tempTextureCoordArrayList.get(k).tu);
String tv = String.valueOf(tempTextureCoordArrayList.get(k).tv);
//Log.d(TAG, "texture coord " + String.valueOf(k) + ": " + tu + ", " + tv);
k++;
}
if (nextLine.startsWith("f ")) {
subString = nextLine.substring(1).trim();
stringArray = subString.split(" ");
for (int index = 0; index <= 2; index++) {
stringArray2 = stringArray[index].split("/");
try {
indexNumberList[index] = Integer.parseInt(stringArray2[0]) - 1;
if(indexNumberList[index] < 0){
Log.d(TAG, "Error: indexNumberList[] is less than zero");
return 0;
}
}
catch(NumberFormatException e){
Log.d(TAG, "Error: Invalid number format in loading indexNumberList[]");
return 0;
}
try{
textureCoordNumberList[index] = Integer.parseInt(stringArray2[1]) - 1;
if(textureCoordNumberList[index] < 0){
Log.d(TAG, "Error: textureCoordNumberList[] is less than zero");
return 0;
}
}
catch(NumberFormatException e){
Log.d(TAG, "Error: Invalid number format in loading textureCoordNumberList[]");
return 0;
}
try{
normalNumberList[index] = Integer.parseInt(stringArray2[2]) - 1;
if(normalNumberList[index] < 0){
Log.d(TAG, "Error: normalNumberList[] is less than zero");
return 0;
}
}
catch(NumberFormatException e){
Log.d(TAG, "Error: Invalid number format in loading normalNumberList[]");
return 0;
}
}
tempFaceArrayList.add(new Face3D(indexNumberList[0], textureCoordNumberList[0], normalNumberList[0],
indexNumberList[1], textureCoordNumberList[1], normalNumberList[1],
indexNumberList[2], textureCoordNumberList[2], normalNumberList[2]));
}
body.append(nextLine);
body.append('\n');
}
//Now that everything has successfully loaded, you can now populate the public variables.
if(tempVertexArrayList != null && tempVertexArrayList.size() != 0)
vertexArrayList.addAll(tempVertexArrayList);
if(tempTextureCoordArrayList != null && tempTextureCoordArrayList.size() != 0)
textureCoordArrayList.addAll(tempTextureCoordArrayList);
if(tempNormalArrayList != null && tempNormalArrayList.size() != 0)
normalArrayList.addAll(tempNormalArrayList);
if(tempFaceArrayList != null && tempFaceArrayList.size() != 0)
faceArrayList.addAll(tempFaceArrayList);
vertexList = new float[faceArrayList.size() * POSITION_COMPONENT_COUNT_3D * NUMBER_OF_SIDES_PER_FACE];
indexList = new short[faceArrayList.size() * NUMBER_OF_SIDES_PER_FACE];
colorList = new float[faceArrayList.size() * COLOR_COMPONENT_COUNT * NUMBER_OF_SIDES_PER_FACE];
textureCoordList = new float[faceArrayList.size() * TEXTURE_COORDINATES_COMPONENT_COUNT * NUMBER_OF_SIDES_PER_FACE];
normalList = new float[faceArrayList.size() * NORMAL_COMPONENT_COUNT * NUMBER_OF_SIDES_PER_FACE];
int nextFace = 0;
int step = POSITION_COMPONENT_COUNT_3D * NUMBER_OF_SIDES_PER_FACE;
for (int currentVertex = 0; currentVertex < vertexList.length; currentVertex += step){
vertexList[currentVertex + 0] = vertexArrayList.get(faceArrayList.get(nextFace).indexNumberList.get(0)).x;
vertexList[currentVertex + 1] = vertexArrayList.get(faceArrayList.get(nextFace).indexNumberList.get(0)).y;
vertexList[currentVertex + 2] = vertexArrayList.get(faceArrayList.get(nextFace).indexNumberList.get(0)).z;
vertexList[currentVertex + 3] = vertexArrayList.get(faceArrayList.get(nextFace).indexNumberList.get(0)).w;
vertexList[currentVertex + 4] = vertexArrayList.get(faceArrayList.get(nextFace).indexNumberList.get(1)).x;
vertexList[currentVertex + 5] = vertexArrayList.get(faceArrayList.get(nextFace).indexNumberList.get(1)).y;
vertexList[currentVertex + 6] = vertexArrayList.get(faceArrayList.get(nextFace).indexNumberList.get(1)).z;
vertexList[currentVertex + 7] = vertexArrayList.get(faceArrayList.get(nextFace).indexNumberList.get(1)).w;
vertexList[currentVertex + 8] = vertexArrayList.get(faceArrayList.get(nextFace).indexNumberList.get(2)).x;
vertexList[currentVertex + 9] = vertexArrayList.get(faceArrayList.get(nextFace).indexNumberList.get(2)).y;
vertexList[currentVertex + 10] = vertexArrayList.get(faceArrayList.get(nextFace).indexNumberList.get(2)).z;
vertexList[currentVertex + 11] = vertexArrayList.get(faceArrayList.get(nextFace).indexNumberList.get(2)).w;
nextFace++;
}
numberOfVertices = vertexList.length / POSITION_COMPONENT_COUNT_3D;
nextFace = 0;
for (int currentIndex = 0; currentIndex < indexList.length; currentIndex += NUMBER_OF_SIDES_PER_FACE){
indexList[currentIndex + 0] = faceArrayList.get(nextFace).indexNumberList.get(0).shortValue();
indexList[currentIndex + 1] = faceArrayList.get(nextFace).indexNumberList.get(1).shortValue();
indexList[currentIndex + 2] = faceArrayList.get(nextFace).indexNumberList.get(2).shortValue();
}
step = COLOR_COMPONENT_COUNT * NUMBER_OF_SIDES_PER_FACE;
for (int currentVertex = 0; currentVertex < colorList.length; currentVertex += step){
colorList[currentVertex + 0] = red;
colorList[currentVertex + 1] = green;
colorList[currentVertex + 2] = blue;
colorList[currentVertex + 3] = alpha;
colorList[currentVertex + 4] = red;
colorList[currentVertex + 5] = green;
colorList[currentVertex + 6] = blue;
colorList[currentVertex + 7] = alpha;
colorList[currentVertex + 8] = red;
colorList[currentVertex + 9] = green;
colorList[currentVertex + 10] = blue;
colorList[currentVertex + 11] = alpha;
}
nextFace = 0;
step = TEXTURE_COORDINATES_COMPONENT_COUNT * NUMBER_OF_SIDES_PER_FACE;
for (int currentVertex = 0; currentVertex < textureCoordList.length; currentVertex += step){
textureCoordList[currentVertex + 0] = textureCoordArrayList.get(faceArrayList.get(nextFace).textureCoordNumberList.get(0)).tu * mult;
textureCoordList[currentVertex + 1] = textureCoordArrayList.get(faceArrayList.get(nextFace).textureCoordNumberList.get(0)).tv * mult;
textureCoordList[currentVertex + 2] = textureCoordArrayList.get(faceArrayList.get(nextFace).textureCoordNumberList.get(1)).tu * mult;
textureCoordList[currentVertex + 3] = textureCoordArrayList.get(faceArrayList.get(nextFace).textureCoordNumberList.get(1)).tv * mult;
textureCoordList[currentVertex + 4] = textureCoordArrayList.get(faceArrayList.get(nextFace).textureCoordNumberList.get(2)).tu * mult;
textureCoordList[currentVertex + 5] = textureCoordArrayList.get(faceArrayList.get(nextFace).textureCoordNumberList.get(2)).tv * mult;
nextFace++;
}
nextFace = 0;
step = NORMAL_COMPONENT_COUNT * NUMBER_OF_SIDES_PER_FACE;
for (int currentVertex = 0; currentVertex < normalList.length; currentVertex += step){
normalList[currentVertex + 0] = normalArrayList.get(faceArrayList.get(nextFace).normalNumberList.get(0)).x;
normalList[currentVertex + 1] = normalArrayList.get(faceArrayList.get(nextFace).normalNumberList.get(0)).y;
normalList[currentVertex + 2] = normalArrayList.get(faceArrayList.get(nextFace).normalNumberList.get(0)).z;
normalList[currentVertex + 3] = normalArrayList.get(faceArrayList.get(nextFace).normalNumberList.get(1)).x;
normalList[currentVertex + 4] = normalArrayList.get(faceArrayList.get(nextFace).normalNumberList.get(1)).y;
normalList[currentVertex + 5] = normalArrayList.get(faceArrayList.get(nextFace).normalNumberList.get(1)).z;
normalList[currentVertex + 6] = normalArrayList.get(faceArrayList.get(nextFace).normalNumberList.get(2)).x;
normalList[currentVertex + 7] = normalArrayList.get(faceArrayList.get(nextFace).normalNumberList.get(2)).y;
normalList[currentVertex + 8] = normalArrayList.get(faceArrayList.get(nextFace).normalNumberList.get(2)).z;
nextFace++;
}
vertexBuffer = ByteBuffer.allocateDirect(vertexList.length * BYTES_PER_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();
indexBuffer = ByteBuffer.allocateDirect(indexList.length * BYTES_PER_FLOAT).order(ByteOrder.nativeOrder()).asShortBuffer();
colorBuffer = ByteBuffer.allocateDirect(colorList.length * BYTES_PER_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();
textureCoordBuffer = ByteBuffer.allocateDirect(textureCoordList.length * BYTES_PER_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();
normalBuffer = ByteBuffer.allocateDirect(normalList.length * BYTES_PER_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();
vertexBuffer.put(vertexList).position(0);
indexBuffer.put(indexList).position(0);
colorBuffer.put(colorList).position(0);
textureCoordBuffer.put(textureCoordList).position(0);
normalBuffer.put(normalList).position(0);
createVertexBuffer();
uMVPMatrixHandle = glGetUniformLocation(program, U_MVPMATRIX);
uMVMatrixHandle = glGetUniformLocation(program, U_MVMATRIX);
uTextureUnitHandle = glGetUniformLocation(program, U_TEXTURE_UNIT);
aPositionHandle = glGetAttribLocation(program, A_POSITION);
aColorHandle = glGetAttribLocation(program, A_COLOR);
aTextureCoordinateHandle = glGetAttribLocation(program, A_TEXTURE_COORDINATES);
aNormalHandle = glGetAttribLocation(program, A_NORMAL);
glEnableVertexAttribArray(aPositionHandle);
glEnableVertexAttribArray(aColorHandle);
glEnableVertexAttribArray(aTextureCoordinateHandle);
glEnableVertexAttribArray(aNormalHandle);
glActiveTexture(GL_TEXTURE0);
glUniform1i(uTextureUnitHandle, 0);
}
catch(IOException e){
}
}
catch (Resources.NotFoundException nfe){
throw new RuntimeException("Resource not found: " + resourceID, nfe);
}
return 1;
}
public void draw(){
glEnable(GL_DEPTH_TEST);
bindData();
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject[0]);
glDrawArrays(GL_TRIANGLES, 0, faceArrayList.size() * NUMBER_OF_SIDES_PER_FACE);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
public void bindData(){
int offset = 0;
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject[0]);
glVertexAttribPointer(aPositionHandle, POSITION_COMPONENT_COUNT_3D, GL_FLOAT, false, POSITION_COMPONENT_STRIDE_3D, offset);
offset += POSITION_COMPONENT_COUNT_3D;
glVertexAttribPointer(aColorHandle, COLOR_COMPONENT_COUNT, GL_FLOAT, false, COLOR_COMPONENT_STRIDE, numberOfVertices * offset * BYTES_PER_FLOAT);
offset += COLOR_COMPONENT_COUNT;
glVertexAttribPointer(aTextureCoordinateHandle, TEXTURE_COORDINATES_COMPONENT_COUNT, GL_FLOAT, false, TEXTURE_COORDINATE_COMPONENT_STRIDE, numberOfVertices * offset * BYTES_PER_FLOAT);
offset += TEXTURE_COORDINATES_COMPONENT_COUNT;
glVertexAttribPointer(aNormalHandle, NORMAL_COMPONENT_COUNT, GL_FLOAT, false, NORMAL_COMPONENT_STRIDE, numberOfVertices * offset * BYTES_PER_FLOAT);
glBindBuffer(GL_ARRAY_BUFFER, 0);
/////////////////////////////////////////////////////
/*
vertexBuffer.position(0);
glVertexAttribPointer(aPositionHandle, POSITION_COMPONENT_COUNT_3D, GL_FLOAT, false, POSITION_COMPONENT_STRIDE_3D, vertexBuffer);
colorBuffer.position(0);
glVertexAttribPointer(aColorHandle, COLOR_COMPONENT_COUNT, GL_FLOAT, false, COLOR_COMPONENT_STRIDE, colorBuffer);
textureCoordBuffer.position(0);
glVertexAttribPointer(aTextureCoordinateHandle, TEXTURE_COORDINATES_COMPONENT_COUNT, GL_FLOAT, false, TEXTURE_COORDINATE_COMPONENT_STRIDE, textureCoordBuffer);
normalBuffer.position(0);
glVertexAttribPointer(aNormalHandle, NORMAL_COMPONENT_COUNT, GL_FLOAT, false, NORMAL_COMPONENT_STRIDE, normalBuffer);
*/
}
public void createVertexBuffer(){
glGenBuffers(1, vertexBufferObject, 0);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject[0]);
glBufferData(GL_ARRAY_BUFFER,numberOfVertices * (POSITION_COMPONENT_COUNT_3D + COLOR_COMPONENT_COUNT + TEXTURE_COORDINATES_COMPONENT_COUNT + NORMAL_COMPONENT_COUNT) * BYTES_PER_FLOAT, null, GL_STATIC_DRAW);
int offset = 0;
glBufferSubData(GL_ARRAY_BUFFER, offset,
numberOfVertices * POSITION_COMPONENT_COUNT_3D * BYTES_PER_FLOAT, vertexBuffer);
offset += POSITION_COMPONENT_COUNT_3D;
glBufferSubData(GL_ARRAY_BUFFER, numberOfVertices * offset * BYTES_PER_FLOAT,
numberOfVertices * COLOR_COMPONENT_COUNT * BYTES_PER_FLOAT, colorBuffer);
offset += COLOR_COMPONENT_COUNT;
glBufferSubData(GL_ARRAY_BUFFER, numberOfVertices * offset * BYTES_PER_FLOAT,
numberOfVertices * TEXTURE_COORDINATES_COMPONENT_COUNT * BYTES_PER_FLOAT, textureCoordBuffer);
offset += TEXTURE_COORDINATES_COMPONENT_COUNT;
glBufferSubData(GL_ARRAY_BUFFER, numberOfVertices * offset * BYTES_PER_FLOAT,
numberOfVertices * NORMAL_COMPONENT_COUNT * BYTES_PER_FLOAT, normalBuffer);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}