Model & texture code improved (including new exporter format), new ship model+texture...
authorslack <slack@codemaniacs.com>
Mon, 13 Oct 2008 03:00:18 +0000 (05:00 +0200)
committerslack <slack@codemaniacs.com>
Mon, 13 Oct 2008 03:00:18 +0000 (05:00 +0200)
12 files changed:
README [new file with mode: 0644]
game.cc
gfx.cc
gfx.h
model.cc
model.h
models/shipdawhip.lob [new file with mode: 0644]
models/shipdawhip.tga [new file with mode: 0644]
texture.cc
texture.h
tools/blender_exporter.py
tools/tga2ltx.cc [new file with mode: 0644]

diff --git a/README b/README
new file mode 100644 (file)
index 0000000..fc7ee55
--- /dev/null
+++ b/README
@@ -0,0 +1,4 @@
+Ship models from:
+
+http://www.turbosquid.com/3d-models/3d-spaceship-ship-space-model/408426
+
diff --git a/game.cc b/game.cc
index 2bcfab71ef8676dff7c9bd484b71626b4d3510d2..9099a590b0ea4ccbd265efbc173fbb1999d0c219 100644 (file)
--- a/game.cc
+++ b/game.cc
@@ -17,8 +17,8 @@ int game_main(int argc, char **argv)
        GFX.init();
 
        //Model cube("colors-noUV.lob");
-       Model cube("models/ship.lob");
-       Texture texture("models/ship.tga");
+       Model cube("models/shipdawhip.lob");
+       Texture texture("models/shipdawhip.tga");
        //sceKernelDcacheWritebackRange(cube.vertices, cube.num_vertices * sizeof(Vertex));
        //sceKernelDcacheWritebackRange(cube.indices, cube.num_faces * sizeof(unsigned short));
        //sceKernelDcacheWritebackRange(&cube, sizeof(cube));
@@ -26,10 +26,7 @@ int game_main(int argc, char **argv)
 
        GFX.perspective(75.0f, 16.0f/9.0f, 0.5f, 1000.0f);
 
-       ScePspFVector3 eye={0,0,-10};
-       ScePspFVector3 center={0,0,0};
-       ScePspFVector3 up={0,1,0};
-       GFX.look_at(&eye, &center, &up);
+       GFX.look_at(0,0,-15, 0,0,0, 0,1,0);
 
        sceGumMatrixMode(GU_MODEL);
        int i=0;
@@ -44,20 +41,11 @@ int game_main(int argc, char **argv)
                sceGumRotateY(0.001f*i);
                sceGumRotateZ(0.001f*i);
                sceGuColor(GU_COLOR(1.0f,1.0f,1.0f,0.0f));
-               sceGuTexImage( 0, texture.width, texture.height, texture.width, texture.pixels ); 
-               sceGumDrawArray(GU_TRIANGLES, 
-                               GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_NORMAL_32BITF |
-                               GU_VERTEX_32BITF | GU_TRANSFORM_3D | GU_INDEX_16BIT, cube.num_faces*3,
-                               cube.indices, cube.vertices);
+               texture.bind();
+               sceGumDrawArray(GU_TRIANGLES, cube.vtype | GU_TRANSFORM_3D, 
+                               cube.num_faces*3, cube.indices, cube.vertices);
        
                
-               ScePspFVector3 move={4,0,0};
-               sceGumLoadIdentity();
-               sceGumRotateZ(0.001f*i);
-               sceGumTranslate(&move);
-               
-               sceGuColor(GU_COLOR(1.0f,0.0f,0.0f,0.0f));
-               sceGumDrawArray(GU_TRIANGLES, GU_VERTEX_32BITF | GU_TRANSFORM_3D, 3, 0, triangle);
                
                sceGuFinish();
                sceGuSync(0,0);
diff --git a/gfx.cc b/gfx.cc
index 6268c6cb4f9083e926f573053c67073bd220f31f..c7f1b5dd6d3e7b457e0f99282c5bc5e72f7961fc 100644 (file)
--- a/gfx.cc
+++ b/gfx.cc
@@ -38,18 +38,17 @@ void Gfx::init()
        sceGuDepthFunc( GU_GEQUAL );
        sceGuEnable( GU_DEPTH_TEST );
        sceGuShadeModel( GU_SMOOTH );
