mirror of
https://github.com/smartcmd/MinecraftConsoles.git
synced 2026-08-20 09:57:09 +00:00
Modify Chunk Loading to Support Significantly Larger World Sizes
This commit is contained in:
parent
5037420311
commit
8356781868
|
|
@ -78,6 +78,7 @@ void Chunk::setPos(int x, int y, int z)
|
|||
clipChunk->zm = zm;
|
||||
|
||||
clipChunk->globalIdx = LevelRenderer::getGlobalIndexForChunk(x, y, z, level);
|
||||
int globalIdx = clipChunk->globalIdx;
|
||||
|
||||
#if 1
|
||||
// 4J - we're not using offsetted renderlists anymore, so just set the full position of this chunk into x/y/zRenderOffs where
|
||||
|
|
@ -126,6 +127,11 @@ void Chunk::setPos(int x, int y, int z)
|
|||
// If we're the first thing to be referencing this, mark it up as dirty to get rebuilt
|
||||
if( refCount == 1 )
|
||||
{
|
||||
int listBase = levelRenderer->allocateListBaseForGlobalIdx(globalIdx);
|
||||
if (listBase < 0)
|
||||
{
|
||||
__debugbreak();
|
||||
}
|
||||
// printf("Setting %d %d %d dirty [%d]\n",x,y,z, idx);
|
||||
// Chunks being made dirty in this way can be very numerous (eg the full visible area of the world at start up, or a whole edge of the world when moving).
|
||||
// On account of this, don't want to stick them into our lock free queue that we would normally use for letting the render update thread know about this chunk.
|
||||
|
|
@ -211,8 +217,14 @@ void Chunk::rebuild()
|
|||
|
||||
int r = 1;
|
||||
|
||||
int lists = levelRenderer->getGlobalIndexForChunk(this->x,this->y,this->z,level) * 2;
|
||||
lists += levelRenderer->chunkLists;
|
||||
int globalIdx = levelRenderer->getGlobalIndexForChunk(this->x, this->y, this->z, level);
|
||||
int listBase = levelRenderer->getListBaseForGlobalIdx(globalIdx);
|
||||
if (listBase < 0)
|
||||
{
|
||||
__debugbreak();
|
||||
PIXEndNamedEvent();
|
||||
return;
|
||||
}
|
||||
|
||||
PIXEndNamedEvent();
|
||||
|
||||
|
|
@ -324,7 +336,7 @@ void Chunk::rebuild()
|
|||
for (int currentLayer = 0; currentLayer < 2; currentLayer++)
|
||||
{
|
||||
levelRenderer->setGlobalChunkFlag(this->x, this->y, this->z, level, LevelRenderer::CHUNK_FLAG_EMPTY0, currentLayer);
|
||||
RenderManager.CBuffClear(lists + currentLayer);
|
||||
RenderManager.CBuffClear(listBase + currentLayer);
|
||||
}
|
||||
|
||||
delete region;
|
||||
|
|
@ -381,7 +393,7 @@ void Chunk::rebuild()
|
|||
started = true;
|
||||
|
||||
MemSect(31);
|
||||
glNewList(lists + currentLayer, GL_COMPILE);
|
||||
glNewList(listBase + currentLayer, GL_COMPILE);
|
||||
MemSect(0);
|
||||
glPushMatrix();
|
||||
glDepthMask(true); // 4J added
|
||||
|
|
@ -459,12 +471,12 @@ void Chunk::rebuild()
|
|||
{
|
||||
// 4J - added - clear any renderer data associated with this unused list
|
||||
levelRenderer->setGlobalChunkFlag(this->x, this->y, this->z, level, LevelRenderer::CHUNK_FLAG_EMPTY0, currentLayer);
|
||||
RenderManager.CBuffClear(lists + currentLayer);
|
||||
RenderManager.CBuffClear(listBase + currentLayer);
|
||||
}
|
||||
if((currentLayer==0)&&(!renderNextLayer))
|
||||
{
|
||||
levelRenderer->setGlobalChunkFlag(this->x, this->y, this->z, level, LevelRenderer::CHUNK_FLAG_EMPTY1);
|
||||
RenderManager.CBuffClear(lists + 1);
|
||||
RenderManager.CBuffClear(listBase + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -670,8 +682,12 @@ void Chunk::rebuild_SPU()
|
|||
Region region(level, x0 - r, y0 - r, z0 - r, x1 + r, y1 + r, z1 + r);
|
||||
TileRenderer tileRenderer(®ion);
|
||||
|
||||
int lists = levelRenderer->getGlobalIndexForChunk(this->x,this->y,this->z,level) * 2;
|
||||
lists += levelRenderer->chunkLists;
|
||||
int globalIdx = levelRenderer->getGlobalIndexForChunk(this->x, this->y, this->z, level);
|
||||
int listBase = levelRenderer->getListBaseForGlobalIdx(globalIdx);
|
||||
if (listBase < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 4J - optimisation begins.
|
||||
|
|
@ -700,7 +716,7 @@ void Chunk::rebuild_SPU()
|
|||
bool rendered = false;
|
||||
|
||||
{
|
||||
glNewList(lists + currentLayer, GL_COMPILE);
|
||||
glNewList(listBase + currentLayer, GL_COMPILE);
|
||||
MemSect(0);
|
||||
glPushMatrix();
|
||||
glDepthMask(true); // 4J added
|
||||
|
|
@ -796,7 +812,7 @@ void Chunk::rebuild_SPU()
|
|||
{
|
||||
// 4J - added - clear any renderer data associated with this unused list
|
||||
levelRenderer->setGlobalChunkFlag(this->x, this->y, this->z, level, LevelRenderer::CHUNK_FLAG_EMPTY0, currentLayer);
|
||||
RenderManager.CBuffClear(lists + currentLayer);
|
||||
RenderManager.CBuffClear(listBase + currentLayer);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -965,18 +981,13 @@ void Chunk::reset()
|
|||
unsigned char refCount = levelRenderer->decGlobalChunkRefCount(x, y, z, level);
|
||||
assigned = false;
|
||||
// printf("\t\t [dec] refcount %d at %d, %d, %d\n",refCount,x,y,z);
|
||||
if( refCount == 0 )
|
||||
if (refCount == 0)
|
||||
{
|
||||
int lists = levelRenderer->getGlobalIndexForChunk(x, y, z, level) * 2;
|
||||
if(lists >= 0)
|
||||
int globalIdx = levelRenderer->getGlobalIndexForChunk(x, y, z, level);
|
||||
if (globalIdx >= 0)
|
||||
{
|
||||
lists += levelRenderer->chunkLists;
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
// 4J - added - clear any renderer data associated with this unused list
|
||||
RenderManager.CBuffClear(lists + i);
|
||||
}
|
||||
levelRenderer->setGlobalChunkFlags(x, y, z, level, 0);
|
||||
levelRenderer->freeListBaseForGlobalIdx(globalIdx);
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&levelRenderer->m_csDirtyChunks);
|
||||
|
|
@ -995,11 +1006,12 @@ int Chunk::getList(int layer)
|
|||
{
|
||||
if (!clipChunk->visible) return -1;
|
||||
|
||||
int lists = levelRenderer->getGlobalIndexForChunk(x, y, z,level) * 2;
|
||||
lists += levelRenderer->chunkLists;
|
||||
int globalIdx = levelRenderer->getGlobalIndexForChunk(x, y, z, level);
|
||||
int listBase = levelRenderer->getListBaseForGlobalIdx(globalIdx);
|
||||
if (listBase < 0) return -1;
|
||||
|
||||
bool empty = levelRenderer->getGlobalChunkFlag(x, y, z, level, LevelRenderer::CHUNK_FLAG_EMPTY0, layer);
|
||||
if (!empty) return lists + layer;
|
||||
bool empty = levelRenderer->getGlobalChunkFlag(x, y, z, level, LevelRenderer::CHUNK_FLAG_EMPTY0, layer);
|
||||
if (!empty) return listBase + layer;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,9 @@ C4JThread *LevelRenderer::rebuildThreads[MAX_CHUNK_REBUILD_THREADS];
|
|||
C4JThread::EventArray *LevelRenderer::s_rebuildCompleteEvents;
|
||||
C4JThread::Event *LevelRenderer::s_activationEventA[MAX_CHUNK_REBUILD_THREADS];
|
||||
|
||||
unordered_map<int, int> m_globalIdxToListBase;
|
||||
vector<int> m_freeListBases;
|
||||
|
||||
// This defines the maximum size of renderable level, must be big enough to cope with actual size of level + view distance at each side
|
||||
// so that we can render the "infinite" sea at the edges. Currently defined as:
|
||||
const int overworldSize = LEVEL_MAX_WIDTH + LevelRenderer::PLAYER_VIEW_DISTANCE + LevelRenderer::PLAYER_VIEW_DISTANCE;
|
||||
|
|
@ -149,10 +152,18 @@ LevelRenderer::LevelRenderer(Minecraft *mc, Textures *textures)
|
|||
this->mc = mc;
|
||||
this->textures = textures;
|
||||
|
||||
chunkLists = MemoryTracker::genLists(getGlobalChunkCount()*2); // *2 here is because there is one renderlist per chunk here for each of the opaque & transparent layers
|
||||
chunkLists = MemoryTracker::genLists(MAX_RENDER_CHUNK_SLOTS * 2); // *2 here is because there is one renderlist per chunk here for each of the opaque & transparent layers
|
||||
globalChunkFlags = new unsigned char[getGlobalChunkCount()];
|
||||
memset(globalChunkFlags, 0, getGlobalChunkCount());
|
||||
|
||||
m_globalIdxToListBase.clear();
|
||||
m_freeListBases.clear();
|
||||
m_freeListBases.reserve(MAX_RENDER_CHUNK_SLOTS);
|
||||
for (int i = 0; i < MAX_RENDER_CHUNK_SLOTS; ++i)
|
||||
{
|
||||
m_freeListBases.push_back(chunkLists + i * 2);
|
||||
}
|
||||
|
||||
starList = MemoryTracker::genLists(4);
|
||||
|
||||
glPushMatrix();
|
||||
|
|
@ -250,6 +261,43 @@ LevelRenderer::LevelRenderer(Minecraft *mc, Textures *textures)
|
|||
#endif // __PS3__
|
||||
}
|
||||
|
||||
int LevelRenderer::allocateListBaseForGlobalIdx(int globalIdx)
|
||||
{
|
||||
AUTO_VAR(it, m_globalIdxToListBase.find(globalIdx));
|
||||
if (it != m_globalIdxToListBase.end())
|
||||
return it->second;
|
||||
|
||||
if (m_freeListBases.empty())
|
||||
return -1;
|
||||
|
||||
int listBase = m_freeListBases.back();
|
||||
m_freeListBases.pop_back();
|
||||
m_globalIdxToListBase[globalIdx] = listBase;
|
||||
return listBase;
|
||||
}
|
||||
|
||||
void LevelRenderer::freeListBaseForGlobalIdx(int globalIdx)
|
||||
{
|
||||
AUTO_VAR(it, m_globalIdxToListBase.find(globalIdx));
|
||||
if (it == m_globalIdxToListBase.end())
|
||||
return;
|
||||
|
||||
int listBase = it->second;
|
||||
RenderManager.CBuffClear(listBase + 0);
|
||||
RenderManager.CBuffClear(listBase + 1);
|
||||
|
||||
m_freeListBases.push_back(listBase);
|
||||
m_globalIdxToListBase.erase(it);
|
||||
}
|
||||
|
||||
int LevelRenderer::getListBaseForGlobalIdx(int globalIdx) const
|
||||
{
|
||||
AUTO_VAR(it, m_globalIdxToListBase.find(globalIdx));
|
||||
if (it == m_globalIdxToListBase.end())
|
||||
return -1;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void LevelRenderer::renderStars()
|
||||
{
|
||||
Random random = Random(10842);
|
||||
|
|
@ -787,8 +835,10 @@ int LevelRenderer::renderChunks(int from, int to, int layer, double alpha)
|
|||
if( ( globalChunkFlags[pClipChunk->globalIdx] & emptyFlag ) == emptyFlag ) continue; // Check that this particular layer isn't empty
|
||||
|
||||
// List can be calculated directly from the chunk's global idex
|
||||
int list = pClipChunk->globalIdx * 2 + layer;
|
||||
list += chunkLists;
|
||||
int listBase = getListBaseForGlobalIdx(pClipChunk->globalIdx);
|
||||
if (listBase < 0)
|
||||
continue;
|
||||
int list = listBase + layer;
|
||||
|
||||
if(RenderManager.CBuffCall(list, first))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -210,6 +210,9 @@ public:
|
|||
#ifdef _LARGE_WORLDS
|
||||
static const int PLAYER_VIEW_DISTANCE = 18; // Straight line distance from centre to extent of visible world
|
||||
static const int PLAYER_RENDER_AREA = (PLAYER_VIEW_DISTANCE * PLAYER_VIEW_DISTANCE * 4);
|
||||
|
||||
static const int MAX_CHUNKS_PER_PLAYER = PLAYER_RENDER_AREA * CHUNK_Y_COUNT;
|
||||
static const int MAX_RENDER_CHUNK_SLOTS = MAX_CHUNKS_PER_PLAYER * 4;
|
||||
#else
|
||||
static const int PLAYER_RENDER_AREA = 400;
|
||||
#endif
|
||||
|
|
@ -271,6 +274,10 @@ public:
|
|||
static void staticCtor();
|
||||
static int rebuildChunkThreadProc(LPVOID lpParam);
|
||||
|
||||
int allocateListBaseForGlobalIdx(int globalIdx);
|
||||
void freeListBaseForGlobalIdx(int globalIdx);
|
||||
int getListBaseForGlobalIdx(int globalIdx) const;
|
||||
|
||||
CRITICAL_SECTION m_csChunkFlags;
|
||||
#endif
|
||||
void nonStackDirtyChunksAdded();
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ class TilePos;
|
|||
// The maximum number of chunks that we can store
|
||||
#ifdef _LARGE_WORLDS
|
||||
// 4J Stu - Our default map (at zoom level 3) is 1024x1024 blocks (or 64 chunks)
|
||||
#define LEVEL_MAX_WIDTH (5*64) //(6*54)
|
||||
#define LEVEL_MAX_WIDTH (64*64) //(6*54) I have tested up to 512x64, but the game was using 16gb of ram to do so, so probably don't set it this high. I am leaving this at 64*64 for now, but feel free to change it lol
|
||||
#else
|
||||
#define LEVEL_MAX_WIDTH 54
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -67,29 +67,42 @@ Dimension::~Dimension()
|
|||
delete biomeSource;
|
||||
}
|
||||
|
||||
ChunkSource *Dimension::createRandomLevelSource() const
|
||||
ChunkSource* Dimension::createRandomLevelSource() const
|
||||
{
|
||||
ChunkSource* src = NULL;
|
||||
|
||||
#ifdef _OVERRIDE_HEIGHTMAP
|
||||
// 4J Stu - Added to enable overriding the heightmap from a loaded in data file
|
||||
if(app.DebugSettingsOn() && app.GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad())&(1L<<eDebugSetting_EnableHeightWaterBiomeOverride))
|
||||
if (app.DebugSettingsOn() && app.GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad()) & (1L << eDebugSetting_EnableHeightWaterBiomeOverride))
|
||||
{
|
||||
return new CustomLevelSource(level, level->getSeed(), level->getLevelData()->isGenerateMapFeatures());
|
||||
src = new CustomLevelSource(level, level->getSeed(), level->getLevelData()->isGenerateMapFeatures());
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (levelType == LevelType::lvl_flat)
|
||||
if (levelType == LevelType::lvl_flat)
|
||||
{
|
||||
src = new FlatLevelSource(level, level->getSeed(), level->getLevelData()->isGenerateMapFeatures());
|
||||
}
|
||||
else
|
||||
{
|
||||
src = new RandomLevelSource(level, level->getSeed(), level->getLevelData()->isGenerateMapFeatures());
|
||||
}
|
||||
|
||||
if (src != NULL)
|
||||
{
|
||||
return new FlatLevelSource(level, level->getSeed(), level->getLevelData()->isGenerateMapFeatures());
|
||||
}
|
||||
else
|
||||
{
|
||||
return new RandomLevelSource(level, level->getSeed(), level->getLevelData()->isGenerateMapFeatures());
|
||||
src->m_XZSize = level->getLevelData()->getXZSize();
|
||||
}
|
||||
|
||||
return src;
|
||||
}
|
||||
|
||||
ChunkSource *Dimension::createFlatLevelSource() const
|
||||
ChunkSource* Dimension::createFlatLevelSource() const
|
||||
{
|
||||
return new FlatLevelSource(level, level->getSeed(), level->getLevelData()->isGenerateMapFeatures());
|
||||
ChunkSource* src = new FlatLevelSource(level, level->getSeed(), level->getLevelData()->isGenerateMapFeatures());
|
||||
if (src != NULL)
|
||||
{
|
||||
src->m_XZSize = level->getLevelData()->getXZSize();
|
||||
}
|
||||
return src;
|
||||
}
|
||||
|
||||
ChunkStorage *Dimension::createStorage(File dir)
|
||||
|
|
|
|||
|
|
@ -573,9 +573,12 @@ doubleArray RandomLevelSource::getHeights(doubleArray buffer, int x, int y, int
|
|||
|
||||
}
|
||||
|
||||
bool RandomLevelSource::hasChunk(int x, int y)
|
||||
bool RandomLevelSource::hasChunk(int x, int z)
|
||||
{
|
||||
return true;
|
||||
const int half = m_XZSize / 2;
|
||||
|
||||
return (x >= -half && x < half &&
|
||||
z >= -half && z < half);
|
||||
}
|
||||
|
||||
void RandomLevelSource::calcWaterDepths(ChunkSource *parent, int xt, int zt)
|
||||
|
|
|
|||
Loading…
Reference in a new issue