ArsThaumaturgis/Panda3DTutorial.io

Lesson 9 - Masks

Closed this issue · 6 comments

First of all, I have to mention you have done a great job while creating these lessons.

As a Panda beginner, I found masks confusing the the way you presented them.

It could have been better in my opinion, if you organised the collide-able objects into an enumeration and created a function for creating the masks for you. Something like this:

masks.py

from enum import Enum
from panda3d.core import BitMask32


class Target(Enum):
    EVERYTHING = -1
    WALL = 0 
    PLAYER = 1
    WALKING_ENEMY = 2
    TRAP = 3
    RAY = 4


def create_mask(things_to_interact):
    if Target.EVERYTHING in things_to_interact: return BitMask32(0xFFFFFFFF)
    mask = BitMask32()
    for thing in things_to_interact: 
        mask.setBit(thing.value)
    return mask

GameObject.py

# Somewhere inside Player's initialization routine

# Player should be collide-able by other object having their
# player bit on and should collide into walls, enemies and traps.
self.collider.node().setIntoCollideMask(create_mask([Target.PLAYER]))
self.collider.node().setFromCollideMask(create_mask([Target.WALL, Target.WALKING_ENEMY, Target.TRAP])) 

# Nothing should collide into a ray, and
# ray should collide with enemies and traps
rayNode.setIntoCollideMask(create_mask([])) 
rayNode.setFromCollideMask(create_mask([Target.TRAP, Target.WALKING_ENEMY]))

Thanks again for the great work.

Greetings!

First of all, I'm very glad if the tutorial has been proving helpful for you, and thank you for the kind words on it! ^_^

As to your suggestion, I'll confess that I'm hesitant: I want to keep the code simple, and to explain the fundamentals of masks. I fear that introducing a function to handle mask-making might complicate the lesson.

That said, looking at the lesson again, I do note that I don't actually lay out what bits I intend to use for what. Perhaps doing that might help?

As a general note, let me say that I do indeed support using enums! (Or something similar; in my own code I usually just use constants.) I'm just not sure that I want to introduce additional complications when teaching a new concept.

I'm not sure about this line, by the way:

if Target.EVERYTHING in things_to_interact: return BitMask32(0xFFFFFFFF)

I'd want to check that so extensive a flag doesn't include the bit that's used for visible geometry--which one generally doesn't want to collide with, even if one wants to collide with all logical objects...

Yes, I think a consise table and/or paragraph would suffice for making the concept more straightforward.

Can you elaborate more on what you mean by bit for all visible geometry? Isn't the default mask (e.g collide with everything) all 1s, if so, what's wrong with the mentioned statement?

Yes, I think a consise table and/or paragraph would suffice for making the concept more straightforward.

Good good! I've made a mental note to add such a thing. ^_^

Can you elaborate more on what you mean by bit for all visible geometry? Isn't the default mask (e.g collide with everything) all 1s, if so, what's wrong with the mentioned statement?

Ah, checking, it seems that I was incorrect in the tutorial in stating that the default is "all on"! Another thing to correct!

In fact, based on a quick test, it looks like the default is 0x000FFFFF.

But returning to the original point, visible geometry is associated with bit 20, if I'm not much mistaken. Thus setting all of the bits of a mask to "on" should include the bit for visible geometry, thus resulting in collisions with standard meshes.

(You can actually get the collide-mask for visible geometry via the following call:
mask = GeomNode.getDefaultCollideMask()
)

Glad I am helping with your work.

It's actually a really underdocumented topic in panda 3d manual that could possibly lead to weird bugs. For instance, when I heard about 32 bit masks I thought "Well, that means I can have 32 different type of collidables". I never thought that special bits were included in that mask.

Well, I mean, technically you can--as long as one of those types is "visible geometry". :P

But yeah, it may well be that more documentation could be put down on the topic! You could perhaps file an issue requesting such an addition (or even make a pull request adding it yourself) over on the Panda3D documentation GitHub page. ^_^

Okay, I've made the relevant changes! (As well as a brief mention of the potential use of constants and enumerations.)