| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 | import {	CompressedTextureLoader,	RGBA_PVRTC_2BPPV1_Format,	RGBA_PVRTC_4BPPV1_Format,	RGB_PVRTC_2BPPV1_Format,	RGB_PVRTC_4BPPV1_Format} from '../../../build/three.module.js';/* *	 PVR v2 (legacy) parser *   TODO : Add Support for PVR v3 format *   TODO : implement loadMipmaps option */class PVRLoader extends CompressedTextureLoader {	constructor( manager ) {		super( manager );	}	parse( buffer, loadMipmaps ) {		const headerLengthInt = 13;		const header = new Uint32Array( buffer, 0, headerLengthInt );		const pvrDatas = {			buffer: buffer,			header: header,			loadMipmaps: loadMipmaps		};		if ( header[ 0 ] === 0x03525650 ) {			// PVR v3			return _parseV3( pvrDatas );		} else if ( header[ 11 ] === 0x21525650 ) {			// PVR v2			return _parseV2( pvrDatas );		} else {			console.error( 'THREE.PVRLoader: Unknown PVR format.' );		}	}}function _parseV3( pvrDatas ) {	const header = pvrDatas.header;	let bpp, format;	const metaLen = header[ 12 ],		pixelFormat = header[ 2 ],		height = header[ 6 ],		width = header[ 7 ],		// numSurfs = header[ 9 ],		numFaces = header[ 10 ],		numMipmaps = header[ 11 ];	switch ( pixelFormat ) {		case 0 : // PVRTC 2bpp RGB			bpp = 2;			format = RGB_PVRTC_2BPPV1_Format;			break;		case 1 : // PVRTC 2bpp RGBA			bpp = 2;			format = RGBA_PVRTC_2BPPV1_Format;			break;		case 2 : // PVRTC 4bpp RGB			bpp = 4;			format = RGB_PVRTC_4BPPV1_Format;			break;		case 3 : // PVRTC 4bpp RGBA			bpp = 4;			format = RGBA_PVRTC_4BPPV1_Format;			break;		default :			console.error( 'THREE.PVRLoader: Unsupported PVR format:', pixelFormat );	}	pvrDatas.dataPtr = 52 + metaLen;	pvrDatas.bpp = bpp;	pvrDatas.format = format;	pvrDatas.width = width;	pvrDatas.height = height;	pvrDatas.numSurfaces = numFaces;	pvrDatas.numMipmaps = numMipmaps;	pvrDatas.isCubemap 	= ( numFaces === 6 );	return _extract( pvrDatas );}function _parseV2( pvrDatas ) {	const header = pvrDatas.header;	const headerLength = header[ 0 ],		height = header[ 1 ],		width = header[ 2 ],		numMipmaps = header[ 3 ],		flags = header[ 4 ],		// dataLength = header[ 5 ],		// bpp =  header[ 6 ],		// bitmaskRed = header[ 7 ],		// bitmaskGreen = header[ 8 ],		// bitmaskBlue = header[ 9 ],		bitmaskAlpha = header[ 10 ],		// pvrTag = header[ 11 ],		numSurfs = header[ 12 ];	const TYPE_MASK = 0xff;	const PVRTC_2 = 24,		PVRTC_4 = 25;	const formatFlags = flags & TYPE_MASK;	let bpp, format;	const _hasAlpha = bitmaskAlpha > 0;	if ( formatFlags === PVRTC_4 ) {		format = _hasAlpha ? RGBA_PVRTC_4BPPV1_Format : RGB_PVRTC_4BPPV1_Format;		bpp = 4;	} else if ( formatFlags === PVRTC_2 ) {		format = _hasAlpha ? RGBA_PVRTC_2BPPV1_Format : RGB_PVRTC_2BPPV1_Format;		bpp = 2;	} else {		console.error( 'THREE.PVRLoader: Unknown PVR format:', formatFlags );	}	pvrDatas.dataPtr = headerLength;	pvrDatas.bpp = bpp;	pvrDatas.format = format;	pvrDatas.width = width;	pvrDatas.height = height;	pvrDatas.numSurfaces = numSurfs;	pvrDatas.numMipmaps = numMipmaps + 1;	// guess cubemap type seems tricky in v2	// it juste a pvr containing 6 surface (no explicit cubemap type)	pvrDatas.isCubemap 	= ( numSurfs === 6 );	return _extract( pvrDatas );}function _extract( pvrDatas ) {	const pvr = {		mipmaps: [],		width: pvrDatas.width,		height: pvrDatas.height,		format: pvrDatas.format,		mipmapCount: pvrDatas.numMipmaps,		isCubemap: pvrDatas.isCubemap	};	const buffer = pvrDatas.buffer;	let dataOffset = pvrDatas.dataPtr,		dataSize = 0,		blockSize = 0,		blockWidth = 0,		blockHeight = 0,		widthBlocks = 0,		heightBlocks = 0;	const bpp = pvrDatas.bpp,		numSurfs = pvrDatas.numSurfaces;	if ( bpp === 2 ) {		blockWidth = 8;		blockHeight = 4;	} else {		blockWidth = 4;		blockHeight = 4;	}	blockSize = ( blockWidth * blockHeight ) * bpp / 8;	pvr.mipmaps.length = pvrDatas.numMipmaps * numSurfs;	let mipLevel = 0;	while ( mipLevel < pvrDatas.numMipmaps ) {		const sWidth = pvrDatas.width >> mipLevel,			sHeight = pvrDatas.height >> mipLevel;		widthBlocks = sWidth / blockWidth;		heightBlocks = sHeight / blockHeight;		// Clamp to minimum number of blocks		if ( widthBlocks < 2 ) widthBlocks = 2;		if ( heightBlocks < 2 ) heightBlocks = 2;		dataSize = widthBlocks * heightBlocks * blockSize;		for ( let surfIndex = 0; surfIndex < numSurfs; surfIndex ++ ) {			const byteArray = new Uint8Array( buffer, dataOffset, dataSize );			const mipmap = {				data: byteArray,				width: sWidth,				height: sHeight			};			pvr.mipmaps[ surfIndex * pvrDatas.numMipmaps + mipLevel ] = mipmap;			dataOffset += dataSize;		}		mipLevel ++;	}	return pvr;}export { PVRLoader };
 |