1 /****************************************************************************/
2 /* This file is part of FreeFEM.                                            */
3 /*                                                                          */
4 /* FreeFEM is free software: you can redistribute it and/or modify          */
5 /* it under the terms of the GNU Lesser General Public License as           */
6 /* published by the Free Software Foundation, either version 3 of           */
7 /* the License, or (at your option) any later version.                      */
8 /*                                                                          */
9 /* FreeFEM is distributed in the hope that it will be useful,               */
10 /* but WITHOUT ANY WARRANTY; without even the implied warranty of           */
11 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
12 /* GNU Lesser General Public License for more details.                      */
13 /*                                                                          */
14 /* You should have received a copy of the GNU Lesser General Public License */
15 /* along with FreeFEM. If not, see <http://www.gnu.org/licenses/>.          */
16 /****************************************************************************/
17 /* SUMMARY : ...                                                            */
18 /* LICENSE : LGPLv3                                                         */
19 /* ORG     : LJLL Universite Pierre et Marie Curie, Paris, FRANCE           */
20 /* AUTHORS : Pascal Frey                                                    */
21 /* E-MAIL  : pascal.frey@sorbonne-universite.fr                             */
22 
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26 
27 #include "medit.h"
28 #include "extern.h"
29 #include "sproto.h"
30 
31 static pClip cclip = 0;
32 static ubyte curclip = 0;
33 static GLfloat plane[4] = {-1.0, 0.0, 0.0, 0.0};
drawCap(pScene sc,pClip clip,GLboolean docap)34 static void drawCap(pScene sc, pClip clip, GLboolean docap) {
35   if (!docap) {
36     if (clip->active & C_EDIT)
37       glColor3f(1.0, 0.0, 1.0);
38     else if (clip->active & C_FREEZE)
39       glColor3f(0.0, 0.6, 0.9);
40     else
41       glColor3f(0.0, 1.0, 0.0);
42 
43     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
44     glLineWidth(3.);
45     glBegin(GL_QUADS);
46     glVertex3f(0., -1., -1.);
47     glVertex3f(0., 1., -1.);
48     glVertex3f(0., 1., 1.);
49     glVertex3f(0., -1., 1.);
50     glEnd( );
51 
52     glLineWidth(1.);
53     glColor3f(1., 0.7, 0.);
54     glBegin(GL_LINES);
55     glVertex3f(0., 0., -1.);
56     glVertex3f(0., 0., 1.);
57     glColor3f(1., 0.7, 0.);
58     glVertex3f(0., -1., 0.);
59     glVertex3f(0., 1., 0.);
60     glEnd( );
61 
62     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
63   } else {
64     glDisable(GL_LIGHTING);
65     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
66     glColor4fv(sc->material[DEFAULT_MAT].dif);
67     glRecti(-100, -100, 100, 100);
68   }
69 }
70 
71 /* display clipping plane */
updateClip(pClip clip,pMesh mesh)72 void updateClip(pClip clip, pMesh mesh) {
73   pScene sc;
74   pTransform cliptr, view;
75   GLfloat dd, dmax, inv[16], axis[4], trans[4], matrix[16];
76   int idw;
77 
78   /* default */
79   if (ddebug) printf("updateClip\n");
80 
81   /* retrieve context */
82   idw = currentScene( );
83   sc = cv.scene[idw];
84   view = sc->view;
85   cliptr = clip->cliptr;
86 
87   /* compute clip transform */
88   if (clip->active & C_EDIT) {
89     invertMatrix(view->matrix, inv);
90     inv[3] = inv[7] = inv[11] = 0.0;
91     inv[15] = 1.0;
92 
93     /* rotation cumulative */
94     if (cliptr->angle != 0.0) {
95       transformVector(trans, cliptr->axis, inv);
96       glPushMatrix( );
97       glLoadIdentity( );
98       glRotatef(cliptr->angle, trans[0], trans[1], trans[2]);
99       glMultMatrixf(cliptr->rot);
100       glGetFloatv(GL_MODELVIEW_MATRIX, cliptr->rot);
101       glPopMatrix( );
102     }
103 
104     /* translation cumulative */
105     axis[0] = cliptr->panx;
106     axis[1] = cliptr->pany;
107     axis[2] = 0.0;
108     axis[3] = 1.0;
109     if (cliptr->manim == GL_FALSE) cliptr->panx = cliptr->pany = 0.0;
110 
111     transformVector(trans, axis, inv);
112 
113     dd = trans[0] * clip->eqn[0] + trans[1] * clip->eqn[1] + trans[2] * clip->eqn[2];
114     trans[0] = dd * clip->eqn[0];
115     trans[1] = dd * clip->eqn[1];
116     trans[2] = dd * clip->eqn[2];
117 
118     cliptr->tra[12] += trans[0];
119     cliptr->tra[13] += trans[1];
120     cliptr->tra[14] += trans[2];
121 
122     /* truncation */
123     dmax = mesh->xmax - mesh->xmin;
124     dmax = max(dmax, mesh->ymax - mesh->ymin);
125     dmax = max(dmax, mesh->zmax - mesh->zmin) / 1.8;
126     if (fabs(cliptr->tra[12]) > dmax || fabs(cliptr->tra[13]) > dmax ||
127         fabs(cliptr->tra[14]) > dmax) {
128       if (cliptr->manim == GL_TRUE) {
129         cliptr->panx = -cliptr->panx;
130         cliptr->pany = -cliptr->pany;
131       } else {
132         cliptr->tra[12] = max(-dmax, min(dmax, cliptr->tra[12]));
133         cliptr->tra[13] = max(-dmax, min(dmax, cliptr->tra[13]));
134         cliptr->tra[14] = max(-dmax, min(dmax, cliptr->tra[14]));
135       }
136     }
137 
138     /* final transformation */
139     glPushMatrix( );
140     glLoadIdentity( );
141     glMultMatrixf(cliptr->tra);
142     glMultMatrixf(cliptr->rot);
143     glGetFloatv(GL_MODELVIEW_MATRIX, cliptr->matrix);
144     glPopMatrix( );
145 
146     /* compute plane equation */
147     invertMatrix(cliptr->matrix, inv);
148     transformPoint(clip->eqn, plane, inv);
149 
150     if (clip->active & C_REDO) clipVertices(mesh, sc, clip);
151 
152     /* clip->active |= C_REDO;*/
153   } else if (clip->active & C_FREEZE) {
154     glPushMatrix( );
155     glLoadMatrixf(view->matrix);
156     glTranslatef(sc->cx, sc->cy, sc->cz);
157     glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
158     glPopMatrix( );
159     invertMatrix(matrix, inv);
160     inv[3] = inv[7] = inv[11] = 0.0;
161     inv[15] = 1.0;
162 
163     glPushMatrix( );
164     glLoadMatrixf(inv);
165     glMultMatrixf(view->oldmat);
166     glTranslatef(sc->cx, sc->cy, sc->cz);
167     glMultMatrixf(cliptr->matrix);
168     glGetFloatv(GL_MODELVIEW_MATRIX, cliptr->matrix);
169     glPopMatrix( );
170 
171     /* compute plane equation */
172     invertMatrix(cliptr->matrix, inv);
173     transformPoint(clip->eqn, plane, inv);
174     clip->active |= C_REDO;
175   }
176 
177   if (!cliptr->manim) {
178     cliptr->angle = 0.0;
179     clip->active ^= C_UPDATE;
180   }
181 }
182 
clipVertices(pMesh mesh,pScene sc,pClip clip)183 void clipVertices(pMesh mesh, pScene sc, pClip clip) {
184   pPoint p0;
185   double dd1, zero;
186   int k, l, nbpos, nbnul;
187 
188   /* check points in plane */
189   zero = sc->dmax * 1.e-13;
190 
191   for (k = 1; k <= mesh->np; k++) {
192     p0 = &mesh->point[k];
193     if (p0->tag & M_UNUSED) continue;
194 
195     dd1 =
196       p0->c[0] * clip->eqn[0] + p0->c[1] * clip->eqn[1] + p0->c[2] * clip->eqn[2] + clip->eqn[3];
197     if (dd1 > zero)
198       p0->clip = 2;
199     else if (dd1 < zero)
200       p0->clip = 1;
201     else
202       p0->clip = 0;
203   }
204 
205   /* update tetrahedra */
206   for (k = 1; k <= mesh->ntet; k++) {
207     pTetra pt;
208 
209     pt = &mesh->tetra[k];
210     pt->clip = 0;
211     nbpos = nbnul = 0;
212 
213     for (l = 0; l < 4; l++) {
214       p0 = &mesh->point[pt->v[l]];
215       if (p0->clip == 2)
216         nbpos++;
217       else if (p0->clip == 1)
218         ;
219       else
220         nbnul++;
221     }
222 
223     if (nbpos && nbpos + nbnul < 4) pt->clip = 1;
224   }
225 
226   /* update hexahedra */
227   for (k = 1; k <= mesh->nhex; k++) {
228     pHexa ph;
229 
230     ph = &mesh->hexa[k];
231     ph->clip = 0;
232     nbpos = nbnul = 0;
233 
234     for (l = 0; l < 8; l++) {
235       p0 = &mesh->point[ph->v[l]];
236       if (p0->clip == 2)
237         nbpos++;
238       else if (p0->clip == 1)
239         ;
240       else
241         nbnul++;
242     }
243 
244     if (nbpos && nbpos + nbnul < 8) ph->clip = 1;
245   }
246 }
247 
drawClip(pScene sc,pClip clip,pMesh mesh,GLboolean docap)248 void drawClip(pScene sc, pClip clip, pMesh mesh, GLboolean docap) {
249   pTransform cliptr;
250   GLfloat scale;
251 
252   /* default */
253   if (ddebug) printf("drawClip\n");
254 
255   cliptr = clip->cliptr;
256 
257   if (clip->active & C_UPDATE) updateClip(clip, mesh);
258 
259   if (clip->active & C_REDO) {
260     if (!animate) glutSetCursor(GLUT_CURSOR_WAIT);
261 
262     /* update clip plane */
263     clipVertices(mesh, sc, clip);
264 
265     /* build display lists */
266     if (clip->active & C_VOL) {
267       if (sc->clist[LTets]) glDeleteLists(sc->clist[LTets], 1);
268 
269       if (sc->clist[LHexa]) glDeleteLists(sc->clist[LHexa], 1);
270 
271       if (sc->cmlist[LTets]) glDeleteLists(sc->cmlist[LTets], 1);
272 
273       if (sc->cmlist[LHexa]) glDeleteLists(sc->cmlist[LHexa], 1);
274 
275       sc->clist[LTets] = sc->cmlist[LTets] = (GLuint)0;
276       sc->clist[LHexa] = sc->cmlist[LHexa] = (GLuint)0;
277 
278       if (clip->active & C_CAP) {
279         sc->clist[LTets] = capTetra(mesh);
280         if (sc->mode & S_MAP)
281           sc->cmlist[LTets] = capTetraMap(mesh);
282         else if (sc->isotyp & S_ISOLINE)
283           sc->ilist[LTets] = capTetraIso(mesh);
284       } else {
285         sc->clist[LTets] = listTetra(sc, mesh, 1);
286         sc->clist[LHexa] = listHexa(sc, mesh, 1);
287         if (sc->mode & S_MAP) {
288           sc->cmlist[LTets] = listTetraMap(sc, mesh, 1);
289           sc->cmlist[LHexa] = listHexaMap(sc, mesh, 1);
290         }
291       }
292 
293       if (!animate) clip->active ^= C_REDO;
294     } else {
295       clip->active ^= C_REDO;
296     }
297 
298     if (sc->isotyp & S_VECTOR) {
299       if (sc->vlist[LTets]) glDeleteLists(sc->vlist[LTets], 1);
300 
301       sc->vlist[LTets] = listClipTetraVector(mesh);
302       if (sc->vlist[LHexa]) glDeleteLists(sc->vlist[LHexa], 1);
303 
304       sc->vlist[LHexa] = listClipHexaVector(mesh);
305     }
306 
307     if (!animate) glutSetCursor(GLUT_CURSOR_INHERIT);
308   }
309 
310   /* display plane frame */
311   if (clip->active & C_HIDE) return;
312 
313   glPushMatrix( );
314   glMultMatrixf(cliptr->matrix);
315   scale = 0.3 * (sc->dmax + sc->dmin);
316   glScalef(scale, scale, scale);
317 
318   drawCap(sc, clip, docap);
319 
320   glPopMatrix( );
321 }
322 
copyClip(pClip clip)323 void copyClip(pClip clip) {
324   if (!cclip) {
325     cclip = (pClip)M_calloc(1, sizeof(struct clip), "clip");
326     if (!clip) exit(2);
327   }
328 
329   cclip = (pClip)memcpy(cclip, clip, sizeof(struct clip));
330   if (!cclip) exit(2);
331 
332   curclip = 1;
333 }
334 
pasteClip(pClip clip)335 int pasteClip(pClip clip) {
336   if (!curclip) return (0);
337 
338   clip = (pClip)memcpy(clip, cclip, sizeof(struct clip));
339   if (!clip) exit(2);
340 
341   clip->active = 0;
342   curclip = 0;
343   return (1);
344 }
345 
tiltClip(pScene sc,pClip clip)346 void tiltClip(pScene sc, pClip clip) {
347   float axis[4];
348 
349   axis[0] = clip->cliptr->axis[0];
350   axis[1] = clip->cliptr->axis[1];
351   axis[2] = clip->cliptr->axis[2];
352 
353   transformVector(clip->cliptr->axis, axis, sc->view->matrix);
354   /*clip->cliptr->angle = 90.0;*/
355 
356   clip->active |= C_REDO;
357 }
358 
359 /* change clip orientation */
invertClip(pScene sc,pClip clip)360 void invertClip(pScene sc, pClip clip) {
361   clip->eqn[0] = -clip->eqn[0];
362   clip->eqn[1] = -clip->eqn[1];
363   clip->eqn[2] = -clip->eqn[2];
364   clip->eqn[3] = -clip->eqn[3];
365   plane[0] = -plane[0];
366 }
367 
resetClip(pScene sc,pClip clip,pMesh mesh)368 void resetClip(pScene sc, pClip clip, pMesh mesh) {
369   double dd;
370 
371   resetTransform(clip->cliptr);
372   dd = sc->par.clip[0] * sc->par.clip[3] + sc->par.clip[1] * sc->par.clip[4] +
373        sc->par.clip[2] * sc->par.clip[5];
374 
375   clip->active |= C_REDO;
376   clip->eqn[0] = sc->par.clip[3];
377   clip->eqn[1] = sc->par.clip[4];
378   clip->eqn[2] = sc->par.clip[5];
379   clip->eqn[3] = -dd;
380 }
381 
382 /* create a clipping plane */
createClip(pScene sc,pMesh mesh)383 pClip createClip(pScene sc, pMesh mesh) {
384   pClip clip;
385 
386   /* default */
387   clip = (pClip)M_calloc(1, sizeof(struct clip), "clip");
388   assert(clip);
389   clip->cliptr = (pTransform)M_calloc(1, sizeof(struct transform), "clip");
390   assert(clip->cliptr);
391 
392   resetClip(sc, clip, mesh);
393   return (clip);
394 }
395 
396 #ifdef __cplusplus
397 }
398 #endif
399