fbe University of New South Wales Sydney Australia UNSW
Faculty of the Built Environment search

5 - Object Definition

5.1 The World Object
5.2 Primitives
5.3 Aggregate Objects
5.4 Constructive Solid Geometry
5.4.1 CSG in Rayshade
5.4.2 Potential CSG Problems
5.5 Named Objects


Objects in rayshade are composed of relatively simple primitive objects. These primitives may be used by themselves, or they may be combined to form more complex objects known as aggregates. A special family of aggregate objects, Constructive Solid Geometry or CSG objects, are the result of a boolean operations applied to primitive, aggregate, or CSG objects.

This chapter describes objects from a strictly geometric point of view. Later chapters on surfaces, textures, and shading describe how object appearances are defined.

An instance is an object that has optionally been transformed and textured. They are the entities that are actually rendered by rayshade; when you specify that, for example, a textured sphere is to be rendered, you are said to be instantiating the textured sphere. An instance is specified as a primitive, aggregate, or CSG object that is followed by optional transformation and texturing information. Transformations and textures are described in Chapters 7 and 8 respectively.


5.1 The World Object

Writing a rayshade input file is principally a matter of defining a special aggregate object, the World object, which is a list of the objects in the scene. When writing a rayshade input file, all objects that are instantiated outside of object-definition blocks are added to the World object; you need not (not should you) define the World object explicitly in the input file.


5.2 Primitives

Primitive objects are the building bocks with which other objects are created. Each primitive type has associated with it specialized methods for creation, intersection with a ray, bounding box calculation, surface normal calculation, ray enter/exit classification, and for the computation of 2D texture coordinates termed u-v coordinates. This latter method is often referred to as the inverse mapping method.

While most of these methods should be of little concern to you, the inverse mapping methods will affect the way in which certain textures are applied to primitives. Inverse mapping is a matter of computing normalized u and v coordinates for a given point on the surface of the primitive. For planar objects, the u and v coordinates of a point are computed by linear interpolation based upon the u and v coordinates assigned to vertices or other known points on the primitive. For non-planar objects, uv computation can be considerably more involved.

This section briefly describes each primitive and the syntax that should be used to create an instance of the primitive. It also describes the inverse mapping method, if any, for each type.

blob thresh st r p» [st r p» ... ]
Defines a blob with consisting of a threshold equal to thresh, and a group of one or more metaballs. Each metaball is defined by its position p», radius r, and strength st. The metaballs affect each other according to a superimposed density disribution:

There is no inverse mapping method for blobs.

box corner1» corner2»
Creates an axis-aligned box which has corner1» and corner2» as opposite corners. Transformations may be applied to the box if a non-axis-aligned instance is required. There is no inverse mapping method for boxes.

sphere radius center»
Creates a sphere with the given radius and centered at the given position. Note that ellipsoids may be created by applying the proper scaling to a sphere. Inverse mapping on the sphere is accomplished by computing the longitude and latitude of the point on the sphere, with the u value corresponding to longitude and v to latitude. On an untransformed sphere, the z axis defines the poles, and the x axis intersects the sphere at u = 0, v = 0.5. There are degeneracies at the poles: the south pole contains all points of latitude 0., the north all points of latitude 1.

torus rmajor rminor center» up»
Creates a torus centered at center» by rotating a circle with the given minor radius around the center point at a distance equal to the major radius. In tori inverse mapping, the u value is computed using the angle of rotation about the up vector, and the v value is computing the angle of rotation around the tube, with v = 0 occurring on the innermost point of the tube.

triangle p1» p2» p3»
Creates a triangle with the given vertices.

triangle p1» n1» p2» n2» p3» n3»
Creates a Phong-shaded triangle with the given vertices and vertex normals.

For both Phong- and flat-shaded triangles, the u axis is the vector from p1» to p2», and the v axis the vector from p1» to p3». There is a degeneracy at p3», which contains all points with v = 1.0. This default mapping may be modified using the triangleuv primitive described below.

