Request for comments on large world FAQ

Miscellaneous Forums/General Discussion/Request for comments on large world FAQ

This is an attempt to answer some recurring questions as well as give people some practical understanding on how to circumvent the limitations of a 3D engine.

I'd like some feedback on this, particularly with regard to my understanding of and explanation of the problems.

Please note that the part on DRM isn't finished yet, so just concentrate on the first part.


Andy





The issues with B3D

When trying to create large worlds in B3D you will encounter several issues
which must be solved in order to create a credible large world.

1) Z buffer issues:
The Z-buffer in B3D has a predefined word-size in which to represent the
range you set with the CameraRange command. As the difference between
Near# and Far# grows, the same number of bit's must represent a larger
range and thus precission suffers.

This means that as you increase the difference between the Near# and Far#
in your CameraRange command, you will experience that entities which are in
view will seem to be melted together or fight over the same place. This
happens because the Z buffer cannot differentiate between an entity placed
at 50000 and 51000. To the Z-buffer they are at the same place.

Basically, things which are further away is drawn on top of things which are
closer. This is because far away things may be so close to each other, that
the lack of z-buffer accuracy makes them appear to be at the same place.

2) Floating point inaccuracies:
Floating point math is inherently imprecise, so when you write 5.0000. The
computer will represent it as approximately 5.0000.

This means that as you get further away from the centre of your 3D
coordinate system, entities will start to jump around. Again, the
larger the numbers get, the less precise the position is.

Basically, 3D coordinates in B3D are only correct to 6 digits, meaning that when
you get far away from the center of your world, everything is just a little
bit away from where it should be, and when you try moving it somewhere, it
will seem to jump around.


What is the solution

When refering to entities in the following, I am really refering to 2 different
kinds of entities. The immovable entities like mesh terrain and buildings, and
moveable entities like vehicles, projectiles etc. I refer to the former as
static entities and refer to the latter as free entities.


Floating Point Inaccuracies:

Floating Point Inaccuracies can be rectified by normalizing your cameras
position every once in a while... If you are at 10000,10000,10000, then you
simply move everything -10000,-10000,-10000, so that the camera is now at 0,0,0.
This way everything stays where it is in relation to each other, but is moved
closer to the origo.

1) Low number of total entities:
If the static entitycount is low, then you can simply move every entity in a
loop(both static and free). This is a simple and instant fix that can be
applied well into the development of a game. I've included Exhibit A to give
you an idea of how this may be done.

2) medium to large number of static entities:
If you have a medium to large number of entities, you will need to attach every
static entity to a pivot and simply move the pivot instead of every entity. Then
you move the free entities in a loop.

The pivot also suffers from Floating Point inaccuracy problems, so to make this
concept useful in a large world, you will have to normalize the static entities
position to the pivot and the pivots position to the cetre of the coordinate
system regularly, but when you do, you are never again limited with regard to
the size of you world.


Z-Buffer inaccuracy:

Z-Buffer inaccuracy can be solved in several ways. You can calculate the largest
distance needed and adjust the Near# and Far# values using the CameraRange command
regularly.

Another way is to render every frame with different sets of Near# and Far# values.
The problem with this is that while it increases accuracy, it does so while
sacrificing speed as you basically render every frame twice. I've included
Exhibit B to give you an idea of how this may be done.


Dynamic Resource Management

For small worlds, you can usually keep the entire map in memory, but for
medium and large sized worlds you will need DRM.

Basically, DRM is any system which will manage the resources used by your programme.
This is done by loading and deleting entities, triangles, vertices, textures or
data on the fly.







Exhibit A:
;***********************************************************'
; Call housekeeping from your main loop
;***********************************************************'
num_ent=10 ; number of entities
dim mesh(num_ent)
fieldsize=5000


.housekeeping
mx = 0.0
my = 0.0
mz = 0.0
If EntityX(player_pivot)>5000 Then
PositionEntity player_pivot,EntityX(player_pivot)-fieldsize,EntityY(player_pivot),EntityZ(player_pivot)
mx = -fieldsize : my = 0.0 : mz = 0.0

