plvMeshCmds.cc
上传用户:kellyonhid
上传日期:2013-10-12
资源大小:932k
文件大小:21k
源码类别:

3D图形编程

开发平台:

Visual C++

  1. #include <stdlib.h>
  2. #include "plvDrawCmds.h"
  3. #include "plvGlobals.h"
  4. #include "plvDraw.h"
  5. #include "plvMeshCmds.h"
  6. #include "plvScene.h"
  7. #include "ply++.h"
  8. #include "Mesh.h"
  9. #include "RigidScan.h"
  10. #include "togl.h"
  11. #include "DisplayMesh.h"
  12. #include "GroupUI.h"
  13. #include "plvPlyCmds.h"
  14. #include "GroupScan.h"
  15. #include "GenericScan.h"
  16. #include "ScanFactory.h"
  17. #include "plvClipBoxCmds.h"
  18. static RigidScan*
  19. GetMeshFromCmd (Tcl_Interp* interp, int argc, char* argv[],
  20. int minArgC = 2, DisplayableMesh** pOutDisp = NULL,
  21. int iMeshName = 1)
  22. {
  23.   char buf [1000];
  24.   if (argc < minArgC) {
  25.     sprintf (buf, "%s: Wrong number of args", argv[0]);
  26.     Tcl_SetResult (interp, buf, TCL_VOLATILE);
  27.     return NULL;
  28.   }
  29.   DisplayableMesh* dispMesh = FindMeshDisplayInfo (argv[iMeshName]);
  30.   if (pOutDisp != NULL)
  31.     *pOutDisp = dispMesh;
  32.   if (dispMesh == NULL) {
  33.     sprintf (buf, "%s: Mesh '%s' does not exist", argv[0], argv[iMeshName]);
  34.     Tcl_SetResult (interp, buf, TCL_VOLATILE);
  35.     return NULL;
  36.   }
  37.   RigidScan* meshSet = dispMesh->getMeshData();
  38.   assert (meshSet != NULL);
  39.   return meshSet;
  40. }
  41. int
  42. PlvMeshResolutionCmd(ClientData clientData, Tcl_Interp *interp, 
  43.      int argc, char *argv[])
  44. {
  45.   DisplayableMesh* dm;
  46.   RigidScan* scan = GetMeshFromCmd (interp, argc, argv, 3, &dm);
  47.   if (!scan)
  48.     return TCL_ERROR;
  49.   bool ok = false;
  50.   if (!strcmp (argv[2], "higher"))
  51.     ok = scan->select_finer();
  52.   else if (!strcmp (argv[2], "lower"))
  53.     ok = scan->select_coarser();
  54.   else if (!strcmp (argv[2], "highest"))
  55.     ok = scan->select_finest();
  56.   else if (!strcmp (argv[2], "lowest"))
  57.     ok = scan->select_coarsest();
  58.   else
  59.     ok = scan->select_by_count (atoi (argv[2]));
  60.   dm->invalidateCachedData();
  61.   redraw (true);
  62.   interp->result = ok ? "1" : "0";
  63.   return TCL_OK;
  64. }
  65. int
  66. PlvMeshDecimateCmd(ClientData clientData, Tcl_Interp *interp,
  67.    int argc, char *argv[])
  68. {
  69.   RigidScan* theSet = GetMeshFromCmd (interp, argc, argv, 3);
  70.   if (!theSet)
  71.     return TCL_ERROR;
  72.   int targetSize = atoi(argv[2]);
  73.   ResolutionCtrl::Decimator dec = ResolutionCtrl::decQslim;
  74.   if (argc > 3) {
  75.     if (!strcmp (argv[3], "qlsim"))
  76.       dec = ResolutionCtrl::decQslim;
  77.     else if (!strcmp (argv[3], "plycrunch"))
  78.       dec = ResolutionCtrl::decPlycrunch;
  79.   }
  80.   int nPolys = theSet->create_resolution_absolute(targetSize, dec);
  81.   char szPolys[20];
  82.   sprintf (szPolys, "%d", nPolys);
  83.   Tcl_SetResult (interp, szPolys, TCL_VOLATILE);
  84.   if (nPolys)
  85.     return TCL_OK;
  86.   else 
  87.     return TCL_ERROR;
  88. }
  89. int
  90. PlvMeshResListCmd(ClientData clientData, Tcl_Interp *interp, 
  91.        int argc, char *argv[])
  92. {
  93.   char result[PATH_MAX], tempstr[PATH_MAX];
  94.   RigidScan* theSet = GetMeshFromCmd (interp, argc, argv, 2);
  95.   if (!theSet)
  96.     return TCL_ERROR;
  97.   bool bShort = false;
  98.   if (argc > 2 && !strcmp (argv[2], "short"))
  99.     bShort = true;
  100.   vector<ResolutionCtrl::res_info> resList;
  101.   theSet->existing_resolutions (resList);
  102.   result[0] = '';
  103.   for (int i = 0; i < resList.size(); i++) {
  104.     if (bShort)
  105.       sprintf (tempstr, "%d ", resList[i].abs_resolution);
  106.     else
  107.       sprintf (tempstr, "(%c%c):%d ",
  108.        resList[i].desired_in_mem ? 'A' : '-',
  109.        resList[i].in_memory ? 'L' : '-',
  110.        resList[i].abs_resolution);
  111.     strcat(result, tempstr);
  112.   }
  113.   Tcl_SetResult(interp, result, TCL_VOLATILE);
  114.   return TCL_OK;
  115. }
  116. int
  117. PlvSetMeshResPreloadCmd(ClientData clientData, Tcl_Interp *interp,
  118. int argc, char *argv[])
  119. {
  120.   RigidScan* theSet = GetMeshFromCmd (interp, argc, argv, 4);
  121.   if (!theSet)
  122.     return TCL_ERROR;
  123.   int nRes = atoi(argv[2]);
  124.   bool bPreload = atoi(argv[3]);
  125.   if (theSet->set_load_desired (nRes, bPreload))
  126.     return TCL_OK;
  127.   
  128.   interp->result = "Specified resolution does not exist";
  129.   return TCL_ERROR;
  130. }
  131. int
  132. PlvCurrentResCmd(ClientData clientData, Tcl_Interp *interp,
  133.  int argc, char *argv[])
  134. {
  135.   char info[PATH_MAX];
  136.   RigidScan* meshSet = GetMeshFromCmd (interp, argc, argv, 2);
  137.   if (!meshSet)
  138.   {
  139.     interp->result = "Unable to find mesh in PlvCurrentResCmd";
  140.     return TCL_ERROR;
  141.   }
  142.   if (!meshSet->num_resolutions())
  143.   {
  144.     interp->result = "Given mesh has no data in PlvCurrentResCmd";
  145.     return TCL_ERROR;
  146.   }
  147.   ResolutionCtrl::res_info res = meshSet->current_resolution();
  148.   sprintf(info, "%d", res.abs_resolution);
  149.   Tcl_SetResult(interp, info, TCL_VOLATILE);
  150.   return TCL_OK;
  151. }
  152. int
  153. PlvMeshInfoCmd(ClientData clientData, Tcl_Interp *interp, 
  154.        int argc, char *argv[])
  155. {
  156.   RigidScan* meshSet = GetMeshFromCmd (interp, argc, argv, 2);
  157.   if (meshSet == NULL)
  158.     return TCL_ERROR;
  159.   
  160.   if (argc > 2 && 0 == strcmp (argv[2], "graphical"))
  161.     Tcl_SetResult(interp, (char *)meshSet->getInfo().c_str(), 
  162.   TCL_VOLATILE);
  163.   else
  164.     cout << meshSet->getInfo() << endl;
  165.   return TCL_OK;
  166. }
  167. int
  168. PlvMeshDeleteResCmd(ClientData clientData, Tcl_Interp *interp,
  169.     int argc, char *argv[])
  170. {
  171.   RigidScan* scan = GetMeshFromCmd (interp, argc, argv, 3);
  172.   if (scan == NULL)
  173.     return TCL_ERROR;
  174.   if (scan->num_resolutions() == 1) {
  175.     interp->result = "Scan has only 1 resolution; can't be deleted";
  176.     return TCL_ERROR;
  177.   }
  178.   int resLevel = atoi(argv[2]);
  179.   if (!scan->delete_resolution (resLevel))
  180.     return TCL_ERROR;
  181.   
  182.   //cout << "new #resolutions: " << scan->num_resolutions() << endl;
  183.   return TCL_OK;
  184. }
  185. int
  186. PlvMeshUnloadResCmd(ClientData clientData, Tcl_Interp *interp,
  187.     int argc, char* argv[])
  188. {
  189.   DisplayableMesh* dm;
  190.   RigidScan* scan = GetMeshFromCmd (interp, argc, argv, 3, &dm);
  191.   if (scan == NULL) {
  192.     cerr << argv[0] << " does not exist!" << endl;
  193.     return TCL_ERROR;
  194.   }
  195.   int resLevel = atoi(argv[2]);
  196.   
  197.   if (!scan->release_resolution (resLevel)) {
  198.     cerr << "scan " << dm->getName()
  199.  << " failed to release resolution" << endl;
  200.     return TCL_ERROR;
  201.   }
  202.   // scan released memory... which dm could have hold on
  203.   dm->invalidateCachedData();
  204.   return TCL_OK;
  205. }
  206. static void DeleteHelper (DisplayableMesh *mesh);
  207. int
  208. PlvMeshSetDeleteCmd(ClientData clientData, Tcl_Interp *interp, 
  209.  int argc, char *argv[])
  210. {
  211.   DisplayableMesh* dispMesh;
  212.   RigidScan* meshSet = GetMeshFromCmd (interp, argc, argv, 2, &dispMesh);
  213.   if (meshSet == NULL)
  214.     return TCL_ERROR;
  215.   DeleteHelper(dispMesh);
  216.   //theScene->deleteMeshSet (dispMesh);
  217.   return TCL_OK;
  218. }
  219. static void 
  220. DeleteHelper (DisplayableMesh *mesh) {
  221.   RigidScan *scan = mesh->getMeshData();
  222.   GroupScan *group = dynamic_cast<GroupScan*>(scan);
  223.   if (group) {
  224.     vector<DisplayableMesh*> children = ungroupScans(mesh);
  225.     
  226.     for (DisplayableMesh** it = children.begin(); it < children.end(); it++) {
  227.       DeleteHelper(*it);
  228.     }
  229.   } else {
  230.     theScene->deleteMeshSet (mesh);
  231.   }
  232. }
  233.   
  234. int
  235. PlvTransMeshCmd (ClientData clientData, Tcl_Interp *interp,
  236.  int argc, char* argv[])
  237. {
  238.   if (argc != 5) {
  239.     printf ("%s: mesh x y zn", argv[0]);
  240.     return TCL_OK;
  241.   }
  242.   
  243.   DisplayableMesh* dispMesh = FindMeshDisplayInfo (argv[1]);
  244.   if (dispMesh == NULL) {
  245.     printf ("Nonexistent mesh %sn", argv[1]);
  246.     return TCL_OK;
  247.   }
  248.   RigidScan* meshSet = dispMesh->getMeshData();
  249.   assert (meshSet != NULL);
  250.   meshSet->translate(atof(argv[2]), atof(argv[3]), atof(argv[4]));
  251.   redraw (true);
  252.   return TCL_OK;
  253. }
  254. int
  255. PlvMeshRemoveStepCmd(ClientData clientData, Tcl_Interp *interp,
  256.      int argc, char *argv[])
  257. {
  258. #if 1
  259.   printf ("Unimplemented!!!n");
  260. #endif
  261.   return TCL_OK;
  262. }
  263. int
  264. PlvScanColorCodeCmd(ClientData clientData, Tcl_Interp *interp,
  265.     int argc, char *argv[])
  266. {
  267.   DisplayableMesh* dispMesh;
  268.   RigidScan* meshSet = GetMeshFromCmd (interp, argc, argv, 3, &dispMesh, 2);
  269.   if (meshSet == NULL)
  270.     return TCL_ERROR;
  271.   if (!strcmp (argv[1], "set")) {
  272.     unsigned int r, g, b;
  273.     if (argc != 4 || 3 != sscanf (argv[3], "#%02x%02x%02x", &r, &g, &b)) {
  274.       interp->result = "Bad color args.";
  275.       return TCL_ERROR;
  276.     }
  277.     vec3uc color = {r, g, b};
  278.     dispMesh->setFalseColor (color);
  279.   } else {
  280.     char color[20];
  281.     const vec3uc& diffuse = dispMesh->getFalseColor();
  282.     sprintf (color, "#%02x%02x%02x",
  283.      (unsigned)diffuse[0],
  284.      (unsigned)diffuse[1],
  285.      (unsigned)diffuse[2]);
  286.     Tcl_SetResult (interp, color, TCL_VOLATILE);
  287.   }
  288.   return TCL_OK;
  289. }
  290. int
  291. PlvFlipMeshNormalsCmd(ClientData clientData, Tcl_Interp *interp,
  292.       int argc, char *argv[])
  293. {
  294.   DisplayableMesh* mesh;
  295.   RigidScan* scan = GetMeshFromCmd (interp, argc, argv, 2, &mesh);
  296.   if (scan == NULL)
  297.     return TCL_ERROR;
  298.   scan->flipNormals();
  299.   mesh->invalidateCachedData();
  300.   redraw (true);
  301.   return TCL_OK;
  302. }
  303. int
  304. PlvBlendMeshCmd(ClientData clientData, Tcl_Interp *interp,
  305. int argc, char *argv[])
  306. {
  307.   DisplayableMesh* mesh;
  308.   RigidScan* meshSet = GetMeshFromCmd (interp, argc, argv, 3, &mesh);
  309.   if (meshSet == NULL)
  310.     return TCL_ERROR;
  311.   float alpha = atof (argv[2]);
  312.   if (alpha > 0.0 && alpha < 1.0)
  313.     mesh->setBlend (true, alpha);
  314.   else
  315.     mesh->setBlend (false, 1);
  316.   redraw (true);
  317.   return TCL_OK;
  318. }
  319. int
  320. PlvGroupScansCmd(ClientData clientData, Tcl_Interp *interp,
  321.  int argc, char *argv[])
  322. {
  323.   if (argc < 3) {
  324.     interp->result = "Bad args to PlvGroupScansCmd";
  325.     return TCL_ERROR;
  326.   }
  327.   vector<DisplayableMesh*> members;
  328.   
  329.   if (!strcmp (argv[1], "create")) {
  330.       
  331.     for (int i = 3; i < argc-1; i++) {
  332.       DisplayableMesh* dm = FindMeshDisplayInfo (argv[i]);
  333.       if (!dm) {
  334. cerr << "No such mesh: " << argv[i] << endl;
  335. interp->result = "Missing scan in PlvGroupScansCmd";
  336. return TCL_ERROR;
  337.       }
  338.       members.push_back (dm);
  339.     }
  340.     bool dirty = (bool) atoi(argv[argc-1]);
  341.     DisplayableMesh* group = groupScans (members, argv[2], dirty);
  342.     
  343.     if (!group) {
  344.       interp->result = "The group could not be created.";
  345.       return TCL_ERROR;
  346.     }
  347.     interp->result = (char*)group->getName();
  348.   } else if (!strcmp (argv[1], "list")) {
  349.     DisplayableMesh* mesh;
  350.     if (!GetMeshFromCmd (interp, argc, argv, 3, &mesh, 2))
  351.       return TCL_ERROR;
  352.     GroupScan* group = dynamic_cast<GroupScan*> (mesh->getMeshData());
  353.     crope names;
  354.     if (group) {
  355.       if (group->get_children_for_display (members)) {
  356. for (int i = 0; i < members.size(); i++) {
  357.   names += crope (" ") + members[i]->getName();
  358. }
  359.       }
  360.     }
  361.     Tcl_SetResult (interp, (char*)names.c_str(), TCL_VOLATILE);
  362.   } else if (!strcmp (argv[1], "break") || !strcmp (argv[1], "expand")) {
  363.     DisplayableMesh* mesh;
  364.     if (!GetMeshFromCmd (interp, argc, argv, 3, &mesh, 2))
  365.       return TCL_ERROR;
  366.     members = ungroupScans (mesh);
  367.     if (!members.size()) {
  368.       interp->result = "The scan could not be ungrouped -- perhaps "
  369. "it's not a group in the first place?";
  370.       return TCL_ERROR;
  371.     }
  372.     crope names (members[0]->getName());
  373.     for (int i = 1; i < members.size(); i++) {
  374.       names += crope (" ") + members[i]->getName();
  375.     }
  376.     Tcl_SetResult (interp, (char*)names.c_str(), TCL_VOLATILE);
  377.   } else if (!strcmp (argv[1], "isgroup")) {
  378.       DisplayableMesh* dm = FindMeshDisplayInfo (argv[2]);
  379.       if (!dm) {
  380. interp->result = "Missing scan in PlvGroupScansCmd";
  381. return TCL_ERROR;
  382.       }
  383.       RigidScan* scan = dm->getMeshData();
  384.       vector<RigidScan*> children;
  385.       if (scan->get_children (children)) {
  386. interp->result = "1";
  387.       } else {
  388. interp->result= "0";
  389.       }
  390.       return TCL_OK;
  391.   } else {
  392.     interp->result = "Unrecognized option to PlvGroupScansCmd";
  393.     return TCL_ERROR;
  394.   }
  395.   //cout << "Group: scene now has " << theScene->meshSets.size()
  396.   //     << " meshes" << endl;
  397.   return TCL_OK;
  398. }
  399. int
  400. PlvHiliteScanCmd(ClientData clientData, Tcl_Interp *interp,
  401.  int argc, char *argv[])
  402. {
  403.   // unhilite previous selection in meshcontrols window
  404.   for (int i = 0; i < g_hilitedScans.size(); i++)
  405.     Tcl_VarEval (interp, "hiliteScanEntry ",
  406.  g_hilitedScans[i]->getName(),
  407.  " 0", NULL);
  408.   // build new vector of currently hilited scans
  409.   g_hilitedScans.clear();
  410.   g_hilitedScans.reserve (argc - 1);
  411.   for (i = 1; i < argc; i++) {
  412.     DisplayableMesh* dispMesh = FindMeshDisplayInfo (argv[i]);
  413.     if (!dispMesh) {
  414.       cerr << argv[0] << " can't find " << argv[i] << endl;
  415.       interp->result = "Bad scan in PlvHiliteScanCmd";
  416.       return TCL_ERROR;
  417.     }
  418.     
  419.     g_hilitedScans.push_back (dispMesh);
  420.   }
  421.   // and hilite current selection in meshcontrols window
  422.   for (i = 0; i < g_hilitedScans.size(); i++)
  423.     Tcl_VarEval (interp, "hiliteScanEntry ",
  424.  g_hilitedScans[i]->getName(),
  425.  " 1", NULL);
  426. #ifndef no_overlay_support
  427.   Togl_PostOverlayRedisplay (toglCurrent);
  428. #else
  429.   drawOverlayAndSwap(toglCurrent);
  430. #endif
  431.   return TCL_OK;
  432. }
  433. int
  434. SczXformScanCmd (ClientData clientData, Tcl_Interp *interp, 
  435.  int argc, char *argv[])
  436. {
  437.   RigidScan* scan = GetMeshFromCmd (interp, argc, argv, 2);
  438.   if (!scan)
  439.     return TCL_ERROR;
  440.   if (argc < 3) {
  441.     interp->result = "Missing command in SczXformScanCmd";
  442.     return TCL_ERROR;
  443.   }
  444.   if (!strcmp (argv[2], "reload")) {
  445.     if (!scan->readXform (scan->get_basename())) {
  446.       cerr << "Scan " << scan->get_name()
  447.    << " failed to read xform." << endl;
  448.       interp->result = "Xform read failed!";
  449.       return TCL_ERROR;
  450.     }
  451.   } else if (!strcmp (argv[2], "matrix")) {
  452.     if (argc < 4) {
  453.       interp->result = "Missing matrix!";
  454.       return TCL_ERROR;
  455.     }
  456.     Xform<float> xfTo;
  457.     if (!matrixFromString (argv[3], xfTo)) {
  458.       interp->result = "Bad matrix!";
  459.       return TCL_ERROR;
  460.     }
  461.     Xform<float> xfRelTo;
  462.     if (argc > 4) {
  463.       if (!strcmp (argv[4], "relative"))
  464. xfTo = xfTo * scan->getXform();
  465.       else if(!matrixFromString (argv[4], xfRelTo)) {
  466. interp->result = "Bad matrix!";
  467. return TCL_ERROR;
  468.       }
  469.     }
  470.     if (!xfRelTo.isIdentity()) {
  471.       xfRelTo.invert();
  472.       xfTo = xfTo * xfRelTo * scan->getXform();
  473.     }
  474.     scan->setXform (xfTo);
  475.   }
  476.   theScene->computeBBox();
  477.   redraw();
  478.   return TCL_OK;
  479. }
  480. int SczGetScanXformCmd(ClientData clientData, Tcl_Interp *interp,
  481.        int argc, char *argv[])
  482. {
  483.   RigidScan* scan = GetMeshFromCmd (interp, argc, argv, 2);
  484.   if (!scan)
  485.     return TCL_ERROR;
  486.   if (argc < 3) {
  487.     interp->result = "Missing command in SczXformScanCmd";
  488.     return TCL_ERROR;
  489.   }
  490.   Xform<float> xf = scan->getXform();
  491.   char buffer[1000] = "";
  492.   if (!strcmp (argv[2], "matrix")) {
  493.     char line[100];
  494.     for (int i = 0; i < 4; i++) {
  495.       sprintf (line, "%g %g %g %gn",
  496.        xf(i,0), xf(i,1), xf(i,2), xf(i,3));
  497.       strcat (buffer, line);
  498.     }
  499.   } else if (!strcmp (argv[2], "quat")) {
  500.     float q[4], t[3];
  501.     xf.toQuaternion (q);
  502.     xf.getTranslation (t);
  503.     sprintf (buffer, "%g %g %g %gn%g %g %gn",
  504.      q[0], q[1], q[2], q[3],
  505.      t[0], t[1], t[2]);
  506.   } else if (!strcmp (argv[2], "axis")) {
  507.     float phi, ax, ay, az, t[3];    
  508.     xf.get_rot (phi, ax, ay, az);
  509.     xf.getTranslation (t);
  510.     sprintf (buffer, "%g around %g %g %gn%g %g %gn",
  511.      phi * 180 / M_PI, ax, ay, az,
  512.      t[0], t[1], t[2]);
  513.   } else {
  514.     interp->result = "Bad command in SczGetScanXformCmd!";
  515.     return TCL_ERROR;
  516.   }
  517.   Tcl_SetResult (interp, buffer, TCL_VOLATILE);
  518.   return TCL_OK;
  519. }
  520. int
  521. PlvSmoothMesh(ClientData clientData, Tcl_Interp *interp,
  522.       int argc, char *argv[])
  523. {
  524.   if (argc < 4) {
  525.     interp->result = "plvSmoothMesh <meshName> <iterations> <maxMotion_mm>";
  526.     return TCL_ERROR;
  527.   }
  528.   RigidScan* scan = GetMeshFromCmd (interp, argc, argv, 1);
  529.   if (scan == NULL)
  530.     {
  531.       return TCL_ERROR;
  532.     }
  533.   int iterations = atoi(argv[2]);
  534.   double maxMotion = atof(argv[3]);
  535.   printf ("%s %d %fn",argv[1],iterations,maxMotion);
  536.   GenericScan* gscan=(GenericScan *)scan;
  537.   gscan->dequantizationSmoothing(iterations,maxMotion);
  538.   
  539.   return TCL_OK;
  540. }
  541. #define MINARGCOUNT(n) 
  542.   if (argc < n) { 
  543.     _BadArgCount (argv[0], interp); 
  544.     return TCL_ERROR; 
  545.   }
  546. void _BadArgCount (char* proc, Tcl_Interp* interp)
  547. {
  548.   char buf[200];
  549.   sprintf (buf, "%s: not enough argumentsn", proc);
  550.   Tcl_SetResult (interp, buf, TCL_VOLATILE);
  551. }
  552. int PolygonArea(vector<ScreenPnt> &pts)
  553. {
  554.   int i, j, area = 0;
  555.   for (i=0; i<pts.size(); i++) {
  556.     j = (i + 1) % pts.size();
  557.     
  558.     area += pts[i].x * pts[j].y;
  559.     area -= pts[j].x * pts[i].y;
  560.   }
  561.   
  562.   return area / 2;
  563. }
  564. //
  565. // PlvRunExternalProgram
  566. // ---------------------
  567. // Tcl visible function that enables an external program to be run
  568. // on a mesh.  Temporary files are used to transfer information to/from
  569. // the external program.
  570. //
  571. int PlvRunExternalProgram(ClientData clientData, Tcl_Interp *interp,
  572.   int argc, char *argv[])
  573. {
  574.   char buf[256]; // temporary storage
  575.   char clipBoxCoord[256];
  576.   GLdouble mvmatrix[16], projmatrix[16];
  577.   if (argc != 5) {
  578.     interp->result = "plvRunExternalProgram <command> <name> "
  579.                      "<output> <incBox>";
  580.     return TCL_ERROR;
  581.   }
  582.   // easier access to command line parameters
  583.   char *command = argv[1];
  584.   char *inputMesh = argv[2];
  585.   char *outputMesh = argv[3];
  586.   int writeCBox = atoi(argv[4]);
  587.   // parameter error checking
  588.   if (!strlen(command) || !strlen(inputMesh) || !strlen(outputMesh)) {
  589.     interp->result = "Please enter a command, inputMesh or outputMesh name";
  590.     return TCL_ERROR;
  591.   }
  592.     
  593.   if (writeCBox) {
  594.     clipBoxCoord[0] = '';
  595.     if (theSel.pts.size() < 3) {
  596.       interp->result = "At least 3 points are needed for clipping information";
  597.       return TCL_ERROR;
  598.     }
  599.     GLint viewport[4];
  600.     vector<Pnt3> obj;
  601.     vector<Pnt3> objNormForward;
  602.     // information for unprojecting
  603.     glGetIntegerv(GL_VIEWPORT, viewport);
  604.     glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
  605.     glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
  606.        
  607.     for (int i=0; i<theSel.pts.size(); i++) {
  608.       Unprojector unp;
  609.       GLdouble objx, objy, objz, objFarX, objFarY, objFarZ;
  610.    
  611.       gluUnProject(theSel.pts[i].x, theSel.pts[i].y, 0,
  612.    mvmatrix, projmatrix, viewport, &objx, &objy, &objz);
  613.       gluUnProject(theSel.pts[i].x, theSel.pts[i].y, 1,
  614.    mvmatrix, projmatrix, viewport, &objFarX, &objFarY, &objFarZ);
  615.       Pnt3 v1(objFarX-objx, objFarY-objy, objFarZ-objz);
  616.       v1.normalize();
  617.       objNormForward.push_back(v1);
  618.       Pnt3 t(objx, objy, objz);
  619.       obj.push_back(t);
  620.     }
  621.     // print the list of information
  622.     // get orientation of face vertices
  623.     bool ccw = (PolygonArea(theSel.pts) > 0 ? true : false);
  624.     
  625.     int j;
  626.     for (i=0; i<theSel.pts.size(); i++) {
  627.       char tempVertBuf[256];
  628.       j = (i + 1) % theSel.pts.size();
  629.       
  630.       Pnt3 crs;
  631.       Pnt3 up(obj[j][0] - obj[i][0], obj[j][1] - obj[i][1], obj[j][2] - obj[i][2]);
  632.       
  633.       if (!ccw)
  634. crs = cross(objNormForward[i], up);
  635.       else
  636. crs = cross(up, objNormForward[i]);
  637.       crs.normalize();
  638.       // make the point list and concat it with the current clip region string
  639.       sprintf(tempVertBuf, "%f %f %f %f %f %f ", (double)obj[i][0], (double)obj[i][1], 
  640.       (double)obj[i][2], (double)crs[0], (double)crs[1], (double)crs[2]);
  641.       strcat(clipBoxCoord, tempVertBuf);
  642.     }    
  643.   }
  644.   // get the mesh to send to output
  645.   DisplayableMesh* dispMesh = FindMeshDisplayInfo (inputMesh);
  646.   if (dispMesh == NULL) {
  647.     sprintf (buf, "%s: Mesh '%s' does not exist", argv[0], inputMesh);
  648.     Tcl_SetResult (interp, buf, TCL_VOLATILE);
  649.     return TCL_ERROR;
  650.   }
  651.   
  652.   // get the rigid scan from the mesh
  653.   RigidScan* meshSet = dispMesh->getMeshData();
  654.   if (meshSet == NULL) {
  655.     sprintf (buf, "%s: Mesh '%s' does not exist", argv[0], inputMesh);
  656.     Tcl_SetResult (interp, buf, TCL_VOLATILE);
  657.     return TCL_ERROR;
  658.   }
  659.   // get a temporary name and convert it to a crope with extension ply
  660.   crope inTName = tmpnam(NULL);
  661.   inTName += ".ply";
  662.     
  663.   // write the highest resolution to the temporary file
  664.   vector<ResolutionCtrl::res_info> resList;
  665.   meshSet->existing_resolutions (resList);
  666.  
  667.   int finest = 0;
  668.   for (int i=1; i<resList.size(); i++) {
  669.     if (resList[finest].abs_resolution < resList[i].abs_resolution)
  670.       finest = i;
  671.   }
  672.    
  673.   // if we're clipping the object against some box, put the object in it's world space orientation
  674.   // rather than just using it's default object space orientation.
  675.   if (writeCBox)
  676.     meshSet->write_resolution_mesh(resList[finest].abs_resolution, inTName, meshSet->getXform());
  677.   else
  678.     meshSet->write_resolution_mesh(resList[finest].abs_resolution, inTName);
  679.   // get another temporary name
  680.   crope outTName = tmpnam(NULL);
  681.   outTName += ".ply";
  682.   
  683.   // execute the command
  684.   char cmdBuffer[512];
  685.   if (writeCBox)
  686.     sprintf(cmdBuffer, "%s %s %s %s", command, inTName.c_str(), outTName.c_str(), clipBoxCoord);
  687.   else
  688.     sprintf(cmdBuffer, "%s %s %s ", command, inTName.c_str(), outTName.c_str());
  689.   if (system (cmdBuffer)) {
  690.     interp->result = "Command failed.";
  691.     // delete the temporary files
  692.     sprintf(cmdBuffer, "rm -f %s", inTName.c_str());
  693.     system(cmdBuffer);
  694.     sprintf(cmdBuffer, "rm -f %s", outTName.c_str());
  695.     system(cmdBuffer);
  696.     return TCL_ERROR;
  697.   }
  698.   // read in the output file
  699.   RigidScan *newScan = CreateScanFromFile(outTName.c_str());
  700.   if (newScan != NULL) {
  701.     crope omName = outputMesh;
  702.     omName += ".ply";
  703.     newScan->set_name(omName);
  704.     
  705.     DisplayableMesh *dm = theScene->addMeshSet(newScan);
  706.     sprintf(cmdBuffer, "clipMeshCreateHelper %s %s", inputMesh, outputMesh);
  707.     Tcl_Eval(interp, cmdBuffer);
  708.   } else {
  709.     interp->result = "A filtered scan could not be created";
  710.     
  711.     // delete the temporary files
  712.     sprintf(cmdBuffer, "rm -f %s", inTName.c_str());
  713.     system(cmdBuffer);
  714.     sprintf(cmdBuffer, "rm -f %s", outTName.c_str());
  715.     system(cmdBuffer);
  716.     return TCL_ERROR;
  717.   }
  718.   // delete the temporary files
  719.   sprintf(cmdBuffer, "rm -f %s", inTName.c_str());
  720.   system(cmdBuffer);
  721.   sprintf(cmdBuffer, "rm -f %s", outTName.c_str());
  722.   system(cmdBuffer);
  723.   return TCL_OK;
  724. }