Преглед на файлове

+ Support animated images in the background
~ ITextures can now also return sub-textures width and height
+ added proper code to handle animated images to properly play at normal speed

this should actually fix #79 for good

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

Alexis Maiquez преди 4 години
родител
ревизия
cad78c58f9

+ 22 - 11
src/WallpaperEngine/Assets/CTexture.cpp

@@ -191,7 +191,7 @@ CTexture::~CTexture ()
     delete this->getHeader ();
 }
 
-const GLuint CTexture::getTextureID (int imageIndex) const
+const GLuint CTexture::getTextureID (uint32_t imageIndex) const
 {
     // ensure we do not go out of bounds
     if (imageIndex > this->m_header->imageCount)
@@ -200,14 +200,20 @@ const GLuint CTexture::getTextureID (int imageIndex) const
     return this->m_textureID [imageIndex];
 }
 
-const uint32_t CTexture::getTextureWidth () const
+const uint32_t CTexture::getTextureWidth (uint32_t imageIndex) const
 {
-    return this->getHeader ()->textureWidth;
+    if (imageIndex > this->m_header->imageCount)
+        return this->getHeader ()->textureWidth;
+
+    return (*this->m_header->images [imageIndex].begin ())->width;
 }
 
-const uint32_t CTexture::getTextureHeight () const
+const uint32_t CTexture::getTextureHeight (uint32_t imageIndex) const
 {
-    return this->getHeader ()->textureHeight;
+    if (imageIndex > this->m_header->imageCount)
+        return this->getHeader ()->textureHeight;
+
+    return (*this->m_header->images [imageIndex].begin ())->height;
 }
 
 const uint32_t CTexture::getRealWidth () const
@@ -235,6 +241,11 @@ const glm::vec4* CTexture::getResolution () const
     return &this->m_resolution;
 }
 
+const std::vector<ITexture::TextureFrame*>& CTexture::getFrames () const
+{
+    return this->getHeader ()->frames;
+}
+
 const bool CTexture::isAnimated () const
 {
     return this->getHeader ()->isAnimated ();
@@ -408,8 +419,8 @@ CTexture::TextureHeader* CTexture::parseHeader (char* fileData)
         {
             TextureFrame* first = *header->frames.begin ();
 
-            header->gifWidth = first->width;
-            header->gifHeight = first->height;
+            header->gifWidth = first->width1;
+            header->gifHeight = first->height1;
         }
     }
 
@@ -433,10 +444,10 @@ CTexture::TextureFrame* CTexture::parseAnimation (TextureHeader* header, char**
     frame->frametime = *fPointer ++;
     frame->x = *fPointer ++;
     frame->y = *fPointer ++;
-    frame->width = *fPointer ++;
-    frame->unk0 = *fPointer ++;
-    frame->unk1 = *fPointer ++;
-    frame->height = *fPointer ++;
+    frame->width1 = *fPointer ++;
+    frame->width2 = *fPointer ++;
+    frame->height2 = *fPointer ++;
+    frame->height1 = *fPointer ++;
 
     // get back the pointer into fileData so it can be reused later
     *originalFileData = reinterpret_cast <char*> (fPointer);

+ 4 - 25
src/WallpaperEngine/Assets/CTexture.h

@@ -21,13 +21,14 @@ namespace WallpaperEngine::Assets
         CTexture (void* fileData);
         ~CTexture ();
 
-        const GLuint getTextureID (int imageIndex) const override;
-        const uint32_t getTextureWidth () const override;
-        const uint32_t getTextureHeight () const override;
+        const GLuint getTextureID (uint32_t imageIndex = 0) const override;
+        const uint32_t getTextureWidth (uint32_t imageIndex = 0) const override;
+        const uint32_t getTextureHeight (uint32_t imageIndex = 0) const override;
         const uint32_t getRealWidth () const override;
         const uint32_t getRealHeight () const override;
         const TextureFormat getFormat () const override;
         const glm::vec4* getResolution () const override;
+        const std::vector<TextureFrame*>& getFrames () const override;
         const bool isAnimated () const override;
 
     private:
@@ -74,28 +75,6 @@ namespace WallpaperEngine::Assets
             void decompressData ();
         };
 
