Changeset 3567


Ignore:
Timestamp:
Mar 25, 2013, 1:23:25 AM (7 years ago)
Author:
ldelgass
Message:

Refactor and cleanups in nanovis, mainly to switch to using STL hash tables
(TR1 required) instead of Tcl hash tables, split out Flow particles and boxes
to separate implementation files. The goal is to achieve better separation of
Tcl command parsing and the core graphics rendering objects and code.

Location:
trunk/packages/vizservers/nanovis
Files:
5 added
1 deleted
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/packages/vizservers/nanovis/Command.cpp

    r3562 r3567  
    266266        }
    267267    }
    268     HeightMap* hmPtr;
    269     hmPtr = new HeightMap();
    270     hmPtr->setHeight(xMin, yMin, xMax, yMax, xNum, yNum, heights);
    271     hmPtr->transferFunction(NanoVis::getTransfunc("default"));
    272     hmPtr->setVisible(true);
    273     hmPtr->setLineContourVisible(true);
     268    HeightMap *heightMap = new HeightMap();
     269    heightMap->setHeight(xMin, yMin, xMax, yMax, xNum, yNum, heights);
     270    heightMap->transferFunction(NanoVis::getTransferFunction("default"));
     271    heightMap->setVisible(true);
     272    heightMap->setLineContourVisible(true);
    274273    delete [] heights;
    275     return hmPtr;
     274    return heightMap;
    276275}
    277276
     
    279278GetHeightMapFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, HeightMap **hmPtrPtr)
    280279{
    281     const char *string;
    282     string = Tcl_GetString(objPtr);
    283 
    284     Tcl_HashEntry *hPtr;
    285     hPtr = Tcl_FindHashEntry(&NanoVis::heightmapTable, string);
    286     if (hPtr == NULL) {
    287         if (interp != NULL) {
    288             Tcl_AppendResult(interp, "can't find a heightmap named \"",
     280    const char *string = Tcl_GetString(objPtr);
     281
     282    NanoVis::HeightMapHashmap::iterator itr = NanoVis::heightMapTable.find(string);
     283    if (itr == NanoVis::heightMapTable.end()) {
     284        if (interp != NULL) {
     285            Tcl_AppendResult(interp, "can't find a heightmap named \"",
    289286                         string, "\"", (char*)NULL);
    290         }
    291         return TCL_ERROR;
    292     }
    293     *hmPtrPtr = (HeightMap *)Tcl_GetHashValue(hPtr);
     287        }
     288        return TCL_ERROR;
     289    }
     290    *hmPtrPtr = itr->second;
    294291    return TCL_OK;
    295292}
     
    308305GetVolumeFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Volume **volPtrPtr)
    309306{
    310     const char *string;
    311     string = Tcl_GetString(objPtr);
    312 
    313     Tcl_HashEntry *hPtr;
    314     hPtr = Tcl_FindHashEntry(&NanoVis::volumeTable, string);
    315     if (hPtr == NULL) {
    316         if (interp != NULL) {
    317             Tcl_AppendResult(interp, "can't find a volume named \"",
     307    const char *string = Tcl_GetString(objPtr);
     308
     309    NanoVis::VolumeHashmap::iterator itr = NanoVis::volumeTable.find(string);
     310    if (itr == NanoVis::volumeTable.end()) {
     311        if (interp != NULL) {
     312            Tcl_AppendResult(interp, "can't find a volume named \"",
    318313                         string, "\"", (char*)NULL);
    319         }
    320         return TCL_ERROR;
    321     }
    322     *volPtrPtr = (Volume *)Tcl_GetHashValue(hPtr);
     314        }
     315        return TCL_ERROR;
     316    }
     317    *volPtrPtr = itr->second;
    323318    return TCL_OK;
    324319}
     
    338333{
    339334    if (objc == 0) {
    340         // No arguments. Get all volumes.
    341         Tcl_HashSearch iter;
    342         Tcl_HashEntry *hPtr;
    343         for (hPtr = Tcl_FirstHashEntry(&NanoVis::volumeTable, &iter);
    344              hPtr != NULL; hPtr = Tcl_NextHashEntry(&iter)) {
    345             Volume *volPtr;
    346             volPtr = (Volume *)Tcl_GetHashValue(hPtr);
    347             vectorPtr->push_back(volPtr);
    348         }
     335        // No arguments. Get all volumes.
     336        NanoVis::VolumeHashmap::iterator itr;
     337        for (itr = NanoVis::volumeTable.begin();
     338             itr != NanoVis::volumeTable.end(); ++itr) {
     339            vectorPtr->push_back(itr->second);
     340        }
    349341    } else {
    350         // Get the volumes associated with the given index arguments.
     342        // Get the volumes associated with the given index arguments.
    351343        for (int n = 0; n < objc; n++) {
    352             Volume *volPtr;
    353 
    354             if (GetVolumeFromObj(interp, objv[n], &volPtr) != TCL_OK) {
     344            Volume *volume;
     345            if (GetVolumeFromObj(interp, objv[n], &volume) != TCL_OK) {
    355346                return TCL_ERROR;
    356347            }
    357             vectorPtr->push_back(volPtr);
     348            vectorPtr->push_back(volume);
    358349        }
    359350    }
     
    375366{
    376367    if (objc == 0) {
    377         // No arguments. Get all heightmaps.
    378         Tcl_HashSearch iter;
    379         Tcl_HashEntry *hPtr;
    380         for (hPtr = Tcl_FirstHashEntry(&NanoVis::heightmapTable, &iter);
    381              hPtr != NULL; hPtr = Tcl_NextHashEntry(&iter)) {
    382             HeightMap *hmPtr;
    383             hmPtr = (HeightMap *)Tcl_GetHashValue(hPtr);
    384             vectorPtr->push_back(hmPtr);
    385         }
     368        // No arguments. Get all heightmaps.
     369        NanoVis::HeightMapHashmap::iterator itr;
     370        for (itr = NanoVis::heightMapTable.begin();
     371             itr != NanoVis::heightMapTable.end(); ++itr) {
     372            vectorPtr->push_back(itr->second);
     373        }
    386374    } else {
    387375        for (int n = 0; n < objc; n++) {
    388             HeightMap *hmPtr;
    389 
    390             if (GetHeightMapFromObj(interp, objv[n], &hmPtr) != TCL_OK) {
     376            HeightMap *heightMap;
     377            if (GetHeightMapFromObj(interp, objv[n], &heightMap) != TCL_OK) {
    391378                return TCL_ERROR;
    392379            }
    393             vectorPtr->push_back(hmPtr);
     380            vectorPtr->push_back(heightMap);
    394381        }
    395382    }
     
    517504    }
    518505    if (NanoVis::recfile != NULL) {
    519         ssize_t nWritten;
     506        ssize_t nWritten;
    520507
    521508        nWritten = fwrite(buf.bytes(), sizeof(char), buf.size(),
    522                           NanoVis::recfile);
    523         assert(nWritten == (ssize_t)buf.size());
     509                          NanoVis::recfile);
     510        assert(nWritten == (ssize_t)buf.size());
    524511        fflush(NanoVis::recfile);
    525512    }
     
    527514    TRACE("Checking header[%.13s]", buf.bytes());
    528515    if (strncmp (buf.bytes(), "@@RP-ENC:", 9) == 0) {
    529         /* There's a header on the buffer, use it to decode the data. */
    530         if (!Rappture::encoding::decode(err, buf, RPENC_HDR)) {
    531             Tcl_AppendResult(interp, err.remark(), (char*)NULL);
    532             return TCL_ERROR;
    533         }
     516        /* There's a header on the buffer, use it to decode the data. */
     517        if (!Rappture::encoding::decode(err, buf, RPENC_HDR)) {
     518            Tcl_AppendResult(interp, err.remark(), (char*)NULL);
     519            return TCL_ERROR;
     520        }
    534521    } else if (Rappture::encoding::isBase64(buf.bytes(), buf.size())) {
    535         /* No header, but it's base64 encoded.  It's likely that it's both
    536         * base64 encoded and compressed. */
    537         if (!Rappture::encoding::decode(err, buf, RPENC_B64 | RPENC_Z)) {
    538             Tcl_AppendResult(interp, err.remark(), (char*)NULL);
    539             return TCL_ERROR;
    540         }
     522        /* No header, but it's base64 encoded.  It's likely that it's both
     523        * base64 encoded and compressed. */
     524        if (!Rappture::encoding::decode(err, buf, RPENC_B64 | RPENC_Z)) {
     525            Tcl_AppendResult(interp, err.remark(), (char*)NULL);
     526            return TCL_ERROR;
     527        }
    541528    }
    542529    return TCL_OK;
     
    644631static int
    645632CameraCmd(ClientData clientData, Tcl_Interp *interp, int objc,
    646           Tcl_Obj *const *objv)
     633          Tcl_Obj *const *objv)
    647634{
    648635    Tcl_ObjCmdProc *proc;
     
    658645static int
    659646SnapshotCmd(ClientData clientData, Tcl_Interp *interp, int objc,
    660             Tcl_Obj *const *objv)
     647            Tcl_Obj *const *objv)
    661648{
    662649    int w, h;
     
    787774 *      "render_start" is written into the stats file.  Afterwards, it
    788775 *      is "render_info".
    789  *     
     776 *       
    790777 *         clientinfo list
    791778 */
     
    803790
    804791    if (objc != 2) {
    805         Tcl_AppendResult(interp, "wrong # of arguments: should be \"",
     792        Tcl_AppendResult(interp, "wrong # of arguments: should be \"",
    806793                Tcl_GetString(objv[0]), " list\"", (char *)NULL);
    807         return TCL_ERROR;
     794        return TCL_ERROR;
    808795    }
    809796#ifdef KEEPSTATS
     
    814801    f = NanoVis::getStatsFile(objv[1]);
    815802    if (f < 0) {
    816         Tcl_AppendResult(interp, "can't open stats file: ",
     803        Tcl_AppendResult(interp, "can't open stats file: ",
    817804                         Tcl_PosixError(interp), (char *)NULL);
    818         return TCL_ERROR;
     805        return TCL_ERROR;
    819806    }
    820807#endif
     
    858845    /* Client arguments. */
    859846    if (Tcl_ListObjGetElements(interp, objv[1], &numItems, &items) != TCL_OK) {
    860         return TCL_ERROR;
     847        return TCL_ERROR;
    861848    }
    862849    for (i = 0; i < numItems; i++) {
     
    891878static int
    892879LegendCmd(ClientData clientData, Tcl_Interp *interp, int objc,
    893           Tcl_Obj *const *objv)
     880          Tcl_Obj *const *objv)
    894881{
    895882    if (objc != 4) {
     
    901888    const char *name;
    902889    name = Tcl_GetString(objv[1]);
    903     TransferFunction *tf;
    904     tf = NanoVis::getTransfunc(name);
     890    TransferFunction *tf = NanoVis::getTransferFunction(name);
    905891    if (tf == NULL) {
    906892        Tcl_AppendResult(interp, "unknown transfer function \"", name, "\"",
     
    11821168    }
    11831169    TRACE("parsing volume data identifier");
    1184     Tcl_HashSearch iter;
    1185     Tcl_HashEntry *hPtr;
    1186     for (hPtr = Tcl_FirstHashEntry(&NanoVis::volumeTable, &iter); hPtr != NULL;
    1187          hPtr = Tcl_NextHashEntry(&iter)) {
    1188         Volume *volPtr;
    1189         volPtr = (Volume *)Tcl_GetHashValue(hPtr);
    1190         NanoVis::volRenderer->addAnimatedVolume(volPtr);
     1170    NanoVis::VolumeHashmap::iterator itr;
     1171    for (itr = NanoVis::volumeTable.begin();
     1172         itr != NanoVis::volumeTable.end(); ++itr) {
     1173        NanoVis::volRenderer->addAnimatedVolume(itr->second);
    11911174    }
    11921175    return TCL_OK;
     
    12101193
    12111194    proc = Rappture::GetOpFromObj(interp, nVolumeAnimationOps,
    1212                 volumeAnimationOps, Rappture::CMDSPEC_ARG2, objc, objv, 0);
     1195                volumeAnimationOps, Rappture::CMDSPEC_ARG2, objc, objv, 0);
    12131196    if (proc == NULL) {
    12141197        return TCL_ERROR;
     
    12271210        return TCL_ERROR;
    12281211    }
    1229     const char *tag;
    1230     tag = Tcl_GetString(objv[4]);
     1212    const char *tag = Tcl_GetString(objv[4]);
    12311213    Rappture::Buffer buf;
    12321214    if (GetDataStream(interp, buf, nbytes) != TCL_OK) {
     
    12411223    TRACE("Checking header[%.20s]", bytes);
    12421224
    1243     Volume *volPtr = NULL;
     1225    Volume *volume = NULL;
    12441226
    12451227    if ((nBytes > 5) && (strncmp(bytes, "<HDR>", 5) == 0)) {
     
    12491231        //vol = NvZincBlendeReconstructor::getInstance()->loadFromStream(fdata);
    12501232
    1251         volPtr = NvZincBlendeReconstructor::getInstance()->loadFromMemory((void*) buf.bytes());
    1252         if (volPtr == NULL) {
     1233        volume = NvZincBlendeReconstructor::getInstance()->loadFromMemory((void*) buf.bytes());
     1234        if (volume == NULL) {
    12531235            Tcl_AppendResult(interp, "can't get volume instance", (char *)NULL);
    12541236            return TCL_ERROR;
     
    12561238        TRACE("finish loading");
    12571239
    1258         Vector3f scale = volPtr->getPhysicalScaling();
     1240        Vector3f scale = volume->getPhysicalScaling();
    12591241        Vector3f loc(scale);
    12601242        loc *= -0.5;
    1261         volPtr->location(loc);
    1262 
    1263         int isNew;
    1264         Tcl_HashEntry *hPtr;
    1265         hPtr = Tcl_CreateHashEntry(&NanoVis::volumeTable, tag, &isNew);
    1266         if (!isNew) {
     1243        volume->location(loc);
     1244
     1245        NanoVis::VolumeHashmap::iterator itr = NanoVis::volumeTable.find(tag);
     1246        if (itr != NanoVis::volumeTable.end()) {
    12671247            Tcl_AppendResult(interp, "volume \"", tag, "\" already exists.",
    1268                              (char *)NULL);
     1248                             (char *)NULL);
    12691249            return TCL_ERROR;
    1270         }
    1271         Tcl_SetHashValue(hPtr, volPtr);
    1272         volPtr->name(Tcl_GetHashKey(&NanoVis::volumeTable, hPtr));
     1250        }
     1251        NanoVis::volumeTable[tag] = volume;
     1252        volume->name(tag);
    12731253    } else if ((nBytes > 14) && (strncmp(bytes, "# vtk DataFile", 14) == 0)) {
    12741254        TRACE("VTK loading...");
     
    12761256        fdata.write(bytes, nBytes);
    12771257        if (nBytes <= 0) {
    1278             ERROR("data buffer is empty");
    1279             abort();
     1258            ERROR("data buffer is empty");
     1259            abort();
    12801260        }
    12811261        Rappture::Outcome context;
    1282         volPtr = load_vtk_volume_stream(context, tag, fdata);
    1283         if (volPtr == NULL) {
     1262        volume = load_vtk_volume_stream(context, tag, fdata);
     1263        if (volume == NULL) {
    12841264            Tcl_AppendResult(interp, context.remark(), (char*)NULL);
    12851265            return TCL_ERROR;
     
    12991279        }
    13001280        Rappture::Outcome context;
    1301         volPtr = load_dx_volume_stream(context, tag, fdata);
    1302         if (volPtr == NULL) {
     1281        volume = load_dx_volume_stream(context, tag, fdata);
     1282        if (volume == NULL) {
    13031283            Tcl_AppendResult(interp, context.remark(), (char*)NULL);
    13041284            return TCL_ERROR;
     
    13061286    }
    13071287
    1308     if (volPtr != NULL) {
    1309         volPtr->disableCutplane(0);
    1310         volPtr->disableCutplane(1);
    1311         volPtr->disableCutplane(2);
    1312         volPtr->transferFunction(NanoVis::getTransfunc("default"));
    1313         volPtr->visible(true);
     1288    if (volume != NULL) {
     1289        volume->disableCutplane(0);
     1290        volume->disableCutplane(1);
     1291        volume->disableCutplane(2);
     1292        volume->transferFunction(NanoVis::getTransferFunction("default"));
     1293        volume->visible(true);
    13141294
    13151295        char info[1024];
    1316         ssize_t nWritten;
     1296        ssize_t nWritten;
    13171297
    13181298        if (Volume::updatePending) {
     
    13221302        // FIXME: strlen(info) is the return value of sprintf
    13231303        sprintf(info, "nv>data tag %s min %g max %g vmin %g vmax %g\n", tag,
    1324                 volPtr->wAxis.min(), volPtr->wAxis.max(),
     1304                volume->wAxis.min(), volume->wAxis.max(),
    13251305                Volume::valueMin, Volume::valueMax);
    13261306        nWritten  = write(1, info, strlen(info));
    1327         assert(nWritten == (ssize_t)strlen(info));
     1307        assert(nWritten == (ssize_t)strlen(info));
    13281308    }
    13291309    return TCL_OK;
     
    13441324    std::vector<Volume *>::iterator iter;
    13451325    for (iter = ivol.begin(); iter != ivol.end(); iter++) {
    1346         (*iter)->dataEnabled(state);
     1326        (*iter)->dataEnabled(state);
    13471327    }
    13481328    return TCL_OK;
     
    13711351static int
    13721352VolumeDeleteOp(ClientData clientData, Tcl_Interp *interp, int objc,
    1373                Tcl_Obj *const *objv)
    1374 {
    1375     int i;
    1376 
    1377     for (i = 2; i < objc; i++) {
    1378         Volume *volPtr;
    1379 
    1380         if (GetVolumeFromObj(interp, objv[i], &volPtr) != TCL_OK) {
    1381             return TCL_ERROR;
    1382         }
    1383         NanoVis::removeVolume(volPtr);
     1353               Tcl_Obj *const *objv)
     1354{
     1355    for (int i = 2; i < objc; i++) {
     1356        Volume *volume;
     1357        if (GetVolumeFromObj(interp, objv[i], &volume) != TCL_OK) {
     1358            return TCL_ERROR;
     1359        }
     1360        NanoVis::removeVolume(volume);
    13841361    }
    13851362    NanoVis::eventuallyRedraw();
     
    13891366static int
    13901367VolumeExistsOp(ClientData clientData, Tcl_Interp *interp, int objc,
    1391                Tcl_Obj *const *objv)
     1368               Tcl_Obj *const *objv)
    13921369{
    13931370    bool value;
    1394     Volume *volPtr;
     1371    Volume *volume;
    13951372
    13961373    value = false;
    1397     if (GetVolumeFromObj(NULL, objv[2], &volPtr) == TCL_OK) {
    1398         value = true;
     1374    if (GetVolumeFromObj(NULL, objv[2], &volume) == TCL_OK) {
     1375        value = true;
    13991376    }
    14001377    Tcl_SetBooleanObj(Tcl_GetObjResult(interp), (int)value);
     
    14041381static int
    14051382VolumeNamesOp(ClientData clientData, Tcl_Interp *interp, int objc,
    1406               Tcl_Obj *const *objv)
     1383              Tcl_Obj *const *objv)
    14071384{
    14081385    Tcl_Obj *listObjPtr;
    14091386    listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
    1410     Tcl_HashEntry *hPtr;
    1411     Tcl_HashSearch iter;
    1412     for (hPtr = Tcl_FirstHashEntry(&NanoVis::volumeTable, &iter); hPtr != NULL;
    1413          hPtr = Tcl_NextHashEntry(&iter)) {
    1414         Volume *volPtr;
    1415         volPtr = (Volume *)Tcl_GetHashValue(hPtr);
    1416         Tcl_Obj *objPtr;
    1417         objPtr = Tcl_NewStringObj(volPtr->name(), -1);
    1418         Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
     1387    NanoVis::VolumeHashmap::iterator itr;
     1388    for (itr = NanoVis::volumeTable.begin();
     1389         itr != NanoVis::volumeTable.end(); ++itr) {
     1390        Tcl_Obj *objPtr = Tcl_NewStringObj(itr->second->name(), -1);
     1391        Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
    14191392    }
    14201393    Tcl_SetObjResult(interp, listObjPtr);
     
    14551428    std::vector<Volume *>::iterator iter;
    14561429    for (iter = ivol.begin(); iter != ivol.end(); iter++) {
    1457         (*iter)->outline(state);
     1430        (*iter)->outline(state);
    14581431    }
    14591432    return TCL_OK;
     
    16331606                         Tcl_Obj *const *objv)
    16341607{
    1635     TransferFunction *tfPtr;
    16361608    const char *name = Tcl_GetString(objv[3]);
    1637     tfPtr = NanoVis::getTransfunc(name);
    1638     if (tfPtr == NULL) {
     1609    TransferFunction *tf = NanoVis::getTransferFunction(name);
     1610    if (tf == NULL) {
    16391611        Tcl_AppendResult(interp, "transfer function \"", name,
    16401612                         "\" is not defined", (char*)NULL);
     
    16471619    std::vector<Volume *>::iterator iter;
    16481620    for (iter = ivol.begin(); iter != ivol.end(); iter++) {
    1649         TRACE("setting %s with transfer function %s", (*iter)->name(),
    1650                tfPtr->name());
    1651         (*iter)->transferFunction(tfPtr);
     1621        TRACE("setting %s with transfer function %s", (*iter)->name(),
     1622               tf->name());
     1623        (*iter)->transferFunction(tf);
    16521624#ifdef USE_POINTSET_RENDERER
    16531625        // TBD..
    16541626        if ((*iter)->pointsetIndex != -1) {
    1655             NanoVis::pointSet[(*iter)->pointsetIndex]->updateColor(tfPtr->getData(), 256);
     1627            NanoVis::pointSet[(*iter)->pointsetIndex]->updateColor(tf->getData(), 256);
    16561628        }
    16571629#endif
     
    17001672    std::vector<Volume *>::iterator iter;
    17011673    for (iter = ivol.begin(); iter != ivol.end(); iter++) {
    1702         (*iter)->visible(state);
    1703     }
    1704     return TCL_OK;
    1705 }
    1706 
    1707 static int
    1708 VolumeTestOp(ClientData clientData, Tcl_Interp *interp, int objc,
    1709              Tcl_Obj *const *objv)
    1710 {
    1711     // Find the first volume in the vector.
    1712     Tcl_HashEntry *hPtr;
    1713     Tcl_HashSearch iter;
    1714     hPtr = Tcl_FirstHashEntry(&NanoVis::volumeTable, &iter);
    1715     if (hPtr != NULL) {
    1716         Volume *volPtr;
    1717         volPtr = (Volume *)Tcl_GetHashValue(hPtr);
    1718         volPtr->dataEnabled(false);
    1719         volPtr->visible(false);
     1674        (*iter)->visible(state);
    17201675    }
    17211676    return TCL_OK;
     
    17311686    {"shading",   2, VolumeShadingOp,     3, 0, "oper ?args?",},
    17321687    {"state",     2, VolumeStateOp,       3, 0, "bool ?indices?",},
    1733     {"test2",     1, VolumeTestOp,        2, 2, "",},
    17341688};
    17351689static int nVolumeOps = NumCmdSpecs(volumeOps);
     
    17521706static int
    17531707VolumeCmd(ClientData clientData, Tcl_Interp *interp, int objc,
    1754           Tcl_Obj *const *objv)
     1708          Tcl_Obj *const *objv)
    17551709{
    17561710    Tcl_ObjCmdProc *proc;
     
    17721726        return TCL_ERROR;
    17731727    }
    1774     const char *tag;
    1775     tag = Tcl_GetString(objv[4]);
    1776     int isNew;
    1777     Tcl_HashEntry *hPtr;
     1728    const char *tag = Tcl_GetString(objv[4]);
    17781729
    17791730    Rappture::Buffer buf;
     
    17831734    Rappture::Unirect2d data(1);
    17841735    if (data.parseBuffer(interp, buf) != TCL_OK) {
    1785         return TCL_ERROR;
     1736        return TCL_ERROR;
    17861737    }
    17871738    if (data.nValues() == 0) {
    1788         Tcl_AppendResult(interp, "no data found in stream", (char *)NULL);
    1789         return TCL_ERROR;
     1739        Tcl_AppendResult(interp, "no data found in stream", (char *)NULL);
     1740        return TCL_ERROR;
    17901741    }
    17911742    if (!data.isInitialized()) {
    1792         return TCL_ERROR;
    1793     }
    1794     HeightMap* hmPtr;
    1795     hPtr = Tcl_CreateHashEntry(&NanoVis::heightmapTable, tag, &isNew);
    1796     if (isNew) {
    1797         hmPtr = new HeightMap();
    1798         Tcl_SetHashValue(hPtr, hmPtr);
     1743        return TCL_ERROR;
     1744    }
     1745    HeightMap *heightMap;
     1746    NanoVis::HeightMapHashmap::iterator itr = NanoVis::heightMapTable.find(tag);
     1747    if (itr != NanoVis::heightMapTable.end()) {
     1748        heightMap = itr->second;
    17991749    } else {
    1800         hmPtr = (HeightMap *)Tcl_GetHashValue(hPtr);
    1801     }
    1802     TRACE("Number of heightmaps=%d", NanoVis::heightmapTable.numEntries);
     1750        heightMap = new HeightMap();
     1751        NanoVis::heightMapTable[tag] = heightMap;
     1752    }
     1753    TRACE("Number of heightmaps=%d", NanoVis::heightMapTable.size());
    18031754    // Must set units before the heights.
    1804     hmPtr->xAxis.units(data.xUnits());
    1805     hmPtr->yAxis.units(data.yUnits());
    1806     hmPtr->zAxis.units(data.vUnits());
    1807     hmPtr->wAxis.units(data.yUnits());
    1808     hmPtr->setHeight(data.xMin(), data.yMin(), data.xMax(), data.yMax(),
    1809                      data.xNum(), data.yNum(), data.transferValues());
    1810     hmPtr->transferFunction(NanoVis::getTransfunc("default"));
    1811     hmPtr->setVisible(true);
    1812     hmPtr->setLineContourVisible(true);
     1755    heightMap->xAxis.units(data.xUnits());
     1756    heightMap->yAxis.units(data.yUnits());
     1757    heightMap->zAxis.units(data.vUnits());
     1758    heightMap->wAxis.units(data.yUnits());
     1759    heightMap->setHeight(data.xMin(), data.yMin(), data.xMax(), data.yMax(),
     1760                         data.xNum(), data.yNum(), data.transferValues());
     1761    heightMap->transferFunction(NanoVis::getTransferFunction("default"));
     1762    heightMap->setVisible(true);
     1763    heightMap->setLineContourVisible(true);
    18131764    NanoVis::eventuallyRedraw();
    18141765    return TCL_OK;
     
    18781829static int
    18791830HeightMapLineContourVisibleOp(ClientData clientData, Tcl_Interp *interp,
    1880                               int objc, Tcl_Obj *const *objv)
     1831                              int objc, Tcl_Obj *const *objv)
    18811832{
    18821833    bool visible;
     
    19331884                  Tcl_Obj *const *objv)
    19341885{
    1935     const char *tag;
    1936     tag = Tcl_GetString(objv[2]);
    1937     Tcl_HashEntry *hPtr;
    1938     int isNew;
    1939     hPtr = Tcl_CreateHashEntry(&NanoVis::heightmapTable, tag, &isNew);
    1940     if (!isNew) {
    1941         Tcl_AppendResult(interp, "heightmap \"", tag, "\" already exists.",
    1942                          (char *)NULL);
    1943         return TCL_ERROR;
    1944     }
    1945     HeightMap *hmPtr;
     1886    const char *tag = Tcl_GetString(objv[2]);
     1887    NanoVis::HeightMapHashmap::iterator itr = NanoVis::heightMapTable.find(tag);
     1888    if (itr != NanoVis::heightMapTable.end()) {
     1889        Tcl_AppendResult(interp, "heightmap \"", tag, "\" already exists.",
     1890                         (char *)NULL);
     1891        return TCL_ERROR;
     1892    }
    19461893    /* heightmap create xmin ymin xmax ymax xnum ynum values */
    1947     hmPtr = CreateHeightMap(clientData, interp, objc - 3, objv + 3);
    1948     if (hmPtr == NULL) {
    1949         return TCL_ERROR;
    1950     }
    1951     Tcl_SetHashValue(hPtr, hmPtr);
    1952     Tcl_SetStringObj(Tcl_GetObjResult(interp), tag, -1);;
     1894    HeightMap *heightMap = CreateHeightMap(clientData, interp, objc - 3, objv + 3);
     1895    if (heightMap == NULL) {
     1896        return TCL_ERROR;
     1897    }
     1898    NanoVis::heightMapTable[tag] = heightMap;
    19531899    NanoVis::eventuallyRedraw();
    1954     TRACE("Number of heightmaps=%d", NanoVis::heightmapTable.numEntries);
     1900    TRACE("Number of heightmaps=%d", NanoVis::heightMapTable.size());
    19551901    return TCL_OK;
    19561902}
     
    19701916    if (tfPtr == NULL) {
    19711917        Tcl_AppendResult(interp, "no transfer function defined for heightmap"
    1972                         " \"", tag, "\"", (char*)NULL);
     1918                        " \"", tag, "\"", (char*)NULL);
    19731919        return TCL_ERROR;
    19741920    }
     
    20181964    const char *name;
    20191965    name = Tcl_GetString(objv[2]);
    2020     TransferFunction *tfPtr;
    2021     tfPtr = NanoVis::getTransfunc(name);
    2022     if (tfPtr == NULL) {
     1966    TransferFunction *tf = NanoVis::getTransferFunction(name);
     1967    if (tf == NULL) {
    20231968        Tcl_AppendResult(interp, "transfer function \"", name,
    20241969                         "\" is not defined", (char*)NULL);
     
    20311976    std::vector<HeightMap *>::iterator iter;
    20321977    for (iter = imap.begin(); iter != imap.end(); iter++) {
    2033         (*iter)->transferFunction(tfPtr);
     1978        (*iter)->transferFunction(tf);
    20341979    }
    20351980    NanoVis::eventuallyRedraw();
     
    20441989    float opacity;
    20451990    if (GetFloatFromObj(interp, objv[2], &opacity) != TCL_OK) {
    2046         return TCL_ERROR;
     1991        return TCL_ERROR;
    20471992    }
    20481993    std::vector<HeightMap *> heightmaps;
     
    20732018static int
    20742019HeightMapCmd(ClientData clientData, Tcl_Interp *interp, int objc,
    2075              Tcl_Obj *const *objv)
     2020             Tcl_Obj *const *objv)
    20762021{
    20772022    Tcl_ObjCmdProc *proc;
     
    21502095static int
    21512096GridVisibleOp(ClientData clientData, Tcl_Interp *interp, int objc,
    2152               Tcl_Obj *const *objv)
     2097              Tcl_Obj *const *objv)
    21532098{
    21542099    bool visible;
     
    21702115static int
    21712116GridCmd(ClientData clientData, Tcl_Interp *interp, int objc,
    2172         Tcl_Obj *const *objv)
     2117        Tcl_Obj *const *objv)
    21732118{
    21742119    Tcl_ObjCmdProc *proc;
     
    21842129static int
    21852130AxisCmd(ClientData clientData, Tcl_Interp *interp, int objc,
    2186         Tcl_Obj *const *objv)
     2131        Tcl_Obj *const *objv)
    21872132{
    21882133    if (objc < 2) {
     
    22112156static int
    22122157PlaneAddOp(ClientData clientData, Tcl_Interp *interp, int objc,
    2213            Tcl_Obj *const *objv)
     2158           Tcl_Obj *const *objv)
    22142159{
    22152160    TRACE("load plane for 2D visualization command");
     
    23162261static int
    23172262PlaneCmd(ClientData clientData, Tcl_Interp *interp, int objc,
    2318         Tcl_Obj *const *objv)
     2263        Tcl_Obj *const *objv)
    23192264{
    23202265    Tcl_ObjCmdProc *proc;
     
    23642309static int
    23652310Unirect3dCmd(ClientData clientData, Tcl_Interp *interp, int objc,
    2366              Tcl_Obj *const *objv)
     2311             Tcl_Obj *const *objv)
    23672312{
    23682313    Rappture::Unirect3d *dataPtr = (Rappture::Unirect3d *)clientData;
     
    23912336    Tcl_CreateObjCommand(interp, "cutplane",    CutplaneCmd,    NULL, NULL);
    23922337    if (FlowCmdInitProc(interp) != TCL_OK) {
    2393         return NULL;
     2338        return NULL;
    23942339    }
    23952340    Tcl_CreateObjCommand(interp, "grid",        GridCmd,        NULL, NULL);
     
    24072352    Tcl_CreateObjCommand(interp, "volume",      VolumeCmd,      NULL, NULL);
    24082353
    2409     Tcl_InitHashTable(&NanoVis::volumeTable, TCL_STRING_KEYS);
    2410     Tcl_InitHashTable(&NanoVis::heightmapTable, TCL_STRING_KEYS);
    24112354    // create a default transfer function
    24122355    if (Tcl_Eval(interp, def_transfunc) != TCL_OK) {
    24132356        WARN("bad default transfer function:\n%s",
    2414              Tcl_GetStringResult(interp));
     2357             Tcl_GetStringResult(interp));
    24152358    }
    24162359    return interp;
  • trunk/packages/vizservers/nanovis/Doxyfile.in

    r3492 r3567  
    215215# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat
    216216# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran),
    217 # use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
     217# use: inc=Fortran f=C. Note that for custom extensions you also need to set
     218# FILE_PATTERNS otherwise the files are not read by doxygen.
    218219
    219220EXTENSION_MAPPING      =
  • trunk/packages/vizservers/nanovis/FlowCmd.cpp

    r3566 r3567  
    2424
    2525#include <vrmath/Vector3f.h>
    26 #include <vrmath/Vector4f.h>
    27 #include <vrmath/Matrix4x4d.h>
    2826
    2927#include "nvconf.h"
    3028
    3129#include "nanovis.h"
     30#include "CmdProc.h"
    3231#include "FlowCmd.h"
    33 #include "CmdProc.h"
     32#include "FlowTypes.h"
     33#include "FlowBox.h"
     34#include "FlowParticles.h"
    3435#include "Switch.h"
    3536#include "TransferFunction.h"
     
    3940#include "VelocityArrowsSlice.h"
    4041#include "Volume.h"
    41 
    42 #define RELPOS 0
    43 #define ABSPOS 1
    4442
    4543using namespace vrmath;
     
    9694     offsetof(FlowValues, specular), 0},
    9795    {Rappture::SWITCH_CUSTOM, "-transferfunction", "name",
    98      offsetof(FlowValues, tfPtr), 0, 0, &transferFunctionSwitch},
     96     offsetof(FlowValues, transferFunction), 0, 0, &transferFunctionSwitch},
    9997    {Rappture::SWITCH_BOOLEAN, "-volume", "boolean",
    10098     offsetof(FlowValues, showVolume), 0},
     
    133131static Tcl_CmdDeleteProc FlowInstDeleteProc;
    134132
    135 FlowParticles::FlowParticles(const char *name, Tcl_HashEntry *hPtr) :
     133FlowCmd::FlowCmd(Tcl_Interp *interp, const char *name) :
     134    _interp(interp),
    136135    _name(name),
    137     _hashPtr(hPtr),
    138     _rendererPtr(new NvParticleRenderer(NMESH, NMESH))
    139 {
    140     _sv.position.value = 0.0f;
    141     _sv.position.flags = RELPOS;
    142     _sv.position.axis = 0; // X_AXIS
    143     _sv.color.r = _sv.color.g = _sv.color.b = _sv.color.a = 1.0f;
    144     _sv.isHidden = false;
    145     _sv.particleSize = 1.2;
    146 }
    147 
    148 FlowParticles::~FlowParticles()
    149 {
    150     if (_rendererPtr != NULL) {
    151         delete _rendererPtr;
    152     }
    153     if (_hashPtr != NULL) {
    154         Tcl_DeleteHashEntry(_hashPtr);
    155     }
    156     Rappture::FreeSwitches(_switches, &_sv, 0);
    157 }
    158 
    159 void
    160 FlowParticles::render()
    161 {
    162     TRACE("Particles '%s' axis: %d pos: %g rel pos: %g",
    163           _name, _sv.position.axis, _sv.position.value,
    164           FlowCmd::getRelativePosition(&_sv.position));
    165     _rendererPtr->setPos(FlowCmd::getRelativePosition(&_sv.position));
    166     _rendererPtr->setAxis(_sv.position.axis);
    167     assert(_rendererPtr->active());
    168     _rendererPtr->render();
    169 }
    170 
    171 void
    172 FlowParticles::configure()
    173 {
    174     _rendererPtr->setPos(FlowCmd::getRelativePosition(&_sv.position));
    175     _rendererPtr->setColor(Vector4f(_sv.color.r, _sv.color.g, _sv.color.b,
    176                                     _sv.color.a));
    177     _rendererPtr->particleSize(_sv.particleSize);
    178     _rendererPtr->setAxis(_sv.position.axis);
    179     _rendererPtr->active(!_sv.isHidden);
    180 }
    181 
    182 FlowBox::FlowBox(const char *name, Tcl_HashEntry *hPtr)
    183 {
    184     _name = name;
    185     _hashPtr = hPtr;
    186     _sv.isHidden = false;
    187     _sv.corner1.x = 0.0f;
    188     _sv.corner1.y = 0.0f;
    189     _sv.corner1.z = 0.0f;
    190     _sv.corner2.x = 1.0f;
    191     _sv.corner2.y = 1.0f;
    192     _sv.corner2.z = 1.0f;
    193     _sv.lineWidth = 1.2f;
    194     _sv.color.r = _sv.color.b = _sv.color.g = _sv.color.a = 1.0f;
    195 }
    196 
    197 void
    198 FlowBox::getWorldSpaceBounds(Vector3f& bboxMin,
    199                              Vector3f& bboxMax,
    200                              const Volume *vol) const
    201 {
    202     bboxMin.set(FLT_MAX, FLT_MAX, FLT_MAX);
    203     bboxMax.set(-FLT_MAX, -FLT_MAX, -FLT_MAX);
    204 
    205     Vector3f origin = vol->location();
    206     Vector3f scale = vol->getPhysicalScaling();
    207 
    208     Matrix4x4d mat;
    209     mat.makeTranslation(origin);
    210     Matrix4x4d mat2;
    211     mat2.makeScale(scale);
    212 
    213     mat.multiply(mat2);
    214 
    215     Vector3f min, max;
    216     min.x = vol->xAxis.min();
    217     min.y = vol->yAxis.min();
    218     min.z = vol->zAxis.min();
    219     max.x = vol->xAxis.max();
    220     max.y = vol->yAxis.max();
    221     max.z = vol->zAxis.max();
    222 
    223     float x0, y0, z0, x1, y1, z1;
    224     x0 = y0 = z0 = 0.0f;
    225     x1 = y1 = z1 = 0.0f;
    226     if (max.x > min.x) {
    227         x0 = (_sv.corner1.x - min.x) / (max.x - min.x);
    228         x1 = (_sv.corner2.x - min.x) / (max.x - min.x);
    229     }
    230     if (max.y > min.y) {
    231         y0 = (_sv.corner1.y - min.y) / (max.y - min.y);
    232         y1 = (_sv.corner2.y - min.y) / (max.y - min.y);
    233     }
    234     if (max.z > min.z) {
    235         z0 = (_sv.corner1.z - min.z) / (max.z - min.z);
    236         z1 = (_sv.corner2.z - min.z) / (max.z - min.z);
    237     }
    238 
    239     TRACE("Box model bounds: (%g,%g,%g) - (%g,%g,%g)",
    240           x0, y0, z0, x1, y1, z1);
    241 
    242     Vector3f modelMin(x0, y0, z0);
    243     Vector3f modelMax(x1, y1, z1);
    244 
    245     Vector4f bvert[8];
    246     bvert[0] = Vector4f(modelMin.x, modelMin.y, modelMin.z, 1);
    247     bvert[1] = Vector4f(modelMax.x, modelMin.y, modelMin.z, 1);
    248     bvert[2] = Vector4f(modelMin.x, modelMax.y, modelMin.z, 1);
    249     bvert[3] = Vector4f(modelMin.x, modelMin.y, modelMax.z, 1);
    250     bvert[4] = Vector4f(modelMax.x, modelMax.y, modelMin.z, 1);
    251     bvert[5] = Vector4f(modelMax.x, modelMin.y, modelMax.z, 1);
    252     bvert[6] = Vector4f(modelMin.x, modelMax.y, modelMax.z, 1);
    253     bvert[7] = Vector4f(modelMax.x, modelMax.y, modelMax.z, 1);
    254 
    255     for (int i = 0; i < 8; i++) {
    256         Vector4f worldVert = mat.transform(bvert[i]);
    257         if (worldVert.x < bboxMin.x) bboxMin.x = worldVert.x;
    258         if (worldVert.x > bboxMax.x) bboxMax.x = worldVert.x;
    259         if (worldVert.y < bboxMin.y) bboxMin.y = worldVert.y;
    260         if (worldVert.y > bboxMax.y) bboxMax.y = worldVert.y;
    261         if (worldVert.z < bboxMin.z) bboxMin.z = worldVert.z;
    262         if (worldVert.z > bboxMax.z) bboxMax.z = worldVert.z;
    263     }
    264 
    265     TRACE("Box world bounds: (%g,%g,%g) - (%g,%g,%g)",
    266           bboxMin.x, bboxMin.y, bboxMin.z,
    267           bboxMax.x, bboxMax.y, bboxMax.z);
    268 }
    269 
    270 void
    271 FlowBox::render(Volume *vol)
    272 {
    273     TRACE("Box: '%s'", _name);
    274 
    275     glPushAttrib(GL_ENABLE_BIT);
    276 
    277     glEnable(GL_DEPTH_TEST);
    278     glDisable(GL_TEXTURE_2D);
    279     glDisable(GL_BLEND);
    280 
    281     glMatrixMode(GL_MODELVIEW);
    282     glPushMatrix();
    283 
    284     Vector3f origin = vol->location();
    285     glTranslatef(origin.x, origin.y, origin.z);
    286 
    287     Vector3f scale = vol->getPhysicalScaling();
    288     glScalef(scale.x, scale.y, scale.z);
    289 
    290     Vector3f min, max;
    291     min.x = vol->xAxis.min();
    292     min.y = vol->yAxis.min();
    293     min.z = vol->zAxis.min();
    294     max.x = vol->xAxis.max();
    295     max.y = vol->yAxis.max();
    296     max.z = vol->zAxis.max();
    297 
    298     TRACE("box is %g,%g %g,%g %g,%g",
    299           _sv.corner1.x, _sv.corner2.x,
    300           _sv.corner1.y, _sv.corner2.y,
    301           _sv.corner1.z, _sv.corner2.z);
    302     TRACE("world is %g,%g %g,%g %g,%g",
    303           min.x, max.x, min.y, max.y, min.z, max.z);
    304 
    305     float x0, y0, z0, x1, y1, z1;
    306     x0 = y0 = z0 = 0.0f;
    307     x1 = y1 = z1 = 0.0f;
    308     if (max.x > min.x) {
    309         x0 = (_sv.corner1.x - min.x) / (max.x - min.x);
    310         x1 = (_sv.corner2.x - min.x) / (max.x - min.x);
    311     }
    312     if (max.y > min.y) {
    313         y0 = (_sv.corner1.y - min.y) / (max.y - min.y);
    314         y1 = (_sv.corner2.y - min.y) / (max.y - min.y);
    315     }
    316     if (max.z > min.z) {
    317         z0 = (_sv.corner1.z - min.z) / (max.z - min.z);
    318         z1 = (_sv.corner2.z - min.z) / (max.z - min.z);
    319     }
    320     TRACE("box bounds: %g,%g %g,%g %g,%g",
    321           x0, x1, y0, y1, z0, z1);
    322 
    323     glColor4d(_sv.color.r, _sv.color.g, _sv.color.b, _sv.color.a);
    324     glLineWidth(_sv.lineWidth);
    325     glBegin(GL_LINE_LOOP);
    326     {
    327         glVertex3d(x0, y0, z0);
    328         glVertex3d(x1, y0, z0);
    329         glVertex3d(x1, y1, z0);
    330         glVertex3d(x0, y1, z0);
    331     }
    332     glEnd();
    333     glBegin(GL_LINE_LOOP);
    334     {
    335         glVertex3d(x0, y0, z1);
    336         glVertex3d(x1, y0, z1);
    337         glVertex3d(x1, y1, z1);
    338         glVertex3d(x0, y1, z1);
    339     }
    340     glEnd();
    341    
    342     glBegin(GL_LINE_LOOP);
    343     {
    344         glVertex3d(x0, y0, z0);
    345         glVertex3d(x0, y0, z1);
    346         glVertex3d(x0, y1, z1);
    347         glVertex3d(x0, y1, z0);
    348     }
    349     glEnd();
    350    
    351     glBegin(GL_LINE_LOOP);
    352     {
    353         glVertex3d(x1, y0, z0);
    354         glVertex3d(x1, y0, z1);
    355         glVertex3d(x1, y1, z1);
    356         glVertex3d(x1, y1, z0);
    357     }
    358     glEnd();
    359 
    360     glPopMatrix();
    361     glPopAttrib();
    362 
    363     assert(CheckGL(AT));
    364 }
    365 
    366 FlowCmd::FlowCmd(Tcl_Interp *interp, const char *name, Tcl_HashEntry *hPtr) :
    367     _interp(interp),
    368     _hashPtr(hPtr),
    369     _name(name),
    370     _dataPtr(NULL),
    371     _volPtr(NULL),
    372     _fieldPtr(NULL)
     136    _data(NULL),
     137    _volume(NULL),
     138    _field(NULL)
    373139{
    374140    memset(&_sv, 0, sizeof(FlowValues));
    375141    _sv.sliceVisible = 1;
    376     _sv.tfPtr = NanoVis::getTransfunc("default");
    377 
    378     Tcl_InitHashTable(&_particlesTable, TCL_STRING_KEYS);
    379     Tcl_InitHashTable(&_boxTable, TCL_STRING_KEYS);
    380 
    381     _cmdToken = Tcl_CreateObjCommand(_interp, (char *)_name,
     142    _sv.transferFunction = NanoVis::getTransferFunction("default");
     143
     144    _cmdToken = Tcl_CreateObjCommand(_interp, (char *)name,
    382145                                     (Tcl_ObjCmdProc *)FlowInstObjCmd,
    383146                                     this, FlowInstDeleteProc);
     
    386149FlowCmd::~FlowCmd()
    387150{
     151    TRACE("Enter");
     152
    388153    Rappture::FreeSwitches(_switches, &_sv, 0);
    389     if (_hashPtr != NULL) {
    390         Tcl_DeleteHashEntry(_hashPtr);
    391     }
    392     if (_fieldPtr != NULL) {
    393         delete _fieldPtr;
    394     }
    395     if (_dataPtr != NULL) {
    396         delete _dataPtr;
    397     }
    398     if (_volPtr != NULL) {
    399         NanoVis::removeVolume(_volPtr);
    400         _volPtr = NULL;
    401     }
    402 
    403     FlowBox *boxPtr;
    404     FlowBoxIterator boxIter;
    405     for (boxPtr = firstBox(&boxIter); boxPtr != NULL;
    406          boxPtr = nextBox(&boxIter)) {
    407         boxPtr->disconnect();
    408         delete boxPtr;
    409     }
    410     FlowParticles *particlesPtr;
    411     FlowParticlesIterator partIter;
    412     for (particlesPtr = firstParticles(&partIter); particlesPtr != NULL;
    413          particlesPtr = nextParticles(&partIter)) {
    414         particlesPtr->disconnect();
    415         delete particlesPtr;
    416     }
    417     Tcl_DeleteHashTable(&_particlesTable);
    418     Tcl_DeleteHashTable(&_boxTable);
     154    if (_field != NULL) {
     155        delete _field;
     156    }
     157    if (_data != NULL) {
     158        delete _data;
     159    }
     160    if (_volume != NULL) {
     161        NanoVis::removeVolume(_volume);
     162        _volume = NULL;
     163    }
     164    for (BoxHashmap::iterator itr = _boxTable.begin();
     165         itr != _boxTable.end(); ++itr) {
     166        delete itr->second;
     167    }
     168    _boxTable.clear();
     169    for (ParticlesHashmap::iterator itr = _particlesTable.begin();
     170         itr != _particlesTable.end(); ++itr) {
     171        delete itr->second;
     172    }
     173    _particlesTable.clear();
     174}
     175
     176void
     177FlowCmd::getBounds(Vector3f& min,
     178                   Vector3f& max,
     179                   bool onlyVisible)
     180{
     181    TRACE("Enter");
     182
     183    if (onlyVisible && !visible())
     184        return;
     185
     186#if 0  // Using volume bounds instead of these
     187    if (isDataLoaded()) {
     188        Vector3f umin, umax;
     189        Rappture::Unirect3d *unirect = data();
     190        unirect->getWorldSpaceBounds(umin, umax);
     191        if (min.x > umin.x) {
     192            min.x = umin.x;
     193        }
     194        if (max.x < umax.x) {
     195            max.x = umax.x;
     196        }
     197        if (min.y > umin.y) {
     198            min.y = umin.y;
     199        }
     200        if (max.y < umax.y) {
     201            max.y = umax.y;
     202        }
     203        if (min.z > umin.z) {
     204            min.z = umin.z;
     205        }
     206        if (max.z < umax.z) {
     207            max.z = umax.z;
     208        }
     209    }
     210#endif
     211    for (BoxHashmap::iterator itr = _boxTable.begin();
     212         itr != _boxTable.end(); ++itr) {
     213        FlowBox *box = itr->second;
     214        if (!onlyVisible || box->visible()) {
     215            Vector3f fbmin, fbmax;
     216            box->getWorldSpaceBounds(fbmin, fbmax,
     217                                     getVolume());
     218            if (min.x > fbmin.x) {
     219                min.x = fbmin.x;
     220            }
     221            if (max.x < fbmax.x) {
     222                max.x = fbmax.x;
     223            }
     224            if (min.y > fbmin.y) {
     225                min.y = fbmin.y;
     226            }
     227            if (max.y < fbmax.y) {
     228                max.y = fbmax.y;
     229            }
     230            if (min.z > fbmin.z) {
     231                min.z = fbmin.z;
     232            }
     233            if (max.z < fbmax.z) {
     234                max.z = fbmax.z;
     235            }
     236        }
     237    }
    419238}
    420239
     
    422241FlowCmd::resetParticles()
    423242{
    424     FlowParticlesIterator iter;
    425     for (FlowParticles *particlesPtr = firstParticles(&iter);
    426          particlesPtr != NULL;
    427          particlesPtr = nextParticles(&iter)) {
    428         particlesPtr->reset();
     243    for (ParticlesHashmap::iterator itr = _particlesTable.begin();
     244         itr != _particlesTable.end(); ++itr) {
     245        itr->second->reset();
    429246    }
    430247}
     
    435252    NvVectorField *fieldPtr = getVectorField();
    436253    fieldPtr->active(true);
    437     FlowParticlesIterator iter;
    438     for (FlowParticles *particlesPtr = firstParticles(&iter);
    439          particlesPtr != NULL;
    440          particlesPtr = nextParticles(&iter)) {
    441         if (particlesPtr->visible()) {
    442             particlesPtr->advect();
     254    for (ParticlesHashmap::iterator itr = _particlesTable.begin();
     255         itr != _particlesTable.end(); ++itr) {
     256        if (itr->second->visible()) {
     257            itr->second->advect();
    443258        }
    444259    }
     
    448263FlowCmd::render()
    449264{
    450     _fieldPtr->active(true);
    451     _fieldPtr->render();
    452     FlowParticlesIterator iter;
    453     for (FlowParticles *particlesPtr = firstParticles(&iter);
    454          particlesPtr != NULL;
    455          particlesPtr = nextParticles(&iter)) {
    456         if (particlesPtr->visible()) {
    457             particlesPtr->render();
     265    _field->active(true);
     266    _field->render();
     267    for (ParticlesHashmap::iterator itr = _particlesTable.begin();
     268         itr != _particlesTable.end(); ++itr) {
     269        if (itr->second->visible()) {
     270            itr->second->render();
    458271        }
    459272    }
     
    461274}
    462275
    463 int
    464 FlowCmd::createParticles(Tcl_Interp *interp, Tcl_Obj *objPtr)
    465 {
    466     Tcl_HashEntry *hPtr;
    467     int isNew;
    468     const char *particlesName = Tcl_GetString(objPtr);
    469     hPtr = Tcl_CreateHashEntry(&_particlesTable, particlesName, &isNew);
    470     if (!isNew) {
    471         Tcl_AppendResult(interp, "particle injection plane \"",
    472                          particlesName, "\" already exists.", (char *)NULL);
    473         return TCL_ERROR;
    474     }
    475     particlesName = Tcl_GetHashKey(&_particlesTable, hPtr);
    476     FlowParticles *particlesPtr;
    477     particlesPtr = new FlowParticles(particlesName, hPtr);
    478     if (particlesPtr == NULL) {
    479         Tcl_AppendResult(interp, "can't allocate particle injection plane",
    480                          (char *)NULL);
    481         Tcl_DeleteHashEntry(hPtr);
    482         return TCL_ERROR;
    483     }
    484     Tcl_SetHashValue(hPtr, particlesPtr);
    485     return TCL_OK;
    486 }
    487 
    488 int
    489 FlowCmd::getParticles(Tcl_Interp *interp, Tcl_Obj *objPtr,
    490                       FlowParticles **particlesPtrPtr)
    491 {
    492     Tcl_HashEntry *hPtr;
    493     hPtr = Tcl_FindHashEntry(&_particlesTable, Tcl_GetString(objPtr));
    494     if (hPtr == NULL) {
    495         if (interp != NULL) {
    496             Tcl_AppendResult(interp, "can't find a particle injection plane \"",
    497                              Tcl_GetString(objPtr), "\"", (char *)NULL);
    498         }
    499         return TCL_ERROR;
    500     }
    501     *particlesPtrPtr = (FlowParticles *)Tcl_GetHashValue(hPtr);
    502     return TCL_OK;
    503 }
    504 
    505276FlowParticles *
    506 FlowCmd::firstParticles(FlowParticlesIterator *iterPtr)
    507 {
    508     iterPtr->hashPtr = Tcl_FirstHashEntry(&_particlesTable,
    509                                           &iterPtr->hashSearch);
    510     if (iterPtr->hashPtr == NULL) {
     277FlowCmd::createParticles(const char *particlesName)
     278{
     279    ParticlesHashmap::iterator itr = _particlesTable.find(particlesName);
     280    if (itr != _particlesTable.end()) {
     281        TRACE("Deleting existing particle injection plane '%s'", particlesName);
     282        delete itr->second;
     283        _particlesTable.erase(itr);
     284    }
     285    FlowParticles *particles = new FlowParticles(particlesName);
     286    _particlesTable[particlesName] = particles;
     287    return particles;
     288}
     289
     290FlowParticles *
     291FlowCmd::getParticles(const char *particlesName)
     292{
     293    ParticlesHashmap::iterator itr;
     294    itr = _particlesTable.find(particlesName);
     295    if (itr == _particlesTable.end()) {
     296        TRACE("Can't find particle injection plane '%s' in '%s'", particlesName, name());
    511297        return NULL;
    512298    }
    513     return (FlowParticles *)Tcl_GetHashValue(iterPtr->hashPtr);
    514 }
    515 
    516 FlowParticles *
    517 FlowCmd::nextParticles(FlowParticlesIterator *iterPtr)
    518 {
    519     if (iterPtr->hashPtr == NULL) {
     299    return itr->second;
     300}
     301
     302void
     303FlowCmd::deleteParticles(const char *particlesName)
     304{
     305    ParticlesHashmap::iterator itr = _particlesTable.find(particlesName);
     306    if (itr == _particlesTable.end()) {
     307        TRACE("Can't find particle injection plane '%s' in '%s'", particlesName, name());
     308        return;
     309    }
     310    delete itr->second;
     311    _particlesTable.erase(itr);
     312}
     313
     314void
     315FlowCmd::getParticlesNames(std::vector<std::string>& names)
     316{
     317    for (ParticlesHashmap::iterator itr = _particlesTable.begin();
     318         itr != _particlesTable.end(); ++itr) {
     319        names.push_back(std::string(itr->second->name()));
     320    }
     321}
     322
     323FlowBox *
     324FlowCmd::createBox(const char *boxName)
     325{
     326    BoxHashmap::iterator itr = _boxTable.find(boxName);
     327    if (itr != _boxTable.end()) {
     328        TRACE("Deleting existing box '%s'", boxName);
     329        delete itr->second;
     330        _boxTable.erase(itr);
     331    }
     332    FlowBox *box = new FlowBox(boxName);
     333    _boxTable[boxName] = box;
     334    return box;
     335}
     336
     337FlowBox *
     338FlowCmd::getBox(const char *boxName)
     339{
     340    BoxHashmap::iterator itr = _boxTable.find(boxName);
     341    if (itr == _boxTable.end()) {
     342        TRACE("Can't find box '%s' in '%s'", boxName, name());
    520343        return NULL;
    521344    }
    522     iterPtr->hashPtr = Tcl_NextHashEntry(&iterPtr->hashSearch);
    523     if (iterPtr->hashPtr == NULL) {
    524         return NULL;
    525     }
    526     return (FlowParticles *)Tcl_GetHashValue(iterPtr->hashPtr);
    527 }
    528 
    529 int
    530 FlowCmd::createBox(Tcl_Interp *interp, Tcl_Obj *objPtr)
    531 {
    532     Tcl_HashEntry *hPtr;
    533     int isNew;
    534     hPtr = Tcl_CreateHashEntry(&_boxTable, Tcl_GetString(objPtr), &isNew);
    535     if (!isNew) {
    536         Tcl_AppendResult(interp, "box \"", Tcl_GetString(objPtr),
    537                          "\" already exists in flow \"", name(), "\"", (char *)NULL);
    538         return TCL_ERROR;
    539     }
    540     const char *boxName;
    541     boxName = Tcl_GetHashKey(&_boxTable, hPtr);
    542     FlowBox *boxPtr;
    543     boxPtr = new FlowBox(boxName, hPtr);
    544     if (boxPtr == NULL) {
    545         Tcl_AppendResult(interp, "can't allocate box \"", boxName, "\"",
    546                          (char *)NULL);
    547         Tcl_DeleteHashEntry(hPtr);
    548         return TCL_ERROR;
    549     }
    550     Tcl_SetHashValue(hPtr, boxPtr);
    551     return TCL_OK;
    552 }
    553 
    554 int
    555 FlowCmd::getBox(Tcl_Interp *interp, Tcl_Obj *objPtr, FlowBox **boxPtrPtr)
    556 {
    557     Tcl_HashEntry *hPtr;
    558     hPtr = Tcl_FindHashEntry(&_boxTable, Tcl_GetString(objPtr));
    559     if (hPtr == NULL) {
    560         if (interp != NULL) {
    561             Tcl_AppendResult(interp, "can't find a box \"",
    562                              Tcl_GetString(objPtr), "\" in flow \"", name(), "\"",
    563                              (char *)NULL);
    564         }
    565         return TCL_ERROR;
    566     }
    567     *boxPtrPtr = (FlowBox *)Tcl_GetHashValue(hPtr);
    568     return TCL_OK;
    569 }
    570 
    571 FlowBox *
    572 FlowCmd::firstBox(FlowBoxIterator *iterPtr)
    573 {
    574     iterPtr->hashPtr = Tcl_FirstHashEntry(&_boxTable, &iterPtr->hashSearch);
    575     if (iterPtr->hashPtr == NULL) {
    576         return NULL;
    577     }
    578     return (FlowBox *)Tcl_GetHashValue(iterPtr->hashPtr);
    579 }
    580 
    581 FlowBox *
    582 FlowCmd::nextBox(FlowBoxIterator *iterPtr)
    583 {
    584     if (iterPtr->hashPtr == NULL) {
    585         return NULL;
    586     }
    587     iterPtr->hashPtr = Tcl_NextHashEntry(&iterPtr->hashSearch);
    588     if (iterPtr->hashPtr == NULL) {
    589         return NULL;
    590     }
    591     return (FlowBox *)Tcl_GetHashValue(iterPtr->hashPtr);
     345    return itr->second;
     346}
     347
     348void
     349FlowCmd::deleteBox(const char *boxName)
     350{
     351    BoxHashmap::iterator itr = _boxTable.find(boxName);
     352    if (itr == _boxTable.end()) {
     353        TRACE("Can't find box '%s' in '%s'", boxName, name());
     354        return;
     355    }
     356    delete itr->second;
     357    _boxTable.erase(itr);
     358}
     359
     360void FlowCmd::getBoxNames(std::vector<std::string>& names)
     361{
     362    for (BoxHashmap::iterator itr = _boxTable.begin();
     363         itr != _boxTable.end(); ++itr) {
     364        names.push_back(std::string(itr->second->name()));
     365    }
    592366}
    593367
     
    595369FlowCmd::initializeParticles()
    596370{
    597     FlowParticlesIterator iter;
    598     for (FlowParticles *particlesPtr = firstParticles(&iter);
    599          particlesPtr != NULL;
    600          particlesPtr = nextParticles(&iter)) {
    601         particlesPtr->initialize();
     371    for (ParticlesHashmap::iterator itr = _particlesTable.begin();
     372         itr != _particlesTable.end(); ++itr) {
     373        itr->second->initialize();
    602374    }
    603375}
     
    606378FlowCmd::scaleVectorField()
    607379{
    608     if (_volPtr != NULL) {
    609         TRACE("Removing existing volume: %s", _volPtr->name());
    610         NanoVis::removeVolume(_volPtr);
    611         _volPtr = NULL;
    612     }
    613     float *vdata;
    614     vdata = getScaledVector();
     380    if (_volume != NULL) {
     381        TRACE("Removing existing volume: %s", _volume->name());
     382        NanoVis::removeVolume(_volume);
     383        _volume = NULL;
     384    }
     385    float *vdata = getScaledVector();
    615386    if (vdata == NULL) {
    616387        return false;
    617388    }
    618     Volume *volPtr;
    619     volPtr = makeVolume(vdata);
     389    Volume *volume = makeVolume(vdata);
    620390    delete [] vdata;
    621     if (volPtr == NULL) {
     391    if (volume == NULL) {
    622392        return false;
    623393    }
    624     _volPtr = volPtr;
     394    _volume = volume;
    625395
    626396    // Remove the associated vector field.
    627     if (_fieldPtr != NULL) {
    628         delete _fieldPtr;
    629     }
    630     _fieldPtr = new NvVectorField();
    631     if (_fieldPtr == NULL) {
     397    if (_field != NULL) {
     398        delete _field;
     399    }
     400    _field = new NvVectorField();
     401    if (_field == NULL) {
    632402        return false;
    633403    }
    634404
    635     Vector3f scale = volPtr->getPhysicalScaling();
    636     Vector3f location = _volPtr->location();
    637 
    638     _fieldPtr->setVectorField(_volPtr,
    639                               location,
    640                               scale.x,
    641                               scale.y,
    642                               scale.z,
    643                               NanoVis::magMax);
    644 
    645     if (NanoVis::licRenderer != NULL) {
    646         NanoVis::licRenderer->
    647             setVectorField(_volPtr->textureID(),
     405    Vector3f scale = volume->getPhysicalScaling();
     406    Vector3f location = _volume->location();
     407
     408    _field->setVectorField(_volume,
    648409                           location,
    649410                           scale.x,
    650411                           scale.y,
    651412                           scale.z,
    652                            _volPtr->wAxis.max());
    653         setCurrentPosition();
    654         setAxis();
    655         setActive();
    656     }
    657 
    658     if (NanoVis::velocityArrowsSlice != NULL) {
    659         NanoVis::velocityArrowsSlice->
    660             setVectorField(_volPtr->textureID(),
     413                           NanoVis::magMax);
     414
     415    if (NanoVis::licRenderer != NULL) {
     416        NanoVis::licRenderer->
     417            setVectorField(_volume->textureID(),
    661418                           location,
    662419                           scale.x,
    663420                           scale.y,
    664421                           scale.z,
    665                            _volPtr->wAxis.max());
     422                           _volume->wAxis.max());
     423        setCurrentPosition();
     424        setAxis();
     425        setActive();
     426    }
     427
     428    if (NanoVis::velocityArrowsSlice != NULL) {
     429        NanoVis::velocityArrowsSlice->
     430            setVectorField(_volume->textureID(),
     431                           location,
     432                           scale.x,
     433                           scale.y,
     434                           scale.z,
     435                           _volume->wAxis.max());
    666436        NanoVis::velocityArrowsSlice->axis(_sv.slicePos.axis);
    667437        NanoVis::velocityArrowsSlice->slicePos(_sv.slicePos.value);
     
    669439    }
    670440
    671     FlowParticlesIterator partIter;
    672     for (FlowParticles *particlesPtr = firstParticles(&partIter);
    673          particlesPtr != NULL;
    674          particlesPtr = nextParticles(&partIter)) {
    675         particlesPtr->setVectorField(_volPtr,
    676                                      location,
    677                                      scale.x,
    678                                      scale.y,
    679                                      scale.z,
    680                                      _volPtr->wAxis.max());
     441    for (ParticlesHashmap::iterator itr = _particlesTable.begin();
     442         itr != _particlesTable.end(); ++itr) {
     443        itr->second->setVectorField(_volume,
     444                                    location,
     445                                    scale.x,
     446                                    scale.y,
     447                                    scale.z,
     448                                    _volume->wAxis.max());
    681449    }
    682450    return true;
     
    686454FlowCmd::renderBoxes()
    687455{
    688     FlowBoxIterator iter;
    689     FlowBox *boxPtr;
    690     for (boxPtr = firstBox(&iter); boxPtr != NULL; boxPtr = nextBox(&iter)) {
    691         if (boxPtr->visible()) {
    692             boxPtr->render(_volPtr);
     456    for (BoxHashmap::iterator itr = _boxTable.begin();
     457         itr != _boxTable.end(); ++itr) {
     458        if (itr->second->visible()) {
     459            itr->second->render(_volume);
    693460        }
    694461    }
     
    698465FlowCmd::getScaledVector()
    699466{
    700     assert(_dataPtr->nComponents() == 3);
    701     size_t n = _dataPtr->nValues() / _dataPtr->nComponents() * 4;
     467    assert(_data->nComponents() == 3);
     468    size_t n = _data->nValues() / _data->nComponents() * 4;
    702469    float *data = new float[n];
    703470    if (data == NULL) {
     
    706473    memset(data, 0, sizeof(float) * n);
    707474    float *destPtr = data;
    708     const float *values = _dataPtr->values();
    709     for (size_t iz = 0; iz < _dataPtr->zNum(); iz++) {
    710         for (size_t iy = 0; iy < _dataPtr->yNum(); iy++) {
    711             for (size_t ix = 0; ix < _dataPtr->xNum(); ix++) {
     475    const float *values = _data->values();
     476    for (size_t iz = 0; iz < _data->zNum(); iz++) {
     477        for (size_t iy = 0; iy < _data->yNum(); iy++) {
     478            for (size_t ix = 0; ix < _data->xNum(); ix++) {
    712479                double vx, vy, vz, vm;
    713480                vx = values[0];
     
    730497FlowCmd::makeVolume(float *data)
    731498{
    732     Volume *volPtr;
    733 
    734     volPtr = NanoVis::loadVolume(_name,
    735                                  _dataPtr->xNum(),
    736                                  _dataPtr->yNum(),
    737                                  _dataPtr->zNum(),
    738                                  4, data,
    739                                  NanoVis::magMin, NanoVis::magMax, 0);
    740     volPtr->xAxis.setRange(_dataPtr->xMin(), _dataPtr->xMax());
    741     volPtr->yAxis.setRange(_dataPtr->yMin(), _dataPtr->yMax());
    742     volPtr->zAxis.setRange(_dataPtr->zMin(), _dataPtr->zMax());
     499    Volume *volume =
     500        NanoVis::loadVolume(_name.c_str(),
     501                            _data->xNum(),
     502                            _data->yNum(),
     503                            _data->zNum(),
     504                            4, data,
     505                            NanoVis::magMin, NanoVis::magMax, 0);
     506    volume->xAxis.setRange(_data->xMin(), _data->xMax());
     507    volume->yAxis.setRange(_data->yMin(), _data->yMax());
     508    volume->zAxis.setRange(_data->zMin(), _data->zMax());
    743509
    744510    TRACE("min=%g %g %g max=%g %g %g mag=%g %g",
     
    747513          NanoVis::magMin, NanoVis::magMax);
    748514
    749     volPtr->disableCutplane(0);
    750     volPtr->disableCutplane(1);
    751     volPtr->disableCutplane(2);
     515    volume->disableCutplane(0);
     516    volume->disableCutplane(1);
     517    volume->disableCutplane(2);
    752518
    753519    /* Initialize the volume with the previously configured values. */
    754     volPtr->transferFunction(_sv.tfPtr);
    755     volPtr->dataEnabled(_sv.showVolume);
    756     volPtr->twoSidedLighting(_sv.twoSidedLighting);
    757     volPtr->outline(_sv.showOutline);
    758     volPtr->opacityScale(_sv.opacity);
    759     volPtr->ambient(_sv.ambient);
    760     volPtr->diffuse(_sv.diffuse);
    761     volPtr->specularLevel(_sv.specular);
    762     volPtr->specularExponent(_sv.specularExp);
    763     volPtr->visible(_sv.showVolume);
    764 
    765     Vector3f volScaling = volPtr->getPhysicalScaling();
     520    volume->transferFunction(_sv.transferFunction);
     521    volume->dataEnabled(_sv.showVolume);
     522    volume->twoSidedLighting(_sv.twoSidedLighting);
     523    volume->outline(_sv.showOutline);
     524    volume->opacityScale(_sv.opacity);
     525    volume->ambient(_sv.ambient);
     526    volume->diffuse(_sv.diffuse);
     527    volume->specularLevel(_sv.specular);
     528    volume->specularExponent(_sv.specularExp);
     529    volume->visible(_sv.showVolume);
     530
     531    Vector3f volScaling = volume->getPhysicalScaling();
    766532    Vector3f loc(volScaling);
    767533    loc *= -0.5;
    768     volPtr->location(loc);
     534    volume->location(loc);
    769535
    770536    Volume::updatePending = true;
    771     return volPtr;
     537    return volume;
    772538}
    773539
     
    996762/* Static NanoVis class commands. */
    997763
     764FlowCmd *
     765NanoVis::getFlow(const char *name)
     766{
     767    FlowHashmap::iterator itr = flowTable.find(name);
     768    if (itr == flowTable.end()) {
     769        TRACE("Can't find flow '%s'", name);
     770        return NULL;
     771    }
     772    return itr->second;
     773}
     774
     775FlowCmd *
     776NanoVis::createFlow(Tcl_Interp *interp, const char *name)
     777{
     778    FlowHashmap::iterator itr = flowTable.find(name);
     779    if (itr != flowTable.end()) {
     780        ERROR("Flow '%s' already exists", name);
     781        return NULL;
     782    }
     783    FlowCmd *flow = new FlowCmd(interp, name);
     784    flowTable[name] = flow;
     785    return flow;
     786}
     787
     788/**
     789 * \brief Delete flow object and hash table entry
     790 *
     791 * This is called by the flow command instance delete callback
     792 */
    998793void
    999 NanoVis::initFlows()
    1000 {
    1001     Tcl_InitHashTable(&flowTable, TCL_STRING_KEYS);
    1002 }
    1003 
    1004 FlowCmd *
    1005 NanoVis::firstFlow(FlowIterator *iterPtr)
    1006 {
    1007     iterPtr->hashPtr = Tcl_FirstHashEntry(&flowTable, &iterPtr->hashSearch);
    1008     if (iterPtr->hashPtr == NULL) {
    1009         return NULL;
    1010     }
    1011     return (FlowCmd *)Tcl_GetHashValue(iterPtr->hashPtr);
    1012 }
    1013 
    1014 FlowCmd *
    1015 NanoVis::nextFlow(FlowIterator *iterPtr)
    1016 {
    1017     if (iterPtr->hashPtr == NULL) {
    1018         return NULL;
    1019     }
    1020     iterPtr->hashPtr = Tcl_NextHashEntry(&iterPtr->hashSearch);
    1021     if (iterPtr->hashPtr == NULL) {
    1022         return NULL;
    1023     }
    1024     return (FlowCmd *)Tcl_GetHashValue(iterPtr->hashPtr);
    1025 }
    1026 
    1027 int
    1028 NanoVis::getFlow(Tcl_Interp *interp, Tcl_Obj *objPtr, FlowCmd **flowPtrPtr)
    1029 {
    1030     Tcl_HashEntry *hPtr;
    1031     hPtr = Tcl_FindHashEntry(&flowTable, Tcl_GetString(objPtr));
    1032     if (hPtr == NULL) {
    1033         if (interp != NULL) {
    1034             Tcl_AppendResult(interp, "can't find a flow \"",
    1035                              Tcl_GetString(objPtr), "\"", (char *)NULL);
    1036         }
    1037         return TCL_ERROR;
    1038     }
    1039     *flowPtrPtr = (FlowCmd *)Tcl_GetHashValue(hPtr);
    1040     return TCL_OK;
    1041 }
    1042 
    1043 int
    1044 NanoVis::createFlow(Tcl_Interp *interp, Tcl_Obj *objPtr)
    1045 {
    1046     Tcl_HashEntry *hPtr;
    1047     int isNew;
    1048     const char *name;
    1049     name = Tcl_GetString(objPtr);
    1050     hPtr = Tcl_CreateHashEntry(&flowTable, name, &isNew);
    1051     if (!isNew) {
    1052         Tcl_AppendResult(interp, "flow \"", name, "\" already exists.",
    1053                          (char *)NULL);
    1054         return TCL_ERROR;
    1055     }
    1056     Tcl_CmdInfo cmdInfo;
    1057     if (Tcl_GetCommandInfo(interp, name, &cmdInfo)) {
    1058         Tcl_AppendResult(interp, "an another command \"", name,
    1059                          "\" already exists.", (char *)NULL);
    1060         return TCL_ERROR;
    1061     }
    1062     FlowCmd *flowPtr;
    1063     name = Tcl_GetHashKey(&flowTable, hPtr);
    1064     flowPtr = new FlowCmd(interp, name, hPtr);
    1065     if (flowPtr == NULL) {
    1066         Tcl_AppendResult(interp, "can't allocate a flow object \"", name,
    1067                          "\"", (char *)NULL);
    1068         return TCL_ERROR;
    1069     }
    1070     Tcl_SetHashValue(hPtr, flowPtr);
    1071     return TCL_OK;
    1072 }
    1073 
     794NanoVis::deleteFlow(const char *name)
     795{
     796    FlowHashmap::iterator itr = flowTable.find(name);
     797    if (itr != flowTable.end()) {
     798        delete itr->second;
     799        flowTable.erase(itr);
     800    }
     801}
     802
     803/**
     804 * \brief Delete all flow object commands
     805 *
     806 * This will also delete the flow objects and hash table entries
     807 */
    1074808void
    1075809NanoVis::deleteFlows(Tcl_Interp *interp)
    1076810{
    1077     FlowCmd *flowPtr;
    1078     FlowIterator iter;
    1079     for (flowPtr = firstFlow(&iter); flowPtr != NULL;
    1080          flowPtr = nextFlow(&iter)) {
    1081         flowPtr->disconnect();                /* Don't disrupt the hash walk */
    1082         Tcl_DeleteCommand(interp, flowPtr->name());
    1083     }
    1084     Tcl_DeleteHashTable(&flowTable);
     811    FlowHashmap::iterator itr;
     812    for (itr = flowTable.begin();
     813         itr != flowTable.end(); ++itr) {
     814        Tcl_DeleteCommandFromToken(interp, itr->second->getCommandToken());
     815    }
     816    flowTable.clear();
    1085817}
    1086818
     
    1098830    magMin = DBL_MAX, magMax = -DBL_MAX;
    1099831
    1100     FlowCmd *flowPtr;
    1101     FlowIterator iter;
    1102     for (flowPtr = firstFlow(&iter); flowPtr != NULL;
    1103          flowPtr = nextFlow(&iter)) {
     832    for (FlowHashmap::iterator itr = flowTable.begin();
     833         itr != flowTable.end(); ++itr) {
     834        FlowCmd *flow = itr->second;
    1104835        double min, max;
    1105         if (!flowPtr->isDataLoaded()) {
     836        if (!flow->isDataLoaded()) {
    1106837            continue;
    1107838        }
    1108         Rappture::Unirect3d *dataPtr = flowPtr->data();
    1109         min = dataPtr->magMin();
    1110         max = dataPtr->magMax();
     839        Rappture::Unirect3d *data = flow->data();
     840        min = data->magMin();
     841        max = data->magMax();
    1111842        if (min < magMin) {
    1112843            magMin = min;
     
    1115846            magMax = max;
    1116847        }
    1117         if (dataPtr->xMin() < xMin) {
    1118             xMin = dataPtr->xMin();
    1119         }
    1120         if (dataPtr->yMin() < yMin) {
    1121             yMin = dataPtr->yMin();
    1122         }
    1123         if (dataPtr->zMin() < zMin) {
    1124             zMin = dataPtr->zMin();
    1125         }
    1126         if (dataPtr->xMax() > xMax) {
    1127             xMax = dataPtr->xMax();
    1128         }
    1129         if (dataPtr->yMax() > yMax) {
    1130             yMax = dataPtr->yMax();
    1131         }
    1132         if (dataPtr->zMax() > zMax) {
    1133             zMax = dataPtr->zMax();
     848        if (data->xMin() < xMin) {
     849            xMin = data->xMin();
     850        }
     851        if (data->yMin() < yMin) {
     852            yMin = data->yMin();
     853        }
     854        if (data->zMin() < zMin) {
     855            zMin = data->zMin();
     856        }
     857        if (data->xMax() > xMax) {
     858            xMax = data->xMax();
     859        }
     860        if (data->yMax() > yMax) {
     861            yMax = data->yMax();
     862        }
     863        if (data->zMax() > zMax) {
     864            zMax = data->zMax();
    1134865        }
    1135866    }
     
    1140871     * Step 2. Generate the vector field from each data set.
    1141872     */
    1142     for (flowPtr = firstFlow(&iter); flowPtr != NULL;
    1143          flowPtr = nextFlow(&iter)) {
    1144         if (!flowPtr->isDataLoaded()) {
     873    for (FlowHashmap::iterator itr = flowTable.begin();
     874         itr != flowTable.end(); ++itr) {
     875        FlowCmd *flow = itr->second;
     876        if (!flow->isDataLoaded()) {
    1145877            continue; // Flow exists, but no data has been loaded yet.
    1146878        }
    1147         if (flowPtr->visible()) {
    1148             flowPtr->initializeParticles();
    1149         }
    1150         if (!flowPtr->scaleVectorField()) {
     879        if (flow->visible()) {
     880            flow->initializeParticles();
     881        }
     882        if (!flow->scaleVectorField()) {
    1151883            return false;
    1152884        }
    1153885        // FIXME: This doesn't work when there is more than one flow.
    1154         licRenderer->setOffset(flowPtr->getRelativePosition());
    1155         velocityArrowsSlice->slicePos(flowPtr->getRelativePosition());
     886        licRenderer->setOffset(flow->getRelativePosition());
     887        velocityArrowsSlice->slicePos(flow->getRelativePosition());
    1156888    }
    1157889    advectFlows();
     
    1169901    max.set(-FLT_MAX, -FLT_MAX, -FLT_MAX);
    1170902
    1171     FlowCmd *flow;
    1172     FlowIterator iter;
    1173     for (flow = firstFlow(&iter); flow != NULL;
    1174          flow = nextFlow(&iter)) {
    1175         if (onlyVisible && !flow->visible())
    1176             continue;
    1177  #if 0  // Using volume bounds instead of these
    1178         if (flow->isDataLoaded()) {
    1179             Vector3f umin, umax;
    1180             Rappture::Unirect3d *unirect = flow->data();
    1181             unirect->getWorldSpaceBounds(umin, umax);
    1182             if (min.x > umin.x) {
    1183                 min.x = umin.x;
    1184             }
    1185             if (max.x < umax.x) {
    1186                 max.x = umax.x;
    1187             }
    1188             if (min.y > umin.y) {
    1189                 min.y = umin.y;
    1190             }
    1191             if (max.y < umax.y) {
    1192                 max.y = umax.y;
    1193             }
    1194             if (min.z > umin.z) {
    1195                 min.z = umin.z;
    1196             }
    1197             if (max.z < umax.z) {
    1198                 max.z = umax.z;
    1199             }
    1200         }
    1201 #endif
    1202         FlowBox *box;
    1203         FlowBoxIterator iter;
    1204         for (box = flow->firstBox(&iter); box != NULL;
    1205              box = flow->nextBox(&iter)) {
    1206             if (!onlyVisible || box->visible()) {
    1207                 Vector3f fbmin, fbmax;
    1208                 box->getWorldSpaceBounds(fbmin, fbmax,
    1209                                          flow->getVolume());
    1210                 if (min.x > fbmin.x) {
    1211                     min.x = fbmin.x;
    1212                 }
    1213                 if (max.x < fbmax.x) {
    1214                     max.x = fbmax.x;
    1215                 }
    1216                 if (min.y > fbmin.y) {
    1217                     min.y = fbmin.y;
    1218                 }
    1219                 if (max.y < fbmax.y) {
    1220                     max.y = fbmax.y;
    1221                 }
    1222                 if (min.z > fbmin.z) {
    1223                     min.z = fbmin.z;
    1224                 }
    1225                 if (max.z < fbmax.z) {
    1226                     max.z = fbmax.z;
    1227                 }
    1228             }
    1229         }
     903    for (FlowHashmap::iterator itr = flowTable.begin();
     904         itr != flowTable.end(); ++itr) {
     905        itr->second->getBounds(min, max, onlyVisible);
    1230906    }
    1231907}
     
    1234910NanoVis::renderFlows()
    1235911{
    1236     FlowCmd *flowPtr;
    1237     FlowIterator iter;
    1238     for (flowPtr = firstFlow(&iter); flowPtr != NULL;
    1239          flowPtr = nextFlow(&iter)) {
    1240         if ((flowPtr->isDataLoaded()) && (flowPtr->visible())) {
    1241             flowPtr->render();
     912    for (FlowHashmap::iterator itr = flowTable.begin();
     913         itr != flowTable.end(); ++itr) {
     914        FlowCmd *flow = itr->second;
     915        if (flow->isDataLoaded() && flow->visible()) {
     916            flow->render();
    1242917        }
    1243918    }
     
    1248923NanoVis::resetFlows()
    1249924{
    1250     FlowCmd *flowPtr;
    1251     FlowIterator iter;
    1252 
    1253925    if (licRenderer->active()) {
    1254926        NanoVis::licRenderer->reset();
    1255927    }
    1256     for (flowPtr = firstFlow(&iter); flowPtr != NULL;
    1257          flowPtr = nextFlow(&iter)) {
    1258         if ((flowPtr->isDataLoaded()) && (flowPtr->visible())) {
    1259             flowPtr->resetParticles();
     928    for (FlowHashmap::iterator itr = flowTable.begin();
     929         itr != flowTable.end(); ++itr) {
     930        FlowCmd *flow = itr->second;
     931        if (flow->isDataLoaded() && flow->visible()) {
     932            flow->resetParticles();
    1260933        }
    1261934    }
     
    1265938NanoVis::advectFlows()
    1266939{
    1267     FlowCmd *flowPtr;
    1268     FlowIterator iter;
    1269     for (flowPtr = firstFlow(&iter); flowPtr != NULL;
    1270          flowPtr = nextFlow(&iter)) {
    1271         if ((flowPtr->isDataLoaded()) && (flowPtr->visible())) {
    1272             flowPtr->advect();
     940    for (FlowHashmap::iterator itr = flowTable.begin();
     941         itr != flowTable.end(); ++itr) {
     942        FlowCmd *flow = itr->second;
     943        if (flow->isDataLoaded() && flow->visible()) {
     944            flow->advect();
    1273945        }
    1274946    }
     
    13391011    Tcl_Obj **objv;
    13401012    int objc;
    1341     FlowColor *colorPtr = (FlowColor *)(record + offset);
     1013    FlowColor *color = (FlowColor *)(record + offset);
    13421014
    13431015    if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
     
    13661038        values[i] = value;
    13671039    }
    1368     colorPtr->r = values[0];
    1369     colorPtr->g = values[1];
    1370     colorPtr->b = values[2];
    1371     colorPtr->a = values[3];
     1040    color->r = values[0];
     1041    color->g = values[1];
     1042    color->b = values[2];
     1043    color->a = values[3];
    13721044    return TCL_OK;
    13731045}
     
    13921064                char *record, int offset, int flags)
    13931065{
    1394     FlowPoint *pointPtr = (FlowPoint *)(record + offset);
     1066    FlowPoint *point = (FlowPoint *)(record + offset);
    13951067    int objc;
    13961068    Tcl_Obj **objv;
     
    14141086        values[i] = value;
    14151087    }
    1416     pointPtr->x = values[0];
    1417     pointPtr->y = values[1];
    1418     pointPtr->z = values[2];
     1088    point->x = values[0];
     1089    point->y = values[1];
     1090    point->z = values[2];
    14191091    return TCL_OK;
    14201092}
     
    14891161{
    14901162    TransferFunction **funcPtrPtr = (TransferFunction **)(record + offset);
    1491     TransferFunction *funcPtr;
    1492     funcPtr = NanoVis::getTransfunc(Tcl_GetString(objPtr));
    1493     if (funcPtr == NULL) {
     1163    TransferFunction *tf = NanoVis::getTransferFunction(Tcl_GetString(objPtr));
     1164    if (tf == NULL) {
    14941165        Tcl_AppendResult(interp, "transfer function \"", Tcl_GetString(objPtr),
    14951166                         "\" is not defined", (char*)NULL);
    14961167        return TCL_ERROR;
    14971168    }
    1498     *funcPtrPtr = funcPtr;
     1169    *funcPtrPtr = tf;
    14991170    return TCL_OK;
    15001171}
     
    15171188                   Tcl_Obj *const *objv)
    15181189{
    1519     FlowCmd *flowPtr = (FlowCmd *)clientData;
    1520 
    1521     if (flowPtr->createParticles(interp, objv[3]) != TCL_OK) {
    1522         return TCL_ERROR;
    1523     }
    1524     FlowParticles *particlesPtr;
    1525     if (flowPtr->getParticles(interp, objv[3], &particlesPtr) != TCL_OK) {
    1526         return TCL_ERROR;
    1527     }
    1528     if (particlesPtr->parseSwitches(interp, objc - 4, objv + 4) != TCL_OK) {
    1529         delete particlesPtr;
    1530         return TCL_ERROR;
    1531     }
    1532     particlesPtr->configure();
     1190    FlowCmd *flow = (FlowCmd *)clientData;
     1191    const char *particlesName = Tcl_GetString(objv[3]);
     1192    FlowParticles *particles = flow->createParticles(particlesName);
     1193    if (particles == NULL) {
     1194        Tcl_AppendResult(interp, "Flow particle injection plane \"",
     1195                         particlesName,
     1196                         "\" already exists or could not be created",
     1197                         (char*)NULL);
     1198        return TCL_ERROR;
     1199    }
     1200    if (particles->parseSwitches(interp, objc - 4, objv + 4) != TCL_OK) {
     1201        flow->deleteParticles(particlesName);
     1202        return TCL_ERROR;
     1203    }
     1204    particles->configure();
    15331205    NanoVis::eventuallyRedraw();
    15341206    Tcl_SetObjResult(interp, objv[3]);
     
    15401212                         Tcl_Obj *const *objv)
    15411213{
    1542     FlowCmd *flowPtr = (FlowCmd *)clientData;
    1543 
    1544     FlowParticles *particlesPtr;
    1545     if (flowPtr->getParticles(interp, objv[3], &particlesPtr) != TCL_OK) {
    1546         return TCL_ERROR;
    1547     }
    1548     if (particlesPtr->parseSwitches(interp, objc - 4, objv + 4) != TCL_OK) {
    1549         return TCL_ERROR;
    1550     }
    1551     particlesPtr->configure();
     1214    FlowCmd *flow = (FlowCmd *)clientData;
     1215    const char *particlesName = Tcl_GetString(objv[3]);
     1216    FlowParticles *particles = flow->getParticles(particlesName);
     1217    if (particles == NULL) {
     1218        Tcl_AppendResult(interp, "Flow particle injection plane \"",
     1219                         particlesName, "\" not found",
     1220                         (char*)NULL);
     1221        return TCL_ERROR;
     1222    }
     1223    if (particles->parseSwitches(interp, objc - 4, objv + 4) != TCL_OK) {
     1224        return TCL_ERROR;
     1225    }
     1226    particles->configure();
    15521227    NanoVis::eventuallyRedraw(NanoVis::MAP_FLOWS);
    15531228    return TCL_OK;
     
    15581233                      Tcl_Obj *const *objv)
    15591234{
    1560     FlowCmd *flowPtr = (FlowCmd *)clientData;
    1561     int i;
    1562     for (i = 3; i < objc; i++) {
    1563         FlowParticles *particlesPtr;
    1564 
    1565         if (flowPtr->getParticles(NULL, objv[i], &particlesPtr) == TCL_OK) {
    1566             delete particlesPtr;
    1567         }
     1235    FlowCmd *flow = (FlowCmd *)clientData;
     1236    for (int i = 3; i < objc; i++) {
     1237        flow->deleteParticles(Tcl_GetString(objv[i]));
    15681238    }
    15691239    NanoVis::eventuallyRedraw();
     
    15751245                     Tcl_Obj *const *objv)
    15761246{
    1577     FlowCmd *flowPtr = (FlowCmd *)clientData;
     1247    FlowCmd *flow = (FlowCmd *)clientData;
    15781248    Tcl_Obj *listObjPtr;
    15791249    listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
    1580     FlowParticlesIterator iter;
    1581     FlowParticles *particlesPtr;
    1582     for (particlesPtr = flowPtr->firstParticles(&iter); particlesPtr != NULL;
    1583          particlesPtr = flowPtr->nextParticles(&iter)) {
    1584         Tcl_Obj *objPtr;
    1585 
    1586         objPtr = Tcl_NewStringObj(particlesPtr->name(), -1);
     1250    std::vector<std::string> names;
     1251    flow->getParticlesNames(names);
     1252    for (std::vector<std::string>::iterator itr = names.begin();
     1253         itr != names.end(); ++itr) {
     1254        Tcl_Obj *objPtr = Tcl_NewStringObj(itr->c_str(), -1);
    15871255        Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
    15881256    }
     
    15941262    {"add",        1, FlowParticlesAddOp,        4, 0, "name ?switches?",},
    15951263    {"configure",  1, FlowParticlesConfigureOp,  4, 0, "name ?switches?",},
    1596     {"delete",     1, FlowParticlesDeleteOp,     4, 0, "?name...?"},
    1597     {"names",      1, FlowParticlesNamesOp,      3, 4, "?pattern?"},
     1264    {"delete",     1, FlowParticlesDeleteOp,     4, 0, "name ?name...?"},
     1265    {"names",      1, FlowParticlesNamesOp,      3, 3, ""},
    15981266};
    15991267
     
    16321300             Tcl_Obj *const *objv)
    16331301{
    1634     FlowCmd *flowPtr = (FlowCmd *)clientData;
    1635 
    1636     if (flowPtr->createBox(interp, objv[3]) != TCL_OK) {
    1637         return TCL_ERROR;
    1638     }
    1639     FlowBox *boxPtr;
    1640     if (flowPtr->getBox(interp, objv[3], &boxPtr) != TCL_OK) {
    1641         return TCL_ERROR;
    1642     }
    1643     if (boxPtr->parseSwitches(interp, objc - 4, objv + 4) != TCL_OK) {
    1644         delete boxPtr;
     1302    FlowCmd *flow = (FlowCmd *)clientData;
     1303    const char *boxName = Tcl_GetString(objv[3]);
     1304    FlowBox *box = flow->createBox(boxName);
     1305    if (box == NULL) {
     1306        Tcl_AppendResult(interp, "Flow box \"", boxName,
     1307                         "\" already exists or could not be created",
     1308                         (char*)NULL);
     1309        return TCL_ERROR;
     1310    }
     1311    if (box->parseSwitches(interp, objc - 4, objv + 4) != TCL_OK) {
     1312        flow->deleteBox(boxName);
    16451313        return TCL_ERROR;
    16461314    }
     
    16511319
    16521320static int
     1321FlowBoxConfigureOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1322                   Tcl_Obj *const *objv)
     1323{
     1324    FlowCmd *flow = (FlowCmd *)clientData;
     1325    const char *boxName = Tcl_GetString(objv[3]);
     1326    FlowBox *box = flow->getBox(boxName);
     1327    if (box == NULL) {
     1328        Tcl_AppendResult(interp, "Flow box \"", boxName, "\" not found",
     1329                         (char*)NULL);
     1330        return TCL_ERROR;
     1331    }
     1332    if (box->parseSwitches(interp, objc - 4, objv + 4) != TCL_OK) {
     1333        return TCL_ERROR;
     1334    }
     1335    NanoVis::eventuallyRedraw();
     1336    return TCL_OK;
     1337}
     1338
     1339static int
    16531340FlowBoxDeleteOp(ClientData clientData, Tcl_Interp *interp, int objc,
    16541341                Tcl_Obj *const *objv)
    16551342{
    1656     FlowCmd *flowPtr = (FlowCmd *)clientData;
    1657     int i;
    1658     for (i = 3; i < objc; i++) {
    1659         FlowBox *boxPtr;
    1660 
    1661         if (flowPtr->getBox(NULL, objv[i], &boxPtr) == TCL_OK) {
    1662             delete boxPtr;
    1663         }
     1343    FlowCmd *flow = (FlowCmd *)clientData;
     1344    for (int i = 3; i < objc; i++) {
     1345        flow->deleteBox(Tcl_GetString(objv[i]));
    16641346    }
    16651347    NanoVis::eventuallyRedraw();
     
    16711353               Tcl_Obj *const *objv)
    16721354{
    1673     FlowCmd *flowPtr = (FlowCmd *)clientData;
    1674     Tcl_Obj *listObjPtr;
    1675     listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
    1676     FlowBoxIterator iter;
    1677     FlowBox *boxPtr;
    1678     for (boxPtr = flowPtr->firstBox(&iter); boxPtr != NULL;
    1679          boxPtr = flowPtr->nextBox(&iter)) {
    1680         Tcl_Obj *objPtr;
    1681 
    1682         objPtr = Tcl_NewStringObj(boxPtr->name(), -1);
     1355    FlowCmd *flow = (FlowCmd *)clientData;
     1356    Tcl_Obj *listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
     1357    std::vector<std::string> names;
     1358    flow->getBoxNames(names);
     1359    for (std::vector<std::string>::iterator itr = names.begin();
     1360         itr != names.end(); ++itr) {
     1361        Tcl_Obj *objPtr = Tcl_NewStringObj(itr->c_str(), -1);
    16831362        Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
    16841363    }
    16851364    Tcl_SetObjResult(interp, listObjPtr);
    1686     return TCL_OK;
    1687 }
    1688 
    1689 static int
    1690 FlowBoxConfigureOp(ClientData clientData, Tcl_Interp *interp, int objc,
    1691                    Tcl_Obj *const *objv)
    1692 {
    1693     FlowCmd *flowPtr = (FlowCmd *)clientData;
    1694 
    1695     FlowBox *boxPtr;
    1696     if (flowPtr->getBox(interp, objv[3], &boxPtr) != TCL_OK) {
    1697         return TCL_ERROR;
    1698     }
    1699     if (boxPtr->parseSwitches(interp, objc - 4, objv + 4) != TCL_OK) {
    1700         return TCL_ERROR;
    1701     }
    1702     NanoVis::eventuallyRedraw();
    17031365    return TCL_OK;
    17041366}
     
    17071369    {"add",        1, FlowBoxAddOp,        4, 0, "name ?switches?",},
    17081370    {"configure",  1, FlowBoxConfigureOp,  4, 0, "name ?switches?",},
    1709     {"delete",     1, FlowBoxDeleteOp,     3, 0, "?name...?"},
    1710     {"names",      1, FlowBoxNamesOp,      3, 0, "?pattern?"},
     1371    {"delete",     1, FlowBoxDeleteOp,     4, 0, "name ?name...?"},
     1372    {"names",      1, FlowBoxNamesOp,      3, 3, ""},
    17111373};
    17121374
     
    18041466    }
    18051467    assert(CheckGL(AT));
    1806     FlowCmd *flowPtr = (FlowCmd *)clientData;
    1807     Tcl_Preserve(flowPtr);
    1808     int result;
    1809     result = (*proc) (clientData, interp, objc, objv);
    1810     Tcl_Release(flowPtr);
     1468    FlowCmd *flow = (FlowCmd *)clientData;
     1469    Tcl_Preserve(flow);
     1470    int result = (*proc) (clientData, interp, objc, objv);
     1471    Tcl_Release(flow);
    18111472    return result;
    18121473}
    18131474
    18141475/**
    1815  * \brief Deletes the command associated with the tree.
    1816  *
    1817  * This is called only when the command associated with the tree is destroyed.
     1476 * \brief Deletes the command associated with the flow
     1477 *
     1478 * This is called only when the command associated with the flow is destroyed.
    18181479 */
    18191480static void
    18201481FlowInstDeleteProc(ClientData clientData)
    18211482{
    1822     FlowCmd *flowPtr = (FlowCmd *)clientData;
    1823     delete flowPtr;
     1483    FlowCmd *flow = (FlowCmd *)clientData;
     1484    NanoVis::deleteFlow(flow->name());
    18241485}
    18251486
     
    18281489          Tcl_Obj *const *objv)
    18291490{
    1830     if (NanoVis::createFlow(interp, objv[2]) != TCL_OK) {
    1831         return TCL_ERROR;
    1832     }
    1833     FlowCmd *flowPtr;
    1834     if (NanoVis::getFlow(interp, objv[2], &flowPtr) != TCL_OK) {
    1835         return TCL_ERROR;
    1836     }
    1837     if (flowPtr->parseSwitches(interp, objc - 3, objv + 3) != TCL_OK) {
    1838         Tcl_DeleteCommand(interp, flowPtr->name());
     1491    const char *name = Tcl_GetString(objv[2]);
     1492    Tcl_CmdInfo cmdInfo;
     1493    if (Tcl_GetCommandInfo(interp, name, &cmdInfo)) {
     1494        Tcl_AppendResult(interp, "an another command \"", name,
     1495                         "\" already exists.", (char *)NULL);
     1496        return NULL;
     1497    }
     1498    FlowCmd *flow = NanoVis::createFlow(interp, name);
     1499    if (flow == NULL) {
     1500        Tcl_AppendResult(interp, "Flow \"", name, "\" already exists",
     1501                         (char*)NULL);
     1502        return TCL_ERROR;
     1503    }
     1504    if (flow->parseSwitches(interp, objc - 3, objv + 3) != TCL_OK) {
     1505        Tcl_DeleteCommand(interp, flow->name());
    18391506        return TCL_ERROR;
    18401507    }
     
    18481515             Tcl_Obj *const *objv)
    18491516{
    1850     int i;
    1851 
    1852     for (i = 2; i < objc; i++) {
    1853         FlowCmd *flowPtr;
    1854 
    1855         if (NanoVis::getFlow(interp, objv[i], &flowPtr) != TCL_OK) {
    1856             return TCL_ERROR;
    1857         }
    1858         Tcl_DeleteCommand(interp, flowPtr->name());
     1517    for (int i = 2; i < objc; i++) {
     1518        FlowCmd *flow = NanoVis::getFlow(Tcl_GetString(objv[i]));
     1519        if (flow != NULL) {
     1520            Tcl_DeleteCommandFromToken(interp, flow->getCommandToken());
     1521        }
    18591522    }
    18601523    NanoVis::eventuallyRedraw(NanoVis::MAP_FLOWS);
     
    18661529             Tcl_Obj *const *objv)
    18671530{
    1868     bool value;
    1869     FlowCmd *flowPtr;
    1870 
    1871     value = false;
    1872     if (NanoVis::getFlow(NULL, objv[2], &flowPtr) == TCL_OK) {
     1531    bool value = false;
     1532    FlowCmd *flow = NanoVis::getFlow(Tcl_GetString(objv[2]));
     1533    if (flow != NULL) {
    18731534        value = true;
    18741535    }
     
    18971558        NanoVis::mapFlows();
    18981559    }
    1899     int i;
    19001560    NanoVis::advectFlows();
    1901     for (i = 0; i < nSteps; i++) {
     1561    for (int i = 0; i < nSteps; i++) {
    19021562        if (NanoVis::licRenderer->active()) {
    19031563            NanoVis::licRenderer->convolve();
     
    19151575    Tcl_Obj *listObjPtr;
    19161576    listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
    1917     FlowCmd *flowPtr;
    1918     FlowIterator iter;
    1919     for (flowPtr = NanoVis::firstFlow(&iter); flowPtr != NULL;
    1920          flowPtr = NanoVis::nextFlow(&iter)) {
    1921         Tcl_Obj *objPtr;
    1922 
    1923         objPtr = Tcl_NewStringObj(flowPtr->name(), -1);
     1577    for (NanoVis::FlowHashmap::iterator itr = NanoVis::flowTable.begin();
     1578         itr != NanoVis::flowTable.end(); ++itr) {
     1579        FlowCmd *flow = itr->second;
     1580        Tcl_Obj *objPtr = Tcl_NewStringObj(flow->name(), -1);
    19241581        Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
    19251582    }
     
    22741931static Rappture::CmdSpec flowCmdOps[] = {
    22751932    {"add",      1, FlowAddOp,     3, 0, "name ?option value...?",},
    2276     {"delete",   1, FlowDeleteOp,  2, 0, "name...",},
     1933    {"delete",   1, FlowDeleteOp,  3, 0, "name ?name...?",},
    22771934    {"exists",   1, FlowExistsOp,  3, 3, "name",},
    22781935    {"goto",     1, FlowGotoOp,    3, 3, "nSteps",},
    2279     {"names",    1, FlowNamesOp,   2, 3, "?pattern?",},
     1936    {"names",    1, FlowNamesOp,   2, 2, "",},
    22801937    {"next",     2, FlowNextOp,    2, 2, "",},
    22811938    {"reset",    1, FlowResetOp,   2, 2, "",},
     
    22991956
    23001957/**
    2301  *\brief This procedure is invoked to initialize the "tree" command.
     1958 *\brief This procedure is invoked to initialize the "flow" command.
    23021959 *
    23031960 * Side effects:
     
    23091966{
    23101967    Tcl_CreateObjCommand(interp, "flow", FlowCmdProc, NULL, NULL);
    2311     NanoVis::initFlows();
    2312     return TCL_OK;
    2313 }
    2314 
    2315 #ifdef notdef
    2316 
    2317 // Read the header of a vtk data file. Returns 0 if error.
    2318 bool
    2319 VtkReadHeader()
    2320 {
    2321     char *p, *endPtr;
    2322 
    2323     line = getline(&p, endPtr);
    2324     if (line == endPtr) {
    2325         vtkErrorMacro(<<"Premature EOF reading first line! " << " for file: "
    2326                       << (this->FileName?this->FileName:"(Null FileName)"));
    2327         return false;
    2328     }
    2329     if (sscanf(line, "# vtk DataFile Version %s", version) != 1) {
    2330         vtkErrorMacro(<< "Unrecognized file type: "<< line << " for file: "
    2331                       << (this->FileName?this->FileName:"(Null FileName)"));
    2332         return false;
    2333     }
    2334 
    2335     // Read title
    2336     line = getline(&p, endPtr);
    2337     if (line == endPtr) {
    2338         vtkErrorMacro(<<"Premature EOF reading title! " << " for file: "
    2339                       << (this->FileName?this->FileName:"(Null FileName)"));
    2340         return false;
    2341     }
    2342     if (_title != NULL) {
    2343         delete [] _title;
    2344     }
    2345     _title = new char[strlen(line) + 1];
    2346     strcpy(_title, line);
    2347 
    2348     // Read type
    2349     line = getline(&p, endPtr);
    2350     if (line == endPtr) {
    2351         vtkErrorMacro(<<"Premature EOF reading file type!" << " for file: "
    2352                       << (this->FileName?this->FileName:"(Null FileName)"));
    2353         return false;
    2354     }
    2355     word = GetWord(line, &endPtr);
    2356     if (strncasecmp(word, "ascii", 5) == 0) {
    2357         _fileType = VTK_ASCII;
    2358     } else if (strcasecmp(word, "binary", 6) == 0) {
    2359         _fileType = VTK_BINARY;
    2360     } else {
    2361         vtkErrorMacro(<< "Unrecognized file type: "<< line << " for file: "
    2362                       << (this->FileName?this->FileName:"(Null FileName)"));
    2363         _fileType = 0;
    2364         return false;
    2365     }
    2366 
    2367     // Read dataset type
    2368     line = getline(&p, endPtr);
    2369     if (line == endPtr) {
    2370         vtkErrorMacro(<<"Premature EOF reading file type!" << " for file: "
    2371                       << (this->FileName?this->FileName:"(Null FileName)"));
    2372         return false;
    2373     }
    2374     word = GetWord(line, &endPtr);
    2375     if (strncasecmp(word, "dataset", 7) == 0) {
    2376         // Read dataset type
    2377         line = getline(&p, endPtr);
    2378         if (line == endPtr) {
    2379             // EOF
    2380         }
    2381         type = GetWord(line, &endPtr);
    2382         if (strncasecmp(word, "structured_grid", 15) == 0) {
    2383             vtkErrorMacro(<< "Cannot read dataset type: " << line);
    2384             return 1;
    2385         }
    2386         // Read keyword and dimensions
    2387         //
    2388         while (!done) {
    2389             if (!this->ReadString(line)) {
    2390                 break;
    2391             }
    2392 
    2393             // Have to read field data because it may be binary.
    2394             if (! strncmp(this->LowerCase(line), "field", 5)) {
    2395                 vtkFieldData* fd = this->ReadFieldData();
    2396                 fd->Delete();
    2397             }
    2398 
    2399             if ( ! strncmp(this->LowerCase(line),"dimensions",10) ) {
    2400                 int ext[6];
    2401                 if (!(this->Read(ext+1) &&
    2402                       this->Read(ext+3) &&
    2403                       this->Read(ext+5))) {
    2404                     vtkErrorMacro(<<"Error reading dimensions!");
    2405                     this->CloseVTKFile ();
    2406                     return 1;
    2407                 }
    2408                 // read dimensions, change to extent;
    2409                 ext[0] = ext[2] = ext[4] = 0;
    2410                 --ext[1];
    2411                 --ext[3];
    2412                 --ext[5];
    2413                 outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),
    2414                              ext, 6);
    2415                 // That is all we wanted !!!!!!!!!!!!!!!
    2416                 this->CloseVTKFile();
    2417                 return 1;
    2418             }
    2419         }
    2420     }
    2421 
    2422     float progress = this->GetProgress();
    2423     this->UpdateProgress(progress + 0.5*(1.0 - progress));
    2424 
    2425     return 1;
    2426 }
    2427 #endif
     1968    return TCL_OK;
     1969}
  • trunk/packages/vizservers/nanovis/FlowCmd.h

    r3566 r3567  
    2525#define FLOWCMD_H
    2626
     27#include <tr1/unordered_map>
     28#include <vector>
     29#include <string>
     30
    2731#include <tcl.h>
    2832
     
    3034
    3135#include "Switch.h"
     36#include "FlowTypes.h"
     37#include "FlowParticles.h"
     38#include "FlowBox.h"
    3239#include "NvLIC.h"
    3340#include "NvParticleRenderer.h"
     
    3542#include "Unirect.h"
    3643#include "Volume.h"
    37 
    38 struct FlowColor {
    39     float r, g, b, a;
    40 };
    41 
    42 struct FlowPosition {
    43     float value;
    44     unsigned int flags;
    45     int axis;
    46 };
    47 
    48 struct FlowPoint {
    49     float x, y, z;
    50 };
    51 
    52 struct FlowParticlesValues {
    53     FlowPosition position;        ///< Position on axis of particle plane
    54     FlowColor color;              ///< Color of particles
    55     /// Indicates if particle injection plane is active or not
    56     int isHidden;
    57     float particleSize;           ///< Size of the particles
    58 };
    59 
    60 struct FlowParticlesIterator {
    61     Tcl_HashEntry *hashPtr;
    62     Tcl_HashSearch hashSearch;
    63 };
    64 
    65 class FlowParticles
    66 {
    67 public:
    68     FlowParticles(const char *name, Tcl_HashEntry *hPtr);
    69 
    70     ~FlowParticles();
    71 
    72     const char *name()
    73     {
    74         return _name;
    75     }
    76 
    77     void disconnect()
    78     {
    79         _hashPtr = NULL;
    80     }
    81 
    82     bool visible()
    83     {
    84         return !_sv.isHidden;
    85     }
    86 
    87     int parseSwitches(Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
    88     {
    89         if (Rappture::ParseSwitches(interp, _switches, objc, objv, &_sv,
    90                                     SWITCH_DEFAULTS) < 0) {
    91             return TCL_ERROR;
    92         }
    93         return TCL_OK;
    94     }
    95 
    96     void advect()
    97     {
    98         assert(_rendererPtr->active());
    99         _rendererPtr->advect();
    100     }
    101 
    102     void render();
    103 
    104     void reset()
    105     {
    106         _rendererPtr->reset();
    107     }
    108 
    109     void initialize()
    110     {
    111         _rendererPtr->initialize();
    112     }
    113 
    114     void setVectorField(Volume *volPtr, const vrmath::Vector3f& location,
    115                         float scaleX, float scaleY, float scaleZ,
    116                         float max)
    117     {
    118         _rendererPtr->
    119             setVectorField(volPtr->textureID(),
    120                            location,
    121                            scaleX,
    122                            scaleY,
    123                            scaleZ,
    124                            max);
    125     }
    126 
    127     void configure();
    128 
    129 private:
    130     /**
    131      * Name of particle injection plane. Actual character string is
    132      * stored in hash table.
    133      */
    134     const char *_name;
    135     Tcl_HashEntry *_hashPtr;
    136     NvParticleRenderer *_rendererPtr;        ///< Particle renderer
    137     FlowParticlesValues _sv;
    138 
    139     static Rappture::SwitchSpec _switches[];
    140 };
    141 
    142 struct FlowBoxIterator {
    143     Tcl_HashEntry *hashPtr;
    144     Tcl_HashSearch hashSearch;
    145 };
    146 
    147 struct FlowBoxValues {
    148     FlowPoint corner1, corner2;    ///< Coordinates of the box.
    149     FlowColor color;               ///< Color of box
    150     float lineWidth;
    151     int isHidden;
    152 };
    153 
    154 class FlowBox
    155 {
    156 public:
    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 
    193     const FlowBoxValues *getValues() const
    194     {
    195         return &_sv;
    196     }
    197 
    198     void getWorldSpaceBounds(vrmath::Vector3f& min,
    199                              vrmath::Vector3f& max,
    200                              const Volume *vol) const;
    201 
    202 private:
    203     const char *_name;          ///< Name of this box in the hash table.
    204     Tcl_HashEntry *_hashPtr;    ///< Pointer to this entry in the hash table of boxes.
    205     FlowBoxValues _sv;
    206     static Rappture::SwitchSpec _switches[];
    207 
    208 };
     44#include "TransferFunction.h"
    20945
    21046struct FlowValues {
    211     TransferFunction *tfPtr;
     47    TransferFunction *transferFunction;
    21248    FlowPosition slicePos;
    21349    int showArrows;
     
    22460};
    22561
    226 struct FlowIterator {
    227     Tcl_HashEntry *hashPtr;
    228     Tcl_HashSearch hashSearch;
    229 };
    230 
    23162class FlowCmd
    23263{
     
    23465    enum SliceAxis { AXIS_X, AXIS_Y, AXIS_Z };
    23566
    236     FlowCmd(Tcl_Interp *interp, const char *name, Tcl_HashEntry *hPtr);
     67    FlowCmd(Tcl_Interp *interp, const char *name);
    23768
    23869    ~FlowCmd();
    23970
    240     int createParticles(Tcl_Interp *interp, Tcl_Obj *objPtr);
    241 
    242     int getParticles(Tcl_Interp *interp, Tcl_Obj *objPtr,
    243                      FlowParticles **particlePtrPtr);
     71    void getBounds(vrmath::Vector3f& min,
     72                   vrmath::Vector3f& max,
     73                   bool onlyVisible);
     74
     75    FlowParticles *createParticles(const char *particlesName);
     76
     77    FlowParticles *getParticles(const char *particlesName);
     78
     79    void deleteParticles(const char *particlesName);
     80
     81    void getParticlesNames(std::vector<std::string>& names);
    24482
    24583    void render();
     
    25189    void initializeParticles();
    25290
    253     FlowParticles *firstParticles(FlowParticlesIterator *iterPtr);
    254 
    255     FlowParticles *nextParticles(FlowParticlesIterator *iterPtr);
    256 
    257     int createBox(Tcl_Interp *interp, Tcl_Obj *objPtr);
    258 
    259     int getBox(Tcl_Interp *interp, Tcl_Obj *objPtr, FlowBox **boxPtrPtr);
    260 
    261     FlowBox *firstBox(FlowBoxIterator *iterPtr);
    262 
    263     FlowBox *nextBox(FlowBoxIterator *iterPtr);
     91    FlowBox *createBox(const char *boxName);
     92
     93    FlowBox *getBox(const char *boxName);
     94
     95    void deleteBox(const char *boxName);
     96
     97    void getBoxNames(std::vector<std::string>& names);
    26498
    26599    float *getScaledVector();
     
    271105    NvVectorField *getVectorField()
    272106    {
    273         return _fieldPtr;
     107        return _field;
    274108    }
    275109
     
    281115    }
    282116
    283     const char *name()
    284     {
    285         return _name;
    286     }
    287 
    288     void disconnect()
    289     {
    290         _hashPtr = NULL;
     117    const char *name() const
     118    {
     119        return _name.c_str();
    291120    }
    292121
    293122    bool isDataLoaded()
    294123    {
    295         return (_dataPtr != NULL);
     124        return (_data != NULL);
    296125    }
    297126
    298127    Rappture::Unirect3d *data()
    299128    {
    300         return _dataPtr;
    301     }
    302 
    303     void data(Rappture::Unirect3d *dataPtr)
    304     {
    305         if (_dataPtr != NULL) {
    306             delete _dataPtr;
     129        return _data;
     130    }
     131
     132    void data(Rappture::Unirect3d *data)
     133    {
     134        if (_data != NULL) {
     135            delete _data;
    307136        }
    308         _dataPtr = dataPtr;
     137        _data = data;
    309138    }
    310139
     
    329158    TransferFunction *getTransferFunction()
    330159    {
    331         return _sv.tfPtr;
     160        return _sv.transferFunction;
    332161    }
    333162
     
    367196    }
    368197
    369     void setVectorField(NvVectorField *fieldPtr)
     198    void setVectorField(NvVectorField *field)
    370199    {
    371200        deleteVectorField();
    372         _fieldPtr = fieldPtr;
     201        _field = field;
    373202    }
    374203
    375204    void deleteVectorField()
    376205    {
    377         if (_fieldPtr != NULL) {
    378             delete _fieldPtr;
    379             _fieldPtr = NULL;
     206        if (_field != NULL) {
     207            delete _field;
     208            _field = NULL;
    380209        }
     210    }
     211
     212    const Volume *getVolume() const
     213    {
     214        return _volume;
    381215    }
    382216
     
    390224    }
    391225
    392     const Volume *getVolume() const
    393     {
    394         return _volPtr;
    395     }
    396 
    397     static float getRelativePosition(FlowPosition *posPtr);
     226    Tcl_Command getCommandToken()
     227    {
     228        return _cmdToken;
     229    }
     230
     231    static float getRelativePosition(FlowPosition *pos);
    398232
    399233    static Rappture::SwitchSpec videoSwitches[];
    400234
    401235private:
     236    typedef std::string ParticlesId;
     237    typedef std::string BoxId;
     238    typedef std::tr1::unordered_map<ParticlesId, FlowParticles *> ParticlesHashmap;
     239    typedef std::tr1::unordered_map<BoxId, FlowBox *> BoxHashmap;
     240
    402241    void configure();
    403242
     
    405244
    406245    Tcl_Interp *_interp;
    407     Tcl_HashEntry *_hashPtr;
    408246    /**
    409247     * Name of the flow.  This may differ
     
    411249     * associated with the flow, if the
    412250     * command was renamed. */
    413     const char *_name;
     251    std::string _name;
    414252
    415253    /**
     
    425263     * kept to regenerate the volume
    426264     * associated with the flow. */
    427     Rappture::Unirect3d *_dataPtr;
     265    Rappture::Unirect3d *_data;
    428266
    429267    /**
     
    431269     * flow.  This isn't the same thing as
    432270     * a normal volume displayed. */
    433     Volume *_volPtr;
     271    Volume *_volume;
    434272
    435273    /**
    436274     * Vector field generated from the
    437275     * above volume */
    438     NvVectorField *_fieldPtr;
     276    NvVectorField *_field;
    439277
    440278    /**
     
    443281     * where the particles are injected
    444282     * into the flow. */
    445     Tcl_HashTable _particlesTable;
     283    ParticlesHashmap _particlesTable;
    446284
    447285    /**
     
    449287     * zero or more boxes associated
    450288     * with each field. */
    451     Tcl_HashTable _boxTable;
     289    BoxHashmap _boxTable;
    452290
    453291    FlowValues _sv;
     
    459297
    460298extern int GetBooleanFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
    461                              bool *boolPtr);
     299                             bool *boolVal);
    462300
    463301extern int GetFloatFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
    464                            float *floatPtr);
     302                           float *floatVal);
    465303
    466304extern int GetAxisFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
    467                           int *axisPtr);
     305                          int *axisVal);
    468306
    469307extern int GetVolumeFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
    470                             Volume **volumePtrPtr);
     308                            Volume **volume);
    471309
    472310#endif
  • trunk/packages/vizservers/nanovis/Makefile.in

    r3563 r3567  
    111111                ContourLineFilter.o \
    112112                ConvexPolygon.o \
     113                FlowBox.o \
    113114                FlowCmd.o \
     115                FlowParticles.o \
    114116                GradientFilter.o \
    115117                Grid.o \
     
    276278ContourLineFilter.o: ContourLineFilter.cpp ContourLineFilter.h
    277279ConvexPolygon.o: ConvexPolygon.cpp ConvexPolygon.h $(VRMATH_DIR)/include/vrmath/Vector4f.h $(VRMATH_DIR)/include/vrmath/Matrix4x4d.h Plane.h
    278 FlowCmd.o: FlowCmd.cpp FlowCmd.h Switch.h Trace.h TransferFunction.h nanovis.h CmdProc.h NvLIC.h Unirect.h Volume.h VelocityArrowsSlice.h
     280FlowBox.o: FlowBox.h FlowTypes.h Switch.h Trace.h Volume.h $(VRMATH_DIR)/include/vrmath/Vector3f.h $(VRMATH_DIR)/include/vrmath/Vector4f.h $(VRMATH_DIR)/include/vrmath/Matrix4x4d.h
     281FlowCmd.o: FlowCmd.cpp FlowCmd.h FlowParticles.h FlowBox.h FlowTypes.h Switch.h Trace.h TransferFunction.h nanovis.h CmdProc.h NvLIC.h Unirect.h Volume.h VelocityArrowsSlice.h $(VRMATH_DIR)/include/vrmath/Vector3f.h
     282FlowParticles.o: FlowParticles.h FlowTypes.h FlowCmd.h Switch.h Trace.h NvParticleRenderer.h Volume.h $(VRMATH_DIR)/include/vrmath/Vector3f.h $(VRMATH_DIR)/include/vrmath/Vector4f.h
    279283GradientFilter.o: GradientFilter.cpp GradientFilter.h
    280284Grid.o: Grid.cpp Grid.h Axis.h Chain.h
  • trunk/packages/vizservers/nanovis/Volume.cpp

    r3502 r3567  
    4545    _lightTwoSide(false),
    4646    _opacityScale(0.5f),
    47     _name(NULL),
    4847    _data(NULL),
    4948    _numComponents(n),
  • trunk/packages/vizservers/nanovis/Volume.h

    r3502 r3567  
    320320    const char *name() const
    321321    {
    322         return _name;
     322        return _name.c_str();
    323323    }
    324324
     
    381381    float _opacityScale;
    382382
    383     const char *_name;
     383    std::string _name;
     384
    384385    float *_data;
    385386
  • trunk/packages/vizservers/nanovis/VolumeRenderer.cpp

    r3502 r3567  
    2121#include <GL/glew.h>
    2222
    23 #include <tcl.h>
    24 
    2523#include <vrmath/Vector3f.h>
    2624#include <vrmath/Matrix4x4d.h>
     
    109107    // Determine the volumes that are to be rendered.
    110108    std::vector<Volume *> volumes;
    111     Tcl_HashEntry *hPtr;
    112     Tcl_HashSearch iter;
    113     for (hPtr = Tcl_FirstHashEntry(&NanoVis::volumeTable, &iter); hPtr != NULL;
    114          hPtr = Tcl_NextHashEntry(&iter)) {
    115         Volume *volPtr;
    116         volPtr = (Volume *)Tcl_GetHashValue(hPtr);
    117         if (!volPtr->visible()) {
     109    for (NanoVis::VolumeHashmap::iterator itr = NanoVis::volumeTable.begin();
     110         itr != NanoVis::volumeTable.end(); ++itr) {
     111        Volume *volume = itr->second;
     112        if (!volume->visible()) {
    118113            continue; // Skip this volume
    119114        }
     
    123118        // second volume will overwrite the first, so the first won't appear
    124119        // at all.
    125         volumes.push_back(volPtr);
    126         volPtr->numSlices(256 - volumes.size());
     120        volumes.push_back(volume);
     121        volume->numSlices(256 - volumes.size());
    127122    }
    128123
  • trunk/packages/vizservers/nanovis/nanovis.cpp

    r3566 r3567  
    6868#include "NvLIC.h"
    6969#include "NvZincBlendeReconstructor.h"
    70 #include "PerfQuery.h"
    7170#include "PlaneRenderer.h"
    7271#ifdef USE_POINTSET_RENDERER
     
    105104
    106105// STATIC MEMBER DATA
    107 struct timeval NanoVis::startTime;      /* Start of elapsed time. */
    108 Grid *NanoVis::grid = NULL;
    109 int NanoVis::updir = Y_POS;
    110 NvCamera *NanoVis::cam = NULL;
    111 Tcl_HashTable NanoVis::volumeTable;
    112 Tcl_HashTable NanoVis::heightmapTable;
    113 VolumeRenderer *NanoVis::volRenderer = NULL;
    114 #ifdef USE_POINTSET_RENDERER
    115 PointSetRenderer *NanoVis::pointSetRenderer = NULL;
    116 std::vector<PointSet *> NanoVis::pointSet;
    117 #endif
    118 
    119 PlaneRenderer *NanoVis::planeRenderer = NULL;
    120 #ifdef PLANE_CMD
    121 // pointers to 2D planes, currently handle up 10
    122 int NanoVis::numPlanes = 10;
    123 Texture2D *NanoVis::plane[10];
    124 #endif
    125 Texture2D *NanoVis::legendTexture = NULL;
    126 NvColorTableRenderer *NanoVis::colorTableRenderer = NULL;
    127 #ifdef notdef
    128 NvFlowVisRenderer *NanoVis::flowVisRenderer = NULL;
    129 #endif
    130 VelocityArrowsSlice *NanoVis::velocityArrowsSlice = NULL;
    131 
    132 RenderContext *NanoVis::renderContext = NULL;
    133 NvLIC *NanoVis::licRenderer = NULL;
    134 Fonts *NanoVis::fonts;
    135106
    136107FILE *NanoVis::stdin = NULL;
     
    140111int NanoVis::statsFile = -1;
    141112
     113unsigned int NanoVis::flags = 0;
     114bool NanoVis::debugFlag = false;
    142115bool NanoVis::axisOn = true;
    143 bool NanoVis::debugFlag = false;
    144 
    145 Tcl_Interp *NanoVis::interp;
    146 
    147 //frame buffer for final rendering
    148 GLuint NanoVis::_finalColorTex = 0;
    149 GLuint NanoVis::_finalDepthRb = 0;
    150 GLuint NanoVis::_finalFbo = 0;
    151 int NanoVis::renderWindow = 0;       /* GLUT handle for the render window */
    152 int NanoVis::winWidth = NPIX;        /* Width of the render window */
    153 int NanoVis::winHeight = NPIX;       /* Height of the render window */
    154 
    155 unsigned char* NanoVis::screenBuffer = NULL;
    156 
    157 unsigned int NanoVis::flags = 0;
    158 Tcl_HashTable NanoVis::flowTable;
     116struct timeval NanoVis::startTime;
     117
     118int NanoVis::winWidth = NPIX;
     119int NanoVis::winHeight = NPIX;
     120int NanoVis::renderWindow = 0;
     121unsigned char *NanoVis::screenBuffer = NULL;
     122Texture2D *NanoVis::legendTexture = NULL;
     123Grid *NanoVis::grid = NULL;
     124Fonts *NanoVis::fonts;
     125int NanoVis::updir = Y_POS;
     126NvCamera *NanoVis::cam = NULL;
     127RenderContext *NanoVis::renderContext = NULL;
     128
     129NanoVis::TransferFunctionHashmap NanoVis::tfTable;
     130NanoVis::VolumeHashmap NanoVis::volumeTable;
     131NanoVis::FlowHashmap NanoVis::flowTable;
     132NanoVis::HeightMapHashmap NanoVis::heightMapTable;
     133
    159134double NanoVis::magMin = DBL_MAX;
    160135double NanoVis::magMax = -DBL_MAX;
     
    169144vrmath::Vector3f NanoVis::sceneMin, NanoVis::sceneMax;
    170145
    171 /* FIXME: This variable is always true. */
    172 static bool volumeMode = true;
     146NvColorTableRenderer *NanoVis::colorTableRenderer = NULL;
     147VolumeRenderer *NanoVis::volRenderer = NULL;
     148#ifdef notdef
     149NvFlowVisRenderer *NanoVis::flowVisRenderer = NULL;
     150#endif
     151VelocityArrowsSlice *NanoVis::velocityArrowsSlice = NULL;
     152NvLIC *NanoVis::licRenderer = NULL;
     153PlaneRenderer *NanoVis::planeRenderer = NULL;
     154#ifdef PLANE_CMD
     155// pointers to 2D planes, currently handle up 10
     156int NanoVis::numPlanes = 10;
     157Texture2D *NanoVis::plane[10];
     158#endif
     159#ifdef USE_POINTSET_RENDERER
     160PointSetRenderer *NanoVis::pointSetRenderer = NULL;
     161std::vector<PointSet *> NanoVis::pointSet;
     162#endif
     163
     164Tcl_Interp *NanoVis::interp;
     165
     166// Image based flow visualization slice location
     167// FLOW
     168float NanoVis::_licSlice = 0.5f;
     169int NanoVis::_licAxis = 2; // z axis
     170
     171//frame buffer for final rendering
     172GLuint NanoVis::_finalFbo = 0;
     173GLuint NanoVis::_finalColorTex = 0;
     174GLuint NanoVis::_finalDepthRb = 0;
    173175
    174176// in Command.cpp
    175177extern Tcl_Interp *initTcl();
    176 
    177 // maps transfunc name to TransferFunction object
    178 Tcl_HashTable NanoVis::tfTable;
    179 
    180 PerfQuery *perf = NULL;                        //performance counter
    181178
    182179// Default camera location.
     
    184181float def_eye_y = 0.0f;
    185182float def_eye_z = 2.5f;
    186 
    187 // Image based flow visualization slice location
    188 // FLOW
    189 float NanoVis::_licSlice = 0.5f;
    190 int NanoVis::_licAxis = 2; // z axis
    191183
    192184void
     
    248240        delete [] screenBuffer;
    249241        screenBuffer = NULL;
    250     }
    251     if (perf != NULL) {
    252         TRACE("Deleting perf");
    253         delete perf;
    254242    }
    255243#ifdef USE_POINTSET_RENDERER
     
    307295    }
    308296    if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
    309         return -1;
     297        return -1;
    310298    }
    311299    Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("pid", 3));
     
    328316    Tcl_DStringFree(&ds);
    329317    if (statsFile < 0) {
    330         ERROR("can't open \"%s\": %s", fileName, strerror(errno));
    331         return -1;
     318        ERROR("can't open \"%s\": %s", fileName, strerror(errno));
     319        return -1;
    332320    }
    333321    return statsFile;
     
    358346
    359347    {
    360         struct timeval tv;
    361 
    362         /* Get ending time.  */
    363         gettimeofday(&tv, NULL);
    364         finish = CVT2SECS(tv);
    365         tv = stats.start;
    366         start = CVT2SECS(tv);
     348        struct timeval tv;
     349
     350        /* Get ending time.  */
     351        gettimeofday(&tv, NULL);
     352        finish = CVT2SECS(tv);
     353        tv = stats.start;
     354        start = CVT2SECS(tv);
    367355    }
    368356    /*
     
    434422    Tcl_DStringAppendElement(&ds, buf);
    435423    {
    436         long clocksPerSec = sysconf(_SC_CLK_TCK);
    437         double clockRes = 1.0 / clocksPerSec;
    438         struct tms tms;
    439 
    440         memset(&tms, 0, sizeof(tms));
    441         times(&tms);
    442         /* utime */
    443         Tcl_DStringAppendElement(&ds, "utime");
    444         sprintf(buf, "%g", tms.tms_utime * clockRes);
    445         Tcl_DStringAppendElement(&ds, buf);
    446         /* stime */
    447         Tcl_DStringAppendElement(&ds, "stime");
    448         sprintf(buf, "%g", tms.tms_stime * clockRes);
    449         Tcl_DStringAppendElement(&ds, buf);
    450         /* cutime */
    451         Tcl_DStringAppendElement(&ds, "cutime");
    452         sprintf(buf, "%g", tms.tms_cutime * clockRes);
    453         Tcl_DStringAppendElement(&ds, buf);
    454         /* cstime */
    455         Tcl_DStringAppendElement(&ds, "cstime");
    456         sprintf(buf, "%g", tms.tms_cstime * clockRes);
    457         Tcl_DStringAppendElement(&ds, buf);
     424        long clocksPerSec = sysconf(_SC_CLK_TCK);
     425        double clockRes = 1.0 / clocksPerSec;
     426        struct tms tms;
     427
     428        memset(&tms, 0, sizeof(tms));
     429        times(&tms);
     430        /* utime */
     431        Tcl_DStringAppendElement(&ds, "utime");
     432        sprintf(buf, "%g", tms.tms_utime * clockRes);
     433        Tcl_DStringAppendElement(&ds, buf);
     434        /* stime */
     435        Tcl_DStringAppendElement(&ds, "stime");
     436        sprintf(buf, "%g", tms.tms_stime * clockRes);
     437        Tcl_DStringAppendElement(&ds, buf);
     438        /* cutime */
     439        Tcl_DStringAppendElement(&ds, "cutime");
     440        sprintf(buf, "%g", tms.tms_cutime * clockRes);
     441        Tcl_DStringAppendElement(&ds, buf);
     442        /* cstime */
     443        Tcl_DStringAppendElement(&ds, "cstime");
     444        sprintf(buf, "%g", tms.tms_cstime * clockRes);
     445        Tcl_DStringAppendElement(&ds, buf);
    458446    }
    459447    Tcl_DStringAppend(&ds, "\n", -1);
     
    513501    if (NanoVis::logfile != NULL) {
    514502        fclose(NanoVis::logfile);
    515         NanoVis::logfile = NULL;
     503        NanoVis::logfile = NULL;
    516504    }
    517505
     
    609597                    double nzero_min)
    610598{
    611     Tcl_HashEntry *hPtr;
    612     hPtr = Tcl_FindHashEntry(&volumeTable, name);
    613     if (hPtr != NULL) {
    614         Volume *volPtr;
     599    VolumeHashmap::iterator itr = volumeTable.find(name);
     600    if (itr != volumeTable.end()) {
    615601        WARN("volume \"%s\" already exists", name);
    616         volPtr = (Volume *)Tcl_GetHashValue(hPtr);
    617         removeVolume(volPtr);
    618     }
    619     int isNew;
    620     hPtr = Tcl_CreateHashEntry(&volumeTable, name, &isNew);
    621     Volume* volPtr;
    622     volPtr = new Volume(0.f, 0.f, 0.f, width, height, depth, n_component,
    623                         data, vmin, vmax, nzero_min);
     602        removeVolume(itr->second);
     603    }
     604
     605    Volume *volume = new Volume(0.f, 0.f, 0.f,
     606                                width, height, depth,
     607                                n_component,
     608                                data, vmin, vmax, nzero_min);
    624609    Volume::updatePending = true;
    625     Tcl_SetHashValue(hPtr, volPtr);
    626     volPtr->name(Tcl_GetHashKey(&volumeTable, hPtr));
    627     return volPtr;
     610    volume->name(name);
     611    volumeTable[name] = volume;
     612
     613    return volume;
    628614}
    629615
    630616// Gets a colormap 1D texture by name.
    631617TransferFunction *
    632 NanoVis::getTransfunc(const char *name)
    633 {
    634     Tcl_HashEntry *hPtr;
    635 
    636     hPtr = Tcl_FindHashEntry(&tfTable, name);
    637     if (hPtr == NULL) {
    638         ERROR("No transfer function named \"%s\" found", name);
     618NanoVis::getTransferFunction(const TransferFunctionId& id)
     619{
     620    TransferFunctionHashmap::iterator itr = tfTable.find(id);
     621    if (itr == tfTable.end()) {
     622        ERROR("No transfer function named \"%s\" found", id.c_str());
    639623        return NULL;
    640     }
    641     return (TransferFunction *)Tcl_GetHashValue(hPtr);
     624    } else {
     625        return itr->second;
     626    }
    642627}
    643628
    644629// Creates of updates a colormap 1D texture by name.
    645630TransferFunction *
    646 NanoVis::defineTransferFunction(const char *name, size_t n, float *data)
    647 {
    648     int isNew;
    649     Tcl_HashEntry *hPtr;
    650     TransferFunction *tfPtr;
    651 
    652     hPtr = Tcl_CreateHashEntry(&tfTable, name, &isNew);
    653     if (isNew) {
    654         TRACE("Creating new transfer function \"%s\"", name);
    655 
    656         tfPtr = new TransferFunction(n, data);
    657         tfPtr->name(Tcl_GetHashKey(&tfTable, hPtr));
    658         Tcl_SetHashValue(hPtr, tfPtr);
     631NanoVis::defineTransferFunction(const TransferFunctionId& id,
     632                                size_t n, float *data)
     633{
     634    TransferFunction *tf = getTransferFunction(id);
     635    if (tf == NULL) {
     636        TRACE("Creating new transfer function \"%s\"", id.c_str());
     637        tf = new TransferFunction(n, data);
     638        tfTable[id] = tf;
    659639    } else {
    660         TRACE("Updating existing transfer function \"%s\"", name);
    661 
    662         /*
    663          * You can't delete the transfer function because many
    664          * objects may be holding its pointer.  We must update it.
    665          */
    666         tfPtr = (TransferFunction *)Tcl_GetHashValue(hPtr);
    667         tfPtr->update(n, data);
    668     }
    669     return tfPtr;
     640        TRACE("Updating existing transfer function \"%s\"", id.c_str());
     641        tf->update(n, data);
     642    }
     643    return tf;
    670644}
    671645
     
    978952    glLightfv(GL_LIGHT1, GL_DIFFUSE, green_light);
    979953    glLightfv(GL_LIGHT1, GL_SPECULAR, white_light);
    980 
    981     // init table of transfer functions
    982     Tcl_InitHashTable(&tfTable, TCL_STRING_KEYS);
    983 
    984     //check if performance query is supported
    985     if (PerfQuery::checkQuerySupport()) {
    986         //create queries to count number of rendered pixels
    987         perf = new PerfQuery();
    988     }
    989954
    990955    initOffscreenBuffer();    //frame buffer object for offscreen rendering
     
    14551420    xMin = yMin = zMin = wMin = DBL_MAX;
    14561421    xMax = yMax = zMax = wMax = -DBL_MAX;
    1457     Tcl_HashEntry *hPtr;
    1458     Tcl_HashSearch iter;
    1459     for (hPtr = Tcl_FirstHashEntry(&volumeTable, &iter); hPtr != NULL;
    1460          hPtr = Tcl_NextHashEntry(&iter)) {
    1461         Volume *volPtr = (Volume *)Tcl_GetHashValue(hPtr);
    1462         if (xMin > volPtr->xAxis.min()) {
    1463             xMin = volPtr->xAxis.min();
    1464         }
    1465         if (xMax < volPtr->xAxis.max()) {
    1466             xMax = volPtr->xAxis.max();
    1467         }
    1468         if (yMin > volPtr->yAxis.min()) {
    1469             yMin = volPtr->yAxis.min();
    1470         }
    1471         if (yMax < volPtr->yAxis.max()) {
    1472             yMax = volPtr->yAxis.max();
    1473         }
    1474         if (zMin > volPtr->zAxis.min()) {
    1475             zMin = volPtr->zAxis.min();
    1476         }
    1477         if (zMax < volPtr->zAxis.max()) {
    1478             zMax = volPtr->zAxis.max();
    1479         }
    1480         if (wMin > volPtr->wAxis.min()) {
    1481             wMin = volPtr->wAxis.min();
    1482         }
    1483         if (wMax < volPtr->wAxis.max()) {
    1484             wMax = volPtr->wAxis.max();
     1422    VolumeHashmap::iterator itr;
     1423    for (itr = volumeTable.begin();
     1424         itr != volumeTable.end(); ++itr) {
     1425        Volume *volume = itr->second;
     1426        if (xMin > volume->xAxis.min()) {
     1427            xMin = volume->xAxis.min();
     1428        }
     1429        if (xMax < volume->xAxis.max()) {
     1430            xMax = volume->xAxis.max();
     1431        }
     1432        if (yMin > volume->yAxis.min()) {
     1433            yMin = volume->yAxis.min();
     1434        }
     1435        if (yMax < volume->yAxis.max()) {
     1436            yMax = volume->yAxis.max();
     1437        }
     1438        if (zMin > volume->zAxis.min()) {
     1439            zMin = volume->zAxis.min();
     1440        }
     1441        if (zMax < volume->zAxis.max()) {
     1442            zMax = volume->zAxis.max();
     1443        }
     1444        if (wMin > volume->wAxis.min()) {
     1445            wMin = volume->wAxis.min();
     1446        }
     1447        if (wMax < volume->wAxis.max()) {
     1448            wMax = volume->wAxis.max();
    14851449        }
    14861450    }
     
    15101474    xMin = yMin = zMin = wMin = DBL_MAX;
    15111475    xMax = yMax = zMax = wMax = -DBL_MAX;
    1512     Tcl_HashEntry *hPtr;
    1513     Tcl_HashSearch iter;
    1514     for (hPtr = Tcl_FirstHashEntry(&heightmapTable, &iter); hPtr != NULL;
    1515          hPtr = Tcl_NextHashEntry(&iter)) {
    1516         HeightMap *hmPtr = (HeightMap *)Tcl_GetHashValue(hPtr);
    1517         if (xMin > hmPtr->xAxis.min()) {
    1518             xMin = hmPtr->xAxis.min();
    1519         }
    1520         if (xMax < hmPtr->xAxis.max()) {
    1521             xMax = hmPtr->xAxis.max();
    1522         }
    1523         if (yMin > hmPtr->yAxis.min()) {
    1524             yMin = hmPtr->yAxis.min();
    1525         }
    1526         if (yMax < hmPtr->yAxis.max()) {
    1527             yMax = hmPtr->yAxis.max();
    1528         }
    1529         if (zMin > hmPtr->zAxis.min()) {
    1530             zMin = hmPtr->zAxis.min();
    1531         }
    1532         if (zMax < hmPtr->zAxis.max()) {
    1533             zMax = hmPtr->zAxis.max();
    1534         }
    1535         if (wMin > hmPtr->wAxis.min()) {
    1536             wMin = hmPtr->wAxis.min();
    1537         }
    1538         if (wMax < hmPtr->wAxis.max()) {
    1539             wMax = hmPtr->wAxis.max();
     1476    HeightMapHashmap::iterator itr;
     1477    for (itr = heightMapTable.begin();
     1478         itr != heightMapTable.end(); ++itr) {
     1479        HeightMap *heightMap = itr->second;
     1480        if (xMin > heightMap->xAxis.min()) {
     1481            xMin = heightMap->xAxis.min();
     1482        }
     1483        if (xMax < heightMap->xAxis.max()) {
     1484            xMax = heightMap->xAxis.max();
     1485        }
     1486        if (yMin > heightMap->yAxis.min()) {
     1487            yMin = heightMap->yAxis.min();
     1488        }
     1489        if (yMax < heightMap->yAxis.max()) {
     1490            yMax = heightMap->yAxis.max();
     1491        }
     1492        if (zMin > heightMap->zAxis.min()) {
     1493            zMin = heightMap->zAxis.min();
     1494        }
     1495        if (zMax < heightMap->zAxis.max()) {
     1496            zMax = heightMap->zAxis.max();
     1497        }
     1498        if (wMin > heightMap->wAxis.min()) {
     1499            wMin = heightMap->wAxis.min();
     1500        }
     1501        if (wMax < heightMap->wAxis.max()) {
     1502            wMax = heightMap->wAxis.max();
    15401503        }
    15411504    }
     
    15531516        HeightMap::valueMax = grid->yAxis.max();
    15541517    }
    1555     for (hPtr = Tcl_FirstHashEntry(&heightmapTable, &iter); hPtr != NULL;
    1556          hPtr = Tcl_NextHashEntry(&iter)) {
    1557         HeightMap *hmPtr;
    1558         hmPtr = (HeightMap *)Tcl_GetHashValue(hPtr);
    1559         hmPtr->mapToGrid(grid);
     1518    for (HeightMapHashmap::iterator itr = heightMapTable.begin();
     1519         itr != heightMapTable.end(); ++itr) {
     1520        itr->second->mapToGrid(grid);
    15601521    }
    15611522    HeightMap::updatePending = false;
     
    15761537    sceneMax.set(-FLT_MAX, -FLT_MAX, -FLT_MAX);
    15771538
    1578     Tcl_HashEntry *hPtr;
    1579     Tcl_HashSearch iter;
    1580     for (hPtr = Tcl_FirstHashEntry(&volumeTable, &iter); hPtr != NULL;
    1581          hPtr = Tcl_NextHashEntry(&iter)) {
    1582         Volume *vol = (Volume *)Tcl_GetHashValue(hPtr);
    1583 
    1584         if (onlyVisible && !vol->visible())
     1539    for (VolumeHashmap::iterator itr = volumeTable.begin();
     1540         itr != volumeTable.end(); ++itr) {
     1541        Volume *volume = itr->second;
     1542
     1543        if (onlyVisible && !volume->visible())
    15851544            continue;
    15861545
    15871546        vrmath::Vector3f bmin, bmax;
    1588         vol->getWorldSpaceBounds(bmin, bmax);
     1547        volume->getWorldSpaceBounds(bmin, bmax);
    15891548        if (bmin.x > bmax.x)
    15901549            continue;
     
    16101569    }
    16111570
    1612     for (hPtr = Tcl_FirstHashEntry(&heightmapTable, &iter); hPtr != NULL;
    1613          hPtr = Tcl_NextHashEntry(&iter)) {
    1614         HeightMap *heightMap = (HeightMap *)Tcl_GetHashValue(hPtr);
     1571    for (HeightMapHashmap::iterator itr = heightMapTable.begin();
     1572         itr != heightMapTable.end(); ++itr) {
     1573        HeightMap *heightMap = itr->second;
    16151574
    16161575        if (onlyVisible && !heightMap->isVisible())
     
    17121671    bindOffscreenBuffer();
    17131672
    1714     TRACE("glClear");
    17151673    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //clear screen
    17161674
    1717     if (volumeMode) {
    1718         TRACE("volumeMode");
    1719         //3D rendering mode
    1720         glEnable(GL_DEPTH_TEST);
    1721         glEnable(GL_COLOR_MATERIAL);
    1722 
    1723         //camera setting activated
    1724         cam->initialize();
    1725 
    1726         //set up the orientation of items in the scene.
    1727         glPushMatrix();
    1728 
    1729         switch (updir) {
    1730         case X_POS:
    1731             glRotatef(90, 0, 0, 1);
    1732             glRotatef(90, 1, 0, 0);
    1733             break;
    1734         case Y_POS:
    1735             // this is the default
    1736             break;
    1737         case Z_POS:
    1738             glRotatef(-90, 1, 0, 0);
    1739             glRotatef(-90, 0, 0, 1);
    1740             break;
    1741         case X_NEG:
    1742             glRotatef(-90, 0, 0, 1);
    1743             break;
    1744         case Y_NEG:
    1745             glRotatef(180, 0, 0, 1);
    1746             glRotatef(-90, 0, 1, 0);
    1747             break;
    1748         case Z_NEG:
    1749             glRotatef(90, 1, 0, 0);
    1750             break;
    1751         }
    1752 
    1753         //now render things in the scene
    1754         if (axisOn) {
    1755             draw3dAxis();
    1756         }
    1757         if (grid->isVisible()) {
    1758             grid->render();
    1759         }
    1760         if ((licRenderer != NULL) && (licRenderer->active())) {
    1761             licRenderer->render();
    1762         }
    1763 
    1764         if ((velocityArrowsSlice != NULL) && (velocityArrowsSlice->enabled())) {
    1765             velocityArrowsSlice->render();
    1766         }
     1675    //3D rendering mode
     1676    glEnable(GL_DEPTH_TEST);
     1677    glEnable(GL_COLOR_MATERIAL);
     1678
     1679    //camera setting activated
     1680    cam->initialize();
     1681
     1682    //set up the orientation of items in the scene.
     1683    glPushMatrix();
     1684
     1685    switch (updir) {
     1686    case X_POS:
     1687        glRotatef(90, 0, 0, 1);
     1688        glRotatef(90, 1, 0, 0);
     1689        break;
     1690    case Y_POS:
     1691        // this is the default
     1692        break;
     1693    case Z_POS:
     1694        glRotatef(-90, 1, 0, 0);
     1695        glRotatef(-90, 0, 0, 1);
     1696        break;
     1697    case X_NEG:
     1698        glRotatef(-90, 0, 0, 1);
     1699        break;
     1700    case Y_NEG:
     1701        glRotatef(180, 0, 0, 1);
     1702        glRotatef(-90, 0, 1, 0);
     1703        break;
     1704    case Z_NEG:
     1705        glRotatef(90, 1, 0, 0);
     1706        break;
     1707    }
     1708
     1709    //now render things in the scene
     1710    if (axisOn) {
     1711        draw3dAxis();
     1712    }
     1713    if (grid->isVisible()) {
     1714        grid->render();
     1715    }
     1716    if ((licRenderer != NULL) && (licRenderer->active())) {
     1717        licRenderer->render();
     1718    }
     1719    if ((velocityArrowsSlice != NULL) && (velocityArrowsSlice->enabled())) {
     1720        velocityArrowsSlice->render();
     1721    }
    17671722#ifdef notdef
    1768         if ((flowVisRenderer != NULL) && (flowVisRenderer->active())) {
    1769             flowVisRenderer->render();
    1770         }
     1723    if ((flowVisRenderer != NULL) && (flowVisRenderer->active())) {
     1724        flowVisRenderer->render();
     1725    }
    17711726#endif
    1772         if (flowTable.numEntries > 0) {
    1773             renderFlows();
    1774         }
    1775 
    1776         volRenderer->renderAll();
    1777 
    1778         if (heightmapTable.numEntries > 0) {
    1779             TRACE("render heightmap");
    1780             Tcl_HashEntry *hPtr;
    1781             Tcl_HashSearch iter;
    1782             for (hPtr = Tcl_FirstHashEntry(&heightmapTable, &iter); hPtr != NULL;
    1783                  hPtr = Tcl_NextHashEntry(&iter)) {
    1784                 HeightMap *hmPtr;
    1785                 hmPtr = (HeightMap *)Tcl_GetHashValue(hPtr);
    1786                 if (hmPtr->isVisible()) {
    1787                     hmPtr->render(renderContext);
    1788                 }
    1789             }
    1790         }
    1791         glPopMatrix();
    1792     } else {
    1793         //2D rendering mode
    1794         perf->enable();
    1795         planeRenderer->render();
    1796         perf->disable();
    1797     }
    1798 
    1799     perf->reset();
     1727    if (!flowTable.empty()) {
     1728        renderFlows();
     1729    }
     1730
     1731    volRenderer->renderAll();
     1732
     1733    TRACE("Render heightmaps");
     1734    HeightMapHashmap::iterator itr;
     1735    for (itr = heightMapTable.begin();
     1736         itr != heightMapTable.end(); ++itr) {
     1737        HeightMap *heightMap = itr->second;
     1738        if (heightMap->isVisible()) {
     1739            heightMap->render(renderContext);
     1740        }
     1741    }
     1742    glPopMatrix();
     1743
    18001744    CHECK_FRAMEBUFFER_STATUS();
    18011745    TRACE("Leave");
     
    20501994
    20511995void
    2052 NanoVis::removeVolume(Volume *volPtr)
    2053 {
    2054     Tcl_HashEntry *hPtr;
    2055     hPtr = Tcl_FindHashEntry(&volumeTable, volPtr->name());
    2056     if (hPtr != NULL) {
    2057         Tcl_DeleteHashEntry(hPtr);
    2058     }
    2059     delete volPtr;
    2060 }
     1996NanoVis::removeVolume(Volume *volume)
     1997{
     1998    VolumeHashmap::iterator itr = volumeTable.find(volume->name());
     1999    if (itr != volumeTable.end()) {
     2000        volumeTable.erase(itr);
     2001    }
     2002    delete volume;
     2003}
  • trunk/packages/vizservers/nanovis/nanovis.h

    r3566 r3567  
    2727#include <vector>
    2828#include <iostream>
     29#include <tr1/unordered_map>
    2930
    3031#include <vrmath/Vector3f.h>
     
    6465class Volume;
    6566class FlowCmd;
    66 class FlowIterator;
    6767
    6868class NanoVis
     
    8383    };
    8484
     85    typedef std::string TransferFunctionId;
     86    typedef std::string VolumeId;
     87    typedef std::string FlowId;
     88    typedef std::string HeightMapId;
     89    typedef std::tr1::unordered_map<TransferFunctionId, TransferFunction *> TransferFunctionHashmap;
     90    typedef std::tr1::unordered_map<VolumeId, Volume *> VolumeHashmap;
     91    typedef std::tr1::unordered_map<FlowId, FlowCmd *> FlowHashmap;
     92    typedef std::tr1::unordered_map<HeightMapId, HeightMap *> HeightMapHashmap;
     93
    8594    static void processCommands();
    8695    static void init(const char *path);
     
    118127    static void bmpWriteToFile(int frame_number, const char* directory_name);
    119128 
    120     static TransferFunction *getTransfunc(const char *name);
    121     static TransferFunction *defineTransferFunction(const char *name,
     129    static TransferFunction *getTransferFunction(const TransferFunctionId& id);
     130    static TransferFunction *defineTransferFunction(const TransferFunctionId& id,
    122131                                                    size_t n, float *data);
    123132
     
    141150    }
    142151
    143     static FlowCmd *firstFlow(FlowIterator *iterPtr);
    144     static FlowCmd *nextFlow(FlowIterator *iterPtr);
    145     static void initFlows();
    146     static int getFlow(Tcl_Interp *interp, Tcl_Obj *objPtr,
    147                        FlowCmd **flowPtrPtr);
    148     static int createFlow(Tcl_Interp *interp, Tcl_Obj *objPtr);
     152    static FlowCmd *getFlow(const char *name);
     153    static FlowCmd *createFlow(Tcl_Interp *interp, const char *name);
     154    static void deleteFlow(const char *name);
    149155    static void deleteFlows(Tcl_Interp *interp);
    150156    static bool mapFlows();
     
    162168    static bool debugFlag;
    163169    static bool axisOn;
    164     static int winWidth;        //size of the render window
    165     static int winHeight;       //size of the render window
    166     static int renderWindow;
     170    static struct timeval startTime;       ///< Start of elapsed time.
     171
     172    static int winWidth;        ///< Width of the render window
     173    static int winHeight;       ///< Height of the render window
     174    static int renderWindow;    //< GLUT handle for the render window
    167175    static unsigned char *screenBuffer;
    168176    static Texture2D *legendTexture;
     
    173181    static nv::graphics::RenderContext *renderContext;
    174182
    175     static Tcl_HashTable tfTable;
    176     static Tcl_HashTable volumeTable;
    177     static Tcl_HashTable flowTable;
    178     static Tcl_HashTable heightmapTable;
     183    static TransferFunctionHashmap tfTable; ///< maps transfunc name to TransferFunction object
     184    static VolumeHashmap volumeTable;
     185    static FlowHashmap flowTable;
     186    static HeightMapHashmap heightMapTable;
    179187
    180188    static double magMin, magMax;
     
    200208
    201209    static Tcl_Interp *interp;
    202     static struct timeval startTime;           /* Start of elapsed time. */
     210
    203211private:
    204212    static void collectBounds(bool onlyVisible = false);
  • trunk/packages/vizservers/nanovis/protocol-nanovis.txt

    r3502 r3567  
    8585flow exists <name>
    8686flow goto <nSteps>
    87 flow names <?pattern?>
     87flow names
    8888flow next
    8989flow reset
     
    104104         -hide <bool>
    105105         -linewidth <val>
    106 <flowObj> box delete <?names?>
    107 <flowObj> box names <?pattern?>
     106<flowObj> box delete <names>
     107<flowObj> box names
    108108
    109109<flowObj> configure <?option value...?>
     
    127127          Send flow data.  Data bytes follow the newline after the command
    128128<flowObj> legend <w> <h>
     129
    129130<flowObj> particles add <name> <?switches?>
    130131          see '<flowObj> particles configure' for switches
     
    136137           val = [0,100], or %val = [0,1]
    137138          -size <val>
     139<flowObj> particles delete <names>
     140<flowObj> particles names
    138141
    139142volume data state <on|off> <?names?>
  • trunk/packages/vizservers/nanovis/vrmath/Makefile.in

    r3492 r3567  
    4242#               BBox.o \
    4343#               BPlane.o \
    44 #               Color4f.o \
    4544#               Projection.o \
    4645
    4746OBJS            = \
    48                 BBox.o \
    49                 BPlane.o \
    50                 Color4f.o \
    5147                LineSegment.o \
    5248                Matrix4x4f.o \
     
    8177BBox.o: $(srcdir)/include/vrmath/BBox.h $(srcdir)/include/vrmath/Vector3f.h
    8278BPlane.o: $(srcdir)/include/vrmath/BPlane.h $(srcdir)/include/vrmath/Vector3f.h $(srcdir)/include/vrmath/LineSegment.h
    83 Color4f.o: $(srcdir)/include/vrmath/Color4f.h
    8479LineSegment.o: $(srcdir)/include/vrmath/LineSegment.h
    8580Matrix4x4d.o: $(srcdir)/include/vrmath/Matrix4x4d.h $(srcdir)/include/vrmath/Vector3f.h $(srcdir)/include/vrmath/Vector4f.h $(srcdir)/include/vrmath/Rotation.h
  • trunk/packages/vizservers/nanovis/vrmath/include/vrmath/Color4f.h

    r3492 r3567  
    88#define VRCOLOR4F_H
    99
     10#include <vrmath/Vector4f.h>
     11
    1012namespace vrmath {
    1113
    12 class Color4f
    13 {
    14 public:
    15     float r, g, b, a;
    16 
    17     Color4f();
    18 
    19     Color4f(float r1, float g1, float b1, float a1 = 0);
    20 
    21     Color4f(const Color4f& col) :
    22         r(col.r), g(col.g), b(col.b), a(col.a)
    23     {}
    24 
    25     friend bool operator==(const Color4f col1, const Color4f& col2);
    26     friend bool operator!=(const Color4f col1, const Color4f& col2);
    27 };
    28 
    29 inline bool operator==(const Color4f col1, const Color4f& col2)
    30 {
    31     return ((col1.r == col2.r) && (col1.g == col2.g) && (col1.b == col2.b));
    32 }
    33 
    34 inline bool operator!=(const Color4f col1, const Color4f& col2)
    35 {
    36     return ((col1.r != col2.r) || (col1.g != col2.g) || (col1.b != col2.b));
    37 }
     14typedef Vector4f Color4f;
    3815
    3916}
  • trunk/packages/vizservers/nanovis/vrmath/include/vrmath/Vector3f.h

    r3492 r3567  
    8080    //friend Vector3f operator*(float scale, const Vector3f& value);
    8181
    82     float x, y, z;
     82    union {
     83        struct {
     84            float x, y, z;
     85        };
     86        struct {
     87            float r, g, b;
     88        };
     89    };
    8390};
    8491
  • trunk/packages/vizservers/nanovis/vrmath/include/vrmath/Vector4f.h

    r3492 r3567  
    2020    {}
    2121
    22     Vector4f(const Vector4f& v4) :
    23         x(v4.x), y(v4.y), z(v4.z), w(v4.w)
     22    Vector4f(const Vector4f& other) :
     23        x(other.x), y(other.y), z(other.z), w(other.w)
    2424    {}
    2525
     
    7272    float dot(const Vector4f& vec) const;
    7373
    74     float x, y, z, w;
     74    union {
     75        struct {
     76            float x, y, z, w;
     77        };
     78        struct {
     79            float r, g, b, a;
     80        };
     81    };
    7582};
    7683
Note: See TracChangeset for help on using the changeset viewer.