Add ortographic camera
This commit is contained in:
parent
4a3dfeafdc
commit
8c4b7bff18
5 changed files with 202 additions and 14 deletions
4
Makefile
4
Makefile
|
|
@ -1,5 +1,5 @@
|
||||||
CFLAGS=-Wall -Wextra -g -pedantic -fenable-matrix -Wno-gnu-zero-variadic-macro-arguments -Wno-incompatible-pointer-types-discards-qualifiers
|
CFLAGS=-Wall -Wextra -g3 -pedantic -fenable-matrix -Wno-gnu-zero-variadic-macro-arguments -Wno-incompatible-pointer-types-discards-qualifiers -fsanitize=undefined -fsanitize-trap -Wconversion -Wno-implicit-int-float-conversion -Wno-implicit-float-conversion -Wno-gnu-empty-initializer
|
||||||
LIBS=`pkg-config --libs glfw3 glew opengl` -lm
|
LIBS=`pkg-config --libs glfw3 glew opengl` -lm
|
||||||
|
|
||||||
hexnando: main.c Makefile
|
hexnando: main.c Makefile hex_math.h hex_debug.h
|
||||||
clang ${CFLAGS} ${LIBS} main.c -o hexnando
|
clang ${CFLAGS} ${LIBS} main.c -o hexnando
|
||||||
|
|
|
||||||
12
hex_debug.h
Normal file
12
hex_debug.h
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef HEX_DEBUG_H
|
||||||
|
#include <stdio.h>
|
||||||
|
#define DEBUG_VERBOSITY 1
|
||||||
|
|
||||||
|
#define log_err(str, ...) do { fprintf(stderr, "[ERROR] (%s:%d): " str "\n", __FILE__, __LINE__, ##__VA_ARGS__); } while (0)
|
||||||
|
|
||||||
|
#if (DEBUG_VERBOSITY > 0)
|
||||||
|
#define log_debug(str, ...) do { fprintf(stderr, "[DEBUG] (%s:%d): " str "\n", __FILE__, __LINE__, ##__VA_ARGS__); } while (0)
|
||||||
|
#else
|
||||||
|
#define log_debug(str, ...)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
87
hex_math.h
87
hex_math.h
|
|
@ -1,10 +1,26 @@
|
||||||
#define _USE_MATH_DEFINES // for finding things like M_PI in Windows build
|
#define _USE_MATH_DEFINES // for finding things like M_PI in Windows build
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "hex_debug.h"
|
||||||
/* Types */
|
/* Types */
|
||||||
typedef float _v2f __attribute__((matrix_type(1,2)));
|
typedef float _v2f __attribute__((matrix_type(1,2)));
|
||||||
typedef float _v3f __attribute__((matrix_type(1,3)));
|
typedef float _v3f __attribute__((matrix_type(1,3)));
|
||||||
typedef float _v4f __attribute__((matrix_type(1,4)));
|
typedef float _v4f __attribute__((matrix_type(1,4)));
|
||||||
|
typedef float _mat4 __attribute__((matrix_type(4,4)));
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
float first;
|
||||||
|
float second;
|
||||||
|
};
|
||||||
|
_v2f v2f;
|
||||||
|
struct {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} vec2f;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
union {
|
union {
|
||||||
|
|
@ -36,6 +52,37 @@ typedef struct {
|
||||||
};
|
};
|
||||||
} vec4f;
|
} vec4f;
|
||||||
|
|
||||||
|
/* Row-major matrix, make sure to pass it to OpenGL trasposed */
|
||||||
|
typedef struct {
|
||||||
|
union {
|
||||||
|
_mat4 m4f;
|
||||||
|
struct {
|
||||||
|
float a0;
|
||||||
|
float a1;
|
||||||
|
float a2;
|
||||||
|
float a3;
|
||||||
|
float b0;
|
||||||
|
float b1;
|
||||||
|
float b2;
|
||||||
|
float b3;
|
||||||
|
float c0;
|
||||||
|
float c1;
|
||||||
|
float c2;
|
||||||
|
float c3;
|
||||||
|
float d0;
|
||||||
|
float d1;
|
||||||
|
float d2;
|
||||||
|
float d3;
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
vec4f row0;
|
||||||
|
vec4f row1;
|
||||||
|
vec4f row2;
|
||||||
|
vec4f row3;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} mat4f;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
vec4f position; // center pos
|
vec4f position; // center pos
|
||||||
float radius; // side length
|
float radius; // side length
|
||||||
|
|
@ -44,7 +91,6 @@ typedef struct {
|
||||||
uint32_t vbo;
|
uint32_t vbo;
|
||||||
float vertices[7*3]; // 7 vert per hex
|
float vertices[7*3]; // 7 vert per hex
|
||||||
unsigned int indices[6*3]; // 6 triangles to render a hex
|
unsigned int indices[6*3]; // 6 triangles to render a hex
|
||||||
|
|
||||||
} hex_t;
|
} hex_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
@ -53,7 +99,17 @@ typedef struct {
|
||||||
uint32_t columns;
|
uint32_t columns;
|
||||||
} hexgrid_t;
|
} hexgrid_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float left;
|
||||||
|
float right;
|
||||||
|
float top;
|
||||||
|
float bottom;
|
||||||
|
float near;
|
||||||
|
float far;
|
||||||
|
} camera_t;
|
||||||
|
|
||||||
_Static_assert(sizeof(vec4f) == sizeof(float) * 4, "Bad vector size");
|
_Static_assert(sizeof(vec4f) == sizeof(float) * 4, "Bad vector size");
|
||||||
|
_Static_assert(sizeof(mat4f) == sizeof(float) * 16, "Bad matrix size");
|
||||||
|
|
||||||
/* Functions */
|
/* Functions */
|
||||||
double sint(double turns)
|
double sint(double turns)
|
||||||
|
|
@ -65,3 +121,32 @@ double cost(double turns)
|
||||||
{
|
{
|
||||||
return cos(turns*2*M_PI);
|
return cos(turns*2*M_PI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mat4f ortho_matrix(float left, float right, float top, float bottom, float near, float far, float width, float height)
|
||||||
|
{
|
||||||
|
// Invert Y coord
|
||||||
|
float aux;
|
||||||
|
aux = bottom;
|
||||||
|
bottom = top;
|
||||||
|
top = aux;
|
||||||
|
|
||||||
|
// Scale and move to [-1,1]
|
||||||
|
left = (left*2 - width)/width;
|
||||||
|
right = (right*2 - width)/width;
|
||||||
|
|
||||||
|
top = (top*2 - height)/height;
|
||||||
|
bottom = (bottom*2 - height)/height;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
mat4f matrix = {};
|
||||||
|
matrix.a0 = 2/(right - left);
|
||||||
|
matrix.a3 = -((right + left)/(right - left));
|
||||||
|
matrix.b1 = 2/(top - bottom);
|
||||||
|
matrix.b3 = -((top + bottom)/(top - bottom));
|
||||||
|
matrix.c2 = -2/(far - near);
|
||||||
|
matrix.c3 = -((far + near)/(far - near));
|
||||||
|
matrix.d3 = 1;
|
||||||
|
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
|
|
||||||
105
main.c
105
main.c
|
|
@ -8,9 +8,8 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "hex_math.h"
|
#include "hex_math.h"
|
||||||
|
#include "hex_debug.h"
|
||||||
|
|
||||||
#define log_err(str, ...) do { fprintf(stderr, "[ERROR] (%s:%d): " str "\n", __FILE__, __LINE__, ##__VA_ARGS__); } while (0)
|
|
||||||
#define log_debug(str, ...) do { fprintf(stderr, "[DEBUG] (%s:%d): " str "\n", __FILE__, __LINE__, ##__VA_ARGS__); } while (0)
|
|
||||||
|
|
||||||
char *read_entire_file(char *path)
|
char *read_entire_file(char *path)
|
||||||
{
|
{
|
||||||
|
|
@ -20,7 +19,7 @@ char *read_entire_file(char *path)
|
||||||
if (f)
|
if (f)
|
||||||
{
|
{
|
||||||
fseek(f, 0, SEEK_END);
|
fseek(f, 0, SEEK_END);
|
||||||
length = ftell(f);
|
length = (size_t)ftell(f);
|
||||||
fseek(f, 0, SEEK_SET);
|
fseek(f, 0, SEEK_SET);
|
||||||
if (length)
|
if (length)
|
||||||
{
|
{
|
||||||
|
|
@ -37,12 +36,31 @@ static void glfw_error_callback(int errcode, const char *description)
|
||||||
fprintf(stderr, "[GLFW ERROR][ERRCODE %d] %s\n", errcode, description);
|
fprintf(stderr, "[GLFW ERROR][ERRCODE %d] %s\n", errcode, description);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_uniform(GLuint program_id, const char *name, vec4f value)
|
void set_uniform4f(GLuint program_id, const char *name, vec4f value)
|
||||||
{
|
{
|
||||||
GLint location = glGetUniformLocation(program_id, name);
|
GLint location = glGetUniformLocation(program_id, name);
|
||||||
glUniform4f(location, value.x, value.y, value.z, value.w);
|
glUniform4f(location, value.x, value.y, value.z, value.w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_uniform2f(GLuint program_id, const char *name, vec2f value)
|
||||||
|
{
|
||||||
|
GLint location = glGetUniformLocation(program_id, name);
|
||||||
|
glUniform2f(location, value.x, value.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_uniform4x4f(GLuint program_id, const char *name, mat4f value)
|
||||||
|
{
|
||||||
|
GLint location = glGetUniformLocation(program_id, name);
|
||||||
|
glUniformMatrix4fv(location, 1, GL_TRUE, &value.a0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define set_uniform(id, name, value) _Generic((value), \
|
||||||
|
vec4f: set_uniform4f, \
|
||||||
|
vec2f: set_uniform2f, \
|
||||||
|
mat4f: set_uniform4x4f)(id, name, value)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
GLFWwindow *window;
|
GLFWwindow *window;
|
||||||
|
|
@ -112,12 +130,12 @@ int main(void)
|
||||||
background_color.a = 1.0f;
|
background_color.a = 1.0f;
|
||||||
|
|
||||||
hexgrid_t grid;
|
hexgrid_t grid;
|
||||||
grid.rows = 10;
|
grid.rows = 30;
|
||||||
grid.columns = 10;
|
grid.columns = 30;
|
||||||
grid.hexes = calloc(1, sizeof(hex_t) * grid.rows * grid.columns);
|
grid.hexes = calloc(1, sizeof(hex_t) * grid.rows * grid.columns);
|
||||||
|
|
||||||
// Scale of hexagon relative to screen. A 1:1 hexagon would reach the entire horizontal space
|
// Scale of hexagon relative to screen. A 1:1 hexagon would reach the entire horizontal space
|
||||||
float scale = 1.0f / 5.0f;
|
float scale = 1.0f / 1.0f;
|
||||||
|
|
||||||
for (size_t i = 0; i < grid.columns; ++i)
|
for (size_t i = 0; i < grid.columns; ++i)
|
||||||
{
|
{
|
||||||
|
|
@ -126,13 +144,14 @@ int main(void)
|
||||||
// Offset the X and Y coordinates of adjacent hexagons so they do not cut each other
|
// Offset the X and Y coordinates of adjacent hexagons so they do not cut each other
|
||||||
float offset = 0.0f;
|
float offset = 0.0f;
|
||||||
if (j % 2)
|
if (j % 2)
|
||||||
offset = sint(1.0f/6);
|
offset = (float)sint(1.0f/6);
|
||||||
|
|
||||||
grid.hexes[i*grid.rows+j].position.x = (0.0f + j*(1 + cost(1.0f/6)));
|
grid.hexes[i*grid.rows+j].position.x = (0.0f + j*(1 + cost(1.0f/6)));
|
||||||
grid.hexes[i*grid.rows+j].position.y = (0.0f + i*(sint(1.0f/6))*2.0f) + offset;
|
grid.hexes[i*grid.rows+j].position.y = (0.0f + i*(sint(1.0f/6))*2.0f) + offset;
|
||||||
grid.hexes[i*grid.rows+j].position.z = 0.0f;
|
grid.hexes[i*grid.rows+j].position.z = 0.0f;
|
||||||
|
|
||||||
grid.hexes[i*grid.rows+j].position.w = 1.0f;
|
grid.hexes[i*grid.rows+j].position.w = 1.0f;
|
||||||
fprintf(stdout, "Position of hex %ld %ld is %f %f\n", i, j, grid.hexes[i*grid.rows+j].position.x, grid.hexes[i*grid.rows+j].position.y);
|
log_debug("Position of hex %ld %ld is %f %f\n", i, j, grid.hexes[i*grid.rows+j].position.x, grid.hexes[i*grid.rows+j].position.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -184,8 +203,63 @@ int main(void)
|
||||||
//glBindBuffer(GL_ARRAY_BUFFER, 0);
|
//glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
//glBindVertexArray(0);
|
//glBindVertexArray(0);
|
||||||
|
|
||||||
|
camera_t camera = {};
|
||||||
|
camera.near = -0.1f;
|
||||||
|
camera.far = 1.0f;
|
||||||
|
camera.left = 0.0f;
|
||||||
|
camera.right = 600.0f;
|
||||||
|
camera.top = 0.0f;
|
||||||
|
camera.bottom = 600.0f;
|
||||||
|
|
||||||
while (!glfwWindowShouldClose(window))
|
while (!glfwWindowShouldClose(window))
|
||||||
{
|
{
|
||||||
|
// Camera logic
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_A))
|
||||||
|
{
|
||||||
|
camera.right -= (camera.right - camera.left) * 0.01f;
|
||||||
|
camera.left -= (camera.right - camera.left) * 0.01f;
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_D))
|
||||||
|
{
|
||||||
|
camera.right += (camera.right - camera.left) * 0.01f;
|
||||||
|
camera.left += (camera.right - camera.left) * 0.01f;
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_W))
|
||||||
|
{
|
||||||
|
camera.top += (camera.bottom - camera.top) * 0.01f;
|
||||||
|
camera.bottom += (camera.bottom - camera.top) * 0.01f;
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_S))
|
||||||
|
{
|
||||||
|
camera.top -= (camera.bottom - camera.top) * 0.01f;
|
||||||
|
camera.bottom -= (camera.bottom - camera.top) * 0.01f;
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_Q))
|
||||||
|
{
|
||||||
|
float offset = (camera.right - camera.left)*0.02f;
|
||||||
|
camera.right -= offset;
|
||||||
|
camera.left += offset;
|
||||||
|
camera.top += offset;
|
||||||
|
camera.bottom -= offset;
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_E))
|
||||||
|
{
|
||||||
|
float offset = (camera.right - camera.left)*0.05f;
|
||||||
|
camera.right += offset;
|
||||||
|
camera.left -= offset;
|
||||||
|
camera.top -= offset;
|
||||||
|
camera.bottom += offset;
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_R))
|
||||||
|
{
|
||||||
|
camera.near = -0.1f;
|
||||||
|
camera.far = 1.0f;
|
||||||
|
camera.left = 0.0f;
|
||||||
|
camera.right = 400.0f;
|
||||||
|
camera.top = 0.0f;
|
||||||
|
camera.bottom = 400.0f;
|
||||||
|
}
|
||||||
|
|
||||||
int width, height;
|
int width, height;
|
||||||
glfwGetFramebufferSize(window, &width, &height);
|
glfwGetFramebufferSize(window, &width, &height);
|
||||||
glViewport(0, 0, width, height);
|
glViewport(0, 0, width, height);
|
||||||
|
|
@ -194,10 +268,19 @@ int main(void)
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
glUseProgram(shader_program);
|
glUseProgram(shader_program);
|
||||||
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
mat4f camera_matrix = ortho_matrix(camera.left, camera.right, camera.top, camera.bottom, camera.near, camera.far, width, height);
|
||||||
|
set_uniform(shader_program, "camera", camera_matrix);
|
||||||
|
|
||||||
|
vec2f window_size = { .x = (float)width, .y = (float)height };
|
||||||
|
set_uniform(shader_program, "window_size", window_size);
|
||||||
|
|
||||||
|
// For debugging
|
||||||
|
float aux;
|
||||||
|
glGetUniformfv(shader_program, glGetUniformLocation(shader_program, "window_size"), &aux);
|
||||||
|
|
||||||
for (size_t i = 0; i < grid.rows * grid.columns; ++i)
|
for (size_t i = 0; i < grid.rows * grid.columns; ++i)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -207,6 +290,7 @@ int main(void)
|
||||||
hex_color.g = (float)i / (grid.rows * grid.columns);
|
hex_color.g = (float)i / (grid.rows * grid.columns);
|
||||||
hex_color.b = (float)i / (grid.rows * grid.columns);
|
hex_color.b = (float)i / (grid.rows * grid.columns);
|
||||||
hex_color.a = 1.0f;
|
hex_color.a = 1.0f;
|
||||||
|
|
||||||
set_uniform(shader_program, "uniform_color", hex_color);
|
set_uniform(shader_program, "uniform_color", hex_color);
|
||||||
glBindVertexArray(grid.hexes[i].vao);
|
glBindVertexArray(grid.hexes[i].vao);
|
||||||
|
|
||||||
|
|
@ -215,6 +299,7 @@ int main(void)
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, grid.hexes[i].ebo);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, grid.hexes[i].ebo);
|
||||||
glDrawElements(GL_TRIANGLES, 3*6, GL_UNSIGNED_INT, 0);
|
glDrawElements(GL_TRIANGLES, 3*6, GL_UNSIGNED_INT, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
glfwSwapBuffers(window);
|
glfwSwapBuffers(window);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,20 @@
|
||||||
#version 330 core
|
#version 330 core
|
||||||
layout (location = 0) in vec3 pos;
|
layout (location = 0) in vec3 pos;
|
||||||
uniform vec4 uniform_color;
|
uniform vec4 uniform_color;
|
||||||
|
uniform mat4 camera;
|
||||||
|
uniform vec2 window_size;
|
||||||
out vec4 vertex_color;
|
out vec4 vertex_color;
|
||||||
const mat4 to_draw_coordinates_matrix = mat4(
|
const mat4 to_draw_coordinates_matrix = mat4(
|
||||||
1., 0., 0., 0.,
|
1., 0., 0., 0.,
|
||||||
0., -1., 0., 0.,
|
0., -1., 0., 0.,
|
||||||
0., 0., 1., 0.,
|
0., 0., 1., 0.,
|
||||||
-1, 1, 0, 1);
|
-1, 1, 0, 1);
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
gl_Position = to_draw_coordinates_matrix*vec4(pos, 1.0f);
|
float aspect_ratio = window_size.x / window_size.y;
|
||||||
|
mat4 scaling_matrix = mat4(1.0);
|
||||||
|
scaling_matrix[1][1] = aspect_ratio;
|
||||||
|
gl_Position = camera*scaling_matrix*to_draw_coordinates_matrix*vec4(pos, 1.0f);
|
||||||
vertex_color = uniform_color;
|
vertex_color = uniform_color;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue