Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

Write an OpenGL program that display a rotating bunny. 1) Initially place a bunny 5 units along the x-axis at (5, 0, 0) of world

Write an OpenGL program that display a rotating bunny.

1) Initially place a bunny 5 units along the x-axis at (5, 0, 0) of world coordinate system. This is already implemented in the provided starting code.

2) Draw a ground plane and xyz-axis of world coordinate system. Draw xyz axis from an arrow object. This is already implemented in the provided starting code.

3) Rotate the bunny around the global y-axis of world coordinate system (WCS) and at the same time rotate around its own x-axis of local coordinate system (LCS).

For the rotating bunny, do the following transformation in order:

a. rotate the bunny around its own x-axis of local coordinate system by 'a' degree; (grade: 4 points)

b. then rotate the bunny by 'b' degrees around the global y-axis of world coordinate system. (grade: 3 points)

Note that the rotation around its own x-axis will not change the center position of bunny. The center position of bunny is changed when it rotates around the global y-axis. Some implementation hints are given below.

4) The program should have user-interaction controls to allow users to interactively increase or decrease a and b. The controls can be buttons, checkboxes, mouse clicks, mouse motion, etc. as long as it is easy to use. (grade: 2 points)

5) Have a Reset button that can reset the bunny to the initial state, a to 0 and b to 0. (grade: 1 point)

A starting code (c++) animating a bunny has been provided. GUI is implemented by Nanogui and GLFW.

To build the code, the following libraries are needed: GLEW, GLFW, Nanogui.

Hints:

1. Every bunny transformation can be implemented by modifying the ModelView matrix in the OpenGL code. The ModelView matrix is used to transform the vertex coordinates from world coordinate system (WCS) to camera coordinate system (CCS).

2. How to rotate the bunny around its own x-axis of local coordinate system (LCS)? Here are some hints that you can consider:

a. Track the direction of the bunnys x-axis of LCS and represent it in WCS.

b. Construct a rotation matrix, with the rotation axis to be the bunnys x-axis and the rotation angle to be 'a' degree. Rodrigues rotation formula gives the form of this matrix.

c. The rotation pivot point is the origin of bunnys LCS, but not the origin of WCS. Think about how to make the bunny rotate around its own origin.

main.cpp

#include "Renderer.h"

int main() {

Renderer m_renderer;

m_renderer.run();

return EXIT_SUCCESS;

}

Animation.h

#pragma once

#include

#include

#include

#include

class Animation

{

public:

Animation();

~Animation();

void init();

void update(float delta_time);

void reset();

glm::mat4 get_model_mat() { return m_model_mat; };

private:

glm::mat4 m_model_mat;

};

Camera.h

#pragma once

#include

#include

#include

#include

enum Camera_Movement {

FORWARD,

BACKWARD,

LEFT,

RIGHT,

UP,

DOWN,

ROTATE_X_UP,

ROTATE_X_DOWN,

ROTATE_Y_UP,

ROTATE_Y_DOWN,

ROTATE_Z_UP,

ROTATE_Z_DOWN,

};

