nova64 0.2.6 โ 0.2.7
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/dist/examples/strider-demo-3d/fix-game.sh +0 -0
- package/dist/runtime/api-2d.js +1158 -0
- package/dist/runtime/api-3d/camera.js +73 -0
- package/dist/runtime/api-3d/instancing.js +180 -0
- package/dist/runtime/api-3d/lights.js +51 -0
- package/dist/runtime/api-3d/materials.js +47 -0
- package/dist/runtime/api-3d/models.js +84 -0
- package/dist/runtime/api-3d/particles.js +296 -0
- package/dist/runtime/api-3d/pbr.js +113 -0
- package/dist/runtime/api-3d/primitives.js +304 -0
- package/dist/runtime/api-3d/scene.js +169 -0
- package/dist/runtime/api-3d/transforms.js +161 -0
- package/dist/runtime/api-3d.js +166 -0
- package/dist/runtime/api-effects.js +840 -0
- package/dist/runtime/api-gameutils.js +476 -0
- package/dist/runtime/api-generative.js +610 -0
- package/dist/runtime/api-presets.js +85 -0
- package/dist/runtime/api-skybox.js +232 -0
- package/dist/runtime/api-sprites.js +100 -0
- package/dist/runtime/api-voxel.js +712 -0
- package/dist/runtime/api.js +201 -0
- package/dist/runtime/assets.js +27 -0
- package/dist/runtime/audio.js +114 -0
- package/dist/runtime/collision.js +47 -0
- package/dist/runtime/console.js +101 -0
- package/dist/runtime/editor.js +233 -0
- package/dist/runtime/font.js +233 -0
- package/dist/runtime/framebuffer.js +28 -0
- package/dist/runtime/fullscreen-button.js +185 -0
- package/dist/runtime/gpu-canvas2d.js +47 -0
- package/dist/runtime/gpu-threejs.js +643 -0
- package/dist/runtime/gpu-webgl2.js +310 -0
- package/dist/runtime/index.d.ts +682 -0
- package/dist/runtime/index.js +22 -0
- package/dist/runtime/input.js +225 -0
- package/dist/runtime/logger.js +60 -0
- package/dist/runtime/physics.js +101 -0
- package/dist/runtime/screens.js +213 -0
- package/dist/runtime/storage.js +38 -0
- package/dist/runtime/store.js +151 -0
- package/dist/runtime/textinput.js +68 -0
- package/dist/runtime/ui/buttons.js +124 -0
- package/dist/runtime/ui/panels.js +105 -0
- package/dist/runtime/ui/text.js +86 -0
- package/dist/runtime/ui/widgets.js +141 -0
- package/dist/runtime/ui.js +111 -0
- package/package.json +34 -32
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
// runtime/api-3d/scene.js
|
|
2
|
+
// clearScene, setupScene, raycasting, stats, N64 effects
|
|
3
|
+
|
|
4
|
+
import * as THREE from 'three';
|
|
5
|
+
import { logger } from '../logger.js';
|
|
6
|
+
|
|
7
|
+
export function sceneModule(ctx) {
|
|
8
|
+
const {
|
|
9
|
+
scene,
|
|
10
|
+
camera,
|
|
11
|
+
renderer,
|
|
12
|
+
gpu,
|
|
13
|
+
meshes,
|
|
14
|
+
cartLights,
|
|
15
|
+
materialCache,
|
|
16
|
+
instancedMeshes,
|
|
17
|
+
lodObjects,
|
|
18
|
+
} = ctx;
|
|
19
|
+
|
|
20
|
+
// These come from other modules โ resolved at call-time via ctx
|
|
21
|
+
function getDisposeMaterial() {
|
|
22
|
+
return ctx.disposeMaterial;
|
|
23
|
+
}
|
|
24
|
+
function getRemoveLight() {
|
|
25
|
+
return ctx.removeLight;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function clearScene() {
|
|
29
|
+
const disposeMaterial = getDisposeMaterial();
|
|
30
|
+
const removeLight = getRemoveLight();
|
|
31
|
+
|
|
32
|
+
logger.info(
|
|
33
|
+
'๐งน Clearing 3D scene... meshes:',
|
|
34
|
+
meshes.size,
|
|
35
|
+
'lights:',
|
|
36
|
+
cartLights.size,
|
|
37
|
+
'materials:',
|
|
38
|
+
materialCache.size
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
// Dispose all cart meshes
|
|
42
|
+
for (const [, mesh] of meshes) {
|
|
43
|
+
scene.remove(mesh);
|
|
44
|
+
if (mesh.geometry) mesh.geometry.dispose();
|
|
45
|
+
if (mesh.material) {
|
|
46
|
+
if (Array.isArray(mesh.material)) mesh.material.forEach(disposeMaterial);
|
|
47
|
+
else disposeMaterial(mesh.material);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
meshes.clear();
|
|
51
|
+
|
|
52
|
+
// Remove dynamic lights
|
|
53
|
+
cartLights.forEach((_, id) => removeLight(id));
|
|
54
|
+
cartLights.clear();
|
|
55
|
+
|
|
56
|
+
// Flush material cache
|
|
57
|
+
materialCache.forEach(disposeMaterial);
|
|
58
|
+
materialCache.clear();
|
|
59
|
+
|
|
60
|
+
// Remove any remaining scene children (e.g. from loadModel / direct additions)
|
|
61
|
+
while (scene.children.length > 0) {
|
|
62
|
+
const child = scene.children[0];
|
|
63
|
+
scene.remove(child);
|
|
64
|
+
if (child.geometry) child.geometry.dispose();
|
|
65
|
+
if (child.material) {
|
|
66
|
+
if (Array.isArray(child.material)) child.material.forEach(disposeMaterial);
|
|
67
|
+
else disposeMaterial(child.material);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Re-add minimal default lighting so scenes aren't black
|
|
72
|
+
scene.add(new THREE.AmbientLight(0xffffff, 0.5));
|
|
73
|
+
const dir = new THREE.DirectionalLight(0xffffff, 0.8);
|
|
74
|
+
dir.position.set(5, 10, 7.5);
|
|
75
|
+
scene.add(dir);
|
|
76
|
+
|
|
77
|
+
// Reset animated mesh registry in GPU backend
|
|
78
|
+
if (gpu.clearAnimatedMeshes) gpu.clearAnimatedMeshes();
|
|
79
|
+
|
|
80
|
+
// Dispose instanced meshes
|
|
81
|
+
for (const { mesh } of instancedMeshes.values()) {
|
|
82
|
+
scene.remove(mesh);
|
|
83
|
+
mesh.geometry?.dispose();
|
|
84
|
+
mesh.material?.dispose();
|
|
85
|
+
}
|
|
86
|
+
instancedMeshes.clear();
|
|
87
|
+
|
|
88
|
+
// Dispose LOD objects
|
|
89
|
+
for (const lod of lodObjects.values()) {
|
|
90
|
+
scene.remove(lod);
|
|
91
|
+
for (const { object } of lod.levels) {
|
|
92
|
+
object.geometry?.dispose();
|
|
93
|
+
object.material?.dispose();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
lodObjects.clear();
|
|
97
|
+
|
|
98
|
+
logger.info('โ
Scene cleared completely');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* setupScene(opts) โ One-call scene configuration.
|
|
103
|
+
* opts: { camera, light, fog, skybox, effects }
|
|
104
|
+
*/
|
|
105
|
+
function setupScene(opts = {}) {
|
|
106
|
+
const cam = opts.camera ?? {};
|
|
107
|
+
ctx.setCameraPosition(cam.x ?? 0, cam.y ?? 5, cam.z ?? 10);
|
|
108
|
+
ctx.setCameraTarget(cam.targetX ?? 0, cam.targetY ?? 0, cam.targetZ ?? 0);
|
|
109
|
+
if (cam.fov) ctx.setCameraFOV(cam.fov);
|
|
110
|
+
|
|
111
|
+
const light = opts.light ?? {};
|
|
112
|
+
if (light.direction) {
|
|
113
|
+
const d = light.direction;
|
|
114
|
+
ctx.setLightDirection(d[0] ?? -0.3, d[1] ?? -1, d[2] ?? -0.5);
|
|
115
|
+
}
|
|
116
|
+
if (light.color !== undefined) ctx.setLightColor(light.color);
|
|
117
|
+
if (light.ambient !== undefined) ctx.setAmbientLight(light.ambient);
|
|
118
|
+
|
|
119
|
+
if (opts.fog && opts.fog !== false) {
|
|
120
|
+
ctx.setFog(opts.fog.color ?? 0x000000, opts.fog.near ?? 10, opts.fog.far ?? 50);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (opts.skybox && typeof globalThis.createSpaceSkybox === 'function') {
|
|
124
|
+
globalThis.createSpaceSkybox(opts.skybox);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (opts.effects && typeof globalThis.enableRetroEffects === 'function') {
|
|
128
|
+
globalThis.enableRetroEffects(typeof opts.effects === 'object' ? opts.effects : {});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function raycastFromCamera(x, y) {
|
|
133
|
+
const raycaster = new THREE.Raycaster();
|
|
134
|
+
const mouse = new THREE.Vector2(
|
|
135
|
+
(x / renderer.domElement.clientWidth) * 2 - 1,
|
|
136
|
+
-(y / renderer.domElement.clientHeight) * 2 + 1
|
|
137
|
+
);
|
|
138
|
+
raycaster.setFromCamera(mouse, camera);
|
|
139
|
+
const objects = Array.from(meshes.values()).filter(m => m.type === 'Mesh');
|
|
140
|
+
const hits = raycaster.intersectObjects(objects);
|
|
141
|
+
if (hits.length > 0) {
|
|
142
|
+
for (const [id, mesh] of meshes) {
|
|
143
|
+
if (mesh === hits[0].object) {
|
|
144
|
+
return { meshId: id, point: hits[0].point, distance: hits[0].distance };
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function get3DStats() {
|
|
152
|
+
return gpu.getStats();
|
|
153
|
+
}
|
|
154
|
+
function enablePixelation(factor = 2) {
|
|
155
|
+
gpu.enablePixelation(factor);
|
|
156
|
+
}
|
|
157
|
+
function enableDithering(enabled = true) {
|
|
158
|
+
gpu.enableDithering(enabled);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return {
|
|
162
|
+
clearScene,
|
|
163
|
+
setupScene,
|
|
164
|
+
raycastFromCamera,
|
|
165
|
+
get3DStats,
|
|
166
|
+
enablePixelation,
|
|
167
|
+
enableDithering,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// runtime/api-3d/transforms.js
|
|
2
|
+
// Mesh position, rotation, scale, visibility, and shadow controls
|
|
3
|
+
|
|
4
|
+
import { logger } from '../logger.js';
|
|
5
|
+
|
|
6
|
+
export function transformsModule({ getMesh }) {
|
|
7
|
+
function setPosition(meshId, x, y, z) {
|
|
8
|
+
try {
|
|
9
|
+
const mesh = getMesh(meshId);
|
|
10
|
+
if (!mesh) {
|
|
11
|
+
logger.warn(`setPosition: mesh with id ${meshId} not found`);
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
mesh.position.set(
|
|
15
|
+
typeof x === 'number' ? x : 0,
|
|
16
|
+
typeof y === 'number' ? y : 0,
|
|
17
|
+
typeof z === 'number' ? z : 0
|
|
18
|
+
);
|
|
19
|
+
return true;
|
|
20
|
+
} catch (e) {
|
|
21
|
+
logger.error('setPosition failed:', e);
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function setRotation(meshId, x, y, z) {
|
|
27
|
+
try {
|
|
28
|
+
const mesh = getMesh(meshId);
|
|
29
|
+
if (!mesh) {
|
|
30
|
+
logger.warn(`setRotation: mesh with id ${meshId} not found`);
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
mesh.rotation.set(
|
|
34
|
+
typeof x === 'number' ? x : 0,
|
|
35
|
+
typeof y === 'number' ? y : 0,
|
|
36
|
+
typeof z === 'number' ? z : 0
|
|
37
|
+
);
|
|
38
|
+
return true;
|
|
39
|
+
} catch (e) {
|
|
40
|
+
logger.error('setRotation failed:', e);
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function setScale(meshId, x, y, z) {
|
|
46
|
+
try {
|
|
47
|
+
const mesh = getMesh(meshId);
|
|
48
|
+
if (!mesh) {
|
|
49
|
+
logger.warn(`setScale: mesh with id ${meshId} not found`);
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
x = typeof x === 'number' && x > 0 ? x : 1;
|
|
53
|
+
if (typeof y === 'undefined') {
|
|
54
|
+
mesh.scale.setScalar(x);
|
|
55
|
+
} else {
|
|
56
|
+
mesh.scale.set(
|
|
57
|
+
x,
|
|
58
|
+
typeof y === 'number' && y > 0 ? y : 1,
|
|
59
|
+
typeof z === 'number' && z > 0 ? z : 1
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
return true;
|
|
63
|
+
} catch (e) {
|
|
64
|
+
logger.error('setScale failed:', e);
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function getPosition(meshId) {
|
|
70
|
+
const mesh = getMesh(meshId);
|
|
71
|
+
return mesh ? [mesh.position.x, mesh.position.y, mesh.position.z] : null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function getRotation(meshId) {
|
|
75
|
+
const mesh = getMesh(meshId);
|
|
76
|
+
return mesh ? [mesh.rotation.x, mesh.rotation.y, mesh.rotation.z] : null;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function rotateMesh(meshId, dX, dY, dZ) {
|
|
80
|
+
try {
|
|
81
|
+
const mesh = getMesh(meshId);
|
|
82
|
+
if (!mesh) {
|
|
83
|
+
logger.warn(`rotateMesh: mesh with id ${meshId} not found`);
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
mesh.rotation.x += typeof dX === 'number' ? dX : 0;
|
|
87
|
+
mesh.rotation.y += typeof dY === 'number' ? dY : 0;
|
|
88
|
+
mesh.rotation.z += typeof dZ === 'number' ? dZ : 0;
|
|
89
|
+
return true;
|
|
90
|
+
} catch (e) {
|
|
91
|
+
logger.error('rotateMesh failed:', e);
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function moveMesh(meshId, x, y, z) {
|
|
97
|
+
const mesh = getMesh(meshId);
|
|
98
|
+
if (mesh) {
|
|
99
|
+
mesh.position.x += x;
|
|
100
|
+
mesh.position.y += y;
|
|
101
|
+
mesh.position.z += z;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function setFlatShading(meshId, enabled = true) {
|
|
106
|
+
const mesh = getMesh(meshId);
|
|
107
|
+
if (!mesh) return false;
|
|
108
|
+
if (mesh.material) {
|
|
109
|
+
mesh.material.flatShading = enabled;
|
|
110
|
+
mesh.material.needsUpdate = true;
|
|
111
|
+
}
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function setMeshVisible(meshId, visible) {
|
|
116
|
+
const mesh = getMesh(meshId);
|
|
117
|
+
if (!mesh) return false;
|
|
118
|
+
mesh.visible = visible;
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function setMeshOpacity(meshId, opacity) {
|
|
123
|
+
const mesh = getMesh(meshId);
|
|
124
|
+
if (!mesh) return false;
|
|
125
|
+
if (mesh.material) {
|
|
126
|
+
mesh.material.transparent = opacity < 1;
|
|
127
|
+
mesh.material.opacity = opacity;
|
|
128
|
+
mesh.material.needsUpdate = true;
|
|
129
|
+
}
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function setCastShadow(meshId, cast) {
|
|
134
|
+
const mesh = getMesh(meshId);
|
|
135
|
+
if (!mesh) return false;
|
|
136
|
+
mesh.castShadow = cast;
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function setReceiveShadow(meshId, receive) {
|
|
141
|
+
const mesh = getMesh(meshId);
|
|
142
|
+
if (!mesh) return false;
|
|
143
|
+
mesh.receiveShadow = receive;
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
setPosition,
|
|
149
|
+
setRotation,
|
|
150
|
+
setScale,
|
|
151
|
+
getPosition,
|
|
152
|
+
getRotation,
|
|
153
|
+
rotateMesh,
|
|
154
|
+
moveMesh,
|
|
155
|
+
setFlatShading,
|
|
156
|
+
setMeshVisible,
|
|
157
|
+
setMeshOpacity,
|
|
158
|
+
setCastShadow,
|
|
159
|
+
setReceiveShadow,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
// runtime/api-3d.js
|
|
2
|
+
// Thin orchestrator โ delegates to runtime/api-3d/*.js sub-modules
|
|
3
|
+
import * as THREE from 'three';
|
|
4
|
+
globalThis.THREE = THREE;
|
|
5
|
+
import { materialsModule } from './api-3d/materials.js';
|
|
6
|
+
import { primitivesModule } from './api-3d/primitives.js';
|
|
7
|
+
import { transformsModule } from './api-3d/transforms.js';
|
|
8
|
+
import { cameraModule } from './api-3d/camera.js';
|
|
9
|
+
import { lightsModule } from './api-3d/lights.js';
|
|
10
|
+
import { modelsModule } from './api-3d/models.js';
|
|
11
|
+
import { instancingModule } from './api-3d/instancing.js';
|
|
12
|
+
import { pbrModule } from './api-3d/pbr.js';
|
|
13
|
+
import { sceneModule } from './api-3d/scene.js';
|
|
14
|
+
import { particlesModule } from './api-3d/particles.js';
|
|
15
|
+
|
|
16
|
+
export function threeDApi(gpu) {
|
|
17
|
+
if (!gpu.getScene) return { exposeTo: () => {} };
|
|
18
|
+
|
|
19
|
+
const scene = gpu.getScene();
|
|
20
|
+
const camera = gpu.getCamera();
|
|
21
|
+
const renderer = gpu.getRenderer();
|
|
22
|
+
|
|
23
|
+
// Shared state โ passed by reference into every sub-module
|
|
24
|
+
const meshes = new Map();
|
|
25
|
+
const mixers = new Map();
|
|
26
|
+
const modelAnimations = new Map();
|
|
27
|
+
const materialCache = new Map();
|
|
28
|
+
const cartLights = new Map();
|
|
29
|
+
const instancedMeshes = new Map();
|
|
30
|
+
const lodObjects = new Map();
|
|
31
|
+
const counters = { mesh: 0, light: 0, instance: 0, lod: 0 };
|
|
32
|
+
|
|
33
|
+
// Build context โ each module appends its exports so later modules can call earlier ones
|
|
34
|
+
const ctx = {
|
|
35
|
+
scene,
|
|
36
|
+
camera,
|
|
37
|
+
renderer,
|
|
38
|
+
gpu,
|
|
39
|
+
meshes,
|
|
40
|
+
mixers,
|
|
41
|
+
modelAnimations,
|
|
42
|
+
materialCache,
|
|
43
|
+
cartLights,
|
|
44
|
+
instancedMeshes,
|
|
45
|
+
lodObjects,
|
|
46
|
+
counters,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
Object.assign(ctx, materialsModule(ctx));
|
|
50
|
+
Object.assign(ctx, primitivesModule(ctx));
|
|
51
|
+
Object.assign(ctx, transformsModule(ctx));
|
|
52
|
+
Object.assign(ctx, cameraModule(ctx));
|
|
53
|
+
Object.assign(ctx, lightsModule(ctx));
|
|
54
|
+
Object.assign(ctx, modelsModule(ctx));
|
|
55
|
+
Object.assign(ctx, instancingModule(ctx));
|
|
56
|
+
Object.assign(ctx, pbrModule(ctx));
|
|
57
|
+
Object.assign(ctx, particlesModule(ctx));
|
|
58
|
+
Object.assign(ctx, sceneModule(ctx)); // last: uses late binding to call other modules
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
exposeTo(target) {
|
|
62
|
+
Object.assign(target, {
|
|
63
|
+
// Primitive creation
|
|
64
|
+
createCube: ctx.createCube,
|
|
65
|
+
createSphere: ctx.createSphere,
|
|
66
|
+
createCylinder: ctx.createCylinder,
|
|
67
|
+
createPlane: ctx.createPlane,
|
|
68
|
+
createAdvancedCube: ctx.createAdvancedCube,
|
|
69
|
+
createAdvancedSphere: ctx.createAdvancedSphere,
|
|
70
|
+
createTorus: ctx.createTorus,
|
|
71
|
+
createCone: ctx.createCone,
|
|
72
|
+
createCapsule: ctx.createCapsule,
|
|
73
|
+
|
|
74
|
+
// Mesh management
|
|
75
|
+
destroyMesh: ctx.destroyMesh,
|
|
76
|
+
removeMesh: ctx.removeMesh,
|
|
77
|
+
|
|
78
|
+
// Model and texture loading
|
|
79
|
+
loadModel: ctx.loadModel,
|
|
80
|
+
playAnimation: ctx.playAnimation,
|
|
81
|
+
updateAnimations: ctx.updateAnimations,
|
|
82
|
+
loadTexture: ctx.loadTexture,
|
|
83
|
+
|
|
84
|
+
// Transforms
|
|
85
|
+
setPosition: ctx.setPosition,
|
|
86
|
+
setRotation: ctx.setRotation,
|
|
87
|
+
setScale: ctx.setScale,
|
|
88
|
+
getPosition: ctx.getPosition,
|
|
89
|
+
getRotation: ctx.getRotation,
|
|
90
|
+
rotateMesh: ctx.rotateMesh,
|
|
91
|
+
moveMesh: ctx.moveMesh,
|
|
92
|
+
|
|
93
|
+
// Mesh helpers
|
|
94
|
+
setFlatShading: ctx.setFlatShading,
|
|
95
|
+
setMeshVisible: ctx.setMeshVisible,
|
|
96
|
+
setMeshOpacity: ctx.setMeshOpacity,
|
|
97
|
+
setCastShadow: ctx.setCastShadow,
|
|
98
|
+
setReceiveShadow: ctx.setReceiveShadow,
|
|
99
|
+
|
|
100
|
+
// Camera
|
|
101
|
+
setCameraPosition: ctx.setCameraPosition,
|
|
102
|
+
setCameraTarget: ctx.setCameraTarget,
|
|
103
|
+
setCameraLookAt: ctx.setCameraLookAt,
|
|
104
|
+
setCameraFOV: ctx.setCameraFOV,
|
|
105
|
+
|
|
106
|
+
// Scene / atmosphere
|
|
107
|
+
setFog: ctx.setFog,
|
|
108
|
+
clearFog: ctx.clearFog,
|
|
109
|
+
setLightDirection: ctx.setLightDirection,
|
|
110
|
+
setLightColor: ctx.setLightColor,
|
|
111
|
+
setAmbientLight: ctx.setAmbientLight,
|
|
112
|
+
setDirectionalLight: ctx.setDirectionalLight,
|
|
113
|
+
clearScene: ctx.clearScene,
|
|
114
|
+
|
|
115
|
+
// Effects
|
|
116
|
+
enablePixelation: ctx.enablePixelation,
|
|
117
|
+
enableDithering: ctx.enableDithering,
|
|
118
|
+
|
|
119
|
+
// Dynamic lights
|
|
120
|
+
createPointLight: ctx.createPointLight,
|
|
121
|
+
setPointLightPosition: ctx.setPointLightPosition,
|
|
122
|
+
setPointLightColor: ctx.setPointLightColor,
|
|
123
|
+
removeLight: ctx.removeLight,
|
|
124
|
+
|
|
125
|
+
// GPU instancing
|
|
126
|
+
createInstancedMesh: ctx.createInstancedMesh,
|
|
127
|
+
setInstanceTransform: ctx.setInstanceTransform,
|
|
128
|
+
setInstanceColor: ctx.setInstanceColor,
|
|
129
|
+
finalizeInstances: ctx.finalizeInstances,
|
|
130
|
+
removeInstancedMesh: ctx.removeInstancedMesh,
|
|
131
|
+
|
|
132
|
+
// LOD system
|
|
133
|
+
createLODMesh: ctx.createLODMesh,
|
|
134
|
+
setLODPosition: ctx.setLODPosition,
|
|
135
|
+
removeLODMesh: ctx.removeLODMesh,
|
|
136
|
+
updateLODs: ctx.updateLODs,
|
|
137
|
+
|
|
138
|
+
// Normal / PBR maps
|
|
139
|
+
loadNormalMap: ctx.loadNormalMap,
|
|
140
|
+
setNormalMap: ctx.setNormalMap,
|
|
141
|
+
setPBRMaps: ctx.setPBRMaps,
|
|
142
|
+
setPBRProperties: ctx.setPBRProperties,
|
|
143
|
+
|
|
144
|
+
// GPU particle system
|
|
145
|
+
createParticleSystem: ctx.createParticleSystem,
|
|
146
|
+
setParticleEmitter: ctx.setParticleEmitter,
|
|
147
|
+
emitParticle: ctx.emitParticle,
|
|
148
|
+
burstParticles: ctx.burstParticles,
|
|
149
|
+
updateParticles: ctx.updateParticles,
|
|
150
|
+
removeParticleSystem: ctx.removeParticleSystem,
|
|
151
|
+
getParticleStats: ctx.getParticleStats,
|
|
152
|
+
|
|
153
|
+
// Interaction / stats / convenience
|
|
154
|
+
raycastFromCamera: ctx.raycastFromCamera,
|
|
155
|
+
get3DStats: ctx.get3DStats,
|
|
156
|
+
setupScene: ctx.setupScene,
|
|
157
|
+
|
|
158
|
+
// Direct Three.js access for advanced users
|
|
159
|
+
getScene: () => scene,
|
|
160
|
+
getCamera: () => camera,
|
|
161
|
+
getRenderer: () => renderer,
|
|
162
|
+
getMesh: ctx.getMesh,
|
|
163
|
+
});
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
}
|