├── .DS_Store ├── .gitattributes ├── .gitignore ├── README.md ├── index.html ├── main.js ├── modules ├── VRSupport.js ├── audioGuide.js ├── bench.js ├── boundingBox.js ├── ceiling.js ├── ceilingLamp.js ├── clickHandling.js ├── eventListeners.js ├── floor.js ├── lighting.js ├── menu.js ├── movement.js ├── paintingData.js ├── paintingInfo.js ├── paintings.js ├── rendering.js ├── scene.js ├── sceneHelpers.js ├── statue.js └── walls.js ├── package-lock.json ├── package.json ├── public ├── .DS_Store ├── OfficeCeiling005_4K-JPG │ ├── OfficeCeiling005_4K-JPG.usda │ ├── OfficeCeiling005_4K-JPG.usdc │ ├── OfficeCeiling005_4K_AmbientOcclusion.jpg │ ├── OfficeCeiling005_4K_Color.jpg │ ├── OfficeCeiling005_4K_Displacement.jpg │ ├── OfficeCeiling005_4K_Emission.jpg │ ├── OfficeCeiling005_4K_Metalness.jpg │ ├── OfficeCeiling005_4K_NormalDX.jpg │ ├── OfficeCeiling005_4K_NormalGL.jpg │ ├── OfficeCeiling005_4K_Roughness.jpg │ └── OfficeCeiling005_PREVIEW.jpg ├── WoodFloor040_4K-JPG │ ├── WoodFloor040_4K-JPG.usda │ ├── WoodFloor040_4K-JPG.usdc │ ├── WoodFloor040_4K_AmbientOcclusion.jpg │ ├── WoodFloor040_4K_Color.jpg │ ├── WoodFloor040_4K_Displacement.jpg │ ├── WoodFloor040_4K_NormalDX.jpg │ ├── WoodFloor040_4K_NormalGL.jpg │ ├── WoodFloor040_4K_Roughness.jpg │ └── WoodFloor040_PREVIEW.jpg ├── artworks │ ├── 0.jpg │ ├── 1.jpg │ ├── 10.jpg │ ├── 11.jpg │ ├── 12.jpg │ ├── 13.jpg │ ├── 14.jpg │ ├── 15.jpg │ ├── 16.jpg │ ├── 17.jpg │ ├── 18.jpg │ ├── 19.jpg │ ├── 2.jpg │ ├── 20.jpg │ ├── 21.jpg │ ├── 22.jpg │ ├── 23.jpg │ ├── 24.jpg │ ├── 25.jpg │ ├── 26.jpg │ ├── 27.jpg │ ├── 28.jpg │ ├── 29.jpg │ ├── 3.jpg │ ├── 4.jpg │ ├── 5.jpg │ ├── 6.jpg │ ├── 7.jpg │ ├── 8.jpg │ └── 9.jpg ├── img │ ├── Floor.jpg │ ├── brick-wall-painted-white.jpg │ ├── ceiling.jpg │ ├── concrete-wall.jpg │ ├── floor.png │ ├── frame.jpg │ ├── glass-background-with-grid-pattern.jpg │ ├── light-gray-concrete-wall.jpg │ ├── starrynight.jpg │ ├── wall.jpg │ └── white-texture.jpg ├── leather_white_4k.gltf │ ├── .DS_Store │ ├── leather_white.bin │ ├── leather_white_4k.gltf │ └── textures │ │ ├── leather_white_diff_4k.jpg │ │ ├── leather_white_nor_gl_4k.jpg │ │ └── leather_white_rough_4k.jpg ├── models │ ├── .DS_Store │ ├── bench │ │ ├── license.txt │ │ ├── scene.bin │ │ ├── scene.gltf │ │ └── textures │ │ │ ├── Stainless_Steel_diffuse.jpeg │ │ │ ├── Stainless_Steel_normal.jpeg │ │ │ ├── Stainless_Steel_specularGlossiness.png │ │ │ ├── Wood_diffuse.jpeg │ │ │ ├── Wood_normal.jpeg │ │ │ └── Wood_specularGlossiness.png │ ├── bench_2 │ │ ├── license.txt │ │ ├── scene.bin │ │ ├── scene.gltf │ │ └── textures │ │ │ ├── Luca3D_Modern_Bench_2_baseColor.png │ │ │ ├── Luca3D_Modern_Bench_2_metallicRoughness.png │ │ │ └── Luca3D_Modern_Bench_2_normal.png │ ├── ceiling-lamp │ │ ├── license.txt │ │ ├── scene.bin │ │ ├── scene.gltf │ │ └── textures │ │ │ └── Madeira_baseColor.jpeg │ └── statue │ │ ├── license.txt │ │ ├── scene.bin │ │ └── scene.gltf └── sounds │ └── tiersen.mp3 ├── style.css └── vite.config.js /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/.DS_Store -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.psd filter=lfs diff=lfs merge=lfs -text 2 | *.jpg filter=lfs diff=lfs merge=lfs -text 3 | *.png filter=lfs diff=lfs merge=lfs -text 4 | *.gltf filter=lfs diff=lfs merge=lfs -text 5 | *.bin filter=lfs diff=lfs merge=lfs -text 6 | *.glb filter=lfs diff=lfs merge=lfs -text -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependency directories 2 | node_modules/ 3 | jspm_packages/ 4 | 5 | # dotenv environment variable files 6 | .env 7 | .env.development.local 8 | .env.test.local 9 | .env.production.local 10 | .env.local -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 3D Art Gallery Tutorial using Three.js 2 | 3 | I made this live coding tutorial about "how to create an interactive 3D Art Gallery using Three.js". This project is perfect for artists or designers to exhibit their artwork portfolios or projects. The full tutorial is almost 8 hours long, and is divided into parts. Please consider subscribing to my YouTube channel if you are interested. 4 | 5 | ## HELP! 6 | First of all, use GitHub commits to mark our progress, so you can easily follow along and see the project evolve. So, to use the initial exact Three.js module I am using, go to "Commits" section of the GitHub repository and scroll down to the first commits, and download that version of the code, then step by step review and compare the other versions of the code. 7 | If you don't know how to do that, follow these instructions: 8 | 9 | Go to my repository, click "commits", you will see all the commits list. Then scroll down to the first commit. On the right side of each commit name, you will see three small icons: 10 | - a code number --> which if you hover on it says "view commit details". 11 | - a two square icon --> which if you hover says "view full SHA" 12 | - '< >' this icon --> which if you hover on says "browse repository at this point". 13 | 14 | Click this last icon I mentioned, '< >'. You will be redirected to the exact point in time of this project. You can then download the repository as you normally do with the green button "Code". 15 | 16 | ## UPDATE! 17 | 18 | Dear followers and enthusiasts, 19 | 20 | I've been made aware of an issue many of you faced regarding the floor and ceiling textures appearing black. After a thorough investigation, I've identified the root of the problem. The high-resolution 4K textures we recently introduced are relatively large files. To manage such large files, GitHub uses a system called Large File Storage (LFS). However, there's a storage quota associated with LFS, and it seems we've reached that limit. This led to the textures not being stored correctly, resulting in broken image links in the downloaded projects. 21 | 22 | The solution at the moment: 23 | Download the 4K textures (or 2K /1K for better performance. I am currently using the 1K textures) and the 3D models yourself and add them in your project woth the correct path. 24 | 25 | The Office Ceiling material in 4K: 26 | https://ambientcg.com/view?id=OfficeCeiling005 27 | 28 | The Wood Floor in 4K: 29 | https://ambientcg.com/view?id=WoodFloor040 30 | 31 | The Walls in 4K: 32 | https://polyhaven.com/a/leather_white 33 | 34 | 3D Model Statue: 35 | https://sketchfab.com/3d-models/100kz11-aphrodite-kallipygos-statuette-c01ba617ec83491195146583b70e3df9 36 | 37 | ## Installation 38 | 39 | You need Node.js installed on your computer. 40 | And VSCode as an Editor. 41 | Download link: 42 | 43 | - https://nodejs.org 44 | - https://code.visualstudio.com/Download 45 | 46 | After cloning, or downloading the zip file, on GitHub (green button `<> Code`) open your terminal, and run: 47 | 48 | ```bash 49 | npm install 50 | ``` 51 | 52 | to install all the dependencies. 53 | "node_modules" folder will appear at the left in the Explorer files in VsCode. 54 | 55 | Then run: 56 | 57 | ```bash 58 | npx vite 59 | ``` 60 | 61 | to run the local server. 62 | You'll see the URL address and the info help. Like for example: 63 | 64 | ```bash 65 | VITE v4.3.1 ready in 1759 ms 66 | 67 | ➜ Local: http://123.4.5.6:7890/ 68 | ➜ Network: use --host to expose ➜ press h to show help 69 | ``` 70 | 71 | Screenshot 2024-03-23 at 23 03 41 72 | 73 | Screenshot 2024-03-23 at 23 01 41 74 | 75 | Screenshot 2024-03-23 at 20 16 09 76 | 77 | 78 | Screenshot 2024-03-22 at 18 51 31 79 | 80 | 81 | 82 | 83 | ## YouTube Video 84 | 85 | [Click here!](https://youtu.be/vfMizAmPprs) 86 | 87 | ## Authors 88 | 89 | - [Emilian Kasemi](https://www.github.com/theringsofsaturn) 90 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 3D Art Gallery 7 | 8 | 9 | 10 | 11 | 12 | 43 | 44 |
45 | 46 |

About the 3D Art Gallery

47 |

48 | Welcome to our virtual 3D Art Gallery. Here, you can navigate through a 49 | variety of wonderful artworks and learn about their history and 50 | significance. 51 |

52 |

53 | This project is brought to you by Emilian Kasemi. We believe in the 54 | power of art to inspire, provoke thought, and communicate across 55 | cultures and epochs. Our mission is to make art accessible to everyone, 56 | regardless of location or background. 57 |

58 |

59 | Feel free to explore and engage with the artworks. The gallery is best 60 | experienced in full-screen mode. For optimal navigation, use the arrow 61 | keys or the W, A, S, and D keys. You can also use your mouse to change 62 | the viewing direction. Additional information about the artworks will 63 | appear on your screen as you approach them. 64 |

65 |
66 | 67 |
68 |
69 |

Controls

70 | 71 |
72 |
73 |

W/A/S/D: Move around

74 |

Mouse: Look around

75 |

Space: Toggle pointer lock

76 |

M: Show Menu

77 |

Enter: Start exploration

78 |

Esc: Stop exploration

79 |

G: Start audio guide

80 |

P: Stop audio guide

