Syntax of the .ray File Format

For this project we define a rudimentary scene graph language. Each command begins with a #-sign and goes on until the next command or until the end of the file is reached. Commands may extend across new-line characters. All color values are floating point values between 0.0 and 1.0, and all other numeric expressions are assumed to be floating point, also, unless otherwise noted.  Angles are given in radians. When needed, the parser automatically scales a vector to a unit-length vector. You should not that in order to define triangles  you must first define the vertices you will use and then index them in the triangle definition.

Commands:

#camera
    px py pz
    dx dy dz
    ux uy uz
    ha

This defines a perspective camera in the scene. (px,py,pz) is the position of the camera in world coordinates, (dx,dy,dz) is a vector describing the direction of the camera, and (ux,uy,uz) is a vector in the up direction.  The height angle of the viewing frustum is given by ha, such that the width angle can be found by ha*ar, where ar is the width-over-height aspect ratio of the output image (given on the command line). The camera command must appear before of any Group or Shape directives.  The first camera found in the file will be used, and subsequent camera definitions are ignored.

#background
    r g b

The background color defines the color to assign to rays which fail to intersect any object, and leave the scene.  Only the first background definition encountered is used, and subsequent instances are ignored.  It must appear before any Group or Shape directives.  If not defined, a value of black is assumed.

#ambient
    r g b

Sets the global ambient light level. The first ambient definition is used, and subsequent instances are ignored.  It must appear before any Group or Shape directives. If not defined, a value of black is assumed.

#light_num n

The total number of lights in the scene is given by this command.  This command must appear before any light_* definitions.  It must appear before any Group or Shape directives. If there are no lights in the scene (only global ambient light), light_num 0 need not be declared.

#light_point
    r g b
    px py pz
    ca la qa

This defines a point light in the scene.  (r,g,b) gives the color of the light.  In this ray tracer, use this single light color for diffuse and specular contributions at each surface.  Do not compute ambient contributions from each light, but rather use the global ambient light defined by the ambient directive.  Each instance must appear before any Group or Shape directives.

(px,py,pz) gives the position of the light in world coordinates.  The attenuation of the light with distance from its position is given by ca, la, and qa which define the constant, linear and quadratic components of the attenuation factor.  If d is the distance from the light to the surface, then the light's color at the surface is given by (r,g,b) *1.0/ (ca + la*d + qa*d*d).  Each coeficient must be positive or equal to zero. Note: to achieve no attenuation use a (ca,la,qa) of (1.0,0.0,0.0).

#light_spot
    r g b
    px py pz
    dx dy dz
    ca la qa
    sc sd

This defines a spot point light in the scene.  (r,g,b) gives the color of the light.  In this ray tracer, use this single light color for diffuse and specular contributions at each surface.  Do not compute ambient contributions from each light, but rather use the global ambient light defined by the ambient directive. Each instance must appear before any Group or Shape directives.

(px,py,pz) gives the position of the light in world coordinates, and (dx,dy,dz) is a unit vector describing the direction of the light.   The attenuation of the light with distance from its position is given by ca, la, and qa which define the constant, linear and quadratic components of the attenuation factor.  If d is the distance from the light to the surface, then the light's color at the surface is given by (r,g,b) *1.0/ (ca + la*d + qa*d*d).  Each coeficient must be positive or equal to zero. Note: to achieve no attenuation use a (ca,la,qa) of (1.0,0.0,0.0).

The spot light cutoff is given by cs and defines the half angle of divergence of the light cone.  It can be measured as the angle from the center axis to the edge of the spot cone.  It should be less than pi/2 radians.  The fall off in intensity from the center axis to the cone edge is given by the spot drop-off factor, sd.  It can take values from 0.0 to 128.0, where 0.0 indicated constant intensity across the cone, and 128.0 yields a sharp fall-off.  The cosine of the angle between light direction and the direction of a ray from (px,py,pz) to the point being lit, raised to the power of sd will yield the correct result.

#light_dir
    r g b
    dx dy dz

This defines a directional light in the scene.  (r,g,b) gives the color of the light.  In this ray tracer, use this single light color for diffuse and specular contributions at each surface.  Do not compute ambient contributions from each light, but rather use the global ambient light defined by the ambient directive. Each instance must appear before any Group or Shape directives.

(dx,dy,dz) is a vector giving the direction of the light in the scene. Note that attenuation makes no sense for directional lights, and so is not a parameter of this directive.

#texture_num n

The total number of textures used in the scene is given by this command.  The command must appear before any texture AND/OR material definitions.  It must appear before any Group or Shape directives. If there are no textures used, texture_num 0 need not be declared.

#texture filename

Each texture used in the scene is declared by the texture directive using the filename of the texture.  The first texture declared will take the interger identifier 0, and subsequent textures will follow in order (i.e. 1, 2, 3, ...). This integer handle is used in material definitions to indicate that the material includes the respective texture. Textures need to be declared before materials. This declaration must appear before any Group or Shape directives.

#vertex_num n
The total number of vertices to be used in the scene. The command must appear before any vertex definitions.  This declaration must appear before any Group or Shape directives.

#vertex
    px py pz
    nx ny nz
    ts tt
This defines a verex at position (px,py,pz) with normal (nx,ny,nz) and texture coordinate (ts,tt). Each vertex used in the scene is declared by the vertex directive. The first vertex declared will take the interger identifier 0, and subsequent vertices will follow in order (i.e. 1, 2, 3, ...). This integer handle is used in triangle definitions to indicate which vertices make up the triangle. This declaration must appear before any Group or Shape directives.

