Author Topic: Selecting.  (Read 1827 times)

Psychedelic_hands

  • Guest
Selecting.
« on: 3 December 2011, 09:19:46 »
I notice two issues with selecting when playing recently. The first is the when selecting a group units and you hold down the the left mouse button, theit icons on the left flicker and switch places. It's not a big deal, but looks totally shocking.
Also, when you hold down the right mouse button to select my frame-rate goes down by over ahalf. It usually sits perfectly at 60 fps but slips down to about 24. Is this for any particalur reason, or is it something which could use tighting up?

silnarm

  • Local Moderator
  • Behemoth
  • ********
  • Posts: 1,373
    • View Profile
Re: Selecting.
« Reply #1 on: 5 December 2011, 20:37:01 »
I notice two issues with selecting when playing recently. The first is the when selecting a group units and you hold down the the left mouse button, theit icons on the left flicker and switch places. It's not a big deal, but looks totally shocking.

Agreed, and fixed.

Quote
Also, when you hold down the right mouse button to select my frame-rate goes down by over ahalf. It usually sits perfectly at 60 fps but slips down to about 24. Is this for any particalur reason, or is it something which could use tighting up?

I just went to try this myself and model rendering in general is all over the shop for me... probably related, will investigate further as time permits.
Glest Advanced Engine - Code Monkey

Timeline | Downloads

will

  • Golem
  • ******
  • Posts: 783
    • View Profile
Re: Selecting.
« Reply #2 on: 5 December 2011, 20:45:06 »
Its because we're using colour picking perhaps?  Surely we're not doing that every frame when the mouse is pressed?  And if we are and need to, it can still be tightened up by rendering just the current pick to see if it still intersects, and so on?

silnarm

  • Local Moderator
  • Behemoth
  • ********
  • Posts: 1,373
    • View Profile
Re: Selecting.
« Reply #3 on: 5 December 2011, 21:08:33 »
We use OpenGL's 'name' based picking, which is probably the same thing in a technical sense.  I think it is happening every render the mouse is pressed, but considering how light-weight a selection render is it shouldn't make a large difference, certainly no where near the less than half frame-rate of the OP.

For me, the time taken by model rendering was jumping up and down randomly with a new game, no camera movement, all idle units etc... Fixed-pipe and shaders, so something is definitely wrong with model render in general.

Glest Advanced Engine - Code Monkey

Timeline | Downloads

will

  • Golem
  • ******
  • Posts: 783
    • View Profile
Re: Selecting.
« Reply #4 on: 5 December 2011, 21:36:19 »
GL_SELECT has a really bad performance reputation but I don't know how current that is.  It certainly used to be true that it was hardware-accelerated yet degraded by Nvidia and ATI to make a price point between consumer products and pro products.

The thing is, if you hold the mouse down, are you picking every frame?  And if so, do you need to?


softcoder

  • MegaGlest Team
  • Battle Machine
  • ********
  • Posts: 2,239
    • View Profile
Re: Selecting.
« Reply #5 on: 9 December 2011, 16:56:06 »
I'm looking into weird issues in MG related to this same selection issue and came across this open OpengGL's site:

Selection and Picking and Feedback Mode
A modern OpenGL program should not use the selection buffer or feedback mode. These are not 3D graphics rendering features yet they have been added to GL since version 1.0. Selection and feedback runs in software (CPU side). On some implementations, when used along with VBOs, it has been reported that performance is lousy.
A modern OpenGL program should do color picking (render each object with some unique color and glReadPixels to find out what object your mouse was on) or do the picking with some 3rd party mathematics library.

I beleive both GAE and MG use selection mode which is very problematic as you search around the web. I'm looking into switching to color picking as described here: http://www.lighthouse3d.com/opengl/picking/index.php3?color1

Thought this might help as it seems performance nose dives when using selection buffer as its all done in software (not GPU)

will

  • Golem
  • ******
  • Posts: 783
    • View Profile
Re: Selecting.
« Reply #6 on: 9 December 2011, 19:32:42 »
If you pre-compute (on load) the bounds of each model, and model it as a sphere you can cheaply check if it could possibly intersect the selection ray, and so avoid rendering any models unnecessarily

silnarm

  • Local Moderator
  • Behemoth
  • ********
  • Posts: 1,373
    • View Profile
Re: Selecting.
« Reply #7 on: 26 December 2011, 05:17:48 »
Just to let peeps know, I've started on a solution but it will not go into 0.4, not messing with the Renderer for 0.4 now, too risky ;)

I'm using FBO (Framebuffer Objects) and MRT (Multiple Render Targets) for this, and we will end up with a kind of 'constant pick', so we will always know what's under the mouse... I've been playing lots of StarCraft2 recently and when testing GAE now I keep hovering the mouse over other units expecting to get health/progress bars, which of course I don't currently get, but I will in the future :)

If you pre-compute (on load) the bounds of each model, and model it as a sphere you can cheaply check if it could possibly intersect the selection ray, and so avoid rendering any models unnecessarily

