#include "dkdata.h"

int		filelength;
int		formlength;
byte	*lwostart, *lwoend;

int	surfacecount;
int	numpolys;
int	numpoints;

static int	uvchunk;

static lwpoly_t		*poly;
static lwpoint3d_t	*point;

surface_t	lwsurface[MAX_SURFACES];

extern char		dirname[64];

/*
================
align
================
*/
int align (int len)
{
	if (len & 1)
		return len + 1;
	return len;
}

/*
================
SkipSurface
================
*/
int SkipSurface (char *name)
{
	if (!strcmp(name, "steed")) 
		return(1);
	if (!strcmp(name, "ass"))   
		return(1);

	return(0);
}

void LWO_LoadPolys(lwtriangle_t **pptri, int *numtriangles)
{
	lwtriangle_t *ptri;
	int i, j, k;
	float temp;

	// verify that file has points and polys
	if (!point)
		Error("No points found\n");

	if (!poly)
		Error("No polys found\n");

	*numtriangles = numpolys;
	*pptri = ptri = malloc(numpolys * sizeof(lwtriangle_t));

	// expand polys
	for (i = 0; i < numpolys; i++)
	{
		for (j = 0; j < 3; j++)
		{
			for (k = 0; k < 3; k++)
			{
				ptri[i].verts[j][k] = point[poly[i].p[j]].v[k];
				ptri[i].id = poly[i].id;
			}
		}
	}

	// ok we need to swap the y and the z components since lightwave has y
	// as up and quake as z as up
	for (i = 0; i < numpolys; i++)
	{
		for (j = 0; j < 3; j++)
		{
			temp                = ptri[i].verts[j][2];
			ptri[i].verts[j][2] = ptri[i].verts[j][1];
			ptri[i].verts[j][1] = temp;
		}
	}
}

void LWO_LoadTexture(surface_t *surf, char *path, int tIndex)
{
    bitmap_t   bit;
	char       *dest, *source;
	int h;

	LoadBMP(path, &bit);

	// make sure this is 24 bit image
	if (bit.bpp != 24)
        Error("Image %s.  Expected 24 bpp.", path);

	// if this puppy is bigger than 256, then blow
	if ((bit.width > 256) || (bit.height > 256))
		Error("Texture %s must be smaller than 256", path);

	// textures must have an aspect ratio of 8:1
	if ((bit.height * 8) < bit.width)
		Error("Texture %s must have aspect ratio of 8:1 or less", path);

	if ((bit.width * 8) < bit.height)
		Error("Texture %s must have aspect ratio of 8:1 or less", path);

	// if this is not the first texture then make sure this texture is the same
	// size as the ones loaded
	if (tIndex > 0)
	{
		if ((bit.width != surf->tWidth) || (bit.height != surf->tHeight))
		{
			Error("LoadTexture: Textures must be same size. (%s)", path);
		}
	}

	// make sure we have room left
	if (tIndex >= MAX_TEXTURES)
	{
		Error("LoadTexture: Increase MAX_TEXTURES.");
	}

	surf->tWidth  = bit.width;
	surf->tHeight = bit.height;

	if (bit.width % 4)
	{
		Error("Texture %s MUST be a multiple of 4", path);
	}

// make the width a multiple of 4; some hardware requires this, and it ensures
// dword alignment for each scan
	// model.skinwidth = (swidth + 3) & ~3;
	// surf->tBitWidth = bit.width;
	surf->tWidth = (bit.width + 3) & ~3;

	// icrease texture count
	if (tIndex == 0)
	{
	    surf->tCount = 1;
	}
	else
	{
		if ((tIndex + 1) > surf->tCount)
		{
			surf->tCount = tIndex + 1;
		}
	}

	// surf->tData[tIndex] = malloc(bit.width * bit.height * 3);
	surf->tData[tIndex] = malloc(surf->tWidth * surf->tHeight * 3);

	// memcpy(surf->tData[tIndex], bit.data, bit.width * bit.height * 3);

	for (h = 0; h < surf->tHeight; h++)
	{
		source = bit.data + (h * bit.width * 3);
		dest   = surf->tData[tIndex] + (h * surf->tWidth * 3);

		memcpy(dest, source, bit.width * 3);
	}

	FreeBMP(&bit);

	qprintf("Loaded texture from %s\n", path);
}

