CD Code Digest Hub /GTA V · v2

模型信息(ModelInfo / Archetype)

35 分钟阅读 9 个章节 1 张图

本页解释 game/modelinfo:GTAV 的 archetype(模型信息)类层次如何在框架 fwArchetype 之上扩展、各类模型信息由哪种数据(ITYP、peds.meta、vehicles.meta、武器 archetype meta 等)创建、CModelInfo 如何注册工厂/存储并作为流式模块装载模型资源,2dEffect(archetype 扩展)的注册,以及 game/game/ModelIndices.* 的“按名字延迟绑定的模型索引”机制。

背景与相关页面#

相关源码文件#

文件内容
game/modelinfo/BaseModelInfo.h/.cppCBaseModelInfo : fwArchetype、ModelInfoType、扩展类型、模型标志/特殊属性
game/modelinfo/ModelInfo.h/.cpp、ModelInfo_Factories.hCModelInfo:工厂与 2dEffect/实体扩展注册、Add*Model、PostLoad、流式模块
game/modelinfo/TimeModelInfo.*、MloModelInfo.*、CompEntityModelInfo.*、WeaponModelInfo.*时间模型、MLO、复合实体、武器模型
game/modelinfo/PedModelInfo.*、PedModelInfoData.pscped 模型信息与 peds.meta 结构
game/modelinfo/VehicleModelInfo*.*、*.psc、ModelSeatInfo.*车辆模型信息及颜色/改装/车牌/警笛/灯光/变体/座位
game/scene/2dEffect.h/.cppC2dEffect 与各种属性类
game/scene/loader/MapData_Buildings.psc、MapData_Interiors.psc、MapData_Composite.pscarchetype 定义的 parser 结构
game/game/ModelIndices.h/.cppCModelIndex 与 MI_* 全局模型索引

1. 类层次与类型#

ModelInfoType 从框架的 AF_TYPE_USER 之后编号:MI_TYPE_BASE(1)、MLO(2)、TIME(3)、WEAPON(4)、VEHICLE(5)、PED(6)、COMPOSITE(7),MI_HIGHEST_FACTORY_ID = NUM_MI_TYPES-1 src/dev_ng/game/modelinfo/BaseModelInfo.h:69-80。

证据:CBaseModelInfo : fwArchetype src/dev_ng/game/modelinfo/BaseModelInfo.h:283;CTimeModelInfo src/dev_ng/game/modelinfo/TimeModelInfo.h:59;CMloModelInfo src/dev_ng/game/modelinfo/MloModelInfo.h:90;CCompEntityModelInfo src/dev_ng/game/modelinfo/CompEntityModelInfo.h:20;CWeaponModelInfo src/dev_ng/game/modelinfo/WeaponModelInfo.h:29;CVehicleModelInfo src/dev_ng/game/modelinfo/VehicleModelInfo.h:729;CPedModelInfo src/dev_ng/game/modelinfo/PedModelInfo.h:280。

类型数据来源主要职责证据
CBaseModelInfoITYP CBaseArchetypeDef静态/道具模型;drawable/碎片/drawable 字典引用、2dEffect、浮力、自定义着色器效果类型、LOD 骨骼映射src/dev_ng/game/modelinfo/BaseModelInfo.h:547-572
CTimeModelInfoITYP CTimeArchetypeDef{m_timeFlags}只在某些小时显示;CTimeInfo::m_hoursOnOff 24 位小时掩码,第 24 位表示可在可见时切换src/dev_ng/game/modelinfo/TimeModelInfo.h:17-60、src/dev_ng/game/scene/loader/MapData_Buildings.psc:12-14
CMloModelInfoITYP CMloArchetypeDef内景:实体定义、房间、门户、实体集、时间周期修改器、每房间音频设置;CreateEntity 返回 CInteriorInstsrc/dev_ng/game/modelinfo/MloModelInfo.h:90-181
CCompEntityModelInfoITYP m_compositeEntityTypesRayfire:开始/结束模型哈希、开始/结束 IMAP、PTFX 资产、动画与特效src/dev_ng/game/modelinfo/CompEntityModelInfo.h:19-60
CWeaponModelInfoWEAPON_METADATA_FILE武器模型:txd、PTFX、LOD 距离、HD 距离、表情集;有 HD 请求队列src/dev_ng/game/modelinfo/WeaponModelInfo.h:29-60、src/dev_ng/game/modelinfo/WeaponModelInfo.h:106
CVehicleModelInfoVEHICLE_METADATA_FILE(vehicles.meta)车辆:操控/布局/颜色/改装/车牌/警笛/灯光/座位等(详见车辆页);HD 请求、静态数据src/dev_ng/game/modelinfo/VehicleModelInfo.h:1195、src/dev_ng/game/modelinfo/VehicleModelInfo.h:1295、src/dev_ng/game/modelinfo/VehicleModelInfo.h:1663
CPedModelInfoPED_METADATA_FILE(peds.meta)ped:组件文件、道具文件、性格、感知、胶囊、布局等(详见 ped 页);HD 请求、常驻对象src/dev_ng/game/modelinfo/PedModelInfo.h:1327、src/dev_ng/game/modelinfo/PedModelInfo.h:1358

