27
#include "NuxCore/NKernel.h"
28
#include "BitmapFormats.h"
31
const char *result_string_pointer = "SOIL initialized";
33
// compressed texture types
34
static const unsigned long FOURCC_DXT1 = 0x31545844l; //(MAKEFOURCC('D','X','T','1'))
35
static const unsigned long FOURCC_DXT3 = 0x33545844l; //(MAKEFOURCC('D','X','T','3'))
36
static const unsigned long FOURCC_DXT5 = 0x35545844l; //(MAKEFOURCC('D','X','T','5'))
41
NBitmapData* Load_DDS_File(const TCHAR *filename)
46
struct _stat file_info;
48
struct stat file_info;
51
// System call: check if the file exist
53
if(_stat(filename, &file_info) != 0)
55
if(stat(filename, &file_info) != 0)
58
nuxAssertMsg(0, TEXT("[Load_DDS_File] File not found."));
62
file.open(filename, std::ifstream::binary); // open as binary
65
nuxAssertMsg(0, TEXT("[Load_DDS_File] Cannot open file."));
72
file.seekg(0, std::ios_base::end);
73
buffer_length = file.tellg();
74
file.seekg(0, std::ios_base::beg);
75
buffer = new BYTE[buffer_length];
76
file.read((char*)buffer, buffer_length);
77
if(file.fail() || file.eof())
79
nuxAssertMsg(0, TEXT("[Load_DDS_File] Cannot read the expected content size."));
85
unsigned int buffer_index = 0;
86
unsigned int tex_ID = 0;
87
/* file reading variables */
88
BitmapFormat DDSFormat = BITFMT_UNKNOWN;
89
unsigned int DDS_main_size;
90
unsigned int DDS_full_size;
91
unsigned int width, height;
92
int mipmaps, uncompressed, block_size = 16;
93
bool isCubemap = false;
94
bool isVolume = false;
96
unsigned int cf_target, ogl_target_start, ogl_target_end;
99
NBitmapData* BitmapData = 0;
101
/* 1st off, does the filename even exist? */
104
/* we can't do it! */
105
result_string_pointer = "NULL buffer";
108
if( buffer_length < sizeof( DDS_header ) )
110
/* we can't do it! */
111
result_string_pointer = "DDS file was too small to contain the DDS header";
114
/* try reading in the header */
115
memcpy ( (void*)(&header), (const void *)buffer, sizeof( DDS_header ) );
116
buffer_index = sizeof( DDS_header );
117
/* guilty until proven innocent */
118
result_string_pointer = "Failed to read a known DDS header";
119
/* validate the header (warning, "goto"'s ahead, shield your eyes!!) */
120
flag = ('D'<<0)|('D'<<8)|('S'<<16)|(' '<<24);
121
if( header.dwMagic != flag ) {goto quick_exit;}
122
if( header.dwSize != 124 ) {goto quick_exit;}
124
/* I need all of these */
125
flag = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
126
if( (header.dwFlags & flag) != flag ) {goto quick_exit;}
127
/* According to the MSDN spec, the dwFlags should contain
128
DDSD_LINEARSIZE if it's compressed, or DDSD_PITCH if
129
uncompressed. Some DDS writers do not conform to the
130
spec, so I need to make my reader more tolerant */
131
/* I need one of these */
133
// DDPF_RGB - Texture contains uncompressed RGB data; dwRGBBitCount and the RGB masks (dwRBitMask, dwRBitMask, dwRBitMask) contain valid data.
134
// DDPF_FOURCC - Texture contains compressed RGB data; dwFourCC contains valid data.
135
flag = DDPF_FOURCC | DDPF_RGB;
136
if( (header.sPixelFormat.dwFlags & flag) == 0 ) {goto quick_exit;}
137
if( (header.sPixelFormat.dwRGBAlphaBitMask & DDPF_ALPHAPIXELS))
139
// texture has valid alpha data.
140
// check dwRGBAlphaBitMask for alpha mask
142
if( header.sPixelFormat.dwSize != 32 ) {goto quick_exit;}
143
if( (header.sCaps.dwCaps1 & DDSCAPS_TEXTURE) == 0 ) {goto quick_exit;}
144
/* make sure it is a type we can upload */
145
if( (header.sPixelFormat.dwFlags & DDPF_FOURCC) &&
147
(header.sPixelFormat.dwFourCC == (('D'<<0)|('X'<<8)|('T'<<16)|('1'<<24))) ||
148
(header.sPixelFormat.dwFourCC == (('D'<<0)|('X'<<8)|('T'<<16)|('2'<<24))) ||
149
(header.sPixelFormat.dwFourCC == (('D'<<0)|('X'<<8)|('T'<<16)|('3'<<24))) ||
150
(header.sPixelFormat.dwFourCC == (('D'<<0)|('X'<<8)|('T'<<16)|('4'<<24))) ||
151
(header.sPixelFormat.dwFourCC == (('D'<<0)|('X'<<8)|('T'<<16)|('5'<<24)))
156
/* OK, validated the header, let's load the image data */
157
result_string_pointer = "DDS header loaded and validated";
158
width = header.dwWidth;
159
height = header.dwHeight;
160
//uncompressed = 1 - (header.sPixelFormat.dwFlags & DDPF_FOURCC) / DDPF_FOURCC;
161
if(header.sPixelFormat.dwFlags & DDPF_FOURCC)
166
isCubemap = (header.sCaps.dwCaps2 & DDSCAPS2_CUBEMAP) / DDSCAPS2_CUBEMAP;
167
isVolume = (header.sCaps.dwCaps2 & DDSCAPS2_VOLUME);
171
if( header.sPixelFormat.dwRGBBitCount == 32 )
173
if((header.sPixelFormat.dwRBitMask & 0x00FF0000) &&
174
(header.sPixelFormat.dwGBitMask & 0x0000FF00) &&
175
(header.sPixelFormat.dwBBitMask & 0x000000FF) &&
176
(header.sPixelFormat.dwRGBAlphaBitMask & 0xFF000000))
177
DDSFormat = BITFMT_B8G8R8A8;
179
else if((header.sPixelFormat.dwRBitMask & 0x000000FF) &&
180
(header.sPixelFormat.dwGBitMask & 0x0000FF00) &&
181
(header.sPixelFormat.dwBBitMask & 0x00FF0000) &&
182
(header.sPixelFormat.dwRGBAlphaBitMask & 0xFF000000))
183
DDSFormat = BITFMT_R8G8B8A8;
185
else if((header.sPixelFormat.dwRBitMask & 0xFF000000) &&
186
(header.sPixelFormat.dwGBitMask & 0x00FF0000) &&
187
(header.sPixelFormat.dwBBitMask & 0x0000FF00) &&
188
(header.sPixelFormat.dwRGBAlphaBitMask & 0x000000FF))
189
DDSFormat = BITFMT_A8B8G8R8;
191
else if((header.sPixelFormat.dwRBitMask & 0x0000FF00) &&
192
(header.sPixelFormat.dwGBitMask & 0x00FF0000) &&
193
(header.sPixelFormat.dwBBitMask & 0xFF000000) &&
194
(header.sPixelFormat.dwRGBAlphaBitMask & 0x000000FF))
195
DDSFormat = BITFMT_A8R8G8B8;
197
else if((header.sPixelFormat.dwRBitMask & 0x00FF0000) &&
198
(header.sPixelFormat.dwGBitMask & 0x0000FF00) &&
199
(header.sPixelFormat.dwBBitMask & 0x000000FF))
200
DDSFormat = BITFMT_B8G8R8A8; // DirectX X8R8G8B8
202
else if((header.sPixelFormat.dwRBitMask & 0x000000FF) &&
203
(header.sPixelFormat.dwGBitMask & 0x0000FF00) &&
204
(header.sPixelFormat.dwBBitMask & 0x00FF0000))
205
DDSFormat = BITFMT_R8G8B8A8; // DirexctX X8B8G8R8
209
else if( header.sPixelFormat.dwRGBBitCount == 24 )
211
if((header.sPixelFormat.dwRBitMask & 0x00FF0000) &&
212
(header.sPixelFormat.dwGBitMask & 0x0000FF00) &&
213
(header.sPixelFormat.dwBBitMask & 0x000000FF) )
214
DDSFormat = BITFMT_B8G8R8;
216
else if((header.sPixelFormat.dwRBitMask & 0x000000FF) &&
217
(header.sPixelFormat.dwGBitMask & 0x0000FF00) &&
218
(header.sPixelFormat.dwBBitMask & 0x00FF0000) )
219
DDSFormat = BITFMT_R8G8B8;
223
else if( header.sPixelFormat.dwRGBBitCount == 16 )
225
DDSFormat = BITFMT_R5G6B5;
228
else if( header.sPixelFormat.dwRGBBitCount == 16 )
230
DDSFormat = BITFMT_A8;
233
DDS_main_size = width * height * block_size;
237
/* well, we know it is DXT1/3/5, because we checked above */
238
switch( (header.sPixelFormat.dwFourCC >> 24) - '0' )
241
DDSFormat = BITFMT_DXT1;
245
DDSFormat = BITFMT_DXT2;
249
DDSFormat = BITFMT_DXT3;
253
DDSFormat = BITFMT_DXT4;
257
DDSFormat = BITFMT_DXT5;
261
DDS_main_size = ((width+3)>>2)*((height+3)>>2)*block_size;
266
ogl_target_start = 0;
268
BitmapData = (NBitmapData*) new NCubemapData(DDSFormat, width, height, (header.dwMipMapCount? header.dwMipMapCount:1));
272
int slice = header.dwDepth;
274
BitmapData = (NBitmapData*) new NVolumeData(DDSFormat, width, height, slice, (header.dwMipMapCount? header.dwMipMapCount:1));
278
ogl_target_start = 0;
280
BitmapData = (NBitmapData*) new NTextureData(DDSFormat, width, height, (header.dwMipMapCount? header.dwMipMapCount:1));
283
if( (header.sCaps.dwCaps1 & DDSCAPS_MIPMAP) && (header.dwMipMapCount > 1) )
285
mipmaps = header.dwMipMapCount;
287
else if(header.dwMipMapCount == 1)
289
mipmaps = header.dwMipMapCount;
290
DDS_full_size = DDS_main_size;
292
else if(header.dwMipMapCount == 0)
295
DDS_full_size = DDS_main_size;
300
for(t_u32 mip = 0; mip < mipmaps; ++mip )
302
t_u32 pitch = ImageSurface::GetLevelPitchNoMemAlignment(DDSFormat, width, height, mip);
303
t_u32 blockheight = ImageSurface::GetLevelBlockHeight(DDSFormat, height, mip);
305
for(t_u32 s = 0; s < ImageSurface::GetLevelDim(DDSFormat, VolumeDepth, mip); s++ )
307
for(t_u32 b = 0; b < blockheight; b++)
309
Memcpy( BitmapData->GetSurface(mip, s).GetPtrRawData() + b * pitch,
310
(const void*)(&buffer[buffer_index + b * pitch]),
314
//BitmapData->GetSurface(mip, s).FlipVertical();
315
buffer_index += blockheight * pitch;
321
for( cf_target = ogl_target_start; cf_target < ogl_target_end; ++cf_target )
323
for( int mip = 0; mip < mipmaps; ++mip )
325
int pitch = ImageSurface::GetLevelPitchNoMemAlignment(DDSFormat, width, height, mip);
326
int blockheight = ImageSurface::GetLevelBlockHeight(DDSFormat, height, mip);
328
for(int b = 0; b < blockheight; b++)
330
Memcpy( BitmapData->GetSurface(cf_target, mip).GetPtrRawData() + b * pitch,
331
(const void*)(&buffer[buffer_index + b * pitch]),
335
//BitmapData->GetSurface(cf_target, mip).FlipVertical();
336
buffer_index += blockheight * pitch;
342
/* report success or failure */
27
#include "NuxCore/NKernel.h"
28
#include "BitmapFormats.h"
31
const char *result_string_pointer = "SOIL initialized";
33
// compressed texture types
34
static const unsigned long FOURCC_DXT1 = 0x31545844l; //(MAKEFOURCC('D','X','T','1'))
35
static const unsigned long FOURCC_DXT3 = 0x33545844l; //(MAKEFOURCC('D','X','T','3'))
36
static const unsigned long FOURCC_DXT5 = 0x35545844l; //(MAKEFOURCC('D','X','T','5'))
41
NBitmapData* Load_DDS_File(const TCHAR *filename)
46
struct _stat file_info;
48
struct stat file_info;
51
// System call: check if the file exist
53
if(_stat(filename, &file_info) != 0)
55
if(stat(filename, &file_info) != 0)
58
nuxAssertMsg(0, TEXT("[Load_DDS_File] File not found."));
62
file.open(filename, std::ifstream::binary); // open as binary
65
nuxAssertMsg(0, TEXT("[Load_DDS_File] Cannot open file."));
72
file.seekg(0, std::ios_base::end);
73
buffer_length = file.tellg();
74
file.seekg(0, std::ios_base::beg);
75
buffer = new BYTE[buffer_length];
76
file.read((char*)buffer, buffer_length);
77
if(file.fail() || file.eof())
79
nuxAssertMsg(0, TEXT("[Load_DDS_File] Cannot read the expected content size."));
85
unsigned int buffer_index = 0;
86
unsigned int tex_ID = 0;
87
/* file reading variables */
88
BitmapFormat DDSFormat = BITFMT_UNKNOWN;
89
unsigned int DDS_main_size;
90
unsigned int DDS_full_size;
91
unsigned int width, height;
92
int mipmaps, uncompressed, block_size = 16;
93
bool isCubemap = false;
94
bool isVolume = false;
96
unsigned int cf_target, ogl_target_start, ogl_target_end;
99
NBitmapData* BitmapData = 0;
101
/* 1st off, does the filename even exist? */
104
/* we can't do it! */
105
result_string_pointer = "NULL buffer";
108
if( buffer_length < sizeof( DDS_header ) )
110
/* we can't do it! */
111
result_string_pointer = "DDS file was too small to contain the DDS header";
114
/* try reading in the header */
115
memcpy ( (void*)(&header), (const void *)buffer, sizeof( DDS_header ) );
116
buffer_index = sizeof( DDS_header );
117
/* guilty until proven innocent */
118
result_string_pointer = "Failed to read a known DDS header";
119
/* validate the header (warning, "goto"'s ahead, shield your eyes!!) */
120
flag = ('D'<<0)|('D'<<8)|('S'<<16)|(' '<<24);
121
if( header.dwMagic != flag ) {goto quick_exit;}
122
if( header.dwSize != 124 ) {goto quick_exit;}
124
/* I need all of these */
125
flag = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
126
if( (header.dwFlags & flag) != flag ) {goto quick_exit;}
127
/* According to the MSDN spec, the dwFlags should contain
128
DDSD_LINEARSIZE if it's compressed, or DDSD_PITCH if
129
uncompressed. Some DDS writers do not conform to the
130
spec, so I need to make my reader more tolerant */
131
/* I need one of these */
133
// DDPF_RGB - Texture contains uncompressed RGB data; dwRGBBitCount and the RGB masks (dwRBitMask, dwRBitMask, dwRBitMask) contain valid data.
134
// DDPF_FOURCC - Texture contains compressed RGB data; dwFourCC contains valid data.
135
flag = DDPF_FOURCC | DDPF_RGB;
136
if( (header.sPixelFormat.dwFlags & flag) == 0 ) {goto quick_exit;}
137
if( (header.sPixelFormat.dwRGBAlphaBitMask & DDPF_ALPHAPIXELS))
139
// texture has valid alpha data.
140
// check dwRGBAlphaBitMask for alpha mask
142
if( header.sPixelFormat.dwSize != 32 ) {goto quick_exit;}
143
if( (header.sCaps.dwCaps1 & DDSCAPS_TEXTURE) == 0 ) {goto quick_exit;}
144
/* make sure it is a type we can upload */
145
if( (header.sPixelFormat.dwFlags & DDPF_FOURCC) &&
147
(header.sPixelFormat.dwFourCC == (('D'<<0)|('X'<<8)|('T'<<16)|('1'<<24))) ||
148
(header.sPixelFormat.dwFourCC == (('D'<<0)|('X'<<8)|('T'<<16)|('2'<<24))) ||
149
(header.sPixelFormat.dwFourCC == (('D'<<0)|('X'<<8)|('T'<<16)|('3'<<24))) ||
150
(header.sPixelFormat.dwFourCC == (('D'<<0)|('X'<<8)|('T'<<16)|('4'<<24))) ||
151
(header.sPixelFormat.dwFourCC == (('D'<<0)|('X'<<8)|('T'<<16)|('5'<<24)))
156
/* OK, validated the header, let's load the image data */
157
result_string_pointer = "DDS header loaded and validated";
158
width = header.dwWidth;
159
height = header.dwHeight;
160
//uncompressed = 1 - (header.sPixelFormat.dwFlags & DDPF_FOURCC) / DDPF_FOURCC;
161
if(header.sPixelFormat.dwFlags & DDPF_FOURCC)
166
isCubemap = (header.sCaps.dwCaps2 & DDSCAPS2_CUBEMAP) / DDSCAPS2_CUBEMAP;
167
isVolume = (header.sCaps.dwCaps2 & DDSCAPS2_VOLUME);
171
if( header.sPixelFormat.dwRGBBitCount == 32 )
173
if((header.sPixelFormat.dwRBitMask & 0x00FF0000) &&
174
(header.sPixelFormat.dwGBitMask & 0x0000FF00) &&
175
(header.sPixelFormat.dwBBitMask & 0x000000FF) &&
176
(header.sPixelFormat.dwRGBAlphaBitMask & 0xFF000000))
177
DDSFormat = BITFMT_B8G8R8A8;
179
else if((header.sPixelFormat.dwRBitMask & 0x000000FF) &&
180
(header.sPixelFormat.dwGBitMask & 0x0000FF00) &&
181
(header.sPixelFormat.dwBBitMask & 0x00FF0000) &&
182
(header.sPixelFormat.dwRGBAlphaBitMask & 0xFF000000))
183
DDSFormat = BITFMT_R8G8B8A8;
185
else if((header.sPixelFormat.dwRBitMask & 0xFF000000) &&
186
(header.sPixelFormat.dwGBitMask & 0x00FF0000) &&
187
(header.sPixelFormat.dwBBitMask & 0x0000FF00) &&
188
(header.sPixelFormat.dwRGBAlphaBitMask & 0x000000FF))
189
DDSFormat = BITFMT_A8B8G8R8;
191
else if((header.sPixelFormat.dwRBitMask & 0x0000FF00) &&
192
(header.sPixelFormat.dwGBitMask & 0x00FF0000) &&
193
(header.sPixelFormat.dwBBitMask & 0xFF000000) &&
194
(header.sPixelFormat.dwRGBAlphaBitMask & 0x000000FF))
195
DDSFormat = BITFMT_A8R8G8B8;
197
else if((header.sPixelFormat.dwRBitMask & 0x00FF0000) &&
198
(header.sPixelFormat.dwGBitMask & 0x0000FF00) &&
199
(header.sPixelFormat.dwBBitMask & 0x000000FF))
200
DDSFormat = BITFMT_B8G8R8A8; // DirectX X8R8G8B8
202
else if((header.sPixelFormat.dwRBitMask & 0x000000FF) &&
203
(header.sPixelFormat.dwGBitMask & 0x0000FF00) &&
204
(header.sPixelFormat.dwBBitMask & 0x00FF0000))
205
DDSFormat = BITFMT_R8G8B8A8; // DirexctX X8B8G8R8
209
else if( header.sPixelFormat.dwRGBBitCount == 24 )
211
if((header.sPixelFormat.dwRBitMask & 0x00FF0000) &&
212
(header.sPixelFormat.dwGBitMask & 0x0000FF00) &&
213
(header.sPixelFormat.dwBBitMask & 0x000000FF) )
214
DDSFormat = BITFMT_B8G8R8;
216
else if((header.sPixelFormat.dwRBitMask & 0x000000FF) &&
217
(header.sPixelFormat.dwGBitMask & 0x0000FF00) &&
218
(header.sPixelFormat.dwBBitMask & 0x00FF0000) )
219
DDSFormat = BITFMT_R8G8B8;
223
else if( header.sPixelFormat.dwRGBBitCount == 16 )
225
DDSFormat = BITFMT_R5G6B5;
228
else if( header.sPixelFormat.dwRGBBitCount == 16 )
230
DDSFormat = BITFMT_A8;
233
DDS_main_size = width * height * block_size;
237
/* well, we know it is DXT1/3/5, because we checked above */
238
switch( (header.sPixelFormat.dwFourCC >> 24) - '0' )
241
DDSFormat = BITFMT_DXT1;
245
DDSFormat = BITFMT_DXT2;
249
DDSFormat = BITFMT_DXT3;
253
DDSFormat = BITFMT_DXT4;
257
DDSFormat = BITFMT_DXT5;
261
DDS_main_size = ((width+3)>>2)*((height+3)>>2)*block_size;
266
ogl_target_start = 0;
268
BitmapData = (NBitmapData*) new NCubemapData(DDSFormat, width, height, (header.dwMipMapCount? header.dwMipMapCount:1));
272
int slice = header.dwDepth;
274
BitmapData = (NBitmapData*) new NVolumeData(DDSFormat, width, height, slice, (header.dwMipMapCount? header.dwMipMapCount:1));
278
ogl_target_start = 0;
280
BitmapData = (NBitmapData*) new NTextureData(DDSFormat, width, height, (header.dwMipMapCount? header.dwMipMapCount:1));
283
if( (header.sCaps.dwCaps1 & DDSCAPS_MIPMAP) && (header.dwMipMapCount > 1) )
285
mipmaps = header.dwMipMapCount;
287
else if(header.dwMipMapCount == 1)
289
mipmaps = header.dwMipMapCount;
290
DDS_full_size = DDS_main_size;
292
else if(header.dwMipMapCount == 0)
295
DDS_full_size = DDS_main_size;
300
for(t_u32 mip = 0; mip < mipmaps; ++mip )
302
t_u32 pitch = ImageSurface::GetLevelPitchNoMemAlignment(DDSFormat, width, height, mip);
303
t_u32 blockheight = ImageSurface::GetLevelBlockHeight(DDSFormat, height, mip);
305
for(t_u32 s = 0; s < ImageSurface::GetLevelDim(DDSFormat, VolumeDepth, mip); s++ )
307
for(t_u32 b = 0; b < blockheight; b++)
309
Memcpy( BitmapData->GetSurface(mip, s).GetPtrRawData() + b * pitch,
310
(const void*)(&buffer[buffer_index + b * pitch]),
314
//BitmapData->GetSurface(mip, s).FlipVertical();
315
buffer_index += blockheight * pitch;
321
for( cf_target = ogl_target_start; cf_target < ogl_target_end; ++cf_target )
323
for( int mip = 0; mip < mipmaps; ++mip )
325
int pitch = ImageSurface::GetLevelPitchNoMemAlignment(DDSFormat, width, height, mip);
326
int blockheight = ImageSurface::GetLevelBlockHeight(DDSFormat, height, mip);
328
for(int b = 0; b < blockheight; b++)
330
Memcpy( BitmapData->GetSurface(cf_target, mip).GetPtrRawData() + b * pitch,
331
(const void*)(&buffer[buffer_index + b * pitch]),
335
//BitmapData->GetSurface(cf_target, mip).FlipVertical();
336
buffer_index += blockheight * pitch;
342
/* report success or failure */