portfolio/visage/objet3d.cpp
thierry_nibert 5b6730b2dc add files
2026-08-01 16:49:57 +02:00

353 lines
12 KiB
C++
Executable File

#include <objet3d.h>
#include <QFile>
#include <QTextStream>
#include <QMessageBox>
#include <QDebug>
#include <QGLWidget>
#include<QFuture>
#include <qtconcurrentrun.h>
Objet3D::Objet3D(QString name)
{
nom = name;
nbsommets=0;
nbfaces=0;
id=0;
smooth = false;
}
Objet3D::Objet3D(const Objet3D& C)
{
nom = C.nom;
nbsommets=C.nbsommets;
nbfaces=C.nbfaces;
lpoints = C.lpoints;
lfaces = C.lfaces;
//ne pas recopier les normal
lpointsnormales = C.lpointsnormales ;
lfacesnormales = C.lfacesnormales;
smooth =C.smooth;
min = C.min;
max = C.max;
centroid = C.centroid;
}
bool Objet3D::charger_Off(QString objet){
nom = objet.split('/').last().split('.').first();
QFile file(objet);
if(!file.open(QIODevice::ReadOnly)) {
QMessageBox::information(0, "error Ouverture fichier", file.errorString());
return false;
}
QTextStream in(&file);
int lin=-1;
while(!in.atEnd()) {
QString line = in.readLine();
QStringList list_value;
line = line.simplified();
if((line != "OFF")&& lin ==-1) // controle header
{
QMessageBox::information(0, "Erreur dans l'en tête du fichier OFF", file.errorString());
return false;
}
if(lin == -1)
lin = 0;
if(lin == 0)
{
uint v=0;
line = in.readLine();
line = line.simplified();
list_value = line.split(' ');
// qDebug()<< list_value << endl;
nbsommets = list_value[0].toUInt( );
nbfaces = list_value[1].toUInt();
v = list_value[2].toUInt();
id = v;
lin=1;
lpoints.clear();
lfaces.clear();
lfacesnormales.clear();
line = in.readLine();
line = line.simplified();
}
if(lpoints.size() < nbsommets) { // chargement des sommet
point3D p;
list_value = line.split(' ');
//qDebug()<< list_value << endl;
p.x=list_value[0].toDouble();
p.y=list_value[1].toDouble();
p.z=list_value[2].toDouble();
if (min.x > p.x)
min.x = p.x;
if (min.y > p.y)
min.y = p.y;
if (min.z > p.z)
min.z = p.z;
if (max.x < p.x)
max.x = p.x;
if (max.y < p.y)
max.y = p.y;
if (max.z < p.z)
max.z = p.z;
lpoints.push_back(p);
}else if(lfaces.size() < nbfaces){
uint v=0;
face F;
list_value = line.split(' ');
//qDebug()<< list_value << endl;
v=list_value[0].toUInt();
F.S1=list_value[1].toUInt();
F.S2=list_value[2].toUInt();
F.S3=list_value[3].toUInt();
if (v != 3) {
QMessageBox::information(0, "Erreur au chargement des faces, non triangulaires", file.errorString());
return false;
}
lfaces.push_back(F);
}
}
//calcul du centroid de l'objet à partir de la boîte min/max
centroid.x = (max.x + min.x) / 2.0f;
centroid.y = (max.y + min.y) / 2.0f;
centroid.z = (max.z + min.z) / 2.0f;
/*qDebug() << "Chargement du fichier " << objet
<< "\t" << "parmétres : " << nbsommets
<< " points - " << nbfaces << " arêtes\n"
<< "\t" << "Box : MAX(" << max.x
<< " " << max.y << " " << max.z
<< ")\t" << " MIN("
<< min.x << " " << min.y << " " << min.z
<< ")\t" << " CENTROID(" << centroid.x
<< " " << centroid.y << " " << centroid.z <<")." << endl;
*/
calcul_normales_faces();
calcul_normales_points();
file.close();
return true;
}
void Objet3D::calcul_normales_points() {
lpointsnormales.clear();
//qDebug()<< "taille vide = "<<lpointsnormales.size()<< endl;
while ( lpointsnormales.size() < lpoints.size()) {
lpointsnormales.push_back(point3D(0.,0.,0.));
}
for(uint i =0; i< lfaces.size(); i++) {
lpointsnormales[lfaces[i].S1] = lpointsnormales[lfaces[i].S1] + lfacesnormales[lfaces[i].S1] ;
lpointsnormales[lfaces[i].S2] = lpointsnormales[lfaces[i].S2] + lfacesnormales[lfaces[i].S2] ;
lpointsnormales[lfaces[i].S3] = lpointsnormales[lfaces[i].S3] + lfacesnormales[lfaces[i].S3] ;
point3D::normalize(lpointsnormales[lfaces[i].S1]);
point3D::normalize(lpointsnormales[lfaces[i].S1]);
point3D::normalize(lpointsnormales[lfaces[i].S1]);
}
}
void Objet3D::calcul_normales_faces() {
lfacesnormales.clear();
point3D v1;
point3D v2;
//qDebug()<< "taille vide = "<<lfacesnormales.size()<< endl;
while ( lfacesnormales.size() < lfaces.size()) {
v1 = point3D::PointsToVecteur(lpoints[lfaces[lfacesnormales.size()].S2],lpoints[lfaces[lfacesnormales.size()].S1]);
v2 = point3D::PointsToVecteur(lpoints[lfaces[lfacesnormales.size()].S1],lpoints[lfaces[lfacesnormales.size()].S3]);
point3D n= point3D::produit_vectoriel(v2, v1);
point3D::normalize(n);
lfacesnormales.push_back(n);
}
//qDebug() << "Fin calcul normales faces, traitement de " << nbfaces << " faces" << endl;
}
void Objet3D::calcul_normales_point(deque<point3D>& lnp, deque<point3D>& lnf, deque<point3D>& lp, deque<face>& lf, deque<uint>& borne)
{
for(uint i =borne[0]; i< borne[1]; i++) {
lnp[lf[i].S1] = lnp[lf[i].S1] + lnf[lf[i].S1] ;
lnp[lf[i].S2] = lnp[lf[i].S2] + lnf[lf[i].S2] ;
lnp[lf[i].S3] = lnp[lf[i].S3] + lnf[lf[i].S3] ;
}
}
void Objet3D::calcul_normales_face(deque<point3D>& lnf, deque<point3D>& lp, deque<face>& lf, uint debut, uint fin)
{
point3D v1;
point3D v2;
//qDebug()<< "taille normal = "<<lnf.size()<< endl;
for(uint i =debut; i < fin; i++){
v1 = point3D::PointsToVecteur(lp[lf[i].S2],lp[lf[i].S1]);
v2 = point3D::PointsToVecteur(lp[lf[i].S1],lp[lf[i].S3]);
point3D n= point3D::produit_vectoriel(v2, v1);
point3D::normalize(n);
lnf[i]= n;
}
}
void Objet3D::affiche() const{
/*qDebug() << "Objet3D "<< nom << ", nbsommets " << nbsommets << ", nbfaces " << nbfaces << endl;
qDebug() << "SOMMET" << endl;
*/
// Enable lighting
if(ligth){
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
}
else glDisable(GL_LIGHTING);
glEnable(GL_NORMALIZE);
if(!smooth)
draw_normale_point();
else
draw_normale_faces();
glDisable(GL_NORMALIZE);
// disable lighting
if(ligth){
glDisable(GL_LIGHT0);
glDisable(GL_LIGHTING);
}else glEnable(GL_LIGHTING);
}
void Objet3D::draw_normale_point() const
{
glBegin(GL_TRIANGLES);
for (unsigned int i=0;i<nbfaces;i++){
glColor3d(1. -lpointsnormales.at(lfaces[i].S1).x, 1. -lfacesnormales.at(lfaces[i].S1).y, 1. -lfacesnormales.at(lfaces[i].S1).z);
glNormal3d(lpointsnormales.at(lfaces[i].S1).x, lfacesnormales.at(lfaces[i].S1).y, lfacesnormales.at(lfaces[i].S1).z);
glVertex3d(lpoints[lfaces[i].S1].x, lpoints[lfaces[i].S1].y, lpoints[lfaces[i].S1].z);
glColor3d(1. -lpointsnormales.at(lfaces[i].S2).x, 1. -lfacesnormales.at(lfaces[i].S2).y, 1. -lfacesnormales.at(lfaces[i].S2).z);
glNormal3d(lpointsnormales.at(lfaces[i].S2).x, lfacesnormales.at(lfaces[i].S2).y, lfacesnormales.at(lfaces[i].S2).z);
glVertex3d(lpoints[lfaces[i].S2].x, lpoints[lfaces[i].S2].y, lpoints[lfaces[i].S2].z);
glColor3d(1. -lpointsnormales.at(lfaces[i].S3).x, 1. -lfacesnormales.at(lfaces[i].S3).y, 1. -lfacesnormales.at(lfaces[i].S3).z);
glNormal3d(lpointsnormales.at(lfaces[i].S3).x, lfacesnormales.at(lfaces[i].S3).y, lfacesnormales.at(lfaces[i].S3).z);
glVertex3d(lpoints[lfaces[i].S3].x, lpoints[lfaces[i].S3].y, lpoints[lfaces[i].S3].z);
}
glEnd();
}
void Objet3D::draw_normale_faces() const
{
glBegin(GL_TRIANGLES);
for (unsigned int i=0;i<nbfaces;i++){
glColor3d(lfacesnormales.at(i).x, lfacesnormales.at(i).y, lfacesnormales.at(i).z);
glNormal3d(lfacesnormales.at(i).x, lfacesnormales.at(i).y, lfacesnormales.at(i).z);
glVertex3d(lpoints[lfaces[i].S1].x, lpoints[lfaces[i].S1].y, lpoints[lfaces[i].S1].z);
glVertex3d(lpoints[lfaces[i].S2].x, lpoints[lfaces[i].S2].y, lpoints[lfaces[i].S2].z);
glVertex3d(lpoints[lfaces[i].S3].x, lpoints[lfaces[i].S3].y, lpoints[lfaces[i].S3].z);
}
glEnd();
}
void Objet3D::interpolation(const Objet3D& debut, const Objet3D& fin,const float& t){
//test de validiter des maillage
if((debut.nbfaces != fin.nbfaces) || (debut.nbsommets != fin.nbsommets)){
QMessageBox::information(0, "error Models incompatible","rechager avec deux model de même nombre de face et sommet");
return;
}
//vidage des variable de l'obj
nbsommets = debut.nbsommets;
nbfaces = debut.nbfaces;
id=debut.id;
lpoints.clear();
//lfaces.clear();
lpointsnormales.clear();
lfacesnormales.clear();
min = point3D(); max = point3D(); centroid=point3D();
//initialisation des variable qui ne chage pas
lfaces=debut.lfaces;
// interpolation linaire des point (1-t).x0 + t.x1
while(lpoints.size() < nbsommets) { // chargement des sommet
point3D p(debut.lpoints[lpoints.size()]);
p*=(1. - t);
p = p + fin.lpoints[lpoints.size()]*t;
if (min.x > p.x)
min.x = p.x;
if (min.y > p.y)
min.y = p.y;
if (min.z > p.z)
min.z = p.z;
if (max.x < p.x)
max.x = p.x;
if (max.y < p.y)
max.y = p.y;
if (max.z < p.z)
max.z = p.z;
lpoints.push_back(p);
}
//calcul du centroid de l'objet à partir de la boîte min/max
centroid.x = (max.x + min.x) / 2.0f;
centroid.y = (max.y + min.y) / 2.0f;
centroid.z = (max.z + min.z) / 2.0f;
/*qDebug() << "Chargement du Maillage " << nom
<< "\t" << "parmétres : " << nbsommets
<< " points - " << nbfaces << " arêtes\n"
<< "\t" << "Box : MAX(" << max.x
<< " " << max.y << " " << max.z
<< ")\t" << " MIN("
<< min.x << " " << min.y << " " << min.z
<< ")\t" << " CENTROID(" << centroid.x
<< " " << centroid.y << " " << centroid.z <<")." << endl;*/
if(!smooth){
calcul_normales_faces();
calcul_normales_points();
/* // sequence multi thread a ameliore
* deque<uint> b1, b2, b3;
while ( lpointsnormales.size() < lpoints.size()) {
lpointsnormales.push_back(point3D(0.,0.,0.));
}
b1.push_back(0);b1.push_back(lfacesnormales.size()/3);
b2.push_back(lfacesnormales.size()/3);b2.push_back(2 * lfacesnormales.size()/3);
b3.push_back(2 * lfacesnormales.size()/3);b1.push_back(lfacesnormales.size());
QFuture<void > t1 = QtConcurrent::run(Objet3D::calcul_normales_point, lpointsnormales, lfacesnormales, lpoints, lfaces, b1);
QFuture<void > t2 = QtConcurrent::run(Objet3D::calcul_normales_point, lpointsnormales, lfacesnormales, lpoints, lfaces, b2);
QFuture<void > t3 = QtConcurrent::run(Objet3D::calcul_normales_point, lpointsnormales, lfacesnormales, lpoints, lfaces, b3);
t1.waitForFinished();
t2.waitForFinished();
t3.waitForFinished();
for(uint i = 0;i<lpointsnormales.size(); i++)
point3D::normalize(lpointsnormales[i]);*/
}else{
calcul_normales_faces();
//set normal point null
while ( lpointsnormales.size() < lpoints.size()) {
lpointsnormales.push_back(point3D(0.,0.,0.));
}}
/*
QFuture<void > t1 = QtConcurrent::run(Objet3D::calcul_normales_face, lfacesnormales, lpoints, lfaces, 0, lfacesnormales.size()/3);
QFuture<void > t2 = QtConcurrent::run(Objet3D::calcul_normales_face, lfacesnormales, lpoints, lfaces, lfacesnormales.size()/3, 2*lfacesnormales.size()/3);
QFuture<void > t3 = QtConcurrent::run(Objet3D::calcul_normales_face, lfacesnormales, lpoints, lfaces, 2*lfacesnormales.size()/3, lfacesnormales.size());
t1.waitForFinished();
t2.waitForFinished();
t3.waitForFinished();
*/
}