1.1 CBaseModelInfo 的布局与标志#

  • 构造/析构函数应为空,所有初始化放在 Init()/Shutdown()(因为对象由工厂存储块批量分配)src/dev_ng/game/modelinfo/BaseModelInfo.h:299-316。
  • 尺寸断言 CompileTimeAssertSize(CBaseModelInfo, 112, 176)(32/64 位);m_type 仅 5 位,另有 m_bLeakObjectsIntentionally、m_bNeverDummy 等对象专用位(注释建议将来拆为扩展)src/dev_ng/game/modelinfo/BaseModelInfo.h:547-606。
  • 工具侧加载标志 CBaseArchetypeDefLoadFlags(32 位,部分注释标为未使用)src/dev_ng/game/modelinfo/BaseModelInfo.h:131-166 在 ConvertLoadFlagsAndAttributes 中被翻译成运行时 MODEL_* 标志:如 FLAG_IS_TYPE_OBJECT→MODEL_IS_TYPE_OBJECT(决定 dummy/object)、FLAG_DOOR_PHYSICS→MODEL_USES_DOOR_PHYSICS(决定创建 CDoor)、FLAG_HAS_CLOTH→NeverDummy(环境布料只能作为真实对象工作)、FLAG_SUPPRESS_HD_TXDS 取反为 HD 贴图能力 src/dev_ng/game/modelinfo/BaseModelInfo.h:168-200、src/dev_ng/game/modelinfo/BaseModelInfo.cpp:164-206。
  • 互斥特殊属性占第 26–31 位(ATOMIC_L_BITSHIFT=26):梯子、红绿灯、可弯曲植物、各种门、MLO 水位、灌木、单轴旋转、动态掩体包围盒、垃圾、时钟、路灯等;红绿灯会开启 PreRender 效果 src/dev_ng/game/modelinfo/BaseModelInfo.h:202-246、src/dev_ng/game/modelinfo/BaseModelInfo.cpp:196-205。InitArchetypeFromDefinition 会对超出 5 位的属性告警并截断,!__FINAL 下 FLAG_IS_DEBUG 强制为调试属性 src/dev_ng/game/modelinfo/BaseModelInfo.cpp:208-228。
  • LOD 距离:GetLodDistance() 返回未缩放距离 × g_LodScale.GetGlobalScale()(见 LOD 页)src/dev_ng/game/modelinfo/BaseModelInfo.h:325。

2. CModelInfo:工厂、存储与注册#

CModelInfo::Init(INIT_CORE) 是 archetype 体系的组合根 src/dev_ng/game/modelinfo/ModelInfo.cpp:529-674:

  1. fwArchetypeManager::Init(MI_HIGHEST_FACTORY_ID)、fwExtensionManager::Init(EXT_HIGHEST_FACTORY_ID)。
  2. 初始化 7 个 fwArchetypeDynamicFactory<T> 存储(容量来自 CGameConfig 的 CModelInfoConfig;基础模型存储容量 = 最大 archetype 索引),并 RegisterArchetypeFactory(MI_TYPE_*, store) src/dev_ng/game/modelinfo/ModelInfo.cpp:545-560、src/dev_ng/game/modelinfo/ModelInfo.cpp:116-123。
  3. parser 结构 → 工厂关联:fwMapTypes::AssociateArchetypeDef(CBaseArchetypeDef→MI_TYPE_BASE, CTimeArchetypeDef→TIME, CMloArchetypeDef→MLO, CCompositeEntityArchetypeDef→COMPOSITE) src/dev_ng/game/modelinfo/ModelInfo.cpp:562-565。这就是 ITYP 中不同定义类型被实例化成不同 C++ 类的动态装配点(CMapTypes::AllocArchetypeStorage 按结构名哈希查表)。武器/车辆/ped 不出现在 ITYP 中,而是由各自的 meta 文件创建。
  4. 为 GLOBAL 段预分配存储块(基础模型块“用于门户与灯光 archetype”、复合、武器、车辆、ped)src/dev_ng/game/modelinfo/ModelInfo.cpp:571-575。
  5. 2dEffect(archetype 扩展)工厂:14 个 fwArchetypeExtensionFactory<T>(梯子、程序化对象、爆炸、粒子、贴花、风扰动、光柱、滚动条、出生点、浮力、音频、世界点、表情、音频碰撞),Register2dEffectFactory(EXT_TYPE_*),并 CMapTypes::AssociateExtensionDef(CExtensionDef* 结构→EXT_TYPE_*) src/dev_ng/game/modelinfo/ModelInfo.cpp:579-640、src/dev_ng/game/modelinfo/ModelInfo.cpp:125-139。
  6. 实体扩展工厂(挂在实体而非 archetype 上):门、灯光、出生点覆盖、布料碰撞,使用各自的池,并 fwMapData::AssociateExtensionDef(CExtensionDefDoor→EXT_TYPE_DOOR, …) src/dev_ng/game/modelinfo/ModelInfo.cpp:642-668。
  7. fwMapTypes::SetMaxFactoryId(NUM_MI_TYPES);CVehicleModelInfo::ConstructStaticData() src/dev_ng/game/modelinfo/ModelInfo.cpp:670-673。

