From e70ba0202b4e319e5f54ff559309c2c91fb22d74 Mon Sep 17 00:00:00 2001 From: Paolo Cignoni cignoni Date: Wed, 21 Apr 2010 15:12:35 +0000 Subject: [PATCH] io_renderman plugin --- src/sampleplugins/io_m/RibFileStack.cpp | 216 +++++++ src/sampleplugins/io_m/RibFileStack.h | 36 ++ src/sampleplugins/io_m/export_rib.h | 240 ++++++++ src/sampleplugins/io_m/io_renderman.cpp | 231 ++++++++ src/sampleplugins/io_m/io_renderman.h | 81 +++ src/sampleplugins/io_m/io_renderman.pro | 14 + src/sampleplugins/io_m/parser_rib.cpp | 536 ++++++++++++++++++ src/sampleplugins/io_m/ribProcedure.h | 191 +++++++ src/sampleplugins/io_m/utilities_hqrender.cpp | 79 +++ src/sampleplugins/io_m/utilities_hqrender.h | 12 + 10 files changed, 1636 insertions(+) create mode 100644 src/sampleplugins/io_m/RibFileStack.cpp create mode 100644 src/sampleplugins/io_m/RibFileStack.h create mode 100644 src/sampleplugins/io_m/export_rib.h create mode 100644 src/sampleplugins/io_m/io_renderman.cpp create mode 100644 src/sampleplugins/io_m/io_renderman.h create mode 100644 src/sampleplugins/io_m/io_renderman.pro create mode 100644 src/sampleplugins/io_m/parser_rib.cpp create mode 100644 src/sampleplugins/io_m/ribProcedure.h create mode 100644 src/sampleplugins/io_m/utilities_hqrender.cpp create mode 100644 src/sampleplugins/io_m/utilities_hqrender.h diff --git a/src/sampleplugins/io_m/RibFileStack.cpp b/src/sampleplugins/io_m/RibFileStack.cpp new file mode 100644 index 000000000..a6a5538a6 --- /dev/null +++ b/src/sampleplugins/io_m/RibFileStack.cpp @@ -0,0 +1,216 @@ +#include "RibFileStack.h" + +RibFileStack::RibFileStack(QString dir) { + ribProc = ribParser::initHash(); //hash of rib procedure + stack = new QStack< QPair* >(); + templateDir = dir; + subDir.append("."); //to search in the same dir +}; + +RibFileStack::~RibFileStack() { + delete ribProc; + while(!stack->isEmpty()) + popFile(); //close all file + delete stack; //it's enough? +}; + +//open file and push the text stream to stack +bool RibFileStack::pushFile(QString path) { + if(QFile::exists(path)) { + QFile* file = new QFile(path); + return pushFile(file); + } else { + return false; + } +}; + +bool RibFileStack::pushFile(QFile* file) { + //add file to stack and open it + if(!(*file).open(QIODevice::ReadOnly)) { + return false; + } + QTextStream* stream = new QTextStream(file); + QPair* p = new QPair(file, stream); + stack->push(p); + if(stack->count() == 1) { //if it's the first prepare next line + bool end; + nextLine = topNextLine(&end); + nextLineType = isRibProcedure(nextLine); + } + return true; +}; + +//close file and pop from stack +bool RibFileStack::popFile() { + if(stack->isEmpty()) + return false; + + QPair* p = stack->pop(); + (*(p->first)).close(); + return true; +}; + +//return the next line from file at top of stack +//if it's the end of this file, pop it and take the line of next +QString RibFileStack::topNextLine(bool* end) { + if(stack->isEmpty()) { + *end = true; + return ""; + } + //take the top element from stack + QPair* p = stack->top(); + //the stream of file + QTextStream* s = (p->second); + if(!s->atEnd()) { + *end = false; + QString str = s->readLine(); + if(str == "") + return topNextLine(end); //ignore empty line + else + return str; + } else { + //close and remove from stack the file + popFile(); + //recursive call (the top is changed) + return topNextLine(end); + } +}; + +//return the next statement of file stack (maybe on more line) +QString RibFileStack::nextStatement(int* type, bool manageReadArchive) { + if(nextLine == "") { + bool end = false; + nextLine = topNextLine(&end); + if(end) { + *type = ribParser::NOMORESTATEMENT; + return nextLine; //no more line to be readable + } + else + *type = isRibProcedure(nextLine); + } + QString str = nextLine; //nextline is a rib procedure + *type = nextLineType; + + if(*type == ribParser::READARCHIVE) { + //qDebug("is a ReadArchive"); + QStringList token = ribParser::splitStatement(&str); + //0: ReadArchive, + //1: " , + //2: , + //3: " + bool end; + while(token.size() < 4 && !end) { + QString line = topNextLine(&end); + str += " " + line; + token = ribParser::splitStatement(&str); + } + if(manageReadArchive) { + if(readArchive(str)) { //add the new file to stack + nextLine = topNextLine(&end); + nextLineType = isRibProcedure(nextLine); + //qDebug("Readed: %s Type: %d",qPrintable(str), *type); + //qDebug("nextline: %s type: %d",qPrintable(nextLine),nextLineType); + return nextStatement(type, manageReadArchive); //read the first line of new file, if found it + } + else { + nextLine = ""; + nextLineType = ribParser::NOMORESTATEMENT; + return str; + } + } + else { + nextLine = ""; + nextLineType = ribParser::NOMORESTATEMENT; + return str; + } + } + else { //it isn't a ReadArchive procedure + bool end; + nextLine = topNextLine(&end); //take next line + if(!inString(str)) + nextLineType = isRibProcedure(nextLine); + else //maybe a string with a procedure name + nextLineType = ribParser::NOTAPROCEDURE; + while(nextLine != "" && nextLineType == ribParser::NOTAPROCEDURE ) { + //qDebug("nextline: %s type: %d",qPrintable(nextLine),nextLineType); + str += "\n" + nextLine; //if isn't a rib procedure append to str + nextLine = topNextLine(&end); + if(!inString(str)) + nextLineType = isRibProcedure(nextLine); //if there's a string opened, don't test if it's a procedure + } + //qDebug("Readed: %s Type: %d",qPrintable(str), *type); + //qDebug("nextline: %s type: %d",qPrintable(nextLine),nextLineType); + return str; + } +} + +//parse the statement, search and add the new file to stack +bool RibFileStack::readArchive(QString line) { + QStringList token = ribParser::splitStatement(&line); + //test if it's a statement to open a new file + if(ribProc->value(token[0]) == ribParser::READARCHIVE) { + //if it's a ReadArchive statement search the next file to parse + QString filename = token[2]; //token[2] is the file name + //search in subdir list + return searchFile(filename); + } + return false; +} + +//search file in subdir and add to stack +bool RibFileStack::searchFile(QString filename) { + //search in subdir list + for(int i=0; ivalue(token); + +} + +bool RibFileStack::hasNext() const { + return !stack->isEmpty(); +}; + +//append a directory list to the list of stack +bool RibFileStack::addSubDirs(QStringList dirs) { + foreach(QString dir,dirs) + subDir.append(dir); + return true; +}; + diff --git a/src/sampleplugins/io_m/RibFileStack.h b/src/sampleplugins/io_m/RibFileStack.h new file mode 100644 index 000000000..29489b46f --- /dev/null +++ b/src/sampleplugins/io_m/RibFileStack.h @@ -0,0 +1,36 @@ +#include +#include +#include +#include +#include +#include +#include +#include "ribProcedure.h" + +class RibFileStack { + +public: + RibFileStack(QString dir); + ~RibFileStack(); + bool pushFile(QString path); + bool pushFile(QFile* file); + bool hasNext() const; + bool addSubDirs(QStringList dirs); + QString nextStatement(int* type, bool manageReadArchive = true); + bool readArchive(QString line); + bool searchFile(QString filename); +private: + QStack< QPair* >* stack; + QString templateDir; + QStringList subDir; + bool popFile(); + int isRibProcedure(QString line) const; + bool inString(QString line) const; + QString nextLine; + int nextLineType; + QString topNextLine(bool* end); + + QHash* ribProc; + + +}; diff --git a/src/sampleplugins/io_m/export_rib.h b/src/sampleplugins/io_m/export_rib.h new file mode 100644 index 000000000..c2bd2935f --- /dev/null +++ b/src/sampleplugins/io_m/export_rib.h @@ -0,0 +1,240 @@ +#ifndef __VCGLIB_EXPORT_RIB +#define __VCGLIB_EXPORT_RIB + +#define RIB_EXPORT_STEPS 7 + +#include +#include +#include + + +#include +#include + +namespace vcg { +namespace tri { +namespace io { + + +template +class ExporterRIB +{ + +public: +typedef typename SaveMeshType::VertexPointer VertexPointer; +typedef typename SaveMeshType::ScalarType ScalarType; +typedef typename SaveMeshType::VertexType VertexType; +typedef typename SaveMeshType::FaceType FaceType; +typedef typename SaveMeshType::FacePointer FacePointer; +typedef typename SaveMeshType::VertexIterator VertexIterator; +typedef typename SaveMeshType::FaceIterator FaceIterator; + +static int Save(SaveMeshType &m, const char * filename, bool binary, CallBackPos *cb=0) { + return Save(m,filename, Mask::IOM_ALL, binary, cb); +} + +static int Save(SaveMeshType &mm, const char * filename, int savemask, bool /*binary*/, CallBackPos *cb=0) +{ + //ignore binary for now! + + //working with a copy of mesh + SaveMeshType &m = mm; + + int cbStep = 100/RIB_EXPORT_STEPS, cbValue = 0, step = 0; + if(*cb != 0) cb(cbValue, "Start exporting"); + + FILE *fout = fopen(filename,"wb"); + if(fout==NULL) { + return E_CANTOPEN; + } + + QTime tt; tt.start(); //debug + + fprintf(fout,"#generated by VCGLIB\n"); //commento d'intestazione???? + + //initial declaring + if(m.HasPerVertexColor() && (savemask & Mask::IOM_VERTCOLOR)) + fprintf(fout,"Declare \"Cs\" \"facevarying color\"\n"); + + if((HasPerVertexTexCoord(m) && (savemask & Mask::IOM_VERTTEXCOORD)) || + (HasPerWedgeTexCoord(m) && (savemask & Mask::IOM_WEDGTEXCOORD))) + fprintf(fout,"Declare \"st\" \"facevarying float[2]\"\n"); + + if(HasPerVertexNormal(m) && (savemask & Mask::IOM_VERTNORMAL)) + fprintf(fout,"Declare \"N\" \"facevarying normal\"\n"); + + if(HasPerVertexQuality(m) && (savemask & Mask::IOM_VERTQUALITY)) + fprintf(fout,"Declare \"Q\" \"facevarying float\"\n"); + + tri::Clean::RemoveUnreferencedVertex(m); + Allocator::CompactVertexVector(m); + Allocator::CompactFaceVector(m); + + //first step: faces topology + fprintf(fout,"PointsPolygons\n[\n"); + int incr = m.fn/cbStep, i=0; + for(i=0; i::VertexClearV(m); + for(FaceIterator fi=m.face.begin(); fi!=m.face.end(); ++fi, ++i) { + if((*cb != 0) && i%incr == 0) cb(++cbValue, "Exporting index of verteces"); + for(int j=0; j<3; ++j) { + int indexOfVertex = (*fi).V(j) - &(m.vert[0]); + fprintf(fout,"%i ",indexOfVertex); + //if it's the first visit, set visited bit + if(!(*fi).V(j)->IsV()) { + (*fi).V(j)->SetV(); + } + } + //fprintf(fout,"\n"); + fprintf(fout," "); + } + fprintf(fout,"\n]\n"); + qDebug("coords %i",tt.elapsed()); + cbValue = (++step)*cbStep; i=0; + + //third step: vertex coordinates + fprintf(fout,"\"P\"\n[\n"); + Matrix44f mat = Matrix44f::Identity(); + mat = mat.SetScale(1.0,1.0,1.0); + incr = m.vn/cbStep; + for(VertexIterator vi=m.vert.begin(); vi!=m.vert.end(); ++vi, ++i) { + if((*cb != 0) && i%incr == 0) cb(++cbValue, "Exporting vertex coordinates"); + if(vi->IsV()) { + Point3f p = mat * vi->P(); + fprintf(fout,"%g %g %g ",p[0],p[1],p[2]); + } + } + fprintf(fout,"\n]\n"); + qDebug("coords %i",tt.elapsed()); + + incr = m.fn/cbStep; cbValue = (++step)*cbStep; i=0; + //fourth step: vertex normal + if(HasPerVertexNormal(m) && (savemask & Mask::IOM_VERTNORMAL)) { + fprintf(fout,"\"N\"\n[\n"); + for(FaceIterator fi=m.face.begin(); fi!=m.face.end(); ++fi, ++i) { + if((*cb != 0) && i%incr == 0) cb(++cbValue, "Exporting vertex normals"); + //for each face, foreach vertex write normal + for(int j=0; j<3; ++j) { + Point3f n = mat * (*fi).V(j)->N(); //transform normal too + fprintf(fout,"%g %g %g ",n[0],n[1],n[2]); + } + } + fprintf(fout,"\n]\n"); + qDebug("normal %i",tt.elapsed()); + } + cbValue = (++step)*cbStep; i=0; + + //fifth step: vertex color (ignore face color?) + if(m.HasPerVertexColor() && (savemask & Mask::IOM_VERTCOLOR)) { + fprintf(fout,"\"Cs\"\n[\n"); + for(FaceIterator fi=m.face.begin(); fi!=m.face.end(); ++fi, ++i) { + if((*cb != 0) && i%incr == 0) cb(++cbValue, "Exporting vertex colors"); + //for each face, foreach vertex write color + for(int j=0; j<3; ++j) { + Color4b &c=(*fi).V(j)->C(); + fprintf(fout,"%g %g %g ",float(c[0])/255,float(c[1])/255,float(c[2])/255); + } + } + fprintf(fout,"\n]\n"); + qDebug("color %i",tt.elapsed()); + } + cbValue = (++step)*cbStep; i=0; + + //sixth step: texture coordinates (for edge) + if((HasPerVertexTexCoord(m) && (savemask & Mask::IOM_VERTTEXCOORD)) || + (HasPerWedgeTexCoord(m) && (savemask & Mask::IOM_WEDGTEXCOORD))) { + fprintf(fout,"\"st\"\n[\n"); i=0; + for(FaceIterator fi=m.face.begin(); fi!=m.face.end(); ++fi, ++i) { + if((*cb != 0) && i%incr == 0) cb(++cbValue, "Exporting vertex/edge texture coordinates"); + //for each face, foreach vertex write uv coord + for(int j=0; j<3; ++j) { + fprintf(fout,"%g %g ",(*fi).WT(j).U() , 1.0 - (*fi).WT(j).V()); //v origin axis is up + } + } + fprintf(fout,"\n]\n"); + qDebug("texcoords %i",tt.elapsed()); + } + cbValue = (++step)*cbStep; i=0; + + //seventh step: vertex quality + if(HasPerVertexQuality(m) && (savemask & Mask::IOM_VERTQUALITY)) { + fprintf(fout,"\"Q\"\n[\n"); i=0; + for(FaceIterator fi=m.face.begin(); fi!=m.face.end(); ++fi, ++i) { + if((*cb != 0) && i%incr == 0) cb(++cbValue, "Exporting vertex quality"); + //for each face, foreach vertex write its quality + for(int j=0; j<3; ++j) { + fprintf(fout,"%g ",(*fi).V(j)->Q()); + } + } + fprintf(fout,"\n]\n"); + qDebug("quality %i",tt.elapsed()); + } + cb(100, "Exporting completed"); + fclose(fout); + + return E_NOERROR; +} + +enum RibError { + E_NOERROR, // 0 + // Errors of open(..) + E_CANTOPEN, // 1 + E_MAXRIBERRORS +}; + +static const char *ErrorMsg(int error) { + static std::vector rib_error_msg; + if(rib_error_msg.empty()) + { + rib_error_msg.resize(E_MAXRIBERRORS); + rib_error_msg[E_NOERROR ]="No errors"; + rib_error_msg[E_CANTOPEN ]="Can't open file"; + } + + if(error > E_MAXRIBERRORS || error < 0) + return "Unknown error"; + else + return rib_error_msg[error].c_str(); +}; + + static int GetExportMaskCapability() { + int capability = 0; + capability |= vcg::tri::io::Mask::IOM_VERTCOORD ; + //capability |= vcg::tri::io::Mask::IOM_VERTFLAGS ; + capability |= vcg::tri::io::Mask::IOM_VERTCOLOR ; + capability |= vcg::tri::io::Mask::IOM_VERTQUALITY ; + capability |= vcg::tri::io::Mask::IOM_VERTNORMAL ; + //capability |= vcg::tri::io::Mask::IOM_VERTRADIUS ; + capability |= vcg::tri::io::Mask::IOM_VERTTEXCOORD ; + //capability |= vcg::tri::io::Mask::IOM_FACEINDEX ; + //capability |= vcg::tri::io::Mask::IOM_FACEFLAGS ; + //capability |= vcg::tri::io::Mask::IOM_FACECOLOR ; + //capability |= vcg::tri::io::Mask::IOM_FACEQUALITY ; + // capability |= vcg::tri::io::Mask::IOM_FACENORMAL ; + capability |= vcg::tri::io::Mask::IOM_WEDGCOLOR ; + capability |= vcg::tri::io::Mask::IOM_WEDGTEXCOORD ; + capability |= vcg::tri::io::Mask::IOM_WEDGTEXMULTI ; + //capability |= vcg::tri::io::Mask::IOM_WEDGNORMAL ; + // capability |= vcg::tri::io::Mask::IOM_CAMERA ; + return capability; + } + + +}; // end class + + + +} // end namespace tri +} // end namespace io +} // end namespace vcg +//@} +#endif diff --git a/src/sampleplugins/io_m/io_renderman.cpp b/src/sampleplugins/io_m/io_renderman.cpp new file mode 100644 index 000000000..0c63e87f5 --- /dev/null +++ b/src/sampleplugins/io_m/io_renderman.cpp @@ -0,0 +1,231 @@ +/**************************************************************************** +* MeshLab o o * +* An extendible mesh processor o o * +* _ O _ * +* Copyright(C) 2005, 2006 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#include +#include +#include +#include + +#include "io_renderman.h" + +#include +#include +#include +#include +#include + +using namespace vcg; + +IORenderman::IORenderman() +{ + templatesDir = PluginManager::getBaseDirPath(); + + if(!templatesDir.cd("render_template")) { + qDebug("Error. I was expecting to find the render_template dir. Now i am in dir %s",qPrintable(templatesDir.absolutePath())); + ;//this->errorMessage = "\"render_template\" folder not found"; + } +} + + +bool IORenderman::open(const QString &formatName, const QString &fileName, MeshModel &m, int& mask,const RichParameterSet & par, CallBackPos *cb, QWidget *parent) +{ + assert(0); + return true; +} + +bool IORenderman::save(const QString &formatName, const QString &fileName, MeshModel &m, const int mask,const RichParameterSet & par, vcg::CallBackPos *cb, QWidget *parent) +{ + QString errorMsgFormat = "Error encountered while exportering file %1:\n%2"; + + //***get the filter parameters and create destination directory*** + //MeshModel* m = md.mm(); + this->cb = cb; + QTime tt; tt.start(); //time for debuging + qDebug("Starting apply filter"); + + if(templates.isEmpty()) //there aren't any template + { + this->errorMessage = "No template scene has been found in \"render_template\" directory"; + return false; + } + QString templateName = templates.at(par.getEnum("scene")); //name of selected template + QFileInfo templateFile = QFileInfo(templatesDir.absolutePath() + QDir::separator() + templateName + QDir::separator() + templateName + ".rib"); + + //directory of current mesh + //QString meshDirString = m->pathName(); + ////creating of destination directory + //bool delRibFiles = !par.getBool("SaveScene"); + ////if SaveScene is true create in same mesh directory, otherwise in system temporary directry + //QDir destDir = QDir::temp(); //system temporary directry + //if(!delRibFiles) { + // //destDir = QDir(par.getSaveFileName("SceneName")); + // destDir = QDir(meshDirString); + //} + ////create scene directory if don't exists + //if(!destDir.cd("scene")) { + // if(!destDir.mkdir("scene") || !destDir.cd("scene")) { + // this->errorMessage = "Creating scene directory at " + destDir.absolutePath(); + // return false; + // } + //} + //create a new directory with template name + QDir destDir = QFileInfo(fileName).dir(); + QString destDirString = templateName + "-" + QFileInfo(m.fullName()).completeBaseName(); + QString newDir = destDirString; + int k = 0; + while(destDir.cd(newDir)) { + destDir.cdUp(); + newDir = destDirString + "-" + QString::number(++k); //dir templateName+k + } + if(!destDir.mkdir(newDir) || !destDir.cd(newDir)) { + this->errorMessage = "Creating scene directory at " + destDir.absolutePath(); + return false; + } + + //destination diretory + destDirString = destDir.absolutePath(); + + //***Texture: take the list of texture mesh + QStringList textureListPath = QStringList(); + for(size_t i=0; ierrorMessage = "The template description hasn't a statement to render any image"; + return false; + }*/ + + //***copy the rest of template files (shaders, textures, procedural..) + UtilitiesHQR::copyFiles(templateFile.dir(), destDir, textureDirs); + UtilitiesHQR::copyFiles(templateFile.dir(), destDir, shaderDirs); + UtilitiesHQR::copyFiles(templateFile.dir(), destDir, proceduralDirs); + qDebug("Copied needed file at %i",tt.elapsed()); + + //***convert the texture mesh to tiff format + if(!textureListPath.empty() && (m.cm.HasPerWedgeTexCoord() || m.cm.HasPerVertexTexCoord())) { + QString textureName = QFileInfo(textureListPath.first()).completeBaseName(); //just texture name + QFile srcFile(m.pathName() + QDir::separator() + textureListPath.first()); + + //destination directory it's the first readable/writable between textures directories + QString newImageDir = "."; + foreach(QString dir, textureDirs) { + if(dir!="." && destDir.cd(dir)) { + newImageDir = dir; + destDir.cdUp(); + break; + } + } + qDebug("source texture directory: %s", qPrintable(srcFile.fileName())); + QString newTex = destDirString + QDir::separator() + newImageDir + QDir::separator() + textureName; + qDebug("destination texture directory: %s", qPrintable(newTex + ".tiff")); + if(srcFile.exists()) { + //convert image to tiff format (the one readable in aqsis) + QImage image; + image.load(srcFile.fileName()); + image.save(newTex + ".tiff", "Tiff"); + + } + else { + this->errorMessage = "Not founded the texture file: " + srcFile.fileName(); + return false; //the mesh has a texture not existing + } + } + /*int result = vcg::tri::io::ExporterRIB::Save(m.cm,qPrintable(fileName),mask,false,cb); + + if(result!=0) + { + QMessageBox::warning(parent, tr("Saving Error"), errorMsgFormat.arg(qPrintable(fileName), vcg::tri::io::ExporterRIB::ErrorMsg(result))); + return false; + }*/ + return true; +} + +/* + returns the list of the file's type which can be imported +*/ +QList IORenderman::importFormats() const +{ + QList formatList; + return formatList; +} + +/* + returns the list of the file's type which can be exported +*/ +QList IORenderman::exportFormats() const +{ + QList formatList; + formatList << Format("RenderMan Interface Bytestream Protocol" ,tr("rib")); + return formatList; +} + +/* + returns the mask on the basis of the file's type. + otherwise it returns 0 if the file format is unknown +*/ +void IORenderman::GetExportMaskCapability(QString &format, int &capability, int &defaultBits) const +{ + capability=defaultBits=vcg::tri::io::ExporterRIB::GetExportMaskCapability(); + return; +} +void IORenderman::initSaveParameter(const QString &/*format*/, MeshModel &/*m*/, RichParameterSet & parlst) +{ + //update the template list + templates = QStringList(); + foreach(QString subDir, templatesDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) { + //foreach directory, search a file with the same name + QString temp(templatesDir.absolutePath() + QDir::separator() + subDir + QDir::separator() + subDir + ".rib"); + if(QFile::exists(temp)) + templates << subDir; + } + if(templates.isEmpty()) + { + this->errorMessage = "No template scene has been found in \"render_template\" directory"; + qDebug("%s",qPrintable(this->errorMessage)); + } + parlst.addParam(new RichEnum("scene",0,templates,"Select scene", + "Select the scene where the loaded mesh will be drawed in.")); + parlst.addParam(new RichInt("FormatX", 640, "Format X", "Final image/s lenght size.")); + parlst.addParam(new RichInt("FormatY", 480, "Format Y", "Final image/s width size.")); + parlst.addParam(new RichFloat("PixelAspectRatio", 1.0, "Pixel aspect ratio", "Final image/s pixel aspect ratio.")); + parlst.addParam(new RichBool("Autoscale",true,"Auto-scale mesh","Check if the mesh will be scaled on render scene")); + QStringList alignValueList = (QStringList() << "Center" << "Top" << "Bottom"); + parlst.addParam(new RichEnum("AlignX",0,alignValueList,"Align X", + "If it's checked the mesh will be aligned with scene x axis")); + parlst.addParam(new RichEnum("AlignY",0,alignValueList,"Align Y", + "If it's checked the mesh will be aligned with scene y axis")); + parlst.addParam(new RichEnum("AlignZ",0,alignValueList,"Align Z", + "If it's checked the mesh will be aligned with scene z axis")); +} +Q_EXPORT_PLUGIN(IORenderman) diff --git a/src/sampleplugins/io_m/io_renderman.h b/src/sampleplugins/io_m/io_renderman.h new file mode 100644 index 000000000..414a26b58 --- /dev/null +++ b/src/sampleplugins/io_m/io_renderman.h @@ -0,0 +1,81 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#ifndef IORenderman_H +#define IORenderman_H + +#include +#include +#include "utilities_hqrender.h" +#include "RibFileStack.h" +#include "export_rib.h" + +class IORenderman : public QObject, public MeshIOInterface +{ + Q_OBJECT + Q_INTERFACES(MeshIOInterface) + + +public: + QList importFormats() const; + QList exportFormats() const; + + virtual void GetExportMaskCapability(QString &format, int &capability, int &defaultBits) const; + void initSaveParameter(const QString &/*format*/, MeshModel &/*m*/, RichParameterSet & /*par*/); + bool open(const QString &formatName, const QString &fileName, MeshModel &m, int& mask,const RichParameterSet & par, vcg::CallBackPos *cb=0, QWidget *parent=0); + bool save(const QString &formatName, const QString &fileName, MeshModel &m, const int mask,const RichParameterSet & par, vcg::CallBackPos *cb, QWidget *parent); + IORenderman(); +private: + vcg::CallBackPos * cb; + QDir templatesDir; //directory of templates ("render_template") + QStringList templates; //list of templates found + + //parser_rib.cpp + enum alignValue { CENTER, TOP, BOTTOM }; + inline const QString mainFileName() { return QString("scene.rib"); } + bool convertedGeometry; + int worldBeginRendered, numOfWorldBegin, lastCb; //for progress bar update + int numberOfDummies, numOfObject; + //the state graphics at procedure call time + struct Procedure { + QString name; + vcg::Matrix44f matrix; + float bound[6]; + QString surfaceShader; + }; + //Graphics state + QStack transfMatrixStack; + QStack surfaceShaderStack; + float objectBound[6]; // xmin, xmax, ymin, ymax, zmin, zmax + + bool makeScene(MeshModel* m, QStringList* textureList,const RichParameterSet &par, QFileInfo* templateFile, QString destDirString, QStringList* shaderDirs, QStringList* textureDirs, QStringList* proceduralDirs, QStringList* imagesRendered); + QString convertObject(int currentFrame, QString destDir, MeshModel* m,const RichParameterSet &par, QStringList* textureList); + bool resetBound(); + bool resetGraphicsState(); + int writeMatrix(FILE* fout, const vcg::Matrix44f* matrix, bool transposed = true); + vcg::Matrix44f getMatrix(const QString* matrixString) const; + enum searchType{ ERR, ARCHIVE, SHADER, TEXTURE, PROCEDURAL }; + QStringList readSearchPath(const QStringList* token, int* type); +}; + +#endif diff --git a/src/sampleplugins/io_m/io_renderman.pro b/src/sampleplugins/io_m/io_renderman.pro new file mode 100644 index 000000000..2985dcd5a --- /dev/null +++ b/src/sampleplugins/io_m/io_renderman.pro @@ -0,0 +1,14 @@ +include (../../shared.pri) +HEADERS += io_renderman.h \ + export_rib.h \ + RibFileStack.h \ + utilities_hqrender.h \ + ribProcedure.h + +SOURCES += io_renderman.cpp \ + RibFileStack.cpp \ + parser_rib.cpp \ + utilities_hqrender.cpp + + +TARGET = io_renderman diff --git a/src/sampleplugins/io_m/parser_rib.cpp b/src/sampleplugins/io_m/parser_rib.cpp new file mode 100644 index 000000000..9c139d74a --- /dev/null +++ b/src/sampleplugins/io_m/parser_rib.cpp @@ -0,0 +1,536 @@ +#include "io_renderman.h" +#include + +using namespace UtilitiesHQR; + +//reset the current bound to infinite (default RIS) +bool IORenderman::resetBound() { + // xmin, xmax, ymin, ymax, zmin, zmax + for(int i=0; i< 6; i=i+2) + objectBound[i] = std::numeric_limits::min(); + for(int i=1; i<6; i=i+2) + objectBound[i] = std::numeric_limits::max(); + return true; +} + +//reset graphics state (transformation matrix, bound, surface shader) to default value +bool IORenderman::resetGraphicsState() { + //graphics state initialization (only interesting things) + transfMatrixStack = QStack(); + transfMatrixStack << vcg::Matrix44f::Identity(); + surfaceShaderStack = QStack(); + surfaceShaderStack << ""; //nothing to set implementation-dependent default surface shader + resetBound(); + return true; +} + +//read source files and write to destination file +//if it's found the attribute name with value "dummy", the following geometry statement +//are replaced with a current mesh conversion +bool IORenderman::makeScene(MeshModel* m, + QStringList* textureList, + const RichParameterSet &par, + QFileInfo* templateFile, + QString destDirString, + QStringList* shaderDirs, + QStringList* textureDirs, + QStringList* proceduralDirs, + QStringList* imagesRendered) +{ + + //rib file structure + RibFileStack files(templateFile->absolutePath()); //constructor + //open file and stream + if(!files.pushFile(templateFile->absoluteFilePath())) { + this->errorMessage = "Template path is wrong: " + templateFile->absoluteFilePath(); + return false; + } + + //output file + FILE* fout; + fout = fopen(qPrintable(destDirString + QDir::separator() + mainFileName()),"wb"); + if(fout==NULL) { + this->errorMessage = "Impossible to create file: " + destDirString + QDir::separator() + mainFileName(); + return false; + } + qDebug("Starting to write rib file into %s",qPrintable(destDirString + QDir::separator() + mainFileName())); + + FILE* fmain = fout; //if change the output file, the main is saved here + convertedGeometry = false; //if the mesh is already converted + int currentFrame = 0; //frame counter + + bool stop = false; + bool currentDisplayTypeIsFile = false; + bool anyOtherDisplayType = false; + numberOfDummies = 0; //the dummy object could be than one (e.g. for ambient occlusion passes) + QString newFormat = "Format " + + QString::number(par.getInt("FormatX")) + " " + + QString::number(par.getInt("FormatY")) + " " + + QString::number(par.getFloat("PixelAspectRatio")); + numOfWorldBegin = 0; //the number of world begin statement found (for progress bar) + numOfObject = 0; + bool foundDummy = false; + bool solidBegin = false; //true only if define a dummy object + bool writeLine = true; //true if the line has to be write to final file + resetGraphicsState(); //transformation matrix, bound, surface shader + QQueue procedures = QQueue(); //every time it's found a procedural call it's stored here + + //reading cycle + while(files.hasNext() && !stop) { + if(!solidBegin) + writeLine = true; + int statementType = 0; //type of statement + QString line = files.nextStatement(&statementType); //current line + + switch(statementType) { + //declare other directory for the template + case ribParser::OPTION: { + QStringList token = ribParser::splitStatement(&line); + if(token[2] == "searchpath") { + int type = 0; + QStringList dirList = readSearchPath(&token,&type); + switch(type) { + case IORenderman::ARCHIVE: + files.addSubDirs(dirList); + break; + case IORenderman::SHADER: + *shaderDirs = dirList; + break; + case IORenderman::TEXTURE: + *textureDirs = dirList; + break; + case IORenderman::PROCEDURAL: + files.addSubDirs(dirList); + *proceduralDirs = dirList; + break; + case IORenderman::ERR: + //ignore: maybe an error or another searchpath type (not in RISpec3.2) + break; + } + } + break; + } + //make a map (create the path if needed) + case ribParser::MAKE: + case ribParser::MAKECUBEFACEENVIRONMENT: + { + QStringList token = ribParser::splitStatement(&line); + QString path = token[2]; //for MakeTexture, MakeShadow, MakeLatLongEnvironment + if(statementType == ribParser::MAKECUBEFACEENVIRONMENT) + path = token[7]; + path = QFileInfo(path).path(); + //qDebug("check dir! line: %s\npath: %s",qPrintable(line),qPrintable(path)); + checkDir(&destDirString,&path); + break; + } + //begin a new frame + case ribParser::FRAMEBEGIN: + { + QStringList token = ribParser::splitStatement(&line); + bool isNum; + int i = token[1].toInt(&isNum); + if(isNum) + currentFrame = i; + break; + } + //set output type (create the path if needed) + case ribParser::DISPLAY: + { + //if output is not a file the format must be the same!! framebuffer is ignored and commented + QStringList token = ribParser::splitStatement(&line); + //create the path if needed + QString path = token[2]; + if(path.startsWith('+.')) + path = path.mid(2,path.size()); + path = QFileInfo(path).path(); + //qDebug("check dir! line: %s\npath: %s",qPrintable(line),qPrintable(path)); + checkDir(&destDirString,&path); + + //if there's more "Display" statement with one that's "file" is not considered a final image + if(token[5] != "framebuffer") + if (!anyOtherDisplayType && token[5] == "file") { + currentDisplayTypeIsFile = true; + QString img = token[2]; + if(img.startsWith('+')) + img = img.mid(1,img.size()); + *imagesRendered << img; + } + else + anyOtherDisplayType = true; + //else + //line = "#" + line; //if there's a framebuffer will be open pqsl automatically + break; + } + case ribParser::SCREENWINDOW: + { + writeLine = false; + break; + } + //a new world description (reset graphics state) + case ribParser::WORLDBEGIN: + { + //make the conversion of texture mesh before the first WorldBegin statement + if(numOfWorldBegin == 0 && !textureList->empty() && (m->cm.HasPerWedgeTexCoord() || m->cm.HasPerVertexTexCoord())) { + QString textureName = QFileInfo(textureList->first()).completeBaseName(); + fprintf(fout,"MakeTexture \"%s.tiff\" \"%s.tx\" \"periodic\" \"periodic\" \"box\" 1 1\n", qPrintable(textureName),qPrintable(textureName)); + } + + numOfWorldBegin++; + //if there's another type of display the format is not change + if(!anyOtherDisplayType && currentDisplayTypeIsFile) { + fprintf(fout,"%s\n", qPrintable(newFormat)); + } + currentDisplayTypeIsFile = false; + anyOtherDisplayType = false; + //is right?yes,because before the next WorldBegin will there be a new Display statement + resetGraphicsState(); //reset the graphics state + break; + } + //set transform in graphics state + case ribParser::TRANSFORM: + { + transfMatrixStack.pop(); + transfMatrixStack.push(getMatrix(&line)); + break; + } + //set surface in graphics state + case ribParser::SURFACE: + { + //the surface shader remain the same of template + surfaceShaderStack.pop(); + surfaceShaderStack.push(line); + break; + } + //set bound in graphics state + case ribParser::BOUND: + { + //take the transformation bound + QStringList token = ribParser::splitStatement(&line); + int index = 1; + if(token[index] == "[") + index++; + for(int i=0; i<6; i++) { + bool isNumber; + float number = token[index+i].toFloat(&isNumber); + if(isNumber) + objectBound[i] = number; + } + break; + } + //looking for a dummy + case ribParser::ATTRIBUTE: + { + QStringList token = ribParser::splitStatement(&line); + //RISpec3.2 not specify what and how many attributes are there in renderman + //we take care of name only + if(token[2] == "identifier") { + //Attribute "identifier" "string name" [ "object name" ] + if(token[5] == "string name" || token[5] == "name") { + int index = 7; + if(token[index] == "[") + index++; + if(token[index] == "\"") + index++; + if(token[index].trimmed().toLower() == "dummy") {//found a dummy object? + foundDummy = true; + } + } + } + break; + } + //the begin of a set of statement to define a solid + case ribParser::SOLIDBEGIN: { + if(foundDummy) { + solidBegin = true; + writeLine = false; + } + } + //the end of solid definition + case ribParser::SOLIDEND: { + if(solidBegin) { //if and only if foundDummy is true + QString filename = convertObject(currentFrame, destDirString, m, par, textureList); + qDebug("dummy conversion, filename: %s",qPrintable(filename)); + if(filename == "") { //error in parseObject + fclose(fmain); + return false; + } + fprintf(fout,"ReadArchive \"%s\"\n",qPrintable(filename)); + + solidBegin = false; + foundDummy = false; + } + //reset bound (and surface?) + resetBound(); + break; + } + //there's a geometric statement...if there was a dummy too, replace geometry + case ribParser::GEOMETRIC: { + if(foundDummy) { + QString filename = convertObject(currentFrame, destDirString, m, par, textureList); + qDebug("dummy conversion, filename: %s",qPrintable(filename)); + if(filename == "") { //error in parseObject + fclose(fmain); + return false; + } + fprintf(fout,"ReadArchive \"%s\"\n",qPrintable(filename)); + + writeLine = false; + foundDummy = false; + } + //reset bound (and surface?) + resetBound(); + break; + } + //add a new graphics state "level" + case ribParser::ATTRIBUTEBEGIN: + { + transfMatrixStack.push(transfMatrixStack.top()); + surfaceShaderStack.push(surfaceShaderStack.top()); + break; + } + //remove a "level" to graphics state stack + case ribParser::ATTRIBUTEEND: + { + transfMatrixStack.pop(); + surfaceShaderStack.pop(); + break; + } + //a procedural statement: managed at the end of cycle + case ribParser::PROCEDURAL: + { + //manage only dealayedreadarchive + //0: Procedural + //1: " + //2: DelayedReadArchive + //3: " + //4: [ + //5: " + //6: filename + //7: " + //8: ] + //9: [ + //10-15: bound element + //11: ] + QStringList token = ribParser::splitStatement(&line); + if(token[2] == "DelayedReadArchive") { + qDebug("found a procedural: %s",qPrintable(token[6])); + Procedure p = Procedure(); + p.name = token[6]; + p.matrix = transfMatrixStack.top(); + p.surfaceShader = surfaceShaderStack.top(); + //have i to read bound from actual graphics state or from procedural call? + for(int i = 0; i < 6; i++) + p.bound[i] = token[10 + i].toFloat(); //from procedural call (don't check if it's a number) + //p.bound[i] = objectBound[i]; //from actual graphics state + procedures.enqueue(p); + } + break; + } + //the end of scene is reached + case ribParser::NOMORESTATEMENT: + { + qDebug("Stack empty"); + stop = true; + writeLine = false; + } + } //end of switch + + if(writeLine) { + //copy the same line in file + fprintf(fout,"%s\n",qPrintable(line)); + } + + if((!files.hasNext() || stop) && !procedures.isEmpty()) { + qDebug("There's a procedural to manage"); + //continue the cycle over procedure files.. + Procedure p = procedures.dequeue(); + //add procedure to rib file stack if exist + bool noProc = false; + while(!files.searchFile(p.name) && !noProc) + if(procedures.isEmpty()) + noProc = true; + else + p = procedures.dequeue(); + + if(!noProc) { //it's true only if all procedures elements don't exist + fclose(fout); + fout = fopen(qPrintable(destDirString + QDir::separator() + p.name),"wb"); + if(fout==NULL) { + this->errorMessage = "Impossible to create file: " + destDirString + QDir::separator() + p.name; + return false; + } + qDebug("Starting to write rib file into %s",qPrintable(destDirString + QDir::separator() + p.name)); + + //restore the graphics state to the procedure call state + transfMatrixStack << p.matrix; + surfaceShaderStack << p.surfaceShader; + for(int i = 0; i < 6; i++) + objectBound[i] = p.bound[i]; + //continue cycle + writeLine = true; + stop = false; + } + } + + } //end of cycle + fclose(fout); + + return true; +} + +//write to an opened file the attribute of object entity +QString IORenderman::convertObject(int currentFrame, QString destDir, MeshModel* m,const RichParameterSet &par, QStringList* textureList)//, ObjValues* dummyValues) +{ + QString name = "meshF" + QString::number(currentFrame) + "O" + QString::number(numberOfDummies) + ".rib"; + numberOfDummies++; + FILE *fout = fopen(qPrintable(destDir + QDir::separator() + name),"wb"); + if(fout == NULL) { + this->errorMessage = "Impossible to create the file: " + destDir + QDir::separator() + name; + return ""; + } + fprintf(fout,"AttributeBegin\n"); + //name + fprintf(fout,"Attribute \"identifier\" \"string name\" [ \"meshlabMesh\" ]\n"); + //modify the transformation matrix + vcg::Matrix44f scaleMatrix = vcg::Matrix44f::Identity(); + float dummyX = objectBound[1] - objectBound[0]; + float dummyY = objectBound[3] - objectBound[2]; + float dummyZ = objectBound[5] - objectBound[4]; + + //autoscale + float scale = 1.0; + if(par.getBool("Autoscale")) { + float ratioX = dummyX / m->cm.trBB().DimX(); + float ratioY = dummyY / m->cm.trBB().DimY(); + float ratioZ = dummyZ / m->cm.trBB().DimZ(); + scale = std::min(ratioX, std::min(ratioY, ratioZ)); //scale factor is min ratio + scaleMatrix.SetScale(scale,scale,scale); + } + + //center mesh + vcg::Point3f c = m->cm.trBB().Center(); + vcg::Matrix44f translateBBMatrix; + translateBBMatrix.SetTranslate(-c[0],-c[1],-c[2]); + + //align + float dx = 0.0, dy = 0.0, dz = 0.0; + switch(par.getEnum("AlignX")) { + case IORenderman::TOP: + dx = (dummyX - m->cm.trBB().DimX() * scale) / 2; break; + case IORenderman::BOTTOM: + dx = -(dummyX - m->cm.trBB().DimX() * scale) / 2; break; + case IORenderman::CENTER: break; //is already center + } + switch(par.getEnum("AlignY")) { + case IORenderman::TOP: + dy = (dummyY - m->cm.trBB().DimY() * scale) / 2; break; + case IORenderman::BOTTOM: + dy = -(dummyY - m->cm.trBB().DimY() * scale) / 2; break; + case IORenderman::CENTER: break; //is already center + } + switch(par.getEnum("AlignZ")) { + case IORenderman::TOP: + dz = (dummyZ - m->cm.trBB().DimZ() * scale) / 2; break; + case IORenderman::BOTTOM: + dz = -(dummyZ - m->cm.trBB().DimZ() * scale) / 2; break; + case IORenderman::CENTER: break; //is already center + } + vcg::Matrix44f alignMatrix; + alignMatrix = alignMatrix.SetTranslate(dx,dy,dz); + vcg::Matrix44f templateMatrix = transfMatrixStack.top(); //by default is identity + + vcg::Matrix44f result = templateMatrix * alignMatrix * scaleMatrix * translateBBMatrix; + //write transformation matrix (after transpose it) + writeMatrix(fout, &result); + //write bounding box + fprintf(fout,"Bound %g %g %g %g %g %g\n", + m->cm.trBB().min.X(), m->cm.trBB().max.X(), + m->cm.trBB().min.Y(), m->cm.trBB().max.Y(), + m->cm.trBB().min.Z(), m->cm.trBB().max.Z()); + + //force the shading interpolation to smooth + fprintf(fout,"ShadingInterpolation \"smooth\"\n"); + //shader + fprintf(fout,"%s\n",qPrintable(surfaceShaderStack.top())); + //texture mapping (are TexCoord needed for texture mapping?) + if(!textureList->empty() > 0 && (m->cm.HasPerWedgeTexCoord() || m->cm.HasPerVertexTexCoord())) { + //multi-texture don't work!I need ad-hoc shader and to read the texture index for vertex.. + //foreach(QString textureName, *textureList) { + + //read only the first texture + QString textureName = QFileInfo(textureList->first()).completeBaseName(); + fprintf(fout,"Surface \"paintedplastic\" \"Kd\" 1.0 \"Ks\" 0.0 \"texturename\" [\"%s.tx\"]\n", qPrintable(textureName)); + } + //geometry + QString filename = "geometry.rib"; + fprintf(fout,"ReadArchive \"%s\"\n", qPrintable(filename)); + if(!convertedGeometry) { + //make the conversion only once + convertedGeometry = true; + QString geometryDest = destDir + QDir::separator() + filename; + int res = vcg::tri::io::ExporterRIB::Save(m->cm, qPrintable(geometryDest), vcg::tri::io::Mask::IOM_ALL, false, cb); + if(res != vcg::tri::io::ExporterRIB::E_NOERROR) { + fclose(fout); + this->errorMessage = QString(vcg::tri::io::ExporterRIB::ErrorMsg(res)); + return ""; + } + else + Log(GLLogStream::FILTER,"Successfully converted mesh"); + } + fprintf(fout,"AttributeEnd\n"); + fclose(fout); + return name; +} + +//return an a list of directory (separated by ':' character) +QStringList IORenderman::readSearchPath(const QStringList* token, int* type) { + //the line maybe: Option "searchpath" "string type" [ ..values..] + // or: Option "searchpath" "type" [ ..values..] + int index = 5; + *type = IORenderman::ERR; + if((*token)[index] == "archive" || (*token)[index] == "string archive") + *type = IORenderman::ARCHIVE; + if((*token)[index] == "shader" || (*token)[index] == "string shader") + *type = IORenderman::SHADER; + if((*token)[index] == "texture" || (*token)[index] == "string texture") + *type = IORenderman::TEXTURE; + if((*token)[index] == "procedural" || (*token)[index] == "string procedural") + *type = IORenderman::PROCEDURAL; + index = 7; + if((*token)[index] == "[") + index++; + if((*token)[index] == "\"") + index++; + //else err? + QStringList dirs = (*token)[index].split(':'); //is it the standard method divide dirs with character ':' ? + return dirs; +} + +//write a vcg::Matrix44f to file +int IORenderman::writeMatrix(FILE* fout, const vcg::Matrix44f* matrix, bool transposed) { + fprintf(fout,"Transform [ "); + for(int i = 0; i<4; i++) + for(int j = 0; j<4; j++) + fprintf(fout,"%f ",(transposed)? matrix->ElementAt(j,i) : matrix->ElementAt(i,j)); + fprintf(fout,"]\n"); + return 0; +} + +//get a vcg::Matrix44f from line (and transpose it) +vcg::Matrix44f IORenderman::getMatrix(const QString* matrixString) const { + float t[16]; + int k=0; + QStringList list = matrixString->split(' '); + for(int i=0; i +#include + +class ribParser { +public: + enum ribProcedure { + NOTAPROCEDURE, + ATTRIBUTE, + ATTRIBUTEBEGIN, + ATTRIBUTEEND, + BOUND, + DISPLAY, + FRAMEBEGIN, + FRAMEEND, + GEOMETRIC, //Pag. 201 RISpec3.2 + MAKE, + MAKECUBEFACEENVIRONMENT, + OPTION, + PROCEDURAL, + READARCHIVE, + SCREENWINDOW, + SOLIDBEGIN, + SOLIDEND, + SURFACE, + TRANSFORM, + WORLDBEGIN, + WORLDEND, + COMMENT, + OTHER, + NOMORESTATEMENT + }; + + static QHash* initHash() { + QHash* proc = new QHash(); + proc->insert("ArchiveRecord", ribParser::OTHER); + proc->insert("AreaLightSource", ribParser::OTHER); + proc->insert("Atmosphere", ribParser::OTHER); + proc->insert("Attribute", ribParser::ATTRIBUTE); + proc->insert("AttributeBegin", ribParser::ATTRIBUTEBEGIN); + proc->insert("AttributeEnd", ribParser::ATTRIBUTEEND); + proc->insert("Basis", ribParser::OTHER); + proc->insert("Begin", ribParser::OTHER); + proc->insert("Blobby", ribParser::GEOMETRIC); + proc->insert("Bound", ribParser::BOUND); + proc->insert("Clipping", ribParser::OTHER); + proc->insert("ClippingPlane", ribParser::OTHER); + proc->insert("Color", ribParser::OTHER); + proc->insert("ColorSamples", ribParser::OTHER); + proc->insert("ConcatTransform", ribParser::OTHER); + proc->insert("Cone", ribParser::GEOMETRIC); + proc->insert("Context", ribParser::OTHER); + proc->insert("CoordinateSystem", ribParser::OTHER); + proc->insert("CoordSysTransform", ribParser::OTHER); + proc->insert("CropWindow", ribParser::OTHER); + proc->insert("Curves", ribParser::GEOMETRIC); + proc->insert("Cylinder", ribParser::GEOMETRIC); + proc->insert("Declare", ribParser::OTHER); + proc->insert("DepthOfField", ribParser::OTHER); + proc->insert("Detail", ribParser::OTHER); + proc->insert("DetailRange", ribParser::OTHER); + proc->insert("Disk", ribParser::GEOMETRIC); + proc->insert("Displacement", ribParser::OTHER); + proc->insert("Display", ribParser::DISPLAY); + proc->insert("End", ribParser::OTHER); + proc->insert("ErrorHandler", ribParser::OTHER); + proc->insert("Exposure", ribParser::OTHER); + proc->insert("Exterior", ribParser::OTHER); + proc->insert("Format", ribParser::OTHER); + proc->insert("FrameAspectRatio", ribParser::OTHER); + proc->insert("FrameBegin", ribParser::FRAMEBEGIN); + proc->insert("FrameEnd", ribParser::FRAMEEND); + proc->insert("GeneralPolygon", ribParser::GEOMETRIC); + proc->insert("GeometricApproximation", ribParser::OTHER); + proc->insert("Geometry", ribParser::GEOMETRIC); + proc->insert("GetContext", ribParser::OTHER); + proc->insert("Hider", ribParser::OTHER); + proc->insert("Hyperboloid", ribParser::GEOMETRIC); + proc->insert("Identity", ribParser::OTHER); + proc->insert("Illuminate", ribParser::OTHER); + proc->insert("Imager", ribParser::OTHER); + proc->insert("Interior", ribParser::OTHER); + proc->insert("LightSource", ribParser::OTHER); + proc->insert("MakeCubeFaceEnvironment", ribParser::MAKECUBEFACEENVIRONMENT); + proc->insert("MakeLatLongEnvironment", ribParser::MAKE); + proc->insert("MakeShadow", ribParser::MAKE); + proc->insert("MakeTexture", ribParser::MAKE); + proc->insert("Matte", ribParser::OTHER); + proc->insert("MotionBegin", ribParser::OTHER); + proc->insert("MotionEnd", ribParser::OTHER); + proc->insert("NuPatch", ribParser::GEOMETRIC); + proc->insert("ObjectBegin", ribParser::OTHER); + proc->insert("ObjectEnd", ribParser::OTHER); + proc->insert("ObjectInstance", ribParser::GEOMETRIC); + proc->insert("Opacity", ribParser::OTHER); + proc->insert("Option", ribParser::OPTION); + proc->insert("Orientation", ribParser::OTHER); + proc->insert("Paraboloid", ribParser::GEOMETRIC); + proc->insert("Patch", ribParser::GEOMETRIC); + proc->insert("PatchMesh", ribParser::GEOMETRIC); + proc->insert("Perspective", ribParser::OTHER); + proc->insert("PixelFilter", ribParser::OTHER); + proc->insert("PixelSamples", ribParser::OTHER); + proc->insert("PixelVariance", ribParser::OTHER); + proc->insert("Points", ribParser::GEOMETRIC); + proc->insert("PointsGeneralPolygons", ribParser::GEOMETRIC); + proc->insert("PointsPolygons", ribParser::GEOMETRIC); + proc->insert("Polygon", ribParser::GEOMETRIC); + proc->insert("Procedural", ribParser::PROCEDURAL); + proc->insert("Projection", ribParser::OTHER); + proc->insert("Quantize", ribParser::OTHER); + proc->insert("ReadArchive", ribParser::READARCHIVE); + proc->insert("RelativeDetail", ribParser::OTHER); + proc->insert("ReverseOrientation", ribParser::OTHER); + proc->insert("Rotate", ribParser::OTHER); + proc->insert("Scale", ribParser::OTHER); + proc->insert("ScreenWindow", ribParser::SCREENWINDOW); + proc->insert("ShadingInterpolation", ribParser::OTHER); + proc->insert("ShadingRate", ribParser::OTHER); + proc->insert("Shutter", ribParser::OTHER); + proc->insert("Sides", ribParser::OTHER); + proc->insert("Skew", ribParser::OTHER); + proc->insert("SolidBegin", ribParser::SOLIDBEGIN); + proc->insert("SolidEnd", ribParser::SOLIDEND); + proc->insert("Sphere", ribParser::GEOMETRIC); + proc->insert("SubdivisionMesh", ribParser::GEOMETRIC); + proc->insert("Surface", ribParser::SURFACE); + proc->insert("TextureCoordinates", ribParser::OTHER); + proc->insert("Torus", ribParser::GEOMETRIC); + proc->insert("Transform", ribParser::TRANSFORM); + proc->insert("TransformBegin", ribParser::OTHER); + proc->insert("TransformEnd", ribParser::OTHER); + proc->insert("TransformPoints", ribParser::OTHER); + proc->insert("Translate", ribParser::OTHER); + proc->insert("TrimCurve", ribParser::GEOMETRIC); + proc->insert("version", ribParser::OTHER); //not a procedure, but a keyword + proc->insert("WorldBegin", ribParser::WORLDBEGIN); + proc->insert("WorldEnd", ribParser::WORLDEND); + return proc; + } + + //split a statement in word (strings are unique word, like so '\"' , '[' and ']' ) + static QStringList splitStatement(const QString* line) { + QString str = line->trimmed(); + + QStringList list = QStringList(); + QString word = ""; + bool string = false, slash = false; + for(int i = 0; isplit(QDir::separator()); + QString temp(""); + for(int i = 0; i < dirs.size(); i++) { + if(!dirs[i].contains(" ")) + temp += dirs[i]; + else + temp = temp + "\"" + dirs[i] + "\""; + temp += QDir::separator(); + } + //the final of path is separator!!! + return temp; +} + +//if dir not exist, create it +bool UtilitiesHQR::checkDir(const QString* destDirString, const QString* path) { + QDir destDir(*destDirString); + return destDir.mkpath(QString(*path)); +} + +//take all files in fromDir/[dirs] directories and copy them in dest/[dirs] +bool UtilitiesHQR::copyFiles(QDir src, QDir dest, const QStringList dirs) { + foreach(QString dir, dirs) { + if(dir != "." && src.cd(dir)) { + if(!dest.mkdir(dir)) { + if(!dest.cd(dir)) + return false; + } + else + dest.cd(dir); + + QStringList filesList = src.entryList(QDir::Files); + foreach(QString file, filesList) { + qDebug("copy file from %s to %s", + qPrintable(src.absolutePath() + QDir::separator() + file), + qPrintable(dest.absolutePath() + QDir::separator() + file)); + QFile::copy(src.absolutePath() + QDir::separator() + file, dest.absolutePath() + QDir::separator() + file); + } + } + } + return true; +} + +//delete a directory and all file and subdirectory (recursive calls) +bool UtilitiesHQR::delDir(QDir* dir, const QString* toDel) { + //qDebug("Deleting: %s in %s", qPrintable(*toDel), qPrintable(dir->absolutePath())); + if(!dir->rmdir(*toDel)) { + dir->cd(*toDel); + //qDebug("I'm in %s", qPrintable(dir->absolutePath())); + QStringList dirs = dir->entryList(QDir::Files|QDir::NoDotAndDotDot); + foreach(QString entry, dirs) { + qDebug("Cycle1 deleting file: %s in %s", qPrintable(entry), qPrintable(dir->absolutePath())); + dir->remove(entry); + } + dirs = dir->entryList(QDir::Dirs|QDir::NoDotAndDotDot); + foreach(QString entry, dirs) { + qDebug("Cycle2 deleting dir: %s in %s", qPrintable(entry), qPrintable(dir->absolutePath())); + if(!dir->rmdir(entry)) { + QDir temp = *dir; + delDir(&temp, &entry); + } + } + dir->cdUp(); + if(!dir->rmdir(*toDel)) + return false; + } + return true; +} + +//return the number of ciphers of a integer +int UtilitiesHQR::numberOfCiphers(int number) { + int digits = 1, pten=10; + while ( pten <= number ) + { digits++; pten*=10; } + return digits; +} diff --git a/src/sampleplugins/io_m/utilities_hqrender.h b/src/sampleplugins/io_m/utilities_hqrender.h new file mode 100644 index 000000000..c99d907a5 --- /dev/null +++ b/src/sampleplugins/io_m/utilities_hqrender.h @@ -0,0 +1,12 @@ +#include +#include +#include +#include + +namespace UtilitiesHQR { + QString quotesPath(const QString* path); + bool checkDir(const QString* destDirString, const QString* path); + bool copyFiles(const QDir templateDir, const QDir destDir, const QStringList dirs); + bool delDir(QDir* dir, const QString* toDel); + int numberOfCiphers(int number); +};