Skip to content

Commit

Permalink
Improvements
Browse files Browse the repository at this point in the history
-Display correct number of drawn triangles
-Optimize drawing model attached morph meshes(like heads)
-Fix ComputePointAABBDistance not calculating correctly distance
-Fix dynamic lights huge impact on FPS in some locations
-Improve loading times by disabling some unnecessary features for GD3D11
-Show DirectX11 as currently used graphic device in video options
-Open GD3D11 settings menu when going into video options
  • Loading branch information
SaiyansKing committed Oct 15, 2021
1 parent d46dcfc commit c5dfcb0
Show file tree
Hide file tree
Showing 11 changed files with 137 additions and 56 deletions.
16 changes: 7 additions & 9 deletions D3D11Engine/D3D11GraphicsEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1102,7 +1102,7 @@ XRESULT D3D11GraphicsEngine::DrawVertexBuffer( D3D11VertexBuffer* vb, unsigned i
GetContext()->Draw( numVertices, 0 );

Engine::GAPI->GetRendererState().RendererInfo.FrameDrawnTriangles +=
numVertices;
numVertices / 3;

return XR_SUCCESS;
}
Expand Down Expand Up @@ -1161,7 +1161,7 @@ XRESULT D3D11GraphicsEngine::DrawVertexBufferIndexedUINT(
GetContext()->IASetVertexBuffers( 0, 1, vb->GetVertexBuffer().GetAddressOf(), &uStride, &offset );
GetContext()->IASetIndexBuffer( ((D3D11VertexBuffer*)ib)->GetVertexBuffer().Get(),
DXGI_FORMAT_R32_UINT, 0 );
}
}

if ( numIndices ) {
// Draw the mesh
Expand Down Expand Up @@ -1232,7 +1232,7 @@ XRESULT D3D11GraphicsEngine::DrawVertexArray( ExVertexStruct* vertices,
GetContext()->Draw( numVertices, startVertex );

Engine::GAPI->GetRendererState().RendererInfo.FrameDrawnTriangles +=
numVertices;
numVertices / 3;

return XR_SUCCESS;
}
Expand Down Expand Up @@ -1264,7 +1264,7 @@ XRESULT D3D11GraphicsEngine::DrawVertexArrayMM( ExVertexStruct* vertices,
GetContext()->Draw( numVertices, startVertex );

Engine::GAPI->GetRendererState().RendererInfo.FrameDrawnTriangles +=
numVertices;
numVertices / 3;

return XR_SUCCESS;
}
Expand Down Expand Up @@ -1305,7 +1305,7 @@ XRESULT D3D11GraphicsEngine::DrawIndexedVertexArray( ExVertexStruct* vertices,
GetContext()->DrawIndexed( numIndices, 0, 0 );

Engine::GAPI->GetRendererState().RendererInfo.FrameDrawnTriangles +=
numVertices;
numVertices / 3;

return XR_SUCCESS;
}
Expand All @@ -1329,7 +1329,8 @@ XRESULT D3D11GraphicsEngine::DrawVertexBufferFF( D3D11VertexBuffer* vb,
// Draw the mesh
GetContext()->Draw( numVertices, startVertex );

Engine::GAPI->GetRendererState().RendererInfo.FrameDrawnTriangles += numVertices;
Engine::GAPI->GetRendererState().RendererInfo.FrameDrawnTriangles +=
numVertices / 3;

return XR_SUCCESS;
}
Expand Down Expand Up @@ -4697,9 +4698,6 @@ LRESULT D3D11GraphicsEngine::OnWindowMessage( HWND hWnd, UINT msg, WPARAM wParam
}

UpdateClipCursor( hWnd );

// Sometimes Gothic doesn't aquire/release input so let's do it ourselves
Engine::GAPI->SetEnableGothicInput( m_isWindowActive );
}
break;
case WM_WINDOWPOSCHANGED: UpdateClipCursor( hWnd ); break;
Expand Down
5 changes: 2 additions & 3 deletions D3D11Engine/D3D7/MyDirect3D7.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,9 @@ class MyDirect3D7 : public IDirect3D7 {
devDesc.dwVertexProcessingCaps = (D3DVTXPCAPS_TEXGEN|D3DVTXPCAPS_MATERIALSOURCE7|D3DVTXPCAPS_DIRECTIONALLIGHTS|D3DVTXPCAPS_POSITIONALLIGHTS|D3DVTXPCAPS_LOCALVIEWER);

// Pass it to the callback function
char desc[256] = "Microsoft Direct3D Hardware Transform and Lighting acceleration capable device";
char name[256] = "Direct3D T&L HAL";
char desc[256] = "DirectX11";
char name[256] = "DirectX11";
(*lpEnumDevicesCallback)(desc, name, &devDesc, lpUserArg);

return S_OK;
}

Expand Down
5 changes: 3 additions & 2 deletions D3D11Engine/D3D7/MyDirectDraw.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,9 @@ class MyDirectDraw : public IDirectDraw7 {
DebugWrite( "MyDirectDraw::GetDeviceIdentifier\n" );

ZeroMemory( lpdddi, sizeof( DDDEVICEIDENTIFIER2 ) );
strcpy( lpdddi->szDescription, "D3D11-Renderer" );
strcpy( lpdddi->szDriver, "D3D11-Renderer" );
strcpy( lpdddi->szDescription, "DirectX11" );
strcpy( lpdddi->szDriver, "DirectX11" );
lpdddi->guidDeviceIdentifier = { 0xF5049E78, 0x4861, 0x11D2, {0xA4, 0x07, 0x00, 0xA0, 0xC9, 0x06, 0x29, 0xA8} };

return S_OK;
}
Expand Down
75 changes: 43 additions & 32 deletions D3D11Engine/GothicAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,14 +368,19 @@ void GothicAPI::SetEnableGothicInput( bool value ) {
if ( oCGame::GetPlayer() ) oCGame::GetPlayer()->SetSleeping( value ? 0 : 1 );
if ( oCGame::GetGame() && oCGame::GetGame()->_zCSession_camVob ) oCGame::GetGame()->_zCSession_camVob->SetSleeping( value ? 0 : 1 );

if ( !value )
disableCounter++;
if ( !value ) {
if ( disableCounter++ > 0 )
return;
}

#ifndef BUILD_SPACER
// zMouse, false
input->SetDeviceEnabled( 2, value ? 1 : 0 );
input->SetDeviceEnabled( 1, value ? 1 : 0 );

// Sometimes without this cursor aren't visible(it is only here as precaution)
ShowCursor( value ? FALSE : TRUE );

IDirectInputDevice7A* dInputMouse = *(IDirectInputDevice7A**)GothicMemoryLocations::GlobalObjects::DInput7DeviceMouse;
IDirectInputDevice7A* dInputKeyboard = *(IDirectInputDevice7A**)GothicMemoryLocations::GlobalObjects::DInput7DeviceKeyboard;
if ( dInputMouse ) {
Expand Down Expand Up @@ -1791,11 +1796,11 @@ void GothicAPI::DrawSkeletalMeshVob( SkeletalVobInfo* vi, float distance, bool u

if ( nodeAttachments.find( i ) != nodeAttachments.end() ) {
// Go through all attachments this node has
for ( unsigned int n = 0; n < nodeAttachments[i].size(); n++ ) {
for ( MeshVisualInfo* mvi : nodeAttachments[i] ) {
XMMATRIX curTransform = XMLoadFloat4x4( &transforms[i] );
SetWorldViewTransform( world * curTransform, view );

if ( !nodeAttachments[i][n]->Visual ) {
if ( !mvi->Visual ) {
LogWarn() << "Attachment without visual on model: " << model->GetVisualName();
continue;
}
Expand All @@ -1808,17 +1813,17 @@ void GothicAPI::DrawSkeletalMeshVob( SkeletalVobInfo* vi, float distance, bool u
}

// Update animated textures
bool isMMS = std::string( nodeAttachments[i][n]->Visual->GetFileExtension( 0 ) ) == ".MMS";
bool isMMS = std::string( mvi->Visual->GetFileExtension( 0 ) ) == ".MMS";
if ( updateState ) {
node->TexAniState.UpdateTexList();
if ( isMMS ) {
zCMorphMesh* mm = (zCMorphMesh*)nodeAttachments[i][n]->Visual;
zCMorphMesh* mm = (zCMorphMesh*)mvi->Visual;
mm->GetTexAniState()->UpdateTexList();
}
}

if ( distance < 1000 && isMMS ) {
zCMorphMesh* mm = (zCMorphMesh*)nodeAttachments[i][n]->Visual;
zCMorphMesh* mm = (zCMorphMesh*)mvi->Visual;
// Only draw this as a morphmesh when rendering the main scene or when rendering as ghost
if ( g->GetRenderingStage() == DES_MAIN || g->GetRenderingStage() == DES_GHOST ) {
// Update constantbuffer
Expand All @@ -1833,7 +1838,7 @@ void GothicAPI::DrawSkeletalMeshVob( SkeletalVobInfo* vi, float distance, bool u

// Only 0.35f of the fatness wanted by gothic.
// They seem to compensate for that with the scaling.
DrawMorphMesh( mm, fatness * 0.35f );
DrawMorphMesh( mm, fatness * 0.35f, mvi->Meshes );
continue;
}
}
Expand All @@ -1843,7 +1848,7 @@ void GothicAPI::DrawSkeletalMeshVob( SkeletalVobInfo* vi, float distance, bool u
vi->VobConstantBuffer->BindToVertexShader( 1 );

// Go through all materials registered here
for ( auto const& itm : nodeAttachments[i][n]->Meshes ) {
for ( auto const& itm : mvi->Meshes ) {
zCTexture* texture;
if ( itm.first && (texture = itm.first->GetAniTexture()) != nullptr ) { // TODO: Crash here!
if ( texture->CacheIn( 0.6f ) == zRES_CACHED_IN ) {
Expand Down Expand Up @@ -2585,8 +2590,10 @@ LRESULT GothicAPI::OnWindowMessage( HWND hWnd, UINT msg, WPARAM wParam, LPARAM l
Engine::AntTweakBar->SetActive( !Engine::AntTweakBar->GetActive() );
SetEnableGothicInput( !Engine::AntTweakBar->GetActive() );
} else {
Engine::AntTweakBar->SetActive( false );
SetEnableGothicInput( true );
if ( Engine::AntTweakBar->GetActive() ) {
Engine::AntTweakBar->SetActive( false );
SetEnableGothicInput( true );
}
Engine::GraphicsEngine->OnUIEvent( BaseGraphicsEngine::EUIEvent::UI_OpenSettings );
}
break;
Expand Down Expand Up @@ -3926,7 +3933,7 @@ void GothicAPI::SetFrameProcessedTexturesReady() {
}

/** Draws a morphmesh */
void GothicAPI::DrawMorphMesh( zCMorphMesh* msh, float fatness ) {
void GothicAPI::DrawMorphMesh( zCMorphMesh* msh, float fatness, std::map<zCMaterial*, std::vector<MeshInfo*>>& meshes ) {
DirectX::XMFLOAT3 bbmin, bbmax;
bbmin = DirectX::XMFLOAT3( FLT_MAX, FLT_MAX, FLT_MAX );
bbmax = DirectX::XMFLOAT3( -FLT_MAX, -FLT_MAX, -FLT_MAX );
Expand All @@ -3936,31 +3943,35 @@ void GothicAPI::DrawMorphMesh( zCMorphMesh* msh, float fatness ) {
return;

DirectX::XMFLOAT3* posList = (DirectX::XMFLOAT3*)morphMesh->GetPositionList()->Array;

// Construct unindexed mesh
for ( int i = 0; i < morphMesh->GetNumSubmeshes(); i++ ) {
std::vector<ExVertexStruct> vertices;

zCSubMesh& sub = morphMesh->GetSubmeshes()[i];
vertices.reserve( sub.TriList.NumInArray * 3 );

// Get vertices
for ( int t = 0; t < sub.TriList.NumInArray; t++ ) {
for ( int v = 3; --v >= 0; ) {
vertices.emplace_back();
ExVertexStruct& vx = vertices.back();
vx.Position = posList[sub.WedgeList.Array[sub.TriList.Array[t].wedge[v]].position];
vx.TexCoord = sub.WedgeList.Array[sub.TriList.Array[t].wedge[v]].texUV;
vx.Color = 0xFFFFFFFF;
vx.Normal = sub.WedgeList.Array[sub.TriList.Array[t].wedge[v]].normal;

// Do this on GPU probably?
XMStoreFloat3( reinterpret_cast<XMFLOAT3*>( &vx.Position ), XMVectorAdd( XMLoadFloat3( reinterpret_cast<const XMFLOAT3*>( &vx.Position ) ), XMLoadFloat3( reinterpret_cast<const XMFLOAT3*>( &vx.Normal ) ) * XMVectorReplicate( fatness ) ) );
}
zCSubMesh* s = morphMesh->GetSubmesh( i );
vertices.reserve( s->WedgeList.NumInArray );
for ( int v = 0; v < s->WedgeList.NumInArray; v++ ) {
zTPMWedge& wedge = s->WedgeList.Array[v];
vertices.emplace_back();
ExVertexStruct& vx = vertices.back();
vx.Position = posList[wedge.position];
vx.Normal = wedge.normal;
vx.TexCoord = wedge.texUV;
vx.Color = 0xFFFFFFFF;

// Do this on GPU probably?
XMStoreFloat3( reinterpret_cast<XMFLOAT3*>( &vx.Position ), XMVectorAdd( XMLoadFloat3( reinterpret_cast<const XMFLOAT3*>( &vx.Position ) ), XMLoadFloat3( reinterpret_cast<const XMFLOAT3*>( &vx.Normal ) ) * XMVectorReplicate( fatness ) ) );
}

sub.Material->BindTexture( 0 );
Engine::GraphicsEngine->DrawVertexArrayMM( &vertices[0], vertices.size() );
s->Material->BindTexture( 0 );
for ( auto const& it : meshes ) {
for ( MeshInfo* mi : it.second ) {
if ( mi->MeshIndex == i ) {
mi->MeshVertexBuffer->UpdateBuffer( &vertices[0], vertices.size() * sizeof( ExVertexStruct ) );
Engine::GraphicsEngine->DrawVertexBufferIndexed( mi->MeshVertexBuffer, mi->MeshIndexBuffer, mi->Indices.size() );
goto Out_Of_Nested_Loop;
}
}
}
Out_Of_Nested_Loop:;
}
}

Expand Down
2 changes: 1 addition & 1 deletion D3D11Engine/GothicAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ class GothicAPI {
void DrawInventory( zCWorld* world, zCCamera& camera );

/** Draws a morphmesh */
void DrawMorphMesh( zCMorphMesh* msh, float fatness );
void DrawMorphMesh( zCMorphMesh* msh, float fatness, std::map<zCMaterial*, std::vector<MeshInfo*>>& meshes );

/** Locks the resource CriticalSection */
void EnterResourceCriticalSection();
Expand Down
70 changes: 67 additions & 3 deletions D3D11Engine/HookedFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ void HookedFunctionInfo::InitHooks() {
LogInfo() << "Patching: Fix integer overflow crash";
PatchAddr( 0x00506B31, "\xEB" );

LogInfo() << "Patching: Marking texture as cached-in after cache-out";
LogInfo() << "Patching: Marking texture as cached-in after cache-out - fix";
PatchAddr( 0x005E90BE, "\x90\x90" );
#else
LogInfo() << "Patching: BroadCast fix";
Expand Down Expand Up @@ -112,8 +112,33 @@ void HookedFunctionInfo::InitHooks() {
PatchAddr( 0x004F4024, "\xEB" );
PatchAddr( 0x004F43FC, "\xEB" );

LogInfo() << "Patching: Marking texture as cached-in after cache-out";
LogInfo() << "Patching: Marking texture as cached-in after cache-out - fix";
PatchAddr( 0x005CA683, "\x90\x90" );

LogInfo() << "Patching: Improve loading times by disabling some unnecessary features";
PatchAddr( 0x0055848A, "\xE9\xE2\x01\x00\x00\x90" );
PatchAddr( 0x005F7F7C, "\x1F" );
PatchAddr( 0x005F8D40, "\x1F" );
PatchAddr( 0x00525BC4, "\xEB" );
PatchAddr( 0x0051E425, "\x90\x90" );
PatchAddr( 0x0051E5B5, "\xEB\x22" );
PatchAddr( 0x0051E62A, "\x8D\x24\x24\x8B\x4A\x30\x8B\x04\xA9\x8B\x48\x40\x83\xC0\x38\x85\xC9\x74\x28\x33\xF6\x85\xC9\x7E\x22\x8B\x18\x8B\xFB\x8D\x1B\x39\x17\x74\x0A\x46\x83\xC7\x04\x3B\xF1\x7C\xF4\xEB\x0E\x49\x3B\xF1\x89\x48\x08\x74\x06\x8B\x04\x8B\x89\x04\xB3\x8B\x42\x38\x45\x3B\xE8\x7C\xC0\xEB\x65\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" );

// Show DirectX11 as currently used graphic device
{
PatchAddr( 0x0071F8DF, "\x55\x56\xBE\x00\x00\x00\x00\x90\x90\x90\x90" );
PatchAddr( 0x0071F8EC, "\x83\xFE\x01" );
PatchAddr( 0x0071F9EC, "\x81\xC6\x18\xE7\x8D\x00" );
PatchAddr( 0x0071FA01, "\x90\x90" );

PatchAddr( 0x0071F5D9, "\xB8\x01\x00\x00\x00\xC3\x90" );
PatchAddr( 0x0071F5E9, "\xB8\x01\x00\x00\x00\xC3\x90" );

PatchAddr( 0x0042BB0D, "\xE8\xC7\x3A\x2F\x00\x90" );
PatchAddr( 0x0042BBE1, "\xE8\x03\x3A\x2F\x00\x90" );

XHook( 0x0071F5D9, HookedFunctionInfo::hooked_GetNumDevices );
}
#endif
#endif

Expand Down Expand Up @@ -156,9 +181,42 @@ void HookedFunctionInfo::InitHooks() {
LogInfo() << "Patching: Texture size is lower than 32 - fix";
PatchAddr( 0x005F4E20, "\xC7\x05\xBC\xB3\x99\x00\x00\x40\x00\x00\xEB\x4D\x90\x90" );

LogInfo() << "Patching: Marking texture as cached-in after cache-out";
LogInfo() << "Patching: Marking texture as cached-in after cache-out - fix";
PatchAddr( 0x005F5573, "\x90\x90" );

LogInfo() << "Patching: Fix dynamic lights huge impact on FPS in some locations";
PatchAddr( 0x006092C4, "\xE9\x45\x02\x00\x00\x90" );
PatchAddr( 0x00609544, "\xE9\x25\x02\x00\x00\x90" );

#ifndef BUILD_SPACER_NET
LogInfo() << "Patching: Improve loading times by disabling some unnecessary features";
PatchAddr( 0x00571256, "\xE9\xC6\x02\x00\x00\x90" );
PatchAddr( 0x006C8748, "\x90\x90\x90\x90\x90\x90" );
PatchAddr( 0x00530D75, "\x90\x90" );
PatchAddr( 0x006265AE, "\x1F" );
PatchAddr( 0x006274E6, "\x1F" );
PatchAddr( 0x005396C9, "\xEB" );
PatchAddr( 0x00530F05, "\xEB\x22" );
PatchAddr( 0x00530F7A, "\x8D\xA4\x24\x00\x00\x00\x00\x8B\x4A\x30\x8B\x04\xA9\x8B\x48\x40\x83\xC0\x38\x85\xC0\x74\x28\x33\xF6\x85\xC9\x7E\x22\x8B\x18\x8B\xFB\x8D\x1B\x39\x17\x74\x0A\x46\x83\xC7\x04\x3B\xF1\x7C\xF4\xEB\x0E\x49\x3B\xF1\x89\x48\x08\x74\x06\x8B\x04\x8B\x89\x04\xB3\x8B\x42\x38\x45\x3B\xE8\x7C\xC0\xEB\x61\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" );
#endif

// Show DirectX11 as currently used graphic device
{
PatchAddr( 0x006581AD, "\x57\xBD\x00\x00\x00\x00\x90" );
PatchAddr( 0x006581B8, "\x83\xFD\x01\x90\x90\x90\x90" );
PatchAddr( 0x00658302, "\x81\xC5\x30\x4C\x9A\x00" );
PatchAddr( 0x00658321, "\x8B\xFD" );
PatchAddr( 0x00658329, "\x55" );

PatchAddr( 0x00657EA9, "\xB8\x01\x00\x00\x00\xC3\x90" );
PatchAddr( 0x00657EB9, "\xB8\x01\x00\x00\x00\xC3\x90" );

PatchAddr( 0x0042DF1F, "\xE8\x85\x9F\x22\x00\x90" );
PatchAddr( 0x0042E000, "\xE8\xB4\x9E\x22\x00\x90" );

XHook( 0x00657EA9, HookedFunctionInfo::hooked_GetNumDevices );
}

// HACK Workaround to fix debuglines in godmode
LogInfo() << "Patching: Godmode Debuglines";
// oCMagFrontier::GetDistanceNewWorld
Expand Down Expand Up @@ -229,3 +287,9 @@ int __fastcall HookedFunctionInfo::hooked_zBinkPlayerOpenVideo( void* thisptr, v

return r;
}

int __cdecl HookedFunctionInfo::hooked_GetNumDevices()
{
Engine::GraphicsEngine->OnUIEvent( BaseGraphicsEngine::EUIEvent::UI_OpenSettings );
return 1;
}
2 changes: 2 additions & 0 deletions D3D11Engine/HookedFunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ struct HookedFunctionInfo {
static long __fastcall hooked_zBinkPlayerGetPixelFormat( void* thisptr, void* unknwn, zTRndSurfaceDesc& desc );
static int __fastcall hooked_zBinkPlayerOpenVideo( void* thisptr, void* unknwn, zSTRING str );
static void __fastcall hooked_zCActiveSndAutoCalcObstruction( void* thisptr, void* unknwn, int i );

static int __cdecl hooked_GetNumDevices();
};

namespace HookedFunctions {
Expand Down
4 changes: 2 additions & 2 deletions D3D11Engine/Toolbox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,8 @@ namespace Toolbox {
float dx = std::max( std::max( min.x - p.x, 0.0f ), p.x - max.x );
float dy = std::max( std::max( min.y - p.y, 0.0f ), p.y - max.y );
float dz = std::max( std::max( min.z - p.z, 0.0f ), p.z - max.z );
//return sqrtf( dx * dx + dy * dy );
return _mm_cvtss_f32( _mm_rcp_ss( _mm_rsqrt_ss( _mm_set_ss( dx * dx + dy * dy ) ) ) );
//return sqrtf( dx * dx + dz * dz );
return _mm_cvtss_f32( _mm_rcp_ss( _mm_rsqrt_ss( _mm_set_ss( dx * dx + dz * dz ) ) ) );
}

/** Computes the Normal of a triangle */
Expand Down
10 changes: 7 additions & 3 deletions D3D11Engine/WorldConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1242,6 +1242,10 @@ void WorldConverter::ExtractNodeVisual( int index, zCModelNodeInst* node, std::m
}

MeshVisualInfo* mi = new MeshVisualInfo;
if ( isMMS ) {
mi->MorphMeshVisual = (void*)node->NodeVisual;
zCObject_AddRef( mi->MorphMeshVisual );
}

Extract3DSMeshFromVisual2( pm, mi );
if ( isMMS ) {
Expand Down Expand Up @@ -1411,14 +1415,14 @@ void WorldConverter::UpdateMorphMeshVisual( void* v, MeshVisualInfo* meshInfo )
}

for ( auto const& it : meshInfo->Meshes ) {
const std::vector<MeshInfo*>& mlist = it.second;
for ( unsigned int x = 0; x < mlist.size(); x++ ) {
MeshInfo* mi = mlist[x];
for ( MeshInfo* mi : it.second ) {
if ( mi->MeshIndex == i ) {
mi->MeshVertexBuffer->UpdateBuffer( &vertices[0], vertices.size() * sizeof( ExVertexStruct ) );
goto Out_Of_Nested_Loop;
}
}
}
Out_Of_Nested_Loop:;
}
}

Expand Down
Loading

0 comments on commit c5dfcb0

Please sign in to comment.