render line with rotation method, still some bugs

This commit is contained in:
Emanuele Trabattoni
2021-06-02 18:04:23 +02:00
parent 7116885f2d
commit 60c6ca83c1
6 changed files with 109 additions and 73 deletions

View File

@@ -1,4 +1,3 @@
#include e-Paper subdirectories
add_subdirectory(epaper)
add_subdirectory(mare)

View File

@@ -10,4 +10,4 @@ include_directories(../epaper/Fonts)
# Generate the link library
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)

View File

@@ -19,14 +19,17 @@ namespace Render {
clearBuffer(_screenBufferBackground, _bufferDim, Color::White);
// init display
DEV_Delay_ms(500);
sleep_ms(500);
if((rv=DEV_Module_Init())!=0){
printf("Init Failed, %d\n",rv);
__breakpoint();
return;
}
EPD_2IN9_V2_Init();
EPD_2IN9_V2_Clear();
printf("Mare render engine created\n");
EPD_2IN9_V2_Display(_screenBufferBackground);
sleep_ms(500);
}
Mare::~Mare(){
@@ -45,7 +48,7 @@ namespace Render {
for (auto d: _drawables) {
if (d != nullptr)
d->render();
}
};
EPD_2IN9_V2_Display_Partial(_screenBufferBackground);
}
@@ -54,17 +57,15 @@ namespace Render {
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;
switch(_rotation){
case ScreenRotation::Rot0 :
{
if (*x >= _screenSize.x || *y >= _screenSize.y) return false;
break;
}
case ScreenRotation::Rot90 :
{
if (*x >= _screenSize.y || *y >= _screenSize.x) return false;
ax = *x; ay = *y;
*x = _screenSize.x - ay;
*y = ax;
@@ -72,21 +73,20 @@ namespace Render {
}
case ScreenRotation::Rot180 :
{
if (*x >= _screenSize.x || *y >= _screenSize.y) return false;
ax = *x; ay = *y;
*x = _screenSize.x - ax;
*y = _screenSize.y - ay;
*y = _screenSize.y - ay;
break;
}
case ScreenRotation::Rot270 :
{
if (*x >= _screenSize.y || *y >= _screenSize.x) return false;
ax = *x; ay = *y;
*x = ay;
*y = _screenSize.y - ax;
break;
}
}
if (*x >= _screenSize.x || *y >= _screenSize.y) return false;
if (*x < 0 || *y < 0) return false;
return true;
}
@@ -105,12 +105,22 @@ namespace Render {
return rv;
}
void Mare::setPixel(uint8_t* img, uint16_t x, uint16_t y, bool value) {
if (!applyRotation(&x,&y)) return;
void Mare::setPixel(uint8_t* img, uint16_t x, uint16_t y, BlendMode bm) {
if (!applyScreenRotation(&x,&y)) return;
// from here the coordinates are natural for the screen
img += (sizeof(uint8_t)*y*(_screenSize.x>>3) + sizeof(uint8_t)*(x>>3));
if (value) *img &= ~(0x80 >> (x%8));
else *img |= (0x80 >> (x%8));
if (bm == BlendMode::Add) *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() {

View File

@@ -2,8 +2,10 @@
* Most Awesome Renderer Ever
*******************************************/
#include <stdio.h>
//#include <stdio.h>
#include <pico/stdlib.h>
#include <pico/printf.h>
#include <pico/int64_ops.h>
#include <pico/float.h>
extern "C" {
@@ -24,6 +26,11 @@ namespace Render{
uint16_t y;
};
struct spos_t {
int16_t x;
int16_t y;
};
struct bbox2d_t {
uint16_t xMin, Ymin;
uint16_t Xmax, Ymax;
@@ -92,12 +99,13 @@ namespace Render{
//render
private:
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) {};
public:
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();
// members
@@ -129,7 +137,7 @@ namespace Render{
void setOrigin(const pos_t origin) { _origin = origin; };
void setDirty() {_dirty = true;};
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 pos_t getOrigin() { return _origin; };
@@ -186,6 +194,8 @@ namespace Render{
const float getRotation() {return _rotation;};
void setLength(uint16_t length) {_lenght = length;};
const uint16_t getLength() {return _lenght;};
void setOutline(bool outline) {_outline = outline;};
const bool getOutline() {return _outline;};
private:
void render(); // difficult business
@@ -195,6 +205,7 @@ namespace Render{
uint16_t _thickness;
uint16_t _lenght;
float _rotation;
bool _outline;
};
class DrawableRectangle: public Drawable {

View File

@@ -8,7 +8,7 @@ namespace Render {
_engine(engine),
_origin({0,0}),
_bbox({0,0,0,0}),
_blendMode(Render::BlendMode::Intersect),
_blendMode(Render::BlendMode::Add),
_dirty(false)
{
}
@@ -32,6 +32,7 @@ namespace Render {
void DrawablePoint::render() {
uint8_t *buf;
pos_t o = getOrigin();
if (isDirty()){
buf = getBuffer();
//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 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();
@@ -54,7 +55,8 @@ namespace Render {
Drawable(id, parent,engine),
_thickness(1),
_lenght(0),
_rotation(0.0f)
_rotation(0.0f),
_outline(false)
{
}
@@ -67,40 +69,55 @@ namespace Render {
uint8_t* buf = getBuffer();
auto tt = _thickness;
auto e = engine();
auto square = [buf,e,tt](uint16_t x, uint16_t y){
uint8_t c = tt > 1 ? tt>>1 : 0; //sprite render
x -= c;
y -= c;
for (auto xx(0); xx <= tt; ++xx)
for (auto yy(0); yy <= tt; ++yy){
e->setPixel(buf,xx+x,yy+y,true);
}
};
// auto square = [buf,e,tt](uint16_t x, uint16_t y){
// uint8_t c = tt > 1 ? tt>>1 : 0; //sprite render
// x -= c;
// y -= c;
// for (auto xx(0); xx <= tt; ++xx)
// for (auto yy(0); yy <= tt; ++yy){
// e->setPixel(buf,xx+x,yy+y,getBlendMode());
// }
// };
if (isDirty()) {
_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));
// 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;
// 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)) {
// 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);
// 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);
pos_t o = getOrigin();
static spos_t res = {0,0};
for (uint16_t t(0); t < _thickness; ++t) {
for (uint16_t xx(0); xx < _lenght; ++xx) {
if (!_outline || (_outline && (xx == 0 || xx == _lenght - 1 || t == 0 || t == _thickness - 1))) {
res = e->rotateXY(xx,t-(_thickness>>1),_rotation);
e->setPixel(buf,res.x+o.x,res.y+o.y,getBlendMode());
}
}
}
resetDirty();

View File

@@ -9,7 +9,7 @@ int main(){
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);
bool s=false;
uint i(2);
uint i(16);
Render::dim_t ssize;
ssize.x = EPD_2IN9_V2_WIDTH;
ssize.y = EPD_2IN9_V2_HEIGHT;
@@ -17,40 +17,39 @@ int main(){
auto viewer = Render::Mare(ssize,
Render::ScreenRotation::Rot90);
Render::dim_t ps; ps.x=0; ps.y=0;
auto line = viewer.addDrawable<Render::DrawableLine>();
auto line2 = viewer.addDrawable<Render::DrawableLine>();
auto c1 = viewer.addDrawable<Render::DrawableLine>();
auto c2 = viewer.addDrawable<Render::DrawableLine>();
auto line3 = viewer.addDrawable<Render::DrawableLine>();
line->setOrigin(ps);
line->setLength(256);
line2->setLength(256);
c1->setOrigin({0,63});
c1->setLength(296);
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->setOrigin(viewer.getCenter());
line3->setBlendMode(Render::BlendMode::Add);
line3->setOutline(false);
while (true){
ps.x = ssize.y-i;
line2->setOrigin(ps);
line->setThickness(i);
line2->setThickness(i);
line3->setThickness(i++);
for (float a(0); a<=M_TWOPI; a+=(M_TWOPI/90.0f)){
line->setRotation(a);
line2->setRotation(M_PI-a);
for (float a(0); a<=M_TWOPI; a+=(M_TWOPI/36.0f)){
line3->setRotation(a);
line->setDirty();
line2->setDirty();
line3->setDirty();
c1->setDirty();
c2->setDirty();
viewer.render();
printf("Angle: %4.3f\n", a/M_PI*180.0f);
}
viewer.clearScreen();
}
while(true){
//line3->setOutline(s);
gpio_put(LED_PIN,s);
s = s ? false : true;
sleep_ms(500);
}
return 0;
}