Skip to content

第 4.2 章:3D 模型 (.p3d)

首页 | << 上一章:纹理 | 3D 模型 | 下一章:材质 >>


简介

DayZ 中每个物理对象——武器、服装、建筑、车辆、树木、岩石——都是存储在 Bohemia 专有 P3D 格式中的 3D 模型。P3D 格式远不止是网格容器:它编码了多个细节级别、碰撞几何体、动画选择、用于附件和效果的记忆点,以及用于可安装物品的代理位置。理解 P3D 文件的工作方式以及如何使用 Object Builder 创建它们,对于任何向游戏世界添加物理物品的模组来说都是必不可少的。

本章涵盖 P3D 格式结构、LOD 系统、命名选择、记忆点、代理系统、通过 model.cfg 的动画配置,以及从标准 3D 格式的导入工作流程。


目录


P3D 格式概述

P3D(Point 3D)是 Bohemia Interactive 的二进制 3D 模型格式,继承自 Real Virtuality 引擎并延续到 Enfusion。它是一种编译后的、引擎就绪的格式——你不能手动编写 P3D 文件。

关键特征

  • 二进制格式: 不可人类阅读。仅使用 Object Builder 创建和编辑。
  • 多 LOD 容器: 单个 P3D 文件包含多个 LOD(细节级别)网格,每个具有不同的用途。
  • 引擎原生: DayZ 引擎直接加载 P3D。不会发生运行时转换。
  • 二进制化 vs. 未二进制化: 来自 Object Builder 的源 P3D 文件是"MLOD"(可编辑的)。Binarize 将它们转换为"ODOL"(优化的、只读的)。游戏可以加载两者,但 ODOL 加载更快且更小。

你将遇到的文件类型

扩展名说明
.p3d3D 模型(MLOD 源文件和 ODOL 二进制化文件)
.rtmRuntime Motion —— 动画关键帧数据
.bisurf表面属性文件(与 P3D 一起使用)

MLOD vs. ODOL

属性MLOD(源文件)ODOL(二进制化)
创建者Object BuilderBinarize
可编辑
文件大小较大较小
加载速度较慢较快
使用场景开发发布
包含完整编辑数据、命名选择优化的网格数据

重要: 当你使用启用二进制化的方式打包 PBO 时,你的 MLOD P3D 文件会自动转换为 ODOL。如果你使用 -packonly 打包,MLOD 文件会按原样包含。两者都能在游戏中工作,但发布版本推荐使用 ODOL。


Object Builder

Object Builder 是 Bohemia 提供的用于创建和编辑 P3D 模型的工具。它包含在 Steam 上的 DayZ Tools 套件中。

核心功能

  • 使用顶点、边和面创建和编辑 3D 网格。
  • 在单个 P3D 文件中定义多个 LOD。
  • 为动画和纹理控制分配 命名选择(顶点/面组)。
  • 放置 记忆点 用于附件位置、粒子原点和声音来源。
  • 为可附加物品(弹匣、瞄准镜等)添加 代理对象
  • 将材质(.rvmat)和纹理(.paa)分配给面。
  • 从 FBX、OBJ 和 3DS 格式导入网格。
  • 导出经过验证的 P3D 文件供 Binarize 使用。

工作空间设置

Object Builder 需要设置 P: 驱动器(workdrive)。此虚拟驱动器提供引擎用于定位资产的统一路径前缀。

P:\
  DZ\                        <-- 原版 DayZ 数据(已提取)
  DayZ Tools\                <-- 工具安装
  MyMod\                     <-- 你的模组源目录
    data\
      models\
        my_item.p3d
      textures\
        my_item_co.paa

P3D 文件和材质中的所有路径都相对于 P: 驱动器根目录。例如,模型内的材质引用将是 MyMod\data\textures\my_item_co.paa

Object Builder 中的基本工作流程

  1. 创建或导入 你的网格几何体。
  2. 定义 LOD —— 至少创建 Resolution、Geometry 和 Fire Geometry LOD。
  3. 在 Resolution LOD 中 分配材质 给面。
  4. 为任何需要动画、纹理交换或代码交互的部分 命名选择
  5. 为附件、枪口闪光位置、弹壳抛出口等 放置记忆点
  6. 为可附加的物品(瞄准镜、弹匣、消音器)添加代理
  7. 使用 Object Builder 内置验证(Structure --> Validate)进行 验证
  8. 保存 为 P3D。
  9. 通过 Binarize 或 AddonBuilder 进行 构建