float fract(float v, char *surfaceName)
{
	if ((v >= 0.0) && (v <= 1.0))
	{
		return(v);
	}

	// v = v - floor(v);

	if (v < 0.0) 
	{
		// printf("WARNING -- v < 0: %f, Surface: %s\n", v, surfaceName);
		return(0.0);
	}
	else if (v > 1.0) 
	{
		// printf("WARNING -- v > 1: %f, Surface: %s\n", v, surfaceName);
		return(1.0);
	}
	else
	{
		return(v);
	}
}

float cfract(float v, char *surfaceName)
{
	if ((v >= 0.0) && (v <= 1.0))
	{
		return(v);
	}

	v = v - floor(v);

	if (v < 0.0) 
	{
		// printf("WARNING -- v < 0: %f, Surface: %s\n", v, surfaceName);
		return(0.0);
	}
	else if (v > 1.0) 
	{
		// printf("WARNING -- v > 1: %f, Surface: %s\n", v, surfaceName);
		return(1.0);
	}
	else
	{
		return(v);
	}
}

void xyztoh(float x,float y,float z,float *h)
{
    if (x == 0.0 && z == 0.0)
        *h = 0.0;
    else {
        if (z == 0.0)
            *h = (x < 0.0) ? HALFPI : -HALFPI;
        else if (z < 0.0)
            *h = -atan(x / z) + PI;
        else
            *h = -atan(x / z);
    }
}

void xyztohp(float x,float y,float z,float *h,float *p)
{
    if (x == 0.0 && z == 0.0) {
        *h = 0.0;
        if (y != 0.0)
            *p = (y < 0.0) ? -HALFPI : HALFPI;
        else
            *p = 0.0;
    }
    else {
        if (z == 0.0)
            *h = (x < 0.0) ? HALFPI : -HALFPI;
        else if (z < 0.0)
            *h = -atan(x / z) + PI;
        else
            *h = -atan(x / z);
        x = sqrt(x * x + z * z);
        if (x == 0.0)
            *p = (y < 0.0) ? -HALFPI : HALFPI;
        else
            *p = atan(y / x);
    }
}

void clean(char *str)
{
	int  i;
	char tempStr[100];

	// take off extension
	for (i = 0; i < strlen(str); i++)
	{
		if ((str[i] == '.') || (str[i] == 0x00))
		{
			str[i] = 0x00;
			break;
		}
	}

	// take of path
	for (i = strlen(str); i >= 0; i--)
	{
		if ((str[i] == '/') || (str[i] == '\\') || (str[i] == ':')) break;
	}

	i++;

	strcpy(tempStr, &str[i]);
	strcpy(str, tempStr);
}

void Sys_Strip(char *str)
{
    int i;

    for (i = 0; i < strlen(str); i++)
    {
        if ((str[i] == '.') || (str[i] == 0x00))
        {
            str[i] = 0x00;
            return;
        }
    }
}

int isTextureDir(char *path)
{
	char dirname[100];
	DWORD ret;

	strcpy(dirname, path);
    Sys_Strip(dirname);

	if ((ret = GetFileAttributes(dirname)) == 0xFFFFFFFF)
	{
		return(0);
	}

	if (ret & FILE_ATTRIBUTE_DIRECTORY)
	{
		printf("isdir %s\n", dirname);
		return(1);
	}
	else
	{
		printf("is not dir %s\n", dirname);
		return(0);
	}
}




/*
void InitModel(float newScale)
{
	memset (&model, 0, sizeof(model));

	// model.synctype = ST_RAND;	// default
	// model.numskins = skinCount;
	model.surfaceCount = 0;
	model.flags        = 0;

	// model.skinwidth  = skinWidth;
	// model.skinheight = skinHeight;

	framecount = 0;
	// skincount = 0;

	// scale    = 0;
	// scale_up = 1.0;

	scale    = newScale;
	scale_up = newScale;

	totsize = 0.0;

	VectorCopy (vec3_origin, adjust);
	VectorCopy (vec3_origin, mins);
	VectorCopy (vec3_origin, maxs);
	VectorCopy (vec3_origin, framesmins);
	VectorCopy (vec3_origin, framesmaxs);

#ifdef NEW
	degeneratetris = 0;
	// cdset = false;
	firstframe = 1;
#endif
}
*/