-       sceGuFrontFace( GU_CW );
-       //sceGuEnable( GU_CULL_FACE );
-       //sceGuEnable( GU_CLIP_PLANES );
+       sceGuFrontFace( GU_CCW );
+       sceGuEnable( GU_CULL_FACE );
+       sceGuEnable( GU_CLIP_PLANES );
        
        // set clear color/depth
-       sceGuClearColor( GU_COLOR( 1.0f, 0.0f, 1.0f, 1.0f ) ); 
+       sceGuClearColor( GU_COLOR( 0.0f, 0.0f, 0.0f, 1.0f ) ); 
        sceGuClearDepth(0);     
 
        // setup texture
        sceGuEnable(GU_TEXTURE_2D);                     //Enable Texture2D
-       sceGuTexMode( GU_PSM_8888, 0, 0, 0 );           // last 0 must be 1 if swizzled 
-       sceGuTexFunc( GU_TFX_DECAL, GU_TCC_RGB );
+       sceGuTexFunc( GU_TFX_MODULATE, GU_TCC_RGB );
        sceGuTexFilter( GU_LINEAR, GU_LINEAR );         // Linear filtering (Good Quality) (NEW)
        sceGuTexScale( 1.0f, 1.0f );                    // No scaling
        sceGuTexOffset( 0.0f, 0.0f );
@@ -69,6 +68,7 @@ void Gfx::init()
 void Gfx::cleanup()
 {
        sceGuTerm();
+       free(display_list);
 }
 
 void Gfx::update_fps( void )
@@ -79,7 +79,8 @@ void Gfx::update_fps( void )
        if( ((fps_tick_now - fps_tick_last)/((float)tick_resolution)) >= 1.0f )
        {
                fps_tick_last = fps_tick_now;
-               sprintf( fps_display, "ticks=%f, FPS: %d", ((double)fps_tick_now/(double)tick_resolution), frames_drawn );
+               //sprintf( fps_display, "ticks=%f, FPS: %d", ((double)fps_tick_now/(double)tick_resolution), frames_drawn );
+               sprintf( fps_display, "FPS: %d", frames_drawn );
                frames_drawn = 0;
        }
        pspDebugScreenSetOffset( (int)fbp0 );
@@ -101,11 +102,16 @@ void Gfx::perspective(float fov, float aspect, float znear, float zfar)
        sceGumPerspective(fov, aspect, znear, zfar);
 }
 
-void Gfx::look_at(ScePspFVector3 *eye, ScePspFVector3 *center, ScePspFVector3 *up)
+void Gfx::look_at(float eye_x, float eye_y, float eye_z,
+                       float center_x, float center_y, float center_z,
+                       float up_x, float up_y, float up_z)
 {
        sceGumMatrixMode(GU_VIEW);
        sceGumLoadIdentity();
-       sceGumLookAt(eye, center, up);
+       ScePspFVector3 eye={eye_x, eye_y, eye_z};
+       ScePspFVector3 center={center_x, center_y, center_z};
+       ScePspFVector3 up={up_x, up_y, up_z};
+       sceGumLookAt(&eye, &center, &up);
 }
 
 
diff --git a/gfx.h b/gfx.h
index 83eb2d4f9ca1911b9ef99795af076bad1c3525ba..7ef25e5d03d6a64dae8633f409b9d052cc3d5887 100644 (file)
--- a/gfx.h
+++ b/gfx.h
@@ -27,6 +27,9 @@ class Gfx: public Singleton<Gfx>
 
        void perspective(float fov, float aspect, float znear, float zfar);
        void look_at(ScePspFVector3 *eye, ScePspFVector3 *center, ScePspFVector3 *up);
+       void look_at(float eye_x, float eye_y, float eye_z,
+                       float center_x, float center_y, float center_z,
+                       float up_x, float up_y, float up_z);
 };
 
 #define GFX Gfx::Instance()
index 48820f98e57711fe16954f9a72588714c733f556..eefc8431e84ed83830de2d34f0a9e295f761d7fb 100644 (file)
--- a/model.cc
+++ b/model.cc
@@ -1,6 +1,7 @@
 #include "model.h"
 #include <cstdio>
 #include <cstring>
