diff --git a/.gitmodules b/.gitmodules index e2adf70..d26cc89 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "ext/aixlog"] path = ext/aixlog url = https://github.com/badaix/aixlog.git +[submodule "ext/stb_libs"] + path = ext/stb_libs + url = https://github.com/nothings/stb.git diff --git a/Makefile b/Makefile index dae0f08..1b47404 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ CXX = g++ -CXXFLAGS = -std=c++11 -g -ggdb -Wall -I/usr/include/SDL2 -Iext/aixlog/include +CXXFLAGS = -std=c++11 -g -ggdb -Wall -I/usr/include/SDL2 -Iext/aixlog/include -Iext/stb_libs SRC_DIR = src OBJ_DIR = build @@ -16,10 +16,6 @@ GL3W_LDFLAGS += -ldl # don't know a good way to require this in make without forcing a specific version LDFLAGS = -lSDL2 -lGLEW -lGL -# SDL2_image -CXXFLAGS += $(shell pkg-config --cflags SDL2_image) -LDFLAGS += $(shell pkg-config --libs SDL2_image) - # IMGUI IMGUI_DIR = ext/imgui CXXFLAGS += -I$(IMGUI_DIR) \ diff --git a/data/test_scene.json b/data/test_scene.json index a8499fb..5a23173 100644 --- a/data/test_scene.json +++ b/data/test_scene.json @@ -71,6 +71,46 @@ "y" : 10, "z" : 10 } + }, + { + "name" : "box", + "model_file" : "animated.block.dae", + "position" : { + "x" : 140, + "y" : -100, + "z" : 0 + }, + "rotation" : { + "x" : 0, + "y" : 0, + "z" : 0, + "w" : 0 + }, + "scale" : { + "x" : 10, + "y" : 10, + "z" : 10 + } + }, + { + "name" : "ground", + "model_file" : "test.level.dae", + "position" : { + "x" : 0, + "y" : 0, + "z" : -100 + }, + "rotation" : { + "x" : 0, + "y" : 0, + "z" : 0, + "w" : 0 + }, + "scale" : { + "x" : 500, + "y" : 500, + "z" : 500 + } } ], diff --git a/ext/stb_libs b/ext/stb_libs new file mode 160000 index 0000000..e6afb9c --- /dev/null +++ b/ext/stb_libs @@ -0,0 +1 @@ +Subproject commit e6afb9cbae4064da8c3e69af3ff5c4629579c1d2 diff --git a/src/hexgame.cpp b/src/hexgame.cpp index 363575f..70884f7 100644 --- a/src/hexgame.cpp +++ b/src/hexgame.cpp @@ -51,8 +51,6 @@ #include #endif -#include - // TODO: replace aixlog with simpler logging #if defined(_WIN32) #pragma warning(push) @@ -271,7 +269,6 @@ cleanUp(SDL_Handles &handles) for (SDL_Surface *surface : handles.texSurfaces) SDL_FreeSurface(surface); meShutdownAssimp(); // mesh.h - IMG_Quit(); // SDL_image SDL_GL_DeleteContext(handles.glContext); SDL_DestroyWindow(handles.window); SDL_Quit(); @@ -332,26 +329,6 @@ int main(int argc, char* argv[]) return 1; } - { - // load support for the JPG and PNG image formats - int flags=IMG_INIT_JPG|IMG_INIT_PNG; - int initted=IMG_Init(flags); - if((initted&flags) != flags) - { - LOG(ERROR) << "IMG_Init: Failed to init required jpg and png support!\n"; - LOG(ERROR) << "IMG_Init: " << IMG_GetError() << "\n"; - return 1; - } - - // pre-load textures - const char * path = "../data/coords.layout.flat.png"; - if (!renAddTexture(g_render_state->handles, path)) - { - LOG(ERROR) << "Error adding " << path << "\n"; - return 1; - } - } - if (!meInitAssimp()) { LOG(ERROR) << "Error initializing assimp\n"; return 1; diff --git a/src/mesh.cpp b/src/mesh.cpp index cadb900..0d114b1 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -1,5 +1,5 @@ #include -#include // calloc +#include #include #include @@ -15,7 +15,7 @@ inline glm::vec3 copyVector(aiVector3D v_in, glm::vec3& v_out); -meMeshInfo* copyMeshInfo(const aiScene* scene, aiMesh* mesh); +meMeshInfo* copyMeshInfo(const char* data_dir, const aiScene* scene, aiMesh* mesh); void freeMesh(meMeshInfo* mesh); bool @@ -32,7 +32,7 @@ meInitAssimp() } bool -meLoadFromFile(const char* filename, meMeshGroup& mesh_group) +meLoadFromFile(const char* data_dir, const char* filename, meMeshGroup& mesh_group) { LOG(INFO) << "Loading file: " << filename << "\n"; const aiScene* scene = aiImportFile(filename, aiProcessPreset_TargetRealtime_MaxQuality); @@ -48,11 +48,11 @@ meLoadFromFile(const char* filename, meMeshGroup& mesh_group) } mesh_group.num_meshes = scene->mNumMeshes; - mesh_group.meshes = (meMeshInfo**) std::calloc(mesh_group.num_meshes, sizeof(meMeshInfo*)); + mesh_group.meshes = UTIL_ALLOC(mesh_group.num_meshes, meMeshInfo*); mesh_group.use_normals = scene->mMeshes[0]->HasNormals(); for (uint i = 0; i < scene->mNumMeshes; i++) { - mesh_group.meshes[i] = copyMeshInfo(scene, scene->mMeshes[i]); + mesh_group.meshes[i] = copyMeshInfo(data_dir, scene, scene->mMeshes[i]); } // free memeory from assimp @@ -65,6 +65,8 @@ meFreeMeshGroup(meMeshGroup& mesh_group) { for (uint i = 0; i < mesh_group.num_meshes; i++) freeMesh(mesh_group.meshes[i]); + + utilSafeFree(mesh_group.meshes); } void @@ -83,17 +85,17 @@ copyVector(aiVector3D v_in, glm::vec3& v_out) } meMeshInfo* -copyMeshInfo(const aiScene* scene, aiMesh* mesh) +copyMeshInfo(const char* data_dir, const aiScene* scene, aiMesh* mesh) { - meMeshInfo* mi = (meMeshInfo*) std::calloc(1, sizeof(meMeshInfo)); + meMeshInfo* mi = UTIL_ALLOC(1, meMeshInfo); mi->model_transform = glm::mat4(1); // allocate buffers for vertex and index data from mesh mi->num_vertices = mesh->mNumVertices; - mi->vertices = (glm::vec3 *) std::calloc(mi->num_vertices, sizeof(glm::vec3)); - mi->normals = (glm::vec3 *) std::calloc(mi->num_vertices, sizeof(glm::vec3)); + mi->vertices = UTIL_ALLOC(mi->num_vertices, glm::vec3); + mi->normals = UTIL_ALLOC(mi->num_vertices, glm::vec3); mi->num_indices = mesh->mNumFaces * 3; // NOTE: assume 3 vertices per face - mi->indices = (uint *) std::calloc(mi->num_indices, sizeof(uint)); + mi->indices = UTIL_ALLOC(mi->num_indices, uint); // copy vertices and normals for (uint i = 0; i < mi->num_vertices; i++) { @@ -119,12 +121,30 @@ copyMeshInfo(const aiScene* scene, aiMesh* mesh) mi->diffuse_color.b = color.b; } + if (mat->GetTextureCount(aiTextureType_DIFFUSE) > 0) { + aiString file_name; + if (AI_SUCCESS != mat->GetTexture(aiTextureType_DIFFUSE, 0, &file_name, NULL, NULL, NULL, NULL, NULL)) { + LOG(ERROR) << "Some Assimp-type-error\n"; + } else { + std::string file_path; + file_path.append(data_dir).append("/").append(file_name.C_Str()); + LOG(INFO) << "Loading texture file: " << file_name.C_Str() << "\n"; + mi->diffuse_texture_path = file_path.c_str(); + mi->diffuse_texture = utilLoadImage(file_path.c_str()); + } + } + return mi; } void freeMesh(meMeshInfo* mesh) { + if (mesh->diffuse_texture.pixels != 0) { + utilFreeImage(mesh->diffuse_texture); + mesh->diffuse_texture_path = 0; + } + utilSafeFree(mesh->vertices); utilSafeFree(mesh->normals); utilSafeFree(mesh->indices); diff --git a/src/mesh.h b/src/mesh.h index 2eecc55..ef8ba99 100644 --- a/src/mesh.h +++ b/src/mesh.h @@ -18,6 +18,9 @@ struct meMeshInfo uint num_indices = 0; uint* indices = nullptr; glm::vec3 diffuse_color; + + const char* diffuse_texture_path; + util_image diffuse_texture; }; struct meMeshGroup @@ -31,7 +34,7 @@ struct meMeshGroup bool meInitAssimp(); -bool meLoadFromFile(const char* filename, meMeshGroup& mesh_group); +bool meLoadFromFile(const char* data_dir, const char* filename, meMeshGroup& mesh_group); void meFreeMeshGroup(meMeshGroup& mesh_group); diff --git a/src/renderer.cpp b/src/renderer.cpp index eb008bc..247c96d 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -9,7 +9,6 @@ #else #include #endif -#include #include #include #include @@ -130,6 +129,8 @@ renFreeBuffers(render_state* rs) bool renAddTexture(SDL_Handles &handles, const char * path) { + // TODO: saved here for moving to stb_image implementation +#if 0 // testing LOG(INFO) << "Loading image: " << path << "\n"; SDL_Surface* image = IMG_Load(path); @@ -151,7 +152,7 @@ renAddTexture(SDL_Handles &handles, const char * path) // store opengl id in SDL_Surface.userdat image->userdata = (void*)(intptr_t) tex_id; handles.texSurfaces.push_back(image); - +#endif return true; } diff --git a/src/scene_loader.cpp b/src/scene_loader.cpp index 60aa0f4..ddcfec1 100644 --- a/src/scene_loader.cpp +++ b/src/scene_loader.cpp @@ -83,13 +83,14 @@ slParseEntities( std::string model_path; model_path.append(data_dir).append("/").append(entities[i]["model_file"].GetString()); - if (meLoadFromFile(model_path.c_str(), mg)) { + if (meLoadFromFile(data_dir, model_path.c_str(), mg)) { Entity& e = entity_array[i]; e.mesh_group = mg; e.scale = parseVec3(entities[i]["scale"]); e.translation = parseVec3(entities[i]["position"]); } else { LOG(ERROR) << "Error loading mesh file\n"; + meFreeMeshGroup(mg); return false; } diff --git a/src/util.cpp b/src/util.cpp index 4582db2..8b64892 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -3,6 +3,8 @@ #include #include +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" #include "aixlog.hpp" #include "util.h" @@ -52,21 +54,40 @@ utilLogAlloc(uint item_count, uint type_size, const char* file_name, const int l } // TODO: search/replace other calls to std::free with this -void -utilSafeFree(void* mem) +void utilSafeFree(const void* mem) { if (mem != nullptr) { - std::free(mem); + std::free((void *) mem); mem = nullptr; } } -// TODO: re-use non-const version, macro or cast away const -void utilSafeFree(const void* mem) +util_image +utilLoadImage(const char* filename) { - if (mem != nullptr) { - std::free((void *) mem); - mem = nullptr; + LOG(INFO) << "Loading Image: " << filename << "\n"; + + util_image image; + image.pixels = stbi_load(filename, &image.w, &image.h, &image.num_channels, 0); + image.data_len = image.w * image.h * image.num_channels; // NOTE: assumes 8 bits per channel + + if (image.pixels == 0) { + LOG(ERROR) << stbi_failure_reason() << "\n"; + utilFreeImage(image); + return image; } + + LOG(INFO) << "Image properties, data_len: " << image.data_len + << ", width: " << image.w << ", height: " << image.h << "\n"; + + return image; } +void +utilFreeImage(util_image image) +{ + image.w = image.h = image.data_len = 0; + image.bits_per_channel = 8; + image.num_channels = 4; + utilSafeFree(image.pixels); +} diff --git a/src/util.h b/src/util.h index f29797b..7fc03ca 100644 --- a/src/util.h +++ b/src/util.h @@ -15,6 +15,7 @@ typedef uint8_t uint8; typedef uint32_t uint32; typedef uint32_t uint; + struct v2f { v2f(): x(0), y(0) {} @@ -48,6 +49,16 @@ struct v4i int32 y1; }; +struct util_image +{ + int32 w = 0; + int32 h = 0; + int32 bits_per_channel = 8; + int32 num_channels = 4; + uint data_len = 0; + uint8* pixels = nullptr; +}; + inline real32 SafeRatio(real32 dividend, real32 divisor) { @@ -75,10 +86,14 @@ utilConvertColor(GLfloat buf[3], uint32 color) } // NOTE: Wrapper for calloc that will send error message on out of memory -void * utilLogAlloc(uint item_count, uint type_size, const char* file_name, const int line); #define UTIL_ALLOC(len, type) (type *) utilLogAlloc((len), sizeof(type), __FILE__, __LINE__) +void * utilLogAlloc(uint item_count, uint type_size, const char* file_name, const int line); char * utilDumpTextFile(const char* filename); -void utilSafeFree(void* mem); + +util_image utilLoadImage(const char* filename); + +void utilFreeImage(util_image image); + void utilSafeFree(const void* mem);