C3D File Format

(17 March 1998)

See C3D.org for more details!

C3D files consist of three sections:

Header Record

Parameter Records
Interleaved 3D and Raw Analogue
Data Records
Records are 256 (16 bit) words long.

Header Record

This is a fixed length block of 256 (16 bit) words with the following structure:

Typical Value

0x5000 | 2
Key (5000 hex) ORed with record number of parameter section (2).

Number of 3D points per field (i.e. the number of stored trajectories).

Number of analogue channels per field. One data WORD per channel is stored.

Field number of first field of video data corresponding to 3d points (1 based).

Field number of last field.

0 or 10
Maximum interpolation gap in fields.

6 -7
Scaling factor (float
< 0 pre-scaled; 3D data in REAL*4
>= 0 scale; 3D data in INTEGER*2

Record number where 3D data starts.

Number of analogue frames per video field.

10 - 11
50, 60, etc.
Video rate in Hz (float1).

12 - 148

octal 12345

Number of defined time events.

Not used.

152 - 187
Event times (float1). Maximum 18 entries.

188 - 197
Byte format event switches:
0 = ON
1 = OFF (yes really!)

198 - 233
4 character event labels.

234 - 255

Parameter Records

The first four bytes of the parameter records section contain the following header:

Typical Value

Part of identification key.

Part of identification key (=50 hex).

Number of parameter records to follow (see below).

83 decimal + processor type (see below).

The processor type may have values as follows:
  1 = PC-DOS
  2 = DEC (VAX, PDP-11)
  3 = MIPS processor (SGI, SUN) 

Note that current versions of Vicon 370 always use processor type 2 (DEC). See Appendix A for ÎCâ code to convert between PC and DEC floating point formats.

Directly following this header, the parameter data is stored contigiously and may overlap record boundaries.  The parameters themselves are organised into groups.  Each parameter and group identifier starts with a header, the format of which is common between the two.  Group identifiers are assigned a negative group number in the header and parameters belonging to the group are assigned the positive of that number.  Group identifiers and parameters may appear in any order in the file.

The record count in byte 3 corresponds to the number of fixed length 512 byte records that constitute the parameters section.  It should be noted that Vicon 370 currently always stores a value of 1 in the byte 3 parameter record count.  It is recognised that this may often be incorrect.  The 370 software does not make use of this value and instead scans the parameter section looking for  specific parameters and stops when it finds a zero (length) value as the first byte of a parameter or group.  This is necessary because although the number of parameter blocks are known, the extent to which the last block is used is not known. It is recommended that any software written to read C3D files generated by 370 should use the same algorithm for detecting the end of the parameters section. 

Group Identifier Format:

If 'n' is negative, the group has been marked as locked and should not be edited.

e.g. Group "POINT" arbitrarily assigned the number -1 and with no description would be stored in 10 bytes as follows:

Parameter Format:

where: 'T' is the parameter type:

  'd' is the number of Dimensions for array parameters (D1, D2, ..., Dd)

 'dlen' is the length of the data and is determined by:
t = |T|  i.e. the magnitude of the type
if (d == 0)
dlen = t
dlen = t * D1 * D2 * ... * Dd
If 'n' is negative, the group has been marked as locked and should not be edited.

Note that for non-array parameters, the usual method of having 'd = 0' is directly equivalent to having 'd = 1' and 'D1 = 1', the only difference is that the second approach requires one extra byte of storage.

Also note that the storage order of multi-dimensioned array parameters follows the FORTRAN convention (for historical reasons). In this format, the dimension that changes more rapidly appears first. For example, the reconstruction volume (parameter "DATA_LIMITS" in group "SEG") is made up from two 3D vectors stored in the order:

 MinX, MinY, MinZ, MaxX, MaxY, MaxZ

Using the convention, this is defined as a 3 by 2 array (rather than 2 by 3).Therefore, the correct definition for the parameter is:

 d  = 2
D1 = 3 (not 2)
D2 = 2 (not 3) 

Data Records

The 3D and analogue data are written field sequentially starting at the beginning of the first data record as specified by WORD 8 in the C3D header record. The data is packed such that field data may cross record boundaries.

3D data for field 1

Analogue data for field 1

3D data for field 2

Analogue data for field 2


3D data for field Înâ
where Înâ is the number of fields stored:

Analogue data for field Înâ
(WORD 4 - WORD 3 + 1)

3D Data:

If the scaling factor ("SCALE" parameter from group "POINT", also stored in WORDS 6 and 7 in the header record) is positive then each 3D data block will contain the following format data for each stored trajectory (the number of which is given by WORD 1 in the header record):
R = Residual, C = Camera Mask
Word 0 = X coordinate in reference coordinate system to be multiplied by the scaling factor.

Word 1 = Y coordinate in reference coordinate system to be multiplied by the scaling factor.

Word 2 = Z coordinate in reference coordinate system to be multiplied by the scaling factor.

Word 3 : This word should be interpreted as follows:

If the word is -ve (i.e. bit 15 set) then the point is invalid (not observed by at least 2 cameras). X, Y and Z should be ignored but should all be zero.

Otherwise, the low byte represents the average of the residuals for the measurement on the point and must be multiplied by the scaling factor. If this is zero then the point is interpolated or otherwise generated. The high byte has bits set corresponding to which cameras contributed to the measurement of the point. Bit 8 of the word (bit 0 of the byte) represents the first camera, bit 9 the second, etc. Again, all camera bits will be clear for interpolated or otherwise generated data points.

If the scale factor is negative then the coordinates are already scaled and stored in float (REAL*4) format as follows:

Float 0 = Scaled X coordinate in reference coordinate system.

Float 1 = Scaled Y coordinate in reference coordinate system.

Float 2 = Scaled Z coordinate in reference coordinate system.

Float 3 = Residual and camera mask. This float should be converted to an integer and treated exactly as for Word 3 in the integer format described above, except that the scaling factor should first be negated to make it positive. In other words, if the integer is negative, the point is invalid. Otherwise, the lower 8 bits of the integer, when multiplied by the absolute value of the scaling factor, yields the residual and the remaining bits represent camera masks. 

Analogue Data:

The analogue data is stored in its raw form of 12 bit offset binary data in 16 bit words. The analogue blocks for each field are split into a number of frames as defined by the sample rate ratio with respect to the video frequency (WORD 9 of the header record). Each frame holds a single sample for each captured channel:
 = WORD 9
 ÎNâ = number of channels = WORD 2 / WORD 9

To convert the data into real world units:

 real world value = (data value - zero offset) * channel scale * general scale

where: Îzero offsetâ is in the ãANALOG:OFFSETä parameters
 Îchannel scaleâ is in the ãANALOG:SCALEä parameters
 Îgeneral scaleâ is the ãANALOG:GEN_SCALEä parameter

Standard Vicon Parameters

Valid "types" are: 7-bit ASCII, 2-byte signed integer, 4-byte floating-point (real)



N labels of length L associated, by order, with analog channels in data section. Note that there may be more than N channels, in which case additional channels may be referenced by number in some applications. L is typically 4 characters.

N descriptions of length L associated with corresponding analog channel labels. L is typically 32 characters.

General scaling factor applied to all analog channels.  Often set to 0.0024414 (10/4096) to derive voltage input from 10V 12-bit ADC. Since different channels may be captured with different input ranges and not all signals are required in volts, it is recommended that this value be set to 1.0 with individual scaling applied to each channel (see SCALE parameter).

Scaling factor applied, with GEN_SCALE, to each analog channel to convert raw a.d.c. data to physical variable UNITS.

Offset to be subtracted from raw a.d.c. values before scaling.

N strings of length L indicating the analog measurement units for each channel, e.g. V, N, Nm, etc. L is typically 4 characters.

Number of analog channels used.  Total number of ADC samples stored per video field must be an integer multiple of USED.

Analog sample rate in Hz

POINT: Group


ASCII (typically upper-case)
N marker labels of length L associated, by order, with trajectories in data section. L is typically 4-30 chars. N is 1-255.
Note: There may be more or less than N trajectories; some applications allow additional trajectories to be referenced by number.

Additional labels beyond the 255 limit in LABELS. Note that LABELS3, LABELS4, etc. parameters may also be present as necessary. In all cases, N is 1-255 representing 256-510, 511-765, etc.
(Introduced in 370 version 2.5)

N descriptions of length L associated with corresponding labels. L is typically 32 characters.

Additional descriptions beyond the 255 limit in DESCRIPTIONS. Note that DESCRIPTIONS3, DESCRIPTIONS4, etc. parameters may also be present as necessary. In all cases, N is 1-255 representing 256-510, 511-765, etc.
(Introduced in 370 version 2.5)

The number of trajectories stored in the data section. Note that USED is set to the number of the highest applied trajectory label, whether from LABELS list, or by default label numbering; #n.  All trajectories up to and including USED are stored, with "invalid" coordinates if no trajectory has been assigned to the label.

String to indicate measurement units, e.g. mm, cm, m.  Note that this string should be defined when the calibration reference points are entered (CRO file). L is typically 4 characters.

Scaling factor which converts integer C3D trajectory records into coordinates in UNITS

Video data field capture rate in Hz

Record (512 bytes) number of the start of data section

Total number of fields of video data stored in the data section.  NB This misuse of the word "frame" is common among VICON users.

Command string interpreted by SID program.

{X,Y,Z,-X,-Y,-Z} indicates which axis of reference coordinate system should be displayed left-to-right across the screen.

{X,Y,Z,-X,-Y,-Z} indicates which axis of reference coordinate system should be displayed bottom-to-top up the screen.

N labels of length L.  Trajectories with labels matching those in this list are to be treated as angles rather than translations. The units are always degrees.
(Introduced in BodyBuilder version 2.5)

N labels of length L.  Trajectories with labels matching those in this list are to be treated as scalars rather than translations. The value is held in the Z component with X and Y both set to zero. The units (if any) depend on the meaning of each scalar according to the model that produced them.
(Introduced in BodyBuilder version 3.5)

N labels of length L.  Trajectories with labels matching those in this list are to be treated as powers rather than translations. Since powers are scalars rather than vectors, the value is held in the Z component with X and Y both set to zero. See POWER_UNITS parameter for units.
(Introduced in BodyBuilder version 3.5)

N labels of length L.  Trajectories with labels matching those in this list are to be treated as forces rather than translations. See FORCE_UNITS parameter for units.
(Introduced in BodyBuilder version 3.5)

N labels of length L.  Trajectories with labels matching those in this list are to be treated as moments rather than translations. See MOMENT_UNITS parameter for units.
(Introduced in BodyBuilder version 3.5)

N labels of length L. These labels are used as a base name for identifying three trajectories each that represent the force, moment and point components of a reaction. The corresponding force trajectories have a ã.Fä suffix, the moment trajectories a ã.Mä suffix and the point trajectories a ã.Pä suffix. For example, ãLKNEEä would correspond to ãLNKEE.Fä, ãLKNEE.Mä and ãLNKEE.Pä trajectories. Note that force and moment trajectories listed in REACTIONS should not appear in the FORCE and MOMENTS list.
(Introduced in BodyBuilder version 3.5)

Measurement units for power values, e.g. mW, cW, dW, W, daW, hW, kW
(Introduced in BodyBuilder version 3.5)

Measurement units for force values, e.g. N, kN, hN, daN, dN, cN, mN
 (Introduced in BodyBuilder version 3.5)

Measurement units for moment values, e.g. Nmm, Ncm, Ndm, Nm, Ndam, Nhm, Nkm.
(Introduced in BodyBuilder version 3.5)

SEG: Group


Diameter of markers, or largest marker used, in POINT:UNITS. Note that, when present, this should only be used as a guide since a single trial may use markers of different sizes.

Lower and upper limits of reconstruction volume (in POINT:UNITS) for SEG program to reconstruct a point

Maximum average acceleration (in POINT:UNITS/sec/sec) over 5 samples for SEG program to start a new segment.  Nominal value for gait analysis: 50mm/sec/sec.

Maximum deviation from constant acceleration (in POINT:UNITS) over 5 points for SEG program to start new segment.  Nominal value for gait analysis: 10mm.
(only used in 370 version 1.x)

Factor multiplied to average calibration angular error of each camera to determine "cone of reconstruction" for SEG program .  Nominal value for gait analysis: 2.0.
(only used in 370 version 1.x)

Radius of extrapolated prediction volume (in POINT:UNITS) for trajectory segment continuity in SEG program.  Nominal value for gait analysis with 25mm markers: 25mm.

Controls inclusion of rays during reconstruction.  Nominal value: 2.0
(New for 370 version 1.2)

Controls creation of new trajectories.  Nominal value: 12
(New for 370 version 2.0)

Limit for intersection of rays to form a reconstruction.  Nominal value: 7mm
(Introduced in 370 version 2.0)



Number of force plates used; L=0,1,2,3,or 4.

Transducer/output code for each plate (1..N);
1 = "AMTI" with c.o.p.+Mz
2 = "AMTI" with Mx,My,Mz
3 = Kistler with 8 channel output.

Corner locations for rectangular plates (1..N), measured in POINT:UNITS in the reference coordinate system, ordered: xy, -xy,-x-y, x-y, with respect to plate coordinate system.  Indicates size of plate and provides relative orientation of kinematic and force plate axes.

Offsets, in POINT:UNITS, measured in plate coordinate system, relating transducer positions to centre of top working surface.
Type 1: (1, ) and (2, ) are irrelevant, (3, ) is vertical distance from transducer plane to top plate (-ve value)
Type 2: components of vector from transducer output origin to centre of top plate.  All components apply.
In VICON products, the opposite vector is used - from the centre of the top plate to the plate origin.
Type 3: (1, ) is half inter-transducer distance in x-direction, (2, ) is half inter-transducer distance in y-direction, (3, ) is same distance as types 2 and 3 (all values +ve)

(6,N), or
ADC channel assignments per plate for:
type 1 type 2 type 3
(1, ) Fx Fx Fx(1+2)
(2, ) Fy Fy Fx(3+4)
(3, ) Fz Fz Fy(4+1)
(4, ) Px Mx Fy(2+3)
(5, ) Py My Fz1
(6, ) Mz' Mz Fz2
(7, ) n/a n/a Fz3
(8, ) n/a n/a Fz4

Note that if mixed plate types are present and any of them are type 3 then the dimension is (8,) for all plates. If only type 1 and/or type 2 plates are used, the dimension may be (6,).

Range of analog sample numbers used to establish force plate baseline.

Introduced in Vicon 370 version 2.5 and BodyBuilder version 3.0.


The value is 1 if the trial subjects were captured in a static pose for the purposes of calibration, otherwise 0.

The value is 1 if label prefixes are being used in this trial, otherwise 0. Used when labelling has not yet been performed. Note that the presence of any non-blank LABEL_PREFIXES entries overrides this parameter.

The number of named subjects in the trial. May be 0 for trials where specific subjects were not used or for subject calibrations.

N subject names of length L.

N prefixes of length L. These identify prefixes attached to the trajectory labels for each subject ordered as in NAMES. Each prefix is typically either blank or the same as the subject name but with a colon Î:â suffix.

N marker set names of length L. These identify the MKR filenames for each subject ordered as in NAMES. Each subject may use a different marker set. Note that the path is excluded from the filename.

N display set names of length L. These identify the active display set within the marker set for each subject ordered as in NAMES. If blank, the first display set should be used.

N marker set names of length L. These identify the model (usually .MOD) filenames for each subject ordered as in NAMES. Each subject may use a different model. Note that the path is excluded from the filename.

N marker set names of length L. These identify the model parameters (usually .MP) filenames for each subject ordered as in NAMES. Each subject will typically have their own model parameters. Note that the path is excluded from the filename. 

Appendix A - Converting between PC and DEC float formats

All Vicon software currently uses the DEC format for storage of floating point numbers in C3D files. The following C code may be used to convert to PC format and back again:

float ConvertDecToFloat(char bytes[4])
    char p[4];
    p[0] = bytes[2];
    p[1] = bytes[3];
    p[2] = bytes[0];
    p[3] = bytes[1];
    if (p[0] || p[1] || p[2] || p[3])
        --p[3];          // adjust exponent
    return *(float*)p;

void ConvertFloatToDec(float f, char* bytes)
    char* p = (char*)&f;
    bytes[0] = p[2];
    bytes[1] = p[3];
    bytes[2] = p[0];
    bytes[3] = p[1];
    if (bytes[0] || bytes[1] || bytes[2] || bytes[3])
        ++bytes[1];      // adjust exponent
 The floating point format depends on the setting for processor type (see Parameter Records section). Vicon 370 currently uses the DEC format for compatibility with earlier Vicon VX systems. Vicon 370 versions prior to B-1.2 incorrectly writes ANALOG:RATE as an integer. 

Appendix A  (C) Copyright.  Andrew Dainis


The C3D data file format was developed by Andrew Dainis in 1987 as
a convenient and efficient means for storing 3D coordinate and analog
data, with all associated parameters, for a single measurement trial.

One design goal of the C3D file format was to provide the user a means
to easily examine, and if necessary modify, any parameter contained
in the file. This goal was achieved by providing the user with a program
(PRM) which interactively allows access to the parameters stored internaly
in binary format.

                            TABLE OF CONTENTS

1.      Parameter Manipulation Program PRM
2.      C3D Data File Format
3.      Parameter Access From Programs




     The PRM program provides the user a means of accessing the parameters in
C3D and other ADTECH parameter files. It operates interactively through a few
simple commands and provides output to terminal screen, printer, or file. The
program allows the user to create, examine, change, and delete parameters in any
file that contains data in the ADTECH parameter format, and acts as a friendly
interface between the user and the parameters.


     This section describes the format of the parameters as displayed by the
PRM program. Internally to a file the parameters are stored in binary format and
may be directly accessed using the techniques described in sections 2. and 3.

     Each parameter is identified by a name, and has a data type. A parameter
also has dimensions which describe how many pieces or elements of data it can
hold, and optionally, a description. Additionally each parameter belongs to a
parameter group having a group name and a group description. In listings and
commands the group name and parameter name are separated by a colon (:). By a
suitable choice of group and parameter names, and through the descriptions, it
is possible to make the parameter functions largely self-explanatory. The
ability to group parameters enables parameters pertaining to different functions
to be included in the same file without risk of confusion.

     A parameter or group name may consist of any number of characters made up
from the letters A through Z, the numerals 0 through 9, and the underscore
character  _ . The name should not start with a numeral or the underscore
character. When a name is interpreted only the first six characters are used.
Hence all group names and all names within a group should show at least one
difference in the first six characters. The same names may be used for two
parameters if they occur in different groups.

     A parameter's type determines the type of data that may be stored in it.
Four parameter types are used; integer, real, character, and byte. These data
types correspond to the conventional meaning of the terms in computer
programming. An integer is a 16-bit signed number between -32768 and +32767, a
real number is one containing a decimal point or written in scientific
exponential representation, a character is a literal symbol such as a letter
entered from the keyboard, and a byte data location can contain a 8-bit signed
integer in the range -128 to +127.

     The dimensions of a parameter define how many elements of the appropriate
type may be stored in that parameter. The use of the term dimensions also
follows normal programming conventions. If a parameter has no dimensions, then
it may only hold one value of its data type. If it has one dimension it is
presented in the form such as PARM(4) where the  4  indicates that the parameter
called PARM is capable of holding four values. Examples of two- and three-
dimensional parameter arrays are PARMA(4,5) and PARMB(3,5,7). The first example
has 4 x 5 = 20 elements, and the second parameter holds 3 x 5 x 7 = 105 entries.
The content of any parameter element may be selectively examined and modified
by use of the PRM program.

     The description part of a group or parameter definition simply provides
information as to the function of the particular group or parameter, and is
included for informational purposes only.


1.3.1  Starting the PRM Program

     The Parameter Manipulation Program is started by entering

               PRM  <file name>

from the keyboard in response to the operating system prompt. The screen will
clear, the program title will be displayed, and the requested file will be
opened. If no file name is provided, the program will request the input of a
file name.

1.3.2  Accessing the Parameters

     If the named file is found, it is opened and the program first tests to
determine that the file does contain parameter data. If the format is valid, the
data are read into memory and become available for manipulation. If the file
does not contain parameter data a message to that effect is output to the
terminal screen and the user is prompted for another file name. If the named
file cannot be opened for any reason, a new file is opened in preparation for
creating a new set of parameters and a  new file  message is displayed on the
terminal screen. The user then may proceed to create parameter groups and
parameters as described in the remainder of this chapter. Once the program is
ready to accept parameter manipulation commands, the prompt symbol ? will be
displayed. If a mistake was made in entering the file name and the user does not
wish to create a new file, the abort command AB(ort) should be entered in
response to the ? prompt. In this circumstance the program will ask for another
file name.

     When an existing file is opened, the program first lists the existing
parameter groups before displaying the ? prompt.

1.3.3  Terminating the Program

     Either of the commands ABort or EXit will terminate the PRM program. The
ABort command will cause the program to exit without making any changes to the
input parameter file, whereas the EXit command will cause the input file to be
updated with the changes entered during this session.


     The PRM program responds to eight commands: CREATE, DELETE, LIST,
PRINT, WRITE, CHANGE, ABORT, and EXIT. All commands except CREATE may
be abbreviated to their first letter. The shortest abbreviation allowed for
CREATE is CR. The CREATE and DELETE commands will be described first.
However, the user will very rarely need to use these two commands since the
modification of existing parameter files, or of copies of existing files,
provides a more efficient technique for obtaining new files. The creation of a
new parameter file must be done very carefully because errors in parameter names
or dimensions will cause programs to reject the parameter data. Occasionally the
CREATE and DELETE facilities may be useful for changing the dimensions or
description of a parameter, or replacing an incorrectly created parameter.

     In the following command descriptions, di refers to the ith dimension of
a parameter (for instance, the 7 in CAM_CHAN (7) ).

1.4.1  Create (CR)  Group

     To create a new parameter group, the command is

          CReate group_name:/description

     The group called group_name is created, and with it is associated a
description. If a group is being created, the ':' must be specified. Also, the
slash character '/' must be used to separate the description from the rest of
the command.  Parameter

     To create a parameter within an existing group, use the command

CReate {group_name:}parameter {(d1, d2,...)},type/description

     If a group name is not placed in front of a parameter name, the parameter
will be created in the default group. The default group is the one whose name
was last specified in any command. If a group name is included before the
parameter name then the parameter is created in the specified group.

     A parameter may have up to seven dimensions, but normally none, one, or
two are used. If no dimension is defined then that parameter can only hold one
element. The parameter type must be specified as a single character from the
list of four; I, R, C, and B where I denotes Integer, R denotes Real, C
denotes Character, and B denotes Byte. The slash / must precede the description
part of the definition.

     When a parameter is created, it is filled with default values. For
numerical parameters (those of type real, integer or byte) the default value is
zero. For the character type of parameter the default entry in all locations is
the space ' ' character. Once a parameter or group is created, its name,
dimensions, or description may only be changed by deletion and re-creation.

     There are no restrictions on the length of group or parameter names, which
must be made up from the letters A - Z, the numerals 0 - 9, and the underscore
character  _ . A name should not start with a numeral or  _ . Only the first six
characters of a name are referenced when a name is interpreted. Therefore no two
names of parameters in the same group should be identical in all first six
characters. Parameters may only have the same names if they belong to different

1.4.2  Delete (D)

     Groups and parameters may be deleted. A group may be deleted only after
all parameters within it have been deleted. A parameter may be deleted if it is
not locked by the program that created it. A locked parameter (identified by and
asterisk (*) in front of its description) may also not be modified by the CHANGE
command. The delete command has the format

          Delete group_name:


          Delete group_name:parameter_name

     Note that a group name must always be used when a parameter is being
deleted. Also, any parameter or group name may be abbreviated, even down to one
letter. However, if the abbreviation can refer to more than one name, action may
be taken on the wrong parameter.

1.4.3  List (L), Write (W), or Print (P)

     The only difference between these commands is the output device to which
the information is sent. The List command results in output to the terminal from
which the command was entered, the Write command writes the output to a file
named LISTPAR.DAT, and the Print command additionally sends the LISTPAR.DAT file
to the system printer. Note that data are written to the output file until
either the EXit or ABort command is given, at which point the file is closed
(and sent to the printer if the Print command was used).  Groups

     A listing of all groups may be obtained by the command

          L :

where the : symbolically denotes groups. The space between the command and the
colon is required. The parameter names, dimensions and descriptions contained
in any group may be listed by the command

          L group_name:

and an L without any group name will list all of the parameter names in the
current default group. It should be noted that any time a group name is used,
that group becomes the current default group. Also, when a group is listed the
content of any parameter that has a single element is also automatically listed.  Parameters

     This output commands has the general syntax:

          List {group _name:}parameter_name {(d1 {, d2,..})}

If the group name is omitted, then the current default group name is used. A
parameter name must be specified, and the dimensions are optional. Abbreviations
for group and parameter file names may be used. If no dimensions are specified,
the values of all elements of the parameter are listed. By use of entries within
the dimension parentheses, any subset of elements of the parameter may be
listed. As an example, consider a parameter that was created with the command

          CR COORD(3,20),R/Reference point coordinates

The organization of this parameter may be thought of as consisting of 60 storage
locations arranged in an array that has three rows and 20 columns. Each location
can store a real (floating point) number. The command

          L COORD

will cause the PRM program to list all values in COORD starting with the value
stored in location (1,1), followed by (2,1), (3,1), (1,2), (2,2), (3,2),
(1,3),.... , (3,19), (1,20), (2,20), (3,20), i.e., the first dimension is varied
most rapidly, followed by the second dimension, and so on. The command

          L CO(2,15)

will list the value stored in the second row and the 15th column. If a dimension
is omitted, all the elements for that dimension will be listed, i.e., the

          L COORD(,15)

will list the elements (1,15), (2,15), and (3,15), whereas the command

          L COORD(3,)

will display the values in (3,1), (3,2),...., (3,20). The command L COORD(,)
is equivalent to L COORD . The above example illustrates how program PRM
provides a simple and flexible facility for selecting parameter data for display
or modification.

1.4.4  Change (C)  Groups

     The Change command may be applied to an entire group as in

          Change group_name:

to have the program prompt for the modification of all single element parameters
contained in the group.  Parameters

     In its most general form the change command has the format

          Change {group_name:}parameter_name {(d1, {d2, ...})}

     If a group name is not given, the current default group name is assumed.
The rules for accessing the elements of a dimensioned parameter are the same as
those for the LIST command, i.e., all, some, or one of the elements of a
parameter may be selected for modification. After a change command is entered,
each element is listed on the terminal with its current value. The user is then
prompted for the entry of a new value. Pressing just the <ENTER> key leaves
the value in that particular element unchanged. If the user wishes to exit from
the change mode without completing the list specified in the change command,
then the PRM prompt symbol ? should be entered.

     Some parameters are locked by their creating programs in order to protect
the data from modifications which may cause succeeding programs to function
incorrectly. A locked parameter can be recognized by an asterisk preceding its
description, and any attempt to change or delete it results in a message stating
that it is locked.

     The first dimension of a parameter which has a character type determines
how long the lines are for entering characters. For example, a character
parameter with dimensions (30,5) holds five lines, with each line having room
for 30 characters. A command to change or list the third line would specify the
dimensions (,3) . Actually for character parameters, the first dimension may be
omitted altogether, and the dimension may be specified as just (3).

NOTE: To clear a character line of any text, enter a single exclamation mark
in response to the prompt for input for that line.




    The coordinate (and analog) data in .C3D files are written in 16-bit
integer (INTEGER*2) format, or optionally floating point (REAL*4) format,
consisting of records that are 512 bytes long. The files have three sections.
The first section consists of just one header record and contains a few
parameters as described in Section 2.2. The second section starts at record
number 2 and contains parameters in ADTECH format. This section is variable in
length but is typically about 10 records long. The rest of the file contains
the 3D point coordinate data, and analog data if analog data were available
when the .C3D file was created. Standard format of coordinate and analog data
is in the integer format. However, the facility for the data to be written
in REAL*4 format is also available for the storing of filtered data where the
integer form may not provide sufficient precision.


    Although all parameters of interest are contained in the parameter
section, a few essential parameters necessary for accessing the data in the
file are repeated in the header record in simple form. The parameters in this
record are useful if one does not wish to use the parameter subroutines
required to access the quantities written in parameter format. The ADTECH
parameter format allows for very convenient interactive user access, but is
more complex from the programming aspect. The first few words of the header
record are utilized to store the abbreviated parameter data, and the rest of
the header record contains zeros unless time event data have been written to
the data file. The parameter values stored in the header record are as listed
in Table 2.1. The 16-bit words hold integer values unless otherwise noted.

  WORD                 CONTENTS

    1            Byte 1:  number of 1st parameter record
                 Byte 2:  must contain  80(decimal)

    2            Number of 3D points

    3            Number of analog channels for which data is stored

    4            Number of first video frame in .C3D file

    5            Number of last video frame in .C3D file

    6            Maximum interpolation gap allowed (in frames)

   7,8           (REAL*4) Scale factor for converting integer 3D data to
                 reference system units. If negative, 3D data is already in
                 REAL*4 format.

    9            Starting record number for 3D point and analog data

   10            Number of analog frames / video frame

 11,12           (REAL*4) Video frame rate (Hz)

 13-149          Currently not used

  150            12345(decimal) keyword to identify presence of event data

  151            Number of defined time events -- maximum of 18

  152            Not used

153-188          (REAL*4) Event times (in seconds) -- maximum of 18

189-198          (BYTE*1) Event display switches (0=ON, 1=OFF)

199-234          Event labels. 4 characters for each event.


          Table 2.1 -- Contents of first record of .C3D file.


    The parameter section is written in ADTECH parameter format which
allows the user to interactively access the parameters with the program PRM.
Programmers may access the parameters through the  FORTRAN library PRMLIB
or write programs to access the parameter data directly. Chapter 3 provides
instructions for calling the subroutines in the PRMLIB library, and the rest
of this section describes in detail the ADTECH parameter format for those
that want to access the parameters the hard way.

    The first two bytes of the first parameter record are either not used,
or form the  first two bytes of the file. If they are the first two bytes of
the file (not the case for C3D files), then byte 1 contains the number of the
first parameter record, and byte 2 contains 80 (decimal).

    Byte 3 of the first parameter record contains the number of parameter
records, and byte 4 contains 85(decimal) + processor_type. Processor_type may
have the value 1, 2, or 3, and is defined in Section 3.1. The actual parameter
data start at byte 5 of the first parameter record.

    Within the parameter records, the data belonging to groups and
parameters are stored in no particular order, and are located by searching
through the total data block. The storage unit is the byte.

Group data are stored in the following format:
 Byte 1             Number (n) of characters in group name

 Byte 2             Group ID number (negative)

 Bytes  3 --> 3 + n - 1       Group name

 Bytes  3 + n , 3 + n + 1    (2-byte integer) offset in bytes pointing to
                             start of next group/parameter

 Byte  3 + n + 2             Number (m) of characters in group description

 Bytes  3 + n + 3 -->  3 + n + 3 + m - 1     Group description

 Parameter data are stored in the following format:
 Byte  1            Number (n) of characters in parameter name

 Byte  2            Group number (positive) to which parameter belongs

 Bytes  3 -->  3 + n + 1     Parameter name

 Bytes  3 + n , 3 + n + 1    (2-byte integer) offset in bytes pointing to
                             start of next group/parameter

 Byte  3 + n + 2             Length in bytes of each data element
                               -1 for Character
                                1 for Byte
                                2 for Integer*2
                                4 for Real*4

 Byte  3 + n + 3         Number (d) of dimensions of the parameter (max. = 7)
                         d = 0 if the parameter is undimensioned.

 Bytes  3 + n + 4  -->  3 + n + 4 + d - 1    Parameter dimensions

 Byte  3 + n + 4 + d  -->  3 + n + 4 + d + t - 1
                           The parameter data. t = product of all dimensions
                           and element length

 Byte  3 + n + 4 + d + t   Number (m) of characters in description

 Bytes  3 + n + 4 + d + t + 1  -->  3 + n + 4 + d + t + 1 + m - 1   Parameter

    The PRM program responds to the command SH, which will dump all
parameter records in byte format, and their ASCII equivalent, to the screen.


    The 3D coordinate and analog data are written frame-sequentially
starting at the beginning of the first data record. The data are packed into
records such that frames may cross record boundaries. The 3D coordinate data
are normally stored in 16-bit integer format and must be multiplied by the
POINT:SCALE factor to generate values expressed in the external (reference
coordinate system) measurement units. If the data is stored in floating point
format (REAL*4), then the scale factor has already been applied and it is set
to be negative.

    Each 3D point is described by four words. If the data is stored in
integer form, these 16-bit words contain the following:

    WORD                               CONTENTS

      1                   X-coordinate of point / scale factor

      2                   Y-coordinate of point / scale factor

      3                   Z-coordinate of point / scale factor

      4                   Byte 1: cameras that measured marker (1 bit for each
                          Byte 2: average residual for point measurement
                              / scale factor
                 Table 2.2 -- 3D point data contents.

        The video data for frame one are stored first, followed by one or more
analog "frames" if analog data are present. If the analog data rate was the
same as the video frame rate then only one analog frame will follow each video
frame. If analog rate was twice the video rate, then two analog frames will
follow the video frame, etc. Both the video and analog data will always be in
the same format, .i.e., INTEGER*2 or REAL*4.


     In Byte 1 of Word 4, bits are set corresponding to which cameras
      contributed to the point's measurement. Bit 0 refers to the first
      camera, bit 1 the second, etc.

     If a point was invalid in a frame (not observed by at least two
      cameras), its 4th word will be set to -1, and the X, Y, and Z
      coordinates will be set to zero. For points that were interpolated,
      the residual is set identically to zero.

     In an integer file the coordinates and residuals are recorded in
      internal units, and must be multiplied by the scaling factor in
      POINT:SCALE to obtain reference coordinate system units.

     The analog data are stored in the same order as in the raw data file,
      i.e., if the analog frame rate was higher than the video frame rate,
      the order through the channels is repeated as many times as is
      appropriate. The first word after the end of the analog data is the X-
      coordinate of the first point in the next frame.

     If the data is stored in floating point format, the X, Y, and Z
      coordinates have already been multiplied by the scale factor. The 4th
      word is the normal 4th word integer value stored as a floating point
      number. To extract its data, it should be converted to integer, divided
      into high and low bytes, and the low byte must be multiplied by the
      scale factor to obtain the correct residual value.




        The location of parameter records in any file is specified as follows:

1.  Byte 1 of the first record of the file must contain the record number
     of the first parameter record in the file.

2.  Byte 2 of the first record of the file must contain 80(decimal).

3.  Byte 3 of the first parameter record must contain the number of
     parameter records to  follow.

4.  Byte 4 of the first parameter record must contain   83(decimal) + data_type.

Data_type is an integer having a value 1, 2, or 3 and designates the computer
system type  the file was created on, or is formatted for. Recognized values

              1  =  PC-DOS
              2  =  DEC  (VAX , PDP-11)
              3  =  MIPS processor (SGI , SUN)

The library routine GPREC checks for the above four conditions when parameter
data is read from a file, and the parameter output subroutine OUTPT ensures
that the four bytes described above are written to the output file.


    The data stored in ADTECH parameter format may be accessed from user
programs by the use of calls to subroutines and functions contained in the
parameter library PRMLIB. The library is provided in Microsoft 16-bit FORTRAN

     The routines operate on the entire parameter data set which must be
first read into memory by the function GPREC. Once in memory, parameters may
be created, deleted, read, or modified. At conclusion, the entire parameter
set may be output to a file by the subroutine OUTPT.

    In order to use the library routines, the calling program or subprogram
must contain the following statements:





    The array LM must be large enough to store the entire parameter set,
i.e. LMSIZE must be at least 512 * number of parameter records. An LMSIZE of
5120 bytes is adequate for most .C3D files.

     Before the library routines can be used, the file containing the
parameter data must be opened. In this chapter the variable LUN will be used
for the data file logical unit number, and LCT will be used for the terminal
output logical unit number. Normally they would be assigned in the calling
program as for example in


In the following both LUN and LCT can be constants or variables.

    The command to open the file will be similar to the following;

    OPEN (UNIT=LUN,FILE='file_name',STATUS='OLD',
   *  ACCESS='DIRECT',RECL=512,ERR=800)

If the file is opened successfully, the routines described in the next
section can then be used to access the parameters.


3.3.1  Read in all parameters


    This function reads in all parameter data into the array LM and
     converts it to the current processor type (see Section 3.1).  GPREC
     must be declared as an INTEGER*2 function and it returns:

    GPREC   =  0        if the read is successful
              -1        if there was a file read error
              -2        if parameter records were not found in the file
              -3        if LTOP was exceeded (LM was too small)

    ISTREC is output, and returns the record number in the file where the
     parameters started. INTYP is also output and contains either 1, 2, or
     3 specifying which processor type the file was formatted for.  After
     the data is read in the input file may be closed.

3.3.2  Write parameters to file


    Writes the full parameter set to logical unit LUN. The file must have
     previously been opened as a direct access file. ISTREC is input and
     specifies the record number where the first parameter record is to be
     written. This value will be stored in the first byte of the data file
     as a pointer to the start of the parameter data. IRLAST returns the
     record number of the last parameter record in the file, i.e., the
     number of parameter records written is given by IRLAST - ISTREC + 1.
     OUTYP is input to the routine and specifies in what processor format
     type the parameters are to be written. This parameter may have the
     values 1, 2, or 3 as described in Section 3.1.

3.3.3  Create a parameter group


    Creates a parameter group whose name is in GNAME. GNAME may be a
     character string, or an INTEGER*1 or LOGICAL*1 array terminated with a
     null byte. Similarly, a group description is specified as a character
     string or byte array in DESCR. The variable IFG is output and contains
     the (negative) internal group ID number assigned to this group. An
     example of a call might be

    CALL DEFG ('POINT','Point parameters',IFG,LM,LTOP)

     Note that in Microsoft FORTRAN, the 'C' character must be appended to
      literal strings, as in 'POINT'C .

 3.3.4  Create a parameter


     A parameter with the name contained in PNAME is created in an existing
      group having the name GNAME.  TYP is one of the single character
      literals 'I','R','B', or 'C' specifying that the  parameter is of type
      Integer (INTEGER*2), Real (REAL*4), Byte (INTEGER*1 or LOGICAL*1), or
      Character, and DESCR contains a description string. PNAME may specify
      dimensions which are interpreted as described in Chapter 8 of the
      User's Manual. Example:

     CALL DEFP ('NN(3,4)','I','GRP1',
    *                 'Descriptive text',LM,LTOP)

     This call would create a parameter named NN of type integer, and having
      dimensions (3,4). If it is desired to use a variable for one or more of
      the dimensions, then the subroutine ENCN described in Section 3.3.8
      must first be used to encode the dimensions into the parameter name

 3.3.5  Delete a Group


     Deletes the group entry for GNAME. All the parameters in the group must
      have been first deleted. e.g.,

          CALL DELG ('GRP1',LM,LTOP)

 3.3.6  Delete a Parameter


     Deletes the parameter named PNAME in the group GNAME and reclaims
      space, e.g.,

          CALL DELP ('GRP1','NN',LM,LTOP)

 3.3.7  Read or write parameters


 This subroutine performs the following functions depending on the input value
 of IFN.

 IFN                   FUNCTION
  0  The contents of the parameter specified in PNAME are listed to unit

  1  Causes a prompt for the interactive modification of the parameter(s)
      PNAME via logical unit LCT.

  2  The parameter values specified by PNAME are extracted from the
      parameter set and stored in the variable ADDR. MAXD specifies in bytes
      the maximum amount of data that is allowed to be read into ADDR (i.e.,
      the size of ADDR). If the data specified in PNAME is larger than MAXD,
      then no action is taken and MAXD is returned as -1. Otherwise MAXD is
      returned as the number of bytes actually read in. If the parameter
      cannot be found MAXD is returned as zero. In an error condition a
      message is written to unit LCT.

  3  The data starting at variable ADDR is stored in the parameter PNAME.
      MAXD should be set to the number of bytes expected to be stored. MAXD
      is returned as 0 if there was room for all data, and returned as the
      number of bytes actually stored if there was not enough room. If the
      parameter was not found MAXD is returned as -1.

 -3  Data is stored as for IFN = 3, but the parameter is locked to prevent
      it from being modified interactively.


          CALL PRPAR (5,'NN(,2)','GRP1',0,ADDR,LM,LTOP,MAXD)

     would list the values of NN(1,2), NN(2,2), and NN(3,2) on the logical
      unit 5.

          CALL PRPAR (5,'NN','GRP1',2,ADDR,LM,LTOP,MAXD)

     copies the contents of parameter NN to  memory starting at the address
      occupied by the variable ADDR. Note that no checks for correct variable
      lengths are performed other than through the MAXD variable. Also MAXD
      must be a variable and not a constant.

          CALL PRPAR (5,'NN(2,4)','GRP1',3,JJ,LM,LTOP,MAXD)

     causes the value in JJ to be stored in the parameter location NN(2,4).

 3.3.8  Encode dimensions into a parameter name


     If it is wished to use  variables rather than constants to specify
      dimensions in a parameter name, use this subroutine to form the
      parameter name before using it in  DEFP or PRPAR.

     ENCN encodes the first NDIM values in the variable array IDIM and adds
      the string to NAMIN to produce NAMOUT, which can then be used as PNAME
      in the subroutine calls, e.g., the call


     where NDIM = 3, IDIM(1) = 3, IDIM(2) = 6, IDIM(3) = 4, will result in
      the output of a string array NAMOUT containing 'INNAME (3,6,4)'

     A zero value in IDIM will omit the value for that dimension. For
      example, if IDIM(2)  was set to zero in the example, the NAMOUT would
      contain the string 'INNAME (3,,4)'

 3.3.9  Create new parameter block


     Call this subroutine to initialize a new parameter block, i.e., if you
      wish to create a new parameter file without using GPREC to read in an
      existing parameter block.

 3.3.10  Convert data between different processor systems

     These subroutines are not directly related to accessing parameter data,
 but are included because they may be useful in converting data between the
 different computer system types.


     RR is an array containing N floating point (REAL*4) numbers to be
      converted from INTYP to OUTYP. INTYP and OUTYP may have values chosen
      from 1, 2, or 3 as described in Section 3.1.

 IR is an array containing N integer (INTEGER*2) numbers to be converted from
 INTYP to OUTYP. INTYP and OUTYP may have values chosen from 1, 2, or 3 as
 described in Section 3.1. The integer formats for type 1 and 2 processors are

 3.4  NOTES

   1.   All of the subroutines in  PRMLIB have been compiled with the /4I2
         switch for Microsoft FORTRAN. This switch causes all integers to be
         interpreted as INTEGER*2 rather than INTEGER*4 which is the default
         for the compiler. All integer variable arguments passed to the
         subroutines must be declared as INTEGER*2. An alternative technique
         is to compile the calling program also with the switch.

   2.   PNAME may contain partial dimensions in order to access a subset of the
         parameters stored in PNAME, and name and group abbreviations may be
         used. The program PRM is simply an implementation of the subroutines
         described in the last section.

   3.   If an error condition results, then a message is output to unit LCT. If
         LCT = 0, then no error messages are generated.

Appendix C -  Corrrespondence between Alan Morris & Oxford Metrics

Date: Tue, 6 Oct 1998 08:27:49 -0400
From: Jonathan Attias <jonathan.attias@metrics.co.uk>
To: 'Alan R Morris' <morrisa@ecf.utoronto.ca>
Cc: Geoff haw <geoff.shaw@metrics.co.uk>,
    Martin Lyster <martin.lyster@metrics.co.uk>,
    Warren Lester <warren.lester@metrics.co.uk>
Subject: RE: C3D format query!

Hello Alan

Prior to version 2.5, unlabelled trajectories did not get saved in the
C3D file unless you explicitly used a command to assign (arbitrary)
numerical labels to them. This means that those trajectories were
permanently lost.

In version 2.5, this is more serious because of automatic processing. If
the automatic labeller fails, for any reason, to label all trajectories
then using the old scheme would result in unrecoverably lost data and a
useless trial. You would have to reconstruct and label it again and tidy
it up manually before saving. So now, all trajectories are saved unless
you explicitly use a command to delete unlabelled (or other unwanted)
trajectories. This allows you to go back and tidy up any trials that
were not processed correctly in their entirety. There are also other
reasons for changing the storage algorithm, related to multiple subject
support, including multiple MKR files in a single trial.

Another difference is that, prior to version 2.5, trajectories happened
to always be written in the order specified in the MKR file. However,
the ordering was never guaranteed and you could easily find yourself
with an equivalent C3D file where the trajectories appear in a different
order based on a different, but equivalent, MKR file. This is because
different people like to manually label in different ways. For example,
many people like to start at the top and work down whereas I like to
label one limb at a time so I might use a different MKR file to reflect

The point is that the ordering of trajectories in a C3D file is
completely arbitrary and should never be relied upon; the corresponding
trajectory labels should always be taken from the parameters section of
the C3D file.

This has tripped up a few people like yourselves who have written custom
software that made assumptions about the storage mechanism. To solve
this, we introduced a new user preference feature in version 2.6 to
force the trajectories to be saved in the order specified by the MKR
file. It uses rules such as outputting trajectories assigned to subjects
first (one subject at a time) followed by trajectories unassigned to
particular subjects. One disadvantage of using this option is that your
files can become quite large, filled with blank trajectories (as
before). You will have to contact Geoff if you need to get hold of this

In addition, you should modify your code to remove the assumption that
there will only be 10 trajectories in the file. You already read in the
actual number of trajectories so this shouldn't be hard.

Hope this has provided you with the answers you need.


Jonathan Attias
Software Development Manager
Oxford Metrics Limited

Date: Wed, 7 Oct 1998 04:10:07 -0400
From: Jonathan Attias <jonathan.attias@metrics.co.uk>
To: 'Alan R Morris' <morrisa@ecf.utoronto.ca>
Subject: RE: Update on previous message!


Regarding the parameters, it is easy to get confused. The record count
you are referring to (byte 3 of the parameter section in the file)
actually indicates the number of 512 byte 'file' records allocated to
the entire parameters section. Because of a mis-interpretation of this
value, Vicon software prior to version 2.6 sometimes writes an incorrect
value in here so it should not be relied upon anyway.

There is no count stored for the number of parameters in each group and,
according to the original C3D specification, all group and parameter
records can appear in any order. This means that parameters could even
appear before the group that they are in. In practice, Vicon always
writes the data out with a group followed by all of its parameters
before going on to the next group.

The way to relate parameters to groups is by use of the group ID number.
Our documentation is rather unclear on this so you would be better
referring to the AMASS documentation from Andy Dainis (part 11, section
2.3 of May 5, 1994 manual set). Group records have unique ID numbers
within the file which are stored as a negative value in byte 2. All
parameters belonging to the group store the same ID as a positive value,
also in byte 2. Having found the group you are interested in, you need
to search through all the other records to find the corresponding
parameters with a matching ID. The end of the parameter data section is
found when the number of characters for the group/parameter name (byte
1) is zero. One thing to note is that you can't rely on the group ID
being the same for the same group in different files, or even successive
saves of the same file, though in practice, Vicon tends to use the same

Best of luck with this!

Jonathan Attias
Software Development Manager
Oxford Metrics Limited

              Re: C3D files
              Mon, 2 Nov 1998 08:37:01 -0500
              Andrew Dainis <adainis@cfw.com>

I agree with the comments summarized by Gerome Garthwaite, that the C3D parameter format is rather tricky. This design
was necessitated by the requirement of flexibility and ease of access to the user. With respect to the recent postings I
would like to point out a number of  things that might prove to be useful.

1) All parameters may be accessed and modifed interactively by use of the PRM program that I provide on the anonymous
NIH ftp site ftp://bmli1.cc.nih.gov/pub/c3d_files/. The program will acces PC-Intel, DEC, and SGI written data files, and
also indicate which data type they are.

2) AMASS software transparently handles C3D files from the three CPU types (PC-Intel, DEC, SGI etc.), but Oxford
Metrics software does not (it still recognizes only DEC). This has been the source of considerable confusion. The
differences are due to the  the way floating point (real*4) numbers are stored by each type of hardware.

3) A complete library of object code is available at the ftp site, with full documentation, for manipulating/creating
parameters. However, it is 16-bit MS Fortran.

4) PRM will allow one to build a parameter section from scratch, but I do not recommend it. It is too easy to make a
mistake. It is better to modify an existing parameter section using PRM or the library.

5) To create a C3D file one does not necessarily have to know how to access the parameter section. You can take the
parameter block from any existing file and just insert it into the new file. You can use PRM to make any modifications to
the parameter section before or after. The header record and data records are quite easy to write.

As the originator, and by default "keeper", of the C3D file format, I will be happy to answer questions of  interpetation,
etc., or receive comments regarding the file format.

Andy Dainis