Get face material or score from a rigid body cube/dice

Hello,

I am creating some dices and got some problems figuring out what the score/top face will be. So i thought to cast an ray from a manager to the dice and use the poly to get the material, this works perfectly fine with a static object but seems not to work with a rigid body type, it just returns None.

        ray = dice_manager.rayCast(min_z_vec, dice_manager, 1, poly = 1)
        
        print(ray[3].material_name) #works on static but not on rigid body types

I could make a workaround for it by just replacing the rolled dices with static ones that copy positions/orientations and read those. I also thought about creating a dict with angles, but this ain’t gonna work either because to handle all the in-between angles would be a pain(90.1, 90.5, etc)

Is there a way to make this work or an other way to know witch side/score/number is up?

Thanks

Dot against up vector, easy money.

from bge.logic import getCurrentController;
from bge.render import drawLine;
from random import uniform;
from mathutils import Vector;
own=getCurrentController().owner;

def apf(f, lb, hb):
    return (f <= hb) and (f >= lb);

faces={

"red"   : [ Vector([ 0, 0, 1]), Vector([255,  0,  0]) ],
"teal"  : [ Vector([ 0, 0,-1]), Vector([  0,255,255]) ],
"yellow": [ Vector([ 1, 0, 0]), Vector([255,255,  0]) ],
"green" : [ Vector([-1, 0, 0]), Vector([  0,255,  0]) ],
"purple": [ Vector([ 0, 1, 0]), Vector([255,  0,255]) ],
"blue"  : [ Vector([ 0,-1, 0]), Vector([  0,  0,255]) ]

}
up = Vector([0,0,1]);

if("init" not in own):
    rand_ang=Vector([uniform(-180,180), uniform(-180,180), uniform(-180,180)]);
    own.worldOrientation=rand_ang;
    own["init"]=1;

for key in faces:
    face=faces[key];
    face_r=face[0].copy(); face_r.rotate(own.worldOrientation);
    drawLine(own.worldPosition, (own.worldPosition)+(face_r*10), face[1]);
    if( apf(face_r.dot(up), 0.95, 1.0) ):
        print(f"{key} up!");
        

uhm i don’t fully understand your example, wel i understand your code, but how would i do this with a physical cube, i can not grab the faces like the dict.

for now my code is like this:

def test(cont):
    
    own = cont.owner
    key = cont.sensors['Keyboard']
    
    if not key.positive:
        return
    
    if not 'init' in own:
        own['dices'] = [obj for obj in own.scene.objects if 'dice' in obj]
        own['dice_manager'] = own.scene.objects['dice_manager']
        own['init'] = True
        
    dices = own['dices']
    
    if not dices:
        print("-> No dice(s) found!!!")
        return
    
    score = []
      
    for dice in dices:
            
        dice_manager = own['dice_manager']   
        dice_manager.worldPosition = [dice.worldPosition.x, dice.worldPosition.y, dice.worldPosition.z + 0.10]
        
        min_z_vec = dice_manager.worldPosition - dice_manager.worldOrientation.col[2]
        ray = dice_manager.rayCast(min_z_vec, dice_manager, 1, poly = 1)
        
        face_material = ray[3].material_name
        rolled_number = face_material.strip('MA')
        
        score.append(int(rolled_number[0]))
                
    print('Rolled:', score, 'total rolled:',sum(score))

(the version for static cubes, those who do not work with rigid body type)

so i wonder how i would grab var. face, and who the owner would be.

My script will give you a key based on which face is up.

You can turn that key into a score, by either making it a flat integer value or by using it to index into another dict.

The idea here is you can assume that key *is* which face is up, because for geometry this simple the truth of the key-face relation is guaranteed.

Here, see if my file works for you dice.blend (802.5 KB)

This is what it looks like.

1 Like

Amazing, implemented it and works like a charm. Thanks!