void RowCollection<Group,Hash>::getChunkIterators(vector<boost::shared_ptr<ChunkIterator> >& chunkIterators, size_t rowId) { Coordinates chunkPos(2); chunkPos[0] = rowId; chunkPos[1] = (_counts[rowId] / _chunkSize) * _chunkSize; if (isLastChunkFull(rowId)) { int chunkMode = ChunkIterator::SEQUENTIAL_WRITE; for (size_t i=0; i<_attributes.size(); ++i) { ScopedMutexLock lock(_mutexArrayIterators); Chunk& chunk = _arrayIterators[i]->newChunk(chunkPos, 0); chunkIterators[i] = chunk.getIterator(_query, chunkMode); chunkMode |= ChunkIterator::NO_EMPTY_CHECK; } } else { Coordinates itemPos(2); itemPos[0] = rowId; itemPos[1] = _counts[rowId]; int chunkMode = ChunkIterator::APPEND_CHUNK; for (size_t i=0; i<_attributes.size(); ++i) { ScopedMutexLock lock(_mutexArrayIterators); _arrayIterators[i]->setPosition(chunkPos); Chunk& chunk = _arrayIterators[i]->updateChunk(); chunkIterators[i] = chunk.getIterator(_query, chunkMode); chunkMode |= ChunkIterator::NO_EMPTY_CHECK; // no empty check except for attribute 0 chunkIterators[i]->setPosition(itemPos); } } }
void ChunkManager::update(const glm::vec3 &cameraPos) { glm::vec2 cameraPosXZ(cameraPos.x, cameraPos.z); //Debug_Log(m_chunksDraw); m_chunksDraw = 0; for (int i = 0; i < NUM_CHUNKS; i++) { for (int j = 0; j < NUM_CHUNKS; j++) { glm::vec2 chunkPos(i * CHUNK_SIZE * BLOCK_WIDTH, j * CHUNK_SIZE * BLOCK_WIDTH); glm::vec2 dist = cameraPosXZ - chunkPos; if (glm::abs(glm::length(dist)) < RENDER_DISTANCE) { m_chunks[i][j].init(); m_chunks[i][j].setActive(true); m_chunks[i][j].update(); } else { m_chunks[i][j].dispose(); } } } }
Chunk * ChunkManager::getChunk(const Vec2 & pos) const { int x = floor(pos.x / CHUNK_WIDTH); int y = floor(pos.y / CHUNK_HEIGHT); Vec2 chunkPos(x*CHUNK_WIDTH, y*CHUNK_HEIGHT); for (auto& c : getChunksOnScene()) { if ((c->getPosition() - chunkPos).lengthSquared() < 1.f) { return c; } } return nullptr; }
void VoxelSceneNode::preRenderFillChunks() { irr::core::vector3d<int> playerChunk = VoxelReference( irr::core::vector3d<int>( (int)IRR.mPlayer->getPosition().X, (int)IRR.mPlayer->getPosition().Y, (int)IRR.mPlayer->getPosition().Z ) ).Chunk; irr::core::vector3d<int> localSpace(5,0,5); irr::core::vector3d<int> chunkPos(0,0,0); //Loop through local space - generate blocks downwards from ship for(int x = playerChunk.X - localSpace.X; x <= playerChunk.X + localSpace.X; x++) { for(int z = playerChunk.Z - localSpace.Z; z <= playerChunk.Z + localSpace.Z; z++) { chunkPos.set(x,playerChunk.Y,z); if(chunkMap.find(chunkPos) == chunkMap.end()) { //printf("Initializing (%i,%i,%i) to queue\n", chunkPos.X, chunkPos.Y, chunkPos.Z); chunkMap[chunkPos] = VoxelChunk(); chunkMap[chunkPos].Initialize(this, chunkPos); } if(chunkMap[chunkPos].status == EMPTY) { //printf("Adding (%i,%i,%i) to queue\n", chunkPos.X, chunkPos.Y, chunkPos.Z); chunkMap[chunkPos].status = FILLING; boost::threadpool::schedule( (*IRR.mThreadPool), boost::threadpool::prio_task_func(1, boost::bind(&VoxelSceneNode::FillBackground, this, chunkPos)) ); } } } }
void VoxelSceneNode::preRenderMeshChunks() { irr::core::vector3d<int> overDraw(1,0,1); irr::core::aabbox3df bounding = IRR.camera->getViewFrustum()->getBoundingBox(); irr::core::vector3d<int> newAabboxStart( (int)floor(bounding.MinEdge.X / dimensions.X) - overDraw.X, (int)floor(bounding.MinEdge.Y / dimensions.Y) - overDraw.Y, (int)floor(bounding.MinEdge.Z / dimensions.Z) - overDraw.Z ); irr::core::vector3d<int> newAabboxEnd( (int)ceil(bounding.MaxEdge.X / dimensions.X) + overDraw.X, (int)ceil(bounding.MaxEdge.Y / dimensions.Y) + overDraw.Y, (int)ceil(bounding.MaxEdge.Z / dimensions.Z) + overDraw.Z ); if((newAabboxStart == aabboxStart && newAabboxEnd == aabboxEnd) && !dirty) { return; } aabboxStart = newAabboxStart; aabboxEnd = newAabboxEnd; Mesh->MeshBuffers.clear(); irr::core::aabbox3df aabbox; irr::core::vector3d<int> chunkPos(0,0,0); dirty = false; for(int z = aabboxEnd.Z; z >= aabboxStart.Z; z--) { for(int x = aabboxEnd.X; x >= aabboxStart.X; x--) { for(int y = aabboxEnd.Y; y >= aabboxStart.Y; y--) { chunkPos.set(x,y,z); if(meshMap.find(chunkPos) == meshMap.end()) { meshMap[chunkPos] = ChunkMesh(); meshMap[chunkPos].Initialize(this, chunkPos); } aabbox = irr::core::aabbox3df( ((int)dimensions.X * x), ((int)dimensions.Y * y), ((int)dimensions.Z * z), ((int)dimensions.X * x + (int)dimensions.X), ((int)dimensions.Y * y + (int)dimensions.Y), ((int)dimensions.Z * z + (int)dimensions.Z) ); if(AABBoxInFrustum(IRR.camera->getViewFrustum(), aabbox)) { if(chunkMap.find(chunkPos) != chunkMap.end()) { //Apparently checking a value is enough to generate an object if(meshMap.find(chunkPos) == meshMap.end()) { meshMap[chunkPos] = ChunkMesh(); meshMap[chunkPos].Initialize(this, chunkPos); } if(meshMap[chunkPos].Meshed) { Mesh->addMeshBuffer(meshMap[chunkPos].buffer); } if(!chunkMap[chunkPos].empty) { if(chunkMap[chunkPos].status == FILLED || chunkMap[chunkPos].status == DIRTY) { chunkMap[chunkPos].status = MESHING; boost::threadpool::schedule( (*IRR.mThreadPool), boost::threadpool::prio_task_func(10, boost::bind(&VoxelSceneNode::MeshBackground, this, chunkPos)) ); } } if(chunkMap[chunkPos].obstruct) { y = aabboxStart.Y; } } } } } } Mesh->recalculateBoundingBox(); Mesh->setDirty(); }
Resource* WoWImporter::Import( const String& pFilename, const String& /*pParams*/ ) { WoW::ADTFile adtFile; WoW::ADTFileReader adtFileReader( adtFile ); adtFileReader.Read( pFilename ); WorldTile* worldTile = GD_NEW(WorldTile, this, "WoW::WorldTile"); worldTile->GetTerrainChunks().resize( 256 ); worldTile->GetVertexList().Allocate( 16*16 * (9*9 + 8*8), (VertexFormat::Component) (VertexFormat::Position3 | VertexFormat::TexCoord2 | VertexFormat::TexCoord2_2 | VertexFormat::Normal3) ); Vector3f* ptrPosition = worldTile->GetVertexList().GetPositions(); Vector3f* ptrNormal = worldTile->GetVertexList().GetNormals(); Vector2f* ptrTexCoord = worldTile->GetVertexList().GetTextureCoords(); Vector2f* ptrTexCoordAlpha = worldTile->GetVertexList().GetTextureCoords_2(); UInt32 verticesOffset = 0; Vector3f firstChunkPos(0,0,0);//-1.0f*adtFile.mMapChunks[0].mHeader.mPosition.y, adtFile.mMapChunks[0].mHeader.mPosition.z, -1.0f*adtFile.mMapChunks[0].mHeader.mPosition.x ); for( UInt32 iChunk = 0; iChunk < 256; iChunk++ ) { WoW::ADTFile::MapChunk* mapChunk = &adtFile.mMapChunks[iChunk]; // Append vertex data to vertex buffer Float* ptrDataHeight = mapChunk->mHeightMap; Char* ptrDataNormals = mapChunk->mHeightMapNormals[0]; Vector3f chunkPos( -1.0f*mapChunk->mHeader.mPosition.y, mapChunk->mHeader.mPosition.z, -1.0f*mapChunk->mHeader.mPosition.x ); Float posX = chunkPos.x - firstChunkPos.x; Float posZ = chunkPos.z - firstChunkPos.z; for( UInt32 z = 0; z < 9; z++ ) { // Normal row posX = chunkPos.x - firstChunkPos.x; for( UInt32 x = 0; x < 9; x++ ) { ptrPosition->x = posX; ptrPosition->y = chunkPos.y + (*ptrDataHeight) - firstChunkPos.y; ptrPosition->z = posZ; (*ptrPosition) *= 0.1f; ptrNormal->x = ((Float)ptrDataNormals[0]) / 127.0f; ptrNormal->y = ((Float)ptrDataNormals[1]) / 127.0f; ptrNormal->z = ((Float)ptrDataNormals[2]) / 127.0f; ptrTexCoord->x = x / 8.0f; ptrTexCoord->y = z / 8.0f; ptrTexCoordAlpha->x = (x+0.125f) / 8.25f; ptrTexCoordAlpha->y = (z+0.125f) / 8.25f; ptrDataHeight++; ptrDataNormals += 3; ptrPosition++; ptrNormal++; ptrTexCoord++; ptrTexCoordAlpha++; posX += UNIT_SIZE; } posZ += 0.5f * UNIT_SIZE; if( z == 8 ) break; // Detailed row posX = chunkPos.x + 0.5f * UNIT_SIZE - firstChunkPos.x; for( UInt32 x = 0; x < 8; x++ ) { ptrPosition->x = posX; ptrPosition->y = chunkPos.y + (*ptrDataHeight) - firstChunkPos.y; ptrPosition->z = posZ; (*ptrPosition) *= 0.1f; ptrNormal->x = ((Float)ptrDataNormals[0]) / 127.0f; ptrNormal->y = ((Float)ptrDataNormals[1]) / 127.0f; ptrNormal->z = ((Float)ptrDataNormals[2]) / 127.0f; ptrTexCoord->x = (x+0.5f) / 8.0f; ptrTexCoord->y = (z+0.5f) / 8.0f; ptrTexCoordAlpha->x = (x+0.5f+0.125f) / 8.25f; ptrTexCoordAlpha->y = (z+0.5f+0.125f) / 8.25f; ptrDataHeight++; ptrDataNormals += 3; ptrPosition++; ptrNormal++; ptrTexCoord++; ptrTexCoordAlpha++; posX += UNIT_SIZE; } posZ += 0.5f * UNIT_SIZE; } WorldTile::TerrainChunk* newChunk = GD_NEW(WorldTile::TerrainChunk, this, "WoW::WorldTile::TerrainChunk"); for( UInt32 iLayer = 0; iLayer < mapChunk->mTextureLayers.size(); iLayer++ ) { String textureName("Data/"); textureName += adtFile.mTextureNames[mapChunk->mTextureLayers[iLayer].mTextureID]; HTexture2D texture(textureName); Texture2D* alpha = NULL; if( iLayer != 0 ) { alpha = Cast<Texture2D>(Texture2D::StaticClass()->AllocateNew( "AlphaMap" )); alpha->Create( mapChunk->mAlphaMaps[iLayer-1], true ); alpha->Init(); alpha->SetWrapMode( Texture::Wrap_S, Texture::Wrap_Clamp ); alpha->SetWrapMode( Texture::Wrap_T, Texture::Wrap_Clamp ); alpha->SetMinFilter( Texture::MinFilter_Linear ); alpha->SetMagFilter( Texture::MagFilter_Linear ); } newChunk->AddTextureLayer( texture, alpha ); } UInt32 detailedStripSize = (16*18 + 7*2 + 8*2); UInt32 normalStripSize = 158; // Build index buffer newChunk->GetHiResTriangles().Allocate( TriangleBatch::TriangleStrip, detailedStripSize ); newChunk->GetLowResTriangles().Allocate( TriangleBatch::TriangleStrip, normalStripSize ); UInt16* ptrHiIndices = newChunk->GetHiResTriangles().GetIndices(); UInt16* ptrLoIndices = newChunk->GetLowResTriangles().GetIndices(); for( int row = 0; row < 8; row++ ) { UInt32 topRow = verticesOffset + row*(9+8); UInt32 detailrow = verticesOffset + row*(9+8) + 9; UInt32 nextRow = verticesOffset + (row+1)*(9+8); if( row > 0 ) { *ptrHiIndices++ = topRow + 0; // jump end *ptrLoIndices++ = topRow + 0; } for( int col = 0; col < 8; col++ ) { *ptrHiIndices++ = topRow + col; *ptrHiIndices++ = detailrow + col; *ptrLoIndices++ = topRow + col; *ptrLoIndices++ = nextRow + col; } *ptrHiIndices++ = topRow + 8; *ptrHiIndices++ = nextRow + 8; *ptrHiIndices++ = nextRow + 8; // jump start *ptrHiIndices++ = topRow + 0; // jump end *ptrHiIndices++ = topRow + 0; *ptrLoIndices++ = topRow + 8; *ptrLoIndices++ = nextRow + 8; for( int col = 0; col < 8; col++ ) { *ptrHiIndices++ = nextRow + col; *ptrHiIndices++ = detailrow + col; } if( row < 8 ) *ptrHiIndices++ = nextRow + 8; if( row < 7 ) { *ptrHiIndices++ = nextRow + 8; // jump start *ptrLoIndices++ = nextRow + 8; } } verticesOffset += 9*9 + 8*8; worldTile->GetTerrainChunks()[iChunk] = newChunk; } return (Resource*)worldTile; }