Dear visitors and members, with the staff having moved on to other life interests and as a result of changes in people's internet usage habits, the CodeWalrus community have migrated almost entirely to Discord, IRC and WalrusIRC and is now essentially a place where to hang out, chat about gaming, programming, music, anime, and chill. As a result, even though the CW forums will remain open for posting, for faster TI, Casio or HP calculator help and news we recommend using the bilingual TI-Planet forums instead.

### WalrusIRC

You need to have 5 posts and not be part of restricted usergroups in order to use the WalrusIRC embedded shoutbox. However, you can also access our IRC channel called #CodeWalrus via EFnet.

### Author Topic: Graphics and other system routines  (Read 13353 times)

0 Members and 1 Guest are viewing this topic.

#### DarkestEx

• Super User
• Join Date: Jan 2015
• Location: Germany
• Posts: 1327
• Post Rating Ratio: +10/-2
• Gender:
##### Graphics and other system routines
« on: October 19, 2015, 10:31:05 pm »
Hello, in this topic you can suggest and vote for graphics and drawing routines that I we will use in he official API and system.

To start, I want to have some sprite routines, but I can't get them to work:
Code: [Select]
`void oled_bdraws(int16_t x, int16_t y, uint8_t width, uint8_t height, const uint8_t bitmap[]) { uint8_t ow = width; if(width + x > BUFFER_WIDTH) width -= width + x - BUFFER_WIDTH; if(height + y > BUFFER_HEIGHT) height -= height + y - BUFFER_HEIGHT; if(width + x <= 0 || height + y <= 0) return; for(int yi = y; yi < (y + height); yi++) { for(int xi = x; xi < (x + width); xi++) { if((yi - y) < 0 || (xi - x) < 0) continue; if(bitmap[(yi - y) * ow + (xi - x)] > 0) screen_buffer[yi * ow + xi] = bitmap[(yi - y) * ow + (xi - x)]; } }}`
The language for all routines should be C, but many other languages can be ported pretty easily I guess.
There is one framebuffer called screen_buffer[128*128]. It is using a palette. If you want to make your own functions, just make them take inputs (coordiantes, colors, etc.) and let them write to screen_buffer. The color 0x00 is transparent when drawn.

• Calculators owned: TI-84+, Casio 101-S, RPN-Calc, Hewlett-Packard 100LX, Hewlett-Packard 95LX
• Consoles, mobile devices and vintage computers owned: Hewlett-Packard 100LX, Hewlett-Packard 95LX, Original Commodore 64C, Tektronix AWG2021, IBM X60s, IBM X60t, Nintendo DS Lite, Nintendo GameBoy Color, Nintendo GameCube, Xbox 360, Palm m5

#### c4ooo

• Pedanticity prevents ambiguity
• Super User
• CW Contest II Winner
• Join Date: Aug 2015
• Location: 127.0.0.1
• Posts: 1028
• Post Rating Ratio: +13/-4
• Gender:
##### Re: Graphics and other system routines
« Reply #1 on: October 20, 2015, 12:33:07 am »
Here is an optimized circle drawing routine in java:
Code: [Select]
`    public void drawCircle(int x, int y, int r) {        double angle, x1, y1;        for (angle = 0; angle < 90; angle += 0.1) {            x1 = r * Math.cos(angle * Math.PI / 180);            y1 = r * Math.sin(angle * Math.PI / 180);            setPixel((int) (x + x1), (int) (y + y1)); //bottom left            setPixel((int) (x + x1), (int) (y - y1)); //top left            setPixel((int) (x - x1), (int) (y + y1)); //nottom right            setPixel((int) (x - x1), (int) (y - y1)); // top right        }    }`I dont really know how you handle doubles/floats in c

setPixer is self explanatory:
Code: [Select]
`    public void setPixel(int x, int y) {        if (x >= 0 && x < width && y >= 0 && y < height) {            pixels[x + width * y] = color;        }    }`
Drawing filled circles is a bit more tricky:

Code: [Select]
`    public void drawFillCircle(int x, int y, int r) {        double angle, x1, y1;        for (angle = 0; angle < 90; angle += 0.1) {            x1 = r * Math.cos(angle * Math.PI / 180);            y1 = r * Math.sin(angle * Math.PI / 180);            setPixel((int) (x + x1), (int) (y + y1)); //bottom left            setPixel((int) (x - x1), (int) (y + y1)); //nottom right            for (double i = x - x1; i <= x + x1; i++) {                setPixel((int) i, (int) (y + y1));                setPixel((int) i, (int) (y - y1));            }        }    }`
Hope it helps you in some way

#### semiprocoder

