I am so angry at my file reading skills

I’m trying to load an Obj file (3d model file) for OGL.
The entire concept behind it is really easy in conjunction with regex.
The problem is how would I make regex include negative numbers?

However take a look at my console output:

1.0, 1.0, 1.0
1.0, 1.0, 1.0
1.0, 1.0, 1.0
1.0, 1.0, 1.0
1.0, 1.0, 1.0
1.0, 1.0, 1.0
1.0, 1.0, 1.0
1.0, 1.0, 1.0
1, 3, 4, 2
5, 7, 8, 6
1, 5, 6, 2
3, 7, 8, 4
1, 5, 7, 3
2, 6, 8, 4

Now take a look at the file:

v 1 1 1
v 1 1 -1
v 1 -1 1
v 1 -1 -1
v -1 1 1
v -1 1 -1
v -1 -1 1
v -1 -1 -1
f 1 3 4 2
f 5 7 8 6
f 1 5 6 2
f 3 7 8 4
f 1 5 7 3
f 2 6 8 4

The negative values don’t appear.

Here is my loader code:
http://members.optusnet.com.au/ksaho/algorithm/ObjLoader.java

It’s obviously unoptimised because I’m focusing on getting it to work before performance.
Also is there any way that I could go from (Float[]) to (float[]) without using loops?

this should help:
http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/Pattern.html

maybe your regex should look like this? :


String regex = "\\-?[0-9]+";

Arne

Thanks.
Regex is one of those things that just blow my mind.

It’s working fully except for the vertex arrays are causing the JVM to crash.
I’ll look into that later.

Isn’t regex a bit heavyweight for such a simple file format? I’d have thought a StringTokenizer would be more appropriate.

Cas :slight_smile:

I thought that was deprecated?

“\-?[0-9]+”
You call that simple? With a tokenizer you’d get lots of if-cases! Now java is doing all the stuff for you!
But actually I don’t know for what to use the regex of the numbers. I’d simply call split(" ") every line.

I should let you guys know I’ve found a good way of doing it.

private void checkStore(String line)
	{
		scanner = new Scanner(line);
		
		if(Pattern.matches("^(.*)" + "v(.*)" + "(\\d+)" + "(.*)$", line))
		{
			scanner.next();
			verts.add(scanner.nextFloat());
			verts.add(scanner.nextFloat());
			verts.add(scanner.nextFloat());
		}
		else if(Pattern.matches("^(.*)" + "f(\\s*)" + "(\\d+)" + "(.*)$", line))
		{
			scanner.next();
			indx.add(scanner.nextInt());
			indx.add(scanner.nextInt());
			indx.add(scanner.nextInt());
			indx.add(scanner.nextInt());
		}
		
		scanner.close();
	}

I broke down the amount of code by 3x at least.
Now if only JOGL would stop crashing the VM.

EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x690c17dc, pid=696, tid=3240

Java VM: Java HotSpot™ Client VM (1.5.0_04-b05 mixed mode, sharing)

Problematic frame:

C [atioglxx.dll+0xc17dc]

If anyone’s interested here’s the error log:
http://members.optusnet.com.au/ksaho/dumb/hs_err_pid696.log

Vertex array call:

public void renderGeneric(GL gl, GLU glu, ModelData entity)
	{
		gl.glVertexPointer(entity.getNoOfCoords(), GL.GL_FLOAT, 0, entity.getVertices());
		
		if(entity.getTexCoords() != null)
		{
			gl.glBindTexture(GL.GL_TEXTURE_2D, entity.getTextureID());
			gl.glTexCoordPointer(entity.getNoOfTexCoords(), GL.GL_FLOAT, 0, entity.getTexCoords());
		}
		
		if(entity.getColours() != null)
			gl.glColorPointer(entity.getNoOfColorCoords(), GL.GL_FLOAT, 0, entity.getColours());
		
		gl.glDrawElements(
				GL.GL_POLYGON,
				entity.getIndicies().length,
				GL.GL_UNSIGNED_INT,
				entity.getIndicies()
		);
	}

Draw elements is the one that causes a crash.
I also debugged my program and the inputs have correct values.

Are you sure you did flip/clear/rewind your Buffers?

Did you enable the correct “vertex-array” states in OpenGL?

Yes, yes, yes and finally yes.

