当前位置: 首页 > 工具软件 > SDL2-CS > 使用案例 >

从零开始的openGL--cs游戏(4)GameObject类 ,Component类,Transform类

宦砚
2023-12-01

GameObject类 ,所有游戏中的物体都继承此类

#ifndef GameObject_H
#define GameObject_H
#include "Transform.h"
#include <map>
#include <string>
#include "Component.h"
using namespace std;
class GameObject
{
public:
	GameObject(string name, Transform* parent);
	Transform* transform;
	map<string, Component*> Components;
	virtual void Update();
	virtual void LateUpdate();
	virtual void Render();
	string name;

	template<typename T>
	T* AddComponent()
	{
		T* t = new T(this);
		Component* component = &(*t);
		string name = typeid(T).name();
		auto find = Components.find(name);
		if (find != Components.end())
		{
			find->second->SetNext(component);
		}
		else
		{
			Components[name] = component;
		}
		return t;
	}
	template<typename T>
	T* GetComponent()
	{
		string name = typeid(T).name();
		auto find = Components.find(name);
		if (find != Components.end())
		{
			return find->second;
		}
		return nullptr;
	}
};
#endif
#include "GameObject.h"

GameObject::GameObject(string name, Transform* parent)
{
    this->name = name;
    transform = new Transform(glm::vec3(0.0f), glm::vec3(0.0f), glm::vec3(1.0f),parent);
    transform->SetGameObject(this);
}

void GameObject::Update()
{
    map<string, Component*>::iterator  iter;
    for (iter = Components.begin(); iter != Components.end(); iter++) {
        iter->second->Update();
    }

}

void GameObject::LateUpdate()
{
    map<string, Component*>::iterator  iter;
    for (iter = Components.begin(); iter != Components.end(); iter++) {
        iter->second->LateUpdate();
    }
}

void GameObject::Render()
{
    map<string, Component*>::iterator  iter;
    for (iter = Components.begin(); iter != Components.end(); iter++) {
        iter->second->Render();
    }
}


Component类,必须附加到gameobject中

#ifndef Component_H
#define Component_H
#include <string>
using namespace std;
class GameObject;
class Component
{
public:
	virtual string GetName();
	GameObject* gameObject;
	Component();
	Component(GameObject* gameObject);
	void SetNext(Component* next);
	virtual void Update();
	virtual void LateUpdate();
	virtual void Render();
	~Component();
private:
	Component* _next;
	string _name;
protected:
	void SetName(string name);

};
#endif


---------------------
#include "Component.h"

#include "Component.h"
#include "GameObject.h"

string Component::GetName()
{
	return _name;
}

Component::Component()
{
	_next = nullptr;
}

Component::Component(GameObject* gameObject)
{
	this->gameObject = gameObject;
	_next = nullptr;
}

void Component::SetNext(Component* next)
{
	if (_next == nullptr)
		_next = next;
	else
		_next->SetNext(next);
}

void Component::Update()
{
	if (_next != nullptr)
		_next->Update();
}

void Component::LateUpdate()
{
	if (_next != nullptr)
		_next->LateUpdate();
}

void Component::Render()
{
	if (_next != nullptr)
		_next->Render();
}

Component::~Component()
{
	;
}

void Component::SetName(string name)
{
	_name = name;
}


Transform类,gameobject的基础属性。

#ifndef Transform_H
#define Transform_H
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <vector>
using namespace std;
const float PI = 3.1415926536f;
class GameObject;
class Transform
{
public:
	static Transform* Root;
	GameObject* gameObject;
	Transform* parent;
	vector<Transform*> childs;

	glm::vec3 localPosition;
	glm::vec3 localXYZAngle;
	glm::vec3 localScale;

	glm::mat4 worldTransformMat;

	

	Transform(glm::vec3 localPosition = glm::vec3(0.0f), glm::vec3 localXYZAngle = glm::vec3(0.0f), glm::vec3 localScale = glm::vec3(1.0f), Transform* parent = Transform::Root);
	glm::mat4 GetLocalTransformMat();
	glm::mat4 SetWorldTransformMat();
	glm::mat4 GetWorldToLocalMat();
	glm::vec3 GetWordPosition();


	glm::mat4 GetLocalPositionMat();
	glm::mat4 GetLocalRotateMat(glm::mat4 model);
	glm::mat4 GetLocalScaleMat(glm::mat4 model);

	glm::vec3 GetWordForward();
	glm::vec3 GetWordRight();
	glm::vec3 GetWordUp();
	glm::vec3 GetLocalForward();
	glm::vec3 GetLocalRight();
	glm::vec3 GetLocalUp();

	void SetLocalForward(glm::vec3 forward);
	void SetLocalRight(glm::vec3 right);
	void SetLocalUp(glm::vec3 up);

	/*void SetForwardUp(glm::vec3 forward , glm::vec3 up);
	void SetRightUP(glm::vec3 right, glm::vec3 up);
	void SetForwardRight(glm::vec3 forward , glm::vec3 right);*/

	glm::mat4 WorldMatToLocal(glm::mat4 worldMat);
	glm::vec3 WorldDirToLocal(glm::vec3 worldVec);
	glm::vec3 LocalDirToWorld(glm::vec3 LocalVec);
	void Updete();
	void LateUpdate();
	void Render();
	void SetGameObject(GameObject* go);


private:
	glm::vec3 m_forward; //Z
	glm::vec3 m_right; //X
	glm::vec3 m_up; //Y
};
#endif


-------------------

#include "Transform.h"
#include "GameObject.h"
#include <glm/gtc/quaternion.hpp>


Transform::Transform(glm::vec3 localPosition, glm::vec3 localXYZAngle, glm::vec3 localScale, Transform* parent) :
	localPosition(localPosition), localXYZAngle(localXYZAngle), localScale(localScale), parent(parent)
{
	m_forward = glm::vec3(0.0f, 0.0f, 1.0f);
	m_up = glm::vec3(0.0f, 1.0f, 0.0f);
	m_right = glm::vec3(1.0f, 0.0f, 0.0f);
	if (parent != nullptr)
	{
		parent->childs.push_back(this);
		worldTransformMat = parent->worldTransformMat;
	}
	else
	{
		worldTransformMat = glm::mat4(1.0f);
	}
}
Transform* Transform::Root = nullptr;

glm::mat4 Transform::GetLocalTransformMat()
{
	/*glm::mat4 model(1.0f);
	model = glm::translate(model, localPosition);
	model = localXYZAngle.z == 0.0f ? model : glm::rotate(model, localXYZAngle.z, m_forward);
	model = localXYZAngle.y == 0.0f ? model : glm::rotate(model, localXYZAngle.y, m_up);
	model = localXYZAngle.x == 0.0f ? model : glm::rotate(model, localXYZAngle.x, m_right);
	model = glm::scale(model, localScale);
	return model;*/
	return GetLocalScaleMat(GetLocalRotateMat(GetLocalPositionMat()));
}

glm::mat4 Transform::SetWorldTransformMat()
{
	glm::mat4 worldTransformMat = GetLocalTransformMat();
	if (this != Transform::Root && parent != Transform::Root)
		worldTransformMat = parent->worldTransformMat * worldTransformMat;
	this->worldTransformMat = worldTransformMat;
	return worldTransformMat;
}

glm::mat4 Transform::GetWorldToLocalMat()
{
	return glm::inverse(worldTransformMat);
}

glm::vec3 Transform::GetWordPosition()
{
	glm::vec3 worldP =  glm::vec3(parent->worldTransformMat * glm::vec4(localPosition ,1.0f));
	return worldP;
}

glm::mat4 Transform::GetLocalPositionMat()
{
	glm::mat4 model(1.0f);
	return glm::translate(model, localPosition);
}

glm::mat4 Transform::GetLocalRotateMat(glm::mat4 model)
{
	//先旋转y再x再z
	/*glm::quat Rotation = glm::quat(1.0f, glm::radians(localXYZAngle.x), glm::radians(localXYZAngle.y), glm::radians(localXYZAngle.z));
	glm::mat4 RotationM = glm::mat4_cast(Rotation);*/
	m_forward = glm::vec3(0.0f, 0.0f, 1.0f);
	m_up = glm::vec3(0.0f, 1.0f, 0.0f);
	m_right = glm::vec3(1.0f, 0.0f, 0.0f);
	auto a = glm::angleAxis(glm::radians(localXYZAngle.y),m_up);
	m_forward = a * m_forward;
	m_right = a * m_right;
	auto b = glm::angleAxis(glm::radians(localXYZAngle.x), m_right);
	m_up = b * m_up; 
	m_forward = b * m_forward;
	auto c = glm::angleAxis(glm::radians(localXYZAngle.z), m_forward);
	m_up = c * m_up;
	m_right = c * m_right;
	/*model = localXYZAngle.z == 0.0f ? model : glm::rotate(model, localXYZAngle.z ,m_forward);
	model = localXYZAngle.y == 0.0f ? model : glm::rotate(model, localXYZAngle.y, m_up);
	model = localXYZAngle.x == 0.0f ? model : glm::rotate(model, localXYZAngle.x, m_right);*/
	return glm::mat4_cast(c*b*a) * model;
}

glm::mat4 Transform::GetLocalScaleMat(glm::mat4 model)
{
	return glm::scale(model, localScale);
}

glm::vec3 Transform::GetWordForward()
{
	return LocalDirToWorld(glm::vec3(0.0f,0.0f,1.0f));
	//return LocalDirToWorld(GetLocalForward());
}

glm::vec3 Transform::GetWordRight()
{
	return LocalDirToWorld(glm::vec3(1.0f, 0.0f, 0.0f));
	//return LocalDirToWorld(GetLocalRight());
}

glm::vec3 Transform::GetWordUp()
{
	return LocalDirToWorld(glm::vec3(0.0f, 1.0f, 0.0f));
	//return LocalDirToWorld(GetLocalUp());
}

glm::vec3 Transform::GetLocalForward()
{
	/*glm::vec3 f(0.0f);
	f.y = sin(glm::radians(localXYZAngle.x));
	float k = sqrtf(1 - f.y * f.y);
	f.x = k * sin(glm::radians(localXYZAngle.y));
	f.z = k * cos(glm::radians(localXYZAngle.y));
	return glm::normalize(f);*/
	return m_forward;
}

glm::vec3 Transform::GetLocalRight()
{
	/*glm::vec3 f(0.0f);
	f.y = sin(-localXYZAngle.z);
	float k = sqrtf(1 - f.y * f.y);
	f.x = k * cos(localXYZAngle.y);
	f.z = k * sin(localXYZAngle.y);
	return glm::normalize(f);*/
	return m_right;
}

glm::vec3 Transform::GetLocalUp()
{
	/*glm::vec3 f(0.0f);
	f.z = sin(-localXYZAngle.x);
	float k = sqrtf(1 - f.z * f.z);
	f.x = k * sin(localXYZAngle.z);
	f.z = k * cos(localXYZAngle.z);
	return glm::normalize(f);*/
	return m_up;
}

void Transform::SetLocalForward(glm::vec3 forward)
{
	localXYZAngle.y = atan2f(-forward.x, forward.z) * (180.f / PI);
	localXYZAngle.x = atan2f(forward.y, forward.x * forward.x + forward.z * forward.z) * (180.f / PI);
	localXYZAngle.z = 0.0f;
}

void Transform::SetLocalRight(glm::vec3 right)
{
	localXYZAngle.y = atan2f(right.z, right.x) * (180.f / PI);
	localXYZAngle.z = atan2f(-right.y, right.x * right.x + right.z * right.z) * (180.f / PI);
	localXYZAngle.x = 0.0f;
}

void Transform::SetLocalUp(glm::vec3 up)
{
	localXYZAngle.z = atan2f(up.x, up.y) * (180.f / PI);
	localXYZAngle.x = atan2f(-up.z, up.x * up.x + up.y * up.y) * (180.f / PI);
	localXYZAngle.y = 0.0f;
}

glm::mat4 Transform::WorldMatToLocal(glm::mat4 worldMat)
{
	return GetWorldToLocalMat() * worldMat;
}

glm::vec3 Transform::WorldDirToLocal(glm::vec3 worldVec)
{
	glm::mat3 worldToLocalMat(glm::transpose(GetWorldToLocalMat()));
	glm::vec3 localVec3 = glm::inverse(worldToLocalMat) * worldVec;
	return glm::normalize(localVec3);
}

glm::vec3 Transform::LocalDirToWorld(glm::vec3 LocalVec)
{
	glm::mat3 worldToObject(GetWorldToLocalMat());
	glm::vec3 worldVec = glm::transpose(worldToObject) * LocalVec;
	return glm::normalize(worldVec);
}

void Transform::Updete()
{
	SetWorldTransformMat();
	gameObject->Update();
	for (vector<Transform*>::iterator iter = childs.begin(); iter != childs.end(); iter++)
	{
		(*iter)->Updete();
	}
}

void Transform::LateUpdate()
{
	gameObject->LateUpdate();
	for (vector<Transform*>::iterator iter = childs.begin(); iter != childs.end(); iter++)
	{
		(*iter)->LateUpdate();
	}
}

void Transform::Render()
{
	gameObject->Render();
	for (vector<Transform*>::iterator iter = childs.begin(); iter != childs.end(); iter++)
	{
		(*iter)->Render();
	}
}

void Transform::SetGameObject(GameObject* go)
{
	gameObject = go;
}



 类似资料: