#include <ctype.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <helianthus.h>
#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 <message> [render]\n"
" - render path is hardcoded to data/output/message3d/msgXXXX.png\n" );
}
windowSetVariableFrameRate();
windowSetResizable(TRUE);
windowSetInit(&init);
windowSetDraw(&draw);
windowRun();
}