@@ -9006,6 +9006,10 @@ xbox::void_xt WINAPI xbox::EMUPATCH(D3DDevice_InsertCallback)
90069006unsigned int MaxRectPatchVertexCount = 0 ;
90079007std::map<uint32_t , D3DRECTPATCH_INFO> g_RectPatchInfoCache;
90089008std::map<uint32_t , D3DTRIPATCH_INFO> g_TriPatchInfoCache;
9009+ // global flag true: using DrawRectPatch. false: converting patches to triangle stripes.
9010+ bool g_bUseDrawPatch = false ;
9011+ INDEX16 IndexedPatchVertex[0x250 ];
9012+ static inline int GetIndex (int x, int y, int stride) { return x + y * stride; }
90099013// ******************************************************************
90109014// * patch: D3DDevice_DrawRectPatch
90119015// ******************************************************************
@@ -9025,7 +9029,6 @@ xbox::hresult_xt WINAPI xbox::EMUPATCH(D3DDevice_DrawRectPatch)
90259029 CxbxUpdateNativeD3DResources ();
90269030 // setup DrawContext in order to call VertexBufferConverter.Apply() to setup stream source and vertex buffer
90279031 CxbxDrawContext DrawContext = {};
9028- DrawContext.XboxPrimitiveType = xbox::X_D3DPRIMITIVETYPE::X_D3DPT_QUADLIST;
90299032 D3DRECTPATCH_INFO tmpRectPatchInfo;
90309033 if (pRectPatchInfo != nullptr ) {
90319034 g_RectPatchInfoCache.insert (std::pair<uint32_t , D3DRECTPATCH_INFO>(Handle, *pRectPatchInfo));
@@ -9036,14 +9039,106 @@ xbox::hresult_xt WINAPI xbox::EMUPATCH(D3DDevice_DrawRectPatch)
90369039 tmpRectPatchInfo = it->second ;
90379040 pRectPatchInfo = &tmpRectPatchInfo;
90389041 }
9039- DrawContext.dwVertexCount = (pRectPatchInfo->StartVertexOffsetHeight + pRectPatchInfo->Height ) * pRectPatchInfo->Stride ;
9040- // keep max. vertex count so we can use same vertex count in DrawContext which will result in using the same vertex buffer cache.
9041- if (MaxRectPatchVertexCount < DrawContext.dwVertexCount )MaxRectPatchVertexCount = DrawContext.dwVertexCount ;
9042- DrawContext.dwVertexCount = MaxRectPatchVertexCount;
9043- VertexBufferConverter.Apply (&DrawContext);
9044- HRESULT hRet = g_pD3DDevice->DrawRectPatch (Handle, pNumSegs, pRectPatchInfo);
9045- DEBUG_D3DRESULT (hRet, " g_pD3DDevice->DrawRectPatch" );
9046- return hRet;
9042+
9043+ DrawContext.XboxPrimitiveType = xbox::X_D3DPRIMITIVETYPE::X_D3DPT_TRIANGLESTRIP;
9044+ /*
9045+
9046+ illustration of a 4X3 RectPatch
9047+ StartVertexOffsetWidth :2
9048+ |<----->|
9049+ V0 V1 V2 V3 V4 ---
9050+ -------------- | StartVertexOffsetHeight:1
9051+ V5 V6 | V7 V8 V9 | --- ---
9052+ /|\
9053+ V10 V11 |V12 V13 V14 | |
9054+ | Height:4
9055+ V15 V16 |V17 V18 V19 | |
9056+ \|/
9057+ V20 V21 |V22 V23 V24 | ---
9058+ --------------
9059+ |<----->| Width:3
9060+
9061+ |<-------------->| Stride:5
9062+
9063+ start vertex index V7 = StartVertexOffsetWidth + StartVertexOffsetHeight * Stride; 2 + 1*5 =7
9064+
9065+ for any given vertex in position x, y, assuming origin is on top left corner, x positive to right, y positive to down.
9066+ the index of given vertex is x + y * Stride
9067+
9068+ give vertex V7, (x,y)=(2,1), index = 2 + 1* 5 =7
9069+
9070+ vertex index in upper row is index(V7) - Stride = 7 - 5 = 2
9071+ vertex index in lower rwo is index(V7) + stride = 7 + 5 = 12
9072+ vertex index in right is index(V7) + 1 = 8
9073+ vertex index in left is index(V7) - 1 = 6
9074+
9075+ we're going to create a index buffer to conver the 4X3 RectPatch into 3 triangle strips.
9076+
9077+ V5 V6 V7 V8 V9
9078+ |\ |\ |
9079+ | \ | \ |
9080+ | \| \|
9081+ V10 V11 V12 V13 V14
9082+ |\ |\ |
9083+ | \ | \ |
9084+ | \| \|
9085+ V15 V16 V17 V18 V19
9086+ |\ |\ |
9087+ | \ | \ |
9088+ | \| \|
9089+ V20 V21 V22 V23 V24
9090+
9091+ test case: Patch sample uses 4X4 RectPatch
9092+ test case: True Crime Streets of LA ?
9093+
9094+ */
9095+
9096+ // g_bUseDrawPatch is global flag which we can dynamically switch between using DrawRectPatch or converting patches to triangle stripes.
9097+ if (!g_bUseDrawPatch){
9098+ int index = 0 ;
9099+ int stride = pRectPatchInfo->Stride ;
9100+ int originY = pRectPatchInfo->StartVertexOffsetHeight ;
9101+ int originX = pRectPatchInfo->StartVertexOffsetWidth ;
9102+ int y;
9103+ int StartVertexIndex= pRectPatchInfo->StartVertexOffsetHeight * pRectPatchInfo->Stride + pRectPatchInfo->StartVertexOffsetWidth ;
9104+ for ( int deltaY = 1 ; deltaY < (pRectPatchInfo->Height ); deltaY++) {
9105+ y = originY + deltaY;
9106+ int x;
9107+ for (int deltaX = 0 ; deltaX < (pRectPatchInfo->Width ); deltaX++) {
9108+ x = originX + deltaX;
9109+ /*
9110+ (x,y-1)(x+1,y-1)
9111+ V5 V6 V7 V8 V9
9112+ |\ |\ |
9113+ | \ | \ |
9114+ | \ | \ |
9115+ | \| \|
9116+ V10 V11 V12 V13 V14
9117+ (x,y) (x+1,y)
9118+ 1st loop: V12,V7,
9119+ 2nd loop: V13,V8,
9120+ 3rd loop: V14,V9
9121+ */
9122+ IndexedPatchVertex[index++] = GetIndex ( x, y, stride);
9123+ IndexedPatchVertex[index++] = GetIndex ( x, y-1 , stride);
9124+ }
9125+ }
9126+ DrawContext.dwVertexCount = index;
9127+ DrawContext.pXboxIndexData = IndexedPatchVertex;
9128+ DrawContext.dwStartVertex = 0 ;
9129+ CxbxDrawIndexed (DrawContext);
9130+ return S_OK;
9131+ }
9132+ else {
9133+ DrawContext.dwVertexCount = (pRectPatchInfo->StartVertexOffsetHeight + pRectPatchInfo->Height ) * pRectPatchInfo->Stride ;
9134+ // keep max. vertex count so we can use same vertex count in DrawContext which will result in using the same vertex buffer cache.
9135+ if (MaxRectPatchVertexCount < DrawContext.dwVertexCount )MaxRectPatchVertexCount = DrawContext.dwVertexCount ;
9136+ DrawContext.dwVertexCount = MaxRectPatchVertexCount;
9137+ VertexBufferConverter.Apply (&DrawContext);
9138+ HRESULT hRet = g_pD3DDevice->DrawRectPatch (Handle, pNumSegs, pRectPatchInfo);
9139+ DEBUG_D3DRESULT (hRet, " g_pD3DDevice->DrawRectPatch" );
9140+ return hRet;
9141+ }
90479142}
90489143
90499144// ******************************************************************
0 commit comments