xxxxxxxxxx
//LA model credit to https://poly.cam/capture/f7ea985c-c301-40b5-a86f-2687f7283d4f
//music from: https://opengameart.org/content/heroic-demise-hero-theme
/*
This code implements three.js and additional libraries that can be seen on index.html tab
Hope you all enjoy!
*/
import { FirstPersonControls } from "three/addons/controls/FirstPersonControls.js";
let sound
// Create a new scene
var scene = new THREE.Scene();
// Set up the renderer with transparency and antialiasing, then append it to the document body
var renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Set up the camera with a field of view of 75, aspect ratio based on window size, and near/far clipping planes
const camera = new THREE.PerspectiveCamera(
59,
window.innerWidth / window.innerHeight,
0.1,
200
);
camera.position.set(24, 5, -0); // Set initial camera position
camera.rotation.set(0, 1.5, 0); // Set initial camera rotation
// Initialize FirstPersonControls to allow looking around
let controls = new FirstPersonControls(camera, renderer.domElement);
controls.lookSpeed = 0.1; // Set the look speed
controls.movementSpeed = 1.5; // Disable built-in movement, we'll handle it manually
// Add ambient light to the scene for general illumination
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
// Add a directional light to the scene to simulate sunlight
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(2.5, 2, 2); // Set light position
light.castShadow = true; // Enable shadows
light.shadow.mapSize.width = 512; // Set shadow map size
light.shadow.mapSize.height = 512; // Set shadow map size
light.shadow.camera.near = 0.5; // Set shadow camera near plane
light.shadow.camera.far = 100; // Set shadow camera far plane
scene.add(light);
// Add event listener to handle window resize
window.addEventListener('resize', onWindowResize);
// Function to handle window resize events
function onWindowResize() {
let width = window.innerWidth+100;
let height = window.innerHeight+100;
renderer.setSize(width, height); // Update renderer size
camera.aspect = width / height; // Update camera aspect ratio
camera.updateProjectionMatrix(); // Update camera projection matrix
}
// create sphere
const geometry = new THREE.SphereGeometry(100, 32, 32);
// load sphere's texture - the sky image
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load('https://deckard.openprocessing.org/user326951/visual2289319/h04a56393e944364c61cf567a127a9310/Skydome.png');
// Create material with the texture
const material = new THREE.MeshBasicMaterial({
map: texture,
side: THREE.BackSide // Render texture on the inside
});
// Create the sphere mesh
const sphere = new THREE.Mesh(geometry, material);
sphere.rotation.z = Math.PI/2 ;
scene.add(sphere);
// Load a 3D model using the GLTFLoader
var loader = new THREE.GLTFLoader();
var mixer; // Animation mixer (if needed)
var model; // Loaded model
loader.load(
'https://deckard.openprocessing.org/user326951/visual2289319/h04a56393e944364c61cf567a127a9310/LA.glb', // Model URL
function (gltf) {
// Traverse the loaded model and enable shadows
gltf.scene.traverse(function (node) {
if (node instanceof THREE.Mesh) {
node.castShadow = true;
node.receiveShadow = true;
node.material.side = THREE.DoubleSide; // Render both sides of the material
}
});
model = gltf.scene;
model.scale.set(75, 75, 75); // Scale the model
scene.add(model); // Add the model to the scene
document.getElementById('loading').style.display = 'none'; // Hide the loading screen
}
);
// Set movement speed for manual camera movement
const movementSpeed = 10;
// Object to keep track of which keys are pressed
const keys = { W: false, A: false, S: false, D: false };
// Event listeners for keydown and keyup events to track key presses
window.addEventListener('keydown', (event) => {
if (event.key.toUpperCase() in keys) {
keys[event.key.toUpperCase()] = true;
}
});
window.addEventListener('keyup', (event) => {
if (event.key.toUpperCase() in keys) {
keys[event.key.toUpperCase()] = false;
}
});
// Create an audio listener and add it to the camera
const listener = new THREE.AudioListener();
camera.add(listener);
// Create a global audio source
sound = new THREE.Audio(listener);
// Load the sound and set it as the audio object's buffer
const audioLoader = new THREE.AudioLoader();
audioLoader.load('https://deckard.openprocessing.org/user326951/visual2289319/h04a56393e944364c61cf567a127a9310/heroSong.mp3', function(buffer) {
sound.setBuffer(buffer);
sound.setLoop(true);
sound.setVolume(0.5);
sound.play()
});
// Function to handle camera movement based on key presses
function moveCamera(delta) {
const direction = new THREE.Vector3(); // Vector for forward/backward direction
const right = new THREE.Vector3(); // Vector for right/left direction
const up = new THREE.Vector3(0, 1, 0); // Up direction vector
camera.getWorldDirection(direction); // Get the camera's forward direction
direction.normalize(); // Normalize the direction vector
right.crossVectors(camera.up, direction).normalize(); // Compute the right vector
// Move camera based on which keys are pressed
if (keys.W)
{
camera.position.add(direction.multiplyScalar(movementSpeed * delta));
}
if (keys.S) camera.position.add(direction.multiplyScalar(-movementSpeed * delta));
if (keys.A) camera.position.add(right.multiplyScalar(movementSpeed * delta));
if (keys.D) camera.position.add(right.multiplyScalar(-movementSpeed * delta));
}
// Initialize a clock to manage time-based updates
var clock = new THREE.Clock();
// Render loop
function render() {
requestAnimationFrame(render); // Request the next frame
var delta = clock.getDelta(); // Get the time elapsed since the last frame
if (mixer) mixer.update(delta); // Update animations if any
moveCamera(delta); // Handle camera movement
controls.update(delta); // Update the controls
renderer.render(scene, camera); // Render the scene from the camera's perspective
}
render(); // Start the render loop
// Set up dat.GUI - slidders on top right
const gui = new dat.GUI();
const cameraFolder = gui.addFolder('Camera');
const cameraParams = { fov: camera.fov, far: camera.far };
// Add FOV slider to dat.GUI
cameraFolder.add(cameraParams, 'fov', 10, 120).onChange(value => {
camera.fov = value;
camera.updateProjectionMatrix();
});
// Add Far Clipping Plane slider to dat.GUI
cameraFolder.add(cameraParams, 'far', 1, 200).onChange(value => {
camera.far = value;
camera.updateProjectionMatrix();
});
cameraFolder.open();