Skip to content

Commit 2c34487

Browse files
feat: add ktx2 compression and other fixes
1 parent 49e55cb commit 2c34487

35 files changed

Lines changed: 841 additions & 203 deletions

examples/cornhole/cornhole.js

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,18 @@
11
import '@/css/base.css';
22
import './cornhole.css';
33

4-
import { CourseKeyboardControls, MeshLoader, ShotPerspectiveCamera, THREE, UIStats, VolumetricClouds, app, generateSetupData } from '@opengolfsim/fuse';
4+
import {
5+
CourseKeyboardControls,
6+
MeshLoader,
7+
ShotPerspectiveCamera,
8+
THREE,
9+
UIMainMenu,
10+
UIStats,
11+
VolumetricClouds,
12+
app,
13+
generateSetupData,
14+
UILoadingScreen
15+
} from '@opengolfsim/fuse';
516
import { Water } from 'three/examples/jsm/Addons.js';
617
import groundBeachModel from './models/GroundBeach.glb?url';
718
import cornHoleBoardModel from './models/CornHoleBoard.glb?url';
@@ -25,7 +36,6 @@ const textureLoader = new THREE.TextureLoader();
2536

2637
const gameContext = {
2738
timer: new THREE.Timer(),
28-
meshLoader: new MeshLoader(),
2939
aimPoint: new THREE.Vector3(0, 0, -10),
3040
startPoint: new THREE.Vector3(0, 0.25, 0),
3141
round: {
@@ -434,8 +444,8 @@ function startRound() {
434444
console.log(`Round ${gameContext.round.number}${first} throws all 4, then ${second}`);
435445
}
436446

437-
async function loadGame() {
438-
gameContext.timer.connect(document);
447+
async function setupGame() {
448+
439449
const boardOffset = window.localStorage.getItem('boardOffset') || 0;
440450
if (boardOffset) {
441451
boardZOffset = parseFloat(boardOffset);
@@ -455,15 +465,18 @@ async function loadGame() {
455465
if (gameContext.camera) gameContext.camera.aimKeys = aimKeys;
456466
});
457467
gameContext.controls.on('toggleStats', () => gameContext.stats?.toggle());
458-
gameContext.controls.on('testShot', shot => launchShot(shot));
468+
gameContext.controls.on('testShot', shot => {
469+
launchShot({ ballSpeed: 12 + (Math.random() * 2), verticalLaunchAngle: 35, horizontalLaunchAngle: -5 + (Math.random() * 10) });
470+
});
459471

460472
gameContext.renderer = new THREE.WebGLRenderer({ canvas: document.getElementById('canvas'), antialias: true });
461473
gameContext.renderer.setSize(window.innerWidth, window.innerHeight);
462474
gameContext.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 1.5));
463475
gameContext.renderer.shadowMap.enabled = true;
464476
gameContext.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
465477

466-
478+
gameContext.meshLoader = new MeshLoader(gameContext.renderer);
479+
467480
// window.addEventListener('resize', () => {
468481
// if (gameContext.camera) {
469482
// gameContext.camera.aspect = window.innerWidth / window.innerHeight;
@@ -492,6 +505,8 @@ async function loadGame() {
492505

493506
gameContext.camera?.setPositions(gameContext.startPoint, gameContext.aimPoint);
494507
createSky();
508+
509+
495510
await loadGameBoards();
496511
await loadModels();
497512

@@ -516,9 +531,22 @@ async function loadGame() {
516531
gameContext.scene.add(debugLines);
517532
}
518533

534+
gameContext.mainMenu = new UIMainMenu('#top-left');
535+
gameContext.mainMenu.on('exit', () => app.exit())
536+
}
519537

520-
gameContext.clock.start();
521-
requestAnimationFrame(animate);
538+
function loadGame() {
539+
gameContext.timer.connect(document);
540+
541+
gameContext.loadingScreen = new UILoadingScreen(document.body, { loadingPrefix: 'Filling the bags' });
542+
gameContext.loadingScreen.on('load', () => {
543+
gameContext.clock.start();
544+
requestAnimationFrame(animate);
545+
});
546+
gameContext.loadingScreen.load(setupGame);
547+
548+
549+
// requestAnimationFrame(animate);
522550
}
523551

524552
function getActiveBag() {

examples/cornhole/index.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33
<head>
44
<meta charset="UTF-8">
55
<title>Cornhole</title>
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
7+
<script type="module" src="./cornhole.js"></script>
68
</head>
79
<body>
810

911
<canvas id="canvas"></canvas>
1012

13+
<div id="top-left"></div>
1114
<div id="top-center">
1215
<div class="distance-item">
1316
<span class="digit" id="board-distance">0</span>
@@ -36,6 +39,5 @@
3639
<div class="team-score" id="red-team-score">0</div>
3740
</div>
3841
</div>
39-
<script type="module" src="./cornhole.js"></script>
4042
</body>
4143
</html>

examples/courses/courses.ts

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { QualityMode } from '@/utils/constants';
1+
import { QualityMode } from '@/utils/quality';
22
import { type World } from '@dimforge/rapier3d-compat';
33
import {
44
THREE,
@@ -18,10 +18,12 @@ import {
1818
UILoadingScreen,
1919
VolumetricClouds,
2020
generateSetupData,
21+
UIMainMenu,
2122
} from '@opengolfsim/fuse';
2223

2324

2425
const gameContext: {
26+
isReady: boolean,
2527
startPoint: THREE.Vector3,
2628
aimPoint: THREE.Vector3,
2729
qualityLevel: QualityMode,
@@ -50,6 +52,7 @@ const gameContext: {
5052
shotData?: UIShotData,
5153
courseMap?: UICourseMap,
5254
playerMenu?: UIPlayerMenu,
55+
mainMenu?: UIMainMenu,
5356
loadingScreen?: UILoadingScreen,
5457
rangeFinder?: UIRangeFinder,
5558
stats?: UIStats,
@@ -58,6 +61,7 @@ const gameContext: {
5861
distanceToAim: number,
5962
heightToAim: number,
6063
} = {
64+
isReady: false,
6165
timer: new THREE.Timer(),
6266
startPoint: new THREE.Vector3(0, 0, 0),
6367
aimPoint: new THREE.Vector3(0, 0, 0),
@@ -97,11 +101,14 @@ function setupNextShot() {
97101
gameContext.golfBall?.reset(gameContext.aimPoint, gameContext.startPoint);
98102

99103
aimPointUpdated(true);
100-
104+
105+
gameContext.clouds?.update();
106+
101107
gameContext.courseMap?.updatePosition(gameContext.startPoint, gameContext.game.pinPoint());
102108
gameContext.courseMap?.updateHole(gameContext.game.activeHole);
103109

104110
gameContext.playerMenu?.update(gameContext.game.activePlayer);
111+
105112
}
106113

107114
function setupRenderer() {
@@ -110,19 +117,29 @@ function setupRenderer() {
110117

111118
THREE.ColorManagement.enabled = true;
112119

113-
gameContext.renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
120+
app.sendMessage({ type: 'log', message: `qualityLevel: ${gameContext.qualityLevel}` });
121+
122+
gameContext.renderer = new THREE.WebGLRenderer({
123+
canvas,
124+
antialias: true // gameContext.qualityLevel >= QualityMode.Medium
125+
});
114126
gameContext.renderer.setSize(window.innerWidth, window.innerHeight);
115-
console.log('window.devicePixelRatio', Math.min(window.devicePixelRatio, 1));
116-
117-
let maxPixelRatio = 1;
127+
128+
let maxPixelRatio = Math.min(window.devicePixelRatio, 1);
118129
if (gameContext.qualityLevel >= QualityMode.High) {
119-
maxPixelRatio = 2;
130+
maxPixelRatio = Math.min(window.devicePixelRatio, 2);
120131
}
121-
gameContext.renderer.setPixelRatio(Math.min(window.devicePixelRatio, maxPixelRatio));
122-
gameContext.renderer.shadowMap.enabled = true;
132+
133+
app.sendMessage({ type: 'log', message: `maxPixelRatio: ${maxPixelRatio}` });
134+
135+
gameContext.renderer.setPixelRatio(maxPixelRatio);
136+
gameContext.renderer.shadowMap.enabled = gameContext.qualityLevel >= QualityMode.Medium;
123137
gameContext.renderer.shadowMap.type = THREE.PCFShadowMap;
124-
gameContext.renderer.toneMapping = THREE.ACESFilmicToneMapping; // or whatever you pick
125-
gameContext.renderer.toneMappingExposure = 1.0;
138+
139+
if (gameContext.qualityLevel >= QualityMode.Medium) {
140+
gameContext.renderer.toneMapping = THREE.ACESFilmicToneMapping; // or whatever you pick
141+
gameContext.renderer.toneMappingExposure = 1.0;
142+
}
126143

127144
}
128145

@@ -227,7 +244,8 @@ function adjustAimPoint(newPosition: THREE.Vector3) {
227244
newPosition.y = ground.y;
228245
}
229246
gameContext.aimPoint.copy(newPosition);
230-
gameContext.camera?.setPositions(gameContext.game.startPoint(), gameContext.aimPoint);
247+
gameContext.camera?.setPositions(gameContext.game.startPoint(), gameContext.aimPoint);
248+
231249
aimPointUpdated(true);
232250
}
233251

@@ -258,18 +276,25 @@ async function setupCourse() {
258276
if (!app.world) {
259277
throw new Error('Physics world does not exist');
260278
}
279+
261280
if (!gameContext?.setupData) {
262281
throw new Error('Missing setupData!');
263282
}
264283
if (!gameContext?.gameData?.courseUrl) {
265284
throw new Error('Missing a courseUrl to a GLB in the gameData object');
266285
}
286+
if (typeof gameContext.setupData?.qualityLevel !== 'undefined') {
287+
gameContext.qualityLevel = gameContext.setupData.qualityLevel;
288+
}
267289
setupRenderer();
268-
290+
if (!gameContext.renderer) {
291+
throw new Error('Missing renderer!');
292+
}
269293
// load course details and meshes
270294
gameContext.course = new CourseLoader(
271295
app.world,
272296
app.rapier,
297+
gameContext.renderer,
273298
{
274299
setupData: gameContext.setupData,
275300
manager: gameContext.loadingScreen?.manager
@@ -305,6 +330,9 @@ async function setupCourse() {
305330

306331
gameContext.shotData = new UIShotData('#shot-data', { units: gameContext.setupData?.units });
307332
gameContext.rangeFinder = new UIRangeFinder('#top-center', { units: gameContext.setupData?.units });
333+
gameContext.mainMenu = new UIMainMenu('#top-left');
334+
gameContext.mainMenu.on('exit', () => app.exit())
335+
308336
gameContext.playerMenu = new UIPlayerMenu('#top-left', { players: gameContext.game?.players || [] });
309337
gameContext.playerMenu.on('selectPlayer', player => {
310338
// handle player changed
@@ -339,8 +367,8 @@ function preLoad() {
339367
// }
340368
// allow override with query param
341369
const qualityParam = (new URLSearchParams(window.location.search)).get('quality');
342-
if (gameContext.setupData && qualityParam) {
343-
gameContext.setupData.qualityLevel = parseInt(qualityParam, 10);
370+
if (qualityParam) {
371+
gameContext.qualityLevel = parseInt(qualityParam, 10);
344372
}
345373

346374
console.log('[debug] Setup Data', gameContext.setupData);
@@ -349,10 +377,11 @@ function preLoad() {
349377
gameContext.stats = new UIStats('#render-stats', { hidden: false, renderer: gameContext.renderer }); // start hidden (press S to toggle)
350378
if (!error) {
351379
requestAnimationFrame(animate);
380+
gameContext.isReady = true;
352381
}
353382
});
354383
gameContext.loadingScreen.load(setupCourse);
355-
384+
document.body.style.opacity = '1';
356385
gameContext.timer.connect(document);
357386
}
358387

@@ -372,7 +401,9 @@ function animate(animDelta: number) {
372401
gameContext.controls?.update(delta);
373402
gameContext.clouds?.update(delta);
374403

375-
if (gameContext.camera) gameContext.course?.update(delta, gameContext.camera);
404+
if (gameContext.camera && gameContext.isReady) {
405+
gameContext.course?.update(delta, gameContext.camera, gameContext.golfBall?.isShotActive);
406+
}
376407

377408
gameContext.game?.update(delta);
378409

examples/courses/index.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
<!DOCTYPE html>
22
<html>
33
<head>
4+
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
45
<title>Fuse Course</title>
56
</head>
6-
<body>
7+
<body style="opacity: 0">
78
<canvas id="canvas"></canvas>
89

910
<div id="top-left"></div>

examples/range/index.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
<html>
33
<head>
44
<link rel="stylesheet" type="text/css" href="../../src/css/base.css" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
56
<title>Fuse Range</title>
67
</head>
7-
<body>
8+
<body style="opacity: 0">
89

910
<canvas id="canvas"></canvas>
1011

0 commit comments

Comments
 (0)