Weltkarte: Anpassungen vor schematischem Umbau
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -163,7 +163,7 @@ public final class WorldMapRenderer {
|
|||||||
int[] slotCols = model.slotColorsRGB();
|
int[] slotCols = model.slotColorsRGB();
|
||||||
int[] colorMap = model.terrainColorMap() != null
|
int[] colorMap = model.terrainColorMap() != null
|
||||||
? model.terrainColorMap()
|
? model.terrainColorMap()
|
||||||
: buildTerrainColorMap(m, slotCols, model.mapTilePixels(), model.voxelSurface(), model.waters());
|
: buildTerrainColorMap(m, slotCols, model.mapTilePixels(), model.voxelSurface(), model.waters(), model.waterfalls());
|
||||||
int[] rawRGB = new int[targetSize * targetSize];
|
int[] rawRGB = new int[targetSize * targetSize];
|
||||||
int waterR = (WATER_COLOR >> 16) & 0xFF;
|
int waterR = (WATER_COLOR >> 16) & 0xFF;
|
||||||
int waterG = (WATER_COLOR >> 8) & 0xFF;
|
int waterG = (WATER_COLOR >> 8) & 0xFF;
|
||||||
@@ -962,6 +962,41 @@ public final class WorldMapRenderer {
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Erzeugt eine Maske: true für jeden Pixel, der innerhalb eines Wasserfall-Quads liegt.
|
||||||
|
* Nutzt Graphics2D-Rasterisierung inkl. Stroke, damit auch schmale Quads erfasst werden. */
|
||||||
|
private static boolean[] buildWaterfallMask(List<PlacedWaterfall> waterfalls, int size) {
|
||||||
|
boolean[] mask = new boolean[size * size];
|
||||||
|
if (waterfalls == null || waterfalls.isEmpty()) return mask;
|
||||||
|
// BYTE_BINARY: 1 bit/px → 512 KB bei 2048px, 8 MB bei 8192px
|
||||||
|
BufferedImage img = new BufferedImage(size, size, BufferedImage.TYPE_BYTE_BINARY);
|
||||||
|
Graphics2D g = img.createGraphics();
|
||||||
|
g.setColor(java.awt.Color.WHITE);
|
||||||
|
float strokeW = Math.max(4f, size / 512f); // mind. 4px Strichbreite für dünne Quads
|
||||||
|
g.setStroke(new BasicStroke(strokeW, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
|
||||||
|
for (PlacedWaterfall wf : waterfalls) {
|
||||||
|
int[] xs = {
|
||||||
|
worldToPixel(wf.ax(), size), worldToPixel(wf.bx(), size),
|
||||||
|
worldToPixel(wf.cx(), size), worldToPixel(wf.dx(), size)
|
||||||
|
};
|
||||||
|
int[] zs = {
|
||||||
|
worldToPixel(wf.az(), size), worldToPixel(wf.bz(), size),
|
||||||
|
worldToPixel(wf.cz(), size), worldToPixel(wf.dz(), size)
|
||||||
|
};
|
||||||
|
g.fillPolygon(xs, zs, 4); // Füllung
|
||||||
|
g.drawPolygon(xs, zs, 4); // Stroke-Backup für schmale Quads
|
||||||
|
}
|
||||||
|
g.dispose();
|
||||||
|
java.awt.image.Raster raster = img.getData();
|
||||||
|
int[] px = new int[1];
|
||||||
|
for (int py = 0; py < size; py++) {
|
||||||
|
for (int x = 0; x < size; x++) {
|
||||||
|
raster.getPixel(x, py, px);
|
||||||
|
if (px[0] != 0) mask[py * size + x] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
/** Lädt die 6 Karten-Kacheln aus Textures/map/ im Asset-Verzeichnis. */
|
/** Lädt die 6 Karten-Kacheln aus Textures/map/ im Asset-Verzeichnis. */
|
||||||
public static int[][] loadMapTiles(Path assetRoot) {
|
public static int[][] loadMapTiles(Path assetRoot) {
|
||||||
int[][] result = new int[TILE_FILE_NAMES.length][];
|
int[][] result = new int[TILE_FILE_NAMES.length][];
|
||||||
@@ -1220,23 +1255,25 @@ public final class WorldMapRenderer {
|
|||||||
* verwendet — kein Splatmap-Blend zur Renderzeit mehr.
|
* verwendet — kein Splatmap-Blend zur Renderzeit mehr.
|
||||||
*/
|
*/
|
||||||
public static int[] buildTerrainColorMap(MapData m, int[] slotColors, int[][] tilePixels,
|
public static int[] buildTerrainColorMap(MapData m, int[] slotColors, int[][] tilePixels,
|
||||||
float[] voxelSurface, List<PlacedWater> waters) {
|
float[] voxelSurface, List<PlacedWater> waters,
|
||||||
|
List<PlacedWaterfall> waterfalls) {
|
||||||
final int SIZE = COLOR_MAP_SIZE;
|
final int SIZE = COLOR_MAP_SIZE;
|
||||||
final int SS = MapData.SPLAT_SIZE;
|
final int SS = MapData.SPLAT_SIZE;
|
||||||
float[] heights = buildTerrainSamples(m, SIZE, voxelSurface);
|
float[] heights = buildTerrainSamples(m, SIZE, voxelSurface);
|
||||||
float[] waterH = buildWaterHeightMap(waters, SIZE);
|
float[] waterH = buildWaterHeightMap(waters, SIZE);
|
||||||
int[] tileAvg = computeTileAvgColors(tilePixels);
|
boolean[] wfMask = buildWaterfallMask(waterfalls, SIZE);
|
||||||
int[] slotTypes = computeSlotTileTypes(m, slotColors);
|
int[] tileAvg = computeTileAvgColors(tilePixels);
|
||||||
float cellW = WORLD_SIZE / (SIZE - 1);
|
int[] slotTypes = computeSlotTileTypes(m, slotColors);
|
||||||
int[] terrainRGB = new int[SIZE * SIZE];
|
float cellW = WORLD_SIZE / (SIZE - 1);
|
||||||
float[] cliffMask = new float[SIZE * SIZE];
|
int[] terrainRGB = new int[SIZE * SIZE];
|
||||||
|
float[] cliffMask = new float[SIZE * SIZE];
|
||||||
for (int py = 0; py < SIZE; py++) {
|
for (int py = 0; py < SIZE; py++) {
|
||||||
float wz = -WORLD_HALF + py * cellW;
|
float wz = -WORLD_HALF + py * cellW;
|
||||||
for (int px = 0; px < SIZE; px++) {
|
for (int px = 0; px < SIZE; px++) {
|
||||||
float wx = -WORLD_HALF + px * cellW;
|
float wx = -WORLD_HALF + px * cellW;
|
||||||
int idx = py * SIZE + px;
|
int idx = py * SIZE + px;
|
||||||
float h = heights[idx];
|
float h = heights[idx];
|
||||||
if (h < 0f || (waterH[idx] > 0f && waterH[idx] > h)) {
|
if (h < 0f || (waterH[idx] > 0f && waterH[idx] > h) || wfMask[idx]) {
|
||||||
int[] wc = TILE_FALLBACK_RGB[TILE_WATER];
|
int[] wc = TILE_FALLBACK_RGB[TILE_WATER];
|
||||||
terrainRGB[idx] = (wc[0]<<16)|(wc[1]<<8)|wc[2];
|
terrainRGB[idx] = (wc[0]<<16)|(wc[1]<<8)|wc[2];
|
||||||
} else {
|
} else {
|
||||||
@@ -1278,6 +1315,7 @@ public final class WorldMapRenderer {
|
|||||||
*/
|
*/
|
||||||
public static int buildAndSaveHiresChunks(MapData m, int[] slotColors, int[][] tilePixels,
|
public static int buildAndSaveHiresChunks(MapData m, int[] slotColors, int[][] tilePixels,
|
||||||
float[] voxelSurface, List<PlacedWater> waters,
|
float[] voxelSurface, List<PlacedWater> waters,
|
||||||
|
List<PlacedWaterfall> waterfalls,
|
||||||
java.nio.file.Path cacheDir, boolean forceRegen) {
|
java.nio.file.Path cacheDir, boolean forceRegen) {
|
||||||
final int SIZE = HIRES_MAP_SIZE;
|
final int SIZE = HIRES_MAP_SIZE;
|
||||||
final int CS = CHUNK_SIZE;
|
final int CS = CHUNK_SIZE;
|
||||||
@@ -1297,11 +1335,12 @@ public final class WorldMapRenderer {
|
|||||||
if (allExist) { log.debug("[HiresChunks] Alle {} Chunks im Cache – übersprungen.", COLS*COLS); return 0; }
|
if (allExist) { log.debug("[HiresChunks] Alle {} Chunks im Cache – übersprungen.", COLS*COLS); return 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
float[] heights = buildTerrainSamples(m, SIZE, voxelSurface);
|
float[] heights = buildTerrainSamples(m, SIZE, voxelSurface);
|
||||||
float[] waterH = buildWaterHeightMap(waters, SIZE);
|
float[] waterH = buildWaterHeightMap(waters, SIZE);
|
||||||
int[] tileAvg = computeTileAvgColors(tilePixels);
|
boolean[] wfMask = buildWaterfallMask(waterfalls, SIZE);
|
||||||
int[] slotTypes = computeSlotTileTypes(m, slotColors);
|
int[] tileAvg = computeTileAvgColors(tilePixels);
|
||||||
float cellW = WORLD_SIZE / (SIZE - 1);
|
int[] slotTypes = computeSlotTileTypes(m, slotColors);
|
||||||
|
float cellW = WORLD_SIZE / (SIZE - 1);
|
||||||
int written = 0;
|
int written = 0;
|
||||||
|
|
||||||
final int CLIFF_BLUR_R = 4; // Blur-Radius für weiche Klippen-Kanten
|
final int CLIFF_BLUR_R = 4; // Blur-Radius für weiche Klippen-Kanten
|
||||||
@@ -1329,7 +1368,7 @@ public final class WorldMapRenderer {
|
|||||||
int eidx = ely * EXTW + elx;
|
int eidx = ely * EXTW + elx;
|
||||||
int hidx = gyC * SIZE + gxC;
|
int hidx = gyC * SIZE + gxC;
|
||||||
float h = heights[hidx];
|
float h = heights[hidx];
|
||||||
if (h < 0f || (waterH[hidx] > 0f && waterH[hidx] > h)) {
|
if (h < 0f || (waterH[hidx] > 0f && waterH[hidx] > h) || wfMask[hidx]) {
|
||||||
isWaterExt[eidx] = true;
|
isWaterExt[eidx] = true;
|
||||||
} else {
|
} else {
|
||||||
float hR = heights[gyC * SIZE + Math.min(SIZE-1, gxC+dPxHires)];
|
float hR = heights[gyC * SIZE + Math.min(SIZE-1, gxC+dPxHires)];
|
||||||
|
|||||||
@@ -563,8 +563,15 @@ public class EditorApp extends Application {
|
|||||||
javafx.animation.Timeline[] pollerRef = new javafx.animation.Timeline[1];
|
javafx.animation.Timeline[] pollerRef = new javafx.animation.Timeline[1];
|
||||||
pollerRef[0] = new javafx.animation.Timeline(
|
pollerRef[0] = new javafx.animation.Timeline(
|
||||||
new javafx.animation.KeyFrame(javafx.util.Duration.millis(100), ev -> {
|
new javafx.animation.KeyFrame(javafx.util.Duration.millis(100), ev -> {
|
||||||
splashStatus.setText(input.loadingStatus);
|
boolean jmeOk = input.jmeReady;
|
||||||
if (input.jmeReady) {
|
boolean mapOk = worldMapView != null && worldMapView.isMapReady();
|
||||||
|
if (!jmeOk) {
|
||||||
|
splashStatus.setText(input.loadingStatus);
|
||||||
|
} else {
|
||||||
|
splashStatus.setText("Karte: " + (worldMapView != null
|
||||||
|
? worldMapView.getLoadingStatus() : "…"));
|
||||||
|
}
|
||||||
|
if (jmeOk && mapOk) {
|
||||||
pollerRef[0].stop();
|
pollerRef[0].stop();
|
||||||
stage.show();
|
stage.show();
|
||||||
restoreEditorPrefs();
|
restoreEditorPrefs();
|
||||||
@@ -5646,30 +5653,34 @@ public class EditorApp extends Application {
|
|||||||
if (isSelected) mapObjectsView.refresh();
|
if (isSelected) mapObjectsView.refresh();
|
||||||
});
|
});
|
||||||
|
|
||||||
worldMapView = new de.blight.editor.ui.WorldMapView(() -> primaryStage);
|
if (worldMapView == null) {
|
||||||
worldMapView.setVoxelChunkSupplier(() -> {
|
worldMapView = new de.blight.editor.ui.WorldMapView(() -> primaryStage);
|
||||||
de.blight.editor.state.VoxelEditorState ves = jmeApp == null ? null
|
worldMapView.setVoxelChunkSupplier(() -> {
|
||||||
: jmeApp.getStateManager().getState(de.blight.editor.state.VoxelEditorState.class);
|
de.blight.editor.state.VoxelEditorState ves = jmeApp == null ? null
|
||||||
return ves != null ? ves.getChunksSnapshot() : de.blight.common.VoxelChunkIO.loadAll();
|
: jmeApp.getStateManager().getState(de.blight.editor.state.VoxelEditorState.class);
|
||||||
});
|
return ves != null ? ves.getChunksSnapshot() : de.blight.common.VoxelChunkIO.loadAll();
|
||||||
worldMapView.setCameraInfoSupplier(() ->
|
});
|
||||||
new de.blight.editor.ui.WorldMapView.CameraInfo(
|
worldMapView.setCameraInfoSupplier(() ->
|
||||||
input.camX, input.camY, input.camZ, input.camYaw));
|
new de.blight.editor.ui.WorldMapView.CameraInfo(
|
||||||
worldMapView.setTeleportCallback(pos -> {
|
input.camX, input.camY, input.camZ, input.camYaw));
|
||||||
input.pendingGotoX = pos[0];
|
worldMapView.setTeleportCallback(pos -> {
|
||||||
input.pendingGotoY = pos[1];
|
input.pendingGotoX = pos[0];
|
||||||
input.pendingGotoZ = pos[2];
|
input.pendingGotoY = pos[1];
|
||||||
});
|
input.pendingGotoZ = pos[2];
|
||||||
|
});
|
||||||
|
worldMapView.setRefreshAction(() -> {
|
||||||
|
input.saveRequested = true;
|
||||||
|
pendingAfterSave = worldMapView::loadAndRender;
|
||||||
|
setStatus("Speichere vor Weltkarten-Refresh…");
|
||||||
|
});
|
||||||
|
worldMapView.loadAndRender(); // Vorladen beim Start, nicht erst beim Tab-Öffnen
|
||||||
|
}
|
||||||
|
|
||||||
weltkartTab = new Tab("Weltkarte", worldMapView);
|
weltkartTab = new Tab("Weltkarte", worldMapView);
|
||||||
weltkartTab.setClosable(false);
|
weltkartTab.setClosable(false);
|
||||||
weltkartTab.selectedProperty().addListener((obs, wasSelected, isSelected) -> {
|
weltkartTab.selectedProperty().addListener((obs, wasSelected, isSelected) -> {
|
||||||
if (isSelected && !worldMapView.isLoaded()) worldMapView.loadAndRender();
|
if (isSelected && !worldMapView.isLoaded()) worldMapView.loadAndRender();
|
||||||
});
|
else if (isSelected) worldMapView.ensureFitToView();
|
||||||
worldMapView.setRefreshAction(() -> {
|
|
||||||
input.saveRequested = true;
|
|
||||||
pendingAfterSave = worldMapView::loadAndRender;
|
|
||||||
setStatus("Speichere vor Weltkarten-Refresh…");
|
|
||||||
});
|
});
|
||||||
worldMapView.setFullscreenCallbacks(
|
worldMapView.setFullscreenCallbacks(
|
||||||
() -> {
|
() -> {
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ public class WorldMapView extends VBox {
|
|||||||
};
|
};
|
||||||
private final java.util.Set<Integer> chunksLoading =
|
private final java.util.Set<Integer> chunksLoading =
|
||||||
java.util.Collections.synchronizedSet(new java.util.HashSet<>());
|
java.util.Collections.synchronizedSet(new java.util.HashSet<>());
|
||||||
|
private volatile boolean chunkRedrawPending = false;
|
||||||
|
|
||||||
private WritableImage bakedForestOverlay = null;
|
private WritableImage bakedForestOverlay = null;
|
||||||
// Wasser-Fill-Overlay entfernt: ocean + PlacedWater sind bereits in mapFxImage korrekt gerendert
|
// Wasser-Fill-Overlay entfernt: ocean + PlacedWater sind bereits in mapFxImage korrekt gerendert
|
||||||
@@ -326,7 +327,16 @@ public class WorldMapView extends VBox {
|
|||||||
|
|
||||||
// ── Öffentliche API ───────────────────────────────────────────────────────
|
// ── Öffentliche API ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
public boolean isLoaded() { return mapFxImage != null || loading.get(); }
|
public boolean isLoaded() { return mapFxImage != null || loading.get(); }
|
||||||
|
public boolean isMapReady() { return mapFxImage != null; }
|
||||||
|
public String getLoadingStatus() { return statusLbl.getText(); }
|
||||||
|
|
||||||
|
/** Stellt sicher, dass die Karte beim ersten Anzeigen korrekt skaliert/positioniert ist. */
|
||||||
|
public void ensureFitToView() {
|
||||||
|
if (mapFxImage != null && zoomLevels == null) {
|
||||||
|
fitCanvas();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Lädt alle Weltdaten neu und baut das Render-Modell (teuer: I/O + Berechnungen). */
|
/** Lädt alle Weltdaten neu und baut das Render-Modell (teuer: I/O + Berechnungen). */
|
||||||
public void loadAndRender() {
|
public void loadAndRender() {
|
||||||
@@ -377,7 +387,8 @@ public class WorldMapView extends VBox {
|
|||||||
Platform.runLater(() -> statusLbl.setText("Generiere Hires-Chunks…"));
|
Platform.runLater(() -> statusLbl.setText("Generiere Hires-Chunks…"));
|
||||||
WorldMapRenderer.buildAndSaveHiresChunks(
|
WorldMapRenderer.buildAndSaveHiresChunks(
|
||||||
chunkModel.mapData(), chunkModel.slotColorsRGB(), chunkModel.mapTilePixels(),
|
chunkModel.mapData(), chunkModel.slotColorsRGB(), chunkModel.mapTilePixels(),
|
||||||
chunkModel.voxelSurface(), chunkModel.waters(), CHUNK_CACHE_DIR, true);
|
chunkModel.voxelSurface(), chunkModel.waters(), chunkModel.waterfalls(),
|
||||||
|
CHUNK_CACHE_DIR, true);
|
||||||
chunkCache.clear();
|
chunkCache.clear();
|
||||||
|
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
@@ -498,9 +509,14 @@ public class WorldMapView extends VBox {
|
|||||||
if (img != null) {
|
if (img != null) {
|
||||||
gc.drawImage(img, canvasLeft, canvasTop, chunkCanvasW, chunkCanvasH);
|
gc.drawImage(img, canvasLeft, canvasTop, chunkCanvasW, chunkCanvasH);
|
||||||
} else {
|
} else {
|
||||||
// Platzhalter (dunkelgrau) + asynchrones Laden
|
// Fallback: lowres-Ausschnitt zeigen bis Hires-Chunk geladen ist
|
||||||
gc.setFill(javafx.scene.paint.Color.rgb(40, 40, 40));
|
if (mapFxImage != null) {
|
||||||
gc.fillRect(canvasLeft, canvasTop, chunkCanvasW, chunkCanvasH);
|
double srcX = (double) cx * RENDER_SIZE / COLS;
|
||||||
|
double srcY = (double) cy * RENDER_SIZE / COLS;
|
||||||
|
double srcW = (double) RENDER_SIZE / COLS;
|
||||||
|
gc.drawImage(mapFxImage, srcX, srcY, srcW, srcW,
|
||||||
|
canvasLeft, canvasTop, chunkCanvasW, chunkCanvasH);
|
||||||
|
}
|
||||||
if (chunksLoading.add(key)) {
|
if (chunksLoading.add(key)) {
|
||||||
final int fcx = cx, fcy = cy, fkey = key;
|
final int fcx = cx, fcy = cy, fkey = key;
|
||||||
Thread lt = new Thread(() -> {
|
Thread lt = new Thread(() -> {
|
||||||
@@ -512,7 +528,7 @@ public class WorldMapView extends VBox {
|
|||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
chunkCache.put(fkey, wi);
|
chunkCache.put(fkey, wi);
|
||||||
chunksLoading.remove(fkey);
|
chunksLoading.remove(fkey);
|
||||||
redraw();
|
scheduleChunkRedraw();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
chunksLoading.remove(fkey);
|
chunksLoading.remove(fkey);
|
||||||
@@ -526,6 +542,17 @@ public class WorldMapView extends VBox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Bündelt Redraws nach Chunk-Ladevorgängen: maximal ein Redraw pro FX-Puls. */
|
||||||
|
private void scheduleChunkRedraw() {
|
||||||
|
if (!chunkRedrawPending) {
|
||||||
|
chunkRedrawPending = true;
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
chunkRedrawPending = false;
|
||||||
|
redraw();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ── Canvas Tile-Overlay (zoom-unabhängige Kacheln) ────────────────────────
|
// ── Canvas Tile-Overlay (zoom-unabhängige Kacheln) ────────────────────────
|
||||||
|
|
||||||
private static int tileSample(int[][] tilePx, int cat,
|
private static int tileSample(int[][] tilePx, int cat,
|
||||||
@@ -916,7 +943,7 @@ public class WorldMapView extends VBox {
|
|||||||
List<PlacedModel> treeList = models.stream()
|
List<PlacedModel> treeList = models.stream()
|
||||||
.filter(WorldMapRenderer::isTree).collect(Collectors.toList());
|
.filter(WorldMapRenderer::isTree).collect(Collectors.toList());
|
||||||
List<List<PlacedModel>> tClusters = clusterTreeModels(treeList, 40f);
|
List<List<PlacedModel>> tClusters = clusterTreeModels(treeList, 40f);
|
||||||
int[] colorMap = WorldMapRenderer.buildTerrainColorMap(mapData, slotColors, mapTiles, voxelSurface, waters);
|
int[] colorMap = WorldMapRenderer.buildTerrainColorMap(mapData, slotColors, mapTiles, voxelSurface, waters, waterfalls);
|
||||||
return new WorldMapRenderModel(
|
return new WorldMapRenderModel(
|
||||||
mapData, areas, zones, locs, waters, models, waterfalls, slotColors,
|
mapData, areas, zones, locs, waters, models, waterfalls, slotColors,
|
||||||
mask, voxelSurface, tSamp, paths, tClusters, mapTiles, colorMap);
|
mask, voxelSurface, tSamp, paths, tClusters, mapTiles, colorMap);
|
||||||
@@ -924,8 +951,8 @@ public class WorldMapView extends VBox {
|
|||||||
|
|
||||||
// Erzeugt interpolierte Marching-Squares-Segmente für Meer + Wasserflächen.
|
// Erzeugt interpolierte Marching-Squares-Segmente für Meer + Wasserflächen.
|
||||||
// Endpunkte liegen am echten Höhen-Nulldurchgang → keine Treppenstufen auf Diagonalen.
|
// Endpunkte liegen am echten Höhen-Nulldurchgang → keine Treppenstufen auf Diagonalen.
|
||||||
private static float[][] buildCoastSegsMS(MapData mapData, List<PlacedWater> waters, int size,
|
private static float[][] buildCoastSegsMS(MapData mapData, List<PlacedWater> waters,
|
||||||
float[] voxelSurface) {
|
int size, float[] voxelSurface) {
|
||||||
int TV = MapData.TERRAIN_VERTS;
|
int TV = MapData.TERRAIN_VERTS;
|
||||||
int VS = WorldMapRenderer.VOXEL_SURFACE_RES;
|
int VS = WorldMapRenderer.VOXEL_SURFACE_RES;
|
||||||
float[] h = new float[size * size];
|
float[] h = new float[size * size];
|
||||||
|
|||||||
Reference in New Issue
Block a user