1 | #include "Command.h" |
---|
2 | |
---|
3 | |
---|
4 | #include "nanovis.h" |
---|
5 | |
---|
6 | #include "RpField1D.h" |
---|
7 | #include "RpFieldRect3D.h" |
---|
8 | #include "RpFieldPrism3D.h" |
---|
9 | #include "RpEncode.h" |
---|
10 | |
---|
11 | #include "transfer-function/TransferFunctionMain.h" |
---|
12 | #include "transfer-function/ControlPoint.h" |
---|
13 | #include "transfer-function/TransferFunctionGLUTWindow.h" |
---|
14 | #include "transfer-function/ColorGradientGLUTWindow.h" |
---|
15 | #include "transfer-function/ColorPaletteWindow.h" |
---|
16 | #include "transfer-function/MainWindow.h" |
---|
17 | |
---|
18 | #include "Nv.h" |
---|
19 | #include "PointSetRenderer.h" |
---|
20 | #include "PointSet.h" |
---|
21 | #include "ZincBlendeVolume.h" |
---|
22 | #include "NvLoadFile.h" |
---|
23 | #include "NvColorTableRenderer.h" |
---|
24 | #include "NvEventLog.h" |
---|
25 | #include "NvZincBlendeReconstructor.h" |
---|
26 | #include "HeightMap.h" |
---|
27 | #include "Grid.h" |
---|
28 | #include "Camera.h" |
---|
29 | |
---|
30 | // FOR testing new functions |
---|
31 | //#define _LOCAL_ZINC_TEST_ |
---|
32 | //#include "Test.h" |
---|
33 | |
---|
34 | // EXTERN DECLARATIONS |
---|
35 | // in Nv.cpp |
---|
36 | extern VolumeRenderer* g_vol_render; |
---|
37 | extern PointSetRenderer* g_pointset_renderer; |
---|
38 | extern NvColorTableRenderer* g_color_table_renderer; |
---|
39 | extern Grid* g_grid; |
---|
40 | |
---|
41 | // in nanovis.cpp |
---|
42 | extern int n_volumes; |
---|
43 | extern vector<Volume*> volume; |
---|
44 | extern vector<HeightMap*> g_heightMap; |
---|
45 | extern vector<PointSet*> g_pointSet; |
---|
46 | |
---|
47 | extern float live_rot_x; //object rotation angles |
---|
48 | extern float live_rot_y; |
---|
49 | extern float live_rot_z; |
---|
50 | extern float live_obj_x; //object translation location from the origin |
---|
51 | extern float live_obj_y; |
---|
52 | extern float live_obj_z; |
---|
53 | extern int updir; |
---|
54 | extern Camera* cam; |
---|
55 | |
---|
56 | extern char *def_transfunc; |
---|
57 | extern Tcl_HashTable tftable; |
---|
58 | extern float live_diffuse; |
---|
59 | extern float live_specular; |
---|
60 | |
---|
61 | extern bool axis_on; |
---|
62 | |
---|
63 | extern int win_width; //size of the render window |
---|
64 | extern int win_height; //size of the render window |
---|
65 | extern PlaneRenderer* plane_render; |
---|
66 | extern Texture2D* plane[10]; |
---|
67 | |
---|
68 | |
---|
69 | extern Rappture::Outcome load_volume_stream(int index, std::iostream& fin); |
---|
70 | extern Rappture::Outcome load_volume_stream2(int index, std::iostream& fin); |
---|
71 | extern void load_volume(int index, int width, int height, int depth, int n_component, float* data, double vmin, double vmax, |
---|
72 | double nzero_min); |
---|
73 | extern TransferFunction* get_transfunc(char *name); |
---|
74 | extern void resize_offscreen_buffer(int w, int h); |
---|
75 | extern void offscreen_buffer_capture(); |
---|
76 | extern void bmp_header_add_int(unsigned char* header, int& pos, int data); |
---|
77 | extern void bmp_write(const char* cmd); |
---|
78 | extern void bmp_write_to_file(); |
---|
79 | extern void display(); |
---|
80 | extern void display_offscreen_buffer(); |
---|
81 | extern void read_screen(); |
---|
82 | extern int renderLegend(int ivol, int width, int height, const char* volArg); |
---|
83 | |
---|
84 | // Tcl interpreter for incoming messages |
---|
85 | Tcl_Interp *interp; |
---|
86 | Tcl_DString cmdbuffer; |
---|
87 | |
---|
88 | static int ScreenShotCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])); |
---|
89 | static int CameraCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])); |
---|
90 | static int CutplaneCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])); |
---|
91 | static int LegendCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])); |
---|
92 | static int ScreenCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])); |
---|
93 | static int TransfuncCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])); |
---|
94 | static int UpCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])); |
---|
95 | static int VolumeCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])); |
---|
96 | |
---|
97 | static int PlaneNewCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])); |
---|
98 | static int PlaneLinkCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])); |
---|
99 | static int PlaneEnableCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])); |
---|
100 | |
---|
101 | static int GridCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])); |
---|
102 | static int AxisCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])); |
---|
103 | |
---|
104 | static int GetVolumeIndices _ANSI_ARGS_((Tcl_Interp *interp, int argc, CONST84 char *argv[], vector<int>* vectorPtr)); |
---|
105 | static int GetIndices(Tcl_Interp *interp, int argc, CONST84 char *argv[], vector<int>* vectorPtr); |
---|
106 | static int GetAxis _ANSI_ARGS_((Tcl_Interp *interp, char *str, int *valPtr)); |
---|
107 | static int GetColor _ANSI_ARGS_((Tcl_Interp *interp, char *str, float *rgbPtr)); |
---|
108 | |
---|
109 | |
---|
110 | /* |
---|
111 | * ---------------------------------------------------------------------- |
---|
112 | * CLIENT COMMAND: |
---|
113 | * camera aim <x0> <y0> <z0> |
---|
114 | * camera angle <xAngle> <yAngle> <zAngle> |
---|
115 | * camera zoom <factor> |
---|
116 | * |
---|
117 | * Clients send these commands to manipulate the camera. The "angle" |
---|
118 | * operation controls the angle of the camera around the focal point. |
---|
119 | * The "zoom" operation sets the zoom factor, moving the camera in |
---|
120 | * and out. |
---|
121 | * ---------------------------------------------------------------------- |
---|
122 | */ |
---|
123 | static int CameraCmd(ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]) |
---|
124 | { |
---|
125 | if (argc < 2) { |
---|
126 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
127 | " option arg arg...\"", (char*)NULL); |
---|
128 | return TCL_ERROR; |
---|
129 | } |
---|
130 | |
---|
131 | char c = *argv[1]; |
---|
132 | if (c == 'a' && strcmp(argv[1],"angle") == 0) { |
---|
133 | if (argc != 5) { |
---|
134 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
135 | " angle xangle yangle zangle\"", (char*)NULL); |
---|
136 | return TCL_ERROR; |
---|
137 | } |
---|
138 | |
---|
139 | double xangle, yangle, zangle; |
---|
140 | if (Tcl_GetDouble(interp, argv[2], &xangle) != TCL_OK) { |
---|
141 | return TCL_ERROR; |
---|
142 | } |
---|
143 | if (Tcl_GetDouble(interp, argv[3], &yangle) != TCL_OK) { |
---|
144 | return TCL_ERROR; |
---|
145 | } |
---|
146 | if (Tcl_GetDouble(interp, argv[4], &zangle) != TCL_OK) { |
---|
147 | return TCL_ERROR; |
---|
148 | } |
---|
149 | cam->rotate(xangle, yangle, zangle); |
---|
150 | |
---|
151 | return TCL_OK; |
---|
152 | } |
---|
153 | else if (c == 'a' && strcmp(argv[1],"aim") == 0) { |
---|
154 | if (argc != 5) { |
---|
155 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
156 | " aim x y z\"", (char*)NULL); |
---|
157 | return TCL_ERROR; |
---|
158 | } |
---|
159 | |
---|
160 | double x0, y0, z0; |
---|
161 | if (Tcl_GetDouble(interp, argv[2], &x0) != TCL_OK) { |
---|
162 | return TCL_ERROR; |
---|
163 | } |
---|
164 | if (Tcl_GetDouble(interp, argv[3], &y0) != TCL_OK) { |
---|
165 | return TCL_ERROR; |
---|
166 | } |
---|
167 | if (Tcl_GetDouble(interp, argv[4], &z0) != TCL_OK) { |
---|
168 | return TCL_ERROR; |
---|
169 | } |
---|
170 | cam->aim(x0, y0, z0); |
---|
171 | |
---|
172 | return TCL_OK; |
---|
173 | } |
---|
174 | else if (c == 'z' && strcmp(argv[1],"zoom") == 0) { |
---|
175 | if (argc != 3) { |
---|
176 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
177 | " zoom factor\"", (char*)NULL); |
---|
178 | return TCL_ERROR; |
---|
179 | } |
---|
180 | |
---|
181 | double zoom; |
---|
182 | if (Tcl_GetDouble(interp, argv[2], &zoom) != TCL_OK) { |
---|
183 | return TCL_ERROR; |
---|
184 | } |
---|
185 | |
---|
186 | live_obj_z = -2.5/zoom; |
---|
187 | cam->move(live_obj_x, live_obj_y, live_obj_z); |
---|
188 | |
---|
189 | return TCL_OK; |
---|
190 | } |
---|
191 | |
---|
192 | Tcl_AppendResult(interp, "bad option \"", argv[1], |
---|
193 | "\": should be aim, angle, or zoom", (char*)NULL); |
---|
194 | return TCL_ERROR; |
---|
195 | } |
---|
196 | |
---|
197 | static int |
---|
198 | ScreenShotCmd(ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]) |
---|
199 | { |
---|
200 | int old_win_width = win_width; |
---|
201 | int old_win_height = win_height; |
---|
202 | |
---|
203 | #ifdef XINETD |
---|
204 | resize_offscreen_buffer(1024, 1024); |
---|
205 | cam->set_screen_size(30, 90, 1024 - 60, 1024 - 120); |
---|
206 | offscreen_buffer_capture(); //enable offscreen render |
---|
207 | display(); |
---|
208 | |
---|
209 | // INSOO |
---|
210 | // TBD |
---|
211 | Volume* vol = volume[0]; |
---|
212 | TransferFunction* tf = g_vol_render->get_volume_shading(vol); |
---|
213 | if (tf) |
---|
214 | { |
---|
215 | float data[512]; |
---|
216 | for (int i=0; i < 256; i++) { |
---|
217 | data[i] = data[i+256] = (float)(i/255.0); |
---|
218 | } |
---|
219 | Texture2D* plane = new Texture2D(256, 2, GL_FLOAT, GL_LINEAR, 1, data); |
---|
220 | g_color_table_renderer->render(1024, 1024, plane, tf, vol->range_min(), vol->range_max()); |
---|
221 | delete plane; |
---|
222 | } |
---|
223 | |
---|
224 | read_screen(); |
---|
225 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); |
---|
226 | |
---|
227 | bmp_write("nv>screenshot -bytes"); |
---|
228 | |
---|
229 | resize_offscreen_buffer(old_win_width, old_win_height); |
---|
230 | #endif |
---|
231 | |
---|
232 | return TCL_OK; |
---|
233 | } |
---|
234 | |
---|
235 | /* |
---|
236 | * ---------------------------------------------------------------------- |
---|
237 | * CLIENT COMMAND: |
---|
238 | * cutplane state on|off <axis> ?<volume>...? |
---|
239 | * cutplane position <relvalue> <axis> ?<volume>...? |
---|
240 | * |
---|
241 | * Clients send these commands to manipulate the cutplanes in one or |
---|
242 | * more data volumes. The "state" command turns a cutplane on or |
---|
243 | * off. The "position" command changes the position to a relative |
---|
244 | * value in the range 0-1. The <axis> can be x, y, or z. These |
---|
245 | * operations are applied to the volumes represented by one or more |
---|
246 | * <volume> indices. If no volumes are specified, then all volumes |
---|
247 | * are updated. |
---|
248 | * ---------------------------------------------------------------------- |
---|
249 | */ |
---|
250 | |
---|
251 | static int |
---|
252 | CutplaneCmd(ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]) |
---|
253 | { |
---|
254 | if (argc < 2) { |
---|
255 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
256 | " option ?arg arg...?\"", (char*)NULL); |
---|
257 | return TCL_ERROR; |
---|
258 | } |
---|
259 | |
---|
260 | char c = *argv[1]; |
---|
261 | if (c == 's' && strcmp(argv[1],"state") == 0) { |
---|
262 | if (argc < 4) { |
---|
263 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
264 | " state on|off axis ?volume ...? \"", (char*)NULL); |
---|
265 | return TCL_ERROR; |
---|
266 | } |
---|
267 | |
---|
268 | int state; |
---|
269 | if (Tcl_GetBoolean(interp, argv[2], &state) != TCL_OK) { |
---|
270 | return TCL_ERROR; |
---|
271 | } |
---|
272 | |
---|
273 | int axis; |
---|
274 | if (GetAxis(interp, (char*) argv[3], &axis) != TCL_OK) { |
---|
275 | return TCL_ERROR; |
---|
276 | } |
---|
277 | |
---|
278 | vector<int> ivol; |
---|
279 | if (GetVolumeIndices(interp, argc-4, argv+4, &ivol) != TCL_OK) { |
---|
280 | return TCL_ERROR; |
---|
281 | } |
---|
282 | |
---|
283 | vector<int>::iterator iter = ivol.begin(); |
---|
284 | while (iter != ivol.end()) { |
---|
285 | if (state) { |
---|
286 | volume[*iter]->enable_cutplane(axis); |
---|
287 | } else { |
---|
288 | volume[*iter]->disable_cutplane(axis); |
---|
289 | } |
---|
290 | ++iter; |
---|
291 | } |
---|
292 | return TCL_OK; |
---|
293 | } |
---|
294 | else if (c == 'p' && strcmp(argv[1],"position") == 0) { |
---|
295 | if (argc < 4) { |
---|
296 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
297 | " position relval axis ?volume ...? \"", (char*)NULL); |
---|
298 | return TCL_ERROR; |
---|
299 | } |
---|
300 | |
---|
301 | double relval; |
---|
302 | if (Tcl_GetDouble(interp, argv[2], &relval) != TCL_OK) { |
---|
303 | return TCL_ERROR; |
---|
304 | } |
---|
305 | // keep this just inside the volume so it doesn't disappear |
---|
306 | if (relval < 0.01) { relval = 0.01; } |
---|
307 | if (relval > 0.99) { relval = 0.99; } |
---|
308 | |
---|
309 | int axis; |
---|
310 | if (GetAxis(interp, (char*) argv[3], &axis) != TCL_OK) { |
---|
311 | return TCL_ERROR; |
---|
312 | } |
---|
313 | |
---|
314 | vector<int> ivol; |
---|
315 | if (GetVolumeIndices(interp, argc-4, argv+4, &ivol) != TCL_OK) { |
---|
316 | return TCL_ERROR; |
---|
317 | } |
---|
318 | |
---|
319 | vector<int>::iterator iter = ivol.begin(); |
---|
320 | while (iter != ivol.end()) { |
---|
321 | volume[*iter]->move_cutplane(axis, (float)relval); |
---|
322 | ++iter; |
---|
323 | } |
---|
324 | return TCL_OK; |
---|
325 | } |
---|
326 | |
---|
327 | Tcl_AppendResult(interp, "bad option \"", argv[1], |
---|
328 | "\": should be position or state", (char*)NULL); |
---|
329 | return TCL_ERROR; |
---|
330 | } |
---|
331 | |
---|
332 | |
---|
333 | /* |
---|
334 | * ---------------------------------------------------------------------- |
---|
335 | * CLIENT COMMAND: |
---|
336 | * legend <volumeIndex> <width> <height> |
---|
337 | * |
---|
338 | * Clients use this to generate a legend image for the specified |
---|
339 | * transfer function. The legend image is a color gradient from 0 |
---|
340 | * to one, drawn in the given transfer function. The resulting image |
---|
341 | * is returned in the size <width> x <height>. |
---|
342 | * ---------------------------------------------------------------------- |
---|
343 | */ |
---|
344 | static int |
---|
345 | LegendCmd(ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]) |
---|
346 | { |
---|
347 | if (argc != 4) { |
---|
348 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
349 | " transfunc width height\"", (char*)NULL); |
---|
350 | return TCL_ERROR; |
---|
351 | } |
---|
352 | |
---|
353 | TransferFunction *tf = NULL; |
---|
354 | int ivol; |
---|
355 | if (Tcl_GetInt(interp, argv[1], &ivol) != TCL_OK) { |
---|
356 | return TCL_ERROR; |
---|
357 | } |
---|
358 | |
---|
359 | if (ivol < n_volumes) { |
---|
360 | tf = g_vol_render->get_volume_shading(volume[ivol]); |
---|
361 | } |
---|
362 | if (tf == NULL) { |
---|
363 | Tcl_AppendResult(interp, "transfer function not defined for volume ", argv[1], (char*)NULL); |
---|
364 | return TCL_ERROR; |
---|
365 | } |
---|
366 | |
---|
367 | int old_width = win_width; |
---|
368 | int old_height = win_height; |
---|
369 | |
---|
370 | int width, height; |
---|
371 | if (Tcl_GetInt(interp, argv[2], &width) != TCL_OK) { |
---|
372 | return TCL_ERROR; |
---|
373 | } |
---|
374 | if (Tcl_GetInt(interp, argv[3], &height) != TCL_OK) { |
---|
375 | return TCL_ERROR; |
---|
376 | } |
---|
377 | |
---|
378 | renderLegend(ivol, width, height, argv[1]); |
---|
379 | |
---|
380 | return TCL_OK; |
---|
381 | } |
---|
382 | |
---|
383 | /* |
---|
384 | * ---------------------------------------------------------------------- |
---|
385 | * CLIENT COMMAND: |
---|
386 | * screen <width> <height> |
---|
387 | * |
---|
388 | * Clients send this command to set the size of the rendering area. |
---|
389 | * Future images are generated at the specified width/height. |
---|
390 | * ---------------------------------------------------------------------- |
---|
391 | */ |
---|
392 | static int |
---|
393 | ScreenCmd(ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]) |
---|
394 | { |
---|
395 | int w, h; |
---|
396 | |
---|
397 | if (argc != 3) { |
---|
398 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
399 | " width height\"", (char*)NULL); |
---|
400 | return TCL_ERROR; |
---|
401 | } |
---|
402 | if (Tcl_GetInt(interp, argv[1], &w) != TCL_OK) { |
---|
403 | return TCL_ERROR; |
---|
404 | } |
---|
405 | if (Tcl_GetInt(interp, argv[2], &h) != TCL_OK) { |
---|
406 | return TCL_ERROR; |
---|
407 | } |
---|
408 | resize_offscreen_buffer(w, h); |
---|
409 | |
---|
410 | return TCL_OK; |
---|
411 | } |
---|
412 | |
---|
413 | /* |
---|
414 | * ---------------------------------------------------------------------- |
---|
415 | * CLIENT COMMAND: |
---|
416 | * transfunc define <name> <colormap> <alphamap> |
---|
417 | * where <colormap> = { <v> <r> <g> <b> ... } |
---|
418 | * <alphamap> = { <v> <w> ... } |
---|
419 | * |
---|
420 | * Clients send these commands to manipulate the transfer functions. |
---|
421 | * ---------------------------------------------------------------------- |
---|
422 | */ |
---|
423 | static int |
---|
424 | TransfuncCmd(ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]) |
---|
425 | { |
---|
426 | if (argc < 2) { |
---|
427 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
428 | " option arg arg...\"", (char*)NULL); |
---|
429 | return TCL_ERROR; |
---|
430 | } |
---|
431 | |
---|
432 | char c = *argv[1]; |
---|
433 | if (c == 'd' && strcmp(argv[1],"define") == 0) { |
---|
434 | if (argc != 5) { |
---|
435 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
436 | argv[1], " define name colormap alphamap\"", (char*)NULL); |
---|
437 | return TCL_ERROR; |
---|
438 | } |
---|
439 | |
---|
440 | // decode the data and store in a series of fields |
---|
441 | Rappture::Field1D rFunc, gFunc, bFunc, wFunc; |
---|
442 | int cmapc, wmapc, i, j; |
---|
443 | char **cmapv, **wmapv; |
---|
444 | |
---|
445 | if (Tcl_SplitList(interp, argv[3], &cmapc, (const char***)&cmapv) != TCL_OK) { |
---|
446 | return TCL_ERROR; |
---|
447 | } |
---|
448 | if (cmapc % 4 != 0) { |
---|
449 | Tcl_Free((char*)cmapv); |
---|
450 | Tcl_AppendResult(interp, "bad colormap in transfunc: should be ", |
---|
451 | "{ v r g b ... }", (char*)NULL); |
---|
452 | return TCL_ERROR; |
---|
453 | } |
---|
454 | |
---|
455 | if (Tcl_SplitList(interp, argv[4], &wmapc, (const char***)&wmapv) != TCL_OK) { |
---|
456 | return TCL_ERROR; |
---|
457 | } |
---|
458 | if (wmapc % 2 != 0) { |
---|
459 | Tcl_Free((char*)cmapv); |
---|
460 | Tcl_Free((char*)wmapv); |
---|
461 | Tcl_AppendResult(interp, "bad alphamap in transfunc: should be ", |
---|
462 | "{ v w ... }", (char*)NULL); |
---|
463 | return TCL_ERROR; |
---|
464 | } |
---|
465 | |
---|
466 | for (i=0; i < cmapc; i += 4) { |
---|
467 | double vals[4]; |
---|
468 | for (j=0; j < 4; j++) { |
---|
469 | if (Tcl_GetDouble(interp, cmapv[i+j], &vals[j]) != TCL_OK) { |
---|
470 | Tcl_Free((char*)cmapv); |
---|
471 | Tcl_Free((char*)wmapv); |
---|
472 | return TCL_ERROR; |
---|
473 | } |
---|
474 | if (vals[j] < 0 || vals[j] > 1) { |
---|
475 | Tcl_Free((char*)cmapv); |
---|
476 | Tcl_Free((char*)wmapv); |
---|
477 | Tcl_AppendResult(interp, "bad value \"", cmapv[i+j], |
---|
478 | "\": should be in the range 0-1", (char*)NULL); |
---|
479 | return TCL_ERROR; |
---|
480 | } |
---|
481 | } |
---|
482 | rFunc.define(vals[0], vals[1]); |
---|
483 | gFunc.define(vals[0], vals[2]); |
---|
484 | bFunc.define(vals[0], vals[3]); |
---|
485 | } |
---|
486 | |
---|
487 | for (i=0; i < wmapc; i += 2) { |
---|
488 | double vals[2]; |
---|
489 | for (j=0; j < 2; j++) { |
---|
490 | if (Tcl_GetDouble(interp, wmapv[i+j], &vals[j]) != TCL_OK) { |
---|
491 | Tcl_Free((char*)cmapv); |
---|
492 | Tcl_Free((char*)wmapv); |
---|
493 | return TCL_ERROR; |
---|
494 | } |
---|
495 | if (vals[j] < 0 || vals[j] > 1) { |
---|
496 | Tcl_Free((char*)cmapv); |
---|
497 | Tcl_Free((char*)wmapv); |
---|
498 | Tcl_AppendResult(interp, "bad value \"", wmapv[i+j], |
---|
499 | "\": should be in the range 0-1", (char*)NULL); |
---|
500 | return TCL_ERROR; |
---|
501 | } |
---|
502 | } |
---|
503 | wFunc.define(vals[0], vals[1]); |
---|
504 | } |
---|
505 | Tcl_Free((char*)cmapv); |
---|
506 | Tcl_Free((char*)wmapv); |
---|
507 | |
---|
508 | // sample the given function into discrete slots |
---|
509 | const int nslots = 256; |
---|
510 | float data[4*nslots]; |
---|
511 | for (i=0; i < nslots; i++) { |
---|
512 | double xval = double(i)/(nslots-1); |
---|
513 | data[4*i] = rFunc.value(xval); |
---|
514 | data[4*i+1] = gFunc.value(xval); |
---|
515 | data[4*i+2] = bFunc.value(xval); |
---|
516 | data[4*i+3] = wFunc.value(xval); |
---|
517 | } |
---|
518 | |
---|
519 | // find or create this transfer function |
---|
520 | int newEntry; |
---|
521 | Tcl_HashEntry *entryPtr; |
---|
522 | TransferFunction *tf; |
---|
523 | |
---|
524 | entryPtr = Tcl_CreateHashEntry(&tftable, argv[2], &newEntry); |
---|
525 | if (newEntry) { |
---|
526 | tf = new TransferFunction(nslots, data); |
---|
527 | Tcl_SetHashValue(entryPtr, (ClientData)tf); |
---|
528 | } else { |
---|
529 | tf = (TransferFunction*)Tcl_GetHashValue(entryPtr); |
---|
530 | tf->update(data); |
---|
531 | } |
---|
532 | |
---|
533 | return TCL_OK; |
---|
534 | } |
---|
535 | |
---|
536 | |
---|
537 | Tcl_AppendResult(interp, "bad option \"", argv[1], |
---|
538 | "\": should be define", (char*)NULL); |
---|
539 | return TCL_ERROR; |
---|
540 | } |
---|
541 | |
---|
542 | /* |
---|
543 | * ---------------------------------------------------------------------- |
---|
544 | * CLIENT COMMAND: |
---|
545 | * up axis |
---|
546 | * |
---|
547 | * Clients use this to set the "up" direction for all volumes. Volumes |
---|
548 | * are oriented such that this direction points upward. |
---|
549 | * ---------------------------------------------------------------------- |
---|
550 | */ |
---|
551 | static int |
---|
552 | UpCmd(ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]) |
---|
553 | { |
---|
554 | if (argc != 2) { |
---|
555 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
556 | " x|y|z|-x|-y|-z\"", (char*)NULL); |
---|
557 | return TCL_ERROR; |
---|
558 | } |
---|
559 | |
---|
560 | int sign = 1; |
---|
561 | char *axisName = (char*)argv[1]; |
---|
562 | if (*axisName == '-') { |
---|
563 | sign = -1; |
---|
564 | axisName++; |
---|
565 | } |
---|
566 | |
---|
567 | int axis; |
---|
568 | if (GetAxis(interp, axisName, &axis) != TCL_OK) { |
---|
569 | return TCL_ERROR; |
---|
570 | } |
---|
571 | |
---|
572 | updir = (axis+1)*sign; |
---|
573 | |
---|
574 | return TCL_OK; |
---|
575 | } |
---|
576 | |
---|
577 | /* |
---|
578 | * ---------------------------------------------------------------------- |
---|
579 | * CLIENT COMMAND: |
---|
580 | * volume axis label x|y|z <value> ?<volumeId> ...? |
---|
581 | * volume data state on|off ?<volumeId> ...? |
---|
582 | * volume outline state on|off ?<volumeId> ...? |
---|
583 | * volume outline color on|off ?<volumeId> ...? |
---|
584 | * volume shading transfunc <name> ?<volumeId> ...? |
---|
585 | * volume shading diffuse <value> ?<volumeId> ...? |
---|
586 | * volume shading specular <value> ?<volumeId> ...? |
---|
587 | * volume shading opacity <value> ?<volumeId> ...? |
---|
588 | * volume state on|off ?<volumeId> ...? |
---|
589 | * |
---|
590 | * Clients send these commands to manipulate the volumes. |
---|
591 | * ---------------------------------------------------------------------- |
---|
592 | */ |
---|
593 | |
---|
594 | static int |
---|
595 | VolumeCmd(ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[]) |
---|
596 | { |
---|
597 | if (argc < 2) { |
---|
598 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
599 | " option arg arg...\"", (char*)NULL); |
---|
600 | return TCL_ERROR; |
---|
601 | } |
---|
602 | |
---|
603 | char c = *argv[1]; |
---|
604 | if (c == 'a' && strcmp(argv[1],"axis") == 0) { |
---|
605 | if (argc < 3) { |
---|
606 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
607 | argv[1], " option ?arg arg...?\"", (char*)NULL); |
---|
608 | return TCL_ERROR; |
---|
609 | } |
---|
610 | c = *argv[2]; |
---|
611 | if (c == 'l' && strcmp(argv[2],"label") == 0) { |
---|
612 | if (argc < 4) { |
---|
613 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
614 | argv[1], " label x|y|z string ?volume ...?\"", (char*)NULL); |
---|
615 | return TCL_ERROR; |
---|
616 | } |
---|
617 | |
---|
618 | int axis; |
---|
619 | if (GetAxis(interp, (char*)argv[3], &axis) != TCL_OK) { |
---|
620 | return TCL_ERROR; |
---|
621 | } |
---|
622 | |
---|
623 | vector<int> ivol; |
---|
624 | if (GetVolumeIndices(interp, argc-5, argv+5, &ivol) != TCL_OK) { |
---|
625 | return TCL_ERROR; |
---|
626 | } |
---|
627 | |
---|
628 | vector<int>::iterator iter = ivol.begin(); |
---|
629 | while (iter != ivol.end()) { |
---|
630 | volume[*iter]->set_label(axis, (char*)argv[4]); |
---|
631 | ++iter; |
---|
632 | } |
---|
633 | return TCL_OK; |
---|
634 | } |
---|
635 | |
---|
636 | Tcl_AppendResult(interp, "bad option \"", argv[2], |
---|
637 | "\": should be label", (char*)NULL); |
---|
638 | return TCL_ERROR; |
---|
639 | } |
---|
640 | else if (c == 'd' && strcmp(argv[1],"data") == 0) { |
---|
641 | if (argc < 3) { |
---|
642 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
643 | argv[1], " option ?arg arg...?\"", (char*)NULL); |
---|
644 | return TCL_ERROR; |
---|
645 | } |
---|
646 | c = *argv[2]; |
---|
647 | if (c == 's' && strcmp(argv[2],"state") == 0) { |
---|
648 | if (argc < 4) { |
---|
649 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
650 | argv[1], " state on|off ?volume ...?\"", (char*)NULL); |
---|
651 | return TCL_ERROR; |
---|
652 | } |
---|
653 | |
---|
654 | int state; |
---|
655 | if (Tcl_GetBoolean(interp, argv[3], &state) != TCL_OK) { |
---|
656 | return TCL_ERROR; |
---|
657 | } |
---|
658 | |
---|
659 | vector<int> ivol; |
---|
660 | if (GetVolumeIndices(interp, argc-4, argv+4, &ivol) != TCL_OK) { |
---|
661 | return TCL_ERROR; |
---|
662 | } |
---|
663 | |
---|
664 | vector<int>::iterator iter = ivol.begin(); |
---|
665 | while (iter != ivol.end()) { |
---|
666 | if (state) { |
---|
667 | volume[*iter]->enable_data(); |
---|
668 | } else { |
---|
669 | volume[*iter]->disable_data(); |
---|
670 | } |
---|
671 | ++iter; |
---|
672 | } |
---|
673 | return TCL_OK; |
---|
674 | } |
---|
675 | else if (c == 'f' && strcmp(argv[2],"follows") == 0) { |
---|
676 | printf("Data Loading\n"); |
---|
677 | //fflush(stdout); |
---|
678 | //return TCL_OK; |
---|
679 | |
---|
680 | int nbytes; |
---|
681 | if (Tcl_GetInt(interp, argv[3], &nbytes) != TCL_OK) { |
---|
682 | return TCL_ERROR; |
---|
683 | } |
---|
684 | |
---|
685 | Rappture::Outcome err; |
---|
686 | Rappture::Buffer buf; |
---|
687 | |
---|
688 | // DEBUG |
---|
689 | int totalsize = nbytes; |
---|
690 | char buffer[8096]; |
---|
691 | while (nbytes > 0) |
---|
692 | { |
---|
693 | int chunk = (sizeof(buffer) < nbytes) ? sizeof(buffer) : nbytes; |
---|
694 | int status = fread(buffer, 1, chunk, stdin); |
---|
695 | //printf("Begin Reading [%d Read : %d Left]\n", status, nbytes - status); |
---|
696 | fflush(stdout); |
---|
697 | if (status > 0) { |
---|
698 | buf.append(buffer,status); |
---|
699 | nbytes -= status; |
---|
700 | } else { |
---|
701 | printf("data unpacking failed\n"); |
---|
702 | Tcl_AppendResult(interp, "data unpacking failed: unexpected EOF", |
---|
703 | (char*)NULL); |
---|
704 | return TCL_ERROR; |
---|
705 | } |
---|
706 | } |
---|
707 | |
---|
708 | err = Rappture::encoding::decode(buf,RPENC_Z|RPENC_B64|RPENC_HDR); |
---|
709 | if (err) { |
---|
710 | printf("ERROR -- DECODING\n"); |
---|
711 | fflush(stdout); |
---|
712 | Tcl_AppendResult(interp, err.remark().c_str(), (char*)NULL); |
---|
713 | return TCL_ERROR; |
---|
714 | } |
---|
715 | |
---|
716 | int n = n_volumes; |
---|
717 | char header[6]; |
---|
718 | memcpy(header, buf.bytes(), sizeof(char) * 5); |
---|
719 | header[5] = '\0'; |
---|
720 | |
---|
721 | #ifdef _LOCAL_ZINC_TEST_ |
---|
722 | //FILE* fp = fopen("/home/nanohub/vrinside/nv/data/HOON/QDWL_100_100_50_strain_8000i.nd_zatom_12_1", "rb"); |
---|
723 | FILE* fp = fopen("/home/nanohub/vrinside/nv/data/HOON/GaAs_AlGaAs_2QD_B4.nd_zc_1_wf", "rb"); |
---|
724 | unsigned char* b = (unsigned char*) malloc(buf.size()); |
---|
725 | if (fp == 0) |
---|
726 | { |
---|
727 | printf("cannot open the file\n"); |
---|
728 | fflush(stdout); |
---|
729 | return TCL_ERROR; |
---|
730 | } |
---|
731 | fread(b, buf.size(), 1, fp); |
---|
732 | fclose(fp); |
---|
733 | #endif |
---|
734 | |
---|
735 | |
---|
736 | printf("Checking header[%s]\n", header); |
---|
737 | fflush(stdout); |
---|
738 | if (!strcmp(header, "<HDR>")) |
---|
739 | { |
---|
740 | Volume* vol = NULL; |
---|
741 | |
---|
742 | printf("ZincBlende stream is in\n"); |
---|
743 | fflush(stdout); |
---|
744 | //std::stringstream fdata(std::ios_base::out|std::ios_base::in|std::ios_base::binary); |
---|
745 | //fdata.write(buf.bytes(),buf.size()); |
---|
746 | //vol = NvZincBlendeReconstructor::getInstance()->loadFromStream(fdata); |
---|
747 | |
---|
748 | #ifdef _LOCAL_ZINC_TEST_ |
---|
749 | vol = NvZincBlendeReconstructor::getInstance()->loadFromMemory(b); |
---|
750 | #else |
---|
751 | vol = NvZincBlendeReconstructor::getInstance()->loadFromMemory((void*) buf.bytes()); |
---|
752 | #endif |
---|
753 | |
---|
754 | printf("finish loading\n"); |
---|
755 | fflush(stdout); |
---|
756 | if (vol) |
---|
757 | { |
---|
758 | while (n_volumes <= n) |
---|
759 | { |
---|
760 | volume.push_back((Volume*) NULL); |
---|
761 | n_volumes++; |
---|
762 | } |
---|
763 | |
---|
764 | if (volume[n] != NULL) |
---|
765 | { |
---|
766 | delete volume[n]; |
---|
767 | volume[n] = NULL; |
---|
768 | } |
---|
769 | |
---|
770 | float dx0 = -0.5; |
---|
771 | float dy0 = -0.5*vol->height/vol->width; |
---|
772 | float dz0 = -0.5*vol->depth/vol->width; |
---|
773 | vol->move(Vector3(dx0, dy0, dz0)); |
---|
774 | |
---|
775 | volume[n] = vol; |
---|
776 | } |
---|
777 | } |
---|
778 | #ifdef __TEST_CODE__ |
---|
779 | else if (!strcmp(header, "<FET>")) |
---|
780 | { |
---|
781 | printf("FET loading...\n"); |
---|
782 | fflush(stdout); |
---|
783 | std::stringstream fdata; |
---|
784 | fdata.write(buf.bytes(),buf.size()); |
---|
785 | err = load_volume_stream3(n, fdata); |
---|
786 | |
---|
787 | if (err) { |
---|
788 | Tcl_AppendResult(interp, err.remark().c_str(), (char*)NULL); |
---|
789 | return TCL_ERROR; |
---|
790 | } |
---|
791 | } |
---|
792 | #endif |
---|
793 | else |
---|
794 | { |
---|
795 | printf("OpenDX loading...\n"); |
---|
796 | fflush(stdout); |
---|
797 | std::stringstream fdata; |
---|
798 | fdata.write(buf.bytes(),buf.size()); |
---|
799 | err = load_volume_stream(n, fdata); |
---|
800 | //err = load_volume_stream2(n, fdata); |
---|
801 | if (err) { |
---|
802 | Tcl_AppendResult(interp, err.remark().c_str(), (char*)NULL); |
---|
803 | return TCL_ERROR; |
---|
804 | } |
---|
805 | } |
---|
806 | |
---|
807 | |
---|
808 | // |
---|
809 | // BE CAREFUL: Set the number of slices to something |
---|
810 | // slightly different for each volume. If we have |
---|
811 | // identical volumes at exactly the same position |
---|
812 | // with exactly the same number of slices, the second |
---|
813 | // volume will overwrite the first, so the first won't |
---|
814 | // appear at all. |
---|
815 | // |
---|
816 | if (volume[n]) |
---|
817 | { |
---|
818 | volume[n]->set_n_slice(256-n); |
---|
819 | volume[n]->disable_cutplane(0); |
---|
820 | volume[n]->disable_cutplane(1); |
---|
821 | volume[n]->disable_cutplane(2); |
---|
822 | |
---|
823 | g_vol_render->add_volume(volume[n], get_transfunc("default")); |
---|
824 | } |
---|
825 | |
---|
826 | return TCL_OK; |
---|
827 | } |
---|
828 | Tcl_AppendResult(interp, "bad option \"", argv[2], |
---|
829 | "\": should be follows or state", (char*)NULL); |
---|
830 | return TCL_ERROR; |
---|
831 | } |
---|
832 | else if (c == 'o' && strcmp(argv[1],"outline") == 0) { |
---|
833 | if (argc < 3) { |
---|
834 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
835 | argv[1], " option ?arg arg...?\"", (char*)NULL); |
---|
836 | return TCL_ERROR; |
---|
837 | } |
---|
838 | c = *argv[2]; |
---|
839 | if (c == 's' && strcmp(argv[2],"state") == 0) { |
---|
840 | if (argc < 3) { |
---|
841 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
842 | argv[1], " state on|off ?volume ...? \"", (char*)NULL); |
---|
843 | return TCL_ERROR; |
---|
844 | } |
---|
845 | |
---|
846 | int state; |
---|
847 | if (Tcl_GetBoolean(interp, argv[3], &state) != TCL_OK) { |
---|
848 | return TCL_ERROR; |
---|
849 | } |
---|
850 | |
---|
851 | vector<int> ivol; |
---|
852 | if (GetVolumeIndices(interp, argc-4, argv+4, &ivol) != TCL_OK) { |
---|
853 | return TCL_ERROR; |
---|
854 | } |
---|
855 | |
---|
856 | vector<int>::iterator iter = ivol.begin(); |
---|
857 | while (iter != ivol.end()) { |
---|
858 | if (state) { |
---|
859 | volume[*iter]->enable_outline(); |
---|
860 | } else { |
---|
861 | volume[*iter]->disable_outline(); |
---|
862 | } |
---|
863 | ++iter; |
---|
864 | } |
---|
865 | return TCL_OK; |
---|
866 | } |
---|
867 | else if (c == 'v' && strcmp(argv[2],"visible") == 0) { |
---|
868 | if (argv[3] == "false") |
---|
869 | { |
---|
870 | for (int i = 0; i < n_volumes; ++i) |
---|
871 | { |
---|
872 | if (volume[i]) volume[i]->disable_outline(); |
---|
873 | } |
---|
874 | } |
---|
875 | else if (argv[3] == "true") |
---|
876 | { |
---|
877 | for (int i = 0; i < n_volumes; ++i) |
---|
878 | { |
---|
879 | if (volume[i]) volume[i]->enable_outline(); |
---|
880 | } |
---|
881 | } |
---|
882 | |
---|
883 | return TCL_OK; |
---|
884 | } |
---|
885 | else if (c == 'c' && strcmp(argv[2],"color") == 0) { |
---|
886 | if (argc < 3) { |
---|
887 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
888 | argv[1], " color {R G B} ?volume ...? \"", (char*)NULL); |
---|
889 | return TCL_ERROR; |
---|
890 | } |
---|
891 | |
---|
892 | float rgb[3]; |
---|
893 | if (GetColor(interp, (char*) argv[3], rgb) != TCL_OK) { |
---|
894 | return TCL_ERROR; |
---|
895 | } |
---|
896 | |
---|
897 | vector<int> ivol; |
---|
898 | if (GetVolumeIndices(interp, argc-4, argv+4, &ivol) != TCL_OK) { |
---|
899 | return TCL_ERROR; |
---|
900 | } |
---|
901 | |
---|
902 | vector<int>::iterator iter = ivol.begin(); |
---|
903 | while (iter != ivol.end()) { |
---|
904 | volume[*iter]->set_outline_color(rgb); |
---|
905 | ++iter; |
---|
906 | } |
---|
907 | return TCL_OK; |
---|
908 | } |
---|
909 | |
---|
910 | Tcl_AppendResult(interp, "bad option \"", argv[2], |
---|
911 | "\": should be color or state", (char*)NULL); |
---|
912 | return TCL_ERROR; |
---|
913 | } |
---|
914 | else if (c == 's' && strcmp(argv[1],"shading") == 0) { |
---|
915 | if (argc < 3) { |
---|
916 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
917 | argv[1], " option ?arg arg...?\"", (char*)NULL); |
---|
918 | return TCL_ERROR; |
---|
919 | } |
---|
920 | c = *argv[2]; |
---|
921 | if (c == 't' && strcmp(argv[2],"transfunc") == 0) { |
---|
922 | if (argc < 4) { |
---|
923 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
924 | argv[1], " transfunc name ?volume ...?\"", (char*)NULL); |
---|
925 | return TCL_ERROR; |
---|
926 | } |
---|
927 | |
---|
928 | TransferFunction *tf = get_transfunc((char*)argv[3]); |
---|
929 | if (tf == NULL) { |
---|
930 | Tcl_AppendResult(interp, "transfer function \"", argv[3], |
---|
931 | "\" is not defined", (char*)NULL); |
---|
932 | return TCL_ERROR; |
---|
933 | } |
---|
934 | |
---|
935 | vector<int> ivol; |
---|
936 | if (GetVolumeIndices(interp, argc-4, argv+4, &ivol) != TCL_OK) { |
---|
937 | return TCL_ERROR; |
---|
938 | } |
---|
939 | |
---|
940 | vector<int>::iterator iter = ivol.begin(); |
---|
941 | while (iter != ivol.end()) { |
---|
942 | g_vol_render->shade_volume(volume[*iter], tf); |
---|
943 | ++iter; |
---|
944 | } |
---|
945 | return TCL_OK; |
---|
946 | } |
---|
947 | else if (c == 'd' && strcmp(argv[2],"diffuse") == 0) { |
---|
948 | if (argc < 4) { |
---|
949 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
950 | argv[1], " diffuse value ?volume ...?\"", (char*)NULL); |
---|
951 | return TCL_ERROR; |
---|
952 | } |
---|
953 | |
---|
954 | double dval; |
---|
955 | if (Tcl_GetDouble(interp, argv[3], &dval) != TCL_OK) { |
---|
956 | return TCL_ERROR; |
---|
957 | } |
---|
958 | |
---|
959 | vector<int> ivol; |
---|
960 | if (GetVolumeIndices(interp, argc-4, argv+4, &ivol) != TCL_OK) { |
---|
961 | return TCL_ERROR; |
---|
962 | } |
---|
963 | |
---|
964 | vector<int>::iterator iter = ivol.begin(); |
---|
965 | while (iter != ivol.end()) { |
---|
966 | volume[*iter]->set_diffuse((float)dval); |
---|
967 | ++iter; |
---|
968 | } |
---|
969 | return TCL_OK; |
---|
970 | } |
---|
971 | else if (c == 'o' && strcmp(argv[2],"opacity") == 0) { |
---|
972 | if (argc < 4) { |
---|
973 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
974 | argv[1], " opacity value ?volume ...?\"", (char*)NULL); |
---|
975 | return TCL_ERROR; |
---|
976 | } |
---|
977 | |
---|
978 | double dval; |
---|
979 | if (Tcl_GetDouble(interp, argv[3], &dval) != TCL_OK) { |
---|
980 | return TCL_ERROR; |
---|
981 | } |
---|
982 | |
---|
983 | vector<int> ivol; |
---|
984 | if (GetVolumeIndices(interp, argc-4, argv+4, &ivol) != TCL_OK) { |
---|
985 | return TCL_ERROR; |
---|
986 | } |
---|
987 | |
---|
988 | vector<int>::iterator iter = ivol.begin(); |
---|
989 | while (iter != ivol.end()) { |
---|
990 | volume[*iter]->set_opacity_scale((float)dval); |
---|
991 | ++iter; |
---|
992 | } |
---|
993 | return TCL_OK; |
---|
994 | } |
---|
995 | else if (c == 's' && strcmp(argv[2],"specular") == 0) { |
---|
996 | if (argc < 4) { |
---|
997 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
998 | argv[1], " specular value ?volume ...?\"", (char*)NULL); |
---|
999 | return TCL_ERROR; |
---|
1000 | } |
---|
1001 | |
---|
1002 | double dval; |
---|
1003 | if (Tcl_GetDouble(interp, argv[3], &dval) != TCL_OK) { |
---|
1004 | return TCL_ERROR; |
---|
1005 | } |
---|
1006 | |
---|
1007 | vector<int> ivol; |
---|
1008 | if (GetVolumeIndices(interp, argc-4, argv+4, &ivol) != TCL_OK) { |
---|
1009 | return TCL_ERROR; |
---|
1010 | } |
---|
1011 | |
---|
1012 | vector<int>::iterator iter = ivol.begin(); |
---|
1013 | while (iter != ivol.end()) { |
---|
1014 | volume[*iter]->set_specular((float)dval); |
---|
1015 | ++iter; |
---|
1016 | } |
---|
1017 | return TCL_OK; |
---|
1018 | } |
---|
1019 | Tcl_AppendResult(interp, "bad option \"", argv[2], |
---|
1020 | "\": should be diffuse, opacity, specular, or transfunc", (char*)NULL); |
---|
1021 | return TCL_ERROR; |
---|
1022 | } |
---|
1023 | else if (c == 's' && strcmp(argv[1],"state") == 0) { |
---|
1024 | if (argc < 3) { |
---|
1025 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
1026 | argv[1], " on|off ?volume...?\"", (char*)NULL); |
---|
1027 | return TCL_ERROR; |
---|
1028 | } |
---|
1029 | |
---|
1030 | int state; |
---|
1031 | if (Tcl_GetBoolean(interp, argv[2], &state) != TCL_OK) { |
---|
1032 | return TCL_ERROR; |
---|
1033 | } |
---|
1034 | |
---|
1035 | vector<int> ivol; |
---|
1036 | if (GetVolumeIndices(interp, argc-3, argv+3, &ivol) != TCL_OK) { |
---|
1037 | return TCL_ERROR; |
---|
1038 | } |
---|
1039 | |
---|
1040 | vector<int>::iterator iter = ivol.begin(); |
---|
1041 | while (iter != ivol.end()) { |
---|
1042 | if (state) { |
---|
1043 | volume[*iter]->enable(); |
---|
1044 | } else { |
---|
1045 | volume[*iter]->disable(); |
---|
1046 | } |
---|
1047 | ++iter; |
---|
1048 | } |
---|
1049 | return TCL_OK; |
---|
1050 | } |
---|
1051 | else if (c == 't' && strcmp(argv[1],"test2") == 0) { |
---|
1052 | volume[1]->disable_data(); |
---|
1053 | volume[1]->disable(); |
---|
1054 | return TCL_OK; |
---|
1055 | } |
---|
1056 | |
---|
1057 | Tcl_AppendResult(interp, "bad option \"", argv[1], |
---|
1058 | "\": should be data, outline, shading, or state", (char*)NULL); |
---|
1059 | return TCL_ERROR; |
---|
1060 | } |
---|
1061 | |
---|
1062 | |
---|
1063 | int HeightMapCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])) |
---|
1064 | { |
---|
1065 | if (argc < 2) |
---|
1066 | { |
---|
1067 | { |
---|
1068 | srand( (unsigned)time( NULL ) ); |
---|
1069 | int size = 20 * 20; |
---|
1070 | float sigma = 5.0f; |
---|
1071 | float mean = exp(0.0f) / (sigma * sqrt(2.0f)); |
---|
1072 | float* data = (float*) malloc(sizeof(float) * size); |
---|
1073 | |
---|
1074 | float x; |
---|
1075 | for (int i = 0; i < size; ++i) |
---|
1076 | { |
---|
1077 | x = - 10 + i%20; |
---|
1078 | data[i] = exp(- (x * x)/(2 * sigma * sigma)) / (sigma * sqrt(2.0f)) / mean; |
---|
1079 | } |
---|
1080 | |
---|
1081 | HeightMap* heightMap = new HeightMap(); |
---|
1082 | heightMap->setHeight(0, 0, 1, 1, 20, 20, data); |
---|
1083 | heightMap->setColorMap(get_transfunc("default")); |
---|
1084 | heightMap->setVisible(true); |
---|
1085 | heightMap->setLineContourVisible(true); |
---|
1086 | g_heightMap.push_back(heightMap); |
---|
1087 | } |
---|
1088 | |
---|
1089 | return TCL_OK; |
---|
1090 | } |
---|
1091 | |
---|
1092 | char c = *argv[1]; |
---|
1093 | if (c == 'd' && strcmp(argv[1],"data") == 0) |
---|
1094 | { |
---|
1095 | //bytes |
---|
1096 | vector<int> indices; |
---|
1097 | if (strcmp(argv[2],"visible") == 0) |
---|
1098 | { |
---|
1099 | bool visible = !strcmp(argv[3], "true"); |
---|
1100 | |
---|
1101 | if (GetIndices(interp, argc-4, argv+4, &indices) != TCL_OK) |
---|
1102 | { |
---|
1103 | return TCL_ERROR; |
---|
1104 | } |
---|
1105 | |
---|
1106 | for (int i = 0; i < indices.size(); ++i) |
---|
1107 | { |
---|
1108 | if ((indices[i] < g_heightMap.size()) && (g_heightMap[indices[i]] != NULL)) |
---|
1109 | { |
---|
1110 | g_heightMap[indices[i]]->setVisible(visible); |
---|
1111 | } |
---|
1112 | } |
---|
1113 | return TCL_OK; |
---|
1114 | } |
---|
1115 | else if (c == 'f' && strcmp(argv[2],"follows") == 0) { |
---|
1116 | int nbytes; |
---|
1117 | if (Tcl_GetInt(interp, argv[3], &nbytes) != TCL_OK) { |
---|
1118 | return TCL_ERROR; |
---|
1119 | } |
---|
1120 | } |
---|
1121 | } |
---|
1122 | else if (c == 'l' && (strcmp(argv[1], "linecontour") == 0)) |
---|
1123 | { |
---|
1124 | //bytes |
---|
1125 | vector<int> indices; |
---|
1126 | if (strcmp(argv[2],"visible") == 0) |
---|
1127 | { |
---|
1128 | |
---|
1129 | bool visible = !(strcmp("true", argv[3])); |
---|
1130 | printf("heightmap linecontour visible %s\n", (visible)?"true":"false"); |
---|
1131 | if (GetIndices(interp, argc-4, argv+4, &indices) != TCL_OK) |
---|
1132 | { |
---|
1133 | return TCL_ERROR; |
---|
1134 | } |
---|
1135 | |
---|
1136 | for (int i = 0; i < indices.size(); ++i) |
---|
1137 | { |
---|
1138 | printf("heightmap index %d\n"); |
---|
1139 | if ((indices[i] < g_heightMap.size()) && (g_heightMap[indices[i]] != NULL)) |
---|
1140 | { |
---|
1141 | printf("heightmap index %d visible applied\n"); |
---|
1142 | g_heightMap[indices[i]]->setLineContourVisible(visible); |
---|
1143 | } |
---|
1144 | } |
---|
1145 | return TCL_OK; |
---|
1146 | } |
---|
1147 | else if (strcmp(argv[2],"color") == 0) |
---|
1148 | { |
---|
1149 | double r, g, b; |
---|
1150 | if ((Tcl_GetDouble(interp, argv[3], &r) == TCL_OK) && |
---|
1151 | (Tcl_GetDouble(interp, argv[4], &g) == TCL_OK) && |
---|
1152 | (Tcl_GetDouble(interp, argv[5], &b) == TCL_OK)) { |
---|
1153 | r = r / 255.0; |
---|
1154 | g = g / 255.0; |
---|
1155 | b = b / 255.0; |
---|
1156 | } |
---|
1157 | else |
---|
1158 | { |
---|
1159 | return TCL_ERROR; |
---|
1160 | } |
---|
1161 | |
---|
1162 | vector<int> indices; |
---|
1163 | if (GetIndices(interp, argc-6, argv+6, &indices) != TCL_OK) |
---|
1164 | { |
---|
1165 | return TCL_ERROR; |
---|
1166 | } |
---|
1167 | for (int i = 0; i < indices.size(); ++i) |
---|
1168 | { |
---|
1169 | if ((indices[i] < g_heightMap.size()) && (g_heightMap[indices[i]] != NULL)) |
---|
1170 | { |
---|
1171 | g_heightMap[indices[i]]->setLineContourColor(r, g, b); |
---|
1172 | } |
---|
1173 | } |
---|
1174 | |
---|
1175 | return TCL_OK; |
---|
1176 | } |
---|
1177 | } |
---|
1178 | else if (c == 't' && (strcmp(argv[1], "transfunc") == 0)) |
---|
1179 | { |
---|
1180 | TransferFunction *tf = get_transfunc((char*)argv[2]); |
---|
1181 | if (tf == NULL) { |
---|
1182 | Tcl_AppendResult(interp, "transfer function \"", argv[3], |
---|
1183 | "\" is not defined", (char*)NULL); |
---|
1184 | return TCL_ERROR; |
---|
1185 | } |
---|
1186 | |
---|
1187 | vector<int> indices; |
---|
1188 | if (GetVolumeIndices(interp, argc - 3, argv + 3, &indices) != TCL_OK) |
---|
1189 | { |
---|
1190 | for (int i = 0; i < indices.size(); ++i) |
---|
1191 | { |
---|
1192 | if ((indices[i] < g_heightMap.size()) && (g_heightMap[indices[i]] != NULL)) |
---|
1193 | { |
---|
1194 | g_heightMap[indices[i]]->setColorMap(tf); |
---|
1195 | } |
---|
1196 | } |
---|
1197 | } |
---|
1198 | return TCL_OK; |
---|
1199 | } |
---|
1200 | |
---|
1201 | Tcl_AppendResult(interp, "bad option \"", argv[1], |
---|
1202 | "\": should be data, outline, shading, or state", (char*)NULL); |
---|
1203 | return TCL_ERROR; |
---|
1204 | } |
---|
1205 | |
---|
1206 | int GridCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])) |
---|
1207 | { |
---|
1208 | char c = *argv[1]; |
---|
1209 | if (c == 'v' && strcmp(argv[1],"visible") == 0) |
---|
1210 | { |
---|
1211 | if (strcmp(argv[2],"true") == 0) |
---|
1212 | { |
---|
1213 | g_grid->setVisible(true); |
---|
1214 | return TCL_OK; |
---|
1215 | } |
---|
1216 | else if (strcmp(argv[2],"false") == 0) |
---|
1217 | { |
---|
1218 | g_grid->setVisible(false); |
---|
1219 | return TCL_OK; |
---|
1220 | } |
---|
1221 | } |
---|
1222 | else if (c == 'l' && strcmp(argv[1],"linecount") == 0) |
---|
1223 | { |
---|
1224 | int x, y, z; |
---|
1225 | |
---|
1226 | if ((Tcl_GetInt(interp, argv[2], &x) == TCL_OK) && |
---|
1227 | (Tcl_GetInt(interp, argv[3], &y) == TCL_OK) && |
---|
1228 | (Tcl_GetInt(interp, argv[4], &z) == TCL_OK)) { |
---|
1229 | |
---|
1230 | if (g_grid) g_grid->setGridLineCount(x, y, z); |
---|
1231 | |
---|
1232 | return TCL_OK; |
---|
1233 | } |
---|
1234 | } |
---|
1235 | else if (c == 'a' && strcmp(argv[1],"axiscolor") == 0) |
---|
1236 | { |
---|
1237 | int r, g, b; |
---|
1238 | if ((Tcl_GetInt(interp, argv[2], &r) == TCL_OK) && |
---|
1239 | (Tcl_GetInt(interp, argv[3], &g) == TCL_OK) && |
---|
1240 | (Tcl_GetInt(interp, argv[4], &b) == TCL_OK)) { |
---|
1241 | |
---|
1242 | if (g_grid) g_grid->setAxisColor(r / 255.0f, g / 255.0f, b / 255.0f); |
---|
1243 | return TCL_OK; |
---|
1244 | } |
---|
1245 | } |
---|
1246 | else if (c == 'l' && strcmp(argv[1],"linecolor") == 0) |
---|
1247 | { |
---|
1248 | int r, g, b; |
---|
1249 | if ((Tcl_GetInt(interp, argv[2], &r) == TCL_OK) && |
---|
1250 | (Tcl_GetInt(interp, argv[3], &g) == TCL_OK) && |
---|
1251 | (Tcl_GetInt(interp, argv[4], &b) == TCL_OK)) { |
---|
1252 | |
---|
1253 | if (g_grid) g_grid->setGridLineColor(r / 255.0f, g / 255.0f, b / 255.0f); |
---|
1254 | return TCL_OK; |
---|
1255 | } |
---|
1256 | } |
---|
1257 | else if (c == 'm') |
---|
1258 | { |
---|
1259 | if (strcmp(argv[1],"minmax") == 0) |
---|
1260 | { |
---|
1261 | double x1, y1, z1, x2, y2, z2; |
---|
1262 | if ((Tcl_GetDouble(interp, argv[2], &x1) == TCL_OK) && |
---|
1263 | (Tcl_GetDouble(interp, argv[3], &y1) == TCL_OK) && |
---|
1264 | (Tcl_GetDouble(interp, argv[4], &z1) == TCL_OK) && |
---|
1265 | (Tcl_GetDouble(interp, argv[5], &x2) == TCL_OK) && |
---|
1266 | (Tcl_GetDouble(interp, argv[6], &y2) == TCL_OK) && |
---|
1267 | (Tcl_GetDouble(interp, argv[7], &z2) == TCL_OK)) { |
---|
1268 | |
---|
1269 | if (g_grid) g_grid->setMinMax(Vector3(x1, y1, z1), Vector3(x2, y2, z2)); |
---|
1270 | |
---|
1271 | return TCL_OK; |
---|
1272 | } |
---|
1273 | } |
---|
1274 | } |
---|
1275 | else if (c == 'a' && strcmp(argv[1],"axisname") == 0) |
---|
1276 | { |
---|
1277 | int axisID = 0; |
---|
1278 | if (!strcmp(argv[2], "x")) axisID = 0; |
---|
1279 | if (!strcmp(argv[2], "y")) axisID = 1; |
---|
1280 | if (!strcmp(argv[2], "z")) axisID = 2; |
---|
1281 | |
---|
1282 | if (g_grid) g_grid->setAxisName(axisID, argv[3]); |
---|
1283 | return TCL_OK; |
---|
1284 | } |
---|
1285 | |
---|
1286 | Tcl_AppendResult(interp, "bad option \"", argv[1], |
---|
1287 | "\": should be data, outline, shading, or state", (char*)NULL); |
---|
1288 | return TCL_ERROR; |
---|
1289 | } |
---|
1290 | |
---|
1291 | |
---|
1292 | int AxisCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])) |
---|
1293 | { |
---|
1294 | if (argc < 2) { |
---|
1295 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
1296 | " option arg arg...\"", (char*)NULL); |
---|
1297 | return TCL_ERROR; |
---|
1298 | } |
---|
1299 | |
---|
1300 | char c = *argv[1]; |
---|
1301 | if (c == 'v' && strcmp(argv[1],"visible") == 0) |
---|
1302 | { |
---|
1303 | if (strcmp(argv[2],"true") == 0) |
---|
1304 | { |
---|
1305 | axis_on = true; |
---|
1306 | } |
---|
1307 | else if (strcmp(argv[2],"false") == 0) |
---|
1308 | { |
---|
1309 | axis_on = false; |
---|
1310 | } |
---|
1311 | |
---|
1312 | return TCL_OK; |
---|
1313 | } |
---|
1314 | |
---|
1315 | Tcl_AppendResult(interp, "bad option \"", argv[1], |
---|
1316 | "\": should be data, outline, shading, or state", (char*)NULL); |
---|
1317 | return TCL_ERROR; |
---|
1318 | } |
---|
1319 | |
---|
1320 | |
---|
1321 | /* |
---|
1322 | * ---------------------------------------------------------------------- |
---|
1323 | * FUNCTION: GetVolumeIndices() |
---|
1324 | * |
---|
1325 | * Used internally to decode a series of volume index values and |
---|
1326 | * store then in the specified vector. If there are no volume index |
---|
1327 | * arguments, this means "all volumes" to most commands, so all |
---|
1328 | * active volume indices are stored in the vector. |
---|
1329 | * |
---|
1330 | * Updates pushes index values into the vector. Returns TCL_OK or |
---|
1331 | * TCL_ERROR to indicate an error. |
---|
1332 | * ---------------------------------------------------------------------- |
---|
1333 | */ |
---|
1334 | static int |
---|
1335 | GetVolumeIndices(Tcl_Interp *interp, int argc, CONST84 char *argv[], |
---|
1336 | vector<int>* vectorPtr) |
---|
1337 | { |
---|
1338 | if (argc == 0) { |
---|
1339 | for (int n=0; n < volume.size(); n++) { |
---|
1340 | if (volume[n] != NULL) { |
---|
1341 | vectorPtr->push_back(n); |
---|
1342 | } |
---|
1343 | } |
---|
1344 | } else { |
---|
1345 | int ivol; |
---|
1346 | for (int n=0; n < argc; n++) { |
---|
1347 | if (Tcl_GetInt(interp, argv[n], &ivol) != TCL_OK) { |
---|
1348 | return TCL_ERROR; |
---|
1349 | } |
---|
1350 | if (ivol < 0 || ivol >= volume.size()) { |
---|
1351 | Tcl_AppendResult(interp, "bad volume index \"", argv[n], |
---|
1352 | "\"", (char*)NULL); |
---|
1353 | return TCL_ERROR; |
---|
1354 | } |
---|
1355 | if (volume[ivol] != NULL) { |
---|
1356 | vectorPtr->push_back(ivol); |
---|
1357 | } |
---|
1358 | } |
---|
1359 | } |
---|
1360 | return TCL_OK; |
---|
1361 | } |
---|
1362 | |
---|
1363 | |
---|
1364 | static int |
---|
1365 | GetIndices(Tcl_Interp *interp, int argc, CONST84 char *argv[], |
---|
1366 | vector<int>* vectorPtr) |
---|
1367 | { |
---|
1368 | int ivol; |
---|
1369 | for (int n=0; n < argc; n++) |
---|
1370 | { |
---|
1371 | if (Tcl_GetInt(interp, argv[n], &ivol) != TCL_OK) { |
---|
1372 | return TCL_ERROR; |
---|
1373 | } |
---|
1374 | vectorPtr->push_back(ivol); |
---|
1375 | } |
---|
1376 | return TCL_OK; |
---|
1377 | } |
---|
1378 | |
---|
1379 | /* |
---|
1380 | * ---------------------------------------------------------------------- |
---|
1381 | * FUNCTION: GetAxis() |
---|
1382 | * |
---|
1383 | * Used internally to decode an axis value from a string ("x", "y", |
---|
1384 | * or "z") to its index (0, 1, or 2). Returns TCL_OK if successful, |
---|
1385 | * along with a value in valPtr. Otherwise, it returns TCL_ERROR |
---|
1386 | * and an error message in the interpreter. |
---|
1387 | * ---------------------------------------------------------------------- |
---|
1388 | */ |
---|
1389 | static int |
---|
1390 | GetAxis(Tcl_Interp *interp, char *str, int *valPtr) |
---|
1391 | { |
---|
1392 | if (strcmp(str,"x") == 0) { |
---|
1393 | *valPtr = 0; |
---|
1394 | return TCL_OK; |
---|
1395 | } |
---|
1396 | else if (strcmp(str,"y") == 0) { |
---|
1397 | *valPtr = 1; |
---|
1398 | return TCL_OK; |
---|
1399 | } |
---|
1400 | else if (strcmp(str,"z") == 0) { |
---|
1401 | *valPtr = 2; |
---|
1402 | return TCL_OK; |
---|
1403 | } |
---|
1404 | Tcl_AppendResult(interp, "bad axis \"", str, |
---|
1405 | "\": should be x, y, or z", (char*)NULL); |
---|
1406 | return TCL_ERROR; |
---|
1407 | } |
---|
1408 | |
---|
1409 | /* |
---|
1410 | * ---------------------------------------------------------------------- |
---|
1411 | * FUNCTION: GetColor() |
---|
1412 | * |
---|
1413 | * Used internally to decode a color value from a string ("R G B") |
---|
1414 | * as a list of three numbers 0-1. Returns TCL_OK if successful, |
---|
1415 | * along with RGB values in valPtr. Otherwise, it returns TCL_ERROR |
---|
1416 | * and an error message in the interpreter. |
---|
1417 | * ---------------------------------------------------------------------- |
---|
1418 | */ |
---|
1419 | static int |
---|
1420 | GetColor(Tcl_Interp *interp, char *str, float *rgbPtr) |
---|
1421 | { |
---|
1422 | int rgbc; |
---|
1423 | char **rgbv; |
---|
1424 | if (Tcl_SplitList(interp, str, &rgbc, (const char***)&rgbv) != TCL_OK) { |
---|
1425 | return TCL_ERROR; |
---|
1426 | } |
---|
1427 | if (rgbc != 3) { |
---|
1428 | Tcl_AppendResult(interp, "bad color \"", str, |
---|
1429 | "\": should be {R G B} as double values 0-1", (char*)NULL); |
---|
1430 | return TCL_ERROR; |
---|
1431 | } |
---|
1432 | |
---|
1433 | double rval, gval, bval; |
---|
1434 | if (Tcl_GetDouble(interp, rgbv[0], &rval) != TCL_OK) { |
---|
1435 | Tcl_Free((char*)rgbv); |
---|
1436 | return TCL_ERROR; |
---|
1437 | } |
---|
1438 | if (Tcl_GetDouble(interp, rgbv[1], &gval) != TCL_OK) { |
---|
1439 | Tcl_Free((char*)rgbv); |
---|
1440 | return TCL_ERROR; |
---|
1441 | } |
---|
1442 | if (Tcl_GetDouble(interp, rgbv[2], &bval) != TCL_OK) { |
---|
1443 | Tcl_Free((char*)rgbv); |
---|
1444 | return TCL_ERROR; |
---|
1445 | } |
---|
1446 | Tcl_Free((char*)rgbv); |
---|
1447 | |
---|
1448 | rgbPtr[0] = (float)rval; |
---|
1449 | rgbPtr[1] = (float)gval; |
---|
1450 | rgbPtr[2] = (float)bval; |
---|
1451 | |
---|
1452 | return TCL_OK; |
---|
1453 | } |
---|
1454 | |
---|
1455 | |
---|
1456 | static int |
---|
1457 | PlaneNewCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])) |
---|
1458 | { |
---|
1459 | fprintf(stderr, "load plane for 2D visualization command\n"); |
---|
1460 | |
---|
1461 | int index, w, h; |
---|
1462 | |
---|
1463 | if (argc != 4) { |
---|
1464 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
1465 | " plane_index w h \"", (char*)NULL); |
---|
1466 | return TCL_ERROR; |
---|
1467 | } |
---|
1468 | if (Tcl_GetInt(interp, argv[1], &index) != TCL_OK) { |
---|
1469 | return TCL_ERROR; |
---|
1470 | } |
---|
1471 | if (Tcl_GetInt(interp, argv[2], &w) != TCL_OK) { |
---|
1472 | return TCL_ERROR; |
---|
1473 | } |
---|
1474 | if (Tcl_GetInt(interp, argv[3], &h) != TCL_OK) { |
---|
1475 | return TCL_ERROR; |
---|
1476 | } |
---|
1477 | |
---|
1478 | //Now read w*h*4 bytes. The server expects the plane to be a stream of floats |
---|
1479 | char* tmp = new char[int(w*h*sizeof(float))]; |
---|
1480 | bzero(tmp, w*h*4); |
---|
1481 | int status = read(0, tmp, w*h*sizeof(float)); |
---|
1482 | if (status <= 0){ |
---|
1483 | exit(0); |
---|
1484 | } |
---|
1485 | |
---|
1486 | plane[index] = new Texture2D(w, h, GL_FLOAT, GL_LINEAR, 1, (float*)tmp); |
---|
1487 | |
---|
1488 | delete[] tmp; |
---|
1489 | return TCL_OK; |
---|
1490 | } |
---|
1491 | |
---|
1492 | |
---|
1493 | static |
---|
1494 | int PlaneLinkCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])) |
---|
1495 | { |
---|
1496 | fprintf(stderr, "link the plane to the 2D renderer command\n"); |
---|
1497 | |
---|
1498 | int plane_index, tf_index; |
---|
1499 | |
---|
1500 | if (argc != 3) { |
---|
1501 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
1502 | " plane_index tf_index \"", (char*)NULL); |
---|
1503 | return TCL_ERROR; |
---|
1504 | } |
---|
1505 | if (Tcl_GetInt(interp, argv[1], &plane_index) != TCL_OK) { |
---|
1506 | return TCL_ERROR; |
---|
1507 | } |
---|
1508 | if (Tcl_GetInt(interp, argv[2], &tf_index) != TCL_OK) { |
---|
1509 | return TCL_ERROR; |
---|
1510 | } |
---|
1511 | |
---|
1512 | //plane_render->add_plane(plane[plane_index], tf[tf_index]); |
---|
1513 | |
---|
1514 | return TCL_OK; |
---|
1515 | } |
---|
1516 | |
---|
1517 | //Enable a 2D plane for render |
---|
1518 | //The plane_index is the index mantained in the 2D plane renderer |
---|
1519 | static |
---|
1520 | int PlaneEnableCmd _ANSI_ARGS_((ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])) |
---|
1521 | { |
---|
1522 | fprintf(stderr, "enable a plane so the 2D renderer can render it command\n"); |
---|
1523 | |
---|
1524 | int plane_index, mode; |
---|
1525 | |
---|
1526 | if (argc != 3) { |
---|
1527 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |
---|
1528 | " plane_index mode \"", (char*)NULL); |
---|
1529 | return TCL_ERROR; |
---|
1530 | } |
---|
1531 | if (Tcl_GetInt(interp, argv[1], &plane_index) != TCL_OK) { |
---|
1532 | return TCL_ERROR; |
---|
1533 | } |
---|
1534 | if (Tcl_GetInt(interp, argv[2], &mode) != TCL_OK) { |
---|
1535 | return TCL_ERROR; |
---|
1536 | } |
---|
1537 | |
---|
1538 | if(mode==0) |
---|
1539 | plane_render->set_active_plane(-1); |
---|
1540 | else |
---|
1541 | plane_render->set_active_plane(plane_index); |
---|
1542 | |
---|
1543 | return TCL_OK; |
---|
1544 | } |
---|
1545 | |
---|
1546 | |
---|
1547 | void initTcl() |
---|
1548 | { |
---|
1549 | interp = Tcl_CreateInterp(); |
---|
1550 | Tcl_MakeSafe(interp); |
---|
1551 | |
---|
1552 | Tcl_DStringInit(&cmdbuffer); |
---|
1553 | |
---|
1554 | // manipulate the viewpoint |
---|
1555 | Tcl_CreateCommand(interp, "camera", CameraCmd, |
---|
1556 | (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); |
---|
1557 | |
---|
1558 | // turn on/off cut planes in x/y/z directions |
---|
1559 | Tcl_CreateCommand(interp, "cutplane", CutplaneCmd, |
---|
1560 | (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); |
---|
1561 | |
---|
1562 | // request the legend for a plot (transfer function) |
---|
1563 | Tcl_CreateCommand(interp, "legend", LegendCmd, |
---|
1564 | (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); |
---|
1565 | |
---|
1566 | // change the size of the screen (size of picture generated) |
---|
1567 | Tcl_CreateCommand(interp, "screen", ScreenCmd, |
---|
1568 | (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); |
---|
1569 | |
---|
1570 | // manipulate transfer functions |
---|
1571 | Tcl_CreateCommand(interp, "transfunc", TransfuncCmd, |
---|
1572 | (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); |
---|
1573 | |
---|
1574 | // set the "up" direction for volumes |
---|
1575 | Tcl_CreateCommand(interp, "up", UpCmd, |
---|
1576 | (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); |
---|
1577 | |
---|
1578 | // manipulate volume data |
---|
1579 | Tcl_CreateCommand(interp, "volume", VolumeCmd, |
---|
1580 | (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); |
---|
1581 | |
---|
1582 | Tcl_CreateCommand(interp, "axis", AxisCmd, |
---|
1583 | (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); |
---|
1584 | |
---|
1585 | Tcl_CreateCommand(interp, "grid", GridCmd, |
---|
1586 | (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); |
---|
1587 | |
---|
1588 | Tcl_CreateCommand(interp, "heightmap", HeightMapCmd, |
---|
1589 | (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); |
---|
1590 | |
---|
1591 | // get screenshot |
---|
1592 | Tcl_CreateCommand(interp, "screenshot", ScreenShotCmd, |
---|
1593 | (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); |
---|
1594 | |
---|
1595 | #ifdef __TEST_CODE__ |
---|
1596 | Tcl_CreateCommand(interp, "test", TestCmd, |
---|
1597 | (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); |
---|
1598 | #endif |
---|
1599 | |
---|
1600 | // create a default transfer function |
---|
1601 | if (Tcl_Eval(interp, def_transfunc) != TCL_OK) { |
---|
1602 | fprintf(stdin, "WARNING: bad default transfer function\n"); |
---|
1603 | fprintf(stdin, Tcl_GetStringResult(interp)); |
---|
1604 | } |
---|
1605 | } |
---|
1606 | |
---|
1607 | void xinetd_listen() |
---|
1608 | { |
---|
1609 | |
---|
1610 | int flags = fcntl(0, F_GETFL, 0); |
---|
1611 | fcntl(0, F_SETFL, flags & ~O_NONBLOCK); |
---|
1612 | |
---|
1613 | int status = TCL_OK; |
---|
1614 | int npass = 0; |
---|
1615 | |
---|
1616 | // |
---|
1617 | // Read and execute as many commands as we can from stdin... |
---|
1618 | // |
---|
1619 | while (status == TCL_OK) { |
---|
1620 | // |
---|
1621 | // Read the next command from the buffer. First time through |
---|
1622 | // we block here and wait if necessary until a command comes in. |
---|
1623 | // |
---|
1624 | // BE CAREFUL: Read only one command, up to a newline. |
---|
1625 | // The "volume data follows" command needs to be able to read |
---|
1626 | // the data immediately following the command, and we shouldn't |
---|
1627 | // consume it here. |
---|
1628 | // |
---|
1629 | while (1) { |
---|
1630 | char c = getchar(); |
---|
1631 | if (c <= 0) { |
---|
1632 | if (npass == 0) { |
---|
1633 | exit(0); // EOF -- we're done! |
---|
1634 | } else { |
---|
1635 | break; |
---|
1636 | } |
---|
1637 | } |
---|
1638 | Tcl_DStringAppend(&cmdbuffer, &c, 1); |
---|
1639 | |
---|
1640 | if (c=='\n' && Tcl_CommandComplete(Tcl_DStringValue(&cmdbuffer))) { |
---|
1641 | break; |
---|
1642 | } |
---|
1643 | } |
---|
1644 | |
---|
1645 | // no command? then we're done for now |
---|
1646 | if (Tcl_DStringLength(&cmdbuffer) == 0) { |
---|
1647 | break; |
---|
1648 | } |
---|
1649 | |
---|
1650 | // back to original flags during command evaluation... |
---|
1651 | fcntl(0, F_SETFL, flags & ~O_NONBLOCK); |
---|
1652 | |
---|
1653 | status = Tcl_Eval(interp, Tcl_DStringValue(&cmdbuffer)); |
---|
1654 | Tcl_DStringSetLength(&cmdbuffer, 0); |
---|
1655 | |
---|
1656 | // non-blocking for next read -- we might not get anything |
---|
1657 | fcntl(0, F_SETFL, flags | O_NONBLOCK); |
---|
1658 | npass++; |
---|
1659 | } |
---|
1660 | fcntl(0, F_SETFL, flags); |
---|
1661 | |
---|
1662 | if (status != TCL_OK) { |
---|
1663 | std::ostringstream errmsg; |
---|
1664 | errmsg << "ERROR: " << Tcl_GetStringResult(interp) << std::endl; |
---|
1665 | write(0, errmsg.str().c_str(), errmsg.str().size()); |
---|
1666 | return; |
---|
1667 | } |
---|
1668 | |
---|
1669 | // |
---|
1670 | // Generate the latest frame and send it back to the client |
---|
1671 | // |
---|
1672 | // INSOO |
---|
1673 | offscreen_buffer_capture(); //enable offscreen render |
---|
1674 | |
---|
1675 | display(); |
---|
1676 | |
---|
1677 | // INSOO |
---|
1678 | #ifdef XINETD |
---|
1679 | read_screen(); |
---|
1680 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); |
---|
1681 | #else |
---|
1682 | display_offscreen_buffer(); //display the final rendering on screen |
---|
1683 | read_screen(); |
---|
1684 | glutSwapBuffers(); |
---|
1685 | #endif |
---|
1686 | |
---|
1687 | #if DO_RLE |
---|
1688 | do_rle(); |
---|
1689 | int sizes[2] = { offsets_size*sizeof(offsets[0]), rle_size }; |
---|
1690 | fprintf(stderr, "Writing %d,%d\n", sizes[0], sizes[1]); fflush(stderr); |
---|
1691 | write(0, &sizes, sizeof(sizes)); |
---|
1692 | write(0, offsets, offsets_size*sizeof(offsets[0])); |
---|
1693 | write(0, rle, rle_size); //unsigned byte |
---|
1694 | #else |
---|
1695 | bmp_write("nv>image -bytes"); |
---|
1696 | #endif |
---|
1697 | } |
---|
1698 | |
---|
1699 | |
---|