/* * Activity9.cpp * * Created on: Apr 22, 2020 * Author: Josh */ /* Header Inclusions */ #include // Includes C++ i/o stream #include // Includes glew header #include // Includes freeglut header #include "SOIL2/SOIL2.h" // SOIL Image Loader Inclusion // GLM Math Header inclusions #include #include #include using namespace std; // Uses the standard namespace #define WINDOW_TITLE "Activity 9 McNew, Joshua" // Macro for window title // Vertex and Fragment Shader Source Macro #ifndef GLSL #define GLSL(Version, Source) "#version " #Version "\n" #Source #endif /* Variable declaration for shader, window size initialization, buffer and array objects */ GLint shaderProgram, WindowWidth = 800, WindowHeight = 600; GLuint VBO, VAO, texture; GLfloat degrees = glm::radians(-45.0f); // Converts float to degrees GLfloat cameraSpeed = 0.0005f; // Movement speed per frame GLchar currentKey; // Will store key pressed int keymod; //Check for alt GLfloat scale_by_y=2.0f; GLfloat scale_by_z=2.0f; GLfloat scale_by_x=2.0f; GLfloat lastMouseX = 400, lastMouseY = 300; // Locks mouse cursor at the center of the screen GLfloat mouseXoffset, mouseYoffset , yaw = 0.0f ,pitch = 0.0f; // Mouse offset , yaw and pitch variables GLfloat sensitivity = 0.01f; // Used for mouse and camera sensitivity bool mouseDetected = true; // Initially true when mouse is detected bool rotate = false; bool checkMotion = false; bool checkZoom = false; // Global vector declarations glm::vec3 CameraPosition = glm::vec3(0.0f, 0.0f, 0.0f); // Initial camera position. Placed units in Z glm::vec3 CameraUpY = glm::vec3(0.0f, 1.0f, 0.0f); // Temporary y unit vector glm::vec3 CameraForwardZ = glm::vec3(0.0f, 0.0f, -1.0f); // Temporary z unit vector glm::vec3 front; // Temporary z unit vector for mouse /* Function prototypes */ void UResizeWindow(int, int); void URenderGraphics(void); void UCreateShader(void); void UCreateBuffers(void); void UGenerateTexture(void); void UMouseMove(int x , int y); void OnMouseClicks(int button, int state, int x , int y); void onMotion(int x, int y); /* Vertex Shader Program Source Code */ const GLchar *vertexShaderSource = GLSL(330, layout(location=0) in vec3 position;// Vertex data from vertex attrib pointer 0 layout(location=2) in vec2 textureCoordinates; out vec2 mobileTextureCoordinate; // Global variables for the transform matrices uniform mat4 model; uniform mat4 view; uniform mat4 projection; void main() { gl_Position = projection * view * model * vec4(position, 1.0f); //Transform vertices to clip coordinates mobileTextureCoordinate = vec2(textureCoordinates.x, 1.0f - textureCoordinates.y); //flips the texture horizontally } ); /* Fragment Shader Program Source Code */ const GLchar *fragmentShaderSource = GLSL(330, in vec2 mobileTextureCoordinate; out vec4 gpuTexture; // Variable to pass texture data to the GPU uniform sampler2D uTexture; // Useful when working with multiple textures void main(){ gpuTexture = texture(uTexture, mobileTextureCoordinate); // Sends texture to the GPU for rendering } ); /* Main Program */ int main(int argc, char* argv[]) { glutInit(&argc, argv); // Initialize the OpenGL program glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); glutInitWindowSize(WindowWidth, WindowHeight); glutCreateWindow(WINDOW_TITLE); glutReshapeFunc(UResizeWindow); glewExperimental = GL_TRUE; if (glewInit() != GLEW_OK) { std::cout << "Failed to initialize GLEW" << std::endl; return -1; } UCreateShader(); UCreateBuffers(); UGenerateTexture(); // Use the Shader program glUseProgram(shaderProgram); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color glutDisplayFunc(URenderGraphics); glutPassiveMotionFunc(UMouseMove); // Detects mouse movement glutMotionFunc(onMotion); glutMouseFunc(OnMouseClicks); glutMainLoop(); // Destroys Buffer objects once used glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); return 0; } /* Resizes the window */ void UResizeWindow(int w, int h) { WindowWidth = w; WindowHeight = h; glViewport(0, 0, WindowWidth, WindowHeight); } /* Renders Graphics */ void URenderGraphics(void) { glEnable(GL_DEPTH_TEST); // Enable Z-depth glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clears the screen glBindVertexArray(VAO); // Activate the Vertex Array Object before rendering and transforming them //* Create Movement Logic */ CameraForwardZ = front; // Transforms the Object glm::mat4 model; model = glm::translate(model, glm::vec3(0.0f, 0.0f, 0.0f)); // Place the object at the center of the viewport model = glm::rotate(model, 45.0f, glm::vec3(0.0, 1.0f, 0.0f)); // Rotate the object 45 degrees on the X model = glm::scale(model, glm::vec3(scale_by_x,scale_by_y,scale_by_z)); // Increase the object size by a scale of 2 // Rotate the pyramid every second by 0.0005f degrees in XYZ model = glm::rotate(model, glutGet(GLUT_ELAPSED_TIME) * -0.0005f, glm::vec3(0.0, 1.0f, 0.0f)); model - glm::scale(model , glm::vec3(2.0f, 2.0f, 2.0f)); // Increase the object size by a scale of 2 // Transforms the camera glm::mat4 view; view = glm::lookAt(CameraForwardZ, CameraPosition, CameraUpY); // Creates a perspective projection glm::mat4 projection; projection = glm::perspective(45.0f, (GLfloat)WindowWidth / (GLfloat)WindowHeight, 0.1f, 100.0f); // Retrieves and passes transform matrices to the Shader program GLint modelLoc = glGetUniformLocation(shaderProgram, "model"); GLint viewLoc = glGetUniformLocation(shaderProgram, "view"); GLint projLoc = glGetUniformLocation(shaderProgram, "projection"); glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model)); glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view)); glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection)); glutPostRedisplay(); glBindTexture(GL_TEXTURE_2D, texture); // Draws the triangles glDrawArrays(GL_TRIANGLES, 0, 180); glBindVertexArray(0); // Deactivate the Vertex Array Object glutSwapBuffers(); // Flips the back buffer with the front buffer every frame. Similar to GL Flush } /* Creates the Shader program */ void UCreateShader() { // Vertex Shader GLint vertexShader = glCreateShader(GL_VERTEX_SHADER); // Creates the vertex Shader glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); // Attaches the vertex shader to the source code glCompileShader(vertexShader); // Compiles the Vertex shader // Fragment Shader GLint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); // Creates the Fragment shader glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); // Attaches the Fragment Shader to the source code glCompileShader(fragmentShader); // Compiles the Fragment Shader // Shader program shaderProgram = glCreateProgram(); // Creates the shader program and returns an id glAttachShader(shaderProgram, vertexShader); // Attach vertex shader to the shader program glAttachShader(shaderProgram, fragmentShader); // Attach Fragment shader to the shader program glLinkProgram(shaderProgram); // Link Vertex and Fragment shaders to shader program // Delete the vertex and fragment shaders once linked glDeleteShader(vertexShader); glDeleteShader(fragmentShader); } /* Creates the Buffer and Array Objects */ void UCreateBuffers() { //Position and color data GLfloat vertices[] = { //Positions //Texture Coordinates 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 1.0f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.5f, 1.0f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 1.0f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.5f, 1.0f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, }; // Generate buffer ids glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); // Activate the Vertex Array Object before binding and setting any VBOs and Vertex Attribute Pointers. glBindVertexArray(VAO); // Activate the VBO glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); //Copy vertices to BVO // Set attribute pointer 0 to hold position data glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0); // Enables vertex attribute // Set attribute pointer 1 to hold color data glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat))); glEnableVertexAttribArray(2); // Enables vertex attribute glBindVertexArray(0); // Deactivates the VAO which is good practice } void UGenerateTexture(){ glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); int width, height; unsigned char* image = SOIL_load_image("Carbon.jpg", &width, &height, 0, SOIL_LOAD_RGB); //Loads texture file glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); glGenerateMipmap(GL_TEXTURE_2D); SOIL_free_image_data(image); glBindTexture(GL_TEXTURE_2D, 0); // Unbind the texture } void UMouseMove(int x, int y){ front.x = 10.0f * cos(yaw); front.y = 10.0f * sin(pitch); front.z = sin(yaw) * cos(pitch) * 10.0f; } void onMotion(int curr_x, int curr_y) { // If left alt and mouse down are set if(checkMotion){ // Gets the direction the mouse was moved mouseXoffset = curr_x - lastMouseX; mouseYoffset = lastMouseY - curr_y; // Updates with new mouse coordinates lastMouseX = curr_x; lastMouseY = curr_y; // Applies sensitivity to mouse direction mouseXoffset *= sensitivity; mouseYoffset *= sensitivity; // Get the direction of the mouse // If there is changes in yaw, then it is moving along X if(yaw != yaw+mouseXoffset && pitch == pitch+mouseYoffset){ // INCREMENT yaw yaw += mouseXoffset; // Else movement in y }else if(pitch != pitch+mouseYoffset && yaw == yaw+mouseXoffset ){ // Increment y to move vertical pitch += mouseYoffset; } front.x = 10.0f * cos(yaw); front.y = 10.0f * sin(pitch); front.z = sin(yaw) * cos(pitch) * 10.0f; } // Check if user is zooming, alt, right mouse button and down if(checkZoom){ // Determine the direction of the , whether up or down if(lastMouseY > curr_y){ // Increment scale values scale_by_y += 0.1f; scale_by_x += 0.1f; scale_by_z += 0.1f; // Redisplay glutPostRedisplay(); }else{ // Decrement scale values, zoom in scale_by_y -= 0.1f; scale_by_x -= 0.1f; scale_by_z -= 0.1f; // Control zoom in size if(scale_by_y < 0.2f){ scale_by_y = 0.2f; scale_by_x = 0.2f; scale_by_z = 0.2f; } glutPostRedisplay(); } // Update x and y lastMouseY = curr_y; lastMouseX = curr_x; } } void OnMouseClicks(int button, int state, int x, int y) { keymod = glutGetModifiers(); // Checks for modifier keys like alt, shif and ctrl checkMotion = false; // Set checkMotion to false // Check if button is left, and mod is alt and state is down, all should be true if(button == GLUT_LEFT_BUTTON && keymod == GLUT_ACTIVE_ALT && state == GLUT_DOWN) { // If true then set motion true checkMotion = true; // Zooming to be false checkZoom = false; }else if(button == GLUT_RIGHT_BUTTON && keymod == GLUT_ACTIVE_ALT && state == GLUT_DOWN){ // Zoom to be true and motion to be false checkMotion = false; checkZoom = true; } }