LWJGL Forum

Programming => OpenGL => Topic started by: Sumec99 on March 31, 2014, 18:05:24

Title: Using VBO 3d Models makes strange triangles at wrong places
Post by: Sumec99 on March 31, 2014, 18:05:24
Hi Everyone,
I've written(well, I've got the code from a tutorial) a few classes to load my own 3d models in .obj format into my programm ...
each single face of the model is a triangle
At first i thought everything would work perfect, but when I load more than just one model, there are triangles between vertices of the model where they shall NOT be...
I use vbos to display my models ...
I've tried changes and googled around for about a week but I haven't got any solution ...

Here's my code of all classes:
OBJLoader:

package the_wormhole;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

import org.lwjgl.util.vector.Vector3f;

public class OBJLoader {
public static Model loadModel(File f) throws FileNotFoundException, IOException{
BufferedReader reader = new BufferedReader(new FileReader(f));

Model m = new Model();
String line;
while((line = reader.readLine()) != null){
if(line.startsWith("v ")){
float x = Float.valueOf(line.split(" ")[1]);
float y = Float.valueOf(line.split(" ")[2]);
float z = Float.valueOf(line.split(" ")[3]);

m.vertices.add(new Vector3f(x, y, z));
}else if(line.startsWith("vn ")){
float x = Float.valueOf(line.split(" ")[1]);
float y = Float.valueOf(line.split(" ")[2]);
float z = Float.valueOf(line.split(" ")[3]);

m.normals.add(new Vector3f(x, y, z));
}else if(line.startsWith("f ")){
Vector3f vertexIndices = new Vector3f(Float.valueOf(line.split(" ")[1].split("/")[0]),
Float.valueOf(line.split(" ")[2].split("/")[0]),
Float.valueOf(line.split(" ")[3].split("/")[0]));
Vector3f normalIndices = new Vector3f(Float.valueOf(line.split(" ")[1].split("/")[2]),
Float.valueOf(line.split(" ")[2].split("/")[2]),
Float.valueOf(line.split(" ")[3].split("/")[2]));
m.faces.add(new Face(vertexIndices, normalIndices));
}
}
reader.close();

return m;
}
}

Model:

package the_wormhole;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;

import java.nio.FloatBuffer;
import java.util.ArrayList;

import org.lwjgl.BufferUtils;
import org.lwjgl.util.vector.Vector3f;

public class Model {
public ArrayList<Vector3f> vertices = new ArrayList<Vector3f>();
public ArrayList<Vector3f> normals = new ArrayList<Vector3f>();
public ArrayList<Face> faces = new ArrayList<Face>();

private FloatBuffer verticesBuffer;
private FloatBuffer normalsBuffer;

private int verticesVBO;
private int normalsVBO;

private int nrVertices = 0;

public float x = 0, y = 0, z = 0;

public static final int X_AXIS = 0, Y_AXIS = 1, Z_AXIS = 2;

public boolean isPlainFloor = false;

public Model() {
glEnable(GL_COLOR_MATERIAL);

verticesVBO = glGenBuffers();
normalsVBO = glGenBuffers();

x = 0;
y = 0;
z = 0;
}

public ArrayList<Vector3f> getVertices() {
return vertices;
}

public ArrayList<Vector3f> getNormals() {
return normals;
}

public ArrayList<Face> getFaces() {
return faces;
}

public void prepare() {
this.nrVertices = 0;

verticesBuffer = BufferUtils.createFloatBuffer(faces.size() * 9);
for (int i = 0; i < faces.size(); i++) {
Face f = faces.get(i);
Vector3f v1 = vertices.get((int) (f.getVertexIndices()[0] - 1));
verticesBuffer.put(new float[] { v1.x, v1.y, v1.z });
Vector3f v2 = vertices.get((int) (f.getVertexIndices()[1] - 1));
verticesBuffer.put(new float[] { v2.x, v2.y, v2.z });
Vector3f v3 = vertices.get((int) (f.getVertexIndices()[2] - 1));
verticesBuffer.put(new float[] { v3.x, v3.y, v3.z });
nrVertices += 3;
}
System.out.println(faces.size() * 9);
verticesBuffer.flip();
glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
glBufferData(GL_ARRAY_BUFFER, verticesBuffer, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);

normalsBuffer = BufferUtils.createFloatBuffer(faces.size() * 9);
for (int i = 0; i < faces.size(); i++) {
Face f = faces.get(i);
Vector3f v1 = normals.get((int) (f.getNormalIndices()[0] - 1));
normalsBuffer.put(new float[] { v1.x, v1.y, v1.z });
Vector3f v2 = normals.get((int) (f.getNormalIndices()[1] - 1));
normalsBuffer.put(new float[] { v2.x, v2.y, v2.z });
Vector3f v3 = normals.get((int) (f.getNormalIndices()[2] - 1));
normalsBuffer.put(new float[] { v3.x, v3.y, v3.z });
}
normalsBuffer.flip();
glBindBuffer(GL_ARRAY_BUFFER, normalsVBO);
glBufferData(GL_ARRAY_BUFFER, normalsBuffer, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}

public void draw() {
if(verticesBuffer == null)
throw new IllegalStateException("prepare() not called yet");

glMaterialf(GL_FRONT, GL_SHININESS, 128f);

glBindBuffer(GL_ARRAY_BUFFER, normalsVBO);
glNormalPointer(GL_FLOAT, 0, 0);

glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
glVertexPointer(3, GL_FLOAT, 0, 0);

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);

glDrawArrays(GL_TRIANGLES, 0, nrVertices);

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);

glBindBuffer(GL_ARRAY_BUFFER, 0);
}

