If you have the rotation matrix, I think the the easier is to get the cos between the normals and forget the vertex position.
The cos will be max and near 1 when the angle among the two vectors is near 0.
Each normal will have a face value so get the face value of the normal nearest to Vector3.UnitY is easy.
Vector3 FaceNormals = new Vector3[] { Vector3.UnitX, -Vector3.UnitX, Vector3.UnitY, -Vector3.UnitY}
int FaceValue = new int[] { 1,2,3,4 }
float cos = -1;
int faceValue = 0;
for (int n=0; n<FaceNormals.Length; n++) {
var RotatedNormal = Vectro3.TransformNormal(FaceNormal[n], RotationMatrix);
var newCos = Vector3.Dot(Vector3.UnitY , RotatedNormal );
if (cos<newCos) {
FaceValue = FaceValues[n];
vod = newCos;
}
}
where the Vector3.UnitY is fixed, and the face normal are rotated, so calculation is now in world space.
EDIT:
If you want to use vertices... calculate the center of each face, if the face has two triangles correlated:
var j =0;
Vector3[] Centers = new Vector3[indices.Lengt/6];
Vector3[] Normals= new Vector3[indices.Lengt/6];
for (int i =0; i<indices.lenght; i+=6)
{
Vector3 center;
for (int n=0; n<6;n++) {
center+= vertices[indices[i+n]].Position;
}
center/=6;
var A = vertices[indices[i+1]].Position - vertices[indices[i]].Position
var B = vertices[indices[i+2]].Position - vertices[indices[i]].Position
normal = Vector3.Cross(A, B);
Centers[j] = center;
Normals[j] = normal;
j++;
}
int[] FaceValues = { 1,2,3,4,5,6...}
float y = float.MinValue;
for (int n=0; n<Centers.Length; n++) {
var rotated = Vector3.Transform(Centers[n], TransformMatrix);
if (y < rotated.Y) {
y = rotated.Y;
FaceValue = FaceValues[n];
}
}
You'll have the dice face value in "FaceValue"