@zephyr3d/scene 0.1.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/dist/animation/animation.js +173 -0
- package/dist/animation/animation.js.map +1 -0
- package/dist/animation/animationset.js +95 -0
- package/dist/animation/animationset.js.map +1 -0
- package/dist/animation/animationtrack.js +38 -0
- package/dist/animation/animationtrack.js.map +1 -0
- package/dist/animation/eulerrotationtrack.js +33 -0
- package/dist/animation/eulerrotationtrack.js.map +1 -0
- package/dist/animation/rotationtrack.js +37 -0
- package/dist/animation/rotationtrack.js.map +1 -0
- package/dist/animation/scaletrack.js +36 -0
- package/dist/animation/scaletrack.js.map +1 -0
- package/dist/animation/skeleton.js +97 -0
- package/dist/animation/skeleton.js.map +1 -0
- package/dist/animation/translationtrack.js +36 -0
- package/dist/animation/translationtrack.js.map +1 -0
- package/dist/animation/usertrack.js +47 -0
- package/dist/animation/usertrack.js.map +1 -0
- package/dist/app.js +173 -0
- package/dist/app.js.map +1 -0
- package/dist/asset/assetmanager.js +476 -0
- package/dist/asset/assetmanager.js.map +1 -0
- package/dist/asset/builtin.js +373 -0
- package/dist/asset/builtin.js.map +1 -0
- package/dist/asset/loaders/dds/dds.js +472 -0
- package/dist/asset/loaders/dds/dds.js.map +1 -0
- package/dist/asset/loaders/dds/dds_loader.js +38 -0
- package/dist/asset/loaders/dds/dds_loader.js.map +1 -0
- package/dist/asset/loaders/gltf/gltf_loader.js +981 -0
- package/dist/asset/loaders/gltf/gltf_loader.js.map +1 -0
- package/dist/asset/loaders/gltf/helpers.js +314 -0
- package/dist/asset/loaders/gltf/helpers.js.map +1 -0
- package/dist/asset/loaders/hdr/hdr.js +175 -0
- package/dist/asset/loaders/hdr/hdr.js.map +1 -0
- package/dist/asset/loaders/image/tga_Loader.js +117 -0
- package/dist/asset/loaders/image/tga_Loader.js.map +1 -0
- package/dist/asset/loaders/image/webimage_loader.js +50 -0
- package/dist/asset/loaders/image/webimage_loader.js.map +1 -0
- package/dist/asset/loaders/loader.js +45 -0
- package/dist/asset/loaders/loader.js.map +1 -0
- package/dist/asset/model.js +264 -0
- package/dist/asset/model.js.map +1 -0
- package/dist/blitter/blitter.js +389 -0
- package/dist/blitter/blitter.js.map +1 -0
- package/dist/blitter/box.js +118 -0
- package/dist/blitter/box.js.map +1 -0
- package/dist/blitter/copy.js +22 -0
- package/dist/blitter/copy.js.map +1 -0
- package/dist/blitter/depthlimitedgaussion.js +166 -0
- package/dist/blitter/depthlimitedgaussion.js.map +1 -0
- package/dist/blitter/gaussianblur.js +229 -0
- package/dist/blitter/gaussianblur.js.map +1 -0
- package/dist/camera/base.js +90 -0
- package/dist/camera/base.js.map +1 -0
- package/dist/camera/camera.js +358 -0
- package/dist/camera/camera.js.map +1 -0
- package/dist/camera/fps.js +246 -0
- package/dist/camera/fps.js.map +1 -0
- package/dist/camera/orbit.js +157 -0
- package/dist/camera/orbit.js.map +1 -0
- package/dist/camera/orthocamera.js +126 -0
- package/dist/camera/orthocamera.js.map +1 -0
- package/dist/camera/perspectivecamera.js +133 -0
- package/dist/camera/perspectivecamera.js.map +1 -0
- package/dist/index.d.ts +8402 -0
- package/dist/index.js +87 -0
- package/dist/index.js.map +1 -0
- package/dist/input/inputmgr.js +242 -0
- package/dist/input/inputmgr.js.map +1 -0
- package/dist/material/blinn.js +75 -0
- package/dist/material/blinn.js.map +1 -0
- package/dist/material/grassmaterial.js +221 -0
- package/dist/material/grassmaterial.js.map +1 -0
- package/dist/material/lambert.js +52 -0
- package/dist/material/lambert.js.map +1 -0
- package/dist/material/lightmodel.js +2074 -0
- package/dist/material/lightmodel.js.map +1 -0
- package/dist/material/lit.js +578 -0
- package/dist/material/lit.js.map +1 -0
- package/dist/material/material.js +458 -0
- package/dist/material/material.js.map +1 -0
- package/dist/material/meshmaterial.js +311 -0
- package/dist/material/meshmaterial.js.map +1 -0
- package/dist/material/mixins/albedocolor.js +130 -0
- package/dist/material/mixins/albedocolor.js.map +1 -0
- package/dist/material/mixins/texture.js +110 -0
- package/dist/material/mixins/texture.js.map +1 -0
- package/dist/material/mixins/vertexcolor.js +45 -0
- package/dist/material/mixins/vertexcolor.js.map +1 -0
- package/dist/material/pbr.js +27 -0
- package/dist/material/pbr.js.map +1 -0
- package/dist/material/standard.js +282 -0
- package/dist/material/standard.js.map +1 -0
- package/dist/material/terrainlightmodel.js +259 -0
- package/dist/material/terrainlightmodel.js.map +1 -0
- package/dist/material/terrainmaterial.js +139 -0
- package/dist/material/terrainmaterial.js.map +1 -0
- package/dist/material/unlit.js +29 -0
- package/dist/material/unlit.js.map +1 -0
- package/dist/posteffect/bloom.js +398 -0
- package/dist/posteffect/bloom.js.map +1 -0
- package/dist/posteffect/compositor.js +264 -0
- package/dist/posteffect/compositor.js.map +1 -0
- package/dist/posteffect/fxaa.js +291 -0
- package/dist/posteffect/fxaa.js.map +1 -0
- package/dist/posteffect/grayscale.js +87 -0
- package/dist/posteffect/grayscale.js.map +1 -0
- package/dist/posteffect/posteffect.js +165 -0
- package/dist/posteffect/posteffect.js.map +1 -0
- package/dist/posteffect/sao.js +327 -0
- package/dist/posteffect/sao.js.map +1 -0
- package/dist/posteffect/tonemap.js +112 -0
- package/dist/posteffect/tonemap.js.map +1 -0
- package/dist/posteffect/water.js +535 -0
- package/dist/posteffect/water.js.map +1 -0
- package/dist/render/clipmap.js +462 -0
- package/dist/render/clipmap.js.map +1 -0
- package/dist/render/cluster_light.js +329 -0
- package/dist/render/cluster_light.js.map +1 -0
- package/dist/render/cull_visitor.js +124 -0
- package/dist/render/cull_visitor.js.map +1 -0
- package/dist/render/depth_pass.js +47 -0
- package/dist/render/depth_pass.js.map +1 -0
- package/dist/render/envlight.js +282 -0
- package/dist/render/envlight.js.map +1 -0
- package/dist/render/forward.js +186 -0
- package/dist/render/forward.js.map +1 -0
- package/dist/render/forward_pass.js +137 -0
- package/dist/render/forward_pass.js.map +1 -0
- package/dist/render/helper.js +38 -0
- package/dist/render/helper.js.map +1 -0
- package/dist/render/primitive.js +246 -0
- package/dist/render/primitive.js.map +1 -0
- package/dist/render/render_queue.js +163 -0
- package/dist/render/render_queue.js.map +1 -0
- package/dist/render/renderpass.js +151 -0
- package/dist/render/renderpass.js.map +1 -0
- package/dist/render/renderscheme.js +61 -0
- package/dist/render/renderscheme.js.map +1 -0
- package/dist/render/scatteringlut.js +634 -0
- package/dist/render/scatteringlut.js.map +1 -0
- package/dist/render/shadowmap_pass.js +70 -0
- package/dist/render/shadowmap_pass.js.map +1 -0
- package/dist/render/sky.js +881 -0
- package/dist/render/sky.js.map +1 -0
- package/dist/render/temporalcache.js +222 -0
- package/dist/render/temporalcache.js.map +1 -0
- package/dist/render/watermesh.js +835 -0
- package/dist/render/watermesh.js.map +1 -0
- package/dist/scene/environment.js +146 -0
- package/dist/scene/environment.js.map +1 -0
- package/dist/scene/graph_node.js +69 -0
- package/dist/scene/graph_node.js.map +1 -0
- package/dist/scene/light.js +436 -0
- package/dist/scene/light.js.map +1 -0
- package/dist/scene/mesh.js +215 -0
- package/dist/scene/mesh.js.map +1 -0
- package/dist/scene/model.js +111 -0
- package/dist/scene/model.js.map +1 -0
- package/dist/scene/octree.js +651 -0
- package/dist/scene/octree.js.map +1 -0
- package/dist/scene/octree_update_visitor.js +16 -0
- package/dist/scene/octree_update_visitor.js.map +1 -0
- package/dist/scene/raycast_visitor.js +72 -0
- package/dist/scene/raycast_visitor.js.map +1 -0
- package/dist/scene/scene.js +225 -0
- package/dist/scene/scene.js.map +1 -0
- package/dist/scene/scene_node.js +299 -0
- package/dist/scene/scene_node.js.map +1 -0
- package/dist/scene/terrain/grass.js +277 -0
- package/dist/scene/terrain/grass.js.map +1 -0
- package/dist/scene/terrain/heightfield.js +391 -0
- package/dist/scene/terrain/heightfield.js.map +1 -0
- package/dist/scene/terrain/patch.js +530 -0
- package/dist/scene/terrain/patch.js.map +1 -0
- package/dist/scene/terrain/quadtree.js +430 -0
- package/dist/scene/terrain/quadtree.js.map +1 -0
- package/dist/scene/terrain/terrain.js +258 -0
- package/dist/scene/terrain/terrain.js.map +1 -0
- package/dist/scene/xform.js +224 -0
- package/dist/scene/xform.js.map +1 -0
- package/dist/shaders/builtins.js +110 -0
- package/dist/shaders/builtins.js.map +1 -0
- package/dist/shaders/framework.js +709 -0
- package/dist/shaders/framework.js.map +1 -0
- package/dist/shaders/lighting.js +335 -0
- package/dist/shaders/lighting.js.map +1 -0
- package/dist/shaders/misc.js +405 -0
- package/dist/shaders/misc.js.map +1 -0
- package/dist/shaders/noise.js +157 -0
- package/dist/shaders/noise.js.map +1 -0
- package/dist/shaders/pbr.js +132 -0
- package/dist/shaders/pbr.js.map +1 -0
- package/dist/shaders/shadow.js +642 -0
- package/dist/shaders/shadow.js.map +1 -0
- package/dist/shaders/water.js +630 -0
- package/dist/shaders/water.js.map +1 -0
- package/dist/shadow/esm.js +235 -0
- package/dist/shadow/esm.js.map +1 -0
- package/dist/shadow/pcf_opt.js +182 -0
- package/dist/shadow/pcf_opt.js.map +1 -0
- package/dist/shadow/pcf_pd.js +190 -0
- package/dist/shadow/pcf_pd.js.map +1 -0
- package/dist/shadow/shadow_impl.js +15 -0
- package/dist/shadow/shadow_impl.js.map +1 -0
- package/dist/shadow/shadowmapper.js +709 -0
- package/dist/shadow/shadowmapper.js.map +1 -0
- package/dist/shadow/ssm.js +194 -0
- package/dist/shadow/ssm.js.map +1 -0
- package/dist/shadow/vsm.js +298 -0
- package/dist/shadow/vsm.js.map +1 -0
- package/dist/shapes/box.js +313 -0
- package/dist/shapes/box.js.map +1 -0
- package/dist/shapes/cylinder.js +74 -0
- package/dist/shapes/cylinder.js.map +1 -0
- package/dist/shapes/plane.js +48 -0
- package/dist/shapes/plane.js.map +1 -0
- package/dist/shapes/shape.js +33 -0
- package/dist/shapes/shape.js.map +1 -0
- package/dist/shapes/sphere.js +91 -0
- package/dist/shapes/sphere.js.map +1 -0
- package/dist/shapes/torus.js +100 -0
- package/dist/shapes/torus.js.map +1 -0
- package/dist/utility/aabbtree.js +390 -0
- package/dist/utility/aabbtree.js.map +1 -0
- package/dist/utility/bounding_volume.js +78 -0
- package/dist/utility/bounding_volume.js.map +1 -0
- package/dist/utility/panorama.js +163 -0
- package/dist/utility/panorama.js.map +1 -0
- package/dist/utility/pmrem.js +345 -0
- package/dist/utility/pmrem.js.map +1 -0
- package/dist/utility/shprojection.js +448 -0
- package/dist/utility/shprojection.js.map +1 -0
- package/dist/values.js +48 -0
- package/dist/values.js.map +1 -0
- package/package.json +70 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watermesh.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { Vector4 } from '@zephyr3d/base';
|
|
2
|
+
import '../app.js';
|
|
3
|
+
import './octree.js';
|
|
4
|
+
import '../material/material.js';
|
|
5
|
+
import '@zephyr3d/device';
|
|
6
|
+
import '../shaders/framework.js';
|
|
7
|
+
import '../render/scatteringlut.js';
|
|
8
|
+
import '../material/lambert.js';
|
|
9
|
+
import '../material/blinn.js';
|
|
10
|
+
import '../material/unlit.js';
|
|
11
|
+
import '../material/lightmodel.js';
|
|
12
|
+
import '../render/forward.js';
|
|
13
|
+
import { SkyRenderer } from '../render/sky.js';
|
|
14
|
+
import '../render/clipmap.js';
|
|
15
|
+
import { EnvIBL, EnvHemisphericAmbient, EnvConstantAmbient } from '../render/envlight.js';
|
|
16
|
+
import '../render/watermesh.js';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Wrapper for environmant lighting
|
|
20
|
+
* @public
|
|
21
|
+
*/ class EnvLightWrapper {
|
|
22
|
+
_envLight;
|
|
23
|
+
_ambientColor;
|
|
24
|
+
_ambientDown;
|
|
25
|
+
_ambientUp;
|
|
26
|
+
_radianceMap;
|
|
27
|
+
_irradianceMap;
|
|
28
|
+
_strength;
|
|
29
|
+
/** @internal */ constructor(){
|
|
30
|
+
this._envLight = new EnvIBL();
|
|
31
|
+
this._ambientColor = new Vector4(0.2, 0.2, 0.2, 1);
|
|
32
|
+
this._ambientDown = new Vector4(0.2, 0.2, 0.2, 1);
|
|
33
|
+
this._ambientUp = new Vector4(0.3, 0.5, 0.8, 1);
|
|
34
|
+
this._radianceMap = null;
|
|
35
|
+
this._irradianceMap = null;
|
|
36
|
+
this._strength = 1;
|
|
37
|
+
}
|
|
38
|
+
/** @internal */ getHash(ctx) {
|
|
39
|
+
return ctx.drawEnvLight ? `${this.type}:${this._envLight.hasRadiance() ? '1' : '0'}:${this._envLight.hasIrradiance() ? '1' : '0'}` : 'none';
|
|
40
|
+
}
|
|
41
|
+
/** @internal */ get envLight() {
|
|
42
|
+
return this._envLight;
|
|
43
|
+
}
|
|
44
|
+
/** The strength of environment lighting */ get strength() {
|
|
45
|
+
return this._strength;
|
|
46
|
+
}
|
|
47
|
+
set strength(val) {
|
|
48
|
+
this._strength = val;
|
|
49
|
+
}
|
|
50
|
+
/** Ambient light color for environment light type constant */ get ambientColor() {
|
|
51
|
+
return this._ambientColor.clone();
|
|
52
|
+
}
|
|
53
|
+
set ambientColor(val) {
|
|
54
|
+
this._ambientColor.set(val);
|
|
55
|
+
if (this.type === 'constant') {
|
|
56
|
+
this._envLight.ambientColor = this._ambientColor;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** Up color for environment light type hemisphere */ get ambientUp() {
|
|
60
|
+
return this._ambientUp.clone();
|
|
61
|
+
}
|
|
62
|
+
set ambientUp(val) {
|
|
63
|
+
this._ambientUp.set(val);
|
|
64
|
+
if (this.type === 'hemisphere') {
|
|
65
|
+
this._envLight.ambientUp = this._ambientUp;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** Down color for environment light type hemisphere */ get ambientDown() {
|
|
69
|
+
return this._ambientDown.clone();
|
|
70
|
+
}
|
|
71
|
+
set ambientDown(val) {
|
|
72
|
+
this._ambientDown.set(val);
|
|
73
|
+
if (this.type === 'hemisphere') {
|
|
74
|
+
this._envLight.ambientDown = this._ambientDown;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/** Radiance map for environment light type ibl */ get radianceMap() {
|
|
78
|
+
return this._radianceMap;
|
|
79
|
+
}
|
|
80
|
+
set radianceMap(tex) {
|
|
81
|
+
this._radianceMap = tex ?? null;
|
|
82
|
+
if (this.type === 'ibl') {
|
|
83
|
+
this._envLight.radianceMap = this._radianceMap;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/** Irradiance map for environment light type ibl */ get irradianceMap() {
|
|
87
|
+
return this._irradianceMap;
|
|
88
|
+
}
|
|
89
|
+
set irradianceMap(tex) {
|
|
90
|
+
this._irradianceMap = tex ?? null;
|
|
91
|
+
if (this.type === 'ibl') {
|
|
92
|
+
this._envLight.irradianceMap = this._irradianceMap;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/** The environment light type */ get type() {
|
|
96
|
+
return this._envLight?.getType() ?? 'none';
|
|
97
|
+
}
|
|
98
|
+
set type(val) {
|
|
99
|
+
switch(val){
|
|
100
|
+
case 'none':
|
|
101
|
+
this._envLight = null;
|
|
102
|
+
break;
|
|
103
|
+
case 'ibl':
|
|
104
|
+
if (this._envLight?.getType() !== val) {
|
|
105
|
+
this._envLight = new EnvIBL(this._radianceMap, this._irradianceMap);
|
|
106
|
+
}
|
|
107
|
+
break;
|
|
108
|
+
case 'constant':
|
|
109
|
+
if (this._envLight?.getType() !== val) {
|
|
110
|
+
this._envLight = new EnvConstantAmbient(this._ambientColor);
|
|
111
|
+
}
|
|
112
|
+
break;
|
|
113
|
+
case 'hemisphere':
|
|
114
|
+
if (this._envLight?.getType() !== val) {
|
|
115
|
+
this._envLight = new EnvHemisphericAmbient(this._ambientUp, this._ambientDown);
|
|
116
|
+
}
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Environment of scene
|
|
123
|
+
* @public
|
|
124
|
+
*/ class Environment {
|
|
125
|
+
_sky;
|
|
126
|
+
_light;
|
|
127
|
+
/** @internal */ constructor(){
|
|
128
|
+
this._sky = new SkyRenderer();
|
|
129
|
+
this._light = new EnvLightWrapper();
|
|
130
|
+
}
|
|
131
|
+
/** The sky renderer */ get sky() {
|
|
132
|
+
return this._sky;
|
|
133
|
+
}
|
|
134
|
+
/** The environment lighting renderer */ get light() {
|
|
135
|
+
return this._light;
|
|
136
|
+
}
|
|
137
|
+
/** @internal */ getHash(ctx) {
|
|
138
|
+
return `${this.light?.getHash(ctx)}:${this._sky?.getHash(ctx)}`;
|
|
139
|
+
}
|
|
140
|
+
/** @internal */ needSceneDepthTexture() {
|
|
141
|
+
return this._sky.fogType !== 'none';
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export { EnvLightWrapper, Environment };
|
|
146
|
+
//# sourceMappingURL=environment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"environment.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { SceneNode } from './scene_node.js';
|
|
2
|
+
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4
|
+
/**
|
|
5
|
+
* Graph scene node
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* Graph node is the base class of any kind of scene node that will be placed into the octree
|
|
9
|
+
*
|
|
10
|
+
* @public
|
|
11
|
+
*/ class GraphNode extends SceneNode {
|
|
12
|
+
/**
|
|
13
|
+
* Creates a graph node
|
|
14
|
+
* @param scene - The scene to which the node belongs
|
|
15
|
+
*/ constructor(scene){
|
|
16
|
+
super(scene);
|
|
17
|
+
this._renderOrder = 0;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Render order of the node
|
|
21
|
+
*/ get renderOrder() {
|
|
22
|
+
return this._renderOrder;
|
|
23
|
+
}
|
|
24
|
+
set renderOrder(val) {
|
|
25
|
+
this._renderOrder = val;
|
|
26
|
+
}
|
|
27
|
+
/** Gets the name */ getName() {
|
|
28
|
+
return this._name;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* {@inheritDoc SceneNode.isGraphNode}
|
|
32
|
+
* @override
|
|
33
|
+
*/ isGraphNode() {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* {@inheritDoc Drawable.getXForm}
|
|
38
|
+
*/ getXForm() {
|
|
39
|
+
return this;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* {@inheritDoc Drawable.getBoneMatrices}
|
|
43
|
+
*/ getBoneMatrices() {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* {@inheritDoc Drawable.getInvBindMatrix}
|
|
48
|
+
*/ getInvBindMatrix() {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* {@inheritDoc Drawable.getSortDistance}
|
|
53
|
+
*/ getSortDistance(camera) {
|
|
54
|
+
const cameraWorldMatrix = camera.worldMatrix;
|
|
55
|
+
const objectWorldMatrix = this.worldMatrix;
|
|
56
|
+
const dx = cameraWorldMatrix.m03 - objectWorldMatrix.m03;
|
|
57
|
+
const dy = cameraWorldMatrix.m13 - objectWorldMatrix.m13;
|
|
58
|
+
const dz = cameraWorldMatrix.m23 - objectWorldMatrix.m23;
|
|
59
|
+
return dx * dx + dy * dy * dz * dz;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* {@inheritDoc Drawable.isBatchable}
|
|
63
|
+
*/ isBatchable() {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export { GraphNode };
|
|
69
|
+
//# sourceMappingURL=graph_node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph_node.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
import { Vector4, Matrix4x4, Vector3 } from '@zephyr3d/base';
|
|
2
|
+
import { GraphNode } from './graph_node.js';
|
|
3
|
+
import { BoundingBox } from '../utility/bounding_volume.js';
|
|
4
|
+
import { ShadowMapper } from '../shadow/shadowmapper.js';
|
|
5
|
+
import { LIGHT_TYPE_DIRECTIONAL, LIGHT_TYPE_POINT, LIGHT_TYPE_SPOT } from '../values.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Base class for any kind of light node
|
|
9
|
+
* @public
|
|
10
|
+
*/ class BaseLight extends GraphNode {
|
|
11
|
+
/** @internal */ _type;
|
|
12
|
+
/** @internal */ _intensity;
|
|
13
|
+
/** @internal */ _positionRange;
|
|
14
|
+
/** @internal */ _directionCutoff;
|
|
15
|
+
/** @internal */ _diffuseIntensity;
|
|
16
|
+
/**
|
|
17
|
+
* Creates a light node
|
|
18
|
+
* @param scene - The scene to which the light node belongs
|
|
19
|
+
* @param type - Type of the light node
|
|
20
|
+
*/ constructor(scene, type){
|
|
21
|
+
super(scene);
|
|
22
|
+
this._intensity = 1;
|
|
23
|
+
this._type = type;
|
|
24
|
+
this._positionRange = null;
|
|
25
|
+
this._directionCutoff = null;
|
|
26
|
+
this._diffuseIntensity = null;
|
|
27
|
+
}
|
|
28
|
+
/** Gets the light type */ get lightType() {
|
|
29
|
+
return this._type;
|
|
30
|
+
}
|
|
31
|
+
/** Intensity of the light */ get intensity() {
|
|
32
|
+
return this._intensity;
|
|
33
|
+
}
|
|
34
|
+
set intensity(val) {
|
|
35
|
+
this.setIntensity(val);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Position and range of the light
|
|
39
|
+
*
|
|
40
|
+
* @remarks
|
|
41
|
+
* Gets the position in world space of the light.
|
|
42
|
+
* Light range is encoded into the W component.
|
|
43
|
+
*/ get positionAndRange() {
|
|
44
|
+
if (!this._positionRange) {
|
|
45
|
+
this.computeUniforms();
|
|
46
|
+
}
|
|
47
|
+
return this._positionRange;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Direction and cutoff of the light
|
|
51
|
+
*
|
|
52
|
+
* @remarks
|
|
53
|
+
* Gets the direction in world space of the light
|
|
54
|
+
* Light cutoff (for spot light only) is encoded into the W component.
|
|
55
|
+
*/ get directionAndCutoff() {
|
|
56
|
+
if (!this._directionCutoff) {
|
|
57
|
+
this.computeUniforms();
|
|
58
|
+
}
|
|
59
|
+
return this._directionCutoff;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Color and intensity of the light
|
|
63
|
+
*
|
|
64
|
+
* @remarks
|
|
65
|
+
* Gets the color of the light.
|
|
66
|
+
* Light intensity is encoded into the W component.
|
|
67
|
+
*/ get diffuseAndIntensity() {
|
|
68
|
+
if (!this._diffuseIntensity) {
|
|
69
|
+
this.computeUniforms();
|
|
70
|
+
}
|
|
71
|
+
return this._diffuseIntensity;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* View matrix of the light
|
|
75
|
+
*
|
|
76
|
+
* @remarks
|
|
77
|
+
* The view matrix of the light is used to transform a point
|
|
78
|
+
* from the world space to the light space.
|
|
79
|
+
*/ get viewMatrix() {
|
|
80
|
+
return this.invWorldMatrix;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* View-projection matrix of the light
|
|
84
|
+
*
|
|
85
|
+
* @remarks
|
|
86
|
+
* The view-projection matrix of the light is used to transform
|
|
87
|
+
* a point from the world space to the clip space of the light view
|
|
88
|
+
*/ get viewProjMatrix() {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Sets the intensity of the light
|
|
93
|
+
* @param val - Intensity of the light
|
|
94
|
+
* @returns self
|
|
95
|
+
*/ setIntensity(val) {
|
|
96
|
+
if (this._intensity !== val) {
|
|
97
|
+
this._intensity = val;
|
|
98
|
+
this.invalidateUniforms();
|
|
99
|
+
}
|
|
100
|
+
return this;
|
|
101
|
+
}
|
|
102
|
+
/** @internal */ invalidateUniforms() {
|
|
103
|
+
this._positionRange = null;
|
|
104
|
+
this._directionCutoff = null;
|
|
105
|
+
this._diffuseIntensity = null;
|
|
106
|
+
}
|
|
107
|
+
/** {@inheritDoc SceneNode.isLight} */ isLight() {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
/** {@inheritDoc SceneNode.isPunctualLight} */ isPunctualLight() {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
/** returns true if this is a directional light */ isDirectionLight() {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
/** returns true if this is a point light */ isPointLight() {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
/** returns true if this is a spot light */ isSpotLight() {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/*
|
|
124
|
+
export abstract class AmbientLight extends BaseLight {
|
|
125
|
+
constructor(scene: Scene, type: number) {
|
|
126
|
+
super(scene, type);
|
|
127
|
+
}
|
|
128
|
+
isAmbientLight(): this is AmbientLight {
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
*/ /*
|
|
133
|
+
export class HemiSphericLight extends AmbientLight {
|
|
134
|
+
protected _colorUp: Vector4;
|
|
135
|
+
protected _colorDown: Vector4;
|
|
136
|
+
constructor(scene: Scene) {
|
|
137
|
+
super(scene, LIGHT_TYPE_HEMISPHERIC);
|
|
138
|
+
this._colorUp = Vector4.zero();
|
|
139
|
+
this._colorDown = Vector4.zero();
|
|
140
|
+
}
|
|
141
|
+
get colorUp() {
|
|
142
|
+
return this._colorUp;
|
|
143
|
+
}
|
|
144
|
+
set colorUp(val: Vector4) {
|
|
145
|
+
this.setColorUp(val);
|
|
146
|
+
}
|
|
147
|
+
setColorUp(val: Vector4) {
|
|
148
|
+
this._colorUp.set(val);
|
|
149
|
+
this.invalidateUniforms();
|
|
150
|
+
return this;
|
|
151
|
+
}
|
|
152
|
+
get colorDown() {
|
|
153
|
+
return this._colorDown;
|
|
154
|
+
}
|
|
155
|
+
set colorDown(val: Vector4) {
|
|
156
|
+
this.setColorDown(val);
|
|
157
|
+
}
|
|
158
|
+
setColorDown(val: Vector4) {
|
|
159
|
+
this._colorDown.set(val);
|
|
160
|
+
this.invalidateUniforms();
|
|
161
|
+
return this;
|
|
162
|
+
}
|
|
163
|
+
isHemiSphericLight(): this is HemiSphericLight {
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
computeUniforms() {
|
|
167
|
+
this._positionRange = this.colorUp;
|
|
168
|
+
this._directionCutoff = this.colorDown;
|
|
169
|
+
this._diffuseIntensity = new Vector4(1, 1, 1, this.intensity);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
*/ /**
|
|
173
|
+
* Base class for any kind of puncual light
|
|
174
|
+
* @public
|
|
175
|
+
*/ class PunctualLight extends BaseLight {
|
|
176
|
+
/** @internal */ _color;
|
|
177
|
+
/** @internal */ _castShadow;
|
|
178
|
+
/** @internal */ _lightViewProjectionMatrix;
|
|
179
|
+
/** @internal */ _shadowMapper;
|
|
180
|
+
/**
|
|
181
|
+
* Creates an instance of punctual light
|
|
182
|
+
* @param scene - The scene to which the punctual light belongs
|
|
183
|
+
* @param type - The light type
|
|
184
|
+
*/ constructor(scene, type){
|
|
185
|
+
super(scene, type);
|
|
186
|
+
this._color = Vector4.one();
|
|
187
|
+
this._castShadow = false;
|
|
188
|
+
this._lightViewProjectionMatrix = Matrix4x4.identity();
|
|
189
|
+
this._shadowMapper = new ShadowMapper(this);
|
|
190
|
+
}
|
|
191
|
+
/** Color of the light */ get color() {
|
|
192
|
+
return this._color;
|
|
193
|
+
}
|
|
194
|
+
set color(clr) {
|
|
195
|
+
this.setColor(clr);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Sets color of the light
|
|
199
|
+
* @param color - The color to set
|
|
200
|
+
* @returns self
|
|
201
|
+
*/ setColor(color) {
|
|
202
|
+
this._color.set(color);
|
|
203
|
+
this.invalidateUniforms();
|
|
204
|
+
return this;
|
|
205
|
+
}
|
|
206
|
+
/** Whether this light casts shadows */ get castShadow() {
|
|
207
|
+
return this._castShadow;
|
|
208
|
+
}
|
|
209
|
+
set castShadow(b) {
|
|
210
|
+
this.setCastShadow(b);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Sets whether this light casts shadows
|
|
214
|
+
* @param b - true if the light casts shadows
|
|
215
|
+
* @returns self
|
|
216
|
+
*/ setCastShadow(b) {
|
|
217
|
+
this._castShadow = b;
|
|
218
|
+
return this;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* {@inheritDoc BaseLight.viewProjMatrix}
|
|
222
|
+
* @override
|
|
223
|
+
*/ get viewProjMatrix() {
|
|
224
|
+
return this._lightViewProjectionMatrix;
|
|
225
|
+
}
|
|
226
|
+
set viewProjMatrix(mat) {
|
|
227
|
+
this.setLightViewProjectionMatrix(mat);
|
|
228
|
+
}
|
|
229
|
+
/** The shadow mapper for this light */ get shadow() {
|
|
230
|
+
return this._shadowMapper;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Sets the view projection matrix for this light
|
|
234
|
+
* @param mat - The matrix to set
|
|
235
|
+
* @returns self
|
|
236
|
+
*/ setLightViewProjectionMatrix(mat) {
|
|
237
|
+
this._lightViewProjectionMatrix.set(mat);
|
|
238
|
+
return this;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* {@inheritDoc BaseLight.isPunctualLight}
|
|
242
|
+
* @override
|
|
243
|
+
*/ isPunctualLight() {
|
|
244
|
+
return true;
|
|
245
|
+
}
|
|
246
|
+
/** @internal */ _onTransformChanged(invalidateLocal) {
|
|
247
|
+
super._onTransformChanged(invalidateLocal);
|
|
248
|
+
this.invalidateUniforms();
|
|
249
|
+
// this._transformCallback(true, false);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Directional light
|
|
254
|
+
* @public
|
|
255
|
+
*/ class DirectionalLight extends PunctualLight {
|
|
256
|
+
static _currentSunLight = null;
|
|
257
|
+
_sunLight;
|
|
258
|
+
/**
|
|
259
|
+
* Creates an instance of directional light
|
|
260
|
+
* @param scene - The scene to which the light belongs
|
|
261
|
+
*/ constructor(scene){
|
|
262
|
+
super(scene, LIGHT_TYPE_DIRECTIONAL);
|
|
263
|
+
if (!DirectionalLight._currentSunLight) {
|
|
264
|
+
DirectionalLight._currentSunLight = this;
|
|
265
|
+
this._sunLight = true;
|
|
266
|
+
} else {
|
|
267
|
+
this._sunLight = false;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* true if the light was defined as sun light
|
|
272
|
+
*
|
|
273
|
+
* @remarks
|
|
274
|
+
* Only one directional light will be marked as sun light.
|
|
275
|
+
**/ get sunLight() {
|
|
276
|
+
return this._sunLight;
|
|
277
|
+
}
|
|
278
|
+
set sunLight(val) {
|
|
279
|
+
if (!!val !== this._sunLight) {
|
|
280
|
+
this._sunLight = !!val;
|
|
281
|
+
if (this._sunLight) {
|
|
282
|
+
DirectionalLight._currentSunLight._sunLight = false;
|
|
283
|
+
DirectionalLight._currentSunLight = this;
|
|
284
|
+
} else {
|
|
285
|
+
DirectionalLight._currentSunLight = null;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
this._sunLight = !!val;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* {@inheritDoc BaseLight.isDirectionLight}
|
|
292
|
+
* @override
|
|
293
|
+
*/ isDirectionLight() {
|
|
294
|
+
return true;
|
|
295
|
+
}
|
|
296
|
+
/** @internal */ computeBoundingVolume(bv) {
|
|
297
|
+
return null;
|
|
298
|
+
}
|
|
299
|
+
/** @internal */ computeUniforms() {
|
|
300
|
+
const a = this.worldMatrix.getRow(3);
|
|
301
|
+
const b = this.worldMatrix.getRow(2).scaleBy(-1);
|
|
302
|
+
this._positionRange = new Vector4(a.x, a.y, a.z, -1);
|
|
303
|
+
this._directionCutoff = new Vector4(b.x, b.y, b.z, 0);
|
|
304
|
+
this._diffuseIntensity = new Vector4(this.color.x, this.color.y, this.color.z, this.intensity);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Point light
|
|
309
|
+
* @public
|
|
310
|
+
*/ class PointLight extends PunctualLight {
|
|
311
|
+
/** @internal */ _range;
|
|
312
|
+
/**
|
|
313
|
+
* Creates an instance of point light
|
|
314
|
+
* @param scene - The scene to which the light belongs
|
|
315
|
+
*/ constructor(scene){
|
|
316
|
+
super(scene, LIGHT_TYPE_POINT);
|
|
317
|
+
this._range = 1;
|
|
318
|
+
this.invalidateBoundingVolume();
|
|
319
|
+
}
|
|
320
|
+
/** The range of the light */ get range() {
|
|
321
|
+
return this._range;
|
|
322
|
+
}
|
|
323
|
+
set range(val) {
|
|
324
|
+
this.setRange(val);
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Sets the range of the light
|
|
328
|
+
* @param val - The value to set
|
|
329
|
+
* @returns self
|
|
330
|
+
*/ setRange(val) {
|
|
331
|
+
val = val < 0 ? 0 : val;
|
|
332
|
+
if (this._range !== val) {
|
|
333
|
+
this._range = val;
|
|
334
|
+
this.invalidateUniforms();
|
|
335
|
+
this.invalidateBoundingVolume();
|
|
336
|
+
}
|
|
337
|
+
return this;
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* {@inheritDoc BaseLight.isPointLight}
|
|
341
|
+
* @override
|
|
342
|
+
*/ isPointLight() {
|
|
343
|
+
return true;
|
|
344
|
+
}
|
|
345
|
+
/** @internal */ computeBoundingVolume(bv) {
|
|
346
|
+
const bbox = bv ? bv : new BoundingBox();
|
|
347
|
+
bbox.minPoint = new Vector3(-this._range, -this._range, -this._range);
|
|
348
|
+
bbox.maxPoint = new Vector3(this._range, this._range, this._range);
|
|
349
|
+
return bbox;
|
|
350
|
+
}
|
|
351
|
+
/** @internal */ computeUniforms() {
|
|
352
|
+
const a = this.worldMatrix.getRow(3);
|
|
353
|
+
const b = this.worldMatrix.getRow(2);
|
|
354
|
+
this._positionRange = new Vector4(a.x, a.y, a.z, this.range);
|
|
355
|
+
this._directionCutoff = new Vector4(b.x, b.y, b.z, -1);
|
|
356
|
+
this._diffuseIntensity = new Vector4(this.color.x, this.color.y, this.color.z, this.intensity);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Spot light
|
|
361
|
+
* @public
|
|
362
|
+
*/ class SpotLight extends PunctualLight {
|
|
363
|
+
/** @internal */ _range;
|
|
364
|
+
/** @internal */ _cutoff;
|
|
365
|
+
/**
|
|
366
|
+
* Creates an instance of spot light
|
|
367
|
+
* @param scene - The scene to which the light belongs
|
|
368
|
+
*/ constructor(scene){
|
|
369
|
+
super(scene, LIGHT_TYPE_SPOT);
|
|
370
|
+
this._range = 1;
|
|
371
|
+
this._cutoff = Math.cos(Math.PI / 4);
|
|
372
|
+
this.invalidateBoundingVolume();
|
|
373
|
+
}
|
|
374
|
+
/** The range of the light */ get range() {
|
|
375
|
+
return this._range;
|
|
376
|
+
}
|
|
377
|
+
set range(val) {
|
|
378
|
+
this.setRange(val);
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Sets the range of the light
|
|
382
|
+
* @param val - The value to set
|
|
383
|
+
* @returns self
|
|
384
|
+
*/ setRange(val) {
|
|
385
|
+
val = val < 0 ? 0 : val;
|
|
386
|
+
if (this._range !== val) {
|
|
387
|
+
this._range = val;
|
|
388
|
+
this.invalidateUniforms();
|
|
389
|
+
this.invalidateBoundingVolume();
|
|
390
|
+
}
|
|
391
|
+
return this;
|
|
392
|
+
}
|
|
393
|
+
/** The cutoff of the light */ get cutoff() {
|
|
394
|
+
return this._cutoff;
|
|
395
|
+
}
|
|
396
|
+
set cutoff(val) {
|
|
397
|
+
this.setCutoff(val);
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Sets the cutoff of the light
|
|
401
|
+
* @param val - The value to set
|
|
402
|
+
* @returns self
|
|
403
|
+
*/ setCutoff(val) {
|
|
404
|
+
val = val < 0 ? 0 : val;
|
|
405
|
+
if (this._cutoff !== val) {
|
|
406
|
+
this._cutoff = val;
|
|
407
|
+
this.invalidateUniforms();
|
|
408
|
+
this.invalidateBoundingVolume();
|
|
409
|
+
}
|
|
410
|
+
return this;
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* {@inheritDoc BaseLight.isSpotLight}
|
|
414
|
+
* @override
|
|
415
|
+
*/ isSpotLight() {
|
|
416
|
+
return true;
|
|
417
|
+
}
|
|
418
|
+
/** @internal */ computeBoundingVolume(bv) {
|
|
419
|
+
const bbox = bv ? bv : new BoundingBox();
|
|
420
|
+
const cosCutoff = Math.cos(this._cutoff);
|
|
421
|
+
const r = this._range / cosCutoff * Math.sqrt(1 - cosCutoff * cosCutoff);
|
|
422
|
+
bbox.minPoint = new Vector3(-r, -r, 0);
|
|
423
|
+
bbox.maxPoint = new Vector3(r, r, this._range);
|
|
424
|
+
return bbox;
|
|
425
|
+
}
|
|
426
|
+
/** @internal */ computeUniforms() {
|
|
427
|
+
const a = this.worldMatrix.getRow(3);
|
|
428
|
+
const b = this.worldMatrix.getRow(2).scaleBy(-1);
|
|
429
|
+
this._positionRange = new Vector4(a.x, a.y, a.z, this.range);
|
|
430
|
+
this._directionCutoff = new Vector4(b.x, b.y, b.z, Math.cos(this.cutoff));
|
|
431
|
+
this._diffuseIntensity = new Vector4(this.color.x, this.color.y, this.color.z, this.intensity);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
export { BaseLight, DirectionalLight, PointLight, PunctualLight, SpotLight };
|
|
436
|
+
//# sourceMappingURL=light.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"light.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|