Recently, I spent a day to rewrite some functions of matrix transformation in OpenGL O P E N GL, mainly including five: G l l oadIdent I ty() gl l oo a t() gl l oo a t() GlTranslated () G L Tra N S L A T E D (), glRotated() G L R O T A T E D () LoadIdentity() Loa D Iden T I ty(), LookAt() Lo k a T (), Scaled() Sca L ed(), Translated() t ran S L A T E D (), Rota T E D (), and because it was in a class, there was a set value and a value function, and two debug d, E, B, U and G functions.

Here the matrix transformation function used in the transformation matrix is relatively simple, just search online or push yourself good, maybe a little more difficult is the rotation matrix, this can go to LearnOpenGL CN L E a R N Op E nGL CN transformation section look at. The main difficulty is the use of Eigen E I G E N is a little unfamiliar, the first use, so it took some time to write. In addition, it needs to be noted that the matrix transformation in OpenGL O P E N GL is not used as the array in C++ C++ and other languages with columns as the main action auxiliary layout. I’m going to do the opposite, which means I’m going to operate with the transpose of these regular transformation matrices.

Be sure to note the transpose!!

opengl_transformations.h o p e n g l _ t r a n s f o r m a t i o n s . h

#ifndef OPENGL_TRANSFORMATIONS_H
#define OPENGL_TRANSFORMATIONS_H

#include <GL/glew.h>
#include <GL/gl.h>

#include <Eigen/Core>
#include <Eigen/Dense>

#include <QString>

class OpenGLTransformations {
 private:
  Eigen::Matrix4d *matrix_;
  GLdouble *matrix_1x16_;

  const GLdouble kPi = 3.14159265359;

 public:
  OpenGLTransformations();
  OpenGLTransformations(GLdouble *matrix);
  ~OpenGLTransformations();

  void set_matrix(GLdouble *matrix);
  GLdouble *matrix_1x16();

  void LoadIdentity();
  void LookAt(Eigen::Vector3d position, Eigen::Vector3d target,
              Eigen::Vector3d world_up);
  void Scaled(Eigen::Vector3d zoom);
  void Translated(Eigen::Vector3d move);
  void Rotated(GLdouble angle, Eigen::Vector3d axis);

  void DebugOutputTransposeMatrix4d(Eigen::Matrix4d mat, QString s);
  void DebugOutputVector3d(Eigen::Vector3d vec, QString s);
};

#endif  // OPENGL_TRANSFORMATIONS_H
Copy the code

opengl_transformations.cpp o p e n g l _ t r a n s f o r m a t i o n s . c p p

#include "opengl_transformations.h"

#include <QDebug>
#include <cmath>

OpenGLTransformations::OpenGLTransformations() {
  matrix_ = new Eigen::Matrix4d();
  matrix_1x16_ = new GLdouble[16];
}

OpenGLTransformations::OpenGLTransformations(GLdouble *matrix) {
  matrix_ = new Eigen::Matrix4d();
  matrix_1x16_ = new GLdouble[16];
  set_matrix(matrix);
}

OpenGLTransformations::~OpenGLTransformations() {
  delete matrix_;
  delete matrix_1x16_;
}

//  set matrix_
void OpenGLTransformations::set_matrix(GLdouble *matrix) {
  Eigen::Matrix4d &mat = *matrix_;
  for (int i = 0; i < 4; i++) {
    mat(i, 0) = matrix[i * 4];
    mat(i, 1) = matrix[i * 4 + 1];
    mat(i, 2) = matrix[i * 4 + 2];
    mat(i, 3) = matrix[i * 4 + 3];
  }
}

//  get matrix_ with GLdouble[16]
GLdouble *OpenGLTransformations::matrix_1x16() {
  GLdouble *matrix = matrix_1x16_;
  Eigen::Matrix4d &mat = *matrix_;
  for (int i = 0; i < 4; i++) {
    matrix[i * 4] = mat(i, 0);
    matrix[i * 4 + 1] = mat(i, 1);
    matrix[i * 4 + 2] = mat(i, 2);
    matrix[i * 4 + 3] = mat(i, 3);
  }

  return matrix;
}

//  Identity
void OpenGLTransformations::LoadIdentity() {
  qDebug() << "gl_load_identity";

  Eigen::Matrix4d &mat = *matrix_;
  mat = Eigen::Matrix4d::Identity();

  //  for (int i = 0; i < 4; i++) {
  //    for (int j = 0; j < 4; j++) {
  //      if (i == j) {
  //        mat(i, j) = 1;
  //      } else {
  //        mat(i, j) = 0;
  //      }
  //    }
  //  }
}

//  look at
void OpenGLTransformations::LookAt(Eigen::Vector3d position,
                                   Eigen::Vector3d target,
                                   Eigen::Vector3d world_up) {
  qDebug() << "gl_u_look_at";

  //  Calculate cameraDirection
  Eigen::Vector3d z_axis = position - target;
  z_axis.normalize();
  //  debug_output_vector3d(z_axis, "z_axis");

  //  Get positive right axis vector
  Eigen::Vector3d x_axis = world_up;
  x_axis.normalize();
  //  debug_output_vector3d(x_axis, "x_axis");
  x_axis = x_axis.cross(z_axis);
  //  debug_output_vector3d(x_axis, "x_axis");
  x_axis.normalize();
  //  debug_output_vector3d(x_axis, "x_axis");

  //  Calculate camera up vector
  Eigen::Vector3d y_axis = z_axis;
  y_axis = y_axis.cross(x_axis);
  //  debug_output_vector3d(y_axis, "y_axis");

  //  Create translation matrix
  Eigen::Matrix4d translation = Eigen::Matrix4d::Identity();
  translation(3, 0) = -position(0);  //  Fourth column, first row
  translation(3, 1) = -position(1);
  translation(3, 2) = -position(2);
  //  debug_output_transpose_matrix4d(translation, "translation");

  //  Create rotation matrix
  Eigen::Matrix4d rotation = Eigen::Matrix4d::Identity();
  rotation(0, 0) = x_axis(0);  //  First column, first row
  rotation(1, 0) = x_axis(1);
  rotation(2, 0) = x_axis(2);
  rotation(0, 1) = y_axis(0);  //  First column, second row
  rotation(1, 1) = y_axis(1);
  rotation(2, 1) = y_axis(2);
  rotation(0, 2) = z_axis(0);  //  First column, third row
  rotation(1, 2) = z_axis(1);
  rotation(2, 2) = z_axis(2);
  //  debug_output_transpose_matrix4d(rotation, "rotation");

  //  Update matrix_
  Eigen::Matrix4d &mat = *matrix_;
  mat = rotation * translation * mat;
  //  debug_output_transpose_matrix4d(mat, "matrix_");
}

void OpenGLTransformations::Scaled(Eigen::Vector3d zoom) {
  //  Create scale matrix
  Eigen::Matrix4d scale = Eigen::Matrix4d::Identity();
  scale(0, 0) = zoom(0);
  scale(1, 1) = zoom(1);
  scale(2, 2) = zoom(2);

  //  Update matrix_
  Eigen::Matrix4d &mat = *matrix_;
  mat = scale * mat;
}

void OpenGLTransformations::Translated(Eigen::Vector3d move) {
  //  Create translation matrix
  Eigen::Matrix4d translation = Eigen::Matrix4d::Identity();
  translation(3, 0) = move(0);  //  Fourth column, first row
  translation(3, 1) = move(1);
  translation(3, 2) = move(2);

  //  Update matrix_
  Eigen::Matrix4d &mat = *matrix_;
  mat = translation * mat;
}

void OpenGLTransformations::Rotated(GLdouble angle, Eigen::Vector3d axis) {
  //  Create rotation matrix
  Eigen::Matrix4d rotation = Eigen::Matrix4d::Identity();

  GLdouble radian = angle / 180 * kPi;
  GLdouble radian_sin = std::sin(radian);
  GLdouble radian_cos = std::cos(radian);
  //  In Eigen we access elements as mat[col][row] due to column-major layout
  if (axis(0) > 0) {
    rotation(1, 1) = radian_cos;
    rotation(1, 2) = radian_sin;
    rotation(2, 1) = -radian_sin;
    rotation(2, 2) = radian_cos;
  } else if (axis(1) > 0) {
    rotation(0, 0) = radian_cos;
    rotation(0, 2) = -radian_sin;
    rotation(2, 0) = radian_sin;
    rotation(2, 2) = radian_cos;
  } else if (axis(2) > 0) {
    rotation(0, 0) = radian_cos;
    rotation(0, 1) = radian_sin;
    rotation(1, 0) = -radian_sin;
    rotation(1, 1) = radian_cos;
  }

  //  Update matrix_
  Eigen::Matrix4d &mat = *matrix_;
  mat = rotation * mat;
}

void OpenGLTransformations::DebugOutputTransposeMatrix4d(Eigen::Matrix4d mat,
                                                         QString s) {
  qDebug() << "debug_4*4:" << s;
  for (int i = 0; i < 4; i++) {
    qDebug() << mat(0, i) << mat(1, i) << mat(2, i) << mat(3, i);
  }
  qDebug() << "debug-";
}

void OpenGLTransformations::DebugOutputVector3d(Eigen::Vector3d vec,
                                                QString s) {
  qDebug() << "debug_3*1:" << s;
  qDebug() << vec(0);
  qDebug() << vec(1);
  qDebug() << vec(2);
  qDebug() << "debug-";
}
Copy the code

Eigen E I g E N or OpenGL Op E n g L The Google C++ programming specification is used here.