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.
Overview 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: nff 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:: nff 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 Gouraud-shading: 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