4#if defined(MXVK_USE_EIGEN_MATH)
29 using SurfacePtr = std::unique_ptr<SDL_Surface, SurfaceDeleter>;
34 throw mxvk::Exception(std::format(
"Failed to create 3dmath frame surface: {}", SDL_GetError()));
46 frame_width(framebuffer.width),
47 frame_height(framebuffer.height),
48 fallback_width(width),
49 fallback_height(height) {
54 void event(SDL_Event &e)
override {
55 if (e.type == SDL_EVENT_KEY_DOWN && e.key.key == SDLK_ESCAPE) {
65 if (frame_sprite ==
nullptr || frame_surface ==
nullptr || frame_format ==
nullptr) {
70 const float time =
static_cast<float>(SDL_GetTicks()) * 0.001f;
73 {-0.75f, -0.45f, 2.6f, 1.0f},
74 {0.75f, -0.45f, 2.6f, 1.0f},
75 {0.0f, 0.75f, 2.6f, 1.0f},
79 rotation.
BuildXYZ(25.0f, time * 42.0f, time * 18.0f);
85 for (
int i = 0; i < 3; ++i) {
86 triangle.
vlist[i] = vertices[i];
88 triangle.
tlist[i].
z += 3.0f;
92 project_to_screen(render_list, frame_width, frame_height);
94 const int pixel_size = std::max(1, frame_width / 360);
96 pipeline.
Begin(frame_width, frame_height, [
this, pixel_size](
int x,
int y,
mxvk::MXCOLOR color) {
97 put_block(x, y, pixel_size, color);
102 frame_sprite->updateTexture(frame_surface.get());
103 frame_sprite->drawSpriteRect(0, 0, output_width, output_height);
107 SurfacePtr frame_surface;
108 const SDL_PixelFormatDetails *frame_format =
nullptr;
110 int frame_width = 1280;
111 int frame_height = 720;
112 int fallback_width = 1280;
113 int fallback_height = 720;
115 void ensure_framebuffer() {
116 if (frame_surface !=
nullptr) {
120 frame_surface = create_frame_surface(frame_width, frame_height);
121 frame_format = SDL_GetPixelFormatDetails(frame_surface->format);
122 if (frame_format ==
nullptr) {
123 throw mxvk::Exception(std::format(
"Failed to query 3dmath frame format: {}", SDL_GetError()));
128 frame_sprite->setTextureFilter(VK_FILTER_NEAREST);
131 [[nodiscard]] std::uint32_t map_color(
mxvk::MXCOLOR color)
const {
136 SDL_FillSurfaceRect(frame_surface.get(),
nullptr, map_color(color));
140 if (x < 0 || y < 0 || x >= frame_width || y >= frame_height) {
144 auto *row =
static_cast<std::uint8_t *
>(frame_surface->pixels) + (
static_cast<std::size_t
>(y) *
static_cast<std::size_t
>(frame_surface->pitch));
145 auto *pixel =
reinterpret_cast<std::uint32_t *
>(row) + x;
146 *pixel = map_color(color);
149 void put_block(
int x,
int y,
int size,
mxvk::MXCOLOR color) {
150 for (
int block_y = 0; block_y < size; ++block_y) {
151 for (
int block_x = 0; block_x < size; ++block_x) {
152 put_pixel(x + block_x, y + block_y, color);
157 static void project_to_screen(mxvk::RenderList &render_list,
int width,
int height) {
158 const float scale =
static_cast<float>(std::min(width, height)) * 0.42f;
159 const float center_x =
static_cast<float>(width) * 0.5f;
160 const float center_y =
static_cast<float>(height) * 0.5f;
162 for (
auto &poly : render_list.
polys) {
163 for (
auto &vertex : poly.tlist) {
164 const float z = std::max(vertex.z, 0.001f);
165 vertex.x = center_x + (vertex.x / z) * scale;
166 vertex.y = center_y - (vertex.y / z) * scale;
173int main(
int argc,
char **argv) {
179 std::cerr << std::format(
"mxvk: Exception: {}\n", e.
text());
182 std::cerr << std::format(
"mxvk: Argument Exception: {}\n", e.
text());
Lightweight, header-only, template command-line argument parser.
Arguments proc_args(int &argc, char **argv)
Parse standard libmx2 command-line options from main()'s argv.
Exception thrown by Argz::proc() on unrecognised or malformed options.
void operator()(SDL_Surface *surface) const
void event(SDL_Event &e) override
Handle one SDL event.
void proc() override
Execute one processing/update step.
Math3DWindow(const std::string &, const std::string &title, int width, int height, bool fullscreen, bool enable_vsync, const FramebufferDimensions &framebuffer)
Four-by-four homogeneous transform matrix.
void BuildXYZ(float theta_x, float theta_y, float theta_z)
Build an XYZ Euler rotation matrix from angles in degrees.
vec4D MulVec(const vec4D &in) const
Transform a homogeneous 4D vector by this matrix.
Clipped software rasterization pipeline for lines and filled triangles.
void End()
End rendering and release the current plotting callbacks.
void DrawPolys(const RenderList &list) const
Draw active render-list triangles as clipped wireframes.
void Begin(int width, int height, std::function< void(int, int, MXCOLOR)> plotter)
Begin rendering with a custom pixel plotter.
Flat list of triangles prepared for transformation and rasterization.
std::vector< Triangle > polys
Triangle storage.
void BuildRenderList(const Triangle &triangle)
Append one triangle to the render list.
Main Vulkan window wrapper for MXVK.
void loop()
Run the main event/render loop.
VK_Sprite * createSprite(const std::string &pngPath, const std::string &vertexShaderPath="", const std::string &fragmentShaderPath="")
Create a sprite from a PNG file and register it with this window.
VkExtent2D swapchain_extent
void setClearColor(float r, float g, float b, float a=1.0f)
Set the per-frame color attachment clear color.
void exit()
Request loop termination.
VK_Window()=default
Construct an empty window object.
Four-dimensional float vector used for homogeneous 3D coordinates.
Math, geometry, rasterization, and simple software 3D pipeline helpers for MXVK examples.
std::unique_ptr< SDL_Surface, SurfaceDeleter > SurfacePtr
SurfacePtr create_frame_surface(int width, int height)
Utilities for loading and saving PNG images.
constexpr std::uint8_t color_r(MXCOLOR color)
Extract the red component from a packed ARGB color.
std::uint32_t MXCOLOR
Packed 32-bit color in ARGB byte order.
void BuildTables()
Rebuild the sine and cosine lookup tables.
constexpr std::uint8_t color_g(MXCOLOR color)
Extract the green component from a packed ARGB color.
constexpr MXCOLOR MXVK_RGB(int r, int g, int b)
Build an opaque ARGB color from red, green, and blue components.
constexpr std::uint8_t color_a(MXCOLOR color)
Extract the alpha component from a packed ARGB color.
@ MX_ACTIVE
Active object or polygon.
@ MX_VISIBLE
Visible object or polygon.
constexpr std::uint8_t color_b(MXCOLOR color)
Extract the blue component from a packed ARGB color.
Plain data structure returned by proc_args() with all common libmx2 CLI options.
FramebufferDimensions framebuffer
Software framebuffer size requested by --framebuffer.
bool fullscreen
Whether fullscreen mode was requested.
bool enable_vsync
Enable FIFO present mode / v-sync (--enable-vsync).
int height
Viewport height in pixels (default: 720).
std::string path
Asset root; proc_args() defaults it to the executable directory.
int width
Viewport width in pixels (default: 1280).
Parsed software framebuffer dimensions.
Triangle primitive used by the simple software rendering pipeline.
vec4D tlist[3]
Transformed vertex positions.
MXCOLOR color
Triangle color.
int state
Polygon state flags.
vec4D vlist[3]
Working vertex positions.