Add bounding volume expansion to the actor instance
Signed-off-by: Benjamin Jillich <jillich@amazon.com>
This commit is contained in:
@@ -67,7 +67,7 @@ namespace EMotionFX
|
||||
mMotionSamplingTimer = 0.0f;
|
||||
|
||||
mTrajectoryDelta.IdentityWithZeroScale();
|
||||
mStaticAABB.Init();
|
||||
m_staticAabb = AZ::Aabb::CreateNull();
|
||||
|
||||
mAnimGraphInstance = nullptr;
|
||||
|
||||
@@ -137,15 +137,15 @@ namespace EMotionFX
|
||||
UpdateDependencies();
|
||||
|
||||
// update the static based AABB dimensions
|
||||
mStaticAABB = mActor->GetStaticAABB();
|
||||
if (mStaticAABB.CheckIfIsValid() == false)
|
||||
m_staticAabb = mActor->GetStaticAabb();
|
||||
if (!m_staticAabb.IsValid())
|
||||
{
|
||||
UpdateMeshDeformers(0.0f, true); // TODO: not really thread safe because of shared meshes, although it probably will output correctly
|
||||
UpdateStaticBasedAABBDimensions();
|
||||
UpdateStaticBasedAabbDimensions();
|
||||
}
|
||||
|
||||
// update the bounds
|
||||
UpdateBounds(0, mBoundsUpdateType, 1);
|
||||
UpdateBounds(/*lodLevel=*/0, mBoundsUpdateType);
|
||||
|
||||
// register it
|
||||
GetActorManager().RegisterActorInstance(this);
|
||||
@@ -254,12 +254,12 @@ namespace EMotionFX
|
||||
UpdateAttachments(); // update the attachment parent matrices
|
||||
|
||||
// update the bounds when needed
|
||||
if (GetBoundsUpdateEnabled() && mBoundsUpdateType != BOUNDS_MESH_BASED)
|
||||
if (GetBoundsUpdateEnabled())
|
||||
{
|
||||
mBoundsUpdatePassedTime += timePassedInSeconds;
|
||||
if (mBoundsUpdatePassedTime >= mBoundsUpdateFrequency)
|
||||
{
|
||||
UpdateBounds(mLODLevel, BOUNDS_NODE_BASED, mBoundsUpdateItemFreq);
|
||||
UpdateBounds(mLODLevel, mBoundsUpdateType, mBoundsUpdateItemFreq);
|
||||
mBoundsUpdatePassedTime = 0.0f;
|
||||
}
|
||||
}
|
||||
@@ -354,7 +354,7 @@ namespace EMotionFX
|
||||
}
|
||||
|
||||
// update the bounds when needed
|
||||
if (GetBoundsUpdateEnabled() && mBoundsUpdateType != BOUNDS_MESH_BASED)
|
||||
if (GetBoundsUpdateEnabled())
|
||||
{
|
||||
mBoundsUpdatePassedTime += timePassedInSeconds;
|
||||
if (mBoundsUpdatePassedTime >= mBoundsUpdateFrequency)
|
||||
@@ -407,18 +407,6 @@ namespace EMotionFX
|
||||
stack->Update(this, node, timePassedInSeconds, processDisabledDeformers);
|
||||
}
|
||||
}
|
||||
|
||||
// Update the bounds when we are set to use mesh based bounds.
|
||||
if (GetBoundsUpdateEnabled() &&
|
||||
GetBoundsUpdateType() == BOUNDS_MESH_BASED)
|
||||
{
|
||||
mBoundsUpdatePassedTime += timePassedInSeconds;
|
||||
if (mBoundsUpdatePassedTime >= mBoundsUpdateFrequency)
|
||||
{
|
||||
UpdateBounds(mLODLevel, mBoundsUpdateType, mBoundsUpdateItemFreq);
|
||||
mBoundsUpdatePassedTime = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update the mesh morph deformers, which updates the vertex positions on the CPU, so performing CPU morphing.
|
||||
@@ -439,18 +427,6 @@ namespace EMotionFX
|
||||
stack->UpdateByModifierType(this, node, timePassedInSeconds, MorphMeshDeformer::TYPE_ID, true, processDisabledDeformers);
|
||||
}
|
||||
}
|
||||
|
||||
// Update the bounds when we are set to use mesh based bounds.
|
||||
if (GetBoundsUpdateEnabled() &&
|
||||
GetBoundsUpdateType() == BOUNDS_MESH_BASED)
|
||||
{
|
||||
mBoundsUpdatePassedTime += timePassedInSeconds;
|
||||
if (mBoundsUpdatePassedTime >= mBoundsUpdateFrequency)
|
||||
{
|
||||
UpdateBounds(mLODLevel, mBoundsUpdateType, mBoundsUpdateItemFreq);
|
||||
mBoundsUpdatePassedTime = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ActorInstance::PostPhysicsUpdate(float timePassedInSeconds)
|
||||
@@ -639,118 +615,40 @@ namespace EMotionFX
|
||||
{
|
||||
// calculate the static based AABB
|
||||
case BOUNDS_STATIC_BASED:
|
||||
CalcStaticBasedAABB(&mAABB);
|
||||
CalcStaticBasedAabb(&m_aabb);
|
||||
break;
|
||||
|
||||
// based on the world space positions of the nodes (least accurate, but fastest)
|
||||
case BOUNDS_NODE_BASED:
|
||||
CalcNodeBasedAABB(&mAABB, itemFrequency);
|
||||
break;
|
||||
|
||||
// based on the world space positions of the vertices of the collision meshes (faster and more accurate than mesh based)
|
||||
case BOUNDS_COLLISIONMESH_BASED:
|
||||
CalcCollisionMeshBasedAABB(geomLODLevel, &mAABB, itemFrequency);
|
||||
CalcNodeBasedAabb(&m_aabb, itemFrequency);
|
||||
break;
|
||||
|
||||
// based on the world space positions of the vertices of the meshes (most accurate)
|
||||
case BOUNDS_MESH_BASED:
|
||||
CalcMeshBasedAABB(geomLODLevel, &mAABB, itemFrequency);
|
||||
break;
|
||||
|
||||
// based on the world space positions of the vertices of the meshes (most accurate)
|
||||
case BOUNDS_NODEOBB_BASED:
|
||||
CalcNodeOBBBasedAABB(&mAABB, itemFrequency);
|
||||
break;
|
||||
|
||||
case BOUNDS_NODEOBBFAST_BASED:
|
||||
CalcNodeOBBBasedAABBFast(&mAABB, itemFrequency);
|
||||
UpdateMeshDeformers(0.0f);
|
||||
CalcMeshBasedAabb(geomLODLevel, &m_aabb, itemFrequency);
|
||||
break;
|
||||
|
||||
// when we're dealing with an unspecified bounding volume update method
|
||||
default:
|
||||
MCore::LogInfo("*** EMotionFX::ActorInstance::UpdateBounds() - Unknown boundsType specified! (%d) ***", (uint32)boundsType);
|
||||
}
|
||||
}
|
||||
|
||||
// calculate the axis aligned bounding box that contains the object oriented boxes of all nodes
|
||||
void ActorInstance::CalcNodeOBBBasedAABBFast(MCore::AABB* outResult, uint32 nodeFrequency)
|
||||
{
|
||||
// init the axis aligned bounding box
|
||||
outResult->Init();
|
||||
|
||||
const Pose* pose = mTransformData->GetCurrentPose();
|
||||
const Skeleton* skeleton = mActor->GetSkeleton();
|
||||
|
||||
// for all nodes, encapsulate the world space positions
|
||||
uint16 nodeNr;
|
||||
const uint32 numNodes = GetNumEnabledNodes();
|
||||
for (uint32 i = 0; i < numNodes; i += nodeFrequency)
|
||||
// Expand the bounding volume by a tolerance area in case set.
|
||||
if (m_boundsExpandBy > 0.0f)
|
||||
{
|
||||
nodeNr = GetEnabledNode(i);
|
||||
Node* node = skeleton->GetNode(nodeNr);
|
||||
if (node->GetIncludeInBoundsCalc())
|
||||
{
|
||||
const MCore::OBB& obb = mActor->GetNodeOBB(nodeNr);
|
||||
if (obb.CheckIfIsValid() == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// calculate the corner points of the node in local space
|
||||
AZ::Vector3 minPoint, maxPoint;
|
||||
obb.CalcMinMaxPoints(&minPoint, &maxPoint);
|
||||
|
||||
// encapsulate the results in the AABB box
|
||||
const Transform worldTransform = pose->GetWorldSpaceTransform(nodeNr);
|
||||
outResult->Encapsulate(worldTransform.TransformPoint(minPoint));
|
||||
outResult->Encapsulate(worldTransform.TransformPoint(maxPoint));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// more accurate node obb based method that uses the 8 corner points of the obb
|
||||
void ActorInstance::CalcNodeOBBBasedAABB(MCore::AABB* outResult, uint32 nodeFrequency)
|
||||
{
|
||||
// init the axis aligned bounding box
|
||||
outResult->Init();
|
||||
|
||||
const Pose* pose = mTransformData->GetCurrentPose();
|
||||
const Skeleton* skeleton = mActor->GetSkeleton();
|
||||
|
||||
// for all nodes, encapsulate the world space positions
|
||||
AZ::Vector3 cornerPoints[8];
|
||||
uint16 nodeNr;
|
||||
const uint32 numNodes = GetNumEnabledNodes();
|
||||
for (uint32 i = 0; i < numNodes; i += nodeFrequency)
|
||||
{
|
||||
nodeNr = GetEnabledNode(i);
|
||||
Node* node = skeleton->GetNode(nodeNr);
|
||||
if (node->GetIncludeInBoundsCalc())
|
||||
{
|
||||
const MCore::OBB& obb = mActor->GetNodeOBB(nodeNr);
|
||||
if (obb.CheckIfIsValid() == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// calculate the 8 corner points
|
||||
obb.CalcCornerPoints(cornerPoints);
|
||||
|
||||
const Transform worldTransform = pose->GetWorldSpaceTransform(nodeNr);
|
||||
|
||||
// encapsulate all OBB world space corner points inside the AABB
|
||||
for (uint32 p = 0; p < 8; ++p)
|
||||
{
|
||||
outResult->Encapsulate(worldTransform.TransformPoint(cornerPoints[p]));
|
||||
}
|
||||
}
|
||||
const AZ::Vector3 center = m_aabb.GetCenter();
|
||||
const AZ::Vector3 halfExtents = m_aabb.GetExtents() * 0.5f;
|
||||
const AZ::Vector3 scaledHalfExtents = halfExtents * (1.0f + m_boundsExpandBy);
|
||||
m_aabb.SetMin(center - scaledHalfExtents);
|
||||
m_aabb.SetMax(center + scaledHalfExtents);
|
||||
}
|
||||
}
|
||||
|
||||
// calculate the axis aligned bounding box based on the world space positions of the nodes
|
||||
void ActorInstance::CalcNodeBasedAABB(MCore::AABB* outResult, uint32 nodeFrequency)
|
||||
void ActorInstance::CalcNodeBasedAabb(AZ::Aabb* outResult, uint32 nodeFrequency)
|
||||
{
|
||||
outResult->Init();
|
||||
*outResult = AZ::Aabb::CreateNull();
|
||||
|
||||
const Pose* pose = mTransformData->GetCurrentPose();
|
||||
const Skeleton* skeleton = mActor->GetSkeleton();
|
||||
@@ -763,16 +661,15 @@ namespace EMotionFX
|
||||
nodeNr = GetEnabledNode(i);
|
||||
if (skeleton->GetNode(nodeNr)->GetIncludeInBoundsCalc())
|
||||
{
|
||||
outResult->Encapsulate(pose->GetWorldSpaceTransform(nodeNr).mPosition);
|
||||
outResult->AddPoint(pose->GetWorldSpaceTransform(nodeNr).mPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// calculate the AABB that contains all world space vertices of all meshes
|
||||
void ActorInstance::CalcMeshBasedAABB(uint32 geomLODLevel, MCore::AABB* outResult, uint32 vertexFrequency)
|
||||
void ActorInstance::CalcMeshBasedAabb(uint32 geomLODLevel, AZ::Aabb* outResult, uint32 vertexFrequency)
|
||||
{
|
||||
// init the axis aligned bounding box
|
||||
outResult->Init();
|
||||
*outResult = AZ::Aabb::CreateNull();
|
||||
|
||||
const Pose* pose = mTransformData->GetCurrentPose();
|
||||
const Skeleton* skeleton = mActor->GetSkeleton();
|
||||
@@ -800,52 +697,9 @@ namespace EMotionFX
|
||||
const Transform worldTransform = pose->GetMeshNodeWorldSpaceTransform(geomLODLevel, nodeNr);
|
||||
|
||||
// calculate and encapsulate the mesh bounds inside the total mesh box
|
||||
MCore::AABB meshBox;
|
||||
mesh->CalcAABB(&meshBox, worldTransform, vertexFrequency);
|
||||
outResult->Encapsulate(meshBox);
|
||||
}
|
||||
}
|
||||
|
||||
void ActorInstance::CalcCollisionMeshBasedAABB(uint32 geomLODLevel, MCore::AABB* outResult, uint32 vertexFrequency)
|
||||
{
|
||||
// init the axis aligned bounding box
|
||||
outResult->Init();
|
||||
|
||||
const Pose* pose = mTransformData->GetCurrentPose();
|
||||
const Skeleton* skeleton = mActor->GetSkeleton();
|
||||
|
||||
// for all nodes, encapsulate the world space positions
|
||||
uint16 nodeNr;
|
||||
const uint32 numNodes = GetNumEnabledNodes();
|
||||
for (uint32 i = 0; i < numNodes; ++i)
|
||||
{
|
||||
nodeNr = GetEnabledNode(i);
|
||||
Node* node = skeleton->GetNode(nodeNr);
|
||||
|
||||
// skip nodes without collision meshes
|
||||
Mesh* mesh = mActor->GetMesh(geomLODLevel, nodeNr);
|
||||
if (mesh == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mesh->GetIsCollisionMesh() == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// if this node should be excluded
|
||||
if (node->GetIncludeInBoundsCalc() == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const Transform worldTransform = pose->GetMeshNodeWorldSpaceTransform(geomLODLevel, nodeNr);
|
||||
|
||||
// calculate and encapsulate the mesh bounds inside the total mesh box
|
||||
MCore::AABB meshBox;
|
||||
mesh->CalcAABB(&meshBox, worldTransform, vertexFrequency);
|
||||
outResult->Encapsulate(meshBox);
|
||||
AZ::Aabb meshBox;
|
||||
mesh->CalcAabb(&meshBox, worldTransform, vertexFrequency);
|
||||
outResult->AddAabb(meshBox);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1567,111 +1421,45 @@ namespace EMotionFX
|
||||
}
|
||||
|
||||
// update the static based aabb dimensions
|
||||
void ActorInstance::UpdateStaticBasedAABBDimensions()
|
||||
void ActorInstance::UpdateStaticBasedAabbDimensions()
|
||||
{
|
||||
// backup the transform
|
||||
Transform orgTransform = GetLocalSpaceTransform();
|
||||
//-------------------------------------
|
||||
|
||||
// reset position and scale
|
||||
SetLocalSpacePosition(AZ::Vector3::CreateZero());
|
||||
EMFX_SCALECODE(SetLocalSpaceScale(AZ::Vector3(1.0f, 1.0f, 1.0f));)
|
||||
|
||||
EMFX_SCALECODE(
|
||||
SetLocalSpaceScale(AZ::Vector3(1.0f, 1.0f, 1.0f));)
|
||||
UpdateTransformations(0.0f, true);
|
||||
UpdateMeshDeformers(0.0f);
|
||||
|
||||
// rotate over x, y and z axis
|
||||
AZ::Vector3 boxMin(FLT_MAX, FLT_MAX, FLT_MAX);
|
||||
AZ::Vector3 boxMax(-FLT_MAX, -FLT_MAX, -FLT_MAX);
|
||||
for (uint32 axis = 0; axis < 3; axis++)
|
||||
// calculate the aabb of this
|
||||
if (mActor->CheckIfHasMeshes(0))
|
||||
{
|
||||
for (uint32 i = 0; i < 360; i += 45) // steps of 45 degrees
|
||||
{
|
||||
// rotate a given amount of degrees over the axis we are currently testing
|
||||
AZ::Vector3 axisVector(0.0f, 0.0f, 0.0f);
|
||||
axisVector.SetElement(axis, 1.0f);
|
||||
const float angle = static_cast<float>(i);
|
||||
SetLocalSpaceRotation(MCore::CreateFromAxisAndAngle(axisVector, MCore::Math::DegreesToRadians(angle)));
|
||||
|
||||
UpdateTransformations(0.0f, true);
|
||||
UpdateMeshDeformers(0.0f);
|
||||
|
||||
// calculate the aabb of this
|
||||
if (mActor->CheckIfHasMeshes(0))
|
||||
{
|
||||
CalcMeshBasedAABB(0, &mStaticAABB);
|
||||
}
|
||||
else
|
||||
{
|
||||
CalcNodeBasedAABB(&mStaticAABB);
|
||||
}
|
||||
|
||||
// find the minimum and maximum
|
||||
const AZ::Vector3& curMin = mStaticAABB.GetMin();
|
||||
const AZ::Vector3& curMax = mStaticAABB.GetMax();
|
||||
if (curMin.GetX() < boxMin.GetX())
|
||||
{
|
||||
boxMin.SetX(curMin.GetX());
|
||||
}
|
||||
if (curMin.GetY() < boxMin.GetY())
|
||||
{
|
||||
boxMin.SetY(curMin.GetY());
|
||||
}
|
||||
if (curMin.GetZ() < boxMin.GetZ())
|
||||
{
|
||||
boxMin.SetZ(curMin.GetZ());
|
||||
}
|
||||
if (curMax.GetX() > boxMax.GetX())
|
||||
{
|
||||
boxMax.SetX(curMax.GetX());
|
||||
}
|
||||
if (curMax.GetY() > boxMax.GetY())
|
||||
{
|
||||
boxMax.SetY(curMax.GetY());
|
||||
}
|
||||
if (curMax.GetZ() > boxMax.GetZ())
|
||||
{
|
||||
boxMax.SetZ(curMax.GetZ());
|
||||
}
|
||||
}
|
||||
CalcMeshBasedAabb(0, &m_staticAabb);
|
||||
}
|
||||
else
|
||||
{
|
||||
CalcNodeBasedAabb(&m_staticAabb);
|
||||
}
|
||||
|
||||
mStaticAABB.SetMin(boxMin);
|
||||
mStaticAABB.SetMax(boxMax);
|
||||
|
||||
/*
|
||||
// calculate the center point of the box
|
||||
const AZ::Vector3 center = mStaticAABB.CalcMiddle();
|
||||
|
||||
// find the maximum of the width, height and depth
|
||||
const float maxDim = MCore::Max3<float>( mStaticAABB.CalcWidth(), mStaticAABB.CalcHeight(), mStaticAABB.CalcDepth() ) * 0.5f;
|
||||
|
||||
// make width, height and depth the same as its maximum
|
||||
mStaticAABB.SetMin( center + AZ::Vector3(-maxDim, -maxDim, -maxDim) );
|
||||
mStaticAABB.SetMax( center + AZ::Vector3( maxDim, maxDim, maxDim) );
|
||||
*/
|
||||
//-------------------------------------
|
||||
|
||||
// restore the transform
|
||||
mLocalTransform = orgTransform;
|
||||
}
|
||||
|
||||
// calculate the moved static based aabb
|
||||
void ActorInstance::CalcStaticBasedAABB(MCore::AABB* outResult)
|
||||
void ActorInstance::CalcStaticBasedAabb(AZ::Aabb* outResult)
|
||||
{
|
||||
if (GetIsSkinAttachment())
|
||||
{
|
||||
mSelfAttachment->GetAttachToActorInstance()->CalcStaticBasedAABB(outResult);
|
||||
mSelfAttachment->GetAttachToActorInstance()->CalcStaticBasedAabb(outResult);
|
||||
return;
|
||||
}
|
||||
|
||||
*outResult = mStaticAABB;
|
||||
*outResult = m_staticAabb;
|
||||
EMFX_SCALECODE(
|
||||
outResult->SetMin(mStaticAABB.GetMin() * mWorldTransform.mScale);
|
||||
outResult->SetMax(mStaticAABB.GetMax() * mWorldTransform.mScale);)
|
||||
outResult->SetMin(m_staticAabb.GetMin() * mWorldTransform.mScale);
|
||||
outResult->SetMax(m_staticAabb.GetMax() * mWorldTransform.mScale);)
|
||||
outResult->Translate(mWorldTransform.mPosition);
|
||||
}
|
||||
|
||||
// adjust the animgraph instance
|
||||
// adjust the anim graph instance
|
||||
void ActorInstance::SetAnimGraphInstance(AnimGraphInstance* instance)
|
||||
{
|
||||
mAnimGraphInstance = instance;
|
||||
@@ -1774,29 +1562,29 @@ namespace EMotionFX
|
||||
SetFlag(BOOL_BOUNDSUPDATEENABLED, enable);
|
||||
}
|
||||
|
||||
void ActorInstance::SetStaticBasedAABB(const MCore::AABB& aabb)
|
||||
void ActorInstance::SetStaticBasedAabb(const AZ::Aabb& aabb)
|
||||
{
|
||||
mStaticAABB = aabb;
|
||||
m_staticAabb = aabb;
|
||||
}
|
||||
|
||||
void ActorInstance::GetStaticBasedAABB(MCore::AABB* outAABB)
|
||||
void ActorInstance::GetStaticBasedAabb(AZ::Aabb* outAabb)
|
||||
{
|
||||
*outAABB = mStaticAABB;
|
||||
*outAabb = m_staticAabb;
|
||||
}
|
||||
|
||||
const MCore::AABB& ActorInstance::GetStaticBasedAABB() const
|
||||
const AZ::Aabb& ActorInstance::GetStaticBasedAabb() const
|
||||
{
|
||||
return mStaticAABB;
|
||||
return m_staticAabb;
|
||||
}
|
||||
|
||||
const MCore::AABB& ActorInstance::GetAABB() const
|
||||
const AZ::Aabb& ActorInstance::GetAabb() const
|
||||
{
|
||||
return mAABB;
|
||||
return m_aabb;
|
||||
}
|
||||
|
||||
void ActorInstance::SetAABB(const MCore::AABB& aabb)
|
||||
void ActorInstance::SetAabb(const AZ::Aabb& aabb)
|
||||
{
|
||||
mAABB = aabb;
|
||||
m_aabb = aabb;
|
||||
}
|
||||
|
||||
uint32 ActorInstance::GetNumAttachments() const
|
||||
@@ -2018,23 +1806,20 @@ namespace EMotionFX
|
||||
mVisualizeScale = 0.0f;
|
||||
UpdateMeshDeformers(0.0f);
|
||||
|
||||
MCore::AABB box;
|
||||
CalcCollisionMeshBasedAABB(0, &box);
|
||||
if (box.CheckIfIsValid())
|
||||
AZ::Aabb box = AZ::Aabb::CreateNull();
|
||||
|
||||
CalcNodeBasedAabb(&box);
|
||||
if (box.IsValid())
|
||||
{
|
||||
mVisualizeScale = MCore::Max<float>(mVisualizeScale, box.CalcRadius());
|
||||
const float boxRadius = AZ::Vector3(box.GetMax() - box.GetMin()).GetLength() * 0.5f;
|
||||
mVisualizeScale = MCore::Max<float>(mVisualizeScale, boxRadius);
|
||||
}
|
||||
|
||||
CalcNodeBasedAABB(&box);
|
||||
if (box.CheckIfIsValid())
|
||||
CalcMeshBasedAabb(0, &box);
|
||||
if (box.IsValid())
|
||||
{
|
||||
mVisualizeScale = MCore::Max<float>(mVisualizeScale, box.CalcRadius());
|
||||
}
|
||||
|
||||
CalcMeshBasedAABB(0, &box);
|
||||
if (box.CheckIfIsValid())
|
||||
{
|
||||
mVisualizeScale = MCore::Max<float>(mVisualizeScale, box.CalcRadius());
|
||||
const float boxRadius = AZ::Vector3(box.GetMax() - box.GetMin()).GetLength() * 0.5f;
|
||||
mVisualizeScale = MCore::Max<float>(mVisualizeScale, boxRadius);
|
||||
}
|
||||
|
||||
mVisualizeScale *= 0.01f;
|
||||
|
||||
@@ -60,9 +60,6 @@ namespace EMotionFX
|
||||
{
|
||||
BOUNDS_NODE_BASED = 0, /**< Calculate the bounding volumes based on the world space node positions. */
|
||||
BOUNDS_MESH_BASED = 1, /**< Calculate the bounding volumes based on the world space vertex positions. */
|
||||
BOUNDS_COLLISIONMESH_BASED = 2, /**< Calculate the bounding volumes based on the world space collision mesh vertex positions. */
|
||||
BOUNDS_NODEOBB_BASED = 3, /**< Calculate the bounding volumes based on the oriented bounding boxes of the nodes. Uses all 8 corner points of the individual node OBB boxes. */
|
||||
BOUNDS_NODEOBBFAST_BASED = 4, /**< Calculate the bounding volumes based on the oriented bounding boxes of the nodes. Uses the min and max point of the individual node OBB boxes. This is less accurate but faster. */
|
||||
BOUNDS_STATIC_BASED = 5 /**< Calculate the bounding volumes based on an approximate box, based on the mesh bounds, and move this box along with the actor instance position. */
|
||||
};
|
||||
|
||||
@@ -348,6 +345,14 @@ namespace EMotionFX
|
||||
*/
|
||||
EBoundsType GetBoundsUpdateType() const;
|
||||
|
||||
/**
|
||||
* Get the normalized percentage that the calculated bounding box is expanded with.
|
||||
* This can be used to add a tolerance area to the calculated bounding box to avoid clipping the character too early.
|
||||
* A static bounding box together with the expansion is the recommended way for maximum performance.
|
||||
* @result A value of 1.0 means that the calculated bounding box won't be expanded at all, while 2.0 means it is twice the size.
|
||||
*/
|
||||
float GetExpandBoundsBy() const { return m_boundsExpandBy; }
|
||||
|
||||
/**
|
||||
* Get the bounding volume auto-update item frequency.
|
||||
* A value of 1 would mean every node or vertex will be taken into account in the bounds calculation.
|
||||
@@ -376,11 +381,19 @@ namespace EMotionFX
|
||||
/**
|
||||
* Set the bounding volume auto-update type.
|
||||
* This can be either based on the node's world space positions, the mesh vertex world space positions, or the
|
||||
* collision mesh vertex world space postitions.
|
||||
* collision mesh vertex world space positions.
|
||||
* @param bType The bounding volume update type.
|
||||
*/
|
||||
void SetBoundsUpdateType(EBoundsType bType);
|
||||
|
||||
/**
|
||||
* Set the normalized percentage that the calculated bounding box should be expanded with.
|
||||
* This can be used to add a tolerance area to the calculated bounding box to avoid clipping the character too early.
|
||||
* A static bounding box together with the expansion is the recommended way for maximum performance.
|
||||
* @param[in] expandBy A value of 1.0 means that the calculated bounding box won't be expanded at all, while 2.0 means it will be twice the size.
|
||||
*/
|
||||
void SetExpandBoundsBy(float expandBy) { m_boundsExpandBy = expandBy; }
|
||||
|
||||
/**
|
||||
* Set the bounding volume auto-update item frequency.
|
||||
* A value of 1 would mean every node or vertex will be taken into account in the bounds calculation.
|
||||
@@ -420,11 +433,11 @@ namespace EMotionFX
|
||||
* This function is generally only executed once, when creating the actor instance.
|
||||
* The CalcStaticBasedAABB function then simply translates this box along with the actor instance's position.
|
||||
*/
|
||||
void UpdateStaticBasedAABBDimensions();
|
||||
void UpdateStaticBasedAabbDimensions();
|
||||
|
||||
void SetStaticBasedAABB(const MCore::AABB& aabb);
|
||||
void GetStaticBasedAABB(MCore::AABB* outAABB);
|
||||
const MCore::AABB& GetStaticBasedAABB() const;
|
||||
void SetStaticBasedAabb(const AZ::Aabb& aabb);
|
||||
void GetStaticBasedAabb(AZ::Aabb* outAabb);
|
||||
const AZ::Aabb& GetStaticBasedAabb() const;
|
||||
|
||||
/**
|
||||
* Calculate an axis aligned bounding box that can be used as static AABB. It is static in the way that the volume does not change. It can however be translated as it will move
|
||||
@@ -434,7 +447,7 @@ namespace EMotionFX
|
||||
* If there are no meshes present, a widened node based box will be used instead as basis.
|
||||
* @param outResult The resulting bounding box, moved along with the actor instance's position.
|
||||
*/
|
||||
void CalcStaticBasedAABB(MCore::AABB* outResult);
|
||||
void CalcStaticBasedAabb(AZ::Aabb* outResult);
|
||||
|
||||
/**
|
||||
* Calculate the axis aligned bounding box based on the world space positions of the nodes.
|
||||
@@ -442,7 +455,7 @@ namespace EMotionFX
|
||||
* @param nodeFrequency This will include every "nodeFrequency"-th node. So a value of 1 will include all nodes. A value of 2 would
|
||||
* process every second node, meaning that half of the nodes will be skipped. A value of 4 would process every 4th node, etc.
|
||||
*/
|
||||
void CalcNodeBasedAABB(MCore::AABB* outResult, uint32 nodeFrequency = 1);
|
||||
void CalcNodeBasedAabb(AZ::Aabb* outResult, uint32 nodeFrequency = 1);
|
||||
|
||||
/**
|
||||
* Calculate the axis aligned bounding box based on the world space vertex coordinates of the meshes.
|
||||
@@ -452,43 +465,7 @@ namespace EMotionFX
|
||||
* @param vertexFrequency This includes every "vertexFrequency"-th vertex. So for example a value of 2 would skip every second vertex and
|
||||
* so will process half of the vertices. A value of 4 would process only each 4th vertex, etc.
|
||||
*/
|
||||
void CalcMeshBasedAABB(uint32 geomLODLevel, MCore::AABB* outResult, uint32 vertexFrequency = 1);
|
||||
|
||||
/**
|
||||
* Calculate the axis aligned bounding box based on the world space vertex coordinates of the collision meshes.
|
||||
* If the actor has no collision meshes, the created box will be invalid.
|
||||
* @param geomLODLevel The geometry LOD level to calculate the box for.
|
||||
* @param outResult The AABB where this method should store the resulting box in.
|
||||
* @param vertexFrequency This includes every "vertexFrequency"-th vertex. So for example a value of 2 would skip every second vertex and
|
||||
* so will process half of the vertices. A value of 4 would process only each 4th vertex, etc.
|
||||
*/
|
||||
void CalcCollisionMeshBasedAABB(uint32 geomLODLevel, MCore::AABB* outResult, uint32 vertexFrequency = 1);
|
||||
|
||||
/**
|
||||
* Calculate the axis aligned bounding box that contains the object oriented boxes of all nodes.
|
||||
* The OBB (oriented bounding box) of each node is calculated by fitting an OBB to its mesh.
|
||||
* The OBB of nodes that act as bones and have no meshes themselves are fit to the set of vertices that are influenced by the given bone.
|
||||
* This method will give more accurate results than the CalcNodeBasedAABB method in trade for a bit lower performance.
|
||||
* Also one big advantage of this method is that you can use these bounds for hit detection, without having artists setup collision meshes.
|
||||
* @param outResult The AABB where this method should store the resulting box in.
|
||||
* @param nodeFrequency This will include every "nodeFrequency"-th node. So a value of 1 will include all nodes. A value of 2 would
|
||||
* process every second node, meaning that half of the nodes will be skipped. A value of 4 would process every 4th node, etc.
|
||||
*/
|
||||
void CalcNodeOBBBasedAABB(MCore::AABB* outResult, uint32 nodeFrequency = 1);
|
||||
|
||||
/**
|
||||
* Calculate the axis aligned bounding box that contains the object oriented boxes of all nodes.
|
||||
* The OBB (oriented bounding box) of each node is calculated by fitting an OBB to its mesh.
|
||||
* The OBB of nodes that act as bones and have no meshes themselves are fit to the set of vertices that are influenced by the given bone.
|
||||
* This method will give more accurate results than the CalcNodeBasedAABB method in trade for a bit lower performance.
|
||||
* Also one big advantage of this method is that you can use these bounds for hit detection, without having artists setup collision meshes.
|
||||
* NOTE: this is a faster variant from the CalcNodeOBBBasedAABB method. The difference is that this method only transforms the min and max point of the box in local space.
|
||||
* Therefore it is less accurate, but it might still be enough. The original CalcNodeOBBBasedAABB method calculates the 8 corner points of the node obb boxes.
|
||||
* @param outResult The AABB where this method should store the resulting box in.
|
||||
* @param nodeFrequency This will include every "nodeFrequency"-th node. So a value of 1 will include all nodes. A value of 2 would
|
||||
* process every second node, meaning that half of the nodes will be skipped. A value of 4 would process every 4th node, etc.
|
||||
*/
|
||||
void CalcNodeOBBBasedAABBFast(MCore::AABB* outResult, uint32 nodeFrequency = 1);
|
||||
void CalcMeshBasedAabb(uint32 geomLODLevel, AZ::Aabb* outResult, uint32 vertexFrequency = 1);
|
||||
|
||||
/**
|
||||
* Get the axis aligned bounding box.
|
||||
@@ -496,14 +473,14 @@ namespace EMotionFX
|
||||
* That method is also called automatically when the bounds auto-update feature is enabled.
|
||||
* @result The axis aligned bounding box.
|
||||
*/
|
||||
const MCore::AABB& GetAABB() const;
|
||||
const AZ::Aabb& GetAabb() const;
|
||||
|
||||
/**
|
||||
* Set the axis aligned bounding box.
|
||||
* Please beware that this box will get automatically overwritten when automatic bounds update is enabled.
|
||||
* @param aabb The axis aligned bounding box to store.
|
||||
*/
|
||||
void SetAABB(const MCore::AABB& aabb);
|
||||
void SetAabb(const AZ::Aabb& aabb);
|
||||
|
||||
//-------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -887,8 +864,8 @@ namespace EMotionFX
|
||||
|
||||
private:
|
||||
TransformData* mTransformData; /**< The transformation data for this instance. */
|
||||
MCore::AABB mAABB; /**< The axis aligned bounding box. */
|
||||
MCore::AABB mStaticAABB; /**< A static pre-calculated bounding box, which we can move along with the position of the actor instance, and use for visibility checks. */
|
||||
AZ::Aabb m_aabb; /**< The axis aligned bounding box. */
|
||||
AZ::Aabb m_staticAabb; /**< A static pre-calculated bounding box, which we can move along with the position of the actor instance, and use for visibility checks. */
|
||||
|
||||
Transform mLocalTransform = Transform::CreateIdentity();
|
||||
Transform mWorldTransform = Transform::CreateIdentity();
|
||||
@@ -907,7 +884,7 @@ namespace EMotionFX
|
||||
MotionSystem* mMotionSystem; /**< The motion system, that handles all motion playback and blending etc. */
|
||||
AnimGraphInstance* mAnimGraphInstance; /**< A pointer to the anim graph instance, which can be nullptr when there is no anim graph instance. */
|
||||
AZStd::unique_ptr<RagdollInstance> m_ragdollInstance;
|
||||
MCore::Mutex mLock; /**< The multithread lock. */
|
||||
MCore::Mutex mLock; /**< The multi-thread lock. */
|
||||
void* mCustomData; /**< A pointer to custom data for this actor. This could be a pointer to your engine or game object for example. */
|
||||
AZ::Entity* m_entity; /**< The entity to which the actor instance belongs to. */
|
||||
float mBoundsUpdateFrequency; /**< The bounds update frequency. Which is a time value in seconds. */
|
||||
@@ -920,7 +897,8 @@ namespace EMotionFX
|
||||
uint32 mBoundsUpdateItemFreq; /**< The bounds update item counter step size. A value of 1 means every vertex/node, a value of 2 means every second vertex/node, etc. */
|
||||
uint32 mID; /**< The unique identification number for the actor instance. */
|
||||
uint32 mThreadIndex; /**< The thread index. This specifies the thread number this actor instance is being processed in. */
|
||||
EBoundsType mBoundsUpdateType; /**< The bounds update type (node based, mesh based or colliison mesh based). */
|
||||
EBoundsType mBoundsUpdateType; /**< The bounds update type (node based, mesh based or collision mesh based). */
|
||||
float m_boundsExpandBy = 0.25f; /**< Expand bounding box by normalized percentage. (Default: 25% greater than the calculated bounding box) */
|
||||
uint8 mNumAttachmentRefs; /**< Specifies how many actor instances use this actor instance as attachment. */
|
||||
uint8 mBoolFlags; /**< Boolean flags. */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user