CodeWalrus

Featured Member Projects => Completed and Inactive Projects => [Inactive] Ninjabyte Electronics (hardware) => Topic started by: DarkestEx on October 19, 2015, 10:31:05 PM

Title: Graphics and other system routines
Post by: DarkestEx 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:
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.
Title: Re: Graphics and other system routines
Post by: c4ooo on 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 ;)
Title: Re: Graphics and other system routines
Post by: semiprocoder 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
Title: Re: Graphics and other system routines
Post by: c4ooo 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. ;)
(http://imgur.com/VRhuyKi.png)
Title: Re: Graphics and other system routines
Post by: 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
Title: Re: Graphics and other system routines
Post by: DarkestEx 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.
Title: Re: Graphics and other system routines
Post by: c4ooo on 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.
Title: Re: Graphics and other system routines
Post by: novenary 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.
Title: Re: Graphics and other system routines
Post by: semiprocoder 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.
Title: Re: Graphics and other system routines
Post by: Snektron on October 20, 2015, 01:13:05 PM
this site explains how triangle rasterization works :)
http://www.sunshine2k.de/coding/java/TriangleRasterization/TriangleRasterization.html
Title: Re: Graphics and other system routines
Post by: 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;
}
Title: Re: Graphics and other system routines
Post by: DarkestEx on 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 :)
Title: Re: Graphics and other system routines
Post by: 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 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);
}
}
}
Title: Re: Graphics and other system routines
Post by: DarkestEx on 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.
Title: Re: Graphics and other system routines
Post by: semiprocoder 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:

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.
Title: Re: Graphics and other system routines
Post by: DarkestEx on October 20, 2015, 07:58:58 PM
Quote from: semiprocoder 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:

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, degree - 90);
}
void fastTanMult(int *val, int angle) {
int val1 = *val;
int val2 = *val;
fastSinMult(&val1, angle);
fastCosMult(&val2, angle);
(*val) = (*val)*val1 / val2;
}

That's great! Thanks for fixing it. I will implement it now :)
Title: Re: Graphics and other system routines
Post by: Snektron on October 20, 2015, 08:00:03 PM
Btw, you can divide the circle in 8 octands, that will reduce the static data even more :)
Title: Re: Graphics and other system routines
Post by: DarkestEx on October 20, 2015, 08:02:06 PM
Quote from: Cumred_Snektron on October 20, 2015, 08:00:03 PM
Btw, you can divide the circle in 8 octands, that will reduce the static data even more :)
Interesting idea. Well I could store a lot more static values. I have half a MB of flash to use up. I will be able to fit multiple fonts too in that space, so I don't think I need to compact this more (for speed reasons too).
Title: Re: Graphics and other system routines
Post by: semiprocoder on October 20, 2015, 08:18:00 PM
Sorry again. So sorry. Even after testing I didn't really pay attention to the cos values or tan values. I modified my second post to work. I checked the outputs of all the functions, and they seem pretty good. Not perfect, obviously, and you have to be very safe with tan due to divide by 0 error.
Title: Re: Graphics and other system routines
Post by: novenary on October 20, 2015, 10:19:56 PM
Quote from: DarkestEx on October 20, 2015, 05:01:23 PM
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.
I'd see that more as a linkable library than a built in feature, it's not exactly small.
Title: Re: Graphics and other system routines
Post by: DarkestEx on October 20, 2015, 10:24:21 PM
Quote from: Streetwalrus on October 20, 2015, 10:19:56 PM
Quote from: DarkestEx on October 20, 2015, 05:01:23 PM
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.
I'd see that more as a linkable library than a built in feature, it's not exactly small.
There are really only two ways to make it happen: Not or builtin
Problems when its not builtin are either size or speed releated. So we try to include a compact raycaster.
Title: Re: Graphics and other system routines
Post by: Dream of Omnimaga on October 21, 2015, 01:14:56 AM
Would the raycaster allow people to use textures?  Otherwise if it's large then maybe it wouldn't be worth adding. On the other hand, if it supports textures and is even larger then that won't be worth it either, so I would say only add raycasting if it won't take too much space.
Title: Re: Graphics and other system routines
Post by: semiprocoder on October 21, 2015, 01:49:29 AM
Also I think that some useful graphics type things you could have would be translating and rotating the display screen.
It would go something along the lines of this:

//some global vars private to the file with them, forget what modifier specifies that so just leaving it be
int degRot;//degree rotated
int transX;//amount translated
int transY;
void setPixelTR(int x, int y){//T is translated, R is rotated. This requires floats, and I am not sure how to do it without, but maybe just mult everything by 256 like I did with fast trig, and then bit shift >>8?
    int mag=sqrt(x^2+y^2);
    int angle=acos(x/mag);
    angle+=degRot;
    setPixel(mag*cos(angle)+transX, mag*sin(angle)+transY);
}


