Terasology code changes

OvermindDL1

New Member
Contributor
Greetings, as I cannot post in the "Core Projects" section I shall post here.

I was looking to create a new module on Terasology, but it is lacking a few features that are fairly required for the style I have planned, thus I plan to add such features via PR's to Terasology, including bug fixes and TODO's that I have been running across.

I have a few things planned, in no defined order:
  • Chunk Tessellator overhaul - This has a lot of hard coded tests, a ton of TODO's, and is fairly spaghetti'ish, obviously grown over time to have those cases added to it. I plan to abstract out a set of mesh generation tasks in to things that can be specified on the blocks while removing a lot of the rendering specific options from the block that will then become useless. Primarily there should be one for general blocks, the default when unspecified, and for something like water that can be rendered at varying heights would be another, and other such things, which also includes:
  • Removing water/lava from the engine, not all games will have those, and not all games will have 'just' those, I personally need a variety of water types, other liquids, liquid metal, etc... I wrote a cellular calculator for fluids in Minecraft that handled both heavier and lighter than air (steam for example) so I can port that over if there is not already another module handling such things. Such a module would also have an above mesh generator for the world tesselator to render the given fluids.
  • Block destruction should be removed from the engine and moved to a module, the engine itself should likely just be a sandbox, place and remove, a module can easily listen to those events and handle the block health an destruction as it is done now, and I personally plan for a slightly different style, which the engine one currently conflicts with.
  • In general many other systems that need to be removed from the engine and placed in to their own modules.
Initially I need the Chunk Tessellator changed, thus I have a question. I have two styles in mind of how to do it, either a class that mods define that will auto-register as a named renderer type (cached pointer for no map lookup at rendering time of course), this is the fastest, but not as flexible. The other style I have in mind is a component/system based renderer, so throw an event if the block type is defined as needing custom rendering, this is more powerful, but if there are many blocks that need custom rendering (as I shall require, potentially tens to hundreds of thousands within chunkloading distance) it could be slower depending on the efficiency of the event system in Terasology, thus my question being, how efficient is the event system in Terasology for this purpose or should I go with the perfectly fast Mesh Generator registration style, which is less powerful but can still do the same effects with more work?
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Good and meaty topics :)

We've talked some already. The parts I understand well enough I agree with. The rest (entity system and rendering) will mostly relate to @Immortius and @manu3d, hopefully they'll chime in. Manu3d just submitted a rendering PR today in fact if you'd like to talk a look and maybe comment, I know he appreciates a second pair of eyes, sometimes refactoring of 3d wizardry can be a lonely journey :) Lots of lovely looking new documentation in there.

@Linus did a cellular automata module a while back for liquids (kinda like in Dwarf Fortress) and @Skaldarnar is trying a newer version of it. Any related tools would be cool! The two of them have also worked some 3D wizardry, like @Linus' particle system and a big fancy dome @Skaldarnar made for Light & Shadow (where'd that go, anyway?).

In the past we've occasionally talked about replacing liquids being represented by standard blocks (even if shaped differently) with something else, like an alternative mesh of some sort - that's pretty much what you're talking about too, right? There are some old comments later in the (relatively ancient) per-block-storage thread as well as in a Steam Greenlight thread for some reason. It's kinda all over the place. In the latter thread there's also some talk about alternative world overlays, like treating grass separate from blocks. Rugs have come up too. All kinds of ideas. Most allow us to have multiple things in one space, like a chair on top of a rug or underwater plants.

Finally I want to ping @Josharias because he's so pingable, along with @Florian, @Marcin Sciesinski and @msteiger for also knowing a good amount of architecture and/or rendering. I'm missing others but that seems a decent starting list :)

A couple more links just because: http://forum.terasology.org/threads/hide-water-edges-with-foam-effects.722 (more particles / shaders / meshes) + https://github.com/MovingBlocks/Terasology/issues/206 (treating stone rubble as a pseudo-liquid represented by a partial block / mesh)
 

OvermindDL1

New Member
Contributor
@Cervator For my first part I am changing up how block rendering works, I likely plan to do it in small chunks of PR's as I have time. The rendering PR Manu3d submitted appears unrelated, his is the low-level bits where I will start out by touching the high level block mesh generation, so no worry about overlap as far as I see. :)
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Oh yes, it is technically unrelated, but both 3d wizardry so I tie them together anyway just in case for review and what not :D
 

manu3d

Active Member
Contributor
Architecture
I wasn't going to comment directly to Overmind's OP as I feel a number of people are more qualified for the issues he's raising. But I could certainly use a brother in arms in the rendering department as it is a bit lonely down there in the pixel forge... ;)

