rendering works :)
This commit is contained in:
parent
2100a9c221
commit
ef22869e48
3 changed files with 321 additions and 26 deletions
26
assignment-2b/make_statements.py
Normal file
26
assignment-2b/make_statements.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
def mkslot(m, i, j):
|
||||
ij = j + i * 4
|
||||
return f"{m}[{ij}]"
|
||||
# return m + "xyzw"[i] + str(j + 1)
|
||||
|
||||
def mm(leftcalled = "l", rightcalled = "r"):
|
||||
stmts = []
|
||||
|
||||
for i in range(4):
|
||||
for j in range(4):
|
||||
res = mkslot("m", i, j)
|
||||
terms = []
|
||||
|
||||
for k in range(4):
|
||||
left = mkslot(leftcalled, i, k)
|
||||
right = mkslot(rightcalled, k, j)
|
||||
|
||||
term = f"{left} * {right}"
|
||||
terms.append(term)
|
||||
|
||||
stmt = f"{res} = {' + '.join(terms)};"
|
||||
stmts.append(stmt)
|
||||
|
||||
return "\n".join(stmts)
|
||||
|
||||
print(mm())
|
|
@ -10,41 +10,72 @@
|
|||
#include "shader.hpp"
|
||||
#include "trimesh.hpp"
|
||||
#include <cstring> // memcpy
|
||||
#include <numeric>
|
||||
|
||||
// Constants
|
||||
#define WIN_WIDTH 500
|
||||
#define WIN_HEIGHT 500
|
||||
#define PI 3.1415926535
|
||||
|
||||
class Mat4x4 {
|
||||
public:
|
||||
float m[16];
|
||||
|
||||
// Default: Identity
|
||||
Mat4x4() {
|
||||
// clang-format off
|
||||
Mat4x4(){ // Default: Identity
|
||||
m[0] = 1.f; m[4] = 0.f; m[8] = 0.f; m[12] = 0.f;
|
||||
m[1] = 0.f; m[5] = 1.f; m[9] = 0.f; m[13] = 0.f;
|
||||
m[2] = 0.f; m[6] = 0.f; m[10] = 1.f; m[14] = 0.f;
|
||||
m[3] = 0.f; m[7] = 0.f; m[11] = 0.f; m[15] = 1.f;
|
||||
}
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
void make_identity() {
|
||||
// clang-format off
|
||||
void make_identity(){
|
||||
m[0] = 1.f; m[4] = 0.f; m[8] = 0.f; m[12] = 0.f;
|
||||
m[1] = 0.f; m[5] = 1.f; m[9] = 0.f; m[13] = 0.f;
|
||||
m[2] = 0.f; m[6] = 0.f; m[10] = 1.f; m[14] = 0.f;
|
||||
m[3] = 0.f; m[7] = 0.f; m[11] = 0.f; m[15] = 1.f;
|
||||
}
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
void zero() {
|
||||
// clang-format off
|
||||
m[0] = 0.0; m[4] = 0.0; m[8] = 0.0; m[12] = 0.0;
|
||||
m[1] = 0.0; m[5] = 0.0; m[9] = 0.0; m[13] = 0.0;
|
||||
m[2] = 0.0; m[6] = 0.0; m[10] = 0.0; m[14] = 0.0;
|
||||
m[3] = 0.0; m[7] = 0.0; m[11] = 0.0; m[15] = 0.0;
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
void transpose() {
|
||||
// 0 1 2 3
|
||||
// 4 5 6 7
|
||||
// 8 9 10 11
|
||||
// 12 13 14 15
|
||||
swap(&m[1], &m[4]);
|
||||
swap(&m[2], &m[8]);
|
||||
swap(&m[3], &m[12]);
|
||||
swap(&m[6], &m[9]);
|
||||
swap(&m[7], &m[13]);
|
||||
swap(&m[11], &m[14]);
|
||||
}
|
||||
|
||||
static void swap(float *a, float *b) {
|
||||
float tmp = *a;
|
||||
*a = *b;
|
||||
*b = tmp;
|
||||
}
|
||||
|
||||
void print() {
|
||||
// clang-format off
|
||||
void print(){
|
||||
std::cout << m[0] << ' ' << m[4] << ' ' << m[8] << ' ' << m[12] << "\n";
|
||||
std::cout << m[1] << ' ' << m[5] << ' ' << m[9] << ' ' << m[13] << "\n";
|
||||
std::cout << m[2] << ' ' << m[6] << ' ' << m[10] << ' ' << m[14] << "\n";
|
||||
std::cout << m[3] << ' ' << m[7] << ' ' << m[11] << ' ' << m[15] << "\n";
|
||||
}
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
void make_scale(float x, float y, float z) {
|
||||
make_identity();
|
||||
|
@ -52,6 +83,33 @@ public:
|
|||
m[5] = y;
|
||||
m[10] = z;
|
||||
}
|
||||
|
||||
inline Mat4x4 operator*(const Mat4x4 &right) {
|
||||
Mat4x4 result;
|
||||
auto l = this->m;
|
||||
auto r = right.m;
|
||||
auto m = result.m;
|
||||
|
||||
// Generated by make_statements.py
|
||||
m[0] = l[0] * r[0] + l[1] * r[4] + l[2] * r[8] + l[3] * r[12];
|
||||
m[1] = l[0] * r[1] + l[1] * r[5] + l[2] * r[9] + l[3] * r[13];
|
||||
m[2] = l[0] * r[2] + l[1] * r[6] + l[2] * r[10] + l[3] * r[14];
|
||||
m[3] = l[0] * r[3] + l[1] * r[7] + l[2] * r[11] + l[3] * r[15];
|
||||
m[4] = l[4] * r[0] + l[5] * r[4] + l[6] * r[8] + l[7] * r[12];
|
||||
m[5] = l[4] * r[1] + l[5] * r[5] + l[6] * r[9] + l[7] * r[13];
|
||||
m[6] = l[4] * r[2] + l[5] * r[6] + l[6] * r[10] + l[7] * r[14];
|
||||
m[7] = l[4] * r[3] + l[5] * r[7] + l[6] * r[11] + l[7] * r[15];
|
||||
m[8] = l[8] * r[0] + l[9] * r[4] + l[10] * r[8] + l[11] * r[12];
|
||||
m[9] = l[8] * r[1] + l[9] * r[5] + l[10] * r[9] + l[11] * r[13];
|
||||
m[10] = l[8] * r[2] + l[9] * r[6] + l[10] * r[10] + l[11] * r[14];
|
||||
m[11] = l[8] * r[3] + l[9] * r[7] + l[10] * r[11] + l[11] * r[15];
|
||||
m[12] = l[12] * r[0] + l[13] * r[4] + l[14] * r[8] + l[15] * r[12];
|
||||
m[13] = l[12] * r[1] + l[13] * r[5] + l[14] * r[9] + l[15] * r[13];
|
||||
m[14] = l[12] * r[2] + l[13] * r[6] + l[14] * r[10] + l[15] * r[14];
|
||||
m[15] = l[12] * r[3] + l[13] * r[7] + l[14] * r[11] + l[15] * r[15];
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
static inline const Vec3f operator*(const Mat4x4 &m, const Vec3f &v) {
|
||||
|
@ -71,6 +129,38 @@ float aspect;
|
|||
GLuint verts_vbo[1], colors_vbo[1], normals_vbo[1], faces_ibo[1], tris_vao;
|
||||
TriMesh mesh;
|
||||
|
||||
// In world coordinates
|
||||
Vec3f eye_pos(0., 0., 0.);
|
||||
Vec3f eye_dir;
|
||||
float view_angle = 0.0f;
|
||||
Vec3f up_dir(0., -1., 0.);
|
||||
|
||||
namespace viewing_window {
|
||||
|
||||
// - center = (0,0,0)
|
||||
// - height: 30.6
|
||||
// - length: 40.3
|
||||
// - width: 17.0
|
||||
float val = 50.0;
|
||||
float near = -1000.0, far = val;
|
||||
float left = -val, right = val;
|
||||
float bottom = -val, top = val;
|
||||
|
||||
const auto WIDTH_ZOOM = 1.0 / 30.0, HEIGHT_ZOOM = 1.0 / 30.0;
|
||||
const float MOVE_BY = 0.25; // 0.75 is actually really fast?
|
||||
const float ANGLE_BY = 0.05;
|
||||
|
||||
float horizontal_fov = 1.0, vertical_fov = 1.0;
|
||||
|
||||
} // namespace viewing_window
|
||||
|
||||
namespace controls {
|
||||
bool is_left_held = false, is_right_held = false, is_up_held = false,
|
||||
is_down_held = false;
|
||||
bool is_raise_held = false, is_lower_held = false;
|
||||
bool is_spin_left_held = false, is_spin_right_held = false;
|
||||
} // namespace controls
|
||||
|
||||
// Model, view and projection matrices, initialized to the identity
|
||||
Mat4x4 model; // not used in this assignment; included for completeness only
|
||||
Mat4x4 view;
|
||||
|
@ -90,27 +180,63 @@ static void key_callback(GLFWwindow *window, int key, int scancode, int action,
|
|||
if (action == GLFW_PRESS) {
|
||||
switch (key) {
|
||||
case GLFW_KEY_ESCAPE:
|
||||
glfwSetWindowShouldClose(window, GL_TRUE);
|
||||
break;
|
||||
case GLFW_KEY_Q:
|
||||
glfwSetWindowShouldClose(window, GL_TRUE);
|
||||
break;
|
||||
// ToDo: update the viewing transformation matrix according to key presses
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
using namespace Globals::controls;
|
||||
if (key == GLFW_KEY_W)
|
||||
is_up_held = action == GLFW_PRESS || action == GLFW_REPEAT;
|
||||
|
||||
if (key == GLFW_KEY_A)
|
||||
is_left_held = action == GLFW_PRESS || action == GLFW_REPEAT;
|
||||
|
||||
if (key == GLFW_KEY_S)
|
||||
is_down_held = action == GLFW_PRESS || action == GLFW_REPEAT;
|
||||
|
||||
if (key == GLFW_KEY_D)
|
||||
is_right_held = action == GLFW_PRESS || action == GLFW_REPEAT;
|
||||
|
||||
if (key == GLFW_KEY_LEFT_BRACKET)
|
||||
is_raise_held = action == GLFW_PRESS || action == GLFW_REPEAT;
|
||||
|
||||
if (key == GLFW_KEY_RIGHT_BRACKET)
|
||||
is_lower_held = action == GLFW_PRESS || action == GLFW_REPEAT;
|
||||
|
||||
if (key == GLFW_KEY_J || key == GLFW_KEY_LEFT)
|
||||
is_spin_left_held = action == GLFW_PRESS || action == GLFW_REPEAT;
|
||||
|
||||
if (key == GLFW_KEY_L || key == GLFW_KEY_RIGHT)
|
||||
is_spin_right_held = action == GLFW_PRESS || action == GLFW_REPEAT;
|
||||
}
|
||||
}
|
||||
|
||||
static void framebuffer_size_callback(GLFWwindow *window, int width,
|
||||
int height) {
|
||||
Globals::win_width = float(width);
|
||||
Globals::win_height = float(height);
|
||||
Globals::aspect = Globals::win_width / Globals::win_height;
|
||||
using namespace Globals;
|
||||
using namespace Globals::viewing_window;
|
||||
|
||||
win_width = float(width);
|
||||
win_height = float(height);
|
||||
aspect = win_width / win_height;
|
||||
|
||||
glViewport(0, 0, width, height);
|
||||
|
||||
// ToDo: update the perspective matrix as the window size changes
|
||||
// printf("Updated viewport to %d %d.\n", width, height);
|
||||
|
||||
left = WIDTH_ZOOM * -width / 2.0;
|
||||
right = WIDTH_ZOOM * width / 2.0;
|
||||
|
||||
top = HEIGHT_ZOOM * height / 2.0;
|
||||
bottom = HEIGHT_ZOOM * -height / 2.0;
|
||||
}
|
||||
|
||||
void update();
|
||||
|
||||
// Function to set up geometry
|
||||
void init_scene();
|
||||
|
||||
|
@ -128,12 +254,19 @@ int main(int argc, char *argv[]) {
|
|||
Globals::mesh.print_details();
|
||||
|
||||
// Forcibly scale the mesh vertices so that the entire model fits within a
|
||||
// (-1,1) volume: the code below is a temporary measure that is needed to
|
||||
// (-1, 1) volume: the code below is a temporary measure that is needed to
|
||||
// enable the entire model to be visible in the template app, before the
|
||||
// student has defined the proper viewing and projection matrices This code
|
||||
// should eventually be replaced by the use of an appropriate projection
|
||||
// matrix FYI: the model dimensions are: center = (0,0,0); height: 30.6;
|
||||
// length: 40.3; width: 17.0
|
||||
// matrix
|
||||
//
|
||||
// FYI: the model dimensions are:
|
||||
//
|
||||
// - center = (0,0,0)
|
||||
// - height: 30.6
|
||||
// - length: 40.3
|
||||
// - width: 17.0
|
||||
//
|
||||
// find the extremum of the vertex locations (this approach works because the
|
||||
// model is known to be centered; a more complicated method would be required
|
||||
// in the general case)
|
||||
|
@ -154,6 +287,7 @@ int main(int argc, char *argv[]) {
|
|||
else if (Globals::mesh.vertices[i][2] > max)
|
||||
max = Globals::mesh.vertices[i][2];
|
||||
}
|
||||
|
||||
// work with positive numbers
|
||||
if (min < 0)
|
||||
min = -min;
|
||||
|
@ -164,6 +298,7 @@ int main(int argc, char *argv[]) {
|
|||
else
|
||||
scale = 1 / min;
|
||||
|
||||
/*
|
||||
// scale the model vertices by brute force
|
||||
Mat4x4 mscale;
|
||||
mscale.make_scale(scale, scale, scale);
|
||||
|
@ -171,6 +306,7 @@ int main(int argc, char *argv[]) {
|
|||
Globals::mesh.vertices[i] = mscale * Globals::mesh.vertices[i];
|
||||
}
|
||||
// The above can be removed once a proper projection matrix is defined
|
||||
*/
|
||||
|
||||
// Set up the window variable
|
||||
GLFWwindow *window;
|
||||
|
@ -189,6 +325,9 @@ int main(int argc, char *argv[]) {
|
|||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
||||
|
||||
// TODO: REMOVE THIS BEFORE TURNING IN
|
||||
// glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
||||
|
||||
// Create the glfw window
|
||||
Globals::win_width = WIN_WIDTH;
|
||||
Globals::win_height = WIN_HEIGHT;
|
||||
|
@ -240,18 +379,24 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
// Game loop
|
||||
while (!glfwWindowShouldClose(window)) {
|
||||
|
||||
// Clear the color and depth buffers
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
update();
|
||||
|
||||
// Send updated info to the GPU
|
||||
{
|
||||
// model transformation (always the identity matrix in this assignment)
|
||||
glUniformMatrix4fv(shader.uniform("model"), 1, GL_FALSE,
|
||||
Globals::model.m); // model transformation (always the
|
||||
// identity matrix in this assignment)
|
||||
glUniformMatrix4fv(shader.uniform("view"), 1, GL_FALSE,
|
||||
Globals::view.m); // viewing transformation
|
||||
Globals::model.m);
|
||||
|
||||
// viewing transformation
|
||||
glUniformMatrix4fv(shader.uniform("view"), 1, GL_TRUE, Globals::view.m);
|
||||
|
||||
// projection matrix
|
||||
glUniformMatrix4fv(shader.uniform("projection"), 1, GL_FALSE,
|
||||
Globals::projection.m); // projection matrix
|
||||
Globals::projection.m);
|
||||
}
|
||||
|
||||
// Draw
|
||||
glDrawElements(GL_TRIANGLES, Globals::mesh.faces.size() * 3,
|
||||
|
@ -333,3 +478,126 @@ void init_scene() {
|
|||
// Done setting data for the vao
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void update() {
|
||||
{
|
||||
using namespace Globals;
|
||||
using namespace Globals::controls;
|
||||
|
||||
Vec3f move_by(0.0, 0.0, 0.0);
|
||||
|
||||
bool move = true;
|
||||
float move_angle_delta;
|
||||
|
||||
// Lol too lazy to get this to be more concise
|
||||
if (is_left_held && is_up_held)
|
||||
move_angle_delta = 3 * PI / 4;
|
||||
else if (is_left_held && is_down_held)
|
||||
move_angle_delta = PI / 4;
|
||||
else if (is_right_held && is_up_held)
|
||||
move_angle_delta = -3 * PI / 4;
|
||||
else if (is_right_held && is_down_held)
|
||||
move_angle_delta = -PI / 4;
|
||||
else if (is_left_held)
|
||||
move_angle_delta = PI / 2;
|
||||
else if (is_right_held)
|
||||
move_angle_delta = -PI / 2;
|
||||
else if (is_up_held)
|
||||
move_angle_delta = PI;
|
||||
else if (is_down_held)
|
||||
move_angle_delta = 0.0;
|
||||
else
|
||||
move = false;
|
||||
|
||||
const float move_angle = view_angle + move_angle_delta;
|
||||
|
||||
if (move) {
|
||||
move_by[0] = sin(move_angle) * viewing_window::MOVE_BY;
|
||||
move_by[2] = cos(move_angle) * viewing_window::MOVE_BY;
|
||||
}
|
||||
|
||||
if (is_raise_held)
|
||||
move_by[1] = viewing_window::MOVE_BY;
|
||||
else if (is_lower_held)
|
||||
move_by[1] = -viewing_window::MOVE_BY;
|
||||
|
||||
if (is_up_held || is_down_held || is_left_held || is_right_held ||
|
||||
is_raise_held || is_lower_held) {
|
||||
eye_pos += move_by;
|
||||
printf("Move by (%.2f, %.2f, %.2f) to (%.2f, %.2f, %.2f)\n", move_by[0],
|
||||
move_by[1], move_by[2], eye_pos[0], eye_pos[1], eye_pos[2]);
|
||||
}
|
||||
|
||||
if (is_spin_left_held)
|
||||
view_angle -= viewing_window::ANGLE_BY;
|
||||
else if (is_spin_right_held)
|
||||
view_angle += viewing_window::ANGLE_BY;
|
||||
}
|
||||
|
||||
// Set up normalization matrix
|
||||
{
|
||||
using namespace Globals::viewing_window;
|
||||
Globals::projection.zero();
|
||||
auto m = Globals::projection.m;
|
||||
|
||||
// 0 1 2 3
|
||||
// 4 5 6 7
|
||||
// 8 9 10 11
|
||||
// 12 13 14 15
|
||||
m[0] = (2.0 * near) / (right - left);
|
||||
m[5] = (2.0 * near) / (top - bottom);
|
||||
m[2] = (right + left) / (right - left);
|
||||
m[6] = (top + bottom) / (top - bottom);
|
||||
m[10] = -(far + near) / (far - near);
|
||||
m[11] = -2.0 * far * near / (far - near);
|
||||
m[14] = -1.0;
|
||||
}
|
||||
|
||||
// Set up view matrix
|
||||
{
|
||||
using namespace Globals;
|
||||
|
||||
Globals::view.zero();
|
||||
auto m = Globals::view.m;
|
||||
auto eye = Globals::eye_pos;
|
||||
|
||||
eye_dir[0] = sin(view_angle);
|
||||
eye_dir[2] = cos(view_angle);
|
||||
|
||||
Vec3f n = eye_dir * -1.0f;
|
||||
n.normalize();
|
||||
|
||||
// Up direction is (0, 1, 0)
|
||||
Vec3f u = Globals::up_dir.cross(n);
|
||||
u.normalize();
|
||||
|
||||
// v = n x u
|
||||
Vec3f v = n.cross(u);
|
||||
v.normalize();
|
||||
|
||||
Vec3f d(-eye.dot(u), -eye.dot(v), -eye.dot(n));
|
||||
|
||||
// 0 1 2 3
|
||||
// 4 5 6 7
|
||||
// 8 9 10 11
|
||||
// 12 13 14 15
|
||||
|
||||
m[0] = u.data[0];
|
||||
m[1] = u.data[1];
|
||||
m[2] = u.data[2];
|
||||
|
||||
m[4] = v.data[0];
|
||||
m[5] = v.data[1];
|
||||
m[6] = v.data[2];
|
||||
|
||||
m[8] = n.data[0];
|
||||
m[9] = n.data[1];
|
||||
m[10] = n.data[2];
|
||||
|
||||
m[3] = d.data[0];
|
||||
m[7] = d.data[1];
|
||||
m[11] = d.data[2];
|
||||
|
||||
m[15] = 1.0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
ninja
|
||||
pandoc
|
||||
poppler_utils
|
||||
renderdoc
|
||||
texlive.combined.scheme-full
|
||||
unzip
|
||||
zip
|
||||
|
|
Loading…
Reference in a new issue