Changeset 3605
- Timestamp:
- Apr 2, 2013, 1:31:30 PM (12 years ago)
- Location:
- trunk/packages/vizservers/nanovis
- Files:
-
- 12 added
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/packages/vizservers/nanovis/Command.cpp
r3597 r3605 45 45 #include <vrmath/Vector3f.h> 46 46 47 #include "nanovisServer.h" 47 48 #include "nanovis.h" 49 #include "ReadBuffer.h" 50 #ifdef USE_THREADS 51 #include "ResponseQueue.h" 52 #endif 53 #include "Command.h" 48 54 #include "CmdProc.h" 49 55 #include "FlowCmd.h" 50 #include "Trace.h"51 #ifdef USE_POINTSET_RENDERER52 #include "PointSet.h"53 #endif54 56 #include "dxReader.h" 55 57 #include "VtkReader.h" 58 #include "BMPWriter.h" 59 #include "PPMWriter.h" 56 60 #include "Grid.h" 57 61 #include "HeightMap.h" 58 62 #include "NvCamera.h" 59 63 #include "NvZincBlendeReconstructor.h" 64 #include "OrientationIndicator.h" 60 65 #include "Unirect.h" 61 66 #include "Volume.h" 62 67 #include "VolumeRenderer.h" 63 68 #include "Trace.h" 69 70 using namespace nv; 64 71 using namespace nv::graphics; 65 72 using namespace vrmath; … … 102 109 }"; 103 110 111 static int lastCmdStatus; 112 113 #ifdef USE_THREADS 114 void 115 nv::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 125 ssize_t 126 nv::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 143 bool 144 nv::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 152 bool 153 nv::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 161 static int 162 ExecuteCommand(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 104 186 bool 105 187 GetBooleanFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, bool *boolPtr) … … 276 358 * TCL_ERROR to indicate an error. 277 359 */ 278 staticint360 int 279 361 GetVolumeFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Volume **volPtrPtr) 280 362 { … … 454 536 GetDataStream(Tcl_Interp *interp, Rappture::Buffer &buf, int nBytes) 455 537 { 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; 486 540 } 487 541 Rappture::Outcome err; … … 621 675 Tcl_Obj *const *objv) 622 676 { 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(); 633 686 NanoVis::render(); 634 687 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); 638 696 639 697 return TCL_OK; … … 753 811 static int 754 812 ClientInfoCmd(ClientData clientData, Tcl_Interp *interp, int objc, 755 Tcl_Obj *const *objv)813 Tcl_Obj *const *objv) 756 814 { 757 815 Tcl_DString ds; … … 769 827 } 770 828 #ifdef KEEPSTATS 771 int f;772 773 829 /* Use the initial client key value pairs as the parts for a generating 774 830 * a unique file name. */ 775 f = NanoVis::getStatsFile(objv[1]);831 int f = nv::getStatsFile(interp, objv[1]); 776 832 if (f < 0) { 777 833 Tcl_AppendResult(interp, "can't open stats file: ", … … 809 865 /* date */ 810 866 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)); 812 868 buf[strlen(buf) - 1] = '\0'; 813 869 Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewStringObj(buf, -1)); … … 816 872 Tcl_NewStringObj("date_secs", 9)); 817 873 Tcl_ListObjAppendElement(interp, listObjPtr, 818 Tcl_NewLongObj( NanoVis::startTime.tv_sec));874 Tcl_NewLongObj(nv::g_stats.start.tv_sec)); 819 875 /* Client arguments. */ 820 876 if (Tcl_ListObjGetElements(interp, objv[1], &numItems, &items) != TCL_OK) { … … 829 885 Tcl_DStringAppend(&ds, "\n", 1); 830 886 #ifdef KEEPSTATS 831 result = NanoVis::writeToStatsFile(f, Tcl_DStringValue(&ds),832 887 result = nv::writeToStatsFile(f, Tcl_DStringValue(&ds), 888 Tcl_DStringLength(&ds)); 833 889 #else 834 890 TRACE("clientinfo: %s", Tcl_DStringValue(&ds)); … … 860 916 } 861 917 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); 865 920 if (tf == NULL) { 866 Tcl_AppendResult(interp, "unknown transfer function \"", name, "\"",921 Tcl_AppendResult(interp, "unknown transfer function \"", tfName, "\"", 867 922 (char*)NULL); 868 923 return TCL_ERROR; … … 876 931 NanoVis::setVolumeRanges(); 877 932 } 878 NanoVis::renderLegend(tf, Volume::valueMin, Volume::valueMax, w, h, name);933 NanoVis::renderLegend(tf, Volume::valueMin, Volume::valueMax, w, h, tfName); 879 934 return TCL_OK; 880 935 } … … 1080 1135 return TCL_ERROR; 1081 1136 } 1082 VolumeInterpolator * interpolator;1083 interpolator =NanoVis::volRenderer->getVolumeInterpolator();1137 VolumeInterpolator *interpolator = 1138 NanoVis::volRenderer->getVolumeInterpolator(); 1084 1139 interpolator->start(); 1085 1140 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) { 1088 1143 float fraction; 1089 1144 1090 fraction = ((float)frame _num) / (total - 1);1145 fraction = ((float)frameNum) / (total - 1); 1091 1146 TRACE("fraction : %f", fraction); 1092 //interpolator->update(((float)frame_num) / (total - 1));1093 1147 interpolator->update(fraction); 1094 1148 … … 1103 1157 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboOrig); 1104 1158 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); 1106 1165 } 1107 1166 } … … 1185 1244 } 1186 1245 const char *tag = Tcl_GetString(objv[4]); 1187 Rappture::Buffer buf; 1246 1247 Rappture::Buffer buf(nbytes); 1188 1248 if (GetDataStream(interp, buf, nbytes) != TCL_OK) { 1189 1249 return TCL_ERROR; 1190 1250 } 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(); 1196 1253 1197 1254 TRACE("Checking header[%.20s]", bytes); … … 1201 1258 if ((nBytes > 5) && (strncmp(bytes, "<HDR>", 5) == 0)) { 1202 1259 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)); 1208 1261 if (volume == NULL) { 1209 1262 Tcl_AppendResult(interp, "can't get volume instance", (char *)NULL); … … 1267 1320 volume->visible(true); 1268 1321 1269 char info[1024];1270 ssize_t nWritten;1271 1272 1322 if (Volume::updatePending) { 1273 1323 NanoVis::setVolumeRanges(); 1274 1324 } 1275 1325 1326 char info[1024]; 1276 1327 // 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 1283 1343 return TCL_OK; 1284 1344 } … … 1304 1364 1305 1365 static Rappture::CmdSpec volumeDataOps[] = { 1306 {"follows", 1, VolumeDataFollowsOp, 5, 5, " sizetag",},1366 {"follows", 1, VolumeDataFollowsOp, 5, 5, "nbytes tag",}, 1307 1367 {"state", 1, VolumeDataStateOp, 4, 0, "bool ?indices?",}, 1308 1368 }; … … 1407 1467 } 1408 1468 1409 1410 1469 static Rappture::CmdSpec volumeOutlineOps[] = { 1411 1470 {"color", 1, VolumeOutlineColorOp, 6, 0, "r g b ?indices?",}, … … 1596 1655 tf->name()); 1597 1656 (*iter)->transferFunction(tf); 1598 #ifdef USE_POINTSET_RENDERER1599 // TBD..1600 if ((*iter)->pointsetIndex != -1) {1601 NanoVis::pointSet[(*iter)->pointsetIndex]->updateColor(tf->getData(), 256);1602 }1603 #endif1604 1657 } 1605 1658 return TCL_OK; … … 1656 1709 {"delete", 2, VolumeDeleteOp, 3, 0, "?name...?",}, 1657 1710 {"exists", 1, VolumeExistsOp, 3, 3, "name",}, 1658 {"names", 1, VolumeNamesOp, 2, 3, "?pattern?",},1711 {"names", 1, VolumeNamesOp, 2, 2, "",}, 1659 1712 {"outline", 1, VolumeOutlineOp, 3, 0, "oper ?args?",}, 1660 1713 {"shading", 2, VolumeShadingOp, 3, 0, "oper ?args?",}, … … 1663 1716 static int nVolumeOps = NumCmdSpecs(volumeOps); 1664 1717 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 */1680 1718 static int 1681 1719 VolumeCmd(ClientData clientData, Tcl_Interp *interp, int objc, … … 1702 1740 const char *tag = Tcl_GetString(objv[4]); 1703 1741 1704 Rappture::Buffer buf ;1742 Rappture::Buffer buf(nBytes); 1705 1743 if (GetDataStream(interp, buf, nBytes) != TCL_OK) { 1706 1744 return TCL_ERROR; … … 1761 1799 1762 1800 static 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...?",}, 1765 1803 }; 1766 1804 static int nHeightMapDataOps = NumCmdSpecs(heightMapDataOps); … … 1822 1860 1823 1861 static 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...?",}, 1826 1864 }; 1827 1865 static int nHeightMapLineContourOps = NumCmdSpecs(heightMapLineContourOps); … … 1956 1994 } 1957 1995 1958 1959 1996 static int 1960 1997 HeightMapOpacityOp(ClientData clientData, Tcl_Interp *interp, int objc, … … 1978 2015 1979 2016 static Rappture::CmdSpec heightMapOps[] = { 1980 {"create", 2, HeightMapCreateOp, 10, 10, " tagxmin ymin xmax ymax xnum ynum values",},2017 {"create", 2, HeightMapCreateOp, 10, 10, "heightmapName xmin ymin xmax ymax xnum ynum values",}, 1981 2018 {"cull", 2, HeightMapCullOp, 3, 3, "mode",}, 1982 2019 {"data", 1, HeightMapDataOp, 3, 0, "oper ?args?",}, 1983 {"legend", 2, HeightMapLegendOp, 5, 5, " indexwidth height",},2020 {"legend", 2, HeightMapLegendOp, 5, 5, "heightmapName width height",}, 1984 2021 {"linecontour", 2, HeightMapLineContourOp, 2, 0, "oper ?args?",}, 1985 {"opacity", 1, HeightMapOpacityOp, 3, 0, "value ?heightmap ...? ",},2022 {"opacity", 1, HeightMapOpacityOp, 3, 0, "value ?heightmapNames...? ",}, 1986 2023 {"polygon", 1, HeightMapPolygonOp, 3, 3, "mode",}, 1987 2024 {"shading", 1, HeightMapShadingOp, 3, 3, "model",}, 1988 {"transfunc", 2, HeightMapTransFuncOp, 3, 0, "name ?heightmap ...?",},2025 {"transfunc", 2, HeightMapTransFuncOp, 3, 0, "name ?heightmapNames...?",}, 1989 2026 }; 1990 2027 static int nHeightMapOps = NumCmdSpecs(heightMapOps); … … 2118 2155 return TCL_ERROR; 2119 2156 } 2120 NanoVis:: axisOn = visible;2157 NanoVis::orientationIndicator->setVisible(visible); 2121 2158 } else { 2122 2159 Tcl_AppendResult(interp, "bad axis option \"", string, … … 2127 2164 } 2128 2165 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. 2166 static int 2167 ImageFlushCmd(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. 2139 2185 */ 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. 2186 int 2187 nv::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 2159 2254 */ 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() 2255 int 2256 nv::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 2305 void 2306 nv::initTcl(Tcl_Interp *interp, ClientData clientData) 2172 2307 { 2173 2308 /* … … 2178 2313 * a test harness through the interpreter for nanovis. 2179 2314 */ 2180 Tcl_Interp *interp; 2181 interp = Tcl_CreateInterp(); 2182 /* 2315 2183 2316 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); 2202 2332 2203 2333 // create a default transfer function … … 2206 2336 Tcl_GetStringResult(interp)); 2207 2337 } 2208 return interp; 2209 } 2338 } -
trunk/packages/vizservers/nanovis/Command.h
r3597 r3605 14 14 #include <tcl.h> 15 15 16 #include <RpBuffer.h> 17 18 #include "ResponseQueue.h" 19 16 20 namespace Rappture { 17 21 class Buffer; … … 19 23 class Volume; 20 24 25 namespace nv { 26 class ReadBuffer; 27 28 #ifdef USE_THREADS 29 extern void queueResponse(const void *bytes, size_t len, 30 Response::AllocationType allocType, 31 Response::ResponseType type = Response::DATA); 32 #else 33 extern ssize_t SocketWrite(const void *bytes, size_t len); 34 #endif 35 36 extern bool SocketRead(char *bytes, size_t len); 37 38 extern bool SocketRead(Rappture::Buffer &buf, size_t len); 39 40 extern int processCommands(Tcl_Interp *interp, 41 ReadBuffer *inBufPtr, 42 int fdOut); 43 44 extern int handleError(Tcl_Interp *interp, 45 int status, 46 int fdOut); 47 48 extern void initTcl(Tcl_Interp *interp, ClientData clientData); 49 } 50 21 51 extern int GetAxisFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, 22 52 int *axisVal); 23 53 24 extern intGetBooleanFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,54 extern bool GetBooleanFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, 25 55 bool *boolVal); 26 56 … … 33 63 Volume **volume); 34 64 35 extern Tcl_Interp *initTcl();36 37 65 #endif -
trunk/packages/vizservers/nanovis/FlowCmd.cpp
r3598 r3605 25 25 #include "nvconf.h" 26 26 27 #include "nanovisServer.h" 27 28 #include "nanovis.h" 28 29 #include "CmdProc.h" 29 30 #include "Command.h" 31 #include "PPMWriter.h" 30 32 #include "FlowCmd.h" 31 33 #include "FlowTypes.h" … … 41 43 #include "Trace.h" 42 44 45 using namespace nv; 43 46 using namespace vrmath; 44 47 … … 231 234 return TCL_ERROR; 232 235 } 233 Rappture::Buffer buf ;236 Rappture::Buffer buf(nBytes); 234 237 TRACE("Flow data loading bytes: %d components: %d", nBytes, nComponents); 235 238 if (GetDataStream(interp, buf, nBytes) != TCL_OK) { 236 239 return TCL_ERROR; 237 240 } 241 char *bytes = (char *)buf.bytes(); 242 size_t length = buf.size(); 243 238 244 Rappture::Unirect3d *dataPtr; 239 245 dataPtr = new Rappture::Unirect3d(nComponents); 240 246 241 247 Flow *flow = (Flow *)clientData; 242 size_t length = buf.size();243 char *bytes = (char *)buf.bytes();244 248 if ((length > 4) && (strncmp(bytes, "<DX>", 4) == 0)) { 245 249 if (!dataPtr->importDx(result, nComponents, length - 4, bytes + 4)) { … … 292 296 { 293 297 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 301 308 } 302 309 NanoVis::eventuallyRedraw(NanoVis::MAP_FLOWS); … … 1064 1071 1065 1072 static 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 header1078 char header[200];1079 #define PPM_MAXVAL 2551080 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 int1118 1073 MakeImageFiles(Tcl_Interp *interp, char *tmpFileName, 1119 1074 FlowVideoSwitches *switchesPtr, bool *cancelPtr) 1120 1075 { 1121 1076 struct pollfd pollResults; 1122 pollResults.fd = fileno( NanoVis::stdin);1077 pollResults.fd = fileno(nv::g_fIn); 1123 1078 pollResults.events = POLLIN; 1124 1079 #define PENDING_TIMEOUT 10 /* milliseconds. */ … … 1160 1115 1161 1116 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); 1163 1119 if (result != TCL_OK) { 1164 1120 break; … … 1230 1186 sprintf(cmd,"nv>image -type movie -token \"%s\" -bytes %lu\n", 1231 1187 token, (unsigned long)data.size()); 1232 NanoVis::sendDataToClient(cmd, data.bytes(), data.size());1188 nv::sendDataToClient(cmd, data.bytes(), data.size()); 1233 1189 return TCL_OK; 1234 1190 } … … 1292 1248 sprintf(tmpFileName + length, "/image%d.ppm", i); 1293 1249 unlink(tmpFileName); 1294 } 1250 } 1295 1251 tmpFileName[length] = '\0'; 1296 1252 rmdir(tmpFileName); … … 1343 1299 * associative array. 1344 1300 */ 1345 int 1346 FlowCmdInitProc(Tcl_Interp *interp) 1347 { 1348 Tcl_CreateObjCommand(interp, "flow", FlowCmdProc, NULL, NULL); 1349 return TCL_OK; 1350 } 1301 void 1302 FlowCmdInitProc(Tcl_Interp *interp, ClientData clientData) 1303 { 1304 Tcl_CreateObjCommand(interp, "flow", FlowCmdProc, clientData, NULL); 1305 } -
trunk/packages/vizservers/nanovis/FlowCmd.h
r3597 r3605 27 27 #include <tcl.h> 28 28 29 extern Tcl_AppInitProc FlowCmdInitProc; 29 extern void FlowCmdInitProc(Tcl_Interp *interp, ClientData clientData); 30 30 31 extern Tcl_ObjCmdProc FlowInstObjCmd; 31 32 extern Tcl_CmdDeleteProc FlowInstDeleteProc; -
trunk/packages/vizservers/nanovis/Grid.cpp
r3502 r3605 36 36 void Grid::render() 37 37 { 38 if (!isVisible()) 39 return; 40 38 41 glPushAttrib(GL_ENABLE_BIT); 39 42 -
trunk/packages/vizservers/nanovis/HeightMap.cpp
r3597 r3605 57 57 HeightMap::render(RenderContext *renderContext) 58 58 { 59 if (!isVisible()) 60 return; 61 59 62 glPushAttrib(GL_ENABLE_BIT | GL_POLYGON_BIT | GL_LIGHTING_BIT); 60 63 -
trunk/packages/vizservers/nanovis/Makefile.in
r3598 r3605 1 TRACE = #yes 1 TRACE = #yes 2 USE_THREADS = yes 3 USE_POINTSET_RENDERER = #yes 2 4 3 5 SHELL = /bin/sh … … 23 25 INSTALL_SCRIPT = ${INSTALL} -m 0444 24 26 RM = rm -f 25 26 AUXSRC = config.h define.h27 27 28 28 CG_INC_SPEC = @CG_INC_SPEC@ … … 89 89 $(RP_INC_SPEC) 90 90 91 USE_POINTSET_RENDERER = #yes92 93 91 CC = @CC@ 94 92 CXX = @CXX@ … … 99 97 DEFINES += -DWANT_TRACE 100 98 endif 99 ifdef USE_THREADS 100 DEFINES += -DUSE_THREADS 101 endif 101 102 ifdef USE_POINTSET_RENDERER 102 103 DEFINES += -DUSE_POINTSET_RENDERER … … 106 107 OBJS = \ 107 108 Axis.o \ 109 BMPWriter.o \ 108 110 Chain.o \ 109 111 CmdProc.o \ … … 129 131 NvZincBlendeReconstructor.o \ 130 132 NvZincBlendeVolumeShader.o \ 133 OrientationIndicator.o \ 131 134 PerfQuery.o \ 132 135 Plane.o \ 133 136 PlaneRenderer.o \ 137 PPMWriter.o \ 138 ReadBuffer.o \ 134 139 ReaderCommon.o \ 135 140 RenderVertexArray.o \ 141 ResponseQueue.o \ 136 142 Switch.o \ 137 143 Texture1D.o \ … … 148 154 ZincBlendeVolume.o \ 149 155 dxReader.o \ 156 md5.o \ 150 157 nanovis.o \ 151 md5.o158 nanovisServer.o 152 159 153 160 resources = \ … … 270 277 271 278 Axis.o: Axis.cpp Axis.h Chain.h 279 BMPWriter.o: BMPWriter.cpp nanovis.h 272 280 BucketSort.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 273 281 Chain.o: Chain.cpp Chain.h 274 282 CmdProc.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.h283 Command.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 276 284 ContourLineFilter.o: ContourLineFilter.cpp ContourLineFilter.h 277 285 ConvexPolygon.o: ConvexPolygon.cpp ConvexPolygon.h $(VRMATH_DIR)/include/vrmath/Vector4f.h $(VRMATH_DIR)/include/vrmath/Matrix4x4d.h Plane.h 278 286 Flow.o: Flow.cpp Flow.h FlowCmd.h FlowTypes.h FlowBox.h FlowParticles.h Switch.h Trace.h 279 287 FlowBox.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.h288 FlowCmd.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 281 289 FlowParticles.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 282 290 GradientFilter.o: GradientFilter.cpp GradientFilter.h … … 294 302 NvZincBlendeReconstructor.o: NvZincBlendeReconstructor.cpp NvZincBlendeReconstructor.h ZincBlendeVolume.h Volume.h $(VRMATH_DIR)/include/vrmath/Vector3f.h 295 303 NvZincBlendeVolumeShader.o: NvZincBlendeVolumeShader.cpp NvZincBlendeVolumeShader.h NvVolumeShader.h NvShader.h 304 OrientationIndicator.o: OrientationIndicator.cpp OrientationIndicator.h 296 305 ParticleEmitter.o: ParticleEmitter.cpp ParticleEmitter.h 297 306 ParticleSystem.o: ParticleSystem.cpp ParticleSystem.h DataLoader.h … … 304 313 PointSetRenderer.o: PointSetRenderer.cpp PointSetRenderer.h 305 314 PointShader.o: PointShader.cpp PointShader.h 315 PPMWriter.o: PPMWriter.cpp PPMWriter.h 306 316 ReaderCommon.o: ReaderCommon.cpp ReaderCommon.h GradientFilter.h $(VRMATH_DIR)/include/vrmath/Vector3f.h 307 317 RenderVertexArray.o: RenderVertexArray.cpp RenderVertexArray.h 308 318 Switch.o: Switch.cpp Switch.h 309 319 Texture1D.o: Texture1D.cpp Texture1D.h 310 Texture2D.o: Texture2D.cpp Texture2D.h $(AUXSRC)311 Texture3D.o: Texture3D.cpp Texture3D.h $(AUXSRC)320 Texture2D.o: Texture2D.cpp Texture2D.h config.h define.h 321 Texture3D.o: Texture3D.cpp Texture3D.h config.h define.h 312 322 Trace.o: Trace.cpp Trace.h 313 323 TransferFunction.o: TransferFunction.cpp 314 324 Unirect.o: Unirect.cpp Unirect.h Command.h Trace.h 315 325 VelocityArrowsSlice.o: VelocityArrowsSlice.cpp VelocityArrowsSlice.h 316 Volume.o: Volume.cpp Volume.h $(AUXSRC)326 Volume.o: Volume.cpp Volume.h config.h define.h 317 327 VolumeInterpolator.o: VolumeInterpolator.cpp VolumeInterpolator.h Volume.h 318 328 VolumeRenderer.o: VolumeRenderer.cpp VolumeRenderer.h 319 329 VtkReader.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)330 ZincBlendeVolume.o: ZincBlendeVolume.cpp ZincBlendeVolume.h config.h define.h 321 331 dxReader.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.h323 332 md5.o: md5.h 333 nanovis.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 334 nanovisServer.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 10 10 #include <string.h> 11 11 12 #include <string> 13 #include <sstream> 14 12 15 #include <GL/glew.h> 13 16 … … 15 18 #include "Trace.h" 16 19 20 using namespace nv; 21 22 static std::ostringstream g_UserErrorString; 23 17 24 #define MSG_LEN 2047 18 25 26 /** 27 * \brief Open syslog for writing 28 */ 29 void 30 nv::initLog() 31 { 32 openlog("nanovis", LOG_CONS | LOG_PERROR | LOG_PID, LOG_USER); 33 } 34 35 /** 36 * \brief Close syslog 37 */ 38 void 39 nv::closeLog() 40 { 41 closelog(); 42 } 43 44 /** 45 * \brief Write a message to syslog 46 */ 19 47 void 20 LogMessage(int priority, const char *funcname,21 const char *path, int lineNum, const char* fmt, ...)48 nv::LogMessage(int priority, const char *funcname, 49 const char *path, int lineNum, const char* fmt, ...) 22 50 { 23 51 char message[MSG_LEN+1]; … … 42 70 43 71 syslog(priority, "%s", message); 72 } 73 74 /** 75 * \brief Write a user message to buffer 76 */ 77 void 78 nv::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 92 const char * 93 nv::getUserMessages() 94 { 95 return g_UserErrorString.str().c_str(); 96 } 97 98 void 99 nv::clearUserMessages() 100 { 101 g_UserErrorString.str(std::string()); 44 102 } 45 103 … … 116 174 return false; 117 175 } 118 119 -
trunk/packages/vizservers/nanovis/Trace.h
r3597 r3605 18 18 #define AT __FILE__ ":" NEWSTRING(__LINE__) 19 19 20 namespace nv { 21 22 extern void logUserMessage(const char* format, ...); 23 24 extern const char *getUserMessages(); 25 26 extern void clearUserMessages(); 27 28 extern void initLog(); 29 30 extern void closeLog(); 31 20 32 extern void LogMessage(int priority, const char *funcname, const char *fileName, 21 33 int lineNum, const char* format, ...); 22 34 23 #define ERROR(...) LogMessage(LOG_ERR, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)35 #define ERROR(...) nv::LogMessage(LOG_ERR, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__) 24 36 #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__) 26 38 #else 27 39 #define TRACE(...) 28 40 #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 } 31 47 32 48 extern bool CheckFBO(GLenum *status); 33 49 extern void PrintFBOStatus(GLenum status, const char *prefix); 34 50 extern bool CheckGL(const char *prefix); 51 35 52 #endif -
trunk/packages/vizservers/nanovis/Unirect.cpp
r3597 r3605 45 45 Rappture::Unirect2d::parseBuffer(Tcl_Interp *interp, Rappture::Buffer &buf) 46 46 { 47 Tcl_Obj *objPtr; 48 objPtr = Tcl_NewStringObj(buf.bytes(), buf.size()); 47 Tcl_Obj *objPtr = Tcl_NewStringObj(buf.bytes(), buf.size()); 49 48 Tcl_Obj **objv; 50 49 int objc; … … 52 51 return TCL_ERROR; 53 52 } 54 int result; 55 result = loadData(interp, objc, objv); 53 int result = loadData(interp, objc, objv); 56 54 Tcl_DecrRefCount(objPtr); 57 55 if ((result != TCL_OK) || (!isInitialized())) { -
trunk/packages/vizservers/nanovis/Unirect.h
r3502 r3605 9 9 10 10 #include <float.h> 11 12 #include <tcl.h> 11 13 12 14 #include <rappture.h> -
trunk/packages/vizservers/nanovis/dxReader.cpp
r3597 r3605 43 43 #include "ZincBlendeVolume.h" 44 44 #include "NvZincBlendeReconstructor.h" 45 #ifdef USE_POINTSET_RENDERER46 #include "PointSet.h"47 #endif48 45 49 46 /** … … 488 485 volume->updatePending = true; 489 486 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 #endif499 487 delete [] data; 500 488 -
trunk/packages/vizservers/nanovis/nanovis.cpp
r3597 r3605 16 16 */ 17 17 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>26 18 #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> 34 20 #include <cstdio> 35 #include <cstring>36 #include <cmath>37 38 #include <iostream>39 #include <fstream>40 #include <sstream>41 #include <string>42 21 43 22 #include <GL/glew.h> 44 23 #include <GL/glut.h> 45 24 46 #include <RpEncode.h>47 48 25 #include <graphics/RenderContext.h> 49 26 #include <vrmath/Vector3f.h> … … 57 34 #include "config.h" 58 35 #include "nanovis.h" 36 #include "nanovisServer.h" 59 37 #include "define.h" 60 38 61 #include "Command.h"62 39 #include "Flow.h" 63 40 #include "Grid.h" 64 41 #include "HeightMap.h" 65 42 #include "NvCamera.h" 43 #include "NvLIC.h" 66 44 #include "NvShader.h" 67 #include "NvLIC.h" 68 #include "NvZincBlendeReconstructor.h" 45 #include "OrientationIndicator.h" 69 46 #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" 75 49 #include "Trace.h" 50 #include "TransferFunction.h" 76 51 #include "Unirect.h" 77 52 #include "VelocityArrowsSlice.h" 53 #include "Volume.h" 78 54 #include "VolumeInterpolator.h" 79 55 #include "VolumeRenderer.h" 80 #include "ZincBlendeVolume.h" 81 56 57 using namespace nv; 82 58 using namespace nv::graphics; 83 59 using namespace nv::util; 84 60 using namespace vrmath; 85 61 86 #define SIZEOF_BMP_HEADER 5487 88 #define CVT2SECS(x) ((double)(x).tv_sec) + ((double)(x).tv_usec * 1.0e-6)89 90 #define TRUE 191 #define FALSE 092 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 executing99 * commands. */100 struct timeval start; /**< Start of elapsed time. */101 } Stats;102 103 static Stats stats;104 105 62 // STATIC MEMBER DATA 106 63 107 FILE *NanoVis::stdin = NULL; 108 FILE *NanoVis::logfile = NULL; 109 FILE *NanoVis::recfile = NULL; 110 111 int NanoVis::statsFile = -1; 64 Tcl_Interp *NanoVis::interp = NULL; 112 65 113 66 unsigned int NanoVis::flags = 0; 114 67 bool NanoVis::debugFlag = false; 115 bool NanoVis::axisOn = true;116 struct timeval NanoVis::startTime;117 68 118 69 int NanoVis::winWidth = NPIX; … … 121 72 unsigned char *NanoVis::screenBuffer = NULL; 122 73 Texture2D *NanoVis::legendTexture = NULL; 123 Grid *NanoVis::grid = NULL;124 74 Fonts *NanoVis::fonts; 125 75 int NanoVis::updir = Y_POS; … … 148 98 NvLIC *NanoVis::licRenderer = NULL; 149 99 PlaneRenderer *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; 100 OrientationIndicator *NanoVis::orientationIndicator = NULL; 101 Grid *NanoVis::grid = NULL; 156 102 157 103 // Image based flow visualization slice location … … 213 159 screenBuffer = NULL; 214 160 } 215 #ifdef USE_POINTSET_RENDERER216 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 #endif226 161 if (fonts != NULL) { 227 162 TRACE("Deleting fonts"); … … 241 176 flags |= REDRAW_PENDING; 242 177 } 243 }244 245 #ifdef KEEPSTATS246 247 #ifndef STATSDIR248 #define STATSDIR "/var/tmp/visservers"249 #endif /*STATSDIR*/250 251 int252 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 int297 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 int311 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 server331 * - Process ID332 * - Hostname where server is running333 * - Start date of session334 * - Start date of session in seconds335 * - Number of frames returned336 * - Number of bytes total returned (in frames)337 * - Number of commands received338 * - Total elapsed time of all commands339 * - Total elapsed time of session340 * - Exit code of vizserver341 * - User time342 * - System time343 * - User time of children344 * - System time of children345 */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 #endif429 430 static void431 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 file451 NanoVis::logfile = fopen(logName, "w");452 dup2(fileno(NanoVis::logfile), 2);453 /* dup2(2,1); */454 455 // clean up malloc'd memory456 if (logName != NULL) {457 free(logName);458 }459 460 TRACE("Leave");461 }462 463 static void464 exitService(int code)465 {466 TRACE("Enter: %d", code);467 468 NanoVis::removeAllData();469 470 NvShader::exitCg();471 472 //close log file473 if (NanoVis::logfile != NULL) {474 fclose(NanoVis::logfile);475 NanoVis::logfile = NULL;476 }477 478 #ifdef KEEPSTATS479 serverStats(code);480 #endif481 closelog();482 483 exit(code);484 }485 486 static int487 executeCommand(Tcl_Interp *interp, Tcl_DString *dsPtr)488 {489 struct timeval tv;490 double start, finish;491 int result;492 493 #ifdef WANT_TRACE494 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 #endif499 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;517 178 } 518 179 … … 649 310 planeRenderer->render(); 650 311 651 // INSOO312 glPixelStorei(GL_PACK_ALIGNMENT, 1); 652 313 glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, screenBuffer); 653 //glReadPixels(0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, screenBuffer); // INSOO's654 655 314 { 656 315 char prefix[200]; 657 ssize_t nWritten;658 316 659 317 TRACE("Sending ppm legend image %s min:%g max:%g", volArg, min, max); 660 318 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 664 324 } 665 325 planeRenderer->removePlane(index); … … 673 333 674 334 //initialize frame buffer objects for offscreen rendering 675 void 335 bool 676 336 NanoVis::initOffscreenBuffer() 677 337 { … … 712 372 if (!CheckFBO(&status)) { 713 373 PrintFBOStatus(status, "finalFbo"); 714 exitService(3);374 return false; 715 375 } 716 376 717 377 TRACE("Leave"); 378 return true; 718 379 } 719 380 720 381 //resize the offscreen buffer 721 void 382 bool 722 383 NanoVis::resizeOffscreenBuffer(int w, int h) 723 384 { 724 385 TRACE("Enter (%d, %d)", w, h); 725 386 if ((w == winWidth) && (h == winHeight)) { 726 return ;387 return true; 727 388 } 728 389 winWidth = w; … … 739 400 } 740 401 741 screenBuffer = new unsigned char[ 4*winWidth*winHeight];402 screenBuffer = new unsigned char[3*winWidth*winHeight]; 742 403 assert(screenBuffer != NULL); 743 404 744 405 //delete the current render buffer resources 745 406 glDeleteTextures(1, &_finalColorTex); … … 785 446 if (!CheckFBO(&status)) { 786 447 PrintFBOStatus(status, "finalFbo"); 787 exitService(3);448 return false; 788 449 } 789 450 … … 794 455 795 456 TRACE("Leave (%d, %d)", w, h); 457 return true; 796 458 } 797 459 … … 801 463 if (!NvShader::printErrorInfo()) { 802 464 TRACE("Cg error, exiting..."); 803 exit Service(-1);804 } 805 } 806 807 voidNanoVis::init(const char* path)465 exit(1); 466 } 467 } 468 469 bool NanoVis::init(const char* path) 808 470 { 809 471 // print OpenGL driver information … … 816 478 if (path == NULL) { 817 479 ERROR("No path defined for shaders or resources"); 818 exitService(1);480 return false; 819 481 } 820 482 GLenum err = glewInit(); 821 483 if (GLEW_OK != err) { 822 484 ERROR("Can't init GLEW: %s", glewGetErrorString(err)); 823 exitService(1);485 return false; 824 486 } 825 487 TRACE("Using GLEW %s", glewGetString(GLEW_VERSION)); … … 829 491 if (!GLEW_VERSION_2_1) { 830 492 ERROR("OpenGL version 2.1 or greater is required"); 831 exitService(1);493 return false; 832 494 } 833 495 … … 836 498 if (!GLEW_ARB_pixel_buffer_object) { 837 499 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; 839 501 } 840 502 … … 844 506 if (!GLEW_EXT_framebuffer_object) { 845 507 ERROR("EXT_framebuffer_oject extension is required"); 846 exitService(1);508 return false; 847 509 } 848 510 // Rectangle textures were promoted in 3.1 … … 850 512 if (!GLEW_ARB_texture_rectangle) { 851 513 ERROR("ARB_texture_rectangle extension is required"); 852 exitService(1);514 return false; 853 515 } 854 516 #ifdef HAVE_FLOAT_TEXTURES … … 857 519 !GLEW_ARB_color_buffer_float) { 858 520 ERROR("ARB_texture_float and ARB_color_buffer_float extensions are required"); 859 exitService(1);521 return false; 860 522 } 861 523 #endif … … 864 526 !GLEW_NV_fragment_program2) { 865 527 ERROR("NV_vertex_program3 and NV_fragment_program2 extensions are required"); 866 exitService(1);528 return false; 867 529 } 868 530 869 531 if (!FilePath::getInstance()->setPath(path)) { 870 532 ERROR("can't set file path to %s", path); 871 exitService(1);533 return false; 872 534 } 873 535 … … 886 548 grid = new Grid(); 887 549 grid->setFont(fonts); 888 889 #ifdef USE_POINTSET_RENDERER 890 pointSetRenderer = new PointSetRenderer(); 891 #endif 892 } 893 894 void 550 return true; 551 } 552 553 bool 895 554 NanoVis::initGL() 896 555 { … … 901 560 screenBuffer = NULL; 902 561 } 903 screenBuffer = new unsigned char[ 4*winWidth*winHeight];562 screenBuffer = new unsigned char[3*winWidth*winHeight]; 904 563 assert(screenBuffer != NULL); 905 564 … … 927 586 glLightfv(GL_LIGHT1, GL_SPECULAR, white_light); 928 587 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 932 593 volRenderer = new VolumeRenderer(); 933 594 934 // create935 595 renderContext = new RenderContext(); 936 596 937 //create a 2D plane renderer938 597 planeRenderer = new PlaneRenderer(winWidth, winHeight); 939 598 599 orientationIndicator = new OrientationIndicator(); 600 940 601 //assert(glGetError()==0); 941 602 942 603 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; 1321 605 } 1322 606 … … 1577 861 TRACE("Setting bgcolor to %g %g %g", color[0], color[1], color[2]); 1578 862 glClearColor(color[0], color[1], color[2], 1); 863 } 864 865 void 866 NanoVis::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; 1579 873 } 1580 874 … … 1829 1123 1830 1124 //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(); 1837 1128 if ((licRenderer != NULL) && (licRenderer->active())) { 1838 1129 licRenderer->render(); … … 1841 1132 velocityArrowsSlice->render(); 1842 1133 } 1843 if (!flowTable.empty()) { 1844 renderFlows(); 1845 } 1846 1134 renderFlows(); 1847 1135 volRenderer->renderAll(); 1848 1136 1849 TRACE("Render heightmaps");1850 1137 HeightMapHashmap::iterator itr; 1851 1138 for (itr = heightMapTable.begin(); … … 1861 1148 TRACE("Leave"); 1862 1149 } 1863 1864 void1865 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 we1884 // block here and wait if necessary until a command comes in.1885 //1886 // BE CAREFUL: Read only one command, up to a newline. The "volume1887 // data follows" command needs to be able to read the data1888 // immediately following the command, and we shouldn't consume it1889 // 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 now1910 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 anything1918 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 render1957 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 int1970 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-specific1987 * 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 notdef2085 signal(SIGPIPE, SIG_IGN);2086 #endif2087 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 void2105 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 17 17 #define NANOVIS_H 18 18 19 #include <tcl.h>20 #include <md5.h>21 #include <GL/glew.h>22 23 19 #include <math.h> 24 20 #include <stddef.h> // For size_t 25 21 #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> 26 28 27 29 #include <vector> … … 32 34 33 35 #include "config.h" 36 #include "md5.h" 34 37 35 #define NANOVIS_VERSION "1. 1"38 #define NANOVIS_VERSION "1.2" 36 39 37 40 //defines for the image based flow visualization … … 46 49 class Fonts; 47 50 } 51 class OrientationIndicator; 48 52 } 49 53 50 54 class VolumeRenderer; 51 class PointSetRenderer;52 55 class NvParticleRenderer; 53 class PlaneRenderer;54 56 class VelocityArrowsSlice; 55 57 class NvLIC; 56 class P ointSet;58 class PlaneRenderer; 57 59 class Texture2D; 58 60 class HeightMap; … … 89 91 typedef std::tr1::unordered_map<HeightMapId, HeightMap *> HeightMapHashmap; 90 92 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); 96 97 static void setBgColor(float color[3]); 97 98 static void render(); 98 99 static void draw3dAxis(); 99 static void idle();100 100 static void update(); 101 101 static void removeAllData(); … … 113 113 static void setVolumeRanges(); 114 114 static void setHeightmapRanges(); 115 116 #ifdef KEEPSTATS117 static int getStatsFile(Tcl_Obj *objPtr);118 static int writeToStatsFile(int f, const char *s, size_t length);119 #endif120 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);125 115 126 116 static TransferFunction *getTransferFunction(const TransferFunctionId& id); … … 139 129 static void readScreen() 140 130 { 131 glPixelStorei(GL_PACK_ALIGNMENT, 1); 141 132 glReadPixels(0, 0, winWidth, winHeight, GL_RGB, GL_UNSIGNED_BYTE, 142 133 screenBuffer); … … 149 140 static Flow *getFlow(const char *name); 150 141 static Flow *createFlow(Tcl_Interp *interp, const char *name); 142 static void deleteFlows(Tcl_Interp *interp); 151 143 static void deleteFlow(const char *name); 152 static void deleteFlows(Tcl_Interp *interp);153 144 static bool mapFlows(); 154 145 static void getFlowBounds(vrmath::Vector3f& min, … … 160 151 static void advectFlows(); 161 152 162 static FILE *stdin, *logfile, *recfile;163 static int statsFile; 153 static Tcl_Interp *interp; 154 164 155 static unsigned int flags; 165 156 static bool debugFlag; 166 static bool axisOn;167 static struct timeval startTime; ///< Start of elapsed time.168 157 169 158 static int winWidth; ///< Width of the render window … … 172 161 static unsigned char *screenBuffer; 173 162 static Texture2D *legendTexture; 174 static Grid *grid;175 163 static nv::util::Fonts *fonts; 176 164 static int updir; … … 191 179 static NvLIC *licRenderer; 192 180 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; 200 183 201 184 private: -
trunk/packages/vizservers/nanovis/protocol-nanovis.txt
r3568 r3605 38 38 Requests: 39 39 ================================================================================ 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> 40 axis visible <bool> 46 41 47 42 camera angle <xAngle> <yAngle> <zAngle> … … 53 48 camera zoom <factor> 54 49 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> 50 clientinfo <list> 51 52 cutplane 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] 56 cutplane state <bool> <x|y|z> <?names?> 57 Set the axis (normal) of a volume cutplane. Names is 58 an optional list of volume names. 78 59 79 60 flow add <name> <?option value...?> … … 84 65 flow delete <names> 85 66 flow exists <name> 67 This doesn't currently produce a response, it only returns a boolean 68 within the server's interpreter 86 69 flow goto <nSteps> 87 70 flow names 71 This doesn't currently produce a response, it only returns a Tcl list 72 within the server's interpreter 88 73 flow next 89 74 flow reset … … 106 91 <flowObj> box delete <names> 107 92 <flowObj> box names 93 This doesn't currently produce a response, it only returns a Tcl list 94 within the server's interpreter 108 95 109 96 <flowObj> configure <?option value...?> … … 113 100 -diffuse <val> 114 101 -hide <bool> 102 -light2side <bool> 115 103 -opacity <val> 116 104 -outline <bool> … … 139 127 <flowObj> particles delete <names> 140 128 <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 132 grid axiscolor <red> <green> <blue> <?alpha?> 133 grid axisname <x|y|z> <name> <units> 134 grid linecolor <red> <green> <blue> <?alpha?> 135 grid visible <bool> 136 137 heightmap create <heightmapName> <xMin> <yMin> <xMax> <yMax> <xNum> <yNum> <valueList> 138 heightmap cull <none|back|front> 139 heightmap data follows <nBytes> <heightmapName> 140 After newline following command, nBytes of data are sent 141 heightmap data visible <bool> <?heightmapNames?> 142 heightmap legend <heightmapName> <width> <height> 143 heightmap linecontour color <red> <green> <blue> <?heightmapNames?> 144 heightmap linecontour visible <bool> <?heightmapNames?> 145 heightmap opacity <value> <?heightmapNames?> 146 heightmap polygon <wireframe|fill> 147 **Warning: This is a global setting** 148 heightmap shading <flat|smooth> 149 **Warning: This is a global setting** 150 heightmap transfunc <transferFunctionName> <?heightmapNames?> 151 152 legend <transferfunc name> <width> <height> 153 Request render of transfer function 154 155 screen bgcolor <r> <g> <b> 156 Set screen background color 157 screen size <width> <height> 158 Set size of rendered images 159 160 snapshot 161 Render a 2k x 2k image (offscreen buffer). Response image data is tagged 162 as '-type print' 163 164 transfunc 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 169 up <x|y|z|-x|-y|-z> 170 Set orientation of volumes 171 172 volume animation capture <numframes> <?filename?> 173 This is not fully implemented. Rendered frames are not returned 174 to the client. 175 volume animation clear 176 volume animation start 177 volume animation stop 178 volume animation volumes <?names?> 179 180 volume data follows <nbytes> <name> 181 volume data state <bool> <?names?> 182 volume delete <names> 145 183 volume 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 186 volume names 187 This doesn't currently produce a response, it only returns a Tcl list 188 within the server's interpreter 147 189 volume outline color <r> <g> <b> <?names?> 148 volume outline state|visible <bool> <?names?> 190 volume outline state <bool> <?names?> 191 volume outline visible <bool> <?names?> 149 192 volume shading ambient <value> <?names?> 150 193 volume shading diffuse <value> <?names?> 151 194 volume shading isosurface <bool> <?names?> 195 volume shading light2side <bool> <?names?> 152 196 volume shading opacity <value> <?names?> 153 197 volume shading specularExp <value> <?names?> … … 156 200 volume state <bool> <?names?> 157 201 158 volume animation volumes <volume IDs>159 volume animation start160 volume animation stop161 volume animation clear162 volume animation capture numframes <filename>163 164 cutplane position <relval> <x|y|z> <?names?>165 Set the position of a volume cutplane. Names is166 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 is170 an optional list of volume names.171 172 up <x|y|z|-x|-y|-z>173 Set orientation of volumes174 175 202 ================================================================================ 176 203 Replies: 177 204 ================================================================================ 178 205 nv>legend <volume> <min> <max> <nbytes> 179 (followed by bytes and newline)206 (followed by bytes) 180 207 181 208 nv>image -type image -bytes <nbytes> 182 (followed by bytes -- command _preceded_ by newline)209 (followed by bytes) 183 210 184 211 nv>image -type print -bytes <nbytes> 185 (followed by bytes -- command _preceded_ by newline)212 (followed by bytes) 186 213 187 214 nv>image -type movie -token <token> -bytes <nbytes> … … 192 219 min,max over all volumes 193 220 221 nv>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 194 225 ================================================================================ 195 226 Error Replies:
Note: See TracChangeset
for help on using the changeset viewer.