Picking.pp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. program picking;
  2. {$L build/cone.bin.o}
  3. {$L build/cylinder.bin.o}
  4. {$L build/sphere.bin.o}
  5. {$mode objfpc}
  6. uses
  7. ctypes, nds9;
  8. {$include inc/cone.bin.inc}
  9. {$include inc/cylinder.bin.inc}
  10. {$include inc/sphere.bin.inc}
  11. type
  12. TClickable = ( clNothing, clCone, clCylinder, clSphere);
  13. var
  14. clicked: TClickable; // what is being clicked
  15. closeW: integer; // closest distace to camera
  16. polyCount: integer; // keeps track of the number of polygons drawn
  17. // run before starting to draw an object while picking
  18. procedure startCheck();
  19. begin
  20. while PosTestBusy() do; // wait for the position test to finish
  21. while GFX_BUSY do; // wait for all the polygons from the last object to be drawn
  22. PosTest_Asynch(0,0,0); // start a position test at the current translated position
  23. polyCount := GFX_POLYGON_RAM_USAGE^; // save the polygon count
  24. end;
  25. // run afer drawing an object while picking
  26. procedure endCheck(obj: TClickable);
  27. begin
  28. while GFX_BUSY do; // wait for all the polygons to get drawn
  29. while PosTestBusy() do; // wait for the position test to finish
  30. if (GFX_POLYGON_RAM_USAGE^ > polyCount) then // if a polygon was drawn
  31. begin
  32. if PosTestWresult() <= closeW then
  33. begin
  34. // this is currently the closest object under the cursor!
  35. closeW := PosTestWresult();
  36. clicked := obj;
  37. end;
  38. end;
  39. end;
  40. var
  41. rotateX: cuint32 = 0;
  42. rotateY: cuint32 = 0;
  43. touchXY: touchPosition;
  44. viewport: array [0..3] of cint32 = (0,0,255,191); // used later for gluPickMatrix()
  45. keys: u16;
  46. begin
  47. // initialize gl
  48. glInit();
  49. //set mode 0, enable BG0 and set it to 3D
  50. videoSetMode(MODE_0_3D);
  51. lcdMainOnBottom(); // we are going to be touching the 3D display
  52. // enable edge outlining, this will be used to show which object is selected
  53. glEnable(GL_OUTLINE);
  54. //set the first outline color to white
  55. glSetOutlineColor(0,RGB15(31,31,31));
  56. // setup the rear plane
  57. glClearColor(0,0,0,0); // set BG to black and clear
  58. glClearPolyID(0); // the BG and polygons will have the same ID unless a polygon is highlighted
  59. glClearDepth($7FFF);
  60. // setup the camera
  61. gluLookAt( 0.0, 0.0, 1.0, //camera possition
  62. 0.0, 0.0, 0.0, //look at
  63. 0.0, 1.0, 0.0); //up
  64. glLight(0, RGB15(31,31,31) , 0, floattov10(-1.0), 0); // setup the light
  65. while true do
  66. begin
  67. // handle key input
  68. scanKeys();
  69. keys := keysHeld();
  70. if ((keys and KEY_UP)) = 0 then rotateX := rotateX +3;
  71. if((keys and KEY_DOWN)) = 0 then rotateX := rotateX -3;
  72. if((keys and KEY_LEFT)) = 0 then rotateY := rotateY +3;
  73. if((keys and KEY_RIGHT)) = 0 then rotateY := rotateY -3;
  74. // get touchscreen position
  75. touchXY := touchReadXY();
  76. glViewPort(0,0,255,191); // set the viewport to fullscreen
  77. // setup the projection matrix for regular drawing
  78. glMatrixMode(GL_PROJECTION);
  79. glLoadIdentity();
  80. gluPerspective(60, 256.0 / 192.0, 0.1, 20);
  81. glMatrixMode(GL_MODELVIEW); // use the modelview matrix while drawing
  82. glPushMatrix(); // save the state of the current matrix(the modelview matrix)
  83. glTranslate3f32(0,0,floattof32(-6));
  84. glRotateXi(rotateX); // add X rotation to the modelview matrix
  85. glRotateYi(rotateY); // add Y rotation to the modelview matrix
  86. glPushMatrix(); // save the state of the modelview matrix while making the first pass
  87. // draw the scene for displaying
  88. glTranslatef32(floattof32(2.9),floattof32(0),floattof32(0)); // translate the modelview matrix to the drawing location
  89. if (clicked = clCone) then
  90. glPolyFmt(POLY_ALPHA(31) or POLY_CULL_BACK or POLY_FORMAT_LIGHT0 or POLY_ID(1)) // set a poly ID for outlining
  91. else
  92. glPolyFmt(POLY_ALPHA(31) or POLY_CULL_BACK or POLY_FORMAT_LIGHT0 or POLY_ID(0)); // set a poly ID for no outlining (same as BG)
  93. glCallList((@cone_bin)); // draw a green cone from a predefined packed command list
  94. glTranslatef32(floattof32(-3),floattof32(1.8),floattof32(2)); // translate the modelview matrix to the drawing location
  95. if (clicked = clCylinder) then
  96. glPolyFmt(POLY_ALPHA(31) or POLY_CULL_BACK or POLY_FORMAT_LIGHT0 or POLY_ID(1)) // set a poly ID for outlining
  97. else
  98. glPolyFmt(POLY_ALPHA(31) or POLY_CULL_BACK or POLY_FORMAT_LIGHT0 or POLY_ID(0)); // set a poly ID for no outlining (same as BG)
  99. glCallList((@cylinder_bin)); // draw a blue cylinder from a predefined packed command list
  100. glTranslatef32(floattof32(0.5),floattof32(-2.6),floattof32(-4)); // translate the modelview matrix to the drawing location
  101. if(clicked = clSphere) then
  102. glPolyFmt(POLY_ALPHA(31) or POLY_CULL_BACK or POLY_FORMAT_LIGHT0 or POLY_ID(1)) // set a poly ID for outlining
  103. else
  104. glPolyFmt(POLY_ALPHA(31) or POLY_CULL_BACK or POLY_FORMAT_LIGHT0 or POLY_ID(0)); // set a poly ID for no outlining (same as BG)
  105. glCallList((@sphere_bin)); // draw a red sphere from a predefined packed command list
  106. glPopMatrix(1); // restores the modelview matrix to where it was just rotated
  107. // draw the scene again for picking
  108. clicked := clNothing; //reset what was clicked on
  109. closeW := $7FFFFFFF; //reset the distance
  110. //set the viewport to just off-screen, this hides all rendering that will be done during picking
  111. glViewport(0,192,0,192);
  112. // setup the projection matrix for picking
  113. glMatrixMode(GL_PROJECTION);
  114. glLoadIdentity();
  115. gluPickMatrix((touchXY.px),(191-touchXY.py),4,4,viewport); // render only what is below the cursor
  116. gluPerspective(60, 256.0 / 192.0, 0.1, 20); // this must be the same as the original perspective matrix
  117. glMatrixMode(GL_MODELVIEW); // switch back to modifying the modelview matrix for drawing
  118. glTranslatef32(floattof32(2.9),floattof32(0),floattof32(0)); // translate the modelview matrix to the drawing location
  119. startCheck();
  120. glCallList((@cone_bin)); // draw a cone from a predefined packed command list
  121. endCheck(clCone);
  122. glTranslatef32(floattof32(-3),floattof32(1.8),floattof32(2)); // translate the modelview matrix to the drawing location
  123. startCheck();
  124. glCallList((@cylinder_bin)); // draw a cylinder from a predefined packed command list
  125. endCheck(clCylinder);
  126. glTranslatef32(floattof32(0.5),floattof32(-2.6),floattof32(-4)); // translate the modelview matrix to the drawing location
  127. startCheck();
  128. glCallList((@sphere_bin)); // draw a sphere from a predefined packed command list
  129. endCheck(clSphere);
  130. glPopMatrix(1); // restores the modelview matrix to its original state
  131. glFlush(0); // wait for everything to be drawn before starting on the next frame
  132. if (keys and KEY_START) <> 0 then break;
  133. end;
  134. end.