Sythrin
Sythrin

Reputation: 1

Draw a cube with OpenGL?

I need to draw a cube with OpenGL in C:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

#include <GL/glew.h>
#include <GLFW/glfw3.h>

GLuint program;
GLuint vao;
int frame = 0;
#define M_PI 3.14159

void matrixmultiply(GLfloat *out, GLfloat *multiplicant) {
    GLfloat temp[16];
    for(int x = 0; x < 16; x++){
        temp[x] = out[x];
    }

    for(int x = 0; x < 4; x++) {
        for(int y = 0; y < 4; y++) {
            GLfloat sum = 0.0f;
            for(int i = 0; i < 4; i++) {
                GLfloat first = (temp[(x*4)+i]);
                GLfloat second = (multiplicant[(i*4)+y]);
                if((first < -0.001 || first > 0.001) && (second < -0.001 || second > -0.001)) {
                    sum += first * second;
                }
        }
            out[(x*4)+y] = sum;
        }
    }
}

void identity(GLfloat *out) {
    for(int x = 0; x < 16; x++) {
        out[x] = 0.0f;
    }
    out[0] = 1.0f;
    out[5] = 1.0f;
    out[10] = 1.0f;
    out[15] = 1.0f;
}

void translate(GLfloat *out, GLfloat *v) {
    identity(out);
    out[12] = v[0];
    out[13] = v[1];
    out[14] = v[2];
}

void scale(GLfloat *out, GLfloat *v) {
    identity(out);
    out[0] = v[0];
    out[5] = v[1];
    out[10] = v[2];
}

void scaleMatrix(GLfloat *out, GLfloat Sx, GLfloat Sy, GLfloat Sz) {
    identity(out);
    out[0] = Sx;
    out[5] = Sy;
    out[10] = Sz;
    out[15] = 1.0f;
}

void rotatez(GLfloat *out, GLfloat a) {
    identity(out);
    out[0] = cos(a);
    out[1] = sin(a);
    out[4] = -1*sin(a);
    out[5] = cos(a);
}

void normalize(GLfloat *x){
    GLfloat laenge = 1/(sqrtf(x[0]* x[0] + x[1]*x[1] + x[2]*x[2]));
    for(int i = 0; i <= 2; i++){
        x[i] = x[i] * laenge;
    }
}

void crossProduct(GLfloat *a, GLfloat *b, GLfloat *c){
    c[0] = a[1] * b[2] - a[2] * b[1];
    c[1] = a[2] * b[0] - a[0] * b[2];
    c[2] = a[0] * b[1] - a[1] * b[0];

}

GLfloat dotProduct(GLfloat *eye, GLfloat *a){
    return (-1) * (a[0] * eye[0] + a[1] * eye[1] + a[2] * eye[2]);
}

void lookAt(GLfloat *out, GLfloat *eye, GLfloat *center, GLfloat *up){
    GLfloat n[3], u[3], v[3];
    n[0] = eye[0] - center[0];
    n[1] = eye[1] - center[1];
    n[2] = eye[2] - center[2];

    crossProduct(up, n, u);
    crossProduct(n, u, v);

    normalize(n);
    normalize(u);
    normalize(v);

    printf("%f, %f, %f \n", u[0],u[1],u[2]);

    out[0] = u[0];
    out[1] = v[0];
    out[2] = n[0];
    out[3] = 0.0f;
    out[4] = u[1];
    out[5] = v[1];
    out[6] = n[1];
    out[7] = 0.0f;
    out[8] = u[2];
    out[9] = v[2];
    out[10] = n[2];
    out[11] = 0.0f;
    out[12] = dotProduct(u, eye);
    out[13] = dotProduct(v, eye);
    out[14] = dotProduct(n, eye);
    out[15] = 1.0f;

    for(int i = 0; i <= 15; i++){
        printf("%f ", out[i]);
        if((i+1) % 4 == 0){
            printf("\n");
        }
    }
}

void perspective(GLfloat *out, GLfloat fovy, GLfloat aspect, GLfloat near, GLfloat far){
        
        if (fovy <= 0 || aspect <= 0 || near <= 0 || far <= 0) {
        printf("Error: Invalid input values in perspective function.\n");
        return;
        }

        GLfloat degreeToRadian = acos(-1.0f) / 180;
        
        GLfloat top = near * tan(fovy/2 * degreeToRadian);
        GLfloat right = top * aspect;

        out[0] = near / right;
        out[1] = 0.0f;  
        out[2] = 0.0f;
        out[3] = 0.0f;
        out[4] = 0.0f;
        out[5] = near / top;
        out[6] = 0.0f;
        out[7] = 0.0f;
        out[8] = 0.0f;
        out[9] = 0.0f;
        out[10] = (-1) * (far + near) / (far - near);
        out[11] = (-2) * far * near / (far - near);
        out[12] = 0.0f;
        out[13] = 0.0f;
        out[14] = -1.0f;
        out[15] = 0.0f;

    for(int i = 0; i <= 15; i++){
        printf("%f ", out[i]);
        if((i+1) % 4 == 0){
            printf("\n");
        }
    }

}

