diff --git a/CMakeLists.txt b/CMakeLists.txt index e4feef1..a2823b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,10 +6,10 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules") function(setup_target NAME) set_property(TARGET ${NAME} PROPERTY CXX_STANDARD 14) set_property(TARGET ${NAME} PROPERTY CXX_STANDARD_REQUIRED ON) - #target_compile_options(${NAME} PRIVATE -Wall -Wextra) - #target_compile_options(${NAME} PRIVATE -fdiagnostics-color=always) - #target_compile_options(${NAME} PRIVATE $<$:-ggdb -O2>) - #target_compile_options(${NAME} PRIVATE $<$:-O3 -NDEBUG>) + target_compile_options(${NAME} PRIVATE -Wall -Wextra) + target_compile_options(${NAME} PRIVATE -fdiagnostics-color=always) + target_compile_options(${NAME} PRIVATE $<$:-ggdb -O2>) + target_compile_options(${NAME} PRIVATE $<$:-O3 -NDEBUG>) endfunction(setup_target) add_subdirectory(game) diff --git a/game/CMakeLists.txt b/game/CMakeLists.txt index d5a0caa..b572f5c 100644 --- a/game/CMakeLists.txt +++ b/game/CMakeLists.txt @@ -4,6 +4,7 @@ find_package(OpenGL REQUIRED) find_package(epoxy REQUIRED) find_package(X11 REQUIRED) find_package(assimp REQUIRED) +find_package(PNG REQUIRED) set(GAME_SRC main.cpp @@ -11,10 +12,14 @@ set(GAME_SRC glclasses.cpp game_window.cpp renderer.cpp + renderer_polygon_2d/renderer_polygon_2d.cpp + renderer_polygon_3d/renderer_polygon_3d.cpp renderer_polygon_3d/polygon_model.cpp renderer_polygon_3d/particle_batch.cpp + renderer_polygon_3d/image_texture.cpp + renderer_ray_tracer/renderer_ray_tracer.cpp network/session.cpp @@ -45,6 +50,7 @@ set(GAME_SRC ${GAME_SRC} sound/dummy_sound.cpp) include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) include_directories(${OPENGL_INCLUDE_DIR}) +include_directories(${PNG_INCLUDE_DIR}) include_directories(${CMAKE_SOURCE_DIR}/libs/glm/) include_directories(${CMAKE_SOURCE_DIR}/libs/asio/asio/include/) include_directories(${assimp_INCLUDE_DIRS}) @@ -52,4 +58,5 @@ include_directories(${assimp_INCLUDE_DIRS}) add_executable(game ${GAME_SRC}) setup_target(game) -target_link_libraries(game X11 epoxy pthread ${assimp_LIBRARIES} assimp ${SOUND_LIBRARIES}) +target_link_libraries(game X11 epoxy pthread ${assimp_LIBRARIES} assimp + ${SOUND_LIBRARIES} ${PNG_LIBRARIES}) diff --git a/game/renderer_polygon_3d/image_texture.cpp b/game/renderer_polygon_3d/image_texture.cpp new file mode 100644 index 0000000..7d14d71 --- /dev/null +++ b/game/renderer_polygon_3d/image_texture.cpp @@ -0,0 +1,161 @@ +#include "image_texture.hpp" + +#include +#include + +namespace endofthejedi { + + bool ImageTexture::loadPng() + { + m_valid = false; + + //header for testing if it is a png + png_byte header[8]; + + //open file as binary + FILE *fp = fopen(m_path.c_str(), "rb"); + if (!fp) { + printf("[image_texture] warning: could not open png file to load: %s\n", m_path.c_str()); + return false; + } + + //read the header + fread(header, 1, 8, fp); + + //test if png + int is_png = !png_sig_cmp(header, 0, 8); + if (!is_png) { + puts("warning: image loader: file is not PNG!"); + fclose(fp); + return false; + } + + //create png struct + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) { + fclose(fp); + return false; + } + + //create png info struct + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL); + fclose(fp); + return false; + } + + //create png info struct + png_infop end_info = png_create_info_struct(png_ptr); + if (!end_info) { + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); + fclose(fp); + return false; + } + + //png error stuff, not sure libpng man suggests this. + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + fclose(fp); + return false; + } + + //init png reading + png_init_io(png_ptr, fp); + + //let libpng know you already read the first 8 bytes + png_set_sig_bytes(png_ptr, 8); + + // read all the info up to the image data + png_read_info(png_ptr, info_ptr); + + //variables to pass to get info + int bit_depth, color_type; + png_uint_32 twidth, theight; + + // get info about png + png_get_IHDR(png_ptr, info_ptr, &twidth, &theight, &bit_depth, &color_type, + NULL, NULL, NULL); + + //update width and height based on png info + m_width = twidth; + m_height = theight; + + int pot_width = (int) pow(2, ceilf(log2f(m_width))); + int pot_height = (int) pow(2, ceilf(log2f(m_height))); + + m_uv_scale_x = m_width / (float) pot_width; + m_uv_scale_y = m_height / (float) pot_height; + + /*puts("#########################################");*/ + /*printf("# PNG: width=%d, height=%d\n", width, height);*/ + /*printf("# powers of two: w=%d, h=%d\n", pot_width, pot_height);*/ + /*puts("#########################################");*/ + + // Update the png info struct. + png_read_update_info(png_ptr, info_ptr); + + // Row size in bytes. + int rowbytes = png_get_rowbytes(png_ptr, info_ptr); + + int pot_rowbytes = 4 * (int) pow(2, ceilf(log2f(rowbytes/4))); + /*printf("rowbytes: %d, pot_rowbytes=%d\n", rowbytes, pot_rowbytes);*/ + + // Allocate the image_data as a big block, to be given to opengl + png_byte *image_data = (png_byte *) calloc(pot_rowbytes * pot_height, sizeof(png_byte)); + if (!image_data) { + //clean up memory and close stuff + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + fclose(fp); + return false; + } + + //row_pointers is for pointing to image_data for reading the png with libpng + png_bytep *row_pointers = (png_bytep *) malloc(sizeof(png_bytep) * m_height); + if (!row_pointers) { + //clean up memory and close stuff + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + free(image_data); + fclose(fp); + return false; + } + + // set the individual row_pointers to point at the correct offsets of image_data + for (int i = 0; i < m_height; ++i) { + row_pointers[m_height - 1 - i] = image_data + i * pot_rowbytes; + } + + //read the png into image_data through row_pointers + png_read_image(png_ptr, row_pointers); + + //Now generate the OpenGL texture object + glGenTextures(1, &m_texture_id); + glBindTexture(GL_TEXTURE_2D, m_texture_id); + glTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA, + pot_width, + pot_height, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + (GLvoid*) image_data); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + // TODO: make selectable via switch! + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + + //clean up memory and close stuff + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + free(image_data); + free(row_pointers); + fclose(fp); + + m_valid = true; + + return true; + } +} + diff --git a/game/renderer_polygon_3d/image_texture.hpp b/game/renderer_polygon_3d/image_texture.hpp new file mode 100644 index 0000000..42657be --- /dev/null +++ b/game/renderer_polygon_3d/image_texture.hpp @@ -0,0 +1,65 @@ +#pragma once + +#include "glclasses.hpp" + +#include + +// based on sources of knoc/chaqu + +namespace endofthejedi { + + /** + * @brief This sprite struct stores all information needed to render an + * arbitrary PNG texture to a quad. + * + * If the loaded texture dimensions have no powers of a bit more space is + * allocated and extra padding is added. + */ + class ImageTexture { + public: + ImageTexture(const std::string &filename) : m_path(filename), m_valid(false) + { + } + + ~ImageTexture() + { + } + + /** + * @brief Try to load a PNG image from file into an opengl texture. + * + * @param path Path of PNG file + * @param texture The used texture id will be saved there. + * @param width Width of the loaded texture in pixels. + * @param height Height of the loaded texture in pixels. + * @param uv_scale_x Horizontal portion of the screen which is padded to get + * power-of-two texture. + * @param uv_scale_y Vertical portion of the screen which is padded to get + * power-of-two texture. + * + * Note: The current active texture unit should be bound (GL_TEXTURE0 etc...) + * before calling this + * + * @return true if loading suceeded, false on errors. + */ + bool loadPng(); + + bool valid() const { return m_valid; } + + glm::vec2 size() const { return glm::vec2(m_width, m_height); } + glm::vec2 uvScale() const { return glm::vec2(m_uv_scale_x, m_uv_scale_y); } + + GLuint textureId() const { return m_texture_id; } + + public: + std::string m_path; // path for the loaded texture is saved here + int m_width; // used width of the pixels of the texture + int m_height; // used height of the pixels of the texture + float m_uv_scale_x; // factor to scale uv-coordinates to get rid of non-power-of-two padding + float m_uv_scale_y; // factor to scale uv-coordinates to get rid of non-power-of-two padding + + bool m_valid; + + GLuint m_texture_id; // texture binding id + }; +} diff --git a/game/renderer_polygon_3d/renderer_polygon_3d.cpp b/game/renderer_polygon_3d/renderer_polygon_3d.cpp index e7784db..eec1f89 100644 --- a/game/renderer_polygon_3d/renderer_polygon_3d.cpp +++ b/game/renderer_polygon_3d/renderer_polygon_3d.cpp @@ -33,6 +33,16 @@ namespace endofthejedi { addModel("../data/mesh/rocket.stl", &m_missileModel); addModel("../data/mesh/planet_128.stl", &m_planetModel); addModel("../data/mesh/ship_ufo.stl", &m_shipModel); + + m_texture = new ImageTexture("../data/image/planet_mars.png"); + std::cout<<"texture loading: " << m_texture->valid() << std::endl; + if (!m_texture->valid()) { + exit(-1); + } + + glm::vec2 s = m_texture->size(); + std::cout<<"texture size is " << s.x << " X " << s.y << std::endl; + exit(0); } void RendererPolygon3d::render(const game::State *state) diff --git a/game/renderer_polygon_3d/renderer_polygon_3d.hpp b/game/renderer_polygon_3d/renderer_polygon_3d.hpp index 32a067f..78bfcd4 100644 --- a/game/renderer_polygon_3d/renderer_polygon_3d.hpp +++ b/game/renderer_polygon_3d/renderer_polygon_3d.hpp @@ -23,6 +23,7 @@ #include "particle_batch.hpp" #include "polygon_model.hpp" +#include "image_texture.hpp" namespace endofthejedi { @@ -87,5 +88,7 @@ namespace endofthejedi { // TODO: put representation specialized for rendering in here std::list m_missiles; std::list m_ships; + + ImageTexture *m_texture; }; } diff --git a/game/sound/dummy_sound.cpp b/game/sound/dummy_sound.cpp index f7e7c68..2a0827d 100644 --- a/game/sound/dummy_sound.cpp +++ b/game/sound/dummy_sound.cpp @@ -121,6 +121,7 @@ namespace sound { int numActiveSounds(void) { + return 0; } void deleteSound(SoundHandle *handle)