From 2cfcd2f2e86752d42ce7bc160c8f98dce7be7796 Mon Sep 17 00:00:00 2001 From: Benjamin <88098139+Bexin3@users.noreply.github.com> Date: Mon, 8 Jan 2024 15:38:46 +0100 Subject: [PATCH] Add circle rendering support and example --- examples/FillCircle/FillCircle.ino | 44 +++++++++++ examples/RotatingSquare/RotatingSquare.ino | 8 +- src/SpeeduinoGL.cpp | 86 +++++++++++++++------- src/SpeeduinoGL.h | 5 +- 4 files changed, 112 insertions(+), 31 deletions(-) create mode 100644 examples/FillCircle/FillCircle.ino diff --git a/examples/FillCircle/FillCircle.ino b/examples/FillCircle/FillCircle.ino new file mode 100644 index 0000000..11e4a38 --- /dev/null +++ b/examples/FillCircle/FillCircle.ino @@ -0,0 +1,44 @@ +#include "SpeeduinoGL.h" +#include "Arduino_H7_Video.h" +#include "dsi.h" +#include "SDRAM.h" + +uint16_t* FrameBuffer = (uint16_t*)SDRAM_START_ADDRESS; +const int ResV = 480; + +Rectangle sq1 = { + { 0, 0 }, + { 0, 480 }, + { 800, 0 }, + { 800, 480 } +}; + +Point centre = {400, 240}; + +// The buffer used to rotate and resize the frame +Arduino_H7_Video Display(800, 480, GigaDisplayShield); + +void setup() { + SDRAM.begin(); + Display.begin(); + + dsi_lcdClear(0); + dsi_drawCurrentFrameBuffer(); + dsi_lcdClear(0); + dsi_drawCurrentFrameBuffer(); + + ConfigBuffer(SDRAM_START_ADDRESS, ResV); + FillRectangle(sq1, 0x00FF); +} + +void loop() { + + int32_t t1 = micros(); + // FillRectangle(sq1, 0x00FF); + FillCircle(100, 0x0FFF, centre); + Serial.println(micros() - t1); + + dsi_lcdDrawImage((void*)FrameBuffer, (void*)dsi_getCurrentFrameBuffer(), 480, 800, DMA2D_INPUT_RGB565); + dsi_drawCurrentFrameBuffer(); +} + diff --git a/examples/RotatingSquare/RotatingSquare.ino b/examples/RotatingSquare/RotatingSquare.ino index 504d129..e1eb780 100644 --- a/examples/RotatingSquare/RotatingSquare.ino +++ b/examples/RotatingSquare/RotatingSquare.ino @@ -6,7 +6,7 @@ uint16_t* FrameBuffer = (uint16_t*)SDRAM_START_ADDRESS; const int ResV = 480; -Square sq1 = { +Rectangle sq1 = { {0, 0}, {0, 480}, {800, 0}, @@ -31,7 +31,7 @@ void setup() { } void loop() { - FillSquare(sq1, 0x0986); + FillRectangle(sq1, 0x0986); angle += 0.01; @@ -42,8 +42,8 @@ void loop() { {400 + 150 * (cos(angle) + sin(angle)), 240 + 150 * (cos(angle) - sin(angle)) } }; - int32_t t1 = micros(); - FillSquare(sq1, 0x00FF); + int32_t t1 = micros(); + FillRectangle(sq1, 0x00FF); Serial.println(micros() - t1); dsi_lcdDrawImage((void *)FrameBuffer, (void *)dsi_getCurrentFrameBuffer(), 480, 800, DMA2D_INPUT_RGB565); diff --git a/src/SpeeduinoGL.cpp b/src/SpeeduinoGL.cpp index 5291056..cadb246 100644 --- a/src/SpeeduinoGL.cpp +++ b/src/SpeeduinoGL.cpp @@ -37,9 +37,9 @@ uint32_t ResH = 800; gradBC, gradAC, Colour, Polarized); } - void FillSquare(Square square, uint16_t Colour) { + void FillRectangle(Rectangle rectangle, uint16_t Colour) { // Sort points based on x-coordinates - std::sort(&square.A, &square.C + 1, + std::sort(&rectangle.A, &rectangle.C + 1, [](const Point &a, const Point &b) { return a.w < b.w; } @@ -48,53 +48,53 @@ uint32_t ResH = 800; bool switched = false; bool Polarized = false; - float gradAC = (square.C.h - square.A.h) / (square.C.w - square.A.w); - float gradAD = (square.D.h - square.A.h) / (square.D.w - square.A.w); - float gradAB = (square.B.h - square.A.h) / (square.B.w - square.A.w); + float gradAC = (rectangle.C.h - rectangle.A.h) / (rectangle.C.w - rectangle.A.w); + float gradAD = (rectangle.D.h - rectangle.A.h) / (rectangle.D.w - rectangle.A.w); + float gradAB = (rectangle.B.h - rectangle.A.h) / (rectangle.B.w - rectangle.A.w); if (gradAD > gradAB) { if (gradAC > gradAD) { - std::swap(square.C, square.D); + std::swap(rectangle.C, rectangle.D); std::swap(gradAC, gradAD); switched = true; } } else { if (gradAC < gradAD) { - std::swap(square.C, square.D); + std::swap(rectangle.C, rectangle.D); std::swap(gradAC, gradAD); switched = true; } } - float gradBC = (square.C.h - square.B.h) / (square.C.w - square.B.w); - float gradDC = (square.C.h - square.D.h) / (square.C.w - square.D.w); + float gradBC = (rectangle.C.h - rectangle.B.h) / (rectangle.C.w - rectangle.B.w); + float gradDC = (rectangle.C.h - rectangle.D.h) / (rectangle.C.w - rectangle.D.w); Polarized = gradAB > gradAD; - PolarizedTwoLineRasterizer(ceil(square.A.w), ceil(square.B.w), - square.A.h + gradAD * (ceil(square.A.w) - square.A.w), - square.A.h + gradAB * (ceil(square.A.w) - square.A.w), + PolarizedTwoLineRasterizer(ceil(rectangle.A.w), ceil(rectangle.B.w), + rectangle.A.h + gradAD * (ceil(rectangle.A.w) - rectangle.A.w), + rectangle.A.h + gradAB * (ceil(rectangle.A.w) - rectangle.A.w), gradAB, gradAD, Colour, Polarized); if (switched) { - PolarizedTwoLineRasterizer(ceil(square.B.w), ceil(square.C.w), - square.A.h + gradAD * (ceil(square.B.w) - square.A.w), - square.B.h + gradBC * (ceil(square.B.w) - square.B.w), + PolarizedTwoLineRasterizer(ceil(rectangle.B.w), ceil(rectangle.C.w), + rectangle.A.h + gradAD * (ceil(rectangle.B.w) - rectangle.A.w), + rectangle.B.h + gradBC * (ceil(rectangle.B.w) - rectangle.B.w), gradBC, gradAD, Colour, Polarized); - PolarizedTwoLineRasterizer(ceil(square.C.w), ceil(square.D.w), - square.A.h + gradAD * (ceil(square.C.w) - square.A.w), - square.C.h + gradDC * (ceil(square.C.w) - square.C.w), + PolarizedTwoLineRasterizer(ceil(rectangle.C.w), ceil(rectangle.D.w), + rectangle.A.h + gradAD * (ceil(rectangle.C.w) - rectangle.A.w), + rectangle.C.h + gradDC * (ceil(rectangle.C.w) - rectangle.C.w), gradDC, gradAD, Colour, Polarized); } else { - PolarizedTwoLineRasterizer(ceil(square.B.w), ceil(square.D.w), - square.A.h + gradAD * (ceil(square.B.w) - square.A.w), - square.B.h + gradBC * (ceil(square.B.w) - square.B.w), + PolarizedTwoLineRasterizer(ceil(rectangle.B.w), ceil(rectangle.D.w), + rectangle.A.h + gradAD * (ceil(rectangle.B.w) - rectangle.A.w), + rectangle.B.h + gradBC * (ceil(rectangle.B.w) - rectangle.B.w), gradBC, gradAD, Colour, Polarized); - PolarizedTwoLineRasterizer(ceil(square.D.w), ceil(square.C.w), - square.D.h + gradDC * (ceil(square.D.w) - square.D.w), - square.B.h + gradBC * (ceil(square.D.w) - square.B.w), + PolarizedTwoLineRasterizer(ceil(rectangle.D.w), ceil(rectangle.C.w), + rectangle.D.h + gradDC * (ceil(rectangle.D.w) - rectangle.D.w), + rectangle.B.h + gradBC * (ceil(rectangle.D.w) - rectangle.B.w), gradBC, gradDC, Colour, Polarized); } } @@ -114,7 +114,6 @@ uint32_t ResH = 800; if (CellStartX < 0) { PointerCoordinateH -= Gradient2 * CellStartX; PointerEndH -= Gradient1 * CellStartX; - CellStartX = 0; } if (CellEndX > ResH) { @@ -138,3 +137,40 @@ uint32_t ResH = 800; } } + void FillCircle(float Radius, uint16_t Colour, Point Centre) { + uint16_t* ImageBuffer = (uint16_t*)ImageAddress; + + float RadiusTo2 = pow(Radius, 2); + + uint32_t CellEndX = ceil(Centre.w+Radius); + + if (CellEndX > ResH) { + CellEndX = ResH; + }; + + uint32_t CellStartX = ceil(Centre.w-Radius); + float RadiusPos = CellStartX-(Centre.w); + + + for (uint32_t CurrentW = CellStartX; CellEndX > CurrentW; CurrentW++) { + + + float height = sqrt(RadiusTo2 - pow(RadiusPos, 2)); + uint16_t PointerCoorInt = floor(Centre.h - height + 1); + uint16_t PointerEndInt = ceil(Centre.h + height); + + + + if (PointerEndInt > ResV) { + PointerEndInt = ResV; + } + + for (int32_t CurrentH = PointerCoorInt; (PointerEndInt) > CurrentH; CurrentH++) { + ImageBuffer[ResV * (CurrentW) + (CurrentH)] = Colour; + }; + + RadiusPos++; + + } + } + diff --git a/src/SpeeduinoGL.h b/src/SpeeduinoGL.h index d26bc2f..c789447 100644 --- a/src/SpeeduinoGL.h +++ b/src/SpeeduinoGL.h @@ -14,7 +14,7 @@ Point C; }; - struct Square { + struct Rectangle { Point A; Point B; Point D; @@ -23,9 +23,10 @@ void ConfigBuffer(uint32_t address = 0x60000000, uint32_t ResolutionV = 480, uint32_t ResolutionH = 800); void FillTriangle(Triangle triangle, uint16_t Colour); - void FillSquare(Square square, uint16_t Colour); + void FillRectangle(Rectangle rectangle, uint16_t Colour); void PolarizedTwoLineRasterizer(int32_t CellStartX, int32_t CellEndX, float PointerCoordinateH, float PointerEndH, float Gradient1, float Gradient2, uint16_t Colour, bool Polarity); void TwoLineRasterizer(int32_t CellStartX, int32_t CellEndX, float PointerCoordinateH, float PointerEndH, float Gradient1, float Gradient2, uint16_t Colour); + void FillCircle(float Radius, uint16_t Colour, Point Centre); #endif