INIT_BEFORE_MAP_LOADED 清空 archetype 指针存储;INIT_SESSION 为武器/车辆/ped 追加 fwFactory::EXTRA 段(DLC 模型)存储块 src/dev_ng/game/modelinfo/ModelInfo.cpp:675-686。CModelInfo::Init 在 CScene::Init 中以 INIT_CORE 调用,并另通过 gameSkeleton 注册其他模式 src/dev_ng/game/scene/scene.cpp:628、src/dev_ng/game/Core/game.cpp:2114。

扩展类型编号:实体扩展 EXT_TYPE_DOOR/LIGHT/SPAWN_POINT_OVERRIDE/CLOTH_COLLISIONS;archetype 扩展从 20 起(LADDER=20 … EXPRESSION=32,AUDIO_COLLISIONS=34)以避免与 MI 类型重叠 src/dev_ng/game/modelinfo/BaseModelInfo.h:86-110。对应的运行时 2dEffect 类型 e2dEffectType(ET_LIGHT=0、ET_PARTICLE、ET_EXPLOSION、ET_DECAL、ET_WINDDISTURBANCE、ET_PROCEDURALOBJECTS=12、ET_COORDSCRIPT、ET_LADDER、ET_AUDIOEFFECT、ET_SPAWN_POINT=17、ET_LIGHT_SHAFT、ET_SCROLLBAR、ET_BUOYANCY=22、ET_EXPRESSION、ET_AUDIOCOLLISION)src/dev_ng/game/scene/2dEffect.h:35-67。灯光 2dEffect(CLightAttr)单独存放在 GetLightArray(),其余在 Get2dEffectsNoLights() src/dev_ng/game/scene/2dEffect.h:261、src/dev_ng/game/scene/Entity.cpp:1390-1391。

2.1 添加模型#

API行为证据
AddBaseModel(name)从 GLOBAL 段创建,RegisterPermanentArchetypesrc/dev_ng/game/modelinfo/ModelInfo.cpp:893-908
AddWeaponModel(name, permanent, mapTypeDefIndex)常驻或流式注册;按 MOD_<name> 查找音频碰撞设置src/dev_ng/game/modelinfo/ModelInfo.cpp:910-934
AddVehicleModel(...)常驻或流式注册(容量按段检查)src/dev_ng/game/modelinfo/ModelInfo.cpp:935-955
AddPedModel(...)所有构建都检查重名哈希,重复则断言并返回 NULL(注释:重复 archetype 会在很久以后致命)src/dev_ng/game/modelinfo/ModelInfo.cpp:958-985
AddCompEntityModel(name)GLOBAL 常驻src/dev_ng/game/modelinfo/ModelInfo.cpp:987-997

“常驻”(permanent)与“流式”(streamed)archetype 的区别是:前者在全局段,关卡装载后 fwArchetypeManager::LockPermanentArchetypes() 锁定 src/dev_ng/game/scene/FileLoader.cpp:2347;后者属于某个 ITYP 槽位,随 ITYP 流入流出(DLC 的 ped 元数据以 permanent=false, fwFactory::EXTRA 加入)src/dev_ng/game/modelinfo/PedModelInfo.cpp:135-137。

2.2 PostLoad:把模型绑定到资源#

