Removed OBBs from Actor including the node infos
Signed-off-by: Benjamin Jillich <jillich@amazon.com>
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user