class Camera {

public:

// Camera view parameters

glm::vec3 ori_position;

glm::vec3 ori_front;

glm::vec3 ori_up;

glm::vec3 ori_right;

glm::vec3 position;

glm::vec3 front;

glm::vec3 up;

glm::vec3 right;

// Camera projection parameters

float ori_zoom;

float zoom;

float near;

float far;

unsigned int width;

unsigned int height;

// Camera projection matrix: used for projection

glm::mat4 proj_mat;

// Camera view matrix: used for changing camera rotation and position

glm::mat4 view_mat;

// Camera parameter initialization

Camera(

glm::vec3 position_ = glm::vec3(0, 1, 10),

glm::vec3 front_ = glm::vec3(0, 0, -1),

glm::vec3 up_ = glm::vec3(0, 1, 0),

glm::vec3 right_ = glm::vec3(1, 0, 0),

float zoom_ = 45.0,

float near_ = 0.1,

float far_ = 100,

unsigned int width_ = 1600,

unsigned int height_ = 900

)

{

this->ori_position = position_;

this->ori_front = front_;

this->ori_up = up_;

this->ori_right = right_;

this->ori_zoom = zoom_;

this->near = near_;

this->far = far_;

this->width = width_;

this->height = height_;

}

void init() {

reset();

};

void reset() {

this->position = ori_position;

this->front = ori_front;

this->up = ori_up;

this->right = ori_right;

this->zoom = ori_zoom;

}

void process_keyboard(Camera_Movement direction, GLfloat delta_time)

{

GLfloat velocity = delta_time;

if (direction == FORWARD)

this->position += this->front * velocity;

if (direction == BACKWARD)

this->position -= this->front * velocity;

if (direction == LEFT)

this->position -= this->right * velocity;

if (direction == RIGHT)

this->position += this->right * velocity;

if (direction == UP)

this->position += this->up * velocity;

if (direction == DOWN)

this->position -= this->up * velocity;

if (direction == ROTATE_X_UP)

rotate_x(velocity);

if (direction == ROTATE_X_DOWN)

rotate_x(-velocity);

if (direction == ROTATE_Y_UP)

rotate_y(velocity);

if (direction == ROTATE_Y_DOWN)

rotate_y(-velocity);

if (direction == ROTATE_Z_UP)

rotate_z(velocity);

if (direction == ROTATE_Z_DOWN)

rotate_z(-velocity);

}

// Rotate specific angle along local camera system(LCS)

void rotate_x(GLfloat angle)

{

glm::vec3 up = this->up;

glm::mat4 rotation_mat(1);

rotation_mat = glm::rotate(rotation_mat, angle, this->right);

this->up = glm::normalize(glm::vec3(rotation_mat * glm::vec4(up, 1.0)));

this->front = glm::normalize(glm::cross(this->up, this->right));

}

void rotate_y(GLfloat angle)

{

glm::vec3 front = this->front;

glm::mat4 rotation_mat(1);

rotation_mat = glm::rotate(rotation_mat, angle, this->up);

this->front = glm::normalize(glm::vec3(rotation_mat * glm::vec4(front, 1.0)));

this->right = glm::normalize(glm::cross(this->front, this->up));

}

void rotate_z(GLfloat angle)

{

glm::vec3 right = this->right;

glm::mat4 rotation_mat(1);

rotation_mat = glm::rotate(rotation_mat, angle, this->front);

this->right = glm::normalize(glm::vec3(rotation_mat * glm::vec4(right, 1.0)));

this->up = glm::normalize(glm::cross(this->right, this->front));

}

// Get camera view matrix

glm::mat4 get_view_mat()

{

this->view_mat = glm::lookAt(this->position, this->position + this->front, this->up);

return this->view_mat;

}

// Get camera projection matrix

glm::mat4 get_projection_mat()

{

this->proj_mat = glm::perspective(this->zoom, (GLfloat)this->width / (GLfloat)this->height, this->near, this->far);

return this->proj_mat;

}

};

Lighting.h

#pragma once

#include

#include

#include

class Lighting {

struct Direction_Light {

bool status;

glm::vec3 direction;

glm::vec4 ambient;

glm::vec4 diffuse;

glm::vec4 specular;

};

struct Point_Light {

bool status;

glm::vec3 position;

float constant;

float linear;

float quadratic;

glm::vec4 ambient;

glm::vec4 diffuse;

glm::vec4 specular;

};

public:

Direction_Light direction_light;

Point_Light point_light;

Lighting() {

}

~Lighting() {}

void init()

{

direction_light.status = true;

direction_light.direction = glm::vec3(0.0f, -1.0f, 0.0f);

direction_light.ambient = glm::vec4(0.1f, 0.1f, 0.1f, 1.0f);

direction_light.diffuse = glm::vec4(0.3f, 0.3f, 0.3f, 1.0f);

direction_light.specular = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);

point_light.status = true;

point_light.position = glm::vec3(1.2f, 1.0f, 2.0f);

point_light.ambient = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);

point_light.diffuse = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);

point_light.specular = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);

point_light.constant = 1.0f;

point_light.linear = 0.09f;

point_light.quadratic = 0.032f;

};

};

Object.h

#pragma once

#include

#include

#include

#include

#include

#include

#include

#include

#include

class Object