CModelInfo::PostLoad() 遍历所有 archetype:drawable 字典型、复合型、碎片型模型都调用 CStreaming::RegisterDummyObject(name, modelIndex, CModelInfo::GetStreamingModuleId()) 在流式系统中登记一个“虚拟对象”(其依赖是真正的 drawable/frag/txd 资源);若同名资源既是独立文件又在字典中,断言名称冲突并清除引用 src/dev_ng/game/modelinfo/ModelInfo.cpp:1002-1060。非常驻 ITYP 的 archetype 在 CMapTypes::PostConstruct 里逐个 PostLoad(pArchetype) src/dev_ng/game/scene/loader/mapTypes.cpp:201-213。

3. 作为流式模块:CModelInfoStreamingModule#

模型信息本身是 strStreamingModule(fwArchetypeStreamingModule 派生),“装载一个模型”= 等待其所有依赖资源装载完毕后初始化 master 数据 src/dev_ng/game/modelinfo/ModelInfo.cpp:161-182:

  • 依赖(GetDependencies):框架依赖(drawable/frag/dwd + txd)之外,加上动画字典、表情字典/表情集(递归)、主 PTFX 资产;基础模型若有 ET_EXPRESSION 扩展则把表情与 creature 元数据加入依赖;ped 加道具 DWD、组件 DWD、混合形状;车辆加 GetStreamingDependencies 结果与绳索贴图 src/dev_ng/game/modelinfo/ModelInfo.cpp:224-404。
  • Load:依赖满足后按 drawable 类型调用 InitMasterDrawableData 或 InitMasterFragData,并通知 gPopStreaming.ModelHasBeenStreamedIn;Remove 反之并 SetHasLoaded(false) src/dev_ng/game/modelinfo/ModelInfo.cpp:406-463。
  • Register/RemoveSlot 被禁止(断言):槽位由 archetype 管理器决定 src/dev_ng/game/modelinfo/ModelInfo.cpp:197-206。
  • 临时流式槽:CArchetypeStreamSlot 池只有 255 个(注释:基础模型信息里只存了 8 位),AssignLocalIndexToModelInfo2 为尚无流式槽的 archetype 临时分配并登记虚拟对象;请求状态的槽在 RECYCLE_TIME=5 帧的计时器循环后被回收 src/dev_ng/game/modelinfo/ModelInfo.h:38-66、src/dev_ng/game/modelinfo/ModelInfo.cpp:107、src/dev_ng/game/modelinfo/ModelInfo.cpp:1108-1189。

游戏代码请求模型统一走 CModelInfo::RequestAssets/HaveAssetsLoaded/SetAssetRequiredFlag 等包装 src/dev_ng/game/modelinfo/ModelInfo.h:196-216;场景流式器请求失败时会 FlagModelAsMissing,避免永远卡在加载画面(见流式页)。

3.1 HD 资产#

车辆、武器、ped 各有 ms_HDStreamRequests 链表:请求 HD 碎片/贴图后,UpdateHDRequests 在全部加载时给 HD 碎片加引用、设置 HD 着色器效果、标记已加载并删除请求(车辆)src/dev_ng/game/modelinfo/VehicleModelInfo.cpp:7888-7913。CScene::Update 在 CGameWorld::Process 之后立即调用车辆与武器的 UpdateHDRequests,注释说明这样新请求能在同帧被处理 src/dev_ng/game/scene/scene.cpp:813-819。

4. Meta 文件的解析入口#

数据入口解析方式证据
peds.meta(PED_METADATA_FILE)CFileLoader::LoadPedMetaData → LoadObjectTypesXml → CPedModelInfo::LoadPedMetaFile先载入性格与感知数据;fwPsoStoreLoader::LoadDataIntoObject 读 InitDataList;设置常驻 TXD 与常驻动画;逐个 AddPedModel + Init(initData);TXD 父子关系src/dev_ng/game/scene/FileLoader.cpp:1372-1395、src/dev_ng/game/scene/FileLoader.cpp:2692-2697、src/dev_ng/game/modelinfo/PedModelInfo.cpp:1931-1990
武器 archetype(WEAPON_METADATA_FILE)LoadObjectTypesXmlPSO 读 CWeaponModelInfo::InitDataList;AddWeaponModel + Init + SetIsTypeObject(true);非常驻时立即 PostLoadsrc/dev_ng/game/scene/FileLoader.cpp:2698-2724、src/dev_ng/game/modelinfo/WeaponModelInfoData.psc:6-21
vehicles.meta(VEHICLE_METADATA_FILE)CFileLoader::LoadVehicleMetaData → CVehicleModelInfo::LoadVehicleMetaFilePARSER.CreateAndLoadAnyType(..., "meta")(剔除其他平台数据);常驻 TXD(不能重映射公共 TXD)、HD 共享 TXD、常驻动画;已安装游戏时逐个 AddVehicleModel + Initsrc/dev_ng/game/scene/FileLoader.cpp:1397-1420、src/dev_ng/game/modelinfo/VehicleModelInfo.cpp:719-779
ITYP archetypefwMapTypes 流式装载 → CMapTypes 回调见 map-data-and-lod.md 第 3.2 节src/dev_ng/game/scene/loader/mapTypes.cpp:30-250

parser 结构定义位于 PedModelInfoData.psc(CPedModelInfo::InitData 等)src/dev_ng/game/modelinfo/PedModelInfoData.psc:90-172、VehicleModelInfoData.psc(CVehicleModelInfo::InitData 等)src/dev_ng/game/modelinfo/VehicleModelInfoData.psc:195-353,以及车辆颜色/改装/车牌/警笛/灯光/标志的独立 .psc。装载顺序约束:ped 元数据依赖胶囊、组件集、任务数据等,必须在其之后(见地图页第 1 节)。

5. ModelIndices:按名字延迟绑定的模型索引#

头文件注释称其“有点 hack”:代码需要引用某些特定模型(手机、风车、警车、船、动物、玩家模型、降落伞、DLC 道具等),但模型索引在构建间会变化 src/dev_ng/game/game/ModelIndices.h:3-14。解决方案是 CModelIndex:

  • 以 strStreamingObjectName(名字 + 预计算哈希)静态构造,构造时把自己挂到全局单链表 sm_pFirst;#pragma init_seg(lib) 让这些全局对象在库初始化阶段先于普通全局对象构造 src/dev_ng/game/game/ModelIndices.cpp:11-35。
  • MatchAllModelStrings() 遍历链表,先把索引重置为无效(注释:支持剧集/DLC 重启后模型消失),再用 CModelInfo::GetModelIdFromName 解析;找不到只告警 src/dev_ng/game/game/ModelIndices.cpp:37-60。__ASSERT 下匹配后再创建新的 CModelIndex 会断言 src/dev_ng/game/game/ModelIndices.cpp:28。
  • 隐式转换为 u32/fwModelId,拷贝被禁止(断言)src/dev_ng/game/game/ModelIndices.h:29-59。
  • 调用时机:关卡 LoadMap 之后 src/dev_ng/game/Core/game.cpp:1351、src/dev_ng/game/Core/game.cpp:1361;会话初始化加载 DLC 后再次调用 src/dev_ng/game/Core/gamesessionstatemachine.cpp:1519;DLC 内容变化时 src/dev_ng/game/scene/ExtraContent.cpp:1671。

ModelIndices.h 声明了 369 个 extern CModelIndex,按“Objects / Cars / Law enforcement / Heist3 / CnC / Heist4 / Tuner / Peds / Animal / Player / Parachute …”分节,之后还有一段“模型名哈希常量” src/dev_ng/game/game/ModelIndices.h:61-516。

约束与边界行为#

  • archetype 总数上限:基础模型存储容量即 GetMaxArchetypeIndex();ITYP 超限时触发紧急卸载(见地图页)src/dev_ng/game/modelinfo/ModelInfo.cpp:545。
  • 各类型容量由 CGameConfig 的模型信息配置决定,超出时 Add*Model 断言 src/dev_ng/game/modelinfo/ModelInfo.cpp:897、src/dev_ng/game/modelinfo/ModelInfo.cpp:939。配置文件内容不在 src 树中。
  • 临时流式槽仅 255 个,且请求状态的槽会按 5 帧周期回收,适用于短期查询而非长期持有 src/dev_ng/game/modelinfo/ModelInfo.h:55-58。
  • CModelInfo 中存在 MP 玩家模型 ID 的混淆副本与校验函数(CopyOutCurrentMPPedMapping/ValidateCurrentMPPedMapping,源码注释称用于发现 mod),属于反篡改范畴,不展开 src/dev_ng/game/modelinfo/ModelInfo.h:109-110。

未决问题 / 证据不足#

  • CBaseModelInfo::InitMasterDrawableData/InitMasterFragData(自定义着色器效果、浮力、LOD 骨骼映射、布料)未逐行展开 src/dev_ng/game/modelinfo/BaseModelInfo.cpp:336、src/dev_ng/game/modelinfo/BaseModelInfo.cpp:1153。
  • ModelSeatInfo(3479 行)、VehicleModelInfoVariation、VehicleModelInfoColors 等车辆子数据只作为文件列出,内容归车辆页。
  • CMloModelInfo::InitArchetypeFromDefinition 对房间/门户数据的处理与音频设置缓存未展开。