Compressed Textures from Apple's texturetool

View previous topic View next topic Go down

Compressed Textures from Apple's texturetool

Post  zzajin on Wed Nov 12, 2008 9:10 pm

So I thought I would have this out sooner, but I just found out that Imagination Tech provides some code in their SDK that will decompress images. Integrating this significantly streamlines the code and workflow, so I added it to SIO2. However it's unclear to me if a custom importer for Blender could be made, so the managing of images for Blender isn't as clean. In order to do this with Blender I've added a bit of meta data in the filename. Which also allows you know something about the images in Finder. I haven't integrated alpha yet, but I wanted to see if there is any feedback.

I should point out these changes are for a workflow which utilizes the raw PVRTC compressed data that Apple's texturetool produces. And not for Imagination Tech's pvrtc file format. Also mipmaps are not supported.

You should read this Q&A doc on Apple's texturetool if you haven't.
http://developer.apple.com/iphone/library/qa/qa2008/qa1611.html


Apple's texturetool will generate 2 files for each compression type - a png for previewing and an .att (Apple texture tool) file for the compressed data. The files will be of the following format [original filename][meta data].pvr.png for the preview png and [original filename][meta data].att for the compressed data.

meta data is ['_'][bits per pixel: '2' or '4'][channel weighting type: 'l' or 'p'][mipmap level][alpha: '1' or '0'][size of square image as a power of two -2]

Here is an example: checkerboard_4p006.pvr.png and checkerboard_4p006.att
The original image was checkerboard.jpg.

zzajin

Posts : 81
Join date : 2008-10-14

View user profile

Back to top Go down

Workflow

Post  zzajin on Wed Nov 12, 2008 9:15 pm

The basic workflow is like this:

1. Create assets as normal.
2. To compress an image I have written a Blender script which uses the CURRENT IMAGE. The current image is selected in Blender's UV/Image Editor window. You will find the script in the Image menu of the UV/Image Editor window or in the sub-menu image in a Scripts window.
3. The script has a number of options and when loaded it will display the current image it will work on.

The first is the output directory for the images that Apple's texturetool will generate. This is not the same as SIO2's exporter: feel free to put these images where ever you want.

There are toggles for the 4 different types of compression.

Two toggles for loading the images into blender after they have been created. By default I've unselected .att since they can't be displayed anyway, but you may want to load them to pack them into a .blend file or keep reference of them.

Level is a placeholder for now - ignore it for now.

Run will run the texturetool. Keep in mind that it may take awhile. There is feedback on the progress.

4. After you have decided which compressed image to use, make sure the png preview is properly applied to your model: shows up in the UV window when the model is in edit mode and applied in the texture buttons window.

5. Export SIO2 as normal. When the preview texture is exported the script will look for the corresponding .att file and copy that into the SIO2 archive. The exporter will just change the .pvr.png extention to .att. So don't change the names of files that are produced by the texturetool and keep the .pvr.png and .att files in the same directory.

6. SIO2 will decompress any .att images in the simulator during loading and on an iPhone will load the compressed data .

zzajin

Posts : 81
Join date : 2008-10-14

View user profile

Back to top Go down

Add imagination tech's decompress code

Post  zzajin on Wed Nov 12, 2008 9:27 pm

Add the following 2 files to the project and make sure the file type is sourcecode.cpp.objcpp


sio2_decompresspvr.h:

Code:


#ifndef SIO2_DECOMPRESSPVR_H
#define SIO2_DECOMPRESSPVR_H


#include <assert.h>

const unsigned int ETC_MIN_TEXWIDTH         = 4;
const unsigned int ETC_MIN_TEXHEIGHT      = 4;



typedef unsigned long U32;
typedef unsigned char U8;




typedef struct
   {
      /* Uses 64 bits pre block*/
      U32 PackedData[2];
   }AMTC_BLOCK_STRUCT;


static void Decompress(AMTC_BLOCK_STRUCT *pCompressedData,
                 const int Do2bitMode,
                 const int XDim,
                 const int YDim,
                 const int AssumeImageTiles,
                 unsigned char* pResultImage);



void PVRTCDecompress(const void *pCompressedData,
                const int Do2bitMode,
                const int XDim,
                const int YDim,
                unsigned char* pResultImage);
#endif



Add the include in sio.h at line 160

Code:

      #include "sio2_decompresspvr.h"

zzajin

Posts : 81
Join date : 2008-10-14

View user profile

Back to top Go down

Re: Compressed Textures from Apple's texturetool

Post  zzajin on Wed Nov 12, 2008 9:29 pm

sio2_decompresspvr.cc

part 1



Code:

/******************************************************************************
 
 @File        PVRTDecompress.cpp
 
 @Title       
 
 @Copyright    Copyright (C) 2000 - 2008 by Imagination Technologies Limited.
 
 @Platform    ANSI compatible
 
 @Description  PVRTC Texture Decompression.
 
 ******************************************************************************/

#include "sio2.h"



/*****************************************************************************
 * defines and consts
 *****************************************************************************/

#define PT_INDEX (2)   /*The Punch-through index*/

#define BLK_Y_SIZE    (4) /*always 4 for all 2D block types*/

#define BLK_X_MAX   (8)   /*Max X dimension for blocks*/

#define BLK_X_2BPP   (8) /*dimensions for the two formats*/
#define BLK_X_4BPP   (4)

#define _MIN(X,Y) (((X)<(Y))? (X):(Y))
#define _MAX(X,Y) (((X)>(Y))? (X):(Y))
#define WRAP_COORD(Val, Size) ((Val) & ((Size)-1))

#define CLAMP(X, lower, upper) (_MIN(_MAX((X),(lower)), (upper)))

#define POWER_OF_2(X)  util_number_is_power_2(X)

//
// Define an expression to either wrap or clamp large or small vals to the
// legal coordinate range
//
#define LIMIT_COORD(Val, Size, AssumeImageTiles) \
((AssumeImageTiles)? WRAP_COORD((Val), (Size)): CLAMP((Val), 0, (Size)-1))

//#define RGBA(r, g, b, a)  ((GLuint) (((a) << 24) | ((b) << 16) | ((g) << 8) | (r)))

#define _ASSERT(X) assert(X)

//
//
//------------------------------ Decompressing Textures --------------------------------------
//
//

//
//
//



void PVRTCDecompress(const void *pCompressedData,
                const int Do2bitMode,
                const int XDim,
                const int YDim,
                unsigned char* pResultImage)
{
   Decompress((AMTC_BLOCK_STRUCT*)pCompressedData,Do2bitMode,XDim,YDim,1,pResultImage);
}


/******************************************************************************
 * Function Name: util_number_is_power_2
 *
 * Inputs      : input - A number.
 * Outputs      : -
 * Returns      : TRUE if the number is an integer power of two, else FALSE.
 * Globals Used : -
 *
 * Description  : Check that a number is an integer power of two, i.e.
 *                1, 2, 4, 8, ... etc.
 *                Returns FALSE for zero.
 * Pre-condition: -
 *****************************************************************************/
int util_number_is_power_2( unsigned  input )
{
   unsigned minus1;
   
   if( !input ) return 0;
   
   minus1 = input - 1;
   return ( (input | minus1) == (input ^ minus1) ) ? 1 : 0;
}

/***********************************************************/
/*
 // Unpack5554Colour
 //
 // Given a block, extract the colour information and convert to 5554 formats
 */
/***********************************************************/

static void Unpack5554Colour(const AMTC_BLOCK_STRUCT *pBlock,
                      int  ABColours[2][4])
{
   U32 RawBits[2];
   
   int i;
   
   /*
    // Extract A and B
    */
   RawBits[0] = pBlock->PackedData[1] & (0xFFFE); /*15 bits (shifted up by one)*/
   RawBits[1] = pBlock->PackedData[1] >> 16;     /*16 bits*/
   
   /*
    //step through both colours
    */
   for(i = 0; i < 2; i++)
   {
      /*
       // if completely opaque
       */
      if(RawBits[i] & (1<<15))
      {
         /*
          // Extract R and G (both 5 bit)
          */
         ABColours[i][0] = (RawBits[i] >> 10) & 0x1F;
         ABColours[i][1] = (RawBits[i] >>  5) & 0x1F;
         
         /*
          // The precision of Blue depends on  A or B. If A then we need to
          // replicate the top bit to get 5 bits in total
          */
         ABColours[i][2] = RawBits[i] & 0x1F;
         if(i==0)
         {
            ABColours[0][2] |= ABColours[0][2] >> 4;
         }
         
         /*
          // set 4bit alpha fully on...
          */
         ABColours[i][3] = 0xF;
      }
      /*
       // Else if colour has variable translucency
       */
      else
      {
         /*
          // Extract R and G (both 4 bit).
          // (Leave a space on the end for the replication of bits
          */
         ABColours[i][0] = (RawBits[i] >>  (8-1)) & 0x1E;
         ABColours[i][1] = (RawBits[i] >>  (4-1)) & 0x1E;
         
         /*
          // replicate bits to truly expand to 5 bits
          */
         ABColours[i][0] |= ABColours[i][0] >> 4;
         ABColours[i][1] |= ABColours[i][1] >> 4;
         
         /*
          // grab the 3(+padding) or 4 bits of blue and add an extra padding bit
          */
         ABColours[i][2] = (RawBits[i] & 0xF) << 1;
         
         /*
          // expand from 3 to 5 bits if this is from colour A, or 4 to 5 bits if from
          // colour B
          */
         if(i==0)
         {
            ABColours[0][2] |= ABColours[0][2] >> 3;
         }
         else
         {
            ABColours[0][2] |= ABColours[0][2] >> 4;
         }
         
         /*
          // Set the alpha bits to be 3 + a zero on the end
          */
         ABColours[i][3] = (RawBits[i] >> 11) & 0xE;
      }/*end if variable alpha*/
   }/*end for i*/
   
}


/***********************************************************/
/*
 // UnpackModulations
 //
 // Given the block and the texture type and it's relative position in the
 // 2x2 group of blocks, extract the bit patterns for the fully defined pixels.
 */
/***********************************************************/

static void   UnpackModulations(const AMTC_BLOCK_STRUCT *pBlock,
                       const int Do2bitMode,
                       int ModulationVals[8][16],
                       int ModulationModes[8][16],
                       int StartX,
                       int StartY)
{
   int BlockModMode;
   U32 ModulationBits;
   
   int x, y;
   
   BlockModMode= pBlock->PackedData[1] & 1;
   ModulationBits   = pBlock->PackedData[0];
   
   /*
    // if it's in an interpolated mode
    */
   if(Do2bitMode && BlockModMode)
   {
      /*
       // run through all the pixels in the block. Note we can now treat all the
       // "stored" values as if they have 2bits (even when they didn't!)
       */
      for(y = 0; y < BLK_Y_SIZE; y++)
      {
         for(x = 0; x < BLK_X_2BPP; x++)
         {
            ModulationModes[y+StartY][x+StartX] = BlockModMode;
            
            /*
             // if this is a stored value...
             */
            if(((x^y)&1) == 0)
            {
               ModulationVals[y+StartY][x+StartX] = ModulationBits & 3;
               ModulationBits >>= 2;
            }
         }
      }/*end for y*/
   }
   /*
    // else if direct encoded 2bit mode - i.e. 1 mode bit per pixel
    */
   else if(Do2bitMode)
   {
      for(y = 0; y < BLK_Y_SIZE; y++)
      {
         for(x = 0; x < BLK_X_2BPP; x++)
         {
            ModulationModes[y+StartY][x+StartX] = BlockModMode;
            
            /*
             // double the bits so 0=> 00, and 1=>11
             */
            if(ModulationBits & 1)
            {
               ModulationVals[y+StartY][x+StartX] = 0x3;
            }
            else
            {
               ModulationVals[y+StartY][x+StartX] = 0x0;
            }
            ModulationBits >>= 1;
         }
      }/*end for y*/
   }
   /*
    // else its the 4bpp mode so each value has 2 bits
    */
   else
   {
      for(y = 0; y < BLK_Y_SIZE; y++)
      {
         for(x = 0; x < BLK_X_4BPP; x++)
         {
            ModulationModes[y+StartY][x+StartX] = BlockModMode;
            
            ModulationVals[y+StartY][x+StartX] = ModulationBits & 3;
            ModulationBits >>= 2;
         }
      }/*end for y*/
   }
   
   /*
    // make sure nothing is left over
    */
   _ASSERT(ModulationBits==0);
}


/***********************************************************/
/*
 // Interpolate Colours
 //
 //
 // This performs a HW bit accurate interpolation of either the
 // A or B colours for a particular pixel
 //
 // NOTE: It is assumed that the source colours are in ARGB 5554 format -
 //       This means that some "preparation" of the values will be necessary.
 */
/***********************************************************/

