Fixed damageable triggers rendering the wrong side in rotated areas

This commit is contained in:
parax0 2016-05-03 03:13:21 -06:00
parent ab38205611
commit 57451e231d
7 changed files with 62 additions and 18 deletions

View File

@ -1,6 +1,8 @@
#include "CDamageableTriggerExtra.h"
#include "Core/Render/CDrawUtil.h"
#include "Core/Render/CRenderer.h"
#include <Common/Assert.h>
#include <Math/MathUtil.h>
CDamageableTriggerExtra::CDamageableTriggerExtra(CScriptObject *pInstance, CScene *pScene, CScriptNode *pParent)
: CScriptExtra(pInstance, pScene, pParent)
@ -38,7 +40,7 @@ CDamageableTriggerExtra::~CDamageableTriggerExtra()
void CDamageableTriggerExtra::CreateMaterial()
{
if (mpMat) delete mpMat;
ASSERT(!mpMat);
mpMat = new CMaterial(mGame, ePosition | eNormal | eTex0);
// Most values/TEV setup were found from the executable + from graphics debuggers
@ -129,6 +131,49 @@ void CDamageableTriggerExtra::UpdatePlaneTransform()
MarkTransformChanged();
}
CDamageableTriggerExtra::ERenderSide CDamageableTriggerExtra::RenderSideForDirection(const CVector3f& rkDir)
{
// Get the index of the largest XYZ component
CVector3f AbsDir(Math::Abs(rkDir.X), Math::Abs(rkDir.Y), Math::Abs(rkDir.Z));
u32 Max = (AbsDir.X > AbsDir.Y ? 0 : 1);
Max = (AbsDir[Max] > AbsDir.Z ? Max : 2);
// Check whether the direction is positive or negative. If the absolute value of the component matches the input one, then it's positive.
bool Positive = (rkDir[Max] == AbsDir[Max]);
// Return corresponding side for direction
if (Max == 0) return (Positive ? eEast : eWest);
else if (Max == 1) return (Positive ? eNorth : eSouth);
else if (Max == 2) return (Positive ? eUp : eDown);
return eNoRender;
}
CDamageableTriggerExtra::ERenderSide CDamageableTriggerExtra::TransformRenderSide(ERenderSide Side)
{
// DamageableTrigger has a convenience feature implemented that changes the
// render side when the area's been rotated, so we need to replicate it here.
CQuaternion AreaRotation = mpScriptNode->Instance()->Area()->Transform().ExtractRotation();
switch (Side)
{
case eNorth:
return RenderSideForDirection(AreaRotation.YAxis());
case eSouth:
return RenderSideForDirection(-AreaRotation.YAxis());
case eWest:
return RenderSideForDirection(-AreaRotation.XAxis());
case eEast:
return RenderSideForDirection(AreaRotation.XAxis());
case eUp:
return RenderSideForDirection(AreaRotation.ZAxis());
case eDown:
return RenderSideForDirection(-AreaRotation.ZAxis());
default:
return eNoRender;
}
}
void CDamageableTriggerExtra::OnTransformed()
{
mPlaneSize = mpSizeProp->Get();
@ -139,7 +184,7 @@ void CDamageableTriggerExtra::PropertyModified(IProperty *pProperty)
{
if (pProperty == mpRenderSideProp)
{
mRenderSide = (ERenderSide) mpRenderSideProp->Get();
mRenderSide = TransformRenderSide( (ERenderSide) mpRenderSideProp->Get() );
UpdatePlaneTransform();
}

View File

@ -35,6 +35,8 @@ public:
~CDamageableTriggerExtra();
void CreateMaterial();
void UpdatePlaneTransform();
ERenderSide RenderSideForDirection(const CVector3f& rkDir);
ERenderSide TransformRenderSide(ERenderSide Side);
void OnTransformed();
void PropertyModified(IProperty *pProperty);
bool ShouldDrawNormalAssets();

View File

@ -185,12 +185,6 @@ CVector4f CMatrix4f::operator*(const CVector4f& rkVec) const
return out;
}
CQuaternion CMatrix4f::operator*(const CQuaternion& rkQuat) const
{
// todo: there's probably a faster way to do this. (mirrored in CTransform4f and CQuaternion)
return CQuaternion::FromRotationMatrix(Inverse().Transpose()) * rkQuat;
}
CMatrix4f CMatrix4f::operator*(const CTransform4f& rkMtx) const
{
// CTransform4f is a 3x4 matrix with an implicit fourth row of {0, 0, 0, 1}

View File

@ -144,13 +144,12 @@ void CQuaternion::operator *= (const CQuaternion& rkOther)
*this = *this * rkOther;
}
CQuaternion CQuaternion::operator*(const CMatrix4f& rkMtx) const
CQuaternion CQuaternion::operator*(const CTransform4f& rkMtx) const
{
// todo: there's probably a faster way to do this. (mirrored in CMatrix4f and CTransform4f)
return *this * CQuaternion::FromRotationMatrix(rkMtx.Inverse().Transpose());
return *this * rkMtx.ExtractRotation();
}
void CQuaternion::operator *= (const CMatrix4f& rkMtx)
void CQuaternion::operator *= (const CTransform4f& rkMtx)
{
*this = *this * rkMtx;
}

View File

@ -25,8 +25,8 @@ public:
CVector3f operator*(const CVector3f& rkVec) const;
CQuaternion operator*(const CQuaternion& rkOther) const;
void operator *= (const CQuaternion& rkOther);
CQuaternion operator*(const CMatrix4f& rkMtx) const;
void operator *= (const CMatrix4f& rkMtx);
CQuaternion operator*(const CTransform4f& rkMtx) const;
void operator *= (const CTransform4f& rkMtx);
// Static
static CQuaternion FromEuler(CVector3f Euler);

View File

@ -186,11 +186,15 @@ CTransform4f CTransform4f::RotationOnly() const
CVector3f CTransform4f::ExtractTranslation() const
{
CVector3f Test = *this * CVector3f::skZero;
Test = Test;
return CVector3f(m[0][3], m[1][3], m[2][3]);
}
CQuaternion CTransform4f::ExtractRotation() const
{
// todo: there's probably a faster way to do this...
return CQuaternion::FromRotationMatrix(Inverse().Transpose());
}
// ************ OPERATORS ************
float* CTransform4f::operator[](long Index)
{
@ -223,8 +227,7 @@ CVector4f CTransform4f::operator*(const CVector4f& rkVec) const
CQuaternion CTransform4f::operator*(const CQuaternion& rkQuat) const
{
// todo: there's probably a faster way to do this. (mirrored in CMatrix4f and CQuaternion)
return CQuaternion::FromRotationMatrix(Inverse().Transpose()) * rkQuat;
return ExtractRotation() * rkQuat;
}
CTransform4f CTransform4f::operator*(const CTransform4f& rkMtx) const

View File

@ -40,6 +40,7 @@ public:
CTransform4f RotationOnly() const;
CVector3f ExtractTranslation() const;
CQuaternion ExtractRotation() const;
// Static
static CTransform4f TranslationMatrix(CVector3f Translation);