Upated babylonjs version, added map, camera, camerawindow.

This commit is contained in:
Michael Mainguy 2024-05-21 06:34:48 -05:00
parent 4c26dca6c5
commit 2872026ac9
16 changed files with 905 additions and 74 deletions

80
package-lock.json generated
View File

@ -1,21 +1,22 @@
{ {
"name": "immersive", "name": "immersive",
"version": "0.0.5", "version": "0.0.7",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "immersive", "name": "immersive",
"version": "0.0.5", "version": "0.0.7",
"dependencies": { "dependencies": {
"@babylonjs/core": "^7.3.1", "@babylonjs/core": "^7.6.0",
"@babylonjs/gui": "^7.3.1", "@babylonjs/gui": "^7.6.0",
"@babylonjs/havok": "1.3.4", "@babylonjs/havok": "1.3.4",
"@babylonjs/inspector": "^7.3.1", "@babylonjs/inspector": "^7.6.0",
"@babylonjs/loaders": "^7.3.1", "@babylonjs/loaders": "^7.6.0",
"@babylonjs/materials": "^7.3.1", "@babylonjs/materials": "^7.6.0",
"@babylonjs/procedural-textures": "^7.3.1", "@babylonjs/procedural-textures": "^7.6.0",
"@babylonjs/serializers": "^7.3.1", "@babylonjs/serializers": "^7.6.0",
"@maptiler/client": "1.8.1",
"@picovoice/cobra-web": "^2.0.3", "@picovoice/cobra-web": "^2.0.3",
"@picovoice/eagle-web": "^1.0.0", "@picovoice/eagle-web": "^1.0.0",
"@picovoice/web-voice-processor": "^4.0.9", "@picovoice/web-voice-processor": "^4.0.9",
@ -55,14 +56,14 @@
} }
}, },
"node_modules/@babylonjs/core": { "node_modules/@babylonjs/core": {
"version": "7.5.0", "version": "7.6.0",
"resolved": "https://registry.npmjs.org/@babylonjs/core/-/core-7.5.0.tgz", "resolved": "https://registry.npmjs.org/@babylonjs/core/-/core-7.6.0.tgz",
"integrity": "sha512-iP/z+j1eRrpv5g/JyqxMAuT7UVdfBWPHZ0Bl/89onq9hZmeyckHM+gXNpepo4sFrxoDefdAblh5eyVbN6iiXDg==" "integrity": "sha512-Pr5TlHQBdTYLkw+HmWZo1V6VYnP48wxEGBAscHcgZuuETo2ITCmsRLv0o+XY0QL1eAL8grQBM5eOkAInNt4SvA=="
}, },
"node_modules/@babylonjs/gui": { "node_modules/@babylonjs/gui": {
"version": "7.5.0", "version": "7.6.0",
"resolved": "https://registry.npmjs.org/@babylonjs/gui/-/gui-7.5.0.tgz", "resolved": "https://registry.npmjs.org/@babylonjs/gui/-/gui-7.6.0.tgz",
"integrity": "sha512-kqS9HtveyG7W918u+h01JZBv9cDoPda3/o/vjbiZOUHem71Lj5MR7WeVr8bSRPbVRyj3mUdL2o1w2tYRPiDC/w==", "integrity": "sha512-5r954RVrnEvSCw/WKwl6CdKb5PIVEMyF6WKS+bDku3PrwaoTUqkd1jlhmyaH6k2bL/bcoaz25ts04TK6YrbmXA==",
"peerDependencies": { "peerDependencies": {
"@babylonjs/core": "^7.0.0" "@babylonjs/core": "^7.0.0"
} }
@ -88,9 +89,9 @@
} }
}, },
"node_modules/@babylonjs/inspector": { "node_modules/@babylonjs/inspector": {
"version": "7.5.0", "version": "7.6.0",
"resolved": "https://registry.npmjs.org/@babylonjs/inspector/-/inspector-7.5.0.tgz", "resolved": "https://registry.npmjs.org/@babylonjs/inspector/-/inspector-7.6.0.tgz",
"integrity": "sha512-B1ACpoljYX5Y3DHJZgCwfkhlS4M5xb9VJKtH3mN+VgXEt5AnOMT2F8pXJNz9ICQC7XhIxo34JL52OnE5iOhlvw==", "integrity": "sha512-utytbidkVhYXNhVY5XOuGIHCPdmHrHw9q1rr9+P7nwUUwTtl3duAQiU8TE/w/6MUejg97kyN6lBGRqXAWpL5nA==",
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.1.0", "@fortawesome/fontawesome-svg-core": "^6.1.0",
"@fortawesome/free-regular-svg-icons": "^6.0.0", "@fortawesome/free-regular-svg-icons": "^6.0.0",
@ -108,34 +109,34 @@
} }
}, },
"node_modules/@babylonjs/loaders": { "node_modules/@babylonjs/loaders": {
"version": "7.5.0", "version": "7.6.0",
"resolved": "https://registry.npmjs.org/@babylonjs/loaders/-/loaders-7.5.0.tgz", "resolved": "https://registry.npmjs.org/@babylonjs/loaders/-/loaders-7.6.0.tgz",
"integrity": "sha512-rVkYkiT3XSGJ1s0rEuUCN3BXJGI4RexKXUrTp1cy0CVj3B2DvNt9pzET4038BmVp8N3EDPBd9+bPZenduicsPw==", "integrity": "sha512-7tt/ImGExADJx5wGs/3vz8tijg1FHuVT2c/8dp0Q+qv3v47KJIgCOtggoXCVDTo+xYj2fQWtucmXwkNhIizg7w==",
"peerDependencies": { "peerDependencies": {
"@babylonjs/core": "^7.0.0", "@babylonjs/core": "^7.0.0",
"babylonjs-gltf2interface": "^7.0.0" "babylonjs-gltf2interface": "^7.0.0"
} }
}, },
"node_modules/@babylonjs/materials": { "node_modules/@babylonjs/materials": {
"version": "7.5.0", "version": "7.6.0",
"resolved": "https://registry.npmjs.org/@babylonjs/materials/-/materials-7.5.0.tgz", "resolved": "https://registry.npmjs.org/@babylonjs/materials/-/materials-7.6.0.tgz",
"integrity": "sha512-IGYQt+0qaX4ZVTyMge4IjZnHcPpwf85/J+fg4QBUz0BoUgrFAvi0nXJl43X7FJaj0H2BJSaERBZm/kK2K9bKqA==", "integrity": "sha512-o5PcKNf/NE+P81E1fQyuoNrCND6dV5RJZga03JzHIs48/+2veq11Dj4FGAOinmqQwe/0U2yrl3v4hsRVwt4YtQ==",
"peerDependencies": { "peerDependencies": {
"@babylonjs/core": "^7.0.0" "@babylonjs/core": "^7.0.0"
} }
}, },
"node_modules/@babylonjs/procedural-textures": { "node_modules/@babylonjs/procedural-textures": {
"version": "7.5.0", "version": "7.6.0",
"resolved": "https://registry.npmjs.org/@babylonjs/procedural-textures/-/procedural-textures-7.5.0.tgz", "resolved": "https://registry.npmjs.org/@babylonjs/procedural-textures/-/procedural-textures-7.6.0.tgz",
"integrity": "sha512-xvJ/gQJBy1mgTJYc/YkzzdzJoK/L/wBi/rtW9o9ckLe+cjw5UQ0gIGEUIJlgIx2GX7hPVjKd73uN2l5LcWYVsA==", "integrity": "sha512-37Dheb8kGX0lWRevFw3mqMtuoJrJ+TT2bEQB/9BOmAKS2yEb2xlLlswkn7UaB4oHax8XzaY9N63zTSzzWj978Q==",
"peerDependencies": { "peerDependencies": {
"@babylonjs/core": "^7.0.0" "@babylonjs/core": "^7.0.0"
} }
}, },
"node_modules/@babylonjs/serializers": { "node_modules/@babylonjs/serializers": {
"version": "7.5.0", "version": "7.6.0",
"resolved": "https://registry.npmjs.org/@babylonjs/serializers/-/serializers-7.5.0.tgz", "resolved": "https://registry.npmjs.org/@babylonjs/serializers/-/serializers-7.6.0.tgz",
"integrity": "sha512-DCQmT8RnBmF7jxIOhXjEmHL4dFmPrypBdMEoI9eVenQfLwBlRim4tbzHlHSwmk1DOy+ENxqODZzhzh4EmUaS4A==", "integrity": "sha512-U/umdH2dAcEuyb1OcaemV2LOgIohsoWAgUriub0SxA+DLlpiyEt6HUSvM+aX/90UyGNz5Dpb4VZXbqBIrUa0Hg==",
"peerDependencies": { "peerDependencies": {
"@babylonjs/core": "^7.0.0", "@babylonjs/core": "^7.0.0",
"babylonjs-gltf2interface": "^7.0.0" "babylonjs-gltf2interface": "^7.0.0"
@ -572,6 +573,14 @@
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
"dev": true "dev": true
}, },
"node_modules/@maptiler/client": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/@maptiler/client/-/client-1.8.1.tgz",
"integrity": "sha512-G1z2xCBwT5WU1CqeukY3R4g1saSjKzi6tmg24LJWZHP81RQ4quVvwdmsx829BxITlFbFhND+BSphFgrDGmwhcA==",
"dependencies": {
"quick-lru": "^7.0.0"
}
},
"node_modules/@nodelib/fs.scandir": { "node_modules/@nodelib/fs.scandir": {
"version": "2.1.5", "version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@ -2579,6 +2588,17 @@
} }
] ]
}, },
"node_modules/quick-lru": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-7.0.0.tgz",
"integrity": "sha512-MX8gB7cVYTrYcFfAnfLlhRd0+Toyl8yX8uBx1MrX7K0jegiz9TumwOK27ldXrgDlHRdVi+MqU9Ssw6dr4BNreg==",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/randombytes": { "node_modules/randombytes": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",

