C++學習_元件物件封裝(一)
阿新 • • 發佈:2022-05-19
建立元件類檔案
#pragma once #ifndef __GAME_COMPONENT_H__ #define __GAME_COMPONENT_H__ //定義一些元件的型別 enum emComponentType { ComType_None, //空型別 ComType_Transform, // 座標變換元件 ComType_MeshRender, //渲染元件 ComType_Camera, // 攝像機元件 ComType_Light, //燈光元件 //... }; //使用前置宣告遊戲物件類 class GameObject; typedef class Component {public: virtual ~Component() = default; //建立預設析構 Component(const Component& that) = delete; //刪除拷貝功能 Component& operator = (const Component& that) = delete;//刪除賦值功能 //初始化型別 Component(GameObject* pObject) { mType = emComponentType::ComType_None; mOwner = pObject; } emComponentType Type() {return mType; }// 獲取元件型別 GameObject* gameobject() { return mOwner; }//獲取持有物件 protected: GameObject* mOwner;//誰持有該元件 emComponentType mType;//元件的型別 }COMPONENT,*LPCOMPONENT; #endif
建立Obj 物件類檔案,每一個遊戲物件至少都應該有這麼唯一的一個tansform元件
#pragma once #ifndef __GAME_OBJECT_H__ #define __GAME_OBJECT_H__ #include"Transform.h" #include <vector> class GameObject { public: //初始 GameObject() { //建立transform元件 mpTransform = nullptr; mpTransform = (Transform*)AddComponent(emComponentType::ComType_Transform); } virtual ~GameObject() { //將建立的元件釋放 } //增加元件的功能 //如果不為空返回,為空則建立 LPCOMPONENT AddComponent(emComponentType t) { switch (t) { case emComponentType::ComType_Transform: { if (mpTransform!=nullptr) { return mpTransform; } mpTransform = new Transform(this); return mpTransform; }break; case emComponentType::ComType_Camera: { }break; case emComponentType::ComType_MeshRender: { }break; case emComponentType::ComType_Light: { }break; default: { } } return nullptr; } //獲取元件的功能 LPCOMPONENT GetComponent(emComponentType t) { if (t == emComponentType::ComType_Transform) { return mpTransform; } for (auto& itr:mComponents) { if (itr->Type() == t) { return itr; } } return nullptr; } //刪除元件的功能 void RemoveComponent(emComponentType t) { if (t == emComponentType::ComType_Transform) { return; } for (auto it = mComponents.begin();it!=mComponents.end();it++) { if ((*it)->Type() == t) { delete* it; mComponents.erase(it); return; } } } Transform& transform() { return *mpTransform; } protected: Transform* mpTransform;//每一個遊戲物件至少都應該有這麼唯一的一個tansform元件 std::vector<LPCOMPONENT> mComponents;//元件儲存除了transform的所有的元件 }; #endif
建立Transform 座標變換元件物件類
#pragma once #ifndef __GAME_COMPONENT_TRANSFORM_H__ #define __GAME_COMPONENT_TRANSFORM_H__ #include "Component.h" #include "Matrix4x4.h" class Transform:public Component { public: //必須使用初始化列表的方式初始化父類唯一的帶參構造 Transform(GameObject* pObj) :Component(pObj) { mType = emComponentType::ComType_Transform; mPosition = vector3d::Zero(); mScale = vector3d::One(); mRotation = vector3d::Zero(); //凡是修改了位置、縮放、旋轉的成員值,都應該呼叫對應的矩陣更新函式 _update_Matrix_Translate(); _update_Matrix_Scale(); _update_Matrix_Rotate(); } //獲取變換元件成員 函式 vector3d forward() { return mZ; } vector3d back() { return -mZ; } vector3d right() { return mX; } vector3d left() { return -mX; } vector3d up() { return mY; } vector3d down() { return -mY; } const vector3d& localScale() { return mScale; } const vector3d& position() { return mPosition; } const vector3d& rotation() { return mRotation; } Matrix4x4& MatT() { return MatrixTranslate; } Matrix4x4& MatS() { return MatrixScale; } Matrix4x4& MatR() { return MatrixRotate; } //修改成員變數函式 ,每次修改都應該呼叫對應的矩陣更新函式 void SetPosition(const vector3d& v) { mPosition = v; _update_Matrix_Translate(); } void SetScale(const vector3d& v) { mScale = v; _update_Matrix_Scale(); } void SetRotation(const vector3d& v) { mRotation = v; _update_Matrix_Rotate(); } void translate(const vector3d& tv) { mPosition += tv; _update_Matrix_Translate(); } void scale(const vector3d& ts) { mScale *= ts; _update_Matrix_Scale(); } void rotate(const vector3d& v); protected: //凡是修改了位置、縮放、旋轉的成員值,都應該呼叫對應的矩陣更新函式 void _update_Matrix_Translate(); void _update_Matrix_Scale(); void _update_Matrix_Rotate(); protected: vector3d mPosition; //位置 vector3d mScale;//縮放 vector3d mRotation; //旋轉 vector3d mX, mY, mZ; Matrix4x4 MatrixTranslate;//平移矩陣 Matrix4x4 MatrixScale;//縮放矩陣 Matrix4x4 MatrixRotate;//旋轉矩陣 }; #endif
#include "Transform.h" #include "GameObject.h" void Transform::rotate(const vector3d& v) { //將角度轉換為弧度 vector3d angle_r = v * 0.01745329f;//M_PI/180; //使用每一個軸旋轉角度得到對應的旋轉矩陣 Matrix4x4 _mx; _mx.SetRotateX_r(angle_r.x); Matrix4x4 _my; _my.SetRotateY_r(angle_r.y); Matrix4x4 _mz; _mz.SetRotateZ_r(angle_r.z); //尤拉角的旋轉順序有6中 xyz,xzy,yxz,yzx,zxy,zyx //我們選取zxy順序進行旋轉 Matrix4x4 _mr = _mz * _mx * _my; //在這個基礎上得到完整的旋轉矩陣 MatrixRotate *= _mr; Matrix4x4& r = MatrixRotate; //根據正交矩陣的性質,對應軸向的矩陣的轉置矩陣為其旋轉矩陣 mX.x = r._11; mY.x = r._12; mZ.x = r._13; mX.y = r._21; mY.y = r._22; mZ.y = r._23; mX.z = r._31; mY.z = r._32; mZ.z = r._33; mX.Normalize(); mY.Normalize(); mZ.Normalize(); //需要根據當前的資料求解尤拉角 double sy = sqrt(r._11 * r._11 + r._21 * r._21); bool singular = sy < 1e-6;//1e-6使用的是科學計數法表示的 0.000001 if (!singular) { mRotation.x = atan2(r._32, r._32); mRotation.y = atan2(-r._31, sy); mRotation.z = atan2(r._21, r._11); } else { mRotation.x = atan2(r._23, r._22); mRotation.y = atan2(-r._31, sy); mRotation.z = 0; } //將弧度轉換為角度 mRotation *= 57.2957795f; } void Transform::_update_Matrix_Translate() { MatrixTranslate.SetTranslate(mPosition); } void Transform::_update_Matrix_Scale() { MatrixScale.SetScale(mScale); } void Transform::_update_Matrix_Rotate() { //將角度轉換為弧度 vector3d angle_r = mRotation * 0.01745329f;//M_PI/180; //使用每一個軸旋轉角度得到對應的旋轉矩陣 Matrix4x4 _mx; _mx.SetRotateX_r(angle_r.x); Matrix4x4 _my; _my.SetRotateY_r(angle_r.y); Matrix4x4 _mz; _mz.SetRotateZ_r(angle_r.z); //尤拉角的旋轉順序有6中 xyz,xzy,yxz,yzx,zxy,zyx //我們選取zxy順序進行旋轉 MatrixRotate = _mz * _mx * _my; Matrix4x4& r = MatrixRotate; //根據正交矩陣的性質,對應軸向的矩陣的轉置矩陣為其旋轉矩陣 mX.x = r._11; mY.x = r._12; mZ.x = r._13; mX.y = r._21; mY.y = r._22; mZ.y = r._23; mX.z = r._31; mY.z = r._32; mZ.z = r._33; mX.Normalize(); mY.Normalize(); mZ.Normalize(); }