You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
227 lines
6.0 KiB
227 lines
6.0 KiB
#include <memory.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "mdl.h"
|
|
#include "ps1mdl.h"
|
|
|
|
#define PALETTE_SIZE 256
|
|
|
|
#define NUMVERTEXNORMALS 162
|
|
static double anorms[NUMVERTEXNORMALS][3] = {
|
|
#include "../anorms.h"
|
|
};
|
|
|
|
int convertPalette(const char* lmpFile)
|
|
{
|
|
FILE* fp;
|
|
const short palette_size = PALETTE_SIZE;
|
|
unsigned char palette[PALETTE_SIZE * 3];
|
|
|
|
fopen_s(&fp, lmpFile, "rb");
|
|
if (fp == NULL)
|
|
return 0;
|
|
|
|
fread(palette, sizeof(unsigned char) * 3, PALETTE_SIZE, fp);
|
|
fclose(fp);
|
|
|
|
int file_size = PALETTE_SIZE * 4 + 24, tmp;
|
|
|
|
fopen_s(&fp, "quake.pal", "wb");
|
|
if (fp == NULL)
|
|
return 0;
|
|
|
|
fwrite("RIFF", sizeof(char), 4, fp);
|
|
tmp = file_size - 8;
|
|
fwrite(&tmp, sizeof(int), 1, fp);
|
|
fwrite("PAL data", sizeof(char), 8, fp);
|
|
tmp = file_size - 20;
|
|
fwrite(&tmp, sizeof(int), 1, fp);
|
|
fwrite("\000\003", sizeof(char), 2, fp);
|
|
fwrite(&palette_size, sizeof(short), 1, fp);
|
|
|
|
for (int i = 0; i < PALETTE_SIZE; ++i)
|
|
{
|
|
fwrite(palette + i * 3, 3, 1, fp);
|
|
fwrite("\000", sizeof(char), 1, fp);
|
|
}
|
|
|
|
tmp = 1337;
|
|
fwrite(&tmp, sizeof(int), 1, fp);
|
|
fclose(fp);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static void toFixedVector(const vec3_t inVec, int outVec[3])
|
|
{
|
|
const int scale = 1 << 12;
|
|
outVec[0] = (int)(inVec[0] * scale);
|
|
outVec[1] = (int)(inVec[1] * scale);
|
|
outVec[2] = (int)(inVec[2] * scale);
|
|
}
|
|
|
|
int convertModel(const char* outFile, const mdl_header_t* inHeader, const mdl_texcoord_t* inTexCoords, const mdl_triangle_t* inTriangles, const mdl_frame_t* inFrames)
|
|
{
|
|
FILE* fout;
|
|
fopen_s(&fout, outFile, "wb");
|
|
if (fout == NULL)
|
|
return 0;
|
|
|
|
// Header
|
|
ps1mdl_header_t outHeader;
|
|
outHeader.ident = inHeader->ident;
|
|
outHeader.version = inHeader->version;
|
|
toFixedVector(inHeader->scale, outHeader.scale);
|
|
toFixedVector(inHeader->translate, outHeader.translate);
|
|
outHeader.skinWidth = (unsigned short)inHeader->skinwidth;
|
|
outHeader.skinHeight = (unsigned short)inHeader->skinheight;
|
|
outHeader.vertexCount = (unsigned short)inHeader->num_verts;
|
|
outHeader.triangleCount = (unsigned short)inHeader->num_tris;
|
|
outHeader.frameCount = (unsigned short)inHeader->num_frames;
|
|
outHeader.pad = 0;
|
|
fwrite(&outHeader, sizeof(ps1mdl_header_t), 1, fout);
|
|
|
|
// Texture coordinates
|
|
for (int i = 0; i < inHeader->num_verts; ++i)
|
|
{
|
|
ps1mdl_texcoord_t outTexCoord;
|
|
outTexCoord.onSeam = (short)(inTexCoords[i].onseam != 0);
|
|
outTexCoord.u = (short)inTexCoords[i].s;
|
|
outTexCoord.v = (short)inTexCoords[i].t;
|
|
fwrite(&outTexCoord, sizeof(ps1mdl_texcoord_t), 1, fout);
|
|
}
|
|
|
|
// Triangles
|
|
for (int i = 0; i < inHeader->num_tris; ++i)
|
|
{
|
|
ps1mdl_triangle_t outTriangle;
|
|
outTriangle.frontFace = (short)(inTriangles[i].facesfront != 0);
|
|
outTriangle.vertexIndex[0] = (unsigned short)inTriangles[i].vertex[0];
|
|
outTriangle.vertexIndex[1] = (unsigned short)inTriangles[i].vertex[1];
|
|
outTriangle.vertexIndex[2] = (unsigned short)inTriangles[i].vertex[2];
|
|
fwrite(&outTriangle, sizeof(ps1mdl_triangle_t), 1, fout);
|
|
}
|
|
|
|
// Vertices
|
|
for (int frameIdx = 0; frameIdx < inHeader->num_frames; ++frameIdx)
|
|
{
|
|
for (int i = 0; i < inHeader->num_verts; ++i)
|
|
{
|
|
mdl_vertex_t* inVert = &inFrames[frameIdx].frame.verts[i];
|
|
ps1mdl_vertex_t outVertex;
|
|
outVertex.position[0] = inVert->v[0];
|
|
outVertex.position[1] = inVert->v[1];
|
|
outVertex.position[2] = inVert->v[2];
|
|
outVertex.normalIndex = inVert->normalIndex;
|
|
fwrite(&outVertex, sizeof(ps1mdl_vertex_t), 1, fout);
|
|
}
|
|
}
|
|
|
|
fclose(fout);
|
|
return 1;
|
|
}
|
|
|
|
void exportNormals()
|
|
{
|
|
FILE* fout;
|
|
fopen_s(&fout, "ps1anorms.h", "w");
|
|
if (fout == NULL)
|
|
return;
|
|
|
|
for (int i = 0; i < NUMVERTEXNORMALS; ++i)
|
|
{
|
|
int x = (int)(anorms[i][0] * 4096);
|
|
int y = (int)(anorms[i][1] * 4096);
|
|
int z = (int)(anorms[i][2] * 4096);
|
|
|
|
fprintf(fout, "{%d, %d, %d, 0},\n", x, y, z);
|
|
}
|
|
|
|
fclose(fout);
|
|
}
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
FILE* f;
|
|
mdl_header_t header;
|
|
char path[_MAX_PATH];
|
|
|
|
convertPalette(argv[1]);
|
|
exportNormals();
|
|
|
|
fopen_s(&f, argv[2], "rb");
|
|
if (f == NULL)
|
|
return 1;
|
|
|
|
fread(&header, sizeof(mdl_header_t), 1, f);
|
|
|
|
printf("Header model identifier: %d, version: %d\n", header.ident, header.version);
|
|
|
|
// Skins
|
|
printf("Reading %d skins of size: %dx%d\n", header.num_skins, header.skinwidth, header.skinheight);
|
|
|
|
size_t skinSize = header.skinwidth * header.skinheight * sizeof(unsigned char);
|
|
unsigned char* buf = (unsigned char*)malloc(skinSize);
|
|
if (!buf)
|
|
{
|
|
fclose(f);
|
|
return 1;
|
|
}
|
|
|
|
for (int i = 0; i < header.num_skins; ++i)
|
|
{
|
|
int group;
|
|
fread(&group, sizeof(int), 1, f);
|
|
|
|
if (group)
|
|
{
|
|
int numPics;
|
|
fread(&numPics, sizeof(int), 1, f);
|
|
fseek(f, numPics * sizeof(float) + numPics * skinSize, SEEK_CUR);
|
|
}
|
|
else
|
|
{
|
|
fread(buf, sizeof(unsigned char), skinSize, f);
|
|
|
|
FILE* fout;
|
|
sprintf_s(path, _MAX_PATH, "skin_%d_%dx%d.raw", i, header.skinwidth, header.skinheight);
|
|
fopen_s(&fout, path, "wb");
|
|
if (fout == NULL)
|
|
continue;
|
|
|
|
fwrite(buf, sizeof(unsigned char), skinSize, fout);
|
|
fclose(fout);
|
|
}
|
|
}
|
|
|
|
free(buf);
|
|
|
|
printf("Reading geometry data for %d vertices, %d triangles, %d frames\n", header.num_verts, header.num_tris, header.num_frames);
|
|
|
|
// Texcoords & triangles (vertex indices)
|
|
mdl_texcoord_t* texCoords = (mdl_texcoord_t*)malloc(sizeof(mdl_texcoord_t) * header.num_verts);
|
|
mdl_triangle_t* triangles = (mdl_triangle_t*)malloc(sizeof(mdl_triangle_t) * header.num_tris);
|
|
fread(texCoords, sizeof(mdl_texcoord_t), header.num_verts, f);
|
|
fread(triangles, sizeof(mdl_triangle_t), header.num_tris, f);
|
|
|
|
// Frames (vertex data)
|
|
mdl_frame_t* frames = (mdl_frame_t*)malloc(sizeof(mdl_frame_t) * header.num_frames);
|
|
for (int i = 0; i < header.num_frames; ++i)
|
|
{
|
|
frames[i].frame.verts = (mdl_vertex_t*)malloc(sizeof(mdl_vertex_t) * header.num_verts);
|
|
|
|
fread(&frames[i].type, sizeof(int), 1, f);
|
|
fread(&frames[i].frame.bboxmin, sizeof(mdl_vertex_t), 1, f);
|
|
fread(&frames[i].frame.bboxmax, sizeof(mdl_vertex_t), 1, f);
|
|
fread(frames[i].frame.name, sizeof(char), 16, f);
|
|
fread(frames[i].frame.verts, sizeof(mdl_vertex_t), header.num_verts, f);
|
|
}
|
|
|
|
fclose(f);
|
|
|
|
// Write simplified model file for PS1
|
|
if (!convertModel(argv[3], &header, texCoords, triangles, frames))
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|