{

public:

struct Vertex {

// Position

glm::vec3 Position;

// Normal

glm::vec3 Normal;

// TexCoords

glm::vec2 TexCoords;

};

struct Vertex_Index {

int pos_idx;

int normal_idx;

int texcoord_idx;

};

struct Face_Index {

Vertex_Index vertex[3];

};

// veo and vao vector

std::vector vao_vertices;

std::vector veo_indices;

// obj original data vector

std::vector ori_positions;

std::vector ori_normals;

std::vector ori_texcoords;

// obj face index vector

std::vector indexed_faces;

glm::vec3 obj_center;

glm::vec4 obj_color = glm::vec4(0.7, 0.7, 0.7, 1.0);

GLfloat shininess = 32.0f;

std::string m_obj_path;

std::string obj_name;

GLuint vao, vbo;

public:

void load_obj(std::string obj_path)

{

int path_str_length = obj_path.size();

std::string suffix = obj_path.substr(path_str_length - 3, path_str_length);

if (suffix == "obj") {

this->vao_vertices.clear();

this->veo_indices.clear();

this->indexed_faces.clear();

this->ori_positions.clear();

this->ori_normals.clear();

this->ori_texcoords.clear();

std::ifstream ifs;

// Store original data vector

try {

ifs.open(obj_path);

std::string one_line;

while (getline(ifs, one_line)) {

std::stringstream ss(one_line);

std::string type;

ss >> type;

if (type == "v") {

glm::vec3 vert_pos;

ss >> vert_pos[0] >> vert_pos[1] >> vert_pos[2];

this->ori_positions.push_back(vert_pos);

}

else if (type == "vt") {

glm::vec2 tex_coord;

ss >> tex_coord[0] >> tex_coord[1];

this->ori_texcoords.push_back(tex_coord);

}

else if (type == "vn") {

glm::vec3 vert_norm;

ss >> vert_norm[0] >> vert_norm[1] >> vert_norm[2];

this->ori_normals.push_back(vert_norm);

}

else if (type == "f") {

Face_Index face_idx;

// Here we only accept face number 3

for (int i = 0; i < 3; i++) {

std::string s_vertex;

ss >> s_vertex;

int pos_idx = -1;

int tex_idx = -1;

int norm_idx = -1;

sscanf(s_vertex.c_str(), "%d/%d/%d", &pos_idx, &tex_idx, &norm_idx);

// We have to use index -1 because the obj index starts at 1

// Incorrect input will be set as -1

face_idx.vertex[i].pos_idx = pos_idx > 0 ? pos_idx - 1 : -1;

face_idx.vertex[i].texcoord_idx = tex_idx > 0 ? tex_idx - 1 : -1;

face_idx.vertex[i].normal_idx = norm_idx > 0 ? norm_idx - 1 : -1;

}

indexed_faces.push_back(face_idx);

}

}

}

catch (const std::exception&) {

std::cout << "Error: Obj file cannot be read ";

}

// Retrieve data from index and assign to vao and veo

for (int i = 0; i < indexed_faces.size(); i++) {

Face_Index cur_idx_face = indexed_faces[i];

// If no normal: recalculate for them

glm::vec3 v0 = ori_positions[cur_idx_face.vertex[0].pos_idx];

glm::vec3 v1 = ori_positions[cur_idx_face.vertex[1].pos_idx];

glm::vec3 v2 = ori_positions[cur_idx_face.vertex[2].pos_idx];

glm::vec3 new_normal = glm::cross(v1 - v0, v2 - v0);

for (int j = 0; j < 3; j++) {

Vertex cur_vertex;

Vertex_Index cur_idx_vertex = cur_idx_face.vertex[j];

if (cur_idx_vertex.pos_idx >= 0) {

cur_vertex.Position = ori_positions[cur_idx_vertex.pos_idx];

}

if (cur_idx_vertex.normal_idx >= 0) {

cur_vertex.Normal = ori_normals[cur_idx_vertex.normal_idx];

}

else {

cur_vertex.Normal = new_normal;

}

if (cur_idx_vertex.texcoord_idx >= 0) {

cur_vertex.TexCoords = ori_texcoords[cur_idx_vertex.texcoord_idx];

}

vao_vertices.push_back(cur_vertex);

veo_indices.push_back(i * 3 + j);

}

}

}

};

void calculate_center()

{

glm::vec3 max_bound(INT_MIN);

glm::vec3 min_bound(INT_MAX);

for (auto vertex : this->vao_vertices) {

max_bound[0] = std::max(vertex.Position[0], max_bound[0]);

max_bound[1] = std::max(vertex.Position[1], max_bound[1]);

max_bound[2] = std::max(vertex.Position[2], max_bound[2]);

min_bound[0] = std::min(vertex.Position[0], min_bound[0]);

min_bound[1] = std::min(vertex.Position[1], min_bound[1]);

min_bound[2] = std::min(vertex.Position[2], min_bound[2]);

}

this->obj_center = (max_bound + min_bound) * 0.5f;

};

Object(std::string obj_path) {

this->m_obj_path = obj_path;

load_obj(this->m_obj_path);

calculate_center();

};

~Object() {};

};

