1 // generated by Fast Light User Interface Designer (fluid) version 1.0100
2
3 #include "ViewEditor.h"
4 // Quat - A 3D fractal generation program
5 // Copyright (C) 1997-2000 Dirk Meyer
6 // (email: dirk.meyer@studserv.uni-stuttgart.de)
7 // mail: Dirk Meyer
8 // Marbacher Weg 29
9 // D-71334 Waiblingen
10 // Germany
11 //
12 // This program is free software; you can redistribute it and/or
13 // modify it under the terms of the GNU General Public License
14 // as published by the Free Software Foundation; either version 2
15 // of the License, or (at your option) any later version.
16 //
17 // This program is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 // GNU General Public License for more details.
21 //
22 // You should have received a copy of the GNU General Public License
23 // along with this program; if not, write to the Free Software
24 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28 #include "ChildWindow.h"
29 #include "ViewSelector.h"
30 #include <FL/math.h>
31 #include <cassert>
32
cb_vre_i(Fl_Value_Input * o,void *)33 inline void ViewEditor::cb_vre_i(Fl_Value_Input* o, void*) {
34 view.s[0] = o->value();
35 for (int i=0; i<3; i++)
36 vs[i]->viewpointre(o->value());
37 if (radio2->value()) { ocular_dist->value(newdist()); ocular_dist->do_callback(); }
38 if (radio1->value()) ocular_angle->value(newangle());
39 checkValidity();
40 }
cb_vre(Fl_Value_Input * o,void * v)41 void ViewEditor::cb_vre(Fl_Value_Input* o, void* v) {
42 ((ViewEditor*)(o->parent()->parent()->user_data()))->cb_vre_i(o,v);
43 }
44
cb_vi_i(Fl_Value_Input * o,void *)45 inline void ViewEditor::cb_vi_i(Fl_Value_Input* o, void*) {
46 view.s[1] = o->value();
47 for (int i=0; i<3; i++)
48 vs[i]->viewpointi(o->value());
49 if (radio2->value()) { ocular_dist->value(newdist()); ocular_dist->do_callback(); }
50 if (radio1->value()) ocular_angle->value(newangle());
51 checkValidity();
52 }
cb_vi(Fl_Value_Input * o,void * v)53 void ViewEditor::cb_vi(Fl_Value_Input* o, void* v) {
54 ((ViewEditor*)(o->parent()->parent()->user_data()))->cb_vi_i(o,v);
55 }
56
cb_vj_i(Fl_Value_Input * o,void *)57 inline void ViewEditor::cb_vj_i(Fl_Value_Input* o, void*) {
58 view.s[2] = o->value();
59 for (int i=0; i<3; i++)
60 vs[i]->viewpointj(o->value());
61 if (radio2->value()) { ocular_dist->value(newdist()); ocular_dist->do_callback(); }
62 if (radio1->value()) ocular_angle->value(newangle());
63 checkValidity();
64 }
cb_vj(Fl_Value_Input * o,void * v)65 void ViewEditor::cb_vj(Fl_Value_Input* o, void* v) {
66 ((ViewEditor*)(o->parent()->parent()->user_data()))->cb_vj_i(o,v);
67 }
68
cb_upre_i(Fl_Value_Input * o,void *)69 inline void ViewEditor::cb_upre_i(Fl_Value_Input* o, void*) {
70 view.up[0] = o->value();
71 for (int i=0; i<3; i++) vs[i]->upre(o->value());
72 checkValidity();
73 }
cb_upre(Fl_Value_Input * o,void * v)74 void ViewEditor::cb_upre(Fl_Value_Input* o, void* v) {
75 ((ViewEditor*)(o->parent()->parent()->user_data()))->cb_upre_i(o,v);
76 }
77
cb_upi_i(Fl_Value_Input * o,void *)78 inline void ViewEditor::cb_upi_i(Fl_Value_Input* o, void*) {
79 view.up[1] = o->value();
80 for (int i=0; i<3; i++) vs[i]->upi(o->value());
81 checkValidity();
82 }
cb_upi(Fl_Value_Input * o,void * v)83 void ViewEditor::cb_upi(Fl_Value_Input* o, void* v) {
84 ((ViewEditor*)(o->parent()->parent()->user_data()))->cb_upi_i(o,v);
85 }
86
cb_upj_i(Fl_Value_Input * o,void *)87 inline void ViewEditor::cb_upj_i(Fl_Value_Input* o, void*) {
88 view.up[2] = o->value();
89 for (int i=0; i<3; i++) vs[i]->upj(o->value());
90 checkValidity();
91 }
cb_upj(Fl_Value_Input * o,void * v)92 void ViewEditor::cb_upj(Fl_Value_Input* o, void* v) {
93 ((ViewEditor*)(o->parent()->parent()->user_data()))->cb_upj_i(o,v);
94 }
95
cb_lxr_i(Fl_Value_Input * o,void *)96 inline void ViewEditor::cb_lxr_i(Fl_Value_Input* o, void*) {
97 view.LXR = o->value();
98 for (int i=0; i<3; i++) vs[i]->LXR(o->value());
99 checkValidity();
100 }
cb_lxr(Fl_Value_Input * o,void * v)101 void ViewEditor::cb_lxr(Fl_Value_Input* o, void* v) {
102 ((ViewEditor*)(o->parent()->user_data()))->cb_lxr_i(o,v);
103 }
104
cb_ocular_dist_i(Fl_Value_Input * o,void *)105 inline void ViewEditor::cb_ocular_dist_i(Fl_Value_Input* o, void*) {
106 view.interocular = o->value();
107 ocular_angle->value(newangle());
108 checkValidity();
109 }
cb_ocular_dist(Fl_Value_Input * o,void * v)110 void ViewEditor::cb_ocular_dist(Fl_Value_Input* o, void* v) {
111 ((ViewEditor*)(o->parent()->parent()->user_data()))->cb_ocular_dist_i(o,v);
112 }
113
cb_ocular_angle_i(Fl_Value_Input *,void *)114 inline void ViewEditor::cb_ocular_angle_i(Fl_Value_Input*, void*) {
115 view.interocular = newdist();
116 ocular_dist->value(view.interocular);
117 checkValidity();
118 }
cb_ocular_angle(Fl_Value_Input * o,void * v)119 void ViewEditor::cb_ocular_angle(Fl_Value_Input* o, void* v) {
120 ((ViewEditor*)(o->parent()->parent()->user_data()))->cb_ocular_angle_i(o,v);
121 }
122
cb_radio1_i(Fl_Round_Button *,void *)123 inline void ViewEditor::cb_radio1_i(Fl_Round_Button*, void*) {
124 ocular_angle->deactivate();
125 ocular_dist->activate();
126 }
cb_radio1(Fl_Round_Button * o,void * v)127 void ViewEditor::cb_radio1(Fl_Round_Button* o, void* v) {
128 ((ViewEditor*)(o->parent()->parent()->user_data()))->cb_radio1_i(o,v);
129 }
130
cb_radio2_i(Fl_Round_Button *,void *)131 inline void ViewEditor::cb_radio2_i(Fl_Round_Button*, void*) {
132 ocular_dist->deactivate();
133 ocular_angle->activate();
134 }
cb_radio2(Fl_Round_Button * o,void * v)135 void ViewEditor::cb_radio2(Fl_Round_Button* o, void* v) {
136 ((ViewEditor*)(o->parent()->parent()->user_data()))->cb_radio2_i(o,v);
137 }
138
cb_lightx_i(Fl_Value_Input * o,void *)139 inline void ViewEditor::cb_lightx_i(Fl_Value_Input* o, void*) {
140 view.light[0] = o->value();
141 }
cb_lightx(Fl_Value_Input * o,void * v)142 void ViewEditor::cb_lightx(Fl_Value_Input* o, void* v) {
143 ((ViewEditor*)(o->parent()->parent()->user_data()))->cb_lightx_i(o,v);
144 }
145
cb_lighty_i(Fl_Value_Input * o,void *)146 inline void ViewEditor::cb_lighty_i(Fl_Value_Input* o, void*) {
147 view.light[1] = o->value();
148 }
cb_lighty(Fl_Value_Input * o,void * v)149 void ViewEditor::cb_lighty(Fl_Value_Input* o, void* v) {
150 ((ViewEditor*)(o->parent()->parent()->user_data()))->cb_lighty_i(o,v);
151 }
152
cb_lightz_i(Fl_Value_Input * o,void *)153 inline void ViewEditor::cb_lightz_i(Fl_Value_Input* o, void*) {
154 view.light[2] = o->value();
155 }
cb_lightz(Fl_Value_Input * o,void * v)156 void ViewEditor::cb_lightz(Fl_Value_Input* o, void* v) {
157 ((ViewEditor*)(o->parent()->parent()->user_data()))->cb_lightz_i(o,v);
158 }
159
cb_movex_i(Fl_Value_Input * o,void *)160 inline void ViewEditor::cb_movex_i(Fl_Value_Input* o, void*) {
161 view.Mov[0] = o->value();
162 for (int i=0; i<3; i++) vs[i]->movex(o->value());
163 }
cb_movex(Fl_Value_Input * o,void * v)164 void ViewEditor::cb_movex(Fl_Value_Input* o, void* v) {
165 ((ViewEditor*)(o->parent()->parent()->user_data()))->cb_movex_i(o,v);
166 }
167
cb_movey_i(Fl_Value_Input * o,void *)168 inline void ViewEditor::cb_movey_i(Fl_Value_Input* o, void*) {
169 view.Mov[1] = o->value();
170 for (int i=0; i<3; i++) vs[i]->movey(o->value());
171 }
cb_movey(Fl_Value_Input * o,void * v)172 void ViewEditor::cb_movey(Fl_Value_Input* o, void* v) {
173 ((ViewEditor*)(o->parent()->parent()->user_data()))->cb_movey_i(o,v);
174 }
175
ViewEditor(int X,int Y,int W,int H,const char * label)176 ViewEditor::ViewEditor(int X, int Y, int W, int H, const char *label) : Fl_Group(X,Y,W,H,label) {
177 ChildWindow* w;
178 { ChildWindow* o = win = new ChildWindow(416, 216);
179 w = o;
180 o->user_data((void*)(this));
181 { Fl_Group* o = new Fl_Group(5, 5, 260, 200, "QSpace coordinates (1, i, j)");
182 o->tooltip("All parameters in this box are coordinates in Quaternion space.");
183 o->box(FL_ENGRAVED_BOX);
184 o->labelsize(12);
185 o->align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE);
186 o->end();
187 }
188 { Fl_Group* o = group_v = new Fl_Group(15, 30, 110, 75, "v");
189 o->tooltip("The view point represents the center point of the screen in QSpace.\nYou can \
190 also use the three View Selectors to set the View Point with the mouse.");
191 o->labeltype(FL_NO_LABEL);
192 { Fl_Value_Input* o = vre = new Fl_Value_Input(15, 45, 110, 20, "View Point");
193 o->tooltip("Real part of View Point.");
194 o->labelsize(12);
195 o->minimum(-1e+20);
196 o->maximum(1e+20);
197 o->textsize(12);
198 o->callback((Fl_Callback*)cb_vre);
199 o->align(FL_ALIGN_TOP_LEFT);
200 }
201 { Fl_Value_Input* o = vi = new Fl_Value_Input(15, 65, 110, 20, "value:");
202 o->tooltip("1st imaginary (i) part of View Point.");
203 o->labeltype(FL_NO_LABEL);
204 o->labelsize(12);
205 o->minimum(-1e+20);
206 o->maximum(1e+20);
207 o->textsize(12);
208 o->callback((Fl_Callback*)cb_vi);
209 }
210 { Fl_Value_Input* o = vj = new Fl_Value_Input(15, 85, 110, 20, "value:");
211 o->tooltip("2nd imaginary (j) part of View Point.");
212 o->labeltype(FL_NO_LABEL);
213 o->labelsize(12);
214 o->minimum(-1e+20);
215 o->maximum(1e+20);
216 o->textsize(12);
217 o->callback((Fl_Callback*)cb_vj);
218 }
219 o->end();
220 }
221 { Fl_Group* o = group_up = new Fl_Group(15, 120, 110, 75, "up");
222 o->tooltip("Needed for orientation of the screen in QSpace.\nDefines the vertical directi\
223 on of screen.");
224 o->labeltype(FL_NO_LABEL);
225 { Fl_Value_Input* o = upre = new Fl_Value_Input(15, 135, 110, 20, "Up (Orientation)");
226 o->tooltip("Real part of Up.");
227 o->labelsize(12);
228 o->minimum(-1e+20);
229 o->maximum(1e+20);
230 o->textsize(12);
231 o->callback((Fl_Callback*)cb_upre);
232 o->align(FL_ALIGN_TOP_LEFT);
233 }
234 { Fl_Value_Input* o = upi = new Fl_Value_Input(15, 155, 110, 20, "value:");
235 o->tooltip("1st imaginary (i) part of Up.");
236 o->labeltype(FL_NO_LABEL);
237 o->labelsize(12);
238 o->minimum(-1e+20);
239 o->maximum(1e+20);
240 o->textsize(12);
241 o->callback((Fl_Callback*)cb_upi);
242 }
243 { Fl_Value_Input* o = upj = new Fl_Value_Input(15, 175, 110, 20, "value:");
244 o->tooltip("2nd imaginary (j) part of Up.");
245 o->labeltype(FL_NO_LABEL);
246 o->labelsize(12);
247 o->minimum(-1e+20);
248 o->maximum(1e+20);
249 o->textsize(12);
250 o->callback((Fl_Callback*)cb_upj);
251 }
252 o->end();
253 }
254 { Fl_Value_Input* o = lxr = new Fl_Value_Input(145, 65, 110, 20, "Length of View\nPlane\'s X-Axis");
255 o->tooltip("Use this to scale the screen (image).");
256 o->labelsize(12);
257 o->minimum(-1e+20);
258 o->maximum(1e+20);
259 o->textsize(12);
260 o->callback((Fl_Callback*)cb_lxr);
261 o->align(FL_ALIGN_TOP_LEFT);
262 }
263 { Fl_Group* o = group_interocular = new Fl_Group(145, 115, 110, 85, "Interocular");
264 o->labelsize(12);
265 o->align(FL_ALIGN_TOP_LEFT);
266 { Fl_Value_Input* o = ocular_dist = new Fl_Value_Input(165, 135, 90, 20, "Distance");
267 o->tooltip("Distance (in QSpace) between the two eyes. If nonzero, you\'ll get a stereo i\
268 mage.");
269 o->labelsize(12);
270 o->maximum(1e+20);
271 o->textsize(12);
272 o->callback((Fl_Callback*)cb_ocular_dist);
273 o->align(FL_ALIGN_TOP_LEFT);
274 }
275 { Fl_Value_Input* o = ocular_angle = new Fl_Value_Input(165, 175, 90, 20, "Angle (\260)");
276 o->tooltip("Angle between the two eyes. If nonzero, you\'ll get a stereo image.");
277 o->labelsize(12);
278 o->maximum(360);
279 o->textsize(12);
280 o->callback((Fl_Callback*)cb_ocular_angle);
281 o->align(FL_ALIGN_TOP_LEFT);
282 o->deactivate();
283 }
284 { Fl_Round_Button* o = radio1 = new Fl_Round_Button(145, 130, 20, 30, "button");
285 o->tooltip("If selected: Interocular distance constant while moving the View Point.");
286 o->type(102);
287 o->down_box(FL_DOWN_BOX);
288 o->value(1);
289 o->selection_color(2);
290 o->labeltype(FL_NO_LABEL);
291 o->labelsize(12);
292 o->callback((Fl_Callback*)cb_radio1);
293 }
294 { Fl_Round_Button* o = radio2 = new Fl_Round_Button(145, 170, 20, 30, "button");
295 o->tooltip("If selected: Angle is constant while moving the View Point.");
296 o->type(102);
297 o->down_box(FL_DOWN_BOX);
298 o->selection_color(2);
299 o->labeltype(FL_NO_LABEL);
300 o->labelsize(12);
301 o->callback((Fl_Callback*)cb_radio2);
302 }
303 o->end();
304 }
305 { Fl_Group* o = new Fl_Group(275, 5, 130, 200, "Viewplane coord.");
306 o->tooltip("All coordinates in this box are measured relative to the view plane.\nX=horiz\
307 ontal, Y=vertical, Z=perpendicular to screen.");
308 o->box(FL_ENGRAVED_BOX);
309 o->labelsize(12);
310 o->align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE);
311 o->end();
312 }
313 { Fl_Group* o = new Fl_Group(285, 30, 110, 75, "light");
314 o->tooltip("Measured from the View Point.");
315 o->labeltype(FL_NO_LABEL);
316 { Fl_Value_Input* o = lightx = new Fl_Value_Input(285, 45, 110, 20, "Light Source");
317 o->tooltip("X coordinate of Light Source.");
318 o->labelsize(12);
319 o->minimum(-1e+20);
320 o->maximum(1e+20);
321 o->textsize(12);
322 o->callback((Fl_Callback*)cb_lightx);
323 o->align(FL_ALIGN_TOP_LEFT);
324 }
325 { Fl_Value_Input* o = lighty = new Fl_Value_Input(285, 65, 110, 20, "value:");
326 o->tooltip("Y coordinate of Light Source.");
327 o->labeltype(FL_NO_LABEL);
328 o->labelsize(12);
329 o->minimum(-1e+20);
330 o->maximum(1e+20);
331 o->textsize(12);
332 o->callback((Fl_Callback*)cb_lighty);
333 }
334 { Fl_Value_Input* o = lightz = new Fl_Value_Input(285, 85, 110, 20, "value:");
335 o->tooltip("Z coordinate of Light Source.");
336 o->labeltype(FL_NO_LABEL);
337 o->labelsize(12);
338 o->minimum(-1e+20);
339 o->maximum(1e+20);
340 o->textsize(12);
341 o->callback((Fl_Callback*)cb_lightz);
342 }
343 o->end();
344 }
345 { Fl_Group* o = group_move = new Fl_Group(285, 120, 110, 55, "move");
346 o->tooltip("Move the view plane parallel to itself.");
347 o->labeltype(FL_NO_LABEL);
348 { Fl_Value_Input* o = movex = new Fl_Value_Input(285, 135, 110, 20, "Move");
349 o->tooltip("Movement in X direction.");
350 o->labelsize(12);
351 o->minimum(-1e+20);
352 o->maximum(1e+20);
353 o->textsize(12);
354 o->callback((Fl_Callback*)cb_movex);
355 o->align(FL_ALIGN_TOP_LEFT);
356 }
357 { Fl_Value_Input* o = movey = new Fl_Value_Input(285, 155, 110, 20, "value:");
358 o->tooltip("Movement in Y direction.");
359 o->labeltype(FL_NO_LABEL);
360 o->labelsize(12);
361 o->minimum(-1e+20);
362 o->maximum(1e+20);
363 o->textsize(12);
364 o->callback((Fl_Callback*)cb_movey);
365 }
366 o->end();
367 }
368 o->clear_border();
369 o->end();
370 }
371 memset(&view, 0, sizeof(view));
372 end(); // VERY IMPORTANT!
373 win->position(X+2, Y+2);
374 // DON'T delete win in destructor (or elsewhere)
375 // it's automatically deleted by Fl_Group
376 }
377
setSelectors(ViewSelector * vsa,ViewSelector * vsb,ViewSelector * vsf,Fl_Light_Button * ster)378 void ViewEditor::setSelectors(ViewSelector *vsa, ViewSelector *vsb, ViewSelector *vsf, Fl_Light_Button *ster) {
379 vs[0] = vsa; vs[1] = vsb; vs[2] = vsf;
380 stereo = ster;
381 }
382
set(const view_cpp & v)383 void ViewEditor::set(const view_cpp& v) {
384 for (int i=0; i<3; i++) assert(vs[i] != 0);
385 assert(stereo != 0);
386 view = v;
387 vre->value(v.s[0]); vi->value(v.s[1]); vj->value(v.s[2]);
388 upre->value(v.up[0]); upi->value(v.up[1]); upj->value(v.up[2]);
389 lxr->value(v.LXR);
390 ocular_dist->value(v.interocular);
391 lightx->value(v.light[0]); lighty->value(v.light[1]); lightz->value(v.light[2]);
392 movex->value(v.Mov[0]);
393 movey->value(v.Mov[1]);
394
395 // Set Angle, set ViewSelectors and checkValidity:
396 ocular_dist->do_callback();
397 vre->do_callback(); vi->do_callback(); vj->do_callback();
398 upre->do_callback(); upi->do_callback(); upj->do_callback();
399 lxr->do_callback(); movex->do_callback(); movey->do_callback();
400
401 return;
402 }
403
get(view_cpp & v)404 void ViewEditor::get(view_cpp& v) {
405 // Don't do v=view, because there are other members
406 // which aren't in the ViewEditor
407
408 v.s[0] = view.s[0]; v.s[1] = view.s[1]; v.s[2] = view.s[2];
409 v.up[0] = view.up[0]; v.up[1] = view.up[1]; v.up[2] = view.up[2];
410 v.LXR = view.LXR;
411 v.interocular = view.interocular;
412 v.light[0] = view.light[0];
413 v.light[1] = view.light[1];
414 v.light[2] = view.light[2];
415 v.Mov[0] = view.Mov[0];
416 v.Mov[1] = view.Mov[1];
417
418 return;
419 }
420
parallel(double a[],double b[])421 bool ViewEditor::parallel(double a[], double b[]) {
422 double c[3] = {0.0, 0.0, 0.0};
423 c[0] = a[1]*b[2] - a[2]*b[1];
424 c[1] = a[2]*b[0] - a[0]*b[2];
425 c[2] = a[0]*b[1] - a[1]*b[0];
426 //double ab = c[0]*c[0] + c[1]*c[1] + c[2]*c[2];
427 return (vec_abs(c)==0.0);
428 }
429
vec_abs(double a[])430 double ViewEditor::vec_abs(double a[]) {
431 return sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
432 }
433
newangle()434 double ViewEditor::newangle() {
435 double a = vec_abs(view.s);
436 if (a==0.0 && view.interocular != 0.0) return 180.0;
437 else if (a==0.0) return(ocular_angle->value());
438 else return atan(view.interocular/(2.0*a))*360.0/M_PI;
439 }
440
newdist()441 double ViewEditor::newdist() {
442 return 2.0*vec_abs(view.s)*tan(M_PI*ocular_angle->value()/360.0);
443 }
444
checkValidity()445 void ViewEditor::checkValidity() {
446 const Fl_Color okc = FL_WHITE;
447 const Fl_Color ndefc = FL_RED;
448 Fl_Color vre_c = okc, vi_c = okc, vj_c = okc,
449 upre_c = okc, upi_c = okc, upj_c = okc,
450 lxr_c = okc, od_c = okc, oa_c = okc;
451
452 if (vec_abs(view.s) == 0.0) {
453 vre_c = ndefc; vi_c = ndefc; vj_c = ndefc;
454 }
455 else if (parallel(view.s, view.up)) {
456 upre_c = ndefc; upi_c = ndefc; upj_c = ndefc;
457 }
458
459 if (view.LXR <= 0.0) lxr_c = ndefc;
460
461 if (view.interocular < 0.0) {
462 od_c = ndefc; oa_c = ndefc;
463 }
464
465 if (vre_c != vre->color()) { vre->color(vre_c); vre->redraw(); }
466 if (vi_c != vi->color()) { vi->color(vi_c); vi->redraw(); }
467 if (vj_c != vj->color()) { vj->color(vj_c); vj->redraw(); }
468
469 if (upre_c != upre->color()) { upre->color(upre_c); upre->redraw(); }
470 if (upi_c != upi->color()) { upi->color(upi_c); upi->redraw(); }
471 if (upj_c != upj->color()) { upj->color(upj_c); upj->redraw(); }
472
473 if (lxr_c != lxr->color()) { lxr->color(lxr_c); lxr->redraw(); }
474
475 if (od_c != ocular_dist->color()) { ocular_dist->color(od_c); ocular_dist->redraw(); }
476 if (oa_c != ocular_angle->color()) { ocular_angle->color(oa_c); ocular_angle->redraw(); }
477
478 if (view.interocular == 0.0 && stereo->active()) stereo->deactivate();
479 if (view.interocular != 0.0 && !stereo->active()) stereo->activate();
480
481 return;
482 }
483