1111#include " Pedestrian.h"
1212#include " Vehicle.h"
1313
14+ // ////////////////////////////////////////////////////////////////////////
15+
16+ void MapRenderStats::FrameStart ()
17+ {
18+ mBlockChunksDrawnCount = 0 ;
19+ }
20+
21+ void MapRenderStats::FrameEnd ()
22+ {
23+ }
24+
25+ // ////////////////////////////////////////////////////////////////////////
26+
1427bool MapRenderer::Initialize ()
1528{
1629 mCityMeshBufferV = gGraphicsDevice .CreateBuffer (eBufferContent_Vertices);
@@ -28,7 +41,6 @@ bool MapRenderer::Initialize()
2841 return false ;
2942 }
3043
31- mCityMapRectangle .SetNull ();
3244 return true ;
3345}
3446
@@ -46,17 +58,11 @@ void MapRenderer::Deinit()
4658 gGraphicsDevice .DestroyBuffer (mCityMeshBufferI );
4759 mCityMeshBufferI = nullptr ;
4860 }
49-
50- for (int iLayer = 0 ; iLayer < MAP_LAYERS_COUNT; ++iLayer)
51- {
52- mCityMeshData [iLayer].SetNull ();
53- }
54- mCityMapRectangle .SetNull ();
5561}
5662
5763void MapRenderer::RenderFrame ()
5864{
59- BuildMapMesh ();
65+ mRenderStats . FrameStart ();
6066
6167 gGraphicsDevice .BindTexture (eTextureUnit_3, gSpriteManager .mPalettesTable );
6268 gGraphicsDevice .BindTexture (eTextureUnit_2, gSpriteManager .mPaletteIndicesTable );
@@ -73,107 +79,8 @@ void MapRenderer::RenderFrame()
7379 currVehicle->DrawFrame (mSpritesBatch );
7480 }
7581 mSpritesBatch .Flush ();
76- }
77-
78- void MapRenderer::CommitCityMeshData ()
79- {
80- int totalIndexCount = 0 ;
81- int totalVertexCount = 0 ;
82-
83- for (int iLayer = 0 ; iLayer < MAP_LAYERS_COUNT; ++iLayer)
84- {
85- int numVertices = mCityMeshData [iLayer].mBlocksVertices .size ();
86- totalVertexCount += numVertices;
87-
88- int numIndices = mCityMeshData [iLayer].mBlocksIndices .size ();
89- totalIndexCount += numIndices;
90- }
91-
92- if (totalIndexCount == 0 || totalVertexCount == 0 )
93- return ;
94-
95- int totalIndexDataBytes = totalIndexCount * Sizeof_DrawIndex;
96- int totalVertexDataBytes = totalVertexCount * Sizeof_CityVertex3D;
97-
98- // upload vertex data
99- mCityMeshBufferV ->Setup (eBufferUsage_Static, totalVertexDataBytes, nullptr );
100- if (void * pdata = mCityMeshBufferV ->Lock (BufferAccess_Write))
101- {
102- char * pcursor = static_cast <char *>(pdata);
103- for (int iLayer = 0 ; iLayer < MAP_LAYERS_COUNT; ++iLayer)
104- {
105- int dataLength = mCityMeshData [iLayer].mBlocksVertices .size () * Sizeof_CityVertex3D;
106- if (mCityMeshData [iLayer].mBlocksVertices .empty ())
107- continue ;
108- memcpy (pcursor, mCityMeshData [iLayer].mBlocksVertices .data (), dataLength);
109- pcursor += dataLength;
110- }
111- mCityMeshBufferV ->Unlock ();
112- }
113-
114- // upload index data
115- mCityMeshBufferI ->Setup (eBufferUsage_Static, totalIndexDataBytes, nullptr );
116- if (void * pdata = mCityMeshBufferI ->Lock (BufferAccess_Write))
117- {
118- char * pcursor = static_cast <char *>(pdata);
119- for (int iLayer = 0 ; iLayer < MAP_LAYERS_COUNT; ++iLayer)
120- {
121- int dataLength = mCityMeshData [iLayer].mBlocksIndices .size () * Sizeof_DrawIndex;
122- if (mCityMeshData [iLayer].mBlocksIndices .empty ())
123- continue ;
124- memcpy (pcursor, mCityMeshData [iLayer].mBlocksIndices .data (), dataLength);
125- pcursor += dataLength;
126- }
127- mCityMeshBufferI ->Unlock ();
128- }
129- }
130-
131- void MapRenderer::BuildMapMesh ()
132- {
133- if (gGameCheatsWindow .mGenerateFullMeshForMap && mCityMapRectangle .h == 0 && mCityMapRectangle .w == 0 )
134- {
135- mCityMapRectangle .x = 0 ;
136- mCityMapRectangle .y = 0 ;
137- mCityMapRectangle .w = MAP_DIMENSIONS;
138- mCityMapRectangle .h = MAP_DIMENSIONS;
139-
140- gConsole .LogMessage (eLogMessage_Debug, " City mesh invalidated [full]" );
141- for (int i = 0 ; i < MAP_LAYERS_COUNT; ++i)
142- {
143- GameMapHelpers::BuildMapMesh (gGameMap , mCityMapRectangle , i, gRenderManager .mMapRenderer .mCityMeshData [i]);
144- }
145- gRenderManager .mMapRenderer .CommitCityMeshData ();
146- return ;
147- }
148-
149- int viewBlocks = 14 ;
150-
151- int tilex = static_cast <int >(gCamera .mPosition .x / MAP_BLOCK_LENGTH);
152- int tiley = static_cast <int >(gCamera .mPosition .z / MAP_BLOCK_LENGTH);
153-
154- Rect2D rcMapView { -viewBlocks / 2 + tilex, -viewBlocks / 2 + tiley, viewBlocks, viewBlocks };
155-
156- bool invalidateCache = mCityMapRectangle .w == 0 || mCityMapRectangle .h == 0 ||
157- rcMapView.x < mCityMapRectangle .x || rcMapView.y < mCityMapRectangle .y ||
158- rcMapView.x + rcMapView.w > mCityMapRectangle .x + mCityMapRectangle .w ||
159- rcMapView.y + rcMapView.h > mCityMapRectangle .y + mCityMapRectangle .h ;
160-
161- if (!invalidateCache)
162- return ;
163-
164- gConsole .LogMessage (eLogMessage_Debug, " City mesh invalidated [partial]" );
165-
166- int cacheNumBlocks = 32 ;
167- mCityMapRectangle .x = (-cacheNumBlocks / 2 ) + tilex;
168- mCityMapRectangle .y = (-cacheNumBlocks / 2 ) + tiley;
169- mCityMapRectangle .w = cacheNumBlocks;
170- mCityMapRectangle .h = cacheNumBlocks;
171-
172- for (int i = 0 ; i < MAP_LAYERS_COUNT; ++i)
173- {
174- GameMapHelpers::BuildMapMesh (gGameMap , mCityMapRectangle , i, gRenderManager .mMapRenderer .mCityMeshData [i]);
175- }
176- gRenderManager .mMapRenderer .CommitCityMeshData ();
82+
83+ mRenderStats .FrameEnd ();
17784}
17885
17986void MapRenderer::DrawCityMesh ()
@@ -192,26 +99,70 @@ void MapRenderer::DrawCityMesh()
19299 gGraphicsDevice .BindTexture (eTextureUnit_0, gSpriteManager .mBlocksTextureArray );
193100 gGraphicsDevice .BindTexture (eTextureUnit_1, gSpriteManager .mBlocksIndicesTable );
194101
195- int currBaseVertex = 0 ;
196- int currIndexOffset = 0 ;
197-
198- for (int i = 0 ; i < MAP_LAYERS_COUNT; ++i)
102+ for (const MapBlocksChunk& currChunk: mMapBlocksChunks )
199103 {
200- int numIndices = mCityMeshData [i].mBlocksIndices .size ();
201- int numVertices = mCityMeshData [i].mBlocksVertices .size ();
202- if (gGameCheatsWindow .mDrawMapLayers [i])
203- {
204- int currIndexOffsetBytes = currIndexOffset * Sizeof_DrawIndex;
205- gGraphicsDevice .RenderIndexedPrimitives (ePrimitiveType_Triangles, eIndicesType_i32, currIndexOffsetBytes, numIndices, currBaseVertex);
206- }
207- currIndexOffset += numIndices;
208- currBaseVertex += numVertices;
104+ if (!gCamera .mFrustum .contains (currChunk.mBounds ))
105+ continue ;
106+
107+ gGraphicsDevice .RenderIndexedPrimitives (ePrimitiveType_Triangles, eIndicesType_i32,
108+ currChunk.mIndicesStart * Sizeof_DrawIndex, currChunk.mIndicesCount );
109+
110+ ++mRenderStats .mBlockChunksDrawnCount ;
209111 }
210112 }
211113 gRenderManager .mCityMeshProgram .Deactivate ();
212114}
213115
214- void MapRenderer::InvalidateMapMesh ()
116+ void MapRenderer::BuildMapMesh ()
215117{
216- mCityMapRectangle .SetNull ();
118+ MapMeshData blocksMesh;
119+ for (int batchy = 0 ; batchy < BlocksBatchesPerSide; ++batchy)
120+ {
121+ for (int batchx = 0 ; batchx < BlocksBatchesPerSide; ++batchx)
122+ {
123+ Rect2D mapArea {
124+ batchx * BlocksBatchDims - ExtraBlocksPerSide,
125+ batchy * BlocksBatchDims - ExtraBlocksPerSide,
126+ BlocksBatchDims,
127+ BlocksBatchDims };
128+
129+ unsigned int prevVerticesCount = blocksMesh.mBlocksVertices .size ();
130+ unsigned int prevIndicesCount = blocksMesh.mBlocksIndices .size ();
131+
132+ MapBlocksChunk& currChunk = mMapBlocksChunks [batchy * BlocksBatchesPerSide + batchx];
133+ currChunk.mBounds .mMin = glm::vec3 { mapArea.x * MAP_BLOCK_LENGTH, 0 , mapArea.y * MAP_BLOCK_LENGTH };
134+ currChunk.mBounds .mMax = glm::vec3 {
135+ (mapArea.x + mapArea.w ) * MAP_BLOCK_LENGTH, MAP_LAYERS_COUNT * MAP_BLOCK_LENGTH,
136+ (mapArea.y + mapArea.h ) * MAP_BLOCK_LENGTH };
137+
138+ currChunk.mVerticesStart = prevVerticesCount;
139+ currChunk.mIndicesStart = prevIndicesCount;
140+
141+ // append new geometry
142+ GameMapHelpers::BuildMapMesh (gGameMap , mapArea, blocksMesh);
143+
144+ currChunk.mVerticesCount = blocksMesh.mBlocksVertices .size () - prevVerticesCount;
145+ currChunk.mIndicesCount = blocksMesh.mBlocksIndices .size () - prevIndicesCount;
146+ }
147+ }
148+
149+ // upload map geometry to video memory
150+ int totalVertexDataBytes = blocksMesh.mBlocksVertices .size () * Sizeof_CityVertex3D;
151+ int totalIndexDataBytes = blocksMesh.mBlocksIndices .size () * Sizeof_DrawIndex;
152+
153+ // upload vertex data
154+ mCityMeshBufferV ->Setup (eBufferUsage_Static, totalVertexDataBytes, nullptr );
155+ if (void * pdata = mCityMeshBufferV ->Lock (BufferAccess_Write))
156+ {
157+ memcpy (pdata, blocksMesh.mBlocksVertices .data (), totalVertexDataBytes);
158+ mCityMeshBufferV ->Unlock ();
159+ }
160+
161+ // upload index data
162+ mCityMeshBufferI ->Setup (eBufferUsage_Static, totalIndexDataBytes, nullptr );
163+ if (void * pdata = mCityMeshBufferI ->Lock (BufferAccess_Write))
164+ {
165+ memcpy (pdata, blocksMesh.mBlocksIndices .data (), totalIndexDataBytes);
166+ mCityMeshBufferI ->Unlock ();
167+ }
217168}
0 commit comments