Compare commits

..

No commits in common. "8b276f089f12ef735eab4d1e582c6cb20a0b83a7" and "28aef55a81dff03443f6d5fa3d28333f9c511c4e" have entirely different histories.

15 changed files with 100 additions and 2710 deletions

View file

@ -1,43 +1,27 @@
# CMake entry point # CMake entry point
cmake_minimum_required (VERSION 3.0) cmake_minimum_required (VERSION 3.0)
project(OpenGL_Analog_Clock C) project (OpenGL_Analog_Clock)
cmake_policy(SET CMP0072 NEW)
find_package(OpenGL REQUIRED)
find_package(OpenGL REQUIRED)
find_package(GLEW REQUIRED) set(ALL_LIBS
find_package(glfw3 REQUIRED) ${OPENGL_LIBRARY}
glfw
include_directories( GLEW
Include/ )
.
) add_definitions(
-DTW_STATIC
set(ALL_LIBS -DTW_NO_LIB_PRAGMA
${OPENGL_LIBRARY} -DTW_NO_DIRECT3D
glfw -DGLEW_STATIC
GLEW -D_CRT_SECURE_NO_WARNINGS
) )
set(CMAKE_C_FLAGS "-O0 -ggdb -lm") add_executable(clock
main.c
add_definitions( )
-DTW_STATIC
-DTW_NO_LIB_PRAGMA target_link_libraries(clock
-DTW_NO_DIRECT3D ${ALL_LIBS}
-DGLEW_STATIC )
-D_CRT_SECURE_NO_WARNINGS
)
add_executable(
clock
src/main.c
src/clock.c
src/shader.c
src/matrix.c
src/model.c
)
target_link_libraries(
clock
${ALL_LIBS}
)

View file

@ -1,32 +0,0 @@
#ifndef CLOCK_H
#define CLOCK_H
// Include standard headers
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <unistd.h>
// Include GLEW
#include <GL/glew.h>
// Include GLFW
#include <GLFW/glfw3.h>
// Include project headers
#include <model.h>
#include <matrix.h>
#include <shader.h>
// Define macros
#define xfree(p) if (p) free((void *)p)
// Declare functions
int clock_init(GLFWwindow **);
int clock_run(GLFWwindow *);
#endif

View file

@ -1,12 +0,0 @@
#ifndef MATRIX_H
#define MATRIX_H
GLfloat *matrix_new(void);
GLfloat *matrix_multip(GLfloat *, GLfloat *);
GLfloat *matrix_transform(GLfloat *, int,
GLfloat *);
#endif

View file

@ -1,18 +0,0 @@
#ifndef MODEL_LOADER_H
#define MODEL_LOADER_H
typedef struct _entity {
size_t offset;
size_t size;
} Entity;
typedef struct _model {
GLfloat *object;
size_t bufsize;
Entity *entities[5];
} Model;
Model * model_load(const char *);
#endif

View file

@ -1,7 +0,0 @@
#ifndef SHADER_H
#define SHADER_H
int LoadShaders(GLuint *, const char *, const char *);
#endif

1057
clock.obj

File diff suppressed because it is too large Load diff

1009
cube.obj

File diff suppressed because it is too large Load diff

73
main.c Normal file
View file