static void InterpolateColours(const int ColourP[4],
                       const int ColourQ[4],
                       const int ColourR[4],
                       const int ColourS[4],
                       const int Do2bitMode,
                       const int x,
                       const int y,
                       int Result[4])
{
   int u, v, uscale;
   int k;
   
   int tmp1, tmp2;
   
   int P[4], Q[4], R[4], S[4];
   
   /*
    // Copy the colours
    */
   for(k = 0; k < 4; k++)
   {
      P[k] = ColourP[k];
      Q[k] = ColourQ[k];
      R[k] = ColourR[k];
      S[k] = ColourS[k];
   }
   
   /*
    // put the x and y values into the right range
    */
   v = (y & 0x3) | ((~y & 0x2) << 1);
   if(Do2bitMode)
   {
      u = (x & 0x7) | ((~x & 0x4) << 1);
      
   }
   else
   {
      u = (x & 0x3) | ((~x & 0x2) << 1);
   }
   
   
   
   /*
    // get the u and v scale amounts
    */
   v  = v - BLK_Y_SIZE/2;
   
   if(Do2bitMode)
   {
      u = u - BLK_X_2BPP/2;
      uscale = 8;
   }
   else
   {
      u = u - BLK_X_4BPP/2;
      uscale = 4;
   }
   
   for(k = 0; k < 4; k++)
   {
      tmp1 = P[k] * uscale + u * (Q[k] - P[k]);
      tmp2 = R[k] * uscale + u * (S[k] - R[k]);
      
      tmp1 = tmp1 * 4 + v * (tmp2 - tmp1);
      
      Result[k] = tmp1;
   }
   
   /*
    // Lop off the appropriate number of bits to get us to 8 bit precision
    */
   if(Do2bitMode)
   {
      /*
       // do RGB
       */
      for(k = 0; k < 3; k++)
      {
         Result[k] >>= 2;
      }
      
      Result[3] >>= 1;
   }
   else
   {
      /*
       // do RGB  (A is ok)
       */
      for(k = 0; k < 3; k++)
      {
         Result[k] >>= 1;
      }
   }
   
   /*
    // sanity check
    */
   for(k = 0; k < 4; k++)
   {
      _ASSERT(Result[k] < 256);
   }
   
   
   /*
    // Convert from 5554 to 8888
    //
    // do RGB 5.3 => 8
    */
   for(k = 0; k < 3; k++)
   {
      Result[k] += Result[k] >> 5;
   }
   Result[3] += Result[3] >> 4;
   
   /*
    // 2nd sanity check
    */
   for(k = 0; k < 4; k++)
   {
      _ASSERT(Result[k] < 256);
   }
   
}

/***********************************************************/
/*
 // GetModulationValue
 //
 // Get the modulation value as a numerator of a fraction of 8ths
 */
/***********************************************************/
static void GetModulationValue(int x,
                       int y,
                       const int Do2bitMode,
                       const int ModulationVals[8][16],
                       const int ModulationModes[8][16],
                       int *Mod,
                       int *DoPT)
{
   static const int RepVals0[4] = {0, 3, 5, 8};
   static const int RepVals1[4] = {0, 4, 4, 8};
   
   int ModVal;
   
   /*
    // Map X and Y into the local 2x2 block
    */
   y = (y & 0x3) | ((~y & 0x2) << 1);
   if(Do2bitMode)
   {
      x = (x & 0x7) | ((~x & 0x4) << 1);


zzajin

Posts : 81
Join date : 2008-10-14

View user profile

Back to top Go down

Re: Compressed Textures from Apple's texturetool

Post  zzajin on Wed Nov 12, 2008 9:30 pm

part 2


Code:


      
   }
   else
   {
      x = (x & 0x3) | ((~x & 0x2) << 1);
   }
   
   /*
    // assume no PT for now
    */
   *DoPT = 0;
   
   /*
    // extract the modulation value. If a simple encoding
    */
   if(ModulationModes[y][x]==0)
   {
      ModVal = RepVals0[ModulationVals[y][x]];
   }
   else if(Do2bitMode)
   {
      /*
       // if this is a stored value
       */
      if(((x^y)&1)==0)
      {
         ModVal = RepVals0[ModulationVals[y][x]];
      }
      /*
       // else average from the neighbours
       //
       // if H&V interpolation...
       */
      else if(ModulationModes[y][x] == 1)
      {
         ModVal = (RepVals0[ModulationVals[y-1][x]] +
                 RepVals0[ModulationVals[y+1][x]] +
                 RepVals0[ModulationVals[y][x-1]] +
                 RepVals0[ModulationVals[y][x+1]] + 2) / 4;
      }
      /*
       // else if H-Only
       */
      else if(ModulationModes[y][x] == 2)
      {
         ModVal = (RepVals0[ModulationVals[y][x-1]] +
                 RepVals0[ModulationVals[y][x+1]] + 1) / 2;
      }
      /*
       // else it's V-Only
       */
      else
      {
         ModVal = (RepVals0[ModulationVals[y-1][x]] +
                 RepVals0[ModulationVals[y+1][x]] + 1) / 2;
         
      }/*end if/then/else*/
   }
   /*
    // else it's 4BPP and PT encoding
    */
   else
   {
      ModVal = RepVals1[ModulationVals[y][x]];
      
      *DoPT = ModulationVals[y][x] == PT_INDEX;
   }
   
   *Mod =ModVal;
}


/*****************************************************************************/
/*
 // TwiddleUV
 //
 // Given the Block (or pixel) coordinates and the dimension of the texture
 // in blocks (or pixels) this returns the twiddled offset of the block
 // (or pixel) from the start of the map.
 //
 // NOTE the dimensions of the texture must be a power of 2
 */
/*****************************************************************************/

static int DisableTwiddlingRoutine = 0;

static U32 TwiddleUV(U32 YSize, U32 XSize, U32 YPos, U32 XPos)
{
   U32 Twiddled;
   
   U32 MinDimension;
   U32 MaxValue;
   
   U32 SrcBitPos;
   U32 DstBitPos;
   
   int ShiftCount;
   
   _ASSERT(YPos < YSize);
   _ASSERT(XPos < XSize);
   
   _ASSERT(POWER_OF_2(YSize));
   _ASSERT(POWER_OF_2(XSize));
   
   
   if(YSize < XSize)
   {
      MinDimension = YSize;
      MaxValue    = XPos;
   }
   else
   {
      MinDimension = XSize;
      MaxValue    = YPos;
   }
   
   /*
    // Nasty hack to disable twiddling
    */
   if(DisableTwiddlingRoutine)
   {
      return (YPos* XSize + XPos);
   }
   
   /*
    // Step through all the bits in the "minimum" dimension
    */
   SrcBitPos = 1;
   DstBitPos = 1;
   Twiddled  = 0;
   ShiftCount = 0;
   
   while(SrcBitPos < MinDimension)
   {
      if(YPos & SrcBitPos)
      {
         Twiddled |= DstBitPos;
      }
      
      if(XPos & SrcBitPos)
      {
         Twiddled |= (DstBitPos << 1);
      }
      
      
      SrcBitPos <<= 1;
      DstBitPos <<= 2;
      ShiftCount += 1;
      
   }/*end while*/
   
   /*
    // prepend any unused bits
    */
   MaxValue >>= ShiftCount;
   
   Twiddled |=  (MaxValue << (2*ShiftCount));
   
   return Twiddled;
}

/***********************************************************/
/*
 // Decompress
 //
 // Takes the compressed input data and outputs the equivalent decompressed
 // image.
 */
/***********************************************************/

static void Decompress(AMTC_BLOCK_STRUCT *pCompressedData,
                 const int Do2bitMode,
                 const int XDim,
                 const int YDim,
                 const int AssumeImageTiles,
                 unsigned char* pResultImage)
{
   int x, y;
   int i, j;
   
   int BlkX, BlkY;
   int BlkXp1, BlkYp1;
   int XBlockSize;
   int BlkXDim, BlkYDim;
   
   int StartX, StartY;
   
   int ModulationVals[8][16];
   int ModulationModes[8][16];
   
   int Mod, DoPT;
   
   unsigned int uPosition;
   
   /*
    // local neighbourhood of blocks
    */
   AMTC_BLOCK_STRUCT *pBlocks[2][2];
   
   AMTC_BLOCK_STRUCT *pPrevious[2][2] = {{NULL, NULL}, {NULL, NULL}};
   
   /*
    // Low precision colours extracted from the blocks
    */
   struct
   {
      int Reps[2][4];
   }Colours5554[2][2];
   
   /*
    // Interpolated A and B colours for the pixel
    */
   int ASig[4], BSig[4];
   
   int Result[4];
   
   if(Do2bitMode)
   {
      XBlockSize = BLK_X_2BPP;
   }
   else
   {
      XBlockSize = BLK_X_4BPP;
   }
   
   
   /*
    // For MBX don't allow the sizes to get too small
    */
   BlkXDim = _MAX(2, XDim / XBlockSize);
   BlkYDim = _MAX(2, YDim / BLK_Y_SIZE);
   
   /*
    // Step through the pixels of the image decompressing each one in turn
    //
    // Note that this is a hideously inefficient way to do this!
    */
   for(y = 0; y < YDim; y++)
   {
      for(x = 0; x < XDim; x++)
      {
         /*
          // map this pixel to the top left neighbourhood of blocks
          */
         BlkX = (x - XBlockSize/2);
         BlkY = (y - BLK_Y_SIZE/2);
         
         BlkX = LIMIT_COORD(BlkX, XDim, AssumeImageTiles);
         BlkY = LIMIT_COORD(BlkY, YDim, AssumeImageTiles);
         
         
         BlkX /= XBlockSize;
         BlkY /= BLK_Y_SIZE;
         
         //BlkX = LIMIT_COORD(BlkX, BlkXDim, AssumeImageTiles);
         //BlkY = LIMIT_COORD(BlkY, BlkYDim, AssumeImageTiles);
         
         
         /*
          // compute the positions of the other 3 blocks
          */
         BlkXp1 = LIMIT_COORD(BlkX+1, BlkXDim, AssumeImageTiles);
         BlkYp1 = LIMIT_COORD(BlkY+1, BlkYDim, AssumeImageTiles);
         
         /*
          // Map to block memory locations
          */
         pBlocks[0][0] = pCompressedData +TwiddleUV(BlkYDim, BlkXDim, BlkY, BlkX);
         pBlocks[0][1] = pCompressedData +TwiddleUV(BlkYDim, BlkXDim, BlkY, BlkXp1);
         pBlocks[1][0] = pCompressedData +TwiddleUV(BlkYDim, BlkXDim, BlkYp1, BlkX);
         pBlocks[1][1] = pCompressedData +TwiddleUV(BlkYDim, BlkXDim, BlkYp1, BlkXp1);
         
         
         /*
          // extract the colours and the modulation information IF the previous values
          // have changed.
          */
         if(memcmp(pPrevious, pBlocks, 4*sizeof(void*)) != 0)
         {
            StartY = 0;
            for(i = 0; i < 2; i++)
            {
               StartX = 0;
               for(j = 0; j < 2; j++)
               {
                  Unpack5554Colour(pBlocks[i][j], Colours5554[i][j].Reps);
                  
                  UnpackModulations(pBlocks[i][j],
                                Do2bitMode,
                                ModulationVals,
                                ModulationModes,
                                StartX, StartY);
                  
                  StartX += XBlockSize;
               }/*end for j*/
               
               StartY += BLK_Y_SIZE;
            }/*end for i*/
            
            /*
             // make a copy of the new pointers
             */
            memcpy(pPrevious, pBlocks, 4*sizeof(void*));
         }/*end if the blocks have changed*/
         
         
         /*
          // decompress the pixel.  First compute the interpolated A and B signals
          */
         InterpolateColours(Colours5554[0][0].Reps[0],
                       Colours5554[0][1].Reps[0],
                       Colours5554[1][0].Reps[0],
                       Colours5554[1][1].Reps[0],
                       Do2bitMode, x, y,
                       ASig);
         
         InterpolateColours(Colours5554[0][0].Reps[1],
                       Colours5554[0][1].Reps[1],
                       Colours5554[1][0].Reps[1],
                       Colours5554[1][1].Reps[1],
                       Do2bitMode, x, y,
                       BSig);
         
         GetModulationValue(x,y, Do2bitMode, (const int (*)[16])ModulationVals, (const int (*)[16])ModulationModes,
                       &Mod, &DoPT);
         
         /*
          // compute the modulated colour
          */
         for(i = 0; i < 4; i++)
         {
            Result[i] = ASig[i] * 8 + Mod * (BSig[i] - ASig[i]);
            Result[i] >>= 3;
         }
         if(DoPT)
         {
            Result[3] = 0;
         }
         
         /*
          // Store the result in the output image
          */
         uPosition = (x+y*XDim)<<2;
         pResultImage[uPosition+0] = (U8)Result[0];
         pResultImage[uPosition+1] = (U8)Result[1];
         pResultImage[uPosition+2] = (U8)Result[2];
         pResultImage[uPosition+3] = (U8)Result[3];
         
      }/*end for x*/
   }/*end for y*/
   
}

//---------------------------   ETC Compression ---------------------------------

#define _CLAMP_(X,Xmin,Xmax) (  (X)<(Xmax) ?  (  (X)<(Xmin)?(Xmin):(X)  )  : (Xmax)    )


unsigned int ETC_FLIP =  0x01000000;
unsigned int ETC_DIFF = 0x02000000;
const int mod[8][4]={{2, 8,-2,-8},
{5, 17, -5, -17},
{9, 29, -9, -29},
{13, 42, -13, -42},
{18, 60, -18, -60},
{24, 80, -24, -80},
{33, 106, -33, -106},
{47, 183, -47, -183}};


// lsb: hgfedcba ponmlkji msb: hgfedcba ponmlkji due to endianness
unsigned long modifyPixel(int red, int green, int blue, int x, int y, unsigned long modBlock, int modTable)
{
   int index = x*4+y, pixelMod;
   unsigned long mostSig = modBlock<<1;
   if (index<8)   //hgfedcba
      pixelMod = mod[modTable][((modBlock>>(index+24))&0x1)+((mostSig>>(index+8))&0x2)];
   else   // ponmlkj
      pixelMod = mod[modTable][((modBlock>>(index+8))&0x1)+((mostSig>>(index-8))&0x2)];
   
   red = _CLAMP_(red+pixelMod,0,255);
   green = _CLAMP_(green+pixelMod,0,255);
   blue = _CLAMP_(blue+pixelMod,0,255);
   
   return ((red<<16) + (green<<8) + blue)|0xff000000;
}


