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
00011 void usage(char* prog);
00012 int parse(int argc, char** argv, ViewerInfo *vi, CurveInfo *ci);
00013
00014
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
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
00036 TubeBundle<Vector3>* Knot;
00037
00038
00039 int N, S;
00040
00041 float R, Tol;
00042
00043 int Closed;
00044
00045 QStringList filenames;
00046
00047
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
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
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
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
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
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
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
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
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
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
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
00284
00285
00286
00287
00288 info.N = (*(info.Knot))[0].nodes();
00289
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
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
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
00356
00357
00358 }
00359
00360
00361
00362
00363
00364 if (1) {
00365
00366 material_bindings[i] = new SoMaterialBinding;
00367
00368 knot_node[i]->addChild(material_bindings[i]);
00369 }
00370 knot_node[i]->addChild(materials[i]);
00371
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
00399
00400
00401