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