this.noOfVertexCoords = (vertex.length % 3 == 0) ? 3 : 2;
		this.indices = index;
		this.texID = texID;
		
		this.vertices = BufferUtils.newFloatBuffer(vertex.length);
		this.vertices.put(vertex);
		this.vertices.rewind();
		
		if(colours != null)
		{
			this.noOfColorCoords = (colours.length % 3 == 0) ? 3 : 4;
			this.colours = BufferUtils.newFloatBuffer(colours.length);
			this.colours.put(colours);
			this.colours.rewind();
		}
		
		if(texCoords != null)
		{
			this.noOfTexCoords = (texCoords.length  % 3) == 0 ? 3 : 2;
			this.texCoords = BufferUtils.newFloatBuffer(texCoords.length);
			this.texCoords.put(texCoords);
			this.texCoords.rewind();
		}
gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
		gl.glEnableClientState(GL.GL_COLOR_ARRAY);
		gl.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY);

in OBJ format the indices are one-based (1,2,3,4,5, etc)
in OpenGL the indices are zero-based (0,1,2,3,4, etc)

So the highest index (8 in this case) grabs a piece of RAM that doesn’t belong to the buffer.
Just substract 1 from all your indices.

Further I’d suggest you use GL_QUADS instead of GL_POLYGON, otherwise everything is rendered as 1 polygon.

Thanks. Although the problem associated with glDrawElements is still there.

In case you want even more useful feedback, try composing a SSCCE.

Also you should not have GL.GL_COLOR_ARRAY (or any of the others) enabled, when you are not setting a pointer to it (when that buffer is null and you skip it)

Thanks. It’s fixed. :slight_smile:
Now I just have a black screen. :stuck_out_tongue:

EDIT: Fixed it, scaled the giant thing back.
BTW What’s wrong with making a model a single polygon? Isn’t that faster?

Thanks for help buddy.
I’m now doing this:

gl.glVertexPointer(entity.getNoOfCoords(), GL.GL_FLOAT, 0, entity.getVertices());
		
		if(entity.getTexCoords() != null)
		{
			gl.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY);
			
			gl.glBindTexture(GL.GL_TEXTURE_2D, entity.getTextureID());
			gl.glTexCoordPointer(entity.getNoOfTexCoords(), GL.GL_FLOAT, 0, entity.getTexCoords());
		}
		else
			gl.glDisableClientState(GL.GL_TEXTURE_COORD_ARRAY);
		
		if(entity.getColours() != null)
		{
			gl.glEnableClientState(GL.GL_COLOR_ARRAY);
			gl.glColorPointer(entity.getNoOfColorCoords(), GL.GL_FLOAT, 0, entity.getColours());
		}
		else
			gl.glDisableClientState(GL.GL_COLOR_ARRAY);
		
		gl.glDrawElements
		(
				GL.GL_QUADS,
				entity.getIndicies().capacity(),
				GL.GL_UNSIGNED_INT,
				entity.getIndicies()
		);

A GL_POLYGON must not have “intersecting borders” / “overlapping pixels” and IIRC should be roughly planar. That pretty much makes it useless for anything 3D or anything semi-complex in 2D.

Further, you should sort your entities so that you need fewer client-state-changes, because they are very expensive.

I have the feeling you never have both TEXCOORD and COLOR enabled at the same time, so you might want to do:

  1. setup states (enable GL_TEXTURE_2D ?)
  2. render entities with Vertex + Texcoords
  3. change states (disable GL_TEXTURE_2D ?)
  4. render entities with Vertex + Colors

Using regex (or String.split for that matter) takes more than twice as long (compared to StringTokenizer).

You can find a working obj loader here:
http://lwjgl.org/forum/viewtopic.php?t=917

On page two you can see my modifications, which speeded it up a lot. However, loading a format like obj will be always a lot slower than loading some java-flavoured dump-format.

Even StringTokenizer is pretty slow compared to writing your own scanner.

Cas :slight_smile:

Why is that? I mean when writing your own scanner you’ll probably don’t implement searching improvements like Boyer-Moore (The algorithm should be implemented in StringTokenizer). Or how would I be able to speed things up?

Because with such an utterly simple problem domain as an obj file you can directly optimize it to work as fast as possible. And there aren’t many optimizations to do either so it’s not quite as hard as it looks.

Cas :slight_smile: