Results 1 to 2 of 2

Thread: Console Window 3D Engine (C++)

  1. #1

    Thread Starter
    College Grad!!! Jacob Roman's Avatar
    Join Date
    Aug 2004
    Location
    Miami Beach, FL
    Posts
    5,339

    Console Window 3D Engine (C++)

    Who needs DirectX when you can have a simple console window do all the 3D for ya.

    C++ Code:
    1. #define NOMINMAX
    2. #define WIN32_LEAN_AND_MEAN
    3. #include <Windows.h>
    4. #include <iostream>
    5. #include <math.h>
    6. #include <string>
    7. using namespace std;
    8.  
    9. class Vertex
    10. {
    11. public:
    12.     float x;
    13.     float y;
    14.     float z;
    15. };
    16.  
    17. struct CONSOLE_FONT
    18. {
    19.     DWORD index;
    20.     COORD dim;
    21. };
    22.  
    23. enum class COLOR
    24. {
    25.     FG_BLACK = 0x0000,
    26.     FG_DARK_BLUE = 0x0001,
    27.     FG_DARK_GREEN = 0x0002,
    28.     FG_DARK_CYAN = 0x0003,
    29.     FG_DARK_RED = 0x0004,
    30.     FG_DARK_MAGENTA = 0x0005,
    31.     FG_DARK_YELLOW = 0x0006,
    32.     FG_GREY = 0x0007,
    33.     FG_DARK_GREY = 0x0008,
    34.     FG_BLUE = 0x0009,
    35.     FG_GREEN = 0x000A,
    36.     FG_CYAN = 0x000B,
    37.     FG_RED = 0x000C,
    38.     FG_MAGENTA = 0x000D,
    39.     FG_YELLOW = 0x000E,
    40.     FG_WHITE = 0x000F,
    41.     BG_BLACK = 0x0000,
    42.     BG_DARK_BLUE = 0x0010,
    43.     BG_DARK_GREEN = 0x0020,
    44.     BG_DARK_CYAN = 0x0030,
    45.     BG_DARK_RED = 0x0040,
    46.     BG_DARK_MAGENTA = 0x0050,
    47.     BG_DARK_YELLOW = 0x0060,
    48.     BG_GREY = 0x0070,
    49.     BG_DARK_GREY = 0x0080,
    50.     BG_BLUE = 0x0090,
    51.     BG_GREEN = 0x00A0,
    52.     BG_CYAN = 0x00B0,
    53.     BG_RED = 0x00C0,
    54.     BG_MAGENTA = 0x00D0,
    55.     BG_YELLOW = 0x00E0,
    56.     BG_WHITE = 0x00F0,
    57. };
    58.  
    59. void Draw_Text(CHAR_INFO* screen_buffer, string text, float sx, float sy, int character_screen_width, int character_screen_height, COLOR color);
    60. int main();
    61.  
    62. int keystate;
    63. Vertex vertex_list[4];
    64. Vertex temp_list[4];
    65. Vertex local_list[4];
    66. Vertex camera_list[4];
    67. Vertex perspective_list[4];
    68. Vertex screen_list[4];
    69. Vertex angle;
    70. Vertex cam;
    71.  
    72. void Draw_Text(CHAR_INFO* screen_buffer, string text, float sx, float sy, int character_screen_width, int character_screen_height, COLOR color)
    73. {
    74.     if (sx >= character_screen_width - 1) sx = 0.0f;
    75.  
    76.     for (int x = 0; x < static_cast<int>(text.length()); x++)
    77.     {
    78.         if (sx >= 0 && sx < character_screen_width && sy >= 0 && sy < character_screen_height)
    79.         {
    80.             screen_buffer[static_cast<int>(sy) * character_screen_width + static_cast<int>(sx + x)].Char.UnicodeChar = text[x];
    81.             screen_buffer[static_cast<int>(sy) * character_screen_width + static_cast<int>(sx + x)].Attributes = static_cast<WORD>(color);
    82.         }
    83.     }
    84. }
    85.  
    86. void Draw_Bresenham_Line(CHAR_INFO* screen_buffer, int x1, int y1, int x2, int y2, int character_screen_width, int character_screen_height, COLOR color)
    87. {
    88.     int x, y, dx, dy, dx1, dy1, px, py, xe, ye, i;
    89.     dx = x2 - x1;
    90.     dy = y2 - y1;
    91.     dx1 = static_cast<int>(fabs(dx));
    92.     dy1 = static_cast<int>(fabs(dy));
    93.     px = 2 * dy1 - dx1;
    94.     py = 2 * dx1 - dy1;
    95.  
    96.     if (dy1 <= dx1)
    97.     {
    98.         if (dx >= 0)
    99.         {
    100.             x = x1;
    101.             y = y1;
    102.             xe = x2;
    103.         }
    104.         else
    105.         {
    106.             x = x2;
    107.             y = y2;
    108.             xe = x1;
    109.         }
    110.  
    111.         if (x >= 0 && x < character_screen_width && y >= 0 && y < character_screen_height)
    112.         {
    113.             screen_buffer[y * character_screen_width + x].Char.UnicodeChar = ' ';
    114.             screen_buffer[y * character_screen_width + x].Attributes = static_cast<WORD>(color);
    115.         }
    116.  
    117.         for (i = 0; x < xe; i++)
    118.         {
    119.             x = x + 1;
    120.  
    121.             if (px < 0)
    122.             {
    123.                 px = px + 2 * dy1;
    124.             }
    125.             else
    126.             {
    127.                 if ((dx < 0 && dy < 0) || (dx > 0 && dy > 0))
    128.                 {
    129.                     y = y + 1;
    130.                 }
    131.                 else
    132.                 {
    133.                     y = y - 1;
    134.                 }
    135.                 px = px + 2 * (dy1 - dx1);
    136.             }
    137.  
    138.             if (x >= 0 && x < character_screen_width && y >= 0 && y < character_screen_height)
    139.             {
    140.                 screen_buffer[y * character_screen_width + x].Char.UnicodeChar = ' ';
    141.                 screen_buffer[y * character_screen_width + x].Attributes = static_cast<WORD>(color);
    142.             }
    143.         }
    144.     }
    145.     else
    146.     {
    147.         if (dy >= 0)
    148.         {
    149.             x = x1;
    150.             y = y1;
    151.             ye = y2;
    152.         }
    153.         else
    154.         {
    155.             x = x2;
    156.             y = y2;
    157.             ye = y1;
    158.         }
    159.  
    160.         if (x >= 0 && x < character_screen_width && y >= 0 && y < character_screen_height)
    161.         {
    162.             screen_buffer[y * character_screen_width + x].Char.UnicodeChar = ' ';
    163.             screen_buffer[y * character_screen_width + x].Attributes = static_cast<WORD>(color);
    164.         }
    165.  
    166.         for (i = 0; y < ye; i++)
    167.         {
    168.             y = y + 1;
    169.  
    170.             if (py <= 0)
    171.             {
    172.                 py = py + 2 * dx1;
    173.             }
    174.             else
    175.             {
    176.                 if ((dx < 0 && dy < 0) || (dx > 0 && dy > 0))
    177.                 {
    178.                     x = x + 1;
    179.                 }
    180.                 else
    181.                 {
    182.                     x = x - 1;
    183.                 }
    184.                 py = py + 2 * (dx1 - dy1);
    185.             }
    186.  
    187.             if (x >= 0 && x < character_screen_width && y >= 0 && y < character_screen_height)
    188.             {
    189.                 screen_buffer[y * character_screen_width + x].Char.UnicodeChar = ' ';
    190.                 screen_buffer[y * character_screen_width + x].Attributes = static_cast<WORD>(color);
    191.             }
    192.         }
    193.     }
    194. }
    195.  
    196.  
    197. int main()
    198. {
    199.     const float PI = 3.14159265358979f;
    200.     const float RADIAN = PI / 180.0f;
    201.     const float FOV = 90.0f;
    202.  
    203.     vertex_list[0].x = -50.0f; vertex_list[0].y = 50.0f; vertex_list[0].z = 0.0f;
    204.     vertex_list[1].x = 50.0f; vertex_list[1].y = 50.0f; vertex_list[1].z = 0.0f;
    205.     vertex_list[2].x = -50.0f; vertex_list[2].y = -50.0f; vertex_list[2].z = 0.0f;
    206.     vertex_list[3].x = 50.0f; vertex_list[3].y = -50.0f; vertex_list[3].z = 0.0f;
    207.  
    208.     //// Get console font size
    209.     //CONSOLE_FONT fonts = {};
    210.     //fonts.dim = GetConsoleFontSize(console, fonts.index);
    211.     //int fontw = fonts.dim.x;
    212.     //int fonth = fonts.dim.y;
    213.  
    214.     CONSOLE_FONT_INFOEX cfi;
    215.     cfi.cbSize = sizeof(cfi);
    216.     cfi.nFont = 0;
    217.     cfi.dwFontSize.X = 20;
    218.     cfi.dwFontSize.Y = 20;
    219.     cfi.FontFamily = FF_DONTCARE;
    220.     cfi.FontWeight = FW_NORMAL;
    221.  
    222.     int screen_width = 1280;
    223.     int screen_height = 720;
    224.     int character_screen_width = static_cast<int>(floor((screen_width) / (cfi.dwFontSize.X)));
    225.     int character_screen_height = static_cast<int>(floor((screen_height - 39) / (cfi.dwFontSize.Y))) + 1;
    226.  
    227.     HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
    228.  
    229.     CONSOLE_SCREEN_BUFFER_INFO SBInfo;
    230.     COORD NewSBSize;
    231.  
    232.     GetConsoleScreenBufferInfo(console, &SBInfo);
    233.     NewSBSize.X = SBInfo.srWindow.Right - SBInfo.srWindow.Left + 1;
    234.     NewSBSize.Y = SBInfo.srWindow.Bottom - SBInfo.srWindow.Top + 1;
    235.  
    236.     SetConsoleScreenBufferSize(console, NewSBSize);
    237.  
    238.     // Setup Console window
    239.     SMALL_RECT m_rectWindow = { 0, 0, (short)character_screen_width - 1, (short)character_screen_height - 1 };
    240.  
    241.     SetConsoleActiveScreenBuffer(console);
    242.     SetCurrentConsoleFontEx(console, false, &cfi);
    243.  
    244.     // Resize Console window
    245.     RECT r;
    246.     GetWindowRect(GetConsoleWindow(), &r); //stores the console's current dimensions
    247.     MoveWindow(GetConsoleWindow(), r.left, r.top, screen_width, screen_height, TRUE);
    248.  
    249.     // Setup screen buffer
    250.     CHAR_INFO* screen_buffer = new CHAR_INFO[character_screen_width * character_screen_height];
    251.  
    252.     // Make key cursor invisible
    253.     CONSOLE_CURSOR_INFO cursor_info;
    254.     GetConsoleCursorInfo(console, &cursor_info);
    255.     cursor_info.bVisible = false; // set the cursor visibility
    256.     SetConsoleCursorInfo(console, &cursor_info);
    257.  
    258.     // Set key cursor to beginning
    259.     SetConsoleCursorPosition(console, { 0, 0 });
    260.  
    261.     cam.x = 0.0f;
    262.     cam.y = 0.0f;
    263.     cam.z = 400.0f;
    264.  
    265.     while (true)
    266.     {
    267.         angle.x = 0.0f;
    268.         angle.y += 0.1f;
    269.         angle.z = 0.0f;
    270.  
    271.         for (int i = 0; i < 4; i++)
    272.         {
    273.             temp_list[i].x = vertex_list[i].x * (cosf(angle.y * RADIAN) * cosf(angle.z * RADIAN)) + vertex_list[i].y * ((sinf(angle.x * RADIAN) * sinf(angle.y * RADIAN) * cosf(angle.z * RADIAN)) + (cosf(angle.x * RADIAN) * -sinf(angle.z * RADIAN))) + vertex_list[i].z * (cosf(angle.x * RADIAN) * sinf(angle.y * RADIAN) * cosf(angle.z * RADIAN)) + (-sinf(angle.x * RADIAN) * -sinf(angle.z * RADIAN));
    274.             temp_list[i].y = vertex_list[i].x * (cosf(angle.y * RADIAN) * sinf(angle.z * RADIAN)) + vertex_list[i].y * ((sinf(angle.x * RADIAN) * sinf(angle.y * RADIAN) * sinf(angle.z * RADIAN)) + (cosf(angle.x * RADIAN) * cosf(angle.z * RADIAN))) + vertex_list[i].z * (cosf(angle.x * RADIAN) * sinf(angle.y * RADIAN) * sinf(angle.z * RADIAN)) + (-sinf(angle.x * RADIAN) * cosf(angle.z * RADIAN));
    275.             temp_list[i].z = vertex_list[i].x * (-sinf(angle.y * RADIAN)) + vertex_list[i].y * (sinf(angle.x * RADIAN) * cosf(angle.y * RADIAN)) + vertex_list[i].z * (cosf(angle.x * RADIAN) * cosf(angle.y * RADIAN));
    276.  
    277.             local_list[i] = temp_list[i];
    278.  
    279.         }
    280.  
    281.         if (GetAsyncKeyState('W'))
    282.             keystate |= 0x1;
    283.         else
    284.             keystate &= ~0x1;
    285.  
    286.         if (GetAsyncKeyState('S'))
    287.             keystate |= 0x2;
    288.         else
    289.             keystate &= ~0x2;
    290.  
    291.         if (GetAsyncKeyState('A'))
    292.             keystate |= 0x4;
    293.         else
    294.             keystate &= ~0x4;
    295.  
    296.         if (GetAsyncKeyState('D'))
    297.             keystate |= 0x8;
    298.         else
    299.             keystate &= ~0x8;
    300.  
    301.         if (keystate & 0x1) cam.z -= 0.5f;
    302.         if (keystate & 0x2) cam.z += 0.5f;
    303.         if (keystate & 0x4) cam.x -= 0.5f;
    304.         if (keystate & 0x8) cam.x += 0.5f;
    305.  
    306.         wchar_t buffer[256];
    307.         swprintf_s(buffer, 256, L"3D: %f, %f", cam.x, cam.z);
    308.         SetConsoleTitle(buffer);
    309.  
    310.         // Clear screen
    311.         memset(screen_buffer, 0, sizeof(CHAR_INFO) * character_screen_width * character_screen_height);
    312.  
    313.         Draw_Text(screen_buffer, "Press W, S, A, and D keys to move around", 0, 0, character_screen_width, character_screen_height, COLOR::FG_WHITE);
    314.        
    315.         float aspect = 16.0f / 9.0f;
    316.         float distance = tanf(PI * (FOV / 2.0f) / 180.0f);
    317.  
    318.         for (int i = 0; i < 4; i++)
    319.         {
    320.             camera_list[i].x = local_list[i].x + cam.x;
    321.             camera_list[i].y = local_list[i].y + cam.y;
    322.             camera_list[i].z = local_list[i].z + cam.z;
    323.  
    324.             if (camera_list[i].z > 0.0f)
    325.             {
    326.                 perspective_list[i].x = distance * camera_list[i].x / camera_list[i].z;
    327.                 perspective_list[i].y = distance * camera_list[i].y * aspect / camera_list[i].z;
    328.                 perspective_list[i].z = 0.0f;
    329.             }
    330.  
    331.  
    332.             float alpha = 0.5f * character_screen_width - 0.5f;
    333.             float beta = 0.5f * character_screen_height - 0.5f;
    334.  
    335.             screen_list[i].x = alpha + alpha * perspective_list[i].x;
    336.             screen_list[i].y = beta - beta * perspective_list[i].y;
    337.             screen_list[i].z = 0.0f;
    338.         }
    339.  
    340.         Draw_Bresenham_Line(screen_buffer, static_cast<int>(screen_list[0].x), static_cast<int>(screen_list[0].y), static_cast<int>(screen_list[1].x), static_cast<int>(screen_list[1].y), character_screen_width, character_screen_height, COLOR::BG_WHITE);
    341.         Draw_Bresenham_Line(screen_buffer, static_cast<int>(screen_list[1].x), static_cast<int>(screen_list[1].y), static_cast<int>(screen_list[2].x), static_cast<int>(screen_list[2].y), character_screen_width, character_screen_height, COLOR::BG_WHITE);
    342.         Draw_Bresenham_Line(screen_buffer, static_cast<int>(screen_list[2].x), static_cast<int>(screen_list[2].y), static_cast<int>(screen_list[0].x), static_cast<int>(screen_list[0].y), character_screen_width, character_screen_height, COLOR::BG_WHITE);
    343.  
    344.         Draw_Bresenham_Line(screen_buffer, static_cast<int>(screen_list[1].x), static_cast<int>(screen_list[1].y), static_cast<int>(screen_list[2].x), static_cast<int>(screen_list[2].y), character_screen_width, character_screen_height, COLOR::BG_WHITE);
    345.         Draw_Bresenham_Line(screen_buffer, static_cast<int>(screen_list[2].x), static_cast<int>(screen_list[2].y), static_cast<int>(screen_list[3].x), static_cast<int>(screen_list[3].y), character_screen_width, character_screen_height, COLOR::BG_WHITE);
    346.         Draw_Bresenham_Line(screen_buffer, static_cast<int>(screen_list[3].x), static_cast<int>(screen_list[3].y), static_cast<int>(screen_list[1].x), static_cast<int>(screen_list[1].y), character_screen_width, character_screen_height, COLOR::BG_WHITE);
    347.  
    348.         // Draw buffer to Console Window
    349.         WriteConsoleOutput(console, screen_buffer, { (short)character_screen_width, (short)character_screen_height }, { 0,0 }, &m_rectWindow);
    350.     }
    351.  
    352.     return 0;
    353. }

  2. #2
    PowerPoster joaquim's Avatar
    Join Date
    Apr 2007
    Posts
    3,904

    Re: Console Window 3D Engine (C++)

    "Who needs DirectX when you can have a simple console window do all the 3D for ya. "
    endeed
    VB6 2D Sprite control

    To live is difficult, but we do it.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width