Renderer.h

#pragma once

#include

#define GLEW_STATIC

#include

#include

#include

#include

#include

#include

#include

#include "Shader.h"

#include "Camera.h"

#include "Object.h"

#include "Lighting.h"

#include "Animation.h"

class Renderer

{

public:

GLFWwindow * m_window;

static Camera* m_camera;

static Lighting* m_lightings;

static Animation* m_animation;

static nanogui::Screen* m_nanogui_screen;

std::vector obj_list;

glm::vec4 background_color = glm::vec4(0.1, 0.1, 0.1, 0.1);

bool is_scean_reset = true;

std::string model_name;

GLfloat delta_time = 0.0;

GLfloat last_frame = 0.0;

static bool keys[1024];

public:

Renderer();

~Renderer();

void nanogui_init(GLFWwindow* window);

void init();

void display(GLFWwindow* window);

void run();

void load_models();

void draw_scene(Shader& shader);

void camera_move();

void draw_object(Shader& shader, Object& object);

void bind_vaovbo(Object &cur_obj);

void setup_uniform_values(Shader& shader);

void scean_reset();

};

Shader.h

#ifndef SHADER_H

#define SHADER_H

#include

#include

#include

#include

#include

class Shader {

public:

GLuint program;

Shader(const GLchar* vertex_shader_path, const GLchar* fragment_shader_path, const GLchar* geometry_shader_path = nullptr) {

std::string vertex_code;

std::string fragment_code;

std::string geometry_code;

std::ifstream v_shader_file;

std::ifstream f_shader_file;

std::ifstream g_shader_file;

v_shader_file.exceptions(std::ifstream::failbit | std::ifstream::badbit);

f_shader_file.exceptions(std::ifstream::failbit | std::ifstream::badbit);

g_shader_file.exceptions(std::ifstream::failbit | std::ifstream::badbit);

try {

v_shader_file.open(vertex_shader_path);

f_shader_file.open(fragment_shader_path);

std::stringstream v_shader_stream, f_shader_stream;

v_shader_stream << v_shader_file.rdbuf();

f_shader_stream << f_shader_file.rdbuf();

v_shader_file.close();

f_shader_file.close();

vertex_code = v_shader_stream.str();

fragment_code = f_shader_stream.str();

if (geometry_shader_path != nullptr) {

g_shader_file.open(geometry_shader_path);

std::stringstream g_shader_stream;

g_shader_stream << g_shader_file.rdbuf();

g_shader_file.close();

geometry_code = g_shader_stream.str();

}

}

catch (const std::exception&) {

std::cout << "Error: Shader not read ";

}

const char* v_shader_code = vertex_code.c_str();

const char* f_shader_code = fragment_code.c_str();

GLuint vertex, fragement, geometry;

GLchar info_log[512];

vertex = glCreateShader(GL_VERTEX_SHADER);

fragement = glCreateShader(GL_FRAGMENT_SHADER);

glShaderSource(vertex, 1, &v_shader_code, NULL);

glShaderSource(fragement, 1, &f_shader_code, NULL);

glCompileShader(vertex);

glCompileShader(fragement);

check_compile_error(vertex, "VERTEX");

check_compile_error(fragement, "FRAGMENT");

if (geometry_shader_path != nullptr) {

const char* g_shader_code = geometry_code.c_str();

geometry = glCreateShader(GL_GEOMETRY_SHADER);

glShaderSource(geometry, 1, &g_shader_code, NULL);

glCompileShader(geometry);

check_compile_error(geometry, "GEOMETRY");

}

this->program = glCreateProgram();

glAttachShader(this->program, vertex);

glAttachShader(this->program, fragement);

if (geometry_shader_path != nullptr) {

glAttachShader(this->program, geometry);

}

glLinkProgram(this->program);

check_compile_error(this->program, "PROGRAM");

glDeleteShader(vertex);

glDeleteShader(fragement);

if (geometry_shader_path != nullptr) {

glDeleteShader(geometry);

}

}

void use() { glUseProgram(this->program); }

private:

void check_compile_error(GLuint shader, std::string type) {

GLint success;

GLchar info_log[1024];

if (type == "PROGRAM") {

glGetProgramiv(shader, GL_LINK_STATUS, &success);

if (!success) {

glGetShaderInfoLog(shader, 1024, NULL, info_log);

std::cout << "| Error:: PROGRAM-LINKING-ERROR of type: " << type << "| " << info_log << " | -- --------------------------------------------------- -- | ";

}

}

else if (type == "VERTEX" || type == "FRAGMENT" || type == "GEOMETRY") {

glGetShaderiv(shader, GL_COMPILE_STATUS, &success);

if (!success) {

glGetShaderInfoLog(shader, 1024, NULL, info_log);

std::cout << "| Error:: SHADER-COMPILATION-ERROR of type: " << type << "| " << info_log << " | -- --------------------------------------------------- -- | ";

}

}

else {

std::cout << "Error: incorrect input type ";

}

}

};

