--- /dev/null
+Ship models from:
+
+http://www.turbosquid.com/3d-models/3d-spaceship-ship-space-model/408426
+
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));
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, ¢er, &up);
+ GFX.look_at(0,0,-15, 0,0,0, 0,1,0);
sceGumMatrixMode(GU_MODEL);
int i=0;
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);
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 );
void Gfx::cleanup()
{
sceGuTerm();
+ free(display_list);
}
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 );
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, ¢er, &up);
}
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()
#include "model.h"
#include <cstdio>
#include <cstring>
+#include <pspgu.h>
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;
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()
#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();
};
#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};
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;
}
// 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);
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;
+}
#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
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, ...]
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
# 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))
--- /dev/null
+#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);
+}
+
+