Browse Source

Integrate the threejsfundamentals articles into three's repo

Notes:

* organization

  ```
  manual
   +-en
   | +-article1.html
   | +-article2.html
   | +-...etc...
   +-ja
   | +-article1.html
   | +-article2.html
   | +-...etc...
   +-...
   +-3rdparty
   | +-monaco-editor
   +-resources (images etc for the articles)
   +-examples (the html files for each working example)
     +-example1.html
     +-example2.html
     +-resources (the image etc for examples)
  ```

* the articles use a special version of `prettify.js` in `manual/resources/prettify.js`

  This version of prettify checks the first character of each line where '+' = line added,
  '-' line deleted, '*' line changed. I bring this up just if you want to use some other
  colorizer for code it will need to handle that.

* manual/3rdparty/monaco-editor is the text editor used for live editing
  It's large and maybe you'd like to serve it from CDN?

* the live editor export and three versions

  The live editor has an export button to jsfiddle/codepen/codesandbox/stackoverflow.
  On threejsfundamenals.org all samples were pegs to a specific version and
  [all versions stayed available](https://github.com/gfxfundamentals/threejsfundamentals/tree/master/threejs/resources/threejs).
.
  This way if a user exports an example it keeps working because it
  links to the version that worked at the time of export.

  In this version the examples all reference `build/three.module.js` and when exported
  those links are converted to skypack.dev links at the current version. The current version
  is determined by fetching `https://raw.githubusercontent.com/mrdoob/three.js/master/package.json`.
  If there is a better way to get the version you can update `/manual/examples/resources/editor-settings.js`.
  Like, if you want exports to link to `https://threejs.org/build/three.modules.js` then just edit
  `/manual/examples/resources/editor-settings.js` and make `fixJSForCodeSite` just return its input.
  (eg: `function fixJSForCodeSite(url) { return url; }`).
  When exported they reference `https://threejs.org/build/three.module.js` whichs means
  when three updates their exported stuff will break.

* Path hacks

  The examples contain valid non qualified links. For example `import * as THREE from '../../build/three.module.js'`.
  In order to actually run the samples in the editor without a server side component the samples are loaded via fetch
  and the inserted into a blob. No URLs are relative to blobs so the URLs need to converted to fully qualified.
  In other words,  `import * as THREE from '../../build/three.module.js'` needs to become
  `import * as THREE from 'https://threejs.org/build/three.module.js'`.

  The process to do this is a bunch of hacky regular expressions in `/manual/examples/resources/editor-settings.js`
  in `fixSourceLinks`. The "proper" way would require a full HTML parser and JavaScript parser which is way too much
  code but, using regular experssions is brittle.

  If you look at the expressions you can see it's searching for things like `<script src="??">`, `<img src="???">`,
  `import bla '???'` and for three.js it's also searching for `loader.load` in various forms.

  The point is, if you add a new sample you need to write it in a way that these expression will find your non qualified links
  and fix them for you or add new expression. For things like `loader.load('some/unqualified/path')` it works but if
  it's `loader.load(someVariable)` then it won't work.

  The solution I chose you can put `/* threejs.org: url */` at the end of a line. This expression looks for the last quoted string
  on the line and assumes it's a link. Example

  ```
  const images = [
    { name: 'dog', path: 'some/unqualified/path/husky.jpg', }  /* threejs.org: url */
    { name: 'cat', path: 'some/unqualified/path/siamese.jpg', }  /* threejs.org: url */
    { name: 'bat', path: 'some/unqualified/path/vampire.jpg', }  /* threejs.org: url */
  ];
  for (const {name, path} of images) {
    loader.load(path);
    ...
  ```

  Now the script will convert these paths when loading them into the editor. The comment will be stripped so the user's
  does not see it in the editor.

* Known Article Issues

  * optimize-lots-of-objects-animated was broken by r134.

    The point of the article was to show how to use morph targets to animate a 1000 cubes like the webgl-globe
    and fix a long standing bug in the webgl-globe that it doesn't animate the colors of the cubes.
    It just uses colors of the first set of cubes values which means it shows the wrong represtation of everything
    but the first set.

    With the new way morph targets work it looks like it's very non trivial to add vertex color morph targets.
    If there is still an easy way to do it I'm happy to update the aritcle
    but as it is, you should probably just delete it.

  * align-html-elements-to-3d was written before I knew about `CSS2DRender`

    I've never had time to re-write it and I thought explaining the math might be useful. It's up to you
    whether or not you want to keep it.

  * all the samples use rAF directly

    I'm guessing you'd prefer `setAnimationLoop` at this point

  * all of the samples follow the advice of the `responsive.html` article

    This means they all assume the user used CSS to set the size of the canvas.
    They always pass `false` as the 3rd parameter to `Renderer.setSize`
Gregg Tavares 3 năm trước cách đây
mục cha
commit
6fd28e6b1e
100 tập tin đã thay đổi với 4046 bổ sung4012 xóa
  1. BIN
      manual/3rdparty/monaco-editor/min/vs/base/browser/ui/codiconLabel/codicon/codicon.ttf
  2. 85 0
      manual/3rdparty/monaco-editor/min/vs/base/worker/workerMain.js
  3. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/abap/abap.js
  4. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/apex/apex.js
  5. 7 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/azcli/azcli.js
  6. 7 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/bat/bat.js
  7. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/cameligo/cameligo.js
  8. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/clojure/clojure.js
  9. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/coffee/coffee.js
  10. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/cpp/cpp.js
  11. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/csharp/csharp.js
  12. 7 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/csp/csp.js
  13. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/css/css.js
  14. 7 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/dockerfile/dockerfile.js
  15. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/fsharp/fsharp.js
  16. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/go/go.js
  17. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/graphql/graphql.js
  18. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/handlebars/handlebars.js
  19. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/html/html.js
  20. 7 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/ini/ini.js
  21. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/java/java.js
  22. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/javascript/javascript.js
  23. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/kotlin/kotlin.js
  24. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/less/less.js
  25. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/lua/lua.js
  26. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/markdown/markdown.js
  27. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/mips/mips.js
  28. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/msdax/msdax.js
  29. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/mysql/mysql.js
  30. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/objective-c/objective-c.js
  31. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/pascal/pascal.js
  32. 7 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/pascaligo/pascaligo.js
  33. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/perl/perl.js
  34. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/pgsql/pgsql.js
  35. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/php/php.js
  36. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/postiats/postiats.js
  37. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/powerquery/powerquery.js
  38. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/powershell/powershell.js
  39. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/pug/pug.js
  40. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/python/python.js
  41. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/r/r.js
  42. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/razor/razor.js
  43. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/redis/redis.js
  44. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/redshift/redshift.js
  45. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/restructuredtext/restructuredtext.js
  46. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/ruby/ruby.js
  47. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/rust/rust.js
  48. 7 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/sb/sb.js
  49. 7 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/scheme/scheme.js
  50. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/scss/scss.js
  51. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/shell/shell.js
  52. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/solidity/solidity.js
  53. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/sophia/sophia.js
  54. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/sql/sql.js
  55. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/st/st.js
  56. 9 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/swift/swift.js
  57. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/tcl/tcl.js
  58. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/twig/twig.js
  59. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/typescript/typescript.js
  60. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/vb/vb.js
  61. 7 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/xml/xml.js
  62. 6 0
      manual/3rdparty/monaco-editor/min/vs/basic-languages/yaml/yaml.js
  63. 5 0
      manual/3rdparty/monaco-editor/min/vs/editor/editor.main.css
  64. 7 0
      manual/3rdparty/monaco-editor/min/vs/editor/editor.main.js
  65. 10 0
      manual/3rdparty/monaco-editor/min/vs/editor/editor.main.nls.de.js
  66. 10 0
      manual/3rdparty/monaco-editor/min/vs/editor/editor.main.nls.es.js
  67. 10 0
      manual/3rdparty/monaco-editor/min/vs/editor/editor.main.nls.fr.js
  68. 10 0
      manual/3rdparty/monaco-editor/min/vs/editor/editor.main.nls.it.js
  69. 9 0
      manual/3rdparty/monaco-editor/min/vs/editor/editor.main.nls.ja.js
  70. 10 0
      manual/3rdparty/monaco-editor/min/vs/editor/editor.main.nls.js
  71. 9 0
      manual/3rdparty/monaco-editor/min/vs/editor/editor.main.nls.ko.js
  72. 9 0
      manual/3rdparty/monaco-editor/min/vs/editor/editor.main.nls.ru.js
  73. 9 0
      manual/3rdparty/monaco-editor/min/vs/editor/editor.main.nls.zh-cn.js
  74. 9 0
      manual/3rdparty/monaco-editor/min/vs/editor/editor.main.nls.zh-tw.js
  75. 6 0
      manual/3rdparty/monaco-editor/min/vs/language/css/cssMode.js
  76. 6 0
      manual/3rdparty/monaco-editor/min/vs/language/css/cssWorker.js
  77. 6 0
      manual/3rdparty/monaco-editor/min/vs/language/html/htmlMode.js
  78. 6 0
      manual/3rdparty/monaco-editor/min/vs/language/html/htmlWorker.js
  79. 6 0
      manual/3rdparty/monaco-editor/min/vs/language/json/jsonMode.js
  80. 6 0
      manual/3rdparty/monaco-editor/min/vs/language/json/jsonWorker.js
  81. 6 0
      manual/3rdparty/monaco-editor/min/vs/language/typescript/tsMode.js
  82. 20 0
      manual/3rdparty/monaco-editor/min/vs/language/typescript/tsWorker.js
  83. 37 0
      manual/3rdparty/monaco-editor/min/vs/loader.js
  84. 1 0
      manual/3rdparty/split.min.js
  85. 274 342
      manual/en/align-html-elements-to-3d.html
  86. 140 132
      manual/en/backgrounds.html
  87. 143 157
      manual/en/billboards.html
  88. 251 308
      manual/en/cameras.html
  89. 151 156
      manual/en/canvas-textures.html
  90. 147 178
      manual/en/cleanup.html
  91. 146 153
      manual/en/custom-buffergeometry.html
  92. 215 248
      manual/en/custom-geometry.html
  93. 86 85
      manual/en/debugging-glsl.html
  94. 308 394
      manual/en/debugging-javascript.html
  95. 122 123
      manual/en/fog.html
  96. 280 336
      manual/en/fundamentals.html
  97. 290 389
      manual/en/game.html
  98. 261 300
      manual/en/indexed-textures.html
  99. 280 353
      manual/en/lights.html
  100. 288 358
      manual/en/load-gltf.html

BIN
manual/3rdparty/monaco-editor/min/vs/base/browser/ui/codiconLabel/codicon/codicon.ttf


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 85 - 0
manual/3rdparty/monaco-editor/min/vs/base/worker/workerMain.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/abap/abap.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/apex/apex.js


+ 7 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/azcli/azcli.js

@@ -0,0 +1,7 @@
+/*!-----------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * monaco-languages version: 1.10.0(1b4729c63bdb0d1e06d4e637e5c3977ddeb714dd)
+ * Released under the MIT license
+ * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md
+ *-----------------------------------------------------------------------------*/
+define("vs/basic-languages/azcli/azcli",["require","exports"],(function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.conf={comments:{lineComment:"#"}},t.language={defaultToken:"keyword",ignoreCase:!0,tokenPostfix:".azcli",str:/[^#\s]/,tokenizer:{root:[{include:"@comment"},[/\s-+@str*\s*/,{cases:{"@eos":{token:"key.identifier",next:"@popall"},"@default":{token:"key.identifier",next:"@type"}}}],[/^-+@str*\s*/,{cases:{"@eos":{token:"key.identifier",next:"@popall"},"@default":{token:"key.identifier",next:"@type"}}}]],type:[{include:"@comment"},[/-+@str*\s*/,{cases:{"@eos":{token:"key.identifier",next:"@popall"},"@default":"key.identifier"}}],[/@str+\s*/,{cases:{"@eos":{token:"string",next:"@popall"},"@default":"string"}}]],comment:[[/#.*$/,{cases:{"@eos":{token:"comment",next:"@popall"}}}]]}}}));

+ 7 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/bat/bat.js

@@ -0,0 +1,7 @@
+/*!-----------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * monaco-languages version: 1.10.0(1b4729c63bdb0d1e06d4e637e5c3977ddeb714dd)
+ * Released under the MIT license
+ * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md
+ *-----------------------------------------------------------------------------*/
+define("vs/basic-languages/bat/bat",["require","exports"],(function(e,s){"use strict";Object.defineProperty(s,"__esModule",{value:!0}),s.conf={comments:{lineComment:"REM"},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'}],surroundingPairs:[{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'}],folding:{markers:{start:new RegExp("^\\s*(::\\s*|REM\\s+)#region"),end:new RegExp("^\\s*(::\\s*|REM\\s+)#endregion")}}},s.language={defaultToken:"",ignoreCase:!0,tokenPostfix:".bat",brackets:[{token:"delimiter.bracket",open:"{",close:"}"},{token:"delimiter.parenthesis",open:"(",close:")"},{token:"delimiter.square",open:"[",close:"]"}],keywords:/call|defined|echo|errorlevel|exist|for|goto|if|pause|set|shift|start|title|not|pushd|popd/,symbols:/[=><!~?&|+\-*\/\^;\.,]+/,escapes:/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,tokenizer:{root:[[/^(\s*)(rem(?:\s.*|))$/,["","comment"]],[/(\@?)(@keywords)(?!\w)/,[{token:"keyword"},{token:"keyword.$2"}]],[/[ \t\r\n]+/,""],[/setlocal(?!\w)/,"keyword.tag-setlocal"],[/endlocal(?!\w)/,"keyword.tag-setlocal"],[/[a-zA-Z_]\w*/,""],[/:\w*/,"metatag"],[/%[^%]+%/,"variable"],[/%%[\w]+(?!\w)/,"variable"],[/[{}()\[\]]/,"@brackets"],[/@symbols/,"delimiter"],[/\d*\.\d+([eE][\-+]?\d+)?/,"number.float"],[/0[xX][0-9a-fA-F_]*[0-9a-fA-F]/,"number.hex"],[/\d+/,"number"],[/[;,.]/,"delimiter"],[/"/,"string",'@string."'],[/'/,"string","@string.'"]],string:[[/[^\\"'%]+/,{cases:{"@eos":{token:"string",next:"@popall"},"@default":"string"}}],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/%[\w ]+%/,"variable"],[/%%[\w]+(?!\w)/,"variable"],[/["']/,{cases:{"$#==$S2":{token:"string",next:"@pop"},"@default":"string"}}],[/$/,"string","@popall"]]}}}));

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/cameligo/cameligo.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/clojure/clojure.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/coffee/coffee.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/cpp/cpp.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/csharp/csharp.js


+ 7 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/csp/csp.js

@@ -0,0 +1,7 @@
+/*!-----------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * monaco-languages version: 1.10.0(1b4729c63bdb0d1e06d4e637e5c3977ddeb714dd)
+ * Released under the MIT license
+ * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md
+ *-----------------------------------------------------------------------------*/
+define("vs/basic-languages/csp/csp",["require","exports"],(function(t,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.conf={brackets:[],autoClosingPairs:[],surroundingPairs:[]},e.language={keywords:[],typeKeywords:[],tokenPostfix:".csp",operators:[],symbols:/[=><!~?:&|+\-*\/\^%]+/,escapes:/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,tokenizer:{root:[[/child-src/,"string.quote"],[/connect-src/,"string.quote"],[/default-src/,"string.quote"],[/font-src/,"string.quote"],[/frame-src/,"string.quote"],[/img-src/,"string.quote"],[/manifest-src/,"string.quote"],[/media-src/,"string.quote"],[/object-src/,"string.quote"],[/script-src/,"string.quote"],[/style-src/,"string.quote"],[/worker-src/,"string.quote"],[/base-uri/,"string.quote"],[/plugin-types/,"string.quote"],[/sandbox/,"string.quote"],[/disown-opener/,"string.quote"],[/form-action/,"string.quote"],[/frame-ancestors/,"string.quote"],[/report-uri/,"string.quote"],[/report-to/,"string.quote"],[/upgrade-insecure-requests/,"string.quote"],[/block-all-mixed-content/,"string.quote"],[/require-sri-for/,"string.quote"],[/reflected-xss/,"string.quote"],[/referrer/,"string.quote"],[/policy-uri/,"string.quote"],[/'self'/,"string.quote"],[/'unsafe-inline'/,"string.quote"],[/'unsafe-eval'/,"string.quote"],[/'strict-dynamic'/,"string.quote"],[/'unsafe-hashed-attributes'/,"string.quote"]]}}}));

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/css/css.js


+ 7 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/dockerfile/dockerfile.js

@@ -0,0 +1,7 @@
+/*!-----------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * monaco-languages version: 1.10.0(1b4729c63bdb0d1e06d4e637e5c3977ddeb714dd)
+ * Released under the MIT license
+ * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md
+ *-----------------------------------------------------------------------------*/
+define("vs/basic-languages/dockerfile/dockerfile",["require","exports"],(function(e,s){"use strict";Object.defineProperty(s,"__esModule",{value:!0}),s.conf={brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}]},s.language={defaultToken:"",tokenPostfix:".dockerfile",variable:/\${?[\w]+}?/,tokenizer:{root:[{include:"@whitespace"},{include:"@comment"},[/(ONBUILD)(\s+)/,["keyword",""]],[/(ENV)(\s+)([\w]+)/,["keyword","",{token:"variable",next:"@arguments"}]],[/(FROM|MAINTAINER|RUN|EXPOSE|ENV|ADD|ARG|VOLUME|LABEL|USER|WORKDIR|COPY|CMD|STOPSIGNAL|SHELL|HEALTHCHECK|ENTRYPOINT)/,{token:"keyword",next:"@arguments"}]],arguments:[{include:"@whitespace"},{include:"@strings"},[/(@variable)/,{cases:{"@eos":{token:"variable",next:"@popall"},"@default":"variable"}}],[/\\/,{cases:{"@eos":"","@default":""}}],[/./,{cases:{"@eos":{token:"",next:"@popall"},"@default":""}}]],whitespace:[[/\s+/,{cases:{"@eos":{token:"",next:"@popall"},"@default":""}}]],comment:[[/(^#.*$)/,"comment","@popall"]],strings:[[/'$/,"string","@popall"],[/'/,"string","@stringBody"],[/"$/,"string","@popall"],[/"/,"string","@dblStringBody"]],stringBody:[[/[^\\\$']/,{cases:{"@eos":{token:"string",next:"@popall"},"@default":"string"}}],[/\\./,"string.escape"],[/'$/,"string","@popall"],[/'/,"string","@pop"],[/(@variable)/,"variable"],[/\\$/,"string"],[/$/,"string","@popall"]],dblStringBody:[[/[^\\\$"]/,{cases:{"@eos":{token:"string",next:"@popall"},"@default":"string"}}],[/\\./,"string.escape"],[/"$/,"string","@popall"],[/"/,"string","@pop"],[/(@variable)/,"variable"],[/\\$/,"string"],[/$/,"string","@popall"]]}}}));

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/fsharp/fsharp.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/go/go.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/graphql/graphql.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/handlebars/handlebars.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/html/html.js


+ 7 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/ini/ini.js

@@ -0,0 +1,7 @@
+/*!-----------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * monaco-languages version: 1.10.0(1b4729c63bdb0d1e06d4e637e5c3977ddeb714dd)
+ * Released under the MIT license
+ * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md
+ *-----------------------------------------------------------------------------*/
+define("vs/basic-languages/ini/ini",["require","exports"],(function(e,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.conf={comments:{lineComment:"#"},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}]},n.language={defaultToken:"",tokenPostfix:".ini",escapes:/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,tokenizer:{root:[[/^\[[^\]]*\]/,"metatag"],[/(^\w+)(\s*)(\=)/,["key","","delimiter"]],{include:"@whitespace"},[/\d+/,"number"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/'([^'\\]|\\.)*$/,"string.invalid"],[/"/,"string",'@string."'],[/'/,"string","@string.'"]],whitespace:[[/[ \t\r\n]+/,""],[/^\s*[#;].*$/,"comment"]],string:[[/[^\\"']+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/["']/,{cases:{"$#==$S2":{token:"string",next:"@pop"},"@default":"string"}}]]}}}));

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/java/java.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/javascript/javascript.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/kotlin/kotlin.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/less/less.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/lua/lua.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/markdown/markdown.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/mips/mips.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/msdax/msdax.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/mysql/mysql.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/objective-c/objective-c.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/pascal/pascal.js


+ 7 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/pascaligo/pascaligo.js

@@ -0,0 +1,7 @@
+/*!-----------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * monaco-languages version: 1.10.0(1b4729c63bdb0d1e06d4e637e5c3977ddeb714dd)
+ * Released under the MIT license
+ * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md
+ *-----------------------------------------------------------------------------*/
+define("vs/basic-languages/pascaligo/pascaligo",["require","exports"],(function(e,o){"use strict";Object.defineProperty(o,"__esModule",{value:!0}),o.conf={comments:{lineComment:"//",blockComment:["(*","*)"]},brackets:[["{","}"],["[","]"],["(",")"],["<",">"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"<",close:">"},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"<",close:">"},{open:"'",close:"'"}]},o.language={defaultToken:"",tokenPostfix:".pascaligo",ignoreCase:!0,brackets:[{open:"{",close:"}",token:"delimiter.curly"},{open:"[",close:"]",token:"delimiter.square"},{open:"(",close:")",token:"delimiter.parenthesis"},{open:"<",close:">",token:"delimiter.angle"}],keywords:["begin","block","case","const","else","end","fail","for","from","function","if","is","nil","of","remove","return","skip","then","type","var","while","with","option","None","transaction"],typeKeywords:["bool","int","list","map","nat","record","string","unit","address","map","mtz","xtz"],operators:["=",">","<","<=",">=","<>",":",":=","and","mod","or","+","-","*","/","@","&","^","%"],symbols:/[=><:@\^&|+\-*\/\^%]+/,tokenizer:{root:[[/[a-zA-Z_][\w]*/,{cases:{"@keywords":{token:"keyword.$0"},"@default":"identifier"}}],{include:"@whitespace"},[/[{}()\[\]]/,"@brackets"],[/[<>](?!@symbols)/,"@brackets"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/\d*\.\d+([eE][\-+]?\d+)?/,"number.float"],[/\$[0-9a-fA-F]{1,16}/,"number.hex"],[/\d+/,"number"],[/[;,.]/,"delimiter"],[/'([^'\\]|\\.)*$/,"string.invalid"],[/'/,"string","@string"],[/'[^\\']'/,"string"],[/'/,"string.invalid"],[/\#\d+/,"string"]],comment:[[/[^\(\*]+/,"comment"],[/\*\)/,"comment","@pop"],[/\(\*/,"comment"]],string:[[/[^\\']+/,"string"],[/\\./,"string.escape.invalid"],[/'/,{token:"string.quote",bracket:"@close",next:"@pop"}]],whitespace:[[/[ \t\r\n]+/,"white"],[/\(\*/,"comment","@comment"],[/\/\/.*$/,"comment"]]}}}));

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/perl/perl.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/pgsql/pgsql.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/php/php.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/postiats/postiats.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/powerquery/powerquery.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/powershell/powershell.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/pug/pug.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/python/python.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/r/r.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/razor/razor.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/redis/redis.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/redshift/redshift.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/restructuredtext/restructuredtext.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/ruby/ruby.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/rust/rust.js


+ 7 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/sb/sb.js

@@ -0,0 +1,7 @@
+/*!-----------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * monaco-languages version: 1.10.0(1b4729c63bdb0d1e06d4e637e5c3977ddeb714dd)
+ * Released under the MIT license
+ * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md
+ *-----------------------------------------------------------------------------*/
+define("vs/basic-languages/sb/sb",["require","exports"],(function(e,o){"use strict";Object.defineProperty(o,"__esModule",{value:!0}),o.conf={comments:{lineComment:"'"},brackets:[["(",")"],["[","]"],["If","EndIf"],["While","EndWhile"],["For","EndFor"],["Sub","EndSub"]],autoClosingPairs:[{open:'"',close:'"',notIn:["string","comment"]},{open:"(",close:")",notIn:["string","comment"]},{open:"[",close:"]",notIn:["string","comment"]}]},o.language={defaultToken:"",tokenPostfix:".sb",ignoreCase:!0,brackets:[{token:"delimiter.array",open:"[",close:"]"},{token:"delimiter.parenthesis",open:"(",close:")"},{token:"keyword.tag-if",open:"If",close:"EndIf"},{token:"keyword.tag-while",open:"While",close:"EndWhile"},{token:"keyword.tag-for",open:"For",close:"EndFor"},{token:"keyword.tag-sub",open:"Sub",close:"EndSub"}],keywords:["Else","ElseIf","EndFor","EndIf","EndSub","EndWhile","For","Goto","If","Step","Sub","Then","To","While"],tagwords:["If","Sub","While","For"],operators:[">","<","<>","<=",">=","And","Or","+","-","*","/","="],identifier:/[a-zA-Z_][\w]*/,symbols:/[=><:+\-*\/%\.,]+/,escapes:/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,tokenizer:{root:[{include:"@whitespace"},[/(@identifier)(?=[.])/,"type"],[/@identifier/,{cases:{"@keywords":{token:"keyword.$0"},"@operators":"operator","@default":"variable.name"}}],[/([.])(@identifier)/,{cases:{$2:["delimiter","type.member"],"@default":""}}],[/\d*\.\d+/,"number.float"],[/\d+/,"number"],[/[()\[\]]/,"@brackets"],[/@symbols/,{cases:{"@operators":"operator","@default":"delimiter"}}],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"/,"string","@string"]],whitespace:[[/[ \t\r\n]+/,""],[/(\').*$/,"comment"]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"C?/,"string","@pop"]]}}}));

+ 7 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/scheme/scheme.js

@@ -0,0 +1,7 @@
+/*!-----------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * monaco-languages version: 1.10.0(1b4729c63bdb0d1e06d4e637e5c3977ddeb714dd)
+ * Released under the MIT license
+ * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md
+ *-----------------------------------------------------------------------------*/
+define("vs/basic-languages/scheme/scheme",["require","exports"],(function(e,o){"use strict";Object.defineProperty(o,"__esModule",{value:!0}),o.conf={comments:{lineComment:";",blockComment:["#|","|#"]},brackets:[["(",")"],["{","}"],["[","]"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'}]},o.language={defaultToken:"",ignoreCase:!0,tokenPostfix:".scheme",brackets:[{open:"(",close:")",token:"delimiter.parenthesis"},{open:"{",close:"}",token:"delimiter.curly"},{open:"[",close:"]",token:"delimiter.square"}],keywords:["case","do","let","loop","if","else","when","cons","car","cdr","cond","lambda","lambda*","syntax-rules","format","set!","quote","eval","append","list","list?","member?","load"],constants:["#t","#f"],operators:["eq?","eqv?","equal?","and","or","not","null?"],tokenizer:{root:[[/#[xXoObB][0-9a-fA-F]+/,"number.hex"],[/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?/,"number.float"],[/(?:\b(?:(define|define-syntax|define-macro))\b)(\s+)((?:\w|\-|\!|\?)*)/,["keyword","white","variable"]],{include:"@whitespace"},{include:"@strings"},[/[a-zA-Z_#][a-zA-Z0-9_\-\?\!\*]*/,{cases:{"@keywords":"keyword","@constants":"constant","@operators":"operators","@default":"identifier"}}]],comment:[[/[^\|#]+/,"comment"],[/#\|/,"comment","@push"],[/\|#/,"comment","@pop"],[/[\|#]/,"comment"]],whitespace:[[/[ \t\r\n]+/,"white"],[/#\|/,"comment","@comment"],[/;.*$/,"comment"]],strings:[[/"$/,"string","@popall"],[/"(?=.)/,"string","@multiLineString"]],multiLineString:[[/[^\\"]+$/,"string","@popall"],[/[^\\"]+/,"string"],[/\\./,"string.escape"],[/"/,"string","@popall"],[/\\$/,"string"]]}}}));

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/scss/scss.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/shell/shell.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/solidity/solidity.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/sophia/sophia.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/sql/sql.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/st/st.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 9 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/swift/swift.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/tcl/tcl.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/twig/twig.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/typescript/typescript.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/vb/vb.js


+ 7 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/xml/xml.js

@@ -0,0 +1,7 @@
+/*!-----------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * monaco-languages version: 1.10.0(1b4729c63bdb0d1e06d4e637e5c3977ddeb714dd)
+ * Released under the MIT license
+ * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md
+ *-----------------------------------------------------------------------------*/
+define("vs/basic-languages/xml/xml",["require","exports"],(function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.conf={comments:{blockComment:["\x3c!--","--\x3e"]},brackets:[["<",">"]],autoClosingPairs:[{open:"<",close:">"},{open:"'",close:"'"},{open:'"',close:'"'}],surroundingPairs:[{open:"<",close:">"},{open:"'",close:"'"},{open:'"',close:'"'}]},t.language={defaultToken:"",tokenPostfix:".xml",ignoreCase:!0,qualifiedName:/(?:[\w\.\-]+:)?[\w\.\-]+/,tokenizer:{root:[[/[^<&]+/,""],{include:"@whitespace"},[/(<)(@qualifiedName)/,[{token:"delimiter"},{token:"tag",next:"@tag"}]],[/(<\/)(@qualifiedName)(\s*)(>)/,[{token:"delimiter"},{token:"tag"},"",{token:"delimiter"}]],[/(<\?)(@qualifiedName)/,[{token:"delimiter"},{token:"metatag",next:"@tag"}]],[/(<\!)(@qualifiedName)/,[{token:"delimiter"},{token:"metatag",next:"@tag"}]],[/<\!\[CDATA\[/,{token:"delimiter.cdata",next:"@cdata"}],[/&\w+;/,"string.escape"]],cdata:[[/[^\]]+/,""],[/\]\]>/,{token:"delimiter.cdata",next:"@pop"}],[/\]/,""]],tag:[[/[ \t\r\n]+/,""],[/(@qualifiedName)(\s*=\s*)("[^"]*"|'[^']*')/,["attribute.name","","attribute.value"]],[/(@qualifiedName)(\s*=\s*)("[^">?\/]*|'[^'>?\/]*)(?=[\?\/]\>)/,["attribute.name","","attribute.value"]],[/(@qualifiedName)(\s*=\s*)("[^">]*|'[^'>]*)/,["attribute.name","","attribute.value"]],[/@qualifiedName/,"attribute.name"],[/\?>/,{token:"delimiter",next:"@pop"}],[/(\/)(>)/,[{token:"tag"},{token:"delimiter",next:"@pop"}]],[/>/,{token:"delimiter",next:"@pop"}]],whitespace:[[/[ \t\r\n]+/,""],[/<!--/,{token:"comment",next:"@comment"}]],comment:[[/[^<\-]+/,"comment.content"],[/-->/,{token:"comment",next:"@pop"}],[/<!--/,"comment.content.invalid"],[/[<\-]/,"comment.content"]]}}}));

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/basic-languages/yaml/yaml.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 5 - 0
manual/3rdparty/monaco-editor/min/vs/editor/editor.main.css


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 7 - 0
manual/3rdparty/monaco-editor/min/vs/editor/editor.main.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 10 - 0
manual/3rdparty/monaco-editor/min/vs/editor/editor.main.nls.de.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 10 - 0
manual/3rdparty/monaco-editor/min/vs/editor/editor.main.nls.es.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 10 - 0
manual/3rdparty/monaco-editor/min/vs/editor/editor.main.nls.fr.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 10 - 0
manual/3rdparty/monaco-editor/min/vs/editor/editor.main.nls.it.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 9 - 0
manual/3rdparty/monaco-editor/min/vs/editor/editor.main.nls.ja.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 10 - 0
manual/3rdparty/monaco-editor/min/vs/editor/editor.main.nls.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 9 - 0
manual/3rdparty/monaco-editor/min/vs/editor/editor.main.nls.ko.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 9 - 0
manual/3rdparty/monaco-editor/min/vs/editor/editor.main.nls.ru.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 9 - 0
manual/3rdparty/monaco-editor/min/vs/editor/editor.main.nls.zh-cn.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 9 - 0
manual/3rdparty/monaco-editor/min/vs/editor/editor.main.nls.zh-tw.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/language/css/cssMode.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/language/css/cssWorker.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/language/html/htmlMode.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/language/html/htmlWorker.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/language/json/jsonMode.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/language/json/jsonWorker.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 0
manual/3rdparty/monaco-editor/min/vs/language/typescript/tsMode.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 20 - 0
manual/3rdparty/monaco-editor/min/vs/language/typescript/tsWorker.js


+ 37 - 0
manual/3rdparty/monaco-editor/min/vs/loader.js

@@ -0,0 +1,37 @@
+/*!-----------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Version: 0.20.0(6363745c0a33c27b149b89342a7b96d354fb554c)
+ * Released under the MIT license
+ * https://github.com/Microsoft/vscode/blob/master/LICENSE.txt
+ *-----------------------------------------------------------*/
+"use strict";var define,AMDLoader,_amdLoaderGlobal=this,_commonjsGlobal="object"==typeof global?global:{};!function(e){e.global=_amdLoaderGlobal;var t=function(){function t(){this._detected=!1,this._isWindows=!1,this._isNode=!1,this._isElectronRenderer=!1,this._isWebWorker=!1}return Object.defineProperty(t.prototype,"isWindows",{get:function(){return this._detect(),this._isWindows},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isNode",{get:function(){return this._detect(),this._isNode},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isElectronRenderer",{get:function(){return this._detect(),this._isElectronRenderer},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isWebWorker",{get:function(){return this._detect(),this._isWebWorker},enumerable:!0,configurable:!0}),t.prototype._detect=function(){this._detected||(this._detected=!0,this._isWindows=t._isWindows(),this._isNode="undefined"!=typeof module&&!!module.exports,
+this._isElectronRenderer="undefined"!=typeof process&&void 0!==process.versions&&void 0!==process.versions.electron&&"renderer"===process.type,this._isWebWorker="function"==typeof e.global.importScripts)},t._isWindows=function(){return!!("undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.indexOf("Windows")>=0)||"undefined"!=typeof process&&"win32"===process.platform},t}();e.Environment=t}(AMDLoader||(AMDLoader={})),function(e){var t=function(e,t,r){this.type=e,this.detail=t,this.timestamp=r};e.LoaderEvent=t;var r=function(){function r(e){this._events=[new t(1,"",e)]}return r.prototype.record=function(r,n){this._events.push(new t(r,n,e.Utilities.getHighPerformanceTimestamp()))},r.prototype.getEvents=function(){return this._events},r}();e.LoaderEventRecorder=r;var n=function(){function e(){}return e.prototype.record=function(e,t){},e.prototype.getEvents=function(){return[]},e.INSTANCE=new e,e}();e.NullLoaderEventRecorder=n}(AMDLoader||(AMDLoader={})),function(e){var t=function(){
+function t(){}return t.fileUriToFilePath=function(e,t){if(t=decodeURI(t).replace(/%23/g,"#"),e){if(/^file:\/\/\//.test(t))return t.substr(8);if(/^file:\/\//.test(t))return t.substr(5)}else if(/^file:\/\//.test(t))return t.substr(7);return t},t.startsWith=function(e,t){return e.length>=t.length&&e.substr(0,t.length)===t},t.endsWith=function(e,t){return e.length>=t.length&&e.substr(e.length-t.length)===t},t.containsQueryString=function(e){return/^[^\#]*\?/gi.test(e)},t.isAbsolutePath=function(e){return/^((http:\/\/)|(https:\/\/)|(file:\/\/)|(\/))/.test(e)},t.forEachProperty=function(e,t){if(e){var r=void 0;for(r in e)e.hasOwnProperty(r)&&t(r,e[r])}},t.isEmpty=function(e){var r=!0;return t.forEachProperty(e,(function(){r=!1})),r},t.recursiveClone=function(e){if(!e||"object"!=typeof e)return e;var r=Array.isArray(e)?[]:{};return t.forEachProperty(e,(function(e,n){r[e]=n&&"object"==typeof n?t.recursiveClone(n):n})),r},t.generateAnonymousModule=function(){return"===anonymous"+t.NEXT_ANONYMOUS_ID+++"==="},
+t.isAnonymousModule=function(e){return t.startsWith(e,"===anonymous")},t.getHighPerformanceTimestamp=function(){return this.PERFORMANCE_NOW_PROBED||(this.PERFORMANCE_NOW_PROBED=!0,this.HAS_PERFORMANCE_NOW=e.global.performance&&"function"==typeof e.global.performance.now),this.HAS_PERFORMANCE_NOW?e.global.performance.now():Date.now()},t.NEXT_ANONYMOUS_ID=1,t.PERFORMANCE_NOW_PROBED=!1,t.HAS_PERFORMANCE_NOW=!1,t}();e.Utilities=t}(AMDLoader||(AMDLoader={})),function(e){function t(e){if(e instanceof Error)return e;var t=new Error(e.message||String(e)||"Unknown Error");return e.stack&&(t.stack=e.stack),t}e.ensureError=t;var r=function(){function r(){}return r.validateConfigurationOptions=function(r){if("string"!=typeof(r=r||{}).baseUrl&&(r.baseUrl=""),"boolean"!=typeof r.isBuild&&(r.isBuild=!1),"object"!=typeof r.paths&&(r.paths={}),"object"!=typeof r.config&&(r.config={}),void 0===r.catchError&&(r.catchError=!1),void 0===r.recordStats&&(r.recordStats=!1),"string"!=typeof r.urlArgs&&(r.urlArgs=""),
+"function"!=typeof r.onError&&(r.onError=function(e){return"loading"===e.phase?(console.error('Loading "'+e.moduleId+'" failed'),console.error(e),console.error("Here are the modules that depend on it:"),void console.error(e.neededBy)):"factory"===e.phase?(console.error('The factory method of "'+e.moduleId+'" has thrown an exception'),void console.error(e)):void 0}),Array.isArray(r.ignoreDuplicateModules)||(r.ignoreDuplicateModules=[]),r.baseUrl.length>0&&(e.Utilities.endsWith(r.baseUrl,"/")||(r.baseUrl+="/")),"string"!=typeof r.cspNonce&&(r.cspNonce=""),Array.isArray(r.nodeModules)||(r.nodeModules=[]),r.nodeCachedData&&"object"==typeof r.nodeCachedData&&("string"!=typeof r.nodeCachedData.seed&&(r.nodeCachedData.seed="seed"),("number"!=typeof r.nodeCachedData.writeDelay||r.nodeCachedData.writeDelay<0)&&(r.nodeCachedData.writeDelay=7e3),!r.nodeCachedData.path||"string"!=typeof r.nodeCachedData.path)){var n=t(new Error("INVALID cached data configuration, 'path' MUST be set"));n.phase="configuration",
+r.onError(n),r.nodeCachedData=void 0}return r},r.mergeConfigurationOptions=function(t,n){void 0===t&&(t=null),void 0===n&&(n=null);var o=e.Utilities.recursiveClone(n||{});return e.Utilities.forEachProperty(t,(function(t,r){"ignoreDuplicateModules"===t&&void 0!==o.ignoreDuplicateModules?o.ignoreDuplicateModules=o.ignoreDuplicateModules.concat(r):"paths"===t&&void 0!==o.paths?e.Utilities.forEachProperty(r,(function(e,t){return o.paths[e]=t})):"config"===t&&void 0!==o.config?e.Utilities.forEachProperty(r,(function(e,t){return o.config[e]=t})):o[t]=e.Utilities.recursiveClone(r)})),r.validateConfigurationOptions(o)},r}();e.ConfigurationOptionsUtil=r;var n=function(){function t(e,t){if(this._env=e,this.options=r.mergeConfigurationOptions(t),this._createIgnoreDuplicateModulesMap(),this._createNodeModulesMap(),this._createSortedPathsRules(),""===this.options.baseUrl){if(this.options.nodeRequire&&this.options.nodeRequire.main&&this.options.nodeRequire.main.filename&&this._env.isNode){
+var n=this.options.nodeRequire.main.filename,o=Math.max(n.lastIndexOf("/"),n.lastIndexOf("\\"));this.options.baseUrl=n.substring(0,o+1)}if(this.options.nodeMain&&this._env.isNode){n=this.options.nodeMain,o=Math.max(n.lastIndexOf("/"),n.lastIndexOf("\\"));this.options.baseUrl=n.substring(0,o+1)}}}return t.prototype._createIgnoreDuplicateModulesMap=function(){this.ignoreDuplicateModulesMap={};for(var e=0;e<this.options.ignoreDuplicateModules.length;e++)this.ignoreDuplicateModulesMap[this.options.ignoreDuplicateModules[e]]=!0},t.prototype._createNodeModulesMap=function(){this.nodeModulesMap=Object.create(null);for(var e=0,t=this.options.nodeModules;e<t.length;e++){var r=t[e];this.nodeModulesMap[r]=!0}},t.prototype._createSortedPathsRules=function(){var t=this;this.sortedPathsRules=[],e.Utilities.forEachProperty(this.options.paths,(function(e,r){Array.isArray(r)?t.sortedPathsRules.push({from:e,to:r}):t.sortedPathsRules.push({from:e,to:[r]})})),this.sortedPathsRules.sort((function(e,t){
+return t.from.length-e.from.length}))},t.prototype.cloneAndMerge=function(e){return new t(this._env,r.mergeConfigurationOptions(e,this.options))},t.prototype.getOptionsLiteral=function(){return this.options},t.prototype._applyPaths=function(t){for(var r,n=0,o=this.sortedPathsRules.length;n<o;n++)if(r=this.sortedPathsRules[n],e.Utilities.startsWith(t,r.from)){for(var i=[],s=0,d=r.to.length;s<d;s++)i.push(r.to[s]+t.substr(r.from.length));return i}return[t]},t.prototype._addUrlArgsToUrl=function(t){return e.Utilities.containsQueryString(t)?t+"&"+this.options.urlArgs:t+"?"+this.options.urlArgs},t.prototype._addUrlArgsIfNecessaryToUrl=function(e){return this.options.urlArgs?this._addUrlArgsToUrl(e):e},t.prototype._addUrlArgsIfNecessaryToUrls=function(e){if(this.options.urlArgs)for(var t=0,r=e.length;t<r;t++)e[t]=this._addUrlArgsToUrl(e[t]);return e},t.prototype.moduleIdToPaths=function(t){if(!0===this.nodeModulesMap[t])return this.isBuild()?["empty:"]:["node|"+t];var r,n=t
+;if(e.Utilities.endsWith(n,".js")||e.Utilities.isAbsolutePath(n))e.Utilities.endsWith(n,".js")||e.Utilities.containsQueryString(n)||(n+=".js"),r=[n];else for(var o=0,i=(r=this._applyPaths(n)).length;o<i;o++)this.isBuild()&&"empty:"===r[o]||(e.Utilities.isAbsolutePath(r[o])||(r[o]=this.options.baseUrl+r[o]),e.Utilities.endsWith(r[o],".js")||e.Utilities.containsQueryString(r[o])||(r[o]=r[o]+".js"));return this._addUrlArgsIfNecessaryToUrls(r)},t.prototype.requireToUrl=function(t){var r=t;return e.Utilities.isAbsolutePath(r)||(r=this._applyPaths(r)[0],e.Utilities.isAbsolutePath(r)||(r=this.options.baseUrl+r)),this._addUrlArgsIfNecessaryToUrl(r)},t.prototype.isBuild=function(){return this.options.isBuild},t.prototype.isDuplicateMessageIgnoredFor=function(e){return this.ignoreDuplicateModulesMap.hasOwnProperty(e)},t.prototype.getConfigForModule=function(e){if(this.options.config)return this.options.config[e]},t.prototype.shouldCatchError=function(){return this.options.catchError},
+t.prototype.shouldRecordStats=function(){return this.options.recordStats},t.prototype.onError=function(e){this.options.onError(e)},t}();e.Configuration=n}(AMDLoader||(AMDLoader={})),function(e){var t=function(){function e(e){this._env=e,this._scriptLoader=null,this._callbackMap={}}return e.prototype.load=function(e,t,i,s){var d=this;this._scriptLoader||(this._scriptLoader=this._env.isWebWorker?new n:this._env.isNode?new o(this._env):new r);var a={callback:i,errorback:s};this._callbackMap.hasOwnProperty(t)?this._callbackMap[t].push(a):(this._callbackMap[t]=[a],this._scriptLoader.load(e,t,(function(){return d.triggerCallback(t)}),(function(e){return d.triggerErrorback(t,e)})))},e.prototype.triggerCallback=function(e){var t=this._callbackMap[e];delete this._callbackMap[e];for(var r=0;r<t.length;r++)t[r].callback()},e.prototype.triggerErrorback=function(e,t){var r=this._callbackMap[e];delete this._callbackMap[e];for(var n=0;n<r.length;n++)r[n].errorback(t)},e}(),r=function(){function e(){}
+return e.prototype.attachListeners=function(e,t,r){var n=function(){e.removeEventListener("load",o),e.removeEventListener("error",i)},o=function(e){n(),t()},i=function(e){n(),r(e)};e.addEventListener("load",o),e.addEventListener("error",i)},e.prototype.load=function(e,t,r,n){var o=document.createElement("script");o.setAttribute("async","async"),o.setAttribute("type","text/javascript"),this.attachListeners(o,r,n),o.setAttribute("src",t);var i=e.getConfig().getOptionsLiteral().cspNonce;i&&o.setAttribute("nonce",i),document.getElementsByTagName("head")[0].appendChild(o)},e}(),n=function(){function e(){}return e.prototype.load=function(e,t,r,n){try{importScripts(t),r()}catch(e){n(e)}},e}(),o=function(){function t(e){this._env=e,this._didInitialize=!1,this._didPatchNodeRequire=!1}return t.prototype._init=function(e){this._didInitialize||(this._didInitialize=!0,this._fs=e("fs"),this._vm=e("vm"),this._path=e("path"),this._crypto=e("crypto"))},t.prototype._initNodeRequire=function(e,t){
+var r=t.getConfig().getOptionsLiteral().nodeCachedData;if(r&&!this._didPatchNodeRequire){this._didPatchNodeRequire=!0;var n=this,o=e("module");o.prototype._compile=function(e,i){var s,d=o.wrap(e.replace(/^#!.*/,"")),a=t.getRecorder(),u=n._getCachedDataPath(r,i),l={filename:i};try{var c=n._fs.readFileSync(u);s=c.slice(0,16),l.cachedData=c.slice(16),a.record(60,u)}catch(e){a.record(61,u)}var h=new n._vm.Script(d,l),f=h.runInThisContext(l),p=n._path.dirname(i),_=function(e){var t=e.constructor,r=function(t){try{return e.require(t)}finally{}};return r.resolve=function(r){return t._resolveFilename(r,e)},r.main=process.mainModule,r.extensions=t._extensions,r.cache=t._cache,r}(this),g=[this.exports,_,this,i,p,process,_commonjsGlobal,Buffer],v=f.apply(this.exports,g);return n._handleCachedData(h,d,u,!l.cachedData,t),n._verifyCachedData(h,d,u,s,t),v}}},t.prototype.load=function(r,n,o,i){var s=this,d=r.getConfig().getOptionsLiteral(),a=d.nodeRequire||e.global.nodeRequire,u=d.nodeInstrumenter||function(e){return e}
+;this._init(a),this._initNodeRequire(a,r);var l=r.getRecorder();if(/^node\|/.test(n)){var c=n.split("|"),h=null;try{h=a(c[1])}catch(e){return void i(e)}r.enqueueDefineAnonymousModule([],(function(){return h})),o()}else{n=e.Utilities.fileUriToFilePath(this._env.isWindows,n);var f=this._path.normalize(n),p=this._getElectronRendererScriptPathOrUri(f),_=Boolean(d.nodeCachedData),g=_?this._getCachedDataPath(d.nodeCachedData,n):void 0;this._readSourceAndCachedData(f,g,l,(function(e,n,d,a){if(e)i(e);else{var l;l=n.charCodeAt(0)===t._BOM?t._PREFIX+n.substring(1)+t._SUFFIX:t._PREFIX+n+t._SUFFIX,l=u(l,f);var c={filename:p,cachedData:d},h=s._createAndEvalScript(r,l,c,o,i);s._handleCachedData(h,l,g,_&&!d,r),s._verifyCachedData(h,l,g,a,r)}}))}},t.prototype._createAndEvalScript=function(t,r,n,o,i){var s=t.getRecorder();s.record(31,n.filename);var d=new this._vm.Script(r,n),a=d.runInThisContext(n),u=t.getGlobalAMDDefineFunc(),l=!1,c=function(){return l=!0,u.apply(null,arguments)};return c.amd=u.amd,
+a.call(e.global,t.getGlobalAMDRequireFunc(),c,n.filename,this._path.dirname(n.filename)),s.record(32,n.filename),l?o():i(new Error("Didn't receive define call in "+n.filename+"!")),d},t.prototype._getElectronRendererScriptPathOrUri=function(e){if(!this._env.isElectronRenderer)return e;var t=e.match(/^([a-z])\:(.*)/i);return t?"file:///"+(t[1].toUpperCase()+":"+t[2]).replace(/\\/g,"/"):"file://"+e},t.prototype._getCachedDataPath=function(e,t){var r=this._crypto.createHash("md5").update(t,"utf8").update(e.seed,"utf8").digest("hex"),n=this._path.basename(t).replace(/\.js$/,"");return this._path.join(e.path,n+"-"+r+".code")},t.prototype._handleCachedData=function(e,t,r,n,o){var i=this;e.cachedDataRejected?this._fs.unlink(r,(function(n){o.getRecorder().record(62,r),i._createAndWriteCachedData(e,t,r,o),n&&o.getConfig().onError(n)})):n&&this._createAndWriteCachedData(e,t,r,o)},t.prototype._createAndWriteCachedData=function(e,t,r,n){
+var o=this,i=Math.ceil(n.getConfig().getOptionsLiteral().nodeCachedData.writeDelay*(1+Math.random())),s=-1,d=0,a=void 0,u=function(){setTimeout((function(){a||(a=o._crypto.createHash("md5").update(t,"utf8").digest());var i=e.createCachedData();0===i.length||i.length===s||d>=5||(s=i.length,o._fs.writeFile(r,Buffer.concat([a,i]),(function(e){e&&n.getConfig().onError(e),n.getRecorder().record(63,r),u()})))}),i*Math.pow(4,d++))};u()},t.prototype._readSourceAndCachedData=function(e,t,r,n){if(t){var o=void 0,i=void 0,s=void 0,d=2,a=function(e){e?n(e):0==--d&&n(void 0,o,i,s)};this._fs.readFile(e,{encoding:"utf8"},(function(e,t){o=t,a(e)})),this._fs.readFile(t,(function(e,n){!e&&n&&n.length>0?(s=n.slice(0,16),i=n.slice(16),r.record(60,t)):r.record(61,t),a()}))}else this._fs.readFile(e,{encoding:"utf8"},n)},t.prototype._verifyCachedData=function(e,t,r,n,o){var i=this;n&&(e.cachedDataRejected||setTimeout((function(){var e=i._crypto.createHash("md5").update(t,"utf8").digest()
+;n.equals(e)||(o.getConfig().onError(new Error("FAILED TO VERIFY CACHED DATA, deleting stale '"+r+"' now, but a RESTART IS REQUIRED")),i._fs.unlink(r,(function(e){return o.getConfig().onError(e)})))}),Math.ceil(5e3*(1+Math.random()))))},t._BOM=65279,t._PREFIX="(function (require, define, __filename, __dirname) { ",t._SUFFIX="\n});",t}();e.createScriptLoader=function(e){return new t(e)}}(AMDLoader||(AMDLoader={})),function(e){var t=function(){function t(e){var t=e.lastIndexOf("/");this.fromModulePath=-1!==t?e.substr(0,t+1):""}return t._normalizeModuleId=function(e){var t,r=e;for(t=/\/\.\//;t.test(r);)r=r.replace(t,"/");for(r=r.replace(/^\.\//g,""),t=/\/(([^\/])|([^\/][^\/\.])|([^\/\.][^\/])|([^\/][^\/][^\/]+))\/\.\.\//;t.test(r);)r=r.replace(t,"/");return r=r.replace(/^(([^\/])|([^\/][^\/\.])|([^\/\.][^\/])|([^\/][^\/][^\/]+))\/\.\.\//,"")},t.prototype.resolveModule=function(r){var n=r
+;return e.Utilities.isAbsolutePath(n)||(e.Utilities.startsWith(n,"./")||e.Utilities.startsWith(n,"../"))&&(n=t._normalizeModuleId(this.fromModulePath+n)),n},t.ROOT=new t(""),t}();e.ModuleIdResolver=t;var r=function(){function t(e,t,r,n,o,i){this.id=e,this.strId=t,this.dependencies=r,this._callback=n,this._errorback=o,this.moduleIdResolver=i,this.exports={},this.error=null,this.exportsPassedIn=!1,this.unresolvedDependenciesCount=this.dependencies.length,this._isComplete=!1}return t._safeInvokeFunction=function(t,r){try{return{returnedValue:t.apply(e.global,r),producedError:null}}catch(e){return{returnedValue:null,producedError:e}}},t._invokeFactory=function(t,r,n,o){return t.isBuild()&&!e.Utilities.isAnonymousModule(r)?{returnedValue:null,producedError:null}:t.shouldCatchError()?this._safeInvokeFunction(n,o):{returnedValue:n.apply(e.global,o),producedError:null}},t.prototype.complete=function(r,n,o){this._isComplete=!0;var i=null;if(this._callback)if("function"==typeof this._callback){r.record(21,this.strId)
+;var s=t._invokeFactory(n,this.strId,this._callback,o);i=s.producedError,r.record(22,this.strId),i||void 0===s.returnedValue||this.exportsPassedIn&&!e.Utilities.isEmpty(this.exports)||(this.exports=s.returnedValue)}else this.exports=this._callback;if(i){var d=e.ensureError(i);d.phase="factory",d.moduleId=this.strId,this.error=d,n.onError(d)}this.dependencies=null,this._callback=null,this._errorback=null,this.moduleIdResolver=null},t.prototype.onDependencyError=function(e){return this._isComplete=!0,this.error=e,!!this._errorback&&(this._errorback(e),!0)},t.prototype.isComplete=function(){return this._isComplete},t}();e.Module=r;var n=function(){function e(){this._nextId=0,this._strModuleIdToIntModuleId=new Map,this._intModuleIdToStrModuleId=[],this.getModuleId("exports"),this.getModuleId("module"),this.getModuleId("require")}return e.prototype.getMaxModuleId=function(){return this._nextId},e.prototype.getModuleId=function(e){var t=this._strModuleIdToIntModuleId.get(e);return void 0===t&&(t=this._nextId++,
+this._strModuleIdToIntModuleId.set(e,t),this._intModuleIdToStrModuleId[t]=e),t},e.prototype.getStrModuleId=function(e){return this._intModuleIdToStrModuleId[e]},e}(),o=function(){function e(e){this.id=e}return e.EXPORTS=new e(0),e.MODULE=new e(1),e.REQUIRE=new e(2),e}();e.RegularDependency=o;var i=function(e,t,r){this.id=e,this.pluginId=t,this.pluginParam=r};e.PluginDependency=i;var s=function(){function s(t,r,o,i,s){void 0===s&&(s=0),this._env=t,this._scriptLoader=r,this._loaderAvailableTimestamp=s,this._defineFunc=o,this._requireFunc=i,this._moduleIdProvider=new n,this._config=new e.Configuration(this._env),this._modules2=[],this._knownModules2=[],this._inverseDependencies2=[],this._inversePluginDependencies2=new Map,this._currentAnnonymousDefineCall=null,this._recorder=null,this._buildInfoPath=[],this._buildInfoDefineStack=[],this._buildInfoDependencies=[]}return s.prototype.reset=function(){return new s(this._env,this._scriptLoader,this._defineFunc,this._requireFunc,this._loaderAvailableTimestamp)},
+s.prototype.getGlobalAMDDefineFunc=function(){return this._defineFunc},s.prototype.getGlobalAMDRequireFunc=function(){return this._requireFunc},s._findRelevantLocationInStack=function(e,t){for(var r=function(e){return e.replace(/\\/g,"/")},n=r(e),o=t.split(/\n/),i=0;i<o.length;i++){var s=o[i].match(/(.*):(\d+):(\d+)\)?$/);if(s){var d=s[1],a=s[2],u=s[3],l=Math.max(d.lastIndexOf(" ")+1,d.lastIndexOf("(")+1);if((d=r(d=d.substr(l)))===n){var c={line:parseInt(a,10),col:parseInt(u,10)};return 1===c.line&&(c.col-="(function (require, define, __filename, __dirname) { ".length),c}}}throw new Error("Could not correlate define call site for needle "+e)},s.prototype.getBuildInfo=function(){if(!this._config.isBuild())return null;for(var e=[],t=0,r=0,n=this._modules2.length;r<n;r++){var o=this._modules2[r];if(o){var i=this._buildInfoPath[o.id]||null,d=this._buildInfoDefineStack[o.id]||null,a=this._buildInfoDependencies[o.id];e[t++]={id:o.strId,path:i,defineLocation:i&&d?s._findRelevantLocationInStack(i,d):null,
+dependencies:a,shim:null,exports:o.exports}}}return e},s.prototype.getRecorder=function(){return this._recorder||(this._config.shouldRecordStats()?this._recorder=new e.LoaderEventRecorder(this._loaderAvailableTimestamp):this._recorder=e.NullLoaderEventRecorder.INSTANCE),this._recorder},s.prototype.getLoaderEvents=function(){return this.getRecorder().getEvents()},s.prototype.enqueueDefineAnonymousModule=function(e,t){if(null!==this._currentAnnonymousDefineCall)throw new Error("Can only have one anonymous define call per script file");var r=null;this._config.isBuild()&&(r=new Error("StackLocation").stack||null),this._currentAnnonymousDefineCall={stack:r,dependencies:e,callback:t}},s.prototype.defineModule=function(e,n,o,i,s,d){var a=this;void 0===d&&(d=new t(e));var u=this._moduleIdProvider.getModuleId(e);if(this._modules2[u])this._config.isDuplicateMessageIgnoredFor(e)||console.warn("Duplicate definition of module '"+e+"'");else{var l=new r(u,e,this._normalizeDependencies(n,d),o,i,d);this._modules2[u]=l,
+this._config.isBuild()&&(this._buildInfoDefineStack[u]=s,this._buildInfoDependencies[u]=(l.dependencies||[]).map((function(e){return a._moduleIdProvider.getStrModuleId(e.id)}))),this._resolve(l)}},s.prototype._normalizeDependency=function(e,t){if("exports"===e)return o.EXPORTS;if("module"===e)return o.MODULE;if("require"===e)return o.REQUIRE;var r=e.indexOf("!");if(r>=0){var n=t.resolveModule(e.substr(0,r)),s=t.resolveModule(e.substr(r+1)),d=this._moduleIdProvider.getModuleId(n+"!"+s),a=this._moduleIdProvider.getModuleId(n);return new i(d,a,s)}return new o(this._moduleIdProvider.getModuleId(t.resolveModule(e)))},s.prototype._normalizeDependencies=function(e,t){for(var r=[],n=0,o=0,i=e.length;o<i;o++)r[n++]=this._normalizeDependency(e[o],t);return r},s.prototype._relativeRequire=function(t,r,n,o){if("string"==typeof r)return this.synchronousRequire(r,t);this.defineModule(e.Utilities.generateAnonymousModule(),r,n,o,null,t)},s.prototype.synchronousRequire=function(e,r){void 0===r&&(r=new t(e))
+;var n=this._normalizeDependency(e,r),o=this._modules2[n.id];if(!o)throw new Error("Check dependency list! Synchronous require cannot resolve module '"+e+"'. This is the first mention of this module!");if(!o.isComplete())throw new Error("Check dependency list! Synchronous require cannot resolve module '"+e+"'. This module has not been resolved completely yet.");if(o.error)throw o.error;return o.exports},s.prototype.configure=function(t,r){var n=this._config.shouldRecordStats();this._config=r?new e.Configuration(this._env,t):this._config.cloneAndMerge(t),this._config.shouldRecordStats()&&!n&&(this._recorder=null)},s.prototype.getConfig=function(){return this._config},s.prototype._onLoad=function(e){if(null!==this._currentAnnonymousDefineCall){var t=this._currentAnnonymousDefineCall;this._currentAnnonymousDefineCall=null,this.defineModule(this._moduleIdProvider.getStrModuleId(e),t.dependencies,t.callback,null,t.stack)}},s.prototype._createLoadError=function(t,r){
+var n=this,o=this._moduleIdProvider.getStrModuleId(t),i=(this._inverseDependencies2[t]||[]).map((function(e){return n._moduleIdProvider.getStrModuleId(e)})),s=e.ensureError(r);return s.phase="loading",s.moduleId=o,s.neededBy=i,s},s.prototype._onLoadError=function(e,t){var n=this._createLoadError(e,t);this._modules2[e]||(this._modules2[e]=new r(e,this._moduleIdProvider.getStrModuleId(e),[],(function(){}),(function(){}),null));for(var o=[],i=0,s=this._moduleIdProvider.getMaxModuleId();i<s;i++)o[i]=!1;var d=!1,a=[];for(a.push(e),o[e]=!0;a.length>0;){var u=a.shift(),l=this._modules2[u];l&&(d=l.onDependencyError(n)||d);var c=this._inverseDependencies2[u];if(c)for(i=0,s=c.length;i<s;i++){var h=c[i];o[h]||(a.push(h),o[h]=!0)}}d||this._config.onError(n)},s.prototype._hasDependencyPath=function(e,t){var r=this._modules2[e];if(!r)return!1;for(var n=[],o=0,i=this._moduleIdProvider.getMaxModuleId();o<i;o++)n[o]=!1;var s=[];for(s.push(r),n[e]=!0;s.length>0;){var d=s.shift().dependencies;if(d)for(o=0,i=d.length;o<i;o++){
+var a=d[o];if(a.id===t)return!0;var u=this._modules2[a.id];u&&!n[a.id]&&(n[a.id]=!0,s.push(u))}}return!1},s.prototype._findCyclePath=function(e,t,r){if(e===t||50===r)return[e];var n=this._modules2[e];if(!n)return null;var o=n.dependencies;if(o)for(var i=0,s=o.length;i<s;i++){var d=this._findCyclePath(o[i].id,t,r+1);if(null!==d)return d.push(e),d}return null},s.prototype._createRequire=function(t){var r=this,n=function(e,n,o){return r._relativeRequire(t,e,n,o)};return n.toUrl=function(e){return r._config.requireToUrl(t.resolveModule(e))},n.getStats=function(){return r.getLoaderEvents()},n.__$__nodeRequire=e.global.nodeRequire,n},s.prototype._loadModule=function(e){var t=this;if(!this._modules2[e]&&!this._knownModules2[e]){this._knownModules2[e]=!0;var r=this._moduleIdProvider.getStrModuleId(e),n=this._config.moduleIdToPaths(r);this._env.isNode&&(-1===r.indexOf("/")||/^@[^\/]+\/[^\/]+$/.test(r))&&n.push("node|"+r);var o=-1,i=function(r){if(++o>=n.length)t._onLoadError(e,r);else{var s=n[o],d=t.getRecorder()
+;if(t._config.isBuild()&&"empty:"===s)return t._buildInfoPath[e]=s,t.defineModule(t._moduleIdProvider.getStrModuleId(e),[],null,null,null),void t._onLoad(e);d.record(10,s),t._scriptLoader.load(t,s,(function(){t._config.isBuild()&&(t._buildInfoPath[e]=s),d.record(11,s),t._onLoad(e)}),(function(e){d.record(12,s),i(e)}))}};i(null)}},s.prototype._loadPluginDependency=function(e,r){var n=this;if(!this._modules2[r.id]&&!this._knownModules2[r.id]){this._knownModules2[r.id]=!0;var o=function(e){n.defineModule(n._moduleIdProvider.getStrModuleId(r.id),[],e,null,null)};o.error=function(e){n._config.onError(n._createLoadError(r.id,e))},e.load(r.pluginParam,this._createRequire(t.ROOT),o,this._config.getOptionsLiteral())}},s.prototype._resolve=function(e){var t=this,r=e.dependencies;if(r)for(var n=0,s=r.length;n<s;n++){var d=r[n];if(d!==o.EXPORTS)if(d!==o.MODULE)if(d!==o.REQUIRE){var a=this._modules2[d.id];if(a&&a.isComplete()){if(a.error)return void e.onDependencyError(a.error);e.unresolvedDependenciesCount--
+}else if(this._hasDependencyPath(d.id,e.id)){console.warn("There is a dependency cycle between '"+this._moduleIdProvider.getStrModuleId(d.id)+"' and '"+this._moduleIdProvider.getStrModuleId(e.id)+"'. The cyclic path follows:");var u=this._findCyclePath(d.id,e.id,0)||[];u.reverse(),u.push(d.id),console.warn(u.map((function(e){return t._moduleIdProvider.getStrModuleId(e)})).join(" => \n")),e.unresolvedDependenciesCount--}else if(this._inverseDependencies2[d.id]=this._inverseDependencies2[d.id]||[],this._inverseDependencies2[d.id].push(e.id),d instanceof i){var l=this._modules2[d.pluginId];if(l&&l.isComplete()){this._loadPluginDependency(l.exports,d);continue}var c=this._inversePluginDependencies2.get(d.pluginId);c||(c=[],this._inversePluginDependencies2.set(d.pluginId,c)),c.push(d),this._loadModule(d.pluginId)}else this._loadModule(d.id)}else e.unresolvedDependenciesCount--;else e.unresolvedDependenciesCount--;else e.exportsPassedIn=!0,e.unresolvedDependenciesCount--}
+0===e.unresolvedDependenciesCount&&this._onModuleComplete(e)},s.prototype._onModuleComplete=function(e){var t=this,r=this.getRecorder();if(!e.isComplete()){var n=e.dependencies,i=[];if(n)for(var s=0,d=n.length;s<d;s++){var a=n[s];if(a!==o.EXPORTS)if(a!==o.MODULE)if(a!==o.REQUIRE){var u=this._modules2[a.id];i[s]=u?u.exports:null}else i[s]=this._createRequire(e.moduleIdResolver);else i[s]={id:e.strId,config:function(){return t._config.getConfigForModule(e.strId)}};else i[s]=e.exports}e.complete(r,this._config,i);var l=this._inverseDependencies2[e.id];if(this._inverseDependencies2[e.id]=null,l)for(s=0,d=l.length;s<d;s++){var c=l[s],h=this._modules2[c];h.unresolvedDependenciesCount--,0===h.unresolvedDependenciesCount&&this._onModuleComplete(h)}var f=this._inversePluginDependencies2.get(e.id);if(f){this._inversePluginDependencies2.delete(e.id);for(s=0,d=f.length;s<d;s++)this._loadPluginDependency(e.exports,f[s])}}},s}();e.ModuleManager=s}(AMDLoader||(AMDLoader={})),function(e){
+var t=new e.Environment,r=null,n=function(e,t,n){"string"!=typeof e&&(n=t,t=e,e=null),"object"==typeof t&&Array.isArray(t)||(n=t,t=null),t||(t=["require","exports","module"]),e?r.defineModule(e,t,n,null,null):r.enqueueDefineAnonymousModule(t,n)};n.amd={jQuery:!0};var o=function(e,t){void 0===t&&(t=!1),r.configure(e,t)},i=function(){if(1===arguments.length){if(arguments[0]instanceof Object&&!Array.isArray(arguments[0]))return void o(arguments[0]);if("string"==typeof arguments[0])return r.synchronousRequire(arguments[0])}if(2!==arguments.length&&3!==arguments.length||!Array.isArray(arguments[0]))throw new Error("Unrecognized require call");r.defineModule(e.Utilities.generateAnonymousModule(),arguments[0],arguments[1],arguments[2],null)};function s(){if(void 0!==e.global.require||"undefined"!=typeof require){var o=e.global.require||require;if("function"==typeof o&&"function"==typeof o.resolve){var s=function(e){r.getRecorder().record(33,e);try{return o(e)}finally{r.getRecorder().record(34,e)}}
+;e.global.nodeRequire=s,i.nodeRequire=s,i.__$__nodeRequire=s}}t.isNode&&!t.isElectronRenderer?(module.exports=i,require=i):(t.isElectronRenderer||(e.global.define=n),e.global.require=i)}i.config=o,i.getConfig=function(){return r.getConfig().getOptionsLiteral()},i.reset=function(){r=r.reset()},i.getBuildInfo=function(){return r.getBuildInfo()},i.getStats=function(){return r.getLoaderEvents()},i.define=function(){return n.apply(null,arguments)},e.init=s,"function"==typeof e.global.define&&e.global.define.amd||(r=new e.ModuleManager(t,e.createScriptLoader(t),n,i,e.Utilities.getHighPerformanceTimestamp()),void 0!==e.global.require&&"function"!=typeof e.global.require&&i.config(e.global.require),(define=function(){return n.apply(null,arguments)}).amd=n.amd,"undefined"==typeof doNotInitLoader&&s())}(AMDLoader||(AMDLoader={}));
+//# sourceMappingURL=../../min-maps/vs/loader.js.map

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 0
manual/3rdparty/split.min.js


+ 274 - 342
manual/en/align-html-elements-to-3d.html

@@ -1,67 +1,69 @@
-Title: Three.js Aligning HTML Elements to 3D
-Description: How to line up an HTML Element to match a point in 3D space
-TOC: Aligning HTML Elements to 3D
-
-This article is part of a series of articles about three.js. The first article
-is [three.js fundamentals](threejs-fundamentals.html). If you haven't read that
-yet and you're new to three.js you might want to consider starting there. 
-
-Sometimes you'd like to display some text in your 3D scene. You have many options
-each with pluses and minuses.
-
-* Use 3D text
-
-  If you look at the [primitives article](threejs-primitives.html) you'll see `TextGeometry` which
-  makes 3D text. This might be useful for flying logos but probably not so useful for stats, info,
-  or labelling lots of things.
-
-* Use a texture with 2D text drawn into it.
-
-  The article on [using a Canvas as a texture](threejs-canvas-textures.html) shows using
-  a canvas as a texture. You can draw text into a canvas and [display it as a billboard](threejs-billboards.html).
-  The plus here might be that the text is integrated into the 3D scene. For something like a computer terminal
-  shown in a 3D scene this might be perfect.
-
-* Use HTML Elements and position them to match the 3D
-
-  The benefits to this approach is you can use all of HTML. Your HTML can have multiple elements. It can
-  by styled with CSS. It can also be selected by the user as it is actual text. 
-
-This article will cover this last approach.
-
-Let's start simple. We'll make a 3D scene with a few primitives and then add a label to each primitive. We'll start
-with an example from [the article on responsive pages](threejs-responsive.html) 
-
-We'll add some `OrbitControls` like we did in [the article on lighting](threejs-lights.html).
-
-```js
-import * as THREE from './resources/three/r132/build/three.module.js';
-+import {OrbitControls} from './resources/threejs/r132/examples/jsm/controls/OrbitControls.js';
-```
-
-```js
-const controls = new OrbitControls(camera, canvas);
+<!DOCTYPE html><html lang="en"><head>
+    <meta charset="utf-8">
+    <title>Aligning HTML Elements to 3D</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 – Aligning HTML Elements to 3D">
+    <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">
+  </head>
+  <body>
+    <div class="container">
+      <div class="lesson-title">
+        <h1>Aligning HTML Elements to 3D</h1>
+      </div>
+      <div class="lesson">
+        <div class="lesson-main">
+          <p>This article is part of a series of articles about three.js. The first article
+is <a href="fundamentals.html">three.js fundamentals</a>. If you haven't read that
+yet and you're new to three.js you might want to consider starting there. </p>
+<p>Sometimes you'd like to display some text in your 3D scene. You have many options
+each with pluses and minuses.</p>
+<ul>
+<li><p>Use 3D text</p>
+<p>If you look at the <a href="primitives.html">primitives article</a> you'll see <a href="/docs/#api/en/geometries/TextGeometry"><code class="notranslate" translate="no">TextGeometry</code></a> which
+makes 3D text. This might be useful for flying logos but probably not so useful for stats, info,
+or labelling lots of things.</p>
+</li>
+<li><p>Use a texture with 2D text drawn into it.</p>
+<p>The article on <a href="canvas-textures.html">using a Canvas as a texture</a> shows using
+a canvas as a texture. You can draw text into a canvas and <a href="billboards.html">display it as a billboard</a>.
+The plus here might be that the text is integrated into the 3D scene. For something like a computer terminal
+shown in a 3D scene this might be perfect.</p>
+</li>
+<li><p>Use HTML Elements and position them to match the 3D</p>
+<p>The benefits to this approach is you can use all of HTML. Your HTML can have multiple elements. It can
+by styled with CSS. It can also be selected by the user as it is actual text. </p>
+</li>
+</ul>
+<p>This article will cover this last approach.</p>
+<p>Let's start simple. We'll make a 3D scene with a few primitives and then add a label to each primitive. We'll start
+with an example from <a href="responsive.html">the article on responsive pages</a> </p>
+<p>We'll add some <a href="/docs/#examples/controls/OrbitControls"><code class="notranslate" translate="no">OrbitControls</code></a> like we did in <a href="lights.html">the article on lighting</a>.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">import * as THREE from '/build/three.module.js';
++import {OrbitControls} from '/examples/jsm/controls/OrbitControls.js';
+</pre>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const controls = new OrbitControls(camera, canvas);
 controls.target.set(0, 0, 0);
 controls.update();
-```
-
-We need to provide an HTML element to contain our label elements
-
-```html
-<body>
--  <canvas id="c"></canvas>
-+  <div id="container">
-+    <canvas id="c"></canvas>
-+    <div id="labels"></div>
-+  </div>
-</body>
-```
-
-By putting both the canvas and the `<div id="labels">` inside a
-parent container we can make them overlap with this CSS
-
-```css
-#c {
+</pre>
+<p>We need to provide an HTML element to contain our label elements</p>
+<pre class="prettyprint showlinemods notranslate lang-html" translate="no">&lt;body&gt;
+-  &lt;canvas id="c"&gt;&lt;/canvas&gt;
++  &lt;div id="container"&gt;
++    &lt;canvas id="c"&gt;&lt;/canvas&gt;
++    &lt;div id="labels"&gt;&lt;/div&gt;
++  &lt;/div&gt;
+&lt;/body&gt;
+</pre>
+<p>By putting both the canvas and the <code class="notranslate" translate="no">&lt;div id="labels"&gt;</code> inside a
+parent container we can make them overlap with this CSS</p>
+<pre class="prettyprint showlinemods notranslate lang-css" translate="no">#c {
 -    width: 100%;
 -    height: 100%;
 +    width: 100%;  /* let our container decide our size */
@@ -80,12 +82,9 @@ parent container we can make them overlap with this CSS
 +  top: 0;
 +  color: white;
 +}
-```
-
-let's also add some CSS for the labels themselves
-
-```css
-#labels>div {
+</pre>
+<p>let's also add some CSS for the labels themselves</p>
+<pre class="prettyprint showlinemods notranslate lang-css" translate="no">#labels&gt;div {
   position: absolute;  /* let us position them inside the container */
   left: 0;             /* make their default position the top left of the container */
   top: 0;
@@ -102,17 +101,14 @@ let's also add some CSS for the labels themselves
     -1px  1px 0 #000,
     -1px  0   0 #000;
 }
-#labels>div:hover {
+#labels&gt;div:hover {
   color: red;
 }
-```
-
-Now into our code we don't have to add too much. We had a function
-`makeInstance` that we used to generate cubes. Let's make it
-so it also adds a label element.
-
-```js
-+const labelContainerElem = document.querySelector('#labels');
+</pre>
+<p>Now into our code we don't have to add too much. We had a function
+<code class="notranslate" translate="no">makeInstance</code> that we used to generate cubes. Let's make it
+so it also adds a label element.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">+const labelContainerElem = document.querySelector('#labels');
 
 -function makeInstance(geometry, color, x) {
 +function makeInstance(geometry, color, x, name) {
@@ -130,15 +126,11 @@ so it also adds a label element.
 -  return cube;
 +  return {cube, elem};
 }
-```
-
-As you can see we're adding a `<div>` to the container, one for each cube. We're
-also returning an object with both the `cube` and the `elem` for the label.
-
-Calling it we need to provide a name for each
-
-```js
-const cubes = [
+</pre>
+<p>As you can see we're adding a <code class="notranslate" translate="no">&lt;div&gt;</code> to the container, one for each cube. We're
+also returning an object with both the <code class="notranslate" translate="no">cube</code> and the <code class="notranslate" translate="no">elem</code> for the label.</p>
+<p>Calling it we need to provide a name for each</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const cubes = [
 -  makeInstance(geometry, 0x44aa88,  0),
 -  makeInstance(geometry, 0x8844aa, -2),
 -  makeInstance(geometry, 0xaa8844,  2),
@@ -146,17 +138,14 @@ const cubes = [
 +  makeInstance(geometry, 0x8844aa, -2, 'Purple'),
 +  makeInstance(geometry, 0xaa8844,  2, 'Gold'),
 ];
-```
-
-What remains is positioning the label elements at render time
-
-```js
-const tempV = new THREE.Vector3();
+</pre>
+<p>What remains is positioning the label elements at render time</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const tempV = new THREE.Vector3();
 
 ...
 
--cubes.forEach((cube, ndx) => {
-+cubes.forEach((cubeInfo, ndx) => {
+-cubes.forEach((cube, ndx) =&gt; {
++cubes.forEach((cubeInfo, ndx) =&gt; {
 +  const {cube, elem} = cubeInfo;
   const speed = 1 + ndx * .1;
   const rot = time * speed;
@@ -179,35 +168,32 @@ const tempV = new THREE.Vector3();
 +  // move the elem to that position
 +  elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
 });
-```
-
-And with that we have labels aligned to their corresponding objects.
-
-{{{example url="../threejs-align-html-to-3d.html" }}}
-
-There are a couple of issues we probably want to deal with.
-
-One is that if we rotate the objects so they overlap all the labels
-overlap as well.
-
-<div class="threejs_center"><img src="resources/images/overlapping-labels.png" style="width: 307px;"></div>
+</pre>
+<p>And with that we have labels aligned to their corresponding objects.</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/align-html-to-3d.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/align-html-to-3d.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-Another is that if we zoom way out so that the objects go outside
-the frustum the labels will still appear.
+<p></p>
+<p>There are a couple of issues we probably want to deal with.</p>
+<p>One is that if we rotate the objects so they overlap all the labels
+overlap as well.</p>
+<div class="threejs_center"><img src="../resources/images/overlapping-labels.png" style="width: 307px;"></div>
 
-A possible solution to the problem of overlapping objects is to use
-the [picking code from the article on picking](threejs-picking.html).
+<p>Another is that if we zoom way out so that the objects go outside
+the frustum the labels will still appear.</p>
+<p>A possible solution to the problem of overlapping objects is to use
+the <a href="picking.html">picking code from the article on picking</a>.
 We'll pass in the position of the object on the screen and then
-ask the `RayCaster` to tell us which objects were intersected.
-If our object is not the first one then we are not in the front.
-
-```js
-const tempV = new THREE.Vector3();
+ask the <code class="notranslate" translate="no">RayCaster</code> to tell us which objects were intersected.
+If our object is not the first one then we are not in the front.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const tempV = new THREE.Vector3();
 +const raycaster = new THREE.Raycaster();
 
 ...
 
-cubes.forEach((cubeInfo, ndx) => {
+cubes.forEach((cubeInfo, ndx) =&gt; {
   const {cube, elem} = cubeInfo;
   const speed = 1 + ndx * .1;
   const rot = time * speed;
@@ -228,7 +214,7 @@ cubes.forEach((cubeInfo, ndx) => {
 +  raycaster.setFromCamera(tempV, camera);
 +  const intersectedObjects = raycaster.intersectObjects(scene.children);
 +  // We're visible if the first intersection is this object.
-+  const show = intersectedObjects.length && cube === intersectedObjects[0].object;
++  const show = intersectedObjects.length &amp;&amp; cube === intersectedObjects[0].object;
 +
 +  if (!show) {
 +    // hide the label
@@ -245,38 +231,32 @@ cubes.forEach((cubeInfo, ndx) => {
     elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
 +  }
 });
-```
-
-This handles overlapping.
-
-To handle going outside the frustum we can add this check if the origin of
-the object is outside the frustum by checking `tempV.z`
-
-```js
--  if (!show) {
-+  if (!show || Math.abs(tempV.z) > 1) {
+</pre>
+<p>This handles overlapping.</p>
+<p>To handle going outside the frustum we can add this check if the origin of
+the object is outside the frustum by checking <code class="notranslate" translate="no">tempV.z</code></p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">-  if (!show) {
++  if (!show || Math.abs(tempV.z) &gt; 1) {
     // hide the label
     elem.style.display = 'none';
-```
-
-This *kind of* works because the normalized coordinates we computed include a `z`
-value that goes from -1 when at the `near` part of our camera frustum to +1 when
-at the `far` part of our camera frustum.
-
-{{{example url="../threejs-align-html-to-3d-w-hiding.html" }}}
-
-For the frustum check, the solution above fails as we're only checking the origin of the object. For a large
-object. That origin might go outside the frustum but half of the object might still be in the frustum.
+</pre>
+<p>This <em>kind of</em> works because the normalized coordinates we computed include a <code class="notranslate" translate="no">z</code>
+value that goes from -1 when at the <code class="notranslate" translate="no">near</code> part of our camera frustum to +1 when
+at the <code class="notranslate" translate="no">far</code> part of our camera frustum.</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/align-html-to-3d-w-hiding.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/align-html-to-3d-w-hiding.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-A more correct solution would be to check if the object itself is in the frustum
+<p></p>
+<p>For the frustum check, the solution above fails as we're only checking the origin of the object. For a large
+object. That origin might go outside the frustum but half of the object might still be in the frustum.</p>
+<p>A more correct solution would be to check if the object itself is in the frustum
 or not. Unfortunate that check is slow. For 3 cubes it will not be a problem
-but for many objects it might be.
-
-Three.js provides some functions to check if an object's bounding sphere is
-in a frustum
-
-```js
-// at init time
+but for many objects it might be.</p>
+<p>Three.js provides some functions to check if an object's bounding sphere is
+in a frustum</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">// at init time
 const frustum = new THREE.Frustum();
 const viewProjection = new THREE.Matrix4();
 
@@ -297,18 +277,14 @@ viewProjection.multiplyMatrices(
     camera.projectionMatrix, camera.matrixWorldInverse);
 frustum.setFromProjectionMatrix(viewProjection);
 const inFrustum = frustum.contains(someMesh));
-```
-
-Our current overlapping solution has similar issues. Picking is slow. We could
-use gpu based picking like we covered in the [picking
-article](threejs-picking.html) but that is also not free. Which solution you
-chose depends on your needs.
-
-Another issue is the order the labels appear. If we change the code to have
-longer labels
-
-```js
-const cubes = [
+</pre>
+<p>Our current overlapping solution has similar issues. Picking is slow. We could
+use gpu based picking like we covered in the <a href="picking.html">picking
+article</a> but that is also not free. Which solution you
+chose depends on your needs.</p>
+<p>Another issue is the order the labels appear. If we change the code to have
+longer labels</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const cubes = [
 -  makeInstance(geometry, 0x44aa88,  0, 'Aqua'),
 -  makeInstance(geometry, 0x8844aa, -2, 'Purple'),
 -  makeInstance(geometry, 0xaa8844,  2, 'Gold'),
@@ -316,27 +292,19 @@ const cubes = [
 +  makeInstance(geometry, 0x8844aa, -2, 'Purple Colored Box'),
 +  makeInstance(geometry, 0xaa8844,  2, 'Gold Colored Box'),
 ];
-```
-
-and set the CSS so these don't wrap
-
-```css
-#labels>div {
+</pre>
+<p>and set the CSS so these don't wrap</p>
+<pre class="prettyprint showlinemods notranslate lang-css" translate="no">#labels&gt;div {
 +  white-space: nowrap;
-```
-
-Then we can run into this issue
-
-<div class="threejs_center"><img src="resources/images/label-sorting-issue.png" style="width: 401px;"></div>
-
-You can see above the purple box is in the back but its label is in front of the aqua box.
-
-We can fix this by setting the `zIndex` of each element. The projected position has a `z` value
-that goes from -1 in front to positive 1 in back. `zIndex` is required to be an integer and goes the
-opposite direction meaning for `zIndex` greater values are in front so the following code should work.
-
-```js
-// convert the normalized position to CSS coordinates
+</pre>
+<p>Then we can run into this issue</p>
+<div class="threejs_center"><img src="../resources/images/label-sorting-issue.png" style="width: 401px;"></div>
+
+<p>You can see above the purple box is in the back but its label is in front of the aqua box.</p>
+<p>We can fix this by setting the <code class="notranslate" translate="no">zIndex</code> of each element. The projected position has a <code class="notranslate" translate="no">z</code> value
+that goes from -1 in front to positive 1 in back. <code class="notranslate" translate="no">zIndex</code> is required to be an integer and goes the
+opposite direction meaning for <code class="notranslate" translate="no">zIndex</code> greater values are in front so the following code should work.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">// convert the normalized position to CSS coordinates
 const x = (tempV.x *  .5 + .5) * canvas.clientWidth;
 const y = (tempV.y * -.5 + .5) * canvas.clientHeight;
 
@@ -345,15 +313,12 @@ elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
 
 +// set the zIndex for sorting
 +elem.style.zIndex = (-tempV.z * .5 + .5) * 100000 | 0;
-```
-
-Because of the way the projected z value works we need to pick a large number to spread out the values
+</pre>
+<p>Because of the way the projected z value works we need to pick a large number to spread out the values
 otherwise many will have the same value. To make sure the labels don't overlap with other parts of
-the page we can tell the browser to create a new [stacking context](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context)
-by setting the `z-index` of the container of the labels
-
-```css
-#labels {
+the page we can tell the browser to create a new <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context">stacking context</a>
+by setting the <code class="notranslate" translate="no">z-index</code> of the container of the labels</p>
+<pre class="prettyprint showlinemods notranslate lang-css" translate="no">#labels {
   position: absolute;  /* let us position ourself inside the container */
 +  z-index: 0;          /* make a new stacking context so children don't sort with rest of page */
   left: 0;             /* make our position the top left of the container */
@@ -361,29 +326,26 @@ by setting the `z-index` of the container of the labels
   color: white;
   z-index: 0;
 }
-```
-
-and now the labels should always be in the correct order.
-
-{{{example url="../threejs-align-html-to-3d-w-sorting.html" }}}
-
-While we're at it let's do one more example to show one more issue.
-Let's draw a globe like Google Maps and label the countries.
+</pre>
+<p>and now the labels should always be in the correct order.</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/align-html-to-3d-w-sorting.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/align-html-to-3d-w-sorting.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-I found [this data](http://thematicmapping.org/downloads/world_borders.php)
+<p></p>
+<p>While we're at it let's do one more example to show one more issue.
+Let's draw a globe like Google Maps and label the countries.</p>
+<p>I found <a href="http://thematicmapping.org/downloads/world_borders.php">this data</a>
 which contains the borders of countries. It's licensed as
-[CC-BY-SA](http://creativecommons.org/licenses/by-sa/3.0/).
-
-I [wrote some code](https://github.com/gfxfundamentals/threejsfundamentals/blob/master/threejs/lessons/tools/geo-picking/)
+<a href="http://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>.</p>
+<p>I <a href="https://github.com/mrdoob/three.js/blob/master/manual/resources/tools/geo-picking/">wrote some code</a>
 to load the data, and generate country outlines and some JSON data with the names
-of the countries and their locations.
+of the countries and their locations.</p>
+<div class="threejs_center"><img src="../examples/resources/data/world/country-outlines-4k.png" style="background: black; width: 700px"></div>
 
-<div class="threejs_center"><img src="../resources/data/world/country-outlines-4k.png" style="background: black; width: 700px"></div>
-
-The JSON data is an array of entries something like this
-
-```json
-[
+<p>The JSON data is an array of entries something like this</p>
+<pre class="prettyprint showlinemods notranslate lang-json" translate="no">[
   {
     "name": "Algeria",
     "min": [
@@ -402,40 +364,29 @@ The JSON data is an array of entries something like this
     }
   },
   ...
-```
-
-where min, max, lat, lon, are all in latitude and longitude degrees.
-
-Let's load it up. The code is based on the examples from [optimizing lots of
-objects](threejs-optimize-lots-of-objects.html) though we are not drawing lots
-of objects we'll be using the same solutions for [rendering on
-demand](threejs-rendering-on-demand.html).
-
-The first thing is to make a sphere and use the outline texture.
-
-```js
-{
+</pre>
+<p>where min, max, lat, lon, are all in latitude and longitude degrees.</p>
+<p>Let's load it up. The code is based on the examples from <a href="optimize-lots-of-objects.html">optimizing lots of
+objects</a> though we are not drawing lots
+of objects we'll be using the same solutions for <a href="rendering-on-demand.html">rendering on
+demand</a>.</p>
+<p>The first thing is to make a sphere and use the outline texture.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
   const loader = new THREE.TextureLoader();
   const texture = loader.load('resources/data/world/country-outlines-4k.png', render);
   const geometry = new THREE.SphereGeometry(1, 64, 32);
   const material = new THREE.MeshBasicMaterial({map: texture});
   scene.add(new THREE.Mesh(geometry, material));
 }
-```
-
-Then let's load the JSON file by first making a loader
-
-```js
-async function loadJSON(url) {
+</pre>
+<p>Then let's load the JSON file by first making a loader</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">async function loadJSON(url) {
   const req = await fetch(url);
   return req.json();
 }
-```
-
-and then calling it
-
-```js
-let countryInfos;
+</pre>
+<p>and then calling it</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">let countryInfos;
 async function loadCountryData() {
   countryInfos = await loadJSON('resources/data/world/country-info.json');
      ...
@@ -443,17 +394,13 @@ async function loadCountryData() {
   requestRenderIfNotRequested();
 }
 loadCountryData();
-```
-
-Now let's use that data to generate and place the labels.
-
-In the article on [optimizing lots of objects](threejs-optimize-lots-of-objects.html)
+</pre>
+<p>Now let's use that data to generate and place the labels.</p>
+<p>In the article on <a href="optimize-lots-of-objects.html">optimizing lots of objects</a>
 we had setup a small scene graph of helper objects to make it easy to 
 compute latitude and longitude positions on our globe. See that article 
-for an explanation of how they work.
-
-```js
-const lonFudge = Math.PI * 1.5;
+for an explanation of how they work.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const lonFudge = Math.PI * 1.5;
 const latFudge = Math.PI;
 // these helpers will make it easy to position the boxes
 // We can rotate the lon helper on its Y axis to the longitude
@@ -465,12 +412,9 @@ lonHelper.add(latHelper);
 const positionHelper = new THREE.Object3D();
 positionHelper.position.z = 1;
 latHelper.add(positionHelper);
-```
-
-We'll use that to compute a position for each label
-
-```js
-const labelParentElem = document.querySelector('#labels');
+</pre>
+<p>We'll use that to compute a position for each label</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const labelParentElem = document.querySelector('#labels');
 for (const countryInfo of countryInfos) {
   const {lat, lon, name} = countryInfo;
 
@@ -489,19 +433,15 @@ for (const countryInfo of countryInfos) {
   elem.textContent = name;
   labelParentElem.appendChild(elem);
   countryInfo.elem = elem;
-```
-
-The code above looks very similar to the code we wrote for making cube labels
-making an element per label. When we're done we have an array, `countryInfos`,
-with one entry for each country to which we've added an `elem` property for
-the label element for that country and a `position` with its position on the
-globe.
-
-Just like we did for the cubes we need to update the position of the
-labels and render time.
-
-```js
-const tempV = new THREE.Vector3();
+</pre>
+<p>The code above looks very similar to the code we wrote for making cube labels
+making an element per label. When we're done we have an array, <code class="notranslate" translate="no">countryInfos</code>,
+with one entry for each country to which we've added an <code class="notranslate" translate="no">elem</code> property for
+the label element for that country and a <code class="notranslate" translate="no">position</code> with its position on the
+globe.</p>
+<p>Just like we did for the cubes we need to update the position of the
+labels and render time.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const tempV = new THREE.Vector3();
 
 function updateLabels() {
   // exit if we have not yet loaded the JSON file
@@ -529,16 +469,12 @@ function updateLabels() {
     elem.style.zIndex = (-tempV.z * .5 + .5) * 100000 | 0;
   }
 }
-```
-
-You can see the code above is substantially similar to the cube example before.
+</pre>
+<p>You can see the code above is substantially similar to the cube example before.
 The only major difference is we pre-computed the label positions at init time.
-We can do this because the globe never moves. Only our camera moves.
-
-Lastly we need to call `updateLabels` in our render loop
-
-```js
-function render() {
+We can do this because the globe never moves. Only our camera moves.</p>
+<p>Lastly we need to call <code class="notranslate" translate="no">updateLabels</code> in our render loop</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function render() {
   renderRequested = false;
 
   if (resizeRendererToDisplaySize(renderer)) {
@@ -553,29 +489,29 @@ function render() {
 
   renderer.render(scene, camera);
 }
-```
-
-And this is what we get
-
-{{{example url="../threejs-align-html-elements-to-3d-globe-too-many-labels.html" }}}
-
-That is way too many labels!
-
-We have 2 problems.
-
-1. Labels facing away from us are showing up.
-
-2. There are too many labels.
+</pre>
+<p>And this is what we get</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/align-html-elements-to-3d-globe-too-many-labels.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/align-html-elements-to-3d-globe-too-many-labels.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-For issue #1 we can't really use the `RayCaster` like we did above as there is
+<p></p>
+<p>That is way too many labels!</p>
+<p>We have 2 problems.</p>
+<ol>
+<li><p>Labels facing away from us are showing up.</p>
+</li>
+<li><p>There are too many labels.</p>
+</li>
+</ol>
+<p>For issue #1 we can't really use the <code class="notranslate" translate="no">RayCaster</code> like we did above as there is
 nothing to intersect except the sphere. Instead what we can do is check if that
 particular country is facing away from us or not. This works because the label
 positions are around a sphere. In fact we're using a unit sphere, a sphere with
 a radius of 1.0. That means the positions are already unit directions making
-the math relatively easy.
-
-```js
-const tempV = new THREE.Vector3();
+the math relatively easy.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const tempV = new THREE.Vector3();
 +const cameraToPoint = new THREE.Vector3();
 +const cameraPosition = new THREE.Vector3();
 +const normalMatrix = new THREE.Matrix3();
@@ -608,11 +544,11 @@ function updateLabels() {
 +    // on the globe with the direction from the camera to that point.
 +    // 1 = facing directly towards the camera
 +    // 0 = exactly on tangent of the sphere from the camera
-+    // < 0 = facing away
++    // &lt; 0 = facing away
 +    const dot = tempV.dot(cameraToPoint);
 +
 +    // if the orientation is not facing us hide it.
-+    if (dot < minVisibleDot) {
++    if (dot &lt; minVisibleDot) {
 +      elem.style.display = 'none';
 +      continue;
 +    }
@@ -637,40 +573,34 @@ function updateLabels() {
     elem.style.zIndex = (-tempV.z * .5 + .5) * 100000 | 0;
   }
 }
-```
-
-Above we use the positions as a direction and get that direction relative to the
+</pre>
+<p>Above we use the positions as a direction and get that direction relative to the
 camera. Then we get the camera relative direction from the camera to that
-position on the globe and take the *dot product*. The dot product returns the cosine
+position on the globe and take the <em>dot product</em>. The dot product returns the cosine
 of the angle between the to vectors. This gives us a value from -1
 to +1 where -1 means the label is facing the camera, 0 means the label is directly
 on the edge of the sphere relative to the camera, and anything greater than zero is
-behind. We then use that value to show or hide the element.
-
+behind. We then use that value to show or hide the element.</p>
 <div class="spread">
   <div>
     <div data-diagram="dotProduct" style="height: 400px"></div>
   </div>
 </div>
 
-In the diagram above we can see the dot product of the direction the label is
+<p>In the diagram above we can see the dot product of the direction the label is
 facing to direction from the camera to that position. If you rotate the
 direction you'll see the dot product is -1.0 when the direction is directly
 facing the camera, it's 0.0 when exactly on the tangent of the sphere relative
 to the camera or to put it another way it's 0 when the 2 vectors are
 perpendicular to each other, 90 degrees It's greater than zero with the label is
-behind the sphere.
-
-For issue #2, too many labels we need some way to decide which labels
+behind the sphere.</p>
+<p>For issue #2, too many labels we need some way to decide which labels
 to show. One way would be to only show labels for large countries.
 The data we're loading contains min and max values for the area a
 country covers. From that we can compute an area and then use that
-area to decide whether or not to display the country.
-
-At init time let's compute the area
-
-```js
-const labelParentElem = document.querySelector('#labels');
+area to decide whether or not to display the country.</p>
+<p>At init time let's compute the area</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const labelParentElem = document.querySelector('#labels');
 for (const countryInfo of countryInfos) {
   const {lat, lon, min, max, name} = countryInfo;
 
@@ -696,13 +626,10 @@ for (const countryInfo of countryInfos) {
   labelParentElem.appendChild(elem);
   countryInfo.elem = elem;
 }
-```
-
-Then at render time let's use the area to decide to display the label
-or not
-
-```js
-+const large = 20 * 20;
+</pre>
+<p>Then at render time let's use the area to decide to display the label
+or not</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">+const large = 20 * 20;
 const maxVisibleDot = 0.2;
 // get a matrix that represents a relative orientation of the camera
 normalMatrix.getNormalMatrix(camera.matrixWorldInverse);
@@ -712,25 +639,20 @@ for (const countryInfo of countryInfos) {
 -  const {position, elem} = countryInfo;
 +  const {position, elem, area} = countryInfo;
 +  // large enough?
-+  if (area < large) {
++  if (area &lt; large) {
 +    elem.style.display = 'none';
 +    continue;
 +  }
 
   ...
-```
-
-Finally, since I'm not sure what good values are for these settings lets
-add a GUI so we can play with them
-
-```js
-import * as THREE from './resources/three/r132/build/three.module.js';
-import {OrbitControls} from './resources/threejs/r132/examples/jsm/controls/OrbitControls.js';
-+import {GUI} from '../3rdparty/dat.gui.module.js';
-```
-
-```js
-+const settings = {
+</pre>
+<p>Finally, since I'm not sure what good values are for these settings lets
+add a GUI so we can play with them</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">import * as THREE from '/build/three.module.js';
+import {OrbitControls} from '/examples/jsm/controls/OrbitControls.js';
++import {GUI} from '/examples/jsm/libs/lil-gui.module.min.js';
+</pre>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">+const settings = {
 +  minArea: 20,
 +  maxVisibleDot: -0.2,
 +};
@@ -755,33 +677,43 @@ function updateLabels() {
     ...
 
     // if the orientation is not facing us hide it.
--    if (dot > maxVisibleDot) {
-+    if (dot > settings.maxVisibleDot) {
+-    if (dot &gt; maxVisibleDot) {
++    if (dot &gt; settings.maxVisibleDot) {
       elem.style.display = 'none';
       continue;
     }
-```
-
-and here's the result
-
-{{{example url="../threejs-align-html-elements-to-3d-globe.html" }}}
-
-You can see as you rotate the earth labels that go behind disappear.
-Adjust the `minVisibleDot` to see the cutoff change.
-You can also adjust the `minArea` value to see larger or smaller countries
-appear.
+</pre>
+<p>and here's the result</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/align-html-elements-to-3d-globe.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/align-html-elements-to-3d-globe.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-The more I worked on this the more I realized just how much
+<p></p>
+<p>You can see as you rotate the earth labels that go behind disappear.
+Adjust the <code class="notranslate" translate="no">minVisibleDot</code> to see the cutoff change.
+You can also adjust the <code class="notranslate" translate="no">minArea</code> value to see larger or smaller countries
+appear.</p>
+<p>The more I worked on this the more I realized just how much
 work is put into Google Maps. They have also have to decide which labels to
 show. I'm pretty sure they use all kinds of criteria. For example your current
 location, your default language setting, your account settings if you have an
 account, they probably use population or popularity, they might give priority
-to the countries in the center of the view, etc ... Lots to think about.
+to the countries in the center of the view, etc ... Lots to think about.</p>
+<p>In any case I hope these examples gave you some idea of how to align HTML
+elements with your 3D. A few things I might change.</p>
+<p>Next up let's make it so you can <a href="indexed-textures.html">pick and highlight a country</a>.</p>
+<p><link rel="stylesheet" href="../resources/threejs-align-html-elements-to-3d.css"></p>
+<script type="module" src="../resources/threejs-align-html-elements-to-3d.js"></script>
+
+        </div>
+      </div>
+    </div>
+  
+  <script src="/manual/resources/prettify.js"></script>
+  <script src="/manual/resources/lesson.js"></script>
+
 
-In any case I hope these examples gave you some idea of how to align HTML
-elements with your 3D. A few things I might change.
 
-Next up let's make it so you can [pick and highlight a country](threejs-indexed-textures.html).
 
-<link rel="stylesheet" href="resources/threejs-align-html-elements-to-3d.css">
-<script type="module" src="resources/threejs-align-html-elements-to-3d.js"></script>
+</body></html>

+ 140 - 132
manual/en/backgrounds.html

@@ -1,17 +1,30 @@
-Title: Three.js Backgrounds and Skyboxes
-Description: How to add a background in THREE.js
-TOC: Add a Background or Skybox
-
-Most of the articles here use a solid color for a background.
-
-Adding as static background can be as simple as setting some CSS. Taking
-an example from [the article on making THREE.js responsive](threejs-responsive.html)
-we only need to change 2 things.
-
-We need to add some CSS to our canvas to set its background to an image
-
-```html
-<style>
+<!DOCTYPE html><html lang="en"><head>
+    <meta charset="utf-8">
+    <title>Backgrounds and Skyboxes</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 – Backgrounds and Skyboxes">
+    <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">
+  </head>
+  <body>
+    <div class="container">
+      <div class="lesson-title">
+        <h1>Backgrounds and Skyboxes</h1>
+      </div>
+      <div class="lesson">
+        <div class="lesson-main">
+          <p>Most of the articles here use a solid color for a background.</p>
+<p>Adding as static background can be as simple as setting some CSS. Taking
+an example from <a href="responsive.html">the article on making THREE.js responsive</a>
+we only need to change 2 things.</p>
+<p>We need to add some CSS to our canvas to set its background to an image</p>
+<pre class="prettyprint showlinemods notranslate lang-html" translate="no">&lt;style&gt;
 body {
     margin: 0;
 }
@@ -22,50 +35,45 @@ body {
 +    background: url(resources/images/daikanyama.jpg) no-repeat center center;
 +    background-size: cover;
 }
-</style>
-```
-
-and we need to tell the `WebGLRenderer` to use `alpha` so places we are not
-drawing anything are transparent.
-
-```js
-function main() {
+&lt;/style&gt;
+</pre>
+<p>and we need to tell the <a href="/docs/#api/en/renderers/WebGLRenderer"><code class="notranslate" translate="no">WebGLRenderer</code></a> to use <code class="notranslate" translate="no">alpha</code> so places we are not
+drawing anything are transparent.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function main() {
   const canvas = document.querySelector('#c');
 -  const renderer = new THREE.WebGLRenderer({canvas});
 +  const renderer = new THREE.WebGLRenderer({
 +    canvas,
 +    alpha: true,
 +  });
-```
-
-And we get a background.
-
-{{{example url="../threejs-background-css.html" }}}
-
-If we want the background to be able to be affected by [post processing
-effects](threejs-post-processing.html) then we need to draw the background using
-THREE.js.
-
-THREE.js makes this some what simple. We can just set the background of the scene to
-a texture.
+</pre>
+<p>And we get a background.</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/background-css.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/background-css.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-```js
-const loader = new THREE.TextureLoader();
+<p></p>
+<p>If we want the background to be able to be affected by <a href="post-processing.html">post processing
+effects</a> then we need to draw the background using
+THREE.js.</p>
+<p>THREE.js makes this some what simple. We can just set the background of the scene to
+a texture.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const loader = new THREE.TextureLoader();
 const bgTexture = loader.load('resources/images/daikanyama.jpg');
-scene.background = bgTexture; 
-```
-
-which gives us
-
-{{{example url="../threejs-background-scene-background.html" }}}
-
-This gets us a background image but its stretched to fit the screen.
-
-We can solve this issue by setting the `repeat` and `offset` properties of
-the texture to show only a portion of image.
+scene.background = bgTexture;
+</pre>
+<p>which gives us</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/background-scene-background.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/background-scene-background.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-```js
-function render(time) {
+<p></p>
+<p>This gets us a background image but its stretched to fit the screen.</p>
+<p>We can solve this issue by setting the <code class="notranslate" translate="no">repeat</code> and <code class="notranslate" translate="no">offset</code> properties of
+the texture to show only a portion of image.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function render(time) {
 
    ...
 
@@ -76,11 +84,11 @@ function render(time) {
 +  const imageAspect = bgTexture.image ? bgTexture.image.width / bgTexture.image.height : 1;
 +  const aspect = imageAspect / canvasAspect;
 +
-+  bgTexture.offset.x = aspect > 1 ? (1 - 1 / aspect) / 2 : 0;
-+  bgTexture.repeat.x = aspect > 1 ? 1 / aspect : 1;
++  bgTexture.offset.x = aspect &gt; 1 ? (1 - 1 / aspect) / 2 : 0;
++  bgTexture.repeat.x = aspect &gt; 1 ? 1 / aspect : 1;
 +
-+  bgTexture.offset.y = aspect > 1 ? 0 : (1 - aspect) / 2;
-+  bgTexture.repeat.y = aspect > 1 ? 1 : aspect;
++  bgTexture.offset.y = aspect &gt; 1 ? 0 : (1 - aspect) / 2;
++  bgTexture.repeat.y = aspect &gt; 1 ? 1 : aspect;
 
   ...
 
@@ -88,54 +96,50 @@ function render(time) {
 
   requestAnimationFrame(render);
 }
-```
-
-and now THREE.js drawing the background. There is no visible difference from
-the CSS version at the top but now if we used a [post processing
-effect](threejs-post-processing.html) the background would be affected too.
-
-{{{example url="../threejs-background-scene-background-fixed-aspect.html" }}}
+</pre>
+<p>and now THREE.js drawing the background. There is no visible difference from
+the CSS version at the top but now if we used a <a href="post-processing.html">post processing
+effect</a> the background would be affected too.</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/background-scene-background-fixed-aspect.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/background-scene-background-fixed-aspect.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-Of course a static background is not usually what we want in a 3D scene. Instead
-we usually want some kind of *skybox*. A skybox is just that, box with the sky
+<p></p>
+<p>Of course a static background is not usually what we want in a 3D scene. Instead
+we usually want some kind of <em>skybox</em>. A skybox is just that, box with the sky
 draw on it. We put the camera inside the box and it looks like there is a sky in
-the background.
-
-The most common way to implement a skybox is to make a cube, apply a texture to
+the background.</p>
+<p>The most common way to implement a skybox is to make a cube, apply a texture to
 it, draw it from the inside. On each side of the cube put a texture (using
 texture coordinates) that looks like some image of the horizon. It's also often
 common to use a sky sphere or a sky dome with a texture drawn on it. You can
 probably figure that one out on your own. Just make a cube or sphere, 
-[apply a texture](threejs-textures.html), mark it as `THREE.BackSide` so we 
+<a href="textures.html">apply a texture</a>, mark it as <code class="notranslate" translate="no">THREE.BackSide</code> so we 
 render the inside instead of the outside, and either put it in your scene directly 
 or like above, or, make 2 scenes, a special one to draw the skybox/sphere/dome and the
-normal one to draw everything else. You'd use your normal `PerspectiveCamera` to
-draw. No need for the `OrthographicCamera`.
-
-Another solution is to use a *Cubemap*. A Cubemap is a special kind of texture
+normal one to draw everything else. You'd use your normal <a href="/docs/#api/en/cameras/PerspectiveCamera"><code class="notranslate" translate="no">PerspectiveCamera</code></a> to
+draw. No need for the <a href="/docs/#api/en/cameras/OrthographicCamera"><code class="notranslate" translate="no">OrthographicCamera</code></a>.</p>
+<p>Another solution is to use a <em>Cubemap</em>. A Cubemap is a special kind of texture
 that has 6 sides, the sides of a cube. Instead of using standard texture
 coordinates it uses a direction from the center pointing outward to decide where
-to get a color.
-
-Here are the 6 images of a cubemap from the computer history museum in Mountain
-View, California.
-
+to get a color.</p>
+<p>Here are the 6 images of a cubemap from the computer history museum in Mountain
+View, California.</p>
 <div class="threejs_center">
-  <img src="../resources/images/cubemaps/computer-history-museum/pos-x.jpg" style="width: 200px" class="border">
-  <img src="../resources/images/cubemaps/computer-history-museum/neg-x.jpg" style="width: 200px" class="border">
-  <img src="../resources/images/cubemaps/computer-history-museum/pos-y.jpg" style="width: 200px" class="border">
+  <img src="../examples/resources/images/cubemaps/computer-history-museum/pos-x.jpg" style="width: 200px" class="border">
+  <img src="../examples/resources/images/cubemaps/computer-history-museum/neg-x.jpg" style="width: 200px" class="border">
+  <img src="../examples/resources/images/cubemaps/computer-history-museum/pos-y.jpg" style="width: 200px" class="border">
 </div>
 <div class="threejs_center">
-  <img src="../resources/images/cubemaps/computer-history-museum/neg-y.jpg" style="width: 200px" class="border">
-  <img src="../resources/images/cubemaps/computer-history-museum/pos-z.jpg" style="width: 200px" class="border">
-  <img src="../resources/images/cubemaps/computer-history-museum/neg-z.jpg" style="width: 200px" class="border">
+  <img src="../examples/resources/images/cubemaps/computer-history-museum/neg-y.jpg" style="width: 200px" class="border">
+  <img src="../examples/resources/images/cubemaps/computer-history-museum/pos-z.jpg" style="width: 200px" class="border">
+  <img src="../examples/resources/images/cubemaps/computer-history-museum/neg-z.jpg" style="width: 200px" class="border">
 </div>
 
-To use them we use `CubeTextureLoader` to load them and then use that as a the
-scene's background.
-
-```js
-{
+<p>To use them we use <a href="/docs/#api/en/loaders/CubeTextureLoader"><code class="notranslate" translate="no">CubeTextureLoader</code></a> to load them and then use that as a the
+scene's background.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
   const loader = new THREE.CubeTextureLoader();
   const texture = loader.load([
     'resources/images/cubemaps/computer-history-museum/pos-x.jpg',
@@ -147,12 +151,9 @@ scene's background.
   ]);
   scene.background = texture;
 }
-```
-
-At render time we don't need to adjust the texture like we did above
-
-```js
-function render(time) {
+</pre>
+<p>At render time we don't need to adjust the texture like we did above</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function render(time) {
 
    ...
 
@@ -163,11 +164,11 @@ function render(time) {
 -  const imageAspect = bgTexture.image ? bgTexture.image.width / bgTexture.image.height : 1;
 -  const aspect = imageAspect / canvasAspect;
 -
--  bgTexture.offset.x = aspect > 1 ? (1 - 1 / aspect) / 2 : 0;
--  bgTexture.repeat.x = aspect > 1 ? 1 / aspect : 1;
+-  bgTexture.offset.x = aspect &gt; 1 ? (1 - 1 / aspect) / 2 : 0;
+-  bgTexture.repeat.x = aspect &gt; 1 ? 1 / aspect : 1;
 -
--  bgTexture.offset.y = aspect > 1 ? 0 : (1 - aspect) / 2;
--  bgTexture.repeat.y = aspect > 1 ? 1 : aspect;
+-  bgTexture.offset.y = aspect &gt; 1 ? 0 : (1 - aspect) / 2;
+-  bgTexture.repeat.y = aspect &gt; 1 ? 1 : aspect;
 
   ...
 
@@ -175,16 +176,11 @@ function render(time) {
 
   requestAnimationFrame(render);
 }
-```
-
-Let's add some controls in so we can rotate the camera.
-
-```js
-import {OrbitControls} from './resources/threejs/r132/examples/jsm/controls/OrbitControls.js';
-```
-
-```js
-const fov = 75;
+</pre>
+<p>Let's add some controls in so we can rotate the camera.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">import {OrbitControls} from '/examples/jsm/controls/OrbitControls.js';
+</pre>
+<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;
@@ -196,29 +192,27 @@ const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
 +const controls = new OrbitControls(camera, canvas);
 +controls.target.set(0, 0, 0);
 +controls.update();
-```
-
-and try it out. Drag on the example to rotate the camera and see the cubemap
-surrounds us.
-
-{{{example url="../threejs-background-cubemap.html" }}}
-
-Another option is to use an Equirectangular map. This is the kind of picture a
-[360 camera](https://google.com/search?q=360+camera) takes.
-
-[Here's one](https://hdrihaven.com/hdri/?h=tears_of_steel_bridge) I found from
-[this site](https://hdrihaven.com).
+</pre>
+<p>and try it out. Drag on the example to rotate the camera and see the cubemap
+surrounds us.</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/background-cubemap.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/background-cubemap.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-<div class="threejs_center"><img src="../resources/images/equirectangularmaps/tears_of_steel_bridge_2k.jpg" style="width: 600px"></div>
+<p></p>
+<p>Another option is to use an Equirectangular map. This is the kind of picture a
+<a href="https://google.com/search?q=360+camera">360 camera</a> takes.</p>
+<p><a href="https://hdrihaven.com/hdri/?h=tears_of_steel_bridge">Here's one</a> I found from
+<a href="https://hdrihaven.com">this site</a>.</p>
+<div class="threejs_center"><img src="../examples/resources/images/equirectangularmaps/tears_of_steel_bridge_2k.jpg" style="width: 600px"></div>
 
-It's not much different. First we load the equirectangular image as a texture
-and then, in the callback after it has loaded, we can call `WebGLCubeRenderTarget.fromEquirectangularTexture`
+<p>It's not much different. First we load the equirectangular image as a texture
+and then, in the callback after it has loaded, we can call <a href="/docs/#api/en/renderers/WebGLCubeRenderTarget.fromEquirectangularTexture"><code class="notranslate" translate="no">WebGLCubeRenderTarget.fromEquirectangularTexture</code></a>
 which will generate a cubemap from the equirectangular texture for us.
-We pass in the size we want the cubemap to be to `WebGLCubeRenderTarget`.
-Passing in the height of the equirectangular image seems like a good bet.
-
-```js
-{
+We pass in the size we want the cubemap to be to <a href="/docs/#api/en/renderers/WebGLCubeRenderTarget"><code class="notranslate" translate="no">WebGLCubeRenderTarget</code></a>.
+Passing in the height of the equirectangular image seems like a good bet.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
 -  const loader = new THREE.CubeTextureLoader();
 -  const texture = loader.load([
 -    'resources/images/cubemaps/computer-history-museum/pos-x.jpg',
@@ -232,17 +226,31 @@ Passing in the height of the equirectangular image seems like a good bet.
 +  const loader = new THREE.TextureLoader();
 +  const texture = loader.load(
 +    'resources/images/equirectangularmaps/tears_of_steel_bridge_2k.jpg',
-+    () => {
++    () =&gt; {
 +      const rt = new THREE.WebGLCubeRenderTarget(texture.image.height);
 +      rt.fromEquirectangularTexture(renderer, texture);
 +      scene.background = rt.texture;
 +    });
 }
-```
+</pre>
+<p>And that's all there is to it.</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/background-equirectangularmap.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/background-equirectangularmap.html" target="_blank">click here to open in a separate window</a>
+</div>
+
+<p></p>
+<p>Rather than do it at load time you can also convert an equirectangular image
+to a cubemap beforehand. <a href="https://matheowis.github.io/HDRI-to-CubeMap/">Here's a site that will do it for you</a>.</p>
+
+        </div>
+      </div>
+    </div>
+  
+  <script src="/manual/resources/prettify.js"></script>
+  <script src="/manual/resources/lesson.js"></script>
+
 
-And that's all there is to it.
 
-{{{example url="../threejs-background-equirectangularmap.html" }}}
 
-Rather than do it at load time you can also convert an equirectangular image
-to a cubemap beforehand. [Here's a site that will do it for you](https://matheowis.github.io/HDRI-to-CubeMap/).
+</body></html>

+ 143 - 157
manual/en/billboards.html

@@ -1,17 +1,31 @@
-Title: Three.js Billboards
-Description: How to make things always face the camera.
-TOC: Billboards and Facades
-
-In [a previous article](threejs-canvas-textures.html) we used a `CanvasTexture`
+<!DOCTYPE html><html lang="en"><head>
+    <meta charset="utf-8">
+    <title>Billboards</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 – Billboards">
+    <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">
+  </head>
+  <body>
+    <div class="container">
+      <div class="lesson-title">
+        <h1>Billboards</h1>
+      </div>
+      <div class="lesson">
+        <div class="lesson-main">
+          <p>In <a href="canvas-textures.html">a previous article</a> we used a <a href="/docs/#api/en/textures/CanvasTexture"><code class="notranslate" translate="no">CanvasTexture</code></a>
 to make labels / badges on characters. Sometimes we'd like to make labels or
-other things that always face the camera. Three.js provides the `Sprite` and
-`SpriteMaterial` to make this happen.
-
-Let's change the badge example from [the article on canvas textures](threejs-canvas-textures.html)
-to use `Sprite` and `SpriteMaterial`
-
-```js
-function makePerson(x, labelWidth, size, name, color) {
+other things that always face the camera. Three.js provides the <a href="/docs/#api/en/objects/Sprite"><code class="notranslate" translate="no">Sprite</code></a> and
+<a href="/docs/#api/en/materials/SpriteMaterial"><code class="notranslate" translate="no">SpriteMaterial</code></a> to make this happen.</p>
+<p>Let's change the badge example from <a href="canvas-textures.html">the article on canvas textures</a>
+to use <a href="/docs/#api/en/objects/Sprite"><code class="notranslate" translate="no">Sprite</code></a> and <a href="/docs/#api/en/materials/SpriteMaterial"><code class="notranslate" translate="no">SpriteMaterial</code></a></p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function makePerson(x, labelWidth, size, name, color) {
   const canvas = makeLabelCanvas(labelWidth, size, name);
   const texture = new THREE.CanvasTexture(canvas);
   // because our canvas is likely not a power of 2
@@ -43,22 +57,20 @@ function makePerson(x, labelWidth, size, name, color) {
   root.add(label);
   label.position.y = bodyHeight * 4 / 5;
   label.position.z = bodyRadiusTop * 1.01;
-
-```
-
-and the labels now always face the camera
-
-{{{example url="../threejs-billboard-labels-w-sprites.html" }}}
-
-One problem is from certain angles the labels now intersect the
-characters. 
-
-<div class="threejs_center"><img src="resources/images/billboard-label-z-issue.png" style="width: 455px;"></div>
-
-We can move the position of the labels to fix.
-
-```js
-+// if units are meters then 0.01 here makes size
+</pre>
+<p>and the labels now always face the camera</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/billboard-labels-w-sprites.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/billboard-labels-w-sprites.html" target="_blank">click here to open in a separate window</a>
+</div>
+
+<p></p>
+<p>One problem is from certain angles the labels now intersect the
+characters. </p>
+<div class="threejs_center"><img src="../resources/images/billboard-label-z-issue.png" style="width: 455px;"></div>
+
+<p>We can move the position of the labels to fix.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">+// if units are meters then 0.01 here makes size
 +// of the label into centimeters.
 +const labelBaseScale = 0.01;
 const label = new THREE.Sprite(labelMaterial);
@@ -72,23 +84,21 @@ root.add(label);
 -const labelBaseScale = 0.01;
 label.scale.x = canvas.width  * labelBaseScale;
 label.scale.y = canvas.height * labelBaseScale;
-```
-
-{{{example url="../threejs-billboard-labels-w-sprites-adjust-height.html" }}}
-
-Another thing we can do with billboards is draw facades.
-
-Instead of drawing 3D objects we draw 2D planes with an image
-of 3D objects. This is often faster than drawing 3D objects.
-
-For example let's make a scene with grid of trees. We'll make each
-tree from a cylinder for the base and a cone for the top.
-
-First we make the cone and cylinder geometry and materials that
-all the trees will share
-
-```js
-const trunkRadius = .2;
+</pre>
+<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/billboard-labels-w-sprites-adjust-height.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/billboard-labels-w-sprites-adjust-height.html" target="_blank">click here to open in a separate window</a>
+</div>
+
+<p></p>
+<p>Another thing we can do with billboards is draw facades.</p>
+<p>Instead of drawing 3D objects we draw 2D planes with an image
+of 3D objects. This is often faster than drawing 3D objects.</p>
+<p>For example let's make a scene with grid of trees. We'll make each
+tree from a cylinder for the base and a cone for the top.</p>
+<p>First we make the cone and cylinder geometry and materials that
+all the trees will share</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const trunkRadius = .2;
 const trunkHeight = 1;
 const trunkRadialSegments = 12;
 const trunkGeometry = new THREE.CylinderGeometry(
@@ -102,13 +112,10 @@ const topGeometry = new THREE.ConeGeometry(
 
 const trunkMaterial = new THREE.MeshPhongMaterial({color: 'brown'});
 const topMaterial = new THREE.MeshPhongMaterial({color: 'green'});
-```
-
-Then we'll make a function that makes a `Mesh` each for the trunk and top
-of a tree and parents both to an `Object3D`.
-
-```js
-function makeTree(x, z) {
+</pre>
+<p>Then we'll make a function that makes a <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a> each for the trunk and top
+of a tree and parents both to an <a href="/docs/#api/en/core/Object3D"><code class="notranslate" translate="no">Object3D</code></a>.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function makeTree(x, z) {
   const root = new THREE.Object3D();
   const trunk = new THREE.Mesh(trunkGeometry, trunkMaterial);
   trunk.position.y = trunkHeight / 2;
@@ -123,22 +130,16 @@ function makeTree(x, z) {
 
   return root;
 }
-```
-
-Then we'll make a loop to place a grid of trees.
-
-```js
-for (let z = -50; z <= 50; z += 10) {
-  for (let x = -50; x <= 50; x += 10) {
+</pre>
+<p>Then we'll make a loop to place a grid of trees.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">for (let z = -50; z &lt;= 50; z += 10) {
+  for (let x = -50; x &lt;= 50; x += 10) {
     makeTree(x, z);
   }
 }
-```
-
-Let's also add a ground plane while we're at it
-
-```js
-// add ground
+</pre>
+<p>Let's also add a ground plane while we're at it</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">// add ground
 {
   const size = 400;
   const geometry = new THREE.PlaneGeometry(size, size);
@@ -147,37 +148,31 @@ Let's also add a ground plane while we're at it
   mesh.rotation.x = Math.PI * -0.5;
   scene.add(mesh);
 }
-```
-
-and change the background to light blue
-
-```js
-const scene = new THREE.Scene();
+</pre>
+<p>and change the background to light blue</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const scene = new THREE.Scene();
 -scene.background = new THREE.Color('white');
 +scene.background = new THREE.Color('lightblue');
-```
-
-and we get a grid of trees
-
-{{{example url="../threejs-billboard-trees-no-billboards.html" }}}
-
-There are 11x11 or 121 trees. Each tree is made from a 12 polygon
+</pre>
+<p>and we get a grid of trees</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/billboard-trees-no-billboards.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/billboard-trees-no-billboards.html" target="_blank">click here to open in a separate window</a>
+</div>
+
+<p></p>
+<p>There are 11x11 or 121 trees. Each tree is made from a 12 polygon
 cone and a 48 polygon trunk so each tree is 60 polygons. 121 * 60
 is 7260 polygons. That's not that many but of course a more detailed
 3D tree might be 1000-3000 polygons. If they were 3000 polygons each
-then 121 trees would be 363000 polygons to draw.
-
-Using facades we can bring that number down.
-
-We could manually create a facade in some painting program but let's write 
-some code to try to generate one.
-
-Let's write some code to render an object to a texture
-using a `RenderTarget`. We covered rendering to a `RenderTarget`
-in [the article on render targets](threejs-rendertargets.html).
-
-```js
-function frameArea(sizeToFitOnScreen, boxSize, boxCenter, camera) {
+then 121 trees would be 363000 polygons to draw.</p>
+<p>Using facades we can bring that number down.</p>
+<p>We could manually create a facade in some painting program but let's write 
+some code to try to generate one.</p>
+<p>Let's write some code to render an object to a texture
+using a <code class="notranslate" translate="no">RenderTarget</code>. We covered rendering to a <code class="notranslate" translate="no">RenderTarget</code>
+in <a href="rendertargets.html">the article on render targets</a>.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function frameArea(sizeToFitOnScreen, boxSize, boxCenter, camera) {
   const halfSizeToFitOnScreen = sizeToFitOnScreen * 0.5;
   const halfFovY = THREE.MathUtils.degToRad(camera.fov * .5);
   const distance = halfSizeToFitOnScreen / Math.tan(halfFovY);
@@ -226,57 +221,40 @@ function makeSpriteTexture(textureSize, obj) {
     texture: rt.texture,
   };
 }
-```
-
-Some things to note about the code above:
-
-We're using the field of view (`fov`) defined above this code.
-
-We're computing a box that contains the tree the same way
-we did in [the article on loading a .obj file](threejs-load-obj.html)
-with a few minor changes.
-
-We call `frameArea` again adapted [the article on loading a .obj file](threejs-load-obj.html).
+</pre>
+<p>Some things to note about the code above:</p>
+<p>We're using the field of view (<code class="notranslate" translate="no">fov</code>) defined above this code.</p>
+<p>We're computing a box that contains the tree the same way
+we did in <a href="load-obj.html">the article on loading a .obj file</a>
+with a few minor changes.</p>
+<p>We call <code class="notranslate" translate="no">frameArea</code> again adapted <a href="load-obj.html">the article on loading a .obj file</a>.
 In this case we compute how far the camera needs to be away from the object
 given its field of view to contain the object. We then position the camera -z that distance
-from the center of the box that contains the object.
-
-We multiply the size we want to fit by 1.1 (`fudge`) to make sure the tree fits
+from the center of the box that contains the object.</p>
+<p>We multiply the size we want to fit by 1.1 (<code class="notranslate" translate="no">fudge</code>) to make sure the tree fits
 completely in the render target. The issue here is the size we're using to
 calculate if the object fits in the camera's view is not taking into account
 that the very edges of the object will end up dipping outside area we
 calculated. We could compute how to make 100% of the box fit but that would
-waste space as well so instead we just *fudge* it.
-
-Then we render to the render target and remove the object from
-the scene. 
-
-It's important to note we need the lights in the scene but we
-need to make sure nothing else is in the scene.
-
-We also need to not set a background color on the scene
-
-```js
-const scene = new THREE.Scene();
+waste space as well so instead we just <em>fudge</em> it.</p>
+<p>Then we render to the render target and remove the object from
+the scene. </p>
+<p>It's important to note we need the lights in the scene but we
+need to make sure nothing else is in the scene.</p>
+<p>We also need to not set a background color on the scene</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const scene = new THREE.Scene();
 -scene.background = new THREE.Color('lightblue');
-```
-
-Finally we've made the texture we return it and the position and scale we
-need to make the facade so that it will appear to be in the same place.
-
-We then make a tree and call this code and pass it in
-
-```js
-// make billboard texture
+</pre>
+<p>Finally we've made the texture we return it and the position and scale we
+need to make the facade so that it will appear to be in the same place.</p>
+<p>We then make a tree and call this code and pass it in</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">// make billboard texture
 const tree = makeTree(0, 0);
 const facadeSize = 64;
 const treeSpriteInfo = makeSpriteTexture(facadeSize, tree);
-```
-
-We can then make a grid of facades instead of a grid of tree models
-
-```js
-+function makeSprite(spriteInfo, x, z) {
+</pre>
+<p>We can then make a grid of facades instead of a grid of tree models</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">+function makeSprite(spriteInfo, x, z) {
 +  const {texture, offset, scale} = spriteInfo;
 +  const mat = new THREE.SpriteMaterial({
 +    map: texture,
@@ -291,38 +269,46 @@ We can then make a grid of facades instead of a grid of tree models
 +  sprite.scale.set(scale, scale, scale);
 +}
 
-for (let z = -50; z <= 50; z += 10) {
-  for (let x = -50; x <= 50; x += 10) {
+for (let z = -50; z &lt;= 50; z += 10) {
+  for (let x = -50; x &lt;= 50; x += 10) {
 -    makeTree(x, z);
 +    makeSprite(treeSpriteInfo, x, z);
   }
 }
-```
-
-In the code above we apply the offset and scale needed to position the facade so it
-appears the same place the original tree would have appeared.
-
-Now that we're done making the tree facade texture we can set the background again
-
-```js
-scene.background = new THREE.Color('lightblue');
-```
-
-and now we get a scene of tree facades
-
-{{{example url="../threejs-billboard-trees-static-billboards.html" }}}
-
-Compare to the trees models above and you can see it looks fairly similar.
+</pre>
+<p>In the code above we apply the offset and scale needed to position the facade so it
+appears the same place the original tree would have appeared.</p>
+<p>Now that we're done making the tree facade texture we can set the background again</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">scene.background = new THREE.Color('lightblue');
+</pre>
+<p>and now we get a scene of tree facades</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/billboard-trees-static-billboards.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/billboard-trees-static-billboards.html" target="_blank">click here to open in a separate window</a>
+</div>
+
+<p></p>
+<p>Compare to the trees models above and you can see it looks fairly similar.
 We used a low-res texture, just 64x64 pixels so the facades are blocky.
 You could increase the resolution. Often facades are used only in the far
 distance when they are fairly small so a low-res texture is enough and
 it saves on drawing detailed trees that are only a few pixels big when
-far away.
-
-Another issue is we are only viewing the tree from one side. This is often
+far away.</p>
+<p>Another issue is we are only viewing the tree from one side. This is often
 solved by rendering more facades, say from 8 directions around the object
 and then setting which facade to show based on which direction the camera
-is looking at the facade.
+is looking at the facade.</p>
+<p>Whether or not you use facades is up to you but hopefully this article
+gave you some ideas and suggested some solutions if you decide to use them.</p>
+
+        </div>
+      </div>
+    </div>
+  
+  <script src="/manual/resources/prettify.js"></script>
+  <script src="/manual/resources/lesson.js"></script>
+
+
+
 
-Whether or not you use facades is up to you but hopefully this article
-gave you some ideas and suggested some solutions if you decide to use them.
+</body></html>

+ 251 - 308
manual/en/cameras.html

@@ -1,22 +1,35 @@
-Title: Three.js Cameras
-Description: How to use Cameras in Three.js
-TOC: Cameras
-
-This article is one in a series of articles about three.js.
-The first article was [about fundamentals](threejs-fundamentals.html).
-If you haven't read that yet you might want to start there.
-
-Let's talk about cameras in three.js. We covered some of this in the [first article](threejs-fundamentals.html) but we'll cover it in more detail here.
-
-The most common camera in three.js and the one we've been using up to this point is
-the `PerspectiveCamera`. It gives a 3d view where things in the distance appear
-smaller than things up close.
-
-The `PerspectiveCamera` defines a *frustum*. [A *frustum* is a solid pyramid shape with
-the tip cut off](https://en.wikipedia.org/wiki/Frustum).
+<!DOCTYPE html><html lang="en"><head>
+    <meta charset="utf-8">
+    <title>Cameras</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 – Cameras">
+    <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">
+  </head>
+  <body>
+    <div class="container">
+      <div class="lesson-title">
+        <h1>Cameras</h1>
+      </div>
+      <div class="lesson">
+        <div class="lesson-main">
+          <p>This article is one in a series of articles about three.js.
+The first article was <a href="fundamentals.html">about fundamentals</a>.
+If you haven't read that yet you might want to start there.</p>
+<p>Let's talk about cameras in three.js. We covered some of this in the <a href="fundamentals.html">first article</a> but we'll cover it in more detail here.</p>
+<p>The most common camera in three.js and the one we've been using up to this point is
+the <a href="/docs/#api/en/cameras/PerspectiveCamera"><code class="notranslate" translate="no">PerspectiveCamera</code></a>. It gives a 3d view where things in the distance appear
+smaller than things up close.</p>
+<p>The <a href="/docs/#api/en/cameras/PerspectiveCamera"><code class="notranslate" translate="no">PerspectiveCamera</code></a> defines a <em>frustum</em>. <a href="https://en.wikipedia.org/wiki/Frustum">A <em>frustum</em> is a solid pyramid shape with
+the tip cut off</a>.
 By name of a solid I mean for example a cube, a cone, a sphere, a cylinder,
-and a frustum are all names of different kinds of solids.
-
+and a frustum are all names of different kinds of solids.</p>
 <div class="spread">
   <div><div data-diagram="shapeCube"></div><div>cube</div></div>
   <div><div data-diagram="shapeCone"></div><div>cone</div></div>
@@ -25,28 +38,22 @@ and a frustum are all names of different kinds of solids.
   <div><div data-diagram="shapeFrustum"></div><div>frustum</div></div>
 </div>
 
-I only point that out because I didn't know it for years. Some book or page would mention
-*frustum* and my eyes would glaze over. Understanding it's the name of a type of solid
-shape made those descriptions suddenly make more sense &#128517;
-
-A `PerspectiveCamera` defines its frustum based on 4 properties. `near` defines where the
-front of the frustum starts. `far` defines where it ends. `fov`, the field of view, defines
+<p>I only point that out because I didn't know it for years. Some book or page would mention
+<em>frustum</em> and my eyes would glaze over. Understanding it's the name of a type of solid
+shape made those descriptions suddenly make more sense 😅</p>
+<p>A <a href="/docs/#api/en/cameras/PerspectiveCamera"><code class="notranslate" translate="no">PerspectiveCamera</code></a> defines its frustum based on 4 properties. <code class="notranslate" translate="no">near</code> defines where the
+front of the frustum starts. <code class="notranslate" translate="no">far</code> defines where it ends. <code class="notranslate" translate="no">fov</code>, the field of view, defines
 how tall the front and back of the frustum are by computing the correct height to get
-the specified field of view at `near` units from the camera. The `aspect` defines how
+the specified field of view at <code class="notranslate" translate="no">near</code> units from the camera. The <code class="notranslate" translate="no">aspect</code> defines how
 wide the front and back of the frustum are. The width of the frustum is just the height
-multiplied by the aspect.
-
-<img src="resources/frustum-3d.svg" width="500" class="threejs_center"/>
-
-Let's use the scene from [the previous article](threejs-lights.html) that has a ground
-plane, a sphere, and a cube and make it so we can adjust the camera's settings.
-
-To do that we'll make a `MinMaxGUIHelper` for the `near` and `far` settings so `far`
-is always greater than `near`. It will have `min` and `max` properties that dat.GUI
-will adjust. When adjusted they'll set the 2 properties we specify.
-
-```js
-class MinMaxGUIHelper {
+multiplied by the aspect.</p>
+<p><img src="../resources/frustum-3d.svg" width="500" class="threejs_center"></p>
+<p>Let's use the scene from <a href="lights.html">the previous article</a> that has a ground
+plane, a sphere, and a cube and make it so we can adjust the camera's settings.</p>
+<p>To do that we'll make a <code class="notranslate" translate="no">MinMaxGUIHelper</code> for the <code class="notranslate" translate="no">near</code> and <code class="notranslate" translate="no">far</code> settings so <code class="notranslate" translate="no">far</code>
+is always greater than <code class="notranslate" translate="no">near</code>. It will have <code class="notranslate" translate="no">min</code> and <code class="notranslate" translate="no">max</code> properties that lil-gui
+will adjust. When adjusted they'll set the 2 properties we specify.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">class MinMaxGUIHelper {
   constructor(obj, minProp, maxProp, minDif) {
     this.obj = obj;
     this.minProp = minProp;
@@ -68,12 +75,9 @@ class MinMaxGUIHelper {
     this.min = this.min;  // this will call the min setter
   }
 }
-```
-
-Now we can setup our GUI like this
-
-```js
-function updateCamera() {
+</pre>
+<p>Now we can setup our GUI like this</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function updateCamera() {
   camera.updateProjectionMatrix();
 }
 
@@ -82,43 +86,37 @@ gui.add(camera, 'fov', 1, 180).onChange(updateCamera);
 const minMaxGUIHelper = new MinMaxGUIHelper(camera, 'near', 'far', 0.1);
 gui.add(minMaxGUIHelper, 'min', 0.1, 50, 0.1).name('near').onChange(updateCamera);
 gui.add(minMaxGUIHelper, 'max', 0.1, 50, 0.1).name('far').onChange(updateCamera);
-```
-
-Anytime the camera's settings change we need to call the camera's
-[`updateProjectionMatrix`](PerspectiveCamera.updateProjectionMatrix) function
-so we made a function called `updateCamera` add passed it to dat.GUI to call it when things change.
-
-{{{example url="../threejs-cameras-perspective.html" }}}
+</pre>
+<p>Anytime the camera's settings change we need to call the camera's
+<a href="/docs/#api/en/cameras/PerspectiveCamera#updateProjectionMatrix"><code class="notranslate" translate="no">updateProjectionMatrix</code></a> function
+so we made a function called <code class="notranslate" translate="no">updateCamera</code> add passed it to lil-gui to call it when things change.</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/cameras-perspective.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/cameras-perspective.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-You can adjust the values and see how they work. Note we didn't make `aspect` settable since
+<p></p>
+<p>You can adjust the values and see how they work. Note we didn't make <code class="notranslate" translate="no">aspect</code> settable since
 it's taken from the size of the window so if you want to adjust the aspect open the example
-in a new window and then size the window.
-
-Still, I think it's a little hard to see so let's change the example so it has 2 cameras.
+in a new window and then size the window.</p>
+<p>Still, I think it's a little hard to see so let's change the example so it has 2 cameras.
 One will show our scene as we see it above, the other will show another camera looking at the
-scene the first camera is drawing and showing that camera's frustum.
-
-To do this we can use the scissor function of three.js.
-Let's change it to draw 2 scenes with 2 cameras side by side using the scissor function
-
-First off let's use some HTML and CSS to define 2 side by side elements. This will also
-help us with events so both cameras can easily have their own `OrbitControls`.
-
-```html
-<body>
-  <canvas id="c"></canvas>
-+  <div class="split">
-+     <div id="view1" tabindex="1"></div>
-+     <div id="view2" tabindex="2"></div>
-+  </div>
-</body>
-```
-
-And the CSS that will make those 2 views show up side by side overlaid on top of
-the canvas
-
-```css
-.split {
+scene the first camera is drawing and showing that camera's frustum.</p>
+<p>To do this we can use the scissor function of three.js.
+Let's change it to draw 2 scenes with 2 cameras side by side using the scissor function</p>
+<p>First off let's use some HTML and CSS to define 2 side by side elements. This will also
+help us with events so both cameras can easily have their own <a href="/docs/#examples/controls/OrbitControls"><code class="notranslate" translate="no">OrbitControls</code></a>.</p>
+<pre class="prettyprint showlinemods notranslate lang-html" translate="no">&lt;body&gt;
+  &lt;canvas id="c"&gt;&lt;/canvas&gt;
++  &lt;div class="split"&gt;
++     &lt;div id="view1" tabindex="1"&gt;&lt;/div&gt;
++     &lt;div id="view2" tabindex="2"&gt;&lt;/div&gt;
++  &lt;/div&gt;
+&lt;/body&gt;
+</pre>
+<p>And the CSS that will make those 2 views show up side by side overlaid on top of
+the canvas</p>
+<pre class="prettyprint showlinemods notranslate lang-css" translate="no">.split {
   position: absolute;
   left: 0;
   top: 0;
@@ -126,43 +124,31 @@ the canvas
   height: 100%;
   display: flex;
 }
-.split>div {
+.split&gt;div {
   width: 100%;
   height: 100%;
 }
-```
-
-Then in our code we'll add a `CameraHelper`. A `CameraHelper` draws the frustum for a `Camera`
-
-```js
-const cameraHelper = new THREE.CameraHelper(camera);
+</pre>
+<p>Then in our code we'll add a <a href="/docs/#api/en/helpers/CameraHelper"><code class="notranslate" translate="no">CameraHelper</code></a>. A <a href="/docs/#api/en/helpers/CameraHelper"><code class="notranslate" translate="no">CameraHelper</code></a> draws the frustum for a <a href="/docs/#api/en/cameras/Camera"><code class="notranslate" translate="no">Camera</code></a></p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const cameraHelper = new THREE.CameraHelper(camera);
 
 ...
 
 scene.add(cameraHelper);
-```
-
-Now let's look up the 2 view elements.
-
-```js
-const view1Elem = document.querySelector('#view1');
+</pre>
+<p>Now let's look up the 2 view elements.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const view1Elem = document.querySelector('#view1');
 const view2Elem = document.querySelector('#view2');
-```
-
-And we'll set our existing `OrbitControls` to respond to the first
-view element only.
-
-```js
--const controls = new OrbitControls(camera, canvas);
+</pre>
+<p>And we'll set our existing <a href="/docs/#examples/controls/OrbitControls"><code class="notranslate" translate="no">OrbitControls</code></a> to respond to the first
+view element only.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">-const controls = new OrbitControls(camera, canvas);
 +const controls = new OrbitControls(camera, view1Elem);
-```
-
-Let's make a second `PerspectiveCamera` and a second `OrbitControls`.
-The second `OrbitControls` is tied to the second camera and gets input
-from the second view element.
-
-```js
-const camera2 = new THREE.PerspectiveCamera(
+</pre>
+<p>Let's make a second <a href="/docs/#api/en/cameras/PerspectiveCamera"><code class="notranslate" translate="no">PerspectiveCamera</code></a> and a second <a href="/docs/#examples/controls/OrbitControls"><code class="notranslate" translate="no">OrbitControls</code></a>.
+The second <a href="/docs/#examples/controls/OrbitControls"><code class="notranslate" translate="no">OrbitControls</code></a> is tied to the second camera and gets input
+from the second view element.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const camera2 = new THREE.PerspectiveCamera(
   60,  // fov
   2,   // aspect
   0.1, // near
@@ -174,17 +160,13 @@ camera2.lookAt(0, 5, 0);
 const controls2 = new OrbitControls(camera2, view2Elem);
 controls2.target.set(0, 5, 0);
 controls2.update();
-```
-
-Finally we need to render the scene from the point of view of each
-camera using the scissor function to only render to part of the canvas.
-
-Here is a function that given an element will compute the rectangle
+</pre>
+<p>Finally we need to render the scene from the point of view of each
+camera using the scissor function to only render to part of the canvas.</p>
+<p>Here is a function that given an element will compute the rectangle
 of that element that overlaps the canvas. It will then set the scissor
-and viewport to that rectangle and return the aspect for that size.
-
-```js
-function setScissorForElement(elem) {
+and viewport to that rectangle and return the aspect for that size.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function setScissorForElement(elem) {
   const canvasRect = canvas.getBoundingClientRect();
   const elemRect = elem.getBoundingClientRect();
 
@@ -205,12 +187,9 @@ function setScissorForElement(elem) {
   // return the aspect
   return width / height;
 }
-```
-
-And now we can use that function to draw the scene twice in our `render` function
-
-```js
-  function render() {
+</pre>
+<p>And now we can use that function to draw the scene twice in our <code class="notranslate" translate="no">render</code> function</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">  function render() {
 
 -    if (resizeRendererToDisplaySize(renderer)) {
 -      const canvas = renderer.domElement;
@@ -264,16 +243,12 @@ And now we can use that function to draw the scene twice in our `render` functio
 
   requestAnimationFrame(render);
 }
-```
-
-The code above sets the background color of the scene when rendering the
-second view to dark blue just to make it easier to distinguish the two views.
-
-We can also remove our `updateCamera` code since we're updating everything
-in the `render` function.
-
-```js
--function updateCamera() {
+</pre>
+<p>The code above sets the background color of the scene when rendering the
+second view to dark blue just to make it easier to distinguish the two views.</p>
+<p>We can also remove our <code class="notranslate" translate="no">updateCamera</code> code since we're updating everything
+in the <code class="notranslate" translate="no">render</code> function.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">-function updateCamera() {
 -  camera.updateProjectionMatrix();
 -}
 
@@ -285,42 +260,39 @@ const minMaxGUIHelper = new MinMaxGUIHelper(camera, 'near', 'far', 0.1);
 -gui.add(minMaxGUIHelper, 'max', 0.1, 50, 0.1).name('far').onChange(updateCamera);
 +gui.add(minMaxGUIHelper, 'min', 0.1, 50, 0.1).name('near');
 +gui.add(minMaxGUIHelper, 'max', 0.1, 50, 0.1).name('far');
-```
-
-And now you can use one view to see the frustum of the other.
-
-{{{example url="../threejs-cameras-perspective-2-scenes.html" }}}
+</pre>
+<p>And now you can use one view to see the frustum of the other.</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/cameras-perspective-2-scenes.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/cameras-perspective-2-scenes.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-On the left you can see the original view and on the right you can
+<p></p>
+<p>On the left you can see the original view and on the right you can
 see a view showing the frustum of the camera on the left. As you adjust
-`near`, `far`, `fov` and move the camera with mouse you can see that
+<code class="notranslate" translate="no">near</code>, <code class="notranslate" translate="no">far</code>, <code class="notranslate" translate="no">fov</code> and move the camera with mouse you can see that
 only what's inside the frustum shown on the right appears in the scene on
-the left.
-
-Adjust `near` up to around 20 and you'll easily see the front of objects
-disappear as they are no longer in the frustum. Adjust `far` below about 35
+the left.</p>
+<p>Adjust <code class="notranslate" translate="no">near</code> up to around 20 and you'll easily see the front of objects
+disappear as they are no longer in the frustum. Adjust <code class="notranslate" translate="no">far</code> below about 35
 and you'll start to see the ground plane disappear as it's no longer in
-the frustum.
-
-This brings up the question, why not just set `near` to 0.0000000001 and `far`
+the frustum.</p>
+<p>This brings up the question, why not just set <code class="notranslate" translate="no">near</code> to 0.0000000001 and <code class="notranslate" translate="no">far</code>
 to 10000000000000 or something like that so you can just see everything?
 The reason is your GPU only has so much precision to decide if something
 is in front or behind something else. That precision is spread out between
-`near` and `far`. Worse, by default the precision close the camera is detailed
-and the precision far from the camera is coarse. The units start with `near`
-and slowly expand as they approach `far`.
-
-Starting with the top example, let's change the code to insert 20 spheres in a
-row.
-
-```js
-{
+<code class="notranslate" translate="no">near</code> and <code class="notranslate" translate="no">far</code>. Worse, by default the precision close the camera is detailed
+and the precision far from the camera is coarse. The units start with <code class="notranslate" translate="no">near</code>
+and slowly expand as they approach <code class="notranslate" translate="no">far</code>.</p>
+<p>Starting with the top example, let's change the code to insert 20 spheres in a
+row.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
   const sphereRadius = 3;
   const sphereWidthDivisions = 32;
   const sphereHeightDivisions = 16;
   const sphereGeo = new THREE.SphereGeometry(sphereRadius, sphereWidthDivisions, sphereHeightDivisions);
   const numSpheres = 20;
-  for (let i = 0; i < numSpheres; ++i) {
+  for (let i = 0; i &lt; numSpheres; ++i) {
     const sphereMat = new THREE.MeshPhongMaterial();
     sphereMat.color.setHSL(i * .73, 1, 0.5);
     const mesh = new THREE.Mesh(sphereGeo, sphereMat);
@@ -328,86 +300,72 @@ row.
     scene.add(mesh);
   }
 }
-```
-
-and let's set `near` to 0.00001
-
-```js
-const fov = 45;
+</pre>
+<p>and let's set <code class="notranslate" translate="no">near</code> to 0.00001</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const fov = 45;
 const aspect = 2;  // the canvas default
 -const near = 0.1;
 +const near = 0.00001;
 const far = 100;
 const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-```
-
-We also need to tweak the GUI code a little to allow 0.00001 if the value is edited
-
-```js
--gui.add(minMaxGUIHelper, 'min', 0.1, 50, 0.1).name('near').onChange(updateCamera);
+</pre>
+<p>We also need to tweak the GUI code a little to allow 0.00001 if the value is edited</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">-gui.add(minMaxGUIHelper, 'min', 0.1, 50, 0.1).name('near').onChange(updateCamera);
 +gui.add(minMaxGUIHelper, 'min', 0.00001, 50, 0.00001).name('near').onChange(updateCamera);
-```
-
-What do you think will happen?
-
-{{{example url="../threejs-cameras-z-fighting.html" }}}
-
-This is an example of *z fighting* where the GPU on your computer does not have
-enough precision to decide which pixels are in front and which pixels are behind.
-
-Just in case the issue doesn't show on your machine here's what I see on mine
+</pre>
+<p>What do you think will happen?</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/cameras-z-fighting.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/cameras-z-fighting.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-<div class="threejs_center"><img src="resources/images/z-fighting.png" style="width: 570px;"></div>
+<p></p>
+<p>This is an example of <em>z fighting</em> where the GPU on your computer does not have
+enough precision to decide which pixels are in front and which pixels are behind.</p>
+<p>Just in case the issue doesn't show on your machine here's what I see on mine</p>
+<div class="threejs_center"><img src="../resources/images/z-fighting.png" style="width: 570px;"></div>
 
-One solution is to tell three.js use to a different method to compute which
+<p>One solution is to tell three.js use to a different method to compute which
 pixels are in front and which are behind. We can do that by enabling
-`logarithmicDepthBuffer` when we create the `WebGLRenderer`
-
-```js
--const renderer = new THREE.WebGLRenderer({canvas});
+<code class="notranslate" translate="no">logarithmicDepthBuffer</code> when we create the <a href="/docs/#api/en/renderers/WebGLRenderer"><code class="notranslate" translate="no">WebGLRenderer</code></a></p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">-const renderer = new THREE.WebGLRenderer({canvas});
 +const renderer = new THREE.WebGLRenderer({
 +  canvas,
 +  logarithmicDepthBuffer: true,
 +});
-```
-
-and with that it might work
-
-{{{example url="../threejs-cameras-logarithmic-depth-buffer.html" }}}
+</pre>
+<p>and with that it might work</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/cameras-logarithmic-depth-buffer.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/cameras-logarithmic-depth-buffer.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-If this didn't fix the issue for you then you've run into one reason why
+<p></p>
+<p>If this didn't fix the issue for you then you've run into one reason why
 you can't always use this solution. That reason is because only certain GPUs
 support it. As of September 2018 almost no mobile devices support this
-solution whereas most desktops do.
-
-Another reason not to choose this solution is it can be significantly slower
-than the standard solution.
-
-Even with this solution there is still limited resolution. Make `near` even
-smaller or `far` even bigger and you'll eventually run into the same issues.
-
-What that means is that you should always make an effort to choose a `near`
-and `far` setting that fits your use case. Set `near` as far away from the camera
-as you can and not have things disappear. Set `far` as close to the camera
+solution whereas most desktops do.</p>
+<p>Another reason not to choose this solution is it can be significantly slower
+than the standard solution.</p>
+<p>Even with this solution there is still limited resolution. Make <code class="notranslate" translate="no">near</code> even
+smaller or <code class="notranslate" translate="no">far</code> even bigger and you'll eventually run into the same issues.</p>
+<p>What that means is that you should always make an effort to choose a <code class="notranslate" translate="no">near</code>
+and <code class="notranslate" translate="no">far</code> setting that fits your use case. Set <code class="notranslate" translate="no">near</code> as far away from the camera
+as you can and not have things disappear. Set <code class="notranslate" translate="no">far</code> as close to the camera
 as you can and not have things disappear. If you're trying to draw a giant
 scene and show a close up of someone's face so you can see their eyelashes
 while in the background you can see all the way to mountains 50 kilometers
 in the distance well then you'll need to find other creative solutions that
 maybe we'll go over later. For now, just be aware you should take care
-to choose appropriate `near` and `far` values for your needs.
-
-The 2nd most common camera is the `OrthographicCamera`. Rather than
-specify a frustum it specifies a box with the settings `left`, `right`
-`top`, `bottom`, `near`, and `far`. Because it's projecting a box
-there is no perspective.
-
-Let's change the 2 view example above to use an `OrthographicCamera`
-in the first view.
-
-First let's setup an `OrthographicCamera`.
-
-```js
-const left = -1;
+to choose appropriate <code class="notranslate" translate="no">near</code> and <code class="notranslate" translate="no">far</code> values for your needs.</p>
+<p>The 2nd most common camera is the <a href="/docs/#api/en/cameras/OrthographicCamera"><code class="notranslate" translate="no">OrthographicCamera</code></a>. Rather than
+specify a frustum it specifies a box with the settings <code class="notranslate" translate="no">left</code>, <code class="notranslate" translate="no">right</code>
+<code class="notranslate" translate="no">top</code>, <code class="notranslate" translate="no">bottom</code>, <code class="notranslate" translate="no">near</code>, and <code class="notranslate" translate="no">far</code>. Because it's projecting a box
+there is no perspective.</p>
+<p>Let's change the 2 view example above to use an <a href="/docs/#api/en/cameras/OrthographicCamera"><code class="notranslate" translate="no">OrthographicCamera</code></a>
+in the first view.</p>
+<p>First let's setup an <a href="/docs/#api/en/cameras/OrthographicCamera"><code class="notranslate" translate="no">OrthographicCamera</code></a>.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const left = -1;
 const right = 1;
 const top = 1;
 const bottom = -1;
@@ -415,29 +373,21 @@ const near = 5;
 const far = 50;
 const camera = new THREE.OrthographicCamera(left, right, top, bottom, near, far);
 camera.zoom = 0.2;
-```
-
-We set `left` and `bottom` to -1 and `right` and `top` to 1. This would make
-a box 2 units wide and 2 units tall but we're going to adjust the `left` and `top`
-by the aspect of the rectangle we're drawing to. We'll use the `zoom` property
-to make it easy to adjust how many units are actually shown by the camera.
-
-Let's add a GUI setting for `zoom`
-
-```js
-const gui = new GUI();
+</pre>
+<p>We set <code class="notranslate" translate="no">left</code> and <code class="notranslate" translate="no">bottom</code> to -1 and <code class="notranslate" translate="no">right</code> and <code class="notranslate" translate="no">top</code> to 1. This would make
+a box 2 units wide and 2 units tall but we're going to adjust the <code class="notranslate" translate="no">left</code> and <code class="notranslate" translate="no">top</code>
+by the aspect of the rectangle we're drawing to. We'll use the <code class="notranslate" translate="no">zoom</code> property
+to make it easy to adjust how many units are actually shown by the camera.</p>
+<p>Let's add a GUI setting for <code class="notranslate" translate="no">zoom</code></p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const gui = new GUI();
 +gui.add(camera, 'zoom', 0.01, 1, 0.01).listen();
-```
-
-The call to `listen` tells dat.GUI to watch for changes. This is here because
-the `OrbitControls` can also control zoom. For example the scroll wheel on
-a mouse will zoom via the `OrbitControls`.
-
-Last we just need to change the part that renders the left
-side to update the `OrthographicCamera`.
-
-```js
-{
+</pre>
+<p>The call to <code class="notranslate" translate="no">listen</code> tells lil-gui to watch for changes. This is here because
+the <a href="/docs/#examples/controls/OrbitControls"><code class="notranslate" translate="no">OrbitControls</code></a> can also control zoom. For example the scroll wheel on
+a mouse will zoom via the <a href="/docs/#examples/controls/OrbitControls"><code class="notranslate" translate="no">OrbitControls</code></a>.</p>
+<p>Last we just need to change the part that renders the left
+side to update the <a href="/docs/#api/en/cameras/OrthographicCamera"><code class="notranslate" translate="no">OrthographicCamera</code></a>.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
   const aspect = setScissorForElement(view1Elem);
 
   // update the camera for this aspect
@@ -453,49 +403,41 @@ side to update the `OrthographicCamera`.
   scene.background.set(0x000000);
   renderer.render(scene, camera);
 }
-```
-
-and now you can see an `OrthographicCamera` at work.
-
-{{{example url="../threejs-cameras-orthographic-2-scenes.html" }}}
+</pre>
+<p>and now you can see an <a href="/docs/#api/en/cameras/OrthographicCamera"><code class="notranslate" translate="no">OrthographicCamera</code></a> at work.</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/cameras-orthographic-2-scenes.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/cameras-orthographic-2-scenes.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-An `OrthographicCamera` is most often used if using three.js
+<p></p>
+<p>An <a href="/docs/#api/en/cameras/OrthographicCamera"><code class="notranslate" translate="no">OrthographicCamera</code></a> is most often used if using three.js
 to draw 2D things. You'd decide how many units you want the camera
 to show. For example if you want one pixel of canvas to match
-one unit in the camera you could do something like
-
-To put the origin at the center and have 1 pixel = 1 three.js unit
-something like
-
-```js
-camera.left = -canvas.width / 2;
+one unit in the camera you could do something like</p>
+<p>To put the origin at the center and have 1 pixel = 1 three.js unit
+something like</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">camera.left = -canvas.width / 2;
 camera.right = canvas.width / 2;
 camera.top = canvas.height / 2;
 camera.bottom = -canvas.height / 2;
 camera.near = -1;
 camera.far = 1;
 camera.zoom = 1;
-```
-
-Or if we wanted the origin to be in the top left just like a
-2D canvas we could use this
-
-```js
-camera.left = 0;
+</pre>
+<p>Or if we wanted the origin to be in the top left just like a
+2D canvas we could use this</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">camera.left = 0;
 camera.right = canvas.width;
 camera.top = 0;
 camera.bottom = canvas.height;
 camera.near = -1;
 camera.far = 1;
 camera.zoom = 1;
-```
-
-In which case the top left corner would be 0,0 just like a 2D canvas
-
-Let's try it! First let's set the camera up
-
-```js
-const left = 0;
+</pre>
+<p>In which case the top left corner would be 0,0 just like a 2D canvas</p>
+<p>Let's try it! First let's set the camera up</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const left = 0;
 const right = 300;  // default canvas size
 const top = 0;
 const bottom = 150;  // default canvas size
@@ -503,17 +445,13 @@ const near = -1;
 const far = 1;
 const camera = new THREE.OrthographicCamera(left, right, top, bottom, near, far);
 camera.zoom = 1;
-```
-
-Then let's load 6 textures and make 6 planes, one for each texture.
-We'll parent each plane to a `THREE.Object3D` to make it easy to offset
-the plane so its center appears to be at its top left corner.
-
-If you're running locally you'll also need to have [setup](threejs-setup.html).
-You might also want to read about [using textures](threejs-textures.html).
-
-```js
-const loader = new THREE.TextureLoader();
+</pre>
+<p>Then let's load 6 textures and make 6 planes, one for each texture.
+We'll parent each plane to a <a href="/docs/#api/en/core/Object3D"><code class="notranslate" translate="no">THREE.Object3D</code></a> to make it easy to offset
+the plane so its center appears to be at its top left corner.</p>
+<p>If you're running locally you'll also need to have <a href="setup.html">setup</a>.
+You might also want to read about <a href="textures.html">using textures</a>.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const loader = new THREE.TextureLoader();
 const textures = [
   loader.load('resources/images/flower-1.jpg'),
   loader.load('resources/images/flower-2.jpg'),
@@ -524,7 +462,7 @@ const textures = [
 ];
 const planeSize = 256;
 const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize);
-const planes = textures.map((texture) => {
+const planes = textures.map((texture) =&gt; {
   const planePivot = new THREE.Object3D();
   scene.add(planePivot);
   texture.magFilter = THREE.NearestFilter;
@@ -538,13 +476,10 @@ const planes = textures.map((texture) => {
   mesh.position.set(planeSize / 2, planeSize / 2, 0);
   return planePivot;
 });
-```
-
-and we need to update the camera if the size of the canvas
-changes.
-
-```js
-function render() {
+</pre>
+<p>and we need to update the camera if the size of the canvas
+changes.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function render() {
 
   if (resizeRendererToDisplaySize(renderer)) {
     camera.right = canvas.width;
@@ -553,13 +488,10 @@ function render() {
   }
 
   ...
-```
-
-`planes` is an array of `THREE.Mesh`, one for each plane.
-Let's move them around based on the time.
-
-```js
-function render(time) {
+</pre>
+<p><code class="notranslate" translate="no">planes</code> is an array of <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">THREE.Mesh</code></a>, one for each plane.
+Let's move them around based on the time.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function render(time) {
   time *= 0.001;  // convert to seconds;
 
   ...
@@ -572,7 +504,7 @@ function render(time) {
   const yRange = distDown * 2;
   const speed = 180;
 
-  planes.forEach((plane, ndx) => {
+  planes.forEach((plane, ndx) =&gt; {
     // compute a unique time for each plane
     const t = time * speed + ndx * 300;
 
@@ -582,31 +514,42 @@ function render(time) {
 
     // set our position going forward if 0 to half of range
     // and backward if half of range to range
-    const x = xt < distAcross ? xt : xRange - xt;
-    const y = yt < distDown   ? yt : yRange - yt;
+    const x = xt &lt; distAcross ? xt : xRange - xt;
+    const y = yt &lt; distDown   ? yt : yRange - yt;
 
     plane.position.set(x, y, 0);
   });
 
   renderer.render(scene, camera);
-```
+</pre>
+<p>And you can see the images bounce pixel perfect off the edges of the
+canvas using pixel math just like a 2D canvas</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/cameras-orthographic-canvas-top-left-origin.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/cameras-orthographic-canvas-top-left-origin.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-And you can see the images bounce pixel perfect off the edges of the
-canvas using pixel math just like a 2D canvas
+<p></p>
+<p>Another common use for an <a href="/docs/#api/en/cameras/OrthographicCamera"><code class="notranslate" translate="no">OrthographicCamera</code></a> is to draw the
+up, down, left, right, front, back views of a 3D modeling
+program or a game engine's editor.</p>
+<div class="threejs_center"><img src="../resources/images/quad-viewport.png" style="width: 574px;"></div>
 
-{{{example url="../threejs-cameras-orthographic-canvas-top-left-origin.html" }}}
+<p>In the screenshot above you can see 1 view is a perspective view and 3 views are
+orthographic views.</p>
+<p>That's the fundamentals of cameras. We'll cover a few common ways to move cameras
+in other articles. For now let's move on to <a href="shadows.html">shadows</a>.</p>
+<p><canvas id="c"></canvas></p>
+<script type="module" src="../resources/threejs-cameras.js"></script>
 
-Another common use for an `OrthographicCamera` is to draw the
-up, down, left, right, front, back views of a 3D modeling
-program or a game engine's editor.
+        </div>
+      </div>
+    </div>
+  
+  <script src="/manual/resources/prettify.js"></script>
+  <script src="/manual/resources/lesson.js"></script>
 
-<div class="threejs_center"><img src="resources/images/quad-viewport.png" style="width: 574px;"></div>
 
-In the screenshot above you can see 1 view is a perspective view and 3 views are
-orthographic views.
 
-That's the fundamentals of cameras. We'll cover a few common ways to move cameras
-in other articles. For now let's move on to [shadows](threejs-shadows.html).
 
-<canvas id="c"></canvas>
-<script type="module" src="resources/threejs-cameras.js"></script>
+</body></html>

+ 151 - 156
manual/en/canvas-textures.html

@@ -1,21 +1,33 @@
-Title: Three.js Canvas Textures
-Description: How to use a canvas as a texture in Three.js
-TOC: Using A Canvas for Dynamic Textures
-
-This article continues from [the article on textures](threejs-textures.html).
-If you haven't read that yet you should probably start there.
-
-In [the previous article on textures](threejs-textures.html) we mostly used
+<!DOCTYPE html><html lang="en"><head>
+    <meta charset="utf-8">
+    <title>Canvas Textures</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 – Canvas Textures">
+    <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">
+  </head>
+  <body>
+    <div class="container">
+      <div class="lesson-title">
+        <h1>Canvas Textures</h1>
+      </div>
+      <div class="lesson">
+        <div class="lesson-main">
+          <p>This article continues from <a href="textures.html">the article on textures</a>.
+If you haven't read that yet you should probably start there.</p>
+<p>In <a href="textures.html">the previous article on textures</a> we mostly used
 image files for textures. Sometimes though we want to generate a texture
-at runtime. One way to do this is to use a `CanvasTexture`.
-
-A canvas texture takes a `<canvas>` as its input. If you don't know how to
-draw with the 2D canvas API on a canvas [there's a good tutorial on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial).
-
-Let's make a simple canvas program. Here's one that draws dots at random places in random colors.
-
-```js
-const ctx = document.createElement('canvas').getContext('2d');
+at runtime. One way to do this is to use a <a href="/docs/#api/en/textures/CanvasTexture"><code class="notranslate" translate="no">CanvasTexture</code></a>.</p>
+<p>A canvas texture takes a <code class="notranslate" translate="no">&lt;canvas&gt;</code> as its input. If you don't know how to
+draw with the 2D canvas API on a canvas <a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial">there's a good tutorial on MDN</a>.</p>
+<p>Let's make a simple canvas program. Here's one that draws dots at random places in random colors.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const ctx = document.createElement('canvas').getContext('2d');
 document.body.appendChild(ctx.canvas);
 ctx.canvas.width = 256;
 ctx.canvas.height = 256;
@@ -46,19 +58,19 @@ function render() {
   requestAnimationFrame(render);
 }
 requestAnimationFrame(render);
-```
-
-it's pretty straight forward.
-
-{{{example url="../canvas-random-dots.html" }}}
-
-Now let's use it to texture something. We'll start with the example of texturing
-a cube from [the previous article](threejs-textures.html).
+</pre>
+<p>it's pretty straight forward.</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/canvas-random-dots.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/canvas-random-dots.html" target="_blank">click here to open in a separate window</a>
+</div>
+
+<p></p>
+<p>Now let's use it to texture something. We'll start with the example of texturing
+a cube from <a href="textures.html">the previous article</a>.
 We'll remove the code that loads an image and instead use
-our canvas by creating a `CanvasTexture` and passing it the canvas we created.
-
-```js
-const cubes = [];  // just an array we can use to rotate the cubes
+our canvas by creating a <a href="/docs/#api/en/textures/CanvasTexture"><code class="notranslate" translate="no">CanvasTexture</code></a> and passing it the canvas we created.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const cubes = [];  // just an array we can use to rotate the cubes
 -const loader = new THREE.TextureLoader();
 -
 +const ctx = document.createElement('canvas').getContext('2d');
@@ -75,12 +87,9 @@ const material = new THREE.MeshBasicMaterial({
 const cube = new THREE.Mesh(geometry, material);
 scene.add(cube);
 cubes.push(cube);  // add to our list of cubes to rotate
-```
-
-And then call the code to draw a random dot in our render loop
-
-```js
-function render(time) {
+</pre>
+<p>And then call the code to draw a random dot in our render loop</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function render(time) {
   time *= 0.001;
 
   if (resizeRendererToDisplaySize(renderer)) {
@@ -92,7 +101,7 @@ function render(time) {
 +  drawRandomDot();
 +  texture.needsUpdate = true;
 
-  cubes.forEach((cube, ndx) => {
+  cubes.forEach((cube, ndx) =&gt; {
     const speed = .2 + ndx * .1;
     const rot = time * speed;
     cube.rotation.x = rot;
@@ -103,31 +112,27 @@ function render(time) {
 
   requestAnimationFrame(render);
 }
-```
-
-The only extra thing we need to do is set the `needsUpdate` property
-of the `CanvasTexture` to tell three.js to update the texture with
-the latest contents of the canvas.
-
-And with that we have a canvas textured cube
-
-{{{example url="../threejs-canvas-textured-cube.html" }}}
-
-Note that if you want to use three.js to draw into the canvas you're
-better off using a `RenderTarget` which is covered in [this article](threejs-rendertargets.html).
-
-A common use case for canvas textures is to provide text in a scene.
+</pre>
+<p>The only extra thing we need to do is set the <code class="notranslate" translate="no">needsUpdate</code> property
+of the <a href="/docs/#api/en/textures/CanvasTexture"><code class="notranslate" translate="no">CanvasTexture</code></a> to tell three.js to update the texture with
+the latest contents of the canvas.</p>
+<p>And with that we have a canvas textured cube</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/canvas-textured-cube.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/canvas-textured-cube.html" target="_blank">click here to open in a separate window</a>
+</div>
+
+<p></p>
+<p>Note that if you want to use three.js to draw into the canvas you're
+better off using a <code class="notranslate" translate="no">RenderTarget</code> which is covered in <a href="rendertargets.html">this article</a>.</p>
+<p>A common use case for canvas textures is to provide text in a scene.
 For example if you wanted to put a person's name on their character's
-badge you might use a canvas texture to texture the badge.
-
-Let's make a scene with 3 people and give each person a badge
-or label.
-
-Let's take the example above and remove all the cube related
-stuff. Then let's set the background to white and add two [lights](threejs-lights.html).
-
-```js
-const scene = new THREE.Scene();
+badge you might use a canvas texture to texture the badge.</p>
+<p>Let's make a scene with 3 people and give each person a badge
+or label.</p>
+<p>Let's take the example above and remove all the cube related
+stuff. Then let's set the background to white and add two <a href="lights.html">lights</a>.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const scene = new THREE.Scene();
 +scene.background = new THREE.Color('white');
 +
 +function addLight(position) {
@@ -140,12 +145,9 @@ const scene = new THREE.Scene();
 +}
 +addLight([-3, 1, 1]);
 +addLight([ 2, 1, .5]);
-```
-
-Let's make some code to make a label using canvas 2D
-
-```js
-+function makeLabelCanvas(size, name) {
+</pre>
+<p>Let's make some code to make a label using canvas 2D</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">+function makeLabelCanvas(size, name) {
 +  const borderSize = 2;
 +  const ctx = document.createElement('canvas').getContext('2d');
 +  const font =  `${size}px bold sans-serif`;
@@ -168,15 +170,11 @@ Let's make some code to make a label using canvas 2D
 +
 +  return ctx.canvas;
 +}
-```
-
-Then we'll make simple people from a cylinder for the body, a sphere
-for the head, and a plane for the label.
-
-First let's make the shared geometry.
-
-```js
-+const bodyRadiusTop = .4;
+</pre>
+<p>Then we'll make simple people from a cylinder for the body, a sphere
+for the head, and a plane for the label.</p>
+<p>First let's make the shared geometry.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">+const bodyRadiusTop = .4;
 +const bodyRadiusBottom = .2;
 +const bodyHeight = 2;
 +const bodyRadialSegments = 6;
@@ -190,13 +188,10 @@ First let's make the shared geometry.
 +    headRadius, headLonSegments, headLatSegments);
 +
 +const labelGeometry = new THREE.PlaneGeometry(1, 1);
-```
-
-Then let's make a function to build a person from these
-parts.
-
-```js
-+function makePerson(x, size, name, color) {
+</pre>
+<p>Then let's make a function to build a person from these
+parts.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">+function makePerson(x, size, name, color) {
 +  const canvas = makeLabelCanvas(size, name);
 +  const texture = new THREE.CanvasTexture(canvas);
 +  // because our canvas is likely not a power of 2
@@ -240,33 +235,24 @@ parts.
 +  scene.add(root);
 +  return root;
 +}
-```
-
-You can see above we put the body, head, and label on a root
-`Object3D` and adjust their positions. This would let us move the
+</pre>
+<p>You can see above we put the body, head, and label on a root
+<a href="/docs/#api/en/core/Object3D"><code class="notranslate" translate="no">Object3D</code></a> and adjust their positions. This would let us move the
 root object if we wanted to move the people. The body is 2 units
 high. If 1 unit equals 1 meter then the code above tries to
 make the label in centimeters so they will be size centimeters
-tall and however wide is needed to fit the text.
-
-We can then make people with labels
-
-```js
-+makePerson(-3, 32, 'Purple People Eater', 'purple');
+tall and however wide is needed to fit the text.</p>
+<p>We can then make people with labels</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">+makePerson(-3, 32, 'Purple People Eater', 'purple');
 +makePerson(-0, 32, 'Green Machine', 'green');
 +makePerson(+3, 32, 'Red Menace', 'red');
-```
-
-What's left is to add some `OrbitControls` so we can move
-the camera.
-
-```js
-import * as THREE from './resources/three/r132/build/three.module.js';
-+import {OrbitControls} from './resources/threejs/r132/examples/jsm/controls/OrbitControls.js';
-```
-
-```js
-const fov = 75;
+</pre>
+<p>What's left is to add some <a href="/docs/#examples/controls/OrbitControls"><code class="notranslate" translate="no">OrbitControls</code></a> so we can move
+the camera.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">import * as THREE from '/build/three.module.js';
++import {OrbitControls} from '/examples/jsm/controls/OrbitControls.js';
+</pre>
+<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;
@@ -278,35 +264,33 @@ const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
 +const controls = new OrbitControls(camera, canvas);
 +controls.target.set(0, 2, 0);
 +controls.update();
-```
-
-and we get simple labels.
-
-{{{example url="../threejs-canvas-textured-labels.html" }}}
-
-Some things to notice.
-
-* If you zoom in the labels get pretty low-res.
-
-There is no easy solution. There are more complex font
+</pre>
+<p>and we get simple labels.</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/canvas-textured-labels.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/canvas-textured-labels.html" target="_blank">click here to open in a separate window</a>
+</div>
+
+<p></p>
+<p>Some things to notice.</p>
+<ul>
+<li>If you zoom in the labels get pretty low-res.</li>
+</ul>
+<p>There is no easy solution. There are more complex font
 rendering techniques but I know of no plugin solutions.
 Plus they will require the user download font data which
-would be slow.
-
-One solution is to increase the resolution of the labels.
+would be slow.</p>
+<p>One solution is to increase the resolution of the labels.
 Try setting the size passed into to double what it is now
-and setting `labelBaseScale` to half what it currently is.
-
-* The labels get longer the longer the name.
-
-If you wanted to fix this you'd instead choose a fixed sized
-label and then squish the text.
-
-This is pretty easy. Pass in a base width and scale the text to fit that
-width like this
-
-```js
--function makeLabelCanvas(size, name) {
+and setting <code class="notranslate" translate="no">labelBaseScale</code> to half what it currently is.</p>
+<ul>
+<li>The labels get longer the longer the name.</li>
+</ul>
+<p>If you wanted to fix this you'd instead choose a fixed sized
+label and then squish the text.</p>
+<p>This is pretty easy. Pass in a base width and scale the text to fit that
+width like this</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">-function makeLabelCanvas(size, name) {
 +function makeLabelCanvas(baseWidth, size, name) {
   const borderSize = 2;
   const ctx = document.createElement('canvas').getContext('2d');
@@ -340,12 +324,9 @@ width like this
 
   return ctx.canvas;
 }
-```
-
-Then we can pass in a width for the labels
-
-```js
--function makePerson(x, size, name, color) {
+</pre>
+<p>Then we can pass in a width for the labels</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">-function makePerson(x, size, name, color) {
 -  const canvas = makeLabelCanvas(size, name);
 +function makePerson(x, labelWidth, size, name, color) {
 +  const canvas = makeLabelCanvas(labelWidth, size, name);
@@ -360,21 +341,21 @@ Then we can pass in a width for the labels
 +makePerson(-3, 150, 32, 'Purple People Eater', 'purple');
 +makePerson(-0, 150, 32, 'Green Machine', 'green');
 +makePerson(+3, 150, 32, 'Red Menace', 'red');
-```
-
-and we get labels where the text is centered and scaled to fit
-
-{{{example url="../threejs-canvas-textured-labels-scale-to-fit.html" }}}
-
-Above we used a new canvas for each texture. Whether or not to use a 
+</pre>
+<p>and we get labels where the text is centered and scaled to fit</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/canvas-textured-labels-scale-to-fit.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/canvas-textured-labels-scale-to-fit.html" target="_blank">click here to open in a separate window</a>
+</div>
+
+<p></p>
+<p>Above we used a new canvas for each texture. Whether or not to use a 
 canvas per texture is up to you. If you need to update them often then 
 having one canvas per texture is probably the best option. If they are
 rarely or never updated then you can choose to use a single canvas
 for multiple textures by forcing three.js to use the texture.
-Let's change the code above to do just that.
-
-```js
-+const ctx = document.createElement('canvas').getContext('2d');
+Let's change the code above to do just that.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">+const ctx = document.createElement('canvas').getContext('2d');
 
 function makeLabelCanvas(baseWidth, size, name) {
   const borderSize = 2;
@@ -409,15 +390,29 @@ function makePerson(x, labelWidth, size, name, color) {
 +  forceTextureInitialization(texture);
 
   ...
-```
-
-{{{example url="../threejs-canvas-textured-labels-one-canvas.html" }}}
-
-Another issue is that the labels don't always face the camera. If you're using 
+</pre>
+<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/canvas-textured-labels-one-canvas.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/canvas-textured-labels-one-canvas.html" target="_blank">click here to open in a separate window</a>
+</div>
+
+<p></p>
+<p>Another issue is that the labels don't always face the camera. If you're using 
 labels as badges that's probably a good thing. If you're using labels to put
 names over players in a 3D game maybe you want the labels to always face the camera.
-We'll cover how to do that in [an article on billboards](threejs-billboards.html).
+We'll cover how to do that in <a href="billboards.html">an article on billboards</a>.</p>
+<p>For labels in particular, <a href="align-html-elements-to-3d.html">another solution is to use HTML</a>.
+The labels in this article are <em>inside the 3D world</em> which is good if you want them
+to be hidden by other objects where as <a href="align-html-elements-to-3d.html">HTML labels</a> are always on top.</p>
+
+        </div>
+      </div>
+    </div>
+  
+  <script src="/manual/resources/prettify.js"></script>
+  <script src="/manual/resources/lesson.js"></script>
+
+
+
 
-For labels in particular, [another solution is to use HTML](threejs-align-html-elements-to-3d.html).
-The labels in this article are *inside the 3D world* which is good if you want them
-to be hidden by other objects where as [HTML labels](threejs-align-html-elements-to-3d.html) are always on top.
+</body></html>

+ 147 - 178
manual/en/cleanup.html

@@ -1,59 +1,62 @@
-Title: Three.js Cleanup
-Description: How to use free memory used by Three.js
-TOC: Freeing Resources
-
-Three.js apps often use lots of memory. A 3D model
+<!DOCTYPE html><html lang="en"><head>
+    <meta charset="utf-8">
+    <title>Cleanup</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 – Cleanup">
+    <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">
+  </head>
+  <body>
+    <div class="container">
+      <div class="lesson-title">
+        <h1>Cleanup</h1>
+      </div>
+      <div class="lesson">
+        <div class="lesson-main">
+          <p>Three.js apps often use lots of memory. A 3D model
 might be 1 to 20 meg memory for all of its vertices.
 A model might use many textures that even if they are
 compressed into jpg files they have to be expanded
 to their uncompressed form to use. Each 1024x1024
-texture takes 4 to 6meg of memory.
-
-Most three.js apps load resources at init time and
+texture takes 4 to 6meg of memory.</p>
+<p>Most three.js apps load resources at init time and
 then use those resources forever until the page is
 closed. But, what if you want to load and change resources
-over time?
-
-Unlike most JavaScript, three.js can not automatically
+over time?</p>
+<p>Unlike most JavaScript, three.js can not automatically
 clean these resources up. The browser will clean them
 up if you switch pages but otherwise it's up to you
 to manage them. This is an issue of how WebGL is designed
 and so three.js has no recourse but to pass on the
-responsibility to free resources back to you.
-
-You free three.js resource this by calling the `dispose` function on
-[textures](threejs-textures.html), 
-[geometries](threejs-primitives.html), and
-[materials](threejs-materials.html).
-
-You could do this manually. At the start you might create
-some of these resources
-
-```js
-const boxGeometry = new THREE.BoxGeometry(...);
+responsibility to free resources back to you.</p>
+<p>You free three.js resource this by calling the <code class="notranslate" translate="no">dispose</code> function on
+<a href="textures.html">textures</a>, 
+<a href="primitives.html">geometries</a>, and
+<a href="materials.html">materials</a>.</p>
+<p>You could do this manually. At the start you might create
+some of these resources</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const boxGeometry = new THREE.BoxGeometry(...);
 const boxTexture = textureLoader.load(...);
 const boxMaterial = new THREE.MeshPhongMaterial({map: texture});
-```
-
-and then when you're done with them you'd free them
-
-```js
-boxGeometry.dispose();
+</pre>
+<p>and then when you're done with them you'd free them</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">boxGeometry.dispose();
 boxTexture.dispose();
 boxMaterial.dispose();
-```
-
-As you use more and more resources that would get more and
-more tedious.
-
-To help remove some of the tedium let's make a class to track
+</pre>
+<p>As you use more and more resources that would get more and
+more tedious.</p>
+<p>To help remove some of the tedium let's make a class to track
 the resources. We'll then ask that class to do the cleanup
-for us.
-
-Here's a first pass at such a class
-
-```js
-class ResourceTracker {
+for us.</p>
+<p>Here's a first pass at such a class</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">class ResourceTracker {
   constructor() {
     this.resources = new Set();
   }
@@ -73,27 +76,18 @@ class ResourceTracker {
     this.resources.clear();
   }
 }
-```
-
-Let's use this class with the first example from [the article on textures](threejs-textures.html).
-We can create an instance of this class
-
-```js
-const resTracker = new ResourceTracker();
-```
-
-and then just to make it easier to use let's create a bound function for the `track` method
-
-```js
-const resTracker = new ResourceTracker();
+</pre>
+<p>Let's use this class with the first example from <a href="textures.html">the article on textures</a>.
+We can create an instance of this class</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const resTracker = new ResourceTracker();
+</pre>
+<p>and then just to make it easier to use let's create a bound function for the <code class="notranslate" translate="no">track</code> method</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const resTracker = new ResourceTracker();
 +const track = resTracker.track.bind(resTracker);
-```
-
-Now to use it we just need to call `track` with for each geometry, texture, and material
-we create
-
-```js
-const boxWidth = 1;
+</pre>
+<p>Now to use it we just need to call <code class="notranslate" translate="no">track</code> with for each geometry, texture, and material
+we create</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);
@@ -111,24 +105,18 @@ const loader = new THREE.TextureLoader();
 const cube = new THREE.Mesh(geometry, material);
 scene.add(cube);
 cubes.push(cube);  // add to our list of cubes to rotate
-```
-
-And then to free them we'd want to remove the cubes from the scene
-and then call `resTracker.dispose`
-
-```js
-for (const cube of cubes) {
+</pre>
+<p>And then to free them we'd want to remove the cubes from the scene
+and then call <code class="notranslate" translate="no">resTracker.dispose</code></p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">for (const cube of cubes) {
   scene.remove(cube);
 }
 cubes.length = 0;  // clears the cubes array
 resTracker.dispose();
-```
-
-That would work but I find having to remove the cubes from the
-scene kind of tedious. Let's add that functionality to the `ResourceTracker`.
-
-```js
-class ResourceTracker {
+</pre>
+<p>That would work but I find having to remove the cubes from the
+scene kind of tedious. Let's add that functionality to the <code class="notranslate" translate="no">ResourceTracker</code>.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">class ResourceTracker {
   constructor() {
     this.resources = new Set();
   }
@@ -157,34 +145,25 @@ class ResourceTracker {
     this.resources.clear();
   }
 }
-```
-
-And now we can track the cubes
-
-```js
-const material = track(new THREE.MeshBasicMaterial({
+</pre>
+<p>And now we can track the cubes</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const material = track(new THREE.MeshBasicMaterial({
   map: track(loader.load('resources/images/wall.jpg')),
 }));
 const cube = track(new THREE.Mesh(geometry, material));
 scene.add(cube);
 cubes.push(cube);  // add to our list of cubes to rotate
-```
-
-We no longer need the code to remove the cubes from the scene.
-
-```js
--for (const cube of cubes) {
+</pre>
+<p>We no longer need the code to remove the cubes from the scene.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">-for (const cube of cubes) {
 -  scene.remove(cube);
 -}
 cubes.length = 0;  // clears the cube array
 resTracker.dispose();
-```
-
-Let's arrange this code so that we can re-add the cube,
-texture, and material.
-
-```js
-const scene = new THREE.Scene();
+</pre>
+<p>Let's arrange this code so that we can re-add the cube,
+texture, and material.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const scene = new THREE.Scene();
 *const cubes = [];  // just an array we can use to rotate the cubes
 
 +function addStuffToScene() {
@@ -206,13 +185,10 @@ const scene = new THREE.Scene();
   cubes.push(cube);  // add to our list of cubes to rotate
 +  return resTracker;
 +}
-```
-
-And then let's write some code to add and remove things over time.
-
-```js
-function waitSeconds(seconds = 0) {
-  return new Promise(resolve => setTimeout(resolve, seconds * 1000));
+</pre>
+<p>And then let's write some code to add and remove things over time.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function waitSeconds(seconds = 0) {
+  return new Promise(resolve =&gt; setTimeout(resolve, seconds * 1000));
 }
 
 async function process() {
@@ -225,25 +201,22 @@ async function process() {
   }
 }
 process();
-```
-
-This code will create the cube, texture and material, wait for 2 seconds, then dispose of them and wait for 1 second
-and repeat.
-
-{{{example url="../threejs-cleanup-simple.html" }}}
-
-So that seems to work.
-
-For a loaded file though it's a little more work. Most loaders only return an `Object3D`
+</pre>
+<p>This code will create the cube, texture and material, wait for 2 seconds, then dispose of them and wait for 1 second
+and repeat.</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/cleanup-simple.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/cleanup-simple.html" target="_blank">click here to open in a separate window</a>
+</div>
+
+<p></p>
+<p>So that seems to work.</p>
+<p>For a loaded file though it's a little more work. Most loaders only return an <a href="/docs/#api/en/core/Object3D"><code class="notranslate" translate="no">Object3D</code></a>
 as a root of the hierarchy of objects they load so we need to discover what all the resources
-are.
-
-Let's update our `ResourceTracker` to try to do that.
-
-First we'll check if the object is an `Object3D` then track its geometry, material, and children
-
-```js
-class ResourceTracker {
+are.</p>
+<p>Let's update our <code class="notranslate" translate="no">ResourceTracker</code> to try to do that.</p>
+<p>First we'll check if the object is an <a href="/docs/#api/en/core/Object3D"><code class="notranslate" translate="no">Object3D</code></a> then track its geometry, material, and children</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">class ResourceTracker {
   constructor() {
     this.resources = new Set();
   }
@@ -260,13 +233,10 @@ class ResourceTracker {
   }
   ...
 }
-```
-
-Now, because any of `resource.geometry`, `resource.material`, and `resource.children`
-might be null or undefined we'll check at the top of `track`.
-
-```js
-class ResourceTracker {
+</pre>
+<p>Now, because any of <code class="notranslate" translate="no">resource.geometry</code>, <code class="notranslate" translate="no">resource.material</code>, and <code class="notranslate" translate="no">resource.children</code>
+might be null or undefined we'll check at the top of <code class="notranslate" translate="no">track</code>.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">class ResourceTracker {
   constructor() {
     this.resources = new Set();
   }
@@ -287,13 +257,10 @@ class ResourceTracker {
   }
   ...
 }
-```
-
-Also because `resource.children` is an array and because `resource.material` can be
-an array let's check for arrays
-
-```js
-class ResourceTracker {
+</pre>
+<p>Also because <code class="notranslate" translate="no">resource.children</code> is an array and because <code class="notranslate" translate="no">resource.material</code> can be
+an array let's check for arrays</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">class ResourceTracker {
   constructor() {
     this.resources = new Set();
   }
@@ -304,7 +271,7 @@ class ResourceTracker {
 
 +    // handle children and when material is an array of materials.
 +    if (Array.isArray(resource)) {
-+      resource.forEach(resource => this.track(resource));
++      resource.forEach(resource =&gt; this.track(resource));
 +      return resource;
 +    }
 
@@ -320,13 +287,10 @@ class ResourceTracker {
   }
   ...
 }
-```
-
-And finally we need to walk the properties and uniforms
-of a material looking for textures.
-
-```js
-class ResourceTracker {
+</pre>
+<p>And finally we need to walk the properties and uniforms
+of a material looking for textures.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">class ResourceTracker {
   constructor() {
     this.resources = new Set();
   }
@@ -338,7 +302,7 @@ class ResourceTracker {
 *    // handle children and when material is an array of materials or
 *    // uniform is array of textures
     if (Array.isArray(resource)) {
-      resource.forEach(resource => this.track(resource));
+      resource.forEach(resource =&gt; this.track(resource));
       return resource;
     }
 
@@ -374,21 +338,18 @@ class ResourceTracker {
   }
   ...
 }
-```
-
-And with that let's take an example from [the article on loading gltf files](threejs-load-gltf.html)
-and make it load and free files.
-
-```js
-const gltfLoader = new GLTFLoader();
+</pre>
+<p>And with that let's take an example from <a href="load-gltf.html">the article on loading gltf files</a>
+and make it load and free files.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const gltfLoader = new GLTFLoader();
 function loadGLTF(url) {
-  return new Promise((resolve, reject) => {
+  return new Promise((resolve, reject) =&gt; {
     gltfLoader.load(url, resolve, undefined, reject);
   });
 }
 
 function waitSeconds(seconds = 0) {
-  return new Promise(resolve => setTimeout(resolve, seconds * 1000));
+  return new Promise(resolve =&gt; setTimeout(resolve, seconds * 1000));
 }
 
 const fileURLs = [
@@ -428,41 +389,49 @@ async function loadFiles() {
   }
 }
 loadFiles();
-```
-
-and we get
-
-{{{example url="../threejs-cleanup-loaded-files.html"}}}
-
-Some notes about the code.
-
-If we wanted to load 2 or more files at once and free them at
-anytime we would use one `ResourceTracker` per file.
-
-Above we are only tracking `gltf.scene` right after loading.
-Based on our current implementation of `ResourceTracker` that 
+</pre>
+<p>and we get</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/cleanup-loaded-files.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/cleanup-loaded-files.html" target="_blank">click here to open in a separate window</a>
+</div>
+
+<p></p>
+<p>Some notes about the code.</p>
+<p>If we wanted to load 2 or more files at once and free them at
+anytime we would use one <code class="notranslate" translate="no">ResourceTracker</code> per file.</p>
+<p>Above we are only tracking <code class="notranslate" translate="no">gltf.scene</code> right after loading.
+Based on our current implementation of <code class="notranslate" translate="no">ResourceTracker</code> that 
 will track all the resources just loaded. If we added more
-things to the scene we need to decide whether or not to track them.
-
-For example let's say after we loaded a character we put a tool
+things to the scene we need to decide whether or not to track them.</p>
+<p>For example let's say after we loaded a character we put a tool
 in their hand by making the tool a child of their hand. As it is
 that tool will not be freed. I'm guessing more often than not
-this is what we want. 
-
-That brings up a point. Originally when I first wrote the `ResourceTracker`
-above I walked through everything inside the `dispose` method instead of `track`.
+this is what we want. </p>
+<p>That brings up a point. Originally when I first wrote the <code class="notranslate" translate="no">ResourceTracker</code>
+above I walked through everything inside the <code class="notranslate" translate="no">dispose</code> method instead of <code class="notranslate" translate="no">track</code>.
 It was only later as I thought about the tool as a child of hand case above
-that it became clear that tracking exactly what to free in `track` was more
+that it became clear that tracking exactly what to free in <code class="notranslate" translate="no">track</code> was more
 flexible and arguably more correct since we could then track what was loaded
-from the file rather than just freeing the state of the scene graph later.
-
-I honestly am not 100% happy with `ResourceTracker`. Doing things this
+from the file rather than just freeing the state of the scene graph later.</p>
+<p>I honestly am not 100% happy with <code class="notranslate" translate="no">ResourceTracker</code>. Doing things this
 way is not common in 3D engines. We shouldn't have to guess what
 resources were loaded, we should know. It would be nice if three.js
 changed so that all file loaders returned some standard object with
 references to all the resources loaded. At least at the moment,
 three.js doesn't give us any more info when loading a scene so this
-solution seems to work.
+solution seems to work.</p>
+<p>I hope you find this example useful or at least a good reference for what is
+required to free resources in three.js</p>
+
+        </div>
+      </div>
+    </div>
+  
+  <script src="/manual/resources/prettify.js"></script>
+  <script src="/manual/resources/lesson.js"></script>
+
+
+
 
-I hope you find this example useful or at least a good reference for what is
-required to free resources in three.js
+</body></html>

+ 146 - 153
manual/en/custom-buffergeometry.html

@@ -1,52 +1,60 @@
-Title: Three.js Custom BufferGeometry
-Description: How to make your own BufferGeometry.
-TOC: Custom BufferGeometry
-
-`BufferGeometry` is three.js's way of representing all geometry. A `BufferGeometry`
-essentially a collection *named* of `BufferAttribute`s.
-Each `BufferAttribute` represents an array of one type of data: positions,
-normals, colors, uv, etc... Together, the named `BufferAttribute`s represent
-*parallel arrays* of all the data for each vertex.
-
-<div class="threejs_center"><img src="resources/threejs-attributes.svg" style="width: 700px"></div>
-
-Above you can see we have 4 attributes: `position`, `normal`, `color`, `uv`.
-They represent *parallel arrays* which means that the Nth set of data in each
+<!DOCTYPE html><html lang="en"><head>
+    <meta charset="utf-8">
+    <title>Custom BufferGeometry</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 – Custom BufferGeometry">
+    <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">
+  </head>
+  <body>
+    <div class="container">
+      <div class="lesson-title">
+        <h1>Custom BufferGeometry</h1>
+      </div>
+      <div class="lesson">
+        <div class="lesson-main">
+          <p><a href="/docs/#api/en/core/BufferGeometry"><code class="notranslate" translate="no">BufferGeometry</code></a> is three.js's way of representing all geometry. A <a href="/docs/#api/en/core/BufferGeometry"><code class="notranslate" translate="no">BufferGeometry</code></a>
+essentially a collection <em>named</em> of <a href="/docs/#api/en/core/BufferAttribute"><code class="notranslate" translate="no">BufferAttribute</code></a>s.
+Each <a href="/docs/#api/en/core/BufferAttribute"><code class="notranslate" translate="no">BufferAttribute</code></a> represents an array of one type of data: positions,
+normals, colors, uv, etc... Together, the named <a href="/docs/#api/en/core/BufferAttribute"><code class="notranslate" translate="no">BufferAttribute</code></a>s represent
+<em>parallel arrays</em> of all the data for each vertex.</p>
+<div class="threejs_center"><img src="../resources/threejs-attributes.svg" style="width: 700px"></div>
+
+<p>Above you can see we have 4 attributes: <code class="notranslate" translate="no">position</code>, <code class="notranslate" translate="no">normal</code>, <code class="notranslate" translate="no">color</code>, <code class="notranslate" translate="no">uv</code>.
+They represent <em>parallel arrays</em> which means that the Nth set of data in each
 attribute belongs to the same vertex. The vertex at index = 4 is highlighted
-to show that the parallel data across all attributes defines one vertex.
-
-This brings up a point, here's a diagram of a cube with one corner highlighted.
+to show that the parallel data across all attributes defines one vertex.</p>
+<p>This brings up a point, here's a diagram of a cube with one corner highlighted.</p>
+<div class="threejs_center"><img src="../resources/cube-faces-vertex.svg" style="width: 500px"></div>
 
-<div class="threejs_center"><img src="resources/cube-faces-vertex.svg" style="width: 500px"></div>
-
-Thinking about it that single corner needs a different normal for each face of the
+<p>Thinking about it that single corner needs a different normal for each face of the
 cube. A normal is info about which direction something faces. In the diagram
 the normals are presented by the arrows around the corner vertex showing that each
-face that shares that vertex position needs a normal that points in a different direction.
-
-That corner needs different UVs for each face as well. UVs are texture coordinates
+face that shares that vertex position needs a normal that points in a different direction.</p>
+<p>That corner needs different UVs for each face as well. UVs are texture coordinates
 that specify which part of a texture being drawn on a triangle corresponds to that
 vertex position. You can see the green face needs that vertex to have a UV that corresponds
 to the top right corner of the F texture, the blue face needs a UV that corresponds to the
 top left corner of the F texture, and the red face needs a UV that corresponds to the bottom
-left corner of the F texture.
-
-A single *vertex* is the combination of all of its parts. If a vertex needs any
-part to be different then it must be a different vertex.
-
-As a simple example let's make a cube using `BufferGeometry`. A cube is interesting
+left corner of the F texture.</p>
+<p>A single <em>vertex</em> is the combination of all of its parts. If a vertex needs any
+part to be different then it must be a different vertex.</p>
+<p>As a simple example let's make a cube using <a href="/docs/#api/en/core/BufferGeometry"><code class="notranslate" translate="no">BufferGeometry</code></a>. A cube is interesting
 because it appears to share vertices at the corners but really
 does not. For our example we'll list out all the vertices with all their data
 and then convert that data into parallel arrays and finally use those to make
-`BufferAttribute`s and add them to a `BufferGeometry`.
-
-We start with a list of all the data needed for the cube. Remember again
+<a href="/docs/#api/en/core/BufferAttribute"><code class="notranslate" translate="no">BufferAttribute</code></a>s and add them to a <a href="/docs/#api/en/core/BufferGeometry"><code class="notranslate" translate="no">BufferGeometry</code></a>.</p>
+<p>We start with a list of all the data needed for the cube. Remember again
 that if a vertex has any unique parts it has to be a separate vertex. As such
 to make a cube requires 36 vertices. 2 triangles per face, 3 vertices per triangle,
-6 faces = 36 vertices.
-
-```js
-const vertices = [
+6 faces = 36 vertices.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const vertices = [
   // front
   { pos: [-1, -1,  1], norm: [ 0,  0,  1], uv: [0, 0], },
   { pos: [ 1, -1,  1], norm: [ 0,  0,  1], uv: [1, 0], },
@@ -96,12 +104,9 @@ const vertices = [
   { pos: [-1, -1,  1], norm: [ 0, -1,  0], uv: [1, 0], },
   { pos: [-1, -1, -1], norm: [ 0, -1,  0], uv: [1, 1], },
 ];
-```
-
-We can then translate all of that into 3 parallel arrays
-
-```js
-const positions = [];
+</pre>
+<p>We can then translate all of that into 3 parallel arrays</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const positions = [];
 const normals = [];
 const uvs = [];
 for (const vertex of vertices) {
@@ -109,13 +114,10 @@ for (const vertex of vertices) {
   normals.push(...vertex.norm);
   uvs.push(...vertex.uv);
 }
-```
-
-Finally we can create a `BufferGeometry` and then a `BufferAttribute` for each array
-and add it to the `BufferGeometry`.
-
-```js
-  const geometry = new THREE.BufferGeometry();
+</pre>
+<p>Finally we can create a <a href="/docs/#api/en/core/BufferGeometry"><code class="notranslate" translate="no">BufferGeometry</code></a> and then a <a href="/docs/#api/en/core/BufferAttribute"><code class="notranslate" translate="no">BufferAttribute</code></a> for each array
+and add it to the <a href="/docs/#api/en/core/BufferGeometry"><code class="notranslate" translate="no">BufferGeometry</code></a>.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">  const geometry = new THREE.BufferGeometry();
   const positionNumComponents = 3;
   const normalNumComponents = 3;
   const uvNumComponents = 2;
@@ -128,32 +130,31 @@ and add it to the `BufferGeometry`.
   geometry.setAttribute(
       'uv',
       new THREE.BufferAttribute(new Float32Array(uvs), uvNumComponents));
-```
-
-Note that the names are significant. You must name your attributes the names
+</pre>
+<p>Note that the names are significant. You must name your attributes the names
 that match what three.js expects (unless you are creating a custom shader).
-In this case `position`, `normal`, and `uv`. If you want vertex colors then
-name your attribute `color`.
-
-Above we created 3 JavaScript native arrays, `positions`, `normals` and `uvs`.
+In this case <code class="notranslate" translate="no">position</code>, <code class="notranslate" translate="no">normal</code>, and <code class="notranslate" translate="no">uv</code>. If you want vertex colors then
+name your attribute <code class="notranslate" translate="no">color</code>.</p>
+<p>Above we created 3 JavaScript native arrays, <code class="notranslate" translate="no">positions</code>, <code class="notranslate" translate="no">normals</code> and <code class="notranslate" translate="no">uvs</code>.
 We then convert those into
-[TypedArrays](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray)
-of type `Float32Array`. A `BufferAttribute` requires a TypedArray not a native
-array. A `BufferAttribute` also requires you to tell it how many components there
+<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray">TypedArrays</a>
+of type <code class="notranslate" translate="no">Float32Array</code>. A <a href="/docs/#api/en/core/BufferAttribute"><code class="notranslate" translate="no">BufferAttribute</code></a> requires a TypedArray not a native
+array. A <a href="/docs/#api/en/core/BufferAttribute"><code class="notranslate" translate="no">BufferAttribute</code></a> also requires you to tell it how many components there
 are per vertex. For the positions and normals we have 3 components per vertex,
-x, y, and z. For the UVs we have 2, u and v.
-
-{{{example url="../threejs-custom-buffergeometry-cube.html"}}}
+x, y, and z. For the UVs we have 2, u and v.</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/custom-buffergeometry-cube.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/custom-buffergeometry-cube.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-That's a lot of data. A small thing we can do is use indices to reference
+<p></p>
+<p>That's a lot of data. A small thing we can do is use indices to reference
 the vertices. Looking back at our cube data, each face is made from 2 triangles
 with 3 vertices each, 6 vertices total, but 2 of those vertices are exactly the same;
 The same position, the same normal, and the same uv.
 So, we can remove the matching vertices and then
-reference them by index. First we remove the matching vertices.
-
-```js
-const vertices = [
+reference them by index. First we remove the matching vertices.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const vertices = [
   // front
   { pos: [-1, -1,  1], norm: [ 0,  0,  1], uv: [0, 0], }, // 0
   { pos: [ 1, -1,  1], norm: [ 0,  0,  1], uv: [1, 0], }, // 1
@@ -203,13 +204,10 @@ const vertices = [
   { pos: [ 1, -1, -1], norm: [ 0, -1,  0], uv: [0, 1], }, // 22
   { pos: [-1, -1, -1], norm: [ 0, -1,  0], uv: [1, 1], }, // 23
 ];
-```
-
-So now we have 24 unique vertices. Then we specify 36 indices
-for the 36 vertices we need drawn to make 12 triangles by calling `BufferGeometry.setIndex` with an array of indices.
-
-```js
-geometry.setAttribute(
+</pre>
+<p>So now we have 24 unique vertices. Then we specify 36 indices
+for the 36 vertices we need drawn to make 12 triangles by calling <a href="/docs/#api/en/core/BufferGeometry.setIndex"><code class="notranslate" translate="no">BufferGeometry.setIndex</code></a> with an array of indices.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">geometry.setAttribute(
     'position',
     new THREE.BufferAttribute(positions, positionNumComponents));
 geometry.setAttribute(
@@ -227,41 +225,39 @@ geometry.setAttribute(
 +  16, 17, 18,  18, 17, 19,  // top
 +  20, 21, 22,  22, 21, 23,  // bottom
 +]);
-```
-
-{{{example url="../threejs-custom-buffergeometry-cube-indexed.html"}}}
+</pre>
+<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/custom-buffergeometry-cube-indexed.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/custom-buffergeometry-cube-indexed.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-`BufferGeometry` has a [`computeVertexNormals`](BufferGeometry.computeVertexNormals) method for computing normals if you
+<p></p>
+<p><a href="/docs/#api/en/core/BufferGeometry"><code class="notranslate" translate="no">BufferGeometry</code></a> has a <a href="/docs/#api/en/core/BufferGeometry#computeVertexNormals"><code class="notranslate" translate="no">computeVertexNormals</code></a> method for computing normals if you
 are not supplying them. Unfortunately, 
 since positions can not be shared if any other part of a vertex is different,
-the results of calling `computeVertexNormals` will generate seams if your
-geometry is supposed to connect to itself like a sphere or a cylinder.
-
+the results of calling <code class="notranslate" translate="no">computeVertexNormals</code> will generate seams if your
+geometry is supposed to connect to itself like a sphere or a cylinder.</p>
 <div class="spread">
   <div>
     <div data-diagram="bufferGeometryCylinder"></div>
   </div>
 </div>
 
-For the cylinder above the normals were created using `computeVertexNormals`.
+<p>For the cylinder above the normals were created using <code class="notranslate" translate="no">computeVertexNormals</code>.
 If you look closely there is a seam on the cylinder. This is because there
 is no way to share the vertices at the start and end of the cylinder since they
 require different UVs so the function to compute them has no idea those are
 the same vertices to smooth over them. Just a small thing to be aware of.
-The solution is to supply your own normals.
-
-We can also use [TypedArrays](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray) from the start instead of native JavaScript arrays.
+The solution is to supply your own normals.</p>
+<p>We can also use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray">TypedArrays</a> from the start instead of native JavaScript arrays.
 The disadvantage to TypedArrays is you must specify their size up front. Of
 course that's not that large of a burden but with native arrays we can just
-`push` values onto them and look at what size they end up by checking their
-`length` at the end. With TypedArrays there is no push function so we need
-to do our own bookkeeping when adding values to them.
-
-In this example knowing the length up front is pretty easy since we're using
-a big block of static data to start.
-
-```js
--const positions = [];
+<code class="notranslate" translate="no">push</code> values onto them and look at what size they end up by checking their
+<code class="notranslate" translate="no">length</code> at the end. With TypedArrays there is no push function so we need
+to do our own bookkeeping when adding values to them.</p>
+<p>In this example knowing the length up front is pretty easy since we're using
+a big block of static data to start.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">-const positions = [];
 -const normals = [];
 -const uvs = [];
 +const numVertices = vertices.length;
@@ -307,26 +303,24 @@ geometry.setIndex([
   16, 17, 18,  18, 17, 19,  // top
   20, 21, 22,  22, 21, 23,  // bottom
 ]);
-```
-
-{{{example url="../threejs-custom-buffergeometry-cube-typedarrays.html"}}}
-
-A good reason to use typedarrays is if you want to dynamically update any
-part of the vertices.
+</pre>
+<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/custom-buffergeometry-cube-typedarrays.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/custom-buffergeometry-cube-typedarrays.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-I couldn't think of a really good example of dynamically updating the vertices
+<p></p>
+<p>A good reason to use typedarrays is if you want to dynamically update any
+part of the vertices.</p>
+<p>I couldn't think of a really good example of dynamically updating the vertices
 so I decided to make a sphere and move each quad in and out from the center. Hopefully
-it's a useful example.
-
-Here's the code to generate positions and indices for a sphere. The code
+it's a useful example.</p>
+<p>Here's the code to generate positions and indices for a sphere. The code
 is sharing vertices within a quad but it's not sharing vertices between
-quads because we want to be able to move each quad separately.
-
-Because I'm lazy I used a small hierarchy of 3 `Object3D` objects to compute
-sphere points. How this works is explained in [the article on optimizing lots of objects](threejs-optimize-lots-of-objects.html).
-
-```js
-function makeSpherePositions(segmentsAround, segmentsDown) {
+quads because we want to be able to move each quad separately.</p>
+<p>Because I'm lazy I used a small hierarchy of 3 <a href="/docs/#api/en/core/Object3D"><code class="notranslate" translate="no">Object3D</code></a> objects to compute
+sphere points. How this works is explained in <a href="optimize-lots-of-objects.html">the article on optimizing lots of objects</a>.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function makeSpherePositions(segmentsAround, segmentsDown) {
   const numVertices = segmentsAround * segmentsDown * 6;
   const numComponents = 3;
   const positions = new Float32Array(numVertices * numComponents);
@@ -349,13 +343,13 @@ function makeSpherePositions(segmentsAround, segmentsDown) {
 
   let posNdx = 0;
   let ndx = 0;
-  for (let down = 0; down < segmentsDown; ++down) {
+  for (let down = 0; down &lt; segmentsDown; ++down) {
     const v0 = down / segmentsDown;
     const v1 = (down + 1) / segmentsDown;
     const lat0 = (v0 - 0.5) * Math.PI;
     const lat1 = (v1 - 0.5) * Math.PI;
 
-    for (let across = 0; across < segmentsAround; ++across) {
+    for (let across = 0; across &lt; segmentsAround; ++across) {
       const u0 = across / segmentsAround;
       const u1 = (across + 1) / segmentsAround;
       const long0 = u0 * Math.PI * 2;
@@ -375,27 +369,18 @@ function makeSpherePositions(segmentsAround, segmentsDown) {
   }
   return {positions, indices};
 }
-```
-
-We can then call it like this
-
-```js
-const segmentsAround = 24;
+</pre>
+<p>We can then call it like this</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const segmentsAround = 24;
 const segmentsDown = 16;
 const {positions, indices} = makeSpherePositions(segmentsAround, segmentsDown);
-```
-
-Because positions returned are unit sphere positions so they are exactly the same
-values we need for normals so we can just duplicated them for the normals.
-
-```js
-const normals = positions.slice();
-```
-
-And then we setup the attributes like before
-
-```js
-const geometry = new THREE.BufferGeometry();
+</pre>
+<p>Because positions returned are unit sphere positions so they are exactly the same
+values we need for normals so we can just duplicated them for the normals.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const normals = positions.slice();
+</pre>
+<p>And then we setup the attributes like before</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const geometry = new THREE.BufferGeometry();
 const positionNumComponents = 3;
 const normalNumComponents = 3;
 
@@ -408,20 +393,16 @@ geometry.setAttribute(
     'normal',
     new THREE.BufferAttribute(normals, normalNumComponents));
 geometry.setIndex(indices);
-```
-
-I've highlighted a few differences. We save a reference to the position attribute.
+</pre>
+<p>I've highlighted a few differences. We save a reference to the position attribute.
 We also mark it as dynamic. This is a hint to THREE.js that we're going to be changing
-the contents of the attribute often.
-
-In our render loop we update the positions based off their normals every frame.
-
-```js
-const temp = new THREE.Vector3();
+the contents of the attribute often.</p>
+<p>In our render loop we update the positions based off their normals every frame.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const temp = new THREE.Vector3();
 
 ...
 
-for (let i = 0; i < positions.length; i += 3) {
+for (let i = 0; i &lt; positions.length; i += 3) {
   const quad = (i / 12 | 0);
   const ringId = quad / segmentsAround | 0;
   const ringQuadId = quad % segmentsAround;
@@ -432,20 +413,32 @@ for (let i = 0; i < positions.length; i += 3) {
   temp.toArray(positions, i);
 }
 positionAttribute.needsUpdate = true;
-```
+</pre>
+<p>And we set <code class="notranslate" translate="no">positionAttribute.needsUpdate</code> to tell THREE.js to use our changes.</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/custom-buffergeometry-dynamic.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/custom-buffergeometry-dynamic.html" target="_blank">click here to open in a separate window</a>
+</div>
+
+<p></p>
+<p>I hope these were useful examples of how to use <a href="/docs/#api/en/core/BufferGeometry"><code class="notranslate" translate="no">BufferGeometry</code></a> directly to
+make your own geometry and how to dynamically update the contents of a
+<a href="/docs/#api/en/core/BufferAttribute"><code class="notranslate" translate="no">BufferAttribute</code></a>.</p>
+<!-- needed in English only to prevent warning from outdated translations -->
+<p><a href="resources/threejs-geometry.svg"></a>
+<a href="custom-geometry.html"></a></p>
+<p><canvas id="c"></canvas></p>
+<script type="module" src="../resources/threejs-custom-buffergeometry.js"></script>
 
-And we set `positionAttribute.needsUpdate` to tell THREE.js to use our changes.
 
-{{{example url="../threejs-custom-buffergeometry-dynamic.html"}}}
+        </div>
+      </div>
+    </div>
+  
+  <script src="/manual/resources/prettify.js"></script>
+  <script src="/manual/resources/lesson.js"></script>
 
-I hope these were useful examples of how to use `BufferGeometry` directly to
-make your own geometry and how to dynamically update the contents of a
-`BufferAttribute`.
 
-<!-- needed in English only to prevent warning from outdated translations -->
-<a href="resources/threejs-geometry.svg"></a>
-<a href="threejs-custom-geometry.html"></a>
 
-<canvas id="c"></canvas>
-<script type="module" src="resources/threejs-custom-buffergeometry.js"></script>
 
+</body></html>

+ 215 - 248
manual/en/custom-geometry.html

@@ -1,78 +1,81 @@
-Title: Three.js Custom Geometry
-Description: How to make your own geometry.
-TOC: Custom Geometry
-
-<div class="warning">
+<!DOCTYPE html><html lang="en"><head>
+    <meta charset="utf-8">
+    <title>Custom Geometry</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 – Custom Geometry">
+    <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">
+  </head>
+  <body>
+    <div class="container">
+      <div class="lesson-title">
+        <h1>Custom Geometry</h1>
+      </div>
+      <div class="lesson">
+        <div class="lesson-main">
+          <div class="warning">
 <strong>NOTE!</strong> This article is deprecated. Three.js r125
-removed support for <code>Geometry</code>. Please refer to
-the article on <a href="threejs-custom-buffergeometry.html">custom BufferGeometry</a>.
+removed support for <code class="notranslate" translate="no">Geometry</code>. Please refer to
+the article on <a href="custom-buffergeometry.html">custom BufferGeometry</a>.
 </div>
 
-A [previous article](threejs-primitives.html) gave a tour of
+<p>A <a href="primitives.html">previous article</a> gave a tour of
 the various built in primitives included in THREE.js. In this
-article we'll cover making our own geometry.
-
-Just to be clear, if you are serious about making 3D content,
+article we'll cover making our own geometry.</p>
+<p>Just to be clear, if you are serious about making 3D content,
 the most common way is to use a 3D modeling package like
-[Blender](https://blender.org),
-[Maya](https://www.autodesk.com/products/maya/overview),
-[3D Studio Max](https://www.autodesk.com/products/3ds-max/overview),
-[Cinema4D](https://www.maxon.net/en-us/), etc...
-You'd build a model and then export to [gLTF](threejs-load-gltf.html)
-or [.obj](threejs-load-obj.html) and load them up.
+<a href="https://blender.org">Blender</a>,
+<a href="https://www.autodesk.com/products/maya/overview">Maya</a>,
+<a href="https://www.autodesk.com/products/3ds-max/overview">3D Studio Max</a>,
+<a href="https://www.maxon.net/en-us/">Cinema4D</a>, etc...
+You'd build a model and then export to <a href="load-gltf.html">gLTF</a>
+or <a href="load-obj.html">.obj</a> and load them up.
 Whichever one you choose, expect to spend 2 or 3 weeks going through
 their respective tutorials as all of them have a learning curve
-to be useful.
-
-Still, there are times when we might want to generate our own
-3D geometry in code instead of using a modeling package.
-
-First let's just make a cube. Even though three.js already
-provides us with `BoxGeometry` and `BoxGeometry` a
-cube is easy to understand so let's start there.
-
-There are 2 ways to make custom geometry in THREE.js. One
-is with the `Geometry` class, the other is `BufferGeometry`.
-Each has their advantages. `Geometry` is arguably easier to
+to be useful.</p>
+<p>Still, there are times when we might want to generate our own
+3D geometry in code instead of using a modeling package.</p>
+<p>First let's just make a cube. Even though three.js already
+provides us with <a href="/docs/#api/en/geometries/BoxGeometry"><code class="notranslate" translate="no">BoxGeometry</code></a> and <a href="/docs/#api/en/geometries/BoxGeometry"><code class="notranslate" translate="no">BoxGeometry</code></a> a
+cube is easy to understand so let's start there.</p>
+<p>There are 2 ways to make custom geometry in THREE.js. One
+is with the <code class="notranslate" translate="no">Geometry</code> class, the other is <a href="/docs/#api/en/core/BufferGeometry"><code class="notranslate" translate="no">BufferGeometry</code></a>.
+Each has their advantages. <code class="notranslate" translate="no">Geometry</code> is arguably easier to
 use but slower and uses more memory. For few 1000s triangles
 it's a great choice but for 10s of thousands of triangles
-it might be better to use `BufferGeometry`.
-
-`BufferGeometry` is arguably harder to use but uses less
+it might be better to use <a href="/docs/#api/en/core/BufferGeometry"><code class="notranslate" translate="no">BufferGeometry</code></a>.</p>
+<p><a href="/docs/#api/en/core/BufferGeometry"><code class="notranslate" translate="no">BufferGeometry</code></a> is arguably harder to use but uses less
 memory and is faster. If quick rule of thumb might be
 if you're going to generate more than 10000 triangles
-consider using `BufferGeometry`.
-
-Note when I say `Geometry` is slower I mean it is slower to
+consider using <a href="/docs/#api/en/core/BufferGeometry"><code class="notranslate" translate="no">BufferGeometry</code></a>.</p>
+<p>Note when I say <code class="notranslate" translate="no">Geometry</code> is slower I mean it is slower to
 start and slower to modify but it is not slower to draw so
 if you're not planning on modifying your geometry then
 as long as it's not too large there will only be slightly more
-delay for your program to start using `Geometry` vs using
-`BufferGeometry`. We'll go over both eventually. For now
-though let's use geometry as it's easier to understand IMO.
-
-First let's make a cube with `Geometry`. We'll start
-with an example from [the article on responsiveness](threejs-responsive.html).
-
-Let's remove the part that uses `BoxGeometry` and replace it with
-a `Geometry`.
-
-```js
--const boxWidth = 1;
+delay for your program to start using <code class="notranslate" translate="no">Geometry</code> vs using
+<a href="/docs/#api/en/core/BufferGeometry"><code class="notranslate" translate="no">BufferGeometry</code></a>. We'll go over both eventually. For now
+though let's use geometry as it's easier to understand IMO.</p>
+<p>First let's make a cube with <code class="notranslate" translate="no">Geometry</code>. We'll start
+with an example from <a href="responsive.html">the article on responsiveness</a>.</p>
+<p>Let's remove the part that uses <a href="/docs/#api/en/geometries/BoxGeometry"><code class="notranslate" translate="no">BoxGeometry</code></a> and replace it with
+a <code class="notranslate" translate="no">Geometry</code>.</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);
 +const geometry = new THREE.Geometry();
-```
+</pre>
+<p>Now let's add the 8 corners of a cube. Here are the 8 corners.</p>
+<div class="threejs_center"><img src="../resources/cube-vertex-positions.svg" style="width: 500px"></div>
 
-Now let's add the 8 corners of a cube. Here are the 8 corners.
-
-<div class="threejs_center"><img src="resources/cube-vertex-positions.svg" style="width: 500px"></div>
-
-Centered around the origin we can add the vertex positions like this
-
-```js
-const geometry = new THREE.Geometry();
+<p>Centered around the origin we can add the vertex positions like this</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const geometry = new THREE.Geometry();
 +geometry.vertices.push(
 +  new THREE.Vector3(-1, -1,  1),  // 0
 +  new THREE.Vector3( 1, -1,  1),  // 1
@@ -83,26 +86,20 @@ const geometry = new THREE.Geometry();
 +  new THREE.Vector3(-1,  1, -1),  // 6
 +  new THREE.Vector3( 1,  1, -1),  // 7
 +);
-```
-
-We then need to make triangles, 2 for each face of the cube
-
-<div class="threejs_center"><img src="resources/cube-triangles.svg" style="width: 500px"></div>
+</pre>
+<p>We then need to make triangles, 2 for each face of the cube</p>
+<div class="threejs_center"><img src="../resources/cube-triangles.svg" style="width: 500px"></div>
 
-We do that by creating `Face3` objects and specifying the indices
-of the 3 vertices that make up that face.
-
-The order we specify the vertices is important. To be pointing toward the
+<p>We do that by creating <a href="/docs/#api/en/core/Face3"><code class="notranslate" translate="no">Face3</code></a> objects and specifying the indices
+of the 3 vertices that make up that face.</p>
+<p>The order we specify the vertices is important. To be pointing toward the
 outside of the cube they must be specified in a counter clockwise direction
-when that triangle is facing the camera.
-
-<div class="threejs_center"><img src="resources/cube-vertex-winding-order.svg" style="width: 500px"></div>
-
-Following that pattern we can specify the 12 triangles that make
-the cube like this
+when that triangle is facing the camera.</p>
+<div class="threejs_center"><img src="../resources/cube-vertex-winding-order.svg" style="width: 500px"></div>
 
-```js
-geometry.faces.push(
+<p>Following that pattern we can specify the 12 triangles that make
+the cube like this</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">geometry.faces.push(
   // front
   new THREE.Face3(0, 3, 2),
   new THREE.Face3(0, 1, 3),
@@ -122,16 +119,12 @@ geometry.faces.push(
   new THREE.Face3(4, 1, 0),
   new THREE.Face3(4, 5, 1),
 );
-```
-
-A few other minor changes to the original code and it should
-work.
-
-These cubes are twice as large as the `BoxGeometry` we were
-using before so let's move the camera back a little
-
-```js
-const fov = 75;
+</pre>
+<p>A few other minor changes to the original code and it should
+work.</p>
+<p>These cubes are twice as large as the <a href="/docs/#api/en/geometries/BoxGeometry"><code class="notranslate" translate="no">BoxGeometry</code></a> we were
+using before so let's move the camera back a little</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;
@@ -139,12 +132,9 @@ const near = 0.1;
 const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
 -camera.position.z = 2;
 +camera.position.z = 5;
-```
-
-and let's separate them a little more and I changed their colors just because
-
-```js
-const cubes = [
+</pre>
+<p>and let's separate them a little more and I changed their colors just because</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const cubes = [
 -  makeInstance(geometry, 0x44aa88,  0),
 -  makeInstance(geometry, 0x8844aa, -2),
 -  makeInstance(geometry, 0xaa8844,  2),
@@ -152,14 +142,11 @@ const cubes = [
 +  makeInstance(geometry, 0x4444FF, -4),
 +  makeInstance(geometry, 0xFF4444,  4),
 ];
-```
-
-One last thing is we haven't added normals yet so we
+</pre>
+<p>One last thing is we haven't added normals yet so we
 can't do any lighting. Let's change the material
-to something that doesn't need lights.
-
-```js
-function makeInstance(geometry, color, x) {
+to something that doesn't need lights.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function makeInstance(geometry, color, x) {
 -  const material = new THREE.MeshPhongMaterial({color});
 +  const material = new THREE.MeshBasicMaterial({color});
 
@@ -167,107 +154,96 @@ function makeInstance(geometry, color, x) {
   scene.add(cube);
 
   ...
-```
-
-and we get cubes we made ourselves.
-
-{{{example url="../threejs-custom-geometry-cube.html" }}}
-
-We can specify a color per face by setting the `color` property of
-each face.
+</pre>
+<p>and we get cubes we made ourselves.</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/custom-geometry-cube.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/custom-geometry-cube.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-```js
-geometry.faces[ 0].color = geometry.faces[ 1].color = new THREE.Color('red');
+<p></p>
+<p>We can specify a color per face by setting the <code class="notranslate" translate="no">color</code> property of
+each face.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">geometry.faces[ 0].color = geometry.faces[ 1].color = new THREE.Color('red');
 geometry.faces[ 2].color = geometry.faces[ 3].color = new THREE.Color('yellow');
 geometry.faces[ 4].color = geometry.faces[ 5].color = new THREE.Color('green');
 geometry.faces[ 6].color = geometry.faces[ 7].color = new THREE.Color('cyan');
 geometry.faces[ 8].color = geometry.faces[ 9].color = new THREE.Color('blue');
 geometry.faces[10].color = geometry.faces[11].color = new THREE.Color('magenta');
-```
-
-note we need to tell the material we want to use vertex colors
-
-```js
--const material = new THREE.MeshBasicMaterial({color});
+</pre>
+<p>note we need to tell the material we want to use vertex colors</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">-const material = new THREE.MeshBasicMaterial({color});
 +const material = new THREE.MeshBasicMaterial({vertexColors: true});
-```
-
-{{{example url="../threejs-custom-geometry-cube-face-colors.html" }}}
-
-We can instead set the color of each individual vertex by setting the `vertexColors`
-property of a `Face` to an array of the 3 colors for the 3 vertices.
+</pre>
+<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/custom-geometry-cube-face-colors.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/custom-geometry-cube-face-colors.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-```js
-geometry.faces.forEach((face, ndx) => {
+<p></p>
+<p>We can instead set the color of each individual vertex by setting the <code class="notranslate" translate="no">vertexColors</code>
+property of a <code class="notranslate" translate="no">Face</code> to an array of the 3 colors for the 3 vertices.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">geometry.faces.forEach((face, ndx) =&gt; {
   face.vertexColors = [
     (new THREE.Color()).setHSL(ndx / 12      , 1, 0.5),
     (new THREE.Color()).setHSL(ndx / 12 + 0.1, 1, 0.5),
     (new THREE.Color()).setHSL(ndx / 12 + 0.2, 1, 0.5),
   ];
 });
-```
-
-{{{example url="../threejs-custom-geometry-cube-vertex-colors.html" }}}
-
-To use lighting we need normals. Normals are vectors that specify direction.
-Just like the colors we can specify a normal for the face by setting the `normal`
-property on each face with
-
-```js
-face.normal = new THREE.Vector3(...)
-```
-
-or we can specify a normal for each vertex by setting the `vertexNormals`
-property with something like
+</pre>
+<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/custom-geometry-cube-vertex-colors.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/custom-geometry-cube-vertex-colors.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-```js
-face.vertexNormals = [
+<p></p>
+<p>To use lighting we need normals. Normals are vectors that specify direction.
+Just like the colors we can specify a normal for the face by setting the <code class="notranslate" translate="no">normal</code>
+property on each face with</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">face.normal = new THREE.Vector3(...)
+</pre>
+<p>or we can specify a normal for each vertex by setting the <code class="notranslate" translate="no">vertexNormals</code>
+property with something like</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">face.vertexNormals = [
   new THREE.Vector3(...),
   new THREE.Vector3(...),
   new THREE.Vector3(...),
 ]
-```
-
-but often it's much easier to just ask THREE.js to compute normals
-for us based on the positions we specified.
-
-For face normals we'd call `Geometry.computeFaceNormals` as in
-
-```js
-geometry.computeFaceNormals();
-```
-
-Removing the vertex color stuff and changing the material back to `MeshPhongMaterial`
-
-```js
--const material = new THREE.MeshBasicMaterial({vertexColors: true});
+</pre>
+<p>but often it's much easier to just ask THREE.js to compute normals
+for us based on the positions we specified.</p>
+<p>For face normals we'd call <code class="notranslate" translate="no">Geometry.computeFaceNormals</code> as in</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">geometry.computeFaceNormals();
+</pre>
+<p>Removing the vertex color stuff and changing the material back to <a href="/docs/#api/en/materials/MeshPhongMaterial"><code class="notranslate" translate="no">MeshPhongMaterial</code></a></p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">-const material = new THREE.MeshBasicMaterial({vertexColors: true});
 +const material = new THREE.MeshPhongMaterial({color});
-```
-
-and now our cubes can be lit.
-
-{{{example url="../threejs-custom-geometry-cube-face-normals.html" }}}
-
-Using face normals will always give us a faceted look. We can use
-vertex normals for a smoother look by calling `Geometry.computeVertexNormals`
+</pre>
+<p>and now our cubes can be lit.</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/custom-geometry-cube-face-normals.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/custom-geometry-cube-face-normals.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-```js
--geometry.computeFaceNormals();
+<p></p>
+<p>Using face normals will always give us a faceted look. We can use
+vertex normals for a smoother look by calling <code class="notranslate" translate="no">Geometry.computeVertexNormals</code></p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">-geometry.computeFaceNormals();
 +geometry.computeVertexNormals();
-```
-
-Unfortunately a cube is not a good candidate for vertex normals since it
+</pre>
+<p>Unfortunately a cube is not a good candidate for vertex normals since it
 means each vertex gets its normal from the
-normals of all the faces it shares.
-
-{{{example url="../threejs-custom-geometry-cube-vertex-normals.html" }}}
-
-Adding texture coordinates, sometimes called UVs, is done via an array of
-layers of parallel arrays to the `faces` array which is set via `Geometry.faceVertexUvs`.
-For our cube we could do something like
+normals of all the faces it shares.</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/custom-geometry-cube-vertex-normals.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/custom-geometry-cube-vertex-normals.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-```js
-geometry.faceVertexUvs[0].push(
+<p></p>
+<p>Adding texture coordinates, sometimes called UVs, is done via an array of
+layers of parallel arrays to the <code class="notranslate" translate="no">faces</code> array which is set via <code class="notranslate" translate="no">Geometry.faceVertexUvs</code>.
+For our cube we could do something like</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">geometry.faceVertexUvs[0].push(
   // front
   [ new THREE.Vector2(0, 0), new THREE.Vector2(1, 1), new THREE.Vector2(0, 1) ],
   [ new THREE.Vector2(0, 0), new THREE.Vector2(1, 0), new THREE.Vector2(1, 1) ],
@@ -287,16 +263,12 @@ geometry.faceVertexUvs[0].push(
   [ new THREE.Vector2(0, 0), new THREE.Vector2(1, 1), new THREE.Vector2(0, 1) ],
   [ new THREE.Vector2(0, 0), new THREE.Vector2(1, 0), new THREE.Vector2(1, 1) ],
 );
-```
-
-It's important to notice `faceVertexUvs` is an array of layers. Each layer
+</pre>
+<p>It's important to notice <code class="notranslate" translate="no">faceVertexUvs</code> is an array of layers. Each layer
 is another set of UV coordinates. By default there is one layer of UV coordinates,
-layer 0, so we just add our UVs to that layer.
-
-Let's [add a texture](threejs-textures.html) to our material and switch back to compute face normals
-
-```js
--geometry.computeVertexNormals();
+layer 0, so we just add our UVs to that layer.</p>
+<p>Let's <a href="textures.html">add a texture</a> to our material and switch back to compute face normals</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">-geometry.computeVertexNormals();
 +geometry.computeFaceNormals();
 
 +const loader = new THREE.TextureLoader();
@@ -310,25 +282,24 @@ function makeInstance(geometry, color, x) {
   scene.add(cube);
 
   ...
-```
-
-{{{example url="../threejs-custom-geometry-cube-texcoords.html" }}}
-
-Putting that all together, let's make a simple heightmap based
-terrain mesh.
+</pre>
+<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/custom-geometry-cube-texcoords.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/custom-geometry-cube-texcoords.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-A heightmap based terrain is where you have a 2D array of heights
+<p></p>
+<p>Putting that all together, let's make a simple heightmap based
+terrain mesh.</p>
+<p>A heightmap based terrain is where you have a 2D array of heights
 that you apply them to a grid. An easy way to get a 2D array of heights
 is to draw them in an image editing program. Here's an image I drew.
-It's 96x64 pixels
-
-<div class="threejs_center"><img src="../resources/images/heightmap-96x64.png" style="width: 512px; image-rendering: pixelated;"></div>
-
-We'll load that and then generate a heightmap mesh from it.
-We can use the `ImageLoader` to load the image.
+It's 96x64 pixels</p>
+<div class="threejs_center"><img src="../examples/resources/images/heightmap-96x64.png" style="width: 512px; image-rendering: pixelated;"></div>
 
-```js
-const imgLoader = new THREE.ImageLoader();
+<p>We'll load that and then generate a heightmap mesh from it.
+We can use the <a href="/docs/#api/en/loaders/ImageLoader"><code class="notranslate" translate="no">ImageLoader</code></a> to load the image.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const imgLoader = new THREE.ImageLoader();
 imgLoader.load('resources/images/heightmap-96x64.png', createHeightmap);
 
 function createHeightmap(image) {
@@ -342,23 +313,19 @@ function createHeightmap(image) {
   const {data} = ctx.getImageData(0, 0, width, height);
 
   const geometry = new THREE.Geometry();
-```
-
-We extracted the data from the image, now we'll make a grid of cells.
+</pre>
+<p>We extracted the data from the image, now we'll make a grid of cells.
 The cells are the squares formed by the center points of each pixel
-from the image
-
-<div class="threejs_center"><img src="resources/heightmap-points.svg" style="width: 500px"></div>
+from the image</p>
+<div class="threejs_center"><img src="../resources/heightmap-points.svg" style="width: 500px"></div>
 
-For each cell we'll generate 5 vertices. One for each corner of the cell
+<p>For each cell we'll generate 5 vertices. One for each corner of the cell
 and one at the center point of the cell with the average height of the 4
-corner heights.
-
-```js
-const cellsAcross = width - 1;
+corner heights.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const cellsAcross = width - 1;
 const cellsDeep = height - 1;
-for (let z = 0; z < cellsDeep; ++z) {
-  for (let x = 0; x < cellsAcross; ++x) {
+for (let z = 0; z &lt; cellsDeep; ++z) {
+  for (let x = 0; x &lt; cellsAcross; ++x) {
     // compute row offsets into the height data
     // we multiply by 4 because the data is R,G,B,A but we
     // only care about R
@@ -391,14 +358,11 @@ for (let z = 0; z < cellsDeep; ++z) {
       new THREE.Vector3(x1, h11, z1),
       new THREE.Vector3((x0 + x1) / 2, hm, (z0 + z1) / 2),
     );
-```
-
-We'll then make 4 triangles from those 5 vertices
-
-<div class="threejs_center"><img src="resources/heightmap-triangles.svg" style="width: 500px"></div>
+</pre>
+<p>We'll then make 4 triangles from those 5 vertices</p>
+<div class="threejs_center"><img src="../resources/heightmap-triangles.svg" style="width: 500px"></div>
 
-```js
-    // create 4 triangles
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">    // create 4 triangles
     geometry.faces.push(
       new THREE.Face3(ndx + 0, ndx + 4, ndx + 1),
       new THREE.Face3(ndx + 1, ndx + 4, ndx + 3),
@@ -421,12 +385,9 @@ We'll then make 4 triangles from those 5 vertices
     );
   }
 }
-```
-
-and finish it up
-
-```js
-  geometry.computeFaceNormals();
+</pre>
+<p>and finish it up</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">  geometry.computeFaceNormals();
 
   // center the geometry
   geometry.translate(width / -2, 0, height / -2);
@@ -439,19 +400,15 @@ and finish it up
   const cube = new THREE.Mesh(geometry, material);
   scene.add(cube);
 }
-```
-
-A few minor changes to make it easier to view.
-
-* include the `OrbitControls`
-
-```js
-import * as THREE from './resources/three/r132/build/three.module.js';
-+import {OrbitControls} from './resources/threejs/r132/examples/jsm/controls/OrbitControls.js';
-```
-
-```js
-const fov = 75;
+</pre>
+<p>A few minor changes to make it easier to view.</p>
+<ul>
+<li>include the <a href="/docs/#examples/controls/OrbitControls"><code class="notranslate" translate="no">OrbitControls</code></a></li>
+</ul>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">import * as THREE from '/build/three.module.js';
++import {OrbitControls} from '/examples/jsm/controls/OrbitControls.js';
+</pre>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const fov = 75;
 const aspect = 2;  // the canvas default
 const near = 0.1;
 -const far = 100;
@@ -463,12 +420,9 @@ const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
 +const controls = new OrbitControls(camera, canvas);
 +controls.target.set(0, 0, 0);
 +controls.update();
-```
-
-add 2 lights
-
-```js
--{
+</pre>
+<p>add 2 lights</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">-{
 +function addLight(...pos) {
   const color = 0xFFFFFF;
   const intensity = 1;
@@ -480,13 +434,26 @@ add 2 lights
 
 +addLight(-1, 2, 4);
 +addLight(1, 2, -2);
-```
+</pre>
+<p>and we deleted the code related to spinning the cubes.</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/custom-geometry-heightmap.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/custom-geometry-heightmap.html" target="_blank">click here to open in a separate window</a>
+</div>
+
+<p></p>
+<p>I hope that was a useful instruction to making your own
+geometry using <code class="notranslate" translate="no">Geometry</code>.</p>
+<p>In <a href="custom-buffergeometry.html">another article</a> we'll go over <a href="/docs/#api/en/core/BufferGeometry"><code class="notranslate" translate="no">BufferGeometry</code></a>.</p>
+
+        </div>
+      </div>
+    </div>
+  
+  <script src="/manual/resources/prettify.js"></script>
+  <script src="/manual/resources/lesson.js"></script>
 
-and we deleted the code related to spinning the cubes.
 
-{{{example url="../threejs-custom-geometry-heightmap.html" }}}
 
-I hope that was a useful instruction to making your own
-geometry using `Geometry`.
 
-In [another article](threejs-custom-buffergeometry.html) we'll go over `BufferGeometry`.
+</body></html>

+ 86 - 85
manual/en/debugging-glsl.html

@@ -1,112 +1,113 @@
-Title: Debugging Three.js - GLSL
-Description: How to debug GLSL Shaders
-TOC: Debugging GLSL
-
-This site so far does not teach GLSL just like it does not teach JavaScript.
+<!DOCTYPE html><html lang="en"><head>
+    <meta charset="utf-8">
+    <title>Debugging - GLSL</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 – Debugging - GLSL">
+    <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">
+  </head>
+  <body>
+    <div class="container">
+      <div class="lesson-title">
+        <h1>Debugging - GLSL</h1>
+      </div>
+      <div class="lesson">
+        <div class="lesson-main">
+          <p>This site so far does not teach GLSL just like it does not teach JavaScript.
 Those are really large topics. If you want to learn GLSL consider checking out
-[these articles](https://webglfundamentals.org) as a starting place.
-
-If you already know GLSL then here are a few tips for debugging.
-
-When I'm making a new GLSL shader and nothing appears generally
+<a href="https://webglfundamentals.org">these articles</a> as a starting place.</p>
+<p>If you already know GLSL then here are a few tips for debugging.</p>
+<p>When I'm making a new GLSL shader and nothing appears generally
 the first thing I do is change the fragment shader to return a solid
-color. For example at the very bottom of the shader I might put
-
-```glsl
-void main() {
+color. For example at the very bottom of the shader I might put</p>
+<pre class="prettyprint showlinemods notranslate lang-glsl" translate="no">void main() {
 
   ...
 
   gl_FragColor = vec4(1, 0, 0, 1);  // red
 }
-```
-
-If I see the object I was trying to draw then I know the issue is
+</pre>
+<p>If I see the object I was trying to draw then I know the issue is
 related to my fragment shader. It could be anything like bad textures,
 uninitialized uniforms, uniforms with the wrong values but at least
-I have a direction to look.
-
-To test some of those I might start trying to draw some of the inputs.
+I have a direction to look.</p>
+<p>To test some of those I might start trying to draw some of the inputs.
 For example if I'm using normals in the fragment shader then I might
-add
-
-```glsl
-gl_FragColor = vec4(vNormal * 0.5 + 0.5, 1);
-```
-
-Normals go from -1 to +1 so by multiplying by 0.5 and adding 0.5 we get
-values that go from 0.0 to 1.0 which makes them useful for colors.
-
-Try this with some things you know work and you'll start getting an idea
-of what normals *normally* look like. If your normals don't look normal
+add</p>
+<pre class="prettyprint showlinemods notranslate lang-glsl" translate="no">gl_FragColor = vec4(vNormal * 0.5 + 0.5, 1);
+</pre>
+<p>Normals go from -1 to +1 so by multiplying by 0.5 and adding 0.5 we get
+values that go from 0.0 to 1.0 which makes them useful for colors.</p>
+<p>Try this with some things you know work and you'll start getting an idea
+of what normals <em>normally</em> look like. If your normals don't look normal
 then you have some clue where to look. If you're manipulating normals
 in the fragments shader you can use the same technique to draw the
-result of that manipulation.
-
-<div class="threejs_center"><img src="resources/images/standard-primitive-normals.jpg" style="width: 650px;"></div>
-
-Similarly if we're using textures there will be texture coordinates and we
-can draw them with something like
-
-```glsl
-gl_FragColor = vec4(fract(vUv), 0, 1);
-```
-
-The `fract` is there in case we're using texture coordinates that go outside
-the 0 to 1 range. This is common if `texture.repeat` is set to something greater
-than 1.
-
-<div class="threejs_center"><img src="resources/images/standard-primitive-uvs.jpg" style="width: 650px;"></div>
-
-You can do similar things for all values in your fragment shader. Figure out
-what their range is likely to be, add some code to set `gl_FragColor` with
-that range scaled to 0.0 to 1.0
-
-To check textures try a `CanvasTexture` or a `DataTexture` that you 
-know works.
-
-Conversely, if after setting `gl_FragColor` to red I still see nothing
+result of that manipulation.</p>
+<div class="threejs_center"><img src="../resources/images/standard-primitive-normals.jpg" style="width: 650px;"></div>
+
+<p>Similarly if we're using textures there will be texture coordinates and we
+can draw them with something like</p>
+<pre class="prettyprint showlinemods notranslate lang-glsl" translate="no">gl_FragColor = vec4(fract(vUv), 0, 1);
+</pre>
+<p>The <code class="notranslate" translate="no">fract</code> is there in case we're using texture coordinates that go outside
+the 0 to 1 range. This is common if <code class="notranslate" translate="no">texture.repeat</code> is set to something greater
+than 1.</p>
+<div class="threejs_center"><img src="../resources/images/standard-primitive-uvs.jpg" style="width: 650px;"></div>
+
+<p>You can do similar things for all values in your fragment shader. Figure out
+what their range is likely to be, add some code to set <code class="notranslate" translate="no">gl_FragColor</code> with
+that range scaled to 0.0 to 1.0</p>
+<p>To check textures try a <a href="/docs/#api/en/textures/CanvasTexture"><code class="notranslate" translate="no">CanvasTexture</code></a> or a <a href="/docs/#api/en/textures/DataTexture"><code class="notranslate" translate="no">DataTexture</code></a> that you 
+know works.</p>
+<p>Conversely, if after setting <code class="notranslate" translate="no">gl_FragColor</code> to red I still see nothing
 then I have a hint my issue might be in the direction of the things
 related to the vertex shader. Some matrices might be wrong or my
-attributes might have bad data or be setup incorrectly.
-
-I'd first look at the matrices. I might put a breakpoint right after
-my call to `renderer.render(scene, camera)` and then start expanding
+attributes might have bad data or be setup incorrectly.</p>
+<p>I'd first look at the matrices. I might put a breakpoint right after
+my call to <code class="notranslate" translate="no">renderer.render(scene, camera)</code> and then start expanding
 things in the inspector. Is the camera's world matrix and projection
-matrix at least not full of `NaN`s? Expanding the scene and looking
-at its `children` I'd check that the world matrices look reasonable (no `NaN`s)
+matrix at least not full of <code class="notranslate" translate="no">NaN</code>s? Expanding the scene and looking
+at its <code class="notranslate" translate="no">children</code> I'd check that the world matrices look reasonable (no <code class="notranslate" translate="no">NaN</code>s)
 and last 4 values of each matrix look reasonable for my scene. If I 
 expect my scene to be 50x50x50 units and some matrix shows 552352623.123 
-clearly something is wrong there.
-
-<div class="threejs_center"><img src="resources/images/inspect-matrices.gif"></div>
+clearly something is wrong there.</p>
+<div class="threejs_center"><img src="../resources/images/inspect-matrices.gif"></div>
 
-Just like we did for the fragment shader we can also draw values from the
+<p>Just like we did for the fragment shader we can also draw values from the
 vertex shader by passing them to the fragment shader. Declare a varying
 in both and pass the value you're not sure is correct. In fact if my
 shader use using normals I'll change the fragment shader to display them
-like is mentioned above and then just set `vNormal` to the value I want 
+like is mentioned above and then just set <code class="notranslate" translate="no">vNormal</code> to the value I want 
 to display but scaled so the values go from 0.0 to 1.0. I then look at the
-results and see if they fit my expectations.
-
-Another good thing to do is use a simpler shader. Can you draw your data
-with `MeshBasicMaterial`? If you can then try it and make sure it shows
-up as expected.
-
-If not what's the simplest vertex shader that will let you visualize your
-geometry? Usually it's as simple as
-
-```glsl
-gl_Position = projection * modelView * vec4(position.xyz, 1);
-```
-
-If that works start adding in your changes a little at a time.
-
-Yet another thing you can do is use the
-[Shader Editor extension for Chrome](https://chrome.google.com/webstore/detail/shader-editor/ggeaidddejpbakgafapihjbgdlbbbpob?hl=en)
+results and see if they fit my expectations.</p>
+<p>Another good thing to do is use a simpler shader. Can you draw your data
+with <a href="/docs/#api/en/materials/MeshBasicMaterial"><code class="notranslate" translate="no">MeshBasicMaterial</code></a>? If you can then try it and make sure it shows
+up as expected.</p>
+<p>If not what's the simplest vertex shader that will let you visualize your
+geometry? Usually it's as simple as</p>
+<pre class="prettyprint showlinemods notranslate lang-glsl" translate="no">gl_Position = projection * modelView * vec4(position.xyz, 1);
+</pre>
+<p>If that works start adding in your changes a little at a time.</p>
+<p>Yet another thing you can do is use the
+<a href="https://chrome.google.com/webstore/detail/shader-editor/ggeaidddejpbakgafapihjbgdlbbbpob?hl=en">Shader Editor extension for Chrome</a>
 or similar for other browsers. It's a great way to look at how other shaders
 are working. It's also good as you can make some of the changes suggested above
-live while the code is running.
+live while the code is running.</p>
+
+        </div>
+      </div>
+    </div>
+  
+  <script src="/manual/resources/prettify.js"></script>
+  <script src="/manual/resources/lesson.js"></script>
+
 
 
 
+</body></html>

+ 308 - 394
manual/en/debugging-javascript.html

@@ -1,137 +1,117 @@
-Title: Three.js Debugging JavaScript
-Description: How to debug JavaScript with THREE.js
-TOC: Debugging JavaScript
-
-Most of this article is not directly about THREE.js but is
+<!DOCTYPE html><html lang="en"><head>
+    <meta charset="utf-8">
+    <title>Debugging JavaScript</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 – Debugging JavaScript">
+    <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">
+  </head>
+  <body>
+    <div class="container">
+      <div class="lesson-title">
+        <h1>Debugging JavaScript</h1>
+      </div>
+      <div class="lesson">
+        <div class="lesson-main">
+          <p>Most of this article is not directly about THREE.js but is
 rather about debugging JavaScript in general. It seemed important in
 that many people just starting with THREE.js are also just
 starting with JavaScript so I hope this can help them more easily
-solve any issues they run into.
-
-Debugging is a big topic and I probably can't begin to cover
+solve any issues they run into.</p>
+<p>Debugging is a big topic and I probably can't begin to cover
 everything there is to know but if you're new to JavaScript
 then here's an attempt to give a few pointers. I strongly
 suggest you take some time to learn them. They'll help you 
-enormously in your learning.
-
-## Learn your Browser's Developer Tools
-
-All browsers have developer tools. 
-[Chrome](https://developers.google.com/web/tools/chrome-devtools/),
-[Firefox](https://developer.mozilla.org/en-US/docs/Tools), 
-[Safari](https://developer.apple.com/safari/tools/), 
-[Edge](https://docs.microsoft.com/en-us/microsoft-edge/devtools-guide).
-
-In Chrome you can click the the `⋮` icon, pick More Tools->Developer Tools
-to get to the developer tools. A keyboard shortcut is also shown there.
-
-<div class="threejs_center"><img class="border" src="resources/images/devtools-chrome.jpg" style="width: 789px;"></div>
-
-In Firefox you click the `☰` icon, pick "Web Developer", then pick
-"Toggle Tools"
-
-<div class="threejs_center"><img class="border" src="resources/images/devtools-firefox.jpg" style="width: 786px;"></div>
-
-In Safari you first have to enable the Develop menu from the 
-Advanced Safari Preferences.
-
-<div class="threejs_center"><img class="border" src="resources/images/devtools-enable-safari.jpg" style="width: 775px;"></div>
-
-Then in the Develop menu you can pick "Show/Connect Web Inspector".
-
-<div class="threejs_center"><img class="border" src="resources/images/devtools-safari.jpg" style="width: 777px;"></div>
-
-With Chrome you can also [use Chrome on your computer to debug webpages running on Chrome on your Android phone or tablet](https://developers.google.com/web/tools/chrome-devtools/remote-debugging/).
+enormously in your learning.</p>
+<h2 id="learn-your-browser-s-developer-tools">Learn your Browser's Developer Tools</h2>
+<p>All browsers have developer tools. 
+<a href="https://developers.google.com/web/tools/chrome-devtools/">Chrome</a>,
+<a href="https://developer.mozilla.org/en-US/docs/Tools">Firefox</a>, 
+<a href="https://developer.apple.com/safari/tools/">Safari</a>, 
+<a href="https://docs.microsoft.com/en-us/microsoft-edge/devtools-guide">Edge</a>.</p>
+<p>In Chrome you can click the the <code class="notranslate" translate="no">⋮</code> icon, pick More Tools-&gt;Developer Tools
+to get to the developer tools. A keyboard shortcut is also shown there.</p>
+<div class="threejs_center"><img class="border" src="../resources/images/devtools-chrome.jpg" style="width: 789px;"></div>
+
+<p>In Firefox you click the <code class="notranslate" translate="no">☰</code> icon, pick "Web Developer", then pick
+"Toggle Tools"</p>
+<div class="threejs_center"><img class="border" src="../resources/images/devtools-firefox.jpg" style="width: 786px;"></div>
+
+<p>In Safari you first have to enable the Develop menu from the 
+Advanced Safari Preferences.</p>
+<div class="threejs_center"><img class="border" src="../resources/images/devtools-enable-safari.jpg" style="width: 775px;"></div>
+
+<p>Then in the Develop menu you can pick "Show/Connect Web Inspector".</p>
+<div class="threejs_center"><img class="border" src="../resources/images/devtools-safari.jpg" style="width: 777px;"></div>
+
+<p>With Chrome you can also <a href="https://developers.google.com/web/tools/chrome-devtools/remote-debugging/">use Chrome on your computer to debug webpages running on Chrome on your Android phone or tablet</a>.
 Similarly with Safari you can 
-[use your computer to debug webpages running on Safari on iPhones and iPads](https://www.google.com/search?q=safari+remote+debugging+ios).
-
-I'm most familiar with Chrome so this guide will be using Chrome
+<a href="https://www.google.com/search?q=safari+remote+debugging+ios">use your computer to debug webpages running on Safari on iPhones and iPads</a>.</p>
+<p>I'm most familiar with Chrome so this guide will be using Chrome
 as an example when referring to tools but most browsers have similar
-features so it should be easy to apply anything here to all browsers.
-
-## Turn off the cache
-
-Browsers try to reuse data they've already downloaded. This is great
+features so it should be easy to apply anything here to all browsers.</p>
+<h2 id="turn-off-the-cache">Turn off the cache</h2>
+<p>Browsers try to reuse data they've already downloaded. This is great
 for users so if you visit a website a second time many of the files
-used to display the site will not have be downloaded again.
-
-On the other hand this can be bad for web development. You change
+used to display the site will not have be downloaded again.</p>
+<p>On the other hand this can be bad for web development. You change
 a file on your computer, reload the page, and you don't see the changes
-because the browser uses the version it got last time.
-
-One solution during web development is to turn off the cache. This
-way the browser will always get the newest versions of your files.
-
-First pick settings from the corner menu
-
-<div class="threejs_center"><img class="border" src="resources/images/devtools-chrome-settings.jpg" style="width: 778px"></div>
-
-Then pick "Disable Cache (while DevTools is open)".
-
-<div class="threejs_center"><img class="border" src="resources/images/devtools-chrome-disable-cache.jpg" style="width: 779px"></div>
-
-## Use the JavaScript console
-
-Inside all devtools is a *console*. It shows warnings and error messages.
-
-** READ THE MESSAGES!! **
-
-Typically there should be only 1 or 2 messages.
-
-<div class="threejs_center"><img class="border" src="resources/images/devtools-no-errors.jpg" style="width: 779px"></div>
-
-If you see any others **READ THEM**. For example:
-
-<div class="threejs_center"><img class="border" src="resources/images/devtools-errors.jpg" style="width: 779px"></div>
-
-I mis-spelled "three" as "threee"
-
-You can also print your own info to the console with with `console.log` as in
-
-```js
-console.log(someObject.position.x, someObject.position.y, someObject.position.z);
-```
-
-Even cooler, if you log an object you can inspect it. For example if we log
-the root scene object from [the gLTF article](threejs-load-gltf.html)
-
-```js
-  {
+because the browser uses the version it got last time.</p>
+<p>One solution during web development is to turn off the cache. This
+way the browser will always get the newest versions of your files.</p>
+<p>First pick settings from the corner menu</p>
+<div class="threejs_center"><img class="border" src="../resources/images/devtools-chrome-settings.jpg" style="width: 778px"></div>
+
+<p>Then pick "Disable Cache (while DevTools is open)".</p>
+<div class="threejs_center"><img class="border" src="../resources/images/devtools-chrome-disable-cache.jpg" style="width: 779px"></div>
+
+<h2 id="use-the-javascript-console">Use the JavaScript console</h2>
+<p>Inside all devtools is a <em>console</em>. It shows warnings and error messages.</p>
+<p><strong> READ THE MESSAGES!! </strong></p>
+<p>Typically there should be only 1 or 2 messages.</p>
+<div class="threejs_center"><img class="border" src="../resources/images/devtools-no-errors.jpg" style="width: 779px"></div>
+
+<p>If you see any others <strong>READ THEM</strong>. For example:</p>
+<div class="threejs_center"><img class="border" src="../resources/images/devtools-errors.jpg" style="width: 779px"></div>
+
+<p>I mis-spelled "three" as "threee"</p>
+<p>You can also print your own info to the console with with <code class="notranslate" translate="no">console.log</code> as in</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">console.log(someObject.position.x, someObject.position.y, someObject.position.z);
+</pre>
+<p>Even cooler, if you log an object you can inspect it. For example if we log
+the root scene object from <a href="load-gltf.html">the gLTF article</a></p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">  {
     const gltfLoader = new GLTFLoader();
-    gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) => {
+    gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) =&gt; {
       const root = gltf.scene;
       scene.add(root);
 +      console.log(root);
-```
-
-Then we can expand that object in the JavaScript console
-
-<div class="threejs_center"><img class="border" src="resources/images/devtools-console-object.gif"></div>
-
-You can also use `console.error` which reports the message in red
-in includes a stack trace.
-
-## Put data on screen
-
-Another obvious but often overlooked way is to add `<div>` or `<pre>` tags
-and put data in them.
-
-The most obvious way is to make some HTML elements
-
-```html
-<canvas id="c"></canvas>
-+<div id="debug">
-+  <div>x:<span id="x"></span></div>
-+  <div>y:<span id="y"></span></div>
-+  <div>z:<span id="z"></span></div>
-+</div>
-```
-
-Style them so they stay on top of the canvas. (assuming your canvas
-fills the page)
-
-```html
-<style>
+</pre>
+<p>Then we can expand that object in the JavaScript console</p>
+<div class="threejs_center"><img class="border" src="../resources/images/devtools-console-object.gif"></div>
+
+<p>You can also use <code class="notranslate" translate="no">console.error</code> which reports the message in red
+in includes a stack trace.</p>
+<h2 id="put-data-on-screen">Put data on screen</h2>
+<p>Another obvious but often overlooked way is to add <code class="notranslate" translate="no">&lt;div&gt;</code> or <code class="notranslate" translate="no">&lt;pre&gt;</code> tags
+and put data in them.</p>
+<p>The most obvious way is to make some HTML elements</p>
+<pre class="prettyprint showlinemods notranslate lang-html" translate="no">&lt;canvas id="c"&gt;&lt;/canvas&gt;
++&lt;div id="debug"&gt;
++  &lt;div&gt;x:&lt;span id="x"&gt;&lt;/span&gt;&lt;/div&gt;
++  &lt;div&gt;y:&lt;span id="y"&gt;&lt;/span&gt;&lt;/div&gt;
++  &lt;div&gt;z:&lt;span id="z"&gt;&lt;/span&gt;&lt;/div&gt;
++&lt;/div&gt;
+</pre>
+<p>Style them so they stay on top of the canvas. (assuming your canvas
+fills the page)</p>
+<pre class="prettyprint showlinemods notranslate lang-html" translate="no">&lt;style&gt;
 #debug {
   position: absolute;
   left: 1em;
@@ -141,13 +121,10 @@ fills the page)
   color: white;
   font-family: monospace;
 }
-</style>
-```
-
-And then looking the elements up and setting their content.
-
-```js
-// at init time
+&lt;/style&gt;
+</pre>
+<p>And then looking the elements up and setting their content.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">// at init time
 const xElem = document.querySelector('#x');
 const yElem = document.querySelector('#y');
 const zElem = document.querySelector('#z');
@@ -156,32 +133,28 @@ const zElem = document.querySelector('#z');
 xElem.textContent = someObject.position.x.toFixed(3);
 yElem.textContent = someObject.position.y.toFixed(3);
 zElem.textContent = someObject.position.z.toFixed(3);
-```
-
-This is more useful for real time values
-
-{{{example url="../threejs-debug-js-html-elements.html" }}}
+</pre>
+<p>This is more useful for real time values</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/debug-js-html-elements.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/debug-js-html-elements.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-Another way to put data on the screen is to make a clearing logger.
+<p></p>
+<p>Another way to put data on the screen is to make a clearing logger.
 I just made that term up but lots of games I've worked on have used this solution. The idea
 is you have a buffer that displays messages for only one frame.
 Any part of your code that wants to display data calls some function
 to add data to that buffer every frame. This is much less work
-than making an element per piece of data above.
-
-For example let's change the HTML from above to just this
-
-```html
-<canvas id="c"></canvas>
-<div id="debug">
-  <pre></pre>
-</div>
-```
-
-And let's make simple class to manage this *clear back buffer*.
-
-```js
-class ClearingLogger {
+than making an element per piece of data above.</p>
+<p>For example let's change the HTML from above to just this</p>
+<pre class="prettyprint showlinemods notranslate lang-html" translate="no">&lt;canvas id="c"&gt;&lt;/canvas&gt;
+&lt;div id="debug"&gt;
+  &lt;pre&gt;&lt;/pre&gt;
+&lt;/div&gt;
+</pre>
+<p>And let's make simple class to manage this <em>clear back buffer</em>.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">class ClearingLogger {
   constructor(elem) {
     this.elem = elem;
     this.lines = [];
@@ -194,16 +167,12 @@ class ClearingLogger {
     this.lines = [];
   }
 }
-```
-
-Then let's make a simple example that every time we click the mouse makes a mesh
+</pre>
+<p>Then let's make a simple example that every time we click the mouse makes a mesh
 that moves in a random direction for 2 seconds. We'll start with one of the
-examples from the article on [making things responsive](threejs-responsive.html)
-
-Here's the code that adds a new `Mesh` every time we click the mouse
-
-```js
-const geometry = new THREE.SphereGeometry();
+examples from the article on <a href="responsive.html">making things responsive</a></p>
+<p>Here's the code that adds a new <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a> every time we click the mouse</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const geometry = new THREE.SphereGeometry();
 const material = new THREE.MeshBasicMaterial({color: 'red'});
 
 const things = [];
@@ -227,13 +196,10 @@ function createThing() {
 }
 
 canvas.addEventListener('click', createThing);
-```
-
-And here's the code that moves the meshes we created, logs them,
-and removes them when their timer has run out
-
-```js
-const logger = new ClearingLogger(document.querySelector('#debug pre'));
+</pre>
+<p>And here's the code that moves the meshes we created, logs them,
+and removes them when their timer has run out</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const logger = new ClearingLogger(document.querySelector('#debug pre'));
 
 let then = 0;
 function render(now) {
@@ -245,7 +211,7 @@ function render(now) {
 
   logger.log('fps:', (1 / deltaTime).toFixed(1));
   logger.log('num things:', things.length);
-  for (let i = 0; i < things.length;) {
+  for (let i = 0; i &lt; things.length;) {
     const thing = things[i];
     const mesh = thing.mesh;
     const pos = mesh.position;
@@ -253,7 +219,7 @@ function render(now) {
         'timer:', thing.timer.toFixed(3), 
         'pos:', pos.x.toFixed(3), pos.y.toFixed(3), pos.z.toFixed(3));
     thing.timer -= deltaTime;
-    if (thing.timer <= 0) {
+    if (thing.timer &lt;= 0) {
       // remove this thing. Note we don't advance `i`
       things.splice(i, 1);
       scene.remove(mesh);
@@ -268,33 +234,28 @@ function render(now) {
 
   requestAnimationFrame(render);
 }
-```
-
-Now click the mouse a bunch in the example below
-
-{{{example url="../threejs-debug-js-clearing-logger.html" }}}
-
-## Query Parameters
+</pre>
+<p>Now click the mouse a bunch in the example below</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/debug-js-clearing-logger.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/debug-js-clearing-logger.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-Another thing to remember is that webpages can have data passed
+<p></p>
+<h2 id="query-parameters">Query Parameters</h2>
+<p>Another thing to remember is that webpages can have data passed
 into them either via query parameters or the anchor, sometimes called
-the search and the hash.
-
-    https://domain/path/?query#anchor
-
-You can use this to make features optional or pass in parameters.
-
-For example let's take the previous example and make it so
-the debug stuff only shows up if we put `?debug=true` in the URL.
-
-First we need some code to parse the query string
-
-```js
-/**
+the search and the hash.</p>
+<pre class="prettyprint showlinemods notranslate notranslate" translate="no">https://domain/path/?query#anchor
+</pre><p>You can use this to make features optional or pass in parameters.</p>
+<p>For example let's take the previous example and make it so
+the debug stuff only shows up if we put <code class="notranslate" translate="no">?debug=true</code> in the URL.</p>
+<p>First we need some code to parse the query string</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">/**
   * Returns the query parameters as a key/value object. 
   * Example: If the query parameters are
   *
-  *    abc=123&def=456&name=gman
+  *    abc=123&amp;def=456&amp;name=gman
   *
   * Then `getQuery()` will return an object like
   *
@@ -307,22 +268,16 @@ First we need some code to parse the query string
 function getQuery() {
   return Object.fromEntries(new URLSearchParams(window.location.search).entries());
 }
-```
-
-Then we might make the debug element not show by default
-
-```html
-<canvas id="c"></canvas>
-+<div id="debug" style="display: none;">
-  <pre></pre>
-</div>
-```
-
-Then in the code we read the params and choose to un-hide the
-debug info if and only if `?debug=true` is passed in
-
-```js
-const query = getQuery();
+</pre>
+<p>Then we might make the debug element not show by default</p>
+<pre class="prettyprint showlinemods notranslate lang-html" translate="no">&lt;canvas id="c"&gt;&lt;/canvas&gt;
++&lt;div id="debug" style="display: none;"&gt;
+  &lt;pre&gt;&lt;/pre&gt;
+&lt;/div&gt;
+</pre>
+<p>Then in the code we read the params and choose to un-hide the
+debug info if and only if <code class="notranslate" translate="no">?debug=true</code> is passed in</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const query = getQuery();
 const debug = query.debug === 'true';
 const logger = debug
    ? new ClearingLogger(document.querySelector('#debug pre'))
@@ -330,98 +285,68 @@ const logger = debug
 if (debug) {
   document.querySelector('#debug').style.display = '';
 }
-```
-
-We also made a `DummyLogger` that does nothing and chose to use it if `?debug=true` has not been passed in.
-
-```js
-class DummyLogger {
+</pre>
+<p>We also made a <code class="notranslate" translate="no">DummyLogger</code> that does nothing and chose to use it if <code class="notranslate" translate="no">?debug=true</code> has not been passed in.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">class DummyLogger {
   log() {}
   render() {}
 }
-```
-
-You can see if we use this url:
-
-<a target="_blank" href="../threejs-debug-js-params.html">threejs-debug-js-params.html</a>
-
-there is no debug info but if we use this url:
-
-<a target="_blank" href="../threejs-debug-js-params.html?debug=true">threejs-debug-js-params.html?debug=true</a>
-
-there is debug info.
-
-Multiple parameters can be passed in by separating with '&' as in `somepage.html?someparam=somevalue&someotherparam=someothervalue`. 
-Using parameters like this we can pass in all kinds of options. Maybe `speed=0.01` to slow down our app for making it easier to understand something or `showHelpers=true` for whether or not to add helpers
-that show the lights, shadow, or camera frustum seen in other lessons.
-
-## Learn to use the Debugger
-
-Every browser has a debugger where you can pause your program
-step through line by line and inspect all the variables.
-
-Teaching you how to use a debugger is too big a topic for this
-article but here's a few links
-
-* [Get Started with Debugging JavaScript in Chrome DevTools](https://developers.google.com/web/tools/chrome-devtools/javascript/)
-* [Debugging in Chrome](https://javascript.info/debugging-chrome)
-* [Tips and Tricks for Debugging in Chrome Developer Tools](https://hackernoon.com/tips-and-tricks-for-debugging-in-chrome-developer-tools-458ade27c7ab)
-
-## Check for `NaN` in the debugger or elsewhere
-
-`NaN` is short for Not A Number. It's what JavaScript will assign
-as a value when you do something that doesn't make sense mathwise.
-
-As a simple example
-
-<div class="threejs_center"><img class="border" src="resources/images/nan-banana.png" style="width: 180px;"></div>
-
-Often when I'm making something and nothing appears on the screen
-I'll check some values and if I see `NaN` I will instantly have a 
-place to start looking.
-
-As an example when I first started making the path for the
-[article about loading gLTF files](threejs-load-gltf.html) I made
-a curve using the `SplineCurve` class which makes a 2D curve.
-
-I then used that curve to move the cars like this
-
-```js
-curve.getPointAt(zeroToOnePointOnCurve, car.position);
-```
-
-Internally `curve.getPointAt` calls the `set` function
+</pre>
+<p>You can see if we use this url:</p>
+<p><a target="_blank" href="../examples/debug-js-params.html">debug-js-params.html</a></p>
+<p>there is no debug info but if we use this url:</p>
+<p><a target="_blank" href="../examples/debug-js-params.html?debug=true">debug-js-params.html?debug=true</a></p>
+<p>there is debug info.</p>
+<p>Multiple parameters can be passed in by separating with '&amp;' as in <code class="notranslate" translate="no">somepage.html?someparam=somevalue&amp;someotherparam=someothervalue</code>. 
+Using parameters like this we can pass in all kinds of options. Maybe <code class="notranslate" translate="no">speed=0.01</code> to slow down our app for making it easier to understand something or <code class="notranslate" translate="no">showHelpers=true</code> for whether or not to add helpers
+that show the lights, shadow, or camera frustum seen in other lessons.</p>
+<h2 id="learn-to-use-the-debugger">Learn to use the Debugger</h2>
+<p>Every browser has a debugger where you can pause your program
+step through line by line and inspect all the variables.</p>
+<p>Teaching you how to use a debugger is too big a topic for this
+article but here's a few links</p>
+<ul>
+<li><a href="https://developers.google.com/web/tools/chrome-devtools/javascript/">Get Started with Debugging JavaScript in Chrome DevTools</a></li>
+<li><a href="https://javascript.info/debugging-chrome">Debugging in Chrome</a></li>
+<li><a href="https://hackernoon.com/tips-and-tricks-for-debugging-in-chrome-developer-tools-458ade27c7ab">Tips and Tricks for Debugging in Chrome Developer Tools</a></li>
+</ul>
+<h2 id="check-for-nan-in-the-debugger-or-elsewhere">Check for <code class="notranslate" translate="no">NaN</code> in the debugger or elsewhere</h2>
+<p><code class="notranslate" translate="no">NaN</code> is short for Not A Number. It's what JavaScript will assign
+as a value when you do something that doesn't make sense mathwise.</p>
+<p>As a simple example</p>
+<div class="threejs_center"><img class="border" src="../resources/images/nan-banana.png" style="width: 180px;"></div>
+
+<p>Often when I'm making something and nothing appears on the screen
+I'll check some values and if I see <code class="notranslate" translate="no">NaN</code> I will instantly have a 
+place to start looking.</p>
+<p>As an example when I first started making the path for the
+<a href="load-gltf.html">article about loading gLTF files</a> I made
+a curve using the <a href="/docs/#api/en/extras/curves/SplineCurve"><code class="notranslate" translate="no">SplineCurve</code></a> class which makes a 2D curve.</p>
+<p>I then used that curve to move the cars like this</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">curve.getPointAt(zeroToOnePointOnCurve, car.position);
+</pre>
+<p>Internally <code class="notranslate" translate="no">curve.getPointAt</code> calls the <code class="notranslate" translate="no">set</code> function
 on the object passed as the second argument. In this case that
-second argument is `car.position` which is a `Vector3`. `Vector3`'s
-`set` function requires 3 arguments, x, y, and z but `SplineCurve` is a 2D curve
-and so it calls `car.position.set` with just x and y.
-
-The result is that `car.position.set` sets x to x, y to y, and z to `undefined`.
-
-A quick glance in the debugger looking at the car's `matrixWorld`
-showed a bunch of `NaN` values.
-
-<div class="threejs_center"><img class="border" src="resources/images/debugging-nan.gif" style="width: 476px;"></div>
-
-Seeing the matrix had `NaN`s in it suggested something like `position`,
-`rotation`, `scale` or some other function that affects that matrix had bad
-data. Working backward from their it was easy to track down the issue.
-
-In top of `NaN` there's also `Infinity` which is a similar sign there
-is a math bug somewhere.
-
-## Look In the Code!
-
-THREE.js is Open Source. Don't be afraid to look inside the code!
-You can look inside on [github](https://github.com/mrdoob/three.js).
-You can also look inside by stepping into functions in the debugger.
-
-## Put `requestAnimationFrame` at bottom of your render function.
-
-I see this pattern often
-
-```js
-function render() {
+second argument is <code class="notranslate" translate="no">car.position</code> which is a <a href="/docs/#api/en/math/Vector3"><code class="notranslate" translate="no">Vector3</code></a>. <a href="/docs/#api/en/math/Vector3"><code class="notranslate" translate="no">Vector3</code></a>'s
+<code class="notranslate" translate="no">set</code> function requires 3 arguments, x, y, and z but <a href="/docs/#api/en/extras/curves/SplineCurve"><code class="notranslate" translate="no">SplineCurve</code></a> is a 2D curve
+and so it calls <code class="notranslate" translate="no">car.position.set</code> with just x and y.</p>
+<p>The result is that <code class="notranslate" translate="no">car.position.set</code> sets x to x, y to y, and z to <code class="notranslate" translate="no">undefined</code>.</p>
+<p>A quick glance in the debugger looking at the car's <code class="notranslate" translate="no">matrixWorld</code>
+showed a bunch of <code class="notranslate" translate="no">NaN</code> values.</p>
+<div class="threejs_center"><img class="border" src="../resources/images/debugging-nan.gif" style="width: 476px;"></div>
+
+<p>Seeing the matrix had <code class="notranslate" translate="no">NaN</code>s in it suggested something like <code class="notranslate" translate="no">position</code>,
+<code class="notranslate" translate="no">rotation</code>, <code class="notranslate" translate="no">scale</code> or some other function that affects that matrix had bad
+data. Working backward from their it was easy to track down the issue.</p>
+<p>In top of <code class="notranslate" translate="no">NaN</code> there's also <code class="notranslate" translate="no">Infinity</code> which is a similar sign there
+is a math bug somewhere.</p>
+<h2 id="look-in-the-code-">Look In the Code!</h2>
+<p>THREE.js is Open Source. Don't be afraid to look inside the code!
+You can look inside on <a href="https://github.com/mrdoob/three.js">github</a>.
+You can also look inside by stepping into functions in the debugger.</p>
+<h2 id="put-requestanimationframe-at-bottom-of-your-render-function-">Put <code class="notranslate" translate="no">requestAnimationFrame</code> at bottom of your render function.</h2>
+<p>I see this pattern often</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function render() {
    requestAnimationFrame(render);
 
    // -- do stuff --
@@ -429,13 +354,10 @@ function render() {
    renderer.render(scene, camera);
 }
 requestAnimationFrame(render);
-```
-
-I'd suggest that putting the call to `requestAnimationFrame` at
-the bottom as in
-
-```js
-function render() {
+</pre>
+<p>I'd suggest that putting the call to <code class="notranslate" translate="no">requestAnimationFrame</code> at
+the bottom as in</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function render() {
    // -- do stuff --
 
    renderer.render(scene, camera);
@@ -443,24 +365,20 @@ function render() {
    requestAnimationFrame(render);
 }
 requestAnimationFrame(render);
-```
-
-The biggest reason is it means your code will stop if you have an error. Putting
-`requestAnimationFrame` at the top means your code will keep running even if you
+</pre>
+<p>The biggest reason is it means your code will stop if you have an error. Putting
+<code class="notranslate" translate="no">requestAnimationFrame</code> at the top means your code will keep running even if you
 have an error since you already requested another frame. IMO it's better to find
 those errors than to ignore them. They could easily be the reason something is
 not appearing as you expect it to but unless your code stops you might not even
-notice.
-
-## Check your units!
-
-This basically means knowing for example when to use degrees vs
+notice.</p>
+<h2 id="check-your-units-">Check your units!</h2>
+<p>This basically means knowing for example when to use degrees vs
 when to use radians. It's unfortunate that THREE.js does not
 consistently use the same units everywhere. Off the top of my head
 the camera's field of view is in degrees. All other angles are in
-radians.
-
-The other place to look out is your world unit size. Until
+radians.</p>
+<p>The other place to look out is your world unit size. Until
 recently 3D apps could choose any unit size they wanted. One app might choose
 1 unit = 1cm. Another might choose 1 unit = 1 foot. It's actually still
 true that you can chose any units you want for certain applications.
@@ -468,113 +386,109 @@ That said, THREE.js assumes 1 unit = 1 meter. This is important for
 things like physically based rendering which uses meters to compute
 lighting effects. It's also important for AR and VR which need to
 deal with real world units like where your phone is or where the VR
-controllers are.
-
-## Making a *Minimal, Complete, Verifiable, Example* for Stack Overflow
-
-If you decide to ask a question about THREE.js it's almost always
+controllers are.</p>
+<h2 id="making-a-minimal-complete-verifiable-example-for-stack-overflow">Making a <em>Minimal, Complete, Verifiable, Example</em> for Stack Overflow</h2>
+<p>If you decide to ask a question about THREE.js it's almost always
 required for you to provide an MCVE which stands for Minimal, Complete,
-Verifiable, Example.
-
-The **Minimal** part is important. Let's say you where having an issue with the
-path movement in the last example of the [loading a gLTF
-article](threejs-load-gltf.html). That example has many parts. Listing them out
-it has
-
-1. A bunch of HTML
-2. Some CSS
-3. Lights
-4. Shadows
-5. DAT.gui code to manipulate shadows
-6. Code to load a .GLTF file
-7. Code to resize the canvas.
-8. Code to move the cars along paths
-
-That's pretty huge. If your question is only about the path following part you
-can remove most of the HTML as you only need a `<canvas>` and a `<script>` tag
+Verifiable, Example.</p>
+<p>The <strong>Minimal</strong> part is important. Let's say you where having an issue with the
+path movement in the last example of the <a href="load-gltf.html">loading a gLTF
+article</a>. That example has many parts. Listing them out
+it has</p>
+<ol>
+<li>A bunch of HTML</li>
+<li>Some CSS</li>
+<li>Lights</li>
+<li>Shadows</li>
+<li>lil-gui code to manipulate shadows</li>
+<li>Code to load a .GLTF file</li>
+<li>Code to resize the canvas.</li>
+<li>Code to move the cars along paths</li>
+</ol>
+<p>That's pretty huge. If your question is only about the path following part you
+can remove most of the HTML as you only need a <code class="notranslate" translate="no">&lt;canvas&gt;</code> and a <code class="notranslate" translate="no">&lt;script&gt;</code> tag
 for THREE.js. You can remove the CSS and the resizing code. You can remove .GLTF
 code because you only care about the path. You can remove the lights and the
-shadows by using a `MeshBasicMaterial`. You can certainly remove the DAT.gui
+shadows by using a <a href="/docs/#api/en/materials/MeshBasicMaterial"><code class="notranslate" translate="no">MeshBasicMaterial</code></a>. You can certainly remove the lil-gui
 code. The code makes a ground plane with a texture. It would be easier to use a
-`GridHelper`. Finally if our question is about moving things on a path we could
-just use cubes on the path instead of loaded car models.
-
-Here's a more minimal example taking all the above into account. It
+<a href="/docs/#api/en/helpers/GridHelper"><code class="notranslate" translate="no">GridHelper</code></a>. Finally if our question is about moving things on a path we could
+just use cubes on the path instead of loaded car models.</p>
+<p>Here's a more minimal example taking all the above into account. It
 shrunk from 271 lines to 135. We might consider shrinking it even
 more by simplifying our path. Maybe a path with 3 or 4 points would
-work just as well as our path with 21 points.
-
-{{{example url="../threejs-debugging-mcve.html" }}}
+work just as well as our path with 21 points.</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/debugging-mcve.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/debugging-mcve.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-I kept the `OrbitController` just because it's useful for others
+<p></p>
+<p>I kept the <code class="notranslate" translate="no">OrbitController</code> just because it's useful for others
 to move the camera and figure out what's going on but depending
-on your issue you might be able to remove that as well.
-
-The best thing about making an MCVE is we'll often solve our own
+on your issue you might be able to remove that as well.</p>
+<p>The best thing about making an MCVE is we'll often solve our own
 problem. The process of removing everything that's not needed and
 making the smallest example we can that reproduces the issue more
-often than not leads us to our bug.
-
-On top of that it's respectful of all the people's time who you are
+often than not leads us to our bug.</p>
+<p>On top of that it's respectful of all the people's time who you are
 asking to look at your code on Stack Overflow. By making the minimal
 example you make it much easier for them to help you. You'll also
-learn in the process.
-
-Also important, when you go to Stack Overflow to post your question **put your
-code [in a snippet](https://stackoverflow.blog/2014/09/16/introducing-runnable-javascript-css-and-html-code-snippets/).**
+learn in the process.</p>
+<p>Also important, when you go to Stack Overflow to post your question <strong>put your
+code <a href="https://stackoverflow.blog/2014/09/16/introducing-runnable-javascript-css-and-html-code-snippets/">in a snippet</a>.</strong>
 Of course you are welcome to use JSFiddle or Codepen or similar site to test out
 your MCVE but once you actually get to posting your question on Stack Overflow
-you're required to put the code to reproduce your issue **in the question itself**. 
-By making a snippet you satisfy that requirement.
-
-Also note all the live examples on this site should run as snippets.
+you're required to put the code to reproduce your issue <strong>in the question itself</strong>. 
+By making a snippet you satisfy that requirement.</p>
+<p>Also note all the live examples on this site should run as snippets.
 Just copy the HTML, CSS, and JavaScript parts to their respective
-parts of the [snippet editor](https://stackoverflow.blog/2014/09/16/introducing-runnable-javascript-css-and-html-code-snippets/).
+parts of the <a href="https://stackoverflow.blog/2014/09/16/introducing-runnable-javascript-css-and-html-code-snippets/">snippet editor</a>.
 Just remember to try to remove the parts that are not relevant to
-your issue and try to make your code the minimal amount needed.
-
-Follow these suggestions and you're far more likely to get help
-with your issue.
-
-## Use a `MeshBasicMaterial`
-
-Because the `MeshBasicMaterial` uses no lights this is one way to 
+your issue and try to make your code the minimal amount needed.</p>
+<p>Follow these suggestions and you're far more likely to get help
+with your issue.</p>
+<h2 id="use-a-meshbasicmaterial-">Use a <a href="/docs/#api/en/materials/MeshBasicMaterial"><code class="notranslate" translate="no">MeshBasicMaterial</code></a></h2>
+<p>Because the <a href="/docs/#api/en/materials/MeshBasicMaterial"><code class="notranslate" translate="no">MeshBasicMaterial</code></a> uses no lights this is one way to 
 remove reasons something might not be showing up. If your objects
-show up using `MeshBasicMaterial` but not with whatever materials
+show up using <a href="/docs/#api/en/materials/MeshBasicMaterial"><code class="notranslate" translate="no">MeshBasicMaterial</code></a> but not with whatever materials
 you were using then you know the issue is likely with the materials
-or the lights and not some other part of the code.
-
-## Check your `near` and `far` settings for your camera
-
-A `PerspectiveCamera` has `near` and `far` settings which are covered in the
-[article on cameras](threejs-cameras.html). Make sure they are set to fit the
-space that contains your objects. Maybe even just **temporarily** set them to
-something large like `near` = 0.001 and `far` = 1000000. You will likely run
+or the lights and not some other part of the code.</p>
+<h2 id="check-your-near-and-far-settings-for-your-camera">Check your <code class="notranslate" translate="no">near</code> and <code class="notranslate" translate="no">far</code> settings for your camera</h2>
+<p>A <a href="/docs/#api/en/cameras/PerspectiveCamera"><code class="notranslate" translate="no">PerspectiveCamera</code></a> has <code class="notranslate" translate="no">near</code> and <code class="notranslate" translate="no">far</code> settings which are covered in the
+<a href="cameras.html">article on cameras</a>. Make sure they are set to fit the
+space that contains your objects. Maybe even just <strong>temporarily</strong> set them to
+something large like <code class="notranslate" translate="no">near</code> = 0.001 and <code class="notranslate" translate="no">far</code> = 1000000. You will likely run
 into depth resolution issues but you'll at least be able to see your objects
-provided they are in front of the camera.
-
-## Check your scene is in front of the camera
-
-Sometimes things don't appear because they are not in front of the camera. If
+provided they are in front of the camera.</p>
+<h2 id="check-your-scene-is-in-front-of-the-camera">Check your scene is in front of the camera</h2>
+<p>Sometimes things don't appear because they are not in front of the camera. If
 your camera is not controllable try adding camera control like the
-`OrbitController` so you can look around and find your scene. Or, try framing
-the scene using code which is covered in [this article](threejs-load-obj.html).
+<code class="notranslate" translate="no">OrbitController</code> so you can look around and find your scene. Or, try framing
+the scene using code which is covered in <a href="load-obj.html">this article</a>.
 That code finds the size of part of the scene and then moves the camera and
-adjusts the `near` and `far` settings to make it visible. You can then look in
-the debugger or add some `console.log` messages to print the size and center of
-the scene.
-
-## Put something in front of the camera
-
-This is just another way of saying if all else fails start with
+adjusts the <code class="notranslate" translate="no">near</code> and <code class="notranslate" translate="no">far</code> settings to make it visible. You can then look in
+the debugger or add some <code class="notranslate" translate="no">console.log</code> messages to print the size and center of
+the scene.</p>
+<h2 id="put-something-in-front-of-the-camera">Put something in front of the camera</h2>
+<p>This is just another way of saying if all else fails start with
 something that works and then slowly add stuff back in. If you get
 a screen with nothing on it then try putting something directly in
 front of the camera. Make a sphere or box, give it a simple material
-like the `MeshBasicMaterial` and make sure you can get that on the screen.
+like the <a href="/docs/#api/en/materials/MeshBasicMaterial"><code class="notranslate" translate="no">MeshBasicMaterial</code></a> and make sure you can get that on the screen.
 Then start adding things back a little at time and testing. Eventually
-you'll either reproduce your bug or you'll find it on the way.
+you'll either reproduce your bug or you'll find it on the way.</p>
+<hr>
+<p>These were a few tips for debugging JavaScript. Let's also go
+over <a href="debugging-glsl.html">some tips for debugging GLSL</a>.</p>
+
+        </div>
+      </div>
+    </div>
+  
+  <script src="/manual/resources/prettify.js"></script>
+  <script src="/manual/resources/lesson.js"></script>
+
+
 
----
 
-These were a few tips for debugging JavaScript. Let's also go
-over [some tips for debugging GLSL](threejs-debugging-glsl.html).
+</body></html>

+ 122 - 123
manual/en/fog.html

@@ -1,54 +1,60 @@
-Title: Three.js Fog
-Description: Fog in Three.js
-TOC: Fog
-
-This article is part of a series of articles about three.js. The
-first article is [three.js fundamentals](threejs-fundamentals.html). If
+<!DOCTYPE html><html lang="en"><head>
+    <meta charset="utf-8">
+    <title>Fog</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 – Fog">
+    <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">
+  </head>
+  <body>
+    <div class="container">
+      <div class="lesson-title">
+        <h1>Fog</h1>
+      </div>
+      <div class="lesson">
+        <div class="lesson-main">
+          <p>This article is part of a series of articles about three.js. The
+first article is <a href="fundamentals.html">three.js fundamentals</a>. If
 you haven't read that yet and you're new to three.js you might want to
 consider starting there. If you haven't read about cameras you might
-want to start with [this article](threejs-cameras.html).
-
-Fog in a 3D engine is generally a way of fading to a specific color
+want to start with <a href="cameras.html">this article</a>.</p>
+<p>Fog in a 3D engine is generally a way of fading to a specific color
 based on the distance from the camera. In three.js you add fog by
-creating `Fog` or `FogExp2` object and setting it on the scene's
-[`fog`](Scene.fog) property.
-
-`Fog` lets you choose `near` and `far` settings which are distances
-from the camera. Anything closer than `near` is unaffected by fog.
-Anything further than `far` is completely the fog color. Parts between
-`near` and `far` fade from their material color to the fog color.
-
-There's also `FogExp2` which grows exponentially with distance from the camera.
-
-To use either type of fog you create one and and assign it to the scene as in
-
-```js
-const scene = new THREE.Scene();
+creating <a href="/docs/#api/en/scenes/Fog"><code class="notranslate" translate="no">Fog</code></a> or <a href="/docs/#api/en/scenes/FogExp2"><code class="notranslate" translate="no">FogExp2</code></a> object and setting it on the scene's
+<a href="/docs/#api/en/scenes/Scene#fog"><code class="notranslate" translate="no">fog</code></a> property.</p>
+<p><a href="/docs/#api/en/scenes/Fog"><code class="notranslate" translate="no">Fog</code></a> lets you choose <code class="notranslate" translate="no">near</code> and <code class="notranslate" translate="no">far</code> settings which are distances
+from the camera. Anything closer than <code class="notranslate" translate="no">near</code> is unaffected by fog.
+Anything further than <code class="notranslate" translate="no">far</code> is completely the fog color. Parts between
+<code class="notranslate" translate="no">near</code> and <code class="notranslate" translate="no">far</code> fade from their material color to the fog color.</p>
+<p>There's also <a href="/docs/#api/en/scenes/FogExp2"><code class="notranslate" translate="no">FogExp2</code></a> which grows exponentially with distance from the camera.</p>
+<p>To use either type of fog you create one and and assign it to the scene as in</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const scene = new THREE.Scene();
 {
   const color = 0xFFFFFF;  // white
   const near = 10;
   const far = 100;
   scene.fog = new THREE.Fog(color, near, far);
 }
-```
-
-or for `FogExp2` it would be
-
-```js
-const scene = new THREE.Scene();
+</pre>
+<p>or for <a href="/docs/#api/en/scenes/FogExp2"><code class="notranslate" translate="no">FogExp2</code></a> it would be</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const scene = new THREE.Scene();
 {
   const color = 0xFFFFFF;
   const density = 0.1;
   scene.fog = new THREE.FogExp2(color, density);
 }
-```
-
-`FogExp2` is closer to reality but `Fog` is used
+</pre>
+<p><a href="/docs/#api/en/scenes/FogExp2"><code class="notranslate" translate="no">FogExp2</code></a> is closer to reality but <a href="/docs/#api/en/scenes/Fog"><code class="notranslate" translate="no">Fog</code></a> is used
 more commonly since it lets you choose a place to apply
 the fog so you can decide to show a clear scene
 up to a certain distance and then fade out to some color
-past that distance.
-
+past that distance.</p>
 <div class="spread">
   <div>
     <div data-diagram="fog" style="height: 300px;"></div>
@@ -60,18 +66,15 @@ past that distance.
   </div>
 </div>
 
-It's important to note that the fog is applied to *things that are rendered*.
+<p>It's important to note that the fog is applied to <em>things that are rendered</em>.
 It is part of the calculation of each pixel of the color of the object.
 What that means is if you want your scene to fade to a certain color you
-need to set the fog **and** the background color to the same color.
+need to set the fog <strong>and</strong> the background color to the same color.
 The background color is set using the
-[`scene.background`](Scene.background)
-property. To pick a background color you attach a `THREE.Color` to it. For example
-
-```js
-scene.background = new THREE.Color('#F00');  // red
-```
-
+<a href="/docs/#api/en/scenes/Scene#background"><code class="notranslate" translate="no">scene.background</code></a>
+property. To pick a background color you attach a <a href="/docs/#api/en/math/Color"><code class="notranslate" translate="no">THREE.Color</code></a> to it. For example</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">scene.background = new THREE.Color('#F00');  // red
+</pre>
 <div class="spread">
   <div>
     <div data-diagram="fogBlueBackgroundRed" style="height: 300px;" class="border"></div>
@@ -83,12 +86,10 @@ scene.background = new THREE.Color('#F00');  // red
   </div>
 </div>
 
-Here is one of our previous examples with fog added. The only addition
+<p>Here is one of our previous examples with fog added. The only addition
 is right after setting up the scene we add the fog and set the scene's
-background color
-
-```js
-const scene = new THREE.Scene();
+background color</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const scene = new THREE.Scene();
 
 +{
 +  const near = 1;
@@ -97,28 +98,28 @@ const scene = new THREE.Scene();
 +  scene.fog = new THREE.Fog(color, near, far);
 +  scene.background = new THREE.Color(color);
 +}
-```
-
-In the example below the camera's `near` is 0.1 and its `far` is 5.
-The camera is at `z = 2`. The cubes are 1 unit large and at Z = 0.
-This means with a fog setting of `near = 1` and `far = 2` the cubes
-will fade out right around their center.
-
-{{{example url="../threejs-fog.html" }}}
+</pre>
+<p>In the example below the camera's <code class="notranslate" translate="no">near</code> is 0.1 and its <code class="notranslate" translate="no">far</code> is 5.
+The camera is at <code class="notranslate" translate="no">z = 2</code>. The cubes are 1 unit large and at Z = 0.
+This means with a fog setting of <code class="notranslate" translate="no">near = 1</code> and <code class="notranslate" translate="no">far = 2</code> the cubes
+will fade out right around their center.</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/fog.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/fog.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-Let's add an interface so we can adjust the fog. Again we'll use
-[dat.GUI](https://github.com/dataarts/dat.gui). dat.GUI takes
+<p></p>
+<p>Let's add an interface so we can adjust the fog. Again we'll use
+<a href="https://github.com/georgealways/lil-gui">lil-gui</a>. lil-gui takes
 an object and a property and automagically makes an interface
 for that type of property. We could just simply let it manipulate
-the fog's `near` and `far` properties but it's invalid to have
-`near` be greater than `far` so let's make a helper so dat.GUI
-can manipulate a `near` and `far` property but we'll make sure `near`
-is less than or equal to `far` and `far` is greater than or equal `near`.
-
-```js
-// We use this class to pass to dat.gui
+the fog's <code class="notranslate" translate="no">near</code> and <code class="notranslate" translate="no">far</code> properties but it's invalid to have
+<code class="notranslate" translate="no">near</code> be greater than <code class="notranslate" translate="no">far</code> so let's make a helper so lil-gui
+can manipulate a <code class="notranslate" translate="no">near</code> and <code class="notranslate" translate="no">far</code> property but we'll make sure <code class="notranslate" translate="no">near</code>
+is less than or equal to <code class="notranslate" translate="no">far</code> and <code class="notranslate" translate="no">far</code> is greater than or equal <code class="notranslate" translate="no">near</code>.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">// We use this class to pass to lil-gui
 // so when it manipulates near or far
-// near is never > far and far is never < near
+// near is never &gt; far and far is never &lt; near
 class FogGUIHelper {
   constructor(fog) {
     this.fog = fog;
@@ -138,12 +139,9 @@ class FogGUIHelper {
     this.fog.near = Math.min(this.fog.near, v);
   }
 }
-```
-
-We can then add it like this
-
-```js
-{
+</pre>
+<p>We can then add it like this</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
   const near = 1;
   const far = 2;
   const color = 'lightblue';
@@ -154,34 +152,27 @@ We can then add it like this
 +  gui.add(fogGUIHelper, 'near', near, far).listen();
 +  gui.add(fogGUIHelper, 'far', near, far).listen();
 }
-```
-
-The `near` and `far` parameters set the minimum and maximum values
-for adjusting the fog. They are set when we setup the camera.
-
-The `.listen()` at the end of the last 2 lines tells dat.GUI to *listen*
-for changes. That way when we change `near` because of an edit to `far`
-or we change `far` in response to an edit to `near` dat.GUI will update
-the other property's UI for us.
-
-It might also be nice to be able to change the fog color but like was
+</pre>
+<p>The <code class="notranslate" translate="no">near</code> and <code class="notranslate" translate="no">far</code> parameters set the minimum and maximum values
+for adjusting the fog. They are set when we setup the camera.</p>
+<p>The <code class="notranslate" translate="no">.listen()</code> at the end of the last 2 lines tells lil-gui to <em>listen</em>
+for changes. That way when we change <code class="notranslate" translate="no">near</code> because of an edit to <code class="notranslate" translate="no">far</code>
+or we change <code class="notranslate" translate="no">far</code> in response to an edit to <code class="notranslate" translate="no">near</code> lil-gui will update
+the other property's UI for us.</p>
+<p>It might also be nice to be able to change the fog color but like was
 mentioned above we need to keep both the fog color and the background
-color in sync. So, let's add another *virtual* property to our helper
-that will set both colors when dat.GUI manipulates it.
-
-dat.GUI can manipulate colors in 4 ways, as a CSS 6 digit hex string (eg: `#112233`). As an hue, saturation, value, object (eg: `{h: 60, s: 1, v: }`).
-As an RGB array (eg: `[255, 128, 64]`). Or, as an RGBA array (eg: `[127, 200, 75, 0.3]`).
-
-It's easiest for our purpose to use the hex string version since that way
-dat.GUI is only manipulating a single value. Fortunately `THREE.Color`
-as a [`getHexString`](Color.getHexString) method
-we get use to easily get such a string, we just have to prepend a '#' to the front.
-
-```js
-// We use this class to pass to dat.gui
+color in sync. So, let's add another <em>virtual</em> property to our helper
+that will set both colors when lil-gui manipulates it.</p>
+<p>lil-gui can manipulate colors in 4 ways, as a CSS 6 digit hex string (eg: <code class="notranslate" translate="no">#112233</code>). As an hue, saturation, value, object (eg: <code class="notranslate" translate="no">{h: 60, s: 1, v: }</code>).
+As an RGB array (eg: <code class="notranslate" translate="no">[255, 128, 64]</code>). Or, as an RGBA array (eg: <code class="notranslate" translate="no">[127, 200, 75, 0.3]</code>).</p>
+<p>It's easiest for our purpose to use the hex string version since that way
+lil-gui is only manipulating a single value. Fortunately <a href="/docs/#api/en/math/Color"><code class="notranslate" translate="no">THREE.Color</code></a>
+as a <a href="/docs/#api/en/math/Color#getHexString"><code class="notranslate" translate="no">getHexString</code></a> method
+we get use to easily get such a string, we just have to prepend a '#' to the front.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">// We use this class to pass to lil-gui
 // so when it manipulates near or far
-// near is never > far and far is never < near
-+// Also when dat.gui manipulates color we'll
+// near is never &gt; far and far is never &lt; near
++// Also when lil-gui manipulates color we'll
 +// update both the fog and background colors.
 class FogGUIHelper {
 *  constructor(fog, backgroundColor) {
@@ -210,12 +201,9 @@ class FogGUIHelper {
 +    this.backgroundColor.set(hexString);
 +  }
 }
-```
-
-We then call `gui.addColor` to add a color UI for our helper's virtual property.
-
-```js
-{
+</pre>
+<p>We then call <code class="notranslate" translate="no">gui.addColor</code> to add a color UI for our helper's virtual property.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
   const near = 1;
   const far = 2;
   const color = 'lightblue';
@@ -227,33 +215,33 @@ We then call `gui.addColor` to add a color UI for our helper's virtual property.
   gui.add(fogGUIHelper, 'far', near, far).listen();
 +  gui.addColor(fogGUIHelper, 'color');
 }
-```
-
-{{{example url="../threejs-fog-gui.html" }}}
+</pre>
+<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/fog-gui.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/fog-gui.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-You can see setting `near` to like 1.9 and `far` to 2.0 gives
+<p></p>
+<p>You can see setting <code class="notranslate" translate="no">near</code> to like 1.9 and <code class="notranslate" translate="no">far</code> to 2.0 gives
 a very sharp transition between un-fogged and completely fogged.
-where as `near` = 1.1 and `far` = 2.9 should just about be
-the smoothest given our cubes are spinning 2 units away from the camera.
-
-One last thing, there is a boolean [`fog`](Material.fog)
+where as <code class="notranslate" translate="no">near</code> = 1.1 and <code class="notranslate" translate="no">far</code> = 2.9 should just about be
+the smoothest given our cubes are spinning 2 units away from the camera.</p>
+<p>One last thing, there is a boolean <a href="/docs/#api/en/materials/Material#fog"><code class="notranslate" translate="no">fog</code></a>
 property on a material for whether or not objects rendered
-with that material are affected by fog. It defaults to `true`
+with that material are affected by fog. It defaults to <code class="notranslate" translate="no">true</code>
 for most materials. As an example of why you might want
 to turn the fog off, imagine you're making a 3D vehicle
 simulator with a view from the driver's seat or cockpit.
 You probably want the fog off for everything inside the vehicle when
-viewing from inside the vehicle.
-
-A better example might be a house
+viewing from inside the vehicle.</p>
+<p>A better example might be a house
 and thick fog outside house. Let's say the fog is set to start
 2 meters away (near = 2) and completely fogged out at 4 meters (far = 4).
 Rooms are longer than 2 meters and the house is probably longer
 than 4 meters so you need to set the materials for the inside
 of the house to not apply fog otherwise when standing inside the
 house looking outside the wall at the far end of the room will look
-like it's in the fog.
-
+like it's in the fog.</p>
 <div class="spread">
   <div>
     <div data-diagram="fogHouseAll" style="height: 300px;" class="border"></div>
@@ -261,9 +249,8 @@ like it's in the fog.
   </div>
 </div>
 
-Notice the walls and ceiling at the far end of the room are getting fog applied.
-By turning fog off on the materials for the house we can fix that issue.
-
+<p>Notice the walls and ceiling at the far end of the room are getting fog applied.
+By turning fog off on the materials for the house we can fix that issue.</p>
 <div class="spread">
   <div>
     <div data-diagram="fogHouseInsideNoFog" style="height: 300px;" class="border"></div>
@@ -271,5 +258,17 @@ By turning fog off on the materials for the house we can fix that issue.
   </div>
 </div>
 
-<canvas id="c"></canvas>
-<script type="module" src="resources/threejs-fog.js"></script>
+<p><canvas id="c"></canvas></p>
+<script type="module" src="../resources/threejs-fog.js"></script>
+
+        </div>
+      </div>
+    </div>
+  
+  <script src="/manual/resources/prettify.js"></script>
+  <script src="/manual/resources/lesson.js"></script>
+
+
+
+
+</body></html>

+ 280 - 336
manual/en/fundamentals.html

@@ -1,269 +1,234 @@
-Title: Three.js Fundamentals
-Description: Your first Three.js lesson starting with the fundamentals
-TOC: Fundamentals
-
-This is the first article in a series of articles about three.js.
-[Three.js](https://threejs.org) is a 3D library that tries to make
-it as easy as possible to get 3D content on a webpage.
-
-Three.js is often confused with WebGL since more often than
+<!DOCTYPE html><html lang="en"><head>
+    <meta charset="utf-8">
+    <title>Fundamentals</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 – Fundamentals">
+    <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">
+  </head>
+  <body>
+    <div class="container">
+      <div class="lesson-title">
+        <h1>Fundamentals</h1>
+      </div>
+      <div class="lesson">
+        <div class="lesson-main">
+          <p>This is the first article in a series of articles about three.js.
+<a href="https://threejs.org">Three.js</a> is a 3D library that tries to make
+it as easy as possible to get 3D content on a webpage.</p>
+<p>Three.js is often confused with WebGL since more often than
 not, but not always, three.js uses WebGL to draw 3D.
-[WebGL is a very low-level system that only draws points, lines, and triangles](https://webglfundamentals.org).
+<a href="https://webglfundamentals.org">WebGL is a very low-level system that only draws points, lines, and triangles</a>.
 To do anything useful with WebGL generally requires quite a bit of
 code and that is where three.js comes in. It handles stuff
 like scenes, lights, shadows, materials, textures, 3d math, all things that you'd
-have to write yourself if you were to use WebGL directly.
-
-These tutorials assume you already know JavaScript and, for the
-most part they will use ES6 style. [See here for a
-terse list of things you're expected to already know](threejs-prerequisites.html).
+have to write yourself if you were to use WebGL directly.</p>
+<p>These tutorials assume you already know JavaScript and, for the
+most part they will use ES6 style. <a href="prerequisites.html">See here for a
+terse list of things you're expected to already know</a>.
 Most browsers that support three.js are auto-updated so most users should
 be able to run this code. If you'd like to make this code run
-on really old browsers look into a transpiler like [Babel](https://babeljs.io).
+on really old browsers look into a transpiler like <a href="https://babeljs.io">Babel</a>.
 Of course users running really old browsers probably have machines
-that can't run three.js.
-
-When learning most programming languages the first thing people
-do is make the computer print `"Hello World!"`. For 3D one
+that can't run three.js.</p>
+<p>When learning most programming languages the first thing people
+do is make the computer print <code class="notranslate" translate="no">"Hello World!"</code>. For 3D one
 of the most common first things to do is to make a 3D cube.
-So let's start with "Hello Cube!"
-
-Before we get started let's try to give you an idea of the structure
+So let's start with "Hello Cube!"</p>
+<p>Before we get started let's try to give you an idea of the structure
 of a three.js app. A three.js app requires you to create a bunch of
 objects and connect them together. Here's a diagram that represents
-a small three.js app
-
-<div class="threejs_center"><img src="resources/images/threejs-structure.svg" style="width: 768px;"></div>
-
-Things to notice about the diagram above.
-
-* There is a `Renderer`. This is arguably the main object of three.js. You pass a
-  `Scene` and a `Camera` to a `Renderer` and it renders (draws) the portion of
-  the 3D scene that is inside the *frustum* of the camera as a 2D image to a
-  canvas.
-
-* There is a [scenegraph](threejs-scenegraph.html) which is a tree like
-  structure, consisting of various objects like a `Scene` object, multiple
-  `Mesh` objects, `Light` objects, `Group`, `Object3D`, and `Camera` objects. A
-  `Scene` object defines the root of the scenegraph and contains properties like
-  the background color and fog. These objects define a hierarchical parent/child
-  tree like structure and represent where objects appear and how they are
-  oriented. Children are positioned and oriented relative to their parent. For
-  example the wheels on a car might be children of the car so that moving and
-  orienting the car's object automatically moves the wheels. You can read more
-  about this in [the article on scenegraphs](threejs-scenegraph.html).
-
-  Note in the diagram `Camera` is half in half out of the scenegraph. This is to
-  represent that in three.js, unlike the other objects, a `Camera` does not have
-  to be in the scenegraph to function. Just like other objects, a `Camera`, as a
-  child of some other object, will move and orient relative to its parent object.
-  There is an example of putting multiple `Camera` objects in a scenegraph at
-  the end of [the article on scenegraphs](threejs-scenegraph.html).
-
-* `Mesh` objects represent drawing a specific `Geometry` with a specific
-   `Material`. Both `Material` objects and `Geometry` objects can be used by
-   multiple `Mesh` objects. For example to draw two blue cubes in different
-   locations we could need two `Mesh` objects to represent the position and
-   orientation of each cube. We would only need one `Geometry` to hold the vertex
-   data for a cube and we would only need one `Material` to specify the color
-   blue. Both `Mesh` objects could reference the same `Geometry` object and the
-   same `Material` object.
-
-* `Geometry` objects represent the vertex data of some piece of geometry like
-   a sphere, cube, plane, dog, cat, human, tree, building, etc...
-   Three.js provides many kinds of built in
-   [geometry primitives](threejs-primitives.html). You can also
-   [create custom geometry](threejs-custom-buffergeometry.html) as well as
-   [load geometry from files](threejs-load-obj.html).
-
-* `Material` objects represent
-  [the surface properties used to draw geometry](threejs-materials.html)
-  including things like the color to use and how shiny it is. A `Material` can also
-  reference one or more `Texture` objects which can be used, for example, 
-  to wrap an image onto the surface of a geometry.
-
-* `Texture` objects generally represent images either [loaded from image files](threejs-textures.html),
-  [generated from a canvas](threejs-canvas-textures.html) or [rendered from another scene](threejs-rendertargets.html).
-
-* `Light` objects represent [different kinds of lights](threejs-lights.html).
-
-Given all of that we're going to make the smallest *"Hello Cube"* setup
-that looks like this
-
-<div class="threejs_center"><img src="resources/images/threejs-1cube-no-light-scene.svg" style="width: 500px;"></div>
-
-First let's load three.js
-
-```html
-<script type="module">
-import * as THREE from './resources/threejs/r132/build/three.module.js';
-</script>
-```
-
-It's important you put `type="module"` in the script tag. This enables
-us to use the `import` keyword to load three.js. There are other ways
+a small three.js app</p>
+<div class="threejs_center"><img src="../resources/images/threejs-structure.svg" style="width: 768px;"></div>
+
+<p>Things to notice about the diagram above.</p>
+<ul>
+<li><p>There is a <a href="/docs/#api/en/constants/Renderer"><code class="notranslate" translate="no">Renderer</code></a>. This is arguably the main object of three.js. You pass a
+<a href="/docs/#api/en/scenes/Scene"><code class="notranslate" translate="no">Scene</code></a> and a <a href="/docs/#api/en/cameras/Camera"><code class="notranslate" translate="no">Camera</code></a> to a <a href="/docs/#api/en/constants/Renderer"><code class="notranslate" translate="no">Renderer</code></a> and it renders (draws) the portion of
+the 3D scene that is inside the <em>frustum</em> of the camera as a 2D image to a
+canvas.</p>
+</li>
+<li><p>There is a <a href="scenegraph.html">scenegraph</a> which is a tree like
+structure, consisting of various objects like a <a href="/docs/#api/en/scenes/Scene"><code class="notranslate" translate="no">Scene</code></a> object, multiple
+<a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a> objects, <a href="/docs/#api/en/lights/Light"><code class="notranslate" translate="no">Light</code></a> objects, <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>, and <a href="/docs/#api/en/cameras/Camera"><code class="notranslate" translate="no">Camera</code></a> objects. A
+<a href="/docs/#api/en/scenes/Scene"><code class="notranslate" translate="no">Scene</code></a> object defines the root of the scenegraph and contains properties like
+the background color and fog. These objects define a hierarchical parent/child
+tree like structure and represent where objects appear and how they are
+oriented. Children are positioned and oriented relative to their parent. For
+example the wheels on a car might be children of the car so that moving and
+orienting the car's object automatically moves the wheels. You can read more
+about this in <a href="scenegraph.html">the article on scenegraphs</a>.</p>
+<p>Note in the diagram <a href="/docs/#api/en/cameras/Camera"><code class="notranslate" translate="no">Camera</code></a> is half in half out of the scenegraph. This is to
+represent that in three.js, unlike the other objects, a <a href="/docs/#api/en/cameras/Camera"><code class="notranslate" translate="no">Camera</code></a> does not have
+to be in the scenegraph to function. Just like other objects, a <a href="/docs/#api/en/cameras/Camera"><code class="notranslate" translate="no">Camera</code></a>, as a
+child of some other object, will move and orient relative to its parent object.
+There is an example of putting multiple <a href="/docs/#api/en/cameras/Camera"><code class="notranslate" translate="no">Camera</code></a> objects in a scenegraph at
+the end of <a href="scenegraph.html">the article on scenegraphs</a>.</p>
+</li>
+<li><p><a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a> objects represent drawing a specific <code class="notranslate" translate="no">Geometry</code> with a specific
+ <a href="/docs/#api/en/materials/Material"><code class="notranslate" translate="no">Material</code></a>. Both <a href="/docs/#api/en/materials/Material"><code class="notranslate" translate="no">Material</code></a> objects and <code class="notranslate" translate="no">Geometry</code> objects can be used by
+ multiple <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a> objects. For example to draw two blue cubes in different
+ locations we could need two <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a> objects to represent the position and
+ orientation of each cube. We would only need one <code class="notranslate" translate="no">Geometry</code> to hold the vertex
+ data for a cube and we would only need one <a href="/docs/#api/en/materials/Material"><code class="notranslate" translate="no">Material</code></a> to specify the color
+ blue. Both <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a> objects could reference the same <code class="notranslate" translate="no">Geometry</code> object and the
+ same <a href="/docs/#api/en/materials/Material"><code class="notranslate" translate="no">Material</code></a> object.</p>
+</li>
+<li><p><code class="notranslate" translate="no">Geometry</code> objects represent the vertex data of some piece of geometry like
+ a sphere, cube, plane, dog, cat, human, tree, building, etc...
+ Three.js provides many kinds of built in
+ <a href="primitives.html">geometry primitives</a>. You can also
+ <a href="custom-buffergeometry.html">create custom geometry</a> as well as
+ <a href="load-obj.html">load geometry from files</a>.</p>
+</li>
+<li><p><a href="/docs/#api/en/materials/Material"><code class="notranslate" translate="no">Material</code></a> objects represent
+<a href="materials.html">the surface properties used to draw geometry</a>
+including things like the color to use and how shiny it is. A <a href="/docs/#api/en/materials/Material"><code class="notranslate" translate="no">Material</code></a> can also
+reference one or more <a href="/docs/#api/en/textures/Texture"><code class="notranslate" translate="no">Texture</code></a> objects which can be used, for example, 
+to wrap an image onto the surface of a geometry.</p>
+</li>
+<li><p><a href="/docs/#api/en/textures/Texture"><code class="notranslate" translate="no">Texture</code></a> objects generally represent images either <a href="textures.html">loaded from image files</a>,
+<a href="canvas-textures.html">generated from a canvas</a> or <a href="rendertargets.html">rendered from another scene</a>.</p>
+</li>
+<li><p><a href="/docs/#api/en/lights/Light"><code class="notranslate" translate="no">Light</code></a> objects represent <a href="lights.html">different kinds of lights</a>.</p>
+</li>
+</ul>
+<p>Given all of that we're going to make the smallest <em>"Hello Cube"</em> setup
+that looks like this</p>
+<div class="threejs_center"><img src="../resources/images/threejs-1cube-no-light-scene.svg" style="width: 500px;"></div>
+
+<p>First let's load three.js</p>
+<pre class="prettyprint showlinemods notranslate lang-html" translate="no">&lt;script type="module"&gt;
+import * as THREE from '../../build/three.module.js';
+&lt;/script&gt;
+</pre>
+<p>It's important you put <code class="notranslate" translate="no">type="module"</code> in the script tag. This enables
+us to use the <code class="notranslate" translate="no">import</code> keyword to load three.js. There are other ways
 to load three.js but as of r106 using modules is the recommended way.
 Modules have the advantage that they can easily import other modules
 they need. That saves us from having to manually load extra scripts
-they are dependent on.
-
-Next we need is a `<canvas>` tag so...
-
-```html
-<body>
-  <canvas id="c"></canvas>
-</body>
-```
-
-We will ask three.js to draw into that canvas so we need to look it up.
-
-```html
-<script type="module">
-import * as THREE from './resources/threejs/r132/build/three.module.js';
+they are dependent on.</p>
+<p>Next we need is a <code class="notranslate" translate="no">&lt;canvas&gt;</code> tag so...</p>
+<pre class="prettyprint showlinemods notranslate lang-html" translate="no">&lt;body&gt;
+  &lt;canvas id="c"&gt;&lt;/canvas&gt;
+&lt;/body&gt;
+</pre>
+<p>We will ask three.js to draw into that canvas so we need to look it up.</p>
+<pre class="prettyprint showlinemods notranslate lang-html" translate="no">&lt;script type="module"&gt;
+import * as THREE from '../../build/three.module.js';
 
 +function main() {
 +  const canvas = document.querySelector('#c');
 +  const renderer = new THREE.WebGLRenderer({canvas});
 +  ...
-</script>
-```
-
-After we look up the canvas we create a `WebGLRenderer`. The renderer
+&lt;/script&gt;
+</pre>
+<p>After we look up the canvas we create a <a href="/docs/#api/en/renderers/WebGLRenderer"><code class="notranslate" translate="no">WebGLRenderer</code></a>. The renderer
 is the thing responsible for actually taking all the data you provide
 and rendering it to the canvas. In the past there have been other renderers
-like `CSSRenderer`, a `CanvasRenderer` and in the future there may be a
-`WebGL2Renderer` or `WebGPURenderer`. For now there's the `WebGLRenderer`
-that uses WebGL to render 3D to the canvas.
-
-Note there are some esoteric details here. If you don't pass a canvas
+like <code class="notranslate" translate="no">CSSRenderer</code>, a <code class="notranslate" translate="no">CanvasRenderer</code> and in the future there may be a
+<code class="notranslate" translate="no">WebGL2Renderer</code> or <code class="notranslate" translate="no">WebGPURenderer</code>. For now there's the <a href="/docs/#api/en/renderers/WebGLRenderer"><code class="notranslate" translate="no">WebGLRenderer</code></a>
+that uses WebGL to render 3D to the canvas.</p>
+<p>Note there are some esoteric details here. If you don't pass a canvas
 into three.js it will create one for you but then you have to add it
 to your document. Where to add it may change depending on your use case
 and you'll have to change your code so I find that passing a canvas
 to three.js feels a little more flexible. I can put the canvas anywhere
 and the code will find it whereas if I had code to insert the canvas
 into to the document I'd likely have to change that code if my use case
-changed.
-
-Next up we need a camera. We'll create a `PerspectiveCamera`.
-
-```js
-const fov = 75;
+changed.</p>
+<p>Next up we need a camera. We'll create a <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);
-```
-
-`fov` is short for `field of view`. In this case 75 degrees in the vertical
+</pre>
+<p><code class="notranslate" translate="no">fov</code> is short for <code class="notranslate" translate="no">field of view</code>. In this case 75 degrees in the vertical
 dimension. Note that most angles in three.js are in radians but for some
-reason the perspective camera takes degrees.
-
-`aspect` is the display aspect of the canvas. We'll go over the details
-[in another article](threejs-responsive.html) but by default a canvas is
- 300x150 pixels which makes the aspect 300/150 or 2.
-
-`near` and `far` represent the space in front of the camera
+reason the perspective camera takes degrees.</p>
+<p><code class="notranslate" translate="no">aspect</code> is the display aspect of the canvas. We'll go over the details
+<a href="responsive.html">in another article</a> but by default a canvas is
+ 300x150 pixels which makes the aspect 300/150 or 2.</p>
+<p><code class="notranslate" translate="no">near</code> and <code class="notranslate" translate="no">far</code> represent the space in front of the camera
 that will be rendered. Anything before that range or after that range
-will be clipped (not drawn).
-
-Those four settings define a *"frustum"*. A *frustum* is the name of
+will be clipped (not drawn).</p>
+<p>Those four settings define a <em>"frustum"</em>. A <em>frustum</em> is the name of
 a 3d shape that is like a pyramid with the tip sliced off. In other
 words think of the word "frustum" as another 3D shape like sphere,
-cube, prism, frustum.
-
-<img src="resources/frustum-3d.svg" width="500" class="threejs_center"/>
-
-The height of the near and far planes are determined by the field of view.
-The width of both planes is determined by the field of view and the aspect.
-
-Anything inside the defined frustum will be be drawn. Anything outside
-will not.
-
-The camera defaults to looking down the -Z axis with +Y up. We'll put our cube
+cube, prism, frustum.</p>
+<p><img src="../resources/frustum-3d.svg" width="500" class="threejs_center"></p>
+<p>The height of the near and far planes are determined by the field of view.
+The width of both planes is determined by the field of view and the aspect.</p>
+<p>Anything inside the defined frustum will be be drawn. Anything outside
+will not.</p>
+<p>The camera defaults to looking down the -Z axis with +Y up. We'll put our cube
 at the origin so we need to move the camera back a little from the origin
-in order to see anything.
-
-```js
-camera.position.z = 2;
-```
-
-Here's what we're aiming for.
-
-<img src="resources/scene-down.svg" width="500" class="threejs_center"/>
-
-In the diagram above we can see our camera is at `z = 2`. It's looking
+in order to see anything.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">camera.position.z = 2;
+</pre>
+<p>Here's what we're aiming for.</p>
+<p><img src="../resources/scene-down.svg" width="500" class="threejs_center"></p>
+<p>In the diagram above we can see our camera is at <code class="notranslate" translate="no">z = 2</code>. It's looking
 down the -Z axis. Our frustum starts 0.1 units from the front of the camera
 and goes to 5 units in front of the camera. Because in this diagram we are looking down,
 the field of view is affected by the aspect. Our canvas is twice as wide
 as it is tall so across the canvas the field of view will be much wider than
-our specified 75 degrees which is the vertical field of view.
-
-Next we make a `Scene`. A `Scene` in three.js is the root of a form of scene graph.
+our specified 75 degrees which is the vertical field of view.</p>
+<p>Next we make a <a href="/docs/#api/en/scenes/Scene"><code class="notranslate" translate="no">Scene</code></a>. A <a href="/docs/#api/en/scenes/Scene"><code class="notranslate" translate="no">Scene</code></a> in three.js is the root of a form of scene graph.
 Anything you want three.js to draw needs to be added to the scene. We'll
-cover more details of [how scenes work in a future article](threejs-scenegraph.html).
-
-```js
-const scene = new THREE.Scene();
-```
-
-Next up we create a `BoxGeometry` which contains the data for a box.
+cover more details of <a href="scenegraph.html">how scenes work in a future article</a>.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const scene = new THREE.Scene();
+</pre>
+<p>Next up we create a <a href="/docs/#api/en/geometries/BoxGeometry"><code class="notranslate" translate="no">BoxGeometry</code></a> which contains the data for a box.
 Almost anything we want to display in Three.js needs geometry which defines
-the vertices that make up our 3D object.
-
-```js
-const boxWidth = 1;
+the vertices that make up our 3D object.</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);
-```
-
-We then create a basic material and set its color. Colors can
-be specified using standard CSS style 6 digit hex color values.
-
-```js
-const material = new THREE.MeshBasicMaterial({color: 0x44aa88});
-```
-
-We then create a `Mesh`. A `Mesh` in three represents the combination
-of a three things
-
-1. A `Geometry` (the shape of the object)
-2. A `Material` (how to draw the object, shiny or flat, what color, what texture(s) to apply. Etc.)
-3. The position, orientation, and scale of that object in the scene relative to its parent. In the code below that parent is the scene.
-
-```js
-const cube = new THREE.Mesh(geometry, material);
-```
-
-And finally we add that mesh to the scene
-
-```js
-scene.add(cube);
-```
-
-We can then render the scene by calling the renderer's render function
-and passing it the scene and the camera
-
-```js
-renderer.render(scene, camera);
-```
-
-Here's a working example
-
-{{{example url="../threejs-fundamentals.html" }}}
+</pre>
+<p>We then create a basic material and set its color. Colors can
+be specified using standard CSS style 6 digit hex color values.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const material = new THREE.MeshBasicMaterial({color: 0x44aa88});
+</pre>
+<p>We then create a <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a>. A <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a> in three represents the combination
+of a three things</p>
+<ol>
+<li>A <code class="notranslate" translate="no">Geometry</code> (the shape of the object)</li>
+<li>A <a href="/docs/#api/en/materials/Material"><code class="notranslate" translate="no">Material</code></a> (how to draw the object, shiny or flat, what color, what texture(s) to apply. Etc.)</li>
+<li>The position, orientation, and scale of that object in the scene relative to its parent. In the code below that parent is the scene.</li>
+</ol>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const cube = new THREE.Mesh(geometry, material);
+</pre>
+<p>And finally we add that mesh to the scene</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">scene.add(cube);
+</pre>
+<p>We can then render the scene by calling the renderer's render function
+and passing it the scene and the camera</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">renderer.render(scene, camera);
+</pre>
+<p>Here's a working example</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">click here to open in a separate window</a>
+</div>
 
-It's kind of hard to tell that is a 3D cube since we're viewing
+<p></p>
+<p>It's kind of hard to tell that is a 3D cube since we're viewing
 it directly down the -Z axis and the cube itself is axis aligned
-so we're only seeing a single face.
-
-Let's animate it spinning and hopefully that will make
+so we're only seeing a single face.</p>
+<p>Let's animate it spinning and hopefully that will make
 it clear it's being drawn in 3D. To animate it we'll render inside a render loop using
-[`requestAnimationFrame`](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame).
-
-Here's our loop
-
-```js
-function render(time) {
+<a href="https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame"><code class="notranslate" translate="no">requestAnimationFrame</code></a>.</p>
+<p>Here's our loop</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function render(time) {
   time *= 0.001;  // convert time to seconds
 
   cube.rotation.x = time;
@@ -274,79 +239,67 @@ function render(time) {
   requestAnimationFrame(render);
 }
 requestAnimationFrame(render);
-```
-
-`requestAnimationFrame` is a request to the browser that you want to animate something.
-You pass it a function to be called. In our case that function is `render`. The browser
+</pre>
+<p><code class="notranslate" translate="no">requestAnimationFrame</code> is a request to the browser that you want to animate something.
+You pass it a function to be called. In our case that function is <code class="notranslate" translate="no">render</code>. The browser
 will call your function and if you update anything related to the display of the
 page the browser will re-render the page. In our case we are calling three's
-`renderer.render` function which will draw our scene.
-
-`requestAnimationFrame` passes the time since the page loaded to
+<code class="notranslate" translate="no">renderer.render</code> function which will draw our scene.</p>
+<p><code class="notranslate" translate="no">requestAnimationFrame</code> passes the time since the page loaded to
 our function. That time is passed in milliseconds. I find it's much
-easier to work with seconds so here we're converting that to seconds.
-
-We then set the cube's X and Y rotation to the current time. These rotations
-are in [radians](https://en.wikipedia.org/wiki/Radian). There are 2 pi radians
+easier to work with seconds so here we're converting that to seconds.</p>
+<p>We then set the cube's X and Y rotation to the current time. These rotations
+are in <a href="https://en.wikipedia.org/wiki/Radian">radians</a>. There are 2 pi radians
 in a circle so our cube should turn around once on each axis in about 6.28
-seconds.
-
-We then render the scene and request another animation frame to continue
-our loop.
-
-Outside the loop we call `requestAnimationFrame` one time to start the loop.
-
-{{{example url="../threejs-fundamentals-with-animation.html" }}}
+seconds.</p>
+<p>We then render the scene and request another animation frame to continue
+our loop.</p>
+<p>Outside the loop we call <code class="notranslate" translate="no">requestAnimationFrame</code> one time to start the loop.</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">click here to open in a separate window</a>
+</div>
 
-It's a little better but it's still hard to see the 3d. What would help is to
+<p></p>
+<p>It's a little better but it's still hard to see the 3d. What would help is to
 add some lighting so let's add a light. There are many kinds of lights in
-three.js which we'll go over in [a future article](threejs-lights.html). For now let's create a directional light.
-
-```js
-{
+three.js which we'll go over in <a href="lights.html">a future article</a>. For now let's create a directional light.</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);
 }
-```
-
-Directional lights have a position and a target. Both default to 0, 0, 0. In our
+</pre>
+<p>Directional lights have a position and a target. Both default to 0, 0, 0. In our
 case we're setting the light's position to -1, 2, 4 so it's slightly on the left,
 above, and behind our camera. The target is still 0, 0, 0 so it will shine
-toward the origin.
-
-We also need to change the material. The `MeshBasicMaterial` is not affected by
-lights. Let's change it to a `MeshPhongMaterial` which is affected by lights.
-
-```js
--const material = new THREE.MeshBasicMaterial({color: 0x44aa88});  // greenish blue
+toward the origin.</p>
+<p>We also need to change the material. The <a href="/docs/#api/en/materials/MeshBasicMaterial"><code class="notranslate" translate="no">MeshBasicMaterial</code></a> is not affected by
+lights. Let's change it to a <a href="/docs/#api/en/materials/MeshPhongMaterial"><code class="notranslate" translate="no">MeshPhongMaterial</code></a> which is affected by lights.</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
-```
-
-Here is our new program structure
-
-<div class="threejs_center"><img src="resources/images/threejs-1cube-with-directionallight.svg" style="width: 500px;"></div>
-
-And here it is working.
-
-{{{example url="../threejs-fundamentals-with-light.html" }}}
-
-It should now be pretty clearly 3D.
-
-Just for the fun of it let's add 2 more cubes.
+</pre>
+<p>Here is our new program structure</p>
+<div class="threejs_center"><img src="../resources/images/threejs-1cube-with-directionallight.svg" style="width: 500px;"></div>
 
-We'll use the same geometry for each cube but make a different
-material so each cube can be a different color.
+<p>And here it is working.</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">click here to open in a separate window</a>
+</div>
 
-First we'll make a function that creates a new material
+<p></p>
+<p>It should now be pretty clearly 3D.</p>
+<p>Just for the fun of it let's add 2 more cubes.</p>
+<p>We'll use the same geometry for each cube but make a different
+material so each cube can be a different color.</p>
+<p>First we'll make a function that creates a new material
 with the specified color. Then it creates a mesh using
 the specified geometry and adds it to the scene and
-sets its X position.
-
-```js
-function makeInstance(geometry, color, x) {
+sets its X position.</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);
@@ -356,27 +309,21 @@ function makeInstance(geometry, color, x) {
 
   return cube;
 }
-```
-
-Then we'll call it 3 times with 3 different colors and X positions
-saving the `Mesh` instances in an array.
-
-```js
-const cubes = [
+</pre>
+<p>Then we'll call it 3 times with 3 different colors and X positions
+saving the <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a> instances in an array.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const cubes = [
   makeInstance(geometry, 0x44aa88,  0),
   makeInstance(geometry, 0x8844aa, -2),
   makeInstance(geometry, 0xaa8844,  2),
 ];
-```
-
-Finally we'll spin all 3 cubes in our render function. We
-compute a slightly different rotation for each one.
-
-```js
-function render(time) {
+</pre>
+<p>Finally we'll spin all 3 cubes in our render function. We
+compute a slightly different rotation for each one.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function render(time) {
   time *= 0.001;  // convert time to seconds
 
-  cubes.forEach((cube, ndx) => {
+  cubes.forEach((cube, ndx) =&gt; {
     const speed = 1 + ndx * .1;
     const rot = time * speed;
     cube.rotation.x = rot;
@@ -384,56 +331,52 @@ function render(time) {
   });
 
   ...
-```
-
-and here's that.
-
-{{{example url="../threejs-fundamentals-3-cubes.html" }}}
+</pre>
+<p>and here's that.</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">click here to open in a separate window</a>
+</div>
 
-If you compare it to the top down diagram above you can see
+<p></p>
+<p>If you compare it to the top down diagram above you can see
 it matches our expectations. With cubes at X = -2 and X = +2
 they are partially outside our frustum. They are also
 somewhat exaggeratedly warped since the field of view
-across the canvas is so extreme.
-
-Our program now has this structure
-
-<div class="threejs_center"><img src="resources/images/threejs-3cubes-scene.svg" style="width: 610px;"></div>
-
-As you can see we have 3 `Mesh` objects each referencing the same `BoxGeometry`.
-Each `Mesh` references a unique `MeshPhongMaterial` so that each cube can have
-a different color.
-
-I hope this short intro helps to get things started. [Next up we'll cover
-making our code responsive so it is adaptable to multiple situations](threejs-responsive.html).
-
+across the canvas is so extreme.</p>
+<p>Our program now has this structure</p>
+<div class="threejs_center"><img src="../resources/images/threejs-3cubes-scene.svg" style="width: 610px;"></div>
+
+<p>As you can see we have 3 <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a> objects each referencing the same <a href="/docs/#api/en/geometries/BoxGeometry"><code class="notranslate" translate="no">BoxGeometry</code></a>.
+Each <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a> references a unique <a href="/docs/#api/en/materials/MeshPhongMaterial"><code class="notranslate" translate="no">MeshPhongMaterial</code></a> so that each cube can have
+a different color.</p>
+<p>I hope this short intro helps to get things started. <a href="responsive.html">Next up we'll cover
+making our code responsive so it is adaptable to multiple situations</a>.</p>
 <div id="es6" class="threejs_bottombar">
 <h3>es6 modules, three.js, and folder structure</h3>
 <p>As of version r106 the preferred way to use three.js is via <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import">es6 modules</a>.</p>
 <p>
-es6 modules can be loaded via the <code>import</code> keyword in a script
-or inline via a <code>&lt;script type="module"&gt;</code> tag. Here's an example of
+es6 modules can be loaded via the <code class="notranslate" translate="no">import</code> keyword in a script
+or inline via a <code class="notranslate" translate="no">&lt;script type="module"&gt;</code> tag. Here's an example of
 both
 </p>
-<pre class=prettyprint>
-&lt;script type="module"&gt;
-import * as THREE from './resources/threejs/r132/build/three.module.js';
+<pre class="prettyprint">&lt;script type="module"&gt;
+import * as THREE from '../../build/three.module.js';
 
 ...
 
 &lt;/script&gt;
 </pre>
 <p>
-Paths must be absolute or relative. Relative paths always start with <code>./</code> or <code>../</code>
-which is different than other tags like <code>&lt;img&gt;</code> and <code>&lt;a&gt;</code>.
+Paths must be absolute or relative. Relative paths always start with <code class="notranslate" translate="no">./</code> or <code class="notranslate" translate="no">../</code>
+which is different than other tags like <code class="notranslate" translate="no">&lt;img&gt;</code> and <code class="notranslate" translate="no">&lt;a&gt;</code>.
 </p>
 <p>
 References to the same script will only be loaded once as long as their absolute paths
 are exactly the same. For three.js this means it's required that you put all the examples
 libraries in the correct folder structure
 </p>
-<pre class="dos">
-someFolder
+<pre class="dos">someFolder
  |
  ├-build
  | |
@@ -458,36 +401,37 @@ someFolder
 </pre>
 <p>
 The reason this folder structure is required is because the scripts in the
-examples like <a href="https://github.com/mrdoob/three.js/blob/master/examples/jsm/controls/OrbitControls.js"><code>OrbitControls.js</code></a>
+examples like <a href="https://github.com/mrdoob/three.js/blob/master/examples/jsm/controls/OrbitControls.js"><code class="notranslate" translate="no">OrbitControls.js</code></a>
 have hard coded relative paths like
 </p>
-<pre class="prettyprint">
-import * as THREE from '../../../build/three.module.js';
+<pre class="prettyprint">import * as THREE from '../../../build/three.module.js';
 </pre>
 <p>
 Using the same structure assures then when you import both three and one of the example
-libraries they'll both reference the same <code>three.module.js</code> file.
+libraries they'll both reference the same <code class="notranslate" translate="no">three.module.js</code> file.
 </p>
-<pre class="prettyprint">
-import * as THREE from './someFolder/build/three.module.js';
+<pre class="prettyprint">import * as THREE from './someFolder/build/three.module.js';
 import {OrbitControls} from './someFolder/examples/jsm/controls/OrbitControls.js';
 </pre>
-<p>This includes when using a CDN. Be sure your path to <code>three.module.js</code> ends with
-<code>/build/three.modules.js</code>. For example</p>
-<pre class="prettyprint">
-import * as THREE from 'https://unpkg.com/[email protected]<b>/build/three.module.js</b>';
+<p>This includes when using a CDN. Be sure your path to <code class="notranslate" translate="no">three.module.js</code> ends with
+<code class="notranslate" translate="no">/build/three.modules.js</code>. For example</p>
+<pre class="prettyprint">import * as THREE from 'https://unpkg.com/[email protected]<b>/build/three.module.js</b>';
 import {OrbitControls} from 'https://unpkg.com/[email protected]/examples/jsm/controls/OrbitControls.js';
 </pre>
-<p>If you'd prefer the old <code>&lt;script src="path/to/three.js"&gt;&lt;/script&gt;</code> style
-you can check out <a href="https://r105.threejsfundamentals.org">an older version of this site</a>.
-Three.js has a policy of not worrying about backward compatibility. They expect you to use a specific
-version, as in you're expected to download the code and put it in your project. When upgrading to a newer version
-you can read the <a href="https://github.com/mrdoob/three.js/wiki/Migration-Guide">migration guide</a> to
-see what you need to change. It would be too much work to maintain both an es6 module and a class script
-version of this site so going forward this site will only show es6 module style. As stated elsewhere,
-to support legacy browsers look into a <a href="https://babeljs.io">transpiler</a>.</p>
 </div>
 
 <!-- needed in English only to prevent warning from outdated translations -->
-<a href="threejs-geometry.html"></a>
-<a href="Geometry"></a>
+<p><a href="geometry.html"></a>
+<a href="Geometry"></a></p>
+
+        </div>
+      </div>
+    </div>
+  
+  <script src="/manual/resources/prettify.js"></script>
+  <script src="/manual/resources/lesson.js"></script>
+
+
+
+
+</body></html>

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 290 - 389
manual/en/game.html


+ 261 - 300
manual/en/indexed-textures.html

@@ -1,80 +1,78 @@
-Title: Three.js Indexed Textures for Picking and Color
-Description: Using Indexed Textures for Picking and Color
-TOC: Using Indexed Textures for Picking and Color
-
-This article is a continuation of [an article about aligning html elements to 3d](threejs-align-html-elements-to-3d.html).
-If you haven't read that yet you should start there before continuing here.
-
-Sometimes using three.js requires coming up with creative solutions.
+<!DOCTYPE html><html lang="en"><head>
+    <meta charset="utf-8">
+    <title>Indexed Textures for Picking and Color</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 – Indexed Textures for Picking and Color">
+    <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">
+  </head>
+  <body>
+    <div class="container">
+      <div class="lesson-title">
+        <h1>Indexed Textures for Picking and Color</h1>
+      </div>
+      <div class="lesson">
+        <div class="lesson-main">
+          <p>This article is a continuation of <a href="align-html-elements-to-3d.html">an article about aligning html elements to 3d</a>.
+If you haven't read that yet you should start there before continuing here.</p>
+<p>Sometimes using three.js requires coming up with creative solutions.
 I'm not sure this is a great solution but I thought I'd share it and
-you can see if it suggests any solutions for your needs.
-
-In the [previous article](threejs-align-html-elements-to-3d.html) we
+you can see if it suggests any solutions for your needs.</p>
+<p>In the <a href="align-html-elements-to-3d.html">previous article</a> we
 displayed country names around a 3d globe. How would we go about letting
-the user select a country and show their selection?
-
-The first idea that comes to mind is to generate geometry for each country.
-We could [use a picking solution](threejs-picking.html) like we covered before.
+the user select a country and show their selection?</p>
+<p>The first idea that comes to mind is to generate geometry for each country.
+We could <a href="picking.html">use a picking solution</a> like we covered before.
 We'd build 3D geometry for each country. If the user clicks on the mesh for 
-that country we'd know what country was clicked.
-
-So, just to check that solution I tried generating 3D meshes of all the countries
+that country we'd know what country was clicked.</p>
+<p>So, just to check that solution I tried generating 3D meshes of all the countries
 using the same data I used to generate the outlines 
-[in the previous article](threejs-align-html-elements-to-3d.html).
+<a href="align-html-elements-to-3d.html">in the previous article</a>.
 The result was a 15.5meg binary GLTF (.glb) file. Making the user download 15.5meg
-sounds like too much to me.
-
-There are lots of ways to compress the data. The first would probably be
+sounds like too much to me.</p>
+<p>There are lots of ways to compress the data. The first would probably be
 to apply some algorithm to lower the resolution of the outlines. I didn't spend
 any time pursuing that solution. For borders of the USA that's probably a huge
-win. For a borders of Canada probably much less. 
-
-Another solution would be to use just actual data compression. For example gzipping
-the file brought it down to 11meg. That's 30% less but arguably not enough.
-
-We could store all the data as 16bit ranged values instead of 32bit float values. 
-Or we could use something like [draco compression](https://google.github.io/draco/)
+win. For a borders of Canada probably much less. </p>
+<p>Another solution would be to use just actual data compression. For example gzipping
+the file brought it down to 11meg. That's 30% less but arguably not enough.</p>
+<p>We could store all the data as 16bit ranged values instead of 32bit float values. 
+Or we could use something like <a href="https://google.github.io/draco/">draco compression</a>
 and maybe that would be enough. I didn't check and I would encourage you to check 
-yourself and tell me how it goes as I'd love to know. 😅
-
-In my case I thought about [the GPU picking solution](threejs-picking.html) 
-we covered at the end of [the article on picking](threejs-picking.html). In
+yourself and tell me how it goes as I'd love to know. 😅</p>
+<p>In my case I thought about <a href="picking.html">the GPU picking solution</a> 
+we covered at the end of <a href="picking.html">the article on picking</a>. In
 that solution we drew every mesh with a unique color that represented that
 mesh's id. We then drew all the meshes and looked at the color that was clicked
-on.
-
-Taking inspiration from that we could pre-generate a map of countries where
+on.</p>
+<p>Taking inspiration from that we could pre-generate a map of countries where
 each country's color is its index number in our array of countries. We could
 then use a similar GPU picking technique. We'd draw the globe off screen using
 this index texture. Looking at the color of the pixel the user clicks would 
-tell us the country id.
-
-So, I [wrote some code](https://github.com/gfxfundamentals/threejsfundamentals/blob/master/threejs/lessons/tools/geo-picking/) 
-to generate such a texture. Here it is. 
-
-<div class="threejs_center"><img src="../resources/data/world/country-index-texture.png" style="width: 700px;"></div>
-
-Note: The data used to generate this texture comes from [this website](http://thematicmapping.org/downloads/world_borders.php) 
-and is therefore licensed as [CC-BY-SA](http://creativecommons.org/licenses/by-sa/3.0/).
-
-It's only 217k, much better than the 14meg for the country meshes. In fact we could probably
-even lower the resolution but 217k seems good enough for now.
-
-So let's try using it for picking countries.
-
-Grabbing code from the [gpu picking example](threejs-picking.html) we need
-a scene for picking.
-
-```js
-const pickingScene = new THREE.Scene();
+tell us the country id.</p>
+<p>So, I <a href="https://github.com/mrdoob/three.js/blob/master/manual/resources/tools/geo-picking/">wrote some code</a> 
+to generate such a texture. Here it is. </p>
+<div class="threejs_center"><img src="../examples/resources/data/world/country-index-texture.png" style="width: 700px;"></div>
+
+<p>Note: The data used to generate this texture comes from <a href="http://thematicmapping.org/downloads/world_borders.php">this website</a> 
+and is therefore licensed as <a href="http://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>.</p>
+<p>It's only 217k, much better than the 14meg for the country meshes. In fact we could probably
+even lower the resolution but 217k seems good enough for now.</p>
+<p>So let's try using it for picking countries.</p>
+<p>Grabbing code from the <a href="picking.html">gpu picking example</a> we need
+a scene for picking.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const pickingScene = new THREE.Scene();
 pickingScene.background = new THREE.Color(0);
-```
-
-and we need to add the globe with the our index texture to the
-picking scene.
-
-```js
-{
+</pre>
+<p>and we need to add the globe with the our index texture to the
+picking scene.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
   const loader = new THREE.TextureLoader();
   const geometry = new THREE.SphereGeometry(1, 64, 32);
 
@@ -89,13 +87,10 @@ picking scene.
   const material = new THREE.MeshBasicMaterial({map: texture});
   scene.add(new THREE.Mesh(geometry, material));
 }
-```
-
-Then let's copy over the `GPUPickingHelper` class we used
-before with a few minor changes.
-
-```js
-class GPUPickHelper {
+</pre>
+<p>Then let's copy over the <code class="notranslate" translate="no">GPUPickingHelper</code> class we used
+before with a few minor changes.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">class GPUPickHelper {
   constructor() {
     // create a 1x1 pixel render target
     this.pickingTexture = new THREE.WebGLRenderTarget(1, 1);
@@ -132,14 +127,14 @@ class GPUPickHelper {
         pixelBuffer);
 
 +    const id =
-+        (pixelBuffer[0] << 16) |
-+        (pixelBuffer[1] <<  8) |
-+        (pixelBuffer[2] <<  0);
++        (pixelBuffer[0] &lt;&lt; 16) |
++        (pixelBuffer[1] &lt;&lt;  8) |
++        (pixelBuffer[2] &lt;&lt;  0);
 +
 +    return id;
 -    const id =
--        (pixelBuffer[0] << 16) |
--        (pixelBuffer[1] <<  8) |
+-        (pixelBuffer[0] &lt;&lt; 16) |
+-        (pixelBuffer[1] &lt;&lt;  8) |
 -        (pixelBuffer[2]      );
 -    const intersectedObject = idToObject[id];
 -    if (intersectedObject) {
@@ -148,16 +143,13 @@ class GPUPickHelper {
 -      // save its color
 -      this.pickedObjectSavedColor = this.pickedObject.material.emissive.getHex();
 -      // set its emissive color to flashing red/yellow
--      this.pickedObject.material.emissive.setHex((time * 8) % 2 > 1 ? 0xFFFF00 : 0xFF0000);
+-      this.pickedObject.material.emissive.setHex((time * 8) % 2 &gt; 1 ? 0xFFFF00 : 0xFF0000);
 -    }
   }
 }
-```
-
-Now we can use that to pick countries.
-
-```js
-const pickHelper = new GPUPickHelper();
+</pre>
+<p>Now we can use that to pick countries.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const pickHelper = new GPUPickHelper();
 
 function getCanvasRelativePosition(event) {
   const rect = canvas.getBoundingClientRect();
@@ -175,13 +167,13 @@ function pickCountry(event) {
 
   const position = getCanvasRelativePosition(event);
   const id = pickHelper.pick(position, pickingScene, camera);
-  if (id > 0) {
+  if (id &gt; 0) {
     // we clicked a country. Toggle its 'selected' property
     const countryInfo = countryInfos[id - 1];
     const selected = !countryInfo.selected;
     // if we're selecting this country and modifiers are not
     // pressed unselect everything else.
-    if (selected && !event.shiftKey && !event.ctrlKey && !event.metaKey) {
+    if (selected &amp;&amp; !event.shiftKey &amp;&amp; !event.ctrlKey &amp;&amp; !event.metaKey) {
       unselectAllCountries();
     }
     numCountriesSelected += selected ? 1 : -1;
@@ -195,23 +187,19 @@ function pickCountry(event) {
 
 function unselectAllCountries() {
   numCountriesSelected = 0;
-  countryInfos.forEach((countryInfo) => {
+  countryInfos.forEach((countryInfo) =&gt; {
     countryInfo.selected = false;
   });
 }
 
 canvas.addEventListener('pointerup', pickCountry);
-```
-
-The code above sets/unsets the `selected` property on
-the array of countries. If `shift` or `ctrl` or `cmd`
-is pressed then you can select more than one country.
-
-All that's left is showing the selected countries. For now
-let's just update the labels.
-
-```js
-function updateLabels() {
+</pre>
+<p>The code above sets/unsets the <code class="notranslate" translate="no">selected</code> property on
+the array of countries. If <code class="notranslate" translate="no">shift</code> or <code class="notranslate" translate="no">ctrl</code> or <code class="notranslate" translate="no">cmd</code>
+is pressed then you can select more than one country.</p>
+<p>All that's left is showing the selected countries. For now
+let's just update the labels.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function updateLabels() {
   // exit if we have not loaded the data yet
   if (!countryInfos) {
     return;
@@ -225,44 +213,40 @@ function updateLabels() {
   for (const countryInfo of countryInfos) {
 -    const {position, elem, area} = countryInfo;
 -    // large enough?
--    if (area < large) {
+-    if (area &lt; large) {
 +    const {position, elem, area, selected} = countryInfo;
-+    const largeEnough = area >= large;
-+    const show = selected || (numCountriesSelected === 0 && largeEnough);
++    const largeEnough = area &gt;= large;
++    const show = selected || (numCountriesSelected === 0 &amp;&amp; largeEnough);
 +    if (!show) {
       elem.style.display = 'none';
       continue;
     }
 
     ...
-```
-
-and with that we should be able to pick countries
-
-{{{example url="../threejs-indexed-textures-picking.html" }}}
-
-The code stills shows countries based on their area but if you
-click one just that one will have a label.
-
-So that seems like a reasonable solution for picking countries 
-but what about highlighting the selected countries?
-
-For that we can take inspiration from *paletted graphics*.
-
-[Paletted graphics](https://en.wikipedia.org/wiki/Palette_%28computing%29)
-or [Indexed Color](https://en.wikipedia.org/wiki/Indexed_color) is 
+</pre>
+<p>and with that we should be able to pick countries</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/indexed-textures-picking.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/indexed-textures-picking.html" target="_blank">click here to open in a separate window</a>
+</div>
+
+<p></p>
+<p>The code stills shows countries based on their area but if you
+click one just that one will have a label.</p>
+<p>So that seems like a reasonable solution for picking countries 
+but what about highlighting the selected countries?</p>
+<p>For that we can take inspiration from <em>paletted graphics</em>.</p>
+<p><a href="https://en.wikipedia.org/wiki/Palette_%28computing%29">Paletted graphics</a>
+or <a href="https://en.wikipedia.org/wiki/Indexed_color">Indexed Color</a> is 
 what older systems like the Atari 800, Amiga, NES, 
 Super Nintendo, and even older IBM PCs used. Instead of storing bitmaps
 as RGB colors 8bits per color, 24 bytes per pixel or more, they stored 
 bitmaps as 8bit values or less. The value for each pixel was an index
 into a palette. So for example a value
 of 3 in the image means "display color 3". What color color#3 is is
-defined somewhere else called a "palette".
-
-In JavaScript you can think of it like this
-
-```js
-const face7x7PixelImageData = [
+defined somewhere else called a "palette".</p>
+<p>In JavaScript you can think of it like this</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const face7x7PixelImageData = [
   0, 1, 1, 1, 1, 1, 0,
   1, 0, 0, 0, 0, 0, 1, 
   1, 0, 2, 0, 2, 0, 1,
@@ -278,86 +262,74 @@ const palette = [
   [  0, 255, 255],  // cyan
   [255,   0,   0],  // red
 ];
-```
-
-Where each pixel in the image data is an index into palette. If you interpreted
-the image data through the palette above you'd get this image
+</pre>
+<p>Where each pixel in the image data is an index into palette. If you interpreted
+the image data through the palette above you'd get this image</p>
+<div class="threejs_center"><img src="../resources/images/7x7-indexed-face.png"></div>
 
-<div class="threejs_center"><img src="resources/images/7x7-indexed-face.png"></div>
-
-In our case we already have a texture above that has a different id
+<p>In our case we already have a texture above that has a different id
 per country. So, we could use that same texture through a palette
 texture to give each country its own color. By changing the palette
 texture we can color each individual country. For example by setting
 the entire palette texture to black and then for one country's entry
-in the palette a different color, we can highlight just that country.
-
-To do paletted index graphics requires some custom shader code. 
+in the palette a different color, we can highlight just that country.</p>
+<p>To do paletted index graphics requires some custom shader code. 
 Let's modify the default shaders in three.js. 
-That way we can use lighting and other features if we want.
-
-Like we covered in [the article on animating lots of objects](threejs-optimize-lots-of-objects-animated.html)
+That way we can use lighting and other features if we want.</p>
+<p>Like we covered in <a href="optimize-lots-of-objects-animated.html">the article on animating lots of objects</a>
 we can modify the default shaders by adding a function to a material's
-`onBeforeCompile` property.
-
-The default fragment shader looks something like this before compiling.
-
-```glsl
-#include <common>
-#include <color_pars_fragment>
-#include <uv_pars_fragment>
-#include <uv2_pars_fragment>
-#include <map_pars_fragment>
-#include <alphamap_pars_fragment>
-#include <aomap_pars_fragment>
-#include <lightmap_pars_fragment>
-#include <envmap_pars_fragment>
-#include <fog_pars_fragment>
-#include <specularmap_pars_fragment>
-#include <logdepthbuf_pars_fragment>
-#include <clipping_planes_pars_fragment>
+<code class="notranslate" translate="no">onBeforeCompile</code> property.</p>
+<p>The default fragment shader looks something like this before compiling.</p>
+<pre class="prettyprint showlinemods notranslate lang-glsl" translate="no">#include &lt;common&gt;
+#include &lt;color_pars_fragment&gt;
+#include &lt;uv_pars_fragment&gt;
+#include &lt;uv2_pars_fragment&gt;
+#include &lt;map_pars_fragment&gt;
+#include &lt;alphamap_pars_fragment&gt;
+#include &lt;aomap_pars_fragment&gt;
+#include &lt;lightmap_pars_fragment&gt;
+#include &lt;envmap_pars_fragment&gt;
+#include &lt;fog_pars_fragment&gt;
+#include &lt;specularmap_pars_fragment&gt;
+#include &lt;logdepthbuf_pars_fragment&gt;
+#include &lt;clipping_planes_pars_fragment&gt;
 void main() {
-	#include <clipping_planes_fragment>
-	vec4 diffuseColor = vec4( diffuse, opacity );
-	#include <logdepthbuf_fragment>
-	#include <map_fragment>
-	#include <color_fragment>
-	#include <alphamap_fragment>
-	#include <alphatest_fragment>
-	#include <specularmap_fragment>
-	ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );
-	#ifdef USE_LIGHTMAP
-		reflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;
-	#else
-		reflectedLight.indirectDiffuse += vec3( 1.0 );
-	#endif
-	#include <aomap_fragment>
-	reflectedLight.indirectDiffuse *= diffuseColor.rgb;
-	vec3 outgoingLight = reflectedLight.indirectDiffuse;
-	#include <envmap_fragment>
-	gl_FragColor = vec4( outgoingLight, diffuseColor.a );
-	#include <premultiplied_alpha_fragment>
-	#include <tonemapping_fragment>
-	#include <encodings_fragment>
-	#include <fog_fragment>
+    #include &lt;clipping_planes_fragment&gt;
+    vec4 diffuseColor = vec4( diffuse, opacity );
+    #include &lt;logdepthbuf_fragment&gt;
+    #include &lt;map_fragment&gt;
+    #include &lt;color_fragment&gt;
+    #include &lt;alphamap_fragment&gt;
+    #include &lt;alphatest_fragment&gt;
+    #include &lt;specularmap_fragment&gt;
+    ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );
+    #ifdef USE_LIGHTMAP
+        reflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;
+    #else
+        reflectedLight.indirectDiffuse += vec3( 1.0 );
+    #endif
+    #include &lt;aomap_fragment&gt;
+    reflectedLight.indirectDiffuse *= diffuseColor.rgb;
+    vec3 outgoingLight = reflectedLight.indirectDiffuse;
+    #include &lt;envmap_fragment&gt;
+    gl_FragColor = vec4( outgoingLight, diffuseColor.a );
+    #include &lt;premultiplied_alpha_fragment&gt;
+    #include &lt;tonemapping_fragment&gt;
+    #include &lt;encodings_fragment&gt;
+    #include &lt;fog_fragment&gt;
 }
-```
-
-[Digging through all those snippets](https://github.com/mrdoob/three.js/tree/dev/src/renderers/shaders/ShaderChunk)
-we find that three.js uses a variable called `diffuseColor` to manage the 
-base material color. It sets this in the `<color_fragment>` [snippet](https://github.com/mrdoob/three.js/blob/dev/src/renderers/shaders/ShaderChunk/color_fragment.glsl.js)
-so we should be able to modify it after that point.
-
-`diffuseColor` at that point in the shader should already be the color from 
+</pre>
+<p><a href="https://github.com/mrdoob/three.js/tree/dev/src/renderers/shaders/ShaderChunk">Digging through all those snippets</a>
+we find that three.js uses a variable called <code class="notranslate" translate="no">diffuseColor</code> to manage the 
+base material color. It sets this in the <code class="notranslate" translate="no">&lt;color_fragment&gt;</code> <a href="https://github.com/mrdoob/three.js/blob/dev/src/renderers/shaders/ShaderChunk/color_fragment.glsl.js">snippet</a>
+so we should be able to modify it after that point.</p>
+<p><code class="notranslate" translate="no">diffuseColor</code> at that point in the shader should already be the color from 
 our outline texture so we can look up the color from a palette texture 
-and mix them for the final result.
-
-Like we [did before](threejs-optimize-lots-of-objects-animated.html) we'll make an array
+and mix them for the final result.</p>
+<p>Like we <a href="optimize-lots-of-objects-animated.html">did before</a> we'll make an array
 of search and replacement strings and apply them to the shader in 
-`Material.onBeforeCompile`.
-
-```js
-{
+<a href="/docs/#api/en/materials/Material.onBeforeCompile"><code class="notranslate" translate="no">Material.onBeforeCompile</code></a>.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
   const loader = new THREE.TextureLoader();
   const geometry = new THREE.SphereGeometry(1, 64, 32);
 
@@ -370,18 +342,18 @@ of search and replacement strings and apply them to the shader in
 
 +  const fragmentShaderReplacements = [
 +    {
-+      from: '#include <common>',
++      from: '#include &lt;common&gt;',
 +      to: `
-+        #include <common>
++        #include &lt;common&gt;
 +        uniform sampler2D indexTexture;
 +        uniform sampler2D paletteTexture;
 +        uniform float paletteTextureWidth;
 +      `,
 +    },
 +    {
-+      from: '#include <color_fragment>',
++      from: '#include &lt;color_fragment&gt;',
 +      to: `
-+        #include <color_fragment>
++        #include &lt;color_fragment&gt;
 +        {
 +          vec4 indexColor = texture2D(indexTexture, vUv);
 +          float index = indexColor.r * 255.0 + indexColor.g * 255.0 * 256.0;
@@ -397,37 +369,31 @@ of search and replacement strings and apply them to the shader in
   const texture = loader.load('resources/data/world/country-outlines-4k.png', render);
   const material = new THREE.MeshBasicMaterial({map: texture});
 +  material.onBeforeCompile = function(shader) {
-+    fragmentShaderReplacements.forEach((rep) => {
++    fragmentShaderReplacements.forEach((rep) =&gt; {
 +      shader.fragmentShader = shader.fragmentShader.replace(rep.from, rep.to);
 +    });
 +  };
   scene.add(new THREE.Mesh(geometry, material));
 }
-```
-
-Above can see above we add 3 uniforms, `indexTexture`, `paletteTexture`,
-and `paletteTextureWidth`. We get a color from the `indexTexture`
-and convert it to an index. `vUv` is the texture coordinates provided by 
+</pre>
+<p>Above can see above we add 3 uniforms, <code class="notranslate" translate="no">indexTexture</code>, <code class="notranslate" translate="no">paletteTexture</code>,
+and <code class="notranslate" translate="no">paletteTextureWidth</code>. We get a color from the <code class="notranslate" translate="no">indexTexture</code>
+and convert it to an index. <code class="notranslate" translate="no">vUv</code> is the texture coordinates provided by 
 three.js. We then use that index to get a color out of the palette texture.
-We then mix the result with the current `diffuseColor`. The `diffuseColor`
+We then mix the result with the current <code class="notranslate" translate="no">diffuseColor</code>. The <code class="notranslate" translate="no">diffuseColor</code>
 at this point is our black and white outline texture so if we add the 2 colors
 we'll get white outlines. If we subtract the current diffuse color we'll get
-black outlines.
-
-Before we can render we need to setup the palette texture
-and these 3 uniforms.
-
-For the palette texture it just needs to be wide enough to
+black outlines.</p>
+<p>Before we can render we need to setup the palette texture
+and these 3 uniforms.</p>
+<p>For the palette texture it just needs to be wide enough to
 hold one color per country + one for the ocean (id = 0).
 There are 240 something countries. We could wait until the
 list of countries loads to get an exact number or look it up.
 There's not much harm in just picking some larger number so
-let's choose 512.
-
-Here's the code to create the palette texture
-
-```js
-const maxNumCountries = 512;
+let's choose 512.</p>
+<p>Here's the code to create the palette texture</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const maxNumCountries = 512;
 const paletteTextureWidth = maxNumCountries;
 const paletteTextureHeight = 1;
 const palette = new Uint8Array(paletteTextureWidth * 3);
@@ -435,34 +401,26 @@ const paletteTexture = new THREE.DataTexture(
     palette, paletteTextureWidth, paletteTextureHeight, THREE.RGBFormat);
 paletteTexture.minFilter = THREE.NearestFilter;
 paletteTexture.magFilter = THREE.NearestFilter;
-```
-
-A `DataTexture` let's us give a texture raw data. In this case
+</pre>
+<p>A <a href="/docs/#api/en/textures/DataTexture"><code class="notranslate" translate="no">DataTexture</code></a> let's us give a texture raw data. In this case
 we're giving it 512 RGB colors, 3 bytes each where each byte is
-red, green, and blue respectively using values that go from 0 to 255.
-
-Let's fill it with random colors just to see it work
-
-```js
-for (let i = 1; i < palette.length; ++i) {
+red, green, and blue respectively using values that go from 0 to 255.</p>
+<p>Let's fill it with random colors just to see it work</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">for (let i = 1; i &lt; palette.length; ++i) {
   palette[i] = Math.random() * 256;
 }
 // set the ocean color (index #0)
 palette.set([100, 200, 255], 0);
 paletteTexture.needsUpdate = true;
-```
-
-Anytime we want three.js to update the palette texture with
-the contents of the `palette` array we need to set `paletteTexture.needsUpdate`
-to `true`.
-
-And then we still need to set the uniforms on the material.
-
-```js
-const geometry = new THREE.SphereGeometry(1, 64, 32);
+</pre>
+<p>Anytime we want three.js to update the palette texture with
+the contents of the <code class="notranslate" translate="no">palette</code> array we need to set <code class="notranslate" translate="no">paletteTexture.needsUpdate</code>
+to <code class="notranslate" translate="no">true</code>.</p>
+<p>And then we still need to set the uniforms on the material.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const geometry = new THREE.SphereGeometry(1, 64, 32);
 const material = new THREE.MeshBasicMaterial({map: texture});
 material.onBeforeCompile = function(shader) {
-  fragmentShaderReplacements.forEach((rep) => {
+  fragmentShaderReplacements.forEach((rep) =&gt; {
     shader.fragmentShader = shader.fragmentShader.replace(rep.from, rep.to);
   });
 +  shader.uniforms.paletteTexture = {value: paletteTexture};
@@ -470,34 +428,29 @@ material.onBeforeCompile = function(shader) {
 +  shader.uniforms.paletteTextureWidth = {value: paletteTextureWidth};
 };
 scene.add(new THREE.Mesh(geometry, material));
-```
-
-and with that we get randomly colored countries.
-
-{{{example url="../threejs-indexed-textures-random-colors.html" }}}
-
-Now that we can see the index and palette textures are working
-let's manipulate the palette for highlighting.
-
-First let's make function that will let us pass in a three.js
-style color and give us values we can put in the palette texture.
-
-```js
-const tempColor = new THREE.Color();
+</pre>
+<p>and with that we get randomly colored countries.</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/indexed-textures-random-colors.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/indexed-textures-random-colors.html" target="_blank">click here to open in a separate window</a>
+</div>
+
+<p></p>
+<p>Now that we can see the index and palette textures are working
+let's manipulate the palette for highlighting.</p>
+<p>First let's make function that will let us pass in a three.js
+style color and give us values we can put in the palette texture.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const tempColor = new THREE.Color();
 function get255BasedColor(color) {
   tempColor.set(color);
-  return tempColor.toArray().map(v => v * 255);
+  return tempColor.toArray().map(v =&gt; v * 255);
 }
-```
-
-Calling it like this `color = get255BasedColor('red')` will
-return an array like `[255, 0, 0]`.
-
-Next let's use it to make a few colors and fill out the
-palette.
-
-```js
-const selectedColor = get255BasedColor('red');
+</pre>
+<p>Calling it like this <code class="notranslate" translate="no">color = get255BasedColor('red')</code> will
+return an array like <code class="notranslate" translate="no">[255, 0, 0]</code>.</p>
+<p>Next let's use it to make a few colors and fill out the
+palette.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const selectedColor = get255BasedColor('red');
 const unselectedColor = get255BasedColor('#444');
 const oceanColor = get255BasedColor('rgb(100,200,255)');
 resetPalette();
@@ -508,7 +461,7 @@ function setPaletteColor(index, color) {
 
 function resetPalette() {
   // make all colors the unselected color
-  for (let i = 1; i < maxNumCountries; ++i) {
+  for (let i = 1; i &lt; maxNumCountries; ++i) {
     setPaletteColor(i, unselectedColor);
   }
 
@@ -516,13 +469,10 @@ function resetPalette() {
   setPaletteColor(0, oceanColor);
   paletteTexture.needsUpdate = true;
 }
-```
-
-Now let's use those functions to update the palette when a country
-is selected
-
-```js
-function getCanvasRelativePosition(event) {
+</pre>
+<p>Now let's use those functions to update the palette when a country
+is selected</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function getCanvasRelativePosition(event) {
   const rect = canvas.getBoundingClientRect();
   return {
     x: (event.clientX - rect.left) * canvas.width  / rect.width,
@@ -538,10 +488,10 @@ function pickCountry(event) {
 
   const position = getCanvasRelativePosition(event);
   const id = pickHelper.pick(position, pickingScene, camera);
-  if (id > 0) {
+  if (id &gt; 0) {
     const countryInfo = countryInfos[id - 1];
     const selected = !countryInfo.selected;
-    if (selected && !event.shiftKey && !event.ctrlKey && !event.metaKey) {
+    if (selected &amp;&amp; !event.shiftKey &amp;&amp; !event.ctrlKey &amp;&amp; !event.metaKey) {
       unselectAllCountries();
     }
     numCountriesSelected += selected ? 1 : -1;
@@ -556,32 +506,30 @@ function pickCountry(event) {
 
 function unselectAllCountries() {
   numCountriesSelected = 0;
-  countryInfos.forEach((countryInfo) => {
+  countryInfos.forEach((countryInfo) =&gt; {
     countryInfo.selected = false;
   });
 +  resetPalette();
 }
-```
-
-and we that we should be able to highlight 1 or more countries.
-
-{{{example url="../threejs-indexed-textures-picking-and-highlighting.html" }}}
-
-That seems to work!
-
-One minor thing is we can't spin the globe without changing
+</pre>
+<p>and we that we should be able to highlight 1 or more countries.</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/indexed-textures-picking-and-highlighting.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/indexed-textures-picking-and-highlighting.html" target="_blank">click here to open in a separate window</a>
+</div>
+
+<p></p>
+<p>That seems to work!</p>
+<p>One minor thing is we can't spin the globe without changing
 the selection state. If we select a country and then want to
-rotate the globe the selection will change.
-
-Let's try to fix that. Off the top of my head we can check 2 things.
+rotate the globe the selection will change.</p>
+<p>Let's try to fix that. Off the top of my head we can check 2 things.
 How much time passed between clicking and letting go.
 Another is did the user actually move the mouse. If the
 time is short or if they didn't move the mouse then it
 was probably a click. Otherwise they were probably trying
-to drag the globe.
-
-```js
-+const maxClickTimeMs = 200;
+to drag the globe.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">+const maxClickTimeMs = 200;
 +const maxMoveDeltaSq = 5 * 5;
 +const startPosition = {};
 +let startTimeMs;
@@ -610,7 +558,7 @@ function pickCountry(event) {
 +  // if it's been a moment since the user started
 +  // then assume it was a drag action, not a select action
 +  const clickTimeMs = performance.now() - startTimeMs;
-+  if (clickTimeMs > maxClickTimeMs) {
++  if (clickTimeMs &gt; maxClickTimeMs) {
 +    return;
 +  }
 +
@@ -618,16 +566,16 @@ function pickCountry(event) {
 +  const position = getCanvasRelativePosition(event);
 +  const moveDeltaSq = (startPosition.x - position.x) ** 2 +
 +                      (startPosition.y - position.y) ** 2;
-+  if (moveDeltaSq > maxMoveDeltaSq) {
++  if (moveDeltaSq &gt; maxMoveDeltaSq) {
 +    return;
 +  }
 
 -  const position = {x: event.clientX, y: event.clientY};
   const id = pickHelper.pick(position, pickingScene, camera);
-  if (id > 0) {
+  if (id &gt; 0) {
     const countryInfo = countryInfos[id - 1];
     const selected = !countryInfo.selected;
-    if (selected && !event.shiftKey && !event.ctrlKey && !event.metaKey) {
+    if (selected &amp;&amp; !event.shiftKey &amp;&amp; !event.ctrlKey &amp;&amp; !event.metaKey) {
       unselectAllCountries();
     }
     numCountriesSelected += selected ? 1 : -1;
@@ -642,7 +590,7 @@ function pickCountry(event) {
 
 function unselectAllCountries() {
   numCountriesSelected = 0;
-  countryInfos.forEach((countryInfo) => {
+  countryInfos.forEach((countryInfo) =&gt; {
     countryInfo.selected = false;
   });
   resetPalette();
@@ -650,17 +598,30 @@ function unselectAllCountries() {
 
 +canvas.addEventListener('pointerdown', recordStartTimeAndPosition);
 canvas.addEventListener('pointerup', pickCountry);
-```
+</pre>
+<p>and with those changes it <em>seems</em> like it works to me.</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/indexed-textures-picking-debounced.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/indexed-textures-picking-debounced.html" target="_blank">click here to open in a separate window</a>
+</div>
+
+<p></p>
+<p>I'm not a UX expert so I'd love to hear if there is a better
+solution.</p>
+<p>I hope that gave you some idea of how indexed graphics can be useful
+and how you can modify the shaders three.js makes to add simple features.
+How to use GLSL, the language the shaders are written in, is too much for
+this article. There are a few links to some info in
+<a href="post-processing.html">the article on post processing</a>.</p>
 
-and with those changes it *seems* like it works to me.
+        </div>
+      </div>
+    </div>
+  
+  <script src="/manual/resources/prettify.js"></script>
+  <script src="/manual/resources/lesson.js"></script>
 
-{{{example url="../threejs-indexed-textures-picking-debounced.html" }}}
 
-I'm not a UX expert so I'd love to hear if there is a better
-solution.
 
-I hope that gave you some idea of how indexed graphics can be useful
-and how you can modify the shaders three.js makes to add simple features.
-How to use GLSL, the language the shaders are written in, is too much for
-this article. There are a few links to some info in
-[the article on post processing](threejs-post-processing.html).
+
+</body></html>

+ 280 - 353
manual/en/lights.html

@@ -1,70 +1,72 @@
-Title: Three.js Lights
-Description: Setting up Lights
-TOC: Lights
-
-This article is part of a series of articles about three.js. The
-first article is [three.js fundamentals](threejs-fundamentals.html). If
+<!DOCTYPE html><html lang="en"><head>
+    <meta charset="utf-8">
+    <title>Lights</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 – Lights">
+    <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">
+  </head>
+  <body>
+    <div class="container">
+      <div class="lesson-title">
+        <h1>Lights</h1>
+      </div>
+      <div class="lesson">
+        <div class="lesson-main">
+          <p>This article is part of a series of articles about three.js. The
+first article is <a href="fundamentals.html">three.js fundamentals</a>. If
 you haven't read that yet and you're new to three.js you might want to
-consider starting there and also the article on [setting up your environment](threejs-setup.html). The
-[previous article was about textures](threejs-textures.html).
-
-Let's go over how to use the various kinds of lights in three.
-
-Starting with one of our previous samples let's update the camera.
+consider starting there and also the article on <a href="setup.html">setting up your environment</a>. The
+<a href="textures.html">previous article was about textures</a>.</p>
+<p>Let's go over how to use the various kinds of lights in three.</p>
+<p>Starting with one of our previous samples let's update the camera.
 We'll set the field of view to 45 degrees, the far plane to 100 units,
-and we'll move the camera 10 units up and 20 units back from the origin
-
-```js
-*const fov = 45;
+and we'll move the camera 10 units up and 20 units back from the origin</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">*const fov = 45;
 const aspect = 2;  // the canvas default
 const near = 0.1;
 *const far = 100;
 const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
 +camera.position.set(0, 10, 20);
-```
-
-Next let's add `OrbitControls`. `OrbitControls` let the user spin
-or *orbit* the camera around some point. The `OrbitControls` are
+</pre>
+<p>Next let's add <a href="/docs/#examples/controls/OrbitControls"><code class="notranslate" translate="no">OrbitControls</code></a>. <a href="/docs/#examples/controls/OrbitControls"><code class="notranslate" translate="no">OrbitControls</code></a> let the user spin
+or <em>orbit</em> the camera around some point. The <a href="/docs/#examples/controls/OrbitControls"><code class="notranslate" translate="no">OrbitControls</code></a> are
 an optional feature of three.js so first we need to include them
-in our page
-
-```js
-import * as THREE from './resources/three/r132/build/three.module.js';
-+import {OrbitControls} from './resources/threejs/r132/examples/jsm/controls/OrbitControls.js';
-```
-
-Then we can use them. We pass the `OrbitControls` a camera to
-control and the DOM element to use to get input events
-
-```js
-const controls = new OrbitControls(camera, canvas);
+in our page</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">import * as THREE from '/build/three.module.js';
++import {OrbitControls} from '/examples/jsm/controls/OrbitControls.js';
+</pre>
+<p>Then we can use them. We pass the <a href="/docs/#examples/controls/OrbitControls"><code class="notranslate" translate="no">OrbitControls</code></a> a camera to
+control and the DOM element to use to get input events</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const controls = new OrbitControls(camera, canvas);
 controls.target.set(0, 5, 0);
 controls.update();
-```
-
-We also set the target to orbit around to 5 units above the origin
-and then call `controls.update` so the controls will use the new
-target.
-
-Next up let's make some things to light up. First we'll make ground
+</pre>
+<p>We also set the target to orbit around to 5 units above the origin
+and then call <code class="notranslate" translate="no">controls.update</code> so the controls will use the new
+target.</p>
+<p>Next up let's make some things to light up. First we'll make ground
 plane. We'll apply a tiny 2x2 pixel checkerboard texture that looks
-like this
-
+like this</p>
 <div class="threejs_center">
-  <img src="../resources/images/checker.png" class="border" style="
+  <img src="../examples/resources/images/checker.png" class="border" style="
     image-rendering: pixelated;
     width: 128px;
   ">
 </div>
 
-First we load the texture, set it to repeating, set the filtering to
+<p>First we load the texture, set it to repeating, set the filtering to
 nearest, and set how many times we want it to repeat. Since the
 texture is a 2x2 pixel checkerboard, by repeating and setting the
 repeat to half the size of the plane each check on the checkerboard
-will be exactly 1 unit large;
-
-```js
-const planeSize = 40;
+will be exactly 1 unit large;</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const planeSize = 40;
 
 const loader = new THREE.TextureLoader();
 const texture = loader.load('resources/images/checker.png');
@@ -73,14 +75,11 @@ texture.wrapT = THREE.RepeatWrapping;
 texture.magFilter = THREE.NearestFilter;
 const repeats = planeSize / 2;
 texture.repeat.set(repeats, repeats);
-```
-
-We then make a plane geometry, a material for the plane, and a mesh
+</pre>
+<p>We then make a plane geometry, a material for the plane, and a mesh
 to insert it in the scene. Planes default to being in the XY plane
-but the ground is in the XZ plane so we rotate it.
-
-```js
-const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize);
+but the ground is in the XZ plane so we rotate it.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize);
 const planeMat = new THREE.MeshPhongMaterial({
   map: texture,
   side: THREE.DoubleSide,
@@ -88,12 +87,9 @@ const planeMat = new THREE.MeshPhongMaterial({
 const mesh = new THREE.Mesh(planeGeo, planeMat);
 mesh.rotation.x = Math.PI * -.5;
 scene.add(mesh);
-```
-
-Let's add a cube and a sphere so we have 3 things to light including the plane
-
-```js
-{
+</pre>
+<p>Let's add a cube and a sphere so we have 3 things to light including the plane</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
   const cubeSize = 4;
   const cubeGeo = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize);
   const cubeMat = new THREE.MeshPhongMaterial({color: '#8AC'});
@@ -111,34 +107,25 @@ Let's add a cube and a sphere so we have 3 things to light including the plane
   mesh.position.set(-sphereRadius - 1, sphereRadius + 2, 0);
   scene.add(mesh);
 }
-```
-
-Now that we have a scene to light up let's add lights!
-
-## `AmbientLight`
-
-First let's make an `AmbientLight`
-
-```js
-const color = 0xFFFFFF;
+</pre>
+<p>Now that we have a scene to light up let's add lights!</p>
+<h2 id="-ambientlight-"><a href="/docs/#api/en/lights/AmbientLight"><code class="notranslate" translate="no">AmbientLight</code></a></h2>
+<p>First let's make an <a href="/docs/#api/en/lights/AmbientLight"><code class="notranslate" translate="no">AmbientLight</code></a></p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const color = 0xFFFFFF;
 const intensity = 1;
 const light = new THREE.AmbientLight(color, intensity);
 scene.add(light);
-```
-
-Let's also make it so we can adjust the light's parameters.
-We'll use [dat.GUI](https://github.com/dataarts/dat.gui) again.
-To be able to adjust the color via dat.GUI we need a small helper
-that presents a property to dat.GUI that looks like a CSS hex color string
-(eg: `#FF8844`). Our helper will get the color from a named property,
-convert it to a hex string to offer to dat.GUI. When dat.GUI tries
+</pre>
+<p>Let's also make it so we can adjust the light's parameters.
+We'll use <a href="https://github.com/georgealways/lil-gui">lil-gui</a> again.
+To be able to adjust the color via lil-gui we need a small helper
+that presents a property to lil-gui that looks like a CSS hex color string
+(eg: <code class="notranslate" translate="no">#FF8844</code>). Our helper will get the color from a named property,
+convert it to a hex string to offer to lil-gui. When lil-gui tries
 to set the helper's property we'll assign the result back to the light's
-color.
-
-Here's the helper:
-
-```js
-class ColorGUIHelper {
+color.</p>
+<p>Here's the helper:</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">class ColorGUIHelper {
   constructor(object, prop) {
     this.object = object;
     this.prop = prop;
@@ -150,144 +137,120 @@ class ColorGUIHelper {
     this.object[this.prop].set(hexString);
   }
 }
-```
-
-And here's our code setting up dat.GUI
-
-```js
-const gui = new GUI();
+</pre>
+<p>And here's our code setting up lil-gui</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const gui = new GUI();
 gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('color');
 gui.add(light, 'intensity', 0, 2, 0.01);
-```
-
-And here's the result
-
-{{{example url="../threejs-lights-ambient.html" }}}
-
-Click and drag in the scene to *orbit* the camera.
+</pre>
+<p>And here's the result</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/lights-ambient.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/lights-ambient.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-Notice there is no definition. The shapes are flat. The `AmbientLight` effectively
+<p></p>
+<p>Click and drag in the scene to <em>orbit</em> the camera.</p>
+<p>Notice there is no definition. The shapes are flat. The <a href="/docs/#api/en/lights/AmbientLight"><code class="notranslate" translate="no">AmbientLight</code></a> effectively
 just multiplies the material's color by the light's color times the
-intensity.
-
-    color = materialColor * light.color * light.intensity;
-
-That's it. It has no direction.
+intensity.</p>
+<pre class="prettyprint showlinemods notranslate notranslate" translate="no">color = materialColor * light.color * light.intensity;
+</pre><p>That's it. It has no direction.
 This style of ambient lighting is actually not all that
 useful as lighting as it's 100% even so other than changing the color
-of everything in the scene it doesn't look much like *lighting*.
-What it does help with is making the darks not too dark.
-
-## `HemisphereLight`
-
-Let's switch the code to a `HemisphereLight`. A `HemisphereLight`
+of everything in the scene it doesn't look much like <em>lighting</em>.
+What it does help with is making the darks not too dark.</p>
+<h2 id="-hemispherelight-"><a href="/docs/#api/en/lights/HemisphereLight"><code class="notranslate" translate="no">HemisphereLight</code></a></h2>
+<p>Let's switch the code to a <a href="/docs/#api/en/lights/HemisphereLight"><code class="notranslate" translate="no">HemisphereLight</code></a>. A <a href="/docs/#api/en/lights/HemisphereLight"><code class="notranslate" translate="no">HemisphereLight</code></a>
 takes a sky color and a ground color and just multiplies the
 material's color between those 2 colors—the sky color if the
 surface of the object is pointing up and the ground color if
-the surface of the object is pointing down.
-
-Here's the new code
-
-```js
--const color = 0xFFFFFF;
+the surface of the object is pointing down.</p>
+<p>Here's the new code</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">-const color = 0xFFFFFF;
 +const skyColor = 0xB1E1FF;  // light blue
 +const groundColor = 0xB97A20;  // brownish orange
 const intensity = 1;
 -const light = new THREE.AmbientLight(color, intensity);
 +const light = new THREE.HemisphereLight(skyColor, groundColor, intensity);
 scene.add(light);
-```
-
-Let's also update the dat.GUI code to edit both colors
-
-```js
-const gui = new GUI();
+</pre>
+<p>Let's also update the lil-gui code to edit both colors</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const gui = new GUI();
 -gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('color');
 +gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('skyColor');
 +gui.addColor(new ColorGUIHelper(light, 'groundColor'), 'value').name('groundColor');
 gui.add(light, 'intensity', 0, 2, 0.01);
-```
-
-The result:
-
-{{{example url="../threejs-lights-hemisphere.html" }}}
+</pre>
+<p>The result:</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/lights-hemisphere.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/lights-hemisphere.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-Notice again there is almost no definition, everything looks kind
-of flat. The `HemisphereLight` used in combination with another light
+<p></p>
+<p>Notice again there is almost no definition, everything looks kind
+of flat. The <a href="/docs/#api/en/lights/HemisphereLight"><code class="notranslate" translate="no">HemisphereLight</code></a> used in combination with another light
 can help give a nice kind of influence of the color of the sky
 and ground. In that way it's best used in combination with some
-other light or a substitute for an `AmbientLight`.
-
-## `DirectionalLight`
-
-Let's switch the code to a `DirectionalLight`.
-A `DirectionalLight` is often used to represent the sun.
-
-```js
-const color = 0xFFFFFF;
+other light or a substitute for an <a href="/docs/#api/en/lights/AmbientLight"><code class="notranslate" translate="no">AmbientLight</code></a>.</p>
+<h2 id="-directionallight-"><a href="/docs/#api/en/lights/DirectionalLight"><code class="notranslate" translate="no">DirectionalLight</code></a></h2>
+<p>Let's switch the code to a <a href="/docs/#api/en/lights/DirectionalLight"><code class="notranslate" translate="no">DirectionalLight</code></a>.
+A <a href="/docs/#api/en/lights/DirectionalLight"><code class="notranslate" translate="no">DirectionalLight</code></a> is often used to represent the sun.</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(0, 10, 0);
 light.target.position.set(-5, 0, 0);
 scene.add(light);
 scene.add(light.target);
-```
-
-Notice that we had to add the `light` and the `light.target`
-to the scene. A three.js `DirectionalLight` will shine
-in the direction of its target.
-
-Let's make it so we can move the target by adding it to
-our GUI.
-
-```js
-const gui = new GUI();
+</pre>
+<p>Notice that we had to add the <code class="notranslate" translate="no">light</code> and the <code class="notranslate" translate="no">light.target</code>
+to the scene. A three.js <a href="/docs/#api/en/lights/DirectionalLight"><code class="notranslate" translate="no">DirectionalLight</code></a> will shine
+in the direction of its target.</p>
+<p>Let's make it so we can move the target by adding it to
+our GUI.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const gui = new GUI();
 gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('color');
 gui.add(light, 'intensity', 0, 2, 0.01);
 gui.add(light.target.position, 'x', -10, 10);
 gui.add(light.target.position, 'z', -10, 10);
 gui.add(light.target.position, 'y', 0, 10);
-```
-
-{{{example url="../threejs-lights-directional.html" }}}
+</pre>
+<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/lights-directional.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/lights-directional.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-It's kind of hard to see what's going on. Three.js has a bunch
+<p></p>
+<p>It's kind of hard to see what's going on. Three.js has a bunch
 of helper objects we can add to our scene to help visualize
 invisible parts of a scene. In this case we'll use the
-`DirectionalLightHelper` which will draw a plane, to represent
+<a href="/docs/#api/en/helpers/DirectionalLightHelper"><code class="notranslate" translate="no">DirectionalLightHelper</code></a> which will draw a plane, to represent
 the light, and a line from the light to the target. We just
-pass it the light and add it to the scene.
-
-```js
-const helper = new THREE.DirectionalLightHelper(light);
+pass it the light and add it to the scene.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const helper = new THREE.DirectionalLightHelper(light);
 scene.add(helper);
-```
-
-While we're at it let's make it so we can set both the position
+</pre>
+<p>While we're at it let's make it so we can set both the position
 of the light and the target. To do this we'll make a function
-that given a `Vector3` will adjust its `x`, `y`, and `z` properties
-using `dat.GUI`.
-
-```js
-function makeXYZGUI(gui, vector3, name, onChangeFn) {
+that given a <a href="/docs/#api/en/math/Vector3"><code class="notranslate" translate="no">Vector3</code></a> will adjust its <code class="notranslate" translate="no">x</code>, <code class="notranslate" translate="no">y</code>, and <code class="notranslate" translate="no">z</code> properties
+using <code class="notranslate" translate="no">lil-gui</code>.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function makeXYZGUI(gui, vector3, name, onChangeFn) {
   const folder = gui.addFolder(name);
   folder.add(vector3, 'x', -10, 10).onChange(onChangeFn);
   folder.add(vector3, 'y', 0, 10).onChange(onChangeFn);
   folder.add(vector3, 'z', -10, 10).onChange(onChangeFn);
   folder.open();
 }
-```
-
-Note that we need to call the helper's `update` function
+</pre>
+<p>Note that we need to call the helper's <code class="notranslate" translate="no">update</code> function
 anytime we change something so the helper knows to update
-itself. As such we pass in an `onChangeFn` function to
-get called anytime dat.GUI updates a value.
-
-Then we can use that for both the light's position
-and the target's position like this
-
-```js
-+function updateLight() {
+itself. As such we pass in an <code class="notranslate" translate="no">onChangeFn</code> function to
+get called anytime lil-gui updates a value.</p>
+<p>Then we can use that for both the light's position
+and the target's position like this</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">+function updateLight() {
 +  light.target.updateMatrixWorld();
 +  helper.update();
 +}
@@ -299,25 +262,23 @@ gui.add(light, 'intensity', 0, 2, 0.01);
 
 +makeXYZGUI(gui, light.position, 'position', updateLight);
 +makeXYZGUI(gui, light.target.position, 'target', updateLight);
-```
-
-Now we can move the light, and its target
-
-{{{example url="../threejs-lights-directional-w-helper.html" }}}
+</pre>
+<p>Now we can move the light, and its target</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/lights-directional-w-helper.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/lights-directional-w-helper.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-Orbit the camera and it gets easier to see. The plane
-represents a `DirectionalLight` because a directional
+<p></p>
+<p>Orbit the camera and it gets easier to see. The plane
+represents a <a href="/docs/#api/en/lights/DirectionalLight"><code class="notranslate" translate="no">DirectionalLight</code></a> because a directional
 light computes light coming in one direction. There is no
-*point* the light comes from, it's an infinite plane of light
-shooting out parallel rays of light.
-
-## `PointLight`
-
-A `PointLight` is a light that sits at a point and shoots light
-in all directions from that point. Let's change the code.
-
-```js
-const color = 0xFFFFFF;
+<em>point</em> the light comes from, it's an infinite plane of light
+shooting out parallel rays of light.</p>
+<h2 id="-pointlight-"><a href="/docs/#api/en/lights/PointLight"><code class="notranslate" translate="no">PointLight</code></a></h2>
+<p>A <a href="/docs/#api/en/lights/PointLight"><code class="notranslate" translate="no">PointLight</code></a> is a light that sits at a point and shoots light
+in all directions from that point. Let's change the code.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const color = 0xFFFFFF;
 const intensity = 1;
 -const light = new THREE.DirectionalLight(color, intensity);
 +const light = new THREE.PointLight(color, intensity);
@@ -325,70 +286,55 @@ light.position.set(0, 10, 0);
 -light.target.position.set(-5, 0, 0);
 scene.add(light);
 -scene.add(light.target);
-```
-
-Let's also switch to a `PointLightHelper`
-
-```js
--const helper = new THREE.DirectionalLightHelper(light);
+</pre>
+<p>Let's also switch to a <a href="/docs/#api/en/helpers/PointLightHelper"><code class="notranslate" translate="no">PointLightHelper</code></a></p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">-const helper = new THREE.DirectionalLightHelper(light);
 +const helper = new THREE.PointLightHelper(light);
 scene.add(helper);
-```
-
-and as there is no target the `onChange` function can be simpler.
-
-```js
-function updateLight() {
+</pre>
+<p>and as there is no target the <code class="notranslate" translate="no">onChange</code> function can be simpler.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function updateLight() {
 -  light.target.updateMatrixWorld();
   helper.update();
 }
 -updateLight();
-```
-
-Note that at some level a `PointLightHelper` has no um, point.
+</pre>
+<p>Note that at some level a <a href="/docs/#api/en/helpers/PointLightHelper"><code class="notranslate" translate="no">PointLightHelper</code></a> has no um, point.
 It just draws a small wireframe diamond. It could just as easily
-be any shape you want, just add a mesh to the light itself.
-
-A `PointLight` has the added property of [`distance`](PointLight.distance).
-If the `distance` is 0 then the `PointLight` shines to
-infinity. If the `distance` is greater than 0 then the light shines
-its full intensity at the light and fades to no influence at `distance`
-units away from the light.
-
-Let's setup the GUI so we can adjust the distance.
-
-```js
-const gui = new GUI();
+be any shape you want, just add a mesh to the light itself.</p>
+<p>A <a href="/docs/#api/en/lights/PointLight"><code class="notranslate" translate="no">PointLight</code></a> has the added property of <a href="/docs/#api/en/lights/PointLight#distance"><code class="notranslate" translate="no">distance</code></a>.
+If the <code class="notranslate" translate="no">distance</code> is 0 then the <a href="/docs/#api/en/lights/PointLight"><code class="notranslate" translate="no">PointLight</code></a> shines to
+infinity. If the <code class="notranslate" translate="no">distance</code> is greater than 0 then the light shines
+its full intensity at the light and fades to no influence at <code class="notranslate" translate="no">distance</code>
+units away from the light.</p>
+<p>Let's setup the GUI so we can adjust the distance.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const gui = new GUI();
 gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('color');
 gui.add(light, 'intensity', 0, 2, 0.01);
 +gui.add(light, 'distance', 0, 40).onChange(updateLight);
 
 makeXYZGUI(gui, light.position, 'position', updateLight);
 -makeXYZGUI(gui, light.target.position, 'target', updateLight);
-```
-
-And now try it out.
-
-{{{example url="../threejs-lights-point.html" }}}
-
-Notice when `distance` is > 0 how the light fades out.
-
-## `SpotLight`
+</pre>
+<p>And now try it out.</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/lights-point.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/lights-point.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-Spotlights are effectively a point light with a cone
+<p></p>
+<p>Notice when <code class="notranslate" translate="no">distance</code> is &gt; 0 how the light fades out.</p>
+<h2 id="-spotlight-"><a href="/docs/#api/en/lights/SpotLight"><code class="notranslate" translate="no">SpotLight</code></a></h2>
+<p>Spotlights are effectively a point light with a cone
 attached where the light only shines inside the cone.
 There's actually 2 cones. An outer cone and an inner
 cone. Between the inner cone and the outer cone the
-light fades from full intensity to zero.
-
-To use a `SpotLight` we need a target just like
+light fades from full intensity to zero.</p>
+<p>To use a <a href="/docs/#api/en/lights/SpotLight"><code class="notranslate" translate="no">SpotLight</code></a> we need a target just like
 the directional light. The light's cone will
-open toward the target.
-
-Modifying our `DirectionalLight` with helper from above
-
-```js
-const color = 0xFFFFFF;
+open toward the target.</p>
+<p>Modifying our <a href="/docs/#api/en/lights/DirectionalLight"><code class="notranslate" translate="no">DirectionalLight</code></a> with helper from above</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const color = 0xFFFFFF;
 const intensity = 1;
 -const light = new THREE.DirectionalLight(color, intensity);
 +const light = new THREE.SpotLight(color, intensity);
@@ -398,48 +344,39 @@ scene.add(light.target);
 -const helper = new THREE.DirectionalLightHelper(light);
 +const helper = new THREE.SpotLightHelper(light);
 scene.add(helper);
-```
-
-The spotlight's cone's angle is set with the [`angle`](SpotLight.angle)
-property in radians. We'll use our `DegRadHelper` from the
-[texture article](threejs-textures.html) to present a UI in
-degrees.
-
-```js
-gui.add(new DegRadHelper(light, 'angle'), 'value', 0, 90).name('angle').onChange(updateLight);
-```
-
-The inner cone is defined by setting the [`penumbra`](SpotLight.penumbra) property
-as a percentage from the outer cone. In other words when `penumbra` is 0 then the
+</pre>
+<p>The spotlight's cone's angle is set with the <a href="/docs/#api/en/lights/SpotLight#angle"><code class="notranslate" translate="no">angle</code></a>
+property in radians. We'll use our <code class="notranslate" translate="no">DegRadHelper</code> from the
+<a href="textures.html">texture article</a> to present a UI in
+degrees.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">gui.add(new DegRadHelper(light, 'angle'), 'value', 0, 90).name('angle').onChange(updateLight);
+</pre>
+<p>The inner cone is defined by setting the <a href="/docs/#api/en/lights/SpotLight#penumbra"><code class="notranslate" translate="no">penumbra</code></a> property
+as a percentage from the outer cone. In other words when <code class="notranslate" translate="no">penumbra</code> is 0 then the
 inner cone is the same size (0 = no difference) from the outer cone. When the
-`penumbra` is 1 then the light fades starting in the center of the cone to the
-outer cone. When `penumbra` is .5 then the light fades starting from 50% between
-the center of the outer cone.
-
-```js
-gui.add(light, 'penumbra', 0, 1, 0.01);
-```
-
-{{{example url="../threejs-lights-spot-w-helper.html" }}}
-
-Notice with the default `penumbra` of 0 the spotlight has a very sharp edge
-whereas as you adjust the `penumbra` toward 1 the edge blurs.
+<code class="notranslate" translate="no">penumbra</code> is 1 then the light fades starting in the center of the cone to the
+outer cone. When <code class="notranslate" translate="no">penumbra</code> is .5 then the light fades starting from 50% between
+the center of the outer cone.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">gui.add(light, 'penumbra', 0, 1, 0.01);
+</pre>
+<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/lights-spot-w-helper.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/lights-spot-w-helper.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-It might be hard to see the *cone* of the spotlight. The reason is it's
+<p></p>
+<p>Notice with the default <code class="notranslate" translate="no">penumbra</code> of 0 the spotlight has a very sharp edge
+whereas as you adjust the <code class="notranslate" translate="no">penumbra</code> toward 1 the edge blurs.</p>
+<p>It might be hard to see the <em>cone</em> of the spotlight. The reason is it's
 below the ground. Shorten the distance to around 5 and you'll see the open
-end of the cone.
-
-## `RectAreaLight`
-
-There's one more type of light, the `RectAreaLight`, which represents
+end of the cone.</p>
+<h2 id="-rectarealight-"><a href="/docs/#api/en/lights/RectAreaLight"><code class="notranslate" translate="no">RectAreaLight</code></a></h2>
+<p>There's one more type of light, the <a href="/docs/#api/en/lights/RectAreaLight"><code class="notranslate" translate="no">RectAreaLight</code></a>, which represents
 exactly what it sounds like, a rectangular area of light like a long
-fluorescent light or maybe a frosted sky light in a ceiling.
-
-The `RectAreaLight` only works with the `MeshStandardMaterial` and the
-`MeshPhysicalMaterial` so let's change all our materials to `MeshStandardMaterial`
-
-```js
-  ...
+fluorescent light or maybe a frosted sky light in a ceiling.</p>
+<p>The <a href="/docs/#api/en/lights/RectAreaLight"><code class="notranslate" translate="no">RectAreaLight</code></a> only works with the <a href="/docs/#api/en/materials/MeshStandardMaterial"><code class="notranslate" translate="no">MeshStandardMaterial</code></a> and the
+<a href="/docs/#api/en/materials/MeshPhysicalMaterial"><code class="notranslate" translate="no">MeshPhysicalMaterial</code></a> so let's change all our materials to <a href="/docs/#api/en/materials/MeshStandardMaterial"><code class="notranslate" translate="no">MeshStandardMaterial</code></a></p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">  ...
 
   const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize);
 -  const planeMat = new THREE.MeshPhongMaterial({
@@ -471,33 +408,23 @@ The `RectAreaLight` only works with the `MeshStandardMaterial` and the
   mesh.position.set(-sphereRadius - 1, sphereRadius + 2, 0);
   scene.add(mesh);
 }
-```
-
-To use the `RectAreaLight` we need to include some extra three.js optional data and we'll
-include the `RectAreaLightHelper` to help us visualize the light
-
-```js
-import * as THREE from './resources/three/r132/build/three.module.js';
-+import {RectAreaLightUniformsLib} from './resources/threejs/r132/examples/jsm/lights/RectAreaLightUniformsLib.js';
-+import {RectAreaLightHelper} from './resources/threejs/r132/examples/jsm/helpers/RectAreaLightHelper.js';
-```
-
-and we need to call `RectAreaLightUniformsLib.init`
-
-```js
-function main() {
+</pre>
+<p>To use the <a href="/docs/#api/en/lights/RectAreaLight"><code class="notranslate" translate="no">RectAreaLight</code></a> we need to include some extra three.js optional data and we'll
+include the <a href="/docs/#api/en/helpers/RectAreaLightHelper"><code class="notranslate" translate="no">RectAreaLightHelper</code></a> to help us visualize the light</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">import * as THREE from '/build/three.module.js';
++import {RectAreaLightUniformsLib} from '/examples/jsm/lights/RectAreaLightUniformsLib.js';
++import {RectAreaLightHelper} from '/examples/jsm/helpers/RectAreaLightHelper.js';
+</pre>
+<p>and we need to call <code class="notranslate" translate="no">RectAreaLightUniformsLib.init</code></p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function main() {
   const canvas = document.querySelector('#c');
   const renderer = new THREE.WebGLRenderer({canvas});
 +  RectAreaLightUniformsLib.init();
-```
-
-If you forget the data the light will still work but it will look funny so
-be sure to remember to include the extra data.
-
-Now we can create the light
-
-```js
-const color = 0xFFFFFF;
+</pre>
+<p>If you forget the data the light will still work but it will look funny so
+be sure to remember to include the extra data.</p>
+<p>Now we can create the light</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const color = 0xFFFFFF;
 *const intensity = 5;
 +const width = 12;
 +const height = 4;
@@ -508,18 +435,14 @@ scene.add(light);
 
 *const helper = new RectAreaLightHelper(light);
 *light.add(helper);
-```
-
-One thing to notice is that unlike the `DirectionalLight` and the `SpotLight`, the
-`RectAreaLight` does not use a target. It just uses its rotation. Another thing
+</pre>
+<p>One thing to notice is that unlike the <a href="/docs/#api/en/lights/DirectionalLight"><code class="notranslate" translate="no">DirectionalLight</code></a> and the <a href="/docs/#api/en/lights/SpotLight"><code class="notranslate" translate="no">SpotLight</code></a>, the
+<a href="/docs/#api/en/lights/RectAreaLight"><code class="notranslate" translate="no">RectAreaLight</code></a> does not use a target. It just uses its rotation. Another thing
 to notice is the helper needs to be a child of the light. It is not a child of the
-scene like other helpers.
-
-Let's also adjust the GUI. We'll make it so we can rotate the light and adjust
-its `width` and `height`
-
-```js
-const gui = new GUI();
+scene like other helpers.</p>
+<p>Let's also adjust the GUI. We'll make it so we can rotate the light and adjust
+its <code class="notranslate" translate="no">width</code> and <code class="notranslate" translate="no">height</code></p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const gui = new GUI();
 gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('color');
 gui.add(light, 'intensity', 0, 10, 0.01);
 gui.add(light, 'width', 0, 20);
@@ -529,60 +452,64 @@ gui.add(new DegRadHelper(light.rotation, 'y'), 'value', -180, 180).name('y rotat
 gui.add(new DegRadHelper(light.rotation, 'z'), 'value', -180, 180).name('z rotation');
 
 makeXYZGUI(gui, light.position, 'position');
-```
-
-And here is that.
-
-{{{example url="../threejs-lights-rectarea.html" }}}
-
-One thing we didn't cover is that there is a setting on the `WebGLRenderer`
-called `physicallyCorrectLights`. It effects how light falls off as distance from light.
-It only affects `PointLight` and `SpotLight`. `RectAreaLight` does this automatically.
+</pre>
+<p>And here is that.</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/lights-rectarea.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/lights-rectarea.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-For lights though the basic idea is you don't set a distance for them to fade out,
-and you don't set `intensity`. Instead you set the [`power`](PointLight.power) of
+<p></p>
+<p>One thing we didn't cover is that there is a setting on the <a href="/docs/#api/en/renderers/WebGLRenderer"><code class="notranslate" translate="no">WebGLRenderer</code></a>
+called <code class="notranslate" translate="no">physicallyCorrectLights</code>. It effects how light falls off as distance from light.
+It only affects <a href="/docs/#api/en/lights/PointLight"><code class="notranslate" translate="no">PointLight</code></a> and <a href="/docs/#api/en/lights/SpotLight"><code class="notranslate" translate="no">SpotLight</code></a>. <a href="/docs/#api/en/lights/RectAreaLight"><code class="notranslate" translate="no">RectAreaLight</code></a> does this automatically.</p>
+<p>For lights though the basic idea is you don't set a distance for them to fade out,
+and you don't set <code class="notranslate" translate="no">intensity</code>. Instead you set the <a href="/docs/#api/en/lights/PointLight#power"><code class="notranslate" translate="no">power</code></a> of
 the light in lumens and then three.js will use physics calculations like real lights.
 The units of three.js in this case are meters and a 60w light bulb would have
-around 800 lumens. There's also a [`decay`](PointLight.decay) property. It should
-be set to `2` for realistic decay.
-
-Let's test that.
-
-First we'll turn on physically correct lights
-
-```js
-const renderer = new THREE.WebGLRenderer({canvas});
+around 800 lumens. There's also a <a href="/docs/#api/en/lights/PointLight#decay"><code class="notranslate" translate="no">decay</code></a> property. It should
+be set to <code class="notranslate" translate="no">2</code> for realistic decay.</p>
+<p>Let's test that.</p>
+<p>First we'll turn on physically correct lights</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const renderer = new THREE.WebGLRenderer({canvas});
 +renderer.physicallyCorrectLights = true;
-```
-
-Then we'll set the `power` to 800 lumens, the `decay` to 2, and
-the `distance` to `Infinity`.
-
-```js
-const color = 0xFFFFFF;
+</pre>
+<p>Then we'll set the <code class="notranslate" translate="no">power</code> to 800 lumens, the <code class="notranslate" translate="no">decay</code> to 2, and
+the <code class="notranslate" translate="no">distance</code> to <code class="notranslate" translate="no">Infinity</code>.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const color = 0xFFFFFF;
 const intensity = 1;
 const light = new THREE.PointLight(color, intensity);
 light.power = 800;
 light.decay = 2;
 light.distance = Infinity;
-```
-
-and we'll add gui so we can change the `power` and `decay`
-
-```js
-const gui = new GUI();
+</pre>
+<p>and we'll add gui so we can change the <code class="notranslate" translate="no">power</code> and <code class="notranslate" translate="no">decay</code></p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const gui = new GUI();
 gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('color');
 gui.add(light, 'decay', 0, 4, 0.01);
 gui.add(light, 'power', 0, 2000);
-```
-
-{{{example url="../threejs-lights-point-physically-correct.html" }}}
+</pre>
+<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/lights-point-physically-correct.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/lights-point-physically-correct.html" target="_blank">click here to open in a separate window</a>
+</div>
 
-It's important to note each light you add to the scene slows down how fast
+<p></p>
+<p>It's important to note each light you add to the scene slows down how fast
 three.js renders the scene so you should always try to use as few as
-possible to achieve your goals.
+possible to achieve your goals.</p>
+<p>Next up let's go over <a href="cameras.html">dealing with cameras</a>.</p>
+<p><canvas id="c"></canvas></p>
+<script type="module" src="../resources/threejs-lights.js"></script>
+
+        </div>
+      </div>
+    </div>
+  
+  <script src="/manual/resources/prettify.js"></script>
+  <script src="/manual/resources/lesson.js"></script>
+
+
 
-Next up let's go over [dealing with cameras](threejs-cameras.html).
 
-<canvas id="c"></canvas>
-<script type="module" src="resources/threejs-lights.js"></script>
+</body></html>

+ 288 - 358
manual/en/load-gltf.html

@@ -1,157 +1,146 @@
-Title: Three.js Loading a .GLTF File
-Description: Loading a .GLTF File
-TOC: Load a .GLTF file
-
-In a previous lesson we [loaded an .OBJ file](threejs-load-obj.html). If
-you haven't read it you might want to check it out first.
-
-As pointed out over there the .OBJ file format is very old and fairly
+<!DOCTYPE html><html lang="en"><head>
+    <meta charset="utf-8">
+    <title>Loading a .GLTF File</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 – Loading a .GLTF File">
+    <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">
+  </head>
+  <body>
+    <div class="container">
+      <div class="lesson-title">
+        <h1>Loading a .GLTF File</h1>
+      </div>
+      <div class="lesson">
+        <div class="lesson-main">
+          <p>In a previous lesson we <a href="load-obj.html">loaded an .OBJ file</a>. If
+you haven't read it you might want to check it out first.</p>
+<p>As pointed out over there the .OBJ file format is very old and fairly
 simple. It provides no scene graph so everything loaded is one large
 mesh. It was designed mostly as a simple way to pass data between
-3D editors.
-
-[The gLTF format](https://github.com/KhronosGroup/glTF) is actually
+3D editors.</p>
+<p><a href="https://github.com/KhronosGroup/glTF">The gLTF format</a> is actually
 a format designed from the ground up for be used for displaying
-graphics. 3D formats can be divided into 3 or 4 basic types.
-
-* 3D Editor Formats
-
-  This are formats specific to a single app. .blend (Blender), .max (3d Studio Max),
-  .mb and .ma (Maya), etc...
-
-* Exchange formats
-
-  These are formats like .OBJ, .DAE (Collada), .FBX. They are designed to help exchange
-  information between 3D editors. As such they are usually much larger than needed with
-  extra info used only inside 3d editors
-
-* App formats
-
-  These are usually specific to certain apps, usually games.
-
-* Transmission formats
-
-  gLTF might be the first true transmission format. I suppose VRML might be considered
-  one but VRML was actually a pretty poor format.
-
-  gLTF is designed to do some things well that all those other formats don't do
-
-  1. Be small for transmission
-
-     For example this means much of their large data, like vertices, is stored in
-     binary. When you download a .gLTF file that data can be uploaded to the GPU
-     with zero processing. It's ready as is. This is in contrast to say VRML, .OBJ,
-     or .DAE where vertices are stored as text and have to be parsed. Text vertex
-     positions can easily be 3x to 5x larger than binary.
-
-  2. Be ready to render
-
-     This again is different from other formats except maybe App formats. The data
-     in a glTF file is mean to be rendered, not edited. Data that's not important to
-     rendering has generally been removed. Polygons have been converted to triangles.
-     Materials have known values that are supposed to work everywhere.
-
-gLTF was specifically designed so you should be able to download a glTF file and
+graphics. 3D formats can be divided into 3 or 4 basic types.</p>
+<ul>
+<li><p>3D Editor Formats</p>
+<p>This are formats specific to a single app. .blend (Blender), .max (3d Studio Max),
+.mb and .ma (Maya), etc...</p>
+</li>
+<li><p>Exchange formats</p>
+<p>These are formats like .OBJ, .DAE (Collada), .FBX. They are designed to help exchange
+information between 3D editors. As such they are usually much larger than needed with
+extra info used only inside 3d editors</p>
+</li>
+<li><p>App formats</p>
+<p>These are usually specific to certain apps, usually games.</p>
+</li>
+<li><p>Transmission formats</p>
+<p>gLTF might be the first true transmission format. I suppose VRML might be considered
+one but VRML was actually a pretty poor format.</p>
+<p>gLTF is designed to do some things well that all those other formats don't do</p>
+<ol>
+<li><p>Be small for transmission</p>
+<p>For example this means much of their large data, like vertices, is stored in
+binary. When you download a .gLTF file that data can be uploaded to the GPU
+with zero processing. It's ready as is. This is in contrast to say VRML, .OBJ,
+or .DAE where vertices are stored as text and have to be parsed. Text vertex
+positions can easily be 3x to 5x larger than binary.</p>
+</li>
+<li><p>Be ready to render</p>
+<p>This again is different from other formats except maybe App formats. The data
+in a glTF file is mean to be rendered, not edited. Data that's not important to
+rendering has generally been removed. Polygons have been converted to triangles.
+Materials have known values that are supposed to work everywhere.</p>
+</li>
+</ol>
+</li>
+</ul>
+<p>gLTF was specifically designed so you should be able to download a glTF file and
 display it with a minimum of trouble. Let's cross our fingers that's truly the case
-as none of the other formats have been able to do this.
-
-I wasn't really sure what I should show. At some level loading and displaying a gLTF file
+as none of the other formats have been able to do this.</p>
+<p>I wasn't really sure what I should show. At some level loading and displaying a gLTF file
 is simpler than an .OBJ file. Unlike a .OBJ file materials are directly part of the format.
 That said I thought I should at least load one up and I think going over the issues I ran 
-into might provide some good info.
-
-Searching the net I found [this low-poly city](https://sketchfab.com/models/edd1c604e1e045a0a2a552ddd9a293e6)
-by [antonmoek](https://sketchfab.com/antonmoek) which seemed like if we're lucky
-might make a good example.
-
-<div class="threejs_center"><img src="resources/images/cartoon_lowpoly_small_city_free_pack.jpg"></div>
-
-Starting with [an example from the .OBJ article](threejs-load-obj.html) I removed the code
-for loading .OBJ and replaced it with code for loading .GLTF
-
-The old .OBJ code was
-
-```js
-const mtlLoader = new MTLLoader();
-mtlLoader.loadMtl('resources/models/windmill/windmill-fixed.mtl', (mtl) => {
+into might provide some good info.</p>
+<p>Searching the net I found <a href="https://sketchfab.com/models/edd1c604e1e045a0a2a552ddd9a293e6">this low-poly city</a>
+by <a href="https://sketchfab.com/antonmoek">antonmoek</a> which seemed like if we're lucky
+might make a good example.</p>
+<div class="threejs_center"><img src="../resources/images/cartoon_lowpoly_small_city_free_pack.jpg"></div>
+
+<p>Starting with <a href="load-obj.html">an example from the .OBJ article</a> I removed the code
+for loading .OBJ and replaced it with code for loading .GLTF</p>
+<p>The old .OBJ code was</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const mtlLoader = new MTLLoader();
+mtlLoader.loadMtl('resources/models/windmill/windmill-fixed.mtl', (mtl) =&gt; {
   mtl.preload();
   mtl.materials.Material.side = THREE.DoubleSide;
   objLoader.setMaterials(mtl);
-  objLoader.load('resources/models/windmill/windmill.obj', (event) => {
+  objLoader.load('resources/models/windmill/windmill.obj', (event) =&gt; {
     const root = event.detail.loaderRootNode;
     scene.add(root);
     ...
   });
 });
-```
-
-The new .GLTF code is
-
-```js
-{
+</pre>
+<p>The new .GLTF code is</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
   const gltfLoader = new GLTFLoader();
   const url = 'resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf';
-  gltfLoader.load(url, (gltf) => {
+  gltfLoader.load(url, (gltf) =&gt; {
     const root = gltf.scene;
     scene.add(root);
     ...
   });
-```
-
-I kept the auto framing code as before
-
-We also need to include the `GLTFLoader` and we can get rid of the `OBJLoader`.
-
-```html
--import {LoaderSupport} from './resources/threejs/r132/examples/jsm/loaders/LoaderSupport.js';
--import {OBJLoader} from './resources/threejs/r132/examples/jsm/loaders/OBJLoader.js';
--import {MTLLoader} from './resources/threejs/r132/examples/jsm/loaders/MTLLoader.js';
-+import {GLTFLoader} from './resources/threejs/r132/examples/jsm/loaders/GLTFLoader.js';
-```
-
-And running that we get
-
-{{{example url="../threejs-load-gltf.html" }}}
-
-Magic! It just works, textures and all.
-
-Next I wanted to see if I could animate the cars driving around so
+</pre>
+<p>I kept the auto framing code as before</p>
+<p>We also need to include the <a href="/docs/#examples/loaders/GLTFLoader"><code class="notranslate" translate="no">GLTFLoader</code></a> and we can get rid of the <a href="/docs/#examples/loaders/OBJLoader"><code class="notranslate" translate="no">OBJLoader</code></a>.</p>
+<pre class="prettyprint showlinemods notranslate lang-html" translate="no">-import {LoaderSupport} from '/examples/jsm/loaders/LoaderSupport.js';
+-import {OBJLoader} from '/examples/jsm/loaders/OBJLoader.js';
+-import {MTLLoader} from '/examples/jsm/loaders/MTLLoader.js';
++import {GLTFLoader} from '/examples/jsm/loaders/GLTFLoader.js';
+</pre>
+<p>And running that we get</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/load-gltf.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/load-gltf.html" target="_blank">click here to open in a separate window</a>
+</div>
+
+<p></p>
+<p>Magic! It just works, textures and all.</p>
+<p>Next I wanted to see if I could animate the cars driving around so
 I needed to check if the scene had the cars as separate entities
-and if they were setup in a way I could use them.
-
-I wrote some code to dump put the scenegraph to the [JavaScript
-console](threejs-debugging-javascript.html).
-
-Here's the code to print out the scenegraph.
-
-```js
-function dumpObject(obj, lines = [], isLast = true, prefix = '') {
+and if they were setup in a way I could use them.</p>
+<p>I wrote some code to dump put the scenegraph to the <a href="debugging-javascript.html">JavaScript
+console</a>.</p>
+<p>Here's the code to print out the scenegraph.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function dumpObject(obj, lines = [], isLast = true, prefix = '') {
   const localPrefix = isLast ? '└─' : '├─';
   lines.push(`${prefix}${prefix ? localPrefix : ''}${obj.name || '*no-name*'} [${obj.type}]`);
   const newPrefix = prefix + (isLast ? '  ' : '│ ');
   const lastNdx = obj.children.length - 1;
-  obj.children.forEach((child, ndx) => {
+  obj.children.forEach((child, ndx) =&gt; {
     const isLast = ndx === lastNdx;
     dumpObject(child, lines, isLast, newPrefix);
   });
   return lines;
 }
-```
-
-And I just called it right after loading the scene.
-
-```js
-const gltfLoader = new GLTFLoader();
-gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) => {
+</pre>
+<p>And I just called it right after loading the scene.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const gltfLoader = new GLTFLoader();
+gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) =&gt; {
   const root = gltf.scene;
   scene.add(root);
   console.log(dumpObject(root).join('\n'));
-```
-
-[Running that](../threejs-load-gltf-dump-scenegraph.html) I got this listing
-
-```text
-OSG_Scene [Scene]
+</pre>
+<p><a href="../examples/load-gltf-dump-scenegraph.html">Running that</a> I got this listing</p>
+<pre class="prettyprint showlinemods notranslate lang-text" translate="no">OSG_Scene [Scene]
   └─RootNode_(gltf_orientation_matrix) [Object3D]
     └─RootNode_(model_correction_matrix) [Object3D]
       └─4d4100bcb1c640e69699a87140df79d7fbx [Object3D]
@@ -189,42 +178,32 @@ OSG_Scene [Scene]
           │ ├─Car_04_2_2 [Object3D]
           │ │ └─Car_04_2_2_World_ap_0 [Mesh]
           ...
-```
-
-From that we can see all the cars happen to be under a parent
-called `"Cars"`
-
-```text
-*          ├─Cars [Object3D]
+</pre>
+<p>From that we can see all the cars happen to be under a parent
+called <code class="notranslate" translate="no">"Cars"</code></p>
+<pre class="prettyprint showlinemods notranslate lang-text" translate="no">*          ├─Cars [Object3D]
           │ ├─CAR_03_1 [Object3D]
           │ │ └─CAR_03_1_World_ap_0 [Mesh]
           │ ├─CAR_03 [Object3D]
           │ │ └─CAR_03_World_ap_0 [Mesh]
           │ ├─Car_04 [Object3D]
           │ │ └─Car_04_World_ap_0 [Mesh]
-```
-
-So as a simple test I thought I would just try rotating
-all the children of the "Cars" node around their Y axis.
-
-I looked up the "Cars" node after loading the scene
-and saved the result.
-
-```js
-+let cars;
+</pre>
+<p>So as a simple test I thought I would just try rotating
+all the children of the "Cars" node around their Y axis.</p>
+<p>I looked up the "Cars" node after loading the scene
+and saved the result.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">+let cars;
 {
   const gltfLoader = new GLTFLoader();
-  gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) => {
+  gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) =&gt; {
     const root = gltf.scene;
     scene.add(root);
 +    cars = root.getObjectByName('Cars');
-```
-
-Then in the `render` function we can just set the rotation
-of each child of `cars`.
-
-```js
-+function render(time) {
+</pre>
+<p>Then in the <code class="notranslate" translate="no">render</code> function we can just set the rotation
+of each child of <code class="notranslate" translate="no">cars</code>.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">+function render(time) {
 +  time *= 0.001;  // convert to seconds
 
   if (resizeRendererToDisplaySize(renderer)) {
@@ -243,42 +222,38 @@ of each child of `cars`.
 
   requestAnimationFrame(render);
 }
-```
-
-And we get
-
-{{{example url="../threejs-load-gltf-rotate-cars.html" }}}
-
-Hmmm, it looks like unfortunately this scene wasn't designed to
+</pre>
+<p>And we get</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/load-gltf-rotate-cars.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/load-gltf-rotate-cars.html" target="_blank">click here to open in a separate window</a>
+</div>
+
+<p></p>
+<p>Hmmm, it looks like unfortunately this scene wasn't designed to
 animate the cars as their origins are not setup for that purpose.
-The trucks are rotating in the wrong direction.
-
-This brings up an important point which is if you're going to
+The trucks are rotating in the wrong direction.</p>
+<p>This brings up an important point which is if you're going to
 do something in 3D you need to plan ahead and design your assets
 so they have their origins in the correct places, so they are
-the correct scale, etc.
-
-Since I'm not an artist and I don't know blender that well I
+the correct scale, etc.</p>
+<p>Since I'm not an artist and I don't know blender that well I
 will hack this example. We'll take each car and parent it to
-another `Object3D`. We will then move those `Object3D` objects
+another <a href="/docs/#api/en/core/Object3D"><code class="notranslate" translate="no">Object3D</code></a>. We will then move those <a href="/docs/#api/en/core/Object3D"><code class="notranslate" translate="no">Object3D</code></a> objects
 to move the cars but separately we can set the car's original
-`Object3D` to re-orient it so it's about where we really need it.
-
-Looking back at the scene graph listing it looks like there
+<a href="/docs/#api/en/core/Object3D"><code class="notranslate" translate="no">Object3D</code></a> to re-orient it so it's about where we really need it.</p>
+<p>Looking back at the scene graph listing it looks like there
 are really only 3 types of cars, "Car_08", "CAR_03", and "Car_04".
-Hopefully each type of car will work with the same adjustments.
-
-I wrote this code to go through each car, parent it to a new
-`Object3D`, parent that new `Object3D` to the scene, and apply
-some per car *type* settings to fix its orientation, and add
-the new `Object3D` a `cars` array.
-
-```js
--let cars;
+Hopefully each type of car will work with the same adjustments.</p>
+<p>I wrote this code to go through each car, parent it to a new
+<a href="/docs/#api/en/core/Object3D"><code class="notranslate" translate="no">Object3D</code></a>, parent that new <a href="/docs/#api/en/core/Object3D"><code class="notranslate" translate="no">Object3D</code></a> to the scene, and apply
+some per car <em>type</em> settings to fix its orientation, and add
+the new <a href="/docs/#api/en/core/Object3D"><code class="notranslate" translate="no">Object3D</code></a> a <code class="notranslate" translate="no">cars</code> array.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">-let cars;
 +const cars = [];
 {
   const gltfLoader = new GLTFLoader();
-  gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) => {
+  gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) =&gt; {
     const root = gltf.scene;
     scene.add(root);
 
@@ -292,7 +267,7 @@ the new `Object3D` a `cars` array.
 +
 +    root.updateMatrixWorld();
 +    for (const car of loadedCars.children.slice()) {
-+      const fix = fixes.find(fix => car.name.startsWith(fix.prefix));
++      const fix = fixes.find(fix =&gt; car.name.startsWith(fix.prefix));
 +      const obj = new THREE.Object3D();
 +      car.getWorldPosition(obj.position);
 +      car.position.set(0, 0, 0);
@@ -302,32 +277,29 @@ the new `Object3D` a `cars` array.
 +      cars.push(obj);
 +    }
      ...
-```
-
-This fixes the orientation of the cars. 
-
-{{{example url="../threejs-load-gltf-rotate-cars-fixed.html" }}}
-
-Now let's drive them around.
-
-Making even a simple driving system is too much for this post but
+</pre>
+<p>This fixes the orientation of the cars. </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/load-gltf-rotate-cars-fixed.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/load-gltf-rotate-cars-fixed.html" target="_blank">click here to open in a separate window</a>
+</div>
+
+<p></p>
+<p>Now let's drive them around.</p>
+<p>Making even a simple driving system is too much for this post but
 it seems instead we could just make one convoluted path that
 drives down all the roads and then put the cars on the path.
 Here's a picture from Blender about half way through building
-the path.
-
-<div class="threejs_center"><img src="resources/images/making-path-for-cars.jpg" style="width: 1094px"></div>
+the path.</p>
+<div class="threejs_center"><img src="../resources/images/making-path-for-cars.jpg" style="width: 1094px"></div>
 
-I needed a way to get the data for that path out of Blender.
-Fortunately I was able to select just my path and export .OBJ checking "write nurbs".
+<p>I needed a way to get the data for that path out of Blender.
+Fortunately I was able to select just my path and export .OBJ checking "write nurbs".</p>
+<div class="threejs_center"><img src="../resources/images/blender-export-obj-write-nurbs.jpg" style="width: 498px"></div>
 
-<div class="threejs_center"><img src="resources/images/blender-export-obj-write-nurbs.jpg" style="width: 498px"></div>
-
-Opening the .OBJ file I was able to get a list of points
-which I formatted into this
-
-```js
-const controlPoints = [
+<p>Opening the .OBJ file I was able to get a list of points
+which I formatted into this</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const controlPoints = [
   [1.118281, 5.115846, -3.681386],
   [3.948875, 5.115846, -3.641834],
   [3.960072, 5.115846, -0.240352],
@@ -350,31 +322,24 @@ const controlPoints = [
   [-5.373599, 5.115846, -3.704133],
   [1.004861, 5.115846, -3.641834],
 ];
-```
-
-THREE.js has some curve classes. The `CatmullRomCurve3` seemed
+</pre>
+<p>THREE.js has some curve classes. The <a href="/docs/#api/en/extras/curves/CatmullRomCurve3"><code class="notranslate" translate="no">CatmullRomCurve3</code></a> seemed
 like it might work. The thing about that kind of curve is
-it tries to make a smooth curve going through the points.
-
-In fact putting those points in directly will generate
-a curve like this
+it tries to make a smooth curve going through the points.</p>
+<p>In fact putting those points in directly will generate
+a curve like this</p>
+<div class="threejs_center"><img src="../resources/images/car-curves-before.png" style="width: 400px"></div>
 
-<div class="threejs_center"><img src="resources/images/car-curves-before.png" style="width: 400px"></div>
-
-but we want a sharper corners. It seemed like if we computed
+<p>but we want a sharper corners. It seemed like if we computed
 some extra points we could get what we want. For each pair
 of points we'll compute a point 10% of the way between
 the 2 points and another 90% of the way between the 2 points
-and pass the result to `CatmullRomCurve3`.
-
-This will give us a curve like this
-
-<div class="threejs_center"><img src="resources/images/car-curves-after.png" style="width: 400px"></div>
-
-Here's the code to make the curve 
+and pass the result to <a href="/docs/#api/en/extras/curves/CatmullRomCurve3"><code class="notranslate" translate="no">CatmullRomCurve3</code></a>.</p>
+<p>This will give us a curve like this</p>
+<div class="threejs_center"><img src="../resources/images/car-curves-after.png" style="width: 400px"></div>
 
-```js
-let curve;
+<p>Here's the code to make the curve </p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">let curve;
 let curveObject;
 {
   const controlPoints = [
@@ -403,7 +368,7 @@ let curveObject;
   const p0 = new THREE.Vector3();
   const p1 = new THREE.Vector3();
   curve = new THREE.CatmullRomCurve3(
-    controlPoints.map((p, ndx) => {
+    controlPoints.map((p, ndx) =&gt; {
       p0.set(...p);
       p1.set(...controlPoints[(ndx + 1) % controlPoints.length]);
       return [
@@ -422,33 +387,26 @@ let curveObject;
     scene.add(curveObject);
   }
 }
-```
-
-The first part of that code makes a curve.
+</pre>
+<p>The first part of that code makes a curve.
 The second part of that code generates 250 points
 from the curve and then creates an object to display
-the lines made by connecting those 250 points.
-
-Running [the example](../threejs-load-gltf-car-path.html) I didn't see
+the lines made by connecting those 250 points.</p>
+<p>Running <a href="../examples/load-gltf-car-path.html">the example</a> I didn't see
 the curve. To make it visible I made it ignore the depth test and
-render last
-
-```js
-    curveObject = new THREE.Line(geometry, material);
+render last</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">    curveObject = new THREE.Line(geometry, material);
 +    material.depthTest = false;
 +    curveObject.renderOrder = 1;
-```
-
-And that's when I discovered it was way too small.
-
-<div class="threejs_center"><img src="resources/images/car-curves-too-small.png" style="width: 498px"></div>
-
-Checking the hierarchy in Blender I found out that the artist had
-scaled the node all the cars are parented to.
+</pre>
+<p>And that's when I discovered it was way too small.</p>
+<div class="threejs_center"><img src="../resources/images/car-curves-too-small.png" style="width: 498px"></div>
 
-<div class="threejs_center"><img src="resources/images/cars-scale-0.01.png" style="width: 342px;"></div>
+<p>Checking the hierarchy in Blender I found out that the artist had
+scaled the node all the cars are parented to.</p>
+<div class="threejs_center"><img src="../resources/images/cars-scale-0.01.png" style="width: 342px;"></div>
 
-Scaling is bad for real time 3D apps. It causes all kinds of
+<p>Scaling is bad for real time 3D apps. It causes all kinds of
 issues and ends up being no end of frustration when doing
 real time 3D. Artists often don't know this because it's so
 easy to scale an entire scene in a 3D editing program but
@@ -456,21 +414,17 @@ if you decide to make a real time 3D app I suggest you request your
 artists to never scale anything. If they change the scale
 they should find a way to apply that scale to the vertices
 so that when it ends up making it to your app you can ignore
-scale.
-
-And, not just scale, in this case the cars are rotated and offset
-by their parent, the `Cars` node. This will make it hard at runtime
+scale.</p>
+<p>And, not just scale, in this case the cars are rotated and offset
+by their parent, the <code class="notranslate" translate="no">Cars</code> node. This will make it hard at runtime
 to move the cars around in world space. To be clear, in this case
 we want cars to drive around in world space which is why these
 issues are coming up. If something that is meant to be manipulated
 in a local space, like the moon revolving around the earth this
-is less of an issue.
-
-Going back to the function we wrote above to dump the scene graph,
-let's dump the position, rotation, and scale of each node.
-
-```js
-+function dumpVec3(v3, precision = 3) {
+is less of an issue.</p>
+<p>Going back to the function we wrote above to dump the scene graph,
+let's dump the position, rotation, and scale of each node.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">+function dumpVec3(v3, precision = 3) {
 +  return `${v3.x.toFixed(precision)}, ${v3.y.toFixed(precision)}, ${v3.z.toFixed(precision)}`;
 +}
 
@@ -485,18 +439,15 @@ function dumpObject(obj, lines, isLast = true, prefix = '') {
 +  lines.push(`${prefix}${dataPrefix}  scl: ${dumpVec3(obj.scale)}`);
   const newPrefix = prefix + (isLast ? '  ' : '│ ');
   const lastNdx = obj.children.length - 1;
-  obj.children.forEach((child, ndx) => {
+  obj.children.forEach((child, ndx) =&gt; {
     const isLast = ndx === lastNdx;
     dumpObject(child, lines, isLast, newPrefix);
   });
   return lines;
 }
-```
-
-And the result from [running it](../threejs-load-gltf-dump-scenegraph-extra.html)
-
-```text
-OSG_Scene [Scene]
+</pre>
+<p>And the result from <a href="../examples/load-gltf-dump-scenegraph-extra.html">running it</a></p>
+<pre class="prettyprint showlinemods notranslate lang-text" translate="no">OSG_Scene [Scene]
   │   pos: 0.000, 0.000, 0.000
   │   rot: 0.000, 0.000, 0.000
   │   scl: 1.000, 1.000, 1.000
@@ -528,22 +479,17 @@ OSG_Scene [Scene]
           │ │       pos: 0.000, 0.000, 0.000
           │ │       rot: 0.000, 0.000, 0.000
           │ │       scl: 1.000, 1.000, 1.000
-```
-
-This shows us that `Cars` in the original scene has had its rotation and scale
+</pre>
+<p>This shows us that <code class="notranslate" translate="no">Cars</code> in the original scene has had its rotation and scale
 removed and applied to its children. That suggests either whatever exporter was
 used to create the .GLTF file did some special work here or more likely the
 artist exported a different version of the file than the corresponding .blend
-file, which is why things don't match.
-
-The moral of that is I should have probably downloaded the .blend
+file, which is why things don't match.</p>
+<p>The moral of that is I should have probably downloaded the .blend
 file and exported myself. Before exporting I should have inspected
-all the major nodes and removed any transformations.
-
-All these nodes at the top
-
-```text
-OSG_Scene [Scene]
+all the major nodes and removed any transformations.</p>
+<p>All these nodes at the top</p>
+<pre class="prettyprint showlinemods notranslate lang-text" translate="no">OSG_Scene [Scene]
   │   pos: 0.000, 0.000, 0.000
   │   rot: 0.000, 0.000, 0.000
   │   scl: 1.000, 1.000, 1.000
@@ -559,27 +505,20 @@ OSG_Scene [Scene]
         │   pos: 0.000, 0.000, 0.000
         │   rot: 1.571, 0.000, 0.000
         │   scl: 1.000, 1.000, 1.000
-```
-
-are also a waste.
-
-Ideally the scene would consist of a single "root" node with no position,
+</pre>
+<p>are also a waste.</p>
+<p>Ideally the scene would consist of a single "root" node with no position,
 rotation, or scale. At runtime I could then pull all the children out of that
 root and parent them to the scene itself. There might be children of the root
 like "Cars" which would help me find all the cars but ideally it would also have
 no translation, rotation, or scale so I could re-parent the cars to the scene
-with the minimal amount of work.
-
-In any case the quickest though maybe not the best fix is to just
-adjust the object we're using to view the curve.
-
-Here's what I ended up with.
-
-First I adjusted the position of the curve and found values
-that seemed to work. I then hid it.
-
-```js
-{
+with the minimal amount of work.</p>
+<p>In any case the quickest though maybe not the best fix is to just
+adjust the object we're using to view the curve.</p>
+<p>Here's what I ended up with.</p>
+<p>First I adjusted the position of the curve and found values
+that seemed to work. I then hid it.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
   const points = curve.getPoints(250);
   const geometry = new THREE.BufferGeometry().setFromPoints(points);
   const material = new THREE.LineBasicMaterial({color: 0xff0000});
@@ -591,16 +530,13 @@ that seemed to work. I then hid it.
   curveObject.renderOrder = 1;
   scene.add(curveObject);
 }
-```
-
-Then I wrote code to move the cars along the curve. For each car we pick a
+</pre>
+<p>Then I wrote code to move the cars along the curve. For each car we pick a
 position from 0 to 1 along the curve and compute a point in world space using
-the `curveObject` to transform the point. We then pick another point slightly
-further down the curve. We set the car's orientation using `lookAt` and put the
-car at the mid point between the 2 points.
-
-```js
-// create 2 Vector3s we can use for path calculations
+the <code class="notranslate" translate="no">curveObject</code> to transform the point. We then pick another point slightly
+further down the curve. We set the car's orientation using <code class="notranslate" translate="no">lookAt</code> and put the
+car at the mid point between the 2 points.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">// create 2 Vector3s we can use for path calculations
 const carPosition = new THREE.Vector3();
 const carTarget = new THREE.Vector3();
 
@@ -614,7 +550,7 @@ function render(time) {
 +  {
 +    const pathTime = time * .01;
 +    const targetOffset = 0.01;
-+    cars.forEach((car, ndx) => {
++    cars.forEach((car, ndx) =&gt; {
 +      // a number between 0 and 1 to evenly space the cars
 +      const u = pathTime + ndx / cars.length;
 +
@@ -635,14 +571,11 @@ function render(time) {
 +      car.position.lerpVectors(carPosition, carTarget, 0.5);
 +    });
 +  }
-```
-
-and when I ran it I found out for each type of car, their height above their origins
+</pre>
+<p>and when I ran it I found out for each type of car, their height above their origins
 are not consistently set and so I needed to offset each one
-a little.
-
-```js
-const loadedCars = root.getObjectByName('Cars');
+a little.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const loadedCars = root.getObjectByName('Cars');
 const fixes = [
 -  { prefix: 'Car_08', rot: [Math.PI * .5, 0, Math.PI * .5], },
 -  { prefix: 'CAR_03', rot: [0, Math.PI, 0], },
@@ -654,7 +587,7 @@ const fixes = [
 
 root.updateMatrixWorld();
 for (const car of loadedCars.children.slice()) {
-  const fix = fixes.find(fix => car.name.startsWith(fix.prefix));
+  const fix = fixes.find(fix =&gt; car.name.startsWith(fix.prefix));
   const obj = new THREE.Object3D();
   car.getWorldPosition(obj.position);
 -  car.position.set(0, 0, 0);
@@ -664,52 +597,42 @@ for (const car of loadedCars.children.slice()) {
   scene.add(obj);
   cars.push(obj);
 }
-```
-
-And the result.
-
-{{{example url="../threejs-load-gltf-animated-cars.html" }}}
-
-Not bad for a few minutes work.
-
-The last thing I wanted to do is turn on shadows.
-
-To do this I grabbed all the GUI code from the `DirectionalLight` shadows
-example in [the article on shadows](threejs-shadows.html) and pasted it
-into our latest code.
-
-Then, after loading, we need to turn on shadows on all the objects.
-
-```js
-{
+</pre>
+<p>And the result.</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/load-gltf-animated-cars.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/load-gltf-animated-cars.html" target="_blank">click here to open in a separate window</a>
+</div>
+
+<p></p>
+<p>Not bad for a few minutes work.</p>
+<p>The last thing I wanted to do is turn on shadows.</p>
+<p>To do this I grabbed all the GUI code from the <a href="/docs/#api/en/lights/DirectionalLight"><code class="notranslate" translate="no">DirectionalLight</code></a> shadows
+example in <a href="shadows.html">the article on shadows</a> and pasted it
+into our latest code.</p>
+<p>Then, after loading, we need to turn on shadows on all the objects.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
   const gltfLoader = new GLTFLoader();
-  gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) => {
+  gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) =&gt; {
     const root = gltf.scene;
     scene.add(root);
 
-+    root.traverse((obj) => {
++    root.traverse((obj) =&gt; {
 +      if (obj.castShadow !== undefined) {
 +        obj.castShadow = true;
 +        obj.receiveShadow = true;
 +      }
 +    });
-```
-
-I then spent nearly 4 hours trying to figure out why the shadow helpers
-were not working. It was because I forgot to enable shadows with
-
-```js
-renderer.shadowMap.enabled = true;
-```
-
-😭
-
-I then adjusted the values until our `DirectionLight`'s shadow camera
+</pre>
+<p>I then spent nearly 4 hours trying to figure out why the shadow helpers
+were not working. It was because I forgot to enable shadows with</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">renderer.shadowMap.enabled = true;
+</pre>
+<p>😭</p>
+<p>I then adjusted the values until our <code class="notranslate" translate="no">DirectionLight</code>'s shadow camera
 had a frustum that covered the entire scene. These are the settings
-I ended up with.
-
-```js
-{
+I ended up with.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
   const color = 0xFFFFFF;
   const intensity = 1;
   const light = new THREE.DirectionalLight(color, intensity);
@@ -731,39 +654,46 @@ I ended up with.
 +  cam.top = 1500;
 +  cam.bottom = -1500;
 ...
-```
-
-and I set the background color to light blue.
-
-```js
-const scene = new THREE.Scene();
+</pre>
+<p>and I set the background color to light blue.</p>
+<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const scene = new THREE.Scene();
 -scene.background = new THREE.Color('black');
 +scene.background = new THREE.Color('#DEFEFF');
-```
-
-And ... shadows
-
-{{{example url="../threejs-load-gltf-shadows.html" }}}
-
-I hope walking through this project was useful and showed some
+</pre>
+<p>And ... shadows</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/load-gltf-shadows.html"></iframe></div>
+  <a class="threejs_center" href="/manual/examples/load-gltf-shadows.html" target="_blank">click here to open in a separate window</a>
+</div>
+
+<p></p>
+<p>I hope walking through this project was useful and showed some
 good examples of working though some of the issues of loading
-a file with a scenegraph.
-
-One interesting thing is that comparing the .blend file to the .gltf
+a file with a scenegraph.</p>
+<p>One interesting thing is that comparing the .blend file to the .gltf
 file, the .blend file has several lights but they are not lights
 after being loaded into the scene. A .GLTF file is just a JSON
 file so you can easily look inside. It consists of several
 arrays of things and each item in an array is referenced by index
 else where. While there are extensions in the works they point
-to a problem with almost all 3d formats. **They can never cover every
-case**.
-
-There is always a need for more data. For example we manually exported
+to a problem with almost all 3d formats. <strong>They can never cover every
+case</strong>.</p>
+<p>There is always a need for more data. For example we manually exported
 a path for the cars to follow. Ideally that info could have been in
 the .GLTF file but to do that we'd need to write our own exporter
 and some how mark nodes for how we want them exported or use a
 naming scheme or something along those lines to get data from
-whatever tool we're using to create the data into our app.
+whatever tool we're using to create the data into our app.</p>
+<p>All of that is left as an exercise to the reader.</p>
+
+        </div>
+      </div>
+    </div>
+  
+  <script src="/manual/resources/prettify.js"></script>
+  <script src="/manual/resources/lesson.js"></script>
+
+
 
-All of that is left as an exercise to the reader.
 
+</body></html>

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác