1 00:00:01,583 --> 00:00:04,195 We will now discuss the matrix stacks 2 00:00:04,195 --> 00:00:08,176 and transforms that we need in OpenGL, 3 00:00:08,176 --> 00:00:12,343 especially in the context of drawing the four pillars. 4 00:00:14,385 --> 00:00:18,866 Let's first summarize the entire OpenGL pipeline 5 00:00:18,866 --> 00:00:21,758 for vertex transformations. 6 00:00:21,758 --> 00:00:26,092 We start with an object defined in object coordinates 7 00:00:26,092 --> 00:00:29,303 that's in the native coordinate system of the object. 8 00:00:29,303 --> 00:00:30,972 In our case, this will always be 9 00:00:30,972 --> 00:00:34,990 in homogeneous coordinates (x,y,z,w). 10 00:00:34,990 --> 00:00:38,498 Thereafter you apply the modelview transforms 11 00:00:38,498 --> 00:00:42,116 which corresponds to the modelview matrix. 12 00:00:42,116 --> 00:00:45,609 Note that this has both a model transformation, 13 00:00:45,609 --> 00:00:48,002 which is the object transformation, 14 00:00:48,002 --> 00:00:52,169 and the view transformation, which is glm::lookAt, 15 00:00:53,335 --> 00:00:57,308 which positions the camera appropriately. 16 00:00:57,308 --> 00:01:00,891 Thereafter you apply the projection matrix, 17 00:01:02,265 --> 00:01:04,348 which goes from 3D to 2D, 18 00:01:05,187 --> 00:01:08,604 and this corresponds to glm::perspective. 19 00:01:10,219 --> 00:01:14,016 Now, the eye coordinates are obtained 20 00:01:14,016 --> 00:01:16,607 after the modelview transformation; 21 00:01:16,607 --> 00:01:19,171 actually, before the projection transformation, 22 00:01:19,171 --> 00:01:22,357 and those correspond to the coordinates 23 00:01:22,357 --> 00:01:25,407 in the 3D world for lighting. 24 00:01:25,407 --> 00:01:28,449 But after you have the projection transformation, 25 00:01:28,449 --> 00:01:31,977 then what you get are clip coordinates. 26 00:01:31,977 --> 00:01:34,560 Here everything is in the range 27 00:01:36,289 --> 00:01:38,447 of -1 to +1. 28 00:01:38,447 --> 00:01:42,289 We are mapping the world essentially into a unit cube, 29 00:01:42,289 --> 00:01:43,831 actually, a cube of two units, 30 00:01:43,831 --> 00:01:46,081 from -1 to +1. 31 00:01:47,039 --> 00:01:48,388 After this, you can do 32 00:01:48,388 --> 00:01:52,037 the prospective division of dehomogenization, 33 00:01:52,037 --> 00:01:53,771 whereupon you get what is known 34 00:01:53,771 --> 00:01:56,518 as normalized device coordinates, 35 00:01:56,518 --> 00:02:00,474 which are then moved on to the pixels in the screen 36 00:02:00,474 --> 00:02:02,938 by using the viewport transformation 37 00:02:02,938 --> 00:02:05,771 and finally appear on your window. 38 00:02:07,366 --> 00:02:10,174 We are most interested in this lecture 39 00:02:10,174 --> 00:02:13,596 in the modelview and projection transformations, 40 00:02:13,596 --> 00:02:17,497 which are usually represented using matrix stacks 41 00:02:17,497 --> 00:02:21,719 corresponding to the modelview and projection matrices. 42 00:02:21,719 --> 00:02:24,166 Matrix stacks are especially useful 43 00:02:24,166 --> 00:02:27,355 for hierarchically defined figures 44 00:02:27,355 --> 00:02:31,185 such as you have a human body with a torso, 45 00:02:31,185 --> 00:02:33,769 then you have the hands, the legs, 46 00:02:33,769 --> 00:02:35,360 and effectively you can see this 47 00:02:35,360 --> 00:02:38,392 as being a scene graph in OpenGL 48 00:02:38,392 --> 00:02:41,182 or a hierarchy of different shapes. 49 00:02:41,182 --> 00:02:43,342 They're also very useful in our case 50 00:02:43,342 --> 00:02:45,367 for placing the pillars where we have 51 00:02:45,367 --> 00:02:47,282 the same geometry for the pillars, 52 00:02:47,282 --> 00:02:48,577 but we are placing them 53 00:02:48,577 --> 00:02:51,958 with different transformations and different colors. 54 00:02:51,958 --> 00:02:53,230 In old OpenGL, 55 00:02:53,230 --> 00:02:56,901 matrix stacks were handled with a number of GL commands, 56 00:02:56,901 --> 00:02:59,734 such as glPushMatrix, glPopMatrix, 57 00:03:00,721 --> 00:03:03,249 glLoad a matrix onto the stack, 58 00:03:03,249 --> 00:03:07,139 glMult(iply) a matrix to the right of the stack. 59 00:03:07,139 --> 00:03:09,900 However, these are all deprecated, 60 00:03:09,900 --> 00:03:11,862 and the current recommendation is 61 00:03:11,862 --> 00:03:14,112 you maintain the stack yourself 62 00:03:14,112 --> 00:03:17,973 either using STL commands in C++ 63 00:03:17,973 --> 00:03:20,123 or using any other technique, 64 00:03:20,123 --> 00:03:23,412 and this is in fact what is done in mytest2, 65 00:03:23,412 --> 00:03:28,331 and you must manage the stack yourself for homework 2. 66 00:03:28,331 --> 00:03:30,962 As far as the transformations are concerned, 67 00:03:30,962 --> 00:03:34,743 we write our own translate, scale, and rotate, 68 00:03:34,743 --> 00:03:36,113 and you will need to do that 69 00:03:36,113 --> 00:03:39,271 for homework 1 and homework 2. 70 00:03:39,271 --> 00:03:42,758 Be somewhat careful of OpenGL convention. 71 00:03:42,758 --> 00:03:44,855 In old-style OpenGL, 72 00:03:44,855 --> 00:03:48,105 one right-multiplies the current matrix 73 00:03:49,554 --> 00:03:51,362 on top of the stack, 74 00:03:51,362 --> 00:03:54,329 which essentially means the last command in code 75 00:03:54,329 --> 00:03:56,789 is the first applied. 76 00:03:56,789 --> 00:03:59,881 glm operations essentially follow this, 77 00:03:59,881 --> 00:04:02,760 but when you are doing the multiplication, 78 00:04:02,760 --> 00:04:06,277 you need to be careful to follow this. 79 00:04:06,277 --> 00:04:08,910 In old OpenGL, we also had commands 80 00:04:08,910 --> 00:04:12,315 like gluLookAt and gluPerspective, 81 00:04:12,315 --> 00:04:13,994 which have the glm equivalents 82 00:04:13,994 --> 00:04:17,514 of glm::lookAt and glm::perspective, 83 00:04:17,514 --> 00:04:22,126 and these are just matrices like any other transform. 84 00:04:22,126 --> 00:04:25,208 They right-multiply the top of the stack. 85 00:04:25,208 --> 00:04:27,307 But that is the way in which you implement 86 00:04:27,307 --> 00:04:30,266 the modelview and projection matrices. 87 00:04:30,266 --> 00:04:32,234 If you are stuck on how to implement 88 00:04:32,234 --> 00:04:34,306 these concepts in homework 2, 89 00:04:34,306 --> 00:04:36,518 look at the mytest sequence of demos, 90 00:04:36,518 --> 00:04:38,480 which will give you some ideas 91 00:04:38,480 --> 00:04:40,980 of how to best implement this. 92 00:04:42,387 --> 00:04:44,914 Let us talk about drawing the pillars 93 00:04:44,914 --> 00:04:47,307 in the display routine. 94 00:04:47,307 --> 00:04:50,061 In the first pillar we right-multiply 95 00:04:50,061 --> 00:04:53,075 the modelview as in old OpenGL. 96 00:04:53,075 --> 00:04:55,746 Notice that the entire pillar drawing 97 00:04:55,746 --> 00:04:59,850 is between these pushMatrix and popMatrix blocks. 98 00:04:59,850 --> 00:05:00,875 In old OpenGL, 99 00:05:00,875 --> 00:05:05,094 these would be glPushMatrix and glPopMatrix. 100 00:05:05,094 --> 00:05:08,227 In our case, we have to implement it ourselves, 101 00:05:08,227 --> 00:05:11,260 and so we push the matrix modelview on the stack, 102 00:05:11,260 --> 00:05:13,664 pop the matrix modelview from the stack. 103 00:05:13,664 --> 00:05:16,381 We'll show the stack commands in a bit. 104 00:05:16,381 --> 00:05:18,902 But let's look at the code within that. 105 00:05:18,902 --> 00:05:21,852 So first we right-multiply the modelview matrix 106 00:05:21,852 --> 00:05:23,269 as in old OpenGL. 107 00:05:24,219 --> 00:05:28,386 modelview is equal to modelview * glm::translate. 108 00:05:29,447 --> 00:05:31,872 The inputs for glm::translate 109 00:05:31,872 --> 00:05:35,372 are the matrix that you want to multiply by, 110 00:05:35,372 --> 00:05:37,729 which in this case is just the identity, 111 00:05:37,729 --> 00:05:40,642 and you have the translation amount, 112 00:05:40,642 --> 00:05:44,809 which is simply a vec3(-0.4,-0.4,0.0). 113 00:05:46,491 --> 00:05:49,822 This just builds the translation matrix. 114 00:05:49,822 --> 00:05:53,773 The next command is this glUniformMatrix4fv, 115 00:05:53,773 --> 00:05:57,253 which simply provides the modelview matrix 116 00:05:57,253 --> 00:06:00,333 as a uniform mat4 to the shader, 117 00:06:00,333 --> 00:06:04,083 and it does it in location modelviewPos. 118 00:06:04,083 --> 00:06:06,030 You're only providing one matrix, 119 00:06:06,030 --> 00:06:07,944 you don't transpose this matrix, 120 00:06:07,944 --> 00:06:09,996 and you give it the input 121 00:06:09,996 --> 00:06:12,398 for the first element of the matrix. 122 00:06:12,398 --> 00:06:16,531 That's what the &(modelview)[0][0] stands for. 123 00:06:16,531 --> 00:06:18,927 The second pillar is exactly the same code, 124 00:06:18,927 --> 00:06:22,198 except now the translation is different, 125 00:06:22,198 --> 00:06:25,589 so it goes to (0.4, -0.4, 0) 126 00:06:25,589 --> 00:06:29,089 instead of (-0.4, -0.4, 0). 127 00:06:30,610 --> 00:06:33,877 We have the same glUniformMatrix4fv, 128 00:06:33,877 --> 00:06:36,405 and we draw the cube. 129 00:06:36,405 --> 00:06:40,768 In this case it's drawcolor of CUBE with color 1. 130 00:06:40,768 --> 00:06:43,432 So color 0 corresponds to red, 131 00:06:43,432 --> 00:06:47,745 color 1 corresponds to green, and so on. 132 00:06:47,745 --> 00:06:49,810 We now talk about the third pillar, 133 00:06:49,810 --> 00:06:52,626 which is exactly the same, 134 00:06:52,626 --> 00:06:54,185 and the fourth pillar, 135 00:06:54,185 --> 00:06:56,852 which is again exactly the same. 136 00:07:00,536 --> 00:07:05,105 Let's look at what our push and pop functions correspond to. 137 00:07:05,105 --> 00:07:08,885 In this case, we need to implement them ourselves. 138 00:07:08,885 --> 00:07:10,687 The pushMatrix function, 139 00:07:10,687 --> 00:07:14,133 given a matrix which is, in this case, the modelview matrix, 140 00:07:14,133 --> 00:07:17,013 pushes it onto the modelview stack. 141 00:07:17,013 --> 00:07:20,358 Earlier we defined the stack of mat4 142 00:07:20,358 --> 00:07:21,836 for modelviewStack. 143 00:07:21,836 --> 00:07:25,669 And you push the matrix corresponding to that. 144 00:07:27,836 --> 00:07:30,420 The popMatrix function pops the matrix 145 00:07:30,420 --> 00:07:32,503 from the modelview stack. 146 00:07:34,135 --> 00:07:36,745 It is a void function, 147 00:07:36,745 --> 00:07:39,995 so it's the void popMatrix function, 148 00:07:39,995 --> 00:07:43,245 and it checks the modelview stack size. 149 00:07:44,897 --> 00:07:48,515 If there is a matrix on the modelview stack, 150 00:07:48,515 --> 00:07:50,899 then you return this matrix. 151 00:07:50,899 --> 00:07:52,869 So you would set mat is equal 152 00:07:52,869 --> 00:07:56,275 to the top element of the stack. 153 00:07:56,275 --> 00:07:59,218 That's what modelviewStack.back() does, 154 00:07:59,218 --> 00:08:03,554 and the pop_back() just removes that element from the stack. 155 00:08:03,554 --> 00:08:06,774 Otherwise you just set it to the identity 156 00:08:06,774 --> 00:08:10,607 to prevent errors when popping an empty stack. 157 00:08:11,494 --> 00:08:13,911 Let me now show you demo 1, 158 00:08:14,783 --> 00:08:19,765 which has not just the floor, but also the pillars. 159 00:08:19,765 --> 00:08:22,013 First I want to refresh your memory. 160 00:08:22,013 --> 00:08:25,044 This is demo 0, which is essentially mytest1, 161 00:08:25,044 --> 00:08:27,127 which has just the floor. 162 00:08:28,744 --> 00:08:33,109 Now we have this DEMO variable which I alluded to earlier, 163 00:08:33,109 --> 00:08:35,109 and I can set it to 1. 164 00:08:36,482 --> 00:08:40,620 Notice that the demo variable is used in a lot of places. 165 00:08:40,620 --> 00:08:43,422 See here I say DEMO >= 2 166 00:08:43,422 --> 00:08:45,810 Here I say if (DEMO > 0) 167 00:08:45,810 --> 00:08:48,116 then I actually draw the pillars, 168 00:08:48,116 --> 00:08:51,949 which is exactly the same code we saw earlier. 169 00:08:53,298 --> 00:08:56,881 And notice that I'm drawing the floor here. 170 00:08:58,636 --> 00:09:03,000 Having done this, I exit out of my program, 171 00:09:03,000 --> 00:09:06,417 I compile, and now I can run the program. 172 00:09:10,851 --> 00:09:14,138 Here I just have my floor and my four pillars. 173 00:09:14,138 --> 00:09:16,707 I can move in and out as before. 174 00:09:16,707 --> 00:09:19,290 This is working perfectly fine, 175 00:09:21,033 --> 00:09:23,519 but I have a question for you, 176 00:09:23,519 --> 00:09:27,016 which is does the order of drawing matter? 177 00:09:27,016 --> 00:09:30,875 What if I move the floor which I drew first 178 00:09:30,875 --> 00:09:33,399 after the pillars in the code, 179 00:09:33,399 --> 00:09:37,220 and is this desirable, or if not, what can I do about it? 180 00:09:37,220 --> 00:09:39,973 So think about this for a little bit 181 00:09:39,973 --> 00:09:43,898 while I write the code to change that. 182 00:09:43,898 --> 00:09:47,425 The code to change that is very simple. 183 00:09:47,425 --> 00:09:51,508 I will comment out the floor drawing routine here 184 00:09:53,345 --> 00:09:56,095 and instead, I will add it later. 185 00:10:04,409 --> 00:10:06,524 So see, does the order of drawing matter? 186 00:10:06,524 --> 00:10:08,944 What happens if I put it here? 187 00:10:08,944 --> 00:10:11,518 For convenience, I have already included 188 00:10:11,518 --> 00:10:14,268 the commands here with a comment. 189 00:10:17,591 --> 00:10:19,841 I go back now to my program 190 00:10:21,135 --> 00:10:23,302 and I will exit out of it. 191 00:10:24,656 --> 00:10:26,265 I make the new program 192 00:10:26,265 --> 00:10:29,682 where I changed the order of the drawing. 193 00:10:31,870 --> 00:10:36,000 And voila, the floor now appears on top of the pillars. 194 00:10:36,000 --> 00:10:37,360 This is not surprising, 195 00:10:37,360 --> 00:10:39,619 because I specified the drawing 196 00:10:39,619 --> 00:10:41,472 for the floor after the pillars, 197 00:10:41,472 --> 00:10:44,030 so it's reasonable it should overwrite the pillars, 198 00:10:44,030 --> 00:10:46,269 but this is not the desirable behavior, 199 00:10:46,269 --> 00:10:51,231 because the floor actually lies behind the pillars. 200 00:10:51,231 --> 00:10:52,405 In the next segment, 201 00:10:52,405 --> 00:10:56,572 we will talk about z-buffering to address this issue.