Introduction

A hypercube/tesseract is the 4 dimensional equivalent of a normal cube. It's made by taking a cube net, extending it to the 3rd dimension, then – using the 4th dimension – folding it into a hypercube. It's basically a cube, where each side is a cube.

To create a hypercube, you need 16 4d vectors (a vector with an x, a y, a z and a w component). These vectors are the following:

With all this information, you technically have a hypercube in code. To rotate this, you need 6 different matrices for each rotational plane, one for the YZ, XZ, XY, XW, YW and ZW planes. After you have every matrix, you need to multiply the cube's vertices with them.

The following images show the structure of each matrix:

For the rotation on the YZ plane:

For the rotation on the XZ plane:

For the rotation on the XY plane:

For the rotation on the XW plane:

For the rotation on the YW plane:

For the rotation on the ZW plane:

The rotations get applied in this order.

After all this, you have a rotated hypercube. Now you need to draw it. You should use an orthogonal projection combined with a perspective projection to send (x, y, z, w) to (2x/(2+z), 2y/(2+z)).

Input

Your input is 6 integers between 0 (inclusively) and 360 (exclusively). These represent the rotations in degrees on the different rotational planes of the hypercube.

Output

Your output should be a single image containing the hypercube. The display can be a rasterized image, a vector image or an ASCII art. The output image should be at least 100 * 100 pixels, and the cube needs to take up at least 50% of the screen. Any default image output format is allowed.

\$\begingroup\$Why did you nuke the other post?\$\endgroup\$
– RɪᴋᴇʀJun 17 '16 at 13:15

\$\begingroup\$@EᴀsᴛᴇʀʟʏIʀᴋ I posted it in the chat for a last review\$\endgroup\$
– BálintJun 17 '16 at 13:17

7

\$\begingroup\$As I've pointed out on two separate occasions in the sandbox, the description of projection for display is incomplete because it assumes that the object to be projected is 3-dimensional whereas it is in fact, obviously, 4-dimensional.\$\endgroup\$
– Peter TaylorJun 17 '16 at 16:28

2

\$\begingroup\$@luserdroog I think the 'U' must be 'N'.\$\endgroup\$
– beakerJun 20 '16 at 2:34

2

\$\begingroup\$@Bálint Thanks for the challenge, I enjoyed it. Hopefully we'll get more answers and different approaches. :D\$\endgroup\$
– beakerJun 23 '16 at 17:20

The rotation matrices still consume a lot of bytes, but the Eulerian cycle worked out quite well, reducing the number of vertices visited from 96 120 down to 33.

Vertices are generated by taking the 4-bit binary representation of [0:15] and considering the msb to be the x-coordinate and the lsb the w-coordinate.

Edit: Pre-multiplying all of the rotation matrices was a nightmare, which is why I didn't use it initially, but pre-multiplying them in pairs saved 41 bytes. Now to look for the optimum combination. :) Multiplying the matrices by threes was worse than no pre-multiplication at all, so I'll be happy with the pair-wise approach.

Postscript 1075732683640631601590545542526514478 470

