source: nanovis/branches/1.1/Flow.cpp @ 4893

Last change on this file since 4893 was 4893, checked in by ldelgass, 5 years ago

merge r4056 from trunk

  • Property svn:eol-style set to native
File size: 11.6 KB
Line 
1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 * Copyright (c) 2004-2013  HUBzero Foundation, LLC
4 *
5 * Authors:
6 *   Wei Qiao <qiaow@purdue.edu>
7 *   Insoo Woo <iwoo@purdue.edu>
8 *   George A. Howlett <gah@purdue.edu>
9 *   Leif Delgass <ldelgass@purdue.edu>
10 */
11
12#include <tcl.h>
13
14#include <vrmath/Vector3f.h>
15
16#include "nanovis.h"
17#include "Flow.h"
18#include "FlowCmd.h"
19#include "FlowTypes.h"
20#include "FlowParticles.h"
21#include "FlowBox.h"
22#include "LIC.h"
23#include "VelocityArrowsSlice.h"
24#include "Switch.h"
25#include "Unirect.h"
26#include "Volume.h"
27#include "Trace.h"
28#include "TransferFunction.h"
29
30using namespace nv;
31using namespace vrmath;
32
33Flow::Flow(Tcl_Interp *interp, const char *name) :
34    _interp(interp),
35    _name(name),
36    _data(NULL),
37    _volume(NULL)
38{
39    memset(&_sv, 0, sizeof(FlowValues));
40    _sv.sliceVisible = 1;
41    _sv.transferFunction = NanoVis::getTransferFunction("default");
42
43    _cmdToken = Tcl_CreateObjCommand(_interp, (char *)name, 
44                                     (Tcl_ObjCmdProc *)FlowInstObjCmd,
45                                     this, FlowInstDeleteProc);
46}
47
48Flow::~Flow()
49{
50    TRACE("Enter");
51
52    FreeSwitches(_switches, &_sv, 0);
53
54    if (_data != NULL) {
55        delete _data;
56    }
57    if (_volume != NULL) {
58        NanoVis::removeVolume(_volume);
59        _volume = NULL;
60    }
61    for (BoxHashmap::iterator itr = _boxTable.begin();
62         itr != _boxTable.end(); ++itr) {
63        delete itr->second;
64    }
65    _boxTable.clear();
66    for (ParticlesHashmap::iterator itr = _particlesTable.begin();
67         itr != _particlesTable.end(); ++itr) {
68        delete itr->second;
69    }
70    _particlesTable.clear();
71}
72
73void
74Flow::getBounds(Vector3f& min,
75                Vector3f& max,
76                bool onlyVisible)
77{
78    TRACE("Enter");
79
80    if (onlyVisible && !visible())
81        return;
82
83#if 0  // Using volume bounds instead of these
84    if (isDataLoaded()) {
85        Vector3f umin, umax;
86        Rappture::Unirect3d *unirect = data();
87        unirect->getWorldSpaceBounds(umin, umax);
88        if (min.x > umin.x) {
89            min.x = umin.x;
90        }
91        if (max.x < umax.x) {
92            max.x = umax.x;
93        }
94        if (min.y > umin.y) {
95            min.y = umin.y;
96        }
97        if (max.y < umax.y) {
98            max.y = umax.y;
99        }
100        if (min.z > umin.z) {
101            min.z = umin.z;
102        }
103        if (max.z < umax.z) {
104            max.z = umax.z;
105        }
106    }
107#endif
108    for (BoxHashmap::iterator itr = _boxTable.begin();
109         itr != _boxTable.end(); ++itr) {
110        FlowBox *box = itr->second;
111        if (!onlyVisible || box->visible()) {
112            Vector3f fbmin, fbmax;
113            box->getWorldSpaceBounds(fbmin, fbmax,
114                                     getVolume());
115            if (min.x > fbmin.x) {
116                min.x = fbmin.x;
117            }
118            if (max.x < fbmax.x) {
119                max.x = fbmax.x;
120            }
121            if (min.y > fbmin.y) {
122                min.y = fbmin.y;
123            }
124            if (max.y < fbmax.y) {
125                max.y = fbmax.y;
126            }
127            if (min.z > fbmin.z) {
128                min.z = fbmin.z;
129            }
130            if (max.z < fbmax.z) {
131                max.z = fbmax.z;
132            }
133        }
134    }
135}
136
137float
138Flow::getRelativePosition(FlowPosition *position)
139{
140    if (position->flags == RELPOS) {
141        return position->value;
142    }
143    switch (position->axis) {
144    case AXIS_X: 
145        return (position->value - NanoVis::xMin) / 
146            (NanoVis::xMax - NanoVis::xMin); 
147    case AXIS_Y: 
148        return (position->value - NanoVis::yMin) / 
149            (NanoVis::yMax - NanoVis::yMin); 
150    case AXIS_Z: 
151        return (position->value - NanoVis::zMin) / 
152            (NanoVis::zMax - NanoVis::zMin); 
153    }
154    return 0.0;
155}
156
157float
158Flow::getRelativePosition() 
159{
160    return getRelativePosition(&_sv.slicePos);
161}
162
163void
164Flow::resetParticles()
165{
166    for (ParticlesHashmap::iterator itr = _particlesTable.begin();
167         itr != _particlesTable.end(); ++itr) {
168        itr->second->reset();
169    }
170}
171
172void
173Flow::advect()
174{
175    for (ParticlesHashmap::iterator itr = _particlesTable.begin();
176         itr != _particlesTable.end(); ++itr) {
177        if (itr->second->visible()) {
178            itr->second->advect();
179        }
180    }
181}
182
183void
184Flow::render()
185{
186    for (ParticlesHashmap::iterator itr = _particlesTable.begin();
187         itr != _particlesTable.end(); ++itr) {
188        if (itr->second->visible()) {
189            itr->second->render();
190        }
191    }
192    renderBoxes();
193}
194
195FlowParticles *
196Flow::createParticles(const char *particlesName)
197{
198    ParticlesHashmap::iterator itr = _particlesTable.find(particlesName);
199    if (itr != _particlesTable.end()) {
200        TRACE("Deleting existing particle injection plane '%s'", particlesName);
201        delete itr->second;
202        _particlesTable.erase(itr);
203    }
204    FlowParticles *particles = new FlowParticles(particlesName);
205    _particlesTable[particlesName] = particles;
206    return particles;
207}
208
209FlowParticles *
210Flow::getParticles(const char *particlesName)
211{
212    ParticlesHashmap::iterator itr;
213    itr = _particlesTable.find(particlesName);
214    if (itr == _particlesTable.end()) {
215        TRACE("Can't find particle injection plane '%s' in '%s'", particlesName, name());
216        return NULL;
217    }
218    return itr->second;
219}
220
221void
222Flow::deleteParticles(const char *particlesName)
223{
224    ParticlesHashmap::iterator itr = _particlesTable.find(particlesName);
225    if (itr == _particlesTable.end()) {
226        TRACE("Can't find particle injection plane '%s' in '%s'", particlesName, name());
227        return;
228    }
229    delete itr->second;
230    _particlesTable.erase(itr);
231}
232
233void
234Flow::getParticlesNames(std::vector<std::string>& names)
235{
236    for (ParticlesHashmap::iterator itr = _particlesTable.begin();
237         itr != _particlesTable.end(); ++itr) {
238        names.push_back(std::string(itr->second->name()));
239    }
240}
241
242FlowBox *
243Flow::createBox(const char *boxName)
244{
245    BoxHashmap::iterator itr = _boxTable.find(boxName);
246    if (itr != _boxTable.end()) {
247        TRACE("Deleting existing box '%s'", boxName);
248        delete itr->second;
249        _boxTable.erase(itr);
250    }
251    FlowBox *box = new FlowBox(boxName);
252    _boxTable[boxName] = box;
253    return box;
254}
255
256FlowBox *
257Flow::getBox(const char *boxName)
258{
259    BoxHashmap::iterator itr = _boxTable.find(boxName);
260    if (itr == _boxTable.end()) {
261        TRACE("Can't find box '%s' in '%s'", boxName, name());
262        return NULL;
263    }
264    return itr->second;
265}
266
267void
268Flow::deleteBox(const char *boxName)
269{
270    BoxHashmap::iterator itr = _boxTable.find(boxName);
271    if (itr == _boxTable.end()) {
272        TRACE("Can't find box '%s' in '%s'", boxName, name());
273        return;
274    }
275    delete itr->second;
276    _boxTable.erase(itr);
277}
278
279void Flow::getBoxNames(std::vector<std::string>& names)
280{
281    for (BoxHashmap::iterator itr = _boxTable.begin();
282         itr != _boxTable.end(); ++itr) {
283        names.push_back(std::string(itr->second->name()));
284    }
285}
286
287void
288Flow::initializeParticles()
289{
290    for (ParticlesHashmap::iterator itr = _particlesTable.begin();
291         itr != _particlesTable.end(); ++itr) {
292        itr->second->initialize();
293    }
294}
295
296bool
297Flow::scaleVectorField()
298{
299    if (_volume != NULL) {
300        TRACE("Removing existing volume: %s", _volume->name());
301        NanoVis::removeVolume(_volume);
302        _volume = NULL;
303    }
304    float *vdata = getScaledVector();
305    if (vdata == NULL) {
306        return false;
307    }
308    Volume *volume = makeVolume(vdata);
309    delete [] vdata;
310    if (volume == NULL) {
311        return false;
312    }
313    _volume = volume;
314
315    Vector3f scale = volume->getPhysicalScaling();
316    Vector3f location = _volume->location();
317
318    if (NanoVis::licRenderer != NULL) {
319        NanoVis::licRenderer->
320            setVectorField(_volume->textureID(),
321                           location,
322                           scale.x,
323                           scale.y,
324                           scale.z,
325                           _volume->wAxis.max());
326        setCurrentPosition();
327        setAxis();
328        setActive();
329    }
330
331    if (NanoVis::velocityArrowsSlice != NULL) {
332        NanoVis::velocityArrowsSlice->
333            setVectorField(_volume->textureID(),
334                           location,
335                           scale.x,
336                           scale.y,
337                           scale.z,
338                           _volume->wAxis.max());
339        NanoVis::velocityArrowsSlice->axis(_sv.slicePos.axis);
340        NanoVis::velocityArrowsSlice->slicePos(_sv.slicePos.value);
341        NanoVis::velocityArrowsSlice->enabled(_sv.showArrows);
342    }
343
344    for (ParticlesHashmap::iterator itr = _particlesTable.begin();
345         itr != _particlesTable.end(); ++itr) {
346        itr->second->setVectorField(_volume,
347                                    location,
348                                    scale.x,
349                                    scale.y,
350                                    scale.z,
351                                    _volume->wAxis.max());
352    }
353    return true;
354}
355
356void
357Flow::renderBoxes()
358{
359    for (BoxHashmap::iterator itr = _boxTable.begin();
360         itr != _boxTable.end(); ++itr) {
361        if (itr->second->visible()) {
362            itr->second->render(_volume);
363        }
364    }
365}
366
367float *
368Flow::getScaledVector()
369{
370    assert(_data->nComponents() == 3);
371    size_t n = _data->nValues() / _data->nComponents() * 4;
372    float *data = new float[n];
373    if (data == NULL) {
374        return NULL;
375    }
376    memset(data, 0, sizeof(float) * n);
377    float *dest = data;
378    const float *values = _data->values();
379    for (size_t iz = 0; iz < _data->zNum(); iz++) {
380        for (size_t iy = 0; iy < _data->yNum(); iy++) {
381            for (size_t ix = 0; ix < _data->xNum(); ix++) {
382                double vx, vy, vz, vm;
383                vx = values[0];
384                vy = values[1];
385                vz = values[2];
386                vm = sqrt(vx*vx + vy*vy + vz*vz);
387                dest[0] = vm / NanoVis::magMax;
388                dest[1] = vx /(2.0*NanoVis::magMax) + 0.5;
389                dest[2] = vy /(2.0*NanoVis::magMax) + 0.5;
390                dest[3] = vz /(2.0*NanoVis::magMax) + 0.5;
391                values += 3;
392                dest += 4;
393            }
394        }
395    }
396    return data;
397}
398
399Volume *
400Flow::makeVolume(float *data)
401{
402    Volume *volume =
403        NanoVis::loadVolume(_name.c_str(),
404                            _data->xNum(),
405                            _data->yNum(), 
406                            _data->zNum(),
407                            4, data, 
408                            NanoVis::magMin, NanoVis::magMax, 0);
409    volume->xAxis.setRange(_data->xMin(), _data->xMax());
410    volume->yAxis.setRange(_data->yMin(), _data->yMax());
411    volume->zAxis.setRange(_data->zMin(), _data->zMax());
412
413    TRACE("min=%g %g %g max=%g %g %g mag=%g %g",
414          NanoVis::xMin, NanoVis::yMin, NanoVis::zMin,
415          NanoVis::xMax, NanoVis::yMax, NanoVis::zMax,
416          NanoVis::magMin, NanoVis::magMax);
417
418    volume->disableCutplane(0);
419    volume->disableCutplane(1);
420    volume->disableCutplane(2);
421
422    /* Initialize the volume with the previously configured values. */
423    volume->transferFunction(_sv.transferFunction);
424    volume->dataEnabled(_sv.showVolume);
425    volume->twoSidedLighting(_sv.twoSidedLighting);
426    volume->outline(_sv.showOutline);
427    volume->opacityScale(_sv.opacity);
428    volume->ambient(_sv.ambient);
429    volume->diffuse(_sv.diffuse);
430    volume->specularLevel(_sv.specular);
431    volume->specularExponent(_sv.specularExp);
432    volume->visible(_sv.showVolume);
433
434    Vector3f volScaling = volume->getPhysicalScaling();
435    Vector3f loc(volScaling);
436    loc *= -0.5;
437    volume->location(loc);
438
439    Volume::updatePending = true;
440    return volume;
441}
Note: See TracBrowser for help on using the repository browser.