LOD 系统

P3D 文件包含多个 LOD(细节级别),每个服务于特定目的。引擎根据情况选择使用哪个 LOD——与摄像机的距离、物理计算、阴影渲染等。

LOD 类型

LOD分辨率值用途
Resolution 01.000最高细节视觉网格。物体靠近摄像机时渲染。
Resolution 11.100中等细节。中等距离渲染。
Resolution 21.200低细节。远距离渲染。
Resolution 3+1.300+额外的距离 LOD。
View Geometry特殊确定什么阻挡玩家视野(第一人称)。简化网格。
Fire Geometry特殊子弹和弹药的碰撞。必须是凸面或由凸面部分组成。
Geometry特殊物理碰撞。用于移动碰撞、重力、放置。必须是凸面或由凸面分解组成。
Shadow 0特殊投射阴影的网格(近距离)。
Shadow 1000特殊投射阴影的网格(远距离)。比 Shadow 0 简单。
Memory特殊仅包含命名点(无可见几何体)。用于附件位置、声音原点等。
Roadway特殊定义物体上的可行走表面(车辆、可进入内部的建筑)。
Paths特殊建筑的 AI 寻路提示。

LOD 分辨率值(视觉 LOD)

引擎使用基于距离和物体大小的公式来确定渲染哪个视觉 LOD:

选择的 LOD = (到物体的距离 * LOD 因子) / 物体包围球半径

较低的值 = 摄像机更近。引擎找到分辨率值与计算值最接近的 LOD。

在 Object Builder 中创建 LOD

  1. File --> New LOD 或右键点击 LOD 列表。
  2. 从下拉菜单中选择 LOD 类型。
  3. 对于视觉 LOD(Resolution),输入分辨率值。
  4. 为该 LOD 建模几何体。

各物品类型的 LOD 要求

物品类型必需 LOD推荐的额外 LOD
手持物品Resolution 0, Geometry, Fire Geometry, MemoryShadow 0, Resolution 1
服装Resolution 0, Geometry, Fire Geometry, MemoryShadow 0, Resolution 1, Resolution 2
武器Resolution 0, Geometry, Fire Geometry, View Geometry, MemoryShadow 0, Resolution 1, Resolution 2
建筑Resolution 0, Geometry, Fire Geometry, View Geometry, MemoryShadow 0, Shadow 1000, Roadway, Paths
车辆Resolution 0, Geometry, Fire Geometry, View Geometry, MemoryShadow 0, Roadway, Resolution 1+

Geometry LOD 规则

Geometry 和 Fire Geometry LOD 有严格的要求:

  • 必须是凸面的 或由多个凸面组件组成。引擎的物理系统需要凸面碰撞形状。
  • 命名选择必须匹配 Resolution LOD 中的那些(用于动画部分)。
  • 必须定义质量。 选择 Geometry LOD 中的所有顶点,通过 Structure --> Mass 分配质量。这决定了物体的物理重量。
  • 保持简单。 更少的三角形 = 更好的物理性能。武器的 Geometry LOD 可能有 20-50 个三角形,而视觉 LOD 有数千个。

命名选择

命名选择是 LOD 中被标记了名称的顶点、边或面的组。它们充当引擎和脚本用于操作模型部分的句柄。

命名选择的功能

用途示例选择名称使用者
动画bolt, trigger, magazinemodel.cfg 动画源
纹理交换camo, camo1, bodyconfig.cpp 中的 hiddenSelections[]
伤害纹理zbytek引擎伤害系统,材质交换
附件点magazine, optics, suppressor代理和附件系统

hiddenSelections(纹理交换)

模组制作者最常用的命名选择用途是 hiddenSelections —— 通过 config.cpp 在运行时交换纹理的能力。

在 P3D 模型中(Resolution LOD):

  1. 选择应可重新纹理化的面。
  2. 命名选择(例如 camo)。

在 config.cpp 中:

cpp
class MyRifle: Rifle_Base
{
    hiddenSelections[] = {"camo"};
    hiddenSelectionsTextures[] = {"MyMod\data\my_rifle_co.paa"};
    hiddenSelectionsMaterials[] = {"MyMod\data\my_rifle.rvmat"};
};

这允许使用不同纹理创建同一模型的不同变体,而无需复制 P3D 文件。

创建命名选择

在 Object Builder 中:

  1. 选择你想要分组的顶点或面。
  2. 进入 Structure --> Named Selections(或按 Ctrl+N)。
  3. 点击 New,输入选择名称。
  4. 点击 Assign 将选定的几何体标记为该名称。

提示: 选择名称区分大小写。Camocamo 是不同的选择。约定是使用小写。

跨 LOD 的选择

命名选择必须跨 LOD 保持一致才能使动画工作:

  • 如果 bolt 选择存在于 Resolution 0 中,它也必须存在于 Geometry 和 Fire Geometry LOD 中(覆盖相应的碰撞几何体)。
  • 如果动画部分应投射正确的阴影,Shadow LOD 也应有该选择。

记忆点

记忆点是在 Memory LOD 中定义的命名位置。它们在游戏中没有视觉表现——它们定义引擎和脚本引用的空间坐标,用于定位效果、附件、声音等。

常用记忆点

点名称用途
usti hlavne枪口位置(子弹起源、枪口闪光出现的位置)
konec hlavne枪管末端(与 usti hlavne 一起定义枪管方向)
nabojnicestart弹壳抛出口起点(弹壳出现的位置)
nabojniceend弹壳抛出口终点(抛出方向)
handguard护手附件点
magazine弹匣井位置
optics瞄准镜导轨位置
suppressor消音器安装位置
trigger扳机位置(用于手部 IK)
pistolgrip手枪握把位置(用于手部 IK)
lefthand左手握持位置
righthand右手握持位置
eye眼睛位置(用于第一人称视角对齐)
pilot驾驶员/飞行员座位位置(车辆)
light_l / light_r左/右前灯位置(车辆)

方向性记忆点

许多效果需要位置和方向两者。这通过成对的记忆点实现:

usti hlavne  ------>  konec hlavne
(枪口起点)          (枪口终点)

方向向量为:konec hlavne - usti hlavne

在 Object Builder 中创建记忆点

  1. 在 LOD 列表中切换到 Memory LOD
  2. 在所需位置创建一个顶点。
  3. 通过 Structure --> Named Selections 命名它:用点名称创建一个选择,并将单个顶点分配给它。

注意: Memory LOD 应 包含命名点(单独的顶点)。不要在 Memory LOD 中创建面或边。


代理系统

代理定义了其他 P3D 模型可以附加的位置。当你看到弹匣插入武器、瞄准镜安装在导轨上或消音器拧到枪管上时——那些都是代理附加的模型。

代理的工作原理

代理是放置在 Resolution LOD 中的特殊引用,指向另一个 P3D 文件。引擎在代理的位置和方向渲染代理引用的模型。

代理命名约定

代理名称遵循模式:proxy:\path\to\model.p3d

对于武器上的附件代理,标准名称是:

代理路径附件类型
proxy:\dz\weapons\attachments\magazine\mag_placeholder.p3d弹匣槽
proxy:\dz\weapons\attachments\optics\optic_placeholder.p3d瞄准镜导轨
proxy:\dz\weapons\attachments\suppressor\sup_placeholder.p3d消音器安装
proxy:\dz\weapons\attachments\handguard\handguard_placeholder.p3d护手槽
proxy:\dz\weapons\attachments\stock\stock_placeholder.p3d枪托槽

在 Object Builder 中添加代理

  1. 在 Resolution LOD 中,将 3D 光标放置在附件应出现的位置。
  2. 进入 Structure --> Proxy --> Create
  3. 输入代理路径(例如 dz\weapons\attachments\magazine\mag_placeholder.p3d)。
  4. 代理显示为一个指示位置和方向的小箭头。
  5. 旋转和定位代理以正确对齐附件几何体。

代理索引

每个代理有一个索引号(从 1 开始)。当模型有多个相同类型的代理时,索引用于区分它们。索引在 config.cpp 中引用:

cpp
class MyWeapon: Rifle_Base
{
    class Attachments
    {
        class magazine
        {
            type = "magazine";
            proxy = "proxy:\dz\weapons\attachments\magazine\mag_placeholder.p3d";
            proxyIndex = 1;
        };
    };
};

