Eigen 重写部分 OpenGL 矩阵变换函数

5 篇文章 0 订阅
2 篇文章 0 订阅

最近花了一天时间重写了 OpenGL O p e n G L 中矩阵变换的部分函数,主要包含五个:
glLoadIdentity() g l L o a d I d e n t i t y ( ) gluLookAt() g l u L o o k A t ( ) glScaled() g l S c a l e d ( ) glTranslated() g l T r a n s l a t e d ( ) glRotated() g l R o t a t e d ( )
重写后对应的命名是:
LoadIdentity() L o a d I d e n t i t y ( ) LookAt() L o o k A t ( ) Scaled() S c a l e d ( ) Translated() T r a n s l a t e d ( ) Rotated() R o t a t e d ( )
另外由于是写在一个类中,所以还写了一个设值一个取值函数,并且还写了两个 debug d e b u g 函数。

这里的矩阵变换函数所用到的变换矩阵都是比较简单的,网上随便搜一下或者自己推一下就好了,可能稍微难一些的是旋转矩阵,这个可以去 LearnOpenGL CN L e a r n O p e n G L   C N 入门章节中变换部分看看。主要难点是使用 Eigen E i g e n 有些生疏,初次使用,所以写起来花了一些功夫,另外需要注意的是,在 OpenGL O p e n G L 中的矩阵变换使用的不是像 C++ C + + 等语言中的数组那样的以列为主行为辅的布局,而是刚好相反,也就是说要利用这些常规的变换矩阵的转置矩阵进行操作。

一定要注意是转置矩阵!!!

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

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-";
}

有关于 Eigen E i g e n 或者 OpenGL O p e n G L 问题的欢迎评论区讨论,如果代码有何不足,也欢迎大佬们指点一二……这里使用的是 Google C++ G o o g l e   C + + 编程规范。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值