1/* 2 * @author mrdoob / http://mrdoob.com/ 3 */ 4 5THREE.DDSLoader = function ( manager ) { 6 7 THREE.CompressedTextureLoader.call( this, manager ); 8 9 this._parser = THREE.DDSLoader.parse; 10 11}; 12 13THREE.DDSLoader.prototype = Object.create( THREE.CompressedTextureLoader.prototype ); 14THREE.DDSLoader.prototype.constructor = THREE.DDSLoader; 15 16THREE.DDSLoader.parse = function ( buffer, loadMipmaps ) { 17 18 var dds = { mipmaps: [], width: 0, height: 0, format: null, mipmapCount: 1 }; 19 20 // Adapted from @toji's DDS utils 21 // https://github.com/toji/webgl-texture-utils/blob/master/texture-util/dds.js 22 23 // All values and structures referenced from: 24 // http://msdn.microsoft.com/en-us/library/bb943991.aspx/ 25 26 var DDS_MAGIC = 0x20534444; 27 28 var DDSD_CAPS = 0x1, 29 DDSD_HEIGHT = 0x2, 30 DDSD_WIDTH = 0x4, 31 DDSD_PITCH = 0x8, 32 DDSD_PIXELFORMAT = 0x1000, 33 DDSD_MIPMAPCOUNT = 0x20000, 34 DDSD_LINEARSIZE = 0x80000, 35 DDSD_DEPTH = 0x800000; 36 37 var DDSCAPS_COMPLEX = 0x8, 38 DDSCAPS_MIPMAP = 0x400000, 39 DDSCAPS_TEXTURE = 0x1000; 40 41 var DDSCAPS2_CUBEMAP = 0x200, 42 DDSCAPS2_CUBEMAP_POSITIVEX = 0x400, 43 DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800, 44 DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000, 45 DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000, 46 DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000, 47 DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000, 48 DDSCAPS2_VOLUME = 0x200000; 49 50 var DDPF_ALPHAPIXELS = 0x1, 51 DDPF_ALPHA = 0x2, 52 DDPF_FOURCC = 0x4, 53 DDPF_RGB = 0x40, 54 DDPF_YUV = 0x200, 55 DDPF_LUMINANCE = 0x20000; 56 57 function fourCCToInt32( value ) { 58 59 return value.charCodeAt( 0 ) + 60 ( value.charCodeAt( 1 ) << 8 ) + 61 ( value.charCodeAt( 2 ) << 16 ) + 62 ( value.charCodeAt( 3 ) << 24 ); 63 64 } 65 66 function int32ToFourCC( value ) { 67 68 return String.fromCharCode( 69 value & 0xff, 70 ( value >> 8 ) & 0xff, 71 ( value >> 16 ) & 0xff, 72 ( value >> 24 ) & 0xff 73 ); 74 75 } 76 77 function loadARGBMip( buffer, dataOffset, width, height ) { 78 79 var dataLength = width * height * 4; 80 var srcBuffer = new Uint8Array( buffer, dataOffset, dataLength ); 81 var byteArray = new Uint8Array( dataLength ); 82 var dst = 0; 83 var src = 0; 84 for ( var y = 0; y < height; y ++ ) { 85 86 for ( var x = 0; x < width; x ++ ) { 87 88 var b = srcBuffer[ src ]; src ++; 89 var g = srcBuffer[ src ]; src ++; 90 var r = srcBuffer[ src ]; src ++; 91 var a = srcBuffer[ src ]; src ++; 92 byteArray[ dst ] = r; dst ++; //r 93 byteArray[ dst ] = g; dst ++; //g 94 byteArray[ dst ] = b; dst ++; //b 95 byteArray[ dst ] = a; dst ++; //a 96 97 } 98 99 } 100 return byteArray; 101 102 } 103 104 var FOURCC_DXT1 = fourCCToInt32( "DXT1" ); 105 var FOURCC_DXT3 = fourCCToInt32( "DXT3" ); 106 var FOURCC_DXT5 = fourCCToInt32( "DXT5" ); 107 var FOURCC_ETC1 = fourCCToInt32( "ETC1" ); 108 109 var headerLengthInt = 31; // The header length in 32 bit ints 110 111 // Offsets into the header array 112 113 var off_magic = 0; 114 115 var off_size = 1; 116 var off_flags = 2; 117 var off_height = 3; 118 var off_width = 4; 119 120 var off_mipmapCount = 7; 121 122 var off_pfFlags = 20; 123 var off_pfFourCC = 21; 124 var off_RGBBitCount = 22; 125 var off_RBitMask = 23; 126 var off_GBitMask = 24; 127 var off_BBitMask = 25; 128 var off_ABitMask = 26; 129 130 var off_caps = 27; 131 var off_caps2 = 28; 132 var off_caps3 = 29; 133 var off_caps4 = 30; 134 135 // Parse header 136 137 var header = new Int32Array( buffer, 0, headerLengthInt ); 138 139 if ( header[ off_magic ] !== DDS_MAGIC ) { 140 141 console.error( 'THREE.DDSLoader.parse: Invalid magic number in DDS header.' ); 142 return dds; 143 144 } 145 146 if ( ! header[ off_pfFlags ] & DDPF_FOURCC ) { 147 148 console.error( 'THREE.DDSLoader.parse: Unsupported format, must contain a FourCC code.' ); 149 return dds; 150 151 } 152 153 var blockBytes; 154 155 var fourCC = header[ off_pfFourCC ]; 156 157 var isRGBAUncompressed = false; 158 159 switch ( fourCC ) { 160 161 case FOURCC_DXT1: 162 163 blockBytes = 8; 164 dds.format = THREE.RGB_S3TC_DXT1_Format; 165 break; 166 167 case FOURCC_DXT3: 168 169 blockBytes = 16; 170 dds.format = THREE.RGBA_S3TC_DXT3_Format; 171 break; 172 173 case FOURCC_DXT5: 174 175 blockBytes = 16; 176 dds.format = THREE.RGBA_S3TC_DXT5_Format; 177 break; 178 179 case FOURCC_ETC1: 180 181 blockBytes = 8; 182 dds.format = THREE.RGB_ETC1_Format; 183 break; 184 185 default: 186 187 if ( header[ off_RGBBitCount ] === 32 188 && header[ off_RBitMask ] & 0xff0000 189 && header[ off_GBitMask ] & 0xff00 190 && header[ off_BBitMask ] & 0xff 191 && header[ off_ABitMask ] & 0xff000000 ) { 192 193 isRGBAUncompressed = true; 194 blockBytes = 64; 195 dds.format = THREE.RGBAFormat; 196 197 } else { 198 199 console.error( 'THREE.DDSLoader.parse: Unsupported FourCC code ', int32ToFourCC( fourCC ) ); 200 return dds; 201 202 } 203 204 } 205 206 dds.mipmapCount = 1; 207 208 if ( header[ off_flags ] & DDSD_MIPMAPCOUNT && loadMipmaps !== false ) { 209 210 dds.mipmapCount = Math.max( 1, header[ off_mipmapCount ] ); 211 212 } 213 214 var caps2 = header[ off_caps2 ]; 215 dds.isCubemap = caps2 & DDSCAPS2_CUBEMAP ? true : false; 216 if ( dds.isCubemap && ( 217 ! ( caps2 & DDSCAPS2_CUBEMAP_POSITIVEX ) || 218 ! ( caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX ) || 219 ! ( caps2 & DDSCAPS2_CUBEMAP_POSITIVEY ) || 220 ! ( caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY ) || 221 ! ( caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ ) || 222 ! ( caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ ) 223 ) ) { 224 225 console.error( 'THREE.DDSLoader.parse: Incomplete cubemap faces' ); 226 return dds; 227 228 } 229 230 dds.width = header[ off_width ]; 231 dds.height = header[ off_height ]; 232 233 var dataOffset = header[ off_size ] + 4; 234 235 // Extract mipmaps buffers 236 237 var faces = dds.isCubemap ? 6 : 1; 238 239 for ( var face = 0; face < faces; face ++ ) { 240 241 var width = dds.width; 242 var height = dds.height; 243 244 for ( var i = 0; i < dds.mipmapCount; i ++ ) { 245 246 if ( isRGBAUncompressed ) { 247 248 var byteArray = loadARGBMip( buffer, dataOffset, width, height ); 249 var dataLength = byteArray.length; 250 251 } else { 252 253 var dataLength = Math.max( 4, width ) / 4 * Math.max( 4, height ) / 4 * blockBytes; 254 var byteArray = new Uint8Array( buffer, dataOffset, dataLength ); 255 256 } 257
258 var mipmap = { "data": byteArray, "width": width, "height": height }; 259 dds.mipmaps.push( mipmap ); 260 261 dataOffset += dataLength; 262 263 width = Math.max( width >> 1, 1 ); 264 height = Math.max( height >> 1, 1 ); 265 266 } 267 268 } 269 270 return dds; 271 272};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.