void World::loadRegion(const PolyVox::ConstVolumeProxy<PolyVox::Material8>& volData, const PolyVox::Region& region) { std::stringstream ss; ss << "Info: loadRegion() is loading region: " << region.getLowerCorner() << " -> " << region.getUpperCorner(); Utils::log(ss.str()); uint8_t material = 2; int lo_x = region.getLowerCorner().getX() +1; int lo_y = region.getLowerCorner().getY() +1; int lo_z = region.getLowerCorner().getZ() +1; int hi_x = 7; int hi_y = 3; int hi_z = 7; for (int x=lo_x; x<hi_x; ++x) { for (int y=lo_y; y<hi_y; ++y) { for (int z=lo_z; z<hi_z; ++z) { PolyVox::Material8 voxel = volData.getVoxelAt(x,y,z); voxel.setMaterial(material); volData.setVoxelAt(x,y,z, voxel); } } } }
void VoxelTerrain::requestVolume( const PolyVox::ConstVolumeProxy<BYTE>& volume, const PolyVox::Region& region) { float interval = 1; //std::cout << "Begin filling VoxelTerrain." << std::endl; for (float z = region.getLowerCorner().getZ(); z <= region.getUpperCorner().getZ(); z+=interval) { for (float y = region.getLowerCorner().getY(); y <= region.getUpperCorner().getY(); y+=interval) { for (float x = region.getLowerCorner().getX(); x <= region.getUpperCorner().getX(); x+=interval) { //std::cout << x/region.getUpperCorner().getX() << std::endl; BYTE voxel_value = ground_cave_multiply.get( 5*x/region.getUpperCorner().getX(), y/region.getUpperCorner().getY(), 5*z/region.getUpperCorner().getZ())*255; // if (static_cast<double>(voxel_value) != 0) // std::cout << static_cast<double>(voxel_value) << std::endl; volume.setVoxelAt(x, y, z, voxel_value); } } } //std::cout << "Done filling VoxelTerrain." << std::endl; }
virtual void pageIn(const PolyVox::Region& region, PagedVolume<MaterialDensityPair44>::Chunk* pChunk) { Perlin perlin(2, 2, 1, 234); for (int x = region.getLowerX(); x <= region.getUpperX(); x++) { for (int y = region.getLowerY(); y <= region.getUpperY(); y++) { float perlinVal = perlin.Get(x / static_cast<float>(255 - 1), y / static_cast<float>(255 - 1)); perlinVal += 1.0f; perlinVal *= 0.5f; perlinVal *= 255; for (int z = region.getLowerZ(); z <= region.getUpperZ(); z++) { MaterialDensityPair44 voxel; if (z < perlinVal) { const int xpos = 50; const int zpos = 100; if ((x - xpos)*(x - xpos) + (z - zpos)*(z - zpos) < 200) { // tunnel voxel.setMaterial(0); voxel.setDensity(MaterialDensityPair44::getMinDensity()); } else { // solid voxel.setMaterial(245); voxel.setDensity(MaterialDensityPair44::getMaxDensity()); } } else { voxel.setMaterial(0); voxel.setDensity(MaterialDensityPair44::getMinDensity()); } // Voxel position within a chunk always start from zero. So if a chunk represents region (4, 8, 12) to (11, 19, 15) // then the valid chunk voxels are from (0, 0, 0) to (7, 11, 3). Hence we subtract the lower corner position of the // region from the volume space position in order to get the chunk space position. pChunk->setVoxel(x - region.getLowerX(), y - region.getLowerY(), z - region.getLowerZ(), voxel); } } } }
// This function encodes a Region as a 64-bit integer so that it can be used as a key to access chunk data in the SQLite database. // A region actually contains more than 64-bits of data so some has to be lost here. Specifically we assume that we already know // the size of the region (so we only have to encode it's lower corner and not its upper corner or extents), and we also restrict // the range of valid coordinates. A Region's coordinates are represented by 3-bits of data, but we only support converting to a key // if every coordinate can be represented by 21 bits of data. This way we can fit three coordinates only 63 bits of data. This limits // the range of values to +/- 2^20, which is enough for our purposes. uint64_t regionToKey(const PolyVox::Region& region) { // Cast to unsigned values so that bit shifting works predictably. uint32_t x = static_cast<uint32_t>(region.getLowerX()); uint32_t y = static_cast<uint32_t>(region.getLowerY()); uint32_t z = static_cast<uint32_t>(region.getLowerZ()); // The magnitude of our input values is fairly restricted, but the values could stil be negative. This means the sign bit could // be set and this needs to be encoded as well. We therefore perform a left rotate on the bits to bring the sign bit into the LSB. x = rotateLeft(x); y = rotateLeft(y); z = rotateLeft(z); // Now convert to 64-bits uint64_t x64 = x; uint64_t y64 = y; uint64_t z64 = z; // Morten-encode the components to give our final key uint64_t result = EncodeMorton3(x64, y64, z64); // Return the combined value return result; }
void LargeVoxelSphere::VoxelSpherePager::pageIn( const PolyVox::Region& region, PolyVox::PagedVolume<BYTE>::Chunk* chunk) { for (int z = region.getLowerCorner().getZ(); z <= region.getUpperCorner().getZ(); z++) { for (int y = region.getLowerCorner().getY(); y <= region.getUpperCorner().getY(); y++) { for (int x = region.getLowerCorner().getX(); x <= region.getUpperCorner().getX(); x++) { PolyVox::Vector3DFloat current_pos(x,y,z); PolyVox::Vector3DFloat volume_center(0,0,0); float dist_to_center = (current_pos - volume_center).length(); BYTE voxel_value = 0; if(dist_to_center <= 100) { voxel_value = 255; } chunk->setVoxel(x, y, z, voxel_value); } } } }
virtual void pageOut(const PolyVox::Region& region, PagedVolume<MaterialDensityPair44>::Chunk* /*pChunk*/) { std::cout << "warning unloading region: " << region.getLowerCorner() << " -> " << region.getUpperCorner() << std::endl; }
UBasicVolume::VolumeType* ImportMagicaVoxel(FArchive& Ar) { // https://voxel.codeplex.com/wikipage?title=Sample%20Codes //auto* Result = new RawVolume(region); //return Result; const int MV_VERSION = 150; const int ID_VOX = MV_ID('V', 'O', 'X', ' '); const int ID_MAIN = MV_ID('M', 'A', 'I', 'N'); const int ID_SIZE = MV_ID('S', 'I', 'Z', 'E'); const int ID_XYZI = MV_ID('X', 'Y', 'Z', 'I'); const int ID_RGBA = MV_ID('R', 'G', 'B', 'A'); int32 magic; int32 version; // magic number Ar << magic; if (magic != ID_VOX) { UE_LOG(LogVoreealVolumeImporter, Warning, TEXT("magic number does not match")); return nullptr; } // version Ar << version; if (version != MV_VERSION) { UE_LOG(LogVoreealVolumeImporter, Warning, TEXT("version does not match")); return nullptr; } // main chunk vox_chunk_t mainChunk; ReadChunk(Ar, mainChunk); if (mainChunk.id != ID_MAIN) { UE_LOG(LogVoreealVolumeImporter, Warning, TEXT("main chunk is not found")); return nullptr; } bool isCustomPalette; MV_RGBA palette[256]; MV_Voxel* voxels = nullptr; int32 sizex = 0, sizey = 0, sizez = 0, numVoxels = 0; while (!Ar.AtEnd()) { // read chunk header vox_chunk_t sub; ReadChunk(Ar, sub); if (sub.id == ID_SIZE) { // size Ar << sizex << sizey << sizez; } else if (sub.id == ID_XYZI) { // numVoxels Ar << numVoxels; if (numVoxels < 0) { UE_LOG(LogVoreealVolumeImporter, Warning, TEXT("negative number of voxels")); return nullptr; } // voxels if (numVoxels > 0) { voxels = new MV_Voxel[numVoxels]; Ar.Serialize(voxels, sizeof(MV_Voxel) * numVoxels); } } else if (sub.id == ID_RGBA) { // last color is not used, so we only need to read 255 colors isCustomPalette = true; Ar.Serialize(palette + 1, sizeof(MV_RGBA) * 255); // NOTICE : skip the last reserved color MV_RGBA reserved; Ar.Serialize(&reserved, sizeof(MV_RGBA)); } } PolyVox::Region region; region.setLowerCorner(PolyVox::Vector3DInt32(0, 0, 0)); region.setUpperCorner(PolyVox::Vector3DInt32(sizex, sizey, sizez)); auto* Result = new UBasicVolume::VolumeType(region); for (int32 i = 0; i < numVoxels; i++) { auto voxel = voxels[i]; auto color = palette[voxel.colorIndex]; uint32 data = (color.r) | (color.g) << 8 | (color.b) << 16 | (color.a) << 24; Result->setVoxel(voxel.x, voxel.y, voxel.z, data); } delete[] voxels; //// print model info //printf("[Log] MV_VoxelModel :: Model : %d %d %d : %d\n", // sizex, sizey, sizez, numVoxels // ); return Result; }
void World::unloadRegion(const PolyVox::ConstVolumeProxy<PolyVox::Material8>& volData, const PolyVox::Region& region) { std::stringstream ss; ss << "Info: unloadRegion() is unloading region: " << region.getLowerCorner() << " -> " << region.getUpperCorner(); Utils::log(ss.str()); }