#include "entities/PathComponent.h" #include #include #include #include "common/SpdLogger.h" #include "common/RecourceHelper.h" #include "utils/TransformPath.h" #include "utils/OsgUtils.h" #include "utils/FileUtils.h" #include "entities/Entity.h" #include "workspace/WorkSpace.h" #include "workspace/Timestep.h" PathComponent::PathComponent(SceneComponent* parent) : SceneComponent(parent) { animationPath_ = new osg::AnimationPath(); animationPath_->setLoopMode(osg::AnimationPath::NO_LOOPING); } PathComponent::~PathComponent() { } std::string PathComponent::GetTypeName() { return "PathComponent"; } bool PathComponent::SetAttribute(const char* name, const char* value) { if (0 == strcmp(name, "path")) { SetPath(value); return nullptr != transformPath_; } return SceneComponent::SetAttribute(name, value); } bool PathComponent::SaveAttribute(tinyxml2::XMLElement* element) { element->SetAttribute("path", path_.toStdString().c_str()); return SceneComponent::SaveAttribute(element); } void PathComponent::Begin() { WorkSpace* workspace = GetEntity()->GetWorkspace(); if (nullptr == workspace) { LOG_WARN("workspace is nullptr"); return; } timeStep_ = workspace->GetTimestep(); if (nullptr == timeStep_) { LOG_WARN("timeStep is nullptr"); return; } if (nullptr == transformPath_) { LOG_WARN("transformPath_ is nullptr"); return; } animationPath_->clear(); std::vector mappedSteps; const bool hasPathTimes = transformPath_ && !transformPath_->GetTimes().empty(); double rangeMin = 0.0, rangeMax = 0.0, rangeStep = 0.0; timeStep_->GetRange(rangeMin, rangeMax, rangeStep); if (hasPathTimes) { const auto& times = transformPath_->GetTimes(); if (timeStep_->HasManualRange()) { double dstMin = timeStep_->GetManualStart(); double dstMax = timeStep_->GetManualEnd(); mappedSteps.reserve(times.size()); for (double t : times) { if (t >= dstMin && t <= dstMax) { mappedSteps.push_back(t); } } if (mappedSteps.empty()) { mappedSteps = times; } } else { mappedSteps = times; } } else { const std::vector& transforms = transformPath_->GetTransforms(); int num = (int)transforms.size(); if (num > 0) { mappedSteps.resize(num); double start = timeStep_->HasManualRange() ? timeStep_->GetManualStart() : rangeMin; double end = timeStep_->HasManualRange() ? timeStep_->GetManualEnd() : rangeMax; double step = rangeStep; if (step <= 0.0) { step = (num > 1) ? std::max(0.0, (end - start)) / double(num - 1) : 0.0; } for (int i = 0; i < num; ++i) { double t = start + step * double(i); if (t > end) t = end; mappedSteps[i] = t; } } } const std::vector& transforms = transformPath_->GetTransforms(); int num = std::min(mappedSteps.size(), transforms.size()); for (int index = 0; index < num; ++index) { const Transform& transform = transforms[index]; osg::AnimationPath::ControlPoint controlPoint(transform.GetLocation() /*+ osg::Vec3(index * 10, 0, 0)*/, OsgUtils::HPRToQuat(transform.GetRotation()), transform.GetScale()); animationPath_->insert(mappedSteps[index], controlPoint); } deltaTime_ = 0; } void PathComponent::Update(double dt) { deltaTime_ += dt; if (nullptr == timeStep_) { return; } double st = timeStep_->GetCurrent(); osg::AnimationPath::ControlPoint cp; if (!animationPath_->getInterpolatedControlPoint(st, cp)) { return; } Transform* transform = owner_->GetTransform(); transform->SetLocation(cp.getPosition()); osg::Vec3 angle; OsgUtils::QuatToHPR(cp.getRotation(), &angle); transform->SetRotation(angle); } void PathComponent::SetPath(const QString& path) { if (path == path_ || path.isEmpty()) { LOG_INFO("path is the same, file:{}", path.toLocal8Bit().constData()); return; } if (nullptr != transformPath_) { transformPath_->deleteLater(); } const QString workPath = GetEntity()->GetWorkspace()->GetDir(); const QString filePath = QString("%1/%2").arg(workPath).arg(path); transformPath_ = TransformPath::LoadFromFile(filePath, this); path_ = path; } const QString& PathComponent::GetPath() const { return path_; }