cheap LOD level selection function

Started by
5 comments, last by Darragh 14 years, 3 months ago
Hi! can someone tell me a cheap function to select a LOD level which bases on square distance but also camera angle? currently I transform two worldpsacepoints using the current modelview and projection matrix to get the onscreen size and pick LOD level by this, but probably there's a cheaper function which also takes camera FOV angle into account and doesn't need two full matrix vector multiplications? thanks!
Advertisement
DirectionToCamera = ObjectPosition - CameraPosition;
DistanceToCamera = Magnitude (or) Length(DirectionToCamera)
Normalize(DirectionToCamera);

d will be 1.0 if it is directly in front of the camera
0.0 is likely _well_ outside of the FOV, you might need/want to precompute the "min" here by taking doing a DotProduct with something defining the minimum value d can be while still being in view. If you do not precompute that and just use 0 as the minPossibleD, then you can remove that code that computes D into a more accurate range.
float d = DotProduct(DirectionToCamera, CameraForward);

//Get 'd' into a more accurate range of FoV. (Can be skipped)
float minPossibleD; //this would be precomputed somehow. Possibly set to zero for simplicity, as that could work well too.
float range = 1.0f - minPossibleD;
float viewImportance = (d - minPossibleD) / range; //0.0f to 1.0f
//If the above was skipped viewImportance = d;

//Use DistanceToCamera to do your LoD selection for distance.
//Use viewImportance to do your LoD selection based on FoV angle. 1 is centered. 0.0 is Out of view (either just, or completely depending on implementation).

-I think that helps? Good luck.
Hey and thanks for your answer

maybe i was not clear enough about this. It doesn't matter whether it's centered, on the edge of the screen or off screen or whatever.

a LOD level should be chosen by the size the object appears on screen. But the size doesn't depend only on distance to the camera, but also on the current camera angle (for example one could zoom onto an object by decreasing the camera angle - then a higher resolution LOD level should be accessed, because the object appears larger on screen).

i'm searching for a cheap function that returns a value somewhat linear to the diameter (or maybe area) the object will take on screen.
Quote:Original post by genesys
a LOD level should be chosen by the size the object appears on screen. But the size doesn't depend only on distance to the camera, but also on the current camera angle (for example one could zoom onto an object by decreasing the camera angle - then a higher resolution LOD level should be accessed, because the object appears larger on screen).


Perhaps you could create an oriented bounding box to approximate the object's volume. Once you have that you could project the box into screen space and compute the area of the screen that the box occupies by decomposing the box polygons into triangles. Backface culling would also be necessary for such an approach since otherwise you would get overlap and this might mess up your area calculations. You'd also have to adjust based on resolution (or perhaps not, lower-res = no need for higher detail at long distances?) so perhaps some sort of percentage based comparison would be required.

As for clipping the projected triangles, I'm not sure if that would be desireable. Even if only a small part of the object was visible at the sides of the screen (but the object is close) then it should still be at a high LOD or otherwise you would get very noticeable jumps in LOD when the user rotates the camera.
Assuming spherical volume, a reasonable approximation:

#pixels = π(object radius)2*(x resolution)*(y resolution)/(4*tan(fovx/2)*tan(fovy/2)*((eye vector)·(object vector))2)
@darragh:

i already do something like this. i have the boundingsphere and i create two points at either side of the object (seen from the camera direction) and transform those two points into screenspace and measure distance.

But this requires one matrixmatrix multiplication (for getting the modelviewprojection) and two matrix-vector multiplication as well as one squareroot. i was looking for something cheaper since i have hundrets of objects. it's not directly my bottleneck, but it's part of it so i try to optimize it.
Quote:Original post by genesys
@darragh:

i already do something like this. i have the boundingsphere and i create two points at either side of the object (seen from the camera direction) and transform those two points into screenspace and measure distance.

But this requires one matrixmatrix multiplication (for getting the modelviewprojection) and two matrix-vector multiplication as well as one squareroot. i was looking for something cheaper since i have hundrets of objects. it's not directly my bottleneck, but it's part of it so i try to optimize it.


It doesn't get much cheaper than that I'm afraid, unless of course you want to use simple distance (or squared distance?) to the camera as a measure of when to pick an LOD.

Are you really sure this is a bottleneck in your application? 100's of matrix multiplications doesn't really sound like something that would bring an app to a standstill- modern hardware should be fast enough to handle that even if you are not using clever stuff like SSE. Thousands or even 10s of thousands of multiplies might be an issue, but not hundreds..

If it is an issue however I guess you could cut down on the matrix multiplies by not bothering to combine the view/projection matrix with the world matrix- simply transform the two points by the world matrix and again by the matrix which projects into screen space. This way you would be doing four matrix-vector multiplies but no matrix-matrix multiplies which should be much cheaper.

This topic is closed to new replies.

Advertisement