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

allow export meshes during the decimation in Radiance Plugin

parent 918098a5
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
<string>Form</string> <string>Form</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="3" column="1"> <item row="4" column="1">
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
...@@ -71,13 +71,26 @@ ...@@ -71,13 +71,26 @@
</item> </item>
</widget> </widget>
</item> </item>
<item row="2" column="0" colspan="2"> <item row="3" column="0" colspan="2">
<widget class="QPushButton" name="button_decimate"> <widget class="QPushButton" name="button_decimate">
<property name="text"> <property name="text">
<string>Decimate</string> <string>Decimate</string>
</property> </property>
</widget> </widget>
</item> </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> </layout>
</widget> </widget>
<resources/> <resources/>
......
...@@ -28,6 +28,8 @@ struct MapParameters ...@@ -28,6 +28,8 @@ struct MapParameters
selector(NULL) selector(NULL)
{} {}
unsigned int nbVertices;
Utils::VBO* positionVBO; Utils::VBO* positionVBO;
Utils::VBO* normalVBO; Utils::VBO* normalVBO;
...@@ -96,12 +98,27 @@ public slots: ...@@ -96,12 +98,27 @@ public slots:
void changePositionVBO(const QString& map, const QString& vbo); void changePositionVBO(const QString& map, const QString& vbo);
void changeNormalVBO(const QString& map, const QString& vbo); void changeNormalVBO(const QString& map, const QString& vbo);
MapHandlerGen* importFromFile(const QString& fileName); 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: protected:
MapHandlerGen* currentlyDecimatedMap() { return m_currentlyDecimatedMap; }
static void checkNbVerticesAndExport(Surface_Radiance_Plugin* p, const unsigned int* nbVertices);
Surface_Radiance_DockTab* m_dockTab; Surface_Radiance_DockTab* m_dockTab;
QHash<MapHandlerGen*, MapParameters> h_mapParameterSet; QHash<MapHandlerGen*, MapParameters> h_mapParameterSet;
MapHandlerGen* m_currentlyDecimatedMap;
std::vector<unsigned int> exportNbVert;
unsigned int nextExportIndex;
QAction* m_importAction; QAction* m_importAction;
}; };
......
...@@ -226,6 +226,8 @@ MapHandlerGen* Surface_Radiance_Plugin::importFromFile(const QString& fileName) ...@@ -226,6 +226,8 @@ MapHandlerGen* Surface_Radiance_Plugin::importFromFile(const QString& fileName)
MapParameters& mapParams = h_mapParameterSet[mhg]; 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.radiance = map->getAttribute<Utils::SphericalHarmonics<PFP2::REAL, PFP2::VEC3>, VERTEX, PFP2::MAP>("radiance") ;
mapParams.radianceTexture = new Utils::Texture<2, Geom::Vec3f>(GL_FLOAT); mapParams.radianceTexture = new Utils::Texture<2, Geom::Vec3f>(GL_FLOAT);
mapParams.param = map->checkAttribute<Geom::Vec2i, VERTEX, PFP2::MAP>("param"); mapParams.param = map->checkAttribute<Geom::Vec2i, VERTEX, PFP2::MAP>("param");
...@@ -279,7 +281,7 @@ MapHandlerGen* Surface_Radiance_Plugin::importFromFile(const QString& fileName) ...@@ -279,7 +281,7 @@ MapHandlerGen* Surface_Radiance_Plugin::importFromFile(const QString& fileName)
return NULL; 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)); MapHandler<PFP2>* mh = static_cast<MapHandler<PFP2>*>(m_schnapps->getMap(mapName));
if(mh == NULL) if(mh == NULL)
...@@ -324,12 +326,190 @@ void Surface_Radiance_Plugin::decimate(const QString& mapName, const QString& po ...@@ -324,12 +326,190 @@ void Surface_Radiance_Plugin::decimate(const QString& mapName, const QString& po
approximators.push_back(mapParams.positionApproximator); approximators.push_back(mapParams.positionApproximator);
approximators.push_back(mapParams.normalApproximator); approximators.push_back(mapParams.normalApproximator);
approximators.push_back(mapParams.radianceApproximator); 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->notifyConnectivityModification();
mh->notifyAttributeModification(position); 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) Q_EXPORT_PLUGIN2(Surface_Radiance_Plugin, Surface_Radiance_Plugin)
} // namespace SCHNApps } // namespace SCHNApps
......
...@@ -52,7 +52,7 @@ void Surface_Radiance_DockTab::normalVBOChanged(int index) ...@@ -52,7 +52,7 @@ void Surface_Radiance_DockTab::normalVBOChanged(int index)
void Surface_Radiance_DockTab::decimateClicked() 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 @@ ...@@ -4,9 +4,10 @@
#include "ui_schnapps.h" #include "ui_schnapps.h"
#include "types.h" #include "types.h"
#include "slot_debug.h"
#include "PythonQt/PythonQt.h" #include "PythonQt/PythonQt.h"
#include "PythonQt/gui/PythonQtScriptingConsole.h" #include "PythonQt/gui/PythonQtScriptingConsole.h"
#include "slot_debug.h"
class QVBoxLayout; class QVBoxLayout;
class QSplitter; class QSplitter;
...@@ -105,7 +106,7 @@ public slots: ...@@ -105,7 +106,7 @@ public slots:
void notifySelectedCellSelectorChanged(CellSelectorGen* cs) { DEBUG_EMIT("selectedCellSelectorChanged"); emit(selectedCellSelectorChanged(cs)); } void notifySelectedCellSelectorChanged(CellSelectorGen* cs) { DEBUG_EMIT("selectedCellSelectorChanged"); emit(selectedCellSelectorChanged(cs)); }
CellSelectorGen* getSelectedSelector(unsigned int orbit) const; CellSelectorGen* getSelectedSelector(unsigned int orbit) const;
const StaticPointers& getStaticPointers() const {return m_sp;} const StaticPointers& getStaticPointers() const { return m_sp; }
/********************************************************* /*********************************************************
* MANAGE TEXTURES * MANAGE TEXTURES
......
...@@ -25,14 +25,10 @@ int main(int argc, char* argv[]) ...@@ -25,14 +25,10 @@ int main(int argc, char* argv[])
// get a smart pointer to the __main__ module of the Python interpreter // get a smart pointer to the __main__ module of the Python interpreter
PythonQtObjectPtr pythonContext = PythonQt::self()->getMainModule(); PythonQtObjectPtr pythonContext = PythonQt::self()->getMainModule();
// PythonQtScriptingConsole pythonConsole(NULL, pythonContext);
PythonQtScriptingConsole* pythonConsole = new PythonQtScriptingConsole(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); CGoGN::SCHNApps::SCHNApps schnapps(app.applicationDirPath(), pythonContext, *pythonConsole);
// schnapps->show();
schnapps.show(); schnapps.show();
pythonContext.addObject("schnapps", &schnapps); pythonContext.addObject("schnapps", &schnapps);
......
...@@ -110,7 +110,6 @@ SCHNApps::SCHNApps(const QString& appPath, PythonQtObjectPtr& pythonContext, Pyt ...@@ -110,7 +110,6 @@ SCHNApps::SCHNApps(const QString& appPath, PythonQtObjectPtr& pythonContext, Pyt
connect(action_ShowHidePythonDock, SIGNAL(triggered()), this, SLOT(showHidePythonDock())); connect(action_ShowHidePythonDock, SIGNAL(triggered()), this, SLOT(showHidePythonDock()));
connect(action_LoadPythonScript, SIGNAL(triggered()), this, SLOT(loadPythonScriptFromFileDialog())); connect(action_LoadPythonScript, SIGNAL(triggered()), this, SLOT(loadPythonScriptFromFileDialog()));
// create & setup central widget (views) // create & setup central widget (views)
m_centralLayout = new QVBoxLayout(centralwidget); m_centralLayout = new QVBoxLayout(centralwidget);
...@@ -130,9 +129,8 @@ SCHNApps::SCHNApps(const QString& appPath, PythonQtObjectPtr& pythonContext, Pyt ...@@ -130,9 +129,8 @@ SCHNApps::SCHNApps(const QString& appPath, PythonQtObjectPtr& pythonContext, Pyt
// register a first plugins directory // register a first plugins directory
// registerPluginsDirectory(m_appPath + QString("/../lib")); // 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)); registerPluginsDirectory(QString(PLUGINS_DEFAULT_DIRECTORY));
} }
SCHNApps::~SCHNApps() SCHNApps::~SCHNApps()
......
...@@ -93,8 +93,10 @@ int decimate( ...@@ -93,8 +93,10 @@ int decimate(
std::vector<ApproximatorGen<PFP>*>& a, std::vector<ApproximatorGen<PFP>*>& a,
unsigned int nbWantedVertices, unsigned int nbWantedVertices,
bool recomputePriorityList = true, bool recomputePriorityList = true,
EdgeAttribute<typename PFP::REAL, typename PFP::MAP>* edgeErrors = NULL, EdgeAttribute<typename PFP::REAL,
void (*callback_wrapper)(void*, const void*) = NULL, void* callback_object = NULL typename PFP::MAP>* edgeErrors = NULL,
void (*callback_wrapper)(void*, const void*) = NULL,
void* callback_object = NULL
) ; ) ;
} // namespace Decimation } // 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