#endif

Animation.cpp

#include "Animation.h"

Animation::Animation()

{

this->m_model_mat = glm::mat4();

}

Animation::~Animation()

{

}

void Animation::init()

{

reset();

}

void Animation::update(float delta_time)

{

}

void Animation::reset()

{

m_model_mat = glm::mat4();

m_model_mat = glm::translate(m_model_mat, glm::vec3(5.0, 0.0, 0.0));

}

Renderer.cpp

#include "Renderer.h"

Camera* Renderer::m_camera = new Camera();

Lighting* Renderer::m_lightings = new Lighting();

Animation* Renderer::m_animation = new Animation();

nanogui::Screen* Renderer::m_nanogui_screen = nullptr;

bool Renderer::keys[1024];

Renderer::Renderer()

{

}

Renderer::~Renderer()

{

}

void Renderer::nanogui_init(GLFWwindow* window)

{

m_nanogui_screen = new nanogui::Screen();

m_nanogui_screen->initialize(window, true);

glViewport(0, 0, m_camera->width, m_camera->height);

//glfwSwapInterval(0);

//glfwSwapBuffers(window);

// Create nanogui gui

nanogui::FormHelper *gui_1 = new nanogui::FormHelper(m_nanogui_screen);

nanogui::ref nanoguiWindow_1 = gui_1->addWindow(Eigen::Vector2i(0, 0), "Nanogui control bar_1");

//screen->setPosition(Eigen::Vector2i(-width/2 + 200, -height/2 + 300));

gui_1->addGroup("Camera Position");

gui_1->addVariable("X", m_camera->position[0])->setSpinnable(true);

gui_1->addVariable("Y", m_camera->position[1])->setSpinnable(true);

gui_1->addVariable("Z", m_camera->position[2])->setSpinnable(true);

gui_1->addButton("Reset Camera", []() {

m_camera->reset();

});

m_nanogui_screen->setVisible(true);

m_nanogui_screen->performLayout();

glfwSetCursorPosCallback(window,

[](GLFWwindow *window, double x, double y) {

m_nanogui_screen->cursorPosCallbackEvent(x, y);

}

);

glfwSetMouseButtonCallback(window,

[](GLFWwindow *, int button, int action, int modifiers) {

m_nanogui_screen->mouseButtonCallbackEvent(button, action, modifiers);

}

);

glfwSetKeyCallback(window,

[](GLFWwindow *window, int key, int scancode, int action, int mods) {

//screen->keyCallbackEvent(key, scancode, action, mods);

if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)

glfwSetWindowShouldClose(window, GL_TRUE);

if (key >= 0 && key < 1024)

{

if (action == GLFW_PRESS)

keys[key] = true;

else if (action == GLFW_RELEASE)

keys[key] = false;

}

}

);

