Enhanced functionality of animation clip container creation #432
Binary file not shown.
|
@ -0,0 +1,7 @@
|
|||
Name: MD_HomeownerV2Anims
|
||||
ID: 217758867
|
||||
Type: 12
|
||||
Sub Assets:
|
||||
Name: Full
|
||||
ID: 227644717
|
||||
Type: 13
|
|
@ -3,6 +3,6 @@
|
|||
SubPass: G-Buffer Write
|
||||
Properties:
|
||||
data.color: {x: 1, y: 1, z: 1, w: 1}
|
||||
data.textureIndex: 57342922
|
||||
data.textureIndex: 54758364
|
||||
data.alpha: 0
|
||||
data.beta: {x: 1, y: 1, z: 1}
|
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -1,7 +0,0 @@
|
|||
Name: BoneIKTest4
|
||||
ID: 81814706
|
||||
Type: 4
|
||||
Sub Assets:
|
||||
Name: Cube
|
||||
ID: 137599708
|
||||
Type: 8
|
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -1,7 +0,0 @@
|
|||
Name: MD_RigTest01_SkinningTest
|
||||
ID: 72178939
|
||||
Type: 4
|
||||
Sub Assets:
|
||||
Name: Cube
|
||||
ID: 141097368
|
||||
Type: 8
|
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -1,7 +0,0 @@
|
|||
Name: MD_RigTest02_HierachyTest1
|
||||
ID: 80500944
|
||||
Type: 4
|
||||
Sub Assets:
|
||||
Name: Cube.001
|
||||
ID: 135102560
|
||||
Type: 8
|
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -1,7 +0,0 @@
|
|||
Name: MD_RigTest03_HierachyTest2
|
||||
ID: 72063399
|
||||
Type: 4
|
||||
Sub Assets:
|
||||
Name: Cube.001
|
||||
ID: 140361184
|
||||
Type: 8
|
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -1,7 +0,0 @@
|
|||
Name: MD_RigTest04_BakedIKLegTest
|
||||
ID: 80728853
|
||||
Type: 4
|
||||
Sub Assets:
|
||||
Name: Cube
|
||||
ID: 149723808
|
||||
Type: 8
|
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -1,7 +0,0 @@
|
|||
Name: MD_RigTest05_MeshDeformTest
|
||||
ID: 82124728
|
||||
Type: 4
|
||||
Sub Assets:
|
||||
Name: Sphere
|
||||
ID: 138773466
|
||||
Type: 8
|
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -1,7 +0,0 @@
|
|||
Name: MD_RigTest06_Piston
|
||||
ID: 76715962
|
||||
Type: 4
|
||||
Sub Assets:
|
||||
Name: Cube
|
||||
ID: 134911040
|
||||
Type: 8
|
|
@ -64,20 +64,20 @@
|
|||
Transform Component:
|
||||
Translate: {x: 0.332949668, y: 0, z: 0}
|
||||
Rotate: {x: -0, y: 0, z: -0}
|
||||
Scale: {x: 0.0710000023, y: 0.0710000023, z: 0.0710000023}
|
||||
Scale: {x: 0.173914507, y: 0.173914507, z: 0.173914507}
|
||||
IsActive: true
|
||||
Renderable Component:
|
||||
Mesh: 141097368
|
||||
Material: 128805346
|
||||
Mesh: 148542784
|
||||
Material: 121518381
|
||||
IsActive: true
|
||||
Animator Component:
|
||||
Rig: 72178939
|
||||
Rig: 76586906
|
||||
AnimationController: 0
|
||||
IsActive: true
|
||||
Scripts:
|
||||
- Type: SHADE.Test.AnimTest
|
||||
Enabled: true
|
||||
fullClip: 231416496
|
||||
fullClip: 227644717
|
||||
idleClip: 0
|
||||
runClip: 0
|
||||
pickUpClip: 0
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,3 @@
|
|||
Name: TX_Homeowner02
|
||||
ID: 54758364
|
||||
Type: 3
|
|
@ -71,7 +71,7 @@ namespace SHADE
|
|||
Play();
|
||||
|
||||
// Set to initial pose
|
||||
if (rig && rig->GetRootNode())
|
||||
if (rig && !rig->GetRootNodes().empty())
|
||||
{
|
||||
updateCurrentAnimatorState(currClip, 0.0f);
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ namespace SHADE
|
|||
std::fill(boneMatrices.begin(), boneMatrices.end(), SHMatrix::Identity);
|
||||
|
||||
// Do not do anything if is not playing or there's nothing to animate
|
||||
if (!rig || !rig->GetRootNode())
|
||||
if (!rig || rig->GetRootNodes().empty())
|
||||
return;
|
||||
|
||||
// We want to still display a paused pose, so we only prevent progression
|
||||
|
@ -274,7 +274,7 @@ namespace SHADE
|
|||
void SHAnimatorComponent::updateCurrentAnimatorState(Handle<SHAnimationClip> clip, float playbackTime)
|
||||
{
|
||||
// Nothing to animate
|
||||
if (!clip || !rig || !rig->GetRootNode())
|
||||
if (!clip || !rig || rig->GetRootNodes().empty())
|
||||
return;
|
||||
|
||||
// Check that we have animation data
|
||||
|
@ -286,7 +286,10 @@ namespace SHADE
|
|||
}
|
||||
void SHAnimatorComponent::updatePoseWithClip(Handle<SHAnimationClip> clip, float poseTime)
|
||||
{
|
||||
updatePoseWithClip(poseTime, clip->GetRawAnimation(), rig->GetRootNode(), SHMatrix::Identity);
|
||||
for (auto rootNode : rig->GetRootNodes())
|
||||
{
|
||||
updatePoseWithClip(poseTime, clip->GetRawAnimation(), rootNode, SHMatrix::Identity);
|
||||
}
|
||||
}
|
||||
|
||||
void SHAnimatorComponent::updatePoseWithClip(float poseTime, Handle<SHRawAnimation> rawAnimData, Handle<SHRigNode> node, const SHMatrix& parentMatrix)
|
||||
|
|
|
@ -26,29 +26,31 @@ namespace SHADE
|
|||
SHRig::SHRig(const SHRigAsset& asset, SHResourceLibrary<SHRigNode>& nodeStore)
|
||||
{
|
||||
// Don't bother if empty
|
||||
if (asset.root == nullptr)
|
||||
if (asset.roots.empty() || *asset.roots.begin() == nullptr)
|
||||
{
|
||||
SHLOG_ERROR("[SHRig] Attempted to load an invalid rig with no root.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Do a recursive depth first traversal to populate the rig
|
||||
rootNode = recurseCreateNode(asset, asset.root, nodeStore);
|
||||
for (auto root : asset.roots)
|
||||
{
|
||||
auto rootNode = recurseCreateNode(asset, root, nodeStore);
|
||||
if (rootNode)
|
||||
{
|
||||
globalInverseMatrix = SHMatrix::Inverse(rootNode->TransformMatrix);
|
||||
rootNodes.emplace_back(rootNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SHRig::SHRig(SHRig&& rhs)
|
||||
: rootNode { rhs.rootNode }
|
||||
: rootNodes { std::move(rhs.rootNodes) }
|
||||
, nodeNames { std::move(rhs.nodeNames) }
|
||||
, nodesByName { std::move(rhs.nodesByName) }
|
||||
, nodes { std::move(rhs.nodes) }
|
||||
, nodeIndexMap { std::move(rhs.nodeIndexMap) }
|
||||
, globalInverseMatrix { std::move(rhs.globalInverseMatrix) }
|
||||
{
|
||||
rhs.rootNode = {};
|
||||
rhs.nodes = {};
|
||||
}
|
||||
SHRig::~SHRig()
|
||||
{
|
||||
|
@ -63,17 +65,17 @@ namespace SHADE
|
|||
|
||||
SHRig& SHRig::operator=(SHRig&& rhs)
|
||||
{
|
||||
rootNode = rhs.rootNode;
|
||||
rootNodes = std::move(rhs.rootNodes);
|
||||
nodeNames = std::move(rhs.nodeNames);
|
||||
nodesByName = std::move(rhs.nodesByName);
|
||||
nodes = std::move(rhs.nodes);
|
||||
nodeIndexMap = std::move(rhs.nodeIndexMap);
|
||||
globalInverseMatrix = std::move(rhs.globalInverseMatrix);
|
||||
|
||||
rhs.rootNode = {};
|
||||
rhs.rootNodes = {};
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Usage Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
|
|
@ -104,11 +104,10 @@ namespace SHADE
|
|||
/// </returns>
|
||||
const std::string& GetName(Handle<SHRigNode> node) const noexcept;
|
||||
/// <summary>
|
||||
/// Retrieves the root node of the rig.
|
||||
/// Retrieves a read only reference to the root nodes of this rig.
|
||||
/// </summary>
|
||||
/// <returns>Handle to the root node of the rig.</returns>
|
||||
Handle<SHRigNode> GetRootNode() const noexcept { return rootNode; }
|
||||
const SHMatrix& GetGlobalInverseMatrix() const noexcept { return globalInverseMatrix; }
|
||||
/// <returns>Vector of handles to the root node of the rig.</returns>
|
||||
const std::vector<Handle<SHRigNode>>& GetRootNodes() const noexcept { return rootNodes; }
|
||||
/// <summary>
|
||||
/// Retrieves a node via name.
|
||||
/// </summary>
|
||||
|
@ -132,12 +131,11 @@ namespace SHADE
|
|||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
Handle<SHRigNode> rootNode;
|
||||
std::vector<Handle<SHRigNode>> rootNodes;
|
||||
std::unordered_map<Handle<SHRigNode>, std::string> nodeNames;
|
||||
std::unordered_map<std::string, Handle<SHRigNode>> nodesByName;
|
||||
std::vector<Handle<SHRigNode>> nodes;
|
||||
std::unordered_map<Handle<SHRigNode>, int> nodeIndexMap;
|
||||
SHMatrix globalInverseMatrix;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace SHADE
|
|||
{
|
||||
SHRigAsset::~SHRigAsset()
|
||||
{
|
||||
if (root != nullptr)
|
||||
delete[] root;
|
||||
if(!roots.empty())
|
||||
delete[] *roots.begin();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,6 @@ namespace SHADE
|
|||
~SHRigAsset();
|
||||
SHRigDataHeader header;
|
||||
std::vector<SHRigNodeData> nodeDataCollection{};
|
||||
SHRigNodeAsset* root;
|
||||
std::vector<SHRigNodeAsset*> roots;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -102,14 +102,12 @@ namespace SHADE
|
|||
{
|
||||
ReadRigHeader(file, asset.rig.header);
|
||||
ReadRigData(file, asset.rig.header, asset.rig.nodeDataCollection);
|
||||
ReadRigTree(file, asset.rig.header, asset.rig.root);
|
||||
ReadRigTree(file, asset.rig.header, asset.rig.roots);
|
||||
|
||||
for (auto& mesh : asset.meshes)
|
||||
{
|
||||
mesh->BoneCount = asset.rig.nodeDataCollection.size();
|
||||
}
|
||||
|
||||
//BuildTransformMatrices(asset.rig);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,26 +138,6 @@ namespace SHADE
|
|||
);
|
||||
}
|
||||
|
||||
void SHModelLoader::BuildTransformMatrices(SHRigAsset& rig)
|
||||
{
|
||||
std::queue<SHRigNodeAsset const*> nodeQueue;
|
||||
nodeQueue.push(rig.root);
|
||||
|
||||
while(!nodeQueue.empty())
|
||||
{
|
||||
auto& current = nodeQueue.front();
|
||||
nodeQueue.pop();
|
||||
auto& parentData {rig.nodeDataCollection[current->idRef]};
|
||||
|
||||
for (auto const& child: current->children)
|
||||
{
|
||||
nodeQueue.push(child);
|
||||
auto& childData {rig.nodeDataCollection[child->idRef]};
|
||||
childData.transform = childData.transform * parentData.transform;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SHModelLoader::ReadRigHeader(FileReference file, SHRigDataHeader& header)
|
||||
{
|
||||
file.read(
|
||||
|
@ -254,7 +232,7 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
void SHModelLoader::ReadRigTree(FileReference file, SHRigDataHeader const& header, SHRigNodeAsset*& root)
|
||||
void SHModelLoader::ReadRigTree(FileReference file, SHRigDataHeader const& header, std::vector<SHRigNodeAsset*>& roots)
|
||||
{
|
||||
// Read All nodes into one contiguous data block
|
||||
struct NodeTemp
|
||||
|
@ -271,7 +249,7 @@ namespace SHADE
|
|||
|
||||
// Build and populate tree
|
||||
SHRigNodeAsset* nodePool = new SHRigNodeAsset[header.nodeCount];
|
||||
root = nodePool;
|
||||
roots.push_back(nodePool);
|
||||
|
||||
std::queue<std::pair<SHRigNodeAsset*, NodeTemp*>> nodeQueue;
|
||||
nodeQueue.emplace(std::make_pair(nodePool, dst));
|
||||
|
@ -279,6 +257,8 @@ namespace SHADE
|
|||
SHRigNodeAsset* depthPtr = nodePool + 1;
|
||||
NodeTemp* depthTempPtr = dst + 1;
|
||||
|
||||
uint32_t nodeCount{ 0 };
|
||||
|
||||
while(!nodeQueue.empty())
|
||||
{
|
||||
auto currPair = nodeQueue.front();
|
||||
|
@ -288,12 +268,26 @@ namespace SHADE
|
|||
|
||||
currNode->idRef = currTemp->id;
|
||||
|
||||
nodeCount++;
|
||||
|
||||
if (
|
||||
nodeQueue.empty() &&
|
||||
currTemp->numChild == 0 &&
|
||||
nodeCount < header.nodeCount
|
||||
)
|
||||
{
|
||||
roots.push_back(depthPtr);
|
||||
nodeQueue.emplace(depthPtr++, depthTempPtr++);
|
||||
}
|
||||
|
||||
for (auto i{0}; i < currTemp->numChild; ++i)
|
||||
{
|
||||
currNode->children.push_back(depthPtr);
|
||||
nodeQueue.emplace(depthPtr++, depthTempPtr++);
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "hi";
|
||||
}
|
||||
|
||||
void SHModelLoader::ReadMeshData(FileReference file, std::vector<SHMeshDataHeader> const& headers,
|
||||
|
|
|
@ -23,14 +23,12 @@ namespace SHADE
|
|||
|
||||
void ReadRigHeader(FileReference file, SHRigDataHeader& header);
|
||||
void ReadRigData(FileReference file, SHRigDataHeader const& header, std::vector<SHRigNodeData>& data);
|
||||
void ReadRigTree(FileReference file, SHRigDataHeader const& header, SHRigNodeAsset*& root);
|
||||
void ReadRigTree(FileReference file, SHRigDataHeader const& header, std::vector<SHRigNodeAsset*>& roots);
|
||||
|
||||
void ReadMeshData(FileReference file, std::vector<SHMeshDataHeader> const& headers, std::vector<SHMeshAsset*>& meshes);
|
||||
void ReadAnimData(FileReference file, std::vector<SHAnimDataHeader> const& headers, std::vector<SHAnimAsset*>& anims);
|
||||
void ReadAnimNode(FileReference file, uint32_t frameCount, SHAnimNode& data);
|
||||
|
||||
void BuildTransformMatrices(SHRigAsset& rig);
|
||||
|
||||
void ReadHeaders(FileReference file, SHModelAsset& asset);
|
||||
void ReadData(FileReference file, SHModelAsset& asset);
|
||||
public:
|
||||
|
|
|
@ -494,6 +494,13 @@ namespace SHADE
|
|||
|
||||
{
|
||||
auto const models {SHAssetManager::GetAllRecordOfType(AssetType::MODEL)};
|
||||
std::vector<SHAsset> displayModels;
|
||||
for (auto const& model : models)
|
||||
{
|
||||
auto const data = SHAssetManager::GetConstData<SHModelAsset>(model.id);
|
||||
if (!data->animHeaders.empty())
|
||||
displayModels.push_back(model);
|
||||
}
|
||||
|
||||
ImGui::RadioButton("Animation Clip Container", true);
|
||||
ImGui::SameLine();
|
||||
|
@ -502,7 +509,7 @@ namespace SHADE
|
|||
AssetID selected {0};
|
||||
if (ImGui::BeginCombo("##combo", currentItem, ImGuiComboFlags_None))
|
||||
{
|
||||
for (auto const& model : models)
|
||||
for (auto const& model : displayModels)
|
||||
{
|
||||
bool isSelected = currentItem == model.name;
|
||||
if (ImGui::Selectable(model.name.data(), isSelected))
|
||||
|
|
Loading…
Reference in New Issue