-        class TextureFrame
-        {
-        public:
-            TextureFrame();
-            ~TextureFrame();
-
-            /** The image index of this frame */
-            uint32_t frameNumber;
-            /** The amount of time this frame spends being displayed */
-            float frametime;
-            /** The x position of the frame in the texture */
-            float x;
-            /** The y position of the frame in the texture */
-            float y;
-            /** The width of the frame in the texture */
-            float width;
-            float unk0;
-            float unk1;
-            /** The height of the frame in the texture */
-            float height;
-        };
-
         /**
          * Configures how the texture will be handled by the background
          */

+ 27 - 3
src/WallpaperEngine/Assets/ITexture.h

@@ -2,12 +2,35 @@
 
 #include <GL/glew.h>
 #include <glm/vec4.hpp>
+#include <vector>
 
 namespace WallpaperEngine::Assets
 {
     class ITexture
     {
     public:
+        class TextureFrame
+        {
+        public:
+            TextureFrame();
+            ~TextureFrame();
+
+            /** The image index of this frame */
+            uint32_t frameNumber;
+            /** The amount of time this frame spends being displayed */
+            float frametime;
+            /** The x position of the frame in the texture */
+            float x;
+            /** The y position of the frame in the texture */
+            float y;
+            /** The width of the frame in the texture */
+            float width1;
+            float width2;
+            float height2;
+            /** The height of the frame in the texture */
+            float height1;
+        };
+
         enum TextureFormat : uint32_t
         {
             ARGB8888 = 0,
@@ -18,12 +41,13 @@ namespace WallpaperEngine::Assets
             R8 = 9,
         };
 
-        virtual const GLuint getTextureID (int imageIndex) const = 0;
-        virtual const uint32_t getTextureWidth () const = 0;
-        virtual const uint32_t getTextureHeight () const = 0;
+        virtual const GLuint getTextureID (uint32_t imageIndex = 0) const = 0;
+        virtual const uint32_t getTextureWidth (uint32_t imageIndex = 0) const = 0;
+        virtual const uint32_t getTextureHeight (uint32_t imageIndex = 0) const = 0;
         virtual const uint32_t getRealWidth () const = 0;
         virtual const uint32_t getRealHeight () const = 0;
         virtual const TextureFormat getFormat () const = 0;
+        virtual const std::vector<TextureFrame*>& getFrames () const = 0;
         virtual const glm::vec4* getResolution () const = 0;
         virtual const bool isAnimated () const = 0;
     };

+ 8 - 3
src/WallpaperEngine/Render/CFBO.cpp

@@ -69,16 +69,16 @@ GLuint CFBO::getDepthbuffer () const
     return this->m_depthbuffer;
 }
 
-const GLuint CFBO::getTextureID (int imageIndex) const
+const GLuint CFBO::getTextureID (uint32_t imageIndex) const
 {
     return this->m_texture;
 }
 
-const uint32_t CFBO::getTextureWidth () const
+const uint32_t CFBO::getTextureWidth (uint32_t imageIndex) const
 {
     return this->m_resolution.x;
 }
-const uint32_t CFBO::getTextureHeight () const
+const uint32_t CFBO::getTextureHeight (uint32_t imageIndex) const
 {
     return this->m_resolution.y;
 }
@@ -93,6 +93,11 @@ const uint32_t CFBO::getRealHeight () const
     return this->m_resolution.w;
 }
 