That been said, while I now have a much better understanding of what the renderer does in general, there are a few "dark corners" I haven't ventured in yet. One in particular is chunks/block handling and rendering. So, at this stage I can only welcome anything that makes that area of the code friendlier to mere mortals' eyes. I'll take it as an opportunity to learn about it though, by following the process through the incoming PRs and hopefully I'll be able to help by offering useful comments on them or simply say "looks good!".

Regarding the potential for overlap @OvermindDL1, indeed I confirm I do not see any overlap with the current PR. However, do please keep an eye on the broader set of changes shown in this branch as that is the direction I'm heading for. I still see little overlap even longer term, but as you start digging in the code, you never know where you might end up having to do modifications. In particular I will be working extensively on the LwjglRenderingProcess (will be broken up in three separate classes) and also a little bit more on the WorldRendererImpl class (needs to accommodate the new classes). If you need changes in those you might want to give me a heads up about them: I might be able to fit the changes as part of the work that is already planned.

@Cervator thanks for the links: some of them are very interesting!
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
I link therefore I am! Also awesome term "Pixel Forge" - finally got you a custom title, hehe :D
 

OvermindDL1

New Member
Contributor
@manu3d I have the first of a multi-step plan complete and tested at https://github.com/OvermindDL1/Terasology/tree/BlockRenderingUpdate (not updated at this second, though should be within the next half hour or so after I finish some final confirmation tests and drag myself out of this hut I have built, which reminds me, some rendering is *really* wonky, here is a completely enclosed wood hut with no torches or other light source except for a sole open door
http://overminddl1.com/Terasology/screenshots/Terasology-150417000520-1152x720.png and the same room, without moving, just the door shut http://overminddl1.com/Terasology/screenshots/Terasology-150417000525-1152x720.png and that one appears to be 'leaking' light, lots of graphical oddities like that I am finding...
) and I am making it so each step can be PR'd individually (or all at once later) for simple code review and they should be fully functional for the state that they are in. I am moving the rendering out from being hardcoded and moving the rendering related functionality into an implementation to allow it to be customized (which is what I require for what I am designing). Basically this will bring it into feature parity with the MinecraftForge ISimpleBlockRenderer, though with more features, and a little faster.

EDIT: Push is committed. Shall I proceed to the second stage of major refactoring or should this be PR'd for testing? If there are any comments then please state, as well as confirm my style matches properly and other such things. :)
This should at least give the initial idea of what I am heading toward, though it will become significantly more different here soon.
 
Last edited:

Immortius

Lead Software Architect
Contributor
Architecture
GUI
Various thoughts:
  • Ideally block types would be entities. This would allow them to have components to define their attributes which could be readily expanded on by mods, and allow the concept of health or hardness to be ripped out of engine. Currently they are sort of at a half-way point where they have both their own class and an entity, but it is a mess. I may clean this up a bit as part of integrating the new asset framework (since they way blocks are handled currently isn't a good fit for the framework) but it won't go all the way, at least in the first pass (because I want to get the framework in sooner rather than later).
  • Similarly block families would also be entities.
  • I had some thoughts around blocks types being queried during chunk mesh generation for exactly which mesh to use based on their immediately surrounding 26 blocks, which would help avoid the need to quite so many block types (e.g. fences having a block type for each connection configuration). This wouldn't make sense for all blocks (stairs would still need multiple block types as their direction is independent of their surrounds). What this would look like, not sure - I guess an event sent to the block type entity ultimately.
  • I think rather than having custom rendering code, chunk meshes should be rendered via entities with mesh components, same as everything else. This may require mesh components having some additional settings around rendering priority. This would eliminate the need for a special class for mesh generation for different aspects of block rendering - mods can just declare systems that generate a mesh and add it to mesh components.
On the light leaking - that is an artifact of vertex lighting, I believe. I assume all the corners and edges of the house are exposed to light on the outside, so the light fades over the transition from the lit vertices to the internal vertices. A simple fix would be for the light of a side to be purely based on the adjacent position's light level. This would mean no smooth transition across blocks though. A further fix would to do the fading by checking lighting positions surrounding the side. Anyway, I believe either way the underlying lighting model is correct, but the application of it to vertices is wrong. Please feel free to correct this. Or there may just be an issue with the direction light is sampled from in the tessellator.

Initially I need the Chunk Tessellator changed, thus I have a question. I have two styles in mind of how to do it, either a class that mods define that will auto-register as a named renderer type (cached pointer for no map lookup at rendering time of course), this is the fastest, but not as flexible. The other style I have in mind is a component/system based renderer, so throw an event if the block type is defined as needing custom rendering, this is more powerful, but if there are many blocks that need custom rendering (as I shall require, potentially tens to hundreds of thousands within chunkloading distance) it could be slower depending on the efficiency of the event system in Terasology, thus my question being, how efficient is the event system in Terasology for this purpose or should I go with the perfectly fast Mesh Generator registration style, which is less powerful but can still do the same effects with more work?
A question back, but where you say renderer do you just mean custom mesh generation for how a block generated into the chunk mesh, or do you mean something else? I probably wouldn't use the word renderer if it is not part of the rendering pipeline.

I believe the event system is pretty efficient. It uses a dynamically generated byte code so that calling the event method be close to a direct method call. There is a some overhead in determining which systems are relevant for a given entity the event is called on though. I'ld say start with that, and if it isn't efficient enough we can optimise. Or at least do some metrics gathering and make an informed decision :). You will also need to decide if rendering is per block, or per block type - if it is per block type perhaps a fusion of the two techniques would work, with the event system used to fetch a rendering chain for each block type once at start up. If it is per block you pretty much have to do the events method as a block could change settings and components.