View File

@ -1,7 +1,7 @@
{ {
"name": "immersive", "name": "immersive",
"private": true, "private": true,
"version": "0.0.6", "version": "0.0.7",
"type": "module", "type": "module",
"engines": { "engines": {
"node": ">=18.0.0" "node": ">=18.0.0"
@ -16,17 +16,18 @@
"havok": "cp ./node_modules/@babylonjs/havok/lib/esm/HavokPhysics.wasm ./node_modules/.vite/deps" "havok": "cp ./node_modules/@babylonjs/havok/lib/esm/HavokPhysics.wasm ./node_modules/.vite/deps"
}, },
"dependencies": { "dependencies": {
"@babylonjs/core": "^7.3.1", "@babylonjs/core": "^7.6.0",
"@babylonjs/gui": "^7.3.1", "@babylonjs/gui": "^7.6.0",
"@babylonjs/havok": "1.3.4", "@babylonjs/havok": "1.3.4",
"@babylonjs/inspector": "^7.3.1", "@babylonjs/inspector": "^7.6.0",
"@babylonjs/loaders": "^7.3.1", "@babylonjs/loaders": "^7.6.0",
"@babylonjs/materials": "^7.3.1", "@babylonjs/materials": "^7.6.0",
"@babylonjs/procedural-textures": "^7.3.1", "@babylonjs/procedural-textures": "^7.6.0",
"@babylonjs/serializers": "^7.3.1", "@babylonjs/serializers": "^7.6.0",
"@picovoice/cobra-web": "^2.0.3", "@picovoice/cobra-web": "^2.0.3",
"@picovoice/eagle-web": "^1.0.0", "@picovoice/eagle-web": "^1.0.0",
"@picovoice/web-voice-processor": "^4.0.9", "@picovoice/web-voice-processor": "^4.0.9",
"@maptiler/client": "1.8.1",
"@typed-mxgraph/typed-mxgraph": "^1.0.8", "@typed-mxgraph/typed-mxgraph": "^1.0.8",
"@types/dom-to-image": "^2.6.7", "@types/dom-to-image": "^2.6.7",
"@types/file-saver": "^2.0.6", "@types/file-saver": "^2.0.6",

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g data-name="Layer 2">
<g data-name="video">
<rect width="24" height="24" opacity="0"/>
<path d="M21 7.15a1.7 1.7 0 0 0-1.85.3l-2.15 2V8a3 3 0 0 0-3-3H5a3 3 0 0 0-3 3v8a3 3 0 0 0 3 3h9a3 3 0 0 0 3-3v-1.45l2.16 2a1.74 1.74 0 0 0 1.16.45 1.68 1.68 0 0 0 .69-.15 1.6 1.6 0 0 0 1-1.48V8.63A1.6 1.6 0 0 0 21 7.15z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 438 B

View File

@ -0,0 +1,300 @@
# Object Export From Tinkercad Server 2015
mtllib obj.mtl
o obj_0
v 4 3.5 4
v 4 3.568 3.482
v 4 3.768 3
v 4 4.086 2.586
v 4 4.5 2.268
v 4 4.982 2.068
v 4 5.5 2
v 4 6.018 2.068
v 4 6.5 2.268
v 4 6.914 2.586
v 4 7.232 3
v 4 7.432 3.482
v 4 7.5 4
v 4 7.432 4.518
v 4 7.232 5
v 4 6.914 5.414
v 4 6.5 5.732
v 4 6.018 5.932
v 4 5.5 6
v 4 4.982 5.932
v 4 4.5 5.732
v 4 4.086 5.414
v 4 3.768 5
v 4 3.568 4.518
v -8.308 4.5 7.952
v 1 4.7272 4.2072
v -8.587 4.5 7.81
v 1 4.7 4
v -8.81 4.5 7.587
v 1 4.8072 4.4
v -8.952 4.5 7.308
v 1 4.9344 4.5656
v -9 4.5 7.0043
v 0.952 6.5 7.308
v 1 5.1 4.6928
v 1 6.5 7.0043
v 0.81 6.5 7.587
v 1 5.2928 4.7728
v 0.587 6.5 7.81
v 0.308 6.5 7.952
v 1 5.5 4.8
v 0.0033 6.5 8
v 1 5.7072 4.7728
v 1 5.9 4.6928
v 1 6.0656 4.5656
v 1 6.1928 4.4
v 1 4.5 7.0043
v 0.952 4.5 7.308
v 0.81 4.5 7.587
v 0.587 4.5 7.81
v 0.308 4.5 7.952
v 1 6.2728 4.2072
v 0.0033 4.5 8
v 1 6.3 4
v -8.0043 4.5 0
v -8.952 4.5 0.692
v -9 4.5 0.9967
v 1 6.2728 3.7928
v -8.81 4.5 0.413
v -8.587 4.5 0.19
v 1 6.1928 3.6
v -8.308 4.5 0.048
v 1 6.0656 3.4344
v 1 5.9 3.3072
v -8.0043 6.5 8
v -8.308 6.5 7.952
v 1 5.7072 3.2272
v -8.587 6.5 7.81
v 1 5.5 3.2
v -8.81 6.5 7.587
v -8.952 6.5 7.308
v 1 5.2928 3.2272
v -9 6.5 7.0043
v 1 5.1 3.3072
v 1 4.9344 3.4344
v 1 4.8072 3.6
v 1 4.7272 3.7928
v -9 6.5 0.9967
v -8.0043 4.5 8
v 0.81 6.5 0.413
v 0.587 6.5 0.19
v 0.952 6.5 0.692
v 1 6.5 0.9967
v 0.0033 6.5 0
v 0.0033 4.5 0
v 0.308 4.5 0.048
v -8.0043 6.5 0
v 0.587 4.5 0.19
v 0.81 4.5 0.413
v 0.952 4.5 0.692
v 1 4.5 0.9967
v -8.952 6.5 0.692
v -8.81 6.5 0.413
v -8.587 6.5 0.19
v -8.308 6.5 0.048
v 0.308 6.5 0.048
# 96 vertices
g group_0_8273816
usemtl color_8273816
s 0
f 1 2 3
f 1 3 4
f 1 4 5
f 1 5 6
f 1 6 7
f 1 7 8
f 1 8 9
f 1 9 10
f 1 10 11
f 1 11 12
f 1 12 13
f 1 13 14
f 1 14 15
f 1 15 16
f 1 16 17
f 1 17 18
f 1 18 19
f 1 19 20
f 1 20 21
f 1 21 22
f 1 22 23
f 1 23 24
f 28 1 26
f 24 26 1
f 23 30 26
f 23 26 24
f 22 32 30
f 22 30 23
f 32 22 35
f 21 35 22
f 49 48 37
f 35 21 38
f 20 38 21
f 19 41 38
f 19 38 20
f 41 19 43
f 18 43 19
f 34 48 36
f 17 44 43
f 17 43 18
f 34 37 48
f 16 45 44
f 16 44 17
f 49 37 39
f 45 16 46
f 15 46 16
f 53 40 42
f 36 48 47
f 49 39 50
f 51 50 40
f 39 40 50
f 46 15 52
f 14 52 15
f 40 53 51
f 52 54 36
f 83 36 54
f 54 58 83
f 58 61 83
f 61 63 83
f 93 60 59
f 64 83 63
f 69 72 91
f 72 74 91
f 73 33 71
f 74 75 91
f 75 76 91
f 25 65 66
f 66 68 27
f 66 27 25
f 29 27 70
f 68 70 27
f 91 76 77
f 91 77 28
f 70 71 31
f 70 31 29
f 71 33 31
f 65 25 79
f 57 33 78
f 73 78 33
f 42 65 53
f 53 65 79
f 81 88 86
f 80 89 88
f 80 88 81
f 89 80 90
f 82 90 80
f 82 83 90
f 91 90 83
f 84 86 85
f 55 87 85
f 84 85 87
f 95 87 55
f 86 91 85
f 88 91 86
f 89 90 88
f 91 88 90
f 92 56 78
f 93 56 92
f 94 60 93
f 94 95 60
f 62 60 95
f 56 55 57
f 91 57 85
f 62 95 55
f 55 85 57
f 59 55 56
f 60 62 59
f 55 59 62
f 78 56 57
f 93 59 56
f 29 31 27
f 33 27 31
f 27 33 25
f 13 54 52
f 13 52 14
f 54 13 58
f 12 58 13
f 49 50 57
f 51 57 50
f 53 57 51
f 79 33 53
f 61 58 11
f 12 11 58
f 63 61 10
f 11 10 61
f 10 9 64
f 10 64 63
f 49 57 48
f 91 47 57
f 25 33 79
f 57 53 33
f 47 48 57
f 9 8 67
f 9 67 64
f 96 73 81
f 84 73 96
f 69 67 7
f 8 7 67
f 80 81 73
f 7 6 72
f 7 72 69
f 74 72 5
f 6 5 72
f 93 92 94
f 78 94 92
f 95 78 87
f 65 42 83
f 75 74 4
f 5 4 74
f 66 83 68
f 70 68 83
f 4 3 76
f 4 76 75
f 39 37 40
f 42 40 37
f 42 37 34
f 3 2 77
f 3 77 76
f 34 36 42
f 28 77 1
f 2 1 77
f 36 83 42
f 65 83 66
f 71 70 83
f 73 71 83
f 82 80 73
f 83 82 73
f 87 78 84
f 94 78 95
f 73 84 78
f 96 86 84
f 81 86 96
f 67 69 83
f 64 67 83
f 69 91 83
f 91 28 47
f 28 26 47
f 26 30 47
f 30 32 47
f 38 41 47
f 32 35 47
f 35 38 47
f 41 36 47
f 41 43 36
f 43 44 36
f 44 45 36
f 45 46 36
f 46 52 36
# 188 faces
#end of obj_0

Binary file not shown.

After

Width:  |  Height:  |  Size: 688 KiB

View File

@ -2,6 +2,7 @@ importScripts('https://storage.googleapis.com/workbox-cdn/releases/7.1.0/workbox
const VERSION = '8'; const VERSION = '8';
const CACHE = "deepdiagram"; const CACHE = "deepdiagram";
const IMAGEDELIVERY_CACHE = "deepdiagram-images"; const IMAGEDELIVERY_CACHE = "deepdiagram-images";
const MAPTILE_CACHE = 'maptiler';
// TODO: replace the following with the correct offline fallback page i.e.: const offlineFallbackPage = "offline.html"; // TODO: replace the following with the correct offline fallback page i.e.: const offlineFallbackPage = "offline.html";
const offlineFallbackPage = "/"; const offlineFallbackPage = "/";
@ -43,7 +44,27 @@ workbox.routing.registerRoute(
cacheName: CACHE cacheName: CACHE
}) })
); );
console.warn('workbox');
workbox.routing.registerRoute(
new RegExp('.*api.maptiler.com/.*'),
new workbox.strategies.CacheFirst({
plugins: [
new workbox.expiration.ExpirationPlugin({
maxEntries: 256,
maxAgeSeconds: 60 * 60 * 24 * 30,
purgeOnQuotaError: true,
matchOptions: {
ignoreVary: true
}
}),
new workbox.cacheableResponse.CacheableResponsePlugin({
statuses: [0, 200]
})
],
cacheName: MAPTILE_CACHE
})
);
workbox.routing.registerRoute( workbox.routing.registerRoute(
new RegExp('/assets/.*'), new RegExp('/assets/.*'),

View File

@ -1,45 +1,96 @@
import {Color3, DynamicTexture, Mesh, MeshBuilder, Scene, StandardMaterial, Vector3} from "@babylonjs/core"; import {Color3, DynamicTexture, MeshBuilder, Scene, StandardMaterial, Vector3} from "@babylonjs/core";
import log, {Logger} from "loglevel"; import log, {Logger} from "loglevel";
import {MaptilerMap} from "../objects/maptilerMap";
export class CameraMenu { export class CameraMenu {
private readonly scene: Scene; private readonly scene: Scene;
private xr;
private controllers;
private readonly logger: Logger = log.getLogger('CameraMenu'); private readonly logger: Logger = log.getLogger('CameraMenu');
constructor(scene, xr, controllers) { constructor(scene) {
this.scene = scene; this.scene = scene;
this.xr = xr; //this.buildMenu(3, new Vector3(-1, 2, 0));
this.controllers = controllers;
this.buildMenu(1, new Vector3(0, 1, 0));
//this.buildMenu(4, new Vector3(0,2,0)); //this.buildMenu(4, new Vector3(0,2,0));
//this.buildMenu(5, new Vector3(1,2,0)); //this.buildMenu(5, new Vector3(1,2,0));
//this.buildMenu(6, new Vector3(1,1,0)); //this.buildMenu(6, new Vector3(2,2,0));
//this.buildIcon();
//this.loadIcon();
this.buildMap();
} }
private buildMap() {
const maptilerMap = new MaptilerMap('YnvhjBiU8oCWP0GXNdHL', this.scene, 'map-node', 3);
maptilerMap.node.position.y = 1;
maptilerMap.node.position.z = -4;
maptilerMap.node.rotation.y = Math.PI;
maptilerMap.node.rotation.x = Math.PI / 6;
maptilerMap.node.scaling = new Vector3(1, 1, 1);
//maptilerMap.setLocation('loves park, il' , 15);
maptilerMap.setLocation('rockford, il', 12).then(() => {
maptilerMap.plotPoint(42.33181896128866, -88.86844896012006);
});
}
//https://maps.geoapify.com/v1/staticmap?style=osm-carto&scaleFactor=2&width=4096&height=4096&center=lonlat:-89.0940,42.2711&zoom=12.4318&apiKey=d548c5ed24604be6a9dd0d989631f783
private buildIcon() {
const icon = MeshBuilder.CreatePlane('camera-icon', {width: .1, height: .1}, this.scene);
icon.position = new Vector3(0, 3, 0);
icon.metadata = {grabbable: true};
const material = new StandardMaterial('icon-material', this.scene);
material.backFaceCulling = false;
const texture = new DynamicTexture('icon-texture', {width: 256, height: 256}, this.scene);
//const texture = new DynamicTexture('/assets/icons/video.png', this.scene);
const image = new Image();
//image.setAttribute('width', '256');
//image.setAttribute('height', '256');
//image.width=32;
//image.height=32;
image.src = '/assets/icons/video.png';
image.onload = () => {
texture.getContext().drawImage(image, 0, 0);
texture.update();
}
material.emissiveColor = new Color3(.1, .1, .8);
material.opacityTexture = texture;
icon.material = material;
material.disableLighting = true;
//material.diffuseTexture = texture;
//material.disableLighting;
//material.emissiveColor = new Color3(1, 1, 1);
//texture.uScale = 1;
//texture.vScale = 1;
}
private buildMenu(camnum: number, position: Vector3) { private buildMenu(camnum: number, position: Vector3) {
const camerasphere = MeshBuilder.CreateSphere("camerasphere", { const camerasphere = MeshBuilder.CreatePlane('camera-' + camnum, {width: 1, height: 1}, this.scene);
diameter: 10,
slice: .5,
sideOrientation: Mesh.DOUBLESIDE
}, this.scene);
camerasphere.position = position; camerasphere.position = position;
const material = new StandardMaterial("cameramaterial", this.scene); const material = new StandardMaterial("cameramaterial", this.scene);
material.emissiveColor = new Color3(1, 1, 1); //material.emissiveColor = new Color3(1, 1, 1);
material.backFaceCulling = false;
const texture = new DynamicTexture('texture', {width: 1600, height: 1600}, this.scene); const texture = new DynamicTexture('texture', {width: 1600, height: 1600}, this.scene);
material.diffuseTexture = texture; material.emissiveTexture = texture;
material.disableLighting = true;
const img = new Image(); const img = new Image();
img.src = 'https://cameras.immersiveidea.com/mjpg/video.mjpg?camera=' + camnum + '&timestamp=1698497537140';
img.setAttribute('crossorigin', 'anonymous');
img.src = 'https://cameras.immersiveidea.com/mjpg/video.mjpg?camera=' + camnum;
const ctx = texture.getContext(); const ctx = texture.getContext();
img.onload = () => { img.onload = () => {
ctx.drawImage(img, 250, 0, 2112, 1940, 0, 0, 1600, 1600);
ctx.drawImage(img, 0, 0);
texture.update(); texture.update();
window.setInterval((texture, img, ctx) => { window.setInterval((texture, img, ctx) => {
ctx.drawImage(img, 250, 0, 2112, 1940, 0, 0, 1600, 1600); ctx.drawImage(img, 0, 0);
texture.update(); texture.update();
}, 60, texture, img, ctx); }, 1000, texture, img, ctx);
} }
texture.onLoadObservable.add(() => { texture.onLoadObservable.add(() => {

66
src/objects/cameraIcon.ts Normal file
View File

@ -0,0 +1,66 @@
import {
AbstractMesh,
ActionManager,
Color3,
ExecuteCodeAction,
InstancedMesh,
Mesh,
Scene,
SceneLoader,
StandardMaterial,
TransformNode,
Vector3
} from "@babylonjs/core";
import {DefaultScene} from "../defaultScene";
import {CameraWindow} from "./cameraWindow";
export class CameraIcon {
private static _baseMesh: AbstractMesh;
private readonly _scene: Scene;
private _cam: CameraWindow;
constructor(scene: Scene, mapNode: TransformNode, position: Vector3) {
this._scene = scene;
if (!CameraIcon._baseMesh) {
this.loadIcon();
}
const newInstance = new InstancedMesh('cam', CameraIcon._baseMesh as Mesh);
newInstance.setParent(mapNode);
newInstance.position = position;
newInstance.actionManager = new ActionManager(this._scene);
newInstance.actionManager.registerAction(new ExecuteCodeAction(ActionManager.OnPickTrigger, () => {
if (this._cam) {
this._cam.dispose();
this._cam = null;
} else {
this._cam = new CameraWindow(scene, null, 'https://cameras.immersiveidea.com/mjpg/video.mjpg?camera=3');
this._cam.mesh.position.x = newInstance.absolutePosition.x;
this._cam.mesh.position.z = newInstance.absolutePosition.z;
this._cam.mesh.position.y = newInstance.absolutePosition.y + .5;
}
}));
//newInstance.billboardMode = Mesh.BILLBOARDMODE_ALL;
}
private loadIcon() {
SceneLoader.ImportMesh('', '/assets/models/', 'tinker.obj', this._scene,
(newMesh) => {
const myMesh = newMesh[0].getChildren()[0] as Mesh;
//myMesh.position = new Vector3(0, 1.5, 0);
myMesh.metadata = {grabbable: true};
const SCALE = .006;
myMesh.scaling = new Vector3(SCALE, SCALE, SCALE);
myMesh.rotation.x = Math.PI / 2;
const material = new StandardMaterial('icon-material', DefaultScene.Scene);
material.emissiveColor = new Color3(.1, .1, .9);
material.disableLighting = true;
myMesh.material = material;
myMesh.name = 'cam';
myMesh.setEnabled(false);
myMesh.setParent(null);
newMesh[0].dispose();
CameraIcon._baseMesh = myMesh;
})
}
}

View File

@ -0,0 +1,59 @@
import {AbstractMesh, DynamicTexture, MeshBuilder, Scene, StandardMaterial, TransformNode} from "@babylonjs/core";
export class CameraWindow {
private readonly _scene: Scene;
private readonly _url: string;
private readonly _parent: TransformNode;
private readonly _intervalId: number;
private _cameraMesh: AbstractMesh;
private _img: HTMLImageElement;
constructor(scene: Scene, parent: TransformNode, url: string) {
this._scene = scene;
this._parent = parent;
this._url = url;
this.build();
}
public get mesh() {
return this._cameraMesh;
}
public dispose() {
window.clearInterval(this._intervalId);
this._cameraMesh.dispose(false, true);
this._img.remove();
}
private build() {
this._cameraMesh = MeshBuilder.CreatePlane('cam-' + this._url, {width: 1, height: 1}, this._scene);
this._cameraMesh.parent = this._parent;
//camerasphere.position = position;
const material = new StandardMaterial("cameramaterial", this._scene);
//material.emissiveColor = new Color3(1, 1, 1);
material.backFaceCulling = false;
const texture = new DynamicTexture('texture', {width: 1600, height: 1600}, this._scene);
material.emissiveTexture = texture;
material.disableLighting = true;
this._img = new Image();
this._img.setAttribute('crossorigin', 'anonymous');
//img.src = 'https://cameras.immersiveidea.com/mjpg/video.mjpg?camera=' + camnum;
this._img.src = this._url;
const ctx = texture.getContext();
this._img.onload = () => {
ctx.drawImage(this._img, 0, 0);
texture.update();
window.setInterval((texture, img, ctx) => {
ctx.drawImage(img, 0, 0);
texture.update();
}, 1000, texture, this._img, ctx);
}
texture.onLoadObservable.add(() => {
});
this._cameraMesh.material = material;
}
}

View File

@ -1,9 +1,55 @@
import {Scene} from "@babylonjs/core"; import {AbstractMesh, Scene} from "@babylonjs/core";
import {DiagramEntity} from "../diagram/types/diagramEntity";
import {buildMeshFromDiagramEntity} from "../diagram/functions/buildMeshFromDiagramEntity";
import {toDiagramEntity} from "../diagram/functions/toDiagramEntity";
type DiagramObjectOptionsType = {
diagramEntity?: DiagramEntity,
mesh?: AbstractMesh
}
export class DiagramObject { export class DiagramObject {
private scene: Scene; private _scene: Scene;
constructor(scene: Scene) { constructor(scene: Scene, options?: DiagramObjectOptionsType) {
this.scene = scene; this._scene = scene;
if (options) {
if (options.diagramEntity) {
this.fromDiagramEntity(options.diagramEntity);
}
if (options.mesh) {
this._mesh = options.mesh;
this._diagramEntity = this.diagramEntity;
}
}
}
private _mesh: AbstractMesh;
public get mesh(): AbstractMesh {
return this._mesh;
}
private _diagramEntity: DiagramEntity;
public get diagramEntity(): DiagramEntity {
if (!this._diagramEntity) {
if (this._mesh) {
this._diagramEntity = toDiagramEntity(this._mesh);
}
}
return this._diagramEntity;
}
public fromDiagramEntity(entity: DiagramEntity): DiagramObject {
this._diagramEntity = entity;
this._mesh = buildMeshFromDiagramEntity(this._diagramEntity, this._scene);
return this;
}
public dispose() {
this._mesh.dispose(false, true);
this._mesh = null;
this._diagramEntity = null;
this._scene = null;
} }
} }

256
src/objects/maptilerMap.ts Normal file
View File

@ -0,0 +1,256 @@
import * as mapTilerClient from '@maptiler/client';
import {
AbstractMesh,
MeshBuilder,
Observable,
Scene,
StandardMaterial,
Texture,
TransformNode,
Vector2,
Vector3
} from "@babylonjs/core";
import {CameraIcon} from "./cameraIcon";
export type MaptilerMapTile = {
lat: number,
lon: number,
zoom: number,
url: string,
x: number,
y: number,
bounds: Vector2[];
}
export class MaptilerMap {
public readonly onReadyObservable = new Observable<MaptilerMapTile>();
private _lat: number;
private _lon: number;
private _min: Vector2;
private _max: Vector2;
private _zoom: number;
//private _bounds: Vector2[];
private readonly _scene: Scene;
private _tileXYCount: number = 2;
private readonly _baseNode: TransformNode;
private readonly _key: string;
private _pendingPoints: Array<number> = [];
private _points: Vector2[] = [];
public constructor(key: string, scene: Scene, name: string = 'map-node', tileXYCount: number = 2) {
this._scene = scene;
this._key = key;
this._tileXYCount = tileXYCount;
this._baseNode = new TransformNode(name, this._scene);
this.onReadyObservable.addOnce(this.buildNodes.bind(this));
this.onReadyObservable.addOnce(this.waitForMeshAdded.bind(this));
}
private _startFallback: number = 10;
public set startFallback(value: number) {
this._startFallback = value;
}
private _fallbackInterval: number = 10;
public set fallbackInterval(value: number) {
this._fallbackInterval = value;
}
public get node(): TransformNode {
return this._baseNode;
}
public async setLocation(name: string, zoom: number = 18): Promise<void> {
mapTilerClient.config.apiKey = this._key;
const result = await mapTilerClient.geocoding.forward(name)
if (result.features.length > 0) {
this.setInitialData(result.features[0].center[1], result.features[0].center[0], zoom);
const tileXY = await this.getTileXY(this._lat, this._lon);
const output = this.getTile(tileXY[0], tileXY[1], zoom);
this.onReadyObservable.notifyObservers({
lat: this._lat,
lon: this._lon,
zoom: zoom,
x: tileXY[0],
y: tileXY[1],
url: output,
bounds: []
});
} else {
console.error(JSON.stringify(result));
}
}
public async setLocationByLatLon(lat: number, lon: number, zoom: number = 18): Promise<void> {
this.setInitialData(lat, lon, zoom);
const tileXY = this.getTileXY(lat, lon);
const imageUrl = this.getTile(tileXY[0], tileXY[1], zoom);
this.onReadyObservable.notifyObservers({
lat: this._lat,
lon: this._lon,
zoom: zoom,
x: tileXY[0],
y: tileXY[1],
url: imageUrl,
bounds: []
});
}
public async plotPoint(lat: number, lon: number) {
const len = this._points.push(new Vector2(lat, lon));
this._pendingPoints.push(len - 1);
}
public getTile(x: number, y: number, z: number) {
return `https://api.maptiler.com/maps/streets-v2/256/${z}/${x}/${y}@2x.png?key=${this._key}`;
}
private waitForMeshAdded() {
this._scene.onAfterRenderObservable.add(() => {
if (this._pendingPoints.length > 0) {
this._pendingPoints = this._pendingPoints.filter((item) => {
const point = this._points[item];
const tileXY = this.getTileXY(point.x, point.y);
console.log(tileXY);
const mesh = this._scene.getMeshByName(`map-${tileXY[0]}-${tileXY[1]}-plane`);
const oldPoint = this._scene.getMeshByName(`map-${point.x}-${point.y}-point`);
if (!mesh) {
console.error(`map-${tileXY[0]}-${tileXY[1]}-plane not found`);
return true;
} else {
if (!oldPoint) {
const pixelx = lonOnTile(point.y, this._zoom) % 1;
const pixely = latOnTile(point.x, this._zoom) % 1;
console.log(`pixelx: ${pixelx}, pixely: ${pixely} found`);
try {
const newIcon = new CameraIcon(this._scene, this._baseNode,
new Vector3(mesh.position.x - .5 + pixelx, mesh.position.y + .5 - pixely, mesh.position.z - .05));
return false;
} catch (err) {
return true;
}
} else {
return false;
//oldPoint.dispose(false, true);
}
}
});
}
}, -1, false, this);
}
private buildNodes(data: MaptilerMapTile) {
this.buildMapTile(0, 0, data.url, data.x, data.y).parent = this._baseNode;
let time = this._startFallback;
const tiles = this._tileXYCount;
if (this._tileXYCount < 1) {
return;
}
for (let x = -tiles; x < (tiles + 1); x++) {
for (let y = -tiles; y < (tiles + 1); y++) {
if (x !== 0 || y !== 0) {
const url = this.getTile(data.x + x, data.y + y, data.zoom);
window.setTimeout((that) => {
that.buildMapTile(x, -y, url, data.x + x, data.y + y).parent = this._baseNode;
}, time += this._fallbackInterval, this);
}
}
}
}
private getTileXY(lat: number, lon: number): number[] {
return [Math.floor(lonOnTile(lon, this._zoom)), Math.floor(latOnTile(lat, this._zoom))];
}
private setInitialData(lat: number, lon: number, zoom: number) {
this._baseNode.getChildren().forEach((child) => {
child.dispose(false, true);
});
this._lat = lat;
this._lon = lon;
this._zoom = zoom;
}
private buildMapTile(x: number, y: number, url: string, xTile: number, yTile: number): AbstractMesh {
const map = MeshBuilder.CreatePlane(`map-${xTile}-${yTile}-plane`, {width: 1, height: 1}, this._scene);
const mapMaterial = new StandardMaterial(`map-${xTile}-${yTile}-material`, this._scene);
const mapTexture = new Texture(url, this._scene);
const lon = tile2long(xTile, this._zoom);
const lat = tile2lat(yTile, this._zoom);
if (!this._min || lat < this._min.x || lon < this._min.y) {
this._min = new Vector2(lat, lon);
console.log(`min: ${lat}, ${lon}`);
}
const maxLat = tile2lat(yTile + 1, this._zoom);
const maxLon = tile2long(xTile + 1, this._zoom);
if (!this._max || maxLat > this._max.y || maxLon > this._max.y) {
this._min = new Vector2(maxLat, maxLon);
console.log(`max: ${maxLat}, ${maxLon}`);
}
map.metadata = {
mapTile: {x: xTile, y: yTile}, bounds:
{
topleft:
{lat: lat, lon: lon},
bottomright:
{
lat: tile2lat(yTile + 1, this._zoom),
lon: tile2long(xTile + 1, this._zoom)
}
}
};
mapTexture.name = `map-${xTile}-${yTile}-texture`;
mapMaterial.emissiveTexture = mapTexture;
mapMaterial.disableLighting = true;
mapMaterial.backFaceCulling = false;
map.material = mapMaterial;
map.position.x = x;
map.position.y = y;
map.isPickable = true;
return map;
}
}
function tile2long(x, z) {
return (x / Math.pow(2, z) * 360 - 180);
}
function tile2lat(y, z) {
var n = Math.PI - 2 * Math.PI * y / Math.pow(2, z);
return (180 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))));
}
const EARTH_CIR_METERS = 40075016.686;
const TILE_SIZE = 512;
const degreesPerMeter = 360 / EARTH_CIR_METERS;
const LIMIT_Y = toDegrees(Math.atan(Math.sinh(Math.PI))) // around 85.0511...
function toRadians(degrees) {
return degrees * Math.PI / 180;
}
function toDegrees(radians) {
return (radians / Math.PI) * 180
}
function lonOnTile(lon, zoom) {
return ((lon + 180) / 360) * Math.pow(2, zoom)
}
function latOnTile(lat, zoom) {
return (
((1 -
Math.log(
Math.tan((lat * Math.PI) / 180) + 1 / Math.cos((lat * Math.PI) / 180)
) /
Math.PI) /
2) *
Math.pow(2, zoom)
)
}

View File

@ -8,9 +8,10 @@ export function buildColor(color: Color3, scene: Scene, parent: TransformNode, i
const height = .1; const height = .1;
const material = new StandardMaterial("material-" + color.toHexString(), scene); const material = new StandardMaterial("material-" + color.toHexString(), scene);
material.diffuseColor = color; material.diffuseColor = color;
material.ambientColor = color;
material.roughness = .1; // material.ambientColor = color;
material.maxSimultaneousLights = 1; //material.roughness = .1;
//material.maxSimultaneousLights = 2;
const colorBoxMesh = MeshBuilder.CreatePlane("toolbox-color-" + color.toHexString(), { const colorBoxMesh = MeshBuilder.CreatePlane("toolbox-color-" + color.toHexString(), {
width: width, width: width,

View File

@ -1,13 +1,13 @@
import { import {
Color3, Color3,
GroundMesh, GroundMesh,
HemisphericLight,
Material, Material,
MeshBuilder, MeshBuilder,
Observable, Observable,
PBRMaterial, PBRMaterial,
PhysicsAggregate, PhysicsAggregate,
PhysicsShapeType, PhysicsShapeType,
PointLight,
PointsCloudSystem, PointsCloudSystem,
Scene, Scene,
Sound, Sound,
@ -33,13 +33,14 @@ export class CustomEnvironment {
if (loading) { if (loading) {
loading.remove(); loading.remove();
} }
this.scene.ambientColor = new Color3(.2, .2, .2); this.scene.ambientColor = new Color3(1, 1, 1);
const light = new HemisphericLight("light1", new Vector3(1, 2, 1), this.scene); //const light = new HemisphericLight("light1", new Vector3(1, 2, 1), this.scene);
light.groundColor = new Color3(.1, .1, .1) //light.groundColor = new Color3(.1, .1, .1)
light.diffuse = new Color3(1, 1, 1); //light.diffuse = new Color3(1, 1, 1);
light.setDirectionToTarget(new Vector3(.4, .5, .5).normalize()); //light.setDirectionToTarget(new Vector3(.4, .5, .5).normalize());
light.intensity = .5; //light.intensity = .7;
const light = new PointLight("light1", new Vector3(0, 10, 10), this.scene);
const light2 = new PointLight("light1", new Vector3(0, 10, -10), this.scene);
const physics = new CustomPhysics(this.scene, config); const physics = new CustomPhysics(this.scene, config);
physics physics
.initializeAsync() .initializeAsync()

View File

@ -60,6 +60,7 @@ export class VrApp {
initEnvironment(diagramManager, spinner); initEnvironment(diagramManager, spinner);
const gamepadManager = new GamepadManager(scene); const gamepadManager = new GamepadManager(scene);
addSceneInspector(); addSceneInspector();
//const camMenu = new CameraMenu(scene);
const el = document.querySelector('#download'); const el = document.querySelector('#download');
if (el) { if (el) {
el.addEventListener('click', () => { el.addEventListener('click', () => {