 Welcome back cat from scratch episode 13 Topic today is implementing some better cat controls and overall feel to our program So if I run the code from last time you can see some of the problems we have so First problem is obviously we can move the model around Rotate it around we can zoom out and zoom in no problem But we can't pan the model left right up and down You don't have that control built in yet So I want to implement panning panning is basically moving the model You know like I said before up down left right You sometimes want to pan in order to look at small features on the part or zoom in a certain feature on the part right now We're moving the entire sort of camera around a single point in space That's actually gonna be the origin in this particular one So we're looking at a single point in space as our you know look at coordinate But if we're panning or basically moving the look at and the look from coordinates some Direction together, so that's gonna be panning, you know Horizontally panning vertically. That's how we kind of move the the render around what we'll implement something that moves our look from and look at coordinates basically along the U1 and U2 Directions from our model So that's gonna be how that works. I'll talk about that a little bit more later. It's not very complicated. It's pretty simple The next problem that we have is that everything I'm doing now is done with the left mouse button So rotations is done with that mouse button in general in CAD software FBA software CFD software Usually the left click is reserved for Like selecting objects features, you know faces edges vertices that kind of stuff And so and the right mouse button is usually reserved for you know, right clicking setting a property adding a color Extruding adding to a group or whatever. So usually the middle mouse button does most of the heavy lifting for You know moving the model around left right up down rotating it all that stuff So that's the plan is to convert this to a left left click There's gonna create from left click to a middle click. I should say and last thing Is going to be the slow Render so much of you notice this in the past, but if I input a bunch of motion events Which I will do in a second the whole model kind of lags So I'm gonna move the model around for a few seconds and then I'm gonna let go and you'll see what happens Letting go in two seconds one second The model is still moving like I said before it's because there's a bunch of motion events in a queue So whenever we move the mouse a single pixel That's a motion event that we have to handle in our event handling loop And that's lacking the whole thing that the massive list of motion events is very slow So we're gonna address that Now to talk a little bit more about this left click. I want to change the controls from what we have now to these three things here So I want to go from the Left click to rotate to being a middle click to rotate. That's this one Strolling same as we have it now keep that for the zooming in and out and lastly I want to use control as a button To basically toggle on panning mode so control plus middle mouse will be panning left right up and down That's the plan for that So and to talk more about this last slow rendering thing. Let's open up the actual code Every change they will be in the draw.c file So, yeah, so here's our render loop this wild one. It's basically we're stuck in this whenever we're you know Drawing to the screen and so we have a couple of parts this first part here this all the GL stuff This is basically drawing everything Every you know, this is all our uniforms for our shaders. This is the actual polygons This is the fill. This is the lines on the polygons And then we have down here this X next event This is a blocking our function basically every event that we passed through with our cursor with our keyboard Goes through this X next event It puts the event into this event address and we handle that with our if statements down here This is what's lagging everything up actually not just this mostly. I mean this here. This is these X buttons This is us clicking on like Well, this here this X button button one. This is a left mouse click on the screen So button clicks and key presses. They're so fast. They don't block anything up Like I mentioned before though these motion events That's what's locking everything up every pixel that a cursor moves with the left mouse button down is blocking our function So I want to pull this out of the loop basically. So here's how the new suit code will be in our render loop That's this while one this while one here Draw stuff stays the same we have that now if we have a keyboard or mouse event I want to set these flags like left clicking one left clicking zero or the keyboard events control down Zero control down one that would be in this X next event section But out of that section and also the you know the toolbar will be there as well But out of that section. I want to pull these Motion events into the flags alone. And so here we use this X X motion X and Y coordinates to basically give us the cursor location That's a very easy way to do it. But there's actually a better way to do it With this X query pointer function in X win Basically, it's a bunch of garbage here that you have to pass in but what we care about is basically this int X return Y return This gives us if you look down here the pointer coordinates relative to the specified window being W So we'll use this function to basically pull out their cursor location in real time when we need it That means we won't have to go around looking for motion events we can just constantly map the X and Y locations of the cursor to the rotation and Basically do this way way way way faster than what we have now You don't have to handle it every single pixel. We can handle it just at the current location of the cursor So that's going to be good. So the first thing to do is going to be to add a bunch of new Variables that will need and changing some old variables that we currently have so Obviously I mentioned before we're going to be changing the left click to middle clicks I'm going to change this to mid-click. I Will be copying that and I'm making it like one for the control being pushed so control press We'll be using the left control. That's usually what's been implemented. And then I want to have a Boolean here for Whether or not we've begun panning I want to be able to keep track if we're you know, whether or not we're panning or if we are Rotating the model sometimes you may want to be doing both at the same time And I want to be able to keep track of which one is going on at which time now here this x star and y start these integers are the The locations of the cursor when you had inst when you had initially Clicked your buttons. So here x star is the X and Y location of the the cursor when you first clicked Now we're keeping track of two different things now rotating and panning. So I want to make two different starts So we'll say inch x rotating inch y rotating And we'll do same thing for panning panning Float and last sort of big important thing to add here is going to be As I mentioned before here for panning. We are obviously going to be translating our look from and look at Coordinates in space. So I want to be able to keep track of the old value to map properly So I'm gonna say I want to have a look at old size 3 and a look from old size 3 And we're just gonna you know keep we're going to store the initial values When we initially push the control button into these locations so we can kind of keep track of how much we've moved in a very easy way now a couple more variables that Initiate here initialize here. I should say That's gonna be these Garbage variables that we don't care about for this function here x query pointer. So we're gonna make some Dummies, so we'll say window dummy window We'll say int Dummy int we need to unsign int. I believe so we'll say unsign int Dummy you int and last day is the two guys that actually matter is the x cursor and The y cursor we may actually go back and use these things later on for something But for the time being I couldn't care less. So x cursor and y cursor One more thing to change really quick while I can see on the screen is this select input So I mentioned before we're going to be moving away from these motion events I'm gonna get rid of motion mask and we're gonna add in two more events. So key press mask And key release mask That's how we're gonna basically tell if we push control or not so now in our Render loop here. Let's go down to the pseudocode here This will also the same this draw stuff but down here in x next event This I said before was blocking so first thing we're gonna add is something called Expending so we're gonna make a a while Loop around all this called while expending on the display. This basically tells us if we have an event If we have events in the queue And if they're in the queue this will evaluate to one and we should if you do this if not just immediately go into the The rest of the code just keep looping through the render loop giving us more frames per second There's no reason not to so that's what this does Let me See if I can remember how to tab all these at the same time. I Don't think I remember. Let's see if I can just guess Hey, that worked. Okay, so That will include that while loop is around everything except for the Rotations in the panning down below so left clicking, you know all that stuff down here for the Everything about rotating is not going to be in that that while loop That's not going to be an event that's just going to be handled in real time if there is a flag set That means we should take into consideration the cursor being moved So first things couple first things to change is We've actually changed button one to button two button one is the left mouse button But two is the middle mouse button and then button four and five by the way are the middle mouse scroll wheel forward and back We've changed this left clicking to middle click Okay, this x star and y star. This is going to be rotating x rotating y rotating. So we're going to change those variables again down here, this is going to be mid-click and We have to add a couple more lines right here. So We have two more events to handle regarding the control button So that's simple. I'll just show you how to do it if event type equals key press and Event x key key code Equals equals 25 in hex. That's the key code for the control button We're going to do some stuff. We're gonna set the control press Equal to one first off and then we're going to set these look from old values to the Look from values also the same thing for look at I'll do that. I'll be right back in a second Okay, I put those in look from old look at old set the values for look from and look at now I'm going to copy this and Just paste it for the release. So You push the control down now, we're going to release the control And we're going to set Control press to zero I'm gonna set that started panning boolean to zero as well Obviously, maybe we've stopped panning. So stop caring about pans. Oh You know what I think this should be Yeah, this should be here might be Yeah Yeah, that makes more sense to me This is this is not a a button event. This is a key event. So that's my mistake All this can stay the same I I believe nothing is going to change here now down here We have some things to change. This is the routine that we made to rotate the model You can see you're rotating you three about you to so Let's change some of this. So first off left click is now mid-click and Then this motion type thing is all dead. We don't care about motion anymore That's not that's no longer in our purview This X start and Y start this becomes I think rotating Yeah, that's what I call the right rotating and this motion stuff is no longer valid It's just going to be X cursor and Y cursor That's good. So This handles the rotations, but remember we are not just rotating. We're also panning So we're gonna have to do some Some more working with the flags here. So this will be the else and the if will be if we're panning So I'll say if Control press Gonna do some stuff else this So let me Do that magic again really quick Probably messed it up Yeah, so if the control is pressed couple options, so If we've started panning so if started panning No, we've already set our initial values. So we don't we don't care about that any longer But if we have not started panning then we can set the initial values. So let's do that So this values. What am I talking about? Well, I mean the the X panning and the Y panning values and Then of course does that bully me set for started panning that needs to be set here as well, obviously equals one Now I keep using this this X cursor thing and Y cursor. What is that? Well, that's that function. I mentioned earlier So let's show you that function X query pointer all this stuff so Let's just paste this copy that in here. So it was X query pointer It took the display in the window first then it took a bunch of dummy garbage. So we passed in I Think it was two dummy windows Right. Is that right? Yeah, two winners. We don't care about these two then we pass in two ins we don't care about Then we pass in the ins we do care about X cursor and Y cursor the addresses It's gonna basically put the values of the cursor into this address in space That's how this works and then we pass in that dummy unsigned in as well That will basically populate these X cursor and Y cursor values that we're using over and over and over again in this in these these loops So if we started panning here's where the actual math comes in and the math is super simple I mentioned before how we're just gonna translate these things along you want to you too based off How much we've moved the mouse left and right? So let me just give you an example of how that will work oops Let me get some more space here. So so let's say it look at first look at zero We're gonna translate the look at coordinate here. That's this one The X coordinates so this will be a long, you know, it's x-axis. It may not be you one or you two But it's the look the X coordinate of look at it's going to be the old value look at old zero plus some stuff so We'll have the X cursor minus the X panning Value and multiply that simply by the X component of you one So we're adding the X components together here look at zero look at old zero you one zero then we're going to be adding to that the Y cursor values so Y cursor minus Y panning How much we've moved from the initial value? This is the current cursor location. This is the old cursor location So if you've moved 30 pixels in Y, this will be 30 so Times you to zero we're taking the component in you too So Y movement is you to X movement as you want as you would expect because you want this to the right you two is up in our in our implementation here and This Well, basically you're going to scale this By I've been something around like this I think if you scale by point five times the width of the structure of the entire Screen times the scaling factor, which we have already set up that seems to work work well and one last thing though is that You two is up and you want us to the right but X counts to the right and Y counts down in terms of pixels So we're gonna have to change one of the signs on these things. I think we'll change this sign here And I think that will be good. So X for sure. Yeah, so that Yeah, this should be negative that one should be positive Yes, that makes sense to me So I'm gonna copy this a few more times for the other components. I'll look at and look from and I'll be right back Okay, I did that really quick So it's the same thing for look at and look from all the components But said one difference is that the the height here The height is actually a little bit less because we've used the first 20 pixels of our screen for the menu bar so H minus 20 there for H so we can not count the header in terms of the how big our start our Our pain is going to be and it's not a huge difference, but I might as well make it accurate and then I'll set these two values here. Just in case we at some point stop panning go back to rotating with the with the With the middle text still down. So just so we can keep track of this value in a more accurate sense Well, so we'll keep track of it here Okay, um That might be most of the changes to make here I Do believe this all stays the same There is one thing that would change from last time Now because we're panning the model up down left right We're gonna be moving our sort of look at coordinate. So previously We've been looking kind of at zero zero most of the time So this was the origin and in a previous video We'd had these a view from positive x positive y positive z functions in our menu bar but these were are based off having Having the model be at the origin and not having the ability to pan left right up and down. So I'm gonna add a couple Letters to each one of these so I'm basically say that look from should be look at identically Except we're gonna displace it along the desired direction. So How does this work? Oops? Basically, I'm saying the look if we're looking from the positive x that basically means for look from is the same as look at Except the x component is gonna be a little bit further away. So one unit in the positive direction So I'm gonna copy this kind of logic for the next six functions. I'll be back in a second. Okay, so I actually added Look at to every look from so Positive y is basically look from equals look at except for the white component is plus one and for example The isometric one is look from equals look at plus one one one. So it's very very simple. So let's save this I actually lied. I want to change one thing in the main function. I want to change this Height from a thousand to a thousand twenty basically because Our rendering assumes that everything is a one-to-one ratio the way we've written our shader So because we have a 20 pixel menu bar, we really should have a 20 extra pixel value for our height So let's compile this and see if it works. It's probably not gonna work. Yeah What did I do? Oh? Did I mess something up? Hold on Okay, I just I just forgot to put this as a comma might be I just replaced this semicolon with a comma So I'm gonna show you See this should be a common awesome equal on them Let's see if this works. So I just compiled it. Let's run. So let's see if I can Preserve I'm clicking left mouse button. It's not working. That's a good sign middle mouse button. Oh, there we go It's working. So the fruit. So let's check off the list. So let me just make this a little bigger We have done This you've converted everything to the middle mouse button So let's see zooming in and out that seems to work just fine Do this now if I control There we go I can move the model left right up down and if you actually look my cursor is in the same spot on the model No matter where I pan it that's thanks to the logic I put at the end of that That equation there that that point five times the width of the of the window times the scaling factor That's how we're keeping the cursor in the same spot. It's very nice And it should it should it should you know work for air any zoom level. There we go. Very nice. Very nice I like that feature quite a bit So panning Panning works just fine. Let's check that off list Let's quickly check our views Perfect everything works still I didn't mess anything up very good and now lastly The render so before if you recall when I moved the rotation around a whole bunch it would lag No more lag See that very nice light show Panning zooming everything is much faster now much more Responsive no more giant queue of motion events. So that's a huge improvement in my opinion in terms of CAD controls and overall feel of the program. So That's it for today. If you enjoyed this I'm happy that you enjoyed this. Have a nice day