This goal of this project was to create a 3D space to view data in, although we only made the axes for now. We implemented controls to zoom, pan, and rotate the view, and we did this using matrices that represented the vpn, vrp, u, vup, and extent, as well as matrices to represent the screen size and offset from the edges of the window. We had these values inside the view class, and manipulated them with methods for normalization and rotation. In the other class, display, we built upon project 1 but added in a way to draw the axis lines as well as methods that user controls triggered, which accessed and manipulated the matrices in formulas that we used to, for example, recalculate the extent in the zooming method. In my project. I also implemented a reset button, included axis labels, and had the zoom level be shown to the user.

For the first task, we built a matrix in view that stores the axes' starting and ending points (plus the homogeneous coordinate), meaning there were six columns in total; the x axis, for example, was (0,0,0,1) and (1,0,0,1). We also had objects representing the canvas objects for the axes (initialized as None) that were stored in a list so that we could later initialize and manipulate them. Then, we made the buildAxes formula, which draws the axes onto the canvas, and calls the build method of the view class, which sets up the matrices in a way that provides us with a kind of starting camera view.

For the second task, we had to build all of the user control capabilities.

The first one we made was the handleButton1 method, which let us press the left mouse/trackpad button and lead into the handleButton1Motion if we moved. For this motion method, we followed a provided algorithm. For this, we first calculated the difference in former and current position, allowing us to get the distance moved. With this, we could get the delta x and delta y, which were scaled to the screen by being divided by the screen height then being multiplied by the current extent. Then, we calculated the new vrp, updated the axes, and replaced the self.baseclick location.

The second function we made was to have the button 3 of the mouse implement scaling. Moving up makes the items come closer, and moving down makes them appear farther away. As before, we calculated the distance moved, but this time, we calculated a scale factor, as well. This would be multiplied by the base extent to determine the new extent. Therefore, it had to start at 1 to ensure the extent remained the same by default, and since it should range from .1 to 3 times the original view size, I subtracted no more than the amount moved divided by the screen size, and added no more than 3 times the amount moved divided by the screen size.

The third subtask concerned making the pipeline for rotation around the view volume in the view class. We made a series of matrices - one to translate, one to align, one to rotate about y, one to rotate about x, one to unalign, and one to represent the starting, untranslated view reference coordinates. We multiply them all in the end, and then reassign the results to vrp, u, vup, and vpn, and normalize them all at the end.

The last part of task 2 was to give the user the ability to utilize this method. They would press button 2 on the mouse, and moving the mouse around would give the mousebutton2 motion-handling method the amount moved, which it would use to calculate the angle (math.pi*((difference)/200)). Then we use the original view matrix and transform that using the angles as input to the view class's rotation method.

My first extension was to implement a reset button. I simply linked the spacebar to a method that calls the reset method of view, which resets all the matrices, and then updates the axes to reflect that change.