Model.cfg 动画配置

model.cfg 文件定义 P3D 模型的动画。它将动画源(由游戏逻辑驱动)映射到命名选择上的变换。

基本结构

cpp
class CfgModels
{
    class Default
    {
        sectionsInherit = "";
        sections[] = {};
        skeletonName = "";
    };

    class MyRifle: Default
    {
        skeletonName = "MyRifle_skeleton";
        sections[] = {"camo"};

        class Animations
        {
            class bolt_move
            {
                type = "translation";
                source = "reload";        // 引擎动画源
                selection = "bolt";       // P3D 中的命名选择
                axis = "bolt_axis";       // 轴记忆点对
                memory = 1;               // 轴在 Memory LOD 中定义
                minValue = 0;
                maxValue = 1;
                offset0 = 0;
                offset1 = 0.05;           // 5cm 平移
            };

            class trigger_move
            {
                type = "rotation";
                source = "trigger";
                selection = "trigger";
                axis = "trigger_axis";
                memory = 1;
                minValue = 0;
                maxValue = 1;
                angle0 = 0;
                angle1 = -0.4;            // 弧度
            };
        };
    };
};

class CfgSkeletons
{
    class Default
    {
        isDiscrete = 0;
        skeletonInherit = "";
        skeletonBones[] = {};
    };

    class MyRifle_skeleton: Default
    {
        skeletonBones[] =
        {
            "bolt", "",          // "骨骼名称", "父骨骼"("" = 根级别)
            "trigger", "",
            "magazine", ""
        };
    };
};

动画类型

类型关键字运动控制方式
平移translation沿轴线性移动offset0 / offset1(米)
旋转rotation围绕轴旋转angle0 / angle1(弧度)
固定轴旋转rotationX围绕固定世界轴旋转angle0 / angle1
隐藏hide显示/隐藏选择hideValue 阈值

动画源

动画源是引擎提供的驱动动画的值:

范围说明
reload0-1武器重新装弹阶段
trigger0-1扳机扣下
zeroing0-N武器归零设置
isFlipped0-1机械瞄准具翻转状态
door0-1门打开/关闭
rpm0-N车辆引擎转速
speed0-N车辆速度
fuel0-1车辆燃油量
damper0-1车辆悬挂

从 FBX/OBJ 导入

大多数模组制作者在外部工具(Blender、3ds Max、Maya)中创建 3D 模型,然后导入到 Object Builder 中。

支持的导入格式

格式扩展名备注
FBX.fbx最佳兼容性。导出为 FBX 2013 或更高版本(二进制)。
OBJ.objWavefront OBJ。仅简单网格数据(无动画)。
3DS.3ds旧版 3ds Max 格式。每个网格限制为 65K 顶点。

导入工作流程

第 1 步:在你的 3D 软件中准备

  • 模型应居中于原点。
  • 应用所有变换(位置、旋转、缩放)。
  • 缩放:1 单位 = 1 米。DayZ 使用米。
  • 三角化网格(Object Builder 使用三角形)。
  • UV 展开模型。
  • 导出为 FBX(二进制,无动画,Y 轴朝上或 Z 轴朝上——Object Builder 两者都能处理)。

第 2 步:导入到 Object Builder

  1. 打开 Object Builder。
  2. File --> Import --> FBX(或 OBJ/3DS)。
  3. 检查导入设置:
    • 缩放因子(如果源文件以米为单位,应为 1.0)。
    • 轴转换(如果需要,Z 轴朝上转为 Y 轴朝上)。
  4. 网格出现在新的 Resolution LOD 中。

第 3 步:导入后设置

  1. 将材质分配给面(选择面,右键点击 --> Face Properties)。
  2. 创建额外的 LOD(Geometry、Fire Geometry、Memory、Shadow)。
  3. 简化碰撞 LOD 的几何体(移除小细节,确保凸面性)。
  4. 添加命名选择、记忆点和代理。
  5. 验证并保存。

Blender 特定提示

  • 如果可用,使用 Blender DayZ Toolbox 社区插件——它简化了导出设置。
  • 导出时选择:Apply ModifiersTriangulate FacesApply Scale
  • 在 FBX 导出对话框中设置 Forward: -Z ForwardUp: Y Up
  • 在 Blender 中将网格对象命名为与预期的命名选择匹配——一些导入器会保留对象名称。

