source: trunk/packages/vizservers/nanovis/FlowCmd.h @ 3474

Last change on this file since 3474 was 3397, checked in by ldelgass, 12 years ago

Add flow switch for two-sided volume lighting

  • Property svn:eol-style set to native
File size: 10.4 KB
Line 
1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 * ----------------------------------------------------------------------
4 * FlowCmd.h
5 *
6 *      This modules creates the Tcl interface to the nanovis server.  The
7 *      communication protocol of the server is the Tcl language.  Commands
8 *      given to the server by clients are executed in a safe interpreter and
9 *      the resulting image rendered offscreen is returned as BMP-formatted
10 *      image data.
11 *
12 * ======================================================================
13 *  AUTHOR:  Wei Qiao <qiaow@purdue.edu>
14 *           Insoo Woo <iwoo@purdue.edu>
15 *           Michael McLennan <mmclennan@purdue.edu>
16 *           Purdue Rendering and Perceptualization Lab (PURPL)
17 *
18 *  Copyright (c) 2004-2012  HUBzero Foundation, LLC
19 *
20 *  See the file "license.terms" for information on usage and
21 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
22 * ======================================================================
23 */
24#ifndef FLOWCMD_H
25#define FLOWCMD_H
26
27#include <tcl.h>
28
29#include "Switch.h"
30#include "NvLIC.h"
31#include "NvParticleRenderer.h"
32#include "NvVectorField.h"
33#include "Unirect.h"
34#include "Volume.h"
35
36struct FlowColor {
37    float r, g, b, a;
38};
39
40struct FlowPosition {
41    float value;
42    unsigned int flags;
43    int axis;
44};
45
46struct FlowPoint {
47    float x, y, z;
48};
49
50struct FlowParticlesValues {
51    FlowPosition position;        ///< Position on axis of particle plane
52    FlowColor color;              ///< Color of particles
53    /// Indicates if particle injection plane is active or not
54    int isHidden;
55    float particleSize;           ///< Size of the particles
56};
57
58struct FlowParticlesIterator {
59    Tcl_HashEntry *hashPtr;
60    Tcl_HashSearch hashSearch;
61};
62
63class FlowParticles
64{
65public:
66    FlowParticles(const char *name, Tcl_HashEntry *hPtr);
67
68    ~FlowParticles();
69
70    const char *name()
71    {
72        return _name;
73    }
74
75    void disconnect()
76    {
77        _hashPtr = NULL;
78    }
79
80    bool visible()
81    {
82        return !_sv.isHidden;
83    }
84
85    int parseSwitches(Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
86    {
87        if (Rappture::ParseSwitches(interp, _switches, objc, objv, &_sv,
88                                    SWITCH_DEFAULTS) < 0) {
89            return TCL_ERROR;
90        }
91        return TCL_OK;
92    }
93
94    void advect()
95    {
96        assert(_rendererPtr->active());
97        _rendererPtr->advect();
98    }
99
100    void render();
101
102    void reset()
103    {
104        _rendererPtr->reset();
105    }
106
107    void initialize()
108    {
109        _rendererPtr->initialize();
110    }
111
112    void setVectorField(Volume *volPtr, const Vector3& location,
113                        float scaleX, float scaleY, float scaleZ,
114                        float max)
115    {
116        _rendererPtr->
117            setVectorField(volPtr->textureID(),
118                           location,
119                           scaleX,
120                           scaleY,
121                           scaleZ,
122                           max);
123    }
124
125    void configure();
126
127private:
128    /**
129     * Name of particle injection plane. Actual character string is
130     * stored in hash table.
131     */
132    const char *_name;
133    Tcl_HashEntry *_hashPtr;
134    NvParticleRenderer *_rendererPtr;        ///< Particle renderer
135    FlowParticlesValues _sv;
136
137    static Rappture::SwitchSpec _switches[];
138};
139
140struct FlowBoxIterator {
141    Tcl_HashEntry *hashPtr;
142    Tcl_HashSearch hashSearch;
143};
144
145struct FlowBoxValues {
146    float position;                ///< Position on axis of particle plane
147    FlowPoint corner1, corner2;    ///< Coordinates of the box.
148    FlowColor color;               ///< Color of particles
149    float lineWidth;
150    /// Indicates if particle injection plane is active or not
151    int isHidden;
152};
153
154class FlowBox
155{
156public:
157    FlowBox(const char *name, Tcl_HashEntry *hPtr);
158
159    ~FlowBox()
160    {
161        Rappture::FreeSwitches(_switches, &_sv, 0);
162        if (_hashPtr != NULL) {
163            Tcl_DeleteHashEntry(_hashPtr);
164        }
165    }
166
167    const char *name()
168    {
169        return _name;
170    }
171
172    bool visible()
173    {
174        return !_sv.isHidden;
175    }
176
177    void disconnect()
178    {
179        _hashPtr = NULL;
180    }
181
182    int ParseSwitches(Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
183    {
184        if (Rappture::ParseSwitches(interp, _switches, objc, objv, &_sv,
185                                    SWITCH_DEFAULTS) < 0) {
186            return TCL_ERROR;
187        }
188        return TCL_OK;
189    }
190
191    void Render(Volume *volPtr);
192
193private:
194    const char *_name;          ///< Name of this box in the hash table.
195    Tcl_HashEntry *_hashPtr;    ///< Pointer to this entry in the hash table of boxes.
196    FlowBoxValues _sv;
197    static Rappture::SwitchSpec _switches[];
198
199};
200
201struct FlowValues {
202    TransferFunction *tfPtr;
203    FlowPosition slicePos;
204    int showArrows;
205    int sliceVisible;
206    int showVolume;
207    int showOutline;
208    int isHidden;
209    int twoSidedLighting;
210    float ambient;     ///< Ambient volume shading
211    float diffuse;     ///< Diffuse volume shading
212    float specular;    ///< Specular level volume shading
213    float specularExp; ///< Specular exponent volume shading
214    float opacity;     ///< Volume opacity scaling
215};
216
217struct FlowIterator {
218    Tcl_HashEntry *hashPtr;
219    Tcl_HashSearch hashSearch;
220};
221
222class FlowCmd
223{
224public:
225    enum SliceAxis { AXIS_X, AXIS_Y, AXIS_Z };
226
227    FlowCmd(Tcl_Interp *interp, const char *name, Tcl_HashEntry *hPtr);
228
229    ~FlowCmd();
230
231    int CreateParticles(Tcl_Interp *interp, Tcl_Obj *objPtr);
232
233    int GetParticles(Tcl_Interp *interp, Tcl_Obj *objPtr,
234                     FlowParticles **particlePtrPtr);
235
236    void Render();
237
238    void Advect();
239
240    void ResetParticles();
241
242    void InitializeParticles();
243
244    FlowParticles *FirstParticles(FlowParticlesIterator *iterPtr);
245
246    FlowParticles *NextParticles(FlowParticlesIterator *iterPtr);
247
248    int CreateBox(Tcl_Interp *interp, Tcl_Obj *objPtr);
249
250    int GetBox(Tcl_Interp *interp, Tcl_Obj *objPtr, FlowBox **boxPtrPtr);
251
252    FlowBox *FirstBox(FlowBoxIterator *iterPtr);
253
254    FlowBox *NextBox(FlowBoxIterator *iterPtr);
255
256    float *GetScaledVector();
257
258    Volume *MakeVolume(float *data);
259   
260    void InitVectorField();
261
262    NvVectorField *VectorField()
263    {
264        return _fieldPtr;
265    }
266
267    bool ScaleVectorField();
268
269    bool visible()
270    {
271        return !_sv.isHidden;
272    }
273
274    const char *name()
275    {
276        return _name;
277    }
278
279    void disconnect()
280    {
281        _hashPtr = NULL;
282    }
283
284    bool isDataLoaded()
285    {
286        return (_dataPtr != NULL);
287    }
288
289    Rappture::Unirect3d *data()
290    {
291        return _dataPtr;
292    }
293
294    void data(Rappture::Unirect3d *dataPtr)
295    {
296        if (_dataPtr != NULL) {
297            delete _dataPtr;
298        }
299        _dataPtr = dataPtr;
300    }
301
302    void ActivateSlice()
303    {
304        /* Must set axis before offset or position goes to wrong axis. */
305        NanoVis::licRenderer->setAxis(_sv.slicePos.axis);
306        NanoVis::licRenderer->setOffset(_sv.slicePos.value);
307        NanoVis::licRenderer->active(true);
308    }
309
310    void DeactivateSlice()
311    {
312        NanoVis::licRenderer->active(false);
313    }
314
315    SliceAxis GetAxis()
316    {
317        return (SliceAxis)_sv.slicePos.axis;
318    }
319
320    TransferFunction *GetTransferFunction()
321    {
322        return _sv.tfPtr;
323    }
324
325    float GetRelativePosition();
326
327    void SetAxis()
328    {
329        NanoVis::licRenderer->setAxis(_sv.slicePos.axis);
330    }
331
332    void SetAxis(FlowCmd::SliceAxis axis)
333    {
334        _sv.slicePos.axis = axis;
335        NanoVis::licRenderer->setAxis(_sv.slicePos.axis);
336    }
337
338    void SetCurrentPosition(float position)
339    {
340        _sv.slicePos.value = position;
341        NanoVis::licRenderer->setOffset(_sv.slicePos.value);
342    }
343
344    void SetCurrentPosition()
345    {
346        NanoVis::licRenderer->setOffset(_sv.slicePos.value);
347    }
348
349    void SetActive(bool state)
350    {
351        _sv.sliceVisible = state;
352        NanoVis::licRenderer->active(state);
353    }
354
355    void SetActive()
356    {
357        NanoVis::licRenderer->active(_sv.sliceVisible);
358    }
359
360    void SetVectorField(NvVectorField *fieldPtr)
361    {
362        DeleteVectorField();
363        _fieldPtr = fieldPtr;
364    }
365
366    void DeleteVectorField()
367    {
368        if (_fieldPtr != NULL) {
369            delete _fieldPtr;
370            _fieldPtr = NULL;
371        }
372    }
373
374    int ParseSwitches(Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
375    {
376        if (Rappture::ParseSwitches(interp, _switches, objc, objv, &_sv,
377                                    SWITCH_DEFAULTS) < 0) {
378            return TCL_ERROR;
379        }
380        return TCL_OK;
381    }
382
383    static float GetRelativePosition(FlowPosition *posPtr);
384
385    static Rappture::SwitchSpec videoSwitches[];
386
387private:
388    void Configure();
389
390    void RenderBoxes();
391
392    Tcl_Interp *_interp;
393    Tcl_HashEntry *_hashPtr;
394    /**
395     * Name of the flow.  This may differ
396     * from the name of the command
397     * associated with the flow, if the
398     * command was renamed. */
399    const char *_name;
400
401    /**
402     * Command associated with the flow.
403     * When the command is deleted, so is
404     * the flow. */
405    Tcl_Command _cmdToken;
406
407    /**
408     * Uniform rectangular data
409     * representing the mesh and vector
410     * field values.  These values are
411     * kept to regenerate the volume
412     * associated with the flow. */
413    Rappture::Unirect3d *_dataPtr;
414
415    /**
416     * The volume associated with the
417     * flow.  This isn't the same thing as
418     * a normal volume displayed. */
419    Volume *_volPtr;
420
421    /**
422     * Vector field generated from the
423     * above volume */
424    NvVectorField *_fieldPtr;
425
426    /**
427     * For each field there can be one or
428     * more particle injection planes
429     * where the particles are injected
430     * into the flow. */
431    Tcl_HashTable _particlesTable;
432
433    /**
434     * A table of boxes.  There maybe
435     * zero or more boxes associated
436     * with each field. */
437    Tcl_HashTable _boxTable;
438
439    FlowValues _sv;
440
441    static Rappture::SwitchSpec _switches[];
442};
443
444extern int GetDataStream(Tcl_Interp *interp, Rappture::Buffer &buf, int nBytes);
445
446extern int GetBooleanFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
447                             bool *boolPtr);
448
449extern int GetFloatFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
450                           float *floatPtr);
451
452extern int GetAxisFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
453                          int *axisPtr);
454
455extern int GetVolumeFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
456                            Volume **volumePtrPtr);
457
458#endif
Note: See TracBrowser for help on using the repository browser.