1 /*!
2    \file lib/ogsf/gsd_cplane.c
3 
4    \brief OGSF library - manipulating surfaces (lower level functions)
5 
6    GRASS OpenGL gsurf OGSF Library
7 
8    (C) 1999-2008 by the GRASS Development Team
9 
10    This program is free software under the
11    GNU General Public License (>=v2).
12    Read the file COPYING that comes with GRASS
13    for details.
14 
15    \author Bill Brown USACERL, GMSL/University of Illinois (January 1993)
16    \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
17  */
18 
19 #include <grass/ogsf.h>
20 #include "rowcol.h"
21 
22 static void init_cplane(void);
23 
24 static float Cp_pt[4], Cp_norm[MAX_CPLANES][4];
25 static float Cp_trans[MAX_CPLANES][3], Cp_rot[MAX_CPLANES][3];
26 static int Cp_ison[MAX_CPLANES];	/* also need isdef? */
27 
init_cplane(void)28 static void init_cplane(void)
29 {
30     int i;
31 
32     gs_get_datacenter(Cp_pt);
33     gs_get_data_avg_zmax(&(Cp_pt[Z]));
34 
35     for (i = 0; i < MAX_CPLANES; i++) {
36 	Cp_ison[i] = 0;
37 	Cp_norm[i][X] = 1.0;
38 	Cp_norm[i][Y] = Cp_norm[i][Z] = 0.0;
39 	Cp_norm[i][W] = 1.;
40 	Cp_rot[i][X] = Cp_trans[i][X] = 0.0;
41 	Cp_rot[i][Y] = Cp_trans[i][Y] = 0.0;
42 	Cp_rot[i][Z] = Cp_trans[i][Z] = 0.0;
43     }
44 
45     return;
46 }
47 
48 /*!
49    \brief Define cplace
50 
51    \param num
52    \param pt
53    \param norm
54  */
gsd_def_cplane(int num,float * pt,float * norm)55 void gsd_def_cplane(int num, float *pt, float *norm)
56 {
57     float sx, sy, sz, ppt[3];
58     double params[4];
59     float zmin, zmax;
60 
61     GS_get_scale(&sx, &sy, &sz, 1);
62 
63     /* Something's still wrong with the zexag - DONT USE TILT */
64     GS_get_zrange(&zmin, &zmax, 0);
65 
66     ppt[0] = (pt[0] + Cp_pt[0]) * sx;
67     ppt[1] = (pt[1] + Cp_pt[1]) * sy;
68     ppt[2] = (pt[2] + Cp_pt[2] - zmin) * sz;
69 
70     params[0] = norm[0] * sx;
71     params[1] = norm[1] * sy;
72     params[2] = norm[2] * sz;
73     GS_dv3norm(params);
74     params[3] = -ppt[0] * params[0] - ppt[1] * params[1] - ppt[2] * params[2];
75 
76     gsd_def_clipplane(num, params);
77 
78     return;
79 }
80 
81 /*!
82    \brief Update cplaces
83 
84    Called when viewing matrix changes
85  */
gsd_update_cplanes(void)86 void gsd_update_cplanes(void)
87 {
88     int i;
89 
90     for (i = 0; i < MAX_CPLANES; i++) {
91 	if (Cp_ison[i]) {
92 	    gsd_def_cplane(i, Cp_trans[i], Cp_norm[i]);
93 	}
94     }
95 
96     return;
97 }
98 
99 /*!
100    \brief ADD
101 
102    \param num
103  */
gsd_cplane_on(int num)104 void gsd_cplane_on(int num)
105 {
106     static int first = 1;
107 
108     if (first) {
109 	first = 0;
110 	init_cplane();
111 	gsd_def_cplane(num, Cp_trans[num], Cp_norm[num]);
112     }
113 
114     gsd_set_clipplane(num, 1);
115 
116     Cp_ison[num] = 1;
117 
118     return;
119 }
120 
121 /*!
122    \brief Turn off clip plane
123 
124    \param num cplane id
125  */
gsd_cplane_off(int num)126 void gsd_cplane_off(int num)
127 {
128 
129     gsd_set_clipplane(num, 0);
130     Cp_ison[num] = 0;
131 
132     return;
133 }
134 
135 /*!
136    \brief Get cplane state
137 
138    <i>onstate</i> MUST be big enough to hold MAX_CPLANES ints
139 
140    \param onstate
141  */
gsd_get_cplanes_state(int * onstate)142 void gsd_get_cplanes_state(int *onstate)
143 {
144     int i;
145 
146     for (i = 0; i < MAX_CPLANES; i++) {
147 	onstate[i] = Cp_ison[i];
148     }
149 
150     return;
151 }
152 
153 /*!
154    \brief Get cplaces
155 
156    Planes MUST be big enough to hold MAX_CPLANES Point4s
157 
158    \param places surface coordinates, normal pointing away from visible side
159 
160    \return ADD
161  */
gsd_get_cplanes(Point4 * planes)162 int gsd_get_cplanes(Point4 * planes)
163 {
164     int i, ons;
165     Point3 thru;
166 
167     for (ons = i = 0; i < MAX_CPLANES; i++) {
168 	if (Cp_ison[i]) {
169 	    thru[X] = Cp_pt[X] + Cp_trans[ons][X];
170 	    thru[Y] = Cp_pt[Y] + Cp_trans[ons][Y];
171 	    thru[Z] = Cp_pt[Z] + Cp_trans[ons][Z];
172 	    planes[ons][X] = -Cp_norm[ons][X];
173 	    planes[ons][Y] = -Cp_norm[ons][Y];
174 	    planes[ons][Z] = -Cp_norm[ons][Z];
175 	    planes[ons][W] = -(DOT3(planes[ons], thru));
176 	    ons++;
177 	}
178     }
179 
180     return (ons);
181 }
182 
183 /*!
184    \brief ADD
185 
186    \param num
187  */
gsd_update_cpnorm(int num)188 void gsd_update_cpnorm(int num)
189 {
190     float v[1][4];
191 
192     v[0][X] = v[0][W] = 1.0;
193     v[0][Y] = v[0][Z] = 0.0;
194 
195     P_pushmatrix();
196     P_rot(Cp_rot[num][Z], 'z');
197     P_rot(Cp_rot[num][Y], 'y');
198     P_rot(Cp_rot[num][X], 'x');
199     P_transform(1, v, &Cp_norm[num]);
200     P_popmatrix();
201 
202     return;
203 }
204 
205 /*!
206    \brief ADD
207 
208    \param num
209    \param rx,ry,rz
210  */
gsd_cplane_setrot(int num,float rx,float ry,float rz)211 void gsd_cplane_setrot(int num, float rx, float ry, float rz)
212 {
213     Cp_rot[num][X] = rx;
214     Cp_rot[num][Y] = ry;
215     Cp_rot[num][Z] = rz;
216 
217     gsd_update_cpnorm(num);
218     gsd_def_cplane(num, Cp_trans[num], Cp_norm[num]);
219 
220     return;
221 }
222 
223 /*!
224    \brief ADD
225 
226    \param num
227    \param tx,ty,tz
228  */
gsd_cplane_settrans(int num,float tx,float ty,float tz)229 void gsd_cplane_settrans(int num, float tx, float ty, float tz)
230 {
231     Cp_trans[num][X] = tx;
232     Cp_trans[num][Y] = ty;
233     Cp_trans[num][Z] = tz;
234 
235     gsd_def_cplane(num, Cp_trans[num], Cp_norm[num]);
236 
237     return;
238 }
239 
240 /*!
241    \brief ADD
242 
243    \param surf1 first surface (geosurf)
244    \param surf2 second surface (geosurf) [unused]
245    \param cpnum
246  */
gsd_draw_cplane_fence(geosurf * surf1,geosurf * surf2,int cpnum)247 void gsd_draw_cplane_fence(geosurf * surf1, geosurf * surf2, int cpnum)
248 {
249     int was_on;
250     float len, dir[3], bgn[2], end[2], px, py, fencenorm[3];
251 
252     /* temporarily turn this plane off */
253     if ((was_on = Cp_ison[cpnum])) {
254 	gsd_set_clipplane(cpnum, 0);
255     }
256 
257     /* line on surface (asuming NO TILT) is (-A,B)->(A,-B),
258        extended thru Cp_pt */
259     dir[X] = -Cp_norm[cpnum][Y];
260     dir[Y] = Cp_norm[cpnum][X];
261     dir[Z] = 0.0;
262     GS_v3norm(dir);
263     px = Cp_trans[cpnum][X] + Cp_pt[X];
264     py = Cp_trans[cpnum][Y] + Cp_pt[Y];
265 
266     /* TODO: make line from point & direction, clip to region */
267     /* for now, to test: */
268     bgn[X] = px;
269     bgn[Y] = py;
270     end[X] = px;
271     end[Y] = 3 * VROW2Y(surf1, 0);
272     len = GS_P2distance(bgn, end) - 1;
273     bgn[X] = px + len * dir[X];
274     bgn[Y] = py + len * dir[Y];
275     end[X] = px - len * dir[X];
276     end[Y] = py - len * dir[Y];
277 
278     fencenorm[X] = -Cp_norm[cpnum][X];
279     fencenorm[Y] = -Cp_norm[cpnum][Y];
280     fencenorm[Z] = -Cp_norm[cpnum][Z];
281     gsd_wall(bgn, end, fencenorm);
282 
283     /* turn this plane back on */
284     if (was_on) {
285 	gsd_set_clipplane(cpnum, 1);
286     }
287 
288     return;
289 }
290 
291 /*!
292    \brief Draw cplane
293 
294    \param num
295  */
gsd_draw_cplane(int num)296 void gsd_draw_cplane(int num)
297 {
298     float size, cpv[3];
299     int i;
300     float scalez;
301     unsigned long colr;
302 
303     /* turn off all clipping planes */
304     for (i = 0; i < MAX_CPLANES; i++) {
305 	if (Cp_ison[i]) {
306 	    gsd_set_clipplane(i, 0);
307 	}
308     }
309 
310     GS_get_longdim(&size);
311     size /= 2.;
312     cpv[X] = 0.0;
313 
314     gsd_blend(1);
315 
316     gsd_zwritemask(0x0);
317 
318     gsd_pushmatrix();
319 
320     gsd_do_scale(1);
321 
322     gsd_translate(Cp_pt[X] + Cp_trans[num][X],
323 		  Cp_pt[Y] + Cp_trans[num][Y], Cp_pt[Z] + Cp_trans[num][Z]);
324 
325     gsd_rot(Cp_rot[num][Z], 'z');
326     gsd_rot(Cp_rot[num][Y], 'y');
327     gsd_rot(Cp_rot[num][X], 'x');
328 
329     if ((scalez = GS_global_exag())) {
330 	gsd_scale(1.0, 1.0, 1. / scalez);
331     }
332 
333     colr = (GS_default_draw_color() | 0xff000000) & 0x33ffffff;
334     gsd_color_func(colr);
335     gsd_bgnpolygon();
336     cpv[Y] = size;
337     cpv[Z] = size;
338     gsd_vert_func(cpv);
339     cpv[Y] = -size;
340     gsd_vert_func(cpv);
341     cpv[Z] = -size;
342     gsd_vert_func(cpv);
343     cpv[Y] = size;
344     gsd_vert_func(cpv);
345     gsd_endpolygon();
346 
347     gsd_popmatrix();
348     gsd_blend(0);
349     gsd_zwritemask(0xffffffff);
350 
351     /* turn on clipping planes */
352     for (i = 0; i < MAX_CPLANES; i++) {
353 	if (Cp_ison[i]) {
354 	    gsd_set_clipplane(i, 1);
355 	}
356     }
357 
358     return;
359 }
360