#include #include "Area.h" #include "Block.h" #include "TransparentChunkGroundModel.h" #include "Constants.h" #include "FactoryCraftModel.h" #include "Globals.h" using namespace Framework; TransparentChunkGroundModel::TransparentChunkGroundModel( FactoryCraftModel* target, Chunk* zChunk) : ChunkModelBuilder(target, zChunk, Chunk::CombinedModels::TRANSPARENT_GROUND) {} __int64 TransparentChunkGroundModel::calculateLight( Framework::Vec3 vertexPos, Framework::Vec3 blockPos, Direction direction) { __int64 result = 0; int sumCount = 1; short lightSum[6]; Block* current = blocks()[Chunk::index(blockPos)]; const unsigned char* light = current->getLightData(direction); for (int i = 0; i < 6; i++) { lightSum[i] = (short)light[i]; } Vec3 vertexDirs(vertexPos.x < 0 ? -1 : 1, vertexPos.y < 0 ? -1 : 1, vertexPos.z < 0 ? -1 : 1); Directions dirs = getDirectionsFromVector(vertexDirs) & ~direction; Vec3 neighborDirs[3]; int neighborIndex = 0; for (int i = 0; i < 6; i++) { Direction dir = getDirectionFromIndex(i); if ((dirs | dir) == dirs) { neighborDirs[neighborIndex++] = getDirection(dir); if (neighborIndex == 2) break; } } neighborDirs[2] = neighborDirs[0] + neighborDirs[1]; for (int i = 0; i < 3; i++) { neighborDirs[i] += blockPos; if (neighborDirs[i].x >= 0 && neighborDirs[i].y >= 0 && neighborDirs[i].z >= 0 && neighborDirs[i].x < CHUNK_SIZE && neighborDirs[i].y < CHUNK_SIZE && neighborDirs[i].z < WORLD_HEIGHT) { int neighborIndex = Chunk::index(neighborDirs[i]); Block* neighbor = blocks()[neighborIndex]; if (neighbor) { const unsigned char* neighborLight = neighbor->getLightData(direction); if ((neighborLight[0] | neighborLight[1] | neighborLight[2] | neighborLight[3] | neighborLight[4] | neighborLight[5]) != 0) { sumCount++; for (int j = 0; j < 6; j++) { lightSum[j] += (short)neighborLight[j]; } } } } else { // TODO: get light from neighbor chunk } } for (int i = 0; i < 6; i++) { lightSum[i] = (lightSum[i] / sumCount) & 0xFF; } result = ((__int64)lightSum[0] << 24) | ((__int64)lightSum[1] << 16) | ((__int64)lightSum[2] << 8) | ((__int64)lightSum[3] << 56) | ((__int64)lightSum[4] << 48) | ((__int64)lightSum[5] << 40); return result; } void TransparentChunkGroundModel::buildModel() { Model3DData* chunkModel = target->zModelData(); // remove old model while (chunkModel->getPolygonAnzahl() > 0) { chunkModel->removePolygon(0); } // calculate verticies Trie groundModelBuidler; Array groundPartArray; Vertex3D* groundVerticies = new Vertex3D[10000]; __int64* lightBuffer = new __int64[10000]; int groundVertexCount = 0; int groundVertexArraySize = 10000; for (int i = 0; i < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT; i++) { if (blocks()[i]) { if (isPartOfModel(blocks()[i])) { setBlockPartOfModel(blocks()[i], 1); __int64 light = blocks()[i]->getMaxLight(); int index = 0; for (Text* textureName : *blocks()[i]->zBlockType()->getModelInfo().getTexturNames()) { if (!groundModelBuidler.get( *textureName, textureName->getLength())) { GroundModelPart* part = new GroundModelPart(); part->indexList = new int[10000]; part->indexCount = 0; part->indexArraySize = 10000; part->name = *textureName; groundModelBuidler.set( *textureName, textureName->getLength(), part); groundPartArray.add(part); } GroundModelPart* part = groundModelBuidler.get( *textureName, textureName->getLength()); const Vertex3D* vBuffer = blocks()[i]->zModelData()->zVertexBuffer(); Polygon3D* polygon = blocks()[i]->zModelData()->getPolygon(index); if (part->indexCount + polygon->indexAnz > part->indexArraySize) { int* tmp = new int[part->indexArraySize + 10000]; memcpy(tmp, part->indexList, part->indexCount * 4); delete[] part->indexList; part->indexList = tmp; part->indexArraySize += 10000; } if (groundVertexCount + polygon->indexAnz > groundVertexArraySize) { Vertex3D* tmp = new Vertex3D[groundVertexArraySize + 10000]; memcpy(tmp, groundVerticies, groundVertexCount * sizeof(Vertex3D)); delete[] groundVerticies; groundVerticies = tmp; groundVertexArraySize += 10000; __int64* lTmp = new __int64[groundVertexArraySize]; memcpy(lTmp, lightBuffer, groundVertexCount * sizeof(__int64)); delete[] lightBuffer; lightBuffer = lTmp; } for (int vi = 0; vi < polygon->indexAnz; vi++) { lightBuffer[groundVertexCount] = light; part->indexList[part->indexCount++] = groundVertexCount; groundVerticies[groundVertexCount++] = vBuffer[polygon->indexList[vi]]; groundVerticies[groundVertexCount - 1].pos += blocks()[i]->getPos() - Vec3((float)chunkCenter().x, (float)chunkCenter().y, (float)WORLD_HEIGHT / 2.f); groundVerticies[groundVertexCount - 1].id = groundVertexCount - 1; } index++; } } else { setBlockPartOfModel(blocks()[i], 0); } } } Model3DTextur* textur = new Model3DTextur(); int pi = 0; for (GroundModelPart* part : groundPartArray) { Polygon3D* polygon = new Polygon3D(); polygon->indexAnz = part->indexCount; polygon->indexList = part->indexList; target->zModelData()->addPolygon(polygon); textur->setPolygonTextur(pi, uiFactory.initParam.bildschirm->zGraphicsApi()->createOrGetTextur( part->name)); pi++; delete part; } target->zModelData()->setVertecies(groundVerticies, groundVertexCount); target->setModelTextur(textur); target->setVertexLightBuffer(lightBuffer, groundVertexCount); } bool TransparentChunkGroundModel::updateLightning() { __int64* lightBuffer = target->zLightBuffer(); int groundVertexCount = 0; for (int i = 0; i < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT; i++) { if (blocks()[i]) { if (isPartOfModel(blocks()[i])) { __int64 light = blocks()[i]->getMaxLight(); int index = 0; for (Text* textureName : *blocks()[i]->zBlockType()->getModelInfo().getTexturNames()) { const Vertex3D* vBuffer = blocks()[i]->zModelData()->zVertexBuffer(); Polygon3D* polygon = blocks()[i]->zModelData()->getPolygon(index); for (int vi = 0; vi < polygon->indexAnz; vi++) { lightBuffer[groundVertexCount++] = light; } } } } } target->copyLightToGPU(); return 1; } bool TransparentChunkGroundModel::isTransparent() const { return true; } bool TransparentChunkGroundModel::isPartOfModel(Block* zBlock) const { return zBlock->zBlockType()->getModelInfo().getModelName().istGleich( "grass"); }