You can help CodeWalrus stay online by donating here. | New CodeWalrus | Old (dark mode) | Old (light) | Discord server

Graphics and other system routines

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

0
b/[Inactive] Ninjabyte Electronics (hardware) publicado por u/DarkestEx 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:
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.
Inicia sesión o crea una cuenta para dejar un comentario
u/c4ooo October 20, 2015, 12:33:07 AM
Here is an optimized circle drawing routine in java:

    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 :P

setPixer is self explanatory:

    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:



    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 ;)
u/semiprocoder 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
u/c4ooo 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. ;)
u/semiprocoder October 20, 2015, 01:57:32 AM
Yeah thats why I was saying 1-90 instead of 1-360  :P

The 360 was 90*4(for num bytes in a float)=360
Last Edit: October 20, 2015, 03:22:15 AM by semiprocoder
u/DarkestEx 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
u/c4ooo October 20, 2015, 10:35:19 AM
Quote from: semiprocoder on October 20, 2015, 01:57:32 AM
Yeah thats why I was saying 1-90 instead of 1-360  :P

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

Any how, although they definatly work, they might be optimizable. It has been a long time since i looked at that code.
u/novenary 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.
u/semiprocoder 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
u/semiprocoder 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:

#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
# define PI 3.14159265358979323846
void 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 pointless
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)//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;
}
u/DarkestEx October 20, 2015, 04:35:12 PM
Quote from: semiprocoder 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:

#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
# define PI 3.14159265358979323846
void 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 pointless
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)//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
u/Snektron October 20, 2015, 04:57:13 PM

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

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
u/DarkestEx October 20, 2015, 05:01:23 PM
Quote from: Cumred_Snektron on October 20, 2015, 04:57:13 PM

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.
u/semiprocoder 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:

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
Start a Discussion

b/[Inactive] Ninjabyte Electronics (hardware)

Official board about Ninjabyte hardware projects, such as their Z80 computer.

10
Topics
Explore Board
Website statistics


MyCalcs | Ticalc.org | Cemetech | Omnimaga | TI-Basic Developer | MaxCoderz | TI-Story | Casiocalc.org | Casiopeia | The Museum of HP Calculators | HPCalc.org | CnCalc.org | Music 2000 Community | TI Education | Casio Education | HP Calcs | NumWorks | SwissMicros | Sharp Calculators
Powered by EzPortal