Skip to content

Commit 49e55cb

Browse files
feat: bake static map image
1 parent 1c7111c commit 49e55cb

6 files changed

Lines changed: 157 additions & 114 deletions

File tree

examples/courses/courses.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,14 @@ async function setupScene() {
168168
gameContext.scene.add(gameContext.visualAimPoint.object);
169169

170170
// Course Map
171+
if (!gameContext.course.courseMap) {
172+
throw new Error('Must pass a map image');
173+
}
171174
gameContext.courseMap = new UICourseMap({
172175
units: gameContext.setupData?.units,
173-
holes: gameContext.course?.holes
176+
holes: gameContext.course?.holes,
177+
map: gameContext.course.courseMap,
178+
worldSize: gameContext.course.courseSize
174179
});
175180

176181
// Controls

examples/index.html

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,18 @@
2020
if (game.courseUrl) {
2121
uri += '?' + new URLSearchParams({ courseUrl: game.courseUrl});
2222
}
23+
const gameItemPoster = document.createElement('img');
24+
gameItemPoster.width = 160;
25+
gameItemPoster.height = 90;
26+
gameItemPoster.src = game.posterUrl;
27+
28+
const gameItemTitle = document.createElement('div');
29+
gameItemTitle.textContent = game.title;
30+
gameItemLink.append(gameItemPoster, gameItemTitle);
31+
32+
// gameItemLink.textContent = game.title;
33+
2334
gameItemLink.setAttribute('href', uri);
24-
gameItemLink.textContent = game.title;
2535
gameItem.append(gameItemLink);
2636
games.append(gameItem);
2737
});
@@ -82,6 +92,22 @@
8292
.section {
8393
margin-bottom: 3rem;
8494
}
95+
#game-list ul {
96+
list-style: none;
97+
display: flex;
98+
flex-direction: row;
99+
justify-content: space-between;
100+
flex-wrap: wrap;
101+
}
102+
#game-list ul li {
103+
104+
}
105+
#game-list ul li a img {
106+
margin-bottom: 10px;
107+
}
108+
#game-list ul li a {
109+
color: #fff;
110+
}
85111
</style>
86112
</head>
87113
<body>
@@ -110,21 +136,10 @@
110136

111137
<div class="section">
112138
<h3>Examples</h3>
113-
<p style="padding: 1rem; background-color: rgba(0, 200, 0, 0.2);">To use the examples: Press any number key (1-9) or the space bar to take a shot.</p>
114139

115140
<div id="game-list"></div>
116141

117-
<!-- <ul>
118-
<li>
119-
<a href="./range/">Driving Range</a>
120-
</li>
121-
<li>
122-
<a href="./courses/?courseUrl=https%3A%2F%2Fcoursedata.opengolfsim.com%2Fwebgl%2Fcourses%2Fmountain-vista%2Fv1%2Fmountain-vista-v1.1.glb">Mountain Vista 9-hole Course</a>
123-
</li>
124-
<li>
125-
<a href="./cornhole/">CornHole</a>
126-
</li>
127-
</ul> -->
142+
<p style="padding: 1rem; background-color: rgba(0, 200, 0, 0.2);">To use the examples: Press any number key (1-9) or the space bar to take a shot.</p>
128143
</div>
129144

130145
<div class="section">

public/games.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"description": "A basic driving range set in the mountains",
66
"url": "range/index.html",
77
"gameMode": 0,
8-
"posterUrl": "https://coursedata.opengolfsim.com/webgl/courses/mountain-vista/v1/mountain-vista.jpg",
8+
"posterUrl": "https://coursedata.opengolfsim.com/webgl/courses/posters/webgl-range-poster.jpg",
99
"slug": "fuse_range"
1010
},
1111
{
@@ -14,7 +14,7 @@
1414
"url": "courses/index.html",
1515
"gameMode": 2,
1616

17-
"courseUrl": "https://coursedata.opengolfsim.com/webgl/courses/mountain-vista/v1/mtn-vista-v1.2.glb",
17+
"courseUrl": "https://coursedata.opengolfsim.com/webgl/courses/mountain-vista/v1/mtn-vista-v1.4.glb",
1818
"posterUrl": "https://coursedata.opengolfsim.com/webgl/courses/mountain-vista/v1/mountain-vista-poster.jpg",
1919
"slug": "fuse_mtn_vista"
2020
},
@@ -23,7 +23,7 @@
2323
"description": "A beach themed cornhole game",
2424
"url": "cornhole/index.html",
2525
"gameMode": 1,
26-
"posterUrl": "https://coursedata.opengolfsim.com/webgl/courses/mountain-vista/v1/mountain-vista-poster.jpg",
26+
"posterUrl": "https://coursedata.opengolfsim.com/webgl/courses/posters/webgl-cornhole-poster.jpg",
2727
"slug": "fuse_cornhole"
2828
}
2929
]