#material_num n

The total number of materials used in the scene is given by this command.  The command must appear before any material definitions.  This declaration must appear before any Group or Shape directives.

#material
    er eg eb
    ar ag ab
    dr dg db
    sr sg sb sfo
    tr tg tb
    ir
    tn
    !string!

Each material used in the scene is declared by the material directive.  The first material declared will take the interger identifier 0, and subsequent materials will follow in order (i.e. 1, 2, 3, ...). This integer handle is used in shape definitions to indicate that the rendering should occur with the appropriate material.  This declaration must appear before any Group or Shape directives.

The colors (er,eg,eb), (ar,ag,ab), (dr,dg,db), and (sr,sg,sb) are the emmisive, ambient, diffuse, and specular colors of the material, respectively. The emmisive material color acts independently of any light source, the ambient material color is used in ambient light calculation with the global ambient light color, and the diffuse and specular material colors are used in diffuse and specular lighting computations with the color of each light in the scene.

The exponent sfo defines the specular 'shininess' (or 'fall-off') of the material, and takes values from 0.0 to 128.0. The cosine of the angle between the ray direction and the specular reflection direction raised to the power of sfo gives the specular highlight factor. sr, sg, and sb define the reflection coefficient for recursive reflection rays. The index of refraction is given by ir and is used in Snell's Law computations for refraction direction.  For non-closed surfaces, such as triangles, it is assumed that ir is the index of refraction on the backside of the surface.  For closed surfaces, such as cones, it is assumed that ir is the index of refraction on the inside of the surface.

To assign a texture to this material, tn should be the integer handle of the appropriate texture declared in the file.  At rendering time, it is assumed that the color of the appropriate texture pixel will modulate the color computed by the lighting equation.  If no texture is to be associated with the material, then a value of -1 must be  indicated.

The final parameter is a string delimited by exclaimation marks.  The string must not contain any control characters, or unpredicatable behaviour could occur.  This field is provided for the users to assign material properties not defined by this file format.  For instance, the numeric constants describing a Perlin Noise 3D solid texture could be put in this field to instruct the rendered to how to texture shapes which are drawn with this material.  If no unsupported parameters are required, empty exclamation marks must conclude the material declaration as follows: !!

#ray_file_num  n

The total number of .ray files used in the scene is given by this command. The command must appear before any ray_file definition. This declration must appear before any Group or Shape directives.

#ray_file  fileName

Each ray_file used in the scene is declared by the ray_file directive. The first ray_file declared will take the identifier 0, and subsequent ray_files will follow in order (i.e. 1,2,3, ...). This integer handle is used in scene-graph definitions to indicate that the scene-graph specified by the file should occur as a node to the current scene-graph. This declaration must appear before any Group or Shape directives.

#group_begin
    m11 m21 m31 m41
    m12 m22 m32 m42
    m13 m23 m33 m43
    m14 m24 m34 m44
#group_end

This pair of directives defines a node that will be added to the current scene-graph with the specified transformation context. All objects within the group_begin .. and associated group_end directive are subject to the 4x4 transformation matrix given in the group_begin declaration.  Groups may be nested, permitting the specification of a transformation heirarchy.  Shapes within nested groups are subject, in order, to the transformation contexts of all their enclosing groups.  The total transformation context of a given shape is determined, then, by starting with the matrix of the root enclosing group, and concatenating additional matrices on the right as we decend into nested groups, until we reach the shape.  The transformation context of a group is applicable only to its shapes and sub groups, so we must remove matrices from the right as we ascend back up the heirarchy.

The matrix elements appear as follows and are intended to operate on column vectors:

|m11 m21 m31 m41|
|m12 m22 m32 m42|
|m13 m23 m33 m43|
|m14 m24 m34 m44|

Note: When the .ray file is initially parsed the root scene-graph node is instantiated with the identity matrix, so that Shapes specified outside any Group directives are still valid.

#shape_* m ...

All shapes that can be defined are prefixed by shape_ and take a common first parameter m which indicates the integer handle of the material to use when rendering the object.  Subsequent descriptions of the supported shapes will omit explanations of the m parameter...
 

#shape_sphere  m
    cx cy cz
    r

This defines a sphere, situated at the point (cx,cy,cz) with a radius given by r.

#shape_box  m
    cx cy cz
    lx ly lz

This defines an axis aligned box, centered at the point (cx,cy,cz).   The length of the x, y, and z axis aligned sides is given by lx, ly, and lz, respectively. The box extends from x=cx-lx/2 to x=cx+lx/2, y=cy-ly/2 to y=cy+ly/2, and z=cz-lz/2 to z=cz+lz/2.

#shape_cylinder m
    cx cy cz
    r h

This defines a cylinder, with a central axis parallel to the y-axis, and centered at the point (cx,cy,cz).  The radius and height are given by r and h, respectively.  The cylinder is a closed surface (i.e. it has end caps.)  The ends lie at y=cy-h/2 and y=cy+h/2.

#shape_cone  m
    cx cy cz
    r h

This defines a cone, with a central axis parallel to the y-axis, and centered at the point (cx,cy,cz).  The radius and height are given by r and h, respectively.  The cone is a closed surface (i.e. it's base is capped) The base and apex of the cone lie at y=cy-h/2 and y=cy+h/2, respectively.

#shape_triangle  m
    i1 i2 i3
This defines a triangle with vertices indexed by i1, i2, and i3.

#ray_file_instance  n

This specifies the index of the scene-graph, that is to be added as a node to the current scene-graph.