Three.js and TypeScript | Sean Bradley | Skillshare

Playback Speed


  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x

Three.js and TypeScript

teacher avatar Sean Bradley, Course Instructor

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

79 Lessons (9h 27m)
    • 1. Threejs and TypeScript Introduction

      1:54
    • 2. How to do this course

      1:08
    • 3. Setup Development Environment

      2:13
    • 4. Install TypeScript

      1:22
    • 5. Begin Creating the Three.js Project

      6:59
    • 6. Add the Initial Scripts

      6:05
    • 7. Setting up the WebPack Dev Server

      9:39
    • 8. Importing Three.js Modules

      3:16
    • 9. Install the Three.js Typescript Boilerplate

      3:13
    • 10. Scene, Camera and Renderer

      20:55
    • 11. Animation Loop

      7:38
    • 12. Stats Panel

      5:18
    • 13. Dat.GUI Panel

      8:17
    • 14. Object3D

      10:03
    • 15. Object3D Hierarchy

      9:09
    • 16. Threejs geometries

      13:48
    • 17. Materials

      11:25
    • 18. MeshBasicMaterial

      10:02
    • 19. MeshNormalMaterial

      3:05
    • 20. MeshLambertMaterial

      4:10
    • 21. MeshPhongMaterial

      3:17
    • 22. MeshStandardMaterial

      3:17
    • 23. MeshPhysicalMaterial

      2:36
    • 24. MeshMatcapMaterial

      3:26
    • 25. MeshToonMaterial

      4:11
    • 26. Specular Map

      4:56
    • 27. Roughness and Metalness Maps

      1:37
    • 28. Bumpmap

      2:45
    • 29. Normalmap

      2:27
    • 30. Displacement Map

      4:18
    • 31. Material Repeat and Center

      3:52
    • 32. Texture Mipmaps

      6:09
    • 33. Custom Mipmaps

      2:46
    • 34. Anistropy

      2:16
    • 35. Lights

      1:09
    • 36. Ambient Light

      2:39
    • 37. Directional Light

      3:55
    • 38. Hemisphere Light

      1:55
    • 39. Point Light

      4:04
    • 40. Spot Light

      2:09
    • 41. Spot Light Shadow

      5:55
    • 42. Directional Light Shadow

      2:29
    • 43. Orbit Controls

      13:33
    • 44. Trackball Controls

      3:43
    • 45. Pointerlock Controls

      7:51
    • 46. Drag Controls

      4:10
    • 47. Transform Controls

      2:48
    • 48. Using Multiple Controls in Same Scene

      3:32
    • 49. OBJ Model Loader

      15:59
    • 50. MTL Loader

      15:07
    • 51. GLTF Loader

      13:17
    • 52. DRACO Loader

      8:17
    • 53. Textured GLTF

      6:05
    • 54. FBX Loader

      6:31
    • 55. FBX Animations

      14:29
    • 56. GLTF Animations

      5:37
    • 57. Custom GLTF Animations

      10:55
    • 58. Raycaster

      23:33
    • 59. Raycaster Collision Detection

      4:46
    • 60. Raycaster Mouse Picking

      9:13
    • 61. Raycaster Measurements

      9:37
    • 62. Using tween.js

      10:52
    • 63. Using tween.js and the THREE. AnimationMixer

      14:44
    • 64. Vector3 Lerp

      5:23
    • 65. Physics with Cannon.js

      16:51
    • 66. The Cannon.js Debug Renderer

      13:22
    • 67. Trimeshes, ConvexPolyhedrons and Compound Shapes

      12:15
    • 68. Deploying to Production

      0:42
    • 69. Setup a Webpack Production Configuration

      6:58
    • 70. Host using GitHub Pages

      4:31
    • 71. Host using GitLab Pages

      3:34
    • 72. Host using an Nginx server

      9:04
    • 73. Point a Domain Name

      4:25
    • 74. Add SSL

      4:30
    • 75. Server-Side Functionality with Nodejs and Express

      7:04
    • 76. Socket.IO with Node.js, Express and Webpack

      17:40
    • 77. Setup Nginx as a Reverse Proxy

      14:01
    • 78. The Ballgame

      15:46
    • 79. Converting JavaScript Threejs Examples to TypeScript Projects

      14:53
  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels
  • Beg/Int level
  • Int/Adv level

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

369

Students

--

Project

About This Class

Welcome to my course on Three.js and Typescript.

Three.js is a cross-browser JavaScript library and Application Programming Interface used to create and display animated 3D computer graphics across the web in a browser.

In this course we will learn all about Three.js using demonstrations and sample code that you can download and experiment with on your own pc.

We start the course by setting up your development environment and installing TypeScript.

We then begin to create a Three.js boilerplate/template project that we can use throughout the remainder of the course, which will also give you exposure to Git, NPM, NodeJS, WebPack and is also generic enough that you will be able to use it in your own Three.js projects into the future.

We then move onto learning about the Three.js Scene, Camera and Renderer,
The Animation loop - when and how to use it,
Import the Stats and Dat.GUI panel tools, which are very useful when learning about Threejs,
We learn about,

  • Object3d base class, with its Rotation, Position and Scale transformation matrices,
  • Inbuilt Three.js geometries such as the Box, Sphere, Icosahedron, Plane, TorusKnot many more,
  • Materials such as the Basic, Normal, Lambert, Phong, Standard, Physical, Matcap, Toon, Shader and Depth,
  • Specular, Roughness and Metalness maps,
  • Bumpmaps and Displacement maps,
  • Manipulating UV coordinates to affect the appearance of the materials and displacement maps,
  • Llighting such at the Ambient, Directional, Hemisphere, Point and Spot Lights,
  • Shadows, and how to achieve perspective verses orthographic shadow affects,
  • Raycaster, and how to use it for mouse picking 3d objects in the scene,
  • The tween.js library to smoothly transition object properties such as camera lookat and object positions.
  • Physics with Cannon.js and using the cannonDebugRenderer
  • Understanding the different options for Cannon.js Physics Collisions.
  • Provisioning and Deployment to a Production Server
  • Setup Nginx Proxy, Domain Name and SSL
  • Using Module Specifiers with Webpack Versus Relative Import References
  • And many more useful examples of Three.js that you can copy and experiment with your side in order to understand Three.js at it's core much better.

At the end of the course, you will understand Three.js and also how to use TypeScript in order to write robust and type safe code much quicker. And then you can begin writing your own 3d games, applications and presentations which will be accessible from a browser and on the web.

So,
Thanks for taking part in my course and I will see you there.

Meet Your Teacher

Teacher Profile Image

Sean Bradley

Course Instructor

Teacher

Hello, I'm Sean.

For over 20 years I have been an IT professional developing and managing real time, low latency, high availability, asynchronous, multi threaded, remotely managed, fully automated, monitored solutions in the education, aeronautical, banking, drone, gaming and telecommunications industries.

I have also created and written hundreds of Open Source GitHub Repositories, Medium Articles and YouTube video tutorials.

See full profile

Class Ratings

Expectations Met?
  • Exceeded!
    0%
  • Yes
    0%
  • Somewhat
    0%
  • Not really
    0%
Reviews Archive

In October 2018, we updated our review system to improve the way we collect feedback. Below are the reviews written before that update.

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

Transcripts

1. Threejs and TypeScript Introduction: We haven't surveyed. Say hello. But to try to teach explosion electricity production. 2. How to do this course: Welcome to my course on three G in TypeScript, discourse comes in five main sections. First, we'll set up a development environment and install TypeScript will then create a three J is boilerplate project manually from the ground up. This will give you a very good understanding of the aspects involved in creating brand new three j's program from scratch or you could bypass I got under Section 3 and install the pre-built boilerplate manually. Then after that, we'll continue with many, many examples, starting from the core three js and building up until it gets more advanced examples and also involving other third-party libraries. And then the final section is about deploying to production. We have several different methods and we'll explore those. Excellent. Now, the course comes with free documentation, which is just full of code and examples that we'll discuss throughout the course. Each new lesson will come with some code that you can download. For example, spotlight shadow. And we get an example that you can look at on the website. Plus you can paste it into the boiler plate and then have it running locally on your own computer. Very good. Excellent. Okay, so let's get started. 3. Setup Development Environment: Okay, let's set up a development environment that matches what I'm using in the videos. So I'm using Visual Studio Code. You could use a different IDE if you like. But I recommend this because it's very good copy that visit that in a browser. And I'm using Windows 10. So it's going to give me the option to download stable build. The download is started. Now open and install. I'm just accepting all the defaults. Very good. Next, Git for Windows, this is optional if you download the boilerplate early on in the course, you will need to use Git because we use git clone. Anyway, we visit good for Windows to open the browser and download and open file. Yes. Install next, next, next, next, next, next, next next. I'm just accepting defaults. Okay, finish. If you're using Linux or a Mac, get is most likely already installed on your computer. It doesn't come pre-installed on Windows 10. And finally, NodeJS, because we'll be using a NodeJS server later on in the course. And also we'll use npm to set up our project. Okay, so no js.org, I'm going to use Windows installer 64-bit MSR. You may be prompted if you want to keep that file, just select. Yes. I'm not being prompted in this browser at this moment. Okay. Next, Next. And once again, I'm just accepting all the defaults. Okay, finish. Brilliant. Now we can verify those things were installed. Open up a command prompt and you can type git version and it will tell you the good version. You can also write no hyphen v, and that will tell you that your Node.js installed if you type in npm, v, would also tell you that your MPM stored that comes with node. Okay, Very good. Next video, we'll set up TypeScript. 4. Install TypeScript: Okay, now we're gonna install TypeScript and verify it works. Okay, so this is a heavy course and we'll be writing it in TypeScript. If you've never seen TypeScript before, don't worry, it looks a lot like JavaScript, except it enforces type safety in your code. So as a result, we get advanced IntelliSense features and we can quickly see the available methods and properties in all the objects that we use. Okay, so let's install TypeScript globally using npm there. So copy that, okay, open a command prompt, CMD, right click using the mouse, enter. Very good Does installed. Now we can verify that installed by typing TSC IF-THEN the 4.3.4. Perfect, that works. Now, if you were using PowerShell, which also happens to be the default integrated terminal in VS Code. I'll show this in the next video. Writing TSC hearth and v may cause an error similar to that below. So how a shell, I've open PowerShell TSC IF and the, it says TSC, PS1 can't be loaded because running scripts is disable on this system. This is an error that you may see in PowerShell. If that happens to you, you can type TSC dot cmd, and it will run the command version of TOC for you. Perfect. In the next video, we'll start creating our three JS project. Excellent. 5. Begin Creating the Three.js Project: Okay, So now we're ready. Let's start creating a three J is project that we'll use throughout the remainder of the course. Now, note that we're building this manually from the ground up. You can bypass the section and go straight down to the three. J is tasked with boilerplate and download it if you like. But doing it manually gives you very good background knowledge and you'll be able to adapt this to your own needs in the future. So anyway, depending on your operating system, open a Command Prompt or Terminal. I'm on Windows 10, so I'm going to open a command prompt. So, and I'm going to go to a folder or drive somewhere on my system where I'm going to work. So I've got a spare drive called D. You might not have a spare drive or you may have something else. That anyway, doesn't matter. We want to do is create a new folder wherever you want to work called three J is TypeScript tutorial. So make directory three J is TypeScript tutorial. This is going to create a new folder, this command. Now, I just copied that using my mouse and then I right-clicked inside the command prompt and I pasted it for me growing up, press Enter. Okay, now cd or change directory into that folder. If you just press Tab after typing a few letters, it'll fill in the rest for you. So now press Enter. Okay, So I'm now in the folder three. J is TypeScript tutorial for DIR that there's nothing there, it's empty. If you're on a Linux or Mac, you can just type ls. And that's the same as typing DIR, but it doesn't work on Windows command prompt, okay, it works in PowerShell if you're using PowerShell, but anyway, on Windows command, just DIR and the way it's empty, 0 bytes now folder, now we need to initialize the project using npm init. So that's down there. Npm init, press Enter. It's going to use the folder name as a project name by default, that's okay. It's press Enter and just keep pressing Enter several times until we get to the end. Yes. Okay, DIR, there's one file in there called package.json, and we can look at that. We'll look at that in a moment. Okay, so now that we've established a working folder for ourselves where we're going to build our project. And we have one fallen it called package JSON. Instead of using command, we can actually start using Visual Studio Code. So Type C, O, D, space dot. And now that's open up Visual Studio code into the same folder where I typed code space dot.me dist folder. If we open that up, we can see package.json and that's the contents of package Jason. It's very simple. We'll add some packages, will start with three js. Now, instead of typing further commands into this command prompt, we can actually closer and have integrated terminal inside this code. So to do that, you can either press terminale, new terminal or you can type Control Shift and single quote. So Control Shift a single quote and that's opened up a new PowerShell terminal down the bottom there for me. So if I type DIR, that will show the current folder. And because I'm using PowerShell, Ls also works, does the same thing. Okay, so next let's install the three JS library. So copy that line there, that's copied it to clipboard and right-click again and paste it. So MPM install three and I'm saving it to my development environment configuration. We won't see that here right at the moment. But if I press Enter, it's downloading three js from the Internet. And it's created a new node called dev dependencies 3, 0, 1, 0, 0, 1. Now this course will be built using three release 130. There's a new three J is released every month. So depending on when you access this course, there'll be other versions of three J is available. I'll try to keep this course updated with all the changes that happen to three J is from now on. If you have downloaded three version 160, for example, and something doesn't work if my B and my code was based on three version 130, but all have notes in my online documentation outlining any differences that you should be aware of as the new versions come out. Js is MIT licensed, so there's no warranty of backwards compatibility. So that's our package.json. Now, next thing to do is to create some extra folders inside our project. First one, we'll call dist. Okay, so I'm going to use Control minus to make the screen slightly larger like that. Okay, so in the root folder here of my project three J is TypeScript tutorial. I'm going to press this icon. This is a new folder icon, and I'm going to call it just dist stands for distribution. So all our files that we'll see in the browser, we will come from the dist folder in that photo, credit to more folders, one called client and another called server. Okay, now we just need to reorder that server should be under dist, dist client and server. Now note that early on in the course, this server folder won't be used DC, something that all use a lot later in the course when I start using server-side functionality, you now three J is project, okay? Now in saw, a deceased client will create a new file called index.html. So distinct client, new file, That's the icon there, index.html. And in that, we'll copy this and paste. Now that's just a very basic index. Html doesn't have much other than what you can see, has one style for the body which are used to remove borders and imports one script called bundle JS, which webpack will create. And there's a tie that module. Now that index.HTML will be the same index HTML that is used through most of the course. We will come back to these fall very rarely but expects to make some changes to it. We'll add some styles, we'll add some extra HTML elements as we go through. Okay, so that's saved right now to create a new file called source SRC in the root down there. So press the new folder and call it SRC. Okay, so I have node modules and SRC. Src add a client and server folder. So if I click Source and add folder, it will already added as part of the source folder, just like so. So that's our folder structure right now. Okay, so verify that your folder structure looks like this. Client with an index.HTML and server is MD. The moment, that's something we'll use later on in the course. There is a new folder called Node module slash 3. This was created when we ran NPM install three and there's only one project in sawdust node modules folder, but this will slowly start filling up with a lot more projects as we install Webpack and TypeScript locally also to the project. Okay, So we will look at many of these things as we progress. But right now, just be aware that it exists. Now in source, client, and server, there are no files just yet. We'll get onto that also. In the early stages of the course, the server folder won't be used, but it's there anyway so that you know. Okay. And there's the package Jason with one dependency three, and I'm using version 130, okay, Now there's no point in running this yet. It won't work. We'll get onto the next lesson where we will add some initial scripts. Excellent. 6. Add the Initial Scripts: Okay, So let's add some initial scripts. Now inside the folder, source client will add a new file called client Ts. So in our project, in source client, new file, client Ts, the extension dot ts, this will be a TypeScript file, so we'll copy this code. So I'm pressing the icon there to Copy to Clipboard. Okay, that's copied. Now paste control V to paste. So that's the code and Control S to save. There we go. Okay, next, we need to create another file and that is called ts config dot JSON. So source client tears config dot Jason create data. So in the client folder, new file, ts config dot JSON and paste that. This is a very minimal tears config. And this is all we're going to need for almost the whole remainder of the course. Typescript can be used to generate JavaScript for many different environments, but we only need it to generate JavaScript suitable for Webpack, to bundle L code into a single file. And this is all we're going to need for the two options. We're using our module resolution, which describes how to find libraries, for example, wages type 3 and need knows where to go in is using a technique called node module resolution. To do that. Find out more about that by pressing this link, if you like, the TypeScript documentation is quite hard to read, but it's there for you. And strict equals true. This is something that I recommend in all of your projects. I'll use it to make sure my variables are either instantiated when they declared or in class initializers. And you can also read more about that. They're strict. And then include that saying that the TypeScript compiler will convert all files ending in dot ts inside this client folder, any subfolders to ts config, he's in the same folder, is the client there. So this t is config is related to this particular project. I'll create another ts config later on when I start looking at server-side code and a production one. Okay, so that's saved. Now, if we go back to the client, yes, we'll see it's having some corner problem. Could not find a declaration fall for module three. Since three Release 12 6 taught definitions that TypeScript users are no longer included in the three JS project. By default, we have to download those independently of three js. Now, the agreed best place to get these definitions from our now, from a project called definitely taught, you can create your own type definition false, which I do occasionally myself. But for this course, we'll get three J is definitions from definitely typed. So to do that, copy that line there, we're going to npm install at types slash three, okay, so in the terminal right-click, so it pastes npm install at types slash three, save-dev, press Enter. Okay, So the top definitions at this other repository would credit for version 300, 300, and look at package Jason at types 33 are slightly different versions. But this is going to happen quite often because they're both projects managed by different sets of people. So there may be occasions when the top definitions don't match the current version of three js and you may have to create your own additions to a type definition fall. But for now this is just fine. So we can continue with that. If we refresh our folders there in Node modules, we now have two projects. There's three. If we started off with the last video and now the AT types Definition folder, which has its own copy of three type definitions. So in there, you won't find any JavaScript code, but you'll find these d dot ts false, which describe the types of all the methods and properties use route through JS. And our IDE will use these files to help us keep our code type-safe. So there's three and the top definitions for three. Okay, so before version 12, 6, these things were in the same project and the types were often updated as three was updated, but now they are different. So you will get some occasional incompatibilities. Bob will resolve those if those things turn up throughout the course. Okay, so I don't need that fall open anymore. Yeah, forget back to client Ts down where it's telling us that it couldn't find a declaration file for three. It actually should have been able to find it by now BOC to fix that, press F1 and press Restart Ts server. Okay, and after a moment, the Node module resolution will take effect that we've set in tears configure, and each should find three, because that's found a definition for three now, that means IntelliSense works now in the IDE. So if I go three dot, it's going to show me all the different methods and properties and types that I can use inside the three module here, it's the same with camera. I can now use camera dot and all the methods and properties types of camera will appear in the IDA that I can click from or find out more information. The Renderer, renderer, or even cubed dot, dot all the methods and properties available to Q. That's the TypeScript definition. Doing that for us. Okay, so verify your folder structure looks like that. Three J is TypeScript tutorial, dist client server folders one index.HTML node modules now with types 33 source client, client ts, ts config server WR, not using Server package.json and package.json. That is something that is auto graded. We don't really need to worry about that for now. If you delete that and run npm install, it will just credit again for you. And in VS code, that's how it looks. Client server types, source client server. Excellent. Now there's still no point in running this. It's not going to work. What we'll do next is install webpack, which when we've finished configuring it, will take our client TypeScript here and create a bundle JS and hosted using the webpack development server. Excellent. 7. Setting up the WebPack Dev Server: Now we're going to set up Webpack with the webpack development server. Okay, so we'll use webpack development server to run our three JS code. We're pack development server has several features that make development and easier process such as HMO, hot module reloading is will auto refresh our browser when we make changes to the code. And it will bundle all of that code dependencies into a single JavaScript file that will be loaded into the HTML as bundle JS, as you see here in index.html. Okay, so we need to run this line here. This line is installing five things. So Webpack itself, which can science to call, that will bundle all of our code into development and production versions is the Webpack CLI, which allows us to use webpack from the command line and also via an NPM script, which I'll show you the webpack development server, which is little mini web server that will host our files so that we can view them through the browser as if we were looking at it through a real web server, the web pack merge, this is optional, but it allows me to create several different configuration files, but also have shared elements to those. We'll look at that and Ts loader, which is used because we're using TypeScript files. Now, if you weren't doing TypeScript and you just rotting away your source using JavaScript. You wouldn't need a T, a slider bar discourses about doing it using TypeScript. So we need that, okay, and then save-dev again. Once again, all of these are only going to be useful during our development server setup. Okay, so copy that line, go to the VS Code integrated terminal, right-click and press Enter. Okay, Now, if I refresh the folder, there we go. The node modules folder now has many, many more dependencies in it. Webpack has many dependencies. It uses a little bit of this and that like so. Now, looking at the output of the in-store, there were several warnings. Webpack is also a project developed by a different set of people. Depending on when you install Webpack, you can get different kinds of warnings. At the moment, there is one moderate severity vulnerability, which is because it uses a project called chocolate, are within the next month or two from creativeness video, this particular area should be fixed right now, this won't affect the ability to run the course, but you can run npm audit fixed, but right now also, that doesn't actually work. But eventually that's one of the options you, I have right now. Is it not functionality? Block us? And also, since we are using DNS load on here, one of the warning says it requires a peer of TypeScript, but none is installed. So that means it needs a local copy of TypeScript inside your project. We've installed TypeScript globally, but dispersion of Ts load or doesn't find the global version of TypeScript. So when you install it locally. So to do that, npm install TypeScript save-dev. Okay, so npm install TypeScript save div. Okay, go to package JSON. And if we look our package Jason, it has a whole lot of other things under dev dependencies, so including TypeScript as well. So that's what we've installed test loader, Webpack, CLI, div server, merge. And these are all the different versions that were available at the time of correctness video. Okay, so next thing, let's create some Webpack configurations. The first one, source client will call it Webpack.com and dot js. So let's create a new file. So under source client, their new file, webpack.com ab.js, copy that script and paste. Now you can ignore those three dots there. It's offering to convert that to an ES6 module. I'm not going to do that in this course. I'm going to keep it just the way it is. Okay? So this is a configuration that is applicable to both our development and production versions of our webpack configurations. So it's saying this is the entry point to our application being source client, client Ts. That's what we've got there. We're describing a role that webpack should follow. And it's looking for anything with Ts or TSX. And if it finds anything like that, it will use the Ts loader to process those falls. And it's going to exclude the node modules folder if it finds one. So it's going to resolve all extensions TSX, Ts, and JS. It will output a file called bundle JS. That's the name of the fall that I'm referencing in my index on NodeJS. And the path that it will save it to will be the client. If I go down one and go down another, so down one and then down another back to the root of 1 to dist then declined. So index.HTML and bundle JS will be at the same level from the perspective of the browser. So the browser will load index.HTML and equal find bundle JS next to it. Okay, so next file, webpack dev JS, it's credit that fall under Client webpack dev js. Copy that, paste that. Now it's using Webpack merge here. What it's gonna do is first load common, which is that one just there. So these are the common configurations for both of our webpack configurations for development. Production and also add a mode being development, a dev tool, email source map, and the dev server, the content base being decent client, hot equals true. That's describing the hot module reloading. If you turn that off, the white refresh the browser when you make changes to the source code. I won't add a production configuration just yet. I'll do that later on in the course when we do the section on deploying to production. But for now, let's continue onto package. Jason did add a script that will use the Webpack CLI that will allow us to start the webpack development server using the configurations that we just saved. So this line here under scripts div, webpack, config source, client, webpack dev JS comma. So that's saved, go down to Jason and under scripts here, add this new option scripts div called dev Webpack assert it will run this line and that will start up a Webpack development server using that configuration webpack dev JS, that's webpack dev JS, which is also loading WebEx CommonJS and those configurations. So let's just save package Jason. Now, after you've done that, you should be able to type npm run dev div is that script there. So npm run dev looked at, okay, it's building the bundle JS for us using the development configuration. And if I scroll up their assigned a project is hosted at localhost. I DID. If I just hold down Control and press plus, it'll open a browser with the three GIS project running it. And it's just a rotating cube. If I press F2, you will live to up the development tools inside the browser. This first era, dc cannot find a fab icon, does nothing to worry about. I haven't added a fab icon. Do like CO2, my project, but you can create one if you like. The official boiler plate has one added, but it's just a little graphic that we use as an icon in the tab there. Okay, now, if we look at the other things written in the console, so the high chair ma, live reloading is enabled. That means that if I was to make a change to client Ts down here, for example, or change the color of the material used by the cube or put in 66. Press Control is to cite it auto updates. That's not a very good color. Let me just do if if 000 and we go, It's completely red or I can comment out Wireframe, press Control site, announce a solid color as the course progresses. All discuss every line of code here so that you know what each of those does that for now, so that you know that what HMO is actually doing, It's refreshing the browser, want to make a change to the source client TS. Now other things to note about the webpack development server is that if I was to refresh the folder structure there under deceased client there there is no bundle ab.js Webpack development server is hosting that dynamically for us, looking at the development tools, if I look at network there, and now it is clear that and then just press F5 to refresh the browser, we can see that it's getting bundled ab.js there. And when you actually look at the contents, but this is being created and served dynamically through the webpack development server. And it's quite a large file. It includes Hashim, It's not good enough for production. That's why we have a different configuration for development, setup and Webpack. Ce credits assigned specific WebSocket which are uses for high GMR, which our production version one do that. But the development version credit through webpack dev server is built quite quickly. So just be aware that that file doesn't actually exist. Here. It's being served dynamically and we can actually visit it in the browser just by typing onto dot js like that. And now we can see the dynamically created bundle JS served by the webpack developments, so on. It's an enormous file and it's not suitable for production, but we'll get onto production set up later in the course. First, we'll spend a lot of time learning about three js and running it in Webpack. And back, there we go. And I'm going to put that back to grain being sewers or if, if 000, it's green. Okay, so now that we didn't create a production version of the webpack configuration just yet, but we'll look at that light up when we do the section on deploying to production. And we have many options on that. The production version of bundle JS will be a much smaller file and it won't contain the hot module reloading by EDs much slower to produce stats while we use a specific and development version during development. Excellent. In the next video, we'll expand on the current example by importing one of the three js example modules, specifically, orbit controls Excellent. 8. Importing Three.js Modules: Let's look at the basics of importing three adjacent modules. The core of three JS is focused on the most important compilers have the 3D engine. Many extra modules such as 3D model loaders and controls are part of the examples directory. If you want to use these extra modules in your project, then you need to import them separately. Okay, so looking at the node modules, and if we scroll all the way down to three, there it is, there, we get billed. So right now our project is referencing H3, which is pointing to the three dot module js file there. But in examples, GSM, more specifically, because we're using the module version of three js, all these extra folders. So modules related to animations, cameras, controls, CSM, many other things, geometries, environments, math, lights, but very common to also include one of the example modules in your projects. Probably the most common that you'll find throughout the Internet is that people will use the orbit controls. So how to get all the controls into your project? Forget about the client. If we look at the source code here and just copy that line highlighted in yellow. Import orbit controls from three examples j, same controls or controls. So that's what I was looking at. Three examples, GSM controls or the controls. And it's showing some kind of issue here. It says orbit controls is declared, but its value is never read. Okay, so let's create a new orbit controls. I'm going to credit after the renderer, because the new orbit controls uses the renderer, it also uses the camera. Now, that's all we need, press Control S. And if Webpack is running in the background because he started at using npm run dev. If you go back to the example, you can now interact with it using your mouse. So up and down, left and right, and you can zoom in and out. You can hold down the middle mouse wheel and do that. You can hold down the royal click and you can pan left and right as well. So that's the orbit controls. My tube is rotating because in my animate function on rotating the cube, but in turn that off and go back. And now it's not water rotating, but I can rotate it myself using the mouse. Then you might want to put that back like so. It's very compiled. And if I view would again, it's moving around again. Okay, so that's just the orbit controls. There are many extra modules in the examples folder, and we'll go through many of those as the course continues. But right now, that As it stands, now is the basic boilerplate that we'll use throughout the course. And we'll add more would change things, but we'll keep coming back to these basic setup. Excellent. Okay, the next video, I'll show you how to download the existing three J is boilerplate from GitHub and that's useful if you just quickly wanted something you could work with and you can quickly prototype new ideas for or if you bypassed these previous videos, okay, and then after that, we'll look at the same and the camera and the renderer. And they are the different elements that the very first example is demonstrating. Excellent. 9. Install the Three.js Typescript Boilerplate: Now installing the three J is TypeScript boilerplate. This section is optional if you completed the sections beforehand from here where we set it all up manually, you already have the boilerplate, but you may want to try this anyway, or you may have already completed the course. And you just want to boil up light because you're getting a new project. So here I'll show you how you can just use that instead. So this boilerplate is on GitHub and we can use the git clone command to download it, set it up, install it, and run it, and view it in the browser. So copy that section, complete or one line at a time, doesn't matter. Open up a command prompt, go to someplace way we'd like to work. I'm going to go to my D drive. If I right-click that whole section, data's copied in, it's now cloning the boilerplate from that address. It's also running npm install because I've copied a whole lot and now it's waiting for me to npm run dev. So I press Enter. It's good. Visit that in the browser. And that's the boilerplate running in the browser. Excellent control C to get out of that. Now looking at those commands again, okay, so I'll copy that whole section right-clicked and then it just did all those things. I could've just did one line at a time, did that density into the new folder, npm install, npm run dev if I wanted, if I wanted to edit the code, taught code space dot, and the code has opened up ready for me to edit. So source, client, client tears. Now when we started, we didn't create a folder called rage IS TypeScript boilerplate, we called it three. J is taus group tutorial. It doesn't really matter. What you can do is clone into custom folder if you like, for example, that first line git clone that you can add a different path to the end of it. So I'll just copy that. I'm gonna go back one guy back down to D, C, D, okay, now, right-clicking that It's the same as before git clone from that address. But here I'm saying example 1. So that will now put the repository into a folder called example one. Press Enter, see cloning into example 1. Now if I did C, D, Example 1, DIR or LS, if you're using Linux, mac, or even PowerShell. The falls of this, so npm install npm run dev. Is it that in the browser? There we go, That's the boilerplate running from the example one photo and Control C to N That taught code dot. And now we can edit our project from example one folder there and npm run dev. And we can visit it in a browser like so. Now I'm just not a quick one that you might come across if running multiple projects at the same time. If I leave all that running and go backwards, CD down and then cd into the three JS boilerplate folder and then run npm, run dev again. It's going to tell me the addresses in use. That's because I've got poor ADHD opened in this window down here. If I Control C that go back and start that again, that's now started. Okay, this console is using port 8080. Excellent. In the next video, we'll look at the scene camera and renderer, and we'll start learning about the core of three. J is excellent. 10. Scene, Camera and Renderer: Okay, Now we're going to look at the basics are the same, the camera and the renderer, three GIS. And it's cool is a library that allows you to add and describe data in three-dimensions, example as meshes and lights, and then convert that data into a 2D representation onto a HTML canvas. Before we can do anything with three js, we need three things seen, a camera and a renderer. So in this video, in order to understand these things better, we discuss and experiment with some of the options we have relayed to them. So there's the same as a camera and there's a renderer. So looking at the code we have so far, There it is this the same camera and to render out, okay, Another way to look at that, there's the same as a tree-like structure or meshes lot cgroups already positions and cameras optional is a camera which describes the view boundaries of the same within frustum dimensions and the renderer, which takes lead data and puts it onto the canvas. And this is a working example that they're like area is a HTML canvas. If I was to look at the output at HTML, CSS, the canvas, HTML tag, the canvas, and that was dynamically written from our code. We'll get onto that. Okay, looking at the code, Let's look at the same in more detail. If we go right down to the end where after I've added at least one mesh to the same. So I've done that day, That's console dot DIR, seem, press Save, go back to the browser. Console scene has now been logged out to the browser. These are all the objects that are inside the scene. The scene itself is a base object called object 3D, which we'll look at later on in the course. But for now an object 3D has many properties, such as its own children. In this example, that's the mesh, mesh 0 geometry, the box geometry. It has a position being 000 000. So I didn't change that default as a rotation which is continually changing. It has many properties. It has a material which I've said is why frame and green. So I'll get N This Wireframe true and color RGB. Now the scene itself also has a position which is default 000, 000, even a rotation and a scale as an APP vector that's important in three J is the up vector is why not all 3D programs are the same. Sometimes I use zetas, the up to Victor, 3 JS y is up. So anyway, so you know, you can view the properties of the same by using consult DIR or even console.log. It doesn't really matter anyway. One property of the scene we can change is the background color. And because we're using TypeScript, if I press dot, it will then give me all the available properties and methods that I can use. So if I start typing B, it says Background equals a new three dot color. Now I can pass in a string or a number, or another three.com. I'm going to pass in a number being our way, X FF 000, 000, That's RGB in hex if f is like saying 255, but that will be converted to a three dot collarbone and saints, which will be RGB floods between 01. But that is a really easy way of saying, OK, save that. Looking back at the example, the background color is now red. We can experiment with those colors IV morphine like so what FF eight zeros or does that color or 448800 or 4488 Ff or even 0000, 0000 fifth completely blew. Its RGB, or black is all zeros, or white is all F's, 66. And I go, and I'm not going to use that for now. Put it back to the way it was. Next thing we'll look at is the renderer just here. There are several different render isn't three gi is that you can use, but most of the time you'll use a WebGL rendering That's the fastest and the most supported. That's the default renderer that you'll find in almost every example on three js. So it comes with a lot of defaults, but one thing you have to sit is the size. And I'm setting the size of the window in a width and a height. That means that when I refresh screen or loads, it fills up all the available space of a document. Here I have the Development Tools open so I can just close that and it'll resources after the available space. But that re-sizing doesn't happen automatically. That happens because down here I have an event listener called re-size where I update the size and also update the aspect ratio of the camera. But we'll get onto that to match the new size. So that's what that function does. So if we comment that out and then I refresh and I resize the window, it doesn't re-size the 3D view on the canvas. So I'll put that back and it updates and now it resizes to fit the canvas and the aspect ratios also changing. We'll look at that in a moment. Okay, So that's a very common function that you'll also see throughout many examples of three JS. Okay, so what happens if we change the size? It's not being in a width and a height, but using numbers directly such as 200 by 200. When I refresh that, the canvas is now 200 by 200, but the aspect ratio looks wrong, but that's because it's being set in the camera there. So in order to match that aspect ratio out of stuff to update it in the camera as well. But there, which you can do to avoid to a 100 divided by height, which actually 200 Boyd to a 100 actually equals one. So if I precise refresher, that's fixed now, but also because I have the window resize event, it's changing if I change the window size. So I can now comment that out. And you asked That's very quickly what you're seeing there with the renderer. So it's quite important to understand the considerations to if you're singing the song is directly as numbers, or whether you're taking the window in a width and height. And also I've done the camera aspect ratio as well. And whether you have a resize event, also updating the camera aspect ratio and render a set size. And you either it's back to the why it was at the beginning. And let's look at what this law and is doing this append child, you can dynamically add. Elements to a HTML document. And here we're appending the renderer DOM element. Now render a DOM element as the render there. It has a DOM element property, which actually is a HTML canvas element. It creates his own internal Canvas element when you create the renderer and we're dynamically adding it to the document body. So when we look at pricing, if 12 open Developer Tools, and if we look at the elements down here, the Canvas, I haven't written this Canvas in my HTML code. So index.HTML, I've written script module bundle JS by haven't written Canvas script module bundle JS. But there's a canvas tag that was dynamically added, that was dynamically added by this line here, we don't use that line. We won't have a Canvas. Nothing's being drawn, but the render is still exists in the background and is still being used in the render function down here. So sometimes people would rather hard code the Canvas into the HTML. You can do that. So index HTML there, I'm just going to put it here. Canvas ID equals C1. For example. I go is a HTML canvas. I'm also going to give it its own style hash for IDs C1 width to 100 and 200 px, like so in the code, we need to create a canvas object of our HTML element there, const Canvas calls document dot getElementByID C1. And when we create our renderer, we tell it which canvas to use. Canvas colon equals does canvas element here. Now because we're using TypeScript, it's indicating that HTML element or null is not assignable to type HTML canvas. So the idea here doesn't know what is being returned by document getElementByID dot C1. It could be anything. It's considering it by default to be something of my HTML element or null because that's what that actual function returns. You can see that there, but we can cast it by saying as HTML canvas element. And now that is considered legal from the perspective of TypeScript because we're passing in a hasty well canvas elements. So we've just casted whatever that's going to return explicitly as a HTML canvas element. So that should work is a hard-coded Canvas, but it has overridden the width and the height and our style, because we're setting the size of the window in a width and a height. So it's just update that to be 200, a 100. I'll also update the camera aspect at the same time being one to a 100 divided by 200 equals one. And I'll turn off this resize event as well. I go, that is our hard-coded canvas width, height 200 with a style matching assignment. Okay, so that's another way of using the render where you're more explicit about the size and you're using existing canvas element that exists on the document. And here I'm using an ID C1. So we can have two renderers if we like. So I'll do that very quickly. Render 0, 1 and renderer to. And because we're using TypeScript, it's telling us all the things that no longer makes sense. So Renderer, renderer to render one, I'll attach the Oba controls render a 1s DOM element. Here, render, render a one, render, render it to render. Now, let's create a second canvas because L second renderer is still using the first Canvas, which is not really useful. So I brought in the first one. So Canvas, one canvas to Canvas, one canvas to C2. That's great. Does canvas in the HTML is a second canvas, C2, and I'll give it a style also being width and height. Okay, now let's refresh that because I've changed HTML. We have two Canvas is now the deck of the same also, since I'm using Oba controls and I've attached all the controls to the canvas one here, or to render the ones DOM element that has an effect, but it doesn't have an effect on random or two's DOM element. If I go back to the controls that you can say attached to render a 2s DOM element. Okay, so now that has the effect and that doesn't. So when we use the other controls, which we'll talk a lot more about lighter, it's using mouse events on the canvas that you have attached it to. Render it to stop element there and put that back to one for now. Okay, Let's create some more canvases because we can have as many canvases as l computer will allow. Okay, So index Canvas 3 Canvas for. And instead of using IDs, I'm going to convert that to a class, B, class C. So I'm giving them all the same class. And now we'll use width and height to 100. Gone back to there, it's quite yellow canvases, 3, 4, 3 4 3 4, 3 4, 1 2, 3 4. Render a 1, 2, 3, 4. And down here in my render function, it's also update the renders 34. Remember go refresh. We have four canvases, or 200 or 200 will doing the same thing. Okay, and of course, you don't have to update the renderer at all. And now one of them isn't showing, okay, so there were four render is now and there were shown the same thing. Now, looking down here in the render is render function, we're telling you which seem to use and which camera we can have several different cameras. I'm going to add a second camera and attach it to render a two. So the second camera, it's going to be a different kind of camera. Camera equals a new three dot orthographic camera. Now an orthographic camera has different properties than a perspective camera will look at these in a moment. I'll just quickly fill in some numbers. We have something to work with. Minus two for Lyft, two for Rod top being two and minus two for bottom, I'm going to call it camera to camera one. Camera one's position is okay. Oba controls camera one that we use camera one. Now, down here Camera 1, 1, 1, and renderer 2 is going to use camera too. And I'm not seeing any errors in a tall script here, so that looks okay to go. There we go. Now render to use using Camera 2, which has different settings and we're getting some clipping. So I'm just going to position camera to, to also be in the same position. There we go. Now I can see it now you can see the perspective camera there has some perspective and the orthographic looks flat, so okay, looking at the documentation down here, our camera, this is called a perspective frustum. So the shape looks like a truncated pyramid. You've got a near plane, and you've got a file plane, and you got a width and a height. And width and height is used to describe the aspect ratio. Okay, so looking at the code perspective camera, if I hover over there, it tells me the different properties on aid. So its field of view aspects near and far. So aspect we can see we're using boxes here which have the same height and width. So aspect of one makes sense. If I change that back to a 100 by 100 and side that we can see that it looks squashed or say 100 to a 100 flat. That's the aspect ratio that we're looking at there, which is really describing that box. But I'm going to keep it to onboard 200, which actually is the same as one. So to square this number here is the new plane and the far plane. So the renderer is going to draw everything within this frustum dimensions here. So if that's 0.1, anything before 0.1 white beetle, so that'll be clipped. So let's just increase that to being two. And if we look, everything that's exist before too is being clipped, were also clipping everything after the far plane. So if I might define applying to and I'll put that back to point 1. We're only seeing the stuff that's close to the camera that is less than two. Okay, so I wanted to reposition those windows. So let's put that 2.1, Let's increase it slightly to 0.2 to 0.32.4. And you can see just the extremities getting chopped. Little bit, 2.52.6 and we go Anyway, I've been using 100 by default, which is little bit over-engineering. But you know, you can make that better if you like by using a smaller number. Just remember when things stock disappear in the same, you'll need to consider your near plane and you'll fall plane anyway. Now let's look at field of view 75. I've got here the default field of view is 50, but I've done 75. So let's put that down to 50 and see what that looks like. So the perspective looks almost flat law the orthographic plus might get even smaller like 10, but it's kind of zooming everybody. I'm going to have to move the camera out, a little camera out. Ten. There we go. And it's still clipping because I've moved the camera back so far, so I'm going to increase that to a 100. There we go. So it looks flat. But if I go backwards and I use a large number, like a 160, for example, Let's move the camera a bit closer for number one. Okay, Let's try 0.5.75.66. Perhaps going to make my knee applying smaller so it doesn't clip the close. So that's like extreme perspective. Let's put that down to maybe a 120 and move that back out. Well, that's playing with the perspective and the field of view. So those four properties, they are on the perspective camera. You can see more about that day if you hover over the top that will show you the basic documentation of it. They affect the frustum of what will be converted to 2D and drawn onto the HTML canvas by the render on. Okay, so let's put that back to the way it was before. That's good enough. So before at 1 110 camera, one position at two on the z axis, which actually results in a camera a big move backwards a little bit from the zeros 0000 because this cube as being positioned at default zeros 0000. Okay, anyway, let's now look at the properties of the orthographic camera. I'm just going to turn off default view there. Now I've used minus two to two and minus two. And orthographic camera is like a cube in space. There's no perspective to what? There's no field of view option. So the far plane dimensions will be exactly the same as a new plane dimensions. So it'll always look flat. And that's what we're seeing here in this second window. There's no perspective, it just looks flat. What do you describe the orthographic camera? You don't have to describe the aspect ratio. You just describe where the lift to the top and the right and the bottom is and that's what I've described here. My left is my honest to my rod is two units across, the top is two, my bottom is minus two. If I change that to 111 site, that is going to look a little larger in the view, which is good. Now I haven't described near and far plane there, but I can do that. My near plane will be 0.1 and my far plane will be 10. For example, if we go, Let's chop the box off a little bit. I've got camera position two, so I will do I'll try to there we go. I've chopped off the front side of the box. Let's jump off the backside of the box and we go anyway, so near plane, far plane of the orthographic camera. Now, what I'm gonna do is cry more cameras and these other views will also use orthographic cameras. And we talked down from the left and from the front camera, three camera for now, just copy those. Right now. I'm just going to copy camera two's position, which is just z. It will come back to that here, the renderer, camera three and camera for k. So if I like that small test case are looking at it and it'll different. After realizing the windows, we can see that those orthographic cameras are identical. I'm just controlling the perspective using the orbit camera. Now, let's change the camera positions of the orthographic cameras. So camera position two, I want it to be top-down. So instead, I'm going to use the y-axis. I'm going to lift the camera up to now because the camera will be lifting up. I know also need to pointed downwards to look back at 000 000. So camera to look at, I've got to say look at 000, 000, or I can say look at a new three dot vector 3 and a default being 000, 000, like that. Now, Camera 2 is looking top down onto the queue. Camera three, I'm going to look at it from the lift. So camera three, x equals minus 2. And also I'm gonna make it look at 000, 0, 3, and we get a camera, 3, 000, 000, 000, 000, 000, 000, 000, 000 as well. And us looking at it from a different angle and sine with camera for, I'm already moving back down the z-axis. So I'm looking at the cube from front on there. So we have one perspective camera and we have three orthographic cameras top-down from the left and from the front. I have an example of that code there on the website that you can use as it stands now? Yeah, my dad look a little more obvious that we're looking at that from different perspectives. I'm just going to change that object because a cube is pretty much the same no matter which way you look at it. Close that. And we saw is that using a box geometry, I'll use a three dot or a snot geometry like so. And I'll scale cube half Soyuz cube dot scale dot x equals 0.5. Let's do the sign for x, y, and z it, okay, so I've made it a little smaller and we can see we've got different things going on there, different perspectives. Now one final thing, if we look at the renderer, again, we're rendering the same scene every time we can render different saints. So I'm going to create a different thing called S2 and render a three will render S2. So up here, S2 is also a new same. I don't have any objects in my saying. So I'm gonna do that down here where I've added cube to the same. It's important to note that we'll get onto these further. And when we look at the object three day but an object or mesh cannot be a member of one scene. So I couldn't say S2 also add Qp because cube is now part of S2. So instead button Credit new cube, called cubed as a new 3D mesh. And I'm going to use the existing geometry and material. There we go. That's different. I'm not actually rotating. Q2, say not seeing it rotate, but I could to two, I'm going to just rotate one axis and we go anyway. You can say it's a different thing. Anyway, this starts to get a little more complicated now the scope of this particular lesson, so we'll look more about the details of what's actually happening here as we progress further. But now, the point of this lesson was to demonstrate the relationships between the same, the renderer and the camera. And the fact that you can have lots of renderers if you wanted to, loss of Sainz, lots of different cameras. You can have perspective orthographic cameras. You can all either hard-code canvases to the document and give them your own styles, or have a dynamically added, which is very common way of doing it. In the next video, we'll look at what's going on here in the animate function, okay, Excellent. 11. Animation Loop: Okay, let's look at the animation loop now. Now before starting this, make sure your scripts or back to the way they were and we finished grading the boilerplate. So that's index.html. Put that in, I've just pasted that in. And client Ts just copied that and select all paste client, yes. Okay. And that's what should be running in your browser. Okay, the animation loop, we're looking at the concept behind this function, okay? So in most three GIS examples, the function is called animate, but another 3D environments or games you may find it called the game loop. Intimate is good enough, That makes sense now and you animate loop. Everything that you want updated as your program is running can be triggered here. Inside D animation loop, there's these request animation frame function which calls itself again, which actually ends up that dysfunction just keeps looping and looping and looping all the time. Now it's using request animation frame. Request animation frame is a method that tells the browser that you wish to perform an animation and requests that the browser course specific function to update an animation for the next 3. So it takes a callback as an argument to be invoked before the next break point. So that's what we're seeing here. Request animation frame enemies. So it's just going to loop around in circles. Now, it happens about 60 times a second, but will generally match the display refresh, right? In most browsers as per the W3C Recommendation. So depending on your browser, which version request animation frame may be paused if it's running in a background tab or in an iframe that's hidden. And this is to improve performance or battery life, okay, on the MDM website, mozilla.org, we've got some information about window request animation frame. And just be aware that the animation will run faster on higher refresh rate screens. For example, if you're using an Oculus Rift, the refresh rate on that will be about 90 frames per seconds. So the animation loop or warm much faster. Anyway, let's look at example. The animation loop here is calling the render function. Now, if you have a 3D scene and you want it to be continually redrawing like that. And there's always something happening then having a render function be called inside animate is a good idea. So let's just turn that off. So what happens? Okay, renders no longer being called, but the animation loop is actually still running behind the scenes and about 60 frames a second. Okay, So let's put now the animate loop doesn't run automatically on this. I've called it. Okay, So animate down there, save that. Now nothing's happening. Animate actually isn't happening at all. Now, this cube rotation is done on the being updated. So if I want the cube rotation, for example, and I didn't want render, I can still call animate. And the cube rotation will be updating behind the saints. But if I wanted the screen to be redrawn, the native be calling the render function, which is actually just calling the renderer Render function. So once again, that's back. Now if you want updating. So the properties of a mesh like that, n d cubed, for example, just stays static like that. There's no need to call render all the time, 60 times a second. You actually just call it once. I'm just going to comment that out and just did a down here and actually not even call animate at all. And we'll refresh. And it's good already surrendered once computers no longer working hard. But I also have orbit controls and the Oba controls is still working behind the scenes. And if I press the mouse button down and move it around, the properties of the saner actually changing, but there's no render call happening, so we're not seeing the update. So that's one good reason to run render in an animate function, but you still don't have to do that. Orbit controls has his own vent. So in order to use, I wanted to put all the controls into its own variable. So const controls equals a new Oba controls, controls, dot, add event listener, change, render like so. Okay, controls add event listener, That's the onchange event. And every time that all the controls changes, we'll call the render function, which is down here. It's just updating the renderer. So save that. Now we've only called render once. So far. We have no animation loop, so I'm not starting it, but the Oba controls has change event registered, so now it's re-rendering every time there's a change to deal with controls. But the animation loop isn't continually re-rendering. So this is one way to improve performance when you throw a GIS applications if you need to, if you had a very heavy same, which was continually redrawing a lot of objects. So the examples that you'll see throughout the course will be a combination of either updating the renderer in the animation loop or all render only when there was a change, such as when the controls was changed or even when the window was resized. For example, here I'm still calling render in the window resize events. So far I changed that, it's re-rendering. But if I commented out that render function there and save, the canvas is not actually being redrawn here, but it's just being stretched because of the style bond the scenes. But if I rotate using Oba controls, it goes back to normal once again. And I go so only on update is render being called and that is actually just stretching the canvas. So, okay, so I often call render in the window, resize events regardless of whether I have an animation loop or not. But you don't have to do that. Let's just not call in their re-size event, re-enable animate. Turn off the first render and naval render and the animate function again. Now if I resize the window, it's still correct regardless of whether I call render inside the event listener or not. That's because render is being continually updated in the animate function which is being triggered about 60 frames a second. Okay, So now I will just put the changes of rotation back so that we see a moving. Okay? Now, if you're running an enter my loop, it's not absolutely necessary to run render in the re-size that event as well, depending on how big your scene, as you may see, a slight delay when resizing the window. It might not be a problem for you, but it's just a very small detail that I've noticed on older browsers that I prefer to actually call render and saw the resize event as well, even if I have an animate loop. And it's also since I'm now running the animation loop again, identity call render. It would tell me all the controls changes because the enemy loop is already calling render, so that it works already. Okay, So just one example where I didn't use the animation loop. I only called render on the first call and render whenever the orbit changes and also render whenever the window changes. Like so is in this program, there'll be a link at the bottom of the documentation, but it's quite a complex model. And when the screen is sitting still like that, There's no need to keep rendering all the time in an animation loop. So I only update the render when I used the Oba controls like I'm using right now. And also, if the screen changes size like that, then the item render is actually being called. And also with anything else changes such as you drag an object into the same. I need to render. There's not one. Okay, I re-rendered. Excellent. So there you go. Beware that that's an option you have. Okay, so anyway, how the code sits now is on the documentation page, faunal scripts, client here, client tiers. So we'll continue the next lesson from these scripts. So next lesson will be stats panel. And we'll look at this little panel here on the top left, which shows us our frames per second. And this is continually being updated in the animation loop in this particular example that's running here. Anyway, Excellent. 12. Stats Panel: Okay. The stats panel, that's this little thing on the left here, top-left shows statistics about L3 JS performance. It's very useful to know when we need to improve the performance of our application. And you can click it, you can see how many milliseconds between each time it was updated, how many megabytes It's using, and how many frames a second it's achieving. So I'm using the same script, how it was from the last lesson animation loop, and that's it running there. I'm rendering upon any change to the orbit controls. I'm rendering when the window resizes and I don't have an animation loop running just the first render when the application starts. So refresh. There we go. Okay, Now the stats module, you'll find it in Node modules go down to three. There is examples, GSM, libs, and in there is stats dot module.js. We're going to use that. So inclined to TS top. Okay, so I'm just going to hide the folder view so I can see better. So import stats from three examples, JS, libs, stats dot module. Once I taught a few letters and it guesses what I'm trying to say. I can just press Tab and it will fill in the letters for me. So important stats from three examples, GSM live stats module, my case, so we'll use it now. Go down your code a little bit and just before the animate function or do const stats equals stats, right? So press Enter and if we refresh now we don't see anything just yet. We need to add it to the document. We're going to dynamically add it just like the renderer in an earlier video. Document. Dot, body, dot, append, child stats, dot DOM, OK, Control S to save. Now top-left, that's else statistics panel. And we can press it and we're gonna see different things, but nothing's been updated in that yet because we're not calling the stats update method the best place to call that is in an animate function because you want it to be updated all the time. Otherwise it's not going to be updated. So what you can do, even though I'm only rendering when something is being changed, I can have the animate function and use the Request Animation Frame method there. And at the end, goal stats dot. Okay, So Control S to save. One more thing, I need to actually turn animate on because it hasn't been run at least once a year to put into the never-ending loop. Control is okay. Now we're getting stats update 60 frames per seconds. So the only real thing happening in solid and make function what now is status update. So if we click that, we can see 70 milliseconds, 22 core, 21 megabytes available. And I'm shooting 60 frames a second. Okay, so that's perfect. Now that's really all you need to think about the stats since I have an animation loop now, I might as well just go back to calling render inside the innermost loop. I no longer need to do that. All really that, that's optional. I saw prefer to do that because of older browsers, but we also get updated over time, so it might no longer be that relevant control S. Okay, so now my render stats are being both updated in the animation loop as 60 frames per second. Now, I use the stats in almost every three J is programmer, right? While I'm developing, you don't need to use it. Once your application is live. You can comment out all the status code if you wanted to, and you didn't have to import it anymore. But it's just very useful during development because it tells you early on The maybe you need to optimize something about your application. So another good thing that you can use with stats is if I turn on, say, the rotations there, Let's say hypothetically, this was actually much more complicated and I had quite a complicated scene and I was doing something which I was suspecting to be causing. My program does slow down. Instead of doing stats update like that, I can just monitor a particular section of code. So stats dot begin and stats dot end like that. And now it's measuring statistics between those two lines. So that is super fast. That's not a problem, but it could potentially be when your program gets much bigger. So that's the steps I will use the stats most of the time just like this at the end of my animation loop, because that's the most common way it's used. Now stats is used in almost all of the official three j as examples. For example, this one is the status. The status is on this page and I go stats, you can see the performance of this model is very good. This one starts achieving 60 frames a second. Now the 16 frames per seconds. So anyway, that's the stats panel. You import it like that, import stats from their credit, the stats, and then append a child to document. Excellent. And I'll be using a stats throughout all the examples in the course. In the next video, we'll look at the dot-dot GUI, and that's this panel on the right that allows us to manage the properties inside the scene using these user interface controls here. Excellent. 13. Dat.GUI Panel: That dot, that dot GUI is this on the right? This minimal user interface that you can use to interact with the scene. And actually it can interact with any public properties inside your HTML document if you wanted to. But it's very commonly used with three js. And you also find in most examples on the official three JS examples website. I've also used it in many of the examples as well in this course. So to get started looking at our code, I'm continuing on from where we left off from the last video, but the stat spinel, okay, if we look at three, again, Node Modules 3 in libs does another module in there called dot-dot, dot-dot module. We'll import that into our code. So client, There we go. Import GUI from three examples, J, S, M, libs that dot GUI module. Now it was having trouble trying to find that then, but that is the correct path. Now, the reason why it was having trouble finding that is because it could not find a declaration file for the module examples, et cetera. That GUI module, the type definitions doesn't come with three J S by default, and it also doesn't come with the types three JS that we've installed from definitely typed. So if we were to look inside types and then go down to three examples, libs, yeah, it's not there. So stats module D3.js as air but not that dog GUI. We're going to have to install this separately. So what to do Control C together, the webpack dev server, okay, so npm install at types slash dot GUI. And I'm going to save to do npm install types. That going, okay, Very good. If we now refresh and look at types, types, dot-dot GUI, there's the index.js for the deck GUI still hasn't found it now project yet, we're going to have to explicitly add a path telling our project which type definition file to use when it sees that path there, control copy that go into your projects ts config dot JSON and down here, right, paths like so inverted commas that will point to, I have it on my documentation here. Okay, make it an array down to levels into Node modules at types dot-dot-dot Kuwait. So if we go down to its client source, sources at the same level as node modules. So up into types, There's types and as Deck GUI that it will find it index.js. So there we go. That's that there were explicitly telling our project when it sees that path in any imports is going to use a type definition for that it finds in that folder that is relative to the ts config here, Control S to save that. Now to a client, it's now found it sometimes when making these changes, these things don't get found even after sitting in the correctly. So what you can do is press F1 and select Restart TFS server. And it will go and refind all the type definitions for all the imports that you are importing. But I didn't have that problem that time. It just happens occasionally. Okay, So Control S, That looks good. I'm going to run npm run dev again just to start the webpack dev server and verify everything is still running, it is very good. Okay, now to add the GUI to our application. So down here, I'm just going to add it somewhere in my document just after where I've added the stats seems like a good idea. Const and gooey equals a new GUI. So GUI dot add the type definitions are telling us what methods we can use when we type GUI like that. Do we don't add target object? I'm going to modify the cubes rotation manually. So cube dot rotation, the actual property of cube rotation will be x needs to be a string because it's going to use that as the name of the user interface control as well. The minimum value, which has been underlined there will be a 0 and the maximum value, I'm going to use math.pi times two. That's the same as saying 360 degrees cube rotations three, eula needs all its properties in radians. So math.pi times 2 equals 306 and degrees. So that's the ratings version of 360 degrees. Press Control S to save. And also, I'm going to stop rotating the cube in my animation loop. So that again, going back to the example, we now have a GUI, the top right there. And now I can rotate the cube manually on the x axis, like so. Now I can move more than just the x-axis. I can also move the y-axis and the z-axis. So the cube rotations x, y and z axes Control S and I go XYZ ID. So there's x is y around the y-axis and rotating around the z-axis. Ok, now, that is just very simply modifying a cubes rotation. We can modify the cubes position as well, or the cube scale. In some of the next videos, we'll do those kinds of things. But right now, I'm going to show you how to put these settings into something called a folder. So looking at this example on the webpage, I have an extra control down here for camera, but I've also got them under a little folder with a name called cube and camera like that, which we can toggle on and off. So I'll show you how to make those. So instead of adding all our objects to gooey like that, we can do const kube folder equals q0 dot Add Folder cube, like so. And then instead of adding all my controls to GUI or add them to the kube folder instead, like so. Now I look back at the code and I go cube and there's acute folder that we can toggle on and off. Now it's not opened by default. So we can say kube folder open, save. Now when we look at it, it's already open. So after refreshing, it's pre-opened. Let's create another folder. Const camera folder equals GUI, dot add folder, camera, camera folder, dot add camera dot position on changing the camera's position. Now that's the target of this control. I'll change the SSID on the camera position and once again Min or make it 0 and maximum being ten, like so let's save that and still good at camera is closed by default, so I haven't opened it, but I can now move the zed axis. And now cause camera was already positioned at z equals to. If we go back up into the code here, camera positions at equals 2, It's preloaded, already set as two, but now I can just move it like that left and right, manually controlling the cameras it using the GUI now. And also I will make it so that the camera folder is open by default. I go now it's opened by default. And also with these controls, you can make them larger like that if you needed to. Excellent, Okay, so remember that when you import deck GUI module, like many modules in three js, they might not be a TypeScript definition for it. So your options are to try and download one from definitely taught using at types of slash name of the module. Or you can make a type definition yourself or find it on another GitHub project somewhere. But whatever you do, you have to tell your ts config where the location of the new type definition should be when it finds that path in your code. So that path, three examples. Jason lives deck GUI module in my code is written there. And when the IDE and TypeScript sees that it's going to go to tears. Config is going to use the index.js that are fines there. So there you go. Client ts is code as it stands now, is on the official documentation page. Here under final script. Also with the official boilerplate, I have created a Stats Can we branch? So if you were to download the boilerplate and cd into the folder, you can type git checkout steps GUI, and the boilerplate will come pre-built with the stats panel. End the GUI, just like what I see in this image down here. Okay, Excellent. In the next video, we'll start looking at some more of the core of three js, and that is the object 3D. Excellent. 14. Object3D: Object 3D. Now, objects 3D is the base class for many objects in three JS. It provides methods and properties from manipulating objects in 3D space. So any objects and three JS that can be described in 3D space derived from the object 3D base class. Okay, So things like the same, a mesh, camera, hole and other things. Cube camera, bone, a line and light points are all derived from one class called objects 3D. In this video, I'll demonstrate some of the most common thing that you'll do with objects per day, and that is rotation, position, scale, and visibility. Okay, so using the existing code leftover from the last lesson where we added the GUI. If we look at the cube here, QB equals a new 3D mesh. Now three mesh, if I go to the definition of that, extends objects 3D. So it gets all the same properties and methods of objects 3D plus a few other things like a geometry and material and creates a read-only property is magical is true. But going to object 3D, we have all the things that are common to all objects. Three days, a position or rotation, quaternion, scale, model view metrics received shadow, rust and cold render order, all kinds of things that all objects 3ds have. So remember the same is also derived from objects ready, Go To Definition extends object 3D and this mesh where I'm adding the cube to the same numbering seen dot add the cube. So objects three-day has a method called add. We can add another object 3D. Anyway, let's do some more things. Are these cubes demonstrate what a find the position and the scale and the visibility. So we already have rotation. What we're gonna do is add some more folders. I'm going to put rotation into its own folder. First cube notation folder. I'm going to call it rotation, and I'm going to do cube rotation folder, dot add and open and a cube rotation folder now just to so it looks like I need to add the rotation folder to the kube folder. Okay, kube folder, Add Folder rotation like that. And the k cube rotation that's underneath the kube folder there. So we'll also open up the kube folder open. So it's pre-opened. Just let the rotation photo and there we go. When it's refreshed, it's auto opened. Now, I'm not going to use the camera in this example, so I can delete that. Now I'm going to change the cubes person, which is an object's ready property and create a new folder for that as well. Qb, position folder, physician, save that. And that's how it looks. Cube with two subfolders, rotation and position. Now, I didn't change the position here. So position, position, position, we're changing the cubes position x, y, and z. The minimum will be minus 10 and the maximum being 10. So we're going to move it between minus 10 and 10 on the x-axis when I use the slaughter and do the same with the y-axis and the z-axis. All right, Good. Save. And we go. Now if I change the cubes position dot x will go left and right like that. Y is up and down, and Z is forwards and backwards, like so. And we still have rotation from the last exercise. Now, we can also add scale. Scale is an object's ready property. So everything which derives from objects ready get scale, that includes the mesh, mesh there, which I credit as a cube upon the geometry and material, we will discuss geometry material in the next videos. Similar process or copy or call it scale. Scale folder. And I'll change the cubes scale. Now, when we press the dot after cube there, IntelliSense gives us a whole lot of suggestions of the available properties and methods. When we look at the little description here on the right, it tells you where that method came from. So the copy method of cube comes from objects, read a copy. So it's a clone, clear, children cast shadow attached. Most of these properties and methods come from objects breathing, not all of them. Dispatch events comes from something else called the Event Dispatcher. Geometry is a property of the mesh and et cetera. You can see that. So most things are from the object 3D. So if I look at the scene, it's a very similar thing. So I've seen dot add most dose things are objects 3D except the add event listener. They're comes from Event Dispatcher auto update is a property of scene background as a property of same cast shadow is a property of objects 3D. So the scene also derives from object 3D. Anyway, let's look at that scale. I will fix up to being between 05 as the minimum and the max. And we'll first see how that looks. Let's refreshed. They'll go scale. It's defaulted as one. So it pre fills in one for us. It also position was defaulted as zeros, so it feels and 0 for us if it was in the slaughter, depending on whatever you set the Min and the max to be. So scale here Let's look at scale x makes it wider, or scale 00 that let's look at y. And zed makes it really easy. When we did that and zoom out a little bit, see what's getting on there. 54. Okay, let's see what happens. We do minus numbers, minus five, minus five, minus five. So x, it just mirrors the other direction, minus 5 all the way to five and default is one. So now, to help visualize the changes in position a little easier, we can add a little helper, two or three J screen called an axis. Help them. Okay, So up here seen dot add, add comes from objects 3D add a new dot axes helper, and we'll give it a default value of five being five units can fall is now x is helper. We go to the top definition, extends line segments. Go to definition. It extends line. Go to definition, extends object 3D. So x is helper, also has all the same properties or methods of objects three days. So if I press dot dot, we're going to get all these objects street a methods and properties as well. So objects 3D is a base class to use, but almost everything in three J is anything that can be represented in 3D space. Okay, so let's save that and see what it looks like. Okay, So now what it's done if I just rotate that slightly using the orbit controls. Strawn, three lines that are five units long. So that's the y-axis. The lines point the positive direction. So why positive? If I move it that way, makes the cubed 0 upwards. The red there, which fades out to orange, is positive x-direction. So if I move x and a positive direction, or the negative direction, and then we've also got the zed, positive or minus. So you'll note that I'm position a camera, which is an object's Friday at position two. So if I refresh, the camera is actually at z equals two. So it's not as 000 000, it's, it's positive two. So it's down the blue line there. So there we go. Camera top position dot-dot-dot equals to the cameras also derived from object 3D. So it has all the same things as objects 3D. Okay, So anyway, one extra thing I'll show you about the object 3D and the same, since the scene is derived from objects reading and the mesh is also derived from objects 3D, let's say a cube there. And render expects a three objects three-day to be passed in, we can actually render the queue instead of the same. So save that and it looks the same. But moving the properties doesn't really change anything because it's not showing us relative from the scene, which will make a bit more sense in the next video. So if we just keep with the standard and create a scene object and add allow objects to our scene. We then see changes to our objects relative to sing. So we're looking at seen 000, 000 and which the position of our cube, which looks different from the perspective of the scene, rather than from renewing the cube, nothing really looks different and the way through make more sense in the next video. And another thing I'll show you with the GUI just here, is that sometimes when you're sliding, you want a little more, maybe snap to a position a little easier. To also note too that it's sunny drawing integers up there like 0, 1, 2, 3, 4, 5, 1 minus 2. If we type in position there, we can also add a step perimeter. So I'm going to add 0.1, step 0.1 and do that down here. Save that. Now, when I move the object, it's drawing it as a float. And it's pegging 2.3, whatever. It's not in-between. So let's say Step 2. Now. Let's look at that. Now. Moving step two. There we go, because it's not a float, it's just printing the integer. Okay, Now let's add a visibility option to the GUI is going to add it to the kube folder. Other than any of the other folders, kube folder dot add target cube. I'm going to add the visibility there or the Visible property there from objects ready, but since I'm not going visible dot x or visible dot y cube comma and put visible. And so the property name, their acute folder, add Cuba visible network default to showing true since it's already visible. Ok, and there we go. That's the visible toggle option. Already there. Now continue to keep on and off. So you can do that with any objects 3D, Okay? And it can move it if you want. Turn it off. So visible. Excellent. So all that code as it stands now exists here in documentation. How finished it off? And in the next lesson we'll look at the object 3D hierarchy. Excellent. 15. Object3D Hierarchy: Okay, We'll talk about the object 3D hierarchy now. So the scene is an object 3D. You can add other objects 3ds to the same, and they become children of the scene. The scene itself is derived from the objects really buys class. If you rotate the scene or scale to scene or translate its position, it will affect all of its child objects. Now, normally we don't translate the same position or rotated or a scalar, you just leave it as defaults. But anyway, you make an object 3D, a child of another object 3D by using the parent's add method. So seen dot add cube, the cube is now charged at the scene. So when you type console.log seeing for example, and we'll do that in the browser. We can sit as seen here in the console, seen children, he says to children and access helper and the mesh and the axis elbow. Okay, So anyway, so you can also add objects released to other objects or eddies that are already parlor seeing any changes to the objects ready, such as position, scale rotation will affect all of the children under the same parent equally. So it's possible to create a hierarchy of objects release by continually adding new objects to any existing objects. So a seen object one, object two, and an object three. So I could add object 1, 2, and 3 all to the same or add object to object one or add objects free to object to and create that hierarchy. So in the example here, there is a red ball and now it's attached to the scene, but the green ball is attached to the red ball and a blue ball is attached to the grain ball. So get this code into our projects so less than scripts, the client index.html there, we're adding a duty to the body and a style for it so we can just copy that whole file there. I've copied it to clipboard now, put that into index.html and just replacing a completely control S to save. And with the client, I'm just going to copy that completely as well. Put that into client select all control, the control S to save. And that will now be updated in the browser because I'm running npm run dev. Okay, so the red ball there has been added to the same edited at position or go up to the code objects. One is the red ball. I've added it at x equals 4 000. So the scenes there are 000. It's actually about here somewhere. I don't have an accessible for that. Actually, I'm going to add one right now. Seeing dot add new three dot texas help our five, and that will default to being zeros 0000. For zoom out there we go with an axis help are there at 000, 000 in the scene, I've got a red ball of x equals four. Now, this green ball is a child of the red ball. And if I look at the code that's object to, I've also added a at x equals four. But because object to was added to object one, object, one object to its world coordinate. Here, the green ball is eight, but it's local coordinate reference its parent, which is the red ball, is for looking at the blue ball, which is object three. I've also added a at x equals four, but because object three was added to object to, its local coordinate is 4, but it's world coordinate reference, the same position is 12. So that's a common confusion for people who don't understand scene hierarchy is that this local coordinate and a world coordinate for your objects. Now often you only add your objects to the scene. So we're seeing can have 20 objects if you wanted in their local coordinates would match the scene coordinate because they'd all just be direct descendants of the scene. We'd like here with the red ball to local x equals four and x equals 4 is the same because it's a child of the same. Okay, So this slide on the right up here helps to demonstrate that further. So if I adjust the exposition of the red ball because it's got a child and that child, it also has a child. It's going to affect green and the blue balls as well. So if I move it along like that, it's moving the whole lot because the grain is a descendant of red and the blue is centered and grain, if I move just the green ball here subject to, it's only going to affect the green and the blue. If I move the objects three, which is a blue ball, it's only going to affect the blue ball. And take note also how when you affect this, the local coordinates, each object doesn't change because it's, the local coordinate is referenced its parent. But the world coordinate, because they are several hierarchies down, changes quite significantly. So if I change the x position of the red ball like that, we can see that it doesn't affect the local coordinates of the grain and the blue, but it does affect the world coordinates. So the same thing with rotation. If I rotate the red ball, it's affecting everything. If I rotate the green ball, just a green and a blue. And if I rotate the blue, justify it, I can also change the scale, which I just scale the red. It's affecting the whole scale of everything. It's stretching all of them. By default was to change the scale of the grain. Then it just specs those two, or just a blur. Now because they are all slightly different scales, it's still affecting the others regardless, the blue was a child of the green and the green is the child read data and have to create these kinds of hierarchies, a sophisticated 3D model that you create using Blender, rather 3D program. I'll end up probably being hierarchies such as an arm and a hand, and fingers on a character will all be situated in a hierarchy. You can change the whole model by changing the rotation of the position of the top object. Or you can change the length of a finger, perhaps just by changing just a finger. But if you change the parent of all the objects, it will affect everything equally. Okay, so looking at the code, the things to take note of. Really that there is object one, object one was added to the same object to, it has a different color, which is green in hex, object T2 was added to object one. Object s3 has a different color, again, that's blue. Objects three was added to object to. I've also added their own axis helpers. So objects radar add its own axis, LPA an object to add its own axis Elba. So object to at this point here actually has two children, one being the axis helper and the other being objects three. So let's console log the same, console.log same and press F2 to open up the developer tools. Seen children play. So disordered has got four children. There is the extra cell, but two lights will discuss lights in later videos, plus the mesh being the red ball there. The mesh, the Red Bull has two children, has its own axis helper plus the green ball, the extra SOPA, and that's the green ball. So if I look at the green ball, it has two children and access alpha plus another mesh. So access helper and the mesh being the blue ball. And the blue ball only has one child and that's an axis helper. That's that one there. Okay? Now looking at these meshes, you can see that they're all actually objects three days. So they have different properties in them like position, quaternion, rotation scale. Anyway, I'll let you look at that in more detail if you want. And also in the GUI, I'm just affecting the exposition, but most, but you could experiment, for example, I could change the Y Rotation stead of each of these file. Let me go and close that. Now this change to y rotation as moving like that. Now let's try the other one. And there we go. And it comes right around the exposition of the first one and the exposition of a second. The exposition of this. Everything is relative. So that's the hierarchy of this particular example. Looking at the local position and the world position to get those properties. When you get an object's position or rotation or its scale, it's always local by default, so it's local, reference its parent. And most of the time an object is going to be referenced the same. So it's going to make sense. But when you try to get the position of something that is a child of another child, the world positions possibly the values that you're going to want to read. So if you want an object's will position, you create a new vector 3 and then you go Object, get will position, and you pass in that new vector 3. That vector three will now be the value of the object in world position. Okay, so looking at the code down here in the animate function, I'm actually just running that out to the debug in a text in the DOM. So we'll look at that debug document.getElementByID debug one as HTML development. So that means when I press debug dot, I'll get all the methods and properties of the HTML development. So in a text is one of those. So I can walk in a text, read. So if you see what is going on here, that is what is being written. Okay, so object position dot x, I'm just writing that out to two decimal places. 4.02, object will position X2 fixed. So object will position object one, get the wool position. So I'm down here from object to object two and object 2 will position objects, reposition objects s3 will position. So we can do the same things for the world direction, the word quaternion or the world scale, if you want to try those things out. Anyway, objects 3D hierarchy can be potentially confusing if you've never considered that before. Anyway, in the next video, we'll start looking at geometries. Excellent. 16. Threejs geometries: Okay, so let's look at geometries in through JS to start off, copy the start scripts. So index.html, the only change to this index.html from the last lesson is the size of the height here. So you can either copy the whole lot or just change the height to 310. This is making the debug box slightly taller end client Ts Copy to Clipboard and select all control V to paste Control S to save. Now I've started the webpack dev server using npm run dev. Okay, so it's the cube like we've seen so far. Many of the lessons when I created the mesh are credited the mesh using a box geometry and it just describes those points. Seeing that look a bit like a cube. If I go to the code where it says cube equals a new three mesh, when you create a mesh, the constructor needs some kind of geometry. Now the geometry that you're parsing has a base class of buffer geometry. All geometries in three js are now buffer geometries since Release 12, 6, there used to be a different kind of version of geometry in three JS, which was easier to work with. It would store all the points in the geometry as three vector 3s, which was quite intuitive to work with. But here is a note. This is a super efficient class, but geometries because it saves all the data on buffers. It reduces memory costs and CPU cycles. Okay, so the code cube, because the new mesh box geometry, box geometry up here of credit as a new three box geometry without any parameters, okay, So box geometry is one of the many predefined geometries that you can get with three JS. If I look at the page again, here is a list, box geometry, circle Geometry, cylinder geometry, geometry, edges geometry, et cetera, of demonstrates some of these geometries in the video, for example, sphere geometry, we can click it and we'll go to the official three JS documentation on it. Now back at the code for the box geometry lock, all predefined geometries and through GIS has a bunch of optional parameters that we can pass in that question mark after the name means optional. So either be a number which or just left undefined. So for example, one for the width to the height, three for the depth, for, for the width segments 56, it still looks like. And that's what that looks like. So that's the new geometry that we credit. The mesh froms to the cube is now Geometry made up of that shape. All right, now let's just put that back to the way it was before. So it's much simpler to look at. Now, I'm going to console log the geometry and we'll log the box geometry there, Control S to save. Now, open up the developer tools, press F 12. And if we look through box geometry here, go to attributes position array. We can see all these numbers here represent the points of this cube. So zoom in there and look at it a bit like that. The 0 and the one of the two actually represent the x, the y, the z to x, y, z, x, y, z, etcetera of each of the points. So 0.5.5.5 would be this vertices just here. The next one is 0.5.5 minus 0.5 would be the bottom vertices down there. Next, 1.5 minus 0.5.5 would be that verticies up there. So starting here and going down, they're drawing up there, and then it'll be going down there again and cetera, all the way to the end. Okay, so that's how a buffer geometry stores its points that make up the shape of the geometry. Okay, so now we'll add some more controls to the GUI, which will allow us to dynamically modify these parameters that we can pass into a box geometry constructor. Okay, so scroll down here. There's this constant cube data variable. So uncomment that I'm using control forward slash while highlighting the text and an uncommented a whole lot. If you want to comment a selection of texts, you can do the same thing, control or slash. It is like a toggle, like that. Okay, So Q properties folder down there and here it needs a function saying regenerate box geometry. That's it just here. And that's good. I'm not seeing any problems in the code there, right? So what's happening for the new folder called cube properties thought I've added it to the kube folder and named it properties. It has options to change the properties of the constructor such as width, height, depth, width segments, segments in depth segments. So each time I change one of these properties using the onChange method here or run regenerate box geometry, what we need to do is generate a new box geometry each time, dispose the existing one. So cube dot geometry is the one that was first created. Dispose it So it's free from memory. It says disposed as the object for memory, you need to call this when you want the buffer geometry removed while the application is running. And then we set the cube geometry to the new geometry that I've just credit just here, using the new cube data values. Okay, so note how the GUI or changing an object here, and that's the object here. And then from that object, we create a new box geometry. So box geometry, once all of these properties I'm using cube data width, height, depth, et cetera. So let's have a look at that in the browser. Okay, so that's reloaded. Now. Now these rotation position scale were there from the beginning. The new one we've got is properties. So if we zoom in there, we can change the width like so. One all the way up to 30. Same height and same with depths. And then width segments. Default was one. And I go. Segments and depth segments we go. So that's a cube with a much larger buffer geometry behind the scenes. Okay, so now perhaps you're asking about this width, height, and depth here, how it makes it bigger. We just looked at scale when we did the object 3D lesson. And scale does almost exactly the same. So I'm changing the scale x there. I'm changing the width x, so it looks the same. But actually what's going on is different things upon the Saints. Okay, so put that width back to one and scale back to one. All these rotation, position and scale, they are part of the object 3D base class because the mesh was an object 3D, they are transformation matrices. What they do, they are an extra mathematical equation that is applied over the geometry to change the shape. So here, position D underlying geometry doesn't change, but the transformation metric is put on top of that, which moves the cube like that. Same with rotation, extra mathematical equations to change the underlying vertices, but the actual geometry hasn't changed, so we still do that or at width segments, etc. So to look at what I've just been describing in a little more detail. Go back to the code. Scroll down to the bottom, and we'll uncomment this constant debug as HTML div element. And then we'll write the cube dot matrix to the screen. So the cube matrix is a three dot matrix for object and it consists of 16 elements. Okay, So save that. Now we'll see what the metrics of the cube looks like on the screen. Okay, so that's these numbers down here. So when I change the position of the x on the cube here, we'll see that the matrix changes like that. So it's changing that one down there, but change the Y changes a different one. These are the elements which relate to the position of the object. Is it? Scale is similar. So we look at x, its changing this here. So all the vertices related to x are being multiplied by 1 at this point. But if I change that, all the vertices which relate to x are being multiplied by 5, et cetera, or now minus numbers. So if we were to look at the box geometry, again, the underlying geometry hasn't changed, but the transformation matrix is multiplying whatever those values are by 4.5 at this point. So we look at attributes, position, array, all these points, they haven't changed from before, that the same. So looking at transformations again on Wikipedia, this is good pageant transformation matrices in Wikipedia, there's a link at the bottom of my documentation for it. If you scroll down, we'll get to this image here. And if we look more closely at it, we can see that there's an object with those points in here. We're not applying any transformation matrix to it. But here this Translate, which actually means move. There's the original object and we translate all the vertices by a certain value. This is a scale transformation. It's making a bigger a rotate transformation. All the points are being rotated around a point. A shear, shear and y-direction reflect about origin, reflected by x. Now, we don't really have to worry about the mathematics behind that. Three J S is doing that for us. So when I'm changing those values, three JS is doing it for us. But that's what it's doing, is changing the transformation matrix, not the actual points of the geometry. Now, position and scale are quite easy to imagine. You can see clearly what element is actually being modified. Rotations a little more complicated. As you can see, it changes many of the values and we don't really have to worry about the complications because three J is the dominant force. That anyway, now to go back down to this properties, when I changed the height or depth of the width segments, we're actually changing the underlying geometry and not the metrics. So if I just leave that matrix as it is right now, with all those different changes, it doesn't really matter what they were all change the width of this box. Now, it's going to regenerate a new box with new points. So there we go. Now, I'm going to have to redraw box geometry, their attributes, position array. So all the actual underlying points are now different, like so. And if I minimize that and do it again, updated, Let's do it again. And attributes, position array, I'm going to say the numbers are all different. So what you're seeing here is what a geometry is about. It's about all the points that make up your object that you see in a 3D scene and looks at before. There are lots of predefined objects that you can choose. For example, a tourist geometry be like that, but you can also use a three-day program to create geometries such splendor, which is very popular. And I'll show you some examples of Blender throughout the next lessons. Anyway, let's look at some more geometries. Okay, so if we go up here further to const sphere equals a new sphere geometry. Now, sphere geometry as a Min credit yet so scroll further. Const sphere geometry equals a new three dots. Via geometry. Sphere geometry also has some methods and properties that we can modify, but instead of doing that directly will enable the controls in the GUI. So let me go const sphere data. It's a custom object and I'm going to use to store variables which I will use in the sphere geometry constructor to there the controls. So credit a new sphere properties folder called properties, added it to spear folder. Okay, so radius, width segments, height segments, and I need a function regenerate sphere geometry. Is there any changes? It will regenerate the sphere geometry. So we'll create a new three speed geometry using all those properties. Dispose the existing one, which is part of the sphere mesh and replace it with the new geometry control is okay, so there's a sphere just over here. There's a sphere bolder with properties in it, the radius we can make it bigger and smaller. So remember, we're changing the actual geometry. We're not changing the metrics. Yes, so we'd segments, height segments phi start. Now, that makes more sense when you reduce the foil length. So if I do that, so phi start and I go, let's just put that back. Now. Theta star and theta length makes more sense. If you reduce the length, we're going to see to start Theta length. Excellent. Next one, Go back up near the top again, icosahedron geometry. Let's scroll down and go. Icosahedral geometry equals and U3 measure of the icosahedron geometry. And then seemed dot-dot-dot icosahedron. Now I'm just going to move the cube position x across by five. So the icosahedron when they'll be drawn at 000, 000 by default. So the cubes of five, the sphere is at minus five and the icosahedron will be at x equals 0. Okay, Scroll down. The icosahedron requires a lot less parameters and the sphere, once again, onchange, regenerate the icosahedron geometry. There we go. Control S to save ME got three different geometries there. So the icosahedron properties radius, detail. Now it looks like a sphere as well. It just draws the sphere differently than the other sphere, which I'll make slightly larger. The icosahedron will lay out the triangles using a different method. And the speed geometry will lay out the triangles. You'd like a square anyway, you'll see that you can make them really small. You can reduce the width, segments and segments and be left with something that looks like that detail. And that's the most simple icosahedron. Okay, so there's a couple of examples of the inbuilt geometries. They're in 3D that you can experiment with and you can try out a few of the others if you like, but I'll introduce a few more as we progress as well. Okay, so if you want to read more about mattresses, a good link is the official three metrics for documentation here it says, this allows a Vector3 representing a point in 3D space to undergo transformations such as translation, rotation, shear scale, et cetera. This is known as applying the metrics to the vector. So anyway, next, we'll start looking at materials. Excellent. 17. Materials: Like I said in his course, we're gonna look at the material and women credit mesh. We also passed in a material. Now I'm using a mesh basic material, but the mesh basic material inherits from a nice class called material and that sit here. There's a material based class and all other materials there, several of them. We'll go through some of these in the next few videos they all inherit from materials. Does this video show you many of the material based class properties? What they do, and we can see them here if I just show the until the sense I can see. It's quite a few things showing up there. Most those come from the material based class. But since this material is a mesh basic material, we're getting a few other things there, so we'll just look at the material. But he's now. I couldn't declare this material as simply a mish material like that. You can't use the material based class directly as a material. It must be something else, and the measure basic materials just a good place to start. But we'll talk about the mish basic material in the next video in this video. It's a better material base class end of prepared code for this lesson. So let's make sure our index and client are the same in the documentation as a start code. Just replace your disk. Klein indexation Mel with this and for client source. Client client ears. Just coffee that and replace soul. There you go, and when you save it, it should look like that. There are five geometries. I've had it. So there are geometries are new geometries box Fear Aiko's ahead. John that had plain and tourists, not geometry because they're slide down and into our gooey here. That material folder. It's a naval, the transparent and the capacity never look what those to him. Five. Now capacity doesn't do anything by itself unless you enable transparency. Okay, now we can change the capacity and you can see what's going on there, since this is a wire frame and we can't really see the full effect of a passage E. What will do goingto material up here? And we'll just remove these two sittings here likes a mish basic material without any parameters and refresh that the material based class doesn't have any options to change the color, but we have transparency and we have a capacity. So now we can actually see what's behind by changing your capacity. Now I'm using the gooey to change the capacity. Here we go is not three Js, but it's just very useful tool for us as we're learning. If we wanted to change the transparency in the A pass ity without using a gooey like with all material properties, you would just right appear off to declare the material material dot Transparent? Yeah, with a little bit of help text, he cools to room and material dark opacity equals 0.25 There's a range between zero and one . We look at opacity. The default is one which is full of Pass it e. And if we refresh that and we go, it's 0.25 transparent already making save a haunt. But what issues they're going, there's many properties we can change. Then we'll use the Gilead go through several autumn now for this next one, we're gonna look a depth tests and depth right, and we'll also use a different kind of material, the mesh normal material, because it will help us on this in a little bit of, I'll discuss the mission of the material in another video. Okay, so that's the mesh normal material. Okay, so the depth test here show the depth test is doing. Take notice. Blue Line Coming out of this geometry here, we can see that it's coming out of the geometry. If we turn off depths test. There is no longer any test in the distance from the camera being calculated. So it's simply just drawing that geometry with his face is completely over top of the blue line, regardless off how far away it is from the camera and you can see here, depending on the render order. This cube was credit after this sphere, so by default it's printing and on top. Now the depths ride here. The difference Twin using deficit right and depth test is very much the same, except this blue line is still protruding from the correct place on this geometry. Here, sort of. His depth test is ignoring multiple materials because this line has different material things in these objects here that I've credit and deaths right is only affecting just the material that have crowded the one example where I did actually use. This technique is here in this project where we can see the floors in this house here to find open up, three debut properties. Scroll that up. I have a depth right option here. And that just changes how the screen was rendered because actually want to see those floors being rendered through the transparency as well. And that's why I used death, right? It's up to you the combination where they use one or the other. It's just a preference, and I do slightly different things. Okay, The next one was looking out for test material dot Alfa test and when it changes is gonna be a date material for us. So Owen comment that as well, we'll discuss this in a moment. So our fittest let's have a look al fittest. Save that. Now Al fittest is about deciding whether it to render an object if it's higher or lower than Europe. Ass ity sitting and to demonstrate. This seems to work best on mesh basic material, no, on mission. All material. If I refresh that, and if we just lower down the opacity as we see nothing's happening because we don't have transparent ticked, but if we change al fittest, it won't show it. If it's above that number there, where is it Will John if it's lower? I've never used this in the real world, sir, But he notes there and ignore sees it was transparent enable. Let's look a visible. If, for we go, it's pretty self explanatory. That's very similar to changing the visibility of the geometry. I mean, the geometry still exists, but we just can't see it because the material is invisible and saw it. Options saw it. Let's uncommon that okay, and we're updating material again when we change some material properties we need to set a flag needs update so that next time it's rendered the material properties we reset in its memory and more specifically, it's to do with anything that needs to be updated with jail. Waas. You don't need to set this flag when you change depth, test or depth right? For example, Tony, some of them, if you're unsure, it doesn't hurt to actually do that. You shouldn't do it all the time cause it affects performance slightly. Just do it whenever you need to, so I'm doing it here. Update material update material now. Options side, front side, back side, double side. Let me just show you what they do very fresh there. It's quite obvious on this plane just here. Backside. We can't see it now. It's still there. If we just rotate around. There we go. We're seeing the backside off the plane. Underside has disappeared. Still there, we're gonna set, and then you can do double side as well. So by default, it's front side, so you can't see it from that angle to sometimes. If you create a plane and you can't see it, maybe it's just facing the wrong way. The focus front sort and troubled with that with a different object. It would be best to use a different material, such as a normal material, if we refresh that. Okay, So backside, Russia's Seaney inside off that material now it's quite good If you want your camera inside an object, Doctor, I'm inside this because that he drawn now and I'm outside it and all I can say is the inner wall. Same thing with the tours. No, there. I'm saying Lee in a wolves. This is a good rendering technique. If you want to show say the inside of a tunnel from the outside on the Cube Here is a good one, so we can always see what's happening inside the Q. Because we're rendering the Cube. Using the back side and double sought is unnecessary. In this case, simply drawing those are the walls unnecessarily. That's why front side is Defoe pacer now to describe what I'm actually doing here in this line here. When we change the options side here, depending on the value and the drop down, it will sit three dot front side, which is actually a zero. This is a constant which actually equals zero, and this is a constant and this is a constant in numbers, and three Js needs those to be numbers. If I was to sit material dot side a cools grey dots front side, that would be OK, so three material outside would equal 80 in the material properties. But when you change that using the gooey, it will convert it to a string. This is the behavior of the gooey that would be ever written because the hasty male specs is any value in a drop down the string. So that's what's actually happening here. The three Js material properties who want to be numbers. That's why I'm doing that just to demonstrate that if I commented out and I refresh that I changed the side being back. So we're not getting any changes, even though we're actually changing aside in the material properties. It's being saved as a string and not as a number. So that's what that line is doing. Okay, so backside, there we go. So if you're using any drop, dance inside your gooey and it doesn't work for you, perhaps just try converting it to a number as well. There'll be another example of this No later video, and also the code as it stands now isn't a section here. Final code source. Client client tears again. Just copy that into your project and refresh it. Next video will discuss the mesh basic material 18. MeshBasicMaterial: Okay, let's look at the mish basic material. You Congrats the start code for this lesson Source. Client Client ears Company Clipboard Source. Clark Lantus and replace. That's what it looks. Look, we have a new folder here. Will start adding things toe for the mish basic material to the 1st 1 That's great A color and kulum. So down here now mesh Basic material. Photo without a color. We have a missing data color because the material doc Allah dot get hicks and on change material dot Cullen said Hicks. Donna Collar to string, replace. If I press save and we refresh, we can now change the color of their material like so black or what grain? This girl here was really meant for hate. Email colors, not three Js colors. Hey, smell colors air for matter to be like this, like your reserve. If it's serious, sure, that will be grain. They are G B. But if you pass in a color to a three Js color, you would for meddling. This o X 00 ff, Syria's O X means hex, and you can update three Js colors using that for it so it does a hash on the hay smell version, and it's an O X on the three Js version. So that's what I'm really doing here. Is taking the value from Donna Color convert to a string, replacing that with that material dot carla dot sit Hicks that's had a change of color using the gooey It's the next thing. One of the great things about the mish based material is that you do not need to sit lighting in your scene. We haven't talked about lighting yet. We will in a later video. But as you can see, the color is pretty much just a flat color. Without shading. That's what you get with mesh basic material. If your credit a larger project such as a game, you'll approach lighting and text oring, such as materials in different phase of the project. So often, when I'm developing a project, I'll just go straight to the three mesh basic material from the beginning. And just use that because I don't have to worry about lighting yet or any materials. I just I just want something, And even then, as you saw earlier, I will also use the mesh basic material in wire fry murder to refresh that I select the color and I also select wire frame like that. And what you've been saying is grain wire frame like that. Now we don't have to use the Gilly Teoh set those as you know, we could have just septum explicitly when we cried in the mesh. Basic material like color and y frame, it says in our wakes, not a hasty car. If you try to do a hasty mail, it tells us there's a problem. So refresh. There we go. That's what we used to sing. Now that's what I'll start off with. That's very informative for May. Get rid of that. We don't need it anymore. Now that we have it now. Gooey now the next one for the goalie is the wire frame Law in wits is a very good chance this one do anything for you. Three. Fresh doesn't change anything. Line with this now Deprecate ID and open jail. Don't expect that to work. I'm just having it here just to bring it to your attention. We can safely to signal that one wire frame line weeks. You don't really need it. We can just comment that out. We will discuss Thika lawns in the light of video. Now with mesh basic material. What we can also do is a sign of texture, so constant texture. We'll use the text you later Class load image grid material dot map equals texture. Now, alongside the resource is in this video there is a zip file where you can download all the images so he had dissed client image. Create this new for record i m. J at the images from the Zip file, which is alongside this video to this photo. So we got this grid is the 1st 1 well uses as a texture on our mesh basic material, which I've started to do here. The texture later is what's Ray J issues is to load mixtures. I'll demonstrate the details of this in another video, but just right now we'll use it to load one image image grid, PNG. And was that material dot map as the texture that we've just loaded control Dave and refresh. There we go. Objects now have a texture, and depending on what that text to file waas And to see that in wire frame. There we go. It's quite a colored what frame. We can also apply a tint just by chance, the color here as well. Not that we have no lighting yet because the mesh basic material doesn't need lighting for us to see it. The next thing I share with the mesh basic material was that we can set an environment texture on now. Environment texture needs a cube texture lighter. Just very quickly, it's loading six images that are to be used for the internal walls of a cube. Now these are the images here that I've added for you. So it's That's one direction, another direction, another direction. The naming off an ex n y and zed p x p y piece. It means positive zed Positive. Why Positive X negative Zed Negative. Why? Which is straight down and negative X. So the cube texture Lodha will assemble that for us into an image, and we'll decide what kind of reflection mapping it will used. Then we decide that the material environment map is the environment texture and if we re fresh that we have a reflection on our mission basic material simply from that environment map image that I've credit, we could also turn off the main texture. Actually, that should be environment, texture, mapping. Then Ray first that there we go. I have one option down here in the really here for reflectivity. Refresh. And we can adjust how much reflectivity it has change the color and another property. The refraction ratio doesn't apply to reflectivity, but it applies to a cube refraction mapping, which was different than the reflection. Living very first that we can see the reflection is slightly different. And if we change, the refraction ratio zooms in or out. Maybe in effect, that you want looks rather flat day. And then now finally, he combined options options start, Combine eso up here in options. Does a new thing here combined Multiply operation three dot multiply operation. Remember, these will resolve to numbers, but when used through the gooey, they'll come out as strings. So down here in update material on change update material, I'm also converting combined to a number. And you can check that out if you like by leaving that off on. And these combined options are about mixing textures together. So if we go back up here and we turn on our main map texture, we could describe how the two textures overlap each other. So put this back onto reflection. Mapping like so five. Yes, we're using a multiply operation to multiply the underlying texture, which was the grid with the numbers with the environment map textures. This is a mix, so basically, just the reflection texture completely overrides the underlying texture. So I wouldn't go away or we can use an ad, which is, uh, another way is a different kinds of options that you might want multiply. Operation is the default Michigan basic material. These are the things you can do with it. Look at the back side version. Turn off reflection. Are you with the books? The same thing. In the next video, we'll look at the mesh normal material. 19. MeshNormalMaterial: Okay. Mesh. Normal material. Describe the stock code here for source client client IUs and put it into your source. Client client is fall like so. Make no more material and then refresh. That's the mission of material. Mesta material doesn't need lighting. It's great for when you've just started a project and you haven't yet created your fancy textures. Materials. It just works. We haven't yet credit of fancy lighting either. It just works right away. As you can see now, the mission normal material shows colors depending on the normal of the object relative to the camera. Look at So if I rotate this sphere, this bottom right will always be that pinky. Purple color doesn't matter which direction I look at it. The bottom right is always gonna be the same color. Miss the same for all the objects. Doesn't matter which way I look at it. The colors are there. That's very good. It gives you a good depth straight away that really needing to do anything else. And on Wikipedia there is a page for normals and this is what they are. You said that it's the direction that the face faces. So when I credit project, all of the EU's dimensional material to start with or the mesh basic material in by a frame . Now the mesh material also has a wire frame mode. Here we go looks like a. It also supports flat shading, which the mesh basic material doesn't. So this is new, and we can see what flat shedding is doing here. So smooth, shaded, and that's flat shaded. Now if we look at the differences here between the Archos that he drawn and the Cube, neither of those are affected by shading at the moment. And that's because of the angle. Grady Int. It's above 60 degrees. So with this psycho Zahi drawn here, this default shape those angles quite large. If we reduce the angle, Grady int there to make something smaller by changing the underlying geometry will use a detail off one and then refresh in case that's now smooth shaded. That's because these angles are quite so great that it has decided to not shade the ankles like a doesn't make you there in wire frame. I can see that's got more triangles and the difference 20. Each angle is less. Let's just put that back back to zero. That's the detail. Perimeter five y Francie Less triangles. That's the fissionable material. Very quickly. Next video. We'll look at the mesh land, but material. 20. MeshLambertMaterial: Meshal Lambert material uses the Lamberton reflect its model. It's a property that defines an ideal Matt or a diffuse Lee reflecting service Now. Examples. Maybe wood or stone generally objects that are Shawnee, but it's still affected by lighting, so copy the start code source. Client Client Tears and replace your client client ISS. We used to measure Olympic material there and refresh the browser, and we can't see anything. That's because by Defoe, the measure land. But material needs lauding that sad lighting the case. I've got one very simple light here. It's a point like it's completely white. Has intensity of two, says the three dark color. An intensity will look at lights in more detail. Another video right now will position now Lied at 10 10 10 seemed or add light, save, refresh. Have a guy That's the measure Lambert material. And right now a lot was a 10 10 10. So it's coming from basically this direction. So if I look at it from the opposite direction but can't see anything nicely, so that's a Mesh Lambert material straight away. We got all the common things that I've seen so far, and we can change the color and we can A ploy textures, and they have a shaded cited A lot Saw it because we're only using one light. If I had another light at minus 10 months. 10 monastery, we would sit about sides. You never go. Then I can say it's more intense at the direction rather than not the direction. Put that back environment Texas This time I'll let you experiment with that. If you like one. Thanks for thing I want to show you is a missive. Let's add this. A missive. Property here add color data. A missive on change material dot of missive. Sit Higgs, Just like with color. Saves that and refresh. And just down here. But a new control here for a missive. Basically, a missive doesn't need lighting, so the mesh basic material and the mesh normal material are fully a missive. Already, it's that need lighting. So right now we could get rid of our light eno