Skip to content

Commit

Permalink
feat: flat mode view and optimized chunks
Browse files Browse the repository at this point in the history
  • Loading branch information
r0man1337 committed Dec 20, 2024
1 parent 82fb5c5 commit de8660b
Show file tree
Hide file tree
Showing 12 changed files with 141 additions and 66 deletions.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added client/public/models/biomes-flat/grassland.glb
Binary file not shown.
4 changes: 2 additions & 2 deletions client/src/three/GameRenderer.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { SetupResult } from "@/dojo/setup";
import useUIStore, { AppStore } from "@/hooks/store/useUIStore";
import { SceneName } from "@/types";
import { GRAPHICS_SETTING, GraphicsSettings } from "@/ui/config";
import { GRAPHICS_SETTING, GraphicsSettings, IS_FLAT_MODE } from "@/ui/config";
import throttle from "lodash/throttle";
import {
BloomEffect,
Expand Down Expand Up @@ -87,7 +87,7 @@ export default class GameRenderer {
this.state = state;
});

this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 30);
this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, IS_FLAT_MODE ? 50 : 30);
const cameraHeight = Math.sin(this.cameraAngle) * this.cameraDistance;
const cameraDepth = Math.cos(this.cameraAngle) * this.cameraDistance;
this.camera.position.set(0, cameraHeight, cameraDepth);
Expand Down
2 changes: 1 addition & 1 deletion client/src/three/helpers/GUIManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import GUI from "lil-gui";
import { env } from "../../../env";

export const GUIManager = new GUI({
autoPlace: env.VITE_PUBLIC_DEV == true && !IS_MOBILE,
autoPlace: env.VITE_PUBLIC_GRAPHICS_DEV == true && !IS_MOBILE,
});