+const std::vector<ITexture::TextureFrame*>& CFBO::getFrames () const
+{
+    return std::vector<TextureFrame*> ();
+}
+
 const glm::vec4* CFBO::getResolution () const
 {
     return &this->m_resolution;

+ 4 - 3
src/WallpaperEngine/Render/CFBO.h

@@ -18,11 +18,12 @@ namespace WallpaperEngine::Render
         const ITexture::TextureFormat getFormat () const override;
         GLuint getFramebuffer () const;
         GLuint getDepthbuffer () const;
-        const GLuint getTextureID (int imageIndex) const override;
-        const uint32_t getTextureWidth () const override;
-        const uint32_t getTextureHeight () const override;
+        const GLuint getTextureID (uint32_t imageIndex = 0) const override;
+        const uint32_t getTextureWidth (uint32_t imageIndex = 0) const override;
+        const uint32_t getTextureHeight (uint32_t imageIndex = 0) const override;
         const uint32_t getRealWidth () const override;
         const uint32_t getRealHeight () const override;
+        const std::vector<TextureFrame*>& getFrames () const override;
         const glm::vec4* getResolution () const override;
         const bool isAnimated () const override;
 

+ 65 - 20
src/WallpaperEngine/Render/Objects/CImage.cpp

@@ -69,8 +69,8 @@ CImage::CImage (CScene* scene, Core::Objects::CImage* image) :
     nameA << "_rt_imageLayerComposite_" << this->getImage ()->getId () << "_a";
     nameB << "_rt_imageLayerComposite_" << this->getImage ()->getId () << "_b";
 
-    this->m_currentMainFBO = this->m_mainFBO = scene->createFBO (nameA.str (), ITexture::TextureFormat::ARGB8888, 1, this->m_texture->getRealWidth (), this->m_texture->getRealHeight (), this->m_texture->getRealWidth (), this->m_texture->getRealHeight ());
-    this->m_currentSubFBO = this->m_subFBO = scene->createFBO (nameB.str (), ITexture::TextureFormat::ARGB8888, 1, this->m_texture->getRealWidth (), this->m_texture->getRealHeight (), this->m_texture->getRealWidth (), this->m_texture->getRealHeight ());
+    this->m_currentMainFBO = this->m_mainFBO = scene->createFBO (nameA.str (), ITexture::TextureFormat::ARGB8888, 1, this->m_texture->getTextureWidth (), this->m_texture->getTextureHeight (), this->m_texture->getTextureWidth (), this->m_texture->getTextureHeight ());
+    this->m_currentSubFBO = this->m_subFBO = scene->createFBO (nameB.str (), ITexture::TextureFormat::ARGB8888, 1, this->m_texture->getTextureWidth (), this->m_texture->getTextureHeight (), this->m_texture->getTextureWidth (), this->m_texture->getTextureHeight ());
 
     GLfloat realWidth = this->m_texture->getRealWidth () / 2;
     GLfloat realHeight = this->m_texture->getRealHeight () / 2;
@@ -106,8 +106,14 @@ CImage::CImage (CScene* scene, Core::Objects::CImage* image) :
     float width = 1.0f;
     float height = 1.0f;
 
+    if (this->getTexture ()->isAnimated () == true)
+    {
+        // animated images use different coordinates as they're essentially a texture atlast
+        width = static_cast<float> (this->getTexture ()->getRealWidth ()) / static_cast<float> (this->getTexture ()->getTextureWidth ());
+        height = static_cast<float> (this->getTexture ()->getRealHeight ()) / static_cast<float> (this->getTexture ()->getTextureHeight ());
+    }
     // calculate the correct texCoord limits for the texture based on the texture screen size and real size
-    if (this->getTexture () != nullptr &&
+    else if (this->getTexture () != nullptr &&
             (this->getTexture ()->getTextureWidth () != this->getTexture ()->getRealWidth () ||
              this->getTexture ()->getTextureHeight () != this->getTexture ()->getRealHeight ())
         )
@@ -122,12 +128,24 @@ CImage::CImage (CScene* scene, Core::Objects::CImage* image) :
         height = size.y * scale.y / y;
     }
 
+    float x = 0.0f;
+    float y = 0.0f;
+
+    if (this->getTexture ()->isAnimated () == true)
+    {
+        // animations should be copied completely
+        x = 0.0f;
+        y = 0.0f;
+        width = 1.0f;
+        height = 1.0f;
+    }
+
     GLfloat texcoordCopy [] = {
-        0.0f, 0.0f,
-        width, 0.0f,
-        0.0f, height,
-        0.0f, height,
-        width, 0.0f,
+        x, y,
+        width, y,
+        x, height,
+        x, height,
+        width, y,
         width, height
     };
 
@@ -177,18 +195,30 @@ void CImage::setup ()
         new CEffect (this, new Core::Objects::CEffect ("", "", "", "", this->m_image)),
         this->m_image->getMaterial ()
     );