EndIf

If EntityZ(player_pivot)>5000 Then
PositionEntity player_pivot,EntityX(player_pivot),EntityY(player_pivot),EntityZ(player_pivot)-fieldsize
mx = 0.0 : my = 0.0 : mz = -fieldsize
EndIf

If EntityX(player_pivot)<-5000 Then
PositionEntity player_pivot,EntityX(player_pivot)+fieldsize,EntityY(player_pivot),EntityZ(player_pivot)
mx = fieldsize : my = 0.0 : mz = 0.0
EndIf

If EntityZ(player_pivot)<-5000 Then
PositionEntity player_pivot,EntityX(player_pivot),EntityY(player_pivot),EntityZ(player_pivot)+fieldsize
mx = 0.0 : my = 0.0 : mz = fieldsize
EndIf

For q = 1 To num_ent
MoveEntity mesh(q),mx,my,mz
Next
Return
;*******************************************************





Exhibit B
;***********************************************************'
; Replace your regular RenderWorld with this
;*******************************************************
near#=1.0
intermediate#=5000.0
far#=1000000.0

;far
CameraRange cam,intermediate#,far#
CameraClsMode cam,1,1
RenderWorld frameTween

;near
CameraRange cam,near#,intermediate#+500
CameraClsMode cam,0,1
RenderWorld frameTween
;*******************************************************




About z-buffer:

Remember also that z-buffer is non-linear... and that you can use w-buffer instead of z-buffer in Blitz3D:

http://www.blitzbasic.com/b3ddocs/command.php?name=WBuffer&ref=3d_cat


Description:
Enables or disables w-buffering.

W-buffering is a technique used to draw 3D object in order of their depth - i.e. the ones furthest away from the camera first, then the ones closer to the camera, and so on.

Normally, z-buffering is used to perform such a technique, but a z-buffer can be slightly inaccurate in 16-bit colour mode, for which the level of precision is less than in 24-bit or 32-bit colour modes. This means that in some situations, objects will appear to overlap each other when they shouldn't and so on.

To compensate for this, you can use w-buffering. This is a slightly more accurate technique than z-buffering, although it may be less compatible on some set-ups than z-buffering.



read this article for better understanding about z-buffer and when to use it and when to use w-buffer:

http://www.extremetech.com/article2/0,1697,1171859,00.asp

Also other ways around z-buffer inaccuracy is to dynamically scale and translate objects closer to the camera (ie move them within smaller CameraRange) - scaling makes them keep their visual look intact, ie like they would be farther away than the are. This works well in space simulators where the distances are great but all objects float in empty space. As you can't scale terrain for example it the above technique won't work with it.

you can get around the z buffer issues by moving the world instead of the player, this way the player stays at 0, 0, 0 hence no zbuffer issues.

Hey, this is a good thread - keep it coming!

>Also other ways around z-buffer inaccuracy is to
>dynamically scale and translate objects closer to the
>camera (ie move them within smaller CameraRange) - scaling
>makes them keep their visual look intact, ie like they
>would be farther away than the are.

Agreed, but I would assume that different cameraFOV settings would influence the calculation?! Can you recommend a formula?

>you can get around the z buffer issues by moving the world
>instead of the player, this way the player stays at 0, 0,
>0 hence no zbuffer issues.

No, that would get around the floating point inaccuracy but the Z-buffer problems are still there. This is basically what parenting the static entities to a pivot achieves.

If you simply move the pivot all of the time instead of moving the camera you wil run into problems when the numbers start getting big enough or you start tilting your camera or use collisions.


Andy

Even Oblivion has problem with mesh and objects.
Many times Martin falls throu mesh and dies in fire. but as soon as he is out of range he recover.

Well, people said that about Morrowind - I never experienced it in either game. I still wonder if it relates to graphics cards.

Essential z-buffer reading:
http://www.sjbaker.org/steve/omniv/love_your_z_buffer.html