Coordinate Issues with CDLOD and Voxels

Started by
6 comments, last by Krohm 11 years, 10 months ago
Hello. So I have a planetary rendering system set up that uses chunked LOD. I want to be able to switch to voxel rendering when the player gets close enough to the surface(when this happens, i will be generating the voxels using noise, and will disregard the chunked LOD tree). However, when thinking about this I don't see a good way to "switch" coordinate systems from CDLOD to voxels for rendering. The planet is rendered on a unit cube of [-1,1], so the vertices on the surface are very small. And I need the voxels to be stored in normal whole units(1,1,1) etc. because when you are at the surface of the planet you are already running out of floating point percision, so there is no way you have enough precision to store all the individual voxels in a volume. Any ideas? I hope I have explained the problem and what I am trying to do enough. Thanks.
Advertisement
Noise does not need to be stored at all, it's a spatial function with deterministic results, and it's probably fast enough to be evaluated per-vertex nowadays on even rock-bottom hardware. It used to be stored because of performance and compatibility concerns on old hardware. Anyway...

So you have this -1...1 cube and you want to have basically little boxes where you kick in more detailed LOD.
Let's say this cube is -1000,1000 for easiness of writing (and think in 2D for easiness).
How big are those boxes? Let's say you want to split the world so each little box covers 2x2. So you would have 500x500 boxes.
When you are outside of that boxes, render stuff normally. When you hit a box, consider it as point+(u,v)

^ +----+
| + +
| v direction + +
| + +
u direction
----->

So when you hit a box, you know "the lower left corner" of the box which you consider origin of your coordinate system. You also know, by construction, u and v directions where (lower left + uv = upper right). We assume them orthorormal by construction. This is the new coordinate system to use for noise eval.

Previously "Krohm"

The problem is that this doesn't seem to allow for digging. Imagine a unit cube, where each face of the cube is normalized to a unit sphere. If I am on the TOP LEFT corner of the front face and the TOP RIGHT corner of the left face, and I dig down one, what happens? You dug to the same place., which is why I was thinking I need some other kind of system. I was thinking of something like having another cube that is my voxel volume and generating a sphere of voxels in that cubic volume, and then somehow translating this properly to the unit sphere coordinates, so when you enter the atmosphere at a mountain from the unit sphere, it will be at the right place in the voxel volume.
I think I don't get your problem. But I'm sincerely interested in elaborating this as I look forward to implement some very large terrain system myself so...
Here is our cube, with its origin and its (xyz) vectors - previously called uv - which we assume unit length for easiness. Given the [font=courier new,courier,monospace]origin = spatial(x,y,z)[/font], the marked point will be at [font=courier new,courier,monospace]spatial(marked = origin + cube.z * TERRAIN_CHUNK_DIMENSIONS.z)[/font].
[attachment=9144:cube-annotated.png]
Those cubes somehow "discretize" the surface. We also add additional cubes for the interior (I don't think this is relevant).

This is its formulation in the spatial coordinate system. However, when we hit a box we transform the point in the interior coordinate system by using the generators. In this internal coordinate system [font=courier new,courier,monospace]origin = internal(0,0,0)[/font] and [font=courier new,courier,monospace]marked = origin + {0,0,1024}[/font], where 1024 is a nice number to have a nice range. In general, let's call 1024 [font=courier new,courier,monospace]TERRAIN_CHUNK_INTERNAL_RANGE.z[/font], it does not have to be the same value as [font=courier new,courier,monospace]TERRAIN_CHUNK_DIMENSIONS.z.[/font]

So we are just right in the box, at [font=courier new,courier,monospace]internal(marked - {0,0,EPSILON})[/font]. And... what's the problem with moving down a tick?
In spatial coordinates: [font=courier new,courier,monospace]spatial(dug = BROKE)[/font] - cannot be represented because of (assumed) FP inaccuracies, might be [font=courier new,courier,monospace]spatial(marked)[/font] or [font=courier new,courier,monospace]spatial(origin)[/font] or another value with insufficient granularity, likely giving a bigger movement that the intended "move down tick".
In internal coordinates: [font=courier new,courier,monospace]internal(dug[/font][font=courier new,courier,monospace] = marked - {0,0,EPSILON} - z * downStepHeight)[/font].

Of couse the tick won't have to be the same tick as in spatial mode.

And what's the deal with those unit spheres? How do you fill the gaps? And how do they solve the FP accuracy problem of having [font=courier new,courier,monospace]{xyz}+{EPS,EPS,EPS}=={xyz}[/font] being true for some sufficiently small nonzero EPS in spatial coordinate system?

I don't understand.

Previously "Krohm"

They don't solve the problem of FP accuracy. Using a unit cube you can only represent so many splits accurately(with chunked LOD). I do like your idea though. To apply this to a unit cube, I wonder if it'd be possible to have a vertice point on the face of the cube represent a voxel volume with its own internal coordinate system like the one you showed.
No they don't solve the FP accuracy problem when transitioning from spatial to internal coordinates.
Please note that the issue is far less problematic: when transitioning, we don't have to accurately represent the position with the same precision of the internal mesh, but only to a point where we don't introduce visible popping. Hopefully that would be a few orders or magnitude.

The main problem is in computing the relative displacement from the origin. The spatial boxes to hit must be "large" in spatial coordinates, and even this does not completely save us. But, if we build a discrete lattice, perhaps a modulo operation would fix that.

They DO solve it when navigating internally because what happens is that you change what your bits mean... that's the whole point of the values [font=courier new,courier,monospace]TERRAIN_CHUNK_INTERNAL_RANGE [/font]and [font=courier new,courier,monospace]TERRAIN_CHUNK_DIMENSIONS[/font].
In other terms, supposing we want the player to move at constant speed (which is nonsense) the speed when navigating in spatial mode would be - say 1 - and much higher when in internal mode say 1024 or more.

In "spatial" coordinates when you do
float x = 125.0f;
You might mean 125 amstrongs or kilometers or whatever.
The same number in internal coordinates could be meters.

But again, since I'm interested in this, I would appreciate if you could elaborate on your concerns.

Previously "Krohm"

Well, with the unit cube, as you divide, each chunk is 1/4 the size of the parent. So as you go deep enough, the coordinates of each vertice are extremely small, and you begin to have FP precision issues. Since I want to be able to render voxels when I am at this extremely small level, I need to be able to place many voxels at these small coordinates. However, I thought that this would be a problem since I already have FP precision issues when I am very close to the surface. So I was trying to think of a way to represent tons of voxel coordinates when dealing with FP issues at this zoomed in level.
I'm sorry dude, I don't understand what you're trying to say. I guess I'll have to give up at that point...

Previously "Krohm"

This topic is closed to new replies.

Advertisement