/* this version extends the previous by drawing a whole series of lines (a 3 dimensional shape) insteadst one line. The definition that begins with const double path[][4] = { { -100, -100, -100, 1 }, defines the shape, every group of four numbers is the coordinates of one corner of the shape. But there is one thing you need to be careful of. The program starts at the first point, then draws lines to each of the remaining points in turn without ever lifting up the pen. The only way to draw a cube involves drawing some of its edges twice. */ #include "library.h" const int winsize = 500; const int halfwinsize = winsize / 2; double matvecmul(const double m[4][4], const double v[4], const int i, const int p) { if (p == 4) return 0.0; return m[i][p] * v[p] + matvecmul(m, v, i, p + 1); } double matvecmul(const double m[4][4], const double v[4], const int i) { return matvecmul(m, v, i, 0); } double matmatmul(const double m1[4][4], const double m2[4][4], const int i, const int j, const int p) { if (p == 4) return 0.0; return m1[i][p] * m2[p][j] + matmatmul(m1, m2, i, j, p + 1); } double matmatmul(const double m1[4][4], const double m2[4][4], const int i, const int j) { return matmatmul(m1, m2, i, j, 0); } const double pi = acos(-1.0); double degrees(const double x) { return x * pi / 180.0; } void move_to(const double p[4]) { move_to(halfwinsize + p[0], halfwinsize - p[1]); } void draw_to(const double p[4]) { draw_to(halfwinsize + p[0], halfwinsize - p[1]); } void draw(const double m[4][4], const double p[][4], const int i, const int len) { if (i == len) return; const double newvec[4] = { matvecmul(m, p[i], 0), matvecmul(m, p[i], 1), matvecmul(m, p[i], 2), matvecmul(m, p[i], 3) }; if (i == 0) move_to(newvec); else draw_to(newvec); draw(m, p, i + 1, len); } void animate(const double m[4][4], const double mstep[4][4], const double p[][4], const int len, const int nsteps) { if (nsteps == 0) return; const int c = get_pen_color(); draw(m, p, 0, len); wait(0.01); set_pen_color(color::white); draw(m, p, 0, len); set_pen_color(c); const double newm[4][4] = { { matmatmul(m, mstep, 0, 0), matmatmul(m, mstep, 0, 1), matmatmul(m, mstep, 0, 2), matmatmul(m, mstep, 0, 3) }, { matmatmul(m, mstep, 1, 0), matmatmul(m, mstep, 1, 1), matmatmul(m, mstep, 1, 2), matmatmul(m, mstep, 1, 3) }, { matmatmul(m, mstep, 2, 0), matmatmul(m, mstep, 2, 1), matmatmul(m, mstep, 2, 2), matmatmul(m, mstep, 2, 3) }, { matmatmul(m, mstep, 3, 0), matmatmul(m, mstep, 3, 1), matmatmul(m, mstep, 3, 2), matmatmul(m, mstep, 3, 3) } }; animate(newm, mstep, p, len, nsteps - 1); } void main() { make_window(winsize, winsize); set_pen_width(3); const double rotz[4][4] = { { cos(degrees(1)), sin(degrees(1)), 0, 0 }, { -sin(degrees(1)), cos(degrees(1)), 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } }; const double roty[4][4] = { { cos(degrees(1)), 0, sin(degrees(1)), 0 }, { 0, 1, 0, 0 }, { -sin(degrees(1)), 0, cos(degrees(1)), 0 }, { 0, 0, 0, 1 } }; const double rotx[4][4] = { { 1, 0, 0, 0 }, { 0, cos(degrees(1)), sin(degrees(1)), 0 }, { 0, -sin(degrees(1)), cos(degrees(1)), 0 }, { 0, 0, 0, 1 } }; const double grow[4][4] = { { 1.01, 0, 0, 0 }, { 0, 1.01, 0, 0 }, { 0, 0, 1.01, 0 }, { 0, 0, 0, 1 } }; const double shrink[4][4] = { { 0.98, 0, 0, 0 }, { 0, 0.98, 0, 0 }, { 0, 0, 0.98, 0 }, { 0, 0, 0, 1 } }; const double movx[4][4] = { { 1, 0, 0, 0.5 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } }; const double movxy[4][4] = { { 1, 0, 0, 2 }, { 0, 1, 0, -2 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } }; const double comb[4][4] = { { matmatmul(rotz, roty, 0, 0), matmatmul(rotz, roty, 0, 1), matmatmul(rotz, roty, 0, 2), matmatmul(rotz, roty, 0, 3) }, { matmatmul(rotz, roty, 1, 0), matmatmul(rotz, roty, 1, 1), matmatmul(rotz, roty, 1, 2), matmatmul(rotz, roty, 1, 3) }, { matmatmul(rotz, roty, 2, 0), matmatmul(rotz, roty, 2, 1), matmatmul(rotz, roty, 2, 2), matmatmul(rotz, roty, 2, 3) }, { matmatmul(rotz, roty, 3, 0), matmatmul(rotz, roty, 3, 1), matmatmul(rotz, roty, 3, 2), matmatmul(rotz, roty, 3, 3) } }; const double ident[4][4] = { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } }; const double path[][4] = { { -100, -100, -100, 1 }, { -100, 100, -100, 1 }, { 100, 100, -100, 1 }, { 100, -100, -100, 1 }, { -100, -100, -100, 1 }, { -100, -100, 100, 1 }, { 100, -100, 100, 1 }, { 100, -100, -100, 1 }, { 100, -100, 100, 1 }, { 100, 100, 100, 1 }, { 100, 100, -100, 1 }, { -100, 100, -100, 1 }, { -100, 100, 100, 1 }, { -100, -100, 100, 1 }, { -100, 100, 100, 1 }, { 100, 100, 100, 1 } }; const double line[4] = { 0, 150, 150, 1 }; set_pen_color(color::red); animate(ident, comb, path, sizeof(path) / sizeof(path[0]), 360); }