From 2ed0d168510a75730168eed9fffacaa8147bf781 Mon Sep 17 00:00:00 2001 From: Ivan Mahonin Date: Jun 22 2022 03:55:26 +0000 Subject: onefile --- diff --git a/onefile/.gitignore b/onefile/.gitignore new file mode 100644 index 0000000..a10da3b --- /dev/null +++ b/onefile/.gitignore @@ -0,0 +1 @@ +/data/output/ diff --git a/onefile/curves.c b/onefile/curves.c new file mode 100644 index 0000000..a7c835e --- /dev/null +++ b/onefile/curves.c @@ -0,0 +1,170 @@ + +#include +#include + + +#define COUNT 16 +#define SIZE 17 +#define RADIUS 5 +#define PRECISION 1e-5 + + +double points[COUNT][2]; +double *curPoint; +double curPointOffset[2]; + +int graphs[10]; + + +double value(int ix) + { return points[ ((ix + COUNT/2)%COUNT + COUNT)%COUNT ][1]; } + +double nearest(double x) + { return value(floor(x)); } + +double linear(double x) { + x -= 0.5; + int ix = floor(x); + x -= ix; + return value(ix)*(1-x) + value(ix+1)*x; +} + +double cubic(double x) { + x -= 0.5; + int ix = floor(x); + x -= ix; + + double a = value(ix-1); + double b = value(ix+0); + double c = value(ix+1); + double d = value(ix+2); + + return a*( -0.5*x*x*x + x*x - 0.5*x ) + + b*( 1.5*x*x*x - 2.5*x*x + 1.0 ) + + c*( -1.5*x*x*x + 2.0*x*x + 0.5*x ) + + d*( 0.5*x*x*x - 0.5*x*x ); +} + +double bspline(double x) { + x -= 0.5; + int ix = floor(x); + x -= ix; + + double a = value(ix-1); + double b = value(ix+0); + double c = value(ix+1); + double d = value(ix+2); + + return a*( -x*x*x + 3*x*x - 3*x + 1)/6 + + b*( 3*x*x*x - 6*x*x + 4 )/6 + + c*(-3*x*x*x + 3*x*x + 3*x + 1)/6 + + d*( x*x*x )/6; +} + + +void graph(double kx, double ky, double (*func)(double), unsigned int color) { + saveState(); + strokeWidth(2); + stroke(color); + int hs = (int)ceil(SIZE*kx/2); + for(int x = -hs; x <= hs; ++x) + lineTo(x, func(x/kx)*ky); + strokePath(); + restoreState(); +} + + +void grid(double kx, double ky) { + saveState(); + strokeWidth(1); + stroke(colorByRGBA(0, 0, 1, 0.125)); + double hs = 0.5*SIZE; + for(int step = 16; step; step >>= 1) { + for(int i = 0; i <= SIZE/2; i += step) { + line(-hs*kx, i*ky, hs*kx, i*ky); + line(-hs*kx, -i*ky, hs*kx, -i*ky); + line( i*kx, -hs*ky, i*kx, hs*ky); + line(-i*kx, -hs*ky, -i*kx, hs*ky); + } + } + restoreState(); +} + +void randomize() { + for(int i = 0; i < COUNT; ++i) + points[i][1] = randomFloat()*SIZE - SIZE/2.0; +} + +void zero() { + for(int i = 0; i < COUNT; ++i) + points[i][1] = 0; +} + +void init() { + for(int i = 0; i < COUNT; ++i) + points[i][0] = i - COUNT/2 + 0.5; + randomize(); +} + + +void draw() { + double w = windowGetWidth(); + double h = windowGetHeight(); + double kx = w/SIZE; + double ky = h/SIZE; + + saveState(); + translate(w/2, h/2); + scale(1, -1); + + if (keyWentDown("r")) { randomize(); curPoint = 0; } + if (keyWentDown("z")) { zero(); curPoint = 0; } + char key[] = "0"; + for(int i = 0; i < 10; ++i, ++*key) + if (keyWentDown(key)) graphs[i] = !graphs[i]; + + int m = mouseWentDown("left"); + double mx = mouseTransformedX(); + double my = mouseTransformedY(); + if (!mouseDown("left")) + { m = FALSE; curPoint = 0; } + if (curPoint) { + //curPoint[0] = (mx + curPointOffset[0])/kx; + curPoint[1] = (my + curPointOffset[1])/ky; + } + + grid(kx, ky); + if (graphs[0]) graph(kx, ky, nearest, colorByRGBA(0, 0, 0, 0.5)); + if (graphs[1]) graph(kx, ky, linear , colorByRGBA(0, 1, 0, 0.5)); + if (graphs[2]) graph(kx, ky, cubic , colorByRGBA(0, 0, 1, 0.5)); + if (graphs[3]) graph(kx, ky, bspline, colorByRGBA(1, 0, 0, 0.5)); + + strokeWidth(2); + stroke(COLOR_BLUE); + fill(COLOR_WHITE); + for(int i = 0; i < COUNT; ++i) { + double x = points[i][0]*kx, y = points[i][1]*ky; + line(x, 0, x, y); + circle(x, y, RADIUS); + if (i == COUNT/2) + circle(x, y, RADIUS + 1); + double dx = x-mx, dy = y-my; + if (m && dx*dx + dy*dy <= RADIUS*RADIUS) { + curPoint = points[i]; + curPointOffset[0] = dx; + curPointOffset[1] = dy; + } + } + + restoreState(); +} + + +int main() { + windowSetVariableFrameRate(); + windowSetResizable(TRUE); + windowSetInit(&init); + windowSetDraw(&draw); + windowRun(); + return 0; +} diff --git a/onefile/curves2.c b/onefile/curves2.c new file mode 100644 index 0000000..d67f032 --- /dev/null +++ b/onefile/curves2.c @@ -0,0 +1,104 @@ + +#include + + +#define COUNT 5 +#define RADIUS 5 +#define PRECISION 1e-5 + + +double points[COUNT][2]; +double *curPoint; +double curPointOffset[2]; + + + +double calcCurveValue(double *curve, int count, double x) { + if (count <= 0) return 0; + if (count == 1) return curve[1]; + if (x <= curve[0]) return curve[1]; + if (x >= curve[(count-1)*2]) return curve[(count-1)*2 + 1]; + + int i = 0; + while(i+1 < count && curve[(i+1)*2] < x) + ++i; + + double *p1 = &curve[i*2]; + double *p0 = i > 0 ? p1-2 : p1; + double *p2 = i+1 < count ? p1+2 : p1; + double *p3 = i+2 < count ? p2+2 : p2; + + double dx = p2[0] - p1[0]; + if (dx <= PRECISION) return p1[1]; + + double a = p1[1]; + double b = p2[1]; + double ta = p2[0]-p0[0]; ta = ta > PRECISION ? (p2[1]-p0[1])/ta*dx : 0; + double tb = p3[0]-p1[0]; tb = tb > PRECISION ? (p3[1]-p1[1])/tb*dx : 0; + double l = (x - p1[0])/dx; + + return a + (ta + (3*(b-a)-ta-ta-tb + (2*(a-b)+ta+tb)*l)*l)*l; +} + + +void init() { + for(int i = 0; i < COUNT; ++i) + points[i][0] = points[i][1] = i/(COUNT - 1.0); + calcCurveValue(points[0], COUNT, 0.3); +} + + +void draw() { + double w = windowGetWidth(); + double h = windowGetHeight(); + + saveState(); + translate(0, h); + scale(1, -1); + + noFill(); + stroke(colorByRGBA(0.75, 0.75, 0.75, 1)); + strokeWidth(2); + rect(0, 0, w, h); + + strokeWidth(2); + line(0, 0, w, h); + + int m = mouseWentDown("left"); + double mx = mouseTransformedX(); + double my = mouseTransformedY(); + if (!mouseDown("left")) + { m = FALSE; curPoint = 0; } + if (curPoint) { + curPoint[0] = (mx + curPointOffset[0])/w; + curPoint[1] = (my + curPointOffset[1])/h; + } + + stroke(COLOR_BLUE); + fill(COLOR_WHITE); + for(int i = 0; i < w+1; ++i) + lineTo(i, calcCurveValue(points[0], COUNT, i/w)*h); + strokePath(); + for(int i = 0; i < COUNT; ++i) { + double x = points[i][0]*w, y = points[i][1]*h; + circle(x, y, RADIUS); + double dx = x-mx, dy = y-my; + if (m && dx*dx + dy*dy <= RADIUS*RADIUS) { + curPoint = points[i]; + curPointOffset[0] = dx; + curPointOffset[1] = dy; + } + } + + restoreState(); +} + + +int main() { + windowSetVariableFrameRate(); + windowSetResizable(TRUE); + windowSetInit(&init); + windowSetDraw(&draw); + windowRun(); + return 0; +} diff --git a/onefile/data/.placeholder b/onefile/data/.placeholder new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/onefile/data/.placeholder diff --git a/onefile/message3d.c b/onefile/message3d.c new file mode 100644 index 0000000..6d0d9aa --- /dev/null +++ b/onefile/message3d.c @@ -0,0 +1,585 @@ + +#include +#include +#include +#include +#include + +#include + + +#define SPLITPOINTS 17 +double pointsArc[SPLITPOINTS][3]; +double pointsQua[SPLITPOINTS][3]; +double pointsCub[SPLITPOINTS][4]; + +double ax = 0; +double ay = 10; +double mx, my; + +int randomAngle = 1; +int rnd = 0; + +typedef struct { + double mat[9]; + double ox, oy; + double curr[3]; +} Painter; + + +const char *letters[][2] = { + { "box", "L000-800-880-080-000-008-808-888-088-008 800-808 880-888 080-088" + " 004-804-884-084z 040-840-848-048z 400-480-488-408z" }, + { "star", "L440-533-844-535-448-335-044-333-440-553-844-555-448-355-044-353z" + " 333-404-535 335-404-533 353-484-555 355-484-553" }, + //{ "cube", "L000-800-880-080-000-008-808-888-088-008 800-808 880-888 080-088" }, + //{ "cub", "L000-800-880-080-000-008-808-888-088-008 800-808 880-888 080-088" }, + { "a", "L000-448-800 080-448-880 224-624-664-264z" }, + { "b", "L000-008-608-A808-806-804-604-L004-064-A084-086-088-068-L008 A806-886-086 608-668-068 604-664-064 600-660-060 802-882-082 604-804-802-800-600-L000-060-A080-082-084-064-L004" }, + { "c", "L800-400-A000-004-008-408-L808-848-A888-884-880-840-L800 A004-084-884 400-440-840 408-448-848" }, + { "d", "L008-000-400-A800-804-808-408-L008-048-A088-084-080-040-L000 A804-884-084 400-440-040 408-448-048" }, + { "e", "L000-800-880-080-000-008-808-888-088-008 004-804-884-084z" }, + { "f", "L000-008-808-888-088-008 004-804-884-084z" }, + { "g", "L800-804-404-A444-844-L804-A800-400-000-004-008-408-L808-848-A888-884-880-840-800-804 A004-084-884 400-440-840 408-448-848" }, + { "h", "L004-804-884-084z 000-008 800-808 880-888 080-088" }, + { "i", "L440-448 220-260-660-620z 228-268-668-628z" }, + { "j", "A848-888-488-088-048-008-408-808-848-L844-A840-440-040-044-004-404-804-844-884-484-084-044 404-400-440-480-484" }, + { "k", "L000-008 800-004-808 080-004-088 880-004-888" }, + { "l", "L008-000-800-880-080-000" }, + { "m", "L000-228-400-628-800 080-268-480-668-880 040-268-440-668-840-628-440-228z" }, + { "n", "L000-008-800-808 008-080-088 008-880-888" }, + { "o", "A044-040-440-840-844-848-448-048-044-004-404-804-844-884-484-084-044 404-400-440-480-484-488-448-408-404" }, + { "p", "L000-008-608-A808-806-804-604-L004-064-A084-086-088-068-L008 A806-886-086 608-668-068 604-664-064" }, + { "q", "A044-040-440-840-844-848-448-048-044-004-404-804-844-884-484-084-044 404-400-440-480-484-488-448-408-404 L444-840-A880-480z" }, + { "r", "L000-008-608-A808-806-804-604-L004-064-A084-086-088-068-L008 A806-886-086 608-668-068 604-664-064 604-804-802-L800-A880-080-L082-A084-064 802-882-082" }, + { "s", "A424-404-204-004-006-008-208-L808-868-A888-886-884-864-844-644 L208-248-A268-468-L868 006-046-A086-486-L886 A248-048-046-044-244 468-488-486-484-464" + " 464-484-684-884-882-880-680-L080-020-A000-002-004-024-L044-244 680-640-A620-420-L020 882-842-A802-402-L002 A640-840-842-844-644 420-400-402-404-424" + " 244-224-424-624-644-664-464-264-244" }, + { "t", "L008-808-888-088z 440-448" }, + { "u", "A848-888-488-088-048-008-408-808-848-L844-A840-440-040-044-L048 408-404-A400-440-480-484-L488 A044-004-404-804-844-884-484-084-044" }, + { "v", "L008-440-808 088-440-888" }, + { "w", "L008-220-408-620-808 088-260-488-660-888 048-260-448-660-848-620-448-220z" }, + { "x", "L000-888 800-088 880-008 080-808" }, + { "y", "L000-888 444-088 444-008 444-808" }, + { "z", "L000-800-880-080-000-888-088-008-808-888" }, + + { "0", "A044-040-440-840-844-848-448-048-044-004-404-804-844-884-484-084-044 404-400-440-480-484-488-448-408-404 L040-848" }, + { "1", "L440-448-226 220-260-660-620z" }, + { "2", "L000-002-A004-204-404-604-804-806-808-608-L008-068-A088-086-084-064-044-024-004-002-L000-800-880-080-000" + " 608-648-A668-468-L068 604-644-A664-464-L064 806-846-A886-486-L086 " + " A648-848-846-844-644 468-488-486-484-464 " }, + { "3", "L008-608-A808-806-804-604-L004-064-A084-086-088-068-L008 A806-886-086 608-668-068 604-664-064 600-660-060 802-882-082 604-804-802-800-600-L000-060-A080-082-084-064-L004" }, + { "4", "L004-804-884-084z 004-008 800-808 884-888 084-088" }, + { "5", "L008-006-A004-204-404-604-804-802-800-600-L000-060-A080-082-084-064-044-024-004-006-L008-808-888-088-008" + " 600-640-A660-460-L060 604-644-A664-464-L064 802-842-A882-482-L082 " + " A640-840-842-844-644 460-480-482-484-464 " }, + { "6", "L042-044-C048-088-488-A888-848-808-408-C008-048-044-048-048-448-L848 408-488" + " A042-040-240-L640-A840-842-844-644-L244-A044-042-002-402-802-842-882-482-082-042" + " 402-400-420-L460-A480-482-484-464-L424-A404-402 244-224-424-624-644-664-464-264-244 240-220-420-620-640-660-460-260-240 "}, + { "7", "L000-888-088-008-808-888 224-264-664-624z" }, + { "8", "A244-044-042-040-240-L640-A840-842-844-644-L244-A044-046-048-248-L648-A848-846-844-644" + " 424-404-402-400-420-L460-A480-482-484-464-L424-A404-406-408-428-L468-A488-486-484-464" + " 042-002-402-802-842-882-482-082-042 046-006-406-806-846-886-486-086-046" + " 240-220-420-620-640-660-460-260-240 244-224-424-624-644-664-464-264-244 248-228-428-628-648-668-468-268-248" }, + { "9", "L846-844-C840-880-480-A080-040-000-400-C800-840-844-840-840-440-L040 400-480" + " A046-048-248-L648-A848-846-844-644-L244-A044-046-006-406-806-846-886-486-086-046" + " 406-408-428-L468-A488-486-484-464-L424-A404-406 244-224-424-624-644-664-464-264-244 248-228-428-628-648-668-468-268-248 "}, + + { ",", "P442 L442-220" }, + { "...", "P002 402 802 042 442 842 882 482 082" }, + { "..", "P222 622 662 262" }, + { ".", "L331-531-551-351-331-333-533-553-353-333 531-533 551-553 351-353 " }, + //{ ".", "P442" }, + { "?", "A442-444-424-404-604-804-806-808-608-L008-068-A088-086-084-064-044-244-444-442" + " L608-648-A668-468-L068 806-846-A886-486-L086" + " A648-848-846-844-644-444-442 468-488-486-484-464-444-442 424-624-644-664-464-264-244 P440" }, + { "!", "A442-244-246-248-448-648-646-644-442 A442-424-426-428-448-468-466-464-442 246-226-426-626-646-666-466-266-246 P440" }, + { ":", "P222 622 662 262 226 626 666 266" }, + { ";", "P222 622 662 262 226 626 666 266 L222-240 L622-420 L662-640 L262-460" }, + { "\"","P226 626 666 266 L226-244 L626-424 L666-644 L266-464" }, + { "\'","P446 L446-224" }, + { "`", "P446 L446-664" }, + { "<", "L800-044-880 808-044-888" }, + { ">", "L000-844-080 008-844-088" }, + { "=", "L222-262-662-622z 226-266-666-626z" }, + { "-", "L224-264-664-624z" }, + { "+", "L244-644 424-464 442-446" }, + { "*", "L244-644 424-464 442-446 222-666 622-266 662-226 262-626" }, + { "/", "L000-888" }, + { "\\","L800-088" }, + { "^", "L226-448-666 626-448-266" }, + { "(", "A640-680-684-688-648-608-604-600-640-240-244-248-648 604-204-244-284-684" }, + { ")", "A240-280-284-288-248-208-204-200-240-640-644-648-248 204-604-644-684-284" }, + { "[", "L640-680-684-688-648-608-604-600-640-240-244-248-648 604-204-244-284-684" }, + { "]", "L240-280-284-288-248-208-204-200-240-640-644-648-248 204-604-644-684-284" }, + { "{", "A640-440-442-444-244-444-446-448-648 604-404-424-444-244-444-464-484-684" + " 464-466-446-426-424-422-442-462-464 L684-688-648-608-604-600-640-680-684 " }, + { "}", "A240-440-442-444-644-444-446-448-248 204-404-424-444-644-444-464-484-284" + " 464-466-446-426-424-422-442-462-464 L284-288-248-208-204-200-240-280-284 " }, + { "_", "L000-800-880-080z" }, + { "||","L220-228 620-628 660-668 260-268" }, + { "|", "L440-448" }, + { "#", "L220-228 620-628 660-668 260-268 202-282 206-286 606-686 602-682 022-822 062-862 066-866 026-826" }, + { "@", "A244-242-442-642-644-646-446-246-244-224-424-624-644-664-464-264-244 424-422-442-462-464-466-446-426-424" + " 440-480-484-084-044-040-440-L840-800-400-440" + " C[8.00][4.00][0.00]-[8.00][6.31][0.00]-[4.52][8.33][1.78]-[4.00][8.00][4.00]" + "-[3.83][7.89][4.73]-[3.89][7.53][5.53]-[4.12][7.03][6.06]" + "-[4.36][6.53][6.59]-[4.78][5.83][6.91]-[5.18][5.18][6.89]" + "-[5.57][4.55][6.86]-[5.98][3.88][6.51]-[6.20][3.43][5.96]" + "-[6.41][3.00][5.44]-[6.47][2.71][4.68]-[6.31][2.67][4.00]" + "-[6.17][2.62][3.38]-[5.82][2.78][2.73]-[5.37][3.06][2.36]" + "-[4.98][3.30][2.04]-[4.45][3.68][1.88]-[4.00][4.00][2.00]" + "-[4.32][3.55][1.88]-[4.70][3.02][2.04]-[4.94][2.63][2.36]" + "-[5.22][2.18][2.73]-[5.38][1.83][3.38]-[5.33][1.69][4.00]" + "-[5.29][1.53][4.68]-[5.00][1.59][5.44]-[4.57][1.80][5.96]" + "-[4.12][2.02][6.51]-[3.45][2.43][6.86]-[2.82][2.82][6.89]" + "-[2.17][3.22][6.91]-[1.47][3.64][6.59]-[0.97][3.88][6.06]" + "-[0.47][4.11][5.53]-[0.11][4.17][4.73]-[0.00][4.00][4.00]" + "-[-0.33][3.48][1.78]-[1.69][0.00][0.00]-[4.00][0.00][0.00]" + " [5.18][5.18][6.89]-[4.50][4.50][7.44]-[3.50][3.50][7.44]-[2.82][2.82][6.89]" }, + { "&", " A046-048-248-L648-A848-846-844-644-L244-A044-046-006-406-806-846-886-486-086-046" + " 406-408-428-L468-A488-486-484-464-L424-A404-406 244-224-424-624-644-664-464-264-244 248-228-428-628-648-668-468-268-248" + " A424-404-204-004-002-000-200-L800-860-A880-882-884-864-844-644" + " L200-240-A260-460-L860 002-042-A082-482-L882 A240-040-042-044-244 460-480-482-484-464" }, + { "%", "A066-064-264-464-466-468-268-068-066-046-246-446-466-486-286-086-066 246-244-264-284-286-288-268-248-246" + " 422-420-620-820-822-824-624-424-422-402-602-802-822-842-642-442-422 602-600-620-640-642-644-624-604-602" + " L000-888" }, + { "~", "C244-254-255-355-A455-444-433-533-C633-634-644 A244-224-424-624-644-664-464-264-244" }, + { "$", "A424-404-204-004-006-008-208-L808-868-A888-886-884-864-844-644 L208-248-A268-468-L868 006-046-A086-486-L886 A248-048-046-044-244 468-488-486-484-464" + " 464-484-684-884-882-880-680-L080-020-A000-002-004-024-L044-244 680-640-A620-420-L020 882-842-A802-402-L002 A640-840-842-844-644 420-400-402-404-424" + " 244-224-424-624-644-664-464-264-244 L24[-2]-24[10] L64[-2]-64[10] L42[-2]-42[10] L46[-2]-46[10] " }, +}; +int lettersCount = sizeof(letters)/sizeof(letters[0]); + +const char *textToDraw = NULL; +double boxStep = 64; +double boxSize = 0.5; +int renderToFiles = 0; + + +void vec3set(double *v, double x, double y, double z) + { v[0] = x, v[1] = y, v[2] = z; } +void vec3cpy(double *v, const double *vv) + { memcpy(v, vv, sizeof(*v)*3); } +void vec3add(double *v, const double *vv) + { v[0] += vv[0]; v[1] += vv[1]; v[2] += vv[2]; } +void vec3trans(double *v, const double *m) { + vec3set(v, v[0]*m[0] + v[1]*m[3] + v[2]*m[6], + v[0]*m[1] + v[1]*m[4] + v[2]*m[7], + v[0]*m[2] + v[1]*m[5] + v[2]*m[8] ); +} + +void mat3cpy(double *m, double *mm) + { memcpy(m, mm, sizeof(*m)*9); } +void mat3one(double *m) { + m[1] = m[2] = m[3] = m[5] = m[6] = m[7] = 0; + m[0] = m[4] = m[8] = 1; +} +void mat3trans(double *m, const double *mm) { + vec3trans(m+0, mm); + vec3trans(m+3, mm); + vec3trans(m+6, mm); +} +void mat3rotX(double *m, double a) { + rotateVector(&m[1], &m[2], a); + rotateVector(&m[4], &m[5], a); + rotateVector(&m[7], &m[8], a); +} +void mat3rotY(double *m, double a) { + rotateVector(&m[2], &m[0], a); + rotateVector(&m[5], &m[3], a); + rotateVector(&m[8], &m[6], a); +} +void mat3rotZ(double *m, double a) { + rotateVector(&m[0], &m[1], a); + rotateVector(&m[3], &m[4], a); + rotateVector(&m[6], &m[7], a); +} + + +void painterInternalMoveTo(Painter *p, double x, double y, double z) { + double xx = p->mat[0]*x + p->mat[3]*y + p->mat[6]*z + p->ox; + double yy = p->mat[1]*x + p->mat[4]*y + p->mat[7]*z + p->oy; + moveTo(xx, yy); +} + +void painterInternalLineTo(Painter *p, double x, double y, double z) { + double xx = p->mat[0]*x + p->mat[3]*y + p->mat[6]*z + p->ox; + double yy = p->mat[1]*x + p->mat[4]*y + p->mat[7]*z + p->oy; + lineTo(xx, yy); +} + +void painterInternalPointTo(Painter *p, double x, double y, double z) { + double xx = p->mat[0]*x + p->mat[3]*y + p->mat[6]*z + p->ox; + double yy = p->mat[1]*x + p->mat[4]*y + p->mat[7]*z + p->oy; + saveState(); + translate(xx, yy); + zoom(3); + point(0, 0); + restoreState(); +} + +void painterFinish(Painter *p) + { strokePath(); } + +void painterMoveTo(Painter *p, double *pos) { + painterFinish(p); + painterInternalMoveTo(p, pos[0], pos[1], pos[2]); + vec3cpy(p->curr, pos); +} + +void painterLineTo(Painter *p, double *pos) { + painterInternalLineTo(p, pos[0], pos[1], pos[2]); + vec3cpy(p->curr, pos); +} + +void painterPointTo(Painter *p, double *pos) { + painterFinish(p); + painterInternalPointTo(p, pos[0], pos[1], pos[2]); + vec3cpy(p->curr, pos); +} + +void painterArcTo(Painter *p, double *pos1, double *pos2) { + double *pos0 = p->curr; + for(int i = 1; i < SPLITPOINTS; ++i) + painterInternalLineTo( p, + pointsArc[i][0]*pos0[0] + pointsArc[i][1]*pos1[0] + pointsArc[i][2]*pos2[0], + pointsArc[i][0]*pos0[1] + pointsArc[i][1]*pos1[1] + pointsArc[i][2]*pos2[1], + pointsArc[i][0]*pos0[2] + pointsArc[i][1]*pos1[2] + pointsArc[i][2]*pos2[2] ); + vec3cpy(p->curr, pos2); +} + +void painterQuadraticTo(Painter *p, double *pos1, double *pos2) { + double *pos0 = p->curr; + for(int i = 1; i < SPLITPOINTS; ++i) + painterInternalLineTo( p, + pointsQua[i][0]*pos0[0] + pointsQua[i][1]*pos1[0] + pointsQua[i][2]*pos2[0], + pointsQua[i][0]*pos0[1] + pointsQua[i][1]*pos1[1] + pointsQua[i][2]*pos2[1], + pointsQua[i][0]*pos0[2] + pointsQua[i][1]*pos1[2] + pointsQua[i][2]*pos2[2] ); + vec3cpy(p->curr, pos2); +} + +void painterCubicTo(Painter *p, double *pos1, double *pos2, double *pos3) { + double *pos0 = p->curr; + for(int i = 1; i < SPLITPOINTS; ++i) + painterInternalLineTo( p, + pointsCub[i][0]*pos0[0] + pointsCub[i][1]*pos1[0] + pointsCub[i][2]*pos2[0] + pointsCub[i][3]*pos3[0], + pointsCub[i][0]*pos0[1] + pointsCub[i][1]*pos1[1] + pointsCub[i][2]*pos2[1] + pointsCub[i][3]*pos3[1], + pointsCub[i][0]*pos0[2] + pointsCub[i][1]*pos1[2] + pointsCub[i][2]*pos2[2] + pointsCub[i][3]*pos3[2] ); + vec3cpy(p->curr, pos3); +} + +void painterClose(Painter *p) + { closePath(); } + + +void drawLetter(Painter *p, const char *cmd) { + saveState(); + noFill(); + double mat[11]; + mat3cpy(mat, p->mat); + mat[9] = p->ox; mat[10] = p->oy; + if (randomAngle) { + double m[9], v[3]; + vec3set(v, -4, -4, -4); + vec3trans(v, p->mat); + + mat3one(m); + mat3rotZ(m, randomFloat()*360); + mat3trans(m, p->mat); + mat3cpy(p->mat, m); + + vec3set(m, -4, -4, -4); + vec3trans(m, p->mat); + p->ox += m[0] - v[0], p->oy += m[1] - v[1]; + } + + char mode = 'L'; + + int begin = 1; + int relative = 0; + int cnt = 0; + double coords[3][3] = {}; + + for(const char *c = cmd; 1; ++c) { + switch(*c) { + case 'L': + case 'A': + case 'Q': + case 'C': + case 'P': + mode = *c; + relative = 0; + cnt = 0; + break; + case 'l': + case 'a': + case 'q': + case 'c': + case 'p': + mode = toupper(*c); + relative = 1; + cnt = 0; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + coords[0][0] = coords[0][1]; + coords[0][1] = coords[0][2]; + coords[0][2] = *c - '0'; + break; + case '[': + coords[0][0] = coords[0][1]; + coords[0][1] = coords[0][2]; + coords[0][2] = atof(c+1); + while(*c != ']' && c[1]) ++c; + break; + case '-': + case ' ': + case 'z': + case 'Z': + case 0: + if (relative) vec3add(coords[0], coords[cnt+1]); + + if (mode == 'P') { + painterPointTo(p, coords[0]); + begin = 1; cnt = 0; + } else + if (begin) { + painterMoveTo(p, coords[0]); + begin = 0; + } else + if (mode == 'L') { + painterLineTo(p, coords[0]); + } else + if (mode == 'A') { + if (cnt) { painterArcTo(p, coords[1], coords[0]); cnt = 0; } + else { vec3cpy(coords[1], coords[0]); ++cnt; } + } else + if (mode == 'Q') { + if (cnt) { painterQuadraticTo(p, coords[1], coords[0]); cnt = 0; } + else { vec3cpy(coords[1], coords[0]); ++cnt; } + } else + if (mode == 'C') { + if (cnt > 1) { painterCubicTo(p, coords[2], coords[1], coords[0]); cnt = 0; } + else { vec3cpy(coords[2], coords[1]); vec3cpy(coords[1], coords[0]); ++cnt; } + } + + if (*c == ' ' || *c == 0) { + painterFinish(p); + begin = 1; cnt = 0; + } else + if (*c == 'z' || *c == 'Z') { + painterClose(p); + begin = 1; cnt = 0; + } + break; + } + if (!*c) break; + } + + mat3cpy(p->mat, mat); + p->ox = mat[9]; p->oy = mat[10]; + restoreState(); +} + + +void drawStr( + Painter *p, double dx, double dy, + const char *str, char stopChar, + int *rows, int *cols ) +{ + if (randomAngle) srand(rnd); + double ox, oy; + if (p) { ox = p->ox; oy = p->oy; } + + int row = 0, col = 0, maxRow = -1, maxCol = -1; + for(const char *c = str; *c && *c != stopChar; ++c) { + if (*c == '\n') + { ++row; col = 0; continue; } + + for(int i = 0; i < lettersCount; ++i) { + int equals = 0; + for(const char *ca = c, *cb = letters[i][0]; 1; ++ca, ++cb) { + if (!*cb) { equals = 1; c += cb-letters[i][0]-1; break; } + if (!*ca || *ca == stopChar || tolower(*ca) != tolower(*cb)) break; + } + if (equals) { + if (maxCol < col) maxCol = col; + if (maxRow < row) maxRow = row; + if (p) { + p->ox = ox + col*dx; + p->oy = oy + row*dy; + drawLetter(p, letters[i][1]); + } + break; + } + } + ++col; + } + if (p) { p->ox = ox; p->oy = oy; } + if (rows) *rows = maxRow + 1; + if (cols) *cols = maxCol + 1; +} + + +void drawAllLetters(Painter *p) { + if (randomAngle) srand(rnd); + double ox = p->ox, oy = p->oy; + int lcnt = (int)ceil(sqrt(lettersCount) - 1e-6); + for(int i = 0; i < lettersCount; ++i) { + int r = i/lcnt, c = i%lcnt; + p->ox = (c - 0.5*(lcnt - 1))*boxStep + ox; + p->oy = (r - 0.5*(lcnt - 1))*boxStep + oy; + drawLetter(p, letters[i][1]); + } + p->ox = ox; p->oy = oy; +} + + +void initCurvePoints() { + for(int i = 0; i < SPLITPOINTS; ++i) { + double l = i/(SPLITPOINTS-1.0), k = 1-l; + double a = l*PI/2, s = sin(a), c = cos(a); + + pointsQua[i][0] = k*k; + pointsQua[i][1] = 2*k*l; + pointsQua[i][2] = l*l; + + pointsCub[i][0] = k*k*k; + pointsCub[i][1] = 3*k*k*l; + pointsCub[i][2] = 3*l*l*k; + pointsCub[i][3] = l*l*l; + + pointsArc[i][0] = 1-s; + pointsArc[i][1] = s+c-1; + pointsArc[i][2] = 1-c; + } +} + + + + +void render(int framesCount) { + saveState(); + + int rows, cols; + drawStr(NULL, 0, 0, textToDraw, 0, &rows, &cols); + int w = (int)ceil(cols*boxStep - 1e-5); + int h = (int)ceil(rows*boxStep - 1e-5); + Framebuffer fb = createFramebuffer(w, h); + target(fb); + + for(int i = 0; i < framesCount; ++i) { + clear(); + double step = boxStep*boxSize/8.0; + double mat[9] = {step, 0, 0, 0, 0, step, 0, -step, 0}; + mat3rotY(mat, 360.0*i/framesCount); + mat3rotX(mat, 10); + double vec[3] = {-4, -4, -4}; + vec3trans(vec, mat); + + Painter p = {}; + mat3cpy(p.mat, mat); + p.ox = vec[0] + boxStep/2; p.oy = vec[1] + boxStep/2; + drawStr(&p, boxStep, boxStep, textToDraw, 0, &rows, &cols); + + char buf[1024] = {}; + sprintf(buf, "data/output/message3d/msg%04d.png", i); + printf("save file: %s\n", buf); + viewportSave(buf); + } + + noTarget(); + framebufferDestroy(fb); + restoreState(); +} + + +void init() { + rnd = rand(); + if (renderToFiles) + render(64); +} + + +void draw() { + double pmx = mx, pmy = my; + mx = mouseX(), my = mouseY(); + + double w = windowGetWidth(); + double h = windowGetHeight(); + saveState(); + translate(w/2, h/2); + + int ml = mouseDown("left"); + int mr = mouseDown("right"); + + ax += ml ? pmx - mx : windowGetFrameTime()*360/2; + if (ml || mr) ay += my - pmy; + ax = fmod(ax, 360); + ay = fmod(ay, 360); + + double step = boxStep*boxSize/8.0; + double mat[9] = {step, 0, 0, 0, 0, step, 0, -step, 0}; + mat3rotY(mat, ax); + mat3rotX(mat, ay); + double vec[3] = {-4, -4, -4}; + vec3trans(vec, mat); + + Painter p = {}; + mat3cpy(p.mat, mat); + p.ox = vec[0]; p.oy = vec[1]; + + if (textToDraw) { + int rows, cols; + drawStr(NULL, 0, 0, textToDraw, 0, &rows, &cols); + p.ox -= (cols - 1)*boxStep/2; + p.oy -= (rows - 1)*boxStep/2; + drawStr(&p, boxStep, boxStep, textToDraw, 0, &rows, &cols); + } else { + drawAllLetters(&p); + } + + restoreState(); +} + + +int main(int argc, char **argv) { + initCurvePoints(); + + windowSetSize(768, 768); + + if (argc > 1) { + textToDraw = argv[1]; + if (argc > 2 && strcmp(argv[2], "render") == 0) renderToFiles = 1; + + int rows, cols; + drawStr(NULL, 0, 0, textToDraw, 0, &rows, &cols); + double w = boxStep*cols; + if (w > 1024) boxStep *= 1024/w; + double h = boxStep*rows; + if (h > 768) boxStep *= 768/h; + windowSetSize( (int)ceil(boxStep*cols - 1e-5), (int)ceil(boxStep*rows - 1e-5) ); + } else { + printf( + "Usage: message3d [render]\n" + " - render path is hardcoded to data/output/message3d/msgXXXX.png\n" ); + } + + windowSetVariableFrameRate(); + windowSetResizable(TRUE); + windowSetInit(&init); + windowSetDraw(&draw); + windowRun(); +} + + + diff --git a/onefile/sphere.c b/onefile/sphere.c new file mode 100644 index 0000000..38a6640 --- /dev/null +++ b/onefile/sphere.c @@ -0,0 +1,255 @@ + +#include +#include +#include + +#include + + +int printed = 0; +int started = 0; +double mx, my, ax, ay; + + +void vec3set(double *v, double x, double y, double z) + { v[0] = x, v[1] = y, v[2] = z; } +void vec3cpy(double *v, const double *vv) + { memcpy(v, vv, sizeof(*v)*3); } +void vec3add(double *v, const double *vv) + { v[0] += vv[0]; v[1] += vv[1]; v[2] += vv[2]; } +void vec3sub(double *v, const double *vv) + { v[0] -= vv[0]; v[1] -= vv[1]; v[2] -= vv[2]; } +void vec3mul(double *v, double x) + { v[0] *= x; v[1] *= x; v[2] *= x; } +double vec3dot(const double *a, const double *b) + { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; } +void vec3trans(double *v, const double *m) { + vec3set(v, v[0]*m[0] + v[1]*m[3] + v[2]*m[6], + v[0]*m[1] + v[1]*m[4] + v[2]*m[7], + v[0]*m[2] + v[1]*m[5] + v[2]*m[8] ); +} + +void mat3cpy(double *m, double *mm) + { memcpy(m, mm, sizeof(*m)*9); } +void mat3one(double *m) { + m[1] = m[2] = m[3] = m[5] = m[6] = m[7] = 0; + m[0] = m[4] = m[8] = 1; +} +void mat3rotX(double *m, double a) { + rotateVector(&m[1], &m[2], a); + rotateVector(&m[4], &m[5], a); + rotateVector(&m[7], &m[8], a); +} +void mat3rotY(double *m, double a) { + rotateVector(&m[2], &m[0], a); + rotateVector(&m[5], &m[3], a); + rotateVector(&m[8], &m[6], a); +} +void mat3rotZ(double *m, double a) { + rotateVector(&m[0], &m[1], a); + rotateVector(&m[3], &m[4], a); + rotateVector(&m[6], &m[7], a); +} + + +void lineTo3d(const double *m, double x, double y, double z) { + double v[] = {x, y, z}; + vec3trans(v, m); + lineTo(v[0], v[1]); +} +void lineTo3dv(const double *m, const double *v) + { lineTo3d(m, v[0], v[1], v[2]); } + + +void func(double *v, double x, double y) { + double angle = 1.5*PI*y; + double radius = 4*(1-y) + 2*y; + double size = (1-y)*0.25; + + double ss = sin(angle), cc = cos(angle); + + double a = 2*PI*(x-0.5)*size + PI/2, s = sin(a), c = cos(a); + vec3set(v, c*radius, s*cc*radius, s*ss*radius); + rotateVector(&v[0], &v[1], 45); +} + + +void tangent(double *v, double x, double y, double dx, double dy) { + double p[3]; + func(p, x-dx, y-dy); + func(v, x+dx, y+dy); + vec3sub(v, p); + double l = sqrt(vec3dot(v, v)); + vec3mul(v, 1/l); +} + + +void drawCubic(const double *m, const double *vv) { + for(int i = 0; i <= 16; ++i) { + double l = i/16.0, k = 1-l; + double v[3] = {}; + double vc[4][3]; + memcpy(vc, vv, sizeof(vc)); + vec3mul(vc[0], k*k*k); + vec3mul(vc[1], 3*k*k*l); + vec3mul(vc[2], 3*l*l*k); + vec3mul(vc[3], l*l*l); + vec3add(v, vc[0]); + vec3add(v, vc[1]); + vec3add(v, vc[2]); + vec3add(v, vc[3]); + lineTo3dv(m, v); + } + strokePath(); +} + + +void makeCubicBase(double *vv, double *p0, double *t0, double *p1, double *t1) { + double d[3], tt0[3], tt1[3]; + vec3cpy(d, p1); + vec3sub(d, p0); + double ld = sqrt(vec3dot(d, d)); + + double l0 = sqrt(vec3dot(t0, t0)); + double l1 = sqrt(vec3dot(t1, t1)); + double k = ld/3; + vec3cpy(tt0, t0); vec3mul(tt0, k/l0); + vec3cpy(tt1, t1); vec3mul(tt1, k/l1); + + double pp0[3], pp1[3]; + vec3cpy(pp0, p0); vec3add(pp0, tt0); + vec3cpy(pp1, p1); vec3sub(pp1, tt1); + + vec3cpy(&vv[0], p0); + vec3cpy(&vv[3], pp0); + vec3cpy(&vv[6], pp1); + vec3cpy(&vv[9], p1); + + if (!printed) { + if (started) + printf(" \""); + else + printf("\" [%.2f][%.2f][%.2f]", vv[0]+4, vv[1]+4, vv[2]+4); + + for(int i = 1; i < 4; ++i) { + printf("-[%.2f][%.2f][%.2f]", vv[3*i+0]+4, vv[3*i+1]+4, vv[3*i+2]+4); + } + printf("\"\n"); + } + started = 1; +} + + + +void makeCubic( + double *vv, + double x0, double y0, double dx0, double dy0, + double x1, double y1, double dx1, double dy1 ) +{ + double p0[3], t0[3], p1[3], t1[3]; + func(p0, x0, y0); + func(p1, x1, y1); + tangent(t0, x0, y0, dx0, dy0); + tangent(t1, x1, y1, dx1, dy1); + makeCubicBase(vv, p0, t0, p1, t1); +} + + +void makeCubicBase2(const double *m, double *vv, double *p0, double *t0, double *p1, double *t1) { + makeCubicBase(vv, p0, t0, p1, t1); + drawCubic(m, vv); +} + +void makeCubic2( + const double *m, double *vv, + double x0, double y0, double dx0, double dy0, + double x1, double y1, double dx1, double dy1 ) +{ + makeCubic(vv, x0, y0, dx0, dy0, x1, y1, dx1, dy1); + drawCubic(m, vv); +} + + + +void init() { } + + +void draw() { + double w = windowGetWidth(); + double h = windowGetHeight(); + + saveState(); + translate(w/2, h/2); + + int ml = mouseDown("left"); + int mr = mouseDown("right"); + + double pmx = mx, pmy = my; + mx = mouseX(), my = mouseY(); + if (ml || mr) { ax += pmx - mx; ay += my - pmy; } + ax = fmod(ax, 360); + ay = fmod(ay, 360); + + double step = 128/8.0; + double mat[9] = {step, 0, 0, 0, 0, step, 0, -step, 0}; + mat3rotY(mat, ax); + mat3rotX(mat, ay); + + double axislen = 1; + strokeWidth(2); + stroke(COLOR_RED); line(0, 0, mat[0]*axislen, mat[1]*axislen); + stroke(COLOR_BLACK); line(0, 0, mat[3]*axislen, mat[4]*axislen); + stroke(COLOR_BLUE); line(0, 0, mat[6]*axislen, mat[7]*axislen); + strokeWidth(1); + stroke(COLOR_BLACK); + + noFill(); + for(int i = 0; i <= 16; ++i) { + for(int j = 0; j <= 16; ++j) { + double v[3]; + func(v, i/16.0, j/16.0); + vec3trans(v, mat); + point(v[0], v[1]); + } + } + + double curve[12]; + double p0[3], t0[3], p1[3], t1[3]; + + started = 0; + vec3set(p0, 4, 0, -4); vec3set(t0, 0, 1, 0); + func(p1, 0, 0); tangent(t1, 0, 0, 0, 0.001); + makeCubicBase2(mat, curve, p0, t0, p1, t1); + for(int i = 0; i < 6; ++i) + makeCubic2(mat, curve, 0, i/6.0, 0, 0.001, 0, (i+1)/6.0, 0, 0.001 ); + + for(int i = 0; i < 6; ++i) + makeCubic2(mat, curve, 1, 1-i/6.0, 0, -0.001, 1, 1-(i+1)/6.0, 0, -0.001 ); + func(p0, 1, 0); tangent(t0, 1, 0, 0, -0.001); + vec3set(p1, 0, -4, -4); vec3set(t1, 1, 0, 0); + makeCubicBase2(mat, curve, p0, t0, p1, t1); + + started = 0; + makeCubic2(mat, curve, 0, 1/3.0, 0.001, 0, 1, 1/3.0, 0.001, 0); + started = 0; + makeCubic2(mat, curve, 0, 2/3.0, 0.001, 0, 1, 2/3.0, 0.001, 0); + + lineTo3d(mat, 4, 0, -4); + lineTo3d(mat, 4, -4, -4); + lineTo3d(mat, 0, -4, -4); + lineTo3d(mat, 0, 0, -4); + closePath(); + + printed = 1; + + restoreState(); +} + + +int main() { + windowSetVariableFrameRate(); + windowSetResizable(TRUE); + windowSetInit(&init); + windowSetDraw(&draw); + windowRun(); +} diff --git a/onefile/splines.c b/onefile/splines.c new file mode 100644 index 0000000..2de3e06 --- /dev/null +++ b/onefile/splines.c @@ -0,0 +1,127 @@ + +#include +#include + + +#define COUNT 10 +#define TL 20 +#define RADIUS 5 +#define PRECISION 1e-5 + + +typedef struct { double x, y, tx, ty; } Point; +typedef struct { double A, B, C, D; } Spline; + + +Point points[COUNT]; +Point *curPoint; +double curPointOffset[2]; +int curTangent; + + +void splineInit(Spline *s, double a, double b, double ta, double tb) { + double d = b - a; + if (!(fabs(d) > 1e-6)) + { s->A = a; s->B = s->C = s->D = 0; return; } + + double B = ta; + double C = ((ta*ta - tb*tb)/d - d)*0.5; + double A = a - C; + double x = ta*tb + C*(d + C); + double y = ta*d + C*(ta - tb); + double D = atan2(fabs(y), x); + //if (D < 0) D += PI; + if (d < 0) D = -D; + + s->A = A; + s->B = B; + s->C = C; + s->D = D; +} + +double splineValue(const Spline *s, double l) { + l *= s->D; + return s->A + s->B*sin(l) + s->C*cos(l); +} + +double splineTangent(const Spline *s, double l) { + l *= s->D; + return s->B*cos(l) + s->C*sin(l); +} + +void drawSplineSegment(const Point *a, const Point *b) { + Spline sx, sy; + splineInit(&sx, a->x, b->x, a->tx, b->tx); + splineInit(&sy, a->y, b->y, a->ty, b->ty); + int count = 10; + for(int i = 1; i < count; ++i) { + double l = i/(double)count; + double x = splineValue(&sx, l); + double y = splineValue(&sy, l); + lineTo(x, y); + } + lineTo(b->x, b->y); +} + +void drawSpline(const Point *p, int count) { + if (count < 2) return; + moveTo(p->x, p->y); + for(int i = 1; i < count; ++i) + drawSplineSegment(p+i-1, p+i); + strokePath(); +} + + + +void init() { + for(int i = 0; i < COUNT; ++i) { + points[i].x = (i/(COUNT - 1.0) - 0.5)*256; + points[i].tx = 100.0; + } +} + + +void draw() { + double w = windowGetWidth(); + double h = windowGetHeight(); + + saveState(); + translate(w/2, h/2); + + int m = mouseWentDown("left"); + double mx = mouseTransformedX(); + double my = mouseTransformedY(); + if (!mouseDown("left")) + { m = FALSE; curPoint = 0; } + if (curPoint) { + curPoint->x = mx + curPointOffset[0]; + curPoint->y = my + curPointOffset[1]; + } + + strokeWidth(2); + stroke(COLOR_BLUE); + fill(COLOR_WHITE); + drawSpline(points, COUNT); + for(int i = 0; i < COUNT; ++i) { + Point *p = points + i; + circle(p->x, p->y, RADIUS); + double dx = p->x-mx, dy = p->y-my; + if (m && dx*dx + dy*dy <= RADIUS*RADIUS) { + curPoint = p; + curPointOffset[0] = dx; + curPointOffset[1] = dy; + } + } + + restoreState(); +} + + +int main() { + windowSetVariableFrameRate(); + windowSetResizable(TRUE); + windowSetInit(&init); + windowSetDraw(&draw); + windowRun(); + return 0; +}