T3D, Existing Object and Terrain System, and Terrain Paging
by Demolishun · in Torque 3D Professional · 09/04/2013 (7:17 pm) · 31 replies
Okay, I got to thinking about T3D, the existing object system, and the terrain system. I was thinking in terms of terrain paging. To me, terrain paging is a really good concept that is only gaining speed. However, after thinking about how the engine is setup as is T3D may not cut it out of the box. Why? Simply put, because T3D does not place the camera at the center of the Video Card's universe terrain paging will never function properly. This is because of the floating point number issue. So what to do?
First I need to find where the assumptions are made:
As I ponder this I wonder if to do terrain paging of any kind will the entire object system and rendering system need a complete overhaul? At the very least the object system does. It is based upon the assumption that the camera is not in the center of the graphics cards rendering space. So at some point (probably SceneObject) this assumption will have to changed. I am thinking that the actual position of objects should be a either a 32 bit or 64 bit integer. This data should either be in the object as additional position data or tracked outside using the object ID or hash of some sort to access this information for rendering. The reason I would represent position with an integer is that it is an absolute position that suffers no issues from large values and accuracy. This could be sub-mapped for rendering using floating point representations in the video card scene.
After thinking this through I came to one startling revelation. Most FPS style games are designed to be a in small space that are easily represented by 32 bit floating point numbers. So from a technical perspective T3D is very much locked into an FPS style mission implementation. So the criticism that the engine is an FPS engine may not be an emotional argument, but a technical one.
First I need to find where the assumptions are made:
- At what point in the engine is the assumption made that the player is not the center of the graphics card universe?
- Is it in the SceneObject, the TerrainObject, the Camera?
- Should the position of the SceneObjects even be stored in the object?
- Should physics and position be tracked outside of the objects themselves?
As I ponder this I wonder if to do terrain paging of any kind will the entire object system and rendering system need a complete overhaul? At the very least the object system does. It is based upon the assumption that the camera is not in the center of the graphics cards rendering space. So at some point (probably SceneObject) this assumption will have to changed. I am thinking that the actual position of objects should be a either a 32 bit or 64 bit integer. This data should either be in the object as additional position data or tracked outside using the object ID or hash of some sort to access this information for rendering. The reason I would represent position with an integer is that it is an absolute position that suffers no issues from large values and accuracy. This could be sub-mapped for rendering using floating point representations in the video card scene.
After thinking this through I came to one startling revelation. Most FPS style games are designed to be a in small space that are easily represented by 32 bit floating point numbers. So from a technical perspective T3D is very much locked into an FPS style mission implementation. So the criticism that the engine is an FPS engine may not be an emotional argument, but a technical one.
About the author
I love programming, I love programming things that go click, whirr, boom. For organized T3D Links visit: http://demolishun.com/?page_id=67
#2
After all, when folks talk terrain paging, the underlying assumption is usage with area paging as well, so most times there, it's in terms of relative position.
09/04/2013 (7:27 pm)
Maybe a few (HA!) alterations to the bin and/or zone systems, and the way object's interact with them, since that's close to the concept of storing object-instance data per-area?After all, when folks talk terrain paging, the underlying assumption is usage with area paging as well, so most times there, it's in terms of relative position.
#3
Your right, how do you track that? I know the Minecraft server solves this using chunks. I also know the demands on a typical Minecraft server is pretty high.
What I am thinking needs to happen is the separation of world space from video card rendering space. Once that happens you have more options.
09/04/2013 (7:34 pm)
This is not a "make a bold statement to make the GG community defensive" post. It is a "look, this may be a technical limitation and future road block" post. I am well aware that many types of games can be made using a location-centric implementation. It just lends to the perception from a technical stand point that it is locked into an FPS style position tracking. Many people over the years have asked for terrain paging. It is not going away. I am wondering if the engine is boxed in at the moment.Your right, how do you track that? I know the Minecraft server solves this using chunks. I also know the demands on a typical Minecraft server is pretty high.
What I am thinking needs to happen is the separation of world space from video card rendering space. Once that happens you have more options.
#4
Actually going from there to paged geometry is a massive step, but it can';t happen without that initial decoupling.
Richard, the simplest solution to you issue you raise is to refactor SceneObject to store positions in double precision. The entire transform matrix wouldn't necessarily have to be stored in double precision, which may necessitate splitting it into a Point3D position and a QuatF rotation, for example. Then the server deals with double precision absolute positions, and the clients convert that into single-precision render transform information.
I reckon the basic solution is to have every getRenderTransform method return a position relative to the camera. Sounds like a lot would have to change to make that happen :P.
09/05/2013 (1:32 am)
I agree that separating the object positions from the render position is a good first step. This wouldn't have to affect client/server dynamics at all, since it just affects rendering.Actually going from there to paged geometry is a massive step, but it can';t happen without that initial decoupling.
Richard, the simplest solution to you issue you raise is to refactor SceneObject to store positions in double precision. The entire transform matrix wouldn't necessarily have to be stored in double precision, which may necessitate splitting it into a Point3D position and a QuatF rotation, for example. Then the server deals with double precision absolute positions, and the clients convert that into single-precision render transform information.
I reckon the basic solution is to have every getRenderTransform method return a position relative to the camera. Sounds like a lot would have to change to make that happen :P.
#5
@Daniel - yeah, that'd probably work, and be a ton of work to boot. I'd hate to scrap the current system because there would be performance trade-offs I'm sure. So the optimal solution would allow the game designer to select which "perspective" to use
09/05/2013 (6:46 am)
@Demo - no, that's not what I meant at all, just wanted to clear the terminology. Everyone uses "FPS" when they talk about stationary world/moving camera systems, but we all know better... ;p Command and Conquer and Warcraft used this same system - and probably Diablo. It is completely viable (and fairly common) to make just about any type of game this way - Freelancer, Wing Commander (and Strike Commander), etc. I'm pretty sure Falcon 3.0 did, too. So, I'm not being defensive - just obnoxious about "lingo" I guess.@Daniel - yeah, that'd probably work, and be a ton of work to boot. I'd hate to scrap the current system because there would be performance trade-offs I'm sure. So the optimal solution would allow the game designer to select which "perspective" to use
#6
I am thinking this could be developed as a second set of objects in parallel to the main set. I see no reason to dump what we have. It is fairly obvious this is meant to tackle a different set of game types.
09/05/2013 (8:26 am)
Why not store the position in 32 bit integer with a float to store the position from 0.0 to 1.0 (or some small range) to offset within the macro range of the integer? I want to specifically move away from the doubles/floats because of precision issues. You would use the same space as a double.I am thinking this could be developed as a second set of objects in parallel to the main set. I see no reason to dump what we have. It is fairly obvious this is meant to tackle a different set of game types.
#7
Man, there is so much work to do and just not enough time and manpower to go around.
09/05/2013 (12:49 pm)
It's a large task anyway, why not tackle the elephant in the room and make the terrain system a pluggable dll? Pave the way for doing the same with the renderer, etc....Man, there is so much work to do and just not enough time and manpower to go around.
#8

