diff --git a/static/assets/study.glb b/static/assets/study.glb new file mode 100644 index 0000000..aee1209 Binary files /dev/null and b/static/assets/study.glb differ diff --git a/static/scripts/main.js b/static/scripts/main.js index 4ddd3e0..09ae764 100644 --- a/static/scripts/main.js +++ b/static/scripts/main.js @@ -1,25 +1,101 @@ import * as THREE from 'three'; +import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'; +import { PointerLockControls } from 'three/addons/controls/PointerLockControls.js'; -const scene = new THREE.Scene(); -const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); +const next_url = 'https://3dworldring.cjsatnarine.space/cjsatnarine_study/next'; +const prev_url = 'https://3dworldring.cjsatnarine.space/cjsatnarine_study/previous'; const renderer = new THREE.WebGLRenderer(); -renderer.setSize( window.innerWidth, window.innerHeight ); -renderer.setAnimationLoop( animate ); -document.body.appendChild( renderer.domElement ); -const geometry = new THREE.BoxGeometry( 1, 1, 1 ); -const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } ); -const cube = new THREE.Mesh( geometry, material ); -scene.add( cube ); +const scene = new THREE.Scene(); +const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); +const light = new THREE.AmbientLight(0xFFFFFF, 2); -camera.position.z = 5; +const study = new GLTFLoader(); -function animate( time ) { +const controls = new PointerLockControls(camera, document.body); +const clock = new THREE.Clock(); +const keymap = {}; +const pointer = new THREE.Vector2(); +const raycaster = new THREE.Raycaster(); - cube.rotation.x = time / 2000; - cube.rotation.y = time / 1000; +init(); - renderer.render( scene, camera ); +function init() { + renderer.setSize(window.innerWidth, window.innerHeight); + + document.body.appendChild(renderer.domElement); + + scene.background = new THREE.Color(0x000000); + scene.add(camera); + + scene.add(light); + + camera.position.y = 1.5; + + study.load('../assets/study.glb', function(gltf) { + scene.add(gltf.scene); + + function onPointerDown(event) { + if (controls.isLocked) { + pointer.set(0, 0); + raycaster.setFromCamera(pointer, camera); + } + else { + const rect = renderer.domElement.getBoundingClientRect(); + pointer.x = ((event.clientX - rect.left) / rect.width) * 2 - 1; + pointer.y = -((event.clientY - rect.top) / rect.height) * 2 + 1; + raycaster.setFromCamera(pointer, camera); + } + + const intersects = raycaster.intersectObject(gltf.scene, true); + if (!intersects.length) return; + + for (let i = 0; i < intersects.length; i++) { + let object = intersects[i].object; + + while (object && object !== gltf.scene) { + if (object.name === 'Next') { + window.open(next_url); + return; + } + + if (object.name === 'Previous') { + window.open(prev_url); + return; + } + object = object.parent; + } + } + } + window.addEventListener('pointerdown', onPointerDown, false); + + }, undefined, function(error) { + console.error(error); + }); + + document.addEventListener('click', () => { controls.lock(); }); + + const onDocumentKey = (e) => { keymap[e.code] = e.type === 'keydown'; }; + document.addEventListener('keydown', onDocumentKey, false); + document.addEventListener('keyup', onDocumentKey, false); +} + + +function animate() { + const delta = clock.getDelta(); + + if (controls.isLocked) { + if (keymap['KeyW']) controls.moveForward(delta * 5); + if (keymap['KeyS']) controls.moveForward(-delta * 5); + if (keymap['KeyA']) controls.moveRight(-delta * 5); + if (keymap['KeyD']) controls.moveRight(delta * 5); + } + + renderer.render(scene, camera); } + +renderer.setAnimationLoop(animate); + +