glfwSetCharCallback(window,

[](GLFWwindow *, unsigned int codepoint) {

m_nanogui_screen->charCallbackEvent(codepoint);

}

);

glfwSetDropCallback(window,

[](GLFWwindow *, int count, const char **filenames) {

m_nanogui_screen->dropCallbackEvent(count, filenames);

}

);

glfwSetScrollCallback(window,

[](GLFWwindow *, double x, double y) {

m_nanogui_screen->scrollCallbackEvent(x, y);

//m_camera->ProcessMouseScroll(y);

}

);

glfwSetFramebufferSizeCallback(window,

[](GLFWwindow *, int width, int height) {

m_nanogui_screen->resizeCallbackEvent(width, height);

}

);

}

void Renderer::init()

{

glfwInit();

// Set all the required options for GLFW

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);

glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);

glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

m_camera->init();

m_lightings->init();

m_animation->init();

// Create a GLFWwindow object that we can use for GLFW's functions

this->m_window = glfwCreateWindow(m_camera->width, m_camera->height, "Assignment 1", nullptr, nullptr);

glfwMakeContextCurrent(this->m_window);

glewExperimental = GL_TRUE;

glewInit();

nanogui_init(this->m_window);

}

void Renderer::display(GLFWwindow* window)

{

Shader m_shader = Shader("./shader/basic.vert", "./shader/basic.frag");

// Main frame while loop

while (!glfwWindowShouldClose(window))

{

glfwPollEvents();

if (is_scean_reset) {

scean_reset();

is_scean_reset = false;

}

camera_move();

m_shader.use();

setup_uniform_values(m_shader);

draw_scene(m_shader);

m_nanogui_screen->drawWidgets();

// Swap the screen buffers

glfwSwapBuffers(window);

}

// Terminate GLFW, clearing any resources allocated by GLFW.

glfwTerminate();

return;

}

void Renderer::run()

{

init();

display(this->m_window);

}

void Renderer::load_models()

{

obj_list.clear();

Object main_object("./objs/bunny.obj");

main_object.obj_color = glm::vec4(0.7, 0.7, 0.7, 1.0);

main_object.obj_name = "main_object";

Object plane_object("./objs/plane.obj");

plane_object.obj_color = glm::vec4(0.5, 0.5, 0.5, 1.0);

plane_object.obj_name = "plane";

Object arrow_object("./objs/arrow.obj");

arrow_object.obj_name = "axis_arrow";

bind_vaovbo(main_object);

bind_vaovbo(plane_object);

bind_vaovbo(arrow_object);

// Here we only load one model

obj_list.push_back(main_object);

obj_list.push_back(plane_object);

obj_list.push_back(arrow_object);

}

void Renderer::draw_scene(Shader& shader)

