//===========================================================================// // Copyright (C) Microsoft Corporation. All rights reserved. // //===========================================================================// #include "MLRHeaders.hpp" extern DWORD gEnableTextureSort, gEnableAlphaSort, gEnableLightMaps; MLRSortByOrder::ClassData* MLRSortByOrder::DefaultData = NULL; //############################################################################# //############################ MLRSortByOrder ################################ //############################################################################# //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MLRSortByOrder::InitializeClass() { Verify(!DefaultData); Verify(gos_GetCurrentHeap() == StaticHeap); DefaultData = new ClassData( MLRSortByOrderClassID, "MidLevelRenderer::MLRSortByOrder", MLRSorter::DefaultData ); Register_Object(DefaultData); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MLRSortByOrder::TerminateClass() { Unregister_Object(DefaultData); delete DefaultData; DefaultData = NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MLRSortByOrder::MLRSortByOrder(MLRTexturePool *tp) : MLRSorter(DefaultData, tp) { Verify(gos_GetCurrentHeap() == Heap); int i; gos_PushCurrentHeap(StaticHeap); for(i=0;iGetSortDataMode()) { case SortData::TriList: case SortData::TriIndexedList: sd = SetRawData(pt, pass); break; } unsigned priority = pt->GetCurrentState(pass).GetPriority(); if(sd != NULL) { priorityBuckets[priority][lastUsedInBucket[priority]++] = sd; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MLRSortByOrder::AddEffect(MLREffect *ef, const MLRState& state) { Check_Object(this); Check_Object(ef); SortData *sd = NULL; switch(ef->GetSortDataMode()) { case SortData::PointCloud: sd = SetRawData( ef->GetGOSVertices(), ef->GetNumGOSVertices(), state, SortData::PointCloud ); sd->numIndices = ef->GetType(0); break; case SortData::LineCloud: sd = SetRawData( ef->GetGOSVertices(), ef->GetNumGOSVertices(), state, SortData::LineCloud ); sd->numIndices = ef->GetType(0); break; case SortData::TriList: sd = SetRawData( ef->GetGOSVertices(), ef->GetNumGOSVertices(), state, SortData::TriList ); break; case SortData::TriIndexedList: { MLRIndexedTriangleCloud *itc = Cast_Object(MLRIndexedTriangleCloud*, ef); sd = SetRawIndexedData( itc->GetGOSVertices(), itc->GetNumGOSVertices(), itc->GetGOSIndices(), itc->GetNumGOSIndices(), state, SortData::TriIndexedList ); } break; } unsigned priority = state.GetPriority(); if(sd != NULL) { priorityBuckets[priority][lastUsedInBucket[priority]++] = sd; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MLRSortByOrder::AddScreenQuads ( GOSVertex *vertices, const DrawScreenQuadsInformation *dInfo ) { Verify(dInfo->currentNrOfQuads != 0 && (dInfo->currentNrOfQuads&3) == 0); SortData *sd = SetRawData ( vertices, dInfo->currentNrOfQuads, dInfo->state, SortData::Quads ); unsigned priority = dInfo->state.GetPriority(); if(sd != NULL) { priorityBuckets[priority][lastUsedInBucket[priority]++] = sd; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MLRSortByOrder::AddSortRawData(SortData *sd) { Check_Object(this); if(sd==NULL) { return; } unsigned priority = sd->state.GetPriority(); priorityBuckets[priority][lastUsedInBucket[priority]++] = sd; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MLRSortByOrder::RenderNow () { Check_Object(this); // // So GameOS knows how long the transform and clip and lighting took of update renderers // Stuff::DynamicArrayOf *priorityBucket; Stuff::DynamicArrayOf *priorityBucketNotDrawn; GOSVertex::farClipReciprocal = farClipReciprocal; int i, j, k; // Limits::Max_Number_Primitives_Per_Frame + Max_Number_ScreenQuads_Per_Frame MLRPrimitiveBase *primitive; for(i=0;i0;hh/=3) { for(ii=hh;ii=hh && (*priorityBucketNotDrawn)[jj-hh]->state.GetTextureHandle() > tempSortData->state.GetTextureHandle()) { (*priorityBucketNotDrawn)[jj] = (*priorityBucketNotDrawn)[jj-hh]; jj -= hh; } (*priorityBucketNotDrawn)[jj] = tempSortData; } } Stop_Timer(Texture_Sorting_Time); } if(i != MLRState::AlphaPriority) { for(j=0;jprimitive; Check_Object(primitive); int nrOfLightMaps = 0; for(k=0;knrOfActiveLights;k++) { Check_Object(tbdp->activeLights[k]); nrOfLightMaps += (tbdp->activeLights[k]->GetLightMap() != NULL) ? 1 : 0; tbdp->activeLights[k]->SetLightToShapeMatrix(tbdp->worldToShape); } if(!gEnableLightMaps) { nrOfLightMaps = 0; } if(nrOfLightMaps) { MLRLightMap::SetDrawData ( ToBeDrawnPrimitive::allVerticesToDraw, &tbdp->shapeToClipMatrix, tbdp->clippingFlags, tbdp->state ); } if(primitive->FindBackFace(tbdp->cameraPosition)) { primitive->Lighting(tbdp->activeLights, tbdp->nrOfActiveLights); if(tbdp->clippingFlags.GetClippingState() != 0) { if(primitive->TransformAndClip( &tbdp->shapeToClipMatrix, tbdp->clippingFlags, ToBeDrawnPrimitive::allVerticesToDraw, true) ) { if(primitive->GetVisible()) { for(k=0;kGetNumPasses();k++) { DrawPrimitive(primitive, k); } } } } else { primitive->TransformNoClip( &tbdp->shapeToClipMatrix, ToBeDrawnPrimitive::allVerticesToDraw, true); for(k=0;kGetNumPasses();k++) { DrawPrimitive(primitive, k); } } #ifdef LAB_ONLY Set_Statistic(Number_Of_Primitives, Number_Of_Primitives+1); if(primitive->IsDerivedFrom(MLRIndexedPrimitiveBase::DefaultData)) { Point3D *coords; unsigned short *indices; int nr; (Cast_Pointer(MLRIndexedPrimitiveBase*, primitive))->GetIndexData(&indices, &nr); Set_Statistic(NumAllIndices, NumAllIndices+nr); primitive->GetCoordData(&coords, &nr); Set_Statistic(NumAllVertices, NumAllVertices + nr); Set_Statistic(Index_Over_Vertex_Ratio, (Scalar)NumAllIndices/(Scalar)NumAllVertices); } #endif } if(nrOfLightMaps) { MLRLightMap::DrawLightMaps(this); } } } else { SortData *sd = NULL; for(j=0;jprimitive; if(primitive->FindBackFace(tbdp->cameraPosition)) { primitive->Lighting(tbdp->activeLights, tbdp->nrOfActiveLights); if(tbdp->clippingFlags.GetClippingState() != 0) { if(primitive->TransformAndClip( &tbdp->shapeToClipMatrix, tbdp->clippingFlags, ToBeDrawnPrimitive::allVerticesToDraw, true) ) { if(!primitive->GetVisible()) { continue; } } } else { primitive->TransformNoClip( &tbdp->shapeToClipMatrix, ToBeDrawnPrimitive::allVerticesToDraw, true); } #ifdef LAB_ONLY Set_Statistic(Number_Of_Primitives, Number_Of_Primitives+1); if(primitive->IsDerivedFrom(MLRIndexedPrimitiveBase::DefaultData)) { Point3D *coords; unsigned short *indices; int nr; (Cast_Pointer(MLRIndexedPrimitiveBase*, primitive))->GetIndexData(&indices, &nr); Set_Statistic(NumAllIndices, NumAllIndices+nr); primitive->GetCoordData(&coords, &nr); Set_Statistic(NumAllVertices, NumAllVertices+nr); Set_Statistic(Index_Over_Vertex_Ratio, (Scalar)NumAllIndices/(Scalar)NumAllVertices); } #endif } else { continue; } if(primitive->GetNumGOSVertices() > 0) for(k=0;kGetNumPasses();k++) { sd = SetRawData(primitive, k); Check_Pointer(sd); if( gEnableAlphaSort && (sd->type == SortData::TriList || sd->type == SortData::TriIndexedList) ) { SortData::LoadSortAlphaFunc alphaFunc = sd->LoadSortAlpha[sd->type]; Verify(alphaToSort+sd->numVertices/3 < 2*Limits::Max_Number_Vertices_Per_Frame); alphaToSort += (sd->*alphaFunc)(alphaSort.GetData() + alphaToSort); } else { if(theCurrentState != sd->state) { SetDifferences(theCurrentState, sd->state); theCurrentState = sd->state; } SortData::DrawFunc drawFunc = sd->Draw[sd->type]; (sd->*drawFunc)(); } } } } } #endif if(lastUsedInBucket[i]) { Verify(lastUsedInBucket[i]<=Limits::Max_Number_Primitives_Per_Frame + Limits::Max_Number_ScreenQuads_Per_Frame); if( gEnableTextureSort && i != MLRState::AlphaPriority) { Start_Timer(Texture_Sorting_Time); // do a shell sort int ii, jj, hh; SortData *tempSortData; priorityBucket = &priorityBuckets[i]; for(hh=1;hh0;hh/=3) { for(ii=hh;ii=hh && (*priorityBucket)[jj-hh]->state.GetTextureHandle() > tempSortData->state.GetTextureHandle()) { (*priorityBucket)[jj] = (*priorityBucket)[jj-hh]; jj -= hh; } (*priorityBucket)[jj] = tempSortData; } } Stop_Timer(Texture_Sorting_Time); } if(i != MLRState::AlphaPriority) { for(j=0;jstate) { SetDifferences(theCurrentState, sd->state); theCurrentState = sd->state; } SortData::DrawFunc drawFunc = sd->Draw[sd->type]; // _clear87(); (sd->*drawFunc)(); // _clear87(); } } else { for(j=0;jtype == SortData::TriList || sd->type == SortData::TriIndexedList) ) { SortData::LoadSortAlphaFunc alphaFunc = sd->LoadSortAlpha[sd->type]; Verify(alphaToSort+sd->numVertices/3 < 2*Limits::Max_Number_Vertices_Per_Frame); alphaToSort += (sd->*alphaFunc)(alphaSort.GetData() + alphaToSort); } else { if(theCurrentState != sd->state) { SetDifferences(theCurrentState, sd->state); theCurrentState = sd->state; } SortData::DrawFunc drawFunc = sd->Draw[sd->type]; (sd->*drawFunc)(); } } } } if(alphaToSort > 0) { Start_Timer(Alpha_Sorting_Time); // do a shell sort int ii, jj, hh; SortAlpha *tempSortAlpha; Stuff::DynamicArrayOf *alphaArray; alphaArray = &alphaSort; for(hh=1;hh0;hh/=3) { for(ii=hh;ii=hh && (*alphaArray)[jj-hh]->distance < tempSortAlpha->distance) { (*alphaArray)[jj] = (*alphaArray)[jj-hh]; jj -= hh; } (*alphaArray)[jj] = tempSortAlpha; } } Stop_Timer(Alpha_Sorting_Time); for(ii=0;iistate) { SetDifferences(theCurrentState, *alphaSort[ii]->state); theCurrentState = *alphaSort[ii]->state; } Start_Timer(GOS_Draw_Time); if ((alphaSort[ii]->triangle[0].z >= 0.0f) && (alphaSort[ii]->triangle[0].z < 1.0f) && (alphaSort[ii]->triangle[1].z >= 0.0f) && (alphaSort[ii]->triangle[1].z < 1.0f) && (alphaSort[ii]->triangle[2].z >= 0.0f) && (alphaSort[ii]->triangle[2].z < 1.0f)) { gos_DrawTriangles( &(alphaSort[ii]->triangle[0]), 3); } Stop_Timer(GOS_Draw_Time); } Set_Statistic(NumberOfAlphaSortedTriangles, NumberOfAlphaSortedTriangles+alphaToSort); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MLRSortByOrder::TestInstance() const { Verify(IsDerivedFrom(DefaultData)); }