mrt-prodz / atmega328-tiny-3d-engine Goto Github PK
View Code? Open in Web Editor NEW3D model viewer made for the ATmega328 and Sainsmart 1.8" TFT screen (ST7735)
3D model viewer made for the ATmega328 and Sainsmart 1.8" TFT screen (ST7735)
//python 3 is not supported by stl2h.py , so here is the conversation for python3..
//online formatting of text might be incorrect so copy and put into a file.. i'm hesitant to change original file at this point
//and leave it up to original authors..
//modified by james villeneuve in 2022 for stl to file conversion for arduino stl files for tiny 3d engine
//using https://www.tutorialspoint.com/online_python_formatter.htm to clean up tab issues
//and using a python 2to3 converter online tool https://python2to3.com/#!/usr/bin/python
//just save in any working directory as stl2h.py
// to use you will most likely need to decimate stl file to under 700 faces in blender and then
//use a program like meshlab to convert it from binary stl to text based output.
//below is an example that uses a file called my_stl_file.stl output file text.txt and scales item by 5.
//example use is python3 stl2h.py -i my_stl_file.stl -o text.txt -s 5
file for python3 is here. https://github.com/jamesdanielv/pyhton3convertof-stl2h.py
I do not see a license for this software. Is it public-domain or what is the license to modify and redistribute?
Hi,
I have ardiuno uno board interfaced with TFT screen st7735 and when I use your code it shows me an error in compiling .
C:\Users\Haaris Moosa\Desktop\arduino-1.8.5\hardware\tools\avr/bin/avr-gcc" -w -Os -g -flto -fuse-linker-plugin -Wl,--gc-sections -mmcu=atmega328p -w -flto -fuse-linker-plugin -o tiny_3d_engine:157: error: unable to find a register to spill in class 'POINTER_REGS'
I have only listed the errors which are useful
I googled it and it's a gcc compiler error. I'm using gcc 4.9.2
Can you please share your gcc version and the Arduino IDE version that you were using?
Hello,
Thanks for this nice engine.
I was able to use it on a Teensy 3.6 with an SSD1306 Oled display at 128x64.
There is only a problem with STL objects TRIcount > 256 in wireframe mode.
Only the first 256 tris are rendered correctly. The rest is rendered in "random" line coordinates.
Vertex mode seems to work correctly wit more than 256 nodes.
I changed the datatype in stl2h.py -> const unsigned char faces[TRICOUNT][3]
to const unsigned short int faces[TRICOUNT][3].
also in the Arduino sketch i changed a lot to widen the data type ranges.
I just cant figure out what the real problem is.
Any help is very appreciated! Thanks!
The planes look like a grid mesh. >> objects.zip
// =============================================================================
// Arduino - Tiny 3D Engine
// =============================================================================
// ----------------------------------------------
// includes
// ----------------------------------------------
#include "type.h"
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
Adafruit_SSD1306 display(4);
// ----------------------------------------------
// meshes
// ----------------------------------------------
//#include "mesh_cube.h"
//#include "mesh_cone.h"
//#include "mesh_sphere.h"
//#include "mesh_torus.h"
//#include "mesh_monkey.h"
#include "plane.h"
//#include "planeLow.h"
// ----------------------------------------------
// defines
// ----------------------------------------------
#define HALFW 64
#define HALFH 32
#define FOV 64
#define SKIP_TICKS 20.0 // 50fps
#define MAX_FRAMESKIP 3
#define LUT(a) (long)(pgm_read_word(&lut[a]))// return value from LUT in PROGMEM
// ----------------------------------------------
// global variables
// ----------------------------------------------
Matrix4 m_world;
Vector3i mesh_rotation = {0, 0, 0};
Vector3i mesh_position = {0, 0, 0};
const unsigned int lut[] PROGMEM = { // 0 to 90 degrees fixed point COSINE look up table
16384, 16381, 16374, 16361, 16344, 16321, 16294, 16261, 16224, 16182, 16135, 16082, 16025, 15964, 15897, 15825, 15749, 15668, 15582, 15491, 15395, 15295, 15190, 15081, 14967, 14848, 14725, 14598, 14466, 14329, 14188, 14043, 13894, 13740, 13582, 13420, 13254, 13084, 12910, 12732, 12550, 12365, 12175, 11982, 11785, 11585, 11381, 11173, 10963, 10748, 10531, 10310, 10086, 9860, 9630, 9397, 9161, 8923, 8682, 8438, 8191, 7943, 7691, 7438, 7182, 6924, 6663, 6401, 6137, 5871, 5603, 5334, 5062, 4790, 4516, 4240, 3963, 3685, 3406, 3126, 2845, 2563, 2280, 1996, 1712, 1427, 1142, 857, 571, 285, 0
};
static long proj_nodes[NODECOUNT][2]; // projected nodes (x,y)
//static int old_nodes[NODECOUNT][2]; // projected nodes of previous frame to check if we need to redraw
static long i;
static int loops;
static double next_tick;
static double last_btn; // used for checking when the button was last pushed
// ----------------------------------------------
// SIN/COS from 90 degrees LUT
// ----------------------------------------------
long SIN(unsigned int angle) {
angle += 90;
if (angle > 450) return LUT(0);
if (angle > 360 && angle < 451) return -LUT(angle - 360);
if (angle > 270 && angle < 361) return -LUT(360 - angle);
if (angle > 180 && angle < 271) return LUT(angle - 180);
return LUT(180 - angle);
}
long COS(unsigned int angle) {
if (angle > 360) return LUT(0);
if (angle > 270 && angle < 361) return LUT(360 - angle);
if (angle > 180 && angle < 271) return -LUT(angle - 180);
if (angle > 90 && angle < 181) return -LUT(180 - angle);
return LUT(angle);
}
// ----------------------------------------------
// Matrix operation
// ----------------------------------------------
Matrix4 mMultiply(const Matrix4 &mat1, const Matrix4 &mat2) {
Matrix4 mat;
unsigned char r, c;
for (c = 0; c < 4; c++)
for (r = 0; r < 4; r++)
mat.m[c][r] = pMultiply(mat1.m[0][r], mat2.m[c][0]) +
pMultiply(mat1.m[1][r], mat2.m[c][1]) +
pMultiply(mat1.m[2][r], mat2.m[c][2]) +
pMultiply(mat1.m[3][r], mat2.m[c][3]);
return mat;
}
Matrix4 mRotateX(const unsigned int angle) {
Matrix4 mat;
mat.m[1][1] = COS(angle);
mat.m[1][2] = SIN(angle);
mat.m[2][1] = -SIN(angle);
mat.m[2][2] = COS(angle);
return mat;
}
Matrix4 mRotateY(const unsigned int angle) {
Matrix4 mat;
mat.m[0][0] = COS(angle);
mat.m[0][2] = -SIN(angle);
mat.m[2][0] = SIN(angle);
mat.m[2][2] = COS(angle);
return mat;
}
Matrix4 mRotateZ(const unsigned int angle) {
Matrix4 mat;
mat.m[0][0] = COS(angle);
mat.m[0][1] = SIN(angle);
mat.m[1][0] = -SIN(angle);
mat.m[1][1] = COS(angle);
return mat;
}
Matrix4 mTranslate(const long x, const long y, const long z) {
Matrix4 mat;
mat.m[3][0] = x << PSHIFT;
mat.m[3][1] = y << PSHIFT;
mat.m[3][2] = z << PSHIFT;
return mat;
}
Matrix4 mScale(const float ratio) {
Matrix4 mat;
mat.m[0][0] *= ratio;
mat.m[1][1] *= ratio;
mat.m[2][2] *= ratio;
return mat;
}
// ----------------------------------------------
// Shoelace algorithm to get the surface
// ----------------------------------------------
int shoelace(const int (*n)[2], const unsigned short int index) {
unsigned short int t = 0;
int surface = 0;
for (; t < 3; t++) {
// (x1y2 - y1x2) + (x2y3 - y2x3) ...
surface += (n[EDGE(index, t)][0] * n[EDGE(index, (t < 2 ? t + 1 : 0))][1]) -
(n[EDGE(index, (t < 2 ? t + 1 : 0))][0] * n[EDGE(index, t)][1]);
}
return surface * 0.5;
}
// ----------------------------------------------
// Shoelace algorithm for triangle visibility
// ----------------------------------------------
bool is_hidden(const int (*n)[2], const unsigned short int index) {
// (x1y2 - y1x2) + (x2y3 - y2x3) ...
return ( ( (n[EDGE(index, 0)][0] * n[EDGE(index, 1)][1]) -
(n[EDGE(index, 1)][0] * n[EDGE(index, 0)][1]) ) +
( (n[EDGE(index, 1)][0] * n[EDGE(index, 2)][1]) -
(n[EDGE(index, 2)][0] * n[EDGE(index, 1)][1]) ) +
( (n[EDGE(index, 2)][0] * n[EDGE(index, 0)][1]) -
(n[EDGE(index, 0)][0] * n[EDGE(index, 2)][1]) ) ) < 0 ? false : true;
}
// ----------------------------------------------
// draw projected nodes
// ----------------------------------------------
void draw_vertex(const int (*n)[2]) {
i = NODECOUNT - 1;
do {
display.drawPixel(n[i][0], n[i][1], WHITE);
} while (i--);
}
// ----------------------------------------------
// draw edges between projected nodes
// ----------------------------------------------
void draw_wireframe(const long (*n)[2]) {
i = TRICOUNT - 1;
int NR1 = 0;
int NR2 = 1;
do {
display.setCursor(0, 0);
display.fillRect(0, 0, 32, 32, BLACK);
display.print(i);
display.setCursor(0, 8);
display.print(NR2);
display.setCursor(0, 16);
display.print(n[EDGE(i, 0)][0]);
display.print(":");
display.print(n[EDGE(i, 0)][1]);
display.setCursor(0, 24);
display.print(n[EDGE(i, 1)][0]);
display.print(":");
display.print(n[EDGE(i, 1)][1]);
// don't draw triangle with negative surface value
//if (!is_hidden(n, i)) {
// draw triangle edges - 0 -> 1 -> 2 -> 0
display.drawLine(n[EDGE(i, 0)][0], n[EDGE(i, 0)][1], n[EDGE(i, 1)][0], n[EDGE(i, 1)][1], WHITE);
display.drawLine(n[EDGE(i, 1)][0], n[EDGE(i, 1)][1], n[EDGE(i, 2)][0], n[EDGE(i, 2)][1], WHITE);
display.drawLine(n[EDGE(i, 2)][0], n[EDGE(i, 2)][1], n[EDGE(i, 0)][0], n[EDGE(i, 0)][1], WHITE);
//}
NR1++;
NR2++;
if (NR1 >= 255)
{
NR1 = 0;
display.clearDisplay();
}
display.display();
} while (i--);
delay(3000);
}
// ----------------------------------------------
// write current drawing mode in corner of screen
// ----------------------------------------------
void draw_print(unsigned short int wert) {
display.setCursor(0, 0);
//display.println(F(" wireframe"));
//display.print(F(" triangles: "));
//display.println(TRICOUNT);
display.fillRect(0, 0, 23, 7, BLACK);
display.print(wert);
}
// ----------------------------------------------
// setup
// ----------------------------------------------
void setup() {
// initialize screen
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.setTextColor(WHITE);
display.setTextSize(1);
display.display();
display.clearDisplay();
// print draw type on screen
//draw_print();
// init tick
next_tick = last_btn = millis();
}
// ----------------------------------------------
// main loop
// ----------------------------------------------
void loop() {
loops = 0;
//while ( millis() > next_tick && loops < MAX_FRAMESKIP) {
// rotation
m_world = mRotateX(mesh_rotation.x);
m_world = mMultiply(mRotateY(mesh_rotation.y), m_world);
m_world = mMultiply(mRotateZ(mesh_rotation.z), m_world);
// scaling
//m_world = mMultiply(mScale(1.5), m_world);
// project nodes with world matrix
Vector3i p;
for (i = 0; i < NODECOUNT; i++) {
p.x = (m_world.m[0][0] * (NODE(i, 0) >> PSHIFT) +
m_world.m[1][0] * (NODE(i, 1) >> PSHIFT) +
m_world.m[2][0] * (NODE(i, 2) >> PSHIFT) +
m_world.m[3][0]) / PRES;
p.y = (m_world.m[0][1] * (NODE(i, 0) >> PSHIFT) +
m_world.m[1][1] * (NODE(i, 1) >> PSHIFT) +
m_world.m[2][1] * (NODE(i, 2) >> PSHIFT) +
m_world.m[3][1]) / PRES;
p.z = (m_world.m[0][2] * (NODE(i, 0) >> PSHIFT) +
m_world.m[1][2] * (NODE(i, 1) >> PSHIFT) +
m_world.m[2][2] * (NODE(i, 2) >> PSHIFT) +
m_world.m[3][2]) / PRES;
// store projected node
proj_nodes[i][0] = (FOV * p.x) / (FOV + p.z) + HALFW;
proj_nodes[i][1] = (FOV * p.y) / (FOV + p.z) + HALFH;
}
// default auto-rotation mode
//mesh_rotation.x += 3; // |
//mesh_rotation.y += 2; // -
//mesh_rotation.z++; // O
if (mesh_rotation.x > 360) mesh_rotation.x = 0;
if (mesh_rotation.y > 360) mesh_rotation.y = 0;
if (mesh_rotation.z > 360) mesh_rotation.z = 0;
next_tick += SKIP_TICKS;
loops++;
//}
//DRAW
display.clearDisplay();
draw_wireframe(proj_nodes);
//draw_vertex(proj_nodes);
display.display();
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.