Neutral ASCII File Format

This document is Copyright (c) 1993 by Sense8 Corporation. Reproduction of this document is allowed and encouraged, as long as the file remains intact with this copyright message.


The Sense8 neutral ASCII file format (NFF) is a generic
representation for polygonal geometry.

In order to import other geometry into WorldToolKit, users may write
translators to transform their proprietary format into the neutral
ASCII file format, which can then be read directly.  Thus, the NFF
format serves as an interface between modelers which cannot write
geometry in any of the forms accepted by WorldToolKit.

NFF is also useful as a general format for the interchange of 3D
geometry, especially between real-time 3d rendering systems.  It is
better suited for this task than any other known ASCII file format,
due to superior efficiency, readability and support of such important
information as vertex normals and backface rejection.  Sense8
encourages and recommends the use of the NFF format by anyone who
uses 3D geometry.

NFF Syntax

The following describes version 2.0 of the NFF standard.  For changes
from earlier versions, see the section below, "NFF Revision History".

NFF header

The file must begin with a line containing the string token "nff".
This is used by WTK to determine the type of file.  The next line
should state the version level of the NFF file.  Next follows an
optional viewpoint specification associated with the file, and a set
of one or more object specifications.  All lines must be terminated
by a linefeed character, but the MSDOS end-of-line convention CR-LF
is also supported, although not encouraged.

NFF files may have comments placed on any line.  The characters "//"
introduce a comment.  All characters on the line following the "//"
are ignored.  The NFF format is also very flexible with white space;
any number of tabs or spaces are allowed before, between and after
words in the file.

The second line in the file should be the NFF version number.  The
current version is 2.0.  Although the version number is optional,
providing it ensures that the file will be read correctly even if the
NFF format changes in the future.

The optional viewpoint is specified as two lines with the tokens
"viewpos" and "viewdir".  These specify the viewpoint's location and
view direction respectively.

Here is the entire header syntax:

version x.xx
[viewpos x y z]
[viewdir x y z]

Here is an example of a an NFF header that uses all the options::

version 2.0
viewpos 0.000 0.000 0.000
viewdir 0.000 0.000 1.000

NFF objects

Each object specification must starts with a line of text giving the
object's symbolic name, followed by the description of the geometry
of the object.  The syntax is as follows:

objectname [shading=on or off]
number of vertices
first vertex
last vertex
number of polygons
first polygon
last polygon

An NFF file can contain any number of objects, each described by its 
own name and geometry:

NFF header
first NFF object
last NFF object

NFF vertices

After the NFF header, the next line should be a single integer value
defining the total number of vertices in the object.  Vertex x, y, z
coordinates, as real numbers, follow one per line.  The vertex
coordinate lines should contain three real numbers (as could be read
in C with a "%f %f %f" format string).  One or more spaces or other
white space must separate the numbers.

If your hardware supports Gouraud-shaded polygons, you can optionally
specify a normal vector for each vertex (this is used to calculate
the shading intensity for each vertex).  When WorldToolKit reads that
a particular vertex has a normal associated with it, WTK will
automatically render the associated polygon as Gouraud-shaded.

The vertex normal is introduced by the keyword "norm" and is defined
as three real numbers following the vertex co-ordinates.  Here is the
vertex definition syntax:

number of vertices
x y z [norm x y z]
x y z [norm x y z]

Here is an example of defining three vertices with vertex normals for 

3   // number of vertices to be defined
0.00 0.00 0.00  norm 0.707 0.707 0.00
-100.00 0.00 0.00  norm -0.707 -0.707 0.00
0.00 100.00 0.00  norm 1.00 0.00 0.00

NFF polygons

After defining the vertices, the next line contains the number of
polygons in the object.  Polygon specification lines follow, one for
each polygon.

The polygon specification line starts with an integer giving the
number of vertices in the polygon.  Following that, a list of vertex
indices is referenced for the current polygon (zero indicates the
first vertex index).  Note that the front face of a polygon is
defined by a counter- clockwise ordering of the vertex indices.  This
is important to understand if you plan on using backface reject
techniques (described below).  

After the list of vertex indices is a color designator given in
hexadecimal as a number in the range 0x0 to 0xfff.  The high order 4
bits represents the red intensity, the middle 4 bits the green, and
the low order 4 bits the blue.  Black is defined as 0x000 and white
is 0xfff.  You may also specify similar 24-bit rgb values, inthe form
0xrrggbb.  However, 24-bit colors are currently converted to 12-bit
colors when read.

The optional string "both" indicates that both sides of the polygon
are to be visible.  In other words, there is no backface rejection
for this polygon.  The default setting is to render only front facing
polygons, by the right hand rule (vertices defined counter-clockwise).

Optionally, a texture name and attributes can be specified for the
polygon.  Note that when texturing is on, color is ignored for the
textured polygons since the surface properties come from the texture.
Texture names give the file containing the bitmap to be used as a
texture, and specify whether the texture is to be plain, shaded or
transparent.  Shaded textures have their brightness affected by the
lights present in the model.  Transparent textures are rendered so
that all black pixels in the source bitmap are transparent when the
texture is applied to a polygon.  Texture names begin with the
character "_".  The character following the "_" indicates the type of
texture, according to the following:

   _v_      plain vanilla texture (no shading)
   _s_      shaded texture
   _t_      transparent texture

For example, a texture named "_v_rug" causes a texture from a file
named "rug" to be used.  A texture named "_s_rug" would apply the same
texture, but shaded based on lighting.  At present, these three
options are mutually exclusive.

You may also specify texture attributes immediately after the texture
name.  These take the format:

[rot value] [scale value] [trans value value] [mirror]

They specify texture rotation, scaling, translation, and mirroring
respectively.  Any or none of these attributes may appear, but they
must be placed after the texture name.

Regardless of the order of the attributes, at the time the polygon is
loaded, they will always be applied in the following order:
mirroring, rotation, scaling, translation.  Since the NFF file's
description of these texture attributes does not uniquely specify
every possible transformation, if you require that files saved by WTK
retain their exact transformation when loaded back in, apply your
attributes in the same order (mirroring, rotation, scaling,
translation) before saving.

Using the optional polygon ID token "id=n", you can assign an integer
value "n" to any polygon in your NFF file (example: id=567).  Then,
from within your WorldToolKit application, you can use the
WTpoly_getid function to retrieve the ID number for the polygon in
question.  You can use this feature to "link" polygons in your NFF
file with polygons in your application.  This is extremely useful for
texture animations or other special tricks.

Finally, a portal name can be specified for a polygon.  Portal names
begin with a "-" and contain the name of the universe to be loaded
when the portal is crossed.

Each polygon specification line is of the form:

#vertices verticies color[both] [texture[attributes]] [id=n] [portal]

This is a sample polygon specification, illustrating all possible options:

5 0 1 2 3 4 0xff0 both _s_rug rot 1.0 scale 0.5 trans 1.0 1.0 id=5 -rugworld

This polygon has 5 vertices and is colored yellow, although the
yellow will not appear unless you are rendering without textures.
Both sides of the polygon are visible, and a shaded rug texture is
applied.  The rug texture is rotated 1 radian, scaled to half-size,
and translated by (1.0,1.0) in (u,v) space.  The polygon`s ID number
is set to 5 and if the viewpoint crosses this polygon, the universe
"rugworld" will be loaded.

WTK Extensions to the NFF Standard

Automatic normal generation

Since adding vertex normals by hand is very difficult, WorldToolKit
supports an automatic normal generation procedure for NFF files (this
doesn't work for DXF or other file formats).  To use this feature,
you would add an "N" at the end of any vertex line that you wanted
WorldToolKit to calculate your normals for you.  When the file is
read into WorldToolKit, the "N" is replaced with an approximate
vertex normal, based on the average of the polygons surrounding that
vertex.  This approximation may lead to an incorrect normal if
polygons are defined haphazardly.  You may also encounter problems if
some vertices are shared by polygons you don't want Gouraud-shaded.
In this case, you will have to make duplicate vertices -- one with a
vertex normal and one without.  After reading in an object with
automatic normals, you may want to write the object back out so that
the next time it is read the normals are already calculated.

NFF Version History

2.0   added "norm" keyword to introduce vertex normals
      removed useless "distinct" keyword
1.9   no changes
1.7   changed object shading to  =on and =off instead of =flat and =none
1.6   first numbered version

Sample NFF File

The following is an example of a simple ASCII NFF file containing a a
simple cube and a pyramid.  Some polygons of the first cube are
textured and some are not.

nff   // This is the first word of any NFF file.
version 2.0

// The following two lines are optional.
viewpos 0.0 0.0 0.0   // Viewpoint is at the origin
viewdir 0.0 0.0 1.0   // and looking straight forward.

SimpleCube         // Name of the object.
8                  // Number of vertices.
3.0 3.0 -3.0       // Vertex info.
3.0 -3.0 -3.0
-3.0 -3.0 -3.0
-3.0 3.0 -3.0
3.0 3.0 3.0
3.0 -3.0 3.0
-3.0 -3.0 3.0
-3.0 3.0 3.0
6                         // Number of polygons.
4 0 1 2 3 0xf00 both      // 0xf00 is the color, in this case, Red
4 7 6 5 4 0x0f0 both      // "both" sides of the cube's faces are visible,
4 0 4 5 1 0x00f both      // so it is visible even from inside the cube.
4 1 5 6 2 0xff0 both _S_wings           // A shaded texture called "wings"
4 2 6 7 3 0xfff both _T_fish rot 1.0    // A rotated, transparent fish texture
4 3 7 4 0 0x000 both _V_kproom -kproom  // a portal to universe "kproom" with
                                        // a texture called "kproom"

SecondObject      // Name of the object.
5                 // Number of vertices.
9.0 9.0 -9.0      // Vertex info.
9.0 -9.0 -9.0
-9.0 -9.0 -9.0
-9.0 9.0 -9.0
0.0 0.0 9.0
5                     // Number of polygons.
4 0 1 2 3 0xf00 both
3 0 1 4 0x00f both
3 1 2 4 0xff0 both 
3 2 3 4 0xfff both
3 3 0 4 0x000 both