mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-04-28 21:07:59 +03:00
Merge branch 'fix-osga-rotate-wildly' into 'master'
Fix OSGAnimation issues See merge request OpenMW/openmw!3989
This commit is contained in:
commit
04f1dc282b
15 changed files with 312 additions and 65 deletions
|
@ -37,11 +37,11 @@ namespace Resource
|
|||
|
||||
bool RetrieveAnimationsVisitor::belongsToLeftUpperExtremity(const std::string& name)
|
||||
{
|
||||
static const std::array boneNames = { "bip01_l_clavicle", "left_clavicle", "bip01_l_upperarm", "left_upper_arm",
|
||||
"bip01_l_forearm", "bip01_l_hand", "left_hand", "left_wrist", "shield_bone", "bip01_l_pinky1",
|
||||
"bip01_l_pinky2", "bip01_l_pinky3", "bip01_l_ring1", "bip01_l_ring2", "bip01_l_ring3", "bip01_l_middle1",
|
||||
"bip01_l_middle2", "bip01_l_middle3", "bip01_l_pointer1", "bip01_l_pointer2", "bip01_l_pointer3",
|
||||
"bip01_l_thumb1", "bip01_l_thumb2", "bip01_l_thumb3", "left_forearm" };
|
||||
static const std::array boneNames = { "bip01 l clavicle", "left clavicle", "bip01 l upperarm", "left upper arm",
|
||||
"bip01 l forearm", "bip01 l hand", "left hand", "left wrist", "shield bone", "bip01 l pinky1",
|
||||
"bip01 l pinky2", "bip01 l pinky3", "bip01 l ring1", "bip01 l ring2", "bip01 l ring3", "bip01 l middle1",
|
||||
"bip01 l middle2", "bip01 l middle3", "bip01 l pointer1", "bip01 l pointer2", "bip01 l pointer3",
|
||||
"bip01 l thumb1", "bip01 l thumb2", "bip01 l thumb3", "left forearm" };
|
||||
|
||||
if (std::find(boneNames.begin(), boneNames.end(), name) != boneNames.end())
|
||||
return true;
|
||||
|
@ -51,11 +51,11 @@ namespace Resource
|
|||
|
||||
bool RetrieveAnimationsVisitor::belongsToRightUpperExtremity(const std::string& name)
|
||||
{
|
||||
static const std::array boneNames = { "bip01_r_clavicle", "right_clavicle", "bip01_r_upperarm",
|
||||
"right_upper_arm", "bip01_r_forearm", "bip01_r_hand", "right_hand", "right_wrist", "bip01_r_thumb1",
|
||||
"bip01_r_thumb2", "bip01_r_thumb3", "weapon_bone", "bip01_r_pinky1", "bip01_r_pinky2", "bip01_r_pinky3",
|
||||
"bip01_r_ring1", "bip01_r_ring2", "bip01_r_ring3", "bip01_r_middle1", "bip01_r_middle2", "bip01_r_middle3",
|
||||
"bip01_r_pointer1", "bip01_r_pointer2", "bip01_r_pointer3", "right_forearm" };
|
||||
static const std::array boneNames = { "bip01 r clavicle", "right clavicle", "bip01 r upperarm",
|
||||
"right upper arm", "bip01 r forearm", "bip01 r hand", "right hand", "right wrist", "bip01 r thumb1",
|
||||
"bip01 r thumb2", "bip01 r thumb3", "weapon bone", "bip01 r pinky1", "bip01 r pinky2", "bip01 r pinky3",
|
||||
"bip01 r ring1", "bip01 r ring2", "bip01 r ring3", "bip01 r middle1", "bip01 r middle2", "bip01 r middle3",
|
||||
"bip01 r pointer1", "bip01 r pointer2", "bip01 r pointer3", "right forearm" };
|
||||
|
||||
if (std::find(boneNames.begin(), boneNames.end(), name) != boneNames.end())
|
||||
return true;
|
||||
|
@ -66,7 +66,7 @@ namespace Resource
|
|||
bool RetrieveAnimationsVisitor::belongsToTorso(const std::string& name)
|
||||
{
|
||||
static const std::array boneNames
|
||||
= { "bip01_spine1", "bip01_spine2", "bip01_neck", "bip01_head", "head", "neck", "chest", "groin" };
|
||||
= { "bip01 spine1", "bip01 spine2", "bip01 neck", "bip01 head", "head", "neck", "chest", "groin" };
|
||||
|
||||
if (std::find(boneNames.begin(), boneNames.end(), name) != boneNames.end())
|
||||
return true;
|
||||
|
@ -99,6 +99,9 @@ namespace Resource
|
|||
const osgAnimation::ChannelList& channels = animation->getChannels();
|
||||
for (const auto& channel : channels)
|
||||
{
|
||||
// Replace channel target name to match the renamed bones/transforms
|
||||
channel->setTargetName(Misc::StringUtils::underscoresToSpaces(channel->getTargetName()));
|
||||
|
||||
if (name == "Bip01 R Clavicle")
|
||||
{
|
||||
if (!belongsToRightUpperExtremity(channel->getTargetName()))
|
||||
|
|
|
@ -9,7 +9,10 @@
|
|||
#include <osg/Node>
|
||||
#include <osg/UserDataContainer>
|
||||
|
||||
#include <osgAnimation/Bone>
|
||||
#include <osgAnimation/RigGeometry>
|
||||
#include <osgAnimation/Skeleton>
|
||||
#include <osgAnimation/UpdateBone>
|
||||
|
||||
#include <osgParticle/ParticleSystem>
|
||||
|
||||
|
@ -268,6 +271,11 @@ namespace Resource
|
|||
|
||||
void apply(osg::Node& node) override
|
||||
{
|
||||
// If an osgAnimation bone/transform, ensure underscores in name are replaced with spaces
|
||||
// this is for compatibility reasons
|
||||
if (dynamic_cast<osgAnimation::Bone*>(&node))
|
||||
node.setName(Misc::StringUtils::underscoresToSpaces(node.getName()));
|
||||
|
||||
if (osg::StateSet* stateset = node.getStateSet())
|
||||
{
|
||||
if (stateset->getRenderingHint() == osg::StateSet::TRANSPARENT_BIN)
|
||||
|
@ -353,6 +361,53 @@ namespace Resource
|
|||
std::vector<osg::ref_ptr<SceneUtil::RigGeometryHolder>> mRigGeometryHolders;
|
||||
};
|
||||
|
||||
void updateVertexInfluenceMap(osgAnimation::RigGeometry& rig)
|
||||
{
|
||||
osgAnimation::VertexInfluenceMap* vertexInfluenceMap = rig.getInfluenceMap();
|
||||
if (!vertexInfluenceMap)
|
||||
return;
|
||||
|
||||
std::vector<std::string> renameList;
|
||||
for (const auto& [boneName, unused] : *vertexInfluenceMap)
|
||||
{
|
||||
if (boneName.find('_') != std::string::npos)
|
||||
renameList.push_back(boneName);
|
||||
}
|
||||
|
||||
for (const std::string& oldName : renameList)
|
||||
{
|
||||
const std::string newName = Misc::StringUtils::underscoresToSpaces(oldName);
|
||||
if (vertexInfluenceMap->find(newName) == vertexInfluenceMap->end())
|
||||
(*vertexInfluenceMap)[newName] = std::move((*vertexInfluenceMap)[oldName]);
|
||||
vertexInfluenceMap->erase(oldName);
|
||||
}
|
||||
}
|
||||
|
||||
class RenameAnimCallbacksVisitor : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
RenameAnimCallbacksVisitor()
|
||||
: osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
|
||||
{
|
||||
}
|
||||
|
||||
void apply(osg::MatrixTransform& node) override
|
||||
{
|
||||
// osgAnimation update callback name must match bone name/channel targets
|
||||
osg::Callback* cb = node.getUpdateCallback();
|
||||
while (cb)
|
||||
{
|
||||
auto animCb = dynamic_cast<osgAnimation::AnimationUpdateCallback<osg::NodeCallback>*>(cb);
|
||||
if (animCb)
|
||||
animCb->setName(Misc::StringUtils::underscoresToSpaces(animCb->getName()));
|
||||
|
||||
cb = cb->getNestedCallback();
|
||||
}
|
||||
|
||||
traverse(node);
|
||||
}
|
||||
};
|
||||
|
||||
SceneManager::SceneManager(const VFS::Manager* vfs, Resource::ImageManager* imageManager,
|
||||
Resource::NifFileManager* nifFileManager, double expiryDelay)
|
||||
: ResourceManager(vfs, expiryDelay)
|
||||
|
@ -556,6 +611,7 @@ namespace Resource
|
|||
VFS::Path::NormalizedView normalizedFilename, std::istream& model, Resource::ImageManager* imageManager)
|
||||
{
|
||||
const std::string_view ext = Misc::getFileExtension(normalizedFilename.value());
|
||||
const bool isColladaFile = ext == "dae";
|
||||
osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension(std::string(ext));
|
||||
if (!reader)
|
||||
{
|
||||
|
@ -571,7 +627,7 @@ namespace Resource
|
|||
// findFileCallback would be necessary. but findFileCallback does not support virtual files, so we can't
|
||||
// implement it.
|
||||
options->setReadFileCallback(new ImageReadCallback(imageManager));
|
||||
if (ext == "dae")
|
||||
if (isColladaFile)
|
||||
options->setOptionString("daeUseSequencedTextureUnits");
|
||||
|
||||
const std::array<std::uint64_t, 2> fileHash = Files::getHash(normalizedFilename.value(), model);
|
||||
|
@ -599,9 +655,13 @@ namespace Resource
|
|||
node->accept(rigFinder);
|
||||
for (osg::Node* foundRigNode : rigFinder.mFoundNodes)
|
||||
{
|
||||
if (foundRigNode->libraryName() == std::string("osgAnimation"))
|
||||
if (foundRigNode->libraryName() == std::string_view("osgAnimation"))
|
||||
{
|
||||
osgAnimation::RigGeometry* foundRigGeometry = static_cast<osgAnimation::RigGeometry*>(foundRigNode);
|
||||
|
||||
if (isColladaFile)
|
||||
Resource::updateVertexInfluenceMap(*foundRigGeometry);
|
||||
|
||||
osg::ref_ptr<SceneUtil::RigGeometryHolder> newRig
|
||||
= new SceneUtil::RigGeometryHolder(*foundRigGeometry, osg::CopyOp::DEEP_COPY_ALL);
|
||||
|
||||
|
@ -616,13 +676,18 @@ namespace Resource
|
|||
}
|
||||
}
|
||||
|
||||
if (ext == "dae")
|
||||
if (isColladaFile)
|
||||
{
|
||||
Resource::ColladaDescriptionVisitor colladaDescriptionVisitor;
|
||||
node->accept(colladaDescriptionVisitor);
|
||||
|
||||
if (colladaDescriptionVisitor.mSkeleton)
|
||||
{
|
||||
// Collada bones may have underscores in place of spaces due to a collada limitation
|
||||
// we should rename the bones and update callbacks here at load time
|
||||
Resource::RenameAnimCallbacksVisitor renameBoneVisitor;
|
||||
node->accept(renameBoneVisitor);
|
||||
|
||||
if (osg::Group* group = dynamic_cast<osg::Group*>(node))
|
||||
{
|
||||
group->removeChildren(0, group->getNumChildren());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue