SDL2

C++ GlassBox physics engine

Jul 7th, 2020
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 90.08 KB | None | 0 0
  1. #include "Camera.h"
  2. #include "GameHeader.h"
  3. #include <GL/glew.h>
  4. #include <cmath>
  5.  
  6. Camera::Camera() :
  7.   width(256),
  8.   height(256) {
  9.   worldView.MakeIdentity();
  10.   projection.MakeIdentity();
  11. }
  12.  
  13. void Camera::SetSize(int w, int h, float n, float f) {
  14.   width = w;
  15.   height = h;
  16.   near = n;
  17.   far = f;
  18.  
  19.   const float e = 1.0f / std::tan(GH_FOV * GH_PI / 360.0f);
  20.   const float a = float(height) / float(width);
  21.   const float d = near - far;
  22.  
  23.   projection.m[0] = e * a;
  24.   projection.m[1] = 0.0f;
  25.   projection.m[2] = 0.0f;
  26.   projection.m[3] = 0.0f;
  27.   projection.m[4] = 0.0f;
  28.   projection.m[5] = e;
  29.   projection.m[6] = 0.0f;
  30.   projection.m[7] = 0.0f;
  31.   projection.m[8] = 0.0f;
  32.   projection.m[9] = 0.0f;
  33.   projection.m[10] = (near + far) / d;
  34.   projection.m[11] = (2 * near * far) / d;
  35.   projection.m[12] = 0.0f;
  36.   projection.m[13] = 0.0f;
  37.   projection.m[14] = -1.0f;
  38.   projection.m[15] = 0.0f;
  39. }
  40.  
  41. void Camera::SetPositionOrientation(const Vector3& pos, float rotX, float rotY) {
  42.   worldView = Matrix4::RotX(rotX) * Matrix4::RotY(rotY) * Matrix4::Trans(-pos);
  43. }
  44.  
  45. Matrix4 Camera::InverseProjection() const {
  46.   Matrix4 invProjection = Matrix4::Zero();
  47.   const float a = projection.m[0];
  48.   const float b = projection.m[5];
  49.   const float c = projection.m[10];
  50.   const float d = projection.m[11];
  51.   const float e = projection.m[14];
  52.   invProjection.m[0] = 1.0f / a;
  53.   invProjection.m[5] = 1.0f / b;
  54.   invProjection.m[11] = 1.0f / e;
  55.   invProjection.m[14] = 1.0f / d;
  56.   invProjection.m[15] = -c / (d * e);
  57.   return invProjection;
  58. }
  59.  
  60. Matrix4 Camera::Matrix() const {
  61.   return projection * worldView;
  62. }
  63.  
  64. void Camera::UseViewport() const {
  65.   glViewport(0, 0, width, height);
  66. }
  67.  
  68. void Camera::ClipOblique(const Vector3& pos, const Vector3& normal) {
  69.   const Vector3 cpos = (worldView * Vector4(pos, 1)).XYZ();
  70.   const Vector3 cnormal = (worldView * Vector4(normal, 0)).XYZ();
  71.   const Vector4 cplane(cnormal.x, cnormal.y, cnormal.z, -cpos.Dot(cnormal));
  72.  
  73.   const Vector4 q = projection.Inverse() * Vector4(
  74.     (cplane.x < 0.0f ? 1.0f : -1.0f),
  75.     (cplane.y < 0.0f ? 1.0f : -1.0f),
  76.     1.0f,
  77.     1.0f
  78.   );
  79.   const Vector4 c = cplane * (2.0f / cplane.Dot(q));
  80.  
  81.   projection.m[8] = c.x - projection.m[12];
  82.   projection.m[9] = c.y - projection.m[13];
  83.   projection.m[10] = c.z - projection.m[14];
  84.   projection.m[11] = c.w - projection.m[15];
  85. }
  86. #pragma once
  87. #include "Vector.h"
  88.  
  89. class Camera {
  90. public:
  91.   Camera();
  92.  
  93.   Matrix4 InverseProjection() const;
  94.  
  95.   Matrix4 Matrix() const;
  96.  
  97.   void SetSize(int w, int h, float n, float f);
  98.   void SetPositionOrientation(const Vector3& pos, float rotX, float rotY);
  99.  
  100.   void UseViewport() const;
  101.  
  102.   void ClipOblique(const Vector3& pos, const Vector3& normal);
  103.  
  104.   Matrix4 projection;
  105.   Matrix4 worldView;
  106.  
  107.   int width;
  108.   int height;
  109.   float near;
  110.   float far;
  111. };
  112. #include "Collider.h"
  113. #include "GameHeader.h"
  114. #include "GL/glew.h"
  115. #include <cassert>
  116. #include <iostream>
  117.  
  118. Collider::Collider(const Vector3& a, const Vector3& b, const Vector3& c) {
  119.   const Vector3 ab = b - a;
  120.   const Vector3 bc = c - b;
  121.   const Vector3 ca = a - c;
  122.   const float magAB = ab.MagSq();
  123.   const float magBC = bc.MagSq();
  124.   const float magCA = ca.MagSq();
  125.   if (magAB >= magBC && magAB >= magCA) {
  126.     CreateSorted(bc*0.5f, (a + b)*0.5f, ca*0.5f);
  127.   } else if (magBC >= magAB && magBC >= magCA) {
  128.     CreateSorted(ca*0.5f, (b + c)*0.5f, ab*0.5f);
  129.   } else {
  130.     CreateSorted(ab*0.5f, (c + a)*0.5f, bc*0.5f);
  131.   }
  132. }
  133.  
  134. bool Collider::Collide(const Matrix4& localToUnit, Vector3& delta) const {
  135.   //Get world delta
  136.   const Matrix4 local = localToUnit * mat;
  137.   const Vector3 v = -local.Translation();
  138.  
  139.   //Get axes
  140.   const Vector3 x = local.XAxis();
  141.   const Vector3 y = local.YAxis();
  142.  
  143.   //Find closest point
  144.   const float px = GH_CLAMP(v.Dot(x) / x.MagSq(), -1.0f, 1.0f);
  145.   const float py = GH_CLAMP(v.Dot(y) / y.MagSq(), -1.0f, 1.0f);
  146.   const Vector3 closest = x*px + y*py;
  147.  
  148.   //Calculate distance to closest point
  149.   delta = v - closest;
  150.   if (delta.MagSq() >= 1.0f) {
  151.     return false;
  152.   } else {
  153.     delta = delta.Normalized() - delta;
  154.     return true;
  155.   }
  156. }
  157.  
  158. void Collider::DebugDraw(const Camera& cam, const Matrix4& objMat) {
  159.   glDepthFunc(GL_ALWAYS);
  160.   glUseProgram(0);
  161.   glBegin(GL_LINE_LOOP);
  162.   glColor3f(0.0f, 1.0f, 0.0f);
  163.  
  164.   const Matrix4 m = cam.Matrix() * objMat * mat;
  165.   Vector4 v;
  166.  
  167.   v = m * Vector4(1, 1, 0, 1);
  168.   glVertex4f(v.x, v.y, v.z, v.w);
  169.   v = m * Vector4(1, -1, 0, 1);
  170.   glVertex4f(v.x, v.y, v.z, v.w);
  171.   v = m * Vector4(-1, -1, 0, 1);
  172.   glVertex4f(v.x, v.y, v.z, v.w);
  173.   v = m * Vector4(-1, 1, 0, 1);
  174.   glVertex4f(v.x, v.y, v.z, v.w);
  175.  
  176.   glEnd();
  177.   glDepthFunc(GL_LESS);
  178. }
  179.  
  180. void Collider::CreateSorted(const Vector3& da, const Vector3& c, const Vector3& db) {
  181.   assert(std::abs(da.Dot(db)) / (da.Mag() * db.Mag()) < 0.001f);
  182.   mat.MakeIdentity();
  183.   mat.SetTranslation(c);
  184.   mat.SetXAxis(da);
  185.   mat.SetYAxis(db);
  186. }
  187. #pragma once
  188. #include "Vector.h"
  189. #include "Camera.h"
  190.  
  191. class Collider {
  192. public:
  193.   Collider(const Vector3& a, const Vector3& b, const Vector3& c);
  194.  
  195.   bool Collide(const Matrix4& localToWorld, Vector3& delta) const;
  196.  
  197.   void DebugDraw(const Camera& cam, const Matrix4& objMat);
  198.  
  199. private:
  200.   void CreateSorted(const Vector3& da, const Vector3& c, const Vector3& db);
  201.  
  202.   Matrix4 mat;
  203. };
  204. #include "Engine.h"
  205. #include "Physical.h"
  206. #include "Level1.h"
  207. #include "Level2.h"
  208. #include "Level3.h"
  209. #include "Level4.h"
  210. #include "Level5.h"
  211. #include "Level6.h"
  212. #include <GL/wglew.h>
  213. #include <cmath>
  214. #include <iostream>
  215. #include <algorithm>
  216.  
  217. Engine* GH_ENGINE = nullptr;
  218. Player* GH_PLAYER = nullptr;
  219. const Input* GH_INPUT = nullptr;
  220. int GH_REC_LEVEL = 0;
  221. int64_t GH_FRAME = 0;
  222.  
  223. LRESULT WINAPI StaticWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  224.   Engine* eng = (Engine*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
  225.   if (eng) {
  226.     return eng->WindowProc(hWnd, uMsg, wParam, lParam);
  227.   }
  228.   return DefWindowProc(hWnd, uMsg, wParam, lParam);
  229. }
  230.  
  231. Engine::Engine() : hWnd(NULL), hDC(NULL), hRC(NULL) {
  232.   GH_ENGINE = this;
  233.   GH_INPUT = &input;
  234.   isFullscreen = false;
  235.  
  236.   SetProcessDPIAware();
  237.   CreateGLWindow();
  238.   InitGLObjects();
  239.   SetupInputs();
  240.  
  241.   player.reset(new Player);
  242.   GH_PLAYER = player.get();
  243.  
  244.   vScenes.push_back(std::shared_ptr<Scene>(new Level1));
  245.   vScenes.push_back(std::shared_ptr<Scene>(new Level2(3)));
  246.   vScenes.push_back(std::shared_ptr<Scene>(new Level2(6)));
  247.   vScenes.push_back(std::shared_ptr<Scene>(new Level3));
  248.   vScenes.push_back(std::shared_ptr<Scene>(new Level4));
  249.   vScenes.push_back(std::shared_ptr<Scene>(new Level5));
  250.   vScenes.push_back(std::shared_ptr<Scene>(new Level6));
  251.  
  252.   LoadScene(0);
  253.  
  254.   sky.reset(new Sky);
  255. }
  256.  
  257. Engine::~Engine() {
  258.   ClipCursor(NULL);
  259.   wglMakeCurrent(NULL, NULL);
  260.   ReleaseDC(hWnd, hDC);
  261.   wglDeleteContext(hRC);
  262.   DestroyWindow(hWnd);
  263. }
  264.  
  265. int Engine::Run() {
  266.   if (!hWnd || !hDC || !hRC) {
  267.     return 1;
  268.   }
  269.  
  270.   //Recieve events from this window
  271.   SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)this);
  272.  
  273.   //Setup the timer
  274.   const int64_t ticks_per_step = timer.SecondsToTicks(GH_DT);
  275.   int64_t cur_ticks = timer.GetTicks();
  276.   GH_FRAME = 0;
  277.  
  278.   //Game loop
  279.   MSG msg;
  280.   while (true) {
  281.     if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  282.       //Handle windows messages
  283.       if (msg.message == WM_QUIT) {
  284.         break;
  285.       } else {
  286.         TranslateMessage(&msg);
  287.         DispatchMessage(&msg);
  288.       }
  289.     } else {
  290.       //Confine the cursor
  291.       ConfineCursor();
  292.  
  293.       if (input.key_press['1']) {
  294.         LoadScene(0);
  295.       } else if (input.key_press['2']) {
  296.         LoadScene(1);
  297.       } else if (input.key_press['3']) {
  298.         LoadScene(2);
  299.       } else if (input.key_press['4']) {
  300.         LoadScene(3);
  301.       } else if (input.key_press['5']) {
  302.         LoadScene(4);
  303.       } else if (input.key_press['6']) {
  304.         LoadScene(5);
  305.       } else if (input.key_press['7']) {
  306.         LoadScene(6);
  307.       }
  308.  
  309.       //Used fixed time steps for updates
  310.       const int64_t new_ticks = timer.GetTicks();
  311.       for (int i = 0; cur_ticks < new_ticks && i < GH_MAX_STEPS; ++i) {
  312.         Update();
  313.         cur_ticks += ticks_per_step;
  314.         GH_FRAME += 1;
  315.         input.EndFrame();
  316.       }
  317.       cur_ticks = (cur_ticks < new_ticks ? new_ticks: cur_ticks);
  318.  
  319.       //Setup camera for rendering
  320.       const float n = GH_CLAMP(NearestPortalDist() * 0.5f, GH_NEAR_MIN, GH_NEAR_MAX);
  321.       main_cam.worldView = player->WorldToCam();
  322.       main_cam.SetSize(iWidth, iHeight, n, GH_FAR);
  323.       main_cam.UseViewport();
  324.  
  325.       //Render scene
  326.       GH_REC_LEVEL = GH_MAX_RECURSION;
  327.       Render(main_cam, 0, nullptr);
  328.       SwapBuffers(hDC);
  329.     }
  330.   }
  331.  
  332.   DestroyGLObjects();
  333.   return 0;
  334. }
  335.  
  336. void Engine::LoadScene(int ix) {
  337.   //Clear out old scene
  338.   if (curScene) { curScene->Unload(); }
  339.   vObjects.clear();
  340.   vPortals.clear();
  341.   player->Reset();
  342.  
  343.   //Create new scene
  344.   curScene = vScenes[ix];
  345.   curScene->Load(vObjects, vPortals, *player);
  346.   vObjects.push_back(player);
  347. }
  348.  
  349. void Engine::Update() {
  350.   //Update
  351.   for (size_t i = 0; i < vObjects.size(); ++i) {
  352.     assert(vObjects[i].get());
  353.     vObjects[i]->Update();
  354.   }
  355.  
  356.   //Collisions
  357.   //For each physics object
  358.   for (size_t i = 0; i < vObjects.size(); ++i) {
  359.     Physical* physical = vObjects[i]->AsPhysical();
  360.     if (!physical) { continue; }
  361.     Matrix4 worldToLocal = physical->WorldToLocal();
  362.  
  363.     //For each object to collide with
  364.     for (size_t j = 0; j < vObjects.size(); ++j) {
  365.       if (i == j) { continue; }
  366.       Object& obj = *vObjects[j];
  367.       if (!obj.mesh) { continue; }
  368.  
  369.       //For each hit sphere
  370.       for (size_t s = 0; s < physical->hitSpheres.size(); ++s) {
  371.         //Brings point from collider's local coordinates to hits's local coordinates.
  372.         const Sphere& sphere = physical->hitSpheres[s];
  373.         Matrix4 worldToUnit = sphere.LocalToUnit() * worldToLocal;
  374.         Matrix4 localToUnit = worldToUnit * obj.LocalToWorld();
  375.         Matrix4 unitToWorld = worldToUnit.Inverse();
  376.  
  377.         //For each collider
  378.         for (size_t c = 0; c < obj.mesh->colliders.size(); ++c) {
  379.           Vector3 push;
  380.           const Collider& collider = obj.mesh->colliders[c];
  381.           if (collider.Collide(localToUnit, push)) {
  382.             //If push is too small, just ignore
  383.             push = unitToWorld.MulDirection(push);
  384.             vObjects[j]->OnHit(*physical, push);
  385.             physical->OnCollide(*vObjects[j], push);
  386.  
  387.             worldToLocal = physical->WorldToLocal();
  388.             worldToUnit = sphere.LocalToUnit() * worldToLocal;
  389.             localToUnit = worldToUnit * obj.LocalToWorld();
  390.             unitToWorld = worldToUnit.Inverse();
  391.           }
  392.         }
  393.       }
  394.     }
  395.   }
  396.  
  397.   //Portals
  398.   for (size_t i = 0; i < vObjects.size(); ++i) {
  399.     Physical* physical = vObjects[i]->AsPhysical();
  400.     if (physical) {
  401.       for (size_t j = 0; j < vPortals.size(); ++j) {
  402.         if (physical->TryPortal(*vPortals[j])) {
  403.           break;
  404.         }
  405.       }
  406.     }
  407.   }
  408. }
  409.  
  410. void Engine::Render(const Camera& cam, GLuint curFBO, const Portal* skipPortal) {
  411.   //Clear buffers
  412.   if (GH_USE_SKY) {
  413.     glClear(GL_DEPTH_BUFFER_BIT);
  414.     sky->Draw(cam);
  415.   } else {
  416.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  417.   }
  418.  
  419.   //Create queries (if applicable)
  420.   GLuint queries[GH_MAX_PORTALS];
  421.   GLuint drawTest[GH_MAX_PORTALS];
  422.   assert(vPortals.size() <= GH_MAX_PORTALS);
  423.   if (occlusionCullingSupported) {
  424.     glGenQueriesARB((GLsizei)vPortals.size(), queries);
  425.   }
  426.  
  427.   //Draw scene
  428.   for (size_t i = 0; i < vObjects.size(); ++i) {
  429.     vObjects[i]->Draw(cam, curFBO);
  430.   }
  431.  
  432.   //Draw portals if possible
  433.   if (GH_REC_LEVEL > 0) {
  434.     //Draw portals
  435.     GH_REC_LEVEL -= 1;
  436.     if (occlusionCullingSupported && GH_REC_LEVEL > 0) {
  437.       glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  438.       glDepthMask(GL_FALSE);
  439.       for (size_t i = 0; i < vPortals.size(); ++i) {
  440.         if (vPortals[i].get() != skipPortal) {
  441.           glBeginQueryARB(GL_SAMPLES_PASSED_ARB, queries[i]);
  442.           vPortals[i]->DrawPink(cam);
  443.           glEndQueryARB(GL_SAMPLES_PASSED_ARB);
  444.         }
  445.       }
  446.       for (size_t i = 0; i < vPortals.size(); ++i) {
  447.         if (vPortals[i].get() != skipPortal) {
  448.           glGetQueryObjectuivARB(queries[i], GL_QUERY_RESULT_ARB, &drawTest[i]);
  449.         }
  450.       };
  451.       glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  452.       glDepthMask(GL_TRUE);
  453.       glDeleteQueriesARB((GLsizei)vPortals.size(), queries);
  454.     }
  455.     for (size_t i = 0; i < vPortals.size(); ++i) {
  456.       if (vPortals[i].get() != skipPortal) {
  457.         if (occlusionCullingSupported && (GH_REC_LEVEL > 0) && (drawTest[i] == 0)) {
  458.           continue;
  459.         } else {
  460.           vPortals[i]->Draw(cam, curFBO);
  461.         }
  462.       }
  463.     }
  464.     GH_REC_LEVEL += 1;
  465.   }
  466.  
  467. #if 0
  468.   //Debug draw colliders
  469.   for (size_t i = 0; i < vObjects.size(); ++i) {
  470.     vObjects[i]->DebugDraw(cam);
  471.   }
  472. #endif
  473. }
  474.  
  475. LRESULT Engine::WindowProc(HWND hCurWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  476.   static PAINTSTRUCT ps;
  477.   static BYTE lpb[256];
  478.   static UINT dwSize = sizeof(lpb);
  479.  
  480.   switch (uMsg) {
  481.   case WM_SYSCOMMAND:
  482.     if (wParam == SC_SCREENSAVE || wParam == SC_MONITORPOWER) {
  483.       return 0;
  484.     }
  485.     break;
  486.  
  487.   case WM_PAINT:
  488.     BeginPaint(hCurWnd, &ps);
  489.     EndPaint(hCurWnd, &ps);
  490.     return 0;
  491.  
  492.   case WM_SIZE:
  493.     iWidth = LOWORD(lParam);
  494.     iHeight = HIWORD(lParam);
  495.     PostMessage(hCurWnd, WM_PAINT, 0, 0);
  496.     return 0;
  497.  
  498.   case WM_KEYDOWN:
  499.     //Ignore repeat keys
  500.     if (lParam & 0x40000000) { return 0; }
  501.     input.key[wParam & 0xFF] = true;
  502.     input.key_press[wParam & 0xFF] = true;
  503.     if (wParam == VK_ESCAPE) {
  504.       PostQuitMessage(0);
  505.     }
  506.     return 0;
  507.  
  508.   case WM_SYSKEYDOWN:
  509.     if (wParam == VK_RETURN) {
  510.       ToggleFullscreen();
  511.       return 0;
  512.     }
  513.     break;
  514.  
  515.   case WM_KEYUP:
  516.     input.key[wParam & 0xFF] = false;
  517.     return 0;
  518.  
  519.   case WM_INPUT:
  520.     dwSize = sizeof(lpb);
  521.     GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER));
  522.     input.UpdateRaw((const RAWINPUT*)lpb);
  523.     break;
  524.  
  525.   case WM_CLOSE:
  526.     PostQuitMessage(0);
  527.     return 0;
  528.   }
  529.  
  530.   return DefWindowProc(hCurWnd, uMsg, wParam, lParam);
  531. }
  532.  
  533. void Engine::CreateGLWindow() {
  534.   WNDCLASSEX wc;
  535.   hInstance = GetModuleHandle(NULL);
  536.   wc.cbSize = sizeof(WNDCLASSEX);
  537.   wc.style = CS_OWNDC;
  538.   wc.lpfnWndProc = (WNDPROC)StaticWindowProc;
  539.   wc.cbClsExtra = 0;
  540.   wc.cbWndExtra = 0;
  541.   wc.hInstance = hInstance;
  542.   wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
  543.   wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  544.   wc.hbrBackground = NULL;
  545.   wc.lpszMenuName = NULL;
  546.   wc.lpszClassName = GH_CLASS;
  547.   wc.hIconSm = NULL;
  548.  
  549.   if (!RegisterClassEx(&wc)) {
  550.     MessageBoxEx(NULL, "RegisterClass() failed: Cannot register window class.", "Error", MB_OK, 0);
  551.     return;
  552.   }
  553.  
  554.   //Always start in windowed mode
  555.   iWidth = GH_SCREEN_WIDTH;
  556.   iHeight = GH_SCREEN_HEIGHT;
  557.  
  558.   //Create the window
  559.   hWnd = CreateWindowEx(
  560.     WS_EX_APPWINDOW | WS_EX_WINDOWEDGE,
  561.     GH_CLASS,
  562.     GH_TITLE,
  563.     WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
  564.     GH_SCREEN_X,
  565.     GH_SCREEN_Y,
  566.     iWidth,
  567.     iHeight,
  568.     NULL,
  569.     NULL,
  570.     hInstance,
  571.     NULL);
  572.  
  573.   if (hWnd == NULL) {
  574.     MessageBoxEx(NULL, "CreateWindow() failed:  Cannot create a window.", "Error", MB_OK, 0);
  575.     return;
  576.   }
  577.  
  578.   hDC = GetDC(hWnd);
  579.  
  580.   PIXELFORMATDESCRIPTOR pfd;
  581.   memset(&pfd, 0, sizeof(pfd));
  582.   pfd.nSize = sizeof(pfd);
  583.   pfd.nVersion = 1;
  584.   pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
  585.   pfd.iPixelType = PFD_TYPE_RGBA;
  586.   pfd.cColorBits = 32;
  587.   pfd.cDepthBits = 32;
  588.   pfd.iLayerType = PFD_MAIN_PLANE;
  589.  
  590.   const int pf = ChoosePixelFormat(hDC, &pfd);
  591.   if (pf == 0) {
  592.     MessageBoxEx(NULL, "ChoosePixelFormat() failed: Cannot find a suitable pixel format.", "Error", MB_OK, 0);
  593.     return;
  594.   }
  595.  
  596.   if (SetPixelFormat(hDC, pf, &pfd) == FALSE) {
  597.     MessageBoxEx(NULL, "SetPixelFormat() failed: Cannot set format specified.", "Error", MB_OK, 0);
  598.     return;
  599.   }
  600.  
  601.   DescribePixelFormat(hDC, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
  602.  
  603.   hRC = wglCreateContext(hDC);
  604.   wglMakeCurrent(hDC, hRC);
  605.  
  606.   if (GH_START_FULLSCREEN) {
  607.     ToggleFullscreen();
  608.   }
  609.   if (GH_HIDE_MOUSE) {
  610.     ShowCursor(FALSE);
  611.   }
  612.  
  613.   ShowWindow(hWnd, SW_SHOW);
  614.   SetForegroundWindow(hWnd);
  615.   SetFocus(hWnd);
  616. }
  617.  
  618. void Engine::InitGLObjects() {
  619.   //Initialize extensions
  620.   glewInit();
  621.  
  622.   //Basic global variables
  623.   glClearColor(0.6f, 0.9f, 1.0f, 1.0f);
  624.   glEnable(GL_CULL_FACE);
  625.   glCullFace(GL_BACK);
  626.   glEnable(GL_DEPTH_TEST);
  627.   glDepthFunc(GL_LESS);
  628.   glDepthMask(GL_TRUE);
  629.  
  630.   //Check GL functionality
  631.   glGetQueryiv(GL_SAMPLES_PASSED_ARB, GL_QUERY_COUNTER_BITS_ARB, &occlusionCullingSupported);
  632.  
  633.   //Attempt to enalbe vsync (if failure then oh well)
  634.   wglSwapIntervalEXT(1);
  635. }
  636.  
  637. void Engine::DestroyGLObjects() {
  638.   curScene->Unload();
  639.   vObjects.clear();
  640.   vPortals.clear();
  641. }
  642.  
  643. void Engine::SetupInputs() {
  644.   static const int HID_USAGE_PAGE_GENERIC     = 0x01;
  645.   static const int HID_USAGE_GENERIC_MOUSE    = 0x02;
  646.   static const int HID_USAGE_GENERIC_JOYSTICK = 0x04;
  647.   static const int HID_USAGE_GENERIC_GAMEPAD  = 0x05;
  648.  
  649.   RAWINPUTDEVICE Rid[3];
  650.  
  651.   //Mouse
  652.   Rid[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
  653.   Rid[0].usUsage = HID_USAGE_GENERIC_MOUSE;
  654.   Rid[0].dwFlags = RIDEV_INPUTSINK;
  655.   Rid[0].hwndTarget = hWnd;
  656.  
  657.   //Joystick
  658.   Rid[1].usUsagePage = HID_USAGE_PAGE_GENERIC;
  659.   Rid[1].usUsage = HID_USAGE_GENERIC_JOYSTICK;
  660.   Rid[1].dwFlags = 0;
  661.   Rid[1].hwndTarget = 0;
  662.  
  663.   //Gamepad
  664.   Rid[2].usUsagePage = HID_USAGE_PAGE_GENERIC;
  665.   Rid[2].usUsage = HID_USAGE_GENERIC_GAMEPAD;
  666.   Rid[2].dwFlags = 0;
  667.   Rid[2].hwndTarget = 0;
  668.  
  669.   RegisterRawInputDevices(Rid, 3, sizeof(Rid[0]));
  670. }
  671.  
  672. void Engine::ConfineCursor() {
  673.   if (GH_HIDE_MOUSE) {
  674.     RECT rect;
  675.     GetWindowRect(hWnd, &rect);
  676.     SetCursorPos((rect.right + rect.left) / 2, (rect.top + rect.bottom) / 2);
  677.   }
  678. }
  679.  
  680. float Engine::NearestPortalDist() const {
  681.   float dist = FLT_MAX;
  682.   for (size_t i = 0; i < vPortals.size(); ++i) {
  683.     dist = GH_MIN(dist, vPortals[i]->DistTo(player->pos));
  684.   }
  685.   return dist;
  686. }
  687.  
  688. void Engine::ToggleFullscreen() {
  689.   isFullscreen = !isFullscreen;
  690.   if (isFullscreen) {
  691.     iWidth = GetSystemMetrics(SM_CXSCREEN);
  692.     iHeight = GetSystemMetrics(SM_CYSCREEN);
  693.     SetWindowLong(hWnd, GWL_STYLE, WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
  694.     SetWindowLong(hWnd, GWL_EXSTYLE, WS_EX_APPWINDOW);
  695.     SetWindowPos(hWnd, HWND_TOPMOST, 0, 0,
  696.       iWidth, iHeight, SWP_SHOWWINDOW);
  697.   } else {
  698.     iWidth = GH_SCREEN_WIDTH;
  699.     iHeight = GH_SCREEN_HEIGHT;
  700.     SetWindowLong(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
  701.     SetWindowLong(hWnd, GWL_EXSTYLE, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
  702.     SetWindowPos(hWnd, HWND_TOP, GH_SCREEN_X, GH_SCREEN_Y,
  703.       iWidth, iHeight, SWP_SHOWWINDOW);
  704.   }
  705. }
  706.  
  707. #pragma once
  708. #include "GameHeader.h"
  709. #include "Camera.h"
  710. #include "Input.h"
  711. #include "Object.h"
  712. #include "Portal.h"
  713. #include "Player.h"
  714. #include "Timer.h"
  715. #include "Scene.h"
  716. #include "Sky.h"
  717. #include <GL/glew.h>
  718. #include <windows.h>
  719. #include <memory>
  720. #include <vector>
  721.  
  722. class Engine {
  723. public:
  724.   Engine();
  725.   ~Engine();
  726.  
  727.   int Run();
  728.   void Update();
  729.   void Render(const Camera& cam, GLuint curFBO, const Portal* skipPortal);
  730.   void LoadScene(int ix);
  731.  
  732.   LRESULT WindowProc(HWND hCurWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  733.  
  734.   const Player& GetPlayer() const { return *player; }
  735.   float NearestPortalDist() const;
  736.  
  737. private:
  738.   void CreateGLWindow();
  739.   void InitGLObjects();
  740.   void DestroyGLObjects();
  741.   void SetupInputs();
  742.   void ConfineCursor();
  743.   void ToggleFullscreen();
  744.  
  745.   HDC   hDC;           // device context
  746.   HGLRC hRC;                   // opengl context
  747.   HWND  hWnd;                  // window
  748.   HINSTANCE hInstance; // process id
  749.  
  750.   LONG iWidth;         // window width
  751.   LONG iHeight;        // window height
  752.   bool isFullscreen;   // fullscreen state
  753.  
  754.   Camera main_cam;
  755.   Input input;
  756.   Timer timer;
  757.  
  758.   std::vector<std::shared_ptr<Object>> vObjects;
  759.   std::vector<std::shared_ptr<Portal>> vPortals;
  760.   std::shared_ptr<Sky> sky;
  761.   std::shared_ptr<Player> player;
  762.  
  763.   GLint occlusionCullingSupported;
  764.  
  765.   std::vector<std::shared_ptr<Scene>> vScenes;
  766.   std::shared_ptr<Scene> curScene;
  767. };
  768. pragma once
  769. #include "Object.h"
  770. #include "Resources.h"
  771. #include "Portal.h"
  772.  
  773. class Floorplan : public Object {
  774. public:
  775.   Floorplan() {
  776.     mesh = AquireMesh("floorplan.obj");
  777.     shader = AquireShader("texture_array");
  778.     texture = AquireTexture("floorplan_textures.bmp", 4, 4);
  779.     scale = Vector3(0.1524f); //6-inches to meters
  780.   }
  781.   virtual ~Floorplan() {}
  782.  
  783.   void AddPortals(PPortalVec& pvec) const {
  784.     std::shared_ptr<Portal> p1(new Portal);
  785.     std::shared_ptr<Portal> p2(new Portal);
  786.     std::shared_ptr<Portal> p3(new Portal);
  787.     std::shared_ptr<Portal> p4(new Portal);
  788.     std::shared_ptr<Portal> p5(new Portal);
  789.     std::shared_ptr<Portal> p6(new Portal);
  790.  
  791.     p1->pos = Vector3(33, 10, 25.5f) * scale;
  792.     p1->scale = Vector3(4, 10, 1) * scale;
  793.  
  794.     p2->pos = Vector3(74, 10, 25.5f) * scale;
  795.     p2->scale = Vector3(4, 10, 1) * scale;
  796.  
  797.     p3->pos = Vector3(33, 10, 66.5f) * scale;
  798.     p3->scale = Vector3(4, 10, 1) * scale;
  799.  
  800.     p4->pos = Vector3(63.5f, 10, 48) * scale;
  801.     p4->scale = Vector3(4, 10, 1) * scale;
  802.     p4->euler.y = GH_PI/2;
  803.  
  804.     p5->pos = Vector3(63.5f, 10, 7) * scale;
  805.     p5->scale = Vector3(4, 10, 1) * scale;
  806.     p5->euler.y = GH_PI / 2;
  807.  
  808.     p6->pos = Vector3(22.5f, 10, 48) * scale;
  809.     p6->scale = Vector3(4, 10, 1) * scale;
  810.     p6->euler.y = GH_PI / 2;
  811.  
  812.     Portal::Connect(p1->front, p3->back);
  813.     Portal::Connect(p1->back, p2->front);
  814.     Portal::Connect(p3->front, p2->back);
  815.  
  816.     Portal::Connect(p4->front, p6->back);
  817.     Portal::Connect(p4->back, p5->front);
  818.     Portal::Connect(p6->front, p5->back);
  819.  
  820.     pvec.push_back(p1);
  821.     pvec.push_back(p2);
  822.     pvec.push_back(p3);
  823.     pvec.push_back(p4);
  824.     pvec.push_back(p5);
  825.     pvec.push_back(p6);
  826.   }
  827. };
  828. #include "FrameBuffer.h"
  829. #include "GameHeader.h"
  830. #include "Engine.h"
  831. #include <iostream>
  832.  
  833. FrameBuffer::FrameBuffer() {
  834.   glGenTextures(1, &texId);
  835.   glBindTexture(GL_TEXTURE_2D, texId);
  836.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  837.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  838.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  839.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  840.   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, GH_FBO_SIZE, GH_FBO_SIZE, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
  841.   //-------------------------
  842.   glGenFramebuffersEXT(1, &fbo);
  843.   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
  844.   glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texId, 0);
  845.   //-------------------------
  846.   glGenRenderbuffersEXT(1, &renderBuf);
  847.   glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderBuf);
  848.   glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, GH_FBO_SIZE, GH_FBO_SIZE);
  849.   //-------------------------
  850.   glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, renderBuf);
  851.   //-------------------------
  852.  
  853.   //Does the GPU support current FBO configuration?
  854.   GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
  855.   if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
  856.     return;
  857.   }
  858.  
  859.   //Unbind so future rendering can proceed normally
  860.   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  861. }
  862.  
  863. void FrameBuffer::Use() {
  864.   glBindTexture(GL_TEXTURE_2D, texId);
  865. }
  866.  
  867. void FrameBuffer::Render(const Camera& cam, GLuint curFBO, const Portal* skipPortal) {
  868.   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
  869.   glViewport(0, 0, GH_FBO_SIZE, GH_FBO_SIZE);
  870.   GH_ENGINE->Render(cam, fbo, skipPortal);
  871.   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, curFBO);
  872. }
  873. #pragma once
  874. #include "Camera.h"
  875. #include <GL/glew.h>
  876.  
  877. //Forward declaration
  878. class Portal;
  879.  
  880. class FrameBuffer {
  881. public:
  882.   FrameBuffer();
  883.  
  884.   void Render(const Camera& cam, GLuint curFBO, const Portal* skipPortal);
  885.   void Use();
  886.  
  887. private:
  888.   GLuint texId;
  889.   GLuint fbo;
  890.   GLuint renderBuf;
  891. };
  892. #pragma once
  893. #include <stdint.h>
  894. #pragma warning(disable : 4100) // Unreferenced formal parameter
  895. #pragma warning(disable : 4099) // Missing PDB file
  896.  
  897. //Windows
  898. static const char GH_TITLE[] = "NonEuclideanDemo";
  899. static const char GH_CLASS[] = "NED";
  900.  
  901. //General
  902. static const float GH_PI = 3.141592653589793f;
  903. static const int GH_MAX_PORTALS = 16;
  904.  
  905. //Graphics
  906. static const bool GH_START_FULLSCREEN = false;
  907. static const bool GH_HIDE_MOUSE = true;
  908. static const bool GH_USE_SKY = true;
  909. static const int GH_SCREEN_WIDTH = 1280;
  910. static const int GH_SCREEN_HEIGHT = 720;
  911. static const int GH_SCREEN_X = 50;
  912. static const int GH_SCREEN_Y = 50;
  913. static const float GH_FOV = 60.0f;
  914. static const float GH_NEAR_MIN = 1e-3f;
  915. static const float GH_NEAR_MAX = 1e-1f;
  916. static const float GH_FAR = 100.0f;
  917. static const int GH_FBO_SIZE = 2048;
  918. static const int GH_MAX_RECURSION = 4;
  919.  
  920. //Gameplay
  921. static const float GH_MOUSE_SENSITIVITY = 0.005f;
  922. static const float GH_MOUSE_SMOOTH = 0.5f;
  923. static const float GH_WALK_SPEED = 2.9f;
  924. static const float GH_WALK_ACCEL = 50.0f;
  925. static const float GH_BOB_FREQ = 8.0f;
  926. static const float GH_BOB_OFFS = 0.015f;
  927. static const float GH_BOB_DAMP = 0.04f;
  928. static const float GH_BOB_MIN = 0.1f;
  929. static const float GH_DT = 0.002f;
  930. static const int GH_MAX_STEPS = 30;
  931. static const float GH_PLAYER_HEIGHT = 1.5f;
  932. static const float GH_PLAYER_RADIUS = 0.2f;
  933. static const float GH_GRAVITY = -9.8f;
  934.  
  935. //Global variables
  936. class Engine;
  937. class Input;
  938. class Player;
  939. extern Engine* GH_ENGINE;
  940. extern Player* GH_PLAYER;
  941. extern const Input* GH_INPUT;
  942. extern int GH_REC_LEVEL;
  943. extern int64_t GH_FRAME;
  944.  
  945. //Functions
  946. template<class T>
  947. inline T GH_CLAMP(T a, T mn, T mx) {
  948.   return a < mn ? mn : (a > mx ? mx : a);
  949. }
  950. template<class T>
  951. inline T GH_MIN(T a, T b) {
  952.   return a < b ? a : b;
  953. }
  954. template<class T>
  955. inline T GH_MAX(T a, T b) {
  956.   return a > b ? a : b;
  957. }
  958. #pragma once
  959. #include "Object.h"
  960. #include "Resources.h"
  961.  
  962. class Ground : public Object {
  963. public:
  964.   Ground(bool slope=false) {
  965.     if (slope) {
  966.       mesh = AquireMesh("ground_slope.obj");
  967.     } else {
  968.       mesh = AquireMesh("ground.obj");
  969.     }
  970.     shader = AquireShader("texture");
  971.     texture = AquireTexture("checker_green.bmp");
  972.     scale = Vector3(10, 1, 10);
  973.   }
  974.   virtual ~Ground() {}
  975. };
  976. #pragma once
  977. #include "Object.h"
  978. #include "Resources.h"
  979.  
  980. class House : public Object {
  981. public:
  982.   House(const char* tex) {
  983.     mesh = AquireMesh("square_rooms.obj");
  984.     shader = AquireShader("texture");
  985.     texture = AquireTexture(tex);
  986.     scale = Vector3(1.0f, 3.0f, 1.0f);
  987.   }
  988.   virtual ~House() {}
  989.  
  990.   void SetDoor1(Object& portal) const {
  991.     portal.pos = LocalToWorld().MulPoint(Vector3(4.0f, 0.5f, 10.0f));
  992.     portal.euler = euler;
  993.     portal.scale = Vector3(2, 0.5f, 1) * scale;
  994.   }
  995.   void SetDoor2(Object& portal) const {
  996.     portal.pos = LocalToWorld().MulPoint(Vector3(10.0f, 0.5f, 4.0f));
  997.     portal.euler = euler;
  998.     portal.euler.y -= GH_PI/2;
  999.     portal.scale = Vector3(2, 0.5f, 1) * scale;
  1000.   }
  1001.   void SetDoor3(Object& portal) const {
  1002.     portal.pos = LocalToWorld().MulPoint(Vector3(16.0f, 0.5f, 10.0f));
  1003.     portal.euler = euler;
  1004.     portal.euler.y -= GH_PI;
  1005.     portal.scale = Vector3(2, 0.5f, 1) * scale;
  1006.   }
  1007.   void SetDoor4(Object& portal) const {
  1008.     portal.pos = LocalToWorld().MulPoint(Vector3(10.0f, 0.5f, 16.0f));
  1009.     portal.euler = euler;
  1010.     portal.euler.y -= GH_PI*3/2;
  1011.     portal.scale = Vector3(2, 0.5f, 1) * scale;
  1012.   }
  1013. };
  1014. #include "Input.h"
  1015. #include "GameHeader.h"
  1016. #include <Windows.h>
  1017. #include <memory>
  1018.  
  1019. Input::Input() {
  1020.   memset(this, 0, sizeof(Input));
  1021. }
  1022.  
  1023. void Input::EndFrame() {
  1024.   memset(key_press, 0, sizeof(key_press));
  1025.   memset(mouse_button_press, 0, sizeof(mouse_button_press));
  1026.   mouse_dx = mouse_dx * GH_MOUSE_SMOOTH + mouse_ddx * (1.0f - GH_MOUSE_SMOOTH);
  1027.   mouse_dy = mouse_dy * GH_MOUSE_SMOOTH + mouse_ddy * (1.0f - GH_MOUSE_SMOOTH);
  1028.   mouse_ddx = 0.0f;
  1029.   mouse_ddy = 0.0f;
  1030. }
  1031.  
  1032. void Input::UpdateRaw(const tagRAWINPUT* raw) {
  1033.   static BYTE buffer[2048];
  1034.   static UINT buffer_size = sizeof(buffer);
  1035.  
  1036.   if (raw->header.dwType == RIM_TYPEMOUSE) {
  1037.     if (raw->data.mouse.usFlags == MOUSE_MOVE_RELATIVE) {
  1038.       mouse_ddx += raw->data.mouse.lLastX;
  1039.       mouse_ddy += raw->data.mouse.lLastY;
  1040.     }
  1041.     if (raw->data.mouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN) {
  1042.       mouse_button[0] = true;
  1043.       mouse_button_press[0] = true;
  1044.     }
  1045.     if (raw->data.mouse.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN) {
  1046.       mouse_button[1] = true;
  1047.       mouse_button_press[1] = true;
  1048.     }
  1049.     if (raw->data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN) {
  1050.       mouse_button[2] = true;
  1051.       mouse_button_press[2] = true;
  1052.     }
  1053.     if (raw->data.mouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_UP) mouse_button[0] = false;
  1054.     if (raw->data.mouse.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_UP) mouse_button[1] = false;
  1055.     if (raw->data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP) mouse_button[2] = false;
  1056.   } else if (raw->header.dwType == RIM_TYPEHID) {
  1057.     //TODO:
  1058.   }
  1059. }
  1060. #pragma once
  1061.  
  1062. struct tagRAWINPUT;
  1063. class Input {
  1064. public:
  1065.   Input();
  1066.  
  1067.   void EndFrame();
  1068.   void UpdateRaw(const tagRAWINPUT* raw);
  1069.  
  1070.   //Keyboard
  1071.   bool key[256];
  1072.   bool key_press[256];
  1073.  
  1074.   //Mouse
  1075.   bool mouse_button[3];
  1076.   bool mouse_button_press[3];
  1077.   float mouse_dx;
  1078.   float mouse_dy;
  1079.   float mouse_ddx;
  1080.   float mouse_ddy;
  1081.  
  1082.   //Joystick
  1083.   //TODO:
  1084.  
  1085.   //Bindings
  1086.   //TODO:
  1087.  
  1088.   //Calibration
  1089.   //TODO:
  1090. };
  1091. #include "Level1.h"
  1092. #include "Tunnel.h"
  1093. #include "Ground.h"
  1094.  
  1095. void Level1::Load(PObjectVec& objs, PPortalVec& portals, Player& player) {
  1096.   std::shared_ptr<Tunnel> tunnel1(new Tunnel(Tunnel::NORMAL));
  1097.   tunnel1->pos = Vector3(-2.4f, 0, -1.8f);
  1098.   tunnel1->scale = Vector3(1, 1, 4.8f);
  1099.   objs.push_back(tunnel1);
  1100.  
  1101.   std::shared_ptr<Tunnel> tunnel2(new Tunnel(Tunnel::NORMAL));
  1102.   tunnel2->pos = Vector3(2.4f, 0, 0);
  1103.   tunnel2->scale = Vector3(1, 1, 0.6f);
  1104.   objs.push_back(tunnel2);
  1105.  
  1106.   std::shared_ptr<Ground> ground(new Ground());
  1107.   ground->scale *= 1.2f;
  1108.   objs.push_back(ground);
  1109.  
  1110.   std::shared_ptr<Portal> portal1(new Portal());
  1111.   tunnel1->SetDoor1(*portal1);
  1112.   portals.push_back(portal1);
  1113.  
  1114.   std::shared_ptr<Portal> portal2(new Portal());
  1115.   tunnel2->SetDoor1(*portal2);
  1116.   portals.push_back(portal2);
  1117.  
  1118.   std::shared_ptr<Portal> portal3(new Portal());
  1119.   tunnel1->SetDoor2(*portal3);
  1120.   portals.push_back(portal3);
  1121.  
  1122.   std::shared_ptr<Portal> portal4(new Portal());
  1123.   tunnel2->SetDoor2(*portal4);
  1124.   portals.push_back(portal4);
  1125.  
  1126.   Portal::Connect(portal1, portal2);
  1127.   Portal::Connect(portal3, portal4);
  1128.  
  1129.   player.SetPosition(Vector3(0, GH_PLAYER_HEIGHT, 5));
  1130. }
  1131. #pragma once
  1132. #include "Scene.h"
  1133.  
  1134. class Level1 : public Scene {
  1135. public:
  1136.   virtual void Load(PObjectVec& objs, PPortalVec& portals, Player& player) override;
  1137. };
  1138. #include "Level2.h"
  1139. #include "House.h"
  1140.  
  1141. void Level2::Load(PObjectVec& objs, PPortalVec& portals, Player& player) {
  1142.   std::shared_ptr<House> house1(new House("three_room.bmp"));
  1143.   house1->pos = Vector3(0, 0, -20);
  1144.   objs.push_back(house1);
  1145.  
  1146.   std::shared_ptr<House> house2;
  1147.   if (num_rooms > 4) {
  1148.     house2.reset(new House("three_room2.bmp"));
  1149.     house2->pos = Vector3(200, 0, -20);
  1150.     objs.push_back(house2);
  1151.   }
  1152.  
  1153.   if (num_rooms == 1) {
  1154.     std::shared_ptr<Portal> portal1(new Portal());
  1155.     house1->SetDoor1(*portal1);
  1156.     portals.push_back(portal1);
  1157.  
  1158.     std::shared_ptr<Portal> portal2(new Portal());
  1159.     house1->SetDoor4(*portal2);
  1160.     portals.push_back(portal2);
  1161.  
  1162.     Portal::Connect(portal1, portal2);
  1163.   } else if (num_rooms == 2) {
  1164.     std::shared_ptr<Portal> portal1(new Portal());
  1165.     house1->SetDoor2(*portal1);
  1166.     portals.push_back(portal1);
  1167.  
  1168.     std::shared_ptr<Portal> portal2(new Portal());
  1169.     house1->SetDoor4(*portal2);
  1170.     portals.push_back(portal2);
  1171.  
  1172.     Portal::Connect(portal1, portal2);
  1173.   } else if (num_rooms == 3) {
  1174.     std::shared_ptr<Portal> portal1(new Portal());
  1175.     house1->SetDoor3(*portal1);
  1176.     portals.push_back(portal1);
  1177.  
  1178.     std::shared_ptr<Portal> portal2(new Portal());
  1179.     house1->SetDoor4(*portal2);
  1180.     portals.push_back(portal2);
  1181.  
  1182.     Portal::Connect(portal1, portal2);
  1183.   } else if (num_rooms == 4) {
  1184.   } else if (num_rooms == 5) {
  1185.     std::shared_ptr<Portal> portal1(new Portal());
  1186.     house1->SetDoor4(*portal1);
  1187.     portals.push_back(portal1);
  1188.  
  1189.     std::shared_ptr<Portal> portal2(new Portal());
  1190.     house2->SetDoor2(*portal2);
  1191.     portals.push_back(portal2);
  1192.  
  1193.     std::shared_ptr<Portal> portal3(new Portal());
  1194.     house2->SetDoor1(*portal3);
  1195.     portals.push_back(portal3);
  1196.  
  1197.     Portal::Connect(portal1->front, portal2->back);
  1198.     Portal::Connect(portal2->front, portal3->back);
  1199.     Portal::Connect(portal3->front, portal1->back);
  1200.   } else if (num_rooms == 6) {
  1201.     std::shared_ptr<Portal> portal1(new Portal());
  1202.     house1->SetDoor4(*portal1);
  1203.     portals.push_back(portal1);
  1204.  
  1205.     std::shared_ptr<Portal> portal2(new Portal());
  1206.     house2->SetDoor3(*portal2);
  1207.     portals.push_back(portal2);
  1208.  
  1209.     std::shared_ptr<Portal> portal3(new Portal());
  1210.     house2->SetDoor1(*portal3);
  1211.     portals.push_back(portal3);
  1212.  
  1213.     Portal::Connect(portal1->front, portal2->back);
  1214.     Portal::Connect(portal2->front, portal3->back);
  1215.     Portal::Connect(portal3->front, portal1->back);
  1216.   }
  1217.  
  1218.   player.SetPosition(Vector3(3, GH_PLAYER_HEIGHT, 3));
  1219. }
  1220. #pragma once
  1221. #include "Scene.h"
  1222.  
  1223. class Level2 : public Scene {
  1224. public:
  1225.   Level2(int rooms) : num_rooms(rooms) {}
  1226.  
  1227.   virtual void Load(PObjectVec& objs, PPortalVec& portals, Player& player) override;
  1228.  
  1229. private:
  1230.   int num_rooms;
  1231. };
  1232. #include "Level3.h"
  1233. #include "Pillar.h"
  1234. #include "Ground.h"
  1235. #include "Statue.h"
  1236. #include "PillarRoom.h"
  1237.  
  1238. void Level3::Load(PObjectVec& objs, PPortalVec& portals, Player& player) {
  1239.   //Room 1
  1240.   std::shared_ptr<Pillar> pillar1(new Pillar);
  1241.   objs.push_back(pillar1);
  1242.  
  1243.   std::shared_ptr<PillarRoom> pillarRoom1(new PillarRoom);
  1244.   objs.push_back(pillarRoom1);
  1245.  
  1246.   std::shared_ptr<Ground> ground1(new Ground);
  1247.   ground1->scale *= 2.0f;
  1248.   objs.push_back(ground1);
  1249.  
  1250.   std::shared_ptr<Statue> statue1(new Statue("teapot.obj"));
  1251.   statue1->pos = Vector3(0, 0.5f, 9);
  1252.   statue1->scale = Vector3(0.5f);
  1253.   statue1->euler.y = GH_PI / 2;
  1254.   objs.push_back(statue1);
  1255.  
  1256.   //Room 2
  1257.   std::shared_ptr<Pillar> pillar2(new Pillar);
  1258.   pillar2->pos = Vector3(200, 0, 0);
  1259.   objs.push_back(pillar2);
  1260.  
  1261.   std::shared_ptr<PillarRoom> pillarRoom2(new PillarRoom);
  1262.   pillarRoom2->pos = Vector3(200, 0, 0);
  1263.   objs.push_back(pillarRoom2);
  1264.  
  1265.   std::shared_ptr<Ground> ground2(new Ground);
  1266.   ground2->pos = Vector3(200, 0, 0);
  1267.   ground2->scale *= 2.0f;
  1268.   objs.push_back(ground2);
  1269.  
  1270.   std::shared_ptr<Statue> statue2(new Statue("bunny.obj"));
  1271.   statue2->pos = Vector3(200, -0.4f, 9);
  1272.   statue2->scale = Vector3(14.0f);
  1273.   statue2->euler.y = GH_PI;
  1274.   objs.push_back(statue2);
  1275.  
  1276.   //Room 3
  1277.   std::shared_ptr<Pillar> pillar3(new Pillar);
  1278.   pillar3->pos = Vector3(400, 0, 0);
  1279.   objs.push_back(pillar3);
  1280.  
  1281.   std::shared_ptr<PillarRoom> pillarRoom3(new PillarRoom);
  1282.   pillarRoom3->pos = Vector3(400, 0, 0);
  1283.   objs.push_back(pillarRoom3);
  1284.  
  1285.   std::shared_ptr<Ground> ground3(new Ground);
  1286.   ground3->pos = Vector3(400, 0, 0);
  1287.   ground3->scale *= 2.0f;
  1288.   objs.push_back(ground3);
  1289.  
  1290.   std::shared_ptr<Statue> statue3(new Statue("suzanne.obj"));
  1291.   statue3->pos = Vector3(400, 0.9f, 9);
  1292.   statue3->scale = Vector3(1.2f);
  1293.   statue3->euler.y = GH_PI;
  1294.   objs.push_back(statue3);
  1295.  
  1296.   //Portals
  1297.   std::shared_ptr<Portal> portal1(new Portal);
  1298.   pillarRoom1->SetPortal(*portal1);
  1299.   portals.push_back(portal1);
  1300.  
  1301.   std::shared_ptr<Portal> portal2(new Portal);
  1302.   pillarRoom2->SetPortal(*portal2);
  1303.   portals.push_back(portal2);
  1304.  
  1305.   std::shared_ptr<Portal> portal3(new Portal);
  1306.   pillarRoom3->SetPortal(*portal3);
  1307.   portals.push_back(portal3);
  1308.  
  1309.   Portal::Connect(portal1->front, portal2->back);
  1310.   Portal::Connect(portal2->front, portal3->back);
  1311.   Portal::Connect(portal3->front, portal1->back);
  1312.  
  1313.   player.SetPosition(Vector3(0, GH_PLAYER_HEIGHT, 3));
  1314. }
  1315. #pragma once
  1316. #include "Scene.h"
  1317.  
  1318. class Level3 : public Scene {
  1319. public:
  1320.   virtual void Load(PObjectVec& objs, PPortalVec& portals, Player& player) override;
  1321. };
  1322. #include "Level4.h"
  1323. #include "Tunnel.h"
  1324. #include "Ground.h"
  1325.  
  1326. void Level4::Load(PObjectVec& objs, PPortalVec& portals, Player& player) {
  1327.   std::shared_ptr<Tunnel> tunnel1(new Tunnel(Tunnel::SLOPE));
  1328.   tunnel1->pos = Vector3(0, 0, 0);
  1329.   tunnel1->scale = Vector3(1, 1, 5);
  1330.   tunnel1->euler.y = GH_PI;
  1331.   objs.push_back(tunnel1);
  1332.  
  1333.   std::shared_ptr<Ground> ground1(new Ground(true));
  1334.   ground1->scale *= Vector3(1, 2, 1);
  1335.   objs.push_back(ground1);
  1336.  
  1337.   std::shared_ptr<Tunnel> tunnel2(new Tunnel(Tunnel::SLOPE));
  1338.   tunnel2->pos = Vector3(200, 0, 0);
  1339.   tunnel2->scale = Vector3(1, 1, 5);
  1340.   objs.push_back(tunnel2);
  1341.  
  1342.   std::shared_ptr<Ground> ground2(new Ground(true));
  1343.   ground2->pos = Vector3(200, 0, 0);
  1344.   ground2->scale *= Vector3(1, 2, 1);
  1345.   ground2->euler.y = GH_PI;
  1346.   objs.push_back(ground2);
  1347.  
  1348.   std::shared_ptr<Portal> portal1(new Portal());
  1349.   tunnel1->SetDoor1(*portal1);
  1350.   portals.push_back(portal1);
  1351.  
  1352.   std::shared_ptr<Portal> portal2(new Portal());
  1353.   tunnel1->SetDoor2(*portal2);
  1354.   portals.push_back(portal2);
  1355.  
  1356.   std::shared_ptr<Portal> portal3(new Portal());
  1357.   tunnel2->SetDoor1(*portal3);
  1358.   portal3->euler.y -= GH_PI;
  1359.   portals.push_back(portal3);
  1360.  
  1361.   std::shared_ptr<Portal> portal4(new Portal());
  1362.   tunnel2->SetDoor2(*portal4);
  1363.   portal4->euler.y -= GH_PI;
  1364.   portals.push_back(portal4);
  1365.  
  1366.   Portal::Connect(portal1, portal4);
  1367.   Portal::Connect(portal2, portal3);
  1368.  
  1369.   player.SetPosition(Vector3(0, GH_PLAYER_HEIGHT - 2, 8));
  1370. }
  1371. #include "Level4.h"
  1372. #include "Tunnel.h"
  1373. #include "Ground.h"
  1374.  
  1375. void Level4::Load(PObjectVec& objs, PPortalVec& portals, Player& player) {
  1376.   std::shared_ptr<Tunnel> tunnel1(new Tunnel(Tunnel::SLOPE));
  1377.   tunnel1->pos = Vector3(0, 0, 0);
  1378.   tunnel1->scale = Vector3(1, 1, 5);
  1379.   tunnel1->euler.y = GH_PI;
  1380.   objs.push_back(tunnel1);
  1381.  
  1382.   std::shared_ptr<Ground> ground1(new Ground(true));
  1383.   ground1->scale *= Vector3(1, 2, 1);
  1384.   objs.push_back(ground1);
  1385.  
  1386.   std::shared_ptr<Tunnel> tunnel2(new Tunnel(Tunnel::SLOPE));
  1387.   tunnel2->pos = Vector3(200, 0, 0);
  1388.   tunnel2->scale = Vector3(1, 1, 5);
  1389.   objs.push_back(tunnel2);
  1390.  
  1391.   std::shared_ptr<Ground> ground2(new Ground(true));
  1392.   ground2->pos = Vector3(200, 0, 0);
  1393.   ground2->scale *= Vector3(1, 2, 1);
  1394.   ground2->euler.y = GH_PI;
  1395.   objs.push_back(ground2);
  1396.  
  1397.   std::shared_ptr<Portal> portal1(new Portal());
  1398.   tunnel1->SetDoor1(*portal1);
  1399.   portals.push_back(portal1);
  1400.  
  1401.   std::shared_ptr<Portal> portal2(new Portal());
  1402.   tunnel1->SetDoor2(*portal2);
  1403.   portals.push_back(portal2);
  1404.  
  1405.   std::shared_ptr<Portal> portal3(new Portal());
  1406.   tunnel2->SetDoor1(*portal3);
  1407.   portal3->euler.y -= GH_PI;
  1408.   portals.push_back(portal3);
  1409.  
  1410.   std::shared_ptr<Portal> portal4(new Portal());
  1411.   tunnel2->SetDoor2(*portal4);
  1412.   portal4->euler.y -= GH_PI;
  1413.   portals.push_back(portal4);
  1414.  
  1415.   Portal::Connect(portal1, portal4);
  1416.   Portal::Connect(portal2, portal3);
  1417.  
  1418.   player.SetPosition(Vector3(0, GH_PLAYER_HEIGHT - 2, 8));
  1419. }
  1420. #include "Level5.h"
  1421. #include "Tunnel.h"
  1422. #include "Ground.h"
  1423.  
  1424. void Level5::Load(PObjectVec& objs, PPortalVec& portals, Player& player) {
  1425.   std::shared_ptr<Tunnel> tunnel1(new Tunnel(Tunnel::SCALE));
  1426.   tunnel1->pos = Vector3(-1.2f, 0, 0);
  1427.   tunnel1->scale = Vector3(1, 1, 2.4f);
  1428.   objs.push_back(tunnel1);
  1429.  
  1430.   std::shared_ptr<Ground> ground1(new Ground());
  1431.   ground1->scale *= 1.2f;
  1432.   objs.push_back(ground1);
  1433.  
  1434.   std::shared_ptr<Tunnel> tunnel2(new Tunnel(Tunnel::NORMAL));
  1435.   tunnel2->pos = Vector3(201.2f, 0, 0);
  1436.   tunnel2->scale = Vector3(1, 1, 2.4f);
  1437.   objs.push_back(tunnel2);
  1438.  
  1439.   std::shared_ptr<Ground> ground2(new Ground());
  1440.   ground2->pos = Vector3(200, 0, 0);
  1441.   ground2->scale *= 1.2f;
  1442.   objs.push_back(ground2);
  1443.  
  1444.   std::shared_ptr<Portal> portal1(new Portal());
  1445.   tunnel1->SetDoor1(*portal1);
  1446.   portals.push_back(portal1);
  1447.  
  1448.   std::shared_ptr<Portal> portal2(new Portal());
  1449.   tunnel2->SetDoor1(*portal2);
  1450.   portals.push_back(portal2);
  1451.  
  1452.   std::shared_ptr<Portal> portal3(new Portal());
  1453.   tunnel1->SetDoor2(*portal3);
  1454.   portals.push_back(portal3);
  1455.  
  1456.   std::shared_ptr<Portal> portal4(new Portal());
  1457.   tunnel2->SetDoor2(*portal4);
  1458.   portals.push_back(portal4);
  1459.  
  1460.   Portal::Connect(portal1, portal2);
  1461.   Portal::Connect(portal3, portal4);
  1462.  
  1463.   std::shared_ptr<Tunnel> tunnel3(new Tunnel(Tunnel::NORMAL));
  1464.   tunnel3->pos = Vector3(-1, 0, -4.2f);
  1465.   tunnel3->scale = Vector3(0.25f, 0.25f, 0.6f);
  1466.   tunnel3->euler.y = GH_PI/2;
  1467.   objs.push_back(tunnel3);
  1468.  
  1469.   player.SetPosition(Vector3(0, GH_PLAYER_HEIGHT, 5));
  1470. }
  1471. #pragma once
  1472. #include "Scene.h"
  1473.  
  1474. class Level5 : public Scene {
  1475. public:
  1476.   virtual void Load(PObjectVec& objs, PPortalVec& portals, Player& player) override;
  1477. };
  1478. #include "Level6.h"
  1479. #include "Floorplan.h"
  1480.  
  1481. void Level6::Load(PObjectVec& objs, PPortalVec& portals, Player& player) {
  1482.   std::shared_ptr<Floorplan> floorplan(new Floorplan);
  1483.   objs.push_back(floorplan);
  1484.   floorplan->AddPortals(portals);
  1485.  
  1486.   player.SetPosition(Vector3(2, GH_PLAYER_HEIGHT, 2));
  1487. }
  1488. #pragma once
  1489. #include "Scene.h"
  1490.  
  1491. class Level6 : public Scene {
  1492. public:
  1493.   virtual void Load(PObjectVec& objs, PPortalVec& portals, Player& player) override;
  1494. };
  1495. #define _CRT_SECURE_NO_WARNINGS
  1496. #include "Engine.h"
  1497.  
  1498. int APIENTRY WinMain(HINSTANCE hCurrentInst, HINSTANCE hPreviousInst, LPSTR lpszCmdLine, int nCmdShow) {
  1499.   //Open console in debug mode
  1500. #ifdef _DEBUG
  1501.   AllocConsole();
  1502.   //SetWindowPos(GetConsoleWindow(), 0, 1920, 200, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
  1503.   AttachConsole(GetCurrentProcessId());
  1504.   freopen("CON", "w", stdout);
  1505. #endif
  1506.  
  1507.   //Run the main engine
  1508.   Engine engine;
  1509.   return engine.Run();
  1510. }
  1511. #include "Mesh.h"
  1512. #include "Vector.h"
  1513. #include <fstream>
  1514. #include <sstream>
  1515. #include <string>
  1516. #include <cassert>
  1517.  
  1518. Mesh::Mesh(const char* fname) {
  1519.   //Open the file for reading
  1520.   std::ifstream fin(std::string("Meshes/") + fname);
  1521.   if (!fin) {
  1522.     return;
  1523.   }
  1524.  
  1525.   //Temporaries
  1526.   std::vector<float> vert_palette;
  1527.   std::vector<float> uv_palette;
  1528.   bool is3DTex = false;
  1529.  
  1530.   //Read the file
  1531.   std::string line;
  1532.   while (!fin.eof()) {
  1533.     std::getline(fin, line);
  1534.     if (line.find("v ") == 0) {
  1535.       std::stringstream ss(line.c_str() + 2);
  1536.       float x, y, z;
  1537.       ss >> x >> y >> z;
  1538.       vert_palette.push_back(x);
  1539.       vert_palette.push_back(y);
  1540.       vert_palette.push_back(z);
  1541.     } else if (line.find("vt ") == 0) {
  1542.       std::stringstream ss(line.c_str() + 3);
  1543.       float u, v, w;
  1544.       ss >> u >> v >> w;
  1545.       uv_palette.push_back(u);
  1546.       uv_palette.push_back(v);
  1547.       if (!ss.fail()) {
  1548.         uv_palette.push_back(w);
  1549.         is3DTex = true;
  1550.       }
  1551.     } else if (line.find("c ") == 0) {
  1552.       uint32_t a = 0, b = 0, c = 0;
  1553.       if (line[2] == '*') {
  1554.         const uint32_t v_ix = (uint32_t)vert_palette.size() / 3;
  1555.         a = v_ix - 2; b = v_ix - 1; c = v_ix;
  1556.       } else {
  1557.         std::stringstream ss(line.c_str() + 2);
  1558.         ss >> a >> b >> c;
  1559.       }
  1560.       const Vector3 v1(&vert_palette[(a - 1) * 3]);
  1561.       const Vector3 v2(&vert_palette[(b - 1) * 3]);
  1562.       const Vector3 v3(&vert_palette[(c - 1) * 3]);
  1563.       colliders.push_back(Collider(v1, v2, v3));
  1564.     } else if (line.find("f ") == 0) {
  1565.       //Count the slashes
  1566.       int num_slashes = 0;
  1567.       size_t last_slash_ix = 0;
  1568.       bool doubleslash = false;
  1569.       for (size_t i = 0; i < line.size(); ++i) {
  1570.         if (line[i] == '/') {
  1571.           line[i] = ' ';
  1572.           if (last_slash_ix == i - 1) {
  1573.             assert(vert_palette.size() == uv_palette.size() || uv_palette.empty());
  1574.             doubleslash = true;
  1575.           }
  1576.           last_slash_ix = i;
  1577.           num_slashes++;
  1578.         }
  1579.       }
  1580.       uint32_t a=0, b=0, c=0, d=0;
  1581.       uint32_t at=0, bt=0, ct=0, dt=0;
  1582.       uint32_t _tmp;
  1583.       std::stringstream ss(line.c_str() + 2);
  1584.       const bool wild = (line[2] == '*');
  1585.       const bool wild2 = (line[3] == '*');
  1586.       bool isQuad = false;
  1587.  
  1588.       //Interpret face based on slash
  1589.       if (wild) {
  1590.         assert(num_slashes == 0);
  1591.         const uint32_t v_ix = (uint32_t)vert_palette.size() / 3;
  1592.         const uint32_t t_ix = (uint32_t)uv_palette.size() / (is3DTex ? 3 : 2);
  1593.         if (wild2) {
  1594.           a = v_ix - 3; b = v_ix - 2; c = v_ix - 1; d = v_ix - 0;
  1595.           at = t_ix - 3; bt = t_ix - 2; ct = t_ix - 1; dt = t_ix - 0;
  1596.           isQuad = true;
  1597.         } else {
  1598.           a = v_ix - 2; b = v_ix - 1; c = v_ix;
  1599.           at = t_ix - 2; bt = t_ix - 1; ct = t_ix;
  1600.         }
  1601.       } else if (num_slashes == 0) {
  1602.         ss >> a >> b >> c >> d;
  1603.         at = a; bt = b; ct = c; dt = d;
  1604.         if (!ss.fail()) {
  1605.           isQuad = true;
  1606.         }
  1607.       } else if (num_slashes == 3) {
  1608.         ss >> a >> at >> b >> bt >> c >> ct;
  1609.       } else if (num_slashes == 4) {
  1610.         isQuad = true;
  1611.         ss >> a >> at >> b >> bt >> c >> ct >> d >> dt;
  1612.       } else if (num_slashes == 6) {
  1613.         if (doubleslash) {
  1614.           ss >> a >> _tmp >> b >> _tmp >> c >> _tmp;
  1615.           at = a; bt = b; ct = c;
  1616.         } else {
  1617.           ss >> a >> at >> _tmp >> b >> bt >> _tmp >> c >> ct >> _tmp;
  1618.         }
  1619.       } else if (num_slashes == 8) {
  1620.         isQuad = true;
  1621.         if (doubleslash) {
  1622.           ss >> a >> _tmp >> b >> _tmp >> c >> _tmp >> d >> _tmp;
  1623.           at = a; bt = b; ct = c; dt = d;
  1624.         } else {
  1625.           ss >> a >> at >> _tmp >> b >> bt >> _tmp >> c >> ct >> _tmp >> d >> dt >> _tmp;
  1626.         }
  1627.       } else {
  1628.         assert(false);
  1629.         continue;
  1630.       }
  1631.  
  1632.       //Add face to list
  1633.       AddFace(vert_palette, uv_palette, a, at, b, bt, c, ct, is3DTex);
  1634.       if (isQuad) {
  1635.         AddFace(vert_palette, uv_palette, c, ct, d, dt, a, at, is3DTex);
  1636.       }
  1637.     }
  1638.   }
  1639.  
  1640.   //Setup GL
  1641.   glGenVertexArrays(1, &vao);
  1642.   glBindVertexArray(vao);
  1643.  
  1644.   glGenBuffers(NUM_VBOS, vbo);
  1645.   {
  1646.     glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
  1647.     glBufferData(GL_ARRAY_BUFFER, verts.size() * sizeof(verts[0]), verts.data(), GL_STATIC_DRAW);
  1648.     glEnableVertexAttribArray(0);
  1649.     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
  1650.   }
  1651.   {
  1652.     glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
  1653.     glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(uvs[0]), uvs.data(), GL_STATIC_DRAW);
  1654.     glEnableVertexAttribArray(1);
  1655.     glVertexAttribPointer(1, (is3DTex ? 3 : 2), GL_FLOAT, GL_FALSE, 0, 0);
  1656.   }
  1657.   {
  1658.     glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
  1659.     glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(normals[0]), normals.data(), GL_STATIC_DRAW);
  1660.     glEnableVertexAttribArray(2);
  1661.     glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
  1662.   }
  1663. }
  1664.  
  1665. Mesh::~Mesh() {
  1666.   glDeleteBuffers(NUM_VBOS, vbo);
  1667.   glDeleteVertexArrays(1, &vao);
  1668. }
  1669.  
  1670. void Mesh::Draw() {
  1671.   glBindVertexArray(vao);
  1672.   glDrawArrays(GL_TRIANGLES, 0, (GLsizei)verts.size());
  1673. }
  1674.  
  1675. void Mesh::DebugDraw(const Camera& cam, const Matrix4& objMat) {
  1676.   for (size_t i = 0; i < colliders.size(); ++i) {
  1677.     colliders[i].DebugDraw(cam, objMat);
  1678.   }
  1679. }
  1680.  
  1681. void Mesh::AddFace(
  1682.   const std::vector<float>& vert_palette, const std::vector<float>& uv_palette,
  1683.   uint32_t a, uint32_t at, uint32_t b, uint32_t bt, uint32_t c, uint32_t ct, bool is3DTex)
  1684. {
  1685.   //Merge texture and vertex indicies
  1686.   assert(a > 0 && b > 0 && c > 0);
  1687.   assert(at > 0 && bt > 0 && ct > 0);
  1688.   a -= 1; b -= 1; c -= 1;
  1689.   at -= 1; bt -= 1; ct -= 1;
  1690.   const uint32_t v_ix[3] = { a, b, c };
  1691.   const uint32_t uv_ix[3] = { at, bt, ct };
  1692.  
  1693.   //Calcuate the normal for this face
  1694.   const Vector3 v1(&vert_palette[a * 3]);
  1695.   const Vector3 v2(&vert_palette[b * 3]);
  1696.   const Vector3 v3(&vert_palette[c * 3]);
  1697.   const Vector3 normal = (v2 - v1).Cross(v3 - v1).Normalized();
  1698.  
  1699.   for (int i = 0; i < 3; ++i) {
  1700.     const uint32_t v = v_ix[i];
  1701.     const uint32_t vt = uv_ix[i];
  1702.     assert(v < vert_palette.size() / 3);
  1703.     verts.push_back(vert_palette[v * 3]);
  1704.     verts.push_back(vert_palette[v * 3 + 1]);
  1705.     verts.push_back(vert_palette[v * 3 + 2]);
  1706.     if (!uv_palette.empty()) {
  1707.       if (is3DTex) {
  1708.         assert(vt < uv_palette.size() / 3);
  1709.         uvs.push_back(uv_palette[vt * 3]);
  1710.         uvs.push_back(uv_palette[vt * 3 + 1]);
  1711.         uvs.push_back(uv_palette[vt * 3 + 2]);
  1712.       } else {
  1713.         assert(vt < uv_palette.size() / 2);
  1714.         uvs.push_back(uv_palette[vt * 2]);
  1715.         uvs.push_back(uv_palette[vt * 2 + 1]);
  1716.       }
  1717.     } else {
  1718.       uvs.push_back(0.0f);
  1719.       uvs.push_back(0.0f);
  1720.     }
  1721.     normals.push_back(normal.x);
  1722.     normals.push_back(normal.y);
  1723.     normals.push_back(normal.z);
  1724.   }
  1725. }
  1726. #pragma once
  1727. #include "Collider.h"
  1728. #include "Camera.h"
  1729. #include <GL/glew.h>
  1730. #include <vector>
  1731. #include <map>
  1732.  
  1733. class Mesh {
  1734. public:
  1735.   static const int NUM_VBOS = 3;
  1736.  
  1737.   Mesh(const char* fname);
  1738.   ~Mesh();
  1739.  
  1740.   void Draw();
  1741.  
  1742.   void DebugDraw(const Camera& cam, const Matrix4& objMat);
  1743.  
  1744.   std::vector<Collider> colliders;
  1745.  
  1746. private:
  1747.   void AddFace(
  1748.     const std::vector<float>& vert_palette, const std::vector<float>& uv_palette,
  1749.     uint32_t a, uint32_t at, uint32_t b, uint32_t bt, uint32_t c, uint32_t ct, bool is3DTex);
  1750.  
  1751.   GLuint vao;
  1752.   GLuint vbo[NUM_VBOS];
  1753.  
  1754.   std::vector<float> verts;
  1755.   std::vector<float> uvs;
  1756.   std::vector<float> normals;
  1757. };
  1758. #include "Object.h"
  1759. #include "Mesh.h"
  1760. #include "Shader.h"
  1761. #include "Texture.h"
  1762.  
  1763. Object::Object() :
  1764.   pos(0.0f),
  1765.   euler(0.0f),
  1766.   scale(1.0f),
  1767.   p_scale(1.0f) {
  1768. }
  1769.  
  1770. void Object::Reset() {
  1771.   pos.SetZero();
  1772.   euler.SetZero();
  1773.   scale.SetOnes();
  1774.   p_scale = 1.0f;
  1775. }
  1776.  
  1777. void Object::Draw(const Camera& cam, uint32_t curFBO) {
  1778.   if (shader && mesh) {
  1779.     const Matrix4 mv = WorldToLocal().Transposed();
  1780.     const Matrix4 mvp = cam.Matrix() * LocalToWorld();
  1781.     shader->Use();
  1782.     if (texture) {
  1783.       texture->Use();
  1784.     }
  1785.     shader->SetMVP(mvp.m, mv.m);
  1786.     mesh->Draw();
  1787.   }
  1788. }
  1789.  
  1790. Vector3 Object::Forward() const {
  1791.   return -(Matrix4::RotZ(euler.z) * Matrix4::RotX(euler.x) * Matrix4::RotY(euler.y)).ZAxis();
  1792. }
  1793.  
  1794. Matrix4 Object::LocalToWorld() const {
  1795.   return Matrix4::Trans(pos) * Matrix4::RotY(euler.y) * Matrix4::RotX(euler.x) * Matrix4::RotZ(euler.z) * Matrix4::Scale(scale * p_scale);
  1796. }
  1797.  
  1798. Matrix4 Object::WorldToLocal() const {
  1799.   return Matrix4::Scale(1.0f / (scale * p_scale)) * Matrix4::RotZ(-euler.z) * Matrix4::RotX(-euler.x) * Matrix4::RotY(-euler.y) * Matrix4::Trans(-pos);
  1800. }
  1801.  
  1802. void Object::DebugDraw(const Camera& cam) {
  1803.   if (mesh) {
  1804.     mesh->DebugDraw(cam, LocalToWorld());
  1805.   }
  1806. }
  1807. #pragma once
  1808. #include "GameHeader.h"
  1809. #include "Vector.h"
  1810. #include "Camera.h"
  1811. #include "Sphere.h"
  1812. #include <vector>
  1813. #include <memory>
  1814.  
  1815. //Forward declarations
  1816. class Physical;
  1817. class Mesh;
  1818. class Texture;
  1819. class Shader;
  1820.  
  1821. class Object {
  1822. public:
  1823.   Object();
  1824.   virtual ~Object() {}
  1825.  
  1826.   virtual void Reset();
  1827.   virtual void Draw(const Camera& cam, uint32_t curFBO);
  1828.   virtual void Update() {};
  1829.   virtual void OnHit(Object& other, Vector3& push) {};
  1830.  
  1831.   //Casts
  1832.   virtual Physical* AsPhysical() { return nullptr; }
  1833.   const Physical* AsPhysical() const { return const_cast<Object*>(this)->AsPhysical(); }
  1834.  
  1835.   void DebugDraw(const Camera& cam);
  1836.  
  1837.   Matrix4 LocalToWorld() const;
  1838.   Matrix4 WorldToLocal() const;
  1839.   Vector3 Forward() const;
  1840.  
  1841.   Vector3 pos;
  1842.   Vector3 euler;
  1843.   Vector3 scale;
  1844.  
  1845.   // Physical scale, only updated by portal scale changes
  1846.   float p_scale;
  1847.  
  1848.   std::shared_ptr<Mesh> mesh;
  1849.   std::shared_ptr<Texture> texture;
  1850.   std::shared_ptr<Shader> shader;
  1851. };
  1852. typedef std::vector<std::shared_ptr<Object>> PObjectVec;
  1853. #include "Physical.h"
  1854. #include "GameHeader.h"
  1855.  
  1856. Physical::Physical() {
  1857.   Reset();
  1858. }
  1859.  
  1860. void Physical::Reset() {
  1861.   Object::Reset();
  1862.   velocity.SetZero();
  1863.   gravity.Set(0.0f, GH_GRAVITY, 0.0f);
  1864.   bounce = 0.0f;
  1865.   friction = 0.0f;
  1866.   high_friction = 0.0f;
  1867.   drag = 0.0f;
  1868.   prev_pos.SetZero();
  1869. }
  1870.  
  1871. void Physical::Update() {
  1872.   prev_pos = pos;
  1873.   velocity += gravity * p_scale * GH_DT;
  1874.   velocity *= (1.0f - drag);
  1875.   pos += velocity * GH_DT;
  1876. }
  1877.  
  1878. void Physical::OnCollide(Object& other, const Vector3& push) {
  1879.   //Update position to avoid collision
  1880.   pos += push;
  1881.  
  1882.   //Ignore push if delta is too small
  1883.   if (push.MagSq() < 1e-8f * p_scale) {
  1884.     return;
  1885.   }
  1886.  
  1887.   //Calculate kinetic friction
  1888.   float kinetic_friction = friction;
  1889.   if (high_friction > 0.0f) {
  1890.     const float vel_ratio = velocity.Mag() / (high_friction * p_scale);
  1891.     kinetic_friction = GH_MIN(friction * (vel_ratio + 5.0f) / (vel_ratio + 1.0f), 1.0f);
  1892.   }
  1893.  
  1894.   //Update velocity to react to collision
  1895.   const Vector3 push_proj = push * (velocity.Dot(push) / push.Dot(push));
  1896.   velocity = (velocity - push_proj) * (1.0f - kinetic_friction) - push_proj * bounce;
  1897. }
  1898.  
  1899. bool Physical::TryPortal(const Portal& portal) {
  1900.   const Vector3 bump = portal.GetBump(prev_pos) * (2 * GH_NEAR_MIN * p_scale);
  1901.   const Portal::Warp* warp = portal.Intersects(prev_pos, pos, bump);
  1902.   if (warp) {
  1903.     //Teleport object
  1904.     pos = warp->deltaInv.MulPoint(pos - bump * 2);
  1905.     velocity = warp->deltaInv.MulDirection(velocity);
  1906.     prev_pos = pos;
  1907.  
  1908.     //Update camera direction
  1909.     const Vector3 forward(-std::sin(euler.y), 0, -std::cos(euler.y));
  1910.     const Vector3 newDir = warp->deltaInv.MulDirection(forward);
  1911.     euler.y = -std::atan2(newDir.x, -newDir.z);
  1912.  
  1913.     //Update object scale
  1914.     p_scale *= warp->deltaInv.XAxis().Mag();
  1915.     return true;
  1916.   }
  1917.   return false;
  1918. }
  1919. #pragma once
  1920. #include "Object.h"
  1921. #include "Portal.h"
  1922. #include "Sphere.h"
  1923.  
  1924. class Physical : public Object {
  1925. public:
  1926.   Physical();
  1927.   virtual ~Physical() override {}
  1928.  
  1929.   virtual void Reset() override;
  1930.   virtual void Update() override;
  1931.   virtual void OnCollide(Object& other, const Vector3& push);
  1932.  
  1933.   void SetPosition(const Vector3& _pos) {
  1934.     pos = _pos;
  1935.     prev_pos = _pos;
  1936.   }
  1937.  
  1938.   bool TryPortal(const Portal& portal);
  1939.  
  1940.   virtual Physical* AsPhysical() override { return this; }
  1941.  
  1942.   Vector3 gravity;
  1943.   Vector3 velocity;
  1944.   float bounce;
  1945.   float friction;
  1946.   float high_friction;
  1947.   float drag;
  1948.  
  1949.   Vector3 prev_pos;
  1950.  
  1951.   std::vector<Sphere> hitSpheres;
  1952. };
  1953. #pragma once
  1954. #include "Object.h"
  1955. #include "Resources.h"
  1956.  
  1957. class Pillar : public Object {
  1958. public:
  1959.   Pillar() {
  1960.     mesh = AquireMesh("pillar.obj");
  1961.     shader = AquireShader("texture");
  1962.     texture = AquireTexture("white.bmp");
  1963.     scale = Vector3(0.1f);
  1964.   }
  1965.   virtual ~Pillar() {}
  1966. };
  1967. #pragma once
  1968. #include "Object.h"
  1969. #include "Resources.h"
  1970.  
  1971. class PillarRoom : public Object {
  1972. public:
  1973.   PillarRoom() {
  1974.     mesh = AquireMesh("pillar_room.obj");
  1975.     shader = AquireShader("texture");
  1976.     texture = AquireTexture("three_room.bmp");
  1977.     scale = Vector3(1.1f);
  1978.   }
  1979.  
  1980.   void SetPortal(Object& portal) const {
  1981.     portal.pos = LocalToWorld().MulPoint(Vector3(0, 1.5f, -1));
  1982.     portal.euler = euler;
  1983.     portal.euler.y -= GH_PI / 2;
  1984.     portal.scale = Vector3(1, 1.5f, 1) * scale;
  1985.   }
  1986.   virtual ~PillarRoom() {}
  1987. };
  1988. #include "Player.h"
  1989. #include "Input.h"
  1990. #include "GameHeader.h"
  1991. #include <Windows.h>
  1992. #include <iostream>
  1993.  
  1994. Player::Player() {
  1995.   Reset();
  1996.   hitSpheres.push_back(Sphere(Vector3(0, 0, 0), GH_PLAYER_RADIUS));
  1997.   hitSpheres.push_back(Sphere(Vector3(0, GH_PLAYER_RADIUS - GH_PLAYER_HEIGHT, 0), GH_PLAYER_RADIUS));
  1998. }
  1999.  
  2000. void Player::Reset() {
  2001.   Physical::Reset();
  2002.   cam_rx = 0.0f;
  2003.   cam_ry = 0.0f;
  2004.   bob_mag = 0.0f;
  2005.   bob_phi = 0.0f;
  2006.   friction = 0.04f;
  2007.   drag = 0.002f;
  2008.   onGround = true;
  2009. }
  2010.  
  2011. void Player::Update() {
  2012.   //Update bobbing motion
  2013.   float magT = (prev_pos - pos).Mag() / (GH_DT * p_scale);
  2014.   if (!onGround) { magT = 0.0f; }
  2015.   bob_mag = bob_mag*(1.0f - GH_BOB_DAMP) + magT*GH_BOB_DAMP;
  2016.   if (bob_mag < GH_BOB_MIN) {
  2017.     bob_phi = 0.0f;
  2018.   } else {
  2019.     bob_phi += GH_BOB_FREQ * GH_DT;
  2020.     if (bob_phi > 2 * GH_PI) {
  2021.       bob_phi -= 2 * GH_PI;
  2022.     }
  2023.   }
  2024.  
  2025.   //Physics
  2026.   Physical::Update();
  2027.  
  2028.   //Looking
  2029.   Look(GH_INPUT->mouse_dx, GH_INPUT->mouse_dy);
  2030.  
  2031.   //Movement
  2032.   float moveF = 0.0f;
  2033.   float moveL = 0.0f;
  2034.   if (GH_INPUT->key['W']) {
  2035.     moveF += 1.0f;
  2036.   }
  2037.   if (GH_INPUT->key['S']) {
  2038.     moveF -= 1.0f;
  2039.   }
  2040.   if (GH_INPUT->key['A']) {
  2041.     moveL += 1.0f;
  2042.   }
  2043.   if (GH_INPUT->key['D']) {
  2044.     moveL -= 1.0f;
  2045.   }
  2046.   Move(moveF, moveL);
  2047.  
  2048. #if 0
  2049.   //Jumping
  2050.   if (onGround && GH_INPUT->key[VK_SPACE]) {
  2051.     velocity.y += 2.0f * p_scale;
  2052.   }
  2053. #endif
  2054.  
  2055.   //Reset ground state after update finishes
  2056.   onGround = false;
  2057. }
  2058.  
  2059. void Player::Look(float mouseDx, float mouseDy) {
  2060.   //Adjust x-axis rotation
  2061.   cam_rx -= mouseDy * GH_MOUSE_SENSITIVITY;
  2062.   if (cam_rx > GH_PI / 2) {
  2063.     cam_rx = GH_PI / 2;
  2064.   } else if (cam_rx < -GH_PI / 2) {
  2065.     cam_rx = -GH_PI / 2;
  2066.   }
  2067.  
  2068.   //Adjust y-axis rotation
  2069.   cam_ry -= mouseDx * GH_MOUSE_SENSITIVITY;
  2070.   if (cam_ry > GH_PI) {
  2071.     cam_ry -= GH_PI * 2;
  2072.   } else if (cam_ry < -GH_PI) {
  2073.     cam_ry += GH_PI * 2;
  2074.   }
  2075. }
  2076.  
  2077. void Player::Move(float moveF, float moveL) {
  2078.   //Make sure movement is not too fast
  2079.   const float mag = std::sqrt(moveF*moveF + moveL*moveL);
  2080.   if (mag > 1.0f) {
  2081.     moveF /= mag;
  2082.     moveL /= mag;
  2083.   }
  2084.  
  2085.   //Movement
  2086.   const Matrix4 camToWorld = LocalToWorld() * Matrix4::RotY(cam_ry);
  2087.   velocity += camToWorld.MulDirection(Vector3(-moveL, 0, -moveF)) * (GH_WALK_ACCEL * GH_DT);
  2088.  
  2089.   //Don't allow non-falling speeds above the player's max speed
  2090.   const float tempY = velocity.y;
  2091.   velocity.y = 0.0f;
  2092.   velocity.ClipMag(p_scale * GH_WALK_SPEED);
  2093.   velocity.y = tempY;
  2094. }
  2095.  
  2096. void Player::OnCollide(Object& other, const Vector3& push) {
  2097.   //Prevent player from rolling down hills if they're not too steep
  2098.   Vector3 newPush = push;
  2099.   if (push.Normalized().y > 0.7f) {
  2100.     newPush.x = 0.0f;
  2101.     newPush.z = 0.0f;
  2102.     onGround = true;
  2103.   }
  2104.  
  2105.   //Friction should only apply when player is on ground
  2106.   const float cur_friction = friction;
  2107.   if (!onGround) {
  2108.     friction = 0.0f;
  2109.   }
  2110.  
  2111.   //Base call
  2112.   Physical::OnCollide(other, newPush);
  2113.   friction = cur_friction;
  2114. }
  2115.  
  2116. Matrix4 Player::WorldToCam() const {
  2117.   return Matrix4::RotX(-cam_rx) * Matrix4::RotY(-cam_ry) * Matrix4::Trans(-CamOffset()) * WorldToLocal();
  2118. }
  2119.  
  2120. Matrix4 Player::CamToWorld() const {
  2121.   return LocalToWorld() * Matrix4::Trans(CamOffset()) * Matrix4::RotY(cam_ry) * Matrix4::RotX(cam_rx);
  2122. }
  2123.  
  2124. Vector3 Player::CamOffset() const {
  2125.   //If bob is too small, don't even bother
  2126.   if (bob_mag < GH_BOB_MIN) {
  2127.     return Vector3::Zero();
  2128.   }
  2129.  
  2130.   //Convert bob to translation
  2131.   const float theta = (GH_PI/2) * std::sin(bob_phi);
  2132.   const float y = bob_mag * GH_BOB_OFFS * (1.0f - std::cos(theta));
  2133.   return Vector3(0, y, 0);
  2134. }
  2135. #pragma once
  2136. #include "Vector.h"
  2137. #include "Physical.h"
  2138.  
  2139. class Player : public Physical {
  2140. public:
  2141.   Player();
  2142.   virtual ~Player() override {}
  2143.  
  2144.   virtual void Reset() override;
  2145.   virtual void Update() override;
  2146.   virtual void OnCollide(Object& other, const Vector3& push) override;
  2147.  
  2148.   void Look(float mouseDx, float mouseDy);
  2149.   void Move(float moveF, float moveL);
  2150.  
  2151.   Matrix4 WorldToCam() const;
  2152.   Matrix4 CamToWorld() const;
  2153.   Vector3 CamOffset() const;
  2154.  
  2155. private:
  2156.   float cam_rx;
  2157.   float cam_ry;
  2158.  
  2159.   float bob_mag;
  2160.   float bob_phi;
  2161.  
  2162.   bool onGround;
  2163. };
  2164. #include "Portal.h"
  2165. #include "Engine.h"
  2166. #include <cassert>
  2167. #include <iostream>
  2168.  
  2169. Portal::Portal() : front(this), back(this) {
  2170.   mesh = AquireMesh("double_quad.obj");
  2171.   shader = AquireShader("portal");
  2172.   errShader = AquireShader("pink");
  2173. }
  2174.  
  2175. void Portal::Draw(const Camera& cam, GLuint curFBO) {
  2176.   assert(euler.x == 0.0f);
  2177.   assert(euler.z == 0.0f);
  2178.  
  2179.   //Draw pink to indicate end of render chain
  2180.   if (GH_REC_LEVEL <= 0) {
  2181.     DrawPink(cam);
  2182.     return;
  2183.   }
  2184.  
  2185.   //Find normal relative to camera
  2186.   Vector3 normal = Forward();
  2187.   const Vector3 camPos = cam.worldView.Inverse().Translation();
  2188.   const bool frontDirection = (camPos - pos).Dot(normal) > 0;
  2189.   const Warp* warp = (frontDirection ? &front : &back);
  2190.   if (frontDirection) {
  2191.     normal = -normal;
  2192.   }
  2193.  
  2194.   //Extra clipping to prevent artifacts
  2195.   const float extra_clip = GH_MIN(GH_ENGINE->NearestPortalDist() * 0.5f, 0.1f);
  2196.  
  2197.   //Create new portal camera
  2198.   Camera portalCam = cam;
  2199.   portalCam.ClipOblique(pos - normal*extra_clip, -normal);
  2200.   portalCam.worldView *= warp->delta;
  2201.   portalCam.width = GH_FBO_SIZE;
  2202.   portalCam.height = GH_FBO_SIZE;
  2203.  
  2204.   //Render portal's view from new camera
  2205.   frameBuf[GH_REC_LEVEL - 1].Render(portalCam, curFBO, warp->toPortal);
  2206.   cam.UseViewport();
  2207.  
  2208.   //Now we can render the portal texture to the screen
  2209.   const Matrix4 mv = LocalToWorld();
  2210.   const Matrix4 mvp = cam.Matrix() * mv;
  2211.   shader->Use();
  2212.   frameBuf[GH_REC_LEVEL - 1].Use();
  2213.   shader->SetMVP(mvp.m, mv.m);
  2214.   mesh->Draw();
  2215. }
  2216.  
  2217. void Portal::DrawPink(const Camera& cam) {
  2218.   const Matrix4 mv = LocalToWorld();
  2219.   const Matrix4 mvp = cam.Matrix() * mv;
  2220.   errShader->Use();
  2221.   errShader->SetMVP(mvp.m, mv.m);
  2222.   mesh->Draw();
  2223. }
  2224.  
  2225. Vector3 Portal::GetBump(const Vector3& a) const {
  2226.   const Vector3 n = Forward();
  2227.   return n * ((a - pos).Dot(n) > 0 ? 1.0f : -1.0f);
  2228. }
  2229.  
  2230. const Portal::Warp* Portal::Intersects(const Vector3& a, const Vector3& b, const Vector3& bump) const {
  2231.   const Vector3 n = Forward();
  2232.   const Vector3 p = pos + bump;
  2233.   const float da = n.Dot(a - p);
  2234.   const float db = n.Dot(b - p);
  2235.   if (da * db > 0.0f) {
  2236.     return nullptr;
  2237.   }
  2238.   const Matrix4 m = LocalToWorld();
  2239.   const Vector3 d = a + (b - a) * (da / (da - db)) - p;
  2240.   const Vector3 x = (m * Vector4(1, 0, 0, 0)).XYZ();
  2241.   if (std::abs(d.Dot(x)) >= x.Dot(x)) {
  2242.     return nullptr;
  2243.   }
  2244.   const Vector3 y = (m * Vector4(0, 1, 0, 0)).XYZ();
  2245.   if (std::abs(d.Dot(y)) >= y.Dot(y)) {
  2246.     return nullptr;
  2247.   }
  2248.   return (da > 0.0f ? &front : &back);
  2249. }
  2250.  
  2251. float Portal::DistTo(const Vector3& pt) const {
  2252.   //Get world delta
  2253.   const Matrix4 localToWorld = LocalToWorld();
  2254.   const Vector3 v = pt - localToWorld.Translation();
  2255.  
  2256.   //Get axes
  2257.   const Vector3 x = localToWorld.XAxis();
  2258.   const Vector3 y = localToWorld.YAxis();
  2259.  
  2260.   //Find closest point
  2261.   const float px = GH_CLAMP(v.Dot(x) / x.MagSq(), -1.0f, 1.0f);
  2262.   const float py = GH_CLAMP(v.Dot(y) / y.MagSq(), -1.0f, 1.0f);
  2263.   const Vector3 closest = x*px + y*py;
  2264.  
  2265.   //Calculate distance to closest point
  2266.   return (v - closest).Mag();
  2267. }
  2268.  
  2269. void Portal::Connect(std::shared_ptr<Portal>& a, std::shared_ptr<Portal>& b) {
  2270.   Connect(a->front, b->back);
  2271.   Connect(b->front, a->back);
  2272. }
  2273.  
  2274. void Portal::Connect(Warp& a, Warp& b) {
  2275.   a.toPortal = b.fromPortal;
  2276.   b.toPortal = a.fromPortal;
  2277.   a.delta = a.fromPortal->LocalToWorld() * b.fromPortal->WorldToLocal();
  2278.   b.delta = b.fromPortal->LocalToWorld() * a.fromPortal->WorldToLocal();
  2279.   a.deltaInv = b.delta;
  2280.   b.deltaInv = a.delta;
  2281. }
  2282. #pragma once
  2283. #include "GameHeader.h"
  2284. #include "Object.h"
  2285. #include "FrameBuffer.h"
  2286. #include "Mesh.h"
  2287. #include "Resources.h"
  2288. #include "Shader.h"
  2289. #include <memory>
  2290.  
  2291. class Portal : public Object {
  2292. public:
  2293.   //Subclass that represents a warp
  2294.   struct Warp {
  2295.     Warp(const Portal* fromPortal) : fromPortal(fromPortal), toPortal(nullptr) {
  2296.       delta.MakeIdentity();
  2297.       deltaInv.MakeIdentity();
  2298.     }
  2299.  
  2300.     Matrix4 delta;
  2301.     Matrix4 deltaInv;
  2302.     const Portal* fromPortal;
  2303.     const Portal* toPortal;
  2304.   };
  2305.  
  2306.   Portal();
  2307.   virtual ~Portal() {}
  2308.  
  2309.   virtual void Draw(const Camera& cam, GLuint curFBO) override;
  2310.   void DrawPink(const Camera& cam);
  2311.  
  2312.   Vector3 GetBump(const Vector3& a) const;
  2313.   const Warp* Intersects(const Vector3& a, const Vector3& b, const Vector3& bump) const;
  2314.   float DistTo(const Vector3& pt) const;
  2315.  
  2316.   static void Connect(std::shared_ptr<Portal>& a, std::shared_ptr<Portal>& b);
  2317.   static void Connect(Warp& a, Warp& b);
  2318.  
  2319.   Warp front;
  2320.   Warp back;
  2321.  
  2322. private:
  2323.   std::shared_ptr<Shader> errShader;
  2324.   FrameBuffer frameBuf[GH_MAX_RECURSION <= 1 ? 1 : GH_MAX_RECURSION - 1];
  2325. };
  2326. typedef std::vector<std::shared_ptr<Portal>> PPortalVec;
  2327. #include "Resources.h"
  2328. #include <unordered_map>
  2329.  
  2330. std::shared_ptr<Mesh> AquireMesh(const char* name) {
  2331.   static std::unordered_map<std::string, std::weak_ptr<Mesh>> map;
  2332.   std::weak_ptr<Mesh>& mesh = map[std::string(name)];
  2333.   if (mesh.expired()) {
  2334.     std::shared_ptr<Mesh> newMesh(new Mesh(name));
  2335.     mesh = newMesh;
  2336.     return newMesh;
  2337.   } else {
  2338.     return mesh.lock();
  2339.   }
  2340. }
  2341.  
  2342. std::shared_ptr<Shader> AquireShader(const char* name) {
  2343.   static std::unordered_map<std::string, std::weak_ptr<Shader>> map;
  2344.   std::weak_ptr<Shader>& shader = map[std::string(name)];
  2345.   if (shader.expired()) {
  2346.     std::shared_ptr<Shader> newShader(new Shader(name));
  2347.     shader = newShader;
  2348.     return newShader;
  2349.   } else {
  2350.     return shader.lock();
  2351.   }
  2352. }
  2353.  
  2354. std::shared_ptr<Texture> AquireTexture(const char* name, int rows, int cols) {
  2355.   static std::unordered_map<std::string, std::weak_ptr<Texture>> map;
  2356.   std::weak_ptr<Texture>& tex = map[std::string(name)];
  2357.   if (tex.expired()) {
  2358.     std::shared_ptr<Texture> newTex(new Texture(name, rows, cols));
  2359.     tex = newTex;
  2360.     return newTex;
  2361.   } else {
  2362.     return tex.lock();
  2363.   }
  2364. }
  2365. #pragma once
  2366. #include "Mesh.h"
  2367. #include "Texture.h"
  2368. #include "Shader.h"
  2369. #include <memory>
  2370.  
  2371. std::shared_ptr<Mesh> AquireMesh(const char* name);
  2372. std::shared_ptr<Shader> AquireShader(const char* name);
  2373. std::shared_ptr<Texture> AquireTexture(const char* name, int rows=1, int cols=1);
  2374. #pragma once
  2375. #include "Object.h"
  2376. #include "Portal.h"
  2377. #include "Player.h"
  2378.  
  2379. class Scene {
  2380. public:
  2381.   virtual void Load(PObjectVec& objs, PPortalVec& portals, Player& player)=0;
  2382.   virtual void Unload() {};
  2383. };
  2384. #include "Shader.h"
  2385. #include <fstream>
  2386. #include <sstream>
  2387.  
  2388. Shader::Shader(const char* name) {
  2389.   //Get the file paths
  2390.   const std::string vert = "Shaders/" + std::string(name) + ".vert";
  2391.   const std::string frag = "Shaders/" + std::string(name) + ".frag";
  2392.  
  2393.   //Load the shaders from disk
  2394.   vertId = LoadShader(vert.c_str(), GL_VERTEX_SHADER);
  2395.   fragId = LoadShader(frag.c_str(), GL_FRAGMENT_SHADER);
  2396.  
  2397.   //Create the program
  2398.   progId = glCreateProgram();
  2399.   glAttachShader(progId, vertId);
  2400.   glAttachShader(progId, fragId);
  2401.  
  2402.   //Bind variables
  2403.   for (size_t i = 0; i < attribs.size(); ++i) {
  2404.     glBindAttribLocation(progId, (GLuint)i, attribs[i].c_str());
  2405.   }
  2406.  
  2407.   //Link the program
  2408.   glLinkProgram(progId);
  2409.  
  2410.   //Check for linking errors
  2411.   GLint isLinked;
  2412.   glGetProgramiv(progId, GL_LINK_STATUS, &isLinked);
  2413.   if (!isLinked) {
  2414.     GLint logLength;
  2415.     glGetProgramiv(progId, GL_INFO_LOG_LENGTH, &logLength);
  2416.  
  2417.     std::vector<GLchar> log;
  2418.     log.resize(logLength);
  2419.     glGetProgramInfoLog(progId, logLength, &logLength, log.data());
  2420.  
  2421.     std::ofstream fout(std::string(vert) + ".link.log");
  2422.     fout.write(log.data(), logLength);
  2423.  
  2424.     progId = 0;
  2425.     return;
  2426.   }
  2427.  
  2428.   //Get global variable locations
  2429.   mvpId = glGetUniformLocation(progId, "mvp");
  2430.   mvId = glGetUniformLocation(progId, "mv");
  2431. }
  2432.  
  2433. Shader::~Shader() {
  2434.   glDetachShader(progId, vertId);
  2435.   glDetachShader(progId, fragId);
  2436.   glDeleteProgram(progId);
  2437.   glDeleteShader(vertId);
  2438.   glDeleteShader(fragId);
  2439. }
  2440.  
  2441. void Shader::Use() {
  2442.   glUseProgram(progId);
  2443. }
  2444.  
  2445. GLuint Shader::LoadShader(const char* fname, GLenum type) {
  2446.   //Read shader source from disk
  2447.   std::ifstream fin(fname);
  2448.   std::stringstream buff;
  2449.   buff << fin.rdbuf();
  2450.   const std::string str = buff.str();
  2451.   const char* source = str.c_str();
  2452.  
  2453.   //Create and compile shader
  2454.   const GLuint id = glCreateShader(type);
  2455.   glShaderSource(id, 1, (const GLchar**)&source, 0);
  2456.   glCompileShader(id);
  2457.  
  2458.   //Check to make sure there were no errors
  2459.   GLint isCompiled = 0;
  2460.   glGetShaderiv(id, GL_COMPILE_STATUS, &isCompiled);
  2461.   if (!isCompiled) {
  2462.     GLint logLength;
  2463.     glGetShaderiv(id, GL_INFO_LOG_LENGTH, &logLength);
  2464.  
  2465.     std::vector<GLchar> log;
  2466.     log.resize(logLength);
  2467.     glGetShaderInfoLog(id, logLength, &logLength, log.data());
  2468.  
  2469.     std::ofstream fout(std::string(fname) + ".log");
  2470.     fout.write(log.data(), logLength);
  2471.     return 0;
  2472.   }
  2473.  
  2474.   //Save variable bindings
  2475.   if (type == GL_VERTEX_SHADER) {
  2476.     size_t ix = 0;
  2477.     while (true) {
  2478.       ix = str.find("\nin ", ix);
  2479.       if (ix == std::string::npos) {
  2480.         break;
  2481.       }
  2482.       ix = str.find(";", ix);
  2483.       size_t start_ix = ix;
  2484.       while (str[--start_ix] != ' ');
  2485.       attribs.push_back(str.substr(start_ix + 1, ix - start_ix - 1));
  2486.     }
  2487.   }
  2488.  
  2489.   //Return the shader id
  2490.   return id;
  2491. }
  2492.  
  2493. void Shader::SetMVP(const float* mvp, const float* mv) {
  2494.   if (mvp) glUniformMatrix4fv(mvpId, 1, GL_TRUE, mvp);
  2495.   if (mv) glUniformMatrix4fv(mvId, 1, GL_TRUE, mv);
  2496. }
  2497. #pragma once
  2498. #include <GL/glew.h>
  2499. #include <vector>
  2500.  
  2501. class Shader {
  2502. public:
  2503.   Shader(const char* name);
  2504.   ~Shader();
  2505.  
  2506.   void Use();
  2507.   void SetMVP(const float* mvp, const float* mv);
  2508.  
  2509. private:
  2510.   GLuint LoadShader(const char* fname, GLenum type);
  2511.  
  2512.   std::vector<std::string> attribs;
  2513.   GLuint vertId;
  2514.   GLuint fragId;
  2515.   GLuint progId;
  2516.   GLuint mvpId;
  2517.   GLuint mvId;
  2518. };
  2519. #pragma once
  2520. #include "Resources.h"
  2521. #include "Vector.h"
  2522.  
  2523. class Sky {
  2524. public:
  2525.   Sky() {
  2526.     mesh = AquireMesh("quad.obj");
  2527.     shader = AquireShader("sky");
  2528.   }
  2529.  
  2530.   void Draw(const Camera& cam) {
  2531.     glDepthMask(GL_FALSE);
  2532.     const Matrix4 mvp = cam.projection.Inverse();
  2533.     const Matrix4 mv = cam.worldView.Inverse();
  2534.     shader->Use();
  2535.     shader->SetMVP(mvp.m, mv.m);
  2536.     mesh->Draw();
  2537.     glDepthMask(GL_TRUE);
  2538.   }
  2539.  
  2540. private:
  2541.   std::shared_ptr<Mesh> mesh;
  2542.   std::shared_ptr<Shader> shader;
  2543. };
  2544. #pragma once
  2545. #include "Vector.h"
  2546. #include <cassert>
  2547.  
  2548. class Sphere {
  2549. public:
  2550.   Sphere(float r=1.0f) : center(0.0f), radius(r) {}
  2551.   Sphere(const Vector3& pos, float r) : center(pos), radius(r) {}
  2552.  
  2553.   //Transformations to and frpom sphere coordinates
  2554.   Matrix4 UnitToLocal() const {
  2555.     assert(radius > 0.0f);
  2556.     return Matrix4::Trans(center) * Matrix4::Scale(radius);
  2557.   }
  2558.   Matrix4 LocalToUnit() const {
  2559.     assert(radius > 0.0f);
  2560.     return Matrix4::Scale(1.0f / radius) * Matrix4::Trans(-center);
  2561.   }
  2562.  
  2563.   Vector3 center;
  2564.   float radius;
  2565. };
  2566. #pragma once
  2567. #include "Object.h"
  2568. #include "Resources.h"
  2569.  
  2570. class Statue : public Object {
  2571. public:
  2572.   Statue(const char* model) {
  2573.     mesh = AquireMesh(model);
  2574.     shader = AquireShader("texture");
  2575.     texture = AquireTexture("gold.bmp");
  2576.   }
  2577.   virtual ~Statue() {}
  2578. };
  2579. #include "Texture.h"
  2580. #include <fstream>
  2581. #include <cassert>
  2582.  
  2583. Texture::Texture(const char* fname, int rows, int cols) {
  2584.   //Check if this is a 3D texture
  2585.   assert(rows >= 1 && cols >= 1);
  2586.   is3D = (rows > 1 || cols > 1);
  2587.  
  2588.   //Open the bitmap
  2589.   std::ifstream fin(std::string("Textures/") + fname, std::ios::in | std::ios::binary);
  2590.   if (!fin) {
  2591.     texId = 0;
  2592.     return;
  2593.   }
  2594.  
  2595.   //Read the bitmap
  2596.   char input[54];
  2597.   fin.read(input, 54);
  2598.   const GLsizei width = *reinterpret_cast<int32_t*>(&input[18]);
  2599.   const GLsizei height = *reinterpret_cast<int32_t*>(&input[22]);
  2600.   assert(width % cols == 0);
  2601.   assert(height % rows == 0);
  2602.   const int block_w = width / cols;
  2603.   const int block_h = height / rows;
  2604.   uint8_t* img = new uint8_t[width * height * 3];
  2605.   for (int y = height; y--> 0;) {
  2606.     const int row = y / block_h;
  2607.     const int ty = y % block_h;
  2608.     for (int x = 0; x < width; x++) {
  2609.       const int col = x / block_w;
  2610.       const int tx = x % block_w;
  2611.       uint8_t* ptr = img + ((row*cols + col)*(block_w * block_h) + ty*block_w + tx)*3;
  2612.       fin.read(reinterpret_cast<char*>(ptr), 3);
  2613.     }
  2614.     const int padding = (width * 3) % 4;
  2615.     if (padding) {
  2616.       char junk[3];
  2617.       fin.read(junk, 4 - padding);
  2618.     }
  2619.   }
  2620.  
  2621.   //Load texture into video memory
  2622.   glGenTextures(1, &texId);
  2623.   if (is3D) {
  2624.     glBindTexture(GL_TEXTURE_2D_ARRAY, texId);
  2625.     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
  2626.     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  2627.     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
  2628.     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT);
  2629.     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_GENERATE_MIPMAP, GL_TRUE);
  2630.     glGenerateMipmap(GL_TEXTURE_2D);
  2631.     glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB8, width/rows, height/cols, rows*cols, 0, GL_BGR, GL_UNSIGNED_BYTE, img);
  2632.   } else {
  2633.     glBindTexture(GL_TEXTURE_2D, texId);
  2634.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  2635.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  2636.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  2637.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  2638.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, img);
  2639.   }
  2640.  
  2641.   //Clenup
  2642.   delete[] img;
  2643. }
  2644.  
  2645. void Texture::Use() {
  2646.   if (is3D) {
  2647.     glBindTexture(GL_TEXTURE_2D_ARRAY, texId);
  2648.   } else {
  2649.     glBindTexture(GL_TEXTURE_2D, texId);
  2650.   }
  2651. }
  2652. #pragma once
  2653. #include <GL/glew.h>
  2654.  
  2655. class Texture {
  2656. public:
  2657.   Texture(const char* fname, int rows, int cols);
  2658.  
  2659.   void Use();
  2660.  
  2661. private:
  2662.   GLuint texId;
  2663.   bool is3D;
  2664. };
  2665. #pragma once
  2666. #include <Windows.h>
  2667.  
  2668. class Timer {
  2669. public:
  2670.   Timer() {
  2671.     QueryPerformanceFrequency(&frequency);
  2672.   }
  2673.  
  2674.   void Start() {
  2675.     QueryPerformanceCounter(&t1);
  2676.   }
  2677.  
  2678.   float Stop() {
  2679.     QueryPerformanceCounter(&t2);
  2680.     return float(t2.QuadPart - t1.QuadPart) / frequency.QuadPart;
  2681.   }
  2682.  
  2683.   int64_t GetTicks() {
  2684.     QueryPerformanceCounter(&t2);
  2685.     return t2.QuadPart;
  2686.   }
  2687.  
  2688.   int64_t SecondsToTicks(float s) {
  2689.     return int64_t(float(frequency.QuadPart) * s);
  2690.   }
  2691.  
  2692.   float StopStart() {
  2693.     const float result = Stop();
  2694.     t1 = t2;
  2695.     return result;
  2696.   }
  2697.  
  2698. private:
  2699.   LARGE_INTEGER frequency;        // ticks per second
  2700.   LARGE_INTEGER t1, t2;           // ticks
  2701. };
  2702. #pragma once
  2703. #include "Object.h"
  2704.  
  2705. class Tunnel : public Object {
  2706. public:
  2707.   enum Type {
  2708.     NORMAL = 0,
  2709.     SCALE = 1,
  2710.     SLOPE = 2,
  2711.   };
  2712.  
  2713.   Tunnel(Type type) : type(type) {
  2714.     if (type == SCALE) {
  2715.       mesh = AquireMesh("tunnel_scale.obj");
  2716.     } else if (type == SLOPE) {
  2717.       mesh = AquireMesh("tunnel_slope.obj");
  2718.     } else {
  2719.       mesh = AquireMesh("tunnel.obj");
  2720.     }
  2721.     shader = AquireShader("texture");
  2722.     texture = AquireTexture("checker_gray.bmp");
  2723.   }
  2724.   virtual ~Tunnel() {}
  2725.  
  2726.   void SetDoor1(Object& portal) const {
  2727.     portal.pos = LocalToWorld().MulPoint(Vector3(0, 1, 1));
  2728.     portal.euler = euler;
  2729.     portal.scale = Vector3(0.6f, 0.999f, 1) * scale.x;
  2730.   }
  2731.   void SetDoor2(Object& portal) const {
  2732.     portal.euler = euler;
  2733.     if (type == SCALE) {
  2734.       portal.pos = LocalToWorld().MulPoint(Vector3(0, 0.5f, -1));
  2735.       portal.scale = Vector3(0.3f, 0.499f, 0.5f) * scale.x;
  2736.     } else if (type == SLOPE) {
  2737.       portal.pos = LocalToWorld().MulPoint(Vector3(0, -1, -1));
  2738.       portal.scale = Vector3(0.6f, 0.999f, 1) * scale.x;
  2739.     } else {
  2740.       portal.pos = LocalToWorld().MulPoint(Vector3(0, 1, -1));
  2741.       portal.scale = Vector3(0.6f, 0.999f, 1) * scale.x;
  2742.     }
  2743.   }
  2744.  
  2745. private:
  2746.   Type type;
  2747. };
  2748. #pragma once
  2749. #include <cmath>
  2750. #include <cfloat>
  2751. #include <memory>
  2752. #include <iostream>
  2753. #include <cassert>
  2754.  
  2755. class Vector3 {
  2756. public:
  2757.   //Constructors
  2758.   Vector3() {}
  2759.   explicit Vector3(float b) : x(b), y(b), z(b) {}
  2760.   explicit Vector3(const float* b) : x(b[0]), y(b[1]), z(b[2]) {}
  2761.   explicit Vector3(float x, float y, float z) : x(x), y(y), z(z) {}
  2762.  
  2763.   //General
  2764.   inline static Vector3 Zero() { return Vector3(0.0f); }
  2765.   inline static Vector3 Ones() { return Vector3(1.0f); }
  2766.   inline static Vector3 UnitX() { return Vector3(1, 0, 0); }
  2767.   inline static Vector3 UnitY() { return Vector3(0, 1, 0); }
  2768.   inline static Vector3 UnitZ() { return Vector3(0, 0, 1); }
  2769.  
  2770.   //Setters
  2771.   inline void Set(float _x, float _y, float _z) { x = _x; y = _y; z = _z; }
  2772.   inline void SetZero() { x = 0.0f; y = 0.0f; z = 0.0f; }
  2773.   inline void SetOnes() { x = 1.0f; y = 1.0f; z = 1.0f; }
  2774.   inline void SetUnitX() { x = 1.0f; y = 0.0f; z = 0.0f; }
  2775.   inline void SetUnitY() { x = 0.0f; y = 1.0f; z = 0.0f; }
  2776.   inline void SetUnitZ() { x = 0.0f; y = 0.0f; z = 1.0f; }
  2777.  
  2778.   //Basic operatios
  2779.   inline Vector3 operator+(float b) const {
  2780.     return Vector3(x + b, y + b, z + b);
  2781.   }
  2782.   inline Vector3 operator-(float b) const {
  2783.     return Vector3(x - b, y - b, z - b);
  2784.   }
  2785.   inline Vector3 operator*(float b) const {
  2786.     return Vector3(x * b, y * b, z * b);
  2787.   }
  2788.   inline Vector3 operator/(float b) const {
  2789.     return Vector3(x / b, y / b, z / b);
  2790.   }
  2791.   inline Vector3 operator+(const Vector3& b) const {
  2792.     return Vector3(x + b.x, y + b.y, z + b.z);
  2793.   }
  2794.   inline Vector3 operator-(const Vector3& b) const {
  2795.     return Vector3(x - b.x, y - b.y, z - b.z);
  2796.   }
  2797.   inline Vector3 operator*(const Vector3& b) const {
  2798.     return Vector3(x * b.x, y * b.y, z * b.z);
  2799.   }
  2800.   inline Vector3 operator/(const Vector3& b) const {
  2801.     return Vector3(x / b.x, y / b.y, z / b.z);
  2802.   }
  2803.   inline void operator+=(float b) {
  2804.     x += b; y += b; z += b;
  2805.   }
  2806.   inline void operator-=(float b) {
  2807.     x -= b; y -= b; z -= b;
  2808.   }
  2809.   inline void operator*=(float b) {
  2810.     x *= b; y *= b; z *= b;
  2811.   }
  2812.   inline void operator/=(float b) {
  2813.     x /= b; y /= b; z /= b;
  2814.   }
  2815.   inline void operator+=(const Vector3& b) {
  2816.     x += b.x; y += b.y; z += b.z;
  2817.   }
  2818.   inline void operator-=(const Vector3& b) {
  2819.     x -= b.x; y -= b.y; z -= b.z;
  2820.   }
  2821.   inline void operator*=(const Vector3& b) {
  2822.     x *= b.x; y *= b.y; z *= b.z;
  2823.   }
  2824.   inline void operator/=(const Vector3& b) {
  2825.     x /= b.x; y /= b.y; z /= b.z;
  2826.   }
  2827.   inline Vector3 operator-() const {
  2828.     return Vector3(-x, -y, -z);
  2829.   }
  2830.  
  2831.   //Vector algebra
  2832.   inline float Dot(const Vector3& b) const {
  2833.     return x*b.x + y*b.y + z*b.z;
  2834.   }
  2835.   inline Vector3 Cross(const Vector3& b) const {
  2836.     return Vector3(y*b.z - z*b.y, z*b.x - x*b.z, x*b.y - y*b.x);
  2837.   }
  2838.   inline float MagSq() const {
  2839.     return x*x + y*y + z*z;
  2840.   }
  2841.   inline float Mag() const {
  2842.     return std::sqrt(MagSq());
  2843.   }
  2844.  
  2845.   //Normalization
  2846.   inline void Normalize() {
  2847.     (*this) /= Mag();
  2848.   }
  2849.   inline void NormalizeSafe() {
  2850.     (*this) /= (Mag() + FLT_EPSILON);
  2851.   }
  2852.   inline Vector3 Normalized() const {
  2853.     return (*this) / Mag();
  2854.   }
  2855.   inline Vector3 NormalizedSafe() const {
  2856.     return (*this) / (Mag() + FLT_EPSILON);
  2857.   }
  2858.   inline float Angle(const Vector3& b) const {
  2859.     return std::acos(Normalized().Dot(b.Normalized()));
  2860.   }
  2861.   inline float AngleSafe(const Vector3& b) const {
  2862.     return std::acos(NormalizedSafe().Dot(b.NormalizedSafe()));
  2863.   }
  2864.   inline void ClipMag(float m) {
  2865.     assert(m > 0.0f);
  2866.     const float r = MagSq() / (m * m);
  2867.     if (r > 1.0f) {
  2868.       (*this) /= std::sqrt(r);
  2869.     }
  2870.   }
  2871.  
  2872.   //Other
  2873.   inline bool IsNDC() const {
  2874.     return (x > -1.0f && x < 1.0f && y > -1.0f && y < 1.0f && z > -1.0f && z < 1.0f);
  2875.   }
  2876.  
  2877.   //Components
  2878.   float x, y, z;
  2879. };
  2880. inline Vector3 operator/(float b, const Vector3& v) {
  2881.   return Vector3(b / v.x, b / v.y, b / v.z);
  2882. }
  2883. inline void operator/=(float b, Vector3& v) {
  2884.   v.x = b / v.x; v.y = b / v.y; v.z = b / v.z;
  2885. }
  2886.  
  2887. class Vector4 {
  2888. public:
  2889.   Vector4() {}
  2890.   explicit Vector4(float b) : x(b), y(b), z(b), w(b) {}
  2891.   explicit Vector4(const Vector3& xyz, float w) : x(xyz.x), y(xyz.y), z(xyz.z), w(w) {}
  2892.   explicit Vector4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
  2893.  
  2894.   inline Vector3 XYZ() const { return Vector3(x, y, z); }
  2895.   inline Vector3 XYZNormalized() const { return Vector3(x, y, z).Normalized(); }
  2896.   inline Vector3 Homogenized() const { return Vector3(x/w, y/w, z/w); }
  2897.  
  2898.   inline Vector4 operator*(float b) const {
  2899.     return Vector4(x * b, y * b, z * b, w * b);
  2900.   }
  2901.   inline Vector4 operator/(float b) const {
  2902.     return Vector4(x / b, y / b, z / b, w / b);
  2903.   }
  2904.   inline void operator*=(float b) {
  2905.     x *= b; y *= b; z *= b; w *= b;
  2906.   }
  2907.   inline void operator/=(float b) {
  2908.     x /= b; y /= b; z /= b; w /= b;
  2909.   }
  2910.  
  2911.   inline float Dot(const Vector4& b) const { return x*b.x + y*b.y + z*b.z + w*b.w; }
  2912.  
  2913.   //Components
  2914.   float x, y, z, w;
  2915. };
  2916.  
  2917. class Matrix4 {
  2918. public:
  2919.   //Constructors
  2920.   Matrix4() {}
  2921.   explicit Matrix4(float b) { Fill(b); }
  2922.  
  2923.   //General
  2924.   inline void Fill(float b) {
  2925.     std::fill(m, m + 16, b);
  2926.   }
  2927.   inline void MakeZero() {
  2928.     Fill(0.0f);
  2929.   }
  2930.   inline void MakeIdentity() {
  2931.     m[0]  = 1.0f; m[1]  = 0.0f; m[2]  = 0.0f; m[3]  = 0.0f;
  2932.     m[4]  = 0.0f; m[5]  = 1.0f; m[6]  = 0.0f; m[7]  = 0.0f;
  2933.     m[8]  = 0.0f; m[9]  = 0.0f; m[10] = 1.0f; m[11] = 0.0f;
  2934.     m[12] = 0.0f; m[13] = 0.0f; m[14] = 0.0f; m[15] = 1.0f;
  2935.   }
  2936.   inline void MakeRotX(float a) {
  2937.     m[0] =  1.0f; m[1]  = 0.0f;        m[2]  = 0.0f;         m[3]  = 0.0f;
  2938.     m[4] =  0.0f; m[5]  = std::cos(a); m[6]  = -std::sin(a); m[7]  = 0.0f;
  2939.     m[8] =  0.0f; m[9]  = std::sin(a); m[10] = std::cos(a);  m[11] = 0.0f;
  2940.     m[12] = 0.0f; m[13] = 0.0f;        m[14] = 0.0f;         m[15] = 1.0f;
  2941.   }
  2942.   inline void MakeRotY(float a) {
  2943.     m[0]  = std::cos(a);  m[1]  = 0.0f; m[2]  = std::sin(a); m[3]  = 0.0f;
  2944.     m[4]  = 0.0f;         m[5]  = 1.0f; m[6]  = 0.0f;        m[7]  = 0.0f;
  2945.     m[8]  = -std::sin(a); m[9]  = 0.0f; m[10] = std::cos(a); m[11] = 0.0f;
  2946.     m[12] = 0.0f;         m[13] = 0.0f; m[14] = 0.0f;        m[15] = 1.0f;
  2947.   }
  2948.   inline void MakeRotZ(float a) {
  2949.     m[0]  = std::cos(a); m[1]  = -std::sin(a); m[2]  = 0.0f; m[3]  = 0.0f;
  2950.     m[4]  = std::sin(a); m[5]  = std::cos(a);  m[6]  = 0.0f; m[7]  = 0.0f;
  2951.     m[8]  = 0.0f;        m[9]  = 0.0f;         m[10] = 1.0f; m[11] = 0.0f;
  2952.     m[12] = 0.0f;        m[13] = 0.0f;         m[14] = 0.0f; m[15] = 1.0f;
  2953.   }
  2954.   inline void MakeTrans(const Vector3& t) {
  2955.     m[0]  = 1.0f; m[1]  = 0.0f; m[2]  = 0.0f; m[3]  = t.x;
  2956.     m[4]  = 0.0f; m[5]  = 1.0f; m[6]  = 0.0f; m[7]  = t.y;
  2957.     m[8]  = 0.0f; m[9]  = 0.0f; m[10] = 1.0f; m[11] = t.z;
  2958.     m[12] = 0.0f; m[13] = 0.0f; m[14] = 0.0f; m[15] = 1.0f;
  2959.   }
  2960.   inline void MakeScale(const Vector3& s) {
  2961.     m[0]  = s.x;  m[1]  = 0.0f; m[2]  = 0.0f; m[3]  = 0.0f;
  2962.     m[4]  = 0.0f; m[5]  = s.y;  m[6]  = 0.0f; m[7]  = 0.0f;
  2963.     m[8]  = 0.0f; m[9]  = 0.0f; m[10] = s.z;  m[11] = 0.0f;
  2964.     m[12] = 0.0f; m[13] = 0.0f; m[14] = 0.0f; m[15] = 1.0f;
  2965.   }
  2966.  
  2967.   //Statics
  2968.   inline static Matrix4 Zero() { Matrix4 m; m.MakeZero(); return m; }
  2969.   inline static Matrix4 Identity() { Matrix4 m; m.MakeIdentity(); return m; }
  2970.   inline static Matrix4 RotX(float a) { Matrix4 m; m.MakeRotX(a); return m; }
  2971.   inline static Matrix4 RotY(float a) { Matrix4 m; m.MakeRotY(a); return m; }
  2972.   inline static Matrix4 RotZ(float a) { Matrix4 m; m.MakeRotZ(a); return m; }
  2973.   inline static Matrix4 Trans(const Vector3& t) { Matrix4 m; m.MakeTrans(t); return m; }
  2974.   inline static Matrix4 Scale(float s) { Matrix4 m; m.MakeScale(Vector3(s)); return m; }
  2975.   inline static Matrix4 Scale(const Vector3& s) { Matrix4 m; m.MakeScale(s); return m; }
  2976.  
  2977.   //Some getters
  2978.   inline Vector3 XAxis() const {
  2979.     return Vector3(m[0], m[4], m[8]);
  2980.   }
  2981.   inline Vector3 YAxis() const {
  2982.     return Vector3(m[1], m[5], m[9]);
  2983.   }
  2984.   inline Vector3 ZAxis() const {
  2985.     return Vector3(m[2], m[6], m[10]);
  2986.   }
  2987.   inline Vector3 Translation() const {
  2988.     return Vector3(m[3], m[7], m[11]);
  2989.   }
  2990.   inline Vector3 Scale() const {
  2991.     return Vector3(m[0], m[5], m[10]);
  2992.   }
  2993.  
  2994.   //Setters
  2995.   inline void SetTranslation(const Vector3& t) {
  2996.     m[3] = t.x;
  2997.     m[7] = t.y;
  2998.     m[11] = t.z;
  2999.   }
  3000.   inline void SetXAxis(const Vector3& t) {
  3001.     m[0] = t.x;
  3002.     m[4] = t.y;
  3003.     m[8] = t.z;
  3004.   }
  3005.   inline void SetYAxis(const Vector3& t) {
  3006.     m[1] = t.x;
  3007.     m[5] = t.y;
  3008.     m[9] = t.z;
  3009.   }
  3010.   inline void SetZAxis(const Vector3& t) {
  3011.     m[2] = t.x;
  3012.     m[6] = t.y;
  3013.     m[10] = t.z;
  3014.   }
  3015.   inline void SetScale(const Vector3& s) {
  3016.     m[0] = s.x;
  3017.     m[5] = s.y;
  3018.     m[10] = s.z;
  3019.   }
  3020.  
  3021.   //Transformations
  3022.   inline Matrix4 Transposed() const {
  3023.     Matrix4 out;
  3024.     out.m[0]  = m[0]; out.m[1]  = m[4]; out.m[2]  = m[8];  out.m[3]  = m[12];
  3025.     out.m[4]  = m[1]; out.m[5]  = m[5]; out.m[6]  = m[9];  out.m[7]  = m[13];
  3026.     out.m[8]  = m[2]; out.m[9]  = m[6]; out.m[10] = m[10]; out.m[11] = m[14];
  3027.     out.m[12] = m[3]; out.m[13] = m[7]; out.m[14] = m[11]; out.m[15] = m[15];
  3028.     return out;
  3029.   }
  3030.   inline void Translate(const Vector3& t) {
  3031.     m[3] += t.x;
  3032.     m[7] += t.y;
  3033.     m[11] += t.z;
  3034.   }
  3035.   inline void Stretch(const Vector3& s) {
  3036.     m[0] *= s.x;
  3037.     m[5] *= s.y;
  3038.     m[10] *= s.z;
  3039.   }
  3040.  
  3041.   //Basic operatios
  3042.   inline Matrix4 operator+(const Matrix4& b) const {
  3043.     Matrix4 out;
  3044.     for (int i = 0; i < 16; ++i) { out.m[i] = m[i] + b.m[i]; }
  3045.     return out;
  3046.   }
  3047.   inline Matrix4 operator-(const Matrix4& b) const {
  3048.     Matrix4 out;
  3049.     for (int i = 0; i < 16; ++i) { out.m[i] = m[i] - b.m[i]; }
  3050.     return out;
  3051.   }
  3052.   inline void operator+=(const Matrix4& b) {
  3053.     for (int i = 0; i < 16; ++i) { m[i] += b.m[i]; }
  3054.   }
  3055.   inline void operator-=(const Matrix4& b) {
  3056.     for (int i = 0; i < 16; ++i) { m[i] -= b.m[i]; }
  3057.   }
  3058.   inline void operator*=(float b) {
  3059.     for (int i = 0; i < 16; ++i) { m[i] *= b; }
  3060.   }
  3061.   inline void operator/=(float b) {
  3062.     operator*=(1.0f / b);
  3063.   }
  3064.  
  3065.   //Multiplication
  3066.   Matrix4 operator*(const Matrix4& b) const {
  3067.     Matrix4 out;
  3068.     out.m[0]  = b.m[0]*m[0]  + b.m[4]*m[1]  + b.m[8] *m[2]  + b.m[12]*m[3];
  3069.     out.m[1]  = b.m[1]*m[0]  + b.m[5]*m[1]  + b.m[9] *m[2]  + b.m[13]*m[3];
  3070.     out.m[2]  = b.m[2]*m[0]  + b.m[6]*m[1]  + b.m[10]*m[2]  + b.m[14]*m[3];
  3071.     out.m[3]  = b.m[3]*m[0]  + b.m[7]*m[1]  + b.m[11]*m[2]  + b.m[15]*m[3];
  3072.  
  3073.     out.m[4]  = b.m[0]*m[4]  + b.m[4]*m[5]  + b.m[8] *m[6]  + b.m[12]*m[7];
  3074.     out.m[5]  = b.m[1]*m[4]  + b.m[5]*m[5]  + b.m[9] *m[6]  + b.m[13]*m[7];
  3075.     out.m[6]  = b.m[2]*m[4]  + b.m[6]*m[5]  + b.m[10]*m[6]  + b.m[14]*m[7];
  3076.     out.m[7]  = b.m[3]*m[4]  + b.m[7]*m[5]  + b.m[11]*m[6]  + b.m[15]*m[7];
  3077.  
  3078.     out.m[8]  = b.m[0]*m[8]  + b.m[4]*m[9]  + b.m[8] *m[10] + b.m[12]*m[11];
  3079.     out.m[9]  = b.m[1]*m[8]  + b.m[5]*m[9]  + b.m[9] *m[10] + b.m[13]*m[11];
  3080.     out.m[10] = b.m[2]*m[8]  + b.m[6]*m[9]  + b.m[10]*m[10] + b.m[14]*m[11];
  3081.     out.m[11] = b.m[3]*m[8]  + b.m[7]*m[9]  + b.m[11]*m[10] + b.m[15]*m[11];
  3082.  
  3083.     out.m[12] = b.m[0]*m[12] + b.m[4]*m[13] + b.m[8] *m[14] + b.m[12]*m[15];
  3084.     out.m[13] = b.m[1]*m[12] + b.m[5]*m[13] + b.m[9] *m[14] + b.m[13]*m[15];
  3085.     out.m[14] = b.m[2]*m[12] + b.m[6]*m[13] + b.m[10]*m[14] + b.m[14]*m[15];
  3086.     out.m[15] = b.m[3]*m[12] + b.m[7]*m[13] + b.m[11]*m[14] + b.m[15]*m[15];
  3087.     return out;
  3088.   }
  3089.   void operator*=(const Matrix4& b) {
  3090.     (*this) = operator*(b);
  3091.   }
  3092.   Vector4 operator*(const Vector4& b) const {
  3093.     return Vector4(
  3094.       m[0]*b.x  + m[1]*b.y  + m[2]*b.z  + m[3]*b.w,
  3095.       m[4]*b.x  + m[5]*b.y  + m[6]*b.z  + m[7]*b.w,
  3096.       m[8]*b.x  + m[9]*b.y  + m[10]*b.z + m[11]*b.w,
  3097.       m[12]*b.x + m[13]*b.y + m[14]*b.z + m[15]*b.w
  3098.     );
  3099.   }
  3100.   Vector3 MulPoint(const Vector3& b) const {
  3101.     const Vector3 p(
  3102.       m[0] * b.x + m[1] * b.y + m[2] * b.z + m[3],
  3103.       m[4] * b.x + m[5] * b.y + m[6] * b.z + m[7],
  3104.       m[8] * b.x + m[9] * b.y + m[10] * b.z + m[11]
  3105.     );
  3106.     const float w = m[12] * b.x + m[13] * b.y + m[14] * b.z + m[15];
  3107.     return p / w;
  3108.   }
  3109.   Vector3 MulDirection(const Vector3& b) const {
  3110.     return Vector3(
  3111.       m[0] * b.x + m[1] * b.y + m[2] * b.z,
  3112.       m[4] * b.x + m[5] * b.y + m[6] * b.z,
  3113.       m[8] * b.x + m[9] * b.y + m[10] * b.z
  3114.     );
  3115.   }
  3116.  
  3117.   //Inverse
  3118.   Matrix4 Inverse() const {
  3119.     Matrix4 inv;
  3120.  
  3121.     inv.m[0] = m[5] * m[10] * m[15] -
  3122.       m[5] * m[11] * m[14] -
  3123.       m[9] * m[6] * m[15] +
  3124.       m[9] * m[7] * m[14] +
  3125.       m[13] * m[6] * m[11] -
  3126.       m[13] * m[7] * m[10];
  3127.  
  3128.     inv.m[4] = -m[4] * m[10] * m[15] +
  3129.       m[4] * m[11] * m[14] +
  3130.       m[8] * m[6] * m[15] -
  3131.       m[8] * m[7] * m[14] -
  3132.       m[12] * m[6] * m[11] +
  3133.       m[12] * m[7] * m[10];
  3134.  
  3135.     inv.m[8] = m[4] * m[9] * m[15] -
  3136.       m[4] * m[11] * m[13] -
  3137.       m[8] * m[5] * m[15] +
  3138.       m[8] * m[7] * m[13] +
  3139.       m[12] * m[5] * m[11] -
  3140.       m[12] * m[7] * m[9];
  3141.  
  3142.     inv.m[12] = -m[4] * m[9] * m[14] +
  3143.       m[4] * m[10] * m[13] +
  3144.       m[8] * m[5] * m[14] -
  3145.       m[8] * m[6] * m[13] -
  3146.       m[12] * m[5] * m[10] +
  3147.       m[12] * m[6] * m[9];
  3148.  
  3149.     inv.m[1] = -m[1] * m[10] * m[15] +
  3150.       m[1] * m[11] * m[14] +
  3151.       m[9] * m[2] * m[15] -
  3152.       m[9] * m[3] * m[14] -
  3153.       m[13] * m[2] * m[11] +
  3154.       m[13] * m[3] * m[10];
  3155.  
  3156.     inv.m[5] = m[0] * m[10] * m[15] -
  3157.       m[0] * m[11] * m[14] -
  3158.       m[8] * m[2] * m[15] +
  3159.       m[8] * m[3] * m[14] +
  3160.       m[12] * m[2] * m[11] -
  3161.       m[12] * m[3] * m[10];
  3162.  
  3163.     inv.m[9] = -m[0] * m[9] * m[15] +
  3164.       m[0] * m[11] * m[13] +
  3165.       m[8] * m[1] * m[15] -
  3166.       m[8] * m[3] * m[13] -
  3167.       m[12] * m[1] * m[11] +
  3168.       m[12] * m[3] * m[9];
  3169.  
  3170.     inv.m[13] = m[0] * m[9] * m[14] -
  3171.       m[0] * m[10] * m[13] -
  3172.       m[8] * m[1] * m[14] +
  3173.       m[8] * m[2] * m[13] +
  3174.       m[12] * m[1] * m[10] -
  3175.       m[12] * m[2] * m[9];
  3176.  
  3177.     inv.m[2] = m[1] * m[6] * m[15] -
  3178.       m[1] * m[7] * m[14] -
  3179.       m[5] * m[2] * m[15] +
  3180.       m[5] * m[3] * m[14] +
  3181.       m[13] * m[2] * m[7] -
  3182.       m[13] * m[3] * m[6];
  3183.  
  3184.     inv.m[6] = -m[0] * m[6] * m[15] +
  3185.       m[0] * m[7] * m[14] +
  3186.       m[4] * m[2] * m[15] -
  3187.       m[4] * m[3] * m[14] -
  3188.       m[12] * m[2] * m[7] +
  3189.       m[12] * m[3] * m[6];
  3190.  
  3191.     inv.m[10] = m[0] * m[5] * m[15] -
  3192.       m[0] * m[7] * m[13] -
  3193.       m[4] * m[1] * m[15] +
  3194.       m[4] * m[3] * m[13] +
  3195.       m[12] * m[1] * m[7] -
  3196.       m[12] * m[3] * m[5];
  3197.  
  3198.     inv.m[14] = -m[0] * m[5] * m[14] +
  3199.       m[0] * m[6] * m[13] +
  3200.       m[4] * m[1] * m[14] -
  3201.       m[4] * m[2] * m[13] -
  3202.       m[12] * m[1] * m[6] +
  3203.       m[12] * m[2] * m[5];
  3204.  
  3205.     inv.m[3] = -m[1] * m[6] * m[11] +
  3206.       m[1] * m[7] * m[10] +
  3207.       m[5] * m[2] * m[11] -
  3208.       m[5] * m[3] * m[10] -
  3209.       m[9] * m[2] * m[7] +
  3210.       m[9] * m[3] * m[6];
  3211.  
  3212.     inv.m[7] = m[0] * m[6] * m[11] -
  3213.       m[0] * m[7] * m[10] -
  3214.       m[4] * m[2] * m[11] +
  3215.       m[4] * m[3] * m[10] +
  3216.       m[8] * m[2] * m[7] -
  3217.       m[8] * m[3] * m[6];
  3218.  
  3219.     inv.m[11] = -m[0] * m[5] * m[11] +
  3220.       m[0] * m[7] * m[9] +
  3221.       m[4] * m[1] * m[11] -
  3222.       m[4] * m[3] * m[9] -
  3223.       m[8] * m[1] * m[7] +
  3224.       m[8] * m[3] * m[5];
  3225.  
  3226.     inv.m[15] = m[0] * m[5] * m[10] -
  3227.       m[0] * m[6] * m[9] -
  3228.       m[4] * m[1] * m[10] +
  3229.       m[4] * m[2] * m[9] +
  3230.       m[8] * m[1] * m[6] -
  3231.       m[8] * m[2] * m[5];
  3232.  
  3233.     const float det = m[0] * inv.m[0] + m[1] * inv.m[4] + m[2] * inv.m[8] + m[3] * inv.m[12];
  3234.     inv /= det;
  3235.     return inv;
  3236.   }
  3237.  
  3238.   //Components
  3239.   float m[16];
  3240. };
  3241.  
  3242. //Debug printing
  3243. inline std::ostream& operator<<(std::ostream& out, const Vector3& v) {
  3244.   out << v.x << ", " << v.y << ", " << v.z;
  3245.   return out;
  3246. }
  3247. inline std::ostream& operator<<(std::ostream& out, const Vector4& v) {
  3248.   out << v.x << ", " << v.y << ", " << v.z << ", " << v.w;
  3249.   return out;
  3250. }
  3251. inline std::ostream& operator<<(std::ostream& out, const Matrix4& m) {
  3252.   out << m.m[0]  << ", " << m.m[1]  << ", " << m.m[2]  << ", " << m.m[3] << "\n";
  3253.   out << m.m[4]  << ", " << m.m[5]  << ", " << m.m[6]  << ", " << m.m[7] << "\n";
  3254.   out << m.m[8]  << ", " << m.m[9]  << ", " << m.m[10] << ", " << m.m[11] << "\n";
  3255.   out << m.m[12] << ", " << m.m[13] << ", " << m.m[14] << ", " << m.m[15];
  3256.   return out;
  3257. }
Add Comment
Please, Sign In to add comment