常见模型类型

武器

武器是最复杂的 P3D 模型,需要:

  • 高多边形 Resolution LOD(5,000-20,000 三角形)
  • 多个命名选择(bolt、trigger、magazine、camo 等)
  • 完整的记忆点集(枪口、弹壳抛出、握持位置)
  • 多个代理(弹匣、瞄准镜、消音器、护手、枪托)
  • model.cfg 中的骨骼和动画
  • View Geometry 用于第一人称遮挡

服装

服装模型绑定到角色骨骼:

  • Resolution LOD 遵循角色的骨骼结构
  • 用于纹理变体的命名选择(camocamo1
  • 较简单的碰撞几何体
  • 无代理(通常)
  • hiddenSelections 用于颜色/迷彩变体

建筑

建筑有独特的要求:

  • 大型、详细的 Resolution LOD
  • Roadway LOD 用于可行走表面(地板、楼梯)
  • Paths LOD 用于 AI 导航
  • View Geometry 防止看穿墙壁
  • 多个 Shadow LOD 用于不同距离的性能
  • 命名选择用于可打开的门和窗户

车辆

车辆结合了许多系统:

  • 带动画部件(车轮、门、引擎盖)的详细 Resolution LOD
  • 包含许多骨骼的复杂骨骼
  • Roadway LOD 用于站在卡车货箱中的乘客
  • 记忆点用于灯光、排气、驾驶员位置、乘客座位
  • 多个代理用于附件(车轮、门)

常见错误

1. 缺少 Geometry LOD

症状: 物体没有碰撞。玩家和子弹穿过它。 修复: 创建一个带有简化凸面网格的 Geometry LOD。为顶点分配质量。

2. 非凸面碰撞形状

症状: 物理故障,物体不规则弹跳,物品穿过表面。 修复: 将复杂形状分解为 Geometry LOD 中的多个凸面组件。每个组件必须是封闭的凸面实体。

3. 命名选择不一致

症状: 动画仅在视觉上工作但不影响碰撞,或阴影不动画化。 修复: 确保 Resolution LOD 中存在的每个命名选择也存在于 Geometry、Fire Geometry 和 Shadow LOD 中。

4. 错误的缩放

症状: 物体在游戏中巨大或微小。 修复: 验证你的 3D 软件使用米作为单位。DayZ 角色大约 1.8 米高。

5. 缺少记忆点

症状: 枪口闪光出现在错误的位置,附件漂浮在空中。 修复: 创建 Memory LOD 并在正确位置添加所有必需的命名点。

6. 未定义质量

症状: 物体无法被拾取,或物理交互行为异常。 修复: 选择 Geometry LOD 中的所有顶点,通过 Structure --> Mass 分配质量。


最佳实践

  1. 从 Geometry LOD 开始。 先勾画出碰撞形状,然后在其上构建视觉细节。这可以防止创建美丽但无法正确碰撞的模型这一常见错误。

  2. 使用参考模型。 从游戏数据中提取原版 P3D 文件,并在 Object Builder 中研究它们。它们准确显示引擎对每种物品类型的期望。

  3. 频繁验证。 在每次重大更改后使用 Object Builder 的 Structure --> Validate。在它们变成神秘的游戏内 bug 之前修复警告。

  4. 保持 LOD 三角形数量成比例。 Resolution 0 可能有 10,000 个三角形;Resolution 1 应有约 5,000 个;Geometry 应有约 100-500 个。每个级别大幅减少。

  5. 描述性地命名选择。 使用 bolt_carrier 而不是 sel01。你未来的自己(和其他模组制作者)会感谢你。

  6. 先使用文件补丁测试。 在提交完整 PBO 构建之前,通过文件补丁模式加载你的未二进制化 P3D。这能更快地发现大多数问题。

  7. 记录记忆点。 保留一个参考图像或文本文件,列出所有记忆点及其预期位置。复杂武器可能有 20 多个点。


导航

上一章上级下一章
4.1 纹理第 4 部分:文件格式与 DayZ Tools4.3 材质

Released under CC BY-SA 4.0 | Code examples under MIT License