RandomMcSomethin / fallingleaves

MIT License
43 stars 20 forks source link

Disabling particle collisions with leaf blocks #18

Open Fourmisain opened 3 years ago

Fourmisain commented 3 years ago

The falling leaf particles actually spawn inside the block they come from, which is no issue if they are going downwards, but if they are going sideways, they can collide with other leaf blocks, resulting in stuck leaves.

It's currently not a big issue since it happens rarely, but when wind is implemented, it makes a lot of sense to me that leaves should flow through leaf blocks.

Fourmisain commented 3 years ago

I've got some partial success with this by slightly changing Entity.adjustMovementForCollisions().

It uses either Entity.adjustMovementForCollisions() or Entity.adjustSingleAxisMovementForCollisions().

adjustMovementForCollisions() is taking a stream of block collisions from world.getBlockCollisions(), which has a version taking a predicate, so I put in (blockState, blockPos) -> !LeafUtil.isLeafBlock(blockState.getBlock(), true), which did work!

However, adjustSingleAxisMovementForCollisions() has 0 configurability. It calls calculatePushVelocity() which walks through the blocks(tates) in a loop that is truly hard to understand.

Interestingly enough, I can't figue out the real difference between the two methods, using either of them alone seems to work, but there has to be a reason they both exist.

Cadiboo commented 3 years ago

Hey, I've been trying to improve my collision handling in my mod recently and have come across the same methods. I've been googling to try to understand what the loop in calculatePushVelocity does but I'm partially stumped too. Possibly this gist I made can help you understand it. I noticed that adjustMovementForCollisions (aka collideBoundingBoxLegacy) doesn't work properly when the entity is standing still (only adjustSingleAxisMovementForCollisions does) and visa versa. FYI I'm using Forge with MojMaps (1.16.5), it shouldn't be too much of a change though.

Fourmisain commented 3 years ago

Oh, thanks for the input! It's been a while since I looked into this, I remember reading some vague descriptions of the algo and about how clever it is.

Not only is there the loop in calculatePushVelocity/collide but it is using calculateMaxDistance/collideX which is another non-trivial loop.

My guess is it's using some optimization technique like sweep and prune (aka sort and sweep), which I vaguely remember as something like: Looking into a fixed direction, sort the objects by how close their front face and back faces are and then walk through all objects in order - there then is a point where either the front or back faces are too far away to allow collisions, at which the iteration stops, skipping most collision tests. I can't remember the exact details though (e.g. how do you sort by 2 values?).

For Falling Leaves I thought about the idea of temporarily modifying collision boxes (just before and after the particle's move method), though this sounds equally as terrible as modifying the collision code, considering it's just mod which just adds some particle effects. 😅

Cadiboo commented 3 years ago

It's been a while since I looked into this, I remember reading some vague descriptions of the algo and about how clever it is.

Do you remember where you read these? I'd be interested in reading it

Fourmisain commented 3 years ago

Do you remember where you read these? I'd be interested in reading it

No, and a quick search turned up nothing, not sure what search terms I used. I remember having seen it in some forum and I think there was code too, but it wasn't yarn mapped.

I'll see if I can find it (or something) again - maybe looking up the MCP mappings could help? I did have a look at the Spigot mappings but I couldn't find the calculatePushVelocity or calculateMaxDistance equivalents (they don't seem to be mapped).

Fourmisain commented 3 years ago

Hm... can't seem to find anything, tried searching for the method names (Confusingly, MCP seems to have the exact same name for Entity.collideBoundingBox?), general "minecraft collision code", "how do minecraft collisions work" etc, searched the Fabric and SpongePowered discord but alas...

Anyway, I think that the stuff I read wasn't really that helpful, it was basically saying something along the lines of "there's 2 collision codes", "actually very clever" but nothing indepth to understand what's actually going on.

It probably makes more sense looking up (AABB) collision code optimizations and see if they match what Minecraft is using. Searching for "minecraft like collision code" does give a few results (even video) about possible implementations.

Is the reason you're looking into the collision code related to https://github.com/Cadiboo/NoCubes? Because if you want collisions to be as smooth as the terrain you likely have to rewrite it from scratch, because the basic assumption of only having AABB collisions is broken (and the outline boxes probably don't fully contain the collision mesh too).

Cadiboo commented 2 years ago

Is the reason you're looking into the collision code related to https://github.com/Cadiboo/NoCubes? Because if you want collisions to be as smooth as the terrain you likely have to rewrite it from scratch, because the basic assumption of only having AABB collisions is broken (and the outline boxes probably don't fully contain the collision mesh too).

Sorry for the late response Yeah, that's why I'm doing it - I've been able to get the vanilla collisions system working work my smooth terrain but I've done it rather inefficiently (by generating a smooth mesh for every single block) and I'm now trying to optimise it (by replacing the vanilla algorithm with a hybrid algorithm that generates the collisions for an entire area).