• Full User
• Join Date: May 2015
• Location:
• Posts: 282
• Post Rating Ratio: +2/-0
• Gender:
##### Re: Graphics and other system routines
« Reply #2 on: October 20, 2015, 01:31:12 am »
Since graphics has extensive trig, have an index of already done trig values so that you don't have to always do the trig. For more accuracy you would obiously need to use full trig, but I think you could do angle vals 1-90 or something without wasting too much ram, like have a 360 b devoted to trig index, and a bit more to arc values
• Calculators owned: ti nspire, ti 84 plus se

#### c4ooo

• Pedanticity prevents ambiguity
• Super User
• CW Contest II Winner
• Join Date: Aug 2015
• Location: 127.0.0.1
• Posts: 1028
• Post Rating Ratio: +13/-4
• Gender:
##### Re: Graphics and other system routines
« Reply #3 on: October 20, 2015, 01:43:05 am »
There will be no accuracy increase from using 1-360, just a speed decrease. Basicly all i need to do is calculate a quarter slice of the circle, then flip the values over the center to get the rest.

#### semiprocoder

• Full User
• Join Date: May 2015
• Location:
• Posts: 282
• Post Rating Ratio: +2/-0
• Gender:
##### Re: Graphics and other system routines
« Reply #4 on: October 20, 2015, 01:57:32 am »
Yeah thats why I was saying 1-90 instead of 1-360

The 360 was 90*4(for num bytes in a float)=360
« Last Edit: October 20, 2015, 03:22:15 am by semiprocoder »
• Calculators owned: ti nspire, ti 84 plus se

#### DarkestEx

• Super User
• Join Date: Jan 2015
• Location: Germany
• Posts: 1327
• Post Rating Ratio: +10/-2
• Gender:
##### Re: Graphics and other system routines
« Reply #5 on: October 20, 2015, 09:14:52 am »
Oh that's awesome
I can't wait implement them all.
I am glad for any help with the graphics functions. As you all obviously know, the quality and speed of them massively affect all games that come out for the platform

I really hope that more functions will follow. Especially from the calculator community who managed writing well working and fast, integer based graphics functions.
« Last Edit: October 20, 2015, 09:16:33 am by DarkestEx »
• Calculators owned: TI-84+, Casio 101-S, RPN-Calc, Hewlett-Packard 100LX, Hewlett-Packard 95LX
• Consoles, mobile devices and vintage computers owned: Hewlett-Packard 100LX, Hewlett-Packard 95LX, Original Commodore 64C, Tektronix AWG2021, IBM X60s, IBM X60t, Nintendo DS Lite, Nintendo GameBoy Color, Nintendo GameCube, Xbox 360, Palm m5

#### c4ooo

• Pedanticity prevents ambiguity
• Super User
• CW Contest II Winner
• Join Date: Aug 2015
• Location: 127.0.0.1
• Posts: 1028
• Post Rating Ratio: +13/-4
• Gender:
##### Re: Graphics and other system routines
« Reply #6 on: October 20, 2015, 10:35:19 am »
Yeah thats why I was saying 1-90 instead of 1-360

The 360 was 90*4(for num bytes in a float)=360
Whoops i completely revered the meaning of your post
*facepalm*

Any how, although they definatly work, they might be optimizable. It has been a long time since i looked at that code.

#### Streetwalrus

• Super User
• Original 5
• Join Date: Nov 2014
• Location:
• Posts: 2903
• Post Rating Ratio: +20/-0
##### Re: Graphics and other system routines
« Reply #7 on: October 20, 2015, 10:54:26 am »
As DarkestEx said, integer routines will be favored as the hardware does not support floating point (which has to be emulated in software) so integer or fixed point math is going to be faster.

#### semiprocoder

• Full User
• Join Date: May 2015
• Location:
• Posts: 282
• Post Rating Ratio: +2/-0
• Gender:
##### Re: Graphics and other system routines
« Reply #8 on: October 20, 2015, 11:53:05 am »
maybe then just have cos*100, estimated to an int, or something returned and ten you just manually divide later?

edit: maybe cos*128, so that to divide you just bit shift some places to the right(for any power of two, 128 may not be accurate enough, idk), which is faster.
« Last Edit: October 20, 2015, 12:08:43 pm by semiprocoder »
• Calculators owned: ti nspire, ti 84 plus se

#### Snektron

• Lvl 69 Russian Snake
• Super User
• Join Date: Dec 2014
• Location: Netherlands
• Posts: 3165
• Post Rating Ratio: +32/-0
• SSSssssss.....
• Gender:
##### Re: Graphics and other system routines
« Reply #9 on: October 20, 2015, 01:13:05 pm »
• Calculators owned: TI-84+
Legends say if you spam more than DJ Omnimaga, you will become a walrus...