{

// Set up some basic parameters

glClearColor(background_color[0], background_color[1], background_color[2], background_color[3]);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glEnable(GL_DEPTH_TEST);

glDepthFunc(GL_LESS);

glEnable(GL_CULL_FACE);

glCullFace(GL_FRONT);

glFrontFace(GL_CW);

for (size_t i = 0; i < obj_list.size(); i++)

{

if (obj_list[i].obj_name == "main_object")

{

// Before draw the model, change its model mat

glm::mat4 main_object_model_mat = glm::mat4();

m_animation->update(delta_time);

main_object_model_mat = m_animation->get_model_mat();

glUniformMatrix4fv(glGetUniformLocation(shader.program, "model"), 1, GL_FALSE, glm::value_ptr(main_object_model_mat));

glUniformMatrix4fv(glGetUniformLocation(shader.program, "view"), 1, GL_FALSE, glm::value_ptr(m_camera->get_view_mat()));

draw_object(shader, obj_list[i]);

}

if (obj_list[i].obj_name == "plane")

{

// Draw plane

glm::mat4 plane_model_mat = glm::mat4();

glUniformMatrix4fv(glGetUniformLocation(shader.program, "model"), 1, GL_FALSE, glm::value_ptr(plane_model_mat));

glUniformMatrix4fv(glGetUniformLocation(shader.program, "view"), 1, GL_FALSE, glm::value_ptr(m_camera->get_view_mat()));

draw_object(shader, obj_list[i]);

}

if (obj_list[i].obj_name == "axis_arrow")

{

// Draw three axis

glm::mat4 model_mat_x = glm::mat4();

glUniformMatrix4fv(glGetUniformLocation(shader.program, "model"), 1, GL_FALSE, glm::value_ptr(model_mat_x));

glUniformMatrix4fv(glGetUniformLocation(shader.program, "view"), 1, GL_FALSE, glm::value_ptr(m_camera->get_view_mat()));

obj_list[i].obj_color = glm::vec4(1, 0, 0, 1);

draw_object(shader, obj_list[i]);

glm::mat4 model_mat_y = glm::mat4();

model_mat_y = glm::rotate(model_mat_y, glm::radians(-90.0f), glm::vec3(0, 1, 0));

glUniformMatrix4fv(glGetUniformLocation(shader.program, "model"), 1, GL_FALSE, glm::value_ptr(model_mat_y));

glUniformMatrix4fv(glGetUniformLocation(shader.program, "view"), 1, GL_FALSE, glm::value_ptr(m_camera->get_view_mat()));

obj_list[i].obj_color = glm::vec4(0, 1, 0, 1);

draw_object(shader, obj_list[i]);

glm::mat4 model_mat_z = glm::mat4();

model_mat_z = glm::rotate(model_mat_z, glm::radians(90.0f), glm::vec3(0, 0, 1));

glUniformMatrix4fv(glGetUniformLocation(shader.program, "model"), 1, GL_FALSE, glm::value_ptr(model_mat_z));

glUniformMatrix4fv(glGetUniformLocation(shader.program, "view"), 1, GL_FALSE, glm::value_ptr(m_camera->get_view_mat()));

obj_list[i].obj_color = glm::vec4(0, 0, 1, 1);

draw_object(shader, obj_list[i]);

}

}

}

void Renderer::camera_move()

{

GLfloat current_frame = glfwGetTime();

delta_time = current_frame - last_frame;

last_frame = current_frame;

// Camera controls

if (keys[GLFW_KEY_W])

m_camera->process_keyboard(FORWARD, delta_time);

if (keys[GLFW_KEY_S])

m_camera->process_keyboard(BACKWARD, delta_time);

if (keys[GLFW_KEY_A])

m_camera->process_keyboard(LEFT, delta_time);

if (keys[GLFW_KEY_D])

m_camera->process_keyboard(RIGHT, delta_time);

if (keys[GLFW_KEY_Q])

m_camera->process_keyboard(UP, delta_time);

if (keys[GLFW_KEY_E])

m_camera->process_keyboard(DOWN, delta_time);

if (keys[GLFW_KEY_I])

m_camera->process_keyboard(ROTATE_X_UP, delta_time);

if (keys[GLFW_KEY_K])

m_camera->process_keyboard(ROTATE_X_DOWN, delta_time);

if (keys[GLFW_KEY_J])

m_camera->process_keyboard(ROTATE_Y_UP, delta_time);

if (keys[GLFW_KEY_L])

m_camera->process_keyboard(ROTATE_Y_DOWN, delta_time);

if (keys[GLFW_KEY_U])

m_camera->process_keyboard(ROTATE_Z_UP, delta_time);

if (keys[GLFW_KEY_O])

m_camera->process_keyboard(ROTATE_Z_DOWN, delta_time);

}

void Renderer::draw_object(Shader& shader, Object& object)

{

glBindVertexArray(object.vao);

glUniform3f(glGetUniformLocation(shader.program, "m_object.object_color"), object.obj_color[0], object.obj_color[1], object.obj_color[2]);

glUniform1f(glGetUniformLocation(shader.program, "m_object.shininess"), object.shininess);

glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

glDrawArrays(GL_TRIANGLES, 0, object.vao_vertices.size());

glBindVertexArray(0);

}

