Skip to content

Commit 15b3da4

Browse files
committed
Introduce RenderPasses which allow custom modifications to the entire tile-model without being bound to a custom block or entity
1 parent 1fdf647 commit 15b3da4

File tree

10 files changed

+315
-157
lines changed

10 files changed

+315
-157
lines changed

core/src/main/java/de/bluecolored/bluemap/core/map/BmMap.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ public BmMap(String id, String name, World world, MapStorage storage, ResourcePa
105105
saveTextureGallery();
106106

107107
this.hiresModelManager = new HiresModelManager(
108+
world,
108109
storage.hiresTiles(),
109110
this.resourcePack,
110111
this.textureGallery,
@@ -135,7 +136,7 @@ public void renderTile(Vector2i tile) {
135136

136137
long start = System.nanoTime();
137138

138-
hiresModelManager.render(world, tile, lowresTileManager, mapSettings.isSaveHiresLayer());
139+
hiresModelManager.render(tile, lowresTileManager, mapSettings.isSaveHiresLayer());
139140

140141
long end = System.nanoTime();
141142
long delta = end - start;

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

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -38,47 +38,60 @@
3838

3939
import java.io.IOException;
4040
import java.io.OutputStream;
41+
import java.util.Collection;
42+
import java.util.List;
4143

4244
public class HiresModelManager {
4345

46+
private final World world;
4447
private final GridStorage storage;
45-
private final HiresModelRenderer renderer;
48+
private final ThreadLocal<Collection<RenderPass>> renderPasses;
4649

4750
@Getter
4851
private final Grid tileGrid;
4952

50-
public HiresModelManager(GridStorage storage, ResourcePack resourcePack, TextureGallery textureGallery, RenderSettings renderSettings, Grid tileGrid) {
51-
this(storage, new HiresModelRenderer(resourcePack, textureGallery, renderSettings), tileGrid);
52-
}
53-
54-
public HiresModelManager(GridStorage storage, HiresModelRenderer renderer, Grid tileGrid) {
53+
public HiresModelManager(World world, GridStorage storage, ResourcePack resourcePack, TextureGallery textureGallery, RenderSettings renderSettings, Grid tileGrid) {
54+
this.world = world;
5555
this.storage = storage;
56-
this.renderer = renderer;
57-
5856
this.tileGrid = tileGrid;
57+
58+
Collection<RenderPassType> renderPassTypes = List.copyOf(RenderPassType.REGISTRY.values());
59+
this.renderPasses = ThreadLocal.withInitial(() -> renderPassTypes.stream()
60+
.map(type -> type.create(resourcePack, textureGallery, renderSettings))
61+
.toList()
62+
);
5963
}
6064

6165
/**
6266
* Renders the given world tile with the provided render-settings
6367
*/
64-
public void render(World world, Vector2i tile, TileMetaConsumer tileMetaConsumer, boolean save) {
65-
Vector2i tileMin = tileGrid.getCellMin(tile);
66-
Vector2i tileMax = tileGrid.getCellMax(tile);
67-
68-
Vector3i modelMin = new Vector3i(tileMin.getX(), Integer.MIN_VALUE, tileMin.getY());
69-
Vector3i modelMax = new Vector3i(tileMax.getX(), Integer.MAX_VALUE, tileMax.getY());
68+
public void render(Vector2i tile, TileMetaConsumer tileMetaConsumer, boolean save) {
69+
Vector3i modelMin = new Vector3i(tileGrid.getCellMinX(tile.getX()), Integer.MIN_VALUE, tileGrid.getCellMinY(tile.getY()));
70+
Vector3i modelMax = new Vector3i(tileGrid.getCellMaxX(tile.getX()), Integer.MAX_VALUE, tileGrid.getCellMaxY(tile.getY()));
71+
Vector3i modelAnchor = new Vector3i(modelMin.getX(), 0, modelMin.getZ());
7072

7173
if (save) {
7274
ArrayTileModel model = ArrayTileModel.instancePool().claimInstance();
75+
TileModelView modelView = new TileModelView(model);
7376

74-
renderer.render(world, modelMin, modelMax, model, tileMetaConsumer);
77+
try {
78+
for (RenderPass renderPass : renderPasses.get()) {
79+
renderPass.render(world, modelMin, modelMax, modelAnchor, modelView.initialize(), tileMetaConsumer);
80+
}
81+
} catch (MaxCapacityReachedException ex) {
82+
Logger.global.noFloodWarning("max-capacity-reached",
83+
"One or more map-tiles are too complex to be completed (@~ %s to %s): %s".formatted(modelMin, modelMax, ex));
84+
}
7585

7686
model.sort();
7787
save(model, tile);
7888

7989
ArrayTileModel.instancePool().recycleInstance(model);
8090
} else {
81-
renderer.render(world, modelMin, modelMax, VoidTileModel.INSTANCE, tileMetaConsumer);
91+
TileModelView modelView = new TileModelView(VoidTileModel.INSTANCE);
92+
for (RenderPass renderPass : renderPasses.get()) {
93+
renderPass.render(world, modelMin, modelMax, modelAnchor, modelView.initialize(), tileMetaConsumer);
94+
}
8295
}
8396

8497
}

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

Lines changed: 0 additions & 138 deletions
This file was deleted.
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* This file is part of BlueMap, licensed under the MIT License (MIT).
3+
*
4+
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
5+
* Copyright (c) contributors
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
* THE SOFTWARE.
24+
*/
25+
package de.bluecolored.bluemap.core.map.hires;
26+
27+
import com.flowpowered.math.vector.Vector3i;
28+
import de.bluecolored.bluemap.core.map.TileMetaConsumer;
29+
import de.bluecolored.bluemap.core.world.World;
30+
31+
public interface RenderPass {
32+
33+
/**
34+
* Does a pass to render a specified of the world onto the given tileModel.
35+
* <p>
36+
* <b>Implementation Note:</b><br>
37+
* This method is guaranteed to be called only on <b>one thread per RenderPass instance</b>, so you can use this
38+
* for optimizations.
39+
* </p>
40+
* @param world The world that should be rendered
41+
* @param modelMin The min-position of the world that should be included in the tileModel
42+
* @param modelMax The max-position of the world that should be included in the tileModel
43+
* @param modelAnchor The position in the world that should be at (0,0,0) in the tileModel
44+
* @param tileModel The model(-view) where the world should be rendered to.
45+
* @param tileMetaConsumer A consumer that the RenderPass can call to emit heightmap and light-data that is produced during rendering.
46+
* This data is then e.g. used to generate the lowres-tiles.
47+
*/
48+
void render(World world, Vector3i modelMin, Vector3i modelMax, Vector3i modelAnchor, TileModelView tileModel, TileMetaConsumer tileMetaConsumer);
49+
50+
/**
51+
* Does a pass to render a specified of the world onto the given tileModel.
52+
* @param world The world that should be rendered
53+
* @param modelMin The min-position of the world that should be included in the tileModel
54+
* @param modelMax The max-position of the world that should be included in the tileModel
55+
* @param modelAnchor The position in the world that should be at (0,0,0) in the tileModel
56+
* @param tileModel The model(-view) where the world should be rendered to.
57+
*/
58+
default void render(World world, Vector3i modelMin, Vector3i modelMax, Vector3i modelAnchor, TileModelView tileModel) {
59+
render(world, modelMin, modelMax, modelAnchor, tileModel, (x, z, c, h, l) -> {});
60+
}
61+
62+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package de.bluecolored.bluemap.core.map.hires;
2+
3+
import de.bluecolored.bluemap.core.map.TextureGallery;
4+
import de.bluecolored.bluemap.core.resources.pack.resourcepack.ResourcePack;
5+
6+
public interface RenderPassFactory {
7+
8+
RenderPass create(ResourcePack resourcePack, TextureGallery textureGallery, RenderSettings renderSettings);
9+
10+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package de.bluecolored.bluemap.core.map.hires;
2+
3+
import de.bluecolored.bluemap.core.map.TextureGallery;
4+
import de.bluecolored.bluemap.core.map.hires.block.BlockRenderPass;
5+
import de.bluecolored.bluemap.core.map.hires.entity.EntityRenderPass;
6+
import de.bluecolored.bluemap.core.resources.pack.resourcepack.ResourcePack;
7+
import de.bluecolored.bluemap.core.util.Key;
8+
import de.bluecolored.bluemap.core.util.Keyed;
9+
import de.bluecolored.bluemap.core.util.Registry;
10+
import lombok.Getter;
11+
import lombok.RequiredArgsConstructor;
12+
13+
public interface RenderPassType extends Keyed, RenderPassFactory {
14+
15+
RenderPassType BLOCKS = new Impl(Key.bluemap("blocks"), BlockRenderPass::new);
16+
RenderPassType ENTITIES = new Impl(Key.bluemap("entities"), EntityRenderPass::new);
17+
18+
Registry<RenderPassType> REGISTRY = new Registry<>(
19+
BLOCKS,
20+
ENTITIES
21+
);
22+
23+
@RequiredArgsConstructor
24+
class Impl implements RenderPassType {
25+
26+
@Getter
27+
private final Key key;
28+
private final RenderPassFactory factory;
29+
30+
@Override
31+
public RenderPass create(ResourcePack resourcePack, TextureGallery textureGallery, RenderSettings renderSettings) {
32+
return factory.create(resourcePack, textureGallery, renderSettings);
33+
}
34+
35+
}
36+
37+
}

0 commit comments

Comments
 (0)