Biovision BVH

The BVH file format was originally developed by Biovision, a motion capture services company, as a way to provide motion capture data to their customers. The name BVH stands for Biovision hierarchical data. This format mostly replaced an earlier format that they developed, the BVA format which is discussed in the next section, as a way to provide skeleton hierarchy information in addition to the motion data. The BVH format is an excellent all around format, its only drawback is the lack of a full definition of the basis pose (this format has only translational offsets of children segments from their parent, no rotational offset is defined), it also lacks explicit information for how to draw the segments but that has no bearing on the definition of the motion.

BVH文件格式最初由动作捕捉服务公司Biovision开发,作为向客户提供动作捕捉数据的一种方式。BVH的全称是Biovision层次数据(Biovision Hierarchical Data)。这种格式主要取代了他们之前开发的BVA格式(在下一节中讨论),不仅提供了运动数据,还包含了骨架层次信息。BVH格式是一个全方位的优秀格式,其唯一的缺点是缺乏对基本姿态的完整定义(这种格式只有子段相对于父段的平移偏移,没有定义旋转偏移),也缺乏如何绘制段的显式信息,但这对运动定义没有影响。

Parsing the file

A BVH file has two parts, a header section which describes the hierarchy and initial pose of the skeleton; and a data section which contains the motion data. Examine the example BVH file called Example1.bvh. The start of the header section begins with the keyword “HIERARCHY”. The following line starts with the keyword “ROOT” followed by the name of the root segment of the hierarchy to be defined. After this hierarchy is described it is permissable to define another hierarchy, this too would be denoted by the keyword “ROOT”. In principle, a BVH file many contain any number of skeleton hierarchies. In practice the number of segments is limited by the format of the motion section, one sample in time for all segments is on one line of data and this will cause problems for readers which assume a limit to the size of a line in a file.

BVH文件有两部分,头部分描述骨架的层次和初始姿态;数据部分包含运动数据。请查看名为Example1.bvh的示例BVH文件。头部分的开始以关键词HIERARCHY开头。下一行以关键词ROOT开头,后跟要定义的层次结构的根段名称。在描述了这个层次结构后,可以定义另一个层次结构,这也用关键词ROOT表示。原则上,一个BVH文件可以包含任意数量的骨架层次结构。实际上,段的数量受到运动部分格式的限制,一个时间样本中的所有段在数据的一行上,这会给假定文件中行大小有限的读者带来问题。

