aboutsummaryrefslogtreecommitdiff
path: root/src/textures.c
diff options
context:
space:
mode:
authorRay <raysan5@gmail.com>2014-04-19 14:21:22 +0200
committerRay <raysan5@gmail.com>2014-04-19 14:21:22 +0200
commit650a8f7f159d3ce2addb1b0fdb31c3f460005391 (patch)
tree01f1a6968b784d07d63f6bf741c1527145cea25c /src/textures.c
parent1c8dce429ee5a58d535fcca0e29fe3711aa3fcb5 (diff)
parente6b82cb111c3485c5e6131fe29791f938305bce3 (diff)
downloadraylib-650a8f7f159d3ce2addb1b0fdb31c3f460005391.tar.gz
raylib-650a8f7f159d3ce2addb1b0fdb31c3f460005391.zip
Merge pull request #2 from raysan5/testing
Integrate raylib 1.1 changes into master
Diffstat (limited to 'src/textures.c')
-rw-r--r--src/textures.c593
1 files changed, 369 insertions, 224 deletions
diff --git a/src/textures.c b/src/textures.c
index ca0492c4..7d4a0fb4 100644
--- a/src/textures.c
+++ b/src/textures.c
@@ -28,12 +28,13 @@
#include "raylib.h"
-#include <GL/gl.h> // OpenGL functions
#include <stdlib.h> // Declares malloc() and free() for memory management
+#include <string.h> // Required for strcmp(), strrchr(), strncmp()
#include "stb_image.h" // Used to read image data (multiple formats support)
-
#include "utils.h" // rRES data decompression utility function
+#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2
+
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
@@ -44,15 +45,29 @@
//----------------------------------------------------------------------------------
typedef unsigned char byte;
+typedef struct {
+ unsigned char *data;
+ int width;
+ int height;
+ int mipmaps;
+ int format;
+} ImageDDS;
+
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
// It's lonely here...
//----------------------------------------------------------------------------------
+// Other Modules Functions Declaration (required by text)
+//----------------------------------------------------------------------------------
+//...
+
+//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
-// No private (static) functions in this module (.c file)
+static const char *GetExtension(const char *fileName);
+static ImageDDS LoadDDS(const char *fileName);
//----------------------------------------------------------------------------------
// Module Functions Definition
@@ -63,32 +78,44 @@ Image LoadImage(const char *fileName)
{
Image image;
- int imgWidth;
- int imgHeight;
- int imgBpp;
-
- // NOTE: Using stb_image to load images (Supports: BMP, TGA, PNG, JPG, ...)
- // Force loading to 4 components (RGBA)
- byte *imgData = stbi_load(fileName, &imgWidth, &imgHeight, &imgBpp, 4);
-
- // Convert array to pixel array for working convenience
- image.pixels = (Color *)malloc(imgWidth * imgHeight * sizeof(Color));
-
- int pix = 0;
-
- for (int i = 0; i < (imgWidth * imgHeight * 4); i += 4)
- {
- image.pixels[pix].r = imgData[i];
- image.pixels[pix].g = imgData[i+1];
- image.pixels[pix].b = imgData[i+2];
- image.pixels[pix].a = imgData[i+3];
- pix++;
+ if ((strcmp(GetExtension(fileName),"png") == 0) ||
+ (strcmp(GetExtension(fileName),"bmp") == 0) ||
+ (strcmp(GetExtension(fileName),"tga") == 0) ||
+ (strcmp(GetExtension(fileName),"jpg") == 0) ||
+ (strcmp(GetExtension(fileName),"gif") == 0) ||
+ (strcmp(GetExtension(fileName),"psd") == 0) ||
+ (strcmp(GetExtension(fileName),"pic") == 0))
+ {
+ int imgWidth;
+ int imgHeight;
+ int imgBpp;
+
+ // NOTE: Using stb_image to load images (Supports: BMP, TGA, PNG, JPG, ...)
+ // Force loading to 4 components (RGBA)
+ byte *imgData = stbi_load(fileName, &imgWidth, &imgHeight, &imgBpp, 4);
+
+ // Convert array to pixel array for working convenience
+ image.pixels = (Color *)malloc(imgWidth * imgHeight * sizeof(Color));
+
+ int pix = 0;
+
+ for (int i = 0; i < (imgWidth * imgHeight * 4); i += 4)
+ {
+ image.pixels[pix].r = imgData[i];
+ image.pixels[pix].g = imgData[i+1];
+ image.pixels[pix].b = imgData[i+2];
+ image.pixels[pix].a = imgData[i+3];
+ pix++;
+ }
+
+ stbi_image_free(imgData);
+
+ image.width = imgWidth;
+ image.height = imgHeight;
+
+ TraceLog(INFO, "[%s] Image loaded successfully", fileName);
}
-
- stbi_image_free(imgData);
-
- image.width = imgWidth;
- image.height = imgHeight;
+ else TraceLog(WARNING, "[%s] Image extension not recognized, it can't be loaded", fileName);
// ALTERNATIVE: We can load pixel data directly into Color struct pixels array,
// to do that struct data alignment should be the right one (4 byte); it is.
@@ -113,103 +140,104 @@ Image LoadImageFromRES(const char *rresName, int resId)
FILE *rresFile = fopen(rresName, "rb");
- if (!rresFile) printf("Error opening raylib Resource file\n");
-
- // Read rres file (basic file check - id)
- fread(&id[0], sizeof(char), 1, rresFile);
- fread(&id[1], sizeof(char), 1, rresFile);
- fread(&id[2], sizeof(char), 1, rresFile);
- fread(&id[3], sizeof(char), 1, rresFile);
- fread(&version, sizeof(char), 1, rresFile);
- fread(&useless, sizeof(char), 1, rresFile);
-
- if ((id[0] != 'r') && (id[1] != 'R') && (id[2] != 'E') &&(id[3] != 'S'))
- {
- printf("This is not a valid raylib Resource file!\n");
- exit(1);
- }
-
- // Read number of resources embedded
- fread(&numRes, sizeof(short), 1, rresFile);
-
- for (int i = 0; i < numRes; i++)
+ if (!rresFile) TraceLog(WARNING, "[%s] Could not open raylib resource file", rresName);
+ else
{
- fread(&infoHeader, sizeof(ResInfoHeader), 1, rresFile);
+ // Read rres file (basic file check - id)
+ fread(&id[0], sizeof(char), 1, rresFile);
+ fread(&id[1], sizeof(char), 1, rresFile);
+ fread(&id[2], sizeof(char), 1, rresFile);
+ fread(&id[3], sizeof(char), 1, rresFile);
+ fread(&version, sizeof(char), 1, rresFile);
+ fread(&useless, sizeof(char), 1, rresFile);
- if (infoHeader.id == resId)
+ if ((id[0] != 'r') && (id[1] != 'R') && (id[2] != 'E') &&(id[3] != 'S'))
{
- found = true;
+ TraceLog(WARNING, "[%s] This is not a valid raylib resource file", rresName);
+ }
+ else
+ {
+ // Read number of resources embedded
+ fread(&numRes, sizeof(short), 1, rresFile);
- // Check data is of valid IMAGE type
- if (infoHeader.type == 0) // IMAGE data type
+ for (int i = 0; i < numRes; i++)
{
- // TODO: Check data compression type
+ fread(&infoHeader, sizeof(ResInfoHeader), 1, rresFile);
- // NOTE: We suppose compression type 2 (DEFLATE - default)
- short imgWidth, imgHeight;
- char colorFormat, mipmaps;
-
- fread(&imgWidth, sizeof(short), 1, rresFile); // Image width
- fread(&imgHeight, sizeof(short), 1, rresFile); // Image height
- fread(&colorFormat, 1, 1, rresFile); // Image data color format (default: RGBA 32 bit)
- fread(&mipmaps, 1, 1, rresFile); // Mipmap images included (default: 0)
-
- printf("Image width: %i\n", (int)imgWidth);
- printf("Image height: %i\n", (int)imgHeight);
-
- image.width = (int)imgWidth;
- image.height = (int)imgHeight;
+ if (infoHeader.id == resId)
+ {
+ found = true;
+
+ // Check data is of valid IMAGE type
+ if (infoHeader.type == 0) // IMAGE data type
+ {
+ // TODO: Check data compression type
+
+ // NOTE: We suppose compression type 2 (DEFLATE - default)
+ short imgWidth, imgHeight;
+ char colorFormat, mipmaps;
+
+ fread(&imgWidth, sizeof(short), 1, rresFile); // Image width
+ fread(&imgHeight, sizeof(short), 1, rresFile); // Image height
+ fread(&colorFormat, 1, 1, rresFile); // Image data color format (default: RGBA 32 bit)
+ fread(&mipmaps, 1, 1, rresFile); // Mipmap images included (default: 0)
- unsigned char *data = malloc(infoHeader.size);
+ image.width = (int)imgWidth;
+ image.height = (int)imgHeight;
+
+ unsigned char *data = malloc(infoHeader.size);
- fread(data, infoHeader.size, 1, rresFile);
-
- unsigned char *imgData = DecompressData(data, infoHeader.size, infoHeader.srcSize);
-
- image.pixels = (Color *)malloc(sizeof(Color)*imgWidth*imgHeight);
-
- int pix = 0;
-
- for (int i = 0; i < (imgWidth*imgHeight*4); i += 4)
+ fread(data, infoHeader.size, 1, rresFile);
+
+ unsigned char *imgData = DecompressData(data, infoHeader.size, infoHeader.srcSize);
+
+ image.pixels = (Color *)malloc(sizeof(Color)*imgWidth*imgHeight);
+
+ int pix = 0;
+
+ for (int i = 0; i < (imgWidth*imgHeight*4); i += 4)
+ {
+ image.pixels[pix].r = imgData[i];
+ image.pixels[pix].g = imgData[i+1];
+ image.pixels[pix].b = imgData[i+2];
+ image.pixels[pix].a = imgData[i+3];
+ pix++;
+ }
+
+ free(imgData);
+
+ free(data);
+
+ TraceLog(INFO, "[%s] Image loaded successfully from resource, size: %ix%i", rresName, image.width, image.height);
+ }
+ else
+ {
+ TraceLog(WARNING, "[%s] Required resource do not seem to be a valid IMAGE resource", rresName);
+ }
+ }
+ else
{
- image.pixels[pix].r = imgData[i];
- image.pixels[pix].g = imgData[i+1];
- image.pixels[pix].b = imgData[i+2];
- image.pixels[pix].a = imgData[i+3];
- pix++;
+ // Depending on type, skip the right amount of parameters
+ switch (infoHeader.type)
+ {
+ case 0: fseek(rresFile, 6, SEEK_CUR); break; // IMAGE: Jump 6 bytes of parameters
+ case 1: fseek(rresFile, 6, SEEK_CUR); break; // SOUND: Jump 6 bytes of parameters
+ case 2: fseek(rresFile, 5, SEEK_CUR); break; // MODEL: Jump 5 bytes of parameters (TODO: Review)
+ case 3: break; // TEXT: No parameters
+ case 4: break; // RAW: No parameters
+ default: break;
+ }
+
+ // Jump DATA to read next infoHeader
+ fseek(rresFile, infoHeader.size, SEEK_CUR);
}
-
- free(imgData);
-
- free(data);
- }
- else
- {
- printf("Required resource do not seem to be a valid IMAGE resource\n");
- exit(2);
}
}
- else
- {
- // Depending on type, skip the right amount of parameters
- switch (infoHeader.type)
- {
- case 0: fseek(rresFile, 6, SEEK_CUR); break; // IMAGE: Jump 6 bytes of parameters
- case 1: fseek(rresFile, 6, SEEK_CUR); break; // SOUND: Jump 6 bytes of parameters
- case 2: fseek(rresFile, 5, SEEK_CUR); break; // MODEL: Jump 5 bytes of parameters (TODO: Review)
- case 3: break; // TEXT: No parameters
- case 4: break; // RAW: No parameters
- default: break;
- }
-
- // Jump DATA to read next infoHeader
- fseek(rresFile, infoHeader.size, SEEK_CUR);
- }
+
+ fclose(rresFile);
}
- fclose(rresFile);
-
- if (!found) printf("Required resource id could not be found in the raylib Resource file!\n");
+ if (!found) TraceLog(WARNING, "[%s] Required resource id [%i] could not be found in the raylib resource file", rresName, resId);
return image;
}
@@ -218,11 +246,33 @@ Image LoadImageFromRES(const char *rresName, int resId)
Texture2D LoadTexture(const char *fileName)
{
Texture2D texture;
- Image image;
-
- image = LoadImage(fileName);
- texture = CreateTexture(image);
- UnloadImage(image);
+
+ if (strcmp(GetExtension(fileName),"dds") == 0)
+ {
+#ifdef USE_OPENGL_11
+ TraceLog(WARNING, "[%s] DDS file loading requires OpenGL 3.2+ or ES 2.0", fileName);
+#else
+ ImageDDS image = LoadDDS(fileName);
+
+ texture.glId = rlglLoadCompressedTexture(image.data, image.width, image.height, image.mipmaps, image.format);
+
+ texture.width = image.width;
+ texture.height = image.height;
+
+ if (texture.glId == 0) TraceLog(WARNING, "Compressed texture could not be loaded");
+ else TraceLog(INFO, "Compressed texture loaded succesfully");
+#endif
+ }
+ else
+ {
+ Image image = LoadImage(fileName);
+
+ if (image.pixels != NULL)
+ {
+ texture = CreateTexture(image);
+ UnloadImage(image);
+ }
+ }
return texture;
}
@@ -238,43 +288,6 @@ Texture2D LoadTextureFromRES(const char *rresName, int resId)
return texture;
}
-// Create a Texture2D from Image data
-// NOTE: Image is not unloaded, it should be done manually...
-Texture2D CreateTexture(Image image)
-{
- Texture2D texture;
-
- // Convert image data to OpenGL texture
- //----------------------------------------
- GLuint id;
- glGenTextures(1, &id); // Generate Pointer to the Texture
-
- glBindTexture(GL_TEXTURE_2D, id);
-
- // NOTE: glTexParameteri does NOT affect texture uploading, just the way it's used!
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture to repead on x-axis
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture to repead on y-axis
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR
-
- // Trilinear filtering
- //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // Activate use of mipmaps (must be available)
- //glGenerateMipmap(GL_TEXTURE_2D); // OpenGL 3.3!
-
- // Upload texture to GPU
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, image.width, image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image.pixels);
-
- // NOTE: Not using mipmappings (texture for 2D drawing)
- // At this point we have the image converted to texture and uploaded to GPU
-
- texture.glId = id;
- texture.width = image.width;
- texture.height = image.height;
-
- return texture;
-}
-
// Unload image from CPU memory (RAM)
void UnloadImage(Image image)
{
@@ -284,13 +297,13 @@ void UnloadImage(Image image)
// Unload texture from GPU memory
void UnloadTexture(Texture2D texture)
{
- glDeleteTextures(1, &texture.glId);
+ rlDeleteTextures(texture.glId);
}
// Draw a Texture2D
void DrawTexture(Texture2D texture, int posX, int posY, Color tint)
{
- DrawTextureEx(texture, (Vector2){ (float)posX, (float)posY}, 0, 1.0f, tint);
+ DrawTextureEx(texture, (Vector2){ (float)posX, (float)posY }, 0, 1.0f, tint);
}
// Draw a Texture2D with position defined as Vector2
@@ -302,101 +315,233 @@ void DrawTextureV(Texture2D texture, Vector2 position, Color tint)
// Draw a Texture2D with extended parameters
void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint)
{
- glEnable(GL_TEXTURE_2D); // Enable textures usage
-
- glBindTexture(GL_TEXTURE_2D, texture.glId);
-
- glPushMatrix();
- // NOTE: Rotation is applied before translation and scaling, even being called in inverse order...
- // NOTE: Rotation point is upper-left corner
- glTranslatef(position.x, position.y, 0);
- glScalef(scale, scale, 1.0f);
- glRotatef(rotation, 0, 0, 1);
-
- glBegin(GL_QUADS);
- glColor4ub(tint.r, tint.g, tint.b, tint.a);
- glNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
- glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f); // Bottom-left corner for texture and quad
- glTexCoord2f(1.0f, 0.0f); glVertex2f(texture.width, 0.0f); // Bottom-right corner for texture and quad
- glTexCoord2f(1.0f, 1.0f); glVertex2f(texture.width, texture.height); // Top-right corner for texture and quad
- glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, texture.height); // Top-left corner for texture and quad
- glEnd();
- glPopMatrix();
+ rlEnableTexture(texture.glId);
+
+ // NOTE: Rotation is applied before translation and scaling, even being called in inverse order...
+ // NOTE: Rotation point is upper-left corner
+ rlPushMatrix();
+ //rlTranslatef(position.x, position.y, 0.0);
+ rlRotatef(rotation, 0, 0, 1);
+ rlScalef(scale, scale, 1.0f);
+
+ rlBegin(RL_QUADS);
+ rlColor4ub(tint.r, tint.g, tint.b, tint.a);
+ rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
+
+ rlTexCoord2f(0.0f, 0.0f);
+ rlVertex2f(position.x, position.y); // Bottom-left corner for texture and quad
+
+ rlTexCoord2f(0.0f, 1.0f);
+ rlVertex2f(position.x, position.y + texture.height); // Bottom-right corner for texture and quad
+
+ rlTexCoord2f(1.0f, 1.0f);
+ rlVertex2f(position.x + texture.width, position.y + texture.height); // Top-right corner for texture and quad
+
+ rlTexCoord2f(1.0f, 0.0f);
+ rlVertex2f(position.x + texture.width, position.y); // Top-left corner for texture and quad
+ rlEnd();
+ rlPopMatrix();
- glDisable(GL_TEXTURE_2D); // Disable textures usage
+ rlDisableTexture();
}
// Draw a part of a texture (defined by a rectangle)
void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint)
{
- glEnable(GL_TEXTURE_2D); // Enable textures usage
-
- glBindTexture(GL_TEXTURE_2D, texture.glId);
+ rlEnableTexture(texture.glId);
- glPushMatrix();
- glTranslatef(position.x, position.y, 0);
- //glScalef(1.0f, 1.0f, 1.0f);
- //glRotatef(rotation, 0, 0, 1);
+ rlBegin(RL_QUADS);
+ rlColor4ub(tint.r, tint.g, tint.b, tint.a);
+ rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
+
+ // Bottom-left corner for texture and quad
+ rlTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height);
+ rlVertex2f(position.x, position.y);
+
+ // Bottom-right corner for texture and quad
+ rlTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
+ rlVertex2f(position.x, position.y + sourceRec.height);
- glBegin(GL_QUADS);
- glColor4ub(tint.r, tint.g, tint.b, tint.a);
- glNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
+ // Top-right corner for texture and quad
+ rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
+ rlVertex2f(position.x + sourceRec.width, position.y + sourceRec.height);
+
+ // Top-left corner for texture and quad
+ rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height);
+ rlVertex2f(position.x + sourceRec.width, position.y);
+ rlEnd();
+
+ rlDisableTexture();
+}
+
+// Draw a part of a texture (defined by a rectangle) with 'pro' parameters
+// TODO: Test this function...
+void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, Vector2 origin, float rotation, Color tint)
+{
+ rlEnableTexture(texture.glId);
+
+ // NOTE: First we translate texture to origin to apply rotation and translation from there
+ rlPushMatrix();
+ rlTranslatef(-origin.x, -origin.y, 0);
+ rlRotatef(rotation, 0, 0, 1);
+ rlTranslatef(destRec.x + origin.x, destRec.y + origin.y, 0);
+
+ rlBegin(RL_QUADS);
+ rlColor4ub(tint.r, tint.g, tint.b, tint.a);
+ rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
// Bottom-left corner for texture and quad
- glTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height);
- glVertex2f(0.0f, 0.0f);
+ rlTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height);
+ rlVertex2f(0.0f, 0.0f);
// Bottom-right corner for texture and quad
- glTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height);
- glVertex2f(sourceRec.width, 0.0f);
+ rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height);
+ rlVertex2f(destRec.width, 0.0f);
// Top-right corner for texture and quad
- glTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
- glVertex2f(sourceRec.width, sourceRec.height);
+ rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
+ rlVertex2f(destRec.width, destRec.height);
// Top-left corner for texture and quad
- glTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
- glVertex2f(0.0f, sourceRec.height);
- glEnd();
- glPopMatrix();
+ rlTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
+ rlVertex2f(0.0f, destRec.height);
+ rlEnd();
+ rlPopMatrix();
- glDisable(GL_TEXTURE_2D); // Disable textures usage
+ rlDisableTexture();
}
-// Draw a part of a texture (defined by a rectangle) with 'pro' parameters
-// TODO: Test this function...
-void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, Vector2 origin, float rotation, Color tint)
+Texture2D CreateTexture(Image image)
{
- glEnable(GL_TEXTURE_2D); // Enable textures usage
+ Texture2D texture;
+
+ unsigned char *img = malloc(image.width * image.height * 4);
+
+ int j = 0;
+
+ for (int i = 0; i < image.width * image.height * 4; i += 4)
+ {
+ img[i] = image.pixels[j].r;
+ img[i+1] = image.pixels[j].g;
+ img[i+2] = image.pixels[j].b;
+ img[i+3] = image.pixels[j].a;
+
+ j++;
+ }
+
+ texture.glId = rlglLoadTexture(image.width, image.height, img);
+
+ texture.width = image.width;
+ texture.height = image.height;
+
+ TraceLog(INFO, "Texture created succesfully");
+
+ free(img);
- glBindTexture(GL_TEXTURE_2D, texture.glId);
+ return texture;
+}
+
+// Get the extension for a filename
+static const char *GetExtension(const char *fileName)
+{
+ const char *dot = strrchr(fileName, '.');
+ if(!dot || dot == fileName) return "";
+ return (dot + 1);
+}
+
+// Loading DDS image compressed data
+ImageDDS LoadDDS(const char *fileName)
+{
+ // TODO: Review and expand DDS file loading to support uncompressed formats and new formats
+
+ // DDS Pixel Format
+ typedef struct {
+ unsigned int size;
+ unsigned int flags;
+ unsigned int fourCC;
+ unsigned int rgbBitCount;
+ unsigned int rBitMask;
+ unsigned int gBitMask;
+ unsigned int bitMask;
+ unsigned int aBitMask;
+ } ddsPixelFormat;
+
+ // DDS Header (124 bytes)
+ typedef struct {
+ unsigned int size;
+ unsigned int flags;
+ unsigned int height;
+ unsigned int width;
+ unsigned int pitchOrLinearSize;
+ unsigned int depth;
+ unsigned int mipMapCount;
+ unsigned int reserved1[11];
+ ddsPixelFormat ddspf;
+ unsigned int caps;
+ unsigned int caps2;
+ unsigned int caps3;
+ unsigned int caps4;
+ unsigned int reserved2;
+ } ddsHeader;
+
+ ImageDDS image;
+ ddsHeader header;
+
+ FILE *ddsFile = fopen(fileName, "rb");
- glPushMatrix();
- glTranslatef(-origin.x, -origin.y, 0);
- glRotatef(rotation, 0, 0, 1);
- glTranslatef(destRec.x + origin.x, destRec.y + origin.y, 0);
+ if (ddsFile == NULL)
+ {
+ TraceLog(WARNING, "DDS File could not be opened");
+ }
+ else
+ {
+ // Verify the type of file
+ char filecode[4];
+
+ fread(filecode, 1, 4, ddsFile);
- glBegin(GL_QUADS);
- glColor4ub(tint.r, tint.g, tint.b, tint.a);
- glNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
+ if (strncmp(filecode, "DDS ", 4) != 0)
+ {
+ TraceLog(WARNING, "DDS File does not seem to be valid");
+ fclose(ddsFile);
+ }
+ else
+ {
+ // Get the surface descriptor
+ fread(&header, sizeof(ddsHeader), 1, ddsFile);
+
+ int height = header.height;
+ int width = header.width;
+ int linearSize = header.pitchOrLinearSize;
+ int mipMapCount = header.mipMapCount;
+ int fourCC = header.ddspf.fourCC;
- // Bottom-left corner for texture and quad
- glTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height);
- glVertex2f(0.0f, 0.0f);
+ TraceLog(DEBUG, "[%s] DDS file header size: %i", fileName, sizeof(ddsHeader));
- // Bottom-right corner for texture and quad
- glTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height);
- glVertex2f(destRec.width, 0.0f);
+ TraceLog(DEBUG, "[%s] DDS file pixel format size: %i", fileName, header.ddspf.size);
+ TraceLog(DEBUG, "[%s] DDS file pixel format flags: 0x%x", fileName, header.ddspf.flags);
+ TraceLog(DEBUG, "[%s] DDS file format: 0x%x", fileName, fourCC);
- // Top-right corner for texture and quad
- glTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
- glVertex2f(destRec.width, destRec.height);
+ int bufsize;
- // Top-left corner for texture and quad
- glTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
- glVertex2f(0.0f, destRec.height);
- glEnd();
- glPopMatrix();
+ // Calculate data size, including all mipmaps
+ bufsize = mipMapCount > 1 ? linearSize * 2 : linearSize;
+
+ image.data = (unsigned char*)malloc(bufsize * sizeof(unsigned char));
+
+ fread(image.data, 1, bufsize, ddsFile);
+
+ // Close file pointer
+ fclose(ddsFile);
+
+ //int components = (fourCC == FOURCC_DXT1) ? 3 : 4; // Not required
+
+ image.width = width;
+ image.height = height;
+ image.mipmaps = mipMapCount;
+ image.format = fourCC;
+ }
+ }
- glDisable(GL_TEXTURE_2D); // Disable textures usage
+ return image;
} \ No newline at end of file