problem with render in far distances

Blitz3D Forums/Blitz3D Programming/problem with render in far distances

Santiworld(Posted 2010) [#1]
hello, I'm having trouble with the precision that controls the position of the vertices at large distances from 0,0,0.

I'm doing a strategy game, where the stage is 65x65 km wide,
when I distanced the camera from 0,0,0 point. I lose precision in the rendering position vertices.

I need large distances in the game, in the image i put a human and a cube created with CREATECUBE() function, to show the human scale i use.



please, see the video, and tell me if this problem have any solution.

the soldier in the video, is at x: -200000 and z: -2000000

YOUTUBE VIDEO LINK showing the problem:
http://www.youtube.com/user/santiworld#p/a/u/0/Oge-wQlp-co

regards, Santiago.



i made this sample to show how shake a simple cube


Graphics3D 800,600,0,2

plane = CreatePlane()
EntityColor plane,100,200,100


cube = CreateCube()
EntityColor cube,255,100,0
PositionEntity cube,-200000,1,-200000
cam = CreateCamera(cube)
MoveEntity cam,3,2,2

light = CreateLight(1)
TurnEntity light,70,70,70


While Not KeyHit(1)
	
	MoveEntity cam,.031,0,0
	PointEntity cam,cube
	
	
	UpdateWorld()
	RenderWorld()
	
	Text 10,10,"CUBE POSITION :    x = -200000     y = 1    z = -200000"
	Text 10,30,"SHAKE"
	Flip
	
Wend


End



Paolo(Posted 2010) [#2]
First,
after creating the camera add this to your code
and see if the problem still there
CameraRange cam,1,100

Second,
test your demo, but without starting the animation of your character,
and see if the problem still there


Santiworld(Posted 2010) [#3]
hi, yes, i have camerarange,1,10000

and i test with 1,100 1,1000 and 1,100000, but the problem is not the camerarange.

all objects shake at that distance from 0,0,0, i read in the forum that this no have solution...

in the demo i post, the cube shake too, maibe the only solution is reduce de worldmap dimension

:(


Jiffy(Posted 2010) [#4]
You can't do this. Floating point numbers lose accuracy at this size in blitz. You can make everything 10 or 100x smaller (including your move increments & such) that way you avoid the 'inacurate range' of 70,000+ but other than that, it's math.


Paolo(Posted 2010) [#5]
I don't know if I understand you well,

but I think the problem is that you are having polygons too close to each others in your character and the camera won't have enough precision to render correctly in far distances.
You should optimize your character a little bit, try to make it as "single-mesh" as possible and reduce the poly-count.

... and also, what Jiffy said ... :)


Gabriel(Posted 2010) [#6]
Floating point numbers lose accuracy at this size in blitz.

They lose accuracy at this size, period. It's not related to Blitz.

A single precision floating point value has between 5 and 7 digits of "accuracy". Not all values in that range can be exactly stored in a 32 bit float, but a reasonable degree of accuracy can be maintained. When you're using up six of those digits before the decimal point (as in the cube example, with 200,000) you only have one digit left, so of course, things are not very accurate.

Reduce the scale. Or keep the camera near the origin and move everything else around it. There are solutions but you're going to have to think creatively because there is no easy, painless solution.


puki(Posted 2010) [#7]
I always use 1 Blitz unit=1 metre - ie a cube is 2 metres tall. Some people micro-scale under this to make things smaller.


Jiffy(Posted 2010) [#8]
Why don't you tell him to declare his floating point variables as doubles? Oh- right. No doubles.
There are no doubles in blitz, really?
Ah- so it is 'related to' blitz... They do not "lose accuracy at this size, period."- unless you are limited to single precision- like in blitz.


PowerPC603(Posted 2010) [#9]
If you're moving the camera that far out, create one master pivot to which your entire world is parented.

Then if your camera is over 1000 units from the center of the world, move the master pivot the opposite way.

Example:
Move your camera forwards via the Z-axis.
If the global camera position in the Z-direction is over 1000 units, move the master-pivot -1000 units in the Z-direction.
Then your camera should be globally back in the center of the 3D-world, but as the scenery moves too, your camera should still be at the same position in your scenery.



In the next example, every entity in the world is parented to a masterpivot.
The cube moves via the X-axis through the world and the camera follows the cube.
Every 1000 units in the X-direction is a cylinder, so you can actually see that you're moving through the world as you pass the cylinders.

Every time your camera is over 1000 units in the X-direction, the masterpivot moves -1000 units in the X-direction.
This moves the entire world -1000 units in the X-direction, including the camera.

This way, you can create endless worlds and never see any inaccuracies, because you're rendering it all near the center of the 3D world.

Graphics3D 800,600,0,2

plane = CreatePlane()
EntityColor plane,100,200,100

Global masterpivot = CreatePivot()

Global cube = CreateCube(masterpivot)
EntityColor cube, 255, 100, 0
PositionEntity cube, 20, 1, 0

Global cam = CreateCamera(cube)
MoveEntity cam,-3,2,2

light = CreateLight(1, masterpivot)
TurnEntity light,70,70,70

; Create some cylinders somewhere in the scenery to show that you're actually moving through the scenery
For i = 1 To 100
	cyl = CreateCylinder()
	ScaleEntity cyl, 5, 5, 5
	EntityColor cyl, 0, 0, 255
	PositionEntity cyl, i * 1000, 0, -10
	EntityParent cyl, masterpivot
Next

While Not KeyHit(1)
	MoveEntity cube, 10,0,0
	PointEntity cam,cube

	If EntityX#(cam, True) > 1000.0 Then
		TranslateEntity masterpivot, -1000, 0, 0
	EndIf

	UpdateWorld()
	RenderWorld()

	Text 10, 10, "Camera-position: " + EntityX#(cam, True)
	Text 10, 30, "Masterpivot position: " + EntityX#(masterpivot, True)

	Flip
Wend


End



Zethrax(Posted 2010) [#10]
As far as I'm aware, changing the scale of the world won't help. You still end up dealing with the same number of distance values to count using the limited resolution of a 32 bit float, so you're basically just scaling the problem to fit the solution.

A paged approach is the best one to adopt.

Each update, check if the camera has strayed beyond a particular distance from the world center (just check it along the X, Y, and Z axiis - no need for a precise distance check), and if it has, move all the entities in the world so that the camera ends up back at the world center (get the X, Y, Z distance of the camera from the world center; negate these values (eg. x = -x) and move all the entities in the world relatively by the resulting amounts).

If you need to use the original world center as a reference value for map displays, etc, then just create a pivot at the world center when you start the game level, and use that as your reference instead.

It's probably best to avoid the temptation to just parent everything to a pivot and move the pivot back to the world center to avoid moving your world items individually. You may just end up with the same float precision issues that are relative to the pivot instead of the global world center.

EDIT: It's probably best to time test different paging systems to see how much time they take to update. Some systems may cause slowdowns due to collision geometry sort trees getting re-organized, etc.


PowerPC603(Posted 2010) [#11]
In my example, when I comment the line "TranslateEntity masterpivot, -1000, 0, 0" and move beyond 100K (100.000) units, the cube begins to shake and shakes heavier when going further from the world center.

When the line is there (not commented), I got up to 10M (10.000.000) units and didn't see any shaking at all. (I didn't go further)


Jiffy(Posted 2010) [#12]
Cool. Yeah, BIll- I think you're right. It seemed like a good idea, though... :P


Gabriel(Posted 2010) [#13]
Why don't you tell him to declare his floating point variables as doubles?

I don't tell him that because DirectX uses single precision floats internally anyway, meaning that you what you use is irrelevant.


kalix(Posted 2010) [#14]
ya i had that problem too ...
first i did just what bill said. and then when i moved to the sdk i just started using doubles!
i only use blitz for what i need too SEE right now.
everything else works in the background.


Jiffy(Posted 2010) [#15]
Of course it's irrelevant. We don't have them.
If we did, it would be up to Mark to do clever manipulations behind the code to keep things good- like the code Bill wrote being made transparent to the system. Programmers use doubles like they want, the system does the gruntwork- transparent to the user.
Maybe that's not the way to go, but I'm sure something can work. If you really see limitations that way, well- maybe that word doesn't mean what you think it does.


Jiffy(Posted 2010) [#16]
kalix,
So using doubles works as a solution in the SDK?


Gabriel(Posted 2010) [#17]
Of course it's irrelevant. We don't have them.

No, it's irrelevant because having them wouldn't make any difference. Feel free to continue grouching and grumbling though. Maybe if you keep going long enough we can find a way to make the facts fit the argument you want to make.


puki(Posted 2010) [#18]
There is a lib or something that allows Blitz3D to use doubles though - just in case anyone wants to use them.


Ross C(Posted 2010) [#19]
Or, change the camera near range, and scale down the world slightyly?

If it's a problem with rendering accuracy with the z-buffer, do multiple renders.

Set CameraRange to 600,60000
Render
Set CameraRange to 0.6 to 600
Render, but don't clear the buffer

That way you get as much precision as you need, at the (small) expense of multiple renders. You won't really be rendering anyone polygons though, which is nice.


MadJack(Posted 2010) [#20]
On a side note, I also found blitz native collisions became a bit patchy on levels larger than 4096x4096 units size - particularly on objects intersecting largish polys...


Jiffy(Posted 2010) [#21]
@Puki yeah- seen it. It's a little awkward to use, to say the least. But if that's what you need- it gets the job done.

@Ross- no, it's a problem with singles only having five places of precision, so way way out putting something at any 'specific' point puts it at an 'approximately accurate-ish' point, which may or may not change when you add a small value- and then will eventually do so in apparent leaps and bounds.

@madjack- yeah, blitz collisions could use an overhaul for sure. Never happen, but it is one of the most wonky features in blitz. Better than nothing, though.

[keeping the peace]


Zethrax(Posted 2010) [#22]
Kids, take a few deep breaths and settle down.

Let's not disrespect Santiworld's post by turning it into an unproductive snipe-fest.


Jiffy(Posted 2010) [#23]
I sorry... (pout)


Ross C(Posted 2010) [#24]
Sorry, i didn't read the initial post properly. Moving the camera would be the right way to go :)


Santiworld(Posted 2010) [#25]
Hi!.

i read the answers many times to understand propertly...

i have these conclusions

1. make a masterpivot and move all world to maintain the camera near of 0,0,0 (*)
2. changing the scale of the world won't help. because the proportion is the same distance<->acurrancy?

(*) - i'm trying to think, what problems can i have if i translate all objects to stay near the 0,0,0?
in the game i have objects parent to other objects, like a helicopter in the carrier deck, i only have to translate the carrier, and all parent to it, is automaticaly moved.
i'm using spritecandy for explotions, i'm sure that i can move the spritecandy objects without problems.
i think that is the correct solution, now i need to try to apply this in the game to see what happens.


Ross C(Posted 2010) [#26]
As long as everything that is created, is parented to a world pivot, it should all be fine, and don't take your positions globally, and use them relative to each other, to gauge distances for instance.

You probably should have an offset value for everything, if you need to know the global co-ords of anything. Just take your offset value as your world pivots X,Y,Z co-ords.


Kryzon(Posted 2010) [#27]
(*) - i'm trying to think, what problems can i have if i translate all objects to stay near the 0,0,0?


I think the biggest "problem" would be applying transformations for every entity in the game except the camera, every frame.

That probably will cause an impact on performance, and that's the reason it has been suggested here to do it sparingly, maybe every other second (doesn't matter the time much, since the transition will be unnoticeable if you do it the right way).


Rroff(Posted 2010) [#28]
IMO moving the entire world on anything but the most simple game is going to have severe performance, collision detection issues and other bugs...

Playing with the scaling can be a bit of a balancing act as well as you can end up moving the problem to warping textures when viewed closeup instead.


kalix(Posted 2010) [#29]
ross c: your still using only ONE single ! and if you try to move something far from the camera you still cant!
aka: if you put out an object at x:9999999 and try to add 0.1(to move it)
NOTHING WILL HAPPEN!

doubles do help coz the i end up with moving everything according to camera:

bb.PositionEntity(ent, (float)(x - Camera.cam.x), (float)(y - Camera.cam.y), (float)(z - Camera.cam.z), 1);

(if you can read c#)

i still did it in blitz 3d with 2 singles(floats).
think of what bill said only with 2 numbers!
you move one number constantly and every 1000 from canter(or 100 frames or whatever) you put that value into the other number and reset the first one!

i sounds heavy but not so mach!
i tryed it with a 1000 ships and it still run!(at about 25fps+)


Ross C(Posted 2010) [#30]
Yep, i did correct myself in my next post. However, the method of multiple rendering, is a good technique for eliminating z-fighting, if the z-buffer doesn't have enough accuracy.


Santiworld(Posted 2010) [#31]
i have a question...


if i use this masterpivot, maybe there is a problem in the objects than have a very far position of camera.

the camera stay near of 0,0,0 world.

but if i have a object (vehicle or palmtree, etc..) in the x = 250000, the object go to change the position because there is no way to save the exactly X position.

in theory, the objects position going to change if they are in big far X,Z position.

in that moment, i can't see the objects, but when i move the camera near to this objects, the position will be the same?

this theory is correct?

(sorry my english)


kalix(Posted 2010) [#32]
test it!


Ross C(Posted 2010) [#33]
Well, don't display objects that are reaaaally far away. If you do, they will not doubt shake until they get a decent accuracy.


MadJack(Posted 2010) [#34]
Sorry if this is a dumb idea - but could you split the world into two scenes with different scales? In other words, the near scene uses a standard 1:1 scale but the 'far' scene uses a 1:10 scale. In other words as an object moves beyond the near scene's boundary, it gets moved to the far scene and resized smaller and moves slower in real terms.

The trick is that when it comes time to rendering these two scenes, the far scene is rendered first with a higher camerazoom to account for the smaller real scale, and then a second render is overlayed of the near scene to produce the final frame.


However I could see that handling events happening at the boundary between the two scenes could be a problem...