Also I am working on arc trig functions. You input a val from 0 to 256 and get the angle correspoding to that value, similar to a converse of my fast trig. It is taking a while cause I also have to make a fast sqrt function for atan(so far I have made an extremely inaccurate one(it got sqrt 7500=82. 82*82=6724, so innacurate. It should be 86 or 87) using bit shifting, which I will use as a guess for the average one that I don't remember the name of. If the number passed to be square rooted is 16 bits or less, I use an index of 256 numbers square rooted, so it uses them. Otherwise the array would be too large.), as atan=fastACos(math.sqrt(1/(1+math.pow(val,2)))), which I calculated for my learn to fly idle game, that really didn't improve performance, but I just wanted to make it for excercise.
Title: Re: Graphics and other system routines
Post by: Snektron on October 21, 2015, 09:06:51 AM
Translation is defenitely cooll, though im not so sure about rotation. Since it requires a sqrt and an acos for every pixel it will be horribly slow...
Title: Re: Graphics and other system routines
Post by: DarkestEx on October 21, 2015, 09:15:42 AM
Quote from: DJ Omnimaga
Would the raycaster allow people to use textures?  Otherwise if it's large then maybe it wouldn't be worth adding. On the other hand, if it supports textures and is even larger then that won't be worth it either, so I would say only add raycasting if it won't take too much space.
I think that it will support textures.

Quote from: semiprocoder
Also I think that some useful graphics type things you could have would be translating and rotating the display screen.
It would go something along the lines of this:

--- Code: ---//some global vars private to the file with them, forget what modifier specifies that so just leaving it be
int degRot;//degree rotated
int transX;//amount translated
int transY;
void setPixelTR(int x, int y){//T is translated, R is rotated. This requires floats, and I am not sure how to do it without, but maybe just mult everything by 256 like I did with fast trig, and then bit shift >>8?
    int mag=sqrt(x^2+y^2);
    int angle=acos(x/mag);
    angle+=degRot;
    setPixel(mag*cos(angle)+transX, mag*sin(angle)+transY);
}

--- End code ---

Also I am working on arc trig functions. You input a val from 0 to 256 and get the angle correspoding to that value, similar to a converse of my fast trig. It is taking a while cause I also have to make a fast sqrt function for atan(so far I have made an extremely inaccurate one(it got sqrt 7500=82. 82*82=6724, so innacurate. It should be 86 or 87) using bit shifting, which I will use as a guess for the average one that I don't remember the name of. If the number passed to be square rooted is 16 bits or less, I use an index of 256 numbers square rooted, so it uses them. Otherwise the array would be too large.), as atan=fastACos(math.sqrt(1/(1+math.pow(val,2)))), which I calculated for my learn to fly idle game, that really didn't improve performance, but I just wanted to make it for excercise.
Thanks, sounds good :)

Quote from: Cumred_Snektron
Translation is defenitely cooll, though im not so sure about rotation. Since it requires a sqrt and an acos for every pixel it will be horribly slow...
I think 90° steps are enough.
Title: Re: Graphics and other system routines
Post by: adekto on October 21, 2015, 11:27:16 AM
curently looking into triangles and stumbled upon u8glibs convex polygon drawing.
i cant realy figure out how it works but it might me nice to have
this is in c++ and we need it in c. im not the best translater and not fully understanding whats going on makes it even harder
/*

  u8g_polygon.c

  Implementation of a polygon draw algorithm for "convex" polygons.

  Universal 8bit Graphics Library
 
  Copyright (c) 2013, [email protected]
  All rights reserved.

  Redistribution and use in source and binary forms, with or without modification,
  are permitted provided that the following conditions are met:

  * Redistributions of source code must retain the above copyright notice, this list
    of conditions and the following disclaimer.
   
  * Redistributions in binary form must reproduce the above copyright notice, this
    list of conditions and the following disclaimer in the documentation and/or other
    materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 

  See also:
  http://www.angelfire.com/linux/myp/ConvexPolRas/ConvexPolRas.html
  Computer Graphics, Principles and Practice, Foley, van Dam, Feiner, Hughes (pp 92)
  Michael Abrash's Graphics Programming Black Book, Special Edition (Chapter 38 and 39)

  Optimized for embedded systems
  - static memory usage only
  - consistent data types
  - low flash ROM consumption
 
*/


#include "u8g.h"




/*===========================================*/
/* procedures, which should not be inlined (save as much flash ROM as possible */

static uint8_t pge_Next(struct pg_edge_struct *pge) PG_NOINLINE;
static uint8_t pg_inc(pg_struct *pg, uint8_t i) PG_NOINLINE;
static uint8_t pg_dec(pg_struct *pg, uint8_t i) PG_NOINLINE;
static void pg_expand_min_y(pg_struct *pg, pg_word_t min_y, uint8_t pge_idx) PG_NOINLINE;
static void pg_line_init(pg_struct * const pg, uint8_t pge_index) PG_NOINLINE;

/*===========================================*/
/* line draw algorithm */

static uint8_t pge_Next(struct pg_edge_struct *pge)
{
  if ( pge->current_y >= pge->max_y )
    return 0;
 
  pge->current_x += pge->current_x_offset;
  pge->error += pge->error_offset;
  if ( pge->error > 0 )
  {
    pge->current_x += pge->x_direction;
    pge->error -= pge->height;
  } 
 
  pge->current_y++;
  return 1;
}

/* assumes y2 > y1 */
static void pge_Init(struct pg_edge_struct *pge, pg_word_t x1, pg_word_t y1, pg_word_t x2, pg_word_t y2)
{
  pg_word_t dx = x2 - x1;
  pg_word_t width;

  pge->height = y2 - y1;
  pge->max_y = y2;
  pge->current_y = y1;
  pge->current_x = x1;

  if ( dx >= 0 )
  {
    pge->x_direction = 1;
    width = dx;
    pge->error = 0;
  }
  else
  {
    pge->x_direction = -1;
    width = -dx;
    pge->error = 1 - pge->height;
  }
 
  pge->current_x_offset = dx / pge->height;
  pge->error_offset = width % pge->height;
}

/*===========================================*/
/* convex polygon algorithm */

static uint8_t pg_inc(pg_struct *pg, uint8_t i)
{
    i++;
    if ( i >= pg->cnt )
      i = 0;
    return i;
}

static uint8_t pg_dec(pg_struct *pg, uint8_t i)
{
    i--;
    if ( i >= pg->cnt )
      i = pg->cnt-1;
    return i;
}

static void pg_expand_min_y(pg_struct *pg, pg_word_t min_y, uint8_t pge_idx)
{
  uint8_t i = pg->pge[pge_idx].curr_idx;
  for(;;)
  {
    i = pg->pge[pge_idx].next_idx_fn(pg, i);
    if ( pg->list[i].y != min_y )
      break;
    pg->pge[pge_idx].curr_idx = i;
  }
}

static uint8_t pg_prepare(pg_struct *pg)
{
  pg_word_t max_y;
  pg_word_t min_y;
  uint8_t i;

  /* setup the next index procedures */
  pg->pge[PG_RIGHT].next_idx_fn = pg_inc;
  pg->pge[PG_LEFT].next_idx_fn = pg_dec;
 
  /* search for highest and lowest point */
  max_y = pg->list[0].y;
  min_y = pg->list[0].y;
  pg->pge[PG_LEFT].curr_idx = 0;
  for( i = 1; i < pg->cnt; i++ )
  {
    if ( max_y < pg->list[i].y )
    {
      max_y = pg->list[i].y;
    }
    if ( min_y > pg->list[i].y )
    {
      pg->pge[PG_LEFT].curr_idx = i;
      min_y = pg->list[i].y;
    }
  }

  /* calculate total number of scan lines */
  pg->total_scan_line_cnt = max_y;
  pg->total_scan_line_cnt -= min_y;
 
  /* exit if polygon height is zero */
  if ( pg->total_scan_line_cnt == 0 )
    return 0;
 
  /* if the minimum y side is flat, try to find the lowest and highest x points */
  pg->pge[PG_RIGHT].curr_idx = pg->pge[PG_LEFT].curr_idx; 
  pg_expand_min_y(pg, min_y, PG_RIGHT);
  pg_expand_min_y(pg, min_y, PG_LEFT);
 
  /* check if the min side is really flat (depends on the x values) */
  pg->is_min_y_not_flat = 1;
  if ( pg->list[pg->pge[PG_LEFT].curr_idx].x != pg->list[pg->pge[PG_RIGHT].curr_idx].x )
  {
    pg->is_min_y_not_flat = 0;
  }
  else
  {
    pg->total_scan_line_cnt--;
    if ( pg->total_scan_line_cnt == 0 )
      return 0;
  }

  return 1;
}

static void pg_hline(pg_struct *pg, u8g_t *u8g)
{
  pg_word_t x1, x2, y;
  x1 = pg->pge[PG_LEFT].current_x;
  x2 = pg->pge[PG_RIGHT].current_x;
  y = pg->pge[PG_RIGHT].current_y;
 
  if ( y < 0 )
    return;
  if ( y >= u8g_GetHeight(u8g) )
    return;
  if ( x1 < x2 )
  {
    if ( x2 < 0 )
      return;
    if ( x1 >= u8g_GetWidth(u8g) )
      return;
    if ( x1 < 0 )
      x1 = 0;
    if ( x2 >= u8g_GetWidth(u8g) )
      x2 = u8g_GetWidth(u8g);
    u8g_DrawHLine(u8g, x1, y, x2 - x1);
  }
  else
  {
    if ( x1 < 0 )
      return;
    if ( x2 >= u8g_GetWidth(u8g) )
      return;
    if ( x2 < 0 )
      x1 = 0;
    if ( x1 >= u8g_GetWidth(u8g) )
      x1 = u8g_GetWidth(u8g);
    u8g_DrawHLine(u8g, x2, y, x1 - x2);
  }
}

static void pg_line_init(pg_struct * pg, uint8_t pge_index)
{
  struct pg_edge_struct  *pge = pg->pge+pge_index;
  uint8_t idx; 
  pg_word_t x1;
  pg_word_t y1;
  pg_word_t x2;
  pg_word_t y2;

  idx = pge->curr_idx; 
  y1 = pg->list[idx].y;
  x1 = pg->list[idx].x;
  idx = pge->next_idx_fn(pg, idx);
  y2 = pg->list[idx].y;
  x2 = pg->list[idx].x;
  pge->curr_idx = idx;
 
  pge_Init(pge, x1, y1, x2, y2);
}

static void pg_exec(pg_struct *pg, u8g_t *u8g)
{
  pg_word_t i = pg->total_scan_line_cnt;

  /* first line is skipped if the min y line is not flat */
  pg_line_init(pg, PG_LEFT);
  pg_line_init(pg, PG_RIGHT);
 
  if ( pg->is_min_y_not_flat != 0 )
  {
    pge_Next(&(pg->pge[PG_LEFT]));
    pge_Next(&(pg->pge[PG_RIGHT]));
  }

  do
  {
    pg_hline(pg, u8g);
    while ( pge_Next(&(pg->pge[PG_LEFT])) == 0 )
    {
      pg_line_init(pg, PG_LEFT);
    }
    while ( pge_Next(&(pg->pge[PG_RIGHT])) == 0 )
    {
      pg_line_init(pg, PG_RIGHT);
    }
    i--;
  } while( i > 0 );
}

/*===========================================*/
/* API procedures */

void pg_ClearPolygonXY(pg_struct *pg)
{
  pg->cnt = 0;
}

void pg_AddPolygonXY(pg_struct *pg, u8g_t *u8g, int16_t x, int16_t y)
{
  if ( pg->cnt < PG_MAX_POINTS )
  {
    pg->list[pg->cnt].x = x;
    pg->list[pg->cnt].y = y;
    pg->cnt++;
  }
}

void pg_DrawPolygon(pg_struct *pg, u8g_t *u8g)
{
  if ( pg_prepare(pg) == 0 )
    return;
  pg_exec(pg, u8g);
}

pg_struct u8g_pg;

void u8g_ClearPolygonXY(void)
{
  pg_ClearPolygonXY(&u8g_pg);
}

void u8g_AddPolygonXY(u8g_t *u8g, int16_t x, int16_t y)
{
  pg_AddPolygonXY(&u8g_pg, u8g, x, y);
}

void u8g_DrawPolygon(u8g_t *u8g)
{
  pg_DrawPolygon(&u8g_pg, u8g);
}

void u8g_DrawTriangle(u8g_t *u8g, int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2)
{
  u8g_ClearPolygonXY();
  u8g_AddPolygonXY(u8g, x0, y0);
  u8g_AddPolygonXY(u8g, x1, y1);
  u8g_AddPolygonXY(u8g, x2, y2);
  u8g_DrawPolygon(u8g);
}



-----------

oh and we got circles filled circles and lines linetriangle in the code and working :)