static void LWO_BuildUV(surface_t *surf, float x, float y, float z, float *newu, float *newv)
{
	float xTextureCenter, yTextureCenter, zTextureCenter;
	float xTextureSize, yTextureSize, zTextureSize;
	int   textureAxis, textureType;
	float lon, lat;

	float s, t;
	float u, v;

	xTextureCenter = surf->x_cent;
	yTextureCenter = surf->y_cent;
	zTextureCenter = surf->z_cent;

	xTextureSize = surf->x_size;
	yTextureSize = surf->y_size;
	zTextureSize = surf->z_size;

	textureAxis = surf->textureAxis;
	textureType = surf->textureType;

    x -= xTextureCenter;
    y -= yTextureCenter;
    z -= zTextureCenter;

    if (textureType == TT_PLANAR) 
	{
        s = (textureAxis == TA_X) ?  z / zTextureSize + .5 :  x / xTextureSize + .5;
        t = (textureAxis == TA_Y) ? -z / zTextureSize + .5 : -y / yTextureSize + .5;

//		if (tileMode)
//		{
//			 u = cfract(s, surf->surfaceName);
//             v = cfract(t, surf->surfaceName);
//		}
//		else
		{
            u = fract(s, surf->name);
            v = fract(t, surf->name);
		}
    }
	else if (textureType == TT_CYLINDRICAL) 
	{
        if (textureAxis == TA_X) 
		{
            xyztoh(z,x,-y,&lon);
            t = -x / xTextureSize + .5;
        }
        else if (textureAxis == TA_Y) 
		{
            xyztoh(-x,y,z,&lon);
            t = -y / yTextureSize + .5;
        }
        else 
		{
            xyztoh(-x,z,-y,&lon);
            t = -z / zTextureSize + .5;
        }

        lon = 1.0 - lon / TWOPI;

        u = cfract(lon, surf->name);
        v = cfract(t, surf->name);
    }
    else if (textureType == TT_SPHERICAL) 
	{
        if (textureAxis == TA_X)
            xyztohp(z,x,-y,&lon,&lat);
        else if (textureAxis == TA_Y)
            xyztohp(-x,y,z,&lon,&lat);
        else
            xyztohp(-x,z,-y,&lon,&lat);

        lon = 1.0 - lon / TWOPI;
        lat = .5 - lat / PI;

        u = fract(lon, surf->name);
        v = fract(lat, surf->name);
	}
	else
	{
		Error("Unknown textureType.");
	}

	*newu = u;
	*newv = v;
}

void LWO_BuildST(void)
{
	int i, j;
	surface_t *surf;
	lwpoint3d_t *p;
	float x, y, z;
	float u, v;

	// go through each surface and culculate the uv's for every point
	for (i = 0; i < surfacecount; i++)
	{
		surf = &lwsurface[i];

		for (j = 0; j < surf->pointCount; j++)
		{
			p = &surf->points[j];

			if (uvchunk)
			{
				u = p->uu;
				v = p->vv;
			}
			else
			{
			    x = p->v[0];
		        y = p->v[1];
		        z = p->v[2];

			    LWO_BuildUV(surf, x, y, z, &u, &v);
			}

			p->s = (surf->tWidth - 1) * u;
			p->t = (surf->tHeight - 1) * v;
		}
	}

	if (uvchunk)
	{
		printf("Used New Method to get uvs\n");
	}
}

void LWO_SwapYZ(void)
{
	int   i, j;
	float temp;
	lwpoint3d_t *p;
	surface_t   *surf;

	for (i = 0; i < surfacecount; i++)
	{
		surf = &lwsurface[i];

		for (j = 0; j < surf->pointCount; j++)
		{
			p = &surf->points[j];

			// swap y and z
			temp    = p->v[2];
			p->v[2] = p->v[1];
			p->v[1] = temp;
		}
	}
}

int surf_AddPoint(surface_t *surf, lwpoint3d_t *p)
{
	int i;

	// make sure this point is not already in list
	for (i = 0; i < surf->pointCount; i++)
		if (surf->points[i].id == p->id)
			return(i);

	// increase points
	if (surf->pointCount == 0)
		surf->points = malloc(sizeof(lwpoint3d_t) * (surf->pointCount + 1));
	else
		surf->points = realloc(surf->points, sizeof(lwpoint3d_t) * (surf->pointCount + 1));

	// ok add this point to point list
	surf->points[surf->pointCount] = *p;
	surf->pointCount++;

	return(surf->pointCount - 1);
}

