How to create this four-dimensional cube animation?
My approach. The main distinguishing feature being the ridiculously clumsy and inefficient way of calculating the faces...
v = Tuples[{-1, 1}, 4];
e = Select[Subsets[Range[Length[v]], {2}], Count[Subtract @@ v[[#]], 0] == 3 &];
f = Select[Union[Flatten[#]] & /@ Subsets[e, {4}], Length@# == 4 &];
f = f /. {a_, b_, c_, d_} :> {b, a, c, d};
rotv[t_] = (RotationMatrix[t, {{0, 0, 1, 0}, {0, 1, 0, 0}} ].
RotationMatrix[2 t, {{1, 0, 0, 0}, {0, 0, 0, 1}} ].#) & /@ v;
proj[t_] := Most[#]/(3 - Last[#]) & /@ rotv[t];
Animate[Graphics3D[GraphicsComplex[proj[t],
{Cyan, Specularity[0.75, 10], Sphere[Range[16], 0.05],
Tube[e, 0.03], Opacity[0.3], Polygon@f}],
Boxed -> False, Background -> Black, PlotRange -> 1], {t, 0, Pi/2}]
Here is my (slightly less) modest attempt to depict the Clifford rotation (a.k.a. double rotation) of a hypercube, using perspective projection (i.e., a Schlegel diagram) to view the rotation (see this for a discussion on perspective projection):
tesseract = GraphicsComplex[
{{-1, -1, -1, -1}, {-1, -1, -1, 1}, {-1, -1, 1, -1}, {-1, -1, 1, 1}, {-1, 1, -1, -1},
{-1, 1, -1, 1}, {-1, 1, 1, -1}, {-1, 1, 1, 1}, {1, -1, -1, -1}, {1, -1, -1, 1},
{1, -1, 1, -1}, {1, -1, 1, 1}, {1, 1, -1, -1}, {1, 1, -1, 1}, {1, 1, 1, -1},
{1, 1, 1, 1}}, {{JoinForm["Round"], (* edges *)
Tube[{{1, 2}, {1, 3}, {1, 5}, {1, 9}, {2, 4}, {2, 6}, {2, 10}, {3, 4}, {3, 7},
{3, 11}, {4, 8}, {4, 12}, {5, 6}, {5, 7}, {5, 13}, {6, 8}, {6, 14}, {7, 8},
{7, 15}, {8, 16}, {9, 10}, {9, 11}, {9, 13}, {10, 12}, {10, 14}, {11, 12},
{11, 15}, {12, 16}, {13, 14}, {13, 15}, {14, 16}, {15, 16}}, 1/8]},
{Directive[Opacity[1/2], EdgeForm[]], (* faces *)
Polygon[{{1, 2, 4, 3}, {1, 2, 6, 5}, {1, 2, 10, 9}, {1, 3, 7, 5}, {1, 3, 11, 9},
{1, 5, 13, 9}, {2, 4, 8, 6}, {2, 4, 12, 10}, {2, 6, 14, 10}, {3, 4, 8, 7},
{3, 4, 12, 11}, {3, 7, 15, 11}, {4, 8, 16, 12}, {5, 6, 8, 7}, {5, 6, 14, 13},
{5, 7, 15, 13}, {6, 8, 16, 14}, {7, 8, 16, 15}, {9, 10, 12, 11},
{9, 10, 14, 13}, {9, 11, 15, 13}, {10, 12, 16, 14}, {11, 12, 16, 15},
{13, 14, 16, 15}}]}}];
With[{(* focal length *) f = 2,
(* distance to focal point *) d = 2,
(* frames *) n = 45,
(* for extracting axes *) ax = IdentityMatrix[4]},
Table[Graphics3D[{ColorData["Legacy", "Cobalt"], MapAt[Map[
Composition[
(* perspective transformation along axis {0, 1, 0, 0} *)
Function[pt, f Delete[pt, 2]/(d - Extract[pt, 2])],
(* Clifford rotation along orthogonal hyperplanes *)
RotationTransform[-θ, ax[[{3, 4}]]],
RotationTransform[θ, ax[[{1, 2}]]]], #] &, tesseract, {1}]},
Background -> Black, Boxed -> False, Lighting -> "Neutral",
PlotRange -> {{-3, 3}, {-5, 5}, {-5, 5}}, PlotRangePadding -> None,
ViewPoint -> {1.4, -2., 1.}], {θ, 0, 2 π, 2 π/(n - 1)}]]
Of note is that in assembling the transformation corresponding to a Clifford rotation, the order of application does not matter (i.e. the component rotations of a Clifford rotation are commutative); thus, both Composition[RotationTransform[-θ, ax[[{3, 4}]]], RotationTransform[θ, ax[[{1, 2}]]]]
and Composition[RotationTransform[θ, ax[[{1, 2}]]], RotationTransform[-θ, ax[[{3, 4}]]]]
will give the same result.
This is my approach, has nothing to do with projection, and it is a little complicated.
I get all coordinates and faces first to determine both start and end state. Then, change the start state smoothly to the end.
coor = Flatten[PolyhedronData["Cuboid", "VertexCoordinates"], 1];
face = Flatten[PolyhedronData["Cuboid", "FaceIndices"], 1];
edge = Flatten[PolyhedronData["Cuboid", "EdgeIndices"], 1];
coor1 = Join[coor, 2 coor];
coor2 = Join[2 coor[[1 ;; 4]], coor[[1 ;; 4]], 2 coor[[5 ;; 8]], coor[[5 ;; 8]]];
finalCoor[t_] := coor1 + (coor2 - coor1) t;(*t from 0 to 1*)
face1 = Join[face, face + 8];
finalface = Join[Join @@@ Thread[{edge, Reverse /@ (8 + edge)}], face1];
fourDimensions[scale_] := Table[Graphics3D[{Opacity[0.5],
Rotate[GraphicsComplex[finalCoor[t], Polygon[finalface]],
t π/2, {1, 0, 0}]}, Boxed -> False,
PlotRange -> {{-scale, scale}, {-scale, scale}, {-scale, scale}},
ViewPoint -> {-1.75, 0.75, 0.5}], {t, 0, 0.95, 0.05}];
Export["F:\\fourDimensionalCube.gif", fourDimensions[1.5]]
Here is the result: