├── .gitignore
├── README.md
├── cube
├── normal-cube.js
├── xr-cube.js
└── xr-hit-cube.js
├── index.html
├── model
├── xr-domOverlay.js
└── xr-hit-models.js
├── package-lock.json
├── package.json
├── public
├── draco
│ ├── README.md
│ ├── draco_decoder.js
│ ├── draco_decoder.wasm
│ ├── draco_encoder.js
│ ├── draco_wasm_wrapper.js
│ └── gltf
│ │ ├── draco_decoder.js
│ │ ├── draco_decoder.wasm
│ │ ├── draco_encoder.js
│ │ └── draco_wasm_wrapper.js
└── models
│ ├── bookcase.gltf
│ ├── chair.gltf
│ ├── tree1.gltf
│ ├── tree2.gltf
│ └── tree3.gltf
└── style.css
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # WEBXR + THREE.js
2 |
3 | Code for the [Youtube playlist](https://youtube.com/playlist?list=PLpM_sf_d5YTPL1iDMJNDHuEMkT0eTYkyL)
4 |
5 | ## Live Links
6 |
7 | - [Rotating cube](https://normal-cube.netlify.app/)
8 |
9 | - [Rotating cube in real world](https://xr-cube.netlify.app/)
10 |
11 | - [Cubes shown in real world using hit testing](https://xr-hit-cube.netlify.app/)
12 |
13 | - [Models shown in real world using hit testing](https://xr-hit-models.netlify.app/)
14 |
15 | - [Models shown in real world based on selected option](https://xr-domoverlay.netlify.app/)
16 |
17 | ## Credits
18 |
19 |
20 | Models taken from https://market.pmnd.rs/
21 |
22 | ### Do star the repository if you found it helpful !!
23 |
--------------------------------------------------------------------------------
/cube/normal-cube.js:
--------------------------------------------------------------------------------
1 | import * as THREE from 'three';
2 |
3 | const scene = new THREE.Scene()
4 |
5 | const sizes = {
6 | width: window.innerWidth,
7 | height: window.innerHeight
8 | }
9 |
10 | const light = new THREE.AmbientLight(0xffffff, 1.0)
11 | scene.add(light)
12 |
13 | const geometry = new THREE.BoxGeometry(1, 1, 1);
14 | const material = new THREE.MeshStandardMaterial({ color: 0xffffff * Math.random() });
15 | const cube = new THREE.Mesh(geometry, material);
16 | scene.add(cube)
17 |
18 | const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 0.1, 1000);
19 | camera.position.set(0, 2, 5);
20 | camera.lookAt(new THREE.Vector3(0, 0, 0))
21 | scene.add(camera);
22 |
23 | const renderer = new THREE.WebGLRenderer({
24 | antialias: true
25 |
26 | });
27 |
28 | renderer.setSize(sizes.width, sizes.height);
29 | renderer.setPixelRatio(window.devicePixelRatio);
30 |
31 | document.body.appendChild(renderer.domElement);
32 |
33 | renderer.setAnimationLoop(render)
34 |
35 | function render() {
36 | cube.rotation.y += 0.01;
37 | renderer.render(scene, camera)
38 | }
39 |
40 | window.addEventListener('resize', () => {
41 | sizes.width = window.innerWidth;
42 | sizes.height = window.innerHeight;
43 |
44 | camera.aspect = sizes.width / sizes.height;
45 | camera.updateProjectionMatrix();
46 |
47 | renderer.setSize(sizes.width, sizes.height);
48 | renderer.setPixelRatio(window.devicePixelRatio)
49 |
50 | })
--------------------------------------------------------------------------------
/cube/xr-cube.js:
--------------------------------------------------------------------------------
1 | import * as THREE from 'three';
2 | import { ARButton } from 'three/examples/jsm/webxr/ARButton'
3 |
4 | const scene = new THREE.Scene()
5 |
6 | const sizes = {
7 | width: window.innerWidth,
8 | height: window.innerHeight
9 | }
10 |
11 | const light = new THREE.AmbientLight(0xffffff, 1.0)
12 | scene.add(light)
13 |
14 | const geometry = new THREE.BoxGeometry(1, 1, 1);
15 | const material = new THREE.MeshStandardMaterial({ color: 0xffffff * Math.random() });
16 | const cube = new THREE.Mesh(geometry, material);
17 | cube.position.set(0, 0, -2)
18 | scene.add(cube)
19 |
20 | const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 0.1, 1000);
21 | camera.position.set(0, 2, 5);
22 | camera.lookAt(new THREE.Vector3(0, 0, 0))
23 | scene.add(camera);
24 |
25 | const renderer = new THREE.WebGLRenderer({
26 | antialias: true,
27 | alpha: true
28 |
29 | });
30 |
31 | renderer.setSize(sizes.width, sizes.height);
32 | renderer.setPixelRatio(window.devicePixelRatio);
33 | renderer.xr.enabled = true
34 |
35 | document.body.appendChild(renderer.domElement);
36 | document.body.appendChild(ARButton.createButton(renderer));
37 |
38 | renderer.setAnimationLoop(render)
39 |
40 | function render() {
41 | cube.rotation.y += 0.01;
42 | renderer.render(scene, camera)
43 | }
44 |
45 | window.addEventListener('resize', () => {
46 | sizes.width = window.innerWidth;
47 | sizes.height = window.innerHeight;
48 |
49 | camera.aspect = sizes.width / sizes.height;
50 | camera.updateProjectionMatrix();
51 |
52 | renderer.setSize(sizes.width, sizes.height);
53 | renderer.setPixelRatio(window.devicePixelRatio)
54 |
55 | })
--------------------------------------------------------------------------------
/cube/xr-hit-cube.js:
--------------------------------------------------------------------------------
1 | import * as THREE from 'three';
2 | import { ARButton } from 'three/examples/jsm/webxr/ARButton'
3 |
4 |
5 | let hitTestSource = null;
6 | let hitTestSourceRequested = false;
7 |
8 | const scene = new THREE.Scene()
9 |
10 | const sizes = {
11 | width: window.innerWidth,
12 | height: window.innerHeight
13 | }
14 |
15 | const light = new THREE.AmbientLight(0xffffff, 1.0)
16 | scene.add(light)
17 |
18 |
19 | let reticle = new THREE.Mesh(
20 | new THREE.RingGeometry(0.15, .2, 32).rotateX(-Math.PI / 2),
21 | new THREE.MeshStandardMaterial({ color: 0xffffff * Math.random() })
22 | )
23 | reticle.visible = false;
24 | reticle.matrixAutoUpdate = false;
25 | scene.add(reticle)
26 |
27 | const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 0.1, 1000);
28 | camera.position.set(0, 2, 5);
29 | camera.lookAt(new THREE.Vector3(0, 0, 0))
30 | scene.add(camera);
31 |
32 | const renderer = new THREE.WebGLRenderer({
33 | antialias: true,
34 | alpha: true
35 |
36 | });
37 |
38 | renderer.setSize(sizes.width, sizes.height);
39 | renderer.setPixelRatio(window.devicePixelRatio);
40 | renderer.xr.enabled = true
41 |
42 | document.body.appendChild(renderer.domElement);
43 | document.body.appendChild(ARButton.createButton(renderer, { requiredFeatures: ['hit-test'] }));
44 |
45 | const geometry = new THREE.BoxGeometry(1, 1, 1);
46 | const material = new THREE.MeshStandardMaterial({ color: 0xffffff * Math.random() });
47 |
48 | let controller = renderer.xr.getController(0);
49 | controller.addEventListener('select', onSelect);
50 | scene.add(controller)
51 |
52 | function onSelect() {
53 | if (reticle.visible) {
54 | const cube = new THREE.Mesh(geometry, material);
55 | cube.position.setFromMatrixPosition(reticle.matrix);
56 | cube.name = "cube"
57 | scene.add(cube)
58 | }
59 | }
60 |
61 | renderer.setAnimationLoop(render)
62 |
63 | function render(timestamp, frame) {
64 | if (frame) {
65 | const referenceSpace = renderer.xr.getReferenceSpace();
66 | const session = renderer.xr.getSession();
67 |
68 | if (hitTestSourceRequested === false) {
69 | session.requestReferenceSpace('viewer').then(referenceSpace => {
70 | session.requestHitTestSource({ space: referenceSpace }).then(source =>
71 | hitTestSource = source)
72 | })
73 |
74 | hitTestSourceRequested = true;
75 |
76 | session.addEventListener("end", () => {
77 | hitTestSourceRequested = false;
78 | hitTestSource = null;
79 | })
80 | }
81 |
82 | if (hitTestSource) {
83 | const hitTestResults = frame.getHitTestResults(hitTestSource);
84 | if (hitTestResults.length > 0) {
85 | const hit = hitTestResults[0];
86 | reticle.visible = true;
87 | reticle.matrix.fromArray(hit.getPose(referenceSpace).transform.matrix)
88 |
89 | } else {
90 | reticle.visible = false
91 |
92 | }
93 | }
94 | }
95 | // console.log(scene.children)
96 | scene.children.forEach(object => {
97 | if (object.name === "cube") {
98 | object.rotation.y += 0.01
99 | }
100 | })
101 | renderer.render(scene, camera)
102 | }
103 |
104 | window.addEventListener('resize', () => {
105 | sizes.width = window.innerWidth;
106 | sizes.height = window.innerHeight;
107 |
108 | camera.aspect = sizes.width / sizes.height;
109 | camera.updateProjectionMatrix();
110 |
111 | renderer.setSize(sizes.width, sizes.height);
112 | renderer.setPixelRatio(window.devicePixelRatio)
113 |
114 | })
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
19 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/model/xr-domOverlay.js:
--------------------------------------------------------------------------------
1 | import * as THREE from 'three';
2 | import { ARButton } from 'three/examples/jsm/webxr/ARButton'
3 | import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
4 | import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'
5 |
6 |
7 | let loadedModels = {}
8 | let hitTestSource = null;
9 | let hitTestSourceRequested = false;
10 | let overlayContent = document.getElementById('overlay-content')
11 | let selectInput = document.getElementById('model-select')
12 | let modelName = selectInput.value;
13 |
14 | selectInput.addEventListener("change", (e) => {
15 | modelName = e.target.value
16 | })
17 |
18 |
19 | let gltfLoader = new GLTFLoader();
20 | let dracoLoader = new DRACOLoader();
21 | dracoLoader.setDecoderPath('/draco/')
22 | gltfLoader.setDRACOLoader(dracoLoader)
23 |
24 |
25 | gltfLoader.load('/models/chair.gltf', onLoad);
26 | gltfLoader.load('/models/bookcase.gltf', onLoad);
27 |
28 |
29 | function onLoad(gltf) {
30 | loadedModels[gltf.scene.name] = gltf.scene
31 | }
32 |
33 |
34 | const scene = new THREE.Scene()
35 |
36 | const sizes = {
37 | width: window.innerWidth,
38 | height: window.innerHeight
39 | }
40 |
41 | const light = new THREE.AmbientLight(0xffffff, 1.0)
42 | scene.add(light)
43 |
44 |
45 | let reticle = new THREE.Mesh(
46 | new THREE.RingGeometry(0.15, .2, 32).rotateX(-Math.PI / 2),
47 | new THREE.MeshStandardMaterial({ color: 0xffffff * Math.random() })
48 | )
49 | reticle.visible = false;
50 | reticle.matrixAutoUpdate = false;
51 | scene.add(reticle)
52 |
53 | const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 0.1, 1000);
54 | camera.position.set(0, 2, 5);
55 | camera.lookAt(new THREE.Vector3(0, 0, 0))
56 | scene.add(camera);
57 |
58 | const renderer = new THREE.WebGLRenderer({
59 | antialias: true,
60 | alpha: true
61 |
62 | });
63 |
64 | renderer.setSize(sizes.width, sizes.height);
65 | renderer.setPixelRatio(window.devicePixelRatio);
66 | renderer.xr.enabled = true
67 |
68 | document.body.appendChild(renderer.domElement);
69 | document.body.appendChild(ARButton.createButton(renderer, {
70 | requiredFeatures: ['hit-test'],
71 | optionalFeatures: ['dom-overlay'],
72 | domOverlay: { root: overlayContent }
73 | }));
74 |
75 |
76 | let controller = renderer.xr.getController(0);
77 | controller.addEventListener('select', onSelect);
78 | scene.add(controller)
79 |
80 | function onSelect() {
81 | if (reticle.visible) {
82 | let model = loadedModels[modelName].clone()
83 | model.position.setFromMatrixPosition(reticle.matrix);
84 | model.scale.set(.5, .5, .5)
85 | scene.add(model)
86 | }
87 | }
88 |
89 | renderer.setAnimationLoop(render)
90 |
91 | function render(timestamp, frame) {
92 | if (frame) {
93 | const referenceSpace = renderer.xr.getReferenceSpace();
94 | const session = renderer.xr.getSession();
95 |
96 | if (hitTestSourceRequested === false) {
97 | session.requestReferenceSpace('viewer').then(referenceSpace => {
98 | session.requestHitTestSource({ space: referenceSpace }).then(source =>
99 | hitTestSource = source)
100 | })
101 |
102 | hitTestSourceRequested = true;
103 |
104 | session.addEventListener("end", () => {
105 | hitTestSourceRequested = false;
106 | hitTestSource = null;
107 | })
108 | }
109 |
110 | if (hitTestSource) {
111 | const hitTestResults = frame.getHitTestResults(hitTestSource);
112 | if (hitTestResults.length > 0) {
113 | const hit = hitTestResults[0];
114 | reticle.visible = true;
115 | reticle.matrix.fromArray(hit.getPose(referenceSpace).transform.matrix)
116 |
117 | } else {
118 | reticle.visible = false
119 |
120 | }
121 | }
122 | }
123 |
124 | renderer.render(scene, camera)
125 | }
126 |
127 | window.addEventListener('resize', () => {
128 | sizes.width = window.innerWidth;
129 | sizes.height = window.innerHeight;
130 |
131 | camera.aspect = sizes.width / sizes.height;
132 | camera.updateProjectionMatrix();
133 |
134 | renderer.setSize(sizes.width, sizes.height);
135 | renderer.setPixelRatio(window.devicePixelRatio)
136 |
137 | })
--------------------------------------------------------------------------------
/model/xr-hit-models.js:
--------------------------------------------------------------------------------
1 | import * as THREE from 'three';
2 | import { ARButton } from 'three/examples/jsm/webxr/ARButton'
3 | import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
4 |
5 |
6 | let loadedModels = [];
7 | let hitTestSource = null;
8 | let hitTestSourceRequested = false;
9 |
10 | let gltfLoader = new GLTFLoader();
11 | gltfLoader.load('/models/tree1.gltf', onLoad);
12 | gltfLoader.load('/models/tree2.gltf', onLoad);
13 | gltfLoader.load('/models/tree3.gltf', onLoad);
14 |
15 | function onLoad(gtlf) {
16 | loadedModels.push(gtlf.scene)
17 | }
18 |
19 | const scene = new THREE.Scene()
20 |
21 | const sizes = {
22 | width: window.innerWidth,
23 | height: window.innerHeight
24 | }
25 |
26 | const light = new THREE.AmbientLight(0xffffff, 1.0)
27 | scene.add(light)
28 |
29 |
30 | let reticle = new THREE.Mesh(
31 | new THREE.RingGeometry(0.15, .2, 32).rotateX(-Math.PI / 2),
32 | new THREE.MeshStandardMaterial({ color: 0xffffff * Math.random() })
33 | )
34 | reticle.visible = false;
35 | reticle.matrixAutoUpdate = false;
36 | scene.add(reticle)
37 |
38 | const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 0.1, 1000);
39 | camera.position.set(0, 2, 5);
40 | camera.lookAt(new THREE.Vector3(0, 0, 0))
41 | scene.add(camera);
42 |
43 | const renderer = new THREE.WebGLRenderer({
44 | antialias: true,
45 | alpha: true
46 |
47 | });
48 |
49 | renderer.setSize(sizes.width, sizes.height);
50 | renderer.setPixelRatio(window.devicePixelRatio);
51 | renderer.xr.enabled = true
52 |
53 | document.body.appendChild(renderer.domElement);
54 | document.body.appendChild(ARButton.createButton(renderer, { requiredFeatures: ['hit-test'] }));
55 |
56 |
57 | let controller = renderer.xr.getController(0);
58 | controller.addEventListener('select', onSelect);
59 | scene.add(controller)
60 |
61 | function onSelect() {
62 | if (reticle.visible) {
63 | let randomIndex = Math.floor((Math.random() * loadedModels.length))
64 | let model = loadedModels[randomIndex].clone()
65 | model.position.setFromMatrixPosition(reticle.matrix);
66 | model.scale.set(.1, .1, .1)
67 | model.name = "model"
68 | scene.add(model)
69 | }
70 | }
71 |
72 | renderer.setAnimationLoop(render)
73 |
74 | function render(timestamp, frame) {
75 | if (frame) {
76 | const referenceSpace = renderer.xr.getReferenceSpace();
77 | const session = renderer.xr.getSession();
78 |
79 | if (hitTestSourceRequested === false) {
80 | session.requestReferenceSpace('viewer').then(referenceSpace => {
81 | session.requestHitTestSource({ space: referenceSpace }).then(source =>
82 | hitTestSource = source)
83 | })
84 |
85 | hitTestSourceRequested = true;
86 |
87 | session.addEventListener("end", () => {
88 | hitTestSourceRequested = false;
89 | hitTestSource = null;
90 | })
91 | }
92 |
93 | if (hitTestSource) {
94 | const hitTestResults = frame.getHitTestResults(hitTestSource);
95 | if (hitTestResults.length > 0) {
96 | const hit = hitTestResults[0];
97 | reticle.visible = true;
98 | reticle.matrix.fromArray(hit.getPose(referenceSpace).transform.matrix)
99 |
100 | } else {
101 | reticle.visible = false
102 |
103 | }
104 | }
105 | }
106 | // console.log(scene.children)
107 | scene.children.forEach(object => {
108 | if (object.name === "model") {
109 | object.rotation.y += 0.01
110 | }
111 | })
112 | renderer.render(scene, camera)
113 | }
114 |
115 | window.addEventListener('resize', () => {
116 | sizes.width = window.innerWidth;
117 | sizes.height = window.innerHeight;
118 |
119 | camera.aspect = sizes.width / sizes.height;
120 | camera.updateProjectionMatrix();
121 |
122 | renderer.setSize(sizes.width, sizes.height);
123 | renderer.setPixelRatio(window.devicePixelRatio)
124 |
125 | })
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "webxr-ar",
3 | "version": "0.0.0",
4 | "lockfileVersion": 2,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "webxr-ar",
9 | "version": "0.0.0",
10 | "dependencies": {
11 | "three": "^0.147.0"
12 | },
13 | "devDependencies": {
14 | "vite": "^3.2.3"
15 | }
16 | },
17 | "node_modules/@esbuild/android-arm": {
18 | "version": "0.15.18",
19 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz",
20 | "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==",
21 | "cpu": [
22 | "arm"
23 | ],
24 | "dev": true,
25 | "optional": true,
26 | "os": [
27 | "android"
28 | ],
29 | "engines": {
30 | "node": ">=12"
31 | }
32 | },
33 | "node_modules/@esbuild/linux-loong64": {
34 | "version": "0.15.18",
35 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz",
36 | "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==",
37 | "cpu": [
38 | "loong64"
39 | ],
40 | "dev": true,
41 | "optional": true,
42 | "os": [
43 | "linux"
44 | ],
45 | "engines": {
46 | "node": ">=12"
47 | }
48 | },
49 | "node_modules/esbuild": {
50 | "version": "0.15.18",
51 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz",
52 | "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==",
53 | "dev": true,
54 | "hasInstallScript": true,
55 | "bin": {
56 | "esbuild": "bin/esbuild"
57 | },
58 | "engines": {
59 | "node": ">=12"
60 | },
61 | "optionalDependencies": {
62 | "@esbuild/android-arm": "0.15.18",
63 | "@esbuild/linux-loong64": "0.15.18",
64 | "esbuild-android-64": "0.15.18",
65 | "esbuild-android-arm64": "0.15.18",
66 | "esbuild-darwin-64": "0.15.18",
67 | "esbuild-darwin-arm64": "0.15.18",
68 | "esbuild-freebsd-64": "0.15.18",
69 | "esbuild-freebsd-arm64": "0.15.18",
70 | "esbuild-linux-32": "0.15.18",
71 | "esbuild-linux-64": "0.15.18",
72 | "esbuild-linux-arm": "0.15.18",
73 | "esbuild-linux-arm64": "0.15.18",
74 | "esbuild-linux-mips64le": "0.15.18",
75 | "esbuild-linux-ppc64le": "0.15.18",
76 | "esbuild-linux-riscv64": "0.15.18",
77 | "esbuild-linux-s390x": "0.15.18",
78 | "esbuild-netbsd-64": "0.15.18",
79 | "esbuild-openbsd-64": "0.15.18",
80 | "esbuild-sunos-64": "0.15.18",
81 | "esbuild-windows-32": "0.15.18",
82 | "esbuild-windows-64": "0.15.18",
83 | "esbuild-windows-arm64": "0.15.18"
84 | }
85 | },
86 | "node_modules/esbuild-android-64": {
87 | "version": "0.15.18",
88 | "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz",
89 | "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==",
90 | "cpu": [
91 | "x64"
92 | ],
93 | "dev": true,
94 | "optional": true,
95 | "os": [
96 | "android"
97 | ],
98 | "engines": {
99 | "node": ">=12"
100 | }
101 | },
102 | "node_modules/esbuild-android-arm64": {
103 | "version": "0.15.18",
104 | "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz",
105 | "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==",
106 | "cpu": [
107 | "arm64"
108 | ],
109 | "dev": true,
110 | "optional": true,
111 | "os": [
112 | "android"
113 | ],
114 | "engines": {
115 | "node": ">=12"
116 | }
117 | },
118 | "node_modules/esbuild-darwin-64": {
119 | "version": "0.15.18",
120 | "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz",
121 | "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==",
122 | "cpu": [
123 | "x64"
124 | ],
125 | "dev": true,
126 | "optional": true,
127 | "os": [
128 | "darwin"
129 | ],
130 | "engines": {
131 | "node": ">=12"
132 | }
133 | },
134 | "node_modules/esbuild-darwin-arm64": {
135 | "version": "0.15.18",
136 | "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz",
137 | "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==",
138 | "cpu": [
139 | "arm64"
140 | ],
141 | "dev": true,
142 | "optional": true,
143 | "os": [
144 | "darwin"
145 | ],
146 | "engines": {
147 | "node": ">=12"
148 | }
149 | },
150 | "node_modules/esbuild-freebsd-64": {
151 | "version": "0.15.18",
152 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz",
153 | "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==",
154 | "cpu": [
155 | "x64"
156 | ],
157 | "dev": true,
158 | "optional": true,
159 | "os": [
160 | "freebsd"
161 | ],
162 | "engines": {
163 | "node": ">=12"
164 | }
165 | },
166 | "node_modules/esbuild-freebsd-arm64": {
167 | "version": "0.15.18",
168 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz",
169 | "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==",
170 | "cpu": [
171 | "arm64"
172 | ],
173 | "dev": true,
174 | "optional": true,
175 | "os": [
176 | "freebsd"
177 | ],
178 | "engines": {
179 | "node": ">=12"
180 | }
181 | },
182 | "node_modules/esbuild-linux-32": {
183 | "version": "0.15.18",
184 | "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz",
185 | "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==",
186 | "cpu": [
187 | "ia32"
188 | ],
189 | "dev": true,
190 | "optional": true,
191 | "os": [
192 | "linux"
193 | ],
194 | "engines": {
195 | "node": ">=12"
196 | }
197 | },
198 | "node_modules/esbuild-linux-64": {
199 | "version": "0.15.18",
200 | "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz",
201 | "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==",
202 | "cpu": [
203 | "x64"
204 | ],
205 | "dev": true,
206 | "optional": true,
207 | "os": [
208 | "linux"
209 | ],
210 | "engines": {
211 | "node": ">=12"
212 | }
213 | },
214 | "node_modules/esbuild-linux-arm": {
215 | "version": "0.15.18",
216 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz",
217 | "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==",
218 | "cpu": [
219 | "arm"
220 | ],
221 | "dev": true,
222 | "optional": true,
223 | "os": [
224 | "linux"
225 | ],
226 | "engines": {
227 | "node": ">=12"
228 | }
229 | },
230 | "node_modules/esbuild-linux-arm64": {
231 | "version": "0.15.18",
232 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz",
233 | "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==",
234 | "cpu": [
235 | "arm64"
236 | ],
237 | "dev": true,
238 | "optional": true,
239 | "os": [
240 | "linux"
241 | ],
242 | "engines": {
243 | "node": ">=12"
244 | }
245 | },
246 | "node_modules/esbuild-linux-mips64le": {
247 | "version": "0.15.18",
248 | "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz",
249 | "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==",
250 | "cpu": [
251 | "mips64el"
252 | ],
253 | "dev": true,
254 | "optional": true,
255 | "os": [
256 | "linux"
257 | ],
258 | "engines": {
259 | "node": ">=12"
260 | }
261 | },
262 | "node_modules/esbuild-linux-ppc64le": {
263 | "version": "0.15.18",
264 | "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz",
265 | "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==",
266 | "cpu": [
267 | "ppc64"
268 | ],
269 | "dev": true,
270 | "optional": true,
271 | "os": [
272 | "linux"
273 | ],
274 | "engines": {
275 | "node": ">=12"
276 | }
277 | },
278 | "node_modules/esbuild-linux-riscv64": {
279 | "version": "0.15.18",
280 | "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz",
281 | "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==",
282 | "cpu": [
283 | "riscv64"
284 | ],
285 | "dev": true,
286 | "optional": true,
287 | "os": [
288 | "linux"
289 | ],
290 | "engines": {
291 | "node": ">=12"
292 | }
293 | },
294 | "node_modules/esbuild-linux-s390x": {
295 | "version": "0.15.18",
296 | "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz",
297 | "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==",
298 | "cpu": [
299 | "s390x"
300 | ],
301 | "dev": true,
302 | "optional": true,
303 | "os": [
304 | "linux"
305 | ],
306 | "engines": {
307 | "node": ">=12"
308 | }
309 | },
310 | "node_modules/esbuild-netbsd-64": {
311 | "version": "0.15.18",
312 | "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz",
313 | "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==",
314 | "cpu": [
315 | "x64"
316 | ],
317 | "dev": true,
318 | "optional": true,
319 | "os": [
320 | "netbsd"
321 | ],
322 | "engines": {
323 | "node": ">=12"
324 | }
325 | },
326 | "node_modules/esbuild-openbsd-64": {
327 | "version": "0.15.18",
328 | "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz",
329 | "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==",
330 | "cpu": [
331 | "x64"
332 | ],
333 | "dev": true,
334 | "optional": true,
335 | "os": [
336 | "openbsd"
337 | ],
338 | "engines": {
339 | "node": ">=12"
340 | }
341 | },
342 | "node_modules/esbuild-sunos-64": {
343 | "version": "0.15.18",
344 | "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz",
345 | "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==",
346 | "cpu": [
347 | "x64"
348 | ],
349 | "dev": true,
350 | "optional": true,
351 | "os": [
352 | "sunos"
353 | ],
354 | "engines": {
355 | "node": ">=12"
356 | }
357 | },
358 | "node_modules/esbuild-windows-32": {
359 | "version": "0.15.18",
360 | "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz",
361 | "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==",
362 | "cpu": [
363 | "ia32"
364 | ],
365 | "dev": true,
366 | "optional": true,
367 | "os": [
368 | "win32"
369 | ],
370 | "engines": {
371 | "node": ">=12"
372 | }
373 | },
374 | "node_modules/esbuild-windows-64": {
375 | "version": "0.15.18",
376 | "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz",
377 | "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==",
378 | "cpu": [
379 | "x64"
380 | ],
381 | "dev": true,
382 | "optional": true,
383 | "os": [
384 | "win32"
385 | ],
386 | "engines": {
387 | "node": ">=12"
388 | }
389 | },
390 | "node_modules/esbuild-windows-arm64": {
391 | "version": "0.15.18",
392 | "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz",
393 | "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==",
394 | "cpu": [
395 | "arm64"
396 | ],
397 | "dev": true,
398 | "optional": true,
399 | "os": [
400 | "win32"
401 | ],
402 | "engines": {
403 | "node": ">=12"
404 | }
405 | },
406 | "node_modules/fsevents": {
407 | "version": "2.3.2",
408 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
409 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
410 | "dev": true,
411 | "hasInstallScript": true,
412 | "optional": true,
413 | "os": [
414 | "darwin"
415 | ],
416 | "engines": {
417 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
418 | }
419 | },
420 | "node_modules/function-bind": {
421 | "version": "1.1.1",
422 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
423 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
424 | "dev": true
425 | },
426 | "node_modules/has": {
427 | "version": "1.0.3",
428 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
429 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
430 | "dev": true,
431 | "dependencies": {
432 | "function-bind": "^1.1.1"
433 | },
434 | "engines": {
435 | "node": ">= 0.4.0"
436 | }
437 | },
438 | "node_modules/is-core-module": {
439 | "version": "2.11.0",
440 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
441 | "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
442 | "dev": true,
443 | "dependencies": {
444 | "has": "^1.0.3"
445 | },
446 | "funding": {
447 | "url": "https://github.com/sponsors/ljharb"
448 | }
449 | },
450 | "node_modules/nanoid": {
451 | "version": "3.3.4",
452 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
453 | "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
454 | "dev": true,
455 | "bin": {
456 | "nanoid": "bin/nanoid.cjs"
457 | },
458 | "engines": {
459 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
460 | }
461 | },
462 | "node_modules/path-parse": {
463 | "version": "1.0.7",
464 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
465 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
466 | "dev": true
467 | },
468 | "node_modules/picocolors": {
469 | "version": "1.0.0",
470 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
471 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
472 | "dev": true
473 | },
474 | "node_modules/postcss": {
475 | "version": "8.4.19",
476 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.19.tgz",
477 | "integrity": "sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA==",
478 | "dev": true,
479 | "funding": [
480 | {
481 | "type": "opencollective",
482 | "url": "https://opencollective.com/postcss/"
483 | },
484 | {
485 | "type": "tidelift",
486 | "url": "https://tidelift.com/funding/github/npm/postcss"
487 | }
488 | ],
489 | "dependencies": {
490 | "nanoid": "^3.3.4",
491 | "picocolors": "^1.0.0",
492 | "source-map-js": "^1.0.2"
493 | },
494 | "engines": {
495 | "node": "^10 || ^12 || >=14"
496 | }
497 | },
498 | "node_modules/resolve": {
499 | "version": "1.22.1",
500 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
501 | "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
502 | "dev": true,
503 | "dependencies": {
504 | "is-core-module": "^2.9.0",
505 | "path-parse": "^1.0.7",
506 | "supports-preserve-symlinks-flag": "^1.0.0"
507 | },
508 | "bin": {
509 | "resolve": "bin/resolve"
510 | },
511 | "funding": {
512 | "url": "https://github.com/sponsors/ljharb"
513 | }
514 | },
515 | "node_modules/rollup": {
516 | "version": "2.79.1",
517 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
518 | "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==",
519 | "dev": true,
520 | "bin": {
521 | "rollup": "dist/bin/rollup"
522 | },
523 | "engines": {
524 | "node": ">=10.0.0"
525 | },
526 | "optionalDependencies": {
527 | "fsevents": "~2.3.2"
528 | }
529 | },
530 | "node_modules/source-map-js": {
531 | "version": "1.0.2",
532 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
533 | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
534 | "dev": true,
535 | "engines": {
536 | "node": ">=0.10.0"
537 | }
538 | },
539 | "node_modules/supports-preserve-symlinks-flag": {
540 | "version": "1.0.0",
541 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
542 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
543 | "dev": true,
544 | "engines": {
545 | "node": ">= 0.4"
546 | },
547 | "funding": {
548 | "url": "https://github.com/sponsors/ljharb"
549 | }
550 | },
551 | "node_modules/three": {
552 | "version": "0.147.0",
553 | "resolved": "https://registry.npmjs.org/three/-/three-0.147.0.tgz",
554 | "integrity": "sha512-LPTOslYQXFkmvceQjFTNnVVli2LaVF6C99Pv34fJypp8NbQLbTlu3KinZ0zURghS5zEehK+VQyvWuPZ/Sm8fzw=="
555 | },
556 | "node_modules/vite": {
557 | "version": "3.2.5",
558 | "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.5.tgz",
559 | "integrity": "sha512-4mVEpXpSOgrssFZAOmGIr85wPHKvaDAcXqxVxVRZhljkJOMZi1ibLibzjLHzJvcok8BMguLc7g1W6W/GqZbLdQ==",
560 | "dev": true,
561 | "dependencies": {
562 | "esbuild": "^0.15.9",
563 | "postcss": "^8.4.18",
564 | "resolve": "^1.22.1",
565 | "rollup": "^2.79.1"
566 | },
567 | "bin": {
568 | "vite": "bin/vite.js"
569 | },
570 | "engines": {
571 | "node": "^14.18.0 || >=16.0.0"
572 | },
573 | "optionalDependencies": {
574 | "fsevents": "~2.3.2"
575 | },
576 | "peerDependencies": {
577 | "@types/node": ">= 14",
578 | "less": "*",
579 | "sass": "*",
580 | "stylus": "*",
581 | "sugarss": "*",
582 | "terser": "^5.4.0"
583 | },
584 | "peerDependenciesMeta": {
585 | "@types/node": {
586 | "optional": true
587 | },
588 | "less": {
589 | "optional": true
590 | },
591 | "sass": {
592 | "optional": true
593 | },
594 | "stylus": {
595 | "optional": true
596 | },
597 | "sugarss": {
598 | "optional": true
599 | },
600 | "terser": {
601 | "optional": true
602 | }
603 | }
604 | }
605 | },
606 | "dependencies": {
607 | "@esbuild/android-arm": {
608 | "version": "0.15.18",
609 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz",
610 | "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==",
611 | "dev": true,
612 | "optional": true
613 | },
614 | "@esbuild/linux-loong64": {
615 | "version": "0.15.18",
616 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz",
617 | "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==",
618 | "dev": true,
619 | "optional": true
620 | },
621 | "esbuild": {
622 | "version": "0.15.18",
623 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz",
624 | "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==",
625 | "dev": true,
626 | "requires": {
627 | "@esbuild/android-arm": "0.15.18",
628 | "@esbuild/linux-loong64": "0.15.18",
629 | "esbuild-android-64": "0.15.18",
630 | "esbuild-android-arm64": "0.15.18",
631 | "esbuild-darwin-64": "0.15.18",
632 | "esbuild-darwin-arm64": "0.15.18",
633 | "esbuild-freebsd-64": "0.15.18",
634 | "esbuild-freebsd-arm64": "0.15.18",
635 | "esbuild-linux-32": "0.15.18",
636 | "esbuild-linux-64": "0.15.18",
637 | "esbuild-linux-arm": "0.15.18",
638 | "esbuild-linux-arm64": "0.15.18",
639 | "esbuild-linux-mips64le": "0.15.18",
640 | "esbuild-linux-ppc64le": "0.15.18",
641 | "esbuild-linux-riscv64": "0.15.18",
642 | "esbuild-linux-s390x": "0.15.18",
643 | "esbuild-netbsd-64": "0.15.18",
644 | "esbuild-openbsd-64": "0.15.18",
645 | "esbuild-sunos-64": "0.15.18",
646 | "esbuild-windows-32": "0.15.18",
647 | "esbuild-windows-64": "0.15.18",
648 | "esbuild-windows-arm64": "0.15.18"
649 | }
650 | },
651 | "esbuild-android-64": {
652 | "version": "0.15.18",
653 | "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz",
654 | "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==",
655 | "dev": true,
656 | "optional": true
657 | },
658 | "esbuild-android-arm64": {
659 | "version": "0.15.18",
660 | "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz",
661 | "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==",
662 | "dev": true,
663 | "optional": true
664 | },
665 | "esbuild-darwin-64": {
666 | "version": "0.15.18",
667 | "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz",
668 | "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==",
669 | "dev": true,
670 | "optional": true
671 | },
672 | "esbuild-darwin-arm64": {
673 | "version": "0.15.18",
674 | "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz",
675 | "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==",
676 | "dev": true,
677 | "optional": true
678 | },
679 | "esbuild-freebsd-64": {
680 | "version": "0.15.18",
681 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz",
682 | "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==",
683 | "dev": true,
684 | "optional": true
685 | },
686 | "esbuild-freebsd-arm64": {
687 | "version": "0.15.18",
688 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz",
689 | "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==",
690 | "dev": true,
691 | "optional": true
692 | },
693 | "esbuild-linux-32": {
694 | "version": "0.15.18",
695 | "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz",
696 | "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==",
697 | "dev": true,
698 | "optional": true
699 | },
700 | "esbuild-linux-64": {
701 | "version": "0.15.18",
702 | "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz",
703 | "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==",
704 | "dev": true,
705 | "optional": true
706 | },
707 | "esbuild-linux-arm": {
708 | "version": "0.15.18",
709 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz",
710 | "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==",
711 | "dev": true,
712 | "optional": true
713 | },
714 | "esbuild-linux-arm64": {
715 | "version": "0.15.18",
716 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz",
717 | "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==",
718 | "dev": true,
719 | "optional": true
720 | },
721 | "esbuild-linux-mips64le": {
722 | "version": "0.15.18",
723 | "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz",
724 | "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==",
725 | "dev": true,
726 | "optional": true
727 | },
728 | "esbuild-linux-ppc64le": {
729 | "version": "0.15.18",
730 | "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz",
731 | "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==",
732 | "dev": true,
733 | "optional": true
734 | },
735 | "esbuild-linux-riscv64": {
736 | "version": "0.15.18",
737 | "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz",
738 | "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==",
739 | "dev": true,
740 | "optional": true
741 | },
742 | "esbuild-linux-s390x": {
743 | "version": "0.15.18",
744 | "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz",
745 | "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==",
746 | "dev": true,
747 | "optional": true
748 | },
749 | "esbuild-netbsd-64": {
750 | "version": "0.15.18",
751 | "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz",
752 | "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==",
753 | "dev": true,
754 | "optional": true
755 | },
756 | "esbuild-openbsd-64": {
757 | "version": "0.15.18",
758 | "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz",
759 | "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==",
760 | "dev": true,
761 | "optional": true
762 | },
763 | "esbuild-sunos-64": {
764 | "version": "0.15.18",
765 | "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz",
766 | "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==",
767 | "dev": true,
768 | "optional": true
769 | },
770 | "esbuild-windows-32": {
771 | "version": "0.15.18",
772 | "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz",
773 | "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==",
774 | "dev": true,
775 | "optional": true
776 | },
777 | "esbuild-windows-64": {
778 | "version": "0.15.18",
779 | "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz",
780 | "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==",
781 | "dev": true,
782 | "optional": true
783 | },
784 | "esbuild-windows-arm64": {
785 | "version": "0.15.18",
786 | "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz",
787 | "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==",
788 | "dev": true,
789 | "optional": true
790 | },
791 | "fsevents": {
792 | "version": "2.3.2",
793 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
794 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
795 | "dev": true,
796 | "optional": true
797 | },
798 | "function-bind": {
799 | "version": "1.1.1",
800 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
801 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
802 | "dev": true
803 | },
804 | "has": {
805 | "version": "1.0.3",
806 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
807 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
808 | "dev": true,
809 | "requires": {
810 | "function-bind": "^1.1.1"
811 | }
812 | },
813 | "is-core-module": {
814 | "version": "2.11.0",
815 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
816 | "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
817 | "dev": true,
818 | "requires": {
819 | "has": "^1.0.3"
820 | }
821 | },
822 | "nanoid": {
823 | "version": "3.3.4",
824 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
825 | "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
826 | "dev": true
827 | },
828 | "path-parse": {
829 | "version": "1.0.7",
830 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
831 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
832 | "dev": true
833 | },
834 | "picocolors": {
835 | "version": "1.0.0",
836 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
837 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
838 | "dev": true
839 | },
840 | "postcss": {
841 | "version": "8.4.19",
842 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.19.tgz",
843 | "integrity": "sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA==",
844 | "dev": true,
845 | "requires": {
846 | "nanoid": "^3.3.4",
847 | "picocolors": "^1.0.0",
848 | "source-map-js": "^1.0.2"
849 | }
850 | },
851 | "resolve": {
852 | "version": "1.22.1",
853 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
854 | "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
855 | "dev": true,
856 | "requires": {
857 | "is-core-module": "^2.9.0",
858 | "path-parse": "^1.0.7",
859 | "supports-preserve-symlinks-flag": "^1.0.0"
860 | }
861 | },
862 | "rollup": {
863 | "version": "2.79.1",
864 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
865 | "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==",
866 | "dev": true,
867 | "requires": {
868 | "fsevents": "~2.3.2"
869 | }
870 | },
871 | "source-map-js": {
872 | "version": "1.0.2",
873 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
874 | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
875 | "dev": true
876 | },
877 | "supports-preserve-symlinks-flag": {
878 | "version": "1.0.0",
879 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
880 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
881 | "dev": true
882 | },
883 | "three": {
884 | "version": "0.147.0",
885 | "resolved": "https://registry.npmjs.org/three/-/three-0.147.0.tgz",
886 | "integrity": "sha512-LPTOslYQXFkmvceQjFTNnVVli2LaVF6C99Pv34fJypp8NbQLbTlu3KinZ0zURghS5zEehK+VQyvWuPZ/Sm8fzw=="
887 | },
888 | "vite": {
889 | "version": "3.2.5",
890 | "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.5.tgz",
891 | "integrity": "sha512-4mVEpXpSOgrssFZAOmGIr85wPHKvaDAcXqxVxVRZhljkJOMZi1ibLibzjLHzJvcok8BMguLc7g1W6W/GqZbLdQ==",
892 | "dev": true,
893 | "requires": {
894 | "esbuild": "^0.15.9",
895 | "fsevents": "~2.3.2",
896 | "postcss": "^8.4.18",
897 | "resolve": "^1.22.1",
898 | "rollup": "^2.79.1"
899 | }
900 | }
901 | }
902 | }
903 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "webxr-ar",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "preview": "vite preview"
10 | },
11 | "devDependencies": {
12 | "vite": "^3.2.3"
13 | },
14 | "dependencies": {
15 | "three": "^0.147.0"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/public/draco/README.md:
--------------------------------------------------------------------------------
1 | # Draco 3D Data Compression
2 |
3 | Draco is an open-source library for compressing and decompressing 3D geometric meshes and point clouds. It is intended to improve the storage and transmission of 3D graphics.
4 |
5 | [Website](https://google.github.io/draco/) | [GitHub](https://github.com/google/draco)
6 |
7 | ## Contents
8 |
9 | This folder contains three utilities:
10 |
11 | * `draco_decoder.js` — Emscripten-compiled decoder, compatible with any modern browser.
12 | * `draco_decoder.wasm` — WebAssembly decoder, compatible with newer browsers and devices.
13 | * `draco_wasm_wrapper.js` — JavaScript wrapper for the WASM decoder.
14 |
15 | Each file is provided in two variations:
16 |
17 | * **Default:** Latest stable builds, tracking the project's [master branch](https://github.com/google/draco).
18 | * **glTF:** Builds targeted by the [glTF mesh compression extension](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression), tracking the [corresponding Draco branch](https://github.com/google/draco/tree/gltf_2.0_draco_extension).
19 |
20 | Either variation may be used with `THREE.DRACOLoader`:
21 |
22 | ```js
23 | var dracoLoader = new THREE.DRACOLoader();
24 | dracoLoader.setDecoderPath('path/to/decoders/');
25 | dracoLoader.setDecoderConfig({type: 'js'}); // (Optional) Override detection of WASM support.
26 | ```
27 |
28 | Further [documentation on GitHub](https://github.com/google/draco/tree/master/javascript/example#static-loading-javascript-decoder).
29 |
30 | ## License
31 |
32 | [Apache License 2.0](https://github.com/google/draco/blob/master/LICENSE)
33 |
--------------------------------------------------------------------------------
/public/draco/draco_decoder.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohitkumartoshniwal/threejs-webxr-ar/037500d8f856052724332271412c7bbe0543374a/public/draco/draco_decoder.wasm
--------------------------------------------------------------------------------
/public/draco/draco_wasm_wrapper.js:
--------------------------------------------------------------------------------
1 | var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.arrayIteratorImpl=function(f){var m=0;return function(){return m