Removed OBBs from Actor including the node infos

Signed-off-by: Benjamin Jillich <jillich@amazon.com>
This commit is contained in:
Benjamin Jillich
2021-08-03 17:04:26 +02:00
parent f9d5a4a93b
commit aab8ab9706
6 changed files with 6 additions and 191 deletions
@@ -272,7 +272,7 @@ namespace EMotionFX
// Post create actor
actor->SetUnitType(MCore::Distance::UNITTYPE_METERS);
actor->SetFileUnitType(MCore::Distance::UNITTYPE_METERS);
actor->PostCreateInit(/*makeGeomLodsCompatibleWithSkeletalLODs=*/false, /*generateOBBs=*/false, /*convertUnitType=*/false);
actor->PostCreateInit(/*makeGeomLodsCompatibleWithSkeletalLODs=*/false, /*convertUnitType=*/false);
// Only enable joints that are used for skinning (and their parents).
// On top of that, enable all joints marked as critical joints.
+1 -114
View File
@@ -42,7 +42,6 @@
#include <MCore/Source/IDGenerator.h>
#include <MCore/Source/Compare.h>
#include <MCore/Source/LogManager.h>
#include <MCore/Source/OBB.h>
#include <Atom/RPI.Reflect/Model/MorphTargetDelta.h>
@@ -50,11 +49,6 @@ namespace EMotionFX
{
AZ_CLASS_ALLOCATOR_IMPL(Actor, ActorAllocator, 0)
Actor::NodeInfo::NodeInfo()
{
mOBB.Init();
}
Actor::LODLevel::LODLevel()
{
}
@@ -188,7 +182,6 @@ namespace EMotionFX
result->mSkeleton = mSkeleton->Clone();
// clone lod data
result->mNodeInfos = mNodeInfos;
const uint32 numNodes = mSkeleton->GetNumNodes();
const size_t numLodLevels = m_meshLodData.m_lodLevels.size();
@@ -998,18 +991,6 @@ namespace EMotionFX
}
}
// update the bounding volumes
void Actor::UpdateNodeBindPoseOBBs(uint32 lodLevel)
{
// for all nodes
const uint32 numNodes = mSkeleton->GetNumNodes();
for (uint32 i = 0; i < numNodes; ++i)
{
CalcOBBFromBindPose(lodLevel, i);
}
}
// remove all node groups
void Actor::RemoveAllNodeGroups()
{
@@ -1353,9 +1334,8 @@ namespace EMotionFX
}
}
// post init
void Actor::PostCreateInit(bool makeGeomLodsCompatibleWithSkeletalLODs, bool generateOBBs, bool convertUnitType)
void Actor::PostCreateInit(bool makeGeomLodsCompatibleWithSkeletalLODs, bool convertUnitType)
{
if (mThreadIndex == MCORE_INVALIDINDEX32)
{
@@ -1388,11 +1368,6 @@ namespace EMotionFX
mSkeleton->GetBindPose()->ForceUpdateFullModelSpacePose();
mSkeleton->GetBindPose()->ZeroMorphWeights();
if (generateOBBs)
{
UpdateNodeBindPoseOBBs(0);
}
if (!GetHasMirrorInfo())
{
AllocateNodeMirrorInfos();
@@ -1883,7 +1858,6 @@ namespace EMotionFX
void Actor::SetNumNodes(uint32 numNodes)
{
mSkeleton->SetNumNodes(numNodes);
mNodeInfos.resize(numNodes);
AZStd::vector<LODLevel>& lodLevels = m_meshLodData.m_lodLevels;
for (LODLevel& lodLevel : lodLevels)
@@ -1901,7 +1875,6 @@ namespace EMotionFX
mSkeleton->GetBindPose()->LinkToActor(this, Pose::FLAG_LOCALTRANSFORMREADY, false);
// initialize the LOD data
mNodeInfos.emplace_back();
AZStd::vector<LODLevel>& lodLevels = m_meshLodData.m_lodLevels;
for (LODLevel& lodLevel : lodLevels)
{
@@ -1932,7 +1905,6 @@ namespace EMotionFX
void Actor::RemoveNode(uint32 nr, bool delMem)
{
mSkeleton->RemoveNode(nr, delMem);
mNodeInfos.erase(mNodeInfos.begin() + nr);
AZStd::vector<LODLevel>& lodLevels = m_meshLodData.m_lodLevels;
for (LODLevel& lodLevel : lodLevels)
@@ -1944,7 +1916,6 @@ namespace EMotionFX
void Actor::DeleteAllNodes()
{
mSkeleton->RemoveAllNodes();
mNodeInfos.clear();
AZStd::vector<LODLevel>& lodLevels = m_meshLodData.m_lodLevels;
for (LODLevel& lodLevel : lodLevels)
@@ -2263,82 +2234,6 @@ namespace EMotionFX
return (stack->CheckIfHasDeformerOfType(SoftSkinDeformer::TYPE_ID) || stack->CheckIfHasDeformerOfType(DualQuatSkinDeformer::TYPE_ID));
}
// calculate the OBB for a given node
void Actor::CalcOBBFromBindPose(uint32 lodLevel, uint32 nodeIndex)
{
AZStd::vector<AZ::Vector3> points;
// if there is a mesh
Mesh* mesh = GetMesh(lodLevel, nodeIndex);
if (mesh)
{
// if the mesh is not skinned
if (mesh->FindSharedVertexAttributeLayer(SkinningInfoVertexAttributeLayer::TYPE_ID) == nullptr)
{
mesh->ExtractOriginalVertexPositions(points);
}
}
else // there is no mesh, so maybe this is a bone
{
const Transform& invBindPoseTransform = GetInverseBindPoseTransform(nodeIndex);
// for all nodes inside the actor where this node belongs to
const uint32 numNodes = mSkeleton->GetNumNodes();
for (uint32 n = 0; n < numNodes; ++n)
{
Mesh* loopMesh = GetMesh(lodLevel, n);
if (loopMesh == nullptr)
{
continue;
}
// get the vertex positions in bind pose
const uint32 numVerts = loopMesh->GetNumVertices();
points.reserve(numVerts * 2);
AZ::Vector3* positions = (AZ::Vector3*)loopMesh->FindOriginalVertexData(Mesh::ATTRIB_POSITIONS);
SkinningInfoVertexAttributeLayer* skinLayer = (SkinningInfoVertexAttributeLayer*)loopMesh->FindSharedVertexAttributeLayer(SkinningInfoVertexAttributeLayer::TYPE_ID);
if (skinLayer)
{
// iterate over all skinning influences and see if this node number is used
// if so, add it to the list of points
const uint32* orgVertices = (uint32*)loopMesh->FindVertexData(Mesh::ATTRIB_ORGVTXNUMBERS);
for (uint32 v = 0; v < numVerts; ++v)
{
// get the original vertex number
const uint32 orgVtx = orgVertices[v];
// for all skinning influences for this vertex
const size_t numInfluences = skinLayer->GetNumInfluences(orgVtx);
for (size_t i = 0; i < numInfluences; ++i)
{
// get the node used by this influence
const uint32 nodeNr = skinLayer->GetInfluence(orgVtx, i)->GetNodeNr();
// if this is the same node as we are updating the bounds for, add the vertex position to the list
if (nodeNr == nodeIndex)
{
const AZ::Vector3 tempPos(positions[v]);
points.emplace_back(invBindPoseTransform.TransformPoint(tempPos));
}
} // for all influences
} // for all vertices
} // if there is skinning info
} // for all nodes
}
// init from the set of points
if (!points.empty())
{
GetNodeOBB(nodeIndex).InitFromPoints(&points[0], static_cast<uint32>(points.size()));
}
else
{
GetNodeOBB(nodeIndex).Init();
}
}
// remove the mesh for a given node in a given LOD
void Actor::RemoveNodeMeshForLOD(uint32 lodLevel, uint32 nodeIndex, bool destroyMesh)
{
@@ -2411,14 +2306,6 @@ namespace EMotionFX
mInvBindPoseTransforms[i] = bindPose->GetModelSpaceTransform(i).Inversed();
}
// update node obbs
for (uint32 i = 0; i < numNodes; ++i)
{
MCore::OBB& box = GetNodeOBB(i);
box.SetExtents(box.GetExtents() * scaleFactor);
box.SetCenter(box.GetCenter() * scaleFactor);
}
// update static aabb
m_staticAabb.SetMin(m_staticAabb.GetMin() * scaleFactor);
m_staticAabb.SetMax(m_staticAabb.GetMax() * scaleFactor);
+1 -73
View File
@@ -24,7 +24,6 @@
#include <MCore/Source/Vector.h>
#include <MCore/Source/Array.h>
#include <MCore/Source/SmallArray.h>
#include <MCore/Source/OBB.h>
#include <MCore/Source/Distance.h>
// include required headers
@@ -564,17 +563,6 @@ namespace EMotionFX
*/
void SetMorphSetup(uint32 lodLevel, MorphSetup* setup);
/**
* Update the oriented bounding volumes (OBB) of all the nodes inside this actor.
* This is a very heavy calculation and must NOT be performed on a per-frame basis but only as pre-process step.
* The OBBs of the nodes are already being calculated at export time, so you shouldn't really need to use this method.
* Only when the bind pose geometry has changed you can update the node OBBs by calling this method.
* For more information about how the bounds are calculated please see the Node::GetOBB() and Node::CalcOBBFromBindPose() methods.
* The calculations performed by this method are automatically spread over multiple threads to improve the performance.
* @param lodLevel The geometry LOD level to use while calculating the object oriented bounds per node.
*/
void UpdateNodeBindPoseOBBs(uint32 lodLevel);
/**
* Get the number of node groups inside this actor object.
* @result The number of node groups.
@@ -758,7 +746,7 @@ namespace EMotionFX
void MakeGeomLODsCompatibleWithSkeletalLODs();
void ReinitializeMeshDeformers();
void PostCreateInit(bool makeGeomLodsCompatibleWithSkeletalLODs = true, bool generateOBBs = true, bool convertUnitType = true);
void PostCreateInit(bool makeGeomLodsCompatibleWithSkeletalLODs = true, bool convertUnitType = true);
void AutoDetectMirrorAxes();
const MCore::Array<NodeMirrorInfo>& GetNodeMirrorInfos() const;
@@ -808,57 +796,6 @@ namespace EMotionFX
bool CheckIfHasMorphDeformer(uint32 lodLevel, uint32 nodeIndex) const;
bool CheckIfHasSkinningDeformer(uint32 lodLevel, uint32 nodeIndex) const;
/**
* Calculate the object oriented box for a given LOD level.
* This will try to fit the tightest bounding box around the mesh of a node.
* If the node has no mesh and acts as bone inside skinning deformations the resulting box will contain
* all the vertices that are influenced by this given node/bone.
* Calculating this box is already done at export time. But you can use this to recalculate it if the mesh data changed.
* This method is relatively slow and not meant for per-frame calculations but only for preprocessing.
* You can use the GetOBB() method to retrieve the calculated box at any time.
* Nodes that do not have a mesh and not act as bone will have invalid OBB bounds, as they have no volume. You can check whether
* this is the case or not by using the MCore::OBB::IsValid() method.
* The box is stored in local space of the node.
* @param lodLevel The geometry LOD level to generate the OBBs from.
* @param nodeIndex The node to calculate the OBB for.
*/
void CalcOBBFromBindPose(uint32 lodLevel, uint32 nodeIndex);
/**
* Get the object oriented bounding box for this node.
* The box is in local space. In order to convert it into world space you have to multiply the corner points of the box
* with the world space matrix of this node.
* Nodes that do not have a mesh and do not act as bone will have invalid bounds. You can use the MCore::OBB::CheckIfIsValid() method to check if
* the bounds are valid bounds or not. If it is not, then it means there was nothing to calculate the box from.
* Object Oriented Boxes for the nodes are calculated at export time by using the Actor::UpdateNodeBindPoseOBBs() and Node::CalcOBBFromBindPose() methods.
* @param nodeIndex The index of the node to get the OBB for.
* @result The object oriented bounding box that has been calculated before already.
*/
MCore::OBB& GetNodeOBB(uint32 nodeIndex) { return mNodeInfos[nodeIndex].mOBB; }
/**
* Get the object oriented bounding box for this node.
* The box is in local space. In order to convert it into world space you have to multiply the corner points of the box
* with the world space matrix of this node.
* Nodes that do not have a mesh and do not act as bone will have invalid bounds. You can use the MCore::OBB::CheckIfIsValid() method to check if
* the bounds are valid bounds or not. If it is not, then it means there was nothing to calculate the box from.
* Object Oriented Boxes for the nodes are calculated at export time by using the Actor::UpdateNodeBindPoseOBBs() and Node::CalcOBBFromBindPose() methods.
* @param nodeIndex The index of the node to get the OBB for.
* @result The object oriented bounding box that has been calculated before already.
*/
const MCore::OBB& GetNodeOBB(uint32 nodeIndex) const { return mNodeInfos[nodeIndex].mOBB; }
/**
* Set the object oriented bounding box for this node.
* The box is in local space. In order to convert it into world space you have to multiply the corner points of the box
* with the world space matrix of this node.
* Nodes that do not have a mesh and do not act as bone will have invalid bounds. You can use the MCore::OBB::CheckIfIsValid() method to check if
* the bounds are valid bounds or not. If it is not, then it means there was nothing to calculate the box from.
* @param nodeIndex The index of the node to set the OBB for.
* @param obb The object oriented bounding box that has been calculated before already.
*/
void SetNodeOBB(uint32 nodeIndex, const MCore::OBB& obb) { mNodeInfos[nodeIndex].mOBB = obb; }
void RemoveNodeMeshForLOD(uint32 lodLevel, uint32 nodeIndex, bool destroyMesh = true);
void SetNumNodes(uint32 numNodes);
@@ -917,14 +854,6 @@ namespace EMotionFX
Node* FindJointByMeshName(const AZStd::string_view meshName) const;
// per node info (shared between lods)
struct EMFX_API NodeInfo
{
MCore::OBB mOBB;
NodeInfo();
};
// data per node, per lod
struct EMFX_API NodeLODInfo
{
@@ -968,7 +897,6 @@ namespace EMotionFX
Skeleton* mSkeleton; /**< The skeleton, containing the nodes and bind pose. */
MCore::Array<Dependency> mDependencies; /**< The dependencies on other actors (shared meshes and transforms). */
AZStd::vector<NodeInfo> mNodeInfos; /**< The per node info, shared between lods. */
AZStd::string mName; /**< The name of the actor. */
AZStd::string mFileName; /**< The filename of the actor. */
MCore::Array<NodeMirrorInfo> mNodeMirrorInfos; /**< The array of node mirror info. */
@@ -45,7 +45,7 @@ namespace EMotionFX
ConstructActor();
ASSERT_TRUE(m_actor) << "Construct actor did not build a valid actor.";
m_actor->ResizeTransformData();
m_actor->PostCreateInit(/*makeGeomLodsCompatibleWithSkeletalLODs=*/ false, /*generateOBBs=*/ false, /*convertUnitType=*/ false);
m_actor->PostCreateInit(/*makeGeomLodsCompatibleWithSkeletalLODs=*/ false, /*convertUnitType=*/ false);
}
{
m_motionSet = aznew MotionSet("testMotionSet");
@@ -84,7 +84,7 @@ namespace EMotionFX
// Without this call, the bind pose does not know about newly added
// morph target (mMorphWeights.GetLength() == 0)
m_actor->ResizeTransformData();
m_actor->PostCreateInit(/*makeGeomLodsCompatibleWithSkeletalLODs=*/false, /*generateOBBs=*/false, /*convertUnitType=*/false);
m_actor->PostCreateInit(/*makeGeomLodsCompatibleWithSkeletalLODs=*/false, /*convertUnitType=*/false);
m_animGraph = AZStd::make_unique<AnimGraph>();
@@ -68,7 +68,7 @@ namespace EMotionFX
// Without this call, the bind pose does not know about newly added morph target (mMorphWeights.GetLength() == 0)
m_actor->ResizeTransformData();
m_actor->PostCreateInit(/*makeGeomLodsCompatibleWithSkeletalLODs=*/false, /*generateOBBs=*/false, /*convertUnitType=*/false);
m_actor->PostCreateInit(/*makeGeomLodsCompatibleWithSkeletalLODs=*/false, /*convertUnitType=*/false);
m_animGraph = AZStd::make_unique<AnimGraph>();