1 | |
---|
2 | #include <assert.h> |
---|
3 | #include <stdlib.h> |
---|
4 | #include <stddef.h> |
---|
5 | #include <limits.h> |
---|
6 | #include <tcl.h> |
---|
7 | #include "Switch.h" |
---|
8 | #include <RpField1D.h> |
---|
9 | #include <RpFieldRect3D.h> |
---|
10 | #include <RpFieldPrism3D.h> |
---|
11 | #include <RpOutcome.h> |
---|
12 | #include <RpAVTranslate.h> |
---|
13 | #include "Trace.h" |
---|
14 | #include "TransferFunction.h" |
---|
15 | |
---|
16 | #include "nanovis.h" |
---|
17 | #include "Command.h" |
---|
18 | #include "CmdProc.h" |
---|
19 | #include "Nv.h" |
---|
20 | |
---|
21 | #include "NvLIC.h" |
---|
22 | |
---|
23 | #include "Unirect.h" |
---|
24 | #include "FlowCmd.h" |
---|
25 | |
---|
26 | #define RELPOS 0 |
---|
27 | #define ABSPOS 1 |
---|
28 | |
---|
29 | unsigned int FlowCmd::flags = 0; |
---|
30 | Tcl_HashTable FlowCmd::_flowTable; |
---|
31 | float FlowCmd::_magMin, FlowCmd::_magMax; |
---|
32 | float FlowCmd::_xMin, FlowCmd::_xMax; |
---|
33 | float FlowCmd::_yMin, FlowCmd::_yMax; |
---|
34 | float FlowCmd::_zMin, FlowCmd::_zMax; |
---|
35 | float FlowCmd::_wMin, FlowCmd::_wMax; |
---|
36 | float FlowCmd::_xOrigin, FlowCmd::_yOrigin, FlowCmd::_zOrigin; |
---|
37 | |
---|
38 | static Rappture::SwitchParseProc AxisSwitchProc; |
---|
39 | static Rappture::SwitchCustom axisSwitch = { |
---|
40 | AxisSwitchProc, NULL, 0, |
---|
41 | }; |
---|
42 | |
---|
43 | static Rappture::SwitchParseProc ColorSwitchProc; |
---|
44 | static Rappture::SwitchCustom colorSwitch = { |
---|
45 | ColorSwitchProc, NULL, 0, |
---|
46 | }; |
---|
47 | |
---|
48 | static Rappture::SwitchParseProc PointSwitchProc; |
---|
49 | static Rappture::SwitchCustom pointSwitch = { |
---|
50 | PointSwitchProc, NULL, 0, |
---|
51 | }; |
---|
52 | |
---|
53 | static Rappture::SwitchParseProc PositionSwitchProc; |
---|
54 | static Rappture::SwitchCustom positionSwitch = { |
---|
55 | PositionSwitchProc, NULL, 0, |
---|
56 | }; |
---|
57 | |
---|
58 | static Rappture::SwitchParseProc TransferFunctionSwitchProc; |
---|
59 | static Rappture::SwitchCustom transferFunctionSwitch = { |
---|
60 | TransferFunctionSwitchProc, NULL, 0, |
---|
61 | }; |
---|
62 | |
---|
63 | Rappture::SwitchSpec FlowCmd::_switches[] = { |
---|
64 | {Rappture::SWITCH_BOOLEAN, "-slice", "boolean", |
---|
65 | offsetof(FlowValues, sliceVisible), 0}, |
---|
66 | {Rappture::SWITCH_CUSTOM, "-axis", "axis", |
---|
67 | offsetof(FlowValues, slicePos.axis), 0, 0, &axisSwitch}, |
---|
68 | {Rappture::SWITCH_BOOLEAN, "-hide", "boolean", |
---|
69 | offsetof(FlowValues, isHidden), 0}, |
---|
70 | {Rappture::SWITCH_CUSTOM, "-position", "number", |
---|
71 | offsetof(FlowValues, slicePos), 0, 0, &positionSwitch}, |
---|
72 | {Rappture::SWITCH_CUSTOM, "-transferfunction", "name", |
---|
73 | offsetof(FlowValues, tfPtr), 0, 0, &transferFunctionSwitch}, |
---|
74 | {Rappture::SWITCH_BOOLEAN, "-volume", "boolean", |
---|
75 | offsetof(FlowValues, showVolume), 0}, |
---|
76 | {Rappture::SWITCH_BOOLEAN, "-outline", "boolean", |
---|
77 | offsetof(FlowValues, showOutline), 0}, |
---|
78 | {Rappture::SWITCH_END} |
---|
79 | }; |
---|
80 | |
---|
81 | Rappture::SwitchSpec FlowParticles::_switches[] = { |
---|
82 | {Rappture::SWITCH_CUSTOM, "-axis", "string", |
---|
83 | offsetof(FlowParticlesValues, position.axis), 0, 0, &axisSwitch}, |
---|
84 | {Rappture::SWITCH_CUSTOM, "-color", "{r g b a}", |
---|
85 | offsetof(FlowParticlesValues, color), 0, 0, &colorSwitch}, |
---|
86 | {Rappture::SWITCH_BOOLEAN, "-hide", "boolean", |
---|
87 | offsetof(FlowParticlesValues, isHidden), 0}, |
---|
88 | {Rappture::SWITCH_CUSTOM, "-position", "number", |
---|
89 | offsetof(FlowValues, slicePos), 0, 0, &positionSwitch}, |
---|
90 | {Rappture::SWITCH_END} |
---|
91 | }; |
---|
92 | |
---|
93 | Rappture::SwitchSpec FlowBox::_switches[] = { |
---|
94 | {Rappture::SWITCH_CUSTOM, "-color", "{r g b a}", |
---|
95 | offsetof(FlowBoxValues, color), 0, 0, &colorSwitch}, |
---|
96 | {Rappture::SWITCH_CUSTOM, "-corner1", "{x y z}", |
---|
97 | offsetof(FlowBoxValues, corner1), 0, 0, &pointSwitch}, |
---|
98 | {Rappture::SWITCH_CUSTOM, "-corner2", "{x y z}", |
---|
99 | offsetof(FlowBoxValues, corner2), 0, 0, &pointSwitch}, |
---|
100 | {Rappture::SWITCH_BOOLEAN, "-hide", "boolean", |
---|
101 | offsetof(FlowBoxValues, isHidden), 0}, |
---|
102 | {Rappture::SWITCH_FLOAT, "-linewidth", "number", |
---|
103 | offsetof(FlowBoxValues, lineWidth), 0}, |
---|
104 | {Rappture::SWITCH_END} |
---|
105 | }; |
---|
106 | |
---|
107 | |
---|
108 | static Tcl_ObjCmdProc FlowInstObjCmd; |
---|
109 | static Tcl_CmdDeleteProc FlowInstDeleteProc; |
---|
110 | |
---|
111 | |
---|
112 | FlowParticles::FlowParticles(const char *name, Tcl_HashEntry *hPtr) |
---|
113 | { |
---|
114 | memset(this, 0, sizeof(FlowParticles)); |
---|
115 | _name = name; |
---|
116 | _hashPtr = hPtr; |
---|
117 | _sv.isHidden = false; |
---|
118 | _sv.position.axis = 0; /* X_AXIS */ |
---|
119 | _sv.position.value = 0.0f; |
---|
120 | _sv.position.flags = RELPOS; |
---|
121 | _sv.color.r = _sv.color.b = _sv.color.g = _sv.color.a = 1.0f; |
---|
122 | _rendererPtr = new NvParticleRenderer(NMESH, NMESH, |
---|
123 | /* Global nVidia Cg context */g_context); |
---|
124 | } |
---|
125 | |
---|
126 | void |
---|
127 | FlowParticles::Render(void) |
---|
128 | { |
---|
129 | fprintf(stderr, "rendering particles, position=%g\n", |
---|
130 | FlowCmd::GetPosition(&_sv.position)); |
---|
131 | _rendererPtr->setPos(FlowCmd::GetPosition(&_sv.position)); |
---|
132 | _rendererPtr->setAxis(_sv.position.axis); |
---|
133 | assert(_rendererPtr->isActivated()); |
---|
134 | _rendererPtr->render(); |
---|
135 | } |
---|
136 | |
---|
137 | void |
---|
138 | FlowParticles::Configure(void) |
---|
139 | { |
---|
140 | _rendererPtr->setPos(_sv.position.value); |
---|
141 | _rendererPtr->setColor(Vector4(_sv.color.r, _sv.color.g, _sv.color.b, |
---|
142 | _sv.color.a)); |
---|
143 | _rendererPtr->setAxis(_sv.position.axis); |
---|
144 | if ((_sv.isHidden) && (_rendererPtr->isActivated())) { |
---|
145 | _rendererPtr->deactivate(); |
---|
146 | } else if ((!_sv.isHidden) && (!_rendererPtr->isActivated())) { |
---|
147 | _rendererPtr->activate(); |
---|
148 | } |
---|
149 | } |
---|
150 | |
---|
151 | FlowBox::FlowBox(const char *name, Tcl_HashEntry *hPtr) |
---|
152 | { |
---|
153 | _name = name; |
---|
154 | _hashPtr = hPtr; |
---|
155 | _sv.isHidden = false; |
---|
156 | _sv.corner1.x = 0.0f; |
---|
157 | _sv.corner1.y = 0.0f; |
---|
158 | _sv.corner1.z = 0.0f; |
---|
159 | _sv.corner2.x = 1.0f; |
---|
160 | _sv.corner2.y = 1.0f; |
---|
161 | _sv.corner2.z = 1.0f; |
---|
162 | _sv.lineWidth = 1.2f; |
---|
163 | _sv.color.r = _sv.color.b = _sv.color.g = _sv.color.a = 1.0f; |
---|
164 | |
---|
165 | } |
---|
166 | |
---|
167 | void |
---|
168 | FlowBox::Render(Volume *volPtr) |
---|
169 | { |
---|
170 | if ((_sv.corner1.x == _sv.corner2.x) || |
---|
171 | (_sv.corner1.y == _sv.corner2.y) || |
---|
172 | (_sv.corner1.z == _sv.corner2.z)) { |
---|
173 | return; |
---|
174 | } |
---|
175 | glColor4d(_sv.color.r, _sv.color.g, _sv.color.b, _sv.color.a); |
---|
176 | |
---|
177 | glPushMatrix(); |
---|
178 | |
---|
179 | glEnable(GL_DEPTH_TEST); |
---|
180 | glDisable(GL_TEXTURE_2D); |
---|
181 | glEnable(GL_BLEND); |
---|
182 | |
---|
183 | glPushMatrix(); |
---|
184 | Vector3 *originPtr = volPtr->get_location(); |
---|
185 | glTranslatef(originPtr->x, originPtr->y, originPtr->z); |
---|
186 | |
---|
187 | double sx, sy, sz; |
---|
188 | sx = 1.0; |
---|
189 | sy = volPtr->height / (double)volPtr->width; |
---|
190 | sz = volPtr->depth / (double)volPtr->width; |
---|
191 | glScaled(sx, sy, sz); |
---|
192 | |
---|
193 | Vector3 min, max; |
---|
194 | |
---|
195 | min = volPtr->getPhysicalBBoxMin(); |
---|
196 | max = volPtr->getPhysicalBBoxMax(); |
---|
197 | |
---|
198 | float x0, y0, z0, x1, y1, z1; |
---|
199 | x0 = (_sv.corner1.x - min.x) / (max.x - min.x); |
---|
200 | y0 = (_sv.corner1.y - min.y) / (max.y - min.y); |
---|
201 | z0 = (_sv.corner1.z - min.z) / (max.z - min.z); |
---|
202 | x1 = (_sv.corner2.x - min.x) / (max.x - min.x); |
---|
203 | y1 = (_sv.corner2.y - min.y) / (max.y - min.y); |
---|
204 | z1 = (_sv.corner2.z - min.z) / (max.z - min.z); |
---|
205 | |
---|
206 | glLineWidth(_sv.lineWidth); |
---|
207 | glBegin(GL_LINE_LOOP); |
---|
208 | { |
---|
209 | glVertex3d(x0, y0, z0); |
---|
210 | glVertex3d(x1, y0, z0); |
---|
211 | glVertex3d(x1, y1, z0); |
---|
212 | glVertex3d(x0, y1, z0); |
---|
213 | } |
---|
214 | glEnd(); |
---|
215 | glBegin(GL_LINE_LOOP); |
---|
216 | { |
---|
217 | glVertex3d(x0, y0, z1); |
---|
218 | glVertex3d(x1, y0, z1); |
---|
219 | glVertex3d(x1, y1, z1); |
---|
220 | glVertex3d(x0, y1, z1); |
---|
221 | } |
---|
222 | glEnd(); |
---|
223 | |
---|
224 | glBegin(GL_LINE_LOOP); |
---|
225 | { |
---|
226 | glVertex3d(x0, y0, z0); |
---|
227 | glVertex3d(x0, y0, z1); |
---|
228 | glVertex3d(x0, y1, z1); |
---|
229 | glVertex3d(x0, y1, z0); |
---|
230 | } |
---|
231 | glEnd(); |
---|
232 | |
---|
233 | glBegin(GL_LINE_LOOP); |
---|
234 | { |
---|
235 | glVertex3d(x1, y0, z0); |
---|
236 | glVertex3d(x1, y0, z1); |
---|
237 | glVertex3d(x1, y1, z1); |
---|
238 | glVertex3d(x1, y1, z0); |
---|
239 | } |
---|
240 | glEnd(); |
---|
241 | |
---|
242 | glPopMatrix(); |
---|
243 | assert(CheckGL(AT)); |
---|
244 | glPopMatrix(); |
---|
245 | assert(CheckGL(AT)); |
---|
246 | |
---|
247 | glDisable(GL_DEPTH_TEST); |
---|
248 | glDisable(GL_BLEND); |
---|
249 | glEnable(GL_TEXTURE_2D); |
---|
250 | } |
---|
251 | |
---|
252 | |
---|
253 | FlowCmd::FlowCmd(Tcl_Interp *interp, const char *name, Tcl_HashEntry *hPtr) |
---|
254 | { |
---|
255 | memset(this, 0, sizeof(FlowCmd)); |
---|
256 | _name = name; |
---|
257 | _interp = interp; |
---|
258 | _hashPtr = hPtr; |
---|
259 | _volIndex = -1; /* Indicates that no volume slot has |
---|
260 | * been allocated for this vector. */ |
---|
261 | _volPtr = NULL; |
---|
262 | _cmdToken = Tcl_CreateObjCommand(interp, (char *)_name, |
---|
263 | (Tcl_ObjCmdProc *)FlowInstObjCmd, this, FlowInstDeleteProc); |
---|
264 | Tcl_InitHashTable(&_particlesTable, TCL_STRING_KEYS); |
---|
265 | Tcl_InitHashTable(&_boxTable, TCL_STRING_KEYS); |
---|
266 | } |
---|
267 | |
---|
268 | FlowCmd::~FlowCmd(void) |
---|
269 | { |
---|
270 | Rappture::FreeSwitches(_switches, &_sv, 0); |
---|
271 | if (_hashPtr != NULL) { |
---|
272 | Tcl_DeleteHashEntry(_hashPtr); |
---|
273 | } |
---|
274 | if (_fieldPtr != NULL) { |
---|
275 | delete _fieldPtr; |
---|
276 | } |
---|
277 | if (_dataPtr != NULL) { |
---|
278 | delete _dataPtr; |
---|
279 | } |
---|
280 | if (_volPtr != NULL) { |
---|
281 | delete _volPtr; |
---|
282 | _volPtr = NULL; |
---|
283 | NanoVis::volume[_volIndex] = NULL; |
---|
284 | NanoVis::vol_renderer->remove_volume(_volIndex); |
---|
285 | } |
---|
286 | |
---|
287 | FlowBox *boxPtr; |
---|
288 | FlowBoxIterator boxIter; |
---|
289 | for (boxPtr = FirstBox(&boxIter); boxPtr != NULL; |
---|
290 | boxPtr = NextBox(&boxIter)) { |
---|
291 | boxPtr->disconnect(); |
---|
292 | delete boxPtr; |
---|
293 | } |
---|
294 | FlowParticles *particlesPtr; |
---|
295 | FlowParticlesIterator partIter; |
---|
296 | for (particlesPtr = FirstParticles(&partIter); particlesPtr != NULL; |
---|
297 | particlesPtr = NextParticles(&partIter)) { |
---|
298 | particlesPtr->disconnect(); |
---|
299 | delete particlesPtr; |
---|
300 | } |
---|
301 | Tcl_DeleteHashTable(&_particlesTable); |
---|
302 | Tcl_DeleteHashTable(&_boxTable); |
---|
303 | } |
---|
304 | |
---|
305 | void |
---|
306 | FlowCmd::ResetParticles(void) |
---|
307 | { |
---|
308 | FlowParticlesIterator iter; |
---|
309 | FlowParticles *particlesPtr; |
---|
310 | for (particlesPtr = FirstParticles(&iter); particlesPtr != NULL; |
---|
311 | particlesPtr = NextParticles(&iter)) { |
---|
312 | particlesPtr->Reset(); |
---|
313 | } |
---|
314 | } |
---|
315 | |
---|
316 | void |
---|
317 | FlowCmd::Advect(void) |
---|
318 | { |
---|
319 | NvVectorField *fieldPtr; |
---|
320 | fieldPtr = VectorField(); |
---|
321 | if (!fieldPtr->isActivated()) { |
---|
322 | fieldPtr->activate(); |
---|
323 | } |
---|
324 | FlowParticlesIterator iter; |
---|
325 | FlowParticles *particlesPtr; |
---|
326 | for (particlesPtr = FirstParticles(&iter); particlesPtr != NULL; |
---|
327 | particlesPtr = NextParticles(&iter)) { |
---|
328 | if (particlesPtr->visible()) { |
---|
329 | particlesPtr->Advect(); |
---|
330 | } |
---|
331 | } |
---|
332 | } |
---|
333 | |
---|
334 | void |
---|
335 | FlowCmd::Render(void) |
---|
336 | { |
---|
337 | if (!_fieldPtr->isActivated()) { |
---|
338 | _fieldPtr->activate(); |
---|
339 | } |
---|
340 | _fieldPtr->render(); |
---|
341 | FlowParticlesIterator iter; |
---|
342 | FlowParticles *particlesPtr; |
---|
343 | for (particlesPtr = FirstParticles(&iter); particlesPtr != NULL; |
---|
344 | particlesPtr = NextParticles(&iter)) { |
---|
345 | if (particlesPtr->visible()) { |
---|
346 | particlesPtr->Render(); |
---|
347 | } |
---|
348 | } |
---|
349 | RenderBoxes(); |
---|
350 | } |
---|
351 | |
---|
352 | void |
---|
353 | FlowCmd::Init(void) |
---|
354 | { |
---|
355 | Tcl_InitHashTable(&_flowTable, TCL_STRING_KEYS); |
---|
356 | } |
---|
357 | |
---|
358 | FlowCmd * |
---|
359 | FlowCmd::FirstFlow(FlowIterator *iterPtr) |
---|
360 | { |
---|
361 | iterPtr->hashPtr = Tcl_FirstHashEntry(&_flowTable, &iterPtr->hashSearch); |
---|
362 | if (iterPtr->hashPtr == NULL) { |
---|
363 | return NULL; |
---|
364 | } |
---|
365 | return (FlowCmd *)Tcl_GetHashValue(iterPtr->hashPtr); |
---|
366 | } |
---|
367 | |
---|
368 | FlowCmd * |
---|
369 | FlowCmd::NextFlow(FlowIterator *iterPtr) |
---|
370 | { |
---|
371 | if (iterPtr->hashPtr == NULL) { |
---|
372 | return NULL; |
---|
373 | } |
---|
374 | iterPtr->hashPtr = Tcl_NextHashEntry(&iterPtr->hashSearch); |
---|
375 | if (iterPtr->hashPtr == NULL) { |
---|
376 | return NULL; |
---|
377 | } |
---|
378 | return (FlowCmd *)Tcl_GetHashValue(iterPtr->hashPtr); |
---|
379 | } |
---|
380 | |
---|
381 | |
---|
382 | int |
---|
383 | FlowCmd::GetFlow(Tcl_Interp *interp, Tcl_Obj *objPtr, FlowCmd **flowPtrPtr) |
---|
384 | { |
---|
385 | Tcl_HashEntry *hPtr; |
---|
386 | hPtr = Tcl_FindHashEntry(&_flowTable, Tcl_GetString(objPtr)); |
---|
387 | if (hPtr == NULL) { |
---|
388 | if (interp != NULL) { |
---|
389 | Tcl_AppendResult(interp, "can't find a flow \"", |
---|
390 | Tcl_GetString(objPtr), "\"", (char *)NULL); |
---|
391 | } |
---|
392 | return TCL_ERROR; |
---|
393 | } |
---|
394 | *flowPtrPtr = (FlowCmd *)Tcl_GetHashValue(hPtr); |
---|
395 | return TCL_OK; |
---|
396 | } |
---|
397 | |
---|
398 | int |
---|
399 | FlowCmd::CreateFlow(Tcl_Interp *interp, Tcl_Obj *objPtr) |
---|
400 | { |
---|
401 | Tcl_HashEntry *hPtr; |
---|
402 | int isNew; |
---|
403 | const char *name; |
---|
404 | name = Tcl_GetString(objPtr); |
---|
405 | hPtr = Tcl_CreateHashEntry(&_flowTable, name, &isNew); |
---|
406 | if (!isNew) { |
---|
407 | Tcl_AppendResult(interp, "flow \"", name, "\" already exists.", |
---|
408 | (char *)NULL); |
---|
409 | return TCL_ERROR; |
---|
410 | } |
---|
411 | Tcl_CmdInfo cmdInfo; |
---|
412 | if (Tcl_GetCommandInfo(interp, name, &cmdInfo)) { |
---|
413 | Tcl_AppendResult(interp, "an another command \"", name, |
---|
414 | "\" already exists.", (char *)NULL); |
---|
415 | return TCL_ERROR; |
---|
416 | } |
---|
417 | FlowCmd *flowPtr; |
---|
418 | name = Tcl_GetHashKey(&_flowTable, hPtr); |
---|
419 | flowPtr = new FlowCmd(interp, name, hPtr); |
---|
420 | if (flowPtr == NULL) { |
---|
421 | Tcl_AppendResult(interp, "can't allocate a flow object \"", name, |
---|
422 | "\"", (char *)NULL); |
---|
423 | return TCL_ERROR; |
---|
424 | } |
---|
425 | Tcl_SetHashValue(hPtr, flowPtr); |
---|
426 | EventuallyRedraw(MAP_PENDING); |
---|
427 | return TCL_OK; |
---|
428 | } |
---|
429 | |
---|
430 | void |
---|
431 | FlowCmd::DeleteFlows(Tcl_Interp *interp) |
---|
432 | { |
---|
433 | FlowCmd *flowPtr; |
---|
434 | FlowIterator iter; |
---|
435 | for (flowPtr = FirstFlow(&iter); flowPtr != NULL; |
---|
436 | flowPtr = NextFlow(&iter)) { |
---|
437 | flowPtr->disconnect(); /* Don't disrupt the hash walk */ |
---|
438 | Tcl_DeleteCommand(interp, flowPtr->name()); |
---|
439 | } |
---|
440 | Tcl_DeleteHashTable(&_flowTable); |
---|
441 | } |
---|
442 | |
---|
443 | bool |
---|
444 | FlowCmd::MapFlows(void) |
---|
445 | { |
---|
446 | flags &= ~FlowCmd::MAP_PENDING; |
---|
447 | |
---|
448 | _xMin = _yMin = _zMin = _wMin = _magMin = FLT_MAX; |
---|
449 | _xMax = _yMax = _zMax = _wMax = _magMax = -FLT_MAX; |
---|
450 | |
---|
451 | /* |
---|
452 | * Step 1. Get the overall min and max magnitudes of all the |
---|
453 | * flow vectors. |
---|
454 | */ |
---|
455 | FlowCmd *flowPtr; |
---|
456 | FlowIterator iter; |
---|
457 | for (flowPtr = FirstFlow(&iter); flowPtr != NULL; |
---|
458 | flowPtr = NextFlow(&iter)) { |
---|
459 | double minMag, maxMag; |
---|
460 | if (!flowPtr->isDataLoaded()) { |
---|
461 | continue; |
---|
462 | } |
---|
463 | flowPtr->GetMagRange(minMag, maxMag); |
---|
464 | if (minMag < _magMin) { |
---|
465 | _magMin = minMag; |
---|
466 | } |
---|
467 | if (maxMag > _magMax) { |
---|
468 | _magMax = maxMag; |
---|
469 | } |
---|
470 | Rappture::Unirect3d *dataPtr; |
---|
471 | dataPtr = flowPtr->GetData(); |
---|
472 | if (dataPtr->xMin() < _xMin) { |
---|
473 | _xMin = dataPtr->xMin(); |
---|
474 | } |
---|
475 | if (dataPtr->yMin() < _yMin) { |
---|
476 | _yMin = dataPtr->yMin(); |
---|
477 | } |
---|
478 | if (dataPtr->zMin() < _zMin) { |
---|
479 | _zMin = dataPtr->zMin(); |
---|
480 | } |
---|
481 | if (dataPtr->xMax() > _xMax) { |
---|
482 | _xMax = dataPtr->xMax(); |
---|
483 | } |
---|
484 | if (dataPtr->yMax() > _yMax) { |
---|
485 | _yMax = dataPtr->yMax(); |
---|
486 | } |
---|
487 | if (dataPtr->zMax() > _zMax) { |
---|
488 | _zMax = dataPtr->zMax(); |
---|
489 | } |
---|
490 | } |
---|
491 | |
---|
492 | /* |
---|
493 | * Step 2. Generate the vector field from each data set. |
---|
494 | * Delete the currently generated fields. |
---|
495 | */ |
---|
496 | for (flowPtr = FirstFlow(&iter); flowPtr != NULL; |
---|
497 | flowPtr = NextFlow(&iter)) { |
---|
498 | if (!flowPtr->isDataLoaded()) { |
---|
499 | continue; |
---|
500 | } |
---|
501 | flowPtr->InitVectorField(); |
---|
502 | if (!flowPtr->visible()) { |
---|
503 | continue; |
---|
504 | } |
---|
505 | if (!flowPtr->ScaleVectorField()) { |
---|
506 | return false; |
---|
507 | } |
---|
508 | flowPtr->InitializeParticles(); |
---|
509 | NanoVis::licRenderer->set_offset(flowPtr->GetPosition()); |
---|
510 | } |
---|
511 | return true; |
---|
512 | } |
---|
513 | |
---|
514 | void |
---|
515 | FlowCmd::RenderFlows(void) |
---|
516 | { |
---|
517 | if (!NanoVis::licRenderer->isActivated()) { |
---|
518 | NanoVis::licRenderer->activate(); |
---|
519 | } |
---|
520 | FlowCmd *flowPtr; |
---|
521 | FlowIterator iter; |
---|
522 | for (flowPtr = FirstFlow(&iter); flowPtr != NULL; |
---|
523 | flowPtr = NextFlow(&iter)) { |
---|
524 | if ((flowPtr->isDataLoaded()) && (flowPtr->visible())) { |
---|
525 | flowPtr->Render(); |
---|
526 | } |
---|
527 | } |
---|
528 | flags &= ~FlowCmd::REDRAW_PENDING; |
---|
529 | } |
---|
530 | |
---|
531 | void |
---|
532 | FlowCmd::ResetFlows(void) |
---|
533 | { |
---|
534 | if (!NanoVis::licRenderer->isActivated()) { |
---|
535 | NanoVis::licRenderer->activate(); |
---|
536 | } |
---|
537 | /*NanoVis::licRenderer->convolve();*/ |
---|
538 | |
---|
539 | FlowCmd *flowPtr; |
---|
540 | FlowIterator iter; |
---|
541 | for (flowPtr = FirstFlow(&iter); flowPtr != NULL; |
---|
542 | flowPtr = NextFlow(&iter)) { |
---|
543 | if ((flowPtr->isDataLoaded()) && (flowPtr->visible())) { |
---|
544 | flowPtr->ResetParticles(); |
---|
545 | } |
---|
546 | } |
---|
547 | } |
---|
548 | |
---|
549 | void |
---|
550 | FlowCmd::AdvectFlows(void) |
---|
551 | { |
---|
552 | if (!NanoVis::licRenderer->isActivated()) { |
---|
553 | NanoVis::licRenderer->activate(); |
---|
554 | } |
---|
555 | /*NanoVis::licRenderer->convolve();*/ |
---|
556 | |
---|
557 | FlowCmd *flowPtr; |
---|
558 | FlowIterator iter; |
---|
559 | for (flowPtr = FirstFlow(&iter); flowPtr != NULL; |
---|
560 | flowPtr = NextFlow(&iter)) { |
---|
561 | if ((flowPtr->isDataLoaded()) && (flowPtr->visible())) { |
---|
562 | flowPtr->Advect(); |
---|
563 | } |
---|
564 | } |
---|
565 | } |
---|
566 | |
---|
567 | |
---|
568 | #ifdef notdef |
---|
569 | int |
---|
570 | FlowCmd::InitVectorField(Tcl_Interp *interp) |
---|
571 | { |
---|
572 | if (NanoVis::flowVisRenderer == NULL) { |
---|
573 | Tcl_AppendResult(interp, "flowvis renderer is NULL", (char *)NULL); |
---|
574 | return TCL_ERROR; |
---|
575 | } |
---|
576 | if (NanoVis::licRenderer == NULL) { |
---|
577 | Tcl_AppendResult(interp, "LIC renderer is NULL", (char *)NULL); |
---|
578 | return TCL_ERROR; |
---|
579 | } |
---|
580 | _fieldPtr->setVectorField(_volPtr->id, *(_volPtr->get_location()), |
---|
581 | 1.0f, _volPtr->height / (float)_volPtr->width, |
---|
582 | _volPtr->depth / (float)_volPtr->width, |
---|
583 | _volPtr->wAxis.max()); |
---|
584 | |
---|
585 | NanoVis::initParticle(); |
---|
586 | NanoVis::licRenderer->setVectorField( |
---|
587 | _volPtr->id, /* Texture ID */ |
---|
588 | *(_volPtr->get_location()), /* Origin */ |
---|
589 | 1.0f / volPtr->aspect_ratio_width, /* X-axis scale. */ |
---|
590 | 1.0f / volPtr->aspect_ratio_height, /* Y-axis scale. */ |
---|
591 | 1.0f / volPtr->aspect_ratio_depth, /* Z-axis scale. */ |
---|
592 | volPtr->wAxis.max()); /* Maximum ???? */ |
---|
593 | |
---|
594 | NanoVis::licRenderer->set_offset(NanoVis::lic_slice_z); |
---|
595 | return TCL_OK; |
---|
596 | } |
---|
597 | #endif |
---|
598 | |
---|
599 | int |
---|
600 | FlowCmd::CreateParticles(Tcl_Interp *interp, Tcl_Obj *objPtr) |
---|
601 | { |
---|
602 | Tcl_HashEntry *hPtr; |
---|
603 | int isNew; |
---|
604 | const char *particlesName = Tcl_GetString(objPtr); |
---|
605 | hPtr = Tcl_CreateHashEntry(&_particlesTable, particlesName, &isNew); |
---|
606 | if (!isNew) { |
---|
607 | Tcl_AppendResult(interp, "particle injection plane \"", |
---|
608 | particlesName, "\" already exists.", (char *)NULL); |
---|
609 | return TCL_ERROR; |
---|
610 | } |
---|
611 | particlesName = Tcl_GetHashKey(&_particlesTable, hPtr); |
---|
612 | FlowParticles *particlesPtr; |
---|
613 | particlesPtr = new FlowParticles(particlesName, hPtr); |
---|
614 | if (particlesPtr == NULL) { |
---|
615 | Tcl_AppendResult(interp, "can't allocate particle injection plane", |
---|
616 | (char *)NULL); |
---|
617 | Tcl_DeleteHashEntry(hPtr); |
---|
618 | return TCL_ERROR; |
---|
619 | } |
---|
620 | Tcl_SetHashValue(hPtr, particlesPtr); |
---|
621 | return TCL_OK; |
---|
622 | } |
---|
623 | |
---|
624 | int |
---|
625 | FlowCmd::GetParticles(Tcl_Interp *interp, Tcl_Obj *objPtr, |
---|
626 | FlowParticles **particlesPtrPtr) |
---|
627 | { |
---|
628 | Tcl_HashEntry *hPtr; |
---|
629 | hPtr = Tcl_FindHashEntry(&_particlesTable, Tcl_GetString(objPtr)); |
---|
630 | if (hPtr == NULL) { |
---|
631 | if (interp != NULL) { |
---|
632 | Tcl_AppendResult(interp, "can't find a particle injection plane \"", |
---|
633 | Tcl_GetString(objPtr), "\"", (char *)NULL); |
---|
634 | } |
---|
635 | return TCL_ERROR; |
---|
636 | } |
---|
637 | *particlesPtrPtr = (FlowParticles *)Tcl_GetHashValue(hPtr); |
---|
638 | return TCL_OK; |
---|
639 | } |
---|
640 | |
---|
641 | FlowParticles * |
---|
642 | FlowCmd::FirstParticles(FlowParticlesIterator *iterPtr) |
---|
643 | { |
---|
644 | iterPtr->hashPtr = Tcl_FirstHashEntry(&_particlesTable, |
---|
645 | &iterPtr->hashSearch); |
---|
646 | if (iterPtr->hashPtr == NULL) { |
---|
647 | return NULL; |
---|
648 | } |
---|
649 | return (FlowParticles *)Tcl_GetHashValue(iterPtr->hashPtr); |
---|
650 | } |
---|
651 | |
---|
652 | FlowParticles * |
---|
653 | FlowCmd::NextParticles(FlowParticlesIterator *iterPtr) |
---|
654 | { |
---|
655 | if (iterPtr->hashPtr == NULL) { |
---|
656 | return NULL; |
---|
657 | } |
---|
658 | iterPtr->hashPtr = Tcl_NextHashEntry(&iterPtr->hashSearch); |
---|
659 | if (iterPtr->hashPtr == NULL) { |
---|
660 | return NULL; |
---|
661 | } |
---|
662 | return (FlowParticles *)Tcl_GetHashValue(iterPtr->hashPtr); |
---|
663 | } |
---|
664 | |
---|
665 | int |
---|
666 | FlowCmd::CreateBox(Tcl_Interp *interp, Tcl_Obj *objPtr) |
---|
667 | { |
---|
668 | Tcl_HashEntry *hPtr; |
---|
669 | int isNew; |
---|
670 | hPtr = Tcl_CreateHashEntry(&_boxTable, Tcl_GetString(objPtr), &isNew); |
---|
671 | if (!isNew) { |
---|
672 | Tcl_AppendResult(interp, "box \"", Tcl_GetString(objPtr), |
---|
673 | "\" already exists in flow \"", name(), "\"", (char *)NULL); |
---|
674 | return TCL_ERROR; |
---|
675 | } |
---|
676 | const char *boxName; |
---|
677 | boxName = Tcl_GetHashKey(&_boxTable, hPtr); |
---|
678 | FlowBox *boxPtr; |
---|
679 | boxPtr = new FlowBox(boxName, hPtr); |
---|
680 | if (boxPtr == NULL) { |
---|
681 | Tcl_AppendResult(interp, "can't allocate box \"", boxName, "\"", |
---|
682 | (char *)NULL); |
---|
683 | Tcl_DeleteHashEntry(hPtr); |
---|
684 | return TCL_ERROR; |
---|
685 | } |
---|
686 | Tcl_SetHashValue(hPtr, boxPtr); |
---|
687 | return TCL_OK; |
---|
688 | } |
---|
689 | |
---|
690 | int |
---|
691 | FlowCmd::GetBox(Tcl_Interp *interp, Tcl_Obj *objPtr, FlowBox **boxPtrPtr) |
---|
692 | { |
---|
693 | Tcl_HashEntry *hPtr; |
---|
694 | hPtr = Tcl_FindHashEntry(&_boxTable, Tcl_GetString(objPtr)); |
---|
695 | if (hPtr == NULL) { |
---|
696 | if (interp != NULL) { |
---|
697 | Tcl_AppendResult(interp, "can't find a box \"", |
---|
698 | Tcl_GetString(objPtr), "\" in flow \"", name(), "\"", |
---|
699 | (char *)NULL); |
---|
700 | } |
---|
701 | return TCL_ERROR; |
---|
702 | } |
---|
703 | *boxPtrPtr = (FlowBox *)Tcl_GetHashValue(hPtr); |
---|
704 | return TCL_OK; |
---|
705 | } |
---|
706 | |
---|
707 | FlowBox * |
---|
708 | FlowCmd::FirstBox(FlowBoxIterator *iterPtr) |
---|
709 | { |
---|
710 | iterPtr->hashPtr = Tcl_FirstHashEntry(&_boxTable, &iterPtr->hashSearch); |
---|
711 | if (iterPtr->hashPtr == NULL) { |
---|
712 | return NULL; |
---|
713 | } |
---|
714 | return (FlowBox *)Tcl_GetHashValue(iterPtr->hashPtr); |
---|
715 | } |
---|
716 | |
---|
717 | FlowBox * |
---|
718 | FlowCmd::NextBox(FlowBoxIterator *iterPtr) |
---|
719 | { |
---|
720 | if (iterPtr->hashPtr == NULL) { |
---|
721 | return NULL; |
---|
722 | } |
---|
723 | iterPtr->hashPtr = Tcl_NextHashEntry(&iterPtr->hashSearch); |
---|
724 | if (iterPtr->hashPtr == NULL) { |
---|
725 | return NULL; |
---|
726 | } |
---|
727 | return (FlowBox *)Tcl_GetHashValue(iterPtr->hashPtr); |
---|
728 | } |
---|
729 | |
---|
730 | void |
---|
731 | FlowCmd::GetMagRange(double &min_mag, double &max_mag) |
---|
732 | { |
---|
733 | const float *values = _dataPtr->values(); |
---|
734 | size_t nValues = _dataPtr->nValues(); |
---|
735 | max_mag = -1e21, min_mag = 1e21; |
---|
736 | for (size_t i = 0; i < nValues; i += 3) { |
---|
737 | double vx, vy, vz, vm; |
---|
738 | |
---|
739 | vx = values[i]; |
---|
740 | vy = values[i+1]; |
---|
741 | vz = values[i+2]; |
---|
742 | |
---|
743 | vm = sqrt(vx*vx + vy*vy + vz*vz); |
---|
744 | if (vm > max_mag) { |
---|
745 | max_mag = vm; |
---|
746 | } |
---|
747 | if (vm < min_mag) { |
---|
748 | min_mag = vm; |
---|
749 | } |
---|
750 | } |
---|
751 | } |
---|
752 | |
---|
753 | |
---|
754 | void |
---|
755 | FlowCmd::InitVectorField(void) |
---|
756 | { |
---|
757 | if (_volPtr != NULL) { |
---|
758 | delete _volPtr; |
---|
759 | _volPtr = NULL; |
---|
760 | NanoVis::volume[_volIndex] = NULL; |
---|
761 | NanoVis::vol_renderer->remove_volume(_volIndex); |
---|
762 | } |
---|
763 | // Remove the associated vector field. |
---|
764 | if (_fieldPtr != NULL) { |
---|
765 | delete _fieldPtr; |
---|
766 | _fieldPtr = NULL; |
---|
767 | } |
---|
768 | |
---|
769 | } |
---|
770 | |
---|
771 | void |
---|
772 | FlowCmd::InitializeParticles(void) |
---|
773 | { |
---|
774 | FlowParticles *particlesPtr; |
---|
775 | FlowParticlesIterator iter; |
---|
776 | for (particlesPtr = FirstParticles(&iter); particlesPtr != NULL; |
---|
777 | particlesPtr = NextParticles(&iter)) { |
---|
778 | particlesPtr->Initialize(); |
---|
779 | } |
---|
780 | } |
---|
781 | |
---|
782 | bool |
---|
783 | FlowCmd::ScaleVectorField() |
---|
784 | { |
---|
785 | if (_volPtr != NULL) { |
---|
786 | delete _volPtr; |
---|
787 | _volPtr = NULL; |
---|
788 | NanoVis::volume[_volIndex] = NULL; |
---|
789 | NanoVis::vol_renderer->remove_volume(_volIndex); |
---|
790 | } |
---|
791 | float *vdata; |
---|
792 | vdata = GetScaledVector(); |
---|
793 | if (vdata == NULL) { |
---|
794 | return false; |
---|
795 | } |
---|
796 | Volume *volPtr; |
---|
797 | volPtr = MakeVolume(vdata); |
---|
798 | delete [] vdata; |
---|
799 | if (volPtr == NULL) { |
---|
800 | return false; |
---|
801 | } |
---|
802 | _volPtr = volPtr; |
---|
803 | |
---|
804 | _fieldPtr = new NvVectorField(); |
---|
805 | if (_fieldPtr == NULL) { |
---|
806 | return false; |
---|
807 | } |
---|
808 | |
---|
809 | double width, height, depth; |
---|
810 | width = _xMax - _xMin; |
---|
811 | height = _yMax - _yMin; |
---|
812 | depth = _zMax - _zMin; |
---|
813 | |
---|
814 | Vector3 *locationPtr = _volPtr->get_location(); |
---|
815 | /*This is wrong. Need to compute origin. */ |
---|
816 | _xOrigin = locationPtr->x; |
---|
817 | _yOrigin = locationPtr->y; |
---|
818 | _zOrigin = locationPtr->z; |
---|
819 | |
---|
820 | _fieldPtr->setVectorField(_volPtr, *locationPtr, |
---|
821 | 1.0f, height / width, depth / width, _magMax); |
---|
822 | |
---|
823 | if (NanoVis::licRenderer != NULL) { |
---|
824 | NanoVis::licRenderer->setVectorField(_volPtr->id, |
---|
825 | *locationPtr, |
---|
826 | 1.0f / _volPtr->aspect_ratio_width, |
---|
827 | 1.0f / _volPtr->aspect_ratio_height, |
---|
828 | 1.0f / _volPtr->aspect_ratio_depth, |
---|
829 | _volPtr->wAxis.max()); |
---|
830 | SetCurrentPosition(); |
---|
831 | SetAxis(); |
---|
832 | } |
---|
833 | FlowParticles *particlesPtr; |
---|
834 | FlowParticlesIterator partIter; |
---|
835 | for (particlesPtr = FirstParticles(&partIter); particlesPtr != NULL; |
---|
836 | particlesPtr = NextParticles(&partIter)) { |
---|
837 | particlesPtr->SetVectorField(_volPtr); |
---|
838 | } |
---|
839 | return true; |
---|
840 | } |
---|
841 | |
---|
842 | void |
---|
843 | FlowCmd::RenderBoxes(void) |
---|
844 | { |
---|
845 | FlowBoxIterator iter; |
---|
846 | FlowBox *boxPtr; |
---|
847 | for (boxPtr = FirstBox(&iter); boxPtr != NULL; boxPtr = NextBox(&iter)) { |
---|
848 | if (boxPtr->visible()) { |
---|
849 | boxPtr->Render(_volPtr); |
---|
850 | } |
---|
851 | } |
---|
852 | } |
---|
853 | |
---|
854 | float * |
---|
855 | FlowCmd::GetScaledVector(void) |
---|
856 | { |
---|
857 | assert(_dataPtr->nComponents() == 3); |
---|
858 | size_t n = _dataPtr->nValues() / _dataPtr->nComponents() * 4; |
---|
859 | float *data = new float[n]; |
---|
860 | if (data == NULL) { |
---|
861 | return NULL; |
---|
862 | } |
---|
863 | memset(data, 0, sizeof(float) * n); |
---|
864 | float *destPtr = data; |
---|
865 | const float *values = _dataPtr->values(); |
---|
866 | for (size_t iz=0; iz < _dataPtr->zNum(); iz++) { |
---|
867 | for (size_t iy=0; iy < _dataPtr->yNum(); iy++) { |
---|
868 | for (size_t ix=0; ix < _dataPtr->xNum(); ix++) { |
---|
869 | double vx, vy, vz, vm; |
---|
870 | vx = values[0]; |
---|
871 | vy = values[1]; |
---|
872 | vz = values[2]; |
---|
873 | vm = sqrt(vx*vx + vy*vy + vz*vz); |
---|
874 | destPtr[0] = vm / _magMax; |
---|
875 | destPtr[1] = vx /(2.0*_magMax) + 0.5; |
---|
876 | destPtr[2] = vy /(2.0*_magMax) + 0.5; |
---|
877 | destPtr[3] = vz /(2.0*_magMax) + 0.5; |
---|
878 | values += 3; |
---|
879 | destPtr += 4; |
---|
880 | } |
---|
881 | } |
---|
882 | } |
---|
883 | return data; |
---|
884 | } |
---|
885 | |
---|
886 | Volume * |
---|
887 | FlowCmd::MakeVolume(float *data) |
---|
888 | { |
---|
889 | if (_volIndex < 0) { |
---|
890 | _volIndex = NanoVis::n_volumes; |
---|
891 | } |
---|
892 | Volume *volPtr; |
---|
893 | volPtr = NanoVis::load_volume(_volIndex, _dataPtr->xNum(), |
---|
894 | _dataPtr->yNum(), _dataPtr->zNum(), 4, data, _magMin, _magMax, 0); |
---|
895 | volPtr->xAxis.SetRange(_dataPtr->xMin(), _dataPtr->xMax()); |
---|
896 | volPtr->yAxis.SetRange(_dataPtr->yMin(), _dataPtr->yMax()); |
---|
897 | volPtr->zAxis.SetRange(_dataPtr->zMin(), _dataPtr->zMax()); |
---|
898 | volPtr->wAxis.SetRange(_magMin, _magMax); |
---|
899 | |
---|
900 | /*volPtr->update_pending = false;*/ |
---|
901 | Vector3 physicalMin(_xMin, _yMin, _zMin); |
---|
902 | Vector3 physicalMax(_xMax, _yMax, _zMax); |
---|
903 | volPtr->setPhysicalBBox(physicalMin, physicalMax); |
---|
904 | |
---|
905 | volPtr->set_n_slice(256 - _volIndex); |
---|
906 | // volPtr->set_n_slice(512- _volIndex); |
---|
907 | volPtr->disable_cutplane(0); |
---|
908 | volPtr->disable_cutplane(1); |
---|
909 | volPtr->disable_cutplane(2); |
---|
910 | |
---|
911 | TransferFunction *tfPtr; |
---|
912 | tfPtr = _sv.tfPtr; |
---|
913 | if (tfPtr == NULL) { |
---|
914 | tfPtr = NanoVis::get_transfunc("default"); |
---|
915 | } |
---|
916 | NanoVis::vol_renderer->add_volume(volPtr, tfPtr); |
---|
917 | if (_sv.showVolume) { |
---|
918 | volPtr->enable_data(); |
---|
919 | } else { |
---|
920 | volPtr->disable_data(); |
---|
921 | } |
---|
922 | if (_sv.showOutline) { |
---|
923 | volPtr->enable_outline(); |
---|
924 | } else { |
---|
925 | volPtr->disable_outline(); |
---|
926 | } |
---|
927 | float dx0 = -0.5; |
---|
928 | float dy0 = -0.5*volPtr->height/volPtr->width; |
---|
929 | float dz0 = -0.5*volPtr->depth/volPtr->width; |
---|
930 | volPtr->move(Vector3(dx0, dy0, dz0)); |
---|
931 | return volPtr; |
---|
932 | } |
---|
933 | |
---|
934 | static int |
---|
935 | FlowDataFileOp(ClientData clientData, Tcl_Interp *interp, int objc, |
---|
936 | Tcl_Obj *const *objv) |
---|
937 | { |
---|
938 | Rappture::Outcome result; |
---|
939 | |
---|
940 | const char *fileName; |
---|
941 | fileName = Tcl_GetString(objv[3]); |
---|
942 | Trace("Flow loading data from file %s\n", fileName); |
---|
943 | |
---|
944 | int extents; |
---|
945 | if (Tcl_GetIntFromObj(interp, objv[4], &extents) != TCL_OK) { |
---|
946 | return TCL_ERROR; |
---|
947 | } |
---|
948 | if ((extents < 1) || (extents > 4)) { |
---|
949 | Tcl_AppendResult(interp, "bad extents value \"", Tcl_GetString(objv[4]), |
---|
950 | "\"", (char *)NULL); |
---|
951 | return TCL_ERROR; |
---|
952 | } |
---|
953 | Rappture::Buffer buf; |
---|
954 | if (!buf.load(result, fileName)) { |
---|
955 | Tcl_AppendResult(interp, "can't load data from \"", fileName, "\": ", |
---|
956 | result.remark(), (char *)NULL); |
---|
957 | return TCL_ERROR; |
---|
958 | } |
---|
959 | |
---|
960 | FlowCmd *flowPtr = (FlowCmd *)clientData; |
---|
961 | if (strncmp(buf.bytes(), "<DX>", 4) == 0) { |
---|
962 | Rappture::Unirect3d *dataPtr; |
---|
963 | |
---|
964 | dataPtr = new Rappture::Unirect3d(extents); |
---|
965 | if (!dataPtr->ReadVectorDataFromDx(result, buf.size(), |
---|
966 | (char *)buf.bytes())) { |
---|
967 | Tcl_AppendResult(interp, result.remark(), (char *)NULL); |
---|
968 | delete dataPtr; |
---|
969 | return TCL_ERROR; |
---|
970 | } |
---|
971 | flowPtr->SetData(dataPtr); |
---|
972 | } else if (strncmp(buf.bytes(), "<unirect3d>", 4) == 0) { |
---|
973 | Rappture::Unirect3d *dataPtr; |
---|
974 | Tcl_CmdInfo cmdInfo; |
---|
975 | |
---|
976 | /* Set the clientdata field of the unirect3d command to contain |
---|
977 | * the local data structure. */ |
---|
978 | if (!Tcl_GetCommandInfo(interp, "unirect3d", &cmdInfo)) { |
---|
979 | return TCL_ERROR; |
---|
980 | } |
---|
981 | dataPtr = new Rappture::Unirect3d(extents); |
---|
982 | cmdInfo.objClientData = (ClientData)dataPtr; |
---|
983 | Tcl_SetCommandInfo(interp, "unirect3d", &cmdInfo); |
---|
984 | if (Tcl_Eval(interp, (const char *)buf.bytes()) != TCL_OK) { |
---|
985 | delete dataPtr; |
---|
986 | return TCL_ERROR; |
---|
987 | } |
---|
988 | if (!dataPtr->isInitialized()) { |
---|
989 | delete dataPtr; |
---|
990 | return TCL_ERROR; |
---|
991 | } |
---|
992 | flowPtr->SetData(dataPtr); |
---|
993 | } else { |
---|
994 | Rappture::Unirect3d *dataPtr; |
---|
995 | |
---|
996 | dataPtr = new Rappture::Unirect3d(extents); |
---|
997 | if (!dataPtr->ReadVectorDataFromDx(result, buf.size(), |
---|
998 | (char *)buf.bytes())) { |
---|
999 | Tcl_AppendResult(interp, result.remark(), (char *)NULL); |
---|
1000 | delete dataPtr; |
---|
1001 | return TCL_ERROR; |
---|
1002 | } |
---|
1003 | flowPtr->SetData(dataPtr); |
---|
1004 | } |
---|
1005 | FlowCmd::EventuallyRedraw(FlowCmd::MAP_PENDING); |
---|
1006 | return TCL_OK; |
---|
1007 | } |
---|
1008 | |
---|
1009 | static int |
---|
1010 | FlowDataFollowsOp(ClientData clientData, Tcl_Interp *interp, int objc, |
---|
1011 | Tcl_Obj *const *objv) |
---|
1012 | { |
---|
1013 | Rappture::Outcome result; |
---|
1014 | |
---|
1015 | Trace("Flow Data Loading\n"); |
---|
1016 | |
---|
1017 | int nBytes; |
---|
1018 | if (Tcl_GetIntFromObj(interp, objv[3], &nBytes) != TCL_OK) { |
---|
1019 | return TCL_ERROR; |
---|
1020 | } |
---|
1021 | if (nBytes <= 0) { |
---|
1022 | Tcl_AppendResult(interp, "bad # bytes request \"", |
---|
1023 | Tcl_GetString(objv[3]), "\" for \"data follows\"", (char *)NULL); |
---|
1024 | return TCL_ERROR; |
---|
1025 | } |
---|
1026 | int extents; |
---|
1027 | if (Tcl_GetIntFromObj(interp, objv[4], &extents) != TCL_OK) { |
---|
1028 | return TCL_ERROR; |
---|
1029 | } |
---|
1030 | Rappture::Buffer buf; |
---|
1031 | if (GetDataStream(interp, buf, nBytes) != TCL_OK) { |
---|
1032 | return TCL_ERROR; |
---|
1033 | } |
---|
1034 | FlowCmd *flowPtr = (FlowCmd *)clientData; |
---|
1035 | if ((buf.size() > 4) && (strncmp(buf.bytes(), "<DX>", 4) == 0)) { |
---|
1036 | Rappture::Unirect3d *dataPtr; |
---|
1037 | |
---|
1038 | dataPtr = new Rappture::Unirect3d(extents); |
---|
1039 | if (!dataPtr->ReadVectorDataFromDx(result, buf.size(), |
---|
1040 | (char *)buf.bytes())) { |
---|
1041 | Tcl_AppendResult(interp, result.remark(), (char *)NULL); |
---|
1042 | delete dataPtr; |
---|
1043 | return TCL_ERROR; |
---|
1044 | } |
---|
1045 | flowPtr->SetData(dataPtr); |
---|
1046 | } else if ((buf.size() > 4) && |
---|
1047 | (strncmp(buf.bytes(), "<unirect3d>", 4) == 0)) { |
---|
1048 | Rappture::Unirect3d *dataPtr; |
---|
1049 | Tcl_CmdInfo cmdInfo; |
---|
1050 | |
---|
1051 | /* Set the clientdata field of the unirect3d command to contain |
---|
1052 | * the local data structure. */ |
---|
1053 | dataPtr = new Rappture::Unirect3d(extents); |
---|
1054 | if (!Tcl_GetCommandInfo(interp, "unirect3d", &cmdInfo)) { |
---|
1055 | return TCL_ERROR; |
---|
1056 | } |
---|
1057 | cmdInfo.objClientData = (ClientData)dataPtr; |
---|
1058 | Tcl_SetCommandInfo(interp, "unirect3d", &cmdInfo); |
---|
1059 | if (Tcl_Eval(interp, (const char *)buf.bytes()) != TCL_OK) { |
---|
1060 | delete dataPtr; |
---|
1061 | return TCL_ERROR; |
---|
1062 | } |
---|
1063 | if (!dataPtr->isInitialized()) { |
---|
1064 | delete dataPtr; |
---|
1065 | return TCL_ERROR; |
---|
1066 | } |
---|
1067 | flowPtr->SetData(dataPtr); |
---|
1068 | } else { |
---|
1069 | Tcl_AppendResult(interp, "unknown data header \"", /*buf.bytes(), "\"",*/ |
---|
1070 | (char *)NULL); |
---|
1071 | Rappture::Unirect3d *dataPtr; |
---|
1072 | |
---|
1073 | dataPtr = new Rappture::Unirect3d(extents); |
---|
1074 | if (!dataPtr->ReadVectorDataFromDx(result, buf.size(), |
---|
1075 | (char *)buf.bytes())) { |
---|
1076 | Tcl_AppendResult(interp, result.remark(), (char *)NULL); |
---|
1077 | delete dataPtr; |
---|
1078 | return TCL_ERROR; |
---|
1079 | } |
---|
1080 | flowPtr->SetData(dataPtr); |
---|
1081 | } |
---|
1082 | FlowCmd::EventuallyRedraw(FlowCmd::MAP_PENDING); |
---|
1083 | return TCL_OK; |
---|
1084 | } |
---|
1085 | |
---|
1086 | static Rappture::CmdSpec flowDataOps[] = { |
---|
1087 | {"file", 2, FlowDataFileOp, 5, 5, "fileName extents",}, |
---|
1088 | {"follows", 2, FlowDataFollowsOp, 5, 5, "size extents",}, |
---|
1089 | }; |
---|
1090 | static int nFlowDataOps = NumCmdSpecs(flowDataOps); |
---|
1091 | |
---|
1092 | static int |
---|
1093 | FlowDataOp(ClientData clientData, Tcl_Interp *interp, int objc, |
---|
1094 | Tcl_Obj *const *objv) |
---|
1095 | { |
---|
1096 | Tcl_ObjCmdProc *proc; |
---|
1097 | |
---|
1098 | proc = Rappture::GetOpFromObj(interp, nFlowDataOps, flowDataOps, |
---|
1099 | Rappture::CMDSPEC_ARG2, objc, objv, 0); |
---|
1100 | if (proc == NULL) { |
---|
1101 | return TCL_ERROR; |
---|
1102 | } |
---|
1103 | return (*proc) (clientData, interp, objc, objv); |
---|
1104 | } |
---|
1105 | |
---|
1106 | |
---|
1107 | static int |
---|
1108 | FlowVectorIdOp(ClientData clientData, Tcl_Interp *interp, int objc, |
---|
1109 | Tcl_Obj *const *objv) |
---|
1110 | { |
---|
1111 | #ifdef notdef |
---|
1112 | Volume *volPtr; |
---|
1113 | if (GetVolumeFromObj(interp, objv[2], &volPtr) != TCL_OK) { |
---|
1114 | return TCL_ERROR; |
---|
1115 | } |
---|
1116 | if (NanoVis::flowVisRenderer != NULL) { |
---|
1117 | NanoVis::flowVisRenderer->setVectorField(volPtr->id, |
---|
1118 | *(volPtr->get_location()), |
---|
1119 | 1.0f, |
---|
1120 | volPtr->height / (float)volPtr->width, |
---|
1121 | volPtr->depth / (float)volPtr->width, |
---|
1122 | volPtr->wAxis.max()); |
---|
1123 | NanoVis::initParticle(); |
---|
1124 | } |
---|
1125 | if (NanoVis::licRenderer != NULL) { |
---|
1126 | NanoVis::licRenderer->setVectorField(volPtr->id, |
---|
1127 | *(volPtr->get_location()), |
---|
1128 | 1.0f / volPtr->aspect_ratio_width, |
---|
1129 | 1.0f / volPtr->aspect_ratio_height, |
---|
1130 | 1.0f / volPtr->aspect_ratio_depth, |
---|
1131 | volPtr->wAxis.max()); |
---|
1132 | NanoVis::licRenderer->set_offset(NanoVis::lic_slice_z); |
---|
1133 | } |
---|
1134 | #endif |
---|
1135 | return TCL_OK; |
---|
1136 | } |
---|
1137 | |
---|
1138 | /* |
---|
1139 | *--------------------------------------------------------------------------- |
---|
1140 | * |
---|
1141 | * AxisSwitchProc -- |
---|
1142 | * |
---|
1143 | * Convert a Tcl_Obj representing the label of a child node into its |
---|
1144 | * integer node id. |
---|
1145 | * |
---|
1146 | * Results: |
---|
1147 | * The return value is a standard Tcl result. |
---|
1148 | * |
---|
1149 | *--------------------------------------------------------------------------- |
---|
1150 | */ |
---|
1151 | /*ARGSUSED*/ |
---|
1152 | static int |
---|
1153 | AxisSwitchProc( |
---|
1154 | ClientData clientData, /* Flag indicating if the node is considered |
---|
1155 | * before or after the insertion position. */ |
---|
1156 | Tcl_Interp *interp, /* Interpreter to send results back to */ |
---|
1157 | const char *switchName, /* Not used. */ |
---|
1158 | Tcl_Obj *objPtr, /* String representation */ |
---|
1159 | char *record, /* Structure record */ |
---|
1160 | int offset, /* Not used. */ |
---|
1161 | int flags) /* Not used. */ |
---|
1162 | { |
---|
1163 | const char *string = Tcl_GetString(objPtr); |
---|
1164 | if (string[1] == '\0') { |
---|
1165 | FlowCmd::SliceAxis *axisPtr = (FlowCmd::SliceAxis *)(record + offset); |
---|
1166 | char c; |
---|
1167 | c = tolower((unsigned char)string[0]); |
---|
1168 | if (c == 'x') { |
---|
1169 | *axisPtr = FlowCmd::AXIS_X; |
---|
1170 | return TCL_OK; |
---|
1171 | } else if (c == 'y') { |
---|
1172 | *axisPtr = FlowCmd::AXIS_Y; |
---|
1173 | return TCL_OK; |
---|
1174 | } else if (c == 'z') { |
---|
1175 | *axisPtr = FlowCmd::AXIS_Z; |
---|
1176 | return TCL_OK; |
---|
1177 | } |
---|
1178 | /*FALLTHRU*/ |
---|
1179 | } |
---|
1180 | Tcl_AppendResult(interp, "bad axis \"", string, |
---|
1181 | "\": should be x, y, or z", (char*)NULL); |
---|
1182 | return TCL_ERROR; |
---|
1183 | } |
---|
1184 | |
---|
1185 | /* |
---|
1186 | *--------------------------------------------------------------------------- |
---|
1187 | * |
---|
1188 | * ColorSwitchProc -- |
---|
1189 | * |
---|
1190 | * Convert a Tcl_Obj representing the label of a list of four color |
---|
1191 | * components in to a RGBA color value. |
---|
1192 | * |
---|
1193 | * Results: |
---|
1194 | * The return value is a standard Tcl result. |
---|
1195 | * |
---|
1196 | *--------------------------------------------------------------------------- |
---|
1197 | */ |
---|
1198 | /*ARGSUSED*/ |
---|
1199 | static int |
---|
1200 | ColorSwitchProc( |
---|
1201 | ClientData clientData, /* Flag indicating if the node is considered |
---|
1202 | * before or after the insertion position. */ |
---|
1203 | Tcl_Interp *interp, /* Interpreter to send results back to */ |
---|
1204 | const char *switchName, /* Not used. */ |
---|
1205 | Tcl_Obj *objPtr, /* String representation */ |
---|
1206 | char *record, /* Structure record */ |
---|
1207 | int offset, /* Not used. */ |
---|
1208 | int flags) /* Not used. */ |
---|
1209 | { |
---|
1210 | Tcl_Obj **objv; |
---|
1211 | int objc; |
---|
1212 | FlowColor *colorPtr = (FlowColor *)(record + offset); |
---|
1213 | |
---|
1214 | if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) { |
---|
1215 | return TCL_ERROR; |
---|
1216 | } |
---|
1217 | if ((objc < 3) || (objc > 4)) { |
---|
1218 | Tcl_AppendResult(interp, "wrong # of elements in color definition", |
---|
1219 | (char *)NULL); |
---|
1220 | return TCL_ERROR; |
---|
1221 | } |
---|
1222 | float values[4]; |
---|
1223 | int i; |
---|
1224 | values[3] = 1.0f; |
---|
1225 | for (i = 0; i < objc; i++) { |
---|
1226 | float value; |
---|
1227 | |
---|
1228 | if (GetFloatFromObj(interp, objv[i], &value) != TCL_OK) { |
---|
1229 | return TCL_ERROR; |
---|
1230 | } |
---|
1231 | if ((value < 0.0) || (value > 1.0)) { |
---|
1232 | Tcl_AppendResult(interp, "bad component value in \"", |
---|
1233 | Tcl_GetString(objPtr), "\": color values must be [0..1]", |
---|
1234 | (char *)NULL); |
---|
1235 | return TCL_ERROR; |
---|
1236 | } |
---|
1237 | values[i] = value; |
---|
1238 | } |
---|
1239 | colorPtr->r = values[0]; |
---|
1240 | colorPtr->g = values[1]; |
---|
1241 | colorPtr->b = values[2]; |
---|
1242 | colorPtr->a = values[3]; |
---|
1243 | return TCL_OK; |
---|
1244 | } |
---|
1245 | |
---|
1246 | /* |
---|
1247 | *--------------------------------------------------------------------------- |
---|
1248 | * |
---|
1249 | * PointSwitchProc -- |
---|
1250 | * |
---|
1251 | * Convert a Tcl_Obj representing the a 3-D coordinate into |
---|
1252 | * a point. |
---|
1253 | * |
---|
1254 | * Results: |
---|
1255 | * The return value is a standard Tcl result. |
---|
1256 | * |
---|
1257 | *--------------------------------------------------------------------------- |
---|
1258 | */ |
---|
1259 | /*ARGSUSED*/ |
---|
1260 | static int |
---|
1261 | PointSwitchProc( |
---|
1262 | ClientData clientData, /* Flag indicating if the node is considered |
---|
1263 | * before or after the insertion position. */ |
---|
1264 | Tcl_Interp *interp, /* Interpreter to send results back to */ |
---|
1265 | const char *switchName, /* Not used. */ |
---|
1266 | Tcl_Obj *objPtr, /* String representation */ |
---|
1267 | char *record, /* Structure record */ |
---|
1268 | int offset, /* Not used. */ |
---|
1269 | int flags) /* Not used. */ |
---|
1270 | { |
---|
1271 | FlowPoint *pointPtr = (FlowPoint *)(record + offset); |
---|
1272 | int objc; |
---|
1273 | Tcl_Obj **objv; |
---|
1274 | |
---|
1275 | if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) { |
---|
1276 | return TCL_ERROR; |
---|
1277 | } |
---|
1278 | if (objc != 3) { |
---|
1279 | Tcl_AppendResult(interp, "wrong # of elements for box coordinates: " |
---|
1280 | " should be \"x y z\"", (char *)NULL); |
---|
1281 | return TCL_ERROR; |
---|
1282 | } |
---|
1283 | float values[3]; |
---|
1284 | int i; |
---|
1285 | for (i = 0; i < objc; i++) { |
---|
1286 | float value; |
---|
1287 | |
---|
1288 | if (GetFloatFromObj(interp, objv[i], &value) != TCL_OK) { |
---|
1289 | return TCL_ERROR; |
---|
1290 | } |
---|
1291 | values[i] = value; |
---|
1292 | } |
---|
1293 | pointPtr->x = values[0]; |
---|
1294 | pointPtr->y = values[1]; |
---|
1295 | pointPtr->z = values[2]; |
---|
1296 | return TCL_OK; |
---|
1297 | } |
---|
1298 | |
---|
1299 | /* |
---|
1300 | *--------------------------------------------------------------------------- |
---|
1301 | * |
---|
1302 | * PositionSwitchProc -- |
---|
1303 | * |
---|
1304 | * Convert a Tcl_Obj representing the a 3-D coordinate into |
---|
1305 | * a point. |
---|
1306 | * |
---|
1307 | * Results: |
---|
1308 | * The return value is a standard Tcl result. |
---|
1309 | * |
---|
1310 | *--------------------------------------------------------------------------- |
---|
1311 | */ |
---|
1312 | /*ARGSUSED*/ |
---|
1313 | static int |
---|
1314 | PositionSwitchProc( |
---|
1315 | ClientData clientData, /* Flag indicating if the node is considered |
---|
1316 | * before or after the insertion position. */ |
---|
1317 | Tcl_Interp *interp, /* Interpreter to send results back to */ |
---|
1318 | const char *switchName, /* Not used. */ |
---|
1319 | Tcl_Obj *objPtr, /* String representation */ |
---|
1320 | char *record, /* Structure record */ |
---|
1321 | int offset, /* Not used. */ |
---|
1322 | int flags) /* Not used. */ |
---|
1323 | { |
---|
1324 | FlowPosition *posPtr = (FlowPosition *)(record + offset); |
---|
1325 | const char *string; |
---|
1326 | char *p; |
---|
1327 | |
---|
1328 | string = Tcl_GetString(objPtr); |
---|
1329 | p = strrchr(string, '%'); |
---|
1330 | if (p == NULL) { |
---|
1331 | float value; |
---|
1332 | |
---|
1333 | if (GetFloatFromObj(interp, objPtr, &value) != TCL_OK) { |
---|
1334 | return TCL_ERROR; |
---|
1335 | } |
---|
1336 | posPtr->value = value; |
---|
1337 | fprintf(stderr, "got absolute value %s\n", string); |
---|
1338 | posPtr->flags = ABSPOS; |
---|
1339 | } else { |
---|
1340 | double value; |
---|
1341 | |
---|
1342 | *p = '\0'; |
---|
1343 | if (Tcl_GetDouble(interp, string, &value) != TCL_OK) { |
---|
1344 | return TCL_ERROR; |
---|
1345 | } |
---|
1346 | posPtr->value = (float)value * 0.01; |
---|
1347 | posPtr->flags = RELPOS; |
---|
1348 | } |
---|
1349 | return TCL_OK; |
---|
1350 | } |
---|
1351 | |
---|
1352 | /* |
---|
1353 | *--------------------------------------------------------------------------- |
---|
1354 | * |
---|
1355 | * TransferFunctionSwitchProc -- |
---|
1356 | * |
---|
1357 | * Convert a Tcl_Obj representing the transfer function into a |
---|
1358 | * TransferFunction pointer. The transfer function must have been |
---|
1359 | * previously defined. |
---|
1360 | * |
---|
1361 | * Results: |
---|
1362 | * The return value is a standard Tcl result. |
---|
1363 | * |
---|
1364 | *--------------------------------------------------------------------------- |
---|
1365 | */ |
---|
1366 | /*ARGSUSED*/ |
---|
1367 | static int |
---|
1368 | TransferFunctionSwitchProc( |
---|
1369 | ClientData clientData, /* Flag indicating if the node is considered |
---|
1370 | * before or after the insertion position. */ |
---|
1371 | Tcl_Interp *interp, /* Interpreter to send results back to */ |
---|
1372 | const char *switchName, /* Not used. */ |
---|
1373 | Tcl_Obj *objPtr, /* String representation */ |
---|
1374 | char *record, /* Structure record */ |
---|
1375 | int offset, /* Not used. */ |
---|
1376 | int flags) /* Not used. */ |
---|
1377 | { |
---|
1378 | TransferFunction **funcPtrPtr = (TransferFunction **)(record + offset); |
---|
1379 | TransferFunction *funcPtr; |
---|
1380 | funcPtr = NanoVis::get_transfunc(Tcl_GetString(objPtr)); |
---|
1381 | if (funcPtr == NULL) { |
---|
1382 | Tcl_AppendResult(interp, "transfer function \"", Tcl_GetString(objPtr), |
---|
1383 | "\" is not defined", (char*)NULL); |
---|
1384 | return TCL_ERROR; |
---|
1385 | } |
---|
1386 | *funcPtrPtr = funcPtr; |
---|
1387 | return TCL_OK; |
---|
1388 | } |
---|
1389 | |
---|
1390 | static int |
---|
1391 | FlowConfigureOp(ClientData clientData, Tcl_Interp *interp, int objc, |
---|
1392 | Tcl_Obj *const *objv) |
---|
1393 | { |
---|
1394 | FlowCmd *flowPtr = (FlowCmd *)clientData; |
---|
1395 | |
---|
1396 | if (flowPtr->ParseSwitches(interp, objc - 2, objv + 2) != TCL_OK) { |
---|
1397 | return TCL_ERROR; |
---|
1398 | } |
---|
1399 | FlowCmd::EventuallyRedraw(); |
---|
1400 | return TCL_OK; |
---|
1401 | } |
---|
1402 | |
---|
1403 | static int |
---|
1404 | FlowParticlesAddOp(ClientData clientData, Tcl_Interp *interp, int objc, |
---|
1405 | Tcl_Obj *const *objv) |
---|
1406 | { |
---|
1407 | FlowCmd *flowPtr = (FlowCmd *)clientData; |
---|
1408 | |
---|
1409 | if (flowPtr->CreateParticles(interp, objv[3]) != TCL_OK) { |
---|
1410 | return TCL_ERROR; |
---|
1411 | } |
---|
1412 | FlowParticles *particlesPtr; |
---|
1413 | if (flowPtr->GetParticles(interp, objv[3], &particlesPtr) != TCL_OK) { |
---|
1414 | return TCL_ERROR; |
---|
1415 | } |
---|
1416 | if (particlesPtr->ParseSwitches(interp, objc - 4, objv + 4) != TCL_OK) { |
---|
1417 | delete particlesPtr; |
---|
1418 | return TCL_ERROR; |
---|
1419 | } |
---|
1420 | particlesPtr->Configure(); |
---|
1421 | FlowCmd::EventuallyRedraw(FlowCmd::MAP_PENDING); |
---|
1422 | Tcl_SetObjResult(interp, objv[3]); |
---|
1423 | return TCL_OK; |
---|
1424 | } |
---|
1425 | |
---|
1426 | static int |
---|
1427 | FlowParticlesConfigureOp(ClientData clientData, Tcl_Interp *interp, int objc, |
---|
1428 | Tcl_Obj *const *objv) |
---|
1429 | { |
---|
1430 | FlowCmd *flowPtr = (FlowCmd *)clientData; |
---|
1431 | |
---|
1432 | FlowParticles *particlesPtr; |
---|
1433 | if (flowPtr->GetParticles(interp, objv[3], &particlesPtr) != TCL_OK) { |
---|
1434 | return TCL_ERROR; |
---|
1435 | } |
---|
1436 | if (particlesPtr->ParseSwitches(interp, objc - 4, objv + 4) != TCL_OK) { |
---|
1437 | return TCL_ERROR; |
---|
1438 | } |
---|
1439 | particlesPtr->Configure(); |
---|
1440 | FlowCmd::EventuallyRedraw(); |
---|
1441 | return TCL_OK; |
---|
1442 | } |
---|
1443 | |
---|
1444 | static int |
---|
1445 | FlowParticlesDeleteOp(ClientData clientData, Tcl_Interp *interp, int objc, |
---|
1446 | Tcl_Obj *const *objv) |
---|
1447 | { |
---|
1448 | FlowCmd *flowPtr = (FlowCmd *)clientData; |
---|
1449 | int i; |
---|
1450 | for (i = 3; i < objc; i++) { |
---|
1451 | FlowParticles *particlesPtr; |
---|
1452 | |
---|
1453 | if (flowPtr->GetParticles(NULL, objv[i], &particlesPtr) == TCL_OK) { |
---|
1454 | delete particlesPtr; |
---|
1455 | } |
---|
1456 | } |
---|
1457 | FlowCmd::EventuallyRedraw(FlowCmd::MAP_PENDING); |
---|
1458 | return TCL_OK; |
---|
1459 | } |
---|
1460 | |
---|
1461 | static int |
---|
1462 | FlowParticlesNamesOp(ClientData clientData, Tcl_Interp *interp, int objc, |
---|
1463 | Tcl_Obj *const *objv) |
---|
1464 | { |
---|
1465 | FlowCmd *flowPtr = (FlowCmd *)clientData; |
---|
1466 | Tcl_Obj *listObjPtr; |
---|
1467 | listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); |
---|
1468 | FlowParticlesIterator iter; |
---|
1469 | FlowParticles *particlesPtr; |
---|
1470 | for (particlesPtr = flowPtr->FirstParticles(&iter); particlesPtr != NULL; |
---|
1471 | particlesPtr = flowPtr->NextParticles(&iter)) { |
---|
1472 | Tcl_Obj *objPtr; |
---|
1473 | |
---|
1474 | objPtr = Tcl_NewStringObj(particlesPtr->name(), -1); |
---|
1475 | Tcl_ListObjAppendElement(interp, listObjPtr, objPtr); |
---|
1476 | } |
---|
1477 | Tcl_SetObjResult(interp, listObjPtr); |
---|
1478 | return TCL_OK; |
---|
1479 | } |
---|
1480 | |
---|
1481 | /* |
---|
1482 | *--------------------------------------------------------------------------- |
---|
1483 | * |
---|
1484 | * FlowParticlesObjCmd -- |
---|
1485 | * |
---|
1486 | * This procedure is invoked to process commands on behalf of the flow |
---|
1487 | * object. |
---|
1488 | * |
---|
1489 | * Results: |
---|
1490 | * A standard Tcl result. |
---|
1491 | * |
---|
1492 | * Side effects: |
---|
1493 | * See the user documentation. |
---|
1494 | * |
---|
1495 | * $flow particles oper $name |
---|
1496 | *--------------------------------------------------------------------------- |
---|
1497 | */ |
---|
1498 | static Rappture::CmdSpec flowParticlesOps[] = { |
---|
1499 | {"add", 1, FlowParticlesAddOp, 4, 0, "name ?switches?",}, |
---|
1500 | {"configure", 1, FlowParticlesConfigureOp, 4, 0, "name ?switches?",}, |
---|
1501 | {"delete", 1, FlowParticlesDeleteOp, 4, 0, "?name...?"}, |
---|
1502 | {"names", 1, FlowParticlesNamesOp, 3, 4, "?pattern?"}, |
---|
1503 | }; |
---|
1504 | |
---|
1505 | static int nFlowParticlesOps = NumCmdSpecs(flowParticlesOps); |
---|
1506 | |
---|
1507 | static int |
---|
1508 | FlowParticlesOp(ClientData clientData, Tcl_Interp *interp, int objc, |
---|
1509 | Tcl_Obj *const *objv) |
---|
1510 | { |
---|
1511 | Tcl_ObjCmdProc *proc; |
---|
1512 | proc = Rappture::GetOpFromObj(interp, nFlowParticlesOps, flowParticlesOps, |
---|
1513 | Rappture::CMDSPEC_ARG2, objc, objv, 0); |
---|
1514 | if (proc == NULL) { |
---|
1515 | return TCL_ERROR; |
---|
1516 | } |
---|
1517 | FlowCmd *flowPtr = (FlowCmd *)clientData; |
---|
1518 | Tcl_Preserve(flowPtr); |
---|
1519 | int result; |
---|
1520 | result = (*proc) (clientData, interp, objc, objv); |
---|
1521 | Tcl_Release(flowPtr); |
---|
1522 | return result; |
---|
1523 | } |
---|
1524 | |
---|
1525 | static int |
---|
1526 | FlowBoxAddOp(ClientData clientData, Tcl_Interp *interp, int objc, |
---|
1527 | Tcl_Obj *const *objv) |
---|
1528 | { |
---|
1529 | FlowCmd *flowPtr = (FlowCmd *)clientData; |
---|
1530 | |
---|
1531 | if (flowPtr->CreateBox(interp, objv[3]) != TCL_OK) { |
---|
1532 | return TCL_ERROR; |
---|
1533 | } |
---|
1534 | FlowBox *boxPtr; |
---|
1535 | if (flowPtr->GetBox(interp, objv[3], &boxPtr) != TCL_OK) { |
---|
1536 | return TCL_ERROR; |
---|
1537 | } |
---|
1538 | if (boxPtr->ParseSwitches(interp, objc - 4, objv + 4) != TCL_OK) { |
---|
1539 | delete boxPtr; |
---|
1540 | return TCL_ERROR; |
---|
1541 | } |
---|
1542 | FlowCmd::EventuallyRedraw(); |
---|
1543 | Tcl_SetObjResult(interp, objv[3]); |
---|
1544 | return TCL_OK; |
---|
1545 | } |
---|
1546 | |
---|
1547 | static int |
---|
1548 | FlowBoxDeleteOp(ClientData clientData, Tcl_Interp *interp, int objc, |
---|
1549 | Tcl_Obj *const *objv) |
---|
1550 | { |
---|
1551 | FlowCmd *flowPtr = (FlowCmd *)clientData; |
---|
1552 | int i; |
---|
1553 | for (i = 3; i < objc; i++) { |
---|
1554 | FlowBox *boxPtr; |
---|
1555 | |
---|
1556 | if (flowPtr->GetBox(NULL, objv[i], &boxPtr) == TCL_OK) { |
---|
1557 | delete boxPtr; |
---|
1558 | } |
---|
1559 | } |
---|
1560 | FlowCmd::EventuallyRedraw(); |
---|
1561 | return TCL_OK; |
---|
1562 | } |
---|
1563 | |
---|
1564 | static int |
---|
1565 | FlowBoxNamesOp(ClientData clientData, Tcl_Interp *interp, int objc, |
---|
1566 | Tcl_Obj *const *objv) |
---|
1567 | { |
---|
1568 | FlowCmd *flowPtr = (FlowCmd *)clientData; |
---|
1569 | Tcl_Obj *listObjPtr; |
---|
1570 | listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); |
---|
1571 | FlowBoxIterator iter; |
---|
1572 | FlowBox *boxPtr; |
---|
1573 | for (boxPtr = flowPtr->FirstBox(&iter); boxPtr != NULL; |
---|
1574 | boxPtr = flowPtr->NextBox(&iter)) { |
---|
1575 | Tcl_Obj *objPtr; |
---|
1576 | |
---|
1577 | objPtr = Tcl_NewStringObj(boxPtr->name(), -1); |
---|
1578 | Tcl_ListObjAppendElement(interp, listObjPtr, objPtr); |
---|
1579 | } |
---|
1580 | Tcl_SetObjResult(interp, listObjPtr); |
---|
1581 | return TCL_OK; |
---|
1582 | } |
---|
1583 | |
---|
1584 | static int |
---|
1585 | FlowBoxConfigureOp(ClientData clientData, Tcl_Interp *interp, int objc, |
---|
1586 | Tcl_Obj *const *objv) |
---|
1587 | { |
---|
1588 | FlowCmd *flowPtr = (FlowCmd *)clientData; |
---|
1589 | |
---|
1590 | FlowBox *boxPtr; |
---|
1591 | if (flowPtr->GetBox(interp, objv[3], &boxPtr) != TCL_OK) { |
---|
1592 | return TCL_ERROR; |
---|
1593 | } |
---|
1594 | if (boxPtr->ParseSwitches(interp, objc - 4, objv + 4) != TCL_OK) { |
---|
1595 | return TCL_ERROR; |
---|
1596 | } |
---|
1597 | FlowCmd::EventuallyRedraw(); |
---|
1598 | return TCL_OK; |
---|
1599 | } |
---|
1600 | |
---|
1601 | /* |
---|
1602 | *--------------------------------------------------------------------------- |
---|
1603 | * |
---|
1604 | * FlowBoxOp-- |
---|
1605 | * |
---|
1606 | * This procedure is invoked to process commands on behalf of the flow |
---|
1607 | * object. |
---|
1608 | * |
---|
1609 | * Results: |
---|
1610 | * A standard Tcl result. |
---|
1611 | * |
---|
1612 | * Side effects: |
---|
1613 | * See the user documentation. |
---|
1614 | * |
---|
1615 | *--------------------------------------------------------------------------- |
---|
1616 | */ |
---|
1617 | static Rappture::CmdSpec flowBoxOps[] = { |
---|
1618 | {"add", 1, FlowBoxAddOp, 4, 0, "name ?switches?",}, |
---|
1619 | {"configure", 1, FlowBoxConfigureOp, 4, 0, "name ?switches?",}, |
---|
1620 | {"delete", 1, FlowBoxDeleteOp, 3, 0, "?name...?"}, |
---|
1621 | {"names", 1, FlowBoxNamesOp, 3, 0, "?pattern?"}, |
---|
1622 | }; |
---|
1623 | |
---|
1624 | static int nFlowBoxOps = NumCmdSpecs(flowBoxOps); |
---|
1625 | |
---|
1626 | static int |
---|
1627 | FlowBoxOp(ClientData clientData, Tcl_Interp *interp, int objc, |
---|
1628 | Tcl_Obj *const *objv) |
---|
1629 | { |
---|
1630 | Tcl_ObjCmdProc *proc; |
---|
1631 | proc = Rappture::GetOpFromObj(interp, nFlowBoxOps, flowBoxOps, |
---|
1632 | Rappture::CMDSPEC_ARG2, objc, objv, 0); |
---|
1633 | if (proc == NULL) { |
---|
1634 | return TCL_ERROR; |
---|
1635 | } |
---|
1636 | FlowCmd *flowPtr = (FlowCmd *)clientData; |
---|
1637 | Tcl_Preserve(flowPtr); |
---|
1638 | int result; |
---|
1639 | result = (*proc) (clientData, interp, objc, objv); |
---|
1640 | Tcl_Release(flowPtr); |
---|
1641 | return result; |
---|
1642 | } |
---|
1643 | |
---|
1644 | /* |
---|
1645 | *--------------------------------------------------------------------------- |
---|
1646 | * |
---|
1647 | * FlowInstObjCmd -- |
---|
1648 | * |
---|
1649 | * This procedure is invoked to process commands on behalf of the flow |
---|
1650 | * object. |
---|
1651 | * |
---|
1652 | * Results: |
---|
1653 | * A standard Tcl result. |
---|
1654 | * |
---|
1655 | * Side effects: |
---|
1656 | * See the user documentation. |
---|
1657 | * |
---|
1658 | *--------------------------------------------------------------------------- |
---|
1659 | */ |
---|
1660 | static Rappture::CmdSpec flowInstOps[] = { |
---|
1661 | {"box", 1, FlowBoxOp, 2, 0, "oper ?args?"}, |
---|
1662 | {"configure", 1, FlowConfigureOp, 2, 0, "?switches?"}, |
---|
1663 | {"data", 1, FlowDataOp, 2, 0, "oper ?args?"}, |
---|
1664 | {"particles", 1, FlowParticlesOp, 2, 0, "oper ?args?"} |
---|
1665 | }; |
---|
1666 | static int nFlowInstOps = NumCmdSpecs(flowInstOps); |
---|
1667 | |
---|
1668 | static int |
---|
1669 | FlowInstObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, |
---|
1670 | Tcl_Obj *const *objv) |
---|
1671 | { |
---|
1672 | Tcl_ObjCmdProc *proc; |
---|
1673 | proc = Rappture::GetOpFromObj(interp, nFlowInstOps, flowInstOps, |
---|
1674 | Rappture::CMDSPEC_ARG1, objc, objv, 0); |
---|
1675 | if (proc == NULL) { |
---|
1676 | return TCL_ERROR; |
---|
1677 | } |
---|
1678 | assert(CheckGL(AT)); |
---|
1679 | FlowCmd *flowPtr = (FlowCmd *)clientData; |
---|
1680 | Tcl_Preserve(flowPtr); |
---|
1681 | int result; |
---|
1682 | result = (*proc) (clientData, interp, objc, objv); |
---|
1683 | Tcl_Release(flowPtr); |
---|
1684 | return result; |
---|
1685 | } |
---|
1686 | |
---|
1687 | /* |
---|
1688 | *--------------------------------------------------------------------------- |
---|
1689 | * |
---|
1690 | * FlowInstDeleteProc -- |
---|
1691 | * |
---|
1692 | * Deletes the command associated with the tree. This is called only |
---|
1693 | * when the command associated with the tree is destroyed. |
---|
1694 | * |
---|
1695 | * Results: |
---|
1696 | * None. |
---|
1697 | * |
---|
1698 | *--------------------------------------------------------------------------- |
---|
1699 | */ |
---|
1700 | static void |
---|
1701 | FlowInstDeleteProc(ClientData clientData) |
---|
1702 | { |
---|
1703 | FlowCmd *flowPtr = (FlowCmd *)clientData; |
---|
1704 | delete flowPtr; |
---|
1705 | } |
---|
1706 | |
---|
1707 | /* |
---|
1708 | *--------------------------------------------------------------------------- |
---|
1709 | * |
---|
1710 | * FlowAddOp -- |
---|
1711 | * |
---|
1712 | *--------------------------------------------------------------------------- |
---|
1713 | */ |
---|
1714 | /*ARGSUSED*/ |
---|
1715 | static int |
---|
1716 | FlowAddOp(ClientData clientData, Tcl_Interp *interp, int objc, |
---|
1717 | Tcl_Obj *const *objv) |
---|
1718 | { |
---|
1719 | if (FlowCmd::CreateFlow(interp, objv[2]) != TCL_OK) { |
---|
1720 | return TCL_ERROR; |
---|
1721 | } |
---|
1722 | FlowCmd *flowPtr; |
---|
1723 | if (FlowCmd::GetFlow(interp, objv[2], &flowPtr) != TCL_OK) { |
---|
1724 | return TCL_ERROR; |
---|
1725 | } |
---|
1726 | if (flowPtr->ParseSwitches(interp, objc - 3, objv + 3) != TCL_OK) { |
---|
1727 | Tcl_DeleteCommand(interp, flowPtr->name()); |
---|
1728 | return TCL_ERROR; |
---|
1729 | } |
---|
1730 | Tcl_SetObjResult(interp, objv[2]); |
---|
1731 | FlowCmd::EventuallyRedraw(); |
---|
1732 | return TCL_OK; |
---|
1733 | } |
---|
1734 | |
---|
1735 | /* |
---|
1736 | *--------------------------------------------------------------------------- |
---|
1737 | * |
---|
1738 | * FlowDeleteOp -- |
---|
1739 | * |
---|
1740 | *--------------------------------------------------------------------------- |
---|
1741 | */ |
---|
1742 | /*ARGSUSED*/ |
---|
1743 | static int |
---|
1744 | FlowDeleteOp(ClientData clientData, Tcl_Interp *interp, int objc, |
---|
1745 | Tcl_Obj *const *objv) |
---|
1746 | { |
---|
1747 | int i; |
---|
1748 | |
---|
1749 | for (i = 2; i < objc; i++) { |
---|
1750 | FlowCmd *flowPtr; |
---|
1751 | |
---|
1752 | if (FlowCmd::GetFlow(interp, objv[i], &flowPtr) != TCL_OK) { |
---|
1753 | return TCL_ERROR; |
---|
1754 | } |
---|
1755 | Tcl_DeleteCommand(interp, flowPtr->name()); |
---|
1756 | } |
---|
1757 | FlowCmd::EventuallyRedraw(FlowCmd::MAP_PENDING); |
---|
1758 | return TCL_OK; |
---|
1759 | } |
---|
1760 | |
---|
1761 | /* |
---|
1762 | *--------------------------------------------------------------------------- |
---|
1763 | * |
---|
1764 | * FlowNamesOp -- |
---|
1765 | * |
---|
1766 | *--------------------------------------------------------------------------- |
---|
1767 | */ |
---|
1768 | /*ARGSUSED*/ |
---|
1769 | static int |
---|
1770 | FlowNamesOp(ClientData clientData, Tcl_Interp *interp, int objc, |
---|
1771 | Tcl_Obj *const *objv) |
---|
1772 | { |
---|
1773 | Tcl_Obj *listObjPtr; |
---|
1774 | listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); |
---|
1775 | FlowCmd *flowPtr; |
---|
1776 | FlowIterator iter; |
---|
1777 | for (flowPtr = FlowCmd::FirstFlow(&iter); flowPtr != NULL; |
---|
1778 | flowPtr = FlowCmd::NextFlow(&iter)) { |
---|
1779 | Tcl_Obj *objPtr; |
---|
1780 | |
---|
1781 | objPtr = Tcl_NewStringObj(flowPtr->name(), -1); |
---|
1782 | Tcl_ListObjAppendElement(interp, listObjPtr, objPtr); |
---|
1783 | } |
---|
1784 | Tcl_SetObjResult(interp, listObjPtr); |
---|
1785 | return TCL_OK; |
---|
1786 | } |
---|
1787 | |
---|
1788 | static int |
---|
1789 | FlowNextOp(ClientData clientData, Tcl_Interp *interp, int objc, |
---|
1790 | Tcl_Obj *const *objv) |
---|
1791 | { |
---|
1792 | assert(NanoVis::licRenderer != NULL); |
---|
1793 | if (!NanoVis::licRenderer->isActivated()) { |
---|
1794 | NanoVis::licRenderer->activate(); |
---|
1795 | } |
---|
1796 | Trace("sending flow playback frame\n"); |
---|
1797 | // Generate the latest frame and send it back to the client |
---|
1798 | if (FlowCmd::flags & FlowCmd::MAP_PENDING) { |
---|
1799 | FlowCmd::MapFlows(); |
---|
1800 | } |
---|
1801 | FlowCmd::EventuallyRedraw(); |
---|
1802 | NanoVis::licRenderer->convolve(); |
---|
1803 | FlowCmd::AdvectFlows(); |
---|
1804 | NanoVis::offscreen_buffer_capture(); //enable offscreen render |
---|
1805 | NanoVis::display(); |
---|
1806 | NanoVis::read_screen(); |
---|
1807 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); |
---|
1808 | static int frame_count = 0; |
---|
1809 | NanoVis::bmp_write_to_file(++frame_count, "."); |
---|
1810 | Trace("FLOW end\n"); |
---|
1811 | return TCL_OK; |
---|
1812 | } |
---|
1813 | |
---|
1814 | static int |
---|
1815 | FlowResetOp(ClientData clientData, Tcl_Interp *interp, int objc, |
---|
1816 | Tcl_Obj *const *objv) |
---|
1817 | { |
---|
1818 | FlowCmd::ResetFlows(); |
---|
1819 | NanoVis::licRenderer->reset(); |
---|
1820 | return TCL_OK; |
---|
1821 | } |
---|
1822 | |
---|
1823 | static int |
---|
1824 | FlowVideoOp(ClientData clientData, Tcl_Interp *interp, int objc, |
---|
1825 | Tcl_Obj *const *objv) |
---|
1826 | { |
---|
1827 | int width, height; // Resolution of video. |
---|
1828 | int numFrames; // Total number of frames. |
---|
1829 | float frameRate; // Frame rate of the video. |
---|
1830 | float bitRate; // Bit rate of the vide. |
---|
1831 | |
---|
1832 | if ((Tcl_GetIntFromObj(interp, objv[2], &width) != TCL_OK) || |
---|
1833 | (Tcl_GetIntFromObj(interp, objv[3], &height) != TCL_OK) || |
---|
1834 | (Tcl_GetIntFromObj(interp, objv[4], &numFrames) != TCL_OK) || |
---|
1835 | (GetFloatFromObj(interp, objv[5], &frameRate) != TCL_OK) || |
---|
1836 | (GetFloatFromObj(interp, objv[6], &bitRate) != TCL_OK)) { |
---|
1837 | return TCL_ERROR; |
---|
1838 | } |
---|
1839 | if ((width<0) || (width>SHRT_MAX) || (height<0) || (height>SHRT_MAX)) { |
---|
1840 | Tcl_AppendResult(interp, "bad dimensions for video", (char *)NULL); |
---|
1841 | return TCL_ERROR; |
---|
1842 | } |
---|
1843 | if ((frameRate < 0.0f) || (frameRate > 30.0f)) { |
---|
1844 | Tcl_AppendResult(interp, "bad frame rate \"", Tcl_GetString(objv[5]), |
---|
1845 | "\"", (char *)NULL); |
---|
1846 | return TCL_ERROR; |
---|
1847 | } |
---|
1848 | if ((bitRate < 0.0f) || (frameRate > 30.0f)) { |
---|
1849 | Tcl_AppendResult(interp, "bad bit rate \"", Tcl_GetString(objv[6]), |
---|
1850 | "\"", (char *)NULL); |
---|
1851 | return TCL_ERROR; |
---|
1852 | } |
---|
1853 | if (NanoVis::licRenderer == NULL) { |
---|
1854 | Tcl_AppendResult(interp, "no lic renderer.", (char *)NULL); |
---|
1855 | return TCL_ERROR; |
---|
1856 | } |
---|
1857 | if (NanoVis::flowVisRenderer == NULL) { |
---|
1858 | Tcl_AppendResult(interp, "no flow renderer.", (char *)NULL); |
---|
1859 | return TCL_ERROR; |
---|
1860 | } |
---|
1861 | NanoVis::licRenderer->activate(); |
---|
1862 | NanoVis::flowVisRenderer->activate(); |
---|
1863 | |
---|
1864 | // Save the old dimensions of the offscreen buffer. |
---|
1865 | int oldWidth, oldHeight; |
---|
1866 | oldWidth = NanoVis::win_width; |
---|
1867 | oldHeight = NanoVis::win_height; |
---|
1868 | |
---|
1869 | if ((width != oldWidth) || (height != oldHeight)) { |
---|
1870 | // Resize to the requested size. |
---|
1871 | NanoVis::resize_offscreen_buffer(width, height); |
---|
1872 | } |
---|
1873 | |
---|
1874 | char fileName[128]; |
---|
1875 | sprintf(fileName,"/tmp/flow%d.mpeg", getpid()); |
---|
1876 | |
---|
1877 | Trace("FLOW started\n"); |
---|
1878 | |
---|
1879 | Rappture::Outcome result; |
---|
1880 | Rappture::AVTranslate movie(width, height, frameRate, bitRate); |
---|
1881 | |
---|
1882 | int pad = 0; |
---|
1883 | if ((3*NanoVis::win_width) % 4 > 0) { |
---|
1884 | pad = 4 - ((3*NanoVis::win_width) % 4); |
---|
1885 | } |
---|
1886 | |
---|
1887 | movie.init(result, fileName); |
---|
1888 | |
---|
1889 | for (int i = 0; i < numFrames; i++) { |
---|
1890 | // Generate the latest frame and send it back to the client |
---|
1891 | NanoVis::licRenderer->convolve(); |
---|
1892 | FlowCmd::AdvectFlows(); |
---|
1893 | FlowCmd::RenderFlows(); |
---|
1894 | NanoVis::offscreen_buffer_capture(); //enable offscreen render |
---|
1895 | NanoVis::display(); |
---|
1896 | |
---|
1897 | NanoVis::read_screen(); |
---|
1898 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); |
---|
1899 | |
---|
1900 | // This is done before bmp_write_to_file because bmp_write_to_file |
---|
1901 | // turns rgb data to bgr |
---|
1902 | movie.append(result, NanoVis::screen_buffer, pad); |
---|
1903 | // NanoVis::bmp_write_to_file(frame_count, fileName); |
---|
1904 | } |
---|
1905 | |
---|
1906 | movie.done(result); |
---|
1907 | Trace("FLOW end\n"); |
---|
1908 | |
---|
1909 | if (NanoVis::licRenderer) { |
---|
1910 | NanoVis::licRenderer->deactivate(); |
---|
1911 | } |
---|
1912 | if (NanoVis::flowVisRenderer) { |
---|
1913 | NanoVis::flowVisRenderer->deactivate(); |
---|
1914 | } |
---|
1915 | NanoVis::initParticle(); |
---|
1916 | |
---|
1917 | // FIXME: find a way to get the data from the movie object as a void* |
---|
1918 | Rappture::Buffer data; |
---|
1919 | if (!data.load(result, fileName)) { |
---|
1920 | Tcl_AppendResult(interp, "can't load data from temporary movie file \"", |
---|
1921 | fileName, "\": ", result.remark(), (char *)NULL); |
---|
1922 | return TCL_ERROR; |
---|
1923 | } |
---|
1924 | // Build the command string for the client. |
---|
1925 | char command[200]; |
---|
1926 | sprintf(command,"nv>image -bytes %lu -type movie -token token\n", |
---|
1927 | (unsigned long)data.size()); |
---|
1928 | |
---|
1929 | NanoVis::sendDataToClient(command, data.bytes(), data.size()); |
---|
1930 | if (unlink(fileName) != 0) { |
---|
1931 | Tcl_AppendResult(interp, "can't unlink temporary movie file \"", |
---|
1932 | fileName, "\": ", Tcl_PosixError(interp), (char *)NULL); |
---|
1933 | return TCL_ERROR; |
---|
1934 | } |
---|
1935 | return TCL_OK; |
---|
1936 | } |
---|
1937 | |
---|
1938 | /* |
---|
1939 | *--------------------------------------------------------------------------- |
---|
1940 | * |
---|
1941 | * FlowObjCmd -- |
---|
1942 | * |
---|
1943 | *--------------------------------------------------------------------------- |
---|
1944 | */ |
---|
1945 | static Rappture::CmdSpec flowCmdOps[] = { |
---|
1946 | {"add", 1, FlowAddOp, 3, 0, "name ?option value...?",}, |
---|
1947 | {"delete", 1, FlowDeleteOp, 2, 0, "name...",}, |
---|
1948 | {"names", 1, FlowNamesOp, 2, 3, "?pattern?",}, |
---|
1949 | {"next", 2, FlowNextOp, 2, 2, "",}, |
---|
1950 | {"reset", 1, FlowResetOp, 2, 2, "",}, |
---|
1951 | {"video", 1, FlowVideoOp, 7, 7, |
---|
1952 | "width height numFrames frameRate bitRate ",}, |
---|
1953 | }; |
---|
1954 | static int nFlowCmdOps = NumCmdSpecs(flowCmdOps); |
---|
1955 | |
---|
1956 | /*ARGSUSED*/ |
---|
1957 | static int |
---|
1958 | FlowCmdProc(ClientData clientData, Tcl_Interp *interp, int objc, |
---|
1959 | Tcl_Obj *const *objv) |
---|
1960 | { |
---|
1961 | Tcl_ObjCmdProc *proc; |
---|
1962 | |
---|
1963 | proc = Rappture::GetOpFromObj(interp, nFlowCmdOps, flowCmdOps, |
---|
1964 | Rappture::CMDSPEC_ARG1, objc, objv, 0); |
---|
1965 | if (proc == NULL) { |
---|
1966 | return TCL_ERROR; |
---|
1967 | } |
---|
1968 | return (*proc) (clientData, interp, objc, objv); |
---|
1969 | } |
---|
1970 | |
---|
1971 | /* |
---|
1972 | *--------------------------------------------------------------------------- |
---|
1973 | * |
---|
1974 | * FlowCmdInitProc -- |
---|
1975 | * |
---|
1976 | * This procedure is invoked to initialize the "tree" command. |
---|
1977 | * |
---|
1978 | * Results: |
---|
1979 | * None. |
---|
1980 | * |
---|
1981 | * Side effects: |
---|
1982 | * Creates the new command and adds a new entry into a global Tcl |
---|
1983 | * associative array. |
---|
1984 | * |
---|
1985 | *--------------------------------------------------------------------------- |
---|
1986 | */ |
---|
1987 | int |
---|
1988 | FlowCmdInitProc(Tcl_Interp *interp) |
---|
1989 | { |
---|
1990 | Tcl_CreateObjCommand(interp, "flow", FlowCmdProc, NULL, NULL); |
---|
1991 | FlowCmd::Init(); |
---|
1992 | return TCL_OK; |
---|
1993 | } |
---|
1994 | |
---|
1995 | |
---|
1996 | float |
---|
1997 | FlowCmd::GetPosition(FlowPosition *posPtr) |
---|
1998 | { |
---|
1999 | if (posPtr->flags == RELPOS) { |
---|
2000 | return posPtr->value; |
---|
2001 | } |
---|
2002 | switch (posPtr->axis) { |
---|
2003 | case AXIS_X: |
---|
2004 | return (posPtr->value - _xMin) / (_xMax - _xMin); |
---|
2005 | case AXIS_Y: |
---|
2006 | return (posPtr->value - _yMin) / (_yMax - _yMin); |
---|
2007 | case AXIS_Z: |
---|
2008 | return (posPtr->value - _zMin) / (_zMax - _zMin); |
---|
2009 | } |
---|
2010 | return 0.0; |
---|
2011 | } |
---|
2012 | |
---|
2013 | float |
---|
2014 | FlowCmd::GetPosition(void) |
---|
2015 | { |
---|
2016 | return FlowCmd::GetPosition(&_sv.slicePos); |
---|
2017 | } |
---|