Changeset 4874 for nanovis/branches


Ignore:
Timestamp:
Dec 18, 2014, 8:45:38 PM (5 years ago)
Author:
ldelgass
Message:

Add command line options to set I/O file descriptors, merge some refactoring to
prep for merging threading support.

Location:
nanovis/branches/1.1
Files:
4 added
16 edited

Legend:

Unmodified
Added
Removed
  • nanovis/branches/1.1

  • nanovis/branches/1.1/Command.cpp

    r4830 r4874  
    3333
    3434#include <assert.h>
     35#include <errno.h>
    3536#include <stdlib.h>
    3637#include <unistd.h>                     /* Needed for getpid, gethostname,
     
    4445#include <vrmath/Vector3f.h>
    4546
     47#include "nanovisServer.h"
    4648#include "nanovis.h"
     49#include "ReadBuffer.h"
     50#include "Command.h"
    4751#include "CmdProc.h"
    4852#include "FlowCmd.h"
     
    5862#include "Trace.h"
    5963
     64using namespace nv;
    6065using namespace nv::graphics;
    6166using namespace vrmath;
     
    100105static int lastCmdStatus;
    101106
     107ssize_t
     108nv::SocketWrite(const void *bytes, size_t len)
     109{
     110    size_t ofs = 0;
     111    ssize_t bytesWritten;
     112    while ((bytesWritten = write(g_fdOut, (const char *)bytes + ofs, len - ofs)) > 0) {
     113        ofs += bytesWritten;
     114        if (ofs == len)
     115            break;
     116    }
     117    if (bytesWritten < 0) {
     118        ERROR("write: %s", strerror(errno));
     119    }
     120    return bytesWritten;
     121}
     122
    102123bool
    103 GetBooleanFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, bool *boolPtr)
     124nv::SocketRead(char *bytes, size_t len)
     125{
     126    ReadBuffer::BufferStatus status;
     127    status = g_inBufPtr->followingData((unsigned char *)bytes, len);
     128    TRACE("followingData status: %d", status);
     129    return (status == ReadBuffer::OK);
     130}
     131
     132static int
     133ExecuteCommand(Tcl_Interp *interp, Tcl_DString *dsPtr)
     134{
     135    int result;
     136#ifdef WANT_TRACE
     137    char *str = Tcl_DStringValue(dsPtr);
     138    std::string cmd(str);
     139    cmd.erase(cmd.find_last_not_of(" \n\r\t")+1);
     140    TRACE("command %lu: '%s'", g_stats.nCommands+1, cmd.c_str());
     141#endif
     142
     143    result = Tcl_EvalEx(interp, Tcl_DStringValue(dsPtr),
     144                        Tcl_DStringLength(dsPtr),
     145                        TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL);
     146    Tcl_DStringSetLength(dsPtr, 0);
     147
     148    if (result != TCL_OK) {
     149        TRACE("Error: %d", result);
     150    }
     151    return result;
     152}
     153
     154int
     155nv::GetBooleanFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, bool *boolPtr)
    104156{
    105157    int value;
     
    113165
    114166int
    115 GetFloatFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, float *valuePtr)
     167nv::GetFloatFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, float *valuePtr)
    116168{
    117169    double value;
     
    392444 */
    393445int
    394 GetAxisFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *indexPtr)
     446nv::GetAxisFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *indexPtr)
    395447{
    396448    return GetAxis(interp, Tcl_GetString(objPtr), indexPtr);
     
    449501 */
    450502int
    451 GetDataStream(Tcl_Interp *interp, Rappture::Buffer &buf, int nBytes)
    452 {
     503nv::GetDataStream(Tcl_Interp *interp, Rappture::Buffer &buf, int nBytes)
     504{
     505#ifdef USE_NEW_EVENT_LOOP
     506    if (!SocketRead((char *)buf.bytes(), nBytes)) {
     507        return TCL_ERROR;
     508    }
     509    buf.count(nBytes);
     510#else
    453511    char buffer[8096];
    454512
    455     clearerr(NanoVis::stdin);
     513    clearerr(g_fIn);
    456514    while (nBytes > 0) {
    457515        unsigned int chunk;
     
    460518        chunk = (sizeof(buffer) < (unsigned int) nBytes) ?
    461519            sizeof(buffer) : nBytes;
    462         nRead = fread(buffer, sizeof(char), chunk, NanoVis::stdin);
    463         if (ferror(NanoVis::stdin)) {
     520        nRead = fread(buffer, sizeof(char), chunk, g_fIn);
     521        if (ferror(g_fIn)) {
    464522            Tcl_AppendResult(interp, "while reading data stream: ",
    465523                             Tcl_PosixError(interp), (char*)NULL);
    466524            return TCL_ERROR;
    467525        }
    468         if (feof(NanoVis::stdin)) {
     526        if (feof(g_fIn)) {
    469527            Tcl_AppendResult(interp, "premature EOF while reading data stream",
    470528                             (char*)NULL);
     
    474532        nBytes -= nRead;
    475533    }
    476     if (NanoVis::recfile != NULL) {
    477         ssize_t nWritten;
    478 
    479         nWritten = fwrite(buf.bytes(), sizeof(char), buf.size(),
    480                           NanoVis::recfile);
    481         assert(nWritten == (ssize_t)buf.size());
    482         fflush(NanoVis::recfile);
    483     }
     534#endif
    484535    Rappture::Outcome err;
    485536    TRACE("Checking header[%.13s]", buf.bytes());
     
    785836    /* Use the initial client key value pairs as the parts for a generating
    786837     * a unique file name. */
    787     int f = NanoVis::getStatsFile(objv[1]);
     838    int f = getStatsFile(objv[1]);
    788839    if (f < 0) {
    789840        Tcl_AppendResult(interp, "can't open stats file: ",
     
    806857        objPtr = Tcl_NewStringObj("pid", 3);
    807858        Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
    808         Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewLongObj((long)NanoVis::stats.pid));
     859        Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewLongObj((long)g_stats.pid));
    809860        /* host */
    810861        objPtr = Tcl_NewStringObj("host", 4);
     
    821872    /* date */
    822873    Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewStringObj("date", 4));
    823     strcpy(buf, ctime(&NanoVis::stats.start.tv_sec));
     874    strcpy(buf, ctime(&g_stats.start.tv_sec));
    824875    buf[strlen(buf) - 1] = '\0';
    825876    Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewStringObj(buf, -1));
     
    828879                             Tcl_NewStringObj("date_secs", 9));
    829880    Tcl_ListObjAppendElement(interp, listObjPtr,
    830                              Tcl_NewLongObj(NanoVis::stats.start.tv_sec));
     881                             Tcl_NewLongObj(g_stats.start.tv_sec));
    831882    /* Client arguments. */
    832883    if (Tcl_ListObjGetElements(interp, objv[1], &numItems, &items) != TCL_OK) {
     
    841892    Tcl_DStringAppend(&ds, "\n", 1);
    842893#ifdef KEEPSTATS
    843     result = NanoVis::writeToStatsFile(f, Tcl_DStringValue(&ds),
    844                                        Tcl_DStringLength(&ds));
     894    result = writeToStatsFile(f, Tcl_DStringValue(&ds),
     895                              Tcl_DStringLength(&ds));
    845896#else
    846897    TRACE("clientinfo: %s", Tcl_DStringValue(&ds));
     
    12991350                    volume->wAxis.min(), volume->wAxis.max(),
    13001351                    Volume::valueMin, Volume::valueMax);
    1301         ssize_t nWritten = write(1, info, (size_t)cmdLength);
    1302         if (nWritten != (ssize_t)cmdLength) {
    1303             ERROR("Short write");
     1352        if (SocketWrite(info, (size_t)cmdLength) != (ssize_t)cmdLength) {
    13041353            return TCL_ERROR;
    13051354        }
     
    21352184}
    21362185
    2137 Tcl_Interp *
    2138 initTcl()
    2139 {
    2140     Tcl_Interp *interp = Tcl_CreateInterp();
     2186/**
     2187 * \brief Execute commands from client in Tcl interpreter
     2188 *
     2189 * In this threaded model, the select call is for event compression.  We
     2190 * want to execute render server commands as long as they keep coming. 
     2191 * This lets us execute a stream of many commands but render once.  This
     2192 * benefits camera movements, screen resizing, and opacity changes
     2193 * (using a slider on the client).  The down side is you don't render
     2194 * until there's a lull in the command stream.  If the client needs an
     2195 * image, it can issue an "imgflush" command.  That breaks us out of the
     2196 * read loop.
     2197 */
     2198int
     2199nv::processCommands(Tcl_Interp *interp,
     2200                    ReadBuffer *inBufPtr, int fdOut)
     2201{
     2202    int ret = 1;
     2203    int status = TCL_OK;
     2204
     2205    Tcl_DString command;
     2206    Tcl_DStringInit(&command);
     2207    fd_set readFds;
     2208    struct timeval tv, *tvPtr;
     2209
     2210    FD_ZERO(&readFds);
     2211    FD_SET(inBufPtr->file(), &readFds);
     2212    tvPtr = NULL;                       /* Wait for the first read. This is so
     2213                                         * that we don't spin when no data is
     2214                                         * available. */
     2215    while (inBufPtr->isLineAvailable() ||
     2216           (select(inBufPtr->file()+1, &readFds, NULL, NULL, tvPtr) > 0)) {
     2217        size_t numBytes;
     2218        unsigned char *buffer;
     2219
     2220        /* A short read is treated as an error here because we assume that we
     2221         * will always get commands line by line. */
     2222        if (inBufPtr->getLine(&numBytes, &buffer) != ReadBuffer::OK) {
     2223            /* Terminate the server if we can't communicate with the client
     2224             * anymore. */
     2225            if (inBufPtr->status() == ReadBuffer::ENDFILE) {
     2226                TRACE("Exiting server on EOF from client");
     2227                return -1;
     2228            } else {
     2229                ERROR("Exiting server, failed to read from client: %s",
     2230                      strerror(errno));
     2231                return -1;
     2232            }
     2233        }
     2234        Tcl_DStringAppend(&command, (char *)buffer, numBytes);
     2235        if (Tcl_CommandComplete(Tcl_DStringValue(&command))) {
     2236            struct timeval start, finish;
     2237            gettimeofday(&start, NULL);
     2238            status = ExecuteCommand(interp, &command);
     2239            gettimeofday(&finish, NULL);
     2240            g_stats.cmdTime += (MSECS_ELAPSED(start, finish) / 1.0e+3);
     2241            g_stats.nCommands++;
     2242            if (status == TCL_BREAK) {
     2243                return 1;               /* This was caused by a "imgflush"
     2244                                         * command. Break out of the read loop
     2245                                         * and allow a new image to be
     2246                                         * rendered. */
     2247            } else { //if (status != TCL_OK) {
     2248                ret = 0;
     2249                if (handleError(interp, status, fdOut) < 0) {
     2250                    return -1;
     2251                }
     2252            }
     2253        }
     2254
     2255        tv.tv_sec = tv.tv_usec = 0L;    /* On successive reads, we break out
     2256                                         * if no data is available. */
     2257        FD_SET(inBufPtr->file(), &readFds);
     2258        tvPtr = &tv;
     2259    }
     2260
     2261    return ret;
     2262}
     2263
     2264/**
     2265 * \brief Send error message to client socket
     2266 */
     2267int
     2268nv::handleError(Tcl_Interp *interp, int status, int fdOut)
     2269{
     2270    const char *string;
     2271    int nBytes;
     2272
     2273    if (status != TCL_OK) {
     2274        string = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
     2275        nBytes = strlen(string);
     2276        if (nBytes > 0) {
     2277            TRACE("status=%d errorInfo=(%s)", status, string);
     2278
     2279            std::ostringstream oss;
     2280            oss << "nv>viserror -type internal_error -token " << g_stats.nCommands << " -bytes " << nBytes << "\n" << string;
     2281            std::string ostr = oss.str();
     2282            nBytes = ostr.length();
     2283
     2284            if (write(fdOut, oss.str().c_str(), nBytes) < 0) {
     2285                ERROR("write failed: %s", strerror(errno));
     2286                return -1;
     2287            }
     2288        }
     2289    }
     2290
     2291    std::string msg = getUserMessages();
     2292    nBytes = msg.length();
     2293    if (nBytes > 0) {
     2294        string = msg.c_str();
     2295        TRACE("userError=(%s)", string);
     2296
     2297        std::ostringstream oss;
     2298        oss << "nv>viserror -type error -token " << g_stats.nCommands << " -bytes " << nBytes << "\n" << string;
     2299        std::string ostr = oss.str();
     2300        nBytes = ostr.length();
     2301
     2302        if (write(fdOut, ostr.c_str(), nBytes) < 0) {
     2303            ERROR("write failed: %s", strerror(errno));
     2304            return -1;
     2305        }
     2306        clearUserMessages();
     2307    }
     2308
     2309    return 0;
     2310}
     2311
     2312void
     2313nv::initTcl(Tcl_Interp *interp, ClientData clientData)
     2314{
    21412315    Tcl_MakeSafe(interp);
    21422316
    2143     Tcl_CreateObjCommand(interp, "axis",        AxisCmd,        NULL, NULL);
    2144     Tcl_CreateObjCommand(interp, "camera",      CameraCmd,      NULL, NULL);
    2145     Tcl_CreateObjCommand(interp, "clientinfo",  ClientInfoCmd,  NULL, NULL);
    2146     Tcl_CreateObjCommand(interp, "cutplane",    CutplaneCmd,    NULL, NULL);
    2147     if (FlowCmdInitProc(interp) != TCL_OK) {
    2148         return NULL;
    2149     }
    2150     Tcl_CreateObjCommand(interp, "grid",        GridCmd,        NULL, NULL);
    2151     Tcl_CreateObjCommand(interp, "heightmap",   HeightMapCmd,   NULL, NULL);
    2152     Tcl_CreateObjCommand(interp, "imgflush",    ImageFlushCmd,  NULL, NULL);
    2153     Tcl_CreateObjCommand(interp, "legend",      LegendCmd,      NULL, NULL);
    2154     Tcl_CreateObjCommand(interp, "screen",      ScreenCmd,      NULL, NULL);
    2155     Tcl_CreateObjCommand(interp, "snapshot",    SnapshotCmd,    NULL, NULL);
    2156     Tcl_CreateObjCommand(interp, "transfunc",   TransfuncCmd,   NULL, NULL);
    2157     Tcl_CreateObjCommand(interp, "up",          UpCmd,          NULL, NULL);
    2158     Tcl_CreateObjCommand(interp, "volume",      VolumeCmd,      NULL, NULL);
     2317    Tcl_CreateObjCommand(interp, "axis",        AxisCmd,        clientData, NULL);
     2318    Tcl_CreateObjCommand(interp, "camera",      CameraCmd,      clientData, NULL);
     2319    Tcl_CreateObjCommand(interp, "clientinfo",  ClientInfoCmd,  clientData, NULL);
     2320    Tcl_CreateObjCommand(interp, "cutplane",    CutplaneCmd,    clientData, NULL);
     2321    FlowCmdInitProc(interp, clientData);
     2322    Tcl_CreateObjCommand(interp, "grid",        GridCmd,        clientData, NULL);
     2323    Tcl_CreateObjCommand(interp, "heightmap",   HeightMapCmd,   clientData, NULL);
     2324    Tcl_CreateObjCommand(interp, "imgflush",    ImageFlushCmd,  clientData, NULL);
     2325    Tcl_CreateObjCommand(interp, "legend",      LegendCmd,      clientData, NULL);
     2326    Tcl_CreateObjCommand(interp, "screen",      ScreenCmd,      clientData, NULL);
     2327    Tcl_CreateObjCommand(interp, "snapshot",    SnapshotCmd,    clientData, NULL);
     2328    Tcl_CreateObjCommand(interp, "transfunc",   TransfuncCmd,   clientData, NULL);
     2329    Tcl_CreateObjCommand(interp, "up",          UpCmd,          clientData, NULL);
     2330    Tcl_CreateObjCommand(interp, "volume",      VolumeCmd,      clientData, NULL);
    21592331
    21602332    // create a default transfer function
     
    21632335             Tcl_GetStringResult(interp));
    21642336    }
    2165     return interp;
    2166 }
     2337}
  • nanovis/branches/1.1/Command.h

    r4612 r4874  
    1212#define COMMAND_H
    1313
     14#include <unistd.h>
     15
    1416#include <tcl.h>
    1517
     
    1820}
    1921class Volume;
     22
     23namespace nv {
     24
     25class ReadBuffer;
     26
     27extern ssize_t SocketWrite(const void *bytes, size_t len);
     28
     29extern bool SocketRead(char *bytes, size_t len);
     30
     31extern int processCommands(Tcl_Interp *interp,
     32                           ReadBuffer *inBufPtr,
     33                           int fdOut);
     34
     35extern int handleError(Tcl_Interp *interp,
     36                       int status,
     37                       int fdOut);
     38
     39extern void initTcl(Tcl_Interp *interp, ClientData clientData);
    2040
    2141extern int GetAxisFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
     
    3050                           float *floatVal);
    3151
    32 extern int GetVolumeFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
    33                             Volume **volume);
    34 
    35 extern Tcl_Interp *initTcl();
     52}
    3653
    3754#endif
  • nanovis/branches/1.1/Flow.cpp

    r4612 r4874  
    2929#include "TransferFunction.h"
    3030
     31using namespace nv;
    3132using namespace vrmath;
    3233
  • nanovis/branches/1.1/FlowCmd.cpp

    r4831 r4874  
    2525#include "nvconf.h"
    2626
     27#include "nanovisServer.h"
    2728#include "nanovis.h"
    2829#include "CmdProc.h"
     
    4142#include "Trace.h"
    4243
     44using namespace nv;
    4345using namespace vrmath;
    4446
     
    296298            sprintf(info, "nv>data tag %s min %g max %g\n",
    297299                    flow->name(), dataPtr->magMin(), dataPtr->magMax());
    298         ssize_t nWritten = write(1, info, (size_t)length);
    299         if (nWritten != (ssize_t)length) {
    300             ERROR("Short write");
     300        if (SocketWrite(info, (size_t)length) < 0) {
    301301            return TCL_ERROR;
    302302        }
     
    835835 */
    836836int
    837 FlowInstObjCmd(ClientData clientData, Tcl_Interp *interp, int objc,
    838                Tcl_Obj *const *objv)
     837nv::FlowInstObjCmd(ClientData clientData, Tcl_Interp *interp, int objc,
     838                   Tcl_Obj *const *objv)
    839839{
    840840    Tcl_ObjCmdProc *proc;
     
    858858 */
    859859void
    860 FlowInstDeleteProc(ClientData clientData)
     860nv::FlowInstDeleteProc(ClientData clientData)
    861861{
    862862    Flow *flow = (Flow *)clientData;
     
    11221122{
    11231123    struct pollfd pollResults;
    1124     pollResults.fd = fileno(NanoVis::stdin);
     1124    pollResults.fd = g_fdIn;
    11251125    pollResults.events = POLLIN;
    11261126#define PENDING_TIMEOUT          10  /* milliseconds. */
     
    12321232    sprintf(cmd,"nv>image -type movie -token \"%s\" -bytes %lu\n",
    12331233            token, (unsigned long)data.size());
    1234     NanoVis::sendDataToClient(cmd, data.bytes(), data.size());
     1234    nv::sendDataToClient(cmd, data.bytes(), data.size());
    12351235    return TCL_OK;
    12361236}
     
    13451345 *    associative array.
    13461346 */
    1347 int
    1348 FlowCmdInitProc(Tcl_Interp *interp)
    1349 {
    1350     Tcl_CreateObjCommand(interp, "flow", FlowCmdProc, NULL, NULL);
    1351     return TCL_OK;
    1352 }
     1347void
     1348nv::FlowCmdInitProc(Tcl_Interp *interp, ClientData clientData)
     1349{
     1350    Tcl_CreateObjCommand(interp, "flow", FlowCmdProc, clientData, NULL);
     1351}
  • nanovis/branches/1.1/FlowCmd.h

    r4612 r4874  
    2727#include <tcl.h>
    2828
    29 extern Tcl_AppInitProc FlowCmdInitProc;
     29namespace nv {
     30
     31extern void FlowCmdInitProc(Tcl_Interp *interp, ClientData clientData);
     32
    3033extern Tcl_ObjCmdProc FlowInstObjCmd;
    3134extern Tcl_CmdDeleteProc FlowInstDeleteProc;
    3235
     36}
     37
    3338#endif
  • nanovis/branches/1.1/Grid.cpp

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

    r4612 r4874  
    5757HeightMap::render(RenderContext *renderContext)
    5858{
     59    if (!isVisible())
     60        return;
     61
    5962    glPushAttrib(GL_ENABLE_BIT | GL_POLYGON_BIT | GL_LIGHTING_BIT);
    6063
  • nanovis/branches/1.1/Makefile.in

    r4831 r4874  
    130130                Plane.o \
    131131                PlaneRenderer.o \
     132                ReadBuffer.o \
    132133                ReaderCommon.o \
    133134                RenderVertexArray.o \
     
    147148                dxReader.o \
    148149                md5.o \
    149                 nanovis.o
     150                nanovis.o \
     151                nanovisServer.o
    150152
    151153resources       = \
     
    271273Chain.o: Chain.cpp Chain.h
    272274CmdProc.o: CmdProc.cpp CmdProc.h
    273 Command.o: Command.cpp nanovis.h config.h 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
     275Command.o: Command.cpp nanovis.h nanovisServer.h ReadBuffer.h config.h define.h FlowCmd.h CmdProc.h Trace.h PlaneRenderer.h dxReader.h Grid.h HeightMap.h NvCamera.h NvZincBlendeReconstructor.h Unirect.h Volume.h VolumeRenderer.h
    274276ContourLineFilter.o: ContourLineFilter.cpp ContourLineFilter.h
    275277ConvexPolygon.o: ConvexPolygon.cpp ConvexPolygon.h $(VRMATH_DIR)/include/vrmath/Vector4f.h $(VRMATH_DIR)/include/vrmath/Matrix4x4d.h Plane.h
    276 Flow.o: Flow.cpp Flow.h FlowCmd.h FlowTypes.h FlowBox.h FlowParticles.h Switch.h Trace.h
     278Flow.o: Flow.cpp Flow.h FlowCmd.h FlowTypes.h FlowBox.h FlowParticles.h NvLIC.h VelocityArrowsSlice.h Switch.h Unirect.h Volume.h TransferFunction.h Trace.h
    277279FlowBox.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
    278 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
     280FlowCmd.o: FlowCmd.cpp FlowCmd.h FlowParticles.h FlowBox.h FlowTypes.h Command.h Switch.h Trace.h TransferFunction.h nanovis.h nanovisServer.h CmdProc.h NvLIC.h Unirect.h Volume.h VelocityArrowsSlice.h $(VRMATH_DIR)/include/vrmath/Vector3f.h
    279281FlowParticles.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
    280282GradientFilter.o: GradientFilter.cpp GradientFilter.h
     
    302304PointSetRenderer.o: PointSetRenderer.cpp PointSetRenderer.h
    303305PointShader.o: PointShader.cpp PointShader.h
     306ReadBuffer.o: ReadBuffer.cpp ReadBuffer.h Trace.h
    304307ReaderCommon.o: ReaderCommon.cpp ReaderCommon.h GradientFilter.h $(VRMATH_DIR)/include/vrmath/Vector3f.h
    305308RenderVertexArray.o: RenderVertexArray.cpp RenderVertexArray.h
     
    318321ZincBlendeVolume.o: ZincBlendeVolume.cpp ZincBlendeVolume.h config.h define.h
    319322dxReader.o: dxReader.cpp ReaderCommon.h config.h nanovis.h Unirect.h ZincBlendeVolume.h NvZincBlendeReconstructor.h
    320 nanovis.o: nanovis.cpp nanovis.h config.h define.h 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
    321323md5.o: md5.h
     324nanovis.o: nanovis.cpp nanovis.h nanovisServer.h config.h define.h 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
     325nanovisServer.o: nanovisServer.cpp nanovisServer.h config.h nanovis.h define.h Command.h NvShader.h Trace.h
  • nanovis/branches/1.1/Trace.cpp

    r4612 r4874  
    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
     92std::string
     93nv::getUserMessages()
     94{
     95    return g_UserErrorString.str();
     96}
     97
     98void
     99nv::clearUserMessages()
     100{
     101    g_UserErrorString.str(std::string());
    44102}
    45103
  • nanovis/branches/1.1/Trace.h

    r4612 r4874  
    99#define __TRACE_H__
    1010
     11#include <string>
     12
    1113#include <GL/glew.h>
    1214#include <syslog.h>
     
    1820#define AT __FILE__ ":" NEWSTRING(__LINE__)
    1921
     22namespace nv {
     23
     24extern void logUserMessage(const char* format, ...);
     25
     26extern std::string getUserMessages();
     27
     28extern void clearUserMessages();
     29
     30extern void initLog();
     31
     32extern void closeLog();
     33
    2034extern void LogMessage(int priority, const char *funcname, const char *fileName,
    2135                       int lineNum, const char* format, ...);
    2236
    23 #define ERROR(...)      LogMessage(LOG_ERR, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
     37#define ERROR(...)      nv::LogMessage(LOG_ERR, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
    2438#ifdef WANT_TRACE
    25 #define TRACE(...)      LogMessage(LOG_DEBUG, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
     39#define TRACE(...)      nv::LogMessage(LOG_DEBUG, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
    2640#else
    2741#define TRACE(...)
    2842#endif
    29 #define WARN(...)       LogMessage(LOG_WARNING, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
    30 #define INFO(...)       LogMessage(LOG_INFO, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
     43#define WARN(...)       nv::LogMessage(LOG_WARNING, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
     44#define INFO(...)       nv::LogMessage(LOG_INFO, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
     45
     46#define USER_ERROR(...) nv::logUserMessage(__VA_ARGS__);
     47
     48}
    3149
    3250extern bool CheckFBO(GLenum *status);
    3351extern void PrintFBOStatus(GLenum status, const char *prefix);
    3452extern bool CheckGL(const char *prefix);
     53
    3554#endif
  • nanovis/branches/1.1/Unirect.cpp

    r4612 r4874  
    1515#include "Unirect.h"
    1616#include "Trace.h"
     17
     18using namespace nv;
    1719
    1820static inline char *
  • nanovis/branches/1.1/VolumeInterpolator.cpp

    r4612 r4874  
    66#include <string.h>
    77#include <memory.h>
    8 #include <time.h>
    98#include <sys/time.h>
    109#include <math.h>
  • nanovis/branches/1.1/config.h

    r4614 r4874  
    4242#define KEEPSTATS
    4343
     44//#define USE_NEW_EVENT_LOOP
     45
    4446/*
    4547 * Controls whether DX data is downsampled.
  • nanovis/branches/1.1/nanovis.cpp

    r4820 r4874  
    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>
    2819#include <sys/types.h>
    29 #include <sys/uio.h> // for readv/writev
    30 #include <time.h>
     20#include <sys/uio.h> // for writev in ppmWrite
    3121#include <unistd.h>
    3222
     23#include <cassert>
    3324#include <cstdlib>
    3425#include <cstdio>
     
    3627#include <cmath>
    3728
    38 #include <iostream>
    39 #include <fstream>
    40 #include <sstream>
    4129#include <string>
    4230
     
    4432#include <GL/glut.h>
    4533
    46 #include <RpEncode.h>
    47 
    4834#include <graphics/RenderContext.h>
    4935#include <vrmath/Vector3f.h>
     
    5743#include "config.h"
    5844#include "nanovis.h"
     45#include "nanovisServer.h"
    5946#include "define.h"
    6047
     
    6653#include "NvShader.h"
    6754#include "NvLIC.h"
    68 #include "NvZincBlendeReconstructor.h"
    6955#include "PlaneRenderer.h"
    7056#include "Switch.h"
    7157#include "Trace.h"
     58#include "TransferFunction.h"
    7259#include "Unirect.h"
    7360#include "VelocityArrowsSlice.h"
    7461#include "VolumeInterpolator.h"
    7562#include "VolumeRenderer.h"
    76 #include "ZincBlendeVolume.h"
    77 
     63
     64using namespace nv;
    7865using namespace nv::graphics;
    7966using namespace nv::util;
     
    8976// STATIC MEMBER DATA
    9077
    91 FILE *NanoVis::stdin = NULL;
    92 FILE *NanoVis::logfile = NULL;
    93 FILE *NanoVis::recfile = NULL;
    94 
    95 NanoVis::Stats NanoVis::stats;
    96 int NanoVis::statsFile = -1;
     78Tcl_Interp *NanoVis::interp = NULL;
    9779
    9880unsigned int NanoVis::flags = 0;
     
    10587unsigned char *NanoVis::screenBuffer = NULL;
    10688Texture2D *NanoVis::legendTexture = NULL;
    107 Grid *NanoVis::grid = NULL;
    10889Fonts *NanoVis::fonts;
    10990int NanoVis::updir = Y_POS;
     
    132113NvLIC *NanoVis::licRenderer = NULL;
    133114PlaneRenderer *NanoVis::planeRenderer = NULL;
    134 
    135 Tcl_Interp *NanoVis::interp;
     115Grid *NanoVis::grid = NULL;
    136116
    137117// Image based flow visualization slice location
     
    210190        flags |= REDRAW_PENDING;
    211191    }
    212 }
    213 
    214 #ifdef KEEPSTATS
    215 
    216 #ifndef STATSDIR
    217 #define STATSDIR        "/var/tmp/visservers"
    218 #endif  /*STATSDIR*/
    219 
    220 int
    221 NanoVis::getStatsFile(Tcl_Obj *objPtr)
    222 {
    223     Tcl_DString ds;
    224     char fileName[33];
    225     char pidstr[200];
    226     const char *path;
    227     md5_state_t state;
    228     md5_byte_t digest[16];
    229     char *string;
    230     int length;
    231 
    232     if ((objPtr == NULL) || (statsFile >= 0)) {
    233         return statsFile;
    234     }
    235     /* By itself the client's key/value pairs aren't unique.  Add in the
    236      * process id of this render server. */
    237     sprintf(pidstr, "%ld", (long)stats.pid);
    238 
    239     /* Create an md5 hash of the key/value pairs and use it as the file name. */
    240     string = Tcl_GetStringFromObj(objPtr, &length);
    241     md5_init(&state);
    242     md5_append(&state, (const md5_byte_t *)string, strlen(string));
    243     md5_append(&state, (const md5_byte_t *)pidstr, strlen(pidstr));
    244     md5_finish(&state, digest);
    245     for (int i = 0; i < 16; i++) {
    246         sprintf(fileName + i * 2, "%02x", digest[i]);
    247     }
    248     Tcl_DStringInit(&ds);
    249     Tcl_DStringAppend(&ds, STATSDIR, -1);
    250     Tcl_DStringAppend(&ds, "/", 1);
    251     Tcl_DStringAppend(&ds, fileName, 32);
    252     path = Tcl_DStringValue(&ds);
    253 
    254     statsFile = open(path, O_EXCL | O_CREAT | O_WRONLY, 0600);
    255     Tcl_DStringFree(&ds);
    256     if (statsFile < 0) {
    257         ERROR("can't open \"%s\": %s", fileName, strerror(errno));
    258         return -1;
    259     }
    260     return statsFile;
    261 }
    262 
    263 int
    264 NanoVis::writeToStatsFile(int f, const char *s, size_t length)
    265 {
    266     if (f >= 0) {
    267         ssize_t numWritten;
    268 
    269         numWritten = write(f, s, length);
    270         if (numWritten == (ssize_t)length) {
    271             close(dup(f));
    272         }
    273     }
    274     return 0;
    275 }
    276 
    277 static int
    278 serverStats(int code)
    279 {
    280     double start, finish;
    281     char buf[BUFSIZ];
    282     Tcl_DString ds;
    283     int result;
    284 
    285     {
    286         struct timeval tv;
    287 
    288         /* Get ending time.  */
    289         gettimeofday(&tv, NULL);
    290         finish = CVT2SECS(tv);
    291         tv = NanoVis::stats.start;
    292         start = CVT2SECS(tv);
    293     }
    294     /*
    295      * Session information:
    296      *   - Name of render server
    297      *   - Process ID
    298      *   - Hostname where server is running
    299      *   - Start date of session
    300      *   - Start date of session in seconds
    301      *   - Number of frames returned
    302      *   - Number of bytes total returned (in frames)
    303      *   - Number of commands received
    304      *   - Total elapsed time of all commands
    305      *   - Total elapsed time of session
    306      *   - Exit code of vizserver
    307      *   - User time
    308      *   - System time
    309      *   - User time of children
    310      *   - System time of children
    311      */
    312 
    313     Tcl_DStringInit(&ds);
    314    
    315     Tcl_DStringAppendElement(&ds, "render_stop");
    316     /* renderer */
    317     Tcl_DStringAppendElement(&ds, "renderer");
    318     Tcl_DStringAppendElement(&ds, "nanovis");
    319     /* pid */
    320     Tcl_DStringAppendElement(&ds, "pid");
    321     sprintf(buf, "%d", NanoVis::stats.pid);
    322     Tcl_DStringAppendElement(&ds, buf);
    323     /* host */
    324     Tcl_DStringAppendElement(&ds, "host");
    325     gethostname(buf, BUFSIZ-1);
    326     buf[BUFSIZ-1] = '\0';
    327     Tcl_DStringAppendElement(&ds, buf);
    328     /* date */
    329     Tcl_DStringAppendElement(&ds, "date");
    330     strcpy(buf, ctime(&NanoVis::stats.start.tv_sec));
    331     buf[strlen(buf) - 1] = '\0';
    332     Tcl_DStringAppendElement(&ds, buf);
    333     /* date_secs */
    334     Tcl_DStringAppendElement(&ds, "date_secs");
    335     sprintf(buf, "%ld", NanoVis::stats.start.tv_sec);
    336     Tcl_DStringAppendElement(&ds, buf);
    337     /* num_frames */
    338     Tcl_DStringAppendElement(&ds, "num_frames");
    339     sprintf(buf, "%lu", (unsigned long)NanoVis::stats.nFrames);
    340     Tcl_DStringAppendElement(&ds, buf);
    341     /* frame_bytes */
    342     Tcl_DStringAppendElement(&ds, "frame_bytes");
    343     sprintf(buf, "%lu", (unsigned long)NanoVis::stats.nBytes);
    344     Tcl_DStringAppendElement(&ds, buf);
    345     /* num_commands */
    346     Tcl_DStringAppendElement(&ds, "num_commands");
    347     sprintf(buf, "%lu", (unsigned long)NanoVis::stats.nCommands);
    348     Tcl_DStringAppendElement(&ds, buf);
    349     /* cmd_time */
    350     Tcl_DStringAppendElement(&ds, "cmd_time");
    351     sprintf(buf, "%g", NanoVis::stats.cmdTime);
    352     Tcl_DStringAppendElement(&ds, buf);
    353     /* session_time */
    354     Tcl_DStringAppendElement(&ds, "session_time");
    355     sprintf(buf, "%g", finish - start);
    356     Tcl_DStringAppendElement(&ds, buf);
    357     /* status */
    358     Tcl_DStringAppendElement(&ds, "status");
    359     sprintf(buf, "%d", code);
    360     Tcl_DStringAppendElement(&ds, buf);
    361     {
    362         long clocksPerSec = sysconf(_SC_CLK_TCK);
    363         double clockRes = 1.0 / clocksPerSec;
    364         struct tms tms;
    365 
    366         memset(&tms, 0, sizeof(tms));
    367         times(&tms);
    368         /* utime */
    369         Tcl_DStringAppendElement(&ds, "utime");
    370         sprintf(buf, "%g", tms.tms_utime * clockRes);
    371         Tcl_DStringAppendElement(&ds, buf);
    372         /* stime */
    373         Tcl_DStringAppendElement(&ds, "stime");
    374         sprintf(buf, "%g", tms.tms_stime * clockRes);
    375         Tcl_DStringAppendElement(&ds, buf);
    376         /* cutime */
    377         Tcl_DStringAppendElement(&ds, "cutime");
    378         sprintf(buf, "%g", tms.tms_cutime * clockRes);
    379         Tcl_DStringAppendElement(&ds, buf);
    380         /* cstime */
    381         Tcl_DStringAppendElement(&ds, "cstime");
    382         sprintf(buf, "%g", tms.tms_cstime * clockRes);
    383         Tcl_DStringAppendElement(&ds, buf);
    384     }
    385     Tcl_DStringAppend(&ds, "\n", -1);
    386     int f = NanoVis::getStatsFile(NULL);
    387     result = NanoVis::writeToStatsFile(f, Tcl_DStringValue(&ds),
    388                                        Tcl_DStringLength(&ds));
    389     close(f);
    390     Tcl_DStringFree(&ds);
    391     return result;
    392 }
    393 
    394 #endif
    395 
    396 static void
    397 initService()
    398 {
    399     TRACE("Enter");
    400 
    401     const char* user = getenv("USER");
    402     char* logName = NULL;
    403     int logNameLen = 0;
    404 
    405     if (user == NULL) {
    406         logNameLen = 20+1;
    407         logName = (char *)calloc(logNameLen, sizeof(char));
    408         strncpy(logName, "/tmp/nanovis_log.txt", logNameLen);
    409     } else {
    410         logNameLen = 17+1+strlen(user);
    411         logName = (char *)calloc(logNameLen, sizeof(char));
    412         strncpy(logName, "/tmp/nanovis_log_", logNameLen);
    413         strncat(logName, user, strlen(user));
    414     }
    415 
    416     //open log and map stderr to log file
    417     NanoVis::logfile = fopen(logName, "w");
    418     dup2(fileno(NanoVis::logfile), 2);
    419     /* dup2(2,1); */
    420 
    421     // clean up malloc'd memory
    422     if (logName != NULL) {
    423         free(logName);
    424     }
    425 
    426     TRACE("Leave");
    427 }
    428 
    429 static void
    430 exitService(int code)
    431 {
    432     TRACE("Enter: %d", code);
    433 
    434     NanoVis::removeAllData();
    435 
    436     NvShader::exitCg();
    437 
    438     //close log file
    439     if (NanoVis::logfile != NULL) {
    440         fclose(NanoVis::logfile);
    441         NanoVis::logfile = NULL;
    442     }
    443 
    444 #ifdef KEEPSTATS
    445     serverStats(code);
    446 #endif
    447     closelog();
    448 
    449     exit(code);
    450 }
    451 
    452 static int
    453 executeCommand(Tcl_Interp *interp, Tcl_DString *dsPtr)
    454 {
    455     struct timeval tv;
    456     double start, finish;
    457     int result;
    458 
    459 #ifdef WANT_TRACE
    460     char *str = Tcl_DStringValue(dsPtr);
    461     std::string cmd(str);
    462     cmd.erase(cmd.find_last_not_of(" \n\r\t")+1);
    463     TRACE("command %lu: '%s'", NanoVis::stats.nCommands+1, cmd.c_str());
    464 #endif
    465 
    466     gettimeofday(&tv, NULL);
    467     start = CVT2SECS(tv);
    468 
    469     if (NanoVis::recfile != NULL) {
    470         fprintf(NanoVis::recfile, "%s", Tcl_DStringValue(dsPtr));
    471         fflush(NanoVis::recfile);
    472     }
    473     result = Tcl_Eval(interp, Tcl_DStringValue(dsPtr));
    474     Tcl_DStringSetLength(dsPtr, 0);
    475 
    476     gettimeofday(&tv, NULL);
    477     finish = CVT2SECS(tv);
    478 
    479     NanoVis::stats.cmdTime += finish - start;
    480     NanoVis::stats.nCommands++;
    481     TRACE("Leave status=%d", result);
    482     return result;
    483192}
    484193
     
    615324    planeRenderer->render();
    616325
    617     // INSOO
     326    //glPixelStorei(GL_PACK_ALIGNMENT, 1);
    618327    glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, screenBuffer);
    619     //glReadPixels(0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, screenBuffer); // INSOO's
    620 
    621328    {
    622329        char prefix[200];
    623         ssize_t nWritten;
    624330
    625331        TRACE("Sending ppm legend image %s min:%g max:%g", volArg, min, max);
    626332        sprintf(prefix, "nv>legend %s %g %g", volArg, min, max);
    627333        ppmWrite(prefix);
    628         nWritten = write(1, "\n", 1);
    629         assert(nWritten == 1);
    630334    }
    631335    planeRenderer->removePlane(index);
     
    639343
    640344//initialize frame buffer objects for offscreen rendering
    641 void
     345bool
    642346NanoVis::initOffscreenBuffer()
    643347{
     
    678382    if (!CheckFBO(&status)) {
    679383        PrintFBOStatus(status, "finalFbo");
    680         exitService(3);
     384        return false;
    681385    }
    682386
    683387    TRACE("Leave");
     388    return true;
    684389}
    685390
    686391//resize the offscreen buffer
    687 void
     392bool
    688393NanoVis::resizeOffscreenBuffer(int w, int h)
    689394{
    690395    TRACE("Enter (%d, %d)", w, h);
    691396    if ((w == winWidth) && (h == winHeight)) {
    692         return;
     397        return true;
    693398    }
    694399    winWidth = w;
     
    751456    if (!CheckFBO(&status)) {
    752457        PrintFBOStatus(status, "finalFbo");
    753         exitService(3);
     458        return false;
    754459    }
    755460
     
    760465
    761466    TRACE("Leave (%d, %d)", w, h);
     467    return true;
    762468}
    763469
     
    767473    if (!NvShader::printErrorInfo()) {
    768474        TRACE("Cg error, exiting...");
    769         exitService(-1);
    770     }
    771 }
    772 
    773 void NanoVis::init(const char* path)
     475        exit(1);
     476    }
     477}
     478
     479bool NanoVis::init(const char* path)
    774480{
    775481    // print OpenGL driver information
     
    782488    if (path == NULL) {
    783489        ERROR("No path defined for shaders or resources");
    784         exitService(1);
     490        return false;
    785491    }
    786492    GLenum err = glewInit();
    787493    if (GLEW_OK != err) {
    788494        ERROR("Can't init GLEW: %s", glewGetErrorString(err));
    789         exitService(1);
     495        return false;
    790496    }
    791497    TRACE("Using GLEW %s", glewGetString(GLEW_VERSION));
     
    795501    if (!GLEW_VERSION_2_1) {
    796502        ERROR("OpenGL version 2.1 or greater is required");
    797         exitService(1);
     503        return false;
    798504    }
    799505
     
    802508    if (!GLEW_ARB_pixel_buffer_object) {
    803509        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).");
    804         exitService(1);
     510        return false;
    805511    }
    806512
     
    810516    if (!GLEW_EXT_framebuffer_object) {
    811517        ERROR("EXT_framebuffer_oject extension is required");
    812         exitService(1);
     518        return false;
    813519    }
    814520    // Rectangle textures were promoted in 3.1
     
    816522    if (!GLEW_ARB_texture_rectangle) {
    817523        ERROR("ARB_texture_rectangle extension is required");
    818         exitService(1);
     524        return false;
    819525    }
    820526#ifdef HAVE_FLOAT_TEXTURES
     
    823529        !GLEW_ARB_color_buffer_float) {
    824530        ERROR("ARB_texture_float and ARB_color_buffer_float extensions are required");
    825         exitService(1);
     531        return false;
    826532    }
    827533#endif
     
    830536        !GLEW_NV_fragment_program2) {
    831537        ERROR("NV_vertex_program3 and NV_fragment_program2 extensions are required");
    832         exitService(1);
     538        return false;
    833539    }
    834540
    835541    if (!FilePath::getInstance()->setPath(path)) {
    836542        ERROR("can't set file path to %s", path);
    837         exitService(1);
     543        return false;
    838544    }
    839545
     
    852558    grid = new Grid();
    853559    grid->setFont(fonts);
    854 }
    855 
    856 void
     560
     561    return true;
     562}
     563
     564bool
    857565NanoVis::initGL()
    858566{
     
    889597    glLightfv(GL_LIGHT1, GL_SPECULAR, white_light);
    890598
    891     initOffscreenBuffer();    //frame buffer object for offscreen rendering
    892 
    893     //create volume renderer
     599    //frame buffer object for offscreen rendering
     600    if (!initOffscreenBuffer()) {
     601        return false;
     602    }
     603
    894604    volRenderer = new VolumeRenderer();
    895605
    896     // create
    897606    renderContext = new RenderContext();
    898607
    899     //create a 2D plane renderer
    900608    planeRenderer = new PlaneRenderer(winWidth, winHeight);
    901609
     
    903611
    904612    TRACE("leaving initGL");
     613
     614    return true;
    905615}
    906616
     
    1035745    char string[200];
    1036746    sprintf(string, "%s %d\n", prefix, fsize);
    1037     nWritten = write(1, string, strlen(string));
     747    nWritten = write(g_fdOut, string, strlen(string));
    1038748    assert(nWritten == (ssize_t)strlen(string));
    1039749    header[pos++] = 'B';
     
    1088798    }
    1089799
    1090     nWritten = write(1, header, SIZEOF_BMP_HEADER);
     800    nWritten = write(g_fdOut, header, SIZEOF_BMP_HEADER);
    1091801    assert(nWritten == SIZEOF_BMP_HEADER);
    1092     nWritten = write(1, screenBuffer, (3*winWidth+pad)*winHeight);
     802    nWritten = write(g_fdOut, screenBuffer, (3*winWidth+pad)*winHeight);
    1093803    assert(nWritten == (3*winWidth+pad)*winHeight);
    1094     stats.nFrames++;
    1095     stats.nBytes += (3*winWidth+pad)*winHeight;
     804    g_stats.nFrames++;
     805    g_stats.nFrameBytes += (3*winWidth+pad)*winHeight;
    1096806}
    1097807
     
    1154864        srcRowPtr += bytesPerRow;
    1155865    }
    1156     if (writev(1, iov, nRecs) < 0) {
     866    if (writev(g_fdOut, iov, nRecs) < 0) {
    1157867        ERROR("write failed: %s", strerror(errno));
    1158868    }
    1159869    free(iov);
    1160     stats.nFrames++;
    1161     stats.nBytes += (bytesPerRow * winHeight);
     870    g_stats.nFrames++;
     871    g_stats.nFrameBytes += (bytesPerRow * winHeight);
    1162872    TRACE("Leave (%dx%d)", winWidth, winHeight);
    1163 }
    1164 
    1165 void
    1166 NanoVis::sendDataToClient(const char *command, const char *data, size_t dlen)
    1167 {
    1168     size_t numRecords = 2;
    1169 
    1170     struct iovec *iov = new iovec[numRecords];
    1171 
    1172     // Write the nanovisviewer command, then the image header and data.
    1173     // Command
    1174     // FIXME: shouldn't have to cast this
    1175     iov[0].iov_base = (char *)command;
    1176     iov[0].iov_len = strlen(command);
    1177     // Data
    1178     // FIXME: shouldn't have to cast this
    1179     iov[1].iov_base = (char *)data;
    1180     iov[1].iov_len = dlen;
    1181     if (writev(1, iov, numRecords) < 0) {
    1182         ERROR("write failed: %s", strerror(errno));
    1183     }
    1184     delete [] iov;
    1185 }
    1186 
    1187 void
    1188 NanoVis::idle()
    1189 {
    1190     TRACE("Enter");
    1191 
    1192     glutSetWindow(renderWindow);
    1193 
    1194     processCommands();
    1195 
    1196     TRACE("Leave");
    1197873}
    1198874
     
    15391215    TRACE("Setting bgcolor to %g %g %g", color[0], color[1], color[2]);
    15401216    glClearColor(color[0], color[1], color[2], 1);
     1217}
     1218
     1219void
     1220NanoVis::removeVolume(Volume *volume)
     1221{
     1222    VolumeHashmap::iterator itr = volumeTable.find(volume->name());
     1223    if (itr != volumeTable.end()) {
     1224        volumeTable.erase(itr);
     1225    }
     1226    delete volume;
    15411227}
    15421228
     
    17941480        draw3dAxis();
    17951481    }
    1796     if (grid->isVisible()) {
    1797         grid->render();
    1798     }
     1482    grid->render();
    17991483    if ((licRenderer != NULL) && (licRenderer->active())) {
    18001484        licRenderer->render();
     
    18031487        velocityArrowsSlice->render();
    18041488    }
    1805     if (!flowTable.empty()) {
    1806         renderFlows();
    1807     }
     1489    renderFlows();
    18081490
    18091491    volRenderer->renderAll();
    18101492
    1811     TRACE("Render heightmaps");
    18121493    HeightMapHashmap::iterator itr;
    18131494    for (itr = heightMapTable.begin();
     
    18241505}
    18251506
    1826 void
    1827 NanoVis::processCommands()
    1828 {
    1829     flags &= ~REDRAW_PENDING;
    1830 
    1831     TRACE("Enter");
    1832 
    1833     int flags = fcntl(0, F_GETFL, 0);
    1834     fcntl(0, F_SETFL, flags & ~O_NONBLOCK);
    1835 
    1836     int status = TCL_OK;
    1837 
    1838     //  Read and execute as many commands as we can from stdin...
    1839     Tcl_DString cmdbuffer;
    1840     Tcl_DStringInit(&cmdbuffer);
    1841     int nCommands = 0;
    1842     bool isComplete = false;
    1843     while ((!feof(NanoVis::stdin)) && (status == TCL_OK)) {
    1844         //
    1845         //  Read the next command from the buffer.  First time through we
    1846         //  block here and wait if necessary until a command comes in.
    1847         //
    1848         //  BE CAREFUL: Read only one command, up to a newline.  The "volume
    1849         //  data follows" command needs to be able to read the data
    1850         //  immediately following the command, and we shouldn't consume it
    1851         //  here.
    1852         //
    1853         while (!feof(NanoVis::stdin)) {
    1854             int c = fgetc(NanoVis::stdin);
    1855             char ch;
    1856             if (c <= 0) {
    1857                 if (errno == EWOULDBLOCK) {
    1858                     break;
    1859                 }
    1860                 exitService(100);
    1861             }
    1862             ch = (char)c;
    1863             Tcl_DStringAppend(&cmdbuffer, &ch, 1);
    1864             if (ch == '\n') {
    1865                 isComplete = Tcl_CommandComplete(Tcl_DStringValue(&cmdbuffer));
    1866                 if (isComplete) {
    1867                     break;
    1868                 }
    1869             }
    1870         }
    1871         // no command? then we're done for now
    1872         if (Tcl_DStringLength(&cmdbuffer) == 0) {
    1873             break;
    1874         }
    1875         if (isComplete) {
    1876             // back to original flags during command evaluation...
    1877             fcntl(0, F_SETFL, flags & ~O_NONBLOCK);
    1878             status = executeCommand(interp, &cmdbuffer);
    1879             // non-blocking for next read -- we might not get anything
    1880             fcntl(0, F_SETFL, flags | O_NONBLOCK);
    1881             isComplete = false;
    1882             nCommands++;
    1883             CHECK_FRAMEBUFFER_STATUS();
    1884         }
    1885     }
    1886     fcntl(0, F_SETFL, flags);
    1887 
    1888     if (status != TCL_OK) {
    1889         char *msg;
    1890         char hdr[200];
    1891         int msgSize, hdrSize;
    1892         Tcl_Obj *objPtr;
    1893 
    1894         objPtr = Tcl_GetObjResult(interp);
    1895         msg = Tcl_GetStringFromObj(objPtr, &msgSize);
    1896         hdrSize = sprintf(hdr, "nv>viserror -type internal_error -bytes %d\n", msgSize);
    1897         {
    1898             struct iovec iov[2];
    1899 
    1900             iov[0].iov_base = hdr;
    1901             iov[0].iov_len = hdrSize;
    1902             iov[1].iov_base = msg;
    1903             iov[1].iov_len = msgSize;
    1904             if (writev(1, iov, 2) < 0) {
    1905                 ERROR("write failed: %s", strerror(errno));
    1906             }
    1907         }
    1908         TRACE("Leaving on ERROR");
    1909         return;
    1910     }
    1911     if (feof(NanoVis::stdin)) {
    1912         TRACE("Exiting server on EOF from client");
    1913         exitService(90);
    1914     }
    1915 
    1916     update();
    1917 
    1918     bindOffscreenBuffer();  //enable offscreen render
    1919     render();
    1920     readScreen();
    1921 
    1922     if (feof(NanoVis::stdin)) {
    1923         exitService(90);
    1924     }
    1925 
    1926     ppmWrite("nv>image -type image -bytes");
    1927 
    1928     TRACE("Leave");
    1929 }
    1930 
    1931 int
    1932 main(int argc, char **argv)
    1933 {
    1934     const char *path;
    1935     char *newPath;
    1936 
    1937     newPath = NULL;
    1938     path = NULL;
    1939     NanoVis::stdin = stdin;
    1940 
    1941     fprintf(stdout, "NanoVis %s (build %s)\n", NANOVIS_VERSION, SVN_VERSION);
    1942     fflush(stdout);
    1943 
    1944     openlog("nanovis", LOG_CONS | LOG_PERROR | LOG_PID, LOG_USER);
    1945     memset(&NanoVis::stats, 0, sizeof(NanoVis::Stats));
    1946     NanoVis::stats.pid = getpid();
    1947     gettimeofday(&NanoVis::stats.start, NULL);
    1948 
    1949     /* Initialize GLUT here so it can parse and remove GLUT-specific
    1950      * command-line options before we parse the command-line below. */
    1951     glutInit(&argc, argv);
    1952     glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
    1953     glutInitWindowSize(NanoVis::winWidth, NanoVis::winHeight);
    1954     glutInitWindowPosition(10, 10);
    1955     NanoVis::renderWindow = glutCreateWindow("nanovis");
    1956     glutIdleFunc(NanoVis::idle);
    1957 
    1958     glutDisplayFunc(NanoVis::render);
    1959     glutReshapeFunc(NanoVis::resizeOffscreenBuffer);
    1960 
    1961     while (1) {
    1962         static struct option long_options[] = {
    1963             {"infile",  required_argument, NULL, 0},
    1964             {"path",    required_argument, NULL, 2},
    1965             {"debug",   no_argument,       NULL, 3},
    1966             {"record",  required_argument, NULL, 4},
    1967             {0, 0, 0, 0}
    1968         };
    1969         int option_index = 0;
    1970         int c;
    1971 
    1972         c = getopt_long(argc, argv, ":dp:i:l:r:", long_options, &option_index);
    1973         if (c == -1) {
    1974             break;
    1975         }
    1976         switch (c) {
    1977         case '?':
    1978             fprintf(stderr, "unknown option -%c\n", optopt);
    1979             return 1;
    1980         case ':':
    1981             if (optopt < 4) {
    1982                 fprintf(stderr, "argument missing for --%s option\n",
    1983                         long_options[optopt].name);
    1984             } else {
    1985                 fprintf(stderr, "argument missing for -%c option\n", optopt);
    1986             }
    1987             return 1;
    1988         case 2:
    1989         case 'p':
    1990             path = optarg;
    1991             break;
    1992         case 3:
    1993         case 'd':
    1994             NanoVis::debugFlag = true;
    1995             break;
    1996         case 0:
    1997         case 'i':
    1998             NanoVis::stdin = fopen(optarg, "r");
    1999             if (NanoVis::stdin == NULL) {
    2000                 perror(optarg);
    2001                 return 2;
    2002             }
    2003             break;
    2004         case 4:
    2005         case 'r':
    2006             Tcl_DString ds;
    2007             char buf[200];
    2008 
    2009             Tcl_DStringInit(&ds);
    2010             Tcl_DStringAppend(&ds, optarg, -1);
    2011             sprintf(buf, ".%d", getpid());
    2012             Tcl_DStringAppend(&ds, buf, -1);
    2013             NanoVis::recfile = fopen(Tcl_DStringValue(&ds), "w");
    2014             if (NanoVis::recfile == NULL) {
    2015                 perror(optarg);
    2016                 return 2;
    2017             }
    2018             break;
    2019         default:
    2020             fprintf(stderr,"unknown option '%c'.\n", c);
    2021             return 1;
    2022         }
    2023     }     
    2024     if (path == NULL) {
    2025         char *p;
    2026 
    2027         // See if we can derive the path from the location of the program.
    2028         // Assume program is in the form <path>/bin/nanovis.
    2029         path = argv[0];
    2030         p = strrchr((char *)path, '/');
    2031         if (p != NULL) {
    2032             *p = '\0';
    2033             p = strrchr((char *)path, '/');
    2034         }
    2035         if (p == NULL) {
    2036             TRACE("path not specified");
    2037             return 1;
    2038         }
    2039         *p = '\0';
    2040         newPath = new char[(strlen(path) + 15) * 2 + 1];
    2041         sprintf(newPath, "%s/lib/shaders:%s/lib/resources", path, path);
    2042         path = newPath;
    2043     }
    2044 
    2045     FilePath::getInstance()->setWorkingDirectory(argc, (const char**) argv);
    2046 
    2047 #ifdef notdef
    2048     signal(SIGPIPE, SIG_IGN);
    2049 #endif
    2050     initService();
    2051 
    2052     NanoVis::init(path);
    2053     if (newPath != NULL) {
    2054         delete [] newPath;
    2055     }
    2056     NanoVis::initGL();
    2057 
    2058     NanoVis::interp = initTcl();
    2059 
    2060     NanoVis::resizeOffscreenBuffer(NanoVis::winWidth, NanoVis::winHeight);
    2061 
    2062     glutMainLoop();
    2063 
    2064     exitService(80);
    2065 }
    2066 
    2067 void
    2068 NanoVis::removeVolume(Volume *volume)
    2069 {
    2070     VolumeHashmap::iterator itr = volumeTable.find(volume->name());
    2071     if (itr != volumeTable.end()) {
    2072         volumeTable.erase(itr);
    2073     }
    2074     delete volume;
    2075 }
  • nanovis/branches/1.1/nanovis.h

    r4820 r4874  
    1414 * ======================================================================
    1515 */
    16 #ifndef NANOVIS_H
    17 #define NANOVIS_H
    18 
    19 #include <tcl.h>
    20 #include <md5.h>
    21 #include <GL/glew.h>
    22 #include <sys/types.h> // For pid_t
    23 #include <sys/time.h>  // For struct timeval
     16#ifndef NV_NANOVIS_H
     17#define NV_NANOVIS_H
    2418
    2519#include <math.h>
    2620#include <stddef.h> // For size_t
    2721#include <stdio.h>
     22#include <sys/time.h>  // For struct timeval
     23#include <sys/types.h> // For pid_t
     24
     25#include <tcl.h>
     26
     27#include <GL/glew.h>
    2828
    2929#include <vector>
     
    3434
    3535#include "config.h"
    36 
    37 #define NANOVIS_VERSION         "1.1.3"
    3836
    3937//defines for the image based flow visualization
     
    5048}
    5149
    52 class VolumeRenderer;
    53 class PointSetRenderer;
     50class NvCamera;
     51class Flow;
     52class Grid;
     53class HeightMap;
     54class NvLIC;
    5455class NvParticleRenderer;
    5556class PlaneRenderer;
     57class Texture2D;
     58class TransferFunction;
    5659class VelocityArrowsSlice;
    57 class NvLIC;
    58 class PointSet;
    59 class Texture2D;
    60 class HeightMap;
    61 class Grid;
    62 class NvCamera;
    63 class TransferFunction;
    6460class Volume;
    65 class Flow;
     61class VolumeRenderer;
    6662
    6763class NanoVis
     
    8278    };
    8379
    84     typedef struct {
    85         pid_t pid;
    86         size_t nFrames;            /**< # of frames sent to client. */
    87         size_t nBytes;             /**< # of bytes for all frames. */
    88         size_t nCommands;          /**< # of commands executed */
    89         double cmdTime;            /**< Elasped time spend executing
    90                                     * commands. */
    91         struct timeval start;      /**< Start of elapsed time. */
    92     } Stats;
    93 
    9480    typedef std::string TransferFunctionId;
    9581    typedef std::string VolumeId;
     
    10187    typedef std::tr1::unordered_map<HeightMapId, HeightMap *> HeightMapHashmap;
    10288
    103     static void processCommands();
    104     static void init(const char *path);
    105     static void initGL();
    106     static void initOffscreenBuffer();
    107     static void resizeOffscreenBuffer(int w, int h);
     89    static bool init(const char *path);
     90    static bool initGL();
     91    static bool initOffscreenBuffer();
     92    static bool resizeOffscreenBuffer(int w, int h);
    10893    static void setBgColor(float color[3]);
    10994    static void render();
    11095    static void draw3dAxis();
    111     static void idle();
    11296    static void update();
    11397    static void removeAllData();
     
    123107    static void eventuallyRedraw(unsigned int flag = 0);
    124108
    125     static void setVolumeRanges();
    126     static void setHeightmapRanges();
    127 
    128 #ifdef KEEPSTATS
    129     static int getStatsFile(Tcl_Obj *objPtr);
    130     static int writeToStatsFile(int f, const char *s, size_t length);
    131 #endif
    132109    static void ppmWrite(const char *prefix);
    133     static void sendDataToClient(const char *command, const char *data,
    134                                  size_t dlen);
    135110    static void bmpWrite(const char *prefix);
    136111    static void bmpWriteToFile(int frame_number, const char* directory_name);
     
    151126    static void readScreen()
    152127    {
     128        //glPixelStorei(GL_PACK_ALIGNMENT, 1);
    153129        glReadPixels(0, 0, winWidth, winHeight, GL_RGB, GL_UNSIGNED_BYTE,
    154130                     screenBuffer);
     
    159135    }
    160136
     137    static void setVolumeRanges();
     138    static void setHeightmapRanges();
     139
    161140    static Flow *getFlow(const char *name);
    162141    static Flow *createFlow(Tcl_Interp *interp, const char *name);
     142    static void deleteFlows(Tcl_Interp *interp);
    163143    static void deleteFlow(const char *name);
    164     static void deleteFlows(Tcl_Interp *interp);
    165144    static bool mapFlows();
    166145    static void getFlowBounds(vrmath::Vector3f& min,
     
    172151    static void advectFlows();
    173152
    174     static FILE *stdin, *logfile, *recfile;
    175     static Stats stats;
    176     static int statsFile;
     153    static Tcl_Interp *interp;
     154
    177155    static unsigned int flags;
    178156    static bool debugFlag;
     
    181159    static int winWidth;        ///< Width of the render window
    182160    static int winHeight;       ///< Height of the render window
    183     static int renderWindow;    //< GLUT handle for the render window
     161    static int renderWindow;    ///< GLUT handle for the render window
    184162    static unsigned char *screenBuffer;
    185163    static Texture2D *legendTexture;
    186     static Grid *grid;
    187164    static nv::util::Fonts *fonts;
    188165    static int updir;
     
    203180    static NvLIC *licRenderer;
    204181    static PlaneRenderer *planeRenderer;
    205 
    206     static Tcl_Interp *interp;
     182    static Grid *grid;
    207183
    208184private:
Note: See TracChangeset for help on using the changeset viewer.