GUIManager.close();
31 changes: 21 additions & 10 deletions client/src/three/scenes/HexagonScene.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { type SetupResult } from "@/dojo/setup";
import useUIStore, { type AppStore } from "@/hooks/store/useUIStore";
import { type HexPosition, type SceneName } from "@/types";
import { GRAPHICS_SETTING, GraphicsSettings, IS_FLAT_MODE } from "@/ui/config";
import { LeftView } from "@/ui/modules/navigation/LeftNavigationModule";
import { RightView } from "@/ui/modules/navigation/RightNavigationModule";
import { getWorldPositionForHex } from "@/ui/utils/utils";
Expand Down Expand Up @@ -66,7 +67,9 @@ export abstract class HexagonScene {
this.scene.background = new THREE.Color(0x8790a1);
this.state = useUIStore.getState();
this.fog = new THREE.Fog(0xffffff, 21, 30);
this.scene.fog = this.fog;
if (!IS_FLAT_MODE && GRAPHICS_SETTING === GraphicsSettings.HIGH) {
this.scene.fog = this.fog;
}

// subscribe to state changes
useUIStore.subscribe(
Expand Down Expand Up @@ -311,19 +314,22 @@ export abstract class HexagonScene {

public moveCameraToXYZ(x: number, y: number, z: number, duration: number = 2) {
const newTarget = new THREE.Vector3(x, y, z);

const target = this.controls.target;
const pos = this.controls.object.position;

// go to new target but keep same view angle
const deltaX = newTarget.x - target.x;
const deltaZ = newTarget.z - target.z;

const newPosition = IS_FLAT_MODE
? new THREE.Vector3(newTarget.x, pos.y, newTarget.z)
: new THREE.Vector3(pos.x + deltaX, pos.y, pos.z + deltaZ);

if (duration) {
this.cameraAnimate(new THREE.Vector3(pos.x + deltaX, pos.y, pos.z + deltaZ), newTarget, duration);
this.cameraAnimate(newPosition, newTarget, duration);
} else {
target.set(newTarget.x, newTarget.y, newTarget.z);
pos.set(pos.x + deltaX, pos.y, pos.z + deltaZ);
target.copy(newTarget);
pos.copy(newPosition);
}

this.controls.update();
}

Expand All @@ -338,11 +344,16 @@ export abstract class HexagonScene {
// go to new target with but keep same view angle
const deltaX = newTarget.x - target.x;
const deltaZ = newTarget.z - target.z;

const newPosition = IS_FLAT_MODE
? new THREE.Vector3(newTarget.x, pos.y, newTarget.z)
: new THREE.Vector3(pos.x + deltaX, pos.y, pos.z + deltaZ);

if (duration) {
this.cameraAnimate(new THREE.Vector3(pos.x + deltaX, pos.y, pos.z + deltaZ), newTarget, duration);
this.cameraAnimate(newPosition, newTarget, duration);
} else {
target.set(newTarget.x, newTarget.y, newTarget.z);
pos.set(pos.x + deltaX, pos.y, pos.z + deltaZ);
target.copy(newTarget);
pos.copy(newPosition);
}
this.controls.update();
}
Expand Down
12 changes: 9 additions & 3 deletions client/src/three/scenes/Hexception.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { SetupResult } from "@/dojo/setup";
import useUIStore from "@/hooks/store/useUIStore";
import { HexPosition, ResourceMiningTypes, SceneName } from "@/types";
import { Position } from "@/types/Position";
import { IS_FLAT_MODE } from "@/ui/config";
import { ResourceIcon } from "@/ui/elements/ResourceIcon";
import { LeftView } from "@/ui/modules/navigation/LeftNavigationModule";
import {
Expand Down Expand Up @@ -271,7 +272,7 @@ export default class HexceptionScene extends HexagonScene {

this.removeCastleFromScene();
this.updateHexceptionGrid(this.hexceptionRadius);
this.controls.maxDistance = 18;
this.controls.maxDistance = IS_FLAT_MODE ? 36 : 18;
this.controls.enablePan = false;
this.controls.zoomToCursor = false;

Expand Down Expand Up @@ -540,6 +541,7 @@ export default class HexceptionScene extends HexagonScene {
this.pillars!.setColorAt(index + pillarOffset, BIOME_COLORS[biome as BiomeType]);
});
pillarOffset += matrices.length;
this.pillars!.position.y = -0.01;
this.pillars!.count = pillarOffset;
this.pillars!.computeBoundingSphere();
hexMesh.setCount(matrices.length);
Expand Down Expand Up @@ -670,12 +672,16 @@ export default class HexceptionScene extends HexagonScene {
positions.forEach((position) => {
dummy.position.x = position.x;
dummy.position.z = position.z;
dummy.position.y = isMainHex || isFlat || position.isBorder ? 0 : position.y / 2;
dummy.position.y = isMainHex || isFlat || position.isBorder || IS_FLAT_MODE ? 0 : position.y / 2;
dummy.scale.set(HEX_SIZE, HEX_SIZE, HEX_SIZE);
const rotationSeed = this.hashCoordinates(position.col, position.row);
const rotationIndex = Math.floor(rotationSeed * 6);
const randomRotation = (rotationIndex * Math.PI) / 3;
dummy.rotation.y = randomRotation;
if (!IS_FLAT_MODE) {
dummy.rotation.y = randomRotation;
} else {
dummy.rotation.y = 0;
}
dummy.updateMatrix();
biomeHexes[biome].push(dummy.matrix.clone());
});
Expand Down
70 changes: 42 additions & 28 deletions client/src/three/scenes/Worldmap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { LoadingStateKey } from "@/hooks/store/useWorldLoading";
import { soundSelector } from "@/hooks/useUISound";
import { HexPosition, SceneName } from "@/types";
import { Position } from "@/types/Position";
import { FELT_CENTER, IS_MOBILE } from "@/ui/config";
import { FELT_CENTER, IS_FLAT_MODE, IS_MOBILE } from "@/ui/config";
import { UNDEFINED_STRUCTURE_ENTITY_ID } from "@/ui/constants";
import { LeftView } from "@/ui/modules/navigation/LeftNavigationModule";
import { getWorldPositionForHex } from "@/ui/utils/utils";
Expand Down Expand Up @@ -369,7 +369,7 @@ export default class WorldmapScene extends HexagonScene {
}

setup() {
this.controls.maxDistance = 20;
this.controls.maxDistance = IS_FLAT_MODE ? 40 : 20;
this.controls.enablePan = true;
this.controls.zoomToCursor = true;
this.moveCameraToURLLocation();
Expand Down Expand Up @@ -428,10 +428,14 @@ export default class WorldmapScene extends HexagonScene {
dummy.scale.set(HEX_SIZE, HEX_SIZE, HEX_SIZE);
}

const rotationSeed = this.hashCoordinates(col, row);
const rotationIndex = Math.floor(rotationSeed * 6);
const randomRotation = (rotationIndex * Math.PI) / 3;
dummy.rotation.y = randomRotation;
if (!IS_FLAT_MODE) {
const rotationSeed = this.hashCoordinates(col, row);
const rotationIndex = Math.floor(rotationSeed * 6);
const randomRotation = (rotationIndex * Math.PI) / 3;
dummy.rotation.y = randomRotation;
} else {
dummy.rotation.y = 0;
}

const biomePosition = new Position({ x: col, y: row }).getContract();
const biome = this.biome.getBiome(biomePosition.x, biomePosition.y);
Expand Down Expand Up @@ -483,6 +487,23 @@ export default class WorldmapScene extends HexagonScene {
this.removeCachedMatricesAroundColRow(renderedChunkCenterCol, renderedChunkCenterRow);
}

getChunksAround(chunkKey: string) {
const startRow = parseInt(chunkKey.split(",")[0]);
const startCol = parseInt(chunkKey.split(",")[1]);
const chunks: string[] = [];
for (let i = -this.renderChunkSize.width / 2; i <= this.renderChunkSize.width / 2; i += this.chunkSize) {
for (let j = -this.renderChunkSize.width / 2; j <= this.renderChunkSize.height / 2; j += this.chunkSize) {
const { x, y, z } = getWorldPositionForHex({ row: startRow + i, col: startCol + j });
const { chunkX, chunkZ } = this.worldToChunkCoordinates(x, z);
const _chunkKey = `${chunkZ * this.chunkSize},${chunkX * this.chunkSize}`;
if (!chunks.includes(_chunkKey)) {
chunks.push(_chunkKey);
}
}
}
return chunks;
}

removeCachedMatricesAroundColRow(col: number, row: number) {
for (let i = -this.renderChunkSize.width / 2; i <= this.renderChunkSize.width / 2; i += 10) {
for (let j = -this.renderChunkSize.width / 2; j <= this.renderChunkSize.height / 2; j += 10) {
Expand Down Expand Up @@ -547,6 +568,7 @@ export default class WorldmapScene extends HexagonScene {
async updateHexagonGrid(startRow: number, startCol: number, rows: number, cols: number) {
await Promise.all(this.modelLoadPromises);
if (this.applyCachedMatricesForChunk(startRow, startCol)) {
console.log("cache applied");
this.computeInteractiveHexes(startRow, startCol, rows, cols);
return;
}
Expand Down Expand Up @@ -577,7 +599,11 @@ export default class WorldmapScene extends HexagonScene {
const batchSize = 25; // Adjust batch size as needed
let currentIndex = 0;
let hashedTiles: string[] = [];

this.computeTileEntities(this.currentChunk);
this.getChunksAround(this.currentChunk).forEach((chunkKey) => {
console.log("chunkKey", chunkKey);
this.computeTileEntities(chunkKey);
});
const processBatch = async () => {
const endIndex = Math.min(currentIndex + batchSize, rows * cols);

Expand Down Expand Up @@ -620,7 +646,11 @@ export default class WorldmapScene extends HexagonScene {
const rotationSeed = this.hashCoordinates(startCol + col, startRow + row);
const rotationIndex = Math.floor(rotationSeed * 6);
const randomRotation = (rotationIndex * Math.PI) / 3;
dummy.rotation.y = randomRotation;
if (!IS_FLAT_MODE) {
dummy.rotation.y = randomRotation;
} else {
dummy.rotation.y = 0;
}

const biome = this.biome.getBiome(startCol + col + FELT_CENTER, startRow + row + FELT_CENTER);

Expand Down Expand Up @@ -648,8 +678,6 @@ export default class WorldmapScene extends HexagonScene {
}
this.cacheMatricesForChunk(startRow, startCol);
this.interactiveHexManager.renderHexes();

await this.computeTileEntities();
}
};

Expand All @@ -658,25 +686,11 @@ export default class WorldmapScene extends HexagonScene {
});
}

private async computeTileEntities() {
const cameraPosition = new THREE.Vector3();
cameraPosition.copy(this.controls.target);

const adjustedX = cameraPosition.x + (this.chunkSize * HEX_SIZE * Math.sqrt(3)) / 2;
const adjustedZ = cameraPosition.z + (this.chunkSize * HEX_SIZE * 1.5) / 3;

// Parse current chunk coordinates
const { chunkX, chunkZ } = this.worldToChunkCoordinates(adjustedX, adjustedZ);

const startCol = chunkX * this.chunkSize + FELT_CENTER;
const startRow = chunkZ * this.chunkSize + FELT_CENTER;

const { width } = this.renderChunkSize;
const range = width / 2;
private async computeTileEntities(chunkKey: string) {
const startCol = parseInt(chunkKey.split(",")[1]) + FELT_CENTER;
const startRow = parseInt(chunkKey.split(",")[0]) + FELT_CENTER;

// Create a unique key for this chunk range
const chunkKey = `${startCol - range},${startCol + range},${startRow - range},${startRow + range}`;
console.log({ chunkKey });
const range = this.chunkSize / 2;

// Skip if we've already fetched this chunk
if (this.fetchedChunks.has(chunkKey)) {
Expand Down
58 changes: 41 additions & 17 deletions client/src/three/scenes/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { HyperstructureTypesNames, ResourceMiningTypes } from "@/types";
import { IS_FLAT_MODE } from "@/ui/config";
import { BuildingType, RealmLevelNames, RealmLevels, ResourcesIds, StructureType } from "@bibliothecadao/eternum";
import * as THREE from "three";
import { BiomeType } from "../components/Biome";
Expand Down Expand Up @@ -76,24 +77,47 @@ export const buildingModelPaths: Record<
};

const BASE_PATH = "/models/biomes-opt/";
const FLAT_PATH = "/models/biomes-flat-opt/";
const MODELS_PATH = IS_FLAT_MODE ? FLAT_PATH : BASE_PATH;

export enum BiomeFilenames {
Bare = "bare.glb",
Beach = "beach.glb",
TemperateDeciduousForest = "deciduousForest.glb",
DeepOcean = "deepOcean.glb",
Grassland = "grassland.glb",
Ocean = "ocean.glb",
Outline = "outline.glb",
Scorched = "scorched.glb",
Tundra = "tundra.glb",
TemperateDesert = "temperateDesert.glb",
Shrubland = "shrubland.glb",
Snow = "snow.glb",
Taiga = "taiga.glb",
TemperateRainForest = "temperateRainforest.glb",
SubtropicalDesert = "subtropicalDesert.glb",
TropicalRainForest = "tropicalRainforest.glb",
TropicalSeasonalForest = "tropicalSeasonalForest.glb",
}

export const biomeModelPaths: Record<BiomeType | "Outline", string> = {
Bare: BASE_PATH + "bare.glb",
Beach: BASE_PATH + "beach.glb",
TemperateDeciduousForest: BASE_PATH + "deciduousForest.glb",
DeepOcean: BASE_PATH + "deepOcean.glb",
Grassland: BASE_PATH + "grassland.glb",
Ocean: BASE_PATH + "ocean.glb",
Outline: BASE_PATH + "outline.glb",
Scorched: BASE_PATH + "scorched.glb",
Tundra: BASE_PATH + "tundra.glb",
TemperateDesert: BASE_PATH + "temperateDesert.glb",
Shrubland: BASE_PATH + "shrubland.glb",
Snow: BASE_PATH + "snow.glb",
Taiga: BASE_PATH + "taiga.glb",
TemperateRainForest: BASE_PATH + "temperateRainforest.glb",
SubtropicalDesert: BASE_PATH + "subtropicalDesert.glb",
TropicalRainForest: BASE_PATH + "tropicalRainforest.glb",
TropicalSeasonalForest: BASE_PATH + "tropicalSeasonalForest.glb",
Bare: MODELS_PATH + BiomeFilenames.Grassland,
Beach: MODELS_PATH + BiomeFilenames.Grassland,
TemperateDeciduousForest: MODELS_PATH + BiomeFilenames.Grassland,
DeepOcean: MODELS_PATH + BiomeFilenames.Grassland,
Grassland: MODELS_PATH + BiomeFilenames.Grassland,
Ocean: MODELS_PATH + BiomeFilenames.Grassland,
Outline: BASE_PATH + BiomeFilenames.Outline,
Scorched: MODELS_PATH + BiomeFilenames.Grassland,
Tundra: MODELS_PATH + BiomeFilenames.TemperateDeciduousForest,
TemperateDesert: MODELS_PATH + BiomeFilenames.TemperateDeciduousForest,
Shrubland: MODELS_PATH + BiomeFilenames.TemperateDeciduousForest,
Snow: MODELS_PATH + BiomeFilenames.TemperateDeciduousForest,
Taiga: MODELS_PATH + BiomeFilenames.TemperateDeciduousForest,
TemperateRainForest: MODELS_PATH + BiomeFilenames.TemperateDeciduousForest,
SubtropicalDesert: MODELS_PATH + BiomeFilenames.TemperateDeciduousForest,
TropicalRainForest: MODELS_PATH + BiomeFilenames.TemperateDeciduousForest,
TropicalSeasonalForest: MODELS_PATH + BiomeFilenames.TemperateDeciduousForest,
};

export const PROGRESS_HALF_THRESHOLD = 50;
Expand Down
10 changes: 8 additions & 2 deletions client/src/ui/config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export { FELT_CENTER };
export enum GraphicsSettings {
LOW = "LOW",
MID = "MID",
HIGH = "HIGH"
HIGH = "HIGH",
}

const checkGraphicsSettings = async () => {
Expand Down Expand Up @@ -40,10 +40,16 @@ const checkGraphicsSettings = async () => {
}
}

return localStorage.getItem("GRAPHICS_SETTING") as GraphicsSettings || GraphicsSettings.HIGH;
return (localStorage.getItem("GRAPHICS_SETTING") as GraphicsSettings) || GraphicsSettings.HIGH;
};

const getFlatMode = () => {
const flatMode = localStorage.getItem("FLAT_MODE");
return flatMode === null ? false : flatMode === "true";
};

export const GRAPHICS_SETTING = await checkGraphicsSettings();
export const IS_FLAT_MODE = getFlatMode();

export const IS_MOBILE = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);

Expand Down
Loading

0 comments on commit de8660b

Please sign in to comment.