void surf_AddPoly(surface_t *surf, lwpoly_t *p)
{
	int i, j;
	lwpoly_t newPoly;

	// we cannot add polys to a surface with no texture loaded for it
	if (!surf->fileName)
		Error("Attempted to add poly to a surface (%s) with no texture.", surf->name);

	newPoly = *p;

	// add all points of this tri to surface points list
	for (i = 0; i < 3; i++)
	{
		j = surf_AddPoint(surf, &point[p->p[i]]);
		newPoly.p[i] = (short) j;
	}

	if (surf->polyCount == 0)
		surf->polys = malloc(sizeof(lwpoly_t) * (surf->polyCount + 1));
	else
		surf->polys = realloc(surf->polys, sizeof(lwpoly_t) * (surf->polyCount + 1));


	// add this poly to our poly list
	surf->polys[surf->polyCount] = newPoly;

	surf->polyCount++;
}

void LWO_SurfacePolys (void)
{
	int i;
	lwpoly_t *p;
	int surfIndex;

	for (i = 0; i < numpolys; i++)
	{
		p = &poly[i];

		surfIndex = p->surface - 1;

		if ((surfIndex < 0) || (surfIndex >= surfacecount))
		{
			Error("SurfacePolys: No surface Number: %d", p->surface);
		}

		// add this poly to this surface
		surf_AddPoly(&lwsurface[surfIndex], p);
	}

}

static void LWO_LoadTextureDir(surface_t *surf, char *path)
{
	char             fullpath[200];
	char             loadPath[200];
	HANDLE           dirHandle;
	WIN32_FIND_DATA  findData;
	int found = 1;
	int tIndex;

	strcpy(fullpath, path);
	Sys_Strip(fullpath);

	dirHandle = FindFirstFile(fullpath, &findData);

	if (dirHandle == INVALID_HANDLE_VALUE)
	{
		Error("LoadTextureDir: FindFirstFile failed.");
		return;
	}

	tIndex = 0;

	while (found)
	{
		sprintf(loadPath, "%s/%s", fullpath, findData.cFileName);
		LWO_LoadTexture(surf, loadPath, tIndex);

		found = FindNextFile(dirHandle, &findData);
		tIndex++;
	}

	FindClose(dirHandle);
}

void LWO_LoadTextures (void)
{
	int        i;
	surface_t *surf;
	char       path[200];
	char       tempName[200];

	for (i = 0; i < surfacecount; i++)
	{
		surf = &lwsurface[i];

		if (!surf->fileName)
			continue;

		strcpy(tempName, surf->fileName);
		clean(tempName);

		sprintf(path, "%s/%s.bmp", dirname, tempName);

		// see if file exists in current directory
		if (FileTime(path) < 0)
		{
			// look in maps dir
			sprintf(path, "%s/maps/%s.bmp", dirname, tempName);

			if (FileTime(path) < 0)
			{
				Error("Unable to file file %s.bmp", tempName);
			}
		}

		if (isTextureDir(path))
		{
			LWO_LoadTextureDir(surf, path);
			return;
		}
		else
            LWO_LoadTexture(surf, path, 0);
	}
}

/*
================
LWO_OpenFile

Opens a .LWO file for reading and sets 
the file pointer to the first chunk
================
*/
void LWO_OpenFile (char *filename, byte **start, byte **end)
{
	byte	*plwo;

	if (!LoadFile (filename, &lwostart))
		Error ("Error opening %s\n", filename);
	
	numpolys = numpoints = 0;

	plwo = lwostart;

	if (strncmp(plwo, "FORM", 4))
		Error("No FORM id at start of file!\n");

	plwo += 4;
	formlength = BigLong( *(int *)plwo );

	plwo += 4;								
	lwoend = plwo + align(formlength);
	
    if (strncmp(plwo, "LWOB", 4))
		Error("Not an LWOB file.\n");

	plwo += 4;

	*start = plwo;
	*end = lwoend;
}

/*
================
LWO_CloseFile
================
*/
void LWO_CloseFile (void)
{
	if (lwostart == NULL)
		return;

	free (lwostart);
}

/*
================
LWO_LocateChunk
================
*/
int LWO_LocateChunk (byte *start, byte *end, char *chunkname)
{
	int		chunklength;
	byte	*c;
	char	name[5];
	
	c = start;

	while (c < end)
	{
		memcpy (name, c, 4);
		name[5] = 0x00;

		if (!memcmp (chunkname, c, 4))
			return c - start;

		c += 4;
		chunklength = BigLong(*(int *)c);
		c += 4;
		c += align (chunklength);
	}

	return -1;
}

/*
================
LWO_SurfaceForName
================
*/
int LWO_SurfaceNumForName (char *name)
{
	int i;

	for (i = 0; i < surfacecount; i++)
	{
		if (!strcmp(lwsurface[i].name, name))
			return(i);
	}

	return(-1);
}