#### semiprocoder

• Full User
• Join Date: May 2015
• Location:
• Posts: 282
• Post Rating Ratio: +2/-0
• Gender:
##### Re: Graphics and other system routines
« Reply #10 on: October 20, 2015, 04:28:47 pm »
Yay! Triangles are awesome! Unfortunately many simple graphics apis don't let you use them, like ti nspire lua. It would be amazing if the microcat api had triangles.

Also, I made a fast sin/cos/tan generating program. It doesnt give you the sin value, but forces you to input a value and have it multiplied by the sin, because otherwise it would be annoying to deal with. I have not tested my code yet and don't have time to right now, but here it is:
Code: [Select]
`#ifdef _MSC_VER#define _CRT_SECURE_NO_WARNINGS#endif#include <math.h>#include <stdio.h>#include <stdlib.h>using namespace std;# define PI 3.14159265358979323846void writeSines() { FILE *myfile; if ((myfile = fopen("C:\\Users\\Andrew\\vs\\sines\\sinesBYTE.txt", "w")) == NULL) { printf("didnt open"); return; } unsigned char tempSin; for (double i = 1.0; i <= 90.0; i += 1.0) { tempSin = (unsigned char)(sin(i / 180.0*PI) * 256); fprintf(myfile, "%d, ", tempSin); double tempcheck = tempSin; } fclose(myfile);}//generated using writeSines(). doesnt include sin(90) because sin(90)*256=256>255, max for byte/unsigned char, so it wraps around to 0, which is pointlessunsigned char sinArray[90] = {0, 4, 8, 13, 17, 22, 26, 31, 35, 40, 44, 48, 53, 57, 61, 66, 70, 74, 79, 83, 87, 91, 95, 100, 104, 108, 112, 116, 120, 124, 127, 131, 135, 139, 143, 146, 150, 154, 157, 161, 164, 167, 171, 174, 177, 181, 184, 187, 190, 193, 196, 198, 201, 204, 207, 209, 212, 214, 217, 219, 221, 223, 226, 228, 230, 232, 233, 235, 237, 238, 240, 242, 243, 244, 246, 247, 248, 249, 250, 251, 252, 252, 253, 254, 254, 255, 255, 255, 255, 255};void fastSinMult(int *val, int degree) { if (degree == 90) { return; } else if (degree < 90 && degree>=0) { *val = (*val)*sinArray[degree+1]; (*val) = (*val) >> 8; return; } else if (degree > 90 && degree <= 180) { fastSinMult(val, 180 - degree); return; } else if (degree > 180 && degree <= 360) { fastSinMult(val, degree - 180); (*val) *= -1; return; } else if (degree > 360)//not allowing negative degrees for now fastSinMult(val, degree % 360);}void fastCosMult(int *val, int degree) { fastSinMult(val, degree - 90);}void fastTanMult(int *val, int angle) { int val1 = *val; int val2 = *val; fastSinMult(&val1, angle); fastCosMult(&val2, angle); (*val) = val1 / val2;}`
• Calculators owned: ti nspire, ti 84 plus se

#### DarkestEx

• Super User
• Join Date: Jan 2015
• Location: Germany
• Posts: 1327
• Post Rating Ratio: +10/-2
• Gender:
##### Re: Graphics and other system routines
« Reply #11 on: October 20, 2015, 04:35:12 pm »
Yay! Triangles are awesome! Unfortunately many simple graphics apis don't let you use them, like ti nspire lua. It would be amazing if the microcat api had triangles.

