1. 程式人生 > 其它 >C++學習_元件物件封裝(一)

C++學習_元件物件封裝(一)

建立元件類檔案
#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();
}