@origingame/engine 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/og.mjs +1 -1
- package/dist/web/origin-engine.d.ts +255 -5
- package/dist/web/origin-engine.js +1584 -125
- package/dist/web/origin-engine_bg.wasm +0 -0
- package/dist/web/origin-engine_bg.wasm.d.ts +80 -3
- package/dist/web-publish/origin-engine-lanes.js +1288 -82
- package/dist/web-publish/origin-engine-lanes_bg.wasm +0 -0
- package/dist/web-publish/origin-engine.d.ts +199 -6
- package/dist/web-publish/origin-engine.js +1285 -79
- package/dist/web-publish/origin-engine_bg.wasm +0 -0
- package/dist/web-publish/origin-engine_bg.wasm.d.ts +65 -4
- package/dist/web-publish-2d/origin-engine-lanes.js +1285 -79
- package/dist/web-publish-2d/origin-engine-lanes_bg.wasm +0 -0
- package/dist/web-publish-2d/origin-engine.d.ts +198 -5
- package/dist/web-publish-2d/origin-engine.js +1282 -76
- package/dist/web-publish-2d/origin-engine_bg.wasm +0 -0
- package/dist/web-publish-2d/origin-engine_bg.wasm.d.ts +64 -3
- package/knowledge/README.md +2 -1
- package/knowledge/guides/three-to-og.md +393 -0
- package/knowledge/knowledge.json +2 -1
- package/knowledge/looks/catalogue.json +40 -40
- package/knowledge/package.json +3 -2
- package/knowledge/scaffold/distribution.json +14 -0
- package/knowledge/scaffold/origin-engine.json +2 -2
- package/knowledge/scaffold/template/README.md +2 -1
- package/knowledge/scaffold/template/assets/audio/sting.ogt +10 -0
- package/knowledge/scaffold/template/assets/timelines/intro.ogt +101 -0
- package/knowledge/scaffold/template/assets/timelines/narration.srt +11 -0
- package/knowledge/scaffold/template/host.d.ts +46 -0
- package/knowledge/scaffold/template/package.json +1 -1
- package/knowledge/scaffold/template/project.ogt +1 -1
- package/knowledge/scaffold/template/src/main.ts +1 -1
- package/knowledge/scaffold/template/tests/frames.ts +134 -0
- package/knowledge/scaffold/template/tests/intro.og.ts +65 -0
- package/knowledge/scaffold/template/tests/smoke.og.ts +30 -36
- package/knowledge/scaffold/template/tsconfig.json +1 -1
- package/knowledge/scripts/mount.ts +2 -1
- package/knowledge/scripts/validate.ts +159 -31
- package/knowledge/skills/og-audio/SKILL.md +2 -2
- package/knowledge/skills/og-build/SKILL.md +29 -7
- package/knowledge/skills/og-core/SKILL.md +31 -5
- package/knowledge/skills/og-feel/SKILL.md +2 -2
- package/knowledge/skills/og-game/SKILL.md +1331 -16
- package/knowledge/skills/og-i18n/SKILL.md +7 -7
- package/knowledge/skills/og-model/SKILL.md +374 -0
- package/knowledge/skills/og-platform-sdk/SKILL.md +2 -1
- package/knowledge/skills/og-taste/SKILL.md +82 -73
- package/knowledge/skills/og-ui/SKILL.md +80 -58
- package/knowledge/wiki/ai.md +20 -20
- package/knowledge/wiki/anim.md +392 -41
- package/knowledge/wiki/atmosphere.md +36 -13
- package/knowledge/wiki/audio.md +18 -18
- package/knowledge/wiki/camera.md +19 -13
- package/knowledge/wiki/commands.md +19 -13
- package/knowledge/wiki/debug.md +414 -0
- package/knowledge/wiki/game.md +8 -8
- package/knowledge/wiki/i18n.md +7 -7
- package/knowledge/wiki/index.md +317 -8
- package/knowledge/wiki/input.md +47 -47
- package/knowledge/wiki/load.md +238 -70
- package/knowledge/wiki/math.md +2607 -0
- package/knowledge/wiki/nav.md +34 -34
- package/knowledge/wiki/net.md +340 -0
- package/knowledge/wiki/path.md +402 -0
- package/knowledge/wiki/physics.md +95 -95
- package/knowledge/wiki/platform.md +463 -29
- package/knowledge/wiki/probe.md +681 -67
- package/knowledge/wiki/reflect.md +29 -17
- package/knowledge/wiki/render.md +4993 -1998
- package/knowledge/wiki/rng.md +14 -14
- package/knowledge/wiki/shapes.md +727 -0
- package/knowledge/wiki/stream.md +15 -15
- package/knowledge/wiki/system.md +8 -8
- package/knowledge/wiki/systems.md +2 -2
- package/knowledge/wiki/terrain.md +24 -20
- package/knowledge/wiki/tilemap.md +13 -13
- package/knowledge/wiki/time.md +4 -4
- package/knowledge/wiki/timeline.md +396 -0
- package/knowledge/wiki/transform.md +8 -8
- package/knowledge/wiki/tween.md +17 -17
- package/knowledge/wiki/ui.md +560 -654
- package/knowledge/wiki/video.md +157 -0
- package/knowledge/wiki/world.md +36 -36
- package/package.json +4 -3
- package/schema/api.schema.json +28151 -19640
- package/shell/page.ts +26 -2
- package/shell/platform.ts +51 -0
- package/shell/player.ts +15 -2
- package/shell/transport.ts +6 -0
- package/src/depth.ts +71 -0
- package/src/e6.ts +32 -1
- package/src/env.d.ts +5 -1
- package/src/generated/abi.ts +226 -4
- package/src/geom.ts +260 -0
- package/src/index.ts +32 -4
- package/src/light.ts +18 -0
- package/src/math.ts +622 -0
- package/src/node/index.ts +17 -0
- package/src/node/playtest-run.ts +115 -18
- package/src/node/polish.ts +13 -3
- package/src/node/render.ts +291 -0
- package/src/node/run.ts +86 -5
- package/src/p2.ts +19 -1
- package/src/platform-local.ts +2 -0
- package/src/playtest.ts +65 -4
- package/src/runtime.ts +100 -9
- package/src/targets.ts +28 -0
- package/src/trace.ts +169 -0
- package/src/ui-kit/huds.ts +34 -34
- package/src/ui-kit/menus.ts +12 -12
- package/src/ui-kit/settings.ts +11 -2
- package/src/ui-kit/store.ts +18 -18
- package/src/ui-kit/story.ts +6 -4
- package/src/ui-kit/util.ts +8 -8
- package/src/web/shell.ts +59 -1
- package/src/web/worker.ts +105 -4
- package/types/bindings.json +9368 -6619
- package/types/index.d.ts +16377 -11520
|
Binary file
|
|
@@ -11,6 +11,8 @@ export const og_ai_set: (a: number, b: number, c: number, d: number, e: number,
|
|
|
11
11
|
export const og_anim_graph: (a: number, b: number, c: number) => [number, number];
|
|
12
12
|
export const og_anim_humanoid: (a: number, b: number, c: number) => [number, number];
|
|
13
13
|
export const og_anim_retarget: (a: number, b: number, c: number) => [number, number];
|
|
14
|
+
export const og_anim_rig2d_info: (a: number, b: number) => [number, number];
|
|
15
|
+
export const og_anim_skeleton2d_boxes: (a: number, b: number) => [number, number];
|
|
14
16
|
export const og_archetype_view_column: (a: number, b: number, c: number) => [number, number];
|
|
15
17
|
export const og_archetype_view_entity: (a: number, b: number) => number;
|
|
16
18
|
export const og_archetype_view_get_count: (a: number) => number;
|
|
@@ -78,16 +80,21 @@ export const og_load_look: (a: number, b: number, c: number) => [number, number]
|
|
|
78
80
|
export const og_load_look_info: (a: number, b: number) => [number, number];
|
|
79
81
|
export const og_load_lut: (a: number, b: number, c: number) => [number, number];
|
|
80
82
|
export const og_load_palette: (a: number, b: number, c: number) => [number, number];
|
|
83
|
+
export const og_load_post: (a: number, b: number, c: number) => [number, number];
|
|
81
84
|
export const og_load_rig: (a: number, b: number, c: number) => [number, number];
|
|
85
|
+
export const og_load_rig2d: (a: number, b: number, c: number) => [number, number];
|
|
82
86
|
export const og_load_scene: (a: number, b: number, c: number) => [number, number];
|
|
83
87
|
export const og_load_shader: (a: number, b: number, c: number) => [number, number];
|
|
84
|
-
export const og_load_skin: (a: number, b: number, c: number) => [number, number];
|
|
85
88
|
export const og_load_sound: (a: number, b: number, c: number) => [number, number];
|
|
86
89
|
export const og_load_sound_info: (a: number, b: number) => [number, number];
|
|
87
90
|
export const og_load_status: (a: number, b: number) => [number, number];
|
|
91
|
+
export const og_load_style: (a: number, b: number, c: number) => [number, number];
|
|
88
92
|
export const og_load_texture: (a: number, b: number, c: number) => [number, number];
|
|
89
93
|
export const og_load_texture_array: (a: number, b: number, c: number) => [number, number];
|
|
90
94
|
export const og_load_tilemap: (a: number, b: number, c: number) => [number, number];
|
|
95
|
+
export const og_load_timeline: (a: number, b: number, c: number) => [number, number];
|
|
96
|
+
export const og_load_video: (a: number, b: number, c: number) => [number, number];
|
|
97
|
+
export const og_load_video_info: (a: number, b: number) => [number, number];
|
|
91
98
|
export const og_nav_build: (a: number, b: number, c: number) => [number, number];
|
|
92
99
|
export const og_nav_cell_at: (a: number, b: number, c: number, d: number) => [number, number];
|
|
93
100
|
export const og_nav_find_path: (a: number, b: number, c: number) => [number, number];
|
|
@@ -101,6 +108,14 @@ export const og_nav_path_of: (a: number, b: number) => [number, number];
|
|
|
101
108
|
export const og_nav_set_cost: (a: number, b: number, c: number, d: number, e: number) => [number, number];
|
|
102
109
|
export const og_nav_set_flow_targets: (a: number, b: number, c: number, d: number) => [number, number];
|
|
103
110
|
export const og_nav_set_obstacle: (a: number, b: number, c: number, d: number, e: number) => [number, number];
|
|
111
|
+
export const og_net_hash: (a: number) => [number, number];
|
|
112
|
+
export const og_net_status: (a: number) => [number, number];
|
|
113
|
+
export const og_net_submit: (a: number, b: number, c: number) => [number, number];
|
|
114
|
+
export const og_path_create: (a: number, b: number, c: number) => [number, number];
|
|
115
|
+
export const og_path_find: (a: number, b: number, c: number) => [number, number];
|
|
116
|
+
export const og_path_length: (a: number, b: number) => [number, number];
|
|
117
|
+
export const og_path_nearest: (a: number, b: number, c: number, d: number) => [number, number];
|
|
118
|
+
export const og_path_sample: (a: number, b: number, c: number) => [number, number];
|
|
104
119
|
export const og_physics_apply_force: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number];
|
|
105
120
|
export const og_physics_apply_impulse: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number];
|
|
106
121
|
export const og_physics_apply_torque: (a: number, b: number, c: number, d: number) => [number, number];
|
|
@@ -130,6 +145,13 @@ export const og_platform_load_slot: (a: number, b: number, c: number) => [number
|
|
|
130
145
|
export const og_platform_now: (a: number) => number;
|
|
131
146
|
export const og_platform_point: (a: number, b: number, c: number) => [number, number];
|
|
132
147
|
export const og_platform_result: (a: number, b: number) => [number, number];
|
|
148
|
+
export const og_platform_room_create: (a: number, b: number, c: number) => [number, number];
|
|
149
|
+
export const og_platform_room_info: (a: number) => [number, number];
|
|
150
|
+
export const og_platform_room_join: (a: number, b: number, c: number) => [number, number];
|
|
151
|
+
export const og_platform_room_leave: (a: number) => [number, number];
|
|
152
|
+
export const og_platform_room_message: (a: number, b: number) => [number, number];
|
|
153
|
+
export const og_platform_room_peers: (a: number) => [number, number];
|
|
154
|
+
export const og_platform_room_send: (a: number, b: number, c: number, d: number) => [number, number];
|
|
133
155
|
export const og_platform_save_settings: (a: number, b: number, c: number) => [number, number];
|
|
134
156
|
export const og_platform_save_slot: (a: number, b: number, c: number) => [number, number];
|
|
135
157
|
export const og_platform_set_host: (a: number, b: number, c: number) => void;
|
|
@@ -149,20 +171,49 @@ export const og_query_count: (a: number) => number;
|
|
|
149
171
|
export const og_reflect_define_component: (a: number, b: number, c: number, d: number) => [number, number];
|
|
150
172
|
export const og_reflect_define_resource: (a: number, b: number, c: number, d: number) => [number, number];
|
|
151
173
|
export const og_render_apply_look: (a: number, b: number) => [number, number];
|
|
174
|
+
export const og_render_apply_quality: (a: number, b: number, c: number) => [number, number];
|
|
175
|
+
export const og_render_baked_lighting: (a: number) => [number, number];
|
|
152
176
|
export const og_render_box_geometry: (a: number, b: number, c: number) => [number, number];
|
|
177
|
+
export const og_render_buffer_geometry: (a: number, b: number, c: number) => [number, number];
|
|
153
178
|
export const og_render_capabilities: (a: number) => [number, number];
|
|
179
|
+
export const og_render_capsule_geometry: (a: number, b: number, c: number) => [number, number];
|
|
180
|
+
export const og_render_circle_geometry: (a: number, b: number, c: number) => [number, number];
|
|
181
|
+
export const og_render_cone_geometry: (a: number, b: number, c: number) => [number, number];
|
|
182
|
+
export const og_render_csg_geometry: (a: number, b: number, c: number) => [number, number];
|
|
183
|
+
export const og_render_cylinder_geometry: (a: number, b: number, c: number) => [number, number];
|
|
184
|
+
export const og_render_dodecahedron_geometry: (a: number, b: number, c: number) => [number, number];
|
|
185
|
+
export const og_render_extrude_geometry: (a: number, b: number, c: number) => [number, number];
|
|
154
186
|
export const og_render_floating_text: (a: number, b: number, c: number) => [number, number];
|
|
187
|
+
export const og_render_geometry_info: (a: number, b: number) => [number, number];
|
|
188
|
+
export const og_render_icosahedron_geometry: (a: number, b: number, c: number) => [number, number];
|
|
189
|
+
export const og_render_lathe_geometry: (a: number, b: number, c: number) => [number, number];
|
|
190
|
+
export const og_render_lines: (a: number, b: number, c: number) => [number, number];
|
|
155
191
|
export const og_render_look: (a: number) => [number, number];
|
|
156
192
|
export const og_render_measure_text: (a: number, b: number, c: number) => [number, number];
|
|
193
|
+
export const og_render_merge_geometries: (a: number, b: number, c: number) => [number, number];
|
|
194
|
+
export const og_render_octahedron_geometry: (a: number, b: number, c: number) => [number, number];
|
|
157
195
|
export const og_render_plane_geometry: (a: number, b: number, c: number) => [number, number];
|
|
196
|
+
export const og_render_points: (a: number, b: number, c: number) => [number, number];
|
|
197
|
+
export const og_render_polyhedron_geometry: (a: number, b: number, c: number) => [number, number];
|
|
198
|
+
export const og_render_post_errors: (a: number) => [number, number];
|
|
199
|
+
export const og_render_raycast: (a: number, b: number, c: number, d: number, e: number) => [number, number];
|
|
200
|
+
export const og_render_render_target: (a: number, b: number, c: number) => [number, number];
|
|
158
201
|
export const og_render_ribbon: (a: number, b: number, c: number) => [number, number];
|
|
202
|
+
export const og_render_ring_geometry: (a: number, b: number, c: number) => [number, number];
|
|
159
203
|
export const og_render_set_material_shader: (a: number, b: number, c: number, d: number) => [number, number];
|
|
204
|
+
export const og_render_set_post_param: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number];
|
|
160
205
|
export const og_render_set_shader_param: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number];
|
|
161
206
|
export const og_render_shader_material: (a: number, b: number, c: number, d: number) => [number, number];
|
|
207
|
+
export const og_render_shape_geometry: (a: number, b: number, c: number) => [number, number];
|
|
162
208
|
export const og_render_sphere_geometry: (a: number, b: number, c: number) => [number, number];
|
|
163
209
|
export const og_render_sprite: (a: number, b: number, c: number) => [number, number];
|
|
164
210
|
export const og_render_standard_material: (a: number, b: number, c: number) => [number, number];
|
|
211
|
+
export const og_render_sweep_geometry: (a: number, b: number, c: number) => [number, number];
|
|
212
|
+
export const og_render_tetrahedron_geometry: (a: number, b: number, c: number) => [number, number];
|
|
165
213
|
export const og_render_text: (a: number, b: number, c: number) => [number, number];
|
|
214
|
+
export const og_render_torus_geometry: (a: number, b: number, c: number) => [number, number];
|
|
215
|
+
export const og_render_tube_geometry: (a: number, b: number, c: number) => [number, number];
|
|
216
|
+
export const og_render_update_geometry: (a: number, b: number, c: number, d: number) => [number, number];
|
|
166
217
|
export const og_render_update_material: (a: number, b: number, c: number, d: number) => [number, number];
|
|
167
218
|
export const og_rng_chance: (a: number, b: number) => number;
|
|
168
219
|
export const og_rng_fork: (a: number, b: number, c: number) => number;
|
|
@@ -175,6 +226,9 @@ export const og_rng_stream_get_seed: (a: number) => number;
|
|
|
175
226
|
export const og_rng_stream_integer: (a: number, b: number, c: number) => number;
|
|
176
227
|
export const og_rng_stream_next: (a: number) => number;
|
|
177
228
|
export const og_rng_stream_range: (a: number, b: number, c: number) => number;
|
|
229
|
+
export const og_room_deliver: (a: number, b: number, c: number) => number;
|
|
230
|
+
export const og_room_set_host: (a: number, b: number, c: number) => void;
|
|
231
|
+
export const og_room_take: (a: number) => [number, number];
|
|
178
232
|
export const og_runtime_probe_entity: (a: number, b: number, c: number) => [number, number];
|
|
179
233
|
export const og_runtime_probe_get_version: (a: number) => number;
|
|
180
234
|
export const og_runtime_probe_input: (a: number, b: number, c: number) => number;
|
|
@@ -202,6 +256,11 @@ export const og_tilemap_get_tile: (a: number, b: number, c: number, d: number, e
|
|
|
202
256
|
export const og_tilemap_set_tile: (a: number, b: number, c: number) => [number, number];
|
|
203
257
|
export const og_time_hit_stop: (a: number, b: number) => [number, number];
|
|
204
258
|
export const og_time_set_scale: (a: number, b: number) => [number, number];
|
|
259
|
+
export const og_timeline_info: (a: number, b: number) => [number, number];
|
|
260
|
+
export const og_timeline_pause: (a: number, b: number) => [number, number];
|
|
261
|
+
export const og_timeline_play: (a: number, b: number) => [number, number];
|
|
262
|
+
export const og_timeline_seek: (a: number, b: number, c: number) => [number, number];
|
|
263
|
+
export const og_timeline_stop: (a: number, b: number) => [number, number];
|
|
205
264
|
export const og_transform_compose: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number];
|
|
206
265
|
export const og_transform_decompose: (a: number, b: number) => [number, number];
|
|
207
266
|
export const og_transform_from_axis_angle: (a: number, b: number, c: number) => [number, number];
|
|
@@ -312,6 +371,8 @@ export const og_web_set_inflater: (a: any) => void;
|
|
|
312
371
|
export const og_web_set_viewport: (a: number, b: number, c: number) => [number, number];
|
|
313
372
|
export const og_web_texture_ktx2: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number];
|
|
314
373
|
export const og_web_texture_target: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number];
|
|
374
|
+
export const og_web_trace: (a: number, b: number) => void;
|
|
375
|
+
export const og_web_trace_take: (a: number, b: number) => [number, number];
|
|
315
376
|
export const og_web_warm: (a: number) => number;
|
|
316
377
|
export const og_world_alive: (a: number, b: number) => number;
|
|
317
378
|
export const og_world_despawn: (a: number, b: number) => [number, number];
|
|
@@ -334,8 +395,8 @@ export const og_world_spawn: (a: number, b: number, c: number) => [number, numbe
|
|
|
334
395
|
export const wasm_bindgen_b8d3fa9391980f8___convert__closures_____invoke___js_sys_8cb0a1ab15bdbf1e___Function_fn_wasm_bindgen_b8d3fa9391980f8___JsValue_____wasm_bindgen_b8d3fa9391980f8___sys__Undefined___js_sys_8cb0a1ab15bdbf1e___Function_fn_wasm_bindgen_b8d3fa9391980f8___JsValue_____wasm_bindgen_b8d3fa9391980f8___sys__Undefined_______true_: (a: number, b: number, c: any, d: any) => void;
|
|
335
396
|
export const wasm_bindgen_b8d3fa9391980f8___convert__closures_____invoke___wasm_bindgen_b8d3fa9391980f8___JsValue__core_37ee0ce0c4cd57d5___result__Result_____wasm_bindgen_b8d3fa9391980f8___JsError___true_: (a: number, b: number, c: any) => [number, number];
|
|
336
397
|
export const wasm_bindgen_b8d3fa9391980f8___convert__closures_____invoke___wasm_bindgen_b8d3fa9391980f8___sys__JsNullable_wgpu_d2fbdff2c91c8b93___backend__webgpu__webgpu_sys__gen_GpuError__GpuError___core_37ee0ce0c4cd57d5___result__Result_____wasm_bindgen_b8d3fa9391980f8___JsError___true_: (a: number, b: number, c: any) => [number, number];
|
|
337
|
-
export const
|
|
338
|
-
export const
|
|
398
|
+
export const wasm_bindgen_b8d3fa9391980f8___convert__closures_____invoke___wasm_bindgen_b8d3fa9391980f8___sys__JsNullable_wgpu_d2fbdff2c91c8b93___backend__webgpu__webgpu_sys__gen_GpuError__GpuError___core_37ee0ce0c4cd57d5___result__Result_____wasm_bindgen_b8d3fa9391980f8___JsError___true__394: (a: number, b: number, c: any) => [number, number];
|
|
399
|
+
export const wasm_bindgen_b8d3fa9391980f8___convert__closures_____invoke___wasm_bindgen_b8d3fa9391980f8___sys__JsNullable_wgpu_d2fbdff2c91c8b93___backend__webgpu__webgpu_sys__gen_GpuError__GpuError___core_37ee0ce0c4cd57d5___result__Result_____wasm_bindgen_b8d3fa9391980f8___JsError___true__395: (a: number, b: number, c: any) => [number, number];
|
|
339
400
|
export const __wbindgen_malloc: (a: number, b: number) => number;
|
|
340
401
|
export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
|
341
402
|
export const __wbindgen_exn_store: (a: number) => void;
|
package/knowledge/README.md
CHANGED
|
@@ -6,7 +6,8 @@ knowledge packs (`packages/game-knowledge/production` of OriginGame):
|
|
|
6
6
|
| Part | Path | Mounted at (`knowledge.json`) |
|
|
7
7
|
|---|---|---|
|
|
8
8
|
| API wiki, one page per IDL module plus `index.md` | `wiki/` (generated: `og api gen --wiki`; `og api check` fails on drift) | `game/skills/og-game/reference/` |
|
|
9
|
-
| Skills, numbered `## N.` sections cross-referenced as `og-feel §4`: `og-game` (the entry point and the map of the others: the project, ECS, scenes, assets, loading, input, 2D, animation, effects, atmosphere and water, material shaders, physics, performance, looks, light and shadows), `og-core` (engine rules), `og-build` (the `og` loop, the evidence discipline, and `og polish`: §5 is the one list of what it measures), `og-feel` (game feel: time scale, hit stop, tweens, camera, juice amounts, controller tunables by genre), `og-ui` (screens, HUDs,
|
|
9
|
+
| Skills, numbered `## N.` sections cross-referenced as `og-feel §4`: `og-game` (the entry point and the map of the others: the project, ECS, scenes, assets, loading, input, 2D, animation, effects, atmosphere and water, material shaders, physics, performance, looks, light and shadows), `og-core` (engine rules), `og-build` (the `og` loop, the evidence discipline, and `og polish`: §5 is the one list of what it measures), `og-feel` (game feel: time scale, hit stop, tweens, camera, juice amounts, controller tunables by genre), `og-ui` (screens, HUDs, styles, motion, text entry, accessibility, gestures), `og-taste` (art direction: a look chosen from the premise out of the style catalogue `looks/catalogue.json`, atmosphere by intent, the done checklist), `og-ai` (navigation and enemy minds as data), `og-audio` (events, presets, the mix, music), `og-i18n` (string tables, fonts, line breaking, right to left), `og-model` (a 3D model built as code from a reference image: the intake's detail inventory, eight gated passes, the og-geom generators' recipes, budgets, the `type model` asset, and the review's `view` and `turntable` frames and `og compare` sheet), `og-platform-sdk` (`og.platform`: saves, settings, leaderboards, telemetry, and how to ask for what is missing; the platform's own `og-platform` covers the Player). Each IDL module's `skill` names the one that teaches it; the wiki's index groups modules by it, and `bun run test` checks that skill names the module's page, no other does, and every section reference resolves | `skills/<name>/SKILL.md` | `game/skills/<name>/` |
|
|
10
|
+
| Guides: hand-written pages an agent reads beside a skill, held to the same rules as the skills (every `og.*` name and `Type.field` in the API, section references resolved, each named by og-game, listed in `GUIDES`): `three-to-og` maps three.js's classes and idioms to the engine's and names the gaps; `og migrate three` cites its sections | `guides/<name>.md` | `game/skills/og-game/guides/` |
|
|
10
11
|
| Scaffold: the project template, its engine pin and binary digests | `scaffold/` and the engine repository's `templates/game` | `game-scaffold/origin-engine-ts/` |
|
|
11
12
|
|
|
12
13
|
`bun run test` validates the package against the platform's rules
|
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
# three.js to Origin Engine
|
|
2
|
+
|
|
3
|
+
For an author who knows three.js, or who has a three.js file to bring
|
|
4
|
+
over. Origin Engine keeps three.js's vocabulary wherever it does not
|
|
5
|
+
contradict the engine: `Vector3`, position, quaternion and scale, the
|
|
6
|
+
material parameters, the geometry classes' parameters and defaults, glTF
|
|
7
|
+
loading, layers. What it does not keep is the object model. A three.js
|
|
8
|
+
program is a tree of mutable objects that a loop you write renders; an
|
|
9
|
+
Origin Engine game is a world of entities with plain components, changed
|
|
10
|
+
by systems on a fixed tick, and the engine draws every frame itself. Read
|
|
11
|
+
og-game §3 (components, systems, the game) and og-core first: this page
|
|
12
|
+
only maps names.
|
|
13
|
+
|
|
14
|
+
`og migrate three <file.ts>` (§11) rewrites the mechanical part of a
|
|
15
|
+
file with these mappings and marks every line it cannot, citing the
|
|
16
|
+
section here that says what to do.
|
|
17
|
+
|
|
18
|
+
## 1. The model, side by side
|
|
19
|
+
|
|
20
|
+
| three.js | Origin Engine |
|
|
21
|
+
|---|---|
|
|
22
|
+
| `new THREE.Scene()` | the world: every entity spawned is in it, nothing is added |
|
|
23
|
+
| an `Object3D`, `Group` or `Mesh` | an entity (`world.spawn`), its data as components |
|
|
24
|
+
| `object.position`, `quaternion`, `scale` | the og.Transform component, read with `world.get` and written with `world.set` |
|
|
25
|
+
| `parent.add(child)` | og.Parent on the child (`SpawnDesc.parent` at spawn) |
|
|
26
|
+
| a `BufferGeometry`, a `Material`, a `Texture` | a handle the world owns (Geometry, Material, Texture), made by `og.render` or `og.load` |
|
|
27
|
+
| `new THREE.Mesh(geometry, material)` | og.Mesh `{ geometry, material }` on an entity |
|
|
28
|
+
| `renderer.render(scene, camera)` in `requestAnimationFrame` | nothing: the engine draws every frame; game logic runs in systems on the fixed tick (§8) |
|
|
29
|
+
| `camera` | the og.Camera resource (one per world), og.CameraView for more |
|
|
30
|
+
| `Raycaster` | `og.render.raycast` (§9) |
|
|
31
|
+
| `GLTFLoader`, `TextureLoader` | `og.load.gltf`, `og.load.texture` of cooked assets (§7) |
|
|
32
|
+
| a thrown error | a Result: `{ ok: true, value }` or `{ ok: false, reason }` |
|
|
33
|
+
| `Math.random()`, `clock.getDelta()` | og.Rng and og.Time: deterministic, so replays and tests repeat |
|
|
34
|
+
|
|
35
|
+
Three rules follow from the model and catch every port:
|
|
36
|
+
|
|
37
|
+
- **Values are plain.** og.Transform's position is `{ x, y, z }`, not a
|
|
38
|
+
Vector3 object with methods. `vec3`, `quat`, `mat4` and `color` are
|
|
39
|
+
three.js's methods as pure functions (`vec3.add(a, b)` returns a new
|
|
40
|
+
value; `a.add(b)` does not exist), so a result can go straight into a
|
|
41
|
+
component (`reference/math.md`).
|
|
42
|
+
- **Every call that can fail answers a Result.** The examples here use
|
|
43
|
+
a `must` helper, as the templates do:
|
|
44
|
+
`function must<T>(r: { ok: true; value: T } | { ok: false; reason: string }): T { if (!r.ok) throw new Error(r.reason); return r.value; }`.
|
|
45
|
+
- **Calls take the world.** Setup goes in `GameDesc.start(world)` (or a
|
|
46
|
+
command), per-tick logic in a system; neither keeps state in module
|
|
47
|
+
variables (og-core).
|
|
48
|
+
|
|
49
|
+
## 2. The scene graph: entities and og.Parent
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
// three.js
|
|
53
|
+
const ship = new THREE.Group();
|
|
54
|
+
const hull = new THREE.Mesh(new THREE.BoxGeometry(2, 0.5, 4), steel);
|
|
55
|
+
ship.add(hull);
|
|
56
|
+
scene.add(ship);
|
|
57
|
+
|
|
58
|
+
// Origin Engine, in start(world)
|
|
59
|
+
const ship = must(world.spawn({ name: "ship" }));
|
|
60
|
+
const hull = must(world.spawn({ name: "hull", parent: ship }));
|
|
61
|
+
world.insert(hull, og.Mesh, { geometry: must(og.render.boxGeometry(world, { width: 2, height: 0.5, depth: 4 })), material: steel });
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
- `parent.add(child)` after the spawn is `world.insert(child, og.Parent,
|
|
65
|
+
{ entity: parent })`; `parent.remove(child)` is `world.remove(child,
|
|
66
|
+
og.Parent)`; `scene.remove(object)` is `world.despawn(object)`.
|
|
67
|
+
- A child's og.Transform is relative to its parent, as three.js's
|
|
68
|
+
`position` is; the engine composes og.MatrixWorld down the chain after
|
|
69
|
+
the systems run, so there is no `updateMatrixWorld` to call.
|
|
70
|
+
- `getObjectByName("hull")` is `world.find("hull")`. Names are unique and
|
|
71
|
+
the probe, the command channel and the tests address entities by them:
|
|
72
|
+
name every entity anyone will ask about.
|
|
73
|
+
- `scene.traverse(fn)` over everything of a kind is a system's query over
|
|
74
|
+
the components that kind has (og-core): `reads: [og.Mesh]` visits every
|
|
75
|
+
drawn mesh, archetype by archetype.
|
|
76
|
+
- A scene written by hand in three.js code is often better as a scene
|
|
77
|
+
file: `.ogt` text with nested `entity` blocks, cooked and diffable
|
|
78
|
+
(og-game §4).
|
|
79
|
+
|
|
80
|
+
## 3. Object3D: og.Transform and the components
|
|
81
|
+
|
|
82
|
+
| three.js `Object3D` | Origin Engine |
|
|
83
|
+
|---|---|
|
|
84
|
+
| `position.set(x, y, z)` | `world.set(e, og.Transform, { position: { x, y, z } })` |
|
|
85
|
+
| `quaternion.set(x, y, z, w)` | `world.set(e, og.Transform, { quaternion: { x, y, z, w } })` |
|
|
86
|
+
| `rotation.set(x, y, z)` (an Euler) | `{ quaternion: quat.fromEuler({ x, y, z }) }`: radians, order `"XYZ"` as three.js's default |
|
|
87
|
+
| `scale.set(x, y, z)`, `scale.setScalar(s)` | `{ scale: { x, y, z } }` |
|
|
88
|
+
| `position.x += v` | read, change, write: `const t = must(world.get(e, og.Transform)); world.set(e, og.Transform, { position: { ...t.position, x: t.position.x + v } })`, or a system over the column (og-core) |
|
|
89
|
+
| `lookAt(target)` (a camera or a light) | `{ quaternion: og.transform.lookAt(eye, target) }`: it points -Z at the target, as three.js turns cameras and lights |
|
|
90
|
+
| `lookAt(target)` (any other object) | three.js points such an object's +Z at the target: `og.transform.lookAt(target, eye)`, the reverse, does the same |
|
|
91
|
+
| `matrixWorld` | og.MatrixWorld (read only; the engine writes it) |
|
|
92
|
+
| `visible`, `castShadow`, `receiveShadow`, `layers` | og.Mesh's (and og.Model's) `visible`, `castShadow`, `receiveShadow`, `layers` |
|
|
93
|
+
| `name` | `SpawnDesc.name` |
|
|
94
|
+
| `userData` | your own component (`defineComponent`): reflected, saved, inspectable |
|
|
95
|
+
|
|
96
|
+
Two defaults differ from three.js: `Mesh.receiveShadow` is on (three.js's
|
|
97
|
+
is off) and `DirectionalLight.castShadow` is on. Set them where the port
|
|
98
|
+
depends on the old value.
|
|
99
|
+
|
|
100
|
+
## 4. Geometry: og.render and og-geom
|
|
101
|
+
|
|
102
|
+
The geometry classes keep their parameters, names and defaults; the
|
|
103
|
+
positional arguments become a desc object of the same names, and the
|
|
104
|
+
result is a Geometry handle (a Result) that draws through og.Mesh, carries
|
|
105
|
+
a BVH for `og.render.raycast` and is a `Collider.mesh` at once
|
|
106
|
+
(og-game §18 has the details).
|
|
107
|
+
|
|
108
|
+
| three.js | Origin Engine | Not carried over |
|
|
109
|
+
|---|---|---|
|
|
110
|
+
| `BoxGeometry(width, height, depth)` | `og.render.boxGeometry(world, { width, height, depth })` | the segment counts |
|
|
111
|
+
| `PlaneGeometry(width, height)` | `og.render.planeGeometry` | the segment counts |
|
|
112
|
+
| `SphereGeometry(radius, widthSegments, heightSegments)` | `og.render.sphereGeometry` | `phiStart`, `phiLength`, `thetaStart`, `thetaLength` |
|
|
113
|
+
| `CylinderGeometry(radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength)` | `og.render.cylinderGeometry` | — |
|
|
114
|
+
| `ConeGeometry(radius, height, radialSegments, heightSegments, openEnded)` | `og.render.coneGeometry` | `thetaStart`, `thetaLength` |
|
|
115
|
+
| `CapsuleGeometry(radius, height, capSegments, radialSegments, heightSegments)` | `og.render.capsuleGeometry` (`height` the straight middle, as r174's) | — |
|
|
116
|
+
| `TorusGeometry(radius, tube, radialSegments, tubularSegments, arc)` | `og.render.torusGeometry` | — |
|
|
117
|
+
| `RingGeometry(innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength)` | `og.render.ringGeometry` | — |
|
|
118
|
+
| `CircleGeometry(radius, segments, thetaStart, thetaLength)` | `og.render.circleGeometry` | — |
|
|
119
|
+
| `TubeGeometry(new CatmullRomCurve3(points), tubularSegments, radius, radialSegments, closed)` | `og.render.tubeGeometry(world, { points, ... })`, or `path` an og.path | other Curve classes: write the curve as an og.path |
|
|
120
|
+
| `LatheGeometry(points, segments, phiStart, phiLength)` | `og.render.latheGeometry` (points `{ x, y }`) | — |
|
|
121
|
+
| `Shape`, `Path` | `og.Shape`, `og.Path2` (the root `shapes` module, `reference/shapes.md`): the same calls | — |
|
|
122
|
+
| `ShapeGeometry(shapes, curveSegments)` | `og.render.shapeGeometry(world, { shapes, curveSegments })` | — |
|
|
123
|
+
| `ExtrudeGeometry(shapes, { depth, bevelEnabled, ... })` | `og.render.extrudeGeometry(world, { shapes, depth, bevelEnabled, ... })`; `extrudePath` an og.path | `UVGenerator` |
|
|
124
|
+
| `PolyhedronGeometry(vertices, indices, radius, detail)` | `og.render.polyhedronGeometry` | — |
|
|
125
|
+
| `IcosahedronGeometry`, `DodecahedronGeometry`, `OctahedronGeometry`, `TetrahedronGeometry` `(radius, detail)` | `og.render.icosahedronGeometry` and the other three | — |
|
|
126
|
+
| `BufferGeometry` with `setAttribute` and `setIndex` | `og.render.bufferGeometry(world, { positions, normals, uvs, colors, indices })` (typed arrays, normals computed when left out) | groups (one material per geometry: split it) |
|
|
127
|
+
| `attribute.needsUpdate = true` | `og.render.updateGeometry` of a geometry made with `dynamic: true` | — |
|
|
128
|
+
| `BufferGeometryUtils.mergeGeometries([...])` | `og.render.mergeGeometries(world, { parts: [{ geometry, position, quaternion, scale, mirror }] })` | — |
|
|
129
|
+
| three-bvh-csg's `Evaluator` | `og.render.csgGeometry(world, { op, a, b })` with exact predicates | — |
|
|
130
|
+
| `TorusKnotGeometry`, `TextGeometry`, `EdgesGeometry`, `WireframeGeometry` | none: a knot as `tubeGeometry` through its points, text as `og.render.text` or og.ui, edges as `wireframe: true` on the material or `og.render.lines` | — |
|
|
131
|
+
|
|
132
|
+
Two more go beyond three.js: `og.render.sweepGeometry` sweeps a section
|
|
133
|
+
along an og.path with a scale and twist over its length (horns, tusks,
|
|
134
|
+
handles), and a prop built of these parts belongs in an asset rather
|
|
135
|
+
than in code: an `.ogt` of `type model` names each part by its
|
|
136
|
+
`og.render` call with the desc's fields, places it as `mergeGeometries`
|
|
137
|
+
does and gives it a material and a pivot; the cook builds it into the
|
|
138
|
+
model blob a glTF cooks to, with levels of detail and the BVH, and
|
|
139
|
+
`og.load.gltf` loads it (og-game §18 has the grammar). The og-model
|
|
140
|
+
skill builds such props from a reference image.
|
|
141
|
+
|
|
142
|
+
`og.render.geometryInfo` answers what `geometry.attributes.position.count`
|
|
143
|
+
and `computeBoundingBox` did. Geometries are made where the world is
|
|
144
|
+
(start, a command, a system), never at module load.
|
|
145
|
+
|
|
146
|
+
## 5. Materials and textures
|
|
147
|
+
|
|
148
|
+
Every lit three.js mesh material becomes `og.render.standardMaterial(world,
|
|
149
|
+
desc)`, with the StandardMaterialDesc fields under three.js's names:
|
|
150
|
+
`color`, `metalness`, `roughness`, `emissive`, `emissiveIntensity`, `map`,
|
|
151
|
+
`normalMap`, `normalScale`, `roughnessMap`, `metalnessMap`, `aoMap`,
|
|
152
|
+
`emissiveMap`, `opacity`, `transparent`, `alphaTest`, `side`,
|
|
153
|
+
`flatShading`, `wireframe`, `envMapIntensity`, and MeshPhysicalMaterial's
|
|
154
|
+
`clearcoat`, `sheen`, `transmission`, `thickness`, `ior`, `iridescence`
|
|
155
|
+
and `anisotropy`.
|
|
156
|
+
|
|
157
|
+
| three.js | Origin Engine |
|
|
158
|
+
|---|---|
|
|
159
|
+
| `MeshStandardMaterial(params)`, `MeshPhysicalMaterial(params)` | `standardMaterial(world, params)` |
|
|
160
|
+
| `MeshBasicMaterial(params)` | `standardMaterial(world, { ...params, unlit: true })` |
|
|
161
|
+
| `MeshToonMaterial(params)` | `standardMaterial(world, { ...params, toon: true })` (`gradientMap` quantizes the light) |
|
|
162
|
+
| `MeshLambertMaterial`, `MeshPhongMaterial` | `standardMaterial`: roughness near 1 for Lambert; Phong's `shininess` and `specular` have no field (lower roughness for a tighter highlight) |
|
|
163
|
+
| `color: 0xff8800`, `new THREE.Color("#ff8800")` | `color: color.fromHex(0xff8800)`: sRGB hex to linear, as three.js's colour management does |
|
|
164
|
+
| `new THREE.Color(r, g, b)` | `{ r, g, b }`, linear, as three.js's components are |
|
|
165
|
+
| `side: THREE.DoubleSide` (`FrontSide`, `BackSide`) | `side: "double"` (`"front"`, `"back"`) |
|
|
166
|
+
| `material.roughness = 0.3` | `og.render.updateMaterial(world, material, { roughness: 0.3 })` |
|
|
167
|
+
| `vertexColors` on | the geometry's `colors` multiply the colour whenever it has them |
|
|
168
|
+
| `texture.repeat.set(4, 4)` with `RepeatWrapping` | the geometry's `uvRepeat: { x: 4, y: 4 }`; textures always wrap |
|
|
169
|
+
| `texture.colorSpace = THREE.SRGBColorSpace` | the cook's import settings (og-game §5): colour textures are sRGB, a `kind normal` texture is linear |
|
|
170
|
+
| `scene.environment = pmrem.fromEquirectangular(hdr)` | og.Environment's `map` from `og.load.environment` of a `type environment` asset (§7) |
|
|
171
|
+
| `LineBasicMaterial`, `PointsMaterial` | `og.render.lines` and `og.render.points` each tick, or the og.Lines and og.Points components over a geometry |
|
|
172
|
+
| `SpriteMaterial` with `THREE.Sprite` | og.Sprite, or `og.render.sprite` each tick |
|
|
173
|
+
| `ShaderMaterial`, `RawShaderMaterial`, `onBeforeCompile` | §10 |
|
|
174
|
+
|
|
175
|
+
Toon, rim, outline, dissolve and hit flash are fields of the same desc
|
|
176
|
+
(og-game §10). One geometry has one material: three.js's material arrays
|
|
177
|
+
and geometry groups become one entity per group.
|
|
178
|
+
|
|
179
|
+
## 6. Lights, the camera and the frame
|
|
180
|
+
|
|
181
|
+
| three.js | Origin Engine |
|
|
182
|
+
|---|---|
|
|
183
|
+
| `DirectionalLight(color, intensity)`, `position` and `target` | og.DirectionalLight `{ color, intensity }` on an entity: it shines along the entity's -Z, so aim it with `og.transform.lookAt(position, target)` (three.js's default target is the origin) |
|
|
184
|
+
| `PointLight(color, intensity, distance)` | og.PointLight `{ color, intensity, distance }`: `distance` is never infinite (10 by default); `decay` is not carried over |
|
|
185
|
+
| `SpotLight(color, intensity, distance, angle, penumbra)` | og.SpotLight, along the entity's -Z like the directional light |
|
|
186
|
+
| `RectAreaLight(color, intensity, width, height)` | og.RectLight |
|
|
187
|
+
| `AmbientLight`, `HemisphereLight` | no light entity: the sky lights every surface (RenderSettings.environmentIntensity), or an environment map does (og.Environment); og.Sky colours the sky itself |
|
|
188
|
+
| `light.castShadow = true`, `light.shadow.mapSize` | the light's `castShadow`; `RenderOptions.shadowMapSize` and RenderSettings.shadowMapScale |
|
|
189
|
+
| `renderer.shadowMap.enabled = true` | nothing: shadows are on per light |
|
|
190
|
+
| `PerspectiveCamera(fov, aspect, near, far)` | the og.Camera resource: `const camera = must(world.resource(og.Camera)); camera.fov = 50;` (degrees, vertical, as three.js); the aspect is the play surface's |
|
|
191
|
+
| `camera.aspect = w / h; camera.updateProjectionMatrix()` on resize | nothing: the engine sizes the canvas and the projection |
|
|
192
|
+
| `OrthographicCamera(left, right, top, bottom, near, far)` | og.Camera with `orthographic: true` and `height` the visible world height (`top - bottom`); the width follows the aspect |
|
|
193
|
+
| `camera.position.set(x, y, z)`, `camera.lookAt(x, y, z)` | `camera.position = { x, y, z }`, `camera.lookAt({ x, y, z })` on the resource handle |
|
|
194
|
+
| `scene.background = new THREE.Color(0x87ceeb)` | `camera.background = color.fromHex(0x87ceeb)` (og.Camera's `background`) |
|
|
195
|
+
| `scene.fog = new THREE.Fog(color, near, far)` | og.Fog's `color`, `start`, `end` (`density` for FogExp2), with `enabled` true (og-game §11) |
|
|
196
|
+
| `new THREE.WebGLRenderer({ antialias: true })` | `GameDesc.render` (`render: { antialias: "msaa4" }`); the engine owns the canvas, on an OffscreenCanvas in a Worker on the web |
|
|
197
|
+
| `renderer.toneMapping`, `toneMappingExposure` | RenderSettings.toneMapping (`"aces"` by default, `"agx"`, `"none"`) and `exposure` (og-game §16) |
|
|
198
|
+
| a second camera into a `WebGLRenderTarget` | og.CameraView with `target` from `og.render.renderTarget` (og-game §23) |
|
|
199
|
+
| `EffectComposer` and its passes | og.PostEffects (bloom, AO, depth of field, outline, LUTs and more, og-game §10) and custom post passes (§10 here) |
|
|
200
|
+
|
|
201
|
+
Light intensities are three.js's physical units in spirit (a point
|
|
202
|
+
light's `intensity` is its radiance at one metre) but not calibrated
|
|
203
|
+
against them: judge a ported scene's light in a frame, not by its
|
|
204
|
+
numbers.
|
|
205
|
+
|
|
206
|
+
## 7. Loaders: og.load and the cook
|
|
207
|
+
|
|
208
|
+
There is no loader object and nothing is fetched by URL. Sources go in
|
|
209
|
+
`assets/`, `og cook` turns them into `cooked/` (meshopt meshes with LODs
|
|
210
|
+
and BVHs, KTX2 textures, QOA audio, MSDF fonts), and every `og.load`
|
|
211
|
+
call names an asset id, the path under `assets/` (og-game §5, §6).
|
|
212
|
+
|
|
213
|
+
| three.js | Origin Engine |
|
|
214
|
+
|---|---|
|
|
215
|
+
| `new GLTFLoader().load(url, (gltf) => scene.add(gltf.scene))` | `const ship = must(og.load.gltf(world, "models/ship.glb"))`, then `world.instantiate(ship, { name: "ship", position })` once `og.load.status(world, ship)` is `"ready"`, or the `AssetReady` event; a scene's `model` line instantiates it for you |
|
|
216
|
+
| `gltf.animations` with an `AnimationMixer` | og.AnimationPlayer or og.AnimationGraph on the instance (og-game §9) |
|
|
217
|
+
| `DRACOLoader`, `KTX2Loader`, `MeshoptDecoder` | the cook compresses; give it the uncompressed glTF (it reads no Draco) |
|
|
218
|
+
| `new THREE.TextureLoader().load("textures/crate.png")` | `og.load.texture(world, "textures/crate.png")` |
|
|
219
|
+
| `RGBELoader`, `EXRLoader`, `CubeTextureLoader` for the environment | an `.ogt` of `type environment` naming the `.hdr`, `.exr` or cube, loaded with `og.load.environment` (prefiltered at cook time) |
|
|
220
|
+
| `AudioLoader` with `THREE.Audio` | `og.load.sound` and og.AudioSource (og-audio) |
|
|
221
|
+
| `FontLoader` | `og.load.font` of a TTF or OTF, for `og.render.text` and og.ui |
|
|
222
|
+
| `loader.loadAsync(url)` and `await` | no promises: a load completes at a tick boundary, and under `og run` before the next tick, so it lands on the same tick every run |
|
|
223
|
+
|
|
224
|
+
A MagicaVoxel `.vox` loads with `og.load.gltf` too, and so does a
|
|
225
|
+
`type model` asset (§4).
|
|
226
|
+
|
|
227
|
+
## 8. The render loop: the tick
|
|
228
|
+
|
|
229
|
+
```ts
|
|
230
|
+
// three.js
|
|
231
|
+
const clock = new THREE.Clock();
|
|
232
|
+
renderer.setAnimationLoop(() => {
|
|
233
|
+
const dt = clock.getDelta();
|
|
234
|
+
cube.rotation.y += dt;
|
|
235
|
+
renderer.render(scene, camera);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// Origin Engine: a component marks what turns, a system turns it
|
|
239
|
+
const Spin = defineComponent("Spin", { speed: f32(1) });
|
|
240
|
+
const Turn = defineSystem("Turn", { reads: [Spin], writes: [og.Transform] }, (q, time) => {
|
|
241
|
+
for (const a of q.archetypes()) {
|
|
242
|
+
const rot = a.column(og.Transform).quaternion;
|
|
243
|
+
const speed = a.column(Spin).speed;
|
|
244
|
+
for (let i = 0; i < a.count; i++) {
|
|
245
|
+
const next = quat.multiply(
|
|
246
|
+
{ x: rot[i * 4], y: rot[i * 4 + 1], z: rot[i * 4 + 2], w: rot[i * 4 + 3] },
|
|
247
|
+
og.transform.fromAxisAngle({ x: 0, y: 1, z: 0 }, speed[i] * time.dt),
|
|
248
|
+
);
|
|
249
|
+
rot.set([next.x, next.y, next.z, next.w], i * 4);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
export default og.game({ systems: [Turn], start(world) { /* spawn the cube with Spin */ } });
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
- The loop body becomes one or more systems, each one job, listed in
|
|
257
|
+
`GameDesc.systems`. A system runs once per tick (60 Hz by default,
|
|
258
|
+
fixed) over the archetypes that hold its components; the engine
|
|
259
|
+
renders between ticks and interpolates.
|
|
260
|
+
- `clock.getDelta()` is `time.dt` (the og.Time resource, fixed per
|
|
261
|
+
tick); `clock.getElapsedTime()` is `time.elapsed`. Nothing in a tick
|
|
262
|
+
reads the wall clock.
|
|
263
|
+
- `Math.random()` is og.Rng (`world.resource(og.Rng)`, `range`, `chance`,
|
|
264
|
+
`integer`): seeded from the project, so a replay repeats the run.
|
|
265
|
+
- `renderer.render(scene, camera)`, `requestAnimationFrame` and the
|
|
266
|
+
resize handler are deleted: the engine draws every frame.
|
|
267
|
+
- Input listeners (`addEventListener("keydown")`) become reads of
|
|
268
|
+
og.Input in a system (`input.pressed("Space")`, og-game §7): the main
|
|
269
|
+
thread owns the events and the tick sees them at its start.
|
|
270
|
+
|
|
271
|
+
## 9. Picking: og.render.raycast
|
|
272
|
+
|
|
273
|
+
```ts
|
|
274
|
+
// three.js
|
|
275
|
+
raycaster.setFromCamera(pointer, camera);
|
|
276
|
+
const hits = raycaster.intersectObjects(scene.children, true);
|
|
277
|
+
|
|
278
|
+
// Origin Engine, in a system that reads og.Input and og.Camera
|
|
279
|
+
const camera = must(world.resource(og.Camera));
|
|
280
|
+
const input = must(world.resource(og.Input));
|
|
281
|
+
const ray = camera.screenToRay(input.pointer.x, input.pointer.y); // CSS pixels, not -1..1
|
|
282
|
+
const hits = must(og.render.raycast(world, ray, { first: true }));
|
|
283
|
+
if (hits.length > 0) og.debug.sphere(world, hits[0].point, 0.05);
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
- It tests what is drawn (every og.Mesh and og.Model at its world
|
|
287
|
+
transform, through each geometry's BVH, both faces), nearest first,
|
|
288
|
+
always over the whole world: there is no list of objects to pass. Each
|
|
289
|
+
hit has `entity`, `geometry`, `distance`, `point`, `normal`, `uv` and
|
|
290
|
+
`faceIndex`, as three.js's intersection.
|
|
291
|
+
- `near` and `far` are `maxDistance`; three.js's `layers` are the desc's
|
|
292
|
+
`layers`, tested as three.js tests them; `first: true` stops at the
|
|
293
|
+
nearest hit.
|
|
294
|
+
- For gameplay against colliders (ground checks, bullets) use
|
|
295
|
+
`og.physics.raycast`, which reads the physics world instead
|
|
296
|
+
(og-game §13).
|
|
297
|
+
|
|
298
|
+
## 10. The gaps, named
|
|
299
|
+
|
|
300
|
+
- **ShaderMaterial and RawShaderMaterial** have no one-line counterpart.
|
|
301
|
+
A shader is an asset of `type shader` written in WGSL, compiled by the
|
|
302
|
+
cook for every back end: four hooks into the lit shader (vertex offset,
|
|
303
|
+
surface colour, normal, emissive; og-game §12) for what most
|
|
304
|
+
`onBeforeCompile` and ShaderMaterial uses do, or `mode full lit` /
|
|
305
|
+
`mode full unlit` for the whole vertex and fragment stages (og-game §23),
|
|
306
|
+
made with `og.render.shaderMaterial` and fed with
|
|
307
|
+
`og.render.setShaderParam`. A screen-space effect (an EffectComposer
|
|
308
|
+
ShaderPass) is a `type post` asset in PostEffects.custom. GLSL is
|
|
309
|
+
rewritten by hand into WGSL; uniforms become `param` lines.
|
|
310
|
+
- **InstancedMesh is not needed.** Draws are batched per geometry and
|
|
311
|
+
material: spawn one entity per instance with the same Geometry and
|
|
312
|
+
Material handles and the renderer draws them instanced, each culled and
|
|
313
|
+
shadowed on its own. `setMatrixAt(i, m)` is that entity's og.Transform
|
|
314
|
+
(`og.transform.decompose(m)`), `setColorAt` a per-entity colour through
|
|
315
|
+
`Mesh.flash` or a texture-array layer (`Mesh.materialLayer`), or one
|
|
316
|
+
material per colour. A part repeated inside one model is instanced by
|
|
317
|
+
the cook (`type model`'s `at { }` blocks).
|
|
318
|
+
- **No OrbitControls object.** Nothing takes a DOM element or listens to
|
|
319
|
+
events. The og.OrbitCamera component is the same controller as data:
|
|
320
|
+
put it on the entity to orbit, list `...og.systems.cameras` first in
|
|
321
|
+
`GameDesc.systems`, and its fields keep OrbitControls' names
|
|
322
|
+
(`target`, `minDistance`, `maxDistance`, `minPolarAngle`,
|
|
323
|
+
`maxPolarAngle`, `rotateSpeed`, `zoomSpeed`, `autoRotate`,
|
|
324
|
+
`autoRotateSpeed`, `enabled`); `controls.update()` is gone. There is no
|
|
325
|
+
damping and no panning. og.FollowCamera follows a target instead
|
|
326
|
+
(og-feel §8 covers both).
|
|
327
|
+
- **No Euler objects.** A rotation is a quaternion; Euler angles go
|
|
328
|
+
through `quat.fromEuler` once, where they are written.
|
|
329
|
+
- **No mutation helpers on values.** `vector.add(v)`, `clone()`,
|
|
330
|
+
`multiplyScalar(s)` and the other in-place methods are the pure `vec3`
|
|
331
|
+
and `quat` functions.
|
|
332
|
+
- **No dispose.** Geometries, materials and textures are handles the
|
|
333
|
+
world owns; a streaming group frees its assets when it unloads
|
|
334
|
+
(og-game §6). Drop the `dispose()` calls.
|
|
335
|
+
- **Not in the engine at all**: CSS2DRenderer and CSS3DRenderer (use
|
|
336
|
+
og.ui, or `camera.worldToScreen` for a label's position), the
|
|
337
|
+
`TransformControls` gizmos, `Line2` fat lines (`og.render.lines` has
|
|
338
|
+
`width` already), and any direct WebGL call.
|
|
339
|
+
|
|
340
|
+
## 11. `og migrate three`
|
|
341
|
+
|
|
342
|
+
```sh
|
|
343
|
+
og migrate three src/scene.ts --out src/scene.og.ts
|
|
344
|
+
og check .
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
It reads one TypeScript file that imports three.js (`import * as THREE
|
|
348
|
+
from "three"`, named imports, and the `three/addons` and
|
|
349
|
+
`three/examples/jsm` paths) and writes it back with every mechanical
|
|
350
|
+
mapping above applied:
|
|
351
|
+
|
|
352
|
+
- the three.js imports replaced by one import of `og` (and `color` or
|
|
353
|
+
`quat` when the rewrite uses them) from `@origingame/engine`, and a
|
|
354
|
+
`must` helper added when the file has none;
|
|
355
|
+
- the geometry constructors of §4 to their `og.render` calls with the
|
|
356
|
+
positional arguments named, `new THREE.Shape` and `Path` to `og.Shape`
|
|
357
|
+
and `og.Path2`;
|
|
358
|
+
- the material constructors of §5 to `og.render.standardMaterial`, hex
|
|
359
|
+
and `#rrggbb` colours through `color.fromHex`, the side constants to
|
|
360
|
+
their strings;
|
|
361
|
+
- `Vector2`, `Vector3`, `Quaternion` and `Color` constructions to plain
|
|
362
|
+
values; `MathUtils.degToRad` and `radToDeg` to arithmetic;
|
|
363
|
+
- `const x = new THREE.Mesh(g, m)`, `Group` and `Object3D` to a spawn
|
|
364
|
+
(named after the variable) with og.Mesh; the three lights to a spawn
|
|
365
|
+
with their component, a directional or spot light's `position.set`
|
|
366
|
+
also aiming it at the origin as three.js's default target does;
|
|
367
|
+
- `add` to og.Parent, the scene's `add` deleted, `remove` to
|
|
368
|
+
`world.remove` or `world.despawn`; `position.set`, `quaternion.set`,
|
|
369
|
+
`rotation.set`, `scale.set` and `setScalar` to `world.set` of
|
|
370
|
+
og.Transform; `castShadow`, `receiveShadow`, `visible`, `geometry` and
|
|
371
|
+
`material` assignments to `world.set` of the component;
|
|
372
|
+
- the camera to the og.Camera resource handle, its aspect and
|
|
373
|
+
`updateProjectionMatrix` deleted; `scene.background` to the camera's
|
|
374
|
+
background;
|
|
375
|
+
- the scene, the renderer and everything said to the renderer deleted,
|
|
376
|
+
`document.body.appendChild(renderer.domElement)` too;
|
|
377
|
+
- `TextureLoader` loads of a string to `og.load.texture` of the asset
|
|
378
|
+
id (a leading `./`, `/`, `public/` or `assets/` removed).
|
|
379
|
+
|
|
380
|
+
What is not mechanical stays as it was, under a line
|
|
381
|
+
`// og migrate: <what to do> (three-to-og §<n>)` naming the section here,
|
|
382
|
+
and is listed with its line: the render loop and the Clock (§8), the
|
|
383
|
+
glTF loader (§7), the Raycaster (§9), OrbitControls, InstancedMesh and
|
|
384
|
+
ShaderMaterial (§10), ambient and hemisphere lights (§6), Euler and
|
|
385
|
+
in-place vector arithmetic, a material or geometry parameter og does not
|
|
386
|
+
have, and a `new THREE.Mesh` that is not a declaration of its own. The
|
|
387
|
+
output is not a game yet: the rewritten calls take `world`, so move the
|
|
388
|
+
setup into `GameDesc.start(world)` and the loop into systems, then
|
|
389
|
+
`og check` until it is clean. `--write` rewrites the file in place,
|
|
390
|
+
without `--out` or `--write` the result goes to standard output, and
|
|
391
|
+
`--json` prints the list as one `migrate` event (each item's `line`,
|
|
392
|
+
`kind` of `rewritten`, `removed` or `manual`, the three.js text, what it
|
|
393
|
+
became or what to do, and the section).
|
package/knowledge/knowledge.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"about": "Where each part of @origingame/engine-knowledge lands in the platform's production tree (packages/game-knowledge/production): skills as game/skills/<name>/, the style catalogue (looks/) beside og-taste as its looks/, the generated API wiki as the og-game skill's reference/, and the project template as one scaffold overlay. `@template/` is templates/game in the engine repository and scaffold/template/ (text files, copied at prepack) in the published package.",
|
|
3
|
+
"about": "Where each part of @origingame/engine-knowledge lands in the platform's production tree (packages/game-knowledge/production): skills as game/skills/<name>/, the style catalogue (looks/) beside og-taste as its looks/, the generated API wiki as the og-game skill's reference/, the hand-written guides (guides/: three-to-og) as its guides/, and the project template as one scaffold overlay. `@template/` is templates/game in the engine repository and scaffold/template/ (text files, copied at prepack) in the published package.",
|
|
4
4
|
"overlay": "origin-engine-ts",
|
|
5
5
|
"mounts": [
|
|
6
6
|
{ "from": "skills/", "to": "game/skills/" },
|
|
7
7
|
{ "from": "looks/", "to": "game/skills/og-taste/looks/" },
|
|
8
8
|
{ "from": "wiki/", "to": "game/skills/og-game/reference/" },
|
|
9
|
+
{ "from": "guides/", "to": "game/skills/og-game/guides/" },
|
|
9
10
|
{ "from": "@template/", "to": "game-scaffold/origin-engine-ts/" },
|
|
10
11
|
{ "from": "scaffold/origin-engine.json", "to": "game-scaffold/origin-engine-ts/origin-engine.json" },
|
|
11
12
|
{ "from": "scaffold/distribution.json", "to": "game-scaffold/origin-engine-ts/distribution.json" }
|