gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > Setting camera/view for picking

#168636 - Drovor - Tue May 12, 2009 4:42 pm

I'm new to 3d programming and I'm having some trouble ordering the OpenGL calls properly. I'm hoping I'm doing something obviously wrong with the camera, but I haven't been able to figure it out.

I have implemented 3D picking using the algorithm in the picking demo where I render a 1 pixel viewport around the cursor and check if it changes after each polygon is drawn (genius idea!).

It works 100% when the camera has z<0, but when I start to move my camera around (specifically along the z-axis through the x/y plane) it fails.

Here is all the relevant code (I think!)
Code:

// main loop
while (1)
{
     // snip: touch/key handling

    // these just call glLight
    light0.set();
    light1.set();
 
    glViewport(0,0,255,191); // set the viewport to fullscreen
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    // this just calls gluPerspective...
    cam.Perspective()

    //change cull mode / enable lights
      glPolyFmt(POLY_ALPHA(31) | POLY_CULL_FRONT | light0.getPolyFmtFlag() | light1.getPolyFmtFlag()  | POLY_ID(1));

    // Set the current matrix to be the model matrix
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    // gluLookAt, location (0,0, variable-z), looking at origin, y=up
    cam.render();

    // draws a grid of quads, essentially a bunch of 3D tiles
    ug->draw()


    // This only half works
    if( held & KEY_TOUCH)
      ug->pickPoint(touchXY.px, touchXY.py, cam);

    swiWaitForVBlank();
}


Here is my picking code, I'm moving the camera along the Z-axis and when z<0 it works 100%, but when z>0 it doesn't. I think because I'm setting up my camera wrong.
Code:

bool UndergroundDrawGrid::pickPoint(int x, int y, Camera &cam)
{
  // This flag makes it so "startCheck" and "endCheck" are called
  // before and after every polygon is drawn
  pickMode = true;


    int viewport[]={0,0,255,191}; // used later for gluPickMatrix()
    glViewport(0,192,0,192); // set the viewport to fullscreen
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
      // render only what is below the cursor
    gluPickMatrix(x,(191-y),4,4,viewport);
      // same perspective as the earlier call
    cam.Perspective();
    glMatrixMode(GL_MODELVIEW);

    // where do I setup the camera?? It doesn't work at all if I put either of these 2 calls in.
//    glLoadIdentity();
//    cam.render();

  // de-select the previously selected object.
  if (picked)
     picked->picked = false;


  // "pickMode" flags will do the magic
  // using the same draw() function it enables startCheck() and endCheck() to be
  // called before/after each polygon and save the object which is picked
  // to "picked"
  draw();

  // if it was hit, mark the new object as picked.
  // also will mark the old one if a new one wasn't set.
  if (picked)
    picked->picked = true;

  pickMode = false;

  return endCheck();
}



// These are pretty much lifted straight from the picking demo:
void UndergroundDrawGrid::startCheck()
{
  while(PosTestBusy()); // wait for the position test to finish
  while(GFX_BUSY); // wait for all the polygons from the last object to be drawn
  PosTest_Asynch(0,0,0); // start a position test at the current translated position
  polyCount = GFX_POLYGON_RAM_USAGE; // save the polygon count
}

bool UndergroundDrawGrid::endCheck()
{
  while(GFX_BUSY); // wait for all the polygons to get drawn
  while(PosTestBusy()); // wait for the position test to finish
  if(GFX_POLYGON_RAM_USAGE>polyCount) // if a polygon was drawn
  {
    {
      // this is currently the closest object under the cursor!
      closeW=PosTestWresult();
      return true;
    }
  }
  return false;
}

#168642 - Drovor - Tue May 12, 2009 8:36 pm

I was trying to optimize by only drawing 1 side of the cubes during the picking check, and I'm guessing the rectangle is only visible from one side so there was nothing to hit.

After removing this and drawing the scene normally picking works the it is supposed to.

*Edit*
Added this right before drawing my simplified scene and it did the trick:
Code:

  // opaque polygons, no culling, this fixes my problems.
  glPolyFmt(POLY_ALPHA(31) | POLY_CULL_NONE);