├── .babelrc
├── .gitignore
├── README.md
├── package.json
├── public
├── assets
│ ├── ambient
│ │ ├── track1.mp3
│ │ ├── track2.mp3
│ │ └── track3.mp3
│ ├── arc
│ │ ├── arc.gltf
│ │ ├── arc_data.bin
│ │ └── arc_diffuse.png
│ ├── char
│ │ ├── char_diffuse.png
│ │ ├── char_mesh.fbx
│ │ ├── char_minmax.json
│ │ ├── char_norm.exr
│ │ └── char_pos.exr
│ ├── cliff
│ │ ├── cliff.gltf
│ │ └── cliff_data.bin
│ ├── cubes
│ │ ├── cubes.gltf
│ │ └── cubes_data.bin
│ ├── dried_body
│ │ ├── dried_body.gltf
│ │ └── dried_body_data.bin
│ ├── dunes
│ │ ├── dunes.gltf
│ │ └── dunes_data.bin
│ ├── favicon.png
│ ├── fire
│ │ ├── fire_col.exr
│ │ ├── fire_mesh.fbx
│ │ ├── fire_minmax.json
│ │ └── fire_pos.exr
│ ├── info.png
│ ├── mask
│ │ ├── mask.gltf
│ │ ├── mask_basecolor.png
│ │ └── mask_data.bin
│ ├── moon_rock
│ │ ├── moon_rock.gltf
│ │ └── moon_rock_data.bin
│ ├── mountains
│ │ ├── mountains.gltf
│ │ ├── mountains_data.bin
│ │ └── mountains_diff.png
│ ├── pendulum
│ │ ├── pendulum.gltf
│ │ └── pendulum_data.bin
│ ├── pendulum_base
│ │ ├── pendulum_base.gltf
│ │ └── pendulum_base_data.bin
│ ├── pyramid
│ │ ├── pyramid.gltf
│ │ └── pyramid_data.bin
│ ├── quest_controller_l
│ │ ├── quest_controller_l.gltf
│ │ └── quest_controller_l_data.bin
│ ├── quest_controller_r
│ │ ├── quest_controller_r.gltf
│ │ └── quest_controller_r_data.bin
│ ├── ruins
│ │ ├── pillar_texture.png
│ │ ├── ruins.gltf
│ │ └── ruins_data.bin
│ ├── speech
│ │ ├── comment1.mp3
│ │ ├── comment2.mp3
│ │ ├── followMe.mp3
│ │ ├── speech1.mp3
│ │ ├── speech2.mp3
│ │ ├── speech3.mp3
│ │ ├── speech4.mp3
│ │ ├── speech5.mp3
│ │ ├── speech6.mp3
│ │ ├── speech7.mp3
│ │ └── speechWin.mp3
│ ├── star.png
│ └── tex_Fern_Lush_Noise.jpg
├── index.html
└── js
│ └── tinyexr.js
├── src
├── Fire.js
├── JSX.js
├── Utils.js
├── components
│ ├── AmbientController.js
│ ├── CharacterMover.js
│ ├── CharacterStateMachine.js
│ ├── Collider.js
│ ├── CustomControl.js
│ ├── DefaultMaterial.js
│ ├── FireManager.js
│ ├── FresnelMaterial.js
│ ├── GlowMaterial.js
│ ├── Intro.js
│ ├── Mover.js
│ ├── Pendulum.js
│ ├── RingOfFire.js
│ ├── SetCharacterMaterial.js
│ ├── SetGLTFMaterial.js
│ ├── Sky.js
│ ├── SpeechController.js
│ ├── Sun.js
│ ├── VertexCacheTextures.js
│ └── WebUIController.js
├── index.js
├── libs
│ ├── FBXLoader.js
│ └── Utils.js
├── shaders
│ ├── CharacterSoftFrag.glsl
│ ├── ColorCorrection.glsl
│ ├── EyeFrag.glsl
│ ├── EyeVert.glsl
│ ├── FireRingFrag.glsl
│ ├── FireRingVert.glsl
│ ├── FogReplaceFrag.glsl
│ ├── FogReplaceVert.glsl
│ ├── FresnelFrag.glsl
│ ├── FresnelVert.glsl
│ ├── IntroFrag.glsl
│ ├── IntroVert.glsl
│ ├── LaserFrag.glsl
│ ├── LaserVert.glsl
│ ├── PendulumFrag.glsl
│ ├── PendulumMaterial.js
│ ├── PendulumVert.glsl
│ ├── PerlinNoise.glsl
│ ├── PhongFrag.glsl
│ ├── PhongVert.glsl
│ ├── SkyFrag.glsl
│ ├── SkyVert.glsl
│ ├── SunCalibratedMaterial.js
│ ├── SunFrag.glsl
│ ├── SunVert.glsl
│ ├── VertexCacheFluidFrag.glsl
│ ├── VertexCacheFluidVert.glsl
│ ├── VertexCacheSoftFrag.glsl
│ └── VertexCacheSoftVert.glsl
├── style.css
└── systems
│ ├── PendulumSystem.js
│ ├── RaycasterSystem.js
│ └── SunSystem.js
├── webpack.config.js
├── yarn-error.log
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "@babel/preset-env"
4 | ],
5 | "plugins": [
6 | "transform-regenerator",
7 | [
8 | "@babel/plugin-transform-react-jsx",
9 | {
10 | "pragma": "JSX.createElement"
11 | }
12 | ]
13 | ]
14 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .vscode/
3 | .DS_Store
4 | /dist
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # A-Frame with Webpack Example
2 |
3 | This project shows:
4 |
5 | - How to use A-Frame with Webpack and JSX for html like syntax withing Java Script similar to React
6 | - How to cleanly use and load custom shaders
7 |
8 | To get started:
9 |
10 | ```
11 | git clone https://github.com/Kif11/aframe-webpack
12 | cd aframe-webpack
13 | yarn install
14 | yarn start
15 | ```
16 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "aframe-webpack",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "private": true,
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1",
9 | "build": "webpack --colors",
10 | "start": "webpack-dev-server --open"
11 | },
12 | "keywords": [],
13 | "author": "",
14 | "license": "ISC",
15 | "devDependencies": {
16 | "@babel/core": "^7.4.3",
17 | "@babel/plugin-transform-react-jsx": "^7.3.0",
18 | "@babel/preset-env": "^7.4.3",
19 | "babel-loader": "^8.0.5",
20 | "babel-plugin-transform-regenerator": "^6.26.0",
21 | "babel-polyfill": "^6.26.0",
22 | "copy-webpack-plugin": "^5.0.2",
23 | "css-loader": "^2.1.1",
24 | "html-webpack-plugin": "^3.2.0",
25 | "style-loader": "^0.23.1",
26 | "webpack": "^4.29.6",
27 | "webpack-cli": "^3.3.0",
28 | "webpack-dev-server": "^3.2.1",
29 | "webpack-glsl-loader": "^1.0.1"
30 | },
31 | "dependencies": {
32 | "aframe": "^1.0.4",
33 | "aframe-extras": "^6.0.0"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/public/assets/ambient/track1.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/ambient/track1.mp3
--------------------------------------------------------------------------------
/public/assets/ambient/track2.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/ambient/track2.mp3
--------------------------------------------------------------------------------
/public/assets/ambient/track3.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/ambient/track3.mp3
--------------------------------------------------------------------------------
/public/assets/arc/arc.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "asset":{
3 | "version":"2.0",
4 | "generator":"Houdini GLTF 2.0 Exporter"
5 | },
6 | "accessors":[
7 | {
8 | "bufferView":0,
9 | "componentType":5123,
10 | "count":7434,
11 | "type":"SCALAR",
12 | "min":[0
13 | ],
14 | "max":[7433
15 | ]
16 | },
17 | {
18 | "bufferView":1,
19 | "componentType":5126,
20 | "count":7434,
21 | "type":"VEC3",
22 | "min":[-5.06129932,-0.0492868423,-5.41723156
23 | ],
24 | "max":[3.88940859,5.34731483,4.85920954
25 | ]
26 | },
27 | {
28 | "bufferView":2,
29 | "componentType":5126,
30 | "count":7434,
31 | "type":"VEC2",
32 | "min":[0.0042976439,0.0015797019
33 | ],
34 | "max":[0.994218946,0.994498789
35 | ]
36 | },
37 | {
38 | "bufferView":3,
39 | "componentType":5126,
40 | "count":7434,
41 | "type":"VEC3",
42 | "min":[-0.99972862,-1,-0.99972862
43 | ],
44 | "max":[0.999836385,0.994760931,0.99972862
45 | ]
46 | }
47 | ],
48 | "buffers":[
49 | {
50 | "uri":"arc_data.bin",
51 | "byteLength":252756,
52 | "name":"main_buffer"
53 | }
54 | ],
55 | "bufferViews":[
56 | {
57 | "buffer":0,
58 | "byteLength":14868,
59 | "target":34963
60 | },
61 | {
62 | "buffer":0,
63 | "byteOffset":14868,
64 | "byteLength":89208,
65 | "target":34962
66 | },
67 | {
68 | "buffer":0,
69 | "byteOffset":104076,
70 | "byteLength":59472,
71 | "target":34962
72 | },
73 | {
74 | "buffer":0,
75 | "byteOffset":163548,
76 | "byteLength":89208,
77 | "target":34962
78 | }
79 | ],
80 | "nodes":[
81 | {
82 | "name":"arc",
83 | "mesh":0
84 | }
85 | ],
86 | "meshes":[
87 | {
88 | "primitives":[
89 | {
90 | "attributes":{
91 | "NORMAL":3,
92 | "TEXCOORD_0":2,
93 | "POSITION":1
94 | },
95 | "indices":0,
96 | "material":0
97 | }
98 | ]
99 | }
100 | ],
101 | "materials":[
102 | {
103 | "name":"ArcMat",
104 | "pbrMetallicRoughness":{
105 | "metallicFactor":0,
106 | "roughnessFactor":0.65200001,
107 | "baseColorTexture":{
108 | "index":0
109 | }
110 | }
111 | }
112 | ],
113 | "scenes":[
114 | {
115 | "nodes":[0
116 | ]
117 | }
118 | ],
119 | "textures":[
120 | {
121 | "source":0
122 | }
123 | ],
124 | "images":[
125 | {
126 | "uri":"arc_diffuse.png",
127 | "mimeType":"image/png"
128 | }
129 | ],
130 | "scene":0
131 | }
132 |
--------------------------------------------------------------------------------
/public/assets/arc/arc_data.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/arc/arc_data.bin
--------------------------------------------------------------------------------
/public/assets/arc/arc_diffuse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/arc/arc_diffuse.png
--------------------------------------------------------------------------------
/public/assets/char/char_diffuse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/char/char_diffuse.png
--------------------------------------------------------------------------------
/public/assets/char/char_minmax.json:
--------------------------------------------------------------------------------
1 | {
2 | "bbox_max": "35.5030059814",
3 | "bbox_min": "-14.0982046127",
4 | "method": 0,
5 | "numframes": "64"
6 | }
--------------------------------------------------------------------------------
/public/assets/char/char_norm.exr:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/char/char_norm.exr
--------------------------------------------------------------------------------
/public/assets/char/char_pos.exr:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/char/char_pos.exr
--------------------------------------------------------------------------------
/public/assets/cliff/cliff.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "asset":{
3 | "version":"2.0",
4 | "generator":"Houdini GLTF 2.0 Exporter"
5 | },
6 | "accessors":[
7 | {
8 | "bufferView":0,
9 | "componentType":5123,
10 | "count":1524,
11 | "type":"SCALAR",
12 | "min":[0
13 | ],
14 | "max":[1523
15 | ]
16 | },
17 | {
18 | "bufferView":1,
19 | "componentType":5126,
20 | "count":1524,
21 | "type":"SCALAR",
22 | "min":[-6.07285929
23 | ],
24 | "max":[3.27972031
25 | ]
26 | },
27 | {
28 | "bufferView":2,
29 | "componentType":5126,
30 | "count":1524,
31 | "type":"SCALAR",
32 | "min":[-0.649106443
33 | ],
34 | "max":[3.59843302
35 | ]
36 | },
37 | {
38 | "bufferView":3,
39 | "componentType":5126,
40 | "count":1524,
41 | "type":"SCALAR",
42 | "min":[0.537069738
43 | ],
44 | "max":[308.893951
45 | ]
46 | },
47 | {
48 | "bufferView":4,
49 | "componentType":5126,
50 | "count":1524,
51 | "type":"VEC2",
52 | "min":[0.224635035,0.0656962991
53 | ],
54 | "max":[0.909336686,0.807251275
55 | ]
56 | },
57 | {
58 | "bufferView":5,
59 | "componentType":5126,
60 | "count":1524,
61 | "type":"SCALAR",
62 | "min":[-6.07285929
63 | ],
64 | "max":[3.27972031
65 | ]
66 | },
67 | {
68 | "bufferView":6,
69 | "componentType":5126,
70 | "count":1524,
71 | "type":"VEC3",
72 | "min":[-18.2457981,4.99803067e-16,-27.4210243
73 | ],
74 | "max":[25.9394417,30.48209,40.6441765
75 | ]
76 | },
77 | {
78 | "bufferView":7,
79 | "componentType":5126,
80 | "count":1524,
81 | "type":"VEC3",
82 | "min":[0.726913154,0.465999991,0.205086857
83 | ],
84 | "max":[0.726913154,0.465999991,0.205086857
85 | ]
86 | },
87 | {
88 | "bufferView":8,
89 | "componentType":5126,
90 | "count":1524,
91 | "type":"VEC3",
92 | "min":[-0.999538481,-0.563712358,-0.999824226
93 | ],
94 | "max":[0.993764222,0.999986112,0.999163389
95 | ]
96 | }
97 | ],
98 | "buffers":[
99 | {
100 | "uri":"cliff_data.bin",
101 | "byteLength":94488,
102 | "name":"main_buffer"
103 | }
104 | ],
105 | "bufferViews":[
106 | {
107 | "buffer":0,
108 | "byteLength":3048,
109 | "target":34963
110 | },
111 | {
112 | "buffer":0,
113 | "byteOffset":3048,
114 | "byteLength":6096,
115 | "target":34962
116 | },
117 | {
118 | "buffer":0,
119 | "byteOffset":9144,
120 | "byteLength":6096,
121 | "target":34962
122 | },
123 | {
124 | "buffer":0,
125 | "byteOffset":15240,
126 | "byteLength":6096,
127 | "target":34962
128 | },
129 | {
130 | "buffer":0,
131 | "byteOffset":21336,
132 | "byteLength":12192,
133 | "target":34962
134 | },
135 | {
136 | "buffer":0,
137 | "byteOffset":33528,
138 | "byteLength":6096,
139 | "target":34962
140 | },
141 | {
142 | "buffer":0,
143 | "byteOffset":39624,
144 | "byteLength":18288,
145 | "target":34962
146 | },
147 | {
148 | "buffer":0,
149 | "byteOffset":57912,
150 | "byteLength":18288,
151 | "target":34962
152 | },
153 | {
154 | "buffer":0,
155 | "byteOffset":76200,
156 | "byteLength":18288,
157 | "target":34962
158 | }
159 | ],
160 | "nodes":[
161 | {
162 | "name":"cliff",
163 | "mesh":0
164 | }
165 | ],
166 | "meshes":[
167 | {
168 | "primitives":[
169 | {
170 | "attributes":{
171 | "POSITION":6,
172 | "TEXCOORD_0":4,
173 | "_height":3,
174 | "NORMAL":8,
175 | "_cliffs":2,
176 | "COLOR_0":7,
177 | "_mesa":5,
178 | "_mask":1
179 | },
180 | "indices":0
181 | }
182 | ]
183 | }
184 | ],
185 | "scenes":[
186 | {
187 | "nodes":[0
188 | ]
189 | }
190 | ],
191 | "scene":0
192 | }
193 |
--------------------------------------------------------------------------------
/public/assets/cliff/cliff_data.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/cliff/cliff_data.bin
--------------------------------------------------------------------------------
/public/assets/cubes/cubes.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "asset":{
3 | "version":"2.0",
4 | "generator":"Houdini GLTF 2.0 Exporter"
5 | },
6 | "accessors":[
7 | {
8 | "bufferView":0,
9 | "componentType":5123,
10 | "count":576,
11 | "type":"SCALAR",
12 | "min":[0
13 | ],
14 | "max":[127
15 | ]
16 | },
17 | {
18 | "bufferView":1,
19 | "componentType":5126,
20 | "count":128,
21 | "type":"VEC3",
22 | "min":[-0.200000003,0,-30.2000008
23 | ],
24 | "max":[0.200000003,10,0.200000003
25 | ]
26 | }
27 | ],
28 | "buffers":[
29 | {
30 | "uri":"cubes_data.bin",
31 | "byteLength":2688
32 | }
33 | ],
34 | "bufferViews":[
35 | {
36 | "buffer":0,
37 | "byteLength":1152,
38 | "target":34963
39 | },
40 | {
41 | "buffer":0,
42 | "byteOffset":1152,
43 | "byteLength":1536,
44 | "target":34962
45 | }
46 | ],
47 | "nodes":[
48 | {
49 | "mesh":0
50 | }
51 | ],
52 | "meshes":[
53 | {
54 | "primitives":[
55 | {
56 | "attributes":{
57 | "POSITION":1
58 | },
59 | "indices":0
60 | }
61 | ]
62 | }
63 | ],
64 | "scenes":[
65 | {
66 | "nodes":[0
67 | ]
68 | }
69 | ],
70 | "scene":0
71 | }
72 |
--------------------------------------------------------------------------------
/public/assets/cubes/cubes_data.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/cubes/cubes_data.bin
--------------------------------------------------------------------------------
/public/assets/dried_body/dried_body.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "asset":{
3 | "version":"2.0",
4 | "generator":"Houdini GLTF 2.0 Exporter"
5 | },
6 | "accessors":[
7 | {
8 | "bufferView":0,
9 | "componentType":5123,
10 | "count":3186,
11 | "type":"SCALAR",
12 | "min":[0
13 | ],
14 | "max":[3185
15 | ]
16 | },
17 | {
18 | "bufferView":1,
19 | "componentType":5126,
20 | "count":3186,
21 | "type":"VEC3",
22 | "min":[-1.11296403,-0.187385768,-0.927352428
23 | ],
24 | "max":[1.0110724,0.499534905,1.91695178
25 | ]
26 | },
27 | {
28 | "bufferView":2,
29 | "componentType":5126,
30 | "count":3186,
31 | "type":"VEC3",
32 | "min":[-0.999184251,-0.999999642,-0.998448431
33 | ],
34 | "max":[0.998073518,0.998995602,0.991905391
35 | ]
36 | }
37 | ],
38 | "buffers":[
39 | {
40 | "uri":"dried_body_data.bin",
41 | "byteLength":82836,
42 | "name":"main_buffer"
43 | }
44 | ],
45 | "bufferViews":[
46 | {
47 | "buffer":0,
48 | "byteLength":6372,
49 | "target":34963
50 | },
51 | {
52 | "buffer":0,
53 | "byteOffset":6372,
54 | "byteLength":38232,
55 | "target":34962
56 | },
57 | {
58 | "buffer":0,
59 | "byteOffset":44604,
60 | "byteLength":38232,
61 | "target":34962
62 | }
63 | ],
64 | "nodes":[
65 | {
66 | "name":"geo1",
67 | "mesh":0
68 | }
69 | ],
70 | "meshes":[
71 | {
72 | "primitives":[
73 | {
74 | "attributes":{
75 | "NORMAL":2,
76 | "POSITION":1
77 | },
78 | "indices":0
79 | }
80 | ]
81 | }
82 | ],
83 | "scenes":[
84 | {
85 | "nodes":[0
86 | ]
87 | }
88 | ],
89 | "scene":0
90 | }
91 |
--------------------------------------------------------------------------------
/public/assets/dried_body/dried_body_data.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/dried_body/dried_body_data.bin
--------------------------------------------------------------------------------
/public/assets/dunes/dunes.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "asset":{
3 | "version":"2.0",
4 | "generator":"Houdini GLTF 2.0 Exporter"
5 | },
6 | "accessors":[
7 | {
8 | "bufferView":0,
9 | "componentType":5123,
10 | "count":24696,
11 | "type":"SCALAR",
12 | "min":[0
13 | ],
14 | "max":[24695
15 | ]
16 | },
17 | {
18 | "bufferView":1,
19 | "componentType":5126,
20 | "count":24696,
21 | "type":"VEC3",
22 | "min":[-500,-0.899999976,-500
23 | ],
24 | "max":[500,0.64126575,500
25 | ]
26 | },
27 | {
28 | "bufferView":2,
29 | "componentType":5126,
30 | "count":24696,
31 | "type":"VEC2",
32 | "min":[-1.87848782e-05,-4.30345535e-05
33 | ],
34 | "max":[1.00006068,1.00004077
35 | ]
36 | },
37 | {
38 | "bufferView":3,
39 | "componentType":5126,
40 | "count":24696,
41 | "type":"VEC3",
42 | "min":[1,1,1
43 | ],
44 | "max":[1,1,1
45 | ]
46 | },
47 | {
48 | "bufferView":4,
49 | "componentType":5126,
50 | "count":24696,
51 | "type":"SCALAR",
52 | "min":[-0.275079548
53 | ],
54 | "max":[0.725597441
55 | ]
56 | },
57 | {
58 | "bufferView":5,
59 | "componentType":5126,
60 | "count":24696,
61 | "type":"SCALAR",
62 | "min":[0
63 | ],
64 | "max":[0
65 | ]
66 | },
67 | {
68 | "bufferView":6,
69 | "componentType":5126,
70 | "count":24696,
71 | "type":"SCALAR",
72 | "min":[-0.0942563117
73 | ],
74 | "max":[1.01541042
75 | ]
76 | },
77 | {
78 | "bufferView":7,
79 | "componentType":5126,
80 | "count":24696,
81 | "type":"VEC3",
82 | "min":[-0.978493631,-0.999998391,-0.9935202
83 | ],
84 | "max":[0.968024015,1,0.981351495
85 | ]
86 | }
87 | ],
88 | "buffers":[
89 | {
90 | "uri":"dunes_data.bin",
91 | "byteLength":1432368,
92 | "name":"main_buffer"
93 | }
94 | ],
95 | "bufferViews":[
96 | {
97 | "buffer":0,
98 | "byteLength":49392,
99 | "target":34963
100 | },
101 | {
102 | "buffer":0,
103 | "byteOffset":49392,
104 | "byteLength":296352,
105 | "target":34962
106 | },
107 | {
108 | "buffer":0,
109 | "byteOffset":345744,
110 | "byteLength":197568,
111 | "target":34962
112 | },
113 | {
114 | "buffer":0,
115 | "byteOffset":543312,
116 | "byteLength":296352,
117 | "target":34962
118 | },
119 | {
120 | "buffer":0,
121 | "byteOffset":839664,
122 | "byteLength":98784,
123 | "target":34962
124 | },
125 | {
126 | "buffer":0,
127 | "byteOffset":938448,
128 | "byteLength":98784,
129 | "target":34962
130 | },
131 | {
132 | "buffer":0,
133 | "byteOffset":1037232,
134 | "byteLength":98784,
135 | "target":34962
136 | },
137 | {
138 | "buffer":0,
139 | "byteOffset":1136016,
140 | "byteLength":296352,
141 | "target":34962
142 | }
143 | ],
144 | "nodes":[
145 | {
146 | "name":"ground1",
147 | "mesh":0
148 | }
149 | ],
150 | "meshes":[
151 | {
152 | "primitives":[
153 | {
154 | "attributes":{
155 | "NORMAL":7,
156 | "_retention":6,
157 | "_mask":5,
158 | "COLOR_0":3,
159 | "_height":4,
160 | "TEXCOORD_0":2,
161 | "POSITION":1
162 | },
163 | "indices":0,
164 | "material":0
165 | }
166 | ]
167 | }
168 | ],
169 | "materials":[
170 | {
171 | "name":"principledshader",
172 | "pbrMetallicRoughness":{
173 | "baseColorFactor":[0.152999997,0.0478023514,0.00823761523,1
174 | ],
175 | "metallicFactor":0,
176 | "roughnessFactor":0.56400001
177 | }
178 | }
179 | ],
180 | "scenes":[
181 | {
182 | "nodes":[0
183 | ]
184 | }
185 | ],
186 | "scene":0
187 | }
188 |
--------------------------------------------------------------------------------
/public/assets/dunes/dunes_data.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/dunes/dunes_data.bin
--------------------------------------------------------------------------------
/public/assets/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/favicon.png
--------------------------------------------------------------------------------
/public/assets/fire/fire_col.exr:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/fire/fire_col.exr
--------------------------------------------------------------------------------
/public/assets/fire/fire_minmax.json:
--------------------------------------------------------------------------------
1 | {
2 | "bbox_max": "460.051025391",
3 | "bbox_min": "-238.770248413",
4 | "method": 2,
5 | "numframes": "128"
6 | }
--------------------------------------------------------------------------------
/public/assets/fire/fire_pos.exr:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/fire/fire_pos.exr
--------------------------------------------------------------------------------
/public/assets/info.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/info.png
--------------------------------------------------------------------------------
/public/assets/mask/mask.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "asset":{
3 | "version":"2.0",
4 | "generator":"Houdini GLTF 2.0 Exporter"
5 | },
6 | "accessors":[
7 | {
8 | "bufferView":0,
9 | "componentType":5121,
10 | "count":66,
11 | "type":"SCALAR",
12 | "min":[0
13 | ],
14 | "max":[65
15 | ]
16 | },
17 | {
18 | "bufferView":1,
19 | "componentType":5126,
20 | "count":66,
21 | "type":"VEC3",
22 | "min":[-0.0777116045,2.28727722,0.147622257
23 | ],
24 | "max":[0.0751317441,2.30562258,0.176552892
25 | ]
26 | },
27 | {
28 | "bufferView":2,
29 | "componentType":5126,
30 | "count":66,
31 | "type":"VEC2",
32 | "min":[0.353801161,0.311060429
33 | ],
34 | "max":[0.87564373,0.933723211
35 | ]
36 | },
37 | {
38 | "bufferView":3,
39 | "componentType":5126,
40 | "count":66,
41 | "type":"VEC3",
42 | "min":[-0.580672622,-0.028489856,0.81212002
43 | ],
44 | "max":[0.483523577,0.0694093555,0.993618488
45 | ]
46 | },
47 | {
48 | "bufferView":4,
49 | "componentType":5123,
50 | "count":6000,
51 | "type":"SCALAR",
52 | "min":[0
53 | ],
54 | "max":[5999
55 | ]
56 | },
57 | {
58 | "bufferView":5,
59 | "componentType":5126,
60 | "count":6000,
61 | "type":"VEC3",
62 | "min":[-0.106135875,2.05905271,0.0980021656
63 | ],
64 | "max":[0.115694694,2.49132752,0.201860026
65 | ]
66 | },
67 | {
68 | "bufferView":6,
69 | "componentType":5126,
70 | "count":6000,
71 | "type":"VEC2",
72 | "min":[0.000974655326,0.0161061287
73 | ],
74 | "max":[0.997191668,0.999025345
75 | ]
76 | },
77 | {
78 | "bufferView":7,
79 | "componentType":5126,
80 | "count":6000,
81 | "type":"VEC3",
82 | "min":[-0.986681581,-1,-1
83 | ],
84 | "max":[0.998884618,1,0.999934256
85 | ]
86 | }
87 | ],
88 | "buffers":[
89 | {
90 | "uri":"mask_data.bin",
91 | "byteLength":206180,
92 | "name":"main_buffer"
93 | }
94 | ],
95 | "bufferViews":[
96 | {
97 | "buffer":0,
98 | "byteLength":66,
99 | "target":34963
100 | },
101 | {
102 | "buffer":0,
103 | "byteOffset":68,
104 | "byteLength":792,
105 | "target":34962
106 | },
107 | {
108 | "buffer":0,
109 | "byteOffset":860,
110 | "byteLength":528,
111 | "target":34962
112 | },
113 | {
114 | "buffer":0,
115 | "byteOffset":1388,
116 | "byteLength":792,
117 | "target":34962
118 | },
119 | {
120 | "buffer":0,
121 | "byteOffset":2180,
122 | "byteLength":12000,
123 | "target":34963
124 | },
125 | {
126 | "buffer":0,
127 | "byteOffset":14180,
128 | "byteLength":72000,
129 | "target":34962
130 | },
131 | {
132 | "buffer":0,
133 | "byteOffset":86180,
134 | "byteLength":48000,
135 | "target":34962
136 | },
137 | {
138 | "buffer":0,
139 | "byteOffset":134180,
140 | "byteLength":72000,
141 | "target":34962
142 | }
143 | ],
144 | "nodes":[
145 | {
146 | "children":[1,2
147 | ],
148 | "name":"Root"
149 | },
150 | {
151 | "name":"eyes",
152 | "mesh":0
153 | },
154 | {
155 | "name":"body",
156 | "mesh":1
157 | }
158 | ],
159 | "meshes":[
160 | {
161 | "primitives":[
162 | {
163 | "attributes":{
164 | "NORMAL":3,
165 | "TEXCOORD_0":2,
166 | "POSITION":1
167 | },
168 | "indices":0,
169 | "material":0
170 | }
171 | ]
172 | },
173 | {
174 | "primitives":[
175 | {
176 | "attributes":{
177 | "NORMAL":7,
178 | "TEXCOORD_0":6,
179 | "POSITION":5
180 | },
181 | "indices":4,
182 | "material":0
183 | }
184 | ]
185 | }
186 | ],
187 | "materials":[
188 | {
189 | "name":"MaskMat",
190 | "pbrMetallicRoughness":{
191 | "metallicFactor":0,
192 | "roughnessFactor":0.65200001,
193 | "baseColorTexture":{
194 | "index":0
195 | }
196 | }
197 | }
198 | ],
199 | "scenes":[
200 | {
201 | "nodes":[0
202 | ]
203 | }
204 | ],
205 | "textures":[
206 | {
207 | "source":0
208 | }
209 | ],
210 | "images":[
211 | {
212 | "uri":"mask_basecolor.png",
213 | "mimeType":"image/png"
214 | }
215 | ],
216 | "scene":0
217 | }
218 |
--------------------------------------------------------------------------------
/public/assets/mask/mask_basecolor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/mask/mask_basecolor.png
--------------------------------------------------------------------------------
/public/assets/mask/mask_data.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/mask/mask_data.bin
--------------------------------------------------------------------------------
/public/assets/moon_rock/moon_rock.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "asset":{
3 | "version":"2.0",
4 | "generator":"Houdini GLTF 2.0 Exporter"
5 | },
6 | "accessors":[
7 | {
8 | "bufferView":0,
9 | "componentType":5123,
10 | "count":2568,
11 | "type":"SCALAR",
12 | "min":[0
13 | ],
14 | "max":[2567
15 | ]
16 | },
17 | {
18 | "bufferView":1,
19 | "componentType":5126,
20 | "count":2568,
21 | "type":"VEC3",
22 | "min":[-54.1655273,0,-16.223877
23 | ],
24 | "max":[56.6383629,54.0221634,25.1934547
25 | ]
26 | },
27 | {
28 | "bufferView":2,
29 | "componentType":5126,
30 | "count":2568,
31 | "type":"VEC3",
32 | "min":[-0.998280764,-0.944678426,-0.99999404
33 | ],
34 | "max":[0.994417727,0.999697924,0.99999404
35 | ]
36 | },
37 | {
38 | "bufferView":3,
39 | "componentType":5126,
40 | "count":2568,
41 | "type":"VEC2",
42 | "min":[0.0139118135,0.0313016176
43 | ],
44 | "max":[0.982096791,0.972430587
45 | ]
46 | },
47 | {
48 | "bufferView":4,
49 | "componentType":5126,
50 | "count":2568,
51 | "type":"VEC4",
52 | "min":[-0.978616953,-0.999268889,-1,1
53 | ],
54 | "max":[1,0.995249152,1,1
55 | ]
56 | }
57 | ],
58 | "buffers":[
59 | {
60 | "uri":"moon_rock_data.bin",
61 | "byteLength":128400,
62 | "name":"main_buffer"
63 | }
64 | ],
65 | "bufferViews":[
66 | {
67 | "buffer":0,
68 | "byteLength":5136,
69 | "target":34963
70 | },
71 | {
72 | "buffer":0,
73 | "byteOffset":5136,
74 | "byteLength":30816,
75 | "target":34962
76 | },
77 | {
78 | "buffer":0,
79 | "byteOffset":35952,
80 | "byteLength":30816,
81 | "target":34962
82 | },
83 | {
84 | "buffer":0,
85 | "byteOffset":66768,
86 | "byteLength":20544,
87 | "target":34962
88 | },
89 | {
90 | "buffer":0,
91 | "byteOffset":87312,
92 | "byteLength":41088,
93 | "target":34962
94 | }
95 | ],
96 | "nodes":[
97 | {
98 | "name":"moon_rock",
99 | "mesh":0
100 | }
101 | ],
102 | "meshes":[
103 | {
104 | "primitives":[
105 | {
106 | "attributes":{
107 | "TANGENT":4,
108 | "TEXCOORD_0":3,
109 | "NORMAL":2,
110 | "POSITION":1
111 | },
112 | "indices":0
113 | }
114 | ]
115 | }
116 | ],
117 | "scenes":[
118 | {
119 | "nodes":[0
120 | ]
121 | }
122 | ],
123 | "scene":0
124 | }
125 |
--------------------------------------------------------------------------------
/public/assets/moon_rock/moon_rock_data.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/moon_rock/moon_rock_data.bin
--------------------------------------------------------------------------------
/public/assets/mountains/mountains.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "asset":{
3 | "version":"2.0",
4 | "generator":"Houdini GLTF 2.0 Exporter"
5 | },
6 | "accessors":[
7 | {
8 | "bufferView":0,
9 | "componentType":5123,
10 | "count":6021,
11 | "type":"SCALAR",
12 | "min":[0
13 | ],
14 | "max":[6020
15 | ]
16 | },
17 | {
18 | "bufferView":1,
19 | "componentType":5126,
20 | "count":6021,
21 | "type":"VEC2",
22 | "min":[0,0.00076675415
23 | ],
24 | "max":[0.999970257,1
25 | ]
26 | },
27 | {
28 | "bufferView":2,
29 | "componentType":5126,
30 | "count":6021,
31 | "type":"VEC3",
32 | "min":[-498.883545,-2.02634907,-499.676056
33 | ],
34 | "max":[499.108582,51.3202438,499.258392
35 | ]
36 | },
37 | {
38 | "bufferView":3,
39 | "componentType":5126,
40 | "count":6021,
41 | "type":"VEC3",
42 | "min":[1,1,1
43 | ],
44 | "max":[1,1,1
45 | ]
46 | }
47 | ],
48 | "buffers":[
49 | {
50 | "uri":"mountains_data.bin",
51 | "byteLength":204716
52 | }
53 | ],
54 | "bufferViews":[
55 | {
56 | "buffer":0,
57 | "byteLength":12042,
58 | "target":34963
59 | },
60 | {
61 | "buffer":0,
62 | "byteOffset":12044,
63 | "byteLength":48168,
64 | "target":34962
65 | },
66 | {
67 | "buffer":0,
68 | "byteOffset":60212,
69 | "byteLength":72252,
70 | "target":34962
71 | },
72 | {
73 | "buffer":0,
74 | "byteOffset":132464,
75 | "byteLength":72252,
76 | "target":34962
77 | }
78 | ],
79 | "nodes":[
80 | {
81 | "mesh":0
82 | }
83 | ],
84 | "meshes":[
85 | {
86 | "primitives":[
87 | {
88 | "attributes":{
89 | "COLOR_0":3,
90 | "POSITION":2,
91 | "TEXCOORD_0":1
92 | },
93 | "indices":0
94 | }
95 | ]
96 | }
97 | ],
98 | "scenes":[
99 | {
100 | "nodes":[0
101 | ]
102 | }
103 | ],
104 | "scene":0
105 | }
106 |
--------------------------------------------------------------------------------
/public/assets/mountains/mountains_data.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/mountains/mountains_data.bin
--------------------------------------------------------------------------------
/public/assets/mountains/mountains_diff.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/mountains/mountains_diff.png
--------------------------------------------------------------------------------
/public/assets/pendulum/pendulum.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "asset":{
3 | "version":"2.0",
4 | "generator":"Houdini GLTF 2.0 Exporter"
5 | },
6 | "accessors":[
7 | {
8 | "bufferView":0,
9 | "componentType":5123,
10 | "count":612,
11 | "type":"SCALAR",
12 | "min":[0
13 | ],
14 | "max":[611
15 | ]
16 | },
17 | {
18 | "bufferView":1,
19 | "componentType":5126,
20 | "count":612,
21 | "type":"VEC3",
22 | "min":[-0.476314008,-0.593448222,-17.8166809
23 | ],
24 | "max":[0.476313978,18.1934757,-7.19410181
25 | ]
26 | },
27 | {
28 | "bufferView":2,
29 | "componentType":5126,
30 | "count":612,
31 | "type":"VEC3",
32 | "min":[1,0,0
33 | ],
34 | "max":[1,0,0
35 | ]
36 | },
37 | {
38 | "bufferView":3,
39 | "componentType":5126,
40 | "count":612,
41 | "type":"SCALAR",
42 | "min":[0.416666657
43 | ],
44 | "max":[1
45 | ]
46 | },
47 | {
48 | "bufferView":4,
49 | "componentType":5126,
50 | "count":612,
51 | "type":"VEC2",
52 | "min":[0,-1.85788393
53 | ],
54 | "max":[19.2293053,1
55 | ]
56 | },
57 | {
58 | "bufferView":5,
59 | "componentType":5126,
60 | "count":612,
61 | "type":"VEC3",
62 | "min":[-0.871984482,-0.711162508,-0.504324496
63 | ],
64 | "max":[0.871984482,0.365786791,1
65 | ]
66 | },
67 | {
68 | "bufferView":6,
69 | "componentType":5121,
70 | "count":48,
71 | "type":"SCALAR",
72 | "min":[0
73 | ],
74 | "max":[47
75 | ]
76 | },
77 | {
78 | "bufferView":7,
79 | "componentType":5126,
80 | "count":48,
81 | "type":"VEC3",
82 | "min":[-0.0500000007,1.96656656,-7.44854832
83 | ],
84 | "max":[0.0500000007,18.0665665,-7.34854794
85 | ]
86 | },
87 | {
88 | "bufferView":8,
89 | "componentType":5126,
90 | "count":48,
91 | "type":"VEC3",
92 | "min":[0,1,0
93 | ],
94 | "max":[0,1,0
95 | ]
96 | },
97 | {
98 | "bufferView":9,
99 | "componentType":5126,
100 | "count":48,
101 | "type":"SCALAR",
102 | "min":[1
103 | ],
104 | "max":[1
105 | ]
106 | },
107 | {
108 | "bufferView":10,
109 | "componentType":5126,
110 | "count":48,
111 | "type":"VEC2",
112 | "min":[0,0.693853259
113 | ],
114 | "max":[16.1000004,1
115 | ]
116 | },
117 | {
118 | "bufferView":11,
119 | "componentType":5126,
120 | "count":48,
121 | "type":"VEC3",
122 | "min":[-1,0,-1
123 | ],
124 | "max":[1,0,1
125 | ]
126 | },
127 | {
128 | "bufferView":12,
129 | "componentType":5121,
130 | "count":108,
131 | "type":"SCALAR",
132 | "min":[0
133 | ],
134 | "max":[19
135 | ]
136 | },
137 | {
138 | "bufferView":13,
139 | "componentType":5126,
140 | "count":20,
141 | "type":"VEC3",
142 | "min":[-1.20000005,0.876239538,-8.44050884
143 | ],
144 | "max":[1.20000005,3.27623963,-6.36204767
145 | ]
146 | }
147 | ],
148 | "buffers":[
149 | {
150 | "uri":"pendulum_data.bin",
151 | "byteLength":33300,
152 | "name":"main_buffer"
153 | }
154 | ],
155 | "bufferViews":[
156 | {
157 | "buffer":0,
158 | "byteLength":1224,
159 | "target":34963
160 | },
161 | {
162 | "buffer":0,
163 | "byteOffset":1224,
164 | "byteLength":7344,
165 | "target":34962
166 | },
167 | {
168 | "buffer":0,
169 | "byteOffset":8568,
170 | "byteLength":7344,
171 | "target":34962
172 | },
173 | {
174 | "buffer":0,
175 | "byteOffset":15912,
176 | "byteLength":2448,
177 | "target":34962
178 | },
179 | {
180 | "buffer":0,
181 | "byteOffset":18360,
182 | "byteLength":4896,
183 | "target":34962
184 | },
185 | {
186 | "buffer":0,
187 | "byteOffset":23256,
188 | "byteLength":7344,
189 | "target":34962
190 | },
191 | {
192 | "buffer":0,
193 | "byteOffset":30600,
194 | "byteLength":48,
195 | "target":34963
196 | },
197 | {
198 | "buffer":0,
199 | "byteOffset":30648,
200 | "byteLength":576,
201 | "target":34962
202 | },
203 | {
204 | "buffer":0,
205 | "byteOffset":31224,
206 | "byteLength":576,
207 | "target":34962
208 | },
209 | {
210 | "buffer":0,
211 | "byteOffset":31800,
212 | "byteLength":192,
213 | "target":34962
214 | },
215 | {
216 | "buffer":0,
217 | "byteOffset":31992,
218 | "byteLength":384,
219 | "target":34962
220 | },
221 | {
222 | "buffer":0,
223 | "byteOffset":32376,
224 | "byteLength":576,
225 | "target":34962
226 | },
227 | {
228 | "buffer":0,
229 | "byteOffset":32952,
230 | "byteLength":108,
231 | "target":34963
232 | },
233 | {
234 | "buffer":0,
235 | "byteOffset":33060,
236 | "byteLength":240,
237 | "target":34962
238 | }
239 | ],
240 | "nodes":[
241 | {
242 | "children":[1,2,3
243 | ],
244 | "name":"Root"
245 | },
246 | {
247 | "name":"stand",
248 | "mesh":0
249 | },
250 | {
251 | "name":"rope",
252 | "mesh":1
253 | },
254 | {
255 | "name":"ball",
256 | "mesh":2
257 | }
258 | ],
259 | "meshes":[
260 | {
261 | "primitives":[
262 | {
263 | "attributes":{
264 | "NORMAL":5,
265 | "TEXCOORD_0":4,
266 | "_up":2,
267 | "_pscale":3,
268 | "POSITION":1
269 | },
270 | "indices":0
271 | }
272 | ]
273 | },
274 | {
275 | "primitives":[
276 | {
277 | "attributes":{
278 | "NORMAL":11,
279 | "TEXCOORD_0":10,
280 | "_up":8,
281 | "_pscale":9,
282 | "POSITION":7
283 | },
284 | "indices":6
285 | }
286 | ]
287 | },
288 | {
289 | "primitives":[
290 | {
291 | "attributes":{
292 | "POSITION":13
293 | },
294 | "indices":12
295 | }
296 | ]
297 | }
298 | ],
299 | "scenes":[
300 | {
301 | "nodes":[0
302 | ]
303 | }
304 | ],
305 | "scene":0
306 | }
307 |
--------------------------------------------------------------------------------
/public/assets/pendulum/pendulum_data.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/pendulum/pendulum_data.bin
--------------------------------------------------------------------------------
/public/assets/pendulum_base/pendulum_base.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "asset":{
3 | "version":"2.0",
4 | "generator":"Houdini GLTF 2.0 Exporter"
5 | },
6 | "accessors":[
7 | {
8 | "bufferView":0,
9 | "componentType":5123,
10 | "count":648,
11 | "type":"SCALAR",
12 | "min":[0
13 | ],
14 | "max":[647
15 | ]
16 | },
17 | {
18 | "bufferView":1,
19 | "componentType":5126,
20 | "count":648,
21 | "type":"VEC3",
22 | "min":[-16.9431019,-0.660000026,-18.6599712
23 | ],
24 | "max":[16.9375591,0.0899999738,14.9689388
25 | ]
26 | },
27 | {
28 | "bufferView":2,
29 | "componentType":5126,
30 | "count":648,
31 | "type":"VEC3",
32 | "min":[-1,0,-0.998850107
33 | ],
34 | "max":[0.999936044,1,0.999991894
35 | ]
36 | }
37 | ],
38 | "buffers":[
39 | {
40 | "uri":"pendulum_base_data.bin",
41 | "byteLength":16848,
42 | "name":"main_buffer"
43 | }
44 | ],
45 | "bufferViews":[
46 | {
47 | "buffer":0,
48 | "byteLength":1296,
49 | "target":34963
50 | },
51 | {
52 | "buffer":0,
53 | "byteOffset":1296,
54 | "byteLength":7776,
55 | "target":34962
56 | },
57 | {
58 | "buffer":0,
59 | "byteOffset":9072,
60 | "byteLength":7776,
61 | "target":34962
62 | }
63 | ],
64 | "nodes":[
65 | {
66 | "children":[1
67 | ],
68 | "name":"Root"
69 | },
70 | {
71 | "name":"base",
72 | "mesh":0
73 | }
74 | ],
75 | "meshes":[
76 | {
77 | "primitives":[
78 | {
79 | "attributes":{
80 | "NORMAL":2,
81 | "POSITION":1
82 | },
83 | "indices":0
84 | }
85 | ]
86 | }
87 | ],
88 | "scenes":[
89 | {
90 | "nodes":[0
91 | ]
92 | }
93 | ],
94 | "scene":0
95 | }
96 |
--------------------------------------------------------------------------------
/public/assets/pendulum_base/pendulum_base_data.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/pendulum_base/pendulum_base_data.bin
--------------------------------------------------------------------------------
/public/assets/pyramid/pyramid.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "asset":{
3 | "version":"2.0",
4 | "generator":"Houdini GLTF 2.0 Exporter"
5 | },
6 | "accessors":[
7 | {
8 | "bufferView":0,
9 | "componentType":5123,
10 | "count":1332,
11 | "type":"SCALAR",
12 | "min":[0
13 | ],
14 | "max":[1331
15 | ]
16 | },
17 | {
18 | "bufferView":1,
19 | "componentType":5126,
20 | "count":1332,
21 | "type":"VEC3",
22 | "min":[-15.9083557,-0.000132443514,-15.905529
23 | ],
24 | "max":[15.9072971,22.1994743,15.9089441
25 | ]
26 | },
27 | {
28 | "bufferView":2,
29 | "componentType":5126,
30 | "count":1332,
31 | "type":"VEC2",
32 | "min":[0.00974657014,-8.65678215
33 | ],
34 | "max":[9.97804546,0.990253389
35 | ]
36 | },
37 | {
38 | "bufferView":3,
39 | "componentType":5126,
40 | "count":1332,
41 | "type":"VEC3",
42 | "min":[-1,-0.997663021,-1
43 | ],
44 | "max":[1,0.997038543,1
45 | ]
46 | }
47 | ],
48 | "buffers":[
49 | {
50 | "uri":"pyramid_data.bin",
51 | "byteLength":45288,
52 | "name":"main_buffer"
53 | }
54 | ],
55 | "bufferViews":[
56 | {
57 | "buffer":0,
58 | "byteLength":2664,
59 | "target":34963
60 | },
61 | {
62 | "buffer":0,
63 | "byteOffset":2664,
64 | "byteLength":15984,
65 | "target":34962
66 | },
67 | {
68 | "buffer":0,
69 | "byteOffset":18648,
70 | "byteLength":10656,
71 | "target":34962
72 | },
73 | {
74 | "buffer":0,
75 | "byteOffset":29304,
76 | "byteLength":15984,
77 | "target":34962
78 | }
79 | ],
80 | "nodes":[
81 | {
82 | "name":"piramid",
83 | "mesh":0
84 | }
85 | ],
86 | "meshes":[
87 | {
88 | "primitives":[
89 | {
90 | "attributes":{
91 | "NORMAL":3,
92 | "TEXCOORD_0":2,
93 | "POSITION":1
94 | },
95 | "indices":0
96 | }
97 | ]
98 | }
99 | ],
100 | "scenes":[
101 | {
102 | "nodes":[0
103 | ]
104 | }
105 | ],
106 | "scene":0
107 | }
108 |
--------------------------------------------------------------------------------
/public/assets/pyramid/pyramid_data.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/pyramid/pyramid_data.bin
--------------------------------------------------------------------------------
/public/assets/quest_controller_l/quest_controller_l.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "asset":{
3 | "version":"2.0",
4 | "generator":"Houdini GLTF 2.0 Exporter"
5 | },
6 | "accessors":[
7 | {
8 | "bufferView":0,
9 | "componentType":5121,
10 | "count":48,
11 | "type":"SCALAR",
12 | "min":[0
13 | ],
14 | "max":[47
15 | ]
16 | },
17 | {
18 | "bufferView":1,
19 | "componentType":5126,
20 | "count":48,
21 | "type":"VEC3",
22 | "min":[-0.00654221047,-0.00287701329,0.000634161057
23 | ],
24 | "max":[0.00332787097,0.00425733253,0.0107826553
25 | ]
26 | },
27 | {
28 | "bufferView":2,
29 | "componentType":5126,
30 | "count":48,
31 | "type":"VEC3",
32 | "min":[-0.995432019,-0.421608537,-0.986988604
33 | ],
34 | "max":[0.914619923,0.87443608,0.846950889
35 | ]
36 | },
37 | {
38 | "bufferView":3,
39 | "componentType":5121,
40 | "count":48,
41 | "type":"SCALAR",
42 | "min":[0
43 | ],
44 | "max":[47
45 | ]
46 | },
47 | {
48 | "bufferView":4,
49 | "componentType":5126,
50 | "count":48,
51 | "type":"VEC3",
52 | "min":[-0.0025230844,-0.0100649763,-0.0114104263
53 | ],
54 | "max":[0.00742041925,-0.00276026293,-0.00143229577
55 | ]
56 | },
57 | {
58 | "bufferView":5,
59 | "componentType":5126,
60 | "count":48,
61 | "type":"VEC3",
62 | "min":[-0.99713999,-0.437907308,-0.940290987
63 | ],
64 | "max":[0.906493187,0.956580341,0.798744321
65 | ]
66 | },
67 | {
68 | "bufferView":6,
69 | "componentType":5123,
70 | "count":2418,
71 | "type":"SCALAR",
72 | "min":[0
73 | ],
74 | "max":[2417
75 | ]
76 | },
77 | {
78 | "bufferView":7,
79 | "componentType":5126,
80 | "count":2418,
81 | "type":"VEC3",
82 | "min":[-0.0548305735,-0.036135938,-0.0282036792
83 | ],
84 | "max":[0.035830576,0.0685576499,0.0905904993
85 | ]
86 | },
87 | {
88 | "bufferView":8,
89 | "componentType":5126,
90 | "count":2418,
91 | "type":"VEC3",
92 | "min":[-0.999905109,-0.999906719,-0.998884499
93 | ],
94 | "max":[0.999976099,0.999981344,0.9848544
95 | ]
96 | },
97 | {
98 | "bufferView":9,
99 | "componentType":5121,
100 | "count":108,
101 | "type":"SCALAR",
102 | "min":[0
103 | ],
104 | "max":[107
105 | ]
106 | },
107 | {
108 | "bufferView":10,
109 | "componentType":5126,
110 | "count":108,
111 | "type":"VEC3",
112 | "min":[-0.00293962075,-0.0202691667,0.0259559471
113 | ],
114 | "max":[0.00992851891,0.00378288794,0.045896396
115 | ]
116 | },
117 | {
118 | "bufferView":11,
119 | "componentType":5126,
120 | "count":108,
121 | "type":"VEC3",
122 | "min":[-0.192015707,-0.995647907,-0.973826647
123 | ],
124 | "max":[0.993348539,0.959720314,0.942871392
125 | ]
126 | },
127 | {
128 | "bufferView":12,
129 | "componentType":5121,
130 | "count":30,
131 | "type":"SCALAR",
132 | "min":[0
133 | ],
134 | "max":[29
135 | ]
136 | },
137 | {
138 | "bufferView":13,
139 | "componentType":5126,
140 | "count":30,
141 | "type":"VEC3",
142 | "min":[-0.013914655,0.00673727551,0.0186645072
143 | ],
144 | "max":[-0.00536754541,0.0128973406,0.0254936088
145 | ]
146 | },
147 | {
148 | "bufferView":14,
149 | "componentType":5126,
150 | "count":30,
151 | "type":"VEC3",
152 | "min":[-0.997852981,-0.633020103,-0.754319966
153 | ],
154 | "max":[0.934634149,0.766091406,0.739575326
155 | ]
156 | },
157 | {
158 | "bufferView":15,
159 | "componentType":5123,
160 | "count":177,
161 | "type":"SCALAR",
162 | "min":[0
163 | ],
164 | "max":[176
165 | ]
166 | },
167 | {
168 | "bufferView":16,
169 | "componentType":5126,
170 | "count":177,
171 | "type":"VEC3",
172 | "min":[-0.0265227668,-0.0118251787,-0.0168912113
173 | ],
174 | "max":[-0.00952241477,0.00374192209,0.000873250421
175 | ]
176 | },
177 | {
178 | "bufferView":17,
179 | "componentType":5126,
180 | "count":177,
181 | "type":"VEC3",
182 | "min":[-0.974404991,-0.874780059,-0.995089352
183 | ],
184 | "max":[0.990759671,0.983626962,0.888638079
185 | ]
186 | },
187 | {
188 | "bufferView":18,
189 | "componentType":5123,
190 | "count":171,
191 | "type":"SCALAR",
192 | "min":[0
193 | ],
194 | "max":[170
195 | ]
196 | },
197 | {
198 | "bufferView":19,
199 | "componentType":5126,
200 | "count":171,
201 | "type":"VEC3",
202 | "min":[-0.0225639734,-0.0420421399,-0.0166532602
203 | ],
204 | "max":[0.00356398593,-0.0229955222,0.00985044613
205 | ]
206 | },
207 | {
208 | "bufferView":20,
209 | "componentType":5126,
210 | "count":171,
211 | "type":"VEC3",
212 | "min":[-0.999799967,-0.881769776,-0.939788997
213 | ],
214 | "max":[0.999799967,0.326179445,0.817227423
215 | ]
216 | }
217 | ],
218 | "buffers":[
219 | {
220 | "uri":"quest_controller_l_data.bin",
221 | "byteLength":77772,
222 | "name":"main_buffer"
223 | }
224 | ],
225 | "bufferViews":[
226 | {
227 | "buffer":0,
228 | "byteLength":48,
229 | "target":34963
230 | },
231 | {
232 | "buffer":0,
233 | "byteOffset":48,
234 | "byteLength":576,
235 | "target":34962
236 | },
237 | {
238 | "buffer":0,
239 | "byteOffset":624,
240 | "byteLength":576,
241 | "target":34962
242 | },
243 | {
244 | "buffer":0,
245 | "byteOffset":1200,
246 | "byteLength":48,
247 | "target":34963
248 | },
249 | {
250 | "buffer":0,
251 | "byteOffset":1248,
252 | "byteLength":576,
253 | "target":34962
254 | },
255 | {
256 | "buffer":0,
257 | "byteOffset":1824,
258 | "byteLength":576,
259 | "target":34962
260 | },
261 | {
262 | "buffer":0,
263 | "byteOffset":2400,
264 | "byteLength":4836,
265 | "target":34963
266 | },
267 | {
268 | "buffer":0,
269 | "byteOffset":7236,
270 | "byteLength":29016,
271 | "target":34962
272 | },
273 | {
274 | "buffer":0,
275 | "byteOffset":36252,
276 | "byteLength":29016,
277 | "target":34962
278 | },
279 | {
280 | "buffer":0,
281 | "byteOffset":65268,
282 | "byteLength":108,
283 | "target":34963
284 | },
285 | {
286 | "buffer":0,
287 | "byteOffset":65376,
288 | "byteLength":1296,
289 | "target":34962
290 | },
291 | {
292 | "buffer":0,
293 | "byteOffset":66672,
294 | "byteLength":1296,
295 | "target":34962
296 | },
297 | {
298 | "buffer":0,
299 | "byteOffset":67968,
300 | "byteLength":30,
301 | "target":34963
302 | },
303 | {
304 | "buffer":0,
305 | "byteOffset":68000,
306 | "byteLength":360,
307 | "target":34962
308 | },
309 | {
310 | "buffer":0,
311 | "byteOffset":68360,
312 | "byteLength":360,
313 | "target":34962
314 | },
315 | {
316 | "buffer":0,
317 | "byteOffset":68720,
318 | "byteLength":354,
319 | "target":34963
320 | },
321 | {
322 | "buffer":0,
323 | "byteOffset":69076,
324 | "byteLength":2124,
325 | "target":34962
326 | },
327 | {
328 | "buffer":0,
329 | "byteOffset":71200,
330 | "byteLength":2124,
331 | "target":34962
332 | },
333 | {
334 | "buffer":0,
335 | "byteOffset":73324,
336 | "byteLength":342,
337 | "target":34963
338 | },
339 | {
340 | "buffer":0,
341 | "byteOffset":73668,
342 | "byteLength":2052,
343 | "target":34962
344 | },
345 | {
346 | "buffer":0,
347 | "byteOffset":75720,
348 | "byteLength":2052,
349 | "target":34962
350 | }
351 | ],
352 | "nodes":[
353 | {
354 | "children":[1,2,3,4,5,6,7
355 | ],
356 | "name":"quest_controller_L"
357 | },
358 | {
359 | "name":"x_button",
360 | "mesh":0
361 | },
362 | {
363 | "name":"y_button",
364 | "mesh":1
365 | },
366 | {
367 | "name":"body",
368 | "mesh":2
369 | },
370 | {
371 | "name":"grip_button",
372 | "mesh":3
373 | },
374 | {
375 | "name":"menu_button",
376 | "mesh":4
377 | },
378 | {
379 | "name":"thumbstick",
380 | "mesh":5
381 | },
382 | {
383 | "name":"trigger",
384 | "mesh":6
385 | }
386 | ],
387 | "meshes":[
388 | {
389 | "primitives":[
390 | {
391 | "attributes":{
392 | "NORMAL":2,
393 | "POSITION":1
394 | },
395 | "indices":0
396 | }
397 | ]
398 | },
399 | {
400 | "primitives":[
401 | {
402 | "attributes":{
403 | "NORMAL":5,
404 | "POSITION":4
405 | },
406 | "indices":3
407 | }
408 | ]
409 | },
410 | {
411 | "primitives":[
412 | {
413 | "attributes":{
414 | "NORMAL":8,
415 | "POSITION":7
416 | },
417 | "indices":6
418 | }
419 | ]
420 | },
421 | {
422 | "primitives":[
423 | {
424 | "attributes":{
425 | "NORMAL":11,
426 | "POSITION":10
427 | },
428 | "indices":9
429 | }
430 | ]
431 | },
432 | {
433 | "primitives":[
434 | {
435 | "attributes":{
436 | "NORMAL":14,
437 | "POSITION":13
438 | },
439 | "indices":12
440 | }
441 | ]
442 | },
443 | {
444 | "primitives":[
445 | {
446 | "attributes":{
447 | "NORMAL":17,
448 | "POSITION":16
449 | },
450 | "indices":15
451 | }
452 | ]
453 | },
454 | {
455 | "primitives":[
456 | {
457 | "attributes":{
458 | "NORMAL":20,
459 | "POSITION":19
460 | },
461 | "indices":18
462 | }
463 | ]
464 | }
465 | ],
466 | "scenes":[
467 | {
468 | "nodes":[0
469 | ]
470 | }
471 | ],
472 | "scene":0
473 | }
474 |
--------------------------------------------------------------------------------
/public/assets/quest_controller_l/quest_controller_l_data.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/quest_controller_l/quest_controller_l_data.bin
--------------------------------------------------------------------------------
/public/assets/quest_controller_r/quest_controller_r.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "asset":{
3 | "version":"2.0",
4 | "generator":"Houdini GLTF 2.0 Exporter"
5 | },
6 | "accessors":[
7 | {
8 | "bufferView":0,
9 | "componentType":5121,
10 | "count":48,
11 | "type":"SCALAR",
12 | "min":[0
13 | ],
14 | "max":[47
15 | ]
16 | },
17 | {
18 | "bufferView":1,
19 | "componentType":5126,
20 | "count":48,
21 | "type":"VEC3",
22 | "min":[-0.00332787097,-0.00287701329,0.000634161057
23 | ],
24 | "max":[0.00654221047,0.00425733253,0.0107826553
25 | ]
26 | },
27 | {
28 | "bufferView":2,
29 | "componentType":5126,
30 | "count":48,
31 | "type":"VEC3",
32 | "min":[-0.914619923,-0.421608537,-0.986988604
33 | ],
34 | "max":[0.995432019,0.87443608,0.846950889
35 | ]
36 | },
37 | {
38 | "bufferView":3,
39 | "componentType":5121,
40 | "count":48,
41 | "type":"SCALAR",
42 | "min":[0
43 | ],
44 | "max":[47
45 | ]
46 | },
47 | {
48 | "bufferView":4,
49 | "componentType":5126,
50 | "count":48,
51 | "type":"VEC3",
52 | "min":[-0.00742041925,-0.0100649763,-0.0114104263
53 | ],
54 | "max":[0.0025230844,-0.00276026293,-0.00143229577
55 | ]
56 | },
57 | {
58 | "bufferView":5,
59 | "componentType":5126,
60 | "count":48,
61 | "type":"VEC3",
62 | "min":[-0.906493187,-0.437907308,-0.940290987
63 | ],
64 | "max":[0.99713999,0.956580341,0.798744321
65 | ]
66 | },
67 | {
68 | "bufferView":6,
69 | "componentType":5123,
70 | "count":2418,
71 | "type":"SCALAR",
72 | "min":[0
73 | ],
74 | "max":[2417
75 | ]
76 | },
77 | {
78 | "bufferView":7,
79 | "componentType":5126,
80 | "count":2418,
81 | "type":"VEC3",
82 | "min":[-0.035830576,-0.036135938,-0.0282036792
83 | ],
84 | "max":[0.0548305735,0.0685576499,0.0905904993
85 | ]
86 | },
87 | {
88 | "bufferView":8,
89 | "componentType":5126,
90 | "count":2418,
91 | "type":"VEC3",
92 | "min":[-0.999976099,-0.999906719,-0.998884499
93 | ],
94 | "max":[0.999905109,0.999981344,0.9848544
95 | ]
96 | },
97 | {
98 | "bufferView":9,
99 | "componentType":5121,
100 | "count":108,
101 | "type":"SCALAR",
102 | "min":[0
103 | ],
104 | "max":[107
105 | ]
106 | },
107 | {
108 | "bufferView":10,
109 | "componentType":5126,
110 | "count":108,
111 | "type":"VEC3",
112 | "min":[-0.00992851891,-0.0202691667,0.0259559471
113 | ],
114 | "max":[0.00293962075,0.00378288794,0.045896396
115 | ]
116 | },
117 | {
118 | "bufferView":11,
119 | "componentType":5126,
120 | "count":108,
121 | "type":"VEC3",
122 | "min":[-0.993348539,-0.995647907,-0.973826647
123 | ],
124 | "max":[0.192015707,0.959720314,0.942871392
125 | ]
126 | },
127 | {
128 | "bufferView":12,
129 | "componentType":5121,
130 | "count":30,
131 | "type":"SCALAR",
132 | "min":[0
133 | ],
134 | "max":[29
135 | ]
136 | },
137 | {
138 | "bufferView":13,
139 | "componentType":5126,
140 | "count":30,
141 | "type":"VEC3",
142 | "min":[0.00536754541,0.00673727551,0.0186645072
143 | ],
144 | "max":[0.013914655,0.0128973406,0.0254936088
145 | ]
146 | },
147 | {
148 | "bufferView":14,
149 | "componentType":5126,
150 | "count":30,
151 | "type":"VEC3",
152 | "min":[-0.934634149,-0.633020103,-0.754319966
153 | ],
154 | "max":[0.997852981,0.766091406,0.739575326
155 | ]
156 | },
157 | {
158 | "bufferView":15,
159 | "componentType":5123,
160 | "count":177,
161 | "type":"SCALAR",
162 | "min":[0
163 | ],
164 | "max":[176
165 | ]
166 | },
167 | {
168 | "bufferView":16,
169 | "componentType":5126,
170 | "count":177,
171 | "type":"VEC3",
172 | "min":[0.00952241477,-0.0118251787,-0.0168912113
173 | ],
174 | "max":[0.0265227668,0.00374192209,0.000873250421
175 | ]
176 | },
177 | {
178 | "bufferView":17,
179 | "componentType":5126,
180 | "count":177,
181 | "type":"VEC3",
182 | "min":[-0.990759671,-0.874780059,-0.995089352
183 | ],
184 | "max":[0.974404991,0.983626962,0.888638079
185 | ]
186 | },
187 | {
188 | "bufferView":18,
189 | "componentType":5123,
190 | "count":171,
191 | "type":"SCALAR",
192 | "min":[0
193 | ],
194 | "max":[170
195 | ]
196 | },
197 | {
198 | "bufferView":19,
199 | "componentType":5126,
200 | "count":171,
201 | "type":"VEC3",
202 | "min":[-0.00356398593,-0.0420421399,-0.0166532602
203 | ],
204 | "max":[0.0225639734,-0.0229955222,0.00985044613
205 | ]
206 | },
207 | {
208 | "bufferView":20,
209 | "componentType":5126,
210 | "count":171,
211 | "type":"VEC3",
212 | "min":[-0.999799967,-0.881769776,-0.939788997
213 | ],
214 | "max":[0.999799967,0.326179445,0.817227423
215 | ]
216 | }
217 | ],
218 | "buffers":[
219 | {
220 | "uri":"quest_controller_r_data.bin",
221 | "byteLength":77772,
222 | "name":"main_buffer"
223 | }
224 | ],
225 | "bufferViews":[
226 | {
227 | "buffer":0,
228 | "byteLength":48,
229 | "target":34963
230 | },
231 | {
232 | "buffer":0,
233 | "byteOffset":48,
234 | "byteLength":576,
235 | "target":34962
236 | },
237 | {
238 | "buffer":0,
239 | "byteOffset":624,
240 | "byteLength":576,
241 | "target":34962
242 | },
243 | {
244 | "buffer":0,
245 | "byteOffset":1200,
246 | "byteLength":48,
247 | "target":34963
248 | },
249 | {
250 | "buffer":0,
251 | "byteOffset":1248,
252 | "byteLength":576,
253 | "target":34962
254 | },
255 | {
256 | "buffer":0,
257 | "byteOffset":1824,
258 | "byteLength":576,
259 | "target":34962
260 | },
261 | {
262 | "buffer":0,
263 | "byteOffset":2400,
264 | "byteLength":4836,
265 | "target":34963
266 | },
267 | {
268 | "buffer":0,
269 | "byteOffset":7236,
270 | "byteLength":29016,
271 | "target":34962
272 | },
273 | {
274 | "buffer":0,
275 | "byteOffset":36252,
276 | "byteLength":29016,
277 | "target":34962
278 | },
279 | {
280 | "buffer":0,
281 | "byteOffset":65268,
282 | "byteLength":108,
283 | "target":34963
284 | },
285 | {
286 | "buffer":0,
287 | "byteOffset":65376,
288 | "byteLength":1296,
289 | "target":34962
290 | },
291 | {
292 | "buffer":0,
293 | "byteOffset":66672,
294 | "byteLength":1296,
295 | "target":34962
296 | },
297 | {
298 | "buffer":0,
299 | "byteOffset":67968,
300 | "byteLength":30,
301 | "target":34963
302 | },
303 | {
304 | "buffer":0,
305 | "byteOffset":68000,
306 | "byteLength":360,
307 | "target":34962
308 | },
309 | {
310 | "buffer":0,
311 | "byteOffset":68360,
312 | "byteLength":360,
313 | "target":34962
314 | },
315 | {
316 | "buffer":0,
317 | "byteOffset":68720,
318 | "byteLength":354,
319 | "target":34963
320 | },
321 | {
322 | "buffer":0,
323 | "byteOffset":69076,
324 | "byteLength":2124,
325 | "target":34962
326 | },
327 | {
328 | "buffer":0,
329 | "byteOffset":71200,
330 | "byteLength":2124,
331 | "target":34962
332 | },
333 | {
334 | "buffer":0,
335 | "byteOffset":73324,
336 | "byteLength":342,
337 | "target":34963
338 | },
339 | {
340 | "buffer":0,
341 | "byteOffset":73668,
342 | "byteLength":2052,
343 | "target":34962
344 | },
345 | {
346 | "buffer":0,
347 | "byteOffset":75720,
348 | "byteLength":2052,
349 | "target":34962
350 | }
351 | ],
352 | "nodes":[
353 | {
354 | "children":[1,2,3,4,5,6,7
355 | ],
356 | "name":"quest_controller_R"
357 | },
358 | {
359 | "name":"a_button",
360 | "mesh":0
361 | },
362 | {
363 | "name":"b_button",
364 | "mesh":1
365 | },
366 | {
367 | "name":"body",
368 | "mesh":2
369 | },
370 | {
371 | "name":"grip_button",
372 | "mesh":3
373 | },
374 | {
375 | "name":"menu_button",
376 | "mesh":4
377 | },
378 | {
379 | "name":"thumbstick",
380 | "mesh":5
381 | },
382 | {
383 | "name":"trigger",
384 | "mesh":6
385 | }
386 | ],
387 | "meshes":[
388 | {
389 | "primitives":[
390 | {
391 | "attributes":{
392 | "NORMAL":2,
393 | "POSITION":1
394 | },
395 | "indices":0
396 | }
397 | ]
398 | },
399 | {
400 | "primitives":[
401 | {
402 | "attributes":{
403 | "NORMAL":5,
404 | "POSITION":4
405 | },
406 | "indices":3
407 | }
408 | ]
409 | },
410 | {
411 | "primitives":[
412 | {
413 | "attributes":{
414 | "NORMAL":8,
415 | "POSITION":7
416 | },
417 | "indices":6
418 | }
419 | ]
420 | },
421 | {
422 | "primitives":[
423 | {
424 | "attributes":{
425 | "NORMAL":11,
426 | "POSITION":10
427 | },
428 | "indices":9
429 | }
430 | ]
431 | },
432 | {
433 | "primitives":[
434 | {
435 | "attributes":{
436 | "NORMAL":14,
437 | "POSITION":13
438 | },
439 | "indices":12
440 | }
441 | ]
442 | },
443 | {
444 | "primitives":[
445 | {
446 | "attributes":{
447 | "NORMAL":17,
448 | "POSITION":16
449 | },
450 | "indices":15
451 | }
452 | ]
453 | },
454 | {
455 | "primitives":[
456 | {
457 | "attributes":{
458 | "NORMAL":20,
459 | "POSITION":19
460 | },
461 | "indices":18
462 | }
463 | ]
464 | }
465 | ],
466 | "scenes":[
467 | {
468 | "nodes":[0
469 | ]
470 | }
471 | ],
472 | "scene":0
473 | }
474 |
--------------------------------------------------------------------------------
/public/assets/quest_controller_r/quest_controller_r_data.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/quest_controller_r/quest_controller_r_data.bin
--------------------------------------------------------------------------------
/public/assets/ruins/pillar_texture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/ruins/pillar_texture.png
--------------------------------------------------------------------------------
/public/assets/ruins/ruins.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "asset":{
3 | "version":"2.0",
4 | "generator":"Houdini GLTF 2.0 Exporter"
5 | },
6 | "accessors":[
7 | {
8 | "bufferView":0,
9 | "componentType":5123,
10 | "count":6756,
11 | "type":"SCALAR",
12 | "min":[0
13 | ],
14 | "max":[6755
15 | ]
16 | },
17 | {
18 | "bufferView":1,
19 | "componentType":5126,
20 | "count":6756,
21 | "type":"VEC3",
22 | "min":[-2.32521033,-0.0851265416,-2.11756158
23 | ],
24 | "max":[4.73573494,1.32957149,4.43106556
25 | ]
26 | },
27 | {
28 | "bufferView":2,
29 | "componentType":5126,
30 | "count":6756,
31 | "type":"VEC2",
32 | "min":[0.00460512983,0.000924170017
33 | ],
34 | "max":[0.997475863,1.00460517
35 | ]
36 | }
37 | ],
38 | "buffers":[
39 | {
40 | "uri":"ruins_data.bin",
41 | "byteLength":148632,
42 | "name":"main_buffer"
43 | }
44 | ],
45 | "bufferViews":[
46 | {
47 | "buffer":0,
48 | "byteLength":13512,
49 | "target":34963
50 | },
51 | {
52 | "buffer":0,
53 | "byteOffset":13512,
54 | "byteLength":81072,
55 | "target":34962
56 | },
57 | {
58 | "buffer":0,
59 | "byteOffset":94584,
60 | "byteLength":54048,
61 | "target":34962
62 | }
63 | ],
64 | "nodes":[
65 | {
66 | "name":"pillar",
67 | "mesh":0
68 | }
69 | ],
70 | "meshes":[
71 | {
72 | "primitives":[
73 | {
74 | "attributes":{
75 | "TEXCOORD_0":2,
76 | "POSITION":1
77 | },
78 | "indices":0,
79 | "material":0
80 | }
81 | ]
82 | }
83 | ],
84 | "materials":[
85 | {
86 | "name":"ruinMat",
87 | "pbrMetallicRoughness":{
88 | "metallicFactor":0,
89 | "roughnessFactor":0.65200001,
90 | "baseColorTexture":{
91 | "index":0
92 | }
93 | }
94 | }
95 | ],
96 | "scenes":[
97 | {
98 | "nodes":[0
99 | ]
100 | }
101 | ],
102 | "textures":[
103 | {
104 | "source":0
105 | }
106 | ],
107 | "images":[
108 | {
109 | "uri":"pillar_texture.png",
110 | "mimeType":"image/png"
111 | }
112 | ],
113 | "scene":0
114 | }
115 |
--------------------------------------------------------------------------------
/public/assets/ruins/ruins_data.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/ruins/ruins_data.bin
--------------------------------------------------------------------------------
/public/assets/speech/comment1.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/speech/comment1.mp3
--------------------------------------------------------------------------------
/public/assets/speech/comment2.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/speech/comment2.mp3
--------------------------------------------------------------------------------
/public/assets/speech/followMe.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/speech/followMe.mp3
--------------------------------------------------------------------------------
/public/assets/speech/speech1.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/speech/speech1.mp3
--------------------------------------------------------------------------------
/public/assets/speech/speech2.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/speech/speech2.mp3
--------------------------------------------------------------------------------
/public/assets/speech/speech3.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/speech/speech3.mp3
--------------------------------------------------------------------------------
/public/assets/speech/speech4.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/speech/speech4.mp3
--------------------------------------------------------------------------------
/public/assets/speech/speech5.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/speech/speech5.mp3
--------------------------------------------------------------------------------
/public/assets/speech/speech6.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/speech/speech6.mp3
--------------------------------------------------------------------------------
/public/assets/speech/speech7.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/speech/speech7.mp3
--------------------------------------------------------------------------------
/public/assets/speech/speechWin.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/speech/speechWin.mp3
--------------------------------------------------------------------------------
/public/assets/star.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/star.png
--------------------------------------------------------------------------------
/public/assets/tex_Fern_Lush_Noise.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kif11/three-body/37396e371e6fb04c699881352291710346d281c1/public/assets/tex_Fern_Lush_Noise.jpg
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Three Body
4 |
5 |
6 |
7 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/Fire.js:
--------------------------------------------------------------------------------
1 | import AFRAME from 'aframe';
2 | import JSX from './JSX';
3 |
4 | const Fire = (id, position, rotation, scale, offset, fps) => (
5 |
50 | )
51 |
52 | export default Fire;
53 |
--------------------------------------------------------------------------------
/src/JSX.js:
--------------------------------------------------------------------------------
1 | const JSX = {
2 | /**
3 | * Convert JSX tags into JS createElement
4 | */
5 | createElement: (tag, attrs, ...children) => {
6 | let element = document.createElement(tag);
7 |
8 | for (let name in attrs) {
9 | if (name && attrs.hasOwnProperty(name)) {
10 | let value = attrs[name];
11 | if (value === true) {
12 | element.setAttribute(name, "");
13 | } else if (value !== false && value != null) {
14 | element.setAttribute(name, value.toString());
15 | }
16 | }
17 | }
18 |
19 | for (let i = 0; i < children.length; i++) {
20 | let child = children[i];
21 | element.appendChild(
22 | child.nodeType == null ?
23 | document.createTextNode(child.toString()) : child);
24 | }
25 |
26 | return element;
27 | }
28 | };
29 |
30 | export default JSX;
31 |
--------------------------------------------------------------------------------
/src/Utils.js:
--------------------------------------------------------------------------------
1 | async function getHeadsetType() {
2 | const displays = await navigator.getVRDisplays();
3 | for (let i = 0; i < displays.length; i += 1) {
4 | const d = displays[i];
5 | if (d.displayName === "Oculus Quest") {
6 | return "Oculus Quest";
7 | } else if (d.displayName === "Oculus Go") {
8 | return "Oculus Go";
9 | }
10 | }
11 | return null
12 | }
13 |
14 | export { getHeadsetType };
15 |
--------------------------------------------------------------------------------
/src/components/AmbientController.js:
--------------------------------------------------------------------------------
1 | AFRAME.registerComponent('ambient-controller', {
2 | init: function() {
3 | this.easingIn = {};
4 | this.easingOut = {};
5 | this.targetVolume = 0.5;
6 |
7 | this.el.sceneEl.addEventListener('begin-game', () => {
8 | this.el.components.sound__1.playSound();
9 | this.el.components.sound__2.playSound();
10 | this.el.components.sound__3.playSound();
11 | this.el.components.sound__1.pool.children[0].setVolume(this.targetVolume);
12 | });
13 |
14 | this.el.sceneEl.addEventListener('speech4-ended', () => {
15 | this.easingIn['2'] = this.el.components.sound__2.pool.children[0];
16 | });
17 |
18 | this.el.sceneEl.addEventListener('speech6-ended', () => {
19 | window.setTimeout(() => {
20 | this.easingIn['3'] = this.el.components.sound__3.pool.children[0];
21 | }, 2000);
22 | });
23 |
24 | this.el.sceneEl.addEventListener('win', () => {
25 | this.easingOut['2'] = this.el.components.sound__2.pool.children[0];
26 | this.easingOut['3'] = this.el.components.sound__3.pool.children[0];
27 | });
28 | },
29 |
30 | tick: function(time, timeDelta) {
31 | for(var key in this.easingIn) {
32 | var value = this.easingIn[key];
33 | var curVolume = value.getVolume();
34 | curVolume += 0.0000625*timeDelta;
35 | if (curVolume > this.targetVolume){
36 | delete this.easingIn[key];
37 | } else {
38 | value.setVolume(curVolume);
39 | }
40 | }
41 | for(var key in this.easingOut) {
42 | var value = this.easingOut[key];
43 | var curVolume = value.getVolume();
44 | curVolume -= 0.0000625*timeDelta;
45 | if(curVolume <= 0){
46 | delete this.easingOut[key];
47 | } else {
48 | value.setVolume(curVolume);
49 | }
50 | }
51 | }
52 | })
53 |
--------------------------------------------------------------------------------
/src/components/CharacterMover.js:
--------------------------------------------------------------------------------
1 | import AFRAME from 'aframe';
2 | const THREE = AFRAME.THREE;
3 | import { setQuaternionFromDirection } from '../libs/Utils';
4 |
5 | import SunCalibratedMaterial from '../shaders/SunCalibratedMaterial';
6 | import CharacterStateMachine from '../components/CharacterStateMachine';
7 |
8 | //CONSTANTS
9 | const CHARACTER_HEIGHT = -1;
10 | const DEHYDRATED_BODY_POS = new THREE.Vector3(5.8, CHARACTER_HEIGHT, 15.8);
11 | const PYRAMID_ENTRANCE_POS = new THREE.Vector3(32.25, CHARACTER_HEIGHT, 54.42);
12 | const PENDULUM_POS = new THREE.Vector3(34, CHARACTER_HEIGHT, -19);
13 |
14 | const UP = new THREE.Vector3(0,1,0);
15 |
16 | AFRAME.registerComponent('character-mover', {
17 | schema: {
18 | },
19 |
20 | init: function () {
21 | const system = document.querySelector('a-scene').systems['sunSystem'];
22 | this.cameraEl = document.querySelector('#camera');
23 |
24 | this.targetPos = new THREE.Vector3(0, 1, -40);
25 | this.characterPos = new THREE.Vector3(0, CHARACTER_HEIGHT, -40);
26 | this.el.setAttribute('position', this.characterPos);
27 | this.targetQuat = new THREE.Quaternion();
28 | this.lookAtDir = new THREE.Vector3();
29 |
30 | this.walkingSpeed = 0.00208;
31 | this.reachedCharacter = true;
32 |
33 | this.stateMachine = new CharacterStateMachine();
34 |
35 | // EVENT CHAIN
36 | this.el.sceneEl.addEventListener('fade-in-complete', (event) => {
37 | this.reachedCharacter = false;
38 | });
39 | this.el.sceneEl.addEventListener('speech1-ended', (event) => {
40 | window.setTimeout(() => {
41 | this.el.sceneEl.emit('speech2');
42 | }, 4000);
43 | });
44 | this.el.sceneEl.addEventListener('speech2-ended', (event) => {
45 | this.targetPos.copy(DEHYDRATED_BODY_POS);
46 | this.reachedCharacter = false;
47 | window.setTimeout(() => {
48 | this.el.sceneEl.emit('comment1');
49 | }, 4000);
50 | });
51 | this.el.sceneEl.addEventListener('comment1-ended', (event) => {
52 | this.commentOver = true;
53 | });
54 | this.el.sceneEl.addEventListener('speech3-ended', (event) => {
55 | this.targetPos.copy(PENDULUM_POS);
56 | this.reachedCharacter = false;
57 | });
58 | this.el.sceneEl.addEventListener('speech4-ended', (event) => {
59 | //START THE PACING CYCLE
60 | this.walkingSpeed = 0.000125;
61 | this.targetPos.copy(PENDULUM_POS);
62 | this.targetPos.x += 4*(Math.random()-0.5);
63 | this.reachedCharacter = false;
64 | window.setTimeout(() => {
65 | //TELLS USER TO RUN
66 | this.stateMachine.state = -1;
67 | this.el.sceneEl.emit('speech6');
68 | }, 69000);
69 | window.setTimeout(() => {
70 | //LOOK AT THE SKY
71 | this.stateMachine.state = 4;
72 | this.targetPos.set(this.characterPos.x ,CHARACTER_HEIGHT, PENDULUM_POS.z - 3);
73 | }, 67000);
74 | window.setTimeout(() => {
75 | const psystem = document.querySelector('a-scene').systems['pendulum'];
76 | const synch = psystem.getSynchStatus();
77 | if(synch) {
78 | this.el.sceneEl.emit('speech5');
79 | } else {
80 | this.el.sceneEl.emit('speech7');
81 | }
82 | //speech 5
83 | }, 40000);
84 | });
85 |
86 | this.el.sceneEl.addEventListener('speech6-ended', (event) => {
87 | this.walkingSpeed = 0.003515;
88 | window.setTimeout(() => {
89 | this.stateMachine.state = 5;
90 | this.targetPos.copy(PYRAMID_ENTRANCE_POS);
91 | this.reachedCharacter = false;
92 | }, 3000);
93 | window.setTimeout(() => {
94 | this.el.sceneEl.emit('comment2');
95 | this.commentOver = false;
96 | document.querySelectorAll('.fire').forEach(el => el.emit('start-char-fire'))
97 | }, 6000);
98 | });
99 | this.el.sceneEl.addEventListener('speechWin-ended', (event) => {
100 | window.setTimeout(() => {
101 | this.el.sceneEl.emit('gameWin');
102 | }, 30000);
103 | });
104 | this.el.sceneEl.addEventListener('comment2-ended', (event) => {
105 | this.commentOver = true;
106 | });
107 | this.el.sceneEl.addEventListener('win', (event) => {
108 | window.setTimeout(() => {
109 | this.el.sceneEl.emit('speechWin');
110 | }, 3000);
111 | window.setTimeout(() => {
112 | document.querySelectorAll('.fire').forEach(el => el.emit('stop-char-fire'))
113 | }, 7000);
114 | });
115 | },
116 |
117 | updateTargetPos: function (timeDelta) {
118 | this.characterPos.y = CHARACTER_HEIGHT;
119 |
120 | if(!this.reachedCharacter){
121 | this.stateMachine.getTargetPos(this.targetPos);
122 | this.lookAtDir.subVectors(this.targetPos, this.characterPos);
123 | //always face facePos
124 | setQuaternionFromDirection(this.lookAtDir.clone().normalize(), UP, this.targetQuat);
125 | var dist = this.lookAtDir.length();
126 | if(dist < 1) {
127 | this.reachedCharacter = true;
128 | this.stateMachine.updateState(this);
129 | return;
130 | }
131 | this.lookAtDir.multiplyScalar(this.walkingSpeed*timeDelta/dist);
132 | this.characterPos.add(this.lookAtDir)
133 | this.el.object3D.quaternion.slerp(this.targetQuat, 0.00625*timeDelta);
134 | } else {
135 | //rotate to face user, when not facing a target
136 | var camWorldPos = new THREE.Vector3();
137 | camWorldPos.setFromMatrixPosition(this.cameraEl.object3D.matrixWorld);
138 | camWorldPos.y = CHARACTER_HEIGHT;
139 | this.lookAtDir.subVectors(camWorldPos, this.characterPos);
140 |
141 | setQuaternionFromDirection(this.lookAtDir.normalize(), UP, this.targetQuat);
142 | this.el.object3D.quaternion.slerp(this.targetQuat, 0.00625*timeDelta);
143 | }
144 |
145 | },
146 |
147 | tick: function (time, timeDelta) {
148 | this.updateTargetPos(timeDelta);
149 |
150 | // move character up and down
151 | var idx = 10*Math.sin(time/3000);
152 | this.characterPos.y = CHARACTER_HEIGHT + 1 + 0.1*Math.sin(idx)/idx;
153 | this.el.setAttribute('position', this.characterPos);
154 | }
155 | });
156 |
--------------------------------------------------------------------------------
/src/components/CharacterStateMachine.js:
--------------------------------------------------------------------------------
1 | const THREE = AFRAME.THREE;
2 | /** SEQUENCER BASED ON EVENTS
3 | REACH USER
4 | BEGIN SPEECH 1 (greeting)
5 | BEGIN SPEECH 2 (history) AND TRIGGER FOLLOW
6 | REACH DEHYDRATED BODY
7 | BEGIN SPEECH 3 (dehydration) AND TRIGGER FOLLOW
8 | REACH SUN DIAL
9 | BEGIN SPEECH 4 (prediction)
10 | BEGIN SPEECH 5 (find shade)
11 | REACH SHELTER, OR BURN
12 | **/
13 |
14 | //CONSTANTS
15 | const CHARACTER_HEIGHT = -1;
16 | const PENDULUM_POS = new THREE.Vector3(34, CHARACTER_HEIGHT, -19);
17 | const WIN_POS = new THREE.Vector3(60.74943, CHARACTER_HEIGHT, 52.90357);
18 |
19 | export default class CharacterStateMachine {
20 | constructor(){
21 | this.state = 0;
22 | this.camera = document.querySelector('#camera');
23 | this.tmps = {
24 | v1: new THREE.Vector3(),
25 | v2: new THREE.Vector3(),
26 | }
27 | }
28 | getTargetPos(targetPos) {
29 | switch(this.state){
30 | case 0:
31 | //REACH USER
32 | var worldPos = this.tmps.v1.setFromMatrixPosition(this.camera.object3D.matrixWorld);
33 | var forward = this.tmps.v2.set(0,0,1).transformDirection(this.camera.object3D.matrixWorld)
34 | worldPos.sub(forward.normalize().multiplyScalar(1.5));
35 | targetPos.set(worldPos.x,-1,worldPos.z);
36 | break;
37 | case 1:
38 | break;
39 | case 3:
40 | break;
41 | }
42 | }
43 | updateState(ref) {
44 | switch(this.state){
45 | case 0:
46 | ref.el.sceneEl.emit('speech1');
47 | this.state += 1;
48 | break;
49 |
50 | case 1:
51 | //if comment 1 is over then start speech3
52 | if(ref.commentOver){
53 | window.setTimeout(() => {
54 | ref.el.sceneEl.emit('speech3');
55 | }, 5000);
56 | window.setTimeout(() => {
57 | ref.el.sceneEl.emit('start-sun-animation');
58 | }, 10);
59 | this.state += 1;
60 | } else {
61 | //try again
62 | ref.reachedCharacter = false;
63 | }
64 | break;
65 |
66 | case 2:
67 | window.setTimeout(() => {
68 | ref.el.sceneEl.emit('speech4');
69 | }, 5000);
70 | this.state += 1;
71 | break;
72 |
73 | case 3:
74 | //keep generating new targets, never update state
75 | ref.targetPos.copy(PENDULUM_POS);
76 | ref.targetPos.x += 4*(Math.random()-0.5);
77 | ref.reachedCharacter = false;
78 | break;
79 |
80 | case 4:
81 | break;
82 |
83 | case 5:
84 | ref.targetPos.set(60.74943, CHARACTER_HEIGHT, 52.90357);
85 | ref.reachedCharacter = false;
86 | this.state += 1;
87 | break;
88 |
89 | case 6:
90 | ref.targetPos.set(55.74943, CHARACTER_HEIGHT, 53.1357);
91 | ref.reachedCharacter = false;
92 | this.state += 1;
93 | break;
94 | case 7:
95 | //should be inside...
96 | if(ref.commentOver){
97 | ref.reachedCharacter = false;
98 | var camWorldPos = this.tmps.v1.setFromMatrixPosition(this.camera.object3D.matrixWorld);
99 | camWorldPos.setFromMatrixPosition(this.camera.object3D.matrixWorld);
100 | var distanceToShade = camWorldPos.distanceTo(WIN_POS);
101 | if(distanceToShade < 10){
102 | ref.el.sceneEl.emit('win');
103 | ref.reachedCharacter = true;
104 | }
105 | } else {
106 | ref.reachedCharacter = false;
107 | }
108 | break;
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/src/components/Collider.js:
--------------------------------------------------------------------------------
1 | import AFRAME from 'aframe';
2 | const THREE = AFRAME.THREE;
3 |
4 | AFRAME.registerComponent('collider', {
5 | schema: {
6 | camera: {
7 | type: 'boolean',
8 | default: 'false'
9 | }
10 | },
11 |
12 | init: function () {
13 | this.raycaster = new THREE.Raycaster();
14 | if(this.data.camera){
15 | this.raycastingEl = document.querySelector('#camera');
16 | } else {
17 | this.raycastingEl = this.el;
18 | }
19 |
20 | },
21 |
22 | collide: function(forward) {
23 | var dir = (forward)? -1 : 1;
24 | //global collider entities ............
25 | this.colliders = this.el.sceneEl.object3D.colliders;
26 | var worldPos = new THREE.Vector3();
27 | worldPos.setFromMatrixPosition(this.raycastingEl.object3D.matrixWorld);
28 | var forward = new THREE.Vector3(0,0,dir).transformDirection(this.raycastingEl.object3D.matrixWorld);
29 |
30 | this.raycaster.set(worldPos, forward.normalize());
31 | var closestPoint = this.raycaster.intersectObjects( this.colliders, true )[0];
32 | if(closestPoint){
33 | //do not move camera!
34 | if(closestPoint.distance < 1){
35 | return true;
36 | }
37 | }
38 | return false;
39 | },
40 | });
41 |
--------------------------------------------------------------------------------
/src/components/CustomControl.js:
--------------------------------------------------------------------------------
1 |
2 | import AFRAME from 'aframe';
3 | import { fresnelMaterial } from './FresnelMaterial';
4 | import { getHeadsetType } from '../Utils.js'
5 |
6 | AFRAME.registerComponent('custom-control', {
7 | schema: {
8 | hand: { default: '' },
9 | modelL: { default: 'assets/quest_controller_l/quest_controller_l.gltf' },
10 | modelR: { default: 'assets/quest_controller_r/quest_controller_r.gltf' }
11 | },
12 |
13 | update: async function () {
14 | const headsetType = await getHeadsetType();
15 |
16 | var hand = this.data.hand;
17 | var controlConfiguration = {
18 | hand: hand,
19 | model: headsetType !== 'Oculus Quest',
20 | };
21 |
22 | // Build on top of controller components.
23 | this.el.setAttribute('oculus-go-controls', controlConfiguration);
24 | this.el.setAttribute('vive-controls', controlConfiguration);
25 | this.el.setAttribute('oculus-touch-controls', controlConfiguration);
26 | this.el.setAttribute('daydream-controls', controlConfiguration);
27 | this.el.setAttribute('gearvr-controls', controlConfiguration);
28 | this.el.setAttribute('windows-motion-controls', controlConfiguration);
29 |
30 | // Add controller when entering VR
31 | if (headsetType === 'Oculus Quest') {
32 | this.el.sceneEl.addEventListener('enter-vr', (ent) => {
33 | this.el.setAttribute('visible', true);
34 |
35 | // Set a model.
36 | if (hand === 'left') {
37 | this.el.setAttribute('gltf-model', this.data.modelL);
38 | } else {
39 | this.el.setAttribute('gltf-model', this.data.modelR);
40 | }
41 |
42 | const activeMaterial = new THREE.MeshBasicMaterial({
43 | color: new THREE.Color("#289683"),
44 | });
45 |
46 | const buttons = {
47 | 'thumbstick': {
48 | down: 'thumbsticktouchstart',
49 | up: 'thumbsticktouchend',
50 | },
51 | 'a_button': {
52 | down: 'abuttondown',
53 | up: 'abuttonup',
54 | },
55 | 'b_button': {
56 | down: 'bbuttondown',
57 | up: 'bbuttonup',
58 | },
59 | 'x_button': {
60 | down: 'xbuttondown',
61 | up: 'xbuttonup',
62 | },
63 | 'y_button': {
64 | down: 'ybuttondown',
65 | up: 'ybuttonup',
66 | },
67 | 'grip_button': {
68 | down: 'gripdown',
69 | up: 'gripup',
70 | },
71 | 'trigger': {
72 | down: 'triggerdown',
73 | up: 'triggerup',
74 | },
75 | }
76 |
77 | this.el.addEventListener('model-loaded', (event) => {
78 | const scene = event.detail.model.children[0].children;
79 |
80 | for (let i = 0; i < scene.length; i += 1) {
81 | const child = scene[i];
82 | child.material = fresnelMaterial;
83 |
84 | // Register events for changing buttons material when pressed
85 | if (child.name in buttons) {
86 | const btn = buttons[child.name]
87 | this.el.addEventListener(btn.down, () => {
88 | child.material = activeMaterial;
89 | })
90 | this.el.addEventListener(btn.up, () => {
91 | child.material = fresnelMaterial;
92 | })
93 | }
94 | }
95 | });
96 | });
97 |
98 | // Remove controllers
99 | this.el.sceneEl.addEventListener('exit-vr', (ent) => {
100 | this.el.setAttribute('visible', false);
101 | });
102 | }
103 |
104 | }
105 | });
--------------------------------------------------------------------------------
/src/components/DefaultMaterial.js:
--------------------------------------------------------------------------------
1 | import AFRAME from 'aframe';
2 | import SunCalibratedMaterial from '../shaders/SunCalibratedMaterial';
3 | const THREE = AFRAME.THREE;
4 |
5 | AFRAME.registerComponent('default-material', {
6 | schema: {
7 | color: {
8 | type: 'color'
9 | },
10 | depthWrite: {
11 | type: 'boolean',
12 | default: 'true'
13 | }
14 | },
15 | init: function () {
16 | const mesh = this.el.object3D.children[0];
17 | mesh.material = new THREE.SunCalibratedMaterial();
18 | mesh.material.color = new THREE.Color(this.data.color);
19 | },
20 |
21 | tick: function (time, timeDelta) {
22 | }
23 | });
24 |
--------------------------------------------------------------------------------
/src/components/FireManager.js:
--------------------------------------------------------------------------------
1 | import AFRAME from 'aframe';
2 | const THREE = AFRAME.THREE;
3 |
4 | AFRAME.registerComponent('fire-manager', {
5 | init: function () {
6 | this.el.addEventListener('vertex-cache-loaded', (evt) => {
7 | this.model = this.el.object3D.children[0];
8 | this.model.visible = false;
9 | });
10 |
11 | this.el.sceneEl.addEventListener('start-char-fire', (evt) => {
12 | this.el.emit('start-vertex-animation'); // vertex cache texture waits for this event to start the animation
13 | this.animateScale = true;
14 | this.model.visible = true;
15 | });
16 |
17 | this.el.sceneEl.addEventListener('stop-char-fire', (evt) => {
18 | this.el.emit('stop-vertex-animation');
19 | this.animateScale = true;
20 | this.model.visible = false;
21 | });
22 |
23 | this.animateScale = false;
24 | this.scaleIncrement = new THREE.Vector3(0.00002, 0.00002, 0.00002); //per second
25 | this.scaleMax = 0.02;
26 | },
27 |
28 | tick: function (time, timeDelta) {
29 | if (this.animateScale) {
30 | let scale = this.el.getAttribute('scale');
31 |
32 | scale.add(this.scaleIncrement.clone().multiplyScalar(time / 10000));
33 | if (scale.x > this.scaleMax){
34 | this.animateScale = false;
35 | }
36 | this.el.setAttribute('scale', scale);
37 | }
38 | }
39 | });
40 |
--------------------------------------------------------------------------------
/src/components/FresnelMaterial.js:
--------------------------------------------------------------------------------
1 |
2 | import FresnelFrag from '../shaders/FresnelFrag.glsl'
3 | import FresnelVert from '../shaders/FresnelVert.glsl'
4 |
5 | export const fresnelMaterial = new THREE.ShaderMaterial({
6 | uniforms: {
7 | mRefractionRatio: { value: 1.02 },
8 | mFresnelBias: { value: 0.1 },
9 | mFresnelPower: { value: 2.0 },
10 | mFresnelScale: { value: 1.0 }
11 | },
12 | vertexShader: FresnelVert,
13 | fragmentShader: FresnelFrag,
14 | });
15 |
--------------------------------------------------------------------------------
/src/components/GlowMaterial.js:
--------------------------------------------------------------------------------
1 | import AFRAME from 'aframe';
2 | import GlowFrag from '../shaders/GlowFrag.glsl';
3 | import GlowVert from '../shaders/GlowVert.glsl';
4 |
5 | AFRAME.registerComponent('glow-material', {
6 | init: function () {
7 | const noiseTexture = new THREE.TextureLoader().load('/assets/tex_Fern_Lush_Noise.jpg');
8 | this.glowMaterial = new THREE.ShaderMaterial({
9 | uniforms: {
10 | noise: {
11 | value: noiseTexture
12 | },
13 | time: {
14 | value: 0
15 | }
16 | },
17 | vertexShader: GlowVert,
18 | fragmentShader: GlowFrag,
19 | });
20 |
21 | const mesh = this.el.object3D.children[0];
22 | mesh.material = this.glowMaterial;
23 | },
24 |
25 | tick: function (time, timeDelta) {
26 | this.glowMaterial.uniforms.time.value = time;
27 | }
28 | });
29 |
--------------------------------------------------------------------------------
/src/components/Intro.js:
--------------------------------------------------------------------------------
1 | import IntroFrag from '../shaders/IntroFrag.glsl';
2 | import IntroVert from '../shaders/IntroVert.glsl';
3 |
4 | import AFRAME from 'aframe';
5 | const THREE = AFRAME.THREE;
6 |
7 | AFRAME.registerComponent('intro', {
8 | init: function () {
9 | const planeMat = new THREE.ShaderMaterial({
10 | uniforms: {
11 | time: { value: 0 },
12 | color1: { value: new THREE.Color("#000319") },
13 | },
14 | vertexShader: IntroVert, //lol
15 | fragmentShader: IntroFrag,
16 | });
17 |
18 | const planeGeo = new THREE.PlaneGeometry(20,20);
19 | const introPlane = new THREE.Mesh(planeGeo, planeMat);
20 | this.el.object3D.add(introPlane)
21 | this.introPlane = introPlane;
22 | },
23 |
24 | tick: function (time, timeDelta) {
25 | this.introPlane.material.uniforms.time.value = time;
26 | }
27 | });
28 |
--------------------------------------------------------------------------------
/src/components/Mover.js:
--------------------------------------------------------------------------------
1 | import AFRAME from 'aframe';
2 | const THREE = AFRAME.THREE;
3 |
4 | const PENDULUM_POS = new THREE.Vector3(34, -1, -19);
5 |
6 | AFRAME.registerComponent('mover', {
7 | schema: {
8 | speed: {
9 | type: 'int',
10 | default: 65
11 | }
12 | },
13 |
14 | init: function () {
15 | this.pressed = false;
16 | this.pressedQuest = false;
17 | this.lastAxis = new THREE.Vector2();
18 | this.vrMovingSpeed = 0.0039;
19 |
20 | const rig = document.querySelector('#cameraRig');
21 | this.rig = rig.object3D;
22 |
23 | const camera = document.querySelector('#camera');
24 | this.collider = this.el.components.collider;
25 |
26 | this.wasd = camera.getAttribute('wasd-controls');
27 | this.camera = camera.object3D;
28 |
29 | this.wasd.acceleration = this.data.speed;
30 | this.forward = true;
31 |
32 | const system = document.querySelector('a-scene').systems['sunSystem'];
33 | system.registerMainCharacter(this.camera);
34 |
35 | this.raycasterSystem = document.querySelector('a-scene').systems['raycasterSystem'];
36 |
37 | this.el.addEventListener('trackpaddown', () => {
38 | this.pressed = true;
39 | });
40 | this.el.addEventListener('trackpadup', () => {
41 | this.pressed = false;
42 | });
43 |
44 | this.el.addEventListener('axismove', (evt) => {
45 | this.lastAxis.x = evt.detail.axis[0];
46 | this.lastAxis.y = evt.detail.axis[1];
47 | });
48 |
49 | window.addEventListener('keydown', (evt) => {
50 | if(evt.key == 'w'){
51 | this.forward = true;
52 | }
53 | if(evt.key == 's'){
54 | this.forward = false;
55 | }
56 | });
57 |
58 | /*
59 | Oculus touch controller events
60 | */
61 | this.el.addEventListener('thumbsticktouchstart', (evt) => {
62 | this.pressedQuest = true;
63 | })
64 | this.el.addEventListener('thumbsticktouchend', (evt) => {
65 | this.pressedQuest = false;
66 | })
67 | },
68 |
69 | tick: function (time, timeDelta) {
70 | if(this.pressed){
71 | const tweenForward = new THREE.Vector3(0, 0, 1).applyQuaternion(this.camera.quaternion);
72 | this.handleMove(tweenForward, timeDelta);
73 | } else if (this.pressedQuest){
74 | const tweenForward = new THREE.Vector3(-this.lastAxis.x, 0, -this.lastAxis.y).applyQuaternion(this.camera.quaternion);
75 | this.handleMove(tweenForward, timeDelta);
76 | } else {
77 | //handle web
78 | const collided = this.collider.collide(this.forward);
79 | this.wasd.enabled = !collided;
80 | }
81 | },
82 |
83 | handleMove: function (move, timeDelta){
84 | move.y = 0;
85 | const collided = this.collider.collide(true);
86 | if (!collided) {
87 | this.rig.position.sub(move.multiplyScalar(this.vrMovingSpeed * timeDelta))
88 | }
89 | const dist = this.rig.position.distanceTo(PENDULUM_POS);
90 | if (dist < 20) {
91 | debugger;
92 | // enable laser
93 | this.raycasterSystem.laserPlane.visible = true;
94 | } else {
95 | // disable laser
96 | this.raycasterSystem.laserPlane.visible = false;
97 | }
98 | }
99 | });
100 |
--------------------------------------------------------------------------------
/src/components/Pendulum.js:
--------------------------------------------------------------------------------
1 | import PendulumMaterial from '../shaders/PendulumMaterial';
2 | import SunCalibratedMaterial from '../shaders/SunCalibratedMaterial';
3 |
4 | import PendulumFrag from '../shaders/PendulumFrag.glsl';
5 | import PendulumVert from '../shaders/PendulumVert.glsl';
6 |
7 | import AFRAME from 'aframe';
8 | const THREE = AFRAME.THREE;
9 |
10 | AFRAME.registerComponent('pendulum', {
11 | schema: {
12 | height: {
13 | type: 'int',
14 | default: 16.1
15 | },
16 | radius: {
17 | type: 'int',
18 | default: 1
19 | },
20 | color: {
21 | type: 'color',
22 | default: null
23 | },
24 | },
25 |
26 | init: function () {
27 | const system = document.querySelector('a-scene').systems['sunSystem'];
28 | this.material = new SunCalibratedMaterial(system, new THREE.Color(this.data.color));
29 |
30 | const camera = document.querySelector('#camera');
31 | this.lookControls = camera.getAttribute('look-controls');
32 |
33 | this.el.addEventListener('model-loaded', () => {
34 | const scene = this.el.getObject3D('mesh');
35 | this.ball = scene.children[0].children[2]
36 | this.el.object3D.add(this.ball);
37 |
38 | this.ball.material = new PendulumMaterial(system, new THREE.Color(this.data.color));
39 | this.ball.geometry.computeVertexNormals();
40 |
41 | this.rope = scene.children[0].children[1];
42 | this.rope.material = this.material;
43 | this.rope.geometry.applyMatrix( new THREE.Matrix4().makeTranslation( 0, -18.1, 0 ) );
44 | this.rope.position.y = 18.1;
45 |
46 | this.stand = scene.children[0].children[0];
47 | this.stand.material = this.material;
48 | });
49 |
50 | this.ball = new THREE.Object3D()
51 | this.ball.material = {};
52 |
53 | this.root = new THREE.Vector3(0,this.data.height,0);
54 | this.offsetRoot = new THREE.Vector3(0, this.data.height, -7.4);
55 |
56 | this.axis = new THREE.Vector3(0, -1, 0);
57 | this.rotAxis = new THREE.Vector3(0, 0, -1);
58 | this.quat = new THREE.Quaternion();
59 | this.length = this.data.height - this.data.radius/2;
60 |
61 | var planeGeo = new THREE.PlaneGeometry( this.data.height,this.data.height );
62 | const planeMat = new THREE.MeshBasicMaterial({
63 | color: new THREE.Color("#ff00ff"),
64 | wireframe: true,
65 | side: THREE.DoubleSide,
66 | alphaTest: 0,
67 | visible: false
68 | })
69 | this.plane = new THREE.Mesh(planeGeo, planeMat);
70 | this.plane.position.z = -7.4;
71 | this.el.object3D.add(this.plane);
72 |
73 | this.force = 2;
74 | this.curTime = 0;
75 | this.startingAngle = 0;
76 | this.curAngle = 0;
77 |
78 | this.raycasterSystem = document.querySelector('a-scene').systems['raycasterSystem'];
79 |
80 | this.el.sceneEl.addEventListener( 'raycast-active-onset', (event) => {
81 | var t = this.raycasterSystem.intersectObject(this.ball);
82 | if(t[0]){
83 | this.lookControls.enabled = false;
84 | this.raycasting = true;
85 | }
86 | }, false );
87 |
88 | this.el.sceneEl.addEventListener( 'raycast-active', (event) => {
89 | var t = this.raycasterSystem.intersectObject(this.ball);
90 | var m = this.raycasterSystem.intersectObject(this.plane);
91 |
92 | if(m[0]&&t[0]){
93 | this.el.object3D.worldToLocal(m[0].point);
94 | m[0].point.sub(this.offsetRoot).normalize().multiplyScalar(this.length).add(this.offsetRoot);
95 | this.startingAngle = m[0].point.clone().sub(this.offsetRoot).angleTo(this.axis);
96 | this.force = 1;
97 | if(m[0].point.x > 0){
98 | this.startingAngle *= -1;
99 | }
100 | this.curTime = 0;
101 | m[0].point.z = 0;
102 | this.ball.position.copy(m[0].point);
103 | if(this.rope){
104 | this.quat.setFromAxisAngle(this.rotAxis, this.startingAngle);
105 | this.rope.quaternion.copy(this.quat);
106 | }
107 | }
108 | }, false );
109 |
110 | this.el.sceneEl.addEventListener( 'raycast-finished', (event) => {
111 | this.raycasting = false;
112 | this.lookControls.enabled = true;
113 | }, false );
114 |
115 | this.system.registerPendulum(this);
116 | },
117 | brighten: function (coef) {
118 | if(!this.ball.material.shader) return;
119 | this.ball.material.shader.uniforms.glow.value = coef;
120 | },
121 | tick: function (time, timeDelta) {
122 |
123 | if(this.raycasting) return;
124 | if(!this.ball) return;
125 |
126 | // this.force *= 0.998;
127 | this.dampeningFactor = this.startingAngle * this.force;
128 | this.curAngle = this.dampeningFactor*Math.cos(this.curTime);
129 | this.quat.setFromAxisAngle(this.rotAxis, this.curAngle);
130 |
131 | if(this.rope){
132 | this.rope.quaternion.copy(this.quat);
133 | }
134 | var newAxis = this.axis.clone().applyQuaternion(this.quat).multiplyScalar(this.length);
135 | var newPos = this.root.clone().add(newAxis);
136 | if(this.startingAngle < 0 ) {
137 | this.curTime -= 0.0015*timeDelta;
138 | } else {
139 | this.curTime += 0.0015*timeDelta;
140 | }
141 | this.ball.position.copy(newPos);
142 | }
143 | });
144 |
--------------------------------------------------------------------------------
/src/components/RingOfFire.js:
--------------------------------------------------------------------------------
1 | import FireRingFrag from '../shaders/FireRingFrag.glsl';
2 | import FireRingVert from '../shaders/FireRingVert.glsl';
3 |
4 | import AFRAME from 'aframe';
5 | const THREE = AFRAME.THREE;
6 |
7 | AFRAME.registerComponent('ring-of-fire', {
8 | schema: {
9 | },
10 |
11 | init: function () {
12 | //add ring of fire cylinder
13 | var fireRingMat = new THREE.ShaderMaterial({
14 | uniforms: {
15 | sunCentroid: {value: new THREE.Vector3(0,0,0)},
16 | fadeOutTime: {value: -1},
17 | fireRingColor2: {value: new THREE.Color("#f7f5e7")},
18 | fireRingColor1: {value: new THREE.Color("#ffcc00")},
19 | time: {value: 0},
20 | },
21 | side:THREE.DoubleSide,
22 | transparent: true,
23 | vertexShader: FireRingVert,
24 | fragmentShader: FireRingFrag,
25 | depthWrite: false,
26 | });
27 |
28 | var fireRingGeo = new THREE.CylinderGeometry( 100, 100, 30, 32, null, true );
29 | var fireRing = new THREE.Mesh(fireRingGeo, fireRingMat);
30 | fireRing.frustumCulled = false;
31 | fireRing.position.set(0,15,0);
32 | fireRing.scale.set(1,1,1);
33 | this.el.object3D.add(fireRing);
34 |
35 | //register to be synced with sun parameters
36 | const system = document.querySelector('a-scene').systems['sunSystem'];
37 | system.registerMaterial(fireRingMat);
38 | },
39 | tick: function (time, timeDelta) {
40 | }
41 | });
42 |
--------------------------------------------------------------------------------
/src/components/SetCharacterMaterial.js:
--------------------------------------------------------------------------------
1 | import AFRAME from 'aframe';
2 |
3 | import SunCalibratedMaterial from '../shaders/SunCalibratedMaterial';
4 | import EyeFrag from '../shaders/EyeFrag.glsl';
5 | import EyeVert from '../shaders/EyeVert.glsl';
6 |
7 | const THREE = AFRAME.THREE;
8 |
9 | AFRAME.registerComponent('set-character-material', {
10 | schema: {
11 | color: {
12 | type: 'color',
13 | default: null
14 | }
15 | },
16 | init: function () {
17 |
18 | const system = document.querySelector('a-scene').systems['sunSystem'];
19 |
20 | this.eyeMaterial = new THREE.ShaderMaterial({
21 | uniforms: {
22 | time: { value: 0 },
23 | },
24 | vertexShader: EyeVert,
25 | fragmentShader: EyeFrag,
26 | });
27 |
28 | this.material = new SunCalibratedMaterial(system);
29 | const { color } = this.data;
30 | this.el.addEventListener('model-loaded', () => {
31 | const scene = this.el.getObject3D('mesh');
32 | const eyeMesh = scene.getObjectByName('eyes');
33 | const bodyMesh = scene.getObjectByName('body');
34 | if (eyeMesh) {
35 | eyeMesh.material = this.eyeMaterial;
36 | }
37 | if (bodyMesh) {
38 | const { map: diffTexture } = bodyMesh.material;
39 |
40 | if (diffTexture) {
41 | this.material.map = diffTexture;
42 | }
43 | bodyMesh.geometry.computeVertexNormals();
44 | bodyMesh.material = this.material;
45 | }
46 | });
47 | },
48 |
49 | tick: function (time) {
50 | this.eyeMaterial.uniforms.time.value = time/1000;
51 | }
52 | });
53 |
--------------------------------------------------------------------------------
/src/components/SetGLTFMaterial.js:
--------------------------------------------------------------------------------
1 | import AFRAME from 'aframe';
2 |
3 | import SunCalibratedMaterial from '../shaders/SunCalibratedMaterial';
4 |
5 | const THREE = AFRAME.THREE;
6 |
7 | AFRAME.registerComponent('set-gltf-material', {
8 | schema: {
9 | color: {
10 | type: 'color',
11 | default: null
12 | },
13 | castShadow: {
14 | type: 'boolean',
15 | default: false
16 | },
17 | receiveShadow: {
18 | type: 'boolean',
19 | default: false
20 | },
21 | collideWith: {
22 | type: 'boolean',
23 | default: false
24 | },
25 | },
26 |
27 | applyMaterialToMesh: function (mesh) {
28 | const system = document.querySelector('a-scene').systems['sunSystem'];
29 | this.material = new SunCalibratedMaterial(system);
30 | const { color, collideWith } = this.data;
31 |
32 | mesh.castShadow = this.data.castShadow;
33 | mesh.receiveShadow = this.data.receiveShadow;
34 | mesh.geometry.computeVertexNormals()
35 |
36 | const { map: diffTexture } = mesh.material;
37 |
38 | if (diffTexture) {
39 | this.material.map = diffTexture;
40 | }
41 |
42 | mesh.material = this.material;
43 |
44 | if (color) {
45 | mesh.material.color = new THREE.Color(color);
46 | }
47 |
48 | // grab colliders from gltfs from kiko
49 | if (collideWith) {
50 | if (!this.el.sceneEl.object3D.colliders) {
51 | this.el.sceneEl.object3D.colliders = [];
52 | }
53 | this.el.sceneEl.object3D.colliders.push(mesh);
54 | }
55 | },
56 |
57 | applyMaterial: function (mesh) {
58 | if (mesh.geometry){
59 | this.applyMaterialToMesh(mesh);
60 | }
61 | mesh.children.forEach(child => {
62 | this.applyMaterial(child);
63 | });
64 | },
65 |
66 | init: function () {
67 | this.el.addEventListener('model-loaded', () => {
68 | const scene = this.el.getObject3D('mesh');
69 | this.applyMaterial(scene);
70 | });
71 | },
72 |
73 | tick: function (time) {
74 | }
75 | });
76 |
--------------------------------------------------------------------------------
/src/components/Sky.js:
--------------------------------------------------------------------------------
1 | import SkyFrag from '../shaders/SkyFrag.glsl';
2 | import SkyVert from '../shaders/SkyVert.glsl';
3 |
4 | import AFRAME from 'aframe';
5 | const THREE = AFRAME.THREE;
6 |
7 | AFRAME.registerComponent('sky', {
8 | schema: {
9 | },
10 |
11 | init: function () {
12 | const system = document.querySelector('a-scene').systems['sunSystem'];
13 | const { widthSegments, heightSegments } = this.data;
14 |
15 | var sphereGeo = new THREE.IcosahedronGeometry(
16 | system.data.skyRadius,
17 | 3 //effectively makes a sphere
18 | );
19 |
20 | var noiseTex = new THREE.TextureLoader().load('assets/star.png', (tex) => {
21 | tex.wrapS = tex.wrapT = THREE.RepeatWrapping;
22 | });
23 |
24 | var sphereMat = new THREE.ShaderMaterial({
25 | uniforms: {
26 | sunPos1: { value: new THREE.Vector3(0,1,0) },
27 | sunPos2: { value: new THREE.Vector3(0,1,0) },
28 | sunPos3: { value: new THREE.Vector3(0,1,0) },
29 | sunCentroid: {value: new THREE.Vector3(0,0,0)},
30 | sunRadius1: { value: 0 },
31 | sunRadius2: { value: 0 },
32 | sunRadius3: { value: 0 },
33 | skyRadius: { value: 0 },
34 | time: { value: 0 },
35 | fadeOutTime: { value: -1 },
36 | env_c1: {value: new THREE.Color("#ecd8ab")},
37 | env_c2: {value: new THREE.Color("#f7dbb6")},
38 | heat_c1: {value: new THREE.Color("#f95c35")},
39 | heat_c2: {value: new THREE.Color("#f78f64")},
40 | night_c1: {value: new THREE.Color("#0d1a2f")},
41 | fogColor: {value: new THREE.Color("#000000")},
42 | fogDensity: {value: 0},
43 | perlinNoiseTex: {value: noiseTex},
44 | },
45 | vertexShader: SkyVert,
46 | fragmentShader: SkyFrag,
47 | depthWrite: false,
48 | side: THREE.DoubleSide,
49 | fog: true,
50 | });
51 |
52 | var sky = new THREE.Mesh(sphereGeo, sphereMat);
53 | this.el.object3D.add(sky)
54 | this.sky = sky;
55 | system.registerSky(this.el);
56 | system.registerMaterial(this.sky.material);
57 | },
58 | tick: function (time, timeDelta) {
59 | this.sky.material.uniforms.time.value = time/1000;
60 | }
61 | });
62 |
--------------------------------------------------------------------------------
/src/components/SpeechController.js:
--------------------------------------------------------------------------------
1 | AFRAME.registerComponent('speech-controller', {
2 | init:function() {
3 | this.el.sceneEl.addEventListener('speech1', (event) => {
4 | this.el.components.sound__1.playSound();
5 | });
6 |
7 | this.el.sceneEl.addEventListener('speech2', (event) => {
8 | this.el.components.sound__2.playSound();
9 | });
10 |
11 | this.el.sceneEl.addEventListener('speech3', (event) => {
12 | this.el.components.sound__3.playSound();
13 | });
14 |
15 | this.el.sceneEl.addEventListener('speech4', (event) => {
16 | this.el.components.sound__4.playSound();
17 | });
18 | this.el.sceneEl.addEventListener('speech5', (event) => {
19 | this.el.components.sound__5.playSound();
20 | });
21 | this.el.sceneEl.addEventListener('speech6', (event) => {
22 | this.el.components.sound__6.playSound();
23 | });
24 | this.el.sceneEl.addEventListener('speech7', (event) => {
25 | this.el.components.sound__7.playSound();
26 | });
27 | this.el.sceneEl.addEventListener('speechWin', (event) => {
28 | this.el.components.sound__8.playSound();
29 | });
30 |
31 | this.el.sceneEl.addEventListener('comment1', (event) => {
32 | this.el.components.sound__9.playSound();
33 | });
34 |
35 | this.el.sceneEl.addEventListener('comment2', (event) => {
36 | this.el.components.sound__10.playSound();
37 | });
38 |
39 | this.el.addEventListener('sound-ended', (event) => {
40 | if(event.detail.id == 1){
41 | this.el.sceneEl.emit('speech1-ended');
42 | } else if(event.detail.id == 2){
43 | this.el.sceneEl.emit('speech2-ended');
44 | } else if(event.detail.id == 3){
45 | this.el.sceneEl.emit('speech3-ended');
46 | } else if(event.detail.id == 4){
47 | this.el.sceneEl.emit('speech4-ended');
48 | } else if(event.detail.id == 5){
49 | this.el.sceneEl.emit('speech5-ended');
50 | } else if(event.detail.id == 6){
51 | this.el.sceneEl.emit('speech6-ended');
52 | } else if(event.detail.id == 7){
53 | this.el.sceneEl.emit('speech7-ended');
54 | } else if(event.detail.id == 8){
55 | this.el.sceneEl.emit('speechWin-ended');
56 | }else if(event.detail.id == 9){
57 | this.el.sceneEl.emit('comment1-ended');
58 | }else if(event.detail.id == 10){
59 | this.el.sceneEl.emit('comment2-ended');
60 | }
61 | });
62 |
63 | }
64 | })
65 |
--------------------------------------------------------------------------------
/src/components/Sun.js:
--------------------------------------------------------------------------------
1 | import AFRAME from 'aframe';
2 | const THREE = AFRAME.THREE;
3 |
4 | import SunFrag from '../shaders/SunFrag.glsl';
5 | import SunVert from '../shaders/SunVert.glsl';
6 |
7 | AFRAME.registerComponent('sun', {
8 | schema: {
9 | sunRadius: {
10 | type: 'float',
11 | default: 0.2
12 | },
13 | pathRadius: {
14 | type: 'float',
15 | default: 0.8
16 | },
17 | speed: {
18 | type: 'float',
19 | default: -0.0002
20 | },
21 | offset: {
22 | type: 'float',
23 | default: 0.2
24 | }
25 | },
26 | init: function () {
27 | const system = document.querySelector('a-scene').systems['sunSystem'];
28 |
29 | const sphereMat = new THREE.ShaderMaterial({
30 | uniforms: {
31 | fadeOutTime: { value: 0 },
32 | sunCentroid: { value: 0 },
33 | time: { value: 0 },
34 | },
35 | vertexShader: SunVert,
36 | fragmentShader: SunFrag,
37 | });
38 |
39 | var sphereGeo = new THREE.SphereBufferGeometry(this.data.sunRadius * system.data.skyRadius, 100, 100);
40 | var sun = new THREE.Mesh(sphereGeo, sphereMat);
41 | this.el.object3D.add(sun)
42 |
43 | system.registerSun(this.el, this.data);
44 | system.registerMaterial(sphereMat);
45 |
46 | },
47 | });
48 |
--------------------------------------------------------------------------------
/src/components/VertexCacheTextures.js:
--------------------------------------------------------------------------------
1 | import VertexCacheSoftFrag from '../shaders/VertexCacheSoftFrag.glsl';
2 | import VertexCacheSoftVert from '../shaders/VertexCacheSoftVert.glsl';
3 | import VertexCacheFluidFrag from '../shaders/VertexCacheFluidFrag.glsl';
4 | import VertexCacheFluidVert from '../shaders/VertexCacheFluidVert.glsl';
5 | import CharacterSoftFrag from '../shaders/CharacterSoftFrag.glsl';
6 |
7 | THREE.FBXLoader = require('../libs/FBXLoader');
8 |
9 | AFRAME.registerComponent('vertex-cache-textures', {
10 | schema: {
11 | posTex: { type: 'asset' },
12 | colorTex: { type: 'asset', default: 'none' },
13 | normalTex: { type: 'asset', default: 'none' },
14 | diffuseTex: { type: 'asset', default: 'none' },
15 | fbxModel: { type: 'asset' },
16 | params: { type: 'asset' },
17 | fps: { type: 'int', default: 30 },
18 | offset: { type: 'int', default: 0 },
19 | mode: { type: 'string', default: 'fluid' },
20 | fragmentShader: { type: 'string' }
21 | },
22 |
23 | init: function () {
24 | this.posTex = null;
25 | this.colorTex = null;
26 | this.normalTex = null;
27 | this.diffuseTex = null;
28 | this.fbxModel = null;
29 | this.params = null;
30 | this.load = this.load.bind(this);
31 | this.animating = true;
32 | this.el.addEventListener('start-vertex-animation', (evt) => {
33 | this.animating = true;
34 | });
35 | },
36 |
37 | update: function () {
38 | const data = this.data;
39 | if (!data.posTex || !data.colorTex || !data.colorTex || !data.fbxModel || !data.params || !data.diffuseTex ) return;
40 |
41 | const fbxLoader = new THREE.FBXLoader();
42 | fbxLoader.load(data.fbxModel, (response) => this.load(response, 'fbx') );
43 |
44 | const loader = new THREE.FileLoader();
45 | loader.load(data.posTex, (response) => this.load(response, 'pos') );
46 | if(data.colorTex !== 'none'){
47 | loader.load(data.colorTex, (response) => this.load(response, 'color') );
48 | } else {
49 | this.colorTex = 'none';
50 | }
51 | if(data.normalTex !== 'none'){
52 | loader.load(data.normalTex, (response) => this.load(response, 'normals') );
53 | } else {
54 | this.normalTex = 'none';
55 | }
56 | loader.load(data.params, (response) => this.load(response, 'params') );
57 |
58 | },
59 |
60 | load: function (response, type) {
61 | if (type == 'fbx'){
62 | this.fbxModel = response;
63 | } else if (type == 'pos') {
64 | this.posTex = response;
65 | } else if (type == 'color') {
66 | this.colorTex = response;
67 | } else if (type == 'normals') {
68 | this.normalTex = response;
69 | } else if (type == 'params') {
70 | this.params = response;
71 | }
72 | if (this.posTex && this.colorTex && this.normalTex && this.fbxModel && this.params) {
73 | this.buildModel();
74 | }
75 | },
76 |
77 | handleFbxModel: function () {
78 | const triangleCloud = this.fbxModel.children[0];
79 |
80 | if(this.data.diffuseTex !== 'none'){
81 | this.diffuseTex = new THREE.TextureLoader().load(this.data.diffuseTex.src, (tex) => {
82 | this.model.material.uniforms.diffuseTex.value = tex;
83 | });
84 | }
85 |
86 | const uniforms = ({
87 | bbox_max: { value: this.params.bbox_max },
88 | bbox_min: { value: this.params.bbox_min },
89 | numFrames: { value: this.params.numframes },
90 | posTex: { value: 0 },
91 | colorTex: { value: 0 },
92 | normalTex: { value: 0 },
93 | diffuseTex: { value: this.diffuseTex },
94 | timeInFrames: { value: 0 },
95 | sunCentroid: { value: 0 },
96 | fadeOutTime: { value: -1 },
97 | time: { value: 0 }
98 | });
99 | const phongShader = THREE.ShaderLib.phong;
100 | const mUniforms = THREE.UniformsUtils.merge([phongShader.uniforms, uniforms]);
101 |
102 | let fragmentShader;
103 | if (this.data.fragmentShader) {
104 | fragmentShader = CharacterSoftFrag;
105 | } else {
106 | fragmentShader = (this.data.mode === 'fluid') ? VertexCacheFluidFrag: VertexCacheSoftFrag;
107 | }
108 | // ANIMATION PARAMETERS
109 | const material = new THREE.ShaderMaterial({
110 | uniforms: mUniforms,
111 | vertexShader: (this.data.mode === 'fluid') ? VertexCacheFluidVert: VertexCacheSoftVert,
112 | fragmentShader: fragmentShader,
113 | side: THREE.DoubleSide,
114 | lights: true,
115 | extensions: {
116 | derivatives: true, // set to use derivatives
117 | }
118 | });
119 | this.model = new THREE.Mesh(triangleCloud.geometry, material);
120 | this.model.scale.set(0.01, 0.01, 0.01); //houdini tool scales mesh up by 100
121 | this.model.frustumCulled = false;
122 | this.model.castShadow = true;
123 |
124 | const system = document.querySelector('a-scene').systems['sunSystem'];
125 | system.registerMaterial(material);
126 | this.el.setObject3D('vertex-cache', this.model);
127 | },
128 |
129 | handleEXRTextures: function () {
130 | let exrPos = new Module.EXRLoader(this.posTex);
131 | let exrColor = new Module.EXRLoader(this.colorTex);
132 | let exrNormal = new Module.EXRLoader(this.normalTex);
133 |
134 | // Cache image data to this variables to avoid call
135 | // to this member functions in the render for loop
136 | const exrPosBytes = exrPos.getBytes();
137 | const exrColorBytes = exrColor.getBytes();
138 | const exrNormalBytes = exrNormal.getBytes();
139 | const texWidth = exrPos.width();
140 | const texHeight = exrPos.height();
141 |
142 | // javascript code must explicitly delete any C++ object handles,
143 | // to clear the emscripten heap
144 | exrPos.delete();
145 | exrColor.delete();
146 | exrNormal.delete();
147 |
148 | const posTexture = new THREE.DataTexture( exrPosBytes, texWidth, texHeight, THREE.RGBAFormat, THREE.FloatType );
149 | posTexture.magFilter = THREE.NearestFilter;
150 | posTexture.minFilter = THREE.NearestFilter;
151 | posTexture.wrapT = posTexture.wrapS =THREE.RepeatWrapping;
152 | posTexture.needsUpdate = true
153 | this.model.material.uniforms.posTex.value = posTexture;
154 |
155 | const colorTexture = new THREE.DataTexture( exrColorBytes, texWidth, texHeight, THREE.RGBAFormat, THREE.FloatType );
156 | colorTexture.magFilter = THREE.NearestFilter;
157 | colorTexture.minFilter = THREE.NearestFilter;
158 | colorTexture.wrapT = colorTexture.wrapS =THREE.RepeatWrapping;
159 | colorTexture.needsUpdate = true
160 | this.model.material.uniforms.colorTex.value = colorTexture;
161 |
162 | // const normalTexture = new THREE.DataTexture( exrNormalBytes, texWidth, texHeight, THREE.RGBAFormat, THREE.FloatType );
163 | // normalTexture.magFilter = THREE.NearestFilter;
164 | // normalTexture.minFilter = THREE.NearestFilter;
165 | // normalTexture.wrapT = normalTexture.wrapS =THREE.RepeatWrapping;
166 | // normalTexture.needsUpdate = true
167 | // this.model.material.uniforms.normalTex.value = normalTexture;
168 | },
169 |
170 | buildModel: function () {
171 | this.handleFbxModel();
172 | this.handleEXRTextures();
173 |
174 | this.time = this.data.offset * this.data.fps;
175 |
176 | this.el.emit('vertex-cache-loaded');
177 | },
178 |
179 | remove: function () {
180 | if (this.model) this.el.removeObject3D('vertex-cache');
181 | },
182 |
183 | tick: function (time, timeDelta) {
184 | if (!this.model) return;
185 | if (!this.animating) return;
186 | const currentFrame = Math.ceil(this.time / this.data.fps);
187 | if (currentFrame >= this.params.numframes) {
188 | this.time = 0
189 | }
190 | this.model.material.uniforms.timeInFrames.value = currentFrame;
191 | this.model.material.uniforms.time.value = time / 1000;
192 | this.time += timeDelta;
193 | }
194 | });
195 |
--------------------------------------------------------------------------------
/src/components/WebUIController.js:
--------------------------------------------------------------------------------
1 | import AFRAME from 'aframe';
2 |
3 | AFRAME.registerComponent('web-ui-controller', {
4 | init: function () {
5 | const { sceneEl } = this.el;
6 | const startBtnEl = document.getElementById('startBtn');
7 | const mainScene = document.getElementById('mainScene');
8 | const introScreen = document.getElementById('introScreen');
9 | const enterVRButton = document.querySelector('.VRButton');
10 | const introText = document.getElementById('introText');
11 | const winningText = document.getElementById('winningText');
12 | const losingText = document.getElementById('losingText');
13 | const creditText = document.getElementById('creditText');
14 | const mainCamera = document.getElementById('camera');
15 |
16 | sceneEl.addEventListener('loaded', (event) => {
17 | // all game assets loaded
18 | introScreen.classList.remove('hidden');
19 | });
20 |
21 | sceneEl.addEventListener('fade-in-complete', (event) => {
22 | introText.emit('hide-intro-text');
23 | });
24 |
25 | startBtnEl.addEventListener('click', event => {
26 | sceneEl.enterVR();
27 | mainScene.setAttribute('visible', 'true');
28 | introScreen.setAttribute('style', 'visibility: hidden');
29 | introScreen.setAttribute('visible', 'false');
30 | enterVRButton.classList.add('visible');
31 |
32 | mainCamera.setAttribute('active', true);
33 |
34 | this.el.emit('begin-game');
35 | introText.emit('show-intro-text');
36 | })
37 |
38 | sceneEl.addEventListener('gameLose', event => {
39 | losingText.emit('show-lose-text');
40 | this.setFrontOfCamera(losingText);
41 | document.querySelectorAll('.fire').forEach(el => el.emit('stop-char-fire'));
42 | window.setTimeout(() => {
43 | losingText.emit('hide-lose-text');
44 | }, 22000);
45 | window.setTimeout(() => {
46 | this.setFrontOfCamera(creditText);
47 | creditText.setAttribute('color', 'black');
48 | creditText.emit('show-credit-text');
49 | }, 27000);
50 | })
51 |
52 | sceneEl.addEventListener('gameWin', event => {
53 | winningText.emit('show-win-text');
54 | this.setFrontOfCamera(winningText);
55 | window.setTimeout(() => {
56 | winningText.emit('hide-win-text');
57 | }, 22000);
58 | window.setTimeout(() => {
59 | this.setFrontOfCamera(creditText);
60 | creditText.setAttribute('color', 'white');
61 | creditText.emit('show-credit-text');
62 | }, 27000);
63 | })
64 | },
65 |
66 | setFrontOfCamera: function(entity) {
67 | const camera = document.querySelector('#camera');
68 | const left = new THREE.Vector3().set(-1,0,0).transformDirection(camera.object3D.matrixWorld);
69 | const worldPos = new THREE.Vector3().setFromMatrixPosition(camera.object3D.matrixWorld).add(left.multiplyScalar(4.5));
70 | worldPos.y = 3;
71 | const forward = new THREE.Vector3().set(0,0,-1).transformDirection(camera.object3D.matrixWorld);
72 | forward.y = 0;
73 | entity.object3D.position.copy(worldPos).add(forward.multiplyScalar(10));
74 | entity.object3D.lookAt(worldPos);
75 | }
76 | });
77 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import AFRAME from 'aframe';
2 |
3 | import JSX from './JSX';
4 | import './style.css';
5 |
6 | import './components/SetGLTFMaterial';
7 | import './components/SetCharacterMaterial';
8 | import './components/DefaultMaterial';
9 | import './components/Sun';
10 | import './components/Sky';
11 | import './components/RingOfFire';
12 | import './components/Pendulum';
13 | import './components/CharacterMover';
14 | import './components/SpeechController';
15 | import './components/AmbientController';
16 | import './components/VertexCacheTextures';
17 | import './components/WebUIController';
18 | import './components/Intro';
19 |
20 | import './systems/SunSystem';
21 | import './systems/RaycasterSystem';
22 | import './systems/PendulumSystem';
23 |
24 | import './components/Mover';
25 | import './components/Collider';
26 | import './components/CustomControl';
27 |
28 | import Fire from './Fire';
29 |
30 | // Good sky setting
31 | // sunSystem="speed: 0.02; skyRadius: 500; timeOffset: 174000; color: #ffe4aa;"
32 |
33 | const App = () => (
34 |
48 |
49 |
50 |
51 | {/* Audio */}
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | {/* Environment */}
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | {/* Character */}
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 | {/* Vertex cache */}
88 |
89 |
90 |
91 |
92 |
93 |
94 | {/* Character hight is 1.6 + cameraRig.z position */}
95 |
96 |
97 |
102 | {Fire("fire1", "0 0 0.05", "0 0 0", "0.05 0.05 0.05", 0, 45)}
103 |
104 |
110 | {Fire("fire1", "0 0 0.05", "0 0 0", "0.05 0.05 0.05", 0, 45)}
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
123 |
124 | ENTER 3BODY.NET
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
156 |
157 |
235 | {Fire("fire1", "0.22 1.9 0", "0 0 23", "0.1 0.1 0.1", 20, 45)}
236 | {Fire("fire2", "0.2 1.8 0.16", "-18 86 14", "0.07 0.07 0.07", 10, 50)}
237 | {Fire("fire3", "0.29095 1.78598 0.02063", "-18.190837037608507 86.59856002945801 14.0116828799281", "0.09 0.09 0.09", 80, 30)}
238 | {Fire("fire4", "0.19745 1.9725 -0.08298", "-0.7855251371243587 69.31872588610752 5.68087653872213", "0.02292 0.05157 0.06232", 75, 38)}
239 | {Fire("fire5", "-0.1 1.68 -0.1", "-20 75 0.46", "0.09 0.09 0.09", 100, 42)}
240 | {Fire("fire6", "-0.1 1.58 -0.1", "-2 -25 -23", "0.064 0.064 0.064", 60, 25)}
241 |
242 |
243 | {/* Environment */}
244 |
274 |
313 |
353 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
417 |
418 |
419 |
420 | );
421 |
422 | document.querySelector('body').appendChild(App());
423 |
--------------------------------------------------------------------------------
/src/libs/Utils.js:
--------------------------------------------------------------------------------
1 | const THREE = AFRAME.THREE;
2 |
3 | const t1 = new THREE.Vector3();
4 | const t2 = new THREE.Vector3();
5 | const t3 = new THREE.Vector3();
6 | const m1 = new THREE.Matrix4();
7 | const UP = new THREE.Vector3(0,1,0);
8 | //util
9 | export function setQuaternionFromDirection(direction, up, target) {
10 | const x = t1;
11 | const y = t2;
12 | const z = t3;
13 | const m = m1;
14 | const el = m1.elements;
15 |
16 | z.copy(direction);
17 | x.crossVectors(up, z);
18 |
19 |
20 | if (x.lengthSq() === 0) {
21 | // parallel
22 | if (Math.abs(up.z) === 1) {
23 | z.x += 0.0001;
24 | } else {
25 | z.z += 0.0001;
26 | }
27 | z.normalize();
28 | x.crossVectors(up, z);
29 | }
30 |
31 | x.normalize();
32 | y.crossVectors(z, x);
33 |
34 | el[0] = x.x; el[4] = y.x; el[8] = z.x;
35 | el[1] = x.y; el[5] = y.y; el[9] = z.y;
36 | el[2] = x.z; el[6] = y.z; el[10] = z.z;
37 |
38 | target.setFromRotationMatrix(m);
39 | }
40 |
--------------------------------------------------------------------------------
/src/shaders/CharacterSoftFrag.glsl:
--------------------------------------------------------------------------------
1 |
2 | #define PHONG
3 | #define FLAT_SHADED
4 |
5 |
6 | uniform vec3 diffuse;
7 | uniform vec3 emissive;
8 | uniform vec3 specular;
9 | uniform vec3 sunCentroid;
10 | uniform float shininess;
11 | uniform float opacity;
12 | uniform float time;
13 | varying vec2 vUv;
14 | uniform sampler2D diffuseTex;
15 | uniform float fadeOutTime;
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 |
34 | varying vec3 vViewPosition;
35 | varying vec3 vNormal;
36 |
37 | #ifndef FLAT_SHADED
38 |
39 | varying vec3 vNormal;
40 |
41 | #endif
42 | #define whiteCompliment(a) ( 1.0 - saturate( a ) )
43 |
44 | struct BlinnPhongMaterial {
45 |
46 | vec3 diffuseColor;
47 | vec3 specularColor;
48 | float specularShininess;
49 | float specularStrength;
50 |
51 | };
52 |
53 | void RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {
54 |
55 |
56 | float dotNL = saturate( dot( geometry.normal, directLight.direction ) );
57 | // dotNL = (dotNL < 0.5)? 0.0: 1.0;
58 | vec3 irradiance = dotNL * directLight.color;
59 |
60 | #ifndef PHYSICALLY_CORRECT_LIGHTS
61 |
62 | irradiance *= PI; // punctual light
63 |
64 | #endif
65 |
66 | reflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );
67 | // reflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;
68 | }
69 |
70 | void RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {
71 | float fogDepth = vViewPosition.z;
72 | float fogDensity = 0.1;
73 |
74 | float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );
75 | reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );
76 |
77 | }
78 |
79 | #define RE_Direct RE_Direct_BlinnPhong
80 | #define RE_IndirectDiffuse RE_IndirectDiffuse_BlinnPhong
81 |
82 | #define Material_LightProbeLOD( material ) (0)
83 |
84 | #include
85 | #include
86 | #include
87 | #include
88 | #include
89 | #include
90 |
91 | #undef USE_SHADOWMAP
92 |
93 | void main() {
94 |
95 | #include
96 |
97 | vec4 diffuseColor = texture2D(diffuseTex, vUv);
98 | vec3 yellow = vec3(241.0/255.0, 161.0/255.0, 0.0);
99 | vec3 red = vec3(161.0/255.0, 37.0/255.0, 45.0/255.0);
100 |
101 | float d = length(yellow - diffuseColor.xyz);
102 | float r = length(red - diffuseColor.xyz);
103 |
104 | float pulse = 10.0*sin(time/2.0);
105 | float glow = 0.0;
106 | if(d < 0.3){
107 | glow = 0.5 + 0.8*abs(sin(pulse)/pulse);
108 | } else if (r < 0.3){
109 | glow = 0.1 ;
110 | }
111 | diffuseColor.x = pow(diffuseColor.x,2.2);
112 | diffuseColor.y = pow(diffuseColor.y,2.2);
113 | diffuseColor.z = pow(diffuseColor.z,2.2);
114 |
115 |
116 | ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );
117 | vec3 totalEmissiveRadiance = emissive;
118 |
119 | #include
120 | #include
121 | #include
122 | #include
123 | #include
124 | #include
125 | #include
126 | #include
127 | #include
128 |
129 | // accumulation
130 | #include
131 | #include
132 | #include
133 | #include
134 |
135 | // modulation
136 | #include
137 |
138 | vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;
139 |
140 | #include
141 |
142 | gl_FragColor = vec4( glow*diffuseColor.xyz + outgoingLight, diffuseColor.a );
143 |
144 | #include
145 | #include
146 | #include
147 | #include
148 | #include
149 |
150 | @import ./ColorCorrection;
151 |
152 | }
153 |
--------------------------------------------------------------------------------
/src/shaders/ColorCorrection.glsl:
--------------------------------------------------------------------------------
1 | float distHoriz = sunCentroid.y/1000.0;
2 |
3 | gl_FragColor.r = clamp(clamp(4.0*(distHoriz),1.0,4.0) * pow( gl_FragColor.r, clamp(distHoriz,1.0,3.0)),0.0,1.0);
4 | gl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(255.0/255.0, 198.0/255.0, 85.0/255.0), clamp(distHoriz,0.0,0.3));
5 |
6 | gl_FragColor.rgb += fadeOutTime/abs(fadeOutTime)*pow(abs(fadeOutTime),2.0);
7 |
--------------------------------------------------------------------------------
/src/shaders/EyeFrag.glsl:
--------------------------------------------------------------------------------
1 | uniform float time;
2 |
3 | void main() {
4 | gl_FragColor = vec4(0.8+0.5*sin(time),0.1,0.0,1.0);
5 | }
6 |
--------------------------------------------------------------------------------
/src/shaders/EyeVert.glsl:
--------------------------------------------------------------------------------
1 | void main() {
2 | vec4 modelViewPosition = modelViewMatrix * vec4( position, 1.0 );
3 | gl_Position = projectionMatrix * modelViewPosition;
4 | }
5 |
--------------------------------------------------------------------------------
/src/shaders/FireRingFrag.glsl:
--------------------------------------------------------------------------------
1 | uniform float time;
2 | uniform float fadeOutTime;
3 | uniform vec3 fireRingColor2;
4 | uniform vec3 fireRingColor1;
5 | uniform vec3 sunCentroid;
6 |
7 | varying vec2 vUv;
8 | varying vec3 vPos;
9 |
10 | @import ./PerlinNoise;
11 |
12 | void main() {
13 | vec3 scrollingPos = vec3(vPos.x, vPos.y*4.0, vPos.z+time);
14 | vec3 scrollingPos2 = vec3(vPos.x, vPos.y, vPos.z+4.0*time);
15 |
16 | float dist2Horiz = clamp(sunCentroid.y/1000.0, 0.0, 1.0);
17 |
18 | float noise = cnoise(vec3(0.01*scrollingPos));
19 |
20 | noise *= dist2Horiz*5.0*(pow(clamp(1.0-vUv.y,0.0,1.0),2.0));
21 | // noise *= sin(0.04*time+0.05*vPos.x);
22 | noise= 6.0*pow(noise,2.0) + dist2Horiz*pow((1.0-vUv.y),4.0)*cnoise(vec3(0.2*scrollingPos2));
23 | vec3 finalColor = mix(fireRingColor1, fireRingColor2, clamp(noise, 0.0, 1.0));
24 | gl_FragColor = vec4(finalColor, noise);
25 |
26 | @import ./ColorCorrection;
27 | }
28 |
--------------------------------------------------------------------------------
/src/shaders/FireRingVert.glsl:
--------------------------------------------------------------------------------
1 | varying vec3 vPos;
2 | varying vec2 vUv;
3 |
4 | void main() {
5 | vPos = position;
6 | vUv = uv;
7 | vec4 modelViewPosition = modelViewMatrix * vec4( vPos, 1.0 );
8 | gl_Position = projectionMatrix * modelViewPosition;
9 | }
10 |
--------------------------------------------------------------------------------
/src/shaders/FogReplaceFrag.glsl:
--------------------------------------------------------------------------------
1 |
2 | #define whiteCompliment(a) ( 1.0 - saturate( a ) )
3 |
4 | #ifdef USE_FOG
5 | #ifdef FOG_EXP2
6 | float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );
7 | #else
8 | float fogFactor = smoothstep( fogNear, fogFar, fogDepth );
9 | #endif
10 | gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor/2.0 );
11 | #endif
12 |
--------------------------------------------------------------------------------
/src/shaders/FogReplaceVert.glsl:
--------------------------------------------------------------------------------
1 | #ifdef USE_FOG
2 | vec4 worldPosition = modelMatrix * vec4( position, 1.0 );
3 | // float noise = 20.0*cnoise( mod(opacity/5000.0, 6000.0) + 4000.0*worldPosition.xyz);
4 | float noise = 0.0;
5 | // fogDepth = - mvPosition.z;
6 | fogDepth = -(mvPosition.z*1.5);
7 | fogDepth = max(fogDepth - pow(worldPosition.y,1.2), 0.0);
8 | // fogDepth -= noise;
9 | #endif
10 |
--------------------------------------------------------------------------------
/src/shaders/FresnelFrag.glsl:
--------------------------------------------------------------------------------
1 | varying float vReflectionFactor;
2 |
3 | void main() {
4 | vec4 refractedColor = vec4( 0.019, 0.192, 0.231, 1.0 );
5 | vec4 reflectedColor = vec4( 0.847, 0.925, 0.933, 1.0 );
6 |
7 | gl_FragColor = 0.3 * mix( refractedColor, reflectedColor, clamp( vReflectionFactor, 0.0, 1.0 ) );
8 | }
9 |
--------------------------------------------------------------------------------
/src/shaders/FresnelVert.glsl:
--------------------------------------------------------------------------------
1 | uniform float mRefractionRatio;
2 | uniform float mFresnelBias;
3 | uniform float mFresnelScale;
4 | uniform float mFresnelPower;
5 |
6 | varying vec3 vReflect;
7 | varying vec3 vRefract[3];
8 | varying float vReflectionFactor;
9 |
10 | void main() {
11 | vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
12 | vec4 worldPosition = modelMatrix * vec4( position, 1.0 );
13 |
14 | vec3 worldNormal = normalize( mat3( modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz ) * normal );
15 |
16 | vec3 I = worldPosition.xyz - cameraPosition;
17 | vReflectionFactor = mFresnelBias + mFresnelScale * pow( 1.0 + dot( normalize( I ), worldNormal ), mFresnelPower );
18 |
19 | gl_Position = projectionMatrix * mvPosition;
20 | }
21 |
--------------------------------------------------------------------------------
/src/shaders/IntroFrag.glsl:
--------------------------------------------------------------------------------
1 | uniform float time;
2 | uniform vec3 color1;
3 | varying vec2 vUv;
4 |
5 | void main() {
6 | float r = 0.12;
7 | float c = pow(vUv.x - 0.5, 2.0) + pow(vUv.y - 0.5, 2.0);
8 | float z = 1.5 * pow(abs(c - r * r), 0.01 * sin(0.001 * time) + 0.115);
9 |
10 | gl_FragColor = z * vec4(color1 * 1.5, 1.0);
11 | }
12 |
--------------------------------------------------------------------------------
/src/shaders/IntroVert.glsl:
--------------------------------------------------------------------------------
1 | varying vec2 vUv;
2 |
3 | void main() {
4 | vUv = uv;
5 | vec4 modelViewPosition = modelViewMatrix * vec4( position, 1.0 );
6 | gl_Position = projectionMatrix * modelViewPosition;
7 | }
8 |
--------------------------------------------------------------------------------
/src/shaders/LaserFrag.glsl:
--------------------------------------------------------------------------------
1 | uniform float time;
2 | uniform float fadeOutTime;
3 | uniform vec3 sunCentroid;
4 |
5 | varying vec2 vUv;
6 |
7 | @import ./PerlinNoise;
8 |
9 | void main() {
10 | vec3 scrollingPos = vec3(.5*vUv.x, 3.0*vUv.y+0.5*time, 1.0);
11 |
12 | float noise = cnoise(vec3(scrollingPos));
13 |
14 | float m = abs(vUv.x - 0.5);
15 | float n = 1.0 - vUv.y;
16 |
17 | vec3 color1 = vec3 (0.5, 0.5, 0.5);
18 | vec3 color2 = vec3 (1.0, 1.0, 1.0);
19 |
20 | gl_FragColor = vec4(color1+abs(noise)*color2, 0.8*(n - 0.2*m));
21 | }
22 |
--------------------------------------------------------------------------------
/src/shaders/LaserVert.glsl:
--------------------------------------------------------------------------------
1 | varying vec2 vUv;
2 |
3 | void main() {
4 | vUv = uv;
5 | vec4 modelViewPosition = modelViewMatrix * vec4( position, 1.0 );
6 | gl_Position = projectionMatrix * modelViewPosition;
7 | }
8 |
--------------------------------------------------------------------------------
/src/shaders/PendulumFrag.glsl:
--------------------------------------------------------------------------------
1 |
2 | #define PHONG
3 |
4 | uniform vec3 diffuse;
5 | uniform vec3 emissive;
6 | uniform vec3 specular;
7 | uniform vec3 sunCentroid;
8 | uniform float shininess;
9 | uniform float opacity;
10 | uniform float time;
11 | uniform float fadeOutTime;
12 |
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 |
30 | varying vec3 vViewPosition;
31 | varying float vReflectionFactor;
32 | uniform float glow;
33 |
34 | #ifndef FLAT_SHADED
35 |
36 | varying vec3 vNormal;
37 |
38 | #endif
39 |
40 |
41 | struct BlinnPhongMaterial {
42 |
43 | vec3 diffuseColor;
44 | vec3 specularColor;
45 | float specularShininess;
46 | float specularStrength;
47 |
48 | };
49 |
50 | void RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {
51 |
52 |
53 | float dotNL = saturate( dot( geometry.normal, directLight.direction ) );
54 | // dotNL = (dotNL < 0.5)? 0.0: 1.0;
55 | vec3 irradiance = dotNL * directLight.color;
56 |
57 | #ifndef PHYSICALLY_CORRECT_LIGHTS
58 |
59 | irradiance *= PI; // punctual light
60 |
61 | #endif
62 |
63 | reflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );
64 | // reflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;
65 | }
66 | #define whiteCompliment(a) ( 1.0 - saturate( a ) )
67 |
68 | void RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {
69 | float fogDepth = vViewPosition.z;
70 | float fogDensity = 0.1;
71 |
72 | float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );
73 | reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );
74 |
75 | }
76 |
77 | #define RE_Direct RE_Direct_BlinnPhong
78 | #define RE_IndirectDiffuse RE_IndirectDiffuse_BlinnPhong
79 |
80 | #define Material_LightProbeLOD( material ) (0)
81 |
82 |
83 | #include
84 | #include
85 | #include
86 | #include
87 | #include
88 | #include
89 |
90 | void main() {
91 |
92 | #include
93 |
94 | vec4 diffuseColor = vec4( diffuse, opacity );
95 | ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );
96 | vec3 totalEmissiveRadiance = emissive;
97 |
98 | #include
99 | #include
100 | #include
101 | #include
102 | #include
103 | #include
104 | #include
105 | #include
106 | #include
107 |
108 | // accumulation
109 | #include
110 | #include
111 | #include
112 | #include
113 |
114 | // modulation
115 | #include
116 |
117 |
118 | vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;
119 |
120 | #include
121 |
122 | gl_FragColor = 30.0*clamp(pow(vReflectionFactor,2.0)*glow,0.0,1.0)*vec4(outgoingLight,1.0) + vec4( outgoingLight, diffuseColor.a );
123 |
124 | #include
125 | #include
126 | #include
127 | #include
128 | #include
129 |
130 | @import ./ColorCorrection;
131 |
132 | }
133 |
--------------------------------------------------------------------------------
/src/shaders/PendulumMaterial.js:
--------------------------------------------------------------------------------
1 | const THREE = AFRAME.THREE;
2 | import fogReplace from './FogReplaceFrag.glsl';
3 | import fogVertReplace from './FogReplaceVert.glsl';
4 |
5 | import phongFrag from './PendulumFrag.glsl';
6 | import phongVert from './PendulumVert.glsl';
7 |
8 | // sun calibrated materials need to have access to the sun system in order to properly update
9 | // the sunCentroid parameter. must include sunCentroid and time uniform to work properly.
10 | export default class PendulumMaterial extends THREE.MeshPhongMaterial {
11 | constructor(system, color){
12 | super();
13 | if(color){
14 | this.color = color;
15 | }
16 | this.onBeforeCompile = (shader) => {
17 | shader.uniforms.time = { value: 0 };
18 | shader.uniforms.sunCentroid = { value: new THREE.Vector3() };
19 | shader.uniforms.fadeOutTime = { value: -1 };
20 | shader.uniforms.glow = { value: 0 };
21 |
22 | shader.vertexShader = phongVert;
23 | shader.fragmentShader = phongFrag;
24 | this.shader = shader;
25 | system.registerMaterial(this.shader);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/shaders/PendulumVert.glsl:
--------------------------------------------------------------------------------
1 | #define PHONG
2 |
3 | varying vec3 vViewPosition;
4 |
5 | #ifndef FLAT_SHADED
6 |
7 | varying vec3 vNormal;
8 |
9 | #endif
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 |
24 | varying float vReflectionFactor;
25 |
26 | void main() {
27 |
28 | #include
29 | #include
30 | #include
31 |
32 | #include
33 | #include
34 | #include
35 | #include
36 | #include
37 |
38 | #ifndef FLAT_SHADED // Normal computed with derivatives when FLAT_SHADED
39 |
40 | vNormal = normalize( transformedNormal );
41 |
42 | #endif
43 |
44 | #include
45 | #include
46 | #include
47 | #include
48 | #include
49 | #include
50 | #include
51 |
52 | vViewPosition = - mvPosition.xyz;
53 | #include
54 | #include
55 | #include
56 | #include
57 |
58 | vec4 worldPos = modelMatrix * vec4( position, 1.0 );
59 | vec3 worldNormal = normalize( mat3( modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz ) * normal );
60 | vec3 I = worldPos.xyz - cameraPosition;
61 | vReflectionFactor = 1.0 + dot( normalize( I ), worldNormal );
62 | }
63 |
--------------------------------------------------------------------------------
/src/shaders/PerlinNoise.glsl:
--------------------------------------------------------------------------------
1 | // Classic Perlin 3D Noise
2 | // by Stefan Gustavson
3 | //
4 | // Source https://gist.github.com/patriciogonzalezvivo/670c22f3966e662d2f83
5 | //
6 | vec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);}
7 | vec4 taylorInvSqrt(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;}
8 | vec3 fade(vec3 t) {return t*t*t*(t*(t*6.0-15.0)+10.0);}
9 |
10 | float cnoise(vec3 P){
11 | vec3 Pi0 = floor(P); // Integer part for indexing
12 | vec3 Pi1 = Pi0 + vec3(1.0); // Integer part + 1
13 | Pi0 = mod(Pi0, 289.0);
14 | Pi1 = mod(Pi1, 289.0);
15 | vec3 Pf0 = fract(P); // Fractional part for interpolation
16 | vec3 Pf1 = Pf0 - vec3(1.0); // Fractional part - 1.0
17 | vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x);
18 | vec4 iy = vec4(Pi0.yy, Pi1.yy);
19 | vec4 iz0 = Pi0.zzzz;
20 | vec4 iz1 = Pi1.zzzz;
21 |
22 | vec4 ixy = permute(permute(ix) + iy);
23 | vec4 ixy0 = permute(ixy + iz0);
24 | vec4 ixy1 = permute(ixy + iz1);
25 |
26 | vec4 gx0 = ixy0 / 7.0;
27 | vec4 gy0 = fract(floor(gx0) / 7.0) - 0.5;
28 | gx0 = fract(gx0);
29 | vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0);
30 | vec4 sz0 = step(gz0, vec4(0.0));
31 | gx0 -= sz0 * (step(0.0, gx0) - 0.5);
32 | gy0 -= sz0 * (step(0.0, gy0) - 0.5);
33 |
34 | vec4 gx1 = ixy1 / 7.0;
35 | vec4 gy1 = fract(floor(gx1) / 7.0) - 0.5;
36 | gx1 = fract(gx1);
37 | vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1);
38 | vec4 sz1 = step(gz1, vec4(0.0));
39 | gx1 -= sz1 * (step(0.0, gx1) - 0.5);
40 | gy1 -= sz1 * (step(0.0, gy1) - 0.5);
41 |
42 | vec3 g000 = vec3(gx0.x,gy0.x,gz0.x);
43 | vec3 g100 = vec3(gx0.y,gy0.y,gz0.y);
44 | vec3 g010 = vec3(gx0.z,gy0.z,gz0.z);
45 | vec3 g110 = vec3(gx0.w,gy0.w,gz0.w);
46 | vec3 g001 = vec3(gx1.x,gy1.x,gz1.x);
47 | vec3 g101 = vec3(gx1.y,gy1.y,gz1.y);
48 | vec3 g011 = vec3(gx1.z,gy1.z,gz1.z);
49 | vec3 g111 = vec3(gx1.w,gy1.w,gz1.w);
50 |
51 | vec4 norm0 = taylorInvSqrt(vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110)));
52 | g000 *= norm0.x;
53 | g010 *= norm0.y;
54 | g100 *= norm0.z;
55 | g110 *= norm0.w;
56 | vec4 norm1 = taylorInvSqrt(vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111)));
57 | g001 *= norm1.x;
58 | g011 *= norm1.y;
59 | g101 *= norm1.z;
60 | g111 *= norm1.w;
61 |
62 | float n000 = dot(g000, Pf0);
63 | float n100 = dot(g100, vec3(Pf1.x, Pf0.yz));
64 | float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z));
65 | float n110 = dot(g110, vec3(Pf1.xy, Pf0.z));
66 | float n001 = dot(g001, vec3(Pf0.xy, Pf1.z));
67 | float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z));
68 | float n011 = dot(g011, vec3(Pf0.x, Pf1.yz));
69 | float n111 = dot(g111, Pf1);
70 |
71 | vec3 fade_xyz = fade(Pf0);
72 | vec4 n_z = mix(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z);
73 | vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y);
74 | float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x);
75 | return 2.2 * n_xyz;
76 | }
77 |
--------------------------------------------------------------------------------
/src/shaders/PhongFrag.glsl:
--------------------------------------------------------------------------------
1 | #define PHONG
2 |
3 | uniform vec3 diffuse;
4 | uniform vec3 emissive;
5 | uniform vec3 specular;
6 | uniform vec3 sunCentroid;
7 | uniform float shininess;
8 | uniform float opacity;
9 | uniform float time;
10 | uniform float fadeOutTime;
11 |
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 |
29 | varying vec3 vViewPosition;
30 |
31 | #ifndef FLAT_SHADED
32 |
33 | varying vec3 vNormal;
34 |
35 | #endif
36 |
37 |
38 | struct BlinnPhongMaterial {
39 |
40 | vec3 diffuseColor;
41 | vec3 specularColor;
42 | float specularShininess;
43 | float specularStrength;
44 |
45 | };
46 |
47 | void RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {
48 |
49 |
50 | float dotNL = saturate( dot( geometry.normal, directLight.direction ) );
51 | // dotNL = (dotNL < 0.5)? 0.0: 1.0;
52 | vec3 irradiance = dotNL * directLight.color;
53 |
54 | #ifndef PHYSICALLY_CORRECT_LIGHTS
55 |
56 | irradiance *= PI; // punctual light
57 |
58 | #endif
59 |
60 | reflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );
61 | // reflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;
62 | }
63 | #define whiteCompliment(a) ( 1.0 - saturate( a ) )
64 |
65 | void RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {
66 | float fogDepth = vViewPosition.z;
67 | float fogDensity = 0.1;
68 |
69 | float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );
70 | reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );
71 |
72 | }
73 |
74 | #define RE_Direct RE_Direct_BlinnPhong
75 | #define RE_IndirectDiffuse RE_IndirectDiffuse_BlinnPhong
76 |
77 | #define Material_LightProbeLOD( material ) (0)
78 |
79 |
80 | #include
81 | #include
82 | #include
83 | #include
84 | #include
85 | #include
86 |
87 | void main() {
88 |
89 | #include
90 |
91 | vec4 diffuseColor = vec4( diffuse, opacity );
92 | ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );
93 | vec3 totalEmissiveRadiance = emissive;
94 |
95 | #include
96 | #include
97 | #include
98 | #include
99 | #include
100 | #include
101 | #include
102 | #include
103 | #include
104 |
105 | // accumulation
106 | #include
107 | #include
108 | #include
109 | #include
110 |
111 | // modulation
112 | #include
113 |
114 |
115 | vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;
116 |
117 | #include
118 |
119 | gl_FragColor = vec4( outgoingLight, diffuseColor.a );
120 |
121 | #include
122 | #include
123 | #include
124 | #include
125 | #include
126 |
127 | @import ./ColorCorrection;
128 |
129 | }
130 |
--------------------------------------------------------------------------------
/src/shaders/PhongVert.glsl:
--------------------------------------------------------------------------------
1 | #define PHONG
2 |
3 | varying vec3 vViewPosition;
4 |
5 | #ifndef FLAT_SHADED
6 |
7 | varying vec3 vNormal;
8 |
9 | #endif
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 |
24 |
25 | void main() {
26 |
27 | #include
28 | #include
29 | #include
30 |
31 | #include
32 | #include
33 | #include
34 | #include
35 | #include
36 |
37 | #ifndef FLAT_SHADED // Normal computed with derivatives when FLAT_SHADED
38 |
39 | vNormal = normalize( transformedNormal );
40 |
41 | #endif
42 |
43 | #include
44 | #include
45 | #include
46 | #include
47 | #include
48 | #include
49 | #include
50 |
51 | vViewPosition = - mvPosition.xyz;
52 | #include
53 | #include
54 | #include
55 | #include
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/src/shaders/SkyFrag.glsl:
--------------------------------------------------------------------------------
1 | @import ./PerlinNoise;
2 | uniform float time;
3 | uniform vec3 sunPos1;
4 | uniform vec3 sunPos2;
5 | uniform vec3 sunPos3;
6 | uniform vec3 sunCentroid;
7 | uniform float sunRadius1;
8 | uniform float sunRadius2;
9 | uniform float sunRadius3;
10 | uniform float skyRadius;
11 | uniform vec3 env_c1;
12 | uniform vec3 env_c2;
13 | uniform vec3 heat_c1;
14 | uniform vec3 heat_c2;
15 | uniform vec3 night_c1;
16 | uniform float fadeOutTime;
17 |
18 | uniform sampler2D perlinNoiseTex;
19 | varying vec2 vUv;
20 | varying vec3 vPos;
21 |
22 | #include
23 | #include
24 |
25 | void main() {
26 |
27 | float freq = 1.1/(0.01 + skyRadius);
28 |
29 | vec3 scrollingPos = vec3(vPos.x, vPos.y, vPos.z + 100.0*time);
30 | float noise = cnoise(scrollingPos * freq) + 0.2;
31 |
32 | vec4 backgroundColor = vec4(mix(env_c1, env_c2, noise), 1.0);
33 | float noise2 = cnoise(scrollingPos*freq*1.0);
34 |
35 | vec4 heatColor = vec4(mix(heat_c1, heat_c2, noise2), 1.0);
36 |
37 | float l = length(vPos - sunPos1);
38 | float l2 = length(vPos - sunPos2);
39 | float l3 = length(vPos - sunPos3);
40 |
41 | float distHorizon = sunCentroid.y/(0.01 + skyRadius);
42 |
43 | backgroundColor = vec4(mix(night_c1.xyz, backgroundColor.xyz, clamp(distHorizon, 0.0, 1.0)), 1.0);
44 |
45 | float magnitude = (length(sunPos1 - sunCentroid) + length(sunPos3 - sunCentroid) + length(sunPos2 - sunCentroid))/6.0/(0.01 + skyRadius);
46 | float magnitudeS = (l + l2 + l3)/6.0/(0.01 + skyRadius);
47 | backgroundColor = mix(backgroundColor, heatColor, clamp(pow(1.0 - clamp(magnitudeS, .0, 1.0),2.0) * (1.5+pow(1.0 - clamp(magnitude, .0, 1.0),2.0)),0.0,1.0) );
48 |
49 |
50 | l = clamp((l-sunRadius1)/(4.0*sunRadius1), 0.0, 1.0);
51 | l2 = clamp((l2-sunRadius2)/(4.0*sunRadius2), 0.0, 1.0);
52 | l3 = clamp((l3-sunRadius3)/(4.0*sunRadius3), 0.0, 1.0);
53 |
54 | vec4 c1 = vec4(0.999, 0.999, 1.0, 1.0);
55 |
56 | //stars
57 | vec4 b1 = texture2D(perlinNoiseTex, 7.0*vUv);
58 | float cs = b1.r;
59 | float ss =clamp(pow(cs,3.0),0.0,1.0);
60 | vec4 starColor = abs(clamp(distHorizon, -1.0, .0))*(vPos.y/(0.01 + skyRadius))*1.5*vec4(ss, ss, ss, 1.0);
61 |
62 | gl_FragColor = backgroundColor;
63 | @import ./ColorCorrection;
64 | @import ./FogReplaceFrag;
65 |
66 | gl_FragColor = mix(gl_FragColor, c1, clamp(pow(1.0 - l, 5.0) + pow(1.0 - l3, 5.0)+ pow(1.0 - l2, 5.0), 0.0, 1.0));
67 | gl_FragColor += starColor;
68 |
69 | gl_FragColor.rgb += (fadeOutTime+0.001)/(abs(fadeOutTime+0.001))*pow(abs(fadeOutTime),2.0);
70 | }
71 |
--------------------------------------------------------------------------------
/src/shaders/SkyVert.glsl:
--------------------------------------------------------------------------------
1 | varying vec3 vPos;
2 | varying vec2 vUv;
3 |
4 | #include
5 |
6 | void main() {
7 | vPos = position;
8 | vUv = uv;
9 |
10 | vec4 mvPosition = modelViewMatrix * vec4( vPos, 1.0 );
11 | gl_Position = projectionMatrix * mvPosition;
12 |
13 | @import ./FogReplaceVert;
14 | }
15 |
--------------------------------------------------------------------------------
/src/shaders/SunCalibratedMaterial.js:
--------------------------------------------------------------------------------
1 | const THREE = AFRAME.THREE;
2 | import fogReplace from './FogReplaceFrag.glsl';
3 | import fogVertReplace from './FogReplaceVert.glsl';
4 |
5 | import phongFrag from './PhongFrag.glsl';
6 | import phongVert from './PhongVert.glsl';
7 | import perlin from './PerlinNoise.glsl';
8 |
9 | // sun calibrated materials need to have access to the sun system in order to properly update
10 | // the sunCentroid parameter. must include sunCentroid and time uniform to work properly.
11 | export default class SunCalibratedMaterial extends THREE.MeshPhongMaterial {
12 | constructor(system, color){
13 | super();
14 | if(color){
15 | this.color = color;
16 | }
17 | this.onBeforeCompile = (shader) => {
18 | shader.uniforms.time = { value: 0 };
19 | shader.uniforms.sunCentroid = { value: new THREE.Vector3() };
20 | shader.uniforms.fadeOutTime = { value: -1 };
21 | shader.vertexShader = phongVert;
22 | shader.fragmentShader = phongFrag;
23 | this.shader = shader;
24 | system.registerMaterial(this.shader);
25 | // shader.vertexShader = perlin + shader.vertexShader;
26 | // shader.vertexShader = "uniform float opacity;\n" + shader.vertexShader;
27 |
28 | // shader.fragmentShader = shader.fragmentShader.replace(
29 | // `#include `,
30 | // fogReplace
31 | // );
32 | // shader.vertexShader = shader.vertexShader.replace(
33 | // `#include `,
34 | // fogVertReplace
35 | // );
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/shaders/SunFrag.glsl:
--------------------------------------------------------------------------------
1 | uniform float fadeOutTime;
2 |
3 | void main() {
4 | gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
5 | gl_FragColor.rgb += fadeOutTime/abs(fadeOutTime)*pow(abs(fadeOutTime),2.0);
6 | }
7 |
--------------------------------------------------------------------------------
/src/shaders/SunVert.glsl:
--------------------------------------------------------------------------------
1 | void main() {
2 | vec4 modelViewPosition = modelViewMatrix * vec4( position, 1.0 );
3 | gl_Position = projectionMatrix * modelViewPosition;
4 | }
5 |
--------------------------------------------------------------------------------
/src/shaders/VertexCacheFluidFrag.glsl:
--------------------------------------------------------------------------------
1 | varying vec3 vColor;
2 | uniform vec3 sunCentroid;
3 | uniform float fadeOutTime;
4 |
5 | void main() {
6 | gl_FragColor = vec4(1.15 * pow(vColor, vec3(0.44, 0.44, 0.44)), 1.0);
7 | @import ./ColorCorrection;
8 | }
9 |
--------------------------------------------------------------------------------
/src/shaders/VertexCacheFluidVert.glsl:
--------------------------------------------------------------------------------
1 | varying vec3 vColor;
2 |
3 | uniform float bbox_max;
4 | uniform float bbox_min;
5 | uniform float timeInFrames;
6 | uniform float numFrames;
7 |
8 | uniform sampler2D posTex;
9 | uniform sampler2D colorTex;
10 |
11 | void main() {
12 | float tt = timeInFrames/numFrames + 1.0/numFrames;
13 | vec4 texPos = texture2D(posTex, vec2(uv.x, uv.y + tt - .25/numFrames));
14 | vec4 texColor = texture2D(colorTex, vec2(uv.x, uv.y + tt - .25/numFrames));
15 | vColor = texColor.xyz;
16 |
17 | vec3 texturePos = texPos.xyz;
18 | float expand = bbox_max - bbox_min; //bbmax - bbmin
19 | texturePos.xyz *= expand;
20 | texturePos.xyz += bbox_min;
21 | vec3 p = texturePos.xzy; //swizzle y and z because textures are exported with z-up
22 | vec4 modelViewPosition = modelViewMatrix * vec4(p, 1.0);
23 | gl_Position = projectionMatrix * modelViewPosition;
24 | }
25 |
--------------------------------------------------------------------------------
/src/shaders/VertexCacheSoftFrag.glsl:
--------------------------------------------------------------------------------
1 |
2 | #define PHONG
3 | #define FLAT_SHADED
4 |
5 |
6 | uniform vec3 diffuse;
7 | uniform vec3 emissive;
8 | uniform vec3 specular;
9 | uniform vec3 sunCentroid;
10 | uniform float shininess;
11 | uniform float opacity;
12 | uniform float time;
13 | uniform float fadeOutTime;
14 | varying vec2 vUv;
15 | uniform sampler2D diffuseTex;
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 |
34 | varying vec3 vViewPosition;
35 | varying vec3 vNormal;
36 |
37 | #ifndef FLAT_SHADED
38 |
39 | varying vec3 vNormal;
40 |
41 | #endif
42 |
43 |
44 | struct BlinnPhongMaterial {
45 |
46 | vec3 diffuseColor;
47 | vec3 specularColor;
48 | float specularShininess;
49 | float specularStrength;
50 |
51 | };
52 |
53 | void RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {
54 |
55 |
56 | float dotNL = saturate( dot( geometry.normal, directLight.direction ) );
57 | // dotNL = (dotNL < 0.5)? 0.0: 1.0;
58 | vec3 irradiance = dotNL * directLight.color;
59 |
60 | #ifndef PHYSICALLY_CORRECT_LIGHTS
61 |
62 | irradiance *= PI; // punctual light
63 |
64 | #endif
65 |
66 | reflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );
67 | // reflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;
68 | }
69 | #define whiteCompliment(a) ( 1.0 - saturate( a ) )
70 |
71 | void RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {
72 | float fogDepth = vViewPosition.z;
73 | float fogDensity = 0.1;
74 |
75 | float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );
76 | reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );
77 |
78 | }
79 |
80 | #define RE_Direct RE_Direct_BlinnPhong
81 | #define RE_IndirectDiffuse RE_IndirectDiffuse_BlinnPhong
82 |
83 | #define Material_LightProbeLOD( material ) (0)
84 |
85 | #include
86 | #include
87 | #include
88 | #include
89 | #include
90 | #include
91 |
92 | void main() {
93 |
94 | #include
95 |
96 | vec4 diffuseColor = texture2D(diffuseTex, vUv);
97 |
98 | ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );
99 | vec3 totalEmissiveRadiance = emissive;
100 |
101 | #include
102 | #include
103 | #include
104 | #include
105 | #include
106 | #include
107 | #include
108 | #include
109 | #include
110 |
111 | // accumulation
112 | #include
113 | #include
114 | #include
115 | #include
116 |
117 | // modulation
118 | #include
119 |
120 | vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;
121 |
122 | #include
123 |
124 | gl_FragColor = vec4( diffuseColor.xyz + outgoingLight, diffuseColor.a );
125 |
126 | #include
127 | #include
128 | #include
129 | #include
130 | #include
131 |
132 | @import ./ColorCorrection;
133 |
134 | }
135 |
--------------------------------------------------------------------------------
/src/shaders/VertexCacheSoftVert.glsl:
--------------------------------------------------------------------------------
1 | varying vec3 vViewPosition;
2 | varying vec3 vNormal;
3 | varying vec2 vUv;
4 |
5 | attribute vec2 uv2;
6 |
7 | uniform float bbox_max;
8 | uniform float bbox_min;
9 | uniform float timeInFrames;
10 | uniform float numFrames;
11 |
12 | uniform sampler2D posTex;
13 | uniform sampler2D normalTex;
14 |
15 | void main() {
16 | vUv = uv;
17 | float tt = timeInFrames/numFrames + 1.0/numFrames;
18 | vec4 texPos = texture2D(posTex, vec2(uv2.x, uv2.y + tt - 1.0)); //repeat wrapping does not work for custom attributes?
19 | vec4 texNormal = texture2D(normalTex, vec2(uv2.x, uv2.y + tt - 1.0));
20 | // vColor = texColor.xyz;
21 | //
22 | vec3 texturePos = texPos.xyz;
23 | float expand = bbox_max - bbox_min; //bbmax - bbmin
24 | texturePos.xyz *= expand;
25 | texturePos.xyz += bbox_min;
26 | vec3 p = position + texturePos.xzy; //swizzle y and z because textures are exported with z-up
27 |
28 | texNormal *= 2.0;
29 | texNormal -= 1.0;
30 | vNormal = normalMatrix * texNormal.xzy;
31 |
32 | vec4 modelViewPosition = modelViewMatrix * vec4(p, 1.0);
33 | vViewPosition = -modelViewPosition.xyz;
34 | gl_Position = projectionMatrix * modelViewPosition;
35 | }
36 |
--------------------------------------------------------------------------------
/src/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css?family=Nanum+Gothic|Nanum+Gothic+Coding|Questrial&display=swap');
2 |
3 | html, body {
4 | color: white;
5 | font-size: 145%;
6 | font-family: 'Questrial', sans-serif;
7 | font-weight: 80;
8 | }
9 |
10 | .a-loader-title {
11 | color: black;
12 | }
13 |
14 | .screenContainer {
15 | display: flex;
16 | flex-direction: column;
17 | position: absolute;
18 | align-items: center;
19 | justify-content: center;
20 | width: 100%;
21 | height: 100%;
22 | z-index: 999;
23 | }
24 |
25 | .screenText {
26 | width: 60%;
27 | text-align: justify;
28 | opacity: 0.5;
29 | line-height: 80%;
30 | }
31 |
32 | #buttonsContainer {
33 | display: flex;
34 | position: absolute;
35 | top: 20px;
36 | left: 20px;
37 | width: 50px;
38 | height: 50px;
39 | z-index: 999;
40 | }
41 |
42 | #buttonsContainer .btnImage {
43 | display: flex;
44 | width: 50px;
45 | opacity: 0.6;
46 | }
47 |
48 | #buttonsContainer .btnImage:hover {
49 | cursor: pointer;
50 | opacity: 0.8;
51 | }
52 |
53 | #introScreen .screenContainer {
54 | /* background-color: #001427; */
55 | }
56 |
57 | #loseScreen .screenContainer {
58 | background-color: #8D0801;
59 | }
60 |
61 | #winScreen .screenContainer {
62 | background-color: #b8541b;
63 | }
64 |
65 | #startBtn {
66 | display: flex;
67 | align-items: center;
68 | justify-content: center;
69 | opacity: 0.6;
70 | text-shadow: 0 0 30px white;
71 | }
72 |
73 | #startBtn:hover {
74 | cursor: pointer;
75 | opacity: 0.8;
76 | }
77 |
78 | .VRButton {
79 | visibility: hidden;
80 | position: absolute;
81 | bottom: 20px;
82 | right: 20px;
83 | min-width: 50px;
84 | min-height: 50px;
85 | background: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20245.82%20141.73%22%3E%3Cdefs%3E%3Cstyle%3E.a%7Bfill%3A%23fff%3Bfill-rule%3Aevenodd%3B%7D%3C%2Fstyle%3E%3C%2Fdefs%3E%3Ctitle%3Emask%3C%2Ftitle%3E%3Cpath%20class%3D%22a%22%20d%3D%22M175.56%2C111.37c-22.52%2C0-40.77-18.84-40.77-42.07S153%2C27.24%2C175.56%2C27.24s40.77%2C18.84%2C40.77%2C42.07S198.08%2C111.37%2C175.56%2C111.37ZM26.84%2C69.31c0-23.23%2C18.25-42.07%2C40.77-42.07s40.77%2C18.84%2C40.77%2C42.07-18.26%2C42.07-40.77%2C42.07S26.84%2C92.54%2C26.84%2C69.31ZM27.27%2C0C11.54%2C0%2C0%2C12.34%2C0%2C28.58V110.9c0%2C16.24%2C11.54%2C30.83%2C27.27%2C30.83H99.57c2.17%2C0%2C4.19-1.83%2C5.4-3.7L116.47%2C118a8%2C8%2C0%2C0%2C1%2C12.52-.18l11.51%2C20.34c1.2%2C1.86%2C3.22%2C3.61%2C5.39%2C3.61h72.29c15.74%2C0%2C27.63-14.6%2C27.63-30.83V28.58C245.82%2C12.34%2C233.93%2C0%2C218.19%2C0H27.27Z%22%2F%3E%3C%2Fsvg%3E) 50% 50%/70% 70% no-repeat rgba(0,0,0,.35);
86 | z-index: 999;
87 | }
88 |
89 | .VRButton:hover {
90 | cursor: pointer;
91 | }
92 |
93 | .visible {
94 | visibility: visible;
95 | }
96 |
97 | .hidden {
98 | visibility: hidden;
99 | }
100 |
--------------------------------------------------------------------------------
/src/systems/PendulumSystem.js:
--------------------------------------------------------------------------------
1 | import AFRAME from 'aframe';
2 | const THREE = AFRAME.THREE;
3 |
4 | //keeps track of all pendulums, and colors them all when in sync
5 | AFRAME.registerSystem('pendulum', {
6 | schema: {
7 | },
8 | init: function () {
9 | this.pendulums = [];
10 | this.totalDist = 10;
11 | },
12 | registerPendulum: function(pendulum) {
13 | this.pendulums.push(pendulum);
14 | },
15 | getSynchStatus: function() {
16 | return (this.totalDist < 1)? true : false;
17 | },
18 | tick: function (time, timeDelta) {
19 | if( Math.abs(this.pendulums[0].dampeningFactor) < 0.1 || Math.abs(this.pendulums[1].dampeningFactor) < 0.1 || Math.abs(this.pendulums[2].dampeningFactor) < 0.1 ){
20 | this.totalDist = 10;
21 | this.pendulums.forEach((p) => {
22 | p.brighten(0);
23 | })
24 | return;
25 | }
26 | //assume we have 3 pendulums .
27 | var dist1 = Math.abs(this.pendulums[0].curAngle-this.pendulums[1].curAngle);
28 | var dist2 = Math.abs(this.pendulums[0].curAngle-this.pendulums[2].curAngle);
29 | var dist3 = Math.abs(this.pendulums[1].curAngle-this.pendulums[2].curAngle);
30 |
31 | this.totalDist = (dist1 + dist2 + dist3)/3;
32 | this.pendulums.forEach((p) => {
33 | p.brighten(1/this.totalDist/100);
34 | })
35 | }
36 | });
37 |
--------------------------------------------------------------------------------
/src/systems/RaycasterSystem.js:
--------------------------------------------------------------------------------
1 | import AFRAME from 'aframe';
2 | const THREE = AFRAME.THREE;
3 |
4 | import LaserFrag from '../shaders/LaserFrag.glsl';
5 | import LaserVert from '../shaders/LaserVert.glsl';
6 |
7 | import { setQuaternionFromDirection } from '../libs/Utils';
8 |
9 | AFRAME.registerSystem('raycasterSystem', {
10 | schema: {
11 | },
12 |
13 | init: function () {
14 | this.raycaster = new THREE.Raycaster();
15 | this.mouse = new THREE.Vector2();
16 |
17 | this.triggerDown = false;
18 | this.mouseDown = false;
19 |
20 | this.tmps = {
21 | v1: new THREE.Vector3(),
22 | v2: new THREE.Vector3()
23 | };
24 |
25 | const controller = document.querySelector('#controller');
26 | this.controllerObject = controller.object3D;
27 |
28 | var planeGeo = new THREE.PlaneGeometry( 0.01,10 );
29 | var m1 = new THREE.Matrix4().makeRotationX(Math.PI/2)
30 | var m2 = new THREE.Matrix4().makeTranslation(0,0,5)
31 | planeGeo.applyMatrix(m2.multiply(m1))
32 | var planeMat = new THREE.ShaderMaterial({
33 | uniforms: {
34 | sunCentroid: {value: new THREE.Vector3(0,0,0)},
35 | fadeOutTime: {value: -1},
36 | time: {value: 0},
37 | },
38 | side:THREE.DoubleSide,
39 | transparent: true,
40 | vertexShader: LaserVert,
41 | fragmentShader: LaserFrag,
42 | depthWrite: false,
43 | });
44 | this.laserPlane = new THREE.Mesh(planeGeo, planeMat);
45 | this.sceneEl.object3D.add(this.laserPlane);
46 | this.laserPlane.visible = false;
47 |
48 | const system = document.querySelector('a-scene').systems['sunSystem'];
49 | system.registerMaterial(planeMat);
50 |
51 | window.addEventListener( 'mousedown', (event) => {
52 | this.mouseDown = true;
53 |
54 | this.mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
55 | this.mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
56 | this.raycaster.setFromCamera( this.mouse, this.sceneEl.camera );
57 | this.sceneEl.emit('raycast-active-onset');
58 | }, false );
59 |
60 | window.addEventListener( 'mousemove', (event) => {
61 | if(!this.mouseDown) return;
62 | this.mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
63 | this.mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
64 | this.raycaster.setFromCamera( this.mouse, this.sceneEl.camera );
65 | this.sceneEl.emit('raycast-active');
66 | }, false );
67 |
68 | window.addEventListener( 'mouseup', (event) => {
69 | this.mouseDown = false;
70 | this.sceneEl.emit('raycast-finished');
71 | }, false );
72 |
73 |
74 | window.addEventListener( 'triggerdown', (event) => {
75 | this.triggerDown = true;
76 | var origin = this.tmps.v1.setFromMatrixPosition(this.controllerObject.matrixWorld);
77 | var forward = this.tmps.v2.set(0,0,-1).transformDirection(this.controllerObject.matrixWorld);
78 | this.raycaster.set(origin, forward);
79 | this.sceneEl.emit('raycast-active-onset');
80 | }, false );
81 |
82 | window.addEventListener( 'triggerup', (event) => {
83 | this.triggerDown = false;
84 | this.sceneEl.emit('raycast-finished');
85 | }, false );
86 | },
87 |
88 | updateTriggerRay: function() {
89 | var origin = this.tmps.v1.setFromMatrixPosition(this.controllerObject.matrixWorld);
90 | var forward = this.tmps.v2.set(0,0,-1).transformDirection(this.controllerObject.matrixWorld);
91 |
92 | setQuaternionFromDirection(forward, new THREE.Vector3(0,1,0), this.laserPlane.quaternion)
93 | this.laserPlane.position.copy(origin)
94 |
95 | if(!this.triggerDown) return;
96 | this.raycaster.set(origin, forward);
97 | this.sceneEl.emit('raycast-active');
98 | },
99 |
100 | intersectObject: function(obj3d) {
101 | return this.raycaster.intersectObject(obj3d);
102 | },
103 |
104 | tick: function (time, timeDelta) {
105 | this.updateTriggerRay();
106 | }
107 | });
108 |
--------------------------------------------------------------------------------
/src/systems/SunSystem.js:
--------------------------------------------------------------------------------
1 | import AFRAME from 'aframe';
2 | const THREE = AFRAME.THREE;
3 |
4 | AFRAME.registerSystem('sunSystem', {
5 | schema: {
6 | speed: {
7 | type: 'float'
8 | },
9 | skyRadius: {
10 | type: 'float'
11 | },
12 | timeOffset: {
13 | type: 'float',
14 | default: 0
15 | },
16 | fogColor: {
17 | type: 'color',
18 | default: '#ffffff'
19 | },
20 | },
21 |
22 | init: function () {
23 | this.entities = [];
24 | this.materials = [];
25 | this.center = new THREE.Object3D();
26 | this.center.up = new THREE.Vector3(1,0,1)
27 | this.sphere = new THREE.Sphere(new THREE.Vector3(0,0,0), this.data.skyRadius);
28 | this.ray = new THREE.Ray();
29 |
30 | //sun system is in charge of the three directional lights
31 | this.sunLight1 = new THREE.DirectionalLight(0xffffff, 0.5);
32 | this.sunLight1.castShadow = true;
33 | this.sunLight1.shadow.camera.far = 2*this.data.skyRadius;
34 | this.sunLight1.shadow.camera.left = -10;
35 | this.sunLight1.shadow.camera.bottom = -10;
36 | this.sunLight1.shadow.camera.right = 10;
37 | this.sunLight1.shadow.camera.top = 10;
38 | this.sunLight1.shadow.mapSize.width = 2*1024;
39 | this.sunLight1.shadow.mapSize.height = 2*1024;
40 |
41 | // this.sceneEl.object3D.add(new THREE.CameraHelper(this.sunLight1.shadow.camera))
42 |
43 | this.sunLight2 = new THREE.DirectionalLight(0xffffff, 0.5);
44 | // this.sunLight2.castShadow = true;
45 | // this.sunLight2.shadow.camera.far = 2*this.data.skyRadius;
46 |
47 | this.sunLight3 = new THREE.DirectionalLight(0xffffff, 0.5);
48 | // this.sunLight3.castShadow = true;
49 | // this.sunLight3.shadow.camera.far = 2*this.data.skyRadius;
50 |
51 | this.fogColor = new THREE.Color(this.data.fogColor);
52 | this.fogNightColor = new THREE.Color("#ffffff");
53 |
54 | this.sceneEl.object3D.add(this.sunLight1)
55 | this.sceneEl.object3D.add(this.sunLight2)
56 | this.sceneEl.object3D.add(this.sunLight3)
57 |
58 | this.startAnimation = false;
59 | this.fadingOutWhite = false;
60 | this.fadingOutBlack = false;
61 | this.fadingIn = false;
62 | this.gameOver = false;
63 |
64 | this.animationTime = this.data.timeOffset;
65 | this.sceneEl.addEventListener('begin-game', () => {
66 | this.fadingIn = true;
67 | this.materials.forEach((mat) => {
68 | mat.uniforms.fadeOutTime.value = -1;
69 | })
70 | });
71 | this.sceneEl.addEventListener('start-sun-animation', () => {
72 | this.startAnimation = true;
73 | });
74 | this.sceneEl.addEventListener('speech6-ended', () => {
75 | window.setTimeout(() => {
76 | if(!this.gameOver){
77 | this.fadingOutWhite = true;
78 | }
79 | }, 40000);
80 | });
81 | this.sceneEl.addEventListener('speechWin-ended', (event) => {
82 | window.setTimeout(() => {
83 | this.fadingOutBlack = true;
84 | }, 10000);
85 | });
86 | this.sceneEl.addEventListener('win', () => {
87 | this.fadingOutWhite = false;
88 | this.gameOver = true;
89 | });
90 | },
91 |
92 | registerSun: function (el, initData) {
93 | //TODO; WHY
94 | initData.sunRadius = this.data.skyRadius*parseFloat(initData.sunRadius);
95 | initData.pathRadius = this.data.skyRadius*parseFloat(initData.pathRadius);
96 | initData.speed = parseFloat(initData.speed);
97 | initData.offset = parseFloat(initData.offset);
98 | this.entities.push({el, initData});
99 | this.updateSkyUniforms();
100 | },
101 |
102 | updateSkyUniforms: function () {
103 | this.sky.material.uniforms["skyRadius"].value = this.data.skyRadius;
104 | this.entities.forEach((sun, index) => {
105 | const uniName = 'sunRadius' + (index+1).toString();
106 | this.sky.material.uniforms[uniName].value = sun.initData.sunRadius;
107 | })
108 | },
109 |
110 | registerSky: function (el) {
111 | this.sky = el.object3D.children[0];
112 | },
113 |
114 | registerMaterial: function(mat) {
115 | this.materials.push(mat);
116 | },
117 |
118 | registerMainCharacter: function(char) {
119 | this.sunLight1.target = char;
120 | },
121 |
122 | tick: function (time, timeDelta) {
123 |
124 | var center;
125 | if(this.startAnimation){
126 | if(this.animationTime < 350122){
127 | this.animationTime += timeDelta;
128 | } else {
129 | this.animationTime += 0.5*timeDelta; //slow down the ending
130 | }
131 | }
132 | center = new THREE.Vector3(0, this.data.skyRadius*Math.sin(this.animationTime/-2000*this.data.speed), this.data.skyRadius*Math.cos(this.animationTime/-2000*this.data.speed));
133 |
134 | this.center.position.copy(center);
135 | this.center.updateMatrixWorld();
136 |
137 | this.center.lookAt(new THREE.Vector3(0,0,0));
138 | var newX = new THREE.Vector3(1,0,0).applyQuaternion(this.center.quaternion);
139 | var newY = new THREE.Vector3(0,1,0).applyQuaternion(this.center.quaternion);
140 |
141 | var sunCentroid = new THREE.Vector3(0,0,0);
142 | this.entities.forEach((sun, index) => {
143 | const curSun = sun.el.object3D.children[0];
144 | var pos = new THREE.Vector3().add(
145 | newX.clone().multiplyScalar(sun.initData.pathRadius*Math.cos(this.animationTime*sun.initData.speed*this.data.speed + sun.initData.offset))).add(
146 | newY.clone().multiplyScalar(sun.initData.pathRadius*Math.sin(this.animationTime*sun.initData.speed*this.data.speed + sun.initData.offset)))
147 | pos.add(center);
148 | this.ray.origin.copy(pos);
149 | this.ray.direction.copy(pos.normalize().multiplyScalar(-1));
150 | this.ray.intersectSphere(this.sphere, curSun.position);
151 | const uniName = 'sunPos' + (index+1).toString();
152 | this.sky.material.uniforms[uniName].value.copy(curSun.position);
153 | const lightName = 'sunLight' + (index+1).toString();
154 | this[lightName].position.copy(curSun.position);
155 | this[lightName].intensity = Math.max(curSun.position.y/this.data.skyRadius, 0);
156 | sunCentroid.add(curSun.position)
157 | })
158 |
159 | sunCentroid.multiplyScalar(1/3);
160 | var t = sunCentroid.y/this.data.skyRadius;
161 |
162 | t = Math.min(Math.max(t, 0), 1);
163 | this.sceneEl.object3D.fog.density = Math.min(t+0.1,1)*0.005;
164 | this.sceneEl.object3D.fog.color = this.fogNightColor.lerp(this.fogColor, t);
165 |
166 |
167 | var fadeOutTime = this.materials[0].uniforms.fadeOutTime.value;
168 | if(this.fadingOutWhite){
169 | fadeOutTime += 0.00006523*timeDelta;
170 | if (fadeOutTime > 1.002){
171 | } else if(fadeOutTime > 1.0){
172 | this.sceneEl.emit('gameLose')
173 | }
174 | } else if(this.fadingIn){
175 | fadeOutTime += 0.00005078*timeDelta;
176 | if(fadeOutTime >= -0.0001){
177 | this.fadingIn = false;
178 | this.sceneEl.emit('fade-in-complete');
179 | }
180 | } else if (this.fadingOutBlack) {
181 | if (fadeOutTime > -1){
182 | fadeOutTime -= 0.00006523*timeDelta;
183 | }
184 | } else {
185 | fadeOutTime = Math.max(fadeOutTime-0.0006523*timeDelta, 0.0001);
186 | }
187 |
188 | this.materials.forEach((mat) => {
189 | mat.uniforms.sunCentroid.value = sunCentroid;
190 | mat.uniforms.time.value = time/1000;
191 | mat.uniforms.fadeOutTime.value = fadeOutTime;
192 | })
193 | }
194 | });
195 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const CopyPlugin = require('copy-webpack-plugin');
3 | const HtmlWebpackPlugin = require('html-webpack-plugin');
4 |
5 | module.exports = {
6 | entry: ['babel-polyfill', './src/index.js'],
7 | output: {
8 | filename: 'bundle.js',
9 | path: path.resolve(__dirname, 'dist')
10 | },
11 | module: {
12 | rules: [
13 | {
14 | test: /\.js$/,
15 | exclude: /node_modules/,
16 | loader: 'babel-loader'
17 | },
18 | {
19 | test: /\.css$/,
20 | use: [
21 | 'style-loader',
22 | 'css-loader'
23 | ]
24 | },
25 | {
26 | test: /\.glsl$/,
27 | loader: 'webpack-glsl-loader'
28 | }
29 | ]
30 | },
31 | plugins: [
32 | new HtmlWebpackPlugin({
33 | inject: true,
34 | template: 'public/index.html',
35 | }),
36 | new CopyPlugin([
37 | {
38 | from: 'public/assets',
39 | to: 'assets',
40 | },
41 | {
42 | from: 'public/js',
43 | to: 'js',
44 | }
45 | ]),
46 | ],
47 | devServer: {
48 | contentBase: './dist',
49 | compress: true,
50 | disableHostCheck: true,
51 | hot: true,
52 | inline: true,
53 | port: 3000,
54 | host: '0.0.0.0',
55 | },
56 | };
57 |
--------------------------------------------------------------------------------