Edit (Streetwalrus): merged double post.
Title: Re: Graphics and other system routines
Post by: DarkestEx on October 21, 2015, 01:30:03 PM
I really don't like the licence of the code. It requires us to include a copyright. I think its better to use the functions provided earlier in this topic.

Also I was rewriting the image converter in Java as we had way better results there.
It will have a GUI and a command line so that it's easy for beginners and powerful for people who like to include it into an automated build system like make.
Title: Re: Graphics and other system routines
Post by: novenary on October 21, 2015, 01:38:39 PM
Quote from: DarkestEx on October 21, 2015, 01:30:03 PM
I really don't like the licence of the code. It requires us to include a copyright. I think its better to use the functions provided earlier in this topic.
That's just the BSD license, the "copyright notice" is only a request for credits.
Title: Re: Graphics and other system routines
Post by: DarkestEx on October 21, 2015, 01:45:10 PM
Quote from: Streetwalrus
--- Quote from: DarkestEx on Today at 03:30:03 pm ---I really don't like the licence of the code. It requires us to include a copyright. I think its better to use the functions provided earlier in this topic.

--- End quote ---
That's just the BSD license, the "copyright notice" is only a request for credits.
Sure, but i don't like and can't include the licence into the binary image. I want to have as much of the code written by us or people interested in the project as possible. I don't like reusing others code when not required. In this case, as we have most functions that we will use provided by either the great people here, written ourselves or adapted from MIT code, I think we will just rewirite the external code.
Title: Re: Graphics and other system routines
Post by: novenary on October 21, 2015, 01:59:46 PM
The copyright notice must be distributed with the binaries. That means you can put a credits screen, have it in a readme or even on a flier that comes with the console.
Title: Re: Graphics and other system routines
Post by: DarkestEx on October 21, 2015, 02:02:01 PM
Quote from: Streetwalrus on October 21, 2015, 01:59:46 PM
The copyright notice must be distributed with the binaries. That means you can put a credits screen, have it in a readme or even on a flier that comes with the console.
Yea, still I don't want to credit them. We aren't using foreign code so far and I don't want to start it. I will just rewrite it.
Title: Re: Graphics and other system routines
Post by: Snektron on October 21, 2015, 02:35:41 PM
It would also be cool to have some kind of overridable setPixel function. That way you can make simple pixel shaders run :)
Title: Re: Graphics and other system routines
Post by: DarkestEx on October 21, 2015, 03:21:34 PM
Quote from: Cumred_Snektron on October 21, 2015, 02:35:41 PM
It would also be cool to have some kind of overridable setPixel function. That way you can make simple pixel shaders run :)
How do you mean?
Also all graphic functions are drawing directly to the buffer not using the setPixel at all for speed.
Title: Re: Graphics and other system routines
Post by: Snektron on October 21, 2015, 03:26:41 PM
Well, you can make an inline setPixel function for simplicity's sake, right? :)
Title: Re: Graphics and other system routines
Post by: adekto on October 21, 2015, 04:07:28 PM
the pixel comand is in there and used by some of my code, so you can use it
i think you can also acces the hole buffer if you want, not sure how thoug ( you prefer a getpixel or specific regions?)
Title: Re: Graphics and other system routines
Post by: Adriweb on October 21, 2015, 04:20:43 PM
Is this useful in some way? https://github.com/adriweb/BetterLuaAPI-for-TI-Nspire/blob/master/BetterLuaAPI.lua#L198-L222
(round rect routines, which I adapted from somewhere a long time ago)
Title: Re: Graphics and other system routines
Post by: Snektron on October 21, 2015, 06:09:29 PM
I've made a ploygon fill algoritm. the speed is okay i think, but it still requires a sort for every horizontal line of pixels. I've used bubble sort for now but its easily changable.


