You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
444 lines
30 KiB
444 lines
30 KiB
2 years ago
|
<!DOCTYPE html><html lang="fr"><head>
|
||
|
<meta charset="utf-8">
|
||
|
<title>principes de base</title>
|
||
|
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
|
||
|
<meta name="twitter:card" content="summary_large_image">
|
||
|
<meta name="twitter:site" content="@threejs">
|
||
|
<meta name="twitter:title" content="Three.js – principes de base">
|
||
|
<meta property="og:image" content="https://threejs.org/files/share.png">
|
||
|
<link rel="shortcut icon" href="/files/favicon_white.ico" media="(prefers-color-scheme: dark)">
|
||
|
<link rel="shortcut icon" href="/files/favicon.ico" media="(prefers-color-scheme: light)">
|
||
|
|
||
|
<link rel="stylesheet" href="/manual/resources/lesson.css">
|
||
|
<link rel="stylesheet" href="/manual/resources/lang.css">
|
||
|
<!-- Import maps polyfill -->
|
||
|
<!-- Remove this when import maps will be widely supported -->
|
||
|
<script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script>
|
||
|
|
||
|
<script type="importmap">
|
||
|
{
|
||
|
"imports": {
|
||
|
"three": "../../build/three.module.js"
|
||
|
}
|
||
|
}
|
||
|
</script>
|
||
|
</head>
|
||
|
<body>
|
||
|
<div class="container">
|
||
|
<div class="lesson-title">
|
||
|
<h1>principes de base</h1>
|
||
|
</div>
|
||
|
<div class="lesson">
|
||
|
<div class="lesson-main">
|
||
|
<p>Ceci est le premier article d'une série consacrée à Three.js.
|
||
|
<a href="https://threejs.org">Three.js</a> est une bibliothèque 3D qui a pour objectif
|
||
|
de rendre aussi facile que possible l'inclusion de contenu 3D dans une page web.</p>
|
||
|
<p>Three.js est souvent confondu avec WebGL puisque la plupart du temps, mais
|
||
|
pas toujours, elle exploite WebGL pour dessiner en 3D.
|
||
|
<a href="https://webglfundamentals.org">WebGL est un système très bas niveau qui ne dessine que des points, des lignes et des triangles</a>.
|
||
|
Faire quelque chose d'exploitable avec WebGL requiert une certaine quantité de code
|
||
|
et c'est là que Three.js intervient. Elle prend en charge des choses
|
||
|
telles que les scènes, lumières, ombres, matériaux, textures, mathématiques 3D, en bref,
|
||
|
tout ce que vous avez à écrire par vous même si vous aviez à utiliser WebGL directement.</p>
|
||
|
<p>Ces tutoriels supposent que JavaScript vous est connu et, pour grande partie,
|
||
|
se conforment au style ES6. <a href="prerequisites.html">Consultez ici une brève liste des choses que vous êtes
|
||
|
déjà censés connaître</a>.</p>
|
||
|
<p>La plupart des navigateurs qui supportent three.js se mettent à jour automatiquement
|
||
|
donc la plupart des utilisateurs devraient être capables d'exécuter ce code.
|
||
|
Si vous souhaitez exécuter ce code sur un très vieux navigateur, nous vous recommandons
|
||
|
un transpileur tel que <a href="https://babeljs.io">Babel</a>.
|
||
|
Bien sûr, les utilisateurs exécutant de très vieux navigateurs ont probablement
|
||
|
des machines incapables de faire tourner Three.js.</p>
|
||
|
<p>Lors de l'apprentissage de la plupart des langages de programmation,
|
||
|
la première tâche que les gens font est de faire afficher à l'ordinateur
|
||
|
<code class="notranslate" translate="no">"Hello World!"</code>. Pour la programmation 3D, l'équivalent est de faire afficher
|
||
|
un cube en 3D. Donc, nous commencerons par "Hello Cube!".</p>
|
||
|
<p>Avant de débuter, nous allons tenter de vous donner un idée de la structure
|
||
|
d'une application Three.js. Elle requiert de créer un ensemble d'objets
|
||
|
et de les connecter. Voici un diagramme qui représente une application
|
||
|
Three.js de petite taille:</p>
|
||
|
<div class="threejs_center"><img src="../resources/images/threejs-structure.svg" style="width: 768px;"></div>
|
||
|
|
||
|
<p>Voici ce qui est à remarquer dans le diagramme ci-dessus :</p>
|
||
|
<ul>
|
||
|
<li><p>Il y a un <a href="/docs/#api/en/constants/Renderer"><code class="notranslate" translate="no">Renderer</code></a>. C'est sans doute l'objet principal de Three.js. Vous passez
|
||
|
une <a href="/docs/#api/en/scenes/Scene"><code class="notranslate" translate="no">Scene</code></a> et une <a href="/docs/#api/en/cameras/Camera"><code class="notranslate" translate="no">Camera</code></a> à un <a href="/docs/#api/en/constants/Renderer"><code class="notranslate" translate="no">Renderer</code></a> et il effectue le rendu (dessine) de la
|
||
|
partie de la scène 3D qui est à l'intérieur de l'espace visible (en réalité une pyramide tronquée ou <em>frustum</em>)
|
||
|
de la caméra dans une image 2D affichée dans un canevas (<em>canvas</em>).</p>
|
||
|
</li>
|
||
|
<li><p>Il y a un <a href="scenegraph.html">graphe de scène</a> qui est une structure arborescente,
|
||
|
constituée de divers objets tel qu'un objet <a href="/docs/#api/en/scenes/Scene"><code class="notranslate" translate="no">Scene</code></a>, de multiple maillages (<a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a>),
|
||
|
des lumières (<a href="/docs/#api/en/lights/Light"><code class="notranslate" translate="no">Light</code></a>), des groupes (<a href="/docs/#api/en/objects/Group"><code class="notranslate" translate="no">Group</code></a>), des objets 3D <a href="/docs/#api/en/core/Object3D"><code class="notranslate" translate="no">Object3D</code></a> et des objets <a href="/docs/#api/en/cameras/Camera"><code class="notranslate" translate="no">Camera</code></a>.
|
||
|
Un objet <a href="/docs/#api/en/scenes/Scene"><code class="notranslate" translate="no">Scene</code></a> définit la racine d'un graphe de scène et contient des propriétés telles que
|
||
|
la couleur d'arrière plan et le brouillard. L'ensemble de ces objets définissent une structure
|
||
|
hiérarchique de type parent/enfant, arborescente, et indique où les objets apparaissent et
|
||
|
comment ils sont orientés. Les enfants sont positionnés et orientés par rapport à leur parent.
|
||
|
Par exemple, les roues d'une voiture sont les enfants du châssis impliquant que si l'on déplace
|
||
|
ou oriente la voiture, les roues suivront automatiquement son déplacement. Plus de
|
||
|
détails sont donnés dans <a href="scenegraph.html">l'article sur les graphes de scène</a>.</p>
|
||
|
<p>Il est à noter sur que ce diagramme <a href="/docs/#api/en/cameras/Camera"><code class="notranslate" translate="no">Camera</code></a> est patiellement placé dans le graphe de scène.
|
||
|
Cela permet d'attirer l'attention qu'en Three.js, contrairement aux autres objets, une <a href="/docs/#api/en/cameras/Camera"><code class="notranslate" translate="no">Camera</code></a> ne doit
|
||
|
pas forcément faire partie du graphe de scène pour être opérationnelle. Une <a href="/docs/#api/en/cameras/Camera"><code class="notranslate" translate="no">Camera</code></a>, de la même
|
||
|
façon que les autres objets, enfant d'un autre objet, se déplace et s'oriente par rapport à son
|
||
|
objet parent. A la fin de <a href="scenegraph.html">l'article sur les graphes de scène</a>, l'inclusion
|
||
|
de multiples objets <a href="/docs/#api/en/cameras/Camera"><code class="notranslate" translate="no">Camera</code></a> dans un unique graphe de scène est donné en exemple.</p>
|
||
|
</li>
|
||
|
<li><p>Les objets de type <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a> représentent une géométrie (<code class="notranslate" translate="no">Geometry</code>) liée à un matériau (<a href="/docs/#api/en/materials/Material"><code class="notranslate" translate="no">Material</code></a>)
|
||
|
spécifique. Les objets <a href="/docs/#api/en/materials/Material"><code class="notranslate" translate="no">Material</code></a> et <code class="notranslate" translate="no">Geometry</code> peuvent être liés à plusieurs objets <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a>
|
||
|
simultanément. Par exemple, pour dessiner deux cubes bleus à des positions différentes, nous
|
||
|
pouvons soit utiliser deux objets <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a> pour spécifier les positions et orientations de
|
||
|
chaque cube; soit nous pouvons utiliser seulement une géométrie unique (<code class="notranslate" translate="no">Geometry</code>) pour décrire les
|
||
|
données spatiales du cube et un matériau unique (<a href="/docs/#api/en/materials/Material"><code class="notranslate" translate="no">Material</code></a>) pour spécifier la couleur bleue.
|
||
|
Les deux objets <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a> peuvent ainsi référencer les mêmes objets <code class="notranslate" translate="no">Geometry</code> et <a href="/docs/#api/en/materials/Material"><code class="notranslate" translate="no">Material</code></a>.</p>
|
||
|
</li>
|
||
|
<li><p>Les objets <code class="notranslate" translate="no">Geometry</code> représentent les données associées aux sommets d'une géométrie telle qu'une
|
||
|
sphère, un cube, un avion, un chien, un chat, un humain, un arbre, un bâtiment, etc...
|
||
|
Three.js fournit plusieurs types intégrés de <a href="primitives.html">primitives géométriques</a>.
|
||
|
Vous pouvez aussi <a href="custom-buffergeometry.html">créer vos propres géométries</a> ou
|
||
|
<a href="load-obj.html">charger des géométries à partir d'un fichier</a>.</p>
|
||
|
</li>
|
||
|
<li><p>Les objets <a href="/docs/#api/en/materials/Material"><code class="notranslate" translate="no">Material</code></a> représentent les
|
||
|
<a href="materials.html">propriétés de surface utilisées pour dessiner la géométrie</a>
|
||
|
telles que la couleur à utiliser ou le pouvoir réfléchissant (brillance). Un matériau (<a href="/docs/#api/en/materials/Material"><code class="notranslate" translate="no">Material</code></a>)
|
||
|
peut aussi se référer à un ou plusieurs objets <a href="/docs/#api/en/textures/Texture"><code class="notranslate" translate="no">Texture</code></a> dont l'utilité est, par exemple, de plaquer
|
||
|
une image sur la surface d'une géométrie.</p>
|
||
|
</li>
|
||
|
<li><p>Les objets <a href="/docs/#api/en/textures/Texture"><code class="notranslate" translate="no">Texture</code></a> représentent généralement des images soit <a href="textures.html">chargées de fichiers image</a>,
|
||
|
soit <a href="canvas-textures.html">générées par le biais d'un canevas</a> ou
|
||
|
<a href="rendertargets.html">résultant du rendu d'une autre scène</a>.</p>
|
||
|
</li>
|
||
|
<li><p>Les objets <a href="/docs/#api/en/lights/Light"><code class="notranslate" translate="no">Light</code></a> représentent <a href="lights.html">différentes sortent de lumière</a>.</p>
|
||
|
</li>
|
||
|
</ul>
|
||
|
<p>Maintenant que tout cela a été défini, nous allons présenter un exemple de type <em>"Hello Cube"</em> utilisant un
|
||
|
nombre minimum d'élements Three.js :</p>
|
||
|
<div class="threejs_center"><img src="../resources/images/threejs-1cube-no-light-scene.svg" style="width: 500px;"></div>
|
||
|
|
||
|
<p>Tout d'abord, chargeons Three.js :</p>
|
||
|
<pre class="prettyprint showlinemods notranslate lang-html" translate="no"><script type="module">
|
||
|
import * as THREE from 'three';
|
||
|
</script>
|
||
|
</pre>
|
||
|
<p>Il est important d'écrire <code class="notranslate" translate="no">type="module"</code> dans la balise script.
|
||
|
Cela nous autorise l'utilisation du mot-clé <code class="notranslate" translate="no">import</code> pour charger Three.js.
|
||
|
Il y a d'autres manières de le réaliser, mais depuis la version 106 (r106),
|
||
|
l'utilisation des modules est recommandée. Ils ont l'avantage de pouvoir
|
||
|
facilement importer les autres modules dont ils ont besoin. Cela nous
|
||
|
épargne d'avoir à charger à la main les scripts supplémentaires dont ils dépendent.</p>
|
||
|
<p>Ensuite, nous avons besoin d'une balise <code class="notranslate" translate="no"><canvas></code> :</p>
|
||
|
<pre class="prettyprint showlinemods notranslate lang-html" translate="no"><body>
|
||
|
<canvas id="c"></canvas>
|
||
|
</body>
|
||
|
</pre>
|
||
|
<p>Nous allons demander à Three.js de dessiner dans ce canevas donc nous devons le rechercher
|
||
|
dans le document html :</p>
|
||
|
<pre class="prettyprint showlinemods notranslate lang-html" translate="no"><script type="module">
|
||
|
import * as THREE from 'three';
|
||
|
|
||
|
+function main() {
|
||
|
+ const canvas = document.querySelector('#c');
|
||
|
+ const renderer = new THREE.WebGLRenderer({canvas});
|
||
|
+ ...
|
||
|
</script>
|
||
|
</pre>
|
||
|
<p>Après la recherche du canevas, nous créons un <a href="/docs/#api/en/renderers/WebGLRenderer"><code class="notranslate" translate="no">WebGLRenderer</code></a>. Le <em>renderer</em>
|
||
|
a pour mission de charger les données fournies et d'en effectuer le rendu
|
||
|
dans le canevas. Par le passé, il y a eu aussi d'autre <em>renderers</em> tels que
|
||
|
<code class="notranslate" translate="no">CSSRenderer</code> ou <code class="notranslate" translate="no">CanvasRenderer</code> et, dans le futur, il pourrait y avoir un
|
||
|
<code class="notranslate" translate="no">WebGL2Renderer</code> ou <code class="notranslate" translate="no">WebGPURenderer</code>. Pour le moment, il y a un <a href="/docs/#api/en/renderers/WebGLRenderer"><code class="notranslate" translate="no">WebGLRenderer</code></a>
|
||
|
qui utiliser WebGL pour effectuer une rendu 3D dans le canevas.</p>
|
||
|
<p>Notez qu'il y a quelques détails ésotériques ici. Si vous ne passez pas un
|
||
|
canevas à Three.js, il va en créer un pour vous mais vous aurez à l'ajouter
|
||
|
au document. Où l'ajouter peut dépendre du contexte d'utilisation et vous aurez
|
||
|
à modifier votre code en conséquence. Passer un canevas à Three.js nous apparaît donc
|
||
|
plus flexible. Nous pouvons mettre le canevas n'importe où et le code le retrouvera.
|
||
|
Dans le cas contraire, nous aurons à coder où insérer le canevas, ce qui amènera
|
||
|
probablement à changer le code si le contexte d'utilisation change.</p>
|
||
|
<p>Ensuite, nous avons besoin d'une caméra. Nous créons une <a href="/docs/#api/en/cameras/PerspectiveCamera"><code class="notranslate" translate="no">PerspectiveCamera</code></a>.</p>
|
||
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const fov = 75;
|
||
|
const aspect = 2; // valeur par défaut du canevas
|
||
|
const near = 0.1;
|
||
|
const far = 5;
|
||
|
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
|
||
|
</pre>
|
||
|
<p><code class="notranslate" translate="no">fov</code> est le raccourci pour <code class="notranslate" translate="no">field of view</code> ou champ de vision.
|
||
|
Dans ce cas, 75 degrés d'ouverture verticale. Il est à noter que
|
||
|
la plupart des angles dans Three.js sont exprimés en radians à l'exception
|
||
|
de la caméra perspective.</p>
|
||
|
<p><code class="notranslate" translate="no">aspect</code> est l'aspect de l'affichage dans le canevas. Cela sera détaillé
|
||
|
<a href="responsive.html">dans un autre article</a>. Toutefois, par défaut,
|
||
|
un canevas est de taille 300x150 pixels ce qui lui confère l'aspect 300/150 ou 2.</p>
|
||
|
<p><code class="notranslate" translate="no">near</code> et <code class="notranslate" translate="no">far</code> délimitent la portion de l'espace devant la caméra dont
|
||
|
le rendu est effectué. Tout ce qui est avant ou après est découpé (<em>clipped</em>),
|
||
|
donc non dessiné.</p>
|
||
|
<p>Ces 4 paramètres définissent une pyramide tronquée ou <em>"frustum"</em>.
|
||
|
En d'autres termes, il s'agit d'une autre forme 3D à l'instar des sphères,
|
||
|
cubes et prismes.</p>
|
||
|
<p><img src="../resources/frustum-3d.svg" width="500" class="threejs_center"></p>
|
||
|
<p>L'espacement entre les plans <em>near</em> et <em>far</em> est déterminé
|
||
|
par le champ de vision. La largeur est fixée par le champ de vision et l'aspect.</p>
|
||
|
<p>Tout ce qui est dans le <em>frustum</em> est dessiné. Ce qui est à l'extérieur ne l'est pas.</p>
|
||
|
<p>La caméra regarde par défaut suivant l'axe -Z, +Y pointant le haut.
|
||
|
Nous mettons notre cube à l'origine donc nous devons déplacer la caméra de l'origine légèrement vers son arrière
|
||
|
pour voir quelque chose.</p>
|
||
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">camera.position.z = 2;
|
||
|
</pre>
|
||
|
<p>Voici ce que nous voudrions voir :</p>
|
||
|
<p><img src="../resources/scene-down.svg" width="500" class="threejs_center"></p>
|
||
|
<p>Dans le schéma ci-dessus, nous pouvons voir que notre caméra est placée
|
||
|
en <code class="notranslate" translate="no">z = 2</code>. Elle regarde le long de la direction -Z.
|
||
|
Notre <em>frustum</em> démarre à 0.1 unités de la caméra et s'étend jusqu'à 5 unités devant elle.
|
||
|
Comme le schéma est vu du haut, le champ de vue est affecté par l'aspect.
|
||
|
Notre canvas est deux fois plus large que haut donc le champ de vue horizontal
|
||
|
est plus grand que les 75 degrés spécifié pour le champ vertical.</p>
|
||
|
<p>Ensuite, nous créons une <a href="/docs/#api/en/scenes/Scene"><code class="notranslate" translate="no">Scene</code></a>. Dans Three.js, une <a href="/docs/#api/en/scenes/Scene"><code class="notranslate" translate="no">Scene</code></a> est la racine
|
||
|
du graphe de scène. Tout ce que nous voulons que Three.js dessine doit être ajouté
|
||
|
à la scène. Cela sera davantage détaillé dans <a href="scenegraph.html">un futur article sur le fonctionnement des scènes</a>.</p>
|
||
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const scene = new THREE.Scene();
|
||
|
</pre>
|
||
|
<p>Ensuite nous créons une géométrie de type <a href="/docs/#api/en/geometries/BoxGeometry"><code class="notranslate" translate="no">BoxGeometry</code></a> qui contient les données pour un parallélépipède.
|
||
|
Quasiment tout ce que nous souhaitons afficher avec Three.js nécessite une
|
||
|
géométrie qui définit les sommets qui composent nos objets 3D.</p>
|
||
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const boxWidth = 1;
|
||
|
const boxHeight = 1;
|
||
|
const boxDepth = 1;
|
||
|
const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
|
||
|
</pre>
|
||
|
<p>Puis nous créons un matériau basique et fixons sa couleur, qui peut être spécifiée au format hexadécimal (6 chiffres) du standard CSS.</p>
|
||
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const material = new THREE.MeshBasicMaterial({color: 0x44aa88});
|
||
|
</pre>
|
||
|
<p>Nous créons ensuite un maillage (<a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a>). Dans Three.js, il représente la combinaison
|
||
|
d'une <code class="notranslate" translate="no">Geometry</code> (forme de l'objet) et d'un matériau (<a href="/docs/#api/en/materials/Material"><code class="notranslate" translate="no">Material</code></a> - aspect
|
||
|
d'un objet, brillant ou plat, quelle couleur, quelle texture appliquer, etc.)
|
||
|
ainsi que la position, l'orientation et l'échelle de l'objet dans la scène.</p>
|
||
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const cube = new THREE.Mesh(geometry, material);
|
||
|
</pre>
|
||
|
<p>Finalement, nous ajoutons le maillage à la scène.</p>
|
||
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">scene.add(cube);
|
||
|
</pre>
|
||
|
<p>Nous pouvons, maintenant, effectuer le rendu de la scène en appelant la fonction <em>render</em> du <em>renderer</em>
|
||
|
et en lui passant la scène et la caméra.</p>
|
||
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">renderer.render(scene, camera);
|
||
|
</pre>
|
||
|
<p>Voici un exemple fonctionnel :</p>
|
||
|
<p></p><div translate="no" class="threejs_example_container notranslate">
|
||
|
<div><iframe class="threejs_example notranslate" translate="no" style=" " src="/manual/examples/resources/editor.html?url=/manual/examples/fundamentals.html"></iframe></div>
|
||
|
<a class="threejs_center" href="/manual/examples/fundamentals.html" target="_blank">Cliquer ici pour ouvrir dans une fenêtre séparée</a>
|
||
|
</div>
|
||
|
|
||
|
<p></p>
|
||
|
<p>Il est difficile de déterminer s'il s'agit d'un cube 3D puisque nous
|
||
|
l'observons suivant l'axe -Z sur lequel le cube est lui même aligné.
|
||
|
Nous n'en voyons donc qu'une face.</p>
|
||
|
<p>Animons notre cube en le faisant tourner et cela fera clairement
|
||
|
apparaître qu'il est dessiné en 3D. Pour l'animation, nous effectuerons son rendu
|
||
|
dans une boucle de rendu en utilisant
|
||
|
<a href="https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame"><code class="notranslate" translate="no">requestAnimationFrame</code></a>.</p>
|
||
|
<p>Voici notre boucle :</p>
|
||
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function render(time) {
|
||
|
time *= 0.001; // convertis le temps en secondes
|
||
|
|
||
|
cube.rotation.x = time;
|
||
|
cube.rotation.y = time;
|
||
|
|
||
|
renderer.render(scene, camera);
|
||
|
|
||
|
requestAnimationFrame(render);
|
||
|
}
|
||
|
requestAnimationFrame(render);
|
||
|
</pre>
|
||
|
<p><code class="notranslate" translate="no">requestAnimationFrame</code> est une requête auprès du navigateur dans le cas où vous
|
||
|
voulez animer quelque chose. Nous lui passons une fonction à appeler.
|
||
|
Dans notre cas, c'est la fonction <code class="notranslate" translate="no">render</code>. Le navigateur appellera cette fonction
|
||
|
et, si nous mettons à jour l'affichage de la page, le navigateur refera le rendu
|
||
|
de la page. Dans notre cas, nous appelons la fonction <code class="notranslate" translate="no">renderer.render</code> de Three.js
|
||
|
qui dessinera notre scène.</p>
|
||
|
<p><code class="notranslate" translate="no">requestAnimationFrame</code> passe à notre fonction le temps depuis lequel la page est chargée.
|
||
|
Il est mesuré en millisecondes. Il est parfois plus facile de travailler
|
||
|
avec des secondes. C'est pourquoi, nous l'avons converti.</p>
|
||
|
<p>A présent, nous appliquons sur le cube des rotations le long des axes X et Y en fonction du temps écoulé.
|
||
|
Les angles de rotation sont exprimés en <a href="https://en.wikipedia.org/wiki/Radian">radians</a>.
|
||
|
Sachant que 2 PI radians fait faire un tour complet, notre cube effectuera une rotation complète
|
||
|
sur chaque axe en, à peu près, 6,28 secondes.</p>
|
||
|
<p>Nous effectuons alors le rendu de la scène et
|
||
|
demandons une autre image pour l'animation afin de poursuivre notre boucle.</p>
|
||
|
<p>A l'extérieur de la boucle, nous appelons <code class="notranslate" translate="no">requestAnimationFrame</code> une première fois pour activer la boucle.</p>
|
||
|
<p></p><div translate="no" class="threejs_example_container notranslate">
|
||
|
<div><iframe class="threejs_example notranslate" translate="no" style=" " src="/manual/examples/resources/editor.html?url=/manual/examples/fundamentals-with-animation.html"></iframe></div>
|
||
|
<a class="threejs_center" href="/manual/examples/fundamentals-with-animation.html" target="_blank">Cliquer ici pour ouvrir dans une fenêtre séparée</a>
|
||
|
</div>
|
||
|
|
||
|
<p></p>
|
||
|
<p>C'est un peu mieux mais il est toujours difficile de percevoir la 3D.
|
||
|
Ce qui aiderait serait d'ajouter de la lumière.
|
||
|
Three.js propose plusieurs type de lumière que nous détaillerons dans
|
||
|
<a href="lights.html">un futur article</a>. Pour le moment, créons une lumière directionnelle.</p>
|
||
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
|
||
|
const color = 0xFFFFFF;
|
||
|
const intensity = 1;
|
||
|
const light = new THREE.DirectionalLight(color, intensity);
|
||
|
light.position.set(-1, 2, 4);
|
||
|
scene.add(light);
|
||
|
}
|
||
|
</pre>
|
||
|
<p>Les lumières directionnelles ont une position et une cible. Les deux sont par défaut en 0, 0, 0.
|
||
|
Dans notre cas, nous positionnons la lumière en -1, 2, 4, de manière à ce qu'elle soit légèrement
|
||
|
sur la gauche, au dessus et derrière notre caméra. La cible est toujours 0, 0, 0 donc elle va
|
||
|
éclairer vers l'origine.</p>
|
||
|
<p>Nous avons également besoin de changer le matériau car <a href="/docs/#api/en/materials/MeshBasicMaterial"><code class="notranslate" translate="no">MeshBasicMaterial</code></a> ne s'applique pas aux
|
||
|
lumières. Nous le remplaçons par un <a href="/docs/#api/en/materials/MeshPhongMaterial"><code class="notranslate" translate="no">MeshPhongMaterial</code></a> qui est affecté par les sources lumineuses.</p>
|
||
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">-const material = new THREE.MeshBasicMaterial({color: 0x44aa88}); // cyan
|
||
|
+const material = new THREE.MeshPhongMaterial({color: 0x44aa88}); // cyan
|
||
|
</pre>
|
||
|
<p>Voici à présent la nouvelle structure de notre programme :</p>
|
||
|
<div class="threejs_center"><img src="../resources/images/threejs-1cube-with-directionallight.svg" style="width: 500px;"></div>
|
||
|
|
||
|
<p>Et voici son fonctionnement :</p>
|
||
|
<p></p><div translate="no" class="threejs_example_container notranslate">
|
||
|
<div><iframe class="threejs_example notranslate" translate="no" style=" " src="/manual/examples/resources/editor.html?url=/manual/examples/fundamentals-with-light.html"></iframe></div>
|
||
|
<a class="threejs_center" href="/manual/examples/fundamentals-with-light.html" target="_blank">Cliquer ici pour ouvrir dans une fenêtre séparée</a>
|
||
|
</div>
|
||
|
|
||
|
<p></p>
|
||
|
<p>Cela devrait à présent apparaître très clairement en 3D.</p>
|
||
|
<p>Pour le sport, ajoutons 2 cubes supplémentaires.</p>
|
||
|
<p>Nous partageons la même géométrie pour chaque cube mais un matériau différent par cube
|
||
|
afin qu'ils aient une couleur différente.</p>
|
||
|
<p>Tout d'abord, nous définissons une fonction qui crée un nouveau matériau
|
||
|
avec la couleur spécifiée. Ensuite, elle créé un maillage à partir de la
|
||
|
géométrie spécifiée, l'ajoute à la scène et change sa position en X.</p>
|
||
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function makeInstance(geometry, color, x) {
|
||
|
const material = new THREE.MeshPhongMaterial({color});
|
||
|
|
||
|
const cube = new THREE.Mesh(geometry, material);
|
||
|
scene.add(cube);
|
||
|
|
||
|
cube.position.x = x;
|
||
|
|
||
|
return cube;
|
||
|
}
|
||
|
</pre>
|
||
|
<p>Ensuite, nous l'appellons à 3 reprises avec 3 différentes couleurs
|
||
|
et positions en X, puis nous conservons ces instances de <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a> dans un tableau.</p>
|
||
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const cubes = [
|
||
|
makeInstance(geometry, 0x44aa88, 0),
|
||
|
makeInstance(geometry, 0x8844aa, -2),
|
||
|
makeInstance(geometry, 0xaa8844, 2),
|
||
|
];
|
||
|
</pre>
|
||
|
<p>Enfin, nous faisons tourner ces 3 cubes dans notre fonction de rendu.
|
||
|
Nous calculons une rotation légèrement différente pour chacun d'eux.</p>
|
||
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function render(time) {
|
||
|
time *= 0.001; // conversion du temps en secondes
|
||
|
|
||
|
cubes.forEach((cube, ndx) => {
|
||
|
const speed = 1 + ndx * .1;
|
||
|
const rot = time * speed;
|
||
|
cube.rotation.x = rot;
|
||
|
cube.rotation.y = rot;
|
||
|
});
|
||
|
|
||
|
...
|
||
|
</pre>
|
||
|
<p>et voilà le résultat.</p>
|
||
|
<p></p><div translate="no" class="threejs_example_container notranslate">
|
||
|
<div><iframe class="threejs_example notranslate" translate="no" style=" " src="/manual/examples/resources/editor.html?url=/manual/examples/fundamentals-3-cubes.html"></iframe></div>
|
||
|
<a class="threejs_center" href="/manual/examples/fundamentals-3-cubes.html" target="_blank">Cliquer ici pour ouvrir dans une fenêtre séparée</a>
|
||
|
</div>
|
||
|
|
||
|
<p></p>
|
||
|
<p>Si nous le comparons au schéma précédent, nous constatons qu'il
|
||
|
est conforme à nos attentes. Les cubes en X = -2 et X = +2
|
||
|
sont partiellement en dehors du <em>frustum</em>. Ils sont, de plus,
|
||
|
exagérément déformés puisque le champ de vision dépeint au travers du
|
||
|
canevas est extrême.</p>
|
||
|
<p>A présent, notre programme est schématisé par la figure suivante :</p>
|
||
|
<div class="threejs_center"><img src="../resources/images/threejs-3cubes-scene.svg" style="width: 610px;"></div>
|
||
|
|
||
|
<p>Comme nous pouvons le constater, nous avons 3 objets de type <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a>, chacun référençant
|
||
|
la même <a href="/docs/#api/en/geometries/BoxGeometry"><code class="notranslate" translate="no">BoxGeometry</code></a>. Chaque <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a> référence également un <a href="/docs/#api/en/materials/MeshPhongMaterial"><code class="notranslate" translate="no">MeshPhongMaterial</code></a> unique
|
||
|
de sorte que chaque cube possède une couleur différente.</p>
|
||
|
<p>Nous espérons que cette courte introduction vous aide à débuter.
|
||
|
<a href="responsive.html">La prochaine étape consiste à rendre notre code réactif et donc adaptable à de multiples situations</a>.</p>
|
||
|
<div class="threejs_bottombar">
|
||
|
<h3>es6 modules, Three.js et structure de dossiers</h3>
|
||
|
<p>Depuis la version 106 (r106), l'utilisation de Three.js privilégie les <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import">modules es6</a>.</p>
|
||
|
<p>
|
||
|
Ils sont chargés via le mot-clé <code class="notranslate" translate="no">import</code> dans un script ou en ligne
|
||
|
par le biais d'une balise <code class="notranslate" translate="no"><script type="module"></code>. Voici un exemple d'utilisation avec les deux :
|
||
|
</p>
|
||
|
<pre class="prettyprint"><script type="module">
|
||
|
import * as THREE from 'three';
|
||
|
|
||
|
...
|
||
|
|
||
|
</script>
|
||
|
</pre>
|
||
|
<p>
|
||
|
Les chemins doivent être absolus ou relatifs. Un chemin relatif commencent toujours par
|
||
|
<code class="notranslate" translate="no">./</code> ou par <code class="notranslate" translate="no">../</code>,
|
||
|
ce qui est différent des autres balises telles que <code class="notranslate" translate="no"><img></code> et <code class="notranslate" translate="no"><a></code>.
|
||
|
</p>
|
||
|
<p>
|
||
|
Les références à un même script ne seront chargées qu'une seule fois à partir du
|
||
|
moment où leur chemin absolu est exactement identique. Pour Three.js, cela veut
|
||
|
dire qu'il est nécessaire de mettre toutes les bibliothèques d'exemples dans une
|
||
|
structure correcte pour les dossiers :
|
||
|
</p>
|
||
|
<pre class="dos">unDossier
|
||
|
|
|
||
|
├-build
|
||
|
| |
|
||
|
| +-three.module.js
|
||
|
|
|
||
|
+-examples
|
||
|
|
|
||
|
+-jsm
|
||
|
|
|
||
|
+-controls
|
||
|
| |
|
||
|
| +-OrbitControls.js
|
||
|
| +-TrackballControls.js
|
||
|
| +-...
|
||
|
|
|
||
|
+-loaders
|
||
|
| |
|
||
|
| +-GLTFLoader.js
|
||
|
| +-...
|
||
|
|
|
||
|
...
|
||
|
</pre>
|
||
|
<p>
|
||
|
La raison nécessitant cette structuration des dossiers est parce que les scripts
|
||
|
des exemples tels que <a href="https://github.com/mrdoob/three.js/blob/master/examples/jsm/controls/OrbitControls.js"><code class="notranslate" translate="no">OrbitControls.js</code></a>
|
||
|
ont des chemins relatifs tels que :
|
||
|
</p>
|
||
|
<pre class="prettyprint">import * as THREE from '../../../build/three.module.js';
|
||
|
</pre>
|
||
|
<p>
|
||
|
Utiliser la même structure permet de s'assurer, lors de l'importation de
|
||
|
Three.js et d'une autre bibliothèque d'exemple, qu'ils référenceront le même fichier
|
||
|
three.module.js.
|
||
|
</p>
|
||
|
<pre class="prettyprint">import * as THREE from './someFolder/build/three.module.js';
|
||
|
import {OrbitControls} from './someFolder/addons/controls/OrbitControls.js';
|
||
|
</pre>
|
||
|
<p>Cela est valable aussi lors de l'utilisation d'un CDN. Assurez vous que vos chemins versThis includes when using a CDN. Be <code class="notranslate" translate="no">three.modules.js</code> terminent par
|
||
|
<code class="notranslate" translate="no">/build/three.modules.js</code>. Par exemple :</p>
|
||
|
<pre class="prettyprint">import * as THREE from 'https://unpkg.com/three@0.108.0/<b>build/three.module.js</b>';
|
||
|
import {OrbitControls} from 'https://unpkg.com/three@0.108.0/addons/controls/OrbitControls.js';
|
||
|
</pre>
|
||
|
</div>
|
||
|
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<script src="/manual/resources/prettify.js"></script>
|
||
|
<script src="/manual/resources/lesson.js"></script>
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
</body></html>
|