Commit 4144a1be authored by Pierre Kraemer's avatar Pierre Kraemer

allow export meshes during the decimation in Radiance Plugin

parent 918098a5
......@@ -14,7 +14,7 @@
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="1">
<item row="4" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
......@@ -71,13 +71,26 @@
</item>
</widget>
</item>
<item row="2" column="0" colspan="2">
<item row="3" column="0" colspan="2">
<widget class="QPushButton" name="button_decimate">
<property name="text">
<string>Decimate</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QSlider" name="slider_decimationGoal">
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>50</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
......
......@@ -28,6 +28,8 @@ struct MapParameters
selector(NULL)
{}
unsigned int nbVertices;
Utils::VBO* positionVBO;
Utils::VBO* normalVBO;
......@@ -96,12 +98,27 @@ public slots:
void changePositionVBO(const QString& map, const QString& vbo);
void changeNormalVBO(const QString& map, const QString& vbo);
MapHandlerGen* importFromFile(const QString& fileName);
void decimate(const QString& mapName, const QString& positionAttributeName, const QString& normalAttributeName);
void decimate(
const QString& mapName,
const QString& positionAttributeName,
const QString& normalAttributeName,
float decimationGoal,
bool exportMeshes = false,
unsigned int nbExports = 0
);
void exportPLY(const QString& mapName, const QString& positionAttributeName, const QString& normalAttributeName, const QString& filename);
protected:
MapHandlerGen* currentlyDecimatedMap() { return m_currentlyDecimatedMap; }
static void checkNbVerticesAndExport(Surface_Radiance_Plugin* p, const unsigned int* nbVertices);
Surface_Radiance_DockTab* m_dockTab;
QHash<MapHandlerGen*, MapParameters> h_mapParameterSet;
MapHandlerGen* m_currentlyDecimatedMap;
std::vector<unsigned int> exportNbVert;
unsigned int nextExportIndex;
QAction* m_importAction;
};
......
......@@ -226,6 +226,8 @@ MapHandlerGen* Surface_Radiance_Plugin::importFromFile(const QString& fileName)
MapParameters& mapParams = h_mapParameterSet[mhg];
mapParams.nbVertices = Algo::Topo::getNbOrbits<VERTEX>(*map);
mapParams.radiance = map->getAttribute<Utils::SphericalHarmonics<PFP2::REAL, PFP2::VEC3>, VERTEX, PFP2::MAP>("radiance") ;
mapParams.radianceTexture = new Utils::Texture<2, Geom::Vec3f>(GL_FLOAT);
mapParams.param = map->checkAttribute<Geom::Vec2i, VERTEX, PFP2::MAP>("param");
......@@ -279,7 +281,7 @@ MapHandlerGen* Surface_Radiance_Plugin::importFromFile(const QString& fileName)
return NULL;
}
void Surface_Radiance_Plugin::decimate(const QString& mapName, const QString& positionAttributeName, const QString& normalAttributeName)
void Surface_Radiance_Plugin::decimate(const QString& mapName, const QString& positionAttributeName, const QString& normalAttributeName, float decimationGoal, bool exportMeshes, unsigned int nbExports)
{
MapHandler<PFP2>* mh = static_cast<MapHandler<PFP2>*>(m_schnapps->getMap(mapName));
if(mh == NULL)
......@@ -324,12 +326,190 @@ void Surface_Radiance_Plugin::decimate(const QString& mapName, const QString& po
approximators.push_back(mapParams.positionApproximator);
approximators.push_back(mapParams.normalApproximator);
approximators.push_back(mapParams.radianceApproximator);
Algo::Surface::Decimation::decimate<PFP2>(*map, mapParams.selector, approximators, 0.5 * nbVertices);
exportNbVert.clear();
if (exportMeshes)
{
float decimationStep = (1.0 - decimationGoal) / nbExports;
for (unsigned int i = 1; i <= nbExports; ++i)
{
exportNbVert.push_back( (1.0 - (i * decimationStep)) * nbVertices );
}
nextExportIndex = 0;
}
m_currentlyDecimatedMap = mh;
Algo::Surface::Decimation::decimate<PFP2>(*map, mapParams.selector, approximators, decimationGoal * nbVertices, true, NULL, (void (*)(void*, const void*))(Surface_Radiance_Plugin::checkNbVerticesAndExport), (void*)(this));
m_currentlyDecimatedMap = NULL;
mh->notifyConnectivityModification();
mh->notifyAttributeModification(position);
}
void Surface_Radiance_Plugin::checkNbVerticesAndExport(Surface_Radiance_Plugin* p, const unsigned int* nbVertices)
{
if (!p->exportNbVert.empty())
{
MapHandlerGen* mhg = p->currentlyDecimatedMap();
if (*nbVertices == p->exportNbVert[p->nextExportIndex])
{
std::stringstream exportName;
exportName << p->currentlyDecimatedMap()->getName().toStdString() << "_" << *nbVertices << ".ply";
std::cout << "export : " << exportName.str() << std::endl;
p->exportPLY(mhg->getName(), "position", "normal", QString::fromStdString(exportName.str()));
p->nextExportIndex++;
}
}
}
void Surface_Radiance_Plugin::exportPLY(
const QString& mapName,
const QString& positionAttributeName,
const QString& normalAttributeName,
const QString& filename)
{
typedef typename PFP2::MAP MAP;
typedef typename PFP2::REAL REAL;
typedef typename PFP2::VEC3 VEC3;
MapHandler<PFP2>* mh = static_cast<MapHandler<PFP2>*>(m_schnapps->getMap(mapName));
if(mh == NULL)
return;
VertexAttribute<VEC3, MAP> position = mh->getAttribute<VEC3, VERTEX>(positionAttributeName);
if(!position.isValid())
return;
VertexAttribute<VEC3, MAP> normal = mh->getAttribute<VEC3, VERTEX>(normalAttributeName);
if(!normal.isValid())
return;
VertexAttribute<Utils::SphericalHarmonics<REAL, VEC3>, MAP> radiance = h_mapParameterSet[mh].radiance;
if(!radiance.isValid())
return;
// open file
std::ofstream out ;
out.open(filename.toStdString(), std::ios::out | std::ios::binary) ;
if (!out.good())
{
CGoGNerr << "Unable to open file " << CGoGNendl ;
return ;
}
MAP* map = mh->getMap();
unsigned int nbDarts = map->getNbDarts() ;
std::vector<unsigned int> facesSize ;
std::vector<std::vector<unsigned int> > facesIdx ;
facesSize.reserve(nbDarts/3) ;
facesIdx.reserve(nbDarts/3) ;
std::map<unsigned int, unsigned int> vIndex ;
unsigned int vCpt = 0 ;
std::vector<unsigned int> vertices ;
vertices.reserve(nbDarts/6) ;
// Go over all faces
CellMarker<MAP, VERTEX> markV(*map) ;
TraversorF<MAP> t(*map) ;
for(Dart d = t.begin(); d != t.end(); d = t.next())
{
std::vector<unsigned int> fidx ;
fidx.reserve(8) ;
unsigned int degree = 0 ;
Traversor2FV<MAP> tfv(*map, d) ;
for(Dart it = tfv.begin(); it != tfv.end(); it = tfv.next())
{
++degree ;
unsigned int vNum = map->getEmbedding<VERTEX>(it) ;
if(!markV.isMarked(it))
{
markV.mark(it) ;
vIndex[vNum] = vCpt++ ;
vertices.push_back(vNum) ;
}
fidx.push_back(vIndex[vNum]) ;
}
facesSize.push_back(degree) ;
facesIdx.push_back(fidx) ;
}
// Start writing the file
out << "ply" << std::endl ;
// test endianness
union
{
uint32_t i ;
char c[4] ;
} bint = {0x01020304} ;
if (bint.c[0] == 1) // big endian
out << "format binary_big_endian 1.0" << std::endl ;
else
out << "format binary_little_endian 1.0" << std::endl ;
out << "comment File generated by the CGoGN library" << std::endl ;
out << "comment See : http://cgogn.unistra.fr/" << std::endl ;
out << "comment or contact : cgogn@unistra.fr" << std::endl ;
// Vertex elements
out << "element vertex " << vertices.size() << std::endl ;
std::string nameOfTypePly_REAL(nameOfTypePly(position[0][0])) ;
out << "property " << nameOfTypePly_REAL << " x" << std::endl ;
out << "property " << nameOfTypePly_REAL << " y" << std::endl ;
out << "property " << nameOfTypePly_REAL << " z" << std::endl ;
out << "property " << nameOfTypePly_REAL << " nx" << std::endl ;
out << "property " << nameOfTypePly_REAL << " ny" << std::endl ;
out << "property " << nameOfTypePly_REAL << " nz" << std::endl ;
int res = Utils::SphericalHarmonics<REAL, VEC3>::get_resolution() ;
for (int l = 0 ; l <= res ; ++l)
{
for (int m = -l ; m <= l ; ++m)
{
out << "property " << nameOfTypePly_REAL << " SHcoef_" << l << "_" << m << "_r" << std::endl ;
out << "property " << nameOfTypePly_REAL << " SHcoef_" << l << "_" << m << "_g" << std::endl ;
out << "property " << nameOfTypePly_REAL << " SHcoef_" << l << "_" << m << "_b" << std::endl ;
}
}
// Face element
out << "element face " << facesSize.size() << std::endl ;
out << "property list uint8 " << nameOfTypePly(facesIdx[0][0]) << " vertex_indices" << std::endl ;
out << "end_header" << std::endl ;
// binary vertices
for(unsigned int i = 0; i < vertices.size(); ++i)
{
const VEC3& p = position[vertices[i]] ;
out.write((char*)(&(p[0])), sizeof(p)) ;
const VEC3& n = normal[vertices[i]] ;
out.write((char*)(&(n[0])), sizeof(n)) ;
for (int l=0 ; l <= res ; ++l)
{
for (int m=-l ; m <= l ; ++m)
{
const VEC3& r = radiance[vertices[i]].get_coef(l,m) ;
out.write((char*)(&(r[0])), sizeof(r)) ;
}
}
}
// binary faces
for(unsigned int i = 0; i < facesSize.size(); ++i)
{
uint8_t nbe = facesSize[i] ;
out.write((char*)(&nbe), sizeof(uint8_t)) ;
out.write((char*)(&(facesIdx[i][0])), facesSize[i] * sizeof(facesIdx[i][0])) ;
}
out.close() ;
}
Q_EXPORT_PLUGIN2(Surface_Radiance_Plugin, Surface_Radiance_Plugin)
} // namespace SCHNApps
......
......@@ -52,7 +52,7 @@ void Surface_Radiance_DockTab::normalVBOChanged(int index)
void Surface_Radiance_DockTab::decimateClicked()
{
m_plugin->decimate(m_schnapps->getSelectedMap()->getName(), combo_positionVBO->currentText(), combo_normalVBO->currentText());
m_plugin->decimate(m_schnapps->getSelectedMap()->getName(), combo_positionVBO->currentText(), combo_normalVBO->currentText(), slider_decimationGoal->value() / 100.0f);
}
......
......@@ -4,9 +4,10 @@
#include "ui_schnapps.h"
#include "types.h"
#include "slot_debug.h"
#include "PythonQt/PythonQt.h"
#include "PythonQt/gui/PythonQtScriptingConsole.h"
#include "slot_debug.h"
class QVBoxLayout;
class QSplitter;
......@@ -105,7 +106,7 @@ public slots:
void notifySelectedCellSelectorChanged(CellSelectorGen* cs) { DEBUG_EMIT("selectedCellSelectorChanged"); emit(selectedCellSelectorChanged(cs)); }
CellSelectorGen* getSelectedSelector(unsigned int orbit) const;
const StaticPointers& getStaticPointers() const {return m_sp;}
const StaticPointers& getStaticPointers() const { return m_sp; }
/*********************************************************
* MANAGE TEXTURES
......
......@@ -25,14 +25,10 @@ int main(int argc, char* argv[])
// get a smart pointer to the __main__ module of the Python interpreter
PythonQtObjectPtr pythonContext = PythonQt::self()->getMainModule();
// PythonQtScriptingConsole pythonConsole(NULL, pythonContext);
PythonQtScriptingConsole* pythonConsole = new PythonQtScriptingConsole(NULL, pythonContext);
// CGoGN::SCHNApps::SCHNApps* schnapps = new CGoGN::SCHNApps::SCHNApps(app.applicationDirPath(), pythonContext, *pythonConsole);
CGoGN::SCHNApps::SCHNApps schnapps(app.applicationDirPath(), pythonContext, *pythonConsole);
// schnapps->show();
schnapps.show();
pythonContext.addObject("schnapps", &schnapps);
......
......@@ -110,7 +110,6 @@ SCHNApps::SCHNApps(const QString& appPath, PythonQtObjectPtr& pythonContext, Pyt
connect(action_ShowHidePythonDock, SIGNAL(triggered()), this, SLOT(showHidePythonDock()));
connect(action_LoadPythonScript, SIGNAL(triggered()), this, SLOT(loadPythonScriptFromFileDialog()));
// create & setup central widget (views)
m_centralLayout = new QVBoxLayout(centralwidget);
......@@ -130,9 +129,8 @@ SCHNApps::SCHNApps(const QString& appPath, PythonQtObjectPtr& pythonContext, Pyt
// register a first plugins directory
// registerPluginsDirectory(m_appPath + QString("/../lib"));
// using macro in plugins_default_directory.h generated by cmake for lib/Release or lib/Debug auto selection !
// using macro in plugins_default_directory.h generated by cmake for lib/Release or lib/Debug auto selection !
registerPluginsDirectory(QString(PLUGINS_DEFAULT_DIRECTORY));
}
SCHNApps::~SCHNApps()
......
......@@ -93,8 +93,10 @@ int decimate(
std::vector<ApproximatorGen<PFP>*>& a,
unsigned int nbWantedVertices,
bool recomputePriorityList = true,
EdgeAttribute<typename PFP::REAL, typename PFP::MAP>* edgeErrors = NULL,
void (*callback_wrapper)(void*, const void*) = NULL, void* callback_object = NULL
EdgeAttribute<typename PFP::REAL,
typename PFP::MAP>* edgeErrors = NULL,
void (*callback_wrapper)(void*, const void*) = NULL,
void* callback_object = NULL
) ;
} // namespace Decimation
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment