Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rotate blocks (0, 90, 180, 270 degrees) #33

Closed
Nesh108 opened this issue Jul 24, 2017 · 19 comments
Closed

Rotate blocks (0, 90, 180, 270 degrees) #33

Nesh108 opened this issue Jul 24, 2017 · 19 comments

Comments

@Nesh108
Copy link
Contributor

Nesh108 commented Jul 24, 2017

Hey @AndyHall,

Is there any way to be able to rotate a specific block (either before or after being placed) by 0, 90, 180, 270 degrees (x, y or z)?

The idea would be to reuse blocks without having to re-create them X times just to add different rotations.

@fenomas
Copy link
Owner

fenomas commented Jul 27, 2017

Hey - this is not in the engine at present. I had thought about it, and there is room in the internals to assign several bits of "variation" per voxel like this, but I haven't thought out all the details.

For example, I'm not sure how the client would specify voxel variations at chunk-creation time. The technically straightforward way would be to have the client pack variations into the high bits of the int values, same as the engine does, but ideally the client wasn't supposed to need to know implementation details like that. But the alternatives wouldn't be very clean either.

I think it could be wrangled, but it would take some thinking and at the moment it's not super-high on my list, sorry! In my content, I'm basically only using block rotations for "custom blocks" (where the voxel has a non-block shape), and for those I apply the rotation in the custom block handlers at block creation.

@EliteAsian123
Copy link

EliteAsian123 commented Sep 14, 2019

I found a way to make static properties like for example the hardness for a block, but it'll be cool if we had dynamic variation, like the direction of a block. This variation will be very handy if added.

@Heath123
Copy link
Contributor

I think the way Minecraft does it now from 1.13 onwards is to register each possible variation of each block as a "blockstate". Maybe you could edit constants.js to use the the variation as extra block ID bits and register each like a separate block? That seems to be the way Minecraft does it now.

@fenomas
Copy link
Owner

fenomas commented Jun 21, 2020

Yes, that's the way something like this would properly be done - by using 2 bits in the voxel ID as state data, and then having the mesher look at that state when building terrain. However it's complicated how this could be implemented API-wise: the game client gives the engine plain voxel IDs, and the engine does meshing shortly afterwards, so there would need to be some new way of letting the client pass in block state flags during the interim. Anyway this is possible but I don't have plans to do it very soon!

@Heath123
Copy link
Contributor

Minecraft 1.13+ registers each possible rotation/state as a separate ID, so there can be any number of states and no redundant bits, which can already be done in noa. Minecraft 1.12 and below had a fixed 4 bits of data for each block, like noa has now.

@fenomas
Copy link
Owner

fenomas commented Jun 21, 2020

Ah sorry, I misunderstood you before. That's really useful to know, thanks! I don't suppose you know why they changed the format?

(To be clear, noa doesn't do anything with the extra bits of voxel state, it just sets aside space for them to be used someday. But it sounds like I should forget that and increase the maximum voxel ID instead.)

@Patbox
Copy link

Patbox commented Jun 21, 2020

They run out of free block ids if I remember correctly.

@Heath123
Copy link
Contributor

Yep, doing it that way is more compact so it frees up IDs. It also lets them use more than 16 combinations, which they probably needed to store waterlogging data for Update Aquatic (you need to store water data and block data).

@Heath123
Copy link
Contributor

https://minecraft.gamepedia.com/Block_states#Daylight_Detector for example has over 16 possible states

@Heath123
Copy link
Contributor

If you did want to move to a blockstate system, I think you should have a way of defining a JS object with values for variation (like the ones on the wiki page), and noa should register all of the combinations, and also you should be able to set fixed values (like "is solid") that no extra states are created for (that's just my opinion though based on how I've seen that Minecraft does it).

@Heath123
Copy link
Contributor

But that's quite a big change so it might be better for me to try doing that in a fork or making a wrapper or something (I think it should be optional at least, even if it does end up in noa)

@fenomas
Copy link
Owner

fenomas commented Jun 22, 2020

@Patbox @Heath123 Thanks for all the info, it's really helpful.

Personally I think it's definitely best to just add those 4 bits to the voxel ID, which would raise the limit on unique voxels to 8191.

That said, I imagine minecraft probably has more IDs than that nowadays? An added option would be to start using Uint32Array for voxel data, effectively allowing unlimited voxel IDs. I haven't tried it, but I'd imagine this would have little effect on CPU performance, but noticeably increase memory usage for medium to large draw distances.

@Heath123
Copy link
Contributor

Heath123 commented Jun 22, 2020

@Patbox @Heath123 Thanks for all the info, it's really helpful.

Personally I think it's definitely best to just add those 4 bits to the voxel ID, which would raise the limit on unique voxels to 8191.

That said, I imagine minecraft probably has more IDs than that nowadays? An added option would be to start using Uint32Array for voxel data, effectively allowing unlimited voxel IDs. I haven't tried it, but I'd imagine this would have little effect on CPU performance, but noticeably increase memory usage for medium to large draw distances.

I think Minecraft has 4096 blockstates available at the moment (they're not all used). For what I'm using it for I'd need to eventually store lighting data too, but that only needs to be done for non-solid blocks and there are probably enough spare states for that (or I could use a separate array).

@Heath123
Copy link
Contributor

There's information about how Minecraft does it here:
https://wiki.vg/Chunk_Format#Global_and_section_palettes
This is a list of block states in 1.15.2:
https://pokechu22.github.io/Burger/1.15.2.html

@Heath123
Copy link
Contributor

Never mind, there are 11,337 in Minecraft (wow)

@Heath123
Copy link
Contributor

Would registering that many blocks cause lag?

@Heath123
Copy link
Contributor

I don't really know too much about JS and optimising it, but can one of the solidity, opacity or object marker bits be sacrificed and looked up based on the ID? That could get the voxel IDs up to 16,384 which is probably enough for most things because it's the same as Minecraft's block states. Is that feasible?

@fenomas
Copy link
Owner

fenomas commented Jun 24, 2020

Hi, this is a really good idea. So good in fact, that I'm hammering a bit trying out just getting rid of the packed bit flags, and storing voxel IDs as a plain uint16, and doing lookups everywhere the bit flag was previously used. That would allow 65k voxel IDs, and also simplify several bits of the engine somewhat. The performance hit, at first blush, seems to be about 10% slower terrain meshing, and negligible elsewhere.

10% slower meshing isn't ideal, but meshing is fast enough that it shouldn't really cause FPS drops, just lower overall throughput on world generation. I'm going to hammer a bit more but I may just check this in and hope for the best.

@fenomas
Copy link
Owner

fenomas commented Jul 2, 2020

Hi, thanks for the input here - I went ahead and merged this into #develop.

Changes:

  • voxel IDs are now plain Uint16Array elements, they're not packed into the low bits anymore
  • the maximum voxel ID is now 65535

Impacts:

  • ~10% slower terrain chunk meshing (on my project/machine, average 0.8ms → 0.9ms or so)
  • noa._constants is removed
  • Anyone who was bypassing APIs and directly accessing chunk data arrays will need to change stuff

That should be it, no public APIs changed, and no other performance impacts I found. LMK if you have issues, thanks!

@fenomas fenomas closed this as completed Jul 13, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants