mirror of
https://github.com/BlueMap-Minecraft/BlueMap.git
synced 2024-11-28 21:48:34 +01:00
Add first iteration of custom block-renderers (#561)
This commit is contained in:
parent
b26b908992
commit
c2fa00db5b
@ -27,7 +27,7 @@
|
|||||||
import com.flowpowered.math.vector.Vector3i;
|
import com.flowpowered.math.vector.Vector3i;
|
||||||
import de.bluecolored.bluemap.core.map.TextureGallery;
|
import de.bluecolored.bluemap.core.map.TextureGallery;
|
||||||
import de.bluecolored.bluemap.core.map.TileMetaConsumer;
|
import de.bluecolored.bluemap.core.map.TileMetaConsumer;
|
||||||
import de.bluecolored.bluemap.core.map.hires.blockmodel.BlockStateModelFactory;
|
import de.bluecolored.bluemap.core.map.hires.blockmodel.BlockStateModelRenderer;
|
||||||
import de.bluecolored.bluemap.core.resources.pack.resourcepack.ResourcePack;
|
import de.bluecolored.bluemap.core.resources.pack.resourcepack.ResourcePack;
|
||||||
import de.bluecolored.bluemap.core.util.math.Color;
|
import de.bluecolored.bluemap.core.util.math.Color;
|
||||||
import de.bluecolored.bluemap.core.world.Chunk;
|
import de.bluecolored.bluemap.core.world.Chunk;
|
||||||
@ -39,31 +39,31 @@ public class HiresModelRenderer {
|
|||||||
private final ResourcePack resourcePack;
|
private final ResourcePack resourcePack;
|
||||||
private final RenderSettings renderSettings;
|
private final RenderSettings renderSettings;
|
||||||
|
|
||||||
private final ThreadLocal<BlockStateModelFactory> threadLocalModelFactory;
|
private final ThreadLocal<BlockStateModelRenderer> threadLocalBlockRenderer;
|
||||||
|
|
||||||
public HiresModelRenderer(ResourcePack resourcePack, TextureGallery textureGallery, RenderSettings renderSettings) {
|
public HiresModelRenderer(ResourcePack resourcePack, TextureGallery textureGallery, RenderSettings renderSettings) {
|
||||||
this.resourcePack = resourcePack;
|
this.resourcePack = resourcePack;
|
||||||
this.renderSettings = renderSettings;
|
this.renderSettings = renderSettings;
|
||||||
|
|
||||||
this.threadLocalModelFactory = ThreadLocal.withInitial(() -> new BlockStateModelFactory(resourcePack, textureGallery, renderSettings));
|
this.threadLocalBlockRenderer = ThreadLocal.withInitial(() -> new BlockStateModelRenderer(resourcePack, textureGallery, renderSettings));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void render(World world, Vector3i modelMin, Vector3i modelMax, TileModel model) {
|
public void render(World world, Vector3i modelMin, Vector3i modelMax, TileModel model) {
|
||||||
render(world, modelMin, modelMax, model, (x, z, c, h, l) -> {});
|
render(world, modelMin, modelMax, model, (x, z, c, h, l) -> {});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void render(World world, Vector3i modelMin, Vector3i modelMax, TileModel model, TileMetaConsumer tileMetaConsumer) {
|
public void render(World world, Vector3i modelMin, Vector3i modelMax, TileModel tileModel, TileMetaConsumer tileMetaConsumer) {
|
||||||
Vector3i min = modelMin.max(renderSettings.getMinPos());
|
Vector3i min = modelMin.max(renderSettings.getMinPos());
|
||||||
Vector3i max = modelMax.min(renderSettings.getMaxPos());
|
Vector3i max = modelMax.min(renderSettings.getMaxPos());
|
||||||
Vector3i modelAnchor = new Vector3i(modelMin.getX(), 0, modelMin.getZ());
|
Vector3i modelAnchor = new Vector3i(modelMin.getX(), 0, modelMin.getZ());
|
||||||
|
|
||||||
BlockStateModelFactory modelFactory = threadLocalModelFactory.get();
|
BlockStateModelRenderer blockRenderer = threadLocalBlockRenderer.get();
|
||||||
|
|
||||||
int maxHeight, minY, maxY;
|
int maxHeight, minY, maxY;
|
||||||
double topBlockLight;
|
double topBlockLight;
|
||||||
Color columnColor = new Color(), blockColor = new Color();
|
Color columnColor = new Color(), blockColor = new Color();
|
||||||
BlockNeighborhood<?> block = new BlockNeighborhood<>(resourcePack, renderSettings, world, 0, 0, 0);
|
BlockNeighborhood<?> block = new BlockNeighborhood<>(resourcePack, renderSettings, world, 0, 0, 0);
|
||||||
BlockModelView blockModel = new BlockModelView(model);
|
TileModelView blockModel = new TileModelView(tileModel);
|
||||||
|
|
||||||
int x, y, z;
|
int x, y, z;
|
||||||
for (x = modelMin.getX(); x <= modelMax.getX(); x++){
|
for (x = modelMin.getX(); x <= modelMax.getX(); x++){
|
||||||
@ -85,7 +85,7 @@ public void render(World world, Vector3i modelMin, Vector3i modelMax, TileModel
|
|||||||
|
|
||||||
blockModel.initialize();
|
blockModel.initialize();
|
||||||
|
|
||||||
modelFactory.render(block, blockModel, blockColor);
|
blockRenderer.render(block, blockModel, blockColor);
|
||||||
|
|
||||||
//update topBlockLight
|
//update topBlockLight
|
||||||
topBlockLight = Math.max(topBlockLight, block.getBlockLightLevel() * (1 - columnColor.a));
|
topBlockLight = Math.max(topBlockLight, block.getBlockLightLevel() * (1 - columnColor.a));
|
||||||
|
@ -27,90 +27,90 @@
|
|||||||
import de.bluecolored.bluemap.core.util.math.MatrixM3f;
|
import de.bluecolored.bluemap.core.util.math.MatrixM3f;
|
||||||
import de.bluecolored.bluemap.core.util.math.MatrixM4f;
|
import de.bluecolored.bluemap.core.util.math.MatrixM4f;
|
||||||
|
|
||||||
public class BlockModelView {
|
public class TileModelView {
|
||||||
|
|
||||||
private TileModel hiresTile;
|
private TileModel tileModel;
|
||||||
private int start, size;
|
private int start, size;
|
||||||
|
|
||||||
public BlockModelView(TileModel hiresTile) {
|
public TileModelView(TileModel tileModel) {
|
||||||
initialize(hiresTile);
|
initialize(tileModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockModelView initialize(TileModel hiresTile, int start) {
|
public TileModelView initialize(TileModel hiresTile, int start) {
|
||||||
this.hiresTile = hiresTile;
|
this.tileModel = hiresTile;
|
||||||
this.start = start;
|
this.start = start;
|
||||||
this.size = hiresTile.size() - start;
|
this.size = hiresTile.size() - start;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockModelView initialize(TileModel hiresTile) {
|
public TileModelView initialize(TileModel hiresTile) {
|
||||||
this.hiresTile = hiresTile;
|
this.tileModel = hiresTile;
|
||||||
this.start = hiresTile.size();
|
this.start = hiresTile.size();
|
||||||
this.size = 0;
|
this.size = 0;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockModelView initialize(int start) {
|
public TileModelView initialize(int start) {
|
||||||
this.start = start;
|
this.start = start;
|
||||||
this.size = hiresTile.size() - start;
|
this.size = tileModel.size() - start;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockModelView initialize() {
|
public TileModelView initialize() {
|
||||||
this.start = hiresTile.size();
|
this.start = tileModel.size();
|
||||||
this.size = 0;
|
this.size = 0;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockModelView reset() {
|
public TileModelView reset() {
|
||||||
hiresTile.reset(this.start);
|
tileModel.reset(this.start);
|
||||||
this.size = 0;
|
this.size = 0;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int add(int count) {
|
public int add(int count) {
|
||||||
int s = hiresTile.add(count);
|
int s = tileModel.add(count);
|
||||||
if (s != start + size) throw new IllegalStateException("Size of HiresTileModel had external changes since view-initialisation!");
|
if (s != start + size) throw new IllegalStateException("Size of HiresTileModel had external changes since view-initialisation!");
|
||||||
this.size += count;
|
this.size += count;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockModelView rotate(float angle, float axisX, float axisY, float axisZ) {
|
public TileModelView rotate(float angle, float axisX, float axisY, float axisZ) {
|
||||||
hiresTile.rotate(start, size, angle, axisX, axisY, axisZ);
|
tileModel.rotate(start, size, angle, axisX, axisY, axisZ);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockModelView rotate(float pitch, float yaw, float roll) {
|
public TileModelView rotate(float pitch, float yaw, float roll) {
|
||||||
hiresTile.rotate(start, size, pitch, yaw, roll);
|
tileModel.rotate(start, size, pitch, yaw, roll);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockModelView scale(float sx, float sy, float sz) {
|
public TileModelView scale(float sx, float sy, float sz) {
|
||||||
hiresTile.scale(start, size, sx, sy, sz);
|
tileModel.scale(start, size, sx, sy, sz);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockModelView translate(float dx, float dy, float dz) {
|
public TileModelView translate(float dx, float dy, float dz) {
|
||||||
hiresTile.translate(start, size, dx, dy, dz);
|
tileModel.translate(start, size, dx, dy, dz);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockModelView transform(MatrixM3f t) {
|
public TileModelView transform(MatrixM3f t) {
|
||||||
hiresTile.transform(start, size, t);
|
tileModel.transform(start, size, t);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockModelView transform(
|
public TileModelView transform(
|
||||||
float m00, float m01, float m02,
|
float m00, float m01, float m02,
|
||||||
float m10, float m11, float m12,
|
float m10, float m11, float m12,
|
||||||
float m20, float m21, float m22
|
float m20, float m21, float m22
|
||||||
) {
|
) {
|
||||||
hiresTile.transform(start, size,
|
tileModel.transform(start, size,
|
||||||
m00, m01, m02,
|
m00, m01, m02,
|
||||||
m10, m11, m12,
|
m10, m11, m12,
|
||||||
m20, m21, m22
|
m20, m21, m22
|
||||||
@ -118,18 +118,18 @@ public BlockModelView transform(
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockModelView transform(MatrixM4f t) {
|
public TileModelView transform(MatrixM4f t) {
|
||||||
hiresTile.transform(start, size, t);
|
tileModel.transform(start, size, t);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockModelView transform(
|
public TileModelView transform(
|
||||||
float m00, float m01, float m02, float m03,
|
float m00, float m01, float m02, float m03,
|
||||||
float m10, float m11, float m12, float m13,
|
float m10, float m11, float m12, float m13,
|
||||||
float m20, float m21, float m22, float m23,
|
float m20, float m21, float m22, float m23,
|
||||||
float m30, float m31, float m32, float m33
|
float m30, float m31, float m32, float m33
|
||||||
) {
|
) {
|
||||||
hiresTile.transform(start, size,
|
tileModel.transform(start, size,
|
||||||
m00, m01, m02, m03,
|
m00, m01, m02, m03,
|
||||||
m10, m11, m12, m13,
|
m10, m11, m12, m13,
|
||||||
m20, m21, m22, m23,
|
m20, m21, m22, m23,
|
||||||
@ -138,8 +138,8 @@ public BlockModelView transform(
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TileModel getHiresTile() {
|
public TileModel getTileModel() {
|
||||||
return hiresTile;
|
return tileModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getStart() {
|
public int getStart() {
|
@ -0,0 +1,27 @@
|
|||||||
|
package de.bluecolored.bluemap.core.map.hires.blockmodel;
|
||||||
|
|
||||||
|
import de.bluecolored.bluemap.core.map.hires.TileModelView;
|
||||||
|
import de.bluecolored.bluemap.core.resources.pack.resourcepack.blockstate.Variant;
|
||||||
|
import de.bluecolored.bluemap.core.util.math.Color;
|
||||||
|
import de.bluecolored.bluemap.core.world.block.BlockNeighborhood;
|
||||||
|
|
||||||
|
public interface BlockRenderer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the given blocks (block-state-)variant into the given blockModel, and sets the given blockColor to the
|
||||||
|
* color that represents the rendered block.
|
||||||
|
* <p>
|
||||||
|
* <b>Implementation Note:</b><br>
|
||||||
|
* This method is guaranteed to be called only on <b>one thread per BlockRenderer instance</b>, so you can use this
|
||||||
|
* for optimizations.<br>
|
||||||
|
* Keep in mind this method will be called once for every block that is being rendered, so be very careful
|
||||||
|
* about performance and instance-creations.
|
||||||
|
* </p>
|
||||||
|
* @param block The block information that should be rendered.
|
||||||
|
* @param variant The block-state variant that should be rendered.
|
||||||
|
* @param blockModel The model(-view) where the block should be rendered to.
|
||||||
|
* @param blockColor The color that should be set to the color that represents the rendered block.
|
||||||
|
*/
|
||||||
|
void render(BlockNeighborhood<?> block, Variant variant, TileModelView blockModel, Color blockColor);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package de.bluecolored.bluemap.core.map.hires.blockmodel;
|
||||||
|
|
||||||
|
import de.bluecolored.bluemap.core.map.TextureGallery;
|
||||||
|
import de.bluecolored.bluemap.core.map.hires.RenderSettings;
|
||||||
|
import de.bluecolored.bluemap.core.resources.pack.resourcepack.ResourcePack;
|
||||||
|
|
||||||
|
public interface BlockRendererFactory {
|
||||||
|
|
||||||
|
BlockRenderer create(ResourcePack resourcePack, TextureGallery textureGallery, RenderSettings renderSettings);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
package de.bluecolored.bluemap.core.map.hires.blockmodel;
|
||||||
|
|
||||||
|
import de.bluecolored.bluemap.core.map.TextureGallery;
|
||||||
|
import de.bluecolored.bluemap.core.map.hires.RenderSettings;
|
||||||
|
import de.bluecolored.bluemap.core.resources.pack.resourcepack.ResourcePack;
|
||||||
|
import de.bluecolored.bluemap.core.util.Key;
|
||||||
|
import de.bluecolored.bluemap.core.util.Keyed;
|
||||||
|
import de.bluecolored.bluemap.core.util.Registry;
|
||||||
|
import de.bluecolored.bluemap.core.world.BlockState;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
public interface BlockRendererType extends Keyed, BlockRendererFactory {
|
||||||
|
|
||||||
|
BlockRendererType DEFAULT = new Impl(Key.bluemap("default"), ResourceModelRenderer::new);
|
||||||
|
BlockRendererType LIQUID = new Impl(Key.bluemap("liquid"), LiquidModelRenderer::new);
|
||||||
|
BlockRendererType MISSING = new Impl(Key.bluemap("missing"), MissingModelRenderer::new);
|
||||||
|
|
||||||
|
Registry<BlockRendererType> REGISTRY = new Registry<>(
|
||||||
|
DEFAULT,
|
||||||
|
LIQUID,
|
||||||
|
MISSING
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the loaded resourcepack does not have any resources for this blockState, this method will be called.
|
||||||
|
* If this method returns true, this renderer will be used to render the block instead of rendering the default
|
||||||
|
* black-purple "missing block" model.
|
||||||
|
* When rendering, the provided "variant" will always be bluemaps default "missing-block" resource.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* This can (and should only then) be used to provide a way of rendering blocks that are completely dynamically
|
||||||
|
* created by a mod, and there is no way to provide static block-state resources that point at the correct renderer.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param blockState The {@link BlockState} that was not found in the loaded resources.
|
||||||
|
* @return true if this renderer-type can render the provided {@link BlockState} despite missing resources.
|
||||||
|
*/
|
||||||
|
default boolean isFallbackFor(BlockState blockState) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
class Impl implements BlockRendererType {
|
||||||
|
|
||||||
|
@Getter private final Key key;
|
||||||
|
private final BlockRendererFactory rendererFactory;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockRenderer create(ResourcePack resourcePack, TextureGallery textureGallery, RenderSettings renderSettings) {
|
||||||
|
return rendererFactory.create(resourcePack, textureGallery, renderSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -24,8 +24,10 @@
|
|||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.map.hires.blockmodel;
|
package de.bluecolored.bluemap.core.map.hires.blockmodel;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||||
import de.bluecolored.bluemap.core.map.TextureGallery;
|
import de.bluecolored.bluemap.core.map.TextureGallery;
|
||||||
import de.bluecolored.bluemap.core.map.hires.BlockModelView;
|
import de.bluecolored.bluemap.core.map.hires.TileModelView;
|
||||||
import de.bluecolored.bluemap.core.map.hires.RenderSettings;
|
import de.bluecolored.bluemap.core.map.hires.RenderSettings;
|
||||||
import de.bluecolored.bluemap.core.resources.pack.resourcepack.ResourcePack;
|
import de.bluecolored.bluemap.core.resources.pack.resourcepack.ResourcePack;
|
||||||
import de.bluecolored.bluemap.core.resources.pack.resourcepack.blockmodel.BlockModel;
|
import de.bluecolored.bluemap.core.resources.pack.resourcepack.blockmodel.BlockModel;
|
||||||
@ -37,27 +39,25 @@
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class BlockStateModelFactory {
|
public class BlockStateModelRenderer {
|
||||||
|
|
||||||
private final ResourcePack resourcePack;
|
private final ResourcePack resourcePack;
|
||||||
private final ResourceModelBuilder resourceModelBuilder;
|
private final LoadingCache<BlockRendererType, BlockRenderer> blockRenderers;
|
||||||
private final LiquidModelBuilder liquidModelBuilder;
|
|
||||||
|
|
||||||
private final List<Variant> variants = new ArrayList<>();
|
private final List<Variant> variants = new ArrayList<>();
|
||||||
|
|
||||||
public BlockStateModelFactory(ResourcePack resourcePack, TextureGallery textureGallery, RenderSettings renderSettings) {
|
public BlockStateModelRenderer(ResourcePack resourcePack, TextureGallery textureGallery, RenderSettings renderSettings) {
|
||||||
this.resourcePack = resourcePack;
|
this.resourcePack = resourcePack;
|
||||||
|
this.blockRenderers = Caffeine.newBuilder()
|
||||||
this.resourceModelBuilder = new ResourceModelBuilder(resourcePack, textureGallery, renderSettings);
|
.build(type -> type.create(resourcePack, textureGallery, renderSettings));
|
||||||
this.liquidModelBuilder = new LiquidModelBuilder(resourcePack, textureGallery, renderSettings);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void render(BlockNeighborhood<?> block, BlockModelView blockModel, Color blockColor) {
|
public void render(BlockNeighborhood<?> block, TileModelView blockModel, Color blockColor) {
|
||||||
render(block, block.getBlockState(), blockModel, blockColor);
|
render(block, block.getBlockState(), blockModel, blockColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Color waterloggedColor = new Color();
|
private final Color waterloggedColor = new Color();
|
||||||
public void render(BlockNeighborhood<?> block, BlockState blockState, BlockModelView blockModel, Color blockColor) {
|
public void render(BlockNeighborhood<?> block, BlockState blockState, TileModelView blockModel, Color blockColor) {
|
||||||
blockColor.set(0, 0, 0, 0, true);
|
blockColor.set(0, 0, 0, 0, true);
|
||||||
|
|
||||||
//shortcut for air
|
//shortcut for air
|
||||||
@ -79,7 +79,7 @@ public void render(BlockNeighborhood<?> block, BlockState blockState, BlockModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final Color variantColor = new Color();
|
private final Color variantColor = new Color();
|
||||||
private void renderModel(BlockNeighborhood<?> block, BlockState blockState, BlockModelView blockModel, Color blockColor) {
|
private void renderModel(BlockNeighborhood<?> block, BlockState blockState, TileModelView blockModel, Color blockColor) {
|
||||||
int modelStart = blockModel.getStart();
|
int modelStart = blockModel.getStart();
|
||||||
|
|
||||||
var stateResource = resourcePack.getBlockState(blockState);
|
var stateResource = resourcePack.getBlockState(blockState);
|
||||||
@ -98,11 +98,8 @@ private void renderModel(BlockNeighborhood<?> block, BlockState blockState, Bloc
|
|||||||
|
|
||||||
variantColor.set(0f, 0f, 0f, 0f, true);
|
variantColor.set(0f, 0f, 0f, 0f, true);
|
||||||
|
|
||||||
if (modelResource.isLiquid()) {
|
blockRenderers.get(modelResource.getRenderer())
|
||||||
liquidModelBuilder.build(block, blockState, variant, blockModel.initialize(), variantColor);
|
.render(block, variant, blockModel.initialize(), blockColor);
|
||||||
} else {
|
|
||||||
resourceModelBuilder.build(block, variant, blockModel.initialize(), variantColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (variantColor.a > blockColorOpacity)
|
if (variantColor.a > blockColorOpacity)
|
||||||
blockColorOpacity = variantColor.a;
|
blockColorOpacity = variantColor.a;
|
@ -27,7 +27,7 @@
|
|||||||
import com.flowpowered.math.TrigMath;
|
import com.flowpowered.math.TrigMath;
|
||||||
import com.flowpowered.math.vector.Vector3i;
|
import com.flowpowered.math.vector.Vector3i;
|
||||||
import de.bluecolored.bluemap.core.map.TextureGallery;
|
import de.bluecolored.bluemap.core.map.TextureGallery;
|
||||||
import de.bluecolored.bluemap.core.map.hires.BlockModelView;
|
import de.bluecolored.bluemap.core.map.hires.TileModelView;
|
||||||
import de.bluecolored.bluemap.core.map.hires.TileModel;
|
import de.bluecolored.bluemap.core.map.hires.TileModel;
|
||||||
import de.bluecolored.bluemap.core.map.hires.RenderSettings;
|
import de.bluecolored.bluemap.core.map.hires.RenderSettings;
|
||||||
import de.bluecolored.bluemap.core.resources.BlockColorCalculatorFactory;
|
import de.bluecolored.bluemap.core.resources.BlockColorCalculatorFactory;
|
||||||
@ -50,7 +50,7 @@
|
|||||||
* A model builder for all liquid blocks
|
* A model builder for all liquid blocks
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("DuplicatedCode")
|
@SuppressWarnings("DuplicatedCode")
|
||||||
public class LiquidModelBuilder {
|
public class LiquidModelRenderer implements BlockRenderer {
|
||||||
private static final float BLOCK_SCALE = 1f / 16f;
|
private static final float BLOCK_SCALE = 1f / 16f;
|
||||||
private static final MatrixM3f FLOWING_UV_SCALE = new MatrixM3f()
|
private static final MatrixM3f FLOWING_UV_SCALE = new MatrixM3f()
|
||||||
.identity()
|
.identity()
|
||||||
@ -68,11 +68,12 @@ public class LiquidModelBuilder {
|
|||||||
|
|
||||||
private BlockNeighborhood<?> block;
|
private BlockNeighborhood<?> block;
|
||||||
private BlockState blockState;
|
private BlockState blockState;
|
||||||
|
private boolean isWaterlogged, isWaterLike;
|
||||||
private BlockModel modelResource;
|
private BlockModel modelResource;
|
||||||
private BlockModelView blockModel;
|
private TileModelView blockModel;
|
||||||
private Color blockColor;
|
private Color blockColor;
|
||||||
|
|
||||||
public LiquidModelBuilder(ResourcePack resourcePack, TextureGallery textureGallery, RenderSettings renderSettings) {
|
public LiquidModelRenderer(ResourcePack resourcePack, TextureGallery textureGallery, RenderSettings renderSettings) {
|
||||||
this.resourcePack = resourcePack;
|
this.resourcePack = resourcePack;
|
||||||
this.textureGallery = textureGallery;
|
this.textureGallery = textureGallery;
|
||||||
this.renderSettings = renderSettings;
|
this.renderSettings = renderSettings;
|
||||||
@ -92,9 +93,11 @@ public LiquidModelBuilder(ResourcePack resourcePack, TextureGallery textureGalle
|
|||||||
for (int i = 0; i < uvs.length; i++) uvs[i] = new VectorM2f(0, 0);
|
for (int i = 0; i < uvs.length; i++) uvs[i] = new VectorM2f(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void build(BlockNeighborhood<?> block, BlockState blockState, Variant variant, BlockModelView blockModel, Color color) {
|
public void render(BlockNeighborhood<?> block, Variant variant, TileModelView blockModel, Color color) {
|
||||||
this.block = block;
|
this.block = block;
|
||||||
this.blockState = blockState;
|
this.blockState = block.getBlockState();
|
||||||
|
this.isWaterlogged = blockState.isWaterlogged() || block.getProperties().isAlwaysWaterlogged();
|
||||||
|
this.isWaterLike = blockState.isWater() || isWaterlogged;
|
||||||
this.modelResource = variant.getModel().getResource();
|
this.modelResource = variant.getModel().getResource();
|
||||||
this.blockModel = blockModel;
|
this.blockModel = blockModel;
|
||||||
this.blockColor = color;
|
this.blockColor = color;
|
||||||
@ -137,9 +140,7 @@ private void build() {
|
|||||||
int flowTextureId = textureGallery.get(flowTexturePath);
|
int flowTextureId = textureGallery.get(flowTexturePath);
|
||||||
|
|
||||||
tintcolor.set(1f, 1f, 1f, 1f, true);
|
tintcolor.set(1f, 1f, 1f, 1f, true);
|
||||||
if (blockState.isWater()) {
|
if (isWaterLike) blockColorCalculator.getBlendedWaterColor(block, tintcolor);
|
||||||
blockColorCalculator.getBlendedWaterColor(block, tintcolor);
|
|
||||||
}
|
|
||||||
|
|
||||||
int modelStart = blockModel.getStart();
|
int modelStart = blockModel.getStart();
|
||||||
|
|
||||||
@ -223,8 +224,15 @@ private boolean isLiquidBlockingBlock(BlockState blockState){
|
|||||||
|
|
||||||
@SuppressWarnings("StringEquality")
|
@SuppressWarnings("StringEquality")
|
||||||
private boolean isSameLiquid(ExtendedBlock<?> block){
|
private boolean isSameLiquid(ExtendedBlock<?> block){
|
||||||
if (block.getBlockState().getFormatted() == this.blockState.getFormatted()) return true;
|
BlockState blockState = block.getBlockState();
|
||||||
return this.blockState.isWater() && (block.getBlockState().isWaterlogged() || block.getProperties().isAlwaysWaterlogged());
|
|
||||||
|
if (this.isWaterlogged)
|
||||||
|
return blockState.isWater() || blockState.isWaterlogged() || block.getProperties().isAlwaysWaterlogged();
|
||||||
|
|
||||||
|
if (blockState.getFormatted() == this.blockState.getFormatted())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return this.isWaterLike && (blockState.isWaterlogged() || block.getProperties().isAlwaysWaterlogged());
|
||||||
}
|
}
|
||||||
|
|
||||||
private float getLiquidBaseHeight(BlockState block){
|
private float getLiquidBaseHeight(BlockState block){
|
||||||
@ -249,7 +257,7 @@ private boolean createElementFace(Direction faceDir, VectorM3f c0, VectorM3f c1,
|
|||||||
blockModel.initialize();
|
blockModel.initialize();
|
||||||
blockModel.add(2);
|
blockModel.add(2);
|
||||||
|
|
||||||
TileModel tileModel = blockModel.getHiresTile();
|
TileModel tileModel = blockModel.getTileModel();
|
||||||
int face1 = blockModel.getStart();
|
int face1 = blockModel.getStart();
|
||||||
int face2 = face1 + 1;
|
int face2 = face1 + 1;
|
||||||
|
|
@ -0,0 +1,37 @@
|
|||||||
|
package de.bluecolored.bluemap.core.map.hires.blockmodel;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||||
|
import de.bluecolored.bluemap.core.map.TextureGallery;
|
||||||
|
import de.bluecolored.bluemap.core.map.hires.RenderSettings;
|
||||||
|
import de.bluecolored.bluemap.core.map.hires.TileModelView;
|
||||||
|
import de.bluecolored.bluemap.core.resources.pack.resourcepack.ResourcePack;
|
||||||
|
import de.bluecolored.bluemap.core.resources.pack.resourcepack.blockstate.Variant;
|
||||||
|
import de.bluecolored.bluemap.core.util.math.Color;
|
||||||
|
import de.bluecolored.bluemap.core.world.BlockState;
|
||||||
|
import de.bluecolored.bluemap.core.world.block.BlockNeighborhood;
|
||||||
|
|
||||||
|
public class MissingModelRenderer implements BlockRenderer {
|
||||||
|
|
||||||
|
private static final LoadingCache<BlockState, BlockRendererType> BLOCK_RENDERER_TYPES = Caffeine.newBuilder()
|
||||||
|
.maximumSize(1000)
|
||||||
|
.build(blockState -> {
|
||||||
|
for (BlockRendererType type : BlockRendererType.REGISTRY.values())
|
||||||
|
if (type.isFallbackFor(blockState)) return type;
|
||||||
|
return BlockRendererType.DEFAULT;
|
||||||
|
});
|
||||||
|
|
||||||
|
private final LoadingCache<BlockRendererType, BlockRenderer> blockRenderers;
|
||||||
|
|
||||||
|
public MissingModelRenderer(ResourcePack resourcePack, TextureGallery textureGallery, RenderSettings renderSettings) {
|
||||||
|
this.blockRenderers = Caffeine.newBuilder()
|
||||||
|
.build(type -> type.create(resourcePack, textureGallery, renderSettings));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(BlockNeighborhood<?> block, Variant variant, TileModelView blockModel, Color blockColor) {
|
||||||
|
blockRenderers.get(BLOCK_RENDERER_TYPES.get(block.getBlockState()))
|
||||||
|
.render(block, variant, blockModel, blockColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -29,7 +29,7 @@
|
|||||||
import com.flowpowered.math.vector.Vector3i;
|
import com.flowpowered.math.vector.Vector3i;
|
||||||
import com.flowpowered.math.vector.Vector4f;
|
import com.flowpowered.math.vector.Vector4f;
|
||||||
import de.bluecolored.bluemap.core.map.TextureGallery;
|
import de.bluecolored.bluemap.core.map.TextureGallery;
|
||||||
import de.bluecolored.bluemap.core.map.hires.BlockModelView;
|
import de.bluecolored.bluemap.core.map.hires.TileModelView;
|
||||||
import de.bluecolored.bluemap.core.map.hires.TileModel;
|
import de.bluecolored.bluemap.core.map.hires.TileModel;
|
||||||
import de.bluecolored.bluemap.core.map.hires.RenderSettings;
|
import de.bluecolored.bluemap.core.map.hires.RenderSettings;
|
||||||
import de.bluecolored.bluemap.core.resources.BlockColorCalculatorFactory;
|
import de.bluecolored.bluemap.core.resources.BlockColorCalculatorFactory;
|
||||||
@ -54,7 +54,7 @@
|
|||||||
* This model builder creates a BlockStateModel using the information from parsed resource-pack json files.
|
* This model builder creates a BlockStateModel using the information from parsed resource-pack json files.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("DuplicatedCode")
|
@SuppressWarnings("DuplicatedCode")
|
||||||
public class ResourceModelBuilder {
|
public class ResourceModelRenderer implements BlockRenderer {
|
||||||
private static final float BLOCK_SCALE = 1f / 16f;
|
private static final float BLOCK_SCALE = 1f / 16f;
|
||||||
|
|
||||||
private final ResourcePack resourcePack;
|
private final ResourcePack resourcePack;
|
||||||
@ -71,11 +71,11 @@ public class ResourceModelBuilder {
|
|||||||
private BlockNeighborhood<?> block;
|
private BlockNeighborhood<?> block;
|
||||||
private Variant variant;
|
private Variant variant;
|
||||||
private BlockModel modelResource;
|
private BlockModel modelResource;
|
||||||
private BlockModelView blockModel;
|
private TileModelView blockModel;
|
||||||
private Color blockColor;
|
private Color blockColor;
|
||||||
private float blockColorOpacity;
|
private float blockColorOpacity;
|
||||||
|
|
||||||
public ResourceModelBuilder(ResourcePack resourcePack, TextureGallery textureGallery, RenderSettings renderSettings) {
|
public ResourceModelRenderer(ResourcePack resourcePack, TextureGallery textureGallery, RenderSettings renderSettings) {
|
||||||
this.resourcePack = resourcePack;
|
this.resourcePack = resourcePack;
|
||||||
this.textureGallery = textureGallery;
|
this.textureGallery = textureGallery;
|
||||||
this.renderSettings = renderSettings;
|
this.renderSettings = renderSettings;
|
||||||
@ -86,7 +86,7 @@ public ResourceModelBuilder(ResourcePack resourcePack, TextureGallery textureGal
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final MatrixM4f modelTransform = new MatrixM4f();
|
private final MatrixM4f modelTransform = new MatrixM4f();
|
||||||
public void build(BlockNeighborhood<?> block, Variant variant, BlockModelView blockModel, Color color) {
|
public void render(BlockNeighborhood<?> block, Variant variant, TileModelView blockModel, Color color) {
|
||||||
this.block = block;
|
this.block = block;
|
||||||
this.blockModel = blockModel;
|
this.blockModel = blockModel;
|
||||||
this.blockColor = color;
|
this.blockColor = color;
|
||||||
@ -132,7 +132,7 @@ public void build(BlockNeighborhood<?> block, Variant variant, BlockModelView bl
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final MatrixM4f modelElementTransform = new MatrixM4f();
|
private final MatrixM4f modelElementTransform = new MatrixM4f();
|
||||||
private void buildModelElementResource(Element element, BlockModelView blockModel) {
|
private void buildModelElementResource(Element element, TileModelView blockModel) {
|
||||||
|
|
||||||
//create faces
|
//create faces
|
||||||
Vector3f from = element.getFrom();
|
Vector3f from = element.getFrom();
|
||||||
@ -215,7 +215,7 @@ private void createElementFace(Element element, Direction faceDir, VectorM3f c0,
|
|||||||
blockModel.initialize();
|
blockModel.initialize();
|
||||||
blockModel.add(2);
|
blockModel.add(2);
|
||||||
|
|
||||||
TileModel tileModel = blockModel.getHiresTile();
|
TileModel tileModel = blockModel.getTileModel();
|
||||||
int face1 = blockModel.getStart();
|
int face1 = blockModel.getStart();
|
||||||
int face2 = face1 + 1;
|
int face2 = face1 + 1;
|
||||||
|
|
@ -29,6 +29,7 @@
|
|||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
import de.bluecolored.bluemap.core.map.hires.blockmodel.BlockRendererType;
|
||||||
import de.bluecolored.bluemap.core.resources.pack.resourcepack.blockmodel.Face;
|
import de.bluecolored.bluemap.core.resources.pack.resourcepack.blockmodel.Face;
|
||||||
import de.bluecolored.bluemap.core.util.Direction;
|
import de.bluecolored.bluemap.core.util.Direction;
|
||||||
import de.bluecolored.bluemap.core.util.Key;
|
import de.bluecolored.bluemap.core.util.Key;
|
||||||
@ -64,6 +65,11 @@ public static GsonBuilder addAdapter(GsonBuilder builder) {
|
|||||||
GrassColorModifier.REGISTRY,
|
GrassColorModifier.REGISTRY,
|
||||||
Key.MINECRAFT_NAMESPACE,
|
Key.MINECRAFT_NAMESPACE,
|
||||||
GrassColorModifier.NONE
|
GrassColorModifier.NONE
|
||||||
|
))
|
||||||
|
.registerTypeAdapter(BlockRendererType.class, new RegistryAdapter<>(
|
||||||
|
BlockRendererType.REGISTRY,
|
||||||
|
Key.BLUEMAP_NAMESPACE,
|
||||||
|
BlockRendererType.DEFAULT
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,28 +24,35 @@
|
|||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.resources.pack.resourcepack.blockmodel;
|
package de.bluecolored.bluemap.core.resources.pack.resourcepack.blockmodel;
|
||||||
|
|
||||||
|
import de.bluecolored.bluemap.core.map.hires.blockmodel.BlockRendererType;
|
||||||
import de.bluecolored.bluemap.core.resources.ResourcePath;
|
import de.bluecolored.bluemap.core.resources.ResourcePath;
|
||||||
import de.bluecolored.bluemap.core.resources.pack.resourcepack.ResourcePack;
|
import de.bluecolored.bluemap.core.resources.pack.resourcepack.ResourcePack;
|
||||||
import de.bluecolored.bluemap.core.resources.pack.resourcepack.texture.Texture;
|
import de.bluecolored.bluemap.core.resources.pack.resourcepack.texture.Texture;
|
||||||
import de.bluecolored.bluemap.core.util.Direction;
|
import de.bluecolored.bluemap.core.util.Direction;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@SuppressWarnings({"FieldMayBeFinal", "FieldCanBeLocal"})
|
@SuppressWarnings({"FieldMayBeFinal", "FieldCanBeLocal"})
|
||||||
public class BlockModel {
|
public class BlockModel {
|
||||||
|
|
||||||
|
private BlockRendererType renderer = BlockRendererType.DEFAULT;
|
||||||
|
|
||||||
private ResourcePath<BlockModel> parent;
|
private ResourcePath<BlockModel> parent;
|
||||||
private Map<String, TextureVariable> textures = new HashMap<>();
|
private Map<String, TextureVariable> textures = new HashMap<>();
|
||||||
private Element[] elements;
|
private Element[] elements;
|
||||||
private boolean ambientocclusion = true;
|
private boolean ambientocclusion = true;
|
||||||
|
|
||||||
private transient boolean liquid = false;
|
|
||||||
private transient boolean culling = false;
|
private transient boolean culling = false;
|
||||||
private transient boolean occluding = false;
|
private transient boolean occluding = false;
|
||||||
|
|
||||||
private BlockModel(){}
|
private BlockModel(){}
|
||||||
|
|
||||||
|
public BlockRendererType getRenderer() {
|
||||||
|
return renderer;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public ResourcePath<BlockModel> getParent() {
|
public ResourcePath<BlockModel> getParent() {
|
||||||
return parent;
|
return parent;
|
||||||
@ -64,10 +71,6 @@ public boolean isAmbientocclusion() {
|
|||||||
return ambientocclusion;
|
return ambientocclusion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLiquid() {
|
|
||||||
return liquid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCulling() {
|
public boolean isCulling() {
|
||||||
return culling;
|
return culling;
|
||||||
}
|
}
|
||||||
@ -95,11 +98,6 @@ public synchronized void applyParent(ResourcePack resourcePack) {
|
|||||||
ResourcePath<BlockModel> parentPath = this.parent;
|
ResourcePath<BlockModel> parentPath = this.parent;
|
||||||
this.parent = null;
|
this.parent = null;
|
||||||
|
|
||||||
if (parentPath.getFormatted().equals("bluemap:builtin/liquid")) {
|
|
||||||
this.liquid = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockModel parent = parentPath.getResource(resourcePack::getBlockModel);
|
BlockModel parent = parentPath.getResource(resourcePack::getBlockModel);
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
parent.applyParent(resourcePack);
|
parent.applyParent(resourcePack);
|
||||||
|
@ -40,6 +40,9 @@ public class Block<T extends Block<T>> {
|
|||||||
private final LightData lightData = new LightData(-1, -1);
|
private final LightData lightData = new LightData(-1, -1);
|
||||||
private @Nullable Biome biome;
|
private @Nullable Biome biome;
|
||||||
|
|
||||||
|
private boolean isBlockEntitySet;
|
||||||
|
private @Nullable BlockEntity blockEntity;
|
||||||
|
|
||||||
public Block(World world, int x, int y, int z) {
|
public Block(World world, int x, int y, int z) {
|
||||||
set(world, x, y, z);
|
set(world, x, y, z);
|
||||||
}
|
}
|
||||||
@ -81,6 +84,8 @@ protected void reset() {
|
|||||||
this.blockState = null;
|
this.blockState = null;
|
||||||
this.lightData.set(-1, -1);
|
this.lightData.set(-1, -1);
|
||||||
this.biome = null;
|
this.biome = null;
|
||||||
|
this.isBlockEntitySet = false;
|
||||||
|
this.blockEntity = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public T add(int dx, int dy, int dz) {
|
public T add(int dx, int dy, int dz) {
|
||||||
@ -148,7 +153,11 @@ public int getBlockLightLevel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public @Nullable BlockEntity getBlockEntity() {
|
public @Nullable BlockEntity getBlockEntity() {
|
||||||
return getChunk().getBlockEntity(x, y, z);
|
if (!isBlockEntitySet) {
|
||||||
|
blockEntity = getChunk().getBlockEntity(x, y, z);
|
||||||
|
isBlockEntitySet = true;
|
||||||
|
}
|
||||||
|
return blockEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"renderer": "bluemap:missing",
|
||||||
"parent": "block/cube_all",
|
"parent": "block/cube_all",
|
||||||
"textures": {
|
"textures": {
|
||||||
"all": "bluemap:block/missing"
|
"all": "bluemap:block/missing"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"parent": "bluemap:builtin/liquid",
|
"renderer": "bluemap:liquid",
|
||||||
"textures": {
|
"textures": {
|
||||||
"particle": "block/lava_still",
|
"particle": "block/lava_still",
|
||||||
"still": "block/lava_still",
|
"still": "block/lava_still",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"parent": "bluemap:builtin/liquid",
|
"renderer": "bluemap:liquid",
|
||||||
"textures": {
|
"textures": {
|
||||||
"particle": "block/water_still",
|
"particle": "block/water_still",
|
||||||
"still": "block/water_still",
|
"still": "block/water_still",
|
||||||
|
Loading…
Reference in New Issue
Block a user