void init(void) {
    // create and compile vertex shader
    const char *vertexText = 
    "#version 330 core\n"
    "layout(location = 0) in vec3 aPosition;\n"
    "layout (location = 1) in vec3 aColor;\n"
    "out vec3 vertexColor;\n"
    //"out float fragValue;\n"
    //"uniform vec3 color;\n"
    "uniform mat4 transformMatrix;\n"
    "uniform mat4 projectionMatrix;\n"
    "void main() {\n"
    "   vertexColor = aColor;\n"
    //" gl_Position = vec4(aPosition, 0.0, 1.0);\n"
    //" gl_Position =  transformMatrix * gl_Position;\n"
    //" fragValue = vertValue;\n"
    "gl_Position = projectionMatrix * modelViewMatrix * vec4(aPosition, 1.0);\n"
    "}\n";
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexText, NULL);
    glCompileShader(vertexShader);
    GLint status;
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
    if(!status) {
        printf("Error compiling vertex shader:");
        GLchar infoLog[1024];
        glGetShaderInfoLog(vertexShader, 1024, NULL, infoLog);
        printf(infoLog);
    }

    // create and compile fragment shader
    const char *fragmentText = 
    "#version 330 core\n"
    "in vec3 vertexColor;\n"
    //"in float fragValue;\n"
    "uniform vec3 fragColor1;\n"
    "uniform vec3 fragColor2;\n"
    "void main() {\n"
    "gl_FragColor = vec4(vertexColor, 1.0);\n"
    //3.2 smooth transition
    //" gl_FragColor = vec4(mix(fragColor1, fragColor2, fragValue), 1.0);\n"
    //3.2 step transition
    //" gl_FragColor = vec4(mix(fragColor1, fragColor2, step(0.5, fragValue)), 1.0);\n"
    //3.2 smoothstep transition
    //" gl_FragColor = vec4(mix(fragColor1, fragColor2, smoothstep(0.4, 0.6, fragValue)), 1.0);\n"
    //3.2 sine repeating pattern
    //" gl_FragColor = vec4(mix(fragColor1, fragColor2, (sin(fragValue*12.5)+1.0)/2.0), 1.0);\n"
    //3.2 sine stepped repeating pattern
    //" gl_FragColor = vec4(step(0.5, mix(fragColor1, fragColor2, (sin(fragValue*12.5)+1.0)/2.0)), 1.0);\n"
    "}\n";
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentText, NULL);
    glCompileShader(fragmentShader);
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status);
    if(!status) {
        printf("Error compiling fragment shader:");
        GLchar infoLog[1024];
        glGetShaderInfoLog(fragmentShader, 1024, NULL, infoLog);
        printf(infoLog);
    }

    // create and link shader program
    program = glCreateProgram();
    glAttachShader(program, vertexShader);
    glAttachShader(program, fragmentShader);
    glLinkProgram(program);
    glGetProgramiv(program, GL_LINK_STATUS, &status);
    if(!status) {
        printf("Error linking program:");
        GLchar infoLog[1024];
        glGetProgramInfoLog(program, 1024, NULL, infoLog);
        printf(infoLog);
    }
    glValidateProgram(program);
    glGetProgramiv(program, GL_VALIDATE_STATUS, &status);
    if(!status) {
        printf("Error validating program:");
        GLchar infoLog[1024];
        glGetProgramInfoLog(program, 1024, NULL, infoLog);
        printf(infoLog);
    }

    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    
    // create triangle buffer
        /* GLfloat triangleVertices[] = 
    { // X      Y 
        -0.25f,  0.6f,
        -0.25f, -0.4f, 
        -0.15f, -0.4f, 

        -0.15f,  0.6f,  
        -0.25f,  0.6f,  
        -0.15f, -0.4f, 
        
         0.15f,  0.6f, 
         0.25f,  0.6f,  
         0.15f, -0.4f,  
        
         0.25f,  0.6f,  
         0.25f, -0.4f, 
         0.15f, -0.4f,  
        
        -0.25f,  0.15f, 
        -0.25f,  0.05f, 
         0.25f,  0.05f, 
        
        -0.25f,  0.15f, 
         0.25f,  0.15f, 
         0.25f,  0.05f, 
        
        -0.25f,  -0.5f,  
         0.25f,  -0.5f, 
         0.25f,  -0.6f, 
        
         0.25f,  -0.6f,  
        -0.25f,  -0.5f, 
        -0.25f,  -0.6f,
    }; */