+
     // generate the main material used to render the image
     this->m_material = new Effects::CMaterial (
         new CEffect (this, new Core::Objects::CEffect ("", "", "", "", this->m_image)),
         this->m_image->getMaterial ()
     );
 
-    // generate the effects used by this material
-    auto cur = this->getImage ()->getEffects ().begin ();
-    auto end = this->getImage ()->getEffects ().end ();
+    {
+        // generate the effects used by this material
+        auto cur = this->getImage ()->getEffects ().begin ();
+        auto end = this->getImage ()->getEffects ().end ();
+
+        for (; cur != end; cur ++)
+            this->m_effects.emplace_back (new CEffect (this, *cur));
+    }
+
+    // calculate full animation time (if any)
+    this->m_animationTime = 0.0f;
+
+    auto cur = this->getTexture ()->getFrames ().begin ();
+    auto end = this->getTexture ()->getFrames ().end ();
 
     for (; cur != end; cur ++)
-        this->m_effects.emplace_back (new CEffect (this, *cur));
+        this->m_animationTime += (*cur)->frametime;
 }
 
 void CImage::pinpongFramebuffer (CFBO** drawTo, ITexture** asInput)
@@ -209,19 +239,29 @@ void CImage::pinpongFramebuffer (CFBO** drawTo, ITexture** asInput)
 
 void CImage::simpleRender ()
 {
-    // first render to the composite layer
-    auto cur = this->m_copyMaterial->getPasses ().begin ();
-    auto end = this->m_copyMaterial->getPasses ().end ();
+    ITexture* input = this->m_mainFBO;
 
-    for (; cur != end; cur ++)
-        (*cur)->render (this->m_mainFBO, this->getTexture (), *this->getCopySpacePosition (), *this->getTexCoordCopy (), this->m_modelViewProjectionPass);
+    // FIXME: THIS IS A QUICK HACK FOR ANIMATED IMAGES, IF ANY OF THOSE HAVE ANY EFFECT ON THEM THIS WILL LIKELY BREAK
+    if (this->getTexture ()->isAnimated () == true)
+    {
+        input = this->getTexture ();
+    }
+    else
+    {
+        // first render to the composite layer
+        auto cur = this->m_copyMaterial->getPasses ().begin ();
+        auto end = this->m_copyMaterial->getPasses ().end ();
+
+        for (; cur != end; cur ++)
+            (*cur)->render (this->m_mainFBO, this->getTexture (), *this->getCopySpacePosition (), *this->getTexCoordCopy (), this->m_modelViewProjectionPass);
+    }
 
     // a simple material renders directly to the screen
-    cur = this->m_material->getPasses ().begin ();
-    end = this->m_material->getPasses ().end ();
+    auto cur = this->m_material->getPasses ().begin ();
+    auto end = this->m_material->getPasses ().end ();
 
     for (; cur != end; cur ++)
-        (*cur)->render (this->getScene ()->getFBO (), this->m_mainFBO, *this->getSceneSpacePosition (), *this->getTexCoordPass (), this->m_modelViewProjectionScreen);
+        (*cur)->render (this->getScene ()->getFBO (), input, *this->getSceneSpacePosition (), *this->getTexCoordPass (), this->m_modelViewProjectionScreen);
 }
 
 void CImage::complexRender ()
@@ -319,6 +359,11 @@ ITexture* CImage::getTexture () const
     return this->m_texture;
 }
 
