How can I get which side landed on top in an octahedron dice?

I am trying to create dice of different shapes - tetrahedron, cube and octahedron. I was able to get which side landed on top in a cube using the quaternion and figuring out certain patterns like this, this too although isnt perfect -

if (Math.abs(body.quaternion.y) < 0.00001) {
        lastRoll += " 4 +";
        presentScore += 4;
      }
      if (Math.abs(body.quaternion.x) < 0.00001) {
        lastRoll += " 3 +";
        presentScore += 3;
      }
      if (
        body.quaternion.x.toString().substring(0, 5) ==
        body.quaternion.y.toString().substring(1, 6)
      ) {
        lastRoll += " 2 +";
        presentScore += 2;
      }

      if (
        body.quaternion.x.toString().substring(0, 5) ==
        body.quaternion.y.toString().substring(0, 5)
      ) {
        lastRoll += " 1 +";
        presentScore += 1;
      }

      if (
        body.quaternion.z.toString().substring(0, 5) ==
        body.quaternion.y.toString().substring(1, 6)
      ) {
        lastRoll += " 6 +";
        presentScore += 6;
      }

      if (
        body.quaternion.z.toString().substring(0, 5) ==
        body.quaternion.y.toString().substring(0, 5)
      ) {
        lastRoll += " 5 +";
        presentScore += 5;
      }

But this isnt working with my octahedron and tetrahedron dice. There are no constant quaternion patterns in those dice like in the cube dice. What can I do to do this? I did find an answer on stackoverflow for a similar queston but I am unable to recreate it with the octahedron and tetrahedron dice?

I would go the way, where I take the index of the side, whose normal’s dot product, in world coordinates, is closer to 1, against the up-vector (0, 1, 0).
Dot product in the docs: https://threejs.org/docs/index.html#api/en/math/Vector3.dot

2 Likes

An alternative is to cast a ray from the center upwards and the intersection will return which face is just above the center.

1 Like

AFAIK, die’s material needs to have side: THREE.DoubleSide for that case. But yes, it’s an option too :slight_smile:
Maybe, to cast a ray from atop (put it high enough) towards the center of a die.
And also, in case of a cube, there is a very slight chance, when a ray goes in between two faces, thus there will be no intersection.

1 Like

@prisoner849, how can i get the individual side’s normal ?

The normal of any face, that belongs to the side, is the normal of the side :thinking:

@prisoner849, but how can I get each face’s normal ?

Any face consists of three vertices. The normal for any of these vertices is the normal of the face :thinking:
This works for BoxGeometry and for other geometries, that extended from PolyhedronGeometry.

Yes but how can I get the vertices of the individual faces of a cube made through boxgeometry like this -

let g = new THREE.BoxGeometry(2, 2, 2);

How can i iterate through the faces of the cube and get the vertices/ normal of each of the 6 faces of this cube to calculate the side of the cube which lands on the top ?

Specifically for BoxGeometry you can iterate through g.attributes.normal, getting data for every fourth vertex.
Some information about BufferGeometry: How ot get vertices, faces, faceVertexUvs from bufferGeometry - #2 by prisoner849

@prisoner849, what about for Octahedron and Tetrahedron geometry ? How can i iterate through the faces of these shapes and get the vertices/ normal of each side from these shapes?

Their sides are triangles. So, how many vertices per side do they have?

I recommend to investigate the source code of VertexNormalHelper.
It contains the code of the iterating through attributes.

@prisoner849, I think the octahedron will have 3 vertices per side. Thus I have used this -

      let normals = body.geometry.attributes.normal.array
      let maxArray = []
      const a = new THREE.Vector3(0, 1, 0)
      for (let i = 0; i < normals.length; i += 9) {
        let vec = new THREE.Vector3(normals[i], normals[i + 3], normals[i + 3])
        console.log(vec)
        let dotProduct = vec.dot(a)

        maxArray.push(dotProduct)
      }

The problem I am facing now is that multiple sides have the exact same values vertices like this -
image

Looks like you didn’t see the source code of that helper. Please, try to do it.
BufferAttribute has many useful properties and methods. .count, for example.
Also, Vector3 has .fromBufferAttribute method.