Remove the BlockContext concept and move the functionality to the Block itself, this improves Render-Speed by A LOT!

This commit is contained in:
Blue (Lukas Rieger) 2020-01-06 15:15:25 +01:00
parent 3e87768d25
commit 76ea6e1918
15 changed files with 109 additions and 530 deletions

View File

@ -104,6 +104,7 @@ public class BlueMapCLI {
HiresModelManager hiresModelManager = new HiresModelManager(
config.getWebDataPath().resolve("hires").resolve(mapConfig.getId()),
resourcePack,
mapConfig,
new Vector2i(mapConfig.getHiresTileSize(), mapConfig.getHiresTileSize()),
ForkJoinPool.commonPool()
);
@ -114,7 +115,7 @@ public class BlueMapCLI {
new Vector2i(mapConfig.getLowresPointsPerHiresTile(), mapConfig.getLowresPointsPerHiresTile())
);
TileRenderer tileRenderer = new TileRenderer(hiresModelManager, lowresModelManager, mapConfig);
TileRenderer tileRenderer = new TileRenderer(hiresModelManager, lowresModelManager);
MapType mapType = new MapType(mapConfig.getId(), mapConfig.getName(), world, tileRenderer);
maps.put(mapConfig.getId(), mapType);

View File

@ -34,12 +34,10 @@ import de.bluecolored.bluemap.core.util.AABB;
public class TileRenderer {
private HiresModelManager hiresModelManager;
private LowresModelManager lowresModelManager;
private RenderSettings renderSettings;
public TileRenderer(HiresModelManager hiresModelManager, LowresModelManager lowresModelManager, RenderSettings renderSettings) {
public TileRenderer(HiresModelManager hiresModelManager, LowresModelManager lowresModelManager) {
this.hiresModelManager = hiresModelManager;
this.lowresModelManager = lowresModelManager;
this.renderSettings = renderSettings.copy();
}
/**
@ -51,7 +49,7 @@ public class TileRenderer {
AABB area = hiresModelManager.getTileRegion(tile);
if (!tile.getWorld().isAreaGenerated(area)) return;
HiresModel hiresModel = hiresModelManager.render(tile, renderSettings);
HiresModel hiresModel = hiresModelManager.render(tile);
lowresModelManager.render(hiresModel);
}
@ -70,8 +68,4 @@ public class TileRenderer {
return lowresModelManager;
}
public RenderSettings getRenderSettings() {
return renderSettings;
}
}

View File

@ -1,57 +0,0 @@
/*
* This file is part of BlueMap, licensed under the MIT License (MIT).
*
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package de.bluecolored.bluemap.core.render.context;
import com.flowpowered.math.vector.Vector3i;
import de.bluecolored.bluemap.core.util.Direction;
import de.bluecolored.bluemap.core.world.Block;
public interface BlockContext {
Vector3i getPosition();
/**
* This returns neighbour blocks.<br>
* The distance can not be larger than one block in each direction!<br>
*/
Block getRelativeBlock(Vector3i direction);
/**
* This returns neighbour blocks.<br>
* The distance can not be larger than one block in each direction!<br>
*/
default Block getRelativeBlock(int x, int y, int z){
return getRelativeBlock(new Vector3i(x, y, z));
}
/**
* This returns neighbour blocks.
*/
default Block getRelativeBlock(Direction direction){
return getRelativeBlock(direction.toVector());
}
}

View File

@ -1,153 +0,0 @@
/*
* This file is part of BlueMap, licensed under the MIT License (MIT).
*
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package de.bluecolored.bluemap.core.render.context;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.UUID;
import com.flowpowered.math.vector.Vector2i;
import com.flowpowered.math.vector.Vector3i;
import de.bluecolored.bluemap.core.world.Biome;
import de.bluecolored.bluemap.core.world.Block;
import de.bluecolored.bluemap.core.world.BlockState;
import de.bluecolored.bluemap.core.world.World;
public class EmptyBlockContext implements ExtendedBlockContext {
private static final EmptyBlockContext instance = new EmptyBlockContext();
public static final Block AIR_BLOCK = new AirBlock();
private EmptyBlockContext() {}
@Override
public Block getRelativeBlock(Vector3i direction) {
return AIR_BLOCK;
}
@Override
public Vector3i getPosition() {
return Vector3i.ZERO;
}
public static ExtendedBlockContext instance() {
return instance;
}
private static class AirBlock extends Block {
private BlockState state = BlockState.AIR;
@Override
public BlockState getBlock() {
return state;
}
@Override
public World getWorld() {
return new EmptyWorld();
}
@Override
public Vector3i getPosition() {
return Vector3i.ZERO;
}
@Override
public double getSunLightLevel() {
return 0d;
}
@Override
public double getBlockLightLevel() {
return 0d;
}
@Override
public boolean isCullingNeighborFaces() {
return false;
}
@Override
public boolean isFlammable() {
return false;
}
@Override
public Biome getBiome() {
return Biome.DEFAULT;
}
}
private static class EmptyWorld implements World {
@Override
public Block getBlock(Vector3i pos) {
return new AirBlock();
}
@Override
public String getName() {
return "-empty-";
}
@Override
public UUID getUUID() {
return new UUID(0, 0);
}
@Override
public int getSeaLevel() {
return 63;
}
@Override
public Vector3i getSpawnPoint() {
return new Vector3i(0, 63, 0);
}
@Override
public Collection<Vector2i> getChunkList(long modifiedSince) {
return Collections.emptyList();
}
@Override
public void invalidateChunkCache() {}
@Override
public void invalidateChunkCache(Vector2i chunk) {}
@Override
public boolean isChunkGenerated(Vector2i chunkPos) throws IOException {
return false;
}
}
}

View File

@ -1,74 +0,0 @@
/*
* This file is part of BlueMap, licensed under the MIT License (MIT).
*
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package de.bluecolored.bluemap.core.render.context;
import com.flowpowered.math.vector.Vector3i;
import de.bluecolored.bluemap.core.world.Block;
/**
* A BlockContext that has a range of TWO blocks instead of one
*/
public interface ExtendedBlockContext extends BlockContext {
/**
* This returns neighbour blocks.<br>
* The distance can not be larger than two blocks in each direction!<br>
*/
@Override
Block getRelativeBlock(Vector3i direction);
/**
* This returns neighbour blocks.<br>
* The distance can not be larger than two blocks in each direction!<br>
*/
@Override
default Block getRelativeBlock(int x, int y, int z){
return getRelativeBlock(new Vector3i(x, y, z));
}
/**
* Returns a relative view of this ExtendedBlockContext!
* The distance can not be larger than two blocks in each direction!<br>
*/
default BlockContext getRelativeView(final Vector3i relative) {
final ExtendedBlockContext parent = this;
return new BlockContext() {
@Override
public Block getRelativeBlock(Vector3i direction) {
return parent.getRelativeBlock(direction.add(relative));
}
@Override
public Vector3i getPosition() {
return parent.getPosition().add(relative);
}
};
}
}

View File

@ -1,52 +0,0 @@
/*
* This file is part of BlueMap, licensed under the MIT License (MIT).
*
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package de.bluecolored.bluemap.core.render.context;
import com.flowpowered.math.vector.Vector3i;
import de.bluecolored.bluemap.core.world.Block;
import de.bluecolored.bluemap.core.world.World;
public class SlicedWorldBlockContext extends WorldBlockContext {
private int sliceY;
/**
* Same as a {@link WorldBlockContext} but if the requested Block is above the slice-value it will return air.
*/
public SlicedWorldBlockContext(World world, Vector3i blockPos, int sliceY) {
super(world, blockPos);
this.sliceY = sliceY;
}
@Override
protected Block getBlock(Vector3i position) {
if (position.getY() > sliceY) return EmptyBlockContext.AIR_BLOCK;
return super.getBlock(position);
}
}

View File

@ -1,69 +0,0 @@
/*
* This file is part of BlueMap, licensed under the MIT License (MIT).
*
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package de.bluecolored.bluemap.core.render.context;
import com.flowpowered.math.vector.Vector3i;
import de.bluecolored.bluemap.core.world.Block;
import de.bluecolored.bluemap.core.world.World;
public class WorldBlockContext implements ExtendedBlockContext {
private Vector3i blockPos;
private World world;
/**
* A BlockContext backed by a WorldChunk.
*
* This Context assumes that the world-chunk is generated around that block-position.
* If the given world chunk is not generated, using this context will result in a RuntimeException!
*/
public WorldBlockContext(World world, Vector3i blockPos) {
this.blockPos = blockPos;
this.world = world;
}
@Override
public Vector3i getPosition() {
return blockPos;
}
@Override
public Block getRelativeBlock(int x, int y, int z) {
Vector3i pos = blockPos.add(x, y, z);
return getBlock(pos);
}
@Override
public Block getRelativeBlock(Vector3i direction) {
Vector3i pos = blockPos.add(direction);
return getBlock(pos);
}
protected Block getBlock(Vector3i position) {
return world.getBlock(position);
}
}

