Skip to content

Commit 8172c68

Browse files
committed
add code to convert RectPatch to indexed triangle strips.
1 parent 9838d27 commit 8172c68

1 file changed

Lines changed: 104 additions & 9 deletions

File tree

src/core/hle/D3D8/Direct3D9/Direct3D9.cpp

Lines changed: 104 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9006,6 +9006,10 @@ xbox::void_xt WINAPI xbox::EMUPATCH(D3DDevice_InsertCallback)
90069006
unsigned int MaxRectPatchVertexCount = 0;
90079007
std::map<uint32_t, D3DRECTPATCH_INFO> g_RectPatchInfoCache;
90089008
std::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

Comments
 (0)