@driftengine/core 4.4.2 → 4.6.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/CHANGELOG.json +97 -0
- package/README.md +1 -1
- package/dist/geometry/boxCsg.d.ts +28 -0
- package/dist/geometry/boxCsg.js +139 -0
- package/dist/geometry/csg.d.ts +36 -0
- package/dist/geometry/csg.js +329 -0
- package/dist/geometry/meshBuilder.js +13 -0
- package/dist/geometry/meshConcat.js +1 -0
- package/dist/geometry/pixelFont.js +2 -0
- package/dist/geometry/solid.d.ts +61 -0
- package/dist/geometry/solid.js +152 -0
- package/dist/geometry/solidFlat.d.ts +35 -0
- package/dist/geometry/solidFlat.js +428 -0
- package/dist/geometry/solidHarness.d.ts +19 -0
- package/dist/geometry/solidHarness.js +66 -0
- package/dist/geometry/solidNormals.d.ts +17 -0
- package/dist/geometry/solidNormals.js +86 -0
- package/dist/geometry/solidRound.d.ts +41 -0
- package/dist/geometry/solidRound.js +323 -0
- package/dist/geometry/solidWriter.d.ts +16 -0
- package/dist/geometry/solidWriter.js +42 -0
- package/dist/index.d.ts +28 -3
- package/dist/index.js +20 -1
- package/dist/render/backend/api.d.ts +34 -14
- package/dist/render/backend/drawFog.d.ts +26 -0
- package/dist/render/backend/drawFog.js +30 -0
- package/dist/render/backend/materialChanges.d.ts +2 -1
- package/dist/render/backend/materialChanges.js +6 -1
- package/dist/render/backend/webgl2/glassTintPrograms.d.ts +13 -0
- package/dist/render/backend/webgl2/glassTintPrograms.js +38 -0
- package/dist/render/backend/webgl2/instanced.d.ts +24 -5
- package/dist/render/backend/webgl2/instanced.js +72 -15
- package/dist/render/backend/webgl2/renderer.d.ts +201 -16
- package/dist/render/backend/webgl2/renderer.js +596 -224
- package/dist/render/backend/webgpu/buffers.d.ts +29 -1
- package/dist/render/backend/webgpu/buffers.js +61 -4
- package/dist/render/backend/webgpu/depthPass.d.ts +1 -1
- package/dist/render/backend/webgpu/depthPass.js +7 -2
- package/dist/render/backend/webgpu/drawCommand.d.ts +5 -0
- package/dist/render/backend/webgpu/drawCommand.js +1 -0
- package/dist/render/backend/webgpu/flatPass.d.ts +6 -1
- package/dist/render/backend/webgpu/flatPass.js +57 -9
- package/dist/render/backend/webgpu/glassTintPass.d.ts +28 -0
- package/dist/render/backend/webgpu/glassTintPass.js +206 -0
- package/dist/render/backend/webgpu/gpuDrivenPass.d.ts +60 -1
- package/dist/render/backend/webgpu/gpuDrivenPass.js +305 -5
- package/dist/render/backend/webgpu/instanceCullPass.d.ts +34 -0
- package/dist/render/backend/webgpu/instanceCullPass.js +144 -0
- package/dist/render/backend/webgpu/instanced.d.ts +23 -2
- package/dist/render/backend/webgpu/instanced.js +41 -4
- package/dist/render/backend/webgpu/latePass.d.ts +30 -0
- package/dist/render/backend/webgpu/latePass.js +140 -0
- package/dist/render/backend/webgpu/lightVolumePass.js +5 -1
- package/dist/render/backend/webgpu/motionPass.d.ts +95 -0
- package/dist/render/backend/webgpu/motionPass.js +491 -0
- package/dist/render/backend/webgpu/pipelineCache.d.ts +10 -1
- package/dist/render/backend/webgpu/pipelineCache.js +11 -1
- package/dist/render/backend/webgpu/pointGlassTintPass.d.ts +32 -0
- package/dist/render/backend/webgpu/pointGlassTintPass.js +193 -0
- package/dist/render/backend/webgpu/pointShadowPass.d.ts +35 -6
- package/dist/render/backend/webgpu/pointShadowPass.js +105 -20
- package/dist/render/backend/webgpu/postPass.d.ts +3 -13
- package/dist/render/backend/webgpu/renderer.d.ts +271 -64
- package/dist/render/backend/webgpu/renderer.js +1395 -580
- package/dist/render/backend/webgpu/scatterPass.js +2 -1
- package/dist/render/backend/webgpu/sdfTextPass.js +6 -1
- package/dist/render/backend/webgpu/shaders/instanceCull.wgsl.d.ts +18 -0
- package/dist/render/backend/webgpu/shaders/instanceCull.wgsl.js +59 -0
- package/dist/render/backend/webgpu/skinPaletteRing.d.ts +4 -0
- package/dist/render/backend/webgpu/skinPaletteRing.js +4 -0
- package/dist/render/backend/webgpu/snapshotMips.d.ts +29 -0
- package/dist/render/backend/webgpu/snapshotMips.js +52 -0
- package/dist/render/backend/webgpu/surfaceTexturePass.d.ts +22 -3
- package/dist/render/backend/webgpu/surfaceTexturePass.js +78 -39
- package/dist/render/driftLight/bake.d.ts +7 -0
- package/dist/render/driftLight/bake.js +61 -56
- package/dist/render/driftLight/denseField.d.ts +46 -0
- package/dist/render/driftLight/denseField.js +109 -0
- package/dist/render/driftLight/lightField.d.ts +10 -5
- package/dist/render/driftLight/lightField.js +25 -19
- package/dist/render/driftLight/presence.d.ts +50 -0
- package/dist/render/driftLight/presence.js +43 -0
- package/dist/render/driftLight/uniforms.d.ts +3 -3
- package/dist/render/driftLight/uniforms.js +5 -6
- package/dist/render/driftLight/worldLightField.d.ts +41 -0
- package/dist/render/driftLight/worldLightField.js +66 -0
- package/dist/render/fixtureAtlas.d.ts +20 -0
- package/dist/render/fixtureAtlas.js +49 -0
- package/dist/render/glass.d.ts +45 -0
- package/dist/render/glass.js +39 -0
- package/dist/render/glassCasters.d.ts +40 -0
- package/dist/render/glassCasters.js +84 -0
- package/dist/render/glassShadow.d.ts +78 -0
- package/dist/render/glassShadow.js +125 -0
- package/dist/render/globalMediumPass.d.ts +2 -3
- package/dist/render/globalMediumPass.js +2 -8
- package/dist/render/gpudriven/lit.d.ts +12 -0
- package/dist/render/gpudriven/lit.js +23 -0
- package/dist/render/gpudriven/materialTable.d.ts +15 -5
- package/dist/render/gpudriven/materialTable.js +26 -6
- package/dist/render/gpudriven/pipeline.d.ts +1 -1
- package/dist/render/gpudriven/pipeline.js +4 -3
- package/dist/render/gpudriven/sunGlass.d.ts +35 -0
- package/dist/render/gpudriven/sunGlass.js +89 -0
- package/dist/render/instanceCull.d.ts +63 -0
- package/dist/render/instanceCull.js +160 -0
- package/dist/render/instances.d.ts +15 -0
- package/dist/render/lightBudget.d.ts +36 -35
- package/dist/render/lightBudget.js +38 -37
- package/dist/render/lightGrid.d.ts +42 -0
- package/dist/render/lightGrid.js +87 -0
- package/dist/render/mesh.d.ts +18 -24
- package/dist/render/mesh.js +51 -68
- package/dist/render/occlusion.d.ts +10 -0
- package/dist/render/occlusion.js +36 -7
- package/dist/render/pointGlassTint.d.ts +59 -0
- package/dist/render/pointGlassTint.js +198 -0
- package/dist/render/pointLightSelection.d.ts +7 -0
- package/dist/render/pointLightSelection.js +29 -4
- package/dist/render/pointShadowArray.d.ts +56 -3
- package/dist/render/pointShadowArray.js +127 -16
- package/dist/render/pointShadowMap.d.ts +23 -1
- package/dist/render/pointShadowMap.js +27 -1
- package/dist/render/rainField.d.ts +13 -0
- package/dist/render/rainField.js +27 -5
- package/dist/render/recon/changeFrames.d.ts +15 -0
- package/dist/render/recon/changeFrames.js +21 -0
- package/dist/render/recon/lateDepth.d.ts +11 -0
- package/dist/render/recon/lateDepth.js +70 -0
- package/dist/render/recon/lateRouting.d.ts +14 -0
- package/dist/render/recon/lateRouting.js +18 -0
- package/dist/render/recon/mover.d.ts +57 -0
- package/dist/render/recon/mover.js +86 -0
- package/dist/render/recon/resolve.d.ts +34 -4
- package/dist/render/recon/resolve.js +161 -20
- package/dist/render/renderQuality.d.ts +35 -0
- package/dist/render/renderQuality.js +7 -0
- package/dist/render/rendererHarness.js +16 -0
- package/dist/render/sceneTarget.d.ts +9 -1
- package/dist/render/sceneTarget.js +60 -12
- package/dist/render/shaders/depth.d.ts +16 -1
- package/dist/render/shaders/depth.js +94 -15
- package/dist/render/shaders/flat/directionalShadow.js +91 -6
- package/dist/render/shaders/flat/driftLight.d.ts +1 -1
- package/dist/render/shaders/flat/driftLight.js +32 -7
- package/dist/render/shaders/flat/glassTint.d.ts +6 -0
- package/dist/render/shaders/flat/glassTint.js +25 -0
- package/dist/render/shaders/flat/index.d.ts +13 -0
- package/dist/render/shaders/flat/index.js +9 -3
- package/dist/render/shaders/flat/lampGlass.d.ts +1 -0
- package/dist/render/shaders/flat/lampGlass.js +183 -0
- package/dist/render/shaders/flat/main.d.ts +1 -1
- package/dist/render/shaders/flat/main.js +190 -38
- package/dist/render/shaders/flat/pointShadow.d.ts +1 -1
- package/dist/render/shaders/flat/pointShadow.js +2 -0
- package/dist/render/shaders/flat/preamble.js +96 -26
- package/dist/render/shaders/flat/surfaceEffects.d.ts +29 -0
- package/dist/render/shaders/flat/surfaceEffects.js +152 -0
- package/dist/render/shaders/generated/depth.wgsl.d.ts +230 -7
- package/dist/render/shaders/generated/depth.wgsl.js +230 -7
- package/dist/render/shaders/generated/flat.wgsl.d.ts +1644 -1596
- package/dist/render/shaders/generated/flat.wgsl.js +1683 -1621
- package/dist/render/shaders/generated/globalMedium.wgsl.d.ts +3 -13
- package/dist/render/shaders/generated/globalMedium.wgsl.js +3 -13
- package/dist/render/shaders/generated/lightVolume.wgsl.d.ts +3 -13
- package/dist/render/shaders/generated/lightVolume.wgsl.js +21 -17
- package/dist/render/shaders/generated/octahedralResolve.wgsl.d.ts +29 -0
- package/dist/render/shaders/generated/octahedralResolve.wgsl.js +29 -0
- package/dist/render/shaders/generated/rush.wgsl.d.ts +21 -16
- package/dist/render/shaders/generated/rush.wgsl.js +21 -16
- package/dist/render/shaders/generated/sdfText.wgsl.d.ts +2 -2
- package/dist/render/shaders/generated/sdfText.wgsl.js +2 -2
- package/dist/render/shaders/generated/text.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/text.wgsl.js +1 -1
- package/dist/render/shaders/gi/driftLight.wgsl.d.ts +1 -1
- package/dist/render/shaders/gi/driftLight.wgsl.js +27 -4
- package/dist/render/shaders/globalMedium.js +6 -6
- package/dist/render/shaders/gpudriven/blendRaster.wgsl.d.ts +7 -0
- package/dist/render/shaders/gpudriven/blendRaster.wgsl.js +86 -1
- package/dist/render/shaders/gpudriven/cull.wgsl.d.ts +1 -1
- package/dist/render/shaders/gpudriven/cull.wgsl.js +11 -2
- package/dist/render/shaders/gpudriven/materialTable.wgsl.d.ts +1 -1
- package/dist/render/shaders/gpudriven/materialTable.wgsl.js +3 -1
- package/dist/render/shaders/gpudriven/shade.wgsl.js +50 -1
- package/dist/render/shaders/gpudriven/sunGlass.wgsl.d.ts +9 -0
- package/dist/render/shaders/gpudriven/sunGlass.wgsl.js +133 -0
- package/dist/render/shaders/lightVolume.js +6 -6
- package/dist/render/shaders/octahedralResolve.d.ts +8 -0
- package/dist/render/shaders/octahedralResolve.js +48 -17
- package/dist/render/shaders/recon/lateDepth.wgsl.d.ts +1 -0
- package/dist/render/shaders/recon/lateDepth.wgsl.js +69 -0
- package/dist/render/shaders/recon/motion.wgsl.d.ts +1 -1
- package/dist/render/shaders/recon/motion.wgsl.js +84 -0
- package/dist/render/shaders/recon/resolve.wgsl.d.ts +8 -7
- package/dist/render/shaders/recon/resolve.wgsl.js +161 -27
- package/dist/render/shaders/rush.js +11 -1
- package/dist/render/shaders/sdfText.d.ts +1 -1
- package/dist/render/shaders/sdfText.js +3 -2
- package/dist/render/shaders/text.d.ts +1 -1
- package/dist/render/shaders/text.js +18 -9
- package/dist/render/shadowCasters.d.ts +20 -1
- package/dist/render/shadowCasters.js +15 -1
- package/dist/render/shadowMap.d.ts +54 -5
- package/dist/render/shadowMap.js +190 -36
- package/dist/render/sunGlassTint.d.ts +25 -0
- package/dist/render/sunGlassTint.js +79 -0
- package/dist/render/surfaceEffects.d.ts +83 -0
- package/dist/render/surfaceEffects.js +75 -0
- package/dist/render/surfaceScene.d.ts +8 -0
- package/dist/render/surfaceScene.js +8 -0
- package/dist/render/surfaceTexture.d.ts +18 -2
- package/dist/render/surfaceTexture.js +68 -15
- package/dist/render/temporalAa.d.ts +25 -6
- package/dist/render/temporalAa.js +45 -15
- package/dist/render/textureSource.d.ts +30 -0
- package/dist/render/textureSource.js +53 -0
- package/dist/render/translucentQueue.d.ts +6 -0
- package/dist/render/translucentQueue.js +15 -1
- package/dist/render/vertexDefaults.js +2 -0
- package/dist/world/hlod.d.ts +104 -0
- package/dist/world/hlod.js +214 -0
- package/package.json +6 -6
- package/src/geometry/boxCsg.ts +186 -0
- package/src/geometry/csg.ts +384 -0
- package/src/geometry/meshBuilder.ts +15 -0
- package/src/geometry/meshConcat.ts +1 -0
- package/src/geometry/pixelFont.ts +2 -0
- package/src/geometry/solid.ts +189 -0
- package/src/geometry/solidFlat.ts +522 -0
- package/src/geometry/solidHarness.ts +83 -0
- package/src/geometry/solidNormals.ts +103 -0
- package/src/geometry/solidRound.ts +443 -0
- package/src/geometry/solidWriter.ts +58 -0
- package/src/index.ts +61 -1
- package/src/render/backend/api.ts +36 -11
- package/src/render/backend/drawFog.ts +31 -0
- package/src/render/backend/materialChanges.ts +9 -2
- package/src/render/backend/webgl2/glassTintPrograms.ts +58 -0
- package/src/render/backend/webgl2/instanced.ts +80 -14
- package/src/render/backend/webgl2/renderer.ts +700 -250
- package/src/render/backend/webgpu/buffers.ts +92 -5
- package/src/render/backend/webgpu/depthPass.ts +7 -2
- package/src/render/backend/webgpu/drawCommand.ts +6 -0
- package/src/render/backend/webgpu/flatPass.ts +62 -11
- package/src/render/backend/webgpu/glassTintPass.ts +245 -0
- package/src/render/backend/webgpu/gpuDrivenPass.ts +349 -5
- package/src/render/backend/webgpu/instanceCullPass.ts +165 -0
- package/src/render/backend/webgpu/instanced.ts +42 -4
- package/src/render/backend/webgpu/latePass.ts +161 -0
- package/src/render/backend/webgpu/lightVolumePass.ts +5 -1
- package/src/render/backend/webgpu/motionPass.ts +535 -0
- package/src/render/backend/webgpu/pipelineCache.ts +12 -1
- package/src/render/backend/webgpu/pointGlassTintPass.ts +233 -0
- package/src/render/backend/webgpu/pointShadowPass.ts +158 -26
- package/src/render/backend/webgpu/renderer.ts +1671 -670
- package/src/render/backend/webgpu/scatterPass.ts +2 -1
- package/src/render/backend/webgpu/sdfTextPass.ts +6 -1
- package/src/render/backend/webgpu/shaders/instanceCull.wgsl.ts +61 -0
- package/src/render/backend/webgpu/skinPaletteRing.ts +4 -0
- package/src/render/backend/webgpu/snapshotMips.ts +80 -0
- package/src/render/backend/webgpu/surfaceTexturePass.ts +91 -51
- package/src/render/driftLight/bake.ts +85 -62
- package/src/render/driftLight/denseField.ts +149 -0
- package/src/render/driftLight/lightField.ts +33 -18
- package/src/render/driftLight/presence.ts +69 -0
- package/src/render/driftLight/uniforms.ts +8 -9
- package/src/render/driftLight/worldLightField.ts +83 -0
- package/src/render/fixtureAtlas.ts +63 -0
- package/src/render/glass.ts +74 -0
- package/src/render/glassCasters.ts +164 -0
- package/src/render/glassShadow.ts +153 -0
- package/src/render/globalMediumPass.ts +4 -11
- package/src/render/gpudriven/lit.ts +31 -0
- package/src/render/gpudriven/materialTable.ts +28 -6
- package/src/render/gpudriven/pipeline.ts +4 -3
- package/src/render/gpudriven/sunGlass.ts +117 -0
- package/src/render/instanceCull.ts +205 -0
- package/src/render/instances.ts +16 -0
- package/src/render/lightBudget.ts +41 -38
- package/src/render/lightGrid.ts +130 -0
- package/src/render/mesh.ts +59 -72
- package/src/render/occlusion.ts +51 -7
- package/src/render/pointGlassTint.ts +250 -0
- package/src/render/pointLightSelection.ts +72 -4
- package/src/render/pointShadowArray.ts +188 -22
- package/src/render/pointShadowMap.ts +41 -0
- package/src/render/rainField.ts +39 -5
- package/src/render/recon/changeFrames.ts +24 -0
- package/src/render/recon/lateDepth.ts +83 -0
- package/src/render/recon/lateRouting.ts +29 -0
- package/src/render/recon/mover.ts +118 -0
- package/src/render/recon/resolve.ts +206 -20
- package/src/render/renderQuality.ts +47 -0
- package/src/render/rendererHarness.ts +16 -0
- package/src/render/sceneTarget.ts +62 -11
- package/src/render/shaders/depth.ts +118 -15
- package/src/render/shaders/flat/directionalShadow.ts +97 -6
- package/src/render/shaders/flat/driftLight.ts +32 -7
- package/src/render/shaders/flat/glassTint.ts +25 -0
- package/src/render/shaders/flat/index.ts +22 -3
- package/src/render/shaders/flat/lampGlass.ts +185 -0
- package/src/render/shaders/flat/main.ts +190 -38
- package/src/render/shaders/flat/pointShadow.ts +2 -0
- package/src/render/shaders/flat/preamble.ts +96 -26
- package/src/render/shaders/flat/surfaceEffects.ts +152 -0
- package/src/render/shaders/generated/depth.wgsl.ts +237 -7
- package/src/render/shaders/generated/flat.wgsl.ts +1685 -1621
- package/src/render/shaders/generated/globalMedium.wgsl.ts +3 -13
- package/src/render/shaders/generated/lightVolume.wgsl.ts +23 -17
- package/src/render/shaders/generated/octahedralResolve.wgsl.ts +30 -0
- package/src/render/shaders/generated/rush.wgsl.ts +21 -16
- package/src/render/shaders/generated/sdfText.wgsl.ts +2 -2
- package/src/render/shaders/generated/text.wgsl.ts +1 -1
- package/src/render/shaders/gi/driftLight.wgsl.ts +27 -4
- package/src/render/shaders/globalMedium.ts +6 -6
- package/src/render/shaders/gpudriven/blendRaster.wgsl.ts +88 -1
- package/src/render/shaders/gpudriven/cull.wgsl.ts +11 -2
- package/src/render/shaders/gpudriven/materialTable.wgsl.ts +3 -1
- package/src/render/shaders/gpudriven/shade.wgsl.ts +50 -1
- package/src/render/shaders/gpudriven/sunGlass.wgsl.ts +139 -0
- package/src/render/shaders/lightVolume.ts +6 -6
- package/src/render/shaders/octahedralResolve.ts +50 -17
- package/src/render/shaders/recon/lateDepth.wgsl.ts +72 -0
- package/src/render/shaders/recon/motion.wgsl.ts +84 -0
- package/src/render/shaders/recon/resolve.wgsl.ts +161 -27
- package/src/render/shaders/rush.ts +11 -1
- package/src/render/shaders/sdfText.ts +3 -2
- package/src/render/shaders/text.ts +18 -9
- package/src/render/shadowCasters.ts +28 -1
- package/src/render/shadowMap.ts +231 -37
- package/src/render/sunGlassTint.ts +86 -0
- package/src/render/surfaceEffects.ts +132 -0
- package/src/render/surfaceScene.ts +16 -0
- package/src/render/surfaceTexture.ts +110 -19
- package/src/render/temporalAa.ts +78 -14
- package/src/render/textureSource.ts +72 -0
- package/src/render/translucentQueue.ts +20 -1
- package/src/render/vertexDefaults.ts +2 -0
- package/src/world/hlod.ts +290 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { batchBoxVisible } from '../render/instanceCull.js';
|
|
2
|
+
/** The level of a region drawn at none of its own: past `farDistance`, or not arrived yet. */
|
|
3
|
+
export const HLOD_NONE = 255;
|
|
4
|
+
/** Room for every region of a set of this capacity, each crossfading at once. */
|
|
5
|
+
export function createHlodDraws(capacity) {
|
|
6
|
+
return {
|
|
7
|
+
count: 0,
|
|
8
|
+
region: new Uint32Array(capacity * 2),
|
|
9
|
+
level: new Uint8Array(capacity * 2),
|
|
10
|
+
dither: new Float32Array(capacity * 2),
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/** Pixels a metre spans at one metre's distance: the screen's half of the switch distance. */
|
|
14
|
+
export function projectionScaleOf(fovYDeg, heightPx) {
|
|
15
|
+
return heightPx / (2 * Math.tan((fovYDeg * Math.PI) / 360));
|
|
16
|
+
}
|
|
17
|
+
export class HlodSet {
|
|
18
|
+
capacity;
|
|
19
|
+
maxLevels;
|
|
20
|
+
tolerance;
|
|
21
|
+
band;
|
|
22
|
+
fadeSec;
|
|
23
|
+
far;
|
|
24
|
+
slots = new Map();
|
|
25
|
+
ids;
|
|
26
|
+
boxes;
|
|
27
|
+
errors;
|
|
28
|
+
levels;
|
|
29
|
+
/** The level each region is at, or arriving at. */
|
|
30
|
+
level;
|
|
31
|
+
/** The level a crossfade is leaving. */
|
|
32
|
+
from;
|
|
33
|
+
/** How far through its crossfade each region is; 1 is settled. */
|
|
34
|
+
fade;
|
|
35
|
+
box = new Float32Array(6);
|
|
36
|
+
count = 0;
|
|
37
|
+
constructor(options) {
|
|
38
|
+
this.capacity = options.capacity;
|
|
39
|
+
this.maxLevels = options.maxLevels ?? 4;
|
|
40
|
+
if (this.maxLevels < 1 || this.maxLevels >= HLOD_NONE) {
|
|
41
|
+
throw new Error(`HlodSet: maxLevels must be 1 to ${HLOD_NONE - 1}, not ${this.maxLevels}`);
|
|
42
|
+
}
|
|
43
|
+
this.tolerance = options.pixelTolerance ?? 1.5;
|
|
44
|
+
this.band = options.hysteresis ?? 0.15;
|
|
45
|
+
this.fadeSec = options.fadeSec ?? 0.4;
|
|
46
|
+
this.far = options.farDistance ?? Number.POSITIVE_INFINITY;
|
|
47
|
+
this.ids = new Uint32Array(this.capacity);
|
|
48
|
+
this.boxes = new Float32Array(this.capacity * 6);
|
|
49
|
+
this.errors = new Float32Array(this.capacity * this.maxLevels);
|
|
50
|
+
this.levels = new Uint8Array(this.capacity);
|
|
51
|
+
this.level = new Uint8Array(this.capacity);
|
|
52
|
+
this.from = new Uint8Array(this.capacity);
|
|
53
|
+
this.fade = new Float32Array(this.capacity);
|
|
54
|
+
}
|
|
55
|
+
get size() {
|
|
56
|
+
return this.count;
|
|
57
|
+
}
|
|
58
|
+
has(id) {
|
|
59
|
+
return this.slots.has(id);
|
|
60
|
+
}
|
|
61
|
+
/** The level a region is at or arriving at, or `HLOD_NONE`. -1 for a region not in the set. */
|
|
62
|
+
levelOf(id) {
|
|
63
|
+
const slot = this.slots.get(id);
|
|
64
|
+
return slot === undefined ? -1 : this.level[slot];
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Add a region: its box as min then max, and one geometric error per level, finest first and
|
|
68
|
+
* never shrinking. It arrives at no level and fades into the one the next `select` picks.
|
|
69
|
+
*/
|
|
70
|
+
add(id, box, errors) {
|
|
71
|
+
if (this.slots.has(id))
|
|
72
|
+
throw new Error(`HlodSet: region ${id} is already in the set`);
|
|
73
|
+
if (this.count >= this.capacity) {
|
|
74
|
+
throw new Error(`HlodSet: the set holds ${this.capacity} regions and is full`);
|
|
75
|
+
}
|
|
76
|
+
if (errors.length < 1 || errors.length > this.maxLevels) {
|
|
77
|
+
throw new Error(`HlodSet: region ${id} has ${errors.length} levels; 1 to ${this.maxLevels} are allowed`);
|
|
78
|
+
}
|
|
79
|
+
for (let i = 1; i < errors.length; i++) {
|
|
80
|
+
if (errors[i] < errors[i - 1]) {
|
|
81
|
+
throw new Error(`HlodSet: region ${id}'s level ${i} is finer than level ${i - 1}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const slot = this.count++;
|
|
85
|
+
this.slots.set(id, slot);
|
|
86
|
+
this.ids[slot] = id;
|
|
87
|
+
for (let i = 0; i < 6; i++)
|
|
88
|
+
this.boxes[slot * 6 + i] = box[i];
|
|
89
|
+
for (let i = 0; i < errors.length; i++) {
|
|
90
|
+
this.errors[slot * this.maxLevels + i] = errors[i];
|
|
91
|
+
}
|
|
92
|
+
this.levels[slot] = errors.length;
|
|
93
|
+
this.level[slot] = HLOD_NONE;
|
|
94
|
+
this.from[slot] = HLOD_NONE;
|
|
95
|
+
this.fade[slot] = 1;
|
|
96
|
+
}
|
|
97
|
+
/** Remove a region; nothing if it is not there. The last region takes its slot. */
|
|
98
|
+
remove(id) {
|
|
99
|
+
const slot = this.slots.get(id);
|
|
100
|
+
if (slot === undefined)
|
|
101
|
+
return;
|
|
102
|
+
this.slots.delete(id);
|
|
103
|
+
const last = --this.count;
|
|
104
|
+
if (slot === last)
|
|
105
|
+
return;
|
|
106
|
+
const moved = this.ids[last];
|
|
107
|
+
this.slots.set(moved, slot);
|
|
108
|
+
this.ids[slot] = moved;
|
|
109
|
+
this.boxes.copyWithin(slot * 6, last * 6, last * 6 + 6);
|
|
110
|
+
this.errors.copyWithin(slot * this.maxLevels, last * this.maxLevels, (last + 1) * this.maxLevels);
|
|
111
|
+
this.levels[slot] = this.levels[last];
|
|
112
|
+
this.level[slot] = this.level[last];
|
|
113
|
+
this.from[slot] = this.from[last];
|
|
114
|
+
this.fade[slot] = this.fade[last];
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Decide every region's level for this view and write what to draw into `out`, returning how
|
|
118
|
+
* many draws that is. `projectionScale` is `projectionScaleOf(fov, height)`; `occluder` may be
|
|
119
|
+
* the renderer, asked after this frame's occluders are declared.
|
|
120
|
+
*/
|
|
121
|
+
select(eye, projectionScale, frustum, occluder, dtSec, out) {
|
|
122
|
+
const ex = eye[0];
|
|
123
|
+
const ey = eye[1];
|
|
124
|
+
const ez = eye[2];
|
|
125
|
+
const perError = projectionScale / this.tolerance;
|
|
126
|
+
const step = this.fadeSec > 0 ? dtSec / this.fadeSec : 1;
|
|
127
|
+
let n = 0;
|
|
128
|
+
for (let slot = 0; slot < this.count; slot++) {
|
|
129
|
+
const b = slot * 6;
|
|
130
|
+
const dx = Math.max(this.boxes[b] - ex, 0, ex - this.boxes[b + 3]);
|
|
131
|
+
const dy = Math.max(this.boxes[b + 1] - ey, 0, ey - this.boxes[b + 4]);
|
|
132
|
+
const dz = Math.max(this.boxes[b + 2] - ez, 0, ez - this.boxes[b + 5]);
|
|
133
|
+
const d = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
134
|
+
const target = this.levelFor(slot, d, perError);
|
|
135
|
+
this.move(slot, target);
|
|
136
|
+
for (let i = 0; i < 6; i++)
|
|
137
|
+
this.box[i] = this.boxes[b + i];
|
|
138
|
+
if (!batchBoxVisible(this.box, frustum, occluder)) {
|
|
139
|
+
this.fade[slot] = 1;
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
let t = this.fade[slot];
|
|
143
|
+
if (t < 1) {
|
|
144
|
+
t = Math.min(1, t + step);
|
|
145
|
+
this.fade[slot] = t;
|
|
146
|
+
}
|
|
147
|
+
const level = this.level[slot];
|
|
148
|
+
const id = this.ids[slot];
|
|
149
|
+
if (t >= 1) {
|
|
150
|
+
if (level !== HLOD_NONE)
|
|
151
|
+
n = this.emit(out, n, id, level, 0);
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
/* Nothing of the arriving level at t = 0, and a dither of 0 would draw it whole. */
|
|
155
|
+
if (level !== HLOD_NONE && t > 0)
|
|
156
|
+
n = this.emit(out, n, id, level, t);
|
|
157
|
+
const from = this.from[slot];
|
|
158
|
+
if (from !== HLOD_NONE)
|
|
159
|
+
n = this.emit(out, n, id, from, -t);
|
|
160
|
+
}
|
|
161
|
+
out.count = n;
|
|
162
|
+
return n;
|
|
163
|
+
}
|
|
164
|
+
/** The level a region at distance `d` should be at, from where it is, through the bands. */
|
|
165
|
+
levelFor(slot, d, perError) {
|
|
166
|
+
const count = this.levels[slot];
|
|
167
|
+
const current = this.level[slot];
|
|
168
|
+
/* NONE counts as the level past the coarsest, whose distance is the far limit. */
|
|
169
|
+
let at = current === HLOD_NONE ? count : current;
|
|
170
|
+
while (at < count && d > this.switchAt(slot, at + 1, count, perError) * (1 + this.band))
|
|
171
|
+
at++;
|
|
172
|
+
while (at > 0 && d < this.switchAt(slot, at, count, perError) * (1 - this.band))
|
|
173
|
+
at--;
|
|
174
|
+
return at === count ? HLOD_NONE : at;
|
|
175
|
+
}
|
|
176
|
+
/** The distance level `index` takes over at; the level past the coarsest is the far limit. */
|
|
177
|
+
switchAt(slot, index, count, perError) {
|
|
178
|
+
if (index >= count)
|
|
179
|
+
return this.far;
|
|
180
|
+
return this.errors[slot * this.maxLevels + index] * perError;
|
|
181
|
+
}
|
|
182
|
+
/** Begin, reverse or redirect a crossfade toward `target`. */
|
|
183
|
+
move(slot, target) {
|
|
184
|
+
const level = this.level[slot];
|
|
185
|
+
if (target === level)
|
|
186
|
+
return;
|
|
187
|
+
const fade = this.fade[slot];
|
|
188
|
+
if (fade >= 1) {
|
|
189
|
+
this.from[slot] = level;
|
|
190
|
+
this.fade[slot] = 0;
|
|
191
|
+
}
|
|
192
|
+
else if (target === this.from[slot]) {
|
|
193
|
+
/* Back the way it came, at the share each level already covers rather than from the start.
|
|
194
|
+
The cells swap — the arriving level always takes the low ones — so a reversal changes the
|
|
195
|
+
grain for a frame and never the balance. */
|
|
196
|
+
this.from[slot] = level;
|
|
197
|
+
this.fade[slot] = 1 - fade;
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
/* A third level: leave from whichever of the two covers more of the region. */
|
|
201
|
+
this.from[slot] = fade < 0.5 ? this.from[slot] : level;
|
|
202
|
+
this.fade[slot] = 0;
|
|
203
|
+
}
|
|
204
|
+
this.level[slot] = target;
|
|
205
|
+
if (this.fadeSec <= 0)
|
|
206
|
+
this.fade[slot] = 1;
|
|
207
|
+
}
|
|
208
|
+
emit(out, n, id, level, dither) {
|
|
209
|
+
out.region[n] = id;
|
|
210
|
+
out.level[n] = level;
|
|
211
|
+
out.dither[n] = dither;
|
|
212
|
+
return n + 1;
|
|
213
|
+
}
|
|
214
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@driftengine/core",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.6.0",
|
|
4
4
|
"description": "DriftEngine reusable browser 3D runtime",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
],
|
|
30
30
|
"sideEffects": false,
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@driftengine/drft": "4.
|
|
33
|
-
"@driftengine/physics": "4.
|
|
32
|
+
"@driftengine/drft": "4.6.0",
|
|
33
|
+
"@driftengine/physics": "4.6.0",
|
|
34
34
|
"gl-matrix": "^3.4.3"
|
|
35
35
|
},
|
|
36
36
|
"author": "Drift Technologies",
|
|
@@ -63,8 +63,8 @@
|
|
|
63
63
|
"prepack": "node ../../scripts/build.mjs @driftengine/core"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"@driftengine/nav": "4.
|
|
67
|
-
"@driftengine/network": "4.
|
|
68
|
-
"@driftengine/texture": "4.
|
|
66
|
+
"@driftengine/nav": "4.6.0",
|
|
67
|
+
"@driftengine/network": "4.6.0",
|
|
68
|
+
"@driftengine/texture": "4.6.0"
|
|
69
69
|
}
|
|
70
70
|
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Booleans on axis-aligned boxes, exactly and with as few faces as the result has.
|
|
3
|
+
*
|
|
4
|
+
* **Why beside `csg.ts` rather than in it.** A BSP boolean splits every face along every plane that
|
|
5
|
+
* crosses it, unrelated cutters included, and never re-merges: a wall of seven boxes with twenty
|
|
6
|
+
* window openings cut out of it came back as 325,187 triangles and took a minute. Boxes that share
|
|
7
|
+
* their axes need none of that. Every face of the result lies on a plane some box already has, so
|
|
8
|
+
* the space splits into the grid of all their coordinates, each cell is in or out by applying the
|
|
9
|
+
* operations to its centre in order, and the surface is the faces between cells that differ —
|
|
10
|
+
* merged greedily into the largest rectangles that fit. The same wall is a few hundred triangles,
|
|
11
|
+
* in milliseconds.
|
|
12
|
+
*
|
|
13
|
+
* **What it gives up.** Only boxes, only on the three axes: a box turned off them is the BSP's.
|
|
14
|
+
* Merged rectangles meet with T-junctions, as the BSP's pieces do, so the result is closed as a
|
|
15
|
+
* surface — its volume exact — but not edge for edge. Texture coordinates run 0..1 across the
|
|
16
|
+
* result's own extent on each face's plane, which is what `solidBox` gives a single box. The grid
|
|
17
|
+
* costs a byte a cell, so a caller with hundreds of boxes should check `boxBooleanCells` first.
|
|
18
|
+
*/
|
|
19
|
+
import type { Solid } from './solid.ts';
|
|
20
|
+
import { emptySolid } from './solid.ts';
|
|
21
|
+
import { SolidWriter } from './solidWriter.ts';
|
|
22
|
+
|
|
23
|
+
export interface BoxOperation {
|
|
24
|
+
/** Minimum and maximum corners: `[x0, y0, z0, x1, y1, z1]`. */
|
|
25
|
+
readonly box: readonly [number, number, number, number, number, number];
|
|
26
|
+
readonly op: 'union' | 'subtract' | 'intersect';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Coordinates within this distance are one. */
|
|
30
|
+
const SAME = 1e-6;
|
|
31
|
+
|
|
32
|
+
function axis(operations: readonly BoxOperation[], a: number): number[] {
|
|
33
|
+
const values = operations
|
|
34
|
+
.flatMap((o) => [o.box[a] as number, o.box[a + 3] as number])
|
|
35
|
+
.sort((p, q) => p - q);
|
|
36
|
+
const out: number[] = [];
|
|
37
|
+
for (const v of values)
|
|
38
|
+
if (out.length === 0 || v - (out[out.length - 1] as number) > SAME) out.push(v);
|
|
39
|
+
return out;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** How many grid cells `solidBoxBoolean` would allocate for `operations`. */
|
|
43
|
+
export function boxBooleanCells(operations: readonly BoxOperation[]): number {
|
|
44
|
+
return (
|
|
45
|
+
(axis(operations, 0).length - 1) *
|
|
46
|
+
(axis(operations, 1).length - 1) *
|
|
47
|
+
(axis(operations, 2).length - 1)
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** The solid the operations make, applied left to right from nothing. */
|
|
52
|
+
export function solidBoxBoolean(operations: readonly BoxOperation[]): Solid {
|
|
53
|
+
if (operations.length === 0) return emptySolid();
|
|
54
|
+
const xs = axis(operations, 0);
|
|
55
|
+
const ys = axis(operations, 1);
|
|
56
|
+
const zs = axis(operations, 2);
|
|
57
|
+
const nx = xs.length - 1;
|
|
58
|
+
const ny = ys.length - 1;
|
|
59
|
+
const nz = zs.length - 1;
|
|
60
|
+
if (nx <= 0 || ny <= 0 || nz <= 0) return emptySolid();
|
|
61
|
+
const inside = new Uint8Array(nx * ny * nz);
|
|
62
|
+
const at = (i: number, j: number, k: number): number => (k * ny + j) * nx + i;
|
|
63
|
+
for (let k = 0; k < nz; k += 1) {
|
|
64
|
+
const cz = ((zs[k] as number) + (zs[k + 1] as number)) / 2;
|
|
65
|
+
for (let j = 0; j < ny; j += 1) {
|
|
66
|
+
const cy = ((ys[j] as number) + (ys[j + 1] as number)) / 2;
|
|
67
|
+
for (let i = 0; i < nx; i += 1) {
|
|
68
|
+
const cx = ((xs[i] as number) + (xs[i + 1] as number)) / 2;
|
|
69
|
+
let state = false;
|
|
70
|
+
for (const o of operations) {
|
|
71
|
+
const b = o.box;
|
|
72
|
+
const hit = cx > b[0] && cx < b[3] && cy > b[1] && cy < b[4] && cz > b[2] && cz < b[5];
|
|
73
|
+
if (o.op === 'union') state ||= hit;
|
|
74
|
+
else if (o.op === 'subtract') state &&= !hit;
|
|
75
|
+
else state &&= hit;
|
|
76
|
+
}
|
|
77
|
+
inside[at(i, j, k)] = state ? 1 : 0;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const filled = (i: number, j: number, k: number): boolean =>
|
|
82
|
+
i >= 0 && j >= 0 && k >= 0 && i < nx && j < ny && k < nz && inside[at(i, j, k)] === 1;
|
|
83
|
+
const out = new SolidWriter();
|
|
84
|
+
const coords = [xs, ys, zs];
|
|
85
|
+
const counts = [nx, ny, nz];
|
|
86
|
+
const lo = [xs[0] as number, ys[0] as number, zs[0] as number];
|
|
87
|
+
const span = [
|
|
88
|
+
(xs[nx] as number) - (lo[0] as number),
|
|
89
|
+
(ys[ny] as number) - (lo[1] as number),
|
|
90
|
+
(zs[nz] as number) - (lo[2] as number),
|
|
91
|
+
];
|
|
92
|
+
for (let d = 0; d < 3; d += 1) {
|
|
93
|
+
/* The face plane's two in-plane axes, ordered so (u × v) is +d. */
|
|
94
|
+
const u = (d + 1) % 3;
|
|
95
|
+
const v = (d + 2) % 3;
|
|
96
|
+
const nu = counts[u] as number;
|
|
97
|
+
const nv = counts[v] as number;
|
|
98
|
+
for (let s = 0; s <= (counts[d] as number); s += 1) {
|
|
99
|
+
for (const sign of [1, -1]) {
|
|
100
|
+
/* Faces on plane s facing `sign`: the cell behind is in, the one in front is out. */
|
|
101
|
+
const mask = new Uint8Array(nu * nv);
|
|
102
|
+
for (let b = 0; b < nv; b += 1) {
|
|
103
|
+
for (let a = 0; a < nu; a += 1) {
|
|
104
|
+
const cell = [0, 0, 0];
|
|
105
|
+
cell[u] = a;
|
|
106
|
+
cell[v] = b;
|
|
107
|
+
cell[d] = sign > 0 ? s - 1 : s;
|
|
108
|
+
const front = [...cell];
|
|
109
|
+
front[d] = sign > 0 ? s : s - 1;
|
|
110
|
+
const inCell = filled(cell[0] as number, cell[1] as number, cell[2] as number);
|
|
111
|
+
const inFront = filled(front[0] as number, front[1] as number, front[2] as number);
|
|
112
|
+
if (inCell && !inFront) mask[b * nu + a] = 1;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
for (let b = 0; b < nv; b += 1) {
|
|
116
|
+
for (let a = 0; a < nu; a += 1) {
|
|
117
|
+
if (mask[b * nu + a] !== 1) continue;
|
|
118
|
+
let a1 = a + 1;
|
|
119
|
+
while (a1 < nu && mask[b * nu + a1] === 1) a1 += 1;
|
|
120
|
+
let b1 = b + 1;
|
|
121
|
+
grow: while (b1 < nv) {
|
|
122
|
+
for (let x = a; x < a1; x += 1) if (mask[b1 * nu + x] !== 1) break grow;
|
|
123
|
+
b1 += 1;
|
|
124
|
+
}
|
|
125
|
+
for (let y = b; y < b1; y += 1) for (let x = a; x < a1; x += 1) mask[y * nu + x] = 0;
|
|
126
|
+
quad(
|
|
127
|
+
out,
|
|
128
|
+
d,
|
|
129
|
+
u,
|
|
130
|
+
v,
|
|
131
|
+
sign,
|
|
132
|
+
(coords[d] as number[])[s] as number,
|
|
133
|
+
[
|
|
134
|
+
(coords[u] as number[])[a] as number,
|
|
135
|
+
(coords[u] as number[])[a1] as number,
|
|
136
|
+
(coords[v] as number[])[b] as number,
|
|
137
|
+
(coords[v] as number[])[b1] as number,
|
|
138
|
+
],
|
|
139
|
+
lo,
|
|
140
|
+
span,
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return out.finish();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function quad(
|
|
151
|
+
out: SolidWriter,
|
|
152
|
+
d: number,
|
|
153
|
+
u: number,
|
|
154
|
+
v: number,
|
|
155
|
+
sign: number,
|
|
156
|
+
plane: number,
|
|
157
|
+
[u0, u1, v0, v1]: [number, number, number, number],
|
|
158
|
+
lo: number[],
|
|
159
|
+
span: number[],
|
|
160
|
+
): void {
|
|
161
|
+
const corner = (cu: number, cv: number): number => {
|
|
162
|
+
const p = [0, 0, 0];
|
|
163
|
+
p[d] = plane;
|
|
164
|
+
p[u] = cu;
|
|
165
|
+
p[v] = cv;
|
|
166
|
+
const n = [0, 0, 0];
|
|
167
|
+
n[d] = sign;
|
|
168
|
+
return out.vertex(
|
|
169
|
+
p[0] as number,
|
|
170
|
+
p[1] as number,
|
|
171
|
+
p[2] as number,
|
|
172
|
+
n[0] as number,
|
|
173
|
+
n[1] as number,
|
|
174
|
+
n[2] as number,
|
|
175
|
+
(cu - (lo[u] as number)) / ((span[u] as number) || 1),
|
|
176
|
+
(cv - (lo[v] as number)) / ((span[v] as number) || 1),
|
|
177
|
+
);
|
|
178
|
+
};
|
|
179
|
+
const a = corner(u0, v0);
|
|
180
|
+
const b = corner(u1, v0);
|
|
181
|
+
const c = corner(u1, v1);
|
|
182
|
+
const e = corner(u0, v1);
|
|
183
|
+
/* Counter-clockwise from outside: (u × v) is +d, so a facing +d winds a b c, a facing −d reverses. */
|
|
184
|
+
if (sign > 0) out.quad(a, b, c, e);
|
|
185
|
+
else out.quad(a, e, c, b);
|
|
186
|
+
}
|