Основной код: < /p>
.#include
#include
#include
#include "drivers/st7789/st7789.hpp"
#include "libraries/pico_graphics/pico_graphics.hpp"
#include "gfx3d.h"
#include "pico/multicore.h"
using namespace pimoroni;
using namespace torus3d;
const int WIDTH = 240;
const int HEIGHT = 240;
#define MAX_OBJ 12
#define NLINES 240
#define SCR_WD 240
#define SCR_HT 240
#define WD_3D 240
#define HT_3D 240
#define BUTTON_PIN 15
uint16_t frBuf[SCR_WD*NLINES];
uint16_t color565_table[256];
volatile bool core0_done = false;
volatile bool core1_done = false;
ST7789 st7789(WIDTH, HEIGHT, ROTATE_0, false, get_spi_pins(BG_SPI_FRONT));
PicoGraphics_PenRGB565 graphics(st7789.width, st7789.height, frBuf);
int buttonState;
int prevState = true;
long btDebounce = 30;
long btMultiClick = 600;
long btLongClick = 500;
long btLongerClick = 2000;
long btTime = 0, btTime2 = 0;
int clickCnt = 1;
void core1_main() {
torus3d::TorusAngles angles;
angles.sB = 0;
angles.cB = 16384;
angles.sA = 11583;
angles.cA = 11583;
angles.sAsB = 0;
angles.cAsB = 0;
angles.sAcB = 11583;
angles.cAcB = 11583;
while (true) {
printf("core1\n");
drawTorus(angles, 0, 120*240, frBuf, color565_table);
core1_done = true;
// Wait for core0 to finish
while (!core0_done) tight_loop_contents();
// (Optional) Core 1 does nothing else, or could help with next frame
}
}
// 0=idle, 1,2,3=click, -1,-2=longclick
int checkButton( bool state)
{
if( state == false && prevState == true ) { btTime = millis(); prevState = state; return 0; } // button just pressed
if( state == true && prevState == false ) { // button just released
prevState = state;
if( millis()-btTime >= btDebounce && millis()-btTime < btLongClick ) {
if( millis()-btTime2= btLongerClick ) { prevState = state; return -2; }
if( state == false && millis()-btTime >= btLongClick ) { prevState = state; return -1; }
return 0;
}
int prevButtonState=0;
int handleButton(bool button)
{
prevButtonState = buttonState;
buttonState = checkButton(button);
return buttonState;
}
unsigned int ms, msMin=1000, msMax=0, stats=1;
void showStats() {
Pen WHITE = graphics.create_pen(255, 255, 255);
Pen YELLOW = graphics.create_pen(255, 255, 0);
Pen GREEN = graphics.create_pen(0, 255, 0);
Pen MAGENTA = graphics.create_pen(255, 0, 255);
Pen BLACK = graphics.create_pen(0, 0, 0);
char txt[30];
if (ms < msMin) msMin = ms;
if (ms > msMax) msMax = ms;
snprintf(txt, 30, "%d ms %d fps ", ms, 1000 / ms);
graphics.set_pen(YELLOW);
graphics.text(txt, Point(0, SCR_HT - 32), 240);
snprintf(txt, 30, "%d-%d ms %d-%d fps ", msMin, msMax, 1000 / msMax, 1000 / msMin);
graphics.set_pen(GREEN);
graphics.text(txt, Point(0, SCR_HT - 22), 240);
snprintf(txt, 30, "r1: %d r2: %d", iter1, iter2);
graphics.set_pen(MAGENTA);
graphics.text(txt, Point(0, SCR_HT - 12), 240);
}
int main() {
stdio_init_all();
multicore_launch_core1(core1_main);
st7789.set_backlight(255);
gpio_init(BUTTON_PIN);
gpio_set_dir(BUTTON_PIN, GPIO_IN);
gpio_pull_up(BUTTON_PIN); // Use pull-up if button connects to GND
bool last_button = true;
//precopumpute color565 table
for (int c = 0; c < 256; ++c) {
color565_table[c] = pimoroni::RGB(c, c, 0).to_rgb565();
}
torus3d::TorusAngles angles;
angles.sB = 0;
angles.cB = 16384;
angles.sA = 11583;
angles.cA = 11583;
angles.sAsB = 0;
angles.cAsB = 0;
angles.sAcB = 11583;
angles.cAcB = 11583;
while(true) {
//printf("core0");
core0_done = false;
core1_done = false;
bool button = gpio_get(BUTTON_PIN);
handleButton(button);
if(buttonState0) {
msMin=1000;
msMax=0;
}
ms=millis();
drawTorus(angles, 120*240, 240*240, frBuf, color565_table);
ms=millis()-ms;
if(stats) showStats();
while (!core1_done) tight_loop_contents();
// update screen
st7789.update(&graphics);
core0_done = true;
}
return 0;
}
< /code>
И это деталь DALTORUS: < /p>
#include "libraries/pico_graphics/pico_graphics.hpp"
uint16_t BLUE = pimoroni::RGB(0,86,253).to_rgb565(); // BLACK
uint16_t GREY = pimoroni::RGB(200,200,200).to_rgb565(); // BLACK
const int dz = 5, r1 = 1, r2 = 2;
#define R(s,x,y) x-=(y>>s); y+=(x>>s)
// SDL screen dimensions
const int SCREEN_WIDTH = 240;
const int SCREEN_HEIGHT = 240;
const int SCREEN_SIZE = SCREEN_WIDTH * SCREEN_HEIGHT;
int iter1 = 8, iter2 = 8;
namespace torus3d {
struct TorusAngles {
int16_t sB;
int16_t cB;
int16_t sA;
int16_t cA;
int16_t sAsB;
int16_t cAsB;
int16_t sAcB;
int16_t cAcB;
};
}
// CORDIC algorithm (calculate the length of a vector https://en.wikipedia.org/wiki/CORDIC)
inline int length_cordic(int16_t x, int16_t y, int16_t *x2_, int16_t y2, int16_t iterations = 8) {
int x2 = *x2_;
if (x < 0) {
x = -x;
x2 = -x2;
}
for (int i = 0; i < iterations; i++) {
int t = x;
int t2 = x2;
if (y < 0) {
x -= y >> i;
y += t >> i;
x2 -= y2 >> i;
y2 += t2 >> i;
} else {
x += y >> i;
y -= t >> i;
x2 += y2 >> i;
y2 -= t2 >> i;
}
}
*x2_ = (x2 >> 1) + (x2 >> 3);
return (x >> 1) + (x >> 3);
}
void drawTorus(torus3d::TorusAngles& angles, int fromLine, int toLine, uint16_t* frBuf, uint16_t* color565_table) {
//backgroundChecker(angles.sA, angles.sB, frBuf);
// Don't worry, even though this looks like a multiplication,
// the compiler will probably optimize it into shifts
// and adds because dz is a known constant (5).
int p0x = dz * angles.sB >> 6;
int p0y = dz * angles.sAcB >> 6;
int p0z = -dz * angles.cAcB >> 6;
const int r1i = r1 * 256;
const int r2i = r2 * 256;
int niters = 0;
int nnormals = 0;
int16_t yincC = (angles.cA >> 6);
int16_t yincS = (angles.sA >> 6);
int16_t xincX = (angles.cB >> 6);
int16_t xincY = (angles.sAsB >> 6);
int16_t xincZ = (angles.cAsB >> 6);
int16_t ycA = -angles.cA;
int16_t ysA = -angles.sA;
int jb = 0;
for (int j = 0; j < SCREEN_SIZE; j +=(SCREEN_WIDTH > 4) - angles.sAsB;
int xcAsB = (angles.cAsB >> 4) - angles.cAsB;
int16_t vxi14 = (angles.cB >> 4) - angles.cB - angles.sB;
int16_t vyi14 = ycA - xsAsB - angles.sAcB;
int16_t vzi14 = ysA + xcAsB + angles.cAcB;
int jbx = jb % 64;
for (int i = 0; i < SCREEN_WIDTH; i +=2, vxi14 += xincX, vyi14 -= xincY, vzi14 += xincZ) {
int t = 512; // (256 * dz) - r2i - r1i;
int ix = i % 64;
int16_t px = p0x + (vxi14 >> 5); // assuming t = 512, t*vxi>>8 == vxi 5);
int16_t pz = p0z + (vzi14 >> 5);
int16_t lx0 = angles.sB >> 2;
int16_t ly0 = angles.sAcB - angles.cA >> 2;
int16_t lz0 = -angles.cAcB - angles.sA >> 2;
if (j >= fromLine && j < toLine) {
for (;;) {
int t0, t1, t2, d;
int16_t lx = lx0, ly = ly0, lz = lz0;
t0 = length_cordic(px, py, &lx, ly, iter1);
t1 = t0 - r2i;
t2 = length_cordic(pz, t1, &lz, lx, iter2);
d = t2 - r1i;
t += d;
int index = j + i;
if (t > 8 * 256) {
uint16_t color = ((jbx32)) ? BLUE : GREY;
frBuf[index] = color;
frBuf[index+1] = color;
frBuf[index+SCREEN_WIDTH] = color;
frBuf[index+SCREEN_WIDTH+1] = color;
break;
} else if (d < 3) {
int N = lz >> 5;
uint16_t color = color565_table[(N > 0 ? N < 256 ? N : 255 : 0)];
int index = j + i;
frBuf[index] = color;
frBuf[index+1] = color;
frBuf[index+SCREEN_WIDTH] = color;
frBuf[index+SCREEN_WIDTH+1] = color;
nnormals++;
break;
}
px += d * vxi14 >> 14;
py += d * vyi14 >> 14;
pz += d * vzi14 >> 14;
niters++;
}
}
}
}
// rotate sines, cosines, and products thereof
// this animates the torus rotation about two axes
R(5, angles.cA, angles.sA);
R(5, angles.cAsB, angles.sAsB);
R(5, angles.cAcB, angles.sAcB);
R(6, angles.cB, angles.sB);
R(6, angles.cAcB, angles.cAsB);
R(6, angles.sAcB, angles.sAsB);
//printf("cA: %d, sA: %d\n", angles.cA, angles.sA);
}
Подробнее здесь: https://stackoverflow.com/questions/797 ... de-working
Мобильная версия