#include "stdafx.h" #include "IEngine.h" #include "IResourceFactory.h" #include "Transformation.h" #include 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(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(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::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& 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(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); }