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:
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user