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