From 0b637f7ac391a5296f9569b8dc387eddab0e46e1 Mon Sep 17 00:00:00 2001 From: Michael Zhang Date: Sat, 8 Apr 2023 23:01:48 -0500 Subject: [PATCH] Finish translation and rotation --- assignment-2a/src/HW2a.cpp | 162 ++++++++++++++++++++++++++++--------- 1 file changed, 124 insertions(+), 38 deletions(-) diff --git a/assignment-2a/src/HW2a.cpp b/assignment-2a/src/HW2a.cpp index 9eb4dc6..d24cf8a 100755 --- a/assignment-2a/src/HW2a.cpp +++ b/assignment-2a/src/HW2a.cpp @@ -33,6 +33,8 @@ using namespace std; //---------------------------------------------------------------------------- // Forward-declaring some functions for later implementation +void copyMatrix(GLfloat *a, GLfloat *b); + /// Print the matrix void printMatrix(string name, GLfloat *matrix); @@ -52,9 +54,11 @@ void slow4x4MatrixMultiplyIntoColumnOrder( GLfloat *left, GLfloat *right, GLfloat *result ); -void slow4x4MatrixMultiplyAllRowOrder( - GLfloat *left, GLfloat *right, GLfloat *result -); +GLfloat *slow4x4MatrixMultiplyAllRowOrder(GLfloat *left, GLfloat *right); + +void handleScaling(int key, int scancode, int action, int mods); +void handleRotate(double xpos, double ypos); +void handleTranslate(double xpos, double ypos); //---------------------------------------------------------------------------- @@ -78,9 +82,20 @@ GLint window_height = 500; GLdouble pi = 4.0 * atan(1.0); // Added state +bool is_ctrl_held = false, is_left_mouse_pressed = false; const GLdouble SCALE_DELTA = 0.05; GLdouble scale_x = 1.0, scale_y = 1.0; +double drag_start_x, drag_start_y; +double last_mouse_x, last_mouse_y; +double delta_mouse_x, delta_mouse_y; +const GLdouble ROTATE_DELTA = 0.01; +double rotation_angle = 0.0; + +GLdouble TRANSLATE_DELTA_X = 2.0 / window_width; +GLdouble TRANSLATE_DELTA_Y = -2.0 / window_height; +GLdouble translate_x = 0.0, translate_y = 0.0; + // Matrices GLfloat rotation_matrix[16], translation_matrix[16], scale_matrix[16]; @@ -104,25 +119,13 @@ key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) { // closes the window glfwSetWindowShouldClose(window, GL_TRUE); - // arrow keys control the scaling of the object + // Handle ctrl key press + if (key == GLFW_KEY_LEFT_CONTROL) + is_ctrl_held = action == GLFW_PRESS; + if (action == GLFW_PRESS || action == GLFW_REPEAT) { - if (key == GLFW_KEY_LEFT || key == GLFW_KEY_A) - scale_x -= SCALE_DELTA; - - else if (key == GLFW_KEY_RIGHT || key == GLFW_KEY_D) - scale_x += SCALE_DELTA; - - else if (key == GLFW_KEY_UP || key == GLFW_KEY_W) - scale_y += SCALE_DELTA; - - else if (key == GLFW_KEY_DOWN || key == GLFW_KEY_S) - scale_y -= SCALE_DELTA; - - if (scale_x <= 0) - scale_x = SCALE_DELTA; - - if (scale_y <= 0) - scale_y = SCALE_DELTA; + // arrow keys control the scaling of the object + handleScaling(key, scancode, action, mods); } } @@ -133,22 +136,42 @@ static void mouse_button_callback(GLFWwindow *window, int button, int action, int mods) { glfwGetCursorPos(window, &mouse_x, &mouse_y); - // Check which mouse button triggered the event, e.g. GLFW_MOUSE_BUTTON_LEFT, - // etc. and what the button action was, e.g. GLFW_PRESS, GLFW_RELEASE, etc. - // (Note that ordinary trackpad click = mouse left button) - // Also check if any modifier keys were active at the time of the button - // press, e.g. GLFW_MOD_ALT, etc. Take the appropriate action, which could - // (optionally) also include changing the cursor's appearance + // Check which mouse button triggered the event, e.g. + // GLFW_MOUSE_BUTTON_LEFT, etc. and what the button action was, e.g. + // GLFW_PRESS, GLFW_RELEASE, etc. (Note that ordinary trackpad click = mouse + // left button) Also check if any modifier keys were active at the time of + // the button press, e.g. GLFW_MOD_ALT, etc. Take the appropriate action, + // which could (optionally) also include changing the cursor's appearance + + if (button == GLFW_MOUSE_BUTTON_LEFT) { + is_left_mouse_pressed = action == GLFW_PRESS; + + if (action == GLFW_PRESS) { + drag_start_x = mouse_x; + drag_start_y = mouse_y; + } + } } //---------------------------------------------------------------------------- // function that is called whenever a cursor motion event occurs static void cursor_pos_callback(GLFWwindow *window, double xpos, double ypos) { - // determine the direction of the mouse or cursor motion // update the current mouse or cursor location // (necessary to quantify the amount and direction of cursor motion) // take the appropriate action + + delta_mouse_x = xpos - last_mouse_x; + delta_mouse_y = ypos - last_mouse_y; + + if (is_left_mouse_pressed) { + if (is_ctrl_held) + handleTranslate(xpos, ypos); + else + handleRotate(xpos, ypos); + } + + glfwGetCursorPos(window, &last_mouse_x, &last_mouse_y); } //---------------------------------------------------------------------------- @@ -225,8 +248,8 @@ void init(void) { glClearColor(1.0, 1.0, 1.0, 1.0); // white, opaque background // Define some GLFW cursors (in case you want to dynamically change the - // cursor's appearance) If you want, you can add more cursors, or even define - // your own cursor appearance + // cursor's appearance) If you want, you can add more cursors, or even + // define your own cursor appearance arrow_cursor = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); hand_cursor = glfwCreateStandardCursor(GLFW_HAND_CURSOR); } @@ -290,8 +313,10 @@ int main(int argc, char **argv) { // fill/re-fill the window with the background color glClear(GL_COLOR_BUFFER_BIT); - rotation_matrix[0] = 1.0; - rotation_matrix[5] = 1.0; + rotation_matrix[0] = cos(rotation_angle); + rotation_matrix[1] = -sin(rotation_angle); + rotation_matrix[4] = sin(rotation_angle); + rotation_matrix[5] = cos(rotation_angle); rotation_matrix[10] = 1.0; rotation_matrix[15] = 1.0; @@ -300,27 +325,45 @@ int main(int argc, char **argv) { scale_matrix[10] = 1.0; scale_matrix[15] = 1.0; + translation_matrix[0] = 1.0; + translation_matrix[5] = 1.0; + translation_matrix[10] = 1.0; + translation_matrix[15] = 1.0; + translation_matrix[3] = translate_x; + translation_matrix[7] = translate_y; + // define/re-define the modelview matrix. In this template, we define M to // be the identity matrix; you will need define M according to the user's // actions. - slow4x4MatrixMultiplyAllRowOrder(rotation_matrix, scale_matrix, M); + GLfloat *result1 = + slow4x4MatrixMultiplyAllRowOrder(scale_matrix, rotation_matrix); + GLfloat *result2 = + slow4x4MatrixMultiplyAllRowOrder(translation_matrix, result1); + + copyMatrix(result2, M); transposeMatrix(M); + free(result1); + free(result2); + // sanity check that your matrix contents are what you expect them to be if (DEBUG_ON) { + /* printf("--------------"); printf("scale_x = %f , scale_y = %f\n", scale_x, scale_y); + printf("translate_x = %f , translate_y = %f\n", translate_x, translate_y); printMatrix("rotation_matrix", rotation_matrix); printMatrix("scale_matrix", scale_matrix); printMatrix("M", M); + */ } // send the updated model transformation matrix to the GPU glUniformMatrix4fv(m_location, 1, GL_FALSE, M); - // draw a triangle between the first vertex and each successive vertex pair - // in the hard-coded model + // draw a triangle between the first vertex and each successive vertex + // pair in the hard-coded model glDrawArrays(GL_TRIANGLES, 0, NVERTICES); // ensure that all OpenGL calls have executed before swapping buffers @@ -353,6 +396,12 @@ void printMatrix(string name, GLfloat *matrix) { ); } +void copyMatrix(GLfloat *a, GLfloat *b) { + for (int i = 0; i < 16; ++i) { + b[i] = a[i]; + } +} + void transposeMatrix(GLfloat *matrix) { for (int i = 0; i < 4; ++i) { for (int j = i + 1; j < 4; ++j) { @@ -369,9 +418,9 @@ void zeroInitGlfloats(GLfloat *arr, uint32_t len) { } } -void slow4x4MatrixMultiplyAllRowOrder( - GLfloat *left, GLfloat *right, GLfloat *result -) { +GLfloat *slow4x4MatrixMultiplyAllRowOrder(GLfloat *left, GLfloat *right) { + GLfloat *result = (GLfloat *)malloc(16 * sizeof(GLfloat)); + for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { result[i * 4 + j] = 0; @@ -382,4 +431,41 @@ void slow4x4MatrixMultiplyAllRowOrder( } } } + + return result; +} + +void handleScaling(int key, int scancode, int action, int mods) { + if (key == GLFW_KEY_LEFT || key == GLFW_KEY_A) + scale_x -= SCALE_DELTA; + + else if (key == GLFW_KEY_RIGHT || key == GLFW_KEY_D) + scale_x += SCALE_DELTA; + + else if (key == GLFW_KEY_UP || key == GLFW_KEY_W) + scale_y += SCALE_DELTA; + + else if (key == GLFW_KEY_DOWN || key == GLFW_KEY_S) + scale_y -= SCALE_DELTA; + + if (scale_x <= 0) + scale_x = SCALE_DELTA; + + if (scale_y <= 0) + scale_y = SCALE_DELTA; +} + +void handleRotate(double xpos, double ypos) { + rotation_angle -= delta_mouse_x * ROTATE_DELTA; +} + +void handleTranslate(double xpos, double ypos) { + /* + printf( + "pos : (%f, %f) -- last_mouse : (%f, %f)\n", xpos, ypos, last_mouse_x, + last_mouse_y + ); + */ + translate_x += delta_mouse_x * TRANSLATE_DELTA_X; + translate_y += delta_mouse_y * TRANSLATE_DELTA_Y; }