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

3D图形编程

开发平台:

Visual C++

  1. //############################################################
  2. // 
  3. // CyberCmds.cc
  4. //
  5. // Matt Ginzton, Kari Pulli
  6. // Mon Jan 25 16:47:50 CET 1999
  7. //
  8. // Implement interface to commands that operate only on
  9. // data from the CyberWare custom range scanner for the
  10. // Digital Michelangelo project.
  11. //
  12. //############################################################
  13. #include <vector.h>
  14. #include <fstream.h>
  15. #include "Xform.h"
  16. #include "Pnt3.h"
  17. #include "CyberScan.h"
  18. #include "CyberCmds.h"
  19. #include "Progress.h"
  20. #include "DisplayMesh.h"
  21. #include "defines.h"
  22. #include "plvGlobals.h"
  23. #include "plvScene.h"
  24. #include "ICP.h"
  25. #include "GlobalReg.h"
  26. #include "BailDetector.h"
  27. #include "WorkingVolume.h"
  28. #include "FileNameUtils.h"
  29. int 
  30. PlvWriteSDForVripCmd(ClientData clientData, 
  31.      Tcl_Interp *interp,
  32.      int argc, char* argv[])
  33. {
  34.    if (argc < 5) {
  35.       interp->result = 
  36. "Usage: PlvWriteSDForVripCmd <res level, 0=max> <dir> "
  37. "<sweeps|subsweeps> <delete-sweeps>";
  38.       return TCL_ERROR;
  39.    }
  40.    int iRes = atoi (argv[1]);
  41.    char* dir = argv[2];
  42.    if (!check_file_access (dir, true, true, true, false, true)) {
  43.      interp->result = "Cannot write to output directory";
  44.      return TCL_ERROR;
  45.    }
  46.    bool useSubSweeps;
  47.    if (!strcmp(argv[3], "sweeps")) {
  48.       useSubSweeps = false;
  49.    } else if (!strcmp(argv[3], "subsweeps")) {
  50.       useSubSweeps = true;
  51.    } else {
  52.       cerr << "Invalid sweep/subsweep option!" << endl;
  53.       return TCL_ERROR;
  54.    }
  55.    bool bDeleteSweeps = atoi (argv[4]);
  56.    bool bConfOnly = (argc > 5) && atoi (argv[5]) && !useSubSweeps;
  57.   // Code for version that used to write the whole scans.
  58.   //Xform<float> xfRotate;
  59.   //xfRotate.rotZ (M_PI);      // right-side-up just for viewing pleasure
  60.   //xfRotate.rotX (-M_PI/2.0); // and for vrip, -90 degrees around X axis
  61.   //Xform<float> xfIR = xfRotate; xfIR.fast_invert();
  62.   
  63.   char name[PATH_MAX];
  64.   crope result;
  65.   bool success = true;
  66.   // vrip can't read tstrips
  67.   char* oldStripVal = Tcl_GetVar (interp, "meshWriteStrips", 
  68.   TCL_GLOBAL_ONLY);
  69.   Tcl_SetVar (interp, "meshWriteStrips", "never", 
  70.       TCL_GLOBAL_ONLY);
  71.   Progress* prog = new Progress (theScene->meshSets.size() * 1000,
  72.  "Output plyfiles for vrip", 
  73.  true);
  74.   char confFN[PATH_MAX];
  75.   sprintf (confFN, "%s/vrip.conf", dir);
  76.   ofstream conffile (confFN, ios::app);
  77.   int framesPerSweep = 256;
  78.   // int overlap = MIN(64, pow(2,iRes+3)+0.5);
  79.   int overlap = int(pow(2,iRes+2)+0.5);
  80.   DisplayableMesh** dm = theScene->meshSets.begin();
  81.   for (; dm < theScene->meshSets.end(); dm++) {
  82.     if (!(*dm)->getVisible())
  83.       continue;
  84.     // JED - Check if mesh loaded, if not load
  85.     
  86.     RigidScan* sd = (*dm)->getMeshData();
  87.     CyberScan* cs = dynamic_cast<CyberScan*> (sd);
  88.     if (!cs)
  89.       continue;
  90.     vector<ResolutionCtrl::res_info> ri;
  91.     int thisIRes;
  92.     int sweepNum = 0;
  93.     vector<CyberSweep*> sweeps = cs->get_sweep_list();
  94.     for (CyberSweep** pSweep = sweeps.begin();
  95.  pSweep < sweeps.end(); pSweep++, sweepNum++) {
  96.       CyberSweep* sweep = *pSweep;
  97.       int numSubSweeps = useSubSweeps ?
  98. (sweep->num_frames()-1)/framesPerSweep + 1
  99. : 1;
  100.       for (int k = 0; k < numSubSweeps; k++) {
  101. // check if file is already there, for incremental ease
  102. // so build the output filename now
  103. const char* sweepnum = sweep->get_basename().c_str();
  104. char* slash = strrchr (sweepnum, '/');
  105. if (slash)
  106.   sweepnum = slash + 1;
  107. sprintf(name, "%s/%s-sweep-%s-%s-sub-%d.ply", dir,
  108. sd->get_basename().c_str(), sweepnum, 
  109. sweep->get_description().c_str(), k);
  110. for (slash = name + strlen(dir) + 1; *slash; slash++)
  111.   if (*slash == '/') *slash = '_';
  112. if (access (name, R_OK)) {
  113.   cout << "Writing " << name << " ... " << flush;
  114. } else if (bConfOnly) {
  115.   cout << "Reusing existing " << name << flush;
  116. } else {
  117.   cout << "Skipping " << name << " (already exists) ... " << endl;
  118.   prog->updateInc (1000 / sweeps.size());
  119.   continue;
  120. }
  121. int res;
  122. CyberSweep *newSweep = sweep;
  123. CyberScan *newScan;
  124. if (!bConfOnly) { // create mesh
  125.   if (useSubSweeps) {
  126.     int frameStart = k*framesPerSweep;
  127.     int frameFinish = MIN(sweep->num_frames()-1,
  128.   (k+1)*framesPerSweep+overlap+1);
  129.     newScan = 
  130.       (CyberScan *)cs->get_piece(sweepNum, frameStart, frameFinish);
  131.     
  132.     if (newScan == NULL)
  133.       continue;
  134.     
  135.     newScan->existing_resolutions (ri);
  136.     thisIRes = MIN (iRes, ri.size() - 1);
  137.     newScan->load_resolution (thisIRes);
  138.     
  139.     vector<CyberSweep*> newSweeps = newScan->get_sweep_list();
  140.     newSweep = newSweeps[0];
  141.     
  142.     ri.clear();
  143.     newSweep->existing_resolutions(ri);
  144.     res = ri[thisIRes].abs_resolution;
  145.   } else {
  146.     // force resolution to exist, since we're writing one or
  147.     // more of its sweeps; harmless enough to call more than once
  148.     sd->existing_resolutions (ri);
  149.     thisIRes = MIN (iRes, ri.size() - 1);
  150.     cs->load_resolution (thisIRes);
  151.     
  152.     newSweep = sweep;
  153.     newSweep->existing_resolutions(ri);
  154.     res = ri[thisIRes].abs_resolution;
  155.   }
  156. } else { // bConfOnly, ensure mesh exists
  157.   res = check_file_access (name, true, true);
  158. }
  159. if (res) {
  160.   Xform<float> xfRotate = newSweep->vrip_reorientation_frame();
  161.   xfRotate.invert();
  162.   if (!bConfOnly) {
  163.     // write plyfile
  164.     if (!newSweep->write_resolution_mesh (res, name, xfRotate)) {
  165.       cerr << "Scan " << sd->get_name() 
  166.    << " failed to write self!"  << endl;
  167.       return TCL_ERROR;
  168.     }
  169.     
  170.     /* Started to write something that would save bboxes for
  171.        pvrip, but realized that the world bboxes would not be
  172.        tight.  We can add tight world bboxes later.  For now,
  173.        pvrip computes its own just fine. */
  174.     
  175.     cout << "done." << endl;
  176.   }
  177.   // write config string:
  178.   // bmesh filename x y z i j k r
  179.   char bmesh[PATH_MAX + 200];
  180.   float t[3];
  181.   float q[4];
  182.   Xform<float> xf = sd->getXform() * newSweep->getXform();
  183.   xfRotate.invert();
  184.   xf = xf * xfRotate;
  185.   xf.toQuaternion (q);
  186.   xf.getTranslation (t);
  187.   sprintf (bmesh, "bmesh %s %g %g %g %g %g %g %g", 
  188.    1+strrchr(name,'/'),
  189.    t[0], t[1], t[2], -q[1], -q[2], -q[3], q[0]);
  190.   
  191.   // write xf
  192.   strcpy (name + strlen(name) - 3, "xf");
  193.   cout << "Writing " << name << " ... " << flush;
  194.   ofstream xffile (name);
  195.   xffile << xf;
  196.   if (xffile.fail()) {
  197.     cerr << "Scan " << sd->get_name() 
  198.  << " failed to write xform!" << endl;
  199.     success = false;
  200.     break;
  201.   }
  202.   cout << "done." << endl;
  203.   conffile << bmesh << endl;
  204. }
  205. if (useSubSweeps) 
  206.   delete newScan;
  207. if (!g_bNoUI && !prog->updateInc (1000 / sweeps.size())) {
  208.   success = false;
  209.   cerr << endl << "CyberScan -> vrip output: cancelled!" 
  210.        << endl << endl;
  211.   break;
  212. }
  213.       }
  214.       if (BailDetector::bail())
  215. break;
  216.     }
  217.     // free memory?
  218.     if (!useSubSweeps && bDeleteSweeps) {
  219.       sd->existing_resolutions (ri);
  220.       int thisIRes = MIN (ri.size() - 1, iRes);
  221.       cout << "now say bye-bye to res " << thisIRes << " of "
  222.    << cs->get_name() << endl;
  223.       sd->release_resolution (ri[thisIRes].abs_resolution);
  224.     }
  225.     // JED - Unload mesh from memory if it started unloaded
  226.     
  227.     if (BailDetector::bail())
  228.       break;
  229.   }
  230.   
  231.   // cleanup
  232.   delete prog;
  233.   Tcl_SetVar (interp, "meshWriteStrips", oldStripVal, 
  234.       TCL_GLOBAL_ONLY);
  235.   if (!success)
  236.     return TCL_ERROR;
  237.   return TCL_OK;
  238. }
  239. int 
  240. PlvCyberScanSelfAlignCmd(ClientData clientData, 
  241.  Tcl_Interp *interp,
  242.  int argc, char* argv[])
  243. {
  244.   // check input
  245.   if (argc < 2) {
  246.     interp->result = 
  247.       "No scan passed to PlvCyberScanSelfAlignCmd";
  248.     return TCL_ERROR;
  249.   }
  250.   // get the actual CyberScan
  251.   DisplayableMesh* dm = FindMeshDisplayInfo (argv[1]);
  252.   if (!dm) {
  253.     interp->result = "Missing scan in PlvCyberScanSelfAlignCmd";
  254.     return TCL_ERROR;
  255.   }
  256.   CyberScan* scan = dynamic_cast<CyberScan*>(dm->getMeshData());
  257.   if (!scan) {
  258.     interp->result = 
  259.       "PlvCyberScanSelfAlignCmd: that's not a CyberScan!";
  260.     return TCL_ERROR;
  261.   }
  262.   vector< vector<CyberSweep*> > shells = 
  263.     scan->get_ordered_sweeps();
  264.   AutoICP<RigidScan*> self_align;
  265.   int i,j;
  266.   for (i = 0; i < shells.size(); i++) {
  267.     vector<CyberSweep*>& shell = shells[i];
  268.     for (j = 0; j < shell.size(); j++) {
  269.       if (j > 0) {
  270. // register with left neighbor
  271. self_align.add_pair (shell[j-1], shell[j]);
  272.       }
  273.       if (i > 0) {
  274. // register with back neighbor(s)
  275. vector<CyberSweep*>& shellPrev = shells[i-1];
  276. // pick upper bound for pass to be odd... 3, 5, 7
  277. for (int pass = 0; pass < 5; pass++) {
  278.   // generate offset sequence, 0, 1, -1, 2, -2, ...
  279.   int ofs = (pass + 1) / 2;
  280.   if (pass % 2) ofs = -ofs;
  281.   int jo = ofs + j;
  282.   if (jo < 0 || jo >= shellPrev.size())
  283.     continue;
  284.   
  285.   self_align.add_pair (shell[j], shellPrev[jo]);
  286. }
  287.       }
  288.     }
  289.   }
  290.   self_align();
  291.   // write the xforms
  292.   for (i = 0; i < shells.size(); i++) {
  293.     vector<CyberSweep*>& shell = shells[i];
  294.     for (j = 0; j < shell.size(); j++) {
  295.       if (!shell[j]->write_metadata(RigidScan::md_xform)) {
  296. cerr << "Couldn't write the xform for "
  297.      << shell[j]->get_name() << endl;
  298.       } else {
  299. cerr << "Saved xform for "
  300.      << shell[j]->get_name() << endl;
  301.       }
  302.     }
  303.   }
  304.   dm->invalidateCachedData(); // changed internal xforms
  305.   return TCL_OK;
  306. }
  307. int 
  308. ScnDumpLaserPntsCmd(ClientData clientData, 
  309.     Tcl_Interp *interp,
  310.     int argc, char* argv[])
  311. {
  312.   // check input
  313.   if (argc < 4) {
  314.     interp->result = 
  315.       "Usage: ScnDumpLaserPntsCmd scan_name filename nPts";
  316.     return TCL_ERROR;
  317.   }
  318.   // get the actual CyberScan
  319.   DisplayableMesh* dm = FindMeshDisplayInfo (argv[1]);
  320.   if (!dm) {
  321.     interp->result = "Missing scan in ScnDumpLaserPntsCmd";
  322.     return TCL_ERROR;
  323.   }
  324.   CyberScan* scan = dynamic_cast<CyberScan*>(dm->getMeshData());
  325.   if (!scan) {
  326.     interp->result = 
  327.       "ScnDumpLaserPntsCmd: that's not a CyberScan!";
  328.     return TCL_ERROR;
  329.   }
  330.   scan->dump_pts_laser_subsampled(argv[2], atoi(argv[3]));
  331.   return TCL_OK;
  332. }
  333. int 
  334. PlvDiceCyberDataCmd(ClientData clientData, 
  335.     Tcl_Interp *interp,
  336.     int argc, char* argv[])
  337. {
  338.   int numMeshes = theScene->meshSets.size();
  339.   int framesPerSweep = 256;
  340.   for (int i = 0; i < numMeshes; i++) {
  341.     DisplayableMesh *displayMesh = theScene->meshSets[i];
  342.     if (!displayMesh->getVisible())
  343.       continue;
  344.       
  345.     RigidScan *sd = displayMesh->getMeshData();
  346.     CyberScan* cs = dynamic_cast<CyberScan*> (sd);
  347.     if (!cs)
  348.       continue;
  349.       
  350.     vector<CyberSweep*> sweeps = cs->get_sweep_list();
  351.     for (int j=0; j < sweeps.size(); j++) {
  352.       CyberSweep *sweep = sweeps[j];
  353.       int numSubSweeps = (sweep->num_frames()-1)/framesPerSweep + 1;
  354.       for (int k = 0; k < numSubSweeps; k++) {
  355. int frameStart = k*framesPerSweep;
  356. int frameFinish = MIN(sweep->num_frames()-1,
  357.       (k+1)*framesPerSweep+33);
  358.       
  359. // newmesh mode... makes a new mesh and adds it to Mesh Controls
  360. // filtered_copy will return NULL if not supported; will return
  361. // valid pointer to scan with no resolutions if the clip excludes
  362. // all data.
  363. cout << frameStart << "  "  << frameFinish << endl;
  364. DisplayableMesh *oldDisp = displayMesh;
  365. RigidScan *meshFrom = sd;
  366. RigidScan *meshTo = cs->get_piece(j, frameStart, frameFinish);
  367. if (meshTo) {
  368.   if (meshTo->num_resolutions() > 0) {
  369.     char tmpstr[PATH_MAX];
  370.     crope name;
  371.     sprintf(tmpstr, "%d", j);
  372.     name = meshFrom->get_basename() + "_" + tmpstr;
  373.     sprintf(tmpstr, "%d", k);
  374.     name = name + "_" + tmpstr + "." + meshFrom->get_nameending();
  375.     meshTo->set_name(name);
  376.     
  377.     DisplayableMesh* newDisp = theScene->addMeshSet (meshTo, false);
  378.     Tcl_VarEval (interp, "clipMeshCreateHelper ",
  379.  oldDisp->getName(), " ", newDisp->getName(), NULL);
  380.   } else {
  381.     // scan supports clipping, but had no data
  382.     Tcl_VarEval (interp, "changeVis ", 
  383.  oldDisp->getName(), " 0", NULL);
  384.   }
  385. }
  386.       }      
  387.     }
  388.   }
  389.   return TCL_OK;  
  390. }
  391. int
  392. PlvWorkingVolumeCmd(ClientData clientData, Tcl_Interp *interp, 
  393.                     int argc, char *argv[])
  394. {
  395.   CyberWorkingVolume *cwv = GetCyberWorkingVolume();
  396.   if        (argc==2 && !strcmp(argv[1], "off"))  {
  397.     cwv->off();
  398.   } else if (argc==2 && !strcmp(argv[1], "on"))  {
  399.     cwv->on();
  400.   } else if (argc==2 && !strcmp(argv[1], "solid"))  {
  401.     cwv->drawMode(0);
  402.   } else if (argc==2 && !strcmp(argv[1], "lines"))  {
  403.     cwv->drawMode(1);
  404.   } else if (argc==3 && !strcmp(argv[1], "use"))  {
  405.     cwv->use((FindMeshDisplayInfo(argv[2]))->getMeshData());
  406.   } else if (argc == 9)  {
  407.     cwv->bounds(atof(argv[1]), atof(argv[2]), atof(argv[3]), atof(argv[4]),
  408. atof(argv[5]), atof(argv[6]), atof(argv[7]), atof(argv[8]));
  409.   } else {
  410.     interp->result = "Bad arguments to plv_working_volume";
  411.     return TCL_ERROR;
  412.   }
  413.   return TCL_OK;
  414. }
  415. int
  416. PlvWorldCoordToSweepCoord(ClientData clientData, Tcl_Interp *interp, 
  417.                     int argc, char *argv[])
  418. {
  419.   if (argc!=5) {
  420.     // Usage
  421.     Tcl_SetResult(interp,"Usage: plv_worldCoordToSweepCoord scanname x y zn  returns four numbers that can be used to resontruct a new world coord n  after callibration or realignment.n",TCL_STATIC);
  422.     return TCL_ERROR;
  423.   }
  424.   // Get args
  425.   char *scanname = argv[1];
  426.   Pnt3 worldPt(atof(argv[2]),atof(argv[3]),atof(argv[4]));
  427.   Pnt3 scanPt;
  428.   int sweepInd;
  429.   Pnt3 newWpt;
  430.   
  431.   // Get scan reference
  432.   RigidScan *rs = FindMeshDisplayInfo(scanname)->getMeshData();
  433.   CyberScan* cs = dynamic_cast<CyberScan*> (rs);
  434.   if (!cs) {
  435.     Tcl_SetResult(interp,"Specified mesh is not a CyberScan",TCL_STATIC);
  436.     return TCL_ERROR;
  437.   }
  438.   
  439.   // Call dk's function
  440.   bool res = cs->worldCoordToSweepCoord(worldPt,&sweepInd, scanPt);
  441.   // cout << "World::n" << worldPt << "nScan:n" << scanPt << "n";
  442.   
  443.   // Return results
  444.   if (res) {
  445.     sprintf(interp->result,"%d %f %f %f",sweepInd, (float)scanPt[0],
  446.     (float)scanPt[1], (float)scanPt[2]);
  447.   } else {
  448.     Tcl_SetResult(interp,"Did not find a sweep containing the Pt.",TCL_STATIC);
  449.   }
  450.   
  451.   cs->sweepCoordToWorldCoord(sweepInd, scanPt, newWpt);
  452.   // cout << "World::n" << newWpt << "nScan:n" << scanPt << "n" << flush;
  453.   return TCL_OK;
  454.   
  455. }
  456. int
  457. PlvSweepCoordToWorldCoord(ClientData clientData, Tcl_Interp *interp, 
  458.                     int argc, char *argv[])
  459. {
  460.   // Usage
  461.   if (argc!=6) {
  462.     Tcl_SetResult(interp,"Usage: plv_sweepCoordToWorldCoord scanname sweepindex val1 val2 val3",TCL_STATIC);
  463.     return TCL_ERROR;
  464.   }
  465.   // Get args
  466.   char *scanname = argv[1];
  467.   int sweepInd = atoi(argv[2]);
  468.   Pnt3 scanPt(atof(argv[3]),atof(argv[4]),atof(argv[5]));
  469.   Pnt3 newWpt;
  470.   // Get scan reference
  471.   RigidScan *rs = FindMeshDisplayInfo(scanname)->getMeshData();
  472.   CyberScan* cs = dynamic_cast<CyberScan*> (rs);
  473.   if (!cs) {
  474.     Tcl_SetResult(interp,"Specified mesh is not a CyberScan",TCL_STATIC);
  475.     return TCL_ERROR;
  476.   }
  477.   // Call dk's function
  478.   cs->sweepCoordToWorldCoord(sweepInd, scanPt, newWpt);
  479.   // cout << "World::n" << newWpt << "nScan:n" << scanPt << "n" << flush;
  480.   // Return results
  481.   sprintf(interp->result,"%f %f %f",(float)newWpt[0],
  482.   (float)newWpt[1],(float)newWpt[2]);
  483.   return TCL_OK;
  484. }