ohzi-core 13.3.0 → 15.0.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/README.md +2 -1
- package/build/index.mjs +1 -1
- package/build/index.mjs.map +1 -1
- package/package.json +12 -6
- package/src/Capabilities.ts +0 -2
- package/src/Debug.ts +38 -33
- package/src/Graphics.ts +2 -2
- package/src/Initializer.ts +2 -1
- package/src/SceneManager.ts +4 -5
- package/src/action_sequencer/NumberInterpolator.ts +2 -0
- package/src/blitter_index.ts +1 -2
- package/src/camera_controller/CameraController.ts +106 -63
- package/src/camera_controller/states/common/CommonCameraState.ts +2 -1
- package/src/components/AxisHelper.ts +1 -0
- package/src/components/Line.ts +35 -27
- package/src/components/PlaneHelper.ts +1 -1
- package/src/components/Text2D.ts +3 -1
- package/src/components/WorldImage.ts +27 -20
- package/src/components/sdf_text/SDFTextBatch.ts +16 -26
- package/src/dev_bridge/CameraBridge.ts +363 -0
- package/src/dev_bridge/CaptureService.ts +256 -0
- package/src/dev_bridge/CommandDispatcher.ts +114 -0
- package/src/dev_bridge/ConsoleBuffer.ts +286 -0
- package/src/dev_bridge/DebugDrawer.ts +399 -0
- package/src/dev_bridge/DevBridge.ts +195 -0
- package/src/dev_bridge/InputSynthesizer.ts +287 -0
- package/src/dev_bridge/PerformanceProbe.ts +118 -0
- package/src/dev_bridge/RenderModeRegistry.ts +66 -0
- package/src/dev_bridge/SceneEditor.ts +288 -0
- package/src/dev_bridge/SceneInspector.ts +388 -0
- package/src/dev_bridge/ViewNavigator.ts +101 -0
- package/src/dev_bridge/protocol.ts +31 -0
- package/src/index.ts +21 -14
- package/src/materials/AddMaterial.ts +14 -7
- package/src/materials/BlitNodeMaterial.ts +85 -0
- package/src/materials/BloomComposeMaterial.ts +21 -9
- package/src/materials/BoxBlurMaterial.ts +26 -6
- package/src/materials/ClearDepthNormalMaterial.ts +12 -6
- package/src/materials/DepthNormalMaterial.ts +25 -14
- package/src/materials/DualFilteringBlurMaterial.ts +32 -5
- package/src/materials/GaussianBlurMaterial.ts +36 -14
- package/src/materials/LineMaterial.ts +52 -0
- package/src/materials/LuminosityHighPassMaterial.ts +23 -10
- package/src/materials/NormalMaterial.ts +10 -11
- package/src/materials/SDFTextMaterial.ts +63 -16
- package/src/materials/SSAOComposeMaterial.ts +14 -5
- package/src/materials/SSAOMaterial.ts +123 -24
- package/src/materials/ScreenSpaceTextureMaterial.ts +19 -31
- package/src/materials/UnrealBloomComposeMaterial.ts +41 -32
- package/src/materials/WorldImageMaterial.ts +51 -0
- package/src/materials/deferred/DeferredPointLightMaterial.ts +45 -14
- package/src/materials/deferred/depth_normal_encoding.ts +36 -0
- package/src/primitives/Cube.ts +1 -1
- package/src/primitives/Sphere.ts +1 -1
- package/src/raycast/GroupRaycaster.ts +2 -2
- package/src/render_mode/BloomRender.ts +18 -4
- package/src/render_mode/DebugNormalsRender.ts +6 -1
- package/src/render_mode/DeferredRender.ts +5 -34
- package/src/render_mode/NormalAORender.ts +9 -19
- package/src/render_mode/UnrealBloomRender.ts +2 -1
- package/src/render_mode/VRRender.ts +6 -3
- package/src/render_utilities/Blitter.ts +4 -4
- package/src/render_utilities/Blurrer.ts +7 -0
- package/src/render_utilities/DualFilteringBlurrer.ts +26 -10
- package/src/resource_loader/AudioLoader.ts +5 -3
- package/src/resource_loader/HDRTextureLoader.ts +1 -1
- package/src/scenes/AbstractScene.ts +7 -3
- package/src/scenes/Compilator.ts +5 -1
- package/src/scenes/loading_states/LoadingState.ts +15 -7
- package/src/scenes/loading_states/RegularLoadingState.ts +2 -1
- package/src/utilities/CameraUtilities.ts +57 -79
- package/src/utilities/HTMLUtilities.ts +2 -1
- package/src/utilities/MeshSampler.ts +8 -1
- package/src/utilities/OrthographicFrustumPointFitter.ts +53 -4
- package/src/view_components/ApplicationView.ts +1 -1
- package/src/view_components/ViewComponent.ts +1 -1
- package/src/view_components/ViewManager.ts +7 -1
- package/src/view_components/transition/DrawIOAnimationSheet.ts +1 -1
- package/types/Capabilities.d.ts +0 -1
- package/types/SceneManager.d.ts +1 -1
- package/types/blitter_index.d.ts +1 -2
- package/types/camera_controller/CameraController.d.ts +9 -0
- package/types/components/Line.d.ts +3 -2
- package/types/components/WorldImage.d.ts +3 -2
- package/types/index.d.ts +2 -7
- package/types/materials/AddMaterial.d.ts +2 -2
- package/types/materials/BlitNodeMaterial.d.ts +18 -0
- package/types/materials/BloomComposeMaterial.d.ts +2 -2
- package/types/materials/BoxBlurMaterial.d.ts +2 -2
- package/types/materials/ClearDepthNormalMaterial.d.ts +2 -2
- package/types/materials/DepthNormalMaterial.d.ts +2 -2
- package/types/materials/DualFilteringBlurMaterial.d.ts +2 -2
- package/types/materials/GaussianBlurMaterial.d.ts +2 -2
- package/types/materials/LuminosityHighPassMaterial.d.ts +2 -2
- package/types/materials/NormalMaterial.d.ts +2 -2
- package/types/materials/SDFTextMaterial.d.ts +2 -2
- package/types/materials/SSAOComposeMaterial.d.ts +2 -2
- package/types/materials/SSAOMaterial.d.ts +2 -2
- package/types/materials/ScreenSpaceTextureMaterial.d.ts +2 -2
- package/types/materials/UnrealBloomComposeMaterial.d.ts +2 -2
- package/types/materials/deferred/DeferredPointLightMaterial.d.ts +2 -2
- package/types/render_mode/DeferredRender.d.ts +0 -2
- package/types/render_mode/NormalAORender.d.ts +0 -2
- package/types/render_utilities/Blitter.d.ts +2 -2
- package/types/render_utilities/DualFilteringBlurrer.d.ts +0 -2
- package/types/utilities/CameraUtilities.d.ts +0 -1
- package/types/utilities/OrthographicFrustumPointFitter.d.ts +14 -8
- package/build/index.module.js +0 -2
- package/build/index.module.js.map +0 -1
- package/src/components/EdgeMesh.ts +0 -150
- package/src/components/GeometryEdgeVisualizer.ts +0 -49
- package/src/components/MultiLinePath.ts +0 -25
- package/src/components/MultiLineText2D.ts +0 -65
- package/src/components/Shape2D.ts +0 -42
- package/src/components/Shape3D.ts +0 -38
- package/src/gpu_particles/GPUParticleSystem.ts +0 -122
- package/src/gpu_particles/ParticleAttribute.ts +0 -110
- package/src/gpu_particles/ParticlePositionAttribute.ts +0 -46
- package/src/materials/AlphaFilterMaterial.ts +0 -21
- package/src/materials/BaseShaderMaterial.ts +0 -20
- package/src/materials/BlitMaterial.ts +0 -27
- package/src/materials/DeferredRendererComposeMaterial.ts +0 -36
- package/src/materials/DisplayNormalTextureMaterial.ts +0 -18
- package/src/materials/FXAAMaterial.ts +0 -12
- package/src/materials/MedianFilterMaterial.ts +0 -46
- package/src/materials/SDFScreenTextMaterial.ts +0 -32
- package/src/materials/UnrealBlurMaterial.ts +0 -20
- package/src/materials/UnrealComposeMaterial.ts +0 -27
- package/src/materials/ViewPositionMaterial.ts +0 -19
- package/src/materials/gpu_particles/AttributeUpdateMaterial.ts +0 -35
- package/src/materials/gpu_particles/BasicParticleMaterial.ts +0 -25
- package/src/materials/gpu_particles/ParticleStorageMaterial.ts +0 -36
- package/src/materials/gpu_particles/PositionStorageMaterial.ts +0 -27
- package/src/render_utilities/MedianFilter.ts +0 -72
- package/src/render_utilities/ViewPositionRenderer.ts +0 -53
- package/src/shaders/add/add.frag +0 -28
- package/src/shaders/anti_aliasing/fxaa.frag +0 -72
- package/src/shaders/basic_color/basic_color.frag +0 -6
- package/src/shaders/basic_color/basic_color.vert +0 -10
- package/src/shaders/basic_line/basic_line.frag +0 -37
- package/src/shaders/basic_line/basic_line.vert +0 -37
- package/src/shaders/basic_texture/basic_texture.frag +0 -10
- package/src/shaders/basic_texture/basic_texture.vert +0 -17
- package/src/shaders/bloom/bloom_compose.frag +0 -22
- package/src/shaders/bloom/cheap_bloom_compose.frag +0 -13
- package/src/shaders/box_blur/box_blur.frag +0 -24
- package/src/shaders/box_blur/compose.frag +0 -31
- package/src/shaders/clear/clear_depth_normal.frag +0 -25
- package/src/shaders/copy/copy.frag +0 -7
- package/src/shaders/copy/copy.vert +0 -6
- package/src/shaders/deferred/blit_copy.vert +0 -11
- package/src/shaders/deferred/deferred_compose.frag +0 -59
- package/src/shaders/deferred/point_light.frag +0 -66
- package/src/shaders/deferred/point_light.vert +0 -13
- package/src/shaders/depth_normals/debug_normals.frag +0 -48
- package/src/shaders/depth_normals/depth_normals.frag +0 -30
- package/src/shaders/depth_normals/depth_normals.vert +0 -13
- package/src/shaders/dual_filter_blur/alpha_filter.frag +0 -14
- package/src/shaders/dual_filter_blur/downsample.frag +0 -21
- package/src/shaders/dual_filter_blur/upsample.frag +0 -24
- package/src/shaders/edge_visualizer/edge_visualizer.frag +0 -18
- package/src/shaders/edge_visualizer/edge_visualizer.vert +0 -16
- package/src/shaders/edges/corners.frag +0 -11
- package/src/shaders/edges/corners.vert +0 -31
- package/src/shaders/edges/edges.frag +0 -7
- package/src/shaders/edges/edges.vert +0 -27
- package/src/shaders/gaussian_blur/gaussian_blur.frag +0 -44
- package/src/shaders/gaussian_blur/unreal_bloom_compose.frag +0 -36
- package/src/shaders/gpu_particles/common_utils.glsl +0 -13
- package/src/shaders/gpu_particles/generic_storage.frag +0 -6
- package/src/shaders/gpu_particles/store/store_position.vert +0 -14
- package/src/shaders/gpu_particles/update/basic_update.frag +0 -21
- package/src/shaders/gpu_particles/visualize/visualize.frag +0 -11
- package/src/shaders/gpu_particles/visualize/visualize.vert +0 -12
- package/src/shaders/grid/grid.frag +0 -17
- package/src/shaders/grid/grid.vert +0 -10
- package/src/shaders/luminosity_high_pass/luminosity_high_pass.frag +0 -38
- package/src/shaders/median_filter/median_filter.frag +0 -134
- package/src/shaders/normal/normal.frag +0 -6
- package/src/shaders/normal/normal.vert +0 -6
- package/src/shaders/sdf_text/sdf_screen_text.frag +0 -51
- package/src/shaders/sdf_text/sdf_screen_text.vert +0 -42
- package/src/shaders/sdf_text/sdf_text.frag +0 -53
- package/src/shaders/sdf_text/sdf_text.vert +0 -42
- package/src/shaders/ssao/hbao.frag +0 -264
- package/src/shaders/ssao/ssao.frag +0 -95
- package/src/shaders/ssao/ssao.vert +0 -11
- package/src/shaders/ssao/ssao_compose.frag +0 -14
- package/src/shaders/transparent_mix/copy.frag +0 -7
- package/src/shaders/transparent_mix/transparent_mix.frag +0 -19
- package/src/shaders/transparent_mix/transparent_mix.vert +0 -8
- package/src/shaders/ui/ss_texture.frag +0 -11
- package/src/shaders/ui/ss_texture.vert +0 -32
- package/src/shaders/ui/ws_texture.vert +0 -39
- package/src/shaders/unreal_blur/unreal_blur.frag +0 -25
- package/src/shaders/unreal_blur/unreal_compose.frag +0 -24
- package/src/shaders/write_view_position/write_view_position.frag +0 -7
- package/src/shaders/write_view_position/write_view_position.vert +0 -9
- package/src/types.d.ts +0 -14
- package/types/components/EdgeMesh.d.ts +0 -16
- package/types/components/GeometryEdgeVisualizer.d.ts +0 -8
- package/types/components/MultiLinePath.d.ts +0 -8
- package/types/components/MultiLineText2D.d.ts +0 -12
- package/types/components/Shape2D.d.ts +0 -7
- package/types/components/Shape3D.d.ts +0 -6
- package/types/gpu_particles/GPUParticleSystem.d.ts +0 -19
- package/types/gpu_particles/ParticleAttribute.d.ts +0 -20
- package/types/gpu_particles/ParticlePositionAttribute.d.ts +0 -6
- package/types/materials/AlphaFilterMaterial.d.ts +0 -7
- package/types/materials/BaseShaderMaterial.d.ts +0 -4
- package/types/materials/BlitMaterial.d.ts +0 -4
- package/types/materials/DeferredRendererComposeMaterial.d.ts +0 -10
- package/types/materials/DisplayNormalTextureMaterial.d.ts +0 -4
- package/types/materials/FXAAMaterial.d.ts +0 -5
- package/types/materials/MedianFilterMaterial.d.ts +0 -8
- package/types/materials/SDFScreenTextMaterial.d.ts +0 -8
- package/types/materials/UIElementMaterial.d.ts +0 -4
- package/types/materials/UnrealBlurMaterial.d.ts +0 -5
- package/types/materials/UnrealComposeMaterial.d.ts +0 -5
- package/types/materials/ViewPositionMaterial.d.ts +0 -5
- package/types/materials/gpu_particles/AttributeUpdateMaterial.d.ts +0 -8
- package/types/materials/gpu_particles/BasicParticleMaterial.d.ts +0 -5
- package/types/materials/gpu_particles/ParticleStorageMaterial.d.ts +0 -5
- package/types/materials/gpu_particles/PositionStorageMaterial.d.ts +0 -5
- package/types/render_utilities/MedianFilter.d.ts +0 -12
- package/types/render_utilities/ViewPositionRenderer.d.ts +0 -12
package/src/components/Line.ts
CHANGED
|
@@ -1,36 +1,31 @@
|
|
|
1
|
-
import
|
|
2
|
-
import line_vs from '../shaders/basic_line/basic_line.vert';
|
|
1
|
+
import { LineMaterial } from '../materials/LineMaterial';
|
|
3
2
|
|
|
4
|
-
import type { Vector3 } from 'three';
|
|
5
|
-
import { BufferAttribute, BufferGeometry,
|
|
3
|
+
import type { Color, ColorRepresentation, Vector3 } from 'three';
|
|
4
|
+
import { BufferAttribute, BufferGeometry, Mesh } from 'three';
|
|
5
|
+
|
|
6
|
+
// An empty geometry with every attribute LineMaterial reads.
|
|
7
|
+
function create_line_geometry(): BufferGeometry
|
|
8
|
+
{
|
|
9
|
+
const geometry = new BufferGeometry();
|
|
10
|
+
geometry.setAttribute('position', new BufferAttribute(new Float32Array([]), 3));
|
|
11
|
+
geometry.setAttribute('next_position', new BufferAttribute(new Float32Array([]), 3));
|
|
12
|
+
geometry.setAttribute('previous_position', new BufferAttribute(new Float32Array([]), 3));
|
|
13
|
+
geometry.setAttribute('orientation', new BufferAttribute(new Float32Array([]), 1));
|
|
14
|
+
geometry.setAttribute('coverage', new BufferAttribute(new Float32Array([]), 1));
|
|
15
|
+
|
|
16
|
+
return geometry;
|
|
17
|
+
}
|
|
6
18
|
|
|
7
19
|
class Line extends Mesh
|
|
8
20
|
{
|
|
9
21
|
_length: number;
|
|
10
22
|
accumulated_length: number;
|
|
11
|
-
material:
|
|
23
|
+
material: LineMaterial;
|
|
12
24
|
|
|
13
25
|
constructor(points?: Vector3[])
|
|
14
26
|
{
|
|
15
|
-
const geometry =
|
|
16
|
-
|
|
17
|
-
geometry.setAttribute('next_position', new BufferAttribute(new Float32Array([]), 3));
|
|
18
|
-
geometry.setAttribute('previous_position', new BufferAttribute(new Float32Array([]), 3));
|
|
19
|
-
geometry.setAttribute('orientation', new BufferAttribute(new Float32Array([]), 1));
|
|
20
|
-
geometry.setAttribute('coverage', new BufferAttribute(new Float32Array([]), 1));
|
|
21
|
-
|
|
22
|
-
const material = new ShaderMaterial({
|
|
23
|
-
uniforms: {
|
|
24
|
-
_Thickness: { value: 0.2 },
|
|
25
|
-
_Length: { value: 0 },
|
|
26
|
-
_ElapsedTime: { value: 0 },
|
|
27
|
-
_Color: { value: new Color('#FF0000') }
|
|
28
|
-
},
|
|
29
|
-
vertexShader: line_vs,
|
|
30
|
-
fragmentShader: line_fs,
|
|
31
|
-
transparent: true,
|
|
32
|
-
depthWrite: false
|
|
33
|
-
});
|
|
27
|
+
const geometry = create_line_geometry();
|
|
28
|
+
const material = new LineMaterial();
|
|
34
29
|
|
|
35
30
|
super(geometry, material);
|
|
36
31
|
this.material = material;
|
|
@@ -106,7 +101,18 @@ class Line extends Mesh
|
|
|
106
101
|
indices.push(index + 1);
|
|
107
102
|
}
|
|
108
103
|
|
|
109
|
-
|
|
104
|
+
// WebGPURenderer sizes each GPU buffer at its first upload and later only writes
|
|
105
|
+
// into it, and it frees a geometry's buffers on its first dispose() only. So a new
|
|
106
|
+
// point count moves the line to a new geometry, which the next render uploads at
|
|
107
|
+
// the new size, and frees the old one. The index depends only on the point count,
|
|
108
|
+
// so it is kept otherwise.
|
|
109
|
+
if (vertexList.length / 3 !== this.geometry.getAttribute('position').count)
|
|
110
|
+
{
|
|
111
|
+
const previous_geometry = this.geometry;
|
|
112
|
+
this.geometry = create_line_geometry();
|
|
113
|
+
this.geometry.setIndex(indices);
|
|
114
|
+
previous_geometry.dispose();
|
|
115
|
+
}
|
|
110
116
|
(this.geometry.getAttribute('position') as BufferAttribute).copy(new BufferAttribute(vertexList, 3));
|
|
111
117
|
(this.geometry.getAttribute('next_position') as BufferAttribute).copy(new BufferAttribute(nextPositionList, 3));
|
|
112
118
|
(this.geometry.getAttribute('previous_position') as BufferAttribute).copy(new BufferAttribute(previousPositionList, 3));
|
|
@@ -180,14 +186,16 @@ class Line extends Mesh
|
|
|
180
186
|
{
|
|
181
187
|
this.parent.remove(this);
|
|
182
188
|
}
|
|
189
|
+
|
|
190
|
+
super.dispose();
|
|
183
191
|
}
|
|
184
192
|
|
|
185
|
-
set color(col)
|
|
193
|
+
set color(col: ColorRepresentation)
|
|
186
194
|
{
|
|
187
195
|
this.material.uniforms._Color.value.set(col);
|
|
188
196
|
}
|
|
189
197
|
|
|
190
|
-
get color()
|
|
198
|
+
get color(): Color
|
|
191
199
|
{
|
|
192
200
|
return this.material.uniforms._Color.value;
|
|
193
201
|
}
|
package/src/components/Text2D.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { SimpleTextDrawer } from '../canvas_drawer/SimpleTextDrawer';
|
|
|
2
2
|
import { WorldImage } from './WorldImage';
|
|
3
3
|
|
|
4
4
|
import type { CanvasTexture, Vector2 } from 'three';
|
|
5
|
-
import { LinearFilter, LinearMipMapLinearFilter } from 'three';
|
|
5
|
+
import { LinearFilter, LinearMipMapLinearFilter, SRGBColorSpace } from 'three';
|
|
6
6
|
|
|
7
7
|
class Text2D extends WorldImage
|
|
8
8
|
{
|
|
@@ -22,6 +22,8 @@ class Text2D extends WorldImage
|
|
|
22
22
|
|
|
23
23
|
canvas_texture.minFilter = LinearMipMapLinearFilter;
|
|
24
24
|
canvas_texture.minFilter = LinearFilter;
|
|
25
|
+
// Canvas colors are CSS colors, so sRGB. Tagged, they render as the given color.
|
|
26
|
+
canvas_texture.colorSpace = SRGBColorSpace;
|
|
25
27
|
canvas_texture.needsUpdate = true;
|
|
26
28
|
super(canvas_texture, pivot);
|
|
27
29
|
|
|
@@ -1,31 +1,20 @@
|
|
|
1
|
-
import
|
|
2
|
-
import basic_texture_vert from '../shaders/basic_texture/basic_texture.vert';
|
|
1
|
+
import { WorldImageMaterial } from '../materials/WorldImageMaterial';
|
|
3
2
|
|
|
4
3
|
import type { Texture } from 'three';
|
|
5
|
-
import {
|
|
4
|
+
import { Mesh, PlaneGeometry, Vector2, Vector3 } from 'three';
|
|
6
5
|
|
|
7
6
|
class WorldImage extends Mesh
|
|
8
7
|
{
|
|
9
8
|
current_scale: number;
|
|
9
|
+
sized_texture: Texture;
|
|
10
|
+
texture_size: Vector2;
|
|
10
11
|
tmp_bb_size: Vector3;
|
|
11
|
-
material:
|
|
12
|
+
material: WorldImageMaterial;
|
|
12
13
|
|
|
13
14
|
constructor(texture: Texture, pivot: Vector2)
|
|
14
15
|
{
|
|
15
16
|
pivot = pivot || new Vector2(0, 0);
|
|
16
|
-
const material = new
|
|
17
|
-
uniforms: {
|
|
18
|
-
_MainTex: { value: texture },
|
|
19
|
-
_ScreenAligned: { value: 0 },
|
|
20
|
-
_Scale: { value: 1 },
|
|
21
|
-
_Opacity: { value: 1 }
|
|
22
|
-
},
|
|
23
|
-
vertexShader: basic_texture_vert,
|
|
24
|
-
fragmentShader: basic_texture_frag,
|
|
25
|
-
transparent: true,
|
|
26
|
-
depthWrite: false,
|
|
27
|
-
side: DoubleSide
|
|
28
|
-
});
|
|
17
|
+
const material = new WorldImageMaterial(texture);
|
|
29
18
|
const geometry = new PlaneGeometry(1, 1, 1);
|
|
30
19
|
geometry.translate(-pivot.x / 2, -pivot.y / 2, 0);
|
|
31
20
|
// @ts-expect-error -- threejs issue
|
|
@@ -33,6 +22,9 @@ class WorldImage extends Mesh
|
|
|
33
22
|
geometry.scale(current_scale, 1, 1);
|
|
34
23
|
super(geometry, material);
|
|
35
24
|
this.current_scale = current_scale;
|
|
25
|
+
this.sized_texture = texture;
|
|
26
|
+
// @ts-expect-error -- threejs issue
|
|
27
|
+
this.texture_size = new Vector2(texture.image.width, texture.image.height);
|
|
36
28
|
this.geometry.computeBoundingBox();
|
|
37
29
|
|
|
38
30
|
this.tmp_bb_size = new Vector3();
|
|
@@ -42,8 +34,21 @@ class WorldImage extends Mesh
|
|
|
42
34
|
|
|
43
35
|
update_texture()
|
|
44
36
|
{
|
|
45
|
-
this.material.uniforms._MainTex.value
|
|
46
|
-
const img =
|
|
37
|
+
const texture = this.material.uniforms._MainTex.value;
|
|
38
|
+
const img = texture.image as { width: number, height: number };
|
|
39
|
+
|
|
40
|
+
// WebGPURenderer allocates the GPU texture at the image size once and later only
|
|
41
|
+
// uploads into it, so an image that changed size needs a new one. A texture swapped
|
|
42
|
+
// into _MainTex may be shared, so it is only measured, never freed.
|
|
43
|
+
const resized = img.width !== this.texture_size.x || img.height !== this.texture_size.y;
|
|
44
|
+
|
|
45
|
+
if (texture === this.sized_texture && resized)
|
|
46
|
+
{
|
|
47
|
+
texture.dispose();
|
|
48
|
+
}
|
|
49
|
+
this.sized_texture = texture;
|
|
50
|
+
this.texture_size.set(img.width, img.height);
|
|
51
|
+
texture.needsUpdate = true;
|
|
47
52
|
|
|
48
53
|
this.geometry.scale(1 / this.current_scale, 1, 1);
|
|
49
54
|
this.current_scale = img.width / img.height;
|
|
@@ -60,7 +65,7 @@ class WorldImage extends Mesh
|
|
|
60
65
|
set size(value)
|
|
61
66
|
{
|
|
62
67
|
this.scale.copy(value);
|
|
63
|
-
this.material.uniforms._Scale.value
|
|
68
|
+
this.material.uniforms._Scale.value.copy(value);
|
|
64
69
|
}
|
|
65
70
|
|
|
66
71
|
set screen_aligned(boolean)
|
|
@@ -89,6 +94,8 @@ class WorldImage extends Mesh
|
|
|
89
94
|
this.parent.remove(this);
|
|
90
95
|
this.material.uniforms._MainTex.value.dispose();
|
|
91
96
|
this.material.dispose();
|
|
97
|
+
|
|
98
|
+
super.dispose();
|
|
92
99
|
}
|
|
93
100
|
}
|
|
94
101
|
|
|
@@ -5,13 +5,17 @@ import { SDFText } from './SDFText';
|
|
|
5
5
|
import {
|
|
6
6
|
DynamicDrawUsage,
|
|
7
7
|
Float32BufferAttribute,
|
|
8
|
-
InstancedBufferAttribute,
|
|
9
8
|
InstancedBufferGeometry,
|
|
9
|
+
InstancedInterleavedBuffer,
|
|
10
|
+
InterleavedBufferAttribute,
|
|
10
11
|
Mesh,
|
|
11
12
|
PlaneGeometry,
|
|
12
13
|
Vector2
|
|
13
14
|
} from 'three';
|
|
14
15
|
|
|
16
|
+
// The per glyph attributes, four floats each, in the order they sit in an instance.
|
|
17
|
+
const GLYPH_ATTRIBUTES = ['transformsCol0', 'transformsCol1', 'transformsCol2', 'transformsCol3', 'glyph_bounds', 'plane_bounds', 'color'];
|
|
18
|
+
|
|
15
19
|
class SDFTextBatch extends Mesh
|
|
16
20
|
{
|
|
17
21
|
font_layout: any;
|
|
@@ -33,32 +37,16 @@ class SDFTextBatch extends Mesh
|
|
|
33
37
|
instanced_geometry.setAttribute('uv', new Float32BufferAttribute(geometry.getAttribute('uv').array, 2));
|
|
34
38
|
instanced_geometry.index = geometry.index;
|
|
35
39
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
const glyph_bounds = new InstancedBufferAttribute(new Float32Array(max_allocations * 4), 4, false);
|
|
42
|
-
const plane_bounds = new InstancedBufferAttribute(new Float32Array(max_allocations * 4), 4, false);
|
|
43
|
-
|
|
44
|
-
const color = new InstancedBufferAttribute(new Float32Array(max_allocations * 4), 4, false);
|
|
45
|
-
|
|
46
|
-
transformsCol0.usage = DynamicDrawUsage;
|
|
47
|
-
transformsCol1.usage = DynamicDrawUsage;
|
|
48
|
-
transformsCol2.usage = DynamicDrawUsage;
|
|
49
|
-
transformsCol3.usage = DynamicDrawUsage;
|
|
50
|
-
glyph_bounds.usage = DynamicDrawUsage;
|
|
51
|
-
plane_bounds.usage = DynamicDrawUsage;
|
|
52
|
-
color.usage = DynamicDrawUsage;
|
|
40
|
+
// One interleaved buffer holds every per glyph attribute. WebGPU allows 8 vertex
|
|
41
|
+
// buffers per pipeline, and one buffer per attribute would take 9 with position
|
|
42
|
+
// and uv.
|
|
43
|
+
const glyphs = new InstancedInterleavedBuffer(new Float32Array(max_allocations * GLYPH_ATTRIBUTES.length * 4), GLYPH_ATTRIBUTES.length * 4);
|
|
44
|
+
glyphs.setUsage(DynamicDrawUsage);
|
|
53
45
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
instanced_geometry.setAttribute('glyph_bounds', glyph_bounds);
|
|
60
|
-
instanced_geometry.setAttribute('plane_bounds', plane_bounds);
|
|
61
|
-
instanced_geometry.setAttribute('color', color);
|
|
46
|
+
GLYPH_ATTRIBUTES.forEach((name, i) =>
|
|
47
|
+
{
|
|
48
|
+
instanced_geometry.setAttribute(name, new InterleavedBufferAttribute(glyphs, 4, i * 4));
|
|
49
|
+
});
|
|
62
50
|
|
|
63
51
|
super(instanced_geometry, new SDFTextMaterial(atlas_texture));
|
|
64
52
|
|
|
@@ -195,6 +183,8 @@ class SDFTextBatch extends Mesh
|
|
|
195
183
|
{
|
|
196
184
|
this.geometry.dispose();
|
|
197
185
|
this.material.dispose();
|
|
186
|
+
|
|
187
|
+
super.dispose();
|
|
198
188
|
}
|
|
199
189
|
}
|
|
200
190
|
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
import type { InspectableObject } from './SceneInspector';
|
|
2
|
+
|
|
3
|
+
const PRECISION = 10000;
|
|
4
|
+
|
|
5
|
+
export interface OrbitalController
|
|
6
|
+
{
|
|
7
|
+
current_tilt: number;
|
|
8
|
+
current_orientation: number;
|
|
9
|
+
current_azimuth: number;
|
|
10
|
+
normalized_zoom: number;
|
|
11
|
+
min_zoom: number;
|
|
12
|
+
max_zoom: number;
|
|
13
|
+
reference_position: { x: number; y: number; z: number };
|
|
14
|
+
get_current_tilt(): number;
|
|
15
|
+
get_current_orientation(): number;
|
|
16
|
+
get_current_azimuth(): number;
|
|
17
|
+
set_normalized_zoom(zoom: number): void;
|
|
18
|
+
set_rotation(tilt?: number, orientation?: number, azimuth?: number): void;
|
|
19
|
+
focus_on_bounding_box(box: unknown, scale?: number): void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface BridgeCamera
|
|
23
|
+
{
|
|
24
|
+
position: { x: number; y: number; z: number };
|
|
25
|
+
fov?: number;
|
|
26
|
+
near?: number;
|
|
27
|
+
far?: number;
|
|
28
|
+
clear_color?: { getHexString?: () => string };
|
|
29
|
+
clear_alpha?: number;
|
|
30
|
+
updateProjectionMatrix?: () => void;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface ControllerState
|
|
34
|
+
{
|
|
35
|
+
tilt: number;
|
|
36
|
+
orientation: number;
|
|
37
|
+
azimuth: number;
|
|
38
|
+
zoom: number;
|
|
39
|
+
min_zoom: number;
|
|
40
|
+
max_zoom: number;
|
|
41
|
+
target: number[];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface CameraState
|
|
45
|
+
{
|
|
46
|
+
position: number[];
|
|
47
|
+
fov: number | null;
|
|
48
|
+
near: number | null;
|
|
49
|
+
far: number | null;
|
|
50
|
+
clear_color: string | null;
|
|
51
|
+
clear_alpha: number | null;
|
|
52
|
+
controller: ControllerState | null;
|
|
53
|
+
changed?: string[];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Changes arrive off the dev-bridge wire and are therefore untrusted.
|
|
57
|
+
export interface CameraChanges
|
|
58
|
+
{
|
|
59
|
+
tilt?: unknown;
|
|
60
|
+
orientation?: unknown;
|
|
61
|
+
azimuth?: unknown;
|
|
62
|
+
zoom?: unknown;
|
|
63
|
+
fov?: unknown;
|
|
64
|
+
target?: unknown;
|
|
65
|
+
position?: unknown;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface FrameRequest
|
|
69
|
+
{
|
|
70
|
+
uuid?: unknown;
|
|
71
|
+
name?: unknown;
|
|
72
|
+
scale?: unknown;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Speaks the CameraController's own idiom. The controller is orbital, driven by
|
|
76
|
+
// tilt, orientation, azimuth and a normalised zoom in degrees, and it rewrites
|
|
77
|
+
// the camera transform every update. Assigning camera.position directly while a
|
|
78
|
+
// controller is active would simply be overwritten on the next frame.
|
|
79
|
+
class CameraBridge
|
|
80
|
+
{
|
|
81
|
+
get(camera: BridgeCamera, controller: OrbitalController | null): CameraState
|
|
82
|
+
{
|
|
83
|
+
return this.describe(this.require_camera(camera), controller);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
set(camera: BridgeCamera, controller: OrbitalController | null, changes: CameraChanges): CameraState
|
|
87
|
+
{
|
|
88
|
+
const target_camera = this.require_camera(camera);
|
|
89
|
+
const changed: string[] = [];
|
|
90
|
+
|
|
91
|
+
if (controller !== null)
|
|
92
|
+
{
|
|
93
|
+
this.apply_orbit(controller, changes, changed);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
this.apply_position(target_camera, controller, changes, changed);
|
|
97
|
+
this.apply_fov(target_camera, changes, changed);
|
|
98
|
+
|
|
99
|
+
const state = this.describe(target_camera, controller);
|
|
100
|
+
state.changed = changed;
|
|
101
|
+
|
|
102
|
+
return state;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
frame(
|
|
106
|
+
camera: BridgeCamera,
|
|
107
|
+
controller: OrbitalController | null,
|
|
108
|
+
root: InspectableObject,
|
|
109
|
+
request: FrameRequest,
|
|
110
|
+
make_bounds: (object: InspectableObject) => unknown
|
|
111
|
+
): CameraState
|
|
112
|
+
{
|
|
113
|
+
const target_camera = this.require_camera(camera);
|
|
114
|
+
|
|
115
|
+
if (controller === null)
|
|
116
|
+
{
|
|
117
|
+
throw this.error('no_controller', 'The active scene has no camera_controller, so framing is unavailable.');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const uuid = typeof request.uuid === 'string' ? request.uuid : null;
|
|
121
|
+
const name = typeof request.name === 'string' ? request.name : null;
|
|
122
|
+
|
|
123
|
+
if (uuid === null && name === null)
|
|
124
|
+
{
|
|
125
|
+
throw this.error('not_found', 'Pass a uuid or a name to identify the object to frame.');
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const found = this.find(root, uuid, name);
|
|
129
|
+
|
|
130
|
+
if (found === null)
|
|
131
|
+
{
|
|
132
|
+
const label = uuid === null ? `name '${name === null ? '' : name}'` : `uuid '${uuid}'`;
|
|
133
|
+
|
|
134
|
+
throw this.error('not_found', `No object matching ${label} in the current scene.`);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const scale = typeof request.scale === 'number' && Number.isFinite(request.scale) ? request.scale : 1;
|
|
138
|
+
|
|
139
|
+
controller.focus_on_bounding_box(make_bounds(found), scale);
|
|
140
|
+
|
|
141
|
+
const state = this.describe(target_camera, controller);
|
|
142
|
+
state.changed = ['framed'];
|
|
143
|
+
|
|
144
|
+
return state;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Angles go through set_rotation, which is nullish-checked, so an omitted
|
|
148
|
+
// value keeps the current angle and an explicit 0 is applied. It also records
|
|
149
|
+
// old_orientation, which assigning the fields directly would skip.
|
|
150
|
+
private apply_orbit(controller: OrbitalController, changes: CameraChanges, changed: string[]): void
|
|
151
|
+
{
|
|
152
|
+
const tilt = this.number(changes.tilt);
|
|
153
|
+
const orientation = this.number(changes.orientation);
|
|
154
|
+
const azimuth = this.number(changes.azimuth);
|
|
155
|
+
|
|
156
|
+
if (tilt !== null || orientation !== null || azimuth !== null)
|
|
157
|
+
{
|
|
158
|
+
if (tilt !== null)
|
|
159
|
+
{
|
|
160
|
+
changed.push('tilt');
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (orientation !== null)
|
|
164
|
+
{
|
|
165
|
+
changed.push('orientation');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (azimuth !== null)
|
|
169
|
+
{
|
|
170
|
+
changed.push('azimuth');
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
controller.set_rotation(
|
|
174
|
+
tilt === null ? undefined : tilt,
|
|
175
|
+
orientation === null ? undefined : orientation,
|
|
176
|
+
azimuth === null ? undefined : azimuth
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const zoom = this.number(changes.zoom);
|
|
181
|
+
|
|
182
|
+
if (zoom !== null)
|
|
183
|
+
{
|
|
184
|
+
controller.set_normalized_zoom(zoom);
|
|
185
|
+
changed.push('zoom');
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const target = this.triple(changes.target);
|
|
189
|
+
|
|
190
|
+
if (target !== null)
|
|
191
|
+
{
|
|
192
|
+
controller.reference_position.x = target[0];
|
|
193
|
+
controller.reference_position.y = target[1];
|
|
194
|
+
controller.reference_position.z = target[2];
|
|
195
|
+
changed.push('target');
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
private apply_position(
|
|
200
|
+
camera: BridgeCamera,
|
|
201
|
+
controller: OrbitalController | null,
|
|
202
|
+
changes: CameraChanges,
|
|
203
|
+
changed: string[]
|
|
204
|
+
): void
|
|
205
|
+
{
|
|
206
|
+
const position = this.triple(changes.position);
|
|
207
|
+
|
|
208
|
+
if (position === null)
|
|
209
|
+
{
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (controller !== null)
|
|
214
|
+
{
|
|
215
|
+
throw this.error(
|
|
216
|
+
'controller_owns_camera',
|
|
217
|
+
'A CameraController is driving this camera and would overwrite a raw position on the next frame. Use tilt, orientation, azimuth, zoom and target instead.'
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
camera.position.x = position[0];
|
|
222
|
+
camera.position.y = position[1];
|
|
223
|
+
camera.position.z = position[2];
|
|
224
|
+
changed.push('position');
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
private apply_fov(camera: BridgeCamera, changes: CameraChanges, changed: string[]): void
|
|
228
|
+
{
|
|
229
|
+
const fov = this.number(changes.fov);
|
|
230
|
+
|
|
231
|
+
if (fov === null)
|
|
232
|
+
{
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
camera.fov = fov;
|
|
237
|
+
changed.push('fov');
|
|
238
|
+
|
|
239
|
+
if (typeof camera.updateProjectionMatrix === 'function')
|
|
240
|
+
{
|
|
241
|
+
camera.updateProjectionMatrix();
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
private describe(camera: BridgeCamera, controller: OrbitalController | null): CameraState
|
|
246
|
+
{
|
|
247
|
+
return {
|
|
248
|
+
position: [this.round(camera.position.x), this.round(camera.position.y), this.round(camera.position.z)],
|
|
249
|
+
fov: typeof camera.fov === 'number' ? camera.fov : null,
|
|
250
|
+
near: typeof camera.near === 'number' ? camera.near : null,
|
|
251
|
+
far: typeof camera.far === 'number' ? camera.far : null,
|
|
252
|
+
clear_color: this.hex(camera.clear_color),
|
|
253
|
+
clear_alpha: typeof camera.clear_alpha === 'number' ? camera.clear_alpha : null,
|
|
254
|
+
controller: controller === null ? null : {
|
|
255
|
+
tilt: controller.get_current_tilt(),
|
|
256
|
+
orientation: controller.get_current_orientation(),
|
|
257
|
+
azimuth: controller.get_current_azimuth(),
|
|
258
|
+
zoom: controller.normalized_zoom,
|
|
259
|
+
min_zoom: controller.min_zoom,
|
|
260
|
+
max_zoom: controller.max_zoom,
|
|
261
|
+
target: [
|
|
262
|
+
this.round(controller.reference_position.x),
|
|
263
|
+
this.round(controller.reference_position.y),
|
|
264
|
+
this.round(controller.reference_position.z)
|
|
265
|
+
]
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
private find(node: InspectableObject, uuid: string | null, name: string | null): InspectableObject | null
|
|
271
|
+
{
|
|
272
|
+
const matches = uuid !== null ? node.uuid === uuid : node.name === name;
|
|
273
|
+
|
|
274
|
+
if (matches)
|
|
275
|
+
{
|
|
276
|
+
return node;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const children = Array.isArray(node.children) ? node.children : [];
|
|
280
|
+
|
|
281
|
+
for (const child of children)
|
|
282
|
+
{
|
|
283
|
+
const found = this.find(child, uuid, name);
|
|
284
|
+
|
|
285
|
+
if (found !== null)
|
|
286
|
+
{
|
|
287
|
+
return found;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return null;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
private require_camera(camera: BridgeCamera): BridgeCamera
|
|
295
|
+
{
|
|
296
|
+
if (typeof camera !== 'object' || camera === null || typeof camera.position !== 'object')
|
|
297
|
+
{
|
|
298
|
+
throw this.error('no_camera', 'No camera is active. CameraManager.current is not set yet.');
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return camera;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
private hex(color: { getHexString?: () => string } | undefined): string | null
|
|
305
|
+
{
|
|
306
|
+
if (typeof color !== 'object' || color === null || typeof color.getHexString !== 'function')
|
|
307
|
+
{
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return `#${color.getHexString()}`;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
private number(value: unknown): number | null
|
|
315
|
+
{
|
|
316
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : null;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
private triple(value: unknown): number[] | null
|
|
320
|
+
{
|
|
321
|
+
if (!Array.isArray(value))
|
|
322
|
+
{
|
|
323
|
+
return null;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const supplied = value as unknown[];
|
|
327
|
+
const out: number[] = [];
|
|
328
|
+
|
|
329
|
+
for (let i = 0; i < 3; i++)
|
|
330
|
+
{
|
|
331
|
+
const entry = this.number(supplied[i]);
|
|
332
|
+
|
|
333
|
+
if (entry === null)
|
|
334
|
+
{
|
|
335
|
+
return null;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
out.push(entry);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
return out;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
private round(value: unknown): number
|
|
345
|
+
{
|
|
346
|
+
if (typeof value !== 'number' || !Number.isFinite(value))
|
|
347
|
+
{
|
|
348
|
+
return 0;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
return Math.round(value * PRECISION) / PRECISION;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
private error(code: string, message: string): Error
|
|
355
|
+
{
|
|
356
|
+
const error: Error & { code?: string } = new Error(message);
|
|
357
|
+
error.code = code;
|
|
358
|
+
|
|
359
|
+
return error;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
export { CameraBridge };
|