mirror of
https://github.com/lucaspalomodevelop/meshlab.git
synced 2026-03-15 17:14:39 +00:00
io_renderman plugin
This commit is contained in:
parent
ccf50d84e5
commit
e70ba0202b
216
src/sampleplugins/io_m/RibFileStack.cpp
Normal file
216
src/sampleplugins/io_m/RibFileStack.cpp
Normal 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;
|
||||
};
|
||||
|
||||
36
src/sampleplugins/io_m/RibFileStack.h
Normal file
36
src/sampleplugins/io_m/RibFileStack.h
Normal 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;
|
||||
|
||||
|
||||
};
|
||||
240
src/sampleplugins/io_m/export_rib.h
Normal file
240
src/sampleplugins/io_m/export_rib.h
Normal 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
|
||||
231
src/sampleplugins/io_m/io_renderman.cpp
Normal file
231
src/sampleplugins/io_m/io_renderman.cpp
Normal 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)
|
||||
81
src/sampleplugins/io_m/io_renderman.h
Normal file
81
src/sampleplugins/io_m/io_renderman.h
Normal 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
|
||||
14
src/sampleplugins/io_m/io_renderman.pro
Normal file
14
src/sampleplugins/io_m/io_renderman.pro
Normal 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
|
||||
536
src/sampleplugins/io_m/parser_rib.cpp
Normal file
536
src/sampleplugins/io_m/parser_rib.cpp
Normal 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();
|
||||
}
|
||||
191
src/sampleplugins/io_m/ribProcedure.h
Normal file
191
src/sampleplugins/io_m/ribProcedure.h
Normal 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;
|
||||
}
|
||||
};
|
||||
79
src/sampleplugins/io_m/utilities_hqrender.cpp
Normal file
79
src/sampleplugins/io_m/utilities_hqrender.cpp
Normal 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;
|
||||
}
|
||||
12
src/sampleplugins/io_m/utilities_hqrender.h
Normal file
12
src/sampleplugins/io_m/utilities_hqrender.h
Normal 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);
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user