diff --git a/ALGUL/index.js b/ALGUL/index.js index 90b33bd6e3b709e20c60d91d17ba149f71ebc933..8f1558aa43c7f8b1d0cfdc31fb2a003bb917adc2 100644 --- a/ALGUL/index.js +++ b/ALGUL/index.js @@ -2,17 +2,24 @@ import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.150.1/build/three.m import { OrbitControls } from 'https://cdn.jsdelivr.net/npm/three@0.150.1/examples/jsm/controls/OrbitControls.js'; import { GLTFLoader } from 'https://cdn.jsdelivr.net/npm/three@0.150.1/examples/jsm/loaders/GLTFLoader.js'; import { OBJLoader } from 'https://cdn.jsdelivr.net/npm/three@0.150.1/examples/jsm/loaders/OBJLoader.js'; +import * as dat from 'https://cdn.jsdelivr.net/npm/dat.gui@0.7.9/build/dat.gui.module.js'; +// SCENE const scene = new THREE.Scene(); -scene.background = new THREE.Color(0x87CEEB); - +scene.background = new THREE.Color(0x87CEEB); +// CAMERA const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 5000); -const renderer = new THREE.WebGLRenderer({ antialias: true }); +camera.position.set(380, 200, 30); +// RENDERER +const renderer = new THREE.WebGLRenderer({ antialias: true }); +renderer.shadowMap.enabled = true; // Active les ombres +renderer.shadowMap.type = THREE.PCFSoftShadowMap; renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); +// CONTROLS const controls = new OrbitControls(camera, renderer.domElement); controls.enableDamping = true; controls.dampingFactor = 0.05; @@ -21,7 +28,7 @@ controls.maxDistance = 2000; controls.minDistance = 50; controls.target.set(0, 0, 0); -// Lumières +// LUMIÈRES const light = new THREE.DirectionalLight(0xffffff, 1); light.position.set(10, 50, 50); scene.add(light); @@ -32,14 +39,43 @@ scene.add(ambientLight); const hemisphereLight = new THREE.HemisphereLight(0x87CEEB, 0x222222, 1); scene.add(hemisphereLight); -camera.position.set(380, 200, 30); +// SOLEIL +const sunGeometry = new THREE.SphereGeometry(50, 32, 32); +const sunMaterial = new THREE.MeshBasicMaterial({ color: 0xffcc00 }); +const sun = new THREE.Mesh(sunGeometry, sunMaterial); +sun.position.set(-700, 800, -1000); +scene.add(sun); -// Chargement des ponts +// DirectionalLight pour le soleil (avec ombres) +const sunLight = new THREE.DirectionalLight(0xffddaa, 3); +sunLight.position.set(500, 1000, -1000); +sunLight.castShadow = true; // Indispensable pour projeter des ombres +sunLight.shadow.mapSize.width = 2048; +sunLight.shadow.mapSize.height = 2048; +sunLight.shadow.camera.near = 1; +sunLight.shadow.camera.far = 3000; +sunLight.shadow.camera.left = -1000; +sunLight.shadow.camera.right = 1000; +sunLight.shadow.camera.top = 1000; +sunLight.shadow.camera.bottom = -1000; +scene.add(sunLight); + +// CHARGEMENT DES PONTS const loader = new GLTFLoader(); + +// 1er pont loader.load('modeles/old_bridge.glb', function (gltf) { const bridge = gltf.scene; - scene.add(bridge); + // Activer les ombres + bridge.traverse((node) => { + if (node.isMesh) { + node.castShadow = true; + node.receiveShadow = true; + } + }); + + scene.add(bridge); bridge.position.set(0, 100, 0); bridge.scale.set(0.5, 0.5, 0.5); bridge.rotation.y = Math.PI / 2; @@ -50,10 +86,17 @@ loader.load('modeles/old_bridge.glb', function (gltf) { console.error("Erreur de chargement du pont :", error); }); +// 2e pont loader.load('modeles/old_bridge.glb', function (gltf) { const bridge2 = gltf.scene; - scene.add(bridge2); + bridge2.traverse((node) => { + if (node.isMesh) { + node.castShadow = true; + node.receiveShadow = true; + } + }); + scene.add(bridge2); bridge2.position.set(-950, 100, 0); bridge2.scale.set(0.5, 0.5, 0.5); bridge2.rotation.y = Math.PI / 2; @@ -63,40 +106,66 @@ loader.load('modeles/old_bridge.glb', function (gltf) { }, undefined, function (error) { console.error("Erreur de chargement du pont :", error); }); + +// 3e pont loader.load('modeles/old_bridge.glb', function (gltf) { const bridge3 = gltf.scene; - scene.add(bridge3); + bridge3.traverse((node) => { + if (node.isMesh) { + node.castShadow = true; + node.receiveShadow = true; + } + }); + scene.add(bridge3); bridge3.position.set(100, 100, 126); bridge3.scale.set(0.5, 0.5, 0.5); bridge3.rotation.y = Math.PI / -2; - controls.target.copy(bridge3.position); controls.update(); }, undefined, function (error) { console.error("Erreur de chargement du pont :", error); }); +// 4e pont loader.load('modeles/old_bridge.glb', function (gltf) { const bridge4 = gltf.scene; - scene.add(bridge4); + bridge4.traverse((node) => { + if (node.isMesh) { + node.castShadow = true; + node.receiveShadow = true; + } + }); + scene.add(bridge4); bridge4.position.set(-850, 100, 126); bridge4.scale.set(0.5, 0.5, 0.5); bridge4.rotation.y = Math.PI / -2; - controls.target.copy(bridge4.position); controls.update(); }, undefined, function (error) { console.error("Erreur de chargement du pont :", error); }); -// Chargement des bateaux +// CHARGEMENT DES BATEAUX loader.load('modeles/bateau.glb', function (gltf) { const boat1 = gltf.scene.clone(); + boat1.traverse((node) => { + if (node.isMesh) { + node.castShadow = true; + node.receiveShadow = true; + } + }); + const boat2 = gltf.scene.clone(); + boat2.traverse((node) => { + if (node.isMesh) { + node.castShadow = true; + node.receiveShadow = true; + } + }); boat1.position.set(-300, 1, -500); boat1.scale.set(0.3, 0.3, 0.3); @@ -111,18 +180,7 @@ loader.load('modeles/bateau.glb', function (gltf) { console.error("Erreur de chargement des bateaux :", error); }); -// Soleil -const sunGeometry = new THREE.SphereGeometry(50, 32, 32); -const sunMaterial = new THREE.MeshBasicMaterial({ color: 0xffcc00 }); -const sun = new THREE.Mesh(sunGeometry, sunMaterial); -sun.position.set(-700, 800, -1000); -scene.add(sun); - -const sunLight = new THREE.DirectionalLight(0xffddaa, 3); -sunLight.position.set(500, 1000, -1000); -scene.add(sunLight); - -// Sol (eau) +// SOL (eau) const textureLoader = new THREE.TextureLoader(); const groundTexture = textureLoader.load('textures/water2.jpg'); groundTexture.wrapS = groundTexture.wrapT = THREE.RepeatWrapping; @@ -136,9 +194,11 @@ const solidGround = new THREE.Mesh( ); solidGround.rotation.x = -Math.PI / 2; solidGround.position.y = -2; +// Reçoit les ombres +solidGround.receiveShadow = true; scene.add(solidGround); -// Modèle Scream +// MODÈLE SCREAM const objLoader = new OBJLoader(); objLoader.load('modeles/scream/Scream 3D-bl.obj', function (obj) { const screamTexture = textureLoader.load('modeles/scream/Scream Texture.png'); @@ -146,6 +206,8 @@ objLoader.load('modeles/scream/Scream 3D-bl.obj', function (obj) { obj.traverse((child) => { if (child.isMesh) { child.material = new THREE.MeshBasicMaterial({ map: screamTexture }); + child.castShadow = true; + child.receiveShadow = true; } }); @@ -159,25 +221,25 @@ objLoader.load('modeles/scream/Scream 3D-bl.obj', function (obj) { console.error("Erreur de chargement du modèle Scream :", error); }); -// SphereBox (Ciel panoramique) +// SPHEREBOX (Ciel panoramique) const skyTexture = textureLoader.load('textures/skybox2.png'); const skyMaterial = new THREE.MeshBasicMaterial({ map: skyTexture, - side: THREE.BackSide + side: THREE.BackSide }); - -const skySphere = new THREE.Mesh(new THREE.SphereGeometry(3000, 32, 32), skyMaterial); +const skySphere = new THREE.Mesh( + new THREE.SphereGeometry(3000, 32, 32), + skyMaterial +); skySphere.rotation.x = Math.PI / 2; skySphere.rotation.z = Math.PI / -1; - - scene.add(skySphere); +// SPRITES const spriteTexture = textureLoader.load('textures/sprite.png'); const spriteMaterial = new THREE.SpriteMaterial({ map: spriteTexture }); const sprite = new THREE.Sprite(spriteMaterial); sprite.position.set(40, 160, -30); - sprite.scale.set(50, 100, 50); scene.add(sprite); @@ -188,19 +250,24 @@ sprite2.position.set(20, 160, 0); sprite2.scale.set(50, 100, 50); scene.add(sprite2); +// GUI +const gui = new dat.GUI(); +gui.add(camera, 'fov', 10, 100).name('Zoom').onChange(() => { + camera.updateProjectionMatrix(); +}); +gui.add(sunLight, 'intensity', 0, 10).name('Soleil Intensité'); -// Animation +// ANIMATION function animate() { requestAnimationFrame(animate); controls.update(); renderer.render(scene, camera); } - animate(); -// Redimensionnement +// REDIMENSIONNEMENT window.addEventListener('resize', () => { renderer.setSize(window.innerWidth, window.innerHeight); camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); -}); \ No newline at end of file +});