This had been one of the construction sides which consumed the most time. Up to now there existed in the game engine Terrain and Component resources. Terrains had been used to create static map geometry while components had been used to create dynamic objects. This separation caused more and more double code and situations where it has been unclear if a terrain or a component should be used. Furthermore terrains started to become more and more similar in the properties they had to components. To end this double code situation Terrain resources have been dropped. This way now components are used for both static map geometry as well as dynamic objects. To deal with this task some additional features have been bestowed upon the Component resource.
For one tangents have been added to the Model resource used in components. So far models only stored the normals. This is though not a full definition of a surface point. For a full definition (a coordinate system) at last 2 vectors are required (assuming the coordinate system is orthogonal which is the case here). The first vector is the normal and the second the tangent. The third is the co-tangent and can be calculated from the other two. With storing tangents in the model files meshes are now fully defined which allows for maximum control over there appearance.
Another addition are texture overrides for components. Terrains had by definition their textures stored in the terrain object instead of the terrain mesh. For each texture a skin could be defined. With components it had been similar in that the component stores the textures not the model file. The difference so far had been that for a component one skin defined all the textures as each skin can host multiple textures which had been matched. To support the ability of using one skin per texture as the terrains had so far texture overrides have been added. Simplified this means that in addition to one skin per component you can now also specify a skin per texture if you want. These per texture skins override the texture with the matching name in the skin. The following graphic shows the process.
This may look now a bit daunting but the way it works is rather simple and intuitive. The model defines which textures exist and are used. The skin assigned to the component then defines the actual texture content to use for each individual texture (matched by same name). This is the default way for handling components like a player or a prop. You can now replace individual textures anytime with another skin. Rendering then uses this overrides where used. This way you can redefine the material of a wall for example using world skins somewhere in your game directory. Good thing is that you can reuse materials this way as well as altering individual textures if required. The initial skin in the component is optional. Hence for a component used as static map geometry you can define all textures only using texture overrides. Handling materials of static map geometry is very simple this way (also in the editor) and in addition you gain this flexibility for all kinds of objects in the world.
One might ask now what the difference is between „Texture Overriding" and „Dynamic Textures". The difference is that texture overriding replaces an entire texture while dynamic textures replaces individual channels inside a texture. Hence texture overriding is the choice if you want to replace entire materials of objects on the fly while dynamic textures are used if you want to replace individual material properties. Texture overriding is faster than dynamic skins and consumes less memory.
Rigs and Colliders
Using components instead of terrains gives you also another neat trick for free. Components can have rigs and colliders. Now what does this mean in detail. In most games map geometry is used in the physics part of the game using a triangle mesh. This is a straight forward solution but also inefficient and not without problems. Testing for collisions against triangle meshes is a lot slower than testing against analytical shapes as they are usualy used for dynamic objects. Furthermore triangles have no thickness. A triangle mesh composed of triangles therefore has no inside and outside mathematically as it composes of volumeless triangles. Analytical shapes on the other hand have a volume and have a well defined inside and outside area. This lack of volume leads to problems like getting stuck in or falling/clipping through triangle meshes. Another problem are the edges of the triangles which can yield false positives requiring forced gaps and other nasty hacks to prevent problems.
Using rigs and colliders map geometry can now be represented where required using analytical shapes. This might sound now like lots of extra work but in most cases it is actually simple. Let's take a house with rooms for example. The walls and floors can compose of a ton of triangles depending on how elaborate the walls are and if they have multiple textures. Testing against such a triangle soup is not very optimal especially since the physics of such a house is rather straight forward. Walls and floors can be represented by boxes. Instead of testing now against lots of triangles the tests boil down to a simple collision test between analytical shapes (since AI usually uses already an analytical shape). The performance and robustness of such an approach is a lot higher. Furthermore using analytical shapes for static map geometry yields other benefits. The shapes can be larger than the wall underneath keeping objects at a distance from the wall without any extra code. You are though not forced to use analytical shapes. Providing no such shapes uses triangle mesh collision. Hence you can quickly create geometry and test with it and provide additional collision shapes later on to optimize.
Furthermore colliders support collision selection using a bit mask as well as a callback. This allows multiple sets of collision volumes to be used for example to define different collision behavior for different objects. For example for a large player actor certain places can be off limits as he can hardly move in there. Instead of trying to sense such situations using additional collision tests or explicite map entities another set of simple collision volumes affecting only this kind of AI can be provided. This set provides larger collision shapes for example. The advantage of this solution is that these additional shapes can be tailored for each situation to provide the best „flow" for an AI. Using the old approach erratical motions can happen or an AI/player can get potentially stuck.
Another nice trick possible with this solution is explicite protection against „smart players" or „climbers". Using triangle meshes fitting the static map geometry correctly smart players can try to step on small triangles in walls trying to climb or otherwise taking advantage of map geometry. Tweaking maps to not provide such „foot-holds" can be time consuming. Using analytic shapes you can prevent all this kind of problems without spending lots of extra time testing and modifying. A wall requires usually one box shape. No matter how you model the wall underneath the player will not be able to misuse your mapping since he collides against the box shape not the triangle mesh.
Another something which can benefit from this is path finding. Path finding in triangle meshes is tricky and consumes valuable time. All path finding algorithms use an abstract view of the map to reduce the information. This information has to be provided explicitely or generated. Both of these have their drawbacks and problems. With rig shapes though the abstraction required by path finding algorithms is already delivered for free. You can reuse this abstraction without extra work. And since shapes are assigned to bones or can contain user assigned properties additional path finding informations are also already present without having to be hacked into the system. And should this not be enough you can still use additional collision shapes with a different set of collision bit-masks to carry more information.
As you can see replacing terrains with components yields a tremendous amount of possibilities. It took some time to do all the changes to the various engine parts, editors and the game itself but the result is worth it. Not only is the system now simpler it's also much more flexible and predictable.
The next news post in the "Big News Pack" series will take a look at changes in the Epsylon game talking about dragons in narrow spaces and some GUI work. Stay tuned.