1 #include "medit.h"
2 #include "extern.h"
3 #include "sproto.h"
4 
5 GLfloat    altcoef=0.0;
6 static int nbimg;
7 extern int refitem,refmat,reftype,imstep,imreverse;
8 extern int *pilmat,ipilmat;
9 
10 #define MAX_LST   128
11 
12 
13 /* rebuild display lists */
doLists(pScene sc,pMesh mesh)14 void doLists(pScene sc,pMesh mesh) {
15   int     k;
16 
17   /*default */
18   if ( ddebug ) printf("build display lists\n");
19 
20   if ( !morphing )  glutSetCursor(GLUT_CURSOR_WAIT);
21   for (k=0; k<MAX_LIST; k++) {
22     if ( sc->dlist[k] )  glDeleteLists(sc->dlist[k],1);
23     if ( sc->clist[k] )  glDeleteLists(sc->clist[k],1);
24     sc->dlist[k] = sc->clist[k] = (GLuint)0;
25   }
26 
27   /* poly lists */
28   sc->dlist[LTria] = listTria(sc,mesh);
29   sc->dlist[LQuad] = listQuad(sc,mesh);
30   if ( !mesh->nt && !mesh->nq ) {
31     sc->dlist[LTets] = listTetra(sc,mesh,0);
32     sc->dlist[LHexa] = listHexa(sc,mesh,0);
33   }
34   if ( sc->clip->active & C_VOL )  sc->clip->active |= C_REDO;
35   glutSetCursor(GLUT_CURSOR_INHERIT);
36   checkErrors();
37 }
38 
39 
40 /* build metric list */
doMapLists(pScene sc,pMesh mesh,int reset)41 void doMapLists(pScene sc,pMesh mesh,int reset) {
42   int   k;
43 
44   /*default */
45   if ( !mesh->sol )  return;
46   if ( ddebug ) printf("build map lists\n");
47   glutSetCursor(GLUT_CURSOR_WAIT);
48 
49   /* delete old lists */
50   if ( reset ) {
51     for (k=0; k<MAX_LIST; k++) {
52       if ( sc->mlist[k] )  glDeleteLists(sc->mlist[k],1);
53       sc->mlist[k] = (GLuint)0;
54     }
55   }
56 
57   /* create map list */
58   if ( sc->mode & S_ALTITUDE ) {
59     sc->mlist[LTria] = alt2dList(sc,mesh,LTria,sc->shrink,altcoef);
60     sc->mlist[LQuad] = alt2dList(sc,mesh,LQuad,sc->shrink,altcoef);
61   }
62   else if ( sc->mode & S_MAP ) {
63     if ( mesh->nt && !sc->mlist[LTria] )
64       sc->mlist[LTria] = listTriaMap(sc,mesh);
65     if ( mesh->nq && !sc->mlist[LQuad] )
66       sc->mlist[LQuad] = listQuadMap(sc,mesh);
67     if ( !mesh->nt && mesh->ntet && !sc->mlist[LTets] )
68       sc->mlist[LTets] = listTetraMap(sc,mesh,0);
69     if ( !mesh->nq && mesh->nhex && !sc->mlist[LHexa] )
70       sc->mlist[LHexa] = listHexaMap(sc,mesh,0);
71   }
72 
73   glutSetCursor(GLUT_CURSOR_INHERIT);
74   checkErrors();
75 }
76 
77 
78 /* rebuild iso-values lists */
doIsoLists(pScene sc,pMesh mesh,int reset)79 void doIsoLists(pScene sc,pMesh mesh,int reset) {
80   pPoint  ppt;
81   int     k,kk,ret;
82 
83   /*default */
84   if ( ddebug ) printf("build iso lists\n");
85   glutSetCursor(GLUT_CURSOR_WAIT);
86 
87   /* delete old lists */
88   if ( reset ) {
89     for (k=0; k<MAX_LIST; k++) {
90       if ( sc->ilist[k] )  glDeleteLists(sc->ilist[k],1);
91       if ( sc->vlist[k] )  glDeleteLists(sc->vlist[k],1);
92       if ( sc->cplist )    glDeleteLists(sc->cplist,1);
93       sc->ilist[k] = sc->vlist[k] = (GLuint)0;
94       sc->cplist   = (GLuint)0;
95     }
96     if ( sc->stream && sc->stream->nbstl ) {
97       for (kk=0; kk<sc->stream->nbstl; kk++) {
98         if ( sc->slist[kk] )  glDeleteLists(sc->slist[kk],1);
99         sc->slist[kk] = (GLuint)0;
100       }
101       sc->slist = (GLuint)0;
102       if ( reset < 2 )   sc->stream->nbstl = 0;
103       for (k=1; k<=mesh->np; k++) {
104         ppt = &mesh->point[k];
105         ppt->flag = 0;
106       }
107     }
108   }
109 
110   /* iso-lines */
111   if ( sc->isotyp & S_ISOLINE ) {
112     if ( mesh->nt && !sc->ilist[LTria] )
113       sc->ilist[LTria] = listTriaIso(sc,mesh);
114     if ( mesh->nq && !sc->ilist[LQuad] )
115       sc->ilist[LQuad] = listQuadIso(sc,mesh);
116   }
117   /* iso-surfaces */
118   if ( sc->isotyp & S_ISOSURF ) {
119     if ( mesh->ntet && !sc->ilist[LTets] )
120       sc->ilist[LTets] = listTetraIso(sc,mesh);
121   }
122 
123   /* vector */
124   if ( sc->isotyp & S_VECTOR ) {
125     if ( mesh->dim == 2 ) {
126       if ( mesh->nt && !sc->vlist[LTria] )
127         sc->vlist[LTria] = listTria2dVector(mesh);
128       if ( mesh->nq && !sc->vlist[LQuad] )
129         sc->vlist[LQuad] = listQuad2dVector(mesh);
130     }
131     else {
132       if ( mesh->ntet+mesh->nhex == 0 ) {
133         sc->vlist[LTria] = listTria3dVector(mesh);
134       }
135       else {
136         if ( mesh->ntet && !sc->vlist[LTets] )
137           sc->vlist[LTets] = listClipTetraVector(mesh);
138         else if ( mesh->nhex && !sc->vlist[LHexa] )
139           sc->vlist[LHexa] = listClipHexaVector(mesh);
140       }
141     }
142   }
143 
144   /* streamlines */
145   if ( sc->isotyp & S_STREAML ) {
146     if ( !mesh->adja || !sc->slist ) {
147       sc->stream = createStream(sc,mesh);
148       if ( !sc->stream )
149         sc->isotyp &= ~S_STREAML;
150     }
151     if ( sc->stream ) {
152       if ( reftype == LPoint )
153         ret = streamRefPoint(sc,mesh);
154       else if ( mesh->dim == 3 ) {
155         if ( reftype == LTria )
156           ret = streamRefTria(sc,mesh);
157         else if ( reftype == LQuad )
158           ret = streamRefQuad(sc,mesh);
159         if ( sc->picklist )  glDeleteLists(sc->picklist,1);
160         sc->picklist = 0;
161       }
162     }
163   }
164 
165   /* critical points */
166   if ( sc->isotyp & S_CRITP ) {
167     if ( mesh->dim == 2 )
168       if ( mesh->nt && !sc->cplist )
169         sc->cplist = listCritPoint(sc,mesh);
170   }
171 
172   glutSetCursor(GLUT_CURSOR_INHERIT);
173   checkErrors();
174 }
175 
176 
resetLists(pScene sc,pMesh mesh)177 void resetLists(pScene sc,pMesh mesh) {
178   int    kk;
179 
180   for (kk=0; kk<MAX_LIST; kk++) {
181     if ( sc->dlist[kk] )  glDeleteLists(sc->dlist[kk],1);
182     if ( sc->mlist[kk] )  glDeleteLists(sc->mlist[kk],1);
183     if ( sc->ilist[kk] )  glDeleteLists(sc->ilist[kk],1);
184     if ( sc->clist[kk] )  glDeleteLists(sc->clist[kk],1);
185     if ( sc->cmlist[kk] ) glDeleteLists(sc->cmlist[kk],1);
186     if ( sc->vlist[kk] )  glDeleteLists(sc->vlist[kk],1);
187     if ( sc->cplist )     glDeleteLists(sc->cplist,1);
188     sc->dlist[kk] = sc->clist[kk] = sc->mlist[kk] = (GLuint)0;
189     sc->ilist[kk] = sc->vlist[kk] = sc->cplist    = (GLuint)0;
190   }
191   if ( sc->glist )  glDeleteLists(sc->glist,1);
192   if ( sc->nlist )  glDeleteLists(sc->nlist,1);
193   sc->glist = sc->nlist = (GLuint)0;
194 }
195 
196 
keyFile(unsigned char key,int x,int y)197 void keyFile(unsigned char key,int x,int y) {
198   pScene       sc;
199   pMesh        mesh;
200   pTransform   view;
201   char        *ptr,data[128];
202   ubyte        post  = FALSE,clipon;
203   static int   nfree = 0;
204 
205   /* default */
206   sc   = cv.scene[currentScene()];
207   mesh = cv.mesh[sc->idmesh];
208   view = sc->view;
209 
210   switch(key) {
211   case 'L':  /* load prefs */
212     if ( parsop(sc,mesh) ) {
213       refitem = reftype = 0;
214       setupPalette(sc,mesh);
215       initGrafix(sc,mesh);
216       doLists(sc,mesh);
217       if ( sc->mode & S_MAP )  doMapLists(sc,mesh,1);
218       if ( sc->isotyp )        doIsoLists(sc,mesh,1);
219       glClearColor(sc->par.back[0],sc->par.back[1],sc->par.back[2],sc->par.back[3]);
220       post = GL_TRUE;
221     }
222     break;
223   case 'W':  /* save prefs */
224     saveMeditFile(mesh->name,sc);
225     break;
226 
227   case 'R':  /* reload mesh */
228     refitem = reftype = 0;
229     if ( !meshUpdate(sc,mesh) ) exit(1);
230     meshRef(sc,mesh);
231     matSort(sc);
232     setupPalette(sc,mesh);
233     doLists(sc,mesh);
234     if ( sc->mode & S_MAP ) doMapLists(sc,mesh,1);
235     if ( sc->isotyp )       doIsoLists(sc,mesh,1);
236     glClearColor(sc->par.back[0],sc->par.back[1],sc->par.back[2],sc->par.back[3]);
237     post = GL_TRUE;
238     break;
239 
240   case 'S':  /* save mesh */
241     strcpy(data,mesh->name);
242     ptr = (char*)strstr(data,".mesh");
243     if ( ptr ) *ptr = '\0';
244     sprintf(data,"%s.d.mesh",data);
245     clipon = sc->clip->active & C_ON;
246     if ( clipon )
247       clipVertices(mesh,sc,sc->clip);
248     saveMesh(sc,mesh,data,clipon);
249     break;
250 
251   case 'B':
252   case 'C':
253   case 'G':
254   case 'H':  /* hardcopy */
255   case 'T':
256     strcpy(data,mesh->name);
257     ptr = (char*)strstr(data,".mesh");
258     if ( ptr ) *ptr = '\0';
259     ptr = (char*)strstr(data,".gis");
260     if ( ptr ) *ptr = '\0';
261 
262     if ( option != SEQUENCE ) {
263       if ( key == 'H' )
264         nfree = filnum(data,nfree,"ppm");
265       else
266         nfree = filnum(data,nfree,"ps");
267       if ( nfree == -1 )  break;
268       sprintf(data,"%s.%.3d",data,nfree);
269     }
270     else
271       sprintf(data,"%s.ppm",data);
272     if (!saveimg )  glutSetCursor(GLUT_CURSOR_WAIT);
273     if ( key == 'B' || key == 'C' || key == 'G' )
274       imgTiling(sc,data,key);
275     else
276       imgHard(sc,data,key);
277     if ( animate && !(sc->persp->pmode & CAMERA) && ++nbimg > 179 ) {
278       view->angle = 0.0;
279       nbimg       = 0;
280       keyAnim('A',0,0);
281     }
282     if (!saveimg ) glutSetCursor(GLUT_CURSOR_INHERIT);
283     break;
284   case 's':  /* softcopy */
285     sftcpy(sc,mesh);
286     post = FALSE;
287     break;
288   }
289   if ( post ) glutPostRedisplay();
290 }
291 
menuFile(int item)292 void menuFile(int item) {
293   keyFile((unsigned char)item,0,0);
294 }
295 
296 
keyItem(unsigned char key,int x,int y)297 void keyItem(unsigned char key,int x,int y) {
298   pScene  sc;
299   pMesh   mesh;
300   pCube   cube;
301   ubyte   post = TRUE;
302 
303   /* default */
304   sc   = cv.scene[currentScene()];
305   mesh = cv.mesh[sc->idmesh];
306   cube = sc->cube;
307 
308   switch(key) {
309   case 'A':  /* draw axis */
310     sc->item ^= S_AXIS;
311     break;
312   case 'B':  /* draw bounding box */
313     sc->item ^= S_BOX;
314     break;
315   case 'D':  /*draw selection cube */
316     if ( cube->active & C_ON ) {
317       cube->active &= ~(C_ON+C_EDIT);
318       dumpCube(sc,mesh,cube);
319     }
320     else {
321       cube->active |= C_ON;
322     }
323     break;
324   case 'G':  /* draw grid */
325     sc->item ^= S_GRID;
326     break;
327   case 'j':  /* toggle info */
328     sc->type ^= S_DECO;
329     break;
330   case 'P':  /* toggle point nums */
331     sc->item ^= S_NUMP;
332     break;
333   case 'F':  /* toggle face nums */
334     sc->item ^= S_NUMF;
335     break;
336   case 'g':  /* const. items */
337     if ( !sc->glist )  post = FALSE;
338     sc->item ^= S_GEOM;
339     break;
340   case 'N':
341     if ( mesh->nvn )
342       sc->type ^= S_NORMAL;
343     else
344       post = FALSE;
345     break;
346   case 'O':
347     if ( mesh->nvn ) {
348       sc->type ^= S_OPPOS;
349       if ( sc->nlist ) {
350 	      glDeleteLists(sc->nlist,1);
351 	      sc->nlist = 0;
352       }
353       else
354 	      post = FALSE;
355     }
356     else
357       post = FALSE;
358     break;
359   }
360   if ( post )  glutPostRedisplay();
361 }
362 
menuItem(int item)363 void menuItem(int item) {
364   keyItem((unsigned char)item,0,0);
365 }
366 
367 
keyAnim(unsigned char key,int x,int y)368 void keyAnim(unsigned char key,int x,int y) {
369   pScene  sc;
370   pMesh   mesh;
371   pClip   clip;
372   ubyte   post = TRUE;
373   char   *ptr,base[256];
374   static int depart = -1;
375 
376   /* default */
377   sc   = cv.scene[currentScene()];
378   mesh = cv.mesh[sc->idmesh];
379   clip = sc->clip;
380   if ( depart == -1 )
381     depart = animdep;
382 
383   switch(key) {
384   case 'A':  /* switch animation */
385     if ( animate ) {
386       sc->view->manim     = GL_FALSE;
387       clip->cliptr->manim = GL_FALSE;
388       sc->view->angle = 0.0f;
389       glutIdleFunc(NULL);
390     }
391     else {
392       sc->view->manim     = GL_TRUE;
393       clip->cliptr->manim = GL_TRUE;
394       if ( sc->persp->pmode == CAMERA )
395         glutIdleFunc(glutIdle);
396     }
397     animate = 1-animate;
398     post = FALSE;
399     break;
400   case 'I':  /* save image */
401     saveimg = 1 - saveimg;
402     nbimg   = 0;
403     post    = GL_FALSE;
404     break;
405 
406   case 'M':  /* morphing */
407     if ( morphing )
408       glutIdleFunc(NULL);
409     else
410       glutIdleFunc(glutIdle);
411     morphing = 1-morphing;
412     post = FALSE;
413     break;
414   case 'R':  /* next morph */
415     imreverse = 1-imreverse;
416     break;
417 
418   case 'S':  /* start animation */
419     if ( ddebug ) fprintf(stdout,"debut sequence %d a %d\n",animdep,animfin);
420     glutSetWindow(sc->idwin);
421     if ( option == SEQUENCE )
422       playAnim(sc,mesh,animdep,animfin);
423     if ( !saveimg )  post = FALSE;
424     break;
425 
426   case 'f': /* first mesh */
427     /* get basename */
428     ptr = (char *)strrchr(mesh->name,'.');
429     if ( ptr )  *ptr = '\0';
430     strcpy(base,mesh->name);
431     resetLists(sc,mesh);
432     if ( !loadNextMesh(mesh,animdep,0) )  break;
433     doLists(sc,mesh);
434     if ( sc->mode & S_MAP ) doMapLists(sc,mesh,0);
435     if ( sc->isotyp )       doIsoLists(sc,mesh,0);
436     strcpy(mesh->name,base);
437     break;
438 
439   case 'l':
440     /* get basename */
441     ptr = (char *)strrchr(mesh->name,'.');
442     if ( ptr )  *ptr = '\0';
443     strcpy(base,mesh->name);
444     resetLists(sc,mesh);
445     if ( !loadNextMesh(mesh,animfin,0) )  break;
446     doLists(sc,mesh);
447     if ( sc->mode & S_MAP ) doMapLists(sc,mesh,0);
448     if ( sc->isotyp )       doIsoLists(sc,mesh,0);
449     strcpy(mesh->name,base);
450     break;
451 
452   case 'n':
453     /* get basename */
454     if ( ++depart > animfin )  depart = animdep;
455     ptr = (char *)strrchr(mesh->name,'.');
456     if ( ptr )  *ptr = '\0';
457     strcpy(base,mesh->name);
458     resetLists(sc,mesh);
459     if ( !loadNextMesh(mesh,depart,0) )  break;
460     doLists(sc,mesh);
461     if ( sc->mode & S_MAP ) doMapLists(sc,mesh,0);
462     if ( sc->isotyp )       doIsoLists(sc,mesh,0);
463     strcpy(mesh->name,base);
464     break;
465 
466   case 'p':
467     /* get basename */
468     if ( --depart < animdep )  depart = animfin;
469     ptr = (char *)strrchr(mesh->name,'.');
470     if ( ptr )  *ptr = '\0';
471     strcpy(base,mesh->name);
472     resetLists(sc,mesh);
473     if ( !loadNextMesh(mesh,depart,0) )  break;
474     doLists(sc,mesh);
475     if ( sc->mode & S_MAP ) doMapLists(sc,mesh,0);
476     if ( sc->isotyp )       doIsoLists(sc,mesh,0);
477     strcpy(mesh->name,base);
478     break;
479   }
480 
481   if ( post == TRUE )   glutPostRedisplay();
482 }
483 
menuAnim(int item)484 void menuAnim(int item) {
485   keyAnim((unsigned char)item,0,0);
486 }
487 
keyTrajet(unsigned char key,int x,int y)488 void keyTrajet(unsigned char key,int x,int y) {
489   pScene   sc;
490   pMesh    mesh;
491 
492   sc = cv.scene[currentScene()];
493   mesh = cv.mesh[sc->idmesh];
494   switch(key) {
495   case 'C': /* add control point */
496     pathAdd(sc,x,y);
497     break;
498   case 'S': /* show all points */
499     sc->type ^= S_PATH;
500     /*if ( sc->path.tlist )  glDeleteLists(sc->path.tlist,1);*/
501     if ( sc->type & S_PATH && !sc->path.tlist )
502       sc->path.tlist = pathList(sc);
503     break;
504   case 'F': /* follow path */
505     break;
506   case 'L': /* load path */
507     pathLoad(mesh->name,sc);
508     break;
509   case 'W': /* save path */
510     pathSave(mesh->name,sc);
511     break;
512   }
513   glutPostRedisplay();
514 }
515 
menuTrajet(int item)516 void menuTrajet(int item) {
517   keyTrajet((unsigned char)item,0,0);
518 }
519 
keyMode(unsigned char key,int x,int y)520 void keyMode(unsigned char key,int x,int y) {
521   pScene  sc;
522   pMesh   mesh;
523   ubyte   post = TRUE,dolist = FALSE,material;
524 
525   sc   = cv.scene[currentScene()];
526   mesh = cv.mesh[sc->idmesh];
527   material = sc->mode & S_MATERIAL;
528 
529   switch(key) {
530   case 'D':  /* depth lines */
531     if ( sc->mode == DEPTH ) break;
532     sc->mode = DEPTH;
533     break;
534   case 'S': /* toggle smooth shading */
535     if ( sc->mode == FILL )
536       break;
537     sc->mode = FILL;
538     if ( material ) sc->mode |= S_MATERIAL;
539     break;
540   case 'P': /* toggle smooth shaded polys */
541     if ( sc->mode == SHADED )
542       break;
543     sc->mode = SHADED;
544     if ( material ) sc->mode |= S_MATERIAL;
545     break;
546   case 'H': /* hidden lines */
547     if ( sc->mode == HIDDEN ) break;
548     sc->mode = HIDDEN;
549     if ( material ) sc->mode |= S_MATERIAL;
550     break;
551   case 'W':  /* wireframe */
552     if ( sc->mode == WIRE ) break;
553     sc->mode = WIRE;
554     if ( material ) sc->mode |= S_MATERIAL;
555     break;
556   case 'n': /* toggle normals */
557     if ( mesh->nvn == 0 ) {
558       post = FALSE;
559       break;
560     }
561     sc->type ^= S_FLAT;
562     dolist = TRUE;
563     break;
564   default:
565     post = FALSE;
566     break;
567   }
568   if ( dolist == TRUE ) doLists(sc,mesh);
569   if ( post == TRUE )   glutPostRedisplay();
570 }
571 
menuMode(int item)572 void menuMode(int item) {
573   keyMode((unsigned char)item,0,0);
574 }
575 
576 
menuScene(int item)577 void menuScene(int item) {
578   keyScene((unsigned char)item,0,0);
579 }
580 
keyView(unsigned char key,int x,int y)581 void keyView(unsigned char key,int x,int y) {
582   pScene  sc,sc1;
583   pMesh   mesh;
584   float   dmax;
585   ubyte   post = FALSE;
586 
587   sc   = cv.scene[currentScene()];
588   mesh = cv.mesh[sc->idmesh];
589   /*glutSetMenu(vmenu);*/
590 
591   switch(key) {
592   case 'R':
593     sc->type |= S_RESET;
594     dmax = mesh->xmax - mesh->xmin;
595     dmax = max(dmax,mesh->ymax - mesh->ymin);
596     dmax = max(dmax,mesh->zmax - mesh->zmin);
597     sc->cx = sc->cy = sc->cz = 0.0f;
598     sc->dmax = fabs(dmax);
599     if ( sc->persp->pmode == PERSPECTIVE ) {
600       resetTransform(sc->view);
601       initPersp(sc->persp,sc->dmax);
602     }
603     else if ( sc->persp->pmode == CAMERA ) {
604       initPersp(sc->persp,sc->dmax);
605       initCamera(sc,sc->camera->vecup);
606       sc->persp->pmode = CAMERA;
607     }
608     reshapeScene(sc->par.xs,sc->par.ys);
609     post = TRUE;
610     break;
611   case 'C':
612     copyView(sc->view,sc->camera,sc->persp);
613     copyClip(sc->clip);
614     break;
615   case 'L':  /* link view */
616     if ( !linkView(sc) )  return;
617     reshapeScene(sc->par.xs,sc->par.ys);
618     post = TRUE;
619     break;
620   case 'P':
621     if ( pasteView(sc->view,sc->camera,sc->persp) &&
622          pasteClip(sc->clip) ) {
623       reshapeScene(sc->par.xs,sc->par.ys);
624       post = TRUE;
625     }
626     break;
627   case 'U':
628     unlinkView(sc);
629     break;
630 
631   case 'D':  /* duplicate view */
632     if ( cv.nbs == MAX_SCENE )  break;
633     if ( !cv.scene[++cv.nbs] ) {
634       cv.scene[cv.nbs] = (pScene)M_calloc(1,sizeof(Scene),"menus.scene");
635       if ( !cv.scene[cv.nbs] )  break;
636       sc1 = cv.scene[cv.nbs];
637       sc1->material = (pMaterial)calloc(2+sc->par.nbmat,sizeof(Material));
638       assert(sc1->material);
639     }
640     sc1 = cv.scene[cv.nbs];
641     memcpy(sc1,sc,sizeof(Scene));
642     memcpy(sc1->material,sc->material,sc->par.nbmat*sizeof(Material));
643     memcpy(&sc1->par,&sc->par,sizeof(Param));
644     if ( !createScene(sc1,sc1->idmesh) ) {
645       fprintf(stdout,"  ## Unable to create\n");
646       return;
647     }
648     copyView(sc->view,sc->camera,sc->persp);
649     copyClip(sc->clip);
650     pasteView(sc1->view,sc1->camera,sc1->persp);
651     pasteClip(sc1->clip);
652     break;
653   }
654   if ( post )  glutPostRedisplay();
655 }
656 
menuView(int item)657 void menuView(int item) {
658   keyView((unsigned char)item,0,0);
659 }
660 
keyColor(unsigned char key,int x,int y)661 void keyColor(unsigned char key,int x,int y) {
662   pScene     sc;
663   pMesh      mesh;
664   pMaterial  pm;
665   int        i,k;
666   ubyte      post = TRUE,dolist = FALSE;
667 
668   sc   = cv.scene[currentScene()];
669   mesh = cv.mesh[sc->idmesh];
670 
671   switch(key) {
672   case 'b':  /* reverse backcolor */
673     sc->par.back[0] = 1.0f - sc->par.back[0];
674     sc->par.back[1] = 1.0f - sc->par.back[1];
675     sc->par.back[2] = 1.0f - sc->par.back[2];
676     glClearColor(sc->par.back[0],sc->par.back[1],sc->par.back[2],sc->par.back[3]);
677     if ( !sc->par.linc ) {
678       sc->par.line[0] = 1.0f - sc->par.line[0];
679       sc->par.line[1] = 1.0f - sc->par.line[1];
680       sc->par.line[2] = 1.0f - sc->par.line[2];
681     }
682     break;
683   case 'e':  /* toggle matcolors */
684     sc->mode ^= S_MATERIAL;
685     dolist = TRUE;
686     break;
687   case 'E':  /* edit matcolors */
688     post   = FALSE;
689     matEdit(sc);
690     break;
691   case 'r':
692       if ( refmat<0 || ipilmat == sc->par.nbmat )  break;
693       pilmat[++ipilmat] = refmat;
694       pm = &sc->material[refmat];
695       pm->flag = 1;
696       updatePoints(sc,mesh,refmat);
697       if ( sc->picklist ) glDeleteLists(sc->picklist,1);
698       sc->picklist = 0;
699       refmat = -1;
700       dolist = TRUE;
701       post   = TRUE;
702     break;
703   case 'R':  /* reset materials */
704     for (k=0; k<sc->par.nbmat; k++) {
705       pm = &sc->material[k];
706       for (i=LTria; i<=LHexa; i++)
707         pm->depmat[i] = abs(pm->depmat[i]);
708     }
709     dolist = TRUE;
710     break;
711   default:
712     post = FALSE;
713   }
714   if ( dolist ) doLists(sc,mesh);
715   if ( post )   glutPostRedisplay();
716 }
717 
menuColor(int item)718 void menuColor(int item) {
719   keyColor((unsigned char)item,0,0);
720 }
721 
722 
keyClip(unsigned char key,int x,int y)723 void keyClip(unsigned char key,int x,int y) {
724   pScene  sc;
725   pMesh   mesh;
726   pClip   clip;
727   ubyte   post = TRUE;
728 
729   /* default */
730   sc   = cv.scene[currentScene()];
731   mesh = cv.mesh[sc->idmesh];
732   clip = sc->clip;
733 
734   switch(key) {
735   case 'C': /* toggle clipping */
736     if ( clip->active & C_ON )
737       clip->active &= ~(C_ON+C_EDIT);
738     else {
739       clip->active |= C_ON;
740       if ( mesh->ntet+mesh->nhex )  clip->active |= C_VOL;
741     }
742     break;
743   case 'E': /* edit clip plane */
744     if ( !(clip->active & C_ON) )  return;
745     if ( clip->active & C_FREEZE ) clip->active ^= C_FREEZE;
746     clip->active ^= C_EDIT;
747     break;
748   case 'F':  /* freeze clip */
749     if ( !(clip->active & C_ON) )  return;
750     if ( clip->active & C_EDIT )   clip->active ^= C_EDIT;
751     clip->active ^= C_FREEZE;
752     break;
753   case 'H':  /* toggle draw plane */
754     clip->active ^= C_HIDE;
755     break;
756   case 'I': /* inverse orientation */
757     invertClip(sc,clip);
758     clip->active |= C_REDO;
759     break;
760   case 'K':  /* toggle capping */
761     clip->active ^= C_CAP;
762     clip->active |= C_REDO;
763     break;
764   case 'R':  /* reset clip */
765     if ( !(clip->active & C_ON) ) break;
766     resetClip(sc,clip,mesh);
767     break;
768   case 'Z':  /* toggle volclip */
769     clip->active ^= C_VOL;
770     if ( clip->active & C_VOL )
771       clip->active |= C_REDO;
772     break;
773   }
774   if ( post ) glutPostRedisplay();
775 }
776 
menuClip(int item)777 void menuClip(int item) {
778   keyClip((unsigned char)item,0,0);
779 }
780 
781 
keyCube(unsigned char key,int x,int y)782 void keyCube(unsigned char key,int x,int y) {
783   pScene  sc;
784   pMesh   mesh;
785   pCube   cube;
786   ubyte   post = TRUE;
787 
788   /* default */
789   sc   = cv.scene[currentScene()];
790   mesh = cv.mesh[sc->idmesh];
791   cube = sc->cube;
792 
793   switch(key) {
794   case 'C': /* toggle clipping */
795     if ( cube->active & C_ON )
796       cube->active &= ~(C_ON+C_EDIT);
797     else
798       cube->active |= C_ON;
799     break;
800   case 'E': /* edit clip plane */
801     if ( !(cube->active & C_ON) )  return;
802     if ( cube->active & C_FREEZE ) cube->active ^= C_FREEZE;
803     cube->active ^= C_EDIT;
804     break;
805   case 'F':  /* freeze cube */
806     if ( !(cube->active & C_ON) )  return;
807     if ( cube->active & C_EDIT )   cube->active ^= C_EDIT;
808     cube->active ^= C_FREEZE;
809     break;
810   case 'R':  /* reset cube */
811     if ( !(cube->active & C_ON) ) break;
812     resetCube(sc,cube,mesh);
813     break;
814   }
815   if ( post ) glutPostRedisplay();
816 }
817 
keyFeature(unsigned char key,int x,int y)818 void keyFeature(unsigned char key,int x,int y) {
819   pScene  sc;
820   pMesh   mesh;
821   ubyte   post=TRUE,dolist=TRUE;
822 
823   /* default */
824   sc   = cv.scene[currentScene()];
825   mesh = cv.mesh[sc->idmesh];
826 
827   switch(key) {
828   case 'S':  /* shrink mode */
829   case 'V':  /* volumic shrink */
830     if ( sc->shrink < 0.99 )
831       sc->shrink = 1.0f;
832     else
833       sc->shrink = 0.95;
834     dolist = TRUE;
835     break;
836   case 'I':  /* increase shrink value */
837     if ( sc->shrink > 0.99 ) break;
838     sc->shrink -= .05;
839     if ( sc->shrink < 0.1 ) sc->shrink = 0.1;
840     dolist = TRUE;
841     break;
842   case 'i':  /* decrease shrink value */
843     if ( sc->shrink > 0.99 ) break;
844     sc->shrink += .05;
845     if ( sc->shrink > 0.95 ) sc->shrink = 0.95;
846     dolist = TRUE;
847     break;
848   case 's':  /* scissor mode */
849     if ( mesh->dim == 2 )  break;
850     sc->type ^= S_SCISSOR;
851     if ( sc->type & S_SCISSOR )
852       glutDisplayFunc(scissorScene);
853     else {
854       glutDisplayFunc(redrawScene);
855       reshapeScene(sc->par.xs,sc->par.ys);
856     }
857     break;
858   }
859   if ( dolist == TRUE ) {
860     doLists(sc,mesh);
861     if ( sc->mode & S_MAP )  doMapLists(sc,mesh,1);
862     /*if ( sc->isotyp )        doIsoLists(sc,mesh,1);*/
863   }
864   if ( post == TRUE )   glutPostRedisplay();
865 }
866 
menuFeature(int item)867 void menuFeature(int item) {
868   keyFeature((unsigned char)item,0,0);
869 }
870 
871 
menuImage(int item)872 void menuImage(int item) {
873   imgtype = item;
874 }
875 
keyMetric(unsigned char key,int x,int y)876 void keyMetric(unsigned char key,int x,int y) {
877   pScene  sc;
878   pMesh   mesh;
879   pPoint  ppt;
880   float   maxd;
881   int     k,kk;
882   ubyte   post=TRUE;
883 
884   /* default */
885   sc   = cv.scene[currentScene()];
886   mesh = cv.mesh[sc->idmesh];
887 
888   switch(key) {
889   case 'c': /* critical points */
890     if ( !mesh->nbb )  return;
891     sc->isotyp ^= S_CRITP;
892     doIsoLists(sc,mesh,0);
893     break;
894   case 'f':  /* flush streamlines */
895     if ( sc->stream->nbstl ) {
896       for (kk=0; kk<sc->stream->nbstl; kk++) {
897         if ( sc->slist[kk] )  glDeleteLists(sc->slist[kk],1);
898         sc->slist[kk] = (GLuint)0;
899       }
900       sc->stream->nbstl = 0;
901       for (k=1; k<=mesh->np; k++) {
902         ppt = &mesh->point[k];
903         ppt->flag = 0;
904       }
905     }
906     break;
907   case 'l': /* iso-lines */
908     if ( !mesh->nbb )  return;
909     sc->isotyp ^= S_ISOLINE;
910     doIsoLists(sc,mesh,0);
911     break;
912   case 's': /* iso-surfaces */
913     if ( !mesh->nbb ) return;
914     sc->isotyp ^= S_ISOSURF;
915     doIsoLists(sc,mesh,0);
916     break;
917   case 'u': /* field lines animation */
918     if ( !mesh->nbb || mesh->nfield != mesh->dim )  return;
919     if ( refitem ) {
920       sc->isotyp |= S_PARTICLE;
921       createParticle(sc,mesh);
922     }
923     glutIdleFunc(streamIdle);
924     break;
925   case 'd': /* displacement */
926     if ( !mesh->nbb || mesh->nfield != mesh->dim )  return;
927     sc->mode ^= S_DISPL;
928 	  meshCoord(mesh,(sc->mode & S_DISPL) ? 1 : 0);
929 	  meshBox(mesh,0);
930     doLists(sc,mesh);
931     if ( sc->mode & S_MAP ) doMapLists(sc,mesh,1);
932     if ( sc->isotyp )       doIsoLists(sc,mesh,1);
933     break;
934 
935   case 'v': /* streamlines */
936     if ( !mesh->nbb || mesh->nfield != mesh->dim )  return;
937     if ( refitem ) {
938       sc->isotyp |= S_STREAML;
939       doIsoLists(sc,mesh,0);
940     }
941     else {
942       if ( !streamIsoPoint(sc,mesh) ) {
943         post = FALSE;
944         sc->isotyp &= ~S_STREAML;
945       }
946     }
947     break;
948   case 'w': /*vector/tensor */
949     if ( mesh->nfield != mesh->dim ) {
950       if ( mesh->dim==2 && mesh->nfield == 3 ) {
951         if ( sc->picklist ) {
952           glDeleteLists(sc->picklist,1);
953           sc->picklist = 0;
954           break;
955         }
956         else {
957           sc->picklist = drawAllEllipse(sc,mesh);
958           break;
959         }
960       }
961       return;
962     }
963     sc->isotyp ^= S_VECTOR;
964     if ( mesh->dim == 3 )
965       if ( mesh->ntet+mesh->nhex && !(sc->clip->active & C_ON) )
966         return;
967     doIsoLists(sc,mesh,0);
968     break;
969 
970   case 'k': /* toggle elevation */
971     if ( mesh->dim != 2 )  return;
972     sc->mode ^= S_ALTITUDE;
973     if ( altcoef == 0.0 ) {
974       maxd = max(mesh->xmax-mesh->xmin,mesh->ymax-mesh->ymin);
975       altcoef = 0.3*maxd / mesh->bbmax;
976     }
977     if ( !(sc->mode & S_ALTITUDE) )
978       sc->type |= S_RESET;
979     doMapLists(sc,mesh,1);
980     break;
981   case 'K': /* elevation coeff */
982     fprintf(stdout,"elevation coeff (%.2f): ",altcoef);
983     fflush(stdout);
984     fflush(stdin); fscanf(stdin,"%f",&altcoef);
985     if ( altcoef == 0.0 ) sc->mode |= ~S_ALTITUDE;
986     sc->type |= S_RESET;
987     doMapLists(sc,mesh,1);
988     doIsoLists(sc,mesh,1);
989     break;
990 
991   case 'm': /* display metric */
992     if ( !mesh->nbb ) return;
993     sc->mode ^= S_MAP;
994     doMapLists(sc,mesh,1);
995     if ( sc->mode & S_MAP ) {
996       if ( sc->clip->active & C_ON ) sc->clip->active |= C_REDO;
997       if ( !(sc->item & S_PALETTE) )
998         sc->item ^= S_PALETTE;
999     }
1000     else if ( sc->item & S_PALETTE )
1001       sc->item ^= S_PALETTE;
1002     break;
1003   case 'p': /* toggle palette */
1004     if ( !mesh->nbb ) return;
1005     sc->item ^= S_PALETTE;
1006     break;
1007 
1008   default:
1009     post = FALSE;
1010     break;
1011   }
1012   if ( post )  glutPostRedisplay();
1013 }
1014 
menuMetric(int item)1015 void menuMetric(int item) {
1016   keyMetric((unsigned char)item,0,0);
1017 }
1018 
1019 
createMenus(pScene sc,pMesh mesh)1020 int createMenus(pScene sc,pMesh mesh) {
1021   int   menu,amenu,fmenu,femenu,vmenu,mmenu,smenu;
1022   int   clmenu,cmenu,vwmenu,trmenu;
1023 
1024   /* default */
1025   if ( ddebug )  printf("create menus\n");
1026   smenu = 0;
1027 
1028   /* File management menu */
1029   fmenu = glutCreateMenu(menuFile);
1030   glutAddMenuEntry("[L] Load prefs",'L');
1031   glutAddMenuEntry("[W] Save prefs",'W');
1032   glutAddMenuEntry("    Update mesh",'R');
1033   glutAddMenuEntry("    Save mesh",'S');
1034   glutAddMenuEntry("[H] Hardcopy PPM",'H');
1035   glutAddMenuEntry("    Hardcopy EPS (Color)",'C');
1036   glutAddMenuEntry("    Hardcopy EPS (Grey)",'G');
1037   glutAddMenuEntry("    Hardcopy EPS (B/W)",'B');
1038   glutAddMenuEntry("    Softcopy EPS",'s');
1039 
1040   /* rendering mode selector */
1041   mmenu = glutCreateMenu(menuMode);
1042   glutAddMenuEntry("Wireframe",'W');
1043   glutAddMenuEntry("Depth  lines",'D');
1044   glutAddMenuEntry("Hidden lines",'H');
1045   glutAddMenuEntry("Shading",'S');
1046   glutAddMenuEntry("Shading+lines",'P');
1047   if ( mesh->nvn > 0 )
1048     glutAddMenuEntry("[n] Toggle Normals",'n');
1049 
1050   /* color & material menu */
1051   cmenu = glutCreateMenu(menuColor);
1052   glutAddMenuEntry("[b] Toggle backcolor",'b');
1053   glutAddMenuEntry("[e] Toggle matcolors",'e');
1054   glutAddMenuEntry("[E] Edit   matcolors",'E');
1055   glutAddMenuEntry("[r] Hide   material",'r');
1056   glutAddMenuEntry("[R] Reset  materials",'R');
1057 
1058   /* metric */
1059   if ( mesh->nbb > 0 ) {
1060     smenu = glutCreateMenu(menuMetric);
1061     glutAddMenuEntry("[m] Toggle metric",'m');
1062     glutAddMenuEntry("[p] Toggle palette",'p');
1063     if ( mesh->typage == 2 )
1064       glutAddMenuEntry("[o] Toggle iso-lines",'l');
1065     if ( mesh->ntet+mesh->nhex > 0 && mesh->nfield == 1 )
1066       glutAddMenuEntry("    Toggle iso-surfaces",'s');
1067     if ( mesh->nfield == mesh->dim ) {
1068       glutAddMenuEntry("[w]  Toggle vector/tensor",'w');
1069 	    glutAddMenuEntry("     Toggle displacement",'d');
1070       glutAddMenuEntry("[v]  Toggle streamlines",'v');
1071       glutAddMenuEntry("     Flush streamlines",'f');
1072       glutAddMenuEntry("     Particle advection",'u');
1073       if ( mesh->dim == 2 )
1074         glutAddMenuEntry("     Critical points",'c');
1075     }
1076     if ( mesh->dim == 2 ) {
1077       glutAddMenuEntry("[k]  Toggle elevation",'k');
1078       glutAddMenuEntry("[K]  Elevation coeff",'K');
1079     }
1080   }
1081 
1082   /* Show misc. items */
1083   vmenu = glutCreateMenu(menuItem);
1084   glutAddMenuEntry("[A] Axis",'A');
1085   glutAddMenuEntry("[B] Bounding box",'B');
1086   glutAddMenuEntry("[G] Grid ",'G');
1087   if ( sc->glist )
1088     glutAddMenuEntry("[g] Geometric items",'g');
1089   glutAddMenuEntry("[j] Toggle Info",'j');
1090   glutAddMenuEntry("[P] Toggle Point num",'P');
1091   glutAddMenuEntry("[F] Toggle Face num",'F');
1092   if ( mesh->nvn ) {
1093     glutAddMenuEntry("[N] Toggle normals",'N');
1094     glutAddMenuEntry("[O] Revert normals",'O');
1095   }
1096 
1097   /* clipping menu */
1098   clmenu = glutCreateMenu(menuClip);
1099   glutAddMenuEntry("[F1] Toggle clip",'C');
1100   glutAddMenuEntry("[F2] Edit clip",'E');
1101   glutAddMenuEntry("[F3] Freeze clip",'F');
1102   glutAddMenuEntry("     Inverse orient",'I');
1103   if ( mesh->ntet+mesh->nhex > 0 )
1104     glutAddMenuEntry("     Toggle capping",'K');
1105   glutAddMenuEntry("     Toggle plane",'H');
1106   glutAddMenuEntry(" --  Reset clip",'R');
1107   if ( mesh->ntet+mesh->nhex > 0 ) {
1108     sc->clip->active |= C_VOL;
1109     glutAddMenuEntry("[F4] Toggle Vclip",'Z');
1110   }
1111 
1112   /* feature menu */
1113   femenu = glutCreateMenu(menuFeature);
1114   if ( mesh->ntet+mesh->nhex > 0 )
1115     glutAddMenuEntry("[F5] Toggle Vshrink",'V');
1116   else
1117     glutAddMenuEntry("[F5] Toggle shrink",'S');
1118   glutAddMenuEntry("[F6] Increase shrink",'I');
1119   glutAddMenuEntry("[F7] Decrease shrink",'i');
1120   if ( mesh->dim == 3 )
1121     glutAddMenuEntry("Toggle splitview",'s');
1122 
1123   /* view handler menu */
1124   vwmenu = glutCreateMenu(menuView);
1125   glutAddMenuEntry("[i] Reset",'R');
1126   glutAddMenuEntry("[Alt-c] Copy",'C');
1127   glutAddMenuEntry("[Alt-p] Paste",'P');
1128   glutAddMenuEntry("[Alt+l] Link",'L');
1129   glutAddMenuEntry("[Alt+u] Unlink",'U');
1130   /*glutAddMenuEntry("[Alt+d] Duplicate",'D');*/
1131 
1132   /* animation menu */
1133   amenu = glutCreateMenu(menuAnim);
1134   glutAddMenuEntry("[a] Toggle Anim",'A');
1135   glutAddMenuEntry("Toggle ImgSave",'I');
1136   if ( option == SEQUENCE || option == SEQUENCE + PARTICLE ) {
1137     glutAddMenuEntry("Play  sequence",'S');
1138     glutAddMenuEntry("First mesh",'f');
1139     glutAddMenuEntry("Last  mesh",'l');
1140     glutAddMenuEntry("Next mesh",'n');
1141     glutAddMenuEntry("Prev mesh",'p');
1142   }
1143   else if ( option == MORPHING ) {
1144     glutAddMenuEntry("Start/Stop morph.",'M');
1145     glutAddMenuEntry("Toggle AutoReverse",'R');
1146   }
1147 
1148   /* trajectoire menu */
1149   if ( mesh->dim == 3 || mesh->nbb ) {
1150     trmenu = glutCreateMenu(menuTrajet);
1151     glutAddMenuEntry("New Ctrl point",'C');
1152     glutAddMenuEntry("Toggle path",'S');
1153     glutAddMenuEntry("Follow path",'F');
1154     glutAddMenuEntry("Load path",'L');
1155     glutAddMenuEntry("Save path",'W');
1156   }
1157   else
1158     trmenu = 0;
1159 
1160   /* main scene menu */
1161   menu = glutCreateMenu(menuScene);
1162   glutAddSubMenu("File",fmenu);
1163   glutAddSubMenu("Render mode",mmenu);
1164   glutAddSubMenu("Colors, Materials",cmenu);
1165   if ( mesh->nbb )
1166     glutAddSubMenu("Data",smenu);
1167   glutAddSubMenu("Items",vmenu);
1168   if ( mesh->dim == 3 )
1169     glutAddSubMenu("Clipping",clmenu);
1170   glutAddSubMenu("Features",femenu);
1171   glutAddSubMenu("View",vwmenu);
1172   glutAddSubMenu("Animation",amenu);
1173   /*if ( trmenu )
1174     glutAddSubMenu("Trajectory",trmenu);
1175   */
1176   glutAddMenuEntry("",'\0');
1177   glutAddMenuEntry("Close window",'X');
1178   glutAddMenuEntry("Quit",'q');
1179 
1180   return(1);
1181 }
1182