The BVH format now becomes a recursive definition. Each segment of the hierarchy contains some data relevant to just that segment then it recursively defines its children. The line following the ROOT keyword contains a single left curly brace ‘{‘, the brace is lined up with the “ROOT” keyword. The line following a curly brace is indented by one tab character, these indentations are mostly to just make the file more human readable but there are some BVH file parsers that expect the tabs so if you create a BVH file be sure to make them tabs and not merely spaces. The first piece of information of a segment is the offset of that segment from its parent, or in the case of the root object the offset will generally be zero. The offset is specified by the keyword “OFFSET” followed by the X,Y and Z offset of the segment from its parent. The offset information also indicates the length and direction used for drawing the parent segment. In the BVH format there isn’t any explicit information about how a segment should be drawn. This is usually inferred from the offset of the first child defined for the parent. Typically, only the root and the upper body segments will have multiple children.

BVH格式现在变成递归定义。层次结构的每个段都包含与该段相关的一些数据,然后递归地定义其子段。ROOT关键词后的行包含一个左花括号{,括号与ROOT关键词对齐。花括号后的行缩进一个制表符,这些缩进主要是为了使文件更易于阅读,但有些BVH文件解析器期望这些制表符,因此如果创建BVH文件,请确保使用制表符而不是仅仅使用空格。段的第一条信息是该段相对于其父段的偏移,或在根对象的情况下,偏移通常为零。偏移由关键词OFFSET后跟段相对于其父段的X、Y和Z偏移指定。偏移信息还指示用于绘制父段的长度和方向。在BVH格式中,没有关于如何绘制段的显式信息。这通常从定义给父段的第一个子段的偏移中推断出来。通常,只有根段和上身段有多个子段。

The line following the offset contains the channel header information. This has the “CHANNELS” keyword followed by a number indicating the number of channels and then a list of that many labels indicating the type of each channel. The BVH file reader must keep track of the channel count and the types of channels encountered as the hierarchy information is parsed. Later, when the motion information is parsed, this ordering will be needed to parse each line of motion data. This format appears to have the flexibility to allow for segments which have any number of channels which can appear in any order. If you write your parser to handle this then so much the better, however, I have never encountered a BVH file that didn’t have 6 channels for the root object and 3 channels for every other object in the hierarchy.

偏移后的行包含通道头信息。它有CHANNELS关键词,后跟一个数字指示通道数量,然后是一个包含这么多标签的列表,指示每个通道的类型。BVH文件读取器必须在解析层次信息时跟踪通道计数和遇到的通道类型。稍后,当解析运动信息时,这种排序将用于解析每行运动数据。此格式似乎具有允许段具有任意数量的通道并以任意顺序出现的灵活性。如果编写的解析器能处理这个问题,那就更好了,然而,我从未遇到过根对象没有6个通道且层次结构中的每个其他对象没有3个通道的BVH文件。

You can see that the order of the rotation channels appears a bit odd, it goes Z rotation, followed by the X rotation and finally the Y rotation. This is not a mistake, the BVH format uses a somewhat unusual rotation order. Place the data elements into your data structure in this order.

你会看到旋转通道的顺序看起来有点奇怪,先是Z旋转,然后是X旋转,最后是Y旋转。这不是错误,BVH格式使用一种稍微不常见的旋转顺序。将数据元素按此顺序放入数据结构中。

On the line of data following the channels specification there can be one of two keywords, either you will find the “JOINT” keyword or you will see the “End Site” keyword. A joint definition is identical to the root definition except for the number of channels. This is where the recursion takes place, the rest of the parsing of the joint information proceeds just like a root. The end site information ends the recursion and indicates that the current segment is an end effector (has no children). The end site definition provides one more bit of information, it gives the length of the preceding segment just like the offset of a child defines the length and direction of its parents segment.

在通道规范后的数据行上可以有两个关键词之一,要么是JOINT关键词,要么是End Site关键词。关节定义与根定义相同,除了通道数量。这是递归发生的地方,关节信息的其余解析与根相同。终点站信息结束递归,指示当前段是终端执行器(没有子段)。终点站定义提供了一个额外的信息,它给出了前一段的长度,就像子段的偏移定义了其父段的长度和方向一样。

The end of any joint, end site or root definition is denoted by a right curly brace ‘}’. This curly brace is lined up with its corresponding right curly brace.

任何关节、终点站或根定义的结束由右花括号}表示。这个花括号与相应的右花括号对齐。

One last note about the BVH hierarchy, the world space is defined as a right handed coordinate system with the Y axis as the world up vector. Thus you will typically find that BVH skeletal segments are aligned along the Y or negative Y axis (since the characters are often have a zero pose where the character stands straight up with the arms straight down to the side).

关于BVH层次结构的最后一点,世界空间定义为右手坐标系,Y轴为世界向上向量。因此,通常会发现BVH骨架段沿Y轴或负Y轴对齐(因为角色通常有一个零姿态,角色直立站立,手臂垂直放在身体两侧)。

The motion section begins with the keyword “MOTION” on a line by itself. This line is followed by a line indicating the number of frames, this line uses the “Frames:” keyword (the colon is part of the keyword) and a number indicating the number of frames, or motion samples that are in the file. On the line after the frames definition is the “Frame Time:” definition, this indicates the sampling rate of the data. In the example BVH file the sample rate is given as 0.033333, this is 30 frames a second the usual rate of sampling in a BVH file.

