├── Twitch ├── Assets │ └── Art │ │ ├── pipe.png │ │ ├── Biplane.png │ │ ├── gameover.png │ │ └── spacetostart.png ├── Engine │ ├── Graphics │ │ ├── SOIL │ │ │ ├── lib │ │ │ │ ├── SOIL.lib │ │ │ │ └── libSOIL.a │ │ │ └── src │ │ │ │ ├── stbi_DDS_aug.h │ │ │ │ ├── image_helper.h │ │ │ │ ├── image_DXT.h │ │ │ │ ├── image_helper.c │ │ │ │ ├── test_SOIL.cpp │ │ │ │ ├── SOIL.h │ │ │ │ ├── stbi_DDS_aug_c.h │ │ │ │ ├── stb_image_aug.h │ │ │ │ └── image_DXT.c │ │ ├── Texture.h │ │ ├── Sprite.h │ │ ├── Texture.cpp │ │ └── Sprite.cpp │ ├── IO │ │ ├── Keyboard.h │ │ ├── Mouse.h │ │ ├── Keyboard.cpp │ │ └── Mouse.cpp │ ├── Math │ │ ├── Math.h │ │ ├── Rect.h │ │ ├── Vector3.h │ │ ├── Math.cpp │ │ ├── Rect.cpp │ │ └── Vector3.cpp │ ├── Engine.h │ ├── Physics │ │ ├── Rigidbody.h │ │ └── Rigidbody.cpp │ └── Engine.cpp ├── packages.config ├── Twitch.cpp ├── FlappyTwitch │ ├── Flapper.h │ ├── GameManager.h │ ├── PipeManager.h │ ├── Pipe.h │ ├── Flapper.cpp │ ├── GameManager.cpp │ ├── Pipe.cpp │ └── PipeManager.cpp ├── Twitch.vcxproj.filters └── Twitch.vcxproj ├── Twitch.sln └── .gitignore /Twitch/Assets/Art/pipe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrematic/LetsMakeAGame/HEAD/Twitch/Assets/Art/pipe.png -------------------------------------------------------------------------------- /Twitch/Assets/Art/Biplane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrematic/LetsMakeAGame/HEAD/Twitch/Assets/Art/Biplane.png -------------------------------------------------------------------------------- /Twitch/Assets/Art/gameover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrematic/LetsMakeAGame/HEAD/Twitch/Assets/Art/gameover.png -------------------------------------------------------------------------------- /Twitch/Assets/Art/spacetostart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrematic/LetsMakeAGame/HEAD/Twitch/Assets/Art/spacetostart.png -------------------------------------------------------------------------------- /Twitch/Engine/Graphics/SOIL/lib/SOIL.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrematic/LetsMakeAGame/HEAD/Twitch/Engine/Graphics/SOIL/lib/SOIL.lib -------------------------------------------------------------------------------- /Twitch/Engine/Graphics/SOIL/lib/libSOIL.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrematic/LetsMakeAGame/HEAD/Twitch/Engine/Graphics/SOIL/lib/libSOIL.a -------------------------------------------------------------------------------- /Twitch/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Twitch/Twitch.cpp: -------------------------------------------------------------------------------- 1 | #include "FlappyTwitch\GameManager.h" 2 | 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | int main() 8 | { 9 | cout << "Hello, Twitch!" << endl; 10 | srand(time(NULL)); 11 | 12 | GameManager gameManager; 13 | gameManager.Start(); 14 | 15 | return 0; 16 | } -------------------------------------------------------------------------------- /Twitch/Engine/IO/Keyboard.h: -------------------------------------------------------------------------------- 1 | #ifndef TWITCH_KEYBOARD 2 | #define TWITCH_KEYBOARD 3 | 4 | #include "GLFW/glfw3.h" 5 | 6 | class Keyboard 7 | { 8 | public: 9 | static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); 10 | 11 | static bool KeyDown(int key); 12 | static bool KeyUp(int key); 13 | static bool Key(int key); 14 | private: 15 | static bool keys[]; 16 | static bool keysDown[]; 17 | static bool keysUp[]; 18 | }; 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /Twitch/Engine/Math/Math.h: -------------------------------------------------------------------------------- 1 | #ifndef TWITCH_MATH 2 | #define TWITCH_MATH 3 | 4 | #include "Vector3.h" 5 | #include 6 | 7 | using namespace std; 8 | 9 | #define PI 3.14159 10 | 11 | namespace Math 12 | { 13 | double ConvertToRadians(double degrees); 14 | double ConvertToDegrees(double radians); 15 | Vector3 RotatePoint(Vector3 point, Vector3 pivot, float rot); 16 | float Min(vector x); 17 | float Max(vector x); 18 | float Abs(float x); 19 | } 20 | 21 | #endif -------------------------------------------------------------------------------- /Twitch/Engine/Graphics/Texture.h: -------------------------------------------------------------------------------- 1 | #ifndef TWITCH_TEXTURE 2 | #define TWITCH_TEXTURE 3 | 4 | #include "GLFW/glfw3.h" 5 | #include "SOIL/src/SOIL.h" 6 | 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | class Texture 12 | { 13 | public: 14 | Texture(); 15 | Texture(int _id); 16 | Texture(string path); 17 | 18 | int GetID(); 19 | int GetWidth(); 20 | int GetHeight(); 21 | 22 | private: 23 | bool GetTextureParams(); 24 | 25 | int id; 26 | int width; 27 | int height; 28 | }; 29 | 30 | #endif -------------------------------------------------------------------------------- /Twitch/Engine/Engine.h: -------------------------------------------------------------------------------- 1 | #ifndef TWITCH_ENGINE 2 | #define TWITCH_ENGINE 3 | 4 | #include "GLFW/glfw3.h" 5 | #pragma comment(lib, "opengl32.lib") 6 | 7 | #include 8 | using namespace std; 9 | 10 | class Engine 11 | { 12 | public: 13 | static int SCREEN_WIDTH; 14 | static int SCREEN_HEIGHT; 15 | static float GetDT(); 16 | 17 | Engine(); 18 | ~Engine(); 19 | 20 | bool Initialize(char* windowTitle); 21 | 22 | void Update(); 23 | void BeginRender(); 24 | void EndRender(); 25 | 26 | private: 27 | static GLFWwindow* window; 28 | 29 | static float dt; 30 | float lastTime; 31 | }; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /Twitch/FlappyTwitch/Flapper.h: -------------------------------------------------------------------------------- 1 | #ifndef TWITCH_FLAPPER 2 | #define TWITCH_FLAPPER 3 | 4 | #include "../Engine/Graphics/Sprite.h" 5 | #include "../Engine/Physics/Rigidbody.h" 6 | 7 | class Flapper 8 | { 9 | public: 10 | 11 | Flapper(); 12 | Flapper(Sprite _sprite); 13 | 14 | void Update(); 15 | void Render(); 16 | 17 | void Flap(); 18 | 19 | Sprite& GetSprite(); 20 | Rigidbody& GetRB(); 21 | 22 | void Reset(); 23 | 24 | private: 25 | void HandleInput(); 26 | 27 | private: 28 | Sprite sprite; 29 | Rigidbody rb; 30 | 31 | float flapForce; 32 | float maxRot; 33 | float minRot; 34 | }; 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /Twitch/Engine/Math/Rect.h: -------------------------------------------------------------------------------- 1 | #ifndef TWITCH_RECT 2 | #define TWITCH_RECT 3 | 4 | #include "Vector3.h" 5 | #include 6 | 7 | using namespace std; 8 | 9 | class Rect 10 | { 11 | public: 12 | Rect(); 13 | Rect(Vector3 _size); 14 | Rect(Vector3 _pos, Vector3 _size); 15 | 16 | void MoveBy(Vector3 by); 17 | void MoveTo(Vector3 to); 18 | void SetSize(Vector3 _size); 19 | 20 | string ToString(); 21 | 22 | Vector3 upperLeftVertex; 23 | Vector3 upperRightVertex; 24 | Vector3 lowerLeftVertex; 25 | Vector3 lowerRightVertex; 26 | private: 27 | void UpdateVertices(); 28 | 29 | Vector3 pos; 30 | Vector3 size; 31 | }; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /Twitch/Engine/IO/Mouse.h: -------------------------------------------------------------------------------- 1 | #ifndef TWITCH_MOUSE 2 | #define TWITCH_MOUSE 3 | 4 | #include "GLFW/glfw3.h" 5 | 6 | class Mouse 7 | { 8 | public: 9 | static void MousePosCallback(GLFWwindow* window, double _x, double _y); 10 | static void MouseButtonCallback(GLFWwindow* window, int button, int action, int mods); 11 | 12 | static double GetMouseX(); 13 | static double GetMouseY(); 14 | 15 | static bool ButtonDown(int button); 16 | static bool ButtonUp(int button); 17 | static bool Button(int button); 18 | 19 | private: 20 | static double x; 21 | static double y; 22 | 23 | static bool buttons[]; 24 | static bool buttonsDown[]; 25 | static bool buttonsUp[]; 26 | }; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /Twitch/FlappyTwitch/GameManager.h: -------------------------------------------------------------------------------- 1 | #ifndef TWITCH_GAMEMANAGER 2 | #define TWITCH_GAMEMANAGER 3 | 4 | #include "../Engine/Engine.h" 5 | #include "../Engine/Graphics/Sprite.h" 6 | 7 | #include "Flapper.h" 8 | #include "PipeManager.h" 9 | 10 | 11 | class GameManager 12 | { 13 | public: 14 | enum class State 15 | { 16 | START, 17 | GAMEPLAY, 18 | GAMEOVER, 19 | COUNT 20 | }; 21 | 22 | public: 23 | GameManager(); 24 | ~GameManager(); 25 | 26 | void Start(); 27 | 28 | private: 29 | void SetState(State state); 30 | 31 | private: 32 | Engine* mEngine; 33 | Flapper* mFlapper; 34 | PipeManager* mPipeManager; 35 | 36 | Sprite mStartSprite; 37 | Sprite mGameoverSprite; 38 | 39 | State mState; 40 | }; 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /Twitch/Engine/Math/Vector3.h: -------------------------------------------------------------------------------- 1 | #ifndef TWITCH_VECTOR3 2 | #define TWITCH_VECTOR3 3 | 4 | class Vector3 5 | { 6 | public: 7 | static float Dot(const Vector3& a, const Vector3& b); 8 | static Vector3 Project(const Vector3& a, const Vector3& b); 9 | 10 | Vector3(); 11 | Vector3(const Vector3& other); 12 | Vector3(float _x); 13 | Vector3(float _x, float _y, float _z); 14 | 15 | Vector3& operator=(const Vector3& other); 16 | Vector3 operator+(const Vector3& other); 17 | Vector3 operator-(const Vector3& other); 18 | Vector3 operator*(const Vector3& other); 19 | Vector3 operator*(float _x); 20 | 21 | bool operator==(const Vector3& other); 22 | bool operator!=(const Vector3& other); 23 | 24 | float x; 25 | float y; 26 | float z; 27 | }; 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /Twitch/Engine/Physics/Rigidbody.h: -------------------------------------------------------------------------------- 1 | #ifndef TWITCH_RIGIDBODY 2 | #define TWITCH_RIGIDBODY 3 | 4 | #include "../Math/Vector3.h" 5 | #include "../Math/Rect.h" 6 | 7 | class Rigidbody 8 | { 9 | public: 10 | 11 | static bool IsColliding(const Rigidbody& rbA, const Rigidbody& rbB); 12 | 13 | Rigidbody(); 14 | 15 | void Initialize(float _friction, float _gravity, Vector3* _pos, float* _rot, Vector3* _scale, Vector3* _size, Rect _boundingRect); 16 | 17 | void Update(); 18 | void Render(Vector3 c); 19 | 20 | void AddForce(Vector3 f); 21 | 22 | Vector3 GetVel(); 23 | void SetVel(Vector3 _vel); 24 | 25 | private: 26 | Vector3* pos; 27 | float* rot; 28 | float lastRot; 29 | Vector3* scale; 30 | Vector3* size; 31 | 32 | float gravity; 33 | float friction; 34 | Vector3 vel; 35 | 36 | Rect boundingRect; 37 | }; 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /Twitch/FlappyTwitch/PipeManager.h: -------------------------------------------------------------------------------- 1 | #ifndef TWITCH_PIPEMANAGER 2 | #define TWITCH_PIPEMANAGER 3 | 4 | #include "Pipe.h" 5 | #include "Flapper.h" 6 | 7 | #include 8 | using namespace std; 9 | 10 | class PipeManager 11 | { 12 | public: 13 | PipeManager(); 14 | ~PipeManager(); 15 | 16 | void Update(); 17 | void Render(); 18 | 19 | bool CheckCollision(Flapper& flapper); 20 | 21 | void Reset(); 22 | 23 | private: 24 | void CreatePipe(); 25 | 26 | private: 27 | vector pipes; 28 | 29 | float xStartSeparation; 30 | float yStartSeparation; 31 | float xSeparation; 32 | float ySeparation; 33 | float minXSeparation; 34 | float minYSeparation; 35 | float xSeparationSpeed; 36 | float ySeparationSpeed; 37 | 38 | int minSpawnY; 39 | int maxSpawnY; 40 | 41 | int totalPipes; 42 | int points; 43 | }; 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /Twitch/FlappyTwitch/Pipe.h: -------------------------------------------------------------------------------- 1 | #ifndef TWITCH_PIPE 2 | #define TWITCH_PIPE 3 | 4 | #include "../Engine/Graphics/Sprite.h" 5 | #include "../Engine/Physics/Rigidbody.h" 6 | #include "../Engine/Math/Vector3.h" 7 | 8 | class Pipe 9 | { 10 | public: 11 | static Sprite* pipeSprite; 12 | static void Initialize(); 13 | 14 | Pipe(); 15 | Pipe(Vector3 _pos); 16 | 17 | void SetGap(float _gap); 18 | float GetPrevPos(); 19 | 20 | void Update(); 21 | void Render(); 22 | 23 | void MoveTo(Vector3 to); 24 | void MoveBy(Vector3 by); 25 | 26 | float GetX(); 27 | float GetWidth(); 28 | 29 | Rigidbody GetTopRB(); 30 | Rigidbody GetBotRB(); 31 | 32 | private: 33 | void UpdatePos(); 34 | 35 | Sprite topSprite; 36 | Sprite botSprite; 37 | Rigidbody topRB; 38 | Rigidbody botRB; 39 | 40 | Vector3 pos; 41 | float prevPos; 42 | 43 | float gap; 44 | float speed; 45 | }; 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /Twitch/Engine/Graphics/SOIL/src/stbi_DDS_aug.h: -------------------------------------------------------------------------------- 1 | /* 2 | adding DDS loading support to stbi 3 | */ 4 | 5 | #ifndef HEADER_STB_IMAGE_DDS_AUGMENTATION 6 | #define HEADER_STB_IMAGE_DDS_AUGMENTATION 7 | 8 | // is it a DDS file? 9 | extern int stbi_dds_test_memory (stbi_uc const *buffer, int len); 10 | 11 | extern stbi_uc *stbi_dds_load (char *filename, int *x, int *y, int *comp, int req_comp); 12 | extern stbi_uc *stbi_dds_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); 13 | #ifndef STBI_NO_STDIO 14 | extern int stbi_dds_test_file (FILE *f); 15 | extern stbi_uc *stbi_dds_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); 16 | #endif 17 | 18 | // 19 | // 20 | //// end header file ///////////////////////////////////////////////////// 21 | #endif // HEADER_STB_IMAGE_DDS_AUGMENTATION 22 | -------------------------------------------------------------------------------- /Twitch/Engine/IO/Keyboard.cpp: -------------------------------------------------------------------------------- 1 | #include "Keyboard.h" 2 | 3 | bool Keyboard::keys[GLFW_KEY_LAST] = { 0 }; 4 | bool Keyboard::keysDown[GLFW_KEY_LAST] = { 0 }; 5 | bool Keyboard::keysUp[GLFW_KEY_LAST] = { 0 }; 6 | 7 | void Keyboard::KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) 8 | { 9 | if (key < 0) 10 | return; 11 | 12 | if (action != GLFW_RELEASE && keys[key] == false) 13 | { 14 | keysDown[key] = true; 15 | keysUp[key] = false; 16 | } 17 | 18 | if (action == GLFW_RELEASE && keys[key] == true) 19 | { 20 | keysDown[key] = false; 21 | keysUp[key] = true; 22 | } 23 | 24 | keys[key] = action != GLFW_RELEASE; 25 | } 26 | 27 | bool Keyboard::KeyDown(int key) 28 | { 29 | bool x = keysDown[key]; 30 | keysDown[key] = false; 31 | return x; 32 | } 33 | 34 | bool Keyboard::KeyUp(int key) 35 | { 36 | bool x = keysUp[key]; 37 | keysUp[key] = false; 38 | return x; 39 | } 40 | 41 | bool Keyboard::Key(int key) 42 | { 43 | return keys[key]; 44 | } -------------------------------------------------------------------------------- /Twitch/Engine/Graphics/Sprite.h: -------------------------------------------------------------------------------- 1 | #ifndef TWITCH_SPRITE 2 | #define TWITCH_SPRITE 3 | 4 | #include "GLFW/glfw3.h" 5 | #include "Texture.h" 6 | #include "../Math/Vector3.h" 7 | 8 | #include 9 | #include 10 | using namespace std; 11 | 12 | class Sprite 13 | { 14 | public: 15 | Sprite(); 16 | Sprite(string imagePath); 17 | Sprite(string imagePath, Vector3 _pos); 18 | 19 | void Update(); 20 | void Render(); 21 | 22 | void SpeedTo(float x); 23 | void SpeedBy(float x); 24 | 25 | void MoveTo(Vector3 v); 26 | void MoveBy(Vector3 v); 27 | 28 | void MoveLeft(); 29 | void MoveRight(); 30 | void MoveUp(); 31 | void MoveDown(); 32 | 33 | void RotateTo(float x); 34 | void RotateBy(float x); 35 | 36 | void SetScale(float x); 37 | void SetScale(Vector3 v); 38 | 39 | void FlipHorizontal(); 40 | void FlipVertical(); 41 | 42 | Vector3* GetPos(); 43 | float* GetRot(); 44 | Vector3* GetScale(); 45 | Vector3* GetSize(); 46 | 47 | private: 48 | Texture texture; 49 | 50 | float speed; 51 | 52 | Vector3 pos; 53 | float rot; 54 | Vector3 scale; 55 | Vector3 size; 56 | }; 57 | 58 | #endif -------------------------------------------------------------------------------- /Twitch/Engine/Graphics/Texture.cpp: -------------------------------------------------------------------------------- 1 | #include "Texture.h" 2 | 3 | Texture::Texture() 4 | { 5 | id = -1; 6 | } 7 | 8 | Texture::Texture(int _id) 9 | { 10 | id = _id; 11 | if (!GetTextureParams()) 12 | { 13 | cout << "Error loading image with ID: " << id << endl; 14 | } 15 | } 16 | 17 | Texture::Texture(string path) 18 | { 19 | id = SOIL_load_OGL_texture(path.c_str(), SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y); 20 | if (!GetTextureParams()) 21 | { 22 | cout << "Error loading image: " << path << endl; 23 | } 24 | } 25 | 26 | int Texture::GetID() 27 | { 28 | return id; 29 | } 30 | 31 | int Texture::GetWidth() 32 | { 33 | return width; 34 | } 35 | 36 | int Texture::GetHeight() 37 | { 38 | return height; 39 | } 40 | 41 | bool Texture::GetTextureParams() 42 | { 43 | if (id > 0) 44 | { 45 | int mipLevel = 0; 46 | glBindTexture(GL_TEXTURE_2D, id); 47 | glGetTexLevelParameteriv(GL_TEXTURE_2D, mipLevel, GL_TEXTURE_WIDTH, &width); 48 | glGetTexLevelParameteriv(GL_TEXTURE_2D, mipLevel, GL_TEXTURE_HEIGHT, &height); 49 | return true; 50 | } 51 | 52 | return false; 53 | } -------------------------------------------------------------------------------- /Twitch/Engine/Math/Math.cpp: -------------------------------------------------------------------------------- 1 | #include "Math.h" 2 | 3 | #include 4 | 5 | namespace Math 6 | { 7 | double ConvertToRadians(double degrees) 8 | { 9 | return (degrees * PI) / 180; 10 | } 11 | 12 | double ConvertToDegrees(double radians) 13 | { 14 | return (radians * 180) / PI; 15 | } 16 | 17 | Vector3 RotatePoint(Vector3 point, Vector3 pivot, float rot) 18 | { 19 | double radRot = ConvertToRadians(rot); 20 | double s = sin(radRot); 21 | double c = cos(radRot); 22 | 23 | point = point - pivot; 24 | 25 | float newX = (float)(point.x * c - point.y * s); 26 | float newY = (float)(point.x * s + point.y * c); 27 | 28 | point.x = newX + pivot.x; 29 | point.y = newY + pivot.y; 30 | 31 | return point; 32 | } 33 | 34 | float Min(vector x) 35 | { 36 | float retVal = x[0]; 37 | 38 | for (unsigned int i = 1; i < x.size(); i++) 39 | { 40 | if (x[i] < retVal) 41 | retVal = x[i]; 42 | } 43 | 44 | return retVal; 45 | } 46 | 47 | float Max(vector x) 48 | { 49 | float retVal = x[0]; 50 | 51 | for (unsigned int i = 1; i < x.size(); i++) 52 | { 53 | if (x[i] > retVal) 54 | retVal = x[i]; 55 | } 56 | 57 | return retVal; 58 | } 59 | 60 | float Abs(float x) 61 | { 62 | if (x > 0) 63 | { 64 | return x; 65 | } 66 | return -x; 67 | } 68 | } -------------------------------------------------------------------------------- /Twitch.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25123.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Twitch", "Twitch\Twitch.vcxproj", "{4DE6D995-030A-473B-A7B3-FB0E88096FA1}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {4DE6D995-030A-473B-A7B3-FB0E88096FA1}.Debug|x64.ActiveCfg = Debug|x64 17 | {4DE6D995-030A-473B-A7B3-FB0E88096FA1}.Debug|x64.Build.0 = Debug|x64 18 | {4DE6D995-030A-473B-A7B3-FB0E88096FA1}.Debug|x86.ActiveCfg = Debug|Win32 19 | {4DE6D995-030A-473B-A7B3-FB0E88096FA1}.Debug|x86.Build.0 = Debug|Win32 20 | {4DE6D995-030A-473B-A7B3-FB0E88096FA1}.Release|x64.ActiveCfg = Release|x64 21 | {4DE6D995-030A-473B-A7B3-FB0E88096FA1}.Release|x64.Build.0 = Release|x64 22 | {4DE6D995-030A-473B-A7B3-FB0E88096FA1}.Release|x86.ActiveCfg = Release|Win32 23 | {4DE6D995-030A-473B-A7B3-FB0E88096FA1}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /Twitch/Engine/Math/Rect.cpp: -------------------------------------------------------------------------------- 1 | #include "Rect.h" 2 | 3 | #include 4 | 5 | Rect::Rect() 6 | { 7 | pos = Vector3(0); 8 | size = Vector3(0); 9 | UpdateVertices(); 10 | } 11 | 12 | Rect::Rect(Vector3 _size) : Rect() 13 | { 14 | pos = Vector3(0); 15 | size = _size; 16 | UpdateVertices(); 17 | } 18 | 19 | Rect::Rect(Vector3 _pos, Vector3 _size) : Rect(_size) 20 | { 21 | pos = _pos; 22 | UpdateVertices(); 23 | } 24 | 25 | void Rect::MoveBy(Vector3 by) 26 | { 27 | pos = pos + by; 28 | UpdateVertices(); 29 | } 30 | 31 | void Rect::MoveTo(Vector3 to) 32 | { 33 | pos = to; 34 | UpdateVertices(); 35 | } 36 | 37 | void Rect::SetSize(Vector3 _size) 38 | { 39 | size = _size; 40 | UpdateVertices(); 41 | } 42 | 43 | string Rect::ToString() 44 | { 45 | stringstream ss; 46 | ss << "Pos(" << pos.x << ", " << pos.y << ", " << pos.z << ") - Size(" << size.x << ", " << size.y << ", " << size.z << ")" << endl; 47 | ss << "LL.X: " << lowerLeftVertex.x << "\tY: " << lowerLeftVertex.y << endl; 48 | ss << "UR.X: " << upperRightVertex.x << "\tY: " << upperRightVertex.y; 49 | return ss.str(); 50 | } 51 | 52 | void Rect::UpdateVertices() 53 | { 54 | lowerLeftVertex = Vector3(pos.x - (size.x / 2), pos.y - (size.y / 2), 0); 55 | lowerRightVertex = Vector3(pos.x + (size.x / 2), pos.y - (size.y / 2), 0); 56 | upperLeftVertex = Vector3(pos.x - (size.x / 2), pos.y + (size.y / 2), 0); 57 | upperRightVertex = Vector3(pos.x + (size.x / 2), pos.y + (size.y / 2), 0); 58 | } -------------------------------------------------------------------------------- /Twitch/Engine/IO/Mouse.cpp: -------------------------------------------------------------------------------- 1 | #include "Mouse.h" 2 | 3 | double Mouse::x = 0; 4 | double Mouse::y = 0; 5 | 6 | bool Mouse::buttons[GLFW_MOUSE_BUTTON_LAST] = { 0 }; 7 | bool Mouse::buttonsDown[GLFW_MOUSE_BUTTON_LAST] = { 0 }; 8 | bool Mouse::buttonsUp[GLFW_MOUSE_BUTTON_LAST] = { 0 }; 9 | 10 | void Mouse::MousePosCallback(GLFWwindow* window, double _x, double _y) 11 | { 12 | int width, height; 13 | glfwGetFramebufferSize(window, &width, &height); 14 | 15 | x = _x; 16 | y = height - _y; 17 | } 18 | 19 | void Mouse::MouseButtonCallback(GLFWwindow* window, int button, int action, int mods) 20 | { 21 | if (button < 0) 22 | return; 23 | 24 | if (action != GLFW_RELEASE && buttons[button] == false) 25 | { 26 | buttonsDown[button] = true; 27 | buttonsUp[button] = false; 28 | } 29 | 30 | if (action == GLFW_RELEASE && buttons[button] == true) 31 | { 32 | buttonsDown[button] = false; 33 | buttonsUp[button] = true; 34 | } 35 | 36 | buttons[button] = action != GLFW_RELEASE; 37 | } 38 | 39 | double Mouse::GetMouseX() 40 | { 41 | return x; 42 | } 43 | 44 | double Mouse::GetMouseY() 45 | { 46 | return y; 47 | } 48 | 49 | bool Mouse::ButtonDown(int button) 50 | { 51 | bool x = buttonsDown[button]; 52 | buttonsDown[button] = false; 53 | return x; 54 | } 55 | 56 | bool Mouse::ButtonUp(int button) 57 | { 58 | bool x = buttonsUp[button]; 59 | buttonsUp[button] = false; 60 | return x; 61 | } 62 | 63 | bool Mouse::Button(int button) 64 | { 65 | return buttons[button]; 66 | } -------------------------------------------------------------------------------- /Twitch/FlappyTwitch/Flapper.cpp: -------------------------------------------------------------------------------- 1 | #include "Flapper.h" 2 | 3 | #include "../Engine/Engine.h" 4 | #include "../Engine/Math/Rect.h" 5 | #include "../Engine/IO/Keyboard.h" 6 | #include "../Engine/IO/Mouse.h" 7 | 8 | Flapper::Flapper() 9 | { 10 | flapForce = 750; 11 | maxRot = 30; 12 | minRot = -maxRot; 13 | } 14 | 15 | Flapper::Flapper(Sprite _sprite) : Flapper() 16 | { 17 | sprite = _sprite; 18 | 19 | Rect boundingRect = Rect(); 20 | Vector3 sizeOffset(0.8, 0.3, 1); 21 | boundingRect.SetSize(*sprite.GetSize() * *sprite.GetScale() * sizeOffset); 22 | rb.Initialize(0.8f, -10, sprite.GetPos(), sprite.GetRot(), sprite.GetScale(), sprite.GetSize(), boundingRect); 23 | } 24 | 25 | void Flapper::Update() 26 | { 27 | HandleInput(); 28 | 29 | sprite.Update(); 30 | rb.Update(); 31 | 32 | float yVel = rb.GetVel().y; 33 | if (flapForce == 0) 34 | { 35 | cout << "Error! Flapping will do you no good! Setting to 750" << endl; 36 | flapForce = 750; 37 | } 38 | float newRot = (maxRot / flapForce) * yVel; 39 | sprite.RotateTo(newRot); 40 | } 41 | 42 | void Flapper::Render() 43 | { 44 | sprite.Render(); 45 | rb.Render(Vector3(0, 0, 0)); 46 | } 47 | 48 | void Flapper::Flap() 49 | { 50 | rb.SetVel(Vector3(0, flapForce, 0)); 51 | sprite.RotateTo(maxRot); 52 | } 53 | 54 | Sprite& Flapper::GetSprite() 55 | { 56 | return sprite; 57 | } 58 | 59 | Rigidbody& Flapper::GetRB() 60 | { 61 | return rb; 62 | } 63 | 64 | void Flapper::Reset() 65 | { 66 | sprite.MoveTo(Vector3(Engine::SCREEN_WIDTH / 2, Engine::SCREEN_HEIGHT / 2, 0)); 67 | sprite.RotateTo(0); 68 | rb.SetVel(Vector3(0, 0, 0)); 69 | } 70 | 71 | // Private 72 | 73 | void Flapper::HandleInput() 74 | { 75 | if (Keyboard::KeyDown(GLFW_KEY_SPACE) || Mouse::ButtonDown(GLFW_MOUSE_BUTTON_LEFT)) 76 | { 77 | Flap(); 78 | } 79 | } -------------------------------------------------------------------------------- /Twitch/Engine/Math/Vector3.cpp: -------------------------------------------------------------------------------- 1 | #include "Vector3.h" 2 | 3 | #include 4 | 5 | float Vector3::Dot(const Vector3& a, const Vector3& b) 6 | { 7 | return a.x * b.x + a.y * b.y; 8 | } 9 | 10 | Vector3 Vector3::Project(const Vector3& a, const Vector3& b) 11 | { 12 | return Vector3( (Vector3::Dot(a, b) / ((float)pow(b.x, 2) + (float)pow(b.y, 2))) * b.x, 13 | (Vector3::Dot(a, b) / ((float)pow(b.x, 2) + (float)pow(b.y, 2))) * b.y, 14 | 0); 15 | } 16 | 17 | Vector3::Vector3() 18 | { 19 | x = 0; 20 | y = 0; 21 | z = 0; 22 | } 23 | 24 | Vector3::Vector3(const Vector3& other) 25 | { 26 | x = other.x; 27 | y = other.y; 28 | z = other.z; 29 | } 30 | 31 | Vector3::Vector3(float _x) 32 | { 33 | x = _x; 34 | y = _x; 35 | z = _x; 36 | } 37 | 38 | Vector3::Vector3(float _x, float _y, float _z) 39 | { 40 | x = _x; 41 | y = _y; 42 | z = _z; 43 | } 44 | 45 | Vector3& Vector3::operator=(const Vector3& other) 46 | { 47 | x = other.x; 48 | y = other.y; 49 | z = other.z; 50 | 51 | return *this; 52 | } 53 | 54 | Vector3 Vector3::operator+(const Vector3& other) 55 | { 56 | Vector3 ret; 57 | 58 | ret.x = x + other.x; 59 | ret.y = y + other.y; 60 | ret.z = z + other.z; 61 | 62 | return ret; 63 | } 64 | 65 | Vector3 Vector3::operator-(const Vector3& other) 66 | { 67 | Vector3 ret; 68 | 69 | ret.x = x - other.x; 70 | ret.y = y - other.y; 71 | ret.z = z - other.z; 72 | 73 | return ret; 74 | } 75 | 76 | 77 | Vector3 Vector3::operator*(const Vector3& other) 78 | { 79 | Vector3 ret; 80 | 81 | ret.x = x * other.x; 82 | ret.y = y * other.y; 83 | ret.z = z * other.z; 84 | 85 | return ret; 86 | } 87 | 88 | 89 | Vector3 Vector3::operator*(float _x) 90 | { 91 | Vector3 ret; 92 | 93 | ret.x = x * _x; 94 | ret.y = y * _x; 95 | ret.z = z * _x; 96 | 97 | return ret; 98 | } 99 | 100 | bool Vector3::operator==(const Vector3& other) 101 | { 102 | return (x == other.x && y == other.y && z == other.z); 103 | } 104 | 105 | bool Vector3::operator!=(const Vector3& other) 106 | { 107 | return !operator==(other); 108 | } 109 | -------------------------------------------------------------------------------- /Twitch/Engine/Engine.cpp: -------------------------------------------------------------------------------- 1 | #include "Engine.h" 2 | #include "IO/Mouse.h" 3 | #include "IO/Keyboard.h" 4 | 5 | int Engine::SCREEN_WIDTH = 1024; 6 | int Engine::SCREEN_HEIGHT = 768; 7 | GLFWwindow* Engine::window = NULL; 8 | float Engine::dt = 0; 9 | 10 | Engine::Engine() 11 | { 12 | 13 | } 14 | 15 | Engine::~Engine() 16 | { 17 | 18 | } 19 | 20 | bool Engine::Initialize(char* windowTitle) 21 | { 22 | if (!glfwInit()) 23 | { 24 | cout << "Error initializing GLFW" << endl; 25 | return false; 26 | } 27 | 28 | window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, windowTitle, NULL, NULL); 29 | if (window == NULL) 30 | { 31 | cout << "Error creating window" << endl; 32 | return false; 33 | } 34 | 35 | //GLFW Setup 36 | glfwMakeContextCurrent(window); 37 | int width, height; 38 | glfwGetFramebufferSize(window, &width, &height); 39 | glfwSwapInterval(1); 40 | 41 | glfwSetCursorPosCallback(window, Mouse::MousePosCallback); 42 | glfwSetMouseButtonCallback(window, Mouse::MouseButtonCallback); 43 | glfwSetKeyCallback(window, Keyboard::KeyCallback); 44 | 45 | const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor()); 46 | int xPos = (mode->width - SCREEN_WIDTH) / 2; 47 | int yPos = (mode->height - SCREEN_HEIGHT) / 2; 48 | glfwSetWindowPos(window, xPos, yPos); 49 | 50 | //GL Setup 51 | //Viewport 52 | glViewport(0, 0, width, height); 53 | glMatrixMode(GL_PROJECTION); 54 | glLoadIdentity(); 55 | glOrtho(0, width, 0, height, -10, 10); 56 | glDepthRange(-10, 10); 57 | glMatrixMode(GL_MODELVIEW); 58 | 59 | //Alpha Blending 60 | glEnable(GL_ALPHA_TEST); 61 | glEnable(GL_BLEND); 62 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 63 | 64 | lastTime = (float)glfwGetTime(); 65 | 66 | return true; 67 | } 68 | 69 | void Engine::Update() 70 | { 71 | float now = (float)glfwGetTime(); 72 | dt = (now - lastTime); 73 | lastTime = now; 74 | glfwPollEvents(); 75 | } 76 | 77 | void Engine::BeginRender() 78 | { 79 | glClearColor(0, 1, 0, 1); 80 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 81 | } 82 | 83 | void Engine::EndRender() 84 | { 85 | glfwSwapBuffers(window); 86 | } 87 | 88 | float Engine::GetDT() 89 | { 90 | return dt; 91 | } -------------------------------------------------------------------------------- /Twitch/FlappyTwitch/GameManager.cpp: -------------------------------------------------------------------------------- 1 | #include "GameManager.h" 2 | 3 | #include "../Engine/IO/Mouse.h" 4 | #include "../Engine/IO/Keyboard.h" 5 | 6 | GameManager::GameManager() 7 | { 8 | mEngine = new Engine(); 9 | mEngine->Initialize("Twitch!"); 10 | 11 | Sprite testSprite = Sprite("Assets/Art/Biplane.png", Vector3(Engine::SCREEN_WIDTH / 2, Engine::SCREEN_HEIGHT / 2, 0)); 12 | testSprite.SetScale(0.15f); 13 | 14 | mFlapper = new Flapper(testSprite); 15 | mPipeManager = new PipeManager(); 16 | 17 | mStartSprite = Sprite("Assets/Art/spacetostart.png", Vector3(Engine::SCREEN_WIDTH / 2, Engine::SCREEN_HEIGHT / 2, 0)); 18 | mGameoverSprite = Sprite("Assets/Art/gameover.png", Vector3(Engine::SCREEN_WIDTH / 2, Engine::SCREEN_HEIGHT / 2, 0)); 19 | mGameoverSprite.SetScale(0.15f); 20 | 21 | mState = State::START; 22 | } 23 | 24 | GameManager::~GameManager() 25 | { 26 | delete mEngine; 27 | delete mFlapper; 28 | delete mPipeManager; 29 | } 30 | 31 | void GameManager::Start() 32 | { 33 | while (true) 34 | { 35 | if (Keyboard::KeyDown(GLFW_KEY_ESCAPE)) 36 | { 37 | break; 38 | } 39 | 40 | mEngine->Update(); 41 | 42 | switch (mState) 43 | { 44 | case State::START: 45 | { 46 | mEngine->BeginRender(); 47 | mStartSprite.Render(); 48 | mEngine->EndRender(); 49 | 50 | if (Keyboard::KeyDown(GLFW_KEY_SPACE) || Mouse::ButtonDown(GLFW_MOUSE_BUTTON_LEFT)) 51 | { 52 | SetState(State::GAMEPLAY); 53 | } 54 | } 55 | break; 56 | case State::GAMEPLAY: 57 | { 58 | mFlapper->Update(); 59 | mPipeManager->Update(); 60 | 61 | mEngine->BeginRender(); 62 | mPipeManager->Render(); 63 | mFlapper->Render(); 64 | mEngine->EndRender(); 65 | 66 | bool isDead = mPipeManager->CheckCollision(*mFlapper); 67 | if (mFlapper->GetSprite().GetPos()->y < 0 || mFlapper->GetSprite().GetPos()->y > Engine::SCREEN_HEIGHT) 68 | { 69 | isDead = true; 70 | } 71 | 72 | if (isDead) 73 | { 74 | SetState(State::GAMEOVER); 75 | } 76 | } 77 | break; 78 | case State::GAMEOVER: 79 | { 80 | mEngine->BeginRender(); 81 | mPipeManager->Render(); 82 | mFlapper->Render(); 83 | mGameoverSprite.Render(); 84 | mEngine->EndRender(); 85 | 86 | if (Keyboard::KeyDown(GLFW_KEY_SPACE) || Mouse::ButtonDown(GLFW_MOUSE_BUTTON_LEFT)) 87 | { 88 | SetState(State::START); 89 | } 90 | } 91 | break; 92 | default: 93 | cout << "Unhandled game state: " << static_cast(mState) << endl; 94 | break; 95 | } 96 | } 97 | } 98 | 99 | // Private 100 | 101 | void GameManager::SetState(State state) 102 | { 103 | mState = state; 104 | 105 | if (mState == State::START) 106 | { 107 | mFlapper->Reset(); 108 | mPipeManager->Reset(); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /Twitch/Engine/Graphics/SOIL/src/image_helper.h: -------------------------------------------------------------------------------- 1 | /* 2 | Jonathan Dummer 3 | 4 | Image helper functions 5 | 6 | MIT license 7 | */ 8 | 9 | #ifndef HEADER_IMAGE_HELPER 10 | #define HEADER_IMAGE_HELPER 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | /** 17 | This function upscales an image. 18 | Not to be used to create MIPmaps, 19 | but to make it square, 20 | or to make it a power-of-two sized. 21 | **/ 22 | int 23 | up_scale_image 24 | ( 25 | const unsigned char* const orig, 26 | int width, int height, int channels, 27 | unsigned char* resampled, 28 | int resampled_width, int resampled_height 29 | ); 30 | 31 | /** 32 | This function downscales an image. 33 | Used for creating MIPmaps, 34 | the incoming image should be a 35 | power-of-two sized. 36 | **/ 37 | int 38 | mipmap_image 39 | ( 40 | const unsigned char* const orig, 41 | int width, int height, int channels, 42 | unsigned char* resampled, 43 | int block_size_x, int block_size_y 44 | ); 45 | 46 | /** 47 | This function takes the RGB components of the image 48 | and scales each channel from [0,255] to [16,235]. 49 | This makes the colors "Safe" for display on NTSC 50 | displays. Note that this is _NOT_ a good idea for 51 | loading images like normal- or height-maps! 52 | **/ 53 | int 54 | scale_image_RGB_to_NTSC_safe 55 | ( 56 | unsigned char* orig, 57 | int width, int height, int channels 58 | ); 59 | 60 | /** 61 | This function takes the RGB components of the image 62 | and converts them into YCoCg. 3 components will be 63 | re-ordered to CoYCg (for optimum DXT1 compression), 64 | while 4 components will be ordered CoCgAY (for DXT5 65 | compression). 66 | **/ 67 | int 68 | convert_RGB_to_YCoCg 69 | ( 70 | unsigned char* orig, 71 | int width, int height, int channels 72 | ); 73 | 74 | /** 75 | This function takes the YCoCg components of the image 76 | and converts them into RGB. See above. 77 | **/ 78 | int 79 | convert_YCoCg_to_RGB 80 | ( 81 | unsigned char* orig, 82 | int width, int height, int channels 83 | ); 84 | 85 | /** 86 | Converts an HDR image from an array 87 | of unsigned chars (RGBE) to RGBdivA 88 | \return 0 if failed, otherwise returns 1 89 | **/ 90 | int 91 | RGBE_to_RGBdivA 92 | ( 93 | unsigned char *image, 94 | int width, int height, 95 | int rescale_to_max 96 | ); 97 | 98 | /** 99 | Converts an HDR image from an array 100 | of unsigned chars (RGBE) to RGBdivA2 101 | \return 0 if failed, otherwise returns 1 102 | **/ 103 | int 104 | RGBE_to_RGBdivA2 105 | ( 106 | unsigned char *image, 107 | int width, int height, 108 | int rescale_to_max 109 | ); 110 | 111 | #ifdef __cplusplus 112 | } 113 | #endif 114 | 115 | #endif /* HEADER_IMAGE_HELPER */ 116 | -------------------------------------------------------------------------------- /Twitch/FlappyTwitch/Pipe.cpp: -------------------------------------------------------------------------------- 1 | #include "Pipe.h" 2 | #include "../Engine/Math/Rect.h" 3 | #include "../Engine/Math/Math.h" 4 | #include "../Engine/Engine.h" 5 | 6 | Sprite* Pipe::pipeSprite = NULL; 7 | 8 | void Pipe::Initialize() 9 | { 10 | pipeSprite = new Sprite("Assets/Art/pipe.png"); 11 | pipeSprite->SetScale(Vector3(0.1f, 0.35f, 1)); 12 | } 13 | 14 | Pipe::Pipe() 15 | { 16 | if (!pipeSprite) 17 | { 18 | cout << "Trying to instantiate a Pipe without having called the Initialize method!" << endl; 19 | return; 20 | } 21 | 22 | topSprite = Sprite(*pipeSprite); 23 | botSprite = Sprite(*pipeSprite); 24 | 25 | gap = 350; 26 | speed = 200; 27 | } 28 | 29 | Pipe::Pipe(Vector3 _pos) : Pipe() 30 | { 31 | if (!pipeSprite) 32 | { 33 | return; 34 | } 35 | 36 | pos = _pos + Vector3(GetWidth(), 0, 0); 37 | prevPos = pos.x; 38 | 39 | UpdatePos(); 40 | topSprite.FlipVertical(); 41 | 42 | Rect topRC = Rect(); 43 | topRC.SetSize(Vector3(Math::Abs(topSprite.GetSize()->x * topSprite.GetScale()->x), Math::Abs(topSprite.GetSize()->y * topSprite.GetScale()->y), 1)); 44 | topRB = Rigidbody(); 45 | topRB.Initialize(1, 0, topSprite.GetPos(), topSprite.GetRot(), topSprite.GetScale(), topSprite.GetSize(), topRC); 46 | 47 | Rect botRC = Rect(); 48 | botRC.SetSize(Vector3(Math::Abs(botSprite.GetSize()->x * botSprite.GetScale()->x), Math::Abs(botSprite.GetSize()->y * botSprite.GetScale()->y), 1)); 49 | botRB = Rigidbody(); 50 | botRB.Initialize(1, 0, botSprite.GetPos(), botSprite.GetRot(), botSprite.GetScale(), botSprite.GetSize(), botRC); 51 | 52 | topRB.AddForce(Vector3(-speed, 0, 0)); 53 | botRB.AddForce(Vector3(-speed, 0, 0)); 54 | } 55 | 56 | void Pipe::SetGap(float _gap) 57 | { 58 | gap = _gap; 59 | UpdatePos(); 60 | } 61 | 62 | float Pipe::GetPrevPos() 63 | { 64 | return prevPos; 65 | } 66 | 67 | void Pipe::Update() 68 | { 69 | prevPos = topSprite.GetPos()->x; 70 | topRB.Update(); 71 | botRB.Update(); 72 | } 73 | 74 | void Pipe::Render() 75 | { 76 | topSprite.Render(); 77 | botSprite.Render(); 78 | topRB.Render(Vector3(255, 0, 0)); 79 | botRB.Render(Vector3(0, 0, 255)); 80 | } 81 | 82 | void Pipe::MoveTo(Vector3 to) 83 | { 84 | pos = to; 85 | UpdatePos(); 86 | } 87 | 88 | void Pipe::MoveBy(Vector3 by) 89 | { 90 | pos = pos + by; 91 | UpdatePos(); 92 | } 93 | 94 | float Pipe::GetX() 95 | { 96 | return topSprite.GetPos()->x; 97 | } 98 | 99 | float Pipe::GetWidth() 100 | { 101 | return topSprite.GetSize()->x * topSprite.GetScale()->x; 102 | } 103 | 104 | void Pipe::UpdatePos() 105 | { 106 | Vector3 topPos = pos; 107 | topPos.y += (gap / 2) + Math::Abs(topSprite.GetSize()->y * topSprite.GetScale()->y / 2); 108 | topSprite.MoveTo(topPos); 109 | 110 | Vector3 botPos = pos; 111 | botPos.y -= (gap / 2) + Math::Abs(botSprite.GetSize()->y * botSprite.GetScale()->y / 2); 112 | botSprite.MoveTo(botPos); 113 | } 114 | 115 | Rigidbody Pipe::GetTopRB() 116 | { 117 | return topRB; 118 | } 119 | 120 | Rigidbody Pipe::GetBotRB() 121 | { 122 | return botRB; 123 | } -------------------------------------------------------------------------------- /Twitch/FlappyTwitch/PipeManager.cpp: -------------------------------------------------------------------------------- 1 | #include "PipeManager.h" 2 | 3 | #include "../Engine/Engine.h" 4 | #include "../Engine/Physics/Rigidbody.h" 5 | 6 | PipeManager::PipeManager() : 7 | xStartSeparation(800), 8 | yStartSeparation(500), 9 | xSeparation(xStartSeparation), 10 | ySeparation(yStartSeparation), 11 | minXSeparation(200), 12 | minYSeparation(300), 13 | xSeparationSpeed(10), 14 | ySeparationSpeed(10), 15 | minSpawnY(284), 16 | maxSpawnY(Engine::SCREEN_HEIGHT - 284), 17 | totalPipes(0), 18 | points(0) 19 | { 20 | Pipe::Initialize(); 21 | CreatePipe(); 22 | } 23 | 24 | PipeManager::~PipeManager() 25 | { 26 | for (unsigned int i = 0; i < pipes.size(); i++) 27 | { 28 | delete pipes[i]; 29 | } 30 | } 31 | 32 | void PipeManager::Update() 33 | { 34 | vector pipesToDelete; 35 | for (unsigned int i = 0; i < pipes.size(); i++) 36 | { 37 | pipes[i]->Update(); 38 | if (pipes[i]->GetX() < -(pipes[i]->GetWidth() / 2)) 39 | { 40 | pipesToDelete.push_back(i); 41 | } 42 | 43 | if (i == pipes.size() - 1) 44 | { 45 | if (pipes[i]->GetX() < Engine::SCREEN_WIDTH - xSeparation) 46 | { 47 | CreatePipe(); 48 | } 49 | } 50 | 51 | if (pipes[i]->GetX() < Engine::SCREEN_WIDTH / 2 && 52 | pipes[i]->GetPrevPos() > Engine::SCREEN_WIDTH / 2) 53 | { 54 | points++; 55 | } 56 | } 57 | 58 | for (unsigned int i = 0; i < pipesToDelete.size(); i++) 59 | { 60 | delete pipes[pipesToDelete[i]]; 61 | pipes.erase(pipes.begin() + pipesToDelete[i]); 62 | } 63 | 64 | cout << "Points: " << points << endl; 65 | } 66 | 67 | void PipeManager::Render() 68 | { 69 | for (unsigned int i = 0; i < pipes.size(); i++) 70 | { 71 | pipes[i]->Render(); 72 | } 73 | } 74 | 75 | bool PipeManager::CheckCollision(Flapper& flapper) 76 | { 77 | bool isColliding = false; 78 | 79 | for (unsigned int i = 0; i < pipes.size(); i++) 80 | { 81 | isColliding = Rigidbody::IsColliding(flapper.GetRB(), pipes[i]->GetTopRB()) || 82 | Rigidbody::IsColliding(flapper.GetRB(), pipes[i]->GetBotRB()); 83 | if (isColliding) 84 | break; 85 | } 86 | 87 | return isColliding; 88 | } 89 | 90 | void PipeManager::Reset() 91 | { 92 | for (unsigned int i = 0; i < pipes.size(); i++) 93 | { 94 | delete pipes[i]; 95 | } 96 | pipes.clear(); 97 | 98 | xSeparation = xStartSeparation; 99 | ySeparation = yStartSeparation; 100 | totalPipes = 0; 101 | points = 0; 102 | 103 | CreatePipe(); 104 | } 105 | 106 | // Private 107 | 108 | void PipeManager::CreatePipe() 109 | { 110 | float spawnY = (rand() % (maxSpawnY - minSpawnY)) + minSpawnY; 111 | Pipe* pipe = new Pipe(Vector3(Engine::SCREEN_WIDTH, spawnY, 0)); 112 | pipe->SetGap(ySeparation); 113 | 114 | pipes.push_back(pipe); 115 | totalPipes++; 116 | 117 | if (totalPipes % 2 == 0) 118 | { 119 | if (xSeparation > minXSeparation + xSeparationSpeed) 120 | { 121 | xSeparation -= xSeparationSpeed; 122 | } 123 | 124 | if (ySeparation > minYSeparation + ySeparationSpeed) 125 | { 126 | ySeparation -= ySeparationSpeed; 127 | } 128 | } 129 | } -------------------------------------------------------------------------------- /Twitch/Engine/Graphics/Sprite.cpp: -------------------------------------------------------------------------------- 1 | #include "Sprite.h" 2 | #include "../Engine.h" 3 | 4 | Sprite::Sprite() 5 | { 6 | pos = Vector3(0); 7 | rot = 0; 8 | scale = Vector3(1); 9 | size = Vector3(0); 10 | speed = 5; 11 | texture = Texture(); 12 | } 13 | 14 | Sprite::Sprite(string imagePath) 15 | { 16 | texture = Texture(imagePath); 17 | pos = Vector3(0); 18 | scale = Vector3(1); 19 | size = Vector3((float)texture.GetWidth(), (float)texture.GetHeight(), 1); 20 | rot = 0; 21 | speed = 100; 22 | } 23 | 24 | Sprite::Sprite(string imagePath, Vector3 v) 25 | { 26 | texture = Texture(imagePath); 27 | pos = v; 28 | scale = Vector3(1); 29 | size = Vector3((float)texture.GetWidth(), (float)texture.GetHeight(), 1); 30 | rot = 0; 31 | speed = 100; 32 | } 33 | 34 | void Sprite::Update() 35 | { 36 | 37 | } 38 | 39 | void Sprite::Render() 40 | { 41 | glEnable(GL_TEXTURE_2D); 42 | glBindTexture(GL_TEXTURE_2D, texture.GetID()); 43 | glLoadIdentity(); 44 | 45 | //TRANSLATE -> ROTATE -> SCALE 46 | glTranslatef(pos.x, pos.y, 0); 47 | glRotatef(rot, 0, 0, 1); 48 | glScalef(scale.x, scale.y, 1); 49 | 50 | //Rendering 51 | glColor4f(1, 1, 1, 1); 52 | glBegin(GL_QUADS); 53 | { 54 | glTexCoord2f(0, 0); glVertex2i(-texture.GetWidth() / 2, -texture.GetHeight() / 2); 55 | glTexCoord2f(1, 0); glVertex2i( texture.GetWidth() / 2, -texture.GetHeight() / 2); 56 | glTexCoord2f(1, 1); glVertex2i( texture.GetWidth() / 2, texture.GetHeight() / 2); 57 | glTexCoord2f(0, 1); glVertex2i(-texture.GetWidth() / 2, texture.GetHeight() / 2); 58 | } 59 | glEnd(); 60 | 61 | glDisable(GL_TEXTURE_2D); 62 | } 63 | 64 | void Sprite::SpeedTo(float x) 65 | { 66 | speed = x; 67 | } 68 | 69 | void Sprite::SpeedBy(float x) 70 | { 71 | speed += x; 72 | } 73 | 74 | void Sprite::MoveTo(Vector3 v) 75 | { 76 | pos = v; 77 | } 78 | 79 | void Sprite::MoveBy(Vector3 v) 80 | { 81 | pos = pos + (v * Engine::GetDT()); 82 | } 83 | 84 | void Sprite::MoveLeft() 85 | { 86 | pos = pos - Vector3((speed * Engine::GetDT()), 0, 0); 87 | } 88 | 89 | void Sprite::MoveRight() 90 | { 91 | pos = pos + Vector3((speed * Engine::GetDT()), 0, 0); 92 | } 93 | 94 | void Sprite::MoveUp() 95 | { 96 | pos = pos + Vector3(0, (speed * Engine::GetDT()), 0); 97 | } 98 | 99 | void Sprite::MoveDown() 100 | { 101 | pos = pos - Vector3(0, (speed * Engine::GetDT()), 0); 102 | } 103 | 104 | void Sprite::RotateTo(float x) 105 | { 106 | rot = x; 107 | } 108 | 109 | void Sprite::RotateBy(float x) 110 | { 111 | rot += (x * Engine::GetDT()); 112 | } 113 | 114 | void Sprite::SetScale(float x) 115 | { 116 | scale = Vector3(x); 117 | } 118 | 119 | void Sprite::SetScale(Vector3 v) 120 | { 121 | scale = v; 122 | } 123 | 124 | void Sprite::FlipHorizontal() 125 | { 126 | scale.x = -scale.x; 127 | } 128 | 129 | void Sprite::FlipVertical() 130 | { 131 | scale.y = -scale.y; 132 | } 133 | 134 | Vector3* Sprite::GetPos() 135 | { 136 | return &pos; 137 | } 138 | 139 | float* Sprite::GetRot() 140 | { 141 | return &rot; 142 | } 143 | 144 | Vector3* Sprite::GetScale() 145 | { 146 | return &scale; 147 | } 148 | 149 | Vector3* Sprite::GetSize() 150 | { 151 | return &size; 152 | } -------------------------------------------------------------------------------- /Twitch/Engine/Graphics/SOIL/src/image_DXT.h: -------------------------------------------------------------------------------- 1 | /* 2 | Jonathan Dummer 3 | 2007-07-31-10.32 4 | 5 | simple DXT compression / decompression code 6 | 7 | public domain 8 | */ 9 | 10 | #ifndef HEADER_IMAGE_DXT 11 | #define HEADER_IMAGE_DXT 12 | 13 | /** 14 | Converts an image from an array of unsigned chars (RGB or RGBA) to 15 | DXT1 or DXT5, then saves the converted image to disk. 16 | \return 0 if failed, otherwise returns 1 17 | **/ 18 | int 19 | save_image_as_DDS 20 | ( 21 | const char *filename, 22 | int width, int height, int channels, 23 | const unsigned char *const data 24 | ); 25 | 26 | /** 27 | take an image and convert it to DXT1 (no alpha) 28 | **/ 29 | unsigned char* 30 | convert_image_to_DXT1 31 | ( 32 | const unsigned char *const uncompressed, 33 | int width, int height, int channels, 34 | int *out_size 35 | ); 36 | 37 | /** 38 | take an image and convert it to DXT5 (with alpha) 39 | **/ 40 | unsigned char* 41 | convert_image_to_DXT5 42 | ( 43 | const unsigned char *const uncompressed, 44 | int width, int height, int channels, 45 | int *out_size 46 | ); 47 | 48 | /** A bunch of DirectDraw Surface structures and flags **/ 49 | typedef struct 50 | { 51 | unsigned int dwMagic; 52 | unsigned int dwSize; 53 | unsigned int dwFlags; 54 | unsigned int dwHeight; 55 | unsigned int dwWidth; 56 | unsigned int dwPitchOrLinearSize; 57 | unsigned int dwDepth; 58 | unsigned int dwMipMapCount; 59 | unsigned int dwReserved1[ 11 ]; 60 | 61 | /* DDPIXELFORMAT */ 62 | struct 63 | { 64 | unsigned int dwSize; 65 | unsigned int dwFlags; 66 | unsigned int dwFourCC; 67 | unsigned int dwRGBBitCount; 68 | unsigned int dwRBitMask; 69 | unsigned int dwGBitMask; 70 | unsigned int dwBBitMask; 71 | unsigned int dwAlphaBitMask; 72 | } 73 | sPixelFormat; 74 | 75 | /* DDCAPS2 */ 76 | struct 77 | { 78 | unsigned int dwCaps1; 79 | unsigned int dwCaps2; 80 | unsigned int dwDDSX; 81 | unsigned int dwReserved; 82 | } 83 | sCaps; 84 | unsigned int dwReserved2; 85 | } 86 | DDS_header ; 87 | 88 | /* the following constants were copied directly off the MSDN website */ 89 | 90 | /* The dwFlags member of the original DDSURFACEDESC2 structure 91 | can be set to one or more of the following values. */ 92 | #define DDSD_CAPS 0x00000001 93 | #define DDSD_HEIGHT 0x00000002 94 | #define DDSD_WIDTH 0x00000004 95 | #define DDSD_PITCH 0x00000008 96 | #define DDSD_PIXELFORMAT 0x00001000 97 | #define DDSD_MIPMAPCOUNT 0x00020000 98 | #define DDSD_LINEARSIZE 0x00080000 99 | #define DDSD_DEPTH 0x00800000 100 | 101 | /* DirectDraw Pixel Format */ 102 | #define DDPF_ALPHAPIXELS 0x00000001 103 | #define DDPF_FOURCC 0x00000004 104 | #define DDPF_RGB 0x00000040 105 | 106 | /* The dwCaps1 member of the DDSCAPS2 structure can be 107 | set to one or more of the following values. */ 108 | #define DDSCAPS_COMPLEX 0x00000008 109 | #define DDSCAPS_TEXTURE 0x00001000 110 | #define DDSCAPS_MIPMAP 0x00400000 111 | 112 | /* The dwCaps2 member of the DDSCAPS2 structure can be 113 | set to one or more of the following values. */ 114 | #define DDSCAPS2_CUBEMAP 0x00000200 115 | #define DDSCAPS2_CUBEMAP_POSITIVEX 0x00000400 116 | #define DDSCAPS2_CUBEMAP_NEGATIVEX 0x00000800 117 | #define DDSCAPS2_CUBEMAP_POSITIVEY 0x00001000 118 | #define DDSCAPS2_CUBEMAP_NEGATIVEY 0x00002000 119 | #define DDSCAPS2_CUBEMAP_POSITIVEZ 0x00004000 120 | #define DDSCAPS2_CUBEMAP_NEGATIVEZ 0x00008000 121 | #define DDSCAPS2_VOLUME 0x00200000 122 | 123 | #endif /* HEADER_IMAGE_DXT */ 124 | -------------------------------------------------------------------------------- /Twitch/Twitch.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | Source Files 44 | 45 | 46 | Source Files 47 | 48 | 49 | Source Files 50 | 51 | 52 | Source Files 53 | 54 | 55 | Source Files 56 | 57 | 58 | Source Files 59 | 60 | 61 | 62 | 63 | Header Files 64 | 65 | 66 | Header Files 67 | 68 | 69 | Header Files 70 | 71 | 72 | Header Files 73 | 74 | 75 | Header Files 76 | 77 | 78 | Header Files 79 | 80 | 81 | Header Files 82 | 83 | 84 | Header Files 85 | 86 | 87 | Header Files 88 | 89 | 90 | Header Files 91 | 92 | 93 | Header Files 94 | 95 | 96 | Header Files 97 | 98 | 99 | Header Files 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /Twitch/Engine/Physics/Rigidbody.cpp: -------------------------------------------------------------------------------- 1 | #include "Rigidbody.h" 2 | #include "../Engine.h" 3 | 4 | #include "../Math/Math.h" 5 | 6 | #include 7 | using namespace std; 8 | 9 | Rigidbody::Rigidbody() 10 | { 11 | friction = 1; 12 | gravity = 0; 13 | } 14 | 15 | void Rigidbody::Initialize(float _friction, float _gravity, Vector3* _pos, float* _rot, Vector3* _scale, Vector3* _size, Rect _boundingRect) 16 | { 17 | friction = _friction; 18 | gravity = _gravity; 19 | 20 | pos = _pos; 21 | rot = _rot; 22 | lastRot = *rot; 23 | scale = _scale; 24 | size = _size; 25 | 26 | boundingRect = _boundingRect; 27 | } 28 | 29 | void Rigidbody::Update() 30 | { 31 | vel.x *= friction; 32 | vel.y += gravity; 33 | 34 | *pos = *pos + (vel * Engine::GetDT()); 35 | 36 | if (lastRot != *rot) 37 | { 38 | boundingRect.lowerLeftVertex = Math::RotatePoint(boundingRect.lowerLeftVertex, Vector3(0), *rot - lastRot); 39 | boundingRect.lowerRightVertex = Math::RotatePoint(boundingRect.lowerRightVertex, Vector3(0), *rot - lastRot); 40 | boundingRect.upperLeftVertex = Math::RotatePoint(boundingRect.upperLeftVertex, Vector3(0), *rot - lastRot); 41 | boundingRect.upperRightVertex = Math::RotatePoint(boundingRect.upperRightVertex, Vector3(0), *rot - lastRot); 42 | lastRot = *rot; 43 | } 44 | } 45 | 46 | void Rigidbody::Render(Vector3 c) 47 | { 48 | glLoadIdentity(); 49 | 50 | glTranslatef(pos->x, pos->y, pos->z); 51 | 52 | glColor4f(c.x, c.y, c.z, 1); 53 | glLineWidth(2.5); 54 | glBegin(GL_LINES); 55 | { 56 | glVertex2f(boundingRect.lowerLeftVertex.x, boundingRect.lowerLeftVertex.y); 57 | glVertex2f(boundingRect.lowerRightVertex.x, boundingRect.lowerRightVertex.y); 58 | 59 | glVertex2f(boundingRect.lowerRightVertex.x, boundingRect.lowerRightVertex.y); 60 | glVertex2f(boundingRect.upperRightVertex.x, boundingRect.upperRightVertex.y); 61 | 62 | glVertex2f(boundingRect.upperRightVertex.x, boundingRect.upperRightVertex.y); 63 | glVertex2f(boundingRect.upperLeftVertex.x, boundingRect.upperLeftVertex.y); 64 | 65 | glVertex2f(boundingRect.upperLeftVertex.x, boundingRect.upperLeftVertex.y); 66 | glVertex2f(boundingRect.lowerLeftVertex.x, boundingRect.lowerLeftVertex.y); 67 | } 68 | glEnd(); 69 | 70 | } 71 | 72 | void Rigidbody::AddForce(Vector3 force) 73 | { 74 | vel = vel + force; 75 | } 76 | 77 | Vector3 Rigidbody::GetVel() 78 | { 79 | return vel; 80 | } 81 | 82 | void Rigidbody::SetVel(Vector3 _vel) 83 | { 84 | vel = _vel; 85 | } 86 | 87 | bool Rigidbody::IsColliding(const Rigidbody& rbA, const Rigidbody& rbB) 88 | { 89 | Rect rcA = rbA.boundingRect; 90 | Rect rcB = rbB.boundingRect; 91 | 92 | Vector3 aUR = rcA.upperRightVertex + *rbA.pos; 93 | Vector3 aUL = rcA.upperLeftVertex + *rbA.pos; 94 | Vector3 aLR = rcA.lowerRightVertex + *rbA.pos; 95 | Vector3 aLL = rcA.lowerLeftVertex + *rbA.pos; 96 | Vector3 bUR = rcB.upperRightVertex + *rbB.pos; 97 | Vector3 bUL = rcB.upperLeftVertex + *rbB.pos; 98 | Vector3 bLR = rcB.lowerRightVertex + *rbB.pos; 99 | Vector3 bLL = rcB.lowerLeftVertex + *rbB.pos; 100 | 101 | float aMax = 0; 102 | float aMin = 0; 103 | float bMax = 0; 104 | float bMin = 0; 105 | 106 | Vector3 axis1 = aUR - aUL; 107 | Vector3 axis2 = aUR - aLR; 108 | Vector3 axis3 = bUL - bLL; 109 | Vector3 axis4 = bUL - bUR; 110 | 111 | vector axes; 112 | axes.push_back(axis1); 113 | axes.push_back(axis2); 114 | axes.push_back(axis3); 115 | axes.push_back(axis4); 116 | 117 | for (unsigned int i = 0; i < axes.size(); i++) 118 | { 119 | Vector3 aURProj = Vector3::Project(aUR, axes[i]); 120 | Vector3 aULProj = Vector3::Project(aUL, axes[i]); 121 | Vector3 aLRProj = Vector3::Project(aLR, axes[i]); 122 | Vector3 aLLProj = Vector3::Project(aLL, axes[i]); 123 | Vector3 bURProj = Vector3::Project(bUR, axes[i]); 124 | Vector3 bULProj = Vector3::Project(bUL, axes[i]); 125 | Vector3 bLRProj = Vector3::Project(bLR, axes[i]); 126 | Vector3 bLLProj = Vector3::Project(bLL, axes[i]); 127 | 128 | float aURScalar = Vector3::Dot(aURProj, axes[i]); 129 | float aULScalar = Vector3::Dot(aULProj, axes[i]); 130 | float aLRScalar = Vector3::Dot(aLRProj, axes[i]); 131 | float aLLScalar = Vector3::Dot(aLLProj, axes[i]); 132 | float bURScalar = Vector3::Dot(bURProj, axes[i]); 133 | float bULScalar = Vector3::Dot(bULProj, axes[i]); 134 | float bLRScalar = Vector3::Dot(bLRProj, axes[i]); 135 | float bLLScalar = Vector3::Dot(bLLProj, axes[i]); 136 | 137 | vector aScalars; 138 | aScalars.push_back(aURScalar); 139 | aScalars.push_back(aULScalar); 140 | aScalars.push_back(aLRScalar); 141 | aScalars.push_back(aLLScalar); 142 | aMin = Math::Min(aScalars); 143 | aMax = Math::Max(aScalars); 144 | 145 | vector bScalars; 146 | bScalars.push_back(bURScalar); 147 | bScalars.push_back(bULScalar); 148 | bScalars.push_back(bLRScalar); 149 | bScalars.push_back(bLLScalar); 150 | bMin = Math::Min(bScalars); 151 | bMax = Math::Max(bScalars); 152 | 153 | if (bMin <= aMax && bMax >= aMin) 154 | { 155 | 156 | } 157 | else 158 | { 159 | return false; 160 | } 161 | } 162 | return true; 163 | } 164 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | *.VC.VC.opendb 85 | 86 | # Visual Studio profiler 87 | *.psess 88 | *.vsp 89 | *.vspx 90 | *.sap 91 | 92 | # TFS 2012 Local Workspace 93 | $tf/ 94 | 95 | # Guidance Automation Toolkit 96 | *.gpState 97 | 98 | # ReSharper is a .NET coding add-in 99 | _ReSharper*/ 100 | *.[Rr]e[Ss]harper 101 | *.DotSettings.user 102 | 103 | # JustCode is a .NET coding add-in 104 | .JustCode 105 | 106 | # TeamCity is a build add-in 107 | _TeamCity* 108 | 109 | # DotCover is a Code Coverage Tool 110 | *.dotCover 111 | 112 | # NCrunch 113 | _NCrunch_* 114 | .*crunch*.local.xml 115 | nCrunchTemp_* 116 | 117 | # MightyMoose 118 | *.mm.* 119 | AutoTest.Net/ 120 | 121 | # Web workbench (sass) 122 | .sass-cache/ 123 | 124 | # Installshield output folder 125 | [Ee]xpress/ 126 | 127 | # DocProject is a documentation generator add-in 128 | DocProject/buildhelp/ 129 | DocProject/Help/*.HxT 130 | DocProject/Help/*.HxC 131 | DocProject/Help/*.hhc 132 | DocProject/Help/*.hhk 133 | DocProject/Help/*.hhp 134 | DocProject/Help/Html2 135 | DocProject/Help/html 136 | 137 | # Click-Once directory 138 | publish/ 139 | 140 | # Publish Web Output 141 | *.[Pp]ublish.xml 142 | *.azurePubxml 143 | # TODO: Comment the next line if you want to checkin your web deploy settings 144 | # but database connection strings (with potential passwords) will be unencrypted 145 | *.pubxml 146 | *.publishproj 147 | 148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 149 | # checkin your Azure Web App publish settings, but sensitive information contained 150 | # in these scripts will be unencrypted 151 | PublishScripts/ 152 | 153 | # NuGet Packages 154 | *.nupkg 155 | # The packages folder can be ignored because of Package Restore 156 | **/packages/* 157 | # except build/, which is used as an MSBuild target. 158 | !**/packages/build/ 159 | # Uncomment if necessary however generally it will be regenerated when needed 160 | #!**/packages/repositories.config 161 | # NuGet v3's project.json files produces more ignoreable files 162 | *.nuget.props 163 | *.nuget.targets 164 | 165 | # Microsoft Azure Build Output 166 | csx/ 167 | *.build.csdef 168 | 169 | # Microsoft Azure Emulator 170 | ecf/ 171 | rcf/ 172 | 173 | # Windows Store app package directories and files 174 | AppPackages/ 175 | BundleArtifacts/ 176 | Package.StoreAssociation.xml 177 | _pkginfo.txt 178 | 179 | # Visual Studio cache files 180 | # files ending in .cache can be ignored 181 | *.[Cc]ache 182 | # but keep track of directories ending in .cache 183 | !*.[Cc]ache/ 184 | 185 | # Others 186 | ClientBin/ 187 | ~$* 188 | *~ 189 | *.dbmdl 190 | *.dbproj.schemaview 191 | *.pfx 192 | *.publishsettings 193 | node_modules/ 194 | orleans.codegen.cs 195 | 196 | # Since there are multiple workflows, uncomment next line to ignore bower_components 197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 198 | #bower_components/ 199 | 200 | # RIA/Silverlight projects 201 | Generated_Code/ 202 | 203 | # Backup & report files from converting an old project file 204 | # to a newer Visual Studio version. Backup files are not needed, 205 | # because we have git ;-) 206 | _UpgradeReport_Files/ 207 | Backup*/ 208 | UpgradeLog*.XML 209 | UpgradeLog*.htm 210 | 211 | # SQL Server files 212 | *.mdf 213 | *.ldf 214 | 215 | # Business Intelligence projects 216 | *.rdl.data 217 | *.bim.layout 218 | *.bim_*.settings 219 | 220 | # Microsoft Fakes 221 | FakesAssemblies/ 222 | 223 | # GhostDoc plugin setting file 224 | *.GhostDoc.xml 225 | 226 | # Node.js Tools for Visual Studio 227 | .ntvs_analysis.dat 228 | 229 | # Visual Studio 6 build log 230 | *.plg 231 | 232 | # Visual Studio 6 workspace options file 233 | *.opt 234 | 235 | # Visual Studio LightSwitch build output 236 | **/*.HTMLClient/GeneratedArtifacts 237 | **/*.DesktopClient/GeneratedArtifacts 238 | **/*.DesktopClient/ModelManifest.xml 239 | **/*.Server/GeneratedArtifacts 240 | **/*.Server/ModelManifest.xml 241 | _Pvt_Extensions 242 | 243 | # Paket dependency manager 244 | .paket/paket.exe 245 | paket-files/ 246 | 247 | # FAKE - F# Make 248 | .fake/ 249 | 250 | # JetBrains Rider 251 | .idea/ 252 | *.sln.iml 253 | -------------------------------------------------------------------------------- /Twitch/Twitch.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {4DE6D995-030A-473B-A7B3-FB0E88096FA1} 23 | Win32Proj 24 | Twitch 25 | 10.0.16299.0 26 | 27 | 28 | 29 | Application 30 | true 31 | v141 32 | Unicode 33 | 34 | 35 | Application 36 | false 37 | v141 38 | true 39 | Unicode 40 | 41 | 42 | Application 43 | true 44 | v141 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | v141 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | true 74 | 75 | 76 | true 77 | 78 | 79 | false 80 | 81 | 82 | false 83 | 84 | 85 | 86 | 87 | 88 | Level3 89 | Disabled 90 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 91 | true 92 | 93 | 94 | Console 95 | true 96 | 97 | 98 | 99 | 100 | 101 | 102 | Level3 103 | Disabled 104 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 105 | true 106 | 107 | 108 | Console 109 | true 110 | 111 | 112 | 113 | 114 | Level3 115 | 116 | 117 | MaxSpeed 118 | true 119 | true 120 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 121 | true 122 | 123 | 124 | Console 125 | true 126 | true 127 | true 128 | 129 | 130 | 131 | 132 | Level3 133 | 134 | 135 | MaxSpeed 136 | true 137 | true 138 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 139 | true 140 | 141 | 142 | Console 143 | true 144 | true 145 | true 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 193 | 194 | 195 | 196 | 197 | -------------------------------------------------------------------------------- /Twitch/Engine/Graphics/SOIL/src/image_helper.c: -------------------------------------------------------------------------------- 1 | /* 2 | Jonathan Dummer 3 | 4 | image helper functions 5 | 6 | MIT license 7 | */ 8 | 9 | #include "image_helper.h" 10 | #include 11 | #include 12 | 13 | /* Upscaling the image uses simple bilinear interpolation */ 14 | int 15 | up_scale_image 16 | ( 17 | const unsigned char* const orig, 18 | int width, int height, int channels, 19 | unsigned char* resampled, 20 | int resampled_width, int resampled_height 21 | ) 22 | { 23 | float dx, dy; 24 | int x, y, c; 25 | 26 | /* error(s) check */ 27 | if ( (width < 1) || (height < 1) || 28 | (resampled_width < 2) || (resampled_height < 2) || 29 | (channels < 1) || 30 | (NULL == orig) || (NULL == resampled) ) 31 | { 32 | /* signify badness */ 33 | return 0; 34 | } 35 | /* 36 | for each given pixel in the new map, find the exact location 37 | from the original map which would contribute to this guy 38 | */ 39 | dx = (width - 1.0f) / (resampled_width - 1.0f); 40 | dy = (height - 1.0f) / (resampled_height - 1.0f); 41 | for ( y = 0; y < resampled_height; ++y ) 42 | { 43 | /* find the base y index and fractional offset from that */ 44 | float sampley = y * dy; 45 | int inty = (int)sampley; 46 | /* if( inty < 0 ) { inty = 0; } else */ 47 | if( inty > height - 2 ) { inty = height - 2; } 48 | sampley -= inty; 49 | for ( x = 0; x < resampled_width; ++x ) 50 | { 51 | float samplex = x * dx; 52 | int intx = (int)samplex; 53 | int base_index; 54 | /* find the base x index and fractional offset from that */ 55 | /* if( intx < 0 ) { intx = 0; } else */ 56 | if( intx > width - 2 ) { intx = width - 2; } 57 | samplex -= intx; 58 | /* base index into the original image */ 59 | base_index = (inty * width + intx) * channels; 60 | for ( c = 0; c < channels; ++c ) 61 | { 62 | /* do the sampling */ 63 | float value = 0.5f; 64 | value += orig[base_index] 65 | *(1.0f-samplex)*(1.0f-sampley); 66 | value += orig[base_index+channels] 67 | *(samplex)*(1.0f-sampley); 68 | value += orig[base_index+width*channels] 69 | *(1.0f-samplex)*(sampley); 70 | value += orig[base_index+width*channels+channels] 71 | *(samplex)*(sampley); 72 | /* move to the next channel */ 73 | ++base_index; 74 | /* save the new value */ 75 | resampled[y*resampled_width*channels+x*channels+c] = 76 | (unsigned char)(value); 77 | } 78 | } 79 | } 80 | /* done */ 81 | return 1; 82 | } 83 | 84 | int 85 | mipmap_image 86 | ( 87 | const unsigned char* const orig, 88 | int width, int height, int channels, 89 | unsigned char* resampled, 90 | int block_size_x, int block_size_y 91 | ) 92 | { 93 | int mip_width, mip_height; 94 | int i, j, c; 95 | 96 | /* error check */ 97 | if( (width < 1) || (height < 1) || 98 | (channels < 1) || (orig == NULL) || 99 | (resampled == NULL) || 100 | (block_size_x < 1) || (block_size_y < 1) ) 101 | { 102 | /* nothing to do */ 103 | return 0; 104 | } 105 | mip_width = width / block_size_x; 106 | mip_height = height / block_size_y; 107 | if( mip_width < 1 ) 108 | { 109 | mip_width = 1; 110 | } 111 | if( mip_height < 1 ) 112 | { 113 | mip_height = 1; 114 | } 115 | for( j = 0; j < mip_height; ++j ) 116 | { 117 | for( i = 0; i < mip_width; ++i ) 118 | { 119 | for( c = 0; c < channels; ++c ) 120 | { 121 | const int index = (j*block_size_y)*width*channels + (i*block_size_x)*channels + c; 122 | int sum_value; 123 | int u,v; 124 | int u_block = block_size_x; 125 | int v_block = block_size_y; 126 | int block_area; 127 | /* do a bit of checking so we don't over-run the boundaries 128 | (necessary for non-square textures!) */ 129 | if( block_size_x * (i+1) > width ) 130 | { 131 | u_block = width - i*block_size_y; 132 | } 133 | if( block_size_y * (j+1) > height ) 134 | { 135 | v_block = height - j*block_size_y; 136 | } 137 | block_area = u_block*v_block; 138 | /* for this pixel, see what the average 139 | of all the values in the block are. 140 | note: start the sum at the rounding value, not at 0 */ 141 | sum_value = block_area >> 1; 142 | for( v = 0; v < v_block; ++v ) 143 | for( u = 0; u < u_block; ++u ) 144 | { 145 | sum_value += orig[index + v*width*channels + u*channels]; 146 | } 147 | resampled[j*mip_width*channels + i*channels + c] = sum_value / block_area; 148 | } 149 | } 150 | } 151 | return 1; 152 | } 153 | 154 | int 155 | scale_image_RGB_to_NTSC_safe 156 | ( 157 | unsigned char* orig, 158 | int width, int height, int channels 159 | ) 160 | { 161 | const float scale_lo = 16.0f - 0.499f; 162 | const float scale_hi = 235.0f + 0.499f; 163 | int i, j; 164 | int nc = channels; 165 | unsigned char scale_LUT[256]; 166 | /* error check */ 167 | if( (width < 1) || (height < 1) || 168 | (channels < 1) || (orig == NULL) ) 169 | { 170 | /* nothing to do */ 171 | return 0; 172 | } 173 | /* set up the scaling Look Up Table */ 174 | for( i = 0; i < 256; ++i ) 175 | { 176 | scale_LUT[i] = (unsigned char)((scale_hi - scale_lo) * i / 255.0f + scale_lo); 177 | } 178 | /* for channels = 2 or 4, ignore the alpha component */ 179 | nc -= 1 - (channels & 1); 180 | /* OK, go through the image and scale any non-alpha components */ 181 | for( i = 0; i < width*height*channels; i += channels ) 182 | { 183 | for( j = 0; j < nc; ++j ) 184 | { 185 | orig[i+j] = scale_LUT[orig[i+j]]; 186 | } 187 | } 188 | return 1; 189 | } 190 | 191 | unsigned char clamp_byte( int x ) { return ( (x) < 0 ? (0) : ( (x) > 255 ? 255 : (x) ) ); } 192 | 193 | /* 194 | This function takes the RGB components of the image 195 | and converts them into YCoCg. 3 components will be 196 | re-ordered to CoYCg (for optimum DXT1 compression), 197 | while 4 components will be ordered CoCgAY (for DXT5 198 | compression). 199 | */ 200 | int 201 | convert_RGB_to_YCoCg 202 | ( 203 | unsigned char* orig, 204 | int width, int height, int channels 205 | ) 206 | { 207 | int i; 208 | /* error check */ 209 | if( (width < 1) || (height < 1) || 210 | (channels < 3) || (channels > 4) || 211 | (orig == NULL) ) 212 | { 213 | /* nothing to do */ 214 | return -1; 215 | } 216 | /* do the conversion */ 217 | if( channels == 3 ) 218 | { 219 | for( i = 0; i < width*height*3; i += 3 ) 220 | { 221 | int r = orig[i+0]; 222 | int g = (orig[i+1] + 1) >> 1; 223 | int b = orig[i+2]; 224 | int tmp = (2 + r + b) >> 2; 225 | /* Co */ 226 | orig[i+0] = clamp_byte( 128 + ((r - b + 1) >> 1) ); 227 | /* Y */ 228 | orig[i+1] = clamp_byte( g + tmp ); 229 | /* Cg */ 230 | orig[i+2] = clamp_byte( 128 + g - tmp ); 231 | } 232 | } else 233 | { 234 | for( i = 0; i < width*height*4; i += 4 ) 235 | { 236 | int r = orig[i+0]; 237 | int g = (orig[i+1] + 1) >> 1; 238 | int b = orig[i+2]; 239 | unsigned char a = orig[i+3]; 240 | int tmp = (2 + r + b) >> 2; 241 | /* Co */ 242 | orig[i+0] = clamp_byte( 128 + ((r - b + 1) >> 1) ); 243 | /* Cg */ 244 | orig[i+1] = clamp_byte( 128 + g - tmp ); 245 | /* Alpha */ 246 | orig[i+2] = a; 247 | /* Y */ 248 | orig[i+3] = clamp_byte( g + tmp ); 249 | } 250 | } 251 | /* done */ 252 | return 0; 253 | } 254 | 255 | /* 256 | This function takes the YCoCg components of the image 257 | and converts them into RGB. See above. 258 | */ 259 | int 260 | convert_YCoCg_to_RGB 261 | ( 262 | unsigned char* orig, 263 | int width, int height, int channels 264 | ) 265 | { 266 | int i; 267 | /* error check */ 268 | if( (width < 1) || (height < 1) || 269 | (channels < 3) || (channels > 4) || 270 | (orig == NULL) ) 271 | { 272 | /* nothing to do */ 273 | return -1; 274 | } 275 | /* do the conversion */ 276 | if( channels == 3 ) 277 | { 278 | for( i = 0; i < width*height*3; i += 3 ) 279 | { 280 | int co = orig[i+0] - 128; 281 | int y = orig[i+1]; 282 | int cg = orig[i+2] - 128; 283 | /* R */ 284 | orig[i+0] = clamp_byte( y + co - cg ); 285 | /* G */ 286 | orig[i+1] = clamp_byte( y + cg ); 287 | /* B */ 288 | orig[i+2] = clamp_byte( y - co - cg ); 289 | } 290 | } else 291 | { 292 | for( i = 0; i < width*height*4; i += 4 ) 293 | { 294 | int co = orig[i+0] - 128; 295 | int cg = orig[i+1] - 128; 296 | unsigned char a = orig[i+2]; 297 | int y = orig[i+3]; 298 | /* R */ 299 | orig[i+0] = clamp_byte( y + co - cg ); 300 | /* G */ 301 | orig[i+1] = clamp_byte( y + cg ); 302 | /* B */ 303 | orig[i+2] = clamp_byte( y - co - cg ); 304 | /* A */ 305 | orig[i+3] = a; 306 | } 307 | } 308 | /* done */ 309 | return 0; 310 | } 311 | 312 | float 313 | find_max_RGBE 314 | ( 315 | unsigned char *image, 316 | int width, int height 317 | ) 318 | { 319 | float max_val = 0.0f; 320 | unsigned char *img = image; 321 | int i, j; 322 | for( i = width * height; i > 0; --i ) 323 | { 324 | /* float scale = powf( 2.0f, img[3] - 128.0f ) / 255.0f; */ 325 | float scale = ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 ); 326 | for( j = 0; j < 3; ++j ) 327 | { 328 | if( img[j] * scale > max_val ) 329 | { 330 | max_val = img[j] * scale; 331 | } 332 | } 333 | /* next pixel */ 334 | img += 4; 335 | } 336 | return max_val; 337 | } 338 | 339 | int 340 | RGBE_to_RGBdivA 341 | ( 342 | unsigned char *image, 343 | int width, int height, 344 | int rescale_to_max 345 | ) 346 | { 347 | /* local variables */ 348 | int i, iv; 349 | unsigned char *img = image; 350 | float scale = 1.0f; 351 | /* error check */ 352 | if( (!image) || (width < 1) || (height < 1) ) 353 | { 354 | return 0; 355 | } 356 | /* convert (note: no negative numbers, but 0.0 is possible) */ 357 | if( rescale_to_max ) 358 | { 359 | scale = 255.0f / find_max_RGBE( image, width, height ); 360 | } 361 | for( i = width * height; i > 0; --i ) 362 | { 363 | /* decode this pixel, and find the max */ 364 | float r,g,b,e, m; 365 | /* e = scale * powf( 2.0f, img[3] - 128.0f ) / 255.0f; */ 366 | e = scale * ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 ); 367 | r = e * img[0]; 368 | g = e * img[1]; 369 | b = e * img[2]; 370 | m = (r > g) ? r : g; 371 | m = (b > m) ? b : m; 372 | /* and encode it into RGBdivA */ 373 | iv = (m != 0.0f) ? (int)(255.0f / m) : 1.0f; 374 | iv = (iv < 1) ? 1 : iv; 375 | img[3] = (iv > 255) ? 255 : iv; 376 | iv = (int)(img[3] * r + 0.5f); 377 | img[0] = (iv > 255) ? 255 : iv; 378 | iv = (int)(img[3] * g + 0.5f); 379 | img[1] = (iv > 255) ? 255 : iv; 380 | iv = (int)(img[3] * b + 0.5f); 381 | img[2] = (iv > 255) ? 255 : iv; 382 | /* and on to the next pixel */ 383 | img += 4; 384 | } 385 | return 1; 386 | } 387 | 388 | int 389 | RGBE_to_RGBdivA2 390 | ( 391 | unsigned char *image, 392 | int width, int height, 393 | int rescale_to_max 394 | ) 395 | { 396 | /* local variables */ 397 | int i, iv; 398 | unsigned char *img = image; 399 | float scale = 1.0f; 400 | /* error check */ 401 | if( (!image) || (width < 1) || (height < 1) ) 402 | { 403 | return 0; 404 | } 405 | /* convert (note: no negative numbers, but 0.0 is possible) */ 406 | if( rescale_to_max ) 407 | { 408 | scale = 255.0f * 255.0f / find_max_RGBE( image, width, height ); 409 | } 410 | for( i = width * height; i > 0; --i ) 411 | { 412 | /* decode this pixel, and find the max */ 413 | float r,g,b,e, m; 414 | /* e = scale * powf( 2.0f, img[3] - 128.0f ) / 255.0f; */ 415 | e = scale * ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 ); 416 | r = e * img[0]; 417 | g = e * img[1]; 418 | b = e * img[2]; 419 | m = (r > g) ? r : g; 420 | m = (b > m) ? b : m; 421 | /* and encode it into RGBdivA */ 422 | iv = (m != 0.0f) ? (int)sqrtf( 255.0f * 255.0f / m ) : 1.0f; 423 | iv = (iv < 1) ? 1 : iv; 424 | img[3] = (iv > 255) ? 255 : iv; 425 | iv = (int)(img[3] * img[3] * r / 255.0f + 0.5f); 426 | img[0] = (iv > 255) ? 255 : iv; 427 | iv = (int)(img[3] * img[3] * g / 255.0f + 0.5f); 428 | img[1] = (iv > 255) ? 255 : iv; 429 | iv = (int)(img[3] * img[3] * b / 255.0f + 0.5f); 430 | img[2] = (iv > 255) ? 255 : iv; 431 | /* and on to the next pixel */ 432 | img += 4; 433 | } 434 | return 1; 435 | } 436 | -------------------------------------------------------------------------------- /Twitch/Engine/Graphics/SOIL/src/test_SOIL.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "SOIL.h" 9 | 10 | LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM); 11 | void EnableOpenGL(HWND hwnd, HDC*, HGLRC*); 12 | void DisableOpenGL(HWND, HDC, HGLRC); 13 | 14 | int WINAPI WinMain(HINSTANCE hInstance, 15 | HINSTANCE hPrevInstance, 16 | LPSTR lpCmdLine, 17 | int nCmdShow) 18 | { 19 | WNDCLASSEX wcex; 20 | HWND hwnd; 21 | HDC hDC; 22 | HGLRC hRC; 23 | MSG msg; 24 | BOOL bQuit = FALSE; 25 | float theta = 0.0f; 26 | 27 | // register window class 28 | wcex.cbSize = sizeof(WNDCLASSEX); 29 | wcex.style = CS_OWNDC; 30 | wcex.lpfnWndProc = WindowProc; 31 | wcex.cbClsExtra = 0; 32 | wcex.cbWndExtra = 0; 33 | wcex.hInstance = hInstance; 34 | wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION); 35 | wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 36 | wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); 37 | wcex.lpszMenuName = NULL; 38 | wcex.lpszClassName = "GLSample"; 39 | wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION); 40 | 41 | 42 | if (!RegisterClassEx(&wcex)) 43 | return 0; 44 | 45 | // create main window 46 | hwnd = CreateWindowEx(0, 47 | "GLSample", 48 | "SOIL Sample", 49 | WS_OVERLAPPEDWINDOW, 50 | CW_USEDEFAULT, 51 | CW_USEDEFAULT, 52 | 512, 53 | 512, 54 | NULL, 55 | NULL, 56 | hInstance, 57 | NULL); 58 | 59 | ShowWindow(hwnd, nCmdShow); 60 | 61 | // check my error handling 62 | /* 63 | SOIL_load_OGL_texture( "img_test.png", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, 0 ); 64 | std::cout << "'" << SOIL_last_result() << "'" << std::endl; 65 | */ 66 | 67 | 68 | // enable OpenGL for the window 69 | EnableOpenGL(hwnd, &hDC, &hRC); 70 | 71 | glEnable( GL_BLEND ); 72 | //glDisable( GL_BLEND ); 73 | // straight alpha 74 | glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); 75 | // premultiplied alpha (remember to do the same in glColor!!) 76 | //glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA ); 77 | 78 | // do I want alpha thresholding? 79 | glEnable( GL_ALPHA_TEST ); 80 | glAlphaFunc( GL_GREATER, 0.5f ); 81 | 82 | // log what the use is asking us to load 83 | std::string load_me = lpCmdLine; 84 | if( load_me.length() > 2 ) 85 | { 86 | //load_me = load_me.substr( 1, load_me.length() - 2 ); 87 | load_me = load_me.substr( 0, load_me.length() - 0 ); 88 | } else 89 | { 90 | //load_me = "img_test_uncompressed.dds"; 91 | //load_me = "img_test_indexed.tga"; 92 | //load_me = "img_test.dds"; 93 | load_me = "img_test.png"; 94 | //load_me = "odd_size.jpg"; 95 | //load_me = "img_cheryl.jpg"; 96 | //load_me = "oak_odd.png"; 97 | //load_me = "field_128_cube.dds"; 98 | //load_me = "field_128_cube_nomip.dds"; 99 | //load_me = "field_128_cube_uc.dds"; 100 | //load_me = "field_128_cube_uc_nomip.dds"; 101 | //load_me = "Goblin.dds"; 102 | //load_me = "parquet.dds"; 103 | //load_me = "stpeters_probe.hdr"; 104 | //load_me = "VeraMoBI_sdf.png"; 105 | 106 | // for testing the texture rectangle code 107 | //load_me = "test_rect.png"; 108 | } 109 | std::cout << "'" << load_me << "'" << std::endl; 110 | 111 | // 1st try to load it as a single-image-cubemap 112 | // (note, need DDS ordered faces: "EWUDNS") 113 | GLuint tex_ID; 114 | int time_me; 115 | 116 | std::cout << "Attempting to load as a cubemap" << std::endl; 117 | time_me = clock(); 118 | tex_ID = SOIL_load_OGL_single_cubemap( 119 | load_me.c_str(), 120 | SOIL_DDS_CUBEMAP_FACE_ORDER, 121 | SOIL_LOAD_AUTO, 122 | SOIL_CREATE_NEW_ID, 123 | SOIL_FLAG_POWER_OF_TWO 124 | | SOIL_FLAG_MIPMAPS 125 | //| SOIL_FLAG_COMPRESS_TO_DXT 126 | //| SOIL_FLAG_TEXTURE_REPEATS 127 | //| SOIL_FLAG_INVERT_Y 128 | | SOIL_FLAG_DDS_LOAD_DIRECT 129 | ); 130 | time_me = clock() - time_me; 131 | std::cout << "the load time was " << 0.001f * time_me << " seconds (warning: low resolution timer)" << std::endl; 132 | if( tex_ID > 0 ) 133 | { 134 | glEnable( GL_TEXTURE_CUBE_MAP ); 135 | glEnable( GL_TEXTURE_GEN_S ); 136 | glEnable( GL_TEXTURE_GEN_T ); 137 | glEnable( GL_TEXTURE_GEN_R ); 138 | glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP ); 139 | glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP ); 140 | glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP ); 141 | glBindTexture( GL_TEXTURE_CUBE_MAP, tex_ID ); 142 | // report 143 | std::cout << "the loaded single cube map ID was " << tex_ID << std::endl; 144 | //std::cout << "the load time was " << 0.001f * time_me << " seconds (warning: low resolution timer)" << std::endl; 145 | } else 146 | { 147 | std::cout << "Attempting to load as a HDR texture" << std::endl; 148 | time_me = clock(); 149 | tex_ID = SOIL_load_OGL_HDR_texture( 150 | load_me.c_str(), 151 | //SOIL_HDR_RGBE, 152 | //SOIL_HDR_RGBdivA, 153 | SOIL_HDR_RGBdivA2, 154 | 0, 155 | SOIL_CREATE_NEW_ID, 156 | SOIL_FLAG_POWER_OF_TWO 157 | | SOIL_FLAG_MIPMAPS 158 | //| SOIL_FLAG_COMPRESS_TO_DXT 159 | ); 160 | time_me = clock() - time_me; 161 | std::cout << "the load time was " << 0.001f * time_me << " seconds (warning: low resolution timer)" << std::endl; 162 | 163 | // did I fail? 164 | if( tex_ID < 1 ) 165 | { 166 | // loading of the single-image-cubemap failed, try it as a simple texture 167 | std::cout << "Attempting to load as a simple 2D texture" << std::endl; 168 | // load the texture, if specified 169 | time_me = clock(); 170 | tex_ID = SOIL_load_OGL_texture( 171 | load_me.c_str(), 172 | SOIL_LOAD_AUTO, 173 | SOIL_CREATE_NEW_ID, 174 | SOIL_FLAG_POWER_OF_TWO 175 | | SOIL_FLAG_MIPMAPS 176 | //| SOIL_FLAG_MULTIPLY_ALPHA 177 | //| SOIL_FLAG_COMPRESS_TO_DXT 178 | | SOIL_FLAG_DDS_LOAD_DIRECT 179 | //| SOIL_FLAG_NTSC_SAFE_RGB 180 | //| SOIL_FLAG_CoCg_Y 181 | //| SOIL_FLAG_TEXTURE_RECTANGLE 182 | ); 183 | time_me = clock() - time_me; 184 | std::cout << "the load time was " << 0.001f * time_me << " seconds (warning: low resolution timer)" << std::endl; 185 | } 186 | 187 | if( tex_ID > 0 ) 188 | { 189 | // enable texturing 190 | glEnable( GL_TEXTURE_2D ); 191 | //glEnable( 0x84F5 );// enables texture rectangle 192 | // bind an OpenGL texture ID 193 | glBindTexture( GL_TEXTURE_2D, tex_ID ); 194 | // report 195 | std::cout << "the loaded texture ID was " << tex_ID << std::endl; 196 | //std::cout << "the load time was " << 0.001f * time_me << " seconds (warning: low resolution timer)" << std::endl; 197 | } else 198 | { 199 | // loading of the texture failed...why? 200 | glDisable( GL_TEXTURE_2D ); 201 | std::cout << "Texture loading failed: '" << SOIL_last_result() << "'" << std::endl; 202 | } 203 | } 204 | 205 | // program main loop 206 | const float ref_mag = 0.1f; 207 | while (!bQuit) 208 | { 209 | // check for messages 210 | if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 211 | { 212 | // handle or dispatch messages 213 | if (msg.message == WM_QUIT) 214 | { 215 | bQuit = TRUE; 216 | } 217 | else 218 | { 219 | TranslateMessage(&msg); 220 | DispatchMessage(&msg); 221 | } 222 | } 223 | else 224 | { 225 | // OpenGL animation code goes here 226 | theta = clock() * 0.1; 227 | 228 | float tex_u_max = 1.0f;//0.2f; 229 | float tex_v_max = 1.0f;//0.2f; 230 | 231 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 232 | glClear(GL_COLOR_BUFFER_BIT); 233 | 234 | glPushMatrix(); 235 | glScalef( 0.8f, 0.8f, 0.8f ); 236 | //glRotatef(-0.314159f*theta, 0.0f, 0.0f, 1.0f); 237 | glColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); 238 | glNormal3f( 0.0f, 0.0f, 1.0f ); 239 | glBegin(GL_QUADS); 240 | glNormal3f( -ref_mag, -ref_mag, 1.0f ); 241 | glTexCoord2f( 0.0f, tex_v_max ); 242 | glVertex3f( -1.0f, -1.0f, -0.1f ); 243 | 244 | glNormal3f( ref_mag, -ref_mag, 1.0f ); 245 | glTexCoord2f( tex_u_max, tex_v_max ); 246 | glVertex3f( 1.0f, -1.0f, -0.1f ); 247 | 248 | glNormal3f( ref_mag, ref_mag, 1.0f ); 249 | glTexCoord2f( tex_u_max, 0.0f ); 250 | glVertex3f( 1.0f, 1.0f, -0.1f ); 251 | 252 | glNormal3f( -ref_mag, ref_mag, 1.0f ); 253 | glTexCoord2f( 0.0f, 0.0f ); 254 | glVertex3f( -1.0f, 1.0f, -0.1f ); 255 | glEnd(); 256 | glPopMatrix(); 257 | 258 | tex_u_max = 1.0f; 259 | tex_v_max = 1.0f; 260 | glPushMatrix(); 261 | glScalef( 0.8f, 0.8f, 0.8f ); 262 | glRotatef(theta, 0.0f, 0.0f, 1.0f); 263 | glColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); 264 | glNormal3f( 0.0f, 0.0f, 1.0f ); 265 | glBegin(GL_QUADS); 266 | glTexCoord2f( 0.0f, tex_v_max ); glVertex3f( 0.0f, 0.0f, 0.1f ); 267 | glTexCoord2f( tex_u_max, tex_v_max ); glVertex3f( 1.0f, 0.0f, 0.1f ); 268 | glTexCoord2f( tex_u_max, 0.0f ); glVertex3f( 1.0f, 1.0f, 0.1f ); 269 | glTexCoord2f( 0.0f, 0.0f ); glVertex3f( 0.0f, 1.0f, 0.1f ); 270 | glEnd(); 271 | glPopMatrix(); 272 | 273 | { 274 | /* check for errors */ 275 | GLenum err_code = glGetError(); 276 | while( GL_NO_ERROR != err_code ) 277 | { 278 | printf( "OpenGL Error @ %s: %i", "drawing loop", err_code ); 279 | err_code = glGetError(); 280 | } 281 | } 282 | 283 | SwapBuffers(hDC); 284 | 285 | Sleep (1); 286 | } 287 | } 288 | 289 | // and show off the screenshot capability 290 | /* 291 | load_me += "-screenshot.tga"; 292 | SOIL_save_screenshot( load_me.c_str(), SOIL_SAVE_TYPE_TGA, 0, 0, 512, 512 ); 293 | //*/ 294 | //* 295 | load_me += "-screenshot.bmp"; 296 | SOIL_save_screenshot( load_me.c_str(), SOIL_SAVE_TYPE_BMP, 0, 0, 512, 512 ); 297 | //*/ 298 | /* 299 | load_me += "-screenshot.dds"; 300 | SOIL_save_screenshot( load_me.c_str(), SOIL_SAVE_TYPE_DDS, 0, 0, 512, 512 ); 301 | //*/ 302 | 303 | // shutdown OpenGL 304 | DisableOpenGL(hwnd, hDC, hRC); 305 | 306 | // destroy the window explicitly 307 | DestroyWindow(hwnd); 308 | 309 | return msg.wParam; 310 | } 311 | 312 | LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 313 | { 314 | switch (uMsg) 315 | { 316 | case WM_CLOSE: 317 | PostQuitMessage(0); 318 | break; 319 | 320 | case WM_DESTROY: 321 | return 0; 322 | 323 | case WM_KEYDOWN: 324 | { 325 | switch (wParam) 326 | { 327 | case VK_ESCAPE: 328 | PostQuitMessage(0); 329 | break; 330 | } 331 | } 332 | break; 333 | 334 | default: 335 | return DefWindowProc(hwnd, uMsg, wParam, lParam); 336 | } 337 | 338 | return 0; 339 | } 340 | 341 | void EnableOpenGL(HWND hwnd, HDC* hDC, HGLRC* hRC) 342 | { 343 | PIXELFORMATDESCRIPTOR pfd; 344 | 345 | int iFormat; 346 | 347 | /* get the device context (DC) */ 348 | *hDC = GetDC(hwnd); 349 | 350 | /* set the pixel format for the DC */ 351 | ZeroMemory(&pfd, sizeof(pfd)); 352 | 353 | pfd.nSize = sizeof(pfd); 354 | pfd.nVersion = 1; 355 | pfd.dwFlags = PFD_DRAW_TO_WINDOW | 356 | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; 357 | pfd.iPixelType = PFD_TYPE_RGBA; 358 | pfd.cColorBits = 24; 359 | pfd.cDepthBits = 16; 360 | pfd.iLayerType = PFD_MAIN_PLANE; 361 | 362 | iFormat = ChoosePixelFormat(*hDC, &pfd); 363 | 364 | SetPixelFormat(*hDC, iFormat, &pfd); 365 | 366 | /* create and enable the render context (RC) */ 367 | *hRC = wglCreateContext(*hDC); 368 | 369 | wglMakeCurrent(*hDC, *hRC); 370 | } 371 | 372 | void DisableOpenGL (HWND hwnd, HDC hDC, HGLRC hRC) 373 | { 374 | wglMakeCurrent(NULL, NULL); 375 | wglDeleteContext(hRC); 376 | ReleaseDC(hwnd, hDC); 377 | } 378 | 379 | -------------------------------------------------------------------------------- /Twitch/Engine/Graphics/SOIL/src/SOIL.h: -------------------------------------------------------------------------------- 1 | /** 2 | @mainpage SOIL 3 | 4 | Jonathan Dummer 5 | 2007-07-26-10.36 6 | 7 | Simple OpenGL Image Library 8 | 9 | A tiny c library for uploading images as 10 | textures into OpenGL. Also saving and 11 | loading of images is supported. 12 | 13 | I'm using Sean's Tool Box image loader as a base: 14 | http://www.nothings.org/ 15 | 16 | I'm upgrading it to load TGA and DDS files, and a direct 17 | path for loading DDS files straight into OpenGL textures, 18 | when applicable. 19 | 20 | Image Formats: 21 | - BMP load & save 22 | - TGA load & save 23 | - DDS load & save 24 | - PNG load 25 | - JPG load 26 | 27 | OpenGL Texture Features: 28 | - resample to power-of-two sizes 29 | - MIPmap generation 30 | - compressed texture S3TC formats (if supported) 31 | - can pre-multiply alpha for you, for better compositing 32 | - can flip image about the y-axis (except pre-compressed DDS files) 33 | 34 | Thanks to: 35 | * Sean Barret - for the awesome stb_image 36 | * Dan Venkitachalam - for finding some non-compliant DDS files, and patching some explicit casts 37 | * everybody at gamedev.net 38 | **/ 39 | 40 | #ifndef HEADER_SIMPLE_OPENGL_IMAGE_LIBRARY 41 | #define HEADER_SIMPLE_OPENGL_IMAGE_LIBRARY 42 | 43 | #ifdef __cplusplus 44 | extern "C" { 45 | #endif 46 | 47 | /** 48 | The format of images that may be loaded (force_channels). 49 | SOIL_LOAD_AUTO leaves the image in whatever format it was found. 50 | SOIL_LOAD_L forces the image to load as Luminous (greyscale) 51 | SOIL_LOAD_LA forces the image to load as Luminous with Alpha 52 | SOIL_LOAD_RGB forces the image to load as Red Green Blue 53 | SOIL_LOAD_RGBA forces the image to load as Red Green Blue Alpha 54 | **/ 55 | enum 56 | { 57 | SOIL_LOAD_AUTO = 0, 58 | SOIL_LOAD_L = 1, 59 | SOIL_LOAD_LA = 2, 60 | SOIL_LOAD_RGB = 3, 61 | SOIL_LOAD_RGBA = 4 62 | }; 63 | 64 | /** 65 | Passed in as reuse_texture_ID, will cause SOIL to 66 | register a new texture ID using glGenTextures(). 67 | If the value passed into reuse_texture_ID > 0 then 68 | SOIL will just re-use that texture ID (great for 69 | reloading image assets in-game!) 70 | **/ 71 | enum 72 | { 73 | SOIL_CREATE_NEW_ID = 0 74 | }; 75 | 76 | /** 77 | flags you can pass into SOIL_load_OGL_texture() 78 | and SOIL_create_OGL_texture(). 79 | (note that if SOIL_FLAG_DDS_LOAD_DIRECT is used 80 | the rest of the flags with the exception of 81 | SOIL_FLAG_TEXTURE_REPEATS will be ignored while 82 | loading already-compressed DDS files.) 83 | 84 | SOIL_FLAG_POWER_OF_TWO: force the image to be POT 85 | SOIL_FLAG_MIPMAPS: generate mipmaps for the texture 86 | SOIL_FLAG_TEXTURE_REPEATS: otherwise will clamp 87 | SOIL_FLAG_MULTIPLY_ALPHA: for using (GL_ONE,GL_ONE_MINUS_SRC_ALPHA) blending 88 | SOIL_FLAG_INVERT_Y: flip the image vertically 89 | SOIL_FLAG_COMPRESS_TO_DXT: if the card can display them, will convert RGB to DXT1, RGBA to DXT5 90 | SOIL_FLAG_DDS_LOAD_DIRECT: will load DDS files directly without _ANY_ additional processing 91 | SOIL_FLAG_NTSC_SAFE_RGB: clamps RGB components to the range [16,235] 92 | SOIL_FLAG_CoCg_Y: Google YCoCg; RGB=>CoYCg, RGBA=>CoCgAY 93 | SOIL_FLAG_TEXTURE_RECTANGE: uses ARB_texture_rectangle ; pixel indexed & no repeat or MIPmaps or cubemaps 94 | **/ 95 | enum 96 | { 97 | SOIL_FLAG_POWER_OF_TWO = 1, 98 | SOIL_FLAG_MIPMAPS = 2, 99 | SOIL_FLAG_TEXTURE_REPEATS = 4, 100 | SOIL_FLAG_MULTIPLY_ALPHA = 8, 101 | SOIL_FLAG_INVERT_Y = 16, 102 | SOIL_FLAG_COMPRESS_TO_DXT = 32, 103 | SOIL_FLAG_DDS_LOAD_DIRECT = 64, 104 | SOIL_FLAG_NTSC_SAFE_RGB = 128, 105 | SOIL_FLAG_CoCg_Y = 256, 106 | SOIL_FLAG_TEXTURE_RECTANGLE = 512 107 | }; 108 | 109 | /** 110 | The types of images that may be saved. 111 | (TGA supports uncompressed RGB / RGBA) 112 | (BMP supports uncompressed RGB) 113 | (DDS supports DXT1 and DXT5) 114 | **/ 115 | enum 116 | { 117 | SOIL_SAVE_TYPE_TGA = 0, 118 | SOIL_SAVE_TYPE_BMP = 1, 119 | SOIL_SAVE_TYPE_DDS = 2 120 | }; 121 | 122 | /** 123 | Defines the order of faces in a DDS cubemap. 124 | I recommend that you use the same order in single 125 | image cubemap files, so they will be interchangeable 126 | with DDS cubemaps when using SOIL. 127 | **/ 128 | #define SOIL_DDS_CUBEMAP_FACE_ORDER "EWUDNS" 129 | 130 | /** 131 | The types of internal fake HDR representations 132 | 133 | SOIL_HDR_RGBE: RGB * pow( 2.0, A - 128.0 ) 134 | SOIL_HDR_RGBdivA: RGB / A 135 | SOIL_HDR_RGBdivA2: RGB / (A*A) 136 | **/ 137 | enum 138 | { 139 | SOIL_HDR_RGBE = 0, 140 | SOIL_HDR_RGBdivA = 1, 141 | SOIL_HDR_RGBdivA2 = 2 142 | }; 143 | 144 | /** 145 | Loads an image from disk into an OpenGL texture. 146 | \param filename the name of the file to upload as a texture 147 | \param force_channels 0-image format, 1-luminous, 2-luminous/alpha, 3-RGB, 4-RGBA 148 | \param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture) 149 | \param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_DDS_LOAD_DIRECT 150 | \return 0-failed, otherwise returns the OpenGL texture handle 151 | **/ 152 | unsigned int 153 | SOIL_load_OGL_texture 154 | ( 155 | const char *filename, 156 | int force_channels, 157 | unsigned int reuse_texture_ID, 158 | unsigned int flags 159 | ); 160 | 161 | /** 162 | Loads 6 images from disk into an OpenGL cubemap texture. 163 | \param x_pos_file the name of the file to upload as the +x cube face 164 | \param x_neg_file the name of the file to upload as the -x cube face 165 | \param y_pos_file the name of the file to upload as the +y cube face 166 | \param y_neg_file the name of the file to upload as the -y cube face 167 | \param z_pos_file the name of the file to upload as the +z cube face 168 | \param z_neg_file the name of the file to upload as the -z cube face 169 | \param force_channels 0-image format, 1-luminous, 2-luminous/alpha, 3-RGB, 4-RGBA 170 | \param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture) 171 | \param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_DDS_LOAD_DIRECT 172 | \return 0-failed, otherwise returns the OpenGL texture handle 173 | **/ 174 | unsigned int 175 | SOIL_load_OGL_cubemap 176 | ( 177 | const char *x_pos_file, 178 | const char *x_neg_file, 179 | const char *y_pos_file, 180 | const char *y_neg_file, 181 | const char *z_pos_file, 182 | const char *z_neg_file, 183 | int force_channels, 184 | unsigned int reuse_texture_ID, 185 | unsigned int flags 186 | ); 187 | 188 | /** 189 | Loads 1 image from disk and splits it into an OpenGL cubemap texture. 190 | \param filename the name of the file to upload as a texture 191 | \param face_order the order of the faces in the file, any combination of NSWEUD, for North, South, Up, etc. 192 | \param force_channels 0-image format, 1-luminous, 2-luminous/alpha, 3-RGB, 4-RGBA 193 | \param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture) 194 | \param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_DDS_LOAD_DIRECT 195 | \return 0-failed, otherwise returns the OpenGL texture handle 196 | **/ 197 | unsigned int 198 | SOIL_load_OGL_single_cubemap 199 | ( 200 | const char *filename, 201 | const char face_order[6], 202 | int force_channels, 203 | unsigned int reuse_texture_ID, 204 | unsigned int flags 205 | ); 206 | 207 | /** 208 | Loads an HDR image from disk into an OpenGL texture. 209 | \param filename the name of the file to upload as a texture 210 | \param fake_HDR_format SOIL_HDR_RGBE, SOIL_HDR_RGBdivA, SOIL_HDR_RGBdivA2 211 | \param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture) 212 | \param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT 213 | \return 0-failed, otherwise returns the OpenGL texture handle 214 | **/ 215 | unsigned int 216 | SOIL_load_OGL_HDR_texture 217 | ( 218 | const char *filename, 219 | int fake_HDR_format, 220 | int rescale_to_max, 221 | unsigned int reuse_texture_ID, 222 | unsigned int flags 223 | ); 224 | 225 | /** 226 | Loads an image from RAM into an OpenGL texture. 227 | \param buffer the image data in RAM just as if it were still in a file 228 | \param buffer_length the size of the buffer in bytes 229 | \param force_channels 0-image format, 1-luminous, 2-luminous/alpha, 3-RGB, 4-RGBA 230 | \param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture) 231 | \param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_DDS_LOAD_DIRECT 232 | \return 0-failed, otherwise returns the OpenGL texture handle 233 | **/ 234 | unsigned int 235 | SOIL_load_OGL_texture_from_memory 236 | ( 237 | const unsigned char *const buffer, 238 | int buffer_length, 239 | int force_channels, 240 | unsigned int reuse_texture_ID, 241 | unsigned int flags 242 | ); 243 | 244 | /** 245 | Loads 6 images from memory into an OpenGL cubemap texture. 246 | \param x_pos_buffer the image data in RAM to upload as the +x cube face 247 | \param x_pos_buffer_length the size of the above buffer 248 | \param x_neg_buffer the image data in RAM to upload as the +x cube face 249 | \param x_neg_buffer_length the size of the above buffer 250 | \param y_pos_buffer the image data in RAM to upload as the +x cube face 251 | \param y_pos_buffer_length the size of the above buffer 252 | \param y_neg_buffer the image data in RAM to upload as the +x cube face 253 | \param y_neg_buffer_length the size of the above buffer 254 | \param z_pos_buffer the image data in RAM to upload as the +x cube face 255 | \param z_pos_buffer_length the size of the above buffer 256 | \param z_neg_buffer the image data in RAM to upload as the +x cube face 257 | \param z_neg_buffer_length the size of the above buffer 258 | \param force_channels 0-image format, 1-luminous, 2-luminous/alpha, 3-RGB, 4-RGBA 259 | \param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture) 260 | \param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_DDS_LOAD_DIRECT 261 | \return 0-failed, otherwise returns the OpenGL texture handle 262 | **/ 263 | unsigned int 264 | SOIL_load_OGL_cubemap_from_memory 265 | ( 266 | const unsigned char *const x_pos_buffer, 267 | int x_pos_buffer_length, 268 | const unsigned char *const x_neg_buffer, 269 | int x_neg_buffer_length, 270 | const unsigned char *const y_pos_buffer, 271 | int y_pos_buffer_length, 272 | const unsigned char *const y_neg_buffer, 273 | int y_neg_buffer_length, 274 | const unsigned char *const z_pos_buffer, 275 | int z_pos_buffer_length, 276 | const unsigned char *const z_neg_buffer, 277 | int z_neg_buffer_length, 278 | int force_channels, 279 | unsigned int reuse_texture_ID, 280 | unsigned int flags 281 | ); 282 | 283 | /** 284 | Loads 1 image from RAM and splits it into an OpenGL cubemap texture. 285 | \param buffer the image data in RAM just as if it were still in a file 286 | \param buffer_length the size of the buffer in bytes 287 | \param face_order the order of the faces in the file, any combination of NSWEUD, for North, South, Up, etc. 288 | \param force_channels 0-image format, 1-luminous, 2-luminous/alpha, 3-RGB, 4-RGBA 289 | \param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture) 290 | \param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_DDS_LOAD_DIRECT 291 | \return 0-failed, otherwise returns the OpenGL texture handle 292 | **/ 293 | unsigned int 294 | SOIL_load_OGL_single_cubemap_from_memory 295 | ( 296 | const unsigned char *const buffer, 297 | int buffer_length, 298 | const char face_order[6], 299 | int force_channels, 300 | unsigned int reuse_texture_ID, 301 | unsigned int flags 302 | ); 303 | 304 | /** 305 | Creates a 2D OpenGL texture from raw image data. Note that the raw data is 306 | _NOT_ freed after the upload (so the user can load various versions). 307 | \param data the raw data to be uploaded as an OpenGL texture 308 | \param width the width of the image in pixels 309 | \param height the height of the image in pixels 310 | \param channels the number of channels: 1-luminous, 2-luminous/alpha, 3-RGB, 4-RGBA 311 | \param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture) 312 | \param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT 313 | \return 0-failed, otherwise returns the OpenGL texture handle 314 | **/ 315 | unsigned int 316 | SOIL_create_OGL_texture 317 | ( 318 | const unsigned char *const data, 319 | int width, int height, int channels, 320 | unsigned int reuse_texture_ID, 321 | unsigned int flags 322 | ); 323 | 324 | /** 325 | Creates an OpenGL cubemap texture by splitting up 1 image into 6 parts. 326 | \param data the raw data to be uploaded as an OpenGL texture 327 | \param width the width of the image in pixels 328 | \param height the height of the image in pixels 329 | \param channels the number of channels: 1-luminous, 2-luminous/alpha, 3-RGB, 4-RGBA 330 | \param face_order the order of the faces in the file, and combination of NSWEUD, for North, South, Up, etc. 331 | \param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture) 332 | \param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_DDS_LOAD_DIRECT 333 | \return 0-failed, otherwise returns the OpenGL texture handle 334 | **/ 335 | unsigned int 336 | SOIL_create_OGL_single_cubemap 337 | ( 338 | const unsigned char *const data, 339 | int width, int height, int channels, 340 | const char face_order[6], 341 | unsigned int reuse_texture_ID, 342 | unsigned int flags 343 | ); 344 | 345 | /** 346 | Captures the OpenGL window (RGB) and saves it to disk 347 | \return 0 if it failed, otherwise returns 1 348 | **/ 349 | int 350 | SOIL_save_screenshot 351 | ( 352 | const char *filename, 353 | int image_type, 354 | int x, int y, 355 | int width, int height 356 | ); 357 | 358 | /** 359 | Loads an image from disk into an array of unsigned chars. 360 | Note that *channels return the original channel count of the 361 | image. If force_channels was other than SOIL_LOAD_AUTO, 362 | the resulting image has force_channels, but *channels may be 363 | different (if the original image had a different channel 364 | count). 365 | \return 0 if failed, otherwise returns 1 366 | **/ 367 | unsigned char* 368 | SOIL_load_image 369 | ( 370 | const char *filename, 371 | int *width, int *height, int *channels, 372 | int force_channels 373 | ); 374 | 375 | /** 376 | Loads an image from memory into an array of unsigned chars. 377 | Note that *channels return the original channel count of the 378 | image. If force_channels was other than SOIL_LOAD_AUTO, 379 | the resulting image has force_channels, but *channels may be 380 | different (if the original image had a different channel 381 | count). 382 | \return 0 if failed, otherwise returns 1 383 | **/ 384 | unsigned char* 385 | SOIL_load_image_from_memory 386 | ( 387 | const unsigned char *const buffer, 388 | int buffer_length, 389 | int *width, int *height, int *channels, 390 | int force_channels 391 | ); 392 | 393 | /** 394 | Saves an image from an array of unsigned chars (RGBA) to disk 395 | \return 0 if failed, otherwise returns 1 396 | **/ 397 | int 398 | SOIL_save_image 399 | ( 400 | const char *filename, 401 | int image_type, 402 | int width, int height, int channels, 403 | const unsigned char *const data 404 | ); 405 | 406 | /** 407 | Frees the image data (note, this is just C's "free()"...this function is 408 | present mostly so C++ programmers don't forget to use "free()" and call 409 | "delete []" instead [8^) 410 | **/ 411 | void 412 | SOIL_free_image_data 413 | ( 414 | unsigned char *img_data 415 | ); 416 | 417 | /** 418 | This function resturn a pointer to a string describing the last thing 419 | that happened inside SOIL. It can be used to determine why an image 420 | failed to load. 421 | **/ 422 | const char* 423 | SOIL_last_result 424 | ( 425 | void 426 | ); 427 | 428 | 429 | #ifdef __cplusplus 430 | } 431 | #endif 432 | 433 | #endif /* HEADER_SIMPLE_OPENGL_IMAGE_LIBRARY */ 434 | -------------------------------------------------------------------------------- /Twitch/Engine/Graphics/SOIL/src/stbi_DDS_aug_c.h: -------------------------------------------------------------------------------- 1 | 2 | /// DDS file support, does decoding, _not_ direct uploading 3 | /// (use SOIL for that ;-) 4 | 5 | /// A bunch of DirectDraw Surface structures and flags 6 | typedef struct { 7 | unsigned int dwMagic; 8 | unsigned int dwSize; 9 | unsigned int dwFlags; 10 | unsigned int dwHeight; 11 | unsigned int dwWidth; 12 | unsigned int dwPitchOrLinearSize; 13 | unsigned int dwDepth; 14 | unsigned int dwMipMapCount; 15 | unsigned int dwReserved1[ 11 ]; 16 | 17 | // DDPIXELFORMAT 18 | struct { 19 | unsigned int dwSize; 20 | unsigned int dwFlags; 21 | unsigned int dwFourCC; 22 | unsigned int dwRGBBitCount; 23 | unsigned int dwRBitMask; 24 | unsigned int dwGBitMask; 25 | unsigned int dwBBitMask; 26 | unsigned int dwAlphaBitMask; 27 | } sPixelFormat; 28 | 29 | // DDCAPS2 30 | struct { 31 | unsigned int dwCaps1; 32 | unsigned int dwCaps2; 33 | unsigned int dwDDSX; 34 | unsigned int dwReserved; 35 | } sCaps; 36 | unsigned int dwReserved2; 37 | } DDS_header ; 38 | 39 | // the following constants were copied directly off the MSDN website 40 | 41 | // The dwFlags member of the original DDSURFACEDESC2 structure 42 | // can be set to one or more of the following values. 43 | #define DDSD_CAPS 0x00000001 44 | #define DDSD_HEIGHT 0x00000002 45 | #define DDSD_WIDTH 0x00000004 46 | #define DDSD_PITCH 0x00000008 47 | #define DDSD_PIXELFORMAT 0x00001000 48 | #define DDSD_MIPMAPCOUNT 0x00020000 49 | #define DDSD_LINEARSIZE 0x00080000 50 | #define DDSD_DEPTH 0x00800000 51 | 52 | // DirectDraw Pixel Format 53 | #define DDPF_ALPHAPIXELS 0x00000001 54 | #define DDPF_FOURCC 0x00000004 55 | #define DDPF_RGB 0x00000040 56 | 57 | // The dwCaps1 member of the DDSCAPS2 structure can be 58 | // set to one or more of the following values. 59 | #define DDSCAPS_COMPLEX 0x00000008 60 | #define DDSCAPS_TEXTURE 0x00001000 61 | #define DDSCAPS_MIPMAP 0x00400000 62 | 63 | // The dwCaps2 member of the DDSCAPS2 structure can be 64 | // set to one or more of the following values. 65 | #define DDSCAPS2_CUBEMAP 0x00000200 66 | #define DDSCAPS2_CUBEMAP_POSITIVEX 0x00000400 67 | #define DDSCAPS2_CUBEMAP_NEGATIVEX 0x00000800 68 | #define DDSCAPS2_CUBEMAP_POSITIVEY 0x00001000 69 | #define DDSCAPS2_CUBEMAP_NEGATIVEY 0x00002000 70 | #define DDSCAPS2_CUBEMAP_POSITIVEZ 0x00004000 71 | #define DDSCAPS2_CUBEMAP_NEGATIVEZ 0x00008000 72 | #define DDSCAPS2_VOLUME 0x00200000 73 | 74 | static int dds_test(stbi *s) 75 | { 76 | // check the magic number 77 | if (get8(s) != 'D') return 0; 78 | if (get8(s) != 'D') return 0; 79 | if (get8(s) != 'S') return 0; 80 | if (get8(s) != ' ') return 0; 81 | // check header size 82 | if (get32le(s) != 124) return 0; 83 | return 1; 84 | } 85 | #ifndef STBI_NO_STDIO 86 | int stbi_dds_test_file (FILE *f) 87 | { 88 | stbi s; 89 | int r,n = ftell(f); 90 | start_file(&s,f); 91 | r = dds_test(&s); 92 | fseek(f,n,SEEK_SET); 93 | return r; 94 | } 95 | #endif 96 | 97 | int stbi_dds_test_memory (stbi_uc const *buffer, int len) 98 | { 99 | stbi s; 100 | start_mem(&s,buffer, len); 101 | return dds_test(&s); 102 | } 103 | 104 | // helper functions 105 | int stbi_convert_bit_range( int c, int from_bits, int to_bits ) 106 | { 107 | int b = (1 << (from_bits - 1)) + c * ((1 << to_bits) - 1); 108 | return (b + (b >> from_bits)) >> from_bits; 109 | } 110 | void stbi_rgb_888_from_565( unsigned int c, int *r, int *g, int *b ) 111 | { 112 | *r = stbi_convert_bit_range( (c >> 11) & 31, 5, 8 ); 113 | *g = stbi_convert_bit_range( (c >> 05) & 63, 6, 8 ); 114 | *b = stbi_convert_bit_range( (c >> 00) & 31, 5, 8 ); 115 | } 116 | void stbi_decode_DXT1_block( 117 | unsigned char uncompressed[16*4], 118 | unsigned char compressed[8] ) 119 | { 120 | int next_bit = 4*8; 121 | int i, r, g, b; 122 | int c0, c1; 123 | unsigned char decode_colors[4*4]; 124 | // find the 2 primary colors 125 | c0 = compressed[0] + (compressed[1] << 8); 126 | c1 = compressed[2] + (compressed[3] << 8); 127 | stbi_rgb_888_from_565( c0, &r, &g, &b ); 128 | decode_colors[0] = r; 129 | decode_colors[1] = g; 130 | decode_colors[2] = b; 131 | decode_colors[3] = 255; 132 | stbi_rgb_888_from_565( c1, &r, &g, &b ); 133 | decode_colors[4] = r; 134 | decode_colors[5] = g; 135 | decode_colors[6] = b; 136 | decode_colors[7] = 255; 137 | if( c0 > c1 ) 138 | { 139 | // no alpha, 2 interpolated colors 140 | decode_colors[8] = (2*decode_colors[0] + decode_colors[4]) / 3; 141 | decode_colors[9] = (2*decode_colors[1] + decode_colors[5]) / 3; 142 | decode_colors[10] = (2*decode_colors[2] + decode_colors[6]) / 3; 143 | decode_colors[11] = 255; 144 | decode_colors[12] = (decode_colors[0] + 2*decode_colors[4]) / 3; 145 | decode_colors[13] = (decode_colors[1] + 2*decode_colors[5]) / 3; 146 | decode_colors[14] = (decode_colors[2] + 2*decode_colors[6]) / 3; 147 | decode_colors[15] = 255; 148 | } else 149 | { 150 | // 1 interpolated color, alpha 151 | decode_colors[8] = (decode_colors[0] + decode_colors[4]) / 2; 152 | decode_colors[9] = (decode_colors[1] + decode_colors[5]) / 2; 153 | decode_colors[10] = (decode_colors[2] + decode_colors[6]) / 2; 154 | decode_colors[11] = 255; 155 | decode_colors[12] = 0; 156 | decode_colors[13] = 0; 157 | decode_colors[14] = 0; 158 | decode_colors[15] = 0; 159 | } 160 | // decode the block 161 | for( i = 0; i < 16*4; i += 4 ) 162 | { 163 | int idx = ((compressed[next_bit>>3] >> (next_bit & 7)) & 3) * 4; 164 | next_bit += 2; 165 | uncompressed[i+0] = decode_colors[idx+0]; 166 | uncompressed[i+1] = decode_colors[idx+1]; 167 | uncompressed[i+2] = decode_colors[idx+2]; 168 | uncompressed[i+3] = decode_colors[idx+3]; 169 | } 170 | // done 171 | } 172 | void stbi_decode_DXT23_alpha_block( 173 | unsigned char uncompressed[16*4], 174 | unsigned char compressed[8] ) 175 | { 176 | int i, next_bit = 0; 177 | // each alpha value gets 4 bits 178 | for( i = 3; i < 16*4; i += 4 ) 179 | { 180 | uncompressed[i] = stbi_convert_bit_range( 181 | (compressed[next_bit>>3] >> (next_bit&7)) & 15, 182 | 4, 8 ); 183 | next_bit += 4; 184 | } 185 | } 186 | void stbi_decode_DXT45_alpha_block( 187 | unsigned char uncompressed[16*4], 188 | unsigned char compressed[8] ) 189 | { 190 | int i, next_bit = 8*2; 191 | unsigned char decode_alpha[8]; 192 | // each alpha value gets 3 bits, and the 1st 2 bytes are the range 193 | decode_alpha[0] = compressed[0]; 194 | decode_alpha[1] = compressed[1]; 195 | if( decode_alpha[0] > decode_alpha[1] ) 196 | { 197 | // 6 step intermediate 198 | decode_alpha[2] = (6*decode_alpha[0] + 1*decode_alpha[1]) / 7; 199 | decode_alpha[3] = (5*decode_alpha[0] + 2*decode_alpha[1]) / 7; 200 | decode_alpha[4] = (4*decode_alpha[0] + 3*decode_alpha[1]) / 7; 201 | decode_alpha[5] = (3*decode_alpha[0] + 4*decode_alpha[1]) / 7; 202 | decode_alpha[6] = (2*decode_alpha[0] + 5*decode_alpha[1]) / 7; 203 | decode_alpha[7] = (1*decode_alpha[0] + 6*decode_alpha[1]) / 7; 204 | } else 205 | { 206 | // 4 step intermediate, pluss full and none 207 | decode_alpha[2] = (4*decode_alpha[0] + 1*decode_alpha[1]) / 5; 208 | decode_alpha[3] = (3*decode_alpha[0] + 2*decode_alpha[1]) / 5; 209 | decode_alpha[4] = (2*decode_alpha[0] + 3*decode_alpha[1]) / 5; 210 | decode_alpha[5] = (1*decode_alpha[0] + 4*decode_alpha[1]) / 5; 211 | decode_alpha[6] = 0; 212 | decode_alpha[7] = 255; 213 | } 214 | for( i = 3; i < 16*4; i += 4 ) 215 | { 216 | int idx = 0, bit; 217 | bit = (compressed[next_bit>>3] >> (next_bit&7)) & 1; 218 | idx += bit << 0; 219 | ++next_bit; 220 | bit = (compressed[next_bit>>3] >> (next_bit&7)) & 1; 221 | idx += bit << 1; 222 | ++next_bit; 223 | bit = (compressed[next_bit>>3] >> (next_bit&7)) & 1; 224 | idx += bit << 2; 225 | ++next_bit; 226 | uncompressed[i] = decode_alpha[idx & 7]; 227 | } 228 | // done 229 | } 230 | void stbi_decode_DXT_color_block( 231 | unsigned char uncompressed[16*4], 232 | unsigned char compressed[8] ) 233 | { 234 | int next_bit = 4*8; 235 | int i, r, g, b; 236 | int c0, c1; 237 | unsigned char decode_colors[4*3]; 238 | // find the 2 primary colors 239 | c0 = compressed[0] + (compressed[1] << 8); 240 | c1 = compressed[2] + (compressed[3] << 8); 241 | stbi_rgb_888_from_565( c0, &r, &g, &b ); 242 | decode_colors[0] = r; 243 | decode_colors[1] = g; 244 | decode_colors[2] = b; 245 | stbi_rgb_888_from_565( c1, &r, &g, &b ); 246 | decode_colors[3] = r; 247 | decode_colors[4] = g; 248 | decode_colors[5] = b; 249 | // Like DXT1, but no choicees: 250 | // no alpha, 2 interpolated colors 251 | decode_colors[6] = (2*decode_colors[0] + decode_colors[3]) / 3; 252 | decode_colors[7] = (2*decode_colors[1] + decode_colors[4]) / 3; 253 | decode_colors[8] = (2*decode_colors[2] + decode_colors[5]) / 3; 254 | decode_colors[9] = (decode_colors[0] + 2*decode_colors[3]) / 3; 255 | decode_colors[10] = (decode_colors[1] + 2*decode_colors[4]) / 3; 256 | decode_colors[11] = (decode_colors[2] + 2*decode_colors[5]) / 3; 257 | // decode the block 258 | for( i = 0; i < 16*4; i += 4 ) 259 | { 260 | int idx = ((compressed[next_bit>>3] >> (next_bit & 7)) & 3) * 3; 261 | next_bit += 2; 262 | uncompressed[i+0] = decode_colors[idx+0]; 263 | uncompressed[i+1] = decode_colors[idx+1]; 264 | uncompressed[i+2] = decode_colors[idx+2]; 265 | } 266 | // done 267 | } 268 | static stbi_uc *dds_load(stbi *s, int *x, int *y, int *comp, int req_comp) 269 | { 270 | // all variables go up front 271 | stbi_uc *dds_data = NULL; 272 | stbi_uc block[16*4]; 273 | stbi_uc compressed[8]; 274 | int flags, DXT_family; 275 | int has_alpha, has_mipmap; 276 | int is_compressed, cubemap_faces; 277 | int block_pitch, num_blocks; 278 | DDS_header header; 279 | int i, sz, cf; 280 | // load the header 281 | if( sizeof( DDS_header ) != 128 ) 282 | { 283 | return NULL; 284 | } 285 | getn( s, (stbi_uc*)(&header), 128 ); 286 | // and do some checking 287 | if( header.dwMagic != (('D' << 0) | ('D' << 8) | ('S' << 16) | (' ' << 24)) ) return NULL; 288 | if( header.dwSize != 124 ) return NULL; 289 | flags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; 290 | if( (header.dwFlags & flags) != flags ) return NULL; 291 | /* According to the MSDN spec, the dwFlags should contain 292 | DDSD_LINEARSIZE if it's compressed, or DDSD_PITCH if 293 | uncompressed. Some DDS writers do not conform to the 294 | spec, so I need to make my reader more tolerant */ 295 | if( header.sPixelFormat.dwSize != 32 ) return NULL; 296 | flags = DDPF_FOURCC | DDPF_RGB; 297 | if( (header.sPixelFormat.dwFlags & flags) == 0 ) return NULL; 298 | if( (header.sCaps.dwCaps1 & DDSCAPS_TEXTURE) == 0 ) return NULL; 299 | // get the image data 300 | s->img_x = header.dwWidth; 301 | s->img_y = header.dwHeight; 302 | s->img_n = 4; 303 | is_compressed = (header.sPixelFormat.dwFlags & DDPF_FOURCC) / DDPF_FOURCC; 304 | has_alpha = (header.sPixelFormat.dwFlags & DDPF_ALPHAPIXELS) / DDPF_ALPHAPIXELS; 305 | has_mipmap = (header.sCaps.dwCaps1 & DDSCAPS_MIPMAP) && (header.dwMipMapCount > 1); 306 | cubemap_faces = (header.sCaps.dwCaps2 & DDSCAPS2_CUBEMAP) / DDSCAPS2_CUBEMAP; 307 | /* I need cubemaps to have square faces */ 308 | cubemap_faces &= (s->img_x == s->img_y); 309 | cubemap_faces *= 5; 310 | cubemap_faces += 1; 311 | block_pitch = (s->img_x+3) >> 2; 312 | num_blocks = block_pitch * ((s->img_y+3) >> 2); 313 | /* let the user know what's going on */ 314 | *x = s->img_x; 315 | *y = s->img_y; 316 | *comp = s->img_n; 317 | /* is this uncompressed? */ 318 | if( is_compressed ) 319 | { 320 | /* compressed */ 321 | // note: header.sPixelFormat.dwFourCC is something like (('D'<<0)|('X'<<8)|('T'<<16)|('1'<<24)) 322 | DXT_family = 1 + (header.sPixelFormat.dwFourCC >> 24) - '1'; 323 | if( (DXT_family < 1) || (DXT_family > 5) ) return NULL; 324 | /* check the expected size...oops, nevermind... 325 | those non-compliant writers leave 326 | dwPitchOrLinearSize == 0 */ 327 | // passed all the tests, get the RAM for decoding 328 | sz = (s->img_x)*(s->img_y)*4*cubemap_faces; 329 | dds_data = (unsigned char*)malloc( sz ); 330 | /* do this once for each face */ 331 | for( cf = 0; cf < cubemap_faces; ++ cf ) 332 | { 333 | // now read and decode all the blocks 334 | for( i = 0; i < num_blocks; ++i ) 335 | { 336 | // where are we? 337 | int bx, by, bw=4, bh=4; 338 | int ref_x = 4 * (i % block_pitch); 339 | int ref_y = 4 * (i / block_pitch); 340 | // get the next block's worth of compressed data, and decompress it 341 | if( DXT_family == 1 ) 342 | { 343 | // DXT1 344 | getn( s, compressed, 8 ); 345 | stbi_decode_DXT1_block( block, compressed ); 346 | } else if( DXT_family < 4 ) 347 | { 348 | // DXT2/3 349 | getn( s, compressed, 8 ); 350 | stbi_decode_DXT23_alpha_block ( block, compressed ); 351 | getn( s, compressed, 8 ); 352 | stbi_decode_DXT_color_block ( block, compressed ); 353 | } else 354 | { 355 | // DXT4/5 356 | getn( s, compressed, 8 ); 357 | stbi_decode_DXT45_alpha_block ( block, compressed ); 358 | getn( s, compressed, 8 ); 359 | stbi_decode_DXT_color_block ( block, compressed ); 360 | } 361 | // is this a partial block? 362 | if( ref_x + 4 > s->img_x ) 363 | { 364 | bw = s->img_x - ref_x; 365 | } 366 | if( ref_y + 4 > s->img_y ) 367 | { 368 | bh = s->img_y - ref_y; 369 | } 370 | // now drop our decompressed data into the buffer 371 | for( by = 0; by < bh; ++by ) 372 | { 373 | int idx = 4*((ref_y+by+cf*s->img_x)*s->img_x + ref_x); 374 | for( bx = 0; bx < bw*4; ++bx ) 375 | { 376 | 377 | dds_data[idx+bx] = block[by*16+bx]; 378 | } 379 | } 380 | } 381 | /* done reading and decoding the main image... 382 | skip MIPmaps if present */ 383 | if( has_mipmap ) 384 | { 385 | int block_size = 16; 386 | if( DXT_family == 1 ) 387 | { 388 | block_size = 8; 389 | } 390 | for( i = 1; i < header.dwMipMapCount; ++i ) 391 | { 392 | int mx = s->img_x >> (i + 2); 393 | int my = s->img_y >> (i + 2); 394 | if( mx < 1 ) 395 | { 396 | mx = 1; 397 | } 398 | if( my < 1 ) 399 | { 400 | my = 1; 401 | } 402 | skip( s, mx*my*block_size ); 403 | } 404 | } 405 | }/* per cubemap face */ 406 | } else 407 | { 408 | /* uncompressed */ 409 | DXT_family = 0; 410 | s->img_n = 3; 411 | if( has_alpha ) 412 | { 413 | s->img_n = 4; 414 | } 415 | *comp = s->img_n; 416 | sz = s->img_x*s->img_y*s->img_n*cubemap_faces; 417 | dds_data = (unsigned char*)malloc( sz ); 418 | /* do this once for each face */ 419 | for( cf = 0; cf < cubemap_faces; ++ cf ) 420 | { 421 | /* read the main image for this face */ 422 | getn( s, &dds_data[cf*s->img_x*s->img_y*s->img_n], s->img_x*s->img_y*s->img_n ); 423 | /* done reading and decoding the main image... 424 | skip MIPmaps if present */ 425 | if( has_mipmap ) 426 | { 427 | for( i = 1; i < header.dwMipMapCount; ++i ) 428 | { 429 | int mx = s->img_x >> i; 430 | int my = s->img_y >> i; 431 | if( mx < 1 ) 432 | { 433 | mx = 1; 434 | } 435 | if( my < 1 ) 436 | { 437 | my = 1; 438 | } 439 | skip( s, mx*my*s->img_n ); 440 | } 441 | } 442 | } 443 | /* data was BGR, I need it RGB */ 444 | for( i = 0; i < sz; i += s->img_n ) 445 | { 446 | unsigned char temp = dds_data[i]; 447 | dds_data[i] = dds_data[i+2]; 448 | dds_data[i+2] = temp; 449 | } 450 | } 451 | /* finished decompressing into RGBA, 452 | adjust the y size if we have a cubemap 453 | note: sz is already up to date */ 454 | s->img_y *= cubemap_faces; 455 | *y = s->img_y; 456 | // did the user want something else, or 457 | // see if all the alpha values are 255 (i.e. no transparency) 458 | has_alpha = 0; 459 | if( s->img_n == 4) 460 | { 461 | for( i = 3; (i < sz) && (has_alpha == 0); i += 4 ) 462 | { 463 | has_alpha |= (dds_data[i] < 255); 464 | } 465 | } 466 | if( (req_comp <= 4) && (req_comp >= 1) ) 467 | { 468 | // user has some requirements, meet them 469 | if( req_comp != s->img_n ) 470 | { 471 | dds_data = convert_format( dds_data, s->img_n, req_comp, s->img_x, s->img_y ); 472 | *comp = s->img_n; 473 | } 474 | } else 475 | { 476 | // user had no requirements, only drop to RGB is no alpha 477 | if( (has_alpha == 0) && (s->img_n == 4) ) 478 | { 479 | dds_data = convert_format( dds_data, 4, 3, s->img_x, s->img_y ); 480 | *comp = 3; 481 | } 482 | } 483 | // OK, done 484 | return dds_data; 485 | } 486 | 487 | #ifndef STBI_NO_STDIO 488 | stbi_uc *stbi_dds_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp) 489 | { 490 | stbi s; 491 | start_file(&s,f); 492 | return dds_load(&s,x,y,comp,req_comp); 493 | } 494 | 495 | stbi_uc *stbi_dds_load (char *filename, int *x, int *y, int *comp, int req_comp) 496 | { 497 | stbi_uc *data; 498 | FILE *f = fopen(filename, "rb"); 499 | if (!f) return NULL; 500 | data = stbi_dds_load_from_file(f,x,y,comp,req_comp); 501 | fclose(f); 502 | return data; 503 | } 504 | #endif 505 | 506 | stbi_uc *stbi_dds_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) 507 | { 508 | stbi s; 509 | start_mem(&s,buffer, len); 510 | return dds_load(&s,x,y,comp,req_comp); 511 | } 512 | -------------------------------------------------------------------------------- /Twitch/Engine/Graphics/SOIL/src/stb_image_aug.h: -------------------------------------------------------------------------------- 1 | /* stbi-1.16 - public domain JPEG/PNG reader - http://nothings.org/stb_image.c 2 | when you control the images you're loading 3 | 4 | QUICK NOTES: 5 | Primarily of interest to game developers and other people who can 6 | avoid problematic images and only need the trivial interface 7 | 8 | JPEG baseline (no JPEG progressive, no oddball channel decimations) 9 | PNG non-interlaced 10 | BMP non-1bpp, non-RLE 11 | TGA (not sure what subset, if a subset) 12 | PSD (composited view only, no extra channels) 13 | HDR (radiance rgbE format) 14 | writes BMP,TGA (define STBI_NO_WRITE to remove code) 15 | decoded from memory or through stdio FILE (define STBI_NO_STDIO to remove code) 16 | supports installable dequantizing-IDCT, YCbCr-to-RGB conversion (define STBI_SIMD) 17 | 18 | TODO: 19 | stbi_info_* 20 | 21 | history: 22 | 1.16 major bugfix - convert_format converted one too many pixels 23 | 1.15 initialize some fields for thread safety 24 | 1.14 fix threadsafe conversion bug; header-file-only version (#define STBI_HEADER_FILE_ONLY before including) 25 | 1.13 threadsafe 26 | 1.12 const qualifiers in the API 27 | 1.11 Support installable IDCT, colorspace conversion routines 28 | 1.10 Fixes for 64-bit (don't use "unsigned long") 29 | optimized upsampling by Fabian "ryg" Giesen 30 | 1.09 Fix format-conversion for PSD code (bad global variables!) 31 | 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz 32 | 1.07 attempt to fix C++ warning/errors again 33 | 1.06 attempt to fix C++ warning/errors again 34 | 1.05 fix TGA loading to return correct *comp and use good luminance calc 35 | 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free 36 | 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR 37 | 1.02 support for (subset of) HDR files, float interface for preferred access to them 38 | 1.01 fix bug: possible bug in handling right-side up bmps... not sure 39 | fix bug: the stbi_bmp_load() and stbi_tga_load() functions didn't work at all 40 | 1.00 interface to zlib that skips zlib header 41 | 0.99 correct handling of alpha in palette 42 | 0.98 TGA loader by lonesock; dynamically add loaders (untested) 43 | 0.97 jpeg errors on too large a file; also catch another malloc failure 44 | 0.96 fix detection of invalid v value - particleman@mollyrocket forum 45 | 0.95 during header scan, seek to markers in case of padding 46 | 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same 47 | 0.93 handle jpegtran output; verbose errors 48 | 0.92 read 4,8,16,24,32-bit BMP files of several formats 49 | 0.91 output 24-bit Windows 3.0 BMP files 50 | 0.90 fix a few more warnings; bump version number to approach 1.0 51 | 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd 52 | 0.60 fix compiling as c++ 53 | 0.59 fix warnings: merge Dave Moore's -Wall fixes 54 | 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian 55 | 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less 56 | than 16 available 57 | 0.56 fix bug: zlib uncompressed mode len vs. nlen 58 | 0.55 fix bug: restart_interval not initialized to 0 59 | 0.54 allow NULL for 'int *comp' 60 | 0.53 fix bug in png 3->4; speedup png decoding 61 | 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments 62 | 0.51 obey req_comp requests, 1-component jpegs return as 1-component, 63 | on 'test' only check type, not whether we support this variant 64 | */ 65 | 66 | #ifndef HEADER_STB_IMAGE_AUGMENTED 67 | #define HEADER_STB_IMAGE_AUGMENTED 68 | 69 | //// begin header file //////////////////////////////////////////////////// 70 | // 71 | // Limitations: 72 | // - no progressive/interlaced support (jpeg, png) 73 | // - 8-bit samples only (jpeg, png) 74 | // - not threadsafe 75 | // - channel subsampling of at most 2 in each dimension (jpeg) 76 | // - no delayed line count (jpeg) -- IJG doesn't support either 77 | // 78 | // Basic usage (see HDR discussion below): 79 | // int x,y,n; 80 | // unsigned char *data = stbi_load(filename, &x, &y, &n, 0); 81 | // // ... process data if not NULL ... 82 | // // ... x = width, y = height, n = # 8-bit components per pixel ... 83 | // // ... replace '0' with '1'..'4' to force that many components per pixel 84 | // stbi_image_free(data) 85 | // 86 | // Standard parameters: 87 | // int *x -- outputs image width in pixels 88 | // int *y -- outputs image height in pixels 89 | // int *comp -- outputs # of image components in image file 90 | // int req_comp -- if non-zero, # of image components requested in result 91 | // 92 | // The return value from an image loader is an 'unsigned char *' which points 93 | // to the pixel data. The pixel data consists of *y scanlines of *x pixels, 94 | // with each pixel consisting of N interleaved 8-bit components; the first 95 | // pixel pointed to is top-left-most in the image. There is no padding between 96 | // image scanlines or between pixels, regardless of format. The number of 97 | // components N is 'req_comp' if req_comp is non-zero, or *comp otherwise. 98 | // If req_comp is non-zero, *comp has the number of components that _would_ 99 | // have been output otherwise. E.g. if you set req_comp to 4, you will always 100 | // get RGBA output, but you can check *comp to easily see if it's opaque. 101 | // 102 | // An output image with N components has the following components interleaved 103 | // in this order in each pixel: 104 | // 105 | // N=#comp components 106 | // 1 grey 107 | // 2 grey, alpha 108 | // 3 red, green, blue 109 | // 4 red, green, blue, alpha 110 | // 111 | // If image loading fails for any reason, the return value will be NULL, 112 | // and *x, *y, *comp will be unchanged. The function stbi_failure_reason() 113 | // can be queried for an extremely brief, end-user unfriendly explanation 114 | // of why the load failed. Define STBI_NO_FAILURE_STRINGS to avoid 115 | // compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly 116 | // more user-friendly ones. 117 | // 118 | // Paletted PNG and BMP images are automatically depalettized. 119 | // 120 | // 121 | // =========================================================================== 122 | // 123 | // HDR image support (disable by defining STBI_NO_HDR) 124 | // 125 | // stb_image now supports loading HDR images in general, and currently 126 | // the Radiance .HDR file format, although the support is provided 127 | // generically. You can still load any file through the existing interface; 128 | // if you attempt to load an HDR file, it will be automatically remapped to 129 | // LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1; 130 | // both of these constants can be reconfigured through this interface: 131 | // 132 | // stbi_hdr_to_ldr_gamma(2.2f); 133 | // stbi_hdr_to_ldr_scale(1.0f); 134 | // 135 | // (note, do not use _inverse_ constants; stbi_image will invert them 136 | // appropriately). 137 | // 138 | // Additionally, there is a new, parallel interface for loading files as 139 | // (linear) floats to preserve the full dynamic range: 140 | // 141 | // float *data = stbi_loadf(filename, &x, &y, &n, 0); 142 | // 143 | // If you load LDR images through this interface, those images will 144 | // be promoted to floating point values, run through the inverse of 145 | // constants corresponding to the above: 146 | // 147 | // stbi_ldr_to_hdr_scale(1.0f); 148 | // stbi_ldr_to_hdr_gamma(2.2f); 149 | // 150 | // Finally, given a filename (or an open file or memory block--see header 151 | // file for details) containing image data, you can query for the "most 152 | // appropriate" interface to use (that is, whether the image is HDR or 153 | // not), using: 154 | // 155 | // stbi_is_hdr(char *filename); 156 | 157 | #ifndef STBI_NO_STDIO 158 | #include 159 | #endif 160 | 161 | #define STBI_VERSION 1 162 | 163 | enum 164 | { 165 | STBI_default = 0, // only used for req_comp 166 | 167 | STBI_grey = 1, 168 | STBI_grey_alpha = 2, 169 | STBI_rgb = 3, 170 | STBI_rgb_alpha = 4, 171 | }; 172 | 173 | typedef unsigned char stbi_uc; 174 | 175 | #ifdef __cplusplus 176 | extern "C" { 177 | #endif 178 | 179 | // WRITING API 180 | 181 | #if !defined(STBI_NO_WRITE) && !defined(STBI_NO_STDIO) 182 | // write a BMP/TGA file given tightly packed 'comp' channels (no padding, nor bmp-stride-padding) 183 | // (you must include the appropriate extension in the filename). 184 | // returns TRUE on success, FALSE if couldn't open file, error writing file 185 | extern int stbi_write_bmp (char const *filename, int x, int y, int comp, void *data); 186 | extern int stbi_write_tga (char const *filename, int x, int y, int comp, void *data); 187 | #endif 188 | 189 | // PRIMARY API - works on images of any type 190 | 191 | // load image by filename, open file, or memory buffer 192 | #ifndef STBI_NO_STDIO 193 | extern stbi_uc *stbi_load (char const *filename, int *x, int *y, int *comp, int req_comp); 194 | extern stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); 195 | extern int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); 196 | #endif 197 | extern stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); 198 | // for stbi_load_from_file, file pointer is left pointing immediately after image 199 | 200 | #ifndef STBI_NO_HDR 201 | #ifndef STBI_NO_STDIO 202 | extern float *stbi_loadf (char const *filename, int *x, int *y, int *comp, int req_comp); 203 | extern float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); 204 | #endif 205 | extern float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); 206 | 207 | extern void stbi_hdr_to_ldr_gamma(float gamma); 208 | extern void stbi_hdr_to_ldr_scale(float scale); 209 | 210 | extern void stbi_ldr_to_hdr_gamma(float gamma); 211 | extern void stbi_ldr_to_hdr_scale(float scale); 212 | 213 | #endif // STBI_NO_HDR 214 | 215 | // get a VERY brief reason for failure 216 | // NOT THREADSAFE 217 | extern char *stbi_failure_reason (void); 218 | 219 | // free the loaded image -- this is just free() 220 | extern void stbi_image_free (void *retval_from_stbi_load); 221 | 222 | // get image dimensions & components without fully decoding 223 | extern int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); 224 | extern int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); 225 | #ifndef STBI_NO_STDIO 226 | extern int stbi_info (char const *filename, int *x, int *y, int *comp); 227 | extern int stbi_is_hdr (char const *filename); 228 | extern int stbi_is_hdr_from_file(FILE *f); 229 | #endif 230 | 231 | // ZLIB client - used by PNG, available for other purposes 232 | 233 | extern char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); 234 | extern char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); 235 | extern int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); 236 | 237 | extern char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); 238 | extern int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); 239 | 240 | // TYPE-SPECIFIC ACCESS 241 | 242 | // is it a jpeg? 243 | extern int stbi_jpeg_test_memory (stbi_uc const *buffer, int len); 244 | extern stbi_uc *stbi_jpeg_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); 245 | extern int stbi_jpeg_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); 246 | 247 | #ifndef STBI_NO_STDIO 248 | extern stbi_uc *stbi_jpeg_load (char const *filename, int *x, int *y, int *comp, int req_comp); 249 | extern int stbi_jpeg_test_file (FILE *f); 250 | extern stbi_uc *stbi_jpeg_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); 251 | 252 | extern int stbi_jpeg_info (char const *filename, int *x, int *y, int *comp); 253 | extern int stbi_jpeg_info_from_file (FILE *f, int *x, int *y, int *comp); 254 | #endif 255 | 256 | // is it a png? 257 | extern int stbi_png_test_memory (stbi_uc const *buffer, int len); 258 | extern stbi_uc *stbi_png_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); 259 | extern int stbi_png_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp); 260 | 261 | #ifndef STBI_NO_STDIO 262 | extern stbi_uc *stbi_png_load (char const *filename, int *x, int *y, int *comp, int req_comp); 263 | extern int stbi_png_info (char const *filename, int *x, int *y, int *comp); 264 | extern int stbi_png_test_file (FILE *f); 265 | extern stbi_uc *stbi_png_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); 266 | extern int stbi_png_info_from_file (FILE *f, int *x, int *y, int *comp); 267 | #endif 268 | 269 | // is it a bmp? 270 | extern int stbi_bmp_test_memory (stbi_uc const *buffer, int len); 271 | 272 | extern stbi_uc *stbi_bmp_load (char const *filename, int *x, int *y, int *comp, int req_comp); 273 | extern stbi_uc *stbi_bmp_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); 274 | #ifndef STBI_NO_STDIO 275 | extern int stbi_bmp_test_file (FILE *f); 276 | extern stbi_uc *stbi_bmp_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); 277 | #endif 278 | 279 | // is it a tga? 280 | extern int stbi_tga_test_memory (stbi_uc const *buffer, int len); 281 | 282 | extern stbi_uc *stbi_tga_load (char const *filename, int *x, int *y, int *comp, int req_comp); 283 | extern stbi_uc *stbi_tga_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); 284 | #ifndef STBI_NO_STDIO 285 | extern int stbi_tga_test_file (FILE *f); 286 | extern stbi_uc *stbi_tga_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); 287 | #endif 288 | 289 | // is it a psd? 290 | extern int stbi_psd_test_memory (stbi_uc const *buffer, int len); 291 | 292 | extern stbi_uc *stbi_psd_load (char const *filename, int *x, int *y, int *comp, int req_comp); 293 | extern stbi_uc *stbi_psd_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); 294 | #ifndef STBI_NO_STDIO 295 | extern int stbi_psd_test_file (FILE *f); 296 | extern stbi_uc *stbi_psd_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); 297 | #endif 298 | 299 | // is it an hdr? 300 | extern int stbi_hdr_test_memory (stbi_uc const *buffer, int len); 301 | 302 | extern float * stbi_hdr_load (char const *filename, int *x, int *y, int *comp, int req_comp); 303 | extern float * stbi_hdr_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); 304 | extern stbi_uc *stbi_hdr_load_rgbe (char const *filename, int *x, int *y, int *comp, int req_comp); 305 | extern float * stbi_hdr_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); 306 | #ifndef STBI_NO_STDIO 307 | extern int stbi_hdr_test_file (FILE *f); 308 | extern float * stbi_hdr_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); 309 | extern stbi_uc *stbi_hdr_load_rgbe_file (FILE *f, int *x, int *y, int *comp, int req_comp); 310 | #endif 311 | 312 | // define new loaders 313 | typedef struct 314 | { 315 | int (*test_memory)(stbi_uc const *buffer, int len); 316 | stbi_uc * (*load_from_memory)(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); 317 | #ifndef STBI_NO_STDIO 318 | int (*test_file)(FILE *f); 319 | stbi_uc * (*load_from_file)(FILE *f, int *x, int *y, int *comp, int req_comp); 320 | #endif 321 | } stbi_loader; 322 | 323 | // register a loader by filling out the above structure (you must defined ALL functions) 324 | // returns 1 if added or already added, 0 if not added (too many loaders) 325 | // NOT THREADSAFE 326 | extern int stbi_register_loader(stbi_loader *loader); 327 | 328 | // define faster low-level operations (typically SIMD support) 329 | #if STBI_SIMD 330 | typedef void (*stbi_idct_8x8)(uint8 *out, int out_stride, short data[64], unsigned short *dequantize); 331 | // compute an integer IDCT on "input" 332 | // input[x] = data[x] * dequantize[x] 333 | // write results to 'out': 64 samples, each run of 8 spaced by 'out_stride' 334 | // CLAMP results to 0..255 335 | typedef void (*stbi_YCbCr_to_RGB_run)(uint8 *output, uint8 const *y, uint8 const *cb, uint8 const *cr, int count, int step); 336 | // compute a conversion from YCbCr to RGB 337 | // 'count' pixels 338 | // write pixels to 'output'; each pixel is 'step' bytes (either 3 or 4; if 4, write '255' as 4th), order R,G,B 339 | // y: Y input channel 340 | // cb: Cb input channel; scale/biased to be 0..255 341 | // cr: Cr input channel; scale/biased to be 0..255 342 | 343 | extern void stbi_install_idct(stbi_idct_8x8 func); 344 | extern void stbi_install_YCbCr_to_RGB(stbi_YCbCr_to_RGB_run func); 345 | #endif // STBI_SIMD 346 | 347 | #ifdef __cplusplus 348 | } 349 | #endif 350 | 351 | // 352 | // 353 | //// end header file ///////////////////////////////////////////////////// 354 | #endif // STBI_INCLUDE_STB_IMAGE_H 355 | -------------------------------------------------------------------------------- /Twitch/Engine/Graphics/SOIL/src/image_DXT.c: -------------------------------------------------------------------------------- 1 | /* 2 | Jonathan Dummer 3 | 2007-07-31-10.32 4 | 5 | simple DXT compression / decompression code 6 | 7 | public domain 8 | */ 9 | 10 | #include "image_DXT.h" 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | /* set this =1 if you want to use the covarince matrix method... 17 | which is better than my method of using standard deviations 18 | overall, except on the infintesimal chance that the power 19 | method fails for finding the largest eigenvector */ 20 | #define USE_COV_MAT 1 21 | 22 | /********* Function Prototypes *********/ 23 | /* 24 | Takes a 4x4 block of pixels and compresses it into 8 bytes 25 | in DXT1 format (color only, no alpha). Speed is valued 26 | over prettyness, at least for now. 27 | */ 28 | void compress_DDS_color_block( 29 | int channels, 30 | const unsigned char *const uncompressed, 31 | unsigned char compressed[8] ); 32 | /* 33 | Takes a 4x4 block of pixels and compresses the alpha 34 | component it into 8 bytes for use in DXT5 DDS files. 35 | Speed is valued over prettyness, at least for now. 36 | */ 37 | void compress_DDS_alpha_block( 38 | const unsigned char *const uncompressed, 39 | unsigned char compressed[8] ); 40 | 41 | /********* Actual Exposed Functions *********/ 42 | int 43 | save_image_as_DDS 44 | ( 45 | const char *filename, 46 | int width, int height, int channels, 47 | const unsigned char *const data 48 | ) 49 | { 50 | /* variables */ 51 | FILE *fout; 52 | unsigned char *DDS_data; 53 | DDS_header header; 54 | int DDS_size; 55 | /* error check */ 56 | if( (NULL == filename) || 57 | (width < 1) || (height < 1) || 58 | (channels < 1) || (channels > 4) || 59 | (data == NULL ) ) 60 | { 61 | return 0; 62 | } 63 | /* Convert the image */ 64 | if( (channels & 1) == 1 ) 65 | { 66 | /* no alpha, just use DXT1 */ 67 | DDS_data = convert_image_to_DXT1( data, width, height, channels, &DDS_size ); 68 | } else 69 | { 70 | /* has alpha, so use DXT5 */ 71 | DDS_data = convert_image_to_DXT5( data, width, height, channels, &DDS_size ); 72 | } 73 | /* save it */ 74 | memset( &header, 0, sizeof( DDS_header ) ); 75 | header.dwMagic = ('D' << 0) | ('D' << 8) | ('S' << 16) | (' ' << 24); 76 | header.dwSize = 124; 77 | header.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_LINEARSIZE; 78 | header.dwWidth = width; 79 | header.dwHeight = height; 80 | header.dwPitchOrLinearSize = DDS_size; 81 | header.sPixelFormat.dwSize = 32; 82 | header.sPixelFormat.dwFlags = DDPF_FOURCC; 83 | if( (channels & 1) == 1 ) 84 | { 85 | header.sPixelFormat.dwFourCC = ('D' << 0) | ('X' << 8) | ('T' << 16) | ('1' << 24); 86 | } else 87 | { 88 | header.sPixelFormat.dwFourCC = ('D' << 0) | ('X' << 8) | ('T' << 16) | ('5' << 24); 89 | } 90 | header.sCaps.dwCaps1 = DDSCAPS_TEXTURE; 91 | /* write it out */ 92 | fout = fopen( filename, "wb"); 93 | fwrite( &header, sizeof( DDS_header ), 1, fout ); 94 | fwrite( DDS_data, 1, DDS_size, fout ); 95 | fclose( fout ); 96 | /* done */ 97 | free( DDS_data ); 98 | return 1; 99 | } 100 | 101 | unsigned char* convert_image_to_DXT1( 102 | const unsigned char *const uncompressed, 103 | int width, int height, int channels, 104 | int *out_size ) 105 | { 106 | unsigned char *compressed; 107 | int i, j, x, y; 108 | unsigned char ublock[16*3]; 109 | unsigned char cblock[8]; 110 | int index = 0, chan_step = 1; 111 | int block_count = 0; 112 | /* error check */ 113 | *out_size = 0; 114 | if( (width < 1) || (height < 1) || 115 | (NULL == uncompressed) || 116 | (channels < 1) || (channels > 4) ) 117 | { 118 | return NULL; 119 | } 120 | /* for channels == 1 or 2, I do not step forward for R,G,B values */ 121 | if( channels < 3 ) 122 | { 123 | chan_step = 0; 124 | } 125 | /* get the RAM for the compressed image 126 | (8 bytes per 4x4 pixel block) */ 127 | *out_size = ((width+3) >> 2) * ((height+3) >> 2) * 8; 128 | compressed = (unsigned char*)malloc( *out_size ); 129 | /* go through each block */ 130 | for( j = 0; j < height; j += 4 ) 131 | { 132 | for( i = 0; i < width; i += 4 ) 133 | { 134 | /* copy this block into a new one */ 135 | int idx = 0; 136 | int mx = 4, my = 4; 137 | if( j+4 >= height ) 138 | { 139 | my = height - j; 140 | } 141 | if( i+4 >= width ) 142 | { 143 | mx = width - i; 144 | } 145 | for( y = 0; y < my; ++y ) 146 | { 147 | for( x = 0; x < mx; ++x ) 148 | { 149 | ublock[idx++] = uncompressed[(j+y)*width*channels+(i+x)*channels]; 150 | ublock[idx++] = uncompressed[(j+y)*width*channels+(i+x)*channels+chan_step]; 151 | ublock[idx++] = uncompressed[(j+y)*width*channels+(i+x)*channels+chan_step+chan_step]; 152 | } 153 | for( x = mx; x < 4; ++x ) 154 | { 155 | ublock[idx++] = ublock[0]; 156 | ublock[idx++] = ublock[1]; 157 | ublock[idx++] = ublock[2]; 158 | } 159 | } 160 | for( y = my; y < 4; ++y ) 161 | { 162 | for( x = 0; x < 4; ++x ) 163 | { 164 | ublock[idx++] = ublock[0]; 165 | ublock[idx++] = ublock[1]; 166 | ublock[idx++] = ublock[2]; 167 | } 168 | } 169 | /* compress the block */ 170 | ++block_count; 171 | compress_DDS_color_block( 3, ublock, cblock ); 172 | /* copy the data from the block into the main block */ 173 | for( x = 0; x < 8; ++x ) 174 | { 175 | compressed[index++] = cblock[x]; 176 | } 177 | } 178 | } 179 | return compressed; 180 | } 181 | 182 | unsigned char* convert_image_to_DXT5( 183 | const unsigned char *const uncompressed, 184 | int width, int height, int channels, 185 | int *out_size ) 186 | { 187 | unsigned char *compressed; 188 | int i, j, x, y; 189 | unsigned char ublock[16*4]; 190 | unsigned char cblock[8]; 191 | int index = 0, chan_step = 1; 192 | int block_count = 0, has_alpha; 193 | /* error check */ 194 | *out_size = 0; 195 | if( (width < 1) || (height < 1) || 196 | (NULL == uncompressed) || 197 | (channels < 1) || ( channels > 4) ) 198 | { 199 | return NULL; 200 | } 201 | /* for channels == 1 or 2, I do not step forward for R,G,B vales */ 202 | if( channels < 3 ) 203 | { 204 | chan_step = 0; 205 | } 206 | /* # channels = 1 or 3 have no alpha, 2 & 4 do have alpha */ 207 | has_alpha = 1 - (channels & 1); 208 | /* get the RAM for the compressed image 209 | (16 bytes per 4x4 pixel block) */ 210 | *out_size = ((width+3) >> 2) * ((height+3) >> 2) * 16; 211 | compressed = (unsigned char*)malloc( *out_size ); 212 | /* go through each block */ 213 | for( j = 0; j < height; j += 4 ) 214 | { 215 | for( i = 0; i < width; i += 4 ) 216 | { 217 | /* local variables, and my block counter */ 218 | int idx = 0; 219 | int mx = 4, my = 4; 220 | if( j+4 >= height ) 221 | { 222 | my = height - j; 223 | } 224 | if( i+4 >= width ) 225 | { 226 | mx = width - i; 227 | } 228 | for( y = 0; y < my; ++y ) 229 | { 230 | for( x = 0; x < mx; ++x ) 231 | { 232 | ublock[idx++] = uncompressed[(j+y)*width*channels+(i+x)*channels]; 233 | ublock[idx++] = uncompressed[(j+y)*width*channels+(i+x)*channels+chan_step]; 234 | ublock[idx++] = uncompressed[(j+y)*width*channels+(i+x)*channels+chan_step+chan_step]; 235 | ublock[idx++] = 236 | has_alpha * uncompressed[(j+y)*width*channels+(i+x)*channels+channels-1] 237 | + (1-has_alpha)*255; 238 | } 239 | for( x = mx; x < 4; ++x ) 240 | { 241 | ublock[idx++] = ublock[0]; 242 | ublock[idx++] = ublock[1]; 243 | ublock[idx++] = ublock[2]; 244 | ublock[idx++] = ublock[3]; 245 | } 246 | } 247 | for( y = my; y < 4; ++y ) 248 | { 249 | for( x = 0; x < 4; ++x ) 250 | { 251 | ublock[idx++] = ublock[0]; 252 | ublock[idx++] = ublock[1]; 253 | ublock[idx++] = ublock[2]; 254 | ublock[idx++] = ublock[3]; 255 | } 256 | } 257 | /* now compress the alpha block */ 258 | compress_DDS_alpha_block( ublock, cblock ); 259 | /* copy the data from the compressed alpha block into the main buffer */ 260 | for( x = 0; x < 8; ++x ) 261 | { 262 | compressed[index++] = cblock[x]; 263 | } 264 | /* then compress the color block */ 265 | ++block_count; 266 | compress_DDS_color_block( 4, ublock, cblock ); 267 | /* copy the data from the compressed color block into the main buffer */ 268 | for( x = 0; x < 8; ++x ) 269 | { 270 | compressed[index++] = cblock[x]; 271 | } 272 | } 273 | } 274 | return compressed; 275 | } 276 | 277 | /********* Helper Functions *********/ 278 | int convert_bit_range( int c, int from_bits, int to_bits ) 279 | { 280 | int b = (1 << (from_bits - 1)) + c * ((1 << to_bits) - 1); 281 | return (b + (b >> from_bits)) >> from_bits; 282 | } 283 | 284 | int rgb_to_565( int r, int g, int b ) 285 | { 286 | return 287 | (convert_bit_range( r, 8, 5 ) << 11) | 288 | (convert_bit_range( g, 8, 6 ) << 05) | 289 | (convert_bit_range( b, 8, 5 ) << 00); 290 | } 291 | 292 | void rgb_888_from_565( unsigned int c, int *r, int *g, int *b ) 293 | { 294 | *r = convert_bit_range( (c >> 11) & 31, 5, 8 ); 295 | *g = convert_bit_range( (c >> 05) & 63, 6, 8 ); 296 | *b = convert_bit_range( (c >> 00) & 31, 5, 8 ); 297 | } 298 | 299 | void compute_color_line_STDEV( 300 | const unsigned char *const uncompressed, 301 | int channels, 302 | float point[3], float direction[3] ) 303 | { 304 | const float inv_16 = 1.0f / 16.0f; 305 | int i; 306 | float sum_r = 0.0f, sum_g = 0.0f, sum_b = 0.0f; 307 | float sum_rr = 0.0f, sum_gg = 0.0f, sum_bb = 0.0f; 308 | float sum_rg = 0.0f, sum_rb = 0.0f, sum_gb = 0.0f; 309 | /* calculate all data needed for the covariance matrix 310 | ( to compare with _rygdxt code) */ 311 | for( i = 0; i < 16*channels; i += channels ) 312 | { 313 | sum_r += uncompressed[i+0]; 314 | sum_rr += uncompressed[i+0] * uncompressed[i+0]; 315 | sum_g += uncompressed[i+1]; 316 | sum_gg += uncompressed[i+1] * uncompressed[i+1]; 317 | sum_b += uncompressed[i+2]; 318 | sum_bb += uncompressed[i+2] * uncompressed[i+2]; 319 | sum_rg += uncompressed[i+0] * uncompressed[i+1]; 320 | sum_rb += uncompressed[i+0] * uncompressed[i+2]; 321 | sum_gb += uncompressed[i+1] * uncompressed[i+2]; 322 | } 323 | /* convert the sums to averages */ 324 | sum_r *= inv_16; 325 | sum_g *= inv_16; 326 | sum_b *= inv_16; 327 | /* and convert the squares to the squares of the value - avg_value */ 328 | sum_rr -= 16.0f * sum_r * sum_r; 329 | sum_gg -= 16.0f * sum_g * sum_g; 330 | sum_bb -= 16.0f * sum_b * sum_b; 331 | sum_rg -= 16.0f * sum_r * sum_g; 332 | sum_rb -= 16.0f * sum_r * sum_b; 333 | sum_gb -= 16.0f * sum_g * sum_b; 334 | /* the point on the color line is the average */ 335 | point[0] = sum_r; 336 | point[1] = sum_g; 337 | point[2] = sum_b; 338 | #if USE_COV_MAT 339 | /* 340 | The following idea was from ryg. 341 | (https://mollyrocket.com/forums/viewtopic.php?t=392) 342 | The method worked great (less RMSE than mine) most of 343 | the time, but had some issues handling some simple 344 | boundary cases, like full green next to full red, 345 | which would generate a covariance matrix like this: 346 | 347 | | 1 -1 0 | 348 | | -1 1 0 | 349 | | 0 0 0 | 350 | 351 | For a given starting vector, the power method can 352 | generate all zeros! So no starting with {1,1,1} 353 | as I was doing! This kind of error is still a 354 | slight posibillity, but will be very rare. 355 | */ 356 | /* use the covariance matrix directly 357 | (1st iteration, don't use all 1.0 values!) */ 358 | sum_r = 1.0f; 359 | sum_g = 2.718281828f; 360 | sum_b = 3.141592654f; 361 | direction[0] = sum_r*sum_rr + sum_g*sum_rg + sum_b*sum_rb; 362 | direction[1] = sum_r*sum_rg + sum_g*sum_gg + sum_b*sum_gb; 363 | direction[2] = sum_r*sum_rb + sum_g*sum_gb + sum_b*sum_bb; 364 | /* 2nd iteration, use results from the 1st guy */ 365 | sum_r = direction[0]; 366 | sum_g = direction[1]; 367 | sum_b = direction[2]; 368 | direction[0] = sum_r*sum_rr + sum_g*sum_rg + sum_b*sum_rb; 369 | direction[1] = sum_r*sum_rg + sum_g*sum_gg + sum_b*sum_gb; 370 | direction[2] = sum_r*sum_rb + sum_g*sum_gb + sum_b*sum_bb; 371 | /* 3rd iteration, use results from the 2nd guy */ 372 | sum_r = direction[0]; 373 | sum_g = direction[1]; 374 | sum_b = direction[2]; 375 | direction[0] = sum_r*sum_rr + sum_g*sum_rg + sum_b*sum_rb; 376 | direction[1] = sum_r*sum_rg + sum_g*sum_gg + sum_b*sum_gb; 377 | direction[2] = sum_r*sum_rb + sum_g*sum_gb + sum_b*sum_bb; 378 | #else 379 | /* use my standard deviation method 380 | (very robust, a tiny bit slower and less accurate) */ 381 | direction[0] = sqrt( sum_rr ); 382 | direction[1] = sqrt( sum_gg ); 383 | direction[2] = sqrt( sum_bb ); 384 | /* which has a greater component */ 385 | if( sum_gg > sum_rr ) 386 | { 387 | /* green has greater component, so base the other signs off of green */ 388 | if( sum_rg < 0.0f ) 389 | { 390 | direction[0] = -direction[0]; 391 | } 392 | if( sum_gb < 0.0f ) 393 | { 394 | direction[2] = -direction[2]; 395 | } 396 | } else 397 | { 398 | /* red has a greater component */ 399 | if( sum_rg < 0.0f ) 400 | { 401 | direction[1] = -direction[1]; 402 | } 403 | if( sum_rb < 0.0f ) 404 | { 405 | direction[2] = -direction[2]; 406 | } 407 | } 408 | #endif 409 | } 410 | 411 | void LSE_master_colors_max_min( 412 | int *cmax, int *cmin, 413 | int channels, 414 | const unsigned char *const uncompressed ) 415 | { 416 | int i, j; 417 | /* the master colors */ 418 | int c0[3], c1[3]; 419 | /* used for fitting the line */ 420 | float sum_x[] = { 0.0f, 0.0f, 0.0f }; 421 | float sum_x2[] = { 0.0f, 0.0f, 0.0f }; 422 | float dot_max = 1.0f, dot_min = -1.0f; 423 | float vec_len2 = 0.0f; 424 | float dot; 425 | /* error check */ 426 | if( (channels < 3) || (channels > 4) ) 427 | { 428 | return; 429 | } 430 | compute_color_line_STDEV( uncompressed, channels, sum_x, sum_x2 ); 431 | vec_len2 = 1.0f / ( 0.00001f + 432 | sum_x2[0]*sum_x2[0] + sum_x2[1]*sum_x2[1] + sum_x2[2]*sum_x2[2] ); 433 | /* finding the max and min vector values */ 434 | dot_max = 435 | ( 436 | sum_x2[0] * uncompressed[0] + 437 | sum_x2[1] * uncompressed[1] + 438 | sum_x2[2] * uncompressed[2] 439 | ); 440 | dot_min = dot_max; 441 | for( i = 1; i < 16; ++i ) 442 | { 443 | dot = 444 | ( 445 | sum_x2[0] * uncompressed[i*channels+0] + 446 | sum_x2[1] * uncompressed[i*channels+1] + 447 | sum_x2[2] * uncompressed[i*channels+2] 448 | ); 449 | if( dot < dot_min ) 450 | { 451 | dot_min = dot; 452 | } else if( dot > dot_max ) 453 | { 454 | dot_max = dot; 455 | } 456 | } 457 | /* and the offset (from the average location) */ 458 | dot = sum_x2[0]*sum_x[0] + sum_x2[1]*sum_x[1] + sum_x2[2]*sum_x[2]; 459 | dot_min -= dot; 460 | dot_max -= dot; 461 | /* post multiply by the scaling factor */ 462 | dot_min *= vec_len2; 463 | dot_max *= vec_len2; 464 | /* OK, build the master colors */ 465 | for( i = 0; i < 3; ++i ) 466 | { 467 | /* color 0 */ 468 | c0[i] = (int)(0.5f + sum_x[i] + dot_max * sum_x2[i]); 469 | if( c0[i] < 0 ) 470 | { 471 | c0[i] = 0; 472 | } else if( c0[i] > 255 ) 473 | { 474 | c0[i] = 255; 475 | } 476 | /* color 1 */ 477 | c1[i] = (int)(0.5f + sum_x[i] + dot_min * sum_x2[i]); 478 | if( c1[i] < 0 ) 479 | { 480 | c1[i] = 0; 481 | } else if( c1[i] > 255 ) 482 | { 483 | c1[i] = 255; 484 | } 485 | } 486 | /* down_sample (with rounding?) */ 487 | i = rgb_to_565( c0[0], c0[1], c0[2] ); 488 | j = rgb_to_565( c1[0], c1[1], c1[2] ); 489 | if( i > j ) 490 | { 491 | *cmax = i; 492 | *cmin = j; 493 | } else 494 | { 495 | *cmax = j; 496 | *cmin = i; 497 | } 498 | } 499 | 500 | void 501 | compress_DDS_color_block 502 | ( 503 | int channels, 504 | const unsigned char *const uncompressed, 505 | unsigned char compressed[8] 506 | ) 507 | { 508 | /* variables */ 509 | int i; 510 | int next_bit; 511 | int enc_c0, enc_c1; 512 | int c0[4], c1[4]; 513 | float color_line[] = { 0.0f, 0.0f, 0.0f, 0.0f }; 514 | float vec_len2 = 0.0f, dot_offset = 0.0f; 515 | /* stupid order */ 516 | int swizzle4[] = { 0, 2, 3, 1 }; 517 | /* get the master colors */ 518 | LSE_master_colors_max_min( &enc_c0, &enc_c1, channels, uncompressed ); 519 | /* store the 565 color 0 and color 1 */ 520 | compressed[0] = (enc_c0 >> 0) & 255; 521 | compressed[1] = (enc_c0 >> 8) & 255; 522 | compressed[2] = (enc_c1 >> 0) & 255; 523 | compressed[3] = (enc_c1 >> 8) & 255; 524 | /* zero out the compressed data */ 525 | compressed[4] = 0; 526 | compressed[5] = 0; 527 | compressed[6] = 0; 528 | compressed[7] = 0; 529 | /* reconstitute the master color vectors */ 530 | rgb_888_from_565( enc_c0, &c0[0], &c0[1], &c0[2] ); 531 | rgb_888_from_565( enc_c1, &c1[0], &c1[1], &c1[2] ); 532 | /* the new vector */ 533 | vec_len2 = 0.0f; 534 | for( i = 0; i < 3; ++i ) 535 | { 536 | color_line[i] = (float)(c1[i] - c0[i]); 537 | vec_len2 += color_line[i] * color_line[i]; 538 | } 539 | if( vec_len2 > 0.0f ) 540 | { 541 | vec_len2 = 1.0f / vec_len2; 542 | } 543 | /* pre-proform the scaling */ 544 | color_line[0] *= vec_len2; 545 | color_line[1] *= vec_len2; 546 | color_line[2] *= vec_len2; 547 | /* compute the offset (constant) portion of the dot product */ 548 | dot_offset = color_line[0]*c0[0] + color_line[1]*c0[1] + color_line[2]*c0[2]; 549 | /* store the rest of the bits */ 550 | next_bit = 8*4; 551 | for( i = 0; i < 16; ++i ) 552 | { 553 | /* find the dot product of this color, to place it on the line 554 | (should be [-1,1]) */ 555 | int next_value = 0; 556 | float dot_product = 557 | color_line[0] * uncompressed[i*channels+0] + 558 | color_line[1] * uncompressed[i*channels+1] + 559 | color_line[2] * uncompressed[i*channels+2] - 560 | dot_offset; 561 | /* map to [0,3] */ 562 | next_value = (int)( dot_product * 3.0f + 0.5f ); 563 | if( next_value > 3 ) 564 | { 565 | next_value = 3; 566 | } else if( next_value < 0 ) 567 | { 568 | next_value = 0; 569 | } 570 | /* OK, store this value */ 571 | compressed[next_bit >> 3] |= swizzle4[ next_value ] << (next_bit & 7); 572 | next_bit += 2; 573 | } 574 | /* done compressing to DXT1 */ 575 | } 576 | 577 | void 578 | compress_DDS_alpha_block 579 | ( 580 | const unsigned char *const uncompressed, 581 | unsigned char compressed[8] 582 | ) 583 | { 584 | /* variables */ 585 | int i; 586 | int next_bit; 587 | int a0, a1; 588 | float scale_me; 589 | /* stupid order */ 590 | int swizzle8[] = { 1, 7, 6, 5, 4, 3, 2, 0 }; 591 | /* get the alpha limits (a0 > a1) */ 592 | a0 = a1 = uncompressed[3]; 593 | for( i = 4+3; i < 16*4; i += 4 ) 594 | { 595 | if( uncompressed[i] > a0 ) 596 | { 597 | a0 = uncompressed[i]; 598 | } else if( uncompressed[i] < a1 ) 599 | { 600 | a1 = uncompressed[i]; 601 | } 602 | } 603 | /* store those limits, and zero the rest of the compressed dataset */ 604 | compressed[0] = a0; 605 | compressed[1] = a1; 606 | /* zero out the compressed data */ 607 | compressed[2] = 0; 608 | compressed[3] = 0; 609 | compressed[4] = 0; 610 | compressed[5] = 0; 611 | compressed[6] = 0; 612 | compressed[7] = 0; 613 | /* store the all of the alpha values */ 614 | next_bit = 8*2; 615 | scale_me = 7.9999f / (a0 - a1); 616 | for( i = 3; i < 16*4; i += 4 ) 617 | { 618 | /* convert this alpha value to a 3 bit number */ 619 | int svalue; 620 | int value = (int)((uncompressed[i] - a1) * scale_me); 621 | svalue = swizzle8[ value&7 ]; 622 | /* OK, store this value, start with the 1st byte */ 623 | compressed[next_bit >> 3] |= svalue << (next_bit & 7); 624 | if( (next_bit & 7) > 5 ) 625 | { 626 | /* spans 2 bytes, fill in the start of the 2nd byte */ 627 | compressed[1 + (next_bit >> 3)] |= svalue >> (8 - (next_bit & 7) ); 628 | } 629 | next_bit += 3; 630 | } 631 | /* done compressing to DXT1 */ 632 | } 633 | --------------------------------------------------------------------------------