diff --git a/include/gfx/bitmap.c b/include/gfx/bitmap.c new file mode 100644 index 0000000..73c8f99 --- /dev/null +++ b/include/gfx/bitmap.c @@ -0,0 +1,1275 @@ +#include "bitmap.h" +#include "tinyfont.h" +#include +#include + +void bm_init(Bitmap * bm, char * data, char cw, char ch) +{ + bm->rdata = nullptr; + bm->data = data; + bm->cwidth = cw; + bm->cheight = ch; + bm->width = cw * 8; +} + +void bm_alloc(Bitmap * bm, char cw, char ch) +{ + bm->rdata = malloc(cw * ch * 8 + 8); + bm->data = bm->rdata + 8 - ((int)bm->rdata & 7); + bm->cwidth = cw; + bm->cheight = ch; + bm->width = cw * 8; +} + +void bm_free(Bitmap * bm) +{ + free(bm->rdata); +} + +void bm_fill(Bitmap * bm, char data) +{ + memset(bm->data, data, bm->cwidth * bm->cheight * 8); +} + + +void bm_set(Bitmap * bm, int x, int y) +{ + bm->data[bm->cwidth * (y & ~7) + (x & ~7) + (y & 7)] |= 0x80 >> (x & 7); +} + +void bm_clr(Bitmap * bm, int x, int y) +{ + bm->data[bm->cwidth * (y & ~7) + (x & ~7) + (y & 7)] &= ~(0x80 >> (x & 7)); +} + +char NineShadesOfGrey[9][8] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0 + {0x22, 0x00, 0x88, 0x00, 0x22, 0x00, 0x88, 0x00}, // 8 + {0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88}, // 16 + {0x88, 0x55, 0x22, 0x55, 0x88, 0x55, 0x22, 0x55}, // 24 + {0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55}, // 32 + {0xbb, 0x55, 0xee, 0x55, 0xbb, 0x55, 0xee, 0x55}, // 40 + {0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77}, // 48 + {0xff, 0xee, 0xff, 0xbb, 0xff, 0xee, 0xff, 0xbb}, // 56 + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, // 64 +}; + +byte BLIT_CODE[16 * 14]; + + +static const byte lmask[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01}; +static const byte rmask[8] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe}; + +void bm_scan_fill(int left, int right, char * lp, int x0, int x1, char pat) +{ + if (x0 < left) + x0 = left; + if (x1 > right) + x1 = right; + + if (x1 > x0) + { + char * dp = lp + (x0 & ~7); + char l = (x1 >> 3) - (x0 >> 3); + char lm = lmask[x0 & 7], rm = rmask[x1 & 7]; + char o = 0; + + if (l == 0) + rm &= lm; + else + { + *dp = (*dp & ~lm) | (pat & lm); + o = 8; + if (l >= 32) + { + for(char i=0; i<31; i++) + { + dp[o] = pat; + o += 8; + } + dp += 256; + l -= 31; + } + for(char i=1; i r) + q >>= 2; + + while (q != 0) + { + h = p + q; + p >>= 1; + if (r >= h) + { + p += q; + r -= h; + } + q >>= 2; + } + + return p; +} + +void bm_circle_fill(Bitmap * bm, ClipRect * clip, int x, int y, char r, const char * pattern) +{ + int y0 = y - r, y1 = y + r; + if (y0 < clip->top) + y0 = clip->top; + if (y1 > clip->bottom) + y1 = clip->bottom; + + const char * pat = pattern; + char * lp = bm->data + bm->cwidth * (y0 & ~7) + (y0 & 7); + int stride = 8 * bm->cwidth - 8; + + unsigned rr = r * r + r; + for(char iy=y0; iy<(char)y1; iy++) + { + int d = (iy - y); + + int t = usqrt(rr - d * d); + + bm_scan_fill(clip->left, clip->right, lp, x - t, x + t + 1, pat[iy & 7]); + lp ++; + if (!((int)lp & 7)) + lp += stride; + } +} + +void bm_trapezoid_fill(Bitmap * bm, ClipRect * clip, long x0, long x1, long dx0, long dx1, int y0, int y1, const char * pattern) +{ + if (y1 <= clip->top || y0 >= clip->bottom) + return; + + long tx0 = x0, tx1 = x1; + + if (y1 > clip->bottom) + y1 = clip->bottom; + if (y0 < clip->top) + { + tx0 += (clip->top - y0) * dx0; + tx1 += (clip->top - y0) * dx1; + y0 = clip->top; + } + + const char * pat = pattern; + char * lp = bm->data + bm->cwidth * (y0 & ~7) + (y0 & 7); + int stride = 8 * bm->cwidth - 8; + + for(char iy=y0; iy<(char)y1; iy++) + { + bm_scan_fill(clip->left, clip->right, lp, tx0 >> 16, tx1 >> 16, pat[iy & 7]); + tx0 += dx0; + tx1 += dx1; + lp ++; + if (!((int)lp & 7)) + lp += stride; + } +} + + +void bm_triangle_fill(Bitmap * bm, ClipRect * clip, int x0, int y0, int x1, int y1, int x2, int y2, const char * pat) +{ + int t; + if (y1 < y0 && y1 < y2) + { + t = y0; y0 = y1; y1 = t; + t = x0; x0 = x1; x1 = t; + } + else if (y2 < y0) + { + t = y0; y0 = y2; y2 = t; + t = x0; x0 = x2; x2 = t; + } + + if (y2 < y1) + { + t = y1; y1 = y2; y2 = t; + t = x1; x1 = x2; x2 = t; + } + + if (y0 < y2) + { + long dx1, lx1; + long dx2 = ((long)(x2 - x0) << 16) / (y2 - y0); + long lx2 = (long)x0 << 16; + + if (y1 > y0) + { + dx1 = ((long)(x1 - x0) << 16) / (y1 - y0); + + if (dx1 < dx2) + bm_trapezoid_fill(bm, clip, lx2, lx2, dx1, dx2, y0, y1, pat); + else + bm_trapezoid_fill(bm, clip, lx2, lx2, dx2, dx1, y0, y1, pat); + if (y2 == y1) + return; + + lx2 += dx2 * (y1 - y0); + } + + dx1 = ((long)(x2 - x1) << 16) / (y2 - y1); + lx1 = (long)x1 << 16; + + if (lx1 < lx2) + bm_trapezoid_fill(bm, clip, lx1, lx2, dx1, dx2, y1, y2, pat); + else + bm_trapezoid_fill(bm, clip, lx2, lx1, dx2, dx1, y1, y2, pat); + } +} + + +void bm_quad_fill(Bitmap * bm, ClipRect * clip, int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3, const char * pat) +{ + bm_triangle_fill(bm, clip, x0, y0, x1, y1, x2, y2, pat); + bm_triangle_fill(bm, clip, x0, y0, x2, y2, x3, y3, pat); +} + +void bm_polygon_fill(Bitmap * bm, ClipRect * clip, int * px, int * py, char num, const char * pat) +{ + char mi = 0; + int my = py[0]; + + for(char i=1; i my) + { + long dlx = (((long)px[li] << 16) - lx) / (py[li] - my); + long drx = (((long)px[ri] << 16) - rx) / (py[ri] - my); + + if (lx < rx || lx == rx && dlx < drx) + bm_trapezoid_fill(bm, clip, lx, rx, dlx, drx, my, ty, pat); + else + bm_trapezoid_fill(bm, clip, rx, lx, drx, dlx, my, ty, pat); + + lx += (ty - my) * dlx; + rx += (ty - my) * drx; + + my = ty; + + while (py[li] == my) + { + lx = (long)px[li] << 16; + if (li == 0) + li = num; + li--; + } + + while (py[ri] == my) + { + rx = (long)px[ri] << 16; + ri++; + if (ri == num) + ri = 0; + } + + ty = py[li] < py[ri] ? py[li] : py[ri]; + } + +} + +struct Edge +{ + char minY, maxY; + long px, dx; + Edge * next; +}; + +void bm_polygon_nc_fill(Bitmap * bm, ClipRect * clip, int * px, int * py, char num, const char * pattern) +{ + Edge * first = nullptr, * active = nullptr; + Edge * e = (Edge *)BLIT_CODE; + + char n = num; + if (n > 16) + n = 16; + + int top = clip->top, bottom = clip->bottom; + + for(char i=0; i= n) + j = 0; + + if (py[i] != py[j]) + { + if (py[i] > py[j]) + { + k = j; j = i; + } + + int minY = py[k], maxY = py[j]; + if (minY < bottom && maxY > top) + { + e->px = ((long)px[k] << 16) + 0x8000; + e->dx = (((long)px[j] << 16) - e->px) / (maxY - minY); + + if (minY < top) + { + e->px += e->dx * (top - minY); + minY = top; + } + if (maxY > bottom) + maxY = bottom; + + e->minY = minY; e->maxY = maxY; + + Edge * pp = nullptr, * pe = first; + + while (pe && minY >= pe->minY) + { + pp = pe; + pe = pe->next; + } + + e->next = pe; + if (pp) + pp->next = e; + else + first = e; + + e++; + } + } + } + + if (first) + { + char y = first->minY; + + const char * pat = pattern; + char * lp = bm->data + bm->cwidth * (y & ~7) + (y & 7); + int stride = 8 * bm->cwidth - 8; + + while (first || active) + { + while (first && first->minY == y) + { + Edge * next = first->next; + + Edge * pp = nullptr, * pe = active; + while (pe && (first->px > pe->px || first->px == pe->px && first->dx > pe->dx)) + { + pp = pe; + pe = pe->next; + } + + first->next = pe; + if (pp) + pp->next = first; + else + active = first; + + first = next; + } + + Edge * e0 = active; + while (e0) + { + Edge * e1 = e0->next; + bm_scan_fill(clip->left, clip->right, lp, e0->px >> 16, e1->px >> 16, pat[y & 7]); + e0 = e1->next; + } + + lp ++; + if (!((int)lp & 7)) + lp += stride; + + y++; + + // remove final edges + Edge * pp = nullptr, * pe = active; + while (pe) + { + if (pe->maxY == y) + { + if (pp) + pp->next = pe->next; + else + active = pe->next; + } + else + { + pe->px += pe->dx; + pp = pe; + } + pe = pe->next; + } + } + } +} + +#define REG_SP 0x03 +#define REG_DP 0x05 +#define REG_PAT 0x07 +#define REG_S0 0x08 +#define REG_S1 0x09 +#define REG_D0 0x0a +#define REG_D1 0x0b + +static void buildline(char ly, char lx, int dx, int dy, int stride, bool left, bool up) +{ + char ip = 0; + + // ylow + ip += asm_im(BLIT_CODE + ip, ASM_LDY, ly); + ip += asm_im(BLIT_CODE + ip, ASM_LDX, lx); + + // set pixel + ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_D0); + + ip += asm_zp(BLIT_CODE + ip, ASM_ASL, REG_PAT); + ip += asm_rl(BLIT_CODE + ip, ASM_BCC, 6); + ip += asm_zp(BLIT_CODE + ip, ASM_INC, REG_PAT); + ip += asm_iy(BLIT_CODE + ip, ASM_ORA, REG_SP); + ip += asm_rl(BLIT_CODE + ip, ASM_BNE, 4); + ip += asm_im(BLIT_CODE + ip, ASM_EOR, 0xff); + ip += asm_iy(BLIT_CODE + ip, ASM_AND, REG_SP); + ip += asm_iy(BLIT_CODE + ip, ASM_STA, REG_SP); + + // m >= 0 + ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP + 1); + ip += asm_rl(BLIT_CODE + ip, ASM_BMI, 5 + 15 + 13); + + ip += asm_np(BLIT_CODE + ip, up ? ASM_DEY : ASM_INY); + ip += asm_im(BLIT_CODE + ip, ASM_CPY, up ? 0xff : 0x08); + ip += asm_rl(BLIT_CODE + ip, ASM_BNE, 15); + + ip += asm_np(BLIT_CODE + ip, ASM_CLC); + ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_SP); + ip += asm_im(BLIT_CODE + ip, ASM_ADC, stride & 0xff); + ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_SP); + ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_SP + 1); + ip += asm_im(BLIT_CODE + ip, ASM_ADC, stride >> 8); + ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_SP + 1); + ip += asm_im(BLIT_CODE + ip, ASM_LDY, up ? 0x07 : 0x00); + + ip += asm_np(BLIT_CODE + ip, ASM_SEC); + ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP); + ip += asm_im(BLIT_CODE + ip, ASM_SBC, dx & 0xff); + ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_DP); + ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP + 1); + ip += asm_im(BLIT_CODE + ip, ASM_SBC, dx >> 8); + ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_DP + 1); + + // m < 0 + ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP + 1); + ip += asm_rl(BLIT_CODE + ip, ASM_BPL, 4 + 15 + 13); + + ip += asm_zp(BLIT_CODE + ip, left ? ASM_ASL : ASM_LSR, REG_D0); + ip += asm_rl(BLIT_CODE + ip, ASM_BCC, 15); + + ip += asm_zp(BLIT_CODE + ip, left ? ASM_ROL : ASM_ROR, REG_D0); + ip += asm_np(BLIT_CODE + ip, ASM_CLC); + ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_SP); + ip += asm_im(BLIT_CODE + ip, ASM_ADC, left ? 0xf8 : 0x08); + ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_SP); + ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_SP + 1); + ip += asm_im(BLIT_CODE + ip, ASM_ADC, left ? 0xff : 0x00); + ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_SP + 1); + + ip += asm_np(BLIT_CODE + ip, ASM_CLC); + ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP); + ip += asm_im(BLIT_CODE + ip, ASM_ADC, dy & 0xff); + ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_DP); + ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP + 1); + ip += asm_im(BLIT_CODE + ip, ASM_ADC, dy >> 8); + ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_DP + 1); + + // l -- + ip += asm_np(BLIT_CODE + ip, ASM_DEX); + ip += asm_rl(BLIT_CODE + ip, ASM_BNE, 2 - ip); + ip += asm_zp(BLIT_CODE + ip, ASM_DEC, REG_D1); + ip += asm_rl(BLIT_CODE + ip, ASM_BPL, 2 - ip); + + ip += asm_np(BLIT_CODE + ip, ASM_RTS); +} + +static inline void callline(byte * dst, byte bit, int m, char lh, char pattern) +{ + __asm + { + lda dst + sta REG_SP + lda dst + 1 + sta REG_SP + 1 + + lda m + sta REG_DP + lda m + 1 + sta REG_DP + 1 + + lda lh + sta REG_D1 + + lda bit + sta REG_D0 + + lda pattern + sta REG_PAT + + jsr BLIT_CODE + } +} + + +void bm_line(Bitmap * bm, int x0, int y0, int x1, int y1, char pattern) +{ + int dx = x1 - x0, dy = y1 - y0; + byte quad = 0; + if (dx < 0) + { + quad = 1; + dx = -dx; + } + if (dy < 0) + { + quad |= 2; + dy = -dy; + } + + int l; + if (dx > dy) + l = dx; + else + l = dy; + + int m = dy - dx; + dx *= 2; + dy *= 2; + + char * dp = bm->data + bm->cwidth * (y0 & ~7) + (x0 & ~7); + char bit = 0x80 >> (x0 & 7); + char ry = y0 & 7; + int stride = 8 * bm->cwidth; + + buildline(ry, (l + 1) & 0xff, dx, dy, (quad & 2) ? -stride : stride, quad & 1, quad & 2); + + callline(dp, bit, m, l >> 8, pattern); +} + +static int muldiv(int x, int mul, int div) +{ + return (int)((long)x * mul / div); +} + +void bm_line_clipped(Bitmap * bm, ClipRect * clip, int x0, int y0, int x1, int y1, char pattern) +{ + int dx = x1 - x0, dy = y1 - y0; + + if (x0 < x1) + { + if (x1 < clip->left || x0 >= clip->right) + return; + + if (x0 < clip->left) + { + y0 += muldiv(clip->left - x0, dy, dx); + x0 = clip->left; + } + + if (x1 >= clip->right) + { + y1 -= muldiv(x1 + 1 - clip->right, dy, dx); + x1 = clip->right - 1; + } + } + else if (x1 < x0) + { + if (x0 < clip->left || x1 >= clip->right) + return; + + if (x1 < clip->left) + { + y1 += muldiv(clip->left - x1, dy, dx); + x1 = clip->left; + } + + if (x0 >= clip->right) + { + y0 -= muldiv(x0 + 1- clip->right, dy, dx); + x0 = clip->right - 1; + } + } + else + { + if (x0 < clip->left || x0 >= clip->right) + return; + } + + if (y0 < y1) + { + if (y1 < clip->top || y0 >= clip->bottom) + return; + + if (y0 < clip->top) + { + x0 += muldiv(clip->top - y0, dx, dy); + y0 = clip->top; + } + + if (y1 >= clip->bottom) + { + x1 -= muldiv(y1 + 1 - clip->bottom, dx, dy); + y1 = clip->bottom - 1; + } + } + else if (y1 < y0) + { + if (y0 < clip->top || y1 >= clip->bottom) + return; + + if (y1 < clip->top) + { + x1 += muldiv(clip->top - y1, dx, dy); + y1 = clip->top; + } + + if (y0 >= clip->bottom) + { + x0 -= muldiv(y0 + 1 - clip->bottom, dx, dy); + y0 = clip->bottom - 1; + } + } + else + { + if (y0 < clip->top || y0 >= clip->bottom) + return; + } + + bm_line(bm, x0, y0, x1, y1, pattern); +} + +static inline void callddop(byte * src, byte * dst, byte pat) +{ + __asm + { + lda src + sta REG_SP + lda src + 1 + sta REG_SP + 1 + lda dst + sta REG_DP + lda dst + 1 + sta REG_DP + 1 + lda pat + sta REG_PAT + jsr BLIT_CODE + } +} + +// build code to fetch src, result in accu + +static char builddop_src(char ip, char shift, bool reverse) +{ + if (shift != 0) + { + ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_S0); + ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_S1); + + ip += asm_iy(BLIT_CODE + ip, ASM_LDA, REG_SP); + ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_S0); + + if (reverse) + { + if (shift > 4) + { + for(char i=shift; i<8; i++) + { + ip += asm_zp(BLIT_CODE + ip, ASM_ASL, REG_S1); + ip += asm_ac(BLIT_CODE + ip, ASM_ROL); + } + } + else + { + for(char i=0; i 4) + { + for(char i=shift; i<8; i++) + { + ip += asm_ac(BLIT_CODE + ip, ASM_ASL); + ip += asm_zp(BLIT_CODE + ip, ASM_ROL, REG_S1); + } + ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_S1); + } + else + { + for(char i=0; i 0) + { + ip += asm_np(BLIT_CODE + ip, asm_clc); + ip += asm_np(BLIT_CODE + ip, ASM_TYA); + ip += asm_im(BLIT_CODE + ip, asm_adc, 8); + ip += asm_np(BLIT_CODE + ip, ASM_TAY); + + if (w > 1) + { + ip += asm_im(BLIT_CODE + ip, ASM_LDX, w - 1); + char lp = ip; + + if (usedst) + { + ip += asm_iy(BLIT_CODE + ip, ASM_LDA, REG_DP); + ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_D0); + } + + if (usesrc) + { + ip = builddop_src(ip, shift, reverse); + } + + ip = builddop_op(ip, op); + ip += asm_iy(BLIT_CODE + ip, ASM_STA, REG_DP); + + ip += asm_np(BLIT_CODE + ip, asm_clc); + ip += asm_np(BLIT_CODE + ip, ASM_TYA); + ip += asm_im(BLIT_CODE + ip, asm_adc, 8); + ip += asm_np(BLIT_CODE + ip, ASM_TAY); + if (w > 31) + { + if (usesrc) + { + ip += asm_rl(BLIT_CODE + ip, asm_bcc, 4); + ip += asm_zp(BLIT_CODE + ip, asm_inc, REG_SP + 1); + } + else + { + ip += asm_rl(BLIT_CODE + ip, asm_bcc, 2); + } + ip += asm_zp(BLIT_CODE + ip, asm_inc, REG_DP + 1); + } + + ip += asm_np(BLIT_CODE + ip, ASM_DEX); + ip += asm_rl(BLIT_CODE + ip, ASM_BNE, lp - ip - 2); + } + + ip += asm_iy(BLIT_CODE + ip, ASM_LDA, REG_DP); + ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_D0); + + if (usesrc) + { + ip = builddop_src(ip, shift, reverse); + } + + ip = builddop_op(ip, op); + ip += asm_im(BLIT_CODE + ip, ASM_AND, rmask); + ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_S1); + ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_D0); + ip += asm_im(BLIT_CODE + ip, ASM_AND, ~rmask); + ip += asm_zp(BLIT_CODE + ip, ASM_ORA, REG_S1); + ip += asm_iy(BLIT_CODE + ip, ASM_STA, REG_DP); + } + + ip += asm_np(BLIT_CODE + ip, ASM_RTS); +} + +void bm_bitblit(Bitmap * dbm, int dx, int dy, Bitmap * sbm, int sx, int sy, int w, int h, const char * pattern, BlitOp op) +{ + int rx = dx + w; + char dxh0 = dx >> 3, dxh1 = rx >> 3; + + char lm = lmask[dx & 7], rm = rmask[rx & 7]; + + char cw = dxh1 - dxh0; + + bool reverse = dbm == sbm && (dy > sy || dy == sy && dx > sx); + + if (reverse) + { + dy += h; + sy += h; + } + + char * dp = dbm->data + dbm->cwidth * (dy & ~7) + (dx & ~7) + (dy & 7); + char * sp = sbm->data + sbm->cwidth * (sy & ~7) + (sx & ~7) + (sy & 7); + + if (reverse) + { + sp += 8 * cw + 8 - 0xf8; + dp += 8 * cw - 0xf8; + byte t = lm; lm = rm; rm = t; + } + + char shift; + if ((dx & 7) > (sx & 7)) + { + shift = (dx & 7) - (sx & 7); + sp -= 8; + } + else + { + shift = 8 + (dx & 7) - (sx & 7); + } + + builddop(shift, cw, lm, rm, op, reverse); + + const char * pat = pattern; + + int sstride = 8 * sbm->cwidth - 8; + int dstride = 8 * dbm->cwidth - 8; + + if (reverse) + { + sstride = -sstride; + dstride = -dstride; + + for(char y=h; y>0; y--) + { + if (((int)sp & 7) == 0) + sp += sstride; + sp--; + + if (((int)dp & 7) == 0) + dp += dstride; + dp--; + + char pi = (int)dp & 7; + + callddop(sp, dp, pat[pi]); + } + } + else + { + for(char y=h; y>0; y--) + { + char pi = (int)dp & 7; + + callddop(sp, dp, pat[pi]); + + sp++; + if (((int)sp & 7) == 0) + sp += sstride; + + dp++; + if (((int)dp & 7) == 0) + dp += dstride; + } + } +} + +void bm_bitblit_clipped(Bitmap * dbm, ClipRect * clip, int dx, int dy, Bitmap * sbm, int sx, int sy, int w, int h, const char * pattern, BlitOp op) +{ + if (dx >= clip->right || dy >= clip->bottom) + return; + + if (dx < clip->left) + { + int d = clip->left - dx; + dx += d; + sx += d; + w -= d; + } + + if (dy < clip->top) + { + int d = clip->top - dy; + dy += d; + sy += d; + h -= d; + } + + if (dx + w > clip->right) + w = clip->right - dx; + + if (dy + h > clip->bottom) + h = clip->bottom - dy; + + if (w > 0 && h > 0) + bm_bitblit(dbm, dx, dy, sbm, sx, sy, w, h, pattern, op); +} + +inline void bm_rect_fill(Bitmap * dbm, int dx, int dy, int w, int h) +{ + bm_bitblit(dbm, dx, dy, dbm, dx, dy, w, h, nullptr, BLTOP_SET); +} + +inline void bm_rect_clear(Bitmap * dbm, int dx, int dy, int w, int h) +{ + bm_bitblit(dbm, dx, dy, dbm, dx, dy, w, h, nullptr, BLTOP_RESET); +} + +inline void bm_rect_pattern(Bitmap * dbm, int dx, int dy, int w, int h, const char * pattern) +{ + bm_bitblit(dbm, dx, dy, dbm, dx, dy, w, h, pattern, BLTOP_PATTERN); +} + +inline void bm_rect_copy(Bitmap * dbm, int dx, int dy, Bitmap * sbm, int sx, int sy, int w, int h) +{ + bm_bitblit(dbm, dx, dy, sbm, sx, sy, w, h, nullptr, BLTOP_COPY); +} + + +inline void bm_rect_fill_clipped(Bitmap * dbm, ClipRect * clip, int dx, int dy, int w, int h) +{ + bm_bitblit_clipped(dbm, clip, dx, dy, dbm, dx, dy, w, h, nullptr, BLTOP_SET); +} + +inline void bm_rect_clear_clipped(Bitmap * dbm, ClipRect * clip, int dx, int dy, int w, int h) +{ + bm_bitblit_clipped(dbm, clip, dx, dy, dbm, dx, dy, w, h, nullptr, BLTOP_RESET); +} + +inline void bm_rect_pattern_clipped(Bitmap * dbm, ClipRect * clip, int dx, int dy, int w, int h, const char * pattern) +{ + bm_bitblit_clipped(dbm, clip, dx, dy, dbm, dx, dy, w, h, pattern, BLTOP_PATTERN); +} + +inline void bm_rect_copy_clipped(Bitmap * dbm, ClipRect * clip, int dx, int dy, Bitmap * sbm, int sx, int sy, int w, int h) +{ + bm_bitblit_clipped(dbm, clip, dx, dy, sbm, sx, sy, w, h, nullptr, BLTOP_COPY); +} + +static char tworks[8]; + +int bm_text(Bitmap * bm, const char * str, char len) +{ + char lx = 0; + int tw = 0; + + char * cp = bm->data; + + for(char fx=0; fx> 2; + tw += w + 1; + + for(char px=0; px> 2) + 1; + } + + return tw; +} + +static char tbuffer[320]; +#pragma align(tbuffer, 8) + +static Bitmap tbitmap = { + tbuffer, nullptr, 40, 1, 320 +}; + +int bm_put_chars(Bitmap * bm, int x, int y, const char * str, char len, BlitOp op) +{ + int tw = bm_text(&tbitmap, str, len); + + bm_bitblit(bm, x, y, &tbitmap, 0, 0, tw, 8, nullptr, op); + + return tw; +} + +int bm_put_chars_clipped(Bitmap * bm, ClipRect * clip, int x, int y, const char * str, char len, BlitOp op) +{ + int tw = 0; + + if (y >= clip->bottom || x >= clip->right || y + 8 <= clip->top) + { + for(char fx=0; fx> 2) + 1; + } + + return tw; + } + + if (x < clip->left) + { + char fx = 0; + while (fx < len) + { + char ch = str[fx] - 32; + char f0 = TinyFont[ch], f1 = TinyFont[ch + 96]; + char w = (f1 >> 2) + 1; + if (x + w >= clip->left) + break; + tw += w; + x += w; + fx++; + } + + str += fx; + len -= fx; + } + + int rx = x; + char fx = 0; + while (fx < len && rx < clip->right) + { + char ch = str[fx] - 32; + char f0 = TinyFont[ch], f1 = TinyFont[ch + 96]; + char w = (f1 >> 2) + 1; + rx += w; + tw += w; + fx++; + } + + int cw = bm_text(&tbitmap, str, fx); + + bm_bitblit_clipped(bm, clip, x, y, &tbitmap, 0, 0, cw, 8, nullptr, op); + + while (fx < len) + { + char ch = str[fx] - 32; + char f0 = TinyFont[ch], f1 = TinyFont[ch + 96]; + char w = (f1 >> 2) + 1; + tw += w; + fx++; + } + + return tw; +} diff --git a/include/gfx/bitmap.h b/include/gfx/bitmap.h new file mode 100644 index 0000000..7b14bfc --- /dev/null +++ b/include/gfx/bitmap.h @@ -0,0 +1,117 @@ +#ifndef BITMAP_H +#define BITMAP_H + +#include + +struct Bitmap +{ + char * data, * rdata; + char cwidth; + char cheight; + unsigned width; +}; + +struct ClipRect +{ + int left, top, right, bottom; +}; + +#define BLIT_OP 0x03 + +#define BLIT_AND 0x01 +#define BLIT_ORA 0x02 +#define BLIT_EOR 0x03 + +#define BLIT_IMM 0x04 +#define BLIT_SRC 0x08 +#define BLIT_DST 0x10 +#define BLIT_PATTERN 0x20 + +#define BLIT_INVERT 0x40 + + +enum BlitOp +{ + BLTOP_SET = BLIT_IMM | BLIT_INVERT, + BLTOP_RESET = BLIT_IMM, + BLTOP_NOT = BLIT_DST | BLIT_IMM | BLIT_INVERT | BLIT_EOR, + + BLTOP_XOR = BLIT_SRC | BLIT_DST | BLIT_EOR, + BLTOP_OR = BLIT_SRC | BLIT_DST | BLIT_ORA, + BLTOP_AND = BLIT_SRC | BLIT_DST | BLIT_AND, + BLTOP_AND_NOT = BLIT_SRC | BLIT_DST | BLIT_INVERT | BLIT_AND, + + BLTOP_COPY = BLIT_SRC, + BLTOP_NCOPY = BLIT_SRC | BLIT_INVERT, + + BLTOP_PATTERN = BLIT_PATTERN, + BLTOP_PATTERN_AND_SRC = BLIT_SRC | BLIT_PATTERN | BLIT_AND +}; + +extern char NineShadesOfGrey[9][8]; + + +void bm_init(Bitmap * bm, char * data, char cw, char ch); + +void bm_alloc(Bitmap * bm, char cw, char ch); + +void bm_free(Bitmap * bm); + +void bm_fill(Bitmap * bm, char data); + + +void bm_scan_fill(int left, int right, char * lp, int x0, int x1, char pat); + +void bm_circle_fill(Bitmap * bm, ClipRect * clip, int x, int y, char r, const char * pat); + +void bm_trapezoid_fill(Bitmap * bm, ClipRect * clip, long x0, long x1, long dx0, long dx1, int y0, int y1, const char * pat) + +void bm_triangle_fill(Bitmap * bm, ClipRect * clip, int x0, int y0, int x1, int y1, int x2, int y2, const char * pat); + +void bm_quad_fill(Bitmap * bm, ClipRect * clip, int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3, const char * pat); + +void bm_polygon_fill(Bitmap * bm, ClipRect * clip, int * x, int * y, char num, const char * pat); + +void bm_polygon_nc_fill(Bitmap * bm, ClipRect * clip, int * x, int * y, char num, const char * pat); + +inline void bm_set(Bitmap * bm, int x, int y); +inline void bm_clr(Bitmap * bm, int x, int y); + + +void bm_line(Bitmap * bm, int x0, int y0, int x1, int y1, char pattern); + +void bm_line_clipped(Bitmap * bm, ClipRect * clip, int x0, int y0, int x1, int y1, char pattern); + + +void bm_bitblit(Bitmap * dbm, int dx, int dy, Bitmap * sbm, int sx, int sy, int w, int h, const char * pattern, BlitOp op); + +inline void bm_rect_fill(Bitmap * dbm, int dx, int dy, int w, int h); + +inline void bm_rect_clear(Bitmap * dbm, int dx, int dy, int w, int h); + +inline void bm_rect_pattern(Bitmap * dbm, int dx, int dy, int w, int h, const char * pattern); + +inline void bm_rect_copy(Bitmap * dbm, int dx, int dy, Bitmap * sbm, int sx, int sy, int w, int h); + + +void bm_bitblit_clipped(Bitmap * dbm, ClipRect * clip, int dx, int dy, Bitmap * sbm, int sx, int sy, int w, int h, const char * pattern, BlitOp op); + +inline void bm_rect_fill_clipped(Bitmap * dbm, ClipRect * clip, int dx, int dy, int w, int h); + +inline void bm_rect_clear_clipped(Bitmap * dbm, ClipRect * clip, int dx, int dy, int w, int h); + +inline void bm_rect_pattern_clipped(Bitmap * dbm, ClipRect * clip, int dx, int dy, int w, int h, const char * pattern); + +inline void bm_rect_copy_clipped(Bitmap * dbm, ClipRect * clip, int dx, int dy, Bitmap * sbm, int sx, int sy, int w, int h); + +int bm_text(Bitmap * bm, const char * str, char len); + +int bm_text_size(const char * str, char len); + +int bm_put_chars(Bitmap * bm, int x, int y, const char * str, char len, BlitOp op); + +int bm_put_chars_clipped(Bitmap * bm, ClipRect * clip, int x, int y, const char * str, char len, BlitOp op); + +#pragma compile("bitmap.c") + +#endif diff --git a/include/gfx/tinyfont.c b/include/gfx/tinyfont.c new file mode 100644 index 0000000..4fc1839 --- /dev/null +++ b/include/gfx/tinyfont.c @@ -0,0 +1,39 @@ +#include "tinyfont.h" + +const char TinyFont[] = { + 0x00, 0x04, 0x05, 0x08, 0x0D, 0x12, 0x17, 0x1C, 0x1D, 0x21, 0x25, 0x2A, 0x2D, 0x2E, 0x31, 0x32, + 0x35, 0x39, 0x3D, 0x41, 0x45, 0x49, 0x4D, 0x51, 0x55, 0x59, 0x5D, 0x5E, 0x5F, 0x62, 0x65, 0x68, + 0x6C, 0x71, 0x76, 0x7A, 0x7E, 0x82, 0x86, 0x8A, 0x8E, 0x92, 0x95, 0x99, 0x9D, 0xA1, 0xA6, 0xAB, + 0xAF, 0xB3, 0xB7, 0xBB, 0xBF, 0xC4, 0xC8, 0xCD, 0xD2, 0xD7, 0xDC, 0xE1, 0xE5, 0xE8, 0xEC, 0xF1, + 0xF5, 0xF9, 0xFD, 0x01, 0x05, 0x09, 0x0D, 0x10, 0x14, 0x18, 0x19, 0x1B, 0x1F, 0x21, 0x26, 0x2A, + 0x2E, 0x32, 0x36, 0x3A, 0x3E, 0x41, 0x45, 0x49, 0x4E, 0x52, 0x56, 0x5A, 0x5E, 0x5F, 0x63, 0x67, + 0x10, 0x04, 0x0C, 0x14, 0x14, 0x14, 0x14, 0x04, 0x10, 0x10, 0x14, 0x0C, 0x04, 0x0C, 0x04, 0x0C, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x04, 0x04, 0x0C, 0x0C, 0x0C, 0x10, + 0x14, 0x14, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0C, 0x10, 0x10, 0x10, 0x14, 0x14, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x14, 0x10, 0x14, 0x14, 0x14, 0x14, 0x14, 0x10, 0x0C, 0x10, 0x14, 0x10, + 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x0D, 0x11, 0x11, 0x05, 0x09, 0x11, 0x09, 0x15, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x0D, 0x11, 0x11, 0x15, 0x11, 0x11, 0x11, 0x11, 0x05, 0x11, 0x11, 0x11, + 0x00, 0x00, 0x00, 0x00, 0xFA, 0xC0, 0x00, 0xC0, 0x28, 0x7C, 0x28, 0x7C, 0x28, 0x20, 0x54, 0xD6, + 0x54, 0x08, 0x04, 0x48, 0x10, 0x24, 0x40, 0x6C, 0x92, 0x92, 0x6C, 0x0A, 0xC0, 0x38, 0x44, 0x82, + 0x82, 0x82, 0x82, 0x44, 0x38, 0x10, 0x54, 0x38, 0x54, 0x10, 0x10, 0x38, 0x10, 0x03, 0x10, 0x10, + 0x10, 0x02, 0x06, 0x38, 0xC0, 0x7C, 0x82, 0x82, 0x7C, 0x22, 0x42, 0xFE, 0x02, 0x46, 0x8A, 0x92, + 0x62, 0x44, 0x82, 0x92, 0x6C, 0xF0, 0x10, 0x3E, 0x10, 0xE4, 0x92, 0x92, 0x8C, 0x7C, 0x92, 0x92, + 0x4C, 0x80, 0x8E, 0x90, 0xE0, 0x6C, 0x92, 0x92, 0x6C, 0x64, 0x92, 0x92, 0x7C, 0x28, 0x0B, 0x10, + 0x28, 0x44, 0x28, 0x28, 0x28, 0x44, 0x28, 0x10, 0x40, 0x80, 0x9A, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x50, 0x90, 0x50, 0x3E, 0xFE, 0x92, 0x92, 0x6C, 0x7C, 0x82, 0x82, 0x44, 0xFE, 0x82, + 0x82, 0x7C, 0xFE, 0x92, 0x92, 0x82, 0xFE, 0x90, 0x90, 0x80, 0x7C, 0x82, 0x92, 0x1C, 0xFE, 0x10, + 0x10, 0xFE, 0x82, 0xFE, 0x82, 0x84, 0x82, 0x82, 0xFC, 0xFE, 0x10, 0x28, 0xC6, 0xFE, 0x02, 0x02, + 0x02, 0xFE, 0x40, 0x20, 0x40, 0xFE, 0xFE, 0x40, 0x20, 0x10, 0xFE, 0x7C, 0x82, 0x82, 0x7C, 0xFE, + 0x90, 0x90, 0x60, 0x7C, 0x82, 0x84, 0x7A, 0xFE, 0x90, 0x90, 0x6E, 0x64, 0x92, 0x92, 0x4C, 0x80, + 0x80, 0xFE, 0x80, 0x80, 0xFC, 0x02, 0x02, 0xFC, 0xE0, 0x18, 0x06, 0x18, 0xE0, 0xFE, 0x04, 0x08, + 0x04, 0xFE, 0xC6, 0x28, 0x10, 0x28, 0xC6, 0xE0, 0x10, 0x1E, 0x10, 0xE0, 0x86, 0x8A, 0x92, 0xA2, + 0xC2, 0xFE, 0x82, 0x82, 0x82, 0xC0, 0x38, 0x06, 0x82, 0x82, 0x82, 0xFE, 0x20, 0x40, 0x80, 0x40, + 0x20, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x2A, 0x2A, 0x1E, 0xFE, 0x22, 0x22, + 0x1C, 0x1C, 0x22, 0x22, 0x14, 0x1C, 0x22, 0x22, 0xFE, 0x1C, 0x2A, 0x2A, 0x18, 0x20, 0x7E, 0xA0, + 0x18, 0x25, 0x25, 0x3E, 0xFE, 0x20, 0x20, 0x1E, 0xBE, 0x01, 0xBE, 0xFE, 0x10, 0x28, 0x46, 0xFC, + 0x02, 0x3E, 0x20, 0x1E, 0x20, 0x1E, 0x3E, 0x20, 0x20, 0x1E, 0x1C, 0x22, 0x22, 0x1C, 0x3F, 0x24, + 0x24, 0x18, 0x18, 0x24, 0x24, 0x3F, 0x3E, 0x10, 0x20, 0x10, 0x12, 0x2A, 0x2A, 0x04, 0x20, 0x7C, + 0x22, 0x3C, 0x02, 0x02, 0x3E, 0x38, 0x04, 0x02, 0x3C, 0x3C, 0x02, 0x1C, 0x02, 0x3C, 0x26, 0x18, + 0x0C, 0x32, 0x38, 0x05, 0x05, 0x3E, 0x26, 0x2A, 0x2A, 0x32, 0x10, 0x6C, 0x82, 0x82, 0xFE, 0x82, + 0x82, 0x6C, 0x10, 0x10, 0x20, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00 +}; diff --git a/include/gfx/tinyfont.h b/include/gfx/tinyfont.h new file mode 100644 index 0000000..b8fb0c4 --- /dev/null +++ b/include/gfx/tinyfont.h @@ -0,0 +1,8 @@ +#ifndef TINYFONT_H +#define TINYFONT_H + +extern const char TinyFont[]; + +#pragma compile("tinyfont.c") + +#endif diff --git a/include/gfx/vector3d.c b/include/gfx/vector3d.c new file mode 100644 index 0000000..897c8c4 --- /dev/null +++ b/include/gfx/vector3d.c @@ -0,0 +1,944 @@ +#include "vector3d.h" +#include + +void vec2_sum(Vector2 * vd, const Vector2 * v1, const Vector2 * v2) +{ + vd->v[0] = v1->v[0] + v2->v[0]; + vd->v[1] = v1->v[1] + v2->v[1]; +} + +void vec2_diff(Vector2 * vd, const Vector2 * v1, const Vector2 * v2) +{ + vd->v[0] = v1->v[0] - v2->v[0]; + vd->v[1] = v1->v[1] - v2->v[1]; +} + +void vec2_add(Vector2 * vd, const Vector2 * vs) +{ + vd->v[0] += vs->v[0]; + vd->v[1] += vs->v[1]; +} + +void vec2_madd(Vector2 * vd, float s, const Vector2 * vs) +{ + vd->v[0] += s * vs->v[0]; + vd->v[1] += s * vs->v[1]; +} + +void vec2_sub(Vector2 * vd, const Vector2 * vs) +{ + vd->v[0] -= vs->v[0]; + vd->v[1] -= vs->v[1]; +} + +void vec2_scale(Vector2 * vd, float s) +{ + vd->v[0] *= s; + vd->v[1] *= s; +} + +void vec2_lincomb(Vector2 * vd, const Vector2 * vb, float x, const Vector2 * vx) +{ + vd->v[0] = vb->v[0] + x * vx->v[0]; + vd->v[1] = vb->v[1] + x * vx->v[1]; +} + +void vec2_lincomb2(Vector2 * vd, const Vector2 * vb, float x, const Vector2 * vx, float y, const Vector2 * vy) +{ + vd->v[0] = vb->v[0] + x * vx->v[0] + y * vy->v[0]; + vd->v[1] = vb->v[1] + x * vx->v[1] + y * vy->v[1]; +} + +void vec2_lerp(Vector2 * vd, const Vector2 * v1, const Vector2 * v2, float t) +{ + vd->v[0] = (1 - t) * v1->v[0] + t * v2->v[0]; + vd->v[1] = (1 - t) * v1->v[1] + t * v2->v[1]; +} + +bool vec2_is_zero(const Vector2 * v) +{ + return v->v[0] == 0 && v->v[1] == 0; +} + +float vec2_vmul(const Vector2 * v1, const Vector2 * v2) +{ + return v1->v[0] * v2->v[0] + v1->v[1] * v2->v[1]; +} + +void vec2_norm(Vector2 * v) +{ + vec2_scale(v, 1.0 / vec2_length(v)); +} + +float vec2_length(const Vector2 * v) +{ + return sqrt(vec2_qlength(v)); +} + +float vec2_qlength(const Vector2 * v) +{ + return vec2_vmul(v, v); +} + +float vec2_distance(const Vector2 * v1, const Vector2 * v2) +{ + return sqrt(vec2_qdistance(v1, v2)); +} + +float vec2_qdistance(const Vector2 * v1, const Vector2 * v2) +{ + float dx = v1->v[0] - v2->v[0], dy = v1->v[1] - v2->v[1]; + return dx * dx + dy * dy; +} + + + + +void mat2_ident(Matrix2 * md) +{ + md[0] = 1.0; + md[1] = 0.0; + md[2] = 0.0; + md[3] = 1.0; +} + +void mat2_add(Matrix2 * md, const Matrix2 * ms) +{ + for(char i=0; i<4; i++) + md->m[i] += ms->m[i]; +} + +void mat2_scale(Matrix2 * md, float s) +{ + for(char i=0; i<4; i++) + md->m[i] *= s; +} + +void mat2_mmul(Matrix2 * md, const Matrix2 * ms) +{ + float m0 = md->m[0] * ms->m[0] + md->m[2] * ms->m[1]; + float m1 = md->m[1] * ms->m[0] + md->m[3] * ms->m[1]; + + float m2 = md->m[0] * ms->m[2] + md->m[2] * ms->m[3]; + float m3 = md->m[1] * ms->m[2] + md->m[3] * ms->m[3]; + + md->m[0] = m0; md->m[1] = m1; + md->m[2] = m2; md->m[3] = m3; +} + +void mat2_rmmul(Matrix2 * md, const Matrix2 * ms) +{ + float m0 = ms->m[0] * md->m[0] + ms->m[2] * md->m[1]; + float m1 = ms->m[1] * md->m[0] + ms->m[3] * md->m[1]; + + float m2 = ms->m[0] * md->m[2] + ms->m[2] * md->m[3]; + float m3 = ms->m[1] * md->m[2] + ms->m[3] * md->m[3]; + + md->m[0] = m0; md->m[1] = m1; + md->m[2] = m2; md->m[3] = m3; +} + +void mat2_tranpose(Matrix2 * md) +{ + float t = md->m[1]; md->m[1] = md->m[2]; md->m[2] = t; +} + +void vec2_mmul(Vector2 * vd, const Matrix2 * m, const Vector2 * vs) +{ + float x = m->m[0] * vs->v[0] + m->m[2] * vs->v[1]; + float y = m->m[1] * vs->v[0] + m->m[3] * vs->v[1]; + + vd->v[0] = x; + vd->v[1] = y; +} + +void vec2_mimul(Vector2 * vd, const Matrix2 * m, const Vector2 * vs) +{ + float det = 1 / mat2_det(m); + + float x = det * ( m->m[3] * vs->v[0] - m->m[2] * vs->v[1]); + float y = det * (-m->m[1] * vs->v[0] + m->m[0] * vs->v[1]); + + vd->v[0] = x; + vd->v[1] = y; +} + +void mat2_set_rotate(Matrix2 * md, float a) +{ + float c = cos(a); + float s = sin(a); + md->m[0] = c; md->m[2] = s; + md->m[1] =-s; md->m[3] = c; + +} + +void mat2_rotate(Matrix2 * md, float a) +{ + Matrix2 mr; + mat2_set_rotate(mr, a); + mat2_rmmul(md, mr); +} + +float mat2_det(const Matrix2 * ms) +{ + return ms->m[0] * ms->m[3] - ms->m[1] * ms->m[2]; +} + +void mat2_invert(Matrix2 * md, const Matrix2 * ms) +{ + float det = 1 / mat2_det(ms); + + float m0 = det * ms->m[3]; + float m1 = -det * ms->m[1]; + float m2 = -det * ms->m[2]; + float m3 = det * ms->m[0]; + + md->m[0] = m0; md->m[1] = m1; + md->m[2] = m2; md->m[3] = m3; +} + + +inline void vec3_set(Vector3 * vd, float x, float y, float z) +{ + vd->v[0] = x; + vd->v[1] = y; + vd->v[2] = z; +} + +void vec3_sum(Vector3 * vd, const Vector3 * v1, const Vector3 * v2) +{ + for(char i=0; i<3; i++) + vd->v[i] = v1->v[i] + v2->v[i]; +} + +void vec3_diff(Vector3 * vd, const Vector3 * v1, const Vector3 * v2) +{ + for(char i=0; i<3; i++) + vd->v[i] = v1->v[i] - v2->v[i]; +} + +void vec3_add(Vector3 * vd, const Vector3 * vs) +{ + for(char i=0; i<3; i++) + vd->v[i] += vs->v[i]; +} + +void vec3_madd(Vector3 * vd, float s, const Vector3 * vs) +{ + for(char i=0; i<3; i++) + vd->v[i] += s * vs->v[i]; +} + +void vec3_sub(Vector3 * vd, const Vector3 * vs) +{ + for(char i=0; i<3; i++) + vd->v[i] -= vs->v[i]; +} + +void vec3_scale(Vector3 * vd, float s) +{ + for(char i=0; i<3; i++) + vd->v[i] *= s; +} + +void vec3_lincomb(Vector3 * vd, const Vector3 * vb, float x, const Vector3 * vx) +{ + for(char i=0; i<3; i++) + vd->v[i] = vb->v[i] + x * vx->v[i]; +} + +void vec3_lincomb2(Vector3 * vd, const Vector3 * vb, float x, const Vector3 * vx, float y, const Vector3 * vy) +{ + for(char i=0; i<3; i++) + vd->v[i] = vb->v[i] + x * vx->v[i] + y * vy->v[i]; +} + +void vec3_lerp(Vector3 * vd, const Vector3 * v1, const Vector3 * v2, float t) +{ + for(char i=0; i<3; i++) + vd->v[i] = (1 - t) * v1->v[i] + t * v2->v[i]; +} + +bool vec3_is_zero(const Vector3 * v) +{ + return v->v[0] == 0 && v->v[1] == 0 && v->v[2] == 0; +} + +float vec3_vmul(const Vector3 * v1, const Vector3 * v2) +{ + return v1->v[0] * v2->v[0] + v1->v[1] * v2->v[1] + v1->v[2] * v2->v[2]; +} + +void vec3_norm(Vector3 * v) +{ + vec3_scale(v, 1.0 / vec3_length(v)); +} + +float vec3_length(const Vector3 * v) +{ + return sqrt(vec3_qlength(v)); +} + +float vec3_qlength(const Vector3 * v) +{ + return vec3_vmul(v, v); +} + +float vec3_distance(const Vector3 * v1, const Vector3 * v2) +{ + return sqrt(vec3_qdistance(v1, v2)); +} + +float vec3_qdistance(const Vector3 * v1, const Vector3 * v2) +{ + float dx = v1->v[0] - v2->v[0], dy = v1->v[1] - v2->v[1], dz = v1->v[2] - v2->v[2]; + return dx * dx + dy * dy + dz * dz; +} + +void vec3_mcadd(Vector3 * vd, const Vector3 * v1, const Vector3 * v2) +{ + for(char i=0; i<3; i++) + vd->v[i] += v1->v[i] * v2->v[i]; +} + +void vec3_mscadd(Vector3 * vd, float s, const Vector3 * v1, const Vector3 * v2) +{ + for(char i=0; i<3; i++) + vd->v[i] += s * v1->v[i] * v2->v[i]; +} + +void vec3_cmul(Vector3 * vd, const Vector3 * v1, const Vector3 * v2) +{ + for(char i=0; i<3; i++) + vd->v[i] = v1->v[i] * v2->v[i]; +} + +void vec3_xmul(Vector3 * vd, const Vector3 * v1, const Vector3 * v2) +{ + float tx = v1->v[1] * v2->v[2] - v1->v[2] * v2->v[1]; + float ty = v1->v[2] * v2->v[0] - v1->v[0] * v2->v[2]; + float tz = v1->v[0] * v2->v[1] - v1->v[1] * v2->v[0]; + + vd->v[0] = tx; + vd->v[1] = ty; + vd->v[2] = tz; +} + +void vec3_mbase(Vector3 * v1, Vector3 * v2, Vector3 * v3) +{ + if (fabs(v1->v[2]) >= fabs(v1->v[0]) && fabs(v1->v[2]) >= fabs(v1->v[1])) + { + v2->v[0] = v1->v[2]; + v2->v[1] = 0; + v2->v[2] = - v1->v[0]; + } + else if (fabs(v1->v[1]) >= fabs(v1->v[0]) && fabs(v1->v[1]) >= fabs(v1->v[2])) + { + v2->v[0] = v1->v[1]; + v2->v[1] = -v1->v[0]; + v2->v[2] = 0; + } + else + { + v2->v[0] = -v1->v[1]; + v2->v[1] = v1->v[0]; + v2->v[2] = 0; + } + vec3_norm(v2); + vec3_xmul(v3, v1, v2); +} + +void vec3_bend(Vector3 * vd, const Vector3 * vs, float chi1, float chi2) +{ + float m0 = sqrt(1 - chi2); + + float hn1x, hn1y, hn1z; + float hn2x, hn2y, hn2z; + float hnl; + + if (fabs(vs->v[2]) >= fabs(vs->v[0]) && fabs(vs->v[2]) >= fabs(vs->v[1])) + { + hn1x = vs->v[1]; hn1y = 0; hn1z = - vs->v[0]; + chi2 /= (hn1x * hn1x + hn1z * hn1z); + hn2x = vs->v[1] * hn1z; + hn2y = vs->v[2] * hn1x - vs->v[0] * hn1z; + hn2z = - vs->v[1] * hn1x; + } + else + { + hn1x = - vs->v[1]; hn1y = vs->v[0]; hn1z = 0; + chi2 /= (hn1x * hn1x + hn1y * hn1y ); + hn2x = - vs->v[2] * hn1y; + hn2y = vs->v[2] * hn1x; + hn2z = vs->v[0] * hn1y - vs->v[1] * hn1x; + } + + float m1 = cos(2 * PI * chi1) * sqrt(chi2); + float m2 = sin(2 * PI * chi1) * sqrt(chi2); + + Vector3 vt; + vt.v[0] = vs->v[0] * m0 + hn1x * m1 + hn2x * m2; + vt.v[1] = vs->v[1] * m0 + hn1y * m1 + hn2y * m2; + vt.v[2] = vs->v[2] * m0 + hn1z * m1 + hn2z * m2; + *vd = vt; +} + + + +void mat3_ident(Matrix3 * m) +{ + m->m[0] = 1.0; + m->m[1] = 0.0; + m->m[2] = 0.0; + + m->m[3] = 0.0; + m->m[4] = 1.0; + m->m[5] = 0.0; + + m->m[6] = 0.0; + m->m[7] = 0.0; + m->m[8] = 1.0; +} + +void mat3_scale(Matrix3 * md, float s) +{ + for(char i=0; i<9; i++) + md->m[i] *= s; +} + +void mat3_add(Matrix3 * md, const Matrix3 * ms) +{ + for(char i=0; i<9; i++) + md->m[i] += md->m[i]; +} + +void mat3_mmul(Matrix3 * md, const Matrix3 * ms) +{ + for(char i=0; i<3; i++) + { + float j = 3 * i; + + float m0 = md->m[i + 0] * ms->m[0] + md->m[i + 3] * ms->m[1] + md->m[i + 6] * ms->m[2]; + float m3 = md->m[i + 0] * ms->m[3] + md->m[i + 3] * ms->m[4] + md->m[i + 6] * ms->m[5]; + float m6 = md->m[i + 0] * ms->m[6] + md->m[i + 3] * ms->m[7] + md->m[i + 6] * ms->m[8]; + + md->m[i + 0] = m0; md->m[i + 3] = m3; md->m[i + 6] = m6; + } +} + +void mat3_rmmul(Matrix3 * md, const Matrix3 * ms) +{ + for(char i=0; i<9; i+=3) + { + float m0 = md->m[i + 0] * ms->m[0] + md->m[i + 1] * ms->m[3] + md->m[i + 2] * ms->m[6]; + float m1 = md->m[i + 0] * ms->m[1] + md->m[i + 1] * ms->m[4] + md->m[i + 2] * ms->m[7]; + float m2 = md->m[i + 0] * ms->m[2] + md->m[i + 1] * ms->m[5] + md->m[i + 2] * ms->m[8]; + + md->m[i + 0] = m0; md->m[i + 1] = m1; md->m[i + 2] = m2; + } +} + +void mat3_transpose(Matrix3 * md, const Matrix3 * ms) +{ + float t + t = ms->m[1]; md->m[1] = ms->m[3]; md->m[3] = t; md->m[0] = ms->m[0]; + t = ms->m[2]; md->m[2] = ms->m[6]; md->m[6] = t; md->m[4] = ms->m[4]; + t = ms->m[5]; md->m[5] = ms->m[7]; md->m[7] = t; md->m[8] = ms->m[8]; +} + +float mat3_det(const Matrix3 * ms) +{ + return ms->m[0] * ms->m[4] * ms->m[8] + + ms->m[1] * ms->m[5] * ms->m[6] + + ms->m[2] * ms->m[3] * ms->m[7] - + ms->m[0] * ms->m[5] * ms->m[7] - + ms->m[2] * ms->m[4] * ms->m[6] - + ms->m[1] * ms->m[3] * ms->m[8]; +} + +void mat3_invert(Matrix3 * md, const Matrix3 * ms) +{ + float det = 1 / mat3_det(ms); + + Matrix3 mt; + mt.m[0] = det * (ms->m[4] * ms->m[8] - ms->m[5] * ms->m[7]); + mt.m[1] = det * (ms->m[7] * ms->m[2] - ms->m[1] * ms->m[8]); + mt.m[2] = det * (ms->m[1] * ms->m[5] - ms->m[4] * ms->m[2]); + + mt.m[3] = det * (ms->m[6] * ms->m[5] - ms->m[3] * ms->m[8]); + mt.m[4] = det * (ms->m[0] * ms->m[8] - ms->m[6] * ms->m[2]); + mt.m[5] = det * (ms->m[3] * ms->m[2] - ms->m[0] * ms->m[5]); + + mt.m[6] = det * (ms->m[3] * ms->m[7] - ms->m[6] * ms->m[4]); + mt.m[7] = det * (ms->m[6] * ms->m[1] - ms->m[0] * ms->m[7]); + mt.m[8] = det * (ms->m[0] * ms->m[4] - ms->m[3] * ms->m[1]); + + *md = mt; +} + +void vec3_mmul(Vector3 * vd, const Matrix3 * m, const Vector3 * vs) +{ + Vector3 vt; + for(char i=0; i<3; i++) + vt.v[i] = m->m[i] * vs->v[0] + m->m[3 + i] * vs->v[1] + m->m[6 + i] * vs->v[2]; + *vd = vt; +} + +void mat3_set_rotate_x(Matrix3 * m, float a) +{ + float c = cos(a); + float s = sin(a); + m->m[0] = 1; m->m[3] = 0; m->m[6] = 0; + m->m[1] = 0; m->m[4] = c; m->m[7] = s; + m->m[2] = 0; m->m[5] =-s; m->m[8] = c; +} + +void mat3_set_rotate_y(Matrix3 * m, float a) +{ + float c = cos(a); + float s = sin(a); + m->m[0] = c; m->m[3] = 0; m->m[6] = s; + m->m[1] = 0; m->m[4] = 1; m->m[7] = 0; + m->m[2] =-s; m->m[5] = 0; m->m[8] = c; +} + + +void mat3_set_rotate_z(Matrix3 * m, float a) +{ + float c = cos(a); + float s = sin(a); + m->m[0] = c; m->m[3] =-s; m->m[6] = 0; + m->m[1] = s; m->m[4] = c; m->m[7] = 0; + m->m[2] = 0; m->m[5] = 0; m->m[8] = 1; +} + +void mat3_set_rotate(Matrix3 * m, const Vector3 * v, float a) +{ + float co = cos(a); + float si = sin(a); + float ico = (1- co); + + m->m[0] = co + v->v[0]*v->v[0]*ico; + m->m[1] = v->v[1]*v->v[0]*ico+v->v[2]*si; + m->m[2] = v->v[2]*v->v[0]*ico-v->v[1]*si; + + m->m[3] = v->v[0]*v->v[1]*ico - v->v[2]*si; + m->m[4] = co + v->v[1]*v->v[1]*ico; + m->m[5] = v->v[2]*v->v[1]*ico+v->v[0]*si; + + m->m[6] = v->v[0]*v->v[2]*ico + v->v[1]*si; + m->m[7] = v->v[1]*v->v[2]*ico - v->v[0]*si; + m->m[8] = co + v->v[2]*v->v[2]*ico; +} + + + + + +inline void vec4_set(Vector4 * vd, float x, float y, float z, float w) +{ + vd->v[0] = x; + vd->v[1] = y; + vd->v[2] = z; + vd->v[3] = w; +} + + +void vec4_sum(Vector4 * vd, const Vector4 * v1, const Vector4 * v2) +{ + for(char i=0; i<4; i++) + vd->v[i] = v1->v[i] + v2->v[i]; +} + +void vec4_diff(Vector4 * vd, const Vector4 * v1, const Vector4 * v2) +{ + for(char i=0; i<4; i++) + vd->v[i] = v1->v[i] - v2->v[i]; +} + +void vec4_add(Vector4 * vd, const Vector4 * vs) +{ + for(char i=0; i<4; i++) + vd->v[i] += vs->v[i]; +} + +void vec4_madd(Vector4 * vd, float s, const Vector4 * vs) +{ + for(char i=0; i<4; i++) + vd->v[i] += s * vs->v[i]; +} + +void vec4_sub(Vector4 * vd, const Vector4 * vs) +{ + for(char i=0; i<4; i++) + vd->v[i] -= vs->v[i]; +} + +void vec4_scale(Vector4 * vd, float s) +{ + for(char i=0; i<4; i++) + vd->v[i] *= s; +} + +void vec4_lincomb(Vector4 * vd, const Vector4 * vb, float x, const Vector4 * vx) +{ + for(char i=0; i<4; i++) + vd->v[i] = vb->v[i] + x * vx->v[i]; +} + +void vec4_lincomb2(Vector4 * vd, const Vector4 * vb, float x, const Vector4 * vx, float y, const Vector4 * vy) +{ + for(char i=0; i<4; i++) + vd->v[i] = vb->v[i] + x * vx->v[i] + y * vy->v[i]; +} + +void vec4_lerp(Vector4 * vd, const Vector4 * v1, const Vector4 * v2, float t) +{ + for(char i=0; i<4; i++) + vd->v[i] = (1 - t) * v1->v[i] + t * v2->v[i]; +} + +bool vec4_is_zero(const Vector4 * v) +{ + return v->v[0] == 0 && v->v[1] == 0 && v->v[2] == 0 && v->v[3] == 0; +} + +float vec4_vmul(const Vector4 * v1, const Vector4 * v2) +{ + return v1->v[0] * v2->v[0] + v1->v[1] * v2->v[1] + v1->v[2] * v2->v[2] + v1->v[3] * v2->v[3]; +} + +void vec4_norm(Vector4 * v) +{ + vec4_scale(v, 1.0 / vec4_length(v)); +} + +float vec4_length(const Vector4 * v) +{ + return sqrt(vec4_qlength(v)); +} + +float vec4_qlength(const Vector4 * v) +{ + return vec4_vmul(v, v); +} + +float vec4_distance(const Vector4 * v1, const Vector4 * v2) +{ + return sqrt(vec4_qdistance(v1, v2)); +} + +float vec4_qdistance(const Vector4 * v1, const Vector4 * v2) +{ + float dx = v1->v[0] - v2->v[0], dy = v1->v[1] - v2->v[1], dz = v1->v[2] - v2->v[2], dw = v1->v[3] - v2->v[3]; + return dx * dx + dy * dy + dz * dz + dw * dw; +} + +void vec4_mcadd(Vector4 * vd, const Vector4 * v1, const Vector4 * v2) +{ + for(char i=0; i<4; i++) + vd->v[i] += v1->v[i] * v2->v[i]; +} + +void vec4_mscadd(Vector4 * vd, float s, const Vector4 * v1, const Vector4 * v2) +{ + for(char i=0; i<4; i++) + vd->v[i] += s * v1->v[i] * v2->v[i]; +} + +void vec4_cmul(Vector4 * vd, const Vector4 * v1, const Vector4 * v2) +{ + for(char i=0; i<4; i++) + vd->v[i] = v1->v[i] * v2->v[i]; +} + + + +void mat4_ident(Matrix4 * m) +{ + for(char i=0; i<4; i++) + for(char j=0; j<4; j++) + m->m[4 * i + j] = (i == j) ? 1 : 0; +} + +void mat4_from_vec4(Matrix4 * m, const Vector4 * vx, const Vector4 * vy, const Vector4 * vz, const Vector4 * vw) +{ + m->m[ 0] = vx->v[0]; + m->m[ 1] = vx->v[1]; + m->m[ 2] = vx->v[2]; + m->m[ 3] = vx->v[3]; + + m->m[ 4] = vy->v[0]; + m->m[ 5] = vy->v[1]; + m->m[ 6] = vy->v[2]; + m->m[ 7] = vy->v[3]; + + m->m[ 8] = vz->v[0]; + m->m[ 9] = vz->v[1]; + m->m[10] = vz->v[2]; + m->m[11] = vz->v[3]; + + m->m[12] = vw->v[0]; + m->m[13] = vw->v[1]; + m->m[14] = vw->v[2]; + m->m[15] = vw->v[3]; +} + +void mat4_from_vec3(Matrix4 * m, const Vector3 * vx, const Vector3 * vy, const Vector3 * vz, const Vector3 * vw) +{ + m->m[ 0] = vx->v[0]; + m->m[ 1] = vx->v[1]; + m->m[ 2] = vx->v[2]; + m->m[ 3] = 0; + + m->m[ 4] = vy->v[0]; + m->m[ 5] = vy->v[1]; + m->m[ 6] = vy->v[2]; + m->m[ 7] = 0; + + m->m[ 8] = vz->v[0]; + m->m[ 9] = vz->v[1]; + m->m[10] = vz->v[2]; + m->m[11] = 0; + + if (vw) + { + m->m[12] = vw->v[0]; + m->m[13] = vw->v[1]; + m->m[14] = vw->v[2]; + m->m[15] = 1; + } + else + { + m->m[12] = 0; + m->m[13] = 0; + m->m[14] = 0; + m->m[15] = 0; + } +} + +void mat4_make_perspective(Matrix4 * m, float fieldOfViewInRadians, float aspect, float near, float far) +{ + float f = tan(PI * 0.5 - 0.5 * fieldOfViewInRadians); + float rangeInv = 1.0 / (far - near); + + m->m[ 0] = f / aspect; + m->m[ 1] = 0; + m->m[ 2] = 0; + m->m[ 3] = 0; + + m->m[ 4] = 0; + m->m[ 5] = f; + m->m[ 6] = 0; + m->m[ 7] = 0; + + m->m[ 8] = 0; + m->m[ 9] = 0; + m->m[10] = (near + far) * rangeInv; + m->m[11] = 1; + + m->m[12] = 0; + m->m[13] = 0; + m->m[14] = near * far * rangeInv * -2; + m->m[15] = 0; +} + +void mat4_make_view(Matrix4 * m, const Vector3 * pos, const Vector3 * target, const Vector3 * up) +{ + Vector3 vx, vy, vz; + + vec3_diff(&vz, target, pos); vec3_norm(&vz); + vec3_xmul(&vx, up, &vz); + vec3_xmul(&vy, &vz, &vx); + + mat4_from_vec3(m, &vx, &vy, &vz, pos); + mat4_invert(m); +} + + +void mat4_scale(Matrix4 * md, float s) +{ + for(char i=0; i<16; i++) + md->m[i] *= s; +} + +void mat4_add(Matrix4 * md, const Matrix4 * ms) +{ + for(char i=0; i<16; i++) + md->m[i] += md->m[i]; +} + +void mat4_mmul(Matrix4 * md, const Matrix4 * ms) +{ + float ma[4]; + for(char i=0; i<4; i++) + { + for(char j=0; j<4; j++) + ma[j] = md->m[i + 0] * ms->m[4 * j] + md->m[i + 4] * ms->m[4 * j + 1] + md->m[i + 8] * ms->m[4 * j + 2] + md->m[i + 12] * ms->m[4 * j + 3]; + for(char j=0; j<4; j++) + md->m[(char)(i + 4 * j)] = ma[j]; + } +} + +void mat4_rmmul(Matrix4 * md, const Matrix4 * ms) +{ + float ma[4]; + for(char i=0; i<16; i+=4) + { + for(char j=0; j<4; j++) + ma[j] = md->m[i + 0] * ms->m[j] + md->m[i + 1] * ms->m[j + 4] + md->m[i + 2] * ms->m[j + 8] + md->m[i + 3] * ms->m[j + 12]; + + for(char j=0; j<4; j++) + md->m[i + j] = ma[j]; + } +} + +float mat4_det(const Matrix4 * m) +{ + return m->m[ 0] * m->m[ 5] * m->m[10] * m->m[15] + m->m[ 0] * m->m[ 9] * m->m[14] * m->m[ 7] + m->m[ 0] * m->m[13] * m->m[ 6] * m->m[11] + + m->m[ 4] * m->m[ 1] * m->m[14] * m->m[11] + m->m[ 4] * m->m[ 9] * m->m[ 2] * m->m[15] + m->m[ 4] * m->m[13] * m->m[10] * m->m[ 3] + + m->m[ 8] * m->m[ 1] * m->m[ 6] * m->m[15] + m->m[ 8] * m->m[ 5] * m->m[14] * m->m[ 3] + m->m[ 8] * m->m[13] * m->m[ 2] * m->m[ 7] + + m->m[12] * m->m[ 1] * m->m[10] * m->m[ 7] + m->m[12] * m->m[ 5] * m->m[ 2] * m->m[11] + m->m[12] * m->m[ 9] * m->m[ 6] * m->m[ 3] - + m->m[ 0] * m->m[ 5] * m->m[14] * m->m[11] - m->m[ 0] * m->m[ 9] * m->m[ 6] * m->m[15] - m->m[ 0] * m->m[13] * m->m[10] * m->m[ 7] - + m->m[ 4] * m->m[ 1] * m->m[10] * m->m[15] - m->m[ 4] * m->m[ 9] * m->m[14] * m->m[ 3] - m->m[ 4] * m->m[13] * m->m[ 2] * m->m[11] - + m->m[ 8] * m->m[ 1] * m->m[14] * m->m[ 7] - m->m[ 8] * m->m[ 5] * m->m[ 2] * m->m[15] - m->m[ 8] * m->m[13] * m->m[ 6] * m->m[ 3] - + m->m[12] * m->m[ 1] * m->m[ 6] * m->m[11] - m->m[12] * m->m[ 5] * m->m[10] * m->m[ 3] - m->m[12] * m->m[ 9] * m->m[ 2] * m->m[ 7]; +} + +void mat4_invert(Matrix4 * md, const Matrix4 * ms) +{ + float det = 1 / mat4_det(ms); + + Matrix4 mt; + + mt.m[ 0] = det * (ms->m[ 5] * ms->m[10] * ms->m[15]+ms->m[ 9] * ms->m[14] * ms->m[ 7]+ms->m[13] * ms->m[ 6] * ms->m[11]-ms->m[ 5] * ms->m[14] * ms->m[11]-ms->m[ 9] * ms->m[ 6] * ms->m[15]-ms->m[13] * ms->m[10] * ms->m[ 7]); + mt.m[ 4] = det * (ms->m[ 4] * ms->m[14] * ms->m[11]+ms->m[ 8] * ms->m[ 6] * ms->m[15]+ms->m[12] * ms->m[10] * ms->m[ 7]-ms->m[ 4] * ms->m[10] * ms->m[15]-ms->m[ 8] * ms->m[14] * ms->m[ 7]-ms->m[12] * ms->m[ 6] * ms->m[11]); + mt.m[ 8] = det * (ms->m[ 4] * ms->m[ 9] * ms->m[15]+ms->m[ 8] * ms->m[13] * ms->m[ 7]+ms->m[12] * ms->m[ 5] * ms->m[11]-ms->m[ 4] * ms->m[13] * ms->m[11]-ms->m[ 8] * ms->m[ 5] * ms->m[15]-ms->m[12] * ms->m[ 9] * ms->m[ 7]); + mt.m[12] = det * (ms->m[ 4] * ms->m[13] * ms->m[10]+ms->m[ 8] * ms->m[ 5] * ms->m[14]+ms->m[12] * ms->m[ 9] * ms->m[ 6]-ms->m[ 4] * ms->m[ 9] * ms->m[14]-ms->m[ 8] * ms->m[13] * ms->m[ 6]-ms->m[12] * ms->m[ 5] * ms->m[10]); + + mt.m[ 1] = det * (ms->m[ 1] * ms->m[14] * ms->m[11]+ms->m[ 9] * ms->m[ 2] * ms->m[15]+ms->m[13] * ms->m[10] * ms->m[ 3]-ms->m[ 1] * ms->m[10] * ms->m[15]-ms->m[ 9] * ms->m[14] * ms->m[ 3]-ms->m[13] * ms->m[ 2] * ms->m[11]); + mt.m[ 5] = det * (ms->m[ 0] * ms->m[10] * ms->m[15]+ms->m[ 8] * ms->m[14] * ms->m[ 3]+ms->m[12] * ms->m[ 2] * ms->m[11]-ms->m[ 0] * ms->m[14] * ms->m[11]-ms->m[ 8] * ms->m[ 2] * ms->m[15]-ms->m[12] * ms->m[10] * ms->m[ 3]); + mt.m[ 9] = det * (ms->m[ 0] * ms->m[13] * ms->m[11]+ms->m[ 8] * ms->m[ 1] * ms->m[15]+ms->m[12] * ms->m[ 9] * ms->m[ 3]-ms->m[ 0] * ms->m[ 9] * ms->m[15]-ms->m[ 8] * ms->m[13] * ms->m[ 3]-ms->m[12] * ms->m[ 1] * ms->m[11]); + mt.m[13] = det * (ms->m[ 0] * ms->m[ 9] * ms->m[14]+ms->m[ 8] * ms->m[13] * ms->m[ 2]+ms->m[12] * ms->m[ 1] * ms->m[10]-ms->m[ 0] * ms->m[13] * ms->m[10]-ms->m[ 8] * ms->m[ 1] * ms->m[14]-ms->m[12] * ms->m[ 9] * ms->m[ 2]); + + mt.m[ 2] = det * (ms->m[ 1] * ms->m[ 6] * ms->m[15]+ms->m[ 5] * ms->m[14] * ms->m[ 3]+ms->m[13] * ms->m[ 2] * ms->m[ 7]-ms->m[ 1] * ms->m[14] * ms->m[ 7]-ms->m[ 5] * ms->m[ 2] * ms->m[15]-ms->m[13] * ms->m[ 6] * ms->m[ 3]); + mt.m[ 6] = det * (ms->m[ 0] * ms->m[14] * ms->m[ 7]+ms->m[ 4] * ms->m[ 2] * ms->m[15]+ms->m[12] * ms->m[ 6] * ms->m[ 3]-ms->m[ 0] * ms->m[ 6] * ms->m[15]-ms->m[ 4] * ms->m[14] * ms->m[ 3]-ms->m[12] * ms->m[ 2] * ms->m[ 7]); + mt.m[10] = det * (ms->m[ 0] * ms->m[ 5] * ms->m[15]+ms->m[ 4] * ms->m[13] * ms->m[ 3]+ms->m[12] * ms->m[ 1] * ms->m[ 7]-ms->m[ 0] * ms->m[13] * ms->m[ 7]-ms->m[ 4] * ms->m[ 1] * ms->m[15]-ms->m[12] * ms->m[ 5] * ms->m[ 3]); + mt.m[14] = det * (ms->m[ 0] * ms->m[13] * ms->m[ 6]+ms->m[ 4] * ms->m[ 1] * ms->m[14]+ms->m[12] * ms->m[ 5] * ms->m[ 2]-ms->m[ 0] * ms->m[ 5] * ms->m[14]-ms->m[ 4] * ms->m[13] * ms->m[ 2]-ms->m[12] * ms->m[ 1] * ms->m[ 6]); + + mt.m[ 3] = det * (ms->m[ 1] * ms->m[10] * ms->m[ 7]+ms->m[ 5] * ms->m[ 2] * ms->m[11]+ms->m[ 9] * ms->m[ 6] * ms->m[ 3]-ms->m[ 1] * ms->m[ 6] * ms->m[11]-ms->m[ 5] * ms->m[10] * ms->m[ 3]-ms->m[ 9] * ms->m[ 2] * ms->m[ 7]); + mt.m[ 7] = det * (ms->m[ 0] * ms->m[ 6] * ms->m[11]+ms->m[ 4] * ms->m[10] * ms->m[ 3]+ms->m[ 8] * ms->m[ 2] * ms->m[ 7]-ms->m[ 0] * ms->m[10] * ms->m[ 7]-ms->m[ 4] * ms->m[ 2] * ms->m[11]-ms->m[ 8] * ms->m[ 6] * ms->m[ 3]); + mt.m[11] = det * (ms->m[ 0] * ms->m[ 9] * ms->m[ 7]+ms->m[ 4] * ms->m[ 1] * ms->m[11]+ms->m[ 8] * ms->m[ 5] * ms->m[ 3]-ms->m[ 0] * ms->m[ 5] * ms->m[11]-ms->m[ 4] * ms->m[ 9] * ms->m[ 3]-ms->m[ 8] * ms->m[ 1] * ms->m[ 7]); + mt.m[15] = det * (ms->m[ 0] * ms->m[ 5] * ms->m[10]+ms->m[ 4] * ms->m[ 9] * ms->m[ 2]+ms->m[ 8] * ms->m[ 1] * ms->m[ 6]-ms->m[ 0] * ms->m[ 9] * ms->m[ 6]-ms->m[ 4] * ms->m[ 1] * ms->m[10]-ms->m[ 8] * ms->m[ 5] * ms->m[ 2]); + + *md = mt; +} + + +void vec4_mmul(Vector4 * vd, const Matrix4 * m, const Vector4 * vs) +{ + Vector4 vt; + for(char i=0; i<4; i++) + vt.v[i] = m->m[0 + i] * vs->v[0] + m->m[4 + i] * vs->v[1] + m->m[8 + i] * vs->v[2] + m->m[12 + i] * vs->v[3]; + *vd = vt; +} + +void vec3_mmulp(Vector3 * vd, const Matrix4 * m, const Vector3 * vs) +{ + Vector3 vt; + for(char i=0; i<3; i++) + vt.v[i] = m->m[0 + i] * vs->v[0] + m->m[4 + i] * vs->v[1] + m->m[8 + i] * vs->v[2] + m->m[12 + i]; + *vd = vt; +} + +void vec3_mmuld(Vector3 * vd, const Matrix4 * m, const Vector3 * vs) +{ + Vector3 vt; + for(char i=0; i<3; i++) + vt.v[i] = m->m[0 + i] * vs->v[0] + m->m[4 + i] * vs->v[1] + m->m[8 + i] * vs->v[2]; + *vd = vt; +} + + +void mat4_set_rotate_x(Matrix4 * m, float a) +{ + float c = cos(a); + float s = sin(a); + m->m[ 0] = 1; m->m[ 4] = 0; m->m[ 8] = 0; m->m[12] = 0; + m->m[ 1] = 0; m->m[ 5] = c; m->m[ 9] = s; m->m[13] = 0; + m->m[ 2] = 0; m->m[ 6] =-s; m->m[10] = c; m->m[14] = 0; + m->m[ 3] = 0; m->m[ 7] = 0; m->m[11] = 0; m->m[15] = 1; +} + +void mat4_set_rotate_y(Matrix4 * m, float a) +{ + float c = cos(a); + float s = sin(a); + m->m[ 0] = c; m->m[ 4] = 0; m->m[ 8] = s; m->m[12] = 0; + m->m[ 1] = 0; m->m[ 5] = 1; m->m[ 9] = 0; m->m[13] = 0; + m->m[ 2] =-s; m->m[ 6] = 0; m->m[10] = c; m->m[14] = 0; + m->m[ 3] = 0; m->m[ 7] = 0; m->m[11] = 0; m->m[15] = 1; +} + + +void mat4_set_rotate_z(Matrix4 * m, float a) +{ + float c = cos(a); + float s = sin(a); + m->m[ 0] = c; m->m[ 4] =-s; m->m[ 8] = 0; m->m[12] = 0; + m->m[ 1] = s; m->m[ 5] = c; m->m[ 9] = 0; m->m[13] = 0; + m->m[ 2] = 0; m->m[ 6] = 0; m->m[10] = 1; m->m[14] = 0; + m->m[ 3] = 0; m->m[ 7] = 0; m->m[11] = 0; m->m[15] = 1; +} + +void mat4_set_rotate(Matrix4 * m, const Vector3 * v, float a) +{ + float co = cos(a); + float si = sin(a); + float ico = (1- co); + + m->m[ 0] = co + v->v[0]*v->v[0]*ico; + m->m[ 1] = v->v[1]*v->v[0]*ico+v->v[2]*si; + m->m[ 2] = v->v[2]*v->v[0]*ico-v->v[1]*si; + m->m[ 3] = 0; + + m->m[ 4] = v->v[0]*v->v[1]*ico - v->v[2]*si; + m->m[ 5] = co + v->v[1]*v->v[1]*ico; + m->m[ 6] = v->v[2]*v->v[1]*ico+v->v[0]*si; + m->m[ 7] = 0; + + m->m[ 8] = v->v[0]*v->v[2]*ico + v->v[1]*si; + m->m[ 9] = v->v[1]*v->v[2]*ico - v->v[0]*si; + m->m[10] = co + v->v[2]*v->v[2]*ico; + m->m[11] = 0; + + m->m[12] = 0; + m->m[13] = 0; + m->m[14] = 0; + m->m[15] = 1; +} + + +void mat4_set_translate(Matrix4 * m, const Vector3 * v) +{ + mat4_ident(m); + m->m[12] = v->v[0]; + m->m[13] = v->v[1]; + m->m[14] = v->v[2]; +} + +void mat4_set_scale(Matrix4 * m, float s) +{ + mat4_ident(m); + m->m[ 0] = s; + m->m[ 5] = s; + m->m[10] = s; +} + + +void vec3_project(Vector3 * vd, const Matrix4 * m, const Vector3 * vs) +{ + vec3_mmulp(vd, m, vs); + vd->v[0] /= vd->v[2]; + vd->v[1] /= vd->v[2]; +} diff --git a/include/gfx/vector3d.h b/include/gfx/vector3d.h new file mode 100644 index 0000000..ebd27da --- /dev/null +++ b/include/gfx/vector3d.h @@ -0,0 +1,262 @@ +#ifndef VECTOR3D_H +#define VECTOR3D_H + +struct Vector2 +{ + float v[2]; +}; + +void vec2_sum(Vector2 * vd, const Vector2 * v1, const Vector2 * v2); + +void vec2_diff(Vector2 * vd, const Vector2 * v1, const Vector2 * v2); + +void vec2_add(Vector2 * vd, const Vector2 * vs); + +void vec2_sub(Vector2 * vd, const Vector2 * vs); + +void vec2_madd(Vector2 * vd, float s, const Vector2 * vs); + +void vec2_scale(Vector2 * vd, float s); + +void vec2_lincomb(Vector2 * vd, const Vector2 * vb, float x, const Vector2 * vx); + +void vec2_lincomb2(Vector2 * vd, const Vector2 * vb, float x, const Vector2 * vx, float y, const Vector2 * vy); + +void vec2_lerp(Vector2 * vd, const Vector2 * v1, const Vector2 * v2, float t); + +bool vec2_is_zero(const Vector2 * v); + +float vec2_vmul(const Vector2 * v1, const Vector2 * v2); + +void vec2_norm(Vector2 * v); + +float vec2_length(const Vector2 * v); + +float vec2_qlength(const Vector2 * v); + +float vec2_distance(const Vector2 * v1, const Vector2 * v2); + +float vec2_qdistance(const Vector2 * v1, const Vector2 * v2); + + +struct Matrix2 +{ + float m[4]; +}; + +void mat2_ident(Matrix2 * md); + +void mat2_add(Matrix2 * md, const Matrix2 * ms); + +void mat2_scale(Matrix2 * md, float s); + +void mat2_mmul(Matrix2 * md, const Matrix2 * ms); + +void mat2_rmmul(Matrix2 * md, const Matrix2 * ms); + +void mat2_tranpose(Matrix2 * md); + +void vec2_mmul(Vector2 * vd, const Matrix2 * m, const Vector2 * vs); + +void vec2_mimul(Vector2 * vd, const Matrix2 * m, const Vector2 * vs); + +void mat2_set_rotate(Matrix2 * md, float a); + +void mat2_rotate(Matrix2 * md, float a); + +float mat2_det(const Matrix2 * ms); + +void mat2_invert(Matrix2 * md, const Matrix2 * ms); + + +struct Vector3 +{ + float v[3]; +} + +inline void vec3_set(Vector3 * vd, float x, float y, float z); + +void vec3_sum(Vector3 * vd, const Vector3 * v1, const Vector3 * v2); + +void vec3_diff(Vector3 * vd, const Vector3 * v1, const Vector3 * v2); + +void vec3_add(Vector3 * vd, const Vector3 * vs); + +void vec3_sub(Vector3 * vd, const Vector3 * vs); + +void vec3_madd(Vector3 * vd, float s, const Vector3 * vs); + +void vec3_scale(Vector3 * vd, float s); + +void vec3_lincomb(Vector3 * vd, const Vector3 * vb, float x, const Vector3 * vx); + +void vec3_lincomb2(Vector3 * vd, const Vector3 * vb, float x, const Vector3 * vx, float y, const Vector3 * vy); + +void vec3_lerp(Vector3 * vd, const Vector3 * v1, const Vector3 * v2, float t); + +bool vec3_is_zero(const Vector3 * v); + +float vec3_vmul(const Vector3 * v1, const Vector3 * v2); + +void vec3_norm(Vector3 * v); + +float vec3_length(const Vector3 * v); + +float vec3_qlength(const Vector3 * v); + +float vec3_distance(const Vector3 * v1, const Vector3 * v2); + +float vec3_qdistance(const Vector3 * v1, const Vector3 * v2); + +void vec3_mcadd(Vector3 * vd, const Vector3 * v1, const Vector3 * v2); + +void vec3_mscadd(Vector3 * vd, float s, const Vector3 * v1, const Vector3 * v2); + +void vec3_cmul(Vector3 * vd, const Vector3 * v1, const Vector3 * v2); + +void vec3_xmul(Vector3 * vd, const Vector3 * v1, const Vector3 * v2); + +void vec3_mbase(Vector3 * v1, Vector3 * v2, Vector3 * v3); + +void vec3_bend(Vector3 * vd, const Vector3 * vs, float chi1, float chi2); + + + +struct Matrix3 +{ + float m[9]; +} + +void mat3_ident(Matrix3 * m); + +void mat3_scale(Matrix3 * md, float s); + +void mat3_add(Matrix3 * md, const Matrix3 * ms); + +void mat3_mmul(Matrix3 * md, const Matrix3 * ms); + +void mat3_rmmul(Matrix3 * md, const Matrix3 * ms); + +void mat3_transpose(Matrix3 * md, const Matrix3 * ms); + +float mat3_det(const Matrix3 * ms); + +void mat3_invert(Matrix3 * md, const Matrix3 * ms); + +void vec3_mmul(Vector3 * vd, const Matrix3 * m, const Vector3 * vs); + +void mat3_set_rotate_x(Matrix3 * m, float a); + +void mat3_set_rotate_y(Matrix3 * m, float a); + +void mat3_set_rotate_z(Matrix3 * m, float a); + +void mat3_set_rotate(Matrix3 * m, const Vector3 * v, float a); + + + +struct Vector4 +{ + float v[4]; +} + +inline void vec4_set(Vector4 * vd, float x, float y, float z, float w); + +void vec4_sum(Vector4 * vd, const Vector4 * v1, const Vector4 * v2); + +void vec4_diff(Vector4 * vd, const Vector4 * v1, const Vector4 * v2); + +void vec4_add(Vector4 * vd, const Vector4 * vs); + +void vec4_sub(Vector4 * vd, const Vector4 * vs); + +void vec4_madd(Vector4 * vd, float s, const Vector4 * vs); + +void vec4_scale(Vector4 * vd, float s); + +void vec4_lincomb(Vector4 * vd, const Vector4 * vb, float x, const Vector4 * vx); + +void vec4_lincomb2(Vector4 * vd, const Vector4 * vb, float x, const Vector4 * vx, float y, const Vector4 * vy); + +void vec4_lerp(Vector4 * vd, const Vector4 * v1, const Vector4 * v2, float t); + +bool vec4_is_zero(const Vector4 * v); + +float vec4_vmul(const Vector4 * v1, const Vector4 * v2); + +void vec4_norm(Vector4 * v); + +float vec4_length(const Vector4 * v); + +float vec4_qlength(const Vector4 * v); + +float vec4_distance(const Vector4 * v1, const Vector4 * v2); + +float vec4_qdistance(const Vector4 * v1, const Vector4 * v2); + +void vec4_mcadd(Vector4 * vd, const Vector4 * v1, const Vector4 * v2); + +void vec4_mscadd(Vector4 * vd, float s, const Vector4 * v1, const Vector4 * v2); + +void vec4_cmul(Vector4 * vd, const Vector4 * v1, const Vector4 * v2); + +void vec4_xmul(Vector4 * vd, const Vector4 * v1, const Vector4 * v2); + +void vec4_mbase(Vector4 * v1, Vector4 * v2, Vector4 * v3); + +void vec4_bend(Vector4 * vd, const Vector4 * vs, float chi1, float chi2); + + +struct Matrix4 +{ + float m[16]; +} + +void mat4_ident(Matrix4 * m); + +void mat4_from_vec4(Matrix4 * m, const Vector4 * vx, const Vector4 * vy, const Vector4 * vz, const Vector4 * vw); + +void mat4_from_vec3(Matrix4 * m, const Vector3 * vx, const Vector3 * vy, const Vector3 * vz, const Vector3 * vw); + +void mat4_make_perspective(Matrix4 * m, float fieldOfViewInRadians, float aspect, float near, float far); + +void mat4_make_view(Matrix4 * m, const Vector3 * pos, const Vector3 * target, const Vector3 * up); + +void mat4_scale(Matrix4 * md, float s); + +void mat4_add(Matrix4 * md, const Matrix4 * ms); + +void mat4_mmul(Matrix4 * md, const Matrix4 * ms); + +void mat4_rmmul(Matrix4 * md, const Matrix4 * ms); + +float mat4_det(const Matrix4 * m); + +void mat4_invert(Matrix4 * md, const Matrix4 * ms); + +void vec4_mmul(Vector4 * vd, const Matrix4 * m, const Vector4 * vs); + +void vec3_mmulp(Vector3 * vd, const Matrix4 * m, const Vector3 * vs); + +void vec3_mmuld(Vector3 * vd, const Matrix4 * m, const Vector3 * vs); + + +void mat4_set_rotate_x(Matrix4 * m, float a); + +void mat4_set_rotate_y(Matrix4 * m, float a); + +void mat4_set_rotate_z(Matrix4 * m, float a); + +void mat4_set_rotate(Matrix4 * m, const Vector3 * v, float a); + +void mat4_set_translate(Matrix4 * m, const Vector3 * v); + +void mat4_set_scale(Matrix4 * m, float s); + + +void vec3_project(Vector3 * vd, const Matrix4 * m, const Vector3 * vs); + +#pragma compile("vector3d.c") + +#endif +