public void polygon(int... points)
{
final int accuracy = 8;

if (points.length % 2 != 0 || points.length < 6)
return;

int[] get = new int[points.length / 2 * 5];
int getn = 0;
int [] xpt = new int[points.length / 2];
int xptn;

int pymax = 0, pymin = height-1;

for (int i=0; i<points.length; i+=2)
{
int x0 = points[i];
int y0 = points[i+1];
int x1 = points[(i+2)%points.length];
int y1 = points[(i+3)%points.length];

if (y0 > y1)
{
get[getn] = y1;
get[getn+1] = y0;
get[getn+2] = (x0-x1<<accuracy)/(y0-y1); // inverse slope
get[getn+3] = x0;
get[getn+4] = x0;
getn += 5;
}else if (y0 != y1)
{
get[getn] = y0;
get[getn+1] = y1;
get[getn+2] = (x1-x0<<accuracy)/(y1-y0); // inverse slope
get[getn+3] = x1;
get[getn+4] = x0;
getn += 5;
}

pymax = Math.max(y0, pymax);
pymin = Math.min(y0, pymin);
}

for (int scan=pymin+1; scan <= pymax; scan++)
{
xptn = 0;
for (int i=0; i<getn; i+=5)
if (scan > get[i] && scan <= get[i+1])
xpt[xptn++] = ((scan - get[i+1])*get[i+2]>>accuracy) + get[i+3];

bubbleSort(xpt, xptn);

for (int i=0; i<xptn-1; i+=2)
for (int x = xpt[i]; x < xpt[i+1]; x++)
setPixel(x, scan);
}
}

