void ITR3DMImport::splitX(Poly* poly,PolyList* polyList)
{
   Vector<Point3F> points;
   Point3F iPoint;

   int v1 = poly->vertexList.size() - 1;
   for (int v2 = 0; v2 < poly->vertexList.size(); v2++) {
      Poly::Vertex* p1 = &poly->vertexList[v1];
      Poly::Vertex* p2 = &poly->vertexList[v2];

      if (p1->texture.x <= float(splitDist - 1) && p2->texture.x > float(splitDist - 1) ||
          p2->texture.x <= float(splitDist - 1) && p1->texture.x > float(splitDist - 1)) {
         Point3F vec;
         vec  = p2->point;
         vec -= p1->point;
         vec *= (float(splitDist - 1) - p1->texture.x) / (p2->texture.x - p1->texture.x);
         vec += p1->point;
         points.push_back(vec);
      }
      if (p1->texture.x < float(splitDist - 1))
         iPoint = p1->point;
      v1 = v2;
   }

   // Build plane and split the poly
   if (points.size() > 1) {
      Point3F vec = points[0];
      vec -= points[1];
      Point3F normal;
      m_cross(vec,poly->plane,&normal);
      TPlaneF plane(points[0],normal);
      if (plane.whichSide(iPoint) != TPlaneF::Inside)
         plane.neg();

      Poly tmp;
      Poly* npoly = new Poly;
      poly->split(plane,&tmp,npoly);
      poly->vertexList    = tmp.vertexList;

      npoly->plane = poly->plane;
      npoly->textureOffset = poly->textureOffset;
      npoly->material = poly->material;
      npoly->volumeMask = poly->volumeMask;
      npoly->textureScaleShift = poly->textureScaleShift;
      npoly->applyAmbient = poly->applyAmbient;
      polyList->push_back(npoly);

		// Normalize after the previous information copy, 
		// normalize alters some of the poly's fields.
      normalizeTexture(poly);
      normalizeTexture(npoly);
   }
}
//----------------------------------------------------------------------------
// ** Note:  The vertex and plane normals values are swapped
// around to align with our normal viewing axis.
//
void ITR3DMImport::import(const char* file,PolyList* polyList)
{
   int version = 0;
   
   FILE* fp = fopen(file,"r");
   char buff[256];
   AssertFatal(fp != 0,"ITR3DMImport::import: Error openning file");

   // Load the vertex list - or the version number...
   do
      fgets(buff,256,fp);
   while( strcmp(buff,"VERTICES\n") && strcmp( buff, "VERSION\n" ) );
   
   // check if we got verion
   if( !strcmp( buff, "VERSION\n" ) )
   {
      fscanf( fp, "%d\n", &version );   
      
      // get to the vertices
      do
         fgets(buff,256,fp);
      while( strcmp(buff,"VERTICES\n") );
   }
   
   int vertexCount;
   fscanf(fp,"%d\n",&vertexCount);

   Vector<Point3F> pointList;
   pointList.setSize(vertexCount);
   for (int i = 0; i < vertexCount; i++) {
      Point3F pp;
      // Convert to our coordinate system.
      fscanf(fp,"%f %f %f\n",&pp.x,&pp.z,&pp.y);
      pp *= scale;
      pointList[i] = snap(pp);
   }

   // Load the faces
   do
      fgets(buff,256,fp);
   while (strcmp(buff,"POLYGONS\n"));
   int polyCount;
   fscanf(fp,"%d\n",&polyCount);
	int degeneratePoly = 0;

   polyList->reserve(polyCount);
   for (int i = 0; i < polyCount; i++) {
      Poly* poly = new Poly;
      fgets(buff,256,fp);
      poly->material = atoi(buff);

      int count;
      fscanf(fp,"%d\n",&count);
      if (count < 3) {
			degeneratePoly++;
         delete poly;
         continue;
      }
      poly->vertexList.setSize(count);

      // DMM - Scan in texture size and offset.  (New in Zed);
      fscanf(fp, "%d %d\n", &poly->textureSize.x, &poly->textureSize.y);
      fscanf(fp, "%d %d\n", &poly->textureOffset.x, &poly->textureOffset.y);
      
      // grab the texture scaling factor
      int textureScaleShift;
      fscanf(fp, "%d\n", &textureScaleShift );
      poly->textureScaleShift = textureScaleShift;

      // check if there is a ambient flag ( any version will have this... )
      if( version )
      {
         int tmp;
         fscanf( fp, "%d\n", &tmp );
         poly->applyAmbient = bool( tmp );
      }
      
		// Vertices
      for (int i = 0; i < count; i++) {
         int index;
         fscanf(fp,"%d",&index);
         poly->vertexList[i].point = pointList[index];
         poly->vertexList[i].colinear = false;
      }
      fscanf(fp,"\n",buff);

		// Texture coor.
      for (int i = 0; i < count; i++) {
         Point2F& texture = poly->vertexList[i].texture;
         fscanf(fp, "%f %f", &texture.x,&texture.y);
      }
      fscanf(fp,"\n",buff);

		// Volume mask
      fscanf(fp,"%lu\n",&poly->volumeMask);

#if 1
      // Read in the plane exported by zed
		fscanf(fp,"%f %f %f %f\n",
			&poly->plane.x, &poly->plane.z, &poly->plane.y, &poly->plane.d);
		poly->plane.d *= scale;

		// Use the plane class to make sure the polygon
		// is not degenerate.
		TPlaneF tmp;
      Point3F* vl[MaxPolyVertex];
      AssertFatal(poly->vertexList.size() <= MaxPolyVertex,
         "ITR3DMImport::import: Poly exceeded max vertex size");
      for (int v = 0; v < poly->vertexList.size(); v++)
         vl[v] = &poly->vertexList[v].point;
      if (!tmp.set(poly->vertexList.size(),vl)) {
			degeneratePoly++;
         delete poly;
         continue;
      }
#else
		// Build the plane using the vertices
      Point3F* vl[MaxPolyVertex];
      AssertFatal(poly->vertexList.size() <= MaxPolyVertex,
         "ITR3DMImport::import: Poly exceeded max vertex size");
      for (int v = 0; v < poly->vertexList.size(); v++)
         vl[v] = &poly->vertexList[v].point;
      if (!poly->plane.set(poly->vertexList.size(),vl)) {
			degeneratePoly++;
         delete poly;
         continue;
      }
#endif

      // If we have bad texture coordinates, let's try re-boxmapping
		// first.
      if (poly->textureSize.x == 0 || poly->textureSize.y == 0) {
         printf("   Degenerate poly textures (%d)\n",i);
         boxMap(poly);
      }
      normalizeTexture(poly);
      if (poly->textureSize.x == 0 || poly->textureSize.y == 0) {
			degeneratePoly++;
         delete poly;
         continue;
      }

		//
      polyList->push_back(poly);
   }

	if (degeneratePoly)
	   printf("\n   *****: %d Degenerate polys dropped\n   ",degeneratePoly);
   fclose(fp);
}  
// function that generates the 2D noise texture
void TextureManager::generateNoiseTexture(void)
{
	float *largeNoiseData1, *largeNoiseData2;
	float *filterKernel;
	// With copied left-right
	largeNoiseData1 = new float [TM_NOISE_TEXTURE_SIZE * TM_NOISE_TEXTURE_SIZE * 4 * 2 * 2];
	largeNoiseData2 = new float [TM_NOISE_TEXTURE_SIZE * TM_NOISE_TEXTURE_SIZE * 4 * 2 * 2];
	filterKernel = new float [TM_FILTER_KERNEL_SIZE];

	// Generate white noise baseline
	for (int i = 0; i < TM_NOISE_TEXTURE_SIZE * TM_NOISE_TEXTURE_SIZE * 4; i++)
	{
		noiseData[i] = frand();
	}

	// copy noise baseline in repeated border buffer
	for (int y = 0; y < TM_NOISE_TEXTURE_SIZE * 2; y++)
	{
		for (int x = 0; x < TM_NOISE_TEXTURE_SIZE * 2; x++)
		{
			int srcIdx = (y % TM_NOISE_TEXTURE_SIZE) * TM_NOISE_TEXTURE_SIZE * 4
					   + (x % TM_NOISE_TEXTURE_SIZE) * 4;
			int dstIdx = y * TM_NOISE_TEXTURE_SIZE * 4 * 2 + x * 4;
			largeNoiseData1[dstIdx++] = noiseData[srcIdx++];
			largeNoiseData1[dstIdx++] = noiseData[srcIdx++];
			largeNoiseData1[dstIdx++] = noiseData[srcIdx++];
			largeNoiseData1[dstIdx++] = noiseData[srcIdx++];
		}
	}

	// genereate filter kernel
	for (int i = 0; i < TM_FILTER_KERNEL_SIZE; i++)
	{
		float position = (float)i / (float)TM_FILTER_KERNEL_SIZE * 2.0f * 3.1415926f;
		filterKernel[i] = 1.0f - (float)cos(position);
		//filterKernel[i] = 1.0f;
	}
	normalizeKernel(filterKernel, TM_FILTER_KERNEL_SIZE);

	float *curSrc = largeNoiseData1;
	float *curDst = largeNoiseData2;
	for (int mode = 0; mode < 2; mode++)
	{
		for (int y = 0; y < TM_NOISE_TEXTURE_SIZE + TM_FILTER_KERNEL_SIZE; y++)
		{
			for (int x = 0; x < TM_NOISE_TEXTURE_SIZE; x++)
			{
				float filtered[4];
				filtered[0] = 0.0f;
				filtered[1] = 0.0f;
				filtered[2] = 0.0f;
				filtered[3] = 0.0f;

				int srcIdx = y * TM_NOISE_TEXTURE_SIZE * 2 * 4 + x * 4;
				for (int xp = 0; xp < TM_FILTER_KERNEL_SIZE; xp++)
				{
					filtered[0] += curSrc[srcIdx++] * filterKernel[xp];
					filtered[1] += curSrc[srcIdx++] * filterKernel[xp];
					filtered[2] += curSrc[srcIdx++] * filterKernel[xp];
					filtered[3] += curSrc[srcIdx++] * filterKernel[xp];
				}

				int dstIdx = x * TM_NOISE_TEXTURE_SIZE * 2 * 4 + y * 4;
				curDst[dstIdx] = filtered[0];
				curDst[dstIdx+1] = filtered[1];
				curDst[dstIdx+2] = filtered[2];
				curDst[dstIdx+3] = filtered[3];
			}
		}

		curSrc = largeNoiseData2;
		curDst = largeNoiseData1;
	}

	// copy back to small array
	for (int y = 0; y < TM_NOISE_TEXTURE_SIZE; y++)
	{
		for (int x = 0; x < TM_NOISE_TEXTURE_SIZE; x++)
		{
			int dstIdx = y * TM_NOISE_TEXTURE_SIZE * 4 + x * 4;
			int srcIdx = y * TM_NOISE_TEXTURE_SIZE * 4 * 2 + x * 4;

			noiseData[dstIdx++] = (float)largeNoiseData1[srcIdx++];
			noiseData[dstIdx++] = (float)largeNoiseData1[srcIdx++];
			noiseData[dstIdx++] = (float)largeNoiseData1[srcIdx++];
			noiseData[dstIdx++] = (float)largeNoiseData1[srcIdx++];
		}
	}

	// normalize small Array
	normalizeTexture(noiseData, TM_NOISE_TEXTURE_SIZE * TM_NOISE_TEXTURE_SIZE);

	delete [] largeNoiseData1;
	delete [] largeNoiseData2;
	delete [] filterKernel;

	makeIntTexture();
}