View File

@ -55,8 +55,8 @@ public class HiresModelManager {
private ExecutorService savingExecutor;
public HiresModelManager(Path fileRoot, ResourcePack resourcePack, Vector2i tileSize, ExecutorService savingExecutor) {
this(fileRoot, new HiresModelRenderer(resourcePack), tileSize, new Vector2i(2, 2), savingExecutor);
public HiresModelManager(Path fileRoot, ResourcePack resourcePack, RenderSettings renderSettings, Vector2i tileSize, ExecutorService savingExecutor) {
this(fileRoot, new HiresModelRenderer(resourcePack, renderSettings), tileSize, new Vector2i(2, 2), savingExecutor);
}
public HiresModelManager(Path fileRoot, HiresModelRenderer renderer, Vector2i tileSize, Vector2i gridOrigin, ExecutorService savingExecutor) {
@ -72,8 +72,8 @@ public class HiresModelManager {
/**
* Renders the given world tile with the provided render-settings
*/
public HiresModel render(WorldTile tile, RenderSettings renderSettings) {
HiresModel model = renderer.render(tile, getTileRegion(tile), renderSettings);
public HiresModel render(WorldTile tile) {
HiresModel model = renderer.render(tile, getTileRegion(tile));
save(model);
return model;
}

View File

@ -31,8 +31,6 @@ import com.flowpowered.math.vector.Vector4f;
import de.bluecolored.bluemap.core.logger.Logger;
import de.bluecolored.bluemap.core.render.RenderSettings;
import de.bluecolored.bluemap.core.render.WorldTile;
import de.bluecolored.bluemap.core.render.context.ExtendedBlockContext;
import de.bluecolored.bluemap.core.render.context.SlicedWorldBlockContext;
import de.bluecolored.bluemap.core.render.hires.blockmodel.BlockStateModel;
import de.bluecolored.bluemap.core.render.hires.blockmodel.BlockStateModelFactory;
import de.bluecolored.bluemap.core.resourcepack.NoSuchResourceException;
@ -45,17 +43,15 @@ import de.bluecolored.bluemap.core.world.World;
public class HiresModelRenderer {
private RenderSettings renderSettings;
private BlockStateModelFactory modelFactory;
public HiresModelRenderer(ResourcePack resourcePack) {
this(new BlockStateModelFactory(resourcePack));
public HiresModelRenderer(ResourcePack resourcePack, RenderSettings renderSettings) {
this.renderSettings = renderSettings;
this.modelFactory = new BlockStateModelFactory(resourcePack, renderSettings);
}
public HiresModelRenderer(BlockStateModelFactory modelFactory) {
this.modelFactory = modelFactory;
}
public HiresModel render(WorldTile tile, AABB region, RenderSettings renderSettings) {
public HiresModel render(WorldTile tile, AABB region) {
Vector3i min = region.getMin().toInt();
Vector3i max = region.getMax().toInt();
@ -78,14 +74,12 @@ public class HiresModelRenderer {
if (!block.getBlock().equals(BlockState.AIR)) maxHeight = y;
ExtendedBlockContext context = new SlicedWorldBlockContext(world, new Vector3i(x, y, z), renderSettings.getSliceY());
BlockStateModel blockModel;
try {
blockModel = modelFactory.createFrom(block.getBlock(), context, renderSettings);
blockModel = modelFactory.createFrom(block);
} catch (NoSuchResourceException e) {
try {
blockModel = modelFactory.createFrom(BlockState.MISSING, context, renderSettings);
blockModel = modelFactory.createFrom(block, BlockState.MISSING);
} catch (NoSuchResourceException e2) {
e.addSuppressed(e2);
blockModel = new BlockStateModel();

View File

@ -25,43 +25,29 @@
package de.bluecolored.bluemap.core.render.hires.blockmodel;
import de.bluecolored.bluemap.core.render.RenderSettings;
import de.bluecolored.bluemap.core.render.context.EmptyBlockContext;
import de.bluecolored.bluemap.core.render.context.ExtendedBlockContext;
import de.bluecolored.bluemap.core.resourcepack.BlockColorCalculator;
import de.bluecolored.bluemap.core.resourcepack.BlockStateResource;
import de.bluecolored.bluemap.core.resourcepack.NoSuchResourceException;
import de.bluecolored.bluemap.core.resourcepack.ResourcePack;
import de.bluecolored.bluemap.core.resourcepack.TransformedBlockModelResource;
import de.bluecolored.bluemap.core.world.Block;
import de.bluecolored.bluemap.core.world.BlockState;
public class BlockStateModelFactory {
private RenderSettings renderSettings;
private ResourcePack resourcePack;
public BlockStateModelFactory(ResourcePack resources) {
this.resourcePack = resources;
public BlockStateModelFactory(ResourcePack resourcePack, RenderSettings renderSettings) {
this.renderSettings = renderSettings;
this.resourcePack = resourcePack;
}
public BlockStateModel createFrom(BlockState blockState) throws NoSuchResourceException {
return createFrom(blockState, EmptyBlockContext.instance(), new RenderSettings() {
@Override
public float getLightShadeMultiplier() {
return 0;
}
@Override
public boolean isExcludeFacesWithoutSunlight() {
return false;
}
@Override
public float getAmbientOcclusionStrenght() {
return 0;
}
});
public BlockStateModel createFrom(Block block) throws NoSuchResourceException {
return createFrom(block, block.getBlock());
}
public BlockStateModel createFrom(BlockState blockState, ExtendedBlockContext context, RenderSettings renderSettings) throws NoSuchResourceException {
public BlockStateModel createFrom(Block block, BlockState blockState) throws NoSuchResourceException {
//shortcut for air
if (
@ -72,28 +58,28 @@ public class BlockStateModelFactory {
return new BlockStateModel();
}
BlockStateModel model = createModel(blockState, context, renderSettings);
BlockStateModel model = createModel(block, blockState);
// if block is waterlogged
if (LiquidModelBuilder.isWaterlogged(blockState)) {
model.merge(createModel(WATERLOGGED_BLOCKSTATE, context, renderSettings));
model.merge(createModel(block, WATERLOGGED_BLOCKSTATE));
}
return model;
}
private BlockStateModel createModel(BlockState blockState, ExtendedBlockContext context, RenderSettings renderSettings) throws NoSuchResourceException {
private BlockStateModel createModel(Block block, BlockState blockState) throws NoSuchResourceException {
BlockStateResource resource = resourcePack.getBlockStateResource(blockState);
BlockStateModel model = new BlockStateModel();
BlockColorCalculator colorCalculator = resourcePack.getBlockColorCalculator();
ResourceModelBuilder modelBuilder = new ResourceModelBuilder(renderSettings, context, colorCalculator);
LiquidModelBuilder liquidBuilder = new LiquidModelBuilder(renderSettings, context, blockState, colorCalculator);
ResourceModelBuilder modelBuilder = new ResourceModelBuilder(block, renderSettings, colorCalculator);
LiquidModelBuilder liquidBuilder = new LiquidModelBuilder(block, blockState, renderSettings, colorCalculator);
for (TransformedBlockModelResource bmr : resource.getModels(blockState, context.getPosition())){
for (TransformedBlockModelResource bmr : resource.getModels(blockState, block.getPosition())){
switch (bmr.getModel().getType()){
case LIQUID:
model.merge(liquidBuilder.build(blockState, bmr.getModel()));
model.merge(liquidBuilder.build(bmr));
break;
default:
model.merge(modelBuilder.build(bmr));

View File

@ -35,10 +35,10 @@ import com.google.common.collect.Sets;
import de.bluecolored.bluemap.core.model.Face;
import de.bluecolored.bluemap.core.model.Model;
import de.bluecolored.bluemap.core.render.RenderSettings;
import de.bluecolored.bluemap.core.render.context.ExtendedBlockContext;
import de.bluecolored.bluemap.core.resourcepack.BlockColorCalculator;
import de.bluecolored.bluemap.core.resourcepack.BlockModelResource;
import de.bluecolored.bluemap.core.resourcepack.Texture;
import de.bluecolored.bluemap.core.resourcepack.TransformedBlockModelResource;
import de.bluecolored.bluemap.core.util.Direction;
import de.bluecolored.bluemap.core.world.Block;
import de.bluecolored.bluemap.core.world.BlockState;
@ -56,25 +56,29 @@ public class LiquidModelBuilder {
);
private BlockState liquidBlockState;
private ExtendedBlockContext context;
private Block block;
private RenderSettings renderSettings;
private BlockColorCalculator colorCalculator;
public LiquidModelBuilder(RenderSettings renderSettings, ExtendedBlockContext context, BlockState liquidBlockState, BlockColorCalculator colorCalculator) {
this.context = context;
public LiquidModelBuilder(Block block, BlockState liquidBlockState, RenderSettings renderSettings, BlockColorCalculator colorCalculator) {
this.block = block;
this.renderSettings = renderSettings;
this.liquidBlockState = liquidBlockState;
this.colorCalculator = colorCalculator;
}
public BlockStateModel build(BlockState blockState, BlockModelResource bmr) {
if (this.renderSettings.isExcludeFacesWithoutSunlight() && context.getRelativeBlock(0, 0, 0).getSunLightLevel() == 0) return new BlockStateModel();
public BlockStateModel build(TransformedBlockModelResource bmr) {
return build(bmr.getModel());
}
public BlockStateModel build(BlockModelResource bmr) {
if (this.renderSettings.isExcludeFacesWithoutSunlight() && block.getSunLightLevel() == 0) return new BlockStateModel();
int level = getLiquidLevel(blockState);
int level = getLiquidLevel(block.getBlock());
float[] heights = new float[]{16f, 16f, 16f, 16f};
float coloralpha = 0.2f;
if (level < 8 && !(level == 0 && isLiquid(context.getRelativeBlock(0, 1, 0)))){
if (level < 8 && !(level == 0 && isLiquid(block.getRelativeBlock(0, 1, 0)))){
heights = new float[]{
getLiquidCornerHeight(-1, 0, -1),
getLiquidCornerHeight(-1, 0, 0),
@ -102,7 +106,7 @@ public class LiquidModelBuilder {
int textureId = texture.getId();
Vector3f tintcolor = Vector3f.ONE;
if (liquidBlockState.getFullId().equals("minecraft:water")) {
tintcolor = colorCalculator.getWaterAverageColor(context);
tintcolor = colorCalculator.getWaterAverageColor(block);
}
createElementFace(model, Direction.DOWN, c[0], c[2], c[3], c[1], tintcolor, textureId);
@ -126,7 +130,7 @@ public class LiquidModelBuilder {
private float getLiquidCornerHeight(int x, int y, int z){
for (int ix = x; ix <= x+1; ix++){
for (int iz = z; iz<= z+1; iz++){
if (isLiquid(context.getRelativeBlock(ix, y+1, iz))){
if (isLiquid(block.getRelativeBlock(ix, y+1, iz))){
return 16f;
}
}
@ -137,7 +141,7 @@ public class LiquidModelBuilder {
for (int ix = x; ix <= x+1; ix++){
for (int iz = z; iz<= z+1; iz++){
Block b = context.getRelativeBlock(ix, y, iz);
Block b = block.getRelativeBlock(ix, y, iz);
if (isLiquid(b)){
if (getLiquidLevel(b.getBlock()) == 0) return 14f;
@ -158,8 +162,8 @@ public class LiquidModelBuilder {
return sumHeight / count;
}
private boolean isLiquidBlockingBlock(Block b){
if (b.getBlock().getId().equals("air")) return false;
private boolean isLiquidBlockingBlock(Block block){
if (block.getBlock().equals(BlockState.AIR)) return false;
return true;
}
@ -188,7 +192,7 @@ public class LiquidModelBuilder {
private void createElementFace(Model model, Direction faceDir, Vector3f c0, Vector3f c1, Vector3f c2, Vector3f c3, Vector3f color, int textureId) {
//face culling
Block bl = context.getRelativeBlock(faceDir);
Block bl = block.getRelativeBlock(faceDir);
if (isLiquid(bl) || (faceDir != Direction.UP && bl.isCullingNeighborFaces())) return;
//UV
@ -212,7 +216,7 @@ public class LiquidModelBuilder {
if (renderSettings.getLightShadeMultiplier() > 0) {
light = 0f;
for (Direction d : Direction.values()){
Block b = context.getRelativeBlock(d.toVector());
Block b = block.getRelativeBlock(d.toVector());
float l = (float) (Math.max(b.getBlockLightLevel(), b.getSunLightLevel()) / 15f) * renderSettings.getLightShadeMultiplier() + (1 - renderSettings.getLightShadeMultiplier());
if (l > light) light = l;
}

View File

@ -36,8 +36,6 @@ import com.flowpowered.math.vector.Vector4f;
import de.bluecolored.bluemap.core.model.Face;
import de.bluecolored.bluemap.core.render.RenderSettings;
import de.bluecolored.bluemap.core.render.context.BlockContext;
import de.bluecolored.bluemap.core.render.context.ExtendedBlockContext;
import de.bluecolored.bluemap.core.resourcepack.BlockColorCalculator;
import de.bluecolored.bluemap.core.resourcepack.BlockModelResource;
import de.bluecolored.bluemap.core.resourcepack.BlockModelResource.Element.Rotation;
@ -56,23 +54,19 @@ public class ResourceModelBuilder {
private static final Vector3f NEG_HALF_3F = HALF_3F.negate();
private static final Vector2f HALF_2F = Vector2f.ONE.mul(0.5);
private ExtendedBlockContext context;
private Block block;
private RenderSettings renderSettings;
private BlockColorCalculator colorCalculator;
private Lazy<Vector3f> tintColor;
public ResourceModelBuilder(RenderSettings renderSettings, ExtendedBlockContext context, BlockColorCalculator colorCalculator) {
this.context = context;
public ResourceModelBuilder(Block block, RenderSettings renderSettings, BlockColorCalculator colorCalculator) {
this.block = block;
this.renderSettings = renderSettings;
this.colorCalculator = colorCalculator;
this.tintColor = new Lazy<>(() -> colorCalculator.getBlockColor(context));
this.tintColor = new Lazy<>(() -> colorCalculator.getBlockColor(block));
}
public BlockStateModel build(TransformedBlockModelResource bmr) {
BlockStateModel model = new BlockStateModel();
colorCalculator.getBlockColor(context);
for (BlockModelResource.Element element : bmr.getModel().getElements()){
model.merge(fromModelElementResource(element, bmr));
}
@ -155,21 +149,20 @@ public class ResourceModelBuilder {
//face culling
if (face.getCullface() != null){
Block b = getRotationRelativeBlock(modelResource, face.getCullface());
Block b = getRotationRelativeBlock(modelResource.getRotation(), face.getCullface());
if (b.isCullingNeighborFaces()) return;
}
//light calculation
Block b = getRotationRelativeBlock(modelResource, faceDir);
BlockContext bContext = context.getRelativeView(getRotationRelativeDirectionVector(modelResource, faceDir.toVector().toFloat()).toInt());
float skyLight = b.getPassedSunLight(bContext);
Block facedBlockNeighbor = getRotationRelativeBlock(modelResource.getRotation(), faceDir);
float skyLight = facedBlockNeighbor.getPassedSunLight();
//filter out faces that are not skylighted
if (skyLight == 0f && renderSettings.isExcludeFacesWithoutSunlight()) return;
float light = 1;
float light = 1f;
if (renderSettings.getLightShadeMultiplier() > 0) {
float blockLight = b.getPassedBlockLight(bContext);
float blockLight = facedBlockNeighbor.getPassedBlockLight();
light = (Math.max(skyLight, blockLight) / 15f) * renderSettings.getLightShadeMultiplier() + (1 - renderSettings.getLightShadeMultiplier());
if (light > 1) light = 1;
if (light < 0) light = 0;
@ -209,10 +202,10 @@ public class ResourceModelBuilder {
//calculate ao
double ao0 = 1d, ao1 = 1d, ao2 = 1d, ao3 = 1d;
if (renderSettings.getAmbientOcclusionStrenght() > 0f && modelResource.getModel().isAmbientOcclusion()){
ao0 = testAo(modelResource, c0, faceDir);
ao1 = testAo(modelResource, c1, faceDir);
ao2 = testAo(modelResource, c2, faceDir);
ao3 = testAo(modelResource, c3, faceDir);
ao0 = testAo(modelResource.getRotation(), c0, faceDir);
ao1 = testAo(modelResource.getRotation(), c1, faceDir);
ao2 = testAo(modelResource.getRotation(), c2, faceDir);
ao3 = testAo(modelResource.getRotation(), c3, faceDir);
}
//tint the face
@ -244,7 +237,7 @@ public class ResourceModelBuilder {
model.addFace(f2);
//if is top face set model-color
Vector3f dir = getRotationRelativeDirectionVector(modelResource, faceDir.toVector().toFloat());
Vector3f dir = getRotationRelativeDirectionVector(modelResource.getRotation(), faceDir.toVector().toFloat());
if (element.getRotation().getAngle() > 0){
Quaternionf rot = Quaternionf.fromAngleDegAxis(
@ -264,26 +257,26 @@ public class ResourceModelBuilder {
}
private Block getRotationRelativeBlock(TransformedBlockModelResource model, Direction direction){
return getRotationRelativeBlock(model, direction.toVector());
private Block getRotationRelativeBlock(Vector2i modelRotation, Direction direction){
return getRotationRelativeBlock(modelRotation, direction.toVector());
}
private Block getRotationRelativeBlock(TransformedBlockModelResource model, Vector3i direction){
Vector3i dir = getRotationRelativeDirectionVector(model, direction.toFloat()).round().toInt();
return context.getRelativeBlock(dir);
private Block getRotationRelativeBlock(Vector2i modelRotation, Vector3i direction){
Vector3i dir = getRotationRelativeDirectionVector(modelRotation, direction.toFloat()).round().toInt();
return block.getRelativeBlock(dir);
}
private Vector3f getRotationRelativeDirectionVector(TransformedBlockModelResource model, Vector3f direction){
private Vector3f getRotationRelativeDirectionVector(Vector2i modelRotation, Vector3f direction){
Quaternionf rot = Quaternionf.fromAxesAnglesDeg(
-model.getRotation().getX(),
-model.getRotation().getY(),
-modelRotation.getX(),
-modelRotation.getY(),
0
);
Vector3f dir = rot.rotate(direction);
return dir;
}
private double testAo(TransformedBlockModelResource model, Vector3f vertex, Direction dir){
private double testAo(Vector2i modelRotation, Vector3f vertex, Direction dir){
int occluding = 0;
int x = 0;
@ -309,22 +302,22 @@ public class ResourceModelBuilder {
Vector3i rel = new Vector3i(x, y, 0);
if (rel.dot(dir.toVector()) > 0){
if (getRotationRelativeBlock(model, rel).isOccludingNeighborFaces()) occluding++;
if (getRotationRelativeBlock(modelRotation, rel).isOccludingNeighborFaces()) occluding++;
}
rel = new Vector3i(x, 0, z);
if (rel.dot(dir.toVector()) > 0){
if (getRotationRelativeBlock(model, rel).isOccludingNeighborFaces()) occluding++;
if (getRotationRelativeBlock(modelRotation, rel).isOccludingNeighborFaces()) occluding++;
}
rel = new Vector3i(0, y, z);
if (rel.dot(dir.toVector()) > 0){
if (getRotationRelativeBlock(model, rel).isOccludingNeighborFaces()) occluding++;
if (getRotationRelativeBlock(modelRotation, rel).isOccludingNeighborFaces()) occluding++;
}
rel = new Vector3i(x, y, z);
if (rel.dot(dir.toVector()) > 0){
if (getRotationRelativeBlock(model, rel).isOccludingNeighborFaces()) occluding++;
if (getRotationRelativeBlock(modelRotation, rel).isOccludingNeighborFaces()) occluding++;
}
if (occluding > 3)

View File

@ -38,7 +38,6 @@ import com.flowpowered.math.vector.Vector2f;
import com.flowpowered.math.vector.Vector2i;
import com.flowpowered.math.vector.Vector3f;
import de.bluecolored.bluemap.core.render.context.BlockContext;
import de.bluecolored.bluemap.core.util.ConfigUtils;
import de.bluecolored.bluemap.core.util.MathUtils;
import de.bluecolored.bluemap.core.world.Biome;
@ -51,7 +50,7 @@ public class BlockColorCalculator {
private BufferedImage foliageMap;
private BufferedImage grassMap;
private Map<String, Function<BlockContext, Vector3f>> blockColorMap;
private Map<String, Function<Block, Vector3f>> blockColorMap;
public BlockColorCalculator(BufferedImage foliageMap, BufferedImage grassMap) {
this.foliageMap = foliageMap;
@ -72,7 +71,7 @@ public class BlockColorCalculator {
String key = entry.getKey().toString();
String value = entry.getValue().getString();
Function<BlockContext, Vector3f> colorFunction;
Function<Block, Vector3f> colorFunction;
switch (value) {
case "@foliage":
colorFunction = this::getFoliageAverageColor;
@ -93,35 +92,34 @@ public class BlockColorCalculator {
}
}
public Vector3f getBlockColor(BlockContext context){
Block block = context.getRelativeBlock(0, 0, 0);
public Vector3f getBlockColor(Block block){
String blockId = block.getBlock().getFullId();
Function<BlockContext, Vector3f> colorFunction = blockColorMap.get(blockId);
Function<Block, Vector3f> colorFunction = blockColorMap.get(blockId);
if (colorFunction == null) colorFunction = blockColorMap.get("default");
if (colorFunction == null) colorFunction = this::getFoliageAverageColor;
return colorFunction.apply(context);
return colorFunction.apply(block);
}
public Vector3f getWaterAverageColor(BlockContext context){
public Vector3f getWaterAverageColor(Block block){
Vector3f color = Vector3f.ZERO;
for (int x = -1; x <= 1; x++){
for (int z = -1; z <= 1; z++){
color = color.add(context.getRelativeBlock(x, 0, z).getBiome().getWaterColor());
color = color.add(block.getRelativeBlock(x, 0, z).getBiome().getWaterColor());
}
}
return color.div(9f);
}
public Vector3f getFoliageAverageColor(BlockContext context){
public Vector3f getFoliageAverageColor(Block block){
Vector3f color = Vector3f.ZERO;
for (int x = -1; x <= 1; x++){
for (int z = -1; z <= 1; z++){
color = color.add(getFoliageColor(context.getRelativeBlock(x, 0, z)));
color = color.add(getFoliageColor(block.getRelativeBlock(x, 0, z)));
}
}
@ -140,12 +138,12 @@ public class BlockColorCalculator {
return mapColor.mul(1f - overlayAlpha).add(overlayColor.mul(overlayAlpha));
}
public Vector3f getGrassAverageColor(BlockContext context){
public Vector3f getGrassAverageColor(Block block){
Vector3f color = Vector3f.ZERO;
for (int x = -1; x <= 1; x++){
for (int z = -1; z <= 1; z++){
color = color.add(getGrassColor(context.getRelativeBlock(x, 0, z)));
color = color.add(getGrassColor(block.getRelativeBlock(x, 0, z)));
}
}

View File

@ -27,7 +27,6 @@ package de.bluecolored.bluemap.core.world;
import com.flowpowered.math.vector.Vector3i;
import com.google.common.base.MoreObjects;
import de.bluecolored.bluemap.core.render.context.BlockContext;
import de.bluecolored.bluemap.core.util.Direction;
public abstract class Block {
@ -64,8 +63,8 @@ public abstract class Block {
* This is internally used for light rendering
* It is basically the sun light that is projected onto adjacent faces
*/
public float getPassedSunLight(BlockContext context) {
if (sunLight < 0) calculateLight(context);
public float getPassedSunLight() {
if (sunLight < 0) calculateLight();
return sunLight;
}
@ -73,24 +72,38 @@ public abstract class Block {
* This is internally used for light rendering
* It is basically the block light that is projected onto adjacent faces
*/
public float getPassedBlockLight(BlockContext context) {
if (blockLight < 0) calculateLight(context);
public float getPassedBlockLight() {
if (blockLight < 0) calculateLight();
return blockLight;
}
private void calculateLight(BlockContext context) {
private void calculateLight() {
sunLight = (float) getSunLightLevel();
blockLight = (float) getBlockLightLevel();
if (blockLight > 0 || sunLight > 0) return;
for (Direction direction : Direction.values()) {
Block neighbor = context.getRelativeBlock(direction);
Block neighbor = getRelativeBlock(direction);
sunLight = (float) Math.max(neighbor.getSunLightLevel(), sunLight);
blockLight = (float) Math.max(neighbor.getBlockLightLevel(), blockLight);
}
}
public Block getRelativeBlock(int x, int y, int z) {
Vector3i pos = getPosition().add(x, y, z);
return getWorld().getBlock(pos);
}
public Block getRelativeBlock(Vector3i direction) {
Vector3i pos = getPosition().add(direction);
return getWorld().getBlock(pos);
}
public Block getRelativeBlock(Direction direction){
return getRelativeBlock(direction.toVector());
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)

View File

@ -218,6 +218,7 @@ public class SpongePlugin {
HiresModelManager hiresModelManager = new HiresModelManager(
config.getWebDataPath().resolve("hires").resolve(id),
resourcePack,
mapConfig,
new Vector2i(mapConfig.getHiresTileSize(), mapConfig.getHiresTileSize()),
getAsyncExecutor()
);
@ -228,7 +229,7 @@ public class SpongePlugin {
new Vector2i(mapConfig.getLowresPointsPerHiresTile(), mapConfig.getLowresPointsPerHiresTile())
);
TileRenderer tileRenderer = new TileRenderer(hiresModelManager, lowresModelManager, mapConfig);
TileRenderer tileRenderer = new TileRenderer(hiresModelManager, lowresModelManager);
MapType mapType = new MapType(id, name, world, tileRenderer);
maps.put(id, mapType);