/*
================
LWO_ReadPNTS
================
*/
void LWO_ReadPNTS (byte *buffer, int chunklength)
{
	int		i, j, count;

	count = 0;
	numpoints = chunklength / 12;

	// alloc memory for points
	point = (lwpoint3d_t *) malloc(numpoints * sizeof(lwpoint3d_t));

	for(i = 0; i < numpoints; i++)
	{
		// for sequencing when we load up frames
		point[i].id = (short) count;

		for(j = 0; j < 3; j++)
		{
			point[i].v[j] = BigFloat(*(float *)buffer);
			buffer += sizeof(float);
		}	

		count++;
	}

	if(count != numpoints)
		Error("GrabPoints: count != numpoints.\n");

}

/*
================
LWO_ReadSRFS
================
*/
void LWO_ReadSRFS (byte *buffer, int chunklength)
{
	byte	*chunkend;

	surfacecount = 0;

	chunkend = buffer + chunklength;

	// read the chunk
	while (buffer < chunkend)
	{
		if (surfacecount >= MAX_SURFACES)
			Error("Increase MAX_SURFACES");

		// zero out surface
		memset(&lwsurface[surfacecount], 0x00, sizeof(surface_t));

		lwsurface[surfacecount].name = strdup((char *) buffer);

		if (SkipSurface(lwsurface[surfacecount].name))
		{
			qprintf("SRFS |%s|, Skipping...\n");
			lwsurface[surfacecount].skip = 1;
		}
		else
		    qprintf("SRFS |%s|\n", lwsurface[surfacecount].name);

		surfacecount++;

		buffer += strlen((char *) buffer) + 1;

		if (!*buffer) 
			buffer++;
	}
}

/*
================
LWO_ReadPOLS
================
*/
void LWO_ReadPOLS (byte *buffer, int chunklength)
{
	int		i, j, count;
	short	numverts;
	byte	*chunkend;
	
	chunkend = buffer + chunklength;

	poly = (lwpoly_t *) malloc(chunklength);

	for(i = 0, count = 0; buffer < chunkend; i++, count++)
	{
		// for sequencing
		poly[i].id = (short) count;

		numverts = BigShort(*(short *) buffer);
		buffer += sizeof(short);

		if (numverts != 3)
			Error("Poly has more than 3 verts\n");

		for(j = 0; j < numverts; j++)
		{
			poly[i].p[j] = BigShort(*(short *)buffer);
			buffer += sizeof(short);
		}		

		poly[i].surface = BigShort(*(short *)buffer);
		buffer += sizeof(short);
	}

	numpolys = count;
}

/*
================
LWO_ReadCTEX

subchunk of SURF
================
*/
void LWO_ReadCTEX (byte *buffer, int surfnum)
{
	if (!memcmp(buffer, "Spherical", 9))
		lwsurface[surfnum].textureType = TT_SPHERICAL;
	else if (!memcmp(buffer, "Cylindrical", 11))
		lwsurface[surfnum].textureType = TT_CYLINDRICAL;
	else
		lwsurface[surfnum].textureType = TT_PLANAR;

	qprintf("SURF CTEX: %s\n", buffer);
}

/*
================
LWO_ReadTIMG

subchunk of SURF
================
*/
void LWO_ReadTIMG (byte *buffer, int surfnum)
{
	lwsurface[surfnum].fileName = strdup((char *) buffer);
	qprintf("SURF TIMG: %s\n", buffer);
}

/*
================
LWO_ReadTFLG

subchunk of SURF
================
*/
void LWO_ReadTFLG (byte *buffer, int surfnum)
{
	short	flags;

	flags = BigShort(*(short *) buffer);

	if (flags & 0x0002) 
		lwsurface[surfnum].textureAxis = TA_Y;
	else if (flags & 0x0004) 
		lwsurface[surfnum].textureAxis = TA_Z;
	else                     
		lwsurface[surfnum].textureAxis = TA_X;

	qprintf("SURF TFLG: %x\n", flags);
}

/*
================
LWO_ReadTSIZ

subchunk of SURF
================
*/
void LWO_ReadTSIZ (byte *buffer, int surfnum)
{
    lwsurface[surfnum].x_size = BigFloat(*(float *) buffer);
	buffer += 4;

	lwsurface[surfnum].y_size = BigFloat(*(float *) buffer);
	buffer += 4;

	lwsurface[surfnum].z_size = BigFloat(*(float *) buffer);
	buffer += 4;

	qprintf("SURF TSIZ: %f %f %f\n",
        lwsurface[surfnum].x_size, 
		lwsurface[surfnum].y_size, 
		lwsurface[surfnum].z_size);
}