void Renderer::bind_vaovbo(Object &cur_obj)

{

glGenVertexArrays(1, &cur_obj.vao);

glGenBuffers(1, &cur_obj.vbo);

glBindVertexArray(cur_obj.vao);

glBindBuffer(GL_ARRAY_BUFFER, cur_obj.vbo);

glBufferData(GL_ARRAY_BUFFER, cur_obj.vao_vertices.size() * sizeof(Object::Vertex), &cur_obj.vao_vertices[0], GL_STATIC_DRAW);

// Vertex Positions

glEnableVertexAttribArray(0);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Object::Vertex), (GLvoid*)0);

// Vertex Normals

glEnableVertexAttribArray(1);

glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Object::Vertex), (GLvoid*)offsetof(Object::Vertex, Normal));

// Vertex Texture Coords

glEnableVertexAttribArray(2);

glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Object::Vertex), (GLvoid*)offsetof(Object::Vertex, TexCoords));

glBindVertexArray(0);

}

void Renderer::setup_uniform_values(Shader& shader)

{

// Camera uniform values

glUniform3f(glGetUniformLocation(shader.program, "camera_pos"), m_camera->position.x, m_camera->position.y, m_camera->position.z);

glUniformMatrix4fv(glGetUniformLocation(shader.program, "projection"), 1, GL_FALSE, glm::value_ptr(m_camera->get_projection_mat()));

// Light uniform values

glUniform1i(glGetUniformLocation(shader.program, "dir_light.status"), m_lightings->direction_light.status);

glUniform3f(glGetUniformLocation(shader.program, "dir_light.direction"), m_lightings->direction_light.direction[0], m_lightings->direction_light.direction[1], m_lightings->direction_light.direction[2]);

glUniform3f(glGetUniformLocation(shader.program, "dir_light.ambient"), m_lightings->direction_light.ambient[0], m_lightings->direction_light.ambient[1], m_lightings->direction_light.ambient[2]);

glUniform3f(glGetUniformLocation(shader.program, "dir_light.diffuse"), m_lightings->direction_light.diffuse[0], m_lightings->direction_light.diffuse[1], m_lightings->direction_light.diffuse[2]);

glUniform3f(glGetUniformLocation(shader.program, "dir_light.specular"), m_lightings->direction_light.specular[0], m_lightings->direction_light.specular[1], m_lightings->direction_light.specular[2]);

// Set current point light as camera's position

m_lightings->point_light.position = m_camera->position;

glUniform1i(glGetUniformLocation(shader.program, "point_light.status"), m_lightings->point_light.status);

glUniform3f(glGetUniformLocation(shader.program, "point_light.position"), m_lightings->point_light.position[0], m_lightings->point_light.position[1], m_lightings->point_light.position[2]);

glUniform3f(glGetUniformLocation(shader.program, "point_light.ambient"), m_lightings->point_light.ambient[0], m_lightings->point_light.ambient[1], m_lightings->point_light.ambient[2]);

glUniform3f(glGetUniformLocation(shader.program, "point_light.diffuse"), m_lightings->point_light.diffuse[0], m_lightings->point_light.diffuse[1], m_lightings->point_light.diffuse[2]);

glUniform3f(glGetUniformLocation(shader.program, "point_light.specular"), m_lightings->point_light.specular[0], m_lightings->point_light.specular[1], m_lightings->point_light.specular[2]);

glUniform1f(glGetUniformLocation(shader.program, "point_light.constant"), m_lightings->point_light.constant);

glUniform1f(glGetUniformLocation(shader.program, "point_light.linear"), m_lightings->point_light.linear);

glUniform1f(glGetUniformLocation(shader.program, "point_light.quadratic"), m_lightings->point_light.quadratic);

}

void Renderer::scean_reset()

{

load_models();

m_camera->reset();

}

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image_2

Step: 3

blur-text-image_3

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Students also viewed these Databases questions

Question

(a) There are five factors (A, B, C, D, and E). Pg45

Answered: 1 week ago

Question

10. Describe the relationship between communication and power.

Answered: 1 week ago