public void bubbleSort(int[] array, int n)
{
    boolean swapped = true;
    int j = 0;
    int tmp;
    while (swapped)
    {
    swapped = false;
    j++;
    for (int i = 0; i < n-j; i++)
    {
    if (array[i] > array[i+1])
    {
    tmp = array[i];
    array[i] = array[i+1];
    array[i+1] = tmp;
    swapped = true;
    }
    }
    }
}


note: "int... points" is anotherway of writing "int[] points" in java. The difference is you can supply the arguments without making them an array first, ie polygon(0, 10, 10, 10, 10, 0); which is the same as polygon(new int[]{0, 10, 10, 10, 10, 0});  ;)

Since it uses ints only and a slope is a value which usually is a floating point number ive mutiplied it with a number (the accuracy constant). To save on precious cpu cycles i've used shift instead of multiply/divide
Title: Re: Graphics and other system routines
Post by: DarkestEx on October 22, 2015, 11:08:18 PM
Quote from: Cumred_Snektron on October 21, 2015, 06:09:29 PM
I've made a ploygon fill algoritm. the speed is okay i think, but it still requires a sort for every horizontal line of pixels. I've used bubble sort for now but its easily changable.


public void polygon(int... points)
{
final int accuracy = 8;

if (points.length % 2 != 0 || points.length < 6)
return;

int[] get = new int[points.length / 2 * 5];
int getn = 0;
int [] xpt = new int[points.length / 2];
int xptn;

int pymax = 0, pymin = height-1;

for (int i=0; i<points.length; i+=2)
{
int x0 = points[i];
int y0 = points[i+1];
int x1 = points[(i+2)%points.length];
int y1 = points[(i+3)%points.length];

if (y0 > y1)
{
get[getn] = y1;
get[getn+1] = y0;
get[getn+2] = (x0-x1<<accuracy)/(y0-y1); // inverse slope
get[getn+3] = x0;
get[getn+4] = x0;
getn += 5;
}else if (y0 != y1)
{
get[getn] = y0;
get[getn+1] = y1;
get[getn+2] = (x1-x0<<accuracy)/(y1-y0); // inverse slope
get[getn+3] = x1;
get[getn+4] = x0;
getn += 5;
}

pymax = Math.max(y0, pymax);
pymin = Math.min(y0, pymin);
}

for (int scan=pymin+1; scan <= pymax; scan++)
{
xptn = 0;
for (int i=0; i<getn; i+=5)
if (scan > get[i] && scan <= get[i+1])
xpt[xptn++] = ((scan - get[i+1])*get[i+2]>>accuracy) + get[i+3];

bubbleSort(xpt, xptn);

for (int i=0; i<xptn-1; i+=2)
for (int x = xpt[i]; x < xpt[i+1]; x++)
setPixel(x, scan);
}
}

