Translate Assimp 3D模型也会旋转

问题描述 投票:0回答:1

This is the view before translate, which is correct.This is the view after translate, which is incorrect.

我使用Assimp加载了OpenGL(C ++)中的3D模型。我需要在屏幕上移动该模型(平移),就像它始终在X和Y轴(无Z轴)时面向相机一样。就像仅以2D方式移动该模型一样(但当然,如果旋转它,它也会显示Z轴)。

我的渲染功能是:

    camX = CamY = 0;  
    camZ = 5;  
    lookatX = lookatY = lookatZ = 0;  

    void C3DModel::render(void)  
    { 

        static float step = 0.0f;  
        setCamera(camX, camY, camZ, lookatX, lookatY, lookatZ);  
        translate(-3, 1, 0); // here is the issue . 
        scale(scaleFactor, scaleFactor, scaleFactor);  
        rotate(step, 0.0f, 1.0f, 0.0f); 
    }

    void C3DModel::translate(float x, float y, float z) 
    {

       float aux[16];

       setTranslationMatrix(aux, x, y, z);
       multMatrix(modelMatrix, aux);
       setModelMatrix();
   }

   void C3DModel::setTranslationMatrix(float *mat, float x, float y, float z)
   {

       setIdentityMatrix(mat, 4);
       mat[12] = x;
       mat[13] = y;
       mat[14] = z;
   }

   void C3DModel::setScaleMatrix(float *mat, float sx, float sy, float sz)
   {

       setIdentityMatrix(mat, 4);
       mat[0] = sx;
       mat[5] = sy;
       mat[10] = sz;
   }

   void C3DModel::setRotationMatrix(float *mat, float angle, float x, float y, float z)
   {
       float radAngle = DegToRad(angle);
       float co = cos(radAngle);
       float si = sin(radAngle);
       float x2 = x * x;
       float y2 = y * y;
       float z2 = z * z;

       mat[0] = x2 + (y2 + z2) * co;
       mat[4] = x * y * (1 - co) - z * si;
       mat[8] = x * z * (1 - co) + y * si;
       mat[12] = 0.0f;

       mat[1] = x * y * (1 - co) + z * si;
       mat[5] = y2 + (x2 + z2) * co;
       mat[9] = y * z * (1 - co) - x * si;
       mat[13] = 0.0f;

       mat[2] = x * z * (1 - co) - y * si;
       mat[6] = y * z * (1 - co) + x * si;
       mat[10] = z2 + (x2 + y2) * co;
       mat[14] = 0.0f;

       mat[3] = 0.0f;
       mat[7] = 0.0f;
       mat[11] = 0.0f;
       mat[15] = 1.0f;
   }


   void C3DModel::rotate(float angle, float x, float y, float z) 
   {

      float aux[16];

      setRotationMatrix(aux, angle, x, y, z);
      multMatrix(modelMatrix, aux);
      setModelMatrix();
  }

  void C3DModel::scale(float x, float y, float z)
  {
      float aux[16];

      setScaleMatrix(aux, x, y, z);
      multMatrix(modelMatrix, aux);
      setModelMatrix();
  }

  void C3DModel::setIdentityMatrix(float *mat, int size)
  {
     // fill matrix with 0s
     for (int i = 0; i < size * size; ++i)
         mat[i] = 0.0f;
     // fill diagonal with 1s
     for (int i = 0; i < size; ++i)
        mat[i + i * size] = 1.0f;
  }

  void C3DModel::multMatrix(float *a, float *b) 
  {

     float res[16];

     for (int i = 0; i < 4; ++i) 
     {
         for (int j = 0; j < 4; ++j) 
         {
             res[j * 4 + i] = 0.0f;
             for (int k = 0; k < 4; ++k) 
             {
                 res[j * 4 + i] += a[k * 4 + i] * b[j * 4 + k];
             }
         }
     }
     memcpy(a, res, 16 * sizeof(float));
  }

  void C3DModel::setModelMatrix() 
  {
      glBindBuffer(GL_UNIFORM_BUFFER, matricesUniBuffer);
      glBufferSubData(GL_UNIFORM_BUFFER, ModelMatrixOffset, MatrixSize, modelMatrix);
      glBindBuffer(GL_UNIFORM_BUFFER, 0);
 }

 void C3DModel::crossProduct(float *a, float *b, float *res) 
 {
     res[0] = a[1] * b[2] - b[1] * a[2];
     res[1] = a[2] * b[0] - b[2] * a[0];
     res[2] = a[0] * b[1] - b[0] * a[1];
 }

 // Normalize a vec3
 void C3DModel::normalize(float *a)
 {

     float mag = sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
     a[0] /= mag;
     a[1] /= mag;
     a[2] /= mag;
 }

 void C3DModel::setCamera(float posX, float posY, float posZ, float lookAtX, float lookAtY, float lookAtZ) 
 {

     float dir[3], right[3], up[3];
     up[0] = 0.0f;  up[1] = 1.0f;   up[2] = 0.0f;
     dir[0] = (lookAtX - posX);
     dir[1] = (lookAtY - posY);
     dir[2] = (lookAtZ - posZ);
     normalize(dir);
     crossProduct(dir, up, right);
     normalize(right);
     crossProduct(right, dir, up);
     normalize(up);
     float viewMatrix[16], aux[16];
     viewMatrix[0] = right[0];
     viewMatrix[4] = right[1];
     viewMatrix[8] = right[2];
     viewMatrix[12] = 0.0f;
     viewMatrix[1] = up[0];
     viewMatrix[5] = up[1];
     viewMatrix[9] = up[2];
     viewMatrix[13] = 0.0f;
     viewMatrix[2] = -dir[0];
     viewMatrix[6] = -dir[1];
     viewMatrix[10] = -dir[2];
     viewMatrix[14] = 0.0f;
     viewMatrix[3] = 0.0f;
     viewMatrix[7] = 0.0f;
     viewMatrix[11] = 0.0f;
     viewMatrix[15] = 1.0f;
     setTranslationMatrix(aux, -posX, -posY, -posZ);
     multMatrix(viewMatrix, aux);
     glBindBuffer(GL_UNIFORM_BUFFER, matricesUniBuffer);
     glBufferSubData(GL_UNIFORM_BUFFER, ViewMatrixOffset, MatrixSize, viewMatrix);
     glBindBuffer(GL_UNIFORM_BUFFER, 0);
 }
c++ opengl assimp
1个回答
0
投票

我将尝试用两种不同的矩阵将对象的旋转和屏幕位置所需的平移分开。

[在每一帧,我将使用C3DModel::setRotationMatrix中的代码计算旋转矩阵,并使用C3DModel::setTranslationMatrix进行平移,将它们合并为一个新的新模型矩阵,并将其应用于您的对象。请记住,顺序很重要,如果先旋转,则对象将绕过obj文件中的原点;如果平移后旋转,则对象将绕世界原点旋转(就像围绕太阳的行星一样,太阳会是原点)。

最后,它看起来像:

void C3DModel::render(void){

    float* rotation = createRotation(angle, x, y, z);
    float* translation = createTranslation(x, y, z);
    float* updatedModel = mul(rotation, translation) //order matters
    setModel(updatedModel);
}
© www.soinside.com 2019 - 2024. All rights reserved.