3ds2pie tool update. Belongs to #1553.
- Added PIE3 support. - Conversion routine has been split into 2 parts, with intermediate PIE structure that can be used for model preview: PIE structure is filled with dump_3ds_to_pie(), PIE structure is dumped to .pie file with dump_pie_file(). - Duplicated points removal routine has been added into dump_3ds_to_pie(). "Borrowed" from simplipie tool. - Implement 'twosided' material handler (instead of old global hack). WARNING! It's completely untested and optional. - Command line interface is broken, most likely. Should be fixed or removed entirely. git-svn-id: https://warzone2100.svn.sourceforge.net/svnroot/warzone2100/trunk@10374 4a71c877-e1ca-e34f-864e-861f7616d084master
parent
c34cad2de3
commit
1e4ac04582
|
@ -1,242 +0,0 @@
|
|||
/*
|
||||
* The 3D Studio File Format Library
|
||||
* Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program 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 Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#include <lib3ds/file.h>
|
||||
#include <lib3ds/mesh.h>
|
||||
#include <lib3ds/vector.h>
|
||||
#include <lib3ds/material.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <stdbool.h>
|
||||
#include <limits.h>
|
||||
#else
|
||||
typedef int bool;
|
||||
#define PATH_MAX 255
|
||||
#define true 1
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
// Based on 3ds2m.c from lib3ds
|
||||
|
||||
// gcc -o 3ds2pie 3ds2pie.c -Wall -g -O0 `pkg-config --cflags --libs lib3ds` -Wshadow
|
||||
|
||||
// Make a string lower case
|
||||
static void resToLower(char *pStr)
|
||||
{
|
||||
while (*pStr != 0)
|
||||
{
|
||||
*pStr = tolower(*pStr);
|
||||
pStr += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void dump_pie_file(Lib3dsFile *f, FILE *o, const char *page, bool swapYZ, bool invertUV, bool reverseWinding, unsigned int baseTexFlags, float scaleFactor)
|
||||
{
|
||||
Lib3dsMesh *m;
|
||||
Lib3dsMaterial *material;
|
||||
int meshIdx, j;
|
||||
|
||||
fprintf(o, "PIE 2\n");
|
||||
fprintf(o, "TYPE 200\n");
|
||||
|
||||
for (j = 0, material = f->materials; material; material = material->next, j++)
|
||||
{
|
||||
Lib3dsTextureMap *texture = &material->texture1_map;
|
||||
|
||||
resToLower(texture->name);
|
||||
if (j > 0)
|
||||
{
|
||||
fprintf(stderr, "Texture %d %s-%s: More than one texture currently not supported!\n", j, page, texture->name);
|
||||
continue;
|
||||
}
|
||||
fprintf(o, "TEXTURE %d %s-%s 256 256\n", j, page, texture->name);
|
||||
}
|
||||
|
||||
for (j = 0, m = f->meshes; m; m = m->next, j++);
|
||||
fprintf(o, "LEVELS %d\n", j);
|
||||
|
||||
for (meshIdx = 0, m = f->meshes; m; m = m->next, meshIdx++)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (meshIdx > 0)
|
||||
{
|
||||
fprintf(stderr, "Mesh %d %s: More than one frame currently not supported!\n", meshIdx, m->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
fprintf(o, "LEVEL %d\n", meshIdx + 1);
|
||||
fprintf(o, "POINTS %d\n", m->points);
|
||||
for (i = 0; i < m->points; i++)
|
||||
{
|
||||
Lib3dsVector pos;
|
||||
|
||||
lib3ds_vector_copy(pos, m->pointL[i].pos);
|
||||
|
||||
if (swapYZ)
|
||||
{
|
||||
fprintf(o, "\t%d %d %d\n", (int)(pos[0] * scaleFactor), (int)(pos[2] * scaleFactor), (int)(pos[1] * scaleFactor));
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(o, "\t%d %d %d\n", (int)(pos[0] * scaleFactor), (int)(pos[1] * scaleFactor), (int)(pos[2] * scaleFactor));
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(o, "POLYGONS %d\n", m->faces);
|
||||
for (i = 0; i < m->faces; ++i)
|
||||
{
|
||||
Lib3dsFace *face = &m->faceL[i];
|
||||
int texel[3][2];
|
||||
|
||||
if (!invertUV)
|
||||
{
|
||||
texel[0][0] = m->texelL[face->points[0]][0] * 256.0f;
|
||||
texel[0][1] = m->texelL[face->points[0]][1] * 256.0f;
|
||||
texel[1][0] = m->texelL[face->points[1]][0] * 256.0f;
|
||||
texel[1][1] = m->texelL[face->points[1]][1] * 256.0f;
|
||||
texel[2][0] = m->texelL[face->points[2]][0] * 256.0f;
|
||||
texel[2][1] = m->texelL[face->points[2]][1] * 256.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
texel[0][0] = m->texelL[face->points[0]][0] * 256.0f;
|
||||
texel[0][1] = (1.0f - m->texelL[face->points[0]][1]) * 256.0f;
|
||||
texel[1][0] = m->texelL[face->points[1]][0] * 256.0f;
|
||||
texel[1][1] = (1.0f - m->texelL[face->points[1]][1]) * 256.0f;
|
||||
texel[2][0] = m->texelL[face->points[2]][0] * 256.0f;
|
||||
texel[2][1] = (1.0f - m->texelL[face->points[2]][1]) * 256.0f;
|
||||
}
|
||||
|
||||
if (reverseWinding)
|
||||
{
|
||||
fprintf(o, "\t%d 3 %d %d %d", baseTexFlags, (int)face->points[2], (int)face->points[1], (int)face->points[0]);
|
||||
fprintf(o, " %d %d %d %d %d %d\n", texel[2][0], texel[2][1], texel[1][0], texel[1][1], texel[0][0], texel[0][1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(o, "\t%d 3 %d %d %d", baseTexFlags, (int)face->points[0], (int)face->points[1], (int)face->points[2]);
|
||||
fprintf(o, " %d %d %d %d %d %d\n", texel[0][0], texel[0][1], texel[1][0], texel[1][1], texel[2][0], texel[2][1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if !defined(WZ_3DS2PIE_GUI)
|
||||
static char *input_file = "";
|
||||
static char *output_file = "";
|
||||
static char *page = "";
|
||||
static bool swapYZ = true;
|
||||
static bool reverseWinding = true;
|
||||
static bool invertUV = true;
|
||||
static unsigned int baseTexFlags = 200;
|
||||
static float scaleFactor = 1.0f;
|
||||
|
||||
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: 3ds2m [-s] [-y] [-r] [-i] [-t] input_filename output_filename page_number\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++];
|
||||
page = argv[i++];
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Lib3dsFile *f = NULL;
|
||||
FILE *o = NULL;
|
||||
|
||||
parse_args(argc, argv);
|
||||
f = lib3ds_file_load(input_file);
|
||||
if (!f)
|
||||
{
|
||||
fprintf(stderr, "***ERROR***\nLoading file %s failed\n", input_file);
|
||||
exit(1);
|
||||
}
|
||||
o = fopen(output_file, "w+");
|
||||
if (!o)
|
||||
{
|
||||
fprintf(stderr, "***ERROR***\nCan't open %s for writing\n", output_file);
|
||||
exit(1);
|
||||
}
|
||||
dump_pie_file(f, o, page, swapYZ, invertUV, reverseWinding, baseTexFlags, scaleFactor);
|
||||
fclose(o);
|
||||
|
||||
lib3ds_file_free(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,428 @@
|
|||
/*
|
||||
* The 3D Studio File Format Library
|
||||
* Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program 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 Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "3ds2pie.h"
|
||||
|
||||
#include <lib3ds/mesh.h>
|
||||
#include <lib3ds/vector.h>
|
||||
#include <lib3ds/material.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <stdbool.h>
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
struct WZ_FACE_PROXY {
|
||||
unsigned int index[POLYGON_SIZE_3DS];
|
||||
float texCoord[POLYGON_SIZE_3DS][2];
|
||||
bool cull;
|
||||
};
|
||||
|
||||
struct WZ_POSITION_PROXY {
|
||||
float x, y, z;
|
||||
unsigned int reindex;
|
||||
bool dupe;
|
||||
};
|
||||
|
||||
// Make a string lower case
|
||||
static void resToLower(char *pStr)
|
||||
{
|
||||
while (*pStr != 0)
|
||||
{
|
||||
*pStr = tolower(*pStr);
|
||||
pStr += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void dump_3ds_to_pie(Lib3dsFile *f, WZ_PIE_LEVEL *pie, PIE_OPTIONS options)
|
||||
{
|
||||
Lib3dsMesh *m;
|
||||
Lib3dsMaterial *material;
|
||||
unsigned int meshIdx, i, j;
|
||||
|
||||
/* Materials */
|
||||
|
||||
for (j = 0, material = f->materials; material; material = material->next, ++j)
|
||||
{
|
||||
Lib3dsTextureMap *texture = &material->texture1_map;
|
||||
|
||||
if (j > 0)
|
||||
{
|
||||
fprintf(stderr, "Texture %d %s-%s: More than one texture currently not supported!\n", j, options.page, texture->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
resToLower(texture->name);
|
||||
pie->texName = strdup(texture->name);
|
||||
}
|
||||
|
||||
/* Vertexes and polygons from meshes */
|
||||
|
||||
for (meshIdx = 0, m = f->meshes; m; m = m->next, ++meshIdx)
|
||||
{
|
||||
unsigned int facesCount;
|
||||
WZ_FACE_PROXY *faceList;
|
||||
WZ_POSITION_PROXY *posList;
|
||||
|
||||
if (meshIdx > 0)
|
||||
{
|
||||
fprintf(stderr, "Mesh %d %s: More than one frame currently not supported!\n", meshIdx, m->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Vertexes */
|
||||
|
||||
posList = (WZ_POSITION_PROXY *) malloc(sizeof(WZ_POSITION_PROXY) * m->points);
|
||||
|
||||
for (j = 0; j < m->points; ++j)
|
||||
{
|
||||
posList[j].dupe = false;
|
||||
|
||||
if (options.swapYZ)
|
||||
{
|
||||
posList[j].x = m->pointL[j].pos[0];
|
||||
posList[j].y = m->pointL[j].pos[2];
|
||||
posList[j].z = m->pointL[j].pos[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
posList[j].x = m->pointL[j].pos[0];
|
||||
posList[j].y = m->pointL[j].pos[1];
|
||||
posList[j].z = m->pointL[j].pos[2];
|
||||
}
|
||||
}
|
||||
|
||||
// Remove duplicate points
|
||||
for (i = 0, j = 0; j < m->points; ++j)
|
||||
{
|
||||
unsigned int k;
|
||||
|
||||
for (k = j + 1; k < m->points; ++k)
|
||||
{
|
||||
// if points in k are equal to points in j, replace all k with j in face list
|
||||
if (!posList[k].dupe &&
|
||||
posList[k].x == posList[j].x &&
|
||||
posList[k].y == posList[j].y &&
|
||||
posList[k].z == posList[j].z)
|
||||
{
|
||||
posList[k].dupe = true; // oh noes, a dupe! let's skip it when we write them out again.
|
||||
posList[k].reindex = i; // rewrite face list to point here
|
||||
}
|
||||
}
|
||||
if (!posList[j].dupe)
|
||||
{
|
||||
posList[j].reindex = i;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
pie->posL = (WZ_POSITION *) malloc(sizeof(WZ_POSITION) * i);
|
||||
pie->numVertexes = i;
|
||||
|
||||
for (j = 0; j < m->points; ++j)
|
||||
{
|
||||
if (!posList[j].dupe)
|
||||
{
|
||||
pie->posL[posList[j].reindex].x = posList[j].x;
|
||||
pie->posL[posList[j].reindex].y = posList[j].y;
|
||||
pie->posL[posList[j].reindex].z = posList[j].z;
|
||||
}
|
||||
}
|
||||
|
||||
/* Polygons */
|
||||
|
||||
faceList = (WZ_FACE_PROXY *) malloc(sizeof(WZ_FACE_PROXY) * m->faces);
|
||||
|
||||
// i controls reverseWinding dynamically in form of (i,1,2-i), do notice 1!
|
||||
i = 2 * (int)options.reverseWinding;
|
||||
for (j = 0; j < m->faces; ++j)
|
||||
{
|
||||
Lib3dsFace *face = &m->faceL[j];
|
||||
|
||||
if (!options.invertUV)
|
||||
{
|
||||
faceList[j].texCoord[i][0] = m->texelL[face->points[0]][0];
|
||||
faceList[j].texCoord[i][1] = m->texelL[face->points[0]][1];
|
||||
faceList[j].texCoord[1][0] = m->texelL[face->points[1]][0];
|
||||
faceList[j].texCoord[1][1] = m->texelL[face->points[1]][1];
|
||||
faceList[j].texCoord[2-i][0] = m->texelL[face->points[2]][0];
|
||||
faceList[j].texCoord[2-i][1] = m->texelL[face->points[2]][1];
|
||||
}
|
||||
else
|
||||
{
|
||||
faceList[j].texCoord[i][0] = m->texelL[face->points[0]][0];
|
||||
faceList[j].texCoord[i][1] = 1.0f - m->texelL[face->points[0]][1];
|
||||
faceList[j].texCoord[1][0] = m->texelL[face->points[1]][0];
|
||||
faceList[j].texCoord[1][1] = 1.0f - m->texelL[face->points[1]][1];
|
||||
faceList[j].texCoord[2-i][0] = m->texelL[face->points[2]][0];
|
||||
faceList[j].texCoord[2-i][1] = 1.0f - m->texelL[face->points[2]][1];
|
||||
}
|
||||
|
||||
faceList[j].index[i] = face->points[0];
|
||||
faceList[j].index[1] = face->points[1];
|
||||
faceList[j].index[2-i] = face->points[2];
|
||||
|
||||
if (face->material[0]) {
|
||||
material=lib3ds_file_material_by_name(f, face->material);
|
||||
faceList[j].cull = !material->two_sided;
|
||||
}
|
||||
else {
|
||||
faceList[j].cull = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Rewrite face table with reindexed vertexes
|
||||
facesCount = m->faces;
|
||||
for (j = 0; j < m->faces; ++j)
|
||||
{
|
||||
faceList[j].index[0] = posList[faceList[j].index[0]].reindex;
|
||||
faceList[j].index[1] = posList[faceList[j].index[1]].reindex;
|
||||
faceList[j].index[2] = posList[faceList[j].index[2]].reindex;
|
||||
|
||||
if (options.twoSidedPolys && !faceList[j].cull)
|
||||
++facesCount;
|
||||
}
|
||||
|
||||
// Free vertex proxy
|
||||
if (posList)
|
||||
free(posList);
|
||||
|
||||
pie->faceL = (WZ_FACE *) malloc(sizeof(WZ_FACE) * facesCount);
|
||||
pie->numFaces = facesCount;
|
||||
|
||||
for (i = 0, j = 0; j < m->faces; ++i, ++j)
|
||||
{
|
||||
pie->faceL[i].index[0] = faceList[j].index[0];
|
||||
pie->faceL[i].index[1] = faceList[j].index[1];
|
||||
pie->faceL[i].index[2] = faceList[j].index[2];
|
||||
|
||||
pie->faceL[i].texCoord[0][0] = faceList[j].texCoord[0][0];
|
||||
pie->faceL[i].texCoord[0][1] = faceList[j].texCoord[0][1];
|
||||
pie->faceL[i].texCoord[1][0] = faceList[j].texCoord[1][0];
|
||||
pie->faceL[i].texCoord[1][1] = faceList[j].texCoord[1][1];
|
||||
pie->faceL[i].texCoord[2][0] = faceList[j].texCoord[2][0];
|
||||
pie->faceL[i].texCoord[2][1] = faceList[j].texCoord[2][1];
|
||||
|
||||
if (!faceList[j].cull)
|
||||
{
|
||||
++i;
|
||||
pie->faceL[i].index[0] = faceList[j].index[2];
|
||||
pie->faceL[i].index[1] = faceList[j].index[1];
|
||||
pie->faceL[i].index[2] = faceList[j].index[0];
|
||||
|
||||
pie->faceL[i].texCoord[0][0] = faceList[j].texCoord[2][0];
|
||||
pie->faceL[i].texCoord[0][1] = faceList[j].texCoord[2][1];
|
||||
pie->faceL[i].texCoord[1][0] = faceList[j].texCoord[1][0];
|
||||
pie->faceL[i].texCoord[1][1] = faceList[j].texCoord[1][1];
|
||||
pie->faceL[i].texCoord[2][0] = faceList[j].texCoord[0][0];
|
||||
pie->faceL[i].texCoord[2][1] = faceList[j].texCoord[0][1];
|
||||
}
|
||||
}
|
||||
|
||||
// Free face proxy
|
||||
if (faceList)
|
||||
free(faceList);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void dump_pie_file(WZ_PIE_LEVEL *pie, FILE *o, PIE_OPTIONS options)
|
||||
{
|
||||
unsigned int i, pietype = 0, levelIdx;
|
||||
|
||||
if (options.exportPIE3)
|
||||
{
|
||||
fprintf(o, "PIE 3\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(o, "PIE 2\n");
|
||||
pietype |= 0x200;
|
||||
}
|
||||
|
||||
if (options.useTCMask)
|
||||
{
|
||||
pietype |= 0x10000;
|
||||
}
|
||||
|
||||
fprintf(o, "TYPE %x\n", pietype);
|
||||
|
||||
if (options.exportPIE3)
|
||||
{
|
||||
fprintf(o, "TEXTURE 0 %s-%s 0 0\n", options.page, pie->texName);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(o, "TEXTURE 0 %s-%s 256 256\n", options.page, pie->texName);
|
||||
}
|
||||
|
||||
fprintf(o, "LEVELS %d\n", 1); // Should be pie.levels
|
||||
|
||||
for (levelIdx = 0; levelIdx < 1; ++levelIdx)
|
||||
{
|
||||
fprintf(o, "LEVEL %d\n", levelIdx + 1);
|
||||
fprintf(o, "POINTS %d\n", pie->numVertexes);
|
||||
|
||||
for (i = 0; i < pie->numVertexes; ++i)
|
||||
{
|
||||
if (options.exportPIE3)
|
||||
{
|
||||
fprintf(o, "\t%f %f %f\n",
|
||||
pie->posL[i].x * options.scaleFactor,
|
||||
pie->posL[i].y * options.scaleFactor,
|
||||
pie->posL[i].z * options.scaleFactor);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(o, "\t%d %d %d\n",
|
||||
(int)(pie->posL[i].x * options.scaleFactor),
|
||||
(int)(pie->posL[i].y * options.scaleFactor),
|
||||
(int)(pie->posL[i].z * options.scaleFactor));
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(o, "POLYGONS %d\n", pie->numFaces);
|
||||
|
||||
for (i = 0; i < pie->numFaces; ++i)
|
||||
{
|
||||
fprintf(o, "\t%X 3 %u %u %u", 0x200,
|
||||
pie->faceL[i].index[0], pie->faceL[i].index[1], pie->faceL[i].index[2]);
|
||||
if (options.exportPIE3)
|
||||
{
|
||||
fprintf(o, " %f %f %f %f %f %f\n",
|
||||
pie->faceL[i].texCoord[0][0], pie->faceL[i].texCoord[0][1],
|
||||
pie->faceL[i].texCoord[1][0], pie->faceL[i].texCoord[1][1],
|
||||
pie->faceL[i].texCoord[2][0], pie->faceL[i].texCoord[2][1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(o, " %d %d %d %d %d %d\n",
|
||||
(int)(pie->faceL[i].texCoord[0][0] * 256),
|
||||
(int)(pie->faceL[i].texCoord[0][1] * 256),
|
||||
(int)(pie->faceL[i].texCoord[1][0] * 256),
|
||||
(int)(pie->faceL[i].texCoord[1][1] * 256),
|
||||
(int)(pie->faceL[i].texCoord[2][0] * 256),
|
||||
(int)(pie->faceL[i].texCoord[2][1] * 256));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME!!! Most likely it's broken...
|
||||
#if !defined(WZ_3DS2PIE_GUI)
|
||||
static char *input_file = "";
|
||||
static char *output_file = "";
|
||||
static char *page = "";
|
||||
static bool swapYZ = true;
|
||||
static bool reverseWinding = true;
|
||||
static bool invertUV = true;
|
||||
static unsigned int baseTexFlags = 200;
|
||||
static float scaleFactor = 1.0f;
|
||||
|
||||
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: 3ds2m [-s] [-y] [-r] [-i] [-t] input_filename output_filename page_number\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++];
|
||||
page = argv[i++];
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Lib3dsFile *f = NULL;
|
||||
FILE *o = NULL;
|
||||
|
||||
parse_args(argc, argv);
|
||||
f = lib3ds_file_load(input_file);
|
||||
if (!f)
|
||||
{
|
||||
fprintf(stderr, "***ERROR***\nLoading file %s failed\n", input_file);
|
||||
exit(1);
|
||||
}
|
||||
o = fopen(output_file, "w+");
|
||||
if (!o)
|
||||
{
|
||||
fprintf(stderr, "***ERROR***\nCan't open %s for writing\n", output_file);
|
||||
exit(1);
|
||||
}
|
||||
dump_pie_file(f, o, page, swapYZ, invertUV, reverseWinding, baseTexFlags, scaleFactor);
|
||||
fclose(o);
|
||||
|
||||
lib3ds_file_free(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
Copyright (C) Warzone 2100 Project
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program 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 Lesser General Public
|
||||
License along with this program. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef __3DS2PIE_H
|
||||
#define __3DS2PIE_H
|
||||
|
||||
#define POLYGON_SIZE_3DS 3 // Should be triangles
|
||||
|
||||
struct WZ_FACE {
|
||||
unsigned int index[POLYGON_SIZE_3DS];
|
||||
float texCoord[POLYGON_SIZE_3DS][2];
|
||||
};
|
||||
|
||||
struct WZ_POSITION {
|
||||
float x, y, z;
|
||||
};
|
||||
|
||||
struct WZ_PIE_LEVEL {
|
||||
unsigned int numFaces;
|
||||
WZ_FACE * faceL;
|
||||
unsigned int numVertexes;
|
||||
WZ_POSITION *posL;
|
||||
char *texName;
|
||||
};
|
||||
|
||||
//TODO: There should be a WZ_PIE structure with a number of levels and a level list
|
||||
|
||||
struct PIE_OPTIONS {
|
||||
char *page;
|
||||
bool swapYZ;
|
||||
bool invertUV;
|
||||
bool reverseWinding;
|
||||
bool twoSidedPolys;
|
||||
float scaleFactor;
|
||||
bool exportPIE3;
|
||||
bool useTCMask;
|
||||
};
|
||||
|
||||
#include <lib3ds/file.h>
|
||||
|
||||
void dump_3ds_to_pie(Lib3dsFile *f, WZ_PIE_LEVEL *pie, PIE_OPTIONS options);
|
||||
void dump_pie_file(WZ_PIE_LEVEL *pie, FILE *o, PIE_OPTIONS options);
|
||||
|
||||
#endif
|
|
@ -16,6 +16,7 @@
|
|||
<http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "3ds2pie_gui.h"
|
||||
#include "3ds2pie.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
|
@ -26,9 +27,6 @@
|
|||
#include <lib3ds/file.h>
|
||||
|
||||
|
||||
extern "C" void dump_pie_file(Lib3dsFile *f, FILE *o, const char *page, bool swapYZ, bool inverseUV, bool reverseWinding, int baseTexFlags, float scaleFactor);
|
||||
|
||||
|
||||
Gui3ds2pie::Gui3ds2pie( QWidget *parent )
|
||||
: QDialog(parent), Ui::Gui3ds2pie()
|
||||
{
|
||||
|
@ -62,14 +60,14 @@ void Gui3ds2pie::spinboxChanged(double value)
|
|||
|
||||
void Gui3ds2pie::browseInputFile()
|
||||
{
|
||||
QString path = QFileDialog::getOpenFileName(this, tr("Choose input file"), QString::null, QString::null);
|
||||
QString path = QFileDialog::getOpenFileName(this, tr("Choose input file"), QString::null, "*.3ds");
|
||||
inputFile_edit->setText(path);
|
||||
}
|
||||
|
||||
|
||||
void Gui3ds2pie::browseOutputFile()
|
||||
{
|
||||
QString path = QFileDialog::getSaveFileName(this, tr("Choose output file"), QString::null, QString::null);
|
||||
QString path = QFileDialog::getSaveFileName(this, tr("Choose output file"), QString::null, "*.pie");
|
||||
outputFile_edit->setText(path);
|
||||
}
|
||||
|
||||
|
@ -104,7 +102,6 @@ void Gui3ds2pie::accept()
|
|||
QString inputFile = inputFile_edit->text();
|
||||
QString outputFile = outputFile_edit->text();
|
||||
QString texturePage = texturePage_edit->text();
|
||||
unsigned int baseTexFlags = (twoSidedPolys->isChecked() ? 2200 : 200 );
|
||||
|
||||
if (inputFile.isEmpty())
|
||||
{
|
||||
|
@ -135,11 +132,27 @@ void Gui3ds2pie::accept()
|
|||
return;
|
||||
}
|
||||
|
||||
dump_pie_file(f, o, texturePage.toAscii().data(), swapYZ->isChecked(), invertUV->isChecked(), reverseWinding->isChecked(), baseTexFlags, scale_spinbox->value());
|
||||
PIE_OPTIONS options;
|
||||
options.twoSidedPolys = twoSidedPolys->isChecked();
|
||||
options.exportPIE3 = exportPIE3->isChecked();
|
||||
options.invertUV = invertUV->isChecked();
|
||||
options.page = strdup(texturePage.toAscii().data());
|
||||
options.reverseWinding = reverseWinding->isChecked();
|
||||
options.scaleFactor = scale_spinbox->value();
|
||||
options.swapYZ = swapYZ->isChecked();
|
||||
options.useTCMask = useTCMask->isChecked();
|
||||
|
||||
WZ_PIE_LEVEL pie;
|
||||
|
||||
dump_3ds_to_pie(f, &pie, options);
|
||||
dump_pie_file(&pie, o, options);
|
||||
|
||||
fclose(o);
|
||||
lib3ds_file_free(f);
|
||||
|
||||
if (options.page)
|
||||
free(options.page);
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
FORMS += 3ds2pie_gui.ui
|
||||
SOURCES += 3ds2pie_gui.cpp \
|
||||
3ds2pie.c \
|
||||
3ds2pie.cpp \
|
||||
main.cpp
|
||||
HEADERS += 3ds2pie_gui.h
|
||||
HEADERS += 3ds2pie_gui.h \
|
||||
3ds2pie.h
|
||||
TEMPLATE = app
|
||||
CONFIG += warn_on \
|
||||
qt \
|
||||
|
|
|
@ -1,184 +1,211 @@
|
|||
<ui version="4.0" >
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Gui3ds2pie</class>
|
||||
<widget class="QDialog" name="Gui3ds2pie" >
|
||||
<property name="geometry" >
|
||||
<widget class="QDialog" name="Gui3ds2pie">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>237</height>
|
||||
<height>256</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<property name="windowTitle">
|
||||
<string>3ds2pie</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" >
|
||||
<item row="0" column="0" >
|
||||
<layout class="QGridLayout" >
|
||||
<item row="0" column="1" >
|
||||
<widget class="QLineEdit" name="inputFile_edit" >
|
||||
<property name="toolTip" >
|
||||
<layout class="QGridLayout">
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout">
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="inputFile_edit">
|
||||
<property name="toolTip">
|
||||
<string>Path to the 3DS file</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="QLineEdit" name="outputFile_edit" >
|
||||
<property name="toolTip" >
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="outputFile_edit">
|
||||
<property name="toolTip">
|
||||
<string>Path to the PIE file</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" >
|
||||
<widget class="QSpinBox" name="texturePage_edit" >
|
||||
<property name="toolTip" >
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="texturePage_edit">
|
||||
<property name="toolTip">
|
||||
<string>Texture page to use</string>
|
||||
</property>
|
||||
<property name="prefix" >
|
||||
<property name="prefix">
|
||||
<string>page-</string>
|
||||
</property>
|
||||
<property name="minimum" >
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" >
|
||||
<widget class="QSlider" name="scale_slider" >
|
||||
<property name="toolTip" >
|
||||
<item row="3" column="1">
|
||||
<widget class="QSlider" name="scale_slider">
|
||||
<property name="toolTip">
|
||||
<string>Scale for model</string>
|
||||
</property>
|
||||
<property name="maximum" >
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
</property>
|
||||
<property name="value" >
|
||||
<property name="value">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="orientation" >
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" >
|
||||
<widget class="QPushButton" name="inputFile_browse" >
|
||||
<property name="text" >
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="inputFile_browse">
|
||||
<property name="text">
|
||||
<string>Browse</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" >
|
||||
<widget class="QPushButton" name="outputFile_browse" >
|
||||
<property name="text" >
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="outputFile_browse">
|
||||
<property name="text">
|
||||
<string>Browse</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2" >
|
||||
<widget class="QDoubleSpinBox" name="scale_spinbox" >
|
||||
<property name="toolTip" >
|
||||
<item row="3" column="2">
|
||||
<widget class="QDoubleSpinBox" name="scale_spinbox">
|
||||
<property name="toolTip">
|
||||
<string>Scale for model</string>
|
||||
</property>
|
||||
<property name="maximum" >
|
||||
<property name="maximum">
|
||||
<double>99.989999999999995</double>
|
||||
</property>
|
||||
<property name="value" >
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" >
|
||||
<widget class="QLabel" name="inputFile" >
|
||||
<property name="text" >
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="inputFile">
|
||||
<property name="text">
|
||||
<string>Input file</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<widget class="QLabel" name="outputFile" >
|
||||
<property name="text" >
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="outputFile">
|
||||
<property name="text">
|
||||
<string>Output file</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" >
|
||||
<widget class="QLabel" name="texturePage" >
|
||||
<property name="text" >
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="texturePage">
|
||||
<property name="text">
|
||||
<string>Texture page</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" >
|
||||
<widget class="QLabel" name="scale" >
|
||||
<property name="text" >
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="scale">
|
||||
<property name="text">
|
||||
<string>Scale</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<layout class="QGridLayout" >
|
||||
<item row="0" column="0" >
|
||||
<widget class="QCheckBox" name="swapYZ" >
|
||||
<property name="toolTip" >
|
||||
<string>Assume that 'Z' denotes "up" direction
|
||||
<item row="1" column="0">
|
||||
<layout class="QGridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="swapYZ">
|
||||
<property name="toolTip">
|
||||
<string>Assume that 'Z' denotes "up" direction
|
||||
(Should be enabled for 3DS Max created files)</string>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<property name="text">
|
||||
<string>Swap Y/Z</string>
|
||||
</property>
|
||||
<property name="checked" >
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<widget class="QCheckBox" name="reverseWinding" >
|
||||
<property name="toolTip" >
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="reverseWinding">
|
||||
<property name="toolTip">
|
||||
<string>Reverse the winding of all polygon faces
|
||||
(Should be enabled for 3DS Max created files)</string>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<property name="text">
|
||||
<string>Reverse polygon winding</string>
|
||||
</property>
|
||||
<property name="checked" >
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<widget class="QCheckBox" name="invertUV" >
|
||||
<property name="toolTip" >
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="invertUV">
|
||||
<property name="toolTip">
|
||||
<string>Invert the vertical point of origin for UV coordinates
|
||||
(Should be enabled for 3DS Max created files)</string>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<property name="text">
|
||||
<string>Invert U/V</string>
|
||||
</property>
|
||||
<property name="checked" >
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="QCheckBox" name="twoSidedPolys" >
|
||||
<property name="toolTip" >
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="twoSidedPolys">
|
||||
<property name="toolTip">
|
||||
<string>Use both sides of Polygons
|
||||
(Not used in Warzone 2100)</string>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<property name="text">
|
||||
<string>Two sided polygons</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="exportPIE3">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Enable floating points in PIE format.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Export PIE3</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="useTCMask">
|
||||
<property name="toolTip">
|
||||
<string>Use TCMask feature instead of old team coloring frames.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enable TCMask texture</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0" >
|
||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||
<property name="orientation" >
|
||||
<item row="2" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons" >
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -192,11 +219,11 @@
|
|||
<receiver>Gui3ds2pie</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<hint type="sourcelabel">
|
||||
<x>199</x>
|
||||
<y>214</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<hint type="destinationlabel">
|
||||
<x>199</x>
|
||||
<y>119</y>
|
||||
</hint>
|
||||
|
@ -208,11 +235,11 @@
|
|||
<receiver>Gui3ds2pie</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<hint type="sourcelabel">
|
||||
<x>199</x>
|
||||
<y>214</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<hint type="destinationlabel">
|
||||
<x>199</x>
|
||||
<y>119</y>
|
||||
</hint>
|
||||
|
|
Loading…
Reference in New Issue