Chunk manager, fixed some chunk mesh problems
@@ -1,9 +1,9 @@
|
||||
SRC=src/math_3d.c src/main.c src/mesh.c src/program.c src/resources.c src/camera.c \
|
||||
src/chunk/chunk.c src/chunk/noise.c src/chunk/chunkmesh.c src/flags.c src/texture.c
|
||||
SRC=src/math_3d.c src/main.c src/program.c src/resources.c src/camera.c \
|
||||
src/chunk/chunk.c src/chunk/mesh.c src/flags.c src/texture.c src/chunk/manager.c
|
||||
|
||||
OBJ=$(SRC:.c=.o)
|
||||
CFLAGS=-Werror -Wextra -Wall `pkg-config --cflags sdl3 sdl3-image gl`
|
||||
LDFLAGS=`pkg-config --libs sdl3 sdl3-image gl` -lm
|
||||
CFLAGS=-Werror -Wextra -Wall `pkg-config --cflags sdl3 sdl3-image gl glib-2.0`
|
||||
LDFLAGS=`pkg-config --libs sdl3 sdl3-image gl glib-2.0` -lm
|
||||
TARGET=wschod
|
||||
CC=gcc
|
||||
LD=gcc
|
||||
|
||||
@@ -3,19 +3,18 @@
|
||||
precision lowp float;
|
||||
|
||||
varying vec2 f_uv;
|
||||
varying vec3 f_material;
|
||||
varying vec4 f_material;
|
||||
varying float f_height;
|
||||
|
||||
uniform sampler2D materials[5];
|
||||
|
||||
void main ()
|
||||
{
|
||||
/* This means there can be four textures on a terrain. Could be
|
||||
extended, but who cares? */
|
||||
vec4 result = texture2D (materials[0], f_uv);
|
||||
result = mix (result, texture2D (materials[1], f_uv), f_material[0]);
|
||||
result = mix (result, texture2D (materials[2], f_uv), f_material[1]);
|
||||
result = mix (result, texture2D (materials[3], f_uv), f_material[2]);
|
||||
result = mix (result, texture2D (materials[4], f_uv), f_material[3]);
|
||||
|
||||
gl_FragColor = result;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
#version 100
|
||||
|
||||
attribute vec4 position;
|
||||
attribute vec3 material;
|
||||
attribute vec4 material;
|
||||
|
||||
varying vec2 f_uv;
|
||||
varying vec4 f_material;
|
||||
varying float f_height;
|
||||
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
varying vec2 f_uv;
|
||||
varying vec3 f_material;
|
||||
varying float f_height;
|
||||
uniform vec4 chunk_position;
|
||||
|
||||
void main ()
|
||||
{
|
||||
@@ -16,5 +17,5 @@ void main ()
|
||||
f_material = material;
|
||||
f_height = position.y;
|
||||
|
||||
gl_Position = projection * view * position;
|
||||
gl_Position = projection * view * (position + chunk_position);
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 50 KiB |
@@ -6,13 +6,15 @@ in
|
||||
|
||||
pkgs.mkShellNoCC {
|
||||
packages = with pkgs; [
|
||||
gcc
|
||||
pkg-config
|
||||
sdl3
|
||||
sdl3-image
|
||||
gdb
|
||||
cglm
|
||||
glew
|
||||
glib
|
||||
|
||||
gcc
|
||||
pkg-config
|
||||
valgrind
|
||||
gdb
|
||||
];
|
||||
}
|
||||
|
||||
@@ -46,3 +46,9 @@ Camera_get_projection (Camera *camera, float aspect)
|
||||
return m4_perspective
|
||||
(camera->fov, aspect, camera->near, camera->far);
|
||||
}
|
||||
|
||||
void
|
||||
Camera_print (Camera *camera)
|
||||
{
|
||||
INFO ("Camera position: (%6.1f, %6.1f, %6.1f)", camera->position.x, camera->position.y, camera->position.z);
|
||||
}
|
||||
|
||||
@@ -18,3 +18,4 @@ vec3_t Camera_get_direction (Camera *camera);
|
||||
vec3_t Camera_get_right (Camera *camera);
|
||||
mat4_t Camera_get_view (Camera *camera);
|
||||
mat4_t Camera_get_projection (Camera *camera, float aspect);
|
||||
void Camera_print (Camera *camera);
|
||||
|
||||
@@ -2,29 +2,24 @@
|
||||
|
||||
#include <math.h>
|
||||
|
||||
Chunk
|
||||
Chunk *
|
||||
Chunk_new ()
|
||||
{
|
||||
Chunk chunk;
|
||||
chunk.heightmap = malloc (sizeof (float) * CHUNK_SIZE);
|
||||
chunk.materialmap = malloc (sizeof (char) * CHUNK_SIZE);
|
||||
INFO ("Created new Chunk. Memory size: %zu bytes",
|
||||
sizeof (float) * CHUNK_SIZE + sizeof (char) * CHUNK_SIZE);
|
||||
Chunk *chunk = malloc (sizeof (Chunk));
|
||||
chunk->heightmap = malloc (sizeof (float) * CHUNK_SIZE);
|
||||
chunk->materialmap = malloc (sizeof (char) * CHUNK_SIZE);
|
||||
return chunk;
|
||||
}
|
||||
|
||||
void
|
||||
Chunk_noise (Chunk *chunk, int xoffset, int yoffset)
|
||||
Chunk_random (Chunk *chunk)
|
||||
{
|
||||
for (int y = 0; y < CHUNK_DIM; ++y)
|
||||
{
|
||||
for (int x = 0; x < CHUNK_DIM; ++x)
|
||||
{
|
||||
(void) xoffset; (void) yoffset;
|
||||
float val = sinf (x) + sinf (y);
|
||||
(void) val;
|
||||
chunk->heightmap[INDEX (x, y)] = 0;
|
||||
chunk->materialmap[INDEX (x, y)] = rand () % 2;
|
||||
chunk->materialmap[INDEX (x, y)] = rand () % 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../util.h"
|
||||
#include "noise.h"
|
||||
|
||||
#define CHUNK_DIM 16
|
||||
#define CHUNK_SIZE (CHUNK_DIM*CHUNK_DIM)
|
||||
@@ -14,7 +15,7 @@ typedef struct Chunk
|
||||
char *materialmap;
|
||||
} Chunk;
|
||||
|
||||
Chunk Chunk_new ();
|
||||
void Chunk_noise (Chunk *chunk, int xoffset, int yoffset);
|
||||
Chunk *Chunk_new ();
|
||||
void Chunk_random (Chunk *chunk);
|
||||
void Chunk_free (Chunk *chunk);
|
||||
void Chunk_heightmap_print (Chunk *chunk);
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
#include "manager.h"
|
||||
|
||||
/* TODO: switch from string keys to struct keys or some other
|
||||
stuff. */
|
||||
|
||||
ChunkManager chunk_manager;
|
||||
|
||||
void
|
||||
ChunkManager_init ()
|
||||
{
|
||||
chunk_manager.chunks = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
chunk_manager.chunk_meshes = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
}
|
||||
|
||||
void
|
||||
cm_get_chunk_pos (float x, float y, int *ox, int *oy)
|
||||
{
|
||||
*ox = floor (x / (float) CHUNK_DIM);
|
||||
*oy = floor (y / (float) CHUNK_DIM);
|
||||
}
|
||||
|
||||
char *
|
||||
cm_coords_to_string (int ox, int oy)
|
||||
{
|
||||
char *buffer = malloc (sizeof (char) * 128);
|
||||
snprintf (buffer, 128, "%d %d", ox, oy);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void
|
||||
ChunkManager_update (float px, float py)
|
||||
/* x = camera's X position, y = camera's Y position */
|
||||
{
|
||||
(void) px; (void) py;
|
||||
int cx = 0, cy = 0;
|
||||
|
||||
/* cm_get_chunk_pos (px, py, &cx, &cy); */
|
||||
|
||||
for (int y = cy - RENDER_DISTANCE - 1; y <= cy + RENDER_DISTANCE + 1; ++y)
|
||||
{
|
||||
for (int x = cx - RENDER_DISTANCE - 1; x <= cx + RENDER_DISTANCE + 1; ++x)
|
||||
{
|
||||
if (ChunkManager_get_chunk_at (x, y) == NULL)
|
||||
{
|
||||
ChunkManager_generate_chunk_at (x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int y = cy - RENDER_DISTANCE; y <= cy + RENDER_DISTANCE; ++y)
|
||||
{
|
||||
for (int x = cx - RENDER_DISTANCE; x <= cx + RENDER_DISTANCE; ++x)
|
||||
{
|
||||
if (ChunkManager_get_chunk_mesh_at (x, y) == NULL)
|
||||
{
|
||||
ChunkManager_generate_chunk_mesh_at (x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ChunkManager_render (float px, float py, int program)
|
||||
{
|
||||
(void) px; (void) py;
|
||||
int cx = 0, cy = 0;
|
||||
/* cm_get_chunk_pos (px, py, &cx, &cy); */
|
||||
|
||||
for (int y = cy - RENDER_DISTANCE; y <= cy + RENDER_DISTANCE; ++y)
|
||||
{
|
||||
for (int x = cx - RENDER_DISTANCE; x <= cx + RENDER_DISTANCE; ++x)
|
||||
{
|
||||
ChunkMesh *mesh = ChunkManager_get_chunk_mesh_at (x, y);
|
||||
if (mesh != NULL)
|
||||
{
|
||||
program_set_vec4 (program, "chunk_position", x * CHUNKMESH_DIM, 0.0, y * CHUNKMESH_DIM, 1.0);
|
||||
ChunkMesh_render (mesh);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Chunk *
|
||||
ChunkManager_get_chunk_at (int x, int y)
|
||||
{
|
||||
char *key = cm_coords_to_string (x, y);
|
||||
return (Chunk *) g_hash_table_lookup (chunk_manager.chunks, key);
|
||||
}
|
||||
|
||||
void
|
||||
ChunkManager_set_chunk_at (int x, int y, Chunk *chunk)
|
||||
{
|
||||
char *key = cm_coords_to_string (x, y);
|
||||
g_hash_table_insert (chunk_manager.chunks, key, chunk);
|
||||
}
|
||||
|
||||
void
|
||||
ChunkManager_generate_chunk_at (int x, int y)
|
||||
{
|
||||
Chunk *chunk = Chunk_new ();
|
||||
Chunk_random (chunk);
|
||||
ChunkManager_set_chunk_at (x, y, chunk);
|
||||
}
|
||||
|
||||
void
|
||||
ChunkManager_get_chunk_neighbors_at (int x, int y, Chunk **nr, Chunk **nd, Chunk **nc)
|
||||
{
|
||||
*nr = ChunkManager_get_chunk_at (x + 1, y);
|
||||
*nd = ChunkManager_get_chunk_at (x, y + 1);
|
||||
*nc = ChunkManager_get_chunk_at (x + 1, y + 1);
|
||||
}
|
||||
|
||||
ChunkMesh *
|
||||
ChunkManager_get_chunk_mesh_at (int x, int y)
|
||||
{
|
||||
char *key = cm_coords_to_string (x, y);
|
||||
return (ChunkMesh *) g_hash_table_lookup (chunk_manager.chunk_meshes, key);
|
||||
}
|
||||
|
||||
void
|
||||
ChunkManager_set_chunk_mesh_at (int x, int y, ChunkMesh *mesh)
|
||||
{
|
||||
char *key = cm_coords_to_string (x, y);
|
||||
g_hash_table_insert (chunk_manager.chunk_meshes, key, mesh);
|
||||
}
|
||||
|
||||
void
|
||||
ChunkManager_generate_chunk_mesh_at (int x, int y)
|
||||
{
|
||||
Chunk *nr, *nd, *nc;
|
||||
ChunkManager_get_chunk_neighbors_at (x, y, &nr, &nd, &nc);
|
||||
ChunkManager_set_chunk_mesh_at
|
||||
(x, y, ChunkMesh_from_Chunk_and_neighbors (ChunkManager_get_chunk_at (x, y), nr, nd, nc));
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
/* Yes, glib. */
|
||||
#include <glib-2.0/glib.h>
|
||||
|
||||
#include "../program.h"
|
||||
#include "chunk.h"
|
||||
#include "mesh.h"
|
||||
|
||||
#define RENDER_DISTANCE 1
|
||||
|
||||
typedef struct ChunkManager
|
||||
{
|
||||
GHashTable *chunks;
|
||||
GHashTable *chunk_meshes;
|
||||
|
||||
GAsyncQueue *chunk_queue;
|
||||
GAsyncQueue *chunk_mesh_queue;
|
||||
} ChunkManager;
|
||||
|
||||
void ChunkManager_init ();
|
||||
void ChunkManager_update (float px, float py);
|
||||
void ChunkManager_render (float px, float py, int program);
|
||||
|
||||
Chunk *ChunkManager_get_chunk_at (int x, int y);
|
||||
void ChunkManager_get_chunk_neighbors_at (int x, int y, Chunk **nr, Chunk **nd, Chunk **nc);
|
||||
void ChunkManager_set_chunk_at (int x, int y, Chunk *chunk);
|
||||
|
||||
ChunkMesh *ChunkManager_get_chunk_mesh_at (int x, int y);
|
||||
void ChunkManager_set_chunk_mesh_at (int x, int y, ChunkMesh *mesh);
|
||||
|
||||
void ChunkManager_generate_chunk_at (int x, int y);
|
||||
void ChunkManager_generate_chunk_mesh_at (int x, int y);
|
||||
@@ -1,20 +1,16 @@
|
||||
#include "chunkmesh.h"
|
||||
#include "mesh.h"
|
||||
|
||||
extern GameFlags game_flags;
|
||||
|
||||
ChunkMesh
|
||||
ChunkMesh_from_Chunk_and_neighbors (Chunk *chunk, Chunk *nd, Chunk *nr, Chunk *nc)
|
||||
ChunkMesh *
|
||||
ChunkMesh_from_Chunk_and_neighbors (Chunk *chunk, Chunk *nr, Chunk *nd, Chunk *nc)
|
||||
/* nd --- down neighbor; nr --- right neighbor; nc --- corner neighbor */
|
||||
{
|
||||
vec3_t *positions = malloc (sizeof (vec3_t) * CHUNKMESH_SIZE);
|
||||
vec3_t *materials = malloc (sizeof (vec3_t) * CHUNKMESH_SIZE);
|
||||
float *materials = malloc (sizeof (float) * 4 * CHUNKMESH_SIZE);
|
||||
unsigned int *indices = malloc (sizeof (unsigned int) * CHUNKMESH_SIZE * 6);
|
||||
|
||||
INFO ("Temporarily allocated %zu bytes for ChunkMesh.",
|
||||
(sizeof (vec3_t) * CHUNKMESH_SIZE * 2
|
||||
+ sizeof (unsigned int) * CHUNKMESH_SIZE * 6));
|
||||
|
||||
int i_i = 0;
|
||||
int m_i = 0, i_i = 0;
|
||||
for (int y = 0; y < CHUNKMESH_DIM; ++y)
|
||||
{
|
||||
for (int x = 0; x < CHUNKMESH_DIM; ++x)
|
||||
@@ -22,28 +18,29 @@ ChunkMesh_from_Chunk_and_neighbors (Chunk *chunk, Chunk *nd, Chunk *nr, Chunk *n
|
||||
float height = chunk->heightmap[INDEX (x, y)];
|
||||
float material_id = chunk->materialmap[INDEX (x, y)];
|
||||
|
||||
if (x == CHUNK_DIM && y < CHUNKMESH_DIM && nr != NULL)
|
||||
if (x == CHUNK_DIM && y < CHUNK_DIM && nr != NULL)
|
||||
{
|
||||
height = nr->heightmap[INDEX (0, y)];
|
||||
material_id = nr->materialmap[INDEX (0, y)];
|
||||
}
|
||||
|
||||
if (y == CHUNK_DIM && x < CHUNKMESH_DIM && nd != NULL)
|
||||
if (y == CHUNK_DIM && x < CHUNK_DIM && nd != NULL)
|
||||
{
|
||||
height = nd->heightmap[INDEX (x, 0)];
|
||||
material_id = nr->materialmap[INDEX (x, 0)];
|
||||
material_id = nd->materialmap[INDEX (x, 0)];
|
||||
}
|
||||
|
||||
if (x == CHUNK_DIM && y == CHUNK_DIM && nc != NULL)
|
||||
{
|
||||
height = nc->heightmap[INDEX (0, 0)];
|
||||
material_id = nr->materialmap[INDEX (0, 0)];
|
||||
material_id = nc->materialmap[INDEX (0, 0)];
|
||||
}
|
||||
|
||||
positions[CMINDEX (x, y)] = vec3 (x, height, y);
|
||||
materials[CMINDEX (x, y)] = vec3
|
||||
(material_id == 1 ? 1 : 0, material_id == 2 ? 1 : 0,
|
||||
material_id == 3 ? 1 : 0);
|
||||
materials[m_i++] = material_id == 1 ? 1 : 0;
|
||||
materials[m_i++] = material_id == 2 ? 1 : 0;
|
||||
materials[m_i++] = material_id == 3 ? 1 : 0;
|
||||
materials[m_i++] = material_id == 4 ? 1 : 0;
|
||||
|
||||
if (x < CHUNK_DIM && y < CHUNK_DIM)
|
||||
{
|
||||
@@ -69,22 +66,22 @@ ChunkMesh_from_Chunk_and_neighbors (Chunk *chunk, Chunk *nd, Chunk *nr, Chunk *n
|
||||
}
|
||||
}
|
||||
|
||||
ChunkMesh mesh;
|
||||
glGenBuffers (1, &mesh.pbo);
|
||||
glGenBuffers (1, &mesh.mbo);
|
||||
glGenBuffers (1, &mesh.ebo);
|
||||
ChunkMesh *mesh = malloc (sizeof (ChunkMesh));
|
||||
glGenBuffers (1, &mesh->pbo);
|
||||
glGenBuffers (1, &mesh->mbo);
|
||||
glGenBuffers (1, &mesh->ebo);
|
||||
|
||||
glBindBuffer (GL_ARRAY_BUFFER, mesh.pbo);
|
||||
glBindBuffer (GL_ARRAY_BUFFER, mesh->pbo);
|
||||
glBufferData (GL_ARRAY_BUFFER, sizeof (vec3_t) * CHUNKMESH_SIZE, positions, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray (0);
|
||||
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, sizeof (vec3_t), 0);
|
||||
|
||||
glBindBuffer (GL_ARRAY_BUFFER, mesh.mbo);
|
||||
glBufferData (GL_ARRAY_BUFFER, sizeof (vec3_t) * CHUNKMESH_SIZE, materials, GL_STATIC_DRAW);
|
||||
glBindBuffer (GL_ARRAY_BUFFER, mesh->mbo);
|
||||
glBufferData (GL_ARRAY_BUFFER, sizeof (float) * 4 * CHUNKMESH_SIZE, materials, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray (1);
|
||||
glVertexAttribPointer (1, 3, GL_FLOAT, GL_FALSE, sizeof (vec3_t), 0);
|
||||
glVertexAttribPointer (1, 4, GL_FLOAT, GL_FALSE, sizeof (float) * 4, 0);
|
||||
|
||||
glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, mesh.ebo);
|
||||
glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, mesh->ebo);
|
||||
glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof (unsigned int) * CHUNKMESH_SIZE * 6, indices, GL_STATIC_DRAW);
|
||||
|
||||
glBindBuffer (GL_ARRAY_BUFFER, 0);
|
||||
@@ -100,15 +97,23 @@ ChunkMesh_from_Chunk_and_neighbors (Chunk *chunk, Chunk *nd, Chunk *nr, Chunk *n
|
||||
void
|
||||
ChunkMesh_render (ChunkMesh *mesh)
|
||||
{
|
||||
glBindBuffer (GL_ARRAY_BUFFER, mesh->pbo);
|
||||
glEnableVertexAttribArray (0);
|
||||
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, sizeof (vec3_t), 0);
|
||||
|
||||
glBindBuffer (GL_ARRAY_BUFFER, mesh->mbo);
|
||||
glEnableVertexAttribArray (1);
|
||||
glVertexAttribPointer (1, 4, GL_FLOAT, GL_FALSE, sizeof (float) * 4, 0);
|
||||
|
||||
glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, mesh->ebo);
|
||||
|
||||
if (game_flags.wireframe_enabled)
|
||||
{
|
||||
glDrawElements (GL_LINES, CHUNKMESH_SIZE * 6, GL_UNSIGNED_INT, 0);
|
||||
glDrawElements (GL_LINES, CHUNK_SIZE * 6, GL_UNSIGNED_INT, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
glDrawElements (GL_TRIANGLES, CHUNKMESH_SIZE * 6, GL_UNSIGNED_INT, 0);
|
||||
glDrawElements (GL_TRIANGLES, CHUNK_SIZE * 6, GL_UNSIGNED_INT, 0);
|
||||
}
|
||||
|
||||
glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "../math_3d.h"
|
||||
#include "chunk.h"
|
||||
|
||||
/* TODO: set to + 1 */
|
||||
#define CHUNKMESH_DIM (CHUNK_DIM+1)
|
||||
#define CHUNKMESH_SIZE (CHUNKMESH_DIM*CHUNKMESH_DIM)
|
||||
#define CMINDEX(x, y) (CHUNKMESH_DIM * (y) + (x))
|
||||
@@ -18,5 +17,6 @@ typedef struct ChunkMesh
|
||||
unsigned int ebo;
|
||||
} ChunkMesh;
|
||||
|
||||
ChunkMesh ChunkMesh_from_Chunk_and_neighbors (Chunk *chunk, Chunk *nd, Chunk *nr, Chunk *nc);
|
||||
/* Rename to ChunkMesh_build */
|
||||
ChunkMesh *ChunkMesh_from_Chunk_and_neighbors (Chunk *chunk, Chunk *nr, Chunk *nd, Chunk *nc);
|
||||
void ChunkMesh_render (ChunkMesh *mesh);
|
||||
@@ -1,43 +0,0 @@
|
||||
#include "noise.h"
|
||||
|
||||
static u_int8_t *perm;
|
||||
|
||||
void
|
||||
noise_seed (int seed)
|
||||
{
|
||||
srand (seed);
|
||||
perm = malloc (sizeof (u_int8_t) * 256);
|
||||
|
||||
for (size_t i = 0; i < 256; ++i) {
|
||||
perm[i] = i;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 255; ++i) {
|
||||
size_t j = i + rand() / (RAND_MAX / (256 - i) + 1);
|
||||
u_int8_t t = perm[j];
|
||||
perm[j] = perm[i];
|
||||
perm[i] = t;
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
noise2 (float x, float y)
|
||||
{
|
||||
int X = (int) FASTFLOOR (x) & 0xff;
|
||||
int Y = (int) FASTFLOOR (y) & 0xff;
|
||||
x -= FASTFLOOR (x);
|
||||
y -= FASTFLOOR (y);
|
||||
float u = FADE (x);
|
||||
float v = FADE (y);
|
||||
int A = (perm[X] + Y) & 0xff;
|
||||
int B = (perm[X + 1] + Y) & 0xff;
|
||||
|
||||
return LERP
|
||||
(v, LERP
|
||||
(u, GRAD2
|
||||
(perm[A], x, y),
|
||||
GRAD2(perm[B], x - 1, y)),
|
||||
LERP(u, GRAD2
|
||||
(perm[A + 1], x, y - 1),
|
||||
GRAD2(perm[B + 1], x - 1, y - 1)));
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define FADE(t) (((6 * t - 15) * t + 10) * t * t * t)
|
||||
#define LERP(t, a, b) (a + t * (b - a))
|
||||
#define FASTFLOOR(x) (((int) (x) < (x)) ? ((int) x) : ((int) x - 1))
|
||||
|
||||
static inline float
|
||||
GRAD2 (int hash, float x, float y)
|
||||
{
|
||||
return ((hash & 1) ? -x : x) + ((hash & 2) ? -y : y);
|
||||
}
|
||||
|
||||
void noise_seed (int seed);
|
||||
float noise2 (float x, float y);
|
||||
@@ -4,11 +4,10 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "chunk/chunkmesh.h"
|
||||
#include "chunk/manager.h"
|
||||
#include "state.h"
|
||||
#include "flags.h"
|
||||
#include "camera.h"
|
||||
#include "mesh.h"
|
||||
#include "resources.h"
|
||||
|
||||
/* TODO: switch back to cglm.h, since it's faster or something */
|
||||
@@ -19,8 +18,8 @@ static SDL_GLContext context = NULL;
|
||||
extern GameState game_state;
|
||||
extern GameFlags game_flags;
|
||||
extern Resources resources;
|
||||
extern ChunkManager chunk_manager;
|
||||
|
||||
static ChunkMesh test_chunkmesh;
|
||||
static Camera camera;
|
||||
|
||||
SDL_AppResult
|
||||
@@ -71,16 +70,11 @@ SDL_AppInit (void **appstate, int argc, char **argv)
|
||||
|
||||
/* Initialize and load resources. */
|
||||
Resources_init ();
|
||||
noise_seed (1337);
|
||||
|
||||
/* Generate a test chunk. */
|
||||
Chunk chunk = Chunk_new ();
|
||||
Chunk_noise (&chunk, 0, 0);
|
||||
test_chunkmesh = ChunkMesh_from_Chunk_and_neighbors (&chunk, NULL, NULL, NULL);
|
||||
ChunkManager_init ();
|
||||
|
||||
program_use (resources.programs[1]);
|
||||
int arr[4] = { 0, 1, 2, 3 };
|
||||
program_set_int_array (resources.programs[1], "materials", 4, arr);
|
||||
int arr[5] = { 0, 1, 2, 3, 4 };
|
||||
program_set_int_array (resources.programs[1], "materials", 5, arr);
|
||||
|
||||
/* Set up game state. */
|
||||
game_state.last_time = SDL_GetTicks ();
|
||||
@@ -91,7 +85,6 @@ SDL_AppInit (void **appstate, int argc, char **argv)
|
||||
|
||||
/* Initialize the default camera. */
|
||||
camera = Camera_default ();
|
||||
camera.position.z = -1.0;
|
||||
|
||||
return SDL_APP_CONTINUE;
|
||||
}
|
||||
@@ -133,6 +126,14 @@ SDL_AppEvent (void *appstate, SDL_Event *event)
|
||||
case SDLK_F1:
|
||||
game_flags.wireframe_enabled = !game_flags.wireframe_enabled;
|
||||
break;
|
||||
case SDLK_F2:
|
||||
int active_program;
|
||||
glGetIntegerv (GL_CURRENT_PROGRAM, &active_program);
|
||||
program_print (active_program);
|
||||
break;
|
||||
case SDLK_F3:
|
||||
Camera_print (&camera);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,48 +173,47 @@ SDL_AppIterate (void *appstate)
|
||||
{
|
||||
camera.position = v3_add
|
||||
(camera.position, v3_muls
|
||||
(Camera_get_direction (&camera), game_state.delta_time));
|
||||
(Camera_get_direction (&camera), game_state.delta_time * 5));
|
||||
}
|
||||
|
||||
if (game_flags.moving_backward)
|
||||
{
|
||||
camera.position = v3_sub
|
||||
(camera.position, v3_muls
|
||||
(Camera_get_direction (&camera), game_state.delta_time));
|
||||
(Camera_get_direction (&camera), game_state.delta_time * 5));
|
||||
}
|
||||
|
||||
if (game_flags.moving_right)
|
||||
{
|
||||
camera.position = v3_add
|
||||
(camera.position, v3_muls
|
||||
(Camera_get_right (&camera), game_state.delta_time));
|
||||
(Camera_get_right (&camera), game_state.delta_time * 5));
|
||||
}
|
||||
|
||||
if (game_flags.moving_left)
|
||||
{
|
||||
camera.position = v3_sub
|
||||
(camera.position, v3_muls
|
||||
(Camera_get_right (&camera), game_state.delta_time));
|
||||
(Camera_get_right (&camera), game_state.delta_time * 5));
|
||||
}
|
||||
|
||||
ChunkManager_update (camera.position.x, camera.position.z);
|
||||
|
||||
/* Render stuff. */
|
||||
|
||||
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
mat4_t view = Camera_get_view (&camera);
|
||||
mat4_t projection = Camera_get_projection (&camera, 640.0 / 480.0);
|
||||
|
||||
program_use (resources.programs[1]);
|
||||
program_set_mat4 (resources.programs[1], "projection", Camera_get_projection (&camera, 640.0 / 480.0));
|
||||
program_set_mat4 (resources.programs[1], "view", Camera_get_view (&camera));
|
||||
|
||||
for (size_t i = 0; i < resources.textures_len; ++i)
|
||||
{
|
||||
glActiveTexture (GL_TEXTURE0 + i);
|
||||
glBindTexture (GL_TEXTURE_2D, resources.textures[i]);
|
||||
}
|
||||
|
||||
program_set_mat4 (resources.programs[1], "view", view);
|
||||
program_set_mat4 (resources.programs[1], "projection", projection);
|
||||
ChunkMesh_render (&test_chunkmesh);
|
||||
|
||||
ChunkManager_render (camera.position.x, camera.position.z, resources.programs[1]);
|
||||
|
||||
glBindTexture (GL_TEXTURE_2D, 0);
|
||||
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#include "mesh.h"
|
||||
|
||||
Mesh
|
||||
Mesh_new (size_t vertices_len, float *vertices)
|
||||
{
|
||||
Mesh mesh = { vertices_len, vertices, 0 };
|
||||
glGenBuffers (1, &mesh.vbo);
|
||||
glBindBuffer (GL_ARRAY_BUFFER, mesh.vbo);
|
||||
glBufferData (GL_ARRAY_BUFFER, vertices_len * sizeof (float), vertices, GL_STATIC_DRAW);
|
||||
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof (float), 0);
|
||||
glEnableVertexAttribArray (0);
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
void
|
||||
Mesh_draw (Mesh *mesh)
|
||||
{
|
||||
glBindBuffer (GL_ARRAY_BUFFER, mesh->vbo);
|
||||
glDrawArrays (GL_TRIANGLES, 0, mesh->vertices_len);
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL3/SDL_opengles2.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
typedef struct Mesh
|
||||
{
|
||||
size_t vertices_len;
|
||||
float *vertices;
|
||||
GLuint vbo;
|
||||
} Mesh;
|
||||
|
||||
Mesh Mesh_new (size_t vertices_len, float *vertices);
|
||||
void Mesh_draw (Mesh *mesh);
|
||||
@@ -72,6 +72,12 @@ program_create (const char *v_src, const char *f_src)
|
||||
return program;
|
||||
}
|
||||
|
||||
void
|
||||
program_set_vec4 (int program, const char *name, float x, float y, float z, float w)
|
||||
{
|
||||
glUniform4f (glGetUniformLocation (program, name), x, y, z, w);
|
||||
}
|
||||
|
||||
void
|
||||
program_set_int_array (int program, const char *name, size_t count, int *value)
|
||||
{
|
||||
@@ -104,26 +110,53 @@ gl_type_to_string (GLenum type)
|
||||
|
||||
void
|
||||
program_print (int program)
|
||||
/* This function assumes that `program' is the active program. */
|
||||
{
|
||||
int bufsize;
|
||||
glGetProgramiv (program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &bufsize);
|
||||
char name[bufsize];
|
||||
|
||||
int uniform_no, attribute_no;
|
||||
glGetProgramiv (program, GL_ACTIVE_UNIFORMS, &uniform_no);
|
||||
glGetProgramiv (program, GL_ACTIVE_ATTRIBUTES, &attribute_no);
|
||||
INFO ("== Program %d ==", program);
|
||||
|
||||
INFO ("== Program %d: %d active attribute(s) / %d active uniform(s) ==", program, attribute_no, uniform_no);
|
||||
int attr_len;
|
||||
glGetProgramiv (program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &attr_len);
|
||||
char attr[attr_len];
|
||||
|
||||
int attribute_no;
|
||||
glGetProgramiv (program, GL_ACTIVE_ATTRIBUTES, &attribute_no);
|
||||
|
||||
GLenum type;
|
||||
|
||||
for (GLint i = 0; i < attribute_no; i++) {
|
||||
glGetActiveAttrib (program, i, bufsize, NULL, NULL, &type, name);
|
||||
INFO ("Attribute #%d: %s %s", i, gl_type_to_string (type), name);
|
||||
glGetActiveAttrib (program, i, attr_len, NULL, NULL, &type, attr);
|
||||
INFO ("Attribute #%d: %s %s", i, gl_type_to_string (type), attr);
|
||||
}
|
||||
|
||||
int uniform_len;
|
||||
glGetProgramiv (program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniform_len);
|
||||
char uniform[uniform_len];
|
||||
|
||||
int uniform_no;
|
||||
glGetProgramiv (program, GL_ACTIVE_UNIFORMS, &uniform_no);
|
||||
|
||||
float *vec = malloc (sizeof (float) * 4);
|
||||
|
||||
for (GLint i = 0; i < uniform_no; i++) {
|
||||
glGetActiveUniform (program, i, bufsize, NULL, NULL, &type, name);
|
||||
INFO ("Uniform #%d: %s %s", i, gl_type_to_string (type), name);
|
||||
glGetActiveUniform (program, i, uniform_len, NULL, NULL, &type, uniform);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case GL_FLOAT_VEC3:
|
||||
glGetUniformfv (program, glGetUniformLocation (program, uniform), vec);
|
||||
INFO ("Uniform #%d: %s %s = (%5.1f,%5.1f,%5.1f)", i, gl_type_to_string (type),
|
||||
uniform, vec[0], vec[1], vec[2]);
|
||||
break;
|
||||
case GL_FLOAT_VEC4:
|
||||
glGetUniformfv (program, glGetUniformLocation (program, uniform), vec);
|
||||
INFO ("Uniform #%d: %s %s = (%5.1f,%5.1f,%5.1f,%5.1f)", i, gl_type_to_string (type),
|
||||
uniform, vec[0], vec[1], vec[2], vec[3]);
|
||||
break;
|
||||
default:
|
||||
INFO ("Uniform #%d: %s %s", i, gl_type_to_string (type), uniform);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free (vec);
|
||||
}
|
||||
|
||||
@@ -12,5 +12,6 @@ void shader_fail (int shader);
|
||||
void program_fail (int program);
|
||||
int program_create (const char *v_src, const char *f_src);
|
||||
void program_set_int_array (int program, const char *name, size_t count, int *value);
|
||||
void program_set_vec4 (int program, const char *name, float x, float y, float z, float w);
|
||||
void program_set_mat4 (int program, const char *name, mat4_t value);
|
||||
void program_print (int program);
|
||||
|
||||
@@ -80,6 +80,7 @@ Resources_init ()
|
||||
Resources_load_texture ("res/textures/dirt.png");
|
||||
Resources_load_texture ("res/textures/drygrass.png");
|
||||
Resources_load_texture ("res/textures/grass.png");
|
||||
Resources_load_texture ("res/textures/rock_cement.png");
|
||||
Resources_load_texture ("res/textures/asphalt_gravel.png");
|
||||
}
|
||||
|
||||
|
||||
@@ -16,3 +16,12 @@
|
||||
#define FATAL(fmt, args...) (fprintf (stderr, COLOR_RED "[!] %s:%d:%s(): " COLOR_RESET fmt "\n", __FILE__, __LINE__, __func__, ##args), exit (-1))
|
||||
|
||||
#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
|
||||
|
||||
typedef struct ivec2_t { int x; int y; } ivec2_t;
|
||||
|
||||
static inline ivec2_t
|
||||
ivec2 (int x, int y)
|
||||
{
|
||||
ivec2_t v = { x, y };
|
||||
return v;
|
||||
}
|
||||
|
||||