+const double CImage::getAnimationTime () const
+{
+    return this->m_animationTime;
+}
+
 const Core::Objects::CImage* CImage::getImage () const
 {
     return this->m_image;

+ 3 - 0
src/WallpaperEngine/Render/Objects/CImage.h

@@ -45,6 +45,7 @@ namespace WallpaperEngine::Render::Objects
         const GLuint* getTexCoordCopy () const;
         const GLuint* getTexCoordPass () const;
         ITexture* getTexture () const;
+        const double getAnimationTime () const;
 
         /**
          * Performs a ping-pong on the available framebuffers to be able to continue rendering things to them
@@ -80,5 +81,7 @@ namespace WallpaperEngine::Render::Objects
         std::vector<CEffect*> m_effects;
         Effects::CMaterial* m_material;
         Effects::CMaterial* m_copyMaterial;
+
+        double m_animationTime;
     };
 }

+ 40 - 3
src/WallpaperEngine/Render/Objects/Effects/CPass.cpp

@@ -138,8 +138,42 @@ void CPass::render (CFBO* drawTo, ITexture* input, GLuint position, GLuint texco
 
     ITexture* texture = this->resolveTexture (input, 0, input);
 
+    uint32_t currentTexture = 0;
+    glm::vec2 translation = {0.0f, 0.0f};
+    glm::vec4 rotation = {0.0f, 0.0f, 0.0f, 0.0f};
+
+    if (texture->isAnimated () == true)
+    {
+        // calculate current texture and frame
+        double currentRenderTime = fmod (static_cast <double> (g_Time), this->m_material->getImage ()->getAnimationTime ());
+
+        // find the right frame now
+        auto frameCur = texture->getFrames ().begin ();
+        auto frameEnd = texture->getFrames ().end ();
+
+        for (; frameCur != frameEnd; frameCur ++)
+        {
+            currentRenderTime -= (*frameCur)->frametime;
+
+            if (currentRenderTime <= 0.0f)
+            {
+                // frame found, store coordinates and done
+                currentTexture = (*frameCur)->frameNumber;
+
+                translation.x = (*frameCur)->x / texture->getTextureWidth (currentTexture);
+                translation.y = (*frameCur)->y / texture->getTextureHeight (currentTexture);
+
+                rotation.x = (*frameCur)->width1 / static_cast<float> (texture->getTextureWidth (currentTexture));
+                rotation.y = (*frameCur)->width2 / static_cast<float> (texture->getTextureWidth(currentTexture));
+                rotation.z = (*frameCur)->height2 / static_cast<float> (texture->getTextureHeight (currentTexture));
+                rotation.w = (*frameCur)->height1 / static_cast<float> (texture->getTextureHeight (currentTexture));
+                break;
+            }
+        }
+    }
+
     glActiveTexture (GL_TEXTURE0);
-    glBindTexture (GL_TEXTURE_2D, texture->getTextureID (0));
+    glBindTexture (GL_TEXTURE_2D, texture->getTextureID (currentTexture));
     int lastTextureIndex = 0;
 
     // first bind the textures to their sampler place
@@ -233,11 +267,14 @@ void CPass::render (CFBO* drawTo, ITexture* input, GLuint position, GLuint texco
 
     if (this->g_Texture0Rotation != -1)
     {
-        glUniform4f (this->g_Texture0Rotation, 1.0f, 0.0f, 1.0f, 0.0f);
+        // used in animations when one of the frames is vertical instead of horizontal
+        // rotation with translation = origin and end of the image to display
+        glUniform4f (this->g_Texture0Rotation, rotation.x, rotation.y, rotation.z, rotation.w);
     }
     if (this->g_Texture0Translation != -1)
     {
-        glUniform2f (this->g_Texture0Translation, 0.0f, 0.0f);
+        // this actually picks the origin point of the image from the atlast
+        glUniform2f (this->g_Texture0Translation, translation.x, translation.y);
     }
     {
         auto cur = this->m_attribs.begin ();