├── 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 |
--------------------------------------------------------------------------------