use of org.terasology.world.generation.Region in project Terasology by MovingBlocks.
the class FacetLayerPreview method render.
@Override
public ByteBuffer render(TextureData texData, int scale, ProgressListener progressListener) throws InterruptedException {
int width = texData.getWidth();
int height = texData.getWidth();
final int offX = -width * scale / 2;
final int offY = -height * scale / 2;
// trigger building the World now
worldGenerator.getWorld();
Rect2i worldArea = Rect2i.createFromMinAndSize(offX, offY, width * scale, height * scale);
Rect2i tileArea = worldToTileArea(worldArea);
AtomicInteger tilesComplete = new AtomicInteger(0);
int tileCount = tileArea.area();
int[] masks = colorModel.getMasks();
DataBufferInt imageBuffer = new DataBufferInt(width * height);
WritableRaster raster = Raster.createPackedRaster(imageBuffer, width, height, width, masks, null);
BufferedImage view = new BufferedImage(colorModel, raster, false, null);
Graphics2D g = view.createGraphics();
g.scale(1f / scale, 1f / scale);
g.translate(-offX, -offY);
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
Map<ImmutableVector2i, Future<BufferedImage>> imageFutures = new HashMap<>(tileCount);
for (int z = tileArea.minY(); z < tileArea.maxY(); z++) {
for (int x = tileArea.minX(); x < tileArea.maxX(); x++) {
ImmutableVector2i pos = new ImmutableVector2i(x, z);
imageFutures.put(pos, threadPool.submit(() -> {
Region createRegion = createRegion(pos);
BufferedImage image = rasterize(createRegion);
if (progressListener != null) {
progressListener.onProgress(tilesComplete.incrementAndGet() / (float) tileCount);
}
return image;
}));
}
}
for (int z = tileArea.minY(); z < tileArea.maxY(); z++) {
for (int x = tileArea.minX(); x < tileArea.maxX(); x++) {
ImmutableVector2i pos = new ImmutableVector2i(x, z);
try {
BufferedImage tileImage = imageFutures.get(pos).get();
g.drawImage(tileImage, x * TILE_SIZE_X, z * TILE_SIZE_Y, null);
} catch (ExecutionException e) {
logger.warn("Could not rasterize tile {}", pos, e);
}
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
}
}
}
// draw coordinate lines through 0 / 0
g.setColor(Color.GRAY);
g.drawLine(worldArea.minX(), 0, worldArea.maxX(), 0);
g.drawLine(0, worldArea.minY(), 0, worldArea.maxY());
g.dispose();
int[] data = imageBuffer.getData();
ByteBuffer byteBuffer = texData.getBuffers()[0];
byteBuffer.asIntBuffer().put(data);
return byteBuffer;
}
use of org.terasology.world.generation.Region in project Terasology by MovingBlocks.
the class FacetLayerPreview method createRegion.
private Region createRegion(ImmutableVector2i chunkPos) {
// 4 chunks high (relevant for trees, etc)
int vertChunks = 4;
int minX = chunkPos.getX() * TILE_SIZE_X;
int minZ = chunkPos.getY() * TILE_SIZE_Y;
int height = vertChunks * ChunkConstants.SIZE_Y;
Region3i area3d = Region3i.createFromMinAndSize(new Vector3i(minX, 0, minZ), new Vector3i(TILE_SIZE_X, height, TILE_SIZE_Y));
World world = worldGenerator.getWorld();
Region region = world.getWorldData(area3d);
return region;
}
use of org.terasology.world.generation.Region in project Terasology by MovingBlocks.
the class AbstractSpawner method findSpawnPosition.
/**
* Tries to find a suitable spawning point based on {@link SurfaceHeightFacet} and {@link SeaLevelFacet}.
* @param searchRadius the radius within a suitable spawning point will be searched
* @param world the facet-based world
* @param pos the desired 2D position in that world
* @return a 3D position above the surface and sea level or <code>null</code> if none was found
* @throws IllegalStateException if no SurfaceHeightFacet can be created.
*/
protected Vector3f findSpawnPosition(World world, Vector2i pos, int searchRadius) {
Vector3i ext = new Vector3i(searchRadius, 1, searchRadius);
Vector3i desiredPos = new Vector3i(pos.getX(), 1, pos.getY());
// try and find somewhere in this region a spot to land
Region3i spawnArea = Region3i.createFromCenterExtents(desiredPos, ext);
Region worldRegion = world.getWorldData(spawnArea);
// check if generation uses sea level and surface height facets
SurfaceHeightFacet surfaceHeightFacet = worldRegion.getFacet(SurfaceHeightFacet.class);
if (surfaceHeightFacet == null) {
throw new IllegalStateException("surface height facet not found");
}
SeaLevelFacet seaLevelFacet = worldRegion.getFacet(SeaLevelFacet.class);
int seaLevel = (seaLevelFacet != null) ? seaLevelFacet.getSeaLevel() : 0;
int spiralRad = searchRadius / 2 - 1;
SpiralIterable spiral = SpiralIterable.clockwise(pos).maxRadius(spiralRad).scale(2).build();
for (BaseVector2i test : spiral) {
float val = surfaceHeightFacet.getWorld(test.getX(), test.getY());
int height = TeraMath.floorToInt(val);
if (height >= seaLevel) {
return new Vector3f(test.getX(), height, test.getY());
}
}
// nothing above sea level found
float y = surfaceHeightFacet.getWorld(pos.getX(), pos.getY());
return new Vector3f(pos.getX(), y, pos.getY());
}
use of org.terasology.world.generation.Region in project Terasology by MovingBlocks.
the class FloraRasterizer method generateChunk.
@Override
public void generateChunk(CoreChunk chunk, Region chunkRegion) {
FloraFacet facet = chunkRegion.getFacet(FloraFacet.class);
WhiteNoise noise = new WhiteNoise(chunk.getPosition().hashCode());
Map<BaseVector3i, FloraType> entries = facet.getRelativeEntries();
// check if some other rasterizer has already placed something here
entries.keySet().stream().filter(pos -> chunk.getBlock(pos).equals(air)).forEach(pos -> {
FloraType type = entries.get(pos);
List<Block> list = flora.get(type);
int blockIdx = Math.abs(noise.intNoise(pos.x(), pos.y(), pos.z())) % list.size();
Block block = list.get(blockIdx);
chunk.setBlock(pos, block);
});
}
use of org.terasology.world.generation.Region in project Terasology by MovingBlocks.
the class TreeFacetLayer method getWorldText.
@Override
public String getWorldText(Region region, int wx, int wy) {
TreeFacet treeFacet = region.getFacet(TreeFacet.class);
Region3i worldRegion = treeFacet.getWorldRegion();
Region3i relativeRegion = treeFacet.getRelativeRegion();
int rx = wx - worldRegion.minX() + relativeRegion.minX();
int rz = wy - worldRegion.minZ() + relativeRegion.minZ();
Vector2f relCursor = new Vector2f(rx, rz);
CirclePicker<TreeGenerator> picker = new CirclePickerAll<>(relCursor, radiusFunc);
for (Entry<BaseVector3i, TreeGenerator> entry : treeFacet.getRelativeEntries().entrySet()) {
TreeGenerator treeGen = entry.getValue();
BaseVector3i treePos = entry.getKey();
picker.offer(treePos.getX(), treePos.getZ(), treeGen);
}
Set<TreeGenerator> picked = picker.getAll();
// try to exit early first
if (picked.isEmpty()) {
return null;
}
if (picked.size() == 1) {
TreeGenerator first = picked.iterator().next();
return labelFunc.apply(first);
}
// convert to a stream of labels
Stream<String> labels = picked.stream().map(labelFunc);
// collect identical String elements and collect the count in a map
Map<String, Long> counters = labels.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
// define a mapping from a map entry to a String representation
// TODO: treat 1x occurrences like above (e.g. Tree instead of 1x Tree)
Function<Entry<String, Long>, String> toStringFunc = e -> String.format("%dx %s", e.getValue(), e.getKey());
// apply that mapping and join the Strings with a comma
return counters.entrySet().stream().map(toStringFunc).collect(Collectors.joining(", "));
}
Aggregations