Created
April 7, 2020 12:14
-
-
Save bit-hack/557d9e5d7d55bc232a93fa6b954270bc to your computer and use it in GitHub Desktop.
Quick and dirty triangle geometry drawing tool
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <cassert> | |
| #include <cstdint> | |
| #include <cmath> | |
| #include <algorithm> | |
| #include <array> | |
| #define _SDL_main_h | |
| #include <SDL/SDL.h> | |
| struct app_t { | |
| app_t() | |
| : _screen(nullptr) | |
| , _active(false) | |
| , _width(0) | |
| , _height(0) | |
| , _color(0xffffff) | |
| { | |
| } | |
| // quick and dirty circle plotter (i know its ugly) | |
| void circle(float x, float y, float r) { | |
| const float pi = 3.14159265359f; | |
| const float circ = 2.f * r * pi; | |
| const float step = (2.f * pi) / circ; | |
| for (float a = 0.f; a < 2.f*pi; a += step) { | |
| float px = sinf(a) * r; | |
| float py = cosf(a) * r; | |
| plot(x + px, y + py); | |
| } | |
| } | |
| // quick and dirty line plotter (i know its also ugly) | |
| void line(float x0, float y0, float x1, float y1) { | |
| const float step = 1.f / std::max(std::abs(x1-x0), | |
| std::abs(y1-y0)); | |
| if (step > 0.f) { | |
| for (float i = 0.f; i <= 1.f; i += step) { | |
| const float x = x0 + (x1 - x0) * i; | |
| const float y = y0 + (y1 - y0) * i; | |
| plot(x, y); | |
| } | |
| } | |
| } | |
| // quick and dirty point plotter (you get the idea) | |
| void plot(float x, float y) { | |
| const int32_t ix = int32_t(x); | |
| const int32_t iy = int32_t(y); | |
| if (ix >= 0 && iy >= 0 && ix < _width && iy < _height) { | |
| uint32_t *pix = (uint32_t*)_screen->pixels; | |
| pix[ ix + iy * _width ] = _color; | |
| } | |
| } | |
| virtual bool init(uint32_t w, uint32_t h) { | |
| const uint32_t mode = SDL_INIT_VIDEO; | |
| if (SDL_WasInit(mode)) { | |
| return false; | |
| } | |
| if (SDL_Init(mode)) { | |
| return false; | |
| } | |
| assert(!_screen); | |
| _screen = SDL_SetVideoMode(w, h, 32, 0); | |
| if (!_screen) { | |
| return false; | |
| } | |
| _active = true; | |
| _width = w; | |
| _height = h; | |
| return true; | |
| } | |
| virtual void on_event(const SDL_Event &event) { | |
| switch (event.type) { | |
| case SDL_QUIT: | |
| _active = false; | |
| break; | |
| } | |
| } | |
| virtual void tick() { | |
| SDL_Event event; | |
| while (SDL_PollEvent(&event)) { | |
| on_event(event); | |
| } | |
| } | |
| bool active() const { | |
| return _active; | |
| } | |
| protected: | |
| SDL_Surface *_screen; | |
| bool _active; | |
| int32_t _width, _height; | |
| uint32_t _color; | |
| }; | |
| struct my_app_t : public app_t { | |
| std::array<float, 3> point_x; | |
| std::array<float, 3> point_y; | |
| int point_picked; | |
| my_app_t() | |
| : point_x({179, 249, 51}) | |
| , point_y({34, 191, 143}) | |
| , point_picked(-1) { | |
| } | |
| void on_event(const SDL_Event &event) override { | |
| switch (event.type) { | |
| case SDL_MOUSEBUTTONDOWN: { | |
| float mx = event.button.x; | |
| float my = event.button.y; | |
| point_picked = -1; | |
| float dist = 32 * 32; | |
| for (int i = 0; i < 3; ++i) { | |
| float dx = (mx - point_x[i]); | |
| float dy = (my - point_y[i]); | |
| float ndist = dx * dx + dy * dy; | |
| if (ndist < dist) { | |
| point_picked = i; | |
| dist = ndist; | |
| } | |
| } | |
| } break; | |
| case SDL_MOUSEBUTTONUP: | |
| point_picked = -1; | |
| break; | |
| case SDL_MOUSEMOTION: | |
| if (point_picked >= 0) { | |
| point_x[point_picked] = event.motion.x; | |
| point_y[point_picked] = event.motion.y; | |
| } | |
| break; | |
| } | |
| // main handler | |
| app_t::on_event(event); | |
| } | |
| void tick() override { | |
| app_t::tick(); | |
| // clear the screen | |
| SDL_FillRect(_screen, nullptr, 0x202020); | |
| // draw control handles | |
| for (int i = 0; i < 3; ++i) { | |
| switch (i) { | |
| case 0: _color = 0xFF0000; break; | |
| case 1: _color = 0x00FF00; break; | |
| case 2: _color = 0x0000FF; break; | |
| } | |
| circle(point_x[i], point_y[i], 7.5); | |
| } | |
| // draw triangle outline | |
| _color = (-1 != point_picked) ? 0xd0d0d0 : 0x909090; | |
| line(point_x[0], point_y[0], point_x[1], point_y[1]); | |
| line(point_x[1], point_y[1], point_x[2], point_y[2]); | |
| line(point_x[2], point_y[2], point_x[0], point_y[0]); | |
| // present to the screen | |
| SDL_Delay(1); | |
| SDL_Flip(_screen); | |
| } | |
| }; | |
| int main(int argc, const char **args) { | |
| my_app_t app; | |
| if (!app.init(320, 240)) { | |
| return 1; | |
| } | |
| while (app.active()) { | |
| app.tick(); | |
| } | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment