Obj mesh does not render correctly - android

I have a problem with the rendering of a cube. I don't know why but it isn't correct.
Here are two images of the "cube":
Front:
Back:
Here's the OpenGL code:
Vertices, faces, colors..
private void initTriangle() {
float[] coords = {
-0.5f, 0.f, 0.5f,
-0.5f, 0.f, -0.5f,
0.5f, 0.f, -0.5f,
0.5f, 0.f, 0.5f,
-0.5f, 1.f, 0.5f,
0.5f, 1.f, 0.5f,
0.5f, 1.f, -0.5f,
-0.5f, 1.f, -0.5f,
};
_nrOfVertices = coords.length;
float[] colors = {
1f, 0f, 0f, 1f, // point 1 red
0f, 1f, 0f, 1f, // point 2 green
0f, 0f, 1f, 1f, // point 3 blue
1f, 1f, 1f, 1f, // point 4 white
1f, 1f, 1f, 1f, // point 5 white
1f, 0f, 0f, 1f, // point 6 white
1f, 1f, 1f, 1f, // point 7 white
1f, 1f, 1f, 1f, // point 8 white
1f, 0f, 0f, 1f, // point 9 white
1f, 1f, 1f, 1f, // point 10 white
1f, 1f, 1f, 1f, // point 11 white
1f, 1f, 1f, 1f, // point 12 white
};
short[] indices = new short[] {
1, 2, 3, // 1
3, 4, 1, // 2
5, 6, 7, // 3
7, 8, 5, // 4
1, 4, 6, // 5
6, 5, 1, // 6
4, 3, 7, // 7
7, 6, 4, // 8
3, 2, 8, // 9
8, 7, 3, // 10
2, 1, 5, // 11
5, 8, 2, // 12
};
// float has 4 bytes, coordinate * 4 bytes
ByteBuffer vbb = ByteBuffer.allocateDirect(coords.length * 4);
vbb.order(ByteOrder.nativeOrder());
_vertexBuffer = vbb.asFloatBuffer();
// short has 2 bytes, indices * 2 bytes
ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
ibb.order(ByteOrder.nativeOrder());
_indexBuffer = ibb.asShortBuffer();
// float has 4 bytes, colors (RGBA) * 4 bytes
ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4);
cbb.order(ByteOrder.nativeOrder());
_colorBuffer = cbb.asFloatBuffer();
_vertexBuffer.put(coords);
_indexBuffer.put(indices);
_colorBuffer.put(colors);
_vertexBuffer.position(0);
_indexBuffer.position(0);
_colorBuffer.position(0);
}
Rendering:
public void onDrawFrame(GL10 gl) {
//gl.glFrontFace(GL10.GL_CCW);
gl.glClearColor(0f, 0f, 0f, 1.0f);
gl.glLoadIdentity();
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
// set rotation
gl.glRotatef(_xAngle, 1f, 0f, 0f);
gl.glRotatef(_yAngle, 0f, 1f, 0f);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBuffer);
gl.glColorPointer(4, GL10.GL_FLOAT, 0, _colorBuffer);
gl.glDrawElements(GL10.GL_TRIANGLES, _nrOfVertices, GL10.GL_UNSIGNED_SHORT, _indexBuffer);
gl.glFrontFace(GL10.GL_CCW);
}
here the obj content:
# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware
# File Created: 19.02.2012 13:31:12
mtllib box22.mtl
#
# object Box01
#
v -0.5000 0.0000 0.5000
v -0.5000 0.0000 -0.5000
v 0.5000 0.0000 -0.5000
v 0.5000 0.0000 0.5000
v -0.5000 1.0000 0.5000
v 0.5000 1.0000 0.5000
v 0.5000 1.0000 -0.5000
v -0.5000 1.0000 -0.5000
# 8 vertices
vn 0.0000 -1.0000 -0.0000
vn 0.0000 1.0000 -0.0000
vn 0.0000 0.0000 1.0000
vn 1.0000 0.0000 -0.0000
vn 0.0000 0.0000 -1.0000
vn -1.0000 0.0000 -0.0000
# 6 vertex normals
vt 1.0000 0.0000 0.0000
vt 1.0000 1.0000 0.0000
vt 0.0000 1.0000 0.0000
vt 0.0000 0.0000 0.0000
# 4 texture coords
g Box01
usemtl wire_177088026
f 1/1/1 2/2/1 3/3/1
f 3/3/1 4/4/1 1/1/1
f 5/4/2 6/1/2 7/2/2
f 7/2/2 8/3/2 5/4/2
f 1/4/3 4/1/3 6/2/3
f 6/2/3 5/3/3 1/4/3
f 4/4/4 3/1/4 7/2/4
f 7/2/4 6/3/4 4/4/4
f 3/4/5 2/1/5 8/2/5
f 8/2/5 7/3/5 3/4/5
f 2/4/6 1/1/6 5/2/6
f 5/2/6 8/3/6 2/4/6
# 12 faces
Hope you can help me.
Thank for your attention (:

Make sure your indices are correct.
The OBJ format starts counting with indices at 1. However, the actual indexing within your array will start at 0. So you will have to subtract 1 from each index within the OBJ file for it to work as you expect.

Related

OpenGL ES Lighting (Matrix And/Or Normals issue)

I'm trying to add per vertex lighting in OpenGL ES and I'm encountering strange problems for which I didn't find solution.
I first used Android documentation to create shapes :
http://developer.android.com/training/graphics/opengl/index.html
Then I used learn opengl es to add lightinh :
http://www.learnopengles.com/android-lesson-two-ambient-and-diffuse-lighting/
So here is the code of my renderer :
#Override
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
// Set the background frame color
GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
// Enable depth testing
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
float[] coords = new float[]{
-0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
0.5f , 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
0.5f , 0.5f, 0.5f
};
short[] drawOrder = new short[]{
0,1,2,
0,2,3,
4,5,6,
4,6,7,
};
float[] normals = new float[]{
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
};
float[] colors = new float[]{
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
};
testSolid = new Solid(coords, drawOrder, colors, normals);
}
public void onDrawFrame(GL10 unused) {
float[] lightPos = new float[]{0.5f, 0.5f, -0.5f, 1.0f};
// Redraw background color
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
// Set the camera position (View matrix)
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -5.0f, 0f, 0f, 0f, 0f, 2.0f, 0.0f);
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.multiplyMM(mVMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
Matrix.setIdentityM(mLightModelMatrix, 0);
Matrix.multiplyMV(mLightPosInWorldSpace, 0, mLightModelMatrix, 0, lightPos, 0);
Matrix.multiplyMV(mLightPosInEyeSpace, 0, mVMatrix, 0, mLightPosInWorldSpace, 0);
Matrix.setRotateM(mRotationMatrix, 0, mAngle, 1.0f, 0.0f, 0.0f);
// Calculate the projection and view transformation
Matrix.multiplyMM(mLightMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
// Combine the rotation matrix with the projection and camera view
Matrix.multiplyMM(mMVPMatrix, 0, mRotationMatrix, 0, mLightMatrix, 0);
// Draw shape
testSolid.draw(mVMatrix, mMVPMatrix, mLightPosInEyeSpace);
}
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
// this projection matrix is applied to object coordinates
// in the onDrawFrame() method
Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
Then, my code for the Solid :
First, my program :
private final String vertexShaderCode =
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
"uniform mat4 uMVPMatrix;" +
"uniform mat4 uMVMatrix;"+
"uniform vec3 uLightPos;"+
"attribute vec3 aNormal;" +
"attribute vec4 aColor;" +
"attribute vec4 aPosition;" +
"varying vec4 vColor;" +
"void main() {" +
// the matrix must be included as a modifier of gl_Position
" vec3 modelViewVertex = vec3(uMVMatrix * aPosition);"+
" vec3 modelViewNormal = vec3(uMVMatrix * vec4(aNormal, 0.0));"+
" float distance = length(uLightPos - modelViewVertex);"+
" vec3 lightVector = normalize(uLightPos - modelViewVertex);"+
" float diffuse = max(dot(modelViewNormal, lightVector), 0.1);"+
" diffuse = diffuse * (1.0 / (1.0 + (0.25 * distance * distance)));"+
" vColor = aColor * diffuse;"+
" gl_Position = aPosition * uMVPMatrix;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"varying vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
And my draw function :
public void draw(float[] mvMatrix, float[] mvpMatrix, float[] lightPos) {
// Add program to OpenGL ES environment
GLES20.glUseProgram(mProgram);
// Positions
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, DATA_PER_VERTEX,
GLES20.GL_FLOAT, false,
0, vertexBuffer);
CubeRenderer.checkGlError(String.format("Positions (%d)", mPositionHandle));
// Colors
mColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor");
GLES20.glEnableVertexAttribArray(mColorHandle);
GLES20.glVertexAttribPointer(mColorHandle, 4,
GLES20.GL_FLOAT, false,
0, colorBuffer);
CubeRenderer.checkGlError(String.format("Colors (%d)", mColorHandle));
// Normals
mNormalHandle = GLES20.glGetAttribLocation(mProgram, "aNormal");
GLES20.glVertexAttribPointer(mNormalHandle, 3,
GLES20.GL_FLOAT, false,
0, normalBuffer);
GLES20.glEnableVertexAttribArray(mNormalHandle);
CubeRenderer.checkGlError(String.format("Normals (%d)", mColorHandle));
// get handle to shape's transformation matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
CubeRenderer.checkGlError("glGetUniformLocation");
mMVMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVMatrix");
CubeRenderer.checkGlError("glGetUniformLocation");
mLightPosHandle = GLES20.glGetUniformLocation(mProgram, "uLightPos");
CubeRenderer.checkGlError("glGetUniformLocation");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mvMatrix, 0);
GLES20.glUniform3f(mLightPosHandle, lightPos[0], lightPos[1], lightPos[2]);
CubeRenderer.checkGlError("glUniformMatrix4fv");
// Draw the polygon
GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
But, when I run it, I have very strange result.
First, light is very dim, and not in good place
Second, I have a rotation with touch event, and if I rotate my shape, the light will also rotate.
May you know where this issue comes from ?
Thank you.