GLfloat cubeVertices[] = {
    // Front face (red)
    -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, 
    // Back face (gree
    -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,  
    // Left face (blu
    -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,  
    // Right face (yello
     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,  
    // Top face (cya
    -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,  
    // Bottom face (mage
    -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
};

GLuint cubeVertexBufferObject;
glGenBuffers(1, &cubeVertexBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, cubeVertexBufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), cubeVertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);

/* GLuint triangleVertexBufferObject;
glGenBuffers(1,&triangleVertexBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, triangleVertexBufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangleVertices), triangleVertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0); */

    // create color buffer
    /* GLfloat triangleColors[] = 
    { // R     G      B
        1.00f, 1.00f, 1.00f,
        1.00f, 1.00f, 1.00f,
        1.00f, 1.00f, 1.00f,
        1.00f, 1.00f, 1.00f,
        1.00f, 1.00f, 1.00f,
        1.00f, 1.00f, 1.00f
    }; */

    //color for the cube
    GLfloat cubeColors[]=
    {
        1.0f, 0.0f, 0.0f,

        0.0f, 1.0f, 0.0f,

        0.0f, 0.0f, 1.0f,

        1.0f, 1.0f, 0.0f,

        0.0f, 1.0f, 1.0f,

        1.0f, 1.0f, 1.0f
    };

    GLuint cubeColorBufferObject;
    glGenBuffers(1, &cubeColorBufferObject);
    glBindBuffer(GL_ARRAY_BUFFER, cubeColorBufferObject);
    glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), cubeVertices, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    /* GLuint triangleColorBufferObject;
    glGenBuffers(1,&triangleColorBufferObject);
    glBindBuffer(GL_ARRAY_BUFFER, triangleColorBufferObject);
    glBufferData(GL_ARRAY_BUFFER, sizeof(triangleColors), triangleColors, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0); */

    // create vertex array object
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    glBindBuffer(GL_ARRAY_BUFFER, cubeVertexBufferObject);
    glVertexAttribPointer(
        0,
        3,
        GL_FLOAT,
        GL_FALSE,
        0,
        0
    );
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, cubeColorBufferObject);
    glVertexAttribPointer(
        1,
        3,
        GL_FLOAT,
        GL_FALSE,
        0,
        0
    );
    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glViewport(0,0,800,600);
}

void draw(void) {
    /* glClear(GL_COLOR_BUFFER_BIT);
    glUseProgram(program);
    glBindVertexArray(vao);

    GLfloat modelViewMatrix[16];
    GLfloat projectionMatrix[16];

    GLint colorUniform = glGetUniformLocation(program, "color");
    float red = ((sin((float)(frame-150)/100))+1.0f)/2.0f;
    float green = ((sin((float)(frame-100)/120))+1.0f)/2.0f;
    float blue = ((sin((float)(frame-150)/140))+1.0f)/2.0f;
    glUniform3f(colorUniform, red, green, blue);

    GLint positionUniform = glGetUniformLocation(program, "transformMatrix");
    GLfloat matrix[16];
    identity(matrix);

    rotatez(matrix, M_PI*(frame/300.0f));
    GLfloat translateMatrix[4] = {sin(frame/100.0f), cos(frame/100.0f), 0.0f, 1.0f};
    translate(matrix, translateMatrix);
    GLfloat scaleMatrix[4] = {(sin(frame/60.0f)+2.5f)/5, (sin(frame/60.0f)+2.5f)/5, 1.0f, 1.0f};
    scale(matrix, scaleMatrix);
    glUniformMatrix4fv(positionUniform, 1, GL_FALSE, matrix);

    GLint fragColor1Uniform = glGetUniformLocation(program, "fragColor1");
    glUniform3f(fragColor1Uniform, 1.0f, 0.0f, 0.0f);
    GLint fragColor2Uniform = glGetUniformLocation(program, "fragColor2");
    glUniform3f(fragColor2Uniform, 0.0f, 1.0f, 0.0f);
    glDrawArrays(GL_TRIANGLES, 0, 104);
    frame++; */

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glUseProgram(program);
    glBindVertexArray(vao);

    // Calculate model-view and projection matrices
    GLfloat modelViewMatrix[16];
    GLfloat projectionMatrix[16];

    //... calculate model-view matrix using rotate, translate, and scale functions...
    identity(modelViewMatrix);
    rotatez(modelViewMatrix, M_PI*(frame/300.0f));
    GLfloat translateMatrix[4] = {sin(frame/100.0f), cos(frame/100.0f), 0.0f, 1.0f};
    translate(modelViewMatrix, translateMatrix);
    GLfloat scaleMatrix[4] = {(sin(frame/60.0f)+2.5f)/5, (sin(frame/60.0f)+2.5f)/5, 1.0f, 1.0f};
    scale(modelViewMatrix, scaleMatrix);

    //... calculate projection matrix using perspective function...
    perspective(projectionMatrix, 45.0f, 800.0f/600.0f, 0.1f, 100.0f);

    // Pass model-view and projection matrices to shader program
    GLint modelViewUniform = glGetUniformLocation(program, "modelViewMatrix");
    glUniformMatrix4fv(modelViewUniform, 1, GL_FALSE, modelViewMatrix);

    GLint projectionUniform = glGetUniformLocation(program, "projectionMatrix");
    glUniformMatrix4fv(projectionUniform, 1, GL_FALSE, projectionMatrix);

    glDrawArrays(GL_TRIANGLES, 0, 36);
    frame++;

}

