//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int 
	MLRIndexedTriangleCloud::Clip(MLRClippingState clippingFlags, GOSVertexPool *vt)
{
	int	myNumberUsedClipVertex, myNumberUsedClipIndex, myNumberUsedClipLength;

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

	Verify(*usedNrOfTriangles > 0);
	
	//
	//------------------------
	// Handle the indexed case
	//------------------------
	//

	memset(visibleIndexedVertices->GetData(), 0, *usedNrOfPoints);

	//
	//-----------------------------------------------------------------
	// Step through each polygon, making sure that we don't try to clip
	// backfaced polygons
	//-----------------------------------------------------------------
	//
	int i, j, k, k0, k1, *cs = (int *)clipPerVertex->GetData();
	unsigned short l;
	int index0, index1, index2, ret = 0;
	int mask;
	Scalar a = 0.0f;

	for(i=0,j=0;i<*usedNrOfTriangles;j+=3,++i)
	{
		index0 = index[j];
		index1 = index[j+1];
		index2 = index[j+2];
		//
		//---------------------------------------------------------------
		// 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 = cs[index0];

		theAnd &= (cs[index1] & cs[index2]);
		theOr |= (cs[index1] | cs[index2]);

		theAnd = theOr = 0;		//ASSUME NO CLIPPING NEEDED FOR MC2.  Its just not done here!
		
		//
		//-------------------------------------------------------------------
		// 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)
		{
			testList[i] = 1;
			ret++;

			(*visibleIndexedVertices)[index0] = 1;
			(*visibleIndexedVertices)[index1] = 1;
			(*visibleIndexedVertices)[index2] = 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
		{
			unsigned short 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<j+3;k++)
				{
					k0 = index[k];
					k1 = index[(k+1) < j+3 ? k+1 : j];

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

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

						(*clipExtraColors)[clipped_index] = colors[k0];

						(*clipExtraTexCoords)[clipped_index] = texCoords[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(cs[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(cs[k1] != 0)
						{
							Verify(cs[k1] == cs[k0]);
							continue;
						}
					}

					//
					//--------------------------------------------------
					// We now find the distance along the edge where the
					// clipping plane will intersect
					//--------------------------------------------------
					//
					int ct = 0;
					mask = 1;
					theTest |= cs[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
						//----------------------------------------------------------
						//
		#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
						//
						//-----------------------------------------------------
						// If there are texture uv's, we need to lerp them in a
						// perspective correct manner
						//-----------------------------------------------------
						//
						(*clipExtraTexCoords)[clipped_index].Lerp
							(
								texCoords[k0],
								texCoords[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
						//----------------------------------------------------------
						//
		#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
						//
						//-----------------------------------------------------
						// If there are texture uv's, we need to lerp them in a
						// perspective correct manner
						//-----------------------------------------------------
						//
						(*clipExtraTexCoords)[clipped_index].Lerp
							(
								texCoords[k1],
								texCoords[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;

				srcPolygon.coords = clipBuffer[dstBuffer].coords.GetData();

				srcPolygon.colors = clipBuffer[dstBuffer].colors.GetData();
				srcPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData();
				srcPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData();

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

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

					srcPolygon.colors[l] = colors[indexK];

					srcPolygon.texCoords[l] = texCoords[indexK];

					srcPolygon.clipPerVertex[l] = (*clipPerVertex)[indexK];
				}

				srcPolygon.length = l;

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

				dstPolygon.coords = clipBuffer[dstBuffer].coords.GetData();
				dstPolygon.colors = clipBuffer[dstBuffer].colors.GetData();
				dstPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData();
				dstPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.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];
									dstPolygon.colors[dstPolygon.length] = 
										srcPolygon.colors[k];

									dstPolygon.texCoords[dstPolygon.length] = 
										srcPolygon.texCoords[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
									//----------------------------------------------------------
									//
			#if COLOR_AS_DWORD
									dstPolygon.colors[dstPolygon.length] = Color_DWORD_Lerp(
										srcPolygon.colors[k],
										srcPolygon.colors[k1],
										a
									);
		#else
									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
									//-----------------------------------------------------
									//
									dstPolygon.texCoords[dstPolygon.length].Lerp
										(
											srcPolygon.texCoords[k],
											srcPolygon.texCoords[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
								//----------------------------------------------------------
								//
		#if COLOR_AS_DWORD
								dstPolygon.colors[dstPolygon.length] = Color_DWORD_Lerp(
									srcPolygon.colors[k1],
									srcPolygon.colors[k],
									a
								);
		#else
								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
								//-----------------------------------------------------
								//
								dstPolygon.texCoords[dstPolygon.length].Lerp
									(
										srcPolygon.texCoords[k1],
										srcPolygon.texCoords[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();
							srcPolygon.colors = clipBuffer[dstBuffer].colors.GetData();
							srcPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData();
							srcPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData();	
							srcPolygon.length = dstPolygon.length;

							dstBuffer = !dstBuffer;

							dstPolygon.coords = clipBuffer[dstBuffer].coords.GetData();
							dstPolygon.colors = clipBuffer[dstBuffer].colors.GetData();
							dstPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData();
							dstPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.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];

					(*clipExtraColors)[clipped_index] = srcPolygon.colors[k];

					(*clipExtraTexCoords)[clipped_index] = srcPolygon.texCoords[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;
		}
	}

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

	unsigned short strideIndex;
	for(j=0,strideIndex=0;j<*usedNrOfPoints;j++)
	{
		if((*visibleIndexedVertices)[j] == 0)
		{
			strideIndex++;
		}
		else
		{
			indexOffset[j] = static_cast<unsigned short>(j-strideIndex);

			GOSCopyData(
				&gos_vertices[numGOSVertices],
				transformedCoords->GetData(),
				colors,
				texCoords,
				j
			);

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

			numGOSVertices++;
		}
	}

	for(i=0,j=0;i<*usedNrOfTriangles;j+=3,++i)
	{
		if(testList[i] == 0)
		{
			continue;
		}

		Verify((vt->GetLastIndex() + 3 + numGOSIndices) < vt->GetLength());

		Verify(indexOffset[index[j]] < numGOSVertices);
		gos_indices[numGOSIndices] = indexOffset[index[j]];

		Verify(indexOffset[index[j+2]] < numGOSVertices);
		gos_indices[numGOSIndices+1] = indexOffset[index[j+2]];

		Verify(indexOffset[index[j+1]] < numGOSVertices);
		gos_indices[numGOSIndices+2] = indexOffset[index[j+1]];

		numGOSIndices += 3;
	}

	unsigned short stride;
	if(myNumberUsedClipLength > 0)
	{
		for(i=0,j=0;i<myNumberUsedClipLength;i++)
		{
#ifdef _ARMOR
			stride = static_cast<unsigned short>((*clipExtraLength)[i] & 0x7fff);
#else
			stride = static_cast<unsigned short>((*clipExtraLength)[i]);
#endif
			for(k=1;k<stride-1;k++)
			{
				Verify((vt->GetLast() + 3 + numGOSVertices) < vt->GetLength());
				Verify((vt->GetLastIndex() + 3 + numGOSIndices) < vt->GetLength());

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

#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


				Verify((vt->GetLastIndex() + 3 + numGOSIndices) < vt->GetLength());
				Verify(numGOSIndices%3 == 0);

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

				numGOSVertices += 3;
				numGOSIndices += 3;
			}

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

	}
	vt->Increase(numGOSVertices);
	vt->IncreaseIndex(numGOSIndices);

	return numGOSIndices;
}
Пример #2
0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MLRLightMap::DrawLightMaps(MLRSorter *sorter)
{
	Check_Object(stream);

	void *ptr, *end = stream->GetPointer();

	Stuff::Matrix4D *currentMatrix=NULL;
	MLRClippingState currentClippingState;
	
	MLRState currentState, masterState;

	unsigned short stride;

	int i, pointerValue;
	Stuff::Point3D *coords = NULL;
	Stuff::RGBAColor color;
	Stuff::RGBAColor *colors = NULL;
	Vector2DScalar *texCoords = NULL;
	DWORD argb = 0xffffffff;

	Check_Object(vertexPool);
	GOSVertex* gos_vertices = vertexPool->GetActualVertexPool();
	int numGOSVertices = 0;

	int msd;
	MemoryStreamData type;

	stream->Rewind();

	ptr = stream->GetPointer();

	while(ptr < end)
	{
		*stream >> msd;

		type = static_cast<MemoryStreamData>(msd);

		switch(msd)
		{
			case Matrix4D:
				*stream >> pointerValue;
				currentMatrix = reinterpret_cast<Stuff::Matrix4D*>(pointerValue);
			break;
			case ClippingState:
				currentClippingState.Load(stream);
			break;
			case MasterRenderState:
				masterState.Load(stream, Current_MLR_Version);
			break;
			case LightMapRenderState:
			{
				MLRState lightmapState;
				lightmapState.Load(stream, Current_MLR_Version);

				lightmapState.Combine(masterState, lightmapState);

				if(numGOSVertices && (lightmapState != currentState))
				{
					vertexPool->Increase(numGOSVertices);

					SortData *sd = sorter->SetRawData
						(
							gos_vertices, 
							numGOSVertices,
							currentState,
							SortData::TriList
						);

					if(currentState.GetDrawNowMode()==MLRState::DrawNowOnMode)

					{
						SortData::DrawFunc drawFunc = sd->Draw[sd->type];
						(sd->*drawFunc)();
					}
					else
					{

						sorter->AddSortRawData(sd);
					}
					gos_vertices = vertexPool->GetActualVertexPool();
					numGOSVertices = 0;

				}
				currentState = lightmapState;
			}
			break;
			case Polygon:
			{
				*stream >> stride;
				Verify(stride<=Limits::Max_Number_Vertices_Per_Polygon);

				*stream >> color;

				argb = GOSCopyColor(&color);

				coords = (Stuff::Point3D *)stream->GetPointer();
				stream->AdvancePointer(stride*sizeof(Stuff::Point3D));
				texCoords = (Vector2DScalar *)stream->GetPointer();
				stream->AdvancePointer(stride*sizeof(Vector2DScalar));

				MLRClippingState theAnd(0x3f), theOr(0);
				MLRClippingState *cs = clippingStates->GetData();
				Vector4D *v4d = transformedCoords->GetData();
				for(i=0;i<stride;i++,v4d++,cs++)
				{
					v4d->Multiply(coords[i], *currentMatrix);

					if(currentClippingState!=0)
					{
						cs->Clip4dVertex(v4d);

						theAnd &= *cs;

						theOr |= *cs;
					}
#if defined(_ARMOR)
					else
					{
						Verify((*transformedCoords)[i].x >= 0.0f && (*transformedCoords)[i].x <= (*transformedCoords)[i].w );
						Verify((*transformedCoords)[i].y >= 0.0f && (*transformedCoords)[i].y <= (*transformedCoords)[i].w );
						Verify((*transformedCoords)[i].z >= 0.0f && (*transformedCoords)[i].z <= (*transformedCoords)[i].w );
					}
#endif
				}

				if(theOr == 0)
				{
					for(i=1;i<stride-1;i++)
					{
						Verify((vertexPool->GetLast() + 3 + numGOSVertices) < vertexPool->GetLength());

						GOSCopyTriangleData(
							&gos_vertices[numGOSVertices],
							transformedCoords->GetData(),
							texCoords,
							0, i + 1, i
						);

						gos_vertices[numGOSVertices].argb = argb;
						gos_vertices[numGOSVertices+1].argb = argb;
						gos_vertices[numGOSVertices+2].argb = argb;

						numGOSVertices+=3;
					}
				}
				else
				{
					if(theAnd != 0)
					{
						break;
					}
					else
					{
						int k, k0, k1, l, mask, ct = 0;
						Scalar a = 0.0f;

						int numberVerticesPerPolygon = 0;

						//
						//---------------------------------------------------------------
						// Handle the case of a single clipping plane by stepping through
						// the vertices and finding the edge it originates
						//---------------------------------------------------------------
						//
						bool firstIsIn;
						MLRClippingState theTest;

						if (theOr.GetNumberOfSetBits() == 1)
						{
#ifdef LAB_ONLY
							Set_Statistic(PolysClippedButOnePlane, PolysClippedButOnePlane+1);
#endif
							for(k=0;k<stride;k++)
							{
								int clipped_index = numberVerticesPerPolygon;

								k0 = k;
								k1 = (k+1) < stride ? k+1 : 0;

								//
								//----------------------------------------------------
								// If this vertex is inside the viewing space, copy it
								// directly to the clipping buffer
								//----------------------------------------------------
								//
								theTest = (*clippingStates)[k0];

								if(theTest == 0)
								{
									firstIsIn = true;
									(*clipExtraCoords)[clipped_index] = (*transformedCoords)[k0];
									Verify((*clipExtraCoords)[clipped_index].x >= 0.0f && (*clipExtraCoords)[clipped_index].x <= (*clipExtraCoords)[clipped_index].w );
									Verify((*clipExtraCoords)[clipped_index].y >= 0.0f && (*clipExtraCoords)[clipped_index].y <= (*clipExtraCoords)[clipped_index].w );
									Verify((*clipExtraCoords)[clipped_index].z >= 0.0f && (*clipExtraCoords)[clipped_index].z <= (*clipExtraCoords)[clipped_index].w );
									(*clipExtraTexCoords)[clipped_index] = texCoords[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((*clippingStates)[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((*clippingStates)[k1] != 0)
									{
										Verify((*clippingStates)[k1] == (*clippingStates)[k0]);
										continue;
									}
								}

								//
								//--------------------------------------------------
								// We now find the distance along the edge where the
								// clipping plane will intersect
								//--------------------------------------------------
								//
								mask = 1;
								theTest |= (*clippingStates)[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);
									Verify((*clipExtraCoords)[clipped_index].x >= 0.0f && (*clipExtraCoords)[clipped_index].x <= (*clipExtraCoords)[clipped_index].w );
									Verify((*clipExtraCoords)[clipped_index].y >= 0.0f && (*clipExtraCoords)[clipped_index].y <= (*clipExtraCoords)[clipped_index].w );
									Verify((*clipExtraCoords)[clipped_index].z >= 0.0f && (*clipExtraCoords)[clipped_index].z <= (*clipExtraCoords)[clipped_index].w );

									//
									//-----------------------------------------------------
									// If there are texture uv's, we need to lerp them in a
									// perspective correct manner
									//-----------------------------------------------------
									//
									(*clipExtraTexCoords)[clipped_index].Lerp
										(
											texCoords[k0],
											texCoords[k1],
											a
										);
								}
								else
								{
									(*clipExtraCoords)[clipped_index].Lerp(
										(*transformedCoords)[k1],
										(*transformedCoords)[k0],
										a
									);

									DoClipTrick((*clipExtraCoords)[clipped_index], ct);
									Verify((*clipExtraCoords)[clipped_index].x >= 0.0f && (*clipExtraCoords)[clipped_index].x <= (*clipExtraCoords)[clipped_index].w );
									Verify((*clipExtraCoords)[clipped_index].y >= 0.0f && (*clipExtraCoords)[clipped_index].y <= (*clipExtraCoords)[clipped_index].w );
									Verify((*clipExtraCoords)[clipped_index].z >= 0.0f && (*clipExtraCoords)[clipped_index].z <= (*clipExtraCoords)[clipped_index].w );
									//
									//-----------------------------------------------------
									// If there are texture uv's, we need to lerp them in a
									// perspective correct manner
									//-----------------------------------------------------
									//
									(*clipExtraTexCoords)[clipped_index].Lerp
										(
											texCoords[k1],
											texCoords[k0],
											a
										);
								}

								//
								//--------------------------------
								// Bump the polygon's vertex count
								//--------------------------------
								//
								numberVerticesPerPolygon++;
							}
						}

						//
						//---------------------------------------------------------------
						// 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;

							srcPolygon.coords = clipBuffer[dstBuffer].coords.GetData();

							srcPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData();
							srcPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData();

							//
							//----------------------------------------------------------
							// unravel and copy the original data into the source buffer
							//----------------------------------------------------------
							//
							for(k=0;k<stride;k++)
							{
								srcPolygon.coords[k] = (*transformedCoords)[k];
								srcPolygon.texCoords[k] = texCoords[k];
								srcPolygon.clipPerVertex[k] = (*clippingStates)[k];
							}

							srcPolygon.length = stride;

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

							dstPolygon.coords = clipBuffer[dstBuffer].coords.GetData();
							dstPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData();
							dstPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.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;

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

										//
										//-----------------------------------
										// Clip each vertex against the plane
										//-----------------------------------
										//
										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];

												dstPolygon.clipPerVertex[dstPolygon.length] = 
													srcPolygon.clipPerVertex[k];
												dstPolygon.texCoords[dstPolygon.length] = 
													srcPolygon.texCoords[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
											);

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

											//
											//-----------------------------------------------------
											// If there are texture uv's, we need to lerp them in a
											// perspective correct manner
											//-----------------------------------------------------
											//
											dstPolygon.texCoords[dstPolygon.length].Lerp
												(
													srcPolygon.texCoords[k],
													srcPolygon.texCoords[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
												);

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

												//
												//-----------------------------------------------------
												// If there are texture uv's, we need to lerp them in a
												// perspective correct manner
												//-----------------------------------------------------
												//
												dstPolygon.texCoords[dstPolygon.length].Lerp
													(
														srcPolygon.texCoords[k1],
														srcPolygon.texCoords[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();
										srcPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData();
										srcPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData();	
										srcPolygon.length = dstPolygon.length;

										dstBuffer = !dstBuffer;

										dstPolygon.coords = clipBuffer[dstBuffer].coords.GetData();
										dstPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData();
										dstPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData();
										dstPolygon.length = 0;

									}

									mask = mask << 1;
								}

								theNewOr = 0;
								for(k=0;k<srcPolygon.length;k++)
								{
									theNewOr |= srcPolygon.clipPerVertex[k];
								}

								theOr == theNewOr;
								loop++;
							} while (theNewOr != 0 && loop--);

							Verify(theNewOr == 0);
							//
							//--------------------------------------------------
							// Move the most recent polygon into the clip buffer
							//--------------------------------------------------
							//
							for(k=0;k<srcPolygon.length;k++)
							{
								(*clipExtraCoords)[k] = srcPolygon.coords[k];

								Verify((*clipExtraCoords)[k].x >= 0.0f && (*clipExtraCoords)[k].x <= (*clipExtraCoords)[k].w );
								Verify((*clipExtraCoords)[k].y >= 0.0f && (*clipExtraCoords)[k].y <= (*clipExtraCoords)[k].w );
								Verify((*clipExtraCoords)[k].z >= 0.0f && (*clipExtraCoords)[k].z <= (*clipExtraCoords)[k].w );

								(*clipExtraTexCoords)[k] = srcPolygon.texCoords[k];
							}

							numberVerticesPerPolygon = srcPolygon.length;
						}

//						clip

						for(i=1;i<numberVerticesPerPolygon-1;i++)
						{
							Verify((vertexPool->GetLast() + 3 + numGOSVertices) < vertexPool->GetLength());

							GOSCopyTriangleData(
								&gos_vertices[numGOSVertices],
								clipExtraCoords->GetData(),
								clipExtraTexCoords->GetData(),
								0, i + 1, i
							);

							gos_vertices[numGOSVertices].argb = argb;
							gos_vertices[numGOSVertices+1].argb = argb;
							gos_vertices[numGOSVertices+2].argb = argb;

							numGOSVertices+=3;
						}

					}
				}
			}
			break;
			case PolygonWithColor:
			{
				*stream >> stride;
				Verify(stride<=Limits::Max_Number_Vertices_Per_Polygon);

				coords = (Stuff::Point3D *)stream->GetPointer();
				stream->AdvancePointer(stride*sizeof(Stuff::Point3D));
				
				colors = (Stuff::RGBAColor *)stream->GetPointer();
				stream->AdvancePointer(stride*sizeof(Stuff::RGBAColor));

				texCoords = (Vector2DScalar *)stream->GetPointer();
				stream->AdvancePointer(stride*sizeof(Vector2DScalar));

				MLRClippingState theAnd(0x3f), theOr(0);
				MLRClippingState *cs = clippingStates->GetData();
				Vector4D *v4d = transformedCoords->GetData();
				for(i=0;i<stride;i++,v4d++,cs++)
				{
					v4d->Multiply(coords[i], *currentMatrix);

					if(currentClippingState!=0)
					{
						cs->Clip4dVertex(v4d);

						theAnd &= *cs;

						theOr |= *cs;
					}
#if defined(_ARMOR)
					else
					{
						Verify((*transformedCoords)[i].x >= 0.0f && (*transformedCoords)[i].x <= (*transformedCoords)[i].w );
						Verify((*transformedCoords)[i].y >= 0.0f && (*transformedCoords)[i].y <= (*transformedCoords)[i].w );
						Verify((*transformedCoords)[i].z >= 0.0f && (*transformedCoords)[i].z <= (*transformedCoords)[i].w );
					}
#endif
				}

				if(theOr == 0)
				{
					for(i=1;i<stride-1;i++)
					{
						Verify((vertexPool->GetLast() + 3 + numGOSVertices) < vertexPool->GetLength());

						GOSCopyTriangleData(
							&gos_vertices[numGOSVertices],
							transformedCoords->GetData(),
							colors,
							texCoords,
							0, i + 1, i
						);

						numGOSVertices+=3;
					}
				}
				else
				{
					if(theAnd != 0)
					{
						break;
					}
					else
					{
						int k, k0, k1, l, mask, ct = 0;
						Scalar a = 0.0f;

						int numberVerticesPerPolygon = 0;

						//
						//---------------------------------------------------------------
						// Handle the case of a single clipping plane by stepping through
						// the vertices and finding the edge it originates
						//---------------------------------------------------------------
						//
						bool firstIsIn;
						MLRClippingState theTest;

						if (theOr.GetNumberOfSetBits() == 1)
						{
#ifdef LAB_ONLY
							Set_Statistic(PolysClippedButOnePlane, PolysClippedButOnePlane+1);
#endif
							for(k=0;k<stride;k++)
							{
								int clipped_index = numberVerticesPerPolygon;

								k0 = k;
								k1 = (k+1) < stride ? k+1 : 0;

								//
								//----------------------------------------------------
								// If this vertex is inside the viewing space, copy it
								// directly to the clipping buffer
								//----------------------------------------------------
								//
								theTest = (*clippingStates)[k0];

								if(theTest == 0)
								{
									firstIsIn = true;
									(*clipExtraCoords)[clipped_index] = (*transformedCoords)[k0];
									Verify((*clipExtraCoords)[clipped_index].x >= 0.0f && (*clipExtraCoords)[clipped_index].x <= (*clipExtraCoords)[clipped_index].w );
									Verify((*clipExtraCoords)[clipped_index].y >= 0.0f && (*clipExtraCoords)[clipped_index].y <= (*clipExtraCoords)[clipped_index].w );
									Verify((*clipExtraCoords)[clipped_index].z >= 0.0f && (*clipExtraCoords)[clipped_index].z <= (*clipExtraCoords)[clipped_index].w );
									(*clipExtraColors)[clipped_index] = colors[k0];
									(*clipExtraTexCoords)[clipped_index] = texCoords[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((*clippingStates)[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((*clippingStates)[k1] != 0)
									{
										Verify((*clippingStates)[k1] == (*clippingStates)[k0]);
										continue;
									}
								}

								//
								//--------------------------------------------------
								// We now find the distance along the edge where the
								// clipping plane will intersect
								//--------------------------------------------------
								//)
								mask = 1;
								theTest |= (*clippingStates)[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);
									Verify((*clipExtraCoords)[clipped_index].x >= 0.0f && (*clipExtraCoords)[clipped_index].x <= (*clipExtraCoords)[clipped_index].w );
									Verify((*clipExtraCoords)[clipped_index].y >= 0.0f && (*clipExtraCoords)[clipped_index].y <= (*clipExtraCoords)[clipped_index].w );
									Verify((*clipExtraCoords)[clipped_index].z >= 0.0f && (*clipExtraCoords)[clipped_index].z <= (*clipExtraCoords)[clipped_index].w );

									//
									//-----------------------------------------------------
									// If there are texture uv's, we need to lerp them in a
									// perspective correct manner
									//-----------------------------------------------------
									//
									(*clipExtraTexCoords)[clipped_index].Lerp
										(
											texCoords[k0],
											texCoords[k1],
											a
										);

									(*clipExtraColors)[clipped_index].Lerp
										(
											colors[k0],
											colors[k1],
											a
										);
								}
								else
								{
									(*clipExtraCoords)[clipped_index].Lerp(
										(*transformedCoords)[k1],
										(*transformedCoords)[k0],
										a
									);

									DoClipTrick((*clipExtraCoords)[clipped_index], ct);
									Verify((*clipExtraCoords)[clipped_index].x >= 0.0f && (*clipExtraCoords)[clipped_index].x <= (*clipExtraCoords)[clipped_index].w );
									Verify((*clipExtraCoords)[clipped_index].y >= 0.0f && (*clipExtraCoords)[clipped_index].y <= (*clipExtraCoords)[clipped_index].w );
									Verify((*clipExtraCoords)[clipped_index].z >= 0.0f && (*clipExtraCoords)[clipped_index].z <= (*clipExtraCoords)[clipped_index].w );
									//
									//-----------------------------------------------------
									// If there are texture uv's, we need to lerp them in a
									// perspective correct manner
									//-----------------------------------------------------
									//
									(*clipExtraTexCoords)[clipped_index].Lerp
										(
											texCoords[k1],
											texCoords[k0],
											a
										);

									(*clipExtraColors)[clipped_index].Lerp
										(
											colors[k1],
											colors[k0],
											a
										);
								}

								//
								//--------------------------------
								// Bump the polygon's vertex count
								//--------------------------------
								//
								numberVerticesPerPolygon++;
							}
						}

						//
						//---------------------------------------------------------------
						// 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;

							srcPolygon.coords = clipBuffer[dstBuffer].coords.GetData();
							srcPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData();
							srcPolygon.colors = clipBuffer[dstBuffer].colors.GetData();
							srcPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData();

							//
							//----------------------------------------------------------
							// unravel and copy the original data into the source buffer
							//----------------------------------------------------------
							//
							for(k=0;k<stride;k++)
							{
								srcPolygon.coords[k] = (*transformedCoords)[k];
								srcPolygon.texCoords[k] = texCoords[k];
								srcPolygon.colors[k] = colors[k];
								srcPolygon.clipPerVertex[k] = (*clippingStates)[k];
							}

							srcPolygon.length = stride;

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

							dstPolygon.coords = clipBuffer[dstBuffer].coords.GetData();
							dstPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData();
							dstPolygon.colors = clipBuffer[dstBuffer].colors.GetData();
							dstPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.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;

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

										//
										//-----------------------------------
										// Clip each vertex against the plane
										//-----------------------------------
										//
										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];

												dstPolygon.clipPerVertex[dstPolygon.length] = 
													srcPolygon.clipPerVertex[k];
												dstPolygon.texCoords[dstPolygon.length] = 
													srcPolygon.texCoords[k];
												dstPolygon.colors[dstPolygon.length] = 
													srcPolygon.colors[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
											);

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

											//
											//-----------------------------------------------------
											// If there are texture uv's, we need to lerp them in a
											// perspective correct manner
											//-----------------------------------------------------
											//
											dstPolygon.texCoords[dstPolygon.length].Lerp
												(
													srcPolygon.texCoords[k],
													srcPolygon.texCoords[k1],
													a
												);
											dstPolygon.colors[dstPolygon.length].Lerp
												(
													srcPolygon.colors[k],
													srcPolygon.colors[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
												);

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

												//
												//-----------------------------------------------------
												// If there are texture uv's, we need to lerp them in a
												// perspective correct manner
												//-----------------------------------------------------
												//
												dstPolygon.texCoords[dstPolygon.length].Lerp
													(
														srcPolygon.texCoords[k1],
														srcPolygon.texCoords[k],
														a
													);
												dstPolygon.colors[dstPolygon.length].Lerp
													(
														srcPolygon.colors[k1],
														srcPolygon.colors[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();
										srcPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData();
										srcPolygon.colors = clipBuffer[dstBuffer].colors.GetData();
										srcPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData();	
										srcPolygon.length = dstPolygon.length;

										dstBuffer = !dstBuffer;

										dstPolygon.coords = clipBuffer[dstBuffer].coords.GetData();
										dstPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData();
										dstPolygon.colors = clipBuffer[dstBuffer].colors.GetData();
										dstPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData();
										dstPolygon.length = 0;

									}

									mask = mask << 1;
								}

								theNewOr = 0;
								for(k=0;k<srcPolygon.length;k++)
								{
									theNewOr |= srcPolygon.clipPerVertex[k];
								}

								theOr == theNewOr;
								loop++;
							} while (theNewOr != 0 && loop--);

							Verify(theNewOr == 0);
							//
							//--------------------------------------------------
							// Move the most recent polygon into the clip buffer
							//--------------------------------------------------
							//
							for(k=0;k<srcPolygon.length;k++)
							{
								(*clipExtraCoords)[k] = srcPolygon.coords[k];

								Verify((*clipExtraCoords)[k].x >= 0.0f && (*clipExtraCoords)[k].x <= (*clipExtraCoords)[k].w );
								Verify((*clipExtraCoords)[k].y >= 0.0f && (*clipExtraCoords)[k].y <= (*clipExtraCoords)[k].w );
								Verify((*clipExtraCoords)[k].z >= 0.0f && (*clipExtraCoords)[k].z <= (*clipExtraCoords)[k].w );

								(*clipExtraTexCoords)[k] = srcPolygon.texCoords[k];

								(*clipExtraColors)[k] = srcPolygon.colors[k];
							}

							numberVerticesPerPolygon = srcPolygon.length;
						}

//						clip

						for(i=1;i<numberVerticesPerPolygon-1;i++)
						{
							Verify((vertexPool->GetLast() + 3 + numGOSVertices) < vertexPool->GetLength());

							GOSCopyTriangleData(
								&gos_vertices[numGOSVertices],
								clipExtraCoords->GetData(),
								clipExtraColors->GetData(),
								clipExtraTexCoords->GetData(),
								0, i + 1, i
							);

							numGOSVertices+=3;
						}

					}
				}
			}
			break;
		}
		ptr = stream->GetPointer();
	}

	if(numGOSVertices)
	{
		vertexPool->Increase(numGOSVertices);

		SortData *sd = sorter->SetRawData
			(
				gos_vertices, 
				numGOSVertices,
				currentState,
				SortData::TriList
			);

		if(currentState.GetDrawNowMode()==MLRState::DrawNowOnMode)
		{
			SortData::DrawFunc drawFunc = sd->Draw[sd->type];
			(sd->*drawFunc)();
		}
		else
		{

			sorter->AddSortRawData(sd);
		}
	}

}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Now it gets serious
int
	MLRIndexedPolyMesh::Clip(MLRClippingState clippingFlags, GOSVertexPool *vt)
{
	StartCycleTiming( &Statistics::MLR_ClipTime );
	SET_MLRIndexedPolyMesh_CLIP();

	Check_Object(this);

	unsigned short stride, l;
	int i, j, k, ret = 0;
	int len = lengths.GetLength();

	Verify(len == testList.GetLength());
	Verify(clippingFlags.GetClippingState() != 0);

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

		CLEAR_MLRIndexedPolyMesh_CLIP();
		EndCycleTiming( &Statistics::MLR_ClipTime );

		return visible;
	}

	int mask, end, k0, k1, ct=0;
	Scalar a=0.0f;
//	Scalar bc0=0.0f, bc1=0.0f;

	int	myNumberUsedClipVertex, myNumberUsedClipIndex, myNumberUsedClipLength;

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

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

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

	//
	//-----------------------------------------------------------------
	// Step through each vertex and check visibility
	// backfaced polygons
	//-----------------------------------------------------------------
	//
	k = transformedCoords.GetLength();
	Stuff::Vector4D *v4d = transformedCoords.GetData();
	MLRClippingState *cs = clipPerVertex.GetData();

 	for(i=0;i<k;i++,v4d++,cs++)
	{
		if(visibleIndexedVertices[i] == 0)
		{
			continue;
		}

		cs->SetClippingState(0);

		if( clippingFlags.IsFarClipped() && v4d->w < v4d->z)
		{
			cs->SetFarClip();
		}

		if( clippingFlags.IsNearClipped() && v4d->z < 0.0f)
		{
			cs->SetNearClip();
		}

		if( clippingFlags.IsRightClipped() && v4d->x < 0.0f)
		{
			cs->SetRightClip();
		}

		if( clippingFlags.IsLeftClipped() && v4d->w < v4d->x)
		{
			cs->SetLeftClip();
		}

		if( clippingFlags.IsBottomClipped() && v4d->y < 0.0f)
		{
			cs->SetBottomClip();
		}

		if(clippingFlags.IsTopClipped() && v4d->w < v4d->y)
		{
			cs->SetTopClip();
		}

#ifdef LAB_ONLY
		if( (*cs)==0)
		{
			Statistics::MLR_NonClippedVertices++;
		}
		else
		{
			Statistics::MLR_ClippedVertices++;
		}
#endif
	}

	//	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]];
		}

		theAnd = theOr = 0;		//ASSUME NO CLIPPING NEEDED FOR MC2.  Its just not done here!

		//
		//-------------------------------------------------------------------
		// 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
			Statistics::MLR_PolysClippedButOutside++;
#endif
		}
		else if (theOr == 0)
		{
			ret++;
			for(k=j;k<end;k++)
			{
				visibleIndexedVertices[index[k]] = 1;
			}
#ifdef LAB_ONLY
			Statistics::MLR_PolysClippedButInside++;
#endif
		}

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

			//
			//---------------------------------------------------------------
			// Handle the case of a single clipping plane by stepping through
			// the vertices and finding the edge it originates
			//---------------------------------------------------------------
			//
			if (theOr.GetNumberOfSetBits() == 1)
			{
#ifdef LAB_ONLY
				Statistics::MLR_PolysClippedButOnePlane++;
#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)
					{
						clipExtraCoords[clipped_index] = transformedCoords[k0];

						Verify((*actualColors).GetLength() > 0);
						clipExtraColors[clipped_index] = (*actualColors)[k0];

						Verify(texCoords.GetLength() > 0);
						clipExtraTexCoords[clipped_index] = texCoords[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 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
							//-------------------------------------------
							//
//							Verify(!Close_Enough(bc0, bc1));
//							a = bc0 / (bc0 - bc1);
							a = GetLerpFactor(l, transformedCoords[k0], transformedCoords[k1]);
							Verify(a >= 0.0f && a <= 1.0f);

							ct = l;

							break;
						}
						mask <<= 1;
					}

					//
					//------------------------------
					// Lerp the homogeneous position
					//------------------------------
					//
					clipExtraCoords[clipped_index].Lerp(
						transformedCoords[k0],
						transformedCoords[k1],
						a
					);

					clipExtraCoords[clipped_index][clipTrick[ct][0]] = clipTrick[ct][1] ? clipExtraCoords[clipped_index].w : 0.0f;

					//
					//----------------------------------------------------------
					// If there are colors, lerp them in screen space for now as
					// most cards do that anyway
					//----------------------------------------------------------
					//
					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

					//
					//-----------------------------------------------------
					// 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
						);

					//
					//--------------------------------
					// Bump the polygon's vertex count
					//--------------------------------
					//
					numberVerticesPerPolygon++;
				}
			}

			//
			//---------------------------------------------------------------
			// 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
				Statistics::MLR_PolysClippedButGOnePlane++;
#endif
				ClipPolygon clipBuffer[2];
				ClipData srcPolygon, dstPolygon;
				int dstBuffer = 1;

				Verify((*actualColors).GetLength() > 0);
				Verify(texCoords.GetLength() > 0);

				srcPolygon.coords = clipBuffer[dstBuffer].coords.GetData();
				srcPolygon.colors = clipBuffer[dstBuffer].colors.GetData();
				srcPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData();
				srcPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.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];
					srcPolygon.colors[l] = (*actualColors)[indexK];
					srcPolygon.texCoords[l] = texCoords[indexK];
					srcPolygon.clipPerVertex[l] = clipPerVertex[indexK];
				}

				srcPolygon.length = l;
				srcPolygon.flags |= 3;


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

				dstPolygon.coords = clipBuffer[dstBuffer].coords.GetData();
				dstPolygon.colors = clipBuffer[dstBuffer].colors.GetData();
				dstPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData();
				dstPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData();
				dstPolygon.flags = srcPolygon.flags;
				dstPolygon.length = 0;

				//
				//-----------------------------------------------------------
				// Spin through each plane that clipped the primitive and use
				// it to actually clip the primitive
				//-----------------------------------------------------------
				//
				mask = 1;

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

						//
						//-----------------------------------
						// Clip each vertex against the plane
						//-----------------------------------
						//
						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)
							{
								dstPolygon.coords[dstPolygon.length] = 
									srcPolygon.coords[k];

								dstPolygon.clipPerVertex[dstPolygon.length] = 
									srcPolygon.clipPerVertex[k];

								if(srcPolygon.flags & 0x1)
								{
									dstPolygon.colors[dstPolygon.length] = 
										srcPolygon.colors[k];
								}

								if(srcPolygon.flags & 0x2)
								{
									dstPolygon.texCoords[dstPolygon.length] = 
										srcPolygon.texCoords[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 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
							//-------------------------------------------
							//

//							GetDoubleBC(l, bc0, bc1, srcPolygon.coords[k], srcPolygon.coords[k1]);

//							Verify(!Close_Enough(bc0, bc1));
//							a = bc0 / (bc0 - bc1);
							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
							);

							dstPolygon.coords[dstPolygon.length][clipTrick[l][0]] = clipTrick[l][1] ? dstPolygon.coords[dstPolygon.length].w : 0.0f;


							//
							//----------------------------------------------------------
							// If there are colors, lerp them in screen space for now as
							// most cards do that anyway
							//----------------------------------------------------------
							//
							if(srcPolygon.flags & 1)
							{
#if COLOR_AS_DWORD
								dstPolygon.colors[dstPolygon.length] = Color_DWORD_Lerp(
									srcPolygon.colors[k],
									srcPolygon.colors[k1],
									a
								);
#else
								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
							//-----------------------------------------------------
							//
							if(srcPolygon.flags & 2)
							{
								dstPolygon.texCoords[dstPolygon.length].Lerp
									(
										srcPolygon.texCoords[k],
										srcPolygon.texCoords[k1],
										a
									);
							}

							//
							//-------------------------------------
							// We have to generate a new clip state
							//-------------------------------------
							//
							dstPolygon.clipPerVertex[dstPolygon.length].SetClippingState(0);
							switch (l)
							{
							case 0:
								if(clippingFlags.IsTopClipped())
								{
									if(dstPolygon.coords[dstPolygon.length].w < dstPolygon.coords[dstPolygon.length].y)
									{
										dstPolygon.clipPerVertex[dstPolygon.length].SetTopClip();
									}
								}
							case 1:
								if(clippingFlags.IsBottomClipped())
								{
									if(dstPolygon.coords[dstPolygon.length].y < 0.0f)
									{
										dstPolygon.clipPerVertex[dstPolygon.length].SetBottomClip();
									}
								}
							case 2:
								if(clippingFlags.IsLeftClipped())
								{
									if(dstPolygon.coords[dstPolygon.length].w < dstPolygon.coords[dstPolygon.length].x)
									{
										dstPolygon.clipPerVertex[dstPolygon.length].SetLeftClip();
									}
								}
							case 3:
								if(clippingFlags.IsRightClipped())
								{
									if(dstPolygon.coords[dstPolygon.length].x < 0.0f)
									{
										dstPolygon.clipPerVertex[dstPolygon.length].SetRightClip();
									}
								}
							case 4:
								if(clippingFlags.IsNearClipped())
								{
									if(dstPolygon.coords[dstPolygon.length].z < 0.0f)
									{
										dstPolygon.clipPerVertex[dstPolygon.length].SetNearClip();
									}
								}
							case 5:
								if(clippingFlags.IsFarClipped())
								{
									if(dstPolygon.coords[dstPolygon.length].w < dstPolygon.coords[dstPolygon.length].z)
									{
										dstPolygon.clipPerVertex[dstPolygon.length].SetFarClip();
									}
								}
							}

							//
							//----------------------------------
							// 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();
						srcPolygon.colors = clipBuffer[dstBuffer].colors.GetData();
						srcPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData();
						srcPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData();	
						srcPolygon.length = dstPolygon.length;

						dstBuffer = !dstBuffer;

						dstPolygon.coords = clipBuffer[dstBuffer].coords.GetData();
						dstPolygon.colors = clipBuffer[dstBuffer].colors.GetData();
						dstPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData();
						dstPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData();
						dstPolygon.length = 0;

					}

					mask = mask << 1;
				}

				//
				//--------------------------------------------------
				// Move the most recent polygon into the clip buffer
				//--------------------------------------------------
				//
				for(k=0;k<srcPolygon.length;k++)
				{
					int clipped_index = myNumberUsedClipVertex + k;
					clipExtraCoords[clipped_index] = srcPolygon.coords[k];

					if(srcPolygon.flags & 0x1)
					{
						clipExtraColors[clipped_index] = srcPolygon.colors[k];
					}

					if(srcPolygon.flags & 0x2)
					{
						clipExtraTexCoords[clipped_index] = srcPolygon.texCoords[k];
					}
				}

				numberVerticesPerPolygon = srcPolygon.length;
			}

			clipExtraLength[myNumberUsedClipLength] = numberVerticesPerPolygon;
			myNumberUsedClipVertex += numberVerticesPerPolygon;
			myNumberUsedClipLength++;
			ret++;

//					clip

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

		j += stride;
	}

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

	k = visibleIndexedVertices.GetLength();

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

		//
		//--------------------------------------------------------
		// JM claims all vertices are in. lets check it. who knows
		//--------------------------------------------------------
		//
			Verify(transformedCoords[j].x >= 0.0f && transformedCoords[j].x <= transformedCoords[j].w );
			Verify(transformedCoords[j].y >= 0.0f && transformedCoords[j].y <= transformedCoords[j].w );
			Verify(transformedCoords[j].z >= 0.0f && transformedCoords[j].z <= transformedCoords[j].w );
			

			GOSCopyData(
				&gos_vertices[numGOSVertices],
				transformedCoords.GetData(),
				actualColors->GetData(),
				texCoords.GetData(),
				j
			);
			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++)
		{
			Verify((vt->GetLastIndex() + 3 + numGOSIndices) < vt->GetLength());

			gos_indices[numGOSIndices] = (unsigned short)(index[j] - visibleIndexedVertices[index[j]]);
			gos_indices[numGOSIndices+1] = (unsigned short)(index[j+k+1] - visibleIndexedVertices[index[j+k+1]]);
			gos_indices[numGOSIndices+2] = (unsigned short)(index[j+k] - visibleIndexedVertices[index[j+k]]);

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

	if(myNumberUsedClipLength > 0)
	{
		for(i=0,j=0;i<myNumberUsedClipLength;i++)
		{
			stride = clipExtraLength[i];

			for(k=1;k<stride-1;k++)
			{
				Verify((vt->GetLast() + 3 + numGOSVertices) < vt->GetLength());
				Verify((vt->GetLastIndex() + 3 + numGOSIndices) < vt->GetLength());

				GOSCopyTriangleData(
					&gos_vertices[numGOSVertices],
					clipExtraCoords.GetData(),
					clipExtraColors.GetData(),
					clipExtraTexCoords.GetData(),
					j, j+k+1, j+k
				);

				Verify(numGOSIndices%3 == 0);
				gos_indices[numGOSIndices] = numGOSVertices;
				gos_indices[numGOSIndices+1] = (unsigned short)(numGOSVertices + 1);
				gos_indices[numGOSIndices+2] = (unsigned short)(numGOSVertices + 2);

				numGOSVertices += 3;
				numGOSIndices += 3;
			}

			j += stride;
		}
	}

	vt->IncreaseIndex(numGOSIndices);
	vt->Increase(numGOSVertices);

	visible = numGOSVertices ? 1 : 0;

	if(visible)
	{
	}
	else
	{
	}

	CLEAR_MLRIndexedPolyMesh_CLIP();
	EndCycleTiming( &Statistics::MLR_ClipTime );

	return ret;
}
Пример #4
0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int 
	MLRNGonCloud::Clip(MLRClippingState clippingFlags, GOSVertexPool *vt)
{
	Check_Object(this);

	int i, j, k;
	int end, len = *usedNrOfNGons, ret = 0;

#if	EFECT_CLIPPED				// this effect gets not clipped
	int l, mask, k1, ct=0;
	Scalar a=0.0f, bc0, bc1;
#endif

	
	Check_Object(vt);
	gos_vertices = vt->GetActualVertexPool();
	Check_Pointer(gos_vertices);
	numGOSVertices = 0;

	//
	//--------------------------------------
	// See if we don't have to draw anything
	//--------------------------------------
	//
	if(clippingFlags.GetClippingState() == 0 || len <= 0)
	{
		if(len <= 0)
		{
			visible = 0;
		}
		else
		{
			//
			//-------------------------------
			// Handle the non-indexed version
			//-------------------------------
			//
			for(i=0,j=0;i<len;i++,j += numOfVertices)
			{
//				if(IsOn(i) == false)
//				{
//					continue;
//				}

				DWORD inColor = GOSCopyColor(&colors[2*i]);
				DWORD outColor = GOSCopyColor(&colors[2*i+1]);
				for(int z=1; z < numOfVertices-1; z++)
				{
					GOSCopyTriangleData(
						&gos_vertices[numGOSVertices],
						transformedCoords->GetData(),
						j, z+j+1, z+j,
						true
					);
					gos_vertices[numGOSVertices].argb = inColor;
					gos_vertices[numGOSVertices+1].argb = outColor;
					gos_vertices[numGOSVertices+2].argb = outColor;

					numGOSVertices += 3;
				}
			}

			Check_Object(vt);
			vt->Increase(numGOSVertices);
			
			visible = numGOSVertices ? 1 : 0;
		}

		return visible;
	}

	int	myNumberUsedClipVertex, myNumberUsedClipIndex, myNumberUsedClipLength;

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

	//
	//-------------------------------
	// Handle the non-indexed version
	//-------------------------------
	//
	//
	//-----------------------------------------------------------------
	// Step through each polygon, making sure that we don't try to clip
	// backfaced polygons
	//-----------------------------------------------------------------
	//
	for(i=0,j=0;i<len;i++,j+=numOfVertices)
	{
//		if(IsOn(i) == false)
//		{
//			continue;
//		}

		TurnVisible(i);

		//
		//---------------------------------------------------------------
		// 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+numOfVertices;

		Stuff::Vector4D *v4d = transformedCoords->GetData()+j;
		MLRClippingState *cs = clipPerVertex->GetData()+j;

		for(k=j;k<end;k++,v4d++,cs++)
		{
			cs->Clip4dVertex(v4d);

			theAnd &= (*clipPerVertex)[k];

			theOr |= (*clipPerVertex)[k];

#ifdef LAB_ONLY
			if(*cs==0)
			{
				Set_Statistic(NonClippedVertices, NonClippedVertices+1);
			}
			else
			{
				Set_Statistic(ClippedVertices, ClippedVertices+1);
			}
#endif
		}

		theAnd = theOr = 0;		//ASSUME NO CLIPPING NEEDED FOR MC2.  Its just not done here!

		//
		//-------------------------------------------------------------------
		// 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)
		{
			TurnInVisible(i);
		}
		else if (theOr == 0)
		{
			TurnVisible(i);

			DWORD inColor = GOSCopyColor(&colors[2*i]);
			DWORD outColor = GOSCopyColor(&colors[2*i+1]);

			for(int z=1; z < numOfVertices-1; z++)
			{
				GOSCopyTriangleData(
					&gos_vertices[numGOSVertices],
					transformedCoords->GetData(),
					j, z+j+1, z+j,
					true
				);
				gos_vertices[numGOSVertices].argb = inColor;
				gos_vertices[numGOSVertices+1].argb = outColor;
				gos_vertices[numGOSVertices+2].argb = outColor;

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

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

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

				numGOSVertices += 3;
			}

			ret++;
		}

		//
		//-----------------------------------------------------------------
		// It is not a trivial case, so we must now do real clipping on the
		// polygon
		//-----------------------------------------------------------------
		//
		else
		{
#if	EFECT_CLIPPED				// this effect gets not clipped

			int numberVerticesPerPolygon = 0;

			//
			//---------------------------------------------------------------
			// Handle the case of a single clipping plane by stepping through
			// the vertices and finding the edge it originates
			//---------------------------------------------------------------
			//
			if (theOr.GetNumberOfSetBits() == 1)
			{
				for(k=j;k<end;k++)
				{
					k1 = (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[k];
					if(theTest == 0)
					{
						clipExtraCoords[clipped_index] = transformedCoords[k];

						if(k==j)
						{
							clipExtraColors[clipped_index] = colors[2*i];
						}
						else
						{
							clipExtraColors[clipped_index] = colors[2*i+1];
						}

						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 if(clipPerVertex[k1] != 0)
					{
						Verify(clipPerVertex[k1] == clipPerVertex[k]);
						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))
						{
							//
							//-------------------------------------------
							// Find the clipping interval from bc0 to bc1
							//-------------------------------------------
							//
							a = GetLerpFactor(l, (*transformedCoords)[k], (*transformedCoords)[k1]);

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

							ct = l;

							break;
						}
						mask <<= 1;
					}

					//
					//------------------------------
					// Lerp the homogeneous position
					//------------------------------
					//
					clipExtraCoords[clipped_index].Lerp(
						transformedCoords[k],
						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
					//----------------------------------------------------------
					//
					clipExtraColors[clipped_index].Lerp(
						(k==j) ? colors[2*i] : colors[2*i+1],
						(k1==j) ? colors[2*i] : colors[2*i+1],
						a
					);

					//
					//--------------------------------
					// Bump the polygon's vertex count
					//--------------------------------
					//
					numberVerticesPerPolygon++;
				}
			}

			//
			//---------------------------------------------------------------
			// 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
			{
				EffectClipData srcPolygon, dstPolygon;
				int dstBuffer = 0;

				specialClipColors[0] = colors[2*i];

				for(l=1;l<numOfVertices;l++)
				{
					specialClipColors[l] = colors[2*i+1];
				}

				//
				//-----------------------------------------------------
				// Point the source polygon buffer at our original data
				//-----------------------------------------------------
				//
				srcPolygon.coords = &transformedCoords[j];
				srcPolygon.clipPerVertex = &clipPerVertex[j];							
				srcPolygon.flags = 0;


				srcPolygon.colors = specialClipColors.GetData();

				srcPolygon.length = numOfVertices;

				//
				//--------------------------------
				// Point to the destination buffer
				//--------------------------------
				//
				dstPolygon.coords = clipBuffer[dstBuffer].coords.GetData();
				dstPolygon.colors = clipBuffer[dstBuffer].colors.GetData();
				dstPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData();
				dstPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData();
				dstPolygon.flags = srcPolygon.flags;
				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;

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

							//
							//-----------------------------------
							// Clip each vertex against the plane
							//-----------------------------------
							//
							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)
								{
									dstPolygon.coords[dstPolygon.length] = 
										srcPolygon.coords[k];

									dstPolygon.clipPerVertex[dstPolygon.length] = 
										srcPolygon.clipPerVertex[k];

									dstPolygon.colors[dstPolygon.length] = 
										srcPolygon.colors[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 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
								//-------------------------------------------
								//
								bc0 = GetBC(l, srcPolygon.coords[k]);
								bc1 = GetBC(l, srcPolygon.coords[k1]);
								Verify(!Close_Enough(bc0, bc1));
								a = bc0 / (bc0 - bc1);
								Verify(a >= 0.0f && a <= 1.0f);

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

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


								//
								//----------------------------------------------------------
								// If there are colors, lerp them in screen space for now as
								// most cards do that anyway
								//----------------------------------------------------------
								//
								dstPolygon.colors[dstPolygon.length].Lerp(
									srcPolygon.colors[k],
									srcPolygon.colors[k1],
									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();
							srcPolygon.colors = clipBuffer[dstBuffer].colors.GetData();
	//						srcPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData();
							srcPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData();	
							srcPolygon.length = dstPolygon.length;

							dstBuffer = !dstBuffer;

							dstPolygon.coords = clipBuffer[dstBuffer].coords.GetData();
							dstPolygon.colors = clipBuffer[dstBuffer].colors.GetData();
	//						dstPolygon.texCoords = clipBuffer[dstBuffer].texCoords.GetData();
							dstPolygon.clipPerVertex = clipBuffer[dstBuffer].clipPerVertex.GetData();
							dstPolygon.length = 0;

						}

						mask = mask << 1;
					}

					theNewOr = 0;
					for(k=0;k<srcPolygon.length;k++)
					{
						theNewOr |= srcPolygon.clipPerVertex[k];
					}

					theOr == theNewOr;
					loop++;
				} while (theNewOr != 0 && loop--);

				Verify(theNewOr == 0);

				//
				//--------------------------------------------------
				// Move the most recent polygon into the clip buffer
				//--------------------------------------------------
				//
				for(k=0;k<srcPolygon.length;k++)
				{
					int clipped_index = myNumberUsedClipVertex + k;

					if(srcPolygon.coords[k].z == srcPolygon.coords[k].w)
					{
						srcPolygon.coords[k].z -= SMALL;
					}

					clipExtraCoords[clipped_index] = srcPolygon.coords[k];

					clipExtraColors[clipped_index] = srcPolygon.colors[k];
				}

				numberVerticesPerPolygon = srcPolygon.length;
			}

			clipExtraLength[myNumberUsedClipLength] = numberVerticesPerPolygon;
			myNumberUsedClipVertex += numberVerticesPerPolygon;
			myNumberUsedClipLength++;
			ret++;

//					clip

//					dont draw the original
			TurnInVisible(i);
#endif
		}
	}

#if	EFECT_CLIPPED				// this effect gets not clipped

	if(myNumberUsedClipLength > 0)
	{
		for(i=0,j=0;i<myNumberUsedClipLength;i++)
		{
			int stride = clipExtraLength[i];

			for(k=1;k<stride-1;k++)
			{
				Verify((vt->GetLast() + 3 + numGOSVertices) < vt->GetLength());

				GOSCopyTriangleData(
					&gos_vertices[numGOSVertices],
					clipExtraCoords.GetData(),
					clipExtraColors.GetData(),
					j, j+k+1, j+k,
					true
				);
#ifdef LAB_ONLY
				if(gShowClippedPolys)
				{
					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;
				}
#endif
				numGOSVertices += 3;
			}
			j += stride;
		}
	}
#endif

	vt->Increase(numGOSVertices);

	visible = numGOSVertices ? 1 : 0;

	if(visible)
	{
	}
	else
	{
	}

	return visible;
}