Skip to content

Commit 17c35ed

Browse files
committed
Add pro meshes for surfaces in all camera views
1 parent fb02edc commit 17c35ed

File tree

16 files changed

+379
-53
lines changed

16 files changed

+379
-53
lines changed

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ using modern web technologies.
6565
- Orange smoke column above lava tiles missing
6666
- Add tiny rockies running around after crumbling
6767
- Two buttons in priority list can be hovered/pressed/released at the same time
68-
- Use pro-meshes to render high-detail walls in first person and shoulder view
6968
- Middle wheel meshes of small digger do not rotate after engine upgrade
7069
- When switching fast from one level to another in level selection no level name is shown, but the level is highlighted
7170

src/game/LevelLoader.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export interface LevelConfData {
1515
fullName: string
1616
generateSpiders: boolean
1717
video: string
18+
meshBasename: string
1819
textureBasename: string
1920
roofTexture: string
2021
rockFallStyle: RockFallStyle
@@ -72,6 +73,7 @@ export class LevelLoader {
7273
video: levelConf.video,
7374
mapWidth: terrainMap.width,
7475
mapHeight: terrainMap.height,
76+
meshBasename: textureSet.meshBasename,
7577
textureBasename: textureSet.textureBasename,
7678
roofTexture: textureSet.roofTexture,
7779
rockFallStyle: rockFallStyle,

src/game/SceneManager.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ export class SceneManager implements Updatable {
8787
EventBroker.subscribe(EventKey.BUILDINGS_CHANGED, () => {
8888
this.setBuildModeSelection(undefined) // TODO Check dependencies precisely
8989
})
90+
EventBroker.subscribe(EventKey.COMMAND_CHANGE_PREFERENCES, (event) => {
91+
this.terrain.forEachSurface((s) => s.mesh.setProMeshEnabled(SaveGameManager.preferences.wallDetails))
92+
})
9093
}
9194

9295
setActiveCamera(camera: PerspectiveCamera) {
@@ -135,10 +138,8 @@ export class SceneManager implements Updatable {
135138
this.setBuildModeSelection(undefined)
136139

137140
this.floorGroup = new Group()
138-
this.floorGroup.scale.setScalar(TILESIZE)
139141
this.roofGroup = new Group()
140142
this.roofGroup.visible = false
141-
this.roofGroup.scale.setScalar(TILESIZE)
142143
this.terrain = TerrainLoader.loadTerrain(levelConf, this.worldMgr)
143144
this.terrain.forEachSurface((s) => {
144145
this.floorGroup.add(s.mesh)

src/game/TerrainLoader.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ export class TerrainLoader {
8383
case SurfaceType.LAVA5:
8484
// fallthrough
8585
case SurfaceType.WATER:
86-
worldMgr.ecs.addComponent(surface.entity, new FluidSurfaceComponent(surface.x, surface.y, surface.mesh.geometry.attributes.uv))
86+
worldMgr.ecs.addComponent(surface.entity, new FluidSurfaceComponent(surface.x, surface.y, surface.mesh.lowMesh.geometry.attributes.uv))
8787
break
8888
case SurfaceType.SLUG_HOLE:
8989
terrain.slugHoles.add(surface)

src/game/model/building/BuildPlacementMarkerMesh.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ import { BufferGeometry, Mesh, MeshPhongMaterial, Vector2 } from 'three'
22
import { TILESIZE } from '../../../params'
33
import { SceneManager } from '../../SceneManager'
44
import { Surface } from '../../terrain/Surface'
5+
import { SurfaceMesh } from '../../terrain/SurfaceMesh'
56

67
export class BuildPlacementMarkerMesh extends Mesh<BufferGeometry, MeshPhongMaterial> {
78
sceneMgr: SceneManager
8-
lastSurfaceMesh?: Mesh
9+
lastSurfaceMesh?: SurfaceMesh
910

1011
constructor(sceneMgr: SceneManager) {
1112
super(new BufferGeometry(), new MeshPhongMaterial({
@@ -28,7 +29,7 @@ export class BuildPlacementMarkerMesh extends Mesh<BufferGeometry, MeshPhongMate
2829
this.position.copy(surfaceMesh.position.clone().multiplyScalar(TILESIZE))
2930
this.position.y += TILESIZE / 20
3031
this.geometry?.dispose()
31-
this.geometry = surfaceMesh.geometry.clone()
32+
this.geometry = surfaceMesh.lowMesh.geometry.clone()
3233
}
3334

3435
setColor(hexColor: number) {

src/game/system/LaserShotSystem.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ export class LaserShotSystem extends AbstractGameSystem {
8888
this.worldMgr.sceneMgr.addPositionalAudio(soundParent, 'SFX_LaserHit', false)
8989
this.worldMgr.sceneMgr.addMiscAnim(GameConfig.instance.miscObjects.boulderExplode, rockyIntersection.point, PRNG.animation.random() * 2 * Math.PI, false)
9090
} else {
91-
const floorIntersection = this.raycaster.intersectObjects<SurfaceMesh>(this.worldMgr.sceneMgr.floorGroup.children, false)[0]
91+
const floorIntersection = this.raycaster.intersectObjects<SurfaceMesh>(this.worldMgr.sceneMgr.floorGroup.children, true)[0]
9292
if (floorIntersection) {
9393
beamLength = floorIntersection.distance
9494
const surface = floorIntersection.object.userData.selectable

src/game/terrain/Surface.ts

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { BackSide, Raycaster, Vector2, Vector3 } from 'three'
1+
import { Raycaster, Vector2, Vector3 } from 'three'
22
import { SoundManager } from '../../audio/SoundManager'
33
import { DeselectAll, SelectionChanged, UpdateRadarSurface, UpdateRadarTerrain } from '../../event/LocalEvents'
44
import { CavernDiscovered, JobCreateEvent, OreFoundEvent, WorldLocationEvent } from '../../event/WorldEvents'
@@ -13,7 +13,7 @@ import { DrillJob } from '../model/job/surface/DrillJob'
1313
import { ReinforceJob } from '../model/job/surface/ReinforceJob'
1414
import { GameEntity } from '../ECS'
1515
import { SurfaceVertex } from './SurfaceGeometry'
16-
import { SurfaceMesh } from './SurfaceMesh'
16+
import { RoofMesh, SurfaceMesh } from './SurfaceMesh'
1717
import { SurfaceType } from './SurfaceType'
1818
import { Terrain } from './Terrain'
1919
import { WALL_TYPE, WallType } from './WallType'
@@ -34,6 +34,8 @@ import { PRNG } from '../factory/PRNG'
3434
import { GameState } from '../model/GameState'
3535
import { CompleteSurfaceJob } from '../model/job/surface/CompleteSurfaceJob'
3636
import { MaterialEntity } from '../model/material/MaterialEntity'
37+
import { ResourceManager } from '../../resource/ResourceManager'
38+
import { SaveGameManager } from '../../resource/SaveGameManager'
3739

3840
export class Surface {
3941
readonly worldMgr: WorldManager
@@ -53,7 +55,7 @@ export class Surface {
5355
drillProgress: number = 0
5456

5557
readonly mesh: SurfaceMesh
56-
readonly roofMesh: SurfaceMesh
58+
readonly roofMesh: RoofMesh
5759
wallType: WallType = WALL_TYPE.floor
5860
needsMeshUpdate: boolean = false
5961

@@ -83,15 +85,10 @@ export class Surface {
8385
this.rubblePositions = [this.getRandomPosition(), this.getRandomPosition(), this.getRandomPosition(), this.getRandomPosition()]
8486
break
8587
}
86-
// TODO Use pro meshes for high wall details in FPV
87-
// const proMesh = ResourceManager.getLwoModel(this.terrain.textureSet.meshBasename + '01b.lwo')
88-
// proMesh.position.copy(this.mesh.position)
89-
// proMesh.scale.setScalar(1 / TILESIZE)
90-
// this.terrain.floorGroup.add(proMesh)
9188
this.mesh = new SurfaceMesh(x, y, {selectable: this, surface: this})
92-
this.roofMesh = new SurfaceMesh(x, y, {})
93-
this.roofMesh.material.side = BackSide
94-
this.roofMesh.position.y = 3
89+
this.mesh.setProMeshEnabled(SaveGameManager.preferences.wallDetails)
90+
const roofTexture = ResourceManager.getSurfaceTexture(this.terrain.levelConf.roofTexture, 0) ?? null // TODO Move to config handling
91+
this.roofMesh = new RoofMesh(x, y, roofTexture)
9592
}
9693

9794
private updateObjectName() {
@@ -143,7 +140,7 @@ export class Surface {
143140
case SurfaceType.LAVA5:
144141
// fallthrough
145142
case SurfaceType.WATER:
146-
this.worldMgr.ecs.addComponent(this.entity, new FluidSurfaceComponent(this.x, this.y, this.mesh.geometry.attributes.uv))
143+
this.worldMgr.ecs.addComponent(this.entity, new FluidSurfaceComponent(this.x, this.y, this.mesh.lowMesh.geometry.attributes.uv))
147144
break
148145
case SurfaceType.HIDDEN_CAVERN:
149146
this.surfaceType = SurfaceType.GROUND
@@ -351,7 +348,7 @@ export class Surface {
351348
this.terrain.pathFinder.updateSurface(this)
352349
}
353350

354-
private getVertex(x: number, y: number, s1: Surface, s2: Surface, s3: Surface): SurfaceVertex {
351+
getVertex(x: number, y: number, s1: Surface, s2: Surface, s3: Surface): SurfaceVertex {
355352
const high = [this, s1, s2, s3].some((s) => !s.discovered) || ![this, s1, s2, s3].some((s) => s.surfaceType.floor)
356353
const minSeamProgress = Math.min(this.getSeamProgress(), s1.getSeamProgress(), s2.getSeamProgress(), s3.getSeamProgress())
357354
const offset = this.terrain.getHeightOffset(x, y)
@@ -365,9 +362,9 @@ export class Surface {
365362
private updateWallType(topLeft: SurfaceVertex, topRight: SurfaceVertex, bottomRight: SurfaceVertex, bottomLeft: SurfaceVertex) {
366363
let wallType: WallType = Surface.getWallType(topLeft.high, topRight.high, bottomRight.high, bottomLeft.high)
367364
if (wallType === WALL_TYPE.wall && topLeft.high === bottomRight.high) wallType = WALL_TYPE.weirdCrevice
368-
this.wallType = wallType
365+
this.wallType = wallType // TODO Update wall type only when necessary
369366
this.mesh.setHeights(wallType, topLeft, topRight, bottomRight, bottomLeft)
370-
this.roofMesh.setHeights(wallType, topLeft.flipY(), topRight.flipY(), bottomRight.flipY(), bottomLeft.flipY())
367+
this.roofMesh.setHeights(wallType, topLeft, topRight, bottomRight, bottomLeft)
371368
if (this.wallType !== WALL_TYPE.wall) this.cancelReinforceJobs()
372369
if (this.wallType < WALL_TYPE.wall) this.worldMgr.ecs.removeComponent(this.entity, EmergeComponent)
373370
}
@@ -427,7 +424,9 @@ export class Surface {
427424
}
428425
const textureFilepath = this.terrain.levelConf.textureBasename + suffix + '.bmp'
429426
this.mesh.setTexture(textureFilepath, rotation)
430-
this.roofMesh.setTexture(this.terrain.levelConf.roofTexture, rotation)
427+
const proMeshSuffix = suffix.startsWith('1') ? '10' : suffix
428+
const proMeshFilepath = (this.terrain.levelConf.meshBasename + proMeshSuffix).toLowerCase()
429+
this.mesh.updateProMesh(proMeshFilepath)
431430
}
432431

433432
private determinePowerPathTextureNameSuffixAndRotation(rotation: number, suffix: string) {
@@ -480,7 +479,7 @@ export class Surface {
480479
select(): boolean {
481480
if (!this.isSelectable()) return false
482481
this.selected = true
483-
this.mesh.setHighlightColor(0x6060a0)
482+
this.setHighlightColor(0x6060a0)
484483
if (this.surfaceType.floor) SoundManager.playSfxSound('SFX_Floor')
485484
else if (this.surfaceType.shaping) SoundManager.playSfxSound('SFX_Wall')
486485
if (DEV_MODE) console.log(`Surface selected ${this.x}/${this.y}`, this)
@@ -502,7 +501,11 @@ export class Surface {
502501
} else if (this.drillJob) {
503502
color = 0xa0a0a0
504503
}
505-
this.mesh.setHighlightColor(color)
504+
this.setHighlightColor(color)
505+
}
506+
507+
setHighlightColor(hex: number) {
508+
this.mesh.setHighlightColor(hex)
506509
}
507510

508511
hasRubble(): boolean {
@@ -595,7 +598,7 @@ export class Surface {
595598
const wasPath = this.surfaceType === SurfaceType.POWER_PATH || this.surfaceType === SurfaceType.POWER_PATH_BUILDING
596599
this.surfaceType = surfaceType
597600
if (this.surfaceType === SurfaceType.WATER || this.surfaceType === SurfaceType.LAVA5) {
598-
this.worldMgr.ecs.addComponent(this.entity, new FluidSurfaceComponent(this.x, this.y, this.mesh.geometry.attributes.uv))
601+
this.worldMgr.ecs.addComponent(this.entity, new FluidSurfaceComponent(this.x, this.y, this.mesh.lowMesh.geometry.attributes.uv))
599602
} else {
600603
this.worldMgr.ecs.removeComponent(this.entity, FluidSurfaceComponent)
601604
}

src/game/terrain/SurfaceGeometry.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { BufferGeometry, Vector2, Vector3 } from 'three'
22
import { BufferAttribute } from 'three/src/core/BufferAttribute'
33
import { WALL_TYPE, WallType } from './WallType'
4+
import { TILESIZE } from '../../params'
45

56
export class SurfaceGeometry extends BufferGeometry {
67
constructor() {
@@ -13,10 +14,10 @@ export class SurfaceGeometry extends BufferGeometry {
1314
setHeights(wallType: WallType, topLeft: SurfaceVertex, topRight: SurfaceVertex, bottomRight: SurfaceVertex, bottomLeft: SurfaceVertex) {
1415
const uvOffset = SurfaceGeometry.determineUvOffset(wallType, topLeft.high, bottomRight.high, topRight.high, bottomLeft.high)
1516

16-
const topLeftVertex = new Vector3(0, topLeft.height, 0)
17-
const topRightVertex = new Vector3(1, topRight.height, 0)
18-
const bottomRightVertex = new Vector3(1, bottomRight.height, 1)
19-
const bottomLeftVertex = new Vector3(0, bottomLeft.height, 1)
17+
const topLeftVertex = new Vector3(0, topLeft.height, 0).multiplyScalar(TILESIZE)
18+
const topRightVertex = new Vector3(1, topRight.height, 0).multiplyScalar(TILESIZE)
19+
const bottomRightVertex = new Vector3(1, bottomRight.height, 1).multiplyScalar(TILESIZE)
20+
const bottomLeftVertex = new Vector3(0, bottomLeft.height, 1).multiplyScalar(TILESIZE)
2021

2122
const vertices: Vector3[] = []
2223
const normals: Vector3[] = []

0 commit comments

Comments
 (0)