/*
================
LWO_ReadTCTR

subchunk of SURF
================
*/
void LWO_ReadTCTR (byte *buffer, int surfnum)
{
    lwsurface[surfnum].x_cent = BigFloat(*(float *) buffer);
	buffer += 4;

	lwsurface[surfnum].y_cent = BigFloat(*(float *) buffer);
	buffer += 4;

	lwsurface[surfnum].z_cent = BigFloat(*(float *) buffer);
	buffer += 4;

	qprintf("SURF TCTR: %f %f %f\n",
        lwsurface[surfnum].x_cent, 
		lwsurface[surfnum].y_cent, 
		lwsurface[surfnum].z_cent);
}

/*
================
LWO_ReadSURF
================
*/
void LWO_ReadSURF (byte *buffer, int chunklength)
{
	int		subchunklength, surfnum;
	byte	*chunkend;
	char	*name, subchunkname[5];

	chunkend = buffer + chunklength;

	name = buffer;
    qprintf("SURF Name: %s, Len: %d\n", name, chunklength);
	buffer += strlen(name) + 1;

	surfnum = LWO_SurfaceNumForName (name);
	if (surfnum == -1)
		Error("LWO_ReadSurf: Unable to find %s in surface table\n", name);

	if (!*buffer) 
		buffer++;

	while (buffer < chunkend)
	{
		memcpy(subchunkname, buffer, 4); 
		subchunkname[4] = 0x00;
		buffer += 4;

		subchunklength = BigShort( *(short *) buffer);
		buffer += sizeof(short);

		if (!strcmp(subchunkname, "CTEX"))
			LWO_ReadCTEX (buffer, surfnum);
		else if (!strcmp(subchunkname, "TIMG"))
			LWO_ReadTIMG (buffer, surfnum);
		else if (!strcmp(subchunkname, "TFLG"))
			LWO_ReadTFLG (buffer, surfnum);
		else if (!strcmp(subchunkname, "TSIZ"))
			LWO_ReadTSIZ (buffer, surfnum);
		else if (!strcmp(subchunkname, "TCTR"))
			LWO_ReadTCTR (buffer, surfnum);

		buffer += subchunklength;
	}
}

/*
================
LWO_ReadUVIM
================
*/
void LWO_ReadUVIM (byte *buffer, int chunklength)
{
	int		surfnum;
	char	*filename;
	byte	*chunkend;

	chunkend = buffer + chunklength;

	surfnum = 0;

	while (buffer < chunkend)
	{
		filename = buffer;
		qprintf("Surface %d Filename: |%s|\n", surfnum, filename);

		if (surfnum >= surfacecount)
			Error("GrabUVIM: Invalid surface number\n");

		if (!strcmpi(filename, "NULL"))
			lwsurface[surfnum].fileName = NULL;
		else
			lwsurface[surfnum].fileName = strdup(filename);

		buffer += strlen(filename) + 1;
		if (!*buffer) 
			buffer++;

		surfnum++;
	}
}

/*
================
LWO_ReadUVCV
================
*/
void LWO_ReadUVCV (byte *buffer, int chunklength)
{
	int		j, pid, pointindex, numverts;
	float	u, v;
	byte	*chunkend;

	chunkend = buffer + chunklength;

	if (!numpolys)
		Error("Polys chunk must come before UVCV chunk.");

	while (buffer < chunkend)
	{
		pid = BigLong(*(int *) buffer);
		buffer += sizeof(int);

		numverts = BigLong(*(int *) buffer);
		buffer += sizeof(int);

		if (numverts != 3)
			Error("GrabUVCV: Got polygon with %d points.", numverts);

		if (pid >= numpolys)
			Error("GrabUVCV: pid %d >= numploys %d\n", pid, numpolys);

		for(j = 0; j < numverts; j++)
		{
			// point[i].v[j] = BigFloat(*(float *)ptr);
			u = BigFloat(*(float *) buffer);
			buffer += sizeof(float);

			v = BigFloat(*(float *) buffer);
			buffer += sizeof(float);

			// user value
			buffer += 4;

			// get index into point array
			pointindex = poly[pid].p[j];

			if (pointindex >= numpoints)
				Error("GrabUVCV: pointindex >= numpoints\n");

			point[pointindex].uu = u;
			point[pointindex].vv = v;
		}		
	}

	uvchunk = 1;
}