//
// returns Number of bytes of ETC data decompressed
//
// Description    : Convert ETC textures to RGBA8888.
//               - pSrcData points to the source DXT data
//               - x and y are the dimensions of the source data, in pixels.
//               - pDestData is a pointer that will contain the output data.
//               - nMode indicates the format of the data (DXT 1 to 5)
//               
int ETCTextureDecompress(const void * const pSrcData, const int &x, const int &y, const void *pDestData,const int &nMode)
{
   unsigned long blockTop, blockBot, *input = (unsigned long*)pSrcData, *output;
   //unsigned long alphaTop, alphaBot, alphaValue[8];
   unsigned char red1, green1, blue1, red2, green2, blue2;
   bool bFlip, bDiff;
   int modtable1,modtable2;
   
   for(int i=0;i<y;i+=4)
   {
      for(int m=0;m<x;m+=4)
      {
         blockTop = *(input++);
         blockBot = *(input++);
         
         output = (unsigned long*)pDestData + i*x +m;
         // check flipbit
         bFlip = (blockTop & ETC_FLIP) != 0;
         bDiff = (blockTop & ETC_DIFF) != 0;
         
         if(bDiff)
         {   // differential mode 5 colour bits + 3 difference bits
            // get base colour for subblock 1
            blue1 = (unsigned char)((blockTop&0xf80000)>>16);
            green1 = (unsigned char)((blockTop&0xf800)>>8);
            red1 = (unsigned char)(blockTop&0xf8);
            
            // get differential colour for subblock 2
            signed char blues = (signed char)(blue1>>3) + ((signed char) ((blockTop & 0x70000) >> 11)>>5);
            signed char greens = (signed char)(green1>>3) + ((signed char)((blockTop & 0x700) >>3)>>5);
            signed char reds = (signed char)(red1>>3) + ((signed char)((blockTop & 0x7)<<5)>>5);
            
            blue2 = (unsigned char)blues;
            green2 = (unsigned char)greens;
            red2 = (unsigned char)reds;
            
            red1 = red1 +(red1>>5);   // copy bits to lower sig
            green1 = green1 + (green1>>5);   // copy bits to lower sig
            blue1 = blue1 + (blue1>>5);   // copy bits to lower sig
            
            red2 = (red2<<3) +(red2>>2);   // copy bits to lower sig
            green2 = (green2<<3) + (green2>>2);   // copy bits to lower sig
            blue2 = (blue2<<3) + (blue2>>2);   // copy bits to lower sig
         }
         else
         {   // individual mode 4 + 4 colour bits
            // get base colour for subblock 1
            blue1 = (unsigned char)((blockTop&0xf00000)>>16);
            blue1 = blue1 +(blue1>>4);   // copy bits to lower sig
            green1 = (unsigned char)((blockTop&0xf000)>>8);
            green1 = green1 + (green1>>4);   // copy bits to lower sig
            red1 = (unsigned char)(blockTop&0xf0);
            red1 = red1 + (red1>>4);   // copy bits to lower sig
            
            // get base colour for subblock 2
            blue2 = (unsigned char)((blockTop&0xf0000)>>12);
            blue2 = blue2 +(blue2>>4);   // copy bits to lower sig
            green2 = (unsigned char)((blockTop&0xf00)>>4);
            green2 = green2 + (green2>>4);   // copy bits to lower sig
            red2 = (unsigned char)((blockTop&0xf)<<4);
            red2 = red2 + (red2>>4);   // copy bits to lower sig
         }
         // get the modtables for each subblock
         modtable1 = (blockTop>>29)&0x7;
         modtable2 = (blockTop>>26)&0x7;
         
         if(!bFlip)
         {   // 2 2x4 blocks side by side
            
            for(int j=0;j<4;j++)   // vertical
            {
               for(int k=0;k<2;k++)   // horizontal
               {
                  *(output+j*x+k) = modifyPixel(red1,green1,blue1,k,j,blockBot,modtable1);
                  *(output+j*x+k+2) = modifyPixel(red2,green2,blue2,k+2,j,blockBot,modtable2);
               }
            }
            
         }
         else
         {   // 2 4x2 blocks on top of each other
            for(int j=0;j<2;j++)
            {
               for(int k=0;k<4;k++)
               {
                  *(output+j*x+k) = modifyPixel(red1,green1,blue1,k,j,blockBot,modtable1);
                  *(output+(j+2)*x+k) = modifyPixel(red2,green2,blue2,k,j+2,blockBot,modtable2);
               }
            }
         }
      }
   }
   return x*y/2;
}

int ETCDecompress(const void * const pSrcData,
              const unsigned int &x,
              const unsigned int &y,
              void *pDestData,
              const int &nMode)
{
   int i32read;
   if(x<ETC_MIN_TEXWIDTH || y<ETC_MIN_TEXHEIGHT)
   {   // decompress into a buffer big enought to take the minimum size
      char* pTempBuffer =   (char*)new char[_MAX(x,ETC_MIN_TEXWIDTH)*_MAX(y,ETC_MIN_TEXHEIGHT)*4];
      i32read = ETCTextureDecompress(pSrcData,_MAX(x,ETC_MIN_TEXWIDTH),_MAX(y,ETC_MIN_TEXHEIGHT),pTempBuffer,nMode);
      for(unsigned int i=0;i<y;i++)
      {   // copy from larger temp buffer to output data
         memcpy((char*)(pDestData)+i*x*4,pTempBuffer+_MAX(x,ETC_MIN_TEXWIDTH)*4*i,x*4);
      }
      if(pTempBuffer)
         delete(pTempBuffer);
   }
   else   // decompress larger MIP levels straight into the output data
      i32read = ETCTextureDecompress(pSrcData,x,y,pDestData,nMode);
   
   // swap r and b channels
   unsigned char* pSwap=(unsigned char*)pDestData, swap;
   for(unsigned int i=0;i<y;i++)
      for(unsigned int j=0;j<x;j++)
      {
         swap = pSwap[0];
         pSwap[0] = pSwap[2];
         pSwap[2] = swap;
         pSwap+=4;
      }
   return i32read;
}




#undef PT_INDEX
#undef BLK_Y_SIZE
#undef BLK_X_MAX
#undef BLK_X_2BPP
#undef BLK_X_4BPP
#undef _MIN
#undef _MAX
#undef WRAP_COORD
#undef CLAMP
#undef POWER_OF_2
#undef LIMIT_COORD
//#undef RGBA
#undef _ASSERT




zzajin

Posts : 81
Join date : 2008-10-14

View user profile

Back to top Go down

Support for att files

Post  zzajin on Wed Nov 12, 2008 9:52 pm

image.h


add to SIO2image struct
Code:

   bool            compressed;
   bool         has_alpha;




add to function def
Code:




void sio2ImageLoadATT( SIO2image  *_SIO2image,
                 SIO2stream *_SIO2stream);


image.cc

in sio2ImageLoad add
Code:


  //load compressed raw data from Apple's texturetool
   else if( strstr( _SIO2stream->fname, ".att" ) )
   {
      sio2ImageLoadATT( _SIO2image,
                   _SIO2stream );
   }



in sio2ImageGenId after


Code:


      if( sio2->afilter != SIO2_IMAGE_ISOTROPIC )
      {
         glTexParameterf( GL_TEXTURE_2D,
                      GL_TEXTURE_MAX_ANISOTROPY_EXT,
                      sio2->maniso );      
      }   



add


Code:

      if (_SIO2image->compressed)
      {      
         glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
         
         
         GLenum format;
         GLsizei size = _SIO2image->width * _SIO2image->width * _SIO2image->bits / 8;
         if(_SIO2image->has_alpha)
         {
            format = (_SIO2image->bits == 4) ? GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG : GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
         }
         else
         {
            format = (_SIO2image->bits == 4) ? GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG : GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
         }
         if(size < 32)
         {
            size = 32;
         }
         int level = 0;
         glCompressedTexImage2D(GL_TEXTURE_2D,
                          level,
                          format,
                          _SIO2image->width,
                          _SIO2image->width,
                          0,
                          size,
                          &_SIO2image->tex[ 0 ]);
                  
         #ifdef SIO2_DEBUG_GL         
            sio2ErrorGL( __FILE__, __FUNCTION__, __LINE__ );
         #endif
         return;      
      }


add the following function


Code:



void sio2ImageLoadATT( SIO2image  *_SIO2image,
                 SIO2stream *_SIO2stream )
{
   unsigned int s = sio2StringLen( _SIO2stream->fname );
   int power = atoi(&_SIO2stream->fname[s-5]);
   char alpha = _SIO2stream->fname[s-6];
   //char level = _SIO2stream->fname[s-7];
   //char type = _SIO2stream->fname[s-8];
   int bpp = atoi(&_SIO2stream->fname[s-9]);
   
   _SIO2image->width  = (int) pow(2,power+2);
   _SIO2image->height = (int) pow(2,power+2);
   _SIO2image->bits  = bpp;
   _SIO2image->compressed = 1;
   _SIO2image->has_alpha = atoi(&alpha);
   sio2DisableState( &_SIO2image->flags, SIO2_IMAGE_MIPMAP );
   
   _SIO2image->tex = ( unsigned char * ) malloc( _SIO2stream->size );   
   sio2StreamRead( _SIO2stream, &_SIO2image->tex[ 0 ], _SIO2stream->size );
   
   
#if (TARGET_IPHONE_SIMULATOR)
      // Convert PVRTC to 32-bit
      unsigned char *u8TempTexture = (unsigned char*) new unsigned char[_SIO2image->width*_SIO2image->width*4];
      unsigned int is2bit = (_SIO2image->bits == 2) ? 1 : 0;
      
      PVRTCDecompress((void*) &_SIO2image->tex[ 0 ], is2bit, _SIO2image->width, _SIO2image->width, u8TempTexture);
   
      free( _SIO2image->tex );
      _SIO2image->tex = ( unsigned char * ) malloc( _SIO2image->width*_SIO2image->width*4 );
      memcpy((void*) &_SIO2image->tex[ 0 ], u8TempTexture, _SIO2image->width*_SIO2image->width*4);
      delete(u8TempTexture);
   
      _SIO2image->bits = 4;
      _SIO2image->compressed = 0;   
      sio2ImageRGBAtoBGRA( _SIO2image );
#endif
   
}


zzajin

Posts : 81
Join date : 2008-10-14

View user profile

Back to top Go down

texturetool for blender

Post  zzajin on Wed Nov 12, 2008 9:55 pm

Here is the script for blender to create compressed textures.


Code:

#!BPY


# Copyright (C) 2008: ZzaJin - zzajin@gmail.com


"""
Name: 'PVRTC TextureTool'
Blender: 248
Group: 'Image'
Tooltip: 'PVRTC TextureTool'
"""


import os
import sys
import struct
import math
import Blender
import platform
import shutil
import bpy

from Blender                 import Texture
from Blender                 import Window
from Blender                import Object
from Blender                import Mesh
from Blender                 import Mathutils

from Blender.Draw          import *
from Blender.BGL         import *
from Blender.Window     import *
from Blender.Mathutils import *


#Location of the texture tool provided by Apple
TOOL = "/Developer/Platforms/iPhoneOS.platform/usr/bin/texturetool "


INTERNAL_NAME    = "PVRTC TextureTool"

VERSION_MAJOR    = 1
VERSION_MINOR    = 0
VERSION_PATCH    = 0

MAX_CHAR             = 32


EVENT_EXIT              = 0
EVENT_PATH_CHANGE        = 1
EVENT_RUN             = 2
EVENT_DIR_SELECT       = 3
EVENT_LEVEL             = 4
EVENT_DONE             = 5

EVENT_TOGGLE_2BPP_LINEAR = 12
EVENT_TOGGLE_4BPP_LINEAR = 13
EVENT_TOGGLE_2BPP_PERCEPTION = 14
EVENT_TOGGLE_4BPP_PERCEPTION = 15

EVENT_TOGGLE_LOAD_PNG = 16
EVENT_TOGGLE_LOAD_ATT = 17

#conversion toggles
LIN_2BPP   = 1      #Linear channel weighting with 2 bits per pixel
LIN_4BPP   = 1      #Linear channel weighting with 4 bits per pixel
PER_2BPP    = 1      #Perception channel weighting with 2 bits per pixel   
PER_4BPP    = 1      #Perception channel weighting with 4 bits per pixel
LEVEL      = 0    #MipMap level
LOAD_PNG    = 1      
LOAD_ATT    = 0

lin_2bpp_text = ""
lin_4bpp_text = ""
per_2bpp_text = ""
per_4bpp_text = ""
IDLE              = 0
RUNNING            = 1
DONE              = 3
SCRIPT_RUN_STATE    = IDLE   
LOG = ""


error_str = ""


   
#=========================================
# DEFAULT OUTPUT PATH::REMOVE WHEN RELEASE
#=========================================
directory = Create("/Users/zzajin/Desktop/")


#========================================
# REGISTER GUI
#========================================
def register_gui():
#========================================
   Register( draw_gui, None, event_gui )


