All language subtitles for Code-It-Yourself! 3D Graphics Engine Part #1 - Triangles & Projection-en

af Afrikaans
ak Akan
sq Albanian
am Amharic
ar Arabic Download
hy Armenian
az Azerbaijani
eu Basque
be Belarusian
bem Bemba
bn Bengali
bh Bihari
bs Bosnian
br Breton
bg Bulgarian
km Cambodian
ca Catalan
ceb Cebuano
chr Cherokee
ny Chichewa
zh-CN Chinese (Simplified)
zh-TW Chinese (Traditional)
co Corsican
hr Croatian
cs Czech
da Danish
nl Dutch
en English
eo Esperanto
et Estonian
ee Ewe
fo Faroese
tl Filipino
fi Finnish
fr French
fy Frisian
gaa Ga
gl Galician
ka Georgian
de German
el Greek
gn Guarani
gu Gujarati
ht Haitian Creole
ha Hausa
haw Hawaiian
iw Hebrew
hi Hindi
hmn Hmong
hu Hungarian
is Icelandic
ig Igbo
id Indonesian
ia Interlingua
ga Irish
it Italian
ja Japanese
jw Javanese
kn Kannada
kk Kazakh
rw Kinyarwanda
rn Kirundi
kg Kongo
ko Korean
kri Krio (Sierra Leone)
ku Kurdish
ckb Kurdish (Soranî)
ky Kyrgyz
lo Laothian
la Latin
lv Latvian
ln Lingala
lt Lithuanian
loz Lozi
lg Luganda
ach Luo
lb Luxembourgish
mk Macedonian
mg Malagasy
ms Malay
ml Malayalam
mt Maltese
mi Maori
mr Marathi
mfe Mauritian Creole
mo Moldavian
mn Mongolian
my Myanmar (Burmese)
sr-ME Montenegrin
ne Nepali
pcm Nigerian Pidgin
nso Northern Sotho
no Norwegian
nn Norwegian (Nynorsk)
oc Occitan
or Oriya
om Oromo
ps Pashto
fa Persian
pl Polish
pt-BR Portuguese (Brazil)
pt Portuguese (Portugal)
pa Punjabi
qu Quechua
ro Romanian
rm Romansh
nyn Runyakitara
ru Russian
sm Samoan
gd Scots Gaelic
sr Serbian
sh Serbo-Croatian
st Sesotho
tn Setswana
crs Seychellois Creole
sn Shona
sd Sindhi
si Sinhalese
sk Slovak
sl Slovenian
so Somali
es Spanish
es-419 Spanish (Latin American)
su Sundanese
sw Swahili
sv Swedish
tg Tajik
ta Tamil
tt Tatar
te Telugu
th Thai
ti Tigrinya
to Tonga
lua Tshiluba
tum Tumbuka
tr Turkish
tk Turkmen
tw Twi
ug Uighur
uk Ukrainian
ur Urdu
uz Uzbek
vi Vietnamese
cy Welsh
wo Wolof
xh Xhosa
yi Yiddish
yo Yoruba
zu Zulu
Would you like to inspect the original subtitles? These are the user uploaded subtitles that are being translated: 0 00:00:00,030 --> 00:00:06,000 hello and welcome to part one of a new 1 00:00:02,639 --> 00:00:09,300 series programming 3d graphics from 2 00:00:06,000 --> 00:00:11,250 scratch in this series we're going to 3 00:00:09,300 --> 00:00:12,150 start from nothing and develop quite a 4 00:00:11,250 --> 00:00:16,680 feature-rich 5 00:00:12,150 --> 00:00:19,590 software rasterizer which will allow us 6 00:00:16,680 --> 00:00:21,949 to explore 3d graphics in an interesting 7 00:00:19,590 --> 00:00:21,949 way 8 00:00:22,640 --> 00:00:27,930 the example I'm showing on the screen 9 00:00:25,019 --> 00:00:31,109 shows the one lone coda phrase rendered 10 00:00:27,930 --> 00:00:33,239 using a full 3d rastering pipeline and 11 00:00:31,109 --> 00:00:36,570 you can see it is even shaded and lit 12 00:00:33,239 --> 00:00:39,270 accordingly I've implemented a 13 00:00:36,570 --> 00:00:41,840 first-person shooter style camera and we 14 00:00:39,270 --> 00:00:44,700 can elevate the camera up and down too 15 00:00:41,840 --> 00:00:47,219 now we won't get quite that far in this 16 00:00:44,700 --> 00:00:48,989 episode this is just episode 1 we're 17 00:00:47,219 --> 00:00:51,360 really going to look at the fundamentals 18 00:00:48,989 --> 00:00:53,430 that are required as part of a 3d engine 19 00:00:51,360 --> 00:00:55,110 but that's the series progresses I'm 20 00:00:53,430 --> 00:00:57,360 going to add more and more features to 21 00:00:55,110 --> 00:01:00,000 turn this into quite a sophisticated 3d 22 00:00:57,360 --> 00:01:02,550 engine now when you hear 3d engine you 23 00:01:00,000 --> 00:01:04,920 might think of the terms OpenGL DirectX 24 00:01:02,550 --> 00:01:08,460 or Vulcan these days we won't be looking 25 00:01:04,920 --> 00:01:10,799 at those exactly instead what I'd like 26 00:01:08,460 --> 00:01:13,860 to present is the theory and the 27 00:01:10,799 --> 00:01:16,500 mathematics and the ideas that go behind 28 00:01:13,860 --> 00:01:18,659 the graphic API so that we know and love 29 00:01:16,500 --> 00:01:21,780 and what I hope to show by the end of 30 00:01:18,659 --> 00:01:23,670 the series is just how complicated it is 31 00:01:21,780 --> 00:01:25,920 to make your favorite games look very 32 00:01:23,670 --> 00:01:28,049 pretty indeed and I'll demonstrate that 33 00:01:25,920 --> 00:01:31,560 the number of calculations per triangle 34 00:01:28,049 --> 00:01:33,659 and per pixel is simply huge now there's 35 00:01:31,560 --> 00:01:36,600 one thing we can't get away from with 3d 36 00:01:33,659 --> 00:01:38,820 graphics and that is mathematics but 37 00:01:36,600 --> 00:01:40,590 don't click stop just yet I'm going to 38 00:01:38,820 --> 00:01:42,479 try and present it in a style that's 39 00:01:40,590 --> 00:01:44,909 maths friendly and the nice thing about 40 00:01:42,479 --> 00:01:48,090 3d engines is even if you don't have 41 00:01:44,909 --> 00:01:51,149 strong mathematics ability you can still 42 00:01:48,090 --> 00:01:53,040 use most of the parts of a 3d engine as 43 00:01:51,149 --> 00:01:55,259 as black boxes you don't necessarily 44 00:01:53,040 --> 00:01:57,479 need to know how they work but you need 45 00:01:55,259 --> 00:02:00,180 to know what these magical functions do 46 00:01:57,479 --> 00:02:01,890 and over time by using such functions 47 00:02:00,180 --> 00:02:04,170 you can actually develop a really 48 00:02:01,890 --> 00:02:06,869 intuitive understanding of what's going 49 00:02:04,170 --> 00:02:09,780 on behind the scenes so let's get 50 00:02:06,869 --> 00:02:11,879 started rather oddly I'm going to start 51 00:02:09,780 --> 00:02:13,890 this tutorial by saying there's no such 52 00:02:11,879 --> 00:02:16,230 thing as 3d graphics 53 00:02:13,890 --> 00:02:20,060 and that's simply because if we try to 54 00:02:16,230 --> 00:02:24,750 represent a 3d shape on a screen of 55 00:02:20,060 --> 00:02:26,970 course this screen is two-dimensional so 56 00:02:24,750 --> 00:02:28,770 even though the object looks 3d what 57 00:02:26,970 --> 00:02:32,340 we're actually trying to generate in the 58 00:02:28,770 --> 00:02:34,500 end is a sequence of 2d shapes that give 59 00:02:32,340 --> 00:02:37,200 the illusion of 3d on the screen 60 00:02:34,500 --> 00:02:40,800 so taking this cube as an example I can 61 00:02:37,200 --> 00:02:47,390 see I've got a top piece and I've got a 62 00:02:40,800 --> 00:02:49,920 side piece and I've got a front face 63 00:02:47,390 --> 00:02:54,060 should be a little squarer than that and 64 00:02:49,920 --> 00:02:57,390 so the purpose of a 3d engine is to take 65 00:02:54,060 --> 00:03:01,410 a three-dimensional geometrical data and 66 00:02:57,390 --> 00:03:05,520 convert it into these 2d shapes so we 67 00:03:01,410 --> 00:03:12,180 might define our cube as being a series 68 00:03:05,520 --> 00:03:17,670 of eight vertices which I'll mark here 69 00:03:12,180 --> 00:03:20,940 with the red dots don't forget there's 70 00:03:17,670 --> 00:03:22,980 one we can't see and from this very 71 00:03:20,940 --> 00:03:25,920 early stage even though it might seem 72 00:03:22,980 --> 00:03:32,160 strange I'm going to suggest that all of 73 00:03:25,920 --> 00:03:33,900 our dots are grouped into triangles so 74 00:03:32,160 --> 00:03:37,440 this front face here I'm marking out in 75 00:03:33,900 --> 00:03:41,880 blue consists of two triangles and the 76 00:03:37,440 --> 00:03:47,790 same applies for the top face and the 77 00:03:41,880 --> 00:03:54,209 side face and even the faces we can't 78 00:03:47,790 --> 00:03:57,600 see in the background and the reason I'm 79 00:03:54,209 --> 00:03:59,580 doing this is a triangle is a very 80 00:03:57,600 --> 00:04:02,610 simple primitive in fact it's the 81 00:03:59,580 --> 00:04:04,830 simplest 2d shape and as will become 82 00:04:02,610 --> 00:04:07,620 apparent it's convenient to group 83 00:04:04,830 --> 00:04:11,130 vertices together in some meaningful way 84 00:04:07,620 --> 00:04:14,220 and because triangles are the simplest 85 00:04:11,130 --> 00:04:16,979 2d primitive it's possible to represent 86 00:04:14,220 --> 00:04:19,910 any two-dimensional shape using nothing 87 00:04:16,979 --> 00:04:19,910 but triangles 88 00:04:29,090 --> 00:04:33,949 and finally when it comes to drawing 89 00:04:31,580 --> 00:04:35,960 triangles on a screen there are some 90 00:04:33,949 --> 00:04:38,600 very optimized algorithms to do this 91 00:04:35,960 --> 00:04:42,800 because a triangle consists of straight 92 00:04:38,600 --> 00:04:45,470 lines well not straight when Javid draws 93 00:04:42,800 --> 00:04:48,770 them and there are also some neat 94 00:04:45,470 --> 00:04:51,860 algorithms to fill in a triangle and 95 00:04:48,770 --> 00:04:54,530 shade it on the screen again using 96 00:04:51,860 --> 00:04:56,690 straight horizontal lines will look at 97 00:04:54,530 --> 00:04:59,180 rasterization in a later part of this 98 00:04:56,690 --> 00:05:02,620 series but what I'm trying to emphasize 99 00:04:59,180 --> 00:05:07,040 is that triangles are really important 100 00:05:02,620 --> 00:05:08,540 and so in this video we're going to look 101 00:05:07,040 --> 00:05:11,780 at how we can take a collection of 102 00:05:08,540 --> 00:05:14,330 vertices in three-dimensional space form 103 00:05:11,780 --> 00:05:16,940 a surface of a solid object out of 104 00:05:14,330 --> 00:05:20,510 triangles and projects these triangles 105 00:05:16,940 --> 00:05:22,370 to the screen for the user to see now 106 00:05:20,510 --> 00:05:24,139 because this is a new series and I'd 107 00:05:22,370 --> 00:05:25,760 like to show how to do this from scratch 108 00:05:24,139 --> 00:05:27,080 I'm actually going to show you how to 109 00:05:25,760 --> 00:05:30,740 create the visual studio project 110 00:05:27,080 --> 00:05:33,770 necessary to do this and in part that's 111 00:05:30,740 --> 00:05:36,289 because visual studio 2017 has changed 112 00:05:33,770 --> 00:05:37,789 the way projects are created and so I 113 00:05:36,289 --> 00:05:39,740 feel it might be useful to demonstrate 114 00:05:37,789 --> 00:05:41,690 how to set up a project to start 115 00:05:39,740 --> 00:05:45,349 something from scratch so I'm going to 116 00:05:41,690 --> 00:05:48,200 go to file new project and I want to 117 00:05:45,349 --> 00:05:49,880 choose windows console application of 118 00:05:48,200 --> 00:05:52,070 course I'm going to be doing all of this 119 00:05:49,880 --> 00:05:54,320 with the console game engine but don't 120 00:05:52,070 --> 00:05:56,300 let that put you off simply because the 121 00:05:54,320 --> 00:05:58,130 maths and the ideas don't change 122 00:05:56,300 --> 00:06:00,979 regardless of the interface that you're 123 00:05:58,130 --> 00:06:04,669 going to use select a console 124 00:06:00,979 --> 00:06:09,919 application and give it a name I'm going 125 00:06:04,669 --> 00:06:11,900 to call this one olc engine 3d now in 126 00:06:09,919 --> 00:06:12,880 previous versions of Visual Studio when 127 00:06:11,900 --> 00:06:16,010 you click OK 128 00:06:12,880 --> 00:06:18,500 it would give you some more options it 129 00:06:16,010 --> 00:06:20,240 no longer does this instead it creates a 130 00:06:18,500 --> 00:06:23,840 project for you and fills it full of 131 00:06:20,240 --> 00:06:27,560 files well the first thing I'm going to 132 00:06:23,840 --> 00:06:30,220 do is delete everything except the dot 133 00:06:27,560 --> 00:06:31,580 CPP file that it is created for me 134 00:06:30,220 --> 00:06:36,400 bye-bye 135 00:06:31,580 --> 00:06:39,169 and then going to remove this line 136 00:06:36,400 --> 00:06:41,000 standard afx that's for the precompiled 137 00:06:39,169 --> 00:06:43,040 headers I'm not interested in using 138 00:06:41,000 --> 00:06:45,230 those and even though I've removed the 139 00:06:43,040 --> 00:06:50,000 I actually need to go into properties of 140 00:06:45,230 --> 00:06:51,950 the project go to C++ expand that open 141 00:06:50,000 --> 00:06:55,100 and choose the precompiled headers 142 00:06:51,950 --> 00:07:00,860 option and tell it that no I don't want 143 00:06:55,100 --> 00:07:03,950 to use precompiled headers and click 144 00:07:00,860 --> 00:07:06,200 apply what I do want to use is the 145 00:07:03,950 --> 00:07:13,850 console game engine so I'm going to 146 00:07:06,200 --> 00:07:15,380 include it and I'm going to make sure 147 00:07:13,850 --> 00:07:17,180 that the header file that contains the 148 00:07:15,380 --> 00:07:23,570 console game engine is also in the 149 00:07:17,180 --> 00:07:25,610 project directory now we go and I'll add 150 00:07:23,570 --> 00:07:29,750 that file just because I like to see all 151 00:07:25,610 --> 00:07:32,750 the files my project is using into my 152 00:07:29,750 --> 00:07:34,100 visual studio project and of course if 153 00:07:32,750 --> 00:07:37,220 you're on a different operating system 154 00:07:34,100 --> 00:07:39,080 now you can use the OpenGL version or 155 00:07:37,220 --> 00:07:41,300 the STL version of the console game 156 00:07:39,080 --> 00:07:43,280 engine even though it says game engine 157 00:07:41,300 --> 00:07:45,470 in the title all we're really doing here 158 00:07:43,280 --> 00:07:48,140 is accepting input from the user and 159 00:07:45,470 --> 00:07:49,580 displaying things on a 2d screen the 160 00:07:48,140 --> 00:07:51,290 fact that this house game engine there 161 00:07:49,580 --> 00:07:54,260 doesn't imply we're going to be using 162 00:07:51,290 --> 00:07:55,460 any of the game engine features which is 163 00:07:54,260 --> 00:07:57,500 important because I don't want you to 164 00:07:55,460 --> 00:07:59,210 think that I'm hiding interesting 165 00:07:57,500 --> 00:08:01,160 technology and clever functions in the 166 00:07:59,210 --> 00:08:02,540 console game engine and exploiting them 167 00:08:01,160 --> 00:08:04,700 to generate 3d graphics 168 00:08:02,540 --> 00:08:06,530 I'm not regular viewers of the channel 169 00:08:04,700 --> 00:08:09,050 will know that we need to create a 170 00:08:06,530 --> 00:08:11,240 subclass of the OLC console game engine 171 00:08:09,050 --> 00:08:15,980 and so I'm going to call it olc engine 172 00:08:11,240 --> 00:08:19,940 3d which inherits from the console game 173 00:08:15,980 --> 00:08:22,570 engine let's just give it a quick 174 00:08:19,940 --> 00:08:22,570 constructor 175 00:08:25,120 --> 00:08:39,099 and there are two functions we must 176 00:08:27,490 --> 00:08:45,870 override the first is on user create and 177 00:08:39,099 --> 00:08:45,870 the second is on user update 178 00:08:58,110 --> 00:09:02,470 for now I'll make these return true and 179 00:09:00,910 --> 00:09:03,760 that tells the game engine that 180 00:09:02,470 --> 00:09:09,550 everything is fine and it should 181 00:09:03,760 --> 00:09:11,140 continue running in our in main function 182 00:09:09,550 --> 00:09:20,470 we need to create an instance of this 183 00:09:11,140 --> 00:09:22,600 class and we should try to create an 184 00:09:20,470 --> 00:09:25,330 instance of the console using it using 185 00:09:22,600 --> 00:09:27,580 the construct console function and for 186 00:09:25,330 --> 00:09:28,990 this application and indeed this series 187 00:09:27,580 --> 00:09:33,340 I'm going to use quite a high resolution 188 00:09:28,990 --> 00:09:35,200 console of 256 characters wide by 240 189 00:09:33,340 --> 00:09:38,140 characters high and each character is 190 00:09:35,200 --> 00:09:41,320 going to be 4 by 4 pixels width and 191 00:09:38,140 --> 00:09:44,080 height an oh dear quick error number 1 I 192 00:09:41,320 --> 00:09:47,400 need to publicly include the console 193 00:09:44,080 --> 00:09:50,200 game engine there we go 194 00:09:47,400 --> 00:09:55,660 so if we can successfully construct the 195 00:09:50,200 --> 00:09:58,090 console I want to start it else I would 196 00:09:55,660 --> 00:10:00,130 display some sort of error message as is 197 00:09:58,090 --> 00:10:02,170 typical in some of my videos I don't 198 00:10:00,130 --> 00:10:04,210 tend to do all of the error capture code 199 00:10:02,170 --> 00:10:08,200 that's to keep the code as clear and 200 00:10:04,210 --> 00:10:16,270 concise as possible finally I'll name 201 00:10:08,200 --> 00:10:19,090 the application 3d demo and a quick 202 00:10:16,270 --> 00:10:21,250 reminder by default now unicode will be 203 00:10:19,090 --> 00:10:23,890 enabled and this is important because I 204 00:10:21,250 --> 00:10:25,840 think it is the singular most popular 205 00:10:23,890 --> 00:10:27,790 question I've been asked since starting 206 00:10:25,840 --> 00:10:30,010 this channel how to enable the Unicode 207 00:10:27,790 --> 00:10:31,990 and thankfully Microsoft do that for me 208 00:10:30,010 --> 00:10:33,970 now well now because I want to 209 00:10:31,990 --> 00:10:37,600 demonstrate all of this from scratch I'm 210 00:10:33,970 --> 00:10:38,920 not going to be using a maths library to 211 00:10:37,600 --> 00:10:40,570 help me we're going to do absolutely 212 00:10:38,920 --> 00:10:43,840 everything so I'm going to create a 213 00:10:40,570 --> 00:10:45,400 structure called BEC 3d and this is 214 00:10:43,840 --> 00:10:49,960 going to hold three floating-point 215 00:10:45,400 --> 00:10:51,670 values X Y & Z which represent a 216 00:10:49,960 --> 00:10:53,590 coordinate in 3d space 217 00:10:51,670 --> 00:10:57,910 I'm also going to create a second 218 00:10:53,590 --> 00:11:02,190 structure called triangle which is going 219 00:10:57,910 --> 00:11:02,190 to group together three vector E DS 220 00:11:07,300 --> 00:11:12,130 as the series progresses we'll be adding 221 00:11:10,070 --> 00:11:14,270 more features to this triangle structure 222 00:11:12,130 --> 00:11:19,100 finally I'm going to create a third 223 00:11:14,270 --> 00:11:21,590 structure called mesh and a mesh is 224 00:11:19,100 --> 00:11:30,230 going to represent the object it's going 225 00:11:21,590 --> 00:11:32,210 to group together triangles and you'll 226 00:11:30,230 --> 00:11:35,390 notice a little red wiggly line has 227 00:11:32,210 --> 00:11:37,670 appeared and that's because at long last 228 00:11:35,390 --> 00:11:40,940 I finally removed the using namespace 229 00:11:37,670 --> 00:11:42,680 STD from the header file as I can here 230 00:11:40,940 --> 00:11:45,320 most of the people on discord cheering 231 00:11:42,680 --> 00:11:47,030 right now and I can't argue that it is 232 00:11:45,320 --> 00:11:49,550 good practice not to include using 233 00:11:47,030 --> 00:11:52,220 namespace in your header files but to 234 00:11:49,550 --> 00:11:56,210 keep this code clear I'm actually going 235 00:11:52,220 --> 00:11:58,610 to use it here so a quick recap we've 236 00:11:56,210 --> 00:12:01,310 got a mesh which contains a vector of 237 00:11:58,610 --> 00:12:03,050 triangles that represents an object and 238 00:12:01,310 --> 00:12:06,470 we've got a triangle which contains 239 00:12:03,050 --> 00:12:08,180 three vertices or vector 3ds these are 240 00:12:06,470 --> 00:12:10,550 the points that define the outline of 241 00:12:08,180 --> 00:12:13,040 the triangle I'm going to add now to our 242 00:12:10,550 --> 00:12:17,180 main class a mesh and I'm going to call 243 00:12:13,040 --> 00:12:19,340 it mesh cube and in on user create I'm 244 00:12:17,180 --> 00:12:21,500 going to populate that mesh with the 245 00:12:19,340 --> 00:12:28,850 vertex data to define a cube made of 246 00:12:21,500 --> 00:12:32,240 triangles and I'm going to use this with 247 00:12:28,850 --> 00:12:34,340 some nifty initializer lists I'm going 248 00:12:32,240 --> 00:12:36,830 to keep the cube simple and define it as 249 00:12:34,340 --> 00:12:39,920 a unit cube in these three dimensions so 250 00:12:36,830 --> 00:12:42,110 each side of the cube is one unit long 251 00:12:39,920 --> 00:12:46,940 and we'll assume the origin of the cube 252 00:12:42,110 --> 00:12:56,150 is at 0 0 0 x y&z therefore this point 253 00:12:46,940 --> 00:12:57,710 becomes 1 0 0 0 1 0 and 1 1 0 I've drawn 254 00:12:56,150 --> 00:13:00,290 the cube edges so we can see what's 255 00:12:57,710 --> 00:13:05,240 going on a little more clearly and this 256 00:13:00,290 --> 00:13:06,650 obviously becomes 0 1 1 in fact it's 257 00:13:05,240 --> 00:13:08,120 each one of these coordinates of the 258 00:13:06,650 --> 00:13:10,880 back is the same as the one at the front 259 00:13:08,120 --> 00:13:15,350 except the Z component is 1 so this one 260 00:13:10,880 --> 00:13:18,850 up here is 1 1 1 and this one is 1 0 1 261 00:13:15,350 --> 00:13:21,920 and the 1 hidden is 0 262 00:13:18,850 --> 00:13:26,510 zero-one and I'm going to top the 263 00:13:21,920 --> 00:13:30,140 convention that this face is South the 264 00:13:26,510 --> 00:13:33,230 face round the back is north this face 265 00:13:30,140 --> 00:13:37,430 is east and that face round the back 266 00:13:33,230 --> 00:13:40,160 there is West this one's the top and 267 00:13:37,430 --> 00:13:43,130 therefore the one underneath I'm going 268 00:13:40,160 --> 00:13:45,320 to call bottom and now I can start to 269 00:13:43,130 --> 00:13:46,850 think about my triangles but there's 270 00:13:45,320 --> 00:13:48,830 something important about the triangles 271 00:13:46,850 --> 00:13:51,050 which will come to again later on and 272 00:13:48,830 --> 00:13:53,630 that is what the order of the points 273 00:13:51,050 --> 00:13:56,960 that we define the triangle in and I 274 00:13:53,630 --> 00:14:01,430 want to always use a clockwise order so 275 00:13:56,960 --> 00:14:05,990 I'm going to take from zero zero zero up 276 00:14:01,430 --> 00:14:08,510 here all the way along and because it's 277 00:14:05,990 --> 00:14:11,960 a triangle I now need to come back down 278 00:14:08,510 --> 00:14:14,260 to the original point you'll notice I've 279 00:14:11,960 --> 00:14:16,940 gone in a clockwise direction 280 00:14:14,260 --> 00:14:23,230 and I want to do the same now for my 281 00:14:16,940 --> 00:14:27,020 second triangle up to the top back down 282 00:14:23,230 --> 00:14:30,070 and along again in a clockwise direction 283 00:14:27,020 --> 00:14:33,970 and I want to do exactly the same for 284 00:14:30,070 --> 00:14:33,970 the remaining faces 285 00:14:43,200 --> 00:14:50,070 always retaining this clockwise ordering 286 00:14:47,030 --> 00:14:52,640 using initializer lists I can define the 287 00:14:50,070 --> 00:14:56,100 vertices manually and I group them into 288 00:14:52,640 --> 00:14:58,260 South East North West and top and bottom 289 00:14:56,100 --> 00:15:00,600 but I'm also using a neat trick that 290 00:14:58,260 --> 00:15:03,360 I've got to initialize a list inside the 291 00:15:00,600 --> 00:15:05,210 other initializer list so this sub 292 00:15:03,360 --> 00:15:08,880 initializer list will initialize the 293 00:15:05,210 --> 00:15:11,220 triangle with three vectors whilst the 294 00:15:08,880 --> 00:15:13,590 outside initializer list initializes the 295 00:15:11,220 --> 00:15:16,260 standard vector I'm going to use the 296 00:15:13,590 --> 00:15:18,600 fill command in on user update to clear 297 00:15:16,260 --> 00:15:21,990 the screen from the top left to the 298 00:15:18,600 --> 00:15:23,760 bottom right and after we've cleared the 299 00:15:21,990 --> 00:15:29,370 screen we're going to need to draw our 300 00:15:23,760 --> 00:15:31,800 triangles and because our triangles are 301 00:15:29,370 --> 00:15:35,670 neatly contained inside a vector inside 302 00:15:31,800 --> 00:15:38,780 of mesh I can use an auto for loop to 303 00:15:35,670 --> 00:15:38,780 iterate through them all 304 00:15:47,100 --> 00:15:53,110 but of course it's not this simple the 305 00:15:50,530 --> 00:15:55,540 objects exist in 3d space and the screen 306 00:15:53,110 --> 00:15:57,460 is in 2d space so we need to come up 307 00:15:55,540 --> 00:15:59,560 with a way of condensing that foodie 308 00:15:57,460 --> 00:16:02,170 space to the 2d screen and this is 309 00:15:59,560 --> 00:16:05,080 called projection so how do we turn our 310 00:16:02,170 --> 00:16:07,420 3d vertices into 2d vertices for 311 00:16:05,080 --> 00:16:10,840 projection onto the screen well first of 312 00:16:07,420 --> 00:16:14,500 all let's define our screen which is 313 00:16:10,840 --> 00:16:17,050 going to be some sort of rectangle with 314 00:16:14,500 --> 00:16:19,090 a width and a height because screens 315 00:16:17,050 --> 00:16:21,330 come in all shapes and sizes it's useful 316 00:16:19,090 --> 00:16:24,730 to reduce the three-dimensional objects 317 00:16:21,330 --> 00:16:26,710 into a normalized screen space and so 318 00:16:24,730 --> 00:16:30,490 I'm going to suggest that if we 319 00:16:26,710 --> 00:16:34,240 partition the screen this way and this 320 00:16:30,490 --> 00:16:37,510 way and we label this as minus one and 321 00:16:34,240 --> 00:16:40,810 this is positive one and up here as 322 00:16:37,510 --> 00:16:43,150 minus one and this as positive one we've 323 00:16:40,810 --> 00:16:45,610 normalized the screen space obviously 324 00:16:43,150 --> 00:16:45,970 that gives us zero zero in the middle of 325 00:16:45,610 --> 00:16:47,980 the screen 326 00:16:45,970 --> 00:16:50,110 and because the width and height can be 327 00:16:47,980 --> 00:16:52,570 different we want to scale movements 328 00:16:50,110 --> 00:16:54,490 within the screen space accordingly so 329 00:16:52,570 --> 00:16:57,040 we're going to use the aspect ratio 330 00:16:54,490 --> 00:17:00,130 which I'll call a and define that as 331 00:16:57,040 --> 00:17:01,750 being the height over the width and this 332 00:17:00,130 --> 00:17:03,790 will be the first of several assumptions 333 00:17:01,750 --> 00:17:09,010 about how we're going to transform our 334 00:17:03,790 --> 00:17:11,520 3d vector X Y & Z into our screen space 335 00:17:09,010 --> 00:17:17,100 vector and I'm going to demonstrate this 336 00:17:11,520 --> 00:17:17,100 by accumulating the operations required 337 00:17:21,490 --> 00:17:25,910 normalizing the screen space has an 338 00:17:23,569 --> 00:17:29,179 additional advantage that anything above 339 00:17:25,910 --> 00:17:32,120 +1 or below minus 1 definitely won't be 340 00:17:29,179 --> 00:17:35,929 drawn to the screen so let's just draw 341 00:17:32,120 --> 00:17:38,660 in some imaginary boundaries here this 342 00:17:35,929 --> 00:17:42,080 object exists entirely within the 343 00:17:38,660 --> 00:17:44,179 visible viewing space but this object on 344 00:17:42,080 --> 00:17:47,049 the right straddles the boundary so 345 00:17:44,179 --> 00:17:50,150 we'll never see this side of the object 346 00:17:47,049 --> 00:17:52,730 however humans don't see screens in that 347 00:17:50,150 --> 00:17:56,570 manner they see instead what's called 348 00:17:52,730 --> 00:17:59,500 the field of view and we can cast array 349 00:17:56,570 --> 00:18:03,559 that way and we'll cast array that way 350 00:17:59,500 --> 00:18:06,559 so at this point it's minus 1 and plus 1 351 00:18:03,559 --> 00:18:10,840 on the screen but also out here in our 352 00:18:06,559 --> 00:18:13,070 space this is also minus 1 and plus 1 353 00:18:10,840 --> 00:18:15,200 and of course this makes a lot of sense 354 00:18:13,070 --> 00:18:17,720 because objects that are further away 355 00:18:15,200 --> 00:18:20,260 well we can see more space the further 356 00:18:17,720 --> 00:18:23,059 away it is and as we approach the screen 357 00:18:20,260 --> 00:18:25,490 we occupy more of the screen with our 358 00:18:23,059 --> 00:18:28,460 objects if the field of view is 359 00:18:25,490 --> 00:18:31,070 particularly narrow how crudely draw in 360 00:18:28,460 --> 00:18:33,530 here is a blue triangle it has the 361 00:18:31,070 --> 00:18:37,820 effect of zooming in on the object and 362 00:18:33,530 --> 00:18:40,280 if the field of view goes really wide it 363 00:18:37,820 --> 00:18:42,290 has the effect of zooming out we see 364 00:18:40,280 --> 00:18:44,450 more stuff and this means we need a 365 00:18:42,290 --> 00:18:46,429 scaling factor that relates to the field 366 00:18:44,450 --> 00:18:50,510 of view and we'll say that the field of 367 00:18:46,429 --> 00:18:52,760 view is theta well one way to think 368 00:18:50,510 --> 00:18:55,250 about a scaling factor is to draw a 369 00:18:52,760 --> 00:18:58,570 right angle triangle right down the 370 00:18:55,250 --> 00:18:58,570 middle of our field of view 371 00:19:01,760 --> 00:19:08,450 say that the right angles and as this 372 00:19:06,410 --> 00:19:11,270 angle increases so this is now theta 373 00:19:08,450 --> 00:19:14,600 divided by two our opposite side of the 374 00:19:11,270 --> 00:19:17,390 triangle increases and so it stands to 375 00:19:14,600 --> 00:19:20,060 reason that since we've got the angle of 376 00:19:17,390 --> 00:19:22,220 a triangle its opposite side and it's 377 00:19:20,060 --> 00:19:25,270 adjacent side that we might want to 378 00:19:22,220 --> 00:19:27,770 consider looking at the tangent function 379 00:19:25,270 --> 00:19:30,010 but of course it's tangent of the field 380 00:19:27,770 --> 00:19:33,080 of U divided by 2 381 00:19:30,010 --> 00:19:36,890 but there's a slight problem here if we 382 00:19:33,080 --> 00:19:40,250 take a point and we increase our field 383 00:19:36,890 --> 00:19:43,340 of view the scaling factor that we get 384 00:19:40,250 --> 00:19:47,360 as a result of this equation gets larger 385 00:19:43,340 --> 00:19:50,240 and naturally if we reduce theta the 386 00:19:47,360 --> 00:19:51,920 scaling factor gets smaller so this has 387 00:19:50,240 --> 00:19:54,050 the rather odd effect that if we 388 00:19:51,920 --> 00:19:56,540 increase the field of view we start 389 00:19:54,050 --> 00:19:59,090 displacing all of our objects outside of 390 00:19:56,540 --> 00:20:02,600 it and naturally if we decrease our 391 00:19:59,090 --> 00:20:04,730 field of view we scale them less so more 392 00:20:02,600 --> 00:20:06,560 objects can appear and this is a 393 00:20:04,730 --> 00:20:09,140 contradiction to what we've just said 394 00:20:06,560 --> 00:20:11,930 that increasing the field of view is the 395 00:20:09,140 --> 00:20:15,230 same as zooming out so what we want is 396 00:20:11,930 --> 00:20:18,470 the exact opposite of this indeed we 397 00:20:15,230 --> 00:20:20,570 want the inverse of it this gives us 398 00:20:18,470 --> 00:20:24,200 some more coefficients to add to our 399 00:20:20,570 --> 00:20:31,250 transformation where F is equal to 1 400 00:20:24,200 --> 00:20:33,710 over tan of theta over 2 since we've 401 00:20:31,250 --> 00:20:36,140 gone to the trouble of normalizing x and 402 00:20:33,710 --> 00:20:38,380 y and realistically all we're interested 403 00:20:36,140 --> 00:20:41,030 is in x and y because this is a 2d 404 00:20:38,380 --> 00:20:43,640 surface in the end we may as well also 405 00:20:41,030 --> 00:20:44,870 attempt to normalize Z and the reasons 406 00:20:43,640 --> 00:20:46,820 for this might not be immediately 407 00:20:44,870 --> 00:20:49,790 apparent but as we'll see in future 408 00:20:46,820 --> 00:20:53,390 videos knowing what Z is in the same 409 00:20:49,790 --> 00:20:55,490 space as x and y can be really useful 410 00:20:53,390 --> 00:20:57,110 for optimizing our algorithms and 411 00:20:55,490 --> 00:20:59,090 handling other interesting drawing 412 00:20:57,110 --> 00:21:01,280 routines like transparency in depth 413 00:20:59,090 --> 00:21:03,710 choosing a scaling coefficient for the z 414 00:21:01,280 --> 00:21:06,800 axis is somewhat more simpler on again a 415 00:21:03,710 --> 00:21:10,400 frustum and this is the z axis going 416 00:21:06,800 --> 00:21:12,920 forward into the distance the furthest 417 00:21:10,400 --> 00:21:15,500 distance of objects that we can see will 418 00:21:12,920 --> 00:21:19,880 be defined by this plane at the back 419 00:21:15,500 --> 00:21:21,890 which I'm going to call Zed far now you 420 00:21:19,880 --> 00:21:24,440 might assume that means where the screen 421 00:21:21,890 --> 00:21:26,210 is at the front that would be zero but 422 00:21:24,440 --> 00:21:28,970 that's not quite the case because the 423 00:21:26,210 --> 00:21:30,830 players head isn't resting against the 424 00:21:28,970 --> 00:21:32,420 screen the player would injure their 425 00:21:30,830 --> 00:21:35,330 eyes where in fact there is a small 426 00:21:32,420 --> 00:21:40,400 distance here I'm going to call that Zed 427 00:21:35,330 --> 00:21:42,590 near which is the distance represented 428 00:21:40,400 --> 00:21:45,980 from the play's head to the front of the 429 00:21:42,590 --> 00:21:49,580 screen and Zed far is from the place 430 00:21:45,980 --> 00:21:51,860 head to the furthest distance we want to 431 00:21:49,580 --> 00:21:53,630 be able to view in the in the engine if 432 00:21:51,860 --> 00:21:55,940 I put some imaginary numbers next to 433 00:21:53,630 --> 00:21:59,330 this so let's say our far plane is at 10 434 00:21:55,940 --> 00:22:02,420 and our near plane is at 1 to work out 435 00:21:59,330 --> 00:22:04,940 where the position of a point in that 436 00:22:02,420 --> 00:22:08,390 plane really is we need to first scale 437 00:22:04,940 --> 00:22:10,760 it to a normalized system so in this 438 00:22:08,390 --> 00:22:14,570 case our Zed far- 439 00:22:10,760 --> 00:22:17,060 RZ near is equal to 9 so we want to take 440 00:22:14,570 --> 00:22:20,540 our point and divide it by 9 that will 441 00:22:17,060 --> 00:22:23,030 give us a point between 0 & 1 but we've 442 00:22:20,540 --> 00:22:25,430 decided that our far plane should be 10 443 00:22:23,030 --> 00:22:28,790 so we need to scale it back up again so 444 00:22:25,430 --> 00:22:32,420 this is implying that we have for our z 445 00:22:28,790 --> 00:22:39,260 axis scale factor something that looks 446 00:22:32,420 --> 00:22:45,080 like this Zed far divided by Zed far - 447 00:22:39,260 --> 00:22:47,870 Zed near but this still leaves us with a 448 00:22:45,080 --> 00:22:50,900 bit of a discrepancy here so we'll also 449 00:22:47,870 --> 00:22:53,990 need to offset our transformed point by 450 00:22:50,900 --> 00:22:55,400 this discrepancy scaled - well 451 00:22:53,990 --> 00:22:58,520 fortunately we know where that 452 00:22:55,400 --> 00:23:01,250 discrepancy is so we can take our 453 00:22:58,520 --> 00:23:04,220 equation up here and simply multiply it 454 00:23:01,250 --> 00:23:07,220 by Z near but we're going to offset it 455 00:23:04,220 --> 00:23:13,360 from the final result so this becomes Z 456 00:23:07,220 --> 00:23:18,170 far multiplied by Z near over Zed far 457 00:23:13,360 --> 00:23:19,790 take xenia and so now if we look at our 458 00:23:18,170 --> 00:23:22,490 initial coordinates and look at the 459 00:23:19,790 --> 00:23:24,830 final transformed coordinate well it's 460 00:23:22,490 --> 00:23:26,500 starting to look a bit complicated and 461 00:23:24,830 --> 00:23:29,120 we're not even quite finished yet 462 00:23:26,500 --> 00:23:32,210 intuitively we know that when things are 463 00:23:29,120 --> 00:23:34,130 further away they appear to move less so 464 00:23:32,210 --> 00:23:37,810 this implies that a change in the 465 00:23:34,130 --> 00:23:38,960 x-coordinate is somehow related to the 466 00:23:37,810 --> 00:23:40,850 z-depth 467 00:23:38,960 --> 00:23:43,250 in this case it's inversely proportional 468 00:23:40,850 --> 00:23:44,090 as Zed gets larger ie further away from 469 00:23:43,250 --> 00:23:47,060 the screen 470 00:23:44,090 --> 00:23:53,780 it makes the changes in X smaller and 471 00:23:47,060 --> 00:23:56,450 this is analogous for Y so our final 472 00:23:53,780 --> 00:24:03,340 scaling that we need to do to our x and 473 00:23:56,450 --> 00:24:03,340 y coordinates is to divide them by Z 474 00:24:04,390 --> 00:24:11,180 let's start to simplify some of this out 475 00:24:07,960 --> 00:24:14,330 I'll take our width in a height and 476 00:24:11,180 --> 00:24:16,730 we'll call it a 4 aspect ratio we'll 477 00:24:14,330 --> 00:24:19,430 take our field of view and we'll call 478 00:24:16,730 --> 00:24:23,750 that f and let's take our said 479 00:24:19,430 --> 00:24:27,280 normalization and we'll call that Q and 480 00:24:23,750 --> 00:24:30,860 which you can see also applies here 481 00:24:27,280 --> 00:24:49,030 which means a much simpler form would be 482 00:24:30,860 --> 00:24:50,900 a F X / z f y / z and z q - said near q 483 00:24:49,030 --> 00:24:53,420 we could go and implement these 484 00:24:50,900 --> 00:24:56,660 equations directly but instead I'm going 485 00:24:53,420 --> 00:24:58,460 to represent them in matrix form as this 486 00:24:56,660 --> 00:25:00,310 allows us then to implement a function 487 00:24:58,460 --> 00:25:02,390 which can multiply a vector by a matrix 488 00:25:00,310 --> 00:25:04,820 something which we're going to use a lot 489 00:25:02,390 --> 00:25:06,890 off in 3d graphics in the Cody self 490 00:25:04,820 --> 00:25:10,580 asteroids video I already talked in 491 00:25:06,890 --> 00:25:12,920 quite some detail about how matrix 492 00:25:10,580 --> 00:25:16,520 multiplication works but just as a quick 493 00:25:12,920 --> 00:25:18,680 recap we'll take this element of the 494 00:25:16,520 --> 00:25:20,840 vector and multiply it by this element 495 00:25:18,680 --> 00:25:23,890 of the matrix and this element of the 496 00:25:20,840 --> 00:25:26,420 vector and this element of the matrix 497 00:25:23,890 --> 00:25:28,910 this element of the vector and this 498 00:25:26,420 --> 00:25:31,490 element of the matrix and we sum them up 499 00:25:28,910 --> 00:25:35,360 and that gives us a result to put into 500 00:25:31,490 --> 00:25:38,510 our new vector in this location so let's 501 00:25:35,360 --> 00:25:41,360 start with the transformed X location so 502 00:25:38,510 --> 00:25:42,930 I'm going to put the result here in the 503 00:25:41,360 --> 00:25:45,630 top corner which 504 00:25:42,930 --> 00:25:52,470 simply want AF the remaining entries are 505 00:25:45,630 --> 00:25:56,850 zero so x x AF + y x 0 + said x 0 gives 506 00:25:52,470 --> 00:25:59,370 us a F X Y is even simpler we're not too 507 00:25:56,850 --> 00:26:02,100 concerned about the X component we just 508 00:25:59,370 --> 00:26:04,290 want F and nothing else and similarly 509 00:26:02,100 --> 00:26:06,960 for the Z we don't compare about the X 510 00:26:04,290 --> 00:26:09,510 component either nor the Y but we do 511 00:26:06,960 --> 00:26:11,610 concern ourselves with Q but we've got 512 00:26:09,510 --> 00:26:12,870 some interesting addition to Zed that 513 00:26:11,610 --> 00:26:14,280 we've got to have this little offset 514 00:26:12,870 --> 00:26:15,960 that's okay 515 00:26:14,280 --> 00:26:18,110 because as we're performing the matrix 516 00:26:15,960 --> 00:26:21,180 calculation we're summing this column 517 00:26:18,110 --> 00:26:25,470 multiplied by the vector so I can simply 518 00:26:21,180 --> 00:26:32,250 include as one of the elements - Zed 519 00:26:25,470 --> 00:26:34,620 near Q but hang on we've suddenly got 520 00:26:32,250 --> 00:26:37,050 four elements in this column and we've 521 00:26:34,620 --> 00:26:39,090 only got three elements of our vector as 522 00:26:37,050 --> 00:26:43,490 an input so to make this happen 523 00:26:39,090 --> 00:26:46,590 I'm going to extend our input vector 524 00:26:43,490 --> 00:26:49,470 with a 1 this of course also means I 525 00:26:46,590 --> 00:26:51,300 have to put in additional zeros for the 526 00:26:49,470 --> 00:26:53,340 x and y elements but now I've got an 527 00:26:51,300 --> 00:26:56,970 interesting scenario of multiplying a 528 00:26:53,340 --> 00:26:59,520 four by one vector by a 3 by 4 matrix I 529 00:26:56,970 --> 00:27:01,500 have to use the final column of a four 530 00:26:59,520 --> 00:27:05,610 by four matrix to make this legitimate 531 00:27:01,500 --> 00:27:08,400 so let me just fill in Zed Q - Zed near 532 00:27:05,610 --> 00:27:10,860 Q so what do we do with this fourth 533 00:27:08,400 --> 00:27:13,560 column well you may also notice that 534 00:27:10,860 --> 00:27:15,810 we've not got to divide by Z anywhere in 535 00:27:13,560 --> 00:27:18,270 there and I can't readily do that in 536 00:27:15,810 --> 00:27:20,280 this calculation getting the divided by 537 00:27:18,270 --> 00:27:22,110 Zed is going to need to be a second 538 00:27:20,280 --> 00:27:24,570 operation in fact we're going to be 539 00:27:22,110 --> 00:27:27,690 normalizing the vector with the Z value 540 00:27:24,570 --> 00:27:32,850 so I do want to extract it and to do 541 00:27:27,690 --> 00:27:34,380 this I'm going to 0 0 1 0 so this will 542 00:27:32,850 --> 00:27:36,420 give me a fourth component of my 543 00:27:34,380 --> 00:27:39,960 transformed vector which will simply be 544 00:27:36,420 --> 00:27:41,910 Z and after I've performed the 545 00:27:39,960 --> 00:27:46,980 transformation and then going to take 546 00:27:41,910 --> 00:27:50,600 the last element of this vector and use 547 00:27:46,980 --> 00:27:50,600 it to divide the others 548 00:27:52,140 --> 00:27:56,530 giving us a coordinate in Cartesian 549 00:27:54,700 --> 00:27:58,870 space and so where we bring this 550 00:27:56,530 --> 00:28:01,630 structure all together is one this is 551 00:27:58,870 --> 00:28:04,120 called the projection matrix and yes it 552 00:28:01,630 --> 00:28:05,380 may seem like a scary bunch of maths but 553 00:28:04,120 --> 00:28:07,300 this is actually probably one of the 554 00:28:05,380 --> 00:28:09,330 more complicated transforms that we'll 555 00:28:07,300 --> 00:28:12,010 need to do as part of the 3d engine and 556 00:28:09,330 --> 00:28:13,660 as I've mentioned before you can really 557 00:28:12,010 --> 00:28:16,210 treat it like a black box this 558 00:28:13,660 --> 00:28:17,800 projection matrix will work for all 3d 559 00:28:16,210 --> 00:28:19,870 applications and it's highly 560 00:28:17,800 --> 00:28:23,170 customizable in terms of aspect ratio 561 00:28:19,870 --> 00:28:24,700 field of view and viewing distance so 562 00:28:23,170 --> 00:28:29,020 this means of course we now need a 563 00:28:24,700 --> 00:28:34,150 matrix structure I'm going to call it 564 00:28:29,020 --> 00:28:38,100 4x4 and I'm simply going to define a two 565 00:28:34,150 --> 00:28:41,380 dimensional array explicitly and 566 00:28:38,100 --> 00:28:44,020 initialize it to zero and the ordering 567 00:28:41,380 --> 00:28:45,970 of this matrix is row followed by column 568 00:28:44,020 --> 00:28:49,480 I'm going to populate the projection 569 00:28:45,970 --> 00:28:51,220 matrix once in on user create because 570 00:28:49,480 --> 00:28:52,450 the screen dimensions and field of view 571 00:28:51,220 --> 00:28:53,380 are not going to change in my 572 00:28:52,450 --> 00:28:56,170 application 573 00:28:53,380 --> 00:28:59,380 we'll have our near plane distance along 574 00:28:56,170 --> 00:29:02,370 the z axis and to set that to not point 575 00:28:59,380 --> 00:29:05,760 what we're going to need the far plane 576 00:29:02,370 --> 00:29:08,290 which I'm going to set to a thousand 577 00:29:05,760 --> 00:29:11,740 let's not forget the important field of 578 00:29:08,290 --> 00:29:16,440 view which I'm going to set to be 90 579 00:29:11,740 --> 00:29:16,440 degrees next up is the aspect ratio 580 00:29:19,020 --> 00:29:23,350 which I'm going to grab directly from 581 00:29:21,520 --> 00:29:27,000 the console so it doesn't really matter 582 00:29:23,350 --> 00:29:27,000 what size console you create 583 00:29:30,550 --> 00:29:38,520 and for convenience I'm going to do the 584 00:29:33,940 --> 00:29:38,520 tangent calculation as a one-off and 585 00:29:47,010 --> 00:29:52,660 you'll notice here I've converted it 586 00:29:49,450 --> 00:29:57,430 from degrees to radians let's create a 587 00:29:52,660 --> 00:30:00,370 projection matrix mat proj that's quite 588 00:29:57,430 --> 00:30:04,480 customary and I'm going to specify the 589 00:30:00,370 --> 00:30:07,720 elements of the matrix directly row 590 00:30:04,480 --> 00:30:10,350 column so we know that this is our W X 591 00:30:07,720 --> 00:30:15,250 value that we've just seen in the slides 592 00:30:10,350 --> 00:30:23,950 which was our aspect ratio times our 593 00:30:15,250 --> 00:30:26,370 tangent calculation our H Y value was 594 00:30:23,950 --> 00:30:29,290 just the tangent calculation directly 595 00:30:26,370 --> 00:30:32,110 and here I've just filled in the 596 00:30:29,290 --> 00:30:33,760 remaining options I've got a sneaking 597 00:30:32,110 --> 00:30:37,120 suspicion that we're going to be doing 598 00:30:33,760 --> 00:30:38,500 matrix vector multiplications a lot so 599 00:30:37,120 --> 00:30:43,750 I'm going to create a function to do it 600 00:30:38,500 --> 00:30:47,170 for me and so we're going to input one 601 00:30:43,750 --> 00:30:49,600 of our vectors and I want to get a 602 00:30:47,170 --> 00:30:53,410 different output vector because I don't 603 00:30:49,600 --> 00:30:58,060 want to upset the input data and we need 604 00:30:53,410 --> 00:31:01,210 to pass in the matrix performing the 605 00:30:58,060 --> 00:31:03,880 multiplication is simple and I'm going 606 00:31:01,210 --> 00:31:06,430 to write the x y&z components directly 607 00:31:03,880 --> 00:31:09,070 to the output vector but don't forget we 608 00:31:06,430 --> 00:31:11,440 had a mysterious fourth element which 609 00:31:09,070 --> 00:31:13,750 I'm going to call W and we have to 610 00:31:11,440 --> 00:31:16,180 include this when we're multiplying by 611 00:31:13,750 --> 00:31:18,160 four by four matrix the only thing to 612 00:31:16,180 --> 00:31:20,320 remember is that we're implying that the 613 00:31:18,160 --> 00:31:23,350 fourth element of the input vector is 614 00:31:20,320 --> 00:31:25,960 one so we can simply sum the final 615 00:31:23,350 --> 00:31:28,210 matrix element now because we've got 616 00:31:25,960 --> 00:31:30,340 four D and we need to get back to 3d 617 00:31:28,210 --> 00:31:33,730 Cartesian space we're going to divide it 618 00:31:30,340 --> 00:31:35,980 by element W but I don't want to do that 619 00:31:33,730 --> 00:31:40,630 if W is equal to zero that's going to 620 00:31:35,980 --> 00:31:43,510 cause me headaches so if W is not zero 621 00:31:40,630 --> 00:31:54,670 then I want to take the output values 622 00:31:43,510 --> 00:31:56,650 and divide them by the W now let's have 623 00:31:54,670 --> 00:31:59,530 a think about how we draw the triangles 624 00:31:56,650 --> 00:32:01,000 using our projection matrix we know that 625 00:31:59,530 --> 00:32:05,140 we're going through this Auto for loop 626 00:32:01,000 --> 00:32:06,400 picking out each triangle at the time we 627 00:32:05,140 --> 00:32:08,050 don't want to upset the original 628 00:32:06,400 --> 00:32:12,820 triangles so I'm going to create a new 629 00:32:08,050 --> 00:32:14,530 triangle called tri projected and tri 630 00:32:12,820 --> 00:32:17,650 projected is where I'm going to put the 631 00:32:14,530 --> 00:32:21,190 result of my matrix multiplication so 632 00:32:17,650 --> 00:32:24,580 I've got the input tri tri projected as 633 00:32:21,190 --> 00:32:26,280 the output and map proj as the matrix 634 00:32:24,580 --> 00:32:28,240 we're going to use in our multiplication 635 00:32:26,280 --> 00:32:30,430 however we can't use the triangle 636 00:32:28,240 --> 00:32:36,880 directly and we need to reference the 637 00:32:30,430 --> 00:32:41,710 vertex inside and I'm going to repeat 638 00:32:36,880 --> 00:32:43,900 this for the three vertices I like the 639 00:32:41,710 --> 00:32:45,940 fact that it's explicit quite a while 640 00:32:43,900 --> 00:32:48,220 ago now I added to the console game 641 00:32:45,940 --> 00:32:50,500 engine the ability to draw a triangle 642 00:32:48,220 --> 00:32:52,750 and this simply draws three lines 643 00:32:50,500 --> 00:32:55,870 between the three coordinates that are 644 00:32:52,750 --> 00:32:57,520 specified using the original draw line 645 00:32:55,870 --> 00:32:59,860 function which has been around since the 646 00:32:57,520 --> 00:33:06,070 beginning this makes drawing a triangle 647 00:32:59,860 --> 00:33:08,950 a little simpler I'm going to take the x 648 00:33:06,070 --> 00:33:10,270 coordinate and we'll do some cut and 649 00:33:08,950 --> 00:33:16,750 paste here just to speed it up a little 650 00:33:10,270 --> 00:33:19,480 bit and the y coordinate of 0.1 I'll do 651 00:33:16,750 --> 00:33:21,130 point two and point three and the final 652 00:33:19,480 --> 00:33:23,700 two arguments and how it appears on the 653 00:33:21,130 --> 00:33:25,870 screen so I want to use solid pixels and 654 00:33:23,700 --> 00:33:31,030 I'm just going to draw everything in 655 00:33:25,870 --> 00:33:32,770 white so let's take a look well I can't 656 00:33:31,030 --> 00:33:35,350 see a cube there but what I can see 657 00:33:32,770 --> 00:33:38,200 right up in the top corner is a single 658 00:33:35,350 --> 00:33:40,540 pixel and in a way this is to be 659 00:33:38,200 --> 00:33:42,580 expected because our projection matrix 660 00:33:40,540 --> 00:33:45,550 has given us results between minus one 661 00:33:42,580 --> 00:33:49,840 and plus one so now we need to scale 662 00:33:45,550 --> 00:33:52,480 that field into the viewing area of the 663 00:33:49,840 --> 00:33:54,310 console screen so the first thing I'm 664 00:33:52,480 --> 00:33:57,250 going to do is take a coordinate and 665 00:33:54,310 --> 00:34:04,150 shift it to between zero and 666 00:33:57,250 --> 00:34:05,200 - I'll do that for both x and y and I 667 00:34:04,150 --> 00:34:06,880 know this is where people will be 668 00:34:05,200 --> 00:34:08,440 screaming at me why are you not making a 669 00:34:06,880 --> 00:34:10,389 special vector class why are you not 670 00:34:08,440 --> 00:34:16,090 using operator overloading and we'll 671 00:34:10,389 --> 00:34:20,950 come to that in later videos so let's do 672 00:34:16,090 --> 00:34:23,349 that for all three points so now it's 673 00:34:20,950 --> 00:34:26,320 between 0 & 2 I want to divide it by 2 674 00:34:23,349 --> 00:34:32,800 and scale it to the appropriate size for 675 00:34:26,320 --> 00:34:38,800 that axis I'll take the X and I'm going 676 00:34:32,800 --> 00:34:43,480 to multiply it by 1/2 times the screen 677 00:34:38,800 --> 00:34:46,480 width and you'll see here I've just done 678 00:34:43,480 --> 00:34:52,060 it for the other two vertices as well so 679 00:34:46,480 --> 00:34:54,700 let's take a look well I can certainly 680 00:34:52,060 --> 00:34:56,980 see what looks to be a cube and some 681 00:34:54,700 --> 00:34:57,400 triangles but something's not quite 682 00:34:56,980 --> 00:35:00,340 right 683 00:34:57,400 --> 00:35:02,650 there's no perspective on this and I'm 684 00:35:00,340 --> 00:35:04,960 not really sure of the orientation so 685 00:35:02,650 --> 00:35:07,930 what can be going wrong here well simply 686 00:35:04,960 --> 00:35:10,119 put our cube has its origin at 0 and our 687 00:35:07,930 --> 00:35:14,320 current viewing to the world is also at 688 00:35:10,119 --> 00:35:16,510 location 0 and so this means our face 689 00:35:14,320 --> 00:35:19,720 for example could very well be inside 690 00:35:16,510 --> 00:35:22,270 the cube at this location that means 691 00:35:19,720 --> 00:35:24,280 some of the cube is behind us and we're 692 00:35:22,270 --> 00:35:27,190 still trying to draw it and this is 693 00:35:24,280 --> 00:35:28,960 undefined so it's not unsurprising that 694 00:35:27,190 --> 00:35:30,790 the result is a little bit useless at 695 00:35:28,960 --> 00:35:33,790 the moment what we need to do is 696 00:35:30,790 --> 00:35:36,700 translate our cube into the world away 697 00:35:33,790 --> 00:35:38,380 from where the camera would be so 698 00:35:36,700 --> 00:35:42,839 instead of projecting the triangle 699 00:35:38,380 --> 00:35:42,839 directly I want to translate it first 700 00:35:45,210 --> 00:35:50,740 and this is easily done for translation 701 00:35:48,040 --> 00:35:54,010 and all we want to do is offset the 702 00:35:50,740 --> 00:35:56,440 triangle in the z-axis into the screen 703 00:35:54,010 --> 00:35:58,720 so we'll add 3 to all of the Zed 704 00:35:56,440 --> 00:36:02,500 components of the triangle into our new 705 00:35:58,720 --> 00:36:04,000 triangle triangle translated so this is 706 00:36:02,500 --> 00:36:06,420 no longer the triangle we wish to 707 00:36:04,000 --> 00:36:06,420 project 708 00:36:08,099 --> 00:36:14,920 let's take a look and see if this has 709 00:36:10,420 --> 00:36:16,749 made it any clearer perfect we've 710 00:36:14,920 --> 00:36:19,690 definitely got some perspective action 711 00:36:16,749 --> 00:36:21,460 going on now but because the scene is 712 00:36:19,690 --> 00:36:23,950 static we can't really get a feel for 713 00:36:21,460 --> 00:36:26,470 what's happening in 3d so I'm not going 714 00:36:23,950 --> 00:36:28,930 to rotate the cube around its X and its 715 00:36:26,470 --> 00:36:30,999 z-axis I'm not going to do the rotations 716 00:36:28,930 --> 00:36:33,160 at the same speed because we'll become a 717 00:36:30,999 --> 00:36:35,200 victim of what's called gimbal lock 718 00:36:33,160 --> 00:36:36,880 so I'll bias the rotations per axis 719 00:36:35,200 --> 00:36:38,769 differently I'm going to add two more 720 00:36:36,880 --> 00:36:42,339 matrices that can perform the rotation 721 00:36:38,769 --> 00:36:44,259 transform around a specific axis now I'm 722 00:36:42,339 --> 00:36:45,880 pretty sure the mathematicians out there 723 00:36:44,259 --> 00:36:47,740 will start screaming while surely we can 724 00:36:45,880 --> 00:36:50,470 combine all of these matrices with 725 00:36:47,740 --> 00:36:53,200 matrix multiplications and we can but 726 00:36:50,470 --> 00:36:54,789 I'm not going to do in this video to 727 00:36:53,200 --> 00:36:56,380 give the impression that something is 728 00:36:54,789 --> 00:36:58,420 rotating I'm going to need an angle 729 00:36:56,380 --> 00:37:00,460 value that changes over time so I'm 730 00:36:58,420 --> 00:37:03,309 going to accumulate the elapsed time in 731 00:37:00,460 --> 00:37:05,950 a variable called F theta and I'm going 732 00:37:03,309 --> 00:37:08,230 to hard-code two rotation matrices one 733 00:37:05,950 --> 00:37:10,720 for the Zed axis and one for the x axis 734 00:37:08,230 --> 00:37:13,180 you can look these up on Wikipedia it's 735 00:37:10,720 --> 00:37:15,430 fairly standard and they work in quite a 736 00:37:13,180 --> 00:37:18,190 similar way as the rotation matrix that 737 00:37:15,430 --> 00:37:20,230 I derived in the asteroids video since 738 00:37:18,190 --> 00:37:22,299 we're not multiplying matrices just yet 739 00:37:20,230 --> 00:37:24,549 I'm going to need more triangle States 740 00:37:22,299 --> 00:37:27,039 for the intermediate transformations and 741 00:37:24,549 --> 00:37:29,289 I still want my translation to be the 742 00:37:27,039 --> 00:37:31,690 last thing that I do because the order 743 00:37:29,289 --> 00:37:33,880 of transformations is quite important I 744 00:37:31,690 --> 00:37:36,759 want to rotate it around the origin of 745 00:37:33,880 --> 00:37:39,339 the object which is currently 0 0 0 and 746 00:37:36,759 --> 00:37:42,009 then once it's rotated I want to 747 00:37:39,339 --> 00:37:44,920 translate the rotated object further 748 00:37:42,009 --> 00:37:46,660 into the Z plane so taking the original 749 00:37:44,920 --> 00:37:50,950 triangle the first thing I'm going to do 750 00:37:46,660 --> 00:37:53,349 is rotate it in the z axis the second 751 00:37:50,950 --> 00:37:56,349 thing I want to do is rotate it in the x 752 00:37:53,349 --> 00:37:59,349 axis I then want to update my 753 00:37:56,349 --> 00:38:02,380 translation code to use the most 754 00:37:59,349 --> 00:38:06,309 up-to-date triangle so now let's take a 755 00:38:02,380 --> 00:38:08,680 look and immediately I think that's 756 00:38:06,309 --> 00:38:11,079 perfect look at that a perfect cube 757 00:38:08,680 --> 00:38:13,690 projected evenly and nicely onto the 758 00:38:11,079 --> 00:38:17,849 screen rotating smoothly and the 759 00:38:13,690 --> 00:38:17,849 triangles and the faces are very visible 760 00:38:19,930 --> 00:38:25,160 and so that's that for part 1 of this 761 00:38:22,549 --> 00:38:27,349 series in the next part we'll be looking 762 00:38:25,160 --> 00:38:28,819 at how we can control the camera and 763 00:38:27,349 --> 00:38:32,329 we'll also be looking how we can shade 764 00:38:28,819 --> 00:38:33,799 the faces of the object as usual all the 765 00:38:32,329 --> 00:38:36,380 source code is going to be available on 766 00:38:33,799 --> 00:38:38,180 github please join the discourse server 767 00:38:36,380 --> 00:38:39,739 and come and have a discussion if you've 768 00:38:38,180 --> 00:38:41,119 enjoyed this video give me a big thumbs 769 00:38:39,739 --> 00:38:45,339 up please and have a think about 770 00:38:41,119 --> 00:38:45,339 subscribing until next time take care 58934

Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.