render line with rotation method, still some bugs
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
#include e-Paper subdirectories
|
#include e-Paper subdirectories
|
||||||
add_subdirectory(epaper)
|
add_subdirectory(epaper)
|
||||||
add_subdirectory(mare)
|
add_subdirectory(mare)
|
||||||
|
|
||||||
|
|||||||
@@ -10,4 +10,4 @@ include_directories(../epaper/Fonts)
|
|||||||
|
|
||||||
# Generate the link library
|
# Generate the link library
|
||||||
add_library(Mare ${DIR_Config_SRCS})
|
add_library(Mare ${DIR_Config_SRCS})
|
||||||
target_link_libraries(Mare PUBLIC Config ePaper Fonts pico_stdlib hardware_spi)
|
target_link_libraries(Mare PUBLIC Config ePaper Fonts pico_stdlib pico_printf pico_mem_ops hardware_spi)
|
||||||
@@ -19,14 +19,17 @@ namespace Render {
|
|||||||
clearBuffer(_screenBufferBackground, _bufferDim, Color::White);
|
clearBuffer(_screenBufferBackground, _bufferDim, Color::White);
|
||||||
|
|
||||||
// init display
|
// init display
|
||||||
DEV_Delay_ms(500);
|
sleep_ms(500);
|
||||||
if((rv=DEV_Module_Init())!=0){
|
if((rv=DEV_Module_Init())!=0){
|
||||||
printf("Init Failed, %d\n",rv);
|
printf("Init Failed, %d\n",rv);
|
||||||
|
__breakpoint();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
EPD_2IN9_V2_Init();
|
EPD_2IN9_V2_Init();
|
||||||
EPD_2IN9_V2_Clear();
|
EPD_2IN9_V2_Clear();
|
||||||
printf("Mare render engine created\n");
|
printf("Mare render engine created\n");
|
||||||
|
EPD_2IN9_V2_Display(_screenBufferBackground);
|
||||||
|
sleep_ms(500);
|
||||||
}
|
}
|
||||||
|
|
||||||
Mare::~Mare(){
|
Mare::~Mare(){
|
||||||
@@ -45,7 +48,7 @@ namespace Render {
|
|||||||
for (auto d: _drawables) {
|
for (auto d: _drawables) {
|
||||||
if (d != nullptr)
|
if (d != nullptr)
|
||||||
d->render();
|
d->render();
|
||||||
}
|
};
|
||||||
EPD_2IN9_V2_Display_Partial(_screenBufferBackground);
|
EPD_2IN9_V2_Display_Partial(_screenBufferBackground);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,17 +57,15 @@ namespace Render {
|
|||||||
std::memset(buffer, col == Color::White ? 0xff : 0x00, len);
|
std::memset(buffer, col == Color::White ? 0xff : 0x00, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mare::applyRotation(uint16_t* x, uint16_t* y) {
|
bool Mare::applyScreenRotation(uint16_t* x, uint16_t* y) {
|
||||||
uint16_t ax,ay;
|
uint16_t ax,ay;
|
||||||
switch(_rotation){
|
switch(_rotation){
|
||||||
case ScreenRotation::Rot0 :
|
case ScreenRotation::Rot0 :
|
||||||
{
|
{
|
||||||
if (*x >= _screenSize.x || *y >= _screenSize.y) return false;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ScreenRotation::Rot90 :
|
case ScreenRotation::Rot90 :
|
||||||
{
|
{
|
||||||
if (*x >= _screenSize.y || *y >= _screenSize.x) return false;
|
|
||||||
ax = *x; ay = *y;
|
ax = *x; ay = *y;
|
||||||
*x = _screenSize.x - ay;
|
*x = _screenSize.x - ay;
|
||||||
*y = ax;
|
*y = ax;
|
||||||
@@ -72,7 +73,6 @@ namespace Render {
|
|||||||
}
|
}
|
||||||
case ScreenRotation::Rot180 :
|
case ScreenRotation::Rot180 :
|
||||||
{
|
{
|
||||||
if (*x >= _screenSize.x || *y >= _screenSize.y) return false;
|
|
||||||
ax = *x; ay = *y;
|
ax = *x; ay = *y;
|
||||||
*x = _screenSize.x - ax;
|
*x = _screenSize.x - ax;
|
||||||
*y = _screenSize.y - ay;
|
*y = _screenSize.y - ay;
|
||||||
@@ -80,13 +80,13 @@ namespace Render {
|
|||||||
}
|
}
|
||||||
case ScreenRotation::Rot270 :
|
case ScreenRotation::Rot270 :
|
||||||
{
|
{
|
||||||
if (*x >= _screenSize.y || *y >= _screenSize.x) return false;
|
|
||||||
ax = *x; ay = *y;
|
ax = *x; ay = *y;
|
||||||
*x = ay;
|
*x = ay;
|
||||||
*y = _screenSize.y - ax;
|
*y = _screenSize.y - ax;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (*x >= _screenSize.x || *y >= _screenSize.y) return false;
|
||||||
if (*x < 0 || *y < 0) return false;
|
if (*x < 0 || *y < 0) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -105,12 +105,22 @@ namespace Render {
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mare::setPixel(uint8_t* img, uint16_t x, uint16_t y, bool value) {
|
void Mare::setPixel(uint8_t* img, uint16_t x, uint16_t y, BlendMode bm) {
|
||||||
if (!applyRotation(&x,&y)) return;
|
if (!applyScreenRotation(&x,&y)) return;
|
||||||
// from here the coordinates are natural for the screen
|
// from here the coordinates are natural for the screen
|
||||||
img += (sizeof(uint8_t)*y*(_screenSize.x>>3) + sizeof(uint8_t)*(x>>3));
|
img += (sizeof(uint8_t)*y*(_screenSize.x>>3) + sizeof(uint8_t)*(x>>3));
|
||||||
if (value) *img &= ~(0x80 >> (x%8));
|
if (bm == BlendMode::Add) *img &= ~(0x80 >> (x%8));
|
||||||
else *img |= (0x80 >> (x%8));
|
else if (bm == BlendMode::Intersect) *img = ~*img ^ ~(0x80 >> (x%8));
|
||||||
|
}
|
||||||
|
|
||||||
|
spos_t Mare::rotateXY(int16_t x, int16_t y, float rot){
|
||||||
|
// apply rotation matrix xy
|
||||||
|
spos_t rv;
|
||||||
|
float cx,sx;
|
||||||
|
sincosf(rot, &sx, &cx);
|
||||||
|
rv.x = x*cx - y*sx;
|
||||||
|
rv.y = x*sx + y*cx;
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mare::clearScreen() {
|
void Mare::clearScreen() {
|
||||||
|
|||||||
@@ -2,8 +2,10 @@
|
|||||||
* Most Awesome Renderer Ever
|
* Most Awesome Renderer Ever
|
||||||
*******************************************/
|
*******************************************/
|
||||||
|
|
||||||
#include <stdio.h>
|
//#include <stdio.h>
|
||||||
#include <pico/stdlib.h>
|
#include <pico/stdlib.h>
|
||||||
|
#include <pico/printf.h>
|
||||||
|
#include <pico/int64_ops.h>
|
||||||
#include <pico/float.h>
|
#include <pico/float.h>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -24,6 +26,11 @@ namespace Render{
|
|||||||
uint16_t y;
|
uint16_t y;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct spos_t {
|
||||||
|
int16_t x;
|
||||||
|
int16_t y;
|
||||||
|
};
|
||||||
|
|
||||||
struct bbox2d_t {
|
struct bbox2d_t {
|
||||||
uint16_t xMin, Ymin;
|
uint16_t xMin, Ymin;
|
||||||
uint16_t Xmax, Ymax;
|
uint16_t Xmax, Ymax;
|
||||||
@@ -92,12 +99,13 @@ namespace Render{
|
|||||||
//render
|
//render
|
||||||
private:
|
private:
|
||||||
void clearBuffer(uint8_t* buffer, uint16_t len, Color col);
|
void clearBuffer(uint8_t* buffer, uint16_t len, Color col);
|
||||||
bool applyRotation(uint16_t* x, uint16_t* y);
|
bool applyScreenRotation(uint16_t* x, uint16_t* y);
|
||||||
void visitDrawables(Drawable* parent) {};
|
void visitDrawables(Drawable* parent) {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void render();
|
void render();
|
||||||
void setPixel(uint8_t* img, uint16_t x, uint16_t y, bool value);
|
void setPixel(uint8_t* img, uint16_t x, uint16_t y, BlendMode bm);
|
||||||
|
spos_t rotateXY(int16_t x, int16_t y, float rot);
|
||||||
void clearScreen();
|
void clearScreen();
|
||||||
|
|
||||||
// members
|
// members
|
||||||
@@ -129,7 +137,7 @@ namespace Render{
|
|||||||
void setOrigin(const pos_t origin) { _origin = origin; };
|
void setOrigin(const pos_t origin) { _origin = origin; };
|
||||||
void setDirty() {_dirty = true;};
|
void setDirty() {_dirty = true;};
|
||||||
void resetDirty() {_dirty = false;};
|
void resetDirty() {_dirty = false;};
|
||||||
void setBlendMode(const BlendMode mode) { _blendMode = BlendMode::Intersect; };
|
void setBlendMode(const BlendMode mode) { _blendMode = mode; };
|
||||||
|
|
||||||
const bool isDirty() {return _dirty;}
|
const bool isDirty() {return _dirty;}
|
||||||
const pos_t getOrigin() { return _origin; };
|
const pos_t getOrigin() { return _origin; };
|
||||||
@@ -186,6 +194,8 @@ namespace Render{
|
|||||||
const float getRotation() {return _rotation;};
|
const float getRotation() {return _rotation;};
|
||||||
void setLength(uint16_t length) {_lenght = length;};
|
void setLength(uint16_t length) {_lenght = length;};
|
||||||
const uint16_t getLength() {return _lenght;};
|
const uint16_t getLength() {return _lenght;};
|
||||||
|
void setOutline(bool outline) {_outline = outline;};
|
||||||
|
const bool getOutline() {return _outline;};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void render(); // difficult business
|
void render(); // difficult business
|
||||||
@@ -195,6 +205,7 @@ namespace Render{
|
|||||||
uint16_t _thickness;
|
uint16_t _thickness;
|
||||||
uint16_t _lenght;
|
uint16_t _lenght;
|
||||||
float _rotation;
|
float _rotation;
|
||||||
|
bool _outline;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DrawableRectangle: public Drawable {
|
class DrawableRectangle: public Drawable {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace Render {
|
|||||||
_engine(engine),
|
_engine(engine),
|
||||||
_origin({0,0}),
|
_origin({0,0}),
|
||||||
_bbox({0,0,0,0}),
|
_bbox({0,0,0,0}),
|
||||||
_blendMode(Render::BlendMode::Intersect),
|
_blendMode(Render::BlendMode::Add),
|
||||||
_dirty(false)
|
_dirty(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -32,6 +32,7 @@ namespace Render {
|
|||||||
|
|
||||||
void DrawablePoint::render() {
|
void DrawablePoint::render() {
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
|
pos_t o = getOrigin();
|
||||||
if (isDirty()){
|
if (isDirty()){
|
||||||
buf = getBuffer();
|
buf = getBuffer();
|
||||||
//TODO: implement screen rotation and margin check
|
//TODO: implement screen rotation and margin check
|
||||||
@@ -40,7 +41,7 @@ namespace Render {
|
|||||||
for (uint16_t xx(0); xx< _size.x; xx++){
|
for (uint16_t xx(0); xx< _size.x; xx++){
|
||||||
for (uint16_t yy(0); yy < _size.y; yy++)
|
for (uint16_t yy(0); yy < _size.y; yy++)
|
||||||
{
|
{
|
||||||
engine()->setPixel(buf,dx-(getOrigin().x+xx),getOrigin().y+yy,true);
|
engine()->setPixel(buf,o.x+xx,o.y+yy,getBlendMode());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resetDirty();
|
resetDirty();
|
||||||
@@ -54,7 +55,8 @@ namespace Render {
|
|||||||
Drawable(id, parent,engine),
|
Drawable(id, parent,engine),
|
||||||
_thickness(1),
|
_thickness(1),
|
||||||
_lenght(0),
|
_lenght(0),
|
||||||
_rotation(0.0f)
|
_rotation(0.0f),
|
||||||
|
_outline(false)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -67,40 +69,55 @@ namespace Render {
|
|||||||
uint8_t* buf = getBuffer();
|
uint8_t* buf = getBuffer();
|
||||||
auto tt = _thickness;
|
auto tt = _thickness;
|
||||||
auto e = engine();
|
auto e = engine();
|
||||||
auto square = [buf,e,tt](uint16_t x, uint16_t y){
|
// auto square = [buf,e,tt](uint16_t x, uint16_t y){
|
||||||
uint8_t c = tt > 1 ? tt>>1 : 0; //sprite render
|
// uint8_t c = tt > 1 ? tt>>1 : 0; //sprite render
|
||||||
x -= c;
|
// x -= c;
|
||||||
y -= c;
|
// y -= c;
|
||||||
for (auto xx(0); xx <= tt; ++xx)
|
// for (auto xx(0); xx <= tt; ++xx)
|
||||||
for (auto yy(0); yy <= tt; ++yy){
|
// for (auto yy(0); yy <= tt; ++yy){
|
||||||
e->setPixel(buf,xx+x,yy+y,true);
|
// e->setPixel(buf,xx+x,yy+y,getBlendMode());
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
if (isDirty()) {
|
// if (isDirty() && false) {
|
||||||
|
// _rotation = fmod(_rotation, M_TWOPI);
|
||||||
|
// float cx,sx;
|
||||||
|
// sincosf(_rotation,&sx,&cx); // use optimized float instructions
|
||||||
|
// uint16_t endX = fabs(round(cx*(float)_lenght));
|
||||||
|
// uint16_t endY = fabs(round(sx*(float)_lenght));
|
||||||
|
|
||||||
|
// int8_t mult = (_rotation <= 3*M_PI_4 || _rotation >= 7*M_PI_4) ? 1 : -1;
|
||||||
|
|
||||||
|
// if ((_rotation >= 7*M_PI_4 || _rotation <= M_PI_4) ||
|
||||||
|
// (_rotation >= 3*M_PI_4 && _rotation <= 5*M_PI_4)) {
|
||||||
|
|
||||||
|
// for(uint16_t xx(0); xx <= endX; ++xx){
|
||||||
|
// float dydx = cx == 0.0f ? 0 : (sx/cx);
|
||||||
|
// uint16_t y = getOrigin().y+xx*mult*dydx;
|
||||||
|
// uint16_t x = getOrigin().x+xx*mult;
|
||||||
|
// square(x,y);
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// for (uint16_t yy(0); yy <= endY; ++yy){
|
||||||
|
// float dxdy = sx == 0.0f ? 0 : (cx/sx);
|
||||||
|
// uint16_t y = getOrigin().y+yy*mult;
|
||||||
|
// uint16_t x = getOrigin().x+yy*mult*dxdy;
|
||||||
|
// square(x,y);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// resetDirty();
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (isDirty() && true) {
|
||||||
_rotation = fmod(_rotation, M_TWOPI);
|
_rotation = fmod(_rotation, M_TWOPI);
|
||||||
float cx,sx;
|
pos_t o = getOrigin();
|
||||||
sincosf(_rotation,&sx,&cx); // use optimized float instructions
|
static spos_t res = {0,0};
|
||||||
uint16_t endX = fabs(round(cx*(float)_lenght));
|
for (uint16_t t(0); t < _thickness; ++t) {
|
||||||
uint16_t endY = fabs(round(sx*(float)_lenght));
|
for (uint16_t xx(0); xx < _lenght; ++xx) {
|
||||||
|
if (!_outline || (_outline && (xx == 0 || xx == _lenght - 1 || t == 0 || t == _thickness - 1))) {
|
||||||
int8_t mult = (_rotation <= 3*M_PI_4 || _rotation >= 7*M_PI_4) ? 1 : -1;
|
res = e->rotateXY(xx,t-(_thickness>>1),_rotation);
|
||||||
|
e->setPixel(buf,res.x+o.x,res.y+o.y,getBlendMode());
|
||||||
if ((_rotation >= 7*M_PI_4 || _rotation <= M_PI_4) ||
|
|
||||||
(_rotation >= 3*M_PI_4 && _rotation <= 5*M_PI_4)) {
|
|
||||||
|
|
||||||
for(uint16_t xx(0); xx <= endX; ++xx){
|
|
||||||
float dydx = cx == 0.0f ? 0 : (sx/cx);
|
|
||||||
uint16_t y = getOrigin().y+xx*mult*dydx;
|
|
||||||
uint16_t x = getOrigin().x+xx*mult;
|
|
||||||
square(x,y);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
for (uint16_t yy(0); yy <= endY; ++yy){
|
|
||||||
float dxdy = sx == 0.0f ? 0 : (cx/sx);
|
|
||||||
uint16_t y = getOrigin().y+yy*mult;
|
|
||||||
uint16_t x = getOrigin().x+yy*mult*dxdy;
|
|
||||||
square(x,y);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resetDirty();
|
resetDirty();
|
||||||
|
|||||||
43
src/main.cpp
43
src/main.cpp
@@ -9,7 +9,7 @@ int main(){
|
|||||||
gpio_init(LED_PIN);
|
gpio_init(LED_PIN);
|
||||||
gpio_set_dir(LED_PIN, GPIO_OUT);
|
gpio_set_dir(LED_PIN, GPIO_OUT);
|
||||||
bool s=false;
|
bool s=false;
|
||||||
uint i(2);
|
uint i(16);
|
||||||
Render::dim_t ssize;
|
Render::dim_t ssize;
|
||||||
ssize.x = EPD_2IN9_V2_WIDTH;
|
ssize.x = EPD_2IN9_V2_WIDTH;
|
||||||
ssize.y = EPD_2IN9_V2_HEIGHT;
|
ssize.y = EPD_2IN9_V2_HEIGHT;
|
||||||
@@ -17,40 +17,39 @@ int main(){
|
|||||||
auto viewer = Render::Mare(ssize,
|
auto viewer = Render::Mare(ssize,
|
||||||
Render::ScreenRotation::Rot90);
|
Render::ScreenRotation::Rot90);
|
||||||
|
|
||||||
Render::dim_t ps; ps.x=0; ps.y=0;
|
auto c1 = viewer.addDrawable<Render::DrawableLine>();
|
||||||
|
auto c2 = viewer.addDrawable<Render::DrawableLine>();
|
||||||
auto line = viewer.addDrawable<Render::DrawableLine>();
|
|
||||||
auto line2 = viewer.addDrawable<Render::DrawableLine>();
|
|
||||||
auto line3 = viewer.addDrawable<Render::DrawableLine>();
|
auto line3 = viewer.addDrawable<Render::DrawableLine>();
|
||||||
|
|
||||||
line->setOrigin(ps);
|
c1->setOrigin({0,63});
|
||||||
line->setLength(256);
|
c1->setLength(296);
|
||||||
line2->setLength(256);
|
c1->setThickness(2);
|
||||||
|
c1->setBlendMode(Render::BlendMode::Add);
|
||||||
|
|
||||||
|
c2->setOrigin({296/2-1, 1});
|
||||||
|
c2->setLength(128);
|
||||||
|
c2->setRotation(M_PI_2);
|
||||||
|
c2->setThickness(2);
|
||||||
|
c1->setBlendMode(Render::BlendMode::Add);
|
||||||
|
|
||||||
line3->setLength(64);
|
line3->setLength(64);
|
||||||
line3->setOrigin(viewer.getCenter());
|
line3->setOrigin(viewer.getCenter());
|
||||||
|
line3->setBlendMode(Render::BlendMode::Add);
|
||||||
|
line3->setOutline(false);
|
||||||
|
|
||||||
while (true){
|
while (true){
|
||||||
ps.x = ssize.y-i;
|
|
||||||
line2->setOrigin(ps);
|
|
||||||
line->setThickness(i);
|
|
||||||
line2->setThickness(i);
|
|
||||||
line3->setThickness(i++);
|
line3->setThickness(i++);
|
||||||
for (float a(0); a<=M_TWOPI; a+=(M_TWOPI/90.0f)){
|
for (float a(0); a<=M_TWOPI; a+=(M_TWOPI/36.0f)){
|
||||||
line->setRotation(a);
|
|
||||||
line2->setRotation(M_PI-a);
|
|
||||||
line3->setRotation(a);
|
line3->setRotation(a);
|
||||||
line->setDirty();
|
|
||||||
line2->setDirty();
|
|
||||||
line3->setDirty();
|
line3->setDirty();
|
||||||
|
c1->setDirty();
|
||||||
|
c2->setDirty();
|
||||||
viewer.render();
|
viewer.render();
|
||||||
printf("Angle: %4.3f\n", a/M_PI*180.0f);
|
|
||||||
}
|
}
|
||||||
viewer.clearScreen();
|
viewer.clearScreen();
|
||||||
}
|
//line3->setOutline(s);
|
||||||
while(true){
|
|
||||||
gpio_put(LED_PIN,s);
|
gpio_put(LED_PIN,s);
|
||||||
s = s ? false : true;
|
s = s ? false : true;
|
||||||
sleep_ms(500);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user