mirror of
https://github.com/lucaspalomodevelop/meshlab.git
synced 2026-03-13 16:14:38 +00:00
397 lines
14 KiB
C++
397 lines
14 KiB
C++
/****************************************************************************
|
|
* MeshLab o o *
|
|
* A versatile mesh processing toolbox o o *
|
|
* _ O _ *
|
|
* Copyright(C) 2005-2008 \/)\/ *
|
|
* 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. *
|
|
* *
|
|
****************************************************************************/
|
|
/****************************************************************************
|
|
History
|
|
$Log$
|
|
Revision 1.4 2007/12/11 16:19:37 corsini
|
|
add mapping between rm code and opengl code
|
|
|
|
Revision 1.3 2007/12/06 14:47:04 corsini
|
|
code restyling
|
|
|
|
Revision 1.2 2007/12/03 10:52:58 corsini
|
|
code restyling
|
|
|
|
|
|
****************************************************************************/
|
|
|
|
// Local headers
|
|
#include "RmXmlParser.h"
|
|
using std::make_pair;
|
|
|
|
|
|
RmXmlParser::RmXmlParser()
|
|
{
|
|
initializeCodeMapping();
|
|
}
|
|
|
|
RmXmlParser::RmXmlParser(QString filename)
|
|
{
|
|
setFileName(filename);
|
|
initializeCodeMapping();
|
|
}
|
|
|
|
void RmXmlParser::initializeCodeMapping()
|
|
{
|
|
// GL_TextureWrapS
|
|
mapcode["GL_TextureWrapS1"] =
|
|
make_pair("GL_CLAMP", GL_CLAMP);
|
|
mapcode["GL_TextureWrapS2"] =
|
|
make_pair("GL_CLAMP_TO_EDGE", GL_CLAMP_TO_EDGE);
|
|
mapcode["GL_TextureWrapS3"] =
|
|
make_pair("GL_REPEAT", GL_REPEAT);
|
|
mapcode["GL_TextureWrapS4"] =
|
|
make_pair("GL_CLAMP_TO_BORDER", GL_CLAMP_TO_BORDER);
|
|
mapcode["GL_TextureWrapS5"] =
|
|
make_pair("GL_MIRRORED_REPEAT", GL_MIRRORED_REPEAT);
|
|
|
|
// GL_TextureWrapT
|
|
mapcode["GL_TextureWrapT1"] =
|
|
make_pair("GL_CLAMP", GL_CLAMP);
|
|
mapcode["GL_TextureWrapT2"] =
|
|
make_pair("GL_CLAMP_TO_EDGE", GL_CLAMP_TO_EDGE);
|
|
mapcode["GL_TextureWrapT3"] =
|
|
make_pair("GL_REPEAT", GL_REPEAT);
|
|
mapcode["GL_TextureWrapT4"] =
|
|
make_pair("GL_CLAMP_TO_BORDER", GL_CLAMP_TO_BORDER);
|
|
mapcode["GL_TextureWrapT5"] =
|
|
make_pair("GL_MIRRORED_REPEAT", GL_MIRRORED_REPEAT);
|
|
|
|
// GL_TextureWrapR
|
|
mapcode["GL_TextureWrapR1"] =
|
|
make_pair("GL_CLAMP", GL_CLAMP);
|
|
mapcode["GL_TextureWrapR2"] =
|
|
make_pair("GL_CLAMP_TO_EDGE", GL_CLAMP_TO_EDGE);
|
|
mapcode["GL_TextureWrapR3"] =
|
|
make_pair("GL_REPEAT", GL_REPEAT);
|
|
mapcode["GL_TextureWrapR4"] =
|
|
make_pair("GL_CLAMP_TO_BORDER", GL_CLAMP_TO_BORDER);
|
|
mapcode["GL_TextureWrapR5"] =
|
|
make_pair("GL_MIRRORED_REPEAT", GL_MIRRORED_REPEAT);
|
|
|
|
|
|
// GL_TextureMagnify
|
|
mapcode["GL_TextureMagnify0"] =
|
|
make_pair("GL_NEAREST", GL_NEAREST);
|
|
mapcode["GL_TextureMagnify1"] =
|
|
make_pair("GL_LINEAR", GL_LINEAR);
|
|
|
|
// GL_TextureMinify
|
|
mapcode["GL_TextureMinify0"] =
|
|
make_pair("GL_NEAREST", GL_NEAREST);
|
|
mapcode["GL_TextureMinify1"] =
|
|
make_pair("GL_LINEAR", GL_LINEAR);
|
|
mapcode["GL_TextureMinify3"] =
|
|
make_pair("GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST);
|
|
mapcode["GL_TextureMagnify4"] =
|
|
make_pair("GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR);
|
|
mapcode["GL_TextureMinify5"] =
|
|
make_pair("GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST);
|
|
mapcode["GL_TextureMinify6"] =
|
|
make_pair("GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR);
|
|
}
|
|
|
|
QString RmXmlParser::convertGlStateToString(GlState &glstate)
|
|
{
|
|
GlParamType par;
|
|
std::stringstream strstream;
|
|
|
|
strstream << glstate.getName().toStdString();
|
|
QString strvalue = QString("%1").arg(glstate.getValue());
|
|
strstream << strvalue.toStdString();
|
|
|
|
par = mapcode[strstream.str()];
|
|
return QString::fromStdString(par.first);
|
|
}
|
|
|
|
int RmXmlParser::convertGlStateToInt(GlState &glstate)
|
|
{
|
|
GlParamType par;
|
|
std::stringstream strstream;
|
|
|
|
strstream << glstate.getName().toStdString();
|
|
QString strvalue = QString("%1").arg(glstate.getValue());
|
|
strstream << strvalue.toStdString();
|
|
|
|
par = mapcode[strstream.str()];
|
|
return par.second;
|
|
}
|
|
|
|
|
|
bool RmXmlParser::parse(QString _filename)
|
|
{
|
|
if (!_filename.isNull())
|
|
setFileName(_filename);
|
|
|
|
QFile file(filename);
|
|
effects.clear();
|
|
|
|
// open the file
|
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
error = "Impossible to open the specified file: ";
|
|
error += filename;
|
|
return false;
|
|
}
|
|
|
|
QString errorMsg;
|
|
int errorLine, errorColumn;
|
|
|
|
// parse the xml document
|
|
if (!doc.setContent(&file, &errorMsg, &errorLine, &errorColumn)) {
|
|
error = QString("Xml Parse Error ") + filename;
|
|
error += QString("(") + QString().setNum(errorLine) +
|
|
QString(",") + QString().setNum(errorColumn) +
|
|
QString("): ") + errorMsg;
|
|
return false;
|
|
}
|
|
|
|
QDomElement root = doc.documentElement();
|
|
|
|
/*
|
|
* This is what i understood and what this parser does.
|
|
* the xml looks like to have one or more RmOpenGLEffect, and each one can
|
|
* contain one or more RmGLPass. The uniform variables are tagged inside the
|
|
* RmGLPass as RmShaderConstant or RmSampler. They are a RmShaderConstant when
|
|
* the type is a "primitive" one (float int vec2, mat4 ..); if they are
|
|
* a RmSampler then they probably refers to a texture. In this case inside the
|
|
* RmGLPass is specified a tag RmTextureObject with the name of variable.
|
|
* This tag tells us the opengl state for the texture and a texture reference.
|
|
* Note, it can happend that in the source code is specified a uniform variable
|
|
* that is not used: in this case no RmShaderConstant neither a RmSampler will
|
|
* appear in RmGLPass.
|
|
*
|
|
* The values of the uniform variable (such as default value, min and max value
|
|
* for RmShaderConstant, and the file name for the RmSampler) are kept in tags
|
|
* at the top level of the xml tree, and they have as tagname something like
|
|
* RmMatrixVariable, RmVectorVariable, RmFloatVariable, Rm2DTextureVariable,
|
|
* RmCubemapVariable etc.. according to the variable type
|
|
*/
|
|
// we're looking for RmOpenGLEffect xml tag
|
|
QDomNodeList list = root.elementsByTagName("RmOpenGLEffect");
|
|
for (int i = 0; i < list.size(); i++) {
|
|
QDomElement effectElement = list.at(i).toElement();
|
|
RmEffect eff(effectElement.attribute("NAME", "name not set"));
|
|
|
|
// each effect has a number (0-n) of RmGLPass.
|
|
QDomNodeList passlist =
|
|
effectElement.elementsByTagName("RmGLPass");
|
|
|
|
for (int j = 0; j < passlist.size(); j++) {
|
|
// get the pass name
|
|
QDomNode passNode = passlist.at(j);
|
|
QDomElement elp = passNode.toElement();
|
|
bool ok;
|
|
int index = elp.attribute("PASS_INDEX").toInt(&ok);
|
|
RmPass pass(elp.attribute("NAME", "name not set"),
|
|
(ok ? index : -1));
|
|
|
|
// openGL state
|
|
QDomElement stateEl =
|
|
passNode.firstChildElement("RmRenderStateBlock");
|
|
|
|
if(!stateEl.isNull()) {
|
|
QDomNodeList statelist =
|
|
stateEl.elementsByTagName("RmState");
|
|
|
|
for (int k = 0; k < statelist.size(); k++) {
|
|
GlState s(statelist.at(k).toElement());
|
|
if (s.isValid())
|
|
pass.addOpenGLState(s);
|
|
}
|
|
}
|
|
|
|
// get the render target
|
|
QDomElement renderEl =
|
|
passNode.firstChildElement("RmRenderTarget");
|
|
if (!renderEl.isNull()) {
|
|
RenderTarget rt(renderEl.attribute("NAME"));
|
|
rt.renderToScreen = renderEl.attribute("RENDER_TO_SCREEN") == "TRUE";
|
|
rt.colorClear = renderEl.attribute("COLOR_CLEAR") == "TRUE";
|
|
rt.depthClear = renderEl.attribute("DEPTH_CLEAR") == "TRUE";
|
|
rt.clearColorValue = renderEl.attribute("CLEAR_COLOR_VALUE").toDouble();
|
|
rt.depthClearValue = renderEl.attribute("DEPTH_CLEAR_VALUE").toDouble();
|
|
pass.setRenderTarget(rt);
|
|
}
|
|
|
|
// get the source code of fragment and vertex program
|
|
QDomNodeList sourcelist =
|
|
elp.elementsByTagName("RmGLShader");
|
|
for (int k = 0; k < sourcelist.size(); k++) {
|
|
QDomNode elnode = sourcelist.at(k);
|
|
QDomElement elsource = elnode.toElement();
|
|
QString name = elsource.attribute("NAME");
|
|
if (name == "Fragment Program" ||
|
|
name == "Fragment Shader") {
|
|
pass.setFragment(elsource.text());
|
|
} else if (name == "Vertex Program" ||
|
|
name == "Vertex Shader") {
|
|
pass.setVertex(elsource.text());
|
|
}
|
|
}
|
|
|
|
// get the name of constant uniform variables and search
|
|
// in the whole document for their values
|
|
QDomNodeList constlist =
|
|
elp.elementsByTagName("RmShaderConstant");
|
|
for (int k = 0; k < constlist.size(); k++) {
|
|
QString name =
|
|
constlist.at(k).toElement().attribute("NAME");
|
|
UniformVar var =
|
|
pass.searchFragmentUniformVariable(name);
|
|
if (!var.isNull()) {
|
|
var.getValueFromXmlDocument(root, effectElement);
|
|
pass.addFragmentUniform(var);
|
|
}
|
|
var = pass.searchVertexUniformVariable(name);
|
|
if (!var.isNull()) {
|
|
var.getValueFromXmlDocument(root, effectElement);
|
|
pass.addVertexUniform(var);
|
|
}
|
|
}
|
|
|
|
// and texture uniform variables
|
|
QDomNodeList textureObjectList = elp.elementsByTagName("RmTextureObject");
|
|
QDomNodeList samplerlist = elp.elementsByTagName("RmSampler");
|
|
for (int k = 0; k < samplerlist.size(); k++) {
|
|
QString name = samplerlist.at(k).toElement().attribute("NAME");
|
|
QString textureName;
|
|
QList<GlState> GLstates;
|
|
|
|
// First get the textureObject xml tag relative to this texture
|
|
for (int q = 0; q < textureObjectList.size(); q++) {
|
|
QDomElement textEl = textureObjectList.at(q).toElement();
|
|
QString toName = textEl.attribute("NAME");
|
|
if (toName == name) {
|
|
QDomElement trEl =
|
|
textEl.firstChildElement("RmTextureReference");
|
|
if (!trEl.isNull())
|
|
textureName = trEl.attribute("NAME");
|
|
|
|
// save the GlStates
|
|
QDomNodeList statesList =
|
|
textEl.elementsByTagName("RmState");
|
|
for (int w = 0; w < statesList.size(); w++) // * LOL! i,j,k,q,w used !
|
|
GLstates.append( statesList.at(w).toElement());
|
|
break;
|
|
}
|
|
}
|
|
|
|
// then search the variable in the source code
|
|
UniformVar var = pass.searchFragmentUniformVariable(name);
|
|
if (!var.isNull()) {
|
|
var.textureName = textureName;
|
|
var.textureGLStates = GLstates;
|
|
var.getValueFromXmlDocument(root, effectElement);
|
|
pass.addFragmentUniform(var);
|
|
}
|
|
|
|
var = pass.searchVertexUniformVariable(name);
|
|
if (!var.isNull()) {
|
|
var.textureName = textureName;
|
|
var.textureGLStates = GLstates;
|
|
var.getValueFromXmlDocument(root, effectElement);
|
|
pass.addVertexUniform(var);
|
|
}
|
|
}
|
|
eff.addPass( pass );
|
|
}
|
|
eff.sortPasses();
|
|
effects.append(eff);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void RmXmlParser::VarDump(bool extendedDump)
|
|
{
|
|
qDebug() << "";
|
|
qDebug() << "Dumping:" << filename;
|
|
qDebug() << "Found" << effects.size() << "RmOpenGLEffect:";
|
|
|
|
for (int i = 0; i < effects.size(); i++) {
|
|
RmEffect eff = effects[i];
|
|
|
|
qDebug() << " RmEffect" << eff.getName() << "with" << eff.size() << "pass";
|
|
for (int j = 0; j < eff.size(); j++) {
|
|
RmPass pass = eff[j];
|
|
|
|
qDebug() << " "
|
|
<< (pass.hasIndex()?
|
|
QString(QString().setNum(pass.getIndex()) + "'").toLatin1().data() :
|
|
QString("").toLatin1().data())
|
|
<< "Pass" << pass.getName() << "on model"
|
|
<< pass.getModelReference()
|
|
<< "(" << pass.getModelReferenceFN().toLatin1().data() << ")";
|
|
|
|
if (pass.hasRenderTarget()) {
|
|
RenderTarget rt = pass.getRenderTarget();
|
|
qDebug() << " Render Target:"
|
|
<< rt.name
|
|
<< (rt.colorClear ?
|
|
" (with color clear: " + QString().setNum(rt.clearColorValue) + ")" :
|
|
"")
|
|
<< (rt.colorClear ?
|
|
" (with depth clear: " + QString().setNum(rt.depthClearValue) + ")" :
|
|
"");
|
|
}
|
|
|
|
if (pass.openGLStatesSize() == 0)
|
|
qDebug() << " with no opengl states set";
|
|
else {
|
|
qDebug() << " with" << pass.openGLStatesSize() << "opengl states set";
|
|
|
|
for (int k = 0; k < pass.openGLStatesSize(); k++)
|
|
qDebug() << " " << pass.getOpenGLState(k).getName() << " (" << QString().setNum(pass.getOpenGLState(k).getState()).toLatin1().data() << ") =>" << pass.getOpenGLState(k).getValue();
|
|
}
|
|
|
|
qDebug() << " - Fragment (" << pass.getFragment().length() << "bytes ): " << pass.getFragment().mid(0, 50).replace( "\n", " " ).replace("\r","") << "...";
|
|
qDebug() << " There are" << pass.fragmentUniformVariableSize() << "uniform variables";
|
|
|
|
for( int k = 0; k < pass.fragmentUniformVariableSize(); k++ )
|
|
pass.getFragmentUniform( k ).VarDump(12, extendedDump);
|
|
|
|
qDebug() << " - Vertex (" << pass.getVertex().length() << "bytes ): " << pass.getVertex().mid(0, 50).replace( "\n", " " ).replace("\r","") << "...";
|
|
qDebug() << " There are" << pass.vertexUniformVariableSize() << "uniform variables";
|
|
|
|
for( int k = 0; k < pass.vertexUniformVariableSize(); k++ )
|
|
pass.getVertexUniform( k ).VarDump(12, extendedDump);
|
|
}
|
|
}
|
|
|
|
qDebug() << "";
|
|
}
|
|
|
|
|
|
|
|
QDomElement RmXmlParser::getDomElement(QDomElement &root, QString tagname, QString name)
|
|
{
|
|
QDomNodeList list = root.elementsByTagName(tagname);
|
|
for (int i = 0; i < list.size(); i++) {
|
|
QString elName = list.at(i).toElement().attribute("NAME");
|
|
if (name == elName)
|
|
return list.at(i).toElement();
|
|
}
|
|
|
|
return QDomElement();
|
|
}
|
|
|