当前位置: 首页 > news >正文

ue5 motion matching

ue5.5   gameanimationsample

先看动画蓝图 核心两个node

第一个是根据数据选择当前的pose

 第二个是缓存一段历史记录,为第一个node选择的时候提供数据。

在animinstance的update方法中 每帧都更新这个函数,每帧更新trajectory的数据

看看第一个node的执行顺序

void FAnimNode_MotionMatching::UpdateAssetPlayer(const FAnimationUpdateContext& Context)void UPoseSearchLibrary::UpdateMotionMatchingState(const FAnimationUpdateContext& Context,const TArray<TObjectPtr<const UPoseSearchDatabase>>& Databases,float BlendTime,int32 MaxActiveBlends,const FFloatInterval& PoseJumpThresholdTime,float PoseReselectHistory,float SearchThrottleTime,const FFloatInterval& PlayRate,FMotionMatchingState& InOutMotionMatchingState,EPoseSearchInterruptMode InterruptMode,bool bShouldSearch,bool bShouldUseCachedChannelData,bool bDebugDrawQuery,bool bDebugDrawCurResult){...........//这里每帧都监听第二个节点,把history trajectory传过来const IPoseHistory* PoseHistory = nullptr;if (FPoseHistoryProvider* PoseHistoryProvider = Context.GetMessage<FPoseHistoryProvider>()){PoseHistory = &PoseHistoryProvider->GetPoseHistory();}FMemMark Mark(FMemStack::Get());const UAnimInstance* AnimInstance = Cast<const UAnimInstance>(Context.AnimInstanceProxy->GetAnimInstanceObject());check(AnimInstance);const UPoseSearchDatabase* CurrentResultDatabase = InOutMotionMatchingState.CurrentSearchResult.Database.Get();if (IsInvalidatingContinuingPose(InterruptMode, CurrentResultDatabase, Databases)){InOutMotionMatchingState.CurrentSearchResult.Reset();}FSearchContext SearchContext(0.f, &InOutMotionMatchingState.PoseIndicesHistory, InOutMotionMatchingState.CurrentSearchResult, PoseJumpThresholdTime);//addSearchContext.AddRole(DefaultRole, AnimInstance, PoseHistory);.........const FSearchResult NewSearchResult = Database->Search(SearchContext);.........
}UE::PoseSearch::FSearchResult UPoseSearchDatabase::Search(UE::PoseSearch::FSearchContext& SearchContext) const{.........Result = SearchPCAKDTree(SearchContext);.........
}UE::PoseSearch::FSearchResult UPoseSearchDatabase::SearchPCAKDTree(UE::PoseSearch::FSearchContext& SearchContext) const
{.........//channelTConstArrayView<float> QueryValues = SearchContext.GetOrBuildQuery(Schema);.........
}TConstArrayView<float> FSearchContext::GetOrBuildQuery(const UPoseSearchSchema* Schema)
{QUICK_SCOPE_CYCLE_COUNTER(STAT_PoseSearch_GetOrBuildQuery);check(Schema);if (const FCachedQuery* FoundCachedQuery = CachedQueries.FindByPredicate([Schema](const FCachedQuery& CachedQuery){return CachedQuery.GetSchema() == Schema;})){return FoundCachedQuery->GetValues();}return Schema->BuildQuery(*this);
}TConstArrayView<float> UPoseSearchSchema::BuildQuery(UE::PoseSearch::FSearchContext& SearchContext) const
{QUICK_SCOPE_CYCLE_COUNTER(STAT_PoseSearch_BuildQuery);SearchContext.AddNewFeatureVectorBuilder(this);for (const TObjectPtr<UPoseSearchFeatureChannel>& ChannelPtr : GetChannels()){ChannelPtr->BuildQuery(SearchContext);}return SearchContext.EditFeatureVector();
}void UPoseSearchFeatureChannel_GroupBase::BuildQuery(UE::PoseSearch::FSearchContext& SearchContext) const
{for (const TObjectPtr<UPoseSearchFeatureChannel>& SubChannelPtr : GetSubChannels()){if (const UPoseSearchFeatureChannel* SubChannel = SubChannelPtr.Get()){SubChannel->BuildQuery(SearchContext);}}
}//subchannel就是各种channel 的数组 比如position channel,velocity channelvoid UPoseSearchFeatureChannel_Position::BuildQuery(UE::PoseSearch::FSearchContext& SearchContext) const
{..............const FVector BonePosition = SearchContext.GetSamplePosition(SampleTimeOffset, OriginTimeOffset, SchemaBoneIdx, SchemaOriginBoneIdx, SampleRole, OriginRole, PermutationTimeType, &BonePositionWorld);...........}FVector FSearchContext::GetSamplePosition(float SampleTimeOffset, float OriginTimeOffset, int8 SchemaSampleBoneIdx, int8 SchemaOriginBoneIdx, const FRole& SampleRole, const FRole& OriginRole, EPermutationTimeType PermutationTimeType, const FVector* SampleBonePositionWorldOverride)
{float PermutationSampleTimeOffset = 0.f;float PermutationOriginTimeOffset = 0.f;UPoseSearchFeatureChannel::GetPermutationTimeOffsets(PermutationTimeType, DesiredPermutationTimeOffset, PermutationSampleTimeOffset, PermutationOriginTimeOffset);const float SampleTime = SampleTimeOffset + PermutationSampleTimeOffset;const float OriginTime = OriginTimeOffset + PermutationOriginTimeOffset;return GetSamplePositionInternal(SampleTime, OriginTime, SchemaSampleBoneIdx, SchemaOriginBoneIdx, SampleRole, OriginRole, SampleBonePositionWorldOverride);
}FVector FSearchContext::GetSamplePositionInternal(float SampleTime, float OriginTime, int8 SchemaSampleBoneIdx, int8 SchemaOriginBoneIdx, const FRole& SampleRole, const FRole& OriginRole, const FVector* SampleBonePositionWorldOverride)
{if (SampleBonePositionWorldOverride){const FTransform RootBoneTransform = GetWorldBoneTransformAtTime(OriginTime, OriginRole, RootSchemaBoneIdx);if (SchemaOriginBoneIdx == RootSchemaBoneIdx){return RootBoneTransform.InverseTransformPosition(*SampleBonePositionWorldOverride);}// @todo: validate this still works for when root bone is not Identityconst FTransform OriginBoneTransform = GetWorldBoneTransformAtTime(OriginTime, OriginRole, SchemaOriginBoneIdx);const FVector DeltaBoneTranslation = *SampleBonePositionWorldOverride - OriginBoneTransform.GetTranslation();return RootBoneTransform.InverseTransformVector(DeltaBoneTranslation);}const FTransform RootBoneTransform = GetWorldBoneTransformAtTime(OriginTime, OriginRole, RootSchemaBoneIdx);const FTransform SampleBoneTransform = GetWorldBoneTransformAtTime(SampleTime, SampleRole, SchemaSampleBoneIdx);if (SchemaOriginBoneIdx == RootSchemaBoneIdx){return RootBoneTransform.InverseTransformPosition(SampleBoneTransform.GetTranslation());}const FTransform OriginBoneTransform = GetWorldBoneTransformAtTime(OriginTime, OriginRole, SchemaOriginBoneIdx);const FVector DeltaBoneTranslation = SampleBoneTransform.GetTranslation() - OriginBoneTransform.GetTranslation();return RootBoneTransform.InverseTransformVector(DeltaBoneTranslation);
}//获得过程终于用到了const IPoseHistory* PoseHistory = GetPoseHistory(SampleRole);
FTransform FSearchContext::GetWorldBoneTransformAtTime(float SampleTime, const FRole& SampleRole, int8 SchemaBoneIdx)
{// CachedQueries.Last is the query we're building check(!CachedQueries.IsEmpty());const UPoseSearchSchema* Schema = CachedQueries.Last().GetSchema();check(Schema);TConstArrayView<FBoneReference> BoneReferences = Schema->GetBoneReferences(SampleRole);check(BoneReferences[SchemaBoneIdx].HasValidSetup());const FBoneIndexType BoneIndexType = BoneReferences[SchemaBoneIdx].BoneIndex;const uint32 SampleTimeHash = GetTypeHash(SampleTime);const uint32 SampleRoleHash = GetTypeHash(SampleRole);const uint32 SampleTimeAndRoleHash = HashCombineFast(SampleTimeHash, SampleRoleHash);const uint32 BoneIndexTypeHash = GetTypeHash(BoneIndexType);const uint32 BoneCachedTransformKey = HashCombineFast(SampleTimeAndRoleHash, BoneIndexTypeHash);if (const FTransform* CachedTransform = CachedTransforms.Find(BoneCachedTransformKey)){return *CachedTransform;}FTransform WorldBoneTransform;if (BoneIndexType == RootBoneIndexType){// we already tried querying the CachedTransforms so, let's search in TrajectoryWorldBoneTransform = GetWorldRootBoneTransformAtTime(SampleTime, SampleRole);}else // if (BoneIndexType != RootBoneIndexType){// searching for RootBoneIndexType in CachedTransformsstatic const uint32 RootBoneIndexTypeHash = GetTypeHash(RootBoneIndexType); // Note: static const, since RootBoneIndexType is a constantconst uint32 RootBoneCachedTransformKey = HashCombineFast(SampleTimeAndRoleHash, RootBoneIndexTypeHash);if (const FTransform* CachedTransform = CachedTransforms.Find(RootBoneCachedTransformKey)){WorldBoneTransform = *CachedTransform;}else{WorldBoneTransform = GetWorldRootBoneTransformAtTime(SampleTime, SampleRole);}// collecting the local bone transforms from the IPoseHistoryconst IPoseHistory* PoseHistory = GetPoseHistory(SampleRole);#if WITH_EDITORif (!PoseHistory){UE_LOG(LogPoseSearch, Error, TEXT("FSearchContext::GetWorldBoneTransformAtTime - Couldn't search for bones requested by %s, because no IPoseHistory has been found!"), *Schema->GetName());}else#endif // WITH_EDITOR{check(PoseHistory);const USkeleton* Skeleton = Schema->GetSkeleton(SampleRole);FTransform LocalBoneTransform;if (!PoseHistory->GetTransformAtTime(SampleTime, LocalBoneTransform, Skeleton, BoneIndexType, RootBoneIndexType)){if (Skeleton){if (!PoseHistory->IsEmpty()){UE_LOG(LogPoseSearch, Warning, TEXT("FSearchContext::GetWorldBoneTransformAtTime - Couldn't find BoneIndexType %d (%s) requested by %s"), BoneIndexType, *Skeleton->GetReferenceSkeleton().GetBoneName(BoneIndexType).ToString(), *Schema->GetName());}}else{UE_LOG(LogPoseSearch, Warning, TEXT("FSearchContext::GetWorldBoneTransformAtTime - Schema '%s' Skeleton is not properly set"), *Schema->GetName());}}WorldBoneTransform = LocalBoneTransform * WorldBoneTransform;}}CachedTransforms.Add(BoneCachedTransformKey) = WorldBoneTransform;return WorldBoneTransform;
}//这里就是第二个节点pose history  里面有 trajectory
bool FPoseHistory::GetTransformAtTime(float Time, FTransform& OutBoneTransform, const USkeleton* BoneIndexSkeleton, FBoneIndexType BoneIndexType, FBoneIndexType ReferenceBoneIndexType, bool bExtrapolate) const
{CheckThreadSafetyRead(ReadPoseDataThreadSafeCounter);static_assert(RootBoneIndexType == 0 && ComponentSpaceIndexType == FBoneIndexType(-1) && WorldSpaceIndexType == FBoneIndexType(-2)); // some assumptionscheck(BoneIndexType != ComponentSpaceIndexType && BoneIndexType != WorldSpaceIndexType);bool bSuccess = false;const bool bApplyComponentToWorld = ReferenceBoneIndexType == WorldSpaceIndexType;FTransform ComponentToWorld = FTransform::Identity;if (bApplyComponentToWorld){//就是这个和trajectory 联系上了ComponentToWorld = Trajectory.GetSampleAtTime(Time, bExtrapolate).GetTransform();ReferenceBoneIndexType = ComponentSpaceIndexType;}const FPoseData& ReadPoseData = GetReadPoseData();const int32 NumEntries = ReadPoseData.Entries.Num();if (NumEntries > 0){int32 NextIdx = 0;int32 PrevIdx = 0;if (NumEntries > 1){const int32 LowerBoundIdx = LowerBound(ReadPoseData.Entries.begin(), ReadPoseData.Entries.end(), Time, [](const FPoseHistoryEntry& Entry, float Value) { return Value > Entry.AccumulatedSeconds; });NextIdx = FMath::Clamp(LowerBoundIdx, 1, NumEntries - 1);PrevIdx = NextIdx - 1;}const FPoseHistoryEntry& PrevEntry = ReadPoseData.Entries[PrevIdx];const FPoseHistoryEntry& NextEntry = ReadPoseData.Entries[NextIdx];bSuccess = LerpEntries(Time, bExtrapolate, PrevEntry, NextEntry, BoneIndexSkeleton, ReadPoseData.LastUpdateSkeleton.Get(), ReadPoseData.BoneToTransformMap, BoneIndexType, ReferenceBoneIndexType, OutBoneTransform);if (bApplyComponentToWorld){OutBoneTransform *= ComponentToWorld;}}else{OutBoneTransform = ComponentToWorld;}return bSuccess;
}

关于pose history

FPoseHistory 里面有    FPoseSearchQueryTrajectory Trajectory;

就是

void FAnimNode_PoseSearchHistoryCollector::Evaluate_AnyThread(FPoseContext& Output)
{DECLARE_SCOPE_HIERARCHICAL_COUNTER_ANIMNODE(Evaluate_AnyThread);ANIM_MT_SCOPE_CYCLE_COUNTER_VERBOSE(PoseSearchHistoryCollector, !IsInGameThread());check(Output.AnimInstanceProxy);Super::Evaluate_AnyThread(Output);Source.Evaluate(Output);const bool bNeedsReset = bResetOnBecomingRelevant && UpdateCounter.HasEverBeenUpdated() && !UpdateCounter.WasSynchronizedCounter(Output.AnimInstanceProxy->GetUpdateCounter());FCSPose<FCompactPose> ComponentSpacePose;ComponentSpacePose.InitPose(Output.Pose);TArray<FBoneIndexType> RequiredBones;if (bCacheBones){RequiredBones = GetRequiredBones(Output.AnimInstanceProxy);}PoseHistory.EvaluateComponentSpace_AnyThread(Output.AnimInstanceProxy->GetDeltaSeconds(), ComponentSpacePose, bStoreScales,RootBoneRecoveryTime, RootBoneTranslationRecoveryRatio, RootBoneRotationRecoveryRatio, bNeedsReset, bCacheBones, RequiredBones, Output.Curve, MakeConstArrayView(CollectedCurves));bCacheBones = false;#if ENABLE_DRAW_DEBUG && ENABLE_ANIM_DEBUGFColor Color;
#if WITH_EDITORONLY_DATAColor = DebugColor.ToFColor(true);
#else // WITH_EDITORONLY_DATAColor = FLinearColor::Red.ToFColor(true);
#endif // WITH_EDITORONLY_DATAPoseHistory.DebugDraw(*Output.AnimInstanceProxy, Color);
#endif // ENABLE_DRAW_DEBUG && ENABLE_ANIM_DEBUG
}

FPoseHistory中Trajectory能确定控件的世界空间下的 pos和rotation

再配合CollectedBones确定的骨骼的历史记录

就能确定某个骨骼的历史 的世界坐标

来作为选择某个pose的支撑数据

在FSearchContext中

const IPoseHistory* GetPoseHistory(const FRole& Role) const { return PoseHistories[RoleToIndex[Role]]; }

资产方面 最重要的是要建立 pose search database 

schema最重要的是定义channel,从不同的维度去解析查找符合预期的pose

各种channel的定义

相关文章:

ue5 motion matching

ue5.5 gameanimationsample 先看动画蓝图 核心两个node 第一个是根据数据选择当前的pose 第二个是缓存一段历史记录&#xff0c;为第一个node选择的时候提供数据。 在animinstance的update方法中 每帧都更新这个函数&#xff0c;每帧更新trajectory的数据 看看第一个node的…...

【从零开始的LeetCode-算法】383. 赎金信

给你两个字符串&#xff1a;ransomNote 和 magazine &#xff0c;判断 ransomNote 能不能由 magazine 里面的字符构成。 如果可以&#xff0c;返回 true &#xff1b;否则返回 false 。 magazine 中的每个字符只能在 ransomNote 中使用一次。 示例 1&#xff1a; 输入&#…...

记录模板学习(持续更新)

目的&#xff1a; 学习C模板的编写&#xff0c;使用模板类包装一个可调用对象 可调用对象包括&#xff1a;普通函数&#xff0c; lambda表达式&#xff0c; 类成员函数 可以参考到QtConcurrent::run的实现&#xff0c;可以看到这个函数有非常多重载&#xff0c;其中可以接受类…...

Android hid 数据传输(device 端 )

最近一直在处理hid 数据需求&#xff0c;简而言之就是两台设备直接可以通过usb 线互相传递数据。 项目架构 为什么Device 端要采用HID&#xff08;人机接口设备&#xff09;的方式发送和接收数据呢&#xff1f; 主要是速度快&#xff0c;举个例子&#xff0c;就是鼠标移动&am…...

MaxEnt模型在物种分布模拟中如何应用?R语言+MaxEnt模型融合物种分布模拟、参数优化方法、结果分析制图与论文写作

目录 第一章 以问题导入的方式&#xff0c;深入掌握原理基础 第二章 常用数据检索与R语言自动化下载及可视化方法 第三章 R语言数据清洗与特征变量筛选 第四章 基于ArcGIS、R数据处理与进阶 第五章 基于Maxent的物种分布建模与预测 第六章 基于R语言的模型参数优化 第七…...

第3章:文本样式 --[CSS零基础入门]

CSS(层叠样式表)允许你以多种方式定制文本的外观。以下是一些常用的文本和字体相关的CSS属性: 1.字体 字体系列 当然,下面是两个使用不同字体系列的CSS示例。每个示例都展示了如何指定一个字体系列,并提供备用字体以确保在用户的系统中找不到首选字体时仍有合适的字体可…...

mysql 架构详解

MySQL的架构可以自顶向下分为多个层次&#xff0c;每个层次都有其特定的功能和组件。以下是对MySQL架构的详细解析&#xff1a; 一、整体架构概述 MySQL的整体架构包括MySQL Connectors&#xff08;连接器&#xff09;、MySQL Shell、连接层、服务层、存储引擎层和文件系统层…...

无代码探索AI大模型:腾讯云函数计算的卓越实践

在数字化转型的浪潮中&#xff0c;人工智能&#xff08;AI&#xff09;技术已经成为企业提升竞争力的关键。然而&#xff0c;对于许多业务人员来说&#xff0c;技术门槛高、开发周期长等问题限制了他们快速探索和应用AI大模型的能力。同时&#xff0c;对于缺乏GPU资源的开发者来…...

解决Ubuntu在VMware关机时,老是一个光标在那里闪动几分钟,才能关机的问题

把强制关机的等待时间缩短即可。 编辑 /etc/systemd/system.conf 文件 sudo gedit /etc/systemd/system.conf把 #DefaultTimeoutStartSec90s修改为 #DefaultTimeoutStartSec10s改完之后重载一下&#xff1a; sudo systemctl daemon-reload然后关机再试一下&#xff0c;这样…...

word poi-tl 图表功能增强,插入图表折线图、柱状图、饼状图

目录 问题解决问题poi-tl介绍 功能实现引入依赖功能介绍 功能实例饼图模版代码效果图 雷达图&#xff08;模版同饼图&#xff09;代码效果图 柱状图&#xff08;模版同饼图&#xff09;代码效果图 附加CustomCharts 工具类CustomChartSingleSeriesRenderData 数据对象CustomCha…...

常见网络钓鱼类型

网络钓鱼是一种网络攻击&#xff0c;是指具有恶意动机的攻击者伪装欺骗人们并收集用户名或密码等敏感信息的一系列行为。由于网络钓鱼涉及心理操纵并依赖于人为失误(而不是硬件或软件漏洞)&#xff0c;因此被认定为是一种社会工程攻击。 1. 普通网络钓鱼&#xff08;群攻&…...

数字图像处理考研考点(持续更新)

一、数字图像基本概念 1、人眼视觉特性 &#xff08;1&#xff09;眼睛上有两类光感受器&#xff1a;锥状体和杆状体 锥状体(锥细胞)&#xff1a;约 700 万个&#xff0c;对颜色高度敏感&#xff0c;每个锥状体都连接到神经末梢&#xff0c;人可以充分地分辨图像细节。锥细胞…...

Spring Cloud Alibaba:一站式微服务解决方案

Spring Cloud Alibaba介绍 在当今的软件开发领域&#xff0c;微服务架构因其灵活性、可扩展性和独立性等优势而备受青睐。Spring Cloud Alibaba 作为一款强大的一站式微服务解决方案&#xff0c;为开发者提供了丰富的工具和组件&#xff0c;帮助他们轻松构建和管理复杂的微服务…...

ubuntu16.04部署dify教程

文章目录 1、克隆 Dify 源代码至本地环境2、加速Dify镜像文件下载3、启动 Dify4、访问 Dify5、更新 Dify6、常见问题及解决方案&#xff08;1&#xff09;容器restarting&#xff08;2&#xff09;日志文件上限&#xff08;3&#xff09;重置管理员密码&#xff08;4&#xff0…...

JavaWeb文件上传

文件上传总览 文件上传主要是指将本地文件&#xff08;包括但不限于图片、视频、音频等&#xff09;上传到服务器&#xff0c;提供其他用户浏览或下载的过程。在日常生活中&#xff0c;我们在很多情况下都需要使用文件上传功能&#xff0c;比如&#xff1a;发微博、发朋友圈等…...

软件工程——期末复习(3)

一、题目类(老师重点提到过的题目) 1、高可靠性是否意味着高可用性&#xff1f;试举例证明自己的观点&#xff1f; 答&#xff1a;高可靠性不意味着高可用性 可靠性说明系统已经准备好&#xff0c;马上可以使用&#xff1b;可用性是系统可以无故障的持续运行&#xff0c;是一…...

apache的BeanUtils的Converter被相互污染覆盖问题

问题描述 apache的BeanUtils工具集中用来把map对象转换为java对象的BeanUtils#populate方法会因为单例的原因其转换器Converter被相互污染覆盖问题 maven依赖 <dependency><groupId>commons-beanutils</groupId><artifactId>commons-beanutils</…...

TCP的“可靠性”(上)

目录 TCP的“可靠性”&#xff08;上&#xff09;确认应答&#xff08;可靠性传输的基础&#xff09;超时重传连接管理&#xff08;三次握手&#xff0c;四次挥手&#xff09; TCP的“可靠性”&#xff08;上&#xff09; 想必大家都或多或少的听说过TCP的特性&#xff1a;有连…...

超标量处理器设计笔记(5)虚拟存储器、地址转换、page fault

虚拟存储器 概述地址转换单级页表多级页表案例最好情况&#xff1a;虚拟地址是连续的最差情况&#xff1a;每个第二级 PT 都装有一项 增加级数 Page Fault 程序保护 概述 当程序比物理内存空间更大时&#xff0c;无法全部装在物理内存中&#xff0c;需要对程序进行切片 虚拟…...

SparkSQL 读写数据攻略:从基础到实战

目录 一、输入Source 1&#xff09;代码演示最普通的文件读取方式&#xff1a; 2&#xff09; 通过jdbc读取数据库数据 3) 读取table中的数据【hive】 二、输出Sink 实战一&#xff1a;保存普通格式 实战二&#xff1a;保存到数据库中 实战三&#xff1a;将结果保存在h…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)

上一章用到了V2 的概念&#xff0c;其实 Fiori当中还有 V4&#xff0c;咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务)&#xff0c;代理中间件&#xff08;ui5-middleware-simpleproxy&#xff09;-CSDN博客…...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域&#xff0c;Hive 作为 Hadoop 生态中重要的数据仓库工具&#xff0c;其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式&#xff0c;很多开发者常常陷入选择困境。本文将从底…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

手机平板能效生态设计指令EU 2023/1670标准解读

手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读&#xff0c;综合法规核心要求、最新修正及企业合规要点&#xff1a; 一、法规背景与目标 生效与强制时间 发布于2023年8月31日&#xff08;OJ公报&…...

libfmt: 现代C++的格式化工具库介绍与酷炫功能

libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库&#xff0c;提供了高效、安全的文本格式化功能&#xff0c;是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全&#xff1a…...

redis和redission的区别

Redis 和 Redisson 是两个密切相关但又本质不同的技术&#xff0c;它们扮演着完全不同的角色&#xff1a; Redis: 内存数据库/数据结构存储 本质&#xff1a; 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能&#xff1a; 提供丰…...

《Docker》架构

文章目录 架构模式单机架构应用数据分离架构应用服务器集群架构读写分离/主从分离架构冷热分离架构垂直分库架构微服务架构容器编排架构什么是容器&#xff0c;docker&#xff0c;镜像&#xff0c;k8s 架构模式 单机架构 单机架构其实就是应用服务器和单机服务器都部署在同一…...