I’m rendering a very simple house to teach myself openGL and I’m up to learning normal calculation. I’m fairly certain that I have the correct function to calculate the normal vectors, but my lighting looks a bit funny. Below is a screenshot.
Here’s the portion of code that renders the model. I’m using coordinates from an array, so I assemble ever three floating-point numbers as a vertex, and then use these for calculating the normals. Originally I was using a Point and Triangle class, but it was being weird, so I just switched to using 2D arrays.
I’m also seeing random polygons all over the place, like the model explodes out. I cannot for the life of me figure out why Any help would be very much appreciated!
package com.android.aliaga;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLSurfaceView;
public class AliagaRenderer implements GLSurfaceView.Renderer {
private FloatBuffer _vertexBuffer, _normalBuffer;
private int _nrOfVertices = 0;
float[][] point;
float[][] out;
float[] normalCoords;
public int detail = GL10.GL_TRIANGLES;
private float _xAngle;
private float _yAngle;
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glEnable(GL10.GL_CULL_FACE);
gl.glCullFace(GL10.GL_BACK);
gl.glFrontFace(GL10.GL_CCW);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
initShape();
}
public void onSurfaceChanged(GL10 gl, int w, int h) {
gl.glViewport(0, 0, w, h);
}
public void setXAngle(float angle) {
_xAngle = angle;
}
public float getXAngle() {
return _xAngle;
}
public void setYAngle(float angle) {
_yAngle = angle;
}
public float getYAngle() {
return _yAngle;
}
public void onDrawFrame(GL10 gl) {
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
if(_xAngle > 0 && _xAngle <= 90) {
gl.glRotatef(_xAngle, 1f, 0f, 0f);
}
if(_xAngle > 90) {
gl.glRotatef(90, 1f, 0f, 0f);
}
gl.glRotatef(_yAngle, 0f, 1f, 0f);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrthof(-2.0f, 2.0f, -2.0f, 2.0f, -2.0f, 2.0f);
gl.glClearColor(0.0f, 0.1f, 1.0f, 1.0f);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBuffer);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glNormalPointer(GL10.GL_FLOAT, 0, _normalBuffer);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
// gl.glShadeModel(GL10.GL_SMOOTH);
gl.glEnable(GL10.GL_LIGHTING);
FloatBuffer light0 = FloatBuffer.allocate(4);
light0.put(2.0f); light0.put(2.0f); light0.put(0.0f); light0.put(1.0f);
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, light0);
FloatBuffer light1 = FloatBuffer.allocate(4);
light1.put(-2.0f); light1.put(2.0f); light1.put(0.0f); light1.put(0.5f);
gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_POSITION, light1);
gl.glEnable(GL10.GL_LIGHT0);
gl.glEnable(GL10.GL_LIGHT1);
gl.glDrawArrays(GL10.GL_TRIANGLES, 0, _nrOfVertices-1);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
}
public void detail(int d) {
detail = d;
}
private void initShape() {
float[] coords = {
-1.0f, 0.0f, 1.0f,
1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 0.0f, 1.0f,
1.0f, 0.0f, 1.0f,
1.0f, 0.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f,
1.0f, 0.0f, -1.0f,
-1.0f, 0.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 0.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 0.0f, -1.0f,
-1.0f, 0.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 0.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
1.0f, 1.5f, 0.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.5f, 0.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.5f, 0.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.5f, 0.0f,
-1.0f, 1.5f, 0.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.5f, 0.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.5f, 0.0f,
1.0f, 1.5f, 0.0f
};
_nrOfVertices = coords.length;
ByteBuffer vbb = ByteBuffer.allocateDirect(coords.length * 4);
vbb.order(ByteOrder.nativeOrder());
_vertexBuffer = vbb.asFloatBuffer();
_vertexBuffer.put(coords);
_vertexBuffer.position(0);
// Fills vertex array with coordinates
point = new float[_nrOfVertices/3][3];
int i = 0;
int j = 0;
while(i<_nrOfVertices) {
point[j][0] = coords[i++]; // x
point[j][1] = coords[i++]; // y
point[j++][2] = coords[i++]; // z
}
// Normal function called
normalCoords = new float[(_nrOfVertices/3)];
normal();
ByteBuffer nb = ByteBuffer.allocateDirect(normalCoords.length*4);
nb.order(ByteOrder.nativeOrder());
_normalBuffer = nb.asFloatBuffer();
_normalBuffer.put(normalCoords);
_normalBuffer.position(0);
}
void normal() {
float[] v1 = new float[3];
float[] v2 = new float[3];
int i = 0;
int j = 0;
while(i<_nrOfVertices) {
v1[0] = point[i+1][0] - point[i][0];
v1[1] = point[i+1][1] - point[i][1];
v1[2] = point[i+1][2] - point[i][2];
v2[0] = point[i+2][0] - point[i][0];
v2[1] = point[i+2][1] - point[i][1];
v2[2] = point[i+2][2] - point[i][2];
normalCoords[j++] = (v1[1] * v2[2]) - (v1[2] * v2[1]);
normalCoords[j++] = (v1[2] * v2[0]) - (v1[0] * v2[2]);
normalCoords[j++] = (v1[0] * v2[1]) - (v1[1] * v2[0]);
i += 3;
}
}
}