Commit 18f6fa30 authored by Pierre Kraemer's avatar Pierre Kraemer
Browse files

suppression exemple linearTest

parent 1b96b9f3
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps *
* version 0.1 *
* Copyright (C) 2009, IGG Team, LSIIT, University of Strasbourg *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your *
* option) any later version. *
* *
* This library 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 Lesser General Public License *
* for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this library; if not, write to the Free Software Foundation, *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
* *
* Web site: https://iggservis.u-strasbg.fr/CGoGN/ *
* Contact information: cgogn@unistra.fr *
* *
*******************************************************************************/
#include "linearTest.h"
/**********************************************************************************************
* AntTweakBar CALLBACKS *
**********************************************************************************************/
void TW_CALL setRenderStyleCB(const void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
mgw->renderStyle = *(GLenum*)value ;
if(mgw->renderStyle == MyGlutWin::FLAT)
TwDefine("Viewer/FaceShrinkage visible=true") ;
else
TwDefine("Viewer/FaceShrinkage visible=false") ;
glutPostRedisplay() ;
}
void TW_CALL getRenderStyleCB(void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
*(GLenum*)value = mgw->renderStyle ;
}
void TW_CALL setShininessCB(const void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
mgw->shininess = *(float*)value ;
glutPostRedisplay() ;
}
void TW_CALL getShininessCB(void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
*(float*)value = mgw->shininess ;
}
void TW_CALL setFocalCB(const void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
mgw->setFocal(*(float*)value) ;
mgw->reshape(-1, -1) ;
glutPostRedisplay() ;
}
void TW_CALL getFocalCB(void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
*(float*)value = mgw->getFocal() ;
}
void TW_CALL setRenderObjectCB(const void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
mgw->renderObject = *(GLboolean*)value ;
glutPostRedisplay() ;
}
void TW_CALL getRenderObjectCB(void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
*(GLboolean*)value = mgw->renderObject ;
}
void TW_CALL setRenderLinesCB(const void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
mgw->renderLines = *(GLboolean*)value ;
glutPostRedisplay() ;
}
void TW_CALL getRenderLinesCB(void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
*(GLboolean*)value = mgw->renderLines ;
}
void TW_CALL setRenderNormalsCB(const void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
mgw->renderNormals = *(GLboolean*)value ;
if(mgw->renderNormals)
{
mgw->initDLNormals() ;
TwDefine("Viewer/NormalScaleFactor visible=true") ;
}
else
TwDefine("Viewer/NormalScaleFactor visible=false") ;
glutPostRedisplay() ;
}
void TW_CALL getRenderNormalsCB(void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
*(GLboolean*)value = mgw->renderNormals ;
}
void TW_CALL setNormalScaleFactorCB(const void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
mgw->normalScaleFactor = *(float*)value ;
if(mgw->renderNormals) mgw->initDLNormals() ;
glutPostRedisplay() ;
}
void TW_CALL getNormalScaleFactorCB(void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
*(float*)value = mgw->normalScaleFactor ;
}
void TW_CALL setFaceShrinkageCB(const void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
mgw->faceShrinkage = *(float*)value ;
glutPostRedisplay() ;
}
void TW_CALL getFaceShrinkageCB(void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
*(float*)value = mgw->faceShrinkage ;
}
void TW_CALL setShowCurvatureCB(const void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
mgw->showCurvature = *(GLboolean*)value ;
if(mgw->showCurvature)
{
mgw->updateVBOdata(Algo::Render::VBO::COLORS) ;
TwDefine("Viewer/CurvatureDirections visible=true") ;
TwDefine("Viewer/CurvType visible=true") ;
TwDefine("Viewer/CurvDir visible=true") ;
TwDefine("Viewer/CurvMultiplicator visible=true") ;
}
else
{
TwDefine("Viewer/CurvatureDirections visible=false") ;
TwDefine("Viewer/CurvType visible=false") ;
TwDefine("Viewer/CurvDir visible=false") ;
TwDefine("Viewer/CurvMultiplicator visible=false") ;
}
glutPostRedisplay() ;
}
void TW_CALL getShowCurvatureCB(void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
*(GLboolean*)value = mgw->showCurvature ;
}
void TW_CALL setShowCurvatureDirectionsCB(const void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
mgw->showCurvatureDirections = *(GLboolean*)value ;
glutPostRedisplay() ;
}
void TW_CALL getShowCurvatureDirectionsCB(void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
*(GLboolean*)value = mgw->showCurvatureDirections ;
}
void TW_CALL setCurvatureTypeCB(const void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
mgw->curvatureType = *(GLenum*)value ;
mgw->updateVBOdata(Algo::Render::VBO::COLORS, false) ;
glutPostRedisplay() ;
}
void TW_CALL getCurvatureTypeCB(void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
*(GLenum*)value = mgw->curvatureType ;
}
void TW_CALL setCurvatureDirCB(const void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
mgw->curvatureDir = *(GLenum*)value ;
glutPostRedisplay() ;
}
void TW_CALL getCurvatureDirCB(void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
*(GLenum*)value = mgw->curvatureDir ;
}
void TW_CALL setCurvMultiplicatorCB(const void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
mgw->curvMultiplicator = *(float*)value ;
mgw->updateVBOdata(Algo::Render::VBO::COLORS, false) ;
glutPostRedisplay() ;
}
void TW_CALL getCurvMultiplicatorCB(void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
*(float*)value = mgw->curvMultiplicator ;
}
void TW_CALL setSolverTypeCB(const void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
mgw->setSolverType(*(GLenum*)value) ;
}
void TW_CALL getSolverTypeCB(void* value, void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
*(GLenum*)value = mgw->getSolverType() ;
}
void TW_CALL smoothCB(void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
mgw->smooth() ;
if(mgw->showCurvature)
mgw->updateVBOdata(Algo::Render::VBO::POSITIONS | Algo::Render::VBO::NORMALS | Algo::Render::VBO::COLORS) ;
else
mgw->updateVBOdata(Algo::Render::VBO::POSITIONS | Algo::Render::VBO::NORMALS) ;
glutPostRedisplay() ;
}
void TW_CALL smoothCurvatureCB(void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
if(mgw->showCurvature)
{
mgw->smoothCurvature() ;
mgw->updateVBOdata(Algo::Render::VBO::COLORS, false) ;
glutPostRedisplay() ;
}
}
void TW_CALL lsmCB(void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
mgw->lsm() ;
if(mgw->showCurvature)
mgw->updateVBOdata(Algo::Render::VBO::POSITIONS | Algo::Render::VBO::NORMALS | Algo::Render::VBO::COLORS) ;
else
mgw->updateVBOdata(Algo::Render::VBO::POSITIONS | Algo::Render::VBO::NORMALS) ;
glutPostRedisplay() ;
}
void TW_CALL diffCoordCB(void* clientData)
{
MyGlutWin* mgw = static_cast<MyGlutWin*>(clientData) ;
mgw->matchDiffCoord(false) ;
if(mgw->showCurvature)
mgw->updateVBOdata(Algo::Render::VBO::POSITIONS | Algo::Render::VBO::NORMALS | Algo::Render::VBO::COLORS) ;
else
mgw->updateVBOdata(Algo::Render::VBO::POSITIONS | Algo::Render::VBO::NORMALS) ;
glutPostRedisplay() ;
}
/**********************************************************************************************
* MyGlutWin IMPLEMENTATION *
**********************************************************************************************/
MyGlutWin::MyGlutWin(int* argc, char **argv, int winX, int winY) :
GlutWin_ATB(argc, argv, winX, winY),
renderStyle(GOURAUD),
renderObject(true),
renderLines(false),
renderNormals(false),
showCurvature(false),
showCurvatureDirections(false),
curvatureType(MEAN),
curvMultiplicator(1.0f),
smoothAmount(0.5f),
vbo_render(NULL),
def_locked(true),
def_handle(false),
selecting(false),
deselecting(false),
dragging(false),
#ifdef WITH_CUDA
gpuSolver(false),
#endif
lockingMarker(myMap, VERTEX_ORBIT),
handleMarker(myMap, VERTEX_ORBIT),
solverType(ITERATIVE)
{
normalScaleFactor = 1.0f ;
faceShrinkage = 0.0f ;
colClear = Geom::Vec4f(0.2f, 0.2f, 0.2f, 0.1f) ;
colDif = Geom::Vec4f(0.8f, 0.9f, 0.7f, 1.0f) ;
colSpec = Geom::Vec4f(0.9f, 0.9f, 0.9f, 1.0f) ;
colNormal = Geom::Vec4f(1.0f, 0.0f, 0.0f, 1.0f) ;
shininess = 80.0f ;
setFocal(5.0f) ;
dl_norm = glGenLists(1) ;
if(this->shaderOk)
{
shaders[0].loadShaders("phong_vs.txt", "phong_ps.txt") ;
shaders[1].loadShaders("flat_vs.txt", "flat_ps.txt", "flat_gs.txt") ;
}
}
void MyGlutWin::init()
{
normal = myMap.addAttribute<PFP::VEC3>(VERTEX_ORBIT, "normal") ;
diffCoord = myMap.addAttribute<PFP::VEC3>(VERTEX_ORBIT, "diffCoord") ;
k1 = myMap.addAttribute<PFP::REAL>(VERTEX_ORBIT, "k1") ;
k2 = myMap.addAttribute<PFP::REAL>(VERTEX_ORBIT, "k2") ;
K1 = myMap.addAttribute<PFP::VEC3>(VERTEX_ORBIT, "K1") ;
K2 = myMap.addAttribute<PFP::VEC3>(VERTEX_ORBIT, "K2") ;
color = myMap.addAttribute<Geom::Vec4f>(VERTEX_ORBIT, "color") ;
vbo_render = new Algo::Render::VBO::MapRender_VBO( ) ;
vbo_render->initPrimitives<PFP>(myMap, allDarts, Algo::Render::VBO::TRIANGLES) ;
vbo_render->initPrimitives<PFP>(myMap, allDarts, Algo::Render::VBO::LINES) ;
updateVBOdata(Algo::Render::VBO::POSITIONS | Algo::Render::VBO::NORMALS) ;
Algo::Geometry::computeLaplacianVertices<PFP>(myMap, Algo::Geometry::TOPOLOGICAL, position, diffCoord) ;
vIndex = myMap.addAttribute<unsigned int>(VERTEX_ORBIT, "index") ;
nb_vertices = myMap.computeIndexCells(vIndex) ;
solver = new LinearSolver<CPUSolverTraits>(nb_vertices) ;
select_area = gWidthObj / (100.0f * getScale()) ;
}
void MyGlutWin::initGUI()
{
viewer_bar = TwNewBar("Viewer") ;
TwDefine("Viewer position='16 16' size='220 400' valueswidth='85'") ;
TwType tw_render_style = TwDefineEnum("Shading","Flat,Gouraud,Phong") ;
TwAddVarCB(viewer_bar, "RenderStyle", tw_render_style, setRenderStyleCB, getRenderStyleCB, this, "") ;
TwAddVarCB(viewer_bar, "Shininess", TW_TYPE_FLOAT, setShininessCB, getShininessCB, this, "min=1 max=255 step=1") ;
TwAddVarCB(viewer_bar, "Focal", TW_TYPE_FLOAT, setFocalCB, getFocalCB, this, "min=0.6 max=5.0 step=0.1") ;
TwAddVarCB(viewer_bar, "Show Object", TW_TYPE_BOOL8, setRenderObjectCB, getRenderObjectCB, this, "") ;
TwAddVarCB(viewer_bar, "Show Lines", TW_TYPE_BOOL8, setRenderLinesCB, getRenderLinesCB, this, "") ;
TwAddVarCB(viewer_bar, "Show Normals", TW_TYPE_BOOL8, setRenderNormalsCB, getRenderNormalsCB, this, "") ;
TwAddVarCB(viewer_bar, "NormalScaleFactor", TW_TYPE_FLOAT, setNormalScaleFactorCB, getNormalScaleFactorCB, this, "min=0.1 max=5.0 step=0.1") ;
TwDefine("Viewer/NormalScaleFactor visible=false") ;
TwAddVarCB(viewer_bar, "FaceShrinkage", TW_TYPE_FLOAT, setFaceShrinkageCB, getFaceShrinkageCB, this, "min=0.0 max=0.9 step=0.01") ;
TwDefine("Viewer/FaceShrinkage visible=false") ;
TwAddVarCB(viewer_bar, "Show Curvature", TW_TYPE_BOOL8, setShowCurvatureCB, getShowCurvatureCB, this, "") ;
TwAddVarCB(viewer_bar, "CurvatureDirections", TW_TYPE_BOOL8, setShowCurvatureDirectionsCB, getShowCurvatureDirectionsCB, this, "") ;
TwType tw_curvature_type = TwDefineEnum("CurvatureType","Mean,Gaussian") ;
TwAddVarCB(viewer_bar, "CurvType", tw_curvature_type, setCurvatureTypeCB, getCurvatureTypeCB, this, "") ;
TwType tw_curvature_dir = TwDefineEnum("CurvatureDir","Both,Min,Max") ;
TwAddVarCB(viewer_bar, "CurvDir", tw_curvature_dir, setCurvatureDirCB, getCurvatureDirCB, this, "") ;
TwAddVarCB(viewer_bar, "CurvMultiplicator", TW_TYPE_FLOAT, setCurvMultiplicatorCB, getCurvMultiplicatorCB, this, "min=0.1 max=10.0 step=0.1") ;
TwDefine("Viewer/CurvatureDirections visible=false") ;
TwDefine("Viewer/CurvType visible=false") ;
TwDefine("Viewer/CurvDir visible=false") ;
TwDefine("Viewer/CurvMultiplicator visible=false") ;
TwAddSeparator(viewer_bar, "", "") ;
TwType tw_solver_type = TwDefineEnum("Solver","Iterative,Direct") ;
TwAddVarCB(viewer_bar, "SolverType", tw_solver_type, setSolverTypeCB, getSolverTypeCB, this, "") ;
#ifdef WITH_CUDA
TwAddVarRW(viewer_bar, "GPUSolver", TW_TYPE_BOOL8, &gpuSolver, "") ;
#endif
TwAddSeparator(viewer_bar, "", "") ;
TwAddButton(viewer_bar, "Smooth", smoothCB, this, "") ;
TwAddButton(viewer_bar, "SmoothCurvature", smoothCurvatureCB, this, "") ;
TwAddVarRW(viewer_bar, "Smooth Amount", TW_TYPE_FLOAT, &smoothAmount, "min=0.01 max=1.0 step=0.01") ;
TwAddButton(viewer_bar, "LSM", lsmCB, this, "") ;
TwAddButton(viewer_bar, "DiffCoord", diffCoordCB, this, "") ;
}
void MyGlutWin::myRedraw()
{
GLfloat black[4] = { 0.0f, 0.0f, 0.0f, 1.0f } ;
GLfloat amb[4] = { 0.2f, 0.1f, 0.1f, 1.0f } ;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) ;
glPushMatrix() ;
float sc = 50. / gWidthObj ;
glScalef(sc, sc, sc) ;
glTranslatef(-gPosObj[0], -gPosObj[1], -gPosObj[2]) ;
if(renderLines)
{
glDisable(GL_LIGHTING);
glColor3f(0.0f,0.0f,0.0f);
vbo_render->disableBuffers(Algo::Render::VBO::COLORS) ;
vbo_render->draw(Algo::Render::VBO::LINES) ;
vbo_render->enableBuffers(Algo::Render::VBO::COLORS) ;
}
if(renderNormals)
glCallList(dl_norm) ;
glEnable(GL_POLYGON_OFFSET_FILL) ;
glPolygonOffset(1.0f, 1.0f) ;
if(renderObject)
{
if(showCurvature)
{
glEnable(GL_COLOR_MATERIAL) ;
if(showCurvatureDirections)
render(CURVATURE_DIRECTIONS) ;
}
else
{
glDisable(GL_COLOR_MATERIAL) ;
glMaterialfv(GL_FRONT, GL_DIFFUSE, colDif.data()) ;
glMaterialfv(GL_FRONT, GL_AMBIENT, amb) ;
if(renderStyle != PHONG)
{
glMaterialfv(GL_FRONT, GL_SPECULAR, black) ;
glMaterialf(GL_FRONT, GL_SHININESS, 1.0f) ;
}
else
{
glMaterialfv(GL_FRONT, GL_SPECULAR, colSpec.data()) ;
glMaterialf(GL_FRONT, GL_SHININESS, shininess) ;
}
}
glEnable(GL_LIGHTING) ;
glEnable(GL_CULL_FACE) ;
glPolygonMode(GL_FRONT, GL_FILL) ;
if(renderStyle == FLAT)
{
glShadeModel(GL_FLAT) ;
shaders[1].bind() ;
glUniform1fARB(glGetUniformLocationARB(shaders[1].program_handler(),"explode"), faceShrinkage) ;
vbo_render->draw(Algo::Render::VBO::TRIANGLES) ;
shaders[1].unbind() ;
}
else
{
glShadeModel(GL_SMOOTH) ;
if(renderStyle == PHONG)
shaders[0].bind() ;
vbo_render->draw(Algo::Render::VBO::TRIANGLES) ;
if(renderStyle == PHONG)
shaders[0].unbind() ;
}
render(VERTICES) ;
}
glDisable(GL_POLYGON_OFFSET_FILL) ;
glPopMatrix() ;
glColor3f(1.0f, 1.0f, 1.0f) ;
int x = getWinWidth() - 170 ;
printString2D(
x,
20,
"Keys :\n"
"----\n"
"'l' : define locked vertices\n"
"'h' : define handle vertices\n"
"'x' : deselect vertices\n"
) ;
}
void MyGlutWin::myKeyboard(unsigned char keycode, int x, int y)
{
switch(keycode)
{
case 'l' : {
def_locked = true ;
def_handle = false ;
break ;
}
case 'h' : {
def_handle = true ;
def_locked = false ;
break ;
}
case 'x' : {
deselectAllVertices() ;
glutPostRedisplay() ;
break ;
}
case '+' : {
select_area *= 1.1f ;
break ;
}
case '-' : {
select_area /= 1.1f ;
break ;
}
case 's' : {
bool success = Algo::Export::exportOFF<PFP>(myMap, position, "export.off") ;
if(!success)
{
std::cerr << "warning export of file export.off failed" << std::endl ;
}
}
}
}
void MyGlutWin::myMouse(int button, int state, int x, int y)
{
if(button == GLUT_LEFT_BUTTON && (glutGetModifiers() & GLUT_ACTIVE_SHIFT) && state == GLUT_DOWN)
selecting = 1 ;
else if(button == GLUT_RIGHT_BUTTON && (glutGetModifiers() & GLUT_ACTIVE_SHIFT) && state == GLUT_DOWN)
deselecting = 1 ;
else if(button == GLUT_LEFT_BUTTON && (glutGetModifiers() & GLUT_ACTIVE_CTRL) && state == GLUT_DOWN)
dragging = 1 ;
else
{
selecting = 0 ;
deselecting = 0 ;
dragging = 0 ;
}
if(selecting)
{
glPushMatrix() ;
float sc = 50.0f / gWidthObj ;
glScalef(sc, sc, sc) ;
glTranslatef(-gPosObj[0], -gPosObj[1], -gPosObj[2]) ;
Geom::Vec3f rayA, rayB ;
getOrthoScreenRay(x, y, rayA, rayB) ;
Geom::Vec3f AB = rayB - rayA ;
Dart d ;
Algo::Selection::vertexRaySelection<PFP>(myMap, position, rayA, AB, d) ;
glPopMatrix();
if(d != myMap.end())
selectVertex(d) ;
glutPostRedisplay() ;
}
else if(deselecting)
{
glPushMatrix() ;
float sc = 50.0f / gWidthObj ;
glScalef(sc, sc, sc) ;
glTranslatef(-gPosObj[0], -gPosObj[1], -gPosObj[2]) ;
Geom::Vec3f rayA, rayB ;
getOrthoScreenRay(x, y, rayA, rayB) ;
Geom::Vec3f AB = rayB - rayA ;
Dart d ;
Algo::Selection::vertexRaySelection<PFP>(myMap, position, rayA, AB, d) ;
glPopMatrix();
if(d != myMap.end())
deselectVertex(d) ;
glutPostRedisplay() ;
}
}
void MyGlutWin::myMotion(int x, int y)
{
if(dragging)
{
++skipCount ;
if(skipCount % 5)
return ;
float sc = 1.0 / getScale() ;
Geom::Vec4f d(0.01f*sc*(x-beginx), 0.01f*sc*(beginy-y), 0.0f, 1.0f) ;
Geom::Vec4f t(0) ;
GLfloat m[4][4] ;
Utils::build_rotmatrix(m, getSceneQuaternion()) ;
for(int i = 0; i < 4; ++i)
for(int j = 0; j < 4; ++j)
t[i] += m[i][j] * d[j] ;
for(unsigned int i = 0; i < handle_vertices.size(); ++i)
{
PFP::VEC3& p = position[handle_vertices[i]] ;
p[0] += t[0] / t[3] ;
p[1] += t[1] / t[3] ;
p[2] += t[2] / t[3] ;
}
matchDiffCoord(true) ;
if(