#if !defined(MLR_MLRCLIPTRICK_HPP)
	#include <MLR\MLRClipTrick.hpp>
#endif

extern DWORD gEnableTextureSort, gShowClippedPolys, gEnableSimpleLight;
extern WORD *indexOffset;	// [MidLevelRenderer::Max_Number_Vertices_Per_Mesh]
extern DWORD Trivial_Accepts;

#define HUNT_CLIP_ERROR 0

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	CLASSNAME::TransformNoClip(Matrix4D *mat, GOSVertexPool *vt, FogData *fogData, DWORD paintMeColor, bool db)
{
	Check_Object(this);
	Check_Object(vt);

#ifdef I_SAY_YES_TO_COLOR
	#ifdef I_SAY_YES_TO_LIGHTING
	if(actualColors==NULL || actualColors->GetLength() == 0 || gEnableSimpleLight>0)
	{
		CLASSNAMENOCOLOR::TransformNoClip(mat, vt, fogData, paintMeColor, db);
		return;
	}
	#else
	if(colors.GetLength()==0)
	{
		CLASSNAMENOCOLOR::TransformNoClip(mat, vt, fogData, paintMeColor, db);
		return;
	}
	#endif
#endif

	MLR_RENDER("Transform::NoClip::MLRPrimitiveClipping");
	Start_Timer(Transform_Time);

	Verify(index.GetLength() > 0);

	WORD stride;
	bool textureAnimation = false;
	Scalar deltaU=0.0f, deltaV=0.0f;
	
	if(state.GetTextureHandle())
	{
		MLRTexture *texture = (*MLRTexturePool::Instance)[state.GetTextureHandle()];

		if(texture!=NULL)
		{
			MLRState::SetCurrentTextureSize(texture->GetImage()->GetWidth());

			textureAnimation = texture->GetAnimateTexture();
			if(textureAnimation)
			{
				Stuff::AffineMatrix4D *textureMatrix = texture->GetTextureMatrix();
				deltaU = (*textureMatrix)(3, 0);
				deltaV = (*textureMatrix)(3, 1);
			}
		}
	}

	int i, j, k, len = lengths.GetLength();

#ifdef I_SAY_YES_TO_DUAL_TEXTURES
	int tex2count = 0;
#endif

	int numVertices = GetNumVertices();
	if (numVertices>Limits::Max_Number_Vertices_Per_Mesh)
	{
		numVertices = Limits::Max_Number_Vertices_Per_Mesh;
	}

	gos_vertices = vt->GetActualVertexPool(db);
	numGOSVertices = 0;

	Verify(index.GetLength() > 0);

	if(visibleIndexedVerticesKey == false)
	{
		FindVisibleVertices();
	}

	for(j=0,stride=0;j<numVertices;j++)
	{
		if((*visibleIndexedVertices)[j] == 0)
		{
			stride++;
		}
		else
		{
#ifdef LAB_ONLY
			TransformedVertices++;
#endif

			if(db==false)
			{
				Verify (vt->GetLast() + numGOSVertices < Limits::Max_Size_Of_Vertex_Buffer);
			}
			else
			{
				Verify (numGOSVertices < Limits::Max_Size_Of_Vertex_Buffer);
			}

			indexOffset[j] = (WORD)(j - stride);

			gos_vertices[numGOSVertices].GOSTransformNoClip(
				coords[j],
				*mat,
				&texCoords[j][0]
#if FOG_HACK
				, (state.GetFogMode() != 0)
#endif
			);

//			gos_vertices[numGOSVertices].u = texCoords[j][0];
//			gos_vertices[numGOSVertices].v = texCoords[j][1];

#ifdef I_SAY_YES_TO_COLOR
	#ifdef I_SAY_YES_TO_LIGHTING
		#if COLOR_AS_DWORD
			gos_vertices[numGOSVertices].argb = (*actualColors)[j];
		#else
			gos_vertices[numGOSVertices].argb = GOSCopyColor(&(*actualColors)[j]);
		#endif
	#else
		#if COLOR_AS_DWORD
			gos_vertices[numGOSVertices].argb = colors[j];
		#else
			gos_vertices[numGOSVertices].argb = GOSCopyColor(&colors[j]);
		#endif
	#endif
#else
			gos_vertices[numGOSVertices].argb = paintMeColor;
#endif

#if 1
			if(fogData!=NULL)
			{
				*((BYTE *)&gos_vertices[numGOSVertices].frgb + 3) = fogData->FogVertex(&coords[j]);
			}
#else
			if(channelUse & 1<<FogChannel)
			{
				*((BYTE *)&gos_vertices[numGOSVertices].frgb + 3) = (*extraChannels[2*FogChannel])[j];
			}
#endif
			if(textureAnimation)
			{
				gos_vertices[numGOSVertices].u += deltaU;
				gos_vertices[numGOSVertices].v += deltaV;
			}

#ifdef I_SAY_YES_TO_DUAL_TEXTURES
			(*texCoords2)[tex2count++] = texCoords[numVertices + j];
#endif
			numGOSVertices++;
		}
	}

#ifdef LAB_ONLY
	Set_Statistic(NonClippedVertices, NonClippedVertices+numGOSVertices);
#endif

	Check_Object(vt);

#ifdef I_SAY_YES_TO_DUAL_TEXTURES
	Verify (tex2count == numGOSVertices);
	if(db==false)
	{
		Verify (vt->GetLast() + 2*numGOSVertices < vt->GetLength());
	}
	else
	{
		Verify (numGOSVertices < Limits::Max_Size_Of_Vertex_Buffer);
	}

	if(state2.GetTextureHandle())
	{
		MLRTexture *texture = (*MLRTexturePool::Instance)[state.GetTextureHandle()];
		textureAnimation = texture->GetAnimateTexture();
		if(textureAnimation)
		{
			Stuff::AffineMatrix4D *textureMatrix = texture->GetTextureMatrix();
			deltaU = (*textureMatrix)(3, 0);
			deltaV = (*textureMatrix)(3, 1);
		}
	}

	memcpy(gos_vertices + numGOSVertices, gos_vertices, numGOSVertices * sizeof(GOSVertex));

	if(textureAnimation)
	{
		for(i=0,j=numGOSVertices;i<numGOSVertices;i++,j++)
		{
			gos_vertices[j].u = (*texCoords2)[i][0] + deltaU;
			gos_vertices[j].v = (*texCoords2)[i][1] + deltaV;
		}
	}
	else
	{
		for(i=0,j=numGOSVertices;i<numGOSVertices;i++,j++)
		{
			gos_vertices[j].u = (*texCoords2)[i][0];
			gos_vertices[j].v = (*texCoords2)[i][1];
		}
	}

	if(db==false)
	{
		vt->Increase(2*numGOSVertices);
	}
#else
	#ifdef I_SAY_YES_TO_DETAIL_TEXTURES
		if(db==false)
		{
			Verify (vt->GetLast() + 2*numGOSVertices < vt->GetLength());
		}
		else
		{
			Verify (numGOSVertices < Limits::Max_Size_Of_Vertex_Buffer);
		}

		memcpy(gos_vertices + numGOSVertices, gos_vertices, numGOSVertices * sizeof(GOSVertex));

		for(i=0,j=numGOSVertices;i<numGOSVertices;i++,j++)
		{
			gos_vertices[j].u = gos_vertices[i].u*xScale + xOffset;
			gos_vertices[j].v = gos_vertices[i].v*yScale + yOffset;
		}

		if(db==false)
		{
			vt->Increase(2*numGOSVertices);
		}
	#else
		if(db==false)
		{
			vt->Increase(numGOSVertices);
		}
	#endif
#endif

	gos_indices = vt->GetActualIndexPool(db);
	numGOSIndices = 0;

	int ngi = 0;
	for(i=0,j=0;i<len;j+=stride,i++)
	{
		stride = lengths[i];

		Verify(stride >= 3);

		if((*testList)[i] == 0)
		{
			continue;
		}

		for(k=1;k<stride-1;k++)
		{
			if(db==false)
			{
				Verify((vt->GetLastIndex() + 3 + numGOSIndices) < vt->GetLength());
			}
			else
			{
				Verify(3 + numGOSIndices < Limits::Max_Size_Of_Index_Buffer);
			}

			gos_indices[ngi++] = indexOffset[index[j]];
			gos_indices[ngi++] = indexOffset[index[j+1+k]];
			gos_indices[ngi++] = indexOffset[index[j+k]];
		}
	}
	numGOSIndices = (WORD)ngi;

	Check_Object(vt);
	if(db==false)
	{
		vt->IncreaseIndex(numGOSIndices);
	}

	Stop_Timer(Transform_Time);

	visible = numGOSVertices ? (BYTE)1 : (BYTE)0;
}

static MLRClippingState theAnd, theOr, theTest;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Now it gets serious
int
	CLASSNAME::TransformAndClip(Matrix4D *mat, MLRClippingState clippingFlags, GOSVertexPool *vt, FogData *fogData, DWORD paintMeColor, bool db)
{
#ifdef I_SAY_YES_TO_COLOR
	#ifdef I_SAY_YES_TO_LIGHTING
	if(actualColors==NULL || actualColors->GetLength() == 0 || gEnableSimpleLight>0)
	{
		return CLASSNAMENOCOLOR::TransformAndClip(mat, clippingFlags, vt, fogData, paintMeColor, db);
	}
	#else
	if(colors.GetLength()==0)
	{
		return CLASSNAMENOCOLOR::TransformAndClip(mat, clippingFlags, vt, fogData, paintMeColor, db);
	}
	#endif
#endif
	WORD l;
	int i, j, k, ret = 0;
	int len;


	{
		MLR_RENDER("Transform::Clip::MLRPrimitiveClipping");
		Start_Timer(Transform_Time);

		Verify(clippingFlags.GetClippingState() != 0);

		//
		//--------------------------------------
		// See if we don't have to draw anything
		//--------------------------------------
		//
		if(lengths.GetLength() <= 0)
		{
			visible = 0;

			Stop_Timer(Transform_Time);

			return visible;
		}

		Verify(index.GetLength() > 0);

	#ifdef I_SAY_YES_TO_TERRAIN2
		#ifdef CALCULATEuvONtheFLY
		Vector2DScalar terrainUV;
		#endif	//	CALCULATEuvONtheFLY
	#endif	//	I_SAY_YES_TO_TERRAIN2

		len = coords.GetLength();

		if(visibleIndexedVerticesKey == false)
		{
			FindVisibleVertices();
		}

		Stuff::Vector4D *v4d = transformedCoords->GetData();
		const Stuff::Point3D *p3d = coords.GetData();
		int *cs = (int *)clipPerVertex->GetData();
		BYTE *viv = visibleIndexedVertices->GetData();

		if(fogData!=NULL)
		{
			for(i=0;i<len;i++,p3d++,v4d++,cs++,viv++)
			{
				if(*viv == 0)
				{
					continue;
				}
				*viv = 0;

				v4d->MultiplySetClip(*p3d, *mat, cs);
				(*extraChannels[2*FogChannel])[i] = fogData->FogVertex(p3d);

		#ifdef LAB_ONLY
				Set_Statistic(TransformedVertices, TransformedVertices+1);
		#endif	//	LAB_ONLY

		//
		//--------------------------------------------------------
		// I claims all vertices are in. lets check it. who knows
		//--------------------------------------------------------
		//
		#ifdef LAB_ONLY
				if( (*cs)==0)
				{
		#if defined(_ARMOR)
					if(ArmorLevel > 3)
					{
		//
		//--------------------------------------------------------
		// I claims all vertices are in. lets check it. who knows
		//--------------------------------------------------------
		//
						Verify(v4d->x >= 0.0f && v4d->x <= v4d->w );
						Verify(v4d->y >= 0.0f && v4d->y <= v4d->w );
						Verify(v4d->z >= 0.0f && v4d->z <= v4d->w );
					}
		#endif	//	_ARMOR
					Set_Statistic(NonClippedVertices, NonClippedVertices+1);
				}
				else
				{
					Set_Statistic(ClippedVertices, ClippedVertices+1);
				}
		#endif	//	LAB_ONLY
			}
		}
		else
		{
			for(i=0;i<len;i++,p3d++,v4d++,cs++,viv++)
			{
				if(*viv == 0)
				{
					continue;
				}
				*viv = 0;

				v4d->MultiplySetClip(*p3d, *mat, cs);

		#ifdef LAB_ONLY
				Set_Statistic(TransformedVertices, TransformedVertices+1);
		#endif	//	LAB_ONLY

		//
		//--------------------------------------------------------
		// I claims all vertices are in. lets check it. who knows
		//--------------------------------------------------------
		//
		#ifdef LAB_ONLY
				if( (*cs)==0)
				{
		#if defined(_ARMOR)
					if(ArmorLevel > 3)
					{
		//
		//--------------------------------------------------------
		// I claims all vertices are in. lets check it. who knows
		//--------------------------------------------------------
		//
						Verify(v4d->x >= 0.0f && v4d->x <= v4d->w );
						Verify(v4d->y >= 0.0f && v4d->y <= v4d->w );
						Verify(v4d->z >= 0.0f && v4d->z <= v4d->w );
					}
		#endif	//	_ARMOR
					Set_Statistic(NonClippedVertices, NonClippedVertices+1);
				}
				else
				{
					Set_Statistic(ClippedVertices, ClippedVertices+1);
				}
		#endif	//	LAB_ONLY
			}
		}
		Stop_Timer(Transform_Time);
	}

	MLR_RENDER("Clipping::MLRPrimitiveClipping");
	Start_Timer(Clipping_Time);

	int mask, end, k0, k1, ct=0;
	Scalar a=0.0f;
	WORD stride;
	len = lengths.GetLength();
//	Scalar bc0=0.0f, bc1=0.0f;

	bool textureAnimation = false;
	Scalar deltaU=0.0f, deltaV=0.0f;
	
	if(state.GetTextureHandle())
	{
		MLRTexture *texture = (*MLRTexturePool::Instance)[state.GetTextureHandle()];

		if(texture!=NULL)
		{
			MLRState::SetCurrentTextureSize(texture->GetImage()->GetWidth());
		
			textureAnimation = texture->GetAnimateTexture();
			if(textureAnimation)
			{
				Stuff::AffineMatrix4D *textureMatrix = texture->GetTextureMatrix();
				deltaU = (*textureMatrix)(3, 0);
				deltaV = (*textureMatrix)(3, 1);
			}
		}
	}

#ifdef I_SAY_YES_TO_DUAL_TEXTURES
	bool textureAnimation2 = false;
	Scalar deltaU2=0.0f, deltaV2=0.0f;
	
	if(state2.GetTextureHandle())
	{
		MLRTexture *texture = (*MLRTexturePool::Instance)[state.GetTextureHandle()];
		textureAnimation2 = texture->GetAnimateTexture();
		if(textureAnimation2)
		{
			Stuff::AffineMatrix4D *textureMatrix = texture->GetTextureMatrix();
			deltaU2 = (*textureMatrix)(3, 0);
			deltaV2 = (*textureMatrix)(3, 1);
		}
	}
#endif

#ifdef I_SAY_YES_TO_DUAL_TEXTURES
	int tex2count = 0;
	int numVertices = GetNumVertices();
	if (numVertices>Limits::Max_Number_Vertices_Per_Mesh)
	{
		numVertices = Limits::Max_Number_Vertices_Per_Mesh;
	}
#endif

	int	myNumberUsedClipVertex, myNumberUsedClipIndex, myNumberUsedClipLength;

	myNumberUsedClipVertex = 0;
	myNumberUsedClipIndex = 0;
	myNumberUsedClipLength = 0;

	Verify(index.GetLength() > 0);
	
	if(visibleIndexedVerticesKey == false)
	{
		FindVisibleVertices();
	}

	//
	//------------------------
	// Handle the indexed case
	//------------------------
	//

	//	initialize visibleIndexedVertices
	memset(visibleIndexedVertices->GetData(), 0, visibleIndexedVertices->GetSize());

	//
	//-----------------------------------------------------------------
	// Step through each polygon, making sure that we don't try to clip
	// backfaced polygons
	//-----------------------------------------------------------------
	//
	for(i=0,j=0;i<len;i++)
	{
		stride = lengths[i];

		if((*testList)[i] == 0)
		{
			j += stride;
			continue;
		}

		//
		//---------------------------------------------------------------
		// Test each vertex of the polygon against the allowed clipping
		// planes, and accumulate status for which planes always clip and
		// which planes clipped at least once
		//---------------------------------------------------------------
		//
		theAnd.SetClippingState(0x3f);
		theOr.SetClippingState(0);
		end = j+stride;
		
		for(k=j;k<end;k++)
		{
			theAnd &= (*clipPerVertex)[index[k]];

			theOr |= (*clipPerVertex)[index[k]];
		}

		//
		//-------------------------------------------------------------------
		// If any bit is set for all vertices, then the polygon is completely
		// outside the viewing space and we don't have to draw it.  On the
		// other hand, if no bits at all were ever set, we can do a trivial
		// accept of the polygon
		//-------------------------------------------------------------------
		//
		if (theAnd != 0)
		{
			(*testList)[i] = 0;
#ifdef LAB_ONLY
			Set_Statistic(PolysClippedButOutside, PolysClippedButOutside+1);
#endif
		}
		else if (theOr == 0)
		{
			ret++;
			for(k=j;k<end;k++)
			{
				(*visibleIndexedVertices)[index[k]] = 1;
			}
#ifdef LAB_ONLY
			Set_Statistic(PolysClippedButInside, PolysClippedButInside+1);
#endif
		}

		//
		//-----------------------------------------------------------------
		// It is not a trivial case, so we must now do real clipping on the
		// polygon
		//-----------------------------------------------------------------
		//
		else
		{
			WORD numberVerticesPerPolygon = 0;

			//
			//---------------------------------------------------------------
			// Handle the case of a single clipping plane by stepping through
			// the vertices and finding the edge it originates
			//---------------------------------------------------------------
			//
			bool firstIsIn;
			if (theOr.GetNumberOfSetBits() == 1)
			{
#ifdef LAB_ONLY
				Set_Statistic(PolysClippedButOnePlane, PolysClippedButOnePlane+1);
#endif
				for(k=j;k<end;k++)
				{
					k0 = index[k];
					k1 = index[(k+1) < end ? k+1 : j];

					//
					//----------------------------------------------------
					// If this vertex is inside the viewing space, copy it
					// directly to the clipping buffer
					//----------------------------------------------------
					//
					int clipped_index =
						myNumberUsedClipVertex + numberVerticesPerPolygon;
					theTest = (*clipPerVertex)[k0];

					if(theTest == 0)
					{
						firstIsIn = true;
						(*clipExtraCoords)[clipped_index] = (*transformedCoords)[k0];

#ifdef I_SAY_YES_TO_COLOR
#ifdef I_SAY_YES_TO_LIGHTING
						Verify((*actualColors).GetLength() > 0);
						(*clipExtraColors)[clipped_index] = (*actualColors)[k0];
#else
						Verify(colors.GetLength() > 0);
						(*clipExtraColors)[clipped_index] = colors[k0];
#endif
#endif

						Verify(texCoords.GetLength() > 0);
						(*clipExtraTexCoords)[clipped_index] = texCoords[k0];

#ifdef I_SAY_YES_TO_DUAL_TEXTURES
						(*clipExtraTexCoords2)[clipped_index] = texCoords[k0+numVertices];
#endif						

						if(channelUse > 0)
						{
							mask = 1;
							for(int n=0;n<MaxNumberOfExtraChannel;n+=2,mask<<=1)
							{
								if(channelUse & mask)
								{
									(*extraChannels[n+1])[clipped_index] = (*extraChannels[n])[k0];
								}
							}
						}

						numberVerticesPerPolygon++;
						clipped_index++;

						//
						//-------------------------------------------------------
						// We don't need to clip this edge if the next vertex is
						// also in the viewing space, so just move on to the next
						// vertex
						//-------------------------------------------------------
						//
						if((*clipPerVertex)[k1] == 0)
						{
							continue;
						}
					}

					//
					//---------------------------------------------------------
					// This vertex is outside the viewing space, so if the next
					// vertex is also outside the viewing space, no clipping is
					// needed and we throw this vertex away.  Since only one
					// clipping plane is involved, it must be in the same space
					// as the first vertex
					//---------------------------------------------------------
					//
					else
					{
						firstIsIn = false;
						if((*clipPerVertex)[k1] != 0)
						{
							Verify((*clipPerVertex)[k1] == (*clipPerVertex)[k0]);
							continue;
						}
					}

					//
					//--------------------------------------------------
					// We now find the distance along the edge where the
					// clipping plane will intersect
					//--------------------------------------------------
					//
					mask = 1;
					theTest |= (*clipPerVertex)[k1];

					//
					//-----------------------------------------------------
					// Find the boundary conditions that match our clipping
					// plane
					//-----------------------------------------------------
					//
					for (l=0; l<MLRClippingState::NextBit; l++)
					{
						if(theTest.IsClipped(mask))
						{
//							GetDoubleBC(l, bc0, bc1, transformedCoords[k0], transformedCoords[k1]);

							//
							//-------------------------------------------
							// Find the clipping interval from bc0 to bc1
							//-------------------------------------------
							//
							if(firstIsIn==true)
							{
								a = GetLerpFactor(l, (*transformedCoords)[k0], (*transformedCoords)[k1]);
							}
							else
							{
								a = GetLerpFactor(l, (*transformedCoords)[k1], (*transformedCoords)[k0]);
							}

							Verify(a >= 0.0f && a <= 1.0f);

							ct = l;

							break;
						}
						mask <<= 1;
					}

					//
					//------------------------------
					// Lerp the homogeneous position
					//------------------------------
					//
					if(firstIsIn==true)
					{
						(*clipExtraCoords)[clipped_index].Lerp(
							(*transformedCoords)[k0],
							(*transformedCoords)[k1],
							a
						);

						DoClipTrick((*clipExtraCoords)[clipped_index], ct);

						//
						//----------------------------------------------------------
						// If there are colors, lerp them in screen space for now as
						// most cards do that anyway
						//----------------------------------------------------------
						//
#ifdef I_SAY_YES_TO_COLOR
	#ifdef I_SAY_YES_TO_LIGHTING
						Verify((*actualColors).GetLength() > 0);
		#if COLOR_AS_DWORD
						(*clipExtraColors)[clipped_index] = Color_DWORD_Lerp (
							(*actualColors)[k0],
							(*actualColors)[k1],
							a
						);
		#else
						(*clipExtraColors)[clipped_index].Lerp(
							(*actualColors)[k0],
							(*actualColors)[k1],
							a
						);
		#endif
	#else
						Verify(colors.GetLength() > 0);
		#if COLOR_AS_DWORD
						(*clipExtraColors)[clipped_index] = Color_DWORD_Lerp (
							colors[k0],
							colors[k1],
							a
						);
		#else
						(*clipExtraColors)[clipped_index].Lerp(
							colors[k0],
							colors[k1],
							a
						);
		#endif
	#endif
#endif
						//
						//-----------------------------------------------------
						// If there are texture uv's, we need to lerp them in a
						// perspective correct manner
						//-----------------------------------------------------
						//
						Verify(texCoords.GetLength() > 0);
						(*clipExtraTexCoords)[clipped_index].Lerp
							(
								texCoords[k0],
								texCoords[k1],
								a
							);

#ifdef I_SAY_YES_TO_DUAL_TEXTURES
						(*clipExtraTexCoords2)[clipped_index].Lerp
							(
								texCoords[k0+numVertices],
								texCoords[k1+numVertices],
								a
							);
#endif
						if(channelUse > 0)
						{
							mask = 1;
							for(int n=0;n<MaxNumberOfExtraChannel;n+=2,mask<<=1)
							{
								if(channelUse & mask)
								{
									(*extraChannels[n+1])[clipped_index] = BYTE_Lerp (
										(*extraChannels[n])[k0],
										(*extraChannels[n])[k1],
										a
									);
								}
							}
						}
					}
					else
					{
						(*clipExtraCoords)[clipped_index].Lerp(
							(*transformedCoords)[k1],
							(*transformedCoords)[k0],
							a
						);

						DoClipTrick((*clipExtraCoords)[clipped_index], ct);

						//
						//----------------------------------------------------------
						// If there are colors, lerp them in screen space for now as
						// most cards do that anyway
						//----------------------------------------------------------
						//
#ifdef I_SAY_YES_TO_COLOR
	#ifdef I_SAY_YES_TO_LIGHTING
						Verify((*actualColors).GetLength() > 0);
		#if COLOR_AS_DWORD
						(*clipExtraColors)[clipped_index] = Color_DWORD_Lerp (
							(*actualColors)[k1],
							(*actualColors)[k0],
							a
						);
		#else
						(*clipExtraColors)[clipped_index].Lerp(
							(*actualColors)[k1],
							(*actualColors)[k0],
							a
						);
		#endif
	#else
						Verify(colors.GetLength() > 0);
		#if COLOR_AS_DWORD
						(*clipExtraColors)[clipped_index] = Color_DWORD_Lerp (
							colors[k1],
							colors[k0],
							a
						);
		#else
						(*clipExtraColors)[clipped_index].Lerp(
							colors[k1],
							colors[k0],
							a
						);
		#endif
	#endif
#endif
						//
						//-----------------------------------------------------
						// If there are texture uv's, we need to lerp them in a
						// perspective correct manner
						//-----------------------------------------------------
						//
						Verify(texCoords.GetLength() > 0);
						(*clipExtraTexCoords)[clipped_index].Lerp
							(
								texCoords[k1],
								texCoords[k0],
								a
							);

#ifdef I_SAY_YES_TO_DUAL_TEXTURES
						(*clipExtraTexCoords2)[clipped_index].Lerp
							(
								texCoords[k1+numVertices],
								texCoords[k0+numVertices],
								a
							);
#endif
						if(channelUse > 0)
						{
							mask = 1;
							for(int n=0;n<MaxNumberOfExtraChannel;n+=2,mask<<=1)
							{
								if(channelUse & mask)
								{
									(*extraChannels[n+1])[clipped_index] = BYTE_Lerp (
										(*extraChannels[n])[k1],
										(*extraChannels[n])[k0],
										a
									);
								}
							}
						}
					}

					//
					//--------------------------------
					// Bump the polygon's vertex count
					//--------------------------------
					//
					numberVerticesPerPolygon++;
				}
				(*clipExtraLength)[myNumberUsedClipLength] = numberVerticesPerPolygon;
#ifdef _ARMOR
				(*clipExtraLength)[myNumberUsedClipLength] &= ~0x8000;
#endif
			}

			//
			//---------------------------------------------------------------
			// We have to handle multiple planes.  We do this by creating two
			// buffers and we switch between them as we clip plane by plane
			//---------------------------------------------------------------
			//
			else
			{
#ifdef LAB_ONLY
				Set_Statistic(PolysClippedButGOnePlane, PolysClippedButGOnePlane+1);
#endif
				ClipData2 srcPolygon, dstPolygon;
				int dstBuffer = 1;

				Verify(texCoords.GetLength() > 0);

				srcPolygon.coords = clipBuffer[dstBuffer].coords.GetData();
#ifdef I_SAY_YES_TO_COLOR
	#ifdef I_SAY_YES_TO_LIGHTING
				Verify((*actualColors).GetLength() > 0);
	#else
				Verify(colors.GetLength() > 0);
	#endif
				srcPolygon.colors = clipBuffer[dstBuffer].colors.GetData();
#endif
				srcPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData();
				srcPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData();

				if(channelUse > 0)
				{
					mask = 1;
					for(int n=0;n<MaxNumberOfExtraChannel;n++,mask<<=1)
					{
						if(channelUse & mask)
						{
							srcPolygon.extraChannel[n] = clipBuffer[dstBuffer].extraChannel[n].GetData();
						}
					}
				}


				//
				//----------------------------------------------------------
				// unravel and copy the original data into the source buffer
				//----------------------------------------------------------
				//
				for(k=j,l=0;k<end;k++,l++)
				{
					int indexK = index[k];

					srcPolygon.coords[l] = (*transformedCoords)[indexK];

#ifdef I_SAY_YES_TO_COLOR
	#ifdef I_SAY_YES_TO_LIGHTING
		#if COLOR_AS_DWORD>0
					DWORD2Color(srcPolygon.colors[l], (*actualColors)[indexK]);
		#else
					srcPolygon.colors[l] = (*actualColors)[indexK];
		#endif
	#else
		#if COLOR_AS_DWORD>0
					DWORD2Color(srcPolygon.colors[l], colors[indexK]);
		#else
					srcPolygon.colors[l] = colors[indexK];
		#endif
	#endif
#endif

#ifdef I_SAY_YES_TO_DUAL_TEXTURES
					srcPolygon.texCoords[2*l] = texCoords[indexK];
					srcPolygon.texCoords[2*l+1] = texCoords[indexK + numVertices];
#else
					srcPolygon.texCoords[l] = texCoords[indexK];
#endif
					srcPolygon.clipPerVertex[l] = (*clipPerVertex)[indexK];

					if(channelUse > 0)
					{
						mask = 1;
						for(int n=0;n<MaxNumberOfExtraChannel;n++,mask<<=1)
						{
							if(channelUse & mask)
							{
								srcPolygon.extraChannel[n][l] = (*extraChannels[2*n])[indexK];
							}
						}
					}
				}

				srcPolygon.length = l;

				//
				//--------------------------------
				// Point to the destination buffer
				//--------------------------------
				//
				dstBuffer = 0;

				dstPolygon.coords = clipBuffer[dstBuffer].coords.GetData();
#ifdef I_SAY_YES_TO_COLOR
				dstPolygon.colors = clipBuffer[dstBuffer].colors.GetData();
#endif
				dstPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData();
				dstPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData();

				if(channelUse > 0)
				{
					mask = 1;
					for(int n=0;n<MaxNumberOfExtraChannel;n++,mask<<=1)
					{
						if(channelUse & mask)
						{
							dstPolygon.extraChannel[n] = clipBuffer[dstBuffer].extraChannel[n].GetData();
						}
					}
				}
				dstPolygon.length = 0;

				//
				//-----------------------------------------------------------
				// Spin through each plane that clipped the primitive and use
				// it to actually clip the primitive
				//-----------------------------------------------------------
				//
				mask = 1;
				MLRClippingState theNewOr(0);
				int loop = 4;

#if HUNT_CLIP_ERROR
				for(k=0;k<srcPolygon.length;k++)
				{
					DEBUG_STREAM << setiosflags( ios::scientific) << setprecision(20) 
						<< srcPolygon.coords[k].x << " "
						<< srcPolygon.coords[k].y << " "
						<< srcPolygon.coords[k].z << " "
						<< srcPolygon.coords[k].w << '\n';
				}
#endif
#if HUNT_CLIP_ERROR
					DEBUG_STREAM << "TheOriginalOR: " << hex << theOr.GetClippingState() << dec << '\n';
#endif

				do
				{
					for(l=0; l<MLRClippingState::NextBit; l++)
					{
						if(theOr.IsClipped(mask))
						{

							//
							//-----------------------------------
							// Clip each vertex against the plane
							//-----------------------------------
							//
	#if HUNT_CLIP_ERROR
							DEBUG_STREAM << l << ": " << '\n';
	#endif
							for(k=0;k<srcPolygon.length;k++)
							{

								k1 = (k+1) < srcPolygon.length ? k+1 : 0;

								theTest = srcPolygon.clipPerVertex[k];

								//
								//----------------------------------------------------
								// If this vertex is inside the viewing space, copy it
								// directly to the clipping buffer
								//----------------------------------------------------
								//
								if(theTest.IsClipped(mask) == 0)
								{
									firstIsIn = true;

									dstPolygon.coords[dstPolygon.length] = 
										srcPolygon.coords[k];
	#if HUNT_CLIP_ERROR
									DEBUG_STREAM << k << " goes " << setiosflags( ios::scientific) << setprecision(20) 
										<< srcPolygon.coords[k].x << " "
										<< srcPolygon.coords[k].y << " "
										<< srcPolygon.coords[k].z << " "
										<< srcPolygon.coords[k].w << '\n';
	#endif


									dstPolygon.clipPerVertex[dstPolygon.length] = 
										srcPolygon.clipPerVertex[k];
	#ifdef I_SAY_YES_TO_COLOR
									dstPolygon.colors[dstPolygon.length] = 
										srcPolygon.colors[k];
	#endif

	#ifdef I_SAY_YES_TO_DUAL_TEXTURES
									dstPolygon.texCoords[2*dstPolygon.length] = 
										srcPolygon.texCoords[2*k];

									dstPolygon.texCoords[2*dstPolygon.length+1] = 
										srcPolygon.texCoords[2*k+1];
	#else
									dstPolygon.texCoords[dstPolygon.length] = 
										srcPolygon.texCoords[k];
	#endif
									if(channelUse > 0)
									{
										mask = 1;
										for(int n=0;n<MaxNumberOfExtraChannel;n++,mask<<=1)
										{
											if(channelUse & mask)
											{
												dstPolygon.extraChannel[n][dstPolygon.length] =
													srcPolygon.extraChannel[n][k];
											}
										}
									}

									dstPolygon.length++;

									//
									//-------------------------------------------------------
									// We don't need to clip this edge if the next vertex is
									// also in the viewing space, so just move on to the next
									// vertex
									//-------------------------------------------------------
									//
									if(srcPolygon.clipPerVertex[k1].IsClipped(mask) == 0)
									{
										continue;
									}
								}

								//
								//---------------------------------------------------------
								// This vertex is outside the viewing space, so if the next
								// vertex is also outside the viewing space, no clipping is
								// needed and we throw this vertex away.  Since only one
								// clipping plane is involved, it must be in the same space
								// as the first vertex
								//---------------------------------------------------------
								//
								else 
								{
									firstIsIn = false;

									if(srcPolygon.clipPerVertex[k1].IsClipped(mask) != 0)
									{
										Verify(
											srcPolygon.clipPerVertex[k1].IsClipped(mask)
											== srcPolygon.clipPerVertex[k].IsClipped(mask)
										);
										continue;
									}
								}

								//
								//-------------------------------------------
								// Find the clipping interval from bc0 to bc1
								//-------------------------------------------
								//
								if(firstIsIn == true)
								{
									a = GetLerpFactor (l, srcPolygon.coords[k], srcPolygon.coords[k1]);

									Verify(a >= 0.0f && a <= 1.0f);

									//
									//------------------------------
									// Lerp the homogeneous position
									//------------------------------
									//
									dstPolygon.coords[dstPolygon.length].Lerp(
										srcPolygon.coords[k],
										srcPolygon.coords[k1],
										a
									);

	#if HUNT_CLIP_ERROR
									DEBUG_STREAM << "True " << a << " " << k << " " << k1 << " we get " << dstPolygon.length << '\n';
									DEBUG_STREAM << setiosflags( ios::scientific) << setprecision(20) 
										<< dstPolygon.coords[dstPolygon.length].x << " "
										<< dstPolygon.coords[dstPolygon.length].y << " "
										<< dstPolygon.coords[dstPolygon.length].z << " "
										<< dstPolygon.coords[dstPolygon.length].w << '\n';
	#endif
									DoClipTrick(dstPolygon.coords[dstPolygon.length], l);


									//
									//----------------------------------------------------------
									// If there are colors, lerp them in screen space for now as
									// most cards do that anyway
									//----------------------------------------------------------
									//
	#ifdef I_SAY_YES_TO_COLOR
									dstPolygon.colors[dstPolygon.length].Lerp(
										srcPolygon.colors[k],
										srcPolygon.colors[k1],
										a
									);
	#endif
									//
									//-----------------------------------------------------
									// If there are texture uv's, we need to lerp them in a
									// perspective correct manner
									//-----------------------------------------------------
									//
	#ifdef I_SAY_YES_TO_DUAL_TEXTURES
									dstPolygon.texCoords[2*dstPolygon.length].Lerp
										(
											srcPolygon.texCoords[2*k],
											srcPolygon.texCoords[2*k1],
											a
										);

									dstPolygon.texCoords[2*dstPolygon.length+1].Lerp
										(
											srcPolygon.texCoords[2*k+1],
											srcPolygon.texCoords[2*k1+1],
											a
										);
	#else
									dstPolygon.texCoords[dstPolygon.length].Lerp
										(
											srcPolygon.texCoords[k],
											srcPolygon.texCoords[k1],
											a
										);
	#endif
									if(channelUse > 0)
									{
										mask = 1;
										for(int n=0;n<MaxNumberOfExtraChannel;n++,mask<<=1)
										{
											if(channelUse & mask)
											{
												dstPolygon.extraChannel[n][dstPolygon.length] = BYTE_Lerp (
													srcPolygon.extraChannel[n][k],
													srcPolygon.extraChannel[n][k1],
													a
												);
											}
										}
									}
								}
								else
								{
									a = GetLerpFactor (l, srcPolygon.coords[k1], srcPolygon.coords[k]);
									Verify(a >= 0.0f && a <= 1.0f);

								//
								//------------------------------
								// Lerp the homogeneous position
								//------------------------------
								//
								dstPolygon.coords[dstPolygon.length].Lerp(
									srcPolygon.coords[k1],
									srcPolygon.coords[k],
									a
								);

	#if HUNT_CLIP_ERROR
									DEBUG_STREAM << "False " << a << " " << k << " " << k1 << " we get " << dstPolygon.length << '\n';
									DEBUG_STREAM << setiosflags( ios::scientific) << setprecision(20) 
										<< dstPolygon.coords[dstPolygon.length].x << " "
										<< dstPolygon.coords[dstPolygon.length].y << " "
										<< dstPolygon.coords[dstPolygon.length].z << " "
										<< dstPolygon.coords[dstPolygon.length].w << '\n';
	#endif

								DoClipTrick(dstPolygon.coords[dstPolygon.length], l);


								//
								//----------------------------------------------------------
								// If there are colors, lerp them in screen space for now as
								// most cards do that anyway
								//----------------------------------------------------------
								//
	#ifdef I_SAY_YES_TO_COLOR
								dstPolygon.colors[dstPolygon.length].Lerp(
									srcPolygon.colors[k1],
									srcPolygon.colors[k],
									a
								);
	#endif
								//
								//-----------------------------------------------------
								// If there are texture uv's, we need to lerp them in a
								// perspective correct manner
								//-----------------------------------------------------
								//
	#ifdef I_SAY_YES_TO_DUAL_TEXTURES
								dstPolygon.texCoords[2*dstPolygon.length].Lerp
									(
										srcPolygon.texCoords[2*k1],
										srcPolygon.texCoords[2*k],
										a
									);

								dstPolygon.texCoords[2*dstPolygon.length+1].Lerp
									(
										srcPolygon.texCoords[2*k1+1],
										srcPolygon.texCoords[2*k+1],
										a
									);
	#else
								dstPolygon.texCoords[dstPolygon.length].Lerp
									(
										srcPolygon.texCoords[k1],
										srcPolygon.texCoords[k],
										a
									);
	#endif
									if(channelUse > 0)
									{
										mask = 1;
										for(int n=0;n<MaxNumberOfExtraChannel;n++,mask<<=1)
										{
											if(channelUse & mask)
											{
												dstPolygon.extraChannel[n][dstPolygon.length] = BYTE_Lerp (
													srcPolygon.extraChannel[n][k1],
													srcPolygon.extraChannel[n][k],
													a
												);
											}
										}
									}
								}

								//
								//-------------------------------------
								// We have to generate a new clip state
								//-------------------------------------
								//
								dstPolygon.clipPerVertex[dstPolygon.length].Clip4dVertex(&dstPolygon.coords[dstPolygon.length]);

								//
								//----------------------------------
								// Bump the new polygon vertex count
								//----------------------------------
								//
								dstPolygon.length++;
							}

							//
							//-----------------------------------------------
							// Swap source and destination buffer pointers in
							// preparation for the next plane test
							//-----------------------------------------------
							//
							srcPolygon.coords = clipBuffer[dstBuffer].coords.GetData();
	#ifdef I_SAY_YES_TO_COLOR
							srcPolygon.colors = clipBuffer[dstBuffer].colors.GetData();
	#endif
							srcPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData();
							srcPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData();	
							if(channelUse > 0)
							{
								mask = 1;
								for(int n=0;n<MaxNumberOfExtraChannel;n++,mask<<=1)
								{
									if(channelUse & mask)
									{
										srcPolygon.extraChannel[n] = clipBuffer[dstBuffer].extraChannel[n].GetData();
									}
								}
							}
							srcPolygon.length = dstPolygon.length;

							dstBuffer = !dstBuffer;

							dstPolygon.coords = clipBuffer[dstBuffer].coords.GetData();
	#ifdef I_SAY_YES_TO_COLOR
							dstPolygon.colors = clipBuffer[dstBuffer].colors.GetData();
	#endif
							dstPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData();
							dstPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData();

							if(channelUse > 0)
							{
								mask = 1;
								for(int n=0;n<MaxNumberOfExtraChannel;n++,mask<<=1)
								{
									if(channelUse & mask)
									{
										dstPolygon.extraChannel[n] = clipBuffer[dstBuffer].extraChannel[n].GetData();
									}
								}
							}

							dstPolygon.length = 0;

						}

						mask = mask << 1;
					}

					theNewOr = 0;
					for(k=0;k<srcPolygon.length;k++)
					{
						theNewOr |= srcPolygon.clipPerVertex[k];
					}
#if HUNT_CLIP_ERROR
					DEBUG_STREAM << "TheOR: " << hex << theNewOr.GetClippingState() << dec << '\n';
#endif
					theOr == theNewOr;
				} while (theNewOr != 0 && loop--);

				//
				//--------------------------------------------------
				// could not clip this rare case, just ignore it
				//--------------------------------------------------
				//
				if(theNewOr != 0)
				{
					(*testList)[i] = 0;
					continue;
				}

				//
				//--------------------------------------------------
				// Move the most recent polygon into the clip buffer
				//--------------------------------------------------
				//
#if HUNT_CLIP_ERROR
				DEBUG_STREAM << "Final: " << srcPolygon.length << '\n';
#endif
				for(k=0;k<srcPolygon.length;k++)
				{
					int clipped_index = myNumberUsedClipVertex + k;
#if HUNT_CLIP_ERROR
					DEBUG_STREAM << setiosflags( ios::scientific) << setprecision(20) 
						<< srcPolygon.coords[k].x << " "
						<< srcPolygon.coords[k].y << " "
						<< srcPolygon.coords[k].z << " "
						<< srcPolygon.coords[k].w << '\n';
#endif

					(*clipExtraCoords)[clipped_index] = srcPolygon.coords[k];

#ifdef I_SAY_YES_TO_COLOR
	#if COLOR_AS_DWORD>0
					(*clipExtraColors)[clipped_index] = GOSCopyColor(&srcPolygon.colors[k]);
	#else
					(*clipExtraColors)[clipped_index] = srcPolygon.colors[k];
	#endif
#endif

#ifdef I_SAY_YES_TO_DUAL_TEXTURES
					(*clipExtraTexCoords)[clipped_index] = srcPolygon.texCoords[2*k];
					(*clipExtraTexCoords2)[clipped_index] = srcPolygon.texCoords[2*k+1];
#else
					(*clipExtraTexCoords)[clipped_index] = srcPolygon.texCoords[k];
#endif
					if(channelUse > 0)
					{
						mask = 1;
						for(int n=0;n<MaxNumberOfExtraChannel;n++,mask<<=1)
						{
							if(channelUse & mask)
							{
								(*extraChannels[2*n+1])[clipped_index] = srcPolygon.extraChannel[n][k];
							}
						}
					}
				}

				numberVerticesPerPolygon = srcPolygon.length;
#if HUNT_CLIP_ERROR
				DEBUG_STREAM << "---" << '\n';
#endif

				(*clipExtraLength)[myNumberUsedClipLength] = numberVerticesPerPolygon;
#ifdef _ARMOR
				(*clipExtraLength)[myNumberUsedClipLength] |= 0x8000;
#endif
			}

			myNumberUsedClipVertex += numberVerticesPerPolygon;
			myNumberUsedClipLength++;
			ret++;

//					clip

//					dont draw the original
			(*testList)[i] = 0;
		}

		j += stride;
	}

	Check_Object(vt);
	gos_vertices = vt->GetActualVertexPool(db);
	numGOSVertices = 0;
	gos_indices = vt->GetActualIndexPool(db);
	numGOSIndices = 0;

	k = visibleIndexedVertices->GetLength();

	for(j=0,stride=0;j<k;j++)
	{
		if((*visibleIndexedVertices)[j] == 0)
		{
			stride++;
		}
		else
		{
			indexOffset[j] = stride;

			if(channelUse & 1<<FogChannel)
			{
				*((BYTE *)&gos_vertices[numGOSVertices].frgb + 3) = (*extraChannels[2*FogChannel])[j];
			}
#if FOG_HACK
			else
			{
				int fogEntry = state.GetFogMode();

				if(fogEntry)
				{
					*((BYTE *)&gos_vertices[numGOSVertices].frgb + 3) =
						GOSVertex::fogTable[fogEntry-1][Truncate_Float_To_Word((*transformedCoords)[j].w)];
				}
				else
				{
					*((BYTE *)&gos_vertices[numGOSVertices].frgb + 3) = 0xff;
				}
			}
#endif

			GOSCopyData(
				&gos_vertices[numGOSVertices],
				transformedCoords->GetData(),
#ifdef I_SAY_YES_TO_COLOR
	#ifdef I_SAY_YES_TO_LIGHTING
				actualColors->GetData(),
	#else
				colors.GetData(),
	#endif
#endif
				texCoords.GetData(),
				j
			);

			if(textureAnimation)
			{
				gos_vertices[numGOSVertices].u += deltaU;
				gos_vertices[numGOSVertices].v += deltaV;
			}

#ifdef LAB_ONLY
			if(gShowClippedPolys)
			{
				gos_vertices[numGOSVertices].argb = 0xff0000ff;
				gos_vertices[numGOSVertices].u = 0.0f;
				gos_vertices[numGOSVertices].v = 0.0f;
			}
#endif

#ifdef I_SAY_YES_TO_DUAL_TEXTURES
			(*texCoords2)[tex2count++] = texCoords[numVertices + j];
#endif
			numGOSVertices++;
		}
	}

	for(i=0,j=0;i<len;i++)
	{
		stride = lengths[i];

		Verify(stride >= 3);

		if((*testList)[i] == 0)
		{
			j += stride;
			continue;
		}

		for(k=1;k<stride-1;k++)
		{
			if(db==false)
			{
				Verify((vt->GetLastIndex() + 3 + numGOSIndices) < vt->GetLength());
			}
			else
			{
				Verify(3 + numGOSIndices < Limits::Max_Size_Of_Index_Buffer);
			}

			gos_indices[numGOSIndices] = (WORD)(index[j] - indexOffset[index[j]]);
			gos_indices[numGOSIndices+1] = (WORD)(index[j+k+1] - indexOffset[index[j+k+1]]);
			gos_indices[numGOSIndices+2] = (WORD)(index[j+k] - indexOffset[index[j+k]]);

			numGOSIndices += 3;
		}
		j += stride;
	}

	if(myNumberUsedClipLength > 0)
	{
		for(i=0,j=0;i<myNumberUsedClipLength;i++)
		{
#ifdef _ARMOR
			stride = static_cast<WORD>((*clipExtraLength)[i] & 0x7fff);
#else
			stride = (*clipExtraLength)[i];
#endif


#if 0
			for(k=j;k<stride+j;k++)
			{
				if(clipExtraCoords[k].x < 0.0f && clipExtraCoords[k].x > -SMALL)
				{
					clipExtraCoords[k].x = 0.0f;
				}

				if(clipExtraCoords[k].y < 0.0f && clipExtraCoords[k].y > -SMALL)
				{
					clipExtraCoords[k].y = 0.0f;
				}

				if(clipExtraCoords[k].z < 0.0f && clipExtraCoords[k].z > -SMALL)
				{
					clipExtraCoords[k].z = 0.0f;
				}

				if(clipExtraCoords[k].x > clipExtraCoords[k].w && clipExtraCoords[k].x < clipExtraCoords[k].w + SMALL)
				{
					clipExtraCoords[k].x = clipExtraCoords[k].w;
				}

				if(clipExtraCoords[k].y > clipExtraCoords[k].w && clipExtraCoords[k].y < clipExtraCoords[k].w + SMALL)
				{
					clipExtraCoords[k].y = clipExtraCoords[k].w;
				}

				if(clipExtraCoords[k].z >= clipExtraCoords[k].w && clipExtraCoords[k].z < clipExtraCoords[k].w + SMALL)
				{
					clipExtraCoords[k].z = clipExtraCoords[k].w - SMALL;
				}
			}
#endif
			for(k=1;k<stride-1;k++)
			{
				if(db==false)
				{
					Verify((vt->GetLast() + 3 + numGOSVertices) < vt->GetLength());
					Verify((vt->GetLastIndex() + 3 + numGOSIndices) < vt->GetLength());
				}
				else
				{
					Verify(3 + numGOSVertices < Limits::Max_Size_Of_Vertex_Buffer);
					Verify(3 + numGOSIndices < Limits::Max_Size_Of_Index_Buffer);
				}

				if(channelUse & 1<<FogChannel)
				{
					*((BYTE *)&gos_vertices[numGOSVertices].frgb + 3) = (*extraChannels[2*FogChannel+1])[j];
					*((BYTE *)&gos_vertices[numGOSVertices+1].frgb + 3) = (*extraChannels[2*FogChannel+1])[j+k+1];
					*((BYTE *)&gos_vertices[numGOSVertices+2].frgb + 3) = (*extraChannels[2*FogChannel+1])[j+k];
				}
#if FOG_HACK
				else
				{
					int fogEntry = state.GetFogMode();
					if(fogEntry)
					{
						fogEntry--;
						*((BYTE *)&gos_vertices[numGOSVertices].frgb + 3) =
							GOSVertex::fogTable[fogEntry][Truncate_Float_To_Word((*clipExtraCoords)[j].w)];
						*((BYTE *)&gos_vertices[numGOSVertices+1].frgb + 3) =
							GOSVertex::fogTable[fogEntry][Truncate_Float_To_Word((*clipExtraCoords)[j+k+1].w)];
						*((BYTE *)&gos_vertices[numGOSVertices+2].frgb + 3) =
							GOSVertex::fogTable[fogEntry][Truncate_Float_To_Word((*clipExtraCoords)[j+k].w)];
					}
					else
					{
						*((BYTE *)&gos_vertices[numGOSVertices].frgb + 3) = 0xff;
						*((BYTE *)&gos_vertices[numGOSVertices+1].frgb + 3) = 0xff;
						*((BYTE *)&gos_vertices[numGOSVertices+2].frgb + 3) = 0xff;
					}
				}
#endif

				GOSCopyTriangleData(
					&gos_vertices[numGOSVertices],
					clipExtraCoords->GetData(),
#ifdef I_SAY_YES_TO_COLOR
					clipExtraColors->GetData(),
#endif
					clipExtraTexCoords->GetData(),
					j, j+k+1, j+k
					);

				if(textureAnimation)
				{
					gos_vertices[numGOSVertices].u += deltaU;
					gos_vertices[numGOSVertices].v += deltaV;

					gos_vertices[numGOSVertices+1].u += deltaU;
					gos_vertices[numGOSVertices+1].v += deltaV;

					gos_vertices[numGOSVertices+2].u += deltaU;
					gos_vertices[numGOSVertices+2].v += deltaV;
				}

#ifdef LAB_ONLY
				if(gShowClippedPolys)
				{
					if((*clipExtraLength)[i] & 0x8000)
					{
						gos_vertices[numGOSVertices].argb = 0xffff0000;
						gos_vertices[numGOSVertices].u = 0.0f;
						gos_vertices[numGOSVertices].v = 0.0f;

						gos_vertices[numGOSVertices+1].argb = 0xffff0000;
						gos_vertices[numGOSVertices+1].u = 0.0f;
						gos_vertices[numGOSVertices+1].v = 0.0f;

						gos_vertices[numGOSVertices+2].argb = 0xffff0000;
						gos_vertices[numGOSVertices+2].u = 0.0f;
						gos_vertices[numGOSVertices+2].v = 0.0f;
					}
					else
					{
						gos_vertices[numGOSVertices].argb = 0xffff9999;
						gos_vertices[numGOSVertices].u = 0.0f;
						gos_vertices[numGOSVertices].v = 0.0f;

						gos_vertices[numGOSVertices+1].argb = 0xffff9999;
						gos_vertices[numGOSVertices+1].u = 0.0f;
						gos_vertices[numGOSVertices+1].v = 0.0f;

						gos_vertices[numGOSVertices+2].argb = 0xffff9999;
						gos_vertices[numGOSVertices+2].u = 0.0f;
						gos_vertices[numGOSVertices+2].v = 0.0f;
					}
				}
#endif

#ifdef I_SAY_YES_TO_DUAL_TEXTURES
				(*texCoords2)[tex2count++] = (*clipExtraTexCoords2)[j];
				(*texCoords2)[tex2count++] = (*clipExtraTexCoords2)[j+k+1];
				(*texCoords2)[tex2count++] = (*clipExtraTexCoords2)[j+k];
#endif
				if(db==false)
				{
					Verify((vt->GetLastIndex() + 3 + numGOSIndices) < vt->GetLength());
				}
				else
				{
					Verify(3 + numGOSIndices < Limits::Max_Size_Of_Index_Buffer);
				}
				Verify(numGOSIndices%3 == 0);

				gos_indices[numGOSIndices] = numGOSVertices;
				gos_indices[numGOSIndices+1] = (WORD)(numGOSVertices + 1);
				gos_indices[numGOSIndices+2] = (WORD)(numGOSVertices + 2);

				numGOSVertices += 3;
				numGOSIndices += 3;
			}

			j += stride;
		}
#if HUNT_CLIP_ERROR
		DEBUG_STREAM << "***" << endl << endl;
#endif

	}
#ifdef LAB_ONLY
	else
	{
		Trivial_Accepts++;
	}
#endif

#ifdef I_SAY_YES_TO_DUAL_TEXTURES
	Verify (tex2count == numGOSVertices);
	if(db==false)
	{
		Verify (vt->GetLast() + 2*numGOSVertices < vt->GetLength());
	}
	else
	{
		Verify (2*numGOSVertices < 2*Limits::Max_Number_Vertices_Per_Mesh);
	}

	memcpy(gos_vertices + numGOSVertices, gos_vertices, numGOSVertices * sizeof(GOSVertex));

	if(textureAnimation2)
	{
		for(i=0,j=numGOSVertices;i<numGOSVertices;i++,j++)
		{
			gos_vertices[j].u = (*texCoords2)[i][0] + deltaU2;
			gos_vertices[j].v = (*texCoords2)[i][1] + deltaV2;
		}
	}
	else
	{
		for(i=0,j=numGOSVertices;i<numGOSVertices;i++,j++)
		{
			gos_vertices[j].u = (*texCoords2)[i][0];
			gos_vertices[j].v = (*texCoords2)[i][1];
		}
	}

	if(db==false)
	{
		vt->Increase(2*numGOSVertices);
	}
#else
	#ifdef I_SAY_YES_TO_DETAIL_TEXTURES
		if(db==false)
		{
			Verify (vt->GetLast() + 2*numGOSVertices < vt->GetLength());
		}
		else
		{
			Verify (numGOSVertices < Limits::Max_Size_Of_Vertex_Buffer);
		}

		memcpy(gos_vertices + numGOSVertices, gos_vertices, numGOSVertices * sizeof(GOSVertex));

		for(i=0,j=numGOSVertices;i<numGOSVertices;i++,j++)
		{
			gos_vertices[j].u = gos_vertices[i].u*xScale + xOffset;
			gos_vertices[j].v = gos_vertices[i].v*yScale + yOffset;
		}

		if(db==false)
		{
			vt->Increase(2*numGOSVertices);
		}
	#else
		if(db==false)
		{
			vt->Increase(numGOSVertices);
		}
	#endif
#endif

	if(db==false)
	{
		vt->IncreaseIndex(numGOSIndices);
	}

	visible = numGOSVertices ? (BYTE)1 : (BYTE)0;

	if(visible)
	{
	}
	else
	{
	}

	Stop_Timer(Clipping_Time);

	return ret;
}
