RandomMcSomethin / fallingleaves

MIT License
43 stars 20 forks source link

Optimization: Check for air beneath leaf block. #11

Closed BrekiTomasson closed 3 years ago

BrekiTomasson commented 3 years ago

Just to test a theory, I placed a bunch of slabs under the leaves of a tree, and it continued to generate leaves that didn't go anywhere. Maybe there should be some kind of check to ensure that there's actually air beneath the leaf block before generating particles? There could even be a setting for users to define whether they want a minimum of 1, 2 or 3 air blocks before particles are generated.

Image included of particles on top of stone slabs in a tree.

image

Abbanon commented 3 years ago

I came to the repo to report this myself, but it's good to see it's been reported already.

Here's a screenshot I took of a 5x5 leaf cube touching the ground, with the Cull Leaves mod in use. You can see how the particles are collecting between the two touching block types. 2021-01-14_08 01 44

Fourmisain commented 3 years ago

This comes down to the isBottomLeafBlock() test:

https://github.com/RandomMcSomethin/fallingleaves/blob/96f86775bbd0f0e462fabda3e9981762019543cf/src/main/java/randommcsomethin/fallingleaves/mixin/LeafTickMixin.java#L87-L95

which works differently to the water drips from leaves you see during rain:

BlockPos belowPos = pos.down();
BlockState blockState = world.getBlockState(belowPos);

return !blockState.isSideSolidFullSquare(world, belowPos, Direction.UP)
    || !blockState.isOpaque();

No matter how often I look at it, it trips me up how different they are; why does the drip check have a negation before isSideSolidFullSquare() while isBottomLeafBlock() does not?

Why was !blockState.isOpaque() replaced by blockState.isTranslucent(world, belowPos) || blockState.isSolidBlock(world, belowPos)? Actually, version 1.0 didn't have blockState.isSolidBlock(world, belowPos), so it was "not opaque" vs "translucent", which seems to make a bit more sense.

Why can't we simply check for air?

Because then leaves wouldn't fall if there's a fence, an open trapdoor, a button or maybe flowing water or a modded fruit below - it'd be too exclusive.

On the other end we need to ensure that leaves don't fall directly between leaf blocks - although we can always test for that directly via blockState.getBlock() instanceof LeavesBlock, so we shouldn't worry about that too much.

What do these properties mean?

In short: Absolutely no clue.

I wrote some interpretations that I had to delete because they all seemed to be wrong, so here's just some fax:

Tested on an oak leaf block (the block itself, not what's below it): blockState.isSideSolidFullSquare(): false blockState.isTranslucent(): false blockState.isSolidBlock(): false blockState.isOpaque(): false blockState.getMaterial().isSolid(): true

The wiki describes solid blocks as ones which have collisions - that may match with getMaterial().isSolid().

Note the seemingly contradictory statement isTranslucent() = isOpaque().

What to do

Maybe we should do an actual collision test before spawning a particle at a specific location, e.g. there's world.getBlockCollisions(@Nullable Entity entity, Box box) and Particle by default has a bounding box with an 0.2 spacing, so I think new Box(0.1, 0.0, 0.1, 0.1, -0.2, 0.1) offset by the position should work. We can extend that box vertically down as far as we like to check if there's anything in the way.

Since I was so close, I just implemented it: collisiondetection It seems to work pretty well!

Fourmisain commented 3 years ago

I also just noticed: Do falling leaves have common drift? They all seem to shoot out in a certain direction.

...

Yes they do! https://github.com/RandomMcSomethin/fallingleaves/blob/cb41ba411497df525f7fbe9e07b6b6990b0e4ffa/src/main/java/randommcsomethin/fallingleaves/mixin/LeafTickMixin.java#L77-L80 The last 3 arguments are the velocity, which are used to give the leaf it's color - and the leaf constructor just keeps (actually reduces) the values, so all same-colored leafes will drift in the same direction.

It makes it look like there's wind, which actually works in the mods favor.

BrekiTomasson commented 3 years ago

Many great comments, and I see no reason to argue against anything you're saying here. The only thing I can imagine adding to the conversation at this point is that we should keep the check that detects whether there's another leaf block beneath as well, since there are mods such as Tiny Tweaks that remove the collision box from leaves. If we'd only check for collision and not identify the "lowest" leaf blocks in a cluster of leaves, then we'd potentially end up with a lot of particles being generated.

I also think we should look into the idea of checking the distance to collision, as I'm sure we could get some performance benefit if we remove particles that only travel 1 block before collision. I'm thinking of Oak trees with leaves just one block off the ground and several modded trees where you have layers of leaves looking something like this: (X for leaves, O for logs):

           XOX
            O
          XXOXX
            O
         XXXOXXX
            O
       XXXXXOXXXXX
            O
     XXXXXXXOXXXXXXX
            O
            O
            O

If we're just checking for collision one block away, there are 22 leaf blocks that would be generating particles that fall down 1 block before hitting another leaf block, not just the 14 bottom leaf blocks that are visible from the user's perspective.

Fourmisain commented 3 years ago

Pushed the implementation to main (and deleted the branch).

Release hopefully comes soon.