1 /*****************************************************************************
2  *
3  *  Elmer, A Finite Element Software for Multiphysical Problems
4  *
5  *  Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland
6  *
7  *  This program is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU General Public License
9  *  as published by the Free Software Foundation; either version 2
10  *  of the License, or (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program (in file fem/GPL-2); if not, write to the
19  *  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  *  Boston, MA 02110-1301, USA.
21  *
22  *****************************************************************************/
23 
24 /*******************************************************************************
25  *
26  * Action routines for the mesh visual class.
27  *
28  *******************************************************************************
29  *
30  *                     Author:       Juha Ruokolainen
31  *
32  *                    Address: CSC - IT Center for Science Ltd.
33  *                                Keilaranta 14, P.O. BOX 405
34  *                                  02101 Espoo, Finland
35  *                                  Tel. +358 0 457 2723
36  *                                Telefax: +358 0 457 2302
37  *                              EMail: Juha.Ruokolainen@csc.fi
38  *
39  *                       Date: 26 Sep 1995
40  *
41  *
42  * Modification history:
43  *
44  * 28 Sep 1995, modified vis_initialize_mesh_visual to set the VisualName field
45  *             of the visual_type structure
46  *
47  * Juha R.
48  *
49  ******************************************************************************/
50 
51 #include "../elmerpost.h"
52 
53 
54 /******************************************************************************
55  *
56  * Parameter sructure definitios for mesh visual class
57  *
58  ******************************************************************************/
59 static char *mesh_style_names[] =
60 {
61    "none", "line", "surf", "line_and_surf", NULL
62 };
63 
64 typedef struct mesh_s
65 {
66     scalar_t   *ColorData;
67 
68     mesh_style_t Style;
69 
70     edge_style_t EdgeStyle;
71 
72     material_t *Material;
73     material_t *EdgeMaterial;
74     colormap_t *ColorMap;
75 
76     int LineQuality;
77     double LineWidth;
78 
79     line_style_t LineStyle;
80 
81     logical_t NodeNumbers;
82 } mesh_t;
83 
84 
85 /*******************************************************************************
86  *
87  *     Name:         vis_polygon
88  *
89  *     Purpose:
90  *
91  *
92  *     Parameters:
93  *
94  *         Input:    (polygon_t *) polygon
95  *
96  *         Output:   graphics
97  *
98  *   Return value:   void
99  *
100  ******************************************************************************/
vis_polygon(polygon_t * poly)101 void vis_polygon( polygon_t *poly)
102 {
103     int n=3;
104 
105     gra_poly3( n,poly->x,poly->y,poly->z,poly->u,poly->v,poly->w,poly->c );
106 }
107 
108 /*******************************************************************************
109  *
110  *     Name:         vis_triangle
111  *
112  *     Purpose:
113  *
114  *
115  *     Parameters:
116  *
117  *         Input:    (triangle_t *) triangle
118  *                   (vertex_t   *) vertex array
119  *                   (double     *) quantity to use color the edges (or NULL)
120  *                   (double,double ) CScl,CAdd are constatnt to scale color
121  *                                  range (0-1)
122  *                   (line_style_t) line style, either line_style_line or
123  *                                  line_style_cylider
124  *
125  *         Output:   graphics
126  *
127  *   Return value:   void
128  *
129  ******************************************************************************/
vis_triangle(triangle_t * t,vertex_t * v,double * color,double CScl,double CAdd)130 void vis_triangle
131    (
132       triangle_t *t,vertex_t *v,double *color,double CScl,double CAdd
133    )
134 {
135     float x[3][3],n[3][3],c[3];
136     int j,k;
137 
138     for( j=0; j<3; j++ )
139     {
140         k = t->v[j];
141         x[j][0] = v[k].x[0];
142         x[j][1] = v[k].x[1];
143         x[j][2] = v[k].x[2];
144 
145         n[j][0] = t->u[j][0];
146         n[j][1] = t->u[j][1];
147         n[j][2] = t->u[j][2];
148 
149         if ( color ) c[j] = CScl * ( color[k]-CAdd );
150     }
151 
152     gra_triangle( x,n,c );
153 }
154 
155 /*******************************************************************************
156  *
157  *     Name:         vis_draw_edge
158  *
159  *     Purpose:      draw element edge as line or cylinder
160  *
161  *     Parameters:
162  *
163  *         Input:    (vertex_t   *) vertex array
164  *                   (int,int)      edge vertex indices
165  *                   (double *)      color quantity
166  *                   (double,double ) CScl,CAdd are constatnt to scale color
167  *                                  range (0-1)
168  *                   (line_style_t) line style, either line_style_line or
169  *                                  line_style_cylider
170  *                   (double)       line width, cylinder radius.
171  *
172  *
173  *         Output:   graphics
174  *
175  *   Return value:   void
176  *
177  ******************************************************************************/
vis_draw_edge(vertex_t * vertex,int v0,int v1,double * color,double CScl,double CAdd,line_style_t style,double width)178 static void vis_draw_edge(vertex_t *vertex,int v0,int v1,double *color,double CScl,
179                        double CAdd,line_style_t style,double width)
180 {
181     double c0=0.0,c1=1.0;
182 
183     /*
184      *  if color function given scale values to 0-1
185      */
186     if ( color )
187     {
188         c0 = CScl*( color[v0] - CAdd );
189         c1 = CScl*( color[v1] - CAdd );
190     }
191 
192     gra_line( vertex[v0].x,c0,vertex[v1].x,c1,style,width );
193 }
194 
195 /*******************************************************************************
196  *
197  *     Name:        vis_mesh
198  *
199  *     Purpose:     draw mesh as lines or surface, with color codes or not
200  *
201  *     Parameters:
202  *
203  *         Input:   (geometry_t *) triangles to draw
204  *                  (mesh_t     *) mesh display parameters
205  *                  (double)
206  *
207  *         Output:  graphics
208  *
209  *   Return value:  if mouse interaction is going on, and time used exeeds
210  *                  given value (TooLong1,2) FALSE, otherwise TRUE
211  *
212  ******************************************************************************/
vis_mesh(geometry_t * geometry,element_model_t * model,mesh_t * Mesh,double dt)213 static int vis_mesh( geometry_t *geometry, element_model_t *model, mesh_t *Mesh,double dt )
214 {
215     scalar_t *ColorData = Mesh->ColorData;
216 
217     vertex_t *v = geometry->Vertices;
218 
219     edge_list_t *edge;
220 
221     double width = Mesh->LineWidth*0.005,CScl=1.0,CAdd=0.0,*C=NULL;
222 
223     int i,j,quick,N=geometry->VertexCount,NT=geometry->TriangleCount;
224 
225     element_t *elements = model->Elements;
226 
227     static char str[100];
228 
229     if ( !GlobalOptions.StereoMode )
230       if ( Mesh->Material->Diffuse[3]  < 1.0 )
231       {
232           if ( GlobalPass != 0 ) return TRUE;
233       } else if ( GlobalPass == 0 )
234       {
235           return TRUE;
236       }
237 
238     quick  = (Mesh->Style == mesh_style_line && Mesh->LineStyle == line_style_line );
239     quick &= ~Mesh->NodeNumbers;
240     quick |= epMouseDown && epMouseDownTakesTooLong;
241 
242     gra_set_material( Mesh->Material );
243 
244     if ( quick && !(epMouseDown && epMouseDownTakesTooLong) )
245     {
246         gra_line_width( Mesh->LineWidth );
247     } else {
248         gra_line_width( 1.0 );
249     }
250 
251     if ( ColorData && ColorData->f )
252     {
253         C = ColorData->f;
254 
255         CAdd = ColorData->min;
256         if ( ABS(ColorData->max - ColorData->min)>0.0 )
257             CScl = 1.0 / (ColorData->max - ColorData->min);
258         else
259             CScl = 1.0;
260 
261         gra_set_colormap( Mesh->ColorMap );
262     } else gra_set_colormap( NULL );
263 
264     if ( quick )
265     {
266         gra_set_material( Mesh->EdgeMaterial );
267         gra_beg_lines();
268 
269         for( i=0; i<N; i++ )
270         {
271             if ( v[i].ElementModelNode )
272             {
273                 for( edge=geometry->Edges[i].EdgeList; edge != NULL; edge = edge->Next )
274                 {
275                     if ( edge->Element && !edge->Element->DisplayFlag ) continue;
276                     if ( Mesh->EdgeStyle == edge_style_all || ABS(edge->Count) == 1 )
277                     {
278                          vis_draw_edge( v,i,edge->Entry,C,CScl,CAdd,line_style_line,width );
279                     }
280                 }
281             } else break;
282 
283             if ( epMouseDown && (i & 128) )
284             {
285                 if ( RealTime() - dt > TooLong2 )
286                     if ( ++epMouseDownTakesTooLong > 3 )
287                     {
288                         gra_end_lines();
289                         return FALSE;
290                     } else dt = RealTime();
291             }
292 
293             if ( BreakLoop ) break;
294         }
295 
296         gra_end_lines();
297         gra_set_material( Mesh->Material );
298 
299         return TRUE;
300     }
301 
302     if ( Mesh->NodeNumbers )
303     {
304        for( i=0; i<N; i++ )
305        {
306           if ( v[i].ElementModelNode )
307           {
308             glRasterPos3f( v[i].x[0],v[i].x[1],v[i].x[2]);
309             sprintf( str, "N %d", i );
310             PrintString( str );
311           }
312        }
313     }
314 
315     if ( Mesh->Style == mesh_style_surf || Mesh->Style == mesh_style_line_and_surf )
316     {
317         triangle_t *t = geometry->Triangles;
318 
319         gra_begin( GRA_TRIANGLES );
320         for( i=0; i<NT; i++,t++ )
321         {
322             if ( t->Element && !t->Element->DisplayFlag ) continue;
323 
324             if ( Mesh->EdgeStyle != edge_style_all && t->Count > 1 ) continue;
325 
326             vis_triangle( t,v,C,CScl,CAdd );
327 
328             if ( epMouseDown && (i & 8) )
329                 if ( RealTime() - dt > TooLong1 )
330                 {
331                     epMouseDownTakesTooLong++;
332                     gra_end();
333                     return FALSE;
334                 }
335 
336             if ( BreakLoop ) break;
337         }
338         gra_end();
339     }
340 
341     if ( Mesh->Style == mesh_style_line_and_surf ) gra_set_colormap( NULL );
342 
343     if ( Mesh->Style == mesh_style_line || Mesh->Style == mesh_style_line_and_surf )
344     {
345 
346         glMatrixMode(GL_PROJECTION);
347         glPushMatrix();
348         glTranslatef(0.0,0.0,0.005);
349         glMatrixMode(GL_MODELVIEW);
350 
351         gra_set_material( Mesh->EdgeMaterial );
352 
353         if ( Mesh->LineStyle == line_style_cylinder )
354         {
355             gra_sphere_quality( Mesh->LineQuality );
356 
357             for( i=0; i<N; i++ )
358             {
359                 if ( v[i].ElementModelNode )
360                 {
361                     for( edge=geometry->Edges[i].EdgeList; edge != NULL; edge = edge->Next )
362                     {
363                         if ( edge->Element && !edge->Element->DisplayFlag ) continue;
364                         if ( Mesh->EdgeStyle == edge_style_all || ABS(edge->Count) == 1 )
365                         {
366                              j = edge->Entry;
367                              vis_draw_edge( v,i,j,C,CScl,CAdd,line_style_cylinder,width );
368                         }
369                    }
370                 } else break;
371 
372                 if ( epMouseDown && (i & 8) )
373                     if ( RealTime() - dt > TooLong1 )
374                     {
375                         epMouseDownTakesTooLong++;
376                         glMatrixMode(GL_PROJECTION);
377                         glPopMatrix();
378                         glMatrixMode( GL_MODELVIEW );
379                         return FALSE;
380                     }
381 
382                 if ( BreakLoop ) break;
383             }
384         } else
385         {
386             gra_line_width( Mesh->LineWidth );
387             gra_beg_lines();
388             for( i=0; i<N; i++ )
389             {
390                 if ( v[i].ElementModelNode )
391                 {
392                     for( edge=geometry->Edges[i].EdgeList; edge != NULL; edge = edge->Next )
393                     {
394                         if ( edge->Element && !edge->Element->DisplayFlag ) continue;
395                         if ( Mesh->EdgeStyle == edge_style_all || ABS(edge->Count) == 1 )
396                         {
397                              vis_draw_edge( v,i,edge->Entry,C,CScl,CAdd,line_style_line,width );
398                         }
399                     }
400                 } else break;
401 
402                 if ( epMouseDown && (i & 32) )
403                     if ( RealTime() - dt > TooLong1 )
404                     {
405                         epMouseDownTakesTooLong++;
406                         gra_end_lines();
407                         glMatrixMode(GL_PROJECTION);
408                         glPopMatrix();
409                         glMatrixMode( GL_MODELVIEW );
410                         return FALSE;
411                     }
412 
413                 if ( BreakLoop ) break;
414             }
415             gra_end_lines();
416         }
417         glMatrixMode(GL_PROJECTION);
418         glPopMatrix();
419         glMatrixMode( GL_MODELVIEW );
420     }
421 
422     return TRUE;
423 }
424 
425 /*******************************************************************************
426  *
427  *     Name:        vis_mesh_alloc
428  *
429  *     Purpose:     allocate memory for mesh_t structure
430  *
431  *     Parameters:
432  *
433  *         Input:   none
434  *
435  *         Output:  none
436  *
437  *   Return value:  pointer to allocated memory
438  *
439  ******************************************************************************/
vis_mesh_alloc()440 static mesh_t *vis_mesh_alloc()
441 {
442      mesh_t *mesh = (mesh_t *)calloc(sizeof(mesh_t),1);
443 
444      if ( !mesh )
445      {
446          fprintf( stderr, "vis_mesh_alloc: FATAL: can't alloc a few bytes of memory\n" );
447      }
448 
449      return mesh;
450 }
451 
452 /*******************************************************************************
453  *
454  *     Name:        vis_mesh_delete
455  *
456  *     Purpose:     free memory associated with mesh_t structure
457  *
458  *     Parameters:
459  *
460  *         Input:   (mesh_t *) pointer to structure
461  *
462  *         Output:  none
463  *
464  *   Return value:  void
465  *
466  ******************************************************************************/
vis_mesh_delete(mesh_t * mesh)467 static void vis_mesh_delete(mesh_t *mesh)
468 {
469     if ( mesh ) free( mesh );
470 }
471 
472 /*******************************************************************************
473  *
474  *     Name:        vis_initialize_mesh_visual
475  *
476  *     Purpose:     Register "Mesh" visual type
477  *
478  *     Parameters:
479  *
480  *         Input:   none
481  *
482  *         Output:  none
483  *
484  *   Return value:  vis_add_visual_type (malloc success probably)...
485  *
486  ******************************************************************************/
vis_initialize_mesh_visual()487 int vis_initialize_mesh_visual()
488 {
489     static char *visual_name = "Mesh";
490     visual_type_t VisualDef;
491 
492     static mesh_t mesh;
493 
494     static visual_param_t MeshParams[] =
495     {
496         { "ColorData",     "%s", 0, VIS_VISUAL_PARAM_POINTER, 0, 0.0, NULL },
497         { "Style",         "%d", 0, VIS_VISUAL_PARAM_INT,     mesh_style_line, 0.0, NULL },
498         { "EdgeStyle",     "%d", 0, VIS_VISUAL_PARAM_INT,     edge_style_all,  0.0, NULL },
499         { "Material",      "%s", 0, VIS_VISUAL_PARAM_POINTER, 0, 0.0, &DefaultMaterial },
500         { "EdgeMaterial",  "%s", 0, VIS_VISUAL_PARAM_POINTER, 0, 0.0, &DefaultEdgeMaterial },
501         { "ColorMap",      "%s", 0, VIS_VISUAL_PARAM_POINTER, 0, 0.0, &DefaultColorMap },
502         { "LineWidth",     "%lf", 0, VIS_VISUAL_PARAM_FLOAT,  0, 1.0, NULL },
503         { "LineQuality",   "%d", 0, VIS_VISUAL_PARAM_INT,     1, 0.0, NULL },
504         { "LineStyle",     "%d", 0, VIS_VISUAL_PARAM_INT,     0, 0.0, NULL },
505         { "NodeNumbers",   "%d", 0, VIS_VISUAL_PARAM_LOGICAL, 0, 0.0, NULL },
506         { NULL, NULL, 0, 0, 0, 0.0, NULL }
507     };
508 
509     int n = 0;
510 
511     MeshParams[n++].Offset = (char *)&mesh.ColorData     - (char *)&mesh;
512     MeshParams[n++].Offset = (char *)&mesh.Style         - (char *)&mesh;
513     MeshParams[n++].Offset = (char *)&mesh.EdgeStyle     - (char *)&mesh;
514     MeshParams[n++].Offset = (char *)&mesh.Material      - (char *)&mesh;
515     MeshParams[n++].Offset = (char *)&mesh.EdgeMaterial  - (char *)&mesh;
516     MeshParams[n++].Offset = (char *)&mesh.ColorMap      - (char *)&mesh;
517     MeshParams[n++].Offset = (char *)&mesh.LineWidth     - (char *)&mesh;
518     MeshParams[n++].Offset = (char *)&mesh.LineQuality   - (char *)&mesh;
519     MeshParams[n++].Offset = (char *)&mesh.LineStyle     - (char *)&mesh;
520     MeshParams[n++].Offset = (char *)&mesh.NodeNumbers   - (char *)&mesh;
521 
522     VisualDef.VisualName    = visual_name;
523 
524     VisualDef.RealizeVisual = (int   (*)()) vis_mesh;
525     VisualDef.AllocParams   = (void *(*)()) vis_mesh_alloc;
526     VisualDef.DeleteParams  = (void  (*)()) vis_mesh_delete;
527     VisualDef.VisualParams  = MeshParams;
528 
529     return vis_add_visual_type( &VisualDef );
530 }
531