Edit:-343 Applied binary-encoding generation of vectors and Eulerian circuit stolen borrowed from other answers. And applied binary-token-strings from the G library.Edit:-49 Redefined sincos and neg to shorter names.Edit:-43 Defined short names for sequences 0 00 11 0.Edit:-9al (ie. aload) is shorter than (")@. Factored 3 calls to idi (ie. idiv) at the cost of a do-nothing 1 idiv.Edit:-30 Applied implicit definition block from G.Edit:-10 A few more triply-used sequences.Edit:-45 Remove variables ijklmn for the angles and always define the current angle as t and functions of angles use the value of the (global) t variable. Defer execution of the code-description of the rotation matrix until its t value is ready.Edit:-3 Remove <16>$ ie. closepath. And a space.Edit:-16 Factor-out array brackets from unit vectors in the rotation matrices (JKL and M). Re-apply dropped mo for mod and su for sub.Edit:-12 In-line the project-and-draw function and remove (now empty) enclosing dictionary.Edit:-36 Encoded the circuit (ie. the faces) in a string.Edit:-8 Remove definition of vertices array V. Instead, leave on stack and dup working copies as needed (once, at first, and again at the end of the loop). Also, translated a few operators from binary-token-strings back to abbreviated names where the BTS gave no savings, so (I)$ is now fora (ie. forall). if du could be (T8)$, but if du is clearly a better choice (it's golf, not obfuscation per se). Also, perform the scalebeforetranslate, so translated coordinates can be 3 and 4 instead of 300 and 400.

The 34 and 100 in the first line of the second block are parameters representing center-x, center-y and scale, respectively, of the drawing on the page (center coordinates are scaled by scale). (300,400) is roughly the center of US letter-sized paper (612,792) in PS units.

If you can roughly follow postscript, the important bizarre things are the implicit procedure block and the encoded operator strings. As shown by comments in the workfile, below, each line of the first block is implicitly named by A, B, C, etc. So, eg. F E D would produce 1 0 0 1 0 0. For the encoded operator strings, anything that is an argument to $# or @ is a sequence of operator calls, using the bytes to select operators from the system name table, PLRM 3ed Appendix F. These features and more are available for PostScript with the G library (now includes the mat.ps functions too).

\$\begingroup\$@TùxCräftîñg There's not actually that much math in this question as long as you can do matrix multiplication easily. And I've wanted to write this program ever since reading A. K. Dewdney's The Armchair Universe.\$\endgroup\$
– luser droogJun 20 '16 at 18:26

\$\begingroup\$Added new functions to the G library. Can't use here, but it allows this 307 byte version.\$\endgroup\$
– luser droogJun 27 '16 at 21:45

I couldn't figure out a simple formula for constructing the rotation matrices nor the "faces" which to draw, so that cost a lot of bytes to hard-code. I borrowed the Eulerian cycle from @beaker. Also, Unity built-ins are extremely verbose.

\$\begingroup\$This is the first time I've seen a C# + Unity answer on here. +1\$\endgroup\$
– DanTheManJun 21 '16 at 22:18

\$\begingroup\$I think every 0.5f can be reduced to .5f and 0.01f to .01f. I also think that the integer arrays can be separated with a comma instead of saying int[] multiple times.\$\endgroup\$
– YytsiJul 29 '16 at 8:45

\$\begingroup\$@Blue Oh, you're right! Haven't used C# for a while so wasn't sure of the last tip.\$\endgroup\$
– YytsiJul 29 '16 at 16:41

\$\begingroup\$Clever, it took me a while to figure out what you were doing with the matrix transforms. :D Also, I can't get your code snippet to work... it's giving me an unhelpful "Script error." in line 0.\$\endgroup\$
– beakerJun 23 '16 at 17:13

\$\begingroup\$@beaker What browser are you using? I've tested it on the latest Firefox.\$\endgroup\$
– DendrobiumJun 23 '16 at 17:25

Mathematica, 453 415 bytes*

Shortened by using the Eulerian tour and cleaning it all up into a single statement without defining functions in variables. This makes the code slower for some reason. I'm guessing Mathematica reevaluates the functions multiple times now that they are not stored in a variable.

Your Answer

If this is an answer to a challenge…

…Be sure to follow the challenge specification. However, please refrain from exploiting obvious loopholes. Answers abusing any of the standard loopholes are considered invalid. If you think a specification is unclear or underspecified, comment on the question instead.

…Try to optimize your score. For instance, answers to code-golf challenges should attempt to be as short as possible. You can always include a readable version of the code in addition to the competitive one.
Explanations of your answer make it more interesting to read and are very much encouraged.

…Include a short header which indicates the language(s) of your code and its score, as defined by the challenge.

More generally…

…Please make sure to answer the question and provide sufficient detail.

…Avoid asking for help, clarification or responding to other answers (use comments instead).

Code Golf Stack Exchange is a site for recreational programming competitions, not general programming questions. Challenges must have an objective scoring criterion, and it is highly recommended to first post proposed challenges in the Sandbox.