Also note that if individual blocks have advanced rendering requirements such as animation, this can be done by not trying to render them in the chunk mesh at all but instead giving them their own mesh/skeletalmesh component, particle effect components, etc.
 
Last edited:

OvermindDL1

New Member
Contributor
Various thoughts:
  • Ideally block types would be entities. This would allow them to have components to define their attributes which could be readily expanded on by mods, and allow the concept of health or hardness to be ripped out of engine. Currently they are sort of at a half-way point where they have both their own class and an entity, but it is a mess. I may clean this up a bit as part of integrating the new asset framework (since they way blocks are handled currently isn't a good fit for the framework) but it won't go all the way, at least in the first pass (because I want to get the framework in sooner rather than later).
That is what I would prefer as well. I was hoping that Block's were just another 'global' entity that you could put components on, though I noticed the entityref, which I am guessing was for that purpose in a round-about kind of way?

  • Similarly block families would also be entities.
Likewise, everything should be an entity.

  • I had some thoughts around blocks types being queried during chunk mesh generation for exactly which mesh to use based on their immediately surrounding 26 blocks, which would help avoid the need to quite so many block types (e.g. fences having a block type for each connection configuration). This wouldn't make sense for all blocks (stairs would still need multiple block types as their direction is independent of their surrounds). What this would look like, not sure - I guess an event sent to the block type entity ultimately.
That is precisely the kind of situation my changes are supposed to handle the, the BlockMeshGenerator subclasses should handle caching of meshes, choosing which mesh to do based on surrounding data, fluid level height decisions, etc... In my mod, for my ores for example, I will be choosing different overlay's to render on my blocks based on various ore data, density, and such.

  • I think rather than having custom rendering code, chunk meshes should be rendered via entities with mesh components, same as everything else. This may require mesh components having some additional settings around rendering priority. This would eliminate the need for a special class for mesh generation for different aspects of block rendering - mods can just declare systems that generate a mesh and add it to mesh components.
That could potentially create a lot of new meshes just to render a couple of blocks. What I think would be nice (by programming style, unsure of speed without testing) would be systems that listen to a component on the base block type and a rendering call as normal, something like this (pseudo-code):
Code:
    // In some System subclass
    @ReceiveEvent(components = {MyMeshType.class})
    void handleChunkRender(ChunkRenderEvent event, EntityRef block) {
        // Handle your custom rendering here
    }
This would have the effect of being able to render multiple things for a single block based on what components are on the block. I would also want the ChunkMesh to, instead of just having 4 'mesh' types internally, would want it to have a variable amount, each that can have different (or same) rendering flags. Reason I would really like that is to allow me to be able to put a group of blocks (think MC redstone) on its own 'mesh' array so I can update it far faster then re-rendering an entire chunk, but not so slow as to rendering each individually via a world Entity. This issue right here was the main reason that MC would become extremely laggy and 'delayed' in its chunk rendering with a lot of updates to blocks.

On the light leaking - that is an artifact of vertex lighting, I believe. I assume all the corners and edges of the house are exposed to light on the outside, so the light fades over the transition from the lit vertices to the internal vertices. A simple fix would be for the light of a side to be purely based on the adjacent position's light level. This would mean no smooth transition across blocks though. A further fix would to do the fading by checking lighting positions surrounding the side. Anyway, I believe either way the underlying lighting model is correct, but the application of it to vertices is wrong. Please feel free to correct this. Or there may just be an issue with the direction light is sampled from in the tessellator.
If vertex rendering is what it is doing then are vertexes being combined? That is the only way I could see them leaking is if corners on different faces are being combined, they would need to be kept on separate indexes so they have unique vertex colors per face. As for the lighting model on the vertices the vertices for each face need to be separate and they need to be aware of 'corner' blocks to know when light is blocking.

A question back, but where you say renderer do you just mean custom mesh generation for how a block generated into the chunk mesh, or do you mean something else? I probably wouldn't use the word renderer if it is not part of the rendering pipeline.
Sorry, I mean mesh generation, I will try to keep it separate. :)

