PDA

View Full Version : constant number of objects on screen - frustum



arctbl
02-27-2009, 12:21 PM
Hi
I am trying write a little program that displays a constant number of object in the view area at all times (currently point objects). I am using a frustum class that gives me the important view coordinates (it
is mostly from the Lighthouse View Frustum Culling Tutorial (http://www.lighthouse3d.com/opengl/viewfrustum/index.php)). It seems like it should be easy but the view remains splotchy with objects constantly blinking (being added to random positions) on screen.

Does anyone have any ideas?

Below is the function I use to redraw the objects. I can attach the rest of the application if it would help.

void cstarfield::weMove()

{
camera.MoveForward(g_speed);//forward is -z

camera.Render();//needs to be here for frustum
lftl = camera.ftl; lfbl=camera.fbl; lfbr=camera.fbr; lftr=camera.ftr;

lntl = camera.ntl; lnbl=camera.nbl; lnbr=camera.fbr; lntr=camera.ftr;



for ( int i = 0; i < NUM_STARS; i++ )

{

glPushMatrix();

glTranslatef( g_xyz[i][0], g_xyz[i][1], g_xyz[i][2] );

if (g_color==GL_TRUE)

glColor3fv( g_colors[i] );

else

glColor3f( 255,255,255);

glPointSize(g_pointsize); //sets the pixel size of the points

glBegin(GL_POINTS); // render with points

glVertex2i(0,0); //display a point at current x,y,z

glEnd();

glPopMatrix();



GLfloat lowest, highest, range;

GLfloat tmp;



Vec3 a( g_xyz[i][0], g_xyz[i][1], g_xyz[i][2] );
enum {TOP=0, BOTTOM,LEFT,RIGHT,NEARP,FARP};

if (camera.pointInFrustum(a) == CCamera::OUTSIDE)

//if star is outside of frustum then recalc to somewhere inside ...

{

GLfloat dn,df,dl,dr,dt,db, td;
dn=camera.pl[NEARP].distance(a);
df=camera.pl[FARP].distance(a);
dl=camera.pl[LEFT].distance(a);
dr=camera.pl[RIGHT].distance(a);
dt=camera.pl[TOP].distance(a);
db=camera.pl[BOTTOM].distance(a);

if (dl<0)
if (camera.ftl.x<camera.ftr.x)
g_xyz[i][0] = g_xyz[i][0]-dr;
else
g_xyz[i][0] = g_xyz[i][0]+dr;
if (dr<0)
if (camera.ftl.x<camera.ftr.x)
g_xyz[i][0] = g_xyz[i][0]+dl;
else
g_xyz[i][0] = g_xyz[i][0]-dl;
if (dt<0)
if (camera.ftl.y>camera.fbl.y)
g_xyz[i][1] = g_xyz[i][1]-db;
else
g_xyz[i][1] = g_xyz[i][1]+db;
if (db<0)
if (camera.ftl.y>camera.fbl.y)
g_xyz[i][1] = g_xyz[i][1]+dt;
else
g_xyz[i][1] = g_xyz[i][1]-dt;
if (df<0)
if (camera.ftl.z>camera.ntl.z)
g_xyz[i][2] = g_xyz[i][2]-dn;
else
g_xyz[i][2] = g_xyz[i][2]+dn;
if (dn<0)
if (camera.ftl.z>camera.ntl.z)
g_xyz[i][2] = g_xyz[i][2]-df;
else
g_xyz[i][2] = g_xyz[i][2]+df;

Vec3 d(g_xyz[i][0], g_xyz[i][1], g_xyz[i][2]);
if (camera.pointInFrustum(d) == CCamera::OUTSIDE)

{

lowest=dl; highest=dr;

if (lowest> highest){tmp=lowest;lowest=highest;highest=tmp; }

range=(highest-lowest)+1;

g_xyz[i][0] = lowest+int(range*rand()/(RAND_MAX + 1.0));

lowest=db; highest=dt;

if (lowest> highest){tmp=lowest;lowest=highest;highest=tmp; }

range=(highest-lowest)+1;

g_xyz[i][1] = lowest+int(range*rand()/(RAND_MAX + 1.0));


lowest=dn; highest=df;

if (lowest> highest){tmp=lowest;lowest=highest;highest=tmp; }

range=(highest-lowest)+1;

g_xyz[i][2] = lowest+int(range*rand()/(RAND_MAX + 1.0));

}
}

Brolingstanz
02-27-2009, 10:41 PM
For a starfield think about griding your universe into cubes, such that for any view only a few actually intersect the view volume; of those, render the points contained within (or use its origin as a basis/seed for loading/generating a new batch). Use alpha blending as a function of distance to fade the points in and out as they move relative to camera to avoid the blinking effect.

The frustum culling described in that tutorial is for coarse level scene object culling, not for stars, snowflakes, raindrops, etc ;-) Generally speaking it's a bad idea to spend time on scene culling when the rendering would be faster than the test itself.

scratt
02-28-2009, 01:13 AM
As modus says for what you are doing culling is probably a wasted overhead.

I have multiple Galaxies in a sim I am working on now with literally 100s of thousands of stars drawn as PointSprites in each of them. Each 'star' is textured and dynamically sized based on distance. My viewpoint is always inside one galaxy, or at least close to one, which I draw *all the time*. i.e I send it to the GPU every frame. I let the GPU decide what to draw and not to draw in that group. I could, if I wanted to, divide each galaxy into a grid, or Octree, and cull it in sections around the viewpoint also. But I have not needed to..

The other more distant galaxies I wrap a box around and cull the entire galaxy against the viewing frustum. I also use Imposters to turn each galaxy into a texture for faster rendering and quicker data transfer, but it's not necessary really.

Total stars, some 10,000,000.
Drawn each frame.. 100,000 - 200,000
Frame Rate : Insane!

arctbl
03-01-2009, 01:56 AM
so each cube would contain a random distribution of points? Or could you think of it as an array of point positions for each cube? if the cube is inside the frustum you draw the points it contains? In which case, how would you deal with cubes that are partially inside the frutum?

Or would it be quick to have a couple cubes, each full of points, that could be drawn multiple times to fill the frustum ?

scratt
03-01-2009, 02:18 AM
If it's partially in view, just draw it all.

It's a trade off between renderer performance and logic performance.

Depending on your GPU and CPU you should devise the best way forward.
If 10 or 20,000 points being culled by the GPU is going to be an issue then you need to pick smaller 'cubes' to contain groups of points and then frustum cull them.. So in effect stars inside a set of 10 x 10 x 10 cubes say, and then one cube to hold them all....

Or some other concoction..

Then frustum cull the big cube and if it's partially visible then frustum cull each cube inside.. But if you have a cube with 10 x 10 x 10 cubes inside it and frustum cull them all then that's 1000 frustum cull operations....

That may well end up being an overhead you don't want...

The next step is something like an Octree!

And the beat goes on.. :)