81 |
82 |
83 | 84 |
85 | 86 | 87 |
88 | 89 |
90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | import * as THREE from "three"; 2 | import { scene, setupScene } from "./modules/scene.js"; 3 | import { createPaintings } from "./modules/paintings.js"; 4 | import { createWalls } from "./modules/walls.js"; 5 | import { setupLighting } from "./modules/lighting.js"; 6 | import { setupFloor } from "./modules/floor.js"; 7 | import { createCeiling } from "./modules/ceiling.js"; 8 | import { createBoundingBoxes } from "./modules/boundingBox.js"; 9 | import { setupRendering } from "./modules/rendering.js"; 10 | import { setupEventListeners } from "./modules/eventListeners.js"; 11 | import { addObjectsToScene } from "./modules/sceneHelpers.js"; 12 | import { setupPlayButton } from "./modules/menu.js"; 13 | import { setupAudio } from "./modules/audioGuide.js"; 14 | import { clickHandling } from "./modules/clickHandling.js"; 15 | import { setupVR } from "./modules/VRSupport.js"; 16 | import { loadStatueModel } from "./modules/statue.js"; 17 | import { loadBenchModel } from "./modules/bench.js"; 18 | import { loadCeilingLampModel } from "./modules/ceilingLamp.js"; 19 | 20 | let { camera, controls, renderer } = setupScene(); 21 | 22 | setupAudio(camera); 23 | 24 | const textureLoader = new THREE.TextureLoader(); 25 | 26 | const walls = createWalls(scene, textureLoader); 27 | const floor = setupFloor(scene); 28 | const ceiling = createCeiling(scene, textureLoader); 29 | const paintings = createPaintings(scene, textureLoader); 30 | const lighting = setupLighting(scene, paintings); 31 | 32 | createBoundingBoxes(walls); 33 | createBoundingBoxes(paintings); 34 | 35 | addObjectsToScene(scene, paintings); 36 | 37 | setupPlayButton(controls); 38 | 39 | setupEventListeners(controls); 40 | 41 | clickHandling(renderer, camera, paintings); 42 | 43 | setupRendering(scene, camera, renderer, paintings, controls, walls); 44 | 45 | loadStatueModel(scene); 46 | 47 | loadBenchModel(scene); 48 | 49 | loadCeilingLampModel(scene); 50 | 51 | setupVR(renderer); 52 | -------------------------------------------------------------------------------- /modules/VRSupport.js: -------------------------------------------------------------------------------- 1 | import { VRButton } from "three/examples/jsm/webxr/VRButton.js"; 2 | 3 | export const setupVR = (renderer) => { 4 | renderer.xr.enabled = true; 5 | 6 | renderer.xr.addEventListener("sessionstart", () => { 7 | console.log("WebXR session started"); 8 | }); 9 | 10 | renderer.xr.addEventListener("sessionend", () => { 11 | console.log("WebXR session ended"); 12 | }); 13 | 14 | document.body.appendChild(VRButton.createButton(renderer)); 15 | }; 16 | -------------------------------------------------------------------------------- /modules/audioGuide.js: -------------------------------------------------------------------------------- 1 | import * as THREE from "three"; 2 | 3 | let sound; 4 | let bufferLoaded = false; // flag to track if audio buffer is loaded 5 | 6 | // setup audio for the scene 7 | export const setupAudio = (camera) => { 8 | // create an audio listener and add it to the camera 9 | const listener = new THREE.AudioListener(); 10 | camera.add(listener); 11 | 12 | sound = new THREE.Audio(listener); // creating the audio source 13 | 14 | const audioLoader = new THREE.AudioLoader(); // create an audio loader 15 | audioLoader.load("sounds/tiersen.mp3", function (buffer) { 16 | // load the audio file 17 | sound.setBuffer(buffer); // set the audio source buffer 18 | sound.setLoop(true); // set the audio source to loop 19 | sound.setVolume(0.5); // set the audio source volume 20 | bufferLoaded = true; // set bufferLoaded flag to true once the audio buffer is loaded 21 | }); 22 | }; 23 | 24 | // play audio 25 | export const startAudio = () => { 26 | if (sound && bufferLoaded) { 27 | // check if the buffer is loaded before playing 28 | sound.play(); 29 | } 30 | }; 31 | 32 | // pause audio 33 | export const stopAudio = () => { 34 | if (sound) { 35 | sound.pause(); 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /modules/bench.js: -------------------------------------------------------------------------------- 1 | import * as THREE from "three"; 2 | import { GLTFLoader } from "three/addons/loaders/GLTFLoader"; 3 | import { GUI } from "lil-gui"; 4 | 5 | export const loadBenchModel = (scene) => { 6 | const loader = new GLTFLoader(); 7 | const gui = new GUI(); 8 | 9 | loader.load("../public/models/bench_2/scene.gltf", (gltf) => { 10 | const bench = gltf.scene; 11 | console.log("BENCH", gltf); 12 | 13 | // Iterate through all the meshes in the bench and update their materials 14 | bench.traverse((child) => { 15 | if (child.isMesh) { 16 | console.log("Materials:", child.material); 17 | console.log("Map Material", child.material.map); 18 | console.log("Material Name:", child.material.name); 19 | console.log("Material Type:", child.material.type); 20 | console.log("UV attributes:", child.geometry.attributes.uv); 21 | } 22 | undefined, 23 | (error) => { 24 | console.error( 25 | "An error occurred while loading the bench model.", 26 | error 27 | ); 28 | }; 29 | }); 30 | 31 | // Default Position and Scale 32 | bench.position.set(0, -3.12, -8); 33 | bench.rotation.set(0, 0, 0); 34 | bench.scale.set(3, 3, 3); 35 | 36 | // Add the bench to the scene 37 | scene.add(bench); 38 | }); 39 | }; 40 | -------------------------------------------------------------------------------- /modules/boundingBox.js: -------------------------------------------------------------------------------- 1 | import * as THREE from 'three'; 2 | 3 | // check if objects is an array. If it's not, we assume it's a THREE.Group and set objects to objects.children. We then use forEach to loop over each object in objects and add a bounding box to it 4 | export const createBoundingBoxes = (objects) => { 5 | // objects will be either paintings or walls that we pass in from main.js 6 | if (!Array.isArray(objects)) { 7 | objects = objects.children; 8 | } 9 | 10 | objects.forEach((object) => { 11 | object.BoundingBox = new THREE.Box3(); // create a new bounding box for each object 12 | object.BoundingBox.setFromObject(object); // set the bounding box to the object (painting or wall) 13 | }); 14 | }; 15 | 16 | // Note: Without the checking won't work! 17 | // if (!Array.isArray(objects)) { 18 | // objects = objects.children; 19 | // } 20 | 21 | // Checking for both THREE.Group and arrays is because the `createWalls` function is returning a THREE.Group while `createPaintings` is returning an array. 22 | 23 | // In Three.js, a THREE.Group is a type of object used to create hierarchical (parent-child) relationships between objects. In other words, a Group is an object that can contain other objects. This is useful if we want to manipulate several objects as one. 24 | 25 | // The children property of a Group is an array that contains all the objects (child objects) that have been added to the group. So when we add an object to a group with group.add(object), we can access that object later with group.children. 26 | 27 | // In our code, createWalls returns a Group that contains several wall objects. When we pass this group to createBoundingBoxes, we want to create a bounding box for each wall in the group. To do that, we need to loop over the children array of the group. 28 | 29 | // So, when we call createBoundingBoxes(walls), the objects parameter of createBoundingBoxes is a Group object. In order to loop over each wall in the group, we need to set objects to objects.children. 30 | 31 | // However, createPaintings returns an array, not a Group. When you call createBoundingBoxes(paintings), the objects parameter of createBoundingBoxes is already an array, so you don't need to do anything. 32 | 33 | // That's why createBoundingBoxes starts by checking if objects is an array with if (!Array.isArray(objects)). If objects is not an array, it assumes that it's a Group and sets objects to objects.children. If objects is already an array, it skips this step. 34 | 35 | // After this check, objects is always an array, whether it was originally an array or a Group. This means that you can use objects.forEach to loop over each object in objects and add a bounding box to it, regardless of whether objects was originally an array or a Group. This is a way of making createBoundingBoxes flexible so it can work with both Groups and arrays. 36 | -------------------------------------------------------------------------------- /modules/ceiling.js: -------------------------------------------------------------------------------- 1 | import * as THREE from "three"; 2 | 3 | // create a function that takes a scene and a textureLoader as arguments that will be passed in from main.js where the createCeiling is called 4 | export const createCeiling = (scene, textureLoader) => { 5 | // Load the textures 6 | const colorTexture = textureLoader.load( 7 | "OfficeCeiling005_4K-JPG/OfficeCeiling005_4K_Color.jpg" 8 | ); 9 | const displacementTexture = textureLoader.load( 10 | "OfficeCeiling005_4K-JPG/OfficeCeiling005_4K_Displacement.jpg" 11 | ); 12 | const aoTexture = textureLoader.load( 13 | "OfficeCeiling005_4K-JPG/OfficeCeiling005_4K_AmbientOcclusion.jpg" 14 | ); 15 | const emissionTexture = textureLoader.load( 16 | "OfficeCeiling005_4K-JPG/OfficeCeiling005_4K_Emission.jpg" 17 | ); 18 | const metalnessTexture = textureLoader.load( 19 | "OfficeCeiling005_4K-JPG/OfficeCeiling005_4K_Metalness.jpg" 20 | ); 21 | const normalGLTexture = textureLoader.load( 22 | "OfficeCeiling005_4K-JPG/OfficeCeiling005_4K_NormalGL.jpg" 23 | ); 24 | const roughnessTexture = textureLoader.load( 25 | "OfficeCeiling005_4K-JPG/OfficeCeiling005_4K_Roughness.jpg" 26 | ); 27 | 28 | // Set texture parameters 29 | colorTexture.wrapS = colorTexture.wrapT = THREE.RepeatWrapping; 30 | displacementTexture.wrapS = displacementTexture.wrapT = THREE.RepeatWrapping; 31 | aoTexture.wrapS = aoTexture.wrapT = THREE.RepeatWrapping; 32 | emissionTexture.wrapS = emissionTexture.wrapT = THREE.RepeatWrapping; 33 | metalnessTexture.wrapS = metalnessTexture.wrapT = THREE.RepeatWrapping; 34 | normalGLTexture.wrapS = normalGLTexture.wrapT = THREE.RepeatWrapping; 35 | roughnessTexture.wrapS = roughnessTexture.wrapT = THREE.RepeatWrapping; 36 | 37 | const ceilingGeometry = new THREE.PlaneGeometry(45, 40); 38 | const ceilingMaterial = new THREE.MeshLambertMaterial({ 39 | map: colorTexture, 40 | displacementMap: displacementTexture, 41 | aoMap: aoTexture, 42 | emissiveMap: emissionTexture, 43 | metalnessMap: metalnessTexture, 44 | normalMap: normalGLTexture, 45 | normalMapType: THREE.NormalMap, 46 | roughnessMap: roughnessTexture, 47 | displacementScale: 0.1, 48 | side: THREE.DoubleSide, 49 | }); 50 | const ceilingPlane = new THREE.Mesh(ceilingGeometry, ceilingMaterial); 51 | 52 | ceilingPlane.rotation.x = Math.PI / 2; 53 | 54 | ceilingPlane.position.y = 10; 55 | 56 | scene.add(ceilingPlane); 57 | }; 58 | -------------------------------------------------------------------------------- /modules/ceilingLamp.js: -------------------------------------------------------------------------------- 1 | import * as THREE from "three"; 2 | import { GLTFLoader } from "three/addons/loaders/GLTFLoader"; 3 | import { GUI } from "lil-gui"; 4 | 5 | export const loadCeilingLampModel = (scene) => { 6 | const loader = new GLTFLoader(); 7 | const gui = new GUI(); 8 | 9 | loader.load("../public/models/ceiling-lamp/scene.gltf", (gltf) => { 10 | const lamp = gltf.scene; 11 | 12 | console.log("Ceiling Lamp", gltf); 13 | 14 | // Position the lamp 15 | lamp.position.set(0, 5.5, 0); 16 | lamp.scale.set(0.1, 0.1, 0.1); 17 | 18 | // Add the lamp to the scene 19 | scene.add(lamp); 20 | 21 | // Add GUI controls for the lamp 22 | const lampFolder = gui.addFolder("Ceiling Lamp"); 23 | lampFolder.add(lamp.position, "x", -50, 50).name("X Position"); 24 | lampFolder.add(lamp.position, "y", -50, 50).name("Y Position"); 25 | lampFolder.add(lamp.position, "z", -50, 50).name("Z Position"); 26 | }); 27 | }; 28 | -------------------------------------------------------------------------------- /modules/clickHandling.js: -------------------------------------------------------------------------------- 1 | import * as THREE from 'three'; 2 | 3 | const mouse = new THREE.Vector2(); 4 | const raycaster = new THREE.Raycaster(); 5 | 6 | function clickHandling(renderer, camera, paintings) { 7 | renderer.domElement.addEventListener( 8 | 'click', 9 | (event) => { 10 | mouse.x = (event.clientX / window.innerWidth) * 2 - 1; 11 | mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; 12 | onClick(camera, paintings); 13 | }, 14 | false 15 | ); 16 | } 17 | 18 | function onClick(camera, paintings) { 19 | raycaster.setFromCamera(mouse, camera); 20 | 21 | const intersects = raycaster.intersectObjects(paintings); 22 | 23 | if (intersects.length > 0) { 24 | const painting = intersects[0].object; 25 | 26 | // Perform the desired action, e.g., open a modal or redirect to another page 27 | console.log('Clicked painting:', painting.userData.info.title); 28 | window.open(painting.userData.info.link, '_blank'); 29 | } 30 | } 31 | 32 | export { clickHandling }; 33 | -------------------------------------------------------------------------------- /modules/eventListeners.js: -------------------------------------------------------------------------------- 1 | import { keysPressed } from "./movement.js"; // import the keysPressed object 2 | import { showMenu, hideMenu } from "./menu.js"; // import the showMenu function 3 | import { startAudio, stopAudio } from "./audioGuide.js"; 4 | 5 | let lockPointer = true; 6 | let showMenuOnUnlock = false; 7 | 8 | // add the controls parameter which is the pointer lock controls and is passed from main.js where setupEventListeners is called 9 | export const setupEventListeners = (controls, camera, scene) => { 10 | // add the event listeners to the document which is the whole page 11 | document.addEventListener( 12 | "keydown", 13 | (event) => onKeyDown(event, controls), 14 | false 15 | ); 16 | document.addEventListener( 17 | "keyup", 18 | (event) => onKeyUp(event, controls), 19 | false 20 | ); 21 | 22 | controls.addEventListener("unlock", () => { 23 | if (showMenuOnUnlock) { 24 | showMenu(); 25 | } 26 | showMenuOnUnlock = false; 27 | }); 28 | 29 | // Add event listeners for the audio guide buttons 30 | document.getElementById("start_audio").addEventListener("click", startAudio); 31 | document.getElementById("stop_audio").addEventListener("click", stopAudio); 32 | }; 33 | 34 | // toggle the pointer lock 35 | function togglePointerLock(controls) { 36 | if (lockPointer) { 37 | controls.lock(); 38 | } else { 39 | showMenuOnUnlock = false; 40 | controls.unlock(); 41 | } 42 | lockPointer = !lockPointer; // toggle the lockPointer variable 43 | } 44 | 45 | function onKeyDown(event, controls) { 46 | // event is the event object that has the key property 47 | if (event.key in keysPressed) { 48 | // check if the key pressed by the user is in the keysPressed object 49 | keysPressed[event.key] = true; // if yes, set the value of the key pressed to true 50 | } 51 | 52 | if (event.key === "Escape") { 53 | // if the "ESC" key is pressed 54 | showMenu(); // show the menu 55 | showMenuOnUnlock = true; 56 | controls.unlock(); // unlock the pointer 57 | lockPointer = false; 58 | } 59 | 60 | if (event.key === "p") { 61 | // if the "SPACE" key is pressed 62 | controls.unlock(); // unlock the pointer 63 | lockPointer = false; 64 | } 65 | 66 | // if key prssed is enter or return for mac 67 | if (event.key === "Enter" || event.key === "Return") { 68 | // if the "ENTER" key is pressed 69 | hideMenu(); // hide the menu 70 | controls.lock(); // lock the pointer 71 | lockPointer = true; 72 | } 73 | 74 | if (event.key === " ") { 75 | // if the "p" key is pressed 76 | togglePointerLock(controls); // toggle the pointer lock 77 | } 78 | 79 | if (event.key === "g") { 80 | // if the "a" key is pressed 81 | startAudio(); // start the audio guide 82 | } 83 | 84 | if (event.key === "p") { 85 | // if the "s" key is pressed 86 | stopAudio(); // stop the audio guide 87 | } 88 | 89 | if (event.key === "m") { 90 | // if the "h" key is pressed 91 | showMenu(); // show the menu 92 | showMenuOnUnlock = true; 93 | controls.unlock(); // unlock the pointer 94 | lockPointer = false; 95 | } 96 | 97 | if (event.key === "r") { 98 | // if the "r" key is pressed 99 | location.reload(); // reload the page 100 | } 101 | } 102 | 103 | function onKeyUp(event, controls) { 104 | // same but for keyup 105 | if (event.key in keysPressed) { 106 | keysPressed[event.key] = false; // set to false when the key is released 107 | } 108 | } 109 | 110 | document.getElementById("toggle-info").addEventListener("click", () => { 111 | document.getElementById("info-panel").classList.toggle("collapsed"); 112 | document.getElementById("toggle-info").innerText = document 113 | .getElementById("info-panel") 114 | .classList.contains("collapsed") 115 | ? "Show" 116 | : "Hide"; 117 | }); 118 | 119 | document.getElementById("about_button").addEventListener("click", function () { 120 | document.getElementById("about-overlay").classList.add("show"); 121 | }); 122 | 123 | document.getElementById("close-about").addEventListener("click", function () { 124 | document.getElementById("about-overlay").classList.remove("show"); 125 | }); 126 | -------------------------------------------------------------------------------- /modules/floor.js: -------------------------------------------------------------------------------- 1 | import * as THREE from "three"; 2 | import floortTexture from "../public/WoodFloor040_4K-JPG/WoodFloor040_4K_Color.jpg"; 3 | 4 | export const setupFloor = (scene) => { 5 | const textureLoader = new THREE.TextureLoader(); 6 | 7 | // Load the textures 8 | const colorTexture = textureLoader.load( 9 | "WoodFloor040_4K-JPG/WoodFloor040_4K_Color.jpg" 10 | ); 11 | const displacementTexture = textureLoader.load( 12 | "WoodFloor040_4K-JPG/WoodFloor040_4K_Displacement.jpg" 13 | ); 14 | const normalTexture = textureLoader.load( 15 | "WoodFloor040_4K-JPG/WoodFloor040_4K_NormalGL.jpg" 16 | ); 17 | const roughnessTexture = textureLoader.load( 18 | "WoodFloor040_4K-JPG/WoodFloor040_4K_Roughness.jpg" 19 | ); 20 | const aoTexture = textureLoader.load( 21 | "WoodFloor040_4K-JPG/WoodFloor040_4K_AmbientOcclusion.jpg" 22 | ); 23 | 24 | // Set texture parameters 25 | colorTexture.wrapS = colorTexture.wrapT = THREE.RepeatWrapping; 26 | displacementTexture.wrapS = displacementTexture.wrapT = THREE.RepeatWrapping; 27 | normalTexture.wrapS = normalTexture.wrapT = THREE.RepeatWrapping; 28 | roughnessTexture.wrapS = roughnessTexture.wrapT = THREE.RepeatWrapping; 29 | aoTexture.wrapS = aoTexture.wrapT = THREE.RepeatWrapping; 30 | 31 | const planeGeometry = new THREE.PlaneGeometry(45, 45); 32 | const planeMaterial = new THREE.MeshStandardMaterial({ 33 | map: colorTexture, 34 | displacementMap: displacementTexture, 35 | normalMap: normalTexture, 36 | roughnessMap: roughnessTexture, 37 | aoMap: aoTexture, 38 | displacementScale: 0.1, 39 | side: THREE.DoubleSide, 40 | }); 41 | 42 | const floorPlane = new THREE.Mesh(planeGeometry, planeMaterial); 43 | 44 | floorPlane.rotation.x = Math.PI / 2; 45 | floorPlane.position.y = -Math.PI; 46 | 47 | scene.add(floorPlane); 48 | }; 49 | -------------------------------------------------------------------------------- /modules/lighting.js: -------------------------------------------------------------------------------- 1 | import * as THREE from "three"; 2 | import { GUI } from "lil-gui"; 3 | 4 | export const setupLighting = (scene, paintings) => { 5 | // Initialize GUI 6 | const gui = new GUI(); 7 | 8 | // Ambient light 9 | const ambientLight = new THREE.AmbientLight(0xffffff, 0.6); 10 | scene.add(ambientLight); 11 | 12 | // GUI for Ambient Light 13 | const ambientFolder = gui.addFolder("Ambient Light"); 14 | ambientFolder.add(ambientLight, "intensity", 0, 2); 15 | 16 | function createSpotlight(x, y, z, intensity, targetPosition) { 17 | const spotlight = new THREE.SpotLight(0xffffff, intensity); 18 | spotlight.position.set(x, y, z); 19 | spotlight.target.position.copy(targetPosition); 20 | spotlight.castShadow = true; 21 | spotlight.angle = 1.57079; 22 | spotlight.penumbra = 0.2; 23 | spotlight.decay = 1; 24 | spotlight.distance = 40; 25 | spotlight.shadow.mapSize.width = 1024; 26 | spotlight.shadow.mapSize.height = 1024; 27 | 28 | // Add spotlight and its target to the scene 29 | scene.add(spotlight); 30 | scene.add(spotlight.target); 31 | 32 | // Add a helper for this spotlight 33 | // const spotlightHelper = new THREE.SpotLightHelper(spotlight); 34 | // scene.add(spotlightHelper); 35 | 36 | // Create a GUI folder for this spotlight 37 | const folder = gui.addFolder(`Spotlight (${x}, ${y}, ${z})`); 38 | folder.add(spotlight, "intensity", 0, 4); 39 | folder.add(spotlight, "angle", 0, Math.PI / 2).name("Angle"); 40 | folder.add(spotlight, "penumbra", 0, 1).name("Penumbra"); 41 | folder.add(spotlight, "decay", 0, 2).name("Decay"); 42 | folder.add(spotlight, "distance", 0, 100).name("Distance"); 43 | folder.add(spotlight.position, "x", -50, 50); 44 | folder.add(spotlight.position, "y", -50, 50); 45 | folder.add(spotlight.position, "z", -50, 50); 46 | folder.add(spotlight.target.position, "x", -50, 50); 47 | folder.add(spotlight.target.position, "y", -50, 50); 48 | folder.add(spotlight.target.position, "z", -50, 50); 49 | 50 | return spotlight; 51 | } 52 | 53 | const frontWallSpotlight = createSpotlight( 54 | 0, 55 | 6.7, 56 | -13, 57 | 0.948, 58 | new THREE.Vector3(0, 0, -20) 59 | ); 60 | 61 | const backWallSpotlight = createSpotlight( 62 | 0, 63 | 6.7, 64 | 13, 65 | 0.948, 66 | new THREE.Vector3(0, 0, 20) 67 | ); 68 | 69 | const leftWallSpotlight = createSpotlight( 70 | -13, 71 | 6.7, 72 | 0, 73 | 0.948, 74 | new THREE.Vector3(-20, 0, 0) 75 | ); 76 | 77 | const rightWallSpotlight = createSpotlight( 78 | 13, 79 | 6.7, 80 | 0, 81 | 0.948, 82 | new THREE.Vector3(20, 0, 0) 83 | ); 84 | 85 | const statueSpotlight = createSpotlight( 86 | 0, 87 | 10, 88 | 0, 89 | 0.948, 90 | new THREE.Vector3(0, -4.2, 0) 91 | ); // Spotlight for the statue 92 | statueSpotlight.angle = 0.75084; 93 | statueSpotlight.decay = 1; 94 | statueSpotlight.penumbra = 1; 95 | statueSpotlight.distance = 0; 96 | 97 | const statueSpotlightFolder = gui.addFolder("Statue Light"); 98 | statueSpotlightFolder.add(statueSpotlight, "intensity", 0, 4); 99 | statueSpotlightFolder 100 | .add(statueSpotlight, "angle", 0, Math.PI / 2) 101 | .name("Angle"); 102 | statueSpotlightFolder.add(statueSpotlight, "penumbra", 0, 1).name("Penumbra"); 103 | statueSpotlightFolder.add(statueSpotlight, "decay", 0, 2).name("Decay"); 104 | }; 105 | -------------------------------------------------------------------------------- /modules/menu.js: -------------------------------------------------------------------------------- 1 | export const hideMenu = () => { 2 | const menu = document.getElementById('menu'); 3 | menu.style.display = 'none'; // Hide the menu 4 | }; 5 | 6 | export const showMenu = () => { 7 | const menu = document.getElementById('menu'); 8 | menu.style.display = 'block'; // Show the menu 9 | }; 10 | 11 | // Lock the pointer (controls are activated) and hide the menu when the experience starts 12 | export const startExperience = (controls) => { 13 | controls.lock(); // Lock the pointer (controls are activated) 14 | hideMenu(); 15 | }; 16 | 17 | export const setupPlayButton = (controls) => { 18 | const playButton = document.getElementById('play_button'); // Get the reference 19 | playButton.addEventListener('click', () => startExperience(controls)); // Add the click event listener to the play button to start the experience 20 | }; 21 | -------------------------------------------------------------------------------- /modules/movement.js: -------------------------------------------------------------------------------- 1 | import * as THREE from 'three'; 2 | 3 | // object to hold the keys pressed 4 | export const keysPressed = { 5 | ArrowUp: false, 6 | ArrowDown: false, 7 | ArrowLeft: false, 8 | ArrowRight: false, 9 | w: false, 10 | a: false, 11 | s: false, 12 | d: false, 13 | }; 14 | 15 | // parameters we get from setupRendering where updateMovement is called. setupRendering gets the parameters from main.jsss 16 | export const updateMovement = (delta, controls, camera, walls) => { 17 | const moveSpeed = 5 * delta; // moveSpeed is the distance the camera will move in one second. We multiply by delta to make the movement framerate independent. This means that the movement will be the same regardless of the framerate. This is important because if the framerate is low, the movement will be slow and if the framerate is high, the movement will be fast. This is not what we want. We want the movement to be the same regardless of the framerate. 18 | 19 | const previousPosition = camera.position.clone(); // clone the camera position and store it in previousPosition. We will use this to reset the camera position if there is a collision 20 | 21 | // cose self-explanatory 22 | if (keysPressed.ArrowRight || keysPressed.d) { 23 | controls.moveRight(moveSpeed); 24 | } 25 | if (keysPressed.ArrowLeft || keysPressed.a) { 26 | controls.moveRight(-moveSpeed); 27 | } 28 | if (keysPressed.ArrowUp || keysPressed.w) { 29 | controls.moveForward(moveSpeed); 30 | } 31 | if (keysPressed.ArrowDown || keysPressed.s) { 32 | controls.moveForward(-moveSpeed); 33 | } 34 | 35 | // After the movement is applied, we check for collisions by calling the checkCollision function. If a collision is detected, we revert the camera's position to its previous position, effectively preventing the player from moving through walls. 36 | if (checkCollision(camera, walls)) { 37 | camera.position.copy(previousPosition); // reset the camera position to the previous position. The `previousPosition` variable is a clone of the camera position before the movement. We use `copy` instead of `set` because `set` will set the position to the same object, so if we change the previousPosition, the camera position will also change. `copy` creates a new object with the same values as the previousPosition. 38 | } 39 | }; 40 | 41 | // checkCollision takes the camera and the walls as parameters and returns true if there is a collision and false if there isn't. the camera parameter is the camera object and the walls parameter is the walls group. The paramaters are passed from updateMovement function where checkCollision is called. updateMovement gets the parameters from setupRendering where it is called. setupRendering gets the parameters from main.js where setupRendering is called. 42 | export const checkCollision = (camera, walls) => { 43 | const playerBoundingBox = new THREE.Box3(); // create a bounding box for the player 44 | const cameraWorldPosition = new THREE.Vector3(); // create a vector to hold the camera's world position 45 | camera.getWorldPosition(cameraWorldPosition); // get the camera's world position and store it in cameraWorldPosition. Note: The camera represents the player's position in our case. 46 | playerBoundingBox.setFromCenterAndSize( 47 | // set the playerBoundingBox to the camera's world position and size. The size is 1, 1, 1 because the camera is a single point. 48 | // setFromCenterAndSize takes two parameters: center and size. The center is a Vector3 that represents the center of the bounding box. The size is a Vector3 that represents the size of the bounding box. The size is the distance from the center to the edge of the bounding box in each direction. So, if the size is 1, 1, 1, the bounding box will be 2 units wide, 2 units tall, and 2 units deep. If the size is 2, 2, 2, the bounding box will be 4 units wide, 4 units tall, and 4 units deep. 49 | cameraWorldPosition, // center 50 | new THREE.Vector3(1, 1, 1) // size 51 | ); 52 | 53 | for (let i = 0; i < walls.children.length; i++) { 54 | // loop through each wall 55 | const wall = walls.children[i]; // get the wall 56 | if (playerBoundingBox.intersectsBox(wall.BoundingBox)) { 57 | // check if the playerBoundingBox intersects with the wall's bounding box. If it does, return true. 58 | return true; 59 | } 60 | } 61 | 62 | return false; // if the playerBoundingBox doesn't intersect with any of the walls, return false. 63 | }; 64 | -------------------------------------------------------------------------------- /modules/paintingData.js: -------------------------------------------------------------------------------- 1 | export const paintingData = [ 2 | // Front Wall 3 | ...Array.from({ length: 4 }, (_, i) => ({ 4 | // Array.from creates an array from an array-like object. The first parameter is the array-like object. The second parameter is a map function that is called for each element in the array-like object. The map function takes two parameters: the element and the index. The map function returns the value that will be added to the new array. In this case, we are returning an object with the painting data. `_` is a placeholder for the element. We don't need it because we are not using the element. `i` is the index. We use it to set the painting number. 5 | imgSrc: `artworks/${i + 1}.jpg`, // `i + 1` is the painting number. We add 1 to the index because the index starts at 0 but we want the painting numbers to start at 1. 6 | width: 5, // width of the painting 7 | height: 3, // height of the painting 8 | position: { x: -15 + 10 * i, y: 2, z: -19.5 }, // position of the painting 9 | rotationY: 0, // rotation of the painting 10 | info: { 11 | // info about the painting 12 | title: `Van Gogh ${i + 1}`, 13 | artist: 'Vincent van Gogh', 14 | description: `This is one of the masterpieces by Vincent van Gogh, showcasing his unique style and emotional honesty. Artwork ${ 15 | i + 1 16 | } perfectly encapsulates his love for the beauty of everyday life.`, 17 | year: `Year ${i + 1}`, 18 | link: 'https://github.com/theringsofsaturn', 19 | }, 20 | })), 21 | // Back Wall 22 | ...Array.from({ length: 4 }, (_, i) => ({ 23 | imgSrc: `artworks/${i + 5}.jpg`, 24 | width: 5, 25 | height: 3, 26 | position: { x: -15 + 10 * i, y: 2, z: 19.5 }, 27 | rotationY: Math.PI, 28 | info: { 29 | title: `Van Gogh ${i + 5}`, 30 | artist: 'Vincent van Gogh', 31 | description: `Artwork ${ 32 | i + 5 33 | } by Vincent van Gogh is an exceptional piece showcasing his remarkable ability to capture emotion and atmosphere.`, 34 | year: `Year ${i + 5}`, 35 | link: 'https://github.com/theringsofsaturn', 36 | }, 37 | })), 38 | // Left Wall 39 | ...Array.from({ length: 4 }, (_, i) => ({ 40 | imgSrc: `artworks/${i + 9}.jpg`, 41 | width: 5, 42 | height: 3, 43 | position: { x: -19.5, y: 2, z: -15 + 10 * i }, 44 | rotationY: Math.PI / 2, 45 | info: { 46 | title: `Van Gogh ${i + 9}`, 47 | artist: 'Vincent van Gogh', 48 | description: `With its striking use of color and brushwork, Artwork ${ 49 | i + 9 50 | } is a testament to Van Gogh's artistic genius.`, 51 | year: `Year ${i + 9}`, 52 | link: 'https://github.com/theringsofsaturn', 53 | }, 54 | })), 55 | // Right Wall 56 | ...Array.from({ length: 4 }, (_, i) => ({ 57 | imgSrc: `artworks/${i + 13}.jpg`, 58 | width: 5, 59 | height: 3, 60 | position: { x: 19.5, y: 2, z: -15 + 10 * i }, 61 | rotationY: -Math.PI / 2, 62 | info: { 63 | title: `Van Gogh ${i + 13}`, 64 | artist: 'Vincent van Gogh', 65 | description: `Artwork ${ 66 | i + 13 67 | } is a captivating piece by Vincent van Gogh, reflecting his distinctive style and deep passion for art.`, 68 | year: `Year ${i + 13}`, 69 | link: 'https://github.com/theringsofsaturn', 70 | }, 71 | })), 72 | ]; 73 | -------------------------------------------------------------------------------- /modules/paintingInfo.js: -------------------------------------------------------------------------------- 1 | // Display painting info in the DOM 2 | export const displayPaintingInfo = (info) => { 3 | const infoElement = document.getElementById('painting-info'); // Get the reference 4 | 5 | // Set the html content inside info element 6 | infoElement.innerHTML = ` 7 |

