commit ef44b24798759e762afcaeb469f2a3421b048768 Author: Adog64 Date: Wed Nov 29 14:01:37 2023 -0500 Cube rendering in c! diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..26511c5 --- /dev/null +++ b/Makefile @@ -0,0 +1,62 @@ +# the name of your executable +TARGET = PlanetMiner + +# launches your target in terminal +RUN = ./$(TARGET) + +# directory for your source files +SRC_DIR = src + +# directory for your object files +BUILD_DIR = bin + +# add more CompilerFLAGS as your project requires +CFLAGS = -Wall -Wextra -O3 + +# add libraries for your project here +LDFLAGS = + +# add library linker commands here (start with -l) +LOADLIBS = -lglfw -lGLEW -lGL + +# add library search paths here (start with -L) +LDLIBS = + +# add include paths (start with -I) +INC = + +# finds all your objects that corrispond to your .cpp files, system agnostic version +OBJECTS := $(patsubst $(SRC_DIR)/%.c, $(BUILD_DIR)/%.o, $(wildcard $(SRC_DIR)/*.c)) + +.PHONY: all +# makes build directory, updates your objects, builds your executable +all: + mkdir -p $(BUILD_DIR) + +$(MAKE) $(TARGET) + +# updates your objects, builds your executable +$(TARGET): $(OBJECTS) + $(CC) $(OBJECTS) $(CFLAGS) -o $@ $(LOADLIBS) $(LDFLAGS) $(LDLIBS) $(INC) + +# builds your objects +$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c + $(CC) $(CFLAGS) -c $< -o $@ $(LOADLIBS) $(LDFLAGS) $(LDLIBS) $(INC) + +# deletes your built objects and executable +.PHONY: clean +clean: + -rm -rf $(BUILD_DIR) $(TARGET) + clear + +# makes build direcotry, updates your objects, builds your executable, launches your program +.PHONY: run +run: + +$(MAKE) all + $(RUN) + +# explains the only three options you should be using (unless you build more of your own) +.PHONY: help +help: + @echo "`make` - builds/updates everything, is ready to run with `$(RUN)` after completion" + @echo "`make clean` - removes object file folder and executable" + @echo "`make run` - builds/updates everything, runs immediately" diff --git a/PlanetMiner b/PlanetMiner new file mode 100755 index 0000000..ae91123 Binary files /dev/null and b/PlanetMiner differ diff --git a/bin/main.o b/bin/main.o new file mode 100644 index 0000000..79d1912 Binary files /dev/null and b/bin/main.o differ diff --git a/bin/textfiles.o b/bin/textfiles.o new file mode 100644 index 0000000..7614711 Binary files /dev/null and b/bin/textfiles.o differ diff --git a/devlog.md b/devlog.md new file mode 100644 index 0000000..6cb6426 --- /dev/null +++ b/devlog.md @@ -0,0 +1,32 @@ +# Planet Miner Development Log + +## November 24th, 2023 + +### General Comments +- Messed around with Godot, didn't really find it all that interesting. +- Started writing a game engine in C. + - Really liking it so far + - Feels like I have finer control + - I'll definitely be using my mouse less, so that's nice + +### C-Based Game Engine +- Boiler plate! Boiler plate! Boiler plate! + - I can't render a boiler or its plate yet. + - Window opens + - Can draw triangle with vertex and fragment shader + - Text file loading works + +#### Text File Reading Functions +- Very nice +- Nice wrapper for builtin functions +- Probably will be used a lot, better keep it simple + +### Error Codes? +- Gonna be writing a lot of code that throws errors, especially when writing all this darn ***BOILER PLATE*** +- Error code standards to be implemented - will be documented when done + +## November 25th, 2023 + +### Boiler plate +- Fixed text file loading not always null terminating stream +- Cube rendering! diff --git a/src/SimpleFragmentShader.fragmentshader b/src/SimpleFragmentShader.fragmentshader new file mode 100644 index 0000000..d2e0cfa --- /dev/null +++ b/src/SimpleFragmentShader.fragmentshader @@ -0,0 +1,7 @@ +#version 330 core +// Ouput data +out vec3 color; +void main() +{ + color = vec3(1,1,1); +} diff --git a/src/SimpleVertexShader.vertexshader b/src/SimpleVertexShader.vertexshader new file mode 100644 index 0000000..28f88c7 --- /dev/null +++ b/src/SimpleVertexShader.vertexshader @@ -0,0 +1,9 @@ +#version 330 core + +layout(location = 0) in vec3 vertexPosition_modelspace; + +uniform mat4 MVP; + +void main(){ + gl_Position = MVP * vec4(vertexPosition_modelspace,1); +} diff --git a/src/controls.h b/src/controls.h new file mode 100644 index 0000000..41ba43b --- /dev/null +++ b/src/controls.h @@ -0,0 +1,14 @@ +#include + +typedef struct camera +{ + vec3s pos; + vec3s dir; + vec3s +} + +void goForward(); +void goBackward(); +void goLeft(); +void goRight(); +void yawLeft(); diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..2afe0a9 --- /dev/null +++ b/src/main.c @@ -0,0 +1,250 @@ +#include +#include +#include + +#include + +#include +GLFWwindow* window; + +#include + +#define WINW 800 +#define WINH 450 + +#define FOV 1.4f + +#define SHADER_BUF_SIZE 1000 + +GLuint loadShaders(const char*, const char*); + +int main() +{ + glewExperimental = true; + if( !glfwInit() ) + { + fprintf( stderr, "Failed to initialize GLFW :(\n" ); + return -1; + } + glfwWindowHint(GLFW_SAMPLES, 4); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); + + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + + window = glfwCreateWindow(WINW, WINH, "Planet Miner", NULL, NULL); + if( window == NULL ) + { + fprintf( stderr, "Failed to create window. If you are using an Intel GPU, please note that they are not compatible with OpenGL 3.3\n" ); + glfwTerminate(); + return -1; + } + glfwMakeContextCurrent(window); + + glewExperimental = true; + if( glewInit() != GLEW_OK ) + { + fprintf( stderr, "Failed to initialize GLEW\n" ); + getchar(); + glfwTerminate(); + return -1; + } + + glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE); + + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + + GLuint vertexArrayID; + glGenVertexArrays(1, &vertexArrayID); + glBindVertexArray(vertexArrayID); + + + GLuint programID = loadShaders( "src/SimpleVertexShader.vertexshader", "src/SimpleFragmentShader.fragmentshader" ); + + GLuint matrixID = glGetUniformLocation(programID, "MVP"); + + mat4s projection = glms_perspective(FOV, 16.0f / 9.0f, 0.1f, 100.0f); + + vec3s eye = {0.0f, 0.0f, 5.0f}; + vec3s center = {0.0f, 0.0f, 0.0f}; + vec3s up = {0.0f, 1.0f, 0.0f}; + + static const GLfloat g_vertex_buffer_data[] = { + -1.0f,-1.0f,-1.0f, // triangle 1 : begin + -1.0f,-1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, // triangle 1 : end + 1.0f, 1.0f,-1.0f, // triangle 2 : begin + -1.0f,-1.0f,-1.0f, + -1.0f, 1.0f,-1.0f, // triangle 2 : end + 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, + -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, + 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, + 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 + }; + + GLuint vertexbuffer; + glGenBuffers(1, &vertexbuffer); + glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW); + + vec3s direction = {0.0f, 0.0f, -5.0f}; + + do + { + glClear( GL_COLOR_BUFFER_BIT ); + g + + if( glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS ) + { + eye.z -= 0.05f; + } + if( glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS ) + { + eye.z += 0.05f; + } + if( glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS ) + { + eye.x += 0.05f; + } + if( glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS ) + { + eye.x -= 0.05f; + } + if( glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS ) + { + eye.y += 0.05f; + } + if( glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS ) + { + eye.y -= 0.05f; + } + + + center = glms_vec3_add(eye, direction); + + mat4s view = glms_lookat(eye, center, up); + mat4s model = glms_mat4_identity(); + mat4s mvp = glms_mat4_mul(glms_mat4_mul(projection, view), model); + + glUseProgram(programID); + + glUniformMatrix4fv(matrixID, 1, GL_FALSE, &mvp); + + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); + + glVertexAttribPointer( + 0, + 3, + GL_FLOAT, + GL_FALSE, + 0, + (void*)0 + ); + + glDrawArrays(GL_TRIANGLES, 0, 12*3); + glDisableVertexAttribArray(0); + + glfwSwapBuffers(window); + glfwPollEvents(); + } + while( glfwGetKey(window, GLFW_KEY_Q) | glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && !glfwWindowShouldClose(window)); + + glDeleteBuffers(1, &vertexbuffer); + glDeleteProgram(programID); + glDeleteVertexArrays(1, &vertexArrayID); + + glfwTerminate(); + + return 0; +} + +GLuint loadShaders(const char* vertexShaderPath, const char* fragmentShaderPath) +{ + char* vertexShaderCode = readTextFile( vertexShaderPath ); + char* fragmentShaderCode = readTextFile( fragmentShaderPath ); + + GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER); + GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); + + GLint result = GL_FALSE; + int infoLogLength; + + printf("Compiling vertex shader...\n"); + glShaderSource(vertexShaderID, 1, &vertexShaderCode, NULL); + glCompileShader(vertexShaderID); + + glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &result); + glGetShaderiv(vertexShaderID, GL_INFO_LOG_LENGTH, &infoLogLength); + if( infoLogLength > 0 ) + { + char vertexShaderErrorMessage[infoLogLength + 1]; + glGetShaderInfoLog(vertexShaderID, infoLogLength, NULL, &vertexShaderErrorMessage); + printf("%s\n", &vertexShaderErrorMessage); + } + + printf("Compiling fragment shader...\n"); + glShaderSource(fragmentShaderID, 1, &fragmentShaderCode, NULL); + glCompileShader(fragmentShaderID); + + glGetShaderiv(fragmentShaderID, GL_COMPILE_STATUS, &result); + glGetShaderiv(fragmentShaderID, GL_INFO_LOG_LENGTH, &infoLogLength); + if( infoLogLength > 0 ) + { + char fragmentShaderErrorMessage[infoLogLength + 1]; + glGetShaderInfoLog(fragmentShaderID, infoLogLength, NULL, &fragmentShaderErrorMessage); + printf("%s\n", &fragmentShaderErrorMessage); + } + + printf("Linking program\n"); + GLuint programID = glCreateProgram(); + glAttachShader(programID, vertexShaderID); + glAttachShader(programID, fragmentShaderID); + glLinkProgram(programID); + + glGetProgramiv(programID, GL_LINK_STATUS, &result); + glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &infoLogLength); + if( infoLogLength > 0 ) + { + char programErrorMessage[infoLogLength + 1]; + glGetProgramInfoLog(programID, infoLogLength, NULL, &programErrorMessage); + printf("%s\n", &programErrorMessage); + } + + free( vertexShaderCode ); + free( fragmentShaderCode ); + + glDetachShader( programID, vertexShaderID ); + glDetachShader( programID, fragmentShaderID ); + + glDeleteShader( vertexShaderID ); + glDeleteShader( fragmentShaderID ); + return programID; +} diff --git a/src/textfiles.c b/src/textfiles.c new file mode 100644 index 0000000..de6edf8 --- /dev/null +++ b/src/textfiles.c @@ -0,0 +1,46 @@ +#include +#include +#pragma once + + +// Reads an entire text file into a buffer. +// USES MALLOC BE SURE TO FREE +char* readTextFile(char* fname) +{ + FILE* inFile; + long fileLength; + char* fileBuffer; + size_t result; + + inFile = fopen( fname, "rb" ); + if( inFile == NULL ) + { + fprintf( stderr, "Failed open file, [%s].\n", fname ); + exit(1); + } + + fseek( inFile, 0, SEEK_END ); + fileLength = ftell( inFile ); + printf("File length: %d\n", fileLength); + rewind( inFile ); + + fileBuffer = (char*) malloc(sizeof(char) * (fileLength + 1)); + if( fileBuffer == NULL ) + { + fprintf( stderr, "Failed to allocate memory for reading the file, [%s].\n", fname); + exit(2); + } + + result = fread( fileBuffer, 1, fileLength, inFile ); + if( result != fileLength ) + { + fprintf( stderr, "Failed while reading [%s] into the file buffer.\n", fname); + exit(3); + } + + fileBuffer[fileLength] = '\0'; + + fclose( inFile ); + + return fileBuffer; +} diff --git a/src/textfiles.h b/src/textfiles.h new file mode 100644 index 0000000..409eb9e --- /dev/null +++ b/src/textfiles.h @@ -0,0 +1 @@ +char* readTextFile(char*); diff --git a/src/worldgen.c b/src/worldgen.c new file mode 100644 index 0000000..6b54831 --- /dev/null +++ b/src/worldgen.c @@ -0,0 +1,21 @@ +#include "worldgen.h" +#include + +#define ORDER 1 +#define RSQRT5 0.4472135954999579 +#define TWICE_RSQRT5 = 0.8944271909999159 + +worldMesh generateWorld(vec3s position) +{ + // placeholder struct for world mesh + worldMesh mesh; + vertex.count = 20 * ORDER * 3; // Icosahedron has 20 triangular sides + + mesh.vertices = (GLfloat*) malloc(sizeof(GLfloat) * mesh.count); + populateIcosphere(mesh, ORDER, 1); +} + +void populateIcosphere(worldMesh mesh, unsigned char order, float radius) +{ + +} diff --git a/src/worldgen.h b/src/worldgen.h new file mode 100644 index 0000000..08af7bd --- /dev/null +++ b/src/worldgen.h @@ -0,0 +1,15 @@ +#include + +typedef struct worldMesh { + long int count; + GLfloat* vertices; +} worldMesh; + + +/*! + * @brief top-level world generation function + * + * @param[in] pos the position of the center of the roughly spherical world + * @return the world mesh as a heap-allocated list of vertices. + */ +worldMesh generateWorld(vec3s pos); diff --git a/todo.md b/todo.md new file mode 100644 index 0000000..05c7b8b --- /dev/null +++ b/todo.md @@ -0,0 +1,45 @@ +# Planet Miner To Do List + +## Priority List +1. Render stuff + 1. Render a cube + 2. Render a bunch of cubes + 3. Diffuse lighting + 4. Ray tracing? +2. Procedural worlds + 1. Optimize rendering for this many cubes +3. Block game + 1. World editing + +## Idea Categories +1. Game Engine? + - Custom in C + - Started work on one, kinda liking it so far + - Don't really like pre-built game engines + - If I use one it'll likely be Godot + +2. Voxelization + - Zoning + - Each planet has its own coordinate system (non-voxelized) + - Material is distributed in amorphous blobs containing a certain percent resource + - Before world editing can begin, a work zone must be established to create a local voxelized coordinate system + - + +3. Progression + - The cores of planets exist as large non-voxelized structures + - Requires high level tools to mine + - Contain lots of resources + - Nickel + - Iron + - Asteroids can be mined like planet cores + - Less valuable resources + - Mostly rock + - Requires lower level tools + - Game starts on an Earth-like planet + - Make basic tool with sticks rope and stone fragments + - Stone fragments from smashing stones on rock + +4. Documentation +- Error Codes! +- In-Game Wiki-System +