public void move(int axis, float distance) {
if(verticesBuffer == null)
throw new IllegalStateException("prepare() not called yet");

switch (axis) {
case X_AXIS:
for(int i = 0 ; i < vertices.size() ; i ++){
Vector3f v = vertices.get(i);
v.x += distance;
x = v.x;
}

break;
case Y_AXIS:
for(int i = 0 ; i < vertices.size() ; i ++){
Vector3f v = vertices.get(i);
v.y += distance;
y = v.y;
}

break;
case Z_AXIS:
for(int i = 0 ; i < vertices.size() ; i ++){
Vector3f v = vertices.get(i);
v.z += distance;
z = v.z;
}

break;
default:
break;
}

verticesBuffer = BufferUtils.createFloatBuffer(faces.size() * 9);
for (int i = 0; i < faces.size(); i++) {
Face f = faces.get(i);
Vector3f v1 = vertices.get((int) (f.getVertexIndices()[0] - 1));
verticesBuffer.put(new float[] { v1.x, v1.y, v1.z });
Vector3f v2 = vertices.get((int) (f.getVertexIndices()[1] - 1));
verticesBuffer.put(new float[] { v2.x, v2.y, v2.z });
Vector3f v3 = vertices.get((int) (f.getVertexIndices()[2] - 1));
verticesBuffer.put(new float[] { v3.x, v3.y, v3.z });

nrVertices += 3;
}
verticesBuffer.flip();
glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
glBufferData(GL_ARRAY_BUFFER, verticesBuffer, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}

public void cleanUp() {
glDeleteBuffers(verticesVBO);
glDeleteBuffers(normalsVBO);
}
}

Main Class:

package the_wormhole;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.util.glu.GLU.gluPerspective;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.FloatBuffer;

import org.lwjgl.*;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.*;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;

public class WormholeMain {

private float rotationX;
private float translationX;
private float translationY;
private float translationZ;
private float rotationY;
private Vector3 walk;
private FloatBuffer fb2 = BufferUtils.createFloatBuffer(4);
private ShaderManager shaderManager;
Model m1, m2, m3, m4, m5, m6;

public WormholeMain() {
fb2.put(new float[] { -2, -2, 0, 0});
fb2.flip();

setUpDisplay();
setUp3dWorld();

walk = new Vector3(0, 0, -1);
wormhole = new Wormhole();

shaderManager = new ShaderManager();
shaderManager.loadShader(GL_VERTEX_SHADER, "shaders/vertexShader.sh");
shaderManager.loadShader(GL_FRAGMENT_SHADER, "shaders/fragmentShader.sh");
shaderManager.prepareProgram();

m1 = loadModelAndPrepare("res/right_up_floor.obj", 0, 0);
m2 = loadModelAndPrepare("res/right_up_floor.obj", 2, 0);
m3 = loadModelAndPrepare("res/right_up_floor.obj", -2, 0);
m4 = loadModelAndPrepare("res/right_up_floor.obj", 0, 2);
m5 = loadModelAndPrepare("res/right_up_floor.obj", 2, 2);
m6 = loadModelAndPrepare("res/right_up_floor.obj", -2, 2);

mainLoop();
cleanUp();
}

private void cleanUp() {
wormhole.cleanUp();
Display.destroy();
}

long thisFrame = System.currentTimeMillis(), lastFrame = System.currentTimeMillis();
float frametime;

private void mainLoop() {
lastFrame = System.currentTimeMillis();
while(!Display.isCloseRequested()){
thisFrame = System.currentTimeMillis();
frametime = (thisFrame - lastFrame) / 1000f;
lastFrame = thisFrame;

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.8f, 0.8f, 0.8f, 1);

glLight(GL_LIGHT0, GL_POSITION, fb2);

applyCamera();

shaderManager.useProgram();
m1.draw();
shaderManager.useProgram0();
shaderManager.useProgram();
m2.draw();
shaderManager.useProgram0();
shaderManager.useProgram();
m3.draw();
shaderManager.useProgram0();
shaderManager.useProgram();
m4.draw();
shaderManager.useProgram0();
shaderManager.useProgram();
m5.draw();
shaderManager.useProgram0();
shaderManager.useProgram();
m6.draw();
shaderManager.useProgram0();

Display.update();
Display.sync(60);
}
}