@ -0,0 +1,73 @@
// Include standard headers
#include <stdio.h>
#include <stdlib.h>
// Include GLEW
#include <GL/glew.h>
// Include GLFW
#include <GLFW/glfw3.h>
GLFWwindow* window;
int main(void) {
// Initialise GLFW
if(!glfwInit()) {
fprintf(stderr, "Failed to initialize GLFW\n");
getchar();
return -1;
}
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Open a window and create its OpenGL context
window = glfwCreateWindow(1024, 768, "OpenGL Clock", NULL, NULL);
if (window == NULL) {
fprintf(stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n");
getchar();
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// Initialize GLEW
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
getchar();
glfwTerminate();
return -1;
}
// Ensure we can capture the escape key being pressed below
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
// Dark grey background
glClearColor(0.15f, 0.15f, 0.15f, 0.0f);
do {
// Clear the screen. It's not mentioned before Tutorial 02,
// but it can cause flickering, so it's there nonetheless.
glClear(GL_COLOR_BUFFER_BIT);
// Draw nothing, see you in tutorial 2 !
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
// Check if the ESC key was pressed or the window was closed
} while(glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0);
// Close OpenGL window and terminate GLFW
glfwTerminate();
return 0;
}

View file

@ -1,12 +0,0 @@
#version 330 core
in float colorF;
out vec3 color;
void main() {
if (colorF == 0)
color = vec3(1, 1, 1);
else
color = vec3(0, 0, 0);
}

View file

@ -1,14 +0,0 @@
#version 330 core
// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec4 position;
out float colorF;
void main() {
if (position.z <= 0.0)
colorF = 0;
else
colorF = 1;
gl_Position = position;
}

View file

@ -1,201 +0,0 @@
#include <clock.h>
int
clock_init(GLFWwindow **window) {
// Initialise GLFW
if(!glfwInit()) {
fprintf(stderr, "Failed to initialize GLFW\n");
getchar();
return -1;
}
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Open a window and create its OpenGL context
*window = glfwCreateWindow(1280, 720, "OpenGL Clock", NULL, NULL);
if (*window == NULL) {
fprintf(stderr, "Failed to open GLFW window.\n");
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(*window);
// Initialize GLEW
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
glfwTerminate();
return -1;
}
// Ensure we can capture the escape key being pressed below
glfwSetInputMode(*window, GLFW_STICKY_KEYS, GL_TRUE);
// Dark grey background
glClearColor(0.15f, 0.15f, 0.15f, 0.0f);
return 0;
}
int
clock_run(GLFWwindow *window) {
GLuint VertexArrayID;
GLuint programID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
// Create and compile our GLSL program from the shaders
if (LoadShaders(&programID,
"../shaders/SimpleVertexShader.vertexshader",
"../shaders/SimpleFragmentShader.fragmentshader")) {
fprintf(stderr, "Could not load shaders.\n");
return -1;
}
static GLfloat g_vertex_buffer_data[] = {
-0.3f, -0.3f, 0.0f, 1.0f,
0.3f, -0.3f, 0.0f, 1.0f,
0.0f, 0.3f, 0.0f, 1.0f
};
Model *model;
model = model_load("../clock.obj");
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, model->bufsize*4*sizeof(GLfloat), model->object, GL_STATIC_DRAW);
double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
GLfloat **matrices = malloc(4 * sizeof(GLfloat *));
GLfloat *temp = matrix_new();
//temp[0] = cos(M_PI*2/60);
//temp[1] = -sin(M_PI*2/60);
//temp[4] = sin(M_PI*2/60);
//temp[5] = cos(M_PI*2/60);
matrices[0] = temp;
time_t t = time(NULL);
for (int i = 1; i < 4; i++) {
temp = matrix_new();
temp[0] = cos(M_PI*2/60*(t%60));
temp[4] = -sin(M_PI*2/60*(t%60));
temp[1] = sin(M_PI*2/60*(t%60));
temp[5] = cos(M_PI*2/60*(t%60));
matrices[i] = temp;
t /= 60;
}
GLfloat *projection = matrix_new();
GLfloat *buffer;
projection[14] = -1.0f;
buffer = matrix_new();
buffer[0] = (GLfloat)9/16;
temp = matrix_multip(projection, buffer);
free(buffer);
free(projection);
projection = temp;
temp = malloc(model->bufsize * 4 * sizeof(GLfloat));
buffer = malloc(model->bufsize * 4 * sizeof(GLfloat));
memcpy(temp, model->object, model->bufsize * 4 * sizeof(GLfloat));
GLfloat *orig;
orig = malloc(model->bufsize * 4 * sizeof(GLfloat));
memcpy(orig, model->object, model->bufsize * 4 * sizeof(GLfloat));
do {
// Clear the screen. It's not mentioned before Tutorial 02,
// but it can cause flickering, so it's there nonetheless.
glClear(GL_COLOR_BUFFER_BIT);
// Use our shader
glUseProgram(programID);
//glfwGetCursorPos(window, &xpos, &ypos);
//g_vertex_buffer_data[0] = (float)xpos / 1280 * 2 - 1 - 0.15;
//g_vertex_buffer_data[1] = 2 - (float)ypos / 720 * 2 - 1 - 0.15;
//g_vertex_buffer_data[3] = (float)xpos / 1280 * 2 - 1 + 0.15;
//g_vertex_buffer_data[4] = 2 - (float)ypos / 720 * 2 - 1 - 0.15;
//g_vertex_buffer_data[6] = (float)xpos / 1280 * 2 - 1;
//g_vertex_buffer_data[7] = 2 - (float)ypos / 720 * 2 - 1 + 0.15;
time_t t = time(NULL);
for (int i = 1; i < 4; i++) {
GLfloat *temp_mat;
temp_mat = matrix_new();
temp_mat[0] = cos(M_PI*2/60*(t%60));
temp_mat[4] = -sin(M_PI*2/60*(t%60));
temp_mat[1] = sin(M_PI*2/60*(t%60));
temp_mat[5] = cos(M_PI*2/60*(t%60));
matrices[i] = temp_mat;
t /= 60;
}
for (int i = 2; i < 5; i++) {
GLfloat *slice;
slice = matrix_transform(&(orig[model->entities[i]->offset]), model->entities[i]->size, matrices[i-1]);
memcpy(&(temp[model->entities[i]->offset]), slice, model->entities[i]->size* 4 * sizeof(GLfloat));
free(slice);
}
free(buffer);
buffer = matrix_transform(temp, model->bufsize, projection);
memcpy(model->object, buffer, model->bufsize * 4 * sizeof(GLfloat));
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, model->bufsize * 4 * sizeof(GLfloat), model->object, GL_STATIC_DRAW);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
4, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
NULL // array buffer offset
);
// Draw!
glDrawArrays(GL_TRIANGLES, 0, model->bufsize); // 3 indices starting at 0 -> 1 triangle
glDisableVertexAttribArray(0);
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
// Check if the ESC key was pressed or the window was closed
usleep(1000000/60);
} while(glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
!glfwWindowShouldClose(window));
// Close OpenGL window and terminate GLFW
for (int i = 0; i < 4; i++) {
free(matrices[i]);
}
free(matrices);
glfwTerminate();
return 0;
}