#========================================
# DRAW RECTANGLE
#========================================
def draw_rectangle( x, y, w, h, r, g, b, a ):
#========================================

   glEnable( GL_BLEND )
   glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA )
   
   glColor4f( r,g,b,a )
   
   glBegin( GL_POLYGON )
   
   glVertex2i( x    , y    )
   glVertex2i( x    , y + h )
   glVertex2i( x + w, y + h )
   glVertex2i( x + w, y    )
   
   glEnd()   
   
   glDisable( GL_BLEND )

#=========================================
# RENDER OUTLINE OF GUI
#=========================================
def draw_outline():
   glClearColor(0.74, 0.74, 0.74, 0.0)
   glClear(GL_COLOR_BUFFER_BIT)

   draw_rectangle( 5, 213, 400,  30, 0.6, 0.6, 0.6, 1.0 )
   draw_rectangle( 5,  6, 400,  207, 0.8, 0.8, 0.8, 1.0 )


   #draw version
   glColor3f( 1.0, 1.0, 1.0 )
   glRasterPos2i( 250, 225 )
   
   tmp = "%s v%d.%d.%d" % (    INTERNAL_NAME,
                        VERSION_MAJOR,
                        VERSION_MINOR,
                        VERSION_PATCH )
   Text( tmp )
   

   glPolygonMode( GL_FRONT_AND_BACK, GL_LINE )
   draw_rectangle( 5,  7, 399, 236, 0.5, 0.5, 0.5, 1.0 )
   draw_rectangle( 5,  7, 399,  207, 0.5, 0.5, 0.5, 1.0 )
   glPolygonMode( GL_FRONT_AND_BACK, GL_FILL )
   
#=========================================
# RENDER THE GUI
#=========================================
def draw_gui():
#=========================================
   global directory
   global current_image
   global status

   draw_outline()
   
   #widgets
   glColor3f(0.0, 0.0, 0.0)
   glRasterPos2i(15, 192)   
   Text("Output Directory:")

   directory = String( "",
                    EVENT_PATH_CHANGE,
                    15, 165, 360, 20,
                    directory.val, 255,
                    "")

   Button( "..."  , EVENT_DIR_SELECT    , 375, 165,  20, 20 )
   
   
   EVENT_TOGGLE_2BPP_LINEAR = 12
   EVENT_TOGGLE_4BPP_LINEAR = 13
   EVENT_TOGGLE_2BPP_PERCEPTION = 14
   EVENT_TOGGLE_4BPP_PERCEPTION = 15


    #Defaults
   BPP2_LINEAR         = 1
   BPP4_LINEAR         = 1
   BPP2_PERCEPTION    = 1   
   BPP4_PERCEPTION    = 1
   

   
   Toggle( "Linear          2 bpp", EVENT_TOGGLE_2BPP_LINEAR, 15,  135,  180, 20, LIN_2BPP, "Linear channel weighting with 2 bits per pixel." )
   Toggle( "Linear          4 bpp", EVENT_TOGGLE_4BPP_LINEAR, 200,  135,  180, 20, LIN_4BPP, "Linear channel weighting with 4 bits per pixel." )
   Toggle( "Perception    2 bpp"   , EVENT_TOGGLE_2BPP_PERCEPTION, 15,  90,  180, 20, PER_2BPP, "Perception channel weighting with 2 bits per pixel." )
   Toggle( "Perception    4 bpp"   , EVENT_TOGGLE_4BPP_PERCEPTION, 200,  90,  180, 20, PER_4BPP, "Perception channel weighting with 4 bits per pixel." )

   
   
   glRasterPos2i(15, 52)   
   Text("Post Load:")
   Toggle( "PNG", EVENT_TOGGLE_LOAD_PNG, 80 ,45,  30, 20, LOAD_PNG, "Load .pvr.png image after conversion." )   
   Toggle( "ATT", EVENT_TOGGLE_LOAD_ATT, 110 ,45,  30, 20, LOAD_ATT, "Load .att image after conversion." )      
   Number("Level",EVENT_LEVEL, 170, 45, 80, 20, LEVEL, 0, 9, "MipMap Level", level_changed)

   glColor3f(0.0, 0.0, 0.8)
   
   #status   
   if (SCRIPT_RUN_STATE == IDLE):
      set_current_image()
         
      Button( "Run"      , EVENT_RUN          , 275, 45, 50, 20 )
      Button( "Exit"      , EVENT_EXIT          , 345, 45, 50, 20 )
   
   glRasterPos2i(15, 20)       
   Text(status)
   
   #per button status
   glRasterPos2i(20, 120)       
   Text(lin_2bpp_text)
   glRasterPos2i(205, 120)       
   Text(lin_4bpp_text)   
   glRasterPos2i(20, 75)       
   Text(per_2bpp_text)
   glRasterPos2i(205, 75)       
   Text(per_4bpp_text)



#====================================
# GUI EVENTS CALLBACKS
#====================================
def event_gui( event ):
#====================================   
   global UPDATE
   global LIN_2BPP
   global LIN_4BPP
   global PER_2BPP
   global PER_4BPP
   global SCRIPT_RUN_STATE
   
   global lin_2bpp_text
   global lin_4bpp_text
   global per_2bpp_text
   global per_4bpp_text

   if( event == EVENT_EXIT                 ): Exit()
   if( event == EVENT_DIR_SELECT       ): Blender.Window.FileSelector( dir_selected, "Select", "" )
   if( event == EVENT_RUN              ): run()
   if( event == EVENT_TOGGLE_2BPP_LINEAR  ): LIN_2BPP  = not LIN_2BPP
   if( event == EVENT_TOGGLE_4BPP_LINEAR  ): LIN_4BPP  = not LIN_4BPP
   if( event == EVENT_TOGGLE_2BPP_PERCEPTION ): PER_2BPP = not PER_2BPP   
   if( event == EVENT_TOGGLE_4BPP_PERCEPTION ): PER_4BPP = not PER_4BPP   
   
   if( event == EVENT_DONE   ):
      SCRIPT_RUN_STATE = IDLE   
      lin_2bpp_text = ""
      lin_4bpp_text = ""
      per_2bpp_text = ""
      per_4bpp_text = ""
      Draw();


#====================================
# DIRECTORY HAVE CHANGED
#====================================
def dir_selected( _dir ):
#====================================
   global directory

   directory.val = _dir


#====================================
# LEVEL CHANGED
#====================================
def level_changed( _evt, _val ):
#====================================
   global LEVEL

   LEVEL = _val

#====================================
# CREATE ARCHITECTURE DIRECTORY
#====================================
def create_directory( d, f = 0 ):

   global error_str
   global UPDATE
   
   try:
      os.mkdir( d )
      
   except:
      dummy = 0   



#====================================
# BASIC STATUS MESSAGE
#====================================
def set_current_image():
   
   global current_image
   global status
   
   current_image = Blender.Image.GetCurrent()
   if(not current_image or current_image.source != Blender.Image.Sources["STILL"] ):
      status = "No image selected"
   else:
      (width, height) = current_image.getSize()      
      status = "Selected image: %s  ( %d x %d )" % (os.path.basename( current_image.filename ), width, height)
      

   
#====================================
# CHECK IMAGE
#====================================
def check_image( img ):
   
   global error_str

   #check exsitence
   if(not img or img.source != Blender.Image.Sources["STILL"] ):
      error_str = "ERROR: No image selected"
      return 0
            
   # Check if the file exists               
   if( not os.path.exists( img.filename ) ):
      error_str = "ERROR: Unable to find file: %s. |" % img.filename
      return 0
      
   #image must be square and power of 2 between 1024x1024 and 4x4
   (width, height) = img.getSize()
   if( width != height ):
      error_str = "ERROR: Image must be square"
      return 0
   
   if( int(math.log(width,2)) != math.log(width,2)):
      error_str = "ERROR: Image must be power of 2"
      return 0
      
   if( width > 1024 ):
      error_str = "ERROR: Image must be 1024x1024 or smaller"
      return 0
      
   if( width < 4 ):
      error_str = "ERROR: Image must be 4x4 or larger"
      return 0      
   
   return 1

#====================================
# convert image to PVRTC
#====================================
def run():

   global error_str
   global TOOL
   global LIN_2BPP
   global LIN_4BPP
   global PER_2BPP
   global PER_4BPP
   global LEVEL

   global lin_2bpp_text
   global lin_4bpp_text
   global per_2bpp_text
   global per_4bpp_text
   global status
   global directory
   
   global SCRIPT_RUN_STATE

   error_str = ""
   
   current_image = Blender.Image.GetCurrent()
   
   if ( check_image(current_image) ):
      #====================================
      # Start the process.
      #====================================
      SCRIPT_RUN_STATE = RUNNING
      start_time = Blender.sys.time()
      
      print
      print
      print "%s v%d.%d.%d\n%s\n" % ( INTERNAL_NAME,VERSION_MAJOR,VERSION_MINOR,VERSION_PATCH,"Copyright (C) 2008" )
      print


      #====================================
      # VALIDATE AND CREATE SCENE DIRECTORY
      #====================================
      if( directory.val[ len(directory.val) - 1 ] != "/" ):
         directory.val = directory.val + "/"

      directory.val.replace('\\','/')
      
   
      source = current_image.filename
      name = directory.val + os.path.basename( source.split(".")[0] )
      alpha = 0
      (width, height) = current_image.getSize()
      size = math.log(width,2) - 2
      png = ""
      pvr = ""
   
      if (LIN_2BPP):
         png = "%s_2l%d%d%d.pvr.png" % (name, LEVEL, alpha, size)   
         pvr = "%s_2l%d%d%d.att" % (name, LEVEL, alpha, size)
         status = "%s & %s" % (os.path.basename(pvr), os.path.basename(png))

         lin_2bpp_text = "Creating..."              
         Draw()
         command = "%s -e PVRTC --channel-weighting-linear --bits-per-pixel-2 -o %s -p %s %s" % (TOOL, pvr, png, source)
         os.system( command )
   
         if( LOAD_ATT ):
            Blender.Image.Load(pvr)
         if( LOAD_PNG ):
            Blender.Image.Load(png)
      
         lin_2bpp_text = "Done"
      
      
      if (LIN_4BPP):
         png = "%s_4l%d%d%d.pvr.png" % (name, LEVEL, alpha, size)   
         pvr = "%s_4l%d%d%d.att" % (name, LEVEL, alpha, size)
         status = "%s & %s" % (os.path.basename(pvr), os.path.basename(png))
         lin_4bpp_text = "Creating..."              
         Draw()
         command = "%s -e PVRTC --channel-weighting-linear --bits-per-pixel-4 -o %s -p %s %s" % (TOOL, pvr, png, source)
         os.system( command )
   
         if( LOAD_ATT ):
            Blender.Image.Load(pvr)
         if( LOAD_PNG ):
            Blender.Image.Load(png)
      
         lin_4bpp_text = "Done"

   
      if (PER_2BPP):
         png = "%s_2p%d%d%d.pvr.png" % (name, LEVEL, alpha, size)   
         pvr = "%s_2p%d%d%d.att" % (name, LEVEL, alpha, size)
         status = "%s & %s" % (os.path.basename(pvr), os.path.basename(png))
         per_2bpp_text = "Creating..."              
         Draw()
         command = "%s -e PVRTC --channel-weighting-perceptual --bits-per-pixel-2 -o %s -p %s %s" % (TOOL, pvr, png, source)
         os.system( command )
   
         if( LOAD_ATT ):
            Blender.Image.Load(pvr)
         if( LOAD_PNG ):
            Blender.Image.Load(png)
      
         per_2bpp_text = "Done"                        
      
   
      if (PER_4BPP):
         png = "%s_4p%d%d%d.pvr.png" % (name, LEVEL, alpha, size)   
         pvr = "%s_4p%d%d%d.att" % (name, LEVEL, alpha, size)
         status = "%s & %s" % (os.path.basename(pvr), os.path.basename(png))
         per_4bpp_text = "Creating..."              
         Draw()
         command = "%s -e PVRTC --channel-weighting-perceptual --bits-per-pixel-4 -o %s -p %s %s" % (TOOL, pvr, png, source)
         os.system( command )
   
         if( LOAD_ATT ):
            Blender.Image.Load(pvr)
         if( LOAD_PNG ):
            Blender.Image.Load(png)
      
         per_4bpp_text = "Done"
      
      

      set_current_image()
      SCRIPT_RUN_STATE = IDLE
      lin_2bpp_text = ""
      lin_4bpp_text = ""
      per_2bpp_text = ""
      per_4bpp_text = ""
      Draw();

      error_str += "Converting Successful: %.3f sec." % ( Blender.sys.time() - start_time )   
      PupMenu( error_str )
      
      
   #error   
   else:
      PupMenu( error_str)
   

#====================================
# MAIN
#====================================
register_gui()



zzajin

Posts : 81
Join date : 2008-10-14

View user profile

Back to top Go down

changes to the sio2 exporter

Post  zzajin on Wed Nov 12, 2008 9:58 pm

EDITTED: added missing buffer writes

Change the following in sio_exporter_v1.2.1.py

replace line 651


Code:


                     t_name = tex_channel[1].tex.image.filename
                     if( t_name.endswith('.pvr.png') > 0):
                        t_name = t_name.replace('.pvr.png', '.att')
                     buffer = "\ttex1( \"%s\" )\n" % ( "image/" + os.path.basename( t_name ) )
                     f.write( buffer )



replace line 629

Code:

                     t_name = tex_channel[0].tex.image.filename
                     if( t_name.endswith('.pvr.png') > 0):
                        t_name = t_name.replace('.pvr.png', '.att')
                     buffer = "\ttex0( \"%s\" )\n" % ( "image/" + os.path.basename( t_name ) )
                     f.write( buffer )