src/courses/loader.ts

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ export class CourseLoader extends EventEmitter<CourseLoaderEvents> {
9292
surfaces: Map<string, LoadedCourseSurface>;
9393
grasses: Map<string, any>;
9494
greenGrids: Map<string, any>;
95-
95+
courseMap?: ImageBitmap;
96+
courseSize: number;
9697

9798
gltf?: GLTF;
9899
scene?: THREE.Group;
@@ -116,6 +117,7 @@ export class CourseLoader extends EventEmitter<CourseLoaderEvents> {
116117
this.rapier = rapier;
117118
this.meshLoader = new MeshLoader(options.manager);
118119
this.setupData = options.setupData || {};
120+
this.courseSize = 1000;
119121

120122
this.holes = new Map();
121123
this.waterSurfaces = new Map();
@@ -133,10 +135,17 @@ export class CourseLoader extends EventEmitter<CourseLoaderEvents> {
133135
async load(coursePath: string) {
134136
this.gltf = await this.meshLoader.gltfLoader.loadAsync(coursePath);
135137
this.scene = this.gltf.scene;
136-
this.sceneSettings = this.gltf.userData?.sceneSettings || {};
137-
138+
if (this.gltf.userData?.courseSize) {
139+
this.courseSize = this.gltf.userData.courseSize;
140+
} else {
141+
console.warn('Course missing world size! Defaulting to 1000');
142+
}
143+
this.sceneSettings = this.gltf.userData?.sceneSettings ?? {};
144+
console.log(' ---- Loaded course ----');
145+
console.dir(this.gltf.userData);
146+
console.log(' ---- ----');
147+
138148
this.golfCup = await this.meshLoader.load(golfCupModel, true);
139-
console.log('this.golfCup', this.golfCup);
140149

141150
// load the model + textures once during init
142151
this.grassAssets = await GrassShader.loadAssets({
@@ -151,6 +160,7 @@ export class CourseLoader extends EventEmitter<CourseLoaderEvents> {
151160
this._addCourseColliders();
152161
this._addWater();
153162
await this._addTrees();
163+
await this._parseMap();
154164

155165
// if (this.options.debug) {
156166
// this.debugLines = new THREE.LineSegments(
@@ -309,6 +319,21 @@ export class CourseLoader extends EventEmitter<CourseLoaderEvents> {
309319
// return treeGroup;
310320
// }
311321

322+
async _parseMap() {
323+
if (!this.gltf) {
324+
throw new Error('Course file not loaded');
325+
}
326+
const parser = this.gltf.parser;
327+
const courseMap = (parser.json?.images || []).find(
328+
(img: any) => img.extras?.type === 'course_map'
329+
);
330+
const buffer = await parser.getDependency('bufferView', courseMap.bufferView);
331+
const blob = new Blob([buffer], { type: 'image/jpeg' });
332+
const bitmap = await window.createImageBitmap(blob, { premultiplyAlpha: 'none' });
333+
this.courseMap = bitmap;
334+
console.log('courseMap', buffer);
335+
}
336+
312337
async _addTrees() {
313338
if (!this.scene) {
314339
throw new Error('Course scene not loaded');
@@ -331,7 +356,7 @@ export class CourseLoader extends EventEmitter<CourseLoaderEvents> {
331356

332357
this.planter = new TreePlanter({
333358
scene: this.scene,
334-
worldSize: 1000,
359+
worldSize: this.courseSize,
335360
qualityLevel: this.setupData?.qualityLevel,
336361
// groundMeshes: this.getGroundMeshes(),
337362
world: this.world,

0 commit comments

Comments
 (0)