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