Jelajahi Sumber

+ Added LZ4 lib to the compilation process
+ Basic draft for the texture custom loader, only ARGB (partially) supported for now

Signed-off-by: Alexis Maiquez Murcia <almamu@almamu.com>

Alexis Maiquez Murcia 7 tahun lalu
induk
melakukan
82682ecf02

+ 4 - 3
CMakeLists.txt

@@ -11,9 +11,10 @@ find_package(OpenGL REQUIRED)
 find_package(GLUT REQUIRED)
 find_package(ZLIB REQUIRED)
 find_package(Irrlicht REQUIRED)
+find_package(LZ4 REQUIRED)
 
-include_directories(${X11_INCLUDE_DIR} ${IRRLICHT_INCLUDE_DIR} .)
+include_directories(${X11_INCLUDE_DIR} ${IRRLICHT_INCLUDE_DIR} ${LZ4_INCLUDE_DIR} .)
 
-add_executable(wallengine main.cpp wallpaperengine/shaders/compiler.h wallpaperengine/shaders/compiler.cpp wallpaperengine/project.cpp wallpaperengine/project.h wallpaperengine/scene.cpp wallpaperengine/scene.h wallpaperengine/object.cpp wallpaperengine/object.h wallpaperengine/camera.cpp wallpaperengine/camera.h wallpaperengine/core.cpp wallpaperengine/core.h wallpaperengine/image.cpp wallpaperengine/image.h wallpaperengine/object3d.cpp wallpaperengine/object3d.h wallpaperengine/effect.cpp wallpaperengine/effect.h wallpaperengine/fs/fileResolver.cpp wallpaperengine/fs/fileResolver.h wallpaperengine/irrlicht.cpp wallpaperengine/irrlicht.h wallpaperengine/config.cpp wallpaperengine/config.h wallpaperengine/video/renderer.cpp wallpaperengine/video/renderer.h wallpaperengine/video/node.cpp wallpaperengine/video/node.h wallpaperengine/video/material.cpp wallpaperengine/video/material.h wallpaperengine/texture.cpp wallpaperengine/texture.h)
+add_executable(wallengine main.cpp wallpaperengine/shaders/compiler.h wallpaperengine/shaders/compiler.cpp wallpaperengine/project.cpp wallpaperengine/project.h wallpaperengine/scene.cpp wallpaperengine/scene.h wallpaperengine/object.cpp wallpaperengine/object.h wallpaperengine/camera.cpp wallpaperengine/camera.h wallpaperengine/core.cpp wallpaperengine/core.h wallpaperengine/image.cpp wallpaperengine/image.h wallpaperengine/object3d.cpp wallpaperengine/object3d.h wallpaperengine/effect.cpp wallpaperengine/effect.h wallpaperengine/fs/fileResolver.cpp wallpaperengine/fs/fileResolver.h wallpaperengine/irrlicht.cpp wallpaperengine/irrlicht.h wallpaperengine/config.cpp wallpaperengine/config.h wallpaperengine/video/renderer.cpp wallpaperengine/video/renderer.h wallpaperengine/video/node.cpp wallpaperengine/video/node.h wallpaperengine/video/material.cpp wallpaperengine/video/material.h wallpaperengine/texture.cpp wallpaperengine/texture.h wallpaperengine/irr/CImageLoaderTEX.h wallpaperengine/irr/CImageLoaderTEX.cpp)
 
-target_link_libraries(wallengine ${X11_LIBRARIES} ${X11_Xxf86vm_LIB} ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} ${ZLIB_LIBRARIES} ${IRRLICHT_LIBRARY})
+target_link_libraries(wallengine ${X11_LIBRARIES} ${X11_Xxf86vm_LIB} ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} ${ZLIB_LIBRARIES} ${IRRLICHT_LIBRARY} ${LZ4_LIBRARY})

+ 41 - 0
CMakeModules/FindLZ4.cmake

