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

3D图形编程

开发平台:

Visual C++

  1. //############################################################
  2. // TbObj.cc
  3. // Kari Pulli
  4. // Tue Jun 30 11:10:13 PDT 1998
  5. //
  6. // A base class for objects that are moved using the trackball
  7. //############################################################
  8. #include <stdlib.h>
  9. #include <time.h>
  10. #include "FileNameUtils.h"
  11. #include "TbObj.h"
  12. #include "Trackball.h"
  13. #include "plvGlobals.h"
  14. vector<TbObj::TbRedoInfo> TbObj::undo_stack;
  15. int TbObj::real_size = 0;
  16. TbObj::TbObj(void)
  17. {
  18.   
  19. }
  20. const int UNDO_SIZE = 400;
  21. TbObj::~TbObj(void)
  22. {
  23.   // remove instances of myself from the undo_stack
  24.   clear_undo (this);
  25. }
  26. Pnt3
  27. TbObj::worldCenter(void)
  28. {
  29.   Pnt3 wctr = rot_ctr;
  30.   xf(wctr);
  31.   return wctr;
  32. }
  33. Bbox
  34. TbObj::worldBbox(void)
  35. {
  36.   return bbox.worldBox(xf);
  37. }
  38. float
  39. TbObj::radius(void)
  40. {
  41.   return bbox.max_dist(rot_ctr);
  42. }
  43. #if 1
  44. #define __DUMP
  45. #else
  46. #define __DUMP  { 
  47.   cout << "dump start" << endl; 
  48.   for (int i = 0; i < real_size; i++) { 
  49.     cout << undo_stack[i].self << ": " << undo_stack[i].xf << endl; 
  50.   } 
  51.   cout << "-- break -- " << endl; 
  52.   for (; i < undo_stack.size(); i++) { 
  53.     cout << undo_stack[i].self << ": " << undo_stack[i].xf << endl; 
  54.   } 
  55.   cout << "dump end" << endl << endl; 
  56. }
  57. #endif
  58. void
  59. TbObj::save_for_undo(void)
  60. {
  61.   // CAREFUL: 'this' pointer could be NULL, indicating trackball itself!
  62.   // no more redo's
  63.   if (real_size != undo_stack.size()) {
  64.     undo_stack.erase(&undo_stack[real_size], undo_stack.end());
  65.   }
  66.   assert(real_size == undo_stack.size());
  67.   if (real_size >= UNDO_SIZE) {
  68.     // forget the 100 first xforms
  69.     undo_stack.erase(undo_stack.begin(), &undo_stack[100]);
  70.   }
  71.   // create the entry
  72.   TbRedoInfo a; a.self = this; 
  73.   a.xf = this ? this->xf : tbView->getUndoXform();
  74.   // save the entry
  75.   undo_stack.push_back(a);
  76.   real_size = undo_stack.size();
  77.   __DUMP;
  78. }
  79. void
  80. TbObj::undo(void)
  81. {
  82.   if (real_size == 0) return;
  83.   assert(real_size > 0);
  84. #if 0
  85.   if (real_size == undo_stack.size()) {
  86.     // if the first undo, save the current situation first
  87.     undo_stack.back().self->save_for_undo();
  88.     real_size--;
  89.   }
  90. #endif
  91.   real_size--;
  92.   TbRedoInfo &info = undo_stack[real_size];
  93.   // careful, info.self could be NULL
  94.   Xform<float> tmp;
  95.   if (info.self) {
  96.     tmp = info.self->xf;
  97.     info.self->xf = info.xf;
  98.   } else {
  99.     tmp = tbView->getUndoXform();
  100.     tbView->setUndoXform (info.xf);
  101.   }
  102.   info.xf = tmp;
  103.   __DUMP;
  104. }
  105. void
  106. TbObj::redo(void)
  107. {
  108.   if (real_size < undo_stack.size()) {
  109.     TbRedoInfo &info = undo_stack[real_size];
  110.     real_size++;
  111.     // careful, info.self could be NULL
  112.     Xform<float> tmp;
  113.     if (info.self) {
  114.       tmp = info.self->xf;
  115.       info.self->xf = info.xf;
  116.     } else {
  117.       tmp = tbView->getUndoXform();
  118.       tbView->setUndoXform (info.xf);
  119.     }
  120.     info.xf = tmp;
  121.   }
  122.   __DUMP;
  123. }
  124. void
  125. TbObj::clear_undo (TbObj* objToRemove)
  126. {
  127.   if (objToRemove) {
  128.     int top = 0;
  129.     for (int i=0; i<real_size; i++) {
  130.       if (undo_stack[i].self != objToRemove) {
  131. undo_stack[top++] = undo_stack[i];
  132.       }
  133.     }
  134.     real_size = top;
  135.     undo_stack.erase(&undo_stack[real_size], undo_stack.end());
  136.   } else {
  137.     // clear all
  138.     undo_stack.clear();
  139.     real_size = 0;
  140.   }
  141. }
  142. void 
  143. TbObj::rotate(float q0, float q1, float q2, float q3,
  144.       bool undoable)
  145. {
  146.   if (undoable) save_for_undo();
  147.   Pnt3 wc = worldCenter();
  148.   xf.translate(-wc[0], -wc[1], -wc[2]);
  149.   xf.rotQ(q0, q1, q2, q3);
  150.   xf.translate(wc);
  151. }
  152. void
  153. TbObj::translate(float t0, float t1, float t2,
  154.  bool undoable)
  155. {
  156.   if (undoable) save_for_undo();
  157.   xf.translate(t0,t1,t2);
  158. }
  159. void 
  160. TbObj::new_rotation_center(const Pnt3 &wc)
  161. {
  162.   // have to apply inverse transformation because
  163.   // the rotation center is in local coordinates!
  164.   xf.apply_inv(wc, rot_ctr);
  165. }
  166. Xform<float>
  167. TbObj::getXform(void) const
  168. {
  169.   return xf;
  170. }
  171. void
  172. TbObj::setXform(const Xform<float> &x, bool undoable)
  173. {
  174.   if (undoable) save_for_undo();
  175.   xf = x;
  176. }
  177. bool
  178. TbObj::readXform(istream& in)
  179. {  
  180.   save_for_undo();
  181.   in >> xf;
  182.   return (!in.fail());
  183. }
  184. bool
  185. TbObj::writeXform(ostream& out)
  186. {
  187.   out << xf;
  188.   return !out.fail();
  189. }
  190. void
  191. TbObj::resetXform(void)
  192.   save_for_undo();
  193.   xf.identity();
  194. }
  195. bool
  196. TbObj::readXform(const crope& baseFile)
  197. {
  198.   crope name = (baseFile + ".xf");
  199.   ifstream istr (name.c_str(), ios::in | ios::nocreate);
  200.   bool success = readXform(istr);
  201.   if (success)
  202.     cout << "Read xform " << name << endl;
  203.   //save_for_undo(); // already done by the other reader
  204.   return success;
  205. }
  206. bool
  207. TbObj::writeXform (const crope& baseFile)
  208. {
  209.   crope name = (baseFile + ".xf");
  210.   // find out whether the file exists already
  211.   // and is readable
  212.   if (access(name.c_str(), R_OK) == 0) {
  213.     // append to the backup file, change also access mode
  214.     crope buname = name + ".bu";
  215.     chmod (buname.c_str(), 0664);
  216.     crope tmpfile = buname + ".tmp";      
  217.     unlink(tmpfile.c_str());
  218.     FILE* to = fopen (tmpfile.c_str(), "w");
  219.     
  220.     FILE* from = fopen (buname.c_str(), "r");
  221.     bool problem = false;
  222.     if (from) {
  223.       if (to) {
  224. int ch;
  225. while ((ch = getc(from)) != EOF) {
  226.   putc(ch, to);
  227. }
  228.       } else {
  229. problem |= true;
  230.       }
  231.       fclose(from);
  232.     }
  233.     
  234.     time_t t;
  235.     fprintf(to, "%s", asctime(localtime (&t)));
  236.       
  237.     from = fopen(name.c_str(), "r");
  238.     if (from) {
  239.       char buf[2000];
  240.       int r = fread (buf, 1, 2000, from);
  241.       problem |= (r != fwrite (buf, 1, r, to));
  242.       fclose(from);      
  243.       fclose(to);
  244.     }
  245.     unlink(buname.c_str());
  246.     if (0 == rename(tmpfile.c_str(), buname.c_str())) {
  247.       chmod (buname.c_str(), 0664);
  248.     } else {
  249.       problem |= true;
  250.     }
  251.     if (problem) {
  252.       cerr << "Problem updating backup " << buname << endl;
  253.     } else {
  254.       cerr << "Appended " << name << " to " << buname << endl;
  255.     }
  256.   } else {
  257.     cerr << "No previous xform file " << name << endl;
  258.   }
  259.   
  260.   cerr << "Writing xform to " << name << " ... " << flush;
  261.   // delete the file first so the owner changes
  262.   unlink(name.c_str()); 
  263.   ofstream ostr (name.c_str());
  264.   bool success = TbObj::writeXform(ostr);
  265.   cout << (success ? "ok" : "fail") << "." << endl;
  266.   if (success) {
  267.     // change the permissions...
  268.     chmod (name.c_str(), 0664);
  269.   }
  270.   return success;
  271. }