replace lines 257-260


Code:


            if( UPDATE or not os.path.exists( tmp_name ) ):
                                                
               #copy the .att image when a placeholder (.pre) image is used
               if( t_name.endswith('.pvr.png') > 0):
                  t_name = Blender.sys.expandpath( t.tex.image.filename )
                  t_name = t_name.replace('.pvr.png', '.att')   
                  if( os.path.exists( t_name ) ):
                     pack_name = t_name.split('\\')[-1].split('/')[-1]
                     pack_name = output + "image/" +  pack_name   
                     shutil.copyfile( t_name, pack_name )
                  else:
                     error_str = "ERROR: Unable to find compressed file: %s. |" % t_name
                     return -1
               else:
                  shutil.copyfile( Blender.sys.expandpath( t.tex.image.filename ), tmp_name )
            
            return 1




Last edited by zzajin on Thu Nov 13, 2008 12:10 pm; edited 1 time in total

zzajin

Posts : 81
Join date : 2008-10-14

View user profile

Back to top Go down

Re: Compressed Textures from Apple's texturetool

Post  uprise78 on Thu Nov 13, 2008 7:56 am

this looks great. thanks for sharing. I will give the workflow a try today and report back.

uprise78

Posts : 228
Join date : 2008-10-31

View user profile

Back to top Go down

Re: Compressed Textures from Apple's texturetool

Post  uprise78 on Thu Nov 13, 2008 11:22 am

zzajin,

Thanks again for this contribution. I got the siodecompresspvr.h/.cc files loaded and compiling properly and the image exporter works like a charm. I modified the exporter but I think I may be unclear as to what is supposed to be modified. When I run the exporter, I get the .att texture in the images folder as expected, but the material is coming out as an empty file which I believe is the issue. When I render, the material is not getting applied though stepping through the debugger sio2ImageLoadATT() is getting called without error. I am thinking the exporter is the problem with it providing an empty material file. The following is the relevant section of the exporter. Can you take a look at it and let me know if it is correct? Should the buffer that is being created be written at some point?

Code:
                  #================================
                  # TEX0
                  #================================
                  flags = 0
                  
                  if( st0 == 1 ):
                     
                     # Use Mipmap
                     if( tex_channel[0].tex.imageFlags & Texture.ImageFlags["MIPMAP"] ):
                        flags = flags | 1
                        
                     # Clamp to Edge
                     if( tex_channel[0].tex.getExtend() == "Clip" ):
                        flags = flags | 2

                     buffer = "\ttflags0( %s )\n" % flags
                     f.write( buffer )
                     
                     buffer = "\ttex0( \"%s\" )\n" % ( "image/" + os.path.basename( tex_channel[0].tex.image.filename ) )
                     f.write( buffer )

                     t_name = tex_channel[0].tex.image.filename
                     if( t_name.endswith('.pvr.png') > 0):
                        t_name = t_name.replace('.pvr.png', '.att')
                     buffer = "\ttex0( \"%s\" )\n" % ( "image/" + os.path.basename( t_name ) )
   
                  #================================
                  # TEX1
                  #================================
                  flags = 0

                  if( st1 == 1 ):
                     
                     # Use mipmap
                     if( tex_channel[1].tex.imageFlags & Texture.ImageFlags["MIPMAP"] ):
                        flags = flags | 1
                        
                     # Clamp to edge
                     if( tex_channel[1].tex.getExtend() == "Clip" ):
                        flags = flags | 2

                     buffer = "\ttflags1( %s )\n" % flags
                     f.write( buffer )

                     buffer = "\ttex1( \"%s\" )\n" % ( "image/" + os.path.basename( tex_channel[1].tex.image.filename ) )
                     f.write( buffer )
   
                     t_name = tex_channel[1].tex.image.filename
                     if( t_name.endswith('.pvr.png') > 0):
                        t_name = t_name.replace('.pvr.png', '.att')
                     buffer = "\ttex1( \"%s\" )\n" % ( "image/" + os.path.basename( t_name ) )

uprise78

Posts : 228
Join date : 2008-10-31

View user profile

Back to top Go down

Re: Compressed Textures from Apple's texturetool

Post  zzajin on Thu Nov 13, 2008 12:08 pm

uprise78 wrote:zzajin,

Should the buffer that is being created be written at some point?


Yes you are right I missed the lines after the setting the buffer. Thanks for finding this.


Code:


f.write( buffer )


I'll fix the above post.

zzajin

Posts : 81
Join date : 2008-10-14

View user profile

Back to top Go down

Re: Compressed Textures from Apple's texturetool

Post  uprise78 on Thu Nov 13, 2008 12:46 pm

zzajin,

I added the f.write( buffer ) lines after each of the 2 texture blocks and when running the exporter it seems to hang when trying to write the Material files. Any ideas? It seems that the .att textures are copied to the images directory as expected.

Would it be possible for you to email or post the updated python exporter script? I can host it if needed so that others can have access to it.


Last edited by uprise78 on Thu Nov 13, 2008 1:04 pm; edited 1 time in total

uprise78

Posts : 228
Join date : 2008-10-31

View user profile

Back to top Go down

Re: Compressed Textures from Apple's texturetool

Post  zzajin on Thu Nov 13, 2008 1:04 pm

Here is my exporter:


part 1



Code:


#!BPY

"""
Name: 'SIO2 Exporter v1.2.1 (.sio2)...'
Blender: 248
Group: 'Export'
Tooltip: 'Export the current scene to SIO2 (.sio2)'
"""


import os
import sys
import struct
import math
import Blender
import platform
import shutil
import bpy

from Blender                 import Texture
from Blender                 import Window
from Blender                import Object
from Blender                import Mesh
from Blender                 import Mathutils
from Blender                import NMesh

from Blender.Draw          import *
from Blender.BGL         import *
from Blender.Window     import *
from Blender.Mathutils import *


SIO2_INTERNAL_NAME    = "SIO2::Exporter"
SIO2_VERSION_MAJOR    = 1
SIO2_VERSION_MINOR    = 2
SIO2_VERSION_PATCH    = 1

EVENT_EXIT                 = 0
EVENT_PATH_CHANGE     = 1
EVENT_EXPORT             = 2
EVENT_DIR_SELECT       = 3
EVENT_TOGGLE_UPDATE    = 4
EVENT_TOGGLE_NORMALS = 5

RAD_TO_DEG                 = 57.295779

UPDATE                      = 0
NORMALS                       = 0
PRECISION                   = 3

#=========================================
# GLOBAL VARIABLES
#=========================================
error_str = ""
output      = ""

   
#=========================================
# DEFAULT OUTPUT PATH::REMOVE WHEN RELEASE
#=========================================
directory = Create("")


#========================================
# REGISTER GUI
#========================================
def register_gui():
#========================================
   Register( draw_gui, None, event_gui )


#========================================
# DRAW RECTANGLE
#========================================
def draw_rectangle( x, y, w, h, r, g, b, a ):
#========================================

   glEnable( GL_BLEND )
   glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA )
   
   glColor4f( r,g,b,a )
   
   glBegin( GL_POLYGON )
   
   glVertex2i( x    , y    )
   glVertex2i( x    , y + h )
   glVertex2i( x + w, y + h )
   glVertex2i( x + w, y    )
   
   glEnd()   
   
   glDisable( GL_BLEND )


#=========================================
# RENDER THE EXPORTER GUI
#=========================================
def draw_gui():
#=========================================
   global directory


   glClearColor(0.74, 0.74, 0.74, 0.0)
   glClear(GL_COLOR_BUFFER_BIT)

   draw_rectangle( 5, 92, 400,  20, 0.6, 0.6, 0.6, 1.0 )
   draw_rectangle( 5,  6, 400,  86, 0.8, 0.8, 0.8, 1.0 )

   glColor3f( 1.0, 1.0, 1.0 )
   glRasterPos2i( 280, 98 )
   
   tmp = "%s v%d.%d.%d" % ( SIO2_INTERNAL_NAME,
                                        SIO2_VERSION_MAJOR,
                                        SIO2_VERSION_MINOR,
                                        SIO2_VERSION_PATCH )
   Text( tmp )
   

   glPolygonMode( GL_FRONT_AND_BACK, GL_LINE )
   draw_rectangle( 5,  7, 399, 106, 0.5, 0.5, 0.5, 1.0 )
   draw_rectangle( 5,  7, 399,  86, 0.5, 0.5, 0.5, 1.0 )   
   glPolygonMode( GL_FRONT_AND_BACK, GL_FILL )

   
   glColor3f(0.0, 0.0, 0.0)
   glRasterPos2i(15, 72)
   Text("Output Directory:")

   directory = String( "",
                    EVENT_PATH_CHANGE,
                    15, 45, 360, 20,
                    directory.val, 255,
                    "")

   Button( "..."  , EVENT_DIR_SELECT    , 375, 45,  20, 20 )
   Button( "Export", EVENT_EXPORT          , 185, 16, 100, 20 )
   Button( "Exit"  , EVENT_EXIT          , 295, 16, 100, 20 )
   Toggle( "UP"      , EVENT_TOGGLE_UPDATE , 15,  16,  20, 20, UPDATE , "Update the current SIO2 archive." )
   Toggle( "NO"      , EVENT_TOGGLE_NORMALS, 40,  16,  20, 20, NORMALS, "Export smooth or solid normals." )

#====================================
# GUI EVENTS CALLBACKS
#====================================
def event_gui( event ):
#====================================   
   global UPDATE
   global NORMALS

   if( event == EVENT_EXIT                 ): Exit()
   if( event == EVENT_DIR_SELECT       ): Blender.Window.FileSelector( dir_selected, "Select", "" )
   if( event == EVENT_EXPORT              ): export()
   if( event == EVENT_TOGGLE_UPDATE  ): UPDATE  = not UPDATE
   if( event == EVENT_TOGGLE_NORMALS ): NORMALS = not NORMALS      


#====================================
# DIRECTORY HAVE CHANGED
#====================================
def dir_selected( _dir ):
#====================================
   global directory

   directory.val = _dir


#====================================
# OPTIMIZE FLOAT FOR STRING
#====================================
def optimize_float( f ):
#====================================
   i = int( f )
   
   r = round( f, PRECISION )
   
   if i == r:   
      return i
   else:
      return r


#====================================
# CREATE ARCHITECTURE DIRECTORY
#====================================
def create_directory( d ):
#====================================
   
   try:
      os.mkdir( d )
      
   except:
      dummy = 0   


#====================================
# DISTANCE BETWEEN 2 VERTICES
#====================================
def distance( v1, v2 ):
#====================================

   v = []
   
   v.append( v1[0] - v2[0] )   
   v.append( v1[1] - v2[1] )      
   v.append( v1[2] - v2[2] )

   return math.sqrt( ( v[0] * v[0] ) +
                            ( v[1] * v[1] ) +
                            ( v[2] * v[2] ) )   



#====================================
# CHECK TEXTURE
#====================================
def check_texture( t ):
#====================================
   global error_str
   global UPDATE

   if( t != None ):

      if( t.tex.type == Texture.Types.IMAGE ):

         if( t.tex.image != None ):
            
            #====================================
            # Check if the file exists
            #====================================            
            if( not os.path.exists( Blender.sys.expandpath( t.tex.image.filename ) ) ):
               error_str = "ERROR: Unable to find file: %s. |" % t.tex.image.filename
               return -1
                  
            #====================================
            # Check if the file is a valid file.
            #====================================
            t_name = t.tex.image.filename.split('\\')[-1].split('/')[-1]
            
            ogg_uc_pos = t_name.upper().rfind('.OGG' )

            if( ogg_uc_pos > -1 ):
                  
               #====================================
               # Copy the sound file.
               #====================================
               tmp_name = output + "sound/" + t_name
                        
               if( UPDATE or not os.path.exists( tmp_name ) ):
                  shutil.copyfile( Blender.sys.expandpath( t.tex.image.filename ), tmp_name )
                  return 1


            #====================================
            # Copy the texture file.
            #====================================
            tmp_name = output + "image/" + t_name
                     
            if( UPDATE or not os.path.exists( tmp_name ) ):
                                                
               #copy the .att image when a placeholder (.pre) image is used
               if( t_name.endswith('.pvr.png') > 0):
                  t_name = Blender.sys.expandpath( t.tex.image.filename )
                  t_name = t_name.replace('.pvr.png', '.att')
                  if( os.path.exists( t_name ) ):
                     pack_name = t_name.split('\\')[-1].split('/')[-1]
                     pack_name = output + "image/" +  pack_name
                     shutil.copyfile( t_name, pack_name )
                  else:
                     error_str = "ERROR: Unable to find compressed file: %s. |" % t_name
                     return -1
               else:
                  shutil.copyfile( Blender.sys.expandpath( t.tex.image.filename ), tmp_name )
            
            return 1
   
   return 0




zzajin

Posts : 81
Join date : 2008-10-14

View user profile

Back to top Go down

Re: Compressed Textures from Apple's texturetool

Post  zzajin on Thu Nov 13, 2008 1:05 pm

part 2


Code:



#====================================
# Function that return a vector in
# object space.
#====================================
def get_loc_obj( v, obj_mat ):
#====================================

   x  = v[0]   
   y  = v[1]
   z  = v[2]
   
   tx = 0.0
   ty = 0.0
   tz = 0.0      

   tx = ( x * obj_mat[0][0] ) + ( y * obj_mat[1][0] ) + ( z * obj_mat[2][0] )
   ty = ( x * obj_mat[0][1] ) + ( y * obj_mat[1][1] ) + ( z * obj_mat[2][1] )
   tz = ( x * obj_mat[0][2] ) + ( y * obj_mat[1][2] ) + ( z * obj_mat[2][2] )

   return tx, ty, tz


#====================================
# Get the DimXYZ of the object
# based on its bounding box
#====================================
def get_dim( obj, mesh ):
#====================================

   dim       = [ 0.0, 0.0, 0.0 ]
   ubound = [-9999.0, -9999.0, -9999.0]
   lbound = [ 9999.0,  9999.0,  9999.0]
   
   tmp_mat = obj.getMatrix().copy()
   obj_mat = tmp_mat.identity()
   
   for v in mesh.verts:
   
      tmp = [ v.co[0], v.co[1], v.co[2] ]

      vloc = get_loc_obj( tmp , obj_mat )
   
      # min
      if vloc[0] < lbound[0]:
         lbound[0] = vloc[0]
         
      if vloc[1] < lbound[1]:
         lbound[1] = vloc[1]
         
      if vloc[2] < lbound[2]:
         lbound[2] = vloc[2]
   
   
      # max
      if vloc[0] > ubound[0]:
         ubound[0] = vloc[0]
   
      if vloc[1] > ubound[1]:
         ubound[1] = vloc[1]
         
      if vloc[2] > ubound[2]:
         ubound[2] = vloc[2]
   
   
   # DimX
   a = [ ubound[0], ubound[1], ubound[2] ]
   b = [ lbound[0], ubound[1], ubound[2] ]
   
   dim[0] = distance( a, b ) / 2


   # DimY
   a = [ ubound[0], ubound[1], ubound[2] ]
   b = [ ubound[0], lbound[1], ubound[2] ]
   
   dim[1] = distance( a, b ) / 2
   
   
   # DimZ
   a = [ ubound[0], ubound[1], ubound[2] ]
   b = [ ubound[0], ubound[1], lbound[2] ]
   
   dim[2] = distance( a, b ) / 2
   
   return dim


#====================================
# Function that return a if an object
# instance have been found.
#====================================
def get_instance( s ):
#====================================
   obj = 0
   us_pos = s.rfind('.')

   if( us_pos == -1 ):
      return obj

   else:
      
      try:   
         obj = Blender.Object.Get( s[:us_pos] )
      
      except:      
         obj = 0
      
   return obj


#====================================
# VERTEX CLASS
#====================================
class vertex( object ):
   pass


#====================================
# GET INDEX IN A SPECIFIED VBO ARRAY
#====================================
def get_index( lst, v ):

   for i in range( len( lst ) ):
      
      if( lst[ i ].ver == v.ver and
            lst[ i ].vco == v.vco and
            lst[ i ].vno == v.vno and
            lst[ i ].uv0 == v.uv0 and
            lst[ i ].uv1 == v.uv1 ):
         return i
      
   return -1


#====================================
# EXPORT
#====================================
def export():
#====================================
   global output
   global directory
   global error_str
   
   error_str = ""

   #====================================
   # Start the export process.
   #====================================
   start_time = Blender.sys.time()

   
   print
   print
   print "%s v%d.%d.%d\n%s\n" % ( SIO2_INTERNAL_NAME,
                                               SIO2_VERSION_MAJOR,
                                                SIO2_VERSION_MINOR,
                                                 SIO2_VERSION_PATCH,
                                                 "Copyright (C) 2008 SIO2 Interactive" )
   print



   #====================================
   # Get the current scene and all the
   # objects related to it.
   #====================================   
   scene  = Blender.Scene.GetCurrent()
   layer      = scene.getLayers()
   objects = scene.objects
   

   #====================================
   # VALIDATE AND CREATE SCENE DIRECTORY
   #====================================
   if( not len( directory.val ) ):
      error_str = "Invalid output directory. |"
      PupMenu( error_str )
      return
   
   if( directory.val[ len(directory.val) - 1 ] != "/" ):
      directory.val = directory.val + "/"
   
   directory.val.replace('\\','/')


   #====================================
   # Check if the path is suspicious cuz
   # instead I can wipe out the whole
   # drive...
   #====================================   
   output = directory.val + scene.getName() + "/"
   
   create_directory( output              )
   create_directory( output + "material/" )
   create_directory( output + "image/"     )   
   create_directory( output + "object/"  )
   create_directory( output + "camera/"  )
   create_directory( output + "sound/"    )
   create_directory( output + "lamp/"    )
   create_directory( output + "script/"  )

   #====================================
   # Make sure that we are not in edit
   # mode...
   #====================================
   Window.EditMode( 0 )


   #================================
   # CAMERA
   #================================
   for obj in objects:
      
      if( obj.getType() == "Camera" and obj.layers[0] == layer[0] and obj.isSelected() ):
         
         #================================
         # CREATING CAMERA FILE
         #================================            
         if( UPDATE or not os.path.exists( output + "camera/" + obj.getName() ) ):
            
            
            f = open( output + "camera/" + obj.getName(), "w")
   
            #====================================
            # Get access to the camera structure.
            #====================================
            cam = obj.getData( False, True )
            

            #================================
            # NAME
            #================================
            buffer = "camera( \"%s\")\n{\n" % ( "camera/" + obj.getName() )
            f.write( buffer )


            #================================
            # POSITION
            #================================
            buffer = "\tpos( %s %s %s )\n" % ( optimize_float( obj.LocX ),
                                                                  optimize_float( obj.LocY ),
                                                                  optimize_float( obj.LocZ ) )
            f.write( buffer )   

   
            #================================
            # TARGET POSITION
            #================================
            tar = ( Blender.Mathutils.Vector( 0.0, 0.0, -1.0 ) * obj.matrixWorld )

            buffer = "\ttar( %s %s %s )\n" % ( optimize_float( tar[0] ),
                                                                  optimize_float( tar[1] ),
                                                                  optimize_float( tar[2] ) )
            f.write( buffer )   
   
   
            #================================
            # FOV
            #================================
            buffer = "\tfov( %s )\n" % optimize_float( cam.getLens() )
            f.write( buffer )
      
      
            #================================
            # ZNEAR
            #================================
            buffer = "\tcstart( %s )\n" % optimize_float( cam.getClipStart() )
            f.write( buffer )


            #================================
            # ZFAR
            #================================
            buffer = "\tcend( %s )\n" % optimize_float( cam.getClipEnd() )
            f.write( buffer )            

            
            #===============================
            # CLOSE CAMERA
            #===============================
            f.write( "}\n" )
            obj.select(0)                     
            f.close()   
      

   #====================================
   # MATERIALS
   #====================================
   for obj in objects:
      
      if( obj.getType() == "Mesh" and obj.layers[0] == layer[0] and obj.isSelected() ):
         
         #====================================
         # Get access to the mesh of this
         # object...
         #====================================         
         mesh = obj.getData( False, True )   
         
         if( len( mesh.materials ) ):
            
            for mat in mesh.materials:
            
               #================================
               # CREATING MATERIAL FILES
               #================================            
               if( UPDATE or not os.path.exists( output + "material/" + mat.getName() ) ):
                  
                  f = open( output + "material/" + mat.getName(), "w")
                  
                  tex_channel = mat.getTextures()   
                  st0 = check_texture( tex_channel[0] ) # Diffuse
                  st1 = check_texture( tex_channel[1] ) # Shadowmap
                  st2 = check_texture( tex_channel[2] ) # Sound (OGG)   
                  
                  if( st0 < 0 or st1 < 0 or st2 < 0 ):
                     PupMenu( error_str )
                     return
   
                  #================================
                  # NAME
                  #================================
                  buffer = "material( \"%s\" )\n{\n" % ( "material/" + mat.getName() )
                  f.write( buffer )
   
   
                  #================================
                  # TEX0
                  #================================
                  flags = 0
                  
                  if( st0 == 1 ):
                     
                     # Use Mipmap
                     if( tex_channel[0].tex.imageFlags & Texture.ImageFlags["MIPMAP"] ):
                        flags = flags | 1
                        
                     # Clamp to Edge
                     if( tex_channel[0].tex.getExtend() == "Clip" ):
                        flags = flags | 2

                     buffer = "\ttflags0( %s )\n" % flags
                     f.write( buffer )
                     
                     t_name = tex_channel[0].tex.image.filename
                     if( t_name.endswith('.pvr.png') > 0):
                        t_name = t_name.replace('.pvr.png', '.att')
                     buffer = "\ttex0( \"%s\" )\n" % ( "image/" + os.path.basename( t_name ) )
                     f.write( buffer )

   
                  #================================
                  # TEX1
                  #================================
                  flags = 0
                  
                  if( st1 == 1 ):
                     
                     # Use mipmap
                     if( tex_channel[1].tex.imageFlags & Texture.ImageFlags["MIPMAP"] ):
                        flags = flags | 1
                        
                     # Clamp to edge
                     if( tex_channel[1].tex.getExtend() == "Clip" ):
                        flags = flags | 2

                     buffer = "\ttflags1( %s )\n" % flags
                     f.write( buffer )

                     t_name = tex_channel[1].tex.image.filename
                     if( t_name.endswith('.pvr.png') > 0):
                        t_name = t_name.replace('.pvr.png', '.att')
                     buffer = "\ttex1( \"%s\" )\n" % ( "image/" + os.path.basename( t_name ) )
                     f.write( buffer )
   
                  
                  #================================
                  # SOUND
                  #================================
                  if( st2 == 1 ):

                     # Autoplay
                     if( tex_channel[2].tex.imageFlags & Texture.ImageFlags["MIPMAP"] ):
                        flags = flags | 1
                        
                     # Loop
                     if( tex_channel[2].tex.getExtend() == "Repeat" ):
                        flags = flags | 2
                        
                     
                     # Ambient
                     if( tex_channel[2].tex.imageFlags & Texture.ImageFlags["INTERPOL"] ):
                        flags = flags | 4
                     
                     # FX
                     else:                     
                        flags = flags | 8

                     buffer = "\tsflags( %s )\n" % flags
                     f.write( buffer )
                     
                     buffer = "\tsbname( \"%s\" )\n" % ( "sound/" + os.path.basename( tex_channel[2].tex.image.filename ) )
                     f.write( buffer )

   
                  #================================
                  # DIFFUSE
                  #================================
                  buffer = "\tdiffuse( %s %s %s )\n" % ( optimize_float( mat.getRGBCol()[0] ),
                                                                             optimize_float( mat.getRGBCol()[1] ),
                                                                              optimize_float( mat.getRGBCol()[2] ) )
                  f.write( buffer )
   
   
                  #================================
                  # SPECULAR
                  #================================
                  buffer = "\tspecular( %s %s %s )\n" % ( optimize_float( mat.getSpecCol()[0] ),
                                                                                 optimize_float( mat.getSpecCol()[1] ),
                                                                                 optimize_float( mat.getSpecCol()[2] ) )
                  f.write( buffer )


                  #================================
                  # ALPHA
                  #================================
                  if( mat.getAlpha() ):               
                     buffer = "\talpha( %s )\n" % optimize_float( mat.getAlpha() )
                     f.write( buffer )


                  #================================
                  # SHININESS
                  #================================
                  if( mat.getHardness() ):
                     buffer = "\tshininess( %s )\n" % optimize_float( ( mat.getHardness() / 4 ) )
                     f.write( buffer )

   
                  #================================
                  # FRICTION
                  #================================
                  if( mat.rbFriction ):
                     buffer = "\tfriction( %s )\n" % optimize_float( mat.rbFriction )
                     f.write( buffer )
      
                     
                  #================================
                  # RESTITUTION
                  #================================
                  if( mat.rbRestitution ):
                     buffer = "\trestitution( %s )\n" % optimize_float( mat.rbRestitution )
                     f.write( buffer )
                  
                  
                  #================================
                  # ALPHA LEVEL
                  #================================
                  if( mat.getTranslucency() ):
                     buffer = "\talvl( %s )\n" % optimize_float( mat.getTranslucency() )
                     f.write( buffer )

   
                  #================================
                  # BLEND MODE
                  #================================
                  blend = 0
                  
                  if( st0 > 0 ):                        
                     blend = tex_channel[0].blendmode
                  
                     # Use Value for Alpha
                     if( blend == 12 ):
                        blend = 1
                                             
                     elif( blend > 0 ):
                        blend = blend + 1

                  if( blend ):
                     buffer = "\tblend( %s )\n" % blend
                     f.write( buffer )
   
   
                  #================================
                  # END MATERIAL
                  #================================               
                  f.write( "}\n" )         
                  f.close()   





zzajin

Posts : 81
Join date : 2008-10-14

View user profile

Back to top Go down

Re: Compressed Textures from Apple's texturetool

Post  zzajin on Thu Nov 13, 2008 1:05 pm

part 3


