@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.
Files changed (118) hide show
  1. package/bin/og.mjs +1 -1
  2. package/dist/web/origin-engine.d.ts +255 -5
  3. package/dist/web/origin-engine.js +1584 -125
  4. package/dist/web/origin-engine_bg.wasm +0 -0
  5. package/dist/web/origin-engine_bg.wasm.d.ts +80 -3
  6. package/dist/web-publish/origin-engine-lanes.js +1288 -82
  7. package/dist/web-publish/origin-engine-lanes_bg.wasm +0 -0
  8. package/dist/web-publish/origin-engine.d.ts +199 -6
  9. package/dist/web-publish/origin-engine.js +1285 -79
  10. package/dist/web-publish/origin-engine_bg.wasm +0 -0
  11. package/dist/web-publish/origin-engine_bg.wasm.d.ts +65 -4
  12. package/dist/web-publish-2d/origin-engine-lanes.js +1285 -79
  13. package/dist/web-publish-2d/origin-engine-lanes_bg.wasm +0 -0
  14. package/dist/web-publish-2d/origin-engine.d.ts +198 -5
  15. package/dist/web-publish-2d/origin-engine.js +1282 -76
  16. package/dist/web-publish-2d/origin-engine_bg.wasm +0 -0
  17. package/dist/web-publish-2d/origin-engine_bg.wasm.d.ts +64 -3
  18. package/knowledge/README.md +2 -1
  19. package/knowledge/guides/three-to-og.md +393 -0
  20. package/knowledge/knowledge.json +2 -1
  21. package/knowledge/looks/catalogue.json +40 -40
  22. package/knowledge/package.json +3 -2
  23. package/knowledge/scaffold/distribution.json +14 -0
  24. package/knowledge/scaffold/origin-engine.json +2 -2
  25. package/knowledge/scaffold/template/README.md +2 -1
  26. package/knowledge/scaffold/template/assets/audio/sting.ogt +10 -0
  27. package/knowledge/scaffold/template/assets/timelines/intro.ogt +101 -0
  28. package/knowledge/scaffold/template/assets/timelines/narration.srt +11 -0
  29. package/knowledge/scaffold/template/host.d.ts +46 -0
  30. package/knowledge/scaffold/template/package.json +1 -1
  31. package/knowledge/scaffold/template/project.ogt +1 -1
  32. package/knowledge/scaffold/template/src/main.ts +1 -1
  33. package/knowledge/scaffold/template/tests/frames.ts +134 -0
  34. package/knowledge/scaffold/template/tests/intro.og.ts +65 -0
  35. package/knowledge/scaffold/template/tests/smoke.og.ts +30 -36
  36. package/knowledge/scaffold/template/tsconfig.json +1 -1
  37. package/knowledge/scripts/mount.ts +2 -1
  38. package/knowledge/scripts/validate.ts +159 -31
  39. package/knowledge/skills/og-audio/SKILL.md +2 -2
  40. package/knowledge/skills/og-build/SKILL.md +29 -7
  41. package/knowledge/skills/og-core/SKILL.md +31 -5
  42. package/knowledge/skills/og-feel/SKILL.md +2 -2
  43. package/knowledge/skills/og-game/SKILL.md +1331 -16
  44. package/knowledge/skills/og-i18n/SKILL.md +7 -7
  45. package/knowledge/skills/og-model/SKILL.md +374 -0
  46. package/knowledge/skills/og-platform-sdk/SKILL.md +2 -1
  47. package/knowledge/skills/og-taste/SKILL.md +82 -73
  48. package/knowledge/skills/og-ui/SKILL.md +80 -58
  49. package/knowledge/wiki/ai.md +20 -20
  50. package/knowledge/wiki/anim.md +392 -41
  51. package/knowledge/wiki/atmosphere.md +36 -13
  52. package/knowledge/wiki/audio.md +18 -18
  53. package/knowledge/wiki/camera.md +19 -13
  54. package/knowledge/wiki/commands.md +19 -13
  55. package/knowledge/wiki/debug.md +414 -0
  56. package/knowledge/wiki/game.md +8 -8
  57. package/knowledge/wiki/i18n.md +7 -7
  58. package/knowledge/wiki/index.md +317 -8
  59. package/knowledge/wiki/input.md +47 -47
  60. package/knowledge/wiki/load.md +238 -70
  61. package/knowledge/wiki/math.md +2607 -0
  62. package/knowledge/wiki/nav.md +34 -34
  63. package/knowledge/wiki/net.md +340 -0
  64. package/knowledge/wiki/path.md +402 -0
  65. package/knowledge/wiki/physics.md +95 -95
  66. package/knowledge/wiki/platform.md +463 -29
  67. package/knowledge/wiki/probe.md +681 -67
  68. package/knowledge/wiki/reflect.md +29 -17
  69. package/knowledge/wiki/render.md +4993 -1998
  70. package/knowledge/wiki/rng.md +14 -14
  71. package/knowledge/wiki/shapes.md +727 -0
  72. package/knowledge/wiki/stream.md +15 -15
  73. package/knowledge/wiki/system.md +8 -8
  74. package/knowledge/wiki/systems.md +2 -2
  75. package/knowledge/wiki/terrain.md +24 -20
  76. package/knowledge/wiki/tilemap.md +13 -13
  77. package/knowledge/wiki/time.md +4 -4
  78. package/knowledge/wiki/timeline.md +396 -0
  79. package/knowledge/wiki/transform.md +8 -8
  80. package/knowledge/wiki/tween.md +17 -17
  81. package/knowledge/wiki/ui.md +560 -654
  82. package/knowledge/wiki/video.md +157 -0
  83. package/knowledge/wiki/world.md +36 -36
  84. package/package.json +4 -3
  85. package/schema/api.schema.json +28151 -19640
  86. package/shell/page.ts +26 -2
  87. package/shell/platform.ts +51 -0
  88. package/shell/player.ts +15 -2
  89. package/shell/transport.ts +6 -0
  90. package/src/depth.ts +71 -0
  91. package/src/e6.ts +32 -1
  92. package/src/env.d.ts +5 -1
  93. package/src/generated/abi.ts +226 -4
  94. package/src/geom.ts +260 -0
  95. package/src/index.ts +32 -4
  96. package/src/light.ts +18 -0
  97. package/src/math.ts +622 -0
  98. package/src/node/index.ts +17 -0
  99. package/src/node/playtest-run.ts +115 -18
  100. package/src/node/polish.ts +13 -3
  101. package/src/node/render.ts +291 -0
  102. package/src/node/run.ts +86 -5
  103. package/src/p2.ts +19 -1
  104. package/src/platform-local.ts +2 -0
  105. package/src/playtest.ts +65 -4
  106. package/src/runtime.ts +100 -9
  107. package/src/targets.ts +28 -0
  108. package/src/trace.ts +169 -0
  109. package/src/ui-kit/huds.ts +34 -34
  110. package/src/ui-kit/menus.ts +12 -12
  111. package/src/ui-kit/settings.ts +11 -2
  112. package/src/ui-kit/store.ts +18 -18
  113. package/src/ui-kit/story.ts +6 -4
  114. package/src/ui-kit/util.ts +8 -8
  115. package/src/web/shell.ts +59 -1
  116. package/src/web/worker.ts +105 -4
  117. package/types/bindings.json +9368 -6619
  118. package/types/index.d.ts +16377 -11520
@@ -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 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__333: (a: number, b: number, c: any) => [number, number];
338
- 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__334: (a: number, b: number, c: any) => [number, number];
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;
@@ -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, skins, 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-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>/` |
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).
@@ -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" }