public void bubbleSort(int[] array, int n)
{
    boolean swapped = true;
    int j = 0;
    int tmp;
    while (swapped)
    {
    swapped = false;
    j++;
    for (int i = 0; i < n-j; i++)
    {
    if (array[i] > array[i+1])
    {
    tmp = array[i];
    array[i] = array[i+1];
    array[i+1] = tmp;
    swapped = true;
    }
    }
    }
}


note: "int... points" is anotherway of writing "int[] points" in java. The difference is you can supply the arguments without making them an array first, ie polygon(0, 10, 10, 10, 10, 0); which is the same as polygon(new int[]{0, 10, 10, 10, 10, 0});  ;)

Since it uses ints only and a slope is a value which usually is a floating point number ive mutiplied it with a number (the accuracy constant). To save on precious cpu cycles i've used shift instead of multiply/divide
Nice :)

This is the final color palette in case somebody hasn't seen it yet:
http://docs.ninjabyte.eu/microcat/global_palette.html
Title: Re: Graphics and other system routines
Post by: Dream of Omnimaga on October 23, 2015, 06:24:13 AM
Quote from: DarkestEx on October 21, 2015, 01:45:10 PM
Quote from: Streetwalrus
--- Quote from: DarkestEx on Today at 03:30:03 pm ---I really don't like the licence of the code. It requires us to include a copyright. I think its better to use the functions provided earlier in this topic.

--- End quote ---
That's just the BSD license, the "copyright notice" is only a request for credits.
Sure, but i don't like and can't include the licence into the binary image. I want to have as much of the code written by us or people interested in the project as possible. I don't like reusing others code when not required. In this case, as we have most functions that we will use provided by either the great people here, written ourselves or adapted from MIT code, I think we will just rewirite the external code.
I think my main gripe with using code that requires copyrights like this would be the fact the readme or console is littered with watermarks. Imagine if everytime you start the console you were forced to display some splash screen with the company logo of the people who wrote the code or something (like when starting a Game Maker game)

It's fine if the only place where you are forced to put credits in is the readme or credits screen, though, since those aren't intrusive. But I guess using your own code would be better since it makes it easier to sell the console.
Title: Re: Graphics and other system routines
Post by: novenary on October 23, 2015, 06:34:38 AM
These licenses are made exactly so that you can freely reuse the code for anything. I think it's pretty fair that the author is asking for credits.
Title: Re: Graphics and other system routines
Post by: Dream of Omnimaga on October 23, 2015, 06:42:42 AM
Yeah I know. I am mostly talking about licenses that requires using anything that looks like a watermark or advertising. Imagine playing First Fantasy Microcat with ads plastered everywhere O.O
Title: Re: Graphics and other system routines
Post by: novenary on October 23, 2015, 06:44:00 AM
Lol that's abusive, no one would want to use code under such a license.
Title: Re: Graphics and other system routines
Post by: DarkestEx on October 23, 2015, 07:18:45 AM
Quote from: Streetwalrus on October 23, 2015, 06:34:38 AM
These licenses are made exactly so that you can freely reuse the code for anything. I think it's pretty fair that the author is asking for credits.
Sure but I don't want to use such code when not absolutely required.
That's my final word on this.
I really don't want to plaster my binary files with copyright notices for single functions.
Title: Re: Graphics and other system routines
Post by: semiprocoder on November 13, 2015, 12:22:13 AM
wait are you still suporting 16 bit color mode?
Also do you want a pure triangle draw code, because I could easily make one, as I made one in lua that I deleted, as it was(a bit) slower than filling polygons,at least on computer. However, it only sorts the points. Also, lua uses decimals, while I would use integers in the c code for this.
Title: Re: Graphics and other system routines
Post by: DarkestEx on November 13, 2015, 12:37:19 AM
Quote from: semiprocoder on November 13, 2015, 12:22:13 AM
wait are you still suporting 16 bit color mode?
Also do you want a pure triangle draw code, because I could easily make one, as I made one in lua that I deleted, as it was(a bit) slower than filling polygons,at least on computer. However, it only sorts the points. Also, lua uses decimals, while I would use integers in the c code for this.
No true 16 bit colors aren't supported anymore. Though you can cheat by using the 39 dynamic palette colors that you can assign any 16 bit color to. You can use these dynamic colors everywhere from sprites to all drawing functions.

