2007-01-15 12:09:25 -08:00
|
|
|
/*
|
|
|
|
This file is part of Warzone 2100.
|
|
|
|
Copyright (C) 1999-2004 Eidos Interactive
|
2010-07-26 16:36:29 -07:00
|
|
|
Copyright (C) 2005-2010 Warzone 2100 Project
|
2007-01-15 12:09:25 -08:00
|
|
|
|
|
|
|
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
|
|
|
|
*/
|
2007-05-21 11:25:46 -07:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* \file imdload.c
|
2007-06-28 10:47:08 -07:00
|
|
|
*
|
2007-05-21 11:25:46 -07:00
|
|
|
* Load IMD (.pie) files
|
2007-06-28 10:47:08 -07:00
|
|
|
*/
|
|
|
|
|
2006-06-02 12:34:58 -07:00
|
|
|
#include "lib/framework/frame.h"
|
2009-02-10 09:23:09 -08:00
|
|
|
#include "lib/framework/string_ext.h"
|
2007-04-28 03:36:21 -07:00
|
|
|
#include "lib/framework/frameresource.h"
|
2009-02-10 09:23:18 -08:00
|
|
|
#include "lib/framework/fixedpoint.h"
|
2007-04-28 03:36:21 -07:00
|
|
|
#include "lib/ivis_opengl/piematrix.h"
|
2007-04-11 07:55:54 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
#include "ivisdef.h" // for imd structures
|
|
|
|
#include "imd.h" // for imd structures
|
|
|
|
#include "tex.h" // texture page loading
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-06-03 06:46:50 -07:00
|
|
|
static BOOL AtEndOfFile(const char *CurPos, const char *EndOfFile)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-05-21 11:25:46 -07:00
|
|
|
while ( *CurPos == 0x00 || *CurPos == 0x09 || *CurPos == 0x0a || *CurPos == 0x0d || *CurPos == 0x20 )
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
CurPos++;
|
2007-05-21 11:25:46 -07:00
|
|
|
if (CurPos >= EndOfFile)
|
|
|
|
{
|
2008-03-24 09:51:17 -07:00
|
|
|
return true;
|
2007-05-21 11:25:46 -07:00
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
if (CurPos >= EndOfFile)
|
|
|
|
{
|
2008-03-24 09:51:17 -07:00
|
|
|
return true;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
2008-03-24 09:51:17 -07:00
|
|
|
return false;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* Load shape level polygons
|
|
|
|
* \param ppFileData Pointer to the data (usualy read from a file)
|
|
|
|
* \param s Pointer to shape level
|
2008-03-24 09:51:17 -07:00
|
|
|
* \return false on error (memory allocation failure/bad file format), true otherwise
|
2007-05-21 11:25:46 -07:00
|
|
|
* \pre ppFileData loaded
|
|
|
|
* \pre s allocated
|
|
|
|
* \pre s->npolys set
|
|
|
|
* \post s->polys allocated (iFSDPoly * s->npolys)
|
|
|
|
* \post s->pindex allocated for each poly
|
|
|
|
*/
|
2010-03-15 14:51:52 -07:00
|
|
|
static bool _imd_load_polys( const char **ppFileData, iIMDShape *s, int pieVersion)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-06-03 06:46:50 -07:00
|
|
|
const char *pFileData = *ppFileData;
|
2007-12-10 15:15:46 -08:00
|
|
|
unsigned int i, j;
|
2007-06-28 10:47:08 -07:00
|
|
|
iIMDPoly *poly;
|
|
|
|
|
|
|
|
s->numFrames = 0;
|
|
|
|
s->animInterval = 0;
|
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
s->polys = (iIMDPoly*)malloc(sizeof(iIMDPoly) * s->npolys);
|
|
|
|
if (s->polys == NULL)
|
|
|
|
{
|
|
|
|
debug(LOG_ERROR, "(_load_polys) Out of memory (polys)");
|
2008-03-24 09:51:17 -07:00
|
|
|
return false;
|
2007-05-21 11:25:46 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0, poly = s->polys; i < s->npolys; i++, poly++)
|
|
|
|
{
|
2007-12-10 15:15:46 -08:00
|
|
|
unsigned int flags, npnts;
|
|
|
|
int cnt;
|
2007-05-21 11:25:46 -07:00
|
|
|
|
2007-12-10 15:15:46 -08:00
|
|
|
if (sscanf(pFileData, "%x %u%n", &flags, &npnts, &cnt) != 2)
|
2007-05-21 11:25:46 -07:00
|
|
|
{
|
2007-12-10 15:15:46 -08:00
|
|
|
debug(LOG_ERROR, "(_load_polys) [poly %u] error loading flags and npoints", i);
|
2007-05-21 11:25:46 -07:00
|
|
|
}
|
|
|
|
pFileData += cnt;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
poly->flags = flags;
|
|
|
|
poly->npnts = npnts;
|
2010-12-31 09:22:22 -08:00
|
|
|
ASSERT_OR_RETURN(false, npnts == 3, "Invalid polygon size (%d)", npnts);
|
|
|
|
if (sscanf(pFileData, "%d %d %d%n", &poly->pindex[0], &poly->pindex[1], &poly->pindex[2], &cnt) != 3)
|
2007-05-21 11:25:46 -07:00
|
|
|
{
|
2010-12-31 09:22:22 -08:00
|
|
|
debug(LOG_ERROR, "failed reading triangle, point %d", i);
|
2008-03-24 09:51:17 -07:00
|
|
|
return false;
|
2007-05-21 11:25:46 -07:00
|
|
|
}
|
2010-12-31 09:22:22 -08:00
|
|
|
pFileData += cnt;
|
2008-03-13 12:09:44 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
// calc poly normal
|
|
|
|
{
|
2007-05-21 12:56:07 -07:00
|
|
|
Vector3f p0, p1, p2;
|
2007-05-21 11:33:07 -07:00
|
|
|
|
|
|
|
//assumes points already set
|
|
|
|
p0.x = s->points[poly->pindex[0]].x;
|
|
|
|
p0.y = s->points[poly->pindex[0]].y;
|
|
|
|
p0.z = s->points[poly->pindex[0]].z;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:33:07 -07:00
|
|
|
p1.x = s->points[poly->pindex[1]].x;
|
|
|
|
p1.y = s->points[poly->pindex[1]].y;
|
|
|
|
p1.z = s->points[poly->pindex[1]].z;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:33:07 -07:00
|
|
|
p2.x = s->points[poly->pindex[poly->npnts-1]].x;
|
|
|
|
p2.y = s->points[poly->pindex[poly->npnts-1]].y;
|
|
|
|
p2.z = s->points[poly->pindex[poly->npnts-1]].z;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2008-01-27 17:29:20 -08:00
|
|
|
poly->normal = pie_SurfaceNormal3fv(p0, p1, p2);
|
2007-05-21 11:25:46 -07:00
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
if (poly->flags & iV_IMD_TEXANIM)
|
|
|
|
{
|
2010-12-05 07:17:26 -08:00
|
|
|
int nFrames, pbRate, tWidth, tHeight;
|
2010-03-15 14:51:52 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
// even the psx needs to skip the data
|
|
|
|
if (sscanf(pFileData, "%d %d %d %d%n", &nFrames, &pbRate, &tWidth, &tHeight, &cnt) != 4)
|
|
|
|
{
|
2007-12-10 15:15:46 -08:00
|
|
|
debug(LOG_ERROR, "(_load_polys) [poly %u] error reading texanim data", i);
|
2008-03-24 09:51:17 -07:00
|
|
|
return false;
|
2007-05-21 11:25:46 -07:00
|
|
|
}
|
|
|
|
pFileData += cnt;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2009-03-20 10:02:49 -07:00
|
|
|
ASSERT(tWidth > 0, "%s: texture width = %d", GetLastResourceFilename(), tWidth);
|
|
|
|
ASSERT(tHeight > 0, "%s: texture height = %d (width=%d)", GetLastResourceFilename(), tHeight, tWidth);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2009-09-28 12:53:10 -07:00
|
|
|
/* Must have same number of frames and same playback rate for all polygons */
|
2007-05-21 11:25:46 -07:00
|
|
|
s->numFrames = nFrames;
|
|
|
|
s->animInterval = pbRate;
|
2009-09-28 12:53:10 -07:00
|
|
|
|
2010-03-15 14:51:52 -07:00
|
|
|
poly->texAnim.x = tWidth / OLD_TEXTURE_SIZE_FIX;
|
|
|
|
poly->texAnim.y = tHeight / OLD_TEXTURE_SIZE_FIX;
|
2007-05-21 11:25:46 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-03-15 14:51:52 -07:00
|
|
|
poly->texAnim.x = 0;
|
|
|
|
poly->texAnim.y = 0;
|
2007-05-21 11:25:46 -07:00
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
// PC texture coord routine
|
|
|
|
if (poly->flags & iV_IMD_TEX)
|
|
|
|
{
|
2010-12-05 07:17:26 -08:00
|
|
|
int nFrames, framesPerLine, frame;
|
2007-07-25 13:58:57 -07:00
|
|
|
|
2010-12-05 07:17:26 -08:00
|
|
|
nFrames = MAX(1, s->numFrames);
|
2010-12-05 08:25:43 -08:00
|
|
|
poly->texCoord = (Vector2f *)malloc(sizeof(*poly->texCoord) * nFrames * poly->npnts);
|
2010-12-05 07:17:26 -08:00
|
|
|
ASSERT_OR_RETURN(false, poly->texCoord, "Out of memory allocating texture coordinates");
|
|
|
|
framesPerLine = OLD_TEXTURE_SIZE_FIX / (poly->texAnim.x * OLD_TEXTURE_SIZE_FIX);
|
2007-05-21 11:25:46 -07:00
|
|
|
for (j = 0; j < poly->npnts; j++)
|
2007-04-28 03:36:21 -07:00
|
|
|
{
|
2007-05-21 12:56:07 -07:00
|
|
|
float VertexU, VertexV;
|
2010-12-05 07:17:26 -08:00
|
|
|
|
2007-05-21 12:56:07 -07:00
|
|
|
if (sscanf(pFileData, "%f %f%n", &VertexU, &VertexV, &cnt) != 2)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-12-10 15:15:46 -08:00
|
|
|
debug(LOG_ERROR, "(_load_polys) [poly %u] error reading tex outline", i);
|
2008-03-24 09:51:17 -07:00
|
|
|
return false;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
pFileData += cnt;
|
|
|
|
|
2010-12-05 07:17:26 -08:00
|
|
|
if (pieVersion != PIE_FLOAT_VER)
|
2010-03-15 14:51:52 -07:00
|
|
|
{
|
2010-12-05 07:17:26 -08:00
|
|
|
VertexU /= OLD_TEXTURE_SIZE_FIX;
|
|
|
|
VertexV /= OLD_TEXTURE_SIZE_FIX;
|
2010-03-15 14:51:52 -07:00
|
|
|
}
|
2010-12-05 07:17:26 -08:00
|
|
|
|
|
|
|
for (frame = 0; frame < nFrames; frame++)
|
2010-03-15 14:51:52 -07:00
|
|
|
{
|
2010-12-05 07:17:26 -08:00
|
|
|
const int uFrame = (frame % framesPerLine) * (poly->texAnim.x * OLD_TEXTURE_SIZE_FIX);
|
|
|
|
const int vFrame = (frame / framesPerLine) * (poly->texAnim.y * OLD_TEXTURE_SIZE_FIX);
|
|
|
|
Vector2f *c = &poly->texCoord[frame * poly->npnts + j];
|
|
|
|
|
|
|
|
c->x = VertexU + uFrame / OLD_TEXTURE_SIZE_FIX;
|
|
|
|
c->y = VertexV + vFrame / OLD_TEXTURE_SIZE_FIX;
|
2010-03-15 14:51:52 -07:00
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
}
|
2007-07-25 13:58:57 -07:00
|
|
|
else
|
|
|
|
{
|
2010-12-05 07:17:26 -08:00
|
|
|
ASSERT_OR_RETURN(false, !(poly->flags & iV_IMD_TEXANIM), "Polygons with texture animation must have textures!");
|
2007-07-25 15:37:48 -07:00
|
|
|
poly->texCoord = NULL;
|
2007-07-25 13:58:57 -07:00
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
*ppFileData = pFileData;
|
2007-05-21 11:25:46 -07:00
|
|
|
|
2008-03-24 09:51:17 -07:00
|
|
|
return true;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
|
2007-06-03 06:46:50 -07:00
|
|
|
static BOOL ReadPoints( const char **ppFileData, iIMDShape *s )
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-06-03 06:46:50 -07:00
|
|
|
const char *pFileData = *ppFileData;
|
2007-12-10 15:15:46 -08:00
|
|
|
unsigned int i;
|
2010-02-13 10:50:15 -08:00
|
|
|
int cnt;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
for (i = 0; i < s->npoints; i++)
|
|
|
|
{
|
2010-02-13 10:50:15 -08:00
|
|
|
if (sscanf(pFileData, "%f %f %f%n", &s->points[i].x, &s->points[i].y, &s->points[i].z, &cnt) != 3)
|
2007-05-21 11:25:46 -07:00
|
|
|
{
|
2007-06-18 08:46:12 -07:00
|
|
|
debug(LOG_ERROR, "(_load_points) file corrupt -K");
|
2008-03-24 09:51:17 -07:00
|
|
|
return false;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
pFileData += cnt;
|
|
|
|
}
|
|
|
|
|
|
|
|
*ppFileData = pFileData;
|
2007-05-21 11:25:46 -07:00
|
|
|
|
2008-03-24 09:51:17 -07:00
|
|
|
return true;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-06-03 06:46:50 -07:00
|
|
|
static BOOL _imd_load_points( const char **ppFileData, iIMDShape *s )
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-05-21 12:56:07 -07:00
|
|
|
Vector3f *p = NULL;
|
2009-04-29 11:55:34 -07:00
|
|
|
int32_t tempXMax, tempXMin, tempZMax, tempZMin;
|
|
|
|
int32_t xmax, ymax, zmax;
|
2007-06-28 10:47:08 -07:00
|
|
|
double dx, dy, dz, rad_sq, rad, old_to_p_sq, old_to_p, old_to_new;
|
|
|
|
double xspan, yspan, zspan, maxspan;
|
2007-03-16 09:20:16 -07:00
|
|
|
Vector3f dia1, dia2, cen;
|
2010-12-21 12:51:29 -08:00
|
|
|
Vector3f vxmin(0, 0, 0), vymin(0, 0, 0), vzmin(0, 0, 0),
|
|
|
|
vxmax(0, 0, 0), vymax(0, 0, 0), vzmax(0, 0, 0);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
//load the points then pass through a second time to setup bounding datavalues
|
2007-05-21 12:56:07 -07:00
|
|
|
s->points = (Vector3f*)malloc(sizeof(Vector3f) * s->npoints);
|
2007-05-21 11:25:46 -07:00
|
|
|
if (s->points == NULL)
|
|
|
|
{
|
2008-03-24 09:51:17 -07:00
|
|
|
return false;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Read in points and remove duplicates (!)
|
2008-03-24 09:51:17 -07:00
|
|
|
if ( ReadPoints( ppFileData, s ) == false )
|
2007-02-19 09:37:11 -08:00
|
|
|
{
|
2008-03-07 07:09:03 -08:00
|
|
|
free(s->points);
|
|
|
|
s->points = NULL;
|
2008-03-24 09:51:17 -07:00
|
|
|
return false;
|
2007-02-19 09:37:11 -08:00
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-12-21 09:34:23 -08:00
|
|
|
s->max.x = s->max.y = s->max.z = tempXMax = tempZMax = -FP12_MULTIPLIER;
|
|
|
|
s->min.x = s->min.y = s->min.z = tempXMin = tempZMin = FP12_MULTIPLIER;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
vxmax.x = vymax.y = vzmax.z = -FP12_MULTIPLIER;
|
|
|
|
vxmin.x = vymin.y = vzmin.z = FP12_MULTIPLIER;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2006-06-02 12:34:58 -07:00
|
|
|
// set up bounding data for minimum number of vertices
|
2007-06-03 06:46:50 -07:00
|
|
|
for (p = s->points; p < s->points + s->npoints; p++)
|
2007-05-21 11:25:46 -07:00
|
|
|
{
|
2007-12-21 09:34:23 -08:00
|
|
|
if (p->x > s->max.x)
|
|
|
|
{
|
|
|
|
s->max.x = p->x;
|
|
|
|
}
|
|
|
|
if (p->x < s->min.x)
|
|
|
|
{
|
|
|
|
s->min.x = p->x;
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
/* Biggest x coord so far within our height window? */
|
|
|
|
if( p->x > tempXMax && p->y > DROID_VIS_LOWER && p->y < DROID_VIS_UPPER )
|
|
|
|
{
|
|
|
|
tempXMax = p->x;
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
/* Smallest x coord so far within our height window? */
|
|
|
|
if( p->x < tempXMin && p->y > DROID_VIS_LOWER && p->y < DROID_VIS_UPPER )
|
|
|
|
{
|
|
|
|
tempXMin = p->x;
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-12-21 09:34:23 -08:00
|
|
|
if (p->y > s->max.y)
|
|
|
|
{
|
|
|
|
s->max.y = p->y;
|
|
|
|
}
|
|
|
|
if (p->y < s->min.y)
|
|
|
|
{
|
|
|
|
s->min.y = p->y;
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-12-21 09:34:23 -08:00
|
|
|
if (p->z > s->max.z)
|
|
|
|
{
|
|
|
|
s->max.z = p->z;
|
|
|
|
}
|
|
|
|
if (p->z < s->min.z)
|
|
|
|
{
|
|
|
|
s->min.z = p->z;
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
/* Biggest z coord so far within our height window? */
|
|
|
|
if( p->z > tempZMax && p->y > DROID_VIS_LOWER && p->y < DROID_VIS_UPPER )
|
|
|
|
{
|
|
|
|
tempZMax = p->z;
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
/* Smallest z coord so far within our height window? */
|
|
|
|
if( p->z < tempZMax && p->y > DROID_VIS_LOWER && p->y < DROID_VIS_UPPER )
|
|
|
|
{
|
|
|
|
tempZMin = p->z;
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
// for tight sphere calculations
|
|
|
|
if (p->x < vxmin.x)
|
|
|
|
{
|
|
|
|
vxmin.x = p->x;
|
|
|
|
vxmin.y = p->y;
|
|
|
|
vxmin.z = p->z;
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
if (p->x > vxmax.x)
|
|
|
|
{
|
|
|
|
vxmax.x = p->x;
|
|
|
|
vxmax.y = p->y;
|
|
|
|
vxmax.z = p->z;
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
if (p->y < vymin.y)
|
|
|
|
{
|
|
|
|
vymin.x = p->x;
|
|
|
|
vymin.y = p->y;
|
|
|
|
vymin.z = p->z;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
if (p->y > vymax.y)
|
|
|
|
{
|
|
|
|
vymax.x = p->x;
|
|
|
|
vymax.y = p->y;
|
|
|
|
vymax.z = p->z;
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
if (p->z < vzmin.z)
|
|
|
|
{
|
|
|
|
vzmin.x = p->x;
|
|
|
|
vzmin.y = p->y;
|
|
|
|
vzmin.z = p->z;
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
if (p->z > vzmax.z)
|
|
|
|
{
|
|
|
|
vzmax.x = p->x;
|
|
|
|
vzmax.y = p->y;
|
|
|
|
vzmax.z = p->z;
|
|
|
|
}
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
// no need to scale an IMD shape (only FSD)
|
2007-12-21 09:34:23 -08:00
|
|
|
xmax = MAX(s->max.x, -s->min.x);
|
|
|
|
ymax = MAX(s->max.y, -s->min.y);
|
|
|
|
zmax = MAX(s->max.z, -s->min.z);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2008-03-07 07:09:03 -08:00
|
|
|
s->radius = MAX(xmax, MAX(ymax, zmax));
|
2007-05-21 11:25:46 -07:00
|
|
|
s->sradius = sqrtf(xmax*xmax + ymax*ymax + zmax*zmax);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
// START: tight bounding sphere
|
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
// set xspan = distance between 2 points xmin & xmax (squared)
|
|
|
|
dx = vxmax.x - vxmin.x;
|
|
|
|
dy = vxmax.y - vxmin.y;
|
|
|
|
dz = vxmax.z - vxmin.z;
|
|
|
|
xspan = dx*dx + dy*dy + dz*dz;
|
|
|
|
|
|
|
|
// same for yspan
|
|
|
|
dx = vymax.x - vymin.x;
|
|
|
|
dy = vymax.y - vymin.y;
|
|
|
|
dz = vymax.z - vymin.z;
|
|
|
|
yspan = dx*dx + dy*dy + dz*dz;
|
|
|
|
|
|
|
|
// and ofcourse zspan
|
|
|
|
dx = vzmax.x - vzmin.x;
|
|
|
|
dy = vzmax.y - vzmin.y;
|
|
|
|
dz = vzmax.z - vzmin.z;
|
|
|
|
zspan = dx*dx + dy*dy + dz*dz;
|
|
|
|
|
|
|
|
// set points dia1 & dia2 to maximally seperated pair
|
|
|
|
// assume xspan biggest
|
|
|
|
dia1 = vxmin;
|
|
|
|
dia2 = vxmax;
|
|
|
|
maxspan = xspan;
|
|
|
|
|
|
|
|
if (yspan > maxspan)
|
|
|
|
{
|
|
|
|
maxspan = yspan;
|
|
|
|
dia1 = vymin;
|
|
|
|
dia2 = vymax;
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
if (zspan > maxspan)
|
|
|
|
{
|
|
|
|
maxspan = zspan;
|
|
|
|
dia1 = vzmin;
|
|
|
|
dia2 = vzmax;
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
// dia1, dia2 diameter of initial sphere
|
|
|
|
cen.x = (dia1.x + dia2.x) / 2.;
|
|
|
|
cen.y = (dia1.y + dia2.y) / 2.;
|
|
|
|
cen.z = (dia1.z + dia2.z) / 2.;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
// calc initial radius
|
|
|
|
dx = dia2.x - cen.x;
|
|
|
|
dy = dia2.y - cen.y;
|
|
|
|
dz = dia2.z - cen.z;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
rad_sq = dx*dx + dy*dy + dz*dz;
|
2010-12-09 08:03:23 -08:00
|
|
|
rad = sqrt((double)rad_sq);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
// second pass (find tight sphere)
|
2007-06-03 06:46:50 -07:00
|
|
|
for (p = s->points; p < s->points + s->npoints; p++)
|
2007-05-21 11:25:46 -07:00
|
|
|
{
|
|
|
|
dx = p->x - cen.x;
|
|
|
|
dy = p->y - cen.y;
|
|
|
|
dz = p->z - cen.z;
|
|
|
|
old_to_p_sq = dx*dx + dy*dy + dz*dz;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
// do r**2 first
|
|
|
|
if (old_to_p_sq>rad_sq)
|
|
|
|
{
|
|
|
|
// this point outside current sphere
|
2010-12-09 08:03:23 -08:00
|
|
|
old_to_p = sqrt((double)old_to_p_sq);
|
2007-05-21 11:25:46 -07:00
|
|
|
// radius of new sphere
|
|
|
|
rad = (rad + old_to_p) / 2.;
|
|
|
|
// rad**2 for next compare
|
|
|
|
rad_sq = rad*rad;
|
|
|
|
old_to_new = old_to_p - rad;
|
|
|
|
// centre of new sphere
|
|
|
|
cen.x = (rad*cen.x + old_to_new*p->x) / old_to_p;
|
|
|
|
cen.y = (rad*cen.y + old_to_new*p->y) / old_to_p;
|
|
|
|
cen.z = (rad*cen.z + old_to_new*p->z) / old_to_p;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
2007-05-21 11:25:46 -07:00
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 12:56:07 -07:00
|
|
|
s->ocen = cen;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
// END: tight bounding sphere
|
2007-05-21 11:25:46 -07:00
|
|
|
|
2008-03-24 09:51:17 -07:00
|
|
|
return true;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
/*!
|
|
|
|
* Load shape level connectors
|
|
|
|
* \param ppFileData Pointer to the data (usualy read from a file)
|
|
|
|
* \param s Pointer to shape level
|
2008-03-24 09:51:17 -07:00
|
|
|
* \return false on error (memory allocation failure/bad file format), true otherwise
|
2007-05-21 11:25:46 -07:00
|
|
|
* \pre ppFileData loaded
|
|
|
|
* \pre s allocated
|
|
|
|
* \pre s->nconnectors set
|
|
|
|
* \post s->connectors allocated
|
|
|
|
*/
|
2007-06-03 06:46:50 -07:00
|
|
|
static BOOL _imd_load_connectors(const char **ppFileData, iIMDShape *s)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-06-03 06:46:50 -07:00
|
|
|
const char *pFileData = *ppFileData;
|
|
|
|
int cnt;
|
2010-12-21 12:51:29 -08:00
|
|
|
Vector3i *p = NULL, newVector(0, 0, 0);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2010-11-20 11:34:21 -08:00
|
|
|
s->connectors = (Vector3i *)malloc(sizeof(Vector3i) * s->nconnectors);
|
2007-05-21 11:25:46 -07:00
|
|
|
if (s->connectors == NULL)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-06-18 08:46:12 -07:00
|
|
|
debug(LOG_ERROR, "(_load_connectors) MALLOC fail");
|
2008-03-24 09:51:17 -07:00
|
|
|
return false;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
2007-06-03 06:46:50 -07:00
|
|
|
for (p = s->connectors; p < s->connectors + s->nconnectors; p++)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2010-11-21 02:30:18 -08:00
|
|
|
if (sscanf(pFileData, "%d %d %d%n", &newVector.x, &newVector.y, &newVector.z, &cnt) != 3 &&
|
|
|
|
sscanf(pFileData, "%d%*[.0-9] %d%*[.0-9] %d%*[.0-9]%n", &newVector.x, &newVector.y, &newVector.z, &cnt) != 3)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-06-18 08:46:12 -07:00
|
|
|
debug(LOG_ERROR, "(_load_connectors) file corrupt -M");
|
2008-03-24 09:51:17 -07:00
|
|
|
return false;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
2007-05-21 11:25:46 -07:00
|
|
|
pFileData += cnt;
|
2007-05-23 13:57:11 -07:00
|
|
|
*p = newVector;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
*ppFileData = pFileData;
|
2007-05-21 11:25:46 -07:00
|
|
|
|
2008-03-24 09:51:17 -07:00
|
|
|
return true;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
/*!
|
|
|
|
* Load shape levels recursively
|
|
|
|
* \param ppFileData Pointer to the data (usualy read from a file)
|
|
|
|
* \param FileDataEnd ???
|
|
|
|
* \param nlevels Number of levels to load
|
|
|
|
* \return pointer to iFSDShape structure (or NULL on error)
|
|
|
|
* \pre ppFileData loaded
|
|
|
|
* \post s allocated
|
|
|
|
*/
|
2010-03-15 14:51:52 -07:00
|
|
|
static iIMDShape *_imd_load_level(const char **ppFileData, const char *FileDataEnd, int nlevels, int pieVersion)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2010-12-26 13:12:53 -08:00
|
|
|
const char *pTmp, *pFileData = *ppFileData;
|
2007-08-21 05:59:05 -07:00
|
|
|
char buffer[PATH_MAX] = {'\0'};
|
2010-12-26 13:12:53 -08:00
|
|
|
int cnt = 0, n = 0, i;
|
2007-05-21 11:25:46 -07:00
|
|
|
iIMDShape *s = NULL;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
if (nlevels == 0)
|
|
|
|
return NULL;
|
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
s = (iIMDShape*)malloc(sizeof(iIMDShape));
|
|
|
|
if (s == NULL)
|
|
|
|
{
|
|
|
|
/* Failed to allocate memory for s */
|
|
|
|
debug(LOG_ERROR, "_imd_load_level: Memory allocation error");
|
|
|
|
return NULL;
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2010-03-06 15:03:29 -08:00
|
|
|
s->flags = 0;
|
2007-05-21 11:25:46 -07:00
|
|
|
s->nconnectors = 0; // Default number of connectors must be 0
|
|
|
|
s->npoints = 0;
|
|
|
|
s->npolys = 0;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
s->points = NULL;
|
|
|
|
s->polys = NULL;
|
|
|
|
s->connectors = NULL;
|
|
|
|
s->next = NULL;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
s->shadowEdgeList = NULL;
|
|
|
|
s->nShadowEdges = 0;
|
2007-07-25 13:58:57 -07:00
|
|
|
s->texpage = iV_TEX_INVALID;
|
2010-03-06 15:03:29 -08:00
|
|
|
s->tcmaskpage = iV_TEX_INVALID;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2010-12-26 13:12:53 -08:00
|
|
|
// Load optional MATERIALS directive
|
|
|
|
pTmp = pFileData; // remember position
|
2010-12-25 05:05:19 -08:00
|
|
|
i = sscanf(pFileData, "%255s %n", buffer, &cnt);
|
2010-12-26 13:12:53 -08:00
|
|
|
ASSERT_OR_RETURN(NULL, i == 1, "Bad directive following LEVEL");
|
|
|
|
memset(s->material, 0, sizeof(s->material));
|
|
|
|
s->material[LIGHT_AMBIENT][3] = 1.0f;
|
|
|
|
s->material[LIGHT_DIFFUSE][3] = 1.0f;
|
|
|
|
s->material[LIGHT_SPECULAR][3] = 1.0f;
|
|
|
|
if (strcmp(buffer, "MATERIALS") == 0)
|
|
|
|
{
|
2010-12-25 05:05:19 -08:00
|
|
|
i = sscanf(pFileData, "%255s %f %f %f %f %f %f %f %f %f %f%n", buffer,
|
2010-12-26 13:12:53 -08:00
|
|
|
&s->material[LIGHT_AMBIENT][0], &s->material[LIGHT_AMBIENT][1], &s->material[LIGHT_AMBIENT][2],
|
|
|
|
&s->material[LIGHT_DIFFUSE][0], &s->material[LIGHT_DIFFUSE][1], &s->material[LIGHT_DIFFUSE][2],
|
|
|
|
&s->material[LIGHT_SPECULAR][0], &s->material[LIGHT_SPECULAR][1], &s->material[LIGHT_SPECULAR][2],
|
|
|
|
&s->shininess, &cnt);
|
|
|
|
ASSERT_OR_RETURN(NULL, i == 11, "Bad MATERIALS directive");
|
|
|
|
pFileData += cnt;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Set default values
|
|
|
|
s->material[LIGHT_AMBIENT][0] = 1.0f;
|
|
|
|
s->material[LIGHT_AMBIENT][1] = 1.0f;
|
|
|
|
s->material[LIGHT_AMBIENT][2] = 1.0f;
|
|
|
|
s->material[LIGHT_DIFFUSE][0] = 1.0f;
|
|
|
|
s->material[LIGHT_DIFFUSE][1] = 1.0f;
|
|
|
|
s->material[LIGHT_DIFFUSE][2] = 1.0f;
|
|
|
|
s->material[LIGHT_SPECULAR][0] = 1.0f;
|
|
|
|
s->material[LIGHT_SPECULAR][1] = 1.0f;
|
|
|
|
s->material[LIGHT_SPECULAR][2] = 1.0f;
|
|
|
|
s->shininess = 10;
|
|
|
|
pFileData = pTmp;
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2010-12-25 05:05:19 -08:00
|
|
|
if (sscanf(pFileData, "%255s %d%n", buffer, &s->npoints, &cnt) != 2)
|
2007-05-21 11:25:46 -07:00
|
|
|
{
|
|
|
|
debug(LOG_ERROR, "_imd_load_level(2): file corrupt");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
pFileData += cnt;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
// load points
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2010-12-26 13:12:53 -08:00
|
|
|
ASSERT_OR_RETURN(NULL, strcmp(buffer, "POINTS") == 0, "Expecting 'POINTS' directive, got: %s", buffer);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
_imd_load_points( &pFileData, s );
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2010-12-25 05:05:19 -08:00
|
|
|
if (sscanf(pFileData, "%255s %d%n", buffer, &s->npolys, &cnt) != 2)
|
2007-05-21 11:25:46 -07:00
|
|
|
{
|
|
|
|
debug(LOG_ERROR, "_imd_load_level(3): file corrupt");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
pFileData += cnt;
|
2006-06-02 12:34:58 -07:00
|
|
|
|
2010-12-26 13:12:53 -08:00
|
|
|
ASSERT_OR_RETURN(NULL, strcmp(buffer, "POLYGONS") == 0, "Expecting 'POLYGONS' directive, got: %s", buffer);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2010-03-15 14:51:52 -07:00
|
|
|
_imd_load_polys( &pFileData, s, pieVersion);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
// NOW load optional stuff
|
|
|
|
while (!AtEndOfFile(pFileData, FileDataEnd)) // check for end of file (give or take white space)
|
|
|
|
{
|
|
|
|
// Scans in the line ... if we don't get 2 parameters then quit
|
2010-12-25 05:05:19 -08:00
|
|
|
if (sscanf(pFileData, "%255s %d%n", buffer, &n, &cnt) != 2)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-05-21 11:25:46 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
pFileData += cnt;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-21 11:25:46 -07:00
|
|
|
// check for next level ... or might be a BSP - This should handle an imd if it has a BSP tree attached to it
|
|
|
|
// might be "BSP" or "LEVEL"
|
|
|
|
if (strcmp(buffer, "LEVEL") == 0)
|
|
|
|
{
|
2007-10-27 06:58:01 -07:00
|
|
|
debug(LOG_3D, "imd[_load_level] = npoints %d, npolys %d", s->npoints, s->npolys);
|
2010-03-15 14:51:52 -07:00
|
|
|
s->next = _imd_load_level(&pFileData, FileDataEnd, nlevels - 1, pieVersion);
|
2007-05-21 11:25:46 -07:00
|
|
|
}
|
|
|
|
else if (strcmp(buffer, "CONNECTORS") == 0)
|
|
|
|
{
|
|
|
|
//load connector stuff
|
|
|
|
s->nconnectors = n;
|
|
|
|
_imd_load_connectors( &pFileData, s );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-06-18 08:46:12 -07:00
|
|
|
debug(LOG_ERROR, "(_load_level) unexpected directive %s %d", buffer, n);
|
2007-05-21 11:25:46 -07:00
|
|
|
break;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
}
|
2007-05-21 11:25:46 -07:00
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
*ppFileData = pFileData;
|
2007-05-21 11:25:46 -07:00
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
return s;
|
|
|
|
}
|
2007-06-03 07:07:31 -07:00
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* Load ppFileData into a shape
|
|
|
|
* \param ppFileData Data from the IMD file
|
|
|
|
* \param FileDataEnd Endpointer
|
|
|
|
* \return The shape, constructed from the data read
|
|
|
|
*/
|
|
|
|
// ppFileData is incremented to the end of the file on exit!
|
|
|
|
iIMDShape *iV_ProcessIMD( const char **ppFileData, const char *FileDataEnd )
|
|
|
|
{
|
|
|
|
const char *pFileName = GetLastResourceFilename(); // Last loaded texture page filename
|
|
|
|
const char *pFileData = *ppFileData;
|
2007-08-21 05:59:05 -07:00
|
|
|
char buffer[PATH_MAX], texfile[PATH_MAX];
|
2007-06-03 07:07:31 -07:00
|
|
|
int cnt, nlevels;
|
|
|
|
iIMDShape *shape, *psShape;
|
|
|
|
UDWORD level;
|
2009-04-29 11:55:34 -07:00
|
|
|
int32_t imd_version;
|
2010-03-06 15:03:29 -08:00
|
|
|
uint32_t imd_flags;
|
2008-03-24 09:51:17 -07:00
|
|
|
BOOL bTextured = false;
|
2007-06-03 07:07:31 -07:00
|
|
|
|
2010-12-25 05:05:19 -08:00
|
|
|
if (sscanf(pFileData, "%255s %d%n", buffer, &imd_version, &cnt) != 2)
|
2007-06-03 07:07:31 -07:00
|
|
|
{
|
|
|
|
debug(LOG_ERROR, "iV_ProcessIMD %s bad version: (%s)", pFileName, buffer);
|
2008-03-24 09:51:17 -07:00
|
|
|
assert(false);
|
2007-06-03 07:07:31 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
pFileData += cnt;
|
|
|
|
|
2010-12-31 09:22:22 -08:00
|
|
|
if (strcmp(PIE_NAME, buffer) != 0)
|
2007-06-03 07:07:31 -07:00
|
|
|
{
|
|
|
|
debug(LOG_ERROR, "iV_ProcessIMD %s not an IMD file (%s %d)", pFileName, buffer, imd_version);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-03-15 14:51:52 -07:00
|
|
|
//Now supporting version PIE_VER and PIE_FLOAT_VER files
|
|
|
|
if (imd_version != PIE_VER && imd_version != PIE_FLOAT_VER)
|
2007-06-03 07:07:31 -07:00
|
|
|
{
|
|
|
|
debug(LOG_ERROR, "iV_ProcessIMD %s version %d not supported", pFileName, imd_version);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-12-05 07:17:26 -08:00
|
|
|
// Read flag
|
2010-12-25 05:05:19 -08:00
|
|
|
if (sscanf(pFileData, "%255s %x%n", buffer, &imd_flags, &cnt) != 2)
|
2007-06-03 07:07:31 -07:00
|
|
|
{
|
|
|
|
debug(LOG_ERROR, "iV_ProcessIMD %s bad flags: %s", pFileName, buffer);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
pFileData += cnt;
|
|
|
|
|
|
|
|
/* This can be either texture or levels */
|
2010-12-25 05:05:19 -08:00
|
|
|
if (sscanf(pFileData, "%255s %d%n", buffer, &nlevels, &cnt) != 2)
|
2007-06-03 07:07:31 -07:00
|
|
|
{
|
|
|
|
debug(LOG_ERROR, "iV_ProcessIMD %s expecting TEXTURE or LEVELS: %s", pFileName, buffer);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
pFileData += cnt;
|
|
|
|
|
|
|
|
// get texture page if specified
|
|
|
|
if (strncmp(buffer, "TEXTURE", 7) == 0)
|
|
|
|
{
|
|
|
|
int i, pwidth, pheight;
|
2007-08-21 05:59:05 -07:00
|
|
|
char ch, texType[PATH_MAX];
|
2007-06-03 07:07:31 -07:00
|
|
|
|
|
|
|
/* the first parameter for textures is always ignored; which is why we ignore
|
|
|
|
* nlevels read in above */
|
|
|
|
ch = *pFileData++;
|
|
|
|
|
|
|
|
// Run up to the dot or till the buffer is filled. Leave room for the extension.
|
2008-02-01 04:59:42 -08:00
|
|
|
for (i = 0; i < PATH_MAX-5 && (ch = *pFileData++) != '\0' && ch != '.'; ++i)
|
2007-06-03 07:07:31 -07:00
|
|
|
{
|
2008-02-01 04:59:42 -08:00
|
|
|
texfile[i] = ch;
|
2007-06-03 07:07:31 -07:00
|
|
|
}
|
|
|
|
texfile[i] = '\0';
|
|
|
|
|
2010-12-25 05:05:19 -08:00
|
|
|
if (sscanf(pFileData, "%255s%n", texType, &cnt) != 1)
|
2007-06-03 07:07:31 -07:00
|
|
|
{
|
|
|
|
debug(LOG_ERROR, "iV_ProcessIMD %s texture info corrupt: %s", pFileName, buffer);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
pFileData += cnt;
|
|
|
|
|
|
|
|
if (strcmp(texType, "png") != 0)
|
|
|
|
{
|
|
|
|
debug(LOG_ERROR, "iV_ProcessIMD %s: only png textures supported", pFileName);
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-05-25 06:46:49 -07:00
|
|
|
sstrcat(texfile, ".png");
|
2007-10-24 14:11:29 -07:00
|
|
|
|
2007-06-03 07:07:31 -07:00
|
|
|
if (sscanf(pFileData, "%d %d%n", &pwidth, &pheight, &cnt) != 2)
|
|
|
|
{
|
|
|
|
debug(LOG_ERROR, "iV_ProcessIMD %s bad texture size: %s", pFileName, buffer);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
pFileData += cnt;
|
|
|
|
|
|
|
|
/* Now read in LEVELS directive */
|
2010-12-25 05:05:19 -08:00
|
|
|
if (sscanf(pFileData, "%255s %d%n", buffer, &nlevels, &cnt) != 2)
|
2007-06-03 07:07:31 -07:00
|
|
|
{
|
|
|
|
debug(LOG_ERROR, "iV_ProcessIMD %s bad levels info: %s", pFileName, buffer);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
pFileData += cnt;
|
|
|
|
|
2008-03-24 09:51:17 -07:00
|
|
|
bTextured = true;
|
2007-06-03 07:07:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (strncmp(buffer, "LEVELS", 6) != 0)
|
|
|
|
{
|
|
|
|
debug(LOG_ERROR, "iV_ProcessIMD: expecting 'LEVELS' directive (%s)", buffer);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Read first LEVEL directive */
|
2010-12-25 05:05:19 -08:00
|
|
|
if (sscanf(pFileData, "%255s %d%n", buffer, &level, &cnt) != 2)
|
2007-06-03 07:07:31 -07:00
|
|
|
{
|
2007-06-18 08:46:12 -07:00
|
|
|
debug(LOG_ERROR, "(_load_level) file corrupt -J");
|
2007-06-03 07:07:31 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
pFileData += cnt;
|
|
|
|
|
|
|
|
if (strncmp(buffer, "LEVEL", 5) != 0)
|
|
|
|
{
|
2008-02-06 05:06:04 -08:00
|
|
|
debug(LOG_ERROR, "iV_ProcessIMD(2): expecting 'LEVEL' directive (%s)", buffer);
|
2007-06-03 07:07:31 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-03-15 14:51:52 -07:00
|
|
|
shape = _imd_load_level(&pFileData, FileDataEnd, nlevels, imd_version);
|
2007-06-03 07:07:31 -07:00
|
|
|
if (shape == NULL)
|
|
|
|
{
|
|
|
|
debug(LOG_ERROR, "iV_ProcessIMD %s unsuccessful", pFileName);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// load texture page if specified
|
|
|
|
if (bTextured)
|
|
|
|
{
|
2007-07-25 13:58:57 -07:00
|
|
|
int texpage = iV_GetTexture(texfile);
|
2007-06-03 07:07:31 -07:00
|
|
|
|
2010-11-12 12:31:56 -08:00
|
|
|
ASSERT_OR_RETURN(NULL, texpage >= 0, "%s could not load tex page %s", pFileName, texfile);
|
2010-04-10 07:59:16 -07:00
|
|
|
|
|
|
|
// assign tex page to levels
|
2007-06-03 07:07:31 -07:00
|
|
|
for (psShape = shape; psShape != NULL; psShape = psShape->next)
|
|
|
|
{
|
|
|
|
psShape->texpage = texpage;
|
|
|
|
}
|
2010-03-06 15:03:29 -08:00
|
|
|
|
|
|
|
// check if model should use team colour mask
|
|
|
|
if (imd_flags & iV_IMD_TCMASK)
|
|
|
|
{
|
2010-11-12 12:31:56 -08:00
|
|
|
int texpage_mask;
|
|
|
|
|
2010-03-06 15:03:29 -08:00
|
|
|
pie_MakeTexPageTCMaskName(texfile);
|
2010-11-12 12:31:56 -08:00
|
|
|
sstrcat(texfile, ".png");
|
|
|
|
texpage_mask = iV_GetTexture(texfile);
|
2010-03-06 15:03:29 -08:00
|
|
|
|
2010-11-12 12:31:56 -08:00
|
|
|
ASSERT_OR_RETURN(shape, texpage_mask >= 0, "%s could not load tcmask %s", pFileName, texfile);
|
|
|
|
|
|
|
|
// Propagate settings through levels
|
|
|
|
for (psShape = shape; psShape != NULL; psShape = psShape->next)
|
2010-03-06 15:03:29 -08:00
|
|
|
{
|
2010-11-12 12:31:56 -08:00
|
|
|
psShape->flags |= iV_IMD_TCMASK;
|
|
|
|
psShape->tcmaskpage = texpage_mask;
|
2010-03-06 15:03:29 -08:00
|
|
|
}
|
|
|
|
}
|
2007-06-03 07:07:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
*ppFileData = pFileData;
|
|
|
|
return shape;
|
|
|
|
}
|