+#include <pspgu.h>
 
 inline bool isnan(float x)
 {
@@ -9,18 +10,42 @@ inline bool isnan(float x)
 
 struct ModelHeader
 {
-       char sig[8]; // "laz0rOBJ"
+       char sig[4]; // "lzrO"
+       int vtype;
        int num_vertices;
        int num_faces;
 };
 
+size_t Model::vertex_size()
+{
+       size_t result=0;
+       if ((vtype & GU_TEXTURE_BITS) == GU_TEXTURE_8BIT) { printf("GU_TEXTURE_8BIT\n"); result += 2; }
+       else if ((vtype & GU_TEXTURE_BITS) == GU_TEXTURE_16BIT) { printf("GU_TEXTURE_16BIT\n"); result +=4; }
+       else if ((vtype & GU_TEXTURE_BITS) == GU_TEXTURE_32BITF) { printf("GU_TEXTURE_32BITF\n"); result += 8; }
+
+       if ((vtype & GU_COLOR_BITS) == GU_COLOR_5650) { printf("GU_COLOR_5650\n"); result += 2; }
+       else if ((vtype & GU_COLOR_BITS) == GU_COLOR_5551) { printf("GU_COLOR_5551\n"); result += 2; }
+       else if ((vtype & GU_COLOR_BITS) == GU_COLOR_4444) { printf("GU_COLOR_4444\n"); result += 2; }
+       else if ((vtype & GU_COLOR_BITS) == GU_COLOR_8888) { printf("GU_COLOR_8888\n"); result += 4; }
+
+       if ((vtype & GU_NORMAL_BITS) == GU_NORMAL_8BIT) { printf("GU_NORMAL_8BIT\n"); result += 3; }
+       else if ((vtype & GU_NORMAL_BITS) == GU_NORMAL_16BIT) { printf("GU_NORMAL_16BIT\n"); result += 6; }
+       else if ((vtype & GU_NORMAL_BITS) == GU_NORMAL_32BITF) { printf("GU_NORMAL_32BITF\n"); result += 12; }
+
+       if ((vtype & GU_VERTEX_BITS) == GU_VERTEX_8BIT) { printf("GU_VERTEX_8BIT\n"); result += 3; }
+       else if ((vtype & GU_VERTEX_BITS) == GU_VERTEX_16BIT) { printf("GU_VERTEX_16BIT\n"); result += 6; }
+       else if ((vtype & GU_VERTEX_BITS) == GU_VERTEX_32BITF) { printf("GU_VERTEX_32BITF\n"); result += 12; }
+
+       return result;
+}
+
 Model::Model(const char *filename)
 {
        printf("Reading model %s\n", filename);
        FILE *f=fopen(filename, "r");
        ModelHeader h;
        fread(&h, sizeof(ModelHeader), 1, f);
-       if (strncmp(h.sig, "laz0rOBJ", 8))
+       if (strncmp(h.sig, "lzrO", 4))
        {
                printf("Error, not a model file.\n");
                num_vertices=0;
@@ -28,22 +53,17 @@ Model::Model(const char *filename)
                return;
        }
 
+       vtype        = h.vtype;
        num_vertices = h.num_vertices;
        num_faces    = h.num_faces;
-       vertices     = new Vertex[num_vertices];
+       vertices     = new unsigned char[num_vertices*vertex_size()];
        indices      = new unsigned short[num_faces*3];
 
-       fread(vertices, sizeof(Vertex), num_vertices, f);
+       fread(vertices, vertex_size(), num_vertices, f);
        fread(indices, sizeof(unsigned short), 3*num_faces, f);
        fclose(f);
 
-       for (int i=0; i<num_vertices; i++)
-       {
-               if (isnan(vertices[i].u) || isnan(vertices[i].v))
-                       printf("NaN!\n");
-       }
-
-       printf("%d vertices, %d faces\n", num_vertices, num_faces);
+       printf("%d vertices, %d faces, vertex_size=%d\n", num_vertices, num_faces, vertex_size());
 }
 
 Model::~Model()
diff --git a/model.h b/model.h
index f217b01500db07b8c43524009357e43a076a6c32..fc33cd10f6df6e7a92c11b71bf65bbb5e730d083 100644 (file)
--- a/model.h
+++ b/model.h
@@ -1,23 +1,18 @@
 #if !defined(MODEL_H)
 #define MODEL_H
 
-#include <psptypes.h>
-
-struct Vertex
-{
-       float u,v;
-       u32 color;
-       float nx,ny,nz;
-       float x,y,z;
-};
+#include <cstdlib>
 
 struct Model
 {
+       int vtype;
        int num_vertices;
        int num_faces;
-       Vertex *vertices;
+       unsigned char *vertices;
        unsigned short *indices;
 
+       size_t vertex_size();
+       
        Model(const char *filename);
        ~Model();
 };
diff --git a/models/shipdawhip.lob b/models/shipdawhip.lob
new file mode 100644 (file)
index 0000000..49975b0
Binary files /dev/null and b/models/shipdawhip.lob differ
diff --git a/models/shipdawhip.tga b/models/shipdawhip.tga
new file mode 100644 (file)
index 0000000..491e0a9
Binary files /dev/null and b/models/shipdawhip.tga differ
index 11b34c9dd9d45e54047824ba9ea22536c750cfda..46de12f51c6e75ef4dd55323e4b64742ab6bfcb1 100644 (file)
@@ -2,14 +2,88 @@
 
 #include <cstdio>
 #include <cstring>
+#include <psptypes.h>
+#include <pspgu.h>
 
 Texture::Texture(const char *filename)
-{      
-       FILE *pFile = 0;
+{
+       int len = strlen(filename);
+       if (!strcmp("tga", filename+len-3) ||
+           !strcmp("TGA", filename+len-3))
+       {
+               readTGA(filename);
+       }
+       else
+       {
+               readLTX(filename);
+       }
+}
+
+// Returns number of bits per pixel based on texture type
+unsigned int Texture::get_bpp()
+{
+       switch(mode)
+       {
+               case GU_PSM_5650:
+               case GU_PSM_5551:
+               case GU_PSM_4444:
+                       return 16;
+               case GU_PSM_8888:
+                       return 32;
+               default:
+                       printf("Error: Unsupported texture type\n");
+       }
+       return -1;
+}
+
+// LTX == Laz0r TeXture ;)
+struct LTXHeader
+{
+       char sig[4]; // "lzrT"
+       int mode;
+       int width;
+       int height;
+};
+
+// init the Texture from a LTX file
+void Texture::readLTX(const char *filename)
+{
+       FILE *fp = fopen(filename, "rb");
+       if(!fp) 
+       {
+               printf("Error, couldn't open file\n");
+               return;
+       }
+
+       LTXHeader header;
+       
+       fread(&header, sizeof(LTXHeader), 1, fp);
+       if (strncmp("lzrT", header.sig, 4))
+       {
+               printf("Error: not a LTX file\n");
+               return;
+       }
+
+       mode   = header.mode;
+       width  = header.width;
+       height = header.height;
+       swizzled = true;
+
+       unsigned int size = width * height * (get_bpp()/8);
+       pixels = new unsigned char[size];
+
+       fread(pixels, sizeof(unsigned char), size, fp);
+       fclose(fp);
+
+       printf("Read LTX texture %s (%ux%ux%u), size=%u\n", filename, width, height, get_bpp(), size);
+
+}
+
+// init the Texture from a TGA file
+void Texture::readTGA(const char *filename)
+{
        // Variables to hold image info
        unsigned char tempColor;
-       unsigned char bitCount;
        int colorMode;
        long tgaSize;
        unsigned char unCompressHeader[12] = {0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0};
@@ -19,20 +93,22 @@ Texture::Texture(const char *filename)
        swizzled=false;
        
        // Open file
-       pFile = fopen( filename, "rb" );
+       FILE *fp = fopen(filename, "rb");
        
-       if( !pFile ) {
-               // if couldn't open, exit
+       if(!fp) 
+       {
+               printf("Error, couldn't open file\n");
                return;
        }
        
        // Read in BitmapHeader info into the structure
-       fread( &tgaHeader, 1, sizeof(tgaHeader), pFile );
+       fread(&tgaHeader, sizeof(tgaHeader), 1, fp);
        
        // We only want to read uncompressed TGA's. Chech the 
        // header if it is of an uncompressed one.
-       if( memcmp( unCompressHeader, tgaHeader, sizeof(unCompressHeader)) != 0 ) {
-               fclose( pFile );
+       if(memcmp(unCompressHeader, tgaHeader, sizeof(unCompressHeader)) != 0) 
+       {
+               fclose(fp);
                printf("Error, not an uncompressed TGA file\n");
                width=0;
                height=0;
@@ -41,32 +117,45 @@ Texture::Texture(const char *filename)
        }
  
        // Read Image info
-       fread( header, 1, sizeof(header), pFile );
+       fread( header, 1, sizeof(header), fp );
  
        // Calculate and save the Width & Height of Image
        width  = header[1] * 256 + header[0];
        height = header[3] * 256 + header[2];
-       bitCount    = header[4];
+       unsigned int bpp    = header[4];
+
+       if (bpp != 32) 
+       {
+               printf("Error: only 32-bit uncompressed TGA is supported");
+               return;
+       }
+
+       mode = GU_PSM_8888;
  
        // Calculate color mode & image size
-       colorMode       = bitCount / 8;
+       colorMode       = bpp / 8;
        tgaSize         = width * height * colorMode;
        printf("width=%hd, height=%hd, tgaSize=%ld\n", width, height, tgaSize);
  
        // Allocate memory for the image and load it
        pixels          = new unsigned char[tgaSize];
  
-       fread( pixels, sizeof(unsigned char), tgaSize, pFile );
+       fread(pixels, sizeof(unsigned char), tgaSize, fp);
  
        // Convert from BGR to RGB format.
-       for(long index = 0; index < tgaSize; index += colorMode) {
+       for(long index = 0; index < tgaSize; index += colorMode) 
+       {
                   tempColor = pixels[index];
                   pixels[index] = pixels[index + 2];
                   pixels[index + 2] = tempColor;
        }
        
        // Close the file
-       fclose( pFile );
+       fclose(fp);
+
+       swizzle();
+       swizzle();
+       swizzle();
 
        printf("Read TGA texture %s (%ux%u)\n", filename, width, height);
  
@@ -78,11 +167,108 @@ Texture::~Texture()
        delete[] pixels;
 }
 
-void swizzle()
+void Texture::bind()
 {
+       sceGuTexMode(mode, 0, 0, swizzled? 1: 0);
+       sceGuTexImage(0, width, height, width, pixels); 
+}
 
+void Texture::swizzle()
+{
+       unsigned int bytes_per_pixel = get_bpp()/8;
+       unsigned int i,j;
+       unsigned int rowblocks = (width * bytes_per_pixel / 16);
+       long size = width * height * long(bytes_per_pixel);
+        
+       unsigned char* out = new unsigned char[size];
+       for (j = 0; j < height; ++j)
+       {
+               for (i = 0; i < width*bytes_per_pixel; ++i)
+               {
+                       unsigned int blockx = i / 16;
+                       unsigned int blocky = j / 8;
+        
+                       unsigned int x = (i - blockx*16);
+                       unsigned int y = (j - blocky*8);
+                       unsigned int block_index = blockx + ((blocky) * rowblocks);
+                       unsigned int block_address = block_index * 16 * 8;
+        
+                       out[block_address + x + y * 16] = pixels[i+j*width*bytes_per_pixel];
+               }
+       }
+       memcpy(pixels, out, size );
+       swizzled = !swizzled;
+       delete[] out;
 }
 
+bool Texture::saveLTX(const char *filename, int dst_mode)
+{
+       // swizzling affects bytes, not pixels, so we unswizzle, convert
+       // the texture to the new pixel format, swizzle the new texture,
+       // save it and restore everything.
+       //
+       // FIXME: Swizzle != Unswizzle :(
+       
+       // Save current parameters
+       int src_mode = mode;
+       unsigned char *src_pixels = pixels;
+       bool src_swizzled = swizzled;
+
+       // Undo swizzling, if any
+       if (src_swizzled) swizzle();
 
+       if (mode != GU_PSM_8888)
+       {
+               printf("Error: Texture::saveLTX only supports GU_PSM_8888 as src mode\n");
+               return false;
+       }
+
+       mode = dst_mode;
+       printf("new_bpp=%u\n", get_bpp());
+       pixels = new unsigned char[width * height * (get_bpp()/8)];
+
+       // convert pixel format
+       int dst_index=0;
+       for (int src_index=0; src_index < width*height*4; src_index+=4)
+       {
+               unsigned char r = src_pixels[src_index];        
+               unsigned char g = src_pixels[src_index+1];      
+               unsigned char b = src_pixels[src_index+2];      
+               unsigned char a = src_pixels[src_index+3];
+               
+               switch(dst_mode)
+               {
+                       case GU_PSM_5650: {
+                               unsigned short val = ((r>>3) << 11) | ((g>>2) << 5) | (b>>3);
+                               ((unsigned short *)pixels)[dst_index] = val;
+                               dst_index++;
+                               break;
+                       }
+                       default:
+                               printf("Texture::saveLTX: Unsupported dst mode\n");
+                               return false;
+               }
+
+       }
+
+       // swizzle
+       swizzle();
+       
+       FILE *fp=fopen(filename, "wb");
+       LTXHeader header={{'l','z','r','T'}, dst_mode, width, height};
+       fwrite(&header, sizeof(LTXHeader), 1, fp);
+       fwrite(pixels, width*height*(get_bpp()/8), 1, fp);
+       fclose(fp);
+
+       delete[] pixels;
+
+       // restore
+       pixels = src_pixels;
+       mode = src_mode;
+       if (src_swizzled) swizzle();
+
+       return true;
+}
 
 
index 21ef07c2ac8ae08ad30121f712b2fff59698b394..9bd5f936cdf88bc9ba07bfe642b42f992193fa91 100644 (file)
--- a/texture.h
+++ b/texture.h
@@ -1,17 +1,27 @@
 #if !defined(TEXTURE_H)
 #define TEXTURE_H
 
+// NOTE: Only power of 2 textures are supported
 struct Texture
 {
        unsigned short width;
        unsigned short height;
-       unsigned char *pixels;
+       int mode;
        bool swizzled;
+       unsigned char *pixels;
 
        Texture(const char *filename);
        ~Texture();
 
-       void swizzle();
+       void bind();
+
+       bool saveLTX(const char *filename, int dst_mode);
+       
+       private:
+       void         swizzle();
+       unsigned int get_bpp();
+       void         readTGA(const char *filename);
+       void         readLTX(const char *filename);
 };
 
 #endif
index 7f0bc2dcfe5ca182e5911a127db77c1baf1e7813..b5af93d23ca7c1ad84cc294243d65f6bf4e37d51 100644 (file)
@@ -12,6 +12,75 @@ import Blender
 import bpy
 import struct
 
+# vertex declarations from pspgu.h
+def GU_TEXTURE_SHIFT(n):
+       return ((n)<<0)
+
+GU_TEXTURE_8BIT   = GU_TEXTURE_SHIFT(1)
+GU_TEXTURE_16BIT  = GU_TEXTURE_SHIFT(2)
+GU_TEXTURE_32BITF = GU_TEXTURE_SHIFT(3)
+GU_TEXTURE_BITS   = GU_TEXTURE_SHIFT(3)
+
+def GU_COLOR_SHIFT(n):
+       return ((n)<<2)
+
+GU_COLOR_5650 = GU_COLOR_SHIFT(4)
+GU_COLOR_5551 = GU_COLOR_SHIFT(5)
+GU_COLOR_4444 = GU_COLOR_SHIFT(6)
+GU_COLOR_8888 = GU_COLOR_SHIFT(7)
+GU_COLOR_BITS = GU_COLOR_SHIFT(7)
+
+def GU_NORMAL_SHIFT(n):
+       return ((n)<<5)
+
+GU_NORMAL_8BIT   = GU_NORMAL_SHIFT(1)
+GU_NORMAL_16BIT  = GU_NORMAL_SHIFT(2)
+GU_NORMAL_32BITF = GU_NORMAL_SHIFT(3)
+GU_NORMAL_BITS   = GU_NORMAL_SHIFT(3)
+
+def GU_VERTEX_SHIFT(n):
+       return ((n)<<7)
+
+GU_VERTEX_8BIT   = GU_VERTEX_SHIFT(1)
+GU_VERTEX_16BIT  = GU_VERTEX_SHIFT(2)
+GU_VERTEX_32BITF = GU_VERTEX_SHIFT(3)
+GU_VERTEX_BITS   = GU_VERTEX_SHIFT(3)
+
+def GU_WEIGHT_SHIFT(n):
+       return ((n)<<9)
+
+GU_WEIGHT_8BIT   = GU_WEIGHT_SHIFT(1)
+GU_WEIGHT_16BIT  = GU_WEIGHT_SHIFT(2)
+GU_WEIGHT_32BITF = GU_WEIGHT_SHIFT(3)
+GU_WEIGHT_BITS   = GU_WEIGHT_SHIFT(3)
+
+def GU_INDEX_SHIFT(n):
+       return ((n)<<11)
+
+GU_INDEX_8BIT  = GU_INDEX_SHIFT(1)
+GU_INDEX_16BIT = GU_INDEX_SHIFT(2)
+GU_INDEX_BITS  = GU_INDEX_SHIFT(3)
+
+def GU_WEIGHTS(n):
+       return ((((n)-1)&7)<<14)
+
+GU_WEIGHTS_BITS = GU_WEIGHTS(8)
+
+def GU_VERTICES(n):
+       return ((((n)-1)&7)<<18)
+
+GU_VERTICES_BITS = GU_VERTICES(8)
+
+def GU_TRANSFORM_SHIFT(n):
+       return ((n)<<23)
+
+GU_TRANSFORM_3D  = GU_TRANSFORM_SHIFT(0)
+GU_TRANSFORM_2D  = GU_TRANSFORM_SHIFT(1)
+GU_TRANSFORM_BITS = GU_TRANSFORM_SHIFT(1)
+
+
+
+
 def write(filename):
        vertex_list = [] # index --> {co=(x,y,z), no=(nx,ny,nz), uv=(u,v)}
        vertex_map = {} # (x,y,z) --> [index, index, ...]
@@ -25,6 +94,14 @@ def write(filename):
        
        mesh = obj.getData(mesh=1)
 
+       # mesh flags
+       flags = GU_VERTEX_32BITF | GU_NORMAL_32BITF | GU_INDEX_16BIT
+       if mesh.faceUV:
+               flags |= GU_TEXTURE_32BITF
+       
+       if mesh.vertexColors:
+               flags |= GU_COLOR_8888
+
        # add every vertex
        for vert in mesh.verts:
                vx,vy,vz = vert.co
@@ -92,16 +169,19 @@ def write(filename):
 
        # write header
        f = file(filename, "w")
-       f.write("laz0rOBJ")
-       f.write(struct.pack("<II", len(vertex_list), len(mesh.faces)))
+       f.write("lzrO")
+       f.write(struct.pack("<III", flags, len(vertex_list), len(mesh.faces)))
        print "%u verts, %u faces"%(len(vertex_list), len(mesh.faces))
        for vert in vertex_list:
                u,v = vert["uv"]
                r,g,b,a = vert["col"]
                nx,ny,nz = vert["no"]
                x,y,z = vert["co"]
-               f.write(struct.pack("< ff BBBB fff fff", u,v, r,g,b,a, nx, ny, nz, x,y,z)) # 36 bytes each
-               #f.write(struct.pack("< BBBB fff fff", r,g,b,a, nx, ny, nz, x,y,z)) # 28 bytes each
+               if mesh.faceUV:
+                       f.write(struct.pack("< ff", u, v)) # 8 bytes each
+               if mesh.vertexColors:
+                       f.write(struct.pack("< BBBB", r,g,b,a)) # 4 bytes each
+               f.write(struct.pack("fff fff", nx, ny, nz, x,y,z)) # 24 bytes each
        
        for i in index_list:
                f.write(struct.pack("<H", i))
diff --git a/tools/tga2ltx.cc b/tools/tga2ltx.cc
new file mode 100644 (file)
index 0000000..7611e55
--- /dev/null
@@ -0,0 +1,15 @@
+#include "../texture.h"
+
+#include <cstdio>
+#include <string>
+#include <pspgu.h>
+
+using namespace std;
+
+int main(int argc, char **argv)
+{
+       Texture t(argv[1]);
+       t.saveLTX(argv[2], GU_PSM_5650);
+}
+
+