diff --git a/CMakeLists.txt b/CMakeLists.txt index d97d52d..599269e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,25 +28,31 @@ add_custom_command( set(SOURCES + src/main.cpp - src/fast_trig.cpp - src/extrakeyboard.cpp - - src/collections.cpp - src/impact.cpp - src/player.cpp - src/utilities.cpp - src/particles.cpp - src/bullet.cpp - src/enemy.cpp - src/starfieldshader.cpp - src/background.cpp - src/bonus.cpp - src/boss.cpp - src/point2D.cpp - src/trajectory.cpp + src/utilities/fast_trig.cpp + src/utilities/extrakeyboard.cpp + src/utilities/utilities.cpp + src/utilities/vector2D.cpp + src/shaders/circle.cpp + src/shaders/poly.cpp + src/shaders/filledcircle.cpp + src/shaders/filledpoly.cpp + src/shaders/line.cpp + src/shaders/starfieldshader.cpp + + src/shmup/collections.cpp + src/shmup/impact.cpp + src/shmup/player.cpp + src/shmup/particles.cpp + src/shmup/bullet.cpp + src/shmup/enemy.cpp + src/shmup/background.cpp + src/shmup/bonus.cpp + src/shmup/boss.cpp + src/shmup/trajectory.cpp # ... ) set(ASSETS_cg diff --git a/assets-cg/__pycache__/converters.cpython-310.pyc b/assets-cg/__pycache__/converters.cpython-310.pyc deleted file mode 100644 index c9120c5..0000000 Binary files a/assets-cg/__pycache__/converters.cpython-310.pyc and /dev/null differ diff --git a/src/MyAzurShaders.h b/src/MyAzurShaders.h deleted file mode 100644 index 5f938f9..0000000 --- a/src/MyAzurShaders.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef MYAZURSHADERS_H -#define MYAZURSHADERS_H - -#include - - -#define SHOW_PIXELS 1 -#define SHOW_STARS 2 - -void azrp_starfield( void ); -void azrp_starfield_init( uint8_t nbstars ); -void azrp_starfield_close( void ); - -void azrp_tilesmap( int shifttile, int *tilemap, bopti_image_t *image, int tileset_size ); - -#endif //MYAZURSHADERS_H \ No newline at end of file diff --git a/src/fast_trig.cpp b/src/fast_trig.cpp deleted file mode 100644 index 28fd3d7..0000000 --- a/src/fast_trig.cpp +++ /dev/null @@ -1,94 +0,0 @@ -#include "fast_trig.h" -#include "num/num.h" - - -static libnum::num cosTable[360]; -static libnum::num sinTable[360]; -static bool is_fast_trig_initialised = false; - -void Fast_Trig_Init( void ) -{ - for(int u=0; u<360; u++) - { - cosTable[u] = libnum::num( cos( u * PI / 180 ) ); - sinTable[u] = libnum::num( sin( u * PI / 180 ) ); - } - is_fast_trig_initialised = true; -} - - -libnum::num FastCosInt( int16_t angle ) -{ - if (!is_fast_trig_initialised) Fast_Trig_Init(); - - if (angle>=0 and angle<360) return cosTable[ angle ]; - else - { - int16_t input = angle; - if (input<0) - { - while (input<0) input+=360; - return cosTable[ input ]; - } - else - { - while (input>=360) input-=360; - return cosTable[ input ]; - } - } -} - -libnum::num FastSinInt( int16_t angle ) -{ - if (!is_fast_trig_initialised) Fast_Trig_Init(); - - if (angle>=0 and angle<360) return sinTable[ angle ]; - else - { - int16_t input = angle; - if (input<0) - { - while (input<0) input+=360; - return sinTable[ input ]; - } - else - { - while (input>=360) input-=360; - return sinTable[ input ]; - } - } -} - -libnum::num FastTanInt( int16_t angle ) -{ - if (!is_fast_trig_initialised) Fast_Trig_Init(); - - int16_t input = angle; - - if (input<0) - { - while (input<0) input+=360; - } - else if (input>=360) - { - while (input>=360) input-=360; - } - - libnum::num value; - - if (input==90) - { - value.v = INT32_MAX; - return value; - } - else if (input==270) - { - value.v = INT32_MIN; - return value; - } - else - { - value = FastSinInt(input) / FastCosInt(input); - return value; - } -} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index ae9ec6e..28f9ec4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -26,23 +26,24 @@ #include -#include "fast_trig.h" -#include "extrakeyboard.h" +#include "utilities/fast_trig.h" +#include "utilities/extrakeyboard.h" +#include "utilities/utilities.h" -#include "collections.h" +#include "shmup/collections.h" -#include "MyAzurShaders.h" +#include "shaders/MyAzurShaders.h" -#include "player.h" -#include "utilities.h" -#include "particles.h" -#include "bullet.h" -#include "enemy.h" -#include "bonus.h" -#include "impact.h" -#include "background.h" -#include "boss.h" -#include "trajectory.h" +#include "shmup/player.h" + +#include "shmup/particles.h" +#include "shmup/bullet.h" +#include "shmup/enemy.h" +#include "shmup/bonus.h" +#include "shmup/impact.h" +#include "shmup/background.h" +#include "shmup/boss.h" +#include "shmup/trajectory.h" #include #include @@ -83,6 +84,7 @@ std::vector MyEnemiesBullets; std::vector MyEnemies; std::vector MyImpacts; std::vector MyBonuses; +std::vector MyTrajectories; Background MyBackground; diff --git a/src/point2D.cpp b/src/point2D.cpp deleted file mode 100644 index 225e695..0000000 --- a/src/point2D.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "point2D.h" - - -Point2D::Point2D( ) -{ - x = libnum::num( 0 ); - y = libnum::num( 0 ); -} - - -Point2D::Point2D( int16_t _x, int16_t _y ) -{ - x = libnum::num( _x ); - y = libnum::num( _y ); -} - - -Point2D::~Point2D( ) -{ - -} diff --git a/src/point2D.h b/src/point2D.h deleted file mode 100644 index dde3885..0000000 --- a/src/point2D.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef POINT2D_H -#define POINT2D_H - -#include -#include -#include - - -class Point2D -{ - public: - libnum::num x, y; - Point2D( ); - Point2D( int16_t _x, int16_t _y ); - ~Point2D( ); -}; - - -#endif \ No newline at end of file diff --git a/src/shaders/MyAzurShaders.h b/src/shaders/MyAzurShaders.h new file mode 100644 index 0000000..af775d1 --- /dev/null +++ b/src/shaders/MyAzurShaders.h @@ -0,0 +1,39 @@ +#ifndef MYAZURSHADERS_H +#define MYAZURSHADERS_H + +#include + + +#define SHOW_PIXELS 1 +#define SHOW_STARS 2 + +void azrp_starfield( void ); +void azrp_starfield_init( uint8_t nbstars ); +void azrp_starfield_close( void ); + + + +void azrp_shader_line_configure(void); +void azrp_shader_circle_configure(void); +void azrp_shader_filledcircle_configure(void); +void azrp_shader_filledpoly_configure(void); +void azrp_shader_poly_configure(void); + +/* azrp_line(): Draw a line with clipping to the screen resolution between point (x1,y1) and (x2,y2) */ +void azrp_line( int x1, int y1, int x2, int y2, uint16_t color ); + +/* azrp_circle() : Draw a circle with clipping to the screen resolution with a center (xc,yc) and a radius rad */ +void azrp_circle( int xc, int yx, uint16_t rad, uint16_t color ); + +/* azrp_filledcircle() : Draw a filled circle with clipping to the screen resolution with a center (xc,yc) and a radius rad */ +void azrp_filledcircle( int xc, int yx, uint16_t rad, uint16_t color ); + +/* azrp_poly() : Draw a polygon with clipping*/ +void azrp_poly(int *x, int *y, int nb_vertices, uint16_t color); + +/* azrp_filledpoly() : Draw a filled polygon with clipping*/ +void azrp_filledpoly(int *x, int *y, int nb_vertices, uint16_t color); + + + +#endif //MYAZURSHADERS_H \ No newline at end of file diff --git a/src/shaders/circle.cpp b/src/shaders/circle.cpp new file mode 100644 index 0000000..ebc5226 --- /dev/null +++ b/src/shaders/circle.cpp @@ -0,0 +1,147 @@ +#include + +uint8_t AZRP_SHADER_CIRCLE = -1; + + +static void azrp_shader_circle_configure(void) +{ + azrp_set_uniforms(AZRP_SHADER_CIRCLE, (void *)azrp_width); +} + +__attribute__((constructor)) +static void register_shader(void) +{ + extern azrp_shader_t azrp_shader_circle; + AZRP_SHADER_CIRCLE = azrp_register_shader(azrp_shader_circle, azrp_shader_circle_configure); +} + + + +static int min(int x, int y) +{ + return (x < y) ? x : y; +} +static int max(int x, int y) +{ + return (x > y) ? x : y; +} + +//--- + +#define TABLE_WIDTH 256 + +struct command { + uint8_t shader_id; + uint16_t color; + uint8_t curr_frag; + uint16_t NbPixels[14]; // Nunmber of pixels in each fragment + uint16_t DataPixelsX[14*TABLE_WIDTH]; // 14 fragments each able to store as much pixels as width + uint16_t DataPixelsY[14*TABLE_WIDTH]; // 14 fragments each able to store as much pixels as width +}; + +void AddPixelCircle( int16_t xp, int16_t yp, struct command *cmd ) +{ + if (xp >= 0 && xp < azrp_width && yp >= 0 && yp < azrp_height) + { + uint8_t cfrag = yp / azrp_frag_height; + uint16_t nbpixinfrag = cmd->NbPixels[ cfrag ]; + + uint16_t index = cfrag * TABLE_WIDTH + nbpixinfrag; + + cmd->DataPixelsX[ index ] = xp; + cmd->DataPixelsY[ index ] = yp & 15; + cmd->NbPixels[ cfrag ]++; + } +} + +void azrp_circle(int xc, int yc, uint16_t rad, uint16_t color) +{ + prof_enter(azrp_perf_cmdgen); + + + int xmin = xc - rad; + int xmax = xc + rad; + int ymin = yc - rad; + int ymax = yc + rad; + + // The circle is fully outside the screen + if ((xmax < 0) || (xmin >= azrp_width) || (ymax < 0) || (ymin >= azrp_height)) + { + prof_leave(azrp_perf_cmdgen); + return; + } + + + + + int ytop = max( ymin, 0 ); + int ybot = min( ymax, azrp_height-1 ); + + int frag_first = ytop / azrp_frag_height; + int frag_last = ybot / azrp_frag_height; + int frag_count = frag_last - frag_first + 1; + + + struct command *cmd = (struct command *) azrp_new_command(sizeof *cmd, frag_first, frag_count); + if(!cmd) { + prof_leave(azrp_perf_cmdgen); + return; + } + + cmd->shader_id = AZRP_SHADER_CIRCLE; + cmd->color = color; + cmd->curr_frag = frag_first; + + // reset the point counters in each cell of the table + for( int i = 0; i < 14; i++ ) + cmd->NbPixels[i]=0; + + int x = 0; + int y = rad; + int m = 5 - 4*rad; + + while (x <= y) + { + AddPixelCircle( xc+x, yc+y, cmd ); + AddPixelCircle( xc+y, yc+x, cmd ); + AddPixelCircle( xc-x, yc+y, cmd ); + AddPixelCircle( xc-y, yc+x, cmd ); + AddPixelCircle( xc+x, yc-y, cmd ); + AddPixelCircle( xc+y, yc-x, cmd ); + AddPixelCircle( xc-x, yc-y, cmd ); + AddPixelCircle( xc-y, yc-x, cmd ); + + if (m > 0) + { + y--; + m -= 8*y; + } + x++; + m += 8*x + 4; + } + + prof_leave(azrp_perf_cmdgen); +} + +void azrp_shader_circle( void *uniforms, void *comnd, void *fragment ) +{ + struct command *cmd = (struct command *) comnd; + uint16_t *frag = (uint16_t *) fragment; + + uint16_t *taille = (uint16_t *) cmd->NbPixels; + uint16_t *DX = (uint16_t *) cmd->DataPixelsX; + uint16_t *DY = (uint16_t *) cmd->DataPixelsY; + + uint16_t nbpix = taille[ cmd->curr_frag ]; + int BaseAdress = cmd->curr_frag * TABLE_WIDTH; + + for( int i = 0; i < nbpix; i++ ) + { + uint16_t X = DX[ BaseAdress + i ]; + uint16_t Y = DY[ BaseAdress + i ]; + + frag[ azrp_width * Y + X ] = cmd->color; + } + + cmd->curr_frag++; +} \ No newline at end of file diff --git a/src/shaders/filledcircle.cpp b/src/shaders/filledcircle.cpp new file mode 100644 index 0000000..b87793a --- /dev/null +++ b/src/shaders/filledcircle.cpp @@ -0,0 +1,124 @@ +#include + +uint8_t AZRP_SHADER_FILLEDCIRCLE = -1; + + +static void azrp_shader_filledcircle_configure(void) { + azrp_set_uniforms(AZRP_SHADER_FILLEDCIRCLE, (void *)azrp_width); +} + + +__attribute__((constructor)) static void register_shader(void) { + extern azrp_shader_t azrp_shader_filledcircle; + AZRP_SHADER_FILLEDCIRCLE = azrp_register_shader(azrp_shader_filledcircle, azrp_shader_filledcircle_configure); +} + + + +static int min(int x, int y) { return (x < y) ? x : y; } +static int max(int x, int y) { return (x > y) ? x : y; } + +//--- + +#define TABLE_WIDTH + +struct command { + uint8_t shader_id; + uint16_t color; + uint8_t curr_frag; + int16_t DataFilling[2 * 224]; // Each line of the screen can have a xmin and + // a xmax value +}; + +void AddPixelFilledCircle(int16_t xpmin, int16_t xpmax, int16_t yp, + struct command *cmd) { + if (yp >= 0 && yp < azrp_height) { + if (xpmin >= 0) + cmd->DataFilling[2 * yp] = xpmin; + else + cmd->DataFilling[2 * yp] = 0; + + if (xpmax < azrp_width) + cmd->DataFilling[2 * yp + 1] = xpmax; + else + cmd->DataFilling[2 * yp + 1] = azrp_width - 1; + } +} + +void azrp_filledcircle(int xc, int yc, uint16_t rad, uint16_t color) { + prof_enter(azrp_perf_cmdgen); + + int xmin = xc - rad; + int xmax = xc + rad; + int ymin = yc - rad; + int ymax = yc + rad; + + // The circle is fully outside the screen + if ((xmax < 0) || (xmin >= azrp_width) || (ymax < 0) || + (ymin >= azrp_height)) { + prof_leave(azrp_perf_cmdgen); + return; + } + + int ytop = max(ymin, 0); + int ybot = min(ymax, azrp_height - 1); + + int frag_first = ytop / azrp_frag_height; + int frag_last = ybot / azrp_frag_height; + int frag_count = frag_last - frag_first + 1; + + struct command *cmd = (struct command *) azrp_new_command(sizeof *cmd, frag_first, frag_count); + if(!cmd) { + prof_leave(azrp_perf_cmdgen); + return; + } + + cmd->shader_id = AZRP_SHADER_FILLEDCIRCLE; + cmd->color = color; + cmd->curr_frag = frag_first; + + // reset the point counters in each cell of the table + for (int i = 0; i < 224; i++) { + cmd->DataFilling[2 * i] = -1; // reset with value equels -1 + cmd->DataFilling[2 * i + 1] = -1; // reset with value equals -1 + } + + int x = 0; + int y = rad; + int m = 5 - 4 * rad; + + while (x <= y) { + AddPixelFilledCircle(xc - x, xc + x, yc - y, cmd); + AddPixelFilledCircle(xc - y, xc + y, yc - x, cmd); + AddPixelFilledCircle(xc - x, xc + x, yc + y, cmd); + AddPixelFilledCircle(xc - y, xc + y, yc + x, cmd); + + if (m > 0) { + y--; + m -= 8 * y; + } + x++; + m += 8 * x + 4; + } + + prof_leave(azrp_perf_cmdgen); +} + +void azrp_shader_filledcircle(void *uniforms, void *comnd, void *fragment) { + struct command *cmd = (struct command *)comnd; + uint16_t *frag = (uint16_t *)fragment; + + int16_t *data = (int16_t *)cmd->DataFilling; + int BaseAdress = cmd->curr_frag * azrp_frag_height * 2; + + for (int i = 0; i < azrp_frag_height; i++) { + int16_t Xmin = data[BaseAdress + 2 * i]; + int16_t Xmax = data[BaseAdress + 2 * i + 1]; + + if (Xmin != -1 && Xmax != -1) + for (int j = Xmin; j <= Xmax; j++) + frag[azrp_width * i + j] = cmd->color; + } + + cmd->curr_frag++; +} \ No newline at end of file diff --git a/src/shaders/filledpoly.cpp b/src/shaders/filledpoly.cpp new file mode 100644 index 0000000..4f1123b --- /dev/null +++ b/src/shaders/filledpoly.cpp @@ -0,0 +1,171 @@ +#include +#include + +uint8_t AZRP_SHADER_FILLEDPOLY = -1; + +static void azrp_shader_filledpoly_configure(void) { + azrp_set_uniforms(AZRP_SHADER_FILLEDPOLY, (void *)azrp_width); +} + +__attribute__((constructor)) static void register_shader(void) { + extern azrp_shader_t azrp_shader_filledpoly; + AZRP_SHADER_FILLEDPOLY = azrp_register_shader(azrp_shader_filledpoly, azrp_shader_filledpoly_configure); +} + + + +static int min(int x, int y) { return (x < y) ? x : y; } +static int max(int x, int y) { return (x > y) ? x : y; } + +//--- + +#define TABLE_WIDTH + +struct command { + uint8_t shader_id; + uint16_t color; + uint8_t curr_frag; + int16_t xmin[224]; + int16_t xmax[224]; + uint8_t empty[224]; +}; + + +void AddPixelFilledPoly(int16_t xpmin, int16_t xpmax, int16_t yp, + struct command *cmd) { + if (yp >= 0 && yp < azrp_height) { + if (xpmin >= 0) + cmd->xmin[yp] = xpmin; + else + cmd->xmin[yp] = 0; + + if (xpmax < azrp_width) + cmd->xmax[yp] = xpmax; + else + cmd->xmax[yp] = azrp_width - 1; + } +} + + +void azrp_filledpoly(int *x, int *y, int nb_vertices, uint16_t color) { + prof_enter(azrp_perf_cmdgen); + + int i, ymin, ymax, xmin2, xmax2, *xmin, *xmax; + char *empty; + + if(nb_vertices < 3) { + prof_leave(azrp_perf_cmdgen); + return; + } + + ymin = ymax = y[0]; + xmin2 = xmax2 = x[0]; + + for(i=0 ; i ymax) ymax = y[i]; + if(x[i] < xmin2) xmin2 = x[i]; + if(x[i] > xmax2) xmax2 = x[i]; + } + + // The polygon is fully outside the screen + if ((xmax2 < 0) || (xmin2 >= azrp_width) || (ymax < 0) || + (ymin >= azrp_height)) { + prof_leave(azrp_perf_cmdgen); + return; + } + + xmin = (int*) malloc((ymax-ymin+1)*sizeof(int)); + xmax = (int*) malloc((ymax-ymin+1)*sizeof(int)); + empty = (char*) malloc(ymax-ymin+1); + + + int ytop = max(ymin, 0); + int ybot = min(ymax, azrp_height - 1); + + int frag_first = ytop / azrp_frag_height; + int frag_last = ybot / azrp_frag_height; + int frag_count = frag_last - frag_first + 1; + + struct command *cmd = (struct command *) azrp_new_command(sizeof *cmd, frag_first, frag_count); + if(!cmd) { + prof_leave(azrp_perf_cmdgen); + return; + } + + cmd->shader_id = AZRP_SHADER_FILLEDPOLY; + cmd->color = color; + cmd->curr_frag = frag_first; + + // reset the point counters in each cell of the table + for (int i = 0; i < 224; i++) { + cmd->xmin[i] = -1; // reset with value equels -1 + cmd->xmax[i] = -1; // reset with value equals -1 + } + + if(xmin && xmax && empty) { + for(i=0 ; i 0) ? 1 : -1; + sy = (dy > 0) ? 1 : -1; + dx = (dx > 0) ? dx : -dx; + dy = (dy > 0) ? dy : -dy; + if(empty[py-ymin]) xmax[py-ymin]=xmin[py-ymin]=px, empty[py-ymin]=0; else xmax[py-ymin]=px; + if(dx > dy) { + cumul = dx >> 1; + for(j=1 ; j dx) cumul -= dx, py += sy; + if(empty[py-ymin]) xmax[py-ymin]=xmin[py-ymin]=px, empty[py-ymin]=0; else xmax[py-ymin]=px; + } + } else { + cumul = dy >> 1; + for(j=1 ; j dy) cumul -= dy, px += sx; + if(empty[py-ymin]) xmax[py-ymin]=xmin[py-ymin]=px, empty[py-ymin]=0; else xmax[py-ymin]=px; + } + } + } + for(i=0 ; ixmin; + int16_t *Xmaxdata = (int16_t *)cmd->xmax; + + int BaseAdress = cmd->curr_frag * azrp_frag_height; + + for (int i = 0; i < azrp_frag_height; i++) + { + int16_t Xmin = Xmindata[BaseAdress + i]; + int16_t Xmax = Xmaxdata[BaseAdress + i]; + + if (Xmin != -1 && Xmax != -1) + { + if (Xmin<=Xmax) + for (int j = Xmin; j <= Xmax; j++) frag[azrp_width * i + j] = cmd->color; + else + for (int j = Xmax; j <= Xmin; j++) frag[azrp_width * i + j] = cmd->color; + } + } + + cmd->curr_frag++; +} \ No newline at end of file diff --git a/src/shaders/line.cpp b/src/shaders/line.cpp new file mode 100644 index 0000000..ca1c354 --- /dev/null +++ b/src/shaders/line.cpp @@ -0,0 +1,211 @@ +#include + +uint8_t AZRP_SHADER_LINE = -1; + + +static void azrp_shader_line_configure(void) +{ + azrp_set_uniforms(AZRP_SHADER_LINE, (void *)azrp_width); +} + + +__attribute__((constructor)) +static void register_shader(void) +{ + extern azrp_shader_t azrp_shader_line; + AZRP_SHADER_LINE = azrp_register_shader(azrp_shader_line, azrp_shader_line_configure ); +} + + + + +//--- + +struct command { + uint8_t shader_id; + uint16_t color; + uint16_t curr_y; + uint16_t curr_x; + int16_t dx, dy, sx, sy; + int16_t cumul; + int16_t i; +}; + +int ABS( int x1 ) +{ + if (x1 >= 0) return x1; + else return (-1 * x1); +} + +int SGN( int x1 ) +{ + if (x1 > 0) return 1; + else if (x1 == 0) return 0; + else return -1; +} + +void azrp_line(int xA, int yA, int xB, int yB, uint16_t color) +{ + prof_enter(azrp_perf_cmdgen); + + //clipping algorithm as per "Another Simple but Faster Method for 2D Line Clipping" + //from Dimitrios Matthes and Vasileios Drakopoulos + //International Journal of Computer Graphics & Animation (IJCGA) Vol.9, No.1/2/3, July 2019 + + int xmin = 0; + int xmax = azrp_width-1; + int ymin = 0; + int ymax = azrp_height-1; + + //step 1 line are fully out of the screen + if ((xAxmax && xB>xmax) || (yAymax && yB>ymax)) { + prof_leave(azrp_perf_cmdgen); + return; + } + + int x1, x2, y1, y2; + + // step 1.5 - specific to Azur fragment approach + // we swap to always start with the point on top as the fragment are updated from top to bottom + // (x1,y1) is the most top point and (x2,y2) is the most bottom point (rankig as per y values only + if (yA <= yB) { + x1 = xA; y1 = yA; + x2 = xB; y2 = yB; + } + else { + x1 = xB; y1 = yB; + x2 = xA; y2 = yA; + } + + //step 2 line clipping within the box (xmin,ymin) --> (xmax,ymax) + int x[2]; + int y[2]; + + x[0] = x1; x[1] = x2; + y[0] = y1; y[1] = y2; + + + for(int i=0; i<2; i++) { + if (x[i] < xmin) { + x[i] = xmin; y[i] = ((y2-y1) * (xmin-x1)) / (x2-x1) + y1; + } + else if (x[i] > xmax) { + x[i] = xmax; y[i] = ((y2-y1) * (xmax-x1)) / (x2-x1) + y1; + } + + if (y[i] < ymin) { + x[i] = ((x2-x1) * (ymin-y1)) / (y2-y1) + x1; y[i] = ymin; + } + else if (y[i] > ymax) { + x[i] = ((x2-x1) * (ymax-y1)) / (y2-y1) + x1; y[i] = ymax; + } + } + + if((x[0] < xmin && x[1] < xmin) || (x[0] > xmax && x[1] > xmax)) { + prof_leave(azrp_perf_cmdgen); + return; + } + + x1 = x[0]; + y1 = y[0]; + x2 = x[1]; + y2 = y[1]; + + int frag_first = y1 / azrp_frag_height; + int frag_last = y2 / azrp_frag_height; + int frag_count = frag_last - frag_first + 1; + + + struct command *cmd = (struct command *) azrp_new_command(sizeof *cmd, frag_first, frag_count); + if(!cmd) { + prof_leave(azrp_perf_cmdgen); + return; + } + + cmd->shader_id = AZRP_SHADER_LINE; + cmd->color = color; + + cmd->curr_x = x1; + cmd->curr_y = y1 & 15; + + cmd->dx = ABS(x2-x1); + cmd->sx = SGN(x2-x1); + + cmd->dy = ABS(y2-y1); + cmd->sy = SGN(y2-y1); + + cmd->i = 0; + cmd->cumul = (cmd->dx >= cmd->dy) ? cmd->dx/2 : cmd->dy/2; + + prof_leave(azrp_perf_cmdgen); +} + +void azrp_shader_line( void *uniforms, void *comnd, void *fragment ) +{ + struct command *cmd = (struct command *) comnd; + uint16_t *frag = (uint16_t *) fragment; + + frag[ azrp_width * cmd->curr_y + cmd->curr_x ] = cmd->color; + + int i; + + if (cmd->dy == 0) + { + for( i = cmd->i; i < cmd->dx ; i++ ) + { + cmd->curr_x += cmd->sx; + frag[ azrp_width * cmd->curr_y + cmd->curr_x ] = cmd->color; + } + } + else if (cmd->dx == 0) + { + for( i = cmd->i; i < cmd->dy ; i++ ) + { + cmd->curr_y += cmd->sy; + + // if curr_y=16, this means we are changing to next fragment + if (cmd->curr_y == azrp_frag_height) break; + + frag[ azrp_width * cmd->curr_y + cmd->curr_x ] = cmd->color; + } + } + else if (cmd->dx >= cmd->dy) + { + for( i = cmd->i; i < cmd->dx; i++ ) + { + cmd->curr_x += cmd->sx; + cmd->cumul += cmd->dy; + if (cmd->cumul > cmd->dx) + { + cmd->cumul -= cmd->dx; + cmd->curr_y += cmd->sy; + } + // if curr_y=16, this means we are changing to next fragment + if (cmd->curr_y == azrp_frag_height ) break; + + frag[ azrp_width * cmd->curr_y + cmd->curr_x ] = cmd->color; + } + } + else + { + for( i = cmd->i; i < cmd->dy; i++ ) + { + cmd->curr_y += cmd->sy; + cmd->cumul += cmd->dx; + if (cmd->cumul > cmd->dy) + { + cmd->cumul -= cmd->dy; + cmd->curr_x += cmd->sx; + } + + // if curr_y=16, this means we are changing to next fragment + if (cmd->curr_y == azrp_frag_height) break; + + frag[ azrp_width * cmd->curr_y + cmd->curr_x ] = cmd->color; + } + } + + cmd->curr_y = cmd->curr_y & 15; + + cmd->i = i+1; +} diff --git a/src/shaders/poly.cpp b/src/shaders/poly.cpp new file mode 100644 index 0000000..609a986 --- /dev/null +++ b/src/shaders/poly.cpp @@ -0,0 +1,16 @@ +#include +#include "MyAzurShaders.h" + +void azrp_poly(int *x, int *y, int nb_vertices, uint16_t color) { + prof_enter(azrp_perf_cmdgen); + + for( int i=0 ; i #include "MyAzurShaders.h" diff --git a/src/background.cpp b/src/shmup/background.cpp similarity index 99% rename from src/background.cpp rename to src/shmup/background.cpp index 28b390a..107d537 100644 --- a/src/background.cpp +++ b/src/shmup/background.cpp @@ -1,4 +1,4 @@ -#include "config.h" +#include "../config.h" #include "background.h" #include diff --git a/src/background.h b/src/shmup/background.h similarity index 100% rename from src/background.h rename to src/shmup/background.h diff --git a/src/bonus.cpp b/src/shmup/bonus.cpp similarity index 96% rename from src/bonus.cpp rename to src/shmup/bonus.cpp index 84a94c2..41e8fd2 100644 --- a/src/bonus.cpp +++ b/src/shmup/bonus.cpp @@ -1,4 +1,4 @@ -#include "config.h" +#include "../config.h" #include "bonus.h" #include @@ -43,7 +43,7 @@ Bonus::Bonus( int16_t _x, int16_t _y, uint8_t _id ) Bonus::~Bonus() { if (hasTrajectory) - delete(pathToFollow); + pathToFollow->DeleteRegistry(); } void Bonus::Update( float dt ) diff --git a/src/bonus.h b/src/shmup/bonus.h similarity index 100% rename from src/bonus.h rename to src/shmup/bonus.h diff --git a/src/boss.cpp b/src/shmup/boss.cpp similarity index 99% rename from src/boss.cpp rename to src/shmup/boss.cpp index 2e25ff7..d38de78 100644 --- a/src/boss.cpp +++ b/src/shmup/boss.cpp @@ -1,4 +1,4 @@ -#include "config.h" +#include "../config.h" #include "boss.h" #include "bullet.h" @@ -6,13 +6,13 @@ #include #include #include -#include "fast_trig.h" +#include "../utilities/fast_trig.h" #include #include "collections.h" #include "player.h" -#include "vector2D.h" +#include "../utilities/vector2D.h" extern bopti_image_t img_Lifebar; extern bopti_image_t img_Boss1; @@ -163,7 +163,7 @@ Boss::Boss( int16_t _x, int16_t _y, uint8_t _id ) Boss::~Boss() { if (hasTrajectory) - delete(pathToFollow); + pathToFollow->DeleteRegistry(); } diff --git a/src/boss.h b/src/shmup/boss.h similarity index 100% rename from src/boss.h rename to src/shmup/boss.h diff --git a/src/bullet.cpp b/src/shmup/bullet.cpp similarity index 99% rename from src/bullet.cpp rename to src/shmup/bullet.cpp index 6e3a207..df90788 100644 --- a/src/bullet.cpp +++ b/src/shmup/bullet.cpp @@ -1,4 +1,4 @@ -#include "config.h" +#include "../config.h" #include "bullet.h" diff --git a/src/bullet.h b/src/shmup/bullet.h similarity index 100% rename from src/bullet.h rename to src/shmup/bullet.h diff --git a/src/collections.cpp b/src/shmup/collections.cpp similarity index 77% rename from src/collections.cpp rename to src/shmup/collections.cpp index 7b23a1e..08e16cc 100644 --- a/src/collections.cpp +++ b/src/shmup/collections.cpp @@ -1,19 +1,18 @@ -#include "config.h" +#include "../config.h" #include "collections.h" +#include "trajectory.h" #include #include extern std::vector MyParticles; - extern std::vector MyPlayerBullets; extern std::vector MyEnemiesBullets; - extern std::vector MyEnemies; extern std::vector MyImpacts; - +extern std::vector MyTrajectories; extern Player *MyPlayer; @@ -50,6 +49,7 @@ void Create_Player_Shoot( uint8_t id ) void Create_Enemies( void ) { +/* Enemy* e1 = new Enemy( 348, 112, 0); e1->Set_Speed_Vector( 1, 1, -6 ); MyEnemies.push_back( e1 ); @@ -65,42 +65,45 @@ void Create_Enemies( void ) Enemy* e4 = new Enemy( 348, 112, 1); e4->Set_Speed_Vector( 1, 3, 3 ); MyEnemies.push_back( e4 ); +*/ - - Point2D *A = new Point2D( 348, 112 ); - Point2D *B = new Point2D( 371, 199 ); - Point2D *C = new Point2D( 198, 149 ); - Point2D *D = new Point2D( 25, 199 ); - Point2D *E = new Point2D( 25, 25 ); - Point2D *F = new Point2D( 198, 75 ); - Point2D *G = new Point2D( 371, 25 ); + Vector2D *A = new Vector2D( 348, 112 ); + Vector2D *B = new Vector2D( 371, 199 ); + Vector2D *C = new Vector2D( 198, 149 ); + Vector2D *D = new Vector2D( 25, 199 ); + Vector2D *E = new Vector2D( 25, 25 ); + Vector2D *F = new Vector2D( 198, 75 ); + Vector2D *G = new Vector2D( 371, 25 ); - Trajectory *MyTrajectory= new Trajectory(); - MyTrajectory->AddPoint( A ); - MyTrajectory->AddPoint( B ); - MyTrajectory->AddPoint( C ); - MyTrajectory->AddPoint( D ); - MyTrajectory->AddPoint( E ); - MyTrajectory->AddPoint( F ); - MyTrajectory->AddPoint( G ); - + Trajectory *MyPath= new Trajectory(); + MyPath->AddPoint( A ); + MyPath->AddPoint( B ); + MyPath->AddPoint( C ); + MyPath->AddPoint( D ); + MyPath->AddPoint( E ); + MyPath->AddPoint( F ); + MyPath->AddPoint( G ); + MyTrajectories.push_back( MyPath ); Enemy* e5 = new Enemy( 348, 112, 2); e5->hasTrajectory = true; - e5->pathToFollow = MyTrajectory; + e5->pathToFollow = MyPath; + MyPath->AddRegistry(); e5->Set_Accumulated_Time(0.0f); Enemy* e6 = new Enemy( 348, 112, 2); e6->hasTrajectory = true; - e6->pathToFollow = MyTrajectory; + e6->pathToFollow = MyPath; + MyPath->AddRegistry(); e6->Set_Accumulated_Time(-1.0f); Enemy* e7 = new Enemy( 348, 112, 2); e7->hasTrajectory = true; - e7->pathToFollow = MyTrajectory; + e7->pathToFollow = MyPath; + MyPath->AddRegistry(); e7->Set_Accumulated_Time(-2.0f); @@ -167,6 +170,13 @@ void Clean_Everything( void ) } MyImpacts.clear(); + for(unsigned int i=0; iDeleteRegistry(); } void Enemy::Update( float dt ) diff --git a/src/enemy.h b/src/shmup/enemy.h similarity index 100% rename from src/enemy.h rename to src/shmup/enemy.h diff --git a/src/impact.cpp b/src/shmup/impact.cpp similarity index 95% rename from src/impact.cpp rename to src/shmup/impact.cpp index 9d4d057..f545823 100644 --- a/src/impact.cpp +++ b/src/shmup/impact.cpp @@ -1,4 +1,4 @@ -#include "config.h" +#include "../config.h" #include "impact.h" diff --git a/src/impact.h b/src/shmup/impact.h similarity index 100% rename from src/impact.h rename to src/shmup/impact.h diff --git a/src/particles.cpp b/src/shmup/particles.cpp similarity index 98% rename from src/particles.cpp rename to src/shmup/particles.cpp index ebe3be0..d3897dc 100644 --- a/src/particles.cpp +++ b/src/shmup/particles.cpp @@ -1,4 +1,4 @@ -#include "config.h" +#include "../config.h" #include "particles.h" diff --git a/src/particles.h b/src/shmup/particles.h similarity index 100% rename from src/particles.h rename to src/shmup/particles.h diff --git a/src/player.cpp b/src/shmup/player.cpp similarity index 98% rename from src/player.cpp rename to src/shmup/player.cpp index 621037a..310680c 100644 --- a/src/player.cpp +++ b/src/shmup/player.cpp @@ -1,11 +1,11 @@ -#include "config.h" +#include "../config.h" #include "player.h" #include "bullet.h" #include "enemy.h" #include #include -#include "fast_trig.h" +#include "../utilities/fast_trig.h" #include "background.h" diff --git a/src/player.h b/src/shmup/player.h similarity index 100% rename from src/player.h rename to src/shmup/player.h diff --git a/src/trajectory.cpp b/src/shmup/trajectory.cpp similarity index 83% rename from src/trajectory.cpp rename to src/shmup/trajectory.cpp index f68a9d9..356401f 100644 --- a/src/trajectory.cpp +++ b/src/shmup/trajectory.cpp @@ -1,28 +1,39 @@ -#include "config.h" +#include "../config.h" #include "trajectory.h" Trajectory::Trajectory( ) { + registration = 0; //accumulatedTime = 0.0f; } Trajectory::~Trajectory( ) { - for( auto& p : ControlPoints ) - delete( p ); - - ControlPoints.clear(); + for( auto& p : ControlPoints ) + delete( p ); + + ControlPoints.clear(); } -void Trajectory::AddPoint( Point2D *p ) +void Trajectory::AddPoint( Vector2D *p ) { ControlPoints.push_back( p ); } +void Trajectory::AddRegistry( void ) +{ + registration++; +} + +void Trajectory::DeleteRegistry( void ) +{ + registration--; +} + void Trajectory::CalculatePosition( float *accumulatedTime, float time, uint16_t speed, bool looped, libnum::num *xreturn, libnum::num *yreturn ) { *accumulatedTime += speed * time / 2000000.0f; diff --git a/src/trajectory.h b/src/shmup/trajectory.h similarity index 65% rename from src/trajectory.h rename to src/shmup/trajectory.h index d8b141d..da7a18d 100644 --- a/src/trajectory.h +++ b/src/shmup/trajectory.h @@ -1,12 +1,13 @@ #ifndef TRAJECTORY_H #define TRAJECTORY_H + #include #include #include #include -#include "point2D.h" +#include "../utilities/vector2D.h" #include "num/num.h" class Trajectory @@ -15,11 +16,16 @@ class Trajectory Trajectory( ); ~Trajectory( ); - void AddPoint( Point2D *p ); + void AddPoint( Vector2D *p ); + void AddRegistry( void ); + void DeleteRegistry( void ); void CalculatePosition( float *accumulatedTime, float time, uint16_t speed, bool looped, libnum::num *xreturn, libnum::num *yreturn ); - std::vector ControlPoints; + std::vector ControlPoints; bool isLoop; + + uint16_t registration; + //float accumulatedTime; }; diff --git a/src/tilesmapshader.cpp b/src/tilesmapshader.cpp deleted file mode 100644 index 3ae58e9..0000000 --- a/src/tilesmapshader.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include "config.h" - -#include -#include "MyAzurShaders.h" -#include -#include - -#include - - - - - -uint8_t AZRP_SHADER_TILESMAP = -1; - - -__attribute__((constructor)) -static void register_shader(void) -{ - extern azrp_shader_t azrp_shader_tilesmap; - AZRP_SHADER_TILESMAP = azrp_register_shader(azrp_shader_tilesmap); -} - - -void azrp_shader_tilesmap_configure(void) -{ - azrp_set_uniforms(AZRP_SHADER_TILESMAP, (void *)azrp_width); -} - -struct command { - uint8_t shader_id; - uint8_t current_frag; - int shifttile; - int *tilemap; - bopti_image_t *image; - int tileset_size; -}; - -void azrp_tilesmap( int shifttile, int *tilemap, bopti_image_t *image, int tileset_size ); -{ - prof_enter(azrp_perf_cmdgen); - - struct command cmd; - cmd.shader_id = AZRP_SHADER_TILESMAP; - cmd.current_frag = 0; - cmd.shifttile = shifttile; - cmd.tilemap = tilemap; - cmd.image = image; - cmd.tileset_size = tileset_size; - - azrp_queue_command(&cmd, sizeof cmd, 0, azrp_frag_count); - prof_leave(azrp_perf_cmdgen); -} - - -void azrp_shader_tilesmap( void *uniforms, void *comnd, void *fragment ) -{ - struct command *cmd = (struct command *) comnd; - uint16_t *frag = (uint16_t *) fragment; - - int currentile = cmd->tilemap[cmd->current_frag*25]; - - for(int u=0; u<=25;u++) - - - - cmd->current_frag++; -} \ No newline at end of file diff --git a/src/extrakeyboard.cpp b/src/utilities/extrakeyboard.cpp similarity index 99% rename from src/extrakeyboard.cpp rename to src/utilities/extrakeyboard.cpp index 8834ac4..6b72dff 100644 --- a/src/extrakeyboard.cpp +++ b/src/utilities/extrakeyboard.cpp @@ -1,4 +1,4 @@ -#include "config.h" +#include "../config.h" #include "extrakeyboard.h" #include diff --git a/src/extrakeyboard.h b/src/utilities/extrakeyboard.h similarity index 100% rename from src/extrakeyboard.h rename to src/utilities/extrakeyboard.h diff --git a/src/utilities/fast_trig.cpp b/src/utilities/fast_trig.cpp new file mode 100644 index 0000000..a744a6a --- /dev/null +++ b/src/utilities/fast_trig.cpp @@ -0,0 +1,183 @@ +#include "fast_trig.h" +#include "num/num.h" + +static libnum::num cosTable[360]; +static libnum::num sinTable[360]; +static bool is_fast_trig_initialised = false; + +void Fast_Trig_Init( void ) +{ + for(int u=0; u<360; u++) + { + cosTable[u] = libnum::num( cos( u * PI / 180 ) ); + sinTable[u] = libnum::num( sin( u * PI / 180 ) ); + } + is_fast_trig_initialised = true; +} + + +libnum::num FastCosInt( int16_t angle ) +{ + if (!is_fast_trig_initialised) Fast_Trig_Init(); + + if (angle>=0 and angle<360) return cosTable[ angle ]; + else + { + int16_t input = angle; + if (input<0) + { + while (input<0) input+=360; + return cosTable[ input ]; + } + else + { + while (input>=360) input-=360; + return cosTable[ input ]; + } + } +} + +libnum::num FastSinInt( int16_t angle ) +{ + if (!is_fast_trig_initialised) Fast_Trig_Init(); + + if (angle>=0 and angle<360) return sinTable[ angle ]; + else + { + int16_t input = angle; + if (input<0) + { + while (input<0) input+=360; + return sinTable[ input ]; + } + else + { + while (input>=360) input-=360; + return sinTable[ input ]; + } + } +} + +libnum::num FastTanInt( int16_t angle ) +{ + if (!is_fast_trig_initialised) Fast_Trig_Init(); + + int16_t input = angle; + + if (input<0) + { + while (input<0) input+=360; + } + else if (input>=360) + { + while (input>=360) input-=360; + } + + libnum::num value; + + if (input==90) + { + value.v = INT32_MAX; + return value; + } + else if (input==270) + { + value.v = INT32_MIN; + return value; + } + else + { + value = FastSinInt(input) / FastCosInt(input); + return value; + } +} + + + +libnum::num32 sqrt_num32(libnum::num32 v) { + uint32_t t, q, b, r; + r = v.v; + b = 0x40000000; + q = 0; + while (b > 0x40) { + t = q + b; + if (r >= t) { + r -= t; + q = t + b; + } + r <<= 1; + b >>= 1; + } + q >>= 8; + libnum::num32 ret; + ret.v = q; + return ret; +} + +/* TO DO : rework these functions for sine and cosine calculation */ + +libnum::num32 cos_num32(libnum::num32 angle) { + // Taylor serie for cos(x) = 1 - x²/2! + x⁴/4! + x⁶/6! + x⁸/8! + ... + + // Cosine function is even + if (angle < libnum::num32(0)) + return cos_num32(-angle); + + // Look for an angle in the range [0, 2*pi [ + libnum::num32 anglereduced = angle; + while (anglereduced >= libnum::num32(2 * PI)) + anglereduced -= libnum::num32(2 * PI); + + // Exploit the symetry for angle and angle+Pi to reduce the order of the + // limited developpement + if (anglereduced >= libnum::num(PI)) + return -cos_num32(anglereduced - libnum::num(PI)); + + libnum::num32 sum = libnum::num32(1); + libnum::num32 angle2 = anglereduced * anglereduced; + + // set first value of the Taylor serie : x⁰/0! = 1/1 + libnum::num32 numerator = libnum::num32(1); + libnum::num32 denominator = libnum::num32(1); + + for (int i = 2; i <= 8; i += 2) { + numerator *= (-angle2); + denominator *= libnum::num32(i - 1) * libnum::num32(i); + sum += (numerator / denominator); + } + + return sum; +} + +libnum::num32 sin_num32(libnum::num32 angle) { + // Taylor serie for cos(x) = x/1! - x³/3! + x⁵/5! - x⁷/7! + x⁹/9! + ... + + // Sine function is odd + if (angle < libnum::num32(0)) + return -sin_num32(-angle); + + // Look for an angle in the range [0, 2*pi [ + libnum::num32 anglereduced = angle; + while (anglereduced >= libnum::num32(2 * PI)) + anglereduced -= libnum::num32(2 * PI); + + // Exploit the symetry for angle and angle+Pi to reduce the order of the + // limited developpement + if (anglereduced >= libnum::num(PI)) + return -sin_num32(anglereduced - libnum::num(PI)); + + libnum::num32 sum = anglereduced; + libnum::num32 angle2 = anglereduced * anglereduced; + + // set first value of the Taylor serie : x¹/1! = x/1 + libnum::num32 numerator = anglereduced; + libnum::num32 denominator = libnum::num32(1); + + for (int i = 2; i <= 8; i += 2) { + numerator *= (-angle2); + denominator *= libnum::num32(i) * libnum::num32(i + 1); + sum += (numerator / denominator); + } + + return sum; +} diff --git a/src/fast_trig.h b/src/utilities/fast_trig.h similarity index 61% rename from src/fast_trig.h rename to src/utilities/fast_trig.h index 7b4b372..30d0648 100644 --- a/src/fast_trig.h +++ b/src/utilities/fast_trig.h @@ -5,9 +5,7 @@ #include #include - -#define PI 3.141592 - +#define PI 3.14159265 void Fast_Trig_Init( void ); @@ -15,5 +13,10 @@ libnum::num FastCosInt( int16_t angle ); libnum::num FastSinInt( int16_t angle ); libnum::num FastTanInt( int16_t angle ); +libnum::num32 sqrt_num32(libnum::num32 v); +libnum::num32 cos_num32(libnum::num32 angle); +libnum::num32 sin_num32(libnum::num32 angle); + + #endif diff --git a/src/utilities.cpp b/src/utilities/utilities.cpp similarity index 99% rename from src/utilities.cpp rename to src/utilities/utilities.cpp index 2901865..f216315 100644 --- a/src/utilities.cpp +++ b/src/utilities/utilities.cpp @@ -1,4 +1,4 @@ -#include "config.h" +#include "../config.h" #include #include diff --git a/src/utilities.h b/src/utilities/utilities.h similarity index 100% rename from src/utilities.h rename to src/utilities/utilities.h diff --git a/src/utilities/vector2D.cpp b/src/utilities/vector2D.cpp new file mode 100644 index 0000000..8b43540 --- /dev/null +++ b/src/utilities/vector2D.cpp @@ -0,0 +1,111 @@ +#include "vector2D.h" +#include "fast_trig.h" + +Vector2D::Vector2D() { + this->x = libnum::num32(0); + this->y = libnum::num32(0); + } + + Vector2D::Vector2D(float x, float y) { + this->x = libnum::num32(x); + this->y = libnum::num32(y); + } + + Vector2D::Vector2D(libnum::num32 x, libnum::num32 y) { + this->x = x; + this->y = y; + } + + Vector2D::Vector2D(const Vector2D &v) { + this->x = v.x; + this->y = v.y; + } + + Vector2D::~Vector2D() {} + + void Vector2D::Set(Vector2D v) { + this->x = v.x; + this->y = v.y; + } + + void Vector2D::Normalise(void) { + libnum::num32 len = this->Length(); + this->x /= len; + this->y /= len; + } + + Vector2D Vector2D::Clone(void) { + Vector2D NewVector(this->x, this->y); + return NewVector; + } + + Vector2D Vector2D::MakeVector(Vector2D A, Vector2D B) { + Vector2D NewVector(B.x - A.x, B.y - A.y); + return NewVector; + } + + void Vector2D::AddVectors(Vector2D a, Vector2D b) { + this->x = a.x + b.x; + this->y = a.y + b.y; + } + + void Vector2D::Add(Vector2D v, libnum::num32 scale) { + this->x += v.x * scale; + this->y += v.y * scale; + } + + void Vector2D::SubtractVectors(Vector2D a, Vector2D b) { + this->x = a.x - b.x; + this->y = a.y - b.y; + } + + void Vector2D::Subtract(Vector2D v, libnum::num32 scale) { + this->x -= v.x * scale; + this->y -= v.y * scale; + } + + libnum::num32 Vector2D::Length(void) { + return sqrt_num32(this->x * this->x + this->y * this->y); + } + + void Vector2D::Scale(libnum::num32 scale) { + this->x *= scale; + this->y *= scale; + } + + libnum::num32 Vector2D::Dot(Vector2D v) { return (this->x * v.x + this->y * v.y); } + + libnum::num32 Vector2D::Det(Vector2D v) { return (this->x * v.y - this->y * v.x); } + + Vector2D Vector2D::PerpCW(void) { + Vector2D temp(-this->y, this->x); + return temp; + } + + Vector2D Vector2D::PerpCCW(void) { + Vector2D temp(this->y, -this->x); + return temp; + } + + + +Vector2D ClosestPointOnSegment(Vector2D P, Vector2D A, Vector2D B) { + Vector2D AB = B - A; + + libnum::num32 t = AB.Dot(AB); + + if (t == 0) + return A; + + libnum::num32 t2 = (P.Dot(AB) - A.Dot(AB)) / t; + + if (t2 < libnum::num32(0)) + t2 = libnum::num32(0); + if (t2 > libnum::num32(1)) + t2 = libnum::num32(1); + + Vector2D C = A.Clone(); + C.Add(AB, t2); + + return C; +} \ No newline at end of file diff --git a/src/utilities/vector2D.h b/src/utilities/vector2D.h new file mode 100644 index 0000000..a58d20d --- /dev/null +++ b/src/utilities/vector2D.h @@ -0,0 +1,112 @@ +#ifndef VECTOR2D_H +#define VECTOR2D_H + +#include +#include +#include "fast_trig.h" + + +class Vector2D { +public: + Vector2D(); + Vector2D(float x, float y); + Vector2D(libnum::num32 x, libnum::num32 y); + Vector2D(const Vector2D &v); + ~Vector2D(); + + void Set(Vector2D v); + + void Normalise(void); + + Vector2D Clone(void); + Vector2D MakeVector(Vector2D A, Vector2D B); + + void AddVectors(Vector2D a, Vector2D b); + void Add(Vector2D v, libnum::num32 scale); + void SubtractVectors(Vector2D a, Vector2D b); + void Subtract(Vector2D v, libnum::num32 scale); + + libnum::num32 Length(void); + void Scale(libnum::num32 scale); + + libnum::num32 Dot(Vector2D v); + libnum::num32 Det(Vector2D v); + + Vector2D PerpCW(void); + Vector2D PerpCCW(void); + + /* overloading of most interesting operators */ + libnum::num32 operator[](uint8_t pos) { return pos == 0 ? x : y; } + + Vector2D &operator=(const Vector2D &v) { + this->x = v.x; + this->y = v.y; + return *this; + } + + Vector2D operator+(const Vector2D &v) const { + return Vector2D(x + v.x, y + v.y); + } + + Vector2D operator-(const Vector2D &v) const { + return Vector2D(x - v.x, y - v.y); + } + + Vector2D &operator+=(Vector2D const &other) { + this->x += other.x; + this->y += other.y; + return *this; + } + + Vector2D operator-() const { return (Vector2D(-x, -y)); } + + Vector2D operator+() const { return *this; } + + Vector2D &operator-=(Vector2D const &other) { + this->x -= other.x; + this->y -= other.y; + return *this; + } + + Vector2D &operator*=(libnum::num32 scale) { + this->x *= scale; + this->y *= scale; + return *this; + } + + Vector2D &operator/=(libnum::num32 scale) { + this->x /= scale; + this->y /= scale; + return *this; + } + + friend Vector2D operator*(libnum::num32 scale, Vector2D const &v) { + Vector2D r; + r.x = v.x * scale; + r.y = v.y * scale; + return r; + } + + friend Vector2D operator*(Vector2D const &v, libnum::num32 scale) { + Vector2D r; + r.x = v.x * scale; + r.y = v.y * scale; + return r; + } + + friend Vector2D operator/(Vector2D const &v, libnum::num32 scale) { + Vector2D r; + r.x = v.x / scale; + r.y = v.y / scale; + return r; + } + + libnum::num32 x; + libnum::num32 y; +}; + + +Vector2D ClosestPointOnSegment(Vector2D P, Vector2D A, Vector2D B); + + +#endif \ No newline at end of file diff --git a/src/vector2D.h b/src/vector2D.h deleted file mode 100644 index 52b77ea..0000000 --- a/src/vector2D.h +++ /dev/null @@ -1,278 +0,0 @@ -#ifndef VECTOR2D_H -#define VECTOR2D_H - -#include -#include - -#define numPI 3.14159265 - -libnum::num32 sqrt_num32(libnum::num32 v) { - uint32_t t, q, b, r; - r = v.v; - b = 0x40000000; - q = 0; - while (b > 0x40) { - t = q + b; - if (r >= t) { - r -= t; - q = t + b; - } - r <<= 1; - b >>= 1; - } - q >>= 8; - libnum::num32 ret; - ret.v = q; - return ret; -} - -/* TO DO : rework these functions for sine and cosine calculation */ - -libnum::num32 cos_num32(libnum::num32 angle) { - // Taylor serie for cos(x) = 1 - x²/2! + x⁴/4! + x⁶/6! + x⁸/8! + ... - - // Cosine function is even - if (angle < libnum::num32(0)) - return cos_num32(-angle); - - // Look for an angle in the range [0, 2*pi [ - libnum::num32 anglereduced = angle; - while (anglereduced >= libnum::num32(2 * numPI)) - anglereduced -= libnum::num32(2 * numPI); - - // Exploit the symetry for angle and angle+Pi to reduce the order of the - // limited developpement - if (anglereduced >= libnum::num(numPI)) - return -cos_num32(anglereduced - libnum::num(numPI)); - - libnum::num32 sum = libnum::num32(1); - libnum::num32 angle2 = anglereduced * anglereduced; - - // set first value of the Taylor serie : x⁰/0! = 1/1 - libnum::num32 numerator = libnum::num32(1); - libnum::num32 denominator = libnum::num32(1); - - for (int i = 2; i <= 8; i += 2) { - numerator *= (-angle2); - denominator *= libnum::num32(i - 1) * libnum::num32(i); - sum += (numerator / denominator); - } - - return sum; -} - -libnum::num32 sin_num32(libnum::num32 angle) { - // Taylor serie for cos(x) = x/1! - x³/3! + x⁵/5! - x⁷/7! + x⁹/9! + ... - - // Sine function is odd - if (angle < libnum::num32(0)) - return -sin_num32(-angle); - - // Look for an angle in the range [0, 2*pi [ - libnum::num32 anglereduced = angle; - while (anglereduced >= libnum::num32(2 * numPI)) - anglereduced -= libnum::num32(2 * numPI); - - // Exploit the symetry for angle and angle+Pi to reduce the order of the - // limited developpement - if (anglereduced >= libnum::num(numPI)) - return -sin_num32(anglereduced - libnum::num(numPI)); - - libnum::num32 sum = anglereduced; - libnum::num32 angle2 = anglereduced * anglereduced; - - // set first value of the Taylor serie : x¹/1! = x/1 - libnum::num32 numerator = anglereduced; - libnum::num32 denominator = libnum::num32(1); - - for (int i = 2; i <= 8; i += 2) { - numerator *= (-angle2); - denominator *= libnum::num32(i) * libnum::num32(i + 1); - sum += (numerator / denominator); - } - - return sum; -} - -class Vector2D { - -public: - Vector2D() { - this->x = libnum::num32(0); - this->y = libnum::num32(0); - } - - Vector2D(float x, float y) { - this->x = libnum::num32(x); - this->y = libnum::num32(y); - } - - Vector2D(libnum::num32 x, libnum::num32 y) { - this->x = x; - this->y = y; - } - - Vector2D(const Vector2D &v) { - this->x = v.x; - this->y = v.y; - } - - ~Vector2D() {} - - void Set(Vector2D v) { - this->x = v.x; - this->y = v.y; - } - - void Normalise(void) { - libnum::num32 len = this->Length(); - this->x /= len; - this->y /= len; - } - - Vector2D Clone(void) { - Vector2D NewVector(this->x, this->y); - return NewVector; - } - - Vector2D MakeVector(Vector2D A, Vector2D B) { - Vector2D NewVector(B.x - A.x, B.y - A.y); - return NewVector; - } - - void AddVectors(Vector2D a, Vector2D b) { - this->x = a.x + b.x; - this->y = a.y + b.y; - } - - void Add(Vector2D v, libnum::num32 scale) { - this->x += v.x * scale; - this->y += v.y * scale; - } - - void SubtractVectors(Vector2D a, Vector2D b) { - this->x = a.x - b.x; - this->y = a.y - b.y; - } - - void Subtract(Vector2D v, libnum::num32 scale) { - this->x -= v.x * scale; - this->y -= v.y * scale; - } - - libnum::num32 Length(void) { - return sqrt_num32(this->x * this->x + this->y * this->y); - } - - void Scale(libnum::num32 scale) { - this->x *= scale; - this->y *= scale; - } - - libnum::num32 Dot(Vector2D v) { return (this->x * v.x + this->y * v.y); } - - libnum::num32 Det(Vector2D v) { return (this->x * v.y - this->y * v.x); } - - Vector2D PerpCW(void) { - Vector2D temp(-this->y, this->x); - return temp; - } - - Vector2D PerpCCW(void) { - Vector2D temp(this->y, -this->x); - return temp; - } - - /* overloading of most interesting operators */ - libnum::num32 operator[](uint8_t pos) { return pos == 0 ? x : y; } - - Vector2D &operator=(const Vector2D &v) { - this->x = v.x; - this->y = v.y; - return *this; - } - - Vector2D operator+(const Vector2D &v) const { - return Vector2D(x + v.x, y + v.y); - } - - Vector2D operator-(const Vector2D &v) const { - return Vector2D(x - v.x, y - v.y); - } - - Vector2D &operator+=(Vector2D const &other) { - this->x += other.x; - this->y += other.y; - return *this; - } - - Vector2D operator-() const { return (Vector2D(-x, -y)); } - - Vector2D operator+() const { return *this; } - - Vector2D &operator-=(Vector2D const &other) { - this->x -= other.x; - this->y -= other.y; - return *this; - } - - Vector2D &operator*=(libnum::num32 scale) { - this->x *= scale; - this->y *= scale; - return *this; - } - - Vector2D &operator/=(libnum::num32 scale) { - this->x /= scale; - this->y /= scale; - return *this; - } - - friend Vector2D operator*(libnum::num32 scale, Vector2D const &v) { - Vector2D r; - r.x = v.x * scale; - r.y = v.y * scale; - return r; - } - - friend Vector2D operator*(Vector2D const &v, libnum::num32 scale) { - Vector2D r; - r.x = v.x * scale; - r.y = v.y * scale; - return r; - } - - friend Vector2D operator/(Vector2D const &v, libnum::num32 scale) { - Vector2D r; - r.x = v.x / scale; - r.y = v.y / scale; - return r; - } - - libnum::num32 x; - libnum::num32 y; -}; - - -Vector2D ClosestPointOnSegment(Vector2D P, Vector2D A, Vector2D B) { - Vector2D AB = B - A; - - libnum::num32 t = AB.Dot(AB); - - if (t == 0) - return A; - - libnum::num32 t2 = (P.Dot(AB) - A.Dot(AB)) / t; - - if (t2 < libnum::num32(0)) - t2 = libnum::num32(0); - if (t2 > libnum::num32(1)) - t2 = libnum::num32(1); - - Vector2D C = A.Clone(); - C.Add(AB, t2); - - return C; -} - -#endif \ No newline at end of file