so I have been trying all day to get the camera working, basically I want this exhibition to be visible, it is a runway with pictures on the left and the right. I want to start at the beginning of the model and walk till the end. Since the beginning of the day, it stops and starts glitching in the middle. I have never had such issues with the arrow keys and controls but here seems to be a problem. I just would like the camera to be blocked at human eyesight and that can turn to see the photos on mouse drag and on click a modal pop up with the description. but that is a detail.
Here is the code with the missing 3d model, but hopefully you will get it with the code provided and the photo, I just added fog in three.
import * as THREE from 'three';
import { RoomEnvironment } from 'three/addons/environments/RoomEnvironment.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { KTX2Loader } from 'three/addons/loaders/KTX2Loader.js';
import { MeshoptDecoder } from 'three/addons/libs/meshopt_decoder.module.js';
let camera, scene, renderer, controls;
let moveForward = false;
let moveBackward = false;
let moveLeft = false;
let moveRight = false;
let clock = new THREE.Clock();
init();
animate();
function init() {
const container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(400, 200, 0);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1;
container.appendChild(renderer.domElement);
const environment = new RoomEnvironment();
const pmremGenerator = new THREE.PMREMGenerator(renderer);
scene = new THREE.Scene();
scene.background = new THREE.Color(0xbbbbbb);
scene.environment = pmremGenerator.fromScene(environment).texture;
environment.dispose();
const grid = new THREE.GridHelper(500, 10, 0xffffff, 0xffffff);
grid.material.opacity = 0.5;
grid.material.depthWrite = false;
grid.material.transparent = true;
scene.add(grid);
const ktx2Loader = new KTX2Loader()
.setTranscoderPath('jsm/libs/basis/')
.detectSupport(renderer);
const loader = new GLTFLoader().setPath('models/gltf/');
loader.setKTX2Loader(ktx2Loader);
loader.setMeshoptDecoder(MeshoptDecoder);
loader.load('Photography-museum.glb', function (gltf) {
gltf.scene.position.y = 8;
gltf.scene.position.z = 0;
gltf.scene.position.x = -18;
scene.add(gltf.scene);
});
controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.enableRotate = true; // Allow rotation
controls.enablePan = false; // Disable panning
controls.maxPolarAngle = Math.PI / 2; // Limit vertical rotation
controls.minDistance = 100; // Set minimum distance
controls.maxDistance = 500; // Set maximum distance
const geometry = new THREE.PlaneGeometry(5000, 5000);
const material = new THREE.MeshBasicMaterial({ color: 0x808080, side: THREE.DoubleSide });
const floor = new THREE.Mesh(geometry, material);
floor.position.y = 0;
floor.rotation.x = -Math.PI / 2;
scene.add(floor);
// Add fog
scene.fog = new THREE.FogExp2(0xcccccc, 0.002);
window.addEventListener('resize', onWindowResize);
document.addEventListener('keydown', onKeyDown);
document.addEventListener('keyup', onKeyUp);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
render();
}
function onKeyDown(event) {
switch (event.code) {
case 'KeyW':
case 'ArrowUp':
moveForward = true;
break;
case 'KeyS':
case 'ArrowDown':
moveBackward = true;
break;
case 'KeyA':
case 'ArrowLeft':
moveLeft = true;
break;
case 'KeyD':
case 'ArrowRight':
moveRight = true;
break;
}
}
function onKeyUp(event) {
switch (event.code) {
case 'KeyW':
case 'ArrowUp':
moveForward = false;
break;
case 'KeyS':
case 'ArrowDown':
moveBackward = false;
break;
case 'KeyA':
case 'ArrowLeft':
moveLeft = false;
break;
case 'KeyD':
case 'ArrowRight':
moveRight = false;
break;
}
}
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const moveSpeed = 100; // Units per second
if (moveForward) camera.translateZ(-moveSpeed * delta);
if (moveBackward) camera.translateZ(moveSpeed * delta);
if (moveLeft) camera.translateX(-moveSpeed * delta);
if (moveRight) camera.translateX(moveSpeed * delta);
controls.update();
render();
}
function render() {
renderer.render(scene, camera);
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - GLTFloader + compressed</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
</head>
<body>
<script type="importmap">
{
"imports": {
"three": "../build/three.module.js",
"three/addons/": "./jsm/"
}
}
</script>
<script type="module" src="script.js">
</script>
</body>
</html>