View file

@ -1,14 +0,0 @@
// Include APIs
#include "clock.h"
int
main(int argc, char *argv[]) {
GLFWwindow *window;
if (clock_init(&window)) {
return -1;
}
return clock_run(window);
}

View file

@ -1,66 +0,0 @@
#include "clock.h"
GLfloat *
matrix_new() {
GLfloat *mat;
mat = calloc(16, sizeof(GLfloat));
for (int i = 0; i < 4; i++) {
mat[i*4+i] = 1;
}
return mat;
}
GLfloat *
matrix_multip(GLfloat *mat1, GLfloat *mat2) {
GLfloat *result;
GLfloat dot_prod;
result = matrix_new();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
dot_prod = 0;
for (int k = 0; k < 4; k++) {
dot_prod += mat1[i*4+k] * mat2[j+k*4];
}
result[j+i*4] = dot_prod;
}
}
return result;
}
GLfloat *
matrix_transform(GLfloat *vects, int vectcount,
GLfloat *mat) {
GLfloat dot_prod;
GLfloat *helper = NULL;
GLfloat *result;
result = calloc(vectcount*4, sizeof(GLfloat));
for (int k = 0; k < vectcount; k++) {
for (int j = 0; j < 4; j++) {
dot_prod = 0;
for (int i = 0; i < 4; i++) {
dot_prod += vects[k*4+i] * mat[i+j*4];
}
result[j+k*4] = dot_prod;
}
if (result[k*4+3] != 0.0f) {
GLfloat div = result[k*4+3];
for (int i = 0; i < 4; i++) {
result[k*4+i] /= div;
}
}
}
return result;
}

View file