If softcoder is going to use glReadPixels() for this in MG, then I heartily concur, and recommend he do so.  I like the MRT solution better myself (only because I want those niceties from SC2!).
Glest Advanced Engine - Code Monkey

Timeline | Downloads

will

  • Golem
  • ******
  • Posts: 783
    • View Profile
Re: Selecting.
« Reply #8 on: 26 December 2011, 10:10:37 »
I'll donate geometry picking code so it can all be done quickly on CPU

will

  • Golem
  • ******
  • Posts: 783
    • View Profile
Re: Selecting.
« Reply #9 on: 27 December 2011, 19:46:01 »
Here's some simple ports of the stuff you don't get in GLES 2 (or, eventually, an OpenGL 4.x world):

Code: [Select]
void graphics_t::set_projection_2D(int width,int height) {
matrix_t projection = {{ // transposed for OpenGL
2./width, 0, 0, 0,
0, 2./-height, 0, 0,
0, 0, -2, 0,
-1, 1, -1, 1
}};
set_projection_matrix(projection);
}

void graphics_t::set_projection_perspective(GLfloat fovy,GLfloat aspect,GLfloat zNear,GLfloat zFar) {
const GLfloat
radians = fovy / 2. * M_PI / 180.,
sine = sin(radians),
deltaZ = zNear - zFar;
graphics_assert((deltaZ!=0)&&(sine!=0)&&(aspect!=0));
const GLfloat cotangent = cos(radians) / sine;
const matrix_t perspective = {{
cotangent / aspect, 0, 0, 0,
0, cotangent, 0, 0,
0, 0, (zFar + zNear) / deltaZ, -1,
0, 0, (2. * zNear * zFar) / deltaZ, 0
}};
set_projection_matrix(perspective);
#if !defined(GLES2) && !defined(NDEBUG)
matrix_t check;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(fovy,aspect,zNear,zFar);
glGetFloatv(GL_PROJECTION_MATRIX,check.f);
if(pimpl->projection != check)
graphics_error("Error setting perspective: " << std::endl << pimpl->projection << std::endl << " != " << std::endl << check);
#endif
}

void graphics_t::set_modelview_look_at(const vec_t& eye,const vec_t& centre,const vec_t& up) {
#if !defined(GLES2) && !defined(NDEBUG)
matrix_t check;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(eye.x,eye.y,eye.z,centre.x,centre.y,centre.z,up.x,up.y,up.z);
glGetFloatv(GL_MODELVIEW_MATRIX,check.f);
#endif
const vec_t f((centre-eye).normalised()),
s(f.cross(up).normalised()),
u(s.cross(f).normalised());
const matrix_t m = {{
s.x,u.x,-f.x,0,
s.y,u.y,-f.y,0,
s.z,u.z,-f.z,0,
0,0,0,1
}};
set_modelview_matrix(matrix_t::translation(-eye).transposition() * m);
#if !defined(GLES2) && !defined(NDEBUG)
graphics_assert(pimpl->modelview == check);
#endif
}

vec_t graphics_t::unproject(const vec_t& win,GLint viewport[4]) {
#if !defined(GLES2) && !defined(NDEBUG)
double p[16], mv[16], c[3];
for(int i=0; i<16; i++) {
p[i] = pimpl->projection.f[i];
mv[i] = pimpl->modelview.f[i];
}
gluUnProject(win.x,win.y,win.z,mv,p,viewport,c,c+1,c+2);
const vec_t check(c[0],c[1],c[2]);
#endif
const vec4_t in(
(win.x - viewport[0]) / viewport[2] * 2. - 1.,
(win.y - viewport[1]) / viewport[3] * 2. - 1.,
2. * win.z - 1.,
1.),
inv = in*pimpl->modelviewprojection.inverse().transposition(); // from OpenGL to normal order
const vec_t out(inv.x/inv.w,inv.y/inv.w,inv.z/inv.w);
#if !defined(GLES2) && !defined(NDEBUG)
if(fabs(out.x-check.x)>0.0001 || // fuzzy to account for using floats not doubles
fabs(out.y-check.y)>0.0001 ||
fabs(out.z-check.z)>0.0001)
std::cout << "WARNING! unproject failed: " << out << " != " << check << std::endl;
#endif
return out;
}

As you can see, the functions check their results against the classic functions they are replacing so I've got good confidence in them nowadays.

For selection, for example, you can unproject the near z (win.z == 0) and the far z (win.z == 1) and this gives you a ray through the scene on the mouse-click.

Because Glest is using a grid, you can then use a Bresenham's to march across the map, foreground to background order, checking to see if there's an object on the intersecting tile to be tested.

Even without bothering to cache the inverse projection matrix there really isn't any performance impact in doing this every frame; this is infinitesimal effort compared to doing any rendering at all.

Which reminds me; it would be so cool if a debug-mode showed models that spilled out over the boundaries of their tiles.

 

anything