0

我想做一個4 * 4矩陣的類,它是從一個16浮點數組構建的,但我也想表示它爲4個vec4的數組(針對每列)。 問題是它沒有編譯,並且在我調用mat4的構造函數的地方給出錯誤。
我mat4.h:類與聯合使用構造函數上的已刪除的函數

struct mat4 { 

    union 
    { 
     float elements[4 * 4]; // column major ordering, index = row + col * 4 
     vec4 columns[4]; 
    }; 

    mat4(); 
    mat4(float diagonal); 

    mat4& mul(const mat4& other); //TODO: maybe return mat4 
    // vec4 getColumn(int colIndex); 
    static mat4 identity(); // construct and return an identity matrix 
    static mat4 orthographic(float left, float right, float bottom, float top, float near, float far); // boundaries (clipping planes) 
    static mat4 perspective(float fov, float aspectRatio, float near, float far); 
    static mat4 translation(const vec3& translation); 
    static mat4 scale(const vec3 &scale); 
    static mat4 rotation(float angle, const vec3 & axis); 
    friend mat4 operator*(mat4 left, const mat4 & right); 
    mat4& operator*=(const mat4 &other); //TODO: check that it fits with the vectors 
    friend std::ostream &operator<<(std::ostream &stream, const mat4 &m); 
}; 

我mat4.cpp:

#include "mat4.h" 
     mat4::mat4() { 
      for (int i = 0; i < 4 * 4; i++) 
       elements[i] = 0; 
     } 
     mat4::mat4(float diagonal) { 
      for (int i = 0; i < 4 * 4; ++i) { 
       elements[i] = 0; 
      } 
      for(int i = 0; i < 4; i += 1) 
       elements[i + i * 4] = diagonal; 
     } 
     mat4& mat4::mul(const mat4 &other) { 
      for (int i = 0; i < 4; ++i)  // col 
       for (int j = 0; j < 4; ++j) { // row 
        float sum = 0; 
        for (int k = 0; k < 4; ++k) 
         sum += elements[j + k * 4] * other.elements[k + i * 4]; 
        elements[j + i * 4] = sum; 
       } 
      return *this; 
     } 

     /*vec4 mat4::getColumn(int colIndex) { 
      //colIndex *= 4; // TODO: profile and see if it's the same as (colIndex * 4) in each cell 
      return vec4(elements[0 + colIndex * 4], elements[1 + colIndex * 4], elements[2 + colIndex * 4], elements[3 + colIndex * 4]); 
     }*/ 
     mat4 mat4::identity() { 
      return mat4(1.0f); 
     } 

     mat4 operator*(mat4 left, const mat4 &right) { 
      return left.mul(right); 
     } 

     mat4 &mat4::operator*=(const mat4 &other) { 
      return mul(other); 
     } 

     mat4 mat4::orthographic(float left, float right, float bottom, float top, float near, float far) { 
      mat4 result(1); 
      result.elements[0 + 0 * 4] = 2.0f/(right - left); 
      result.elements[1 + 1 * 4] = 2.0f/(top - bottom); 
      result.elements[2 + 2 * 4] = -2.0f/(far - near); 
      result.elements[0 + 3 * 4] = (left + right)/(left - right); 
      result.elements[1 + 3 * 4] = (bottom + top)/(bottom - top); 
      result.elements[2 + 3 * 4] = (far + near) /(far - near); 
      //result.elements[3 + 3 * 4] = 1; this is achieved by mat result(1); 
      return result; 
     } 

     mat4 mat4::perspective(float fov, float aspectRatio, float near, float far) { 
      mat4 result; 

      float q = 1.0f/tanf(toRadians(fov)/2.0f); 
      result.elements[0 + 0 * 4] = q/aspectRatio; 
      result.elements[1 + 1 * 4] = q; 
      result.elements[2 + 2 * 4] = (near + far)/(near - far); // -(far + near)/(far - near); 
      result.elements[3 + 2 * 4] = -1; 
      result.elements[2 + 3 * 4] = 2 * far * near/(near - far); // -2 * far * near/(far - near); 

      return result; 
     } 

     mat4 mat4::translation(const vec3 &translation) { 
      mat4 result(1.0f); // identity matrix 
      result.elements[0 + 3 * 4] = translation.x;  // create a matrix as follows: 1 0 0 x 
      result.elements[1 + 3 * 4] = translation.y;  //        0 1 0 y 
      result.elements[2 + 3 * 4] = translation.z;  //        0 0 1 z 
      return result;         //        0 0 0 1 
     } 

     mat4 mat4::scale(const vec3 &scale) { 
      mat4 result(1.0f); 
      result.elements[0 + 0 * 4] = scale.x;  // create a matrix as follows: x 0 0 0 
      result.elements[1 + 1 * 4] = scale.y;  //        0 y 0 0 
      result.elements[2 + 2 * 4] = scale.z;  //        0 0 z 0 
      return result;       //        0 0 0 1 
     } 

     mat4 mat4::rotation(float angle, const vec3 &axis) { 
      mat4 result(1.0f); 
      float r = toRadians(angle); 
      float s = sinf(r); 
      float c = cosf(r); 
      result.elements[0 + 0 * 4] = axis.x * (1 - c) + c; 
      result.elements[1 + 0 * 4] = axis.x * axis.y * (1 - c) + axis.z * s; 
      result.elements[2 + 0 * 4] = axis.x * axis.z * (1 - c) - axis.y * s; 

      result.elements[0 + 1 * 4] = axis.y * axis.x * (1 - c) - axis.z * s; 
      result.elements[1 + 1 * 4] = axis.y * (1 - c) + c; 
      result.elements[2 + 1 * 4] = axis.y * axis.z * (1 - c) + axis.x * s; 

      result.elements[0 + 2 * 4] = axis.z * axis.x * (1 - c) + axis.y * s; 
      result.elements[1 + 2 * 4] = axis.z * axis.y * (1 - c) - axis.x * s; 
      result.elements[2 + 2 * 4] = axis.z * (1 - c) + c; 

      return result; 
     } 

     std::ostream &operator<<(std::ostream &stream, const mat4 &m) { 
      stream << "mat4: ("; 
      for (int i = 0; i < 4; ++i) { 
       for (int j = 0; j < 4; ++j) { 
        stream << m.elements[i + j * 4] << " "; 
       } 
       if(i < 3) stream << std::endl << "  "; 
       else stream << ")"; 
      } 
      return stream; 
     } 

