diff options
Diffstat (limited to 'src/engine')
| -rw-r--r-- | src/engine/M_block.c | 33 | ||||
| -rw-r--r-- | src/engine/M_block.h | 26 | ||||
| -rw-r--r-- | src/engine/M_camera.c | 30 | ||||
| -rw-r--r-- | src/engine/M_camera.h | 19 | ||||
| -rw-r--r-- | src/engine/M_chunk.c | 24 | ||||
| -rw-r--r-- | src/engine/M_chunk.h | 17 | ||||
| -rw-r--r-- | src/engine/M_cube.c | 39 | ||||
| -rw-r--r-- | src/engine/M_cube.h | 4 | ||||
| -rw-r--r-- | src/engine/M_game.c | 66 | ||||
| -rw-r--r-- | src/engine/M_game.h | 33 | ||||
| -rw-r--r-- | src/engine/M_main.c | 48 | ||||
| -rw-r--r-- | src/engine/M_object.c | 108 | ||||
| -rw-r--r-- | src/engine/M_object.h | 64 | ||||
| -rw-r--r-- | src/engine/M_player.c | 32 | ||||
| -rw-r--r-- | src/engine/M_player.h | 16 | ||||
| -rw-r--r-- | src/engine/M_render.c | 17 | ||||
| -rw-r--r-- | src/engine/M_render.h | 16 | ||||
| -rw-r--r-- | src/engine/M_shader.c | 57 | ||||
| -rw-r--r-- | src/engine/M_shader.h | 21 | ||||
| -rw-r--r-- | src/engine/M_types.h | 10 |
20 files changed, 680 insertions, 0 deletions
diff --git a/src/engine/M_block.c b/src/engine/M_block.c new file mode 100644 index 0000000..0f3fb27 --- /dev/null +++ b/src/engine/M_block.c @@ -0,0 +1,33 @@ +#include "M_block.h" + +void M_createBlock(M_Block *block, unsigned short type) +{ + block->type = type; +} + +unsigned short M_createBlockType(M_Object obj, M_BlockAtlas *atl) +{ + M_BlockType block_type; + block_type.obj = obj; + + if (atl->block_amount >= atl->size) { + atl->size += 10; + atl->blocks = realloc(atl->blocks, atl->size*sizeof(M_BlockType)); + } + atl->blocks[atl->block_amount++] = block_type; + return atl->block_amount; +} + +M_BlockAtlas M_createBlockAtlas() +{ + return (M_BlockAtlas){ + .blocks = malloc(10*sizeof(M_BlockType)), + .block_amount = 0, + .size = 10 + }; +} + +void M_killBlockAtlas(M_BlockAtlas *atl) +{ + free(atl->blocks); +} diff --git a/src/engine/M_block.h b/src/engine/M_block.h new file mode 100644 index 0000000..852830c --- /dev/null +++ b/src/engine/M_block.h @@ -0,0 +1,26 @@ +#pragma once + +//#include "M_types.ḥ" +#include "M_object.h" + +typedef struct { + unsigned short type; +} M_Block; + +typedef struct { + M_Object obj; +} M_BlockType; + +typedef struct { + M_BlockType *blocks; + unsigned short block_amount; + unsigned short size; +} M_BlockAtlas; + +void M_createBlock(M_Block *block, unsigned short type); + +unsigned short M_createBlockType(M_Object obj, M_BlockAtlas *atl); + +M_BlockAtlas M_createBlockAtlas(); + +void M_killBlockAtlas(M_BlockAtlas *atl); diff --git a/src/engine/M_camera.c b/src/engine/M_camera.c new file mode 100644 index 0000000..58414a7 --- /dev/null +++ b/src/engine/M_camera.c @@ -0,0 +1,30 @@ +#include "M_camera.h" + +void M_initCamera(M_Camera *camera, vec3 up) +{ + glm_vec3_zero(camera->pos); + glm_vec3_copy( + up, + camera->up + ); + glm_vec3_copy( + (vec3){0.0f, 0.0f, -1.0f}, + camera->direction + ); +} + +inline void M_cameraViewMatrix(M_Camera* camera) +{ + vec3 target; + glm_vec3_add( + camera->pos, + camera->direction, + target + ); + glm_lookat( + camera->pos, + target, + camera->up, + camera->view_matrix + ); +} diff --git a/src/engine/M_camera.h b/src/engine/M_camera.h new file mode 100644 index 0000000..4663a94 --- /dev/null +++ b/src/engine/M_camera.h @@ -0,0 +1,19 @@ +#pragma once + +#include <cglm/cglm.h> +#include <cglm/mat4.h> +#include <cglm/vec3.h> + +typedef struct { + vec3 pos; + vec3 direction; + vec3 up; + + mat4 view_matrix; +} M_Camera; + + +void M_initCamera(M_Camera *camera, vec3 up); + +//Generates the M_Camera's view matrix required for rendering +void M_cameraViewMatrix(M_Camera *camera); diff --git a/src/engine/M_chunk.c b/src/engine/M_chunk.c new file mode 100644 index 0000000..5c120f5 --- /dev/null +++ b/src/engine/M_chunk.c @@ -0,0 +1,24 @@ +#include "M_chunk.h" + +void M_generateChunk(M_Chunk *chunk) +{ + for (int x=0;x<M_CHUNK_SIZE;x++) + for (int y=0;y<M_CHUNK_SIZE;y++) + for (int z=0;z<M_CHUNK_SIZE;z++) { + M_Block block; + M_createBlock(&block, 0); + chunk->blocks[x][y][z] = block; + } +} + +void M_renderChunk(M_Game *game, M_Chunk *chunk) +{ + for (int x=0;x<M_CHUNK_SIZE;x++) + for (int y=0;y<M_CHUNK_SIZE;y++) + for (int z=0;z<M_CHUNK_SIZE;z++) { + M_Block block = chunk->blocks[x][y][z]; + M_Object *block_object = &game->block_atlas.blocks[block.type].obj; + M_moveObject(block_object, (vec3){(float)x, (float)y-32, (float)z}); + M_drawObject(&game->render_info, &game->player.camera, block_object); + } +} diff --git a/src/engine/M_chunk.h b/src/engine/M_chunk.h new file mode 100644 index 0000000..be1d4f1 --- /dev/null +++ b/src/engine/M_chunk.h @@ -0,0 +1,17 @@ +#pragma once + +#include "M_object.h" +#include "M_block.h" +#include "M_game.h" + +#define M_CHUNK_SIZE 32 + + +typedef struct { + M_Block blocks[M_CHUNK_SIZE][M_CHUNK_SIZE][M_CHUNK_SIZE]; + int x, y, z; +} M_Chunk; + +void M_generateChunk(M_Chunk *chunk); + +void M_renderChunk(M_Game *game, M_Chunk *chunk); diff --git a/src/engine/M_cube.c b/src/engine/M_cube.c new file mode 100644 index 0000000..3be7417 --- /dev/null +++ b/src/engine/M_cube.c @@ -0,0 +1,39 @@ +#include "M_cube.h" + +M_ViewModel M_createCube() +{ + float vertices[] = { + 1.0f, 1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + -1.0f, -1.0f, -1.0f, + -1.0f, 1.0f, -1.0f, + + 1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, + -1.0f, -1.0f, 1.0f, + -1.0f, 1.0f, 1.0f + }; + unsigned int indices[] = { + 0, 1, 2, + 0, 2, 3, + + 4, 5, 6, + 4, 6, 7, + + 0, 4, 5, + 2, 6, 3, + + 3, 7, 6, + 1, 5, 0, + + 3, 7, 0, + 0, 4, 7, + + 2, 6, 1, + 1, 5, 6 + }; + + M_ViewModel model; + M_createViewModel(&model, 8, vertices, 38, indices); + return model; +} diff --git a/src/engine/M_cube.h b/src/engine/M_cube.h new file mode 100644 index 0000000..5c82901 --- /dev/null +++ b/src/engine/M_cube.h @@ -0,0 +1,4 @@ +#pragma once +#include "M_object.h" + +M_ViewModel M_createCube(); diff --git a/src/engine/M_game.c b/src/engine/M_game.c new file mode 100644 index 0000000..3c76d96 --- /dev/null +++ b/src/engine/M_game.c @@ -0,0 +1,66 @@ +#include "M_game.h" + +int M_initGame(M_Game *game, const char *window_title) +{ + game->window_width = 1280; + game->window_height = 720; + + SDL_Init( + SDL_INIT_VIDEO + ); + + game->window = SDL_CreateWindow( + window_title, + game->window_width, + game->window_height, + SDL_WINDOW_OPENGL + ); + M_setupProjection(90.0f, ((float)game->window_width)/((float)game->window_height), &game->render_info); + + game->block_atlas = M_createBlockAtlas(); + + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + game->gpu = SDL_GL_CreateContext(game->window); + + SDL_GL_MakeCurrent(game->window, game->gpu); + + game->running = 1; + + int version = gladLoadGL((GLADloadfunc)SDL_GL_GetProcAddress); + if (version == 0) { + return 1; + } + + game->event_handler = SDL_CreateThread(M_handleEvents, "eventHandler", (void*)game); + + glClearColor(0.0f, 0.25f, 0.5f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + return 0; +} + +int M_killGame(M_Game *game) +{ + SDL_WaitThread(game->event_handler, NULL); + SDL_Quit(); + return 0; +} + +int SDLCALL M_handleEvents(void* arg) +{ + M_Game *game = arg; + SDL_Event event; + while (game->running) { + SDL_PollEvent(&event); + switch (event.type) { + case SDL_EVENT_QUIT: + game->running = 0; + break; + } + SDL_Delay(1); + } + return 0; +} diff --git a/src/engine/M_game.h b/src/engine/M_game.h new file mode 100644 index 0000000..a0b7942 --- /dev/null +++ b/src/engine/M_game.h @@ -0,0 +1,33 @@ +#pragma once + +#include <SDL3/SDL_init.h> +#include <SDL3/SDL_video.h> +#include <SDL3/SDL_timer.h> + +#include <glad/gl.h> + +//#include "M_types.h" +#include "M_render.h" +#include "M_player.h" +//#include "M_object.h" +#include "M_block.h" + +typedef struct { + SDL_Window *window; + SDL_GLContext gpu; + + int window_width, window_height; + int running; + M_RenderInfo render_info; + + M_BlockAtlas block_atlas; + + M_Player player; + + SDL_Thread *event_handler; +} M_Game; + +int M_initGame(M_Game *game, const char *window_title); +int M_killGame(M_Game *game); + +int SDLCALL M_handleEvents(void* arg); diff --git a/src/engine/M_main.c b/src/engine/M_main.c new file mode 100644 index 0000000..93c186e --- /dev/null +++ b/src/engine/M_main.c @@ -0,0 +1,48 @@ +#include <SDL3/SDL_video.h> + +#include "M_game.h" +#include "M_object.h" +#include "M_cube.h" +#include "M_block.h" +#include "M_chunk.h" + +int main() +{ + M_Game game; + M_initGame(&game, "MNM Engine"); + M_initPlayer(&game.player); + + M_ViewModel cube_model = M_createCube(); + + M_ShaderProgram my_shader = M_createShaderProgram( + "../src/shaders/test.vert", + "../src/shaders/test.frag" + ); + + M_Object my_cube; + M_createObject(&my_cube, &cube_model); + my_cube.shader = &my_shader; + + M_scaleObject(&my_cube, (vec3){0.5f, 0.5, 0.5f}); + + M_createBlockType(my_cube, &game.block_atlas); + + M_Chunk my_chunk; + M_generateChunk(&my_chunk); + + M_moveObject(&my_cube, (vec3){0.0f, -0.5f, -1.0f}); + + M_bindViewModel(my_cube.model); + + while (game.running) { + glClear(GL_COLOR_BUFFER_BIT); + glClear(GL_DEPTH_BUFFER_BIT); + M_renderChunk(&game, &my_chunk); + SDL_GL_SwapWindow(game.window); + } + + M_killShaderProgram(&my_shader); + M_killViewModel(&cube_model); + M_killGame(&game); + return 0; +} diff --git a/src/engine/M_object.c b/src/engine/M_object.c new file mode 100644 index 0000000..07293d5 --- /dev/null +++ b/src/engine/M_object.c @@ -0,0 +1,108 @@ +#include "M_object.h" +#include "M_camera.h" + +void M_createViewModel(M_ViewModel *model, int num_vertices, float *vert, int num_indices, unsigned int *indices) +{ + model->num_indices = num_indices; + + glGenVertexArrays(1, &model->VAO); + glBindVertexArray(model->VAO); + + glGenBuffers(1, &model->VBO); + glBindBuffer(GL_ARRAY_BUFFER, model->VBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*num_vertices*3, vert, GL_STATIC_DRAW); + + glGenBuffers(1, &model->EBO); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, model->EBO); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*num_indices, indices, GL_STATIC_DRAW); + + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); + glEnableVertexAttribArray(0); +} + +void M_killViewModel(M_ViewModel *model) +{ + glDeleteVertexArrays(1, &model->VAO); + glDeleteBuffers(1, &model->VBO); + glDeleteBuffers(1, &model->EBO); +} + +M_ViewModel M_loadViewModel(const char* filename) +{ + const struct aiScene* scene = aiImportFile(filename, + aiProcess_CalcTangentSpace | + aiProcess_Triangulate | + aiProcess_JoinIdenticalVertices | + aiProcess_SortByPType); + + struct aiMesh *mesh = scene->mMeshes[0]; + + unsigned int *indices = malloc(mesh->mNumFaces*3*sizeof(unsigned int)); + int index = 0; + for (unsigned int i=0;i<mesh->mNumFaces;i++) { + memcpy(&indices[index], mesh->mFaces[i].mIndices, 3*sizeof(unsigned int)); + index+=3; + } + + M_ViewModel model; + M_createViewModel(&model, mesh->mNumVertices, (float*)mesh->mVertices, mesh->mNumFaces*3, indices); + free(indices); + return model; +} + +void M_bindViewModel(M_ViewModel *model) +{ + glBindVertexArray(model->VAO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, model->EBO); +} + + +void M_createObject(M_Object *obj, M_ViewModel *model) +{ + obj->model = model; + glm_mat4_identity(obj->transform); + + glm_vec3_zero(obj->pos); + glm_vec3_one(obj->size); + + obj->rotation.angle = 0.0f; + glm_vec3_zero(obj->rotation.direction); +} + +void M_moveObject(M_Object *obj, vec3 pos) +{ + glm_vec3_copy( + pos, + obj->pos + ); + M_updateObjectTransform(obj); +} + +void M_scaleObject(M_Object *obj, vec3 scale) +{ + glm_vec3_copy( + scale, + obj->size + ); + M_updateObjectTransform(obj); +} + +void M_rotateObject(M_Object *obj, float angle, vec3 direction) +{ + obj->rotation.angle = angle; + glm_vec3_copy( + direction, + obj->rotation.direction + ); + M_updateObjectTransform(obj); +} + +inline void M_updateObjectTransform(M_Object *obj) +{ + glm_mat4_identity(obj->transform); + glm_translate(obj->transform, obj->pos); + glm_rotate(obj->transform, obj->rotation.angle, obj->rotation.direction); + glm_scale(obj->transform, obj->size); +} + diff --git a/src/engine/M_object.h b/src/engine/M_object.h new file mode 100644 index 0000000..ca87f0a --- /dev/null +++ b/src/engine/M_object.h @@ -0,0 +1,64 @@ +#pragma once + +#include <cglm/cglm.h> +#include <cglm/mat4.h> +#include <cglm/vec3.h> + +#include <assimp/cimport.h> +#include <assimp/scene.h> +#include <assimp/mesh.h> +#include <assimp/postprocess.h> + +//#include "M_game.h" +#include "M_shader.h" + +//Temporary type for storing M_Object rotation information, +//will get replaced in later revisions. +typedef struct { + float angle; + vec3 direction; +} M_Rotation; + +//Stores information about a 3D model loaded in VRAM +typedef struct { + int num_indices; + + unsigned int VAO, VBO, EBO; +} M_ViewModel; + +//Type meant for handling 3D models in a scene, +//stores additional information like a model's position, size and rotation. +typedef struct { + M_ViewModel *model; + M_ShaderProgram *shader; + + vec3 pos, size; + + M_Rotation rotation; + + mat4 transform; +} M_Object; + +//Creates a M_ViewModel out of vertices and indices manually +void M_createViewModel(M_ViewModel *model, int num_vertices, float *vert, int num_indices, unsigned int *indices); + +//Unloads M_ViewModel from memory when no longer needed +void M_killViewModel(M_ViewModel *model); + +//Loads and creates a M_ViewModel from a 3D object file like .obj +M_ViewModel M_loadViewModel(const char* filename); + +//Creates a M_Object +void M_createObject(M_Object *obj, M_ViewModel *model); + + +//Functions for moving, scaling and rotating M_Object +void M_moveObject(M_Object *obj, vec3 pos); +void M_scaleObject(M_Object *obj, vec3 scale); +void M_rotateObject(M_Object *obj, float angle, vec3 direction); + +//Updates M_Object transform matrix manually +void M_updateObjectTransform(M_Object *obj); + +//Binds M_ViewModel for drawing +void M_bindViewModel(M_ViewModel *model); diff --git a/src/engine/M_player.c b/src/engine/M_player.c new file mode 100644 index 0000000..1e065fd --- /dev/null +++ b/src/engine/M_player.c @@ -0,0 +1,32 @@ +#include "M_player.h" + +void M_initPlayer(M_Player* player) +{ + glm_vec3_zero(player->pos); + M_initCamera(&player->camera, (vec3){0.0f, 1.0f, 0.0f}); +} + +void M_teleportPlayer(M_Player* player, vec3 pos) +{ + glm_vec3_copy( + pos, + player->pos + ); + glm_vec3_copy( + pos, + player->camera.pos + ); +} + +void M_movePlayer(M_Player* player, vec3 pos) +{ + glm_vec3_add( + pos, + player->pos, + player->pos + ); + glm_vec3_copy( + player->pos, + player->camera.pos + ); +} diff --git a/src/engine/M_player.h b/src/engine/M_player.h new file mode 100644 index 0000000..80856f8 --- /dev/null +++ b/src/engine/M_player.h @@ -0,0 +1,16 @@ +#pragma once + +#include <cglm/vec3.h> + +#include "M_camera.h" + +typedef struct { + vec3 pos; + M_Camera camera; +} M_Player; + +void M_initPlayer(M_Player* player); + + +//void M_teleportPlayer(M_Player* player, vec3 pos) +void M_movePlayer(M_Player* player, vec3 pos); diff --git a/src/engine/M_render.c b/src/engine/M_render.c new file mode 100644 index 0000000..1d83ceb --- /dev/null +++ b/src/engine/M_render.c @@ -0,0 +1,17 @@ +#include "M_render.h" + +void M_setupProjection(float fov, float aspect_ratio, M_RenderInfo *render_info) +{ + glm_perspective(fov, aspect_ratio, 0.01f, 10.0f, render_info->projection_matrix); +} + +void M_drawObject(M_RenderInfo *render_info, M_Camera *camera, M_Object *obj) +{ + glUseProgram(obj->shader->prog); + glUniformMatrix4fv(obj->shader->transform_loc, 1, GL_FALSE, (float*)obj->transform); + M_cameraViewMatrix(camera); + glUniformMatrix4fv(obj->shader->view_loc, 1, GL_FALSE, (float*)camera->view_matrix); + glUniformMatrix4fv(obj->shader->projection_loc, 1, GL_FALSE, (float*)render_info->projection_matrix); + + glDrawElements(GL_TRIANGLES, obj->model->num_indices, GL_UNSIGNED_INT, 0); +} diff --git a/src/engine/M_render.h b/src/engine/M_render.h new file mode 100644 index 0000000..948f0d5 --- /dev/null +++ b/src/engine/M_render.h @@ -0,0 +1,16 @@ +#pragma once + +#include <cglm/cglm.h> +#include <cglm/mat4.h> + +#include "M_object.h" +#include "M_camera.h" + +typedef struct { + mat4 view_matrix, projection_matrix; +} M_RenderInfo; + +void M_setupProjection(float fov, float aspect_ratio, M_RenderInfo *render_indo); + +//Draws M_Object in space +void M_drawObject(M_RenderInfo *render_info, M_Camera *camera, M_Object *obj); diff --git a/src/engine/M_shader.c b/src/engine/M_shader.c new file mode 100644 index 0000000..17f6248 --- /dev/null +++ b/src/engine/M_shader.c @@ -0,0 +1,57 @@ +#include "M_shader.h" + +unsigned int M_loadShader(const char* filename, unsigned int shadertype) +{ + void* shader_source = SDL_LoadFile(filename, NULL); + unsigned int shader = glCreateShader(shadertype); + glShaderSource(shader, 1, (const char**)&shader_source, NULL); + glCompileShader(shader); + SDL_free(shader_source); + + int success; + + glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + if (!success) { + printf("Couldn't compile shader\n"); + return 0; + } + + return shader; +} + +M_ShaderProgram M_createShaderProgram(const char *vertex_shader_file, const char* fragment_shader_file) +{ + unsigned int vertex_shader = M_loadShader(vertex_shader_file, GL_VERTEX_SHADER); + unsigned int fragment_shader = M_loadShader(fragment_shader_file, GL_FRAGMENT_SHADER); + return M_compileShaderProgram(vertex_shader, fragment_shader); +} + +M_ShaderProgram M_compileShaderProgram(unsigned int vertex_shader, unsigned int fragment_shader) +{ + M_ShaderProgram shader_program; + shader_program.prog = glCreateProgram(); + glAttachShader(shader_program.prog, vertex_shader); + glAttachShader(shader_program.prog, fragment_shader); + glLinkProgram(shader_program.prog); + + shader_program.vertex_shader = vertex_shader; + shader_program.fragment_shader = fragment_shader; + + int success; + glGetProgramiv(shader_program.prog, GL_LINK_STATUS, &success); + if (!success) { + printf("Couldn't link shader program\n"); + } + + shader_program.transform_loc = glGetUniformLocation(shader_program.prog, "model"); + shader_program.view_loc = glGetUniformLocation(shader_program.prog, "view"); + shader_program.projection_loc = glGetUniformLocation(shader_program.prog, "projection"); + + return shader_program; +} + +void M_killShaderProgram(M_ShaderProgram *shader_program) +{ + glDeleteShader(shader_program->vertex_shader); + glDeleteShader(shader_program->fragment_shader); +} diff --git a/src/engine/M_shader.h b/src/engine/M_shader.h new file mode 100644 index 0000000..0dbd170 --- /dev/null +++ b/src/engine/M_shader.h @@ -0,0 +1,21 @@ +#pragma once + +#include <stdio.h> + +#include <SDL3/SDL_iostream.h> + +#include <glad/gl.h> + +typedef struct { + unsigned int prog; + unsigned int vertex_shader, fragment_shader; + unsigned int transform_loc, view_loc, projection_loc; +} M_ShaderProgram; + +unsigned int M_loadShader(const char* filename, unsigned int shadertype); + +M_ShaderProgram M_createShaderProgram(const char *vertex_shader, const char* fragment_shader); + +M_ShaderProgram M_compileShaderProgram(unsigned int vertex_shader, unsigned int fragment_shader); + +void M_killShaderProgram(M_ShaderProgram *shader_program); diff --git a/src/engine/M_types.h b/src/engine/M_types.h new file mode 100644 index 0000000..cba3310 --- /dev/null +++ b/src/engine/M_types.h @@ -0,0 +1,10 @@ +#pragma once + +typedef struct M_Game; + +typedef struct M_ViewModel; +typedef struct M_Object; + +typedef struct M_Block; +typedef struct M_BlockType; +typedef struct M_BlockAtlas; |
