Using Geometry Nodes, you can instance a 1 m cube (a piece) onto a subdivided 2 m cube, then store the pieces positions for later. The "Scale" node can be unmuted by people who suffer from OCD, but the logic works regardless.
Use a modifier to bevel the cubes, I chose 3 segments and Amount = $0.05$
🦉 Draw the rest of the owl:
- Select (before B3.5 use a switch) faces by position.
- Color selected faces based on normal.
- Normal can be converted to luminance and all axis-aligned normals will produce a different luminance.
- The luminance is then converted to correct color using a color ramp.
- Move all pieces to origin [only if the node was unmuted, otherwise something different happens, DON'T WORRY].
Below that I converted the geometry to 26 instances. Unfortunately there's no vanilla node to convert to multiple instances, so I chain 26 custom groups:
It simply separates the first island (inverted selection), converts it to an instance, joins with geometry already converted to instances, and then joins with still unconverted mesh, so that it can be chained using one link per node. Both "Join" nodes are required in order to not nest the instances.
Below that:
- Spawn a grid which represents the centers of Rubik's Cubes.
- Capture those centers used later as pivot points in rotations.
- On each such center spawn and realize 26 points, which will spawn pieces.
- Offset the pieces inside the dynamically assembled collection back to the correct position.
- Thanks to offsetting before and after converting to instances, they are now aware of their position, rather than considering the Rubik Cube's center to be their position.
- Instance the pieces.
- If you don't want your cubes to stand boringly in military-like fashion, you need to move them after rotations, because XYZ coordinates are used to rotate entire sides in unison.
Finally, rotation is hidden in this custom group:
- ${π\over2} \text{ rad} = 90° = 1.571 \text{ rad}$
- It rotates the instances around each axis. It's important for this to be 3 separate nodes, because the rotation depends on the position, and after each cube twist, positions change.
- In reality you don't twist the middle pieces of a Rubik's cube, but you can imagine holding the cube in a vice and rotating the middle, so it's valid and spares the step to rotate the entire cube.
- To maximize randomness, a different seed is used in each use of this custom group, and the
step
attribute is used to increment this seed automatically.
- Notice the warning: rounding to integers is an unstable, bifurcating process: Something at $x = 3.0$ will floor to $3$, but something that has been very slightly (perhaps due to messy nature of rotations and float number precision) moved to $x = 2.99999999$ will floor to $2$ and therefore possibly rotate by a different angle! This is why I set such dimensions of the spawning grid to have all pieces on whole number coordinates, and use "round" operation - which would fail if you had pieces on $.5$ coordinates…
If you use "Scene Time" node by passing the frame/seconds to 3 map ranges:
- from
(step-1)*100
to (step-1)*100 + 30
- from
(step-1)*100 + 30
to (step-1)*100 + 60
- from
(step-1)*100 + 60
to (step-1)*100 + 90
and use the standard 0..1 output to multiply calculated rotations, you get an animation:
which is also a proof the technique produces valid Rubik's Cube layouts.