Code:



   #====================================
   # LAMP
   #====================================
   for obj in objects:
      
      if( obj.getType() == "Lamp" and obj.layers[0] == layer[0] and obj.isSelected() ):
         
         if( UPDATE or not os.path.exists( output + "lamp/" + obj.getName() ) ):      
            
            #====================================
            # Write the current lamp data.
            #====================================
            f = open( output + "lamp/" + obj.getName(), "w")
   
   
            #================================
            # NAME
            #================================
            buffer = "lamp( \"%s\")\n{\n" % ( "lamp/" + obj.getName() )
            f.write( buffer )
   
   
            #===============================
            # TYPE
            #===============================   
            # 0 = Lamp
            # 1 = Sun
            # 2 = Spot
            # 3 = Hemi
            # 4 = Area
            #===============================
            lamp = obj.getData()
            
            if( lamp.getType() ):
               buffer = "\ttype( %s )\n" % lamp.getType()
               f.write( buffer )
   
   
            #===============================
            # FLAGS
            #===============================
            flags = 0
            
            if( lamp.getMode() & Blender.Lamp.Modes["NoDiffuse"] ):
               flags = flags | 1
            
            if( lamp.getMode() & Blender.Lamp.Modes["NoSpecular"] ):
               flags = flags | 2
   
            if( flags ):
               buffer = "\tflags( %s )\n" % flags
               f.write( buffer )         
   
                     
            #===============================
            # POSITION
            #===============================
            buffer = "\tpos( %s %s %s )\n" % ( optimize_float( obj.loc[0] ),
                                                                  optimize_float( obj.loc[1] ),
                                                                  optimize_float( obj.loc[2] ) )
            f.write( buffer )
   
   
            #===============================
            # DIRECTION VECTOR
            #===============================
            dir = Blender.Mathutils.Vector( 0.0, 0.0, -1.0 )
            
            if( lamp.getType() == 1 ):
               dir.x = obj.matrixWorld[2][0]
               dir.y = obj.matrixWorld[2][1]
               dir.z = obj.matrixWorld[2][2]         
            
            elif( lamp.getType() == 2 ):
               dir.x = -obj.matrixWorld[2][0]
               dir.y = -obj.matrixWorld[2][1]
               dir.z = -obj.matrixWorld[2][2]         
   
            buffer = "\tdir( %s %s %s )\n" % ( optimize_float( dir.x ),
                                                                  optimize_float( dir.y ),
                                                                  optimize_float( dir.z ) )
            f.write( buffer )
   
   
            #===============================
            # COLOR
            #===============================
            buffer = "\tcol( %s %s %s )\n" % ( optimize_float( lamp.col[0] ),
                                                                  optimize_float( lamp.col[1] ),
                                                                  optimize_float( lamp.col[2] ) )
            f.write( buffer )
            
   
            #===============================
            # ENERGY
            #===============================
            buffer = "\tnrg( %s )\n" % optimize_float( lamp.getEnergy() )
            f.write( buffer )
   
   
            #===============================
            # DISTANCE
            #===============================
            buffer = "\tdst( %s )\n" % optimize_float( lamp.getDist() )
            f.write( buffer )         
   
   
            #===============================
            # FOV
            #===============================
            buffer = "\tfov( %s )\n" % optimize_float( lamp.getSpotSize() )
            f.write( buffer )
   
   
            #===============================
            # SPOT BLEND
            #===============================
            buffer = "\tsblend( %s )\n" % optimize_float( lamp.getSpotBlend() )
            f.write( buffer )
            
   
            #===============================
            # LINEAR ATTENUATION
            #===============================
            buffer = "\tatt1( %s )\n" % optimize_float( lamp.getQuad1() )
            f.write( buffer )         
            
   
            #===============================
            # QUADRATIC ATTENUATION
            #===============================
            buffer = "\tatt2( %s )\n" % optimize_float( lamp.getQuad2() )
            f.write( buffer )         
   
   
            #===============================
            # CLOSE LAMP
            #===============================
            f.write( "}\n" )
            obj.select(0)         
            f.close()


   #====================================
   # OBJECT
   #====================================   
   for obj in objects:
      
      if( obj.getType() == "Mesh" and obj.layers[0] == layer[0] and obj.isSelected() ):   

         if( UPDATE or not os.path.exists( output + "object/" + obj.getName() ) ):
      
            #====================================
            # Write the current object data.
            #====================================
            f = open( output + "object/" + obj.getName(), "w")


            #====================================
            # Get access to the mesh of this
            # object...
            #====================================         
            mesh = obj.getData( False, True )
      
      
            #====================================
            # Convert all quads into triangles,
            # and remove every duplicates.
            #====================================
            for face in mesh.faces:
               face.sel = 1
      
            mesh.quadToTriangle( 0 )
            mesh.remDoubles( 0 )
            mesh.update()
            mesh = obj.getData( False, True )   
      
            for face in mesh.faces:
               face.sel = 0
            
            
            #================================
            # NAME
            #================================
            buffer = "object( \"%s\" )\n{\n" % ( "object/" + obj.getName() )
            f.write( buffer )
   
            
            #===============================
            # POSITION
            #===============================
            buffer = "\tpos( %s %s %s )\n" % ( optimize_float( obj.loc[0] ),
                                                                  optimize_float( obj.loc[1] ),
                                                                  optimize_float( obj.loc[2] ) )
            f.write( buffer )
            
            
            #===============================
            # ROTATION (in degree)
            #===============================
            rot   = []
            rot.append( obj.rot[0] * RAD_TO_DEG )
            rot.append( obj.rot[1] * RAD_TO_DEG )
            rot.append( obj.rot[2] * RAD_TO_DEG )
      
            if( rot[0] < 0 ): rot[0] = rot[0] + 360.0
            if( rot[1] < 0 ): rot[1] = rot[1] + 360.0
            if( rot[2] < 0 ): rot[2] = rot[2] + 360.0   
      
            if( optimize_float( rot[0] ) != 0.0 or
                   optimize_float( rot[1] ) != 0.0 or
                   optimize_float( rot[2] ) != 0.0 ):
      
               buffer = "\trot( %s %s %s )\n" % ( optimize_float( rot[0] ),
                                                                     optimize_float( rot[1] ),
                                                                     optimize_float( rot[2] ) )
               f.write( buffer )   
            
            
            #===============================
            # SCALE
            #===============================
            if( optimize_float( obj.size[0] ) != 1.0 or
                   optimize_float( obj.size[1] ) != 1.0 or
                   optimize_float( obj.size[2] ) != 1.0 ):
               
               buffer = "\tscl( %s %s %s )\n" % ( optimize_float( obj.size[0] ),
                                                                     optimize_float( obj.size[1] ),
                                                                     optimize_float( obj.size[2] ) )
               f.write( buffer )
            
            
            #================================
            # BOUNDING SPHERE RADIUS
            #================================
            i = 0
            j = 1
            
            bb = obj.getBoundBox()            
      
            bs_radius = 0
      
            for i in range( 7 ):
      
               for j in range( 8 ):
      
                  dd = ( distance( bb[i], bb[j] ) * 0.5 )
      
                  if( dd > bs_radius ):
      
                     bs_radius = dd
      
            buffer = "\trad( %s )\n" % optimize_float( bs_radius )
            f.write( buffer )
   
      
            #===============================
            # PHYSIC FLAGS
            #===============================
            flags  = 0
            bounds  = 4
            mass    = 0.0
            
            if( obj.rbFlags & Object.RBFlags["ACTOR"] ):
               flags = flags | 1         
      
            if( obj.rbFlags & Object.RBFlags["GHOST"] ):
               flags = flags | 2   
            
            if( obj.rbFlags & Object.RBFlags["ACTOR"] and
                  obj.rbFlags & Object.RBFlags["DYNAMIC"] ):
               
               flags = flags | 4
               
               if( obj.rbFlags & Object.RBFlags["ACTOR"] and
                     obj.rbFlags & Object.RBFlags["DYNAMIC"] and
                     obj.rbFlags & Object.RBFlags["RIGIDBODY"] ):
                  flags = flags | 8
      
               """
               if( obj.rbFlags & Object.RBFlags["ACTOR"] and
                     obj.rbFlags & Object.RBFlags["DYNAMIC"] and
                     obj.rbFlags & Object.RBFlags["SOFTBODY"] ):
                  flags = flags & ~ 8
                  flags = flags | 16
               """
               
               if( obj.rbFlags & Object.RBFlags["COLLISION_RESPONSE"] ):
                  flags = flags | 256
            
            
            #===============================
            # MISC. FLAGS
            #===============================
            uv_channel = mesh.getUVLayerNames()
            
            for face in mesh.faces:
      
               if( not len( uv_channel ) ):
                  break
   
               # Two Side
               if( face.mode & NMesh.FaceModes["TWOSIDE"] ):
                  flags = flags | 128
                  
               # Cylindrical               
               if( face.mode & NMesh.FaceModes["BILLBOARD"] ):
                  flags = flags | 32
                  break
      
               # Spherical
               if( face.mode & NMesh.FaceModes["HALO"] ):
                  flags = flags | 64
                  break
   
      
            if( flags ):      
               buffer = "\tflags( %s )\n" % flags
               f.write( buffer )
            
      
            #====================================
            # OBJECT BOUNDS
            #
            # 0 - Cube
            # 1 - Sphere
            # 2 - Cylinder
            # 3 - Cone
            # 4 - Static Triangle Mesh
            # 5 - Convex Hull Polytope
            #
            #====================================         
            if( obj.rbFlags & Object.RBFlags[ "ACTOR"  ] and
                  obj.rbFlags & Object.RBFlags[ "DYNAMIC" ] ):
               """
                   or
                  obj.rbFlags & Object.RBFlags[ "SOFTBODY"]         
               """
               
               bounds = obj.rbShapeBoundType
               
               if( bounds != 4 ):
                  mass = obj.rbMass
            
            if( bounds ):
               buffer = "\tbounds( %s )\n" % bounds
               f.write( buffer )
            
      
            #===============================
            # MASS
            #===============================
            if( mass ):
               buffer = "\tmass( %s )\n" % optimize_float( mass )
               f.write( buffer )
   
   
            #===============================
            # Please take note that the
            # following properties cannot
            # be accessed with python, you'll
            # have to manually enter them
            # to the object properties in
            # order for them to work.
            #===============================
            """
            damp <float>
            rotdamp <float>
            margin <float>
            """   
            
            #===============================
            # DIM XYZ
            #===============================
            dim = get_dim( obj, mesh )
      
            buffer = "\tdim( %s %s %s )\n" % ( optimize_float( dim[0] ),
                                                                  optimize_float( dim[1] ),
                                                                  optimize_float( dim[2] ) )
            f.write( buffer )         
   
      
            #===============================
            # USER PROPERTIES
            #===============================
            properties = obj.getAllProperties()
   
            for p in properties:
   
               if( p.getType() == "STRING" ):               
                  buffer = "\t%s( \"%s\" )\n" % ( p.getName(), p.getData() )
                  
               else:
                  buffer = "\t%s( %s )\n" % ( p.getName(), p.getData() )               
                  
               f.write( buffer )
   
   
            #===============================
            # SCRIPTS
            #===============================
            script = obj.getScriptLinks( "FrameChanged" )
            
            for s in script:
               
               tmp_name = output + "script/" + s
               t = Blender.Text.Get( s )
               
               if( UPDATE or not os.path.exists( tmp_name ) ):
                  shutil.copyfile( t.getFilename(), tmp_name )
            
   
            #===============================
            # INSTANCE
            #===============================               
            inst = get_instance( obj.getName() )
            
            if( inst and inst.layers[0] == layer[0] ):
               
               buffer = "\tiname( \"%s\" )\n" % ( "object/" + inst.getName() )
               f.write( buffer )
               
               
               #===============================
               # CLOSE OBJECT
               #===============================
               f.write( "}\n" )
               obj.select(0)         
               f.close()
      
               continue
   
            #================================
            # CREATE VERTEX GROUP (IF NOT ANY)
            #================================         
            if( not len( mesh.getVertGroupNames() ) ):
      
                  mesh.addVertGroup( "null" )
                  
                  tmp_vert_lst = []
                  for v in mesh.verts:
                     tmp_vert_lst.append( v.index )
                     
                  mesh.assignVertsToGroup( "null", tmp_vert_lst, 1.0, Blender.Mesh.AssignModes.REPLACE )
                  mesh.update()
   


zzajin

Posts : 81
Join date : 2008-10-14

View user profile

Back to top Go down

Re: Compressed Textures from Apple's texturetool

Post  zzajin on Thu Nov 13, 2008 1:06 pm

part 4


Code:


      
            #===============================
            # CREATE THE NECESSARY VBO ARRAY
            #===============================
            vert_lst = []
            
            for face in mesh.faces:
   
               for i in range( 3 ):
                  
                  tmp_vert = vertex()
                  
                  tmp_vert.ver = Blender.Mathutils.Vector( optimize_float( face.v[i].co[0] ),
                                                                             optimize_float( face.v[i].co[1] ),
                                                                               optimize_float( face.v[i].co[2] ) )
                  
                  
                  tmp_vert.vco = None
                  if( mesh.vertexColors ):
                     
                     rgba = [ face.col[i][0],
                                  face.col[i][1],
                                  face.col[i][2],
                                  face.col[i][3] ]
                                 
                     tmp_vert.vco = rgba
                  
                  
                  tmp_vert.vno = None
                  
                  if( NORMALS ):
                     
                     if( face.smooth ):
                        tmp_vert.vno = Blender.Mathutils.Vector( optimize_float( face.v[i].no[0] ),
                                                                                     optimize_float( face.v[i].no[1] ),
                                                                                     optimize_float( face.v[i].no[2] ) )                  
                     else:
                        tmp_vert.vno = Blender.Mathutils.Vector( optimize_float( face.no[0] ),
                                                                                     optimize_float( face.no[1] ),
                                                                                     optimize_float( face.no[2] ) )
                        
                  
                  tmp_vert.uv0 = None
                  if( len( uv_channel ) ):
                     mesh.activeUVLayer = uv_channel[0]
                     tmp_vert.uv0 = Blender.Mathutils.Vector( optimize_float( face.uv[i][0] ),
                                                                                  optimize_float( 1.0 - face.uv[i][1] ),
                                                                                  0.0 )
                  
                           
                  tmp_vert.uv1 = None
                  if( len( uv_channel ) > 1 ):
                     mesh.activeUVLayer = uv_channel[1]
                     tmp_vert.uv1 = Blender.Mathutils.Vector( optimize_float( face.uv[i][0] ),
                                                                                  optimize_float( 1.0 - face.uv[i][1] ),
                                                                                  0.0 )
            
                  
                  if( get_index( vert_lst, tmp_vert ) == -1 ):
                     vert_lst.append( tmp_vert )
   
   
            #===============================
            # BOFFSET
            #===============================
            vbo_offset = [ 0, 0, 0, 0 ]
            vbo_size     = len( vert_lst ) * 3 * 4
            
            
            # Vertex Color
            if( mesh.vertexColors ):
               vbo_offset[0] = vbo_size
               vbo_size = vbo_size + len( vert_lst ) * 4
   
         
            # Vertex Normals
            if( NORMALS ):
               
               vbo_offset[1] = vbo_size
               vbo_size = vbo_size + len( vert_lst ) * 3 * 4
   
                  
            # UV0
            if( len( uv_channel ) ):
               vbo_offset[2] = vbo_size
               vbo_size = vbo_size + len( vert_lst ) * 2 * 4
   
      
            # UV1         
            if( len( uv_channel ) > 1 ):
               vbo_offset[3] = vbo_size
               vbo_size = vbo_size + len( vert_lst ) * 2 * 4
               
            
            #===============================
            # WRITE BUFFER SIZE + OFFSET
            #===============================
            buffer = "\tvbo_offset( %s %s %s %s %s )\n" % ( vbo_size,
                                                                                   vbo_offset[0],
                                                                                   vbo_offset[1],
                                                                                   vbo_offset[2],
                                                                                   vbo_offset[3] )
            f.write( buffer )
   
         
            #===============================
            # VBO
            #===============================         
            
            # Vertex      
            for v in vert_lst:
               buffer = "\tvert( %s %s %s )\n" % ( optimize_float( v.ver.x ),
                                                                      optimize_float( v.ver.y ),
                                                                      optimize_float( v.ver.z ) )
               f.write( buffer )            
   
   
            # Vertex Color
            if( mesh.vertexColors ):
               vbo_offset[0] = vbo_size
               vbo_size = vbo_size + len( vert_lst ) * 4
               
               for v in vert_lst:
                  buffer = "\tvcol( %s %s %s %s )\n" % ( v.vco[ 0 ],
                                                                            v.vco[ 1 ],
                                                                            v.vco[ 2 ],
                                                                            v.vco[ 3 ] )
                  f.write( buffer )                  
   
         
            # Vertex Normals
            if( NORMALS ):
               
               vbo_offset[1] = vbo_size
               vbo_size = vbo_size + len( vert_lst ) * 3 * 4
               
               for v in vert_lst:
                  buffer = "\tvnor( %s %s %s )\n" % ( optimize_float( v.vno.x ),
                                                                         optimize_float( v.vno.y ),
                                                                         optimize_float( v.vno.z ) )
                  f.write( buffer )                                                      
   
                  
            # UV0
            if( len( uv_channel ) ):
               vbo_offset[2] = vbo_size
               vbo_size = vbo_size + len( vert_lst ) * 2 * 4
                              
               for v in vert_lst:
                  buffer = "\tuv0( %s %s )\n" % ( optimize_float( v.uv0.x ),
                                                                   optimize_float( v.uv0.y ) )
                  f.write( buffer )
   
      
            # UV1         
            if( len( uv_channel ) > 1 ):
               vbo_offset[3] = vbo_size
               vbo_size = vbo_size + len( vert_lst ) * 2 * 4
      
               for v in vert_lst:
                  buffer = "\tuv1( %s %s )\n" % ( optimize_float( v.uv1.x ),
                                                                   optimize_float( v.uv1.y ) )
                  f.write( buffer )
   
   
      
            #================================
            # WRITE THE N VERTEX GROUPS
            #================================
            buffer = "\tn_vgroup( %s )\n" % len( mesh.getVertGroupNames() )
            f.write( buffer )         
   
            
            #================================
            # WRITE THE VERTEX GROUPS BLOCKS
            #================================         
            for vg in mesh.getVertGroupNames():
                     
               # Unselect All
               for i in mesh.verts:
                  i.sel = 0
                  
               for face in mesh.faces:
                  face.sel = 0               
      
               # Get vertex list
               try:
                  
                  v_lst = mesh.getVertsFromGroup( vg, 1 )
            
               except:
                  
                  error_str = "ERROR: This object contain no vertices: %s. |" % obj.getName()
                  PupMenu( error_str )
                  return
            
               #===============================
               # NAME
               #===============================
               buffer = "\tvgroup( \"%s\" )\n" % vg
               f.write( buffer )
      
                                 
               # Select all group vertices
               for v in v_lst:
                  mesh.verts[ v[0] ].sel = 1
            
               n_ind = 0
               for face in mesh.faces:
                  
                  if( face.v[0].sel == 1 and
                        face.v[1].sel == 1 and
                        face.v[2].sel == 1 ):
                     face.sel = 1
                     
                     if( not n_ind ):
                        
                        if( len( mesh.materials ) ):
                           
                           mat = mesh.materials[ face.mat ]
                           buffer = "\tmname( \"%s\" )\n" % ( "material/" + mat.getName() )
                           f.write( buffer )               
                     
                     n_ind = n_ind + 3
   
   
               #===============================
               # N_INDICES
               #===============================            
               buffer = "\tn_ind( %s )\n" % n_ind
               f.write( buffer )
   
   
               #===============================
               # TRIANGLE INDICES
               #===============================
               for face in mesh.faces:
      
                  if( face.sel == 1 ):
                     
                     buffer = "\tind( "
                     f.write( buffer )
                     
                     #===============================
                     # INDICES
                     #===============================                              
                     for i in range( 3 ):
                        
                        tmp_vert = vertex()
                        
                        tmp_vert.ver = Blender.Mathutils.Vector( optimize_float( face.v[i].co[0] ),
                                                                                   optimize_float( face.v[i].co[1] ),
                                                                                     optimize_float( face.v[i].co[2] ) )
                        
                        tmp_vert.vco = None
                        
                        if( mesh.vertexColors ):
                           rgba = [ face.col[i][0],
                                        face.col[i][1],
                                        face.col[i][2],
                                        face.col[i][3] ]
                                       
                           tmp_vert.vco = rgba
                        
   
                        tmp_vert.vno = None
                        
                        if( NORMALS ):
                           
                           if( face.smooth ):
                              tmp_vert.vno = Blender.Mathutils.Vector( optimize_float( face.v[i].no[0] ),
                                                                                           optimize_float( face.v[i].no[1] ),
                                                                                           optimize_float( face.v[i].no[2] ) )                  
                           else:
                              tmp_vert.vno = Blender.Mathutils.Vector( optimize_float( face.no[0] ),
                                                                                           optimize_float( face.no[1] ),
                                                                                           optimize_float( face.no[2] ) )
                        
                        tmp_vert.uv0 = None
                        if( len( uv_channel ) ):
                           mesh.activeUVLayer = uv_channel[0]
                           tmp_vert.uv0 = Blender.Mathutils.Vector( optimize_float( face.uv[i][0] ),
                                                                                        optimize_float( 1.0 - face.uv[i][1] ),
                                                                                        0.0 )
                        
                                 
                        tmp_vert.uv1 = None
                        if( len( uv_channel ) > 1 ):
                           mesh.activeUVLayer = uv_channel[1]
                           tmp_vert.uv1 = Blender.Mathutils.Vector( optimize_float( face.uv[i][0] ),
                                                                                        optimize_float( 1.0 - face.uv[i][1] ),
                                                                                        0.0 )
                                                                                                         
                        index = get_index( vert_lst, tmp_vert )
                        
                        if( index == -1 ):
                           error_str = "ERROR: Unable to find vertex indice: %s. |" % obj.getName()
                           PupMenu( error_str )
                           return
                        
                        buffer = "%s " % index
                        f.write( buffer )
                        
                     buffer = ")\n"
                     f.write( buffer )
      
            #===============================
            # CLOSE OBJECT
            #===============================
            f.write( "}\n" )         
            obj.select(0)         
            f.close()


   #====================================
   # CREATE/UPDATE THE ZIP ARCHIVE
   #====================================
   os.chdir( output )
   
   if( not UPDATE ):
      remove = "rm ../" + scene.getName() + ".sio2"
      os.system( remove )
      
   
   compress = "zip -9 -o ../" + scene.getName() + ".sio2 -r *"
   os.system( compress )
         
   #===============================
   # END
   #===============================
   error_str += "Export Successful: %.3f sec." % ( Blender.sys.time() - start_time )   
   PupMenu( error_str )
   
   #Exit()
      

#====================================
# MAIN
#====================================
register_gui()



zzajin

Posts : 81
Join date : 2008-10-14

View user profile

Back to top Go down

Re: Compressed Textures from Apple's texturetool

Post  matt on Thu Nov 13, 2008 1:11 pm

Thanks for your efforts. Does using this format make any difference in terms of performance?

Best,
Matt

matt

Posts : 155
Join date : 2008-09-30

View user profile http://elfrun.net

Back to top Go down

Re: Compressed Textures from Apple's texturetool

Post  zzajin on Thu Nov 13, 2008 1:21 pm

matt wrote:Thanks for your efforts. Does using this format make any difference in terms of performance?


While I have no numbers to back me up - it should: both in memory usage and speed.

It's part of the recommended method for optimizing textures according to Apple https://developer.apple.com/iphone/library/technotes/tn2008/tn2230.html and Imagination Technologies ( I don't have that link - actually I think it's in a pdf).

Actually seeing the memory usage change should be easy - I just haven't checked it out.

Part of my hope is the workflow is convenient enough to make trying different textures semi-easy.

zzajin

Posts : 81
Join date : 2008-10-14

View user profile

Back to top Go down

Re: Compressed Textures from Apple's texturetool

Post  matt on Thu Nov 13, 2008 1:28 pm

zzajin wrote:While I have no numbers to back me up - it should: both in memory usage and speed.
If you ever get some numbers on performance, please let me know. Memory isn't really an issue for me, but performance is. But, honestly, I think the image format is only interesting for disk space and pregenerated mipmaps, internally the device will most likely store the texture in a format most convenient for the texture processing unit. (But I have no idea about the GPU internals so I may very well be wrong. ;-))

Best,
Matt

matt

Posts : 155
Join date : 2008-09-30

View user profile http://elfrun.net

Back to top Go down

Re: Compressed Textures from Apple's texturetool

Post  uprise78 on Thu Nov 13, 2008 1:57 pm

Thanks again zzajin,

For some reason I still can't get the material to export. It either doesn't complete the export or I get a material that is an empty file. Any idea what it can be?

uprise78

Posts : 228
Join date : 2008-10-31

View user profile

Back to top Go down

Re: Compressed Textures from Apple's texturetool

Post  zzajin on Thu Nov 13, 2008 2:07 pm

Would you mind sending me you blend file, .pvr.png, and .att file(s)? I sent you my email. Also what version of blender are you using? Are the textures in the same directory and differ only by ".pvr.png" and ".att" extensions?

zzajin

Posts : 81
Join date : 2008-10-14

View user profile

Back to top Go down

Re: Compressed Textures from Apple's texturetool

Post  uprise78 on Thu Nov 13, 2008 2:45 pm

zzajin wrote:Would you mind sending me you blend file, .pvr.png, and .att file(s)? I sent you my email. Also what version of blender are you using? Are the textures in the same directory and differ only by ".pvr.png" and ".att" extensions?

Email sent with the files. I am using Blender 2.48. The .att files seem to get created properly along with the .pvr.png files.

Thanks for looking at this.

uprise78

Posts : 228
Join date : 2008-10-31

View user profile

Back to top Go down

Re: Compressed Textures from Apple's texturetool

Post  uprise78 on Thu Nov 13, 2008 3:24 pm

Just so everyone knows, zzajin is awesome. He found the problem in no time at all (my silly mistake for having an indent off in the Python script). Many thanks to zzajin for this contribution which will allow textures to load faster and take up less memory!

Thanks zzajin.

uprise78

Posts : 228
Join date : 2008-10-31

View user profile

Back to top Go down

Re: Compressed Textures from Apple's texturetool

Post  uprise78 on Sun Dec 21, 2008 5:39 pm

Is there any chance of getting these changes into SIO2? This is the type of optimization that everyone can benefit from.

uprise78

Posts : 228
Join date : 2008-10-31

View user profile

Back to top Go down

Re: Compressed Textures from Apple's texturetool

Post  zzajin on Mon Dec 22, 2008 11:20 am

Unfortunately, this is somewhat outdated now and I'm not sure when I'll be able to update it. The newest version of the SDK includes a new texturetool. This new version includes mipmaps and I think creates pvr files similar to ImgTech's file format. There is sample code for parsing the pvr file available in the dev center. Having the meta data embedded into the file would be a nice improvement. As would mipmaps of course.

zzajin

Posts : 81
Join date : 2008-10-14

View user profile

Back to top Go down

Re: Compressed Textures from Apple's texturetool

Post  Sponsored content


Sponsored content


Back to top Go down

View previous topic View next topic Back to top

- Similar topics

 
Permissions in this forum:
You cannot reply to topics in this forum