Who needs DirectX when you can have a simple console window do all the 3D for ya. :bigyello:
C++ Code:
#define NOMINMAX #define WIN32_LEAN_AND_MEAN #include <Windows.h> #include <iostream> #include <math.h> #include <string> using namespace std; class Vertex { public: float x; float y; float z; }; struct CONSOLE_FONT { DWORD index; COORD dim; }; enum class COLOR { FG_BLACK = 0x0000, FG_DARK_BLUE = 0x0001, FG_DARK_GREEN = 0x0002, FG_DARK_CYAN = 0x0003, FG_DARK_RED = 0x0004, FG_DARK_MAGENTA = 0x0005, FG_DARK_YELLOW = 0x0006, FG_GREY = 0x0007, FG_DARK_GREY = 0x0008, FG_BLUE = 0x0009, FG_GREEN = 0x000A, FG_CYAN = 0x000B, FG_RED = 0x000C, FG_MAGENTA = 0x000D, FG_YELLOW = 0x000E, FG_WHITE = 0x000F, BG_BLACK = 0x0000, BG_DARK_BLUE = 0x0010, BG_DARK_GREEN = 0x0020, BG_DARK_CYAN = 0x0030, BG_DARK_RED = 0x0040, BG_DARK_MAGENTA = 0x0050, BG_DARK_YELLOW = 0x0060, BG_GREY = 0x0070, BG_DARK_GREY = 0x0080, BG_BLUE = 0x0090, BG_GREEN = 0x00A0, BG_CYAN = 0x00B0, BG_RED = 0x00C0, BG_MAGENTA = 0x00D0, BG_YELLOW = 0x00E0, BG_WHITE = 0x00F0, }; void Draw_Text(CHAR_INFO* screen_buffer, string text, float sx, float sy, int character_screen_width, int character_screen_height, COLOR color); int main(); int keystate; Vertex vertex_list[4]; Vertex temp_list[4]; Vertex local_list[4]; Vertex camera_list[4]; Vertex perspective_list[4]; Vertex screen_list[4]; Vertex angle; Vertex cam; void Draw_Text(CHAR_INFO* screen_buffer, string text, float sx, float sy, int character_screen_width, int character_screen_height, COLOR color) { if (sx >= character_screen_width - 1) sx = 0.0f; for (int x = 0; x < static_cast<int>(text.length()); x++) { if (sx >= 0 && sx < character_screen_width && sy >= 0 && sy < character_screen_height) { screen_buffer[static_cast<int>(sy) * character_screen_width + static_cast<int>(sx + x)].Char.UnicodeChar = text[x]; screen_buffer[static_cast<int>(sy) * character_screen_width + static_cast<int>(sx + x)].Attributes = static_cast<WORD>(color); } } } 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) { int x, y, dx, dy, dx1, dy1, px, py, xe, ye, i; dx = x2 - x1; dy = y2 - y1; dx1 = static_cast<int>(fabs(dx)); dy1 = static_cast<int>(fabs(dy)); px = 2 * dy1 - dx1; py = 2 * dx1 - dy1; if (dy1 <= dx1) { if (dx >= 0) { x = x1; y = y1; xe = x2; } else { x = x2; y = y2; xe = x1; } if (x >= 0 && x < character_screen_width && y >= 0 && y < character_screen_height) { screen_buffer[y * character_screen_width + x].Char.UnicodeChar = ' '; screen_buffer[y * character_screen_width + x].Attributes = static_cast<WORD>(color); } for (i = 0; x < xe; i++) { x = x + 1; if (px < 0) { px = px + 2 * dy1; } else { if ((dx < 0 && dy < 0) || (dx > 0 && dy > 0)) { y = y + 1; } else { y = y - 1; } px = px + 2 * (dy1 - dx1); } if (x >= 0 && x < character_screen_width && y >= 0 && y < character_screen_height) { screen_buffer[y * character_screen_width + x].Char.UnicodeChar = ' '; screen_buffer[y * character_screen_width + x].Attributes = static_cast<WORD>(color); } } } else { if (dy >= 0) { x = x1; y = y1; ye = y2; } else { x = x2; y = y2; ye = y1; } if (x >= 0 && x < character_screen_width && y >= 0 && y < character_screen_height) { screen_buffer[y * character_screen_width + x].Char.UnicodeChar = ' '; screen_buffer[y * character_screen_width + x].Attributes = static_cast<WORD>(color); } for (i = 0; y < ye; i++) { y = y + 1; if (py <= 0) { py = py + 2 * dx1; } else { if ((dx < 0 && dy < 0) || (dx > 0 && dy > 0)) { x = x + 1; } else { x = x - 1; } py = py + 2 * (dx1 - dy1); } if (x >= 0 && x < character_screen_width && y >= 0 && y < character_screen_height) { screen_buffer[y * character_screen_width + x].Char.UnicodeChar = ' '; screen_buffer[y * character_screen_width + x].Attributes = static_cast<WORD>(color); } } } } int main() { const float PI = 3.14159265358979f; const float RADIAN = PI / 180.0f; const float FOV = 90.0f; vertex_list[0].x = -50.0f; vertex_list[0].y = 50.0f; vertex_list[0].z = 0.0f; vertex_list[1].x = 50.0f; vertex_list[1].y = 50.0f; vertex_list[1].z = 0.0f; vertex_list[2].x = -50.0f; vertex_list[2].y = -50.0f; vertex_list[2].z = 0.0f; vertex_list[3].x = 50.0f; vertex_list[3].y = -50.0f; vertex_list[3].z = 0.0f; //// Get console font size //CONSOLE_FONT fonts = {}; //fonts.dim = GetConsoleFontSize(console, fonts.index); //int fontw = fonts.dim.x; //int fonth = fonts.dim.y; CONSOLE_FONT_INFOEX cfi; cfi.cbSize = sizeof(cfi); cfi.nFont = 0; cfi.dwFontSize.X = 20; cfi.dwFontSize.Y = 20; cfi.FontFamily = FF_DONTCARE; cfi.FontWeight = FW_NORMAL; int screen_width = 1280; int screen_height = 720; int character_screen_width = static_cast<int>(floor((screen_width) / (cfi.dwFontSize.X))); int character_screen_height = static_cast<int>(floor((screen_height - 39) / (cfi.dwFontSize.Y))) + 1; HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_SCREEN_BUFFER_INFO SBInfo; COORD NewSBSize; GetConsoleScreenBufferInfo(console, &SBInfo); NewSBSize.X = SBInfo.srWindow.Right - SBInfo.srWindow.Left + 1; NewSBSize.Y = SBInfo.srWindow.Bottom - SBInfo.srWindow.Top + 1; SetConsoleScreenBufferSize(console, NewSBSize); // Setup Console window SMALL_RECT m_rectWindow = { 0, 0, (short)character_screen_width - 1, (short)character_screen_height - 1 }; SetConsoleActiveScreenBuffer(console); SetCurrentConsoleFontEx(console, false, &cfi); // Resize Console window RECT r; GetWindowRect(GetConsoleWindow(), &r); //stores the console's current dimensions MoveWindow(GetConsoleWindow(), r.left, r.top, screen_width, screen_height, TRUE); // Setup screen buffer CHAR_INFO* screen_buffer = new CHAR_INFO[character_screen_width * character_screen_height]; // Make key cursor invisible CONSOLE_CURSOR_INFO cursor_info; GetConsoleCursorInfo(console, &cursor_info); cursor_info.bVisible = false; // set the cursor visibility SetConsoleCursorInfo(console, &cursor_info); // Set key cursor to beginning SetConsoleCursorPosition(console, { 0, 0 }); cam.x = 0.0f; cam.y = 0.0f; cam.z = 400.0f; while (true) { angle.x = 0.0f; angle.y += 0.1f; angle.z = 0.0f; for (int i = 0; i < 4; i++) { 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)); 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)); 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)); local_list[i] = temp_list[i]; } if (GetAsyncKeyState('W')) keystate |= 0x1; else keystate &= ~0x1; if (GetAsyncKeyState('S')) keystate |= 0x2; else keystate &= ~0x2; if (GetAsyncKeyState('A')) keystate |= 0x4; else keystate &= ~0x4; if (GetAsyncKeyState('D')) keystate |= 0x8; else keystate &= ~0x8; if (keystate & 0x1) cam.z -= 0.5f; if (keystate & 0x2) cam.z += 0.5f; if (keystate & 0x4) cam.x -= 0.5f; if (keystate & 0x8) cam.x += 0.5f; wchar_t buffer[256]; swprintf_s(buffer, 256, L"3D: %f, %f", cam.x, cam.z); SetConsoleTitle(buffer); // Clear screen memset(screen_buffer, 0, sizeof(CHAR_INFO) * character_screen_width * character_screen_height); 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); float aspect = 16.0f / 9.0f; float distance = tanf(PI * (FOV / 2.0f) / 180.0f); for (int i = 0; i < 4; i++) { camera_list[i].x = local_list[i].x + cam.x; camera_list[i].y = local_list[i].y + cam.y; camera_list[i].z = local_list[i].z + cam.z; if (camera_list[i].z > 0.0f) { perspective_list[i].x = distance * camera_list[i].x / camera_list[i].z; perspective_list[i].y = distance * camera_list[i].y * aspect / camera_list[i].z; perspective_list[i].z = 0.0f; } float alpha = 0.5f * character_screen_width - 0.5f; float beta = 0.5f * character_screen_height - 0.5f; screen_list[i].x = alpha + alpha * perspective_list[i].x; screen_list[i].y = beta - beta * perspective_list[i].y; screen_list[i].z = 0.0f; } 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); 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); 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); 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); 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); 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); // Draw buffer to Console Window WriteConsoleOutput(console, screen_buffer, { (short)character_screen_width, (short)character_screen_height }, { 0,0 }, &m_rectWindow); } return 0; }