/*----------------------------------------------------------------------------- Name : btgGetTexture Description : creates a GL texture object with the contents of the given .TGA file Inputs : filename - the name of the bitmap, in btg\bitmaps thandle - place where the texture name goes width, height - dimensions of the bitmap Outputs : thandle, width, height are modified Return : ----------------------------------------------------------------------------*/ void btgGetTexture(char* filename, udword* thandle, sdword* width, sdword* height) { char fullname[64]; ubyte* data; ubyte* pdata; ubyte* bp; unsigned short* psdata; TGAFileHeader head; sdword i; #ifdef _WIN32 #ifdef _WIN32_FIXME strcpy(fullname, "btg\\bitmaps\\b01.tga"); #else strcpy(fullname, "btg\\bitmaps\\"); #endif #else strcpy(fullname, "btg/bitmaps/"); #endif strcat(fullname, filename); if (fileExists(fullname, 0)) { fileLoadAlloc(fullname, (void**)&data, 0); //this pointer wackiness gets around alignment strangeness pdata = data; head.idLength = *pdata++; head.colorMapType = *pdata++; head.imageType = *pdata++; psdata = (unsigned short*)pdata; #if FIX_ENDIAN head.colorMapStartIndex = FIX_ENDIAN_INT_16( *psdata ); pdata += 2; psdata = (unsigned short*)pdata; head.colorMapNumEntries = FIX_ENDIAN_INT_16( *psdata ); pdata += 2; head.colorMapBitsPerEntry = *pdata++; psdata = (unsigned short*)pdata; head.imageOffsetX = (signed short)FIX_ENDIAN_INT_16( *psdata ); pdata += 2; psdata = (unsigned short*)pdata; head.imageOffsetY = (signed short)FIX_ENDIAN_INT_16( *psdata ); pdata += 2; psdata = (unsigned short*)pdata; head.imageWidth = FIX_ENDIAN_INT_16( *psdata ); pdata += 2; psdata = (unsigned short*)pdata; head.imageHeight = FIX_ENDIAN_INT_16( *psdata ); #else head.colorMapStartIndex = *psdata; pdata += 2; psdata = (unsigned short*)pdata; head.colorMapNumEntries = *psdata; pdata += 2; head.colorMapBitsPerEntry = *pdata++; psdata = (unsigned short*)pdata; head.imageOffsetX = (signed short)*psdata; pdata += 2; psdata = (unsigned short*)pdata; head.imageOffsetY = (signed short)*psdata; pdata += 2; psdata = (unsigned short*)pdata; head.imageWidth = *psdata; pdata += 2; psdata = (unsigned short*)pdata; head.imageHeight = *psdata; #endif // FIX_ENDIAN pdata += 2; head.pixelDepth = *pdata++; head.imageDescriptor = *pdata++; //only 32bit TGAs dbgAssertOrIgnore(head.pixelDepth == 32); pdata += head.idLength; *width = (sdword)head.imageWidth; *height = (sdword)head.imageHeight; //convert to GL_RGBA for (i = 0, bp = pdata; i < 4*(*width)*(*height); i += 4, bp += 4) { ubyte r, b; r = bp[0]; b = bp[2]; bp[0] = b; bp[2] = r; bp[3] = (ubyte)(255 - (int)bp[3]); } //create the GL texture object glGenTextures(1, thandle); glBindTexture(GL_TEXTURE_2D, *thandle); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, *width, *height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pdata); memFree(data); } else { *thandle = 0; *width = 0; *height = 0; } }
/*----------------------------------------------------------------------------- Name : madFileLoad Description : Load in a .MAD mesh animation file Inputs : fileName - name of file to load Outputs : Return : newly allocated animation data Note : the string block for binding information is allocated as a separate block of memory so it can be freed after all animation binding is complete. ----------------------------------------------------------------------------*/ madheader *madFileLoad(char *fileName) { madheader header; madheader *newHeader; sdword index, j; filehandle file; sdword fileSize; #ifdef _X86_64 char newFileName[80]; sprintf(newFileName, "%s.64",fileName); fileName = newFileName; #endif dbgAssertOrIgnore(fileName != NULL); fileSize = fileSizeGet(fileName, 0); file = fileOpen(fileName, 0); fileBlockRead(file, &header, madHeaderSize(0)); #if FIX_ENDIAN header.version = FIX_ENDIAN_FLOAT_32( header.version ); header.stringBlockLength = FIX_ENDIAN_INT_32( header.stringBlockLength ); header.stringBlock = ( char *)FIX_ENDIAN_INT_32( ( udword )header.stringBlock ); header.length = FIX_ENDIAN_FLOAT_32( header.length ); header.framesPerSecond = FIX_ENDIAN_FLOAT_32( header.framesPerSecond ); header.nObjects = FIX_ENDIAN_INT_32( header.nObjects ); header.objPath = ( madobjpath *)FIX_ENDIAN_INT_32( ( udword )header.objPath ); header.nAnimations = FIX_ENDIAN_INT_32( header.nAnimations ); #endif #if MAD_ERROR_CHECKING if (strcmp(header.identifier, MAD_FileIdentifier) != 0) { dbgFatalf(DBG_Loc, "Invalid header in '%s'. Expected '%s', found '%s'.", fileName, MAD_FileIdentifier, header.identifier); } if (header.version != MAD_FileVersion) { dbgFatalf(DBG_Loc, "Invalid file version in '%s'. Expected %.2f, found %.2f", fileName, MAD_FileVersion, header.version); } if (header.nAnimations > MAD_MaxAnimations) { dbgFatalf(DBG_Loc, "Too many animations in '%s': %d", fileName, header.nAnimations); } #endif newHeader = memAlloc(fileSize - header.stringBlockLength, "meshAnimation", NonVolatile); *newHeader = header; fileBlockRead(file, &newHeader->anim[0], fileSize - newHeader->stringBlockLength - madHeaderSize(0)); newHeader->stringBlock = memAlloc(newHeader->stringBlockLength, "madStringBlock", NonVolatile);//!!!should this be non volatile? I guess it depends on how soon the string block is freed, if ever. fileBlockRead(file, newHeader->stringBlock, newHeader->stringBlockLength); fileClose(file); #if MAD_VERBOSE_LEVEL >= 2 dbgMessagef("madFileLoad: loaded %d animations for %d objects from '%s'", newHeader->nAnimations, newHeader->nObjects, fileName); #endif //loop through all the structures and fix up pointers for (index = 0; index < newHeader->nAnimations; index++) { //fixup the name of all animations #if FIX_ENDIAN newHeader->anim[index].name = ( char *)FIX_ENDIAN_INT_32( ( memsize )newHeader->anim[index].name ); newHeader->anim[index].startTime = FIX_ENDIAN_FLOAT_32( newHeader->anim[index].startTime ); newHeader->anim[index].endTime = FIX_ENDIAN_FLOAT_32( newHeader->anim[index].endTime ); newHeader->anim[index].flags = FIX_ENDIAN_INT_32( newHeader->anim[index].flags ); #endif newHeader->anim[index].name += (memsize)newHeader->stringBlock; } newHeader->objPath = (madobjpath *)((memsize)newHeader + (ubyte *)newHeader->objPath); for (index = 0; index < newHeader->nObjects; index++) { #if FIX_ENDIAN newHeader->objPath[index].name = ( char *)FIX_ENDIAN_INT_32( ( memsize )newHeader->objPath[index].name ); newHeader->objPath[index].nameCRC = FIX_ENDIAN_INT_16( newHeader->objPath[index].nameCRC ); newHeader->objPath[index].animationBits = FIX_ENDIAN_INT_32( newHeader->objPath[index].animationBits ); newHeader->objPath[index].nKeyframes = FIX_ENDIAN_INT_32( newHeader->objPath[index].nKeyframes ); newHeader->objPath[index].times = ( real32 *)FIX_ENDIAN_INT_32( ( udword )newHeader->objPath[index].times ); newHeader->objPath[index].parameters = ( tcb *)FIX_ENDIAN_INT_32( ( udword )newHeader->objPath[index].parameters ); #endif newHeader->objPath[index].name += (memsize)newHeader->stringBlock;//fixup name newHeader->objPath[index].nameCRC = crc16Compute((ubyte *)newHeader->objPath[index].name, strlen(newHeader->objPath[index].name)); newHeader->objPath[index].times = (real32 *)((memsize)newHeader + (ubyte *)newHeader->objPath[index].times);//fixup times pointers newHeader->objPath[index].parameters = (tcb *)((memsize)newHeader + (ubyte *)newHeader->objPath[index].parameters);//fixup times pointers for (j = 0; j < 6; j++) { //fixup the motion path array pointers #if FIX_ENDIAN newHeader->objPath[index].path[j] = ( real32 *)FIX_ENDIAN_INT_32( ( udword )newHeader->objPath[index].path[j] ); #endif newHeader->objPath[index].path[j] = (real32 *)((memsize)newHeader + (ubyte *)newHeader->objPath[index].path[j]); } #if FIX_ENDIAN for( j = 0; j < newHeader->objPath[index].nKeyframes; j++ ) { int k = 0; newHeader->objPath[index].times[j] = FIX_ENDIAN_FLOAT_32( newHeader->objPath[index].times[j] ); newHeader->objPath[index].parameters[j].tension = FIX_ENDIAN_FLOAT_32( newHeader->objPath[index].parameters[j].tension ); newHeader->objPath[index].parameters[j].continuity = FIX_ENDIAN_FLOAT_32( newHeader->objPath[index].parameters[j].continuity ); newHeader->objPath[index].parameters[j].bias = FIX_ENDIAN_FLOAT_32( newHeader->objPath[index].parameters[j].bias ); for( k = 0; k < 6; k++ ) { newHeader->objPath[index].path[k][j] = FIX_ENDIAN_FLOAT_32( newHeader->objPath[index].path[k][j] ); } } #endif } return(newHeader); }