Changeset 3605


Ignore:
Timestamp:
Apr 2, 2013, 1:31:30 PM (12 years ago)
Author:
ldelgass
Message:

Add writer thread to nanovis (set USE_THREADS in Makefile), more refactoring.

Location:
trunk/packages/vizservers/nanovis
Files:
12 added
15 edited

Legend:

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

    r3597 r3605  
    4545#include <vrmath/Vector3f.h>
    4646
     47#include "nanovisServer.h"
    4748#include "nanovis.h"
     49#include "ReadBuffer.h"
     50#ifdef USE_THREADS
     51#include "ResponseQueue.h"
     52#endif
     53#include "Command.h"
    4854#include "CmdProc.h"
    4955#include "FlowCmd.h"
    50 #include "Trace.h"
    51 #ifdef USE_POINTSET_RENDERER
    52 #include "PointSet.h"
    53 #endif
    5456#include "dxReader.h"
    5557#include "VtkReader.h"
     58#include "BMPWriter.h"
     59#include "PPMWriter.h"
    5660#include "Grid.h"
    5761#include "HeightMap.h"
    5862#include "NvCamera.h"
    5963#include "NvZincBlendeReconstructor.h"
     64#include "OrientationIndicator.h"
    6065#include "Unirect.h"
    6166#include "Volume.h"
    6267#include "VolumeRenderer.h"
    63 
     68#include "Trace.h"
     69
     70using namespace nv;
    6471using namespace nv::graphics;
    6572using namespace vrmath;
     
    102109}";
    103110
     111static int lastCmdStatus;
     112
     113#ifdef USE_THREADS
     114void
     115nv::queueResponse(const void *bytes, size_t len,
     116                  Response::AllocationType allocType,
     117                  Response::ResponseType type)
     118{
     119    Response *response = new Response(type);
     120    response->setMessage((unsigned char *)bytes, len, allocType);
     121    g_queue->enqueue(response);
     122}
     123#else
     124
     125ssize_t
     126nv::SocketWrite(const void *bytes, size_t len)
     127{
     128    size_t ofs = 0;
     129    ssize_t bytesWritten;
     130    while ((bytesWritten = write(g_fdOut, (const char *)bytes + ofs, len - ofs)) > 0) {
     131        ofs += bytesWritten;
     132        if (ofs == len)
     133            break;
     134    }
     135    if (bytesWritten < 0) {
     136        ERROR("write: %s", strerror(errno));
     137    }
     138    return bytesWritten;
     139}
     140
     141#endif  /*USE_THREADS*/
     142
     143bool
     144nv::SocketRead(char *bytes, size_t len)
     145{
     146    ReadBuffer::BufferStatus status;
     147    status = g_inBufPtr->followingData((unsigned char *)bytes, len);
     148    TRACE("followingData status: %d", status);
     149    return (status == ReadBuffer::OK);
     150}
     151
     152bool
     153nv::SocketRead(Rappture::Buffer &buf, size_t len)
     154{
     155    ReadBuffer::BufferStatus status;
     156    status = g_inBufPtr->followingData(buf, len);
     157    TRACE("followingData status: %d", status);
     158    return (status == ReadBuffer::OK);
     159}
     160
     161static int
     162ExecuteCommand(Tcl_Interp *interp, Tcl_DString *dsPtr)
     163{
     164    int result;
     165#ifdef WANT_TRACE
     166    char *str = Tcl_DStringValue(dsPtr);
     167    std::string cmd(str);
     168    cmd.erase(cmd.find_last_not_of(" \n\r\t")+1);
     169    TRACE("command %lu: '%s'", g_stats.nCommands+1, cmd.c_str());
     170#endif
     171    lastCmdStatus = TCL_OK;
     172    result = Tcl_EvalEx(interp, Tcl_DStringValue(dsPtr),
     173                        Tcl_DStringLength(dsPtr),
     174                        TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL);
     175    Tcl_DStringSetLength(dsPtr, 0);
     176    if (lastCmdStatus == TCL_BREAK) {
     177        return TCL_BREAK;
     178    }
     179    lastCmdStatus = result;
     180    if (result != TCL_OK) {
     181        TRACE("Error: %d", result);
     182    }
     183    return result;
     184}
     185
    104186bool
    105187GetBooleanFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, bool *boolPtr)
     
    276358 * TCL_ERROR to indicate an error.
    277359 */
    278 static int
     360int
    279361GetVolumeFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Volume **volPtrPtr)
    280362{
     
    454536GetDataStream(Tcl_Interp *interp, Rappture::Buffer &buf, int nBytes)
    455537{
    456     char buffer[8096];
    457 
    458     clearerr(NanoVis::stdin);
    459     while (nBytes > 0) {
    460         unsigned int chunk;
    461         int nRead;
    462 
    463         chunk = (sizeof(buffer) < (unsigned int) nBytes) ?
    464             sizeof(buffer) : nBytes;
    465         nRead = fread(buffer, sizeof(char), chunk, NanoVis::stdin);
    466         if (ferror(NanoVis::stdin)) {
    467             Tcl_AppendResult(interp, "while reading data stream: ",
    468                              Tcl_PosixError(interp), (char*)NULL);
    469             return TCL_ERROR;
    470         }
    471         if (feof(NanoVis::stdin)) {
    472             Tcl_AppendResult(interp, "premature EOF while reading data stream",
    473                              (char*)NULL);
    474             return TCL_ERROR;
    475         }
    476         buf.append(buffer, nRead);
    477         nBytes -= nRead;
    478     }
    479     if (NanoVis::recfile != NULL) {
    480         ssize_t nWritten;
    481 
    482         nWritten = fwrite(buf.bytes(), sizeof(char), buf.size(),
    483                           NanoVis::recfile);
    484         assert(nWritten == (ssize_t)buf.size());
    485         fflush(NanoVis::recfile);
     538    if (!SocketRead(buf, nBytes)) {
     539        return TCL_ERROR;
    486540    }
    487541    Rappture::Outcome err;
     
    621675            Tcl_Obj *const *objv)
    622676{
    623     int w, h;
    624 
    625     w = NanoVis::winWidth, h = NanoVis::winHeight;
    626 
    627     NanoVis::resizeOffscreenBuffer(2048, 2048);
    628 #ifdef notdef
    629     NanoVis::cam->setScreenSize(0, 0, NanoVis::winWidth, NanoVis::winHeight);
    630     NanoVis::cam->setScreenSize(30, 90, 2048 - 60, 2048 - 120);
    631 #endif
    632     NanoVis::bindOffscreenBuffer();  //enable offscreen render
     677    int origWidth, origHeight, width, height;
     678
     679    origWidth = NanoVis::winWidth;
     680    origHeight = NanoVis::winHeight;
     681    width = 2048;
     682    height = 2048;
     683
     684    NanoVis::resizeOffscreenBuffer(width, height);
     685    NanoVis::bindOffscreenBuffer();
    633686    NanoVis::render();
    634687    NanoVis::readScreen();
    635 
    636     NanoVis::ppmWrite("nv>image -type print -bytes %d");
    637     NanoVis::resizeOffscreenBuffer(w, h);
     688#ifdef USE_THREADS
     689    queuePPM(g_queue, "nv>image -type print -bytes",
     690             NanoVis::screenBuffer, width, height);
     691#else
     692    writePPM(g_fdOut, "nv>image -type print -bytes",
     693             NanoVis::screenBuffer, width, height);
     694#endif
     695    NanoVis::resizeOffscreenBuffer(origWidth, origHeight);
    638696
    639697    return TCL_OK;
     
    753811static int
    754812ClientInfoCmd(ClientData clientData, Tcl_Interp *interp, int objc,
    755         Tcl_Obj *const *objv)
     813              Tcl_Obj *const *objv)
    756814{
    757815    Tcl_DString ds;
     
    769827    }
    770828#ifdef KEEPSTATS
    771     int f;
    772 
    773829    /* Use the initial client key value pairs as the parts for a generating
    774830     * a unique file name. */
    775     f = NanoVis::getStatsFile(objv[1]);
     831    int f = nv::getStatsFile(interp, objv[1]);
    776832    if (f < 0) {
    777833        Tcl_AppendResult(interp, "can't open stats file: ",
     
    809865    /* date */
    810866    Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewStringObj("date", 4));
    811     strcpy(buf, ctime(&NanoVis::startTime.tv_sec));
     867    strcpy(buf, ctime(&nv::g_stats.start.tv_sec));
    812868    buf[strlen(buf) - 1] = '\0';
    813869    Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewStringObj(buf, -1));
     
    816872                Tcl_NewStringObj("date_secs", 9));
    817873    Tcl_ListObjAppendElement(interp, listObjPtr,
    818                 Tcl_NewLongObj(NanoVis::startTime.tv_sec));
     874                Tcl_NewLongObj(nv::g_stats.start.tv_sec));
    819875    /* Client arguments. */
    820876    if (Tcl_ListObjGetElements(interp, objv[1], &numItems, &items) != TCL_OK) {
     
    829885    Tcl_DStringAppend(&ds, "\n", 1);
    830886#ifdef KEEPSTATS
    831     result = NanoVis::writeToStatsFile(f, Tcl_DStringValue(&ds),
    832                                        Tcl_DStringLength(&ds));
     887    result = nv::writeToStatsFile(f, Tcl_DStringValue(&ds),
     888                                  Tcl_DStringLength(&ds));
    833889#else
    834890    TRACE("clientinfo: %s", Tcl_DStringValue(&ds));
     
    860916    }
    861917
    862     const char *name;
    863     name = Tcl_GetString(objv[1]);
    864     TransferFunction *tf = NanoVis::getTransferFunction(name);
     918    const char *tfName = Tcl_GetString(objv[1]);
     919    TransferFunction *tf = NanoVis::getTransferFunction(tfName);
    865920    if (tf == NULL) {
    866         Tcl_AppendResult(interp, "unknown transfer function \"", name, "\"",
     921        Tcl_AppendResult(interp, "unknown transfer function \"", tfName, "\"",
    867922                             (char*)NULL);
    868923        return TCL_ERROR;
     
    876931        NanoVis::setVolumeRanges();
    877932    }
    878     NanoVis::renderLegend(tf, Volume::valueMin, Volume::valueMax, w, h, name);
     933    NanoVis::renderLegend(tf, Volume::valueMin, Volume::valueMax, w, h, tfName);
    879934    return TCL_OK;
    880935}
     
    10801135        return TCL_ERROR;
    10811136    }
    1082     VolumeInterpolator* interpolator;
    1083     interpolator = NanoVis::volRenderer->getVolumeInterpolator();
     1137    VolumeInterpolator *interpolator =
     1138        NanoVis::volRenderer->getVolumeInterpolator();
    10841139    interpolator->start();
    10851140    if (interpolator->isStarted()) {
    1086         const char *fileName = (objc < 5) ? NULL : Tcl_GetString(objv[4]);
    1087         for (int frame_num = 0; frame_num < total; ++frame_num) {
     1141        const char *dirName = (objc < 5) ? NULL : Tcl_GetString(objv[4]);
     1142        for (int frameNum = 0; frameNum < total; ++frameNum) {
    10881143            float fraction;
    10891144
    1090             fraction = ((float)frame_num) / (total - 1);
     1145            fraction = ((float)frameNum) / (total - 1);
    10911146            TRACE("fraction : %f", fraction);
    1092             //interpolator->update(((float)frame_num) / (total - 1));
    10931147            interpolator->update(fraction);
    10941148
     
    11031157            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboOrig);
    11041158
    1105             NanoVis::bmpWriteToFile(frame_num, fileName);
     1159            /* FIXME: this function requires 4-byte aligned RGB rows,
     1160             * but screen buffer is now 1 byte aligned for PPM images.
     1161             */
     1162            nv::writeBMPFile(frameNum, dirName,
     1163                             NanoVis::screenBuffer,
     1164                             NanoVis::winWidth, NanoVis::winHeight);
    11061165        }
    11071166    }
     
    11851244    }
    11861245    const char *tag = Tcl_GetString(objv[4]);
    1187     Rappture::Buffer buf;
     1246
     1247    Rappture::Buffer buf(nbytes);
    11881248    if (GetDataStream(interp, buf, nbytes) != TCL_OK) {
    11891249        return TCL_ERROR;
    11901250    }
    1191     const char *bytes;
    1192     size_t nBytes;
    1193 
    1194     bytes = buf.bytes();
    1195     nBytes = buf.size();
     1251    const char *bytes = buf.bytes();
     1252    size_t nBytes = buf.size();
    11961253
    11971254    TRACE("Checking header[%.20s]", bytes);
     
    12011258    if ((nBytes > 5) && (strncmp(bytes, "<HDR>", 5) == 0)) {
    12021259        TRACE("ZincBlende Stream loading...");
    1203          //std::stringstream fdata(std::ios_base::out|std::ios_base::in|std::ios_base::binary);
    1204         //fdata.write(buf.bytes(),buf.size());
    1205         //vol = NvZincBlendeReconstructor::getInstance()->loadFromStream(fdata);
    1206 
    1207         volume = NvZincBlendeReconstructor::getInstance()->loadFromMemory((void*) buf.bytes());
     1260        volume = NvZincBlendeReconstructor::getInstance()->loadFromMemory(const_cast<char *>(bytes));
    12081261        if (volume == NULL) {
    12091262            Tcl_AppendResult(interp, "can't get volume instance", (char *)NULL);
     
    12671320        volume->visible(true);
    12681321
    1269         char info[1024];
    1270         ssize_t nWritten;
    1271 
    12721322        if (Volume::updatePending) {
    12731323            NanoVis::setVolumeRanges();
    12741324        }
    12751325
     1326        char info[1024];
    12761327        // FIXME: strlen(info) is the return value of sprintf
    1277         sprintf(info, "nv>data tag %s min %g max %g vmin %g vmax %g\n", tag,
    1278                 volume->wAxis.min(), volume->wAxis.max(),
    1279                 Volume::valueMin, Volume::valueMax);
    1280         nWritten  = write(1, info, strlen(info));
    1281         assert(nWritten == (ssize_t)strlen(info));
    1282     }
     1328        int cmdLength =
     1329            sprintf(info, "nv>data tag %s min %g max %g vmin %g vmax %g\n", tag,
     1330                    volume->wAxis.min(), volume->wAxis.max(),
     1331                    Volume::valueMin, Volume::valueMax);
     1332#ifdef USE_THREADS
     1333        queueResponse(info, cmdLength, Response::VOLATILE);
     1334#else
     1335        ssize_t nWritten  = SocketWrite(info, (size_t)cmdLength);
     1336        if (nWritten != (ssize_t)cmdLength) {
     1337            ERROR("Short write");
     1338             return TCL_ERROR;
     1339        }
     1340#endif
     1341    }
     1342
    12831343    return TCL_OK;
    12841344}
     
    13041364
    13051365static Rappture::CmdSpec volumeDataOps[] = {
    1306     {"follows",   1, VolumeDataFollowsOp, 5, 5, "size tag",},
     1366    {"follows",   1, VolumeDataFollowsOp, 5, 5, "nbytes tag",},
    13071367    {"state",     1, VolumeDataStateOp,   4, 0, "bool ?indices?",},
    13081368};
     
    14071467}
    14081468
    1409 
    14101469static Rappture::CmdSpec volumeOutlineOps[] = {
    14111470    {"color",     1, VolumeOutlineColorOp,  6, 0, "r g b ?indices?",},
     
    15961655               tf->name());
    15971656        (*iter)->transferFunction(tf);
    1598 #ifdef USE_POINTSET_RENDERER
    1599         // TBD..
    1600         if ((*iter)->pointsetIndex != -1) {
    1601             NanoVis::pointSet[(*iter)->pointsetIndex]->updateColor(tf->getData(), 256);
    1602         }
    1603 #endif
    16041657    }
    16051658    return TCL_OK;
     
    16561709    {"delete",    2, VolumeDeleteOp,      3, 0, "?name...?",},
    16571710    {"exists",    1, VolumeExistsOp,      3, 3, "name",},
    1658     {"names",     1, VolumeNamesOp,       2, 3, "?pattern?",},
     1711    {"names",     1, VolumeNamesOp,       2, 2, "",},
    16591712    {"outline",   1, VolumeOutlineOp,     3, 0, "oper ?args?",},
    16601713    {"shading",   2, VolumeShadingOp,     3, 0, "oper ?args?",},
     
    16631716static int nVolumeOps = NumCmdSpecs(volumeOps);
    16641717
    1665 /*
    1666  * ----------------------------------------------------------------------
    1667  * CLIENT COMMAND:
    1668  *   volume data state on|off ?<volumeId> ...?
    1669  *   volume outline state on|off ?<volumeId> ...?
    1670  *   volume outline color on|off ?<volumeId> ...?
    1671  *   volume shading transfunc <name> ?<volumeId> ...?
    1672  *   volume shading diffuse <value> ?<volumeId> ...?
    1673  *   volume shading specular <value> ?<volumeId> ...?
    1674  *   volume shading opacity <value> ?<volumeId> ...?
    1675  *   volume state on|off ?<volumeId> ...?
    1676  *
    1677  * Clients send these commands to manipulate the volumes.
    1678  * ----------------------------------------------------------------------
    1679  */
    16801718static int
    16811719VolumeCmd(ClientData clientData, Tcl_Interp *interp, int objc,
     
    17021740    const char *tag = Tcl_GetString(objv[4]);
    17031741
    1704     Rappture::Buffer buf;
     1742    Rappture::Buffer buf(nBytes);
    17051743    if (GetDataStream(interp, buf, nBytes) != TCL_OK) {
    17061744        return TCL_ERROR;
     
    17611799
    17621800static Rappture::CmdSpec heightMapDataOps[] = {
    1763     {"follows",  1, HeightMapDataFollowsOp, 5, 5, "size tag",},
    1764     {"visible",  1, HeightMapDataVisibleOp, 4, 0, "bool ?indices?",},
     1801    {"follows",  1, HeightMapDataFollowsOp, 5, 5, "size heightmapName",},
     1802    {"visible",  1, HeightMapDataVisibleOp, 4, 0, "bool ?heightmapNames...?",},
    17651803};
    17661804static int nHeightMapDataOps = NumCmdSpecs(heightMapDataOps);
     
    18221860
    18231861static Rappture::CmdSpec heightMapLineContourOps[] = {
    1824     {"color",   1, HeightMapLineContourColorOp,   4, 4, "length",},
    1825     {"visible", 1, HeightMapLineContourVisibleOp, 4, 0, "bool ?indices?",},
     1862    {"color",   1, HeightMapLineContourColorOp,   6, 0, "r g b ?heightmapNames...?",},
     1863    {"visible", 1, HeightMapLineContourVisibleOp, 4, 0, "bool ?heightmapNames...?",},
    18261864};
    18271865static int nHeightMapLineContourOps = NumCmdSpecs(heightMapLineContourOps);
     
    19561994}
    19571995
    1958 
    19591996static int
    19601997HeightMapOpacityOp(ClientData clientData, Tcl_Interp *interp, int objc,
     
    19782015
    19792016static Rappture::CmdSpec heightMapOps[] = {
    1980     {"create",       2, HeightMapCreateOp,      10, 10, "tag xmin ymin xmax ymax xnum ynum values",},
     2017    {"create",       2, HeightMapCreateOp,      10, 10, "heightmapName xmin ymin xmax ymax xnum ynum values",},
    19812018    {"cull",         2, HeightMapCullOp,        3, 3, "mode",},
    19822019    {"data",         1, HeightMapDataOp,        3, 0, "oper ?args?",},
    1983     {"legend",       2, HeightMapLegendOp,      5, 5, "index width height",},
     2020    {"legend",       2, HeightMapLegendOp,      5, 5, "heightmapName width height",},
    19842021    {"linecontour",  2, HeightMapLineContourOp, 2, 0, "oper ?args?",},
    1985     {"opacity",      1, HeightMapOpacityOp,     3, 0, "value ?heightmap...? ",},
     2022    {"opacity",      1, HeightMapOpacityOp,     3, 0, "value ?heightmapNames...? ",},
    19862023    {"polygon",      1, HeightMapPolygonOp,     3, 3, "mode",},
    19872024    {"shading",      1, HeightMapShadingOp,     3, 3, "model",},
    1988     {"transfunc",    2, HeightMapTransFuncOp,   3, 0, "name ?heightmap...?",},
     2025    {"transfunc",    2, HeightMapTransFuncOp,   3, 0, "name ?heightmapNames...?",},
    19892026};
    19902027static int nHeightMapOps = NumCmdSpecs(heightMapOps);
     
    21182155            return TCL_ERROR;
    21192156        }
    2120         NanoVis::axisOn = visible;
     2157        NanoVis::orientationIndicator->setVisible(visible);
    21212158    } else {
    21222159        Tcl_AppendResult(interp, "bad axis option \"", string,
     
    21272164}
    21282165
    2129 /*
    2130  * This command should be Tcl procedure instead of a C command.  The reason
    2131  * for this that 1) we are using a safe interpreter so we would need a master
    2132  * interpreter to load the Tcl environment properly (including our "unirect2d"
    2133  * procedure). And 2) the way nanovis is currently deployed doesn't make it
    2134  * easy to add new directories for procedures, since it's loaded into /tmp.
    2135  *
    2136  * Ideally, the "unirect2d" proc would do a rundimentary parsing of the data
    2137  * to verify the structure and then pass it to the appropiate Tcl command
    2138  * (heightmap, volume, etc). Our C command always creates a heightmap.
     2166static int
     2167ImageFlushCmd(ClientData clientData, Tcl_Interp *interp, int objc,
     2168              Tcl_Obj *const *objv)
     2169{
     2170    lastCmdStatus = TCL_BREAK;
     2171    return TCL_OK;
     2172}
     2173
     2174/**
     2175 * \brief Execute commands from client in Tcl interpreter
     2176 *
     2177 * In this threaded model, the select call is for event compression.  We
     2178 * want to execute render server commands as long as they keep coming. 
     2179 * This lets us execute a stream of many commands but render once.  This
     2180 * benefits camera movements, screen resizing, and opacity changes
     2181 * (using a slider on the client).  The down side is you don't render
     2182 * until there's a lull in the command stream.  If the client needs an
     2183 * image, it can issue an "imgflush" command.  That breaks us out of the
     2184 * read loop.
    21392185 */
    2140 static int
    2141 Unirect2dCmd(ClientData clientData, Tcl_Interp *interp, int objc,
    2142              Tcl_Obj *const *objv)
    2143 {
    2144     Rappture::Unirect2d *dataPtr = (Rappture::Unirect2d *)clientData;
    2145 
    2146     return dataPtr->loadData(interp, objc, objv);
    2147 }
    2148 
    2149 /*
    2150  * This command should be Tcl procedure instead of a C command.  The reason
    2151  * for this that 1) we are using a safe interpreter so we would need a master
    2152  * interpreter to load the Tcl environment properly (including our "unirect2d"
    2153  * procedure). And 2) the way nanovis is currently deployed doesn't make it
    2154  * easy to add new directories for procedures, since it's loaded into /tmp.
    2155  *
    2156  * Ideally, the "unirect2d" proc would do a rundimentary parsing of the data
    2157  * to verify the structure and then pass it to the appropiate Tcl command
    2158  * (heightmap, volume, etc). Our C command always creates a heightmap.
     2186int
     2187nv::processCommands(Tcl_Interp *interp,
     2188                    ReadBuffer *inBufPtr, int fdOut)
     2189{
     2190    int ret = 1;
     2191    int status = TCL_OK;
     2192
     2193    Tcl_DString command;
     2194    Tcl_DStringInit(&command);
     2195    fd_set readFds;
     2196    struct timeval tv, *tvPtr;
     2197
     2198    FD_ZERO(&readFds);
     2199    FD_SET(inBufPtr->file(), &readFds);
     2200    tvPtr = NULL;                       /* Wait for the first read. This is so
     2201                                         * that we don't spin when no data is
     2202                                         * available. */
     2203    while (inBufPtr->isLineAvailable() ||
     2204           (select(1, &readFds, NULL, NULL, tvPtr) > 0)) {
     2205        size_t numBytes;
     2206        unsigned char *buffer;
     2207
     2208        /* A short read is treated as an error here because we assume that we
     2209         * will always get commands line by line. */
     2210        if (inBufPtr->getLine(&numBytes, &buffer) != ReadBuffer::OK) {
     2211            /* Terminate the server if we can't communicate with the client
     2212             * anymore. */
     2213            if (inBufPtr->status() == ReadBuffer::ENDFILE) {
     2214                TRACE("Exiting server on EOF from client");
     2215                return -1;
     2216            } else {
     2217                ERROR("Exiting server, failed to read from client: %s",
     2218                      strerror(errno));
     2219                return -1;
     2220            }
     2221        }
     2222        Tcl_DStringAppend(&command, (char *)buffer, numBytes);
     2223        if (Tcl_CommandComplete(Tcl_DStringValue(&command))) {
     2224            struct timeval start, finish;
     2225            gettimeofday(&start, NULL);
     2226            status = ExecuteCommand(interp, &command);
     2227            gettimeofday(&finish, NULL);
     2228            g_stats.cmdTime += (MSECS_ELAPSED(start, finish) / 1.0e+3);
     2229            g_stats.nCommands++;
     2230            if (status == TCL_BREAK) {
     2231                return 1;               /* This was caused by a "imgflush"
     2232                                         * command. Break out of the read loop
     2233                                         * and allow a new image to be
     2234                                         * rendered. */
     2235            } else { //if (status != TCL_OK) {
     2236                ret = 0;
     2237                if (handleError(interp, status, fdOut) < 0) {
     2238                    return -1;
     2239                }
     2240            }
     2241        }
     2242
     2243        tv.tv_sec = tv.tv_usec = 0L;    /* On successive reads, we break out
     2244                                         * if no data is available. */
     2245        FD_SET(inBufPtr->file(), &readFds);
     2246        tvPtr = &tv;
     2247    }
     2248
     2249    return ret;
     2250}
     2251
     2252/**
     2253 * \brief Send error message to client socket
    21592254 */
    2160 
    2161 static int
    2162 Unirect3dCmd(ClientData clientData, Tcl_Interp *interp, int objc,
    2163              Tcl_Obj *const *objv)
    2164 {
    2165     Rappture::Unirect3d *dataPtr = (Rappture::Unirect3d *)clientData;
    2166 
    2167     return dataPtr->loadData(interp, objc, objv);
    2168 }
    2169 
    2170 Tcl_Interp *
    2171 initTcl()
     2255int
     2256nv::handleError(Tcl_Interp *interp, int status, int fdOut)
     2257{
     2258    const char *string;
     2259    int nBytes;
     2260
     2261    if (status != TCL_OK) {
     2262        string = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
     2263        nBytes = strlen(string);
     2264        if (nBytes > 0) {
     2265            TRACE("status=%d errorInfo=(%s)", status, string);
     2266
     2267            std::ostringstream oss;
     2268            oss << "nv>viserror -type internal_error -token " << g_stats.nCommands << " -bytes " << nBytes << "\n" << string;
     2269            nBytes = oss.str().length();
     2270
     2271#ifdef USE_THREADS
     2272            queueResponse(oss.str().c_str(), nBytes, Response::VOLATILE, Response::ERROR);
     2273#else
     2274            if (write(fdOut, oss.str().c_str(), nBytes) < 0) {
     2275                ERROR("write failed: %s", strerror(errno));
     2276                return -1;
     2277            }
     2278#endif
     2279        }
     2280    }
     2281
     2282    string = getUserMessages();
     2283    nBytes = strlen(string);
     2284    if (nBytes > 0) {
     2285        TRACE("userError=(%s)", string);
     2286
     2287        std::ostringstream oss;
     2288        oss << "nv>viserror -type error -token " << g_stats.nCommands << " -bytes " << nBytes << "\n" << string;
     2289        nBytes = oss.str().length();
     2290
     2291#ifdef USE_THREADS
     2292        queueResponse(oss.str().c_str(), nBytes, Response::VOLATILE, Response::ERROR);
     2293#else
     2294        if (write(fdOut, oss.str().c_str(), nBytes) < 0) {
     2295            ERROR("write failed: %s", strerror(errno));
     2296            return -1;
     2297        }
     2298#endif
     2299        clearUserMessages();
     2300    }
     2301
     2302    return 0;
     2303}
     2304
     2305void
     2306nv::initTcl(Tcl_Interp *interp, ClientData clientData)
    21722307{
    21732308    /*
     
    21782313     * a test harness through the interpreter for nanovis.
    21792314     */
    2180     Tcl_Interp *interp;
    2181     interp = Tcl_CreateInterp();
    2182     /*
     2315
    21832316    Tcl_MakeSafe(interp);
    2184     */
    2185     Tcl_CreateObjCommand(interp, "axis",        AxisCmd,        NULL, NULL);
    2186     Tcl_CreateObjCommand(interp, "camera",      CameraCmd,      NULL, NULL);
    2187     Tcl_CreateObjCommand(interp, "clientinfo",  ClientInfoCmd,  NULL, NULL);
    2188     Tcl_CreateObjCommand(interp, "cutplane",    CutplaneCmd,    NULL, NULL);
    2189     if (FlowCmdInitProc(interp) != TCL_OK) {
    2190         return NULL;
    2191     }
    2192     Tcl_CreateObjCommand(interp, "grid",        GridCmd,        NULL, NULL);
    2193     Tcl_CreateObjCommand(interp, "heightmap",   HeightMapCmd,   NULL, NULL);
    2194     Tcl_CreateObjCommand(interp, "legend",      LegendCmd,      NULL, NULL);
    2195     Tcl_CreateObjCommand(interp, "screen",      ScreenCmd,      NULL, NULL);
    2196     Tcl_CreateObjCommand(interp, "snapshot",    SnapshotCmd,    NULL, NULL);
    2197     Tcl_CreateObjCommand(interp, "transfunc",   TransfuncCmd,   NULL, NULL);
    2198     Tcl_CreateObjCommand(interp, "unirect2d",   Unirect2dCmd,   NULL, NULL);
    2199     Tcl_CreateObjCommand(interp, "unirect3d",   Unirect3dCmd,   NULL, NULL);
    2200     Tcl_CreateObjCommand(interp, "up",          UpCmd,          NULL, NULL);
    2201     Tcl_CreateObjCommand(interp, "volume",      VolumeCmd,      NULL, NULL);
     2317
     2318    Tcl_CreateObjCommand(interp, "axis",        AxisCmd,        clientData, NULL);
     2319    Tcl_CreateObjCommand(interp, "camera",      CameraCmd,      clientData, NULL);
     2320    Tcl_CreateObjCommand(interp, "clientinfo",  ClientInfoCmd,  clientData, NULL);
     2321    Tcl_CreateObjCommand(interp, "cutplane",    CutplaneCmd,    clientData, NULL);
     2322    FlowCmdInitProc(interp, clientData);
     2323    Tcl_CreateObjCommand(interp, "grid",        GridCmd,        clientData, NULL);
     2324    Tcl_CreateObjCommand(interp, "heightmap",   HeightMapCmd,   clientData, NULL);
     2325    Tcl_CreateObjCommand(interp, "imgflush",    ImageFlushCmd,  clientData, NULL);
     2326    Tcl_CreateObjCommand(interp, "legend",      LegendCmd,      clientData, NULL);
     2327    Tcl_CreateObjCommand(interp, "screen",      ScreenCmd,      clientData, NULL);
     2328    Tcl_CreateObjCommand(interp, "snapshot",    SnapshotCmd,    clientData, NULL);
     2329    Tcl_CreateObjCommand(interp, "transfunc",   TransfuncCmd,   clientData, NULL);
     2330    Tcl_CreateObjCommand(interp, "up",          UpCmd,          clientData, NULL);
     2331    Tcl_CreateObjCommand(interp, "volume",      VolumeCmd,      clientData, NULL);
    22022332
    22032333    // create a default transfer function
     
    22062336             Tcl_GetStringResult(interp));
    22072337    }
    2208     return interp;
    2209 }
     2338}
  • trunk/packages/vizservers/nanovis/Command.h

    r3597 r3605  
    1414#include <tcl.h>
    1515
     16#include <RpBuffer.h>
     17
     18#include "ResponseQueue.h"
     19
    1620namespace Rappture {
    1721class Buffer;
     
    1923class Volume;
    2024
     25namespace nv {
     26class ReadBuffer;
     27
     28#ifdef USE_THREADS
     29extern void queueResponse(const void *bytes, size_t len,
     30                          Response::AllocationType allocType,
     31                          Response::ResponseType type = Response::DATA);
     32#else
     33extern ssize_t SocketWrite(const void *bytes, size_t len);
     34#endif
     35
     36extern bool SocketRead(char *bytes, size_t len);
     37
     38extern bool SocketRead(Rappture::Buffer &buf, size_t len);
     39
     40extern int processCommands(Tcl_Interp *interp,
     41                           ReadBuffer *inBufPtr,
     42                           int fdOut);
     43
     44extern int handleError(Tcl_Interp *interp,
     45                       int status,
     46                       int fdOut);
     47
     48extern void initTcl(Tcl_Interp *interp, ClientData clientData);
     49}
     50
    2151extern int GetAxisFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
    2252                          int *axisVal);
    2353
    24 extern int GetBooleanFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
     54extern bool GetBooleanFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
    2555                             bool *boolVal);
    2656
     
    3363                            Volume **volume);
    3464
    35 extern Tcl_Interp *initTcl();
    36 
    3765#endif
  • trunk/packages/vizservers/nanovis/FlowCmd.cpp

    r3598 r3605  
    2525#include "nvconf.h"
    2626
     27#include "nanovisServer.h"
    2728#include "nanovis.h"
    2829#include "CmdProc.h"
    2930#include "Command.h"
     31#include "PPMWriter.h"
    3032#include "FlowCmd.h"
    3133#include "FlowTypes.h"
     
    4143#include "Trace.h"
    4244
     45using namespace nv;
    4346using namespace vrmath;
    4447
     
    231234        return TCL_ERROR;
    232235    }
    233     Rappture::Buffer buf;
     236    Rappture::Buffer buf(nBytes);
    234237    TRACE("Flow data loading bytes: %d components: %d", nBytes, nComponents);
    235238    if (GetDataStream(interp, buf, nBytes) != TCL_OK) {
    236239        return TCL_ERROR;
    237240    }
     241    char *bytes = (char *)buf.bytes();
     242    size_t length = buf.size();
     243
    238244    Rappture::Unirect3d *dataPtr;
    239245    dataPtr = new Rappture::Unirect3d(nComponents);
    240246
    241247    Flow *flow = (Flow *)clientData;
    242     size_t length = buf.size();
    243     char *bytes = (char *)buf.bytes();
    244248    if ((length > 4) && (strncmp(bytes, "<DX>", 4) == 0)) {
    245249        if (!dataPtr->importDx(result, nComponents, length - 4, bytes + 4)) {
     
    292296    {
    293297        char info[1024];
    294         ssize_t nWritten;
    295         size_t length;
    296 
    297         length = sprintf(info, "nv>data tag %s min %g max %g\n",
    298                          flow->name(), dataPtr->magMin(), dataPtr->magMax());
    299         nWritten  = write(1, info, length);
    300         assert(nWritten == (ssize_t)strlen(info));
     298        int length =
     299            sprintf(info, "nv>data tag %s min %g max %g\n",
     300                    flow->name(), dataPtr->magMin(), dataPtr->magMax());
     301#ifdef USE_THREADS
     302        queueResponse(info, (size_t)length, Response::VOLATILE);
     303#else
     304        if (SocketWrite(info, (size_t)length) < 0) {
     305            return TCL_ERROR;
     306        }
     307#endif
    301308    }
    302309    NanoVis::eventuallyRedraw(NanoVis::MAP_FLOWS);
     
    10641071
    10651072static int
    1066 ppmWriteToFile(Tcl_Interp *interp, const char *path, FlowVideoSwitches *switchesPtr)
    1067 {
    1068     int f;
    1069    
    1070     /* Open the named file for writing. */
    1071     f = creat(path, 0600);
    1072     if (f < 0) {
    1073         Tcl_AppendResult(interp, "can't open temporary image file \"", path,
    1074                          "\": ", Tcl_PosixError(interp), (char *)NULL);
    1075         return TCL_ERROR;
    1076     }
    1077     // Generate the PPM binary file header
    1078     char header[200];
    1079 #define PPM_MAXVAL 255
    1080     sprintf(header, "P6 %d %d %d\n", switchesPtr->width, switchesPtr->height,
    1081         PPM_MAXVAL);
    1082 
    1083     size_t header_length = strlen(header);
    1084     size_t wordsPerRow = (switchesPtr->width * 24 + 31) / 32;
    1085     size_t bytesPerRow = wordsPerRow * 4;
    1086     size_t rowLength = switchesPtr->width * 3;
    1087     size_t numRecords = switchesPtr->height + 1;
    1088 
    1089     struct iovec *iov;
    1090     iov = (struct iovec *)malloc(sizeof(struct iovec) * numRecords);
    1091 
    1092     // Add the PPM image header.
    1093     iov[0].iov_base = header;
    1094     iov[0].iov_len = header_length;
    1095 
    1096     // Now add the image data, reversing the order of the rows.
    1097     int y;
    1098     unsigned char *srcRowPtr = NanoVis::screenBuffer;
    1099     /* Reversing the pointers for the image rows.  PPM is top-to-bottom. */
    1100     for (y = switchesPtr->height; y >= 1; y--) {
    1101         iov[y].iov_base = srcRowPtr;
    1102         iov[y].iov_len = rowLength;
    1103         srcRowPtr += bytesPerRow;
    1104     }
    1105     if (writev(f, iov, numRecords) < 0) {
    1106         Tcl_AppendResult(interp, "writing image to \"", path, "\" failed: ",
    1107                          Tcl_PosixError(interp), (char *)NULL);
    1108         free(iov);
    1109         close(f);
    1110         return TCL_ERROR;
    1111     }
    1112     close(f);
    1113     free(iov);
    1114     return TCL_OK;
    1115 }
    1116 
    1117 static int
    11181073MakeImageFiles(Tcl_Interp *interp, char *tmpFileName,
    11191074               FlowVideoSwitches *switchesPtr, bool *cancelPtr)
    11201075{
    11211076    struct pollfd pollResults;
    1122     pollResults.fd = fileno(NanoVis::stdin);
     1077    pollResults.fd = fileno(nv::g_fIn);
    11231078    pollResults.events = POLLIN;
    11241079#define PENDING_TIMEOUT          10  /* milliseconds. */
     
    11601115
    11611116        sprintf(tmpFileName + length, "/image%d.ppm", i);
    1162         result = ppmWriteToFile(interp, tmpFileName, switchesPtr);
     1117        result = nv::writePPMFile(tmpFileName, NanoVis::screenBuffer,
     1118                                  switchesPtr->width, switchesPtr->height);
    11631119        if (result != TCL_OK) {
    11641120            break;
     
    12301186    sprintf(cmd,"nv>image -type movie -token \"%s\" -bytes %lu\n",
    12311187            token, (unsigned long)data.size());
    1232     NanoVis::sendDataToClient(cmd, data.bytes(), data.size());
     1188    nv::sendDataToClient(cmd, data.bytes(), data.size());
    12331189    return TCL_OK;
    12341190}
     
    12921248        sprintf(tmpFileName + length, "/image%d.ppm", i);
    12931249        unlink(tmpFileName);
    1294     }       
     1250    }
    12951251    tmpFileName[length] = '\0';
    12961252    rmdir(tmpFileName);
     
    13431299 *    associative array.
    13441300 */
    1345 int
    1346 FlowCmdInitProc(Tcl_Interp *interp)
    1347 {
    1348     Tcl_CreateObjCommand(interp, "flow", FlowCmdProc, NULL, NULL);
    1349     return TCL_OK;
    1350 }
     1301void
     1302FlowCmdInitProc(Tcl_Interp *interp, ClientData clientData)
     1303{
     1304    Tcl_CreateObjCommand(interp, "flow", FlowCmdProc, clientData, NULL);
     1305}
  • trunk/packages/vizservers/nanovis/FlowCmd.h

    r3597 r3605  
    2727#include <tcl.h>
    2828
    29 extern Tcl_AppInitProc FlowCmdInitProc;
     29extern void FlowCmdInitProc(Tcl_Interp *interp, ClientData clientData);
     30
    3031extern Tcl_ObjCmdProc FlowInstObjCmd;
    3132extern Tcl_CmdDeleteProc FlowInstDeleteProc;
  • trunk/packages/vizservers/nanovis/Grid.cpp

    r3502 r3605  
    3636void Grid::render()
    3737{
     38    if (!isVisible())
     39        return;
     40
    3841    glPushAttrib(GL_ENABLE_BIT);
    3942
  • trunk/packages/vizservers/nanovis/HeightMap.cpp

    r3597 r3605  
    5757HeightMap::render(RenderContext *renderContext)
    5858{
     59    if (!isVisible())
     60        return;
     61
    5962    glPushAttrib(GL_ENABLE_BIT | GL_POLYGON_BIT | GL_LIGHTING_BIT);
    6063
  • trunk/packages/vizservers/nanovis/Makefile.in

    r3598 r3605  
    1 TRACE           = #yes
     1TRACE                   = #yes
     2USE_THREADS             = yes
     3USE_POINTSET_RENDERER   = #yes
    24
    35SHELL = /bin/sh
     
    2325INSTALL_SCRIPT  = ${INSTALL} -m 0444
    2426RM              = rm -f
    25 
    26 AUXSRC          = config.h define.h
    2727
    2828CG_INC_SPEC     = @CG_INC_SPEC@
     
    8989                $(RP_INC_SPEC)
    9090
    91 USE_POINTSET_RENDERER = #yes
    92 
    9391CC              = @CC@
    9492CXX             = @CXX@
     
    9997DEFINES         += -DWANT_TRACE
    10098endif
     99ifdef USE_THREADS
     100DEFINES         += -DUSE_THREADS
     101endif
    101102ifdef USE_POINTSET_RENDERER
    102103DEFINES         += -DUSE_POINTSET_RENDERER
     
    106107OBJS            = \
    107108                Axis.o \
     109                BMPWriter.o \
    108110                Chain.o \
    109111                CmdProc.o \
     
    129131                NvZincBlendeReconstructor.o \
    130132                NvZincBlendeVolumeShader.o \
     133                OrientationIndicator.o \
    131134                PerfQuery.o \
    132135                Plane.o \
    133136                PlaneRenderer.o \
     137                PPMWriter.o \
     138                ReadBuffer.o \
    134139                ReaderCommon.o \
    135140                RenderVertexArray.o \
     141                ResponseQueue.o \
    136142                Switch.o \
    137143                Texture1D.o \
     
    148154                ZincBlendeVolume.o \
    149155                dxReader.o \
     156                md5.o \
    150157                nanovis.o \
    151                 md5.o
     158                nanovisServer.o
    152159
    153160resources       = \
     
    270277
    271278Axis.o: Axis.cpp Axis.h Chain.h
     279BMPWriter.o: BMPWriter.cpp nanovis.h
    272280BucketSort.o: BucketSort.cpp BucketSort.h $(VRMATH_DIR)/include/vrmath/Vector3f.h $(VRMATH_DIR)/include/vrmath/Vector4f.h $(VRMATH_DIR)/include/vrmath/Matrix4x4d.h PCASplit.h
    273281Chain.o: Chain.cpp Chain.h
    274282CmdProc.o: CmdProc.cpp CmdProc.h
    275 Command.o: Command.cpp nanovis.h $(AUXSRC) FlowCmd.h CmdProc.h Trace.h PlaneRenderer.h PointSet.h dxReader.h Grid.h HeightMap.h NvCamera.h NvZincBlendeReconstructor.h Unirect.h Volume.h VolumeRenderer.h
     283Command.o: Command.cpp nanovis.h config.h define.h FlowCmd.h CmdProc.h Trace.h PlaneRenderer.h PPMWriter.h BMPWriter.h dxReader.h Grid.h HeightMap.h NvCamera.h NvZincBlendeReconstructor.h OrientationIndicator.h Unirect.h Volume.h VolumeRenderer.h
    276284ContourLineFilter.o: ContourLineFilter.cpp ContourLineFilter.h
    277285ConvexPolygon.o: ConvexPolygon.cpp ConvexPolygon.h $(VRMATH_DIR)/include/vrmath/Vector4f.h $(VRMATH_DIR)/include/vrmath/Matrix4x4d.h Plane.h
    278286Flow.o: Flow.cpp Flow.h FlowCmd.h FlowTypes.h FlowBox.h FlowParticles.h Switch.h Trace.h
    279287FlowBox.o: FlowBox.cpp 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
    280 FlowCmd.o: FlowCmd.cpp FlowCmd.h FlowParticles.h FlowBox.h FlowTypes.h Command.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
     288FlowCmd.o: FlowCmd.cpp FlowCmd.h FlowParticles.h FlowBox.h FlowTypes.h Command.h PPMWriter.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
    281289FlowParticles.o: FlowParticles.cpp 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
    282290GradientFilter.o: GradientFilter.cpp GradientFilter.h
     
    294302NvZincBlendeReconstructor.o: NvZincBlendeReconstructor.cpp NvZincBlendeReconstructor.h ZincBlendeVolume.h Volume.h $(VRMATH_DIR)/include/vrmath/Vector3f.h
    295303NvZincBlendeVolumeShader.o: NvZincBlendeVolumeShader.cpp NvZincBlendeVolumeShader.h NvVolumeShader.h NvShader.h
     304OrientationIndicator.o: OrientationIndicator.cpp OrientationIndicator.h
    296305ParticleEmitter.o: ParticleEmitter.cpp ParticleEmitter.h
    297306ParticleSystem.o: ParticleSystem.cpp ParticleSystem.h DataLoader.h
     
    304313PointSetRenderer.o: PointSetRenderer.cpp PointSetRenderer.h
    305314PointShader.o: PointShader.cpp PointShader.h
     315PPMWriter.o: PPMWriter.cpp PPMWriter.h
    306316ReaderCommon.o: ReaderCommon.cpp ReaderCommon.h GradientFilter.h $(VRMATH_DIR)/include/vrmath/Vector3f.h
    307317RenderVertexArray.o: RenderVertexArray.cpp RenderVertexArray.h
    308318Switch.o: Switch.cpp Switch.h
    309319Texture1D.o: Texture1D.cpp Texture1D.h
    310 Texture2D.o: Texture2D.cpp Texture2D.h $(AUXSRC)
    311 Texture3D.o: Texture3D.cpp Texture3D.h $(AUXSRC)
     320Texture2D.o: Texture2D.cpp Texture2D.h config.h define.h
     321Texture3D.o: Texture3D.cpp Texture3D.h config.h define.h
    312322Trace.o: Trace.cpp Trace.h
    313323TransferFunction.o: TransferFunction.cpp
    314324Unirect.o: Unirect.cpp Unirect.h Command.h Trace.h
    315325VelocityArrowsSlice.o: VelocityArrowsSlice.cpp VelocityArrowsSlice.h
    316 Volume.o: Volume.cpp Volume.h $(AUXSRC)
     326Volume.o: Volume.cpp Volume.h config.h define.h
    317327VolumeInterpolator.o: VolumeInterpolator.cpp VolumeInterpolator.h Volume.h
    318328VolumeRenderer.o: VolumeRenderer.cpp VolumeRenderer.h
    319329VtkReader.o: VtkReader.h Trace.h Volume.h $(VRMATH_DIR)/include/vrmath/Vector3f.h ReaderCommon.h nanovis.h
    320 ZincBlendeVolume.o: ZincBlendeVolume.cpp ZincBlendeVolume.h $(AUXSRC)
     330ZincBlendeVolume.o: ZincBlendeVolume.cpp ZincBlendeVolume.h config.h define.h
    321331dxReader.o: dxReader.cpp ReaderCommon.h config.h nanovis.h Unirect.h ZincBlendeVolume.h NvZincBlendeReconstructor.h
    322 nanovis.o: nanovis.cpp nanovis.h $(AUXSRC) Command.h Flow.h Grid.h HeightMap.h NvCamera.h NvLIC.h NvZincBlendeReconstructor.h PerfQuery.h PlaneRenderer.h PointSetRenderer.h PointSet.h Switch.h Trace.h Unirect.h VelocityArrowsSlice.h VolumeInterpolator.h VolumeRenderer.h ZincBlendeVolume.h Axis.h Chain.h
    323332md5.o: md5.h
     333nanovis.o: nanovis.cpp nanovis.h config.h define.h Command.h Flow.h Grid.h HeightMap.h NvCamera.h NvLIC.h NvZincBlendeReconstructor.h OrientationIndicator.h PerfQuery.h PlaneRenderer.h PointSetRenderer.h PointSet.h Switch.h Trace.h Unirect.h VelocityArrowsSlice.h VolumeInterpolator.h VolumeRenderer.h ZincBlendeVolume.h Axis.h Chain.h
     334nanovisServer.o: nanovisServer.cpp nanovisServer.h config.h nanovis.h define.h Command.h PPMWriter.h ReadBuffer.h NvShader.h ResponseQueue.h Trace.h
  • trunk/packages/vizservers/nanovis/Trace.cpp

    r3597 r3605  
    1010#include <string.h>
    1111
     12#include <string>
     13#include <sstream>
     14
    1215#include <GL/glew.h>
    1316
     
    1518#include "Trace.h"
    1619
     20using namespace nv;
     21
     22static std::ostringstream g_UserErrorString;
     23
    1724#define MSG_LEN 2047
    1825
     26/**
     27 * \brief Open syslog for writing
     28 */
     29void
     30nv::initLog()
     31{
     32    openlog("nanovis", LOG_CONS | LOG_PERROR | LOG_PID,  LOG_USER);
     33}
     34
     35/**
     36 * \brief Close syslog
     37 */
     38void
     39nv::closeLog()
     40{
     41    closelog();
     42}
     43
     44/**
     45 * \brief Write a message to syslog
     46 */
    1947void
    20 LogMessage(int priority, const char *funcname,
    21            const char *path, int lineNum, const char* fmt, ...)
     48nv::LogMessage(int priority, const char *funcname,
     49               const char *path, int lineNum, const char* fmt, ...)
    2250{
    2351    char message[MSG_LEN+1];
     
    4270
    4371    syslog(priority, "%s", message);
     72}
     73
     74/**
     75 * \brief Write a user message to buffer
     76 */
     77void
     78nv::logUserMessage(const char* fmt, ...)
     79{
     80    char message[MSG_LEN + 1];
     81    int length = 0;
     82    va_list lst;
     83
     84    va_start(lst, fmt);
     85
     86    length += vsnprintf(message, MSG_LEN, fmt, lst);
     87    message[MSG_LEN] = '\0';
     88
     89    g_UserErrorString << message << "\n";
     90}
     91
     92const char *
     93nv::getUserMessages()
     94{
     95    return g_UserErrorString.str().c_str();
     96}
     97
     98void
     99nv::clearUserMessages()
     100{
     101    g_UserErrorString.str(std::string());
    44102}
    45103
     
    116174    return false;
    117175}
    118 
    119 
  • trunk/packages/vizservers/nanovis/Trace.h

    r3597 r3605  
    1818#define AT __FILE__ ":" NEWSTRING(__LINE__)
    1919
     20namespace nv {
     21
     22extern void logUserMessage(const char* format, ...);
     23
     24extern const char *getUserMessages();
     25
     26extern void clearUserMessages();
     27
     28extern void initLog();
     29
     30extern void closeLog();
     31
    2032extern void LogMessage(int priority, const char *funcname, const char *fileName,
    2133                       int lineNum, const char* format, ...);
    2234
    23 #define ERROR(...)      LogMessage(LOG_ERR, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
     35#define ERROR(...)      nv::LogMessage(LOG_ERR, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
    2436#ifdef WANT_TRACE
    25 #define TRACE(...)      LogMessage(LOG_DEBUG, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
     37#define TRACE(...)      nv::LogMessage(LOG_DEBUG, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
    2638#else
    2739#define TRACE(...)
    2840#endif
    29 #define WARN(...)       LogMessage(LOG_WARNING, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
    30 #define INFO(...)       LogMessage(LOG_INFO, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
     41#define WARN(...)       nv::LogMessage(LOG_WARNING, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
     42#define INFO(...)       nv::LogMessage(LOG_INFO, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
     43
     44#define USER_ERROR(...) nv::logUserMessage(__VA_ARGS__)
     45
     46}
    3147
    3248extern bool CheckFBO(GLenum *status);
    3349extern void PrintFBOStatus(GLenum status, const char *prefix);
    3450extern bool CheckGL(const char *prefix);
     51
    3552#endif
  • trunk/packages/vizservers/nanovis/Unirect.cpp

    r3597 r3605  
    4545Rappture::Unirect2d::parseBuffer(Tcl_Interp *interp, Rappture::Buffer &buf)
    4646{
    47     Tcl_Obj *objPtr;
    48     objPtr = Tcl_NewStringObj(buf.bytes(), buf.size());
     47    Tcl_Obj *objPtr = Tcl_NewStringObj(buf.bytes(), buf.size());
    4948    Tcl_Obj **objv;
    5049    int objc;
     
    5251        return TCL_ERROR;
    5352    }
    54     int result;
    55     result = loadData(interp, objc, objv);
     53    int result = loadData(interp, objc, objv);
    5654    Tcl_DecrRefCount(objPtr);
    5755    if ((result != TCL_OK) || (!isInitialized())) {
  • trunk/packages/vizservers/nanovis/Unirect.h

    r3502 r3605  
    99
    1010#include <float.h>
     11
     12#include <tcl.h>
    1113
    1214#include <rappture.h>
  • trunk/packages/vizservers/nanovis/dxReader.cpp

    r3597 r3605  
    4343#include "ZincBlendeVolume.h"
    4444#include "NvZincBlendeReconstructor.h"
    45 #ifdef USE_POINTSET_RENDERER
    46 #include "PointSet.h"
    47 #endif
    4845
    4946/**
     
    488485    volume->updatePending = true;
    489486
    490     // TBD..
    491 #if 0 && defined(USE_POINTSET_RENDERER)
    492     PointSet *pset = new PointSet();
    493     pset->initialize(volume, (float*)data);
    494     pset->setVisible(true);
    495     NanoVis::pointSet.push_back(pset);
    496     updateColor(pset);
    497     volume->pointsetIndex = NanoVis::pointSet.size() - 1;
    498 #endif
    499487    delete [] data;
    500488
  • trunk/packages/vizservers/nanovis/nanovis.cpp

    r3597 r3605  
    1616 */
    1717
    18 #include <assert.h>
    19 #include <errno.h>
    20 #include <fcntl.h>
    21 #include <getopt.h>
    22 #include <memory.h>
    23 #include <signal.h>
    24 #include <sys/resource.h>
    25 #include <sys/stat.h>
    2618#include <sys/time.h>
    27 #include <sys/times.h>
    28 #include <sys/types.h>
    29 #include <sys/uio.h> // for readv/writev
    30 #include <time.h>
    31 #include <unistd.h>
    32 
    33 #include <cstdlib>
     19#include <cassert>
    3420#include <cstdio>
    35 #include <cstring>
    36 #include <cmath>
    37 
    38 #include <iostream>
    39 #include <fstream>
    40 #include <sstream>
    41 #include <string>
    4221
    4322#include <GL/glew.h>
    4423#include <GL/glut.h>
    4524
    46 #include <RpEncode.h>
    47 
    4825#include <graphics/RenderContext.h>
    4926#include <vrmath/Vector3f.h>
     
    5734#include "config.h"
    5835#include "nanovis.h"
     36#include "nanovisServer.h"
    5937#include "define.h"
    6038
    61 #include "Command.h"
    6239#include "Flow.h"
    6340#include "Grid.h"
    6441#include "HeightMap.h"
    6542#include "NvCamera.h"
     43#include "NvLIC.h"
    6644#include "NvShader.h"
    67 #include "NvLIC.h"
    68 #include "NvZincBlendeReconstructor.h"
     45#include "OrientationIndicator.h"
    6946#include "PlaneRenderer.h"
    70 #ifdef USE_POINTSET_RENDERER
    71 #include "PointSetRenderer.h"
    72 #include "PointSet.h"
    73 #endif
    74 #include "Switch.h"
     47#include "PPMWriter.h"
     48#include "Texture2D.h"
    7549#include "Trace.h"
     50#include "TransferFunction.h"
    7651#include "Unirect.h"
    7752#include "VelocityArrowsSlice.h"
     53#include "Volume.h"
    7854#include "VolumeInterpolator.h"
    7955#include "VolumeRenderer.h"
    80 #include "ZincBlendeVolume.h"
    81 
     56
     57using namespace nv;
    8258using namespace nv::graphics;
    8359using namespace nv::util;
    8460using namespace vrmath;
    8561
    86 #define SIZEOF_BMP_HEADER   54
    87 
    88 #define CVT2SECS(x)  ((double)(x).tv_sec) + ((double)(x).tv_usec * 1.0e-6)
    89 
    90 #define TRUE    1
    91 #define FALSE   0
    92 
    93 typedef struct {
    94     pid_t pid;
    95     size_t nFrames;            /**< # of frames sent to client. */
    96     size_t nBytes;             /**< # of bytes for all frames. */
    97     size_t nCommands;          /**< # of commands executed */
    98     double cmdTime;            /**< Elasped time spend executing
    99                                 * commands. */
    100     struct timeval start;      /**< Start of elapsed time. */
    101 } Stats;
    102 
    103 static Stats stats;
    104 
    10562// STATIC MEMBER DATA
    10663
    107 FILE *NanoVis::stdin = NULL;
    108 FILE *NanoVis::logfile = NULL;
    109 FILE *NanoVis::recfile = NULL;
    110 
    111 int NanoVis::statsFile = -1;
     64Tcl_Interp *NanoVis::interp = NULL;
    11265
    11366unsigned int NanoVis::flags = 0;
    11467bool NanoVis::debugFlag = false;
    115 bool NanoVis::axisOn = true;
    116 struct timeval NanoVis::startTime;
    11768
    11869int NanoVis::winWidth = NPIX;
     
    12172unsigned char *NanoVis::screenBuffer = NULL;
    12273Texture2D *NanoVis::legendTexture = NULL;
    123 Grid *NanoVis::grid = NULL;
    12474Fonts *NanoVis::fonts;
    12575int NanoVis::updir = Y_POS;
     
    14898NvLIC *NanoVis::licRenderer = NULL;
    14999PlaneRenderer *NanoVis::planeRenderer = NULL;
    150 #ifdef USE_POINTSET_RENDERER
    151 PointSetRenderer *NanoVis::pointSetRenderer = NULL;
    152 std::vector<PointSet *> NanoVis::pointSet;
    153 #endif
    154 
    155 Tcl_Interp *NanoVis::interp;
     100OrientationIndicator *NanoVis::orientationIndicator = NULL;
     101Grid *NanoVis::grid = NULL;
    156102
    157103// Image based flow visualization slice location
     
    213159        screenBuffer = NULL;
    214160    }
    215 #ifdef USE_POINTSET_RENDERER
    216     if (pointSetRenderer != NULL) {
    217         TRACE("Deleting pointSetRenderer");
    218         delete pointSetRenderer;
    219     }
    220     for (std::vector<PointSet *>::iterator itr = pointSet.begin();
    221          itr != pointSet.end(); ++itr) {
    222         TRACE("Deleting pointSet: %p", *itr);
    223         delete (*itr);
    224     }
    225 #endif
    226161    if (fonts != NULL) {
    227162        TRACE("Deleting fonts");
     
    241176        flags |= REDRAW_PENDING;
    242177    }
    243 }
    244 
    245 #ifdef KEEPSTATS
    246 
    247 #ifndef STATSDIR
    248 #define STATSDIR        "/var/tmp/visservers"
    249 #endif  /*STATSDIR*/
    250 
    251 int
    252 NanoVis::getStatsFile(Tcl_Obj *objPtr)
    253 {
    254     Tcl_DString ds;
    255     Tcl_Obj **objv;
    256     int objc;
    257     int i;
    258     char fileName[33];
    259     const char *path;
    260     md5_state_t state;
    261     md5_byte_t digest[16];
    262     char *string;
    263     int length;
    264 
    265     if ((objPtr == NULL) || (statsFile >= 0)) {
    266         return statsFile;
    267     }
    268     if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
    269         return -1;
    270     }
    271     Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("pid", 3));
    272     Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewIntObj(getpid()));
    273     string = Tcl_GetStringFromObj(objPtr, &length);
    274 
    275     md5_init(&state);
    276     md5_append(&state, (const md5_byte_t *)string, length);
    277     md5_finish(&state, digest);
    278     for (i = 0; i < 16; i++) {
    279         sprintf(fileName + i * 2, "%02x", digest[i]);
    280     }
    281     Tcl_DStringInit(&ds);
    282     Tcl_DStringAppend(&ds, STATSDIR, -1);
    283     Tcl_DStringAppend(&ds, "/", 1);
    284     Tcl_DStringAppend(&ds, fileName, 32);
    285     path = Tcl_DStringValue(&ds);
    286 
    287     statsFile = open(path, O_EXCL | O_CREAT | O_WRONLY, 0600);
    288     Tcl_DStringFree(&ds);
    289     if (statsFile < 0) {
    290         ERROR("can't open \"%s\": %s", fileName, strerror(errno));
    291         return -1;
    292     }
    293     return statsFile;
    294 }
    295 
    296 int
    297 NanoVis::writeToStatsFile(int f, const char *s, size_t length)
    298 {
    299     if (f >= 0) {
    300         ssize_t numWritten;
    301 
    302         numWritten = write(f, s, length);
    303         if (numWritten == (ssize_t)length) {
    304             close(dup(f));
    305         }
    306     }
    307     return 0;
    308 }
    309 
    310 static int
    311 serverStats(int code)
    312 {
    313     double start, finish;
    314     char buf[BUFSIZ];
    315     Tcl_DString ds;
    316     int result;
    317     int f;
    318 
    319     {
    320         struct timeval tv;
    321 
    322         /* Get ending time.  */
    323         gettimeofday(&tv, NULL);
    324         finish = CVT2SECS(tv);
    325         tv = stats.start;
    326         start = CVT2SECS(tv);
    327     }
    328     /*
    329      * Session information:
    330      *   - Name of render server
    331      *   - Process ID
    332      *   - Hostname where server is running
    333      *   - Start date of session
    334      *   - Start date of session in seconds
    335      *   - Number of frames returned
    336      *   - Number of bytes total returned (in frames)
    337      *   - Number of commands received
    338      *   - Total elapsed time of all commands
    339      *   - Total elapsed time of session
    340      *   - Exit code of vizserver
    341      *   - User time
    342      *   - System time
    343      *   - User time of children
    344      *   - System time of children
    345      */
    346 
    347     Tcl_DStringInit(&ds);
    348    
    349     Tcl_DStringAppendElement(&ds, "render_stop");
    350     /* renderer */
    351     Tcl_DStringAppendElement(&ds, "renderer");
    352     Tcl_DStringAppendElement(&ds, "nanovis");
    353     /* pid */
    354     Tcl_DStringAppendElement(&ds, "pid");
    355     sprintf(buf, "%d", getpid());
    356     Tcl_DStringAppendElement(&ds, buf);
    357     /* host */
    358     Tcl_DStringAppendElement(&ds, "host");
    359     gethostname(buf, BUFSIZ-1);
    360     buf[BUFSIZ-1] = '\0';
    361     Tcl_DStringAppendElement(&ds, buf);
    362     /* date */
    363     Tcl_DStringAppendElement(&ds, "date");
    364     strcpy(buf, ctime(&stats.start.tv_sec));
    365     buf[strlen(buf) - 1] = '\0';
    366     Tcl_DStringAppendElement(&ds, buf);
    367     /* date_secs */
    368     Tcl_DStringAppendElement(&ds, "date_secs");
    369     sprintf(buf, "%ld", stats.start.tv_sec);
    370     Tcl_DStringAppendElement(&ds, buf);
    371     /* num_frames */
    372     Tcl_DStringAppendElement(&ds, "num_frames");
    373     sprintf(buf, "%lu", (unsigned long int)stats.nFrames);
    374     Tcl_DStringAppendElement(&ds, buf);
    375     /* frame_bytes */
    376     Tcl_DStringAppendElement(&ds, "frame_bytes");
    377     sprintf(buf, "%lu", (unsigned long int)stats.nBytes);
    378     Tcl_DStringAppendElement(&ds, buf);
    379     /* num_commands */
    380     Tcl_DStringAppendElement(&ds, "num_commands");
    381     sprintf(buf, "%lu", (unsigned long int)stats.nCommands);
    382     Tcl_DStringAppendElement(&ds, buf);
    383     /* cmd_time */
    384     Tcl_DStringAppendElement(&ds, "cmd_time");
    385     sprintf(buf, "%g", stats.cmdTime);
    386     Tcl_DStringAppendElement(&ds, buf);
    387     /* session_time */
    388     Tcl_DStringAppendElement(&ds, "session_time");
    389     sprintf(buf, "%g", finish - start);
    390     Tcl_DStringAppendElement(&ds, buf);
    391     /* status */
    392     Tcl_DStringAppendElement(&ds, "status");
    393     sprintf(buf, "%d", code);
    394     Tcl_DStringAppendElement(&ds, buf);
    395     {
    396         long clocksPerSec = sysconf(_SC_CLK_TCK);
    397         double clockRes = 1.0 / clocksPerSec;
    398         struct tms tms;
    399 
    400         memset(&tms, 0, sizeof(tms));
    401         times(&tms);
    402         /* utime */
    403         Tcl_DStringAppendElement(&ds, "utime");
    404         sprintf(buf, "%g", tms.tms_utime * clockRes);
    405         Tcl_DStringAppendElement(&ds, buf);
    406         /* stime */
    407         Tcl_DStringAppendElement(&ds, "stime");
    408         sprintf(buf, "%g", tms.tms_stime * clockRes);
    409         Tcl_DStringAppendElement(&ds, buf);
    410         /* cutime */
    411         Tcl_DStringAppendElement(&ds, "cutime");
    412         sprintf(buf, "%g", tms.tms_cutime * clockRes);
    413         Tcl_DStringAppendElement(&ds, buf);
    414         /* cstime */
    415         Tcl_DStringAppendElement(&ds, "cstime");
    416         sprintf(buf, "%g", tms.tms_cstime * clockRes);
    417         Tcl_DStringAppendElement(&ds, buf);
    418     }
    419     Tcl_DStringAppend(&ds, "\n", -1);
    420     f = NanoVis::getStatsFile(NULL);
    421     result = NanoVis::writeToStatsFile(f, Tcl_DStringValue(&ds),
    422                                        Tcl_DStringLength(&ds));
    423     close(f);
    424     Tcl_DStringFree(&ds);
    425     return result;
    426 }
    427 
    428 #endif
    429 
    430 static void
    431 initService()
    432 {
    433     TRACE("Enter");
    434 
    435     const char* user = getenv("USER");
    436     char* logName = NULL;
    437     int logNameLen = 0;
    438 
    439     if (user == NULL) {
    440         logNameLen = 20+1;
    441         logName = (char *)calloc(logNameLen, sizeof(char));
    442         strncpy(logName, "/tmp/nanovis_log.txt", logNameLen);
    443     } else {
    444         logNameLen = 17+1+strlen(user);
    445         logName = (char *)calloc(logNameLen, sizeof(char));
    446         strncpy(logName, "/tmp/nanovis_log_", logNameLen);
    447         strncat(logName, user, strlen(user));
    448     }
    449 
    450     //open log and map stderr to log file
    451     NanoVis::logfile = fopen(logName, "w");
    452     dup2(fileno(NanoVis::logfile), 2);
    453     /* dup2(2,1); */
    454 
    455     // clean up malloc'd memory
    456     if (logName != NULL) {
    457         free(logName);
    458     }
    459 
    460     TRACE("Leave");
    461 }
    462 
    463 static void
    464 exitService(int code)
    465 {
    466     TRACE("Enter: %d", code);
    467 
    468     NanoVis::removeAllData();
    469 
    470     NvShader::exitCg();
    471 
    472     //close log file
    473     if (NanoVis::logfile != NULL) {
    474         fclose(NanoVis::logfile);
    475         NanoVis::logfile = NULL;
    476     }
    477 
    478 #ifdef KEEPSTATS
    479     serverStats(code);
    480 #endif
    481     closelog();
    482 
    483     exit(code);
    484 }
    485 
    486 static int
    487 executeCommand(Tcl_Interp *interp, Tcl_DString *dsPtr)
    488 {
    489     struct timeval tv;
    490     double start, finish;
    491     int result;
    492 
    493 #ifdef WANT_TRACE
    494     char *str = Tcl_DStringValue(dsPtr);
    495     std::string cmd(str);
    496     cmd.erase(cmd.find_last_not_of(" \n\r\t")+1);
    497     TRACE("command %lu: '%s'", stats.nCommands+1, cmd.c_str());
    498 #endif
    499 
    500     gettimeofday(&tv, NULL);
    501     start = CVT2SECS(tv);
    502 
    503     if (NanoVis::recfile != NULL) {
    504         fprintf(NanoVis::recfile, "%s", Tcl_DStringValue(dsPtr));
    505         fflush(NanoVis::recfile);
    506     }
    507     result = Tcl_Eval(interp, Tcl_DStringValue(dsPtr));
    508     Tcl_DStringSetLength(dsPtr, 0);
    509 
    510     gettimeofday(&tv, NULL);
    511     finish = CVT2SECS(tv);
    512 
    513     stats.cmdTime += finish - start;
    514     stats.nCommands++;
    515     TRACE("Leave status=%d", result);
    516     return result;
    517178}
    518179
     
    649310    planeRenderer->render();
    650311
    651     // INSOO
     312    glPixelStorei(GL_PACK_ALIGNMENT, 1);
    652313    glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, screenBuffer);
    653     //glReadPixels(0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, screenBuffer); // INSOO's
    654 
    655314    {
    656315        char prefix[200];
    657         ssize_t nWritten;
    658316
    659317        TRACE("Sending ppm legend image %s min:%g max:%g", volArg, min, max);
    660318        sprintf(prefix, "nv>legend %s %g %g", volArg, min, max);
    661         ppmWrite(prefix);
    662         nWritten = write(1, "\n", 1);
    663         assert(nWritten == 1);
     319#ifdef USE_THREADS
     320        queuePPM(nv::g_queue, prefix, screenBuffer, width, height);
     321#else
     322        writePPM(nv::g_fdOut, prefix, screenBuffer, width, height);
     323#endif
    664324    }
    665325    planeRenderer->removePlane(index);
     
    673333
    674334//initialize frame buffer objects for offscreen rendering
    675 void
     335bool
    676336NanoVis::initOffscreenBuffer()
    677337{
     
    712372    if (!CheckFBO(&status)) {
    713373        PrintFBOStatus(status, "finalFbo");
    714         exitService(3);
     374        return false;
    715375    }
    716376
    717377    TRACE("Leave");
     378    return true;
    718379}
    719380
    720381//resize the offscreen buffer
    721 void
     382bool
    722383NanoVis::resizeOffscreenBuffer(int w, int h)
    723384{
    724385    TRACE("Enter (%d, %d)", w, h);
    725386    if ((w == winWidth) && (h == winHeight)) {
    726         return;
     387        return true;
    727388    }
    728389    winWidth = w;
     
    739400    }
    740401
    741     screenBuffer = new unsigned char[4*winWidth*winHeight];
     402    screenBuffer = new unsigned char[3*winWidth*winHeight];
    742403    assert(screenBuffer != NULL);
    743    
     404
    744405    //delete the current render buffer resources
    745406    glDeleteTextures(1, &_finalColorTex);
     
    785446    if (!CheckFBO(&status)) {
    786447        PrintFBOStatus(status, "finalFbo");
    787         exitService(3);
     448        return false;
    788449    }
    789450
     
    794455
    795456    TRACE("Leave (%d, %d)", w, h);
     457    return true;
    796458}
    797459
     
    801463    if (!NvShader::printErrorInfo()) {
    802464        TRACE("Cg error, exiting...");
    803         exitService(-1);
    804     }
    805 }
    806 
    807 void NanoVis::init(const char* path)
     465        exit(1);
     466    }
     467}
     468
     469bool NanoVis::init(const char* path)
    808470{
    809471    // print OpenGL driver information
     
    816478    if (path == NULL) {
    817479        ERROR("No path defined for shaders or resources");
    818         exitService(1);
     480        return false;
    819481    }
    820482    GLenum err = glewInit();
    821483    if (GLEW_OK != err) {
    822484        ERROR("Can't init GLEW: %s", glewGetErrorString(err));
    823         exitService(1);
     485        return false;
    824486    }
    825487    TRACE("Using GLEW %s", glewGetString(GLEW_VERSION));
     
    829491    if (!GLEW_VERSION_2_1) {
    830492        ERROR("OpenGL version 2.1 or greater is required");
    831         exitService(1);
     493        return false;
    832494    }
    833495
     
    836498    if (!GLEW_ARB_pixel_buffer_object) {
    837499        ERROR("Pixel buffer objects are not supported by driver, please check that the user running nanovis has permissions to create a direct rendering context (e.g. user has read/write access to /dev/nvidia* device nodes in Linux).");
    838         exitService(1);
     500        return false;
    839501    }
    840502
     
    844506    if (!GLEW_EXT_framebuffer_object) {
    845507        ERROR("EXT_framebuffer_oject extension is required");
    846         exitService(1);
     508        return false;
    847509    }
    848510    // Rectangle textures were promoted in 3.1
     
    850512    if (!GLEW_ARB_texture_rectangle) {
    851513        ERROR("ARB_texture_rectangle extension is required");
    852         exitService(1);
     514        return false;
    853515    }
    854516#ifdef HAVE_FLOAT_TEXTURES
     
    857519        !GLEW_ARB_color_buffer_float) {
    858520        ERROR("ARB_texture_float and ARB_color_buffer_float extensions are required");
    859         exitService(1);
     521        return false;
    860522    }
    861523#endif
     
    864526        !GLEW_NV_fragment_program2) {
    865527        ERROR("NV_vertex_program3 and NV_fragment_program2 extensions are required");
    866         exitService(1);
     528        return false;
    867529    }
    868530
    869531    if (!FilePath::getInstance()->setPath(path)) {
    870532        ERROR("can't set file path to %s", path);
    871         exitService(1);
     533        return false;
    872534    }
    873535
     
    886548    grid = new Grid();
    887549    grid->setFont(fonts);
    888 
    889 #ifdef USE_POINTSET_RENDERER
    890     pointSetRenderer = new PointSetRenderer();
    891 #endif
    892 }
    893 
    894 void
     550    return true;
     551}
     552
     553bool
    895554NanoVis::initGL()
    896555{
     
    901560        screenBuffer = NULL;
    902561    }
    903     screenBuffer = new unsigned char[4*winWidth*winHeight];
     562    screenBuffer = new unsigned char[3*winWidth*winHeight];
    904563    assert(screenBuffer != NULL);
    905564
     
    927586    glLightfv(GL_LIGHT1, GL_SPECULAR, white_light);
    928587
    929     initOffscreenBuffer();    //frame buffer object for offscreen rendering
    930 
    931     //create volume renderer
     588    //frame buffer object for offscreen rendering
     589    if (!initOffscreenBuffer()) {
     590        return false;
     591    }
     592
    932593    volRenderer = new VolumeRenderer();
    933594
    934     // create
    935595    renderContext = new RenderContext();
    936596
    937     //create a 2D plane renderer
    938597    planeRenderer = new PlaneRenderer(winWidth, winHeight);
    939598
     599    orientationIndicator = new OrientationIndicator();
     600
    940601    //assert(glGetError()==0);
    941602
    942603    TRACE("leaving initGL");
    943 }
    944 
    945 // used internally to build up the BMP file header
    946 // Writes an integer value into the header data structure at pos
    947 static inline void
    948 bmpHeaderAddInt(unsigned char* header, int& pos, int data)
    949 {
    950 #ifdef WORDS_BIGENDIAN
    951     header[pos++] = (data >> 24) & 0xFF;
    952     header[pos++] = (data >> 16) & 0xFF;
    953     header[pos++] = (data >> 8)  & 0xFF;
    954     header[pos++] = (data)       & 0xFF;
    955 #else
    956     header[pos++] = data & 0xff;
    957     header[pos++] = (data >> 8) & 0xff;
    958     header[pos++] = (data >> 16) & 0xff;
    959     header[pos++] = (data >> 24) & 0xff;
    960 #endif
    961 }
    962 
    963 // INSOO
    964 // FOR DEBUGGING
    965 void
    966 NanoVis::bmpWriteToFile(int frame_number, const char *directory_name)
    967 {
    968     unsigned char header[SIZEOF_BMP_HEADER];
    969     int pos = 0;
    970     header[pos++] = 'B';
    971     header[pos++] = 'M';
    972 
    973     // BE CAREFUL:  BMP files must have an even multiple of 4 bytes
    974     // on each scan line.  If need be, we add padding to each line.
    975     int pad = 0;
    976     if ((3*winWidth) % 4 > 0) {
    977         pad = 4 - ((3*winWidth) % 4);
    978     }
    979 
    980     // file size in bytes
    981     int fsize = (3*winWidth+pad)*winHeight + SIZEOF_BMP_HEADER;
    982     bmpHeaderAddInt(header, pos, fsize);
    983 
    984     // reserved value (must be 0)
    985     bmpHeaderAddInt(header, pos, 0);
    986 
    987     // offset in bytes to start of bitmap data
    988     bmpHeaderAddInt(header, pos, SIZEOF_BMP_HEADER);
    989 
    990     // size of the BITMAPINFOHEADER
    991     bmpHeaderAddInt(header, pos, 40);
    992 
    993     // width of the image in pixels
    994     bmpHeaderAddInt(header, pos, winWidth);
    995 
    996     // height of the image in pixels
    997     bmpHeaderAddInt(header, pos, winHeight);
    998 
    999     // 1 plane + (24 bits/pixel << 16)
    1000     bmpHeaderAddInt(header, pos, 1572865);
    1001 
    1002     // no compression
    1003     // size of image for compression
    1004     bmpHeaderAddInt(header, pos, 0);
    1005     bmpHeaderAddInt(header, pos, 0);
    1006 
    1007     // x pixels per meter
    1008     // y pixels per meter
    1009     bmpHeaderAddInt(header, pos, 0);
    1010     bmpHeaderAddInt(header, pos, 0);
    1011 
    1012     // number of colors used (0 = compute from bits/pixel)
    1013     // number of important colors (0 = all colors important)
    1014     bmpHeaderAddInt(header, pos, 0);
    1015     bmpHeaderAddInt(header, pos, 0);
    1016 
    1017     // BE CAREFUL: BMP format wants BGR ordering for screen data
    1018     unsigned char* scr = screenBuffer;
    1019     for (int row=0; row < winHeight; row++) {
    1020         for (int col=0; col < winWidth; col++) {
    1021             unsigned char tmp = scr[2];
    1022             scr[2] = scr[0];  // B
    1023             scr[0] = tmp;     // R
    1024             scr += 3;
    1025         }
    1026         scr += pad;  // skip over padding already in screen data
    1027     }
    1028 
    1029     FILE* f;
    1030     char filename[100];
    1031     if (frame_number >= 0) {
    1032         if (directory_name)
    1033             sprintf(filename, "%s/image%03d.bmp", directory_name, frame_number);
    1034         else
    1035             sprintf(filename, "/tmp/flow_animation/image%03d.bmp", frame_number);
    1036 
    1037         TRACE("Writing %s", filename);
    1038         f = fopen(filename, "wb");
    1039         if (f == 0) {
    1040             ERROR("cannot create file");
    1041         }
    1042     } else {
    1043         f = fopen("/tmp/image.bmp", "wb");
    1044         if (f == 0) {
    1045             ERROR("cannot create file");
    1046         }
    1047     }
    1048     if (fwrite(header, SIZEOF_BMP_HEADER, 1, f) != 1) {
    1049         ERROR("can't write header: short write");
    1050     }
    1051     if (fwrite(screenBuffer, (3*winWidth+pad)*winHeight, 1, f) != 1) {
    1052         ERROR("can't write data: short write");
    1053     }
    1054     fclose(f);
    1055 }
    1056 
    1057 void
    1058 NanoVis::bmpWrite(const char *prefix)
    1059 {
    1060     unsigned char header[SIZEOF_BMP_HEADER];
    1061     ssize_t nWritten;
    1062     int pos = 0;
    1063 
    1064     // BE CAREFUL:  BMP files must have an even multiple of 4 bytes
    1065     // on each scan line.  If need be, we add padding to each line.
    1066     int pad = 0;
    1067     if ((3*winWidth) % 4 > 0) {
    1068         pad = 4 - ((3*winWidth) % 4);
    1069     }
    1070     pad = 0;
    1071     int fsize = (3*winWidth+pad)*winHeight + sizeof(header);
    1072 
    1073     char string[200];
    1074     sprintf(string, "%s %d\n", prefix, fsize);
    1075     nWritten = write(1, string, strlen(string));
    1076     assert(nWritten == (ssize_t)strlen(string));
    1077     header[pos++] = 'B';
    1078     header[pos++] = 'M';
    1079 
    1080     // file size in bytes
    1081     bmpHeaderAddInt(header, pos, fsize);
    1082 
    1083     // reserved value (must be 0)
    1084     bmpHeaderAddInt(header, pos, 0);
    1085 
    1086     // offset in bytes to start of bitmap data
    1087     bmpHeaderAddInt(header, pos, SIZEOF_BMP_HEADER);
    1088 
    1089     // size of the BITMAPINFOHEADER
    1090     bmpHeaderAddInt(header, pos, 40);
    1091 
    1092     // width of the image in pixels
    1093     bmpHeaderAddInt(header, pos, winWidth);
    1094 
    1095     // height of the image in pixels
    1096     bmpHeaderAddInt(header, pos, winHeight);
    1097 
    1098     // 1 plane + (24 bits/pixel << 16)
    1099     bmpHeaderAddInt(header, pos, 1572865);
    1100 
    1101     // no compression
    1102     // size of image for compression
    1103     bmpHeaderAddInt(header, pos, 0);
    1104     bmpHeaderAddInt(header, pos, 0);
    1105 
    1106     // x pixels per meter
    1107     // y pixels per meter
    1108     bmpHeaderAddInt(header, pos, 0);
    1109     bmpHeaderAddInt(header, pos, 0);
    1110 
    1111     // number of colors used (0 = compute from bits/pixel)
    1112     // number of important colors (0 = all colors important)
    1113     bmpHeaderAddInt(header, pos, 0);
    1114     bmpHeaderAddInt(header, pos, 0);
    1115 
    1116     // BE CAREFUL: BMP format wants BGR ordering for screen data
    1117     unsigned char* scr = screenBuffer;
    1118     for (int row=0; row < winHeight; row++) {
    1119         for (int col=0; col < winWidth; col++) {
    1120             unsigned char tmp = scr[2];
    1121             scr[2] = scr[0];  // B
    1122             scr[0] = tmp;     // R
    1123             scr += 3;
    1124         }
    1125         scr += pad;  // skip over padding already in screen data
    1126     }
    1127 
    1128     nWritten = write(1, header, SIZEOF_BMP_HEADER);
    1129     assert(nWritten == SIZEOF_BMP_HEADER);
    1130     nWritten = write(1, screenBuffer, (3*winWidth+pad)*winHeight);
    1131     assert(nWritten == (3*winWidth+pad)*winHeight);
    1132     stats.nFrames++;
    1133     stats.nBytes += (3*winWidth+pad)*winHeight;
    1134 }
    1135 
    1136 /*
    1137  * ppmWrite --
    1138  *
    1139  *  Writes the screen image as PPM binary data to the nanovisviewer
    1140  *  client.  The PPM binary format is very simple.
    1141  *
    1142  *      P6 w h 255\n
    1143  *      3-byte RGB pixel data.
    1144  *
    1145  *  The nanovisviewer client (using the TkImg library) will do less work
    1146  *  to unpack this format, as opposed to BMP or PNG.  (This doesn't
    1147  *  eliminate the need to look into DXT compression performed on the GPU).
    1148  *
    1149  *      Note that currently the image data from the screen is both row-padded
    1150  *      and the scan lines are reversed.  This routine could be made even
    1151  *      simpler (faster) if the screen buffer is an array of packed 3-bytes
    1152  *      per pixels (no padding) and where the origin is the top-left corner.
    1153  */
    1154 void
    1155 NanoVis::ppmWrite(const char *prefix)
    1156 {
    1157 #define PPM_MAXVAL 255
    1158     char header[200];
    1159 
    1160     TRACE("Enter (%dx%d)", winWidth, winHeight);
    1161     // Generate the PPM binary file header
    1162     sprintf(header, "P6 %d %d %d\n", winWidth, winHeight, PPM_MAXVAL);
    1163 
    1164     size_t header_length = strlen(header);
    1165     size_t data_length = winWidth * winHeight * 3;
    1166 
    1167     char command[200];
    1168     sprintf(command, "%s %lu\n", prefix,
    1169             (unsigned long)header_length + data_length);
    1170 
    1171     size_t wordsPerRow = (winWidth * 24 + 31) / 32;
    1172     size_t bytesPerRow = wordsPerRow * 4;
    1173     size_t rowLength = winWidth * 3;
    1174     size_t nRecs = winHeight + 2;
    1175 
    1176     struct iovec *iov;
    1177     iov = (struct iovec *)malloc(sizeof(struct iovec) * nRecs);
    1178 
    1179     // Write the nanovisviewer command, then the image header and data.
    1180     // Command
    1181     iov[0].iov_base = command;
    1182     iov[0].iov_len = strlen(command);
    1183     // Header of image data
    1184     iov[1].iov_base = header;
    1185     iov[1].iov_len = header_length;
    1186     // Image data.
    1187     int y;
    1188     unsigned char *srcRowPtr = screenBuffer;
    1189     for (y = winHeight + 1; y >= 2; y--) {
    1190         iov[y].iov_base = srcRowPtr;
    1191         iov[y].iov_len = rowLength;
    1192         srcRowPtr += bytesPerRow;
    1193     }
    1194     if (writev(1, iov, nRecs) < 0) {
    1195         ERROR("write failed: %s", strerror(errno));
    1196     }
    1197     free(iov);
    1198     stats.nFrames++;
    1199     stats.nBytes += (bytesPerRow * winHeight);
    1200     TRACE("Leave (%dx%d)", winWidth, winHeight);
    1201 }
    1202 
    1203 void
    1204 NanoVis::sendDataToClient(const char *command, const char *data, size_t dlen)
    1205 {
    1206     size_t numRecords = 2;
    1207 
    1208     struct iovec *iov = new iovec[numRecords];
    1209 
    1210     // Write the nanovisviewer command, then the image header and data.
    1211     // Command
    1212     // FIXME: shouldn't have to cast this
    1213     iov[0].iov_base = (char *)command;
    1214     iov[0].iov_len = strlen(command);
    1215     // Data
    1216     // FIXME: shouldn't have to cast this
    1217     iov[1].iov_base = (char *)data;
    1218     iov[1].iov_len = dlen;
    1219     if (writev(1, iov, numRecords) < 0) {
    1220         ERROR("write failed: %s", strerror(errno));
    1221     }
    1222     delete [] iov;
    1223 }
    1224 
    1225 void
    1226 NanoVis::idle()
    1227 {
    1228     TRACE("Enter");
    1229 
    1230     glutSetWindow(renderWindow);
    1231 
    1232     processCommands();
    1233 
    1234     TRACE("Leave");
    1235 }
    1236 
    1237 void
    1238 NanoVis::draw3dAxis()
    1239 {
    1240     glPushAttrib(GL_ENABLE_BIT);
    1241 
    1242     glDisable(GL_TEXTURE_2D);
    1243     glEnable(GL_DEPTH_TEST);
    1244     glEnable(GL_COLOR_MATERIAL);
    1245     glDisable(GL_BLEND);
    1246 
    1247     //draw axes
    1248     GLUquadric *obj;
    1249 
    1250     obj = gluNewQuadric();
    1251 
    1252     int segments = 50;
    1253 
    1254     glColor3f(0.8, 0.8, 0.8);
    1255     glPushMatrix();
    1256     glTranslatef(0.4, 0., 0.);
    1257     glRotatef(90, 1, 0, 0);
    1258     glRotatef(180, 0, 1, 0);
    1259     glScalef(0.0005, 0.0005, 0.0005);
    1260     glutStrokeCharacter(GLUT_STROKE_ROMAN, 'x');
    1261     glPopMatrix();
    1262 
    1263     glPushMatrix();
    1264     glTranslatef(0., 0.4, 0.);
    1265     glRotatef(90, 1, 0, 0);
    1266     glRotatef(180, 0, 1, 0);
    1267     glScalef(0.0005, 0.0005, 0.0005);
    1268     glutStrokeCharacter(GLUT_STROKE_ROMAN, 'y');
    1269     glPopMatrix();
    1270 
    1271     glPushMatrix();
    1272     glTranslatef(0., 0., 0.4);
    1273     glRotatef(90, 1, 0, 0);
    1274     glRotatef(180, 0, 1, 0);
    1275     glScalef(0.0005, 0.0005, 0.0005);
    1276     glutStrokeCharacter(GLUT_STROKE_ROMAN, 'z');
    1277     glPopMatrix();
    1278 
    1279     glEnable(GL_LIGHTING);
    1280     glEnable(GL_LIGHT0);
    1281 
    1282     //glColor3f(0.2, 0.2, 0.8);
    1283     glPushMatrix();
    1284     glutSolidSphere(0.02, segments, segments );
    1285     glPopMatrix();
    1286 
    1287     glPushMatrix();
    1288     glRotatef(-90, 1, 0, 0);
    1289     gluCylinder(obj, 0.01, 0.01, 0.3, segments, segments);
    1290     glPopMatrix();
    1291 
    1292     glPushMatrix();
    1293     glTranslatef(0., 0.3, 0.);
    1294     glRotatef(-90, 1, 0, 0);
    1295     gluCylinder(obj, 0.02, 0.0, 0.06, segments, segments);
    1296     glPopMatrix();
    1297 
    1298     glPushMatrix();
    1299     glRotatef(90, 0, 1, 0);
    1300     gluCylinder(obj, 0.01, 0.01, 0.3, segments, segments);
    1301     glPopMatrix();
    1302 
    1303     glPushMatrix();
    1304     glTranslatef(0.3, 0., 0.);
    1305     glRotatef(90, 0, 1, 0);
    1306     gluCylinder(obj, 0.02, 0.0, 0.06, segments, segments);
    1307     glPopMatrix();
    1308 
    1309     glPushMatrix();
    1310     gluCylinder(obj, 0.01, 0.01, 0.3, segments, segments);
    1311     glPopMatrix();
    1312 
    1313     glPushMatrix();
    1314     glTranslatef(0., 0., 0.3);
    1315     gluCylinder(obj, 0.02, 0.0, 0.06, segments, segments);
    1316     glPopMatrix();
    1317 
    1318     gluDeleteQuadric(obj);
    1319 
    1320     glPopAttrib();
     604    return true;
    1321605}
    1322606
     
    1577861    TRACE("Setting bgcolor to %g %g %g", color[0], color[1], color[2]);
    1578862    glClearColor(color[0], color[1], color[2], 1);
     863}
     864
     865void
     866NanoVis::removeVolume(Volume *volume)
     867{
     868    VolumeHashmap::iterator itr = volumeTable.find(volume->name());
     869    if (itr != volumeTable.end()) {
     870        volumeTable.erase(itr);
     871    }
     872    delete volume;
    1579873}
    1580874
     
    18291123
    18301124    //now render things in the scene
    1831     if (axisOn) {
    1832         draw3dAxis();
    1833     }
    1834     if (grid->isVisible()) {
    1835         grid->render();
    1836     }
     1125
     1126    orientationIndicator->render();
     1127    grid->render();
    18371128    if ((licRenderer != NULL) && (licRenderer->active())) {
    18381129        licRenderer->render();
     
    18411132        velocityArrowsSlice->render();
    18421133    }
    1843     if (!flowTable.empty()) {
    1844         renderFlows();
    1845     }
    1846 
     1134    renderFlows();
    18471135    volRenderer->renderAll();
    18481136
    1849     TRACE("Render heightmaps");
    18501137    HeightMapHashmap::iterator itr;
    18511138    for (itr = heightMapTable.begin();
     
    18611148    TRACE("Leave");
    18621149}
    1863 
    1864 void
    1865 NanoVis::processCommands()
    1866 {
    1867     flags &= ~REDRAW_PENDING;
    1868 
    1869     TRACE("Enter");
    1870 
    1871     int flags = fcntl(0, F_GETFL, 0);
    1872     fcntl(0, F_SETFL, flags & ~O_NONBLOCK);
    1873 
    1874     int status = TCL_OK;
    1875 
    1876     //  Read and execute as many commands as we can from stdin...
    1877     Tcl_DString cmdbuffer;
    1878     Tcl_DStringInit(&cmdbuffer);
    1879     int nCommands = 0;
    1880     bool isComplete = false;
    1881     while ((!feof(NanoVis::stdin)) && (status == TCL_OK)) {
    1882         //
    1883         //  Read the next command from the buffer.  First time through we
    1884         //  block here and wait if necessary until a command comes in.
    1885         //
    1886         //  BE CAREFUL: Read only one command, up to a newline.  The "volume
    1887         //  data follows" command needs to be able to read the data
    1888         //  immediately following the command, and we shouldn't consume it
    1889         //  here.
    1890         //
    1891         while (!feof(NanoVis::stdin)) {
    1892             int c = fgetc(NanoVis::stdin);
    1893             char ch;
    1894             if (c <= 0) {
    1895                 if (errno == EWOULDBLOCK) {
    1896                     break;
    1897                 }
    1898                 exitService(100);
    1899             }
    1900             ch = (char)c;
    1901             Tcl_DStringAppend(&cmdbuffer, &ch, 1);
    1902             if (ch == '\n') {
    1903                 isComplete = Tcl_CommandComplete(Tcl_DStringValue(&cmdbuffer));
    1904                 if (isComplete) {
    1905                     break;
    1906                 }
    1907             }
    1908         }
    1909         // no command? then we're done for now
    1910         if (Tcl_DStringLength(&cmdbuffer) == 0) {
    1911             break;
    1912         }
    1913         if (isComplete) {
    1914             // back to original flags during command evaluation...
    1915             fcntl(0, F_SETFL, flags & ~O_NONBLOCK);
    1916             status = executeCommand(interp, &cmdbuffer);
    1917             // non-blocking for next read -- we might not get anything
    1918             fcntl(0, F_SETFL, flags | O_NONBLOCK);
    1919             isComplete = false;
    1920             nCommands++;
    1921             CHECK_FRAMEBUFFER_STATUS();
    1922         }
    1923     }
    1924     fcntl(0, F_SETFL, flags);
    1925 
    1926     if (status != TCL_OK) {
    1927         char *msg;
    1928         char hdr[200];
    1929         int msgSize, hdrSize;
    1930         Tcl_Obj *objPtr;
    1931 
    1932         objPtr = Tcl_GetObjResult(interp);
    1933         msg = Tcl_GetStringFromObj(objPtr, &msgSize);
    1934         hdrSize = sprintf(hdr, "nv>viserror -type internal_error -bytes %d\n", msgSize);
    1935         {
    1936             struct iovec iov[2];
    1937 
    1938             iov[0].iov_base = hdr;
    1939             iov[0].iov_len = hdrSize;
    1940             iov[1].iov_base = msg;
    1941             iov[1].iov_len = msgSize;
    1942             if (writev(1, iov, 2) < 0) {
    1943                 ERROR("write failed: %s", strerror(errno));
    1944             }
    1945         }
    1946         TRACE("Leaving on ERROR");
    1947         return;
    1948     }
    1949     if (feof(NanoVis::stdin)) {
    1950         TRACE("Exiting server on EOF from client");
    1951         exitService(90);
    1952     }
    1953 
    1954     update();
    1955 
    1956     bindOffscreenBuffer();  //enable offscreen render
    1957     render();
    1958     readScreen();
    1959 
    1960     if (feof(NanoVis::stdin)) {
    1961         exitService(90);
    1962     }
    1963 
    1964     ppmWrite("nv>image -type image -bytes");
    1965 
    1966     TRACE("Leave");
    1967 }
    1968 
    1969 int
    1970 main(int argc, char **argv)
    1971 {
    1972     const char *path;
    1973     char *newPath;
    1974 
    1975     newPath = NULL;
    1976     path = NULL;
    1977     NanoVis::stdin = stdin;
    1978 
    1979     fprintf(stdout, "NanoVis %s (build %s)\n", NANOVIS_VERSION, SVN_VERSION);
    1980     fflush(stdout);
    1981 
    1982     openlog("nanovis", LOG_CONS | LOG_PERROR | LOG_PID, LOG_USER);
    1983     gettimeofday(&NanoVis::startTime, NULL);
    1984     stats.start = NanoVis::startTime;
    1985 
    1986     /* Initialize GLUT here so it can parse and remove GLUT-specific
    1987      * command-line options before we parse the command-line below. */
    1988     glutInit(&argc, argv);
    1989     glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
    1990     glutInitWindowSize(NanoVis::winWidth, NanoVis::winHeight);
    1991     glutInitWindowPosition(10, 10);
    1992     NanoVis::renderWindow = glutCreateWindow("nanovis");
    1993     glutIdleFunc(NanoVis::idle);
    1994 
    1995     glutDisplayFunc(NanoVis::render);
    1996     glutReshapeFunc(NanoVis::resizeOffscreenBuffer);
    1997 
    1998     while (1) {
    1999         static struct option long_options[] = {
    2000             {"infile",  required_argument, NULL, 0},
    2001             {"path",    required_argument, NULL, 2},
    2002             {"debug",   no_argument,       NULL, 3},
    2003             {"record",  required_argument, NULL, 4},
    2004             {0, 0, 0, 0}
    2005         };
    2006         int option_index = 0;
    2007         int c;
    2008 
    2009         c = getopt_long(argc, argv, ":dp:i:l:r:", long_options, &option_index);
    2010         if (c == -1) {
    2011             break;
    2012         }
    2013         switch (c) {
    2014         case '?':
    2015             fprintf(stderr, "unknown option -%c\n", optopt);
    2016             return 1;
    2017         case ':':
    2018             if (optopt < 4) {
    2019                 fprintf(stderr, "argument missing for --%s option\n",
    2020                         long_options[optopt].name);
    2021             } else {
    2022                 fprintf(stderr, "argument missing for -%c option\n", optopt);
    2023             }
    2024             return 1;
    2025         case 2:
    2026         case 'p':
    2027             path = optarg;
    2028             break;
    2029         case 3:
    2030         case 'd':
    2031             NanoVis::debugFlag = true;
    2032             break;
    2033         case 0:
    2034         case 'i':
    2035             NanoVis::stdin = fopen(optarg, "r");
    2036             if (NanoVis::stdin == NULL) {
    2037                 perror(optarg);
    2038                 return 2;
    2039             }
    2040             break;
    2041         case 4:
    2042         case 'r':
    2043             Tcl_DString ds;
    2044             char buf[200];
    2045 
    2046             Tcl_DStringInit(&ds);
    2047             Tcl_DStringAppend(&ds, optarg, -1);
    2048             sprintf(buf, ".%d", getpid());
    2049             Tcl_DStringAppend(&ds, buf, -1);
    2050             NanoVis::recfile = fopen(Tcl_DStringValue(&ds), "w");
    2051             if (NanoVis::recfile == NULL) {
    2052                 perror(optarg);
    2053                 return 2;
    2054             }
    2055             break;
    2056         default:
    2057             fprintf(stderr,"unknown option '%c'.\n", c);
    2058             return 1;
    2059         }
    2060     }     
    2061     if (path == NULL) {
    2062         char *p;
    2063 
    2064         // See if we can derive the path from the location of the program.
    2065         // Assume program is in the form <path>/bin/nanovis.
    2066         path = argv[0];
    2067         p = strrchr((char *)path, '/');
    2068         if (p != NULL) {
    2069             *p = '\0';
    2070             p = strrchr((char *)path, '/');
    2071         }
    2072         if (p == NULL) {
    2073             TRACE("path not specified");
    2074             return 1;
    2075         }
    2076         *p = '\0';
    2077         newPath = new char[(strlen(path) + 15) * 2 + 1];
    2078         sprintf(newPath, "%s/lib/shaders:%s/lib/resources", path, path);
    2079         path = newPath;
    2080     }
    2081 
    2082     FilePath::getInstance()->setWorkingDirectory(argc, (const char**) argv);
    2083 
    2084 #ifdef notdef
    2085     signal(SIGPIPE, SIG_IGN);
    2086 #endif
    2087     initService();
    2088 
    2089     NanoVis::init(path);
    2090     if (newPath != NULL) {
    2091         delete [] newPath;
    2092     }
    2093     NanoVis::initGL();
    2094 
    2095     NanoVis::interp = initTcl();
    2096 
    2097     NanoVis::resizeOffscreenBuffer(NanoVis::winWidth, NanoVis::winHeight);
    2098 
    2099     glutMainLoop();
    2100 
    2101     exitService(80);
    2102 }
    2103 
    2104 void
    2105 NanoVis::removeVolume(Volume *volume)
    2106 {
    2107     VolumeHashmap::iterator itr = volumeTable.find(volume->name());
    2108     if (itr != volumeTable.end()) {
    2109         volumeTable.erase(itr);
    2110     }
    2111     delete volume;
    2112 }
  • trunk/packages/vizservers/nanovis/nanovis.h

    r3597 r3605  
    1717#define NANOVIS_H
    1818
    19 #include <tcl.h>
    20 #include <md5.h>
    21 #include <GL/glew.h>
    22 
    2319#include <math.h>
    2420#include <stddef.h> // For size_t
    2521#include <stdio.h>
     22#include <sys/time.h>
     23#include <sys/types.h> // For pid_t
     24
     25#include <tcl.h>
     26
     27#include <GL/glew.h>
    2628
    2729#include <vector>
     
    3234
    3335#include "config.h"
     36#include "md5.h"
    3437
    35 #define NANOVIS_VERSION         "1.1"
     38#define NANOVIS_VERSION         "1.2"
    3639
    3740//defines for the image based flow visualization
     
    4649    class Fonts;
    4750}
     51class OrientationIndicator;
    4852}
    4953
    5054class VolumeRenderer;
    51 class PointSetRenderer;
    5255class NvParticleRenderer;
    53 class PlaneRenderer;
    5456class VelocityArrowsSlice;
    5557class NvLIC;
    56 class PointSet;
     58class PlaneRenderer;
    5759class Texture2D;
    5860class HeightMap;
     
    8991    typedef std::tr1::unordered_map<HeightMapId, HeightMap *> HeightMapHashmap;
    9092
    91     static void processCommands();
    92     static void init(const char *path);
    93     static void initGL();
    94     static void initOffscreenBuffer();
    95     static void resizeOffscreenBuffer(int w, int h);
     93    static bool init(const char *path);
     94    static bool initGL();
     95    static bool initOffscreenBuffer();
     96    static bool resizeOffscreenBuffer(int w, int h);
    9697    static void setBgColor(float color[3]);
    9798    static void render();
    9899    static void draw3dAxis();
    99     static void idle();
    100100    static void update();
    101101    static void removeAllData();
     
    113113    static void setVolumeRanges();
    114114    static void setHeightmapRanges();
    115 
    116 #ifdef KEEPSTATS
    117     static int getStatsFile(Tcl_Obj *objPtr);
    118     static int writeToStatsFile(int f, const char *s, size_t length);
    119 #endif
    120     static void ppmWrite(const char *prefix);
    121     static void sendDataToClient(const char *command, const char *data,
    122                                  size_t dlen);
    123     static void bmpWrite(const char *prefix);
    124     static void bmpWriteToFile(int frame_number, const char* directory_name);
    125115 
    126116    static TransferFunction *getTransferFunction(const TransferFunctionId& id);
     
    139129    static void readScreen()
    140130    {
     131        glPixelStorei(GL_PACK_ALIGNMENT, 1);
    141132        glReadPixels(0, 0, winWidth, winHeight, GL_RGB, GL_UNSIGNED_BYTE,
    142133                     screenBuffer);
     
    149140    static Flow *getFlow(const char *name);
    150141    static Flow *createFlow(Tcl_Interp *interp, const char *name);
     142    static void deleteFlows(Tcl_Interp *interp);
    151143    static void deleteFlow(const char *name);
    152     static void deleteFlows(Tcl_Interp *interp);
    153144    static bool mapFlows();
    154145    static void getFlowBounds(vrmath::Vector3f& min,
     
    160151    static void advectFlows();
    161152
    162     static FILE *stdin, *logfile, *recfile;
    163     static int statsFile;
     153    static Tcl_Interp *interp;
     154
    164155    static unsigned int flags;
    165156    static bool debugFlag;
    166     static bool axisOn;
    167     static struct timeval startTime;       ///< Start of elapsed time.
    168157
    169158    static int winWidth;        ///< Width of the render window
     
    172161    static unsigned char *screenBuffer;
    173162    static Texture2D *legendTexture;
    174     static Grid *grid;
    175163    static nv::util::Fonts *fonts;
    176164    static int updir;
     
    191179    static NvLIC *licRenderer;
    192180    static PlaneRenderer *planeRenderer;
    193 
    194 #ifdef USE_POINTSET_RENDERER
    195     static PointSetRenderer *pointSetRenderer;
    196     static std::vector<PointSet *> pointSet;
    197 #endif
    198 
    199     static Tcl_Interp *interp;
     181    static nv::OrientationIndicator *orientationIndicator;
     182    static Grid *grid;
    200183
    201184private:
  • trunk/packages/vizservers/nanovis/protocol-nanovis.txt

    r3568 r3605  
    3838Requests:
    3939================================================================================
    40 axis visible <false|true>
    41 
    42 grid axiscolor <red> <green> <blue> <?alpha?>
    43 grid axisname <x|y|z> <name>
    44 grid linecolor <red> <green> <blue> <?alpha?>
    45 grid visible <false|true>
     40axis visible <bool>
    4641
    4742camera angle <xAngle> <yAngle> <zAngle>
     
    5348camera zoom <factor>
    5449
    55 screen bgcolor <r> <g> <b>
    56        Set screen background color
    57 screen size <width> <height>
    58        Set size of rendered images
    59 
    60 snapshot
    61          Render a 2k x 2k image (offscreen buffer)
    62 
    63 transfunc define <name> {colors} {alpha}
    64           colors => 1 line each of "value r g b"
    65           alpha => 1 line each of "value alpha"
    66           value => [0,1]
    67 
    68 legend <transferfunc name> <width> <height>
    69        Request render of transfer function
    70 
    71 heightmap data visible <true|false> <volume IDs>
    72 heightmap data follows <nbytes> <data>
    73 heightmap linecontour visible <true|false> <volume IDs>
    74 heightmap linecontour color <red> <green> <blue> <volume IDs>
    75 heightmap tranfunc <transfer function name> <volume IDs>
    76 heightmap cull <no/back/front>
    77 heightmap polygon <wireframe/fill>
     50clientinfo <list>
     51
     52cutplane position <relval> <x|y|z> <?names?>
     53         Set the position of a volume cutplane.  Names is
     54         an optional list of volume names.
     55         relval = [0,1]
     56cutplane state <bool> <x|y|z> <?names?>
     57         Set the axis (normal) of a volume cutplane.  Names is
     58         an optional list of volume names.
    7859
    7960flow add <name> <?option value...?>
     
    8465flow delete <names>
    8566flow exists <name>
     67     This doesn't currently produce a response, it only returns a boolean
     68     within the server's interpreter
    8669flow goto <nSteps>
    8770flow names
     71     This doesn't currently produce a response, it only returns a Tcl list
     72     within the server's interpreter
    8873flow next
    8974flow reset
     
    10691<flowObj> box delete <names>
    10792<flowObj> box names
     93          This doesn't currently produce a response, it only returns a Tcl list
     94          within the server's interpreter
    10895
    10996<flowObj> configure <?option value...?>
     
    113100          -diffuse <val>
    114101          -hide <bool>
     102          -light2side <bool>
    115103          -opacity <val>
    116104          -outline <bool>
     
    139127<flowObj> particles delete <names>
    140128<flowObj> particles names
    141 
    142 volume data state <on|off> <?names?>
    143 volume data follows <size> <tag>
    144 volume delete <?names?>
     129          This doesn't currently produce a response, it only returns a Tcl list
     130          within the server's interpreter
     131
     132grid axiscolor <red> <green> <blue> <?alpha?>
     133grid axisname <x|y|z> <name> <units>
     134grid linecolor <red> <green> <blue> <?alpha?>
     135grid visible <bool>
     136
     137heightmap create <heightmapName> <xMin> <yMin> <xMax> <yMax> <xNum> <yNum> <valueList>
     138heightmap cull <none|back|front>
     139heightmap data follows <nBytes> <heightmapName>
     140          After newline following command, nBytes of data are sent
     141heightmap data visible <bool> <?heightmapNames?>
     142heightmap legend <heightmapName> <width> <height>
     143heightmap linecontour color <red> <green> <blue> <?heightmapNames?>
     144heightmap linecontour visible <bool> <?heightmapNames?>
     145heightmap opacity <value> <?heightmapNames?>
     146heightmap polygon <wireframe|fill>
     147          **Warning: This is a global setting**
     148heightmap shading <flat|smooth>
     149          **Warning: This is a global setting**
     150heightmap transfunc <transferFunctionName> <?heightmapNames?>
     151
     152legend <transferfunc name> <width> <height>
     153       Request render of transfer function
     154
     155screen bgcolor <r> <g> <b>
     156       Set screen background color
     157screen size <width> <height>
     158       Set size of rendered images
     159
     160snapshot
     161         Render a 2k x 2k image (offscreen buffer). Response image data is tagged
     162         as '-type print'
     163
     164transfunc define <name> {colors} {alpha}
     165          colors => 1 line each of "value r g b"
     166          alpha => 1 line each of "value alpha"
     167          value => [0,1]
     168
     169up <x|y|z|-x|-y|-z>
     170   Set orientation of volumes
     171
     172volume animation capture <numframes> <?filename?>
     173       This is not fully implemented.  Rendered frames are not returned
     174       to the client.
     175volume animation clear
     176volume animation start
     177volume animation stop
     178volume animation volumes <?names?>
     179
     180volume data follows <nbytes> <name>
     181volume data state <bool> <?names?>
     182volume delete <names>
    145183volume exists <name>
    146 volume names <?pattern?>
     184       This doesn't currently produce a response, it only returns a boolean
     185       within the server's interpreter
     186volume names
     187       This doesn't currently produce a response, it only returns a Tcl list
     188       within the server's interpreter
    147189volume outline color <r> <g> <b> <?names?>
    148 volume outline state|visible <bool> <?names?>
     190volume outline state <bool> <?names?>
     191volume outline visible <bool> <?names?>
    149192volume shading ambient <value> <?names?>
    150193volume shading diffuse <value> <?names?>
    151194volume shading isosurface <bool> <?names?>
     195volume shading light2side <bool> <?names?>
    152196volume shading opacity <value> <?names?>
    153197volume shading specularExp <value> <?names?>
     
    156200volume state <bool> <?names?>
    157201
    158 volume animation volumes <volume IDs>
    159 volume animation start
    160 volume animation stop
    161 volume animation clear
    162 volume animation capture numframes <filename>
    163 
    164 cutplane position <relval> <x|y|z> <?names?>
    165          Set the position of a volume cutplane.  Names is
    166          an optional list of volume names.
    167          relval = [0,1]
    168 cutplane state <bool> <x|y|z> <?names?>
    169          Set the axis (normal) of a volume cutplane.  Names is
    170          an optional list of volume names.
    171 
    172 up <x|y|z|-x|-y|-z>
    173    Set orientation of volumes
    174 
    175202================================================================================
    176203Replies:
    177204================================================================================
    178205nv>legend <volume> <min> <max> <nbytes>
    179   (followed by bytes and newline)
     206  (followed by bytes)
    180207
    181208nv>image -type image -bytes <nbytes>
    182   (followed by bytes -- command _preceded_ by newline)
     209  (followed by bytes)
    183210
    184211nv>image -type print -bytes <nbytes>
    185   (followed by bytes -- command _preceded_ by newline)
     212  (followed by bytes)
    186213
    187214nv>image -type movie -token <token> -bytes <nbytes>
     
    192219   min,max over all volumes
    193220
     221nv>data tag <flow-tag> min <val> max <val>
     222   Sent after a "<flowObj> data follows...".  Min,max values are for the
     223   magnitude of the vector field.
     224
    194225================================================================================
    195226Error Replies:
Note: See TracChangeset for help on using the changeset viewer.