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
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
@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
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 -
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.