#include <stdio.h>
#include <stdlib.h>
+#include <stdbool.h>
#include <malloc.h>
-#include <stdarg.h>
+#include <alloca.h>
#include <unistd.h>
+#include <math.h>
#include <GLES3/gl3.h>
#include <GLFW/glfw3.h>
+#include "types.h"
+#include "utils.h"
+#include "physics.h"
+
+#define PI 3.141592653589793238462643383
+
#define WINDOW_WIDTH 1600
#define WINDOW_HEIGHT 900
#define WINDOW_TITLE "N-Body Simulation"
-void panic_and_die(const char* msg, ...) __attribute__((noreturn));
-void panic_and_die(const char* msg, ...) {
- puts("************ PANIC ************");
-
- va_list va;
- va_start(va, msg);
- vprintf(msg, va);
- va_end(va);
-
-#ifdef DEBUG
- // NOTE: This allows for a debugger to stop here.
- __asm("int $3");
-#endif
-
- exit(1);
-}
-
-void glfw_key_handler(GLFWwindow* window, int key, int scancode, int action, int mods) {
+void glfw_key_handler(GLFWwindow* window, i32 key, i32 scancode, i32 action, i32 mods) {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, 1);
}
-void glfw_resize_handler(GLFWwindow* window, int width, int height) {
+void glfw_resize_handler(GLFWwindow* window, i32 width, i32 height) {
glViewport(0, 0, width, height);
}
-void glfw_error_handler(int error, const char* desc) {
+void glfw_error_handler(i32 error, const char* desc) {
panic_and_die("GLFW Error (%d): %s\n", error, desc);
}
GLFWwindow* window;
-void init_opengl() {
+void init_glfw() {
if (!glfwInit()) panic_and_die("Failed to initalize GLFW.");
glfwSetErrorCallback(glfw_error_handler);
window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE, NULL, NULL);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
- glfwMakeContextCurrent(window);
+ glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glfwSetKeyCallback(window, glfw_key_handler);
glfwSetFramebufferSizeCallback(window, glfw_resize_handler);
+
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_CCW);
+}
+
+GLuint load_shader(GLenum shader_type, const char* shader_loc) {
+ GLuint shader = glCreateShader(shader_type);
+
+ FILE* shader_file = fopen(shader_loc, "rb");
+ if (shader_file == NULL) panic_and_die("Shader file not found: %s\n", shader_loc);
+
+ fseek(shader_file, 0, SEEK_END);
+ i32 shader_file_size = ftell(shader_file);
+ fseek(shader_file, 0, SEEK_SET);
+
+ char* shader_buffer = malloc(shader_file_size + 1);
+ fread(shader_buffer, 1, shader_file_size, shader_file);
+ fclose(shader_file);
+
+ shader_buffer[shader_file_size] = 0;
+
+ glShaderSource(shader, 1, (const char* const*) &shader_buffer, NULL);
+ glCompileShader(shader);
+
+ GLint successful;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &successful);
+ if (successful != GL_TRUE) {
+ GLsizei log_length = 0;
+ GLchar shader_log[1024];
+ glGetShaderInfoLog(shader, 1023, &log_length, shader_log);
+ shader_log[log_length] = 0;
+
+ panic_and_die("Error compiling %s:\n%s\n", shader_loc, shader_log);
+ }
+
+ free(shader_buffer);
+
+ return shader;
+}
+
+GLuint create_program(GLuint vertex_shader, GLuint fragment_shader) {
+ GLuint program = glCreateProgram();
+ glAttachShader(program, vertex_shader);
+ glAttachShader(program, fragment_shader);
+ glLinkProgram(program);
+
+ GLint successful;
+ glGetProgramiv(program, GL_LINK_STATUS, &successful);
+ if (successful != GL_TRUE) {
+ GLsizei log_length = 0;
+ GLchar program_log[1024];
+ glGetProgramInfoLog(program, 1023, &log_length, program_log);
+ program_log[log_length] = 0;
+
+ panic_and_die("Error linking program:\n%s", program_log);
+ }
+
+ return program;
+}
+
+
+
+
+
+
+
+#define CIRCLE_POINT_COUNT 36 // NOTE(Brendan): Treat a circle as a many-sided polygon.
+
+// NOTE(Brendan): Returns the VAO where the mesh data was bound.
+GLsizei create_circle_mesh() {
+ GLsizei vao;
+ glGenVertexArrays(1, &vao);
+ glBindVertexArray(vao);
+
+ V2f circle_points[CIRCLE_POINT_COUNT] = {};
+ foreach (i, 0, CIRCLE_POINT_COUNT) {
+ f32 t = (f32) i / (f32) CIRCLE_POINT_COUNT;
+ circle_points[i].x = cos(t * 2 * PI) / 2.0f;
+ circle_points[i].y = sin(t * 2 * PI) / 2.0f;
+ }
+
+ GLsizei vertex_buffer;
+ glGenBuffers(1, &vertex_buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(circle_points), &circle_points, GL_STATIC_DRAW);
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, 2, GL_FLOAT, false, sizeof(V2f), (void *) offset_of(V2f, x));
+ glBindBuffer(GL_ARRAY_BUFFER, -1);
+
+ u8 circle_indicies[CIRCLE_POINT_COUNT] = {};
+ foreach(i, 0, CIRCLE_POINT_COUNT) circle_indicies[i] = i;
+
+ GLsizei index_buffer;
+ glGenBuffers(1, &index_buffer);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(circle_indicies), &circle_indicies, GL_STATIC_DRAW);
+
+ glBindVertexArray(-1);
+
+ return vao;
}
void deinit_opengl() {
glfwTerminate();
}
-// NOTE: dt is expected to be in units of "per second".
-void update(double dt) {
+// NOTE(Brendan): dt is expected to be in units of "per second".
+void update(f64 dt) {
}
+GLsizei circle_mesh;
void draw() {
glClearColor(0.1, 0.1, 0.1, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glfwSwapBuffers(window);
+
+ glBindVertexArray(circle_mesh);
+ glDrawElements(GL_TRIANGLE_FAN, CIRCLE_POINT_COUNT, GL_UNSIGNED_BYTE, 0);
+ glBindVertexArray(-1);
+
+ glfwSwapBuffers(window);
}
void loop() {
- double last_time = glfwGetTime();
- double curr_time = last_time;
- double delta;
+ f64 last_time = glfwGetTime();
+ f64 curr_time = last_time;
+ f64 delta;
- while (!glfwWindowShouldClose(window)) {
- glfwPollEvents();
+ while (!glfwWindowShouldClose(window)) {
+ glfwPollEvents();
- curr_time = glfwGetTime();
- delta = curr_time - last_time;
- last_time = curr_time;
+ curr_time = glfwGetTime();
+ delta = curr_time - last_time;
+ last_time = curr_time;
if (delta > 0.0) {
-
update(delta);
draw();
}
- }
+ }
}
-int main(int argc, char* argv[]) {
- init_opengl();
+i32 main(i32 argc, char* argv[]) {
+ init_glfw();
+ circle_mesh = create_circle_mesh();
+
+ GLuint v_shader = load_shader(GL_VERTEX_SHADER, "res/shaders/planet_vert.glsl");
+ GLuint f_shader = load_shader(GL_FRAGMENT_SHADER, "res/shaders/planet_frag.glsl");
+ GLuint program = create_program(v_shader, f_shader);
+
+ glUseProgram(program);
loop();
+
deinit_opengl();
return 0;