运动部分以单独一行的MOTION关键词开始。这行后面是一行指示帧数的行,这行使用 Frames: 关键词(冒号是关键词的一部分)和一个数字,指示文件中的帧数或运动样本数。在帧定义后的行是 Frame Time: 定义,这指示数据的采样率。在示例BVH文件中,采样率给出为0.033333,即每秒30帧,这是BVH文件中的常用采样率。

The rest of the file contains the actual motion data. Each line is one sample of motion data. The numbers appear in the order of the channel specifications as the skeleton hierarchy was parsed.

文件的其余部分包含实际的运动数据。每行是一个运动数据样本。数字按解析骨架层次结构时的通道规范顺序出现。

Interpreting the data

To calculate the position of a segment you first create a transformation matrix from the local translation and rotation information for that segment. For any joint segment the translation information will simply be the offset as defined in the hierarchy section. The rotation data comes from the motion section. For the root object, the translation data will be the sum of the offset data and the translation data from the motion section. The BVH format doesn’t account for scales so it isn’t necessary to worry about including a scale factor calculation. A straightforward way to create the rotation matrix is to create 3 separate rotation matrices, one for each axis of rotation. Then concatenate the matrices from left to right Y, X and Z.

\[\text{v}\mathbf{R} = \text{v}\mathbf{YXZ}\]

An alternative method is to compute the rotation matrix directly. A method for doing this is described in Graphics Gems II, p 322. Adding the offset information is simple, just poke the X,Y and Z translation data into into the proper locations of the matrix. Once the local transformation is created then concatenate it with the local transformation of its parent, then its grand parent, and so on.

\[\text{v}\mathbf{M} = \text{v}\mathbf{M}\text{child}\mathbf{M}\text{parent}\mathbf{M}\text{grandparent}\dots\]

要计算一个段的位置,首先从该段的局部平移和旋转信息创建一个变换矩阵。对于任何关节段,平移信息将只是层次部分定义的偏移。旋转数据来自运动部分。对于根对象,平移数据将是偏移数据和运动部分平移数据的总和。BVH格式不考虑缩放,因此不必担心包括缩放因子的计算。创建旋转矩阵的一个简单方法是为每个旋转轴创建3个单独的旋转矩阵。然后从左到右连接这些矩阵Y、X和Z。

\[\text{v}\mathbf{R} = \text{v}\mathbf{YXZ}\]

另一种方法是直接计算旋转矩阵。《Graphics Gems II》第322页描述了这样的方法。添加偏移信息很简单,只需将X、Y和Z平移数据放入矩阵的适当位置。一旦创建了局部变换,就将其与父级的局部变换连接,然后是祖父级的局部变换,依此类推。

\[\text{v}\mathbf{M} = \text{v}\mathbf{M}\text{child}\mathbf{M}\text{parent}\mathbf{M}\text{grandparent}\dots\]

Example1.bvh:

