Home
Categories
Coilguns
AVR Projects
Gumstix Projects
PIC Projects
Tutorials
The Forum
Contact Me

If you like this
site please

page counter

OLED 3-D Triangle

6/18/08
A while ago I ordered a OLED and carrier board from SparkFun. The OLED has amazing contrast. You can not tell where the screen is when it is blank. With LCD (that have backlights) when the screen is black you can still see a little light coming though. With OLED each pixel emits their own light so you get the darkest black and the brightest white.

I decided to have fun with the line function that is built into the OLED. The odd thing about the controller is it will not let you draw a line with negative slope, for example from the bottom left corner to the top right. If you attempt to do this then the line is often draw but in some random location. I got over this as all I needed for my example was horizontal lines and they work fine.

I wanted to try my luck with 3-D graphics like with the PIC but this time solid polygons. To draw solid graphics you draw a series of horizontal lines of varying lengths.

All 3-D objects using this method are made of triangles. A triangle consists of three, 3-D points. After the triangle is rotated, translated, and projected the slopes of the three lines are calculated when needed. By using the slope and a point you can find any point on the line. My code uses the formula y=mx+b to find the end points of the horizontal lines. This is all contained in the function get_lines().

The entire code and the hex file are available here.

Click a section for an explanation.
void get_lines(uint8_t poly_num)
{
float slopetb,yinttb,slopes1,yints1;
signed char topt=0,bott=0,side=0,ypt;
/* we need to first find what point is on the top*/
if (Poly_2D[poly_num][0][1]>=Poly_2D[poly_num][1][1]&&
Poly_2D[poly_num][0][1]>=Poly_2D[poly_num][2][1])
topt=0;
else
if (Poly_2D[poly_num][1][1]>=Poly_2D[poly_num][0][1]&&
Poly_2D[poly_num][1][1]>=Poly_2D[poly_num][2][1])
topt=1;
else
if (Poly_2D[poly_num][2][1]>=Poly_2D[poly_num][0][1]&&
Poly_2D[poly_num][2][1]>=Poly_2D[poly_num][1][1])
topt=2;
/* we also need to know the bottom point*/
if (Poly_2D[poly_num][0][1]<=Poly_2D[poly_num][1][1]&&
Poly_2D[poly_num][0][1]<=Poly_2D[poly_num][2][1])
bott=0;
else
if (Poly_2D[poly_num][1][1]<=Poly_2D[poly_num][0][1]&&
Poly_2D[poly_num][1][1]<=Poly_2D[poly_num][2][1])
bott=1;
else
if (Poly_2D[poly_num][2][1]<=Poly_2D[poly_num][0][1]&&
Poly_2D[poly_num][2][1]<=Poly_2D[poly_num][1][1])
bott=2;
/* the remaining point is between them and forms two sides*/
if (topt==0&&bott==1)side=2;
else if(topt==1&&bott==0)side=2;
else if(topt==1&&bott==2)side=0;
else if(topt==2&&bott==1)side=0;
else if(topt==2&&bott==0)side=1;
else if(topt==0&&bott==2)side=1;
/*is there is no vertical lines then you can calculate things normally*/
if (Poly_2D[poly_num][0][0]!=Poly_2D[poly_num][1][0]&&
Poly_2D[poly_num][0][0]!=Poly_2D[poly_num][2][0]&&
Poly_2D[poly_num][1][0]!=Poly_2D[poly_num][2][0])
{
slopetb=Poly_2D[poly_num][topt][1]-Poly_2D[poly_num][bott][1]; //slope=y1-y2/x1-x2
slopetb/=Poly_2D[poly_num][topt][0]-Poly_2D[poly_num][bott][0];
//spit into two lines for greater accuracy

yinttb=Poly_2D[poly_num][topt][1]-(slopetb*Poly_2D[poly_num][topt][0]);
//Y intersept = y-(m*x)
slopes1=Poly_2D[poly_num][topt][1]-Poly_2D[poly_num][side][1];
slopes1/=Poly_2D[poly_num][topt][0]-Poly_2D[poly_num][side][0];

yints1=Poly_2D[poly_num][topt][1]-(slopes1*Poly_2D[poly_num][topt][0]);

for (ypt=Poly_2D[poly_num][topt][1]; //from top point to middle point
ypt>=Poly_2D[poly_num][side][1];
ypt--)
{
horz_lines[line_ct][0]=(ypt-yinttb)/slopetb;
horz_lines[line_ct][1]=(ypt-yints1)/slopes1;
horz_lines[line_ct][2]=ypt;
line_ct++;
}
slopes1=Poly_2D[poly_num][side][1]-Poly_2D[poly_num][bott][1];
slopes1/=Poly_2D[poly_num][side][0]-Poly_2D[poly_num][bott][0];
//calculate the slope for the bottom side
yints1=Poly_2D[poly_num][side][1]-(slopes1*Poly_2D[poly_num][side][0]);

for (ypt=Poly_2D[poly_num][side][1];
ypt>=Poly_2D[poly_num][bott][1];
ypt--)
{
horz_lines[line_ct][0]=(ypt-yinttb)/slopetb;
horz_lines[line_ct][1]=(ypt-yints1)/slopes1;
horz_lines[line_ct][2]=ypt;
line_ct++;
}
}else//if the top point and the middle point are vertical
if (Poly_2D[poly_num][topt][0]==Poly_2D[poly_num][side][0]){
slopetb=Poly_2D[poly_num][topt][1]-Poly_2D[poly_num][bott][1];
slopetb/=Poly_2D[poly_num][topt][0]-Poly_2D[poly_num][bott][0];
yinttb=Poly_2D[poly_num][topt][1]-(slopetb*Poly_2D[poly_num][topt][0]);

for (ypt=Poly_2D[poly_num][topt][1];
ypt>=Poly_2D[poly_num][side][1];
ypt--)
{
horz_lines[line_ct][0]=(ypt-yinttb)/slopetb;
horz_lines[line_ct][1]=Poly_2D[poly_num][side][0];
horz_lines[line_ct][2]=ypt;
line_ct++;
}
slopes1=Poly_2D[poly_num][side][1]-Poly_2D[poly_num][bott][1];
slopes1/=Poly_2D[poly_num][side][0]-Poly_2D[poly_num][bott][0];

yints1=Poly_2D[poly_num][side][1]-(slopes1*Poly_2D[poly_num][side][0]);
//use a constant x value
for (ypt=Poly_2D[poly_num][side][1];
ypt>=Poly_2D[poly_num][bott][1];
ypt--)
{
horz_lines[line_ct][0]=(ypt-yinttb)/slopetb;
horz_lines[line_ct][1]=(ypt-yints1)/slopes1;
horz_lines[line_ct][2]=ypt;
line_ct++;
}//second fill is normal
}else//if the top and bottom points for a vertical line
if (Poly_2D[poly_num][topt][0]==Poly_2D[poly_num][bott][0]){
slopes1=Poly_2D[poly_num][topt][1]-Poly_2D[poly_num][side][1];
slopes1/=Poly_2D[poly_num][topt][0]-Poly_2D[poly_num][side][0];
yints1=Poly_2D[poly_num][topt][1]-(slopes1*Poly_2D[poly_num][topt][0]);

for (ypt=Poly_2D[poly_num][topt][1];
ypt>=Poly_2D[poly_num][side][1];
ypt--)
{
horz_lines[line_ct][0]=Poly_2D[poly_num][topt][0];
horz_lines[line_ct][1]=(ypt-yints1)/slopes1;
horz_lines[line_ct][2]=ypt;
line_ct++;
}//use constant for that line
slopes1=Poly_2D[poly_num][side][1]-Poly_2D[poly_num][bott][1];
slopes1/=Poly_2D[poly_num][side][0]-Poly_2D[poly_num][bott][0];

yints1=Poly_2D[poly_num][side][1]-(slopes1*Poly_2D[poly_num][side][0]);

for (ypt=Poly_2D[poly_num][side][1];
ypt>=Poly_2D[poly_num][bott][1];
ypt--)
{
horz_lines[line_ct][0]=Poly_2D[poly_num][topt][0];
horz_lines[line_ct][1]=(ypt-yints1)/slopes1;
horz_lines[line_ct][2]=ypt;
line_ct++;
}
}else//if the middle and bottom points are vertical
if (Poly_2D[poly_num][side][0]==Poly_2D[poly_num][bott][0]){
slopetb=Poly_2D[poly_num][topt][1]-Poly_2D[poly_num][bott][1];
slopetb/=Poly_2D[poly_num][topt][0]-Poly_2D[poly_num][bott][0];
yinttb=Poly_2D[poly_num][topt][1]-(slopetb*Poly_2D[poly_num][topt][0]);
slopes1=Poly_2D[poly_num][topt][1]-Poly_2D[poly_num][side][1];
slopes1/=Poly_2D[poly_num][topt][0]-Poly_2D[poly_num][side][0];
yints1=Poly_2D[poly_num][topt][1]-(slopetb*Poly_2D[poly_num][topt][0]);

for (ypt=Poly_2D[poly_num][topt][1];
ypt>=Poly_2D[poly_num][side][1];
ypt--)
{
horz_lines[line_ct][0]=(ypt-yinttb)/slopetb;
horz_lines[line_ct][1]=(ypt-yints1)/slopes1;
horz_lines[line_ct][2]=ypt;
line_ct++;
}

for (ypt=Poly_2D[poly_num][side][1];
ypt>=Poly_2D[poly_num][bott][1];
ypt--)
{
horz_lines[line_ct][0]=(ypt-yinttb)/slopetb;
horz_lines[line_ct][1]=Poly_2D[poly_num][side][0];
horz_lines[line_ct][2]=ypt;
line_ct++;
}
}
}