From b51c63ea0c69e4e5afcdfe28af4faacc40edc546 Mon Sep 17 00:00:00 2001 From: mo7sener Date: Mon, 9 Dec 2019 05:46:30 +0200 Subject: [PATCH] Adding a buggy FPS Camera with position and rotation --- OpenWindow/OpenWindow.vcxproj | 2 + OpenWindow/OpenWindow.vcxproj.filters | 6 ++ OpenWindow/camera.cpp | 120 ++++++++++++++++++++++++++ OpenWindow/camera.h | 48 +++++++++++ OpenWindow/geometry.h | 3 + OpenWindow/main.cpp | 63 ++++++++------ OpenWindow/renderer.cpp | 109 ++++++++--------------- OpenWindow/renderer.h | 9 +- OpenWindow/util_window.h | 1 + 9 files changed, 255 insertions(+), 106 deletions(-) create mode 100644 OpenWindow/camera.cpp create mode 100644 OpenWindow/camera.h diff --git a/OpenWindow/OpenWindow.vcxproj b/OpenWindow/OpenWindow.vcxproj index 6ec45ac..f617bbd 100644 --- a/OpenWindow/OpenWindow.vcxproj +++ b/OpenWindow/OpenWindow.vcxproj @@ -115,6 +115,7 @@ + @@ -124,6 +125,7 @@ + diff --git a/OpenWindow/OpenWindow.vcxproj.filters b/OpenWindow/OpenWindow.vcxproj.filters index 53f3b63..89db46c 100644 --- a/OpenWindow/OpenWindow.vcxproj.filters +++ b/OpenWindow/OpenWindow.vcxproj.filters @@ -33,6 +33,9 @@ Source Files + + Source Files + @@ -50,5 +53,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/OpenWindow/camera.cpp b/OpenWindow/camera.cpp new file mode 100644 index 0000000..5c1742e --- /dev/null +++ b/OpenWindow/camera.cpp @@ -0,0 +1,120 @@ +#include "camera.h" + +Camera::Camera() +{ + fov = 30; + position = Vec3f(0, 0, 0); + rotation = Vec3f(0, 0, 0); + up = Vec3f(0, 0, 0); + right = Vec3f(0, 0, 0); + forward = Vec3f(0, 0, 0); + + near_plane = 0; + far_plane = 15; + horizontal_camera_speed = 0.5; + vertical_camera_speed = 0.5; + vertical_camera_clamp_up = 90; + vertical_camera_clamp_down = -90; +} + +Vec3f Camera::GetForward() { + return forward; +} + +void Camera::Move(Vec3f move_vec) { + position = position + move_vec; +} + +void Camera::SetPosition(Vec3f pos) { + position = pos; +} +void Camera::Rotate(Vec3f rot_vec) { + rotation = rotation + rot_vec; +} +void Camera::SetRotation(Vec3f rot) { + rotation = rot; +} +void Camera::SetFOV(int angle) { + fov = angle; +} +void Camera::SetVerticalRotSpeed(float speed) { + vertical_camera_speed = speed; +} +void Camera::SetHorizontalRotSpeed(float speed) { + horizontal_camera_speed = speed; +} +void Camera::SetClampRotUp(float angle) { + vertical_camera_clamp_up = angle; +} +void Camera::SetClampRotDown(float angle) { + vertical_camera_clamp_down = angle; +} +void Camera::SetNearPlane(float near_val) { + near_plane = near_val; +} +void Camera::SetFarPlane(float far_val) { + far_plane = far_val; +} + + +void Camera::rotate_camera_right() { + rotation.y += horizontal_camera_speed; +} +void Camera::rotate_camera_left() { + rotation.y -= horizontal_camera_speed; +} +void Camera::rotate_camera_up() { + rotation.x += vertical_camera_speed; + if (rotation.x > vertical_camera_clamp_up) rotation.x = 90; +} +void Camera::rotate_camera_down() { + rotation.x -= vertical_camera_speed; + if (rotation.x < vertical_camera_clamp_down) rotation.x = -90; +} + +#define MOVEMENT_SPEED 0.05f; + +void Camera::move_camera_left() { + position = position - right * MOVEMENT_SPEED; +} +void Camera::move_camera_right() { + position = position + right * MOVEMENT_SPEED; +} +void Camera::move_camera_forward() { + position = position + forward * MOVEMENT_SPEED; +} +void Camera::move_camera_backward() { + position = position - forward * MOVEMENT_SPEED; +} + +void Camera::ApplyChanges() { + forward = Vec3f(sin(rotation.y * DEG2RAD), -sin(rotation.x * DEG2RAD), -cosf(rotation.y*DEG2RAD) * cosf(rotation.x*DEG2RAD)); + right = Vec3f(cos(rotation.y*DEG2RAD), 0, sin(rotation.y * DEG2RAD)); + up = cross(right, forward); +} + +Matrix Camera::GetModelViewMatrix() { + Vec3f center = position + forward; + Vec3f z = (position - center).normalize(); + Vec3f x = cross(up, z).normalize(); + Vec3f y = cross(z, x).normalize(); + Matrix Minv = Matrix::identity(); + Matrix Tr = Matrix::identity(); + for (int i = 0; i < 3; i++) { + Minv[0][i] = x[i]; + Minv[1][i] = y[i]; + Minv[2][i] = z[i]; + Tr[i][3] = -center[i]; + } + return Minv * Tr; +} + +Matrix Camera::GetProjectionMatrix() { + Matrix Projection = Matrix::identity(); + Projection[0][0] = 1 / tan(fov * DEG2RAD); + Projection[1][1] = 1 / tan(fov * DEG2RAD); + Projection[2][2] = (far_plane + near_plane) / (far_plane - near_plane); + Projection[2][3] = (-2 * far_plane * near_plane) / (far_plane - near_plane); + Projection[3][2] = -1; + return Projection; +} diff --git a/OpenWindow/camera.h b/OpenWindow/camera.h new file mode 100644 index 0000000..a20117d --- /dev/null +++ b/OpenWindow/camera.h @@ -0,0 +1,48 @@ +#ifndef __CAMERA_HEADER__ +#define __CAMERA_HEADER__ +#include "geometry.h" + +class Camera { +private: + Vec3f position; + Vec3f rotation; + Vec3f up; + Vec3f right; + Vec3f forward; + float fov; + float near_plane; + float far_plane; + float horizontal_camera_speed; + float vertical_camera_speed; + float vertical_camera_clamp_up; + float vertical_camera_clamp_down; + +public: + Camera(); + void SetPosition(Vec3f pos); + void SetRotation(Vec3f rot); + void Move(Vec3f move_vec); + void Rotate(Vec3f rot_vec); + void SetFOV(int angle); + void SetNearPlane(float near_val); + void SetFarPlane(float far_val); + void SetVerticalRotSpeed(float speed); + void SetHorizontalRotSpeed(float speed); + void SetClampRotUp(float angle); + void SetClampRotDown(float angle); + Vec3f GetForward(); + + void rotate_camera_right(); + void rotate_camera_left(); + void rotate_camera_up(); + void rotate_camera_down(); + void move_camera_left(); + void move_camera_right(); + void move_camera_forward(); + void move_camera_backward(); + + void ApplyChanges(); + Matrix GetModelViewMatrix(); + Matrix GetProjectionMatrix(); +}; +#endif \ No newline at end of file diff --git a/OpenWindow/geometry.h b/OpenWindow/geometry.h index 630234a..98d1221 100644 --- a/OpenWindow/geometry.h +++ b/OpenWindow/geometry.h @@ -1,10 +1,13 @@ #ifndef __GEOMETRY_H__ #define __GEOMETRY_H__ +#define _USE_MATH_DEFINES #include #include #include #include +#define DEG2RAD M_PI/180 + template class mat; template struct vec { diff --git a/OpenWindow/main.cpp b/OpenWindow/main.cpp index 8c10ec9..3feaeee 100644 --- a/OpenWindow/main.cpp +++ b/OpenWindow/main.cpp @@ -6,8 +6,10 @@ const int screen_width = 1000; const int screen_height = 1000; -int prev_mouse_x = 0; -int prev_mouse_y = 0; +#define TARGET_FRAMERATE 30 + +int prev_mouse_x = screen_width/2; +int prev_mouse_y = screen_height/2; int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { @@ -15,18 +17,14 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine MSG Msg; hwnd = create_window(hInstance); + ShowCursor(false); ShowWindow(hwnd, nCmdShow); - char debug_str[100]; + init_camera(); - clock_t first_time = clock(); - render(); - clock_t end_time = clock(); - Update(); - sprintf_s(debug_str, "%f\n", (double)(end_time - first_time) / CLOCKS_PER_SEC); - OutputDebugString(debug_str); - + SetTimer(hwnd, NULL, 1000 / TARGET_FRAMERATE, (TIMERPROC)FixedUpdate); + while (GetMessage(&Msg, NULL, 0, 0)) { TranslateMessage(&Msg); @@ -35,34 +33,49 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine return Msg.wParam; } -bool HandleMouseMovement(LPARAM lParam) { +bool HandleMouseMovement() { int xPos, yPos; - xPos = LOWORD(lParam); - yPos = HIWORD(lParam); + POINT point; + GetCursorPos(&point); bool movement_detected_x = true; bool movement_detected_y = true; - if (xPos > prev_mouse_x) - move_camera_right(); - else if (xPos < prev_mouse_x) - move_camera_left(); + if (point.x > prev_mouse_x) + camera.rotate_camera_right(); + else if (point.x < prev_mouse_x) + camera.rotate_camera_left(); else movement_detected_x = false; - prev_mouse_x = xPos; - if (yPos > prev_mouse_y) - move_camera_up(); - else if (yPos < prev_mouse_y) - move_camera_down(); + if (point.y > prev_mouse_y) + camera.rotate_camera_up(); + else if (point.y < prev_mouse_y) + camera.rotate_camera_down(); else movement_detected_y = false; - prev_mouse_y = yPos; + SetCursorPos(prev_mouse_x, prev_mouse_y); return movement_detected_x || movement_detected_y; } -void Update_Window() { +bool HandleButtonPressed() { + if (GetAsyncKeyState(VK_UP) & 0x8000) + camera.move_camera_forward(); + if (GetAsyncKeyState(VK_DOWN) & 0x8000) + camera.move_camera_backward(); + if (GetAsyncKeyState(VK_RIGHT) & 0x8000) + camera.move_camera_right(); + if (GetAsyncKeyState(VK_LEFT) & 0x8000) + camera.move_camera_left(); + return true; +} + +void CALLBACK FixedUpdate(HWND hwnd, UINT message, UINT uInt, DWORD dWord) +{ + HandleMouseMovement(); + HandleButtonPressed(); + camera.ApplyChanges(); render(); Update(); } @@ -72,8 +85,6 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) switch (message) { case WM_MOUSEMOVE: - if(HandleMouseMovement(lParam)) - Update_Window(); break; case WM_RBUTTONDOWN: break; diff --git a/OpenWindow/renderer.cpp b/OpenWindow/renderer.cpp index cfdf9ca..aed5563 100644 --- a/OpenWindow/renderer.cpp +++ b/OpenWindow/renderer.cpp @@ -1,5 +1,4 @@ -#define _USE_MATH_DEFINES -#include +#include #include #include #include "tgaimage.h" @@ -8,44 +7,41 @@ #include "renderer.h" #include "util_window.h" #include +#include "camera.h" -#define DEG2RAD M_PI/180 -#define HORIZONTAL_CAMERA_SPEED 1 -#define VERTICAL_CAMERA_SPEED 1 - -#define NEAR_CLIP_PLANE 0 -#define FAR_CLIP_PLANE 15 -#define FOV 15 +#define HORIZONTAL_CAMERA_SPEED 1 +#define VERTICAL_CAMERA_SPEED 1 +#define VERTICAL_CAMERA_CLAMP_UP 90 +#define VERTICAL_CAMERA_CLAMP_DOWN -90 +#define NEAR_CLIP_PLANE 0 +#define FAR_CLIP_PLANE 15 +#define FOV 30 +#define DEFAULT_CAMERA_POS Vec3f(0, 0, 5) +#define DEFAULT_CAMERA_ROT Vec3f(0, 0, 0) const TGAColor white = TGAColor(255, 255, 255, 255); const TGAColor red = TGAColor(255, 0, 0, 255); const TGAColor green = TGAColor(0, 255, 0, 255); const TGAColor blue = TGAColor(0, 0, 255, 255); -const int depth = 255; - -int angle_hor = 0; -int angle_ver = 0; - bool wireframe = false; Model* model = new Model("african_head.obj"); +Camera camera; float* z_buffer = new float[screen_width * screen_height]; Vec3f light_dir = Vec3f(0, 0, 1).normalize(); -Vec3f eye(0, 0, 5); -Vec3f center(0, 0, 0); Matrix viewport(int x, int y, int w, int h) { Matrix m = Matrix::identity(); m[0][3] = x + w / 2.f; m[1][3] = y + h / 2.f; - m[2][3] = depth / 2.f; + m[2][3] = (FAR_CLIP_PLANE-NEAR_CLIP_PLANE) / 2.f; m[0][0] = w / 2.f; m[1][1] = h / 2.f; - m[2][2] = depth / 2.f; + m[2][2] = (FAR_CLIP_PLANE+NEAR_CLIP_PLANE) / 2.f; return m; } @@ -143,6 +139,7 @@ void triangle( Vec2i clamp(screen_width - 1, screen_height - 1); TGAColor color = white; + #pragma omp parallel for for (int i = 0; i < 3; i++) { for (int j = 0; j < 2; j++) { bounding_box_min[j] = std::fmax(0, std::fmin(bounding_box_min[j], (int)pts[i][j])); @@ -151,6 +148,7 @@ void triangle( } Vec3f P; + #pragma omp parallel for for (P.x = bounding_box_min.x; P.x <= bounding_box_max.x; P.x++) { for (P.y = bounding_box_min.y; P.y <= bounding_box_max.y; P.y++) { Vec3f bc_coord = barycentric(pts, P); @@ -168,7 +166,7 @@ void triangle( for (int i = 0; i < 3; i++) P.z += pts[i][2] * bc_coord[i]; // Coloring according to the Z-Buffer - if (P.z > z_buffer[(int)(P.x + P.y * screen_width)] && P.z > 20 && P.z < 50) + if (P.z > z_buffer[(int)(P.x + P.y * screen_width)] && P.z > 0) { z_buffer[(int)(P.x + P.y * screen_width)] = P.z; @@ -196,77 +194,40 @@ int color_to_int(TGAColor col) { return (col[2] << 16) | (col[1] << 8) | col[0]; } +void init_camera() { + camera.SetPosition(DEFAULT_CAMERA_POS); + camera.SetRotation(DEFAULT_CAMERA_ROT); + camera.SetFOV(FOV); + camera.SetNearPlane(NEAR_CLIP_PLANE); + camera.SetFarPlane(FAR_CLIP_PLANE); + camera.SetClampRotDown(VERTICAL_CAMERA_CLAMP_DOWN); + camera.SetClampRotUp(VERTICAL_CAMERA_CLAMP_UP); + camera.SetHorizontalRotSpeed(HORIZONTAL_CAMERA_SPEED); + camera.SetVerticalRotSpeed(VERTICAL_CAMERA_SPEED); + camera.ApplyChanges(); +} + void clear_zbuffer() { for (int i = 0; i < screen_width * screen_height; i++) z_buffer[i] = INT_MIN; } -Matrix lookat(Vec3f eye, Vec3f center, Vec3f up) { - Vec3f z = (eye-center).normalize(); - Vec3f x = cross(up,z).normalize(); - Vec3f y = cross(z,x).normalize(); - Matrix Minv = Matrix::identity(); - Matrix Tr = Matrix::identity(); - for (int i=0; i<3; i++) { - Minv[0][i] = x[i]; - Minv[1][i] = y[i]; - Minv[2][i] = z[i]; - Tr[i][3] = -center[i]; - } - return Minv*Tr; -} - -void move_camera_right() { - angle_hor += HORIZONTAL_CAMERA_SPEED; -} - -void move_camera_left() { - angle_hor -= HORIZONTAL_CAMERA_SPEED; -} - -void move_camera_up() { - angle_ver += VERTICAL_CAMERA_SPEED; - if (angle_ver > 90) angle_ver = 90; -} - -void move_camera_down() { - angle_ver -= VERTICAL_CAMERA_SPEED; - if (angle_ver < -90) angle_ver = -90; -} - Matrix ViewPort = Matrix::identity(); Matrix Projection = Matrix::identity(); Matrix ModelView = Matrix::identity(); void render() { - - Vec3f forward = Vec3f( - sinf(angle_hor * DEG2RAD), - -sinf(angle_ver * DEG2RAD), - -cosf(angle_hor*DEG2RAD) * cosf(angle_ver*DEG2RAD)); - Vec3f right = Vec3f(sinf(angle_hor*DEG2RAD + M_PI_2), 0, 0); - - center = eye + forward; - - //ViewPort = viewport(0, 0, screen_width, screen_height); - ViewPort = viewport(screen_width / 8, screen_height / 8, screen_width * 3 / 4, screen_height * 3 / 4); - ModelView = lookat(eye, center, cross(right, forward)); - Projection[0][0] = 1 / tanf(FOV * DEG2RAD); - Projection[1][1] = 1 / tanf(FOV * DEG2RAD); - Projection[2][2] = (FAR_CLIP_PLANE + NEAR_CLIP_PLANE) / (FAR_CLIP_PLANE - NEAR_CLIP_PLANE); - Projection[2][3] = (-2 * FAR_CLIP_PLANE * NEAR_CLIP_PLANE) / (FAR_CLIP_PLANE - NEAR_CLIP_PLANE); - Projection[3][2] = -1.f / (forward).norm(); - //Projection[3][2] = 1; - //Projection[3][3] = 0; - -// model->rotate(Vec3f(0, 180, 0)); -// model->ApplyTransform(); + light_dir = camera.GetForward() * -1; + ViewPort = viewport(0, 0, screen_width, screen_height); + Projection = camera.GetProjectionMatrix(); + ModelView = camera.GetModelViewMatrix(); Matrix z = ViewPort * Projection * ModelView * model->Transform; clear_zbuffer(); + #pragma omp parallel for for (int i = 0; i < model->nfaces(); i++) { std::vector face = model->face(i); diff --git a/OpenWindow/renderer.h b/OpenWindow/renderer.h index 8e4bd94..9aef4a6 100644 --- a/OpenWindow/renderer.h +++ b/OpenWindow/renderer.h @@ -1,16 +1,13 @@ #ifndef RENDERER_HEADER #define RENDERER_HEADER #include "tgaimage.h" +#include "camera.h" -extern int angle_hor; -extern int angle_ver; extern float* z_buffer; +extern Camera camera; -void move_camera_right(); -void move_camera_left(); -void move_camera_up(); -void move_camera_down(); +void init_camera(); void render(); int color_to_int(TGAColor col); #endif \ No newline at end of file diff --git a/OpenWindow/util_window.h b/OpenWindow/util_window.h index aaf7cff..ebcb042 100644 --- a/OpenWindow/util_window.h +++ b/OpenWindow/util_window.h @@ -31,5 +31,6 @@ void set_pixel(unsigned int x, unsigned int y, unsigned int color); void Update(); LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); +void CALLBACK FixedUpdate(HWND hwnd, UINT message, UINT uInt, DWORD dWord); #endif