I believe the event system is pretty efficient. It uses a dynamically generated byte code so that calling the event method be close to a direct method call. There is a some overhead in determining which systems are relevant for a given entity the event is called on though. I'ld say start with that, and if it isn't efficient enough we can optimise. Or at least do some metrics gathering and make an informed decision :). You will also need to decide if rendering is per block, or per block type - if it is per block type perhaps a fusion of the two techniques would work, with the event system used to fetch a rendering chain for each block type once at start up. If it is per block you pretty much have to do the events method as a block could change settings and components.
What I was thinking for the ultimate style would be for:
  • Blocks to be entities
  • During chunk rendering either do:
    • Loop over each block like it is now and then send a mesh generation event to a World Block Entity if it exists, then send a mesh generation event to the base block entity that represents all blocks of that type in world.
    • For each chunk, not each block, send a mesh generation event based on the chunk, then things listening to it would gather all block locations in that chunk (an iterator given by the Chunk for blocks) for components that are either on the block itself or on a world entity for that block that have a given component(s) then it would render all of the given blocks that use that component at once. This has a higher gathering cost to determine which blocks have given components, but the Chunk class itself could cache that information by seeing which components the systems ask for and recording when those blocks have those components added or removed over the game from then on into a map, this should fix the overall initial speed problem, and with being able to generate many at once then a lot of things can be done to speed that up too. This would be the more substantial change of course, but would be the most 'component-system style'.
Also note that if individual blocks have advanced rendering requirements such as animation, this can be done by not trying to render them in the chunk mesh at all but instead giving them their own mesh/skeletalmesh component, particle effect components, etc.
Yep, *many* of my blocks will have fairly complicated and large rendering requirements that are not animated. In MC I render those to the static world chunk mesh and that is fine, if I rendered them individually, well, there could be, quite literally, hundreds of thousands within chunkloading distance, so that would be infeasible. Animated blocks of course would have to be custom-rendered, but honestly those should not be rendered individually but since those are World Entities there should be a System for a given component that takes all that are currently 'renderable' in world and handles their rendering, that way they can do custom distance checks or other criteria, can batch them up all at once (a great speed boon in many cases!) and more.

P.S. Please excuse spelling/grammar, currently am out and about instead of programming. :)
 

manu3d

Active Member
Contributor
Architecture
@OvermindDL1 : regarding workflow, I don't know what the other think, but from my perspective the key is to keep other people's limited time in mind. For example, the work I'm doing on the renderer will cause significant changes, and if I packed those in a single PR straight from my work branch, it would make it very difficult or at least very time consuming for others to review it. For this reason, in my work branch I more or less reached my "destination commit", and only now I'm starting to submit small(ish) PRs that can be more easily reviewed by others and that represent steps towards that destination. The destination commit is made available in support of the process, just in case somebody wants to see what lies ahead, but I consider the PRs the main interface between me and the rest of the crew.

So, personally I'd recommend that you first reach a sensible destination, not necessarily all the way to where you want to get, but at least a place in codescape where you can feel something is significantly better, a place where if you had to stop for whatever reason, you'd still have a sense of accomplishment. Then I'd aim to submit a string of PRs for others to reach that point in manageable bites.
 

OvermindDL1

New Member
Contributor
That is the stages I speak of, each is complete, self-contained, add something useful, and just build on the prior stages. So as it is now the PR is small and it fully adds the capability for mesh generation to be customized or left as default. :)

Should I go ahead and PR the changes I have made? Should I keep following this style of PR's?

EDIT: Cervator in IRC suggested that I should go ahead and PR in small and complete chunks like this, I have submitted a PR: https://github.com/MovingBlocks/Terasology/pull/1671
 
Last edited:

