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