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 half-height angle of the viewing frustum is given by ha, such that the half-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 1.0, where 0.0 indicated constant intensity across the cone, and 1.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 128*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
ar ag ab
dr dg db
sr sg sb
er eg eb
n kt 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 (ar,ag,ab), (dr,dg,db), (sr,sg,sb), and (er,eg,eb) are the ambient, diffuse, specular, and emmisive colors of the material, respectively. The ambient material color is used in ambient light calculation with the global ambient light color, the diffuse and specular material colors are used in diffuse and specular lighting computations with the color of each light in the scene, and the emmisive material color acts independently of any light source.
The exponent n defines the specular 'shininess' of the material, and takes values from 0.0 to 1.0. The cosine of the angle between the ray direction and the specular reflection direction raised to the power of 128*n gives the specular highlight factor. sr, sg, and sb define the reflection coefficient for recursive reflection rays. kt is the transmission coefficient for recursive transmission rays, and ranges from 0.0 to 1.0. ks + kt need not total to 1.0. 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_line m
sx sy sz
ex ey ez
This defines a line segment with starting point at (sx,sy,sz) and ending point at (ex,ey,ez). (Your ray tracer should ignore this but it will be useful for using the ray-viewer when debugging.)
#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.