#include "MLRHeaders.hpp" #if !defined(MLR_MLRCLIPTRICK_HPP) #include #endif #if !defined(MLR_MLRINDEXEDTRIANGLECLOUD_HPP) #include #endif extern DWORD gShowClippedPolys; extern WORD *indexOffset; // [MidLevelRenderer::Max_Number_Vertices_Per_Effect] //############################################################################# //#################### MLRIndexedTriangleCloud ########################## //############################################################################# DynamicArrayOf *MLRIndexedTriangleCloud::clipExtraIndex; DynamicArrayOf *MLRIndexedTriangleCloud::clipExtraTexCoords; DynamicArrayOf *MLRIndexedTriangleCloud::visibleIndexedVertices; MLRIndexedTriangleCloud::ClassData* MLRIndexedTriangleCloud::DefaultData = NULL; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MLRIndexedTriangleCloud::InitializeClass() { Verify(!DefaultData); Verify(gos_GetCurrentHeap() == StaticHeap); DefaultData = new ClassData( MLRIndexedTriangleCloudClassID, "MidLevelRenderer::MLRIndexedTriangleCloud", MLRTriangleCloud::DefaultData ); Register_Object(DefaultData); clipExtraIndex = new DynamicArrayOf (Limits::Max_Number_Vertices_Per_Effect); Register_Pointer(clipExtraIndex); clipExtraTexCoords = new DynamicArrayOf (Limits::Max_Number_Vertices_Per_Effect); Register_Pointer(clipExtraTexCoords); visibleIndexedVertices = new DynamicArrayOf (Limits::Max_Number_Vertices_Per_Effect); Register_Pointer(visibleIndexedVertices); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MLRIndexedTriangleCloud::TerminateClass() { Unregister_Pointer(clipExtraIndex); delete clipExtraIndex; Unregister_Pointer(clipExtraTexCoords); delete clipExtraTexCoords; Unregister_Pointer(visibleIndexedVertices); delete visibleIndexedVertices; Unregister_Object(DefaultData); delete DefaultData; DefaultData = NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MLRIndexedTriangleCloud::MLRIndexedTriangleCloud(int nr) : MLRTriangleCloud(nr) { Verify(gos_GetCurrentHeap() == EffectHeap); usedNrOfPoints = NULL; Check_Pointer(this); drawMode = SortData::TriIndexedList; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MLRIndexedTriangleCloud::~MLRIndexedTriangleCloud() { Check_Object(this); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MLRIndexedTriangleCloud::SetData ( const int *tri_count, const int *point_count, const WORD *index_data, const Stuff::Point3D *point_data, const Stuff::RGBAColor *color_data, const Vector2DScalar *uv_data ) { Check_Pointer(this); usedNrOfTriangles = tri_count; usedNrOfPoints = point_count; Verify(*usedNrOfTriangles <= maxNrOf); index = index_data; points = point_data; colors = color_data; texCoords = uv_data; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MLRIndexedTriangleCloud::Draw (DrawEffectInformation *dInfo, GOSVertexPool *allVerticesToDraw, MLRSorter *sorter) { Check_Object(this); #ifdef LAB_ONLY if(Limits::Max_Number_Vertices_Per_Frame < allVerticesToDraw->GetLast() + *usedNrOfPoints) { SPEWALWAYS((0, "Not drawing MLRIndexedTriangleCloud. Too many vertices! Raid a bug to Art!")); return; } if(Limits::Max_Number_Vertices_Per_Frame < allVerticesToDraw->GetLastIndex() + *usedNrOfTriangles * 3) { SPEWALWAYS((0, "Not drawing MLRIndexedTriangleCloud. Too many indices! Raid a bug to Art!")); return; } #endif worldToEffect.Invert(*dInfo->effectToWorld); Vector4D *v4 = transformedCoords->GetData(); for(int k=0;k<*usedNrOfPoints;k++, v4++) { v4->Multiply(points[k], effectToClipMatrix); (*clipPerVertex)[k].Clip4dVertex(v4); } if( Clip(dInfo->clippingFlags, allVerticesToDraw, false) ) { sorter->AddEffect(this, dInfo->state); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int MLRIndexedTriangleCloud::Draw (ToBeDrawnPrimitive *tbdp, MLRSorter *sorter) { Check_Object(this); Vector4D *v4 = transformedCoords->GetData(); for(int k=0;k<*usedNrOfPoints;k++, v4++) { v4->Multiply(points[k], tbdp->shapeToClipMatrix); (*clipPerVertex)[k].Clip4dVertex(v4); } int index = -1; if( Clip(tbdp->clippingFlags, tbdp->allVerticesToDraw, true) ) { sorter->AddEffect(this, tbdp->state, index); } return index; } static MLRClippingState theAnd, theOr, theTest; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int MLRIndexedTriangleCloud::Clip(MLRClippingState clippingFlags, GOSVertexPool *vt, bool db) { 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(); WORD l; int index0, index1, index2, ret = 0; int mask; Scalar a = 0.0f; for(i=0,j=0;i<*usedNrOfTriangles;j+=3,++i) { // if(IsOn(i) == false) // { // continue; // } 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]; theOr = theAnd; theAnd &= (cs[index1] & cs[index2]); theOr |= (cs[index1] | cs[index2]); // //------------------------------------------------------------------- // 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 { WORD numberVerticesPerPolygon = 0; // //--------------------------------------------------------------- // Handle the case of a single clipping plane by stepping through // the vertices and finding the edge it originates //--------------------------------------------------------------- // bool firstIsIn; if (theOr.GetNumberOfSetBits() == 1) { #ifdef LAB_ONLY Set_Statistic(PolysClippedButOnePlane, PolysClippedButOnePlane+1); #endif for(k=j;k= 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 //---------------------------------------------------------- // (*clipExtraColors)[clipped_index].Lerp( colors[k0], colors[k1], a ); // //----------------------------------------------------- // 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 //---------------------------------------------------------- // (*clipExtraColors)[clipped_index].Lerp( colors[k1], colors[k0], a ); // //----------------------------------------------------- // 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= 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 //---------------------------------------------------------- // dstPolygon.colors[dstPolygon.length].Lerp( srcPolygon.colors[k], srcPolygon.colors[k1], a ); // //----------------------------------------------------- // 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 //---------------------------------------------------------- // dstPolygon.colors[dstPolygon.length].Lerp( srcPolygon.colors[k1], srcPolygon.colors[k], a ); // //----------------------------------------------------- // 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;kGetActualVertexPool(db); numGOSVertices = 0; gos_indices = vt->GetActualIndexPool(db); numGOSIndices = 0; WORD strideIndex; for(j=0,strideIndex=0;j<*usedNrOfPoints;j++) { if((*visibleIndexedVertices)[j] == 0) { strideIndex++; } else { indexOffset[j] = static_cast(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; } if(db==false) { 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; } WORD stride; if(myNumberUsedClipLength > 0) { for(i=0,j=0;i((*clipExtraLength)[i] & 0x7fff); #else stride = static_cast((*clipExtraLength)[i]); #endif for(k=1;kGetLast() + 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 if(db==false) { Verify((vt->GetLastIndex() + 3 + numGOSIndices) < vt->GetLength()); Verify(numGOSIndices%3 == 0); } gos_indices[numGOSIndices] = (WORD)numGOSVertices; gos_indices[numGOSIndices+1] = (WORD)(numGOSVertices + 1); gos_indices[numGOSIndices+2] = (WORD)(numGOSVertices + 2); numGOSVertices += 3; numGOSIndices += 3; } j += stride; } #if HUNT_CLIP_ERROR DEBUG_STREAM << "***" << endl << endl; #endif } if(db==false) { vt->Increase(numGOSVertices); vt->IncreaseIndex(numGOSIndices); } return numGOSIndices; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MLRIndexedTriangleCloud::TestInstance() const { if (usedNrOfTriangles) { Check_Pointer(usedNrOfTriangles); Verify(*usedNrOfTriangles >= 0); Verify(*usedNrOfTriangles <= maxNrOf); } }