Example #1
0
	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;
	}