@ -1,107 +0,0 @@
#include <clock.h>
Model *
model_new(size_t size) {
Model *model = calloc(1, sizeof(Model));
model->object = calloc((size ? size : 1) *4 , sizeof(GLfloat));
model->bufsize = size;
for (int i = 0; i < 5; i++) {
model->entities[i] = calloc(1, sizeof(Entity));
}
}
void
model_free(Model *self) {
free(self->object);
free(self);
for (int i = 0; i < 5; i++) {
free(self->entities[i]);
}
}
Model *
model_load(const char *path) {
Model *model;
GLfloat *vertices;
int **faces;
size_t vertcount, facecount[5] = {0};
char type, check, *buffer;
FILE *f;
GLfloat colorset[3];
size_t entity_read;
f = fopen(path, "r");
buffer = malloc(255);
vertices = malloc(3 * sizeof(GLfloat));
faces = malloc(5*sizeof(int *));
for (int i = 0; i < 5; i++) {
faces[i] = malloc(3 * sizeof(int));
}
type = 0;
vertcount = 0;
do {
check = fscanf(f, "%c", &type);
if (check == EOF) {
break;
}
else if (type == 'v') {
vertices = realloc(vertices, (vertcount+1)*3*sizeof(GLfloat));
check = fscanf(f, "%f %f %f\n", &(vertices[vertcount*3]),
&(vertices[vertcount*3+1]),
&(vertices[vertcount*3+2]));
vertcount++;
}
else if (type == 'f') {
faces[entity_read] = realloc(faces[entity_read], (facecount[entity_read]+1)*3*sizeof(GLfloat));
check = fscanf(f, "%d %d %d\n", &(faces[entity_read][facecount[entity_read]*3]),
&(faces[entity_read][facecount[entity_read]*3+1]),
&(faces[entity_read][facecount[entity_read]*3+2]));
facecount[entity_read]++;
}
else if (type == 'o') {
check = fscanf(f, "%s\n", buffer);
if (strstr(buffer, "Sphere")) {
entity_read = 0;
}
else if (strstr(buffer, "Text")) {
entity_read = 1;
}
else if (strstr(buffer, "Sec")) {
entity_read = 2;
}
else if (strstr(buffer, "Min")) {
entity_read = 3;
}
else if (strstr(buffer, "Hrs")) {
entity_read = 4;
}
}
else {
check = fscanf(f, "%*[^\n]\n", NULL);
continue;
}
} while(check != EOF);
int total_facecount = 0;
for (int i = 0; i < 5; i++) {
total_facecount += facecount[i];
}
model = model_new(total_facecount*3);
int offset = 0;
for (int ent = 0; ent < 5; ent++) {
model->entities[ent]->offset = offset;
for (int i = 0; i < facecount[ent]; i++) {
for (int j = 0; j < 3; j++) {
for (int k = 0; k < 3; k++) {
model->object[i*12+j*4+k+offset] = vertices[(faces[ent][i*3+j]-1)*3+k];
}
model->object[i*12+j*4+3+offset] = 1;
}
}
offset += facecount[ent]*4*3;
model->entities[ent]->size = facecount[ent]*3;
}
return model;
}

View file

@ -1,118 +0,0 @@
#include "clock.h"
#include "shader.h"
static int
load_code(const char *filepath, char **code) {
FILE *file;
int cursor;
char c;
file = fopen(filepath, "r");
if (file == NULL) {
fprintf(stderr, "Could not open %s.\n", filepath);
return 1;
}
*code = malloc(256 * sizeof(char));
if (code == NULL) {
fprintf(stderr, "Out of memory", filepath);
return 1;
}
cursor = 0;
while ((c = fgetc(file)) != EOF) {
(*code)[cursor] = c;
cursor++;
}
return 0;
}
static int
compile_code(const char *filepath, const char *code,
GLuint ShaderID, GLuint *Result) {
int InfoLogLength;
// Compile Shader
printf("Compiling shader : %s\n", filepath);
glShaderSource(ShaderID, 1, (const char **)&code, NULL);
glCompileShader(ShaderID);
// Check Shader
glGetShaderiv(ShaderID, GL_COMPILE_STATUS, Result);
glGetShaderiv(ShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0) {
char *ShaderErrorMessage = malloc(InfoLogLength+1);
glGetShaderInfoLog(ShaderID, InfoLogLength, NULL, ShaderErrorMessage);
printf("%s\n", ShaderErrorMessage);
free(ShaderErrorMessage);
return -1;
}
return 0;
}
int
LoadShaders(GLuint *programID, const char *vertex_file_path,
const char *fragment_file_path) {
int retval = -1;
const char *vertex_code = NULL;
const char *fragment_code = NULL;
// Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
// Read the Vertex Shader code from the file
if (load_code(vertex_file_path, (char **)&vertex_code)) {
goto end;
}
// Read the Fragment Shader code from the file
if (load_code(fragment_file_path, (char **)&fragment_code)) {
goto end;
}
GLint Result = GL_FALSE;
// Compile Vertex Shader
if (compile_code(vertex_file_path, vertex_code, VertexShaderID, &Result)) {
goto end;
}
// Compile Fragment Shader
if (compile_code(fragment_file_path, fragment_code, FragmentShaderID, &Result)) {
goto end;
}
// Link the program
printf("Linking program\n");
*programID = glCreateProgram();
glAttachShader(*programID, VertexShaderID);
glAttachShader(*programID, FragmentShaderID);
glLinkProgram(*programID);
GLuint InfoLogLength;
// Check the program
glGetProgramiv(*programID, GL_LINK_STATUS, &Result);
glGetProgramiv(*programID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0) {
char *ProgramErrorMessage = malloc(InfoLogLength+1);
glGetProgramInfoLog(*programID, InfoLogLength, NULL, ProgramErrorMessage);
printf("%s\n", ProgramErrorMessage);
}
glDetachShader(*programID, VertexShaderID);
glDetachShader(*programID, FragmentShaderID);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
// If code got here, it means it was successful
retval = 0;
end:
xfree(vertex_code);
xfree(fragment_code);
return retval;
}