我vec4.h:

#include <iostream> 

     struct vec4 { 
      float w, x, y, z; 

      vec4() = default; // declare a default constructor as a no-parameter constructor (given that I have another one) 

      vec4(float w, float x, float y, float z); 

      vec4(const vec4 &v); 

      vec4 add(const vec4 &other); 
      vec4 add(float w, float x, float y, float z); 
      vec4 sub(const vec4 &other); 
      vec4 sub(float w, float x, float y, float z); 
      vec4 mul(const vec4 &other); 
      vec4 mul(float w, float x, float y, float z); 
      vec4 div(const vec4 &other); 
      vec4 div(float w, float x, float y, float z); 

      friend vec4 operator+(vec4 left, const vec4 &right); 

      friend vec4 operator-(vec4 left, const vec4 &right); 

      friend vec4 operator*(vec4 left, const vec4 &right); 

      friend vec4 operator/(vec4 left, const vec4 &right); 

      vec4 operator+=(const vec4 &other); 

      vec4 operator-=(const vec4 &other); 

      vec4 operator*=(const vec4 &other); 

      vec4 operator/=(const vec4 &other); 

      bool operator==(const vec4 &other); 

      bool operator!=(const vec4 &other); 

      friend std::ostream &operator<<(std::ostream &stream, const vec4 &vector); 
     }; 

我vec4.cpp:

/*  vec4::vec4() { 
      w = 0; 
      x = 0; 
      y = 0; 
      z = 0; 
     } 
*/ 
     vec4::vec4(float w, float x, float y, float z) { 
      this->w = w; 
      this->x = x; 
      this->y = y; 
      this->z = z; 
     } 

     vec4::vec4(const vec4 &v) { 
      this->w = v.w; 
      this->x = v.x; 
      this->y = v.y; 
      this->z = v.z; 
     } 

     vec4 vec4::add(const vec4 &other) { 
      this->w += other.w; 
      this->x += other.x; 
      this->y += other.y; 
      this->z += other.z; 
      return *this; 
     } 

     vec4 vec4::add(float w, float x, float y, float z) { 
      this->w += w; 
      this->x += x; 
      this->y += y; 
      this->z += z; 
      return *this; 
     } 

     vec4 vec4::sub(const vec4 &other) { 
      this->w -= other.w; 
      this->x -= other.x; 
      this->y -= other.y; 
      this->z -= other.z; 
      return *this; 
     } 

     vec4 vec4::sub(float w, float x, float y, float z) { 
      this->w -= w; 
      this->x -= x; 
      this->y -= y; 
      this->z -= z; 
      return *this; 
     } 

     vec4 vec4::mul(const vec4 &other) { 
      this->w *= other.w; 
      this->x *= other.x; 
      this->y *= other.y; 
      this->z *= other.z; 
      return *this; 
     } 

     vec4 vec4::mul(float w, float x, float y, float z) { 
      this->w *= w; 
      this->x *= x; 
      this->y *= y; 
      this->z *= z; 
      return *this; 
     } 

     vec4 vec4::div(const vec4 &other) { 
      this->w /= other.w; 
      this->x /= other.x; 
      this->y /= other.y; 
      this->z /= other.z; 
      return *this; 
     } 

     vec4 vec4::div(float w, float x, float y, float z) { 
      this->w /= w; 
      this->x /= x; 
      this->y /= y; 
      this->z /= z; 
      return *this; 
     } 

     std::ostream &operator<<(std::ostream &stream, const vec4 &vector) { 
      stream << "vec4: (" << vector.w << ", " << vector.x << ", " << vector.y << ", " << vector.z << ")"; 
      return stream; 
     } 

     vec4 operator+(vec4 left, const vec4 &right) { 
      return left.add(right); 
     } 

     vec4 operator-(vec4 left, const vec4 &right) { 
      return left.sub(right); 
     } 

     vec4 operator*(vec4 left, const vec4 &right) { 
      return left.mul(right); 
     } 

     vec4 operator/(vec4 left, const vec4 &right) { 
      return left.div(right); 
     } 

     vec4 vec4::operator+=(const vec4 &other) { 
      return add(other); 
     } 

     vec4 vec4::operator-=(const vec4 &other) { 
      return sub(other); 

     } 

     vec4 vec4::operator*=(const vec4 &other) { 
      return mul(other); 

     } 

     vec4 vec4::operator/=(const vec4 &other) { 
      return div(other); 

     } 

     bool vec4::operator==(const vec4 &other) { 
      return (this->w == other.w && this->x == other.x && this->y == other.y && this->z == other.z); 
     } 

     bool vec4::operator!=(const vec4 &other) { 
      return !(*this == other); 
     } 

錯誤日誌:

.../src/math/mat4.cpp: In static member function ‘static engine::math::mat4 engine::math::mat4::identity()’: 
.../src/math/mat4.cpp:36:29: error: use of deleted function ‘engine::math::mat4::mat4(engine::math::mat4&&)’ 
      return mat4(1.0f); 
          ^
In file included from .../src/math/mat4.cpp:5:0: 
.../src/math/mat4.h:11:16: note: ‘engine::math::mat4::mat4(engine::math::mat4&&)’ is implicitly deleted because the default definition would be ill-formed: 
     struct mat4 { 
       ^
.../src/math/mat4.h:16:31: error: union member ‘engine::math::mat4::<anonymous union>::columns’ with non-trivial ‘engine::math::vec4::vec4(const engine::math::vec4&)’ 
       vec4 columns[4]; 
          ^
.../src/math/mat4.cpp: In function ‘engine::math::mat4 engine::math::operator*(engine::math::mat4, const engine::math::mat4&)’: 
.../src/math/mat4.cpp:40:34: error: use of deleted function ‘engine::math::mat4::mat4(const engine::math::mat4&)’ 
      return left.mul(right); 
           ^
In file included from .../src/math/mat4.cpp:5:0: 
.../src/math/mat4.h:11:16: note: ‘engine::math::mat4::mat4(const engine::math::mat4&)’ is implicitly deleted because the default definition would be ill-formed: 
     struct mat4 { 
       ^
.../src/math/mat4.h:16:31: error: union member ‘engine::math::mat4::<anonymous union>::columns’ with non-trivial ‘engine::math::vec4::vec4(const engine::math::vec4&)’ 
       vec4 columns[4]; 
          ^
.../src/math/mat4.cpp: In static member function ‘static engine::math::mat4 engine::math::mat4::orthographic(float, float, float, float, float, float)’: 
.../src/math/mat4.cpp:56:20: error: use of deleted function ‘engine::math::mat4::mat4(engine::math::mat4&&)’ 
      return result; 
        ^
.../src/math/mat4.cpp: In static member function ‘static engine::math::mat4 engine::math::mat4::perspective(float, float, float, float)’: 
.../src/math/mat4.cpp:69:20: error: use of deleted function ‘engine::math::mat4::mat4(engine::math::mat4&&)’ 
      return result; 
        ^
.../src/math/mat4.cpp: In static member function ‘static engine::math::mat4 engine::math::mat4::translation(const engine::math::vec3&)’: 
.../src/math/mat4.cpp:77:20: error: use of deleted function ‘engine::math::mat4::mat4(engine::math::mat4&&)’ 
      return result;         //        0 0 0 1 
        ^
.../src/math/mat4.cpp: In static member function ‘static engine::math::mat4 engine::math::mat4::scale(const engine::math::vec3&)’: 
.../src/math/mat4.cpp:85:20: error: use of deleted function ‘engine::math::mat4::mat4(engine::math::mat4&&)’ 
      return result;       //        0 0 0 1 
        ^
.../src/math/mat4.cpp: In static member function ‘static engine::math::mat4 engine::math::mat4::rotation(float, const engine::math::vec3&)’: 
.../src/math/mat4.cpp:105:20: error: use of deleted function ‘engine::math::mat4::mat4(engine::math::mat4&&)’ 
      return result; 
        ^
CMakeFiles/GameEngine.dir/build.make:169: recipe for target 'CMakeFiles/GameEngine.dir/src/math/mat4.cpp.o' failed 
make[3]: *** [CMakeFiles/GameEngine.dir/src/math/mat4.cpp.o] Error 1 
make[3]: *** Waiting for unfinished jobs.... 
.../main.cpp: In function ‘int main(int, char**)’: 
.../main.cpp:19:50: error: use of deleted function ‘engine::math::mat4::mat4(engine::math::mat4&&)’ 
    mat4 position = mat4::translation(vec3(2,3,4)); 
               ^
In file included from .../src/math/math.h:8:0, 
       from .../main.cpp:4: 
.../src/math/mat4.h:11:16: note: ‘engine::math::mat4::mat4(engine::math::mat4&&)’ is implicitly deleted because the default definition would be ill-formed: 
     struct mat4 { 
       ^
.../src/math/mat4.h:16:31: error: union member ‘engine::math::mat4::<anonymous union>::columns’ with non-trivial ‘engine::math::vec4::vec4(const engine::math::vec4&)’ 
       vec4 columns[4]; 
          ^

我認爲大部分代碼都是不相關的,所以不要去讀它的所有內容。 只是爲了比較的緣故,如果我從mat4.h中的聯盟中刪除鏈接vec4 columns[4];,那麼一切都太棒了。

在過去的一個小時裏,我一直在爲此付出沉重的代價,所以我非常樂意幫助。

謝謝。

編輯:

想什麼@ 0x499602D2建議,並且還加入mat4(mat4&&) = default;到mat4.h之後,我只有一個錯誤剩餘:

.../src/math/mat4.cpp: In function ‘engine::math::mat4 engine::math::operator*(engine::math::mat4, const engine::math::mat4&)’: 
.../src/math/mat4.cpp:39:34: error: use of deleted function ‘engine::math::mat4::mat4(const engine::math::mat4&)’ 
      return left.mul(right); 
           ^
In file included from .../src/math/mat4.cpp:5:0: 
.../src/math/mat4.h:11:16: note: ‘engine::math::mat4::mat4(const engine::math::mat4&)’ is implicitly declared as deleted because ‘engine::math::mat4’ declares a move constructor or move assignment operator 
     struct mat4 { 
       ^

我能做些什麼來解決這個問題?

回答

2

vec4聲明瞭一個複製構造函數,所以沒有爲其類生成的隱式移動構造函數。由於你的union中有一個vec4的數組,因此它的移動構造函數被刪除,因爲vec4不能移出。此外,由於vec4具有用戶提供的複製構造函數,因此它被認爲是非平凡的,因此聯合的複製構造函數也被刪除。由於工會是mat4的成員(並且工會有刪除的副本和移動構造函數),所以mat4的副本和移動構造函數也被刪除。

刪除的函數在重載分辨率中仍然起作用,因此您從初始化初始化返回值時選擇了刪除的移動構造函數。爲了解決這個問題,聲明默認移動構造函數裏面vec4

struct vec4 { 
    // ... 
    vec4(vec4&&) = default; 
    // ... 
}; 

和拷貝構造函數mat4

mat4(mat4 const&) {} 

如果您有需要複製你的任何成員必須這樣做手動AFAIK。

+0

很抱歉的新手問題,之間有什麼區別一個複製構造函數和一個移動構造函數?我來自Java的背景,不知道移動構造函數是什麼... – shoham

+0

@shoham http://stackoverflow.com/questions/3106110/what-are-move-semantics – 0x499602D2

+0

@shoham解決您的問題是在'vec4'中聲明一個移動構造函數,請參閱我的編輯。 – 0x499602D2

0

0x499602D2的答案解釋了你的錯誤,並回答了你問的具體問題。但我認爲這至少是一種奇怪的設計,以兩種可能的方式存儲矩陣數據。而你的實現與它是不一致的,因爲在mat4& mat4::mul(const mat4 &other)(和其他方法)中,你只使用聯合的elements部分。

IMHO你應該considere到:

  • 用簡單float elements[4 * 4];
  • 更換聯合添加一個構造服用4個vec4參數和存儲的值到elements陣列
  • 添加一個const方法來提取矩陣中的向量

因爲定義一個單一的內部實現n和儘可能多的外部表示,如你所願。

它不直接回答你的問題(@ 0x499602D2已經沒有),但如果你聽從這個建議,問題就會消失,所以這個答案...

相關問題