From fa97efdce6005b3ef8a87488cf73e432de886dde Mon Sep 17 00:00:00 2001 From: koma Date: Wed, 6 Apr 2022 20:06:02 +0200 Subject: [PATCH] Add source files --- Makefile | 4 + assets/block.png | Bin 0 -> 10256 bytes include/app.h | 80 ++++++++++++ include/camera.h | 51 ++++++++ include/game.h | 11 ++ include/utils.h | 49 ++++++++ src/app.c | 314 +++++++++++++++++++++++++++++++++++++++++++++++ src/camera.c | 83 +++++++++++++ src/game.c | 61 +++++++++ src/main.c | 80 ++++++++++++ src/utils.c | 31 +++++ 11 files changed, 764 insertions(+) create mode 100644 Makefile create mode 100644 assets/block.png create mode 100644 include/app.h create mode 100644 include/camera.h create mode 100644 include/game.h create mode 100644 include/utils.h create mode 100644 src/app.c create mode 100644 src/camera.c create mode 100644 src/game.c create mode 100644 src/main.c create mode 100644 src/utils.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..256a2d3 --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ +all: + gcc -Iinclude/ src/app.c src/camera.c src/main.c src/game.c src/utils.c -lSDL2 -lGL -lm -lSDL2_image -o test -Wall +debug: + gcc -Iinclude/ src/app.c src/camera.c src/main.c src/game.c src/utils.c -lSDL2 -lGL -lm -lSDL2_image -o test -Wall -g diff --git a/assets/block.png b/assets/block.png new file mode 100644 index 0000000000000000000000000000000000000000..e065bb6a24857122352905ca3179f2425651ea76 GIT binary patch literal 10256 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 +#include +#include +#include +#include +#include "camera.h" +#include + +#define SPEED 5 +#define GRAVITY 10 + +#define VIEWPORT_RATIO (16.0 / 9.0) +#define VIEWPORT_ASPECT 50.0 + +typedef unsigned int uint; + +#define CHUNK_MAX_X 16 +#define CHUNK_MAX_Y 16 +#define CHUNK_MAX_Z 128 + +typedef enum { + BLOCKTYPE_AIR, + BLOCKTYPE_GRASS, + BLOCKTYPE_DIRT, + BLOCKTYPE_STONE, +} Block_type; + +typedef struct +{ + Block_type type; + bool visible; +} Block; + +typedef struct { + vec3f start_pos; + Block blocks[CHUNK_MAX_X][CHUNK_MAX_Y][CHUNK_MAX_Z]; + GLuint id; +} Chunk; + + +typedef struct { + bool is_running; + SDL_Window *window; + SDL_GLContext context; + Camera camera; + double frame_time; + SDL_Surface *surface; + GLuint tid; + unsigned int chunk_count; + Chunk *chunks; +} App; + +bool chunk_is_block_neighboring_block(Chunk* chunk, vec3i pos); +void chunk_set_blocks_visibility(Chunk* chunk); +void chunk_create_displayl(App *app, Chunk *chunk); +void chunk_render(Chunk* chunk); + +bool is_block(Block b); + +int app_get_current_chunk_index(App *app); + +bool app_check_collision(App *app); + +void init_app(App *app, uint w, uint h); + +void init_opengl(); + +void handle_events(App *app); + +void draw_cube(App *app, float x, float y, float z); + +void reshape(GLsizei width, GLsizei height); + +void update_app(App* app); + +float calc_frame_time(struct timespec *start, struct timespec *end); + +#endif \ No newline at end of file diff --git a/include/camera.h b/include/camera.h new file mode 100644 index 0000000..128dbb6 --- /dev/null +++ b/include/camera.h @@ -0,0 +1,51 @@ +#ifndef CAMERA_H +#define CAMERA_H + +#include "utils.h" + +#include + +/** + * Camera, as a moving point with direction + */ + +typedef struct Camera +{ + vec3f position; + vec3f rotation; + vec3f speed; +} Camera; + +/** + * Initialize the camera to the start position. + */ +void init_camera(Camera* camera); + +/** + * Update the position of the camera. + */ +void update_camera(Camera* camera, double time); + +/** + * Apply the camera settings to the view transformation. + */ +void set_view(const Camera* camera); + +/** + * Set the horizontal and vertical rotation of the view angle. + */ +void rotate_camera(Camera* camera, double horizontal, double vertical); + +/** + * Set the speed of forward and backward motion. + */ +void set_camera_speed(Camera* camera, double speed); + +void camera_set_vertical_speed(Camera* camera, double speed); + +/** + * Set the speed of left and right side steps. + */ +void set_camera_side_speed(Camera* camera, double speed); + +#endif /* CAMERA_H */ diff --git a/include/game.h b/include/game.h new file mode 100644 index 0000000..ca67bb4 --- /dev/null +++ b/include/game.h @@ -0,0 +1,11 @@ +#ifndef GAME_H +#define GAME_H +#include "app.h" +#include "utils.h" +#include +#include + + + + +#endif \ No newline at end of file diff --git a/include/utils.h b/include/utils.h new file mode 100644 index 0000000..d11d5a5 --- /dev/null +++ b/include/utils.h @@ -0,0 +1,49 @@ +#ifndef UTILS_H +#define UTILS_H +#include + +/** + * GLSL-like three dimensional vector + */ +typedef struct vec3f +{ + float x; + float y; + float z; +} vec3f; + +typedef struct vec3i +{ + int x; + int y; + int z; +} vec3i; + +typedef struct vec4f +{ + float x; + float y; + float z; + float w; +} vec4f; + +/** + * Color with RGB components + */ +typedef struct Color +{ + float red; + float green; + float blue; +} Color; + +/** + * Calculates radian from degree. + */ +double degree_to_radian(double degree); + +bool is_oob(int i, int min, int max); + +void mult_matrix(float *matrix, vec4f vector, vec4f *ret); + +#endif /* UTILS_H */ diff --git a/src/app.c b/src/app.c new file mode 100644 index 0000000..72bfc2f --- /dev/null +++ b/src/app.c @@ -0,0 +1,314 @@ +#include "../include/app.h" +#include + +void init_app(App *app, uint w, uint h) +{ + int err; + + err = SDL_Init(SDL_INIT_EVERYTHING); + if (err != 0) { + printf("Failed to initialize SDL. Error: %s\n", + SDL_GetError()); + exit(1); + } + + app->window = SDL_CreateWindow( + "test", + SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, + w, h, SDL_WINDOW_OPENGL); + + if (app->window == NULL) { + printf("Failed to create window.\n"); + exit(1); + } + + app->context = SDL_GL_CreateContext(app->window); + if (app->context == NULL) { + printf("Failed to create OpenGL context.\n"); + exit(1); + } + app->is_running = true; + + //SDL_ShowCursor(SDL_DISABLE); + init_camera(&app->camera); + init_opengl(); + reshape(w, h); + + init_camera(&(app->camera)); + + app->surface = IMG_Load("assets/block.jpg"); + app->tid = 0; + + if(app->surface==NULL) { + printf("error\n"); + exit(1); + } + glGenTextures(1, &app->tid); + glBindTexture(GL_TEXTURE_2D, app->tid); + + int Mode = GL_RGB; + + if(app->surface->format->BytesPerPixel == 4) { + Mode = GL_RGBA; + } + + glTexImage2D(GL_TEXTURE_2D, 0, Mode, app->surface->w, app->surface->h, 0, Mode, GL_UNSIGNED_BYTE, app->surface->pixels); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glBindTexture(GL_TEXTURE_2D, app->tid); +} + +void update_app(App* app) +{ + app->camera.speed.z -= GRAVITY * (app->frame_time/1000); + + if(app_check_collision(app)) + camera_set_vertical_speed(&app->camera, 0.0); + update_camera(&(app->camera), app->frame_time/1000); +} + +void init_opengl() +{ + // https://gitlab.com/imre-piller/me-courses/ alapjan. + glShadeModel(GL_SMOOTH); + + glEnable(GL_NORMALIZE); + glEnable(GL_AUTO_NORMAL); + + glClearColor(0.1, 0.1, 0.1, 1.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glEnable(GL_DEPTH_TEST); + glClearDepth(1.0); + glEnable(GL_TEXTURE_2D); +} + +void reshape(GLsizei width, GLsizei height) +{ + int x, y, w, h; + double ratio; + + ratio = (double)width / height; + if (ratio > VIEWPORT_RATIO) { + w = (int)((double)height * VIEWPORT_RATIO); + h = height; + x = (width - w) / 2; + y = 0; + } + else { + w = width; + h = (int)((double)width / VIEWPORT_RATIO); + x = 0; + y = (height - h) / 2; + } + + glViewport(x, y, w, h); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum( + -.08, .08, + -.06, .06, + .1, 1000 + ); +} + +void handle_events(App* app) +{ + SDL_Event event; + static bool is_mouse_down = false; + static int mouse_x = 0; + static int mouse_y = 0; + int x; + int y; + + while (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_KEYDOWN: + switch (event.key.keysym.scancode) { + case SDL_SCANCODE_ESCAPE: + app->is_running = false; + break; + case SDL_SCANCODE_W: + set_camera_speed(&(app->camera), SPEED); + break; + case SDL_SCANCODE_S: + set_camera_speed(&(app->camera), -SPEED); + break; + case SDL_SCANCODE_A: + set_camera_side_speed(&(app->camera), SPEED); + break; + case SDL_SCANCODE_D: + set_camera_side_speed(&(app->camera), -SPEED); + break; + case SDL_SCANCODE_SPACE: + if (app_check_collision(app)) + app->camera.position.z+=0.3; + camera_set_vertical_speed(&app->camera, SPEED); + break; + case SDL_SCANCODE_LSHIFT: + camera_set_vertical_speed(&app->camera, -SPEED); + break; + default: + break; + } + break; + case SDL_KEYUP: + switch (event.key.keysym.scancode) { + case SDL_SCANCODE_W: + case SDL_SCANCODE_S: + set_camera_speed(&(app->camera), 0); + break; + case SDL_SCANCODE_A: + case SDL_SCANCODE_D: + set_camera_side_speed(&(app->camera), 0); + break; + case SDL_SCANCODE_SPACE: + case SDL_SCANCODE_LSHIFT: + camera_set_vertical_speed(&app->camera, -0); + default: + break; + } + break; + case SDL_MOUSEBUTTONDOWN: + is_mouse_down = true; + break; + case SDL_MOUSEMOTION: + SDL_GetMouseState(&x, &y); + if (is_mouse_down) { + rotate_camera(&(app->camera), mouse_x - x, mouse_y - y); + } + mouse_x = x; + mouse_y = y; + break; + case SDL_MOUSEBUTTONUP: + is_mouse_down = false; + break; + case SDL_QUIT: + app->is_running = false; + break; + default: + break; + } + } + +} + +void app_raycast(App *app) +{ + vec4f v = {0, 0, -1, 1}; + vec4f retv; + float projection[16]; + glGetFloatv(GL_PROJECTION_MATRIX, projection); + mult_matrix(projection, v, &retv); + retv.z = -1.0; + retv.w = 0.0; + +} + +void draw_cube(App *app, float x, float y, float z) +{ + /*x*=2; + y*=2; + z*=2; + */ + glBegin( GL_QUADS ); + + glColor3f(1, 1, 1); + glTexCoord2f(0, 0); glVertex3f(x+1.0, y, z-1.0 ); + glTexCoord2f(0, 1); glVertex3f(x, y, z-1.0); + glTexCoord2f(1, 1); glVertex3f(x, y, z); + glTexCoord2f(1, 0); glVertex3f(x+1.0, y, z); + + glColor3f(1, 1, 1); + glTexCoord2f(0, 0); glVertex3f(x+1.0, y-1.0, z-1.0); + glTexCoord2f(0, 1); glVertex3f(x, y-1.0, z-1.0); + glTexCoord2f(1, 1); glVertex3f(x, y-1.0, z); + glTexCoord2f(1, 0); glVertex3f(x+1.0, y-1.0, z); + + glColor3f(1, 1, 1); + glTexCoord2f(0, 0); glVertex3f(x+1.0, y, z); + glTexCoord2f(0, 1); glVertex3f(x, y, z); + glTexCoord2f(1, 1); glVertex3f(x, y-1.0, z); + glTexCoord2f(1, 0); glVertex3f(x+1.0, y-1.0, z); + + glColor3f(1, 1, 1); + glTexCoord2f(0, 0); glVertex3f(x, y, z-1.0); // Top-Right of back face + glTexCoord2f(0, 1); glVertex3f(x+1.0, y, z-1.0); // Top-Left of back face + glTexCoord2f(1, 1); glVertex3f(x+1.0, y-1.0, z-1.0); // Bottom-Left of back face + glTexCoord2f(1, 0); glVertex3f(x, y-1.0, z-1.0); // Bottom-Right of back face + + glColor3f(1, 1, 1); + glTexCoord2f(0, 0); glVertex3f(x, y, z); // Top-Right of left face + glTexCoord2f(0, 1); glVertex3f(x, y, z-1.0); // Top-Left of left face + glTexCoord2f(1, 1); glVertex3f(x, y-1.0, z-1.0); // Bottom-Left of left face + glTexCoord2f(1, 0); glVertex3f(x, y-1.0, z); // Bottom-Right of left face + + glColor3f(1, 1, 1); + glTexCoord2f(0, 0); glVertex3f(x+1.0, y, z); // Top-Right of left face + glTexCoord2f(0, 1); glVertex3f(x+1.0, y, z-1.0); // Top-Left of left face + glTexCoord2f(1, 1); glVertex3f(x+1.0, y-1.0, z-1.0); // Bottom-Left of left face + glTexCoord2f(1, 0); glVertex3f(x+1.0, y-1.0, z); // Bottom-Right of left face + glEnd(); + glFlush(); +} + +float calc_frame_time(struct timespec *start, struct timespec *end) +{ + float elapsed_time = (end->tv_sec - start->tv_sec)*1000; + + elapsed_time += (float)(end->tv_nsec - start->tv_nsec)/1000000; + + return elapsed_time; +} + +int app_get_current_chunk_index(App *app) +{ + for (int i = 0; i < app->chunk_count; i++) { + for (int x = 0; x < CHUNK_MAX_X; x++) { + for (int y = 0; y < CHUNK_MAX_Y; y++) { + for (int z = 0; z < CHUNK_MAX_Z; z++) { + if (app->camera.position.x < app->chunks[i].start_pos.x + CHUNK_MAX_X && + app->camera.position.x > app->chunks[i].start_pos.x && + app->camera.position.y < app->chunks[i].start_pos.y + CHUNK_MAX_Y && + app->camera.position.y > app->chunks[i].start_pos.y) { + return i; + } + } + } + } + } + + return -1; +} + +bool is_block(Block b) +{ + if(b.type != BLOCKTYPE_AIR) + return true; + return false; +} + +bool app_check_collision(App *app) +{ + int i = app_get_current_chunk_index(app); + + if (i < 0) + return false; + + for (int x = 0; x < CHUNK_MAX_X; x++) { + for (int y = 0; y < CHUNK_MAX_Y; y++) { + for (int z = 0; z < CHUNK_MAX_Z; z++) { + if (!is_block(app->chunks[i].blocks[x][y][z])) + continue; + if (app->camera.position.z <= z+2) + return true; + } + } + } + return false; +} diff --git a/src/camera.c b/src/camera.c new file mode 100644 index 0000000..ff3f2ea --- /dev/null +++ b/src/camera.c @@ -0,0 +1,83 @@ +#include "../include/camera.h" + +#include +#include + +#include + +void init_camera(Camera* camera) +{ + camera->position.x = 5.0; + camera->position.y = 5.0; + camera->position.z = 60.0; + camera->rotation.x = 0.0; + camera->rotation.y = 0.0; + camera->rotation.z = 0.0; + camera->speed.x = 0.0; + camera->speed.y = 0.0; + camera->speed.z = 0.0; +} + +void update_camera(Camera* camera, double time) +{ + double angle; + double side_angle; + + angle = degree_to_radian(camera->rotation.z); + side_angle = degree_to_radian(camera->rotation.z + 90.0); + + camera->position.x += cos(angle) * camera->speed.y * time; + camera->position.y += sin(angle) * camera->speed.y * time; + camera->position.z += camera->speed.z * time; + + camera->position.x += cos(side_angle) * camera->speed.x * time; + camera->position.y += sin(side_angle) * camera->speed.x * time; + camera->position.z += camera->speed.z * time; +} + +void set_view(const Camera* camera) +{ + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glRotatef(-(camera->rotation.x), 1.0, 0, 0); + glRotatef(-(camera->rotation.z - 90), 0, 0, 1.0); + glTranslatef(-camera->position.x, -camera->position.y, -camera->position.z); +} + +void rotate_camera(Camera* camera, double horizontal, double vertical) +{ + camera->rotation.z += horizontal; + camera->rotation.x += vertical; + + if (camera->rotation.z < 0) { + camera->rotation.z += 360.0; + } + + if (camera->rotation.z > 360.0) { + camera->rotation.z -= 360.0; + } + + if (camera->rotation.x < 0.0) { + camera->rotation.x = 0.0; + } + + if (camera->rotation.x > 180.0) { + camera->rotation.x = 180.0; + } +} + +void set_camera_speed(Camera* camera, double speed) +{ + camera->speed.y = speed; +} + +void camera_set_vertical_speed(Camera* camera, double speed) +{ + camera->speed.z = speed; +} + +void set_camera_side_speed(Camera* camera, double speed) +{ + camera->speed.x = speed; +} diff --git a/src/game.c b/src/game.c new file mode 100644 index 0000000..3dcd84d --- /dev/null +++ b/src/game.c @@ -0,0 +1,61 @@ +#include "../include/game.h" +#include + +bool chunk_is_block_neighboring_block(Chunk* chunk, vec3i pos) +{ + if (is_oob(pos.x-1, 0, CHUNK_MAX_X) || is_oob(pos.x+1, 0, CHUNK_MAX_X)) + return false; + if (is_oob(pos.y-1, 0, CHUNK_MAX_Y) || is_oob(pos.y+1, 0, CHUNK_MAX_Y)) + return false; + if (is_oob(pos.z-1, 0, CHUNK_MAX_Z) || is_oob(pos.z+1, 0, CHUNK_MAX_Z)) + return false; + + if (chunk->blocks[pos.x-1][pos.y][pos.z].type != BLOCKTYPE_AIR && + chunk->blocks[pos.x+1][pos.y][pos.z].type != BLOCKTYPE_AIR && + chunk->blocks[pos.x][pos.y-1][pos.z].type != BLOCKTYPE_AIR && + chunk->blocks[pos.x][pos.y+1][pos.z].type != BLOCKTYPE_AIR && + chunk->blocks[pos.x][pos.y][pos.z-1].type != BLOCKTYPE_AIR && + chunk->blocks[pos.x][pos.y][pos.z+1].type != BLOCKTYPE_AIR) + return true; + + return false; +} + +void chunk_set_blocks_visibility(Chunk* chunk) +{ + for (int x = 0; x < CHUNK_MAX_X; x++) { + for (int y = 0; y < CHUNK_MAX_Y; y++) { + for (int z = 0; z < CHUNK_MAX_Z; z++) { + vec3i v = {x, y, z}; + if (chunk_is_block_neighboring_block(chunk, v)) + chunk->blocks[x][y][z].visible = false; + else + chunk->blocks[x][y][z].visible = true; + + if (chunk->blocks[x][y][z].type == BLOCKTYPE_AIR) + chunk->blocks[x][y][z].visible = false; + } + } + } +} + +void chunk_create_displayl(App *app, Chunk *chunk) +{ + chunk->id = glGenLists(1); + + glNewList(chunk->id, GL_COMPILE); + for (int x = 0; x < CHUNK_MAX_X; x++) { + for (int y = 0; y < CHUNK_MAX_Y; y++) { + for (int z = 0; z < CHUNK_MAX_Z; z++) { + if (chunk->blocks[x][y][z].visible) + draw_cube(app, chunk->start_pos.x + x, chunk->start_pos.y + y, chunk->start_pos.z + z); + } + } + } + glEndList(); +} + +void chunk_render(Chunk* chunk) +{ + glCallList(chunk->id); +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..eb83d15 --- /dev/null +++ b/src/main.c @@ -0,0 +1,80 @@ +#include "../include/app.h" +#include +#include +#include + +int main() +{ + App app; + init_app(&app, 1280, 720); + + Chunk *chunks = malloc(100*sizeof(Chunk)); + memset(chunks, 0, 100*sizeof(Chunk)); + + for (int i = 0; i < 10; i++) { + for (int j = 0; j < 10; j++) { + Chunk c; + c.start_pos.x = i*CHUNK_MAX_X; + c.start_pos.y = j*CHUNK_MAX_Y; + c.start_pos.z = 0; + for (int x = 0; x < CHUNK_MAX_X; x++) { + for (int y = 0; y < CHUNK_MAX_Y; y++) { + for (int z = 0; z < CHUNK_MAX_Z; z++) { + if (z < 40) + c.blocks[x][y][z].type = BLOCKTYPE_STONE; + else + c.blocks[x][y][z].type = BLOCKTYPE_AIR; + } + } + } + chunk_set_blocks_visibility(&c); + chunk_create_displayl(&app, &c); + + chunks[i+(j*10)] = c; + } + } + + app.chunks = chunks; + app.chunk_count = 100; + + while(app.is_running) { + struct timespec start; + struct timespec end; + + clock_gettime(CLOCK_MONOTONIC_RAW, &start); + + handle_events(&app); + update_app(&app); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glMatrixMode(GL_MODELVIEW); + set_view(&app.camera); + + + printf("camera x: %f y: %f z: %f\n", app.camera.position.x, app.camera.position.y, app.camera.position.z); + + for (int i = 0; i < 100; i++) { + chunk_render(&chunks[i]); + } + + vec3f dir = {cos(degree_to_radian(app.camera.rotation.z)), sin(degree_to_radian(app.camera.rotation.z)), -cos(degree_to_radian(app.camera.rotation.x))}; + vec3f pos = {app.camera.position.x, app.camera.position.y, app.camera.position.z }; + + glLineWidth(20); + glBegin(GL_LINES); + glColor3f(1.0, 0.0, 0.0); + glVertex3f(pos.x, pos.y, pos.z); + glVertex3f(pos.x+5*dir.x, pos.y+5*dir.y, pos.z+5*dir.z); + glEnd(); + + SDL_GL_SwapWindow(app.window); + + clock_gettime(CLOCK_MONOTONIC_RAW, &end); + + printf("fps: %f\n", 1000/calc_frame_time(&start, &end)); + printf("lkat pos x: %f y: %f z: %f\n", pos.x+5*dir.x, pos.y+5*dir.y, pos.z+5*dir.z); + printf("lkat x: %f y: %f z: %f\n", dir.x, dir.y, dir.z); + app.frame_time = calc_frame_time(&start, &end); + } + + return 0; +} diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..93ef9f0 --- /dev/null +++ b/src/utils.c @@ -0,0 +1,31 @@ +#include "utils.h" + +#include +#include + +double degree_to_radian(double degree) +{ + return degree * M_PI / 180.0; +} + +bool is_oob(int i, int min, int max) +{ + if (i < min || i >= max) + return true; + return false; +} + +void mult_matrix(float *matrix, vec4f vector, vec4f *ret) +{ + float vec[] = {vector.x, vector.y, vector.z, vector.w}; + float ret1[4]; + for(int i = 0; i <= 12; i+=4) { + float line_sum = 0.0; + for(int j = 0; j < 4; j++){ + matrix[i+j] *= vec[j]; + line_sum += matrix[i+j]; + } + ret1[i/4] = line_sum; + } + ret->x = ret1[0]; ret->y = ret1[1]; ret->z=ret1[2]; ret->w = ret1[3]; +} \ No newline at end of file