About the triangle code, I would love to have yours if you post it here. I am glad about any graphic function that is useful in game making and has no requirement for floating point :)
Title: Re: Graphics and other system routines
Post by: Dream of Omnimaga on November 13, 2015, 08:27:29 AM
By the way, will there be commands to draw rectangles with customizeable opacity, within the palette limits, like on the HP Prime? That would be handy for some special effects.
Title: Re: Graphics and other system routines
Post by: novenary on November 13, 2015, 09:05:46 AM
It's not very easy to do with paletted colors. Alpha blending requires access to the raw colors.
Title: Re: Graphics and other system routines
Post by: DarkestEx on November 13, 2015, 11:15:12 AM
Quote from: DJ Omnimaga on November 13, 2015, 08:27:29 AM
By the way, will there be commands to draw rectangles with customizeable opacity, within the palette limits, like on the HP Prime? That would be handy for some special effects.
Well memory use is a big concern so we went for palettes as you know. We aren't using RGB. Sprites and the graphic functions have access to the screen buffer which is using these global palette colors.
But as you know we have 4 different pixel formats being 1bpp (transparent + 1 color), 2bpp (transparent + 3 colors), 4bpp (transparent + 15 colors) and 8bpp (which has all palette colors). The global palette has 216 colors that are predefined and cannot be changed at all. Then we also have a transparent color which, when used in sprites or graphic functions not drawn to the screen buffer. And the special thing is that we also have a dynamic set of 39 custom RGB colors that can be changed by any game at any point. These colors can be used in any graphics function or sprite. When the screen is synced the next time (which games need to do manually by calling a command) after the colors have been altered, the screen can look entirely different. But back to your question, no I doubt we will do such alpha blending as its hard and basically wouldn't work to well.

