From 87242d0a6c818e675676cdfb68013dc3af5a7656 Mon Sep 17 00:00:00 2001 From: inmarket Date: Fri, 21 Nov 2014 17:09:44 +1000 Subject: [PATCH] Add MatrixFloat2D and MatrixFixed2D operations to GMISC. Add polygon demo --- demos/modules/gdisp/polygons/demo.mk | 3 + demos/modules/gdisp/polygons/gfxconf.h | 66 +++++++ demos/modules/gdisp/polygons/main.c | 160 +++++++++++++++ docs/releases.txt | 2 + gfxconf.example.h | 2 + src/gmisc/gmisc_matrix2d.c | 196 +++++++++++++++++++ src/gmisc/sys_defs.h | 260 ++++++++++++++++++++++++- src/gmisc/sys_make.mk | 1 + 8 files changed, 684 insertions(+), 6 deletions(-) create mode 100644 demos/modules/gdisp/polygons/demo.mk create mode 100644 demos/modules/gdisp/polygons/gfxconf.h create mode 100644 demos/modules/gdisp/polygons/main.c create mode 100644 src/gmisc/gmisc_matrix2d.c diff --git a/demos/modules/gdisp/polygons/demo.mk b/demos/modules/gdisp/polygons/demo.mk new file mode 100644 index 00000000..81510914 --- /dev/null +++ b/demos/modules/gdisp/polygons/demo.mk @@ -0,0 +1,3 @@ +DEMODIR = $(GFXLIB)/demos/modules/gdisp/polygons +GFXINC += $(DEMODIR) +GFXSRC += $(DEMODIR)/main.c diff --git a/demos/modules/gdisp/polygons/gfxconf.h b/demos/modules/gdisp/polygons/gfxconf.h new file mode 100644 index 00000000..51170ecc --- /dev/null +++ b/demos/modules/gdisp/polygons/gfxconf.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2012, 2013, Joel Bodenmann aka Tectu + * Copyright (c) 2012, 2013, Andrew Hannam aka inmarket + * + * 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. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 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 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. + */ + +#ifndef _GFXCONF_H +#define _GFXCONF_H + +/* The operating system to use. One of these must be defined - preferably in your Makefile */ +//#define GFX_USE_OS_CHIBIOS FALSE +//#define GFX_USE_OS_WIN32 FALSE +//#define GFX_USE_OS_LINUX FALSE +//#define GFX_USE_OS_OSX FALSE + +/* GFX sub-systems to turn on */ +#define GFX_USE_GDISP TRUE +#define GFX_USE_GMISC TRUE + +/* Features for the GDISP sub-system. */ +#define GDISP_NEED_VALIDATION TRUE +#define GDISP_NEED_CLIP TRUE +#define GDISP_NEED_CONVEX_POLYGON TRUE + +/* For this demo define either: + * GMISC_NEED_MATRIXFLOAT2D to use floating point math operations + * + * or + * + * GMISC_NEED_MATRIXFIXED2D to use fixed point math operations. + * + * If you choose floating point you may optionally define GMISC_NEED_FASTTRIG. + * If you choose fixed point you MUST define GMISC_NEED_FIXEDTRIG for this demo. + */ + +//#define GMISC_NEED_FASTTRIG TRUE +//#define GMISC_NEED_MATRIXFLOAT2D TRUE + +#define GMISC_NEED_FIXEDTRIG TRUE +#define GMISC_NEED_MATRIXFIXED2D TRUE + +#endif /* _GFXCONF_H */ + diff --git a/demos/modules/gdisp/polygons/main.c b/demos/modules/gdisp/polygons/main.c new file mode 100644 index 00000000..f71505d9 --- /dev/null +++ b/demos/modules/gdisp/polygons/main.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2012, 2013, Joel Bodenmann aka Tectu + * Copyright (c) 2012, 2013, Andrew Hannam aka inmarket + * + * 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. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 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 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. + */ + +#include "gfx.h" +#include + +#define FRAME_DELAY 100 /* The interframe delay in milliseconds */ + +// Our shape definition +static const point shape[] = { + { 10, 10 }, + { 10, 15 }, + { 17, 17 }, + { 20, 5 }, + { 10, 0 }, + { 3, -10}, + { -7, -15}, + { -15, -15}, + { -13, -12 }, + { -8, 0 }, +}; + +#define NUM_POINTS (sizeof(shape)/sizeof(shape[0])) + +// Where we put our calculated points +static point result[NUM_POINTS]; +static point oldresult[NUM_POINTS]; + +// Make fixed point and floating point options look pretty similar +#if GMISC_NEED_MATRIXFLOAT2D + static MatrixFloat2D m1, m2; + typedef float mtype; + #define FP2MTYPE(f) (f) + #define INT2MTYPE(i) (i) +#elif GMISC_NEED_MATRIXFIXED2D + static MatrixFixed2D m1, m2; + typedef fixed mtype; + #define FP2MTYPE(f) FP2FIXED(f) + #define INT2MTYPE(i) FIXED(i) +#else + #error "Either GMISC_NEED_MATRIXFLOAT2D or GMISC_NEED_MATRIXFIXED2D must be defined for this demo" +#endif + + +int main(void) { + coord_t width, height; + mtype scalex, scaley; + mtype scaleincx, scaleincy; + mtype translatex, translatey; + mtype transincx, transincy; + mtype transmaxx, transmaxy; + mtype transminx, transminy; + int angle; + int angleinc; + + // Initialize and clear the display + gfxInit(); + gdispClear(White); + + // Get the screen size + width = gdispGetWidth(); + height = gdispGetHeight(); + + // Initial position, rotation and scale + scalex = scaley = FP2MTYPE(1.0); + translatex = INT2MTYPE(width/2); + translatey = INT2MTYPE(height/2); + angle = 0; + + // How much to change the position, rotation and scale each cycle + scaleincx = scaleincy = FP2MTYPE(0.5); + transincx = INT2MTYPE(2); + transincy = INT2MTYPE(-2); + angleinc = 2; + transmaxx = INT2MTYPE(width - 15); + transminx = INT2MTYPE(15); + transmaxy = INT2MTYPE(height - 15); + transminy = INT2MTYPE(15); + + while(TRUE) { + + // Move to the new location, rotation and scale + scalex += scaleincx; + scaley += scaleincy; + angle += angleinc; + if (angle >= 360) + angle -= 360; + translatex += transincx; + translatey += transincy; + + // Adjust our speed etc + if (scalex > FP2MTYPE(10.0)) scaleincx = FP2MTYPE(-0.3); + else if (scalex < FP2MTYPE(1.0)) scaleincx = FP2MTYPE(0.5); + if (scaley > FP2MTYPE(7.0)) scaleincy = FP2MTYPE(-0.25); + else if (scaley < FP2MTYPE(1.0)) scaleincy = FP2MTYPE(0.3); + if (translatex > transmaxx || translatex < transminx) transincx = -transincx; + if (translatey > transmaxy || translatey < transminy) transincy = -transincy; + + // Build a matrix of all the operations we want to do and then apply it to all the shape points + #if GMISC_NEED_MATRIXFLOAT2D + gmiscMatrixFloat2DApplyScale(&m1, 0, scalex, scaley); + gmiscMatrixFloat2DApplyRotation(&m2, &m1, angle); + gmiscMatrixFloat2DApplyTranslation(&m1, &m2, translatex, translatey); + gmiscMatrixFloat2DApplyToPoints(result, shape, &m1, NUM_POINTS); + #else + gmiscMatrixFixed2DApplyScale(&m1, 0, scalex, scaley); + gmiscMatrixFixed2DApplyRotation(&m2, &m1, angle); + gmiscMatrixFixed2DApplyTranslation(&m1, &m2, translatex, translatey); + gmiscMatrixFixed2DApplyToPoints(result, shape, &m1, NUM_POINTS); + #endif + + // Clear the old shape + gdispDrawPoly(0, 0, oldresult, NUM_POINTS, White); + gdispFillConvexPoly(0, 0, oldresult, NUM_POINTS, White); + + // Play the new shape position + // NOTE: Because our shape is not a true convex polygon, we get some frames + // where the line outline and the filled shape don't match. This is + // expected due to the shapes non-convex nature and was left in the + // demo to demonstrate this exact point. + gdispFillConvexPoly(0, 0, result, NUM_POINTS, Red); + gdispDrawPoly(0, 0, result, NUM_POINTS, Blue); + + // Make sure the display is updated + gdispFlush(); + + // Save the results so we can clear them next cycle + memcpy(oldresult, result, sizeof(result)); + + // Delay for a while + gfxSleepMilliseconds(FRAME_DELAY); + } +} + diff --git a/docs/releases.txt b/docs/releases.txt index d76f335b..79e27cc2 100644 --- a/docs/releases.txt +++ b/docs/releases.txt @@ -38,6 +38,8 @@ DEPRECATE: gwinAttachMouse() is now handled automaticly. FEATURE: Added MAX11802 touch driver by user steved FEATURE: Added STM32F429i-Discovery board support FEATURE: Added DejaVuSans20 and DejaVuSans20_aa built-in fonts +FEATURE: Added MatrixFloat2D and MatrixFixed2D operations to GMISC +FEATURE: Added polygon drawing demo (with rotation, scaling and translation) *** Release 2.1 *** diff --git a/gfxconf.example.h b/gfxconf.example.h index 579b2f6c..e4d54bbf 100644 --- a/gfxconf.example.h +++ b/gfxconf.example.h @@ -279,5 +279,7 @@ //#define GMISC_NEED_INVSQRT FALSE // #define GMISC_INVSQRT_MIXED_ENDIAN FALSE // #define GMISC_INVSQRT_REAL_SLOW FALSE +//#define GMISC_NEED_MATRIXFLOAT2D FALSE +//#define GMISC_NEED_MATRIXFIXED2D FALSE #endif /* _GFXCONF_H */ diff --git a/src/gmisc/gmisc_matrix2d.c b/src/gmisc/gmisc_matrix2d.c new file mode 100644 index 00000000..dd13603e --- /dev/null +++ b/src/gmisc/gmisc_matrix2d.c @@ -0,0 +1,196 @@ +/* + * This file is subject to the terms of the GFX License. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://ugfx.org/license.html + */ + +/** + * @file src/gmisc/gmisc_matrix2d.c + * @brief GMISC 2D matrix operations code. + */ +#include "gfx.h" + +#if GFX_USE_GMISC + +#if GMISC_NEED_MATRIXFLOAT2D + +#if !GMISC_NEED_FASTTRIG + #include +#endif + +void gmiscMatrixFloat2DSetIdentity(MatrixFloat2D *m) { + m->a00 = m->a11 = m->a22 = 1.0; + m->a01 = m->a02 = m->a10 = m->a12 = m->a20 = m->a21 = 0.0; +} + +void gmiscMatrixFloat2DMultiply(MatrixFloat2D *dst, const MatrixFloat2D *src1, const MatrixFloat2D *src2) { + dst->a00 = src1->a00*src2->a00 + src1->a01*src2->a10 + src1->a02*src2->a20; + dst->a01 = src1->a00*src2->a01 + src1->a01*src2->a11 + src1->a02*src2->a21; + dst->a02 = src1->a00*src2->a02 + src1->a01*src2->a12 + src1->a02*src2->a22; + dst->a10 = src1->a10*src2->a00 + src1->a11*src2->a10 + src1->a12*src2->a20; + dst->a11 = src1->a10*src2->a01 + src1->a11*src2->a11 + src1->a12*src2->a21; + dst->a12 = src1->a10*src2->a02 + src1->a11*src2->a12 + src1->a12*src2->a22; + dst->a20 = src1->a20*src2->a00 + src1->a21*src2->a10 + src1->a22*src2->a20; + dst->a21 = src1->a20*src2->a01 + src1->a21*src2->a11 + src1->a22*src2->a21; + dst->a22 = src1->a20*src2->a02 + src1->a21*src2->a12 + src1->a22*src2->a22; +} + +void gmiscMatrixFloat2DApplyTranslation(MatrixFloat2D *dst, const MatrixFloat2D *src, float tx, float ty) { + if (src) { + dst->a00 = src->a00; dst->a01 = src->a01; dst->a02 = src->a02+tx; + dst->a10 = src->a10; dst->a11 = src->a11; dst->a12 = src->a12+ty; + dst->a20 = src->a20; dst->a21 = src->a21; dst->a22 = src->a22; + } else { + dst->a00 = 1.0; dst->a01 = 0.0; dst->a02 = tx; + dst->a10 = 0.0; dst->a11 = 1.0; dst->a12 = ty; + dst->a20 = 0.0; dst->a21 = 0.0; dst->a22 = 1.0; + } +} + +void gmiscMatrixFloat2DApplyScale(MatrixFloat2D *dst, const MatrixFloat2D *src, float sx, float sy) { + if (src) { + dst->a00 = src->a00*sx; dst->a01 = src->a01*sy; dst->a02 = src->a02; + dst->a10 = src->a10*sx; dst->a11 = src->a11*sy; dst->a12 = src->a12; + dst->a20 = src->a20*sx; dst->a21 = src->a21*sy; dst->a22 = src->a22; + } else { + dst->a00 = sx; dst->a01 = 0.0; dst->a02 = 0.0; + dst->a10 = 0.0; dst->a11 = sy; dst->a12 = 0.0; + dst->a20 = 0.0; dst->a21 = 0.0; dst->a22 = 1.0; + } +} + +void gmiscMatrixFloat2DApplyShear(MatrixFloat2D *dst, const MatrixFloat2D *src, float sx, float sy) { + if (src) { + dst->a00 = src->a00 + src->a01*sy; dst->a01 = src->a00*sx + src->a01; dst->a02 = src->a02; + dst->a10 = src->a10 + src->a11*sy; dst->a11 = src->a10*sx + src->a11; dst->a12 = src->a12; + dst->a20 = src->a20 + src->a21*sy; dst->a21 = src->a20*sx + src->a21; dst->a22 = src->a22; + } else { + dst->a00 = 1.0; dst->a01 = sx; dst->a02 = 0.0; + dst->a10 = sy; dst->a11 = 1.0; dst->a12 = 0.0; + dst->a20 = 0.0; dst->a21 = 0.0; dst->a22 = 1.0; + } +} + +void gmiscMatrixFloat2DApplyRotation(MatrixFloat2D *dst, const MatrixFloat2D *src, int angle) { + float s, c; + + #if GMISC_NEED_FASTTRIG + s = fsin(angle); + c = fcos(angle); + #else + c = angle*M_PI/180; + s = sin(c); + c = cos(c); + #endif + + if (src) { + dst->a00 = src->a00*c - src->a01*s; dst->a01 = src->a00*s + src->a01*c; dst->a02 = src->a02; + dst->a10 = src->a10*c - src->a11*s; dst->a11 = src->a10*s + src->a11*c; dst->a12 = src->a12; + dst->a20 = src->a20*c - src->a21*s; dst->a21 = src->a20*s + src->a21*c; dst->a22 = src->a22; + } else { + dst->a00 = c; dst->a01 = s; dst->a02 = 0.0; + dst->a10 = -s; dst->a11 = c; dst->a12 = 0.0; + dst->a20 = 0.0; dst->a21 = 0.0; dst->a22 = 1.0; + } +} + +void gmiscMatrixFloat2DApplyToPoints(point *dst, const point *src, const MatrixFloat2D *m, int cnt) { + float x; + + for( ;cnt--; dst++, src++) { + x = src->x; // This allows in-place operation + dst->x = round(x*m->a00+src->y*m->a01+m->a02); + dst->y = round(x*m->a10+src->y*m->a11+m->a12); + } +} + +#endif // GMISC_NEED_MATRIXFLOAT2D + +#if GMISC_NEED_MATRIXFIXED2D + +void gmiscMatrixFixed2DSetIdentity(MatrixFixed2D *m) { + m->a00 = m->a11 = m->a22 = FIXED(1); + m->a01 = m->a02 = m->a10 = m->a12 = m->a20 = m->a21 = 0; +} + +void gmiscMatrixFixed2DMultiply(MatrixFixed2D *dst, const MatrixFixed2D *src1, const MatrixFixed2D *src2) { + dst->a00 = FIXEDMUL(src1->a00,src2->a00) + FIXEDMUL(src1->a01,src2->a10) + FIXEDMUL(src1->a02,src2->a20); + dst->a01 = FIXEDMUL(src1->a00,src2->a01) + FIXEDMUL(src1->a01,src2->a11) + FIXEDMUL(src1->a02,src2->a21); + dst->a02 = FIXEDMUL(src1->a00,src2->a02) + FIXEDMUL(src1->a01,src2->a12) + FIXEDMUL(src1->a02,src2->a22); + dst->a10 = FIXEDMUL(src1->a10,src2->a00) + FIXEDMUL(src1->a11,src2->a10) + FIXEDMUL(src1->a12,src2->a20); + dst->a11 = FIXEDMUL(src1->a10,src2->a01) + FIXEDMUL(src1->a11,src2->a11) + FIXEDMUL(src1->a12,src2->a21); + dst->a12 = FIXEDMUL(src1->a10,src2->a02) + FIXEDMUL(src1->a11,src2->a12) + FIXEDMUL(src1->a12,src2->a22); + dst->a20 = FIXEDMUL(src1->a20,src2->a00) + FIXEDMUL(src1->a21,src2->a10) + FIXEDMUL(src1->a22,src2->a20); + dst->a21 = FIXEDMUL(src1->a20,src2->a01) + FIXEDMUL(src1->a21,src2->a11) + FIXEDMUL(src1->a22,src2->a21); + dst->a22 = FIXEDMUL(src1->a20,src2->a02) + FIXEDMUL(src1->a21,src2->a12) + FIXEDMUL(src1->a22,src2->a22); +} + +void gmiscMatrixFixed2DApplyTranslation(MatrixFixed2D *dst, const MatrixFixed2D *src, fixed tx, fixed ty) { + if (src) { + dst->a00 = src->a00; dst->a01 = src->a01; dst->a02 = src->a02+tx; + dst->a10 = src->a10; dst->a11 = src->a11; dst->a12 = src->a12+ty; + dst->a20 = src->a20; dst->a21 = src->a21; dst->a22 = src->a22; + } else { + dst->a00 = FIXED(1); dst->a01 = 0; dst->a02 = tx; + dst->a10 = 0; dst->a11 = FIXED(1); dst->a12 = ty; + dst->a20 = 0; dst->a21 = 0; dst->a22 = FIXED(1); + } +} + +void gmiscMatrixFixed2DApplyScale(MatrixFixed2D *dst, const MatrixFixed2D *src, fixed sx, fixed sy) { + if (src) { + dst->a00 = FIXEDMUL(sx,src->a00); dst->a01 = FIXEDMUL(sy,src->a01); dst->a02 = src->a02; + dst->a10 = FIXEDMUL(sx,src->a10); dst->a11 = FIXEDMUL(sy,src->a11); dst->a12 = src->a12; + dst->a20 = FIXEDMUL(sx,src->a20); dst->a21 = FIXEDMUL(sy,src->a21); dst->a22 = src->a22; + } else { + dst->a00 = sx; dst->a01 = 0; dst->a02 = 0; + dst->a10 = 0; dst->a11 = sy; dst->a12 = 0; + dst->a20 = 0; dst->a21 = 0; dst->a22 = FIXED(1); + } +} + +void gmiscMatrixFixed2DApplyShear(MatrixFixed2D *dst, const MatrixFixed2D *src, fixed sx, fixed sy) { + if (src) { + dst->a00 = src->a00 + FIXEDMUL(sy,src->a01); dst->a01 = FIXEDMUL(sx,src->a00) + src->a01; dst->a02 = src->a02; + dst->a10 = src->a10 + FIXEDMUL(sy,src->a11); dst->a11 = FIXEDMUL(sx,src->a10) + src->a11; dst->a12 = src->a12; + dst->a20 = src->a20 + FIXEDMUL(sy,src->a21); dst->a21 = FIXEDMUL(sx,src->a20) + src->a21; dst->a22 = src->a22; + } else { + dst->a00 = FIXED(1); dst->a01 = sx; dst->a02 = 0; + dst->a10 = sy; dst->a11 = FIXED(1); dst->a12 = 0; + dst->a20 = 0; dst->a21 = 0; dst->a22 = FIXED(1); + } +} + +#if GMISC_NEED_FIXEDTRIG + void gmiscMatrixFixed2DApplyRotation(MatrixFixed2D *dst, const MatrixFixed2D *src, int angle) { + fixed s, c; + + s = ffsin(angle); + c = ffcos(angle); + + if (src) { + dst->a00 = FIXEDMUL(c,src->a00) - FIXEDMUL(s,src->a01); dst->a01 = FIXEDMUL(s,src->a00) + FIXEDMUL(c,src->a01); dst->a02 = src->a02; + dst->a10 = FIXEDMUL(c,src->a10) - FIXEDMUL(s,src->a11); dst->a11 = FIXEDMUL(s,src->a10) + FIXEDMUL(c,src->a11); dst->a12 = src->a12; + dst->a20 = FIXEDMUL(c,src->a20) - FIXEDMUL(s,src->a21); dst->a21 = FIXEDMUL(s,src->a20) + FIXEDMUL(c,src->a21); dst->a22 = src->a22; + } else { + dst->a00 = c; dst->a01 = s; dst->a02 = 0; + dst->a10 = -s; dst->a11 = c; dst->a12 = 0; + dst->a20 = 0; dst->a21 = 0; dst->a22 = FIXED(1); + } + } +#endif + +void gmiscMatrixFixed2DApplyToPoints(point *dst, const point *src, const MatrixFixed2D *m, int cnt) { + coord_t x; + + for( ;cnt--; dst++, src++) { + x = src->x; // This allows in-place operation + dst->x = NONFIXED(x*m->a00+src->y*m->a01+m->a02+FIXED0_5); + dst->y = NONFIXED(x*m->a10+src->y*m->a11+m->a12+FIXED0_5); + } +} + +#endif // GMISC_NEED_MATRIXFIXED2D + +#endif // GFX_USE_GMISC diff --git a/src/gmisc/sys_defs.h b/src/gmisc/sys_defs.h index 4b5a1127..813fa07e 100644 --- a/src/gmisc/sys_defs.h +++ b/src/gmisc/sys_defs.h @@ -25,6 +25,9 @@ /* Type definitions */ /*===========================================================================*/ +// Forward definition +typedef struct point point; + /** * @brief Sample data formats * @note These are defined regardless of whether you use the GMISC module @@ -60,11 +63,13 @@ typedef int32_t fixed; * @brief Macros to convert to and from a fixed point. * @{ */ -#define FIXED(x) ((fixed)(x)<<16) /* @< integer to fixed */ -#define NONFIXED(x) ((x)>>16) /* @< fixed to integer */ -#define FIXED0_5 32768 /* @< 0.5 as a fixed (used for rounding) */ -#define FP2FIXED(x) ((fixed)((x)*65536.0)) /* @< floating point to fixed */ -#define FIXED2FP(x) ((double)(x)/65536.0) /* @< fixed to floating point */ +#define FIXED(x) ((fixed)(x)<<16) /* @< integer to fixed */ +#define NONFIXED(x) ((x)>>16) /* @< fixed to integer */ +#define FIXED0_5 32768 /* @< 0.5 as a fixed (used for rounding) */ +#define FP2FIXED(x) ((fixed)((x)*65536.0)) /* @< floating point to fixed */ +#define FIXED2FP(x) ((double)(x)/65536.0) /* @< fixed to floating point */ +#define FIXEDMUL(a,b) ((fixed)((((long long)(a))*(b))>>16)) /* @< fixed,fixed multiplication */ +#define FIXEDMULINT(a,b) ((a)*(b)) /* @< integer,fixed multiplication */ /** @} */ /** @@ -90,6 +95,7 @@ extern "C" { #if GMISC_NEED_ARRAYOPS || defined(__DOXYGEN__) /** * @brief Convert from one array format to another array format. + * @pre Requires GFX_USE_GMISC and GMISC_NEED_ARRAYOPS * * @param[in] srcfmt The format of the source array * @param[in] src The source array @@ -131,6 +137,7 @@ extern "C" { /** * @brief Fast Table Based Trig functions * @return A double in the range -1.0 .. 0.0 .. 1.0 + * @pre Requires GFX_USE_GMISC and GMISC_NEED_FASTTRIG * * @param[in] degrees The angle in degrees (not radians) * @@ -145,6 +152,7 @@ extern "C" { * * @brief Fast Table Based Trig functions * @return A double in the range -1.0 .. 0.0 .. 1.0 + * @pre Requires GFX_USE_GMISC and GMISC_NEED_FASTTRIG * * @param[in] degrees The angle in degrees 0 .. 359 * @@ -166,6 +174,7 @@ extern "C" { /** * @brief Fast Table Based Trig functions * @return A fixed point in the range -1.0 .. 0.0 .. 1.0 + * @pre Requires GFX_USE_GMISC and GMISC_NEED_FIXEDTRIG * * @param[in] degrees The angle in degrees (not radians) * @@ -180,6 +189,7 @@ extern "C" { * * @brief Fast Table Based Trig functions * @return A fixed point in the range -1.0 .. 0.0 .. 1.0 + * @pre Requires GFX_USE_GMISC and GMISC_NEED_FIXEDTRIG * * @param[in] degrees The angle in degrees 0 .. 359 * @@ -195,10 +205,11 @@ extern "C" { /** @} */ #endif -#if GMISC_NEED_INVSQRT +#if GMISC_NEED_INVSQRT || defined(__DOXYGEN__) /** * @brief Fast inverse square root function (x^-1/2) * @return The approximate inverse square root + * @pre Requires GFX_USE_GMISC and GMISC_NEED_INVSQRT * * @param[in] n The number to find the inverse square root of * @@ -212,6 +223,243 @@ extern "C" { */ float invsqrt(float n); #endif + +#if GMISC_NEED_MATRIXFLOAT2D || defined(__DOXYGEN__) + + /** + * @brief A matrix for doing 2D graphics using floats + * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFLOAT2D + */ + typedef struct MatrixFloat2D { + float a00, a01, a02; + float a10, a11, a12; + float a20, a21, a22; + } MatrixFloat2D; + + /** + * @brief Apply the matrix to a set of points + * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFLOAT2D + * + * @param[in] dst The destination array of points + * @param[in] src The source array of points + * @param[in] m The matrix to apply + * @param[in] cnt How many points are in the array + * + * @note In-place matrix application is allowed ie. dst = src + * + * @api + */ + void gmiscMatrixFloat2DApplyToPoints(point *dst, const point *src, const MatrixFloat2D *m, int cnt); + + /** + * @brief Set the 2D matrix to the identity matrix + * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFLOAT2D + * + * @param[in] m The matrix to set to identity + * + * @api + */ + void gmiscMatrixFloat2DSetIdentity(MatrixFloat2D *m); + + /** + * @brief Multiple two 2D matrixes together + * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFLOAT2D + * + * @param[in] dst The destination matrix + * @param[in] src1 The first source matrix + * @param[in] src2 The second source matrix + * + * @note In-place matrix application is NOT allowed ie. dst != src1, dst != src2 + * + * @api + */ + void gmiscMatrixFloat2DMultiply(MatrixFloat2D *dst, const MatrixFloat2D *src1, const MatrixFloat2D *src2); + + /** + * @brief Add an x,y translation to a matrix + * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFLOAT2D + * + * @param[in] dst The destination matrix + * @param[in] src The source matrix. Can be NULL + * @param[in] tx, ty The x and y translation to apply + * + * @note In-place matrix operation is NOT allowed ie. dst != src + * @note If no source matrix is provided, it is equivalent to applying the operation + * to an identity matrix. It also is a much simpler operation requiring no multiplication. + * + * @api + */ + void gmiscMatrixFloat2DApplyTranslation(MatrixFloat2D *dst, const MatrixFloat2D *src, float tx, float ty); + + /** + * @brief Add x,y scaling to a matrix + * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFLOAT2D + * + * @param[in] dst The destination matrix + * @param[in] src The source matrix. Can be NULL + * @param[in] sx, sy The scaling to apply in the x and y direction. Negative numbers give reflection. + * + * @note In-place matrix operation is NOT allowed ie. dst != src + * @note If no source matrix is provided, it is equivalent to applying the operation + * to an identity matrix. It also is a much simpler operation requiring no multiplication. + * + * @api + */ + void gmiscMatrixFloat2DApplyScale(MatrixFloat2D *dst, const MatrixFloat2D *src, float sx, float sy); + + /** + * @brief Add x,y shear to a matrix + * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFLOAT2D + * + * @param[in] dst The destination matrix + * @param[in] src The source matrix. Can be NULL + * @param[in] sx, sy The shear to apply in the x and y direction. + * + * @note In-place matrix operation is NOT allowed ie. dst != src + * @note If no source matrix is provided, it is equivalent to applying the operation + * to an identity matrix. It also is a much simpler operation requiring no multiplication. + * + * @api + */ + void gmiscMatrixFloat2DApplyShear(MatrixFloat2D *dst, const MatrixFloat2D *src, float sx, float sy); + + /** + * @brief Add rotation to a matrix + * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFLOAT2D + * + * @param[in] dst The destination matrix + * @param[in] src The source matrix. Can be NULL + * @param[in] angle The angle to apply in degrees (not radians). + * + * @note In-place matrix operation is NOT allowed ie. dst != src + * @note If no source matrix is provided, it is equivalent to applying the operation + * to an identity matrix. It also is a much simpler operation. + * @note If GMISC_NEED_FASTTRIG is defined then the fast table sin and cos lookup's will be used + * rather than the C library versions. + * + * @api + */ + void gmiscMatrixFloat2DApplyRotation(MatrixFloat2D *dst, const MatrixFloat2D *src, int angle); +#endif + +#if GMISC_NEED_MATRIXFIXED2D || defined(__DOXYGEN__) + + /** + * @brief A matrix for doing 2D graphics using fixed point maths + * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFIXED2D + */ + typedef struct MatrixFixed2D { + fixed a00, a01, a02; + fixed a10, a11, a12; + fixed a20, a21, a22; + } MatrixFixed2D; + + /** + * @brief Apply the matrix to a set of points + * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFIXED2D + * + * @param[in] dst The destination array of points + * @param[in] src The source array of points + * @param[in] m The matrix to apply + * @param[in] cnt How many points are in the array + * + * @note In-place matrix application is allowed ie. dst = src + * + * @api + */ + void gmiscMatrixFixed2DApplyToPoints(point *dst, const point *src, const MatrixFixed2D *m, int cnt); + + /** + * @brief Set the 2D matrix to the identity matrix + * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFIXED2D + * + * @param[in] m The matrix to set to identity + * + * @api + */ + void gmiscMatrixFixed2DSetIdentity(MatrixFixed2D *m); + + /** + * @brief Multiple two 2D matrixes together + * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFIXED2D + * + * @param[in] dst The destination matrix + * @param[in] src1 The first source matrix + * @param[in] src2 The second source matrix + * + * @note In-place matrix application is NOT allowed ie. dst != src1, dst != src2 + * + * @api + */ + void gmiscMatrixFixed2DMultiply(MatrixFixed2D *dst, const MatrixFixed2D *src1, const MatrixFixed2D *src2); + + /** + * @brief Add an x,y translation to a matrix + * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFIXED2D + * + * @param[in] dst The destination matrix + * @param[in] src The source matrix. Can be NULL + * @param[in] tx, ty The x and y translation to apply + * + * @note In-place matrix operation is NOT allowed ie. dst != src + * @note If no source matrix is provided, it is equivalent to applying the operation + * to an identity matrix. It also is a much simpler operation requiring no multiplication. + * + * @api + */ + void gmiscMatrixFixed2DApplyTranslation(MatrixFixed2D *dst, const MatrixFixed2D *src, fixed tx, fixed ty); + + /** + * @brief Add x,y scaling to a matrix + * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFIXED2D + * + * @param[in] dst The destination matrix + * @param[in] src The source matrix. Can be NULL + * @param[in] sx, sy The scaling to apply in the x and y direction. Negative numbers give reflection. + * + * @note In-place matrix operation is NOT allowed ie. dst != src + * @note If no source matrix is provided, it is equivalent to applying the operation + * to an identity matrix. It also is a much simpler operation requiring no multiplication. + * + * @api + */ + void gmiscMatrixFixed2DApplyScale(MatrixFixed2D *dst, const MatrixFixed2D *src, fixed sx, fixed sy); + + /** + * @brief Add x,y shear to a matrix + * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFIXED2D + * + * @param[in] dst The destination matrix + * @param[in] src The source matrix. Can be NULL + * @param[in] sx, sy The shear to apply in the x and y direction. + * + * @note In-place matrix operation is NOT allowed ie. dst != src + * @note If no source matrix is provided, it is equivalent to applying the operation + * to an identity matrix. It also is a much simpler operation requiring no multiplication. + * + * @api + */ + void gmiscMatrixFixed2DApplyShear(MatrixFixed2D *dst, const MatrixFixed2D *src, fixed sx, fixed sy); + + #if GMISC_NEED_FIXEDTRIG || defined(__DOXYGEN__) + /** + * @brief Add rotation to a matrix + * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFIXED2D and GMISC_NEED_FIXEDTRIG + * + * @param[in] dst The destination matrix + * @param[in] src The source matrix. Can be NULL + * @param[in] angle The angle to apply in degrees (not radians). + * + * @note In-place matrix operation is NOT allowed ie. dst != src + * @note If no source matrix is provided, it is equivalent to applying the operation + * to an identity matrix. It also is a much simpler operation requiring no multiplication. + * + * @api + */ + void gmiscMatrixFixed2DApplyRotation(MatrixFixed2D *dst, const MatrixFixed2D *src, int angle); + #endif +#endif + #ifdef __cplusplus } #endif diff --git a/src/gmisc/sys_make.mk b/src/gmisc/sys_make.mk index 0431c134..203910e6 100644 --- a/src/gmisc/sys_make.mk +++ b/src/gmisc/sys_make.mk @@ -1,3 +1,4 @@ GFXSRC += $(GFXLIB)/src/gmisc/gmisc_gmisc.c \ $(GFXLIB)/src/gmisc/gmisc_arrayops.c \ + $(GFXLIB)/src/gmisc/gmisc_matrix2d.c \ $(GFXLIB)/src/gmisc/gmisc_trig.c