No demo yet, so make sure you follow the explanations (text I posted earlier today at Segaxtreme) :
I got the model converter I promised you working at pretty much 70-80%, but I didn't have time to test it nor write a demo.
It seems to be ok, but since I didn't test it, I can't guarantee it.
IT'S ALSO REALLY QUICKLY CODED! I made it in like 2 hours and only did small tests, so it might not work properly.
I'm sharing it with you now, but I guess without a demo it might be a bit hard to use.
The file starts with a header portion of 36 bytes, then writes the texture data, then the polygon data.
I added the header and the code to know how I write to the binary file so that you know what to load.
You can use the image converter I posted elsewhere to know how to load the paletted textures.
The program also outputs a text file including all the PDATA, but no textures, so you can also play with that.
Please note that it only supports textures, so if you want to load a flat shaded polygon, you can use something such as a 8x1 texture with 1 color. I guess it would be a bit slower than using a real flat shaded quad, but I don't think I will have time to modify my code to allow it for now.
//HEADER
typedef struct
{
unsigned short TOTAL_MESH; //total amount of PDATA
short TOT_TEXT; //total amount of textures
unsigned int TEXT_SIZE; //to quickly load from disk, that's the size of the textures in bytes
unsigned int PDATA_SIZE; //to quickly load from disk, total size of pdata in bytes
vector3 Origin; //Origin point used to "center" the culling/collision data and your model's position. Should be 0,0,0 unless you have an offset
vector3 Length; //Lenght along the x,y z axis. Together with the origin, that gives you the bounding box for quick broad collision testing
} _MOD_DATA;
//TEXTURE DATA
unsigned short convert_to_4bpp(unsigned short a, unsigned short b){ return (((a&0xffff)<<4) | (b));}
void WRITES_TEXTURES(ofstream * binFile)
{
cout << "Writing the textures to binary file...\n\n";
unsigned short buf16;
for (short i=0; i<MODEL_DATA.TOT_TEXT; i++)
{
unsigned short w = swap_endian_ushort(pimg[i].width); //pimg == paletted image
unsigned short h = swap_endian_ushort(pimg[i].height);
binFile->write((char*)&w, sizeof(unsigned short));
binFile->write((char*)&h, sizeof(unsigned short));
binFile->write((char*)&MODEL_DATA.TEXT_SIZE, sizeof(int));
for (short ii=0; ii< (pimg[i].width * pimg[i].height);)
{
unsigned char buf = 0;
buf = (unsigned char) convert_to_4bpp(pimg[i].palette_id[ii], pimg[i].palette_id[ii+1]);
binFile->write((char*)&buf, sizeof(unsigned char));
ii+=2;
}
}
for (short i=0; i<MODEL_DATA.TOT_TEXT; i++)
{
for (unsigned int ii=0; ii<16; ii++)
{
buf16 = swap_endian_ushort(pimg[i].palette[ii]);
binFile->write((char*)(&buf16), sizeof(unsigned short));
}
}
}
//PDATA
/*****
This writes all the PDATA in a sequential order
*****/
void WRITE_PDATA(ofstream * file)
{
unsigned short bUint16;
unsigned int bUint32;
int bSint32;
for (unsigned int i=0; i<MODEL_DATA.TOTAL_MESH; i++)
{
//PDATA, including buffers for the pointers
bUint32 = 0;
file->write((char*)&bUint32, sizeof(unsigned int));
bUint32 = swap_endian_uint(mesh_array[i].nbPoint);
file->write((char*)&bUint32, sizeof(unsigned int));
bUint32 = 0;
file->write((char*)&bUint32, sizeof(unsigned int));
bUint32 = swap_endian_uint(mesh_array[i].nbPolygon);
file->write((char*)&bUint32, sizeof(unsigned int));
bUint32 = 0;
file->write((char*)&bUint32, sizeof(unsigned int));
//POINT (vertices), 12 bytes each
for (unsigned int ii=0; ii<mesh_array[i].nbPoint; ii++)
{
for (unsigned int j=0; j<3; j++)
{
bSint32 = swap_endian_sint(mesh_array[i].pntbl[ii][j]);
file->write((char*)&bSint32, sizeof(int));
}
}
//POLYGON, 12 bytes for normals and 8 bytes for vertices
for (unsigned int ii=0; ii<mesh_array[i].nbPolygon; ii++)
{
//Normals
for (unsigned int j=0; j<3; j++)
{
bSint32 = swap_endian_sint(mesh_array[i].pltbl[ii].norm[j]);
file->write((char*)&bSint32, sizeof(int));
}
//Vertices
for (unsigned int j=0; j<4; j++)
{
bUint16 = swap_endian_ushort(mesh_array[i].pltbl[ii].Vertices[j]);
file->write((char*)&bUint16, sizeof(unsigned short));
}
}
//ATTRIBUTES, 12 bytes each
for (unsigned int ii=0; ii<mesh_array[i].nbPolygon; ii++)
{
file->write((char*)&TextureAttributeArray[mesh_array[i].attbl[ii].texno].flag, sizeof(unsigned char));
file->write((char*)&TextureAttributeArray[mesh_array[i].attbl[ii].texno].sorting, sizeof(unsigned char));
bUint16=swap_endian_ushort(TextureAttributeArray[mesh_array[i].attbl[ii].texno].texno);
file->write((char*)&bUint16, sizeof(unsigned short));
bUint16=swap_endian_ushort(TextureAttributeArray[mesh_array[i].attbl[ii].texno].atrb);
file->write((char*)&bUint16, sizeof(unsigned short));
bUint16=swap_endian_ushort(TextureAttributeArray[mesh_array[i].attbl[ii].texno].colno);
file->write((char*)&bUint16, sizeof(unsigned short));
bUint16=swap_endian_ushort(TextureAttributeArray[mesh_array[i].attbl[ii].texno].gstb);
file->write((char*)&bUint16, sizeof(unsigned short));
bUint16=swap_endian_ushort(TextureAttributeArray[mesh_array[i].attbl[ii].texno].dir);
file->write((char*)&bUint16, sizeof(unsigned short));
}
}
}
So, you can use something such as GFS_LOAD starting with 36 bytes to know what the file contains, then read the textures (just put it in low-work RAM), DMA everything to VRAM where it belongs and then overwrite the data in low-work RAM with the PDATA (since the textures are transfered, you don't need them in work-RAM, so just overwrite them).
For the textures, make sure you do it per face instead of using texture coordinates.
The converter I wrote only supports 16 colors per texture, but save your TGA files as 32 bits files. The alpha channel is treated as transparent.
I'll see what I can do for the demo, but I'm a bit busy with work so I might not have time. Let me know if you encounter bugs!
I added the title map from Quake as a demo, but this tool isn't meant for maps since it doesn't do map partition nor does it hold data for culling!