332 lines
7.7 KiB
C
332 lines
7.7 KiB
C
/*
|
|
This file is part of Warzone 2100.
|
|
Copyright (C) 2007-2008 Warzone Resurrection Project
|
|
|
|
Warzone 2100 is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Warzone 2100 is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Warzone 2100; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#ifndef WIN32
|
|
#include <stdbool.h>
|
|
#include <limits.h>
|
|
#else
|
|
typedef int bool;
|
|
#define PATH_MAX 255
|
|
#define true 1
|
|
#define false 0
|
|
#endif
|
|
|
|
static char *input_file = "";
|
|
static char *output_file = "";
|
|
static char *texture_file;
|
|
static bool swapYZ = true;
|
|
static bool reverseWinding = true;
|
|
static bool invertUV = true;
|
|
static unsigned int baseTexFlags = 200;
|
|
static float scaleFactor = 1.0f;
|
|
|
|
typedef struct _vector3i
|
|
{
|
|
int x, y, z;
|
|
} vector3i;
|
|
|
|
typedef struct _vector2i
|
|
{
|
|
int u, v;
|
|
} vector2i;
|
|
|
|
typedef struct _face
|
|
{
|
|
int index_a_vertex, index_a_texture;
|
|
int index_b_vertex, index_b_texture;
|
|
int index_c_vertex, index_c_texture;
|
|
} face;
|
|
|
|
static vector3i *points;
|
|
static int count_points;
|
|
|
|
static vector2i *uvcoords;
|
|
static int count_uvcoords;
|
|
|
|
static face *faces;
|
|
static int count_faces;
|
|
|
|
void addpoint(int x, int y, int z)
|
|
{
|
|
if (points == NULL)
|
|
{
|
|
points = (vector3i*) malloc(sizeof(vector3i));
|
|
count_points = 1;
|
|
}
|
|
else
|
|
{
|
|
count_points++;
|
|
points = (vector3i*)realloc(points, count_points * sizeof(vector3i));
|
|
}
|
|
|
|
points[count_points-1].x = x;
|
|
points[count_points-1].y = y;
|
|
points[count_points-1].z = z;
|
|
}
|
|
|
|
void adduvcoord(int u, int v)
|
|
{
|
|
if (uvcoords == NULL)
|
|
{
|
|
uvcoords = (vector2i*) malloc(sizeof(vector2i));
|
|
count_uvcoords = 1;
|
|
}
|
|
else
|
|
{
|
|
count_uvcoords++;
|
|
uvcoords = (vector2i*)realloc(uvcoords, count_uvcoords * sizeof(vector2i));
|
|
}
|
|
|
|
if (u > 255)
|
|
{
|
|
u = 255;
|
|
}
|
|
if (v > 255)
|
|
{
|
|
v = 255;
|
|
}
|
|
uvcoords[count_uvcoords-1].u = u;
|
|
uvcoords[count_uvcoords-1].v = v;
|
|
}
|
|
|
|
void addface(int index_a_vertex, int index_a_texture, int index_b_vertex, int index_b_texture, int index_c_vertex, int index_c_texture)
|
|
{
|
|
if (faces == NULL)
|
|
{
|
|
faces = (face*) malloc(sizeof(face));
|
|
count_faces = 1;
|
|
}
|
|
else
|
|
{
|
|
count_faces++;
|
|
faces = (face*) realloc(faces, count_faces * sizeof(face));
|
|
}
|
|
|
|
faces[count_faces-1].index_a_vertex = index_a_vertex;
|
|
faces[count_faces-1].index_a_texture = index_a_texture;
|
|
faces[count_faces-1].index_b_vertex = index_b_vertex;
|
|
faces[count_faces-1].index_b_texture = index_b_texture;
|
|
faces[count_faces-1].index_c_vertex = index_c_vertex;
|
|
faces[count_faces-1].index_c_texture = index_c_texture;
|
|
}
|
|
|
|
void readobj(FILE *input)
|
|
{
|
|
char buffer[256];
|
|
int index_a_vertex, index_a_texture, index_b_vertex, index_b_texture, index_c_vertex, index_c_texture;
|
|
float u, v;
|
|
float x, y, z;
|
|
|
|
if (input == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
points = NULL;
|
|
count_points = 0;
|
|
|
|
uvcoords = NULL;
|
|
count_uvcoords = 0;
|
|
|
|
faces = NULL;
|
|
count_faces = 0;
|
|
|
|
while (!feof(input))
|
|
{
|
|
fgets(buffer, 256, input);
|
|
|
|
if (buffer[0] == 'v' && buffer[1] != 't')
|
|
{
|
|
sscanf(&buffer[2], "%f %f %f", &x, &y, &z);
|
|
addpoint((int)(x*scaleFactor), (int)(y*scaleFactor), (int)(z*scaleFactor));
|
|
}
|
|
else if (buffer[0] == 'v' && buffer[1] == 't')
|
|
{
|
|
sscanf(&buffer[3], "%f %f", &u, &v);
|
|
if (invertUV)
|
|
v = 1.0f - v;
|
|
adduvcoord((int)(u*256.f), (int)(v*256.f));
|
|
}
|
|
else if (buffer[0] == 'f')
|
|
{
|
|
sscanf(&buffer[2], "%d/%d %d/%d %d/%d", &index_a_vertex, &index_a_texture, &index_b_vertex, &index_b_texture, &index_c_vertex, &index_c_texture);
|
|
addface(index_a_vertex - 1, index_a_texture - 1, index_b_vertex - 1, index_b_texture - 1, index_c_vertex - 1, index_c_texture - 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void writepie(FILE *output)
|
|
{
|
|
size_t i;
|
|
|
|
if (output == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
fprintf(output, "PIE 2\nTYPE 200\n");
|
|
fprintf(output, "TEXTURE 0 %s 256 256\n", texture_file);
|
|
fprintf(output, "LEVELS 1\nLEVEL 1\n");
|
|
|
|
fprintf(output, "POINTS %d\n", count_points);
|
|
for (i = 0;i < count_points;i++)
|
|
{
|
|
if (swapYZ)
|
|
{
|
|
fprintf(output, "\t%d %d %d\n", points[i].x, points[i].z, points[i].y);
|
|
}
|
|
else
|
|
{
|
|
fprintf(output, "\t%d %d %d\n", points[i].x, points[i].y, points[i].z);
|
|
}
|
|
}
|
|
|
|
fprintf(output, "POLYGONS %d\n", count_faces);
|
|
for (i = 0;i < count_faces;i++)
|
|
{
|
|
if (reverseWinding)
|
|
{
|
|
fprintf(output, "\t%d 3 %d %d %d %d %d %d %d %d %d\n",
|
|
baseTexFlags,
|
|
faces[i].index_c_vertex,
|
|
faces[i].index_b_vertex,
|
|
faces[i].index_a_vertex,
|
|
uvcoords[faces[i].index_c_texture].u,
|
|
uvcoords[faces[i].index_c_texture].v,
|
|
uvcoords[faces[i].index_b_texture].u,
|
|
uvcoords[faces[i].index_b_texture].v,
|
|
uvcoords[faces[i].index_a_texture].u,
|
|
uvcoords[faces[i].index_a_texture].v);
|
|
}
|
|
else
|
|
{
|
|
fprintf(output, "\t%d 3 %d %d %d %d %d %d %d %d %d\n",
|
|
baseTexFlags,
|
|
faces[i].index_a_vertex,
|
|
faces[i].index_b_vertex,
|
|
faces[i].index_c_vertex,
|
|
uvcoords[faces[i].index_a_texture].u,
|
|
uvcoords[faces[i].index_a_texture].v,
|
|
uvcoords[faces[i].index_b_texture].u,
|
|
uvcoords[faces[i].index_b_texture].v,
|
|
uvcoords[faces[i].index_c_texture].u,
|
|
uvcoords[faces[i].index_c_texture].v);
|
|
}
|
|
}
|
|
}
|
|
|
|
void objtopie()
|
|
{
|
|
FILE *input = NULL;
|
|
FILE *output = NULL;
|
|
|
|
input = fopen(input_file, "rt");
|
|
if (input == NULL)
|
|
{
|
|
perror("Couldn't open input file");
|
|
return;
|
|
}
|
|
|
|
output = fopen(output_file, "wt");
|
|
if (output == NULL)
|
|
{
|
|
perror("Couldn't open output file");
|
|
fclose(input);
|
|
return;
|
|
}
|
|
|
|
readobj(input);
|
|
writepie(output);
|
|
|
|
fclose(input);
|
|
fclose(output);
|
|
}
|
|
|
|
static void parse_args(int argc, char **argv)
|
|
{
|
|
unsigned int i = 1;
|
|
|
|
for (i = 1; argc >= 3 + i && argv[i][0] == '-'; i++)
|
|
{
|
|
if (argv[i][1] == 'y')
|
|
{
|
|
swapYZ = false; // exporting program used Y-axis as "up", like we do, don't switch
|
|
}
|
|
else if (argv[i][1] == 'i')
|
|
{
|
|
invertUV = false;
|
|
}
|
|
else if (argv[i][1] == 't')
|
|
{
|
|
baseTexFlags = 2200;
|
|
}
|
|
else if (argv[i][1] == 'r')
|
|
{
|
|
reverseWinding = false;
|
|
}
|
|
else if (argv[i][1] == 's')
|
|
{
|
|
int ret;
|
|
|
|
i++;
|
|
if (argc < i)
|
|
{
|
|
fprintf(stderr, "Missing parameter to scale option.\n");
|
|
exit(1);
|
|
}
|
|
ret = sscanf(argv[i], "%f", &scaleFactor);
|
|
if (ret != 1)
|
|
{
|
|
fprintf(stderr, "Bad parameter to scale option.\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
|
|
exit(1);
|
|
}
|
|
}
|
|
if (argc < 3 + i)
|
|
{
|
|
fprintf(stderr, "Syntax: obj2pie [-s] [-y] [-r] [-i] [-t] input_filename output_filename texture_filename\n");
|
|
fprintf(stderr, " -y Do not swap Y and Z axis. Exporter uses Y-axis as \"up\".\n");
|
|
fprintf(stderr, " -r Do not reverse winding of all polygons.\n");
|
|
fprintf(stderr, " -i Do not invert the vertical texture coordinates.\n");
|
|
fprintf(stderr, " -s N Scale model points by N before converting.\n");
|
|
fprintf(stderr, " -t Use two sided polygons (slower; deprecated).\n");
|
|
exit(1);
|
|
}
|
|
input_file = argv[i++];
|
|
output_file = argv[i++];
|
|
texture_file = argv[i++];
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
parse_args(argc, argv);
|
|
objtopie();
|
|
return 0;
|
|
}
|