Also, I made a fast sin/cos/tan generating program. It doesnt give you the sin value, but forces you to input a value and have it multiplied by the sin, because otherwise it would be annoying to deal with. I have not tested my code yet and don't have time to right now, but here it is:
Code: [Select]
`#ifdef _MSC_VER#define _CRT_SECURE_NO_WARNINGS#endif#include <math.h>#include <stdio.h>#include <stdlib.h>using namespace std;# define PI 3.14159265358979323846void writeSines() { FILE *myfile; if ((myfile = fopen("C:\\Users\\Andrew\\vs\\sines\\sinesBYTE.txt", "w")) == NULL) { printf("didnt open"); return; } unsigned char tempSin; for (double i = 1.0; i <= 90.0; i += 1.0) { tempSin = (unsigned char)(sin(i / 180.0*PI) * 256); fprintf(myfile, "%d, ", tempSin); double tempcheck = tempSin; } fclose(myfile);}//generated using writeSines(). doesnt include sin(90) because sin(90)*256=256>255, max for byte/unsigned char, so it wraps around to 0, which is pointlessunsigned char sinArray[90] = {0, 4, 8, 13, 17, 22, 26, 31, 35, 40, 44, 48, 53, 57, 61, 66, 70, 74, 79, 83, 87, 91, 95, 100, 104, 108, 112, 116, 120, 124, 127, 131, 135, 139, 143, 146, 150, 154, 157, 161, 164, 167, 171, 174, 177, 181, 184, 187, 190, 193, 196, 198, 201, 204, 207, 209, 212, 214, 217, 219, 221, 223, 226, 228, 230, 232, 233, 235, 237, 238, 240, 242, 243, 244, 246, 247, 248, 249, 250, 251, 252, 252, 253, 254, 254, 255, 255, 255, 255, 255};void fastSinMult(int *val, int degree) { if (degree == 90) { return; } else if (degree < 90 && degree>=0) { *val = (*val)*sinArray[degree+1]; (*val) = (*val) >> 8; return; } else if (degree > 90 && degree <= 180) { fastSinMult(val, 180 - degree); return; } else if (degree > 180 && degree <= 360) { fastSinMult(val, degree - 180); (*val) *= -1; return; } else if (degree > 360)//not allowing negative degrees for now fastSinMult(val, degree % 360);}void fastCosMult(int *val, int degree) { fastSinMult(val, degree - 90);}void fastTanMult(int *val, int angle) { int val1 = *val; int val2 = *val; fastSinMult(&val1, angle); fastCosMult(&val2, angle); (*val) = val1 / val2;}`
Thank you
As you were so kind and provided the functions, I will absolutely implement them
Especially the Sin tables are pretty useful.

I'll add you all to the special thanks list obviously for all your great code
« Last Edit: October 20, 2015, 05:00:42 pm by DarkestEx »
• Calculators owned: TI-84+, Casio 101-S, RPN-Calc, Hewlett-Packard 100LX, Hewlett-Packard 95LX
• Consoles, mobile devices and vintage computers owned: Hewlett-Packard 100LX, Hewlett-Packard 95LX, Original Commodore 64C, Tektronix AWG2021, IBM X60s, IBM X60t, Nintendo DS Lite, Nintendo GameBoy Color, Nintendo GameCube, Xbox 360, Palm m5

#### Snektron

• Lvl 69 Russian Snake
• Super User
• Join Date: Dec 2014
• Location: Netherlands
• Posts: 3165
• Post Rating Ratio: +32/-0
• SSSssssss.....
• Gender:
##### Re: Graphics and other system routines
« Reply #12 on: October 20, 2015, 04:57:13 pm »
Code: [Select]
` public void circle(int cx, int cy, int r) { int f = 1-r; int ddFx = 1; int ddFy = -2*r; int x = 0; int y = r; setPixel(cx, cy+r); setPixel(cx, cy-r); setPixel(cx+r, cy); setPixel(cx-r, cy); while (x < y) { if (f>=0) { y--; ddFy += 2; f += ddFy; } x++; ddFx += 2; f += ddFx; setPixel(cx + x, cy + y); setPixel(cx - x, cy + y); setPixel(cx + x, cy - y); setPixel(cx - x, cy - y); setPixel(cx + y, cy + x); setPixel(cx - y, cy + x); setPixel(cx + y, cy - x); setPixel(cx - y, cy - x); } }`
Here's a sine/cosineless circle algoritm in java (midpoint circle/bresenham). Also you might want to thin about adding translations, since they;re really usefull.

EDIT: i've altered the circle algoritm for a filled circle
Code: [Select]
` public void fcircle(int cx, int cy, int r) { int f = 1-r; int ddFx = 1; int ddFy = -2*r; int x = 0; int y = r; for (int fr=r; fr>0; fr--) { setPixel(cx, cy+fr); setPixel(cx, cy-fr); setPixel(cx+fr, cy); setPixel(cx-fr, cy); } setPixel(cx, cy); while (x < y) { if (f >= 0) { y--; ddFy += 2; f += ddFy; } x++; ddFx += 2; f += ddFx; for (int fx=x; fx>0; fx--) { setPixel(cx + fx, cy + y); setPixel(cx - fx, cy + y); setPixel(cx + fx, cy - y); setPixel(cx - fx, cy - y); } for (int fy=y; fy>0; fy--) { setPixel(cx + fy, cy + x); setPixel(cx - fy, cy + x); setPixel(cx + fy, cy - x); setPixel(cx - fy, cy - x); } } }`
« Last Edit: October 20, 2015, 05:05:52 pm by Cumred_Snektron »
• Calculators owned: TI-84+
Legends say if you spam more than DJ Omnimaga, you will become a walrus...

