A vrai dire je voulais charger la matrice à chaque fois que je me déplaçais dans le monde avec cette classe-ci pour éviter de devoir le faire à chaque rendu :
#include "3DView.h"
#include <SFML/OpenGL.hpp>
View3D::View3D (double width, double height, double depth, Vec3f up) {
glViewport(0, 0, width, height);
setPerspective(-width * 0.5f, width * 0.5f, -height * 0.5f, height * 0.5f, 1, depth);
this->up = up;
Vec3f v1 (up.x, up.y, 0);
Vec3f v2 (0, up.y, up.z);
position = Vec3f (0, 0, 0);
teta = phi = 0.f;
gamma = v1.getAngleBetween(Vec3f::yAxis, Vec3f::zAxis);
phi2 = v2.getAngleBetween(Vec3f::yAxis, Vec3f::zAxis);
zoomFactor = 1.f;
forward = Math::toCartesian(Math::toRadians(phi), Math::toRadians(teta));
left = up.cross(forward).normalize();
target = position + forward;
Vec3f angles (-(phi + phi2), -teta, -gamma);
viewMatrix.setRotation(angles);
viewMatrix.setScale(Vec3f(zoomFactor, zoomFactor, zoomFactor));
viewMatrix.setTranslation(Vec3f(-position.x, -position.y, -position.z));
float matrix[16];
viewMatrix.getGlMatrix(matrix);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLoadMatrixf(matrix);
}
View3D::View3D (double width, double height, double fovy, double depth, Vec3f up) {
glViewport(0, 0, width, height);
setPerspective(-width * 0.5f, width * 0.5f, -height * 0.5f, height * 0.5f, fovy, width / height, 1, depth);
this->up = up;
Vec3f v1 (up.x, up.y, 0);
Vec3f v2 (0, up.y, up.z);
position = Vec3f (0, 0, 0);
teta = phi = 0.f;
gamma = v1.getAngleBetween(Vec3f::yAxis, Vec3f::zAxis);
phi2 = v2.getAngleBetween(Vec3f::yAxis, Vec3f::zAxis);
zoomFactor = 1.f;
forward = Math::toCartesian(Math::toRadians(teta), Math::toRadians(phi));
left = up.cross(forward).normalize();
target = position + forward;
Vec3f angles (-(phi + phi2), -teta, -gamma);
viewMatrix.setRotation(angles);
viewMatrix.setScale(Vec3f(zoomFactor, zoomFactor, 1));
viewMatrix.setTranslation(Vec3f(-position.x, -position.y, -position.z));
float matrix[16];
viewMatrix.getGlMatrix(matrix);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLoadMatrixf(matrix);
}
void View3D::move(float x, float y, float z) {
position += Vec3f (x, y, z);
target = position + forward;
viewMatrix.setTranslation(Vec3f (-position.x, -position.y, -position.z));
viewMatrix.setOrigin(position);
float matrix[16];
viewMatrix.getGlMatrix(matrix);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLoadMatrixf(matrix);
}
void View3D::move (Vec3f dir, float delta) {
position += dir * delta;
target = position + forward;
viewMatrix.setTranslation(Vec3f (-position.x, -position.y, -position.z));
viewMatrix.setOrigin(position);
float matrix[16];
viewMatrix.getGlMatrix(matrix);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLoadMatrixf(matrix);
}
ViewMatrix View3D::getViewMatrix() {
return viewMatrix;
}
Vec3f View3D::getLeft() {
return left;
}
Vec3f View3D::getUp() {
return up;
}
Vec3f View3D::getForward() {
return forward;
}
float View3D::getTeta() {
return teta;
}
float View3D::getPhi() {
return phi;
}
void View3D::computeVectorsFromAngles() {
forward = Math::toCartesian(Math::toRadians(teta), Math::toRadians(phi));
left = up.cross(forward).normalize();
target = position + forward;
}
void View3D::computeAnglesFromVectors () {
float r = forward.magnitude();
Vec2f xy (forward.x, forward.z);
Vec2f yz (forward.y, -Math::abs(forward.z));
teta = xy.getAngleBetween(Vec2f(0, -1));
phi = yz.getAngleBetween(Vec2f(0, -1));
}
void View3D::lookAt(float x, float y, float z) {
target = Vec3f(x, y, z);
forward = target - position;
left = up.cross(forward).normalize();
computeAnglesFromVectors();
Vec3f angles (-(phi + phi2), -teta, -gamma);
viewMatrix.setRotation(angles);
viewMatrix.setOrigin(position);
float matrix[16];
viewMatrix.getGlMatrix(matrix);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLoadMatrixf(matrix);
}
void View3D::rotate(float teta, float phi) {
if (phi > 90)
phi = 90;
if (phi < -90)
phi = -90;
this->phi = phi;
this->teta = teta;
computeVectorsFromAngles();
Vec3f angles (-(phi + phi2), -teta, -gamma);
viewMatrix.setRotation(angles);
float matrix[16];
viewMatrix.getGlMatrix(matrix);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLoadMatrixf(matrix);
}
void View3D::zoom (float zoom) {
zoomFactor = zoom;
viewMatrix.setScale(Vec3f(zoomFactor, zoomFactor, zoomFactor));
float matrix[16];
viewMatrix.getGlMatrix(matrix);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLoadMatrixf(matrix);
}
void View3D::setPerspective (double left, double right, double bottom, double top, double front, double back) {
if (front < 0)
front = -front;
if (back < 0)
back = -back;
projMatrix.setGlOrthoMatrix(left, right, bottom, top, front, back);
float matrix[16];
projMatrix.getGlMatrix(matrix);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum (left, right, bottom, top, front, back);
glLoadMatrixf (matrix);
}
void View3D::setPerspective(double left, double right, double bottom, double top, double fovy, double aspect, double front, double back) {
if (front < 0)
front = -front;
if (back < 0)
back = -back;
double tangent = Math::tang(Math::toRadians(fovy) * 0.5f); // tangent of half fovY
double hheight = front * tangent; // half height of near plane
double hwidth = hheight * aspect;
projMatrix.setGlPerspectiveMatrix(left, right, bottom, top, front, back);
float matrix[16];
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum (-hwidth, hwidth, -hheight, hheight, front, back);
projMatrix.getGlMatrix(matrix);
glLoadMatrixf(matrix);
}
Mais comme je suis soumis à cette contrainte "le contexte opengl ne peut être actif que dans un seul thread à la fois" : je suis obligé de charger la matrice à chaque rendu dans mon thread de rendu.
Et pas dans les fonctions move, rotate, etc... de la classe view3D qui sont appelée dans le thread main, dans la boucle de gestion d’évènement.
Je me demandais si il y avait une alternative qui me pemettrait d'éviter de devoir charger la matrice à chaque rendu en utilisant 1 thread pour le rendu mais apparemment non.