| DATE | 2016-11-21T22:03:59+00:00 |
| DESCRIPTION | Format Specification |
| IDENTIFIER | bab4dfb1-4cca-4aa4-b05a-e77d96135b85 |
| LANGUAGE | en |
| SOURCE | https://www.io7m.com/software/smfj/ |
| TITLE | SMF Format Specification 0.16.0-SNAPSHOT |
module Attribute where
data ComponentType =
IntegerSigned
| IntegerUnsigned
| FloatingPoint
data AttributeType = AttributeType {
attribute_component_type :: ComponentType,
attribute_component_count :: Word32,
attribute_component_size :: Word32
}
data Attribute = Attribute {
attribute_name :: String,
attribute_type :: AttributeType
}
attribute_name =
? [a-z_.0-9]{1,64} ? ;
| Component Type | Component Count | Component size (bits) |
|---|---|---|
| Signed integer | 1 | 8 |
| Signed integer | 2 | 8 |
| Signed integer | 3 | 8 |
| Signed integer | 4 | 8 |
| Signed integer | 1 | 16 |
| Signed integer | 2 | 16 |
| Signed integer | 3 | 16 |
| Signed integer | 4 | 16 |
| Signed integer | 1 | 32 |
| Signed integer | 2 | 32 |
| Signed integer | 3 | 32 |
| Signed integer | 4 | 32 |
| Signed integer | 1 | 64 |
| Signed integer | 2 | 64 |
| Signed integer | 3 | 64 |
| Signed integer | 4 | 64 |
| Unsigned integer | 1 | 8 |
| Unsigned integer | 2 | 8 |
| Unsigned integer | 3 | 8 |
| Unsigned integer | 4 | 8 |
| Unsigned integer | 1 | 16 |
| Unsigned integer | 2 | 16 |
| Unsigned integer | 3 | 16 |
| Unsigned integer | 4 | 16 |
| Unsigned integer | 1 | 32 |
| Unsigned integer | 2 | 32 |
| Unsigned integer | 3 | 32 |
| Unsigned integer | 4 | 32 |
| Unsigned integer | 1 | 64 |
| Unsigned integer | 2 | 64 |
| Unsigned integer | 3 | 64 |
| Unsigned integer | 4 | 64 |
| IEEE754 floating point | 1 | 16 |
| IEEE754 floating point | 2 | 16 |
| IEEE754 floating point | 3 | 16 |
| IEEE754 floating point | 4 | 16 |
| IEEE754 floating point | 1 | 32 |
| IEEE754 floating point | 2 | 32 |
| IEEE754 floating point | 3 | 32 |
| IEEE754 floating point | 4 | 32 |
| IEEE754 floating point | 1 | 64 |
| IEEE754 floating point | 2 | 64 |
| IEEE754 floating point | 3 | 64 |
| IEEE754 floating point | 4 | 64 |
module Axis where
data Axis
= PositiveX
| PositiveY
| PositiveZ
| NegativeX
| NegativeY
| NegativeZ
data AxisName
= AxisX
| AxisY
| AxisZ
axisName :: Axis -> AxisName
axisName PositiveX = AxisX
axisName NegativeX = AxisX
axisName PositiveY = AxisY
axisName NegativeY = AxisY
axisName PositiveZ = AxisZ
axisName NegativeZ = AxisZ
data AxisSystem = AxisSystem {
axis_right :: Axis,
axis_up :: Axis,
axis_forward :: Axis
}
axisValid :: (Axis, Axis, Axis) -> Bool
axisValid (right, up, forward) =
case (axisName right, axisName up, axisName forward) of
(AxisX, AxisY, AxisZ) -> True
(AxisZ, AxisX, AxisY) -> True
(AxisY, AxisZ, AxisX) -> True
_ -> False
data WindingOrder
= WindingOrderClockwise
| WindingOrderCounterClockwise
data CoordinateSystem = CoordinateSystem {
coords_axes :: AxisSystem,
coords_order :: WindingOrder
}
data SchemaIdentifier = SchemaIdentifier {
schema_id :: String,
schema_version_major :: Word32,
schema_version_minor :: Word32
}
schema_name =
? [a-z_.0-9]{1,64} ? ;
<composite name="SMFHeader">
<type name="magicNumber"
description="The magic number identifying the section."
presence="constant"
primitiveType="uint64">
0x89534D460D0A1A0A
</type>
<type name="versionMajor"
description="The major version of the specification to which this file conforms."
primitiveType="uint32"/>
<type name="versionMinor"
description="The minor version of the specification to which this file conforms."
primitiveType="uint32"/>
</composite>
<composite name="SMFSectionFields">
<ref name="fieldsSize"
type="uint32"/>
<ref name="schemaIdentifier"
type="SMFSchemaIdentifier"/>
<ref name="vertexCount"
type="uint64"/>
<type name="triangleCount"
primitiveType="uint64"
semanticType="Length"/>
<type name="triangleSizeBits"
primitiveType="uint32"
semanticType="Length"/>
<ref name="attributeCount"
type="uint32"/>
<ref name="coordinateSystem"
type="SMFCoordinateSystem"/>
<enum name="SMFByteOrder"
encodingType="uint32">
<validValue name="BIG_ENDIAN">0</validValue>
<validValue name="LITTLE_ENDIAN">1</validValue>
</enum>
</composite>
<composite name="SMFSchemaIdentifier">
<type name="nameLength"
description="The number of bytes in the following name array that should be extracted to form a name."
primitiveType="uint32"/>
<type name="name"
primitiveType="uint8"
characterEncoding="UTF-8"
length="64"/>
<type name="versionMajor"
description="The major version of the schema."
primitiveType="uint32"/>
<type name="versionMinor"
description="The minor version of the schema."
primitiveType="uint32"/>
</composite>
<enum name="SMFAxis"
encodingType="uint8">
<validValue name="AXIS_POSITIVE_X">0</validValue>
<validValue name="AXIS_POSITIVE_Y">1</validValue>
<validValue name="AXIS_POSITIVE_Z">2</validValue>
<validValue name="AXIS_NEGATIVE_X">3</validValue>
<validValue name="AXIS_NEGATIVE_Y">4</validValue>
<validValue name="AXIS_NEGATIVE_Z">5</validValue>
</enum>
<enum name="SMFWindingOrder"
encodingType="uint8">
<validValue name="FACE_WINDING_ORDER_CLOCKWISE">0</validValue>
<validValue name="FACE_WINDING_ORDER_COUNTER_CLOCKWISE">1</validValue>
</enum>
<composite name="SMFCoordinateSystem">
<ref name="right"
type="SMFAxis"/>
<ref name="up"
type="SMFAxis"/>
<ref name="forward"
type="SMFAxis"/>
<ref name="windingOrder"
type="SMFWindingOrder"/>
</composite>
import qualified Axis as A axisOrdinal :: A.Axis -> Integer axisOrdinal A.PositiveX = 0 axisOrdinal A.PositiveY = 1 axisOrdinal A.PositiveZ = 2 axisOrdinal A.NegativeX = 3 axisOrdinal A.NegativeY = 4 axisOrdinal A.NegativeZ = 5 windingOrdinal :: A.WindingOrder -> Integer windingOrdinal A.WindingOrderClockwise = 0 windingOrdinal A.WindingOrderCounterClockwise = 1
<composite name="SMFSchemaAttribute">
<type name="nameLength"
description="The number of bytes in the following name array that should be extracted to form a name."
primitiveType="uint32"/>
<type name="name"
primitiveType="uint8"
characterEncoding="UTF-8"
length="64"/>
<enum name="componentKind"
encodingType="uint32">
<validValue name="ELEMENT_TYPE_INTEGER_SIGNED">0</validValue>
<validValue name="ELEMENT_TYPE_INTEGER_UNSIGNED">1</validValue>
<validValue name="ELEMENT_TYPE_FLOATING">2</validValue>
</enum>
<type name="componentCount"
description="The number of components in a single attribute value."
minValue="1"
maxValue="4"
primitiveType="uint32"/>
<type name="componentSizeBits"
description="The size in bits of components in a single attribute value."
minValue="1"
maxValue="64"
primitiveType="uint32"/>
</composite>
import qualified Attribute as A attributeTypeOrdinal :: A.ComponentType -> Integer attributeTypeOrdinal A.IntegerSigned = 0 attributeTypeOrdinal A.IntegerUnsigned = 1 attributeTypeOrdinal A.FloatingPoint = 2
<composite name="SMFSection">
<type name="magicNumber"
description="The magic number identifying the section."
primitiveType="uint64"/>
<type name="size"
description="The size of the section data"
primitiveType="uint64"
semanticType="Length"/>
</composite>
void showSections()
{
// Read SMF header
long smf = readUnsigned64();
int major = readUnsigned32();
int minor = readUnsigned32();
// Read all sections
while (bytesRemaining()) {
long offset = currentOffset();
long magic = readUnsigned64();
long size = readUnsigned64();
System.out.printf(
"section: %s %s %s\n",
Long.toUnsignedString(offset),
Long.toUnsignedString(magic, 16),
Long.toUnsignedString(size));
seek(size);
}
}
| 1 |
Ignoring unrecognized sections allows for forwards compatibility: An implementation
supporting version
m
can read a file of version n, where
m < n, and ignore any new sections specified by format
n
that it does not understand.
References to this footnote:
1
|
| 2 |
The requirement for data to be aligned to 16 octet boundaries is intended to facilitate
implementations using vector instruction sets such as
SSE
to efficiently operate on memory-mapped SMF/B files.
References to this footnote:
1
|
<composite name="SMFMeta">
<ref name="metaSchemaIdentifier"
type="SchemaIdentifier"/>
<ref name="metaSize"
type="uint32"/>
</composite>
smf = "smf" , integer-unsigned , integer-unsigned ;
attribute_name_raw =
? [a-z_.0-9]{1,64} ? ;
attribute_name_quoted =
""" , attribute_name_raw , """ ;
attribute_name =
attribute_name_raw | attribute_name_quoted ;
attribute_type =
"integer-signed" | "integer-unsigned" | "float" ;
smf_attribute =
"attribute" , attribute_name , attribute_type , integer-unsigned , integer-unsigned ;
axis = "+x" | "-x" | "+y" | "-y" | "+z" | "-z" ; winding_order = "clockwise" | "counter-clockwise" ; smf_coordinates = "coordinates" , <axis> , <axis> , <axis> , <winding_order> ;
coordinates +x +y -z counter-clockwise
byte_order = "big" | "little" ; smf_attribute = "endianness" , byte_order ;
smf_schema = "schema" , schema_name , integer-unsigned , integer-unsigned ;
smf_triangles = "triangles" , integer-unsigned , integer-unsigned ;
trianges 0 32
smf_vertices = "vertices" , integer-unsigned ;
vertices 0
end = "end" ;
metadata = "metadata" , schema_name , integer-unsigned , integer-unsigned , integer-unsigned ;
data_command_triangles = "triangles" ;
vertices_noninterleaved_attribute = "attribute" , attribute_name ;
smf 1 0 schema com.io7m.example.smf 1 0 vertices 9 triangles 4 32 coordinates +x +y -z counter-clockwise attribute "POSITION" float 3 32 attribute "NORMAL" float 3 32 attribute "UV:UVMap" float 2 32 attribute "GROUP:group0" float 1 32 end # # This is a comment and will be ignored. # vertices-noninterleaved attribute "POSITION" 0.000000000000000 0.000000000000000 0.000000000000000 1.000000000000000 0.000000000000000 0.000000000000000 0.000000000000000 0.000000000000000 -2.000000000000000 1.000000000000000 0.000000000000000 -2.000000000000000 2.000000000000000 0.000000000000000 0.000000000000000 2.000000000000000 0.000000000000000 -2.000000000000000 1.000000000000000 0.000000000000000 0.000000000000000 1.000000000000000 0.000000000000000 -2.000000000000000 1.000000000000000 0.000000000000000 0.000000000000000 attribute "NORMAL" 0.000000000000000 1.000000000000000 0.000000000000000 0.000000000000000 0.999999940395355 0.000000000000000 0.000000000000000 1.000000000000000 0.000000000000000 0.000000000000000 1.000000000000000 0.000000000000000 0.000000000000000 1.000000000000000 0.000000000000000 0.000000000000000 1.000000000000000 0.000000000000000 0.000000000000000 0.999999940395355 0.000000000000000 0.000000000000000 1.000000000000000 0.000000000000000 0.000000000000000 0.999999940395355 0.000000000000000 attribute "UV:UVMap" 0.112528264522552 0.912521243095398 0.112528264522552 0.712549567222595 0.512471735477448 0.912521243095398 0.696853816509247 0.614087224006653 0.396896183490753 0.464108407497406 0.696853816509247 0.464108407497406 0.396896213293076 0.614087224006653 0.512471735477448 0.712549448013306 0.396896213293076 0.614087224006653 attribute "GROUP:group0" 0.000000000000000 0.300000011920929 0.200000002980232 0.400000005960465 0.600000023841858 0.699999988079071 0.300000011920929 0.400000005960465 0.300000011920929 end triangles 1 2 0 6 5 3 1 7 2 8 4 5 end metadata com.example.metadata.example0 1 0 1 aGVsbG8taGVsbG8K end metadata com.example.metadata.example3 2 0 5 AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1 Njc4OTo7PD0-P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWpr bG1ub3BxcnN0dXZ3eHl6e3x9fn-AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6Ch oqOkpaanqKmqq6ytrq-wsbKztLW2t7i5uru8vb6_wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX 2Nna29zd3t_g4eLj5OXm5-jp6uvs7e7v8PHy8_T19vf4-fr7_P3-_w== end