I'm creating a regular tetrahedron using raw css. I understand the math of what should be happening. The main problem is, that the dihedral angle provided by wikipedia or my own calculations is not working. Here is an example:
:root {
/* 360 / 3 */
--d4-side-angle: 120deg;
/* asin( 2*sqrt(2) / 3) = 70.53 */
/* why 19.5 and not 70.53??? */
--d4-plane-angle: 19.5deg;
/* inradius of the triangle */
--d4-base-radius: 2rem;
/* triangle side = 6*r / sqrt(3) */
--d4-triangle-width: calc(var(--d4-base-radius) * 3.4641);
/* height = width * sin(60) */
--d4-triangle-height: calc(var(--d4-triangle-width) * 0.866);
--d4-double-triangle-height: calc(var(--d4-triangle-height) * 2.0);
}
.test-main {
width: 100%;
height: 100%;
display: grid;
place-content: center;
}
#d4-die {
transform-style: preserve-3d;
width: 5rem;
height: 5rem;
animation: spin 20s infinite ease-in-out;
}
#d4-die figure {
overflow: hidden;
transform-style: preserve-3d;
position: absolute;
width: var(--d4-triangle-width);
/* double the height, so rotations around X axis are based at the bottom of the triangle */
height: var(--d4-double-triangle-height);
clip-path: polygon(0% 50%, 50% 0%, 100% 50%);
margin: 0;
top: 0;
left: 0;
transition: all 5s;
}
#d4-die figure p {
text-align: center;
margin-top: 35%;
background-color: red;
}
#d4-die figure:nth-child(1) {
background-color: gold;
transform: translateZ( var(--d4-base-radius) ) rotateX( var(--d4-plane-angle) );
}
#d4-die figure:nth-child(2) {
background-color: blueviolet;
transform: rotateY( var(--d4-side-angle) ) translateZ( var(--d4-base-radius) ) rotateX( var(--d4-plane-angle) );
}
#d4-die figure:nth-child(3) {
background-color: green;
transform: rotateY( calc(var(--d4-side-angle) + var(--d4-side-angle)) ) translateZ( var(--d4-base-radius) ) rotateX( var(--d4-plane-angle) ) ;
}
#d4-die figure:nth-child(4) {
background-color: blue;
transform: translateZ(var(--d4-base-radius)) rotateX( 90deg );
}
@keyframes spin {
0% { transform: translateZ(-100px) rotateX( 0deg) rotateY( 0deg); }
100% { transform: translateZ(-100px) rotateX(360deg) rotateY(360deg); }
}
<body class=test-main>
<div id="d4-die">
<figure><p>1</p></figure>
<figure><p>2</p></figure>
<figure><p>3</p></figure>
<figure><p>4</p></figure>
</div>
</body>
There're 2 things I don't understand:
- Why dihedral angle of 19.5 degrees is working and theoretically right angle of 70.53 degrees isn't?
- According to the documentation and answers to this question, transforms are performed in the right-to-left order. But, if I would write code in such manner(first - rotate triangle around Y axis, then translate it along Z axis, so it moves in the right direction and finally rotate around X axis), then this happens.
:root {
--d4-side-angle: 120deg;
--d4-plane-angle: 19.5deg;
--d4-base-radius: 2rem;
--d4-triangle-width: calc(var(--d4-base-radius) * 3.4641);
--d4-triangle-height: calc(var(--d4-triangle-width) * 0.866);
--d4-double-triangle-height: calc(var(--d4-triangle-height) * 2.0);
}
.test-main {
width: 100%;
height: 100%;
display: grid;
place-content: center;
}
#d4-die {
transform-style: preserve-3d;
width: 5rem;
height: 5rem;
animation: spin 20s infinite ease-in-out;
}
#d4-die figure {
overflow: hidden;
transform-style: preserve-3d;
position: absolute;
width: var(--d4-triangle-width);
height: var(--d4-double-triangle-height);
clip-path: polygon(0% 50%, 50% 0%, 100% 50%);
margin: 0;
top: 0;
left: 0;
transition: all 5s;
}
#d4-die figure p {
text-align: center;
margin-top: 35%;
background-color: red;
}
#d4-die figure:nth-child(1) {
background-color: gold;
transform: rotateX( var(--d4-plane-angle) ) translateZ( var(--d4-base-radius) );
}
#d4-die figure:nth-child(2) {
background-color: blueviolet;
transform: rotateX( var(--d4-plane-angle) ) translateZ( var(--d4-base-radius) ) rotateY( var(--d4-side-angle) );
}
#d4-die figure:nth-child(3) {
background-color: green;
transform: rotateX( var(--d4-plane-angle) ) translateZ( var(--d4-base-radius) ) rotateY( calc(var(--d4-side-angle) + var(--d4-side-angle)) );
}
#d4-die figure:nth-child(4) {
background-color: blue;
transform: rotateX( 90deg ) translateZ(var(--d4-base-radius));
}
@keyframes spin {
0% { transform: translateZ(-100px) rotateX( 0deg) rotateY( 0deg); }
100% { transform: translateZ(-100px) rotateX(360deg) rotateY(360deg); }
}
<body class=test-main>
<div id="d4-die">
<figure><p>1</p></figure>
<figure><p>2</p></figure>
<figure><p>3</p></figure>
<figure><p>4</p></figure>
</div>
</body>
All of the triangles are in the same place, which means, that they were translated before rotation around Y axis, as this is the only difference in transform of the first 3 triangles.
I got the angle of 19.5 degrees using binary search and have no idea what it means. Also, I've tried more complex shapes and got similar results. ~35deg for octahedron(should be 109.47), ~153deg for dodecahedron(should be 116.57)