Where active would be where players are, loaded would be one zone over, cached would be outside of scope, and object-positions are stored relative to a given active zone, with an interpreter for when an object crosses a boundary.
One of the folks in IRC mentioned a different approach from... OGRE3D? Where everything was stored as offsets from their respective parents, though I believe the general consensus was 'that gets hairy quick'.
edited with a somewhat clearer pic of the mechanic. not to mention a smaller one. oops.
09/05/2013 (12:54 pm)
To elaborate a bit on the concept I'd mentioned a bit earlier, most 'streaming level' systems operate the same way a streamed video, or sound one does:
Where active would be where players are, loaded would be one zone over, cached would be outside of scope, and object-positions are stored relative to a given active zone, with an interpreter for when an object crosses a boundary.
One of the folks in IRC mentioned a different approach from... OGRE3D? Where everything was stored as offsets from their respective parents, though I believe the general consensus was 'that gets hairy quick'.
edited with a somewhat clearer pic of the mechanic. not to mention a smaller one. oops.
#9
I most likely will be not using the terrain system. I will probably be gutting the object system as well. What is there is not going to work for what I want to do. This will all happen after I finish my proto. I need to get game play testing occurring in parallel to my low level work.
However, as I have been pondering the issues with T3D this came up as a potential issue for certain game types. I have always been fond of open world games like Morrowind. Now I am completely enamored with the game play of Minecraft (learning about how that gameplay works in half the fun!). So the existing stuff in T3D won't do what I want. That is whole point of the way the engine is designed anyway. The "game" code in the engine is what needs to be customized for the game type. In this case it will be pageable terrain. I realized the coordinate system may be holding me back.
I will keep my eye out for where things can be modularized. I could see this helping people wanting to page octree terrain as well. I may not give away the marching cubes stuff, but I can certainly help lay the ground work for a world centered camera. Heck, I may even find this is more of an abstraction issue anyway.
09/05/2013 (2:16 pm)
@Richard,I most likely will be not using the terrain system. I will probably be gutting the object system as well. What is there is not going to work for what I want to do. This will all happen after I finish my proto. I need to get game play testing occurring in parallel to my low level work.
However, as I have been pondering the issues with T3D this came up as a potential issue for certain game types. I have always been fond of open world games like Morrowind. Now I am completely enamored with the game play of Minecraft (learning about how that gameplay works in half the fun!). So the existing stuff in T3D won't do what I want. That is whole point of the way the engine is designed anyway. The "game" code in the engine is what needs to be customized for the game type. In this case it will be pageable terrain. I realized the coordinate system may be holding me back.
I will keep my eye out for where things can be modularized. I could see this helping people wanting to page octree terrain as well. I may not give away the marching cubes stuff, but I can certainly help lay the ground work for a world centered camera. Heck, I may even find this is more of an abstraction issue anyway.
#10
09/05/2013 (2:27 pm)
Stuff like typedefing more core data structures might help. We typedef for platform abstraction, but not for modularity. On the other hand, there's too much code dependent on stuff like object transforms for a typedef to make it any easier - you could change the typedef but then you'd have to deal with a bunch of broken code anyway.
#11
How big of a mission can I actually get away with before the precision issue kicks in? Honestly, one does not necessarily travel that far in a single player game in minecraft. So if you went beyond a boundary you could load a different mission. Barring the mission load annoyance it might actually be better on the server and allow for load better load distribution.
09/05/2013 (3:04 pm)
I guess one question is this:How big of a mission can I actually get away with before the precision issue kicks in? Honestly, one does not necessarily travel that far in a single player game in minecraft. So if you went beyond a boundary you could load a different mission. Barring the mission load annoyance it might actually be better on the server and allow for load better load distribution.
#12
I've been thinking about this on and off for a while. I started to consider loading multiple small missions in separate scenes at the same time, you know; name them scene1~scene9 with scene5 being the one you're actually in and hide the rest until you're close enough to see 'em. Then just swap them and load the next ones as needed. Have to make a background loader to make it smooth, I suppose.
09/05/2013 (4:44 pm)
@Demo - it is a hell of a task, no matter how you slice it. I can see how it would be easier to gut it and go. I keep finding myself coming back to a desire to modularize the engine though - it would be nice if you could just select which terrain system to use and just plug it in, eh?I've been thinking about this on and off for a while. I started to consider loading multiple small missions in separate scenes at the same time, you know; name them scene1~scene9 with scene5 being the one you're actually in and hide the rest until you're close enough to see 'em. Then just swap them and load the next ones as needed. Have to make a background loader to make it smooth, I suppose.
#13
09/05/2013 (4:51 pm)
Yeah, I can see where you are coming from on the modularity. I don't necessarily like the existing object hierarchy either. I would love to have to object capabilities determined by script functions rather than C++ classes. So a modular object system would be excellent as well. I know someone is working on a component system so it will cool to see what comes of that.
#14
I'll admit, I haven't(yet?) looked too deeply into the larger state of affairs when it comes to core object functions, I've pretty much always worked SceneObject and down.
My ideal end goal for the component/behavior system would be to gut pretty much any actual gameplay/scene object class and just use behaviors on entities, which would include terrain, skyboxes, yada yada.
While that would definitely boost the flexibility of just about everything, that doesn't resolve the core problems that inhibit precision issues in large worlds.
I'd mulled on what Richard was talking about, with sub-mission loading, and you could probably cut down on load-lurching by doing checks on if stuff's already loaded from other zones(allowing you to skip datablock[or in the behavior system's case - templates] loading, only leaving the instance creation as your biggest down-time), but you'd still have issues with precision breaking down once it gets huge enough.
Hmm, I have the source from this one old engine that simulated - to scale - the solar system and let you freely fly between the sun, planets, etc seamlessly. I recall it did some interesting trickery with the local/global positioning to avoid the precision breakdown and I recal it staying silky smooth even if you flew from the sun to pluto(again, this was calculated in 1:1 scale as far as the sim was concerned) so I'll see if I can dredge through that to see what tricks it used.
The best bet would probably be, at a guess, doing the zonal-center approach if possible, where entering a zone re-zeroes the stuff around the client using the zone center.
09/05/2013 (5:09 pm)
Aaaand that's my cue, I think ;)I'll admit, I haven't(yet?) looked too deeply into the larger state of affairs when it comes to core object functions, I've pretty much always worked SceneObject and down.
My ideal end goal for the component/behavior system would be to gut pretty much any actual gameplay/scene object class and just use behaviors on entities, which would include terrain, skyboxes, yada yada.
While that would definitely boost the flexibility of just about everything, that doesn't resolve the core problems that inhibit precision issues in large worlds.
I'd mulled on what Richard was talking about, with sub-mission loading, and you could probably cut down on load-lurching by doing checks on if stuff's already loaded from other zones(allowing you to skip datablock[or in the behavior system's case - templates] loading, only leaving the instance creation as your biggest down-time), but you'd still have issues with precision breaking down once it gets huge enough.
Hmm, I have the source from this one old engine that simulated - to scale - the solar system and let you freely fly between the sun, planets, etc seamlessly. I recall it did some interesting trickery with the local/global positioning to avoid the precision breakdown and I recal it staying silky smooth even if you flew from the sun to pluto(again, this was calculated in 1:1 scale as far as the sim was concerned) so I'll see if I can dredge through that to see what tricks it used.
The best bet would probably be, at a guess, doing the zonal-center approach if possible, where entering a zone re-zeroes the stuff around the client using the zone center.
#15
I definitely agree with the approach of keeping areas smaller to prevent float precision issues. I would make the zone index 32/64 bit integer so that the amount of zones would be massive.
09/05/2013 (5:22 pm)
What about open worlds where you want to be able to see the other areas? Would zones help with that?I definitely agree with the approach of keeping areas smaller to prevent float precision issues. I would make the zone index 32/64 bit integer so that the amount of zones would be massive.
#16
09/05/2013 (7:08 pm)
Naw, naw - I left out the part where you swap your zones and "reset" everything (similar to your last line, Jeff). Basically, "teleport" the whole world to keep the player near the center of the coordinate space. Since the scene is already loaded just swap out which is which, move the player to the same relative point in the corresponding tile and continue (and start loading the opposite edge tiles). It would really depend on whether the swap can be made quickly enough to avoid visual artifacts. This would work far better if the camera were stationary and the world were moved around it instead - no "warping." Moving the player can be done quickly enough, it's all the other swapping that I'd be concerned about. And background loading of resources, pre-fetching, etc. to keep loading from being a huge hit on performance.
#17
Actually, that sounds rather feasible. You may still get minor hiccups, but if it's only a second or less, like in Oblivion, I don't think people would mind(as long as the zones are a decent size)
One trick could be to anticipate the approximate position of the zone when loaded by the player hitting the buffer space and loading objects into the approximate position before they even actually get there. That way you can progressively load objects by importance and size, leaving only the small clutter stuff by the time they actually hit the zone swap to re-zero everything.
I don't think the re-zero approach would really have a problem as long as you make sure to keep the respective position when the player triggers the zone load/swap.
You can definitely smartly remember the player position and rotation without having them jump when it loads, and that'd go a long way to making it feel seamless, even if under the hood it isn't. See HL2's level loads as an example.
It's loading a whole new level, but it remembers where the player is respective to the load trigger and retains that so the player doesn't feel like it's a whole new level, just loading the next chunk of the current one.
For pre-load, you could have customizable buffer zones that trigger the loading process when players enter it, and un-load when they leave it. The bigger the buffer zone the more seamless the loading of zones, but at a memory hit. But that'd let the developers tweak to get the idea effect for the targeted specs.
09/05/2013 (7:30 pm)
Richard:Actually, that sounds rather feasible. You may still get minor hiccups, but if it's only a second or less, like in Oblivion, I don't think people would mind(as long as the zones are a decent size)
One trick could be to anticipate the approximate position of the zone when loaded by the player hitting the buffer space and loading objects into the approximate position before they even actually get there. That way you can progressively load objects by importance and size, leaving only the small clutter stuff by the time they actually hit the zone swap to re-zero everything.
I don't think the re-zero approach would really have a problem as long as you make sure to keep the respective position when the player triggers the zone load/swap.
You can definitely smartly remember the player position and rotation without having them jump when it loads, and that'd go a long way to making it feel seamless, even if under the hood it isn't. See HL2's level loads as an example.
It's loading a whole new level, but it remembers where the player is respective to the load trigger and retains that so the player doesn't feel like it's a whole new level, just loading the next chunk of the current one.
For pre-load, you could have customizable buffer zones that trigger the loading process when players enter it, and un-load when they leave it. The bigger the buffer zone the more seamless the loading of zones, but at a memory hit. But that'd let the developers tweak to get the idea effect for the targeted specs.
#18
09/05/2013 (7:50 pm)
Rezeroing is a great solution, but you're still back to the start if you want to consider multiplayer.
#19
Minecraft is an interesting point of note in regards to this stuff. I was looking into it; it uses small 16-square block chunks for it's loading and keeps like 10-ish in each direction loaded as the player moves about. I was looking at how it manages the massive worlds it has, and I think it benefits from each chunk being comparatively tiny and thus quick to load.
It allows for 30 million blocks out before the world size caps(about 30 million meters) which is interesting, given that T3D has issues in the 10k range if i remember right.
T3D uses Point3F for it's position, which stems off 32 bit floats, so we should be seeing a much larger distance before it all breaks so I don't think it's exclusive to floating point error?
09/05/2013 (10:46 pm)
Yeah, it's definitely a single player solution. Great if you're making something like Skyrim. Not so great if you want to co-op it.Minecraft is an interesting point of note in regards to this stuff. I was looking into it; it uses small 16-square block chunks for it's loading and keeps like 10-ish in each direction loaded as the player moves about. I was looking at how it manages the massive worlds it has, and I think it benefits from each chunk being comparatively tiny and thus quick to load.
It allows for 30 million blocks out before the world size caps(about 30 million meters) which is interesting, given that T3D has issues in the 10k range if i remember right.
T3D uses Point3F for it's position, which stems off 32 bit floats, so we should be seeing a much larger distance before it all breaks so I don't think it's exclusive to floating point error?
#20
Perhaps moving to a 64 bit double would take care of this. I don't know.
Edit:
Actually a double won't cut it. It is what the video card uses for coordinates that matters. If it could be changed to a double it might just make things a lot easier. I have no idea of any video cards support this though. I think they assume that you should abstract the view rather than support huge high precision numbers.
09/05/2013 (11:14 pm)
The issue is that the "point" in floating point moves.// lets say you have floating point number that can handle 5 digits pos = 0.1234; // now you use this position say in the meter size // now move 10 meters pos = 10.123; // you just lost the last digit of precision // now move 100 meters pos = 110.12; // lost another digit // now 1000 pos = 1110.1; // now at best I can represent 1/10 of a meter // now my movements are jittery
Perhaps moving to a 64 bit double would take care of this. I don't know.
Edit:
Actually a double won't cut it. It is what the video card uses for coordinates that matters. If it could be changed to a double it might just make things a lot easier. I have no idea of any video cards support this though. I think they assume that you should abstract the view rather than support huge high precision numbers.
Torque Owner Richard Ranft
Roostertail Games
The down side to that is this - how do you make that work in a multiplayer game? On some level the server has to have the whole world in memory (even if it's only the collision shapes) to be able to tell where the clients are in relation to each other....