Skip to content

Commit c2fa00d

Browse files
committed
Add first iteration of custom block-renderers (#561)
1 parent b26b908 commit c2fa00d

File tree

15 files changed

+239
-89
lines changed

15 files changed

+239
-89
lines changed

core/src/main/java/de/bluecolored/bluemap/core/map/hires/HiresModelRenderer.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
import com.flowpowered.math.vector.Vector3i;
2828
import de.bluecolored.bluemap.core.map.TextureGallery;
2929
import de.bluecolored.bluemap.core.map.TileMetaConsumer;
30-
import de.bluecolored.bluemap.core.map.hires.blockmodel.BlockStateModelFactory;
30+
import de.bluecolored.bluemap.core.map.hires.blockmodel.BlockStateModelRenderer;
3131
import de.bluecolored.bluemap.core.resources.pack.resourcepack.ResourcePack;
3232
import de.bluecolored.bluemap.core.util.math.Color;
3333
import de.bluecolored.bluemap.core.world.Chunk;
@@ -39,31 +39,31 @@ public class HiresModelRenderer {
3939
private final ResourcePack resourcePack;
4040
private final RenderSettings renderSettings;
4141

42-
private final ThreadLocal<BlockStateModelFactory> threadLocalModelFactory;
42+
private final ThreadLocal<BlockStateModelRenderer> threadLocalBlockRenderer;
4343

4444
public HiresModelRenderer(ResourcePack resourcePack, TextureGallery textureGallery, RenderSettings renderSettings) {
4545
this.resourcePack = resourcePack;
4646
this.renderSettings = renderSettings;
4747

48-
this.threadLocalModelFactory = ThreadLocal.withInitial(() -> new BlockStateModelFactory(resourcePack, textureGallery, renderSettings));
48+
this.threadLocalBlockRenderer = ThreadLocal.withInitial(() -> new BlockStateModelRenderer(resourcePack, textureGallery, renderSettings));
4949
}
5050

5151
public void render(World world, Vector3i modelMin, Vector3i modelMax, TileModel model) {
5252
render(world, modelMin, modelMax, model, (x, z, c, h, l) -> {});
5353
}
5454

55-
public void render(World world, Vector3i modelMin, Vector3i modelMax, TileModel model, TileMetaConsumer tileMetaConsumer) {
55+
public void render(World world, Vector3i modelMin, Vector3i modelMax, TileModel tileModel, TileMetaConsumer tileMetaConsumer) {
5656
Vector3i min = modelMin.max(renderSettings.getMinPos());
5757
Vector3i max = modelMax.min(renderSettings.getMaxPos());
5858
Vector3i modelAnchor = new Vector3i(modelMin.getX(), 0, modelMin.getZ());
5959

60-
BlockStateModelFactory modelFactory = threadLocalModelFactory.get();
60+
BlockStateModelRenderer blockRenderer = threadLocalBlockRenderer.get();
6161

6262
int maxHeight, minY, maxY;
6363
double topBlockLight;
6464
Color columnColor = new Color(), blockColor = new Color();
6565
BlockNeighborhood<?> block = new BlockNeighborhood<>(resourcePack, renderSettings, world, 0, 0, 0);
66-
BlockModelView blockModel = new BlockModelView(model);
66+
TileModelView blockModel = new TileModelView(tileModel);
6767

6868
int x, y, z;
6969
for (x = modelMin.getX(); x <= modelMax.getX(); x++){
@@ -85,7 +85,7 @@ public void render(World world, Vector3i modelMin, Vector3i modelMax, TileModel
8585

8686
blockModel.initialize();
8787

88-
modelFactory.render(block, blockModel, blockColor);
88+
blockRenderer.render(block, blockModel, blockColor);
8989

9090
//update topBlockLight
9191
topBlockLight = Math.max(topBlockLight, block.getBlockLightLevel() * (1 - columnColor.a));

core/src/main/java/de/bluecolored/bluemap/core/map/hires/BlockModelView.java renamed to core/src/main/java/de/bluecolored/bluemap/core/map/hires/TileModelView.java

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -27,109 +27,109 @@
2727
import de.bluecolored.bluemap.core.util.math.MatrixM3f;
2828
import de.bluecolored.bluemap.core.util.math.MatrixM4f;
2929

30-
public class BlockModelView {
30+
public class TileModelView {
3131

32-
private TileModel hiresTile;
32+
private TileModel tileModel;
3333
private int start, size;
3434

35-
public BlockModelView(TileModel hiresTile) {
36-
initialize(hiresTile);
35+
public TileModelView(TileModel tileModel) {
36+
initialize(tileModel);
3737
}
3838

39-
public BlockModelView initialize(TileModel hiresTile, int start) {
40-
this.hiresTile = hiresTile;
39+
public TileModelView initialize(TileModel hiresTile, int start) {
40+
this.tileModel = hiresTile;
4141
this.start = start;
4242
this.size = hiresTile.size() - start;
4343

4444
return this;
4545
}
4646

47-
public BlockModelView initialize(TileModel hiresTile) {
48-
this.hiresTile = hiresTile;
47+
public TileModelView initialize(TileModel hiresTile) {
48+
this.tileModel = hiresTile;
4949
this.start = hiresTile.size();
5050
this.size = 0;
5151

5252
return this;
5353
}
5454

55-
public BlockModelView initialize(int start) {
55+
public TileModelView initialize(int start) {
5656
this.start = start;
57-
this.size = hiresTile.size() - start;
57+
this.size = tileModel.size() - start;
5858

5959
return this;
6060
}
6161

62-
public BlockModelView initialize() {
63-
this.start = hiresTile.size();
62+
public TileModelView initialize() {
63+
this.start = tileModel.size();
6464
this.size = 0;
6565

6666
return this;
6767
}
6868

69-
public BlockModelView reset() {
70-
hiresTile.reset(this.start);
69+
public TileModelView reset() {
70+
tileModel.reset(this.start);
7171
this.size = 0;
7272

7373
return this;
7474
}
7575

7676
public int add(int count) {
77-
int s = hiresTile.add(count);
77+
int s = tileModel.add(count);
7878
if (s != start + size) throw new IllegalStateException("Size of HiresTileModel had external changes since view-initialisation!");
7979
this.size += count;
8080
return s;
8181
}
8282

83-
public BlockModelView rotate(float angle, float axisX, float axisY, float axisZ) {
84-
hiresTile.rotate(start, size, angle, axisX, axisY, axisZ);
83+
public TileModelView rotate(float angle, float axisX, float axisY, float axisZ) {
84+
tileModel.rotate(start, size, angle, axisX, axisY, axisZ);
8585
return this;
8686
}
8787

88-
public BlockModelView rotate(float pitch, float yaw, float roll) {
89-
hiresTile.rotate(start, size, pitch, yaw, roll);
88+
public TileModelView rotate(float pitch, float yaw, float roll) {
89+
tileModel.rotate(start, size, pitch, yaw, roll);
9090
return this;
9191
}
9292

93-
public BlockModelView scale(float sx, float sy, float sz) {
94-
hiresTile.scale(start, size, sx, sy, sz);
93+
public TileModelView scale(float sx, float sy, float sz) {
94+
tileModel.scale(start, size, sx, sy, sz);
9595
return this;
9696
}
9797

98-
public BlockModelView translate(float dx, float dy, float dz) {
99-
hiresTile.translate(start, size, dx, dy, dz);
98+
public TileModelView translate(float dx, float dy, float dz) {
99+
tileModel.translate(start, size, dx, dy, dz);
100100
return this;
101101
}
102102

103-
public BlockModelView transform(MatrixM3f t) {
104-
hiresTile.transform(start, size, t);
103+
public TileModelView transform(MatrixM3f t) {
104+
tileModel.transform(start, size, t);
105105
return this;
106106
}
107107

108-
public BlockModelView transform(
108+
public TileModelView transform(
109109
float m00, float m01, float m02,
110110
float m10, float m11, float m12,
111111
float m20, float m21, float m22
112112
) {
113-
hiresTile.transform(start, size,
113+
tileModel.transform(start, size,
114114
m00, m01, m02,
115115
m10, m11, m12,
116116
m20, m21, m22
117117
);
118118
return this;
119119
}
120120

121-
public BlockModelView transform(MatrixM4f t) {
122-
hiresTile.transform(start, size, t);
121+
public TileModelView transform(MatrixM4f t) {
122+
tileModel.transform(start, size, t);
123123
return this;
124124
}
125125

126-
public BlockModelView transform(
126+
public TileModelView transform(
127127
float m00, float m01, float m02, float m03,
128128
float m10, float m11, float m12, float m13,
129129
float m20, float m21, float m22, float m23,
130130
float m30, float m31, float m32, float m33
131131
) {
132-
hiresTile.transform(start, size,
132+
tileModel.transform(start, size,
133133
m00, m01, m02, m03,
134134
m10, m11, m12, m13,
135135
m20, m21, m22, m23,
@@ -138,8 +138,8 @@ public BlockModelView transform(
138138
return this;
139139
}
140140

141-
public TileModel getHiresTile() {
142-
return hiresTile;
141+
public TileModel getTileModel() {
142+
return tileModel;
143143
}
144144

145145
public int getStart() {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package de.bluecolored.bluemap.core.map.hires.blockmodel;
2+
3+
import de.bluecolored.bluemap.core.map.hires.TileModelView;
4+
import de.bluecolored.bluemap.core.resources.pack.resourcepack.blockstate.Variant;
5+
import de.bluecolored.bluemap.core.util.math.Color;
6+
import de.bluecolored.bluemap.core.world.block.BlockNeighborhood;
7+
8+
public interface BlockRenderer {
9+
10+
/**
11+
* Renders the given blocks (block-state-)variant into the given blockModel, and sets the given blockColor to the
12+
* color that represents the rendered block.
13+
* <p>
14+
* <b>Implementation Note:</b><br>
15+
* This method is guaranteed to be called only on <b>one thread per BlockRenderer instance</b>, so you can use this
16+
* for optimizations.<br>
17+
* Keep in mind this method will be called once for every block that is being rendered, so be very careful
18+
* about performance and instance-creations.
19+
* </p>
20+
* @param block The block information that should be rendered.
21+
* @param variant The block-state variant that should be rendered.
22+
* @param blockModel The model(-view) where the block should be rendered to.
23+
* @param blockColor The color that should be set to the color that represents the rendered block.
24+
*/
25+
void render(BlockNeighborhood<?> block, Variant variant, TileModelView blockModel, Color blockColor);
26+
27+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package de.bluecolored.bluemap.core.map.hires.blockmodel;
2+
3+
import de.bluecolored.bluemap.core.map.TextureGallery;
4+
import de.bluecolored.bluemap.core.map.hires.RenderSettings;
5+
import de.bluecolored.bluemap.core.resources.pack.resourcepack.ResourcePack;
6+
7+
public interface BlockRendererFactory {
8+
9+
BlockRenderer create(ResourcePack resourcePack, TextureGallery textureGallery, RenderSettings renderSettings);
10+
11+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package de.bluecolored.bluemap.core.map.hires.blockmodel;
2+
3+
import de.bluecolored.bluemap.core.map.TextureGallery;
4+
import de.bluecolored.bluemap.core.map.hires.RenderSettings;
5+
import de.bluecolored.bluemap.core.resources.pack.resourcepack.ResourcePack;
6+
import de.bluecolored.bluemap.core.util.Key;
7+
import de.bluecolored.bluemap.core.util.Keyed;
8+
import de.bluecolored.bluemap.core.util.Registry;
9+
import de.bluecolored.bluemap.core.world.BlockState;
10+
import lombok.Getter;
11+
import lombok.RequiredArgsConstructor;
12+
13+
public interface BlockRendererType extends Keyed, BlockRendererFactory {
14+
15+
BlockRendererType DEFAULT = new Impl(Key.bluemap("default"), ResourceModelRenderer::new);
16+
BlockRendererType LIQUID = new Impl(Key.bluemap("liquid"), LiquidModelRenderer::new);
17+
BlockRendererType MISSING = new Impl(Key.bluemap("missing"), MissingModelRenderer::new);
18+
19+
Registry<BlockRendererType> REGISTRY = new Registry<>(
20+
DEFAULT,
21+
LIQUID,
22+
MISSING
23+
);
24+
25+
/**
26+
* If the loaded resourcepack does not have any resources for this blockState, this method will be called.
27+
* If this method returns true, this renderer will be used to render the block instead of rendering the default
28+
* black-purple "missing block" model.
29+
* When rendering, the provided "variant" will always be bluemaps default "missing-block" resource.
30+
*
31+
* <p>
32+
* This can (and should only then) be used to provide a way of rendering blocks that are completely dynamically
33+
* created by a mod, and there is no way to provide static block-state resources that point at the correct renderer.
34+
* </p>
35+
*
36+
* @param blockState The {@link BlockState} that was not found in the loaded resources.
37+
* @return true if this renderer-type can render the provided {@link BlockState} despite missing resources.
38+
*/
39+
default boolean isFallbackFor(BlockState blockState) {
40+
return false;
41+
}
42+
43+
@RequiredArgsConstructor
44+
class Impl implements BlockRendererType {
45+
46+
@Getter private final Key key;
47+
private final BlockRendererFactory rendererFactory;
48+
49+
@Override
50+
public BlockRenderer create(ResourcePack resourcePack, TextureGallery textureGallery, RenderSettings renderSettings) {
51+
return rendererFactory.create(resourcePack, textureGallery, renderSettings);
52+
}
53+
54+
}
55+
56+
}

core/src/main/java/de/bluecolored/bluemap/core/map/hires/blockmodel/BlockStateModelFactory.java renamed to core/src/main/java/de/bluecolored/bluemap/core/map/hires/blockmodel/BlockStateModelRenderer.java

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@
2424
*/
2525
package de.bluecolored.bluemap.core.map.hires.blockmodel;
2626

27+
import com.github.benmanes.caffeine.cache.Caffeine;
28+
import com.github.benmanes.caffeine.cache.LoadingCache;
2729
import de.bluecolored.bluemap.core.map.TextureGallery;
28-
import de.bluecolored.bluemap.core.map.hires.BlockModelView;
30+
import de.bluecolored.bluemap.core.map.hires.TileModelView;
2931
import de.bluecolored.bluemap.core.map.hires.RenderSettings;
3032
import de.bluecolored.bluemap.core.resources.pack.resourcepack.ResourcePack;
3133
import de.bluecolored.bluemap.core.resources.pack.resourcepack.blockmodel.BlockModel;
@@ -37,27 +39,25 @@
3739
import java.util.ArrayList;
3840
import java.util.List;
3941

40-
public class BlockStateModelFactory {
42+
public class BlockStateModelRenderer {
4143

4244
private final ResourcePack resourcePack;
43-
private final ResourceModelBuilder resourceModelBuilder;
44-
private final LiquidModelBuilder liquidModelBuilder;
45+
private final LoadingCache<BlockRendererType, BlockRenderer> blockRenderers;
4546

4647
private final List<Variant> variants = new ArrayList<>();
4748

48-
public BlockStateModelFactory(ResourcePack resourcePack, TextureGallery textureGallery, RenderSettings renderSettings) {
49+
public BlockStateModelRenderer(ResourcePack resourcePack, TextureGallery textureGallery, RenderSettings renderSettings) {
4950
this.resourcePack = resourcePack;
50-
51-
this.resourceModelBuilder = new ResourceModelBuilder(resourcePack, textureGallery, renderSettings);
52-
this.liquidModelBuilder = new LiquidModelBuilder(resourcePack, textureGallery, renderSettings);
51+
this.blockRenderers = Caffeine.newBuilder()
52+
.build(type -> type.create(resourcePack, textureGallery, renderSettings));
5353
}
5454

55-
public void render(BlockNeighborhood<?> block, BlockModelView blockModel, Color blockColor) {
55+
public void render(BlockNeighborhood<?> block, TileModelView blockModel, Color blockColor) {
5656
render(block, block.getBlockState(), blockModel, blockColor);
5757
}
5858

5959
private final Color waterloggedColor = new Color();
60-
public void render(BlockNeighborhood<?> block, BlockState blockState, BlockModelView blockModel, Color blockColor) {
60+
public void render(BlockNeighborhood<?> block, BlockState blockState, TileModelView blockModel, Color blockColor) {
6161
blockColor.set(0, 0, 0, 0, true);
6262

6363
//shortcut for air
@@ -79,7 +79,7 @@ public void render(BlockNeighborhood<?> block, BlockState blockState, BlockModel
7979
}
8080

8181
private final Color variantColor = new Color();
82-
private void renderModel(BlockNeighborhood<?> block, BlockState blockState, BlockModelView blockModel, Color blockColor) {
82+
private void renderModel(BlockNeighborhood<?> block, BlockState blockState, TileModelView blockModel, Color blockColor) {
8383
int modelStart = blockModel.getStart();
8484

8585
var stateResource = resourcePack.getBlockState(blockState);
@@ -98,11 +98,8 @@ private void renderModel(BlockNeighborhood<?> block, BlockState blockState, Bloc
9898

9999
variantColor.set(0f, 0f, 0f, 0f, true);
100100

101-
if (modelResource.isLiquid()) {
102-
liquidModelBuilder.build(block, blockState, variant, blockModel.initialize(), variantColor);
103-
} else {
104-
resourceModelBuilder.build(block, variant, blockModel.initialize(), variantColor);
105-
}
101+
blockRenderers.get(modelResource.getRenderer())
102+
.render(block, variant, blockModel.initialize(), blockColor);
106103

107104
if (variantColor.a > blockColorOpacity)
108105
blockColorOpacity = variantColor.a;

0 commit comments

Comments
 (0)