HIERARCHY
ROOT Hips
{
	OFFSET	0.00	0.00	0.00
	CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
	JOINT Chest
	{
		OFFSET	 0.00	 5.21	 0.00
		CHANNELS 3 Zrotation Xrotation Yrotation
		JOINT Neck
		{
			OFFSET	 0.00	 18.65	 0.00
			CHANNELS 3 Zrotation Xrotation Yrotation
			JOINT Head
			{
				OFFSET	 0.00	 5.45	 0.00
				CHANNELS 3 Zrotation Xrotation Yrotation
				End Site 
				{
					OFFSET	 0.00	 3.87	 0.00
				}
			}
		}
		JOINT LeftCollar
		{
			OFFSET	 1.12	 16.23	 1.87
			CHANNELS 3 Zrotation Xrotation Yrotation
			JOINT LeftUpArm
			{
				OFFSET	 5.54	 0.00	 0.00
				CHANNELS 3 Zrotation Xrotation Yrotation
				JOINT LeftLowArm
				{
					OFFSET	 0.00	-11.96	 0.00
					CHANNELS 3 Zrotation Xrotation Yrotation
					JOINT LeftHand
					{
						OFFSET	 0.00	-9.93	 0.00
						CHANNELS 3 Zrotation Xrotation Yrotation
						End Site 
						{
							OFFSET	 0.00	-7.00	 0.00
						}
					}
				}
			}
		}
		JOINT RightCollar
		{
			OFFSET	-1.12	 16.23	 1.87
			CHANNELS 3 Zrotation Xrotation Yrotation
			JOINT RightUpArm
			{
				OFFSET	-6.07	 0.00	 0.00
				CHANNELS 3 Zrotation Xrotation Yrotation
				JOINT RightLowArm
				{
					OFFSET	 0.00	-11.82	 0.00
					CHANNELS 3 Zrotation Xrotation Yrotation
					JOINT RightHand
					{
						OFFSET	 0.00	-10.65	 0.00
						CHANNELS 3 Zrotation Xrotation Yrotation
						End Site 
						{
							OFFSET	 0.00	-7.00	 0.00
						}
					}
				}
			}
		}
	}
	JOINT LeftUpLeg
	{
		OFFSET	 3.91	 0.00	 0.00
		CHANNELS 3 Zrotation Xrotation Yrotation
		JOINT LeftLowLeg
		{
			OFFSET	 0.00	-18.34	 0.00
			CHANNELS 3 Zrotation Xrotation Yrotation
			JOINT LeftFoot
			{
				OFFSET	 0.00	-17.37	 0.00
				CHANNELS 3 Zrotation Xrotation Yrotation
				End Site 
				{
					OFFSET	 0.00	-3.46	 0.00
				}
			}
		}
	}
	JOINT RightUpLeg
	{
		OFFSET	-3.91	 0.00	 0.00
		CHANNELS 3 Zrotation Xrotation Yrotation
		JOINT RightLowLeg
		{
			OFFSET	 0.00	-17.63	 0.00
			CHANNELS 3 Zrotation Xrotation Yrotation
			JOINT RightFoot
			{
				OFFSET	 0.00	-17.14	 0.00
				CHANNELS 3 Zrotation Xrotation Yrotation
				End Site 
				{
					OFFSET	 0.00	-3.75	 0.00
				}
			}
		}
	}
}
MOTION
Frames:    2
Frame Time: 0.033333
 8.03	 35.01	 88.36	-3.41	 14.78	-164.35	 13.09	 40.30	-24.60	 7.88	 43.80	 0.00	-3.61	-41.45	 5.82	 10.08	 0.00	 10.21	 97.95	-23.53	-2.14	-101.86	-80.77	-98.91	 0.69	 0.03	 0.00	-14.04	 0.00	-10.50	-85.52	-13.72	-102.93	 61.91	-61.18	 65.18	-1.57	 0.69	 0.02	 15.00	 22.78	-5.92	 14.93	 49.99	 6.60	 0.00	-1.14	 0.00	-16.58	-10.51	-3.11	 15.38	 52.66	-21.80	 0.00	-23.95	 0.00	
 7.81	 35.10	 86.47	-3.78	 12.94	-166.97	 12.64	 42.57	-22.34	 7.67	 43.61	 0.00	-4.23	-41.41	 4.89	 19.10	 0.00	 4.16	 93.12	-9.69	-9.43	 132.67	-81.86	 136.80	 0.70	 0.37	 0.00	-8.62	 0.00	-21.82	-87.31	-27.57	-100.09	 56.17	-61.56	 58.72	-1.63	 0.95	 0.03	 13.16	 15.44	-3.56	 7.97	 59.29	 4.97	 0.00	 1.64	 0.00	-17.18	-10.02	-3.08	 13.56	 53.38	-18.07	 0.00	-25.93	 0.00