← Back to file list Raw

src/CTransform.cpp

#include "CTransform.h"
#include "U_Scripting.h"
CRotationEulerRepresentation::CRotationEulerRepresentation(CTransformBase& transform) : m_transform(transform) {}
CQuatEulerRepresentation::CQuatEulerRepresentation(glm::quat& quat) : m_quat(quat) {}
void CEulerRepresentationBase::m_wrapEulerToQuat(const CAngles& euler)
{
glm::quat q = glm::quat(glm::vec3(euler.x.asRadians(), euler.y.asRadians(), euler.z.asRadians()));
m_setQuat(q);
}
CAngles CEulerRepresentationBase::m_wrapQuatToEuler() const
{
glm::vec3 euler_glm = glm::eulerAngles(m_getQuat());
return euler_glm;
}
CAngles CEulerRepresentationBase::GetRotation() const
{
return m_wrapQuatToEuler();
}
CAngle CEulerRepresentationBase::GetRotationX() const
{
return m_wrapQuatToEuler().x;
}
CAngle CEulerRepresentationBase::GetRotationY() const
{
return m_wrapQuatToEuler().y;
}
CAngle CEulerRepresentationBase::GetRotationZ() const
{
return m_wrapQuatToEuler().z;
}
void CEulerRepresentationBase::SetRotation(const CAngles& rot)
{
m_wrapEulerToQuat(rot);
}
void CEulerRepresentationBase::SetRotationX(CAngle x)
{
CAngles rot = m_wrapQuatToEuler();
m_wrapEulerToQuat(CAngles(x, rot.y, rot.z));
}
void CEulerRepresentationBase::SetRotationY(CAngle y)
{
CAngles rot = m_wrapQuatToEuler();
m_wrapEulerToQuat(CAngles(rot.x, y, rot.z));
}
void CEulerRepresentationBase::SetRotationZ(CAngle z)
{
CAngles rot = m_wrapQuatToEuler();
m_wrapEulerToQuat(CAngles(rot.x, rot.y, z));
}
void CEulerRepresentationBase::ResetRotation()
{
m_wrapEulerToQuat(CAngles(0.0f, 0.0f, 0.0f));
}
CQuatEulerRepresentation CTransformBase::CMeasurePack::GetEulerRotation() { return CQuatEulerRepresentation(Rotation); }
CEulerRepresentationBase::operator CAngles() const
{
return m_wrapQuatToEuler();
}
CTransformBase& CRotationEulerRepresentation::GetTransform()
{
return m_transform;
}
void CRotationEulerRepresentation::m_setQuat(const glm::quat& q)
{
return m_transform.SetRotation(q);
}
glm::quat CRotationEulerRepresentation::m_getQuat() const
{
return m_transform.GetRotation();
}
void CQuatEulerRepresentation::m_setQuat(const glm::quat& q)
{
m_quat = q;
}
glm::quat CQuatEulerRepresentation::m_getQuat() const
{
return m_quat;
}
glm::quat& CQuatEulerRepresentation::GetQuaternion()
{
return m_quat;
}
CTransformBase::CTransformBase(const CMeasurePack& pack) : CTransformBase()
{
SetPRS(pack);
}
glm::vec3 CTransformBase::GetPosition() const
{
return m_getPosition();
}
glm::quat CTransformBase::GetRotation() const
{
return m_getRotation();
}
glm::vec3 CTransformBase::GetScale() const
{
return m_getScale();
}
void CTransformBase::SetPosition(const glm::vec3& pos)
{
if(GetPosition() == pos) { return; }
CMeasurePack old = GetPRS();
m_setPosition(pos);
OnTransformChanged(old, this);
}
void CTransformBase::SetRotation(const glm::quat& rot)
{
if(GetRotation() == rot) { return; }
CMeasurePack old = GetPRS();
m_setRotation(rot);
OnTransformChanged(old, this);
}
void CTransformBase::SetScale(const glm::vec3& scl)
{
if(GetScale() == scl) { return; }
CMeasurePack old = GetPRS();
m_setScale(scl);
OnTransformChanged(old, this);
}
glm::vec3 CTransformBase::GetForwardVector() const
{
static const glm::vec3 forw = glm::vec3(0, 0, -1);
return glm::mat3_cast(GetRotation()) * forw;
}
glm::vec3 CTransformBase::GetRightVector() const
{
static const glm::vec3 right = glm::vec3(1, 0, 0);
return glm::mat3_cast(GetRotation()) * right;
}
glm::vec3 CTransformBase::GetUpVector() const
{
static const glm::vec3 up = glm::vec3(0, 1, 0);
return glm::mat3_cast(GetRotation()) * up;
}
CRotationEulerRepresentation CTransformBase::GetEulerRotation() { return CRotationEulerRepresentation(*this); }
void CTransformBase::SetFromMatrix(const glm::mat4x4 matrix)
{
auto pos = glm::vec3(matrix[3]);
glm::vec3 scale;
scale.x = glm::length(glm::vec3(matrix[0]));
scale.y = glm::length(glm::vec3(matrix[1]));
scale.z = glm::length(glm::vec3(matrix[2]));
glm::mat4 rotationMatrix = matrix;
rotationMatrix[0] /= scale.x;
rotationMatrix[1] /= scale.y;
rotationMatrix[2] /= scale.z;
glm::quat rotation = glm::quat_cast(rotationMatrix);
SetPRS({ pos, rotation, scale });
}
glm::mat4 CTransformBase::GetModelMatrix() const
{
glm::mat4 translate_matrix = glm::translate(glm::mat4(1.0f), GetPosition());
glm::mat4 rotation_matrix = glm::mat4_cast(GetRotation());
glm::mat4 scale_matrix = glm::scale(glm::mat4(1.0f), GetScale());
return translate_matrix * rotation_matrix * scale_matrix;
}
void CTransformBase::ResetTransform()
{
SetPRS(glm::vec3(0.0f, 0.0f, 0.0f), glm::identity<glm::quat>(), glm::vec3(1.0f, 1.0f, 1.0f));
}
CTransformBase::CMeasurePack CTransformBase::GetPRS() const
{
return { GetPosition(), GetRotation(), GetScale() };
}
CTransformBase& CTransformBase::operator=(const CTransformBase& rhs)
{
SetPRS(rhs.GetPRS());
return *this;
}
CTransform& CTransform::operator=(const CTransform& rhs)
{
SetPRS(rhs.GetPRS());
return *this;
}
glm::mat4 CTransformBase::operator*(const CTransformBase& rhs) const
{
return GetModelMatrix() * rhs.GetModelMatrix();
}
void CTransformBase::SetPRS(const glm::vec3& pos, const glm::quat& rot, const glm::vec3& scl)
{
CMeasurePack old = GetPRS();
m_setPosition(pos);
m_setRotation(rot);
m_setScale(scl);
OnTransformChanged(old, this);
}
void CTransformBase::SetPRS(const CMeasurePack& pack)
{
CMeasurePack old = GetPRS();
m_setPosition(pack.Position);
m_setRotation(pack.Rotation);
m_setScale(pack.Scale);
OnTransformChanged(old, this);
}
void CTransformBase::SetPR(const glm::vec3& pos, const glm::quat& rot)
{
CMeasurePack old = GetPRS();
m_setPosition(pos);
m_setRotation(rot);
OnTransformChanged(old, this);
}
void CTransformBase::SetPS(const glm::vec3& pos, const glm::vec3& scl)
{
CMeasurePack old = GetPRS();
m_setPosition(pos);
m_setScale(scl);
OnTransformChanged(old, this);
}
void CTransformBase::SetRS(const glm::quat& rot, const glm::vec3& scl)
{
CMeasurePack old = GetPRS();
m_setRotation(rot);
m_setScale(scl);
OnTransformChanged(old, this);
}
CTransformBase::CTransformBase()
{
auto scForward = std::make_unique<CFunctionalScriptField>(
[this](sol::state_view st) -> sol::object
{
return sol::make_object_userdata<glm::vec3>(st, GetForwardVector());
//return ScriptUtils::CreateSharedObject<glm::vec3>(st, GetForwardVector()).second;
});
auto scRight = std::make_unique<CFunctionalScriptField>(
[this](sol::state_view st) -> sol::object
{
return sol::make_object_userdata<glm::vec3>(st, GetRightVector());
//return ScriptUtils::CreateSharedObject<glm::vec3>(st, GetRightVector()).second;
});
auto scUp = std::make_unique<CFunctionalScriptField>(
[this](sol::state_view st) -> sol::object
{
return sol::make_object_userdata<glm::vec3>(st, GetUpVector());
//return ScriptUtils::CreateSharedObject<glm::vec3>(st, GetUpVector()).second;
});
auto scModelMatrix = std::make_unique<CFunctionalScriptField>(
[this](sol::state_view st) -> sol::object
{
return ScriptUtils::ToObject<glm::mat4>(GetModelMatrix(), st); //TODO shared_ptr of matrix
});
ScriptFields.AddField("forward", std::move(scForward));
ScriptFields.AddField("right", std::move(scRight));
ScriptFields.AddField("up", std::move(scUp));
ScriptFields.AddField("modelMatrix", std::move(scModelMatrix));
OnTransformChanged += [this](CMeasurePack old, CTransformBase* _this) { m_Changed = true; };
}
bool CTransformBase::AcknowledgeChange() const
{
bool ret = m_Changed;
m_Changed = false;
return ret;
}
std::unique_ptr<CScriptFieldBase> CTransform::V_SetupPositionProp()
{
return std::make_unique<CFunctionalScriptField>
(
[this](sol::state_view st) -> sol::object
{
return ScriptUtils::ToObject(this->m_position, st);
},
[this](sol::object obj) -> void
{
SetPosition(ScriptUtils::FromObject<glm::vec3>(obj));
}
);
}
std::unique_ptr<CScriptFieldBase> CTransform::V_SetupRotationProp()
{
return std::make_unique<CFunctionalScriptField>
(
[this](sol::state_view st) -> sol::object
{
return ScriptUtils::ToObject(this->m_rotation, st);
},
[this](sol::object obj) -> void
{
SetRotation(ScriptUtils::FromObject<glm::quat>(obj));
}
);
}
std::unique_ptr<CScriptFieldBase> CTransform::V_SetupScaleProp()
{
return std::make_unique<CFunctionalScriptField>
(
[this](sol::state_view st) -> sol::object
{
return ScriptUtils::ToObject(this->m_scale, st);
},
[this](sol::object obj) -> void
{
SetScale(ScriptUtils::FromObject<glm::vec3>(obj));
}
);
}
bool CTransformBase::V_ScriptInit(std::shared_ptr<sol::state> state, sol::table table)
{
if(!ScriptFields.IsFieldExist<std::string>("position"))
{
auto scPosition = V_SetupPositionProp();
auto scRotation = V_SetupRotationProp();
auto scScale = V_SetupScaleProp();
ScriptFields.AddField("position", std::move(scPosition));
ScriptFields.AddField("rotation", std::move(scRotation));
ScriptFields.AddField("scale", std::move(scScale));
}
table.set_function("resetTransform", [this]() { ResetTransform(); });
sol::table onTransformChanged = OnTransformChanged.GetScriptTable(state);
table["onTransformChanged"] = onTransformChanged;
ScriptFields.CreateMetaTable(table);
return true;
}
glm::vec3 CTransform::m_getPosition() const
{
return m_position;
}
glm::quat CTransform::m_getRotation() const
{
return m_rotation;
}
glm::vec3 CTransform::m_getScale() const
{
return m_scale;
}
void CTransform::m_setPosition(const glm::vec3& pos)
{
for(size_t i = 0; i < pos.length(); i++) { if(std::isnan(pos[i])) { return; } }
m_position = pos;
}
void CTransform::m_setRotation(const glm::quat& qua)
{
for(size_t i = 0; i < qua.length(); i++) { if(std::isnan(qua[i])) { return; } }
m_rotation = qua;
}
void CTransform::m_setScale(const glm::vec3& scl)
{
for(size_t i = 0; i < scl.length(); i++) { if(std::isnan(scl[i])) { return; } }
m_scale = scl;
}
CTransform::CTransform(const CTransform& other) : m_position(other.m_position), m_rotation(other.m_rotation), m_scale(other.m_scale) {}
CTransformBoolDelta GetTransformBoolDelta(const CTransformBase::CMeasurePack& oldprs, CTransformBase* _this)
{
return
{
oldprs.Position != _this->GetPosition(),
oldprs.Rotation != _this->GetRotation(),
oldprs.Scale != _this->GetScale()
};
}
CTransformBase::CMeasurePack GetTransformDelta(const CTransformBase::CMeasurePack& oldprs, CTransformBase* _this)
{
return
{
_this->GetPosition() - oldprs.Position,
_this->GetRotation() - oldprs.Rotation,
_this->GetScale() - oldprs.Scale
};
}