Aller au contenu principal

Test

<!DOCTYPE html>
<html lang="fr">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">

 <title>Viewer OBJ</title>

 <style>
   html,
   body {
     margin: 0;
     width: 100%;
     height: 100%;
     overflow: hidden;
     background: #ffffff;
   }

   canvas {
     display: block;
   }
 </style>

 <script type="importmap">
 {
   "imports": {
     "three": "https://cdn.jsdelivr.net/npm/three@0.180.0/build/three.module.js",
     "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.180.0/examples/jsm/"
   }
 }
 </script>
</head>

<body>

<script type="module">

import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import { OBJLoader } from "three/addons/loaders/OBJLoader.js";


/* =========================================================
  FICHIERS À CHARGER
========================================================= */

const MODEL_FOLDER = "./model/";

const OBJ_FILE = "objet.obj";
const TEXTURE_FILE = "texture.jpg";


/* =========================================================
  SCÈNE
========================================================= */

const scene = new THREE.Scene();

scene.background = new THREE.Color(0xffffff);


/* =========================================================
  CAMÉRA
========================================================= */

const camera = new THREE.PerspectiveCamera(
 45,
 window.innerWidth / window.innerHeight,
 0.01,
 100000
);

camera.position.set(0, 0, 5);


/* =========================================================
  RENDERER
========================================================= */

const renderer = new THREE.WebGLRenderer({
 antialias: true
});

renderer.setPixelRatio(
 Math.min(window.devicePixelRatio, 2)
);

renderer.setSize(
 window.innerWidth,
 window.innerHeight
);

renderer.outputColorSpace = THREE.SRGBColorSpace;

document.body.appendChild(
 renderer.domElement
);


/* =========================================================
  CONTRÔLES SOURIS
========================================================= */

const controls = new OrbitControls(
 camera,
 renderer.domElement
);

controls.enableDamping = true;

controls.dampingFactor = 0.08;

controls.enablePan = true;
controls.enableZoom = true;
controls.enableRotate = true;


/* =========================================================
  LUMIÈRES
========================================================= */

const hemisphereLight = new THREE.HemisphereLight(
 0xffffff,
 0x777777,
 2.5
);

scene.add(
 hemisphereLight
);


const directionalLight1 = new THREE.DirectionalLight(
 0xffffff,
 2.5
);

directionalLight1.position.set(
 4,
 5,
 5
);

scene.add(
 directionalLight1
);


const directionalLight2 = new THREE.DirectionalLight(
 0xffffff,
 1.5
);

directionalLight2.position.set(
 -4,
 2,
 -3
);

scene.add(
 directionalLight2
);


/* =========================================================
  TEXTURE
========================================================= */

const textureLoader = new THREE.TextureLoader();

const texture = textureLoader.load(
 MODEL_FOLDER + TEXTURE_FILE,

 function(texture) {

   texture.colorSpace = THREE.SRGBColorSpace;

   texture.wrapS = THREE.RepeatWrapping;
   texture.wrapT = THREE.RepeatWrapping;

   texture.flipY = true;

 },

 undefined,

 function(error) {

   console.warn(
     "La texture n'a pas pu être chargée.",
     error
   );

 }
);


/* =========================================================
  MATÉRIAU
========================================================= */

const material = new THREE.MeshStandardMaterial({

 map: texture,

 color: 0xffffff,

 roughness: 0.8,

 metalness: 0,

 side: THREE.DoubleSide

});


/* =========================================================
  CHARGEMENT OBJ
========================================================= */

const objLoader = new OBJLoader();

objLoader.setPath(
 MODEL_FOLDER
);


objLoader.load(

 OBJ_FILE,


 function(object) {

   object.traverse(
     function(child) {

       if (child.isMesh) {

         if (
           !child.geometry.attributes.normal
         ) {

           child.geometry.computeVertexNormals();

         }


         child.material =
           material;

       }

     }
   );


   scene.add(
     object
   );


   centerObject(
     object
   );

 },


 function(xhr) {

   if (
     xhr.total > 0
   ) {

     const percent =
       Math.round(
         xhr.loaded /
         xhr.total *
         100
       );


     console.log(
       percent +
       "% chargé"
     );

   }

 },


 function(error) {

   console.error(
     "Erreur de chargement OBJ :",
     error
   );

 }

);


/* =========================================================
  CENTRER AUTOMATIQUEMENT L'OBJET
========================================================= */

function centerObject(
 object
) {

 const box =
   new THREE.Box3()
   .setFromObject(
     object
   );


 const center =
   box.getCenter(
     new THREE.Vector3()
   );


 object.position.x -=
   center.x;

 object.position.y -=
   center.y;

 object.position.z -=
   center.z;


 const centeredBox =
   new THREE.Box3()
   .setFromObject(
     object
   );


 const size =
   centeredBox.getSize(
     new THREE.Vector3()
   );


 const maxSize =
   Math.max(
     size.x,
     size.y,
     size.z
   );


 if (
   !Number.isFinite(maxSize) ||
   maxSize <= 0
 ) {

   return;

 }


 const fov =
   camera.fov *
   Math.PI /
   180;


 let distance =
   maxSize /
   (
     2 *
     Math.tan(
       fov / 2
     )
   );


 distance *= 1.5;


 camera.position.set(

   distance * 0.65,

   distance * 0.35,

   distance

 );


 camera.near =
   Math.max(
     distance / 1000,
     0.001
   );


 camera.far =
   distance * 100;


 camera.updateProjectionMatrix();


 controls.target.set(
   0,
   0,
   0
 );


 controls.minDistance =
   distance * 0.05;


 controls.maxDistance =
   distance * 10;


 controls.update();

}


/* =========================================================
  REDIMENSIONNEMENT
========================================================= */

window.addEventListener(
 "resize",
 function() {

   camera.aspect =
     window.innerWidth /
     window.innerHeight;


   camera.updateProjectionMatrix();


   renderer.setSize(
     window.innerWidth,
     window.innerHeight
   );

 }
);


/* =========================================================
  BOUCLE D'AFFICHAGE
========================================================= */

function animate() {

 requestAnimationFrame(
   animate
 );


 controls.update();


 renderer.render(
   scene,
   camera
 );

}


animate();

</script>

</body>
</html>