Compare commits
No commits in common. "devel" and "master" have entirely different histories.
15 changed files with 99 additions and 2710 deletions
|
@ -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}
|
|
||||||
)
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
#ifndef SHADER_H
|
|
||||||
#define SHADER_H
|
|
||||||
|
|
||||||
int LoadShaders(GLuint *, const char *, const char *);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
72
main.c
Normal file
72
main.c
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
// 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, "Tutorial 01", 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;
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
201
src/clock.c
201
src/clock.c
|
@ -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;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
14
src/main.c
14
src/main.c
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
66
src/matrix.c
66
src/matrix.c
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
107
src/model.c
107
src/model.c
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
118
src/shader.c
118
src/shader.c
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue