the whole game
This commit is contained in:
237
project/iosproj/minecraftpe/PVRTexture.m
Executable file
237
project/iosproj/minecraftpe/PVRTexture.m
Executable file
@@ -0,0 +1,237 @@
|
||||
#import "PVRTexture.h"
|
||||
|
||||
#define PVR_TEXTURE_FLAG_TYPE_MASK 0xff
|
||||
|
||||
static char gPVRTexIdentifier[4] = "PVR!";
|
||||
|
||||
enum
|
||||
{
|
||||
kPVRTextureFlagTypePVRTC_2 = 24,
|
||||
kPVRTextureFlagTypePVRTC_4
|
||||
};
|
||||
|
||||
typedef struct _PVRTexHeader
|
||||
{
|
||||
uint32_t headerLength;
|
||||
uint32_t height;
|
||||
uint32_t width;
|
||||
uint32_t numMipmaps;
|
||||
uint32_t flags;
|
||||
uint32_t dataLength;
|
||||
uint32_t bpp;
|
||||
uint32_t bitmaskRed;
|
||||
uint32_t bitmaskGreen;
|
||||
uint32_t bitmaskBlue;
|
||||
uint32_t bitmaskAlpha;
|
||||
uint32_t pvrTag;
|
||||
uint32_t numSurfs;
|
||||
} PVRTexHeader;
|
||||
|
||||
|
||||
@implementation PVRTexture
|
||||
|
||||
@synthesize name = _name;
|
||||
@synthesize width = _width;
|
||||
@synthesize height = _height;
|
||||
@synthesize internalFormat = _internalFormat;
|
||||
@synthesize hasAlpha = _hasAlpha;
|
||||
|
||||
|
||||
- (BOOL)unpackPVRData:(NSData *)data
|
||||
{
|
||||
BOOL success = FALSE;
|
||||
PVRTexHeader *header = NULL;
|
||||
uint32_t flags, pvrTag;
|
||||
uint32_t dataLength = 0, dataOffset = 0, dataSize = 0;
|
||||
uint32_t blockSize = 0, widthBlocks = 0, heightBlocks = 0;
|
||||
uint32_t width = 0, height = 0, bpp = 4;
|
||||
uint8_t *bytes = NULL;
|
||||
uint32_t formatFlags;
|
||||
|
||||
header = (PVRTexHeader *)[data bytes];
|
||||
|
||||
pvrTag = CFSwapInt32LittleToHost(header->pvrTag);
|
||||
|
||||
if (gPVRTexIdentifier[0] != ((pvrTag >> 0) & 0xff) ||
|
||||
gPVRTexIdentifier[1] != ((pvrTag >> 8) & 0xff) ||
|
||||
gPVRTexIdentifier[2] != ((pvrTag >> 16) & 0xff) ||
|
||||
gPVRTexIdentifier[3] != ((pvrTag >> 24) & 0xff))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
flags = CFSwapInt32LittleToHost(header->flags);
|
||||
formatFlags = flags & PVR_TEXTURE_FLAG_TYPE_MASK;
|
||||
|
||||
if (formatFlags == kPVRTextureFlagTypePVRTC_4 || formatFlags == kPVRTextureFlagTypePVRTC_2)
|
||||
{
|
||||
[_imageData removeAllObjects];
|
||||
|
||||
if (formatFlags == kPVRTextureFlagTypePVRTC_4)
|
||||
_internalFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
|
||||
else if (formatFlags == kPVRTextureFlagTypePVRTC_2)
|
||||
_internalFormat = GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
|
||||
|
||||
_width = width = CFSwapInt32LittleToHost(header->width);
|
||||
_height = height = CFSwapInt32LittleToHost(header->height);
|
||||
|
||||
if (CFSwapInt32LittleToHost(header->bitmaskAlpha))
|
||||
_hasAlpha = TRUE;
|
||||
else
|
||||
_hasAlpha = FALSE;
|
||||
|
||||
dataLength = CFSwapInt32LittleToHost(header->dataLength);
|
||||
|
||||
bytes = ((uint8_t *)[data bytes]) + sizeof(PVRTexHeader);
|
||||
|
||||
// Calculate the data size for each texture level and respect the minimum number of blocks
|
||||
while (dataOffset < dataLength)
|
||||
{
|
||||
if (formatFlags == kPVRTextureFlagTypePVRTC_4)
|
||||
{
|
||||
blockSize = 4 * 4; // Pixel by pixel block size for 4bpp
|
||||
widthBlocks = width / 4;
|
||||
heightBlocks = height / 4;
|
||||
bpp = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
blockSize = 8 * 4; // Pixel by pixel block size for 2bpp
|
||||
widthBlocks = width / 8;
|
||||
heightBlocks = height / 4;
|
||||
bpp = 2;
|
||||
}
|
||||
|
||||
// Clamp to minimum number of blocks
|
||||
if (widthBlocks < 2)
|
||||
widthBlocks = 2;
|
||||
if (heightBlocks < 2)
|
||||
heightBlocks = 2;
|
||||
|
||||
dataSize = widthBlocks * heightBlocks * ((blockSize * bpp) / 8);
|
||||
|
||||
[_imageData addObject:[NSData dataWithBytes:bytes+dataOffset length:dataSize]];
|
||||
|
||||
dataOffset += dataSize;
|
||||
|
||||
width = MAX(width >> 1, 1);
|
||||
height = MAX(height >> 1, 1);
|
||||
}
|
||||
|
||||
success = TRUE;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)createGLTexture
|
||||
{
|
||||
int width = _width;
|
||||
int height = _height;
|
||||
NSData *data;
|
||||
GLenum err;
|
||||
|
||||
if ([_imageData count] > 0)
|
||||
{
|
||||
if (_name != 0)
|
||||
glDeleteTextures(1, &_name);
|
||||
|
||||
glGenTextures(1, &_name);
|
||||
glBindTexture(GL_TEXTURE_2D, _name);
|
||||
}
|
||||
|
||||
if ([_imageData count] > 1) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
}
|
||||
else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
}
|
||||
|
||||
NSLog(@"Image levels: %d\n", [_imageData count]);
|
||||
for (int i=0; i < [_imageData count]; i++)
|
||||
{
|
||||
data = [_imageData objectAtIndex:i];
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, i, _internalFormat, width, height, 0, [data length], [data bytes]);
|
||||
|
||||
err = glGetError();
|
||||
if (err != GL_NO_ERROR)
|
||||
{
|
||||
NSLog(@"Error uploading compressed texture level: %d. glError: 0x%04X", i, err);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
width = MAX(width >> 1, 1);
|
||||
height = MAX(height >> 1, 1);
|
||||
}
|
||||
|
||||
[_imageData removeAllObjects];
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
- (id)initWithContentsOfFile:(NSString *)path
|
||||
{
|
||||
if (self = [super init])
|
||||
{
|
||||
NSData *data = [NSData dataWithContentsOfFile:path];
|
||||
|
||||
_imageData = [[NSMutableArray alloc] initWithCapacity:10];
|
||||
|
||||
_name = 0;
|
||||
_width = _height = 0;
|
||||
_internalFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
|
||||
_hasAlpha = FALSE;
|
||||
|
||||
if (!data || ![self unpackPVRData:data] || ![self createGLTexture])
|
||||
{
|
||||
[self release];
|
||||
self = nil;
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (id)initWithContentsOfURL:(NSURL *)url
|
||||
{
|
||||
if (![url isFileURL])
|
||||
{
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [self initWithContentsOfFile:[url path]];
|
||||
}
|
||||
|
||||
|
||||
+ (id)pvrTextureWithContentsOfFile:(NSString *)path
|
||||
{
|
||||
return [[[self alloc] initWithContentsOfFile:path] autorelease];
|
||||
}
|
||||
|
||||
|
||||
+ (id)pvrTextureWithContentsOfURL:(NSURL *)url
|
||||
{
|
||||
if (![url isFileURL])
|
||||
return nil;
|
||||
|
||||
return [PVRTexture pvrTextureWithContentsOfFile:[url path]];
|
||||
}
|
||||
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[_imageData release];
|
||||
|
||||
if (_name != 0)
|
||||
glDeleteTextures(1, &_name);
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user