Quote from: Streetwalrus on November 13, 2015, 09:05:46 AM
It's not very easy to do with paletted colors. Alpha blending requires access to the raw colors.
Yes. Maybe using the dynamic colors it's possible to do so but I really doubt it will work.
Title: Re: Graphics and other system routines
Post by: Dream of Omnimaga on November 15, 2015, 06:30:43 AM
I see. I guess for fade-in effects I'll just create extra copies of my sprites then make them go darker by switching colors to the nearest available darker color in the palette. :P
Title: Re: Graphics and other system routines
Post by: adekto on November 15, 2015, 08:09:52 AM
Quote from: DJ Omnimaga on November 15, 2015, 06:30:43 AM
I see. I guess for fade-in effects I'll just create extra copies of my sprites then make them go darker by switching colors to the nearest available darker color in the palette. :P
wel there are other ways to do that replacing the variable color pallet part could do a fade to a set color (no blending, but sorta what you want)
also if you use a custom pallet and use say only grey's, you could in theory do a adetive color blend but its a bit complicated
Title: Re: Graphics and other system routines
Post by: semiprocoder on November 15, 2015, 03:08:15 PM
I know that you said you don't support 16 bit color mode anymore, but couldn't you just leave it as an option instead of completely removing it? Maybe with that mode you would have half of the screen rendered at a time. Also could you support 12 bit color mode? Its unconventional but I think it could work.
Title: Re: Graphics and other system routines
Post by: DarkestEx on November 15, 2015, 03:28:23 PM
Quote from: semiprocoder on November 15, 2015, 03:08:15 PM
I know that you said you don't support 16 bit color mode anymore, but couldn't you just leave it as an option instead of completely removing it? Maybe with that mode you would have half of the screen rendered at a time. Also could you support 12 bit color mode? Its unconventional but I think it could work.
No, sorry but supporting any of these is not really possible. You can directly talk to the OLED, but this is very discouraged. You won't end up using 16 bit colors anyways. I don't see any use for them really. And if the 216 colors don't contain the colors you like, then you can always use the 39 16 bit colors that can be defined at runtime.
Title: Re: Graphics and other system routines
Post by: adekto on November 15, 2015, 10:11:25 PM
an alternative system to acheave a blend is true overlaped ditered sprites, or some sort of mask
here is a 3D example from pico8 (they do some neat stuff) but the thing i would like you take notice of is that they use a 16 color pallet and use 2 textures and use ditering to achive the lighting
http://www.lexaloffle.com/bbs/?tid=2688&autoplay=1#pp (http://www.lexaloffle.com/bbs/?tid=2688&autoplay=1#pp)
its not perfect but in theory it can work
Title: Re: Graphics and other system routines
Post by: Dream of Omnimaga on November 22, 2015, 07:39:30 AM
If we can change the color palette we are currently using for the sprites on screen refresh, then I guess that can be used for special effects too. I could live without it, but it was nice to be able to do it on the NES. :)
Title: Re: Graphics and other system routines
Post by: DarkestEx on November 22, 2015, 12:52:54 PM
Quote from: DJ Omnimaga on November 22, 2015, 07:39:30 AM
If we can change the color palette we are currently using for the sprites on screen refresh, then I guess that can be used for special effects too. I could live without it, but it was nice to be able to do it on the NES. :)
You can change 39 colors of the palette.
Title: Re: Graphics and other system routines
Post by: Dream of Omnimaga on November 22, 2015, 11:15:03 PM
That's good enough to me. Just as long as making sprites is as easy as just using Paint. :P I got plenty of 8*8 sprites at low color depth.
Title: Re: Graphics and other system routines
Post by: semiprocoder on November 23, 2015, 12:38:07 AM
Can you only change the value of the 39 extra colors each frame or each time you draw something?
Title: Re: Graphics and other system routines
Post by: DarkestEx on November 23, 2015, 12:45:48 AM
Quote from: semiprocoder on November 23, 2015, 12:38:07 AM
Can you only change the value of the 39 extra colors each frame or each time you draw something?
Well each frame. The screen buffer is global so is the palette. If you change the dynamic colors, everything that has been drawn using these dynamic colors and is currently visible on the screen will be changed.
Drawing does not show anything on the screen. The buffer need to be swapped in order to see the newly generated image from the buffer. When generating it, the current dynamic palette and the static palette is used to resolve the RGB colors sent to the screen (OLED).
Quote from: DJ Omnimaga on November 22, 2015, 11:15:03 PM
That's good enough to me. Just as long as making sprites is as easy as just using Paint. [emoji14] I got plenty of 8*8 sprites at low color depth.
Well you can't use the 39 dynamic colors in paint. We will come up with a way to use them at some point.
Title: Re: Graphics and other system routines
Post by: Dream of Omnimaga on November 23, 2015, 04:23:05 AM
Oh I meant in general. One major issue with individual sprites in Doors CSE is that there is no way to edit them other than typing the hexadecimal by hand. Entire sprite sheets are editable, but not individual sprites (DCSE supports inline sprites). Even SourceCoder lacks that feature.

This is definitively something that needs to be avoided with Microcat and claw. I'm confident that you'll find a way to make sprite editing/importing easy, though.
Title: Re: Graphics and other system routines
Post by: Dream of Omnimaga on November 24, 2015, 07:55:27 AM
So I am curious about what the following sprites would look like in Microcat format and how much space they would take:

(http://img.codewalr.us/censoredwalriispritesheet.png)

Would the sprite sheet need to be split into multiple files and only one part loaded at a time?
Title: Re: Graphics and other system routines
Post by: DarkestEx on November 24, 2015, 08:30:05 AM
Quote from: DJ Omnimaga on November 24, 2015, 07:55:27 AM
So I am curious about what the following sprites would look like in Microcat format and how much space they would take:

(http://img.codewalr.us/censoredwalriispritesheet.png)

Would the sprite sheet need to be split into multiple files and only one part loaded at a time?
Sure, I'll convert it for you.
About the size and if you have to split it, you can calculate that easily.
But first, what pixel format do you want to use? In this case I would either use 4bpp or preferably 8bpp.
To calculate the size of an image in bytes, simply do:
size = 20 + (2^bpp) - 1 + (width * height * bpp) / 8

(Only do the + (2^bpp) - 1 if you are using a bpp < 8 )

The maximum size of a sprite(sheet) is 32KB.

Edit: But to answer your question, no, you cannot load a sprite(sheet) this big at once. 32 KB max per sprite(sheet). I will in the future just refer to sprite as for the console / claw, a spritesheet and a single sprite are exactly the same thing.
There will be a draw sprite rectangle method to draw only a part of a sprite or spritesheet.
Title: Re: Graphics and other system routines
Post by: Dream of Omnimaga on November 24, 2015, 02:31:24 PM
Thanks for the info. Not bad I guess, since I can split the spritesheet in rows :)