|
|
(28 intermediate revisions by the same user not shown) |
Line 1: |
Line 1: |
| {{LanguageBar}} | | {{LanguageBar|Valve Map Format|title=Valve地图格式}} |
| {{tabsBar|main=MAP}}
| | '''Valve地图格式'''('''VMF''')是一种纯文本文件格式,用于存储原始(预编译)地图数据,由{{L|Valve Hammer Editor}}(4.0版起)用于保存生产阶段的地图和{{L|prefab|预置件}}。它以{{L|KeyValues}}格式存储所有地图笔刷和实体的信息,文件扩展名为".vmf"。 |
| The '''Valve Map Format''' ('''VMF''') is a plain-text file format that stores raw (pre-compile) map data, used by the [[Valve Hammer Editor]] (since version 4.0) to save production-stage maps and [[prefab]]s. It contains information on all map brushes and entities in the [[KeyValues]] format stored with a ".vmf" extension.
| |
|
| |
|
| A .vmf file is the source code of a map designed for use in the [[Source|engine]]. Like any source file it must be compiled to be used and is thus designed to be easy to read and work with rather than optimized for execution. Because of this a .vmf file is written in an easy to understand form of coding language common in dealings with the source engine. This is to be the documentation of everything defined within a .vmf file detailing what is what and how it's shown. This is not a tutorial with an end result, it is more like a lesson in the theory behind it. This documentation is written using files generated by Hammer 4.1 within the Jan 1st 2006 [[SDK Beta|Source SDK Beta]].
| | .vmf文件是专为{{Source}}{{Source|3}}设计的地图源代码。与任何源代码文件一样,它必须经过编译才能使用,因此设计目标是易于阅读和编辑而非执行效率。文件采用Source引擎常用的易读编码形式。本文档将详细说明.vmf文件中定义的所有内容,包括各项元素的含义及其表示方式。这不是带结果的教程,而是对其背后原理的解析。本文档基于2006年1月1日{{L|SDK Beta|Source SDK Beta}}中Hammer 4.1生成的文件编写。 |
|
| |
|
| == The structure of .vmf == | | == .vmf文件结构 == |
| The code structure in a .vmf is simple and easy to understand, it's also common in many other factors of the engine. This is a simple review of the structure for those first exposed and to set out the terms that things will be referred to as.
| | .vmf中的代码结构简单易懂,这种结构在引擎的许多其他部分也很常见。以下是面向初学者的结构概述及术语说明: |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| // This is a comment. | | // 这是注释 |
| ClassName_1
| | 类名_1 |
| { | | { |
| "Property_1" "Value_1" | | "属性_1" "值_1" |
| "Property_2" "Value_2" | | "属性_2" "值_2" |
| ClassName_2 | | 类名_2 |
| { | | { |
| "Property_1" "Value_1" | | "属性_1" "值_1" |
| } | | } |
| } | | } |
| </nowiki>}} | | </nowiki>}} |
|
| |
|
| The given names are merely placeholders using the naming techniques they will be referenced with; Classes, Properties and Values. Within this documentation each section will be laid out the same. It will have a title of the Class it is explaining followed by a simple introduction of what that Class defines. Underneath will be a code sample, and then each property and the valid data type will be stated along with an explanation. There are only a few data types a .vmf file could contain, they are generally standard data types and values but are listed for reference.
| | 所示名称仅为占位符,采用它们将被引用的命名规范:类(Classes)、属性(Properties)和值(Values)。本文档每节结构相同:标题为要解释的类名,随后简要说明该类定义的内容,下方提供代码示例,最后列出每个属性及其有效数据类型和解释。.vmf文件仅包含几种数据类型: |
| {| class=standard-table | | {| class=standard-table |
| !| Notation || Description | | !| 标记 || 说明 |
| |- | | |- |
| |int || Any integer value. | | |int || 整数值 |
| |- | | |- |
| |dec || Any decimal value. | | |dec || 十进制数值 |
| |- | | |- |
| |sz || Any string of characters. | | |sz || 字符串 |
| |- | | |- |
| |bool || A Boolean value of true/false in binary. | | |bool || 布尔值(true/false的二进制表示) |
| |- | | |- |
| |vertex || An XYZ location given by 3 decimal values separated by spaces. | | |vertex || XYZ坐标点,由3个用空格分隔的十进制值表示 |
| |- | | |- |
| |rgb || A color value using 3 integers between 0 and 255 separated by spaces corresponding to the Red channel, Green channel, and Blue channel, respectively. | | |rgb || 颜色值,使用3个0-255的整数(分别对应红/绿/蓝通道),空格分隔 |
| |} | | |} |
| The Properties and values will always come right under the code sample and be laid out in the following manner. The explanation will be in brief and cover only that Property.
| | 属性说明将紧接在代码示例下方,按以下格式呈现: |
|
| |
|
| | *'''属性_1 (数据类型):''' |
| | :解释该属性的含义及取值注意事项。 |
|
| |
|
| *'''property_1 (data_type):'''
| | 当某个属性需要单独解释,或是某类的属性实为另一个独立类时,将在代码示例下方添加链接说明。这表示该内容有独立章节解释,不包含在当前类定义中。所有属性定义后,将整体讨论该类及其属性对最终结果的影响。 |
| :This will explain what the property represents and any further notes on possible values.
| |
|
| |
|
| Sometimes the explanation cannot be brief, or a Property for one Class is in fact another different Class. When one line requires its own explanation it will be written as a link below the code sample. This merely indicates it is explained under its own title and is not included in the definitions for that Class. After each property is defined the Class will be discussed as a whole, along with the reasons behind the properties and how they affect the end result will be detailed.
| | === 常规结构 === |
| | .vmf文件的常规结构如下: |
| | {{pre|[[Zh/VMF_(Valve_Map_Format)#版本信息|versioninfo{}]] |
| | [[Zh/VMF_(Valve_Map_Format)#可视组(VisGroup)|visgroups{}]] |
| | [[Zh/VMF_(Valve_Map_Format)#视图设置|viewsettings{}]] |
| | [[Zh/VMF_(Valve_Map_Format)#世界|world{}]] |
| | [[Zh/VMF_(Valve_Map_Format)#实体|entity{}]] |
| | [[Zh/VMF_(Valve_Map_Format)#隐藏|hidden{}]] |
| | [[Zh/VMF_(Valve_Map_Format)#摄像机|cameras{}]] |
| | [[Zh/VMF_(Valve_Map_Format)#隔离区|cordon{}]]}} |
|
| |
|
| === Usual Structure ===
| | 各章节功能可以单击结构跳到对应说明。 |
| The usual structure of a vmf is as follows:
| |
| {{pre|[[Valve Map Format#Version info|versioninfo{}]]
| |
| [[Valve Map Format#VisGroups|visgroups{}]]
| |
| [[Valve Map Format#Viewsettings|viewsettings{}]]
| |
| [[Valve Map Format#World|world{}]]
| |
| [[Valve Map Format#Entity|entity{}]]
| |
| [[Valve Map Format#Hidden|hidden{}]]
| |
| [[Valve Map Format#Cameras|cameras{}]]
| |
| [[Valve Map Format#Cordon|cordon{}]]}}
| |
|
| |
|
| | 注意:顺序对Hammer不重要,但VBSP可能在特定类顺序错误时报错(如“Error: displacement found on a(n) worldspawn entity...”)。在Hammer中重新打开并保存地图可恢复默认顺序。 |
|
| |
|
| See each of these for what they do.
| | == 版本信息 == |
| | | 此类包含Hammer创建文件的版本信息和保存次数,本质是文件头,与地图内容无关: |
| NOTE: the order doesn't matter to Hammer, but VBSP may have trouble if certain Classes are out of order (e.g. "Error: displacement found on a(n) worldspawn entity - not supported ..."). Opening and re-saving the map in Hammer will restore the default order.
| |
| | |
| == Version info == | |
| This Class details information for Hammer on what version created the file and how many times it has been saved. It is basically the file header and contains no information relevant to the map itself.
| |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| versioninfo | | versioninfo |
Line 73: |
Line 70: |
| </nowiki>}} | | </nowiki>}} |
| *'''editorversion (int)''' | | *'''editorversion (int)''' |
| :The version of Hammer used to create the file, version 4.00 is "400". | | :创建文件所用的Hammer版本,4.00版对应"400" |
| *'''editorbuild (int)''' | | *'''editorbuild (int)''' |
| :The patch number of Hammer the file was generated with. | | :生成文件时Hammer的补丁号 |
| *'''mapversion (int)''' | | *'''mapversion (int)''' |
| :It represents how many times you've saved the file, useful for comparing old or new versions. | | :文件保存次数,用于比较新旧版本 |
| *'''formatversion (100)''' | | *'''formatversion (100)''' |
| :Unknown. (Most likely the VMF file format version) | | :未知(很可能是VMF文件格式版本) |
| *'''prefab (bool)''' | | *'''prefab (bool)''' |
| :Whether it is a full map or simply a collection of [[Prefab|prefabricated objects]]. | | :标识是否为完整地图或{{L|Prefab|预置件}}对象集合 |
|
| |
|
| What the <code>formatversion</code> represents is unknown due to the fact no different values are ever generated. Any changes in value yield no results and are simply overridden back to "100" on save or when compiling a map.
| | 由于从未生成过不同值,<code>formatversion</code>含义未知。修改该值无效,保存或编译时会被重置为"100"。<code>prefab</code>属性定义文件是否包含由笔刷/实体组成的对象(如沙发)而非完整地图。若缺失任何信息,Hammer将按当前状态重建。 |
| The <code>prefab</code> property is used to define if the file contains an object like a sofa made from other brushes and entities, rather than a full blown map.
| |
| If any of this information is missing Hammer will simply recreate it from its current form.
| |
|
| |
|
| == VisGroups == | | == 可视组(VisGroup) == |
| This Class itself is usually empty; however, it contains all the unique [[Grouping_and_VisGrouping#VisGroups|VIS group]] definitions in Hammer, along with their structure and properties. The first separated section in the code sample is one unique group. The entire code sample is used for example.
| | 此类通常为空,但包含Hammer中所有唯一的{{L|Grouping_and_VisGrouping#VisGroups|可视组}}定义及其结构和属性。以下示例展示完整结构: |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| visgroups | | visgroups |
| { | | { |
|
| |
| visgroup | | visgroup |
| { | | { |
Line 99: |
Line 93: |
| "color" "65 45 0" | | "color" "65 45 0" |
| } | | } |
|
| |
| visgroup | | visgroup |
| { | | { |
Line 125: |
Line 118: |
| } | | } |
| } | | } |
|
| |
| </nowiki>}} | | </nowiki>}} |
| *'''name (sz)''' | | *'''name (sz)''' |
| :The name of the group, it's the only identifier within in Hammer so it should be unique for your own benefit. | | :组名称,是Hammer中的唯一标识符 |
| *'''visgroupid (int)''' | | *'''visgroupid (int)''' |
| :A unique value among all other visgroup ids, identical values will cause weird minor errors in Hammer. | | :所有可视组ID中唯一的值,重复会导致Hammer轻微异常 |
| *'''color (rgb)''' | | *'''color (rgb)''' |
| :A color for the group, can be applied to brush outlines in Hammer. | | :组的颜色,可应用于Hammer中的笔刷轮廓 |
|
| |
|
| [[Grouping_and_VisGrouping#VisGroups|VIS groups]] are unrelated to the VIS part of a compile and in the new Hammer there are 2 types; auto, and custom. Auto refers to the automatic ones Hammer creates to single out types of brushes or entities, the auto groups are not defined in the file as Hammer generates them. Custom refers to groups that a user creates and they are defined within this Class. In older versions all groups were originally listed here. The groups themselves have a hierarchical tree like structure, meaning that one group may be a parent and have other groups be its children. When something is done to a parent children are affected, but children do not affect parents. To establish one group as a child to another group you define that group within the definition of the parent group. The code sample given is an example of this structure. Tree_1 is the parent of Branches and Branch_2 is the parent of Leaf_1. There's no limit to the complexity of this Class and its subclasses; however, there is a limit of 128 groups before Hammer begins to function improperly.
| | {{L|Grouping_and_VisGrouping#VisGroups|可视组}}与编译的VIS无关。新版Hammer中有两种类型:自动组(由Hammer按笔刷/实体类型生成,不在此定义)和用户创建的{{L|Grouping_and_VisGrouping#VisGroups|自定义组}}(在此类中定义)。组采用层次树结构,即一个组可以是父组并包含子组。对父组的操作会影响子组,但子组不影响父组。要定义子组,需在父组定义内嵌套该组(见示例)。组结构复杂度无限制,但超过128组会导致Hammer异常。允许多个visgroups类,但Hammer会将其合并。 |
| It is possible to have more than one visgroups class, but Hammer will condense them into one, adding the additional vis groups into the main visgroup.
| |
|
| |
|
| == Viewsettings == | | == 视图设置 == |
| This class contains the map specific view properties used in Hammer, any of the other properties are not saved into the map.
| | 此类包含Hammer中地图特定的视图属性,其他属性不存入地图: |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| viewsettings | | viewsettings |
Line 150: |
Line 141: |
| </nowiki>}} | | </nowiki>}} |
| *'''bSnapToGrid (bool)''' | | *'''bSnapToGrid (bool)''' |
| :Whether the map has the grid snapping feature enabled. | | :是否启用网格吸附功能 |
| *'''bShowGrid (bool)''' | | *'''bShowGrid (bool)''' |
| :Whether the map is showing the 2D grid. | | :是否显示2D网格 |
| *'''bShowLogicalGrid (bool)''' | | *'''bShowLogicalGrid (bool)''' |
| :Changes whether the hidden "[[Logical view|Logical View]]" should show a grid | | :是否在隐藏的{{L|Logical view|逻辑视图}}中显示网格 |
| *'''nGridSpacing (int)''' | | *'''nGridSpacing (int)''' |
| :The value the grid lines are spaced at. | | :网格线间距值 |
| *'''bShow3DGrid (bool)''' | | *'''bShow3DGrid (bool)''' |
| :Whether the map is showing the 3D grid. | | :是否显示3D网格 |
|
| |
|
| If <code>bSnapToGrid</code> is true, Hammer will force all points the user interacts with to a multiple of <code>nGridSpacing</code>; this does not affect loaded vertices. Any other property set within Hammer will only be set for Hammer and not for the map. If any of this information is missing Hammer will simply recreate it from defaults so it is not essential.
| | 若<code>bSnapToGrid</code>为真,Hammer会强制用户操作点对齐<code>nGridSpacing</code>倍数(不影响已载入顶点)。其他Hammer属性设置仅作用于编辑器。缺失信息将被重置为默认值。 |
|
| |
|
| == World == | | == World == |
| In a VMF file, the world Class contains all the world brush information for Hammer. World brushes are the brushes without any entity information attached to them. The <code>world</code> Class takes on the same form as other entities but has some unique factors.
| | .vmf文件中,world类包含Hammer的所有世界笔刷信息(即无实体附加的笔刷)。<code>world</code>类形式与其他实体相同但有特殊属性: |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| world | | world |
Line 177: |
Line 168: |
| </nowiki>}} | | </nowiki>}} |
| *'''id (int)''' | | *'''id (int)''' |
| :A unique value among other world Class ids. | | :世界类ID中的唯一值 |
| *'''mapversion (sz)''' | | *'''mapversion (sz)''' |
| :A reiteration of the mapversion from the versioninfo Class. | | :来自versioninfo类的mapversion副本 |
| *'''classname ({{ent|worldspawn}})''' | | *'''classname ({{ent|worldspawn}})''' |
| :States what type of entity the world is. | | :声明世界实体的类型 |
| *'''skyname (sz)''' | | *'''skyname (sz)''' |
| :The name of the skybox to be used. | | :使用的天空盒名称 |
| *[[Valve Map Format#Solid|solid{}]] | | *[[Zh/VMF_(Valve_Map_Format)#Solid|solid{}]] |
| *[[Valve Map Format#Group|group{}]] | | *[[Zh/VMF_(Valve_Map_Format)#Group|group{}]] |
| *[[Valve Map Format#Hidden|hidden{}]] | | *[[Zh/VMF_(Valve_Map_Format)#Hidden|hidden{}]] |
|
| |
|
| The definition of the World class actually takes the form of an entity. This causes the possibility for a large number of properties to be defined, they have been omitted for simplicities sake as they followed standard entity notation. As entities are discussed later only the following information will be given for now. The <code>classname</code> for World '''always''' has to be "worldspawn". Without it the map is not properly defined and cannot be compiled properly, "worldspawn" is a special type of entity the game has to find here. The only property that must be included is the <code>skyname</code> to avoid errors in compiling.
| | World类定义实际采用实体形式,可包含大量属性(此处省略)。关键点:World的<code>classname</code>必须为"worldspawn",否则地图无法正确定义和编译("worldspawn"是游戏必需的实体类型)。编译时必须包含<code>skyname</code>属性避免错误。允许多个world类,但Hammer会合并为单个定义(保留首个类的属性,后续同名属性覆盖前者)。 |
| It is possible to define multiple world Classes, but Hammer will condense them into one single definition, adding the solids and groups of the additional world classes into the first, and using the "latest" properties; that is, if the first world has ("A" "1") and ("B" "2") but the second world only has ("B" "3"), the new world will have ("A" "1") and ("B" "3").
| |
|
| |
|
| == Solid == | | == 笔刷 == |
| This Class represents 1 single brush in Hammer. It contains 1 property and 2 subclasses. One brush is defined simply by the total of all sides that make up its shape. All brushes have to be saved as a valid shape or Hammer will either not load the solid or reshape it so that it becomes valid.
| | 此类代表Hammer中的单个笔刷,含1个属性和2个子类。笔刷由其所有围成形状的面定义。无效笔刷会导致Hammer拒绝加载或自动修复。 |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| solid | | solid |
Line 202: |
Line 192: |
| </nowiki>}} | | </nowiki>}} |
| *'''id (int)''' | | *'''id (int)''' |
| :A unique value among other solids' IDs, Identical values will cause weird minor errors. | | :笔刷ID中的唯一值,重复会导致轻微异常 |
| *[[Valve Map Format#Side|side{}]] | | *[[Zh/VMF_(Valve_Map_Format)#Side|side{}]] |
| *[[Valve Map Format#Editor|editor{}]] | | *[[Zh/VMF_(Valve_Map_Format)#Editor|editor{}]] |
|
| |
|
| Within the <code>solid</code> Class you must define multiple sides, at least four. As mentioned this is because each stored brush should be valid, due to the way Hammer calculates and represents brushes a non valid brush will cause errors either in Hammer or in game.
| | <code>solid</code>类必须定义至少四个面。因Hammer计算方式,无效笔刷会导致编辑器或游戏错误。 |
|
| |
|
| == Side == | | == 面 == |
| This Class defines all the data relevant to one side and just to that side. It details its orientation, texture, and properties. The plane property defines the orientation of the face. Where a face intersects with other planes is used to define all of its borders, thus they are not saved into the file. The u-axis and v axis properties are complex and require an independent explanation.
| | 此类定义单面的所有相关数据(朝向、纹理和属性)。plane属性定义面的朝向,面边界由相交平面计算得出故不存储。u轴/v轴属性需单独解释: |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| side | | side |
Line 226: |
Line 216: |
| } | | } |
| </nowiki>}} | | </nowiki>}} |
| * '''id (int)''' | | *'''id (int)''' |
| : A unique value among other sides ids. Identical values will cause weird minor errors. | | :面ID中的唯一值,重复会导致轻微异常 |
| * [[Valve Map Format#Planes|plane ()]] | | *[[Zh/VMF_(Valve_Map_Format)#Planes|plane()]] |
| * '''material (sz)''' | | *'''material (sz)''' |
| :The directory and name of the texture the side has applied to it. | | :面所应用纹理的路径和名称 |
| * [[Valve Map Format#U/V Axis|uaxis ()]] | | *[[Zh/VMF_(Valve_Map_Format)#U/V Axis|uaxis()]] |
| * [[Valve Map Format#U/V Axis|vaxis ()]] | | *[[Zh/VMF_(Valve_Map_Format)#U/V Axis|vaxis()]] |
| * '''rotation (dec)''' | | *'''rotation (dec)''' |
| : The rotation of the given texture on the side. The rotation is built into the uaxis and vaxis, this value is merely displayed to the user, changing it does not change the texture's rotation, just the value displayed to the user. | | :面纹理的旋转角度(实际由u/v轴计算,此值仅用于显示) |
| * '''lightmapscale (int)''' | | *'''lightmapscale (int)''' |
| : The light map resolution on the face. | | :面的光照贴图分辨率 |
| * '''Smoothing_groups (int)''' | | *'''smoothing_groups (int)''' |
| : Select a smoothing group to use for lighting on the face. | | :面所用的{{L|Hammer_Smoothing_Groups_Dialog|平滑组}} |
| * '''contents (bitfield)''' | | *'''contents (bitfield)''' |
| * '''flags (bitfield)''' | | *'''flags (bitfield)''' |
| : Contents and Surface flags, as defined in {{path|public/bspflags|h}}, but in base 10 instead of base 16. | | :内容/表面标志(定义于{{path|public/bspflags|h}}),十进制存储 |
| : Stripped by {{hammer4|2}}, but read by the compilers; using {{h++|2}} or putting relevant brushes in a separate [[instance]]. Remnant from {{quake2|2}} [[WAL]] flags. | | :被{{hammer4|2}}剥离但编译器读取,使用{{h++|2}}或相关笔刷放入独立{{L|instance}}处理 |
| *[[Valve Map Format#Dispinfo|dispinfo{}]] | | *[[Zh/VMF_(Valve_Map_Format)#Dispinfo|dispinfo{}]] |
|
| |
|
| The id values should be unique even between solids. That is because the face identifier needs to be unique for entities like [[Env_cubemap|cubemaps]] that reference one specific face. The <code>lightmapscale</code> Property refers to the size you define for the lighting patches to be applied to the face during compiling. The <code>smoothing_groups</code> Property indicates which [[Hammer_Smoothing_Groups_Dialog|smoothing groups]] the face will be placed in. All adjacent faces in a [[Hammer_Smoothing_Groups_Dialog|smoothing group]] will have the differences in light between them bled together. The easiest way to determine what groups the value indicates is by converting it back to binary. A high in the least significant bit will mean it's in the first group, a high in the last bit will mean it's in the 32nd group.
| | ID值在笔刷间也需唯一(因{{L|Env_cubemap|立方体贴图}}等实体需引用特定面)。<code>lightmapscale</code>定义编译时应用于面的光照块大小。<code>smoothing_groups</code>表示面所属的{{L|Hammer_Smoothing_Groups_Dialog|平滑组}},组内相邻面的光照差异将被平滑处理。通过转二进制可确定分组(最低位为1表示在第1组,最高位为1表示在第32组)。 |
|
| |
|
| === Planes === | | {{LanguageBar|Valve Map Format|title=Valve地图格式}} |
| A plane is a fundamental two-dimensional object. It can be visualized as a flat infinite sheet of paper. That piece of paper is then positioned in a three-dimensional world. Where planes intersect forms a brushes edges and vertices.
| | === 平面 === |
| | 平面是基本的二维对象,可视为三维世界中无限延伸的平坦薄片。平面相交形成笔刷的边和顶点。 |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| "plane" "(0 0 0) (0 0 0) (0 0 0)" | | "plane" "(0 0 0) (0 0 0) (0 0 0)" |
| </nowiki>}} | | </nowiki>}} |
| *'''plane ((vertex) (vertex) (vertex))''' | | *'''plane ((顶点) (顶点) (顶点))''' |
| :This defines the three points that will be used to set the plane's orientation and position in the three-dimensional world. | | :定义用于确定平面在三维空间中朝向和位置的三个点 |
|
| |
|
| To define the orientation three sequential points are used. Think of these as three objects the sheet is placed upon. If one is higher or lower than the others it will cause the paper to sit at an angle. By choosing how high or low the other points are you can rotates the sheet in any direction. The paper passes through all three defined points, this means they can be used to represent the orientation of the plane.
| | 使用三个有序点确定平面朝向,这些点如同支撑纸张的物体。点的高度差异会使平面倾斜,通过调整点的高度可旋转平面。平面必须穿过所有三个定义点,这些点共同决定平面朝向。平面朝向由点的定义顺序决定:从特定方向观察时顺时针定义的点序会使平面朝该方向可见。 |
| The direction the plane faces is determined by the order you define them in. Defining them in a clockwise order when looking from one direction order will cause the face to be visible from that direction.
| | |
| The following example will generate a plane for a square 32x32 floor, a plane flat in the z-axis that will face upwards.
| | 以下示例生成32x32地板的平面(z轴平面朝上): |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| "plane" "(-16 -16 0) (16 -16 0) (16 16 0)" | | "plane" "(-16 -16 0) (16 -16 0) (16 16 0)" |
| </nowiki>}} | | </nowiki>}} |
| The plane is defined using these three points. The first marks the bottom left of the face, the second marks the top left, and the third marks the top right. When viewed from the top this forms a clockwise order, this means the plane will be facing upwards. The vertex positions leave a space of 32 units for each side and lay out 3 corners of a square. This will form the required floor.
| | 三个点分别代表面的左下角、左上角和右上角。从顶部观察呈顺时针顺序,因此平面朝上。顶点间距32单位,形成正方形地板。 |
|
| |
|
| [[File:Brush_planes.gif|right|frame]] | | [[File:Brush_planes.gif|right|frame]] |
| | | 右侧动画展示通过CSG从六个平面构建简单笔刷的过程(详见{{L|VMF_(Valve_Map_Format)#附加资源|附加资源}})。红/绿/蓝点分别代表第一/二/三点。该笔刷的平面点如下: |
| On the right is an animation of a simple brush being build from six planes via CSG (see section [[VMF_(Valve_Map_Format)#Additional_resources|Additional resources]] for detailed description of the process). The first, second and third plane point is represented by red, green and blue dots. Below are the plane points for this brush:
| |
| | |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| "plane" "(-128 32 128) (128 32 128) (128 0 128)" | | "plane" "(-128 32 128) (128 32 128) (128 0 128)" |
Line 276: |
Line 265: |
| </nowiki>}} | | </nowiki>}} |
|
| |
|
| The next example details a crucial note.
| | 关键注意事项示例: |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| "plane" "(-32 -32 0) (32 -32 0) (32 32 0)" | | "plane" "(-32 -32 0) (32 -32 0) (32 32 0)" |
Line 283: |
Line 272: |
| "plane" "(-32 32 0) (-32 -32 0) (32 -32 0)" | | "plane" "(-32 32 0) (-32 -32 0) (32 -32 0)" |
| </nowiki>}} | | </nowiki>}} |
| All of the above definitions will create the same plane. The sequential points chosen to define the plane will form the same plane regardless, if choosing different points on the same face forms a different plane then that brush is invalid.
| | 以上定义均生成相同平面。同一面上的不同点序始终定义相同平面,否则笔刷无效。 |
| The vertices that make up all the edges of a face are determined using the intersection of all the defined planes of a brush. Vertices mark the point where three or more planes intersect and edges mark the area where two planes intersect along a line. This is almost a base definition of how they are supposed to exist and cannot be altered. The problem comes with the fact that vertices are used to define the planes, as such the points of intersection have already been defined and must be adhered to. Failure to do so will generate many varied shapes but will always result in an invalid brush. When defining a plane any other defined vertices must be able to be placed on that plane or another plane defined within the brush.
| | |
| | 面的所有边顶点由笔刷各平面相交确定:顶点是三个及以上平面的交点,边是两个平面沿线的交线。此为基础定义不可更改。问题在于顶点用于定义平面,因此交点必须严格匹配,否则将生成无效笔刷。定义平面时,任何其他定义顶点必须位于该平面或笔刷内其他平面上。 |
|
| |
|
| === U/V Axis === | | === U/V轴 === |
| The u-axis and v-axis are the texture specific axes. They hold their own designations as they are independent of the true x-axis and y-axis, but it's easier to think of them in terms of x and y. The u-axis represents the x-axis and the v-axis represents the y-axis. These two code lines work together to define how the texture is displayed upon a face.
| | u轴和v轴是纹理专用坐标系。u轴对应x轴,v轴对应y轴,两者共同定义纹理在面上的显示方式。 |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| "uaxis" "[1 0 0 0] 0.25" | | "uaxis" "[1 0 0 0] 0.25" |
| "vaxis" "[0 1 0 0] 0.25" | | "vaxis" "[0 1 0 0] 0.25" |
| </nowiki>}} | | </nowiki>}} |
| *'''u/v axis ([x y z dec] dec)''' | | *'''u/v轴 ([x y z 平移] 缩放)''' |
| :The x, y, and z are decimal values representing that axis. The following value is the translation and the last decimal is the total scaling. | | :xyz为十进制值代表轴向,随后是平移值,末尾为总缩放值 |
| | |
| | xyz值决定纹理在对应轴的显示比例。值1表示在标准空间显示一次完整纹理,值2表示显示两次。此设置仅应用于纹理的单一轴,且相对于真实xyz轴。这意味着可将纹理设置在平面不存在的轴上(如xy平面无需z轴定义)。负值会翻转纹理,若纹理显示在平面不存在的轴上,Hammer将报错。 |
|
| |
|
| The values for the x y z set represent the amount of the texture to be shown in that axis. They modify how much of the texture is shown within the normal space the texture would occupy on the face. A value of one means one repetition in the normal space, a value of two would mean two repetitions in the normal space. The key is that this only applies to one axis of the texture and is applied relative to true x, y, and z axes. That means that it is possible to set the texture to appear along an axis the plane doesn't exist in. With a flat plane in the x-axis and the y-axis definitions are only needed for those axes as any definition in the z-axis has no surface to appear on. The code sample shows how this would be generated by Hammer. The texture's x-axis (the u-axis) is displayed in the real x-axis and the texture's y-axis (v-axis) is displayed in the real y-axis. Which of the x, y, and z axes are showing the axes of the texture depends entirely upon the faces orientation. Negative values will flip textures and Hammer will generate errors about textures shown in a plane the surface does not occupy.
| | 倒数第二个值是纹理原点的平移量(Hammer显示时四舍五入但保存精确值)。末尾十进制是包含xyz定义的总缩放值。缩放比为1时,纹理1像素对应1Hammer单位。 |
| The second to last value is the simple translation of the textures origin within that axis; this value is actually a decimal though Hammer will round it up when displaying Hammer will still save the correct decimal value. The last decimal is the overall scaling of the entire axis including what is defined in the x y z group. With an effective scale of 1, 1 pixel on the texture corresponds to 1 Hammer Unit.
| |
|
| |
|
| === Dispinfo === | | === 位移信息 === |
| The <code>dispinfo</code> Class deals with all the information for a [[displacement]] map. Information is stored on each vertex and thus creates a large amount of information to be sorted. This leaves a lot of subclasses to help organize all the information. The presence of the <code>dispinfo</code> Class itself tells Hammer that the face is a displacement map and the Class therefore should not be included if the face is not a [[displacement]]. All the properties are applied over top of the original side's properties.
| | <code>dispinfo</code>类处理{{L|displacement|位移}}的所有信息。每个顶点信息独立存储,产生大量需整理的数据。该类仅当面为{{L|displacement|位移}}时存在,属性覆盖原始面的属性。 |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| dispinfo | | dispinfo |
Line 317: |
Line 308: |
| </nowiki>}} | | </nowiki>}} |
| *'''power (2,3,4)''' | | *'''power (2,3,4)''' |
| :Used to calculate the number of rows and columns, only the three given values will compile properly. If omitted Hammer assumes 4. If the data is built around another power value, the vertex data will be squished into the starting corner. | | :计算行列数的幂值(仅此三值可编译)。缺省时Hammer假定为4。若数据基于其他幂值,顶点数据将被挤压到起始角 |
| *'''startposition (vertex)''' | | *'''startposition (顶点)''' |
| :The position of the bottom left corner in an actual x y z position. | | :左下角在xyz空间的实际位置 |
| *'''elevation (float)''' | | *'''elevation (浮点数)''' |
| :A universal displacement in the direction of the vertex's normal added to all of the points. | | :沿顶点法线方向作用于所有点的整体位移 |
| *'''Subdiv (bool)''' | | *'''Subdiv (布尔值)''' |
| :Marks whether or not the displacement is being sub divided. | | :标记是否进行{{L|displacement#Subdivision|细分位移}} |
| *[[Valve Map Format#Normals|normals{}]] | | *[[Zh/VMF_(Valve_Map_Format)#Normals|法线{}}} |
| *[[Valve Map Format#Distances|distances{}]] | | *[[Zh/VMF_(Valve_Map_Format)#Distances|距离{}}} |
| *[[Valve Map Format#Offsets|offsets{}]] | | *[[Zh/VMF_(Valve_Map_Format)#Offsets|偏移{}}} |
| *[[Valve Map Format#Offset_normals|offset_normals{}]] | | *[[Zh/VMF_(Valve_Map_Format)#Offset_normals|offset_normals{}}} |
| *[[Valve Map Format#Alpha|alpha{}]] | | *[[Zh/VMF_(Valve_Map_Format)#Alpha|alpha{}}} |
| *[[Valve Map Format#Traingle_tags|traingle_tags{}]] | | *[[Zh/VMF_(Valve_Map_Format)#Traingle_tags|traingle_tags{}}} |
| *[[Valve Map Format#Allowed_verts|allowed_verts{}]] | | *[[Zh/VMF_(Valve_Map_Format)#Allowed_verts|allowed_verts{}}} |
|
| |
|
| There's also a temporary value called "scale" within in Hammer. This value is actually not saved into the file and only affects the scaling of current movements.
| | Hammer中存在临时值"scale",不存入文件仅影响当前移动缩放。 |
| All grid based subclasses follow a similar system, the equation 2^''n'' + 1 is used to determine the number of rows where ''n'' is the power. This determines the number of rows and columns to be used. The rows are numbered and stored starting from 0 at the vertex <code>startposition</code> defines. Each Property will simply be row# where # is the rows number. Sometimes a column will have multiple parts and lead to there being 2 or 3 times as many values.
| | 所有基于网格的子类遵循相同规则:行数公式为2<sup>n</sup>+1(n=power值)。行号从<code>startposition</code>定义的0号顶点开始。每行以row#存储,#为行号(部分列含多个值)。 |
|
| |
|
| ==== Normals ==== | | ==== 法线 ==== |
| The Class defines the normal line for each vertex. This is a line that points outwards from the face and is used for light shading and vertex placement. Each column contains a group of 3 values.
| | 此类定义各顶点的法线(从面朝外指向的线),用于光照着色和顶点定位: |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| normals | | normals |
Line 348: |
Line 339: |
| </nowiki>}} | | </nowiki>}} |
| *'''row# ((x y z) (x y z) ...)''' | | *'''row# ((x y z) (x y z) ...)''' |
| :Each group of decimals is used to define the normal line for that vertex. | | :每组十进制值定义顶点的法线 |
|
| |
|
| The normal line is an imaginary one unit long line drawn from the vertex. The decimal values represent the length of the line that exists in that axis. A line straight along one axis will be a value of 1 in that axis, if however the line is sloped part of it will be in one axis and another part will be another axis. That results in two different decimal values in the different axes of the same column. This line is important for two reasons, the line is used as a guide on how to light the [[displacement]] map, and the line is used to guide the vertex to its defined position. In the code sample it shows how normal lines may appear in the last three rows. The first row is all straight up, and the second row is all straight down. In the third row the inside three points face down and the two outside points face up.
| | 法线是从顶点绘制的单位长度假想线。十进制值代表线在各轴的分量(纯轴向为1,斜面则含多轴分量)。法线决定{{L|displacement|地面位移}}的光照方式及顶点最终位置。示例中:第1行全部朝上(0,0,1),第2行朝下(0,0,-1),第3行内侧三点朝下、外侧两点朝上。 |
|
| |
|
| Note that having negative distances with an up normal (0, 0, 1) is the same as having positive distances with a down (0, 0, -1) normal.
| | > 注意:朝上法线(0,0,1)配合负距离等效于朝下法线(0,0,-1)配合正距离。 |
|
| |
|
| ==== Distances ==== | | ==== 距离 ==== |
| The distance values represent how much the vertex is moved along the normal line. With an undefined normal line the distance is not applied.
| | 距离值表示顶点沿法线移动的量(非法线则距离不生效): |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| distances | | distances |
Line 366: |
Line 357: |
| } | | } |
| </nowiki>}} | | </nowiki>}} |
| *'''row# (dec dec ...)''' | | *'''row# (小数 小数 ...)''' |
| :Any decimal value representing the final distance a vertex is moved along the normal line. | | :顶点沿法线移动的最终距离 |
|
| |
|
| Once a distance value is set the vertex is moved along the normal line for the given value. This then gives the final position for the vertex. Although negative values are accepted and compiled it is better for the normal line to handle the direction of the displacement. Applying the values from the <code>[[Valve Map Format#Normals|normals]]</code> Class to this Class gives a displacement map its form. If the code samples for rows 2, 3, and 4 were actually used they would create a displacement map with three unique rows. One row would be 64 units high, the next 64 units deep. The third would have three 32 unit deep points and the two outside points 32 units high.
| | 距离值使顶点沿法线方向移动形成最终位置。结合{{L|Valve Map Format#法线|法线}}类数据可构建位移贴图形状。若使用示例中的2-4行数据:第2行上移64单位,第3行下移64单位,第4行外侧两点上移32单位、内侧三点下移32单位。 |
|
| |
|
| ==== Offsets ==== | | ==== 偏移 ==== |
| This Class lists all the default positions for each vertex in a displacement map. The <code>[[Valve Map Format#Distances|distances]]</code> are judged from the points the <code>offsets</code> Class defines. Each column contains a group of 3 values.
| | 此类定义位移贴图各顶点的默认位置,{{L|Valve Map Format#距离|距离}}值以此为基准计算: |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| offsets | | offsets |
Line 383: |
Line 374: |
| } | | } |
| </nowiki>}} | | </nowiki>}} |
| *'''row# (vertex vertex ...)''' | | *'''row# (顶点 顶点 ...)''' |
| :Each group is the vertex position in x, y, and z relative to the original position. | | :相对于原始位置的顶点新位置 |
|
| |
|
| The <code>offsets</code> Class defines new default vertex positions relative to the original calculated positions. In the code sample above just the contents of this Class recreates an identical displacement map to the previous two Classes combined. Hammer does not modify these points in any way.
| | <code>offsets</code>定义相对于原始计算位置的新顶点位置。本例数据与前两个类组合效果相同。Hammer不修改这些点。 |
|
| |
|
| ==== offset_normals ==== | | ==== 偏移法线 ==== |
| This Class is almost identical to the <code>[[Valve Map Format#Normals|normals]]</code> Class. The data structure is identical except the name, thus the code sample has been omitted to save space. The only differences lie in what it does and what it affects. This class defines the default normal lines that the <code>[[Valve Map Format#Normals|normals]]</code> Class is based from. It does not modify the <code>[[Valve Map Format#Offsets|offsets]]</code> Class. Hammer has no options to modify these values, it can only set them based upon the faces orientation.
| | 此类与[[Zh/VMF_(Valve_Map_Format)#法线|法线]]类几乎相同(数据结构一致)。差异在于功能:此类定义[[Zh/VMF_(Valve_Map_Format)#法线|法线]]类的基准法线,不影响[[Zh/VMF_(Valve_Map_Format)#偏移|偏移]]类。Hammer无法直接修改这些值,仅能根据面朝向自动设置。 |
|
| |
|
| ==== Alpha ==== | | ==== 透明度 ==== |
| This Class contains a value for each vertex that represents how much of which texture to shown in [[Displacement#Blended displacement materials (vertex alpha painting)|blended materials]]. The difference between the values is merged linearly across the [[displacement]] map.
| | 此类包含各顶点的透明度值(0-255),用于{{L|Displacement#Blended displacement materials (vertex alpha painting)|地面位移}}。值间差异通过线性插值混合。 |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| alphas | | alphas |
Line 403: |
Line 394: |
| } | | } |
| </nowiki>}} | | </nowiki>}} |
| *'''row# (dec dec ...)''' | | *'''row# (小数 小数 ...)''' |
| :It represents a decimal between 0 and 255. | | :0-255的十进制值 |
|
| |
|
| | 值表示次纹理覆盖基础纹理的程度。示例:第1行纯次纹理(255),第2行纯基础纹理(0),第3行外侧两点半透明(128),内侧三点纯基础纹理(0)。 |
|
| |
|
| The value simply marks how much of the secondary texture is visible overtop the base texture. The differences in values are blended via linear interpolation so only the key values at vertices are stored. As the last 3 rows in the code sample provide an example. The first row is pure secondary texture, and the second row is pure base. The third row has the two outside points showing half of each texture and the inner 3 showing all base texture.
| | ==== 三角标记 ==== |
| | | 此类存储位移中每个三角形(非顶点)的信息。数据量由2<sup>n</sup>决定(n=power值),行列号从起点向外定义。 |
| ==== triangle_tags ==== | |
| This Class contains information specific to each triangle in the displacement, rather than every vertex. This means that the size and number of its rows will differ. It follows the pattern of 2^''n'' where ''n'' is the power. The row and column numbers are still defined from the starting point outwards.
| |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| triangle_tags | | triangle_tags |
Line 421: |
Line 411: |
| } | | } |
| </nowiki>}} | | </nowiki>}} |
| *'''row# (((0,1,9) (0,1,9)) ((0,1,9) (0,1,9))...)''' | | *'''row# (((0,1,9) (0,1,9))...)''' |
| :Each group represents one square consisting of two triangles. Only values of 0, 1, or 9 will compile. | | :每组代表一个正方形内的两个三角形,仅0/1/9可编译 |
|
| |
|
| The value assigned to the triangle represents its orientation. A value of "9" means the triangles has little or no slope in the z-axis. A value of "1" means it has a significant slope in the z-axis but a player is still able to walk on it. A value of "0" means it has a large slope in the z-axis and the player cannot walk up it. Any value is accepted by Hammer, a value of "2" will even produce green highlights in the [[Hammer_Map_Operations_Toolbar#Display_Walkable|Display walkable area]] view, but any such values will not compile.
| | 值定义三角形朝向:"9"=z轴坡度极小;"1"=z轴坡度可步行;"0"=z轴坡度不可攀爬。Hammer接受任意值(如"2"在{{L|Hammer_Map_Operations_Toolbar#Display_Walkable|可步行区域视图}}显示绿色高亮),但非0/1/9值编译失败。 |
|
| |
|
| ==== allowed_verts ==== | | ==== 允许顶点 ==== |
| This affects the in-game tesselation of the displacement map, stating which vertices share an edge with another displacement map but do not share a vertex.
| | 此类影响位移贴图的游戏端曲面细分,标记与其他位移贴图共享边但不共享顶点的顶点。 |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| allowed_verts | | allowed_verts |
Line 434: |
Line 424: |
| } | | } |
| </nowiki>}} | | </nowiki>}} |
| *'''10 (int, int, int, int, int, int, int, int, int, int)''' | | *'''10 (整数集)''' |
| :A set of binary flags which corresponds to which vertices are allowed in the displacement map. A false flag removes the vertex from the compiled map. Note that -1 is all bits set to true. | | :二进制标志集(-1=全启用),false值将在编译时移除顶点 |
|
| |
|
| This by definition has no effect in Hammer, it modifies properties for compiled maps which the editor does not need to consider. A quick way to view the "disallowed" vertices is to turn on the [[Hammer_Map_Operations_Toolbar#Displacement_Edge_Collapse|Show collapsible vertices]] button. The vertices will now be shown as pink cubes. When the displacement maps are compiled the disabled vertices are interpolated with its neighbors to fit with the line. See [[:Image:Dispverts inhammer.jpg|in hammer]] and [[:Image:Dispverts inhl2.jpg|after compiling]].
| | Hammer中此属性无视觉效果,启用{{L|Hammer_Map_Operations_Toolbar#Displacement_Edge_Collapse|可折叠顶点显示}}后,禁用顶点显示为粉色立方体。编译时禁用顶点与其相邻点插值拟合(对比[[:Image:Dispverts inhammer.jpg|编辑器]]与[[:Image:Dispverts inhl2.jpg|游戏效果]])。 |
|
| |
|
| == Editor == | | {{LanguageBar|Valve Map Format|title=Valve地图格式}} |
| All information within this Class is for Hammer only and bears no significance to the map itself.
| | |
| | === 编辑器 === |
| | 此类信息仅供Hammer使用,与地图本身无关: |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| editor | | editor |
Line 449: |
Line 441: |
| "visgroupshown" "1" | | "visgroupshown" "1" |
| "visgroupautoshown" "1" | | "visgroupautoshown" "1" |
| "comments" "Only exists on entities." | | "comments" "仅存在于实体上" |
| "logicalpos" "[34 28]" | | "logicalpos" "[34 28]" |
| } | | } |
| </nowiki>}} | | </nowiki>}} |
| *'''color (rgb)''' | | *'''color (rgb)''' |
| :A color for the brushes outline and flat color. | | :笔刷轮廓线和平面的显示颜色 |
| *'''visgroupid (int)''' | | *'''visgroupid (int)''' |
| :The id of the visgroup this solid belongs to. | | :笔刷所属可视组ID |
| *'''group (int)''' | | *'''group (int)''' |
| :The id of the brush group this solid belongs to. | | :笔刷所属可见组ID |
| *'''visgroupshown (bool)''' | | *'''visgroupshown (bool)''' |
| :Whether or not that group is shown. | | :该组是否可见 |
| *'''visgroupautoshown (bool)''' | | *'''visgroupautoshown (bool)''' |
| :Whether or not the automatic group is shown. | | :自动组是否可见 |
| *'''comments (string)''' | | *'''comments (字符串)''' |
| :A comment string that Hammer will show in the Class Info tab pane. | | :在"类信息"选项卡显示的注释(仅实体有效) |
| *'''logicalpos (2D vector)''' | | *'''logicalpos (2D向量)''' |
| :The 2D position of the entity in the hidden "Logical View". | | :实体在隐藏的{{L|Logical view|逻辑视图}}中的位置 |
|
| |
|
| The <code>visgroupid</code> is special in that you can define the property as many times as you want in order to assign the brush to multiple visgroups. The group property defines which brush group the solid belongs to in Hammer. The number is the id of the first child group the brush belonged to. The <code>visgroupshown</code> is one misplaced item, why include the definition of a group being visible within a brush for that group and for every brush in that group. All it does is allow a brush to be visible when it shouldn't be. The <code>comments</code> property allows you to make comments on your entities for yourself or other map developers. You can find the comments in the lower right of the Class Info pane in Entity Properties. Note that this only works on entities, and will be ignored and deleted by Hammer if placed on anything else. The "Logical View" is a partially-implemented view available in some versions of Hammer, displaying all entities and their IO connections in a flowchart-like fashion. <code>logicalpos</code> stores the position of each entity in this display. Hammer appears to initialize this to a semi-random location along the positive X axis.
| | <code>visgroupid</code>属性可多次定义使笔刷归属多个可视组。<code>group</code>属性定义笔刷所属的{{L|Grouping_and_VisGrouping#groups|可见组}}(值为笔刷首个子组ID)。<code>visgroupshown</code>属性存在设计矛盾——在组内每个笔刷定义组可见性会导致异常显示。<code>comments</code>属性允许为实体添加开发者注释(在实体属性窗口的"类信息"面板查看),非实体元素上的注释将被Hammer删除。"逻辑视图"是部分Hammer版本中半成品流程图视图,<code>logicalpos</code>存储实体在此视图的位置(默认初始化为X轴正半轴随机位置)。 |
|
| |
|
| == Group == | | === 组 === |
| This class sets the brush [[Grouping_and_VisGrouping#groups|groups]] that exist and their properties. It also defines their hierarchy.
| | 此类定义{{L|Grouping_and_VisGrouping#groups|可见组}}及其层级结构: |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| group | | group |
Line 479: |
Line 471: |
| } | | } |
| </nowiki>}} | | </nowiki>}} |
| *'''id(int)''' | | *'''id(整数)''' |
| :This is a unique number among other group ids. | | :组ID中的唯一值 |
| *[[Valve Map Format#Editor|editor{}]] | | *[[Zh/VMF_(Valve_Map_Format)#编辑器|editor{}]] |
|
| |
|
| A group is assigned one id, the brush itself states whether or not it is within the group. The definition for the <code>[[Valve Map Format#Editor|editor]]</code> Class is included again. This is important because it is how the hierarchy of all the groups is maintained. If one group is a child to another it then includes the group id within its <code>[[Valve Map Format#Editor|editor]]</code> subclass. That defines it is a sub group of the parent group, so when the parent groups break all the child groups will remain intact.
| | 组分配唯一ID,笔刷通过声明<code>groupid</code>归属组。嵌套的<code>[[Zh/VMF_(Valve_Map_Format)#Editor|editor]]</code>类维护组层级:子组在其<code>editor</code>类中包含父组ID。当父组解散时,子组保持完整结构。 |
|
| |
|
| == Hidden == | | === 隐藏 === |
| There are two versions of the hidden class, but both include classes which have the <code>visgroupshown</code> or <code>autovisgroupshown</code> in [[Valve Map Format#Editor|<code>editor</code>]] set to "0".
| | 存在两种隐藏类,均包含<code>visgroupshown</code>或<code>autovisgroupshown</code>设为"0"的元素: |
|
| |
|
| The first type is in the [[Valve Map Format#World|<code>world</code>]] and [[Valve Map Format#Entity|<code>entity</code>]] class
| | **类型1**(位于{{L|Valve Map Format#World|world}}和{{L|Valve Map Format#Entity|entity}}类): |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| hidden | | hidden |
Line 495: |
Line 487: |
| } | | } |
| </nowiki>}} | | </nowiki>}} |
| *[[Valve Map Format#Solid|solid{}]] | | *[[Zh/VMF_(Valve_Map_Format)#Solid|solid{}]] |
|
| |
|
| This is very simple, just every hidden solid that would usually be held under <code>world</code> or <code>entity</code> is instead held under this. There's no other difference. Hammer itself will show solids under "hidden" if both of the visgroupshown properties are true.
| | 简单存储所有隐藏笔刷。当<code>visgroupshown</code>和<code>autovisgroupshown</code>均为真时,Hammer会显示这些笔刷。 |
|
| |
|
| | | **类型2**(位于{{L|Valve Map Format#Usual Structure|文件根}}): |
| The second type is under [[Valve Map Format#Usual Structure|the file itself]]:
| |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| hidden | | hidden |
Line 507: |
Line 498: |
| } | | } |
| </nowiki>}} | | </nowiki>}} |
| *[[Valve Map Format#Entity|entity{}]] | | *[[Zh/VMF_(Valve_Map_Format)#Entity|entity{}]] |
|
| |
|
| As with the other version this is simple, it simply holds the entity which is hidden. No other difference is visible. Again, Hammer will show entities with both <code>visgroupshown</code> properties set to true, even if it is under "hidden".
| | 存储隐藏实体。当两个可见性属性均为真时,Hammer仍会显示这些实体。 |
|
| |
|
| == Entity == | | === 实体 === |
| Both brush and point based entities are defined in the same way. Both are defined outside of the <code>[[Valve Map Format#World|world]]</code> class as the <code>[[Valve Map Format#World|world]]</code> class itself is an entity. All entities work in the same way: you define its properties and then either give the entity solids to inhabit or a point to exist at.
| | 笔刷实体与点实体定义方式相同,均在<code>{{L|Valve Map Format#World|world}}</code>类外定义(因world类本身是实体)。所有实体结构相同:定义属性后赋予笔刷或位置点。 |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| entity | | entity |
Line 527: |
Line 518: |
| } | | } |
| </nowiki>}} | | </nowiki>}} |
| *'''id(int)''' | | *'''id(整数)''' |
| :This is a unique number among other entity ids. | | :实体ID中的唯一值 |
| *'''classname(sz)''' | | *'''classname(字符串)''' |
| :This is the name of the entity class. | | :实体类名 |
| *'''spawnflags(int)''' | | *'''spawnflags(整数)''' |
| :Indicates which flags are enabled on the entity. | | :实体启用的标志位 |
| *'''origin(vertex)''' | | *'''origin(顶点)''' |
| :This is the point where the point entity exists. | | :点实体的存在位置 |
| *[[#Connections|connections{}]] | | *{{L|#Connections|connections{}}} |
| *[[#Solid|solid{}]] | | *{{L|#Solid|solid{}}} |
| *[[#Editor|editor{}]] | | *{{L|#Editor|editor{}}} |
| *[[#hidden|hidden{}]] | | *{{L|#hidden|hidden{}}} |
| *[[#OverlayTransition|overlaytransition{}]] | | *{{L|#OverlayTransition|overlaytransition{}}} |
|
| |
|
| There are several lines that are important. First is the underscores, this is a placeholder for all the entities properties and values. These are the exact same thing seen with smart edit disabled in Hammer. The properties and values can be anything, but only valid properties will mean anything when compiled. It may be wise to review the definition of the <code>[[Valve Map Format#World|world]]</code> Class and the [[Worldspawn]] entity. With entities the possible values and properties extend far beyond the scope of this document and should be reviewed independently.
| | 关键元素说明: |
| Second is the <code>connections{}</code> Class. This is all the i/o information and is optional.
| | 1. 下划线部分:实体所有属性键值对(与Hammer禁用"智能编辑"时显示一致) |
| Third, is the solid line. Defining a <code>[[Valve Map Format#Solid|solid]]</code> subclass will make it a brush based entity; having both an origin and solid will make a brush based entity with an origin property. Defining only an <code>origin</code> will make it a point based entity. Any missing entity properties will be recreated from default upon compiling and do not have to be saved.
| | 2. <code>connections{}</code>类:可选的I/O连接信息 |
| | 3. <code>solid{}</code>子类:存在时转为笔刷实体 |
| | 4. <code>origin</code>属性:存在时转为点实体 |
| | 5. 同时存在<code>solid</code>和<code>origin</code>:笔刷实体带原点属性 |
| | 缺失属性将在编译时按默认值重建。 |
|
| |
|
| === Connections === | | ==== 连接 ==== |
| This is where all the outputs for an entity are stored. Inputs are not stored as they are simply traced from the outputs. Therefore only the outputs are stored in this optional class.
| | 存储实体所有输出(输入通过输出反向追踪,故不存储): |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| connections | | connections |
Line 554: |
Line 549: |
| } | | } |
| </nowiki>}} | | </nowiki>}} |
| *'''Output(sz,Input,sz,dec,bool)''' | | *'''输出(事件,目标,输入,参数,延迟,次数)''' |
| :The entire output event stored in 1 string. | | :整个输出事件存储为单字符串 |
| | |
| The string is pretty simple to decompose. The property is the output event triggering another entities input. The value on the other hand, is either a comma separated string (pre-{{l4d2}}) or an escape character (byte: 0x1b) separated string of the rest of the output's properties. First is the target entity name or class. Second is the Input being triggered on the target object(s). Third is the parameter override, leave blank for no value. Fourth being the delay before triggering. The final parameter is the number of times to fire, or -1 to always fire. To create multiple outputs you simply add more properties.
| |
|
| |
|
| Note that this is one string which Hammer does not make assumptions about. If you omit any value (except the last one) Hammer will crash with an unhelpful error message. If you omit the last value, which is the number of times to fire, Hammer sets it to 1 or Fire Once.
| | 字符串结构({{l4d2}}前为逗号分隔): |
| | 1. 目标实体名或类名 |
| | 2. 触发的目标输入 |
| | 3. 覆盖参数(空表示无) |
| | 4. 触发延迟(秒) |
| | 5. 触发次数(-1=无限) |
|
| |
|
| == OverlayTransition ==
| | > 注意:省略除末位外的任何值将导致Hammer崩溃,省略末位值默认为1(触发一次)。 |
| {{todo|[[info_overlay_transition]] stores information in a special block, document this.}}
| |
|
| |
|
| == Cameras == | | ==== 覆盖层过渡 ==== |
| Used for the 3D viewport cameras used in Hammer, created with the [[Hammer_Camera_Tool|Camera Tool]]. These cameras are not used in-engine and are not compiled into the final .BSP.
| | {{todo|{{L|info_overlay_transition}}在特殊块存储信息,待补充文档}} |
|
| |
|
| | === 摄像机 === |
| | 存储Hammer的3D视口摄像机(通过{{L|Hammer_Camera_Tool|摄像机工具}}创建),不编译进BSP文件。 |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| cameras | | cameras |
Line 589: |
Line 588: |
| </nowiki>}} | | </nowiki>}} |
|
| |
|
| | 无摄像机时: |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| cameras | | cameras |
Line 596: |
Line 596: |
| </nowiki>}} | | </nowiki>}} |
|
| |
|
| *'''activecamera (int)''' | | *'''activecamera (整数)''' |
| : Sets the currently active camera used for the Hammer 3D View. When no cameras are present in the .VMF, this value is set to -1 and the camera position defaults to the world origin, facing North. | | : 设置Hammer 3D视图的当前摄像机(-1=无摄像机,默认定位世界原点朝北) |
| | | *'''position (顶点)''' |
| *'''position (vertex)''' | | : 摄像机在空间中的眼睛位置 |
| : The eye position of the camera in the map. | | *'''look (顶点)''' |
| | : 摄像机目标点位置 |
|
| |
|
| *'''look (vertex)'''
| | === 隔离区 === |
| : The position of the camera target -- the point the camera is looking toward.
| | 存储{{L|Hammer_Cordon_Tool|隔离工具}}所需信息: |
| | |
| == Cordon == | |
| This stores all the information Hammer needs and uses for its cordon tool.
| |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| cordon | | cordon |
Line 615: |
Line 613: |
| } | | } |
| </nowiki>}} | | </nowiki>}} |
| *'''mins (vertex)''' | | *'''mins (顶点)''' |
| :The top right upper co-ordinate. | | :矩形区域右上角坐标 |
| *'''maxs (vertex)''' | | *'''maxs (顶点)''' |
| :The bottom left lower co-ordinate. | | :矩形区域左下角坐标 |
| *'''active (bool)''' | | *'''active (布尔值)''' |
| :Whether or not the cordon is turned on. | | :是否启用隔离区 |
|
| |
|
| | 两点定义的空间外对象将被排除渲染/编译。 |
|
| |
|
| After the 2 points are defined, a rectangular prism is drawn between the two points. This will make any object that is outside the prism excluded from rendering or compiling.
| | 新版Hammer(L4D起)格式: |
| | |
| In newer Hammer versions (L4D onwards)
| |
| {{pre|<nowiki> | | {{pre|<nowiki> |
| cordons | | cordons |
Line 642: |
Line 639: |
| } | | } |
| </nowiki>}} | | </nowiki>}} |
| | 隔离区组(<code>cordons</code>)包含多个隔离区(<code>cordon</code>),每个隔离区由<code>mins</code>/<code>maxs</code>定义矩形区域。 |
|
| |
|
| Cordons are in a group cordons and a cordon itself is a set of boxes defined by mins and maxs. (See above)
| | === CSG(构造实体几何) === |
| | | 如{{L|VMF_(Valve_Map_Format)#平面|平面}}章节所述,笔刷最终形状通过CSG操作生成。主要方法: |
| == CSG (Constructive Solid Geometry) == | | 1. 相交法:计算平面间交线定义笔刷边 |
| As stated in [[VMF_(Valve_Map_Format)#Planes|Planes]] section - a final shape of a brush is constructed using CSG operations. There exist two main methods of obtaining the final shape - intersection method and clipping method (originally used in Quake). The intersection method, for every side of the brush, calculates the intersection points with other planes. The clipping method starts with a big quad, spanning the entire map area, aligned with the currently constructed side, being repeatedly clipped using the planes of other sides. In other words - the final shape of a side is obtained by cutting it and leaving only the portion that is inside the volume of a brush.
| | 2. 裁剪法(源自Quake):从对齐当前面的大四边形开始,用其他面反复裁剪 |
| Details about both processes are included in the article linked in [[VMF_(Valve_Map_Format)#Additional_resources|Additional resources]] section.
| | {{L|VMF_(Valve_Map_Format)#附加资源|附加资源}}提供详细说明。 |
| [[File:csg_clipping.gif|frame|A brush being constructed using the clipping method]] | | [[File:csg_clipping.gif|frame|裁剪法构建笔刷过程]] |
| | |
| == Conclusion ==
| |
| That's all the information on the .vmf file format that Hammer will generate. This hopefully covers all possible questions and enables anyone to do what they wish with the file format. Below are some files for use as reference or used for the experiments that revealed how the format is laid out.
| |
|
| |
|
| == Additional resources == | | === 结语 === |
| * [https://github.com/jakgor471/vmf-files_webgl/blob/main/vmffiles.pdf VMF Files - converting brushes into a 3D mesh] - detailed description of the CSG process of constructing brushes.
| | 本文涵盖Hammer生成的.vmf文件所有信息。以下提供参考文件及格式解析实验素材: |
|
| |
|
| [[Category:File formats|vmf]]
| | === 附加资源 === |
| [[Category:Files|vmf]] | | * [https://github.com/jakgor471/vmf-files_webgl/blob/main/vmffiles.pdf VMF文件:将笔刷转换为3D网格] - CSG构建笔刷的详细说明 |
| [[Category:Programming]]<!--How exactly this is relevant?-->
| |
| [[Category:Level Design]]<!--How exactly this is relevant?-->
| |
| [[Category:Glossary]]
| |
| [[Category:Hammer|vmf]]
| |
|
| |
|
| | {{ACategory|File formats|文件格式}} |
| | {{ACategory|Files|文件}} |
| | {{ACategory|Programming|编程}} |
| | {{ACategory|Level Design|关卡设计}} |
| | {{ACategory|Glossary|术语表}} |
| | {{ACategory|Hammer|vmf}} |
|
| |
|
| {{stub}} | | {{stub}} |
Valve地图格式(VMF)是一种纯文本文件格式,用于存储原始(预编译)地图数据,由Valve Hammer Editor(en)(4.0版起)用于保存生产阶段的地图和预置件(en)。它以KeyValues(en)格式存储所有地图笔刷和实体的信息,文件扩展名为".vmf"。
.vmf文件是专为
起源设计的地图源代码。与任何源代码文件一样,它必须经过编译才能使用,因此设计目标是易于阅读和编辑而非执行效率。文件采用Source引擎常用的易读编码形式。本文档将详细说明.vmf文件中定义的所有内容,包括各项元素的含义及其表示方式。这不是带结果的教程,而是对其背后原理的解析。本文档基于2006年1月1日Source SDK Beta(en)中Hammer 4.1生成的文件编写。
.vmf文件结构
.vmf中的代码结构简单易懂,这种结构在引擎的许多其他部分也很常见。以下是面向初学者的结构概述及术语说明:
// 这是注释
类名_1
{
"属性_1" "值_1"
"属性_2" "值_2"
类名_2
{
"属性_1" "值_1"
}
}
所示名称仅为占位符,采用它们将被引用的命名规范:类(Classes)、属性(Properties)和值(Values)。本文档每节结构相同:标题为要解释的类名,随后简要说明该类定义的内容,下方提供代码示例,最后列出每个属性及其有效数据类型和解释。.vmf文件仅包含几种数据类型:
标记 |
说明
|
int |
整数值
|
dec |
十进制数值
|
sz |
字符串
|
bool |
布尔值(true/false的二进制表示)
|
vertex |
XYZ坐标点,由3个用空格分隔的十进制值表示
|
rgb |
颜色值,使用3个0-255的整数(分别对应红/绿/蓝通道),空格分隔
|
属性说明将紧接在代码示例下方,按以下格式呈现:
- 解释该属性的含义及取值注意事项。
当某个属性需要单独解释,或是某类的属性实为另一个独立类时,将在代码示例下方添加链接说明。这表示该内容有独立章节解释,不包含在当前类定义中。所有属性定义后,将整体讨论该类及其属性对最终结果的影响。
常规结构
.vmf文件的常规结构如下:
versioninfo{}
visgroups{}
viewsettings{}
world{}
entity{}
hidden{}
cameras{}
cordon{}
各章节功能可以单击结构跳到对应说明。
注意:顺序对Hammer不重要,但VBSP可能在特定类顺序错误时报错(如“Error: displacement found on a(n) worldspawn entity...”)。在Hammer中重新打开并保存地图可恢复默认顺序。
版本信息
此类包含Hammer创建文件的版本信息和保存次数,本质是文件头,与地图内容无关:
versioninfo
{
"editorversion" "400"
"editorbuild" "3325"
"mapversion" "0"
"formatversion" "100"
"prefab" "0"
}
- 创建文件所用的Hammer版本,4.00版对应"400"
- 生成文件时Hammer的补丁号
- 文件保存次数,用于比较新旧版本
- 未知(很可能是VMF文件格式版本)
- 标识是否为完整地图或预置件(en)对象集合
由于从未生成过不同值,formatversion
含义未知。修改该值无效,保存或编译时会被重置为"100"。prefab
属性定义文件是否包含由笔刷/实体组成的对象(如沙发)而非完整地图。若缺失任何信息,Hammer将按当前状态重建。
可视组(VisGroup)
此类通常为空,但包含Hammer中所有唯一的可视组(en)定义及其结构和属性。以下示例展示完整结构:
visgroups
{
visgroup
{
"name" "Tree_1"
"visgroupid" "5"
"color" "65 45 0"
}
visgroup
{
"name" "Tree_2"
"visgroupid" "1"
"color" "60 35 0"
visgroup
{
"name" "Branch_1"
"visgroupid" "2"
"color" "0 192 0"
}
visgroup
{
"name" "Branch_2"
"visgroupid" "3"
"color" "0 255 0"
visgroup
{
"name" "Leaf"
"visgroupid" "4"
"color" "255 0 0"
}
}
}
}
- 组名称,是Hammer中的唯一标识符
- 所有可视组ID中唯一的值,重复会导致Hammer轻微异常
- 组的颜色,可应用于Hammer中的笔刷轮廓
可视组(en)与编译的VIS无关。新版Hammer中有两种类型:自动组(由Hammer按笔刷/实体类型生成,不在此定义)和用户创建的自定义组(en)(在此类中定义)。组采用层次树结构,即一个组可以是父组并包含子组。对父组的操作会影响子组,但子组不影响父组。要定义子组,需在父组定义内嵌套该组(见示例)。组结构复杂度无限制,但超过128组会导致Hammer异常。允许多个visgroups类,但Hammer会将其合并。
视图设置
此类包含Hammer中地图特定的视图属性,其他属性不存入地图:
viewsettings
{
"bSnapToGrid" "1"
"bShowGrid" "1"
"bShowLogicalGrid" "0"
"nGridSpacing" "64"
"bShow3DGrid" "0"
}
- 是否启用网格吸附功能
- 是否显示2D网格
- 是否在隐藏的逻辑视图(en)中显示网格
- 网格线间距值
- 是否显示3D网格
若bSnapToGrid
为真,Hammer会强制用户操作点对齐nGridSpacing
倍数(不影响已载入顶点)。其他Hammer属性设置仅作用于编辑器。缺失信息将被重置为默认值。
World
.vmf文件中,world类包含Hammer的所有世界笔刷信息(即无实体附加的笔刷)。world
类形式与其他实体相同但有特殊属性:
world
{
"id" "1"
"mapversion" "1"
"classname" "worldspawn"
"skyname" "sky_wasteland02"
Solid{}
Hidden{}
Group{}
}
- 世界类ID中的唯一值
- 来自versioninfo类的mapversion副本
- 声明世界实体的类型
- 使用的天空盒名称
World类定义实际采用实体形式,可包含大量属性(此处省略)。关键点:World的classname
必须为"worldspawn",否则地图无法正确定义和编译("worldspawn"是游戏必需的实体类型)。编译时必须包含skyname
属性避免错误。允许多个world类,但Hammer会合并为单个定义(保留首个类的属性,后续同名属性覆盖前者)。
笔刷
此类代表Hammer中的单个笔刷,含1个属性和2个子类。笔刷由其所有围成形状的面定义。无效笔刷会导致Hammer拒绝加载或自动修复。
solid
{
"id" "1"
side{}
editor{}
}
- 笔刷ID中的唯一值,重复会导致轻微异常
solid
类必须定义至少四个面。因Hammer计算方式,无效笔刷会导致编辑器或游戏错误。
面
此类定义单面的所有相关数据(朝向、纹理和属性)。plane属性定义面的朝向,面边界由相交平面计算得出故不存储。u轴/v轴属性需单独解释:
side
{
"id" "6"
"plane" "(512 -512 -512) (-512 -512 -512) (-512 -512 512)"
"material" "BRICK/BRICKFLOOR001A"
"uaxis" "[1 0 0 0] 0.25"
"vaxis" "[0 0 -1 0] 0.25"
"rotation" "0"
"lightmapscale" "16"
"smoothing_groups" "0"
"contents" "1"
"flags" "0"
dispinfo{}
}
- 面ID中的唯一值,重复会导致轻微异常
- 面所应用纹理的路径和名称
- 面纹理的旋转角度(实际由u/v轴计算,此值仅用于显示)
- 面的光照贴图分辨率
- 面所用的平滑组(en)
- contents (bitfield)
- flags (bitfield)
- 内容/表面标志(定义于

public/bspflags.h
),十进制存储
- 被
Hammer 4.x剥离但编译器读取,使用
Hammer++或相关笔刷放入独立instance(en)处理
ID值在笔刷间也需唯一(因立方体贴图(en)等实体需引用特定面)。lightmapscale
定义编译时应用于面的光照块大小。smoothing_groups
表示面所属的平滑组(en),组内相邻面的光照差异将被平滑处理。通过转二进制可确定分组(最低位为1表示在第1组,最高位为1表示在第32组)。
平面
平面是基本的二维对象,可视为三维世界中无限延伸的平坦薄片。平面相交形成笔刷的边和顶点。
"plane" "(0 0 0) (0 0 0) (0 0 0)"
- 定义用于确定平面在三维空间中朝向和位置的三个点
使用三个有序点确定平面朝向,这些点如同支撑纸张的物体。点的高度差异会使平面倾斜,通过调整点的高度可旋转平面。平面必须穿过所有三个定义点,这些点共同决定平面朝向。平面朝向由点的定义顺序决定:从特定方向观察时顺时针定义的点序会使平面朝该方向可见。
以下示例生成32x32地板的平面(z轴平面朝上):
"plane" "(-16 -16 0) (16 -16 0) (16 16 0)"
三个点分别代表面的左下角、左上角和右上角。从顶部观察呈顺时针顺序,因此平面朝上。顶点间距32单位,形成正方形地板。
右侧动画展示通过CSG从六个平面构建简单笔刷的过程(详见附加资源(en))。红/绿/蓝点分别代表第一/二/三点。该笔刷的平面点如下:
"plane" "(-128 32 128) (128 32 128) (128 0 128)"
"plane" "(-128 0 0) (128 0 0) (128 32 0)"
"plane" "(-128 32 128) (-128 0 128) (-128 0 0)"
"plane" "(128 32 0) (128 0 0) (128 0 128)"
"plane" "(128 32 128) (-128 32 128) (-128 32 0)"
"plane" "(128 0 0) (-128 0 0) (-128 0 128)"
关键注意事项示例:
"plane" "(-32 -32 0) (32 -32 0) (32 32 0)"
"plane" "(32 -32 0) (32 32 0) (-32 32 0)"
"plane" "(32 32 0) (-32 32 0) (-32 -32 0)"
"plane" "(-32 32 0) (-32 -32 0) (32 -32 0)"
以上定义均生成相同平面。同一面上的不同点序始终定义相同平面,否则笔刷无效。
面的所有边顶点由笔刷各平面相交确定:顶点是三个及以上平面的交点,边是两个平面沿线的交线。此为基础定义不可更改。问题在于顶点用于定义平面,因此交点必须严格匹配,否则将生成无效笔刷。定义平面时,任何其他定义顶点必须位于该平面或笔刷内其他平面上。
U/V轴
u轴和v轴是纹理专用坐标系。u轴对应x轴,v轴对应y轴,两者共同定义纹理在面上的显示方式。
"uaxis" "[1 0 0 0] 0.25"
"vaxis" "[0 1 0 0] 0.25"
- xyz为十进制值代表轴向,随后是平移值,末尾为总缩放值
xyz值决定纹理在对应轴的显示比例。值1表示在标准空间显示一次完整纹理,值2表示显示两次。此设置仅应用于纹理的单一轴,且相对于真实xyz轴。这意味着可将纹理设置在平面不存在的轴上(如xy平面无需z轴定义)。负值会翻转纹理,若纹理显示在平面不存在的轴上,Hammer将报错。
倒数第二个值是纹理原点的平移量(Hammer显示时四舍五入但保存精确值)。末尾十进制是包含xyz定义的总缩放值。缩放比为1时,纹理1像素对应1Hammer单位。
位移信息
dispinfo
类处理位移(en)的所有信息。每个顶点信息独立存储,产生大量需整理的数据。该类仅当面为位移(en)时存在,属性覆盖原始面的属性。
dispinfo
{
"power" "2"
"startposition" "[-512 -512 0]"
"elevation" "0"
"subdiv" "0"
normals{}
distances{}
offsets{}
offset_normals{}
alphas{}
triangle_tags{}
allowed_verts{}
}
- 计算行列数的幂值(仅此三值可编译)。缺省时Hammer假定为4。若数据基于其他幂值,顶点数据将被挤压到起始角
- 左下角在xyz空间的实际位置
- 沿顶点法线方向作用于所有点的整体位移
- 标记是否进行细分位移(en)
- [[Zh/VMF_(Valve_Map_Format)#Normals|法线{}}}
- [[Zh/VMF_(Valve_Map_Format)#Distances|距离{}}}
- [[Zh/VMF_(Valve_Map_Format)#Offsets|偏移{}}}
- [[Zh/VMF_(Valve_Map_Format)#Offset_normals|offset_normals{}}}
- [[Zh/VMF_(Valve_Map_Format)#Alpha|alpha{}}}
- [[Zh/VMF_(Valve_Map_Format)#Traingle_tags|traingle_tags{}}}
- [[Zh/VMF_(Valve_Map_Format)#Allowed_verts|allowed_verts{}}}
Hammer中存在临时值"scale",不存入文件仅影响当前移动缩放。
所有基于网格的子类遵循相同规则:行数公式为2n+1(n=power值)。行号从startposition
定义的0号顶点开始。每行以row#存储,#为行号(部分列含多个值)。
法线
此类定义各顶点的法线(从面朝外指向的线),用于光照着色和顶点定位:
normals
{
"row0" "X0 Y0 Z0 X1 Y1 Z1 X2 Y2 Z2 X3 Y3 Z3 X4 Y4 Z4"
"row1" "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"
"row2" "0 0 1 0 0 1 0 0 1 0 0 1 0 0 1"
"row3" "0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1"
"row4" "0 0 1 0 0 -1 0 0 -1 0 0 -1 0 0 1"
}
- row# ((x y z) (x y z) ...)
- 每组十进制值定义顶点的法线
法线是从顶点绘制的单位长度假想线。十进制值代表线在各轴的分量(纯轴向为1,斜面则含多轴分量)。法线决定地面位移(en)的光照方式及顶点最终位置。示例中:第1行全部朝上(0,0,1),第2行朝下(0,0,-1),第3行内侧三点朝下、外侧两点朝上。
> 注意:朝上法线(0,0,1)配合负距离等效于朝下法线(0,0,-1)配合正距离。
距离
距离值表示顶点沿法线移动的量(非法线则距离不生效):
distances
{
"row0" "#0 #1 #2 #3 #4"
"row1" "0 0 0 0 0 "
"row2" "64 64 64 64 64"
"row3" "64 64 64 64 64"
"row4" "32 32 32 32 32"
}
- 顶点沿法线移动的最终距离
距离值使顶点沿法线方向移动形成最终位置。结合法线(en)类数据可构建位移贴图形状。若使用示例中的2-4行数据:第2行上移64单位,第3行下移64单位,第4行外侧两点上移32单位、内侧三点下移32单位。
偏移
此类定义位移贴图各顶点的默认位置,距离(en)值以此为基准计算:
offsets
{
"row0" "X0 Y0 Z0 X1 Y1 Z1 X2 Y2 Z2 X3 Y3 Z3 X4 Y4 Z4"
"row1" "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"
"row2" "0 0 64 0 0 64 0 0 64 0 0 64 0 0 64"
"row3" "0 0 -64 0 0 -64 0 0 -64 0 0 -64 0 0 -64"
"row4" "0 0 32 0 0 -32 0 0 -32 0 0 -32 0 0 32"
}
- 相对于原始位置的顶点新位置
offsets
定义相对于原始计算位置的新顶点位置。本例数据与前两个类组合效果相同。Hammer不修改这些点。
偏移法线
此类与法线类几乎相同(数据结构一致)。差异在于功能:此类定义法线类的基准法线,不影响偏移类。Hammer无法直接修改这些值,仅能根据面朝向自动设置。
透明度
此类包含各顶点的透明度值(0-255),用于地面位移(en)。值间差异通过线性插值混合。
alphas
{
"row0" "#0 #1 #2 #3 #4"
"row1" "0 0 0 0 0 "
"row2" "255 255 255 255 255"
"row3" "0 0 0 0 0"
"row4" "128 0 0 0 128"
}
- 0-255的十进制值
值表示次纹理覆盖基础纹理的程度。示例:第1行纯次纹理(255),第2行纯基础纹理(0),第3行外侧两点半透明(128),内侧三点纯基础纹理(0)。
三角标记
此类存储位移中每个三角形(非顶点)的信息。数据量由2n决定(n=power值),行列号从起点向外定义。
triangle_tags
{
"row0" "#0 #0 #1 #1 #2 #2 #3 #3 #4 #4"
"row1" "9 9 9 9 9 9 9 9"
"row2" "0 0 0 0 0 0 0 0"
"row3" "1 1 1 1 1 1 1 1"
"row4" "9 9 9 9 9 9 9 9"
}
- row# (((0,1,9) (0,1,9))...)
- 每组代表一个正方形内的两个三角形,仅0/1/9可编译
值定义三角形朝向:"9"=z轴坡度极小;"1"=z轴坡度可步行;"0"=z轴坡度不可攀爬。Hammer接受任意值(如"2"在可步行区域视图(en)显示绿色高亮),但非0/1/9值编译失败。
允许顶点
此类影响位移贴图的游戏端曲面细分,标记与其他位移贴图共享边但不共享顶点的顶点。
allowed_verts
{
"10" "-1 -1 -1 -1 -1 -1 -1 -1 -1 -1"
}
- 二进制标志集(-1=全启用),false值将在编译时移除顶点
Hammer中此属性无视觉效果,启用可折叠顶点显示(en)后,禁用顶点显示为粉色立方体。编译时禁用顶点与其相邻点插值拟合(对比编辑器与游戏效果)。
编辑器
此类信息仅供Hammer使用,与地图本身无关:
editor
{
"color" "0 255 0"
"visgroupid" "2"
"groupid" "7"
"visgroupshown" "1"
"visgroupautoshown" "1"
"comments" "仅存在于实体上"
"logicalpos" "[34 28]"
}
- 笔刷轮廓线和平面的显示颜色
- 笔刷所属可视组ID
- 笔刷所属可见组ID
- 该组是否可见
- 自动组是否可见
- 在"类信息"选项卡显示的注释(仅实体有效)
- 实体在隐藏的逻辑视图(en)中的位置
visgroupid
属性可多次定义使笔刷归属多个可视组。group
属性定义笔刷所属的可见组(en)(值为笔刷首个子组ID)。visgroupshown
属性存在设计矛盾——在组内每个笔刷定义组可见性会导致异常显示。comments
属性允许为实体添加开发者注释(在实体属性窗口的"类信息"面板查看),非实体元素上的注释将被Hammer删除。"逻辑视图"是部分Hammer版本中半成品流程图视图,logicalpos
存储实体在此视图的位置(默认初始化为X轴正半轴随机位置)。
组
此类定义可见组(en)及其层级结构:
group
{
"id" "7"
editor{}
}
- 组ID中的唯一值
组分配唯一ID,笔刷通过声明groupid
归属组。嵌套的editor
类维护组层级:子组在其editor
类中包含父组ID。当父组解散时,子组保持完整结构。
隐藏
存在两种隐藏类,均包含visgroupshown
或autovisgroupshown
设为"0"的元素:
hidden
{
solid{}
}
简单存储所有隐藏笔刷。当visgroupshown
和autovisgroupshown
均为真时,Hammer会显示这些笔刷。
hidden
{
entity{}
}
存储隐藏实体。当两个可见性属性均为真时,Hammer仍会显示这些实体。
实体
笔刷实体与点实体定义方式相同,均在world(en)
类外定义(因world类本身是实体)。所有实体结构相同:定义属性后赋予笔刷或位置点。
entity
{
"id" "19"
"classname" "func_detail"
"spawnflags" "0"
______
connections{}
solid{}
hidden{}
"origin" "-512 0 0"
editor{}
}
- 实体ID中的唯一值
- 实体类名
- 实体启用的标志位
- 点实体的存在位置
- Connections|connections{]](en)}
- Solid|solid{]](en)}
- Editor|editor{]](en)}
- hidden|hidden{]](en)}
- OverlayTransition|overlaytransition{]](en)}
关键元素说明:
1. 下划线部分:实体所有属性键值对(与Hammer禁用"智能编辑"时显示一致)
2. connections{}
类:可选的I/O连接信息
3. solid{}
子类:存在时转为笔刷实体
4. origin
属性:存在时转为点实体
5. 同时存在solid
和origin
:笔刷实体带原点属性
缺失属性将在编译时按默认值重建。
连接
存储实体所有输出(输入通过输出反向追踪,故不存储):
connections
{
"OnTrigger" "bob,Color,255 255 0,1.23,1"
"OnTrigger" "bob,ToggleSprite,,3.14,-1"
}
- 整个输出事件存储为单字符串
字符串结构(
前为逗号分隔):
1. 目标实体名或类名
2. 触发的目标输入
3. 覆盖参数(空表示无)
4. 触发延迟(秒)
5. 触发次数(-1=无限)
> 注意:省略除末位外的任何值将导致Hammer崩溃,省略末位值默认为1(触发一次)。
覆盖层过渡
摄像机
存储Hammer的3D视口摄像机(通过摄像机工具(en)创建),不编译进BSP文件。
cameras
{
"activecamera" "1"
camera
{
"position" "[-1093.7 1844.91 408.455]"
"look" "[-853.42 1937.5 175.863]"
}
camera
{
"position" "[692.788 1394.95 339.652]"
"look" "[508.378 1493 347.127]"
}
camera
{
"position" "[-4613.89 2528.77 -2834.88]"
"look" "[-4533.53 2950.1 -2896.85]"
}
}
无摄像机时:
cameras
{
"activecamera" "-1"
}
- 设置Hammer 3D视图的当前摄像机(-1=无摄像机,默认定位世界原点朝北)
- 摄像机在空间中的眼睛位置
- 摄像机目标点位置
隔离区
存储隔离工具(en)所需信息:
cordon
{
"mins" "(99999 99999 99999)"
"maxs" "(-99999 -99999 -99999)"
"active" "0"
}
- 矩形区域右上角坐标
- 矩形区域左下角坐标
- 是否启用隔离区
两点定义的空间外对象将被排除渲染/编译。
新版Hammer(L4D起)格式:
cordons
{
"active" "0"
cordon
{
"name" "cordon"
"active" "1"
box
{
"mins" "(-1204 -1512 -748)"
"maxs" "(836 444 1128)"
}
}
}
隔离区组(cordons
)包含多个隔离区(cordon
),每个隔离区由mins
/maxs
定义矩形区域。
CSG(构造实体几何)
如平面(en)章节所述,笔刷最终形状通过CSG操作生成。主要方法:
1. 相交法:计算平面间交线定义笔刷边
2. 裁剪法(源自Quake):从对齐当前面的大四边形开始,用其他面反复裁剪
附加资源(en)提供详细说明。
裁剪法构建笔刷过程
结语
本文涵盖Hammer生成的.vmf文件所有信息。以下提供参考文件及格式解析实验素材:
附加资源
小作品
This article or section is a stub. You can help by expanding it.