|
|
|
|
<!DOCTYPE html><html lang="fr"><head>
|
|
|
|
|
<meta charset="utf-8">
|
|
|
|
|
<title>Principes fondamentaux</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 fondamentaux">
|
|
|
|
|
<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="../resources/lesson.css">
|
|
|
|
|
<link rel="stylesheet" href="../resources/lang.css">
|
|
|
|
|
<script type="importmap">
|
|
|
|
|
{
|
|
|
|
|
"imports": {
|
|
|
|
|
"three": "../../build/three.module.js"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
</head>
|
|
|
|
|
<body>
|
|
|
|
|
<div class="container">
|
|
|
|
|
<div class="lesson-title">
|
|
|
|
|
<h1>Principes fondamentaux</h1>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="lesson">
|
|
|
|
|
<div class="lesson-main">
|
|
|
|
|
<p>Ceci est le premier article d'une série d'articles sur three.js.
|
|
|
|
|
<a href="https://threejs.org">Three.js</a> est une bibliothèque 3D qui essaie de rendre
|
|
|
|
|
aussi facile que possible l'affichage de contenu 3D sur une page web.</p>
|
|
|
|
|
<p>Three.js est souvent confondu avec WebGL car la plupart du temps,
|
|
|
|
|
mais pas toujours, three.js utilise WebGL pour dessiner en 3D.
|
|
|
|
|
<a href="https://webglfundamentals.org">WebGL est un système de très bas niveau qui ne dessine que des points, des lignes et des triangles</a>.
|
|
|
|
|
Pour faire quoi que ce soit d'utile avec WebGL, cela nécessite généralement beaucoup de
|
|
|
|
|
code et c'est là que three.js intervient. Il gère des choses
|
|
|
|
|
comme les scènes, les lumières, les ombres, les matériaux, les textures, les mathématiques 3D,
|
|
|
|
|
toutes choses que vous auriez à écrire vous-même si vous utilisiez WebGL directement.</p>
|
|
|
|
|
<p>Ces tutoriels supposent que vous connaissez déjà JavaScript et, pour la
|
|
|
|
|
plupart, ils utiliseront le style ES6. <a href="prerequisites.html">Voir ici pour une
|
|
|
|
|
liste concise des choses que vous êtes censé déjà connaître</a>.
|
|
|
|
|
La plupart des navigateurs qui supportent three.js sont mis à jour automatiquement, donc la plupart des utilisateurs
|
|
|
|
|
devraient pouvoir exécuter ce code. Si vous souhaitez faire fonctionner ce code
|
|
|
|
|
sur de très vieux navigateurs, penchez-vous sur un transpiler comme <a href="https://babeljs.io">Babel</a>.
|
|
|
|
|
Bien sûr, les utilisateurs qui exécutent de très vieux navigateurs ont probablement des machines
|
|
|
|
|
qui ne peuvent pas exécuter three.js.</p>
|
|
|
|
|
<p>Lors de l'apprentissage de la plupart des langages de programmation, la première chose que les gens
|
|
|
|
|
font est de faire afficher <code class="notranslate" translate="no">"Hello World!"</code> par l'ordinateur. Pour la 3D,
|
|
|
|
|
l'une des premières choses les plus courantes à faire est de créer un cube 3D.
|
|
|
|
|
Alors commençons par "Hello Cube !"</p>
|
|
|
|
|
<p>Avant de commencer, essayons de vous donner une idée de la structure
|
|
|
|
|
d'une application three.js. Une application three.js vous demande de créer un tas
|
|
|
|
|
d'objets et de les connecter ensemble. Voici un diagramme qui représente
|
|
|
|
|
une petite application three.js</p>
|
|
|
|
|
<div class="threejs_center"><img src="../resources/images/threejs-structure.svg" style="width: 768px;"></div>
|
|
|
|
|
|
|
|
|
|
<p>Points à noter concernant 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 rend (dessine) la partie
|
|
|
|
|
de la scène 3D qui se trouve à l'intérieur du <em>frustum</em> de la caméra en tant qu'image 2D sur un
|
|
|
|
|
canevas.</p>
|
|
|
|
|
</li>
|
|
|
|
|
<li><p>Il y a un <a href="scenegraph.html">graphe de scène (scenegraph)</a> qui est une structure arborescente,
|
|
|
|
|
composée de divers objets comme un objet <a href="/docs/#api/en/scenes/Scene"><code class="notranslate" translate="no">Scene</code></a>, plusieurs objets
|
|
|
|
|
<a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a>, des objets <a href="/docs/#api/en/lights/Light"><code class="notranslate" translate="no">Light</code></a>, <a href="/docs/#api/en/objects/Group"><code class="notranslate" translate="no">Group</code></a>, <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 du graphe de scène et contient des propriétés
|
|
|
|
|
comme la couleur de fond et le brouillard. Ces objets définissent une structure arborescente
|
|
|
|
|
hiérarchique parent/enfant et représentent 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 pourraient être les enfants de la voiture de sorte que déplacer et
|
|
|
|
|
orienter l'objet voiture déplace automatiquement les roues. Vous pouvez en savoir plus
|
|
|
|
|
à ce sujet dans <a href="scenegraph.html">l'article sur les graphes de scène</a>.</p>
|
|
|
|
|
<p>Notez dans le diagramme que la <a href="/docs/#api/en/cameras/Camera"><code class="notranslate" translate="no">Camera</code></a> est à moitié dedans et à moitié dehors du graphe de scène. Cela représente
|
|
|
|
|
qu'en three.js, contrairement aux autres objets, une <a href="/docs/#api/en/cameras/Camera"><code class="notranslate" translate="no">Camera</code></a> n'a pas besoin
|
|
|
|
|
d'être dans le graphe de scène pour fonctionner. Tout comme les autres objets, une <a href="/docs/#api/en/cameras/Camera"><code class="notranslate" translate="no">Camera</code></a>, en tant
|
|
|
|
|
qu'enfant d'un autre objet, se déplacera et s'orientera par rapport à son objet parent.
|
|
|
|
|
Il y a un exemple de mise en place de plusieurs objets <a href="/docs/#api/en/cameras/Camera"><code class="notranslate" translate="no">Camera</code></a> dans un graphe de scène à
|
|
|
|
|
la fin de <a href="scenegraph.html">l'article sur les graphes de scène</a>.</p>
|
|
|
|
|
</li>
|
|
|
|
|
<li><p>Les objets <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a> représentent le dessin d'une <code class="notranslate" translate="no">Geometry</code> spécifique avec un
|
|
|
|
|
<a href="/docs/#api/en/materials/Material"><code class="notranslate" translate="no">Material</code></a> spécifique.</p>
|
|
|
|
|
<p>Les objets <a href="/docs/#api/en/materials/Material"><code class="notranslate" translate="no">Material</code></a> et les objets <code class="notranslate" translate="no">Geometry</code> peuvent être utilisés par
|
|
|
|
|
plusieurs objets <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a>. Par exemple, pour dessiner deux cubes bleus à différents
|
|
|
|
|
endroits, nous aurions besoin de deux objets <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a> pour représenter la position et
|
|
|
|
|
l'orientation de chaque cube. Nous n'aurions besoin que d'une seule <code class="notranslate" translate="no">Geometry</code> pour stocker les
|
|
|
|
|
données de sommet d'un cube et nous n'aurions besoin que d'un seul <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> pourraient référencer le même objet <code class="notranslate" translate="no">Geometry</code> et le
|
|
|
|
|
même objet <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 de sommet d'une pièce de géométrie
|
|
|
|
|
comme une sphère, un cube, un plan, un chien, un chat, un humain, un arbre, un bâtiment, etc...
|
|
|
|
|
Three.js fournit de nombreux types de
|
|
|
|
|
<a href="primitives.html">primitives de géométrie intégrées</a>. Vous pouvez également
|
|
|
|
|
<a href="custom-buffergeometry.html">créer une géométrie personnalisée</a> ainsi que
|
|
|
|
|
<a href="load-obj.html">charger de la géométrie à partir de fichiers</a>.</p>
|
|
|
|
|
</li>
|
|
|
|
|
<li><p>Les objets <a href="/docs/#api/en/materials/Material"><code class="notranslate" translate="no">Material</code></a> représentent
|
|
|
|
|
<a href="materials.html">les propriétés de surface utilisées pour dessiner la géométrie</a>
|
|
|
|
|
y compris des choses comme la couleur à utiliser et à quel point elle est brillante. Un <a href="/docs/#api/en/materials/Material"><code class="notranslate" translate="no">Material</code></a> peut
|
|
|
|
|
également référencer un ou plusieurs objets <a href="/docs/#api/en/textures/Texture"><code class="notranslate" translate="no">Texture</code></a> qui peuvent être utilisés, par exemple,
|
|
|
|
|
pour envelopper 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 à partir de fichiers image</a>,
|
|
|
|
|
<a href="canvas-textures.html">générées à partir d'un canevas</a>, soit <a href="rendertargets.html">rendues à partir 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érents types de lumières</a>.</p>
|
|
|
|
|
</li>
|
|
|
|
|
</ul>
|
|
|
|
|
<p>Étant donné tout cela, nous allons créer la configuration *« Hello Cube »* la plus simple
|
|
|
|
|
qui ressemble à ceci</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 de mettre <code class="notranslate" translate="no">type="module"</code> dans la balise script. Cela nous permet
|
|
|
|
|
d'utiliser le mot-clé <code class="notranslate" translate="no">import</code> pour charger three.js. À partir de r147, c'est la
|
|
|
|
|
seule façon de charger properly three.js. Les modules ont l'avantage de pouvoir facilement
|
|
|
|
|
importer d'autres modules dont ils ont besoin. Cela nous évite d'avoir à
|
|
|
|
|
charger manuellement les scripts supplémentaires dont ils dépendent.</p>
|
|
|
|
|
<p>Ensuite, nous avons besoin d'une balise <code class="notranslate" translate="no"><canvas></code>, donc...</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, nous devons donc le rechercher.</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({antialias: true, canvas});
|
|
|
|
|
+ ...
|
|
|
|
|
</script>
|
|
|
|
|
</pre>
|
|
|
|
|
<p>Après avoir trouvé le canevas, nous créons un <a href="/docs/#api/en/renderers/WebGLRenderer"><code class="notranslate" translate="no">WebGLRenderer</code></a>. Le renderer
|
|
|
|
|
est la chose responsable de prendre toutes les données que vous fournissez
|
|
|
|
|
et de les rendre sur le canevas.</p>
|
|
|
|
|
<p>Notez qu'il y a quelques détails ésotériques ici. Si vous ne passez pas de canevas
|
|
|
|
|
à three.js, il en créera un pour vous, mais vous devrez ensuite l'ajouter
|
|
|
|
|
à votre document. L'endroit où l'ajouter peut changer en fonction de votre cas d'utilisation
|
|
|
|
|
et vous devrez changer votre code. Je trouve que passer un canevas
|
|
|
|
|
à three.js est un peu plus flexible. Je peux placer le canevas n'importe où
|
|
|
|
|
et le code le trouvera, alors que si j'avais du code pour insérer le canevas
|
|
|
|
|
dans le document, je devrais probablement changer ce code si mon cas d'utilisation changeait.</p>
|
|
|
|
|
<p>Ensuite, nous avons besoin d'une caméra. Nous allons créer 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; // the canvas default
|
|
|
|
|
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 l'abréviation de <code class="notranslate" translate="no">field of view</code> (champ de vision). Dans ce cas, 75 degrés dans la dimension verticale.
|
|
|
|
|
Notez que la plupart des angles en three.js sont en radians, mais pour une raison quelconque, la caméra perspective prend des degrés.</p>
|
|
|
|
|
<p><code class="notranslate" translate="no">aspect</code> est le rapport d'aspect (display aspect) du canevas. Nous aborderons les détails
|
|
|
|
|
<a href="responsive.html">dans un autre article</a> mais par défaut, un canevas est
|
|
|
|
|
de 300x150 pixels, ce qui donne un rapport d'aspect de 300/150, soit 2.</p>
|
|
|
|
|
<p><code class="notranslate" translate="no">near</code> et <code class="notranslate" translate="no">far</code> représentent l'espace devant la caméra
|
|
|
|
|
qui sera rendu. Tout ce qui se trouve avant cette plage ou après cette plage
|
|
|
|
|
sera écrêté (non dessiné).</p>
|
|
|
|
|
<p>Ces quatre paramètres définissent un *« frustum »*.</p>
|
|
|
|
|
<p>Un *frustum* est le nom d'une forme 3D qui ressemble à une pyramide dont la pointe est tranchée.</p>
|
|
|
|
|
<p>En d'autres termes, considérez le mot "frustum" comme une autre forme 3D comme une sphère,
|
|
|
|
|
un cube, un prisme, un frustum.</p>
|
|
|
|
|
<p><img src="../resources/frustum-3d.svg" width="500" class="threejs_center"></p>
|
|
|
|
|
<p>La hauteur des plans near et far est déterminée par le champ de vision.
|
|
|
|
|
La largeur des deux plans est déterminée par le champ de vision et l'aspect.</p>
|
|
|
|
|
<p>Tout ce qui se trouve à l'intérieur du frustum défini sera dessiné. Tout ce qui se trouve à l'extérieur
|
|
|
|
|
ne le sera pas.</p>
|
|
|
|
|
<p>La caméra est orientée par défaut vers l'axe -Z avec +Y vers le haut. Nous allons placer notre cube
|
|
|
|
|
à l'origine, nous devons donc reculer légèrement la caméra par rapport à l'origine
|
|
|
|
|
afin de voir quelque chose.</p>
|
|
|
|
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">camera.position.z = 2;
|
|
|
|
|
</pre>
|
|
|
|
|
<p>Voici ce que nous visons.</p>
|
|
|
|
|
<p><img src="../resources/scene-down.svg" width="500" class="threejs_center"></p>
|
|
|
|
|
<p>Dans le diagramme ci-dessus, nous pouvons voir que notre caméra est à <code class="notranslate" translate="no">z = 2</code>. Elle regarde
|
|
|
|
|
vers l'axe -Z. Notre frustum commence à 0.1 unité de l'avant de la caméra
|
|
|
|
|
et va jusqu'à 5 unités devant la caméra. Parce que dans ce diagramme nous regardons vers le bas,
|
|
|
|
|
le champ de vision est affecté par l'aspect. Notre canevas est deux fois plus large
|
|
|
|
|
qu'il n'est haut, donc sur la largeur du canevas, le champ de vision sera beaucoup plus large que
|
|
|
|
|
nos 75 degrés spécifiés, qui correspondent au champ de vision vertical.</p>
|
|
|
|
|
<p>Ensuite, nous créons une <a href="/docs/#api/en/scenes/Scene"><code class="notranslate" translate="no">Scene</code></a>. Une <a href="/docs/#api/en/scenes/Scene"><code class="notranslate" translate="no">Scene</code></a> dans three.js est la racine d'une forme de graphe de scène.
|
|
|
|
|
Tout ce que vous voulez que three.js dessine doit être ajouté à la scène. Nous allons
|
|
|
|
|
couvrir plus de détails sur <a href="scenegraph.html">le fonctionnement des scènes dans un futur article</a>.</p>
|
|
|
|
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const scene = new THREE.Scene();
|
|
|
|
|
</pre>
|
|
|
|
|
<p>Ensuite, nous créons une <a href="/docs/#api/en/geometries/BoxGeometry"><code class="notranslate" translate="no">BoxGeometry</code></a> qui contient les données pour une boîte.
|
|
|
|
|
Presque tout ce que nous voulons afficher dans Three.js nécessite une géométrie qui définit
|
|
|
|
|
les sommets qui composent notre objet 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>Nous créons ensuite un matériau de base et définissons sa couleur. Les couleurs peuvent
|
|
|
|
|
être spécifiées en utilisant les valeurs hexadécimales à 6 chiffres de style CSS standard.</p>
|
|
|
|
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const material = new THREE.MeshBasicMaterial({color: 0x44aa88});
|
|
|
|
|
</pre>
|
|
|
|
|
<p>Nous créons ensuite un <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a>. Un <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a> en three.js représente la combinaison
|
|
|
|
|
de trois choses</p>
|
|
|
|
|
<ol>
|
|
|
|
|
<li>Une <code class="notranslate" translate="no">Geometry</code> (la forme de l'objet)</li>
|
|
|
|
|
<li>Un <a href="/docs/#api/en/materials/Material"><code class="notranslate" translate="no">Material</code></a> (comment dessiner l'objet, brillant ou plat, quelle couleur, quelle(s) texture(s) appliquer. Etc.)</li>
|
|
|
|
|
<li>La position, l'orientation et l'échelle de cet objet dans la scène par rapport à son parent. Dans le code ci-dessous, ce parent est la scène.</li>
|
|
|
|
|
</ol>
|
|
|
|
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const cube = new THREE.Mesh(geometry, material);
|
|
|
|
|
</pre>
|
|
|
|
|
<p>Et enfin, nous ajoutons ce maillage à la scène</p>
|
|
|
|
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">scene.add(cube);
|
|
|
|
|
</pre>
|
|
|
|
|
<p>Nous pouvons ensuite rendre la scène en appelant la fonction de rendu du renderer
|
|
|
|
|
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">cliquez ici pour ouvrir dans une fenêtre séparée</a>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<p></p>
|
|
|
|
|
<p>Il est un peu difficile de voir qu'il s'agit d'un cube 3D puisque nous le visualisons
|
|
|
|
|
directement le long de l'axe -Z et que le cube lui-même est aligné sur les axes,
|
|
|
|
|
donc nous ne voyons qu'une seule face.</p>
|
|
|
|
|
<p>Animons-le en rotation et, espérons-le, cela montrera
|
|
|
|
|
clairement qu'il est dessiné en 3D. Pour l'animer, nous allons le rendre 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; // convert time to seconds
|
|
|
|
|
|
|
|
|
|
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 au navigateur indiquant que vous souhaitez animer quelque chose.
|
|
|
|
|
Vous lui passez une fonction à appeler. Dans notre cas, cette fonction est <code class="notranslate" translate="no">render</code>. Le navigateur
|
|
|
|
|
appellera votre fonction et si vous mettez à jour quoi que ce soit lié à l'affichage de la
|
|
|
|
|
page, le navigateur re-rendrera la page. Dans notre cas, nous appelons la fonction
|
|
|
|
|
<code class="notranslate" translate="no">renderer.render</code> de three, qui dessinera notre scène.</p>
|
|
|
|
|
<p><code class="notranslate" translate="no">requestAnimationFrame</code> passe le temps écoulé depuis le chargement de la page
|
|
|
|
|
à notre fonction. Ce temps est exprimé en millisecondes. Je trouve beaucoup
|
|
|
|
|
plus facile de travailler avec des secondes, donc ici nous convertissons cela en secondes.</p>
|
|
|
|
|
<p>Nous définissons ensuite les rotations X et Y du cube à l'heure actuelle. Ces rotations
|
|
|
|
|
sont en <a href="https://en.wikipedia.org/wiki/Radian">radians</a>. Il y a 2 pi radians
|
|
|
|
|
dans un cercle, donc notre cube devrait faire un tour sur chaque axe en environ 6,28
|
|
|
|
|
secondes.</p>
|
|
|
|
|
<p>Nous rendons ensuite la scène et demandons une autre frame d'animation pour continuer
|
|
|
|
|
notre boucle.</p>
|
|
|
|
|
<p>En dehors de la boucle, nous appelons <code class="notranslate" translate="no">requestAnimationFrame</code> une seule fois pour démarrer 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">cliquez 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 voir le 3D. Ce qui aiderait,
|
|
|
|
|
c'est d'ajouter un peu d'éclairage, alors ajoutons une lumière. Il existe de nombreux types de lumières dans
|
|
|
|
|
three.js que nous aborderons dans <a href="lights.html">un futur article</a>. Pour l'instant, créons une lumière directionnelle.</p>
|
|
|
|
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const color = 0xFFFFFF;
|
|
|
|
|
const intensity = 3;
|
|
|
|
|
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 à 0, 0, 0. Dans notre
|
|
|
|
|
cas, nous définissons la position de la lumière à -1, 2, 4, de sorte qu'elle est légèrement sur la gauche,
|
|
|
|
|
au-dessus et derrière notre caméra. La cible est toujours 0, 0, 0, elle brillera donc
|
|
|
|
|
vers l'origine.</p>
|
|
|
|
|
<p>Nous devons également changer le matériau. Le <a href="/docs/#api/en/materials/MeshBasicMaterial"><code class="notranslate" translate="no">MeshBasicMaterial</code></a> n'est pas affecté par
|
|
|
|
|
les lumières. Changeons-le pour un <a href="/docs/#api/en/materials/MeshPhongMaterial"><code class="notranslate" translate="no">MeshPhongMaterial</code></a> qui est affecté par les lumières.</p>
|
|
|
|
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">-const material = new THREE.MeshBasicMaterial({color: 0x44aa88}); // greenish blue
|
|
|
|
|
+const material = new THREE.MeshPhongMaterial({color: 0x44aa88}); // greenish blue
|
|
|
|
|
</pre>
|
|
|
|
|
<p>Voici la structure de notre nouveau programme</p>
|
|
|
|
|
<div class="threejs_center"><img src="../resources/images/threejs-1cube-with-directionallight.svg" style="width: 500px;"></div>
|
|
|
|
|
|
|
|
|
|
<p>Et le voici en 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">cliquez ici pour ouvrir dans une fenêtre séparée</a>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<p></p>
|
|
|
|
|
<p>Maintenant, il devrait être assez clairement en 3D.</p>
|
|
|
|
|
<p>Juste pour le plaisir, ajoutons 2 cubes de plus.</p>
|
|
|
|
|
<p>Nous utiliserons la même géométrie pour chaque cube mais créerons un matériau différent
|
|
|
|
|
afin que chaque cube puisse avoir une couleur différente.</p>
|
|
|
|
|
<p>Tout d'abord, nous allons créer une fonction qui crée un nouveau matériau
|
|
|
|
|
avec la couleur spécifiée. Ensuite, elle crée un maillage en utilisant
|
|
|
|
|
la géométrie spécifiée et l'ajoute à la scène et
|
|
|
|
|
définit 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'appellerons 3 fois avec 3 couleurs et positions X différentes
|
|
|
|
|
en stockant les instances <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 allons faire tourner les 3 cubes dans notre fonction de rendu. Nous
|
|
|
|
|
calculons une rotation légèrement différente pour chacun.</p>
|
|
|
|
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function render(time) {
|
|
|
|
|
time *= 0.001; // convert time to seconds
|
|
|
|
|
|
|
|
|
|
cubes.forEach((cube, ndx) => {
|
|
|
|
|
const speed = 1 + ndx * .1;
|
|
|
|
|
const rot = time * speed;
|
|
|
|
|
cube.rotation.x = rot;
|
|
|
|
|
cube.rotation.y = rot;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
...
|
|
|
|
|
</pre>
|
|
|
|
|
<p>et voici 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">cliquez ici pour ouvrir dans une fenêtre séparée</a>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<p></p>
|
|
|
|
|
<p>Si vous le comparez au diagramme vu de dessus ci-dessus, vous pouvez voir
|
|
|
|
|
qu'il correspond à nos attentes.</p>
|
|
|
|
|
<p>Avec les cubes à X = -2 et X = +2, ils sont partiellement en dehors de notre frustum.</p>
|
|
|
|
|
<p>Ils sont également quelque peu exagérément déformés car le champ de vision
|
|
|
|
|
à travers le canevas est si extrême.</p>
|
|
|
|
|
<p>Notre programme a maintenant cette structure</p>
|
|
|
|
|
<div class="threejs_center"><img src="../resources/images/threejs-3cubes-scene.svg" style="width: 610px;"></div>
|
|
|
|
|
|
|
|
|
|
<p>Comme vous pouvez le voir, nous avons 3 objets <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 un <a href="/docs/#api/en/materials/MeshPhongMaterial"><code class="notranslate" translate="no">MeshPhongMaterial</code></a> unique afin que chaque cube puisse avoir
|
|
|
|
|
une couleur différente.</p>
|
|
|
|
|
<p>J'espère que cette courte introduction vous aidera à démarrer. <a href="responsive.html">Ensuite, nous verrons
|
|
|
|
|
comment rendre notre code réactif afin qu'il soit adaptable à plusieurs situations</a>.</p>
|
|
|
|
|
<div id="es6" class="threejs_bottombar">
|
|
|
|
|
<h3>modules es6, three.js et structure de dossiers</h3>
|
|
|
|
|
<p>À partir de la version r147, la manière préférée d'utiliser three.js est via les <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import">modules es6</a> et les cartes d'importation (import maps).</p>
|
|
|
|
|
<p>
|
|
|
|
|
Les modules es6 peuvent être chargés via le mot-clé <code class="notranslate" translate="no">import</code> dans un script
|
|
|
|
|
ou en ligne via une balise <code class="notranslate" translate="no"><script type="module"></code>. Voici un exemple
|
|
|
|
|
</p>
|
|
|
|
|
<pre class="prettyprint showlinemods notranslate lang-html" translate="no"><script type="module">
|
|
|
|
|
import * as THREE from 'three';
|
|
|
|
|
|
|
|
|
|
...
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
</pre>
|
|
|
|
|
<p>
|
|
|
|
|
Notez le spécificateur <code class="notranslate" translate="no">'three'</code> ici. Si vous le laissez tel quel, il produira probablement une erreur. Une *carte d'importation* doit être utilisée pour indiquer au navigateur où trouver three.js
|
|
|
|
|
</p>
|
|
|
|
|
<pre class="prettyprint showlinemods notranslate lang-html" translate="no"><script type="importmap">
|
|
|
|
|
{
|
|
|
|
|
"imports": {
|
|
|
|
|
"three": "./path/to/three.module.js"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
</pre>
|
|
|
|
|
<p>
|
|
|
|
|
Notez que le spécificateur de chemin ne peut commencer qu'avec <code class="notranslate" translate="no">./</code> ou <code class="notranslate" translate="no">../</code>.
|
|
|
|
|
</p>
|
|
|
|
|
<p>
|
|
|
|
|
Pour importer des extensions (addons) comme <a href="https://github.com/mrdoob/three.js/blob/master/examples/jsm/controls/OrbitControls.js"><code class="notranslate" translate="no">OrbitControls.js</code></a>, utilisez ce qui suit
|
|
|
|
|
</p>
|
|
|
|
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
|
|
|
|
|
</pre>
|
|
|
|
|
<p>
|
|
|
|
|
N'oubliez pas d'ajouter les extensions (addons) à la carte d'importation comme ceci
|
|
|
|
|
</p>
|
|
|
|
|
<pre class="prettyprint showlinemods notranslate lang-html" translate="no"><script type="importmap">
|
|
|
|
|
{
|
|
|
|
|
"imports": {
|
|
|
|
|
"three": "./path/to/three.module.js",
|
|
|
|
|
"three/addons/": "./different/path/to/examples/jsm/"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
</pre>
|
|
|
|
|
<p>
|
|
|
|
|
Vous pouvez également utiliser un CDN
|
|
|
|
|
</p>
|
|
|
|
|
<pre class="prettyprint showlinemods notranslate lang-html" translate="no"><script type="importmap">
|
|
|
|
|
{
|
|
|
|
|
"imports": {
|
|
|
|
|
"three": "https://cdn.jsdelivr.net/npm/three@<version>/build/three.module.js",
|
|
|
|
|
"three/addons/": "https://cdn.jsdelivr.net/npm/three@<version>/examples/jsm/"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
</pre>
|
|
|
|
|
<p>
|
|
|
|
|
En conclusion, la manière recommandée d'utiliser three.js est
|
|
|
|
|
</p>
|
|
|
|
|
<pre class="prettyprint showlinemods notranslate lang-html" translate="no">
|
|
|
|
|
<script type="importmap">
|
|
|
|
|
{
|
|
|
|
|
"imports": {
|
|
|
|
|
"three": "./path/to/three.module.js",
|
|
|
|
|
"three/addons/": "./different/path/to/examples/jsm/"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<script type="module">
|
|
|
|
|
import * as THREE from 'three';
|
|
|
|
|
import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
|
|
|
|
|
|
|
|
|
|
...
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
</pre>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- needed in English only to prevent warning from outdated translations -->
|
|
|
|
|
<p><a href="geometry.html"></a>
|
|
|
|
|
<a href="Geometry"></a></p>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<script src="../resources/prettify.js"></script>
|
|
|
|
|
<script src="../resources/lesson.js"></script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</body></html>
|