utils.h

00001 #ifndef _UTILS_H_
00002 #define _UTILS_H_
00003 
00004 #include "main.h"
00005 #include "../fourierknots/fourier_syn.h"
00006 #include <QStringList>
00007 
00008 struct CurveInfo;
00009 
00010 // General Sutff
00011 void usage(char* prog);
00012 int parse(int argc, char** argv, ViewerInfo *vi, CurveInfo *ci);
00013 
00014 // GFX Stuff
00015 void addBezierCurve(SoSeparator *root, Tube<Vector3>* t, bool BLACK = false);
00016 SoSeparator* drawCircle(const Vector3& p0, const Vector3& t0, const Vector3& p1, bool BLACK = false);
00017 
00018 // Frame Normal generation helpers
00019 void frenet_frame_normals(Tube<Vector3>* t, Vector3* nor, int FRENET = 0);
00020 void parallel_frame_normals(Tube<Vector3>* t, Vector3* nor, float TwistSpeed = 0.);
00021 void parallel_ode_frame_normals(Tube<Vector3>* t, Vector3* Normals);
00022 void writhe_frame_normals(Tube<Vector3>* t, Vector3* Normals);
00023 void writhe_ode_frame_normals(Tube<Vector3>* t, Vector3* Normals);
00024 
00034 struct CurveInfo {
00035   // Knot information
00036   TubeBundle<Vector3>* Knot;
00037 
00038   // Nodes, Segments
00039   int N, S;
00040   // Radius, Frame Tolerance
00041   float R, Tol;
00042   
00043   int Closed;
00044   
00045   QStringList filenames;
00046   
00047   // 3D
00048   uint TEXTURES;
00049   QString texture_file;
00050 };
00051 
00057 class CurveInterface {
00058   
00059 public:
00060   
00061   CurveInterface() : graph_node(0), frame_node(0) {}
00062   
00063   struct CurveInfo info;
00064   
00065   // Viewer and Coin
00066   SoSeparator **knot_node;
00067   SoKnot **knot_shape;
00068   SoMaterialBinding **material_bindings;
00069   SoMaterial **materials;
00070   SoTexture2 *knot_texture;
00071 
00072   SoSeparator *graph_node;
00073   SoSeparator *frame_node;
00074 
00075 public slots:
00076   int save();
00077   int exportIV();
00078   int exportRIB();
00079   int exportPOV();
00080 
00081   void decreaseTransparency() {
00082     float transp = materials[0]->transparency[0] + 0.05;
00083     if (transp>1.0) transp = 1.0;
00084     for (int i=0;i<info.Knot->tubes();i++) {
00085       materials[i]->transparency = transp;
00086     }
00087   }
00088 
00089   void increaseTransparency() {
00090     float transp = materials[0]->transparency[0] - 0.05;
00091     if (transp<0.0) transp = 0.0;
00092     for (int i=0;i<info.Knot->tubes();i++) {
00093       materials[i]->transparency = transp;
00094     }
00095   }
00096 
00097   void increaseRadius() {
00098     for (int i=0;i<info.Knot->tubes();i++)
00099       knot_shape[i]->radius = knot_shape[i]->radius.getValue()*1.1;
00100 //    cout << "Radius : " << knot_shape[0]->radius.getValue() << endl;
00101   }
00102 
00103   void decreaseRadius() {
00104     for (int i=0;i<info.Knot->tubes();i++)
00105       knot_shape[i]->radius = knot_shape[i]->radius.getValue()*0.9;
00106 //    cout << "Radius : " << knot_shape[0]->radius.getValue() << endl;
00107   }
00108 
00109   void increaseSegments() {
00110     int tS = knot_shape[0]->segments.getValue()+1;
00111     if (tS>120) {
00112       cerr << "Warning : more than 120 segments requested. Set to 120!\n";
00113       tS = 120;
00114     }
00115     for (int i=0;i<info.Knot->tubes();i++)
00116       knot_shape[i]->segments.setValue(tS);
00117     // cout << "Segments : " << tS << endl;
00118   }
00119 
00120   void decreaseSegments() {
00121     int tS = knot_shape[0]->segments.getValue()-1;
00122     if (tS<3) {
00123       cerr << "Warning : more than 120 segments requested. Set to 120!\n";
00124       tS = 3;
00125     }
00126     for (int i=0;i<info.Knot->tubes();i++)
00127       knot_shape[i]->segments.setValue(tS);
00128     // cout << "Segments : " << tS << endl;
00129   }
00130 
00131   void setNumberOfNodes(int N) {
00132     for (int i=0;i<info.Knot->tubes();i++)
00133       knot_shape[i]->nodes.setValue(N);
00134   }
00135 
00136   SoSeparator* frame(int FRAME = 0) {
00137     
00138     Tube<Vector3>* t = knot_shape[0]->getKnot();
00139     float rad = knot_shape[0]->radius.getValue();
00140 
00141     // Construct Frenet Frame using fourier representation
00142     SoSeparator *frenet = new SoSeparator;
00143     SoSeparator *sep_tangents  = new SoSeparator;
00144     SoSeparator *sep_normals   = new SoSeparator;
00145     SoSeparator *sep_binormals = new SoSeparator;
00146     frenet->addChild(sep_tangents);
00147     frenet->addChild(sep_normals);
00148     frenet->addChild(sep_binormals);
00149 
00150     // Materials
00151     SoMaterial *ma_t = new SoMaterial, *ma_n = new SoMaterial, *ma_b = new SoMaterial;
00152 
00153     ma_t->diffuseColor.setValue(1,0,0); sep_tangents->addChild(ma_t);
00154     ma_n->diffuseColor.setValue(0,1,0); sep_normals->addChild(ma_n);
00155     ma_b->diffuseColor.setValue(0,0,1); sep_binormals->addChild(ma_b);
00156 
00157     SoCoordinate3 *co_tangents  = new SoCoordinate3;
00158     SoCoordinate3 *co_normals   = new SoCoordinate3; 
00159     SoCoordinate3 *co_binormals = new SoCoordinate3;
00160 
00161     SoLineSet *ls_tangents  = new SoLineSet;
00162     SoLineSet *ls_normals   = new SoLineSet;
00163     SoLineSet *ls_binormals = new SoLineSet;
00164 
00165     sep_tangents->addChild(co_tangents);   sep_tangents->addChild(ls_tangents);
00166     sep_normals->addChild(co_normals);     sep_normals->addChild(ls_normals);
00167     sep_binormals->addChild(co_binormals); sep_binormals->addChild(ls_binormals);
00168 
00169     Vector3* Normals = new Vector3[t->nodes()];
00170     switch(FRAME) {
00171       case 0:
00172         frenet_frame_normals(t,Normals,0);
00173         break;
00174       case 1:
00175         frenet_frame_normals(t,Normals,1);
00176         break;
00177       case 2:
00178         parallel_frame_normals(t,Normals);
00179         break;
00180       case 3:
00181         parallel_ode_frame_normals(t,Normals);
00182         break;
00183       case 4:
00184         writhe_frame_normals(t,Normals);
00185         break;
00186       case 5:
00187         writhe_ode_frame_normals(t,Normals);
00188         break;
00189     }
00190 
00191     float scale = 2.*rad;
00192     Vector3 pt, tan, nor, bin, vec;
00193     for (int i=0;i<t->nodes();++i) {
00194       pt  = (*t)[i].getPoint();
00195       tan = (*t)[i].getTangent();
00196       nor = Normals[i];
00197       bin = Normals[i].cross(tan);   bin.normalize();
00198 
00199       co_tangents->point.set1Value(2*i,SbVec3f(pt[0],pt[1],pt[2]));
00200       vec = pt+scale*tan;
00201       co_tangents->point.set1Value(2*i+1,SbVec3f(vec[0],vec[1],vec[2]));
00202 
00203       co_normals->point.set1Value(2*i,SbVec3f(pt[0],pt[1],pt[2]));
00204       vec = pt+scale*nor;
00205       co_normals->point.set1Value(2*i+1,SbVec3f(vec[0],vec[1],vec[2]));
00206 
00207       co_binormals->point.set1Value(2*i,SbVec3f(pt[0],pt[1],pt[2]));
00208       vec = pt+scale*bin;
00209       co_binormals->point.set1Value(2*i+1,SbVec3f(vec[0],vec[1],vec[2]));
00210 
00211       ls_tangents->numVertices.set1Value(i,2);
00212       ls_normals->numVertices.set1Value(i,2);
00213       ls_binormals->numVertices.set1Value(i,2);
00214     }
00215     return frenet;
00216   }
00217 
00218 
00219 
00220 public:
00221   
00222   void clear() { info.Knot = NULL; }
00223 
00228   void makeMesh() {
00229     // cout << "Generate mesh for all curves"<<flush;
00230     if (info.Closed)
00231        for (int i=0;i<info.Knot->tubes();++i)
00232          (*(info.Knot))[i].link();
00233     info.Knot->makeMesh(info.N,info.S,info.R,info.Tol);
00234     // cout << "\t[OK]\n";
00235   }
00236 
00241   SoSeparator* load() {
00242     clear();
00243     if (info.Knot==NULL) info.Knot = new TubeBundle<Vector3>;
00244 
00245     int count = 0;
00246     for (int i = 0; i < info.filenames.size(); ++i) {
00247       cout << "Read file : " << info.filenames.at(i).toLocal8Bit().constData() << endl;
00248       // Guess PKF or VECT
00249       if (info.filenames.at(i).endsWith(".pkf") ||
00250           info.filenames.at(i).endsWith(".PKF")) {
00251         if (!info.Knot->readPKF((const char*)(info.filenames.at(i).toLocal8Bit().constData())))
00252           cout << "! Could not load " << (const char*)(info.filenames.at(i).toLocal8Bit()) << endl;
00253         else count++;
00254       }
00255       else if (info.filenames.at(i).endsWith(".xyz") ||
00256                info.filenames.at(i).endsWith(".XYZ")) {
00257         if (!info.Knot->readXYZ((const char*)(info.filenames.at(i).toLocal8Bit().constData())))
00258           cout << "! Could not load " << (const char*)(info.filenames.at(i).toLocal8Bit()) << endl;
00259         else count++;
00260       }
00261       else if (info.filenames.at(i).endsWith(".vect") ||
00262                info.filenames.at(i).endsWith(".VECT")) {
00263         CurveBundle<Vector3> cb;
00264         if (!cb.readVECT(info.filenames.at(i).toLocal8Bit().constData()))
00265           cout << "! Could not load " << (const char*)(info.filenames.at(i).toLocal8Bit()) << endl;
00266 
00267         else {
00268           for (int k=0;k<cb.curves();++k) {
00269             cb[k].computeTangents();
00270             info.Knot->newTube(Tube<Vector3>(cb[k]));
00271             count++;
00272           }
00273         }
00274       }
00275       else {
00276         cerr << "[Warn] Unknown filetype. Skip!\n";
00277         continue;
00278       }
00279     }
00280     
00281     if (count==0) return NULL;
00282        
00283     // FIXME
00284     // We arbitrarily choose for N the number of datapoints of the first curve
00285     // It would be reasonnable to include the option to show exactly what
00286     // is in the data file
00287 //    if (!info.N)
00288       info.N = (*(info.Knot))[0].nodes();
00289 //      info.R = (*(info.Knot))[0].thickness_fast()/20.;
00290 
00291     makeMesh();
00292     return curveSeparator();
00293   }
00294     
00295   void dumpInfo() {
00296     if (info.Knot->tubes()<=0) {
00297       cout << "No knot initialized.\n";
00298       return;
00299     }
00300     cout << "Curves    : "<< info.Knot->tubes() << endl;
00301     for (int i=0;i<info.Knot->tubes();i++) {
00302       cout << "Curve " << i+1 << endl;
00303       cout << "Nodes     : "<< (*(info.Knot))[i].nodes() << endl;
00304       cout << "Segments  : "<< (*(info.Knot))[i].segments() << endl;
00305       cout << "Radius    : "<< (*(info.Knot))[i].radius() << endl;
00306                         cout << "Length    : "<< (*(info.Knot))[i].length() << endl;
00307     }
00308     cout << "Tolerance : " << info.Tol << endl;
00309     if ((*(info.Knot))[0].isClosed()) cout << "Closed curves!\n";
00310     cout << "Files : ";
00311     for (int i = 0; i < info.filenames.size(); ++i)
00312        cout << info.filenames.at(i).toLocal8Bit().constData()
00313             << (info.filenames.size()==i+1?"":", ");
00314     cout << endl;
00315   }
00316   
00317   SoSeparator* curveSeparator() {
00318     if (graph_node) {
00319       cout << "CurveInterface::curveSeparator : [Warn]"
00320            << " There seems to be an already existing "
00321            << "curve graph node! Doing nothing.\n";
00322       return graph_node;
00323     }
00324     
00325     this->graph_node = new SoSeparator;
00326 
00327     // Prepare texture for for knot(s)
00328     if (info.TEXTURES) {
00329       knot_texture = new SoTexture2;
00330       knot_texture->filename.setValue((const char*)info.texture_file.toLocal8Bit().constData());
00331       graph_node->addChild(knot_texture);
00332       cout << "Texture node added (" << info.texture_file.toLocal8Bit().constData() << ")\n";
00333     }
00334     
00335     // cout << "Create " << info.Knot->tubes() << " SoKnot objects";
00336     knot_shape = new SoKnot*[info.Knot->tubes()];
00337     knot_node = new SoSeparator*[info.Knot->tubes()];
00338     materials = new SoMaterial*[info.Knot->tubes()];
00339     material_bindings = new SoMaterialBinding*[info.Knot->tubes()];
00340 
00341     for (int i=0;i<info.Knot->tubes();i++) {
00342       (*(info.Knot))[i].make_default();
00343       knot_shape[i] = new SoKnot;
00344       knot_node[i] = new SoSeparator;
00345 
00346       knot_shape[i]->setKnot( &((*(info.Knot))[i]), (*(info.Knot))[i].isClosed()?info.Tol:-1 );
00347       knot_shape[i]->radius.setValue(info.R);
00348       knot_shape[i]->segments.setValue(info.S);
00349       knot_shape[i]->nodes.setValue(info.N);
00350 
00351       materials[i] = new SoMaterial;
00352       for (int z=0;z<(*(info.Knot))[i].nodes()-((*(info.Knot))[i].isClosed()?0:1);z++) {
00353         materials[i]->diffuseColor.set1Value(z,ColorTable[i%ColorNum]);
00354   /*
00355         materials[i]->diffuseColor.set1Value(z,ColorTable[ColorIdx]);
00356           ColorIdx=((ColorIdx+1)%ColorNum);
00357     */
00358       }
00359         // Mark beginning of curve!
00360     //    materials[i]->diffuseColor.set1Value(0,ColorTable[1]);
00361 
00362 //      materials[i]->transparency = transp;
00363 
00364       if (1) {
00365         // Material bundle
00366         material_bindings[i] = new SoMaterialBinding;
00367         // material_bindings[i]->value = SoMaterialBinding::PER_PART;
00368         knot_node[i]->addChild(material_bindings[i]);
00369       }
00370       knot_node[i]->addChild(materials[i]);
00371       //addBezierCurve(root,&(*Knot)[i]);
00372       knot_node[i]->addChild(knot_shape[i]);
00373 #if 0 // SPHERE_END
00374       if (!(*(info.Knot))[i].isClosed()) {
00375         SoTranslation *tr = new SoTranslation;
00376         SoTranslation *tr2 = new SoTranslation;
00377         tr->translation.setValue((SbVec3f&)((*(info.Knot))[i][0].getPoint()[0]));
00378         tr2->translation.setValue((SbVec3f&)((*(info.Knot))[i][(*(info.Knot))[i].nodes()-1].getPoint()[0]));
00379         SoSphere *sp = new SoSphere;
00380         sp->radius = info.R;
00381         SoSeparator *sep1 = new SoSeparator;
00382         knot_node[i]->addChild(sep1);
00383         SoSeparator *sep2 = new SoSeparator;
00384         knot_node[i]->addChild(sep2);
00385         sep1->addChild(tr);
00386         sep1->addChild(sp);
00387         sep2->addChild(tr2);
00388         sep2->addChild(sp);
00389       }
00390 #endif
00391       graph_node->addChild(knot_node[i]);
00392     }
00393     cout << "graph_node : " << graph_node << endl;
00394     return graph_node;
00395   }
00396 };
00397 
00398 #endif /* _UTILS_H_ */
00399 
00400 
00401 

Generated on Mon Feb 8 17:22:35 2010 for libbiarc by  doxygen 1.5.6