0

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:

  1. Why dihedral angle of 19.5 degrees is working and theoretically right angle of 70.53 degrees isn't?
  2. 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)

Unrealf1
  • 26
  • 7
  • `90 - 19.5 = 70.5` – Temani Afif May 04 '21 at 23:05
  • 1
    ^ you rotate by 19.5deg to get the 70.5deg. The angle you need to have is not necessarely the one you need to use – Temani Afif May 04 '21 at 23:06
  • use 0deg and see the initial state of your element without rotation. Rotation will rotate your element from an initial state. The angle your are calculating is the angle of the shape not the rotation you need to perform in order to get the angle of the shape. – Temani Afif May 04 '21 at 23:10
  • you're right, thanks! Do you have any ideas about the order of the operations? – Unrealf1 May 04 '21 at 23:12
  • you can read this: https://stackoverflow.com/a/53672795/8620333 I am explaining in detail there (also this one: https://stackoverflow.com/a/51080643/8620333) – Temani Afif May 04 '21 at 23:14
  • @TemaniAfif thanks, I've read your answers, but still don't fully understand the situation. I think, I need to understand one thing: does the coordinate system transform after _each_ transform-function or are all of the transformations done in respect to the same coordinate system? – Unrealf1 May 04 '21 at 23:44
  • each transformation will create a new coordianate system for the next one so you will have as many transformation as coordiante system. You can see muttiple transformation like one transformation applied to nested elements. In my answer I said *Transformations are cumulative. That is, elements establish their local coordinate system within the coordinate system of their parent.* --> read this part of the Spec for more detail: https://www.w3.org/TR/css-transforms-1/#transform-rendering – Temani Afif May 05 '21 at 00:03

0 Answers0