Immortius

Lead Software Architect
Contributor
Architecture
GUI
That could potentially create a lot of new meshes just to render a couple of blocks.
I am talking about the complete chunk meshes here. Shouldn't be any more or less mesh than the current approach, just avoid us having a special bit of code for rendering them (and I mean rendering in this case).

This would have the effect of being able to render multiple things for a single block based on what components are on the block. I would also want the ChunkMesh to, instead of just having 4 'mesh' types internally, would want it to have a variable amount, each that can have different (or same) rendering flags. Reason I would really like that is to allow me to be able to put a group of blocks (think MC redstone) on its own 'mesh' array so I can update it far faster then re-rendering an entire chunk, but not so slow as to rendering each individually via a world Entity. This issue right here was the main reason that MC would become extremely laggy and 'delayed' in its chunk rendering with a lot of updates to blocks.
What I mean is the ChunkMesh would be thrown away and those generated mesh would just be put into entities.

If vertex rendering is what it is doing then are vertexes being combined? That is the only way I could see them leaking is if corners on different faces are being combined, they would need to be kept on separate indexes so they have unique vertex colors per face. As for the lighting model on the vertices the vertices for each face need to be separate and they need to be aware of 'corner' blocks to know when light is blocking.
The vertices aren't shared, but the code that determines the lighting of each vertex is probably sampling lighting incorrectly.

What I was thinking for the ultimate style would be for:
  • Blocks to be entities
  • During chunk rendering either do:
    • Loop over each block like it is now and then send a mesh generation event to a World Block Entity if it exists, then send a mesh generation event to the base block entity that represents all blocks of that type in world.
    • For each chunk, not each block, send a mesh generation event based on the chunk, then things listening to it would gather all block locations in that chunk (an iterator given by the Chunk for blocks) for components that are either on the block itself or on a world entity for that block that have a given component(s) then it would render all of the given blocks that use that component at once. This has a higher gathering cost to determine which blocks have given components, but the Chunk class itself could cache that information by seeing which components the systems ask for and recording when those blocks have those components added or removed over the game from then on into a map, this should fix the overall initial speed problem, and with being able to generate many at once then a lot of things can be done to speed that up too. This would be the more substantial change of course, but would be the most 'component-system style'.
This is fair. Keep in mind you probably want the chunk and adjacent chunks, because you need the adjacent blocks which are just outside the chunk of interest.

Please be aware we don't not keep an entity in memory for every chunk. For the majority of blocks we generate a temporary entity as required, but clean it up shortly thereafter. I don't know how reasonable caching per block information on component presence would be, memory-wise. Blocks that require it have permanent entities (such as chests).
 

OvermindDL1

New Member
Contributor
I am talking about the complete chunk meshes here. Shouldn't be any more or less mesh than the current approach, just avoid us having a special bit of code for rendering them (and I mean rendering in this case).
Ah, I misread that, yeah that is what I would prefer as well, the 'Block' class should instead just be an Entity with components on it, one entity per block 'type' basically.

What I mean is the ChunkMesh would be thrown away and those generated mesh would just be put into entities.
That makes sense yeah, similar to what I have considered.

The vertices aren't shared, but the code that determines the lighting of each vertex is probably sampling lighting incorrectly.
My initial thought is that it does not consider blocks only touching an edge instead of a face, but I have not looked at it yet, just from how it looks that seems most likely.

This is fair. Keep in mind you probably want the chunk and adjacent chunks, because you need the adjacent blocks which are just outside the chunk of interest.
I have not actually looked at ChunkView yet, does it allow you to get neighbor blocks from an adjacent chunk? Or do we need a WorldView or so?

Please be aware we don't not keep an entity in memory for every chunk. For the majority of blocks we generate a temporary entity as required, but clean it up shortly thereafter. I don't know how reasonable caching per block information on component presence would be, memory-wise. Blocks that require it have permanent entities (such as chests).
Ah those were not the Entities I was thinking, I consider two kinds of Entities for blocks, which for mesh generation would be accessed in this order:
  1. World Block Entity, these are in-world Entities that have a block location, like the Chest Entity, this may or may not exist, usually not exist. If this has a component(s) for mesh generation then render using them (first? or only?) using a System
  2. Block Entity, these are the result from the block ID number to Entity mapping, only one of these Entities exist per block type (should a family just be one of thsese), but throw a message on 'it' now to let a system handle rendering it based on its information (unless a world block entity states not to use the default mesh generator, a cancelable event from the world block entity mesh generator can handle that).
 
Top