triangleuv p1» n1» uv1» p2» n 2» uv2» p3» n3» uv3»
Creates a Phong-shaded triangle with the given vertices, vertex normals. When performing texturing, the uv given for each vertex are used instead of the default values. When computing uv coordinates within the interior of the triangle, linear interpolation of the coordinates associated with each triangle vertex is used.

poly p1» p2» p3» [p4» ...]
Creates a polygon with the given vertices. The vertices should be given in counter-clockwise order as one is looking at the "front" side of the polygon. The number of vertices in a polygon is limited only by available memory. Inverse mapping for arbitrary polygons is problematical. Rayshade punts and equate u with the x coordinate of the point of intersection, and v with the y coordinate.

heightfield file
Creates a height field defined by the altitude data stored in the named file. The height field is based upon perturbations of the unit square in the z = 0 plane, and is rendered as a surface tessellated by right isosceles triangles.

See Appendix C for a discussion of the format of a height field file. Height field inverse mapping is straight-forward: u is the x coordinate of the point of intersection, v the y coordinate.

plane point» normal»
Creates a plane that passes through the given point and has the specified normal. Inverse mapping on the plane is identical to polygonal inverse mapping.

cylinder radius bottom» top»
Creates a cylinder that extends from bottom» to top» and has the indicated radius. Cylinders are rendered without endcaps. The cylinder's axis defines the v axis. The u axis wraps around the cylinder, with u = 0 dependent upon the orientation of the cylinder.

cone radbottom bottom» radtop top»
Creates a (truncated) cone that extends from bottom» to top». The cone will have a radius of radbottom at bottom» and a radius of radtop at top». Cones are rendered without endcaps. Cone inverse mapping is analogous to cylinder mapping.

disc radius pos» normal»
Creates a disc centered at the given position and with the indicated surface normal. Discs are useful for placing endcaps on cylinders and cones. Inverse mapping for the disc is based on the computation of the normalized polar coordinates of the point of intersection. The normalized radius of the point of intersection is assigned to u, while the normalized angle from a reference vector is assigned to v.


5.3 Aggregate Objects

An is a collection of primitives, aggregate, and CSG objects. An aggregate, once defined, may be instantiated at will, which means that copies that are optionally transformed and textured may be made. If a scene calls for the presence of many geometrically identical objects, only one such object need be defined; the one defined object may then be instantiated many times.

An aggregate is one of several possible types. These aggregate types are differentiated by the type of ray/aggregate intersection algorithm (often termed an acceleration technique or efficiency scheme) that is used.

Aggregates are defined by giving a keyword that defines the type of the aggregate, followed by a series of object instantiations and surface definitions, and terminated using the end keyword. If a defined object contains no instantiations, a warning message is printed.

The most basic type of aggregate, the list, performs intersection testing in the simplest possible way: Each object in the list is tested for intersection with the ray in turn, and the closest intersection is returned.

list . . . end
Create a List object containing those objects instantiated between the list/end pair.

The grid aggregate divides the region of space it occupies into a number of discrete box-shaped voxels. Each of these voxels contains a list of the objects that intersect the voxel. This discretization makes it possible to restrict the objects tested for intersection to those that are likely to hit the ray, and to test the objects in nearly "closest- first" order.

grid xvox yvox zvox . . . end
Create a Grid objects composed of xvox by yvox by zvox voxels containing those objects instantiated between the grid/end pair. It is usually only worthwhile to "engrid" rather large, complex collections of objects. Grids also use a great deal more memory than List objects.


5.4 Constructive Solid Geometry

Constructive Solid Geometry is the process of building solid objects from other solids. The three CSG operators are Union, Intersection, and Difference. Each operator acts upon two objects and produces a single object result. By combining multiple levels of CSG operators, complex objects can be produced from simple primitives.

The union of two objects results in an object that encloses the space occupied by the two given objects. Intersection results in an object that encloses the space where the two given objects overlap. Difference is an order dependent operator; it results in the first given object minus the space where the second intersected the first.

5.4.1 CSG in Rayshade