private void setUp3dWorld() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30, 800f/600f, 0.001f, 100);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_TEXTURE_2D);
glEnable(GL_TRIANGLE_FAN);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);

FloatBuffer fb1 = BufferUtils.createFloatBuffer(4);
fb1.put(new float[] { 0.05f, 0.05f, 0.05f, 1 });
fb1.flip();

glLightModel(GL_LIGHT_MODEL_AMBIENT, fb1);
glLight(GL_LIGHT0, GL_POSITION, fb2);

glRotatef(-25f, 0, 1, 0);
glRotatef(30f, 1, 0, 0);
glTranslatef(-1.5f, -2.1f, -0.55f);
}

private void setUpDisplay() {
try {
Display.setDisplayMode(new DisplayMode(800, 600));
Display.setTitle("The Wormhole");
Display.setVSyncEnabled(true);
Display.create();
} catch (LWJGLException e) {
e.printStackTrace();
}
}

public static void main(String[] args) {
new WormholeMain();
}

private Model loadModelAndPrepare(String path, float xdistance, float zdistance){
Model m = null;
try {
m = OBJLoader.loadModel(new File(path));
} catch (FileNotFoundException e) {
e.printStackTrace();
return m;
} catch (IOException e) {
e.printStackTrace();
return m;
}
m.prepare();
m.move(Model.X_AXIS, xdistance);
m.move(Model.Z_AXIS, zdistance);
if(path.equals("res/plain_floor.obj"))
m.isPlainFloor = true;
return m;
}
}


Thanks for your help ...  ;D ;D
Title: Re: Using VBO 3d Models makes strange triangles at wrong places
Post by: Oebele on March 31, 2014, 18:41:52
Pics or it didn't happen ;-)

Just a wild guess: shouldn't you be using indexed drawing?
Title: Re: Using VBO 3d Models makes strange triangles at wrong places
Post by: Sumec99 on April 01, 2014, 05:15:51
I'm sorry but I don't understand  the first sentence "Pics or it didn't happen" of your answer because English isn't my first language ... Sorry for that
And , what is indexed drawing ?
Title: Re: Using VBO 3d Models makes strange triangles at wrong places
Post by: Oebele on April 01, 2014, 15:55:03
With "Pics or it didn't happen" I meant to say: "please post some pictures, so we can actually see what is wrong".

for indexed drawing, look at this page: http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-9-vbo-indexing/ or this one:
Title: Re: Using VBO 3d Models makes strange triangles at wrong places
Post by: Sumec99 on April 01, 2014, 18:10:56
Ok, thanks for the description ...
2 screenshots are attached
Title: Re: Using VBO 3d Models makes strange triangles at wrong places
Post by: matanui159 on April 15, 2014, 00:33:34
May I see the .obj file? I believe I have an idea...

You store your vertices in an array which (because of java) starts at zero. So when the face requests vertex 1 it is requesting (according to your code) the second vertex. But the .obj file might be starting at one so when a face requests vertex 1 it wants the first vertex but your code is giving it the second vertex.

Also how did you show a working version if it is not working?
Title: Re: Using VBO 3d Models makes strange triangles at wrong places
Post by: matanui159 on April 15, 2014, 00:43:43
Actually nevermind... I just realised you are already subtracting one from it so it should work unless your .obj file starts at zero (to find out search it using your text editor for a 0/ or a /0). Try another model like the Utah teapot of Stanford bunny and post the results because your current model ( whatever it is) doesn't really like anything and it is hard to tell what is going on...
Title: Re: Using VBO 3d Models makes strange triangles at wrong places
Post by: Sumec99 on May 12, 2014, 17:34:51
The matter ifs , if I just want to display Model, everything is fine, but if there are 2 or 3 models (or more) it's messed up
(Sorry that I have not written these days, I just haven't seen the new answer after 2 weeks)