void framebuffer_size_callback(GLFWwindow *window, int width, int height) {
    glViewport(0, 0, width, height);
}

int main(void) {
    printf("Hallo!\n");

    GLfloat probeMatrix[16];
    identity(probeMatrix);
    GLfloat eye[3] = {1.0f, 3.0f, 2.0f};
    GLfloat center[3] = {2.0f, 2.0f, 2.0f};
    GLfloat up[3] = {1.0f, 1.0f, 1.0f};
    GLfloat fovy = 10.0f;
    GLfloat aspect = 2.0f;
    GLfloat near = 2.0f;
    GLfloat far = 4.0f;

    //lookAt(probeMatrix, eye, center, up );
    perspective(probeMatrix, fovy, aspect, near, far);

    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    GLFWwindow *window = glfwCreateWindow(800, 600, "Computergrafik 1", NULL, NULL);
    if (!window) {
        printf("Failed to create window\n");
        glfwTerminate();
        return -1;
    }
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
    glfwMakeContextCurrent(window);
    glewInit();


    init();
    while (!glfwWindowShouldClose(window)) {
        draw();

        glfwSwapBuffers(window);
        glfwPollEvents();
    }
    glfwTerminate();
    return 0;
}

...and I don't understand how. I expected a cube.

Perhaps I do not understand my code, but I think it should work.

Upvotes: -2

Views: 80

Answers (1)

rafix07
rafix07

Reputation: 20918

  1. Function for computing perspective transform matrix has bug, indices 11 and 14 have to be swapped:

    out[9] = 0.0f;
    out[10] = (-1) * (far + near) / (far - near);
    out[14] = (-2) * far * near / (far - near);  // <---
    out[12] = 0.0f;
    out[13] = 0.0f;
    out[11] = -1.0f;   // <---
    out[15] = 0.0f;
    
  2. You don't set matrix of view transformation, so default position of eye is (0,0,0) that points along [0,0,-1] direction vector.

  3. Becuase we are affected by point 2, your cube has to be shifted towards negative value of Z axis in order to be seen:

    //... calculate model-view matrix using rotate, translate, and scale functions...
    identity(modelViewMatrix);
    //rotatez(modelViewMatrix, M_PI*(frame/300.0f));
    GLfloat translateMatrix[4] = {sin(frame/100.0f), cos(frame/100.0f), -20.0f, 1.0f};
    translate(modelViewMatrix, translateMatrix);
    //GLfloat scaleMatrix[4] = {(sin(frame/60.0f)+2.5f)/5, (sin(frame/60.0f)+2.5f)/5, 1.0f, 1.0f};
    //scale(modelViewMatrix, scaleMatrix);
    

    as you can see, Z value in translation is set to -20.

    You may ask why I left only translation matrix. Because if your intention was to combine scale, translate and rotation as composition you have to fix all mentioned functions and remove from them identity. For example scale function doesn't multiply modelViewMatrix but just set scale matrix into modelViewMatrix.

  4. Vertex shader code has typos:

    uniform mat4 transformMatrix;
    

    should be:

    uniform mat4 modelViewMatrix;
    

After applying all above fixes, you will get:

preview

Upvotes: 2

Related Questions