Hi,
I'm a beginner with LWJGL and I'm stuck trying to port some C++ code. Instead of a vague question I made the smallest possible program illustrating the problem (mainly init code but still 150 lines, sorry!). the program attempts to create two VBOs (one for vertex data and one for index data), maps them to memory, fills them up (with interleaved data in the vertex buffer), and displays them. There is a native crash somewhere and I haven't got a clue as to how to pinpoint the issue. Maybe the issue comes from the interleaved data being incorrectly described in the gl***Pointer() functions, or maybe the buffers are in a bad state (position, limit...), I can't really tell. The VBO describes a single triangle to be displayed.
There is a switch in the rendering loop to replace VBO rendering with immediate mode with the same vertex data, just to show what the result should be like.
import java.nio.ByteBuffer;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.ARBVertexBufferObject;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GLContext;
import org.lwjgl.util.glu.GLU;
public class VBOTest
{
public static void main(String [] args)
{
//init display
Display.setTitle("vbo test");
try
{
DisplayMode mode = new DisplayMode(800, 600);
Display.setDisplayMode(mode);
Display.setFullscreen(true);
Display.create();
}
catch (LWJGLException e)
{
e.printStackTrace();
System.exit(0);
}
//init OpenGL
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);//_MINUS_SRC_ALPHA);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glFrustum(-1, 1, -1, 1, 1, 1000);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();
GLU.gluLookAt(0, 10, 0, 0, 0, 0, 0, 0, 1);
if (!GLContext.getCapabilities().GL_ARB_vertex_buffer_object)
throw new RuntimeException("VBOs unsupported");
//Create two VBO ids, one for vertice data and one for index data
int dataVboId = ARBVertexBufferObject.glGenBuffersARB();
int indexVboId = ARBVertexBufferObject.glGenBuffersARB();
//The vertex buffer will contain interleaved data :
// -3d vertex (in doubles)
// -3d normal (in doubles)
// -RGBA color (in floats)
//Get the size of primitive types in bytes
int intSize = Integer.SIZE/8;
int floatSize = Float.SIZE/8;
int doubleSize = Double.SIZE/8;
//Get the size of a 3d vector (in doubles) and RGBA color (in floats)
int verticeSize = 3*doubleSize;
int normalSize = 3*doubleSize;
int colorSize = 4*floatSize;
//Get the size of an element
int elementSize = verticeSize+normalSize+colorSize;
//Allocate the vertex buffer for three elements (to test displaying a triangle)
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, dataVboId);
ARBVertexBufferObject.glBufferDataARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB,
elementSize*3, ARBVertexBufferObject.GL_STATIC_DRAW_ARB);
//Map the vertex buffer to a ByteBuffer
ByteBuffer dataBuffer = ARBVertexBufferObject.glMapBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB,
ARBVertexBufferObject.GL_WRITE_ONLY_ARB, elementSize*3, null);
//write vertex {5,0,5}, normal {0,1,0}, color {0,0,1,1}
dataBuffer.putDouble(5); dataBuffer.putDouble(0); dataBuffer.putDouble(5);
dataBuffer.putDouble(0); dataBuffer.putDouble(1); dataBuffer.putDouble(0);
dataBuffer.putFloat(0).putFloat(0).putFloat(1).putFloat(1);
//write vertex {-5,0,5}, normal {0,1,0}, color {0,0,1,1}
dataBuffer.putDouble(-5); dataBuffer.putDouble(0); dataBuffer.putDouble(5);
dataBuffer.putDouble(0); dataBuffer.putDouble(1); dataBuffer.putDouble(0);
dataBuffer.putFloat(0).putFloat(0).putFloat(1).putFloat(1);
//write vertex {-5,0,-5}, normal {0,1,0}, color {0,0,1,1}
dataBuffer.putDouble(-5); dataBuffer.putDouble(0); dataBuffer.putDouble(-5);
dataBuffer.putDouble(0); dataBuffer.putDouble(1); dataBuffer.putDouble(0);
dataBuffer.putFloat(0).putFloat(0).putFloat(1).putFloat(1);
//flip buffer for reading
dataBuffer.flip();
//unmap and unbind
ARBVertexBufferObject.glUnmapBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB);
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, 0);
//Allocate the index buffer for three elements (they will point to the three elements above)
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, indexVboId);
ARBVertexBufferObject.glBufferDataARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB,
intSize*3, ARBVertexBufferObject.GL_STATIC_DRAW_ARB);
//Map the index buffer to a ByteBuffer
ByteBuffer indexBuffer = ARBVertexBufferObject.glMapBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB,
ARBVertexBufferObject.GL_WRITE_ONLY_ARB, intSize*3, null);
//Write the indexes and flip
indexBuffer.putInt(0).putInt(1).putInt(2);
indexBuffer.flip();
//unmap and unbind
ARBVertexBufferObject.glUnmapBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB);
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
boolean useVbos = true;
while (!Keyboard.isKeyDown(Keyboard.KEY_ESCAPE))
{
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
if (useVbos)
{
//enable the arrays
GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glEnableClientState(GL11.GL_NORMAL_ARRAY);
GL11.glEnableClientState(GL11.GL_COLOR_ARRAY);
//bind the vertex buffer and the index buffer
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, dataVboId);
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, indexVboId);
//the vertex pointer has an offset of 0 and a stride of elementSize
GL11.glVertexPointer(3, GL11.GL_DOUBLE, elementSize, 0);
//the normal pointer has an offset of verticeSize and a stride of elementSize
GL11.glNormalPointer(GL11.GL_DOUBLE, elementSize, verticeSize);
//the color pointer has an offset of (verticeSize+normalSize) and a stride of elementSize
GL11.glColorPointer(4, GL11.GL_FLOAT, elementSize, verticeSize+normalSize);
//Draw the triangle with three indexes (with 0 offset in the index buffer)
GL11.glDrawElements(GL11.GL_TRIANGLES, 3, GL11.GL_UNSIGNED_INT, 0);
//unbind the buffers
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, 0);
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
//disable the arrays
GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glDisableClientState(GL11.GL_NORMAL_ARRAY);
GL11.glDisableClientState(GL11.GL_COLOR_ARRAY);
}
else
{
GL11.glColor4f(0, 0, 1, 1);
GL11.glBegin(GL11.GL_TRIANGLES);
GL11.glNormal3d(0, 1, 0);
GL11.glVertex3d(5, 0, 5);
GL11.glVertex3d(-5, 0, 5);
GL11.glVertex3d(-5, 0, -5);
GL11.glEnd();
}
Display.update();
}
}
}
If there is anyone who would be kind a enough to take a few minutes and try to see what is wrong I would greatly appreciate. Or to point me to some tutorial would be nice too (I tried the wiki tutorial on VBOs, but it's a little cryptic).
Thanks
Hey schmiley,
The problem is that the ByteBuffer that glMapBuffer returns when the old_buffer parameter is null has the default BIG_ENDIAN order. I have fixed this and will commit soon. Until then, you can workaround this by doing a .order(ByteOrder.nativeOrder()) before using the mapped buffer.
works fine now, thanks alot :)
This has been committed now, you can test it with the next nightly build (https://www.newdawnsoftware.com/hudson/view/LWJGL/).
Hi!
Sorry, but I not understand. Help me, please
Thanks
p.s. Sorry my english T_T
yes
how(where) use .order(ByteOrder.nativeOrder()) ?
create a Buffer like this :
public static ByteBuffer createByteBuffer ( int size )
{
return ByteBuffer.allocateDirect ( size ).order ( ByteOrder.nativeOrder () );
}
.. and it should work :)