@@ -0,0 +1,41 @@
+# Finds liblz4.
+#
+# This module defines:
+# LZ4_FOUND
+# LZ4_INCLUDE_DIR
+# LZ4_LIBRARY
+#
+# From https://github.com/facebook/hhvm/blob/master/CMake/FindLZ4.cmake
+#
+
+find_path(LZ4_INCLUDE_DIR NAMES lz4.h)
+find_library(LZ4_LIBRARY NAMES lz4)
+
+# We require LZ4_compress_default() which was added in v1.7.0
+if (LZ4_LIBRARY)
+  include(CheckCSourceRuns)
+  set(CMAKE_REQUIRED_INCLUDES ${LZ4_INCLUDE_DIR})
+  set(CMAKE_REQUIRED_LIBRARIES ${LZ4_LIBRARY})
+  check_c_source_runs("
+#include <lz4.h>
+int main() {
+  int good = (LZ4_VERSION_MAJOR > 1) ||
+    ((LZ4_VERSION_MAJOR == 1) && (LZ4_VERSION_MINOR >= 7));
+return !good;
+}" LZ4_GOOD_VERSION)
+  set(CMAKE_REQUIRED_INCLUDES)
+  set(CMAKE_REQUIRED_LIBRARIES)
+endif()
+
+include(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(
+    LZ4 DEFAULT_MSG
+    LZ4_LIBRARY LZ4_INCLUDE_DIR LZ4_GOOD_VERSION)
+
+if (NOT LZ4_FOUND)
+  message(STATUS "Using third-party bundled LZ4")
+else()
+  message(STATUS "Found LZ4: ${LZ4_LIBRARY}")
+endif (NOT LZ4_FOUND)
+
+mark_as_advanced(LZ4_INCLUDE_DIR LZ4_LIBRARY)

+ 5 - 0
main.cpp

@@ -8,6 +8,7 @@
 #include "wallpaperengine/shaders/compiler.h"
 #include "wallpaperengine/project.h"
 #include "wallpaperengine/irrlicht.h"
+#include "wallpaperengine/irr/CImageLoaderTEX.h"
 
 int WinID = 0;
 irr::SIrrlichtCreationParameters _irr_params;
@@ -125,6 +126,10 @@ int main (int argc, char* argv[])
 
     // set our working directory
     wp::fs::resolver.changeWorkingDirectory (_wp_engine_folder);
+
+    // register custom loader
+    wp::irrlicht::driver->addExternalImageLoader (new irr::video::CImageLoaderTex ());
+
     wp::project* wp_project = new wp::project ();
 
     if (wp_project->getScene ()->isOrthogonal() == true)

+ 3 - 11
wallpaperengine/image.cpp

@@ -65,19 +65,11 @@ namespace wp
                             for (; texturesCur != texturesEnd; texturesCur ++)
                             {
                                 // TODO: SUPPORT PROPER WALLPAPERENGINE FORMATS
-                                irr::io::path texturePath = this->m_resolver.resolveOnWorkingDirectory ((*texturesCur));
+                                std::string name = (*texturesCur);
+                                name += ".tex";
+                                irr::io::path texturePath = this->m_resolver.resolveOnWorkingDirectory (name);
                                 std::string basename = (*texturesCur);
 
-                                // TRY NORMAL EXTENSIONS FOR NOW...
-                                if (texturePath == "")
-                                {
-                                    texturePath = this->m_resolver.resolveOnWorkingDirectory (basename + ".png");
-                                }
-                                if (texturePath == "")
-                                {
-                                    texturePath = this->m_resolver.resolveOnWorkingDirectory (basename + ".jpg");
-                                }
-
                                 this->m_textures.push_back (new wp::texture (texturePath));
                             }
                         }

+ 178 - 0
wallpaperengine/irr/CImageLoaderTEX.cpp

@@ -0,0 +1,178 @@
+// Copyright (C) 2002-2012 Nikolaus Gebhardt
+// This file is part of the "Irrlicht Engine".
+// For conditions of distribution and use, see copyright notice in irrlicht.h
+
+#include "CImageLoaderTEX.h"
+
+#include <irrlicht/irrlicht.h>
+#include <lz4.h>
+#include <wallpaperengine/irrlicht.h>
+#include <string>
+
+namespace irr {
+    namespace video {
+
+        //! returns true if the file maybe is able to be loaded by this class
+        //! based on the file extension (e.g. ".tga")
+        bool CImageLoaderTex::isALoadableFileExtension (const io::path &filename) const
+        {
+            return core::hasFileExtension (filename, "tex");
+        }
+
+
+        //! returns true if the file maybe is able to be loaded by this class
+        bool CImageLoaderTex::isALoadableFileFormat (io::IReadFile *file) const
+        {
+            return false;
+        }
+
+
+        // load in the image data
+        IImage *CImageLoaderTex::loadImage (io::IReadFile *input) const
+        {
+            if (!input)
+                return 0;
+
+            video::IImage *image = 0;
+
+            char buffer [1024];
+
+            if (input->read (buffer, 9) != 9)
+            {
+                wp::irrlicht::device->getLogger ()->log ("LOAD TEX: cannot read header\n", input->getFileName ().c_str (), irr::ELL_ERROR);
+                return 0;
+            }
+
+            if (memcmp (buffer, "TEXV0005", 9) != 0)
+            {
+                wp::irrlicht::device->getLogger ()->log ("LOAD TEX: not really a tex\n", input->getFileName ().c_str (), irr::ELL_ERROR);
+                return 0;
+            }
+
+            if (input->read (buffer, 9) != 9)
+            {
+                wp::irrlicht::device->getLogger ()->log ("LOAD TEX: cannot read second header\n", input->getFileName ().c_str (), irr::ELL_ERROR);
+                return 0;
+            }
+
+            if (memcmp (buffer, "TEXI0001", 9) != 0)
+            {
+                wp::irrlicht::device->getLogger ()->log ("LOAD TEX: not really a tex\n", input->getFileName ().c_str (), irr::ELL_ERROR);
+                return 0;
+            }
+
+            u32 width;
+            u32 height;
+            u32 texture_width;
+            u32 texture_height;
+            u32 format;
+
+            input->read (&format, 4);
+            input->seek (4, true); // ignore bytes
+            input->read (&texture_width, 4);
+            input->read (&texture_height, 4);
+            input->read (&width, 4);
+            input->read (&height, 4);
+            input->seek (4, true); // ignore bytes
+            input->read (buffer, 9);
+
+            if (memcmp (buffer, "TEXB0003", 9) == 0)
+            {
+                wp::irrlicht::device->getLogger ()->log ("LOAD TEX: TEXB0003 container not supported yet\n", input->getFileName ().c_str (), irr::ELL_ERROR);
+                return 0;
+            }
+            else if (memcmp (buffer, "TEXB0002", 9) == 0)
+            {
+                input->seek (4, true);
+            }
+            else
+            {
+                wp::irrlicht::device->getLogger ()->log ("LOAD TEX: Unknown container type\n", input->getFileName ().c_str (), irr::ELL_ERROR);
+                return 0;
+            }
+
+            if (format != TextureFormat::ARGB8888)
+            {
+                wp::irrlicht::device->getLogger ()->log ("LOAD TEX: Only ARGB8888 supported\n", input->getFileName ().c_str (), irr::ELL_ERROR);
+                return 0;
+            }
+
+            u32 mipmap_count = 0;
+
+            input->read (&mipmap_count, 4);
+
+            u32 mipmap_width = 0;
+            u32 mipmap_height = 0;
+            u32 mipmap_compression = 0;
+            u32 mipmap_uncompressed_size = 0;
+            u32 mipmap_compressed_size = 0;
+
+            input->read (&mipmap_width, 4);
+            input->read (&mipmap_height, 4);
+            input->read (&mipmap_compression, 4);
+            input->read (&mipmap_uncompressed_size, 4);
+            input->read (&mipmap_compressed_size, 4);
+
+            char *decompressedBuffer = new char [mipmap_uncompressed_size];
+
+            if (mipmap_compression == 1)
+            {
+                char *compressedBuffer = new char [mipmap_compressed_size];
+
+                input->read (compressedBuffer, mipmap_compressed_size);
+
+                int result = LZ4_decompress_safe (compressedBuffer, decompressedBuffer, mipmap_compressed_size, mipmap_uncompressed_size);
+
+                if (!result)
+                {
+                    delete [] decompressedBuffer;
+                    delete [] compressedBuffer;
+                    wp::irrlicht::device->getLogger ()->log ("LOAD TEX: cannot decompress texture data\n", input->getFileName ().c_str (), irr::ELL_ERROR);
+                    return 0;
+                }
+
+                delete [] compressedBuffer;
+            }
+            else
+            {
+                input->read (decompressedBuffer, mipmap_uncompressed_size);
+            }
+
+            image = wp::irrlicht::driver->createImage (ECF_A8R8G8B8, irr::core::dimension2d<u32> (texture_width, texture_height));
+
+            if (!image)
+            {
+                delete [] decompressedBuffer;
+                delete image;
+                wp::irrlicht::device->getLogger ()->log ("LOAD TEX: cannot create destination image\n", input->getFileName ().c_str (), irr::ELL_ERROR);
+                return 0;
+            }
+
+            u32 bytesPerPixel = image->getBytesPerPixel ();
+            char *imagedata = (char *) image->lock ();
+
+            for (u32 y = 0; y < height; y++)
+            {
+                u32 baseDestination = y * image->getPitch ();
+                u32 baseOrigin = y * (texture_width * 4);
+
+                for (u32 x = 0; x < width; x++)
+                {
+                    imagedata[baseDestination + (x * bytesPerPixel) + 0] = decompressedBuffer[baseOrigin + ((texture_width - x) * 4) + 0];
+                    imagedata[baseDestination + (x * bytesPerPixel) + 1] = decompressedBuffer[baseOrigin + ((texture_width - x) * 4) + 1];
+                    imagedata[baseDestination + (x * bytesPerPixel) + 2] = decompressedBuffer[baseOrigin + ((texture_width - x) * 4) + 2];
+                    imagedata[baseDestination + (x * bytesPerPixel) + 3] = decompressedBuffer[baseOrigin + ((texture_width - x) * 4) + 3];
+                }
+            }
+
+            image->unlock ();
+
+            delete [] decompressedBuffer;
+
+            return image;
+        }
+
+
+    }// end namespace irr
+}//end namespace video
+

+ 51 - 0
wallpaperengine/irr/CImageLoaderTEX.h

@@ -0,0 +1,51 @@
+// Copyright (C) 2002-2012 Nikolaus Gebhardt
+// This file is part of the "Irrlicht Engine".
+// For conditions of distribution and use, see copyright notice in irrlicht.h
+
+// this file was created by rt (www.tomkorp.com), based on ttk's png-reader
+// i wanted to be able to read in PNG images with irrlicht :)
+// why?  lossless compression with 8-bit alpha channel!
+
+#ifndef __C_IMAGE_LOADER_TEX_H_INCLUDED__
+#define __C_IMAGE_LOADER_PNG_H_INCLUDED__
+
+#include <irrlicht/irrlicht.h>
+
+namespace irr
+{
+namespace video
+{
+
+//!  Surface Loader for PNG files
+class CImageLoaderTex : public IImageLoader
+{
+public:
+
+	//! returns true if the file maybe is able to be loaded by this class
+	//! based on the file extension (e.g. ".png")
+	virtual bool isALoadableFileExtension(const io::path& filename) const;
+
+	//! returns true if the file maybe is able to be loaded by this class
+	virtual bool isALoadableFileFormat(io::IReadFile* file) const;
+
+	//! creates a surface from the file
+	virtual IImage* loadImage(io::IReadFile* input) const;
+
+private:
+    enum TextureFormat
+    {
+        ARGB8888,
+        RA88,
+        A8,
+        DXT5,
+        DXT3,
+        DXT1
+    };
+};
+
+
+} // end namespace video
+} // end namespace irr
+
+#endif
+

+ 2 - 1
wallpaperengine/project.cpp

@@ -1,6 +1,7 @@
 #include <irrlicht/irrlicht.h>
 #include <iostream>
 #include <fstream>
+#include <stdexcept>
 
 #include "fs/fileResolver.h"
 
@@ -41,7 +42,7 @@ namespace wp
 
         if (this->m_type != "scene")
         {
-            throw "Only scene wallpapers supported for now";
+            throw std::runtime_error ("Only scene wallpapers are supported");
         }
     }
 

+ 3 - 2
wallpaperengine/texture.cpp

@@ -1,15 +1,16 @@
 #include <wallpaperengine/texture.h>
+#include <stdexcept>
+#include <lz4.h>
+
 #include "irrlicht.h"
 
 namespace wp
 {
-
     texture::texture (irr::io::path file)
     {
         this->m_texture = wp::irrlicht::driver->getTexture (file);
     }
 
-
     irr::video::ITexture* texture::getIrrTexture ()
     {
         return this->m_texture;