345 lines
10 KiB
C++
345 lines
10 KiB
C++
#include "stdafx.h"
|
|
#include "IEngine.h"
|
|
#include "IResourceFactory.h"
|
|
#include "Transformation.h"
|
|
#include <algorithm>
|
|
|
|
|
|
Transformation::Transformation(IEngine& argEngine)
|
|
: ShaderParameterCollection(argEngine, 5)
|
|
, m_LocalTranslation(0.0f, 0.0f, 0.0f)
|
|
, m_WorldTranslation(0.0f, 0.0f, 0.0f)
|
|
, m_LocalScale(1.0f, 1.0f, 1.0f)
|
|
, m_WorldScale(1.0f, 1.0f, 1.0f)
|
|
, m_LocalDirection(0.0f, 0.0f, 1.0f)
|
|
, m_LocalUpDirection(0.0f, 1.0f, 0.0f)
|
|
, m_WorldDirection(0.0f, 0.0f, 1.0f)
|
|
, m_WorldUpDirection(0.0f, 1.0f, 0.0f)
|
|
, m_LocalRotation(0.0f, 0.0f, 0.0f, 1.0f)
|
|
, m_LastKnownYawPitchRoll(0.0f, 0.0f, 0.0f)
|
|
, m_IsDirty(true)
|
|
, m_ParentTransformation(NULL)
|
|
{
|
|
}
|
|
|
|
|
|
Transformation::~Transformation()
|
|
{
|
|
m_Engine.get_ResourceFactory().DeleteTransformation(*const_cast<Transformation*>(this), true);
|
|
}
|
|
|
|
|
|
void Transformation::set_TransformationBindings(const TransformationBindings& argData)
|
|
{
|
|
m_TransformationBindings = argData;
|
|
|
|
m_BasisShaderParameterCollection.RemoveAllShaderParameters();
|
|
this->RecreateAllShaderParameters();
|
|
}
|
|
|
|
|
|
TransformationBindings Transformation::get_TransformationBindings() const
|
|
{
|
|
return m_TransformationBindings;
|
|
}
|
|
|
|
|
|
void Transformation::set_LocalPosition(const D3DXVECTOR3& argValue)
|
|
{
|
|
m_LocalTranslation = argValue;
|
|
m_IsDirty = true;
|
|
}
|
|
|
|
|
|
const D3DXVECTOR3& Transformation::get_LocalPosition() const
|
|
{
|
|
return m_LocalTranslation;
|
|
}
|
|
|
|
|
|
const D3DXVECTOR3& Transformation::get_WorldPosition() const
|
|
{
|
|
return m_WorldTranslation;
|
|
}
|
|
|
|
|
|
void Transformation::set_LocalRotationYPR(const D3DXVECTOR3& argValue)
|
|
{
|
|
m_LastKnownYawPitchRoll = argValue;
|
|
::D3DXQuaternionRotationYawPitchRoll(&m_LocalRotation, argValue.x, argValue.y, argValue.z);
|
|
m_IsDirty = true;
|
|
}
|
|
|
|
|
|
const D3DXVECTOR3& Transformation::get_LocalRotationYPR() const
|
|
{
|
|
return m_LastKnownYawPitchRoll;
|
|
}
|
|
|
|
|
|
void Transformation::set_LocalRotation(const D3DXQUATERNION& argValue)
|
|
{
|
|
m_LocalRotation = argValue;
|
|
m_IsDirty = true;
|
|
}
|
|
|
|
|
|
const D3DXQUATERNION& Transformation::get_LocalRotation() const
|
|
{
|
|
return m_LocalRotation;
|
|
}
|
|
|
|
|
|
const D3DXQUATERNION& Transformation::get_WorldRotation() const
|
|
{
|
|
return m_WorldRotation;
|
|
}
|
|
|
|
|
|
const D3DXVECTOR3& Transformation::get_LocalDirection() const
|
|
{
|
|
return m_LocalDirection;
|
|
}
|
|
|
|
|
|
const D3DXVECTOR3& Transformation::get_WorldDirection() const
|
|
{
|
|
return m_WorldDirection;
|
|
}
|
|
|
|
|
|
const D3DXVECTOR3& Transformation::get_LocalUpDirection() const
|
|
{
|
|
return m_LocalUpDirection;
|
|
}
|
|
|
|
|
|
const D3DXVECTOR3& Transformation::get_WorldUpDirection() const
|
|
{
|
|
return m_WorldUpDirection;
|
|
}
|
|
|
|
|
|
D3DXVECTOR3 Transformation::get_LocalRightDirection() const
|
|
{
|
|
return m_LocalRightDirection;
|
|
}
|
|
|
|
|
|
D3DXVECTOR3 Transformation::get_WorldRightDirection() const
|
|
{
|
|
return m_WorldRightDirection;
|
|
}
|
|
|
|
|
|
void Transformation::set_LocalScale(const D3DXVECTOR3& argValue)
|
|
{
|
|
m_LocalScale = argValue;
|
|
m_IsDirty = true;
|
|
}
|
|
|
|
|
|
const D3DXVECTOR3& Transformation::get_LocalScale() const
|
|
{
|
|
return m_LocalScale;
|
|
}
|
|
|
|
|
|
const D3DXVECTOR3& Transformation::get_WorldScale() const
|
|
{
|
|
return m_WorldScale;
|
|
}
|
|
|
|
|
|
const D3DXMATRIX& Transformation::get_WorldMatrix() const
|
|
{
|
|
return m_WorldMatrix;
|
|
}
|
|
|
|
|
|
const D3DXMATRIX& Transformation::get_LocalMatrix() const
|
|
{
|
|
return m_LocalMatrix;
|
|
}
|
|
|
|
|
|
void Transformation::set_TransformationParent(ITransformation* argValue)
|
|
{
|
|
ITransformation* oldTransformationParent = m_ParentTransformation;
|
|
m_ParentTransformation = argValue;
|
|
m_IsDirty = true;
|
|
|
|
if (oldTransformationParent != NULL)
|
|
oldTransformationParent->RemoveTransformation(*const_cast<Transformation*>(this));
|
|
}
|
|
|
|
|
|
ITransformation* Transformation::get_TransformationParent() const
|
|
{
|
|
return m_ParentTransformation;
|
|
}
|
|
|
|
|
|
void Transformation::AddTransformation(ITransformation& argTransformation)
|
|
{
|
|
if (std::find(m_TransformationChildren.begin(),m_TransformationChildren.end(), &argTransformation) == m_TransformationChildren.end())
|
|
{
|
|
argTransformation.set_TransformationParent(this);
|
|
m_TransformationChildren.push_back(&argTransformation);
|
|
m_IsDirty = true;
|
|
}
|
|
}
|
|
|
|
|
|
void Transformation::RemoveTransformation(ITransformation& argTransformation)
|
|
{
|
|
std::vector<ITransformation*>::iterator found = std::find(m_TransformationChildren.begin(),m_TransformationChildren.end(), &argTransformation);
|
|
if (found != m_TransformationChildren.end())
|
|
{
|
|
m_TransformationChildren.erase(found);
|
|
argTransformation.set_TransformationParent(NULL);
|
|
m_IsDirty = true;
|
|
}
|
|
}
|
|
|
|
|
|
const std::vector<ITransformation*>& Transformation::get_Transformations() const
|
|
{
|
|
return m_TransformationChildren;
|
|
}
|
|
|
|
|
|
void Transformation::Update(bool argForceUpdate)
|
|
{
|
|
if (!m_IsDirty && !argForceUpdate)
|
|
return;
|
|
|
|
m_IsDirty = false;
|
|
|
|
D3DXMATRIXA16 localMatrix;
|
|
D3DXMATRIXA16 worldMatrix;
|
|
::D3DXMatrixIdentity(&localMatrix);
|
|
|
|
// look if we use our own matrix
|
|
D3DXMATRIXA16 rotationMatrix;
|
|
D3DXMATRIXA16 scaleMatrix;
|
|
D3DXMATRIXA16 translationMatrix;
|
|
D3DXMATRIXA16 comboMatrix;
|
|
|
|
D3DXQUATERNION rotation = m_LocalRotation;
|
|
|
|
::D3DXMatrixRotationQuaternion(&rotationMatrix, &rotation);
|
|
::D3DXMatrixScaling(&scaleMatrix, m_LocalScale.x, m_LocalScale.y, m_LocalScale.z);
|
|
::D3DXMatrixTranslation(&translationMatrix, m_LocalTranslation.x, m_LocalTranslation.y, m_LocalTranslation.z);
|
|
|
|
::D3DXMatrixMultiply(&comboMatrix, &rotationMatrix, &translationMatrix);
|
|
::D3DXMatrixMultiply(&comboMatrix, &scaleMatrix, &comboMatrix);
|
|
::D3DXMatrixMultiply(&localMatrix, &localMatrix, &comboMatrix);
|
|
|
|
D3DXVECTOR3 localDirection = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
|
|
D3DXVECTOR3 localUpDirection = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
|
|
D3DXVECTOR3 localRightDirection = D3DXVECTOR3(1.0f, 0.0f, 0.0f);
|
|
{
|
|
D3DXMATRIX tempMatrix;
|
|
::D3DXMatrixRotationQuaternion(&tempMatrix, &rotation);
|
|
D3DXVECTOR4 tempVector;
|
|
::D3DXVec3Transform(&tempVector, &localDirection, &tempMatrix);
|
|
localDirection.x = tempVector.x;
|
|
localDirection.y = tempVector.y;
|
|
localDirection.z = tempVector.z;
|
|
::D3DXVec3Normalize(&localDirection, &localDirection);
|
|
::D3DXVec3Transform(&tempVector, &localUpDirection, &tempMatrix);
|
|
localUpDirection.x = tempVector.x;
|
|
localUpDirection.y = tempVector.y;
|
|
localUpDirection.z = tempVector.z;
|
|
::D3DXVec3Normalize(&localUpDirection, &localUpDirection);
|
|
::D3DXVec3Transform(&tempVector, &localRightDirection, &tempMatrix);
|
|
localRightDirection.x = tempVector.x;
|
|
localRightDirection.y = tempVector.y;
|
|
localRightDirection.z = tempVector.z;
|
|
::D3DXVec3Normalize(&localRightDirection, &localRightDirection);
|
|
}
|
|
|
|
worldMatrix = localMatrix;
|
|
// stack parent matrix
|
|
if (m_ParentTransformation != NULL)
|
|
::D3DXMatrixMultiply(&worldMatrix, &localMatrix, &m_ParentTransformation->get_WorldMatrix());
|
|
|
|
// extract world related data
|
|
D3DXVECTOR3 worldScale, worldPosition;
|
|
D3DXQUATERNION worldRotation;
|
|
::D3DXMatrixDecompose(&worldScale, &worldRotation, &worldPosition, &worldMatrix);
|
|
|
|
D3DXVECTOR3 worldDirection = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
|
|
D3DXVECTOR3 worldUpDirection = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
|
|
D3DXVECTOR3 worldRightDirection = D3DXVECTOR3(1.0f, 0.0f, 0.0f);
|
|
{
|
|
D3DXMATRIX tempMatrix;
|
|
::D3DXMatrixRotationQuaternion(&tempMatrix, &worldRotation);
|
|
D3DXVECTOR4 tempVector;
|
|
::D3DXVec3Transform(&tempVector, &worldDirection, &tempMatrix);
|
|
worldDirection.x = tempVector.x;
|
|
worldDirection.y = tempVector.y;
|
|
worldDirection.z = tempVector.z;
|
|
::D3DXVec3Normalize(&worldDirection, &worldDirection);
|
|
::D3DXVec3Transform(&tempVector, &worldUpDirection, &tempMatrix);
|
|
worldUpDirection.x = tempVector.x;
|
|
worldUpDirection.y = tempVector.y;
|
|
worldUpDirection.z = tempVector.z;
|
|
::D3DXVec3Normalize(&worldUpDirection, &worldUpDirection);
|
|
::D3DXVec3Transform(&tempVector, &worldRightDirection, &tempMatrix);
|
|
worldRightDirection.x = tempVector.x;
|
|
worldRightDirection.y = tempVector.y;
|
|
worldRightDirection.z = tempVector.z;
|
|
::D3DXVec3Normalize(&worldRightDirection, &worldRightDirection);
|
|
}
|
|
|
|
m_LocalRightDirection = localRightDirection;
|
|
m_LocalUpDirection = localRightDirection;
|
|
m_LocalDirection = localDirection;
|
|
m_WorldRightDirection = worldRightDirection;
|
|
m_WorldUpDirection = worldUpDirection;
|
|
m_WorldDirection = worldDirection;
|
|
m_WorldScale = worldScale;
|
|
m_WorldRotation = worldRotation;
|
|
m_WorldTranslation = worldPosition;
|
|
m_LocalMatrix = localMatrix;
|
|
m_WorldMatrix = worldMatrix;
|
|
|
|
// update following transformations
|
|
for (uint32 i = 0; i < m_TransformationChildren.size(); ++i)
|
|
{
|
|
IUpdatable* updatable = dynamic_cast<IUpdatable*>(m_TransformationChildren[i]);
|
|
if (updatable != NULL && (updatable->get_WantsUpdate() || argForceUpdate))
|
|
updatable->Update(argForceUpdate);
|
|
}
|
|
}
|
|
|
|
|
|
void Transformation::RecreateAllShaderParameters()
|
|
{
|
|
if (!m_TransformationBindings.WorldMatrixSemanticName.empty())
|
|
this->SetParameter(m_TransformationBindings.WorldMatrixSemanticName, &m_WorldMatrix, ParameterBindType::BindBySemantic);
|
|
if (!m_TransformationBindings.LocalMatrixSemanticName.empty())
|
|
this->SetParameter(m_TransformationBindings.LocalMatrixSemanticName, &m_LocalMatrix, ParameterBindType::BindBySemantic);
|
|
|
|
if (!m_TransformationBindings.WorldPositionSemanticName.empty())
|
|
this->SetParameter(m_TransformationBindings.WorldPositionSemanticName, &m_WorldTranslation, ParameterBindType::BindBySemantic);
|
|
if (!m_TransformationBindings.LocalPositionSemanticName.empty())
|
|
this->SetParameter(m_TransformationBindings.LocalPositionSemanticName, &m_LocalTranslation, ParameterBindType::BindBySemantic);
|
|
|
|
if (!m_TransformationBindings.WorldDirectionSemanticName.empty())
|
|
this->SetParameter(m_TransformationBindings.WorldDirectionSemanticName, &m_WorldDirection, ParameterBindType::BindBySemantic);
|
|
if (!m_TransformationBindings.LocalDirectionSemanticName.empty())
|
|
this->SetParameter(m_TransformationBindings.LocalDirectionSemanticName, &m_LocalDirection, ParameterBindType::BindBySemantic);
|
|
|
|
if (!m_TransformationBindings.WorldUpDirectionSemanticName.empty())
|
|
this->SetParameter(m_TransformationBindings.WorldUpDirectionSemanticName, &m_WorldUpDirection, ParameterBindType::BindBySemantic);
|
|
if (!m_TransformationBindings.LocalUpDirectionSemanticName.empty())
|
|
this->SetParameter(m_TransformationBindings.LocalUpDirectionSemanticName, &m_LocalUpDirection, ParameterBindType::BindBySemantic);
|
|
|
|
if (!m_TransformationBindings.WorldRightDirectionSemanticName.empty())
|
|
this->SetParameter(m_TransformationBindings.WorldRightDirectionSemanticName, &m_WorldRightDirection, ParameterBindType::BindBySemantic);
|
|
if (!m_TransformationBindings.LocalRightDirectionSemanticName.empty())
|
|
this->SetParameter(m_TransformationBindings.LocalRightDirectionSemanticName, &m_LocalRightDirection, ParameterBindType::BindBySemantic);
|
|
} |