Source Files Header Files Resource Files Input Files Text Files DevStudio Files Program Files

7001 Project 2 by Mark Carlson for Jarek Rossignac *** A Better Looking Version of this paper in Rich Text Format and in Word97 format***

Forcing Obtuse Recursion on Graphics Expressed Through Iterative Terminology

Mark Carlson

 

 

Figure 1: Picture produced by file in Table 1.

Abstract

Many real life objects contain repeating patterns—a tree has a trunk with branches, those branches have smaller branches, and so on until you reach the leaves. It would be productive to create a language description where one could describe a leaf, and then build a branch with leaves. Then, using that branch description, one could build a tree with trunk as a big branch, and decide how bushy and thick the tree grew by defining a level of recursion on the branches. Building on this idea, one would build rows of trees by performing an iterative translation and copy on the trees (say along the x-axis), and one could build a grove by performing an iterative translation and copy on the rows along the y-axis. It these objects were saved and given names, one could re-use them to build other objects.

Introduction

The purpose of this project was to find an elegant format with witch to represent the objects, described above, and the operations preformed on them. This paper will describe the syntax and semantic restrictions of the rudimentary input language I devised. Following that I will give instructions on how to run the program that uses the input to display the objects. I will give a brief account of my coding style and format. The research I have conducted is barley a first step in finding an easily usable input format, so I sill give suggestions for further study.

Input Format

I will explain the input format by presenting an example. Table 1 is the input file given to produce the output shown in figure 1. The bold numbers on the left are the line numbers and are used for reference; they are not part of the input.

The first line of the input [1] is the number of objects contained in the file. Following that are all the object definitions. There are two objects defined in this file; lines 3 through 9 and 11 through 13 are both object definitions. I use the convention of a blank line [2][10] before the start of each object to make the file easier to read; however, the blank is not strictly necessary.

The first line of each object [3][11] contains the object name—actually an integer label for the object—and the number of operations the object is described with. Once an object is named, other objects can use it within their own descriptions. Object 200 (start at line 11) uses object 100 (the first object). An object can only use objects that have been defined before it; however, it can use itself recursively.

1

2

2

 

3

100 3

4

P 1 1

5

1 r[0.0 0.0 0.0 0.0] t[0.0 0.0 0.0] s[1.0 1.0 1.0]

6

R 5 1

7

2 r[30.0 0.0 0.5 1.0] t[0.0 20.0 0.0] s[0.85 0.85 0.85]

8

R 3 1

9

1 r[-30.0 0.0 0.7 1.0] t[0.0 40.0 0.0] s[0.85 0.85 0.85]

10

 

11

200 1

12

D 100 1

13

3 r[0.0 0.0 0.0 0.0] t[100.0 0.0 0.0] s[1.0 1.0 1.0]

Table 1: Example input file that produced fig 1.

Note that object 100 has 3 operations [3]. Each operation has 2 or more lines. The first line of an operation has three parts. The first part is the type and the last part is the number of transforms preformed on that type. The middle part can be different depending on the type.

There are three types.

Primitive Types—these are the basic building blocks of the program, they are defined within the function and can be used without defining them—which are represented by the letter p [4]. When using a primitive type, the second part is the number of the type. The primitive types are defined in the OBJ_Init function.

Defined Types—objects that the user has previously created—which are represented by the letter d [12]. The second variable of a defined type is the name of the previously defined type.

Recursive Types—operations that use themselves in the definition—which are represented by the letter r [8][6]. These types must come after all other types. There can be as many recursive types as you like, just make sure they are all at the end of the object definition. The second variable in the recursive case is the depth of recursion.

Each transform in the operation takes up one line. All transforms have the same format. First is the number of times to repeat the transform; this is followed by variables for rotation (r[angle x y z]), translation (t[x y z]), scale (s[x y z]). The redundancy of this is addressed in the improving input section.

In figure 1, the red tree is object 100, and the green trees are objects 200.

Ignoring the second object for now, and changing the first number in line 7 to 1, we can observe how the recursion works by changing the recursive depth in lines 6 and 8. Refer to figure 2 during this example.

The recursive types have to be at the end because of the entity that they recur on. They recur only on the object as it is defined up to the first recursive operation. For example, if the recursive depth is 0 (fig 2(a)), then each recursive operation is treated as the object so far transformed as the user defines. To understand the pattern, look how much changing the recursive depth on the left branch from 2 to 5 increases the complexity of the picture (Fig 2(b)(c)).

The name of the input file is objects.ini. It is a ASCII text document.

Running the Program

I wrote the program in Visual C++ for the Win32 environment for two major reasons. There was no learning curve because I am proficient in language on Win32, and the necessary development environment is already set up at GaTech and my home.

The keyboard commands are listed in table 2. Exiting the program can be done by pressing escape or by clicking the ‘x’ box when in windowed mode.

Key

Command

0 – 6

Change screen resolution. 0 = 320 X 240, 6 = 1600 X 1200.

Alt + Enter

Toggle between windowed and full-screen mode.

Left Arrow

Toggle X-axis rotation.

Down Arrow

Toggle Y-axis rotation.

Right Arrow

Toggle Z-axis rotation.

Table 2: Keyboard commands.

Before the program is run, the ASCII (table 1 has an example of one valid file) text file objects.ini must be in the same directory.

Figure 2: (a) both the right and left branch have 0 recursive depth, i.e. RD[0, 0]. The other depths are as follows: (b) RD[1, 0], (c) RD[5, 0], (d) RD[0, 1], (e) RD[0, 2], and (f) RD[5, 2].

 

Code Style

This section is here to help you navigate my code easier. There are a few simple things that you should know when reading the code.

The source is broken into five packages, each with a three-letter abbreviation: file [FIL], objects [OBJ], system [SYS], video [VID], and windows specific [WIN]. Each module has a source and a header file that is prefixed with its abbreviation. Within each of these packages are private and public functions. The private functions are declared in the source file of the package and can not be used by other packages. Public functions are declared in the header file and are prefixed with the appropriate abbreviation. There are also public variables, these are declared in the source file, but an extern reference is used in the header function to give the other modules access to the variables.

For example, the objects are in the obj_main.cpp and obj_main.h files. One function in this module is OBJ_Init. The public (package global) variable obj_numberOfObjects stores the number of objects from the input file. The file package manipulates files and assigns obj_numberOfObjects a value, that is why it is public.

Keep these conventions in mind when you read the source; it will make reading it easier. On more thing to take not of is the cls prefix. This is the class prefix. Only one class is defined in the source: cls_vertex. Vertex objects are used to simplify many operations on three-dimensional points and vectors, depending on what you consider the Vertex object to be at the time you use it. Vertex objects have an x, y, and z. They can do cross-product, distance from one another, and many other useful operations.

Figure 3: A red tree, a green row, and a blue forest (rotated about the x-axis).

Improving Input

If we add these three lines to the input in table 1 we get figure 3 for output. The lines are in table 3.

14

300 1

15

d 200 1

16

5 r[30.0 0.0 1.0 0.0] t[0.0 0.0 0.0] s[0.75 0.75 0.75]

Table 3: Lines to add to table 1.

Eventually, I would like to have an input format that did not contain so much redundancy in the transforms, and was not forced into a single column format. I would also like to remove the restriction of only using objects that are previously defined. In order to accomplish this, a parser would have to be built. It would not be too hard with Lex/Yacc but it looked like a nightmare to me when I thought of implementing with Visual C++.