io_renderman plugin

This commit is contained in:
Paolo Cignoni cignoni 2010-04-21 15:12:35 +00:00
parent ccf50d84e5
commit e70ba0202b
10 changed files with 1636 additions and 0 deletions

View File

@ -0,0 +1,216 @@
#include "RibFileStack.h"
RibFileStack::RibFileStack(QString dir) {
ribProc = ribParser::initHash(); //hash of rib procedure
stack = new QStack< QPair<QFile*, QTextStream*>* >();
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<QFile*, QTextStream*>* p = new QPair<QFile*, QTextStream*>(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<QFile*, QTextStream*>* 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<QFile*, QTextStream*>* 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: <string> ,
//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; i<subDir.size(); i++) {
QString str(templateDir + QDir::separator() + (subDir)[i] + QDir::separator() + filename);
//qDebug("looking for: %s",qPrintable(str));
if(pushFile(str)) {
return true;
}
}
return false;
}
//true if in line there's a string opened and not closed
bool RibFileStack::inString(QString line) const {
if(!line.contains('\"'))
return false;
line = line.trimmed();
int a = 0;
bool slash = false;
for(int i=0; i<line.size(); i++) {
if(!slash && line[i] == '\"') {
a++;
slash = false;
}
else {
if(!slash && line[i] == '\\')
slash = true;
else
slash = false;
}
}
return a%2 != 0;
}
//check if is't a rib procedure (in ribProc table)
int RibFileStack::isRibProcedure(QString line) const {
if(line == "")
return ribParser::NOTAPROCEDURE;
if(line.trimmed().startsWith('#')) //RibProcedure " ...\n#..." how does appen?
return ribParser::COMMENT;
QString token = line.left(line.indexOf(' ')).trimmed();
return ribProc->value(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;
};

View File

@ -0,0 +1,36 @@
#include <QTextStream>
#include <QFile>
#include <QDir>
#include <QStack>
#include <QPair>
#include <QString>
#include <QStringList>
#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<QFile*, QTextStream*>* >* 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<QString, int>* ribProc;
};

View File

@ -0,0 +1,240 @@
#ifndef __VCGLIB_EXPORT_RIB
#define __VCGLIB_EXPORT_RIB
#define RIB_EXPORT_STEPS 7
#include<wrap/io_trimesh/io_mask.h>
#include<wrap/callback.h>
#include<vcg/complex/trimesh/clean.h>
#include <stdio.h>
#include <QTime>
namespace vcg {
namespace tri {
namespace io {
template <class SaveMeshType>
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<SaveMeshType>::RemoveUnreferencedVertex(m);
Allocator<SaveMeshType>::CompactVertexVector(m);
Allocator<SaveMeshType>::CompactFaceVector(m);
//first step: faces topology
fprintf(fout,"PointsPolygons\n[\n");
int incr = m.fn/cbStep, i=0;
for(i=0; i<m.fn; i++) {
fprintf(fout,"3 ");//\n");
if((*cb != 0) && i%incr == 0) cb(++cbValue, "Exporting face topology");
}
fprintf(fout,"\n");
fprintf(fout,"]\n[\n");
qDebug("PointsPolygons %i",tt.elapsed());
cbValue = (++step)*cbStep; i=0;
//second step: index of vertex for face
UpdateFlags<SaveMeshType>::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<std::string> 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

View File

@ -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 <Qt>
#include <QtGui>
#include <QMessageBox>
#include <QFileDialog>
#include "io_renderman.h"
#include <wrap/io_trimesh/export_smf.h>
#include <wrap/io_trimesh/import_smf.h>
#include <vcg/complex/trimesh/allocate.h>
#include <vcg/complex/trimesh/polygon_support.h>
#include <common/pluginmanager.h>
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; i<m.cm.textures.size(); i++) {
QString path = QString(m.cm.textures[i].c_str());
textureListPath << path;
}
//***read the template files and create the new scenes files
QStringList shaderDirs, textureDirs, proceduralDirs, imagesRendered;
qDebug("Starting reading cycle %i",tt.elapsed());
if(!makeScene(&m, &textureListPath, par, &templateFile, destDirString, &shaderDirs, &textureDirs, &proceduralDirs, &imagesRendered))
return false; //message already set
qDebug("Cycle ending at %i",tt.elapsed());
Log(GLLogStream::FILTER,"Successfully created scene");
//check if the final rib file will render any image
/*if(imagesRendered.size() == 0) {
this->errorMessage = "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<CMeshO>::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<CMeshO>::ErrorMsg(result)));
return false;
}*/
return true;
}
/*
returns the list of the file's type which can be imported
*/
QList<MeshIOInterface::Format> IORenderman::importFormats() const
{
QList<Format> formatList;
return formatList;
}
/*
returns the list of the file's type which can be exported
*/
QList<MeshIOInterface::Format> IORenderman::exportFormats() const
{
QList<Format> 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<CMeshO>::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)

View File

@ -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 <QObject>
#include <common/interfaces.h>
#include "utilities_hqrender.h"
#include "RibFileStack.h"
#include "export_rib.h"
class IORenderman : public QObject, public MeshIOInterface
{
Q_OBJECT
Q_INTERFACES(MeshIOInterface)
public:
QList<Format> importFormats() const;
QList<Format> 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<vcg::Matrix44f> transfMatrixStack;
QStack<QString> 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

View File

@ -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

View File

@ -0,0 +1,536 @@
#include "io_renderman.h"
#include <limits>
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<float>::min();
for(int i=1; i<6; i=i+2)
objectBound[i] = std::numeric_limits<float>::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<vcg::Matrix44f>();
transfMatrixStack << vcg::Matrix44f::Identity();
surfaceShaderStack = QStack<QString>();
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<Procedure> procedures = QQueue<Procedure>(); //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<float>(ratioX, std::min<float>(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<CMeshO>::Save(m->cm, qPrintable(geometryDest), vcg::tri::io::Mask::IOM_ALL, false, cb);
if(res != vcg::tri::io::ExporterRIB<CMeshO>::E_NOERROR) {
fclose(fout);
this->errorMessage = QString(vcg::tri::io::ExporterRIB<CMeshO>::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<list.size(); i++) {
if(list[i].trimmed().contains('[') || list[i].trimmed().contains(']')) {
list[i] = list[i].remove('[');
list[i] = list[i].remove(']');
}
bool isNumber;
float number = list[i].toFloat(&isNumber);
if(isNumber)
t[k++]=number;
}
vcg::Matrix44f tempMatrix(t);
return tempMatrix.transpose();
}

View File

@ -0,0 +1,191 @@
#include <QHash>
#include <QString>
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<QString, int>* initHash() {
QHash<QString, int>* proc = new QHash<QString,int>();
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; i<str.size(); i++) {
if(str[i] != ' ' && str[i] != '\n') {
if(str[i] == '\\') {
slash = true;
}
if(!slash && str[i] == '\"') {
if(word != "")
list << word.simplified();
list << "\"";
word = "";
string = !string;
}
else {
if((str[i] == '[' || str[i] == ']') && !string) {
if(word != "")
list << word.simplified();
list << QString(str[i]);
word = "";
}
else
word += str[i];
}
}
else { //is a ' ' or \n
if(string) {
word += str[i];
}
else {
if(word != "") { //it's a sequence of
list << word.simplified();
word = "";
}
}
slash = false;
}
}
word = word.simplified();
if(word != "")
list << word;
//foreach(QString s,list)
// qDebug(qPrintable(s));
return list;
}
};

View File

@ -0,0 +1,79 @@
#include "utilities_hqrender.h"
//if path contains a space, is wrapped in quotes (e.g. ..\"Program files"\..)
QString UtilitiesHQR::quotesPath(const QString* path) {
QStringList dirs = path->split(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;
}

View File

@ -0,0 +1,12 @@
#include <QDir.h>
#include <QString.h>
#include <QStringList.h>
#include <math.h>
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);
};