From: outfrost Date: Wed, 19 Feb 2020 19:06:47 +0000 (+0000) Subject: Move code into game and engine directories X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=f4dbdbda0c191b72ad1f0fa44be0dc8d0b68775e;p=shadowclad.git Move code into game and engine directories --- diff --git a/src/asset.c b/src/asset.c deleted file mode 100644 index fafe81c..0000000 --- a/src/asset.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include -#include - -#include "asset.h" -#include "logger.h" -#include "tga.h" - -static const AiScene* importScene(const char* path); -static Vector3D convertAiVector3D(AiVector3D vect); -static const char* replaceFileExtension(const AiString path, const char* ext); - - - -const Asset3D* importAsset(const char* path) { - const AiScene* scene = importScene(path); - if (scene == NULL) { - return NULL; - } - - const unsigned int numMeshes = scene->mNumMeshes; - const unsigned int numMaterials = scene->mNumMaterials; - - Asset3D* asset = malloc(sizeof(Asset3D)); - asset->numMeshes = numMeshes; - asset->meshes = malloc(numMeshes * sizeof(Mesh)); - asset->numMaterials = numMaterials; - asset->materials = malloc(numMaterials * sizeof(Material)); - - for (unsigned int meshIndex = 0; meshIndex < numMeshes; ++meshIndex) { - const AiMesh* aiMesh = scene->mMeshes[meshIndex]; - const unsigned int numVertices = aiMesh->mNumVertices; - const unsigned int numFaces = aiMesh->mNumFaces; - - Mesh mesh = { .numVertices = numVertices, - .vertices = malloc(numVertices * sizeof(Vector3D)), - .normals = NULL, - .textureCoords = NULL, - .numFaces = numFaces, - .faces = malloc(numFaces * sizeof(Face)), - .materialIndex = aiMesh->mMaterialIndex }; - - for (unsigned int vertIndex = 0; vertIndex < numVertices; ++vertIndex) { - mesh.vertices[vertIndex] = convertAiVector3D( - aiMesh->mVertices[vertIndex]); - } - - if (aiMesh->mNormals != NULL) { - mesh.normals = malloc(numVertices * sizeof(Vector3D)); - for (unsigned int normIndex = 0; normIndex < numVertices; ++normIndex) { - mesh.normals[normIndex] = convertAiVector3D( - aiMesh->mNormals[normIndex]); - } - } - - mesh.textureCoords = malloc(numVertices * sizeof(Vector3D)); - for (unsigned int texcIndex = 0; texcIndex < numVertices; ++texcIndex) { - mesh.textureCoords[texcIndex] = convertAiVector3D( - aiMesh->mTextureCoords[0][texcIndex]); - } - - for (unsigned int faceIndex = 0; faceIndex < numFaces; ++faceIndex) { - const AiFace aiFace = aiMesh->mFaces[faceIndex]; - const unsigned int numIndices = aiFace.mNumIndices; - - Face face = { .numIndices = numIndices, - .indices = malloc(numIndices - * sizeof(unsigned int)) }; - - for (unsigned int i = 0; i < numIndices; ++i) { - face.indices[i] = aiFace.mIndices[i]; - } - - mesh.faces[faceIndex] = face; - } - - asset->meshes[meshIndex] = mesh; - } - - GLuint* textureIds = malloc(numMaterials * sizeof(GLuint)); - glGenTextures(numMaterials, textureIds); - - for (unsigned int matIndex = 0; matIndex < numMaterials; ++matIndex) { - Material material = { .textureId = textureIds[matIndex] }; - - glBindTexture(GL_TEXTURE_2D, material.textureId); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - AiString originalTexturePath; - if (aiGetMaterialTexture(scene->mMaterials[matIndex], - aiTextureType_DIFFUSE, - 0, - &originalTexturePath, - NULL, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS) { - const char* textureFile = replaceFileExtension(originalTexturePath, ".tga"); - const size_t textureFileLength = strlen(textureFile); - char* texturePath = malloc(strlen("assets/") + textureFileLength + 1); - strcpy(texturePath, "assets/"); - strncat(texturePath, textureFile, textureFileLength); - - TgaImage* textureImage = readTga(texturePath); - if (textureImage == NULL) { - logError("Asset texture file not found: %s", texturePath); - } - else { - glTexImage2D(GL_TEXTURE_2D, - 0, - textureImage->imageComponents, - textureImage->header.imageWidth, - textureImage->header.imageHeight, - 0, - textureImage->imageFormat, - GL_UNSIGNED_BYTE, - textureImage->bytes); - free(textureImage->bytes); - free(textureImage); - } - } - - asset->materials[matIndex] = material; - } - glBindTexture(GL_TEXTURE_2D, 0); - - aiReleaseImport(scene); - return asset; -} - -static const AiScene* importScene(const char* path) { - const AiScene* scene = aiImportFile(path, aiProcess_PreTransformVertices); - if (scene == NULL) { - logError("Failed to import asset from %s", path); - } - else if ((scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE) == AI_SCENE_FLAGS_INCOMPLETE) { - logError("Incomplete scene imported from %s", path); - aiReleaseImport(scene); - scene = NULL; - } - return scene; -} - -static Vector3D convertAiVector3D(AiVector3D vect) { - return (Vector3D) { .x = vect.x, - .y = vect.y, - .z = vect.z }; -} - -/** BUGS - * The following function will not work properly with texture - * file names (excluding directory part) beginning with '.' - */ -static const char* replaceFileExtension(const AiString path, const char* ext) { - size_t lengthToCopy = path.length; - - char* lastDotSubstr = strrchr(path.data, '.'); - if (lastDotSubstr != NULL) { - if (strpbrk(lastDotSubstr, "\\/") == NULL) { - lengthToCopy = lastDotSubstr - path.data; - } - } - - size_t extLength = strlen(ext) + 1; - char* newPath = malloc(lengthToCopy + extLength); - strncpy(newPath, path.data, lengthToCopy); - strncpy(newPath + lengthToCopy, ext, extLength); - - return newPath; -} diff --git a/src/asset.h b/src/asset.h deleted file mode 100644 index c16338f..0000000 --- a/src/asset.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef ASSET_H_ -#define ASSET_H_ - -#include - -#include "assimp_types.h" - -#include "typedefs.h" - -typedef struct Asset3D Asset3D; -typedef struct Mesh Mesh; -typedef struct Face Face; -typedef struct Material Material; - -struct Asset3D { - unsigned int numMeshes; - Mesh* meshes; - unsigned int numMaterials; - Material* materials; -}; - -struct Mesh { - unsigned int numVertices; - Vector3D* vertices; - Vector3D* normals; - Vector3D* textureCoords; - unsigned int numFaces; - Face* faces; - unsigned int materialIndex; -}; - -struct Face { - unsigned int numIndices; - unsigned int* indices; -}; - -struct Material { - GLuint textureId; -}; - -const Asset3D* importAsset(const char* path); - -#endif diff --git a/src/assimp_types.h b/src/assimp_types.h deleted file mode 100644 index 5e58279..0000000 --- a/src/assimp_types.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef ASSIMP_TYPES_H_ -#define ASSIMP_TYPES_H_ - -#include - -#ifdef ASSIMP_DOUBLE_PRECISION - #error "ASSIMP_DOUBLE_PRECISION is defined" - #error "shadowclad relies on ai_real defined as a single precision float" -#endif - -typedef struct aiScene AiScene; -typedef struct aiNode AiNode; -typedef struct aiMesh AiMesh; -typedef struct aiFace AiFace; -typedef struct aiVector3D AiVector3D; -typedef struct aiString AiString; - -#endif diff --git a/src/debugutil.c b/src/debugutil.c deleted file mode 100644 index 4292212..0000000 --- a/src/debugutil.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include -#include - -char* getGlInfoString() { - const char* glVersion = (const char*) glGetString(GL_VERSION); - const char* glslVersion = (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION); - const char* glRenderer = (const char*) glGetString(GL_RENDERER); - - size_t glInfoLength = strlen("OpenGL - GLSL - ") - + strlen(glVersion) - + strlen(glslVersion) - + strlen(glRenderer); - - char* glInfoString = malloc(glInfoLength + sizeof(char)); - sprintf(glInfoString, - "OpenGL %s - GLSL %s - %s", - glVersion, - glslVersion, - glRenderer); - - return glInfoString; -} diff --git a/src/debugutil.h b/src/debugutil.h deleted file mode 100644 index eb77ac9..0000000 --- a/src/debugutil.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef DEBUGUTIL_H_ -#define DEBUGUTIL_H_ - -#include - -char* getGlInfoString(); - -#endif diff --git a/src/engine/asset.c b/src/engine/asset.c new file mode 100644 index 0000000..fafe81c --- /dev/null +++ b/src/engine/asset.c @@ -0,0 +1,167 @@ +#include +#include +#include + +#include "asset.h" +#include "logger.h" +#include "tga.h" + +static const AiScene* importScene(const char* path); +static Vector3D convertAiVector3D(AiVector3D vect); +static const char* replaceFileExtension(const AiString path, const char* ext); + + + +const Asset3D* importAsset(const char* path) { + const AiScene* scene = importScene(path); + if (scene == NULL) { + return NULL; + } + + const unsigned int numMeshes = scene->mNumMeshes; + const unsigned int numMaterials = scene->mNumMaterials; + + Asset3D* asset = malloc(sizeof(Asset3D)); + asset->numMeshes = numMeshes; + asset->meshes = malloc(numMeshes * sizeof(Mesh)); + asset->numMaterials = numMaterials; + asset->materials = malloc(numMaterials * sizeof(Material)); + + for (unsigned int meshIndex = 0; meshIndex < numMeshes; ++meshIndex) { + const AiMesh* aiMesh = scene->mMeshes[meshIndex]; + const unsigned int numVertices = aiMesh->mNumVertices; + const unsigned int numFaces = aiMesh->mNumFaces; + + Mesh mesh = { .numVertices = numVertices, + .vertices = malloc(numVertices * sizeof(Vector3D)), + .normals = NULL, + .textureCoords = NULL, + .numFaces = numFaces, + .faces = malloc(numFaces * sizeof(Face)), + .materialIndex = aiMesh->mMaterialIndex }; + + for (unsigned int vertIndex = 0; vertIndex < numVertices; ++vertIndex) { + mesh.vertices[vertIndex] = convertAiVector3D( + aiMesh->mVertices[vertIndex]); + } + + if (aiMesh->mNormals != NULL) { + mesh.normals = malloc(numVertices * sizeof(Vector3D)); + for (unsigned int normIndex = 0; normIndex < numVertices; ++normIndex) { + mesh.normals[normIndex] = convertAiVector3D( + aiMesh->mNormals[normIndex]); + } + } + + mesh.textureCoords = malloc(numVertices * sizeof(Vector3D)); + for (unsigned int texcIndex = 0; texcIndex < numVertices; ++texcIndex) { + mesh.textureCoords[texcIndex] = convertAiVector3D( + aiMesh->mTextureCoords[0][texcIndex]); + } + + for (unsigned int faceIndex = 0; faceIndex < numFaces; ++faceIndex) { + const AiFace aiFace = aiMesh->mFaces[faceIndex]; + const unsigned int numIndices = aiFace.mNumIndices; + + Face face = { .numIndices = numIndices, + .indices = malloc(numIndices + * sizeof(unsigned int)) }; + + for (unsigned int i = 0; i < numIndices; ++i) { + face.indices[i] = aiFace.mIndices[i]; + } + + mesh.faces[faceIndex] = face; + } + + asset->meshes[meshIndex] = mesh; + } + + GLuint* textureIds = malloc(numMaterials * sizeof(GLuint)); + glGenTextures(numMaterials, textureIds); + + for (unsigned int matIndex = 0; matIndex < numMaterials; ++matIndex) { + Material material = { .textureId = textureIds[matIndex] }; + + glBindTexture(GL_TEXTURE_2D, material.textureId); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + AiString originalTexturePath; + if (aiGetMaterialTexture(scene->mMaterials[matIndex], + aiTextureType_DIFFUSE, + 0, + &originalTexturePath, + NULL, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS) { + const char* textureFile = replaceFileExtension(originalTexturePath, ".tga"); + const size_t textureFileLength = strlen(textureFile); + char* texturePath = malloc(strlen("assets/") + textureFileLength + 1); + strcpy(texturePath, "assets/"); + strncat(texturePath, textureFile, textureFileLength); + + TgaImage* textureImage = readTga(texturePath); + if (textureImage == NULL) { + logError("Asset texture file not found: %s", texturePath); + } + else { + glTexImage2D(GL_TEXTURE_2D, + 0, + textureImage->imageComponents, + textureImage->header.imageWidth, + textureImage->header.imageHeight, + 0, + textureImage->imageFormat, + GL_UNSIGNED_BYTE, + textureImage->bytes); + free(textureImage->bytes); + free(textureImage); + } + } + + asset->materials[matIndex] = material; + } + glBindTexture(GL_TEXTURE_2D, 0); + + aiReleaseImport(scene); + return asset; +} + +static const AiScene* importScene(const char* path) { + const AiScene* scene = aiImportFile(path, aiProcess_PreTransformVertices); + if (scene == NULL) { + logError("Failed to import asset from %s", path); + } + else if ((scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE) == AI_SCENE_FLAGS_INCOMPLETE) { + logError("Incomplete scene imported from %s", path); + aiReleaseImport(scene); + scene = NULL; + } + return scene; +} + +static Vector3D convertAiVector3D(AiVector3D vect) { + return (Vector3D) { .x = vect.x, + .y = vect.y, + .z = vect.z }; +} + +/** BUGS + * The following function will not work properly with texture + * file names (excluding directory part) beginning with '.' + */ +static const char* replaceFileExtension(const AiString path, const char* ext) { + size_t lengthToCopy = path.length; + + char* lastDotSubstr = strrchr(path.data, '.'); + if (lastDotSubstr != NULL) { + if (strpbrk(lastDotSubstr, "\\/") == NULL) { + lengthToCopy = lastDotSubstr - path.data; + } + } + + size_t extLength = strlen(ext) + 1; + char* newPath = malloc(lengthToCopy + extLength); + strncpy(newPath, path.data, lengthToCopy); + strncpy(newPath + lengthToCopy, ext, extLength); + + return newPath; +} diff --git a/src/engine/asset.h b/src/engine/asset.h new file mode 100644 index 0000000..c16338f --- /dev/null +++ b/src/engine/asset.h @@ -0,0 +1,43 @@ +#ifndef ASSET_H_ +#define ASSET_H_ + +#include + +#include "assimp_types.h" + +#include "typedefs.h" + +typedef struct Asset3D Asset3D; +typedef struct Mesh Mesh; +typedef struct Face Face; +typedef struct Material Material; + +struct Asset3D { + unsigned int numMeshes; + Mesh* meshes; + unsigned int numMaterials; + Material* materials; +}; + +struct Mesh { + unsigned int numVertices; + Vector3D* vertices; + Vector3D* normals; + Vector3D* textureCoords; + unsigned int numFaces; + Face* faces; + unsigned int materialIndex; +}; + +struct Face { + unsigned int numIndices; + unsigned int* indices; +}; + +struct Material { + GLuint textureId; +}; + +const Asset3D* importAsset(const char* path); + +#endif diff --git a/src/engine/assimp_types.h b/src/engine/assimp_types.h new file mode 100644 index 0000000..5e58279 --- /dev/null +++ b/src/engine/assimp_types.h @@ -0,0 +1,18 @@ +#ifndef ASSIMP_TYPES_H_ +#define ASSIMP_TYPES_H_ + +#include + +#ifdef ASSIMP_DOUBLE_PRECISION + #error "ASSIMP_DOUBLE_PRECISION is defined" + #error "shadowclad relies on ai_real defined as a single precision float" +#endif + +typedef struct aiScene AiScene; +typedef struct aiNode AiNode; +typedef struct aiMesh AiMesh; +typedef struct aiFace AiFace; +typedef struct aiVector3D AiVector3D; +typedef struct aiString AiString; + +#endif diff --git a/src/engine/debugutil.c b/src/engine/debugutil.c new file mode 100644 index 0000000..4292212 --- /dev/null +++ b/src/engine/debugutil.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include + +char* getGlInfoString() { + const char* glVersion = (const char*) glGetString(GL_VERSION); + const char* glslVersion = (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION); + const char* glRenderer = (const char*) glGetString(GL_RENDERER); + + size_t glInfoLength = strlen("OpenGL - GLSL - ") + + strlen(glVersion) + + strlen(glslVersion) + + strlen(glRenderer); + + char* glInfoString = malloc(glInfoLength + sizeof(char)); + sprintf(glInfoString, + "OpenGL %s - GLSL %s - %s", + glVersion, + glslVersion, + glRenderer); + + return glInfoString; +} diff --git a/src/engine/debugutil.h b/src/engine/debugutil.h new file mode 100644 index 0000000..eb77ac9 --- /dev/null +++ b/src/engine/debugutil.h @@ -0,0 +1,8 @@ +#ifndef DEBUGUTIL_H_ +#define DEBUGUTIL_H_ + +#include + +char* getGlInfoString(); + +#endif diff --git a/src/engine/logger.c b/src/engine/logger.c new file mode 100644 index 0000000..373df63 --- /dev/null +++ b/src/engine/logger.c @@ -0,0 +1,42 @@ +#include +#include + +#include "logger.h" + +LogLevel logLevel = LOGLEVEL_DEBUG; + + + +void logMessage(LogLevel msgLevel, const char* file, int line, const char* message, ...) { + if (msgLevel > logLevel) { + return; + } + + const char* msgLevelString; + switch (msgLevel) { + case LOGLEVEL_ERROR: + msgLevelString = "error: "; + break; + case LOGLEVEL_WARNING: + msgLevelString = "warning: "; + break; + case LOGLEVEL_INFO: + msgLevelString = ""; + break; + case LOGLEVEL_DEBUG: + msgLevelString = "debug: "; + break; + default: + msgLevelString = "(invalid message level!) "; + break; + } + + va_list args; + va_start(args, message); + + fprintf(stderr, "%s:%i: %s", file, line, msgLevelString); + vfprintf(stderr, message, args); + fputc('\n', stderr); + + va_end(args); +} diff --git a/src/engine/logger.h b/src/engine/logger.h new file mode 100644 index 0000000..4918f58 --- /dev/null +++ b/src/engine/logger.h @@ -0,0 +1,20 @@ +#ifndef LOGGER_H_ +#define LOGGER_H_ + +typedef enum { + LOGLEVEL_ERROR, + LOGLEVEL_WARNING, + LOGLEVEL_INFO, + LOGLEVEL_DEBUG +} LogLevel; + +LogLevel logLevel; + +#define logError(...) logMessage(LOGLEVEL_ERROR, __FILE__, __LINE__, __VA_ARGS__) +#define logWarning(...) logMessage(LOGLEVEL_WARNING, __FILE__, __LINE__, __VA_ARGS__) +#define logInfo(...) logMessage(LOGLEVEL_INFO, __FILE__, __LINE__, __VA_ARGS__) +#define logDebug(...) logMessage(LOGLEVEL_DEBUG, __FILE__, __LINE__, __VA_ARGS__) + +void logMessage(LogLevel msgLevel, const char* file, int line, const char* message, ...); + +#endif diff --git a/src/engine/performance.c b/src/engine/performance.c new file mode 100644 index 0000000..443652c --- /dev/null +++ b/src/engine/performance.c @@ -0,0 +1,51 @@ +#ifndef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 199309L +#endif + +#include +#include // TODO remove +#include + +#include "logger.h" + +typedef struct timespec Timepoint; + +static Timepoint lastDisplayTime; +static int frames = 0; +static bool meteringEnabled = false; + + + +void initPerformanceMetering() { + if (clock_gettime(CLOCK_MONOTONIC, &lastDisplayTime) != 0) { + logWarning("Clock read failed, performance metering unavailable"); + } + else { + meteringEnabled = true; + } +} + +void frameRendered() { + if (meteringEnabled) { + ++frames; + Timepoint now; + + if (clock_gettime(CLOCK_MONOTONIC, &now) != 0) { + logWarning("Clock read failed, stopping performance metering"); + meteringEnabled = false; + return; + } + + time_t fullSeconds = now.tv_sec - lastDisplayTime.tv_sec; + if (now.tv_nsec < lastDisplayTime.tv_nsec) --fullSeconds; + + if (fullSeconds > 0) { + float seconds = (now.tv_nsec - lastDisplayTime.tv_nsec) / 1000000000.0f; + seconds += (float) (now.tv_sec - lastDisplayTime.tv_sec); + // This goes to STDOUT because it's, uh, temporary + printf("frametime avg %.1f ms; fps avg %.f\n", (seconds / frames) * 1000.0f, (frames / seconds)); + lastDisplayTime = now; + frames = 0; + } + } +} diff --git a/src/engine/performance.h b/src/engine/performance.h new file mode 100644 index 0000000..b4ded6b --- /dev/null +++ b/src/engine/performance.h @@ -0,0 +1,7 @@ +#ifndef PERFORMANCE_H_ +#define PERFORMANCE_H_ + +void initPerformanceMetering(); +void frameRendered(); + +#endif diff --git a/src/engine/render.c b/src/engine/render.c new file mode 100644 index 0000000..56b0a9f --- /dev/null +++ b/src/engine/render.c @@ -0,0 +1,173 @@ +#include +#include + +#include "level.h" +#include "performance.h" +#include "player.h" +#include "typedefs.h" + +const float AXIS_RADIUS = 5.0f; + +static void setupCamera(); +static void moveCameraTo(const Vector3D pos); +static void drawAxes(); +static void renderBlockGrid(const BlockGrid grid); +static void renderCharacter(const Character* character, const Vector3D pos); +static void drawAsset3D(const Asset3D* asset3D); + +float viewportAspectRatio = 1.0f; + + + +void initRender() { + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + + GLfloat light0_ambient[] = {0.1f, 0.1f, 0.1f, 1.0f}; + GLfloat light0_diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f}; + GLfloat light0_specular[] = {0.96f, 0.98f, 1.0f, 1.0f}; + GLfloat light0_position[] = {5.0f, 10.0f, 5.0f, 0.0f}; // (w == 0.0f) == directional + + glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse); + glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular); + glLightfv(GL_LIGHT0, GL_POSITION, light0_position); + + glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.0f); + glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05f); + glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.005f); +} + +void renderScene() { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glEnable(GL_NORMALIZE); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + + setupCamera(); + moveCameraTo(playerPos); + + glDisable(GL_LIGHTING); + drawAxes(); + glEnable(GL_LIGHTING); + + glEnable(GL_LIGHT0); + glEnable(GL_TEXTURE_2D); + renderBlockGrid(levelGrid); + renderCharacter(&playerCharacter, playerPos); + glDisable(GL_TEXTURE_2D); + glDisable(GL_LIGHT0); + + glFlush(); + glutSwapBuffers(); + frameRendered(); + glutPostRedisplay(); +} + +static void setupCamera() { + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(-16.0, + 16.0, + -16.0/viewportAspectRatio, + 16.0/viewportAspectRatio, + -128.0, + 128.0); + glRotatef(45.0f, 1.0f, 0.0f, 0.0f); + glRotatef(45.0f, 0.0f, 1.0f, 0.0f); +} + +static void moveCameraTo(const Vector3D pos) { + glMatrixMode(GL_PROJECTION); + glTranslatef(-pos.x, -pos.y, -pos.z); +} + +static void drawAxes() { + glMatrixMode(GL_MODELVIEW); + // X axis + glColor3f(1.0f, 0.0f, 0.0f); + glBegin(GL_LINES); + glVertex3f(0.0f, 0.0f, 0.0f); + glVertex3f(AXIS_RADIUS, 0.0f, 0.0f); + glEnd(); + // Y axis + glColor3f(0.0f, 1.0f, 0.0f); + glBegin(GL_LINES); + glVertex3f(0.0f, 0.0f, 0.0f); + glVertex3f(0.0f, AXIS_RADIUS, 0.0f); + glEnd(); + // Z axis + glColor3f(0.0f, 0.0f, 1.0f); + glBegin(GL_LINES); + glVertex3f(0.0f, 0.0f, 0.0f); + glVertex3f(0.0f, 0.0f, AXIS_RADIUS); + glEnd(); +} + +static void renderBlockGrid(const BlockGrid grid) { + glMatrixMode(GL_MODELVIEW); + for (int z = 0; z < grid.depth; ++z) { + glLoadIdentity(); + glTranslatef(0.0f, 0.0f, z * BLOCKGRID_CELL_SIZE); + for (int x = 0; x < grid.width; ++x) { + drawAsset3D(getBlockFromGrid(grid, x, z)->asset3D); + glTranslatef(BLOCKGRID_CELL_SIZE, 0.0f, 0.0f); + } + } + glLoadIdentity(); +} + +static void renderCharacter(const Character* character, const Vector3D pos) { + glMatrixMode(GL_MODELVIEW); + glTranslatef(pos.x, pos.y, pos.z); + drawAsset3D(character->asset3D); + glLoadIdentity(); +} + +static void drawAsset3D(const Asset3D* asset3D) { + if (asset3D == NULL) { + return; + } + + glMatrixMode(GL_MODELVIEW); + glColor3f(0.5f, 1.0f, 0.0f); + + for (size_t meshIndex = 0; meshIndex < asset3D->numMeshes; ++meshIndex) { + const Mesh mesh = asset3D->meshes[meshIndex]; + glBindTexture(GL_TEXTURE_2D, + asset3D->materials[mesh.materialIndex].textureId); + bool hasNormals = mesh.normals != NULL; + bool hasTextureCoords = mesh.textureCoords != NULL; + + for (size_t faceIndex = 0; faceIndex < mesh.numFaces; ++faceIndex) { + const Face face = mesh.faces[faceIndex]; + + GLenum faceMode; + switch (face.numIndices) { + case 1: faceMode = GL_POINTS; break; + case 2: faceMode = GL_LINES; break; + case 3: faceMode = GL_TRIANGLES; break; + default: faceMode = GL_POLYGON; break; + } + + glBegin(faceMode); + + for (size_t i = 0; i < face.numIndices; ++i) { + unsigned int vertIndex = face.indices[i]; + if (hasNormals) { + if (hasTextureCoords) { + Vector3D coords = mesh.textureCoords[vertIndex]; + glTexCoord2f(coords.x, coords.y); + } + Vector3D normal = mesh.normals[vertIndex]; + glNormal3f(normal.x, normal.y, normal.z); + } + Vector3D vertex = mesh.vertices[vertIndex]; + glVertex3f(vertex.x, vertex.y, vertex.z); + } + + glEnd(); + } + } + glBindTexture(GL_TEXTURE_2D, 0); +} diff --git a/src/engine/render.h b/src/engine/render.h new file mode 100644 index 0000000..9251b16 --- /dev/null +++ b/src/engine/render.h @@ -0,0 +1,9 @@ +#ifndef RENDER_H_ +#define RENDER_H_ + +float viewportAspectRatio; + +void initRender(); +void renderScene(); + +#endif diff --git a/src/engine/tga.c b/src/engine/tga.c new file mode 100644 index 0000000..551039c --- /dev/null +++ b/src/engine/tga.c @@ -0,0 +1,67 @@ +#include +#include + +#include "tga.h" + +TgaImage* readTga(const char* path) { + FILE* tgaFile = fopen(path, "rb"); + if (tgaFile == NULL) { + return NULL; + } + + TgaHeader header; + + if (fread(&header, sizeof(TgaHeader), 1, tgaFile) != 1) { + fclose(tgaFile); + return NULL; + } + + GLenum imageFormat; + GLint imageComponents; + + switch (header.imageBpp) { + case 32: + imageFormat = GL_BGRA; + imageComponents = GL_RGBA8; + break; + case 24: + imageFormat = GL_BGR; + imageComponents = GL_RGB8; + break; + case 8: + imageFormat = GL_LUMINANCE; + imageComponents = GL_LUMINANCE8; + break; + default: + fclose(tgaFile); + return NULL; + } + + unsigned long imageSize = header.imageWidth * header.imageHeight * (header.imageBpp >> 3); + + GLbyte* bytes = malloc(imageSize * sizeof(GLbyte)); + if (bytes == NULL) { + fclose(tgaFile); + return NULL; + } + + if (fread(bytes, imageSize, 1, tgaFile) != 1) { + free(bytes); + fclose(tgaFile); + return NULL; + } + + fclose(tgaFile); + + TgaImage* image = malloc(sizeof(TgaImage)); + if (image == NULL) { + return NULL; + } + + (*image).header = header; + (*image).imageFormat = imageFormat; + (*image).imageComponents = imageComponents; + (*image).bytes = bytes; + + return image; +} diff --git a/src/engine/tga.h b/src/engine/tga.h new file mode 100644 index 0000000..96be414 --- /dev/null +++ b/src/engine/tga.h @@ -0,0 +1,32 @@ +#ifndef TGA_H_ +#define TGA_H_ + +#include + +#pragma pack(push, 1) +typedef struct { + GLubyte idLength; + GLbyte colorMapType; + GLbyte imageType; + GLushort colorMapStart; + GLushort colorMapLength; + GLubyte colorMapBpp; + GLushort originX; + GLushort originY; + GLushort imageWidth; + GLushort imageHeight; + GLubyte imageBpp; + GLbyte imageDescriptor; +} TgaHeader; +#pragma pack(pop) + +typedef struct { + TgaHeader header; + GLenum imageFormat; + GLint imageComponents; + GLbyte* bytes; +} TgaImage; + +TgaImage* readTga(const char* path); + +#endif diff --git a/src/engine/typedefs.h b/src/engine/typedefs.h new file mode 100644 index 0000000..8e690ed --- /dev/null +++ b/src/engine/typedefs.h @@ -0,0 +1,10 @@ +#ifndef TYPEDEFS_H_ +#define TYPEDEFS_H_ + +typedef struct { + float x; + float y; + float z; +} Vector3D; + +#endif diff --git a/src/engine/ui.c b/src/engine/ui.c new file mode 100644 index 0000000..a5b8b1e --- /dev/null +++ b/src/engine/ui.c @@ -0,0 +1,12 @@ +#include + +#include "render.h" + +void resizeStage(GLsizei width, GLsizei height) { + if (height == 0) + height = 1; + + glViewport(0, 0, width, height); + + viewportAspectRatio = (float) width / (float) height; +} diff --git a/src/engine/ui.h b/src/engine/ui.h new file mode 100644 index 0000000..5d3117a --- /dev/null +++ b/src/engine/ui.h @@ -0,0 +1,8 @@ +#ifndef GLUT_JANITOR_H_ +#define GLUT_JANITOR_H_ + +#include + +void resizeStage(GLsizei width, GLsizei height); + +#endif diff --git a/src/game/level.c b/src/game/level.c new file mode 100644 index 0000000..a16061a --- /dev/null +++ b/src/game/level.c @@ -0,0 +1,75 @@ +#include +#include + +#include "level.h" +#include "logger.h" +#include "player.h" + +static Block blockEmpty = { .type = BLOCKTYPE_SPACE, + .asset3D = NULL }; +static Block blockWall01 = { .type = BLOCKTYPE_OBSTACLE, + .asset3D = NULL }; + +static Block* testBlocks[9] = { &blockWall01, &blockWall01, &blockWall01, + &blockEmpty, &blockEmpty, &blockEmpty, + &blockWall01, &blockEmpty, &blockWall01 }; + +BlockGrid levelGrid = { .width = 3, + .depth = 3, + .blocks = testBlocks }; + +#define DEFAULT_PLAYER_SPAWN_POS { -BLOCKGRID_CELL_SIZE, 0.0f, -BLOCKGRID_CELL_SIZE } +Vector3D playerSpawnPos = DEFAULT_PLAYER_SPAWN_POS; + + + +void initLevel() { + blockWall01.asset3D = importAsset("assets/wall01.3ds"); + + buildLevelFromImage(readTga("assets/level01.tga")); +} + +void buildLevelFromImage(TgaImage* image) { + if (image == NULL) { + logError("Null image received, cannot build level"); + return; + } + + if (image->header.imageBpp != 32) { + logError("Invalid level image format (%d bpp)", image->header.imageBpp); + return; + } + + BlockGrid newGrid = { .width = image->header.imageWidth, + .depth = image->header.imageHeight, + .blocks = malloc(image->header.imageWidth + * image->header.imageHeight + * sizeof(Block*)) }; + playerSpawnPos = (Vector3D) DEFAULT_PLAYER_SPAWN_POS; + + for (int row = 0; row < newGrid.depth; ++row) { + for (int x = 0; x < newGrid.width; ++x) { + // Flip the image vertically due to (0, 0) being bottom left + int z = newGrid.depth - row - 1; + + uint32_t pixelColorARGB = ((uint32_t*) image->bytes)[(row * newGrid.width) + x]; + Block* block; + switch (pixelColorARGB) { + case 0xFFFF0000: + block = &blockWall01; + break; + case 0xFF00FFFF: + block = &blockEmpty; + playerSpawnPos = (Vector3D) { x * BLOCKGRID_CELL_SIZE, 0.0f, z * BLOCKGRID_CELL_SIZE }; + break; + default: + block = &blockEmpty; + break; + } + setBlockInGrid(newGrid, x, z, block); + } + } + + levelGrid = newGrid; + spawnPlayer(); +} diff --git a/src/game/level.h b/src/game/level.h new file mode 100644 index 0000000..967c78e --- /dev/null +++ b/src/game/level.h @@ -0,0 +1,43 @@ +#ifndef LEVEL_H_ +#define LEVEL_H_ + +#include + +#include "asset.h" +#include "tga.h" + +typedef enum { + BLOCKTYPE_SPACE, + BLOCKTYPE_OBSTACLE_X, + BLOCKTYPE_OBSTACLE_Z, + BLOCKTYPE_OBSTACLE +} BlockType; + +typedef struct { + const BlockType type; + const Asset3D* asset3D; +} Block; + +typedef struct { + int width; + int depth; + Block** blocks; +} BlockGrid; + +#define BLOCKGRID_CELL_SIZE 2.5f + +BlockGrid levelGrid; +Vector3D playerSpawnPos; + +void initLevel(); +void buildLevelFromImage(TgaImage* image); + +static inline Block* getBlockFromGrid(BlockGrid grid, int x, int z) { + return grid.blocks[(z * grid.width) + x]; +} + +static inline void setBlockInGrid(BlockGrid grid, int x, int z, Block* block) { + grid.blocks[(z * grid.width) + x] = block; +} + +#endif diff --git a/src/game/player.c b/src/game/player.c new file mode 100644 index 0000000..4e12613 --- /dev/null +++ b/src/game/player.c @@ -0,0 +1,15 @@ +#include "level.h" +#include "logger.h" +#include "player.h" + +Character playerCharacter = { .asset3D = NULL }; + + + +void initPlayer() { + playerCharacter.asset3D = importAsset("assets/playercharacter.3ds"); +} + +void spawnPlayer() { + playerPos = playerSpawnPos; +} diff --git a/src/game/player.h b/src/game/player.h new file mode 100644 index 0000000..4b0317c --- /dev/null +++ b/src/game/player.h @@ -0,0 +1,18 @@ +#ifndef PLAYER_H_ +#define PLAYER_H_ + +#include + +#include "asset.h" + +typedef struct { + const Asset3D* asset3D; +} Character; + +Character playerCharacter; +Vector3D playerPos; + +void initPlayer(); +void spawnPlayer(); + +#endif diff --git a/src/level.c b/src/level.c deleted file mode 100644 index a16061a..0000000 --- a/src/level.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include - -#include "level.h" -#include "logger.h" -#include "player.h" - -static Block blockEmpty = { .type = BLOCKTYPE_SPACE, - .asset3D = NULL }; -static Block blockWall01 = { .type = BLOCKTYPE_OBSTACLE, - .asset3D = NULL }; - -static Block* testBlocks[9] = { &blockWall01, &blockWall01, &blockWall01, - &blockEmpty, &blockEmpty, &blockEmpty, - &blockWall01, &blockEmpty, &blockWall01 }; - -BlockGrid levelGrid = { .width = 3, - .depth = 3, - .blocks = testBlocks }; - -#define DEFAULT_PLAYER_SPAWN_POS { -BLOCKGRID_CELL_SIZE, 0.0f, -BLOCKGRID_CELL_SIZE } -Vector3D playerSpawnPos = DEFAULT_PLAYER_SPAWN_POS; - - - -void initLevel() { - blockWall01.asset3D = importAsset("assets/wall01.3ds"); - - buildLevelFromImage(readTga("assets/level01.tga")); -} - -void buildLevelFromImage(TgaImage* image) { - if (image == NULL) { - logError("Null image received, cannot build level"); - return; - } - - if (image->header.imageBpp != 32) { - logError("Invalid level image format (%d bpp)", image->header.imageBpp); - return; - } - - BlockGrid newGrid = { .width = image->header.imageWidth, - .depth = image->header.imageHeight, - .blocks = malloc(image->header.imageWidth - * image->header.imageHeight - * sizeof(Block*)) }; - playerSpawnPos = (Vector3D) DEFAULT_PLAYER_SPAWN_POS; - - for (int row = 0; row < newGrid.depth; ++row) { - for (int x = 0; x < newGrid.width; ++x) { - // Flip the image vertically due to (0, 0) being bottom left - int z = newGrid.depth - row - 1; - - uint32_t pixelColorARGB = ((uint32_t*) image->bytes)[(row * newGrid.width) + x]; - Block* block; - switch (pixelColorARGB) { - case 0xFFFF0000: - block = &blockWall01; - break; - case 0xFF00FFFF: - block = &blockEmpty; - playerSpawnPos = (Vector3D) { x * BLOCKGRID_CELL_SIZE, 0.0f, z * BLOCKGRID_CELL_SIZE }; - break; - default: - block = &blockEmpty; - break; - } - setBlockInGrid(newGrid, x, z, block); - } - } - - levelGrid = newGrid; - spawnPlayer(); -} diff --git a/src/level.h b/src/level.h deleted file mode 100644 index 967c78e..0000000 --- a/src/level.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef LEVEL_H_ -#define LEVEL_H_ - -#include - -#include "asset.h" -#include "tga.h" - -typedef enum { - BLOCKTYPE_SPACE, - BLOCKTYPE_OBSTACLE_X, - BLOCKTYPE_OBSTACLE_Z, - BLOCKTYPE_OBSTACLE -} BlockType; - -typedef struct { - const BlockType type; - const Asset3D* asset3D; -} Block; - -typedef struct { - int width; - int depth; - Block** blocks; -} BlockGrid; - -#define BLOCKGRID_CELL_SIZE 2.5f - -BlockGrid levelGrid; -Vector3D playerSpawnPos; - -void initLevel(); -void buildLevelFromImage(TgaImage* image); - -static inline Block* getBlockFromGrid(BlockGrid grid, int x, int z) { - return grid.blocks[(z * grid.width) + x]; -} - -static inline void setBlockInGrid(BlockGrid grid, int x, int z, Block* block) { - grid.blocks[(z * grid.width) + x] = block; -} - -#endif diff --git a/src/logger.c b/src/logger.c deleted file mode 100644 index 373df63..0000000 --- a/src/logger.c +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include - -#include "logger.h" - -LogLevel logLevel = LOGLEVEL_DEBUG; - - - -void logMessage(LogLevel msgLevel, const char* file, int line, const char* message, ...) { - if (msgLevel > logLevel) { - return; - } - - const char* msgLevelString; - switch (msgLevel) { - case LOGLEVEL_ERROR: - msgLevelString = "error: "; - break; - case LOGLEVEL_WARNING: - msgLevelString = "warning: "; - break; - case LOGLEVEL_INFO: - msgLevelString = ""; - break; - case LOGLEVEL_DEBUG: - msgLevelString = "debug: "; - break; - default: - msgLevelString = "(invalid message level!) "; - break; - } - - va_list args; - va_start(args, message); - - fprintf(stderr, "%s:%i: %s", file, line, msgLevelString); - vfprintf(stderr, message, args); - fputc('\n', stderr); - - va_end(args); -} diff --git a/src/logger.h b/src/logger.h deleted file mode 100644 index 4918f58..0000000 --- a/src/logger.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef LOGGER_H_ -#define LOGGER_H_ - -typedef enum { - LOGLEVEL_ERROR, - LOGLEVEL_WARNING, - LOGLEVEL_INFO, - LOGLEVEL_DEBUG -} LogLevel; - -LogLevel logLevel; - -#define logError(...) logMessage(LOGLEVEL_ERROR, __FILE__, __LINE__, __VA_ARGS__) -#define logWarning(...) logMessage(LOGLEVEL_WARNING, __FILE__, __LINE__, __VA_ARGS__) -#define logInfo(...) logMessage(LOGLEVEL_INFO, __FILE__, __LINE__, __VA_ARGS__) -#define logDebug(...) logMessage(LOGLEVEL_DEBUG, __FILE__, __LINE__, __VA_ARGS__) - -void logMessage(LogLevel msgLevel, const char* file, int line, const char* message, ...); - -#endif diff --git a/src/performance.c b/src/performance.c deleted file mode 100644 index 443652c..0000000 --- a/src/performance.c +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _POSIX_C_SOURCE -#define _POSIX_C_SOURCE 199309L -#endif - -#include -#include // TODO remove -#include - -#include "logger.h" - -typedef struct timespec Timepoint; - -static Timepoint lastDisplayTime; -static int frames = 0; -static bool meteringEnabled = false; - - - -void initPerformanceMetering() { - if (clock_gettime(CLOCK_MONOTONIC, &lastDisplayTime) != 0) { - logWarning("Clock read failed, performance metering unavailable"); - } - else { - meteringEnabled = true; - } -} - -void frameRendered() { - if (meteringEnabled) { - ++frames; - Timepoint now; - - if (clock_gettime(CLOCK_MONOTONIC, &now) != 0) { - logWarning("Clock read failed, stopping performance metering"); - meteringEnabled = false; - return; - } - - time_t fullSeconds = now.tv_sec - lastDisplayTime.tv_sec; - if (now.tv_nsec < lastDisplayTime.tv_nsec) --fullSeconds; - - if (fullSeconds > 0) { - float seconds = (now.tv_nsec - lastDisplayTime.tv_nsec) / 1000000000.0f; - seconds += (float) (now.tv_sec - lastDisplayTime.tv_sec); - // This goes to STDOUT because it's, uh, temporary - printf("frametime avg %.1f ms; fps avg %.f\n", (seconds / frames) * 1000.0f, (frames / seconds)); - lastDisplayTime = now; - frames = 0; - } - } -} diff --git a/src/performance.h b/src/performance.h deleted file mode 100644 index b4ded6b..0000000 --- a/src/performance.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef PERFORMANCE_H_ -#define PERFORMANCE_H_ - -void initPerformanceMetering(); -void frameRendered(); - -#endif diff --git a/src/player.c b/src/player.c deleted file mode 100644 index 4e12613..0000000 --- a/src/player.c +++ /dev/null @@ -1,15 +0,0 @@ -#include "level.h" -#include "logger.h" -#include "player.h" - -Character playerCharacter = { .asset3D = NULL }; - - - -void initPlayer() { - playerCharacter.asset3D = importAsset("assets/playercharacter.3ds"); -} - -void spawnPlayer() { - playerPos = playerSpawnPos; -} diff --git a/src/player.h b/src/player.h deleted file mode 100644 index 4b0317c..0000000 --- a/src/player.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef PLAYER_H_ -#define PLAYER_H_ - -#include - -#include "asset.h" - -typedef struct { - const Asset3D* asset3D; -} Character; - -Character playerCharacter; -Vector3D playerPos; - -void initPlayer(); -void spawnPlayer(); - -#endif diff --git a/src/render.c b/src/render.c deleted file mode 100644 index 56b0a9f..0000000 --- a/src/render.c +++ /dev/null @@ -1,173 +0,0 @@ -#include -#include - -#include "level.h" -#include "performance.h" -#include "player.h" -#include "typedefs.h" - -const float AXIS_RADIUS = 5.0f; - -static void setupCamera(); -static void moveCameraTo(const Vector3D pos); -static void drawAxes(); -static void renderBlockGrid(const BlockGrid grid); -static void renderCharacter(const Character* character, const Vector3D pos); -static void drawAsset3D(const Asset3D* asset3D); - -float viewportAspectRatio = 1.0f; - - - -void initRender() { - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - - GLfloat light0_ambient[] = {0.1f, 0.1f, 0.1f, 1.0f}; - GLfloat light0_diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f}; - GLfloat light0_specular[] = {0.96f, 0.98f, 1.0f, 1.0f}; - GLfloat light0_position[] = {5.0f, 10.0f, 5.0f, 0.0f}; // (w == 0.0f) == directional - - glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient); - glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse); - glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular); - glLightfv(GL_LIGHT0, GL_POSITION, light0_position); - - glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.0f); - glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05f); - glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.005f); -} - -void renderScene() { - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glEnable(GL_NORMALIZE); - glEnable(GL_CULL_FACE); - glEnable(GL_DEPTH_TEST); - - setupCamera(); - moveCameraTo(playerPos); - - glDisable(GL_LIGHTING); - drawAxes(); - glEnable(GL_LIGHTING); - - glEnable(GL_LIGHT0); - glEnable(GL_TEXTURE_2D); - renderBlockGrid(levelGrid); - renderCharacter(&playerCharacter, playerPos); - glDisable(GL_TEXTURE_2D); - glDisable(GL_LIGHT0); - - glFlush(); - glutSwapBuffers(); - frameRendered(); - glutPostRedisplay(); -} - -static void setupCamera() { - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(-16.0, - 16.0, - -16.0/viewportAspectRatio, - 16.0/viewportAspectRatio, - -128.0, - 128.0); - glRotatef(45.0f, 1.0f, 0.0f, 0.0f); - glRotatef(45.0f, 0.0f, 1.0f, 0.0f); -} - -static void moveCameraTo(const Vector3D pos) { - glMatrixMode(GL_PROJECTION); - glTranslatef(-pos.x, -pos.y, -pos.z); -} - -static void drawAxes() { - glMatrixMode(GL_MODELVIEW); - // X axis - glColor3f(1.0f, 0.0f, 0.0f); - glBegin(GL_LINES); - glVertex3f(0.0f, 0.0f, 0.0f); - glVertex3f(AXIS_RADIUS, 0.0f, 0.0f); - glEnd(); - // Y axis - glColor3f(0.0f, 1.0f, 0.0f); - glBegin(GL_LINES); - glVertex3f(0.0f, 0.0f, 0.0f); - glVertex3f(0.0f, AXIS_RADIUS, 0.0f); - glEnd(); - // Z axis - glColor3f(0.0f, 0.0f, 1.0f); - glBegin(GL_LINES); - glVertex3f(0.0f, 0.0f, 0.0f); - glVertex3f(0.0f, 0.0f, AXIS_RADIUS); - glEnd(); -} - -static void renderBlockGrid(const BlockGrid grid) { - glMatrixMode(GL_MODELVIEW); - for (int z = 0; z < grid.depth; ++z) { - glLoadIdentity(); - glTranslatef(0.0f, 0.0f, z * BLOCKGRID_CELL_SIZE); - for (int x = 0; x < grid.width; ++x) { - drawAsset3D(getBlockFromGrid(grid, x, z)->asset3D); - glTranslatef(BLOCKGRID_CELL_SIZE, 0.0f, 0.0f); - } - } - glLoadIdentity(); -} - -static void renderCharacter(const Character* character, const Vector3D pos) { - glMatrixMode(GL_MODELVIEW); - glTranslatef(pos.x, pos.y, pos.z); - drawAsset3D(character->asset3D); - glLoadIdentity(); -} - -static void drawAsset3D(const Asset3D* asset3D) { - if (asset3D == NULL) { - return; - } - - glMatrixMode(GL_MODELVIEW); - glColor3f(0.5f, 1.0f, 0.0f); - - for (size_t meshIndex = 0; meshIndex < asset3D->numMeshes; ++meshIndex) { - const Mesh mesh = asset3D->meshes[meshIndex]; - glBindTexture(GL_TEXTURE_2D, - asset3D->materials[mesh.materialIndex].textureId); - bool hasNormals = mesh.normals != NULL; - bool hasTextureCoords = mesh.textureCoords != NULL; - - for (size_t faceIndex = 0; faceIndex < mesh.numFaces; ++faceIndex) { - const Face face = mesh.faces[faceIndex]; - - GLenum faceMode; - switch (face.numIndices) { - case 1: faceMode = GL_POINTS; break; - case 2: faceMode = GL_LINES; break; - case 3: faceMode = GL_TRIANGLES; break; - default: faceMode = GL_POLYGON; break; - } - - glBegin(faceMode); - - for (size_t i = 0; i < face.numIndices; ++i) { - unsigned int vertIndex = face.indices[i]; - if (hasNormals) { - if (hasTextureCoords) { - Vector3D coords = mesh.textureCoords[vertIndex]; - glTexCoord2f(coords.x, coords.y); - } - Vector3D normal = mesh.normals[vertIndex]; - glNormal3f(normal.x, normal.y, normal.z); - } - Vector3D vertex = mesh.vertices[vertIndex]; - glVertex3f(vertex.x, vertex.y, vertex.z); - } - - glEnd(); - } - } - glBindTexture(GL_TEXTURE_2D, 0); -} diff --git a/src/render.h b/src/render.h deleted file mode 100644 index 9251b16..0000000 --- a/src/render.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef RENDER_H_ -#define RENDER_H_ - -float viewportAspectRatio; - -void initRender(); -void renderScene(); - -#endif diff --git a/src/tga.c b/src/tga.c deleted file mode 100644 index 551039c..0000000 --- a/src/tga.c +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include - -#include "tga.h" - -TgaImage* readTga(const char* path) { - FILE* tgaFile = fopen(path, "rb"); - if (tgaFile == NULL) { - return NULL; - } - - TgaHeader header; - - if (fread(&header, sizeof(TgaHeader), 1, tgaFile) != 1) { - fclose(tgaFile); - return NULL; - } - - GLenum imageFormat; - GLint imageComponents; - - switch (header.imageBpp) { - case 32: - imageFormat = GL_BGRA; - imageComponents = GL_RGBA8; - break; - case 24: - imageFormat = GL_BGR; - imageComponents = GL_RGB8; - break; - case 8: - imageFormat = GL_LUMINANCE; - imageComponents = GL_LUMINANCE8; - break; - default: - fclose(tgaFile); - return NULL; - } - - unsigned long imageSize = header.imageWidth * header.imageHeight * (header.imageBpp >> 3); - - GLbyte* bytes = malloc(imageSize * sizeof(GLbyte)); - if (bytes == NULL) { - fclose(tgaFile); - return NULL; - } - - if (fread(bytes, imageSize, 1, tgaFile) != 1) { - free(bytes); - fclose(tgaFile); - return NULL; - } - - fclose(tgaFile); - - TgaImage* image = malloc(sizeof(TgaImage)); - if (image == NULL) { - return NULL; - } - - (*image).header = header; - (*image).imageFormat = imageFormat; - (*image).imageComponents = imageComponents; - (*image).bytes = bytes; - - return image; -} diff --git a/src/tga.h b/src/tga.h deleted file mode 100644 index 96be414..0000000 --- a/src/tga.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef TGA_H_ -#define TGA_H_ - -#include - -#pragma pack(push, 1) -typedef struct { - GLubyte idLength; - GLbyte colorMapType; - GLbyte imageType; - GLushort colorMapStart; - GLushort colorMapLength; - GLubyte colorMapBpp; - GLushort originX; - GLushort originY; - GLushort imageWidth; - GLushort imageHeight; - GLubyte imageBpp; - GLbyte imageDescriptor; -} TgaHeader; -#pragma pack(pop) - -typedef struct { - TgaHeader header; - GLenum imageFormat; - GLint imageComponents; - GLbyte* bytes; -} TgaImage; - -TgaImage* readTga(const char* path); - -#endif diff --git a/src/typedefs.h b/src/typedefs.h deleted file mode 100644 index 8e690ed..0000000 --- a/src/typedefs.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef TYPEDEFS_H_ -#define TYPEDEFS_H_ - -typedef struct { - float x; - float y; - float z; -} Vector3D; - -#endif diff --git a/src/ui.c b/src/ui.c deleted file mode 100644 index a5b8b1e..0000000 --- a/src/ui.c +++ /dev/null @@ -1,12 +0,0 @@ -#include - -#include "render.h" - -void resizeStage(GLsizei width, GLsizei height) { - if (height == 0) - height = 1; - - glViewport(0, 0, width, height); - - viewportAspectRatio = (float) width / (float) height; -} diff --git a/src/ui.h b/src/ui.h deleted file mode 100644 index 5d3117a..0000000 --- a/src/ui.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef GLUT_JANITOR_H_ -#define GLUT_JANITOR_H_ - -#include - -void resizeStage(GLsizei width, GLsizei height); - -#endif