|
NCBI Home IEB Home C Toolkit docs C++ Toolkit source browser C Toolkit source browser (2) |
NCBI C Toolkit Cross ReferenceC/cn3d/cn3dshim.c |
source navigation diff markup identifier search freetext search file search |
1 /* cn3dshim.c
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information (NCBI)
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government do not place any restriction on its use or reproduction.
13 * We would, however, appreciate having the NCBI and the author cited in
14 * any work or product based on this material
15 *
16 * Although all reasonable efforts have been taken to ensure the accuracy
17 * and reliability of the software and data, the NLM and the U.S.
18 * Government do not and cannot warrant the performance or results that
19 * may be obtained by using this software or data. The NLM and the U.S.
20 * Government disclaim all warranties, express or implied, including
21 * warranties of performance, merchantability or fitness for any particular
22 * purpose.
23 *
24 * ===========================================================================
25 *
26 * File Name: cn3dshim.c
27 *
28 * Authors: Lewis Geer
29 *
30 * Version Creation Date:
31 *
32 * File Description: Shim functions necessary to convert to OpenGL
33 *
34 * Modifications:
35 * --------------------------------------------------------------------------
36 * $Log: cn3dshim.c,v $
37 * Revision 6.30 2001/04/27 20:08:04 juran
38 * Heed warnings.
39 *
40 * Revision 6.29 2000/07/23 12:37:23 thiessen
41 * allow dynamic slave->master transformation
42 *
43 * Revision 6.28 2000/04/08 00:37:31 lewisg
44 * multiple seqentries, NEWSEQ message, etc.
45 *
46 * Revision 6.27 2000/04/04 22:18:42 lewisg
47 * add defline to ddv, fix seq import bugs, set boundbox
48 *
49 * Revision 6.26 2000/03/20 18:18:33 thiessen
50 * fixed header problem causing network unavailability
51 *
52 * Revision 6.25 2000/03/08 21:46:15 lewisg
53 * cn3d saves viewport, misc bugs
54 *
55 * Revision 6.24 2000/02/19 01:23:59 lewisg
56 * use ibm, add row tracking code, various bug fixes
57 *
58 * Revision 6.23 2000/02/05 01:32:21 lewisg
59 * add viewmgr, move place freeing is done in ddv, modify visual c++ projects
60 *
61 * Revision 6.22 2000/01/18 22:49:16 lewisg
62 * send OM_MSG_FLUSH to ddv/udv, tweak CPK coloration, misc bugs
63 *
64 * Revision 6.21 2000/01/08 00:47:53 lewisg
65 * fixes to selection, update, color
66 *
67 * Revision 6.20 2000/01/06 00:04:42 lewisg
68 * selection bug fixes, update message outbound, animation APIs moved to vibrant
69 *
70 * Revision 6.19 2000/01/04 15:55:51 lewisg
71 * don't hang on disconnected network and fix memory leak/hang at exit
72 *
73 * Revision 6.18 1999/12/29 22:55:03 lewisg
74 * get rid of seqalign id
75 *
76 * Revision 6.17 1999/12/28 15:08:44 lewisg
77 * remove remaining mediainfo code
78 *
79 * Revision 6.16 1999/12/27 23:14:12 lewisg
80 * add colormgr show/hide in Cn3D
81 *
82 * Revision 6.15 1999/12/23 21:40:33 lewisg
83 * move animation controls to dialog
84 *
85 * Revision 6.14 1999/12/02 20:31:59 lewisg
86 * put seqentries into bioseqset and fix calling convention in alignmgr.c
87 *
88 * Revision 6.13 1999/12/01 16:15:54 lewisg
89 * interim checkin to fix blocking memory leak
90 *
91 * Revision 6.12 1999/11/30 22:46:37 vakatov
92 * Cast callback arg in Cn3D_SizeCB() lest to cast the callback func.type
93 *
94 * Revision 6.11 1999/11/12 16:06:34 lewisg
95 * fix sequentry to valnode conversion
96 *
97 * Revision 6.10 1999/11/10 23:19:42 lewisg
98 * rewrite of selection code for ddv
99 *
100 * Revision 6.9 1999/11/02 23:06:08 lewisg
101 * fix cn3d to launch correctly if there is no seqentry associated with bioseq
102 *
103 * Revision 6.8 1999/10/29 14:15:30 thiessen
104 * ran all Cn3D source through GNU Indent to prettify
105 *
106 * Revision 6.7 1999/10/18 15:32:50 lewisg
107 * move ClearSequences() to cn3dshim.c
108 *
109 * Revision 6.6 1999/10/15 20:56:40 lewisg
110 * append DDV_ColorGlobal as userdata. free memory when cn3d terminates.
111 *
112 * Revision 6.5 1999/10/05 23:18:24 lewisg
113 * add ddv and udv to cn3d with memory management
114 *
115 * Revision 6.4 1999/09/22 20:07:39 thiessen
116 * minor fix for mac compiler
117 *
118 * Revision 6.3 1999/09/21 18:09:15 lewisg
119 * binary search added to color manager, various bug fixes, etc.
120 *
121 * Revision 6.2 1999/04/06 14:23:30 lewisg
122 * add opengl replacement for viewer3d
123 *
124 * Revision 6.1 1999/02/10 23:49:44 lewisg
125 * use RGB values instead of indexed palette
126 *
127 *
128 */
129
130
131 #include <cn3dmain.h>
132 #include <cn3dmsg.h>
133 #include <ncbi.h>
134 #include <cn3dshim.h>
135 #include <seqmgr.h>
136 #include <salpacc.h>
137 #include <asn.h>
138 #include <objall.h>
139 #include <strimprt.h>
140 #include <objmmdb1.h>
141 #include <objmmdb2.h>
142 #include <objmmdb3.h>
143 #include <algorend.h>
144
145
146 #ifdef _OPENGL
147 #include <undefwin.h>
148 #ifdef _WIN32
149 #include <windows.h>
150 #endif
151
152 #if defined(macintosh)
153 #include <gl.h>
154 #include <glu.h>
155 #else
156 #include <GL/gl.h>
157 #include <GL/glu.h>
158 #endif
159 #endif /* _OPENGL */
160
161
162 /*****************************************************************************
163
164 Function: Cn3D_SetVisible()
165
166 Purpose: Sets the visible bit for a chain in the biostruc AND the color
167 manager
168
169 Parameters: pColorGlobal
170 pmmdThis: the chain
171 fVisible: TRUE if the chain is to be visible
172
173 *****************************************************************************/
174
175 NLM_EXTERN void Cn3D_SetVisible(DDV_ColorGlobal *pColorGlobal, PMMD pmmdThis,
176 Boolean fVisible)
177 {
178 if(pmmdThis == NULL) return;
179 if(pmmdThis->pSeqId == NULL) return;
180 DDV_SetVisible(pColorGlobal, pmmdThis->pSeqId, -1, fVisible);
181 pmmdThis->bVisible = fVisible;
182 }
183
184
185 /*****************************************************************************
186
187 Function: Cn3D_IsVisible()
188
189 Purpose: Gets the visible bit for a chain in the biostruc.
190
191 Parameters: pColorGlobal
192 pmmdThis: the chain
193
194 Returns: TRUE if visible
195
196 *****************************************************************************/
197
198 NLM_EXTERN Boolean Cn3D_IsVisible(DDV_ColorGlobal *pColorGlobal,
199 PMMD pmmdThis)
200 {
201 if(pmmdThis == NULL) return FALSE;
202 return pmmdThis->bVisible;
203 }
204
205 /*****************************************************************************
206
207 Function: ClearSequences()
208
209 Purpose: Deletes the Cn3D messagefunc from userdata on the SeqAnnots and
210 SeqEntries presently displayed.
211
212 *****************************************************************************/
213
214 void ClearSequences(void)
215 {
216 Uint2 entityID;
217 SeqAnnot *sap;
218 SeqAlign *salp;
219 SeqEntry *sep;
220 BioseqSet *bssp;
221 Bioseq *bsp;
222 ValNode *pvnsep, *pvnnext;
223
224 if (Cn3D_ColorData.sap != NULL) {
225 for (sap = Cn3D_ColorData.sap; sap != NULL; sap = sap->next) {
226 if (sap->data == NULL) continue;
227 salp = sap->data;
228 entityID = ObjMgrGetEntityIDForPointer(salp);
229 ObjMgrFreeUserData(entityID, Cn3D_ColorData.sapprocid, OMPROC_EDIT,
230 Cn3D_ColorData.userkey);
231 ObjMgrSendMsg(OM_MSG_FLUSH, entityID, 0, 0);
232 ObjMgrSendMsg (OM_MSG_DEL, entityID, 0, 0);
233 }
234 }
235 Cn3D_ColorData.sap = NULL;
236
237 /* this is a hack, but seems harmless? objects are not freed until
238 the viewer windows die. Viewer windows don't die until the event loop.
239 This is because there could be a few mouse clicks remaining. The problem
240 is that when loading a new sequence when the old sequence is identical,
241 the object manager gets completely confused because the old sequence is not
242 dead yet. The following loop makes it play dead. */
243
244 if(Cn3D_ColorData.pvnsep != NULL) {
245 bssp = Cn3D_ColorData.pvnsep->data.ptrvalue;
246 for(sep = bssp->seq_set; sep != NULL; sep = sep->next) {
247 bsp = sep->data.ptrvalue;
248 SeqMgrDeleteFromBioseqIndex(bsp);
249 }
250 }
251
252 for(pvnsep = Cn3D_ColorData.pvnsep; pvnsep != NULL;
253 pvnsep = pvnnext) {
254 pvnnext = pvnsep->next;
255 entityID =
256 ObjMgrGetEntityIDForPointer((void *) pvnsep);
257 ObjMgrFreeUserData(entityID, Cn3D_ColorData.sepprocid, OMPROC_VIEW,
258 Cn3D_ColorData.userkey);
259 ObjMgrSendMsg(OM_MSG_FLUSH, entityID, 0, 0);
260 ObjMgrSendMsg (OM_MSG_DEL, entityID, 0, 0);
261 }
262
263 if(Cn3D_ColorData.IsUserData == FALSE)
264 DDV_DeleteColorGlobal(Cn3D_ColorData.pDDVColorGlobal);
265 Cn3D_ColorData.pDDVColorGlobal = NULL;
266 Cn3D_ColorData.pvnsep = NULL;
267
268 return;
269 }
270
271
272 /* constructor for DDV_ColorEntry structure */
273 void Cn3D_ConstructColorData(TCn3D_ColorData * ColorData
274 #ifdef _OPENGL
275 , TOGL_Data * OGL_Data
276 #endif
277 , Boolean StandAlone)
278 {
279
280 if (ColorData == NULL)
281 return;
282 #ifdef _OPENGL
283 if (OGL_Data == NULL)
284 return;
285 #endif
286 ColorData->sap = NULL;
287 ColorData->pvnsep = NULL;
288 ColorData->StandAlone = StandAlone;
289 ColorData->pDDVColorGlobal = NULL;
290 ColorData->IsUserData = FALSE;
291 #ifdef _OPENGL
292 ColorData->OGL_Data = OGL_Data;
293 #endif
294 ColorData->AnimateDlg.Cn3D_wAnimate = NULL;
295 ColorData->Cn3D_w = NULL;
296 }
297
298 /* destructor for Color structure */
299 void Cn3D_DestructColorData(TCn3D_ColorData * ColorData)
300 {
301 if (ColorData == NULL)
302 return;
303 DDV_DeleteColorGlobal(ColorData->pDDVColorGlobal);
304 }
305
306 /*****************************************************************************
307
308 Function: Cn3D_FindFeature
309
310 Purpose: Finds a feature of a given type in the feature set
311
312 Parameters: bsfsp, the head of the BiostrucFeatureSets to search
313 type, the type of feature to look for
314 num, the nth occurrence of the feature type
315
316 Returns: The feature if found, NULL otherwise
317
318 *****************************************************************************/
319 NLM_EXTERN BiostrucFeature *Cn3D_FindFeature(BiostrucFeatureSetPtr bsfsp,
320 Int4 type, Int4 num)
321 {
322 BiostrucFeature *bsfp;
323 Int4 i = 0;
324
325 for(;bsfsp != NULL; bsfsp = bsfsp->next) {
326 for(bsfp = bsfsp->features; bsfp != NULL; bsfp = bsfp->next) {
327 if(bsfp->type == type) {
328 i++;
329 if(i >= num) return bsfp;
330 }
331 }
332 }
333 return NULL;
334 }
335
336 /*****************************************************************************
337
338 Function: Cn3D_AddFeatureSet
339
340 Purpose: Adds a new BiostrucFeatureSet the feature set
341
342 Parameters: bsfspp, pointer to the head of the BiostrucFeatureSets
343
344 Returns: the feature set
345
346 *****************************************************************************/
347 NLM_EXTERN BiostrucFeatureSetPtr Cn3D_AddFeatureSet(
348 BiostrucFeatureSetPtr *bsfspp)
349 {
350 BiostrucFeatureSetPtr bsfsp;
351
352 if(*bsfspp == NULL) {
353 *bsfspp = BiostrucFeatureSetNew();
354 return *bsfspp;
355 }
356 else {
357 for (bsfsp = *bsfspp; bsfsp->next != NULL; bsfsp = bsfsp->next) continue;
358 bsfsp->next = BiostrucFeatureSetNew();
359 return bsfsp->next;
360 }
361 }
362
363
364 /************************* OpenGL specific functions *****************************/
365
366 #ifdef _OPENGL
367
368
369
370
371 static void LIBCALLBACK Cn3D_SizeCB(PFB pfbThis, Nlm_Int4 iModel,
372 Nlm_Int4 iIndex,
373 Pointer ptr)
374 /* callback used to find the bounding box of the atoms of a structure */
375 {
376 TOGL_BoundBox* BoundBox = (TOGL_BoundBox*) ptr;
377 PMAD pmadThis = NULL;
378 PALD paldThis = NULL;
379 Nlm_FloatLoPtr pflvDataThis = NULL;
380 Nlm_Int4 i;
381
382 if (pfbThis == NULL || BoundBox == NULL)
383 return;
384 if (pfbThis->bMe == (Byte) AM_MAD) { /* is this molecular atom data? *//* iIndex isn't used */
385 pmadThis = (PMAD) pfbThis;
386 paldThis = GetAtomLocs(pmadThis, iModel);
387 while (paldThis) {
388 pflvDataThis = paldThis->pflvData;
389 if (BoundBox->set == FALSE) { /* if the bounding box has not been used, set it */
390 for (i = 0; i < 6; i++) {
391 BoundBox->x[i] = pflvDataThis[i / (int) 2];
392 BoundBox->set = TRUE;
393 }
394 } else {
395 for (i = 0; i < 6; i += 2) { /* check to see if the atom lies outside the bound box */
396 if (pflvDataThis[i / (Nlm_Int4) 2] < BoundBox->x[i])
397 BoundBox->x[i] = pflvDataThis[i / (Nlm_Int4) 2];
398 if (pflvDataThis[i / (Nlm_Int4) 2] >
399 BoundBox->x[i + 1]) BoundBox->x[i + 1] =
400 pflvDataThis[i / (Nlm_Int4) 2];
401 }
402 }
403 paldThis = paldThis->next;
404 }
405 }
406 }
407
408
409 void LIBCALL Cn3D_Size(TOGL_BoundBox * BoundBox, PDNMS pdnmsThis)
410 /* find coordinates of the bounding box of a structure */
411 {
412 PDNMS pdnmsSlave;
413 PMSD pmsdThis;
414
415 if (BoundBox == NULL || pdnmsThis == NULL) return;
416 OGL_ClearBoundBox(BoundBox);
417 BoundBox->set = FALSE;
418 TraverseModels(pdnmsThis, TRAVERSE_ATOM, 0, BoundBox, Cn3D_SizeCB);
419 /* don't do slaves, since their coordinates are no longer trasnformed onto master
420 pmsdThis = pdnmsThis->data.ptrvalue;
421 for(pdnmsSlave = pmsdThis->pdnmsSlaves; pdnmsSlave != NULL;
422 pdnmsSlave = pdnmsSlave->next)
423 TraverseModels(pdnmsSlave, TRAVERSE_ATOM, 0, BoundBox, Cn3D_SizeCB);
424 */
425 }
426
427
428 /* Buttons on the OGL Viewer UI */
429
430 static ButtoN OGL_allButton;
431 static ButtoN OGL_rewindButton;
432 static ButtoN OGL_prevButton;
433 static ButtoN OGL_nextButton;
434 #ifndef WIN_MAC
435 static ButtoN OGL_playButton;
436 #endif /* ndef WIN_MAC */
437
438
439 /* the OpenGL UI */
440
441 static void AllLayerOnProc(Nlm_ButtoN b)
442 {
443 OGL_StopPlaying(Cn3D_ColorData.OGL_Data);
444 OGL_AllLayerOnProc(Cn3D_ColorData.OGL_Data);
445 OGL_DrawViewer3D(Cn3D_ColorData.OGL_Data);
446 }
447
448 static void RewindLayerProc(Nlm_ButtoN b)
449 {
450 OGL_StopPlaying(Cn3D_ColorData.OGL_Data);
451 OGL_RewindLayerProc(Cn3D_ColorData.OGL_Data);
452 OGL_DrawViewer3D(Cn3D_ColorData.OGL_Data);
453 }
454
455 static void PrevLayerProc(Nlm_ButtoN b)
456 {
457 OGL_StopPlaying(Cn3D_ColorData.OGL_Data);
458 OGL_PrevLayerProc(Cn3D_ColorData.OGL_Data);
459 OGL_DrawViewer3D(Cn3D_ColorData.OGL_Data);
460 }
461
462 static void NextLayerProc(Nlm_ButtoN b)
463 {
464 OGL_StopPlaying(Cn3D_ColorData.OGL_Data);
465 OGL_NextLayerProc(Cn3D_ColorData.OGL_Data);
466 OGL_DrawViewer3D(Cn3D_ColorData.OGL_Data);
467 }
468
469 static void PlayOGL(Nlm_ButtoN b)
470 {
471 #ifndef WIN_MAC
472 if( OGL_IsPlaying(Cn3D_ColorData.OGL_Data)) {
473 OGL_StopPlaying(Cn3D_ColorData.OGL_Data);
474 return;
475 }
476 OGL_StartPlaying(Cn3D_ColorData.OGL_Data);
477 #endif
478 }
479
480 static void Cn3D_AnimateCloseProc(ButtoN b)
481 {
482 WindoW hAnimateDlg;
483
484 hAnimateDlg= (WindoW)ParentWindow(b);
485 if(hAnimateDlg == NULL) return;
486
487 OGL_StopPlaying(Cn3D_ColorData.OGL_Data);
488 Remove(Cn3D_ColorData.AnimateDlg.Cn3D_wAnimate);
489 Cn3D_ColorData.AnimateDlg.Cn3D_wAnimate = NULL;
490 return;
491 }
492
493
494 NLM_EXTERN void Cn3D_Animate(IteM i)
495 {
496 GrouP h;
497
498 if(Cn3D_ColorData.AnimateDlg.Cn3D_wAnimate != NULL) return;
499 Cn3D_ColorData.AnimateDlg.Cn3D_wAnimate =
500 FixedWindow(-30, -20, -10, -10, "Model and Animation Controls",
501 NULL);
502 OGL_StopPlaying(Cn3D_ColorData.OGL_Data);
503 h = HiddenGroup(Cn3D_ColorData.AnimateDlg.Cn3D_wAnimate,
504 #ifndef WIN_MAC
505 6,
506 #else
507 7,
508 #endif
509 1, NULL);
510
511
512 OGL_rewindButton = Nlm_PushButton(h, "|<<", RewindLayerProc);
513 OGL_prevButton = Nlm_PushButton(h, "|< ", PrevLayerProc);
514 #ifndef WIN_MAC
515 OGL_playButton = Nlm_PushButton(h, " > ", PlayOGL);
516 #endif
517 OGL_nextButton = Nlm_PushButton(h, ">| ", NextLayerProc);
518 OGL_allButton = Nlm_PushButton(h, "All", AllLayerOnProc);
519 PushButton(h, "Close", (BtnActnProc) Cn3D_AnimateCloseProc);
520
521 Show(Cn3D_ColorData.AnimateDlg.Cn3D_wAnimate);
522 return;
523 }
524
525 /*****************************************************************************
526
527 Function: Cn3D_Asn2Matrix
528
529 Purpose: Converts an ASN.1 GLMatrix to an OpenGL matrix
530
531 Parameters: modelmatrixin, the destination opengl matrix
532 glmatrix, the source ASN.1 GLMatrix
533
534 *****************************************************************************/
535 NLM_EXTERN void Cn3D_Asn2Matrix (void *modelmatrixin, GLMatrix *glmatrix)
536 {
537 GLdouble *modelmatrix;
538
539 if(modelmatrixin == NULL || glmatrix == NULL) return;
540 modelmatrix = (GLdouble *)modelmatrixin;
541
542 if(glmatrix->scale == 0) return;
543
544 modelmatrix[0] = glmatrix->m11/(double)glmatrix->scale;
545 modelmatrix[1] = glmatrix->m12/(double)glmatrix->scale;
546 modelmatrix[2] = glmatrix->m13/(double)glmatrix->scale;
547 modelmatrix[3] = glmatrix->m14/(double)glmatrix->scale;
548
549 modelmatrix[4] = glmatrix->m21/(double)glmatrix->scale;
550 modelmatrix[5] = glmatrix->m22/(double)glmatrix->scale;
551 modelmatrix[6] = glmatrix->m23/(double)glmatrix->scale;
552 modelmatrix[7] = glmatrix->m24/(double)glmatrix->scale;
553
554 modelmatrix[8] = glmatrix->m31/(double)glmatrix->scale;
555 modelmatrix[9] = glmatrix->m32/(double)glmatrix->scale;
556 modelmatrix[10] = glmatrix->m33/(double)glmatrix->scale;
557 modelmatrix[11] = glmatrix->m34/(double)glmatrix->scale;
558
559 modelmatrix[12] = glmatrix->m41/(double)glmatrix->scale;
560 modelmatrix[13] = glmatrix->m42/(double)glmatrix->scale;
561 modelmatrix[14] = glmatrix->m43/(double)glmatrix->scale;
562 modelmatrix[15] = glmatrix->m44/(double)glmatrix->scale;
563
564 return;
565 }
566
567 /*****************************************************************************
568
569 Function: Cn3D_Matrix2Asn
570
571 Purpose: Converts an OpenGL matrix to an ASN.1 GLMatrix
572
573 Parameters: glmatrix, the destination ASN.1 GLMatrix
574 modelmatrixin, the source opengl matrix
575
576 *****************************************************************************/
577 NLM_EXTERN void Cn3D_Matrix2Asn (GLMatrix *glmatrix, void *modelmatrixin)
578 {
579 GLdouble *modelmatrix;
580
581 if(modelmatrixin == NULL || glmatrix == NULL) return;
582 modelmatrix = (GLdouble *)modelmatrixin;
583 glmatrix->scale = (Int4)VIEWSCALE;
584
585 glmatrix->m11 = (Int4)(modelmatrix[0]*glmatrix->scale);
586 glmatrix->m12 = (Int4)(modelmatrix[1]*glmatrix->scale);
587 glmatrix->m13 = (Int4)(modelmatrix[2]*glmatrix->scale);
588 glmatrix->m14 = (Int4)(modelmatrix[3]*glmatrix->scale);
589
590 glmatrix->m21 = (Int4)(modelmatrix[4]*glmatrix->scale);
591 glmatrix->m22 = (Int4)(modelmatrix[5]*glmatrix->scale);
592 glmatrix->m23 = (Int4)(modelmatrix[6]*glmatrix->scale);
593 glmatrix->m24 = (Int4)(modelmatrix[7]*glmatrix->scale);
594
595 glmatrix->m31 = (Int4)(modelmatrix[8]*glmatrix->scale);
596 glmatrix->m32 = (Int4)(modelmatrix[9]*glmatrix->scale);
597 glmatrix->m33 = (Int4)(modelmatrix[10]*glmatrix->scale);
598 glmatrix->m34 = (Int4)(modelmatrix[11]*glmatrix->scale);
599
600 glmatrix->m41 = (Int4)(modelmatrix[12]*glmatrix->scale);
601 glmatrix->m42 = (Int4)(modelmatrix[13]*glmatrix->scale);
602 glmatrix->m43 = (Int4)(modelmatrix[14]*glmatrix->scale);
603 glmatrix->m44 = (Int4)(modelmatrix[15]*glmatrix->scale);
604
605 return;
606 }
607
608
609 #endif /* _OPENGL */
610 |
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more information. |