source: nanovis/tags/1.2.0/Flow.cpp @ 5049

Last change on this file since 5049 was 4904, checked in by ldelgass, 9 years ago

Merge serveral changes from trunk. Does not include threading, world space
changes, etc.

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