diff --git a/DUFOUR/INFOS.md b/DUFOUR/INFOS.md index 52e96fabcd98f3a5dfdcdb49ef8797afe9eb6ac3..c3a874434407ea0bb03bfe49c72acf44e659dc21 100644 --- a/DUFOUR/INFOS.md +++ b/DUFOUR/INFOS.md @@ -34,14 +34,14 @@ https://github.com/mrdoob/three.js/blob/master/examples/webgl_loader_obj_mtl.htm ## CHECK LIST *(ajouter X pour cocher)* - [X] Esthetisme -- [ ] Mise en page de la page web +- [x] Mise en page de la page web - [ ] Paragraphe(s) d'explications techniques - [ ] Légèreté du dossier (<2Mo) - [X] Géométrie - [X] Couleur - [X] Transparence - [X] Eclairage -- [ ] Ombres portées +- [X] Ombres portées - [X] Position de la caméra - [X] Brouillard - [X] Effet miroir @@ -52,4 +52,4 @@ https://github.com/mrdoob/three.js/blob/master/examples/webgl_loader_obj_mtl.htm - [ ] Skybox - [ ] specular maps - [X] normal maps -- [ ] Interaction par GUI +- [X] Interaction par GUI diff --git a/DUFOUR/chambre.js b/DUFOUR/chambre.js index c15ede81bad8f86977be34194035a6ef9c92976d..156255b5330b3c8b037531e7568a1d7980d7aede 100644 --- a/DUFOUR/chambre.js +++ b/DUFOUR/chambre.js @@ -1,40 +1,72 @@ import * as THREE from 'three'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; import { OBJLoader } from 'three/addons/loaders/OBJLoader.js'; // Remplacer GLTFLoader par OBJLoader -import { Coordinates } from '../lib/Coordinates.js'; +// import { Coordinates } from '../lib/Coordinates.js'; +import { GUI } from 'https://cdn.jsdelivr.net/npm/lil-gui@0.17/+esm'; -var camera, renderer; -window.scene = new THREE.Scene(); + +// var camera, renderer; +// window.scene = new THREE.Scene(); +var camera, renderer, scene; +scene = new THREE.Scene(); var cameraControls; var clock = new THREE.Clock(); var transparentCube; +var light1, light2; +var params = { + ambientLightIntensity: 0.2, + light1Intensity: 4, + light2Intensity: 3, + fogDensity: 0.001, + enableShadows: true, + enableFog: true, + cameraX: -400, + cameraY: 150, + cameraZ: -20, + light1X: 200, + light1Y: 400, + light1Z: 400, + shadowBias: -0.0005, + shadowRadius: 2, + showHelpers: false +}; const objLoader = new OBJLoader(); // Utilisation de OBJLoader au lieu de GLTFLoader function fillScene() { - scene.fog = new THREE.FogExp2(0xB0BEC5, 0.001); + scene.fog = new THREE.FogExp2(0xB0BEC5, params.fogDensity); + + // LIGHTS avec configuration précise des ombres + const ambientLight = new THREE.AmbientLight(0x444444, params.ambientLightIntensity); + scene.add(ambientLight); - // LIGHTS - scene.add(new THREE.AmbientLight(0x222222)); + // Lumière directionnelle principale pour les ombres + light1 = new THREE.DirectionalLight(0xFFFFFF, params.light1Intensity); + light1.position.set(params.light1X, params.light1Y, params.light1Z); + light1.castShadow = params.enableShadows; + scene.add(light1); - var light = new THREE.DirectionalLight(0xFFFFFF, 4); - light.position.set(200, 400, 400); - light.castShadow = true; // Cette lumière génère des ombres - scene.add(light); + // Configuration des paramètres d'ombre + light1.shadow.mapSize.width = 2048; // Haute résolution pour des ombres nettes + light1.shadow.mapSize.height = 2048; + light1.shadow.camera.near = 10; + light1.shadow.camera.far = 1000; + light1.shadow.bias = params.shadowBias; // Contrôlable via GUI + light1.shadow.radius = params.shadowRadius; // Contrôlable via GUI - light = new THREE.DirectionalLight(0xFFFFFF, 3); - light.position.set(-200, -100, -400); - light.castShadow = true; // Cette lumière génère des ombres - scene.add(light); + // Configuration critique: définir la boîte de la caméra d'ombre + light1.shadow.camera.left = -500; + light1.shadow.camera.right = 500; + light1.shadow.camera.top = 500; + light1.shadow.camera.bottom = -500; - // Optionally adjust the shadow for the light - light.shadow.mapSize.width = 1024; - light.shadow.mapSize.height = 1024; - light.shadow.camera.near = 1; - light.shadow.camera.far = 1000; - light.shadow.bias = -0.005; + // Helper pour visualiser la zone d'ombre + const helper1 = new THREE.CameraHelper(light1.shadow.camera); + helper1.visible = params.showHelpers; + scene.add(helper1); - Coordinates.drawGround({ size: 800 }); + + // Coordinates.drawGround({ size: 800 }); // Cube Transparent au Centre var transparentMaterial = new THREE.MeshBasicMaterial({ @@ -43,9 +75,8 @@ function fillScene() { }); var cubeGeometry = new THREE.BoxGeometry(100, 100, 100); transparentCube = new THREE.Mesh(cubeGeometry, transparentMaterial); - transparentCube.position.set(0, 50, 0); - transparentCube.castShadow = true; // Activer la projection d'ombre - transparentCube.receiveShadow = true; // Activer la réception d'ombre + transparentCube.position.set(0, -100, 0); + scene.add(transparentCube); // Sol @@ -53,7 +84,7 @@ function fillScene() { var floorMaterial = new THREE.MeshStandardMaterial({ map: floorTexture }); var floor = new THREE.Mesh(new THREE.PlaneGeometry(400, 400), floorMaterial); floor.rotation.x = -Math.PI / 2; - floor.position.y = 0; + floor.position.y = -100; floor.receiveShadow = true; // Le sol reçoit des ombres scene.add(floor); @@ -62,82 +93,252 @@ function fillScene() { var wallMaterial = new THREE.MeshStandardMaterial({ map: wallTexture }); var backWall = new THREE.Mesh(new THREE.PlaneGeometry(400, 300), wallMaterial); - backWall.position.set(0, 150, -200); + backWall.position.set(0, 50, -200); scene.add(backWall); var leftWall = new THREE.Mesh(new THREE.PlaneGeometry(400, 300), wallMaterial); leftWall.rotation.y = Math.PI / 2; - leftWall.position.set(-200, 150, 0); + leftWall.position.set(-200, 50, 0); scene.add(leftWall); var rightWall = new THREE.Mesh(new THREE.PlaneGeometry(400, 300), wallMaterial); rightWall.rotation.y = -Math.PI / 2; - rightWall.position.set(200, 150, 0); + rightWall.position.set(200, 50, 0); scene.add(rightWall); var frontWall = new THREE.Mesh(new THREE.PlaneGeometry(400, 300), wallMaterial); frontWall.rotation.y = Math.PI; - frontWall.position.set(0, 150, 200); + frontWall.position.set(0, 50, 200); scene.add(frontWall); // Lit - objLoader.load('elements/wooden_bed.obj', function (object) { - let bed = object; - bed.position.set(130 - 50, 0, 127); - bed.scale.set(100, 100, 100); - bed.rotation.y = 11; - bed.castShadow = true; // Activer la projection d'ombre - bed.receiveShadow = true; // Activer la réception d'ombre - scene.add(bed); + // Lit avec texture et matériaux différents +objLoader.load('elements/wooden_bed.obj', function (object) { + let bed = object; + + // Textures + var woodTexture = new THREE.TextureLoader().load('elements/sol_boiserie.jpg'); + + // Matériaux + const woodMaterial = new THREE.MeshStandardMaterial({ + map: woodTexture, + color: 0x8B4513, + roughness: 0.8, + metalness: 0.2 + }); + + const redMaterial = new THREE.MeshStandardMaterial({ + color: 0xAA0000, // Rouge foncé + roughness: 0.7, + metalness: 0.1 + }); + + const whiteMaterial = new THREE.MeshStandardMaterial({ + color: 0xFFFFFF, // Blanc + roughness: 0.5, + metalness: 0.0 + }); + + // Compter les meshes pour identifier différentes parties + let meshCount = 0; + + // Appliquer les matériaux en fonction de l'index des meshes + bed.traverse(function (child) { + if (child instanceof THREE.Mesh) { + if (meshCount % 3 === 0) { + child.material = whiteMaterial; // Cadre + } else if (meshCount % 3 === 1) { + child.material = woodMaterial; // Couverture + } else { + child.material = redMaterial; // Oreillers + } + meshCount++; + } }); + enableShadows(bed); + + bed.position.set(130 - 50, -100, 127); + bed.scale.set(100, 100, 100); + bed.rotation.y = 11; + bed.castShadow = true; + bed.receiveShadow = true; + scene.add(bed); +}); + // Chaise objLoader.load('elements/wooden_chair.obj', function (object) { let chair1 = object.clone(); let chair2 = object.clone(); + + // Appliquer le même matériau bois que la table aux chaises + const woodTexture = new THREE.TextureLoader().load('elements/sol_boiserie.jpg'); + const chairMaterial = new THREE.MeshStandardMaterial({ + map: woodTexture, // Utiliser la texture pour le bois + color: 0x8B4513, // Teinte supplémentaire (peut être ajustée) + roughness: 0.8, + metalness: 0.2 + }); + + // Appliquer le matériau à chaque chaise + chair1.traverse(function (child) { + if (child instanceof THREE.Mesh) { + child.material = chairMaterial; + } + }); + + chair2.traverse(function (child) { + if (child instanceof THREE.Mesh) { + child.material = chairMaterial; + } + }); + + enableShadows(chair1); + enableShadows(chair2); - chair1.position.set(100, 0, 0); // Première chaise à côté du lit + chair1.position.set(100, -100, 0); // Première chaise à côté du lit chair1.rotation.y = 12; - chair2.position.set(-100, 0, -150); // Deuxième chaise à côté de la première + chair2.position.set(-100, -100, -150); // Deuxième chaise à côté de la première chair2.rotation.y = 12; chair1.scale.set(100, 100, 100); chair2.scale.set(100, 100, 100); - - chair1.castShadow = true; // Activer la projection d'ombre - chair1.receiveShadow = true; // Activer la réception d'ombre - chair2.castShadow = true; // Activer la projection d'ombre - chair2.receiveShadow = true; // Activer la réception d'ombre scene.add(chair1); scene.add(chair2); - }); - // Table - objLoader.load('elements/wooden_table.obj', function (object) { - object.traverse(function (child) { - if (child instanceof THREE.Mesh) { - child.material = new THREE.MeshStandardMaterial({ - color: 0x8B4513, // Couleur bois - roughness: 0.8, - metalness: 0.2 + + // Charger la table au format OBJ + const objLoader = new OBJLoader(); + objLoader.load('elements/wooden_table.obj', function (object) { + // Appliquer un matériau à tous les enfants de l'objet + object.traverse(function (child) { + if (child instanceof THREE.Mesh) { + child.material = new THREE.MeshStandardMaterial({ + color: 0x8B4513, // Couleur bois + roughness: 0.8, + metalness: 0.2 + }); + } + }); + + // Ajuster la position, la taille et la rotation de la table + object.position.set(100, -100, -110); // Position entre les chaises + object.scale.set(100, 100, 100); // Échelle à ajuster selon le modèle + object.rotation.y = Math.PI / 4; + enableShadows(object); + // Ajouter la table à la scène + scene.add(object); + + + // Charger la théière et la placer sur la table + objLoader.load('elements/tea.obj', function (teapot) { + // Appliquer un matériau à la théière + teapot.traverse(function (child) { + if (child instanceof THREE.Mesh) { + child.material = new THREE.MeshStandardMaterial({ + color: 0x0000FF, // Couleur bleu + roughness: 0.2, + metalness: 0.8 + }); + } }); - } + + // Positionner la théière sur la table + teapot.position.set(100, 5, -110); // Même position X/Z que la table mais plus haut en Y + teapot.scale.set(10, 10, 10); // Échelle appropriée pour la théière + teapot.rotation.y = Math.PI / 4; // Même rotation que la table + + // Ajouter la théière à la scène + scene.add(teapot); + + + + // Charger le vase et le placer à côté de la théière + objLoader.load('elements/vase.obj', function (vase) { + // Appliquer un matériau au vase + vase.traverse(function (child) { + if (child instanceof THREE.Mesh) { + child.material = new THREE.MeshStandardMaterial({ + color: 0x0000FF, // Couleur orange-rouge + roughness: 0.1, + metalness: 0.2 + }); + } + }); + + // Positionner le vase à côté de la théière sur la table + vase.position.set(80, -16, -130); // Position décalée par rapport à la théière + vase.scale.set(1, 1, 1); // Ajuster l'échelle selon la taille du modèle + vase.rotation.x = -(Math.PI / 2); // 90 degrés + + // Ajouter le vase à la scène + scene.add(vase); + + // Créer un verre simple avec une géométrie de cylindre + const glassGeometry = new THREE.CylinderGeometry(3, 2.5, 8, 16); + const glassMaterial = new THREE.MeshPhysicalMaterial({ + color: 0x0066FF, // Couleur bleue + transparent: true, // Transparent pour l'effet verre + opacity: 0.6, // Semi-transparent + roughness: 0.1, // Lisse + metalness: 0.0, // Non métallique + clearcoat: 1.0, // Effet de vernis + clearcoatRoughness: 0.1 // Vernis lisse + }); + + const glass = new THREE.Mesh(glassGeometry, glassMaterial); + + // Positionner le verre à côté du vase sur la table + glass.position.set(65, -13, -130); // Ajusté pour être à côté du vase + glass.scale.set(1, 1, 1); + + // Ajouter le verre à la scène + scene.add(glass); + + + + // Ajouter deux bougies sur la table + objLoader.load('elements/candle.obj', function (candle) { + // Appliquer un matériau à la bougie + candle.traverse(function (child) { + if (child instanceof THREE.Mesh) { + child.material = new THREE.MeshStandardMaterial({ + color: 0xF5DEB3, // Couleur crème + roughness: 0.7, + metalness: 0.1 + }); + } + }); + + // Créer un clone pour la deuxième bougie + const candle1 = candle; + const candle2 = candle.clone(); + + // Positionner les bougies sur la table + candle1.position.set(110, -16, -90); // Premier emplacement + candle1.scale.set(3, 3, 3); // Ajuster la taille selon le modèle + candle1.rotation.y = Math.PI / 6; // Légère rotation + + candle2.position.set(110, -16, -100); // Deuxième emplacement + candle2.scale.set(3, 3, 3); + candle2.rotation.y = -Math.PI / 8; // Rotation différente + + // Ajouter les bougies à la scène + scene.add(candle1); + scene.add(candle2); + }); + }); + }); }); - - object.position.set(100, 0, -110); - object.scale.set(100, 100, 100); - object.rotation.y = Math.PI / 4; - object.castShadow = true; // Activer la projection d'ombre - object.receiveShadow = true; // Activer la réception d'ombre - scene.add(object); }); + // Fenêtre var windowTexture = new THREE.TextureLoader().load('elements/window.jpg'); var windowMaterial = new THREE.MeshStandardMaterial({ map: windowTexture }); var window = new THREE.Mesh(new THREE.PlaneGeometry(75, 125), windowMaterial); - window.position.set(199, 160, -80); + window.position.set(199, 60, -80); window.rotation.y = 11; scene.add(window); @@ -146,19 +347,199 @@ function fillScene() { var doorMaterial = new THREE.MeshStandardMaterial({ map: doorTexture }); var door1 = new THREE.Mesh(new THREE.PlaneGeometry(150, 250), doorMaterial); - door1.position.set(-60, 125, 199); + door1.position.set(-60, 25, 199); door1.rotation.y = 22; door1.castShadow = true; // Activer la projection d'ombre door1.receiveShadow = true; // Activer la réception d'ombre scene.add(door1); var door2 = new THREE.Mesh(new THREE.PlaneGeometry(150, 250), doorMaterial); - door2.position.set(0, 125, -199); + door2.position.set(0, 25, -199); door2.castShadow = true; // Activer la projection d'ombre door2.receiveShadow = true; // Activer la réception d'ombre scene.add(door2); + + // Premier tableau (celui d'origine) + const painting1 = createWallPainting(35, 25, 60, 80, 198, -Math.PI); + scene.add(painting1); + + // Deuxième tableau (duplicata à côté) + const painting2 = createWallPainting(35, 25, 120, 80, 198, -Math.PI); + scene.add(painting2); + + // Troisième tableau (plus large en haut) + const painting3 = createWallPainting(70, 40, 198, 100, 100, -Math.PI/2); + scene.add(painting3); + + // Quatrième tableau (sur le mur de gauche) + const painting4 = createWallPainting(20, 70, 198, 80, -160, -Math.PI/2); + scene.add(painting4); } +// Ajouter un tableau suspendu au mur +function createWallPainting(width, height, posX, posY, posZ, rotY) { + // Groupe contenant le tableau et la corde + const paintingGroup = new THREE.Group(); + + // Créer le cadre du tableau + const frameGeometry = new THREE.BoxGeometry(width + 5, height + 5, 2); + const frameTexture = new THREE.TextureLoader().load('elements/sol_boiserie.jpg'); + const frameMaterial = new THREE.MeshStandardMaterial({ + map: frameTexture, + color: 0x8B4513 + }); + const frame = new THREE.Mesh(frameGeometry, frameMaterial); + + // Créer la toile du tableau (légèrement devant le cadre) + const canvasGeometry = new THREE.PlaneGeometry(width, height); + const canvasTexture = new THREE.TextureLoader().load('elements/sol_boiserie.jpg'); + const canvasMaterial = new THREE.MeshStandardMaterial({ map: canvasTexture }); + const canvas = new THREE.Mesh(canvasGeometry, canvasMaterial); + canvas.position.z = 1.1; // Légèrement devant le cadre + + // Ajouter le cadre et la toile au groupe + paintingGroup.add(frame); + paintingGroup.add(canvas); + + // Créer la corde pour suspendre le tableau (en forme de toit/triangle) + const ropeGeometry = new THREE.BufferGeometry(); + const ropePoints = [ + new THREE.Vector3(-width/2 + 5, height/2, 0), // Point gauche du tableau + new THREE.Vector3(0, height/2 + 10, 0), // Point haut de la corde (sommet du toit) + new THREE.Vector3(width/2 - 5, height/2, 0) // Point droit du tableau + ]; + ropeGeometry.setFromPoints(ropePoints); + const ropeMaterial = new THREE.LineBasicMaterial({ color: 0x5A3A22, linewidth: 2 }); + const rope = new THREE.Line(ropeGeometry, ropeMaterial); + + // Ajouter la corde au groupe + paintingGroup.add(rope); + + // Positionner le tableau sur le mur + paintingGroup.position.set(posX, posY, posZ); + paintingGroup.rotation.y = rotY || 0; // Rotation optionnelle + + return paintingGroup; +} + +// Fonction utilitaire pour activer les ombres sur un objet et tous ses enfants +function enableShadows(object) { + object.traverse(function(child) { + if (child instanceof THREE.Mesh) { + child.castShadow = true; + child.receiveShadow = true; + } + }); + return object; // Retourner l'objet pour permettre le chaînage +} + +// Ajouter une fonction pour créer l'interface GUI +function createGUI() { + const gui = new GUI({ title: 'Contrôles' }); + // Ajouter un dossier pour les positions des lumières + const light1PosFolder = gui.addFolder('Position Lumière 1'); + light1PosFolder.add(params, 'light1X', -600, 600) + .name('X') + .onChange(value => { + light1.position.x = value; + // Mettre à jour les helpers + scene.children.forEach(child => { + if (child instanceof THREE.CameraHelper && child.camera === light1.shadow.camera) { + child.update(); + } + }); + }); + + light1PosFolder.add(params, 'light1Y', 0, 600) + .name('Y') + .onChange(value => { + light1.position.y = value; + scene.children.forEach(child => { + if (child instanceof THREE.CameraHelper && child.camera === light1.shadow.camera) { + child.update(); + } + }); + }); + + light1PosFolder.add(params, 'light1Z', -600, 600) + .name('Z') + .onChange(value => { + light1.position.z = value; + scene.children.forEach(child => { + if (child instanceof THREE.CameraHelper && child.camera === light1.shadow.camera) { + child.update(); + } + }); + }); + + // Dossier pour les lumières + const lightsFolder = gui.addFolder('Lumières'); + + lightsFolder.add(params, 'light1Intensity', 0, 10) + .name('Intensité lumière 1') + .onChange(value => { + light1.intensity = value; + }); + + lightsFolder.add(params, 'light2Intensity', 0, 10) + .name('Intensité lumière 2') + .onChange(value => { + light2.intensity = value; + }); + + // Dossier pour les effets + const effectsFolder = gui.addFolder('Effets'); + effectsFolder.add(params, 'enableShadows') + .name('Ombres') + .onChange(value => { + renderer.shadowMap.enabled = value; + light1.castShadow = value; + light2.castShadow = value; + }); + + effectsFolder.add(params, 'enableFog') + .name('Brouillard') + .onChange(value => { + if (value) { + scene.fog = new THREE.FogExp2(0xB0BEC5, params.fogDensity); + } else { + scene.fog = null; + } + }); + + effectsFolder.add(params, 'fogDensity', 0, 0.01) + .name('Densité brouillard') + .onChange(value => { + if (scene.fog) { + scene.fog.density = value; + } + }); + + // Dossier pour la caméra + const cameraFolder = gui.addFolder('Caméra'); + cameraFolder.add(params, 'cameraX', -600, 600) + .name('Position X') + .onChange(value => { + camera.position.x = value; + }); + + cameraFolder.add(params, 'cameraY', 0, 300) + .name('Position Y') + .onChange(value => { + camera.position.y = value; + }); + + cameraFolder.add(params, 'cameraZ', -600, 600) + .name('Position Z') + .onChange(value => { + camera.position.z = value; + }); + + return gui; +} + + + function init() { var canvasWidth = 900; var canvasHeight = 500; @@ -177,7 +558,7 @@ function init() { // CAMERA camera = new THREE.PerspectiveCamera(45, canvasRatio, 1, 4000); - camera.position.set(-400, 400, 20); + camera.position.set(-400, 150, -20); camera.lookAt(new THREE.Vector3(0, 0, 0)); // CONTROLS @@ -185,6 +566,9 @@ function init() { cameraControls.enableDamping = true; cameraControls.dampingFactor = 0.05; cameraControls.rotateSpeed = 1.0; + + createGUI(); + } function addToDOM() { @@ -201,10 +585,17 @@ function animate() { render(); } +// function render() { +// var delta = clock.getDelta(); +// cameraControls.update(); +// renderer.render(window.scene, camera); +// } + + function render() { var delta = clock.getDelta(); cameraControls.update(); - renderer.render(window.scene, camera); + renderer.render(scene, camera); // CORRECTION CRITIQUE } try { diff --git a/DUFOUR/elements/lit.png b/DUFOUR/elements/lit.png deleted file mode 100644 index 8661fdc19b44b57cb4de437d2a0111847beca1e7..0000000000000000000000000000000000000000 Binary files a/DUFOUR/elements/lit.png and /dev/null differ diff --git a/DUFOUR/elements/sol_boiserie.jpg b/DUFOUR/elements/sol_boiserie.jpg index c45c27b06bf28eb71b06684e12acff4df6703fa3..3776ab76c71176332fda597f9d6b0f5a33c54b9d 100644 Binary files a/DUFOUR/elements/sol_boiserie.jpg and b/DUFOUR/elements/sol_boiserie.jpg differ diff --git a/DUFOUR/img.jpg b/DUFOUR/img.jpg index 5952262131caa0b207e305b13379d19c8434f25b..5f338638e4b8c9d917fd26724f6b835f40da3e6a 100644 Binary files a/DUFOUR/img.jpg and b/DUFOUR/img.jpg differ diff --git a/DUFOUR/index.html b/DUFOUR/index.html index 6785335c3d120a9ed7b44267db0f55c59cf7903d..767f46f7822d6fd0d4c30e32b8e250a0fdfb7ca8 100644 --- a/DUFOUR/index.html +++ b/DUFOUR/index.html @@ -14,7 +14,7 @@ justify-content: center; width: 100%; gap: 20px; - } + } h2 { font-style: italic; font-weight: lighter; @@ -60,7 +60,7 @@ 1889<br> Huile sur toile</p> <img src="img.jpg" alt="La Chambre de Van Gogh - Peinture originale"> - <p>DE RYCKE Leanne <br>DUFOUR Louise <br><br>Reproduction 3D WEBGL <br>BUT1 INFO 2025</p> + <p>DE RYCKE Leanne <br>DUFOUR Louise <br><br>Reproduction 3D WEBGL <br>BUT2 INFO 2025</p> </div> <!-- Scène WebGL à droite -->