0022650: Exception in Primitive Array during Redisplay of Presentable Object
[occt.git] / src / OpenGl / OpenGl_pick.cxx
1 /***********************************************************************
2
3 FONCTION :
4 ----------
5 File OpenGl_pick :
6
7
8 REMARQUES:
9 ----------       
10
11 HISTORIQUE DES MODIFICATIONS   :
12 --------------------------------
13 xx-xx-xx : xxx ; Creation.
14 25-06-96 : FMN ; Suppression utilisation de glScissor.
15 03-07-96 : FMN ; Suppression TelGetViewportAtLocation.
16
17 ************************************************************************/
18
19 /*----------------------------------------------------------------------*/
20 /*
21 * Includes
22 */ 
23
24 #include <OpenGl_tgl_all.hxx>
25
26 #include <stdio.h>
27
28 #include <GL/gl.h>
29
30 #include <OpenGl_tsm.hxx>
31 #include <OpenGl_tsm_ws.hxx>
32 #include <OpenGl_telem_pick.hxx>
33 #include <OpenGl_telem_view.hxx>
34 #include <OpenGl_Memory.hxx>
35
36
37 /*----------------------------------------------------------------------*/
38 /*
39 * Constantes
40 */ 
41
42 #define ARRAY_GROW_SIZE 10
43
44
45 /*----------------------------------------------------------------------*/
46 /*
47 * Variables statiques
48 */ 
49
50 static  GLuint *tgl_pick_buffer;  /* buffer to be given to GL */
51 static  Tint   tgl_pick_bufsize;
52
53
54 /*----------------------------------------------------------------------*/
55
56 static TStatus
57 allocate( Tint *cur_size, Tint size_reqd, void **arr, Tint elem_size )
58 {
59   size_reqd = ( ( size_reqd / ARRAY_GROW_SIZE ) + 1 ) * ARRAY_GROW_SIZE;
60
61   if( !( *cur_size ) ) {
62     *arr = malloc( size_reqd * elem_size );
63     memset( *arr, 0, size_reqd * elem_size );
64   }
65   else
66 #if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)    
67     *arr = realloc( *arr, size_reqd * elem_size );
68 #else
69     *arr = (void*)cmn_resizemem<char>( (char*)*arr, size_reqd * elem_size );
70 #endif
71
72   if( !(*arr) )
73     return TFailure;
74
75   *cur_size = size_reqd;
76   return TSuccess;
77 }
78
79 static TStatus
80 Initialize( Tint wsid, Tint *view_stid )
81 {
82   Tint         depth;
83   CMN_KEY_DATA key;
84   Tint         buf_siz_reqd = 0;
85
86   TsmGetWSAttri( wsid, WSViewStid, &key );
87   if( key.ldata == -1 )
88     return TFailure;
89
90   *view_stid = key.ldata;
91   TsmGetStructureDepth( *view_stid, &depth );
92
93   buf_siz_reqd = depth*6 + 2;
94
95   if( tgl_pick_bufsize < buf_siz_reqd )
96   {
97     if( allocate( &tgl_pick_bufsize, buf_siz_reqd, (void **)&tgl_pick_buffer,
98       sizeof( int ) ) == TFailure )
99       return TFailure;
100   }
101
102   return TSuccess;
103 }
104 /*----------------------------------------------------------------------*/
105
106 static void
107 fill_pick_report( tel_pick_report rep, TPickOrder order, Tint depth )
108 {
109   Tint  i, j;
110   TEL_PACKED_NAME pn;
111
112   rep->depth = tgl_pick_buffer[0]/6;
113
114   if( order == TTopFirst )
115   {
116     for( i = 0, j = 3; i < ( Tint )(tgl_pick_buffer[0]/6) && i < depth; i++ )
117     {         /* skip hit numb. zmin, zmax -> j = 3 */
118       pn.s[0] = tgl_pick_buffer[j++];
119       pn.s[1] = tgl_pick_buffer[j++];
120       rep->pick_path[i].struct_id = pn.i;
121       pn.s[0] = tgl_pick_buffer[j++];
122       pn.s[1] = tgl_pick_buffer[j++];
123       rep->pick_path[i].pick_id = pn.i;
124       pn.s[0] = tgl_pick_buffer[j++];
125       pn.s[1] = tgl_pick_buffer[j++];
126       rep->pick_path[i].el_num = pn.i;
127     }
128   }
129   else
130   {
131     Tint is, js;
132
133     is = rep->depth < depth ? rep->depth : depth;
134     js = 3 + ( rep->depth - is )*6;  /* skip hit numb. zmin, zmax -> j = 3 */
135     is--;
136
137     for( i = is, j = js; i >= 0; i-- )
138     {
139       pn.s[0] = tgl_pick_buffer[j++];
140       pn.s[1] = tgl_pick_buffer[j++];
141       rep->pick_path[i].struct_id = pn.i;
142       pn.s[0] = tgl_pick_buffer[j++];
143       pn.s[1] = tgl_pick_buffer[j++];
144       rep->pick_path[i].pick_id = pn.i;
145       pn.s[0] = tgl_pick_buffer[j++];
146       pn.s[1] = tgl_pick_buffer[j++];
147       rep->pick_path[i].el_num = pn.i;
148     }
149   }
150
151   return;
152 }
153 /*----------------------------------------------------------------------*/
154
155 Tint TglVpBeingPicked = -1;
156
157 TStatus
158 TPick( Tint Wsid, Tint x, Tint y, Tfloat apw, Tfloat aph,
159       TPickOrder order, Tint depth, tel_pick_report rep )
160 {
161   Tint           vid;
162   TSM_ELEM_DATA  data;
163   CMN_KEY        key;
164   CMN_KEY_DATA   key1;
165   TEL_VIEW_REP   ovrep, vrep;
166
167   if( Initialize( Wsid, &(data.ldata) ) == TFailure )
168     return TFailure;
169
170   TglActiveWs = Wsid;
171   key.id      = Wsid;
172
173   {
174     /* TStatus  stat; */
175     Tfloat   xsf, ysf, x1, x2, y1, y2, W, H, xm, xp, ym, yp, cx, cy;
176     Tint              err;
177     TEL_VIEW_MAPPING  map;
178
179     vid  = Wsid;
180     TglVpBeingPicked = vid;
181     TelGetViewRepresentation( Wsid, vid, &vrep );
182     ovrep = vrep;
183
184     TsmGetWSAttri( Wsid, WSWidth, &key1 );
185     W = ( float )key1.ldata;
186     TsmGetWSAttri( Wsid, WSHeight, &key1 );
187     H = ( float )key1.ldata;
188
189     xm = vrep.extra.map.window.xmax, xp = vrep.extra.map.window.xmin;
190     ym = vrep.extra.map.window.ymax, yp = vrep.extra.map.window.ymin;
191     cx = xm + xp, cx /= 2;
192     cy = ym + yp, cy /= 2;
193     x1 = x - apw/2, x2 = x1 + apw, y1 = y - aph/2, y2 = y1 + aph;
194     xsf = xm - xp, xsf /= W;
195     ysf = ym - yp, ysf /= H;
196     x1 = xsf * x1 + xp;
197     y1 = ysf * y1 + yp;
198     x2 = xsf * x2 + xp;
199     y2 = ysf * y2 + yp;
200
201     map = vrep.extra.map;
202     map.window.xmin = x1, map.window.xmax = x2;
203     map.window.ymin = y1, map.window.ymax = y2;
204     TelEvalViewMappingMatrixPick( &map, &err, vrep.mapping_matrix, cx, cy );
205     if( err )
206       printf( "Error in Mapping pick\n" );
207
208     if( TelSetViewRepresentation( Wsid, vid, &vrep ) == TFailure )
209       printf( "Error in Set vrep for pick\n" );
210   }
211
212   glMatrixMode(GL_MODELVIEW);
213   tgl_pick_buffer[0] = 0;
214   glSelectBuffer( tgl_pick_bufsize ,  tgl_pick_buffer);
215   glRenderMode(GL_SELECT);
216   glLoadName(55);
217   TsmSendMessage( TelExecuteStructure, PickTraverse, data, 1, &key );
218   glRenderMode(GL_RENDER);
219   TglVpBeingPicked = -1;
220
221   /* print( ); */
222   fill_pick_report( rep, order, depth );
223   TelSetViewRepresentation( Wsid, vid, &ovrep );
224
225   return TSuccess;
226 }
227 /*----------------------------------------------------------------------*/