mirror of
https://github.com/copyrighttxt/watrbx-game-engine.git
synced 2026-09-04 20:57:49 +00:00
185 lines
6.8 KiB
C++
185 lines
6.8 KiB
C++
#pragma once
|
|
|
|
namespace RBX { namespace Voxel {
|
|
|
|
template<unsigned int XDim, unsigned int YDim, unsigned int ZDim>
|
|
bool AreaCopy<XDim, YDim, ZDim>::Chunk::contains(const Vector3int16& cellLocation) const {
|
|
return cellLocation.isBetweenInclusive(firstCellLocation,
|
|
firstCellLocation + Vector3int16(XDim, YDim, ZDim) - Vector3int16::one());
|
|
}
|
|
|
|
template<unsigned int XDim, unsigned int YDim, unsigned int ZDim>
|
|
void AreaCopy<XDim, YDim, ZDim>::Chunk::fillEmpty(
|
|
const Vector3int16& minLoc, const Vector3int16& maxLoc) {
|
|
|
|
unsigned int xWidth = maxLoc.x - minLoc.x + 1;
|
|
RBXASSERT((xWidth & 0x1) == 0);
|
|
|
|
Vector3int16 counter;
|
|
for (counter.y = minLoc.y; counter.y <= maxLoc.y; ++counter.y) {
|
|
for (counter.z = minLoc.z; counter.z <= maxLoc.z; ++counter.z) {
|
|
counter.x = minLoc.x;
|
|
unsigned int index = voxelCoordToArrayIndex(counter);
|
|
memset(&cells[index],
|
|
Cell::convertToUnsignedCharForFile(Constants::kUniqueEmptyCellRepresentation),
|
|
xWidth * sizeof(Cell));
|
|
// technically material doesn't need to be set for empty cells
|
|
memset(&materials[index / 2], 0xff, xWidth / 2);
|
|
}
|
|
}
|
|
}
|
|
|
|
template<unsigned int XDim, unsigned int YDim, unsigned int ZDim>
|
|
template<class RegionType>
|
|
void AreaCopy<XDim, YDim, ZDim>::Chunk::fillFromRegion(const RegionType& region) {
|
|
for (typename RegionType::xline_iterator itr = region.xLineBegin();
|
|
itr != region.xLineEnd(); ++itr) {
|
|
const size_t lineSize = itr.getLineSize();
|
|
RBXASSERT(contains(itr.getCurrentLocation()));
|
|
RBXASSERT(contains(itr.getCurrentLocation() + Vector3int16(lineSize - 1, 0, 0)));
|
|
|
|
unsigned int index = voxelCoordToArrayIndex(itr.getCurrentLocation());
|
|
if (lineSize == 32) {
|
|
memcpy(&cells[index], itr.getLineCells(), 32 * sizeof(Cell));
|
|
memcpy(&materials[index/2], itr.getLineMaterials(), 32 / 2);
|
|
} else {
|
|
const Cell* cellSrc = itr.getLineCells();
|
|
const unsigned char* materialSrc = itr.getLineMaterials();
|
|
for (size_t i = 0; i < lineSize; ++i) {
|
|
cells[index + i] = cellSrc[i];
|
|
materials[(index + i) / 2] = materialSrc[i / 2];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
template<unsigned int XDim, unsigned int YDim, unsigned int ZDim>
|
|
int AreaCopy<XDim, YDim, ZDim>::Chunk::kFaceDirectionToPointerOffset[7] = {
|
|
1,
|
|
XDim,
|
|
-1,
|
|
-((int)XDim),
|
|
XDim * ZDim,
|
|
-(int)(XDim * ZDim),
|
|
0
|
|
};
|
|
|
|
template<unsigned int XDim, unsigned int YDim, unsigned int ZDim>
|
|
int AreaCopy<XDim, YDim, ZDim>::Chunk::voxelCoordOffsetToIndexOffset(
|
|
const Vector3int16& localCoord) {
|
|
return localCoord.x + (XDim * localCoord.z) + (XDim * ZDim * localCoord.y);
|
|
}
|
|
|
|
template<unsigned int XDim, unsigned int YDim, unsigned int ZDim>
|
|
int AreaCopy<XDim, YDim, ZDim>::Chunk::voxelCoordToArrayIndex(
|
|
const Vector3int16& globalCoord) const {
|
|
return voxelCoordOffsetToIndexOffset(globalCoord - firstCellLocation);
|
|
}
|
|
|
|
template<unsigned int XDim, unsigned int YDim, unsigned int ZDim>
|
|
const std::vector<Cell>& AreaCopy<XDim, YDim, ZDim>::Chunk::getConstData() const {
|
|
return cells;
|
|
}
|
|
|
|
template<unsigned int XDim, unsigned int YDim, unsigned int ZDim>
|
|
const std::vector<unsigned char>& AreaCopy<XDim, YDim, ZDim>::Chunk::getConstMaterial() const {
|
|
return materials;
|
|
}
|
|
|
|
template<unsigned int XDim, unsigned int YDim, unsigned int ZDim>
|
|
void AreaCopy<XDim, YDim, ZDim>::Chunk::fillLocalAreaInfo(
|
|
const Vector3int16& globalCoord,
|
|
const Water::RelevantNeighbors& relevantNeighbors,
|
|
Water::LocalAreaInfo* out) const {
|
|
|
|
RBXASSERT(contains(globalCoord));
|
|
RBXASSERT(contains(globalCoord + relevantNeighbors.aboveNeighbor));
|
|
RBXASSERT(contains(globalCoord + relevantNeighbors.primaryNeighbor));
|
|
RBXASSERT(contains(globalCoord + relevantNeighbors.secondaryNeighbor));
|
|
RBXASSERT(contains(globalCoord + relevantNeighbors.diagonalNeighbor));
|
|
RBXASSERT(contains(globalCoord + relevantNeighbors.diagonalUpNeighbor));
|
|
|
|
unsigned int centerIndex = voxelCoordToArrayIndex(globalCoord);
|
|
|
|
out->aboveNeighbor = cells[centerIndex +
|
|
voxelCoordOffsetToIndexOffset(relevantNeighbors.aboveNeighbor)];
|
|
out->primaryNeighbor = cells[centerIndex +
|
|
voxelCoordOffsetToIndexOffset(relevantNeighbors.primaryNeighbor)];
|
|
out->secondaryNeighbor = cells[centerIndex +
|
|
voxelCoordOffsetToIndexOffset(relevantNeighbors.secondaryNeighbor)];
|
|
out->diagonalNeighbor = cells[centerIndex +
|
|
voxelCoordOffsetToIndexOffset(relevantNeighbors.diagonalNeighbor)];
|
|
out->diagonalUpNeighbor = cells[centerIndex +
|
|
voxelCoordOffsetToIndexOffset(relevantNeighbors.diagonalUpNeighbor)];
|
|
}
|
|
|
|
template<unsigned int XDim, unsigned int YDim, unsigned int ZDim>
|
|
template<class Source>
|
|
void AreaCopy<XDim, YDim, ZDim>::Chunk::loadData(const Source* source,
|
|
const Vector3int16& rootCell) {
|
|
|
|
if (cells.empty()) {
|
|
std::vector<Cell> cellsSwap(kSize, Constants::kUniqueEmptyCellRepresentation);
|
|
std::vector<unsigned char> materialsSwap((kSize + 1) / 2, 0xff);
|
|
cells.swap(cellsSwap);
|
|
materials.swap(materialsSwap);
|
|
}
|
|
|
|
firstCellLocation = rootCell;
|
|
|
|
const Vector3int16 maxCell = rootCell +
|
|
Vector3int16(XDim, YDim, ZDim) - Vector3int16::one();
|
|
|
|
const SpatialRegion::Id minRegion =
|
|
SpatialRegion::regionContainingVoxel(rootCell);
|
|
const SpatialRegion::Id maxRegion =
|
|
SpatialRegion::regionContainingVoxel(maxCell);
|
|
|
|
isAllEmpty = true;
|
|
Vector3int16 regionIdCounter;
|
|
for (regionIdCounter.y = minRegion.value().y; regionIdCounter.y <= maxRegion.value().y; ++regionIdCounter.y) {
|
|
for (regionIdCounter.z = minRegion.value().z; regionIdCounter.z <= maxRegion.value().z; ++regionIdCounter.z) {
|
|
for (regionIdCounter.x = minRegion.value().x; regionIdCounter.x <= maxRegion.value().x; ++regionIdCounter.x) {
|
|
SpatialRegion::Id id(regionIdCounter);
|
|
Region3int16 extents = SpatialRegion::inclusiveVoxelExtentsOfRegion(id);
|
|
const Vector3int16 queryMin = extents.getMinPos().max(rootCell);
|
|
const Vector3int16 queryMax = extents.getMaxPos().min(maxCell);
|
|
|
|
// for material alignment issues, all x segments must be even, and
|
|
// start from an even location in the region
|
|
RBXASSERT(((queryMax.x - queryMin.x + 1) & 0x1) == 0);
|
|
RBXASSERT(((queryMin.x - firstCellLocation.x) & 0x1) == 0);
|
|
|
|
typename Source::Region region = source->getRegion(queryMin, queryMax);
|
|
if (region.isGuaranteedAllEmpty()) {
|
|
fillEmpty(queryMin, queryMax);
|
|
} else {
|
|
isAllEmpty = false;
|
|
fillFromRegion(region);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
template<unsigned int XDim, unsigned int YDim, unsigned int ZDim>
|
|
bool AreaCopy<XDim, YDim, ZDim>::Chunk::getIsAllEmpty() const {
|
|
return isAllEmpty;
|
|
}
|
|
|
|
|
|
template<unsigned int XDim, unsigned int YDim, unsigned int ZDim>
|
|
typename AreaCopy<XDim, YDim, ZDim>::Region AreaCopy<XDim, YDim, ZDim>::getRegion(
|
|
const Vector3int16& minCoords, const Vector3int16& maxCoords) const {
|
|
return Region(storage.getIsAllEmpty() ? NULL : &storage, minCoords, maxCoords);
|
|
}
|
|
|
|
template<unsigned int XDim, unsigned int YDim, unsigned int ZDim>
|
|
template<class Source>
|
|
void AreaCopy<XDim, YDim, ZDim>::loadData(const Source* source,
|
|
const Vector3int16& rootCell) {
|
|
storage.loadData(source, rootCell);
|
|
}
|
|
|
|
} }
|