2d Triangle with OpenGL ES 2.0

EDIT 2: Take a look on the Triangle2d sample of this GitHub project for a complete, working sample.
EDIT: See the accepted answer for a link with a good explanation on how the ortographic matrix works. In the end, I tweaked the provided code a little:
float[] mvp = {
2f/width, 0f, 0f, 0f,
0f, -2f/height, 0f, 0f,
0f, 0f, 0f, 0f,
-1f, 1f, 0f, 1f
};
Please note that my z is fixed in 0 and w fixed in 1. This matrix make the origin (0,0) at the bottom-left of the screen; if you want the origin at top-left, try:
float[] mvp = {
2f/width, 0f, 0f, 0f,
0f, 2f/height, 0f, 0f,
0f, 0f, 0f, 0f,
-1f, -1f, 0f, 1f
};
Another problem was the call to GLES20.glUniformMatrix4fv which I changed to:
FloatBuffer b = ByteBuffer.allocateDirect(mvp.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
b.put(mvp).position(0);
GLES20.glUniformMatrix4fv(uMvpPos, b.limit() / mvp.length, false, b);
If you want to mess with this a bit, try this online calculator. Just remember that the rows in your sorce file will be columns in the calculator.
Original Problem:
I'm trying to draw a 2d triangle using OpenGLES 2.0 on android, but so far, not much success. These are my shaders:
(Vertex shader)
uniform mat4 uMvp;
attribute vec3 aPosition;
attribute vec3 aColor;
varying vec4 vColor;
void main() {
vColor = vec4(aColor.xyz, 1.0);
vec4 position = vec4(aPosition.xyz, 1.0);
gl_Position = uMvp * position;
};
(Fragment shader)
precision mediump float;
varying vec4 vColor;
void main(void)
{
gl_FragColor = vColor;
};
Then, in the onSurfaceChanged method of GLSurfaceView.Renderer, I put the following:
public void onSurfaceChanged(GL10 gl, int width, int height)
{
// here I load and compile the shaders and link the program.
// in the end, I use GLES20.glUseProgram(programHandle);
// (code omitted)
// create the matrix for the uniform
int uMvpPos = GLES20.glGetUniformLocation(programHandle, "uMvp");
float[] mvp = {width, 0f, 0f, 0f,
0f, -height, 0f, 0f,
0f, 0f, -2f, 0f,
-1f, 1, -1f, 1};
GLES20.glUniformMatrix4fv(uMvpPos, mvp.length * 4, false, mvp, 0);
// set viewport and clear color to white
GLES20.glViewport(0, 0, width, height);
GLES20.glClearColor(1f, 1f, 1f,1.0f);
}
I used the values of the matrix showed on this question. My intent here is to work with coordinates in the same way as a canvas works: (0,0) on top-left of screen and (width, height) on bottom-right.
And last but not least, this is the code of onDrawFrame:
public void onDrawFrame(GL10 gl)
{
int aPos = GLES20.glGetAttribLocation(programHandle,"aPosition");
int aColor = GLES20.glGetAttribLocation(programHandle,"aColor");
// assuming I correctly set up my coordinate system,
// these are the triangle coordinates and color
float[] data =
{
// XYZ, RGB
100f, 100f, 0f,
1f, 0f, 0f,
50f, 50f, 0f,
1f, 0f, 0f,
150f, 50f, 0f,
1f, 0f, 0f,
};
// put all my data into a float buffer
// the '* 4' is because a float has 4 bytes
FloatBuffer dataVertex = ByteBuffer.allocateDirect(data.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
dataVertex.put(data).position(0);
// set the POSITION values
// attribute, dataSize(number of elements), data type, normalized?, size(bytes), data
GLES20.glEnableVertexAttribArray(aPos);
GLES20.glVertexAttribPointer(aPos, 3, GLES20.GL_FLOAT, false, 6 * 4, dataVertex);
// set the COLOR values
dataVertex.position(3); // offset
GLES20.glEnableVertexAttribArray(aColor);
GLES20.glVertexAttribPointer(aColor, 3, GLES20.GL_FLOAT, false, 6 * 4, dataVertex);
// put a white background
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
// and finally draw the triangle!
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
}
The end result is... a boring white screen, without the triangle. I guess I'm committing a very simple mistake, but I just can't spot it. Any thoughts?
Your orthographic projection matrix is wrong.
Orthographic projection is defined as (in column major order):
2/(r-l), 0, 0, 0,
0, 2/(t-b), 0, 0,
0, 0, 2/(f-n), 0,
(r+l)/(l-r), (t+b)/(b-t), (f+n)/(n-f), 1
In your case r=0, l=width, t=height, b=0, f=1, n=0 and you get:
-2/width, 0, 0, 0,
0, 2/height, 0, 0,
0, 0, 2, 0,
1, -1, -1, 1

OpenGL drawing a Hexigon with vertices

Im trying to make a basic shape ( Hexigon ) to start and learn some basics about OpenGL on the Android platform and i have a little problem.
I have successfully made a pointy Hexagon, but when i convert it into a flat Hexygon it doesnt render correctly. Here is some code, for you guys to figure out the problem ( probably a easy fix.. )
vertices / indices
//flat hexagon
private float verticesFlat[] = {
0.0f, 0.0f, 0.0f, //center
-0.5f, 1.0f, 0.0f, // left top
0.5f, 1.0f, 0.0f, // right top
1.0f, 0.0f, 0.0f, // right
0.5f, 1.0f, 0.0f, // right bottom
-0.5f, -1.0f, 0.0f, // left bottom
-1.0f, 0.0f, 0.0f, // left
};
private short[] indices = { 0, 1, 2, 3, 4, 5, 6, 1 };
standard vertex / index Buffers..
// a float is 4 bytes, therefore we multiply the number if
// vertices with 4.
ByteBuffer vbb = ByteBuffer.allocateDirect(verticesFlat.length * 4);
vbb.order(ByteOrder.nativeOrder());
vertexBuffer = vbb.asFloatBuffer();
vertexBuffer.put(verticesFlat);
vertexBuffer.position(0);
// short is 2 bytes, therefore we multiply the number if
// vertices with 2.
ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
ibb.order(ByteOrder.nativeOrder());
indexBuffer = ibb.asShortBuffer();
indexBuffer.put(indices);
indexBuffer.position(0);
The onDraw(GL10 gl):
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glDrawElements(GL10.GL_TRIANGLE_FAN, indices.length, GL10.GL_UNSIGNED_SHORT, indexBuffer);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
The result im getting is illustrated in the image below:
Should be
private float verticesFlat[] = {
0.0f, 0.0f, 0.0f, //center
-0.5f, 1.0f, 0.0f, // left top
0.5f, 1.0f, 0.0f, // right top
1.0f, 0.0f, 0.0f, // right
0.5f, -1.0f, 0.0f, // right bottom (notice sign)
-0.5f, -1.0f, 0.0f, // left bottom
-1.0f, 0.0f, 0.0f, // left
};

Need help understanding glDrawElements for GLES 2.0

I'm trying to learn OpenGL ES 2.0 for Android, but I am finding it hard to locate good introduction tutorials... I found This, but it only explains "glDrawArrays" and not "glDrawElements"... I'm trying to convert code from my model loading class ES 1.1, but I feel that drawing arrays might be too slow...
So what I'm asking is how would I convert the following to work in ES 2.0?
How an object is stored (seems to be fine):
private ShortBuffer SindexBuffer;
private FloatBuffer SvertexBuffer;
private FloatBuffer StexBuffer;
private void initSprite()
{
float[] fcol = {1,1,1,1};
float[] coords = {
0.5f, 0.5f, 0f,
-0.5f, 0.5f, 0f,
0.5f, -0.5f, 0f,
-0.5f, -0.5f, 0f
};
short[] index = {
0,1,2,
1,3,2
};
float[] texCoords ={
0,1,
1,1,
0,0,
1,0
};
//float has 4 bytes
ByteBuffer vbb = ByteBuffer.allocateDirect(coords.length * 4);
vbb.order(ByteOrder.nativeOrder());
SvertexBuffer = vbb.asFloatBuffer();
ByteBuffer tC = ByteBuffer.allocateDirect(texCoords.length * 4);
tC.order(ByteOrder.nativeOrder());
StexBuffer = tC.asFloatBuffer();
StexBuffer.put(texCoords);
StexBuffer.position(0);
//short has 2 bytes
ByteBuffer ibb = ByteBuffer.allocateDirect(index.length*2);
ibb.order(ByteOrder.nativeOrder());
SindexBuffer = ibb.asShortBuffer();
SvertexBuffer.put(coords);
SindexBuffer.put(index);
SvertexBuffer.position(0);
SindexBuffer.position(0);
ByteBuffer fbb = ByteBuffer.allocateDirect(fcol.length * 4);
fbb.order(ByteOrder.nativeOrder());
}
And how it is drawn (this is where I need help):
public void drawSprite(GL10 gl, int tex)
{
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glBindTexture(GL10.GL_TEXTURE_2D, tex);
//defines the vertices we want to draw
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, SvertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, StexBuffer);
//Draw the vertices
gl.glDrawElements(GL10.GL_TRIANGLES, 6, GL10.GL_UNSIGNED_SHORT, SindexBuffer);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}
(though the texture part isn't that important yet... not up to that yet).
Thanks to anyone who can help... oh, and does anyone know any simple introductions to ES 2.0 for Android aimed at people who used 1.1 first?
Translate as this
float[] coords = {
0.5f, 0.5f, 0f, //index 0
-0.5f, 0.5f, 0f, //index 1
0.5f, -0.5f, 0f, //index 2
-0.5f, -0.5f, 0f //index 3
}
And you are telling to opengl that plot using this sequence of points:
0, 1, 2, 1, 3 , 2.
Here you save memory becouse indexes are short type and each vertex needs 3 floats
Regards

Problem rendering a mesh from an OBJ file

I am having a problem adapting and or I guess understanding the vertices/indices/faces in an OBJ file. I want to eventually parse a OBJ file programmatically but first I need to understand how to do it manually. I am using an adaptation of the example from GLWallpaperService(provided by a dev on the web) to do this.
The problem I am having is it seems to work fine with the code he provided to produce a generic cube with different colored faces which he had to implement and draw individually. My adjusted code below trying to draw just a basic cube from the coords I exported from blender and plugged in values.
public class GLCube {
private final int _nrOfVertices = 8;
private FloatBuffer _vertexBuffer;
private FloatBuffer _normalBuffer;
private ShortBuffer _indiceBuffer;
public GLCube() {
this.init();
}
private void init() {
// 3 is the number of coordinates to each vertex.
_vertexBuffer = BufferFactory.createFloatBuffer(_nrOfVertices * 3);
_normalBuffer = BufferFactory.createFloatBuffer(18);
_indiceBuffer = BufferFactory.createShortBuffer(72);
// Coordinates for the vertexes of the cube.
float[] vertexCoords = {
/*
1f, 1f, 0f,
0f, 1f, 0f,
0f, 0f, 0f,
1f, 0f, 0f,
1f, 0f, -1f,
1f, 1f, -1f,
0f, 1f, -1f,
0f, 0f, -1f,
*/
2.195671f, -0.176713f, -1.292541f,
2.195671f, -0.176713f, 0.707459f,
0.195671f, -0.176713f, 0.707459f,
0.195672f, -0.176713f, -1.292542f,
2.195672f, 1.823287f, -1.292541f,
2.195671f, 1.823287f, 0.707460f,
0.195671f, 1.823287f, 0.707459f,
0.195671f, 1.823287f, -1.292541f
};
short[] indicesArray = {/*
0, 1, 2, 0, 2, 3,
3, 4, 0, 4, 5, 0,
7, 2, 6, 6, 2, 1,
4, 7, 5, 7, 6, 5,
1, 0, 6, 6, 0, 5,
2, 7, 3, 7, 4, 3
*/
1,1,2, 1,3,1,
1,1,3, 1,4,1,
5,2,8, 2,7,2,
5,2,7, 2,6,2,
1,3,5, 3,6,3,
1,3,6, 3,2,3,
2,4,6, 4,7,4,
2,4,7, 4,3,4,
3,5,7, 5,8,5,
3,5,8, 5,4,5,
5,6,1, 6,4,6,
5,6,4, 6,8,6
};
//Coordinates for Normal Vector. Used for Lighting calculations
float[] normalCoords = {/*
0f, 0f, 1f, 0f, 0f, 1f,
0f, 0f, 1f, 0f, 0f, 1f,
0f, 0f, 1f, 0f, 0f, 1f,
1f, 0f, 0f, 1f, 0f, 0f,
1f, 0f, 0f, 1f, 0f, 0f,
1f, 0f, 0f, 1f, 0f, 0f,
-1f, 0f, 0f, -1f, 0f, 0f,
-1f, 0f, 0f, -1f, 0f, 0f,
-1f, 0f, 0f, -1f, 0f, 0f,
0f, 0f,-1f, 0f, 0f,-1f,
0f, 0f,-1f, 0f, 0f,-1f,
0f, 0f,-1f, 0f, 0f,-1f,
0f, 1f, 0f, 0f, 1f, 0f,
0f, 1f, 0f, 0f, 1f, 0f,
0f, 1f, 0f, 0f, 1f, 0f,
0f,-1f, 0f, 0f,-1f, 0f,
0f,-1f, 0f, 0f,-1f, 0f,
0f,-1f, 0f, 0f,-1f, 0f
*/
0f, -1f, 0f,
0f, 1f, 0f,
1f, -0f, 0f,
-0f, -0f, 1f,
-1f, -0f, -0f,
0f, 0f, -1f
};
_vertexBuffer.put(vertexCoords);
_normalBuffer.put(normalCoords);
_indiceBuffer.put(indicesArray);
_indiceBuffer.position(0);
_vertexBuffer.position(0);
_normalBuffer.position(0);
}
public void draw(GL10 gl) {
// 3 coordinates in each vertex
// 0 is the space between each vertex. They are densely packed in the array, so the value is 0
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBuffer);
// 0 is the space between each vertex. They are densely packed in the array, so the value is 0
gl.glNormalPointer(GL10.GL_FLOAT, 0, _normalBuffer);
gl.glColor4f(1.0f, 0f, 0f, 1f); //Red
gl.glDrawElements(GL10.GL_TRIANGLES, 72, GL10.GL_UNSIGNED_SHORT, _indiceBuffer);
}
}
This is the Obj file and maybe I'm just not putting the values in the correct arrays but I have been trying to figure this out for awhile and honestly just don't have any background working with OpenGL so this is my first project trying to work with it.
# Blender v2.58 (sub 1) OBJ File: ''
# www.blender.org
v 2.195671 -0.176713 -1.292541
v 2.195671 -0.176713 0.707459
v 0.195671 -0.176713 0.707459
v 0.195672 -0.176713 -1.292542
v 2.195672 1.823287 -1.292541
v 2.195671 1.823287 0.707460
v 0.195671 1.823287 0.707459
v 0.195671 1.823287 -1.292541
vn 0.000000 -1.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 1.000000 -0.000000 0.000000
vn -0.000000 -0.000000 1.000000
vn -1.000000 -0.000000 -0.000000
vn 0.000000 0.000000 -1.000000
usemtl (null)
s off
f 1//1 2//1 3//1
f 1//1 3//1 4//1
f 5//2 8//2 7//2
f 5//2 7//2 6//2
f 1//3 5//3 6//3
f 1//3 6//3 2//3
f 2//4 6//4 7//4
f 2//4 7//4 3//4
f 3//5 7//5 8//5
f 3//5 8//5 4//5
f 5//6 1//6 4//6
f 5//6 4//6 8//6
Any help with this would be so greatly appreciated. I left his values commented in so you could see what works. The image I see on my screen is a completely distorted set of triangles and it appears its trying to make my cube but is just not quite getting there.
An answer containing what to change would be awesome. -=)
I think you're interpreting the .obj format in the wrong way. Have a look at this document.
Basically the indices for your faces into the vertexCoords should be the first ints.
Each face is defined by indices in a format like this:
f v1/t1/n1 v2/t2/n2 v3/t3/n3
Where the v's are vertex indices, the t's are texture coordinate indices and the n's are normal indices.
So for this line (which defines a single face/triangle)
f 1//1 2//1 3//1
the vertex indices would be 1,2,3and the normal indices 1,1,1.
You have no texture coordinates, so no indices there and hence the double slash.
Keep in mind that the indices for the vertices that make up a face and the indices of the associated normals are different. So you will have to create two sets of indices. (See my edit below about glDrawElements though)
Another minor detail is to keep in mind that .obj files start counting with indices at 1, although that might be (an probably is) the 0th value in your array. So you'll have to account for that (i.e. subtract 1 from all index values).
Edit:
Looking at your code I see you're using glDrawElements. From what I know (but correct me if I'm wrong) this doesn't allow you to have multiple (different) sets of indices for vertices, texcoords and normals. So you will have to change your normal data to match the same indices as you have for your vertices.

Categories

Resources