Advertisement
extremq

Untitled

Nov 1st, 2020
1,168
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.44 KB | None | 0 0
  1. #define OLC_PGE_APPLICATION
  2. #include "olcPixelGameEngine.h"
  3. #include <fstream>
  4. #include <strstream>
  5. #include <algorithm>
  6. #include <iostream>
  7.  
  8. struct vec3d {
  9.     float x = 0.0f;
  10.     float y = 0.0f;
  11.     float z = 0.0f;
  12.     float w = 1.0f;
  13. };
  14.  
  15. struct triangle {
  16.     vec3d p[3];
  17.  
  18.     wchar_t sym;
  19.     short col;
  20. };
  21.  
  22. struct mesh {
  23.     std::vector<triangle> tris;
  24.  
  25.     bool LoadFromObjectFile(std::string sFilename)
  26.     {
  27.         std::ifstream f(sFilename);
  28.         if (!f.is_open())
  29.         {
  30.             return false;
  31.         }
  32.  
  33.         // Local cache of verts
  34.         std::vector<vec3d> verts;
  35.  
  36.         while (!f.eof())
  37.         {
  38.             char line[128];
  39.             f.getline(line, 128);
  40.  
  41.             std::strstream s;
  42.             s << line;
  43.  
  44.             char junk;
  45.  
  46.             if (line[0] == 'v')
  47.             {
  48.                 vec3d v;
  49.                 s >> junk >> v.x >> v.y >> v.z;
  50.                 verts.push_back(v);
  51.             }
  52.  
  53.             if (line[0] == 'f')
  54.             {
  55.                 int f[3];
  56.                 s >> junk >> f[0] >> f[1] >> f[2];
  57.                 tris.push_back({ verts[f[0] - 1], verts[f[1] - 1], verts[f[2] - 1] });
  58.             }
  59.  
  60.         }
  61.  
  62.         return true;
  63.     }
  64. };
  65.  
  66. struct mat4x4 {
  67.     float m[4][4] = { 0 };
  68. };
  69.  
  70. class olcEngine3D : public olc::PixelGameEngine {
  71. public:
  72.     olcEngine3D() {
  73.         sAppName = "3D demo";
  74.     }
  75.  
  76. private:
  77.     mesh meshCube;
  78.     mat4x4 matProj;
  79.  
  80.     vec3d vCamera;
  81.  
  82.     float fTheta = 0.0f;
  83.  
  84.     void MultiplyMatrixVector(vec3d& i, vec3d& o, mat4x4& m) {
  85.         o.x = i.x * m.m[0][0] + i.y * m.m[1][0] + i.z * m.m[2][0] + m.m[3][0];
  86.         o.y = i.x * m.m[0][1] + i.y * m.m[1][1] + i.z * m.m[2][1] + m.m[3][1];
  87.         o.z = i.x * m.m[0][2] + i.y * m.m[1][2] + i.z * m.m[2][2] + m.m[3][2];
  88.         float w = i.x * m.m[0][3] + i.y * m.m[1][3] + i.z * m.m[2][3] + m.m[3][3];
  89.  
  90.         if (w != 0.0f) {
  91.             o.x /= w; o.y /= w; o.z /= w;
  92.         }
  93.     }
  94.  
  95.     vec3d Vector_Add(vec3d& v1, vec3d& v2) {
  96.         return { v1.x + v2.x, v1.y + v2.y, v1.z + v2.z };
  97.     }
  98.  
  99.     vec3d Vector_Sub(vec3d& v1, vec3d& v2) {
  100.         return { v1.x - v2.x, v1.y - v2.y, v1.z - v2.z };
  101.     }
  102.  
  103.     vec3d Vector_Mul(vec3d& v1, float k) {
  104.         return { v1.x * k, v1.y * k, v1.z * k };
  105.     }
  106.  
  107.     vec3d Vector_Div(vec3d& v1, float k) {
  108.         return { v1.x / k, v1.y / k, v1.z / k };
  109.     }
  110.  
  111.     float Vector_DotProduct(vec3d& v1, vec3d& v2) {
  112.         return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
  113.     }
  114.  
  115.     float Vector_Length(vec3d& v1) {
  116.         return sqrt(Vector_DotProduct(v1, v1));
  117.     }
  118.  
  119.     vec3d Vector_Normalise(vec3d& v1) {
  120.         float l = Vector_Length(v1);
  121.         return Vector_Div(v1, l);
  122.     }
  123.  
  124.     vec3d Vector_CrossProduct(vec3d& v1, vec3d& v2) {
  125.         vec3d v;
  126.         v.x = v1.y * v2.z - v1.z * v2.y;
  127.         v.y = v1.z * v2.x - v1.x * v2.z;
  128.         v.z = v1.x * v2.y - v1.y * v2.x;
  129.         return v;
  130.     }
  131.  
  132.     vec3d Matrix_MultiplyVector(mat4x4& m, vec3d& v1) {
  133.         vec3d v;
  134.         v.x = v1.x * m.m[0][0] + v1.y * m.m[1][0] + v1.z * m.m[2][0] + v1.w * m.m[3][0];
  135.         v.y = v1.x * m.m[0][1] + v1.y * m.m[1][1] + v1.z * m.m[2][1] + v1.w * m.m[3][1];
  136.         v.z = v1.x * m.m[0][2] + v1.y * m.m[1][2] + v1.z * m.m[2][2] + v1.w * m.m[3][2];
  137.         v.w = v1.x * m.m[0][3] + v1.y * m.m[1][3] + v1.z * m.m[2][3] + v1.w * m.m[3][3];
  138.         return v;
  139.     }
  140.  
  141.     mat4x4 Matrix_MakeIdentity()
  142.     {
  143.         mat4x4 matrix;
  144.         matrix.m[0][0] = 1.0f;
  145.         matrix.m[1][1] = 1.0f;
  146.         matrix.m[2][2] = 1.0f;
  147.         matrix.m[3][3] = 1.0f;
  148.         return matrix;
  149.     }
  150.  
  151.     mat4x4 Matrix_MakeRotationX(float fAngleRad)
  152.     {
  153.         mat4x4 matrix;
  154.         matrix.m[0][0] = 1.0f;
  155.         matrix.m[1][1] = cosf(fAngleRad);
  156.         matrix.m[1][2] = sinf(fAngleRad);
  157.         matrix.m[2][1] = -sinf(fAngleRad);
  158.         matrix.m[2][2] = cosf(fAngleRad);
  159.         matrix.m[3][3] = 1.0f;
  160.         return matrix;
  161.     }
  162.  
  163.     mat4x4 Matrix_MakeRotationY(float fAngleRad)
  164.     {
  165.         mat4x4 matrix;
  166.         matrix.m[0][0] = cosf(fAngleRad);
  167.         matrix.m[0][2] = sinf(fAngleRad);
  168.         matrix.m[2][0] = -sinf(fAngleRad);
  169.         matrix.m[1][1] = 1.0f;
  170.         matrix.m[2][2] = cosf(fAngleRad);
  171.         matrix.m[3][3] = 1.0f;
  172.         return matrix;
  173.     }
  174.  
  175.     mat4x4 Matrix_MakeRotationZ(float fAngleRad)
  176.     {
  177.         mat4x4 matrix;
  178.         matrix.m[0][0] = cosf(fAngleRad);
  179.         matrix.m[0][1] = sinf(fAngleRad);
  180.         matrix.m[1][0] = -sinf(fAngleRad);
  181.         matrix.m[1][1] = cosf(fAngleRad);
  182.         matrix.m[2][2] = 1.0f;
  183.         matrix.m[3][3] = 1.0f;
  184.         return matrix;
  185.     }
  186.  
  187.     mat4x4 Matrix_MakeTranslation(float x, float y, float z)
  188.     {
  189.         mat4x4 matrix;
  190.         matrix.m[0][0] = 1.0f;
  191.         matrix.m[1][1] = 1.0f;
  192.         matrix.m[2][2] = 1.0f;
  193.         matrix.m[3][3] = 1.0f;
  194.         matrix.m[3][0] = x;
  195.         matrix.m[3][1] = y;
  196.         matrix.m[3][2] = z;
  197.         return matrix;
  198.     }
  199.  
  200.     mat4x4 Matrix_MakeProjection(float fFovDegrees, float fAspectRatio, float fNear, float fFar)
  201.     {
  202.         float fFovRad = 1.0f / tanf(fFovDegrees * 0.5f / 180.0f * 3.14159f);
  203.         mat4x4 matrix;
  204.         matrix.m[0][0] = fAspectRatio * fFovRad;
  205.         matrix.m[1][1] = fFovRad;
  206.         matrix.m[2][2] = fFar / (fFar - fNear);
  207.         matrix.m[3][2] = (-fFar * fNear) / (fFar - fNear);
  208.         matrix.m[2][3] = 1.0f;
  209.         matrix.m[3][3] = 0.0f;
  210.         return matrix;
  211.     }
  212.  
  213.     mat4x4 Matrix_MultiplyMatrix(mat4x4& m1, mat4x4& m2)
  214.     {
  215.         mat4x4 matrix;
  216.         for (int c = 0; c < 4; c++)
  217.             for (int r = 0; r < 4; r++)
  218.                 matrix.m[r][c] = m1.m[r][0] * m2.m[0][c] + m1.m[r][1] * m2.m[1][c] + m1.m[r][2] * m2.m[2][c] + m1.m[r][3] * m2.m[3][c];
  219.         return matrix;
  220.     }
  221.  
  222.     // Taken From Command Line Webcam Video
  223.     /*CHAR_INFO GetColour(float lum)
  224.     {
  225.         short bg_col, fg_col;
  226.         wchar_t sym;
  227.         int pixel_bw = (int)(13.0f * lum);
  228.         switch (pixel_bw)
  229.         {
  230.         case 0: bg_col = BG_BLACK; fg_col = FG_BLACK; sym = PIXEL_SOLID; break;
  231.  
  232.         case 1: bg_col = BG_BLACK; fg_col = FG_DARK_GREY; sym = PIXEL_QUARTER; break;
  233.         case 2: bg_col = BG_BLACK; fg_col = FG_DARK_GREY; sym = PIXEL_HALF; break;
  234.         case 3: bg_col = BG_BLACK; fg_col = FG_DARK_GREY; sym = PIXEL_THREEQUARTERS; break;
  235.         case 4: bg_col = BG_BLACK; fg_col = FG_DARK_GREY; sym = PIXEL_SOLID; break;
  236.  
  237.         case 5: bg_col = BG_DARK_GREY; fg_col = FG_GREY; sym = PIXEL_QUARTER; break;
  238.         case 6: bg_col = BG_DARK_GREY; fg_col = FG_GREY; sym = PIXEL_HALF; break;
  239.         case 7: bg_col = BG_DARK_GREY; fg_col = FG_GREY; sym = PIXEL_THREEQUARTERS; break;
  240.         case 8: bg_col = BG_DARK_GREY; fg_col = FG_GREY; sym = PIXEL_SOLID; break;
  241.  
  242.         case 9:  bg_col = BG_GREY; fg_col = FG_WHITE; sym = PIXEL_QUARTER; break;
  243.         case 10: bg_col = BG_GREY; fg_col = FG_WHITE; sym = PIXEL_HALF; break;
  244.         case 11: bg_col = BG_GREY; fg_col = FG_WHITE; sym = PIXEL_THREEQUARTERS; break;
  245.         case 12: bg_col = BG_GREY; fg_col = FG_WHITE; sym = PIXEL_SOLID; break;
  246.         default:
  247.             bg_col = BG_BLACK; fg_col = FG_BLACK; sym = PIXEL_SOLID;
  248.         }
  249.  
  250.         CHAR_INFO c;
  251.         c.Attributes = bg_col | fg_col;
  252.         c.Char.UnicodeChar = sym;
  253.         return c;
  254.     }*/
  255.  
  256. public:
  257.     bool OnUserCreate() override {
  258.         meshCube.LoadFromObjectFile("C:\\Users\\Stefan\\Documents\\teapot.obj");
  259.  
  260.         matProj = Matrix_MakeProjection(90.0f, (float)ScreenHeight() / (float)ScreenWidth(), 0.1f, 1000.0f);
  261.         return true;
  262.     }
  263.  
  264.     bool OnUserUpdate(float ElapsedTime) override {
  265.         Clear(olc::BLACK);
  266.         //Fill(0, 0, ScreenWidth(), ScreenHeight(), PIXEL_SOLID, FG_BLACK);
  267.  
  268.         // Set up rotation matrices
  269.         mat4x4 matRotZ, matRotX;
  270.         fTheta -= 1.0f * ElapsedTime;
  271.  
  272.         matRotZ = Matrix_MakeRotationZ(fTheta * 0.5f);
  273.         matRotX = Matrix_MakeRotationY(fTheta);
  274.  
  275.         mat4x4 matTrans;
  276.         matTrans = Matrix_MakeTranslation(0.0f, 0.0f, 6.0f);
  277.  
  278.         mat4x4 matWorld;
  279.         matWorld = Matrix_MakeIdentity();
  280.         matWorld = Matrix_MultiplyMatrix(matRotZ, matRotX);
  281.         matWorld = Matrix_MultiplyMatrix(matWorld, matTrans);
  282.  
  283.         // Store triagles for rastering later
  284.         std::vector<triangle> vecTrianglesToRaster;
  285.  
  286.         // draw triangle
  287.         for (auto tri : meshCube.tris) {
  288.             triangle triProjected, triTransformed;
  289.  
  290.             triTransformed.p[0] = Matrix_MultiplyVector(matWorld, tri.p[0]);
  291.             triTransformed.p[1] = Matrix_MultiplyVector(matWorld, tri.p[1]);
  292.             triTransformed.p[2] = Matrix_MultiplyVector(matWorld, tri.p[2]);
  293.  
  294.             vec3d normal, line1, line2;
  295.             line1 = Vector_Sub(triTransformed.p[1], triTransformed.p[0]);
  296.             line2 = Vector_Sub(triTransformed.p[2], triTransformed.p[0]);
  297.  
  298.             normal = Vector_CrossProduct(line1, line2);
  299.             normal = Vector_Normalise(normal);
  300.  
  301.             vec3d vCameraRay = Vector_Sub(triTransformed.p[0], vCamera);
  302.  
  303.             // check dot product
  304.             if (Vector_DotProduct(normal, vCameraRay) < 0.0f) {
  305.  
  306.                 // Illumination
  307.                 vec3d light_direction = { 0.0f, 0.0f, -1.0f };
  308.                 light_direction = Vector_Normalise(light_direction);
  309.                 // How similar is normal to light direction
  310.                 float dp = Vector_DotProduct(light_direction, normal);
  311.  
  312.                 //CHAR_INFO c = GetColour(dp);
  313.                 //triTransformed.col = c.Attributes;
  314.                 //triTransformed.sym = c.Char.UnicodeChar;
  315.  
  316.  
  317.                 // project 3d to 2d triangles
  318.                 triProjected.p[0] = Matrix_MultiplyVector(matProj, triTransformed.p[0]);
  319.                 triProjected.p[1] = Matrix_MultiplyVector(matProj, triTransformed.p[1]);
  320.                 triProjected.p[2] = Matrix_MultiplyVector(matProj, triTransformed.p[2]);
  321.  
  322.                 triProjected.col = triTransformed.col;
  323.                 triProjected.sym = triTransformed.sym;
  324.  
  325.                 triProjected.p[0] = Vector_Div(triProjected.p[0], triProjected.p[0].w);
  326.                 triProjected.p[1] = Vector_Div(triProjected.p[1], triProjected.p[1].w);
  327.                 triProjected.p[2] = Vector_Div(triProjected.p[2], triProjected.p[2].w);
  328.  
  329.                 // Scale into view
  330.                 vec3d vOffsetView = { 1, 1, 0 };
  331.                 triProjected.p[0] = Vector_Add(triProjected.p[0], vOffsetView);
  332.                 triProjected.p[1] = Vector_Add(triProjected.p[1], vOffsetView);
  333.                 triProjected.p[2] = Vector_Add(triProjected.p[2], vOffsetView);
  334.  
  335.                 triProjected.p[0].x *= 0.5f * (float)ScreenWidth();
  336.                 triProjected.p[0].y *= 0.5f * (float)ScreenHeight();
  337.                 triProjected.p[1].x *= 0.5f * (float)ScreenWidth();
  338.                 triProjected.p[1].y *= 0.5f * (float)ScreenHeight();
  339.                 triProjected.p[2].x *= 0.5f * (float)ScreenWidth();
  340.                 triProjected.p[2].y *= 0.5f * (float)ScreenHeight();
  341.  
  342.                 // Store triangle for sorting
  343.                 vecTrianglesToRaster.push_back(triProjected);
  344.             }
  345.  
  346.             // Sort triangles from back to front
  347.             std::sort(vecTrianglesToRaster.begin(), vecTrianglesToRaster.end(), [](triangle& t1, triangle& t2) {
  348.                     float z1 = (t1.p[0].z + t1.p[1].z + t1.p[2].z) / 3.0f;
  349.                     float z2 = (t2.p[0].z + t2.p[1].z + t2.p[2].z) / 3.0f;
  350.                     return z1 > z2;
  351.             });
  352.  
  353.             for (auto& triProjected : vecTrianglesToRaster){
  354.                 // Rasterize triangle
  355.                 FillTriangle(
  356.                     olc::vi2d(triProjected.p[0].x, triProjected.p[0].y),
  357.                     olc::vi2d(triProjected.p[1].x, triProjected.p[1].y),
  358.                     olc::vi2d(triProjected.p[2].x, triProjected.p[2].y));
  359.  
  360.                  // Rasterize triangle
  361.                 /*DrawTriangle(triProjected.p[0].x, triProjected.p[0].y,
  362.                     triProjected.p[1].x, triProjected.p[1].y,
  363.                     triProjected.p[2].x, triProjected.p[2].y,
  364.                     PIXEL_SOLID, FG_WHITE);*/
  365.             }
  366.         }
  367.  
  368.         return true;
  369.     }
  370. };
  371.  
  372.  
  373. int main() {
  374.     olcEngine3D demo;
  375.     if (demo.Construct(256, 240, 2, 2))
  376.         demo.Start();
  377.     return 0;
  378. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement