From ac2a6000bcf1592c74c4ed34bf38b67880edda11 Mon Sep 17 00:00:00 2001 From: Relintai Date: Mon, 29 Mar 2021 21:24:15 +0200 Subject: [PATCH] Initial sdl renderer class implementation (for software mode). --- 05_sdl_alapok/.clang-format | 128 +++++++++++++++++++++++++++++ 05_sdl_alapok/compile.sh | 23 ++++++ 05_sdl_alapok/main.cpp | 43 ++++++++++ 05_sdl_alapok/math.cpp | 72 +++++++++++++++++ 05_sdl_alapok/math.h | 89 ++++++++++++++++++++ 05_sdl_alapok/rect2.cpp | 156 ++++++++++++++++++++++++++++++++++++ 05_sdl_alapok/rect2.h | 37 +++++++++ 05_sdl_alapok/renderer.cpp | 95 ++++++++++++++++++++++ 05_sdl_alapok/renderer.h | 35 ++++++++ 9 files changed, 678 insertions(+) create mode 100755 05_sdl_alapok/.clang-format create mode 100755 05_sdl_alapok/compile.sh create mode 100644 05_sdl_alapok/main.cpp create mode 100644 05_sdl_alapok/math.cpp create mode 100644 05_sdl_alapok/math.h create mode 100644 05_sdl_alapok/rect2.cpp create mode 100644 05_sdl_alapok/rect2.h create mode 100644 05_sdl_alapok/renderer.cpp create mode 100644 05_sdl_alapok/renderer.h diff --git a/05_sdl_alapok/.clang-format b/05_sdl_alapok/.clang-format new file mode 100755 index 0000000..cb67d39 --- /dev/null +++ b/05_sdl_alapok/.clang-format @@ -0,0 +1,128 @@ +# Commented out parameters are those with the same value as base LLVM style +# We can uncomment them if we want to change their value, or enforce the +# chosen value in case the base style changes (last sync: Clang 6.0.1). +--- +### General config, applies to all languages ### +BasedOnStyle: LLVM +AccessModifierOffset: -4 +AlignAfterOpenBracket: DontAlign +# AlignConsecutiveAssignments: false +# AlignConsecutiveDeclarations: false +# AlignEscapedNewlines: Right +# AlignOperands: true +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: false +# AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: true +# AllowShortLoopsOnASingleLine: false +# AlwaysBreakAfterDefinitionReturnType: None +# AlwaysBreakAfterReturnType: None +# AlwaysBreakBeforeMultilineStrings: false +# AlwaysBreakTemplateDeclarations: false +# BinPackArguments: true +# BinPackParameters: true +# BraceWrapping: +# AfterClass: false +# AfterControlStatement: false +# AfterEnum: false +# AfterFunction: false +# AfterNamespace: false +# AfterObjCDeclaration: false +# AfterStruct: false +# AfterUnion: false +# AfterExternBlock: false +# BeforeCatch: false +# BeforeElse: false +# IndentBraces: false +# SplitEmptyFunction: true +# SplitEmptyRecord: true +# SplitEmptyNamespace: true +# BreakBeforeBinaryOperators: None +# BreakBeforeBraces: Attach +# BreakBeforeInheritanceComma: false +BreakBeforeTernaryOperators: false +# BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: AfterColon +# BreakStringLiterals: true +ColumnLimit: 0 +# CommentPragmas: '^ IWYU pragma:' +# CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 8 +ContinuationIndentWidth: 8 +Cpp11BracedListStyle: false +# DerivePointerAlignment: false +# DisableFormat: false +# ExperimentalAutoDetectBinPacking: false +# FixNamespaceComments: true +# ForEachMacros: +# - foreach +# - Q_FOREACH +# - BOOST_FOREACH +# IncludeBlocks: Preserve +IncludeCategories: + - Regex: '".*"' + Priority: 1 + - Regex: '^<.*\.h>' + Priority: 2 + - Regex: '^<.*' + Priority: 3 +# IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: true +# IndentPPDirectives: None +IndentWidth: 4 +# IndentWrappedFunctionNames: false +# JavaScriptQuotes: Leave +# JavaScriptWrapImports: true +# KeepEmptyLinesAtTheStartOfBlocks: true +# MacroBlockBegin: '' +# MacroBlockEnd: '' +# MaxEmptyLinesToKeep: 1 +# NamespaceIndentation: None +# PenaltyBreakAssignment: 2 +# PenaltyBreakBeforeFirstCallParameter: 19 +# PenaltyBreakComment: 300 +# PenaltyBreakFirstLessLess: 120 +# PenaltyBreakString: 1000 +# PenaltyExcessCharacter: 1000000 +# PenaltyReturnTypeOnItsOwnLine: 60 +# PointerAlignment: Right +# RawStringFormats: +# - Delimiter: pb +# Language: TextProto +# BasedOnStyle: google +# ReflowComments: true +# SortIncludes: true +# SortUsingDeclarations: true +# SpaceAfterCStyleCast: false +# SpaceAfterTemplateKeyword: true +# SpaceBeforeAssignmentOperators: true +# SpaceBeforeParens: ControlStatements +# SpaceInEmptyParentheses: false +# SpacesBeforeTrailingComments: 1 +# SpacesInAngles: false +# SpacesInContainerLiterals: true +# SpacesInCStyleCastParentheses: false +# SpacesInParentheses: false +# SpacesInSquareBrackets: false +TabWidth: 4 +UseTab: Always +--- +### C++ specific config ### +Language: Cpp +Standard: Cpp03 +--- +### ObjC specific config ### +Language: ObjC +Standard: Cpp03 +ObjCBlockIndentWidth: 4 +# ObjCSpaceAfterProperty: false +# ObjCSpaceBeforeProtocolList: true +--- +### Java specific config ### +Language: Java +# BreakAfterJavaFieldAnnotations: false +JavaImportGroups: ['org.godotengine', 'android', 'androidx', 'com.android', 'com.google', 'java', 'javax'] +... diff --git a/05_sdl_alapok/compile.sh b/05_sdl_alapok/compile.sh new file mode 100755 index 0000000..067b5e9 --- /dev/null +++ b/05_sdl_alapok/compile.sh @@ -0,0 +1,23 @@ + +if [ ! -d "obj" ]; then + mkdir obj +fi + +if [ ! -d "bin" ]; then + mkdir bin +fi + +#-Iinclude + +#g++ -Wall -g -c vector2.cpp -o obj/vector2.o +#g++ -Wall -g -c vector3.cpp -o obj/vector3.o +#g++ -Wall -g -c int_vector.cpp -o obj/int_vector.o +#g++ -Wall -g -c string.cpp -o obj/string.o + +g++ -Wall -g -c math.cpp -o obj/math.o +g++ -Wall -g -c rect2.cpp -o obj/rect2.o +g++ -Wall -g $(sdl2-config --cflags) -c renderer.cpp -o obj/renderer.o +g++ -Wall -g $(sdl2-config --cflags) -c main.cpp -o obj/main.o + +g++ -o bin/program obj/math.o obj/rect2.o obj/renderer.o obj/main.o $(sdl2-config --libs) + diff --git a/05_sdl_alapok/main.cpp b/05_sdl_alapok/main.cpp new file mode 100644 index 0000000..9c4e7f6 --- /dev/null +++ b/05_sdl_alapok/main.cpp @@ -0,0 +1,43 @@ +#include + +#include "renderer.h" + + + +int main(int argv, char** args) { + Renderer r; + + r.set_draw_color(0, 0, 0, 255); + r.clear(); + r.present(); + + int rgb[] = { 203, 203, 203, // Gray + 254, 254, 31, // Yellow + 0, 255, 255, // Cyan + 0, 254, 30, // Green + 255, 16, 253, // Magenta + 253, 3, 2, // Red + 18, 14, 252, // Blue + 0, 0, 0 // Black + }; + + SDL_Rect colorBar; + colorBar.x = 0; + colorBar.y = 0; + colorBar.w = 90; + colorBar.h = 480; + + // Render a new color bar every 0.5 seconds + for ( int i = 0; i != sizeof rgb / sizeof *rgb; i += 3, colorBar.x += 90) + { + r.set_draw_color(rgb[i], rgb[i + 1], rgb[i + 2], 255); + r.draw_rect(colorBar); + r.present(); + + SDL_Delay(500); + } + + r.destroy(); + + SDL_Quit(); +} diff --git a/05_sdl_alapok/math.cpp b/05_sdl_alapok/math.cpp new file mode 100644 index 0000000..9bb5581 --- /dev/null +++ b/05_sdl_alapok/math.cpp @@ -0,0 +1,72 @@ +#include "math.h" + +float Math::inv_sqrt(const float x) { + return (float)(1.0 / ::sqrtf(x)); +} + +float Math::fast_inv_sqrt(const float number) { + long i; + float x2, y; + const float threehalfs = 1.5F; + + x2 = number * 0.5F; + y = number; + i = *(long *)&y; + i = 0x5f3759df - (i >> 1); + y = *(float *)&i; + y = y * (threehalfs - (x2 * y * y)); + + return y; +} + +float Math::is_equal_approx(const float a, const float b) { + if (a + EPSILON < b && a - EPSILON > b) { + return true; + } + + return false; +} + +float Math::is_zero_approx(const float a) { + if (a + EPSILON < 0 && a - EPSILON > 0) { + return true; + } + + return false; +} + +void Math::seed(const unsigned int s) { + srand(s); +} + +void Math::randomize() { + srand(time(NULL)); +} + +int Math::rand() { + return ::rand(); +} + +float Math::randf() { + return ::rand() / static_cast(RANDOM_32BIT_MAX); +} + +double Math::randd() { + return ::rand() / static_cast(RANDOM_32BIT_MAX); +} + +int Math::rand(const int m) { + return rand() % m; +} + +int Math::rand(const int from, const int to) { + return (rand() % (to - from)) + from; +} + +float Math::rand(const float from, const float to) { + return randf() * (to - from) + from; +} + +float Math::rand(const double from, const double to) { + return randd() * (to - from) + from; +} diff --git a/05_sdl_alapok/math.h b/05_sdl_alapok/math.h new file mode 100644 index 0000000..cd5fb8f --- /dev/null +++ b/05_sdl_alapok/math.h @@ -0,0 +1,89 @@ +#ifndef MATH_H +#define MATH_H + +#include +#include +#include +#include + +#define MATH_PI 3.1415926535897932384626433833 +#define EPSILON 0.00001 + +class Math { +public: + + static const uint64_t RANDOM_32BIT_MAX = 0xFFFFFFFF; + + inline static float sin(const float x) { return ::sinf(x); } + inline static double sin(const double x) { return ::sin(x); } + + inline static float cos(const float x) { return ::cosf(x); } + inline static double cos(const double x) { return ::cos(x); } + + inline static float tan(const float x) { return ::tanf(x); } + inline static double tan(const double x) { return ::tan(x); } + + inline static float asin(const float x) { return ::asinf(x); } + inline static double asin(const double x) { return ::asin(x); } + + inline static float acos(const float x) { return ::acosf(x); } + inline static double acos(const double x) { return ::acos(x); } + + inline static float atan(const float x) { return ::atanf(x); } + inline static double atan(const double x) { return ::atan(x); } + + inline static float atan2(const float x, const float y) { return ::atan2f(x, y); } + inline static double atan2(const double x, const float y) { return ::atan2(x, y); } + + inline static float sqrt(const float x) { return ::sqrtf(x); } + inline static double sqrt(const double x) { return ::sqrt(x); } + + inline static float fmod(const float x, const float y) { return ::fmodf(x, y); } + inline static double fmod(const double x, const float y) { return ::fmod(x, y); } + + inline static float floor(const float x) { return ::floorf(x); } + inline static double floor(const double x) { return ::floor(x); } + + inline static float ceil(const float x) { return ::ceilf(x); } + inline static double ceil(const double x) { return ::ceil(x); } + + inline static float pow(const float x, const float y) { return ::powf(x, y); } + inline static double pow(const double x, const float y) { return ::pow(x, y); } + + inline static float log(const float x) { return ::logf(x); } + inline static double log(const double x) { return ::log(x); } + + static float inv_sqrt(const float x); + static float fast_inv_sqrt(const float x); + + inline static float abs(const float x) { return x > 0 ? x : -x; } + inline static double abs(const double x) { return x > 0 ? x : -x; } + inline static int abs(const int x) { return x > 0 ? x : -x; } + + inline static float deg2rad(const float x) { return x * MATH_PI / 180.0; } + inline static double deg2rad(const double x) { return x * MATH_PI / 180.0; } + inline static int deg2rad(const int x) { return x * MATH_PI / 180.0; } + + inline static float rad2deg(const float x) { return x * 180.0 / MATH_PI; } + inline static double rad2deg(const double x) { return x * 180.0 / MATH_PI; } + inline static int rad2deg(const int x) { return x * 180.0 / MATH_PI; } + + static float is_equal_approx(const float a, const float b); + static float is_zero_approx(const float a); + + static void seed(const unsigned int s); + static void randomize(); + + static int rand(); + static float randf(); + static double randd(); + + static int rand(const int m); + + static int rand(const int from, const int to); + static float rand(const float from, const float to); + static float rand(const double from, const double to); + +}; + +#endif diff --git a/05_sdl_alapok/rect2.cpp b/05_sdl_alapok/rect2.cpp new file mode 100644 index 0000000..b6f7cc6 --- /dev/null +++ b/05_sdl_alapok/rect2.cpp @@ -0,0 +1,156 @@ +#include "rect2.h" + +#include "math.h" + +float Rect2::get_area() const { + return w * h; +} + +bool Rect2::intersects(const Rect2 &b) const { + if (x >= (b.x + b.w)) + return false; + + if ((x + w) <= b.x) + return false; + + if (y >= (b.y + b.h)) + return false; + + if ((y + h) <= b.y) + return false; + + return true; +} + +bool Rect2::intersects_include_borders(const Rect2 &b) const { + if (x > (b.x + b.w)) + return false; + + if ((x + w) < b.x) + return false; + + if (y > (b.y + b.h)) + return false; + + if ((y + h) < b.y) + return false; + + return true; +} + +bool Rect2::encloses(const Rect2 &b) const { + return (b.x >= x) && (b.y >= y) && + ((b.x + b.w) <= (x + w)) && + ((b.y + b.h) <= (y + h)); +} + +bool Rect2::has_no_area() const { + if (w == 0 && h == 0) { + return true; + } + + return false; +} + +bool Rect2::has_point(const float px, const float py) const { + if (px > x && px < x + w && py > y && py < py + h) { + return true; + } + + return false; +} + +bool Rect2::is_equal_approx(const Rect2 &b) const { + if (x + EPSILON < b.x && x - EPSILON > b.x && y + EPSILON < b.y && y - EPSILON > b.y && + w + EPSILON < b.w && w - EPSILON > b.w && h + EPSILON < b.h && h - EPSILON > b.h) { + return true; + } + + return false; +} + +void Rect2::grow(const float by) { + x -= by; + y -= by; + h += by; + w += by; +} + +void Rect2::shrink(const float by) { + x += by; + y += by; + h -= by; + w -= by; +} + +Rect2 &Rect2::operator+=(const Rect2 &b) { + x += b.x; + y += b.y; + w += b.w; + h += b.h; + + return *this; +} + +Rect2 &Rect2::operator-=(const Rect2 &b) { + x -= b.x; + y -= b.y; + w -= b.w; + h -= b.h; + + return *this; +} + +Rect2 operator+(Rect2 lhs, const Rect2 &rhs) { + lhs.x += rhs.x; + lhs.y += rhs.y; + lhs.w += rhs.w; + lhs.h += rhs.h; + + return lhs; +} + +Rect2 operator-(Rect2 lhs, const Rect2 &rhs) { + lhs.x -= rhs.x; + lhs.y -= rhs.y; + lhs.w -= rhs.w; + lhs.h -= rhs.h; + + return lhs; +} + +bool operator==(const Rect2 &a, const Rect2 &b) { + return a.is_equal_approx(b); +} + +bool operator!=(const Rect2 &a, const Rect2 &b) { + return !a.is_equal_approx(b); +} + +Rect2::Rect2() { + x = 0; + y = 0; + w = 0; + h = 0; +} + +Rect2::Rect2(const Rect2 &b) { + x = b.x; + y = b.y; + w = b.w; + h = b.h; +} + +Rect2::Rect2(const float rx, const float ry) { + x = rx; + y = ry; + w = 0; + h = 0; +} + +Rect2::Rect2(const float rx, const float ry, const float rw, const float rh) { + x = rx; + y = ry; + w = rw; + h = rh; +} diff --git a/05_sdl_alapok/rect2.h b/05_sdl_alapok/rect2.h new file mode 100644 index 0000000..1925811 --- /dev/null +++ b/05_sdl_alapok/rect2.h @@ -0,0 +1,37 @@ +#ifndef RECT2_H +#define RECT2_H + +class Rect2 { +public: + float get_area() const; + bool intersects(const Rect2 &b) const; + bool intersects_include_borders(const Rect2 &b) const; + bool encloses(const Rect2 &b) const; + bool has_no_area() const; + bool has_point(const float px, const float py) const; + bool is_equal_approx(const Rect2 &b) const; + + void grow(const float by); + void shrink(const float by); + + Rect2 &operator+=(const Rect2 &b); + Rect2 &operator-=(const Rect2 &b); + + friend Rect2 operator+(Rect2 lhs, const Rect2 &rhs); + friend Rect2 operator-(Rect2 lhs, const Rect2 &rhs); + + friend bool operator==(const Rect2 &a, const Rect2 &b); + friend bool operator!=(const Rect2 &a, const Rect2 &b); + + Rect2(); + Rect2(const Rect2 &b); + Rect2(const float rx, const float ry); + Rect2(const float rx, const float ry, const float rw, const float rh); + + float x; + float y; + float w; + float h; +}; + +#endif \ No newline at end of file diff --git a/05_sdl_alapok/renderer.cpp b/05_sdl_alapok/renderer.cpp new file mode 100644 index 0000000..97a9d2d --- /dev/null +++ b/05_sdl_alapok/renderer.cpp @@ -0,0 +1,95 @@ +#include "renderer.h" + +#include + +void Renderer::present() { + SDL_RenderPresent(_renderer); +} + +void Renderer::set_draw_color(Uint8 r, Uint8 g, Uint8 b, Uint8 a) { + SDL_SetRenderDrawColor(_renderer, r, g, b, a); +} + +void Renderer::clear() { + SDL_RenderClear(_renderer); +} + +void Renderer::draw_rect(const SDL_Rect &rect) { + SDL_RenderFillRect(_renderer, &rect); +} +void Renderer::draw_rect(const Rect2 &rect) { + SDL_Rect r; + r.x = rect.x; + r.y = rect.y; + r.w = rect.w; + r.h = rect.h; + + SDL_RenderFillRect(_renderer, &r); +} + +void Renderer::initialize() { + if (SDL_Init(_flags) != 0) { + printf("SDL_Init() hiba!\n"); + + return; + } + + if (SDL_CreateWindowAndRenderer(640, 480, _window_flags, &_window, &_renderer) != 0) { + printf("SDL_CreateWindowAndRenderer() hiba!\n"); + + return; + } +} + +void Renderer::destroy() { + if (_window) + SDL_DestroyWindow(_window); + + if (_renderer) + SDL_DestroyRenderer(_renderer); + + _window = nullptr; + _renderer = nullptr; +} + +Renderer::Renderer() { + if (_singleton) { + printf("Renderer::Renderer(): _singleton is not null!\n"); + } + + _singleton = this; + + _flags = SDL_INIT_VIDEO | SDL_INIT_TIMER; + _window_flags = SDL_WINDOW_SHOWN; + + initialize(); +} + +Renderer::Renderer(unsigned int flags, unsigned int window_flags) { + if (_singleton) { + printf("Renderer::Renderer(flags): _singleton is not null!\n"); + } + + _singleton = this; + + _flags = flags; + _window_flags = window_flags; + + initialize(); +} + +Renderer::~Renderer() { + if (_singleton != this) { + printf("Renderer::~Renderer(): _singleton is not this!\n"); + } + + _singleton = nullptr; + + destroy(); +} + +Renderer *Renderer::get_singleton() { + return _singleton; +} + +Renderer *Renderer::_singleton = nullptr; \ No newline at end of file diff --git a/05_sdl_alapok/renderer.h b/05_sdl_alapok/renderer.h new file mode 100644 index 0000000..66a1d67 --- /dev/null +++ b/05_sdl_alapok/renderer.h @@ -0,0 +1,35 @@ +#ifndef RENDERER_H +#define RENDERER_H + +#include "rect2.h" +#include + +class Renderer { +public: + void present(); + void set_draw_color(Uint8 r, Uint8 g, Uint8 b, Uint8 a); + void clear(); + + void draw_rect(const SDL_Rect &rect); + void draw_rect(const Rect2 &rect); + + void initialize(); + void destroy(); + + Renderer(); + Renderer(unsigned int flags, unsigned int window_flags); + virtual ~Renderer(); + + static Renderer *get_singleton(); + +private: + unsigned int _flags; + unsigned int _window_flags; + + SDL_Window *_window; + SDL_Renderer *_renderer; + + static Renderer *_singleton; +}; + +#endif \ No newline at end of file