render line with rotation method, still some bugs
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
#include e-Paper subdirectories
|
||||
add_subdirectory(epaper)
|
||||
add_subdirectory(mare)
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -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() {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
|
||||
43
src/main.cpp
43
src/main.cpp
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user