Saving node chunk v2 and adapting the chunk processor and importer to it

Signed-off-by: Benjamin Jillich <jillich@amazon.com>
This commit is contained in:
Benjamin Jillich
2021-08-04 11:48:16 +02:00
parent 8190d61e18
commit 1b002dcc82
5 changed files with 18 additions and 99 deletions
@@ -18,21 +18,6 @@
namespace ExporterLib
{
void WriteObbToNodeChunk(EMotionFX::FileFormat::Actor_Node& nodeChunk, const MCore::OBB& obb)
{
AZ::Transform obbMatrix = obb.GetTransformation();
obbMatrix.GetBasisX().StoreToFloat3(nodeChunk.mOBB);
nodeChunk.mOBB[3] = 0.0f;
obbMatrix.GetBasisY().StoreToFloat3(nodeChunk.mOBB + 4);
nodeChunk.mOBB[7] = 0.0f;
obbMatrix.GetBasisZ().StoreToFloat3(nodeChunk.mOBB + 8);
nodeChunk.mOBB[11] = 0.0f;
nodeChunk.mOBB[12] = 0.0f;
nodeChunk.mOBB[13] = 0.0f;
nodeChunk.mOBB[14] = 0.0f;
nodeChunk.mOBB[15] = 1.0f;
}
void SaveNode(MCore::Stream* file, EMotionFX::Actor* actor, EMotionFX::Node* node, MCore::Endian::EEndianType targetEndianType)
{
MCORE_ASSERT(file);
@@ -47,7 +32,7 @@ namespace ExporterLib
const uint32 numChilds = node->GetNumChildNodes();
const EMotionFX::Transform& transform = actor->GetBindPose()->GetLocalSpaceTransform(nodeIndex);
AZ::PackedVector3f position = AZ::PackedVector3f(transform.mPosition);
AZ::Quaternion rotation = transform.mRotation.GetNormalized();;
AZ::Quaternion rotation = transform.mRotation.GetNormalized();
#ifndef EMFX_SCALE_DISABLED
AZ::PackedVector3f scale = AZ::PackedVector3f(transform.mScale);
@@ -56,14 +41,13 @@ namespace ExporterLib
#endif
// create the node chunk and copy over the information
EMotionFX::FileFormat::Actor_Node nodeChunk;
memset(&nodeChunk, 0, sizeof(EMotionFX::FileFormat::Actor_Node));
EMotionFX::FileFormat::Actor_Node2 nodeChunk;
memset(&nodeChunk, 0, sizeof(EMotionFX::FileFormat::Actor_Node2));
CopyVector(nodeChunk.mLocalPos, position);
CopyQuaternion(nodeChunk.mLocalQuat, rotation);
CopyVector(nodeChunk.mLocalScale, scale);
//nodeChunk.mImportanceFactor = FLT_MAX;//importance;
nodeChunk.mNumChilds = numChilds;
nodeChunk.mParentIndex = parentIndex;
@@ -98,10 +82,6 @@ namespace ExporterLib
nodeChunk.mNodeFlags &= ~EMotionFX::Node::ENodeFlags::FLAG_CRITICAL;
}
// OBB
WriteObbToNodeChunk(nodeChunk, actor->GetNodeOBB(node->GetNodeIndex()));
// log the node chunk information
MCore::LogDetailedInfo("- Node: name='%s' index=%i", actor->GetSkeleton()->GetNode(nodeIndex)->GetName(), nodeIndex);
if (parentIndex == MCORE_INVALIDINDEX32)
@@ -140,19 +120,13 @@ namespace ExporterLib
ConvertUnsignedInt(&nodeChunk.mNumChilds, targetEndianType);
ConvertUnsignedInt(&nodeChunk.mSkeletalLODs, targetEndianType);
for (uint32 j = 0; j < 16; ++j)
{
ConvertFloat(&nodeChunk.mOBB[j], targetEndianType);
}
// write it
file->Write(&nodeChunk, sizeof(EMotionFX::FileFormat::Actor_Node));
file->Write(&nodeChunk, sizeof(EMotionFX::FileFormat::Actor_Node2));
// write the name of the node and parent
SaveString(node->GetName(), file, targetEndianType);
}
void SaveNodes(MCore::Stream* file, EMotionFX::Actor* actor, MCore::Endian::EEndianType targetEndianType)
{
uint32 i;
@@ -167,10 +141,10 @@ namespace ExporterLib
// chunk information
EMotionFX::FileFormat::FileChunk chunkHeader;
chunkHeader.mChunkID = EMotionFX::FileFormat::ACTOR_CHUNK_NODES;
chunkHeader.mVersion = 1;
chunkHeader.mVersion = 2;
// get the nodes chunk size
chunkHeader.mSizeInBytes = sizeof(EMotionFX::FileFormat::Actor_Nodes) + numNodes * sizeof(EMotionFX::FileFormat::Actor_Node);
chunkHeader.mSizeInBytes = sizeof(EMotionFX::FileFormat::Actor_Nodes2) + numNodes * sizeof(EMotionFX::FileFormat::Actor_Node2);
for (i = 0; i < numNodes; i++)
{
chunkHeader.mSizeInBytes += GetStringChunkSize(actor->GetSkeleton()->GetNode(i)->GetName());
@@ -181,23 +155,15 @@ namespace ExporterLib
file->Write(&chunkHeader, sizeof(EMotionFX::FileFormat::FileChunk));
// nodes chunk
EMotionFX::FileFormat::Actor_Nodes nodesChunk;
EMotionFX::FileFormat::Actor_Nodes2 nodesChunk;
nodesChunk.mNumNodes = numNodes;
nodesChunk.mNumRootNodes = actor->GetSkeleton()->GetNumRootNodes();
nodesChunk.mStaticBoxMin.mX = actor->GetStaticAabb().GetMin().GetX();
nodesChunk.mStaticBoxMin.mY = actor->GetStaticAabb().GetMin().GetY();
nodesChunk.mStaticBoxMin.mZ = actor->GetStaticAabb().GetMin().GetZ();
nodesChunk.mStaticBoxMax.mX = actor->GetStaticAabb().GetMax().GetX();
nodesChunk.mStaticBoxMax.mY = actor->GetStaticAabb().GetMax().GetY();
nodesChunk.mStaticBoxMax.mZ = actor->GetStaticAabb().GetMax().GetZ();
// endian conversion and write it
ConvertUnsignedInt(&nodesChunk.mNumNodes, targetEndianType);
ConvertUnsignedInt(&nodesChunk.mNumRootNodes, targetEndianType);
ConvertFileVector3(&nodesChunk.mStaticBoxMin, targetEndianType);
ConvertFileVector3(&nodesChunk.mStaticBoxMax, targetEndianType);
file->Write(&nodesChunk, sizeof(EMotionFX::FileFormat::Actor_Nodes));
file->Write(&nodesChunk, sizeof(EMotionFX::FileFormat::Actor_Nodes2));
// write the nodes
for (uint32 n = 0; n < numNodes; n++)
@@ -108,7 +108,7 @@ namespace EMotionFX
// a node header
// (not aligned)
struct Actor_Node
struct Actor_Node2
{
FileQuaternion mLocalQuat; // the local rotation (before hierarchy)
FileVector3 mLocalPos; // the local translation (before hierarchy)
@@ -117,7 +117,6 @@ namespace EMotionFX
uint32 mParentIndex;// parent node number, or 0xFFFFFFFF in case of a root node
uint32 mNumChilds; // the number of child nodes
uint8 mNodeFlags; // #1 bit boolean specifies whether we have to include this node in the bounds calculation or not
float mOBB[16];
// followed by:
// string : node name (the unique name of the node)
@@ -200,14 +199,11 @@ namespace EMotionFX
// uint16 [mNumNodes]
};
// (aligned)
struct Actor_Nodes
struct Actor_Nodes2
{
uint32 mNumNodes;
uint32 mNumRootNodes;
FileVector3 mStaticBoxMin;
FileVector3 mStaticBoxMax;
// followed by Actor_Node4[mNumNodes] or Actor_NODE5[mNumNodes] (for v2)
};
@@ -355,12 +355,9 @@ namespace EMotionFX
return mLoggingActive;
}
//=================================================================================================
// a chunk that contains all nodes in one chunk
bool ChunkProcessorActorNodes::Process(MCore::File* file, Importer::ImportParameters& importParams)
bool ChunkProcessorActorNodes2::Process(MCore::File* file, Importer::ImportParameters& importParams)
{
const MCore::Endian::EEndianType endianType = importParams.mEndianType;
Actor* actor = importParams.mActor;
@@ -369,28 +366,12 @@ namespace EMotionFX
MCORE_ASSERT(actor);
Skeleton* skeleton = actor->GetSkeleton();
FileFormat::Actor_Nodes nodesHeader;
file->Read(&nodesHeader, sizeof(FileFormat::Actor_Nodes));
FileFormat::Actor_Nodes2 nodesHeader;
file->Read(&nodesHeader, sizeof(FileFormat::Actor_Nodes2));
// convert endian
MCore::Endian::ConvertUnsignedInt32(&nodesHeader.mNumNodes, endianType);
MCore::Endian::ConvertUnsignedInt32(&nodesHeader.mNumRootNodes, endianType);
MCore::Endian::ConvertFloat(&nodesHeader.mStaticBoxMin.mX, endianType);
MCore::Endian::ConvertFloat(&nodesHeader.mStaticBoxMin.mY, endianType);
MCore::Endian::ConvertFloat(&nodesHeader.mStaticBoxMin.mZ, endianType);
MCore::Endian::ConvertFloat(&nodesHeader.mStaticBoxMax.mX, endianType);
MCore::Endian::ConvertFloat(&nodesHeader.mStaticBoxMax.mY, endianType);
MCore::Endian::ConvertFloat(&nodesHeader.mStaticBoxMax.mZ, endianType);
// convert endian and coord system of the static box
AZ::Vector3 boxMin(nodesHeader.mStaticBoxMin.mX, nodesHeader.mStaticBoxMin.mY, nodesHeader.mStaticBoxMin.mZ);
AZ::Vector3 boxMax(nodesHeader.mStaticBoxMax.mX, nodesHeader.mStaticBoxMax.mY, nodesHeader.mStaticBoxMax.mZ);
// build the box and set it
MCore::AABB staticBox;
staticBox.SetMin(boxMin);
staticBox.SetMax(boxMax);
actor->SetStaticAABB(staticBox);
// pre-allocate space for the nodes
actor->SetNumNodes(nodesHeader.mNumNodes);
@@ -410,8 +391,8 @@ namespace EMotionFX
for (uint32 n = 0; n < nodesHeader.mNumNodes; ++n)
{
// read the node header
FileFormat::Actor_Node nodeChunk;
file->Read(&nodeChunk, sizeof(FileFormat::Actor_Node));
FileFormat::Actor_Node2 nodeChunk;
file->Read(&nodeChunk, sizeof(FileFormat::Actor_Node2));
// read the node name
const char* nodeName = SharedHelperData::ReadString(file, importParams.mSharedData, endianType);
@@ -420,7 +401,6 @@ namespace EMotionFX
MCore::Endian::ConvertUnsignedInt32(&nodeChunk.mParentIndex, endianType);
MCore::Endian::ConvertUnsignedInt32(&nodeChunk.mSkeletalLODs, endianType);
MCore::Endian::ConvertUnsignedInt32(&nodeChunk.mNumChilds, endianType);
MCore::Endian::ConvertFloat(&nodeChunk.mOBB[0], endianType, 16);
// show the name of the node, the parent and the number of children
if (GetLogging())
@@ -453,11 +433,6 @@ namespace EMotionFX
ConvertScale(&scale, endianType);
ConvertQuaternion(&rot, endianType);
// make sure the input data is normalized
// TODO: this isn't really needed as we already normalized?
//rot.FastNormalize();
//scaleRot.FastNormalize();
// set the local transform
Transform bindTransform;
bindTransform.mPosition = pos;
@@ -503,23 +478,6 @@ namespace EMotionFX
skeleton->AddRootNode(nodeIndex);
}
// OBB
AZ::Matrix4x4 obbMatrix4x4 = AZ::Matrix4x4::CreateFromRowMajorFloat16(nodeChunk.mOBB);
const AZ::Vector3 obbCenter = obbMatrix4x4.GetTranslation();
const AZ::Vector3 obbExtents = obbMatrix4x4.GetRowAsVector3(3);
// initialize the OBB
MCore::OBB obb;
obb.SetCenter(obbCenter);
obb.SetExtents(obbExtents);
// need to transpose to go from row major to column major
const AZ::Matrix3x3 obbMatrix3x3 = AZ::Matrix3x3::CreateFromMatrix4x4(obbMatrix4x4).GetTranspose();
const AZ::Transform obbTransform = AZ::Transform::CreateFromMatrix3x3AndTranslation(obbMatrix3x3, obbExtents);
obb.SetTransformation(obbTransform);
actor->SetNodeOBB(nodeIndex, obb);
if (GetLogging())
{
MCore::LogDetailedInfo(" - Position: x=%f, y=%f, z=%f",
@@ -256,7 +256,6 @@ namespace EMotionFX
virtual ~ChunkProcessor();
};
//-------------------------------------------------------------------------------------------------
/**
@@ -287,7 +286,7 @@ namespace EMotionFX
EMFX_CHUNKPROCESSOR(ChunkProcessorActorInfo3, FileFormat::ACTOR_CHUNK_INFO, 3)
EMFX_CHUNKPROCESSOR(ChunkProcessorActorProgMorphTarget, FileFormat::ACTOR_CHUNK_STDPROGMORPHTARGET, 1)
EMFX_CHUNKPROCESSOR(ChunkProcessorActorNodeGroups, FileFormat::ACTOR_CHUNK_NODEGROUPS, 1)
EMFX_CHUNKPROCESSOR(ChunkProcessorActorNodes, FileFormat::ACTOR_CHUNK_NODES, 1)
EMFX_CHUNKPROCESSOR(ChunkProcessorActorNodes2, FileFormat::ACTOR_CHUNK_NODES, 2)
EMFX_CHUNKPROCESSOR(ChunkProcessorActorProgMorphTargets, FileFormat::ACTOR_CHUNK_STDPMORPHTARGETS, 1)
EMFX_CHUNKPROCESSOR(ChunkProcessorActorProgMorphTargets2, FileFormat::ACTOR_CHUNK_STDPMORPHTARGETS, 2)
EMFX_CHUNKPROCESSOR(ChunkProcessorActorNodeMotionSources, FileFormat::ACTOR_CHUNK_NODEMOTIONSOURCES, 1)
@@ -352,7 +352,7 @@ namespace EMotionFX
}
// post create init
actor->PostCreateInit(actorSettings.mMakeGeomLODsCompatibleWithSkeletalLODs, false, actorSettings.mUnitTypeConvert);
actor->PostCreateInit(actorSettings.mMakeGeomLODsCompatibleWithSkeletalLODs, actorSettings.mUnitTypeConvert);
}
// close the file and return a pointer to the actor we loaded
@@ -846,7 +846,7 @@ namespace EMotionFX
RegisterChunkProcessor(aznew ChunkProcessorActorInfo3());
RegisterChunkProcessor(aznew ChunkProcessorActorProgMorphTarget());
RegisterChunkProcessor(aznew ChunkProcessorActorNodeGroups());
RegisterChunkProcessor(aznew ChunkProcessorActorNodes());
RegisterChunkProcessor(aznew ChunkProcessorActorNodes2());
RegisterChunkProcessor(aznew ChunkProcessorActorProgMorphTargets());
RegisterChunkProcessor(aznew ChunkProcessorActorProgMorphTargets2());
RegisterChunkProcessor(aznew ChunkProcessorActorNodeMotionSources());