Commit 69a82e95 authored by untereiner's avatar untereiner

Merge cgogn:~maire/CGoGN

parents ac0562e7 31366e50
SET(EXECUTABLE_OUTPUT_PATH ${CGoGN_ROOT_DIR}/bin)
SET (COMMON_LIBS ${GLUT_LIBRARY} ${OPENGL_LIBRARY} ${GLEW_LIBRARY} ${DEVIL_LIBRARIES} ${ZLIB_LIBRARIES} ${LIBXML2_LIBRARIES} gzstream AntTweakBar openctm assimp)
BOOST_LIBS(boost_regex_lib_lists "boost_regex-mt")
SET (COMMON_LIBS ${GLUT_LIBRARY} ${OPENGL_LIBRARY} ${GLEW_LIBRARY} ${DEVIL_LIBRARIES} ${ZLIB_LIBRARIES} ${LIBXML2_LIBRARIES} ${boost_regex_lib_lists} gzstream AntTweakBar openctm assimp)
SET(CGoGN_LIBS_R topology algo container utils)
......
......@@ -59,3 +59,9 @@ add_executable( viewerD ../viewer.cpp ${viewer_moc} ${viewer_ui})
target_link_libraries( viewerD
${CGoGN_LIBS_D} ${NUMERICAL_LIBS} ${COMMON_LIBS} ${QT_LIBRARIES} )
QT4_WRAP_UI( clipping_ui ../clipping.ui )
QT4_WRAP_CPP( clipping_moc ../clipping.h )
add_executable( clippingD ../clipping.cpp ${clipping_ui} ${clipping_moc})
target_link_libraries( clippingD
${CGoGN_LIBS_D} ${COMMON_LIBS} ${QT_LIBRARIES} )
......@@ -63,3 +63,9 @@ add_executable( viewer ../viewer.cpp ${viewer_moc} ${viewer_ui})
target_link_libraries( viewer
${CGoGN_LIBS_R} ${NUMERICAL_LIBS} ${COMMON_LIBS} ${QT_LIBRARIES} )
QT4_WRAP_UI( clipping_ui ../clipping.ui )
QT4_WRAP_CPP( clipping_moc ../clipping.h )
add_executable( clipping ../clipping.cpp ${clipping_ui} ${clipping_moc})
target_link_libraries( clipping
${CGoGN_LIBS_D} ${COMMON_LIBS} ${QT_LIBRARIES} )
......@@ -22,95 +22,227 @@
* *
*******************************************************************************/
#include "stage_shader.h"
#include "clipping.h"
#include "Utils/static_assert.h"
/*******************************************************************************
* SLOTS
*******************************************************************************/
void StageShader::slot_drawTopo(bool b)
void Clipping::slot_drawTopo(bool b)
{
m_drawTopo = b;
updateGL();
}
void StageShader::slot_drawVertices(bool b)
void Clipping::slot_drawVertices(bool b)
{
m_drawVertices = b;
updateGL();
}
void StageShader::slot_drawLines(bool b)
void Clipping::slot_drawLines(bool b)
{
m_drawLines = b;
updateGL();
}
void StageShader::slot_drawFaces(bool b)
void Clipping::slot_drawFaces(bool b)
{
m_drawFaces = b;
updateGL();
}
void StageShader::slot_explodTopoPhi1(double c)
void Clipping::slot_explodTopoPhi1(double c)
{
m_coeffTopoExplod[0] = (float)c;
m_render_topo->updateData<PFP>(myMap, allDarts, position, m_coeffTopoExplod[0], m_coeffTopoExplod[1], m_coeffTopoExplod[2]);
updateGL();
}
void StageShader::slot_explodTopoPhi2(double c)
void Clipping::slot_explodTopoPhi2(double c)
{
m_coeffTopoExplod[1] = (float)c;
m_render_topo->updateData<PFP>(myMap, allDarts, position, m_coeffTopoExplod[0], m_coeffTopoExplod[1], m_coeffTopoExplod[2]);
updateGL();
}
void StageShader::slot_explodTopoPhi3(double c)
void Clipping::slot_explodTopoPhi3(double c)
{
m_coeffTopoExplod[2] = (float)c;
m_render_topo->updateData<PFP>(myMap, allDarts, position, m_coeffTopoExplod[0], m_coeffTopoExplod[1], m_coeffTopoExplod[2]);
updateGL();
}
void StageShader::button_compile()
void Clipping::slot_pushButton_addPlane()
{
QString st1 = dynamic_cast<Utils::QT::uiDockInterface*>(dockWidget())->vertexEdit->toPlainText();
QString st2 = dynamic_cast<Utils::QT::uiDockInterface*>(dockWidget())->fragmentEdit->toPlainText();
QString st3 = dynamic_cast<Utils::QT::uiDockInterface*>(dockWidget())->geometryEdit->toPlainText();
// Create clipping and pickable objects
int newPlaneId = m_shader->addClipPlane();
Utils::Pickable* pickable = new Utils::Pickable(m_planeDrawable, newPlaneId);
m_pickablePlanes.push_back(pickable);
m_shader->reloadVertexShaderFromMemory(st1.toStdString().c_str());
m_shader->reloadFragmentShaderFromMemory(st2.toStdString().c_str());
m_shader->reloadGeometryShaderFromMemory(st3.toStdString().c_str());
// Set params
m_shader->setClipPlaneParamsOrigin(newPlaneId, m_bb.center());
pickable->translate(m_bb.center());
// Update shader sources edits
dock.vertexEdit->setPlainText(QString(m_shader->getVertexShaderSrc()));
dock.fragmentEdit->setPlainText(QString(m_shader->getFragmentShaderSrc()));
m_shader->recompile();
updateGLMatrices();
}
/*******************************************************************************
* QT TRICK
*******************************************************************************/
void Clipping::slot_spinBox_GridResolution(int i)
{
m_planeDrawable->updatePrecisionDrawing(i);
updateGL();
}
void Clipping::slot_pushButton_changePlanesColor()
{
QColor NewColor;
QColorDialog ColDialog;
NewColor = ColDialog.getColor();
int r, g, b;
NewColor.getRgb(&r, &g, &b);
m_planeDrawable->setColor(Geom::Vec4f((float)r/255.0, (float)g/255.0, (float)b/255.0, 1.0));
}
void Clipping::slot_pushButton_addSphere()
{
// Create clipping and pickable objects
int newSphereId = m_shader->addClipSphere();
Utils::Pickable* pickable = new Utils::Pickable(m_sphereDrawable, newSphereId);
m_pickableSpheres.push_back(pickable);
// Set params
m_shader->setClipSphereParamsCenter(newSphereId, m_bb.center());
m_shader->setClipSphereParamsRadius(newSphereId, (m_bb.maxSize())*1.0);
pickable->translate(m_bb.center());
pickable->scale(Geom::Vec3f(m_bb.maxSize()*1.0));
// Update shader sources edits
dock.vertexEdit->setPlainText(QString(m_shader->getVertexShaderSrc()));
dock.fragmentEdit->setPlainText(QString(m_shader->getFragmentShaderSrc()));
updateGLMatrices();
}
void Clipping::slot_spinBox_SphereResolution(int i)
{
m_sphereDrawable->updatePrecisionDrawing(i);
updateGL();
}
void Clipping::slot_pushButton_changeSpheresColor()
{
QColor NewColor;
QColorDialog ColDialog;
NewColor = ColDialog.getColor();
int r, g, b;
NewColor.getRgb(&r, &g, &b);
m_sphereDrawable->setColor(Geom::Vec4f((float)r/255.0, (float)g/255.0, (float)b/255.0, 1.0));
}
void Clipping::slot_doubleSpinBox_ColorAttenuationFactor(double c)
{
m_shader->setClipColorAttenuationFactor((float)c);
updateGL();
}
void Clipping::slot_radioButton_ClippingMode(bool b)
{
if (b)
m_shader->setClipMode(Utils::ClippingShader::CLIPPING_MODE_AND);
else
m_shader->setClipMode(Utils::ClippingShader::CLIPPING_MODE_OR);
dock.vertexEdit->setPlainText(QString(m_shader->getVertexShaderSrc()));
dock.fragmentEdit->setPlainText(QString(m_shader->getFragmentShaderSrc()));
updateGLMatrices();
}
void StageShader::dockWidget_topLevelChanged(bool isFloating)
void Clipping::slot_radioButton_ColorAttenuationMode(bool b)
{
if(isFloating)
if (b)
m_shader->setClipColorAttenuationMode(Utils::ClippingShader::COLOR_ATTENUATION_MODE_LINEAR);
else
m_shader->setClipColorAttenuationMode(Utils::ClippingShader::COLOR_ATTENUATION_MODE_QUADRATIC);
dock.vertexEdit->setPlainText(QString(m_shader->getVertexShaderSrc()));
dock.fragmentEdit->setPlainText(QString(m_shader->getFragmentShaderSrc()));
updateGLMatrices();
}
void Clipping::slot_pushButton_deleteSelectedObject()
{
if (m_lastPickedObject)
{
dockWidget()->setWindowFlags(Qt::Window);
// Delete clipping object
if (m_lastPickedObject->checkType<Utils::Grid>())
m_shader->deleteClipPlane(m_lastPickedObject->id());
else if (m_lastPickedObject->checkType<Utils::Sphere>())
m_shader->deleteClipSphere(m_lastPickedObject->id());
// Delete pickable
if (m_lastPickedObject->checkType<Utils::Grid>())
{
for (size_t i = 0; i < m_pickablePlanes.size(); i++)
{
if (m_pickablePlanes[i] == m_lastPickedObject)
{
delete m_pickablePlanes[i];
m_pickablePlanes.erase(m_pickablePlanes.begin() + i);
}
}
}
else if (m_lastPickedObject->checkType<Utils::Sphere>())
{
for (size_t i = 0; i < m_pickableSpheres.size(); i++)
{
if (m_pickableSpheres[i] == m_lastPickedObject)
{
delete m_pickableSpheres[i];
m_pickableSpheres.erase(m_pickableSpheres.begin() + i);
}
}
}
m_lastPickedObject = NULL;
// Update shader sources edits
dock.vertexEdit->setPlainText(QString(m_shader->getVertexShaderSrc()));
dock.fragmentEdit->setPlainText(QString(m_shader->getFragmentShaderSrc()));
updateGLMatrices();
// setWindowFlags calls setParent() when changing the flags for a window, causing the widget to be hidden.
// You must call show() to make the widget visible again
dockWidget()->show();
}
}
void Clipping::button_compile()
{
QString st1 = dynamic_cast<Utils::QT::uiDockInterface*>(dockWidget())->vertexEdit->toPlainText();
QString st2 = dynamic_cast<Utils::QT::uiDockInterface*>(dockWidget())->fragmentEdit->toPlainText();
m_shader->reloadVertexShaderFromMemory(st1.toStdString().c_str());
m_shader->reloadFragmentShaderFromMemory(st2.toStdString().c_str());
m_shader->recompile();
updateGLMatrices();
}
/*******************************************************************************
* Init Functions
*******************************************************************************/
StageShader::StageShader():
Clipping::Clipping():
m_drawVertices(false),
m_drawLines(true),
m_drawFaces(true),
......@@ -123,10 +255,10 @@ StageShader::StageShader():
m_coeffTopoExplod = Geom::Vec3f(0.9,0.9,0.9);
}
void StageShader::initGUI()
void Clipping::initGUI()
{
CGoGNStream::allToConsole(this) ;
CGoGNStream::allToStd(false) ;
CGoGNStream::allToStd(true) ;
setDock(&dock);
......@@ -135,23 +267,58 @@ void StageShader::initGUI()
setCallBack(dock.checkBox_vertices, SIGNAL(toggled(bool)), SLOT(slot_drawVertices(bool)));
setCallBack(dock.checkBox_lines, SIGNAL(toggled(bool)), SLOT(slot_drawLines(bool)));
setCallBack(dock.checkBox_faces, SIGNAL(toggled(bool)), SLOT(slot_drawFaces(bool)));
setCallBack( dock.groupBox_topo, SIGNAL(toggled(bool)), SLOT(slot_drawTopo(bool)));
setCallBack(dock.groupBox_topo, SIGNAL(toggled(bool)), SLOT(slot_drawTopo(bool)));
setCallBack(dock.explod_phi1, SIGNAL(valueChanged(double)), SLOT(slot_explodTopoPhi1(double)));
setCallBack(dock.explod_phi2, SIGNAL(valueChanged(double)), SLOT(slot_explodTopoPhi2(double)));
setCallBack(dock.explod_phi3, SIGNAL(valueChanged(double)), SLOT(slot_explodTopoPhi3(double)));
setCallBack(&dock, SIGNAL(topLevelChanged(bool)), SLOT(dockWidget_topLevelChanged(bool)));
setCallBack(dock.pushButton_addPlane, SIGNAL(clicked()), SLOT(slot_pushButton_addPlane()));
setCallBack(dock.spinBox_GridResolution, SIGNAL(valueChanged(int)), SLOT(slot_spinBox_GridResolution(int)));
setCallBack(dock.pushButton_changePlanesColor, SIGNAL(clicked()), SLOT(slot_pushButton_changePlanesColor()));
setCallBack(dock.compileButton, SIGNAL(clicked()), SLOT(button_compile()) );
setCallBack(dock.compileButton, SIGNAL(clicked()), SLOT(button_compile()));
dock.vertexEdit->setPlainText(QString(m_shader->getVertexShaderSrc()));
dock.fragmentEdit->setPlainText(QString(m_shader->getFragmentShaderSrc()));
dock.geometryEdit->setPlainText(QString(m_shader->getGeometryShaderSrc()));
unsigned int planesPrecision1, planesPrecision2;
m_planeDrawable->getPrecisionDrawing(planesPrecision1, planesPrecision2);
dock.spinBox_GridResolution->setValue(planesPrecision1);
setCallBack(dock.pushButton_addSphere, SIGNAL(clicked()), SLOT(slot_pushButton_addSphere()));
setCallBack(dock.spinBox_SphereResolution, SIGNAL(valueChanged(int)), SLOT(slot_spinBox_SphereResolution(int)));
setCallBack(dock.pushButton_changeSpheresColor, SIGNAL(clicked()), SLOT(slot_pushButton_changeSpheresColor()));
unsigned int spheresPrecision1, spheresPrecision2;
m_sphereDrawable->getPrecisionDrawing(spheresPrecision1, spheresPrecision2);
dock.spinBox_SphereResolution->setValue(spheresPrecision1);
setCallBack(dock.doubleSpinBox_ColorAttenuationFactor, SIGNAL(valueChanged(double)), SLOT(slot_doubleSpinBox_ColorAttenuationFactor(double)));
setCallBack(dock.radioButton_ClippingModeAnd, SIGNAL(toggled(bool)), SLOT(slot_radioButton_ClippingMode(bool)));
setCallBack(dock.radioButton_ColorAttenuationModeLinear, SIGNAL(toggled(bool)), SLOT(slot_radioButton_ColorAttenuationMode(bool)));
dock.doubleSpinBox_ColorAttenuationFactor->setValue(m_shader->getClipColorAttenuationFactor());
Utils::ClippingShader::clippingMode clipMode = m_shader->getClipMode();
if (clipMode == Utils::ClippingShader::CLIPPING_MODE_AND)
dock.radioButton_ClippingModeAnd->setChecked(true);
else if (clipMode == Utils::ClippingShader::CLIPPING_MODE_OR)
dock.radioButton_ClippingModeOr->setChecked(true);
Utils::ClippingShader::colorAttenuationMode colorAttMode = m_shader->getClipColorAttenuationMode();
if (colorAttMode == Utils::ClippingShader::COLOR_ATTENUATION_MODE_LINEAR)
dock.radioButton_ColorAttenuationModeLinear->setChecked(true);
else if (colorAttMode == Utils::ClippingShader::COLOR_ATTENUATION_MODE_QUADRATIC)
dock.radioButton_ColorAttenuationModeQuadratic->setChecked(true);
}
void StageShader::cb_Open()
void Clipping::cb_Open()
{
std::string filters("all (*.*)") ;
std::string filename = selectFile("Open Mesh", "", filters) ;
......@@ -160,7 +327,7 @@ void StageShader::cb_Open()
updateGL() ;
}
void StageShader::importMesh(std::string& filename)
void Clipping::importMesh(std::string& filename)
{
std::vector<std::string> attrNames ;
......@@ -195,25 +362,25 @@ void StageShader::importMesh(std::string& filename)
m_render_topo->updateData<PFP>(myMap, allDarts, position, m_coeffTopoExplod[0], m_coeffTopoExplod[1], m_coeffTopoExplod[2]);
Geom::BoundingBox<PFP::VEC3> bb = Algo::Geometry::computeBoundingBox<PFP>(myMap, position) ;
gPosObj = bb.center() ;
float tailleX = bb.size(0) ;
float tailleY = bb.size(1) ;
float tailleZ = bb.size(2) ;
m_bb = Algo::Geometry::computeBoundingBox<PFP>(myMap, position) ;
gPosObj = m_bb.center() ;
float tailleX = m_bb.size(0) ;
float tailleY = m_bb.size(1) ;
float tailleZ = m_bb.size(2) ;
gWidthObj = std::max<float>(std::max<float>(tailleX, tailleY), tailleZ) ;
m_positionVBO->updateData(position) ;
setParamObject(gWidthObj, gPosObj.data()) ;
updateGLMatrices() ;
updateGLMatrices();
}
/*******************************************************************************
* GL FUNCTIONS
*******************************************************************************/
void StageShader::cb_initGL()
void Clipping::cb_initGL()
{
// choose to use GL version 2
Utils::GLSLShader::setCurrentOGLVersion(2);
......@@ -231,27 +398,36 @@ void StageShader::cb_initGL()
m_shader->setColor(Geom::Vec4f(0.,1.,0.,0.));
registerShader(m_shader);
// setup clipping
m_shader->insertClippingCode();
// setup clipping shapes
m_planeDrawable = new Utils::Grid;
m_planeDrawable->setColor(Geom::Vec4f(1.0, 0.0, 0.0, 1.0));
m_planeDrawable->updatePrecisionDrawing(5);
m_sphereDrawable = new Utils::IcoSphere;
m_sphereDrawable->setColor(Geom::Vec4f(0.0, 0.4, 1.0, 1.0));
m_sphereDrawable->updatePrecisionDrawing(1);
// setup clipping picking frame
m_frameManipulator = new Utils::FrameManipulator();
m_lastPickedObject = NULL;
}
void StageShader::updateVBOprimitives(int upType)
void Clipping::updateVBOprimitives(int upType)
{
if(upType & Algo::Render::GL2::TRIANGLES)
{
m_render->initPrimitives<PFP>(myMap, allDarts, Algo::Render::GL2::TRIANGLES) ;
}
if(upType & Algo::Render::GL2::LINES)
{
m_render->initPrimitives<PFP>(myMap, allDarts, Algo::Render::GL2::LINES,false) ;
}
if(upType & Algo::Render::GL2::POINTS)
{
m_render->initPrimitives<PFP>(myMap, allDarts, Algo::Render::GL2::POINTS) ;
}
}
void StageShader::cb_redraw()
void Clipping::cb_redraw()
{
if(m_drawVertices)
{
......@@ -280,15 +456,168 @@ void StageShader::cb_redraw()
if (m_drawTopo)
m_render_topo->drawTopo();
// Display clipping shapes
for (size_t i = 0; i < m_pickablePlanes.size(); i++)
{
if (m_pickablePlanes[i] == m_lastPickedObject)
glLineWidth(5.0);
else
glLineWidth(2.0);
m_pickablePlanes[i]->draw();
}
for (size_t i = 0; i < m_pickableSpheres.size(); i++)
{
if (m_pickableSpheres[i] == m_lastPickedObject)
glLineWidth(5.0);
else
glLineWidth(2.0);
m_pickableSpheres[i]->draw();
}
// Display picking frame
if (m_lastPickedObject)
m_frameManipulator->draw();
}
void StageShader::cb_keyPress(int code)
void Clipping::cb_keyPress(int code)
{
switch (code)
{
case 16777223 : // Suppr
slot_pushButton_deleteSelectedObject();
break;
}
}
void Clipping::cb_mousePress(int button, int x, int y)
{
if (!Shift())
return;
m_lastClickedX = x;
m_lastClickedY = y;
// get ray of selection
Geom::Vec3f rayA, rayB;
float dist = getOrthoScreenRay(x, y, rayA, rayB);
Geom::Vec3f AB = rayB - rayA;
unsigned int newPickedFrameAxis = 0;
unsigned int lastPickedFrameAxis = m_frameManipulatorPickedAxis;
if (m_lastPickedObject) // an object is already picked ? => frame is drawn
{
// picking the frame -> axis
newPickedFrameAxis = m_frameManipulator->pick(rayA, AB, dist);
m_frameManipulatorPickedAxis = newPickedFrameAxis;
// highlight new axis
if (lastPickedFrameAxis != newPickedFrameAxis)
m_frameManipulator->highlight(m_frameManipulatorPickedAxis);
}
if (newPickedFrameAxis == 0) // frame not picked -> pick the pickable objects
{
std::vector<Utils::Pickable*> tempo = m_pickablePlanes;
tempo.insert(tempo.end(), m_pickableSpheres.begin(), m_pickableSpheres.end());
m_lastPickedObject = Utils::Pickable::pick(tempo, rayA, AB);
// set FrameManipulator on picked object
if (m_lastPickedObject)
{
m_frameManipulator->setTransformation(m_lastPickedObject->transfo());
// Lock individual scale axes for the sphere
if (m_lastPickedObject->checkType<Utils::Grid>())
m_frameManipulator->unlock(Utils::FrameManipulator::Scales);
else if (m_lastPickedObject->checkType<Utils::Sphere>())
m_frameManipulator->lock(Utils::FrameManipulator::Scales);
}
}
// store origin & selected axis on screen projection for easy manipulation.
m_frameManipulator->storeProjection(m_frameManipulatorPickedAxis);
updateGL();
}
void StageShader::cb_mousePress(int button, int x, int y)
void Clipping::cb_mouseMove(int buttons, int x, int y)
{
if (!Shift())
return;
bool clippingUpdateNeeded = false;
// rotation selected ?
if (Utils::FrameManipulator::rotationAxis(m_frameManipulatorPickedAxis))
{
if (buttons & 1)
{
float angle = m_frameManipulator->angleFromMouse(x, y, x - m_lastClickedX, y - m_lastClickedY);
m_frameManipulator->rotate(m_frameManipulatorPickedAxis, angle);
}
else if (buttons & 2)
m_frameManipulator->rotateInScreen(x - m_lastClickedX, y - m_lastClickedY);
m_lastPickedObject->transfo() = m_frameManipulator->transfo();
clippingUpdateNeeded = true;
}
// translation selected
else if (Utils::FrameManipulator::translationAxis(m_frameManipulatorPickedAxis))
{
if (buttons & 1)
{
float dist = m_frameManipulator->distanceFromMouse(x - m_lastClickedX, y - m_lastClickedY);
m_frameManipulator->translate(m_frameManipulatorPickedAxis, dist);
}
else if (buttons & 2)
m_frameManipulator->translateInScreen(x - m_lastClickedX, y - m_lastClickedY);
m_lastPickedObject->transfo() = m_frameManipulator->transfo();
clippingUpdateNeeded = true;
}
// scale selected
else if (Utils::FrameManipulator::scaleAxis(m_frameManipulatorPickedAxis) )
{
float scale = m_frameManipulator->scaleFromMouse(x - m_lastClickedX, y - m_lastClickedY);
m_frameManipulator->scale(m_frameManipulatorPickedAxis, scale );
m_lastPickedObject->transfo() = m_frameManipulator->transfo();
clippingUpdateNeeded = true;
}
// Update clipping shape if needed
if (clippingUpdateNeeded && m_lastPickedObject)
{
if (m_lastPickedObject->checkType<Utils::Grid>())
{
// Get plane position and normal
Geom::Vec3f planeNewPos = m_lastPickedObject->getPosition();
float planeNewAxisScale; // Not used
Geom::Vec3f planeNewNormal = m_lastPickedObject->getAxisScale(2, planeNewAxisScale); // 2 = Z axis = plane normal
// Update clipping shape
m_shader->setClipPlaneParamsAll(m_lastPickedObject->id(), planeNewNormal, planeNewPos);
}
else if (m_lastPickedObject->checkType<Utils::Sphere>())
{
// Get sphere position and size
Geom::Vec3f sphereNewPos = m_lastPickedObject->getPosition();
float sphereNewSize;
m_lastPickedObject->getAxisScale(0, sphereNewSize); // On the sphere, every axis has the same size, so take 0 as default
// Update clipping shape
m_shader->setClipSphereParamsAll(m_lastPickedObject->id(), sphereNewPos, sphereNewSize);
}
}
m_lastClickedX = x;
m_lastClickedY = y;
updateGL();
}
......@@ -298,16 +627,16 @@ void StageShader::cb_mousePress(int button, int x, int y)
int main(int argc, char** argv)
{
QApplication app(argc, argv) ;
QApplication app(argc, argv);