Hey guys, I’m currently trying to port this tutorial (http://www.arcsynthesis.org/gltut/Positioning/Tut06%20Fun%20with%20Matrices.html) to lwjgl, but I’m having some issues when it comes to actually drawing the object, and instead of looking like this:
http://www.arcsynthesis.org/gltut/Positioning/Robot%20Arm.png
It looks like this:
I think the issue might have something to do with the way the index data is being buffered/read, but I really have no idea. Any help would be greatly appreciated.
import org.lwjgl.opengl.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.ARBVertexBufferObject.*;
import static org.lwjgl.opengl.ARBVertexArrayObject.*;
import org.lwjgl.util.vector.*;
import org.lwjgl.BufferUtils;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
public class DrawRobot {
private Matrix4f cameraToClipMatrix;
private int program, positionAttrib, colorAttrib, modelToCameraMatrixUnif, cameraToClipMatrixUnif, vertexBuffObj, indexBuffObj, vao;
private float fFrustumScale;
private final int numberOfVerticies = 24;
IntBuffer indexDatBuff;
private final float[] RED_COLOR = { 1.0f, 0.0f, 0.0f, 1.0f };
private final float[] GREEN_COLOR = { 0.0f, 1.0f, 0.0f, 1.0f };
private final float[] BLUE_COLOR = { 0.0f, 0.0f, 1.0f, 1.0f };
private final float[] YELLOW_COLOR = { 1.0f, 1.0f, 0.0f, 1.0f };
private final float[] CYAN_COLOR = { 0.0f, 1.0f, 1.0f, 1.0f };
private final float[] MAGENTA_COLOR = { 1.0f, 0.0f, 1.0f, 1.0f };
private final float[] vertexData = {
//Front
+1.0f, +1.0f, +1.0f,
+1.0f, -1.0f, +1.0f,
-1.0f, -1.0f, +1.0f,
-1.0f, +1.0f, +1.0f,
//Top
+1.0f, +1.0f, +1.0f,
-1.0f, +1.0f, +1.0f,
-1.0f, +1.0f, -1.0f,
+1.0f, +1.0f, -1.0f,
//Left
+1.0f, +1.0f, +1.0f,
+1.0f, +1.0f, -1.0f,
+1.0f, -1.0f, -1.0f,
+1.0f, -1.0f, +1.0f,
//Back
+1.0f, +1.0f, -1.0f,
-1.0f, +1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
+1.0f, -1.0f, -1.0f,
//Bottom
+1.0f, -1.0f, +1.0f,
+1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, +1.0f,
//Right
-1.0f, +1.0f, +1.0f,
-1.0f, -1.0f, +1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, +1.0f, -1.0f,
GREEN_COLOR[0], GREEN_COLOR[1], GREEN_COLOR[2], GREEN_COLOR[3],
GREEN_COLOR[0], GREEN_COLOR[1], GREEN_COLOR[2], GREEN_COLOR[3],
GREEN_COLOR[0], GREEN_COLOR[1], GREEN_COLOR[2], GREEN_COLOR[3],
GREEN_COLOR[0], GREEN_COLOR[1], GREEN_COLOR[2], GREEN_COLOR[3],
BLUE_COLOR[0], BLUE_COLOR[1], BLUE_COLOR[2], BLUE_COLOR[3],
BLUE_COLOR[0], BLUE_COLOR[1], BLUE_COLOR[2], BLUE_COLOR[3],
BLUE_COLOR[0], BLUE_COLOR[1], BLUE_COLOR[2], BLUE_COLOR[3],
BLUE_COLOR[0], BLUE_COLOR[1], BLUE_COLOR[2], BLUE_COLOR[3],
RED_COLOR[0], RED_COLOR[1], RED_COLOR[2], RED_COLOR[3],
RED_COLOR[0], RED_COLOR[1], RED_COLOR[2], RED_COLOR[3],
RED_COLOR[0], RED_COLOR[1], RED_COLOR[2], RED_COLOR[3],
RED_COLOR[0], RED_COLOR[1], RED_COLOR[2], RED_COLOR[3],
YELLOW_COLOR[0], YELLOW_COLOR[1], YELLOW_COLOR[2], YELLOW_COLOR[3],
YELLOW_COLOR[0], YELLOW_COLOR[1], YELLOW_COLOR[2], YELLOW_COLOR[3],
YELLOW_COLOR[0], YELLOW_COLOR[1], YELLOW_COLOR[2], YELLOW_COLOR[3],
YELLOW_COLOR[0], YELLOW_COLOR[1], YELLOW_COLOR[2], YELLOW_COLOR[3],
CYAN_COLOR[0], CYAN_COLOR[1], CYAN_COLOR[2], CYAN_COLOR[3],
CYAN_COLOR[0], CYAN_COLOR[1], CYAN_COLOR[2], CYAN_COLOR[3],
CYAN_COLOR[0], CYAN_COLOR[1], CYAN_COLOR[2], CYAN_COLOR[3],
CYAN_COLOR[0], CYAN_COLOR[1], CYAN_COLOR[2], CYAN_COLOR[3],
MAGENTA_COLOR[0], MAGENTA_COLOR[1], MAGENTA_COLOR[2], MAGENTA_COLOR[3],
MAGENTA_COLOR[0], MAGENTA_COLOR[1], MAGENTA_COLOR[2], MAGENTA_COLOR[3],
MAGENTA_COLOR[0], MAGENTA_COLOR[1], MAGENTA_COLOR[2], MAGENTA_COLOR[3],
MAGENTA_COLOR[0], MAGENTA_COLOR[1], MAGENTA_COLOR[2], MAGENTA_COLOR[3],
};
private final int indexData[] = {
0, 1, 2,
2, 3, 0,
4, 5, 6,
6, 7, 4,
8, 9, 10,
10, 11, 8,
12, 13, 14,
14, 15, 12,
16, 17, 18,
18, 19, 16,
20, 21, 22,
22, 23, 20,
};
DrawRobot(int w, int h) {
// Set up opengl environment
glViewport(0, 0, w, h);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthMask(true);
glDepthFunc(GL_LEQUAL);
glDepthRange(0.0f, 1.0f);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CW);
programInit();
VAOInit();
robot();
}
private float calcFrustrumscale(float fDegFOV) {
final float degToRad = 3.14159f * 2.0f / 360.0f;
float fRadFOV = fDegFOV * degToRad;
return (float) Math.atan(fRadFOV);
}
private void programInit() {
ShaderLoader loader = new ShaderLoader("src/shaders/PosColorLocalTransform.vert", "src/shaders/ColorPassthrough.frag");
if (!loader.getBuildStatus()) {
System.out.println("Failed to load shaders. Exiting.");
Display.destroy();
System.exit(0);
}
program = loader.getProgram();
positionAttrib = glGetAttribLocation(program, "position");
colorAttrib = glGetAttribLocation(program, "color");
modelToCameraMatrixUnif = glGetUniformLocation(program, "modelToCameraMatrix");
cameraToClipMatrixUnif = glGetUniformLocation(program, "cameraToClipMatrix");
// Set up camera to clip space translation matrix
float fzNear = 1.0f, fzFar = 100.0f;
fFrustumScale = calcFrustrumscale(45.0f);
cameraToClipMatrix = new Matrix4f();
cameraToClipMatrix.m00 = fFrustumScale;
cameraToClipMatrix.m11 = fFrustumScale;
cameraToClipMatrix.m22 = (fzFar + fzNear) / (fzNear - fzFar);
cameraToClipMatrix.m23 = -1.0f;
cameraToClipMatrix.m32 = (2 * fzFar * fzNear) / (fzNear - fzFar);
FloatBuffer buf = BufferUtils.createFloatBuffer(16);
cameraToClipMatrix.store(buf);
buf.flip();
glUseProgram(program);
glUniformMatrix4(cameraToClipMatrixUnif, false, buf);
glUseProgram(0);
}
private void VAOInit() {
IntBuffer vertBuff = BufferUtils.createIntBuffer(1);
glGenBuffersARB(vertBuff);
vertexBuffObj = vertBuff.get(0);
FloatBuffer vertexDatBuff = BufferUtils.createFloatBuffer(vertexData.length);
vertexDatBuff.put(vertexData);
vertexDatBuff.flip();
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffObj);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexDatBuff, GL_STATIC_DRAW_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
IntBuffer indexBuff = BufferUtils.createIntBuffer(1);
glGenBuffersARB(indexBuff);
indexBuffObj = indexBuff.get(0);
indexDatBuff = BufferUtils.createIntBuffer(indexData.length);
indexDatBuff.put(indexData);
indexDatBuff.flip();
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexBuffObj);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexDatBuff, GL_STATIC_DRAW_ARB);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
IntBuffer vaoBuff = BufferUtils.createIntBuffer(1);
glGenVertexArrays(vaoBuff);
vao = vaoBuff.get(0);
glBindVertexArray(vao);
int colorDataOffset = 4 * 3 * numberOfVerticies; // 4 bytes * 3 points * obvious
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffObj);
glEnableVertexAttribArray(positionAttrib);
glEnableVertexAttribArray(colorAttrib);
glVertexAttribPointer(positionAttrib, 3, GL_FLOAT, false, 0, 0);
glVertexAttribPointer(colorAttrib, 4, GL_FLOAT, false, 0, colorDataOffset);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexBuffObj);
glBindVertexArray(0);
}
private float clamp(float fValue, float fMin, float fMax) {
if (fValue < fMin)
return fMin;
if (fValue > fMax)
return fMax;
return fValue;
}
void reshape (int w, int h)
{
cameraToClipMatrix.m00 = fFrustumScale * (h / (float)w);
cameraToClipMatrix.m11 = fFrustumScale;
glUseProgram(program);
FloatBuffer buf = BufferUtils.createFloatBuffer(16);
cameraToClipMatrix.store(buf);
buf.flip();
glUniformMatrix4(cameraToClipMatrixUnif, false, buf);
glUseProgram(0);
glViewport(0, 0, w, h);
}
// Defines block for robot
private final float STANDARD_ANGLE_INCREMENT = 11.25f;
private final float SMALL_ANGLE_INCREMENT = 9.0f;
Vector3f posBase;
float angBase;
Vector3f posBaseLeft, posBaseRight;
float scaleBaseZ;
float angUpperArm;
float sizeUpperArm;
Vector3f posLowerArm;
float angLowerArm;
float lenLowerArm;
float widthLowerArm;
Vector3f posWrist;
float angWristRoll;
float angWristPitch;
float lenWrist;
float widthWrist;
Vector3f posLeftFinger, posRightFinger;
float angFingerOpen;
float lenFinger;
float widthFinger;
float angLowerFinger;
// End Defines
private void robot() {
posBase = new Vector3f(3.0f, -5.0f, -40.0f);
angBase = -45.0f;
posBaseLeft = new Vector3f(2.0f, 0.0f, 0.0f);
posBaseRight = new Vector3f(-2.0f, 0.0f, 0.0f);
scaleBaseZ = 3.0f;
angUpperArm = -33.75f;
sizeUpperArm = 9.0f;
posLowerArm = new Vector3f(0.0f, 0.0f, 8.0f);
angLowerArm = 146.25f;
lenLowerArm = 5.0f;
widthLowerArm = 1.5f;
posWrist = new Vector3f(0.0f, 0.0f, 5.0f);
angWristRoll = 0.0f;
angWristPitch = 67.5f;
lenWrist = 2.0f;
widthWrist = 2.0f;
posLeftFinger = new Vector3f(1.0f, 0.0f, 1.0f);
posRightFinger = new Vector3f(-1.0f, 0.0f, 1.0f);
angFingerOpen = 180.0f;
lenFinger = 2.0f;
widthFinger = 0.5f;
angLowerFinger = 45.0f;
}
public void Draw()
{
MatrixStack modelToCameraStack = new MatrixStack();
glUseProgram(program);
glBindVertexArray(vao);
modelToCameraStack.translate(posBase);
modelToCameraStack.rotateY(angBase);
//Draw left base.
{
modelToCameraStack.push();
modelToCameraStack.translate(posBaseLeft);
modelToCameraStack.scale(new Vector3f(1.0f, 1.0f, scaleBaseZ));
glUniformMatrix4(modelToCameraMatrixUnif, false, modelToCameraStack.top());
glDrawElements(GL_TRIANGLES, indexData.length, GL_UNSIGNED_INT, 0);
modelToCameraStack.pop();
}
//Draw right base.
{
modelToCameraStack.push();
modelToCameraStack.translate(posBaseRight);
modelToCameraStack.scale(new Vector3f(1.0f, 1.0f, scaleBaseZ));
glUniformMatrix4(modelToCameraMatrixUnif, false, modelToCameraStack.top());
glDrawElements(GL_TRIANGLES, indexData.length, GL_UNSIGNED_INT, 0);
modelToCameraStack.pop();
}
//Draw main arm.
DrawUpperArm(modelToCameraStack);
glBindVertexArray(0);
glUseProgram(0);
}
void DrawFingers(MatrixStack modelToCameraStack)
{
//Draw left finger
modelToCameraStack.push();
modelToCameraStack.translate(posLeftFinger);
modelToCameraStack.rotateY(angFingerOpen);
modelToCameraStack.push();
modelToCameraStack.translate(new Vector3f(0.0f, 0.0f, lenFinger / 2.0f));
modelToCameraStack.scale(new Vector3f(widthFinger / 2.0f, widthFinger/ 2.0f, lenFinger / 2.0f));
glUniformMatrix4(modelToCameraMatrixUnif, false, modelToCameraStack.top());
glDrawElements(GL_TRIANGLES, indexData.length, GL_UNSIGNED_INT, 0);
modelToCameraStack.pop();
{
//Draw left lower finger
modelToCameraStack.push();
modelToCameraStack.translate(new Vector3f(0.0f, 0.0f, lenFinger));
modelToCameraStack.rotateY(-angLowerFinger);
modelToCameraStack.push();
modelToCameraStack.translate(new Vector3f(0.0f, 0.0f, lenFinger / 2.0f));
modelToCameraStack.scale(new Vector3f(widthFinger / 2.0f, widthFinger/ 2.0f, lenFinger / 2.0f));
glUniformMatrix4(modelToCameraMatrixUnif, false, modelToCameraStack.top());
glDrawElements(GL_TRIANGLES, indexData.length, GL_UNSIGNED_INT, 0);
modelToCameraStack.pop();
modelToCameraStack.pop();
}
modelToCameraStack.pop();
//Draw right finger
modelToCameraStack.push();
modelToCameraStack.translate(posRightFinger);
modelToCameraStack.rotateY(-angFingerOpen);
modelToCameraStack.push();
modelToCameraStack.translate(new Vector3f(0.0f, 0.0f, lenFinger / 2.0f));
modelToCameraStack.scale(new Vector3f(widthFinger / 2.0f, widthFinger/ 2.0f, lenFinger / 2.0f));
glUniformMatrix4(modelToCameraMatrixUnif, false, modelToCameraStack.top());
glDrawElements(GL_TRIANGLES, indexData.length, GL11.GL_UNSIGNED_INT, 0);
modelToCameraStack.pop();
{
//Draw right lower finger
modelToCameraStack.push();
modelToCameraStack.translate(new Vector3f(0.0f, 0.0f, lenFinger));
modelToCameraStack.rotateY(angLowerFinger);
modelToCameraStack.push();
modelToCameraStack.translate(new Vector3f(0.0f, 0.0f, lenFinger / 2.0f));
modelToCameraStack.scale(new Vector3f(widthFinger / 2.0f, widthFinger/ 2.0f, lenFinger / 2.0f));
glUniformMatrix4(modelToCameraMatrixUnif, false, modelToCameraStack.top());
glDrawElements(GL_TRIANGLES, indexData.length, GL_UNSIGNED_INT, 0);
modelToCameraStack.pop();
modelToCameraStack.pop();
}
modelToCameraStack.pop();
}
void DrawWrist(MatrixStack modelToCameraStack)
{
modelToCameraStack.push();
modelToCameraStack.translate(posWrist);
modelToCameraStack.rotateZ(angWristRoll);
modelToCameraStack.rotateX(angWristPitch);
modelToCameraStack.push();
modelToCameraStack.scale(new Vector3f(widthWrist / 2.0f, widthWrist/ 2.0f, lenWrist / 2.0f));
glUniformMatrix4(modelToCameraMatrixUnif, false, modelToCameraStack.top());
glDrawElements(GL_TRIANGLES, indexData.length, GL_UNSIGNED_INT, 0);
modelToCameraStack.pop();
DrawFingers(modelToCameraStack);
modelToCameraStack.pop();
}
void DrawLowerArm(MatrixStack modelToCameraStack)
{
modelToCameraStack.push();
modelToCameraStack.translate(posLowerArm);
modelToCameraStack.rotateX(angLowerArm);
modelToCameraStack.push();
modelToCameraStack.translate(new Vector3f(0.0f, 0.0f, lenLowerArm / 2.0f));
modelToCameraStack.scale(new Vector3f(widthLowerArm / 2.0f, widthLowerArm / 2.0f, lenLowerArm / 2.0f));
glUniformMatrix4(modelToCameraMatrixUnif, false, modelToCameraStack.top());
glDrawElements(GL_TRIANGLES, indexData.length, GL_UNSIGNED_INT, 0);
modelToCameraStack.pop();
DrawWrist(modelToCameraStack);
modelToCameraStack.pop();
}
void DrawUpperArm(MatrixStack modelToCameraStack)
{
modelToCameraStack.push();
modelToCameraStack.rotateX(angUpperArm);
{
modelToCameraStack.push();
modelToCameraStack.translate(new Vector3f(0.0f, 0.0f, (sizeUpperArm / 2.0f) - 1.0f));
modelToCameraStack.scale(new Vector3f(1.0f, 1.0f, sizeUpperArm / 2.0f));
glUniformMatrix4(modelToCameraMatrixUnif, false, modelToCameraStack.top());
glDrawElements(GL_TRIANGLES, indexData.length, GL_UNSIGNED_INT, 0);
modelToCameraStack.pop();
}
DrawLowerArm(modelToCameraStack);
modelToCameraStack.pop();
}
void AdjBase(boolean bIncrement)
{
angBase += bIncrement ? STANDARD_ANGLE_INCREMENT : -STANDARD_ANGLE_INCREMENT;
angBase = angBase % 360.0f;
}
void AdjUpperArm(boolean bIncrement)
{
angUpperArm += bIncrement ? STANDARD_ANGLE_INCREMENT : -STANDARD_ANGLE_INCREMENT;
angUpperArm = clamp(angUpperArm, -90.0f, 0.0f);
}
void AdjLowerArm(boolean bIncrement)
{
angLowerArm += bIncrement ? STANDARD_ANGLE_INCREMENT : -STANDARD_ANGLE_INCREMENT;
angLowerArm = clamp(angLowerArm, 0.0f, 146.25f);
}
void AdjWristPitch(boolean bIncrement)
{
angWristPitch += bIncrement ? STANDARD_ANGLE_INCREMENT : -STANDARD_ANGLE_INCREMENT;
angWristPitch = clamp(angWristPitch, 0.0f, 90.0f);
}
void AdjWristRoll(boolean bIncrement)
{
angWristRoll += bIncrement ? STANDARD_ANGLE_INCREMENT : -STANDARD_ANGLE_INCREMENT;
angWristRoll = angWristRoll % 360.0f;
}
void AdjFingerOpen(boolean bIncrement)
{
angFingerOpen += bIncrement ? SMALL_ANGLE_INCREMENT : -SMALL_ANGLE_INCREMENT;
angFingerOpen = clamp(angFingerOpen, 9.0f, 180.0f);
}
void display() {
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Draw();
Display.update();
}
}