resources.LoadResources(ctx.pathProvider);
if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
{
- scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor);
scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
ConfigureBlendShapeShaders(resources, scene, actor, std::move(nodeParams.mBlendshapeRequests));
scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
resources.LoadResources(ctx.pathProvider);
if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
{
- scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor);
scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
ConfigureBlendShapeShaders(resources, scene, actor, std::move(nodeParams.mBlendshapeRequests));
scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
resources.LoadResources(ctx.pathProvider);
if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
{
- scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor);
scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
ConfigureBlendShapeShaders(resources, scene, actor, std::move(nodeParams.mBlendshapeRequests));
scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
resources.LoadResources(ctx.pathProvider);
if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
{
- scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor);
scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
ConfigureBlendShapeShaders(resources, scene, actor, std::move(nodeParams.mBlendshapeRequests));
scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
ctx.resources.LoadResources(ctx.pathProvider);
if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
{
- scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor);
scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
root.Add(actor);
resources.LoadResources(ctx.pathProvider);
if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
{
- scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor);
scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
root.Add(actor);
resources.LoadResources(ctx.pathProvider);
if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
{
- scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor);
scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
root.Add(actor);
resources.LoadResources(ctx.pathProvider);
if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
{
- scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor);
scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
root.Add(actor);
ModelNode mRoot;
};
-bool IsAncestor(const SceneDefinition& scene, Index ancestor, Index node, Index rootHint = INVALID_INDEX)
-{
- bool isAncestor = false;
- while(node != rootHint && !isAncestor)
- {
- node = scene.GetNode(node)->mParentIdx;
- isAncestor = ancestor == node;
- }
- return isAncestor;
-}
-
-void InsertUniqueSorted(std::vector<Index>& data, Index value)
-{
- auto iInsert = std::lower_bound(data.begin(), data.end(), value);
- if(iInsert == data.end() || *iInsert != value)
- {
- data.insert(iInsert, value);
- }
-}
-
-void RemoveFromSorted(std::vector<Index>& data, Index value)
-{
- auto iRemove = std::lower_bound(data.begin(), data.end(), value);
- if(iRemove != data.end() && *iRemove == value)
- {
- data.erase(iRemove);
- }
-}
-
-Property::Index ConfigureJointMatrix(Actor actor, Actor ancestor, Property::Index propJointMatrix)
-{
- Actor parent = actor.GetParent();
- if(parent != ancestor)
- {
- propJointMatrix = ConfigureJointMatrix(parent, ancestor, propJointMatrix);
- }
-
- auto myPropJointMatrix = actor.GetPropertyIndex(Skinning::JOINT_MATRIX);
- if(myPropJointMatrix == Property::INVALID_INDEX)
- {
- myPropJointMatrix = actor.RegisterProperty(Skinning::JOINT_MATRIX, Matrix{false});
- Constraint constraint = Constraint::New<Matrix>(actor, propJointMatrix, [](Matrix& output, const PropertyInputContainer& inputs) {
- Matrix jointMatrix{false};
- jointMatrix.SetTransformComponents(Vector3::ONE, inputs[0]->GetQuaternion(), inputs[1]->GetVector3());
-
- Matrix::Multiply(output, jointMatrix, inputs[2]->GetMatrix());
- });
- constraint.AddSource(Source{actor, Actor::Property::ORIENTATION});
- constraint.AddSource(Source{actor, Actor::Property::POSITION});
- constraint.AddSource(Source{parent, propJointMatrix});
- constraint.Apply();
- }
-
- return myPropJointMatrix;
-}
-
void SortAndDeduplicateSkinningRequests(std::vector<SkinningShaderConfigurationRequest>& requests)
{
// Sort requests by shaders.
}
}
-void SceneDefinition::ConfigureSkeletonJoints(uint32_t iRoot, const SkeletonDefinition::Vector& skeletons, Actor root) const
-{
- // 1, For each skeleton, for each joint, walk upwards until we reach mNodes[iRoot]. If we do, record +1
- // to the refcount of each node we have visited, in our temporary registry. Those with refcount 1
- // are the leaves, while the most descendant node with the highest refcount is the root of the skeleton.
- std::map<Index, std::vector<Index>> rootsJoints;
- std::vector<Index> path;
- path.reserve(16);
- for(auto& s : skeletons)
- {
- std::map<uint32_t, uint32_t> jointRefs;
- for(auto& j : s.mJoints)
- {
- auto nodeIdx = j.mNodeIdx;
- do // Traverse upwards and record each node we have visited until we reach the scene root.
- {
- path.push_back(nodeIdx);
- if(nodeIdx == iRoot)
- {
- break;
- }
- auto node = GetNode(nodeIdx);
- nodeIdx = node->mParentIdx;
- } while(nodeIdx != INVALID_INDEX);
-
- if(nodeIdx == iRoot) // If the joint is in the correct scene, increment the reference count for all visited nodes.
- {
- for(auto i : path)
- {
- ++jointRefs[i];
- }
- }
-
- path.clear();
- }
-
- // Only record the skeleton if we have encountered the root of the current scene.
- if(jointRefs.empty())
- {
- continue;
- }
-
- Index root = s.mRootNodeIdx;
- uint32_t maxRef = 0;
- auto iFind = jointRefs.find(root);
- if(iFind != jointRefs.end())
- {
- maxRef = iFind->second;
- }
-
- std::vector<Index> joints;
- for(auto& j : jointRefs) // NOTE: jointRefs are sorted, so joints will also be.
- {
- // The most descendant node with the highest ref count is the root of the skeleton.
- if(j.second > maxRef || (j.second == maxRef && IsAncestor(*this, root, j.first, iRoot)))
- {
- maxRef = j.second;
-
- RemoveFromSorted(joints, root);
- root = j.first;
- }
- else if(j.second == 1) // This one's a leaf.
- {
- InsertUniqueSorted(joints, j.first);
- }
- }
-
- // Merge skeletons that share the same root.
- auto& finalJoints = rootsJoints[root];
- for(auto j : joints)
- {
- if(std::find_if(finalJoints.begin(), finalJoints.end(), [this, j, root](Index jj) {
- return IsAncestor(*this, j, jj, root);
- }) != finalJoints.end())
- {
- continue; // if the joint is found to be an ancestor of another joint already registered, move on.
- }
-
- auto i = j;
- while(i != root) // See if the current joint is a better leaf, i.e. descended from another leaf - which we'll then remove.
- {
- auto node = GetNode(i);
- i = node->mParentIdx;
-
- RemoveFromSorted(finalJoints, i);
- }
-
- InsertUniqueSorted(finalJoints, j);
- }
- }
-
- // 2, Merge records where one root joint is descendant of another. Handle leaf node changes - remove previous
- // leaf nodes that now have descendants, and add new ones.
- auto iRoots = rootsJoints.begin();
- auto iRootsEnd = rootsJoints.end();
- while(iRoots != iRootsEnd)
- {
- auto i = iRoots->first;
- bool merged = false;
- while(i != iRoot) // Starting with the root joint of the skeleton, traverse upwards.
- {
- auto node = GetNode(i);
- i = node->mParentIdx;
-
- auto iFind = rootsJoints.find(i);
- if(iFind != rootsJoints.end()) // Check if we've reached the root of another skeleton.
- {
- // Now find out which leaf of iFind is an ancestor, if any.
- auto iFindLeaf = std::find_if(iFind->second.begin(), iFind->second.end(), [this, iRoots, iFind](Index j) {
- return IsAncestor(*this, j, iRoots->first, iFind->first);
- });
- if(iFindLeaf != iFind->second.end())
- {
- iFind->second.erase(iFindLeaf); // Will no longer be a leaf -- remove it.
- }
-
- // Merge iRoots with iFind
- auto& targetJoints = iFind->second;
- if(iRoots->second.empty()) // The root is a leaf.
- {
- InsertUniqueSorted(targetJoints, iRoots->first);
- }
- else
- for(auto j : iRoots->second)
- {
- InsertUniqueSorted(targetJoints, j);
- }
-
- merged = true;
- break; // Traverse no more
- }
- }
-
- iRoots = merged ? rootsJoints.erase(iRoots) : std::next(iRoots);
- }
-
- // 3, For each root, register joint matrices and constraints
- for(const auto& r : rootsJoints)
- {
- auto node = GetNode(r.first);
- auto rootJoint = root.FindChildByName(node->mName);
- DALI_ASSERT_ALWAYS(!!rootJoint);
-
- DALI_ASSERT_DEBUG(rootJoint.GetPropertyIndex(Skinning::JOINT_MATRIX) == Property::INVALID_INDEX);
- auto propJointMatrix = rootJoint.RegisterProperty(Skinning::JOINT_MATRIX, Matrix{false});
- Constraint constraint = Constraint::New<Matrix>(rootJoint, propJointMatrix, [](Matrix& output, const PropertyInputContainer& inputs) {
- output.SetTransformComponents(Vector3::ONE, inputs[0]->GetQuaternion(), inputs[1]->GetVector3());
- });
- constraint.AddSource(Source(rootJoint, Actor::Property::ORIENTATION));
- constraint.AddSource(Source(rootJoint, Actor::Property::POSITION));
- constraint.Apply();
-
- for(const auto j : r.second)
- {
- node = GetNode(j);
- auto joint = rootJoint.FindChildByName(node->mName);
- ConfigureJointMatrix(joint, rootJoint, propJointMatrix);
- }
- }
-}
-
void SceneDefinition::EnsureUniqueSkinningShaderInstances(ResourceBundle& resources) const
{
std::map<Index, std::map<Index, std::vector<Index*>>> skinningShaderUsers;