#### DarkestEx

• Super User
• Join Date: Jan 2015
• Location: Germany
• Posts: 1327
• Post Rating Ratio: +10/-2
• Gender:
##### Re: Graphics and other system routines
« Reply #13 on: October 20, 2015, 05:01:23 pm »
Code: [Select]
` public void circle(int cx, int cy, int r) { int f = 1-r; int ddFx = 1; int ddFy = -2*r; int x = 0; int y = r; setPixel(cx, cy+r); setPixel(cx, cy-r); setPixel(cx+r, cy); setPixel(cx-r, cy); while (x < y) { if (f>=0) { y--; ddFy += 2; f += ddFy; } x++; ddFx += 2; f += ddFx; setPixel(cx + x, cy + y); setPixel(cx - x, cy + y); setPixel(cx + x, cy - y); setPixel(cx - x, cy - y); setPixel(cx + y, cy + x); setPixel(cx - y, cy + x); setPixel(cx + y, cy - x); setPixel(cx - y, cy - x); } }`
Here's a sine/cosineless circle algoritm (midpoint circle/bresenham). Also you might want to thin about adding translations, since they;re really usefull.
Thats great, thank you!

Rounded rectangles would be useful too I guess. And if somebody has a lightweight raycaster or raytracer written in C or who could port one, I would absolutely love to have it in the graphics library. At 120MHz core speed, a raytracer or raycaster is feasible and would allow for more great games.
• Calculators owned: TI-84+, Casio 101-S, RPN-Calc, Hewlett-Packard 100LX, Hewlett-Packard 95LX
• Consoles, mobile devices and vintage computers owned: Hewlett-Packard 100LX, Hewlett-Packard 95LX, Original Commodore 64C, Tektronix AWG2021, IBM X60s, IBM X60t, Nintendo DS Lite, Nintendo GameBoy Color, Nintendo GameCube, Xbox 360, Palm m5

#### semiprocoder

• Full User
• Join Date: May 2015
• Location:
• Posts: 282
• Post Rating Ratio: +2/-0
• Gender:
##### Re: Graphics and other system routines
« Reply #14 on: October 20, 2015, 07:57:25 pm »
Just wanted to point it out, I don't know any graphics so I won't be able to help you there.

Anyways, the trig functions, namely tan don't even give near the correct value, so here are the actual functions. I also updated sin to allow negative numbers, forgot to do that. Here is the new code, without any of the testing stuff that I had before that I was going to use:
Code: [Select]
`unsigned char sinArray[90] = {0, 4, 8, 13, 17, 22, 26, 31, 35, 40, 44, 48, 53, 57, 61, 66, 70, 74, 79, 83, 87, 91, 95, 100, 104, 108, 112, 116, 120, 124, 127, 131, 135, 139, 143, 146, 150, 154, 157, 161, 164, 167, 171, 174, 177, 181, 184, 187, 190, 193, 196, 198, 201, 204, 207, 209, 212, 214, 217, 219, 221, 223, 226, 228, 230, 232, 233, 235, 237, 238, 240, 242, 243, 244, 246, 247, 248, 249, 250, 251, 252, 252, 253, 254, 254, 255, 255, 255, 255, 255};void fastSinMult(int *val, int degree) { if (degree == 90) { return; } else if (degree < 90 && degree>=0) { *val = (*val)*sinArray[degree-1]; (*val) = (*val) >> 8; return; } else if (degree > 90 && degree <= 180) { fastSinMult(val, 180 - degree); return; } else if (degree > 180 && degree <= 360) { fastSinMult(val, degree - 180); (*val) *= -1; return; } else if (degree > 360) fastSinMult(val, degree % 360); else { fastSinMult(val, -degree); (*val) = -(*val); }}void fastCosMult(int *val, int degree) { fastSinMult(val, 90-degree);}void fastTanMult(int *val, int degree) { int val1 = *val; int val2 = *val; fastSinMult(&val1, degree); fastCosMult(&val2, degree); (*val) = ((*val) * val1) / val2;}`
Also I want to do arccos, arctan, and arcsin, but I am not sure how I would do that with ints. If you have any ideas about that tell me.
Furthermore, should I make a simple vector library, like magnitude, dot product, cross product, etc. or do you already have that without floats, cause I think it would be quite easy to do.
« Last Edit: October 20, 2015, 08:16:06 pm by semiprocoder »
• Calculators owned: ti nspire, ti 84 plus se