CSG in rayshade will generally operate properly when applied to conjunction with on boxes, spheres, tori, and blobs. These primitives are by nature consistent, as they all enclose a portion of space (no hole from the "inside" to the "outside"), have surface normals which point outward (they are not "inside-out"), and do not have any extraneous surfaces.

CSG objects may also be constructed from aggregate objects. These aggregates contain whatever is listed inside, and may therefore be inconsistent. For example, an object which contains a single triangle will not produce correct results in CSG models, because the triangle does not enclose space. However, a collection of four triangles which form a pyramid does enclose space, and if the triangle normals are oriented correctly, the CSG operators should work correctly on the pyramid.

CSG objects are specified by surrounding the objects upon which to operate, as well as any associated surface-binding commands, by the operator verb on one side and the end keyword on the other:

union <Object> <Object> end
Specify a new object defined as the union of the given objects.

difference <Object> <Object> end
Specify a new object defined as the difference of the given objects.

intersect <Object> <Object> end
Specify a new object defined as the intersection of the given objects.

Note that the current implementation does not support more that two objects in a CSG list (but it is planned for a future version).

5.4.2 Potential CSG Problems

A consistent CSG model is one which is made up of solid objects with no dangling surfaces. In rayshade, it is quite easy to construct inconsistent models, which will usually appear incorrect in the final images. In rayshade, CSG is implemented by maintaining the tree structure of the CSG operations. This tree is traversed, and the operators therein applied, on a per-ray basis. It is therefore difficult to verify the consistency of the model "on the fly."

One class of CSG problems occur when surfaces of objects being operated upon coincide. For example, when subtracting a box from another box to make a square cup, the result will be wrong if the tops of the two boxes coincide. To correct this, the inner box should be made slightly taller than the outer box. A related problem that must be avoided occurs when two coincident surfaces are assigned different surface properties.

It may seem that the union operator is unnecessary, since listing two objects together in an aggregate results in an image that appears to be the same. While the result of such a short-cut may appear the same on the exterior, the interior of the resulting object will contain extraneous surfaces. The following examples show this quite clearly.

difference
    box -2 0 -3 2 3 3
    union           /* change to list;  note bad internal surfaces */
        sphere 2 1 0 0
        sphere 2 -1 0 0
    end
end rotate 1 0 0 -40 rotate 0 0 1 50
The visual evidence of an inconsistent CSG object varies depending upon the operator being used. When subtracting a consistent object from and inconsistent one, the resulting object will appear to be the union of the two objects, but the shading will be incorrect. It will appear to be inside-out in places, while correct in other places. The inside-out sections indicate the areas where the problems occur. Such problems are often caused by polygons with incorrectly specified normals, or by surfaces that exactly coincide (which appear as partial "Swiss-cheese" objects).

The following example illustrates an attempt to subtract a sphere from a pyramid defined using an incorrectly facing triangle. Note that the resulting image obviously points to which triangle is reversed.

name pyramid list
    triangle 1 0 0 0 1 0 0 0 1
    triangle 1 0 0 0 0 0 0 1 0
    triangle 0 1 0 0 0 0 0 0 1
    triangle 0 0 1 1 0 0 0 0 0       /* wrong order */
end

difference
    object pyramid scale 3 3 3 rotate 0 0 1 45
        rotate 1 0 0 -30 translate 0 -3.5 0
    sphere 2.4 0 0 0
end
By default, cylinders and cones do not have end caps, and thus are not consistent primitives. One must usually add endcaps by listing the cylinder or cone with (correctly-oriented) endcap discs in an aggregate.


5.5 Named Objects

A may be associated with any primitive, aggregate, or CSG object through the use of the name keyword:

name objname <Instance>
Associate objname with the given object. The specified object is not actually instantiated; it is only stored under the given name.

An object thus named may then be instantiated (with possible additional transforming and texturing) via the object keyword:

object objname [<Transformations>] [<Textures>]
Instantiate a copy of the object associated with objname. If given, the transformations and textures are composed with any already associated with the object being instantiated.


Go to the next section
Surfaces amd Atmospheric Effects
Go to the Contents