123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793 |
- //===========================================================================//
- // Copyright (C) Microsoft Corporation. All rights reserved. //
- //===========================================================================//
- #include "MLRHeaders.hpp"
- #if !defined(MLR_MLRCLIPTRICK_HPP)
- #include <MLR\MLRClipTrick.hpp>
- #endif
- extern DWORD gShowClippedPolys;
- //#############################################################################
- //####################### MLRTriangleCloud ##############################
- //#############################################################################
- DynamicArrayOf<MLRClippingState>
- *MLRTriangleCloud::clipPerVertex;
- DynamicArrayOf<Vector4D>
- *MLRTriangleCloud::clipExtraCoords;
- DynamicArrayOf<RGBAColor>
- *MLRTriangleCloud::clipExtraColors;
- DynamicArrayOf<int>
- *MLRTriangleCloud::clipExtraLength;
- MLRTriangleCloud::ClassData*
- MLRTriangleCloud::DefaultData = NULL;
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- //
- void
- MLRTriangleCloud::InitializeClass()
- {
- Verify(!DefaultData);
- Verify(gos_GetCurrentHeap() == StaticHeap);
- DefaultData =
- new ClassData(
- MLRTriangleCloudClassID,
- "MidLevelRenderer::MLRTriangleCloud",
- MLREffect::DefaultData
- );
- Register_Object(DefaultData);
-
- clipPerVertex = new DynamicArrayOf<MLRClippingState> (Limits::Max_Number_Vertices_Per_Mesh);
- Register_Pointer(clipPerVertex);
- clipExtraCoords = new DynamicArrayOf<Vector4D> (Limits::Max_Number_Vertices_Per_Mesh);
- Register_Pointer(clipExtraCoords);
- clipExtraColors = new DynamicArrayOf<RGBAColor> (Limits::Max_Number_Vertices_Per_Mesh);
- Register_Pointer(clipExtraColors);
-
- clipExtraLength = new DynamicArrayOf<int> (Limits::Max_Number_Primitives_Per_Frame);
- Register_Pointer(clipExtraLength);
- }
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- //
- void
- MLRTriangleCloud::TerminateClass()
- {
- Unregister_Pointer(clipPerVertex);
- delete clipPerVertex;
- Unregister_Pointer(clipExtraCoords);
- delete clipExtraCoords;
- Unregister_Pointer(clipExtraColors);
- delete clipExtraColors;
-
- Unregister_Pointer(clipExtraLength);
- delete clipExtraLength;
- Unregister_Object(DefaultData);
- delete DefaultData;
- DefaultData = NULL;
- }
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- //
- MLRTriangleCloud::MLRTriangleCloud(int nr) :
- MLREffect(nr, DefaultData)
- {
- Verify(gos_GetCurrentHeap() == Heap);
- usedNrOfTriangles = NULL;
- Check_Pointer(this);
-
- drawMode = SortData::TriList;
- }
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- //
- MLRTriangleCloud::~MLRTriangleCloud()
- {
- Check_Object(this);
- }
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- //
- void
- MLRTriangleCloud::SetData
- (
- const int *count,
- const Stuff::Point3D *point_data,
- const Stuff::RGBAColor *color_data
- )
- {
- Check_Pointer(this);
- usedNrOfTriangles = count;
- Verify(*usedNrOfTriangles <= maxNrOf);
- points = point_data;
- colors = color_data;
- }
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- //
- void
- MLRTriangleCloud::Draw (DrawEffectInformation *dInfo, GOSVertexPool *allVerticesToDraw, MLRSorter *sorter)
- {
- Check_Object(this);
- worldToEffect.Invert(*dInfo->effectToWorld);
- Transform(*usedNrOfTriangles, 3);
- #if 0
- Lighting(*shape->worldToShape, dInfo->activeLights, dInfo->nrOfActiveLights);
- #endif
- if( Clip(dInfo->clippingFlags, allVerticesToDraw) )
- {
- sorter->AddEffect(this, dInfo->state);
- }
- }
- static MLRClippingState theAnd, theOr, theTest;
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- //
- int
- MLRTriangleCloud::Clip(MLRClippingState clippingFlags, GOSVertexPool *vt)
- {
- Check_Object(this);
- int i, j, k;
- int end, len = *usedNrOfTriangles;
- int ret = 0;
- #if EFECT_CLIPPED // this effect gets not clipped
- int l, mask, k1, ct=0,
- Scalar a=0.0f, bc0, bc1;
- #endif
-
- //
- //--------------------------------------
- // See if we don't have to draw anything
- //--------------------------------------
- //
- if(clippingFlags.GetClippingState() == 0 || len <= 0)
- {
- if(len <= 0)
- {
- visible = 0;
- }
- else
- {
- Check_Object(vt);
- gos_vertices = vt->GetActualVertexPool();
- numGOSVertices = 0;
- //
- //-------------------------------
- // Handle the non-indexed version
- //-------------------------------
- //
- for(i=0,j=0;i<len;i++,j+=3)
- {
- if(IsOn(i) == false)
- {
- continue;
- }
- GOSCopyTriangleData(
- &gos_vertices[numGOSVertices],
- transformedCoords->GetData(),
- colors,
- j, j+2, j+1,
- true
- );
- numGOSVertices += 3;
- }
- Check_Object(vt);
- vt->Increase(numGOSVertices);
-
- visible = numGOSVertices ? 1 : 0;
- }
- return visible;
- }
- int myNumberUsedClipVertex, myNumberUsedClipIndex, myNumberUsedClipLength;
- myNumberUsedClipVertex = 0;
- myNumberUsedClipIndex = 0;
- myNumberUsedClipLength = 0;
- gos_vertices = vt->GetActualVertexPool();
- numGOSVertices = 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+=3)
- {
- // 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+3;
- 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)
- {
- continue;
- // TurnInVisible(i);
- }
- else if (theOr == 0)
- {
- // TurnVisible(i);
- GOSCopyTriangleData(
- &gos_vertices[numGOSVertices],
- transformedCoords->GetData(),
- colors,
- j, j+2, j+1,
- true
- );
- #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];
- clipExtraColors[clipped_index] = colors[k];
- 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(
- colors[k],
- colors[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
- {
- EffectClipData srcPolygon, dstPolygon;
- int dstBuffer = 0;
- //
- //-----------------------------------------------------
- // Point the source polygon buffer at our original data
- //-----------------------------------------------------
- //
- srcPolygon.coords = &transformedCoords[j];
- srcPolygon.clipPerVertex = &clipPerVertex[j];
- srcPolygon.flags = 0;
- srcPolygon.colors = const_cast<RGBAColor*>(&colors[j]);
- srcPolygon.flags |= 1;
- srcPolygon.texCoords = NULL;
- srcPolygon.length = 3;
- //
- //--------------------------------
- // 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];
- 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
- //-------------------------------------------
- //
- 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
- //----------------------------------------------------------
- //
- if(srcPolygon.flags & 1)
- {
- 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
- //-----------------------------------------------------
- //
- 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].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;
- }
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- //
- void
- MLRTriangleCloud::TestInstance() const
- {
- if (usedNrOfTriangles)
- {
- Check_Pointer(usedNrOfTriangles);
- Verify(*usedNrOfTriangles >= 0);
- Verify(*usedNrOfTriangles <= maxNrOf);
- }
- }
|