${info.title}

8 |

Artist: ${info.artist}

9 |

Description: ${info.description}

10 |

Year: ${info.year}

11 | `; 12 | infoElement.classList.add('show'); // Add the 'show' class 13 | }; 14 | 15 | // Hide painting info in the DOM 16 | export const hidePaintingInfo = () => { 17 | const infoElement = document.getElementById('painting-info'); // Get the reference 18 | infoElement.classList.remove('show'); // Remove the 'show' class 19 | }; 20 | 21 | -------------------------------------------------------------------------------- /modules/paintings.js: -------------------------------------------------------------------------------- 1 | import * as THREE from 'three'; 2 | 3 | import { paintingData } from './paintingData.js'; 4 | 5 | export function createPaintings(scene, textureLoader) { 6 | 7 | let paintings = []; 8 | 9 | paintingData.forEach((data) => { 10 | 11 | const painting = new THREE.Mesh( 12 | new THREE.PlaneGeometry(data.width, data.height), 13 | new THREE.MeshLambertMaterial({ map: textureLoader.load(data.imgSrc) }) 14 | ); 15 | 16 | painting.position.set(data.position.x, data.position.y, data.position.z); 17 | painting.rotation.y = data.rotationY; 18 | 19 | 20 | painting.userData = { 21 | type: 'painting', 22 | info: data.info, 23 | url: data.info.link 24 | }; 25 | 26 | painting.castShadow = true; 27 | painting.receiveShadow = true; 28 | 29 | paintings.push(painting); 30 | }); 31 | 32 | return paintings; 33 | } 34 | -------------------------------------------------------------------------------- /modules/rendering.js: -------------------------------------------------------------------------------- 1 | import * as THREE from "three"; 2 | import { displayPaintingInfo, hidePaintingInfo } from "./paintingInfo.js"; 3 | import { updateMovement } from "./movement.js"; 4 | 5 | export const setupRendering = ( 6 | scene, 7 | camera, 8 | renderer, 9 | paintings, 10 | controls, 11 | walls 12 | ) => { 13 | const clock = new THREE.Clock(); 14 | 15 | let render = function () { 16 | const delta = clock.getDelta(); 17 | 18 | updateMovement(delta, controls, camera, walls); 19 | 20 | const distanceThreshold = 8; 21 | 22 | let paintingToShow; 23 | paintings.forEach((painting) => { 24 | const distanceToPainting = camera.position.distanceTo(painting.position); 25 | if (distanceToPainting < distanceThreshold) { 26 | paintingToShow = painting; 27 | } 28 | }); 29 | 30 | if (paintingToShow) { 31 | // if there is a painting to show 32 | displayPaintingInfo(paintingToShow.userData.info); 33 | } else { 34 | hidePaintingInfo(); 35 | } 36 | 37 | renderer.gammaOutput = true; 38 | renderer.gammaFactor = 2.2; 39 | 40 | renderer.render(scene, camera); 41 | requestAnimationFrame(render); 42 | }; 43 | 44 | render(); 45 | }; 46 | -------------------------------------------------------------------------------- /modules/scene.js: -------------------------------------------------------------------------------- 1 | import * as THREE from "three"; 2 | import { PointerLockControls } from "three-stdlib"; 3 | 4 | export const scene = new THREE.Scene(); // create a scene 5 | let camera; 6 | let controls; 7 | let renderer; 8 | 9 | export const setupScene = () => { 10 | // PerspectiveCamera is a type of camera that mimics the way the human eye sees things. It takes 4 parameters: field of view, aspect ratio, near clipping plane, and far clipping plane. The field of view is the extent of the scene that is seen on the display at any given moment. The aspect ratio should be the width of the element divided by the height (in this case, the screen width and height). The camera will not render objects that are closer to the camera than the near clipping plane or further away than the far clipping plane. Objects that are exactly on the clipping plane will not be rendered. 11 | camera = new THREE.PerspectiveCamera( 12 | 60, // fov = field of view 13 | window.innerWidth / window.innerHeight, // aspect ratio 14 | 0.1, // near clipping plane 15 | 1000 // far clipping plane 16 | ); 17 | scene.add(camera); // add the camera to the scene 18 | camera.position.set(0, 2, 15); // move the camera up 3 units in the Y axis 19 | 20 | renderer = new THREE.WebGLRenderer({ antialias: false }); // create a WebGLRenderer and set its antialias property to true to enable antialiasing which smooths out the edges of what is rendered 21 | renderer.setSize(window.innerWidth, window.innerHeight); // set the size of the renderer to the inner width and height of the window (the browser window) 22 | renderer.setClearColor(0xffffff, 1); // set the background color of the renderer to white 23 | document.body.appendChild(renderer.domElement); // append the renderer to the body of the document (the element that the renderer uses will be added to the body) 24 | 25 | renderer.shadowMap.enabled = true; // enable shadow mapping 26 | renderer.shadowMap.type = THREE.PCFSoftShadowMap; // `renderer.shadowMap.type` is a property that defines the type of shadow map used by the renderer. THREE.PCFSoftShadowMap is one of the available shadow map types and stands for Percentage-Closer Filtering Soft Shadow Map. This type of shadow map uses an algorithm to smooth the edges of shadows and make them appear softer 27 | 28 | controls = new PointerLockControls(camera, renderer.domElement); // create a PointerLockControls object that takes the camera and the renderer's domElement as arguments. PointerLockControls is a class that allows the camera to be controlled by the mouse and keyboard. 29 | scene.add(controls.getObject()); // add the PointerLockControls object to the scene 30 | 31 | window.addEventListener("resize", onWindowResize, false); // add an event listener to the window that calls the onWindowResize function when the window is resized. Its work is to update the camera's aspect ratio and the renderer's size. The third parameter is set to false to indicate that the event listener should be triggered in the bubbling phase instead of the capturing phase. The bubbling phase is when the event bubbles up from the target element to the parent elements. The capturing phase is when the event trickles down from the parent elements to the target element. The default value is false, so we don't need to include it, but I included it for clarity. The capturing phase is rarely used, so you can ignore it for now. You can read more about the capturing and bubbling phases here: https://javascript.info/bubbling-and-capturing 32 | 33 | function onWindowResize() { 34 | camera.aspect = window.innerWidth / window.innerHeight; // update the camera's aspect ratio 35 | camera.updateProjectionMatrix(); // update the camera's projection matrix. The projection matrix is used to determine how 3D points are mapped to the 2D space of the screen. It is used to calculate the frustum of the camera which is a truncated pyramid that represents the camera's field of view. Anything outside the frustum is not rendered. The projection matrix is used to calculate the frustum every time the window is resized. 36 | renderer.setSize(window.innerWidth, window.innerHeight); // update the size of the renderer 37 | } 38 | 39 | return { camera, controls, renderer }; // return the camera, controls, and renderer so that they can be used in other modules 40 | }; 41 | -------------------------------------------------------------------------------- /modules/sceneHelpers.js: -------------------------------------------------------------------------------- 1 | // This function will take a scene and an array of objects, and add each object to the scene. We can use this function to add the paintings to the scene. It will be called in main.js after we create the paintings 2 | export const addObjectsToScene = (scene, objects) => { 3 | objects.forEach((object) => { 4 | scene.add(object); 5 | }); 6 | }; 7 | -------------------------------------------------------------------------------- /modules/statue.js: -------------------------------------------------------------------------------- 1 | // statue.js 2 | import * as THREE from "three"; 3 | import { GLTFLoader } from "three/addons/loaders/GLTFLoader"; 4 | 5 | export const loadStatueModel = (scene) => { 6 | const loader = new GLTFLoader(); 7 | 8 | loader.load( 9 | "../public/models/statue/scene.gltf", 10 | (gltf) => { 11 | const statue = gltf.scene; 12 | 13 | // console.log("STATUE", gltf); 14 | 15 | // Position the statue at the center of the floor 16 | statue.position.set(0, -3.2, 0); 17 | 18 | // Scale if necessary 19 | statue.scale.set(0.06, 0.06, 0.06); 20 | 21 | // Iterate through all the meshes in the statue and update their materials 22 | statue.traverse((child) => { 23 | if (child.isMesh) { 24 | map: child.material.map, 25 | // Modify child.material here to improve appearance 26 | (child.material.metalness = 0.0), 27 | (child.material.roughness = 0.2), 28 | // Cast shadow 29 | (child.castShadow = true); 30 | 31 | // console.log("Statue Material:", child.material); 32 | } 33 | }); 34 | 35 | // Add the statue to the scene 36 | scene.add(statue); 37 | }, 38 | undefined, 39 | (error) => { 40 | console.error("An error occurred while loading the model.", error); 41 | } 42 | ); 43 | }; 44 | -------------------------------------------------------------------------------- /modules/walls.js: -------------------------------------------------------------------------------- 1 | import * as THREE from "three"; 2 | 3 | export function createWalls(scene, textureLoader) { 4 | let wallGroup = new THREE.Group(); 5 | scene.add(wallGroup); 6 | 7 | const normalTexture = textureLoader.load( 8 | "leather_white_4k.gltf/textures/leather_white_nor_gl_4k.jpg" 9 | ); 10 | const roughnessTexture = textureLoader.load( 11 | "leather_white_4k.gltf/textures/leather_white_rough_4k.jpg" 12 | ); 13 | 14 | normalTexture.wrapS = normalTexture.wrapT = THREE.RepeatWrapping; 15 | roughnessTexture.wrapS = roughnessTexture.wrapT = THREE.RepeatWrapping; 16 | 17 | const wallMaterial = new THREE.MeshStandardMaterial({ 18 | color: 0xadadae, 19 | normalMap: normalTexture, 20 | roughnessMap: roughnessTexture, 21 | side: THREE.DoubleSide, 22 | }); 23 | // Front Wall 24 | const frontWall = new THREE.Mesh( 25 | new THREE.BoxGeometry(80, 20, 0.001), 26 | wallMaterial 27 | ); 28 | 29 | frontWall.position.z = -20; 30 | 31 | // Left Wall 32 | const leftWall = new THREE.Mesh( 33 | new THREE.BoxGeometry(80, 20, 0.001), 34 | wallMaterial 35 | ); 36 | 37 | leftWall.rotation.y = Math.PI / 2; 38 | leftWall.position.x = -20; 39 | 40 | // Right Wall 41 | const rightWall = new THREE.Mesh( 42 | new THREE.BoxGeometry(80, 20, 0.001), 43 | wallMaterial 44 | ); 45 | 46 | rightWall.position.x = 20; 47 | rightWall.rotation.y = Math.PI / 2; 48 | 49 | // Back Wall 50 | const backWall = new THREE.Mesh( 51 | new THREE.BoxGeometry(80, 20, 0.001), 52 | wallMaterial 53 | ); 54 | backWall.position.z = 20; 55 | 56 | wallGroup.add(frontWall, backWall, leftWall, rightWall); 57 | 58 | return wallGroup; 59 | } 60 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "3D-art-gallery", 3 | "lockfileVersion": 2, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "license": "Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International", 8 | "dependencies": { 9 | "ammo.js": "^0.0.10", 10 | "ammojs-typed": "^1.0.6", 11 | "cannon": "^0.6.2", 12 | "lil-gui": "^0.18.2", 13 | "three": "^0.151.3", 14 | "three-stdlib": "^2.21.8" 15 | }, 16 | "devDependencies": { 17 | "vite": "^4.3.1" 18 | } 19 | }, 20 | "node_modules/@babel/runtime": { 21 | "version": "7.21.0", 22 | "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", 23 | "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", 24 | "dependencies": { 25 | "regenerator-runtime": "^0.13.11" 26 | }, 27 | "engines": { 28 | "node": ">=6.9.0" 29 | } 30 | }, 31 | "node_modules/@chevrotain/cst-dts-gen": { 32 | "version": "10.5.0", 33 | "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-10.5.0.tgz", 34 | "integrity": "sha512-lhmC/FyqQ2o7pGK4Om+hzuDrm9rhFYIJ/AXoQBeongmn870Xeb0L6oGEiuR8nohFNL5sMaQEJWCxr1oIVIVXrw==", 35 | "dependencies": { 36 | "@chevrotain/gast": "10.5.0", 37 | "@chevrotain/types": "10.5.0", 38 | "lodash": "4.17.21" 39 | } 40 | }, 41 | "node_modules/@chevrotain/gast": { 42 | "version": "10.5.0", 43 | "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-10.5.0.tgz", 44 | "integrity": "sha512-pXdMJ9XeDAbgOWKuD1Fldz4ieCs6+nLNmyVhe2gZVqoO7v8HXuHYs5OV2EzUtbuai37TlOAQHrTDvxMnvMJz3A==", 45 | "dependencies": { 46 | "@chevrotain/types": "10.5.0", 47 | "lodash": "4.17.21" 48 | } 49 | }, 50 | "node_modules/@chevrotain/types": { 51 | "version": "10.5.0", 52 | "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-10.5.0.tgz", 53 | "integrity": "sha512-f1MAia0x/pAVPWH/T73BJVyO2XU5tI4/iE7cnxb7tqdNTNhQI3Uq3XkqcoteTmD4t1aM0LbHCJOhgIDn07kl2A==" 54 | }, 55 | "node_modules/@chevrotain/utils": { 56 | "version": "10.5.0", 57 | "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-10.5.0.tgz", 58 | "integrity": "sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ==" 59 | }, 60 | "node_modules/@esbuild/android-arm": { 61 | "version": "0.17.17", 62 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.17.tgz", 63 | "integrity": "sha512-E6VAZwN7diCa3labs0GYvhEPL2M94WLF8A+czO8hfjREXxba8Ng7nM5VxV+9ihNXIY1iQO1XxUU4P7hbqbICxg==", 64 | "cpu": [ 65 | "arm" 66 | ], 67 | "dev": true, 68 | "optional": true, 69 | "os": [ 70 | "android" 71 | ], 72 | "engines": { 73 | "node": ">=12" 74 | } 75 | }, 76 | "node_modules/@esbuild/android-arm64": { 77 | "version": "0.17.17", 78 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.17.tgz", 79 | "integrity": "sha512-jaJ5IlmaDLFPNttv0ofcwy/cfeY4bh/n705Tgh+eLObbGtQBK3EPAu+CzL95JVE4nFAliyrnEu0d32Q5foavqg==", 80 | "cpu": [ 81 | "arm64" 82 | ], 83 | "dev": true, 84 | "optional": true, 85 | "os": [ 86 | "android" 87 | ], 88 | "engines": { 89 | "node": ">=12" 90 | } 91 | }, 92 | "node_modules/@esbuild/android-x64": { 93 | "version": "0.17.17", 94 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.17.tgz", 95 | "integrity": "sha512-446zpfJ3nioMC7ASvJB1pszHVskkw4u/9Eu8s5yvvsSDTzYh4p4ZIRj0DznSl3FBF0Z/mZfrKXTtt0QCoFmoHA==", 96 | "cpu": [ 97 | "x64" 98 | ], 99 | "dev": true, 100 | "optional": true, 101 | "os": [ 102 | "android" 103 | ], 104 | "engines": { 105 | "node": ">=12" 106 | } 107 | }, 108 | "node_modules/@esbuild/darwin-arm64": { 109 | "version": "0.17.17", 110 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.17.tgz", 111 | "integrity": "sha512-m/gwyiBwH3jqfUabtq3GH31otL/0sE0l34XKpSIqR7NjQ/XHQ3lpmQHLHbG8AHTGCw8Ao059GvV08MS0bhFIJQ==", 112 | "cpu": [ 113 | "arm64" 114 | ], 115 | "dev": true, 116 | "optional": true, 117 | "os": [ 118 | "darwin" 119 | ], 120 | "engines": { 121 | "node": ">=12" 122 | } 123 | }, 124 | "node_modules/@esbuild/darwin-x64": { 125 | "version": "0.17.17", 126 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.17.tgz", 127 | "integrity": "sha512-4utIrsX9IykrqYaXR8ob9Ha2hAY2qLc6ohJ8c0CN1DR8yWeMrTgYFjgdeQ9LIoTOfLetXjuCu5TRPHT9yKYJVg==", 128 | "cpu": [ 129 | "x64" 130 | ], 131 | "dev": true, 132 | "optional": true, 133 | "os": [ 134 | "darwin" 135 | ], 136 | "engines": { 137 | "node": ">=12" 138 | } 139 | }, 140 | "node_modules/@esbuild/freebsd-arm64": { 141 | "version": "0.17.17", 142 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.17.tgz", 143 | "integrity": "sha512-4PxjQII/9ppOrpEwzQ1b0pXCsFLqy77i0GaHodrmzH9zq2/NEhHMAMJkJ635Ns4fyJPFOlHMz4AsklIyRqFZWA==", 144 | "cpu": [ 145 | "arm64" 146 | ], 147 | "dev": true, 148 | "optional": true, 149 | "os": [ 150 | "freebsd" 151 | ], 152 | "engines": { 153 | "node": ">=12" 154 | } 155 | }, 156 | "node_modules/@esbuild/freebsd-x64": { 157 | "version": "0.17.17", 158 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.17.tgz", 159 | "integrity": "sha512-lQRS+4sW5S3P1sv0z2Ym807qMDfkmdhUYX30GRBURtLTrJOPDpoU0kI6pVz1hz3U0+YQ0tXGS9YWveQjUewAJw==", 160 | "cpu": [ 161 | "x64" 162 | ], 163 | "dev": true, 164 | "optional": true, 165 | "os": [ 166 | "freebsd" 167 | ], 168 | "engines": { 169 | "node": ">=12" 170 | } 171 | }, 172 | "node_modules/@esbuild/linux-arm": { 173 | "version": "0.17.17", 174 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.17.tgz", 175 | "integrity": "sha512-biDs7bjGdOdcmIk6xU426VgdRUpGg39Yz6sT9Xp23aq+IEHDb/u5cbmu/pAANpDB4rZpY/2USPhCA+w9t3roQg==", 176 | "cpu": [ 177 | "arm" 178 | ], 179 | "dev": true, 180 | "optional": true, 181 | "os": [ 182 | "linux" 183 | ], 184 | "engines": { 185 | "node": ">=12" 186 | } 187 | }, 188 | "node_modules/@esbuild/linux-arm64": { 189 | "version": "0.17.17", 190 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.17.tgz", 191 | "integrity": "sha512-2+pwLx0whKY1/Vqt8lyzStyda1v0qjJ5INWIe+d8+1onqQxHLLi3yr5bAa4gvbzhZqBztifYEu8hh1La5+7sUw==", 192 | "cpu": [ 193 | "arm64" 194 | ], 195 | "dev": true, 196 | "optional": true, 197 | "os": [ 198 | "linux" 199 | ], 200 | "engines": { 201 | "node": ">=12" 202 | } 203 | }, 204 | "node_modules/@esbuild/linux-ia32": { 205 | "version": "0.17.17", 206 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.17.tgz", 207 | "integrity": "sha512-IBTTv8X60dYo6P2t23sSUYym8fGfMAiuv7PzJ+0LcdAndZRzvke+wTVxJeCq4WgjppkOpndL04gMZIFvwoU34Q==", 208 | "cpu": [ 209 | "ia32" 210 | ], 211 | "dev": true, 212 | "optional": true, 213 | "os": [ 214 | "linux" 215 | ], 216 | "engines": { 217 | "node": ">=12" 218 | } 219 | }, 220 | "node_modules/@esbuild/linux-loong64": { 221 | "version": "0.17.17", 222 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.17.tgz", 223 | "integrity": "sha512-WVMBtcDpATjaGfWfp6u9dANIqmU9r37SY8wgAivuKmgKHE+bWSuv0qXEFt/p3qXQYxJIGXQQv6hHcm7iWhWjiw==", 224 | "cpu": [ 225 | "loong64" 226 | ], 227 | "dev": true, 228 | "optional": true, 229 | "os": [ 230 | "linux" 231 | ], 232 | "engines": { 233 | "node": ">=12" 234 | } 235 | }, 236 | "node_modules/@esbuild/linux-mips64el": { 237 | "version": "0.17.17", 238 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.17.tgz", 239 | "integrity": "sha512-2kYCGh8589ZYnY031FgMLy0kmE4VoGdvfJkxLdxP4HJvWNXpyLhjOvxVsYjYZ6awqY4bgLR9tpdYyStgZZhi2A==", 240 | "cpu": [ 241 | "mips64el" 242 | ], 243 | "dev": true, 244 | "optional": true, 245 | "os": [ 246 | "linux" 247 | ], 248 | "engines": { 249 | "node": ">=12" 250 | } 251 | }, 252 | "node_modules/@esbuild/linux-ppc64": { 253 | "version": "0.17.17", 254 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.17.tgz", 255 | "integrity": "sha512-KIdG5jdAEeAKogfyMTcszRxy3OPbZhq0PPsW4iKKcdlbk3YE4miKznxV2YOSmiK/hfOZ+lqHri3v8eecT2ATwQ==", 256 | "cpu": [ 257 | "ppc64" 258 | ], 259 | "dev": true, 260 | "optional": true, 261 | "os": [ 262 | "linux" 263 | ], 264 | "engines": { 265 | "node": ">=12" 266 | } 267 | }, 268 | "node_modules/@esbuild/linux-riscv64": { 269 | "version": "0.17.17", 270 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.17.tgz", 271 | "integrity": "sha512-Cj6uWLBR5LWhcD/2Lkfg2NrkVsNb2sFM5aVEfumKB2vYetkA/9Uyc1jVoxLZ0a38sUhFk4JOVKH0aVdPbjZQeA==", 272 | "cpu": [ 273 | "riscv64" 274 | ], 275 | "dev": true, 276 | "optional": true, 277 | "os": [ 278 | "linux" 279 | ], 280 | "engines": { 281 | "node": ">=12" 282 | } 283 | }, 284 | "node_modules/@esbuild/linux-s390x": { 285 | "version": "0.17.17", 286 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.17.tgz", 287 | "integrity": "sha512-lK+SffWIr0XsFf7E0srBjhpkdFVJf3HEgXCwzkm69kNbRar8MhezFpkIwpk0qo2IOQL4JE4mJPJI8AbRPLbuOQ==", 288 | "cpu": [ 289 | "s390x" 290 | ], 291 | "dev": true, 292 | "optional": true, 293 | "os": [ 294 | "linux" 295 | ], 296 | "engines": { 297 | "node": ">=12" 298 | } 299 | }, 300 | "node_modules/@esbuild/linux-x64": { 301 | "version": "0.17.17", 302 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.17.tgz", 303 | "integrity": "sha512-XcSGTQcWFQS2jx3lZtQi7cQmDYLrpLRyz1Ns1DzZCtn898cWfm5Icx/DEWNcTU+T+tyPV89RQtDnI7qL2PObPg==", 304 | "cpu": [ 305 | "x64" 306 | ], 307 | "dev": true, 308 | "optional": true, 309 | "os": [ 310 | "linux" 311 | ], 312 | "engines": { 313 | "node": ">=12" 314 | } 315 | }, 316 | "node_modules/@esbuild/netbsd-x64": { 317 | "version": "0.17.17", 318 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.17.tgz", 319 | "integrity": "sha512-RNLCDmLP5kCWAJR+ItLM3cHxzXRTe4N00TQyQiimq+lyqVqZWGPAvcyfUBM0isE79eEZhIuGN09rAz8EL5KdLA==", 320 | "cpu": [ 321 | "x64" 322 | ], 323 | "dev": true, 324 | "optional": true, 325 | "os": [ 326 | "netbsd" 327 | ], 328 | "engines": { 329 | "node": ">=12" 330 | } 331 | }, 332 | "node_modules/@esbuild/openbsd-x64": { 333 | "version": "0.17.17", 334 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.17.tgz", 335 | "integrity": "sha512-PAXswI5+cQq3Pann7FNdcpSUrhrql3wKjj3gVkmuz6OHhqqYxKvi6GgRBoaHjaG22HV/ZZEgF9TlS+9ftHVigA==", 336 | "cpu": [ 337 | "x64" 338 | ], 339 | "dev": true, 340 | "optional": true, 341 | "os": [ 342 | "openbsd" 343 | ], 344 | "engines": { 345 | "node": ">=12" 346 | } 347 | }, 348 | "node_modules/@esbuild/sunos-x64": { 349 | "version": "0.17.17", 350 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.17.tgz", 351 | "integrity": "sha512-V63egsWKnx/4V0FMYkr9NXWrKTB5qFftKGKuZKFIrAkO/7EWLFnbBZNM1CvJ6Sis+XBdPws2YQSHF1Gqf1oj/Q==", 352 | "cpu": [ 353 | "x64" 354 | ], 355 | "dev": true, 356 | "optional": true, 357 | "os": [ 358 | "sunos" 359 | ], 360 | "engines": { 361 | "node": ">=12" 362 | } 363 | }, 364 | "node_modules/@esbuild/win32-arm64": { 365 | "version": "0.17.17", 366 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.17.tgz", 367 | "integrity": "sha512-YtUXLdVnd6YBSYlZODjWzH+KzbaubV0YVd6UxSfoFfa5PtNJNaW+1i+Hcmjpg2nEe0YXUCNF5bkKy1NnBv1y7Q==", 368 | "cpu": [ 369 | "arm64" 370 | ], 371 | "dev": true, 372 | "optional": true, 373 | "os": [ 374 | "win32" 375 | ], 376 | "engines": { 377 | "node": ">=12" 378 | } 379 | }, 380 | "node_modules/@esbuild/win32-ia32": { 381 | "version": "0.17.17", 382 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.17.tgz", 383 | "integrity": "sha512-yczSLRbDdReCO74Yfc5tKG0izzm+lPMYyO1fFTcn0QNwnKmc3K+HdxZWLGKg4pZVte7XVgcFku7TIZNbWEJdeQ==", 384 | "cpu": [ 385 | "ia32" 386 | ], 387 | "dev": true, 388 | "optional": true, 389 | "os": [ 390 | "win32" 391 | ], 392 | "engines": { 393 | "node": ">=12" 394 | } 395 | }, 396 | "node_modules/@esbuild/win32-x64": { 397 | "version": "0.17.17", 398 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.17.tgz", 399 | "integrity": "sha512-FNZw7H3aqhF9OyRQbDDnzUApDXfC1N6fgBhkqEO2jvYCJ+DxMTfZVqg3AX0R1khg1wHTBRD5SdcibSJ+XF6bFg==", 400 | "cpu": [ 401 | "x64" 402 | ], 403 | "dev": true, 404 | "optional": true, 405 | "os": [ 406 | "win32" 407 | ], 408 | "engines": { 409 | "node": ">=12" 410 | } 411 | }, 412 | "node_modules/@types/offscreencanvas": { 413 | "version": "2019.7.0", 414 | "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.0.tgz", 415 | "integrity": "sha512-PGcyveRIpL1XIqK8eBsmRBt76eFgtzuPiSTyKHZxnGemp2yzGzWpjYKAfK3wIMiU7eH+851yEpiuP8JZerTmWg==" 416 | }, 417 | "node_modules/@webgpu/glslang": { 418 | "version": "0.0.15", 419 | "resolved": "https://registry.npmjs.org/@webgpu/glslang/-/glslang-0.0.15.tgz", 420 | "integrity": "sha512-niT+Prh3Aff8Uf1MVBVUsaNjFj9rJAKDXuoHIKiQbB+6IUP/3J3JIhBNyZ7lDhytvXxw6ppgnwKZdDJ08UMj4Q==" 421 | }, 422 | "node_modules/ammo.js": { 423 | "version": "0.0.10", 424 | "resolved": "https://registry.npmjs.org/ammo.js/-/ammo.js-0.0.10.tgz", 425 | "integrity": "sha512-jOv977u71jrDUzHfmQ99YaW90/y8YLn/3HFTmtLLzf5wJynAfG+/a1Ie5gbn0fE0uSAHxXVsFk4Bzq8qRPWqAA==" 426 | }, 427 | "node_modules/ammojs-typed": { 428 | "version": "1.0.6", 429 | "resolved": "https://registry.npmjs.org/ammojs-typed/-/ammojs-typed-1.0.6.tgz", 430 | "integrity": "sha512-ut/tD0m5eEdlJ5KK97ma6SIEGZ4FN3AJTSVz8wl6C4EtnpVQdP70lOwgDMJKsHjTohxc2/xEZl6yJfMBZNlQ5w==" 431 | }, 432 | "node_modules/cannon": { 433 | "version": "0.6.2", 434 | "resolved": "https://registry.npmjs.org/cannon/-/cannon-0.6.2.tgz", 435 | "integrity": "sha512-n/7wWSXr8KOSvjad2x0fJHgpMepKjOKi+NdSnjfYyijoDBZnp4JQKgPcpv28jlXoWM+N9zVYU09J0A6Qxx+Y7w==", 436 | "engines": { 437 | "node": "*" 438 | } 439 | }, 440 | "node_modules/chevrotain": { 441 | "version": "10.5.0", 442 | "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-10.5.0.tgz", 443 | "integrity": "sha512-Pkv5rBY3+CsHOYfV5g/Vs5JY9WTHHDEKOlohI2XeygaZhUeqhAlldZ8Hz9cRmxu709bvS08YzxHdTPHhffc13A==", 444 | "dependencies": { 445 | "@chevrotain/cst-dts-gen": "10.5.0", 446 | "@chevrotain/gast": "10.5.0", 447 | "@chevrotain/types": "10.5.0", 448 | "@chevrotain/utils": "10.5.0", 449 | "lodash": "4.17.21", 450 | "regexp-to-ast": "0.5.0" 451 | } 452 | }, 453 | "node_modules/draco3d": { 454 | "version": "1.5.6", 455 | "resolved": "https://registry.npmjs.org/draco3d/-/draco3d-1.5.6.tgz", 456 | "integrity": "sha512-+3NaRjWktb5r61ZFoDejlykPEFKT5N/LkbXsaddlw6xNSXBanUYpFc2AXXpbJDilPHazcSreU/DpQIaxfX0NfQ==" 457 | }, 458 | "node_modules/esbuild": { 459 | "version": "0.17.17", 460 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.17.tgz", 461 | "integrity": "sha512-/jUywtAymR8jR4qsa2RujlAF7Krpt5VWi72Q2yuLD4e/hvtNcFQ0I1j8m/bxq238pf3/0KO5yuXNpuLx8BE1KA==", 462 | "dev": true, 463 | "hasInstallScript": true, 464 | "bin": { 465 | "esbuild": "bin/esbuild" 466 | }, 467 | "engines": { 468 | "node": ">=12" 469 | }, 470 | "optionalDependencies": { 471 | "@esbuild/android-arm": "0.17.17", 472 | "@esbuild/android-arm64": "0.17.17", 473 | "@esbuild/android-x64": "0.17.17", 474 | "@esbuild/darwin-arm64": "0.17.17", 475 | "@esbuild/darwin-x64": "0.17.17", 476 | "@esbuild/freebsd-arm64": "0.17.17", 477 | "@esbuild/freebsd-x64": "0.17.17", 478 | "@esbuild/linux-arm": "0.17.17", 479 | "@esbuild/linux-arm64": "0.17.17", 480 | "@esbuild/linux-ia32": "0.17.17", 481 | "@esbuild/linux-loong64": "0.17.17", 482 | "@esbuild/linux-mips64el": "0.17.17", 483 | "@esbuild/linux-ppc64": "0.17.17", 484 | "@esbuild/linux-riscv64": "0.17.17", 485 | "@esbuild/linux-s390x": "0.17.17", 486 | "@esbuild/linux-x64": "0.17.17", 487 | "@esbuild/netbsd-x64": "0.17.17", 488 | "@esbuild/openbsd-x64": "0.17.17", 489 | "@esbuild/sunos-x64": "0.17.17", 490 | "@esbuild/win32-arm64": "0.17.17", 491 | "@esbuild/win32-ia32": "0.17.17", 492 | "@esbuild/win32-x64": "0.17.17" 493 | } 494 | }, 495 | "node_modules/fflate": { 496 | "version": "0.6.10", 497 | "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.6.10.tgz", 498 | "integrity": "sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==" 499 | }, 500 | "node_modules/fsevents": { 501 | "version": "2.3.2", 502 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 503 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 504 | "dev": true, 505 | "hasInstallScript": true, 506 | "optional": true, 507 | "os": [ 508 | "darwin" 509 | ], 510 | "engines": { 511 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 512 | } 513 | }, 514 | "node_modules/ktx-parse": { 515 | "version": "0.4.5", 516 | "resolved": "https://registry.npmjs.org/ktx-parse/-/ktx-parse-0.4.5.tgz", 517 | "integrity": "sha512-MK3FOody4TXbFf8Yqv7EBbySw7aPvEcPX++Ipt6Sox+/YMFvR5xaTyhfNSk1AEmMy+RYIw81ctN4IMxCB8OAlg==" 518 | }, 519 | "node_modules/lil-gui": { 520 | "version": "0.18.2", 521 | "resolved": "https://registry.npmjs.org/lil-gui/-/lil-gui-0.18.2.tgz", 522 | "integrity": "sha512-DgdrLy3/KGC0PiQLKgOcJMPItP4xY4iWgJ9+91Zaxfr8GCTmMps05QS9w9jW7yspILlbscbquwjOwxmWnSx5Uw==" 523 | }, 524 | "node_modules/lodash": { 525 | "version": "4.17.21", 526 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 527 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 528 | }, 529 | "node_modules/mmd-parser": { 530 | "version": "1.0.4", 531 | "resolved": "https://registry.npmjs.org/mmd-parser/-/mmd-parser-1.0.4.tgz", 532 | "integrity": "sha512-Qi0VCU46t2IwfGv5KF0+D/t9cizcDug7qnNoy9Ggk7aucp0tssV8IwTMkBlDbm+VqAf3cdQHTCARKSsuS2MYFg==" 533 | }, 534 | "node_modules/nanoid": { 535 | "version": "3.3.6", 536 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", 537 | "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", 538 | "dev": true, 539 | "funding": [ 540 | { 541 | "type": "github", 542 | "url": "https://github.com/sponsors/ai" 543 | } 544 | ], 545 | "bin": { 546 | "nanoid": "bin/nanoid.cjs" 547 | }, 548 | "engines": { 549 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 550 | } 551 | }, 552 | "node_modules/opentype.js": { 553 | "version": "1.3.4", 554 | "resolved": "https://registry.npmjs.org/opentype.js/-/opentype.js-1.3.4.tgz", 555 | "integrity": "sha512-d2JE9RP/6uagpQAVtJoF0pJJA/fgai89Cc50Yp0EJHk+eLp6QQ7gBoblsnubRULNY132I0J1QKMJ+JTbMqz4sw==", 556 | "dependencies": { 557 | "string.prototype.codepointat": "^0.2.1", 558 | "tiny-inflate": "^1.0.3" 559 | }, 560 | "bin": { 561 | "ot": "bin/ot" 562 | }, 563 | "engines": { 564 | "node": ">= 8.0.0" 565 | } 566 | }, 567 | "node_modules/picocolors": { 568 | "version": "1.0.0", 569 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", 570 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", 571 | "dev": true 572 | }, 573 | "node_modules/postcss": { 574 | "version": "8.4.23", 575 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz", 576 | "integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==", 577 | "dev": true, 578 | "funding": [ 579 | { 580 | "type": "opencollective", 581 | "url": "https://opencollective.com/postcss/" 582 | }, 583 | { 584 | "type": "tidelift", 585 | "url": "https://tidelift.com/funding/github/npm/postcss" 586 | }, 587 | { 588 | "type": "github", 589 | "url": "https://github.com/sponsors/ai" 590 | } 591 | ], 592 | "dependencies": { 593 | "nanoid": "^3.3.6", 594 | "picocolors": "^1.0.0", 595 | "source-map-js": "^1.0.2" 596 | }, 597 | "engines": { 598 | "node": "^10 || ^12 || >=14" 599 | } 600 | }, 601 | "node_modules/potpack": { 602 | "version": "1.0.2", 603 | "resolved": "https://registry.npmjs.org/potpack/-/potpack-1.0.2.tgz", 604 | "integrity": "sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==" 605 | }, 606 | "node_modules/regenerator-runtime": { 607 | "version": "0.13.11", 608 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", 609 | "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" 610 | }, 611 | "node_modules/regexp-to-ast": { 612 | "version": "0.5.0", 613 | "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz", 614 | "integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==" 615 | }, 616 | "node_modules/rollup": { 617 | "version": "3.20.7", 618 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.20.7.tgz", 619 | "integrity": "sha512-P7E2zezKSLhWnTz46XxjSmInrbOCiul1yf+kJccMxT56vxjHwCbDfoLbiqFgu+WQoo9ij2PkraYaBstgB2prBA==", 620 | "dev": true, 621 | "bin": { 622 | "rollup": "dist/bin/rollup" 623 | }, 624 | "engines": { 625 | "node": ">=14.18.0", 626 | "npm": ">=8.0.0" 627 | }, 628 | "optionalDependencies": { 629 | "fsevents": "~2.3.2" 630 | } 631 | }, 632 | "node_modules/source-map-js": { 633 | "version": "1.0.2", 634 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", 635 | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", 636 | "dev": true, 637 | "engines": { 638 | "node": ">=0.10.0" 639 | } 640 | }, 641 | "node_modules/string.prototype.codepointat": { 642 | "version": "0.2.1", 643 | "resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.1.tgz", 644 | "integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==" 645 | }, 646 | "node_modules/three": { 647 | "version": "0.151.3", 648 | "resolved": "https://registry.npmjs.org/three/-/three-0.151.3.tgz", 649 | "integrity": "sha512-+vbuqxFy8kzLeO5MgpBHUvP/EAiecaDwDuOPPDe6SbrZr96kccF0ktLngXc7xA7bzyd3N0t2f6mw3Z9y6JCojQ==" 650 | }, 651 | "node_modules/three-stdlib": { 652 | "version": "2.21.8", 653 | "resolved": "https://registry.npmjs.org/three-stdlib/-/three-stdlib-2.21.8.tgz", 654 | "integrity": "sha512-kqisiKvO4mSy59v5vWqBQSH8famLxp7Z51LxpMJI9GwDxqODaW02rhIwmjYDEzZWNFpjZpoDHVGbdpeHf8h3SA==", 655 | "dependencies": { 656 | "@babel/runtime": "^7.16.7", 657 | "@types/offscreencanvas": "^2019.6.4", 658 | "@webgpu/glslang": "^0.0.15", 659 | "chevrotain": "^10.1.2", 660 | "draco3d": "^1.4.1", 661 | "fflate": "^0.6.9", 662 | "ktx-parse": "^0.4.5", 663 | "mmd-parser": "^1.0.4", 664 | "opentype.js": "^1.3.3", 665 | "potpack": "^1.0.1", 666 | "zstddec": "^0.0.2" 667 | }, 668 | "peerDependencies": { 669 | "three": ">=0.122.0" 670 | } 671 | }, 672 | "node_modules/tiny-inflate": { 673 | "version": "1.0.3", 674 | "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", 675 | "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==" 676 | }, 677 | "node_modules/vite": { 678 | "version": "4.3.1", 679 | "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.1.tgz", 680 | "integrity": "sha512-EPmfPLAI79Z/RofuMvkIS0Yr091T2ReUoXQqc5ppBX/sjFRhHKiPPF/R46cTdoci/XgeQpB23diiJxq5w30vdg==", 681 | "dev": true, 682 | "dependencies": { 683 | "esbuild": "^0.17.5", 684 | "postcss": "^8.4.21", 685 | "rollup": "^3.20.2" 686 | }, 687 | "bin": { 688 | "vite": "bin/vite.js" 689 | }, 690 | "engines": { 691 | "node": "^14.18.0 || >=16.0.0" 692 | }, 693 | "optionalDependencies": { 694 | "fsevents": "~2.3.2" 695 | }, 696 | "peerDependencies": { 697 | "@types/node": ">= 14", 698 | "less": "*", 699 | "sass": "*", 700 | "stylus": "*", 701 | "sugarss": "*", 702 | "terser": "^5.4.0" 703 | }, 704 | "peerDependenciesMeta": { 705 | "@types/node": { 706 | "optional": true 707 | }, 708 | "less": { 709 | "optional": true 710 | }, 711 | "sass": { 712 | "optional": true 713 | }, 714 | "stylus": { 715 | "optional": true 716 | }, 717 | "sugarss": { 718 | "optional": true 719 | }, 720 | "terser": { 721 | "optional": true 722 | } 723 | } 724 | }, 725 | "node_modules/zstddec": { 726 | "version": "0.0.2", 727 | "resolved": "https://registry.npmjs.org/zstddec/-/zstddec-0.0.2.tgz", 728 | "integrity": "sha512-DCo0oxvcvOTGP/f5FA6tz2Z6wF+FIcEApSTu0zV5sQgn9hoT5lZ9YRAKUraxt9oP7l4e8TnNdi8IZTCX6WCkwA==" 729 | } 730 | }, 731 | "dependencies": { 732 | "@babel/runtime": { 733 | "version": "7.21.0", 734 | "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", 735 | "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", 736 | "requires": { 737 | "regenerator-runtime": "^0.13.11" 738 | } 739 | }, 740 | "@chevrotain/cst-dts-gen": { 741 | "version": "10.5.0", 742 | "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-10.5.0.tgz", 743 | "integrity": "sha512-lhmC/FyqQ2o7pGK4Om+hzuDrm9rhFYIJ/AXoQBeongmn870Xeb0L6oGEiuR8nohFNL5sMaQEJWCxr1oIVIVXrw==", 744 | "requires": { 745 | "@chevrotain/gast": "10.5.0", 746 | "@chevrotain/types": "10.5.0", 747 | "lodash": "4.17.21" 748 | } 749 | }, 750 | "@chevrotain/gast": { 751 | "version": "10.5.0", 752 | "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-10.5.0.tgz", 753 | "integrity": "sha512-pXdMJ9XeDAbgOWKuD1Fldz4ieCs6+nLNmyVhe2gZVqoO7v8HXuHYs5OV2EzUtbuai37TlOAQHrTDvxMnvMJz3A==", 754 | "requires": { 755 | "@chevrotain/types": "10.5.0", 756 | "lodash": "4.17.21" 757 | } 758 | }, 759 | "@chevrotain/types": { 760 | "version": "10.5.0", 761 | "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-10.5.0.tgz", 762 | "integrity": "sha512-f1MAia0x/pAVPWH/T73BJVyO2XU5tI4/iE7cnxb7tqdNTNhQI3Uq3XkqcoteTmD4t1aM0LbHCJOhgIDn07kl2A==" 763 | }, 764 | "@chevrotain/utils": { 765 | "version": "10.5.0", 766 | "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-10.5.0.tgz", 767 | "integrity": "sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ==" 768 | }, 769 | "@esbuild/android-arm": { 770 | "version": "0.17.17", 771 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.17.tgz", 772 | "integrity": "sha512-E6VAZwN7diCa3labs0GYvhEPL2M94WLF8A+czO8hfjREXxba8Ng7nM5VxV+9ihNXIY1iQO1XxUU4P7hbqbICxg==", 773 | "dev": true, 774 | "optional": true 775 | }, 776 | "@esbuild/android-arm64": { 777 | "version": "0.17.17", 778 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.17.tgz", 779 | "integrity": "sha512-jaJ5IlmaDLFPNttv0ofcwy/cfeY4bh/n705Tgh+eLObbGtQBK3EPAu+CzL95JVE4nFAliyrnEu0d32Q5foavqg==", 780 | "dev": true, 781 | "optional": true 782 | }, 783 | "@esbuild/android-x64": { 784 | "version": "0.17.17", 785 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.17.tgz", 786 | "integrity": "sha512-446zpfJ3nioMC7ASvJB1pszHVskkw4u/9Eu8s5yvvsSDTzYh4p4ZIRj0DznSl3FBF0Z/mZfrKXTtt0QCoFmoHA==", 787 | "dev": true, 788 | "optional": true 789 | }, 790 | "@esbuild/darwin-arm64": { 791 | "version": "0.17.17", 792 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.17.tgz", 793 | "integrity": "sha512-m/gwyiBwH3jqfUabtq3GH31otL/0sE0l34XKpSIqR7NjQ/XHQ3lpmQHLHbG8AHTGCw8Ao059GvV08MS0bhFIJQ==", 794 | "dev": true, 795 | "optional": true 796 | }, 797 | "@esbuild/darwin-x64": { 798 | "version": "0.17.17", 799 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.17.tgz", 800 | "integrity": "sha512-4utIrsX9IykrqYaXR8ob9Ha2hAY2qLc6ohJ8c0CN1DR8yWeMrTgYFjgdeQ9LIoTOfLetXjuCu5TRPHT9yKYJVg==", 801 | "dev": true, 802 | "optional": true 803 | }, 804 | "@esbuild/freebsd-arm64": { 805 | "version": "0.17.17", 806 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.17.tgz", 807 | "integrity": "sha512-4PxjQII/9ppOrpEwzQ1b0pXCsFLqy77i0GaHodrmzH9zq2/NEhHMAMJkJ635Ns4fyJPFOlHMz4AsklIyRqFZWA==", 808 | "dev": true, 809 | "optional": true 810 | }, 811 | "@esbuild/freebsd-x64": { 812 | "version": "0.17.17", 813 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.17.tgz", 814 | "integrity": "sha512-lQRS+4sW5S3P1sv0z2Ym807qMDfkmdhUYX30GRBURtLTrJOPDpoU0kI6pVz1hz3U0+YQ0tXGS9YWveQjUewAJw==", 815 | "dev": true, 816 | "optional": true 817 | }, 818 | "@esbuild/linux-arm": { 819 | "version": "0.17.17", 820 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.17.tgz", 821 | "integrity": "sha512-biDs7bjGdOdcmIk6xU426VgdRUpGg39Yz6sT9Xp23aq+IEHDb/u5cbmu/pAANpDB4rZpY/2USPhCA+w9t3roQg==", 822 | "dev": true, 823 | "optional": true 824 | }, 825 | "@esbuild/linux-arm64": { 826 | "version": "0.17.17", 827 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.17.tgz", 828 | "integrity": "sha512-2+pwLx0whKY1/Vqt8lyzStyda1v0qjJ5INWIe+d8+1onqQxHLLi3yr5bAa4gvbzhZqBztifYEu8hh1La5+7sUw==", 829 | "dev": true, 830 | "optional": true 831 | }, 832 | "@esbuild/linux-ia32": { 833 | "version": "0.17.17", 834 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.17.tgz", 835 | "integrity": "sha512-IBTTv8X60dYo6P2t23sSUYym8fGfMAiuv7PzJ+0LcdAndZRzvke+wTVxJeCq4WgjppkOpndL04gMZIFvwoU34Q==", 836 | "dev": true, 837 | "optional": true 838 | }, 839 | "@esbuild/linux-loong64": { 840 | "version": "0.17.17", 841 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.17.tgz", 842 | "integrity": "sha512-WVMBtcDpATjaGfWfp6u9dANIqmU9r37SY8wgAivuKmgKHE+bWSuv0qXEFt/p3qXQYxJIGXQQv6hHcm7iWhWjiw==", 843 | "dev": true, 844 | "optional": true 845 | }, 846 | "@esbuild/linux-mips64el": { 847 | "version": "0.17.17", 848 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.17.tgz", 849 | "integrity": "sha512-2kYCGh8589ZYnY031FgMLy0kmE4VoGdvfJkxLdxP4HJvWNXpyLhjOvxVsYjYZ6awqY4bgLR9tpdYyStgZZhi2A==", 850 | "dev": true, 851 | "optional": true 852 | }, 853 | "@esbuild/linux-ppc64": { 854 | "version": "0.17.17", 855 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.17.tgz", 856 | "integrity": "sha512-KIdG5jdAEeAKogfyMTcszRxy3OPbZhq0PPsW4iKKcdlbk3YE4miKznxV2YOSmiK/hfOZ+lqHri3v8eecT2ATwQ==", 857 | "dev": true, 858 | "optional": true 859 | }, 860 | "@esbuild/linux-riscv64": { 861 | "version": "0.17.17", 862 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.17.tgz", 863 | "integrity": "sha512-Cj6uWLBR5LWhcD/2Lkfg2NrkVsNb2sFM5aVEfumKB2vYetkA/9Uyc1jVoxLZ0a38sUhFk4JOVKH0aVdPbjZQeA==", 864 | "dev": true, 865 | "optional": true 866 | }, 867 | "@esbuild/linux-s390x": { 868 | "version": "0.17.17", 869 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.17.tgz", 870 | "integrity": "sha512-lK+SffWIr0XsFf7E0srBjhpkdFVJf3HEgXCwzkm69kNbRar8MhezFpkIwpk0qo2IOQL4JE4mJPJI8AbRPLbuOQ==", 871 | "dev": true, 872 | "optional": true 873 | }, 874 | "@esbuild/linux-x64": { 875 | "version": "0.17.17", 876 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.17.tgz", 877 | "integrity": "sha512-XcSGTQcWFQS2jx3lZtQi7cQmDYLrpLRyz1Ns1DzZCtn898cWfm5Icx/DEWNcTU+T+tyPV89RQtDnI7qL2PObPg==", 878 | "dev": true, 879 | "optional": true 880 | }, 881 | "@esbuild/netbsd-x64": { 882 | "version": "0.17.17", 883 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.17.tgz", 884 | "integrity": "sha512-RNLCDmLP5kCWAJR+ItLM3cHxzXRTe4N00TQyQiimq+lyqVqZWGPAvcyfUBM0isE79eEZhIuGN09rAz8EL5KdLA==", 885 | "dev": true, 886 | "optional": true 887 | }, 888 | "@esbuild/openbsd-x64": { 889 | "version": "0.17.17", 890 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.17.tgz", 891 | "integrity": "sha512-PAXswI5+cQq3Pann7FNdcpSUrhrql3wKjj3gVkmuz6OHhqqYxKvi6GgRBoaHjaG22HV/ZZEgF9TlS+9ftHVigA==", 892 | "dev": true, 893 | "optional": true 894 | }, 895 | "@esbuild/sunos-x64": { 896 | "version": "0.17.17", 897 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.17.tgz", 898 | "integrity": "sha512-V63egsWKnx/4V0FMYkr9NXWrKTB5qFftKGKuZKFIrAkO/7EWLFnbBZNM1CvJ6Sis+XBdPws2YQSHF1Gqf1oj/Q==", 899 | "dev": true, 900 | "optional": true 901 | }, 902 | "@esbuild/win32-arm64": { 903 | "version": "0.17.17", 904 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.17.tgz", 905 | "integrity": "sha512-YtUXLdVnd6YBSYlZODjWzH+KzbaubV0YVd6UxSfoFfa5PtNJNaW+1i+Hcmjpg2nEe0YXUCNF5bkKy1NnBv1y7Q==", 906 | "dev": true, 907 | "optional": true 908 | }, 909 | "@esbuild/win32-ia32": { 910 | "version": "0.17.17", 911 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.17.tgz", 912 | "integrity": "sha512-yczSLRbDdReCO74Yfc5tKG0izzm+lPMYyO1fFTcn0QNwnKmc3K+HdxZWLGKg4pZVte7XVgcFku7TIZNbWEJdeQ==", 913 | "dev": true, 914 | "optional": true 915 | }, 916 | "@esbuild/win32-x64": { 917 | "version": "0.17.17", 918 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.17.tgz", 919 | "integrity": "sha512-FNZw7H3aqhF9OyRQbDDnzUApDXfC1N6fgBhkqEO2jvYCJ+DxMTfZVqg3AX0R1khg1wHTBRD5SdcibSJ+XF6bFg==", 920 | "dev": true, 921 | "optional": true 922 | }, 923 | "@types/offscreencanvas": { 924 | "version": "2019.7.0", 925 | "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.0.tgz", 926 | "integrity": "sha512-PGcyveRIpL1XIqK8eBsmRBt76eFgtzuPiSTyKHZxnGemp2yzGzWpjYKAfK3wIMiU7eH+851yEpiuP8JZerTmWg==" 927 | }, 928 | "@webgpu/glslang": { 929 | "version": "0.0.15", 930 | "resolved": "https://registry.npmjs.org/@webgpu/glslang/-/glslang-0.0.15.tgz", 931 | "integrity": "sha512-niT+Prh3Aff8Uf1MVBVUsaNjFj9rJAKDXuoHIKiQbB+6IUP/3J3JIhBNyZ7lDhytvXxw6ppgnwKZdDJ08UMj4Q==" 932 | }, 933 | "ammo.js": { 934 | "version": "0.0.10", 935 | "resolved": "https://registry.npmjs.org/ammo.js/-/ammo.js-0.0.10.tgz", 936 | "integrity": "sha512-jOv977u71jrDUzHfmQ99YaW90/y8YLn/3HFTmtLLzf5wJynAfG+/a1Ie5gbn0fE0uSAHxXVsFk4Bzq8qRPWqAA==" 937 | }, 938 | "ammojs-typed": { 939 | "version": "1.0.6", 940 | "resolved": "https://registry.npmjs.org/ammojs-typed/-/ammojs-typed-1.0.6.tgz", 941 | "integrity": "sha512-ut/tD0m5eEdlJ5KK97ma6SIEGZ4FN3AJTSVz8wl6C4EtnpVQdP70lOwgDMJKsHjTohxc2/xEZl6yJfMBZNlQ5w==" 942 | }, 943 | "cannon": { 944 | "version": "0.6.2", 945 | "resolved": "https://registry.npmjs.org/cannon/-/cannon-0.6.2.tgz", 946 | "integrity": "sha512-n/7wWSXr8KOSvjad2x0fJHgpMepKjOKi+NdSnjfYyijoDBZnp4JQKgPcpv28jlXoWM+N9zVYU09J0A6Qxx+Y7w==" 947 | }, 948 | "chevrotain": { 949 | "version": "10.5.0", 950 | "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-10.5.0.tgz", 951 | "integrity": "sha512-Pkv5rBY3+CsHOYfV5g/Vs5JY9WTHHDEKOlohI2XeygaZhUeqhAlldZ8Hz9cRmxu709bvS08YzxHdTPHhffc13A==", 952 | "requires": { 953 | "@chevrotain/cst-dts-gen": "10.5.0", 954 | "@chevrotain/gast": "10.5.0", 955 | "@chevrotain/types": "10.5.0", 956 | "@chevrotain/utils": "10.5.0", 957 | "lodash": "4.17.21", 958 | "regexp-to-ast": "0.5.0" 959 | } 960 | }, 961 | "draco3d": { 962 | "version": "1.5.6", 963 | "resolved": "https://registry.npmjs.org/draco3d/-/draco3d-1.5.6.tgz", 964 | "integrity": "sha512-+3NaRjWktb5r61ZFoDejlykPEFKT5N/LkbXsaddlw6xNSXBanUYpFc2AXXpbJDilPHazcSreU/DpQIaxfX0NfQ==" 965 | }, 966 | "esbuild": { 967 | "version": "0.17.17", 968 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.17.tgz", 969 | "integrity": "sha512-/jUywtAymR8jR4qsa2RujlAF7Krpt5VWi72Q2yuLD4e/hvtNcFQ0I1j8m/bxq238pf3/0KO5yuXNpuLx8BE1KA==", 970 | "dev": true, 971 | "requires": { 972 | "@esbuild/android-arm": "0.17.17", 973 | "@esbuild/android-arm64": "0.17.17", 974 | "@esbuild/android-x64": "0.17.17", 975 | "@esbuild/darwin-arm64": "0.17.17", 976 | "@esbuild/darwin-x64": "0.17.17", 977 | "@esbuild/freebsd-arm64": "0.17.17", 978 | "@esbuild/freebsd-x64": "0.17.17", 979 | "@esbuild/linux-arm": "0.17.17", 980 | "@esbuild/linux-arm64": "0.17.17", 981 | "@esbuild/linux-ia32": "0.17.17", 982 | "@esbuild/linux-loong64": "0.17.17", 983 | "@esbuild/linux-mips64el": "0.17.17", 984 | "@esbuild/linux-ppc64": "0.17.17", 985 | "@esbuild/linux-riscv64": "0.17.17", 986 | "@esbuild/linux-s390x": "0.17.17", 987 | "@esbuild/linux-x64": "0.17.17", 988 | "@esbuild/netbsd-x64": "0.17.17", 989 | "@esbuild/openbsd-x64": "0.17.17", 990 | "@esbuild/sunos-x64": "0.17.17", 991 | "@esbuild/win32-arm64": "0.17.17", 992 | "@esbuild/win32-ia32": "0.17.17", 993 | "@esbuild/win32-x64": "0.17.17" 994 | } 995 | }, 996 | "fflate": { 997 | "version": "0.6.10", 998 | "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.6.10.tgz", 999 | "integrity": "sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==" 1000 | }, 1001 | "fsevents": { 1002 | "version": "2.3.2", 1003 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 1004 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 1005 | "dev": true, 1006 | "optional": true 1007 | }, 1008 | "ktx-parse": { 1009 | "version": "0.4.5", 1010 | "resolved": "https://registry.npmjs.org/ktx-parse/-/ktx-parse-0.4.5.tgz", 1011 | "integrity": "sha512-MK3FOody4TXbFf8Yqv7EBbySw7aPvEcPX++Ipt6Sox+/YMFvR5xaTyhfNSk1AEmMy+RYIw81ctN4IMxCB8OAlg==" 1012 | }, 1013 | "lil-gui": { 1014 | "version": "0.18.2", 1015 | "resolved": "https://registry.npmjs.org/lil-gui/-/lil-gui-0.18.2.tgz", 1016 | "integrity": "sha512-DgdrLy3/KGC0PiQLKgOcJMPItP4xY4iWgJ9+91Zaxfr8GCTmMps05QS9w9jW7yspILlbscbquwjOwxmWnSx5Uw==" 1017 | }, 1018 | "lodash": { 1019 | "version": "4.17.21", 1020 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 1021 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 1022 | }, 1023 | "mmd-parser": { 1024 | "version": "1.0.4", 1025 | "resolved": "https://registry.npmjs.org/mmd-parser/-/mmd-parser-1.0.4.tgz", 1026 | "integrity": "sha512-Qi0VCU46t2IwfGv5KF0+D/t9cizcDug7qnNoy9Ggk7aucp0tssV8IwTMkBlDbm+VqAf3cdQHTCARKSsuS2MYFg==" 1027 | }, 1028 | "nanoid": { 1029 | "version": "3.3.6", 1030 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", 1031 | "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", 1032 | "dev": true 1033 | }, 1034 | "opentype.js": { 1035 | "version": "1.3.4", 1036 | "resolved": "https://registry.npmjs.org/opentype.js/-/opentype.js-1.3.4.tgz", 1037 | "integrity": "sha512-d2JE9RP/6uagpQAVtJoF0pJJA/fgai89Cc50Yp0EJHk+eLp6QQ7gBoblsnubRULNY132I0J1QKMJ+JTbMqz4sw==", 1038 | "requires": { 1039 | "string.prototype.codepointat": "^0.2.1", 1040 | "tiny-inflate": "^1.0.3" 1041 | } 1042 | }, 1043 | "picocolors": { 1044 | "version": "1.0.0", 1045 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", 1046 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", 1047 | "dev": true 1048 | }, 1049 | "postcss": { 1050 | "version": "8.4.23", 1051 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz", 1052 | "integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==", 1053 | "dev": true, 1054 | "requires": { 1055 | "nanoid": "^3.3.6", 1056 | "picocolors": "^1.0.0", 1057 | "source-map-js": "^1.0.2" 1058 | } 1059 | }, 1060 | "potpack": { 1061 | "version": "1.0.2", 1062 | "resolved": "https://registry.npmjs.org/potpack/-/potpack-1.0.2.tgz", 1063 | "integrity": "sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==" 1064 | }, 1065 | "regenerator-runtime": { 1066 | "version": "0.13.11", 1067 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", 1068 | "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" 1069 | }, 1070 | "regexp-to-ast": { 1071 | "version": "0.5.0", 1072 | "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz", 1073 | "integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==" 1074 | }, 1075 | "rollup": { 1076 | "version": "3.20.7", 1077 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.20.7.tgz", 1078 | "integrity": "sha512-P7E2zezKSLhWnTz46XxjSmInrbOCiul1yf+kJccMxT56vxjHwCbDfoLbiqFgu+WQoo9ij2PkraYaBstgB2prBA==", 1079 | "dev": true, 1080 | "requires": { 1081 | "fsevents": "~2.3.2" 1082 | } 1083 | }, 1084 | "source-map-js": { 1085 | "version": "1.0.2", 1086 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", 1087 | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", 1088 | "dev": true 1089 | }, 1090 | "string.prototype.codepointat": { 1091 | "version": "0.2.1", 1092 | "resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.1.tgz", 1093 | "integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==" 1094 | }, 1095 | "three": { 1096 | "version": "0.151.3", 1097 | "resolved": "https://registry.npmjs.org/three/-/three-0.151.3.tgz", 1098 | "integrity": "sha512-+vbuqxFy8kzLeO5MgpBHUvP/EAiecaDwDuOPPDe6SbrZr96kccF0ktLngXc7xA7bzyd3N0t2f6mw3Z9y6JCojQ==" 1099 | }, 1100 | "three-stdlib": { 1101 | "version": "2.21.8", 1102 | "resolved": "https://registry.npmjs.org/three-stdlib/-/three-stdlib-2.21.8.tgz", 1103 | "integrity": "sha512-kqisiKvO4mSy59v5vWqBQSH8famLxp7Z51LxpMJI9GwDxqODaW02rhIwmjYDEzZWNFpjZpoDHVGbdpeHf8h3SA==", 1104 | "requires": { 1105 | "@babel/runtime": "^7.16.7", 1106 | "@types/offscreencanvas": "^2019.6.4", 1107 | "@webgpu/glslang": "^0.0.15", 1108 | "chevrotain": "^10.1.2", 1109 | "draco3d": "^1.4.1", 1110 | "fflate": "^0.6.9", 1111 | "ktx-parse": "^0.4.5", 1112 | "mmd-parser": "^1.0.4", 1113 | "opentype.js": "^1.3.3", 1114 | "potpack": "^1.0.1", 1115 | "zstddec": "^0.0.2" 1116 | } 1117 | }, 1118 | "tiny-inflate": { 1119 | "version": "1.0.3", 1120 | "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", 1121 | "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==" 1122 | }, 1123 | "vite": { 1124 | "version": "4.3.1", 1125 | "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.1.tgz", 1126 | "integrity": "sha512-EPmfPLAI79Z/RofuMvkIS0Yr091T2ReUoXQqc5ppBX/sjFRhHKiPPF/R46cTdoci/XgeQpB23diiJxq5w30vdg==", 1127 | "dev": true, 1128 | "requires": { 1129 | "esbuild": "^0.17.5", 1130 | "fsevents": "~2.3.2", 1131 | "postcss": "^8.4.21", 1132 | "rollup": "^3.20.2" 1133 | } 1134 | }, 1135 | "zstddec": { 1136 | "version": "0.0.2", 1137 | "resolved": "https://registry.npmjs.org/zstddec/-/zstddec-0.0.2.tgz", 1138 | "integrity": "sha512-DCo0oxvcvOTGP/f5FA6tz2Z6wF+FIcEApSTu0zV5sQgn9hoT5lZ9YRAKUraxt9oP7l4e8TnNdi8IZTCX6WCkwA==" 1139 | } 1140 | } 1141 | } 1142 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "repository": "https://github.com/theringsofsaturn/3D-art-gallery", 3 | "author": { 4 | "name": "Emilian Kasemi", 5 | "email": "emiliankasemi@gmail.com" 6 | }, 7 | "license": "Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International", 8 | "dependencies": { 9 | "ammo.js": "^0.0.10", 10 | "ammojs-typed": "^1.0.6", 11 | "cannon": "^0.6.2", 12 | "lil-gui": "^0.18.2", 13 | "three": "^0.151.3", 14 | "three-stdlib": "^2.21.8" 15 | }, 16 | "devDependencies": { 17 | "vite": "^4.3.1" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /public/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/.DS_Store -------------------------------------------------------------------------------- /public/OfficeCeiling005_4K-JPG/OfficeCeiling005_4K-JPG.usda: -------------------------------------------------------------------------------- 1 | #usda 1.0 2 | ( 3 | customLayerData = { 4 | string author = "ambientCG (ambientCG.com)" 5 | string copyright = "CC0 1.0 Public Domain Dedication (https://creativecommons.org/publicdomain/zero/1.0/)" 6 | string generator = "ambientCG USD Script (v2)" 7 | string title = "OfficeCeiling005 by ambientCG" 8 | string url = "https://ambientcg.com/a/OfficeCeiling005" 9 | } 10 | defaultPrim = "ambientCG_OfficeCeiling005_4K_JPG" 11 | ) 12 | 13 | def Material "ambientCG_OfficeCeiling005_4K_JPG" 14 | { 15 | token outputs:surface.connect = 16 | 17 | def Shader "TextureCoordinateReader" 18 | { 19 | uniform token info:id = "UsdPrimvarReader_float2" 20 | token inputs:varname = "st" 21 | float2 outputs:result 22 | } 23 | 24 | def Shader "PBRShader" 25 | { 26 | uniform token info:id = "UsdPreviewSurface" 27 | color3f inputs:diffuseColor.connect = 28 | color3f inputs:emissiveColor.connect = 29 | float inputs:metallic.connect = 30 | float inputs:displacement.connect = 31 | normal3f inputs:normal.connect = 32 | float inputs:occlusion.connect = 33 | float inputs:roughness.connect = 34 | int inputs:useSpecularWorkflow = 0 35 | token outputs:surface 36 | } 37 | 38 | def Shader "diffuseColor" 39 | { 40 | uniform token info:id = "UsdUVTexture" 41 | float4 inputs:fallback = (0.8, 0.8, 0.8, 1) 42 | asset inputs:file = @OfficeCeiling005_4K_Color.jpg@ 43 | float2 inputs:st.connect = 44 | token inputs:sourceColorSpace = "sRGB" 45 | token inputs:wrapS = "repeat" 46 | token inputs:wrapT = "repeat" 47 | float3 outputs:rgb 48 | } 49 | 50 | def Shader "occlusion" 51 | { 52 | uniform token info:id = "UsdUVTexture" 53 | float4 inputs:fallback = (1, 1, 1, 1) 54 | asset inputs:file = @OfficeCeiling005_4K_AmbientOcclusion.jpg@ 55 | float2 inputs:st.connect = 56 | token inputs:sourceColorSpace = "raw" 57 | token inputs:wrapS = "repeat" 58 | token inputs:wrapT = "repeat" 59 | float outputs:r 60 | } 61 | 62 | def Shader "emissiveColor" 63 | { 64 | uniform token info:id = "UsdUVTexture" 65 | asset inputs:file = @OfficeCeiling005_4K_Emission.jpg@ 66 | float2 inputs:st.connect = 67 | token inputs:sourceColorSpace = "raw" 68 | token inputs:wrapS = "repeat" 69 | token inputs:wrapT = "repeat" 70 | float3 outputs:rgb 71 | } 72 | 73 | def Shader "displacement" 74 | { 75 | uniform token info:id = "UsdUVTexture" 76 | float4 inputs:fallback = (0.5, 0.5, 0.5, 1) 77 | asset inputs:file = @OfficeCeiling005_4K_Displacement.jpg@ 78 | float2 inputs:st.connect = 79 | token inputs:sourceColorSpace = "raw" 80 | token inputs:wrapS = "repeat" 81 | token inputs:wrapT = "repeat" 82 | float outputs:r 83 | } 84 | 85 | def Shader "roughness" 86 | { 87 | uniform token info:id = "UsdUVTexture" 88 | float4 inputs:fallback = (1, 1, 1, 1) 89 | asset inputs:file = @OfficeCeiling005_4K_Roughness.jpg@ 90 | float2 inputs:st.connect = 91 | token inputs:sourceColorSpace = "raw" 92 | token inputs:wrapS = "repeat" 93 | token inputs:wrapT = "repeat" 94 | float outputs:r 95 | } 96 | 97 | def Shader "metallic" 98 | { 99 | uniform token info:id = "UsdUVTexture" 100 | float4 inputs:fallback = (0, 0, 0, 1) 101 | asset inputs:file = @OfficeCeiling005_4K_Metalness.jpg@ 102 | float2 inputs:st.connect = 103 | token inputs:sourceColorSpace = "raw" 104 | token inputs:wrapS = "repeat" 105 | token inputs:wrapT = "repeat" 106 | float outputs:r 107 | } 108 | 109 | def Shader "normal" 110 | { 111 | uniform token info:id = "UsdUVTexture" 112 | float4 inputs:fallback = (0, 0, 1, 1) 113 | asset inputs:file = @OfficeCeiling005_4K_NormalGL.jpg@ 114 | float2 inputs:st.connect = 115 | float4 inputs:bias = (-1, -1, -1, 0) 116 | float4 inputs:scale = (2, 2, 2, 1) 117 | token inputs:sourceColorSpace = "raw" 118 | token inputs:wrapS = "repeat" 119 | token inputs:wrapT = "repeat" 120 | float3 outputs:rgb 121 | } 122 | } 123 | 124 | -------------------------------------------------------------------------------- /public/OfficeCeiling005_4K-JPG/OfficeCeiling005_4K-JPG.usdc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/OfficeCeiling005_4K-JPG/OfficeCeiling005_4K-JPG.usdc -------------------------------------------------------------------------------- /public/OfficeCeiling005_4K-JPG/OfficeCeiling005_4K_AmbientOcclusion.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f80f6fcb76774fed8b8f76fbe98bb4da79e727395ab626df8a9fad57ba55b6e6 3 | size 14532676 4 | -------------------------------------------------------------------------------- /public/OfficeCeiling005_4K-JPG/OfficeCeiling005_4K_Color.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a119c7ff20527bfd6805112bf5bba9eb19243293c628bb6dc003e8203a5945cc 3 | size 1550637 4 | -------------------------------------------------------------------------------- /public/OfficeCeiling005_4K-JPG/OfficeCeiling005_4K_Displacement.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:84da80e435f798b1139ac0aa0dd5d4cf1c11b62a6d6aab63ea2b28c8107c093f 3 | size 11325205 4 | -------------------------------------------------------------------------------- /public/OfficeCeiling005_4K-JPG/OfficeCeiling005_4K_Emission.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5fd06244e9d9b749d4b95e0b19f84023602b161e6ab0cfc1ae40ea2587ba4dc3 3 | size 251678 4 | -------------------------------------------------------------------------------- /public/OfficeCeiling005_4K-JPG/OfficeCeiling005_4K_Metalness.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:725446c766960f87596050be208b16b88fd2cc33f4a10d78b0d959a6345513bd 3 | size 107242 4 | -------------------------------------------------------------------------------- /public/OfficeCeiling005_4K-JPG/OfficeCeiling005_4K_NormalDX.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:7db9998701cade81f103960a3166bce7a3eec2386ec6b38885f82018b75e8c0e 3 | size 38040126 4 | -------------------------------------------------------------------------------- /public/OfficeCeiling005_4K-JPG/OfficeCeiling005_4K_NormalGL.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:659559a95f0fb77599681a66972b50949ae3f0a92f5e8e00142792233693e392 3 | size 38158650 4 | -------------------------------------------------------------------------------- /public/OfficeCeiling005_4K-JPG/OfficeCeiling005_4K_Roughness.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:cfab223cd1026bf46b0024d5ff2e4fe6cf5ab894de9f9bfe0e8f9c0d33899502 3 | size 4929597 4 | -------------------------------------------------------------------------------- /public/OfficeCeiling005_4K-JPG/OfficeCeiling005_PREVIEW.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c28cee0bb3b3558d4dcc82fbcf0db11d96e77f7773aae5b4eb02fc9421328630 3 | size 294413 4 | -------------------------------------------------------------------------------- /public/WoodFloor040_4K-JPG/WoodFloor040_4K-JPG.usda: -------------------------------------------------------------------------------- 1 | #usda 1.0 2 | ( 3 | customLayerData = { 4 | string author = "ambientCG (ambientCG.com)" 5 | string copyright = "CC0 1.0 Public Domain Dedication (https://creativecommons.org/publicdomain/zero/1.0/)" 6 | string generator = "ambientCG USD Script (v2)" 7 | string title = "WoodFloor040 by ambientCG" 8 | string url = "https://ambientcg.com/a/WoodFloor040" 9 | } 10 | defaultPrim = "ambientCG_WoodFloor040_4K_JPG" 11 | ) 12 | 13 | def Material "ambientCG_WoodFloor040_4K_JPG" 14 | { 15 | token outputs:surface.connect = 16 | 17 | def Shader "TextureCoordinateReader" 18 | { 19 | uniform token info:id = "UsdPrimvarReader_float2" 20 | token inputs:varname = "st" 21 | float2 outputs:result 22 | } 23 | 24 | def Shader "PBRShader" 25 | { 26 | uniform token info:id = "UsdPreviewSurface" 27 | color3f inputs:diffuseColor.connect = 28 | float inputs:displacement.connect = 29 | normal3f inputs:normal.connect = 30 | float inputs:occlusion.connect = 31 | float inputs:roughness.connect = 32 | int inputs:useSpecularWorkflow = 0 33 | token outputs:surface 34 | } 35 | 36 | def Shader "diffuseColor" 37 | { 38 | uniform token info:id = "UsdUVTexture" 39 | float4 inputs:fallback = (0.8, 0.8, 0.8, 1) 40 | asset inputs:file = @WoodFloor040_4K_Color.jpg@ 41 | float2 inputs:st.connect = 42 | token inputs:sourceColorSpace = "sRGB" 43 | token inputs:wrapS = "repeat" 44 | token inputs:wrapT = "repeat" 45 | float3 outputs:rgb 46 | } 47 | 48 | def Shader "occlusion" 49 | { 50 | uniform token info:id = "UsdUVTexture" 51 | float4 inputs:fallback = (1, 1, 1, 1) 52 | asset inputs:file = @WoodFloor040_4K_AmbientOcclusion.jpg@ 53 | float2 inputs:st.connect = 54 | token inputs:sourceColorSpace = "raw" 55 | token inputs:wrapS = "repeat" 56 | token inputs:wrapT = "repeat" 57 | float outputs:r 58 | } 59 | 60 | def Shader "displacement" 61 | { 62 | uniform token info:id = "UsdUVTexture" 63 | float4 inputs:fallback = (0.5, 0.5, 0.5, 1) 64 | asset inputs:file = @WoodFloor040_4K_Displacement.jpg@ 65 | float2 inputs:st.connect = 66 | token inputs:sourceColorSpace = "raw" 67 | token inputs:wrapS = "repeat" 68 | token inputs:wrapT = "repeat" 69 | float outputs:r 70 | } 71 | 72 | def Shader "roughness" 73 | { 74 | uniform token info:id = "UsdUVTexture" 75 | float4 inputs:fallback = (1, 1, 1, 1) 76 | asset inputs:file = @WoodFloor040_4K_Roughness.jpg@ 77 | float2 inputs:st.connect = 78 | token inputs:sourceColorSpace = "raw" 79 | token inputs:wrapS = "repeat" 80 | token inputs:wrapT = "repeat" 81 | float outputs:r 82 | } 83 | 84 | def Shader "normal" 85 | { 86 | uniform token info:id = "UsdUVTexture" 87 | float4 inputs:fallback = (0, 0, 1, 1) 88 | asset inputs:file = @WoodFloor040_4K_NormalGL.jpg@ 89 | float2 inputs:st.connect = 90 | float4 inputs:bias = (-1, -1, -1, 0) 91 | float4 inputs:scale = (2, 2, 2, 1) 92 | token inputs:sourceColorSpace = "raw" 93 | token inputs:wrapS = "repeat" 94 | token inputs:wrapT = "repeat" 95 | float3 outputs:rgb 96 | } 97 | } 98 | 99 | -------------------------------------------------------------------------------- /public/WoodFloor040_4K-JPG/WoodFloor040_4K-JPG.usdc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/WoodFloor040_4K-JPG/WoodFloor040_4K-JPG.usdc -------------------------------------------------------------------------------- /public/WoodFloor040_4K-JPG/WoodFloor040_4K_AmbientOcclusion.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3a3dab1182f30b3d691cd83c89edd720a55eb598810cd236c580b586b5442e04 3 | size 5867907 4 | -------------------------------------------------------------------------------- /public/WoodFloor040_4K-JPG/WoodFloor040_4K_Color.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:64078e7f952a284e0e972dd97cc4955b1b469ca6496f507979ef05ff4fa8e26a 3 | size 11281155 4 | -------------------------------------------------------------------------------- /public/WoodFloor040_4K-JPG/WoodFloor040_4K_Displacement.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ce9e28a4ad88a43c91ee8faf791f2759e77315e4983346e46e98c87a3aafe91e 3 | size 6557610 4 | -------------------------------------------------------------------------------- /public/WoodFloor040_4K-JPG/WoodFloor040_4K_NormalDX.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:700d6898829d0bdf67386b4663cbe4151306330288b56377e77b264368cb8f58 3 | size 20687763 4 | -------------------------------------------------------------------------------- /public/WoodFloor040_4K-JPG/WoodFloor040_4K_NormalGL.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:dbdb4b05461bafbd8ca09f1b0e06a14e05aee13f1d710c6d2fb22aaf938ea6db 3 | size 21817178 4 | -------------------------------------------------------------------------------- /public/WoodFloor040_4K-JPG/WoodFloor040_4K_Roughness.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:daa1b6386f3f95c9438a4d4a804dbb0cd27221f3dc60d7b76112fdd622b6ccdc 3 | size 4959178 4 | -------------------------------------------------------------------------------- /public/WoodFloor040_4K-JPG/WoodFloor040_PREVIEW.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:69f85dcab9a7e412c7e22fd7dba61da0b25f62b4ec034d343a8d7d7b5cbae0bc 3 | size 306683 4 | -------------------------------------------------------------------------------- /public/artworks/0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/0.jpg -------------------------------------------------------------------------------- /public/artworks/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/1.jpg -------------------------------------------------------------------------------- /public/artworks/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/10.jpg -------------------------------------------------------------------------------- /public/artworks/11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/11.jpg -------------------------------------------------------------------------------- /public/artworks/12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/12.jpg -------------------------------------------------------------------------------- /public/artworks/13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/13.jpg -------------------------------------------------------------------------------- /public/artworks/14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/14.jpg -------------------------------------------------------------------------------- /public/artworks/15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/15.jpg -------------------------------------------------------------------------------- /public/artworks/16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/16.jpg -------------------------------------------------------------------------------- /public/artworks/17.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/17.jpg -------------------------------------------------------------------------------- /public/artworks/18.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/18.jpg -------------------------------------------------------------------------------- /public/artworks/19.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/19.jpg -------------------------------------------------------------------------------- /public/artworks/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/2.jpg -------------------------------------------------------------------------------- /public/artworks/20.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/20.jpg -------------------------------------------------------------------------------- /public/artworks/21.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/21.jpg -------------------------------------------------------------------------------- /public/artworks/22.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/22.jpg -------------------------------------------------------------------------------- /public/artworks/23.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/23.jpg -------------------------------------------------------------------------------- /public/artworks/24.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/24.jpg -------------------------------------------------------------------------------- /public/artworks/25.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/25.jpg -------------------------------------------------------------------------------- /public/artworks/26.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/26.jpg -------------------------------------------------------------------------------- /public/artworks/27.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/27.jpg -------------------------------------------------------------------------------- /public/artworks/28.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/28.jpg -------------------------------------------------------------------------------- /public/artworks/29.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/29.jpg -------------------------------------------------------------------------------- /public/artworks/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/3.jpg -------------------------------------------------------------------------------- /public/artworks/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/4.jpg -------------------------------------------------------------------------------- /public/artworks/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/5.jpg -------------------------------------------------------------------------------- /public/artworks/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/6.jpg -------------------------------------------------------------------------------- /public/artworks/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/7.jpg -------------------------------------------------------------------------------- /public/artworks/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/8.jpg -------------------------------------------------------------------------------- /public/artworks/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/artworks/9.jpg -------------------------------------------------------------------------------- /public/img/Floor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/img/Floor.jpg -------------------------------------------------------------------------------- /public/img/brick-wall-painted-white.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/img/brick-wall-painted-white.jpg -------------------------------------------------------------------------------- /public/img/ceiling.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/img/ceiling.jpg -------------------------------------------------------------------------------- /public/img/concrete-wall.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/img/concrete-wall.jpg -------------------------------------------------------------------------------- /public/img/floor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/img/floor.png -------------------------------------------------------------------------------- /public/img/frame.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/img/frame.jpg -------------------------------------------------------------------------------- /public/img/glass-background-with-grid-pattern.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/img/glass-background-with-grid-pattern.jpg -------------------------------------------------------------------------------- /public/img/light-gray-concrete-wall.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/img/light-gray-concrete-wall.jpg -------------------------------------------------------------------------------- /public/img/starrynight.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/img/starrynight.jpg -------------------------------------------------------------------------------- /public/img/wall.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/img/wall.jpg -------------------------------------------------------------------------------- /public/img/white-texture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/img/white-texture.jpg -------------------------------------------------------------------------------- /public/leather_white_4k.gltf/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/leather_white_4k.gltf/.DS_Store -------------------------------------------------------------------------------- /public/leather_white_4k.gltf/leather_white.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:93f11fb16588c30f48ad50da6e4432b063b00fbc09c2f26e5914b60aecad3f67 3 | size 2369012 4 | -------------------------------------------------------------------------------- /public/leather_white_4k.gltf/leather_white_4k.gltf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0a6113123c481572702eaa44a47961ec4aef84779518f192dc1f905e9fa826a4 3 | size 2714 4 | -------------------------------------------------------------------------------- /public/leather_white_4k.gltf/textures/leather_white_diff_4k.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4290cd40c33b2e1d8e1037186babd39db5f9e533f1f671d05e75b890ed995467 3 | size 10362553 4 | -------------------------------------------------------------------------------- /public/leather_white_4k.gltf/textures/leather_white_nor_gl_4k.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0c80416ae3e0ad2057a1026bb252e27877cee21067e3631d6e1bf7081bf5a9ea 3 | size 9401398 4 | -------------------------------------------------------------------------------- /public/leather_white_4k.gltf/textures/leather_white_rough_4k.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0932da2869cc9630d7830e35550db5d3a67ed23b0a45d3cf06e7395070c72e1d 3 | size 7501740 4 | -------------------------------------------------------------------------------- /public/models/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/models/.DS_Store -------------------------------------------------------------------------------- /public/models/bench/license.txt: -------------------------------------------------------------------------------- 1 | Model Information: 2 | * title: Modern Bench 1 3 | * source: https://sketchfab.com/3d-models/modern-bench-1-caa4515e36444e4c8c100296463e83c1 4 | * author: Elasta Kristya (https://sketchfab.com/luca3d) 5 | 6 | Model License: 7 | * license type: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/) 8 | * requirements: Author must be credited. Commercial use is allowed. 9 | 10 | If you use this 3D model in your project be sure to copy paste this credit wherever you share it: 11 | This work is based on "Modern Bench 1" (https://sketchfab.com/3d-models/modern-bench-1-caa4515e36444e4c8c100296463e83c1) by Elasta Kristya (https://sketchfab.com/luca3d) licensed under CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/) -------------------------------------------------------------------------------- /public/models/bench/scene.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4550e62de1134f6df3e560c49277c738024ec5aaf8cb4ad4958089e1d8206554 3 | size 183352 4 | -------------------------------------------------------------------------------- /public/models/bench/scene.gltf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4f1624a107974561db61f6e14fb1cdefa40b14cbd51579dcad266f2e114d430f 3 | size 8117 4 | -------------------------------------------------------------------------------- /public/models/bench/textures/Stainless_Steel_diffuse.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/models/bench/textures/Stainless_Steel_diffuse.jpeg -------------------------------------------------------------------------------- /public/models/bench/textures/Stainless_Steel_normal.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/models/bench/textures/Stainless_Steel_normal.jpeg -------------------------------------------------------------------------------- /public/models/bench/textures/Stainless_Steel_specularGlossiness.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0bf7a449875519e72b167ceb303b936de5a8d4c75d1739477344f88f9aa7c7fb 3 | size 3798199 4 | -------------------------------------------------------------------------------- /public/models/bench/textures/Wood_diffuse.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/models/bench/textures/Wood_diffuse.jpeg -------------------------------------------------------------------------------- /public/models/bench/textures/Wood_normal.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/models/bench/textures/Wood_normal.jpeg -------------------------------------------------------------------------------- /public/models/bench/textures/Wood_specularGlossiness.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:80f1f002ed6d34258adf5938821c44fa68d8a7b5dc49916a1dace39f1cf8b271 3 | size 327195 4 | -------------------------------------------------------------------------------- /public/models/bench_2/license.txt: -------------------------------------------------------------------------------- 1 | Model Information: 2 | * title: Modern Bench 2 3 | * source: https://sketchfab.com/3d-models/modern-bench-2-118e358d76a642329b51c5cdd2ffc1c6 4 | * author: Elasta Kristya (https://sketchfab.com/luca3d) 5 | 6 | Model License: 7 | * license type: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/) 8 | * requirements: Author must be credited. Commercial use is allowed. 9 | 10 | If you use this 3D model in your project be sure to copy paste this credit wherever you share it: 11 | This work is based on "Modern Bench 2" (https://sketchfab.com/3d-models/modern-bench-2-118e358d76a642329b51c5cdd2ffc1c6) by Elasta Kristya (https://sketchfab.com/luca3d) licensed under CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/) -------------------------------------------------------------------------------- /public/models/bench_2/scene.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:90dfdc7d0f41f43cef8aec2b375506e941f576dac1e81fefd6fc7ed79ce9995e 3 | size 113280 4 | -------------------------------------------------------------------------------- /public/models/bench_2/scene.gltf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a289b2050919aa67b8f21d194639d17f2184678851496a8259c248393cf2807d 3 | size 5018 4 | -------------------------------------------------------------------------------- /public/models/bench_2/textures/Luca3D_Modern_Bench_2_baseColor.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:79d9a8b2ab65f883f467535ec4e99894ec1cde0491663c75a246d829f89cb2e3 3 | size 2801957 4 | -------------------------------------------------------------------------------- /public/models/bench_2/textures/Luca3D_Modern_Bench_2_metallicRoughness.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d4a19f6abfe740ecc0480f16bb4055a9b88acc64785ab37f13d248527b58e1ea 3 | size 1749586 4 | -------------------------------------------------------------------------------- /public/models/bench_2/textures/Luca3D_Modern_Bench_2_normal.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a81ef04c8a35d2b53ffd4b6acdccb91941f0c88aa67e6d9a366a90ffcc653713 3 | size 1952939 4 | -------------------------------------------------------------------------------- /public/models/ceiling-lamp/license.txt: -------------------------------------------------------------------------------- 1 | Model Information: 2 | * title: Pendente Mantra 30500 3 | * source: https://sketchfab.com/3d-models/pendente-mantra-30500-4b3ae3b8744d429a8a4aa1b5b5cb4f7c 4 | * author: Homak (https://sketchfab.com/edudias) 5 | 6 | Model License: 7 | * license type: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/) 8 | * requirements: Author must be credited. Commercial use is allowed. 9 | 10 | If you use this 3D model in your project be sure to copy paste this credit wherever you share it: 11 | This work is based on "Pendente Mantra 30500" (https://sketchfab.com/3d-models/pendente-mantra-30500-4b3ae3b8744d429a8a4aa1b5b5cb4f7c) by Homak (https://sketchfab.com/edudias) licensed under CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/) -------------------------------------------------------------------------------- /public/models/ceiling-lamp/scene.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:73e82d7033ae668862595c9ac3fdd801094c02921038bcc4f8e73767158a578d 3 | size 414776 4 | -------------------------------------------------------------------------------- /public/models/ceiling-lamp/scene.gltf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:cb592dfb247e8bfdea59738b24ad7948dc6451d207a468c02d996d637cfda476 3 | size 9201 4 | -------------------------------------------------------------------------------- /public/models/ceiling-lamp/textures/Madeira_baseColor.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/models/ceiling-lamp/textures/Madeira_baseColor.jpeg -------------------------------------------------------------------------------- /public/models/statue/license.txt: -------------------------------------------------------------------------------- 1 | Model Information: 2 | * title: 100.KZ.11 Aphrodite Kallipygos Statuette 3 | * source: https://sketchfab.com/3d-models/100kz11-aphrodite-kallipygos-statuette-c01ba617ec83491195146583b70e3df9 4 | * author: Ancient World 3D (https://sketchfab.com/ancientworld3d) 5 | 6 | Model License: 7 | * license type: CC-BY-NC-SA-4.0 (http://creativecommons.org/licenses/by-nc-sa/4.0/) 8 | * requirements: Author must be credited. No commercial use. Modified versions must have the same license. 9 | 10 | If you use this 3D model in your project be sure to copy paste this credit wherever you share it: 11 | This work is based on "100.KZ.11 Aphrodite Kallipygos Statuette" (https://sketchfab.com/3d-models/100kz11-aphrodite-kallipygos-statuette-c01ba617ec83491195146583b70e3df9) by Ancient World 3D (https://sketchfab.com/ancientworld3d) licensed under CC-BY-NC-SA-4.0 (http://creativecommons.org/licenses/by-nc-sa/4.0/) -------------------------------------------------------------------------------- /public/models/statue/scene.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:17e9bc00f52f40f4f40d905d710efcf913b1a7f44b6cc053ca6d1df8dc06e8f4 3 | size 5183748 4 | -------------------------------------------------------------------------------- /public/models/statue/scene.gltf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:373356fd48f4dd87424ef6cf44d6abde4e510d01369c60f134a37003bc533f40 3 | size 3870 4 | -------------------------------------------------------------------------------- /public/sounds/tiersen.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theringsofsaturn/3D-art-gallery-threejs/8be5adddaf60ac7f78f0a7f1fb28adbd84e98592/public/sounds/tiersen.mp3 -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | /* Add Animate.css to your project */ 2 | @import url("https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"); 3 | 4 | html, 5 | body { 6 | width: 100%; 7 | height: 100%; 8 | font-size: 12px; 9 | color: #28282f; 10 | margin: 0em; 11 | } 12 | 13 | body { 14 | margin: 0em; 15 | padding: 0em; 16 | overflow: hidden; 17 | font-family: "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, 18 | "Lucida Grande", sans-serif; 19 | background-color: #121212; 20 | cursor: url("http://www.rw-designer.com/cursor-view/97756.png") 16 16, auto; 21 | } 22 | 23 | p, 24 | img, 25 | div, 26 | canvas { 27 | vertical-align: top; 28 | } 29 | 30 | ::-moz-selection { 31 | /* Code for Firefox */ 32 | background: #34495e; 33 | background-color: #34495e; 34 | color: #fff; 35 | } 36 | 37 | ::selection { 38 | /* Code for Chrome, Safari and Opera */ 39 | background: #34495e; 40 | background-color: #34495e; 41 | color: #fff; 42 | } 43 | 44 | .hide { 45 | display: none; 46 | } 47 | 48 | #menu { 49 | width: 40em; 50 | position: absolute; 51 | top: 50%; 52 | left: 50%; 53 | transform: translate(-50%, -50%); 54 | text-align: center; 55 | font-size: 1.2em; 56 | border-radius: 0.9em; 57 | box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.6); 58 | overflow: hidden; 59 | } 60 | 61 | #menu .title { 62 | padding: 1em; 63 | background-color: rgba(52, 58, 125, 0.8); 64 | color: #f2c641; 65 | border-radius: 0.9em; 66 | position: relative; 67 | z-index: 2; 68 | text-shadow: 2px 2px 0px #f2c641, 4px 4px 0px rgba(0, 0, 0, 0.4); 69 | animation: fadeIn 2s ease-in, shadow-pulse 2s infinite; 70 | } 71 | 72 | @keyframes shadow-pulse { 73 | 0% { 74 | text-shadow: 2px 2px 0px #2323be, 4px 4px 0px rgba(0, 0, 0, 0.4); 75 | } 76 | 100% { 77 | text-shadow: 4px 4px 0px #2323be, 8px 8px 0px rgba(0, 0, 0, 0.4); 78 | } 79 | } 80 | 81 | #menu .title:hover { 82 | transform: rotateX(0deg); /* reset the transformation on hover */ 83 | } 84 | 85 | .title-info { 86 | background-color: rgba(35, 37, 88, 0.8); 87 | color: #f2c641; 88 | padding: 1em; 89 | border-radius: 0.9em; 90 | width: 80%; 91 | text-align: center; 92 | margin: 0 auto; 93 | } 94 | 95 | #menu #content_container { 96 | padding: 1em; 97 | border-bottom-left-radius: 0.9em; 98 | border-bottom-right-radius: 0.9em; 99 | 100 | -webkit-box-shadow: 0em 0.25em 0.75em rgba(124, 124, 124, 0.5); 101 | -moz-box-shadow: 0em 0.25em 0.75em rgba(124, 124, 124, 0.5); 102 | box-shadow: 0em 0.25em 0.75em rgba(124, 124, 124, 0.5); 103 | } 104 | 105 | #menu #img_container { 106 | position: relative; 107 | height: 14.5em; 108 | overflow: hidden; 109 | border-top-left-radius: 0.9em; 110 | border-top-right-radius: 0.9em; 111 | } 112 | 113 | #menu #img_container img { 114 | flex-shrink: 0; 115 | width: 105%; 116 | } 117 | 118 | @keyframes fadeInSlideUp { 119 | 0% { 120 | opacity: 0; 121 | transform: translateY(50px); 122 | } 123 | 100% { 124 | opacity: 1; 125 | transform: translateY(0); 126 | } 127 | } 128 | 129 | #menu { 130 | width: 40em; 131 | position: absolute; 132 | top: 50%; 133 | left: 50%; 134 | transform: translate(-50%, -50%); 135 | text-align: center; 136 | font-size: 1.2em; 137 | border-radius: 0.9em; 138 | box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.6); 139 | overflow: hidden; 140 | } 141 | 142 | #menu .title h1 { 143 | margin: 0; 144 | font-size: 2.5em; 145 | } 146 | 147 | #menu #content { 148 | padding: 1em; 149 | } 150 | 151 | #menu #content p { 152 | font-size: 1.1em; 153 | line-height: 1.6em; 154 | margin: 0.5em 0; 155 | } 156 | 157 | #menu #play_button { 158 | display: inline-block; 159 | background-color: rgba(52, 58, 125, 0.8); 160 | color: #f2c641; 161 | border-radius: 0.9em; 162 | padding: 0.5em 1.5em; 163 | font-weight: bold; 164 | margin-top: 1em; 165 | margin-bottom: 1em; 166 | transition: all 0.4s; 167 | } 168 | 169 | #menu #play_button:hover { 170 | background-color: rgba(52, 58, 125); 171 | cursor: pointer; 172 | transform: scale(1.05); 173 | } 174 | 175 | canvas { 176 | width: 100%; 177 | height: 100%; 178 | } 179 | 180 | @keyframes fadeIn { 181 | 0% { 182 | opacity: 0; 183 | } 184 | 100% { 185 | opacity: 1; 186 | } 187 | } 188 | 189 | .title { 190 | position: relative; 191 | display: inline-block; 192 | margin-bottom: 1em; 193 | } 194 | 195 | #starry_night_bg { 196 | position: fixed; 197 | top: 0; 198 | left: 0; 199 | width: 100%; 200 | height: 100%; 201 | background-image: url("https://th.bing.com/th/id/R.cf8cb0d1a972300c5e60b3ebf20b5779?rik=QLOj5Ukvu%2brJNQ&pid=ImgRaw&r=0"); 202 | background-size: cover; 203 | background-position: center; 204 | z-index: -1; 205 | animation: panBg 30s linear infinite; 206 | background-attachment: fixed; 207 | } 208 | 209 | #starry_night_bg:before { 210 | content: ""; 211 | position: absolute; 212 | top: 0; 213 | right: 0; 214 | bottom: 0; 215 | left: 0; 216 | background-color: rgba(0, 0, 0, 0.4); 217 | } 218 | 219 | @keyframes panBg { 220 | 0% { 221 | background-position: 0% 0%; 222 | } 223 | 100% { 224 | background-position: 100% 0%; 225 | } 226 | } 227 | 228 | #painting-info { 229 | position: fixed; 230 | top: 20px; 231 | left: 20px; 232 | background-color: rgba(0, 0, 0, 0.7); 233 | padding: 20px; 234 | border-radius: 10px; 235 | font-family: "Arial", sans-serif; 236 | color: #fff; 237 | width: 300px; 238 | height: 150px; 239 | z-index: 1; 240 | transition: all 0.3s ease-in-out; 241 | transform: translateY(100px); 242 | opacity: 0; 243 | } 244 | 245 | #painting-info.show { 246 | transform: translateY(0); 247 | opacity: 1; 248 | } 249 | 250 | #painting-info h3 { 251 | margin: 0 0 10px 0; 252 | font-size: 2em; 253 | font-weight: bold; 254 | text-transform: uppercase; 255 | } 256 | 257 | #painting-info p { 258 | margin: 0; 259 | font-size: 1.2em; 260 | } 261 | 262 | #info-panel { 263 | position: fixed; 264 | bottom: 10px; 265 | right: 10px; 266 | width: 200px; 267 | background-color: rgba(35, 35, 190, 0.8); 268 | border-radius: 10px; 269 | padding: 10px; 270 | color: white; 271 | box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.6); 272 | overflow: hidden; 273 | transition: all 0.5s ease; 274 | } 275 | 276 | #info-header { 277 | display: flex; 278 | justify-content: space-between; 279 | align-items: center; 280 | margin-bottom: 10px; 281 | cursor: pointer; 282 | } 283 | 284 | #info-header h3 { 285 | font-size: 1.5em; 286 | font-weight: bold; 287 | margin: 0; 288 | } 289 | 290 | #info-header button { 291 | background-color: rgba(255, 255, 255, 0.8); 292 | border: none; 293 | border-radius: 50%; 294 | padding: 5px; 295 | cursor: pointer; 296 | color: #2323be; 297 | } 298 | 299 | #info-content { 300 | font-size: 1em; 301 | line-height: 1.5em; 302 | } 303 | 304 | #info-content p { 305 | margin: 5px 0; 306 | } 307 | 308 | #info-panel.collapsed #info-content { 309 | max-height: 0; 310 | overflow: hidden; 311 | } 312 | 313 | #about-overlay { 314 | position: fixed; 315 | top: 0; 316 | left: 0; 317 | width: 100%; 318 | height: 100%; 319 | background-color: rgba(0, 0, 0, 0.8); 320 | color: white; 321 | padding: 50px; 322 | box-sizing: border-box; 323 | transform: translateY(-100%); 324 | transition: transform 0.3s ease-in-out; 325 | } 326 | 327 | #about-overlay.show { 328 | transform: translateY(0); 329 | } 330 | 331 | #about-overlay h1 { 332 | margin-top: 0; 333 | } 334 | 335 | #close-about { 336 | background: none; 337 | border: none; 338 | color: white; 339 | font-size: 2em; 340 | position: absolute; 341 | top: 10px; 342 | right: 20px; 343 | cursor: pointer; 344 | } 345 | 346 | #about_button { 347 | display: inline-block; 348 | background-color: rgba(52, 58, 125, 0.8); 349 | color: #f2c641; 350 | border-radius: 30px; 351 | padding: 0.5em 1.5em; 352 | font-weight: bold; 353 | margin: 0 auto; /* Centered the button */ 354 | transition: all 0.4s; 355 | border: 2px solid #2323be; 356 | } 357 | 358 | #about_button:hover { 359 | background-color: rgba(52, 58, 125); 360 | cursor: pointer; 361 | transform: scale(1.05); 362 | } 363 | 364 | #audio_controls { 365 | position: fixed; 366 | top: 10px; 367 | right: 10px; 368 | z-index: 2; /* To make sure it shows up on top of other elements */ 369 | } 370 | 371 | #audio_controls button { 372 | display: block; 373 | background-color: rgba(35, 37, 88, 0.8); 374 | color: #f2c641; 375 | border: none; 376 | border-radius: 10px; 377 | padding: 5px 10px; 378 | margin-bottom: 10px; 379 | cursor: pointer; 380 | transition: background-color 0.3s ease; 381 | } 382 | 383 | #audio_controls button:hover { 384 | background-color: rgba(52, 58, 125, 0.8); 385 | } 386 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | 3 | export default defineConfig({ 4 | base: '/3D-art-gallery', 5 | build: { 6 | rollupOptions: { 7 | input: '/main.js', 8 | }, 9 | }, 10 | }); 11 | --------------------------------------------------------------------------------