CALIFORNIA STATE UNIVERSITY, NORTHRIDGE
PRISM: A COMPUTER ANIMATION SYSTEM
A project submitted in partial satisfaction of the
requirements for the degree of Master of Science in
Computer Science
by
Fred Mikami
\
May 1987
The Project of Fred Mikami is approved
G. Michael Barnes (Chair)
I
California State University, Northridge
ii
ACKNOWLEDGMENTS
I would like to thank California Computing
Resources, Inc.
system.
for the generous use of their computer
Also I like to thank Mel Epstein and David
Salomon for being on my committee.
A special thanks
goes to Mike Barnes, for not only being my project
chairperson, but also for putting up with me for the
last six years.
; i;
TABLE OF CONTENTS
Acknowledgments
.................
iii
.
List of Figures . • • • • • • • • • • • • • • • • • v 1
Abstract
...................
• • vii
Chapter
1.
Introduction •
........
• 1
1.1 Academic Objectives
1. 2 Animation
• 2
.........
•
•
• 2
1.3 Computer Animation • • •
2.
Background • .
2.1 Basic Terms
3.
• 3
............
..........
• •
•
• 7
• • 7
2.2 Three Phases for 3D Animation
. 8
2.3 Basic 3D Animation Concepts .
. 11
System Overview • • • • •
. 13
. . 13
3.1 Hardware Overview ••
3.2 Software overview .
.
.
• 15
3.3 Animation Production Steps
4.
Data File of Prism
18
•
........
4.1 Script File • .
•
•
20
. 20
4.2 Object Definition File
. 25
4.3 Image Descripti?n File
• 27
iv
5.
.
One . . . . . .
Two
....
Three . . . . .
Video Tape Demonstration
5.1 Sequence
5.2 Sequence
5.3 Sequence
6.
7.
Programs of Prism .
..
. .
..
..
...
. 30
. . . . 31
. . . . . . 32
. . . . . . 34
. .
•
•
• 37
6.1 Image Description Generator .
•
• 37
6.2 Image Generator .
.
• 43
•
• 46
•
• 47
•
• 49
•
• 49
• • .
• 52
Portability of Prism
•
•
•
•
7.1 Device Specific Jacket Routines
8.
Conclusions .
.
.
8.1 Analysis of Prism .
8.2 Enhancements
•
8.4 Final Comments
Bibliography
• 54
...............
•
• 56
•
•
• 58
•
•
• 60
Appendices
A.
IDG
and IG Error Messages
B.
IDG and IG Command Syntax .
c.
Directory Layout
D.
IDG Routines
E.
IG Routines
F.
Support Routines .
. 174
G.
Header Files .
. 181
H.
IDF Directives .
I.
Current Object Database
•
. 62
•
.
.
.
. .
v
•
63
. 104
. 187
. 189
LIST OF FIGURES
1.1 Computer Animation Hierarchy
•.••....• 4
3.1 Hardware Configuration •
3.2 Software Configuration • .
4.1 Format of Object Definition File •
4.2 Format of Object •
4.3 Format of Polygon
. 16
•
• •
• 17
• 26
. • • 26
......
5.1 Sequence One Script
5.2 Sequence Two Script
5.3 Sequence Three Script
. . . . . . 26
.......
.........
....
33
33
36
6.1 Coefficient Matrix Calculation .
. . 41
8.1 Reflection Problem
. . 51
8.2 Enhanced Prism System
. . 55
vi
ABSTRACT
PRISM: A COMPUTER ANIMATION SYSTEM
by
Fred Mikami
Master of Science in Computer Science
This paper presents a report on the Prism animation
system.
Prism is a script-based system (Sturman[l5]},
that allows a user to specify the 3-dimensional motion
of an object with the use of a text file, known as a
script.
To generate the illusion of animation, Prism
uses the frame-by-frame technique as mentioned in
Magnenat[9].
This report describes in detail, the software
design and implementation of Prism.
Also discussed in
this report, is a description of the current script
commands, the hardware configuration used in running the
system, the device dependent routines, and portability
considerations.
Included as part of the report, is a
short video tape demonstration of some animation
generated by Prism.
vii
CHAPTER 1
Introduction
This report on the Prism Animation System contains .
an additional seven chapters:
background, system
overview, the files used in Prism, a video tape
demonstration, the programs of Prism, Prism's
portability and conclusions.
This chapter will state
the academic objectives of this project, introduce the
basic concepts of animation, and the
used in computer animation.
gen~ral
approaches
The background chapter will
discuss general concepts that are employed in
3-dimensional computer animation systems.
The system
overview chapter will discuss the system design and give
an overview of the major hardware and software
components of Prism.
Chapter 4 will discuss the purpose
and the syntax of the files associated with Prism.
Chapter 5 is a text supplement to the video tape
demonstration included with this report.
Chapter 6 will
examine the programs that make up the Prism system.
1
The
2
portability chapter will discuss the work necessary to
port Prism to another machine.
The comcluding chapter
will give an analysis of Prism.
1.1 Academic Objectives
The objective of this project was to experience,
first hand, the problems in designing and
3-dimensional animation system.
build~ng
a
Since Prism is an
initial prototype an animation system, errors in design
and implementation were considered to be part of the
learning experience and were not construed as a
measurement of success or failure.
1.2 Animation
Cqmputer animation can be defined as the use of
computer graphics to create the visual illusion of
motion*.
This illusion is caused by the same
physiological phenomenon that allows traditional
animation (e.g.
cartoons), and motion pictures to work.
This phenomenon, called persistence of vision, is caused
by the brain's inability to distinguish between discrete
images shown at a rate greater approximately 12 frames
per second (fps) .
When images are displayed at a rate
* Motion not only implies movement in a given direction
but,
it also refers to any sort of change an object may
go through in time. In the context of this report, the
word "transformation" is analogous to motion.
3
greater than this, the brain will attempt to "blend" the
individual images together to create an illusion of
animation.
When the image display rate falls below 12
fps, the brain is able to discern the different images,
and the illusion of animation breaks down.
1.3 Computer Animation
The two basic techniques in computer animation that
have been devised to meet the 12 fps requirement, are
real-time animation and frame-by-frame animation.
Figure 1.1 uses a hierarchical tree to further
categorize these two basic animation techniques.
1.3.1 Real-time Animation.
Real-time animation
systems produce images at a rate of typically at 30 or
60 frames a second.
These systems are used in
applications where immediate response to a user's input
is critical.
Within this category of systems, there is a wide
range in the amount of realism generated.
At the lower
end of the spectrum, the per-system cost is important.
In these systems (e.g.
video games} realism is
sacrificed to make high volume production of these
systems possible.
At the other end of the spectrum,
greater realism is
achiev~d
by using more sophisticated
hardware and software at the expense of incurring a
greater per-system cost (e.g.
flight simulators).
@
•
Figure 1.1 Animation Hierarchy
7~
Real
Time
Frame
by
Frame
Low
End
High
End
2-o·
Paint
System
30
Key
Frame
Script
Parameterized Key
Frame
.,..
5
1.3.2 Frame-by-Frame Animation.
The second method
of generating computer animation is to defer the viewing
of the animation sequence by recording it, one frame at
a time, onto a recording media such as video tape.
Later the tape is played back at the proper viewing rate
for animation.
This technique (frame-by-frame
animation) allows for the generation of more realistic
images at a lower cost because the actual image·
generation is no longer constrained by the 12 fps limit.
In this type of system, the user becomes an animator who
choreographs the motion of objects within hisjher
animated sequence.
There are basically two types of
frame-by-frame systems, 2-dimensional (2D) and
3-dimensional (3D).
20 systems allow the computer to
take over many of the mundane chores associated with
animation (e.g.
input and coloring of objects and the
recording of images onto video tape).
There are two
basic types of 2D system, paint and key-frame.
More
information on 2D animation systems can be found in
Magnenat[9].
3D animation systems are similar to 2D systems
except they incorporate motion in all three axial
directions :
x,y, and z.
These system open up a new
area of animation because of their ability to render
complex three dimensional images, which in traditional
animation is very difficult (Magnenat[9]).
Some 3D
6
systems have the ability to generate realistic images
with multiple light sources, surface properties,
textures, reflections, and refractions (Magnenat[9] and
sturman[l5)).
Of the two frame-by-frame systems mentioned above,
Prism falls into the latter class.
It is a
frame-by-frame 3-dimensional system that allows a user
to define the motion of objects by the use of a script.
Included as part of this report, is a short (one minute
and thirty seconds) video tape demonstration of some
animation generated with Prism.
At this point, the
reader may wish to view this tape.
(The actual scripts
used to generate these sequences, will be discussed in
chapter 5.)
CHAPTER 2
Background
In this chapter, a conceptual model of a 3D
animation system will be presented.
chapter will present:
Specifically this
a definition of some basic terms
used throughout this report, a description of the three
phases of 3D animation (object specification,
transformation specification, and object·rendering) and
a discussion of a few basic 3D animation concepts.
2.1 Basic Terms
Before going further in this report, it is useful
to define five terms that have a specific meaning with
regards to this paper, specifically:
sequence,
animation segment, image, view point and frame.
2.1.2 Sequence.
This term refers to all the
animation described in a script.
7
8
2.1.2 Segment.
A sequence is composed of a series
of smaller units call segments.
A segment is delimited
within a script by a starttime and an endtime command.
(The starttime and endtime commands are discussed later
in chapter 4) .
2.1.3 Image.
This refers to a single completely
rendered picture that is ready to be recorded.
2.1.4 View Point.
The location where the image is
being viewed from, essentially it's the view that the
current camera has from its current vantage point.
2.1.5 Frame.
This refers to a single recorded
image on the recording media.
2.2 Three Phases for 3D Animation
The purpose of any 3D animation system (also known
as Modeled Animation, Magnenat[9]), is to make the
creation of an animation sequence easier, by providing a
higher level control to the user than what is normally
found in a conventional programming language.
In
effect, an animation system should allow the user to
concentrate on generating the desired effect, instead of
worrying about the underlying details of generating
individual images.
A 3D animation system can be broken
down into three distinct phases.
First, an object
definition phase, where the items to be animated are
defined.
Second, a motion specification phase, where
9
object transformations are declared.
And the third
phase, object rendering, where the individual images are
actually generated and recorded.
2.2.1 Object Specification.
In this phase, a
3-dimensional model of each object to be displayed is
defined and placed into a database for use in the object
rendering phase.
The model can be specified in may ways
(Magnenat(9],Hearn[5]), polygon/vertex tables,
constructive solid geometry, or curved surfaces.
The
method used for object definition, will be determined by
the type of animation sequence being rendered and by the
sophistication of the available hardware and software
that can be used to define models.
Since Prism uses the
polygonjvertex approach for object specification, a more
detailed examination of this technique will be presented
later in this report.
2.2.2 Transformation Specification.
Transformation
specification, or motion specification, is the most
important phase of the computer animation process.
It's
in this phase that the actual specifications of how the
objects will move are defined.
The technique used by
Prism is a script-based approach.
motion specification, e.g.
{Other techniques of
key-frame, parameterized,
can also be found in sturman[l5].)
craig Reynolds defin.es a script-based animation
system as "a notation for animated graphics" [11].
In
10
this type of a system, the user defines the objects•
motions with the use of a script.
The script is then
read by a script-interpreter to determine the necessary
object transformations for the animation sequence.
In
effect, the development of a script is analogous to the
process of debugging a program.
The user would write a
script, run it through the interpreter, and then render
the images defined by the interpreter.
If the sequence
was incorrect, hejshe would go back and correct errors,
run it through the interpreter, render the
sequence, •.. etc.
The major advantage to a script-based
system is that it allows for fast prototyping of an
animation sequence.
A rough script of the principal
motions can be quickly written and tested.
A major disadvantage to script-based systems, is
the lack of direct user interaction with the system.
As
mentioned above, using a script-based system is much
like using a computer language compiler (e.g.
or C) to write programs.
FORTRAN
As with compilers,
script-based systems do not allow their users to see the
result of their work until the actual rendering of the
sequence is done.
This delay in feed-back, tends to
increase the time required to produce the desired
animation.
After both the object definitions and the
transformation specifications have been defined, the
@ '
11
final phase, object rendering, can begin.
2.2.3 Object Rendering.
The third phase involved
in 3-dimensional animation, is the rendering and
displaying of the object for recording.
It's in this
step that the visual production of the object
transformation takes place.
Some rendering features
that can be implemented include light reflection models,
refraction, shading, texture, transparency and
projection viewing.
Hearn[5] gives a good introduction
to these concepts.
2.3 Basic 3D Animation Concepts
In this section, the basic concepts of
transformation, viewing systems and time-step are
discussed.
2.3.1 Transformation Matrix.
In general, a
transformation of an articulated body can be described
with a 4x4 matrix.
With the use of this matrix an
object can be rotated, translated, scaled, and sheared.
This matrix is also used to calculate the projection of
a 3-dimensional object on to a 2-dimensional surface.
A
good explanation of the use of transformation matrices
is given by Hearn[5].
2.3.2 View Systems.
As discussed by Hearn[5],
there are two possible 3-dimensional viewing systems.
The first assumes that the z direction in coming out of
12
the surface and toward the viewer, this is known as a
right-handed system.
The second system assumes that the
z direction is pointing away from the viewer.
system is called a left-handed system.
This
The advantage of
a left handed system in computer animation is that
objects that appear to be moving away from the viewpoint
have increasing z values.
so for convenience sake, all
rotational angles are done with the left hand rule (i.e.
clock-wise rotation indicates increasing values).
2.3.3 Time-step.
To determine an object's position
on any given frame of an animation sequence, some sort
of time function must be used.
Typically, video
recorders record at a rate 30 frames per second.
Therefore, increment of time between frames (know as the
time-step) is usually l/30th of a second.
time-step is reduced (e.g.
If the
l/60th of a second), objects
in the sequence will tend to look like they are moving
in slow-motion.
If the time-step in made larger (e.g.
l/15th of a second) objects will tend to move as if they
are in a "fast-play" mode at play-back time.
CHAPTER 3
System overview
The fundamental objective of this project was to
build a 3-dimensional script based animation system.
The result of this effort, was the development of Prism.
This chapter gives an overview of both the hardware and
software components of Prism, and the steps required to
create an animation sequence.
3.1 Hardware Overview
The actual generation of a computer animation
sequence requires the interaction of video and computer
hardware.
In the case of the Prism system, the
following seven hardware components were used to
generate and record images.
3.1.1 Host computer.
In this project, a Celerity
C1200 running BSD 4.2 UNIX was used.
13
The Celerity was
14
used to control the input into the frame buffer and to
command the video tape controller.
3.1.2 Frame buffer.
A frame buffer is a device
that holds and generates an raster image from the data
in its local memory (Foley[4]).
In it the image is
converted into red, green and blue (RGB) signals to be
used by the color encoder.
In this implementation, a
Raster Technologies One/80 frame buffer was used
(Raster[10]).
3.1.3 Video tape controller (VTC).
The major
function of the VTC is to place images that are in the
frame buffer onto video tape in the correct location.
In the case of this project, a Lyon-Lamb VAS-IV was used
(Lyon[16]).
3.1.4 Color encoder.
A color encoder is a device
that converts the separate RGB signals into a single
composite video signal that can be recorded onto video
tape.
A Lenco PCE-466 color encoder was used on this
project (Lenco[8]).
3.1.5 Video tape recorder (VTR).
This device is
used to record images onto video tape, and it's
controlled by the VTC.
This project used a Sony
V0-5850, 3/4 inch U-matic VTR (Sony[14]).
3.1.6 Sync generator.
This device is the master
sync source, all video timing signals_are referenced
from this source.
A Lenco CSL-7100 was used on this
15
project {Lenco[7]).
3.1.7 NTSC color monitor.
This is standard NTSC
color monitor that displayed the images being generated
by the frame buffer.
In this project a Sony PVM-19 was
used {Sony[l3]).
Figure 3.1 shows the relationships between these
different devices.
3.2 Software overview
Prism can be viewed as a set of five interrelated
software components:
a script, an image definition
generator, an image definition file, an image generator
and an object definition file.
The overall design of
the Prism system is shown in figure 3.2.
The function
each part is described as the following:
3.2.1 Script.
The script is a file that contains
run-time information about the animation sequence to be
generated.
Information in this file would include
object creation, deletion, and transformation commands.
Also definitions for start/end times and camera
information would be specified in this file.
3.2.2 Image Definition Generator {IDG).
The Image
Definition Generator uses the script to generate the
positions of each object on a frame-by-frame basis.
This information is written out to the Image Definition
16
Figure 3.1 Hardware Configuration
Data Line from host
c
...
1200
Frame
Buffer
....
Sync
Sync
Generator
RGB Lines
Sync
Color
Encoder
,,
Video
Tape
Recorder
-
Composite Video
Video
Animation
Controller
Composite
Video
Composite Vide·o
Color
Monitor
Figure 3.2 Software Configuration
IDG
IG
Display /Record .
Device
......,
-J
18
File, where it is latter used by the Image Generator.
3.2.3 Image Definition File (IDF}.
The IDF
contains information required by the Image Generator to
generate a complete animation sequence on a
frame-by-frame basis.
Information in this file would
include transformation data for objects, and image
recording directives.
3.2.4 Image Generator (IG).
This module is
responsible for the actual transformation of objects,
hidden surface removal and any other rendering features
(e.g.
texture or shadows} that are relevant.
Also the
IG is responsible for recording the images once they are
generated.
The IG uses the Object Definition File to
determine the actual shape of the object to be created.
3.2.5 Object Definition File (ODF}.
This file
contains information on the actual objects to be
rendered.
Information in this file would include the
shape, color, size, and other relevant data about each
object.
3.3 Animation Production Steps
For a user to produce an animation sequence with
Prism, a series of steps are performed.
First, the user
defines shapes to be displayed in the animation sequence
in the ODF.
Next, the user creates a script file with
information about the motion paths, and rotations for
19
each object.
Third, the script is used as input to the
IDG for the creation of a frame-by-frame description
file, the IDF.
Finally, the IDF is used as input into
the image generator, which would determine the placement
of objects within an image and then record the image
onto video tape on a frame-by-frame basis.
CHAPTER 4
Data Files of Prism
As mentioned in Chapter 3, Prism can be viewed as a
set of related system components that interact with each
other.
In this chapter, the three major files of Prism
are discussed.
with it:
Prism has three data files associated
the script, the Image Definition File, and the
Object Definition File.
The Script file is written by
the animator to specify the transformations that will
occur in the animation sequence.
The Image Description
file is created by the Image Definition Generator and is
used as input for the Image Generator.
The Object
Definition file contains the definition of the objects
to be animated.
4.1 Script File
To specify the motio"ns of objects within a segment,
the animator writes a script file expressing the
20
21
objects' transformations in the syntax of the Image
Definition Generator {IDG).
four basic categories :
Commands for IDG fall into
timing, creationjdeletion,
motion/rotation and extras.
The timing commands control
the time associated parameters of an animation segment.
The creation/deletion commands allows the user to
declare instances of objects (and cameras) and to turn
off the visibility of objects.
Motion/rotation commands
allow the user to transform objects and cameras within a
segment.
Commands that fall into the "extras" category
include world dimension, set attribute and value array
declarations.
4.1.1 Timing Commands.
related commands in Prism:
timestep.
There are three time
starttime, endtime and
The starttime command tells the IDG at what
time to start the animation segment.
The endtime
command specifies the ending time of a segment, and the
timestep command specifies time elapsed time between
images in a segment.
(Typically, timestep is set to
l/30th of a second for video animation.) These commands
have the format of:
command string value.
Where "command" is either starttime, endtime or
timestep.
"String" is a place holder with no special
meaning.
"Value" is value associated with the command.
22
4.1.2 Creation/Deletion Commands.
The object
creation/deletion commands are creainst, and delinst.
The creainst commands creates an instance of an object.
The syntax of this command is:
creainst name type.
Where "name" is the reference name to be associated
within this object, and "type" is the type of object as
defined in the Object Definition File.
The delinst command "turns off" the displaying of
the instance of the object "name".
Its syntax is:
delinst name.
The creacam command allows the user to create an
object of type camera.
The camera is, in effect, a view
point from which the animation sequence is viewed.
The
syntax of this command is:
creacam name.
Where "name" is a name associated with the camera.
4.1.3 Motion/Rotation Commands.
The
motionjrotation commands allow a user to specify the
rate of motion in a given direction.
The syntax of the
move an instance command is:
movobj name direct interp time value.
23
Where "name" is the name of the instance to move,
"direct" is the direction to move the object (i.e.
x, y
or z), "interp" is the interpolation method to be used
(either linear or spline).
"Time" is the name of the
time-line (the independent variable), and "value" is the
name of the value-line {the dependent variable).
Currently only linear and cubic spline (Burden[3])
interpolations are supported.
The rotobj command has the same format as the
movobj command except that "direct" refers to the axis
of rotation.
The camera commands to move and rotate the current
camera are movcam and rotcam.
These commands have the
same format as movobj and rotobj commands (e.g.
movcam
name interp time value).
4.1.4 Extras Commands.
The last set of commands,
are commands that do not neatly fall into any of the
above categories.
These command are world, setattr,
timeline and valline.
The world command sets up the "x" and "y" dimension
of the image screen.
Its syntax is:
world name xmin ymin xmax ymax.
Where "xmin", "ymin", "xmax" and "ymax" are real numbers
that specify the minimum and maximum x and y values of
the screen.
"Name" is just a place holder.
24
The setattr command allows the user to set certain
attributes of an object to a fixed value for a given
segment.
These attributes are the x, y, or z's
position, rotation or size of the object on the screen.
The syntax of this command is:
setattr name attrib value.
The "name" parameter refers to the name of the instance
to be modified.
instance to set.
"Attrib" refers to attribute of the
Possible values for this parameter are
xscale, yscale and zscale for scaling along x, y or z
axis; xtran, ytran and ztran for an offset from the
center of the screen; or xrot, yrot and zrot for a
rotation around the object's x, y, or z axis.
is the amount to change the object.
"Value"
For example, to set
the x location of "cube1" to a fixed position of 10.0,
the commands used would be:
setattr cube1 xtran 10.0
The timeline and valine command declares the
independent (i.e.
time-line) and dependent (i.e.
value-line) values to be used by an object's (or a
camera's), interpolation function.
An example of the
use of these commands is shown in the example in Chapter
2.
The syntax of a timeline command is:
timeline name n value1 value2 .•. value-n.
25
Where name is the "name" to be associated with the time
line, "n" is the number of elements in the time line and
"valuel" thru "value-n" are the values associated with
the time line.
The same syntax is used for valline
except the command timeline is replaced with valline.
4.2 Object Definition File (ODF)
The ODF contains information on objects that are
avaliable to be displayed.
In this version of Prism,
only geometric objects that can be defined in terms of
polygons are allowed.
To define an object, the user determines the
location of the vertices with respect to the center of
the object and then connects the vertices together to
form polygons.
The overall format of the ODF is shown
in figure 4.1.
Individual objects in ODF are defined with the use
of vertex and polygon tables.
format of a single object.
Figure 4.2 shows the
In figure 4.2, "refer" is
the reference number associated with the type of object
defined.
(This number is used to relate the definition
of an object to its instance in the Image Generator
program) .
"ObjName" is t.he name of the object.
is the number of polygons in this object.
"Npoly"
"Nvert" is
the number of vertices in the vertex table of this
26
Figure 4.1 Format of Object Definition File
Num-of-Obj
Object 1
Object 2
.
Object Num-of-Obj
Figure 4.2 Format of Object
index ObjName
Npoly Nvert
vertext 1
vertext 2
vertext Nvert
polygon 1
polygon 2
polygon Npoly
Figure 4.3 Format of a Polygon
Nvert Color
index-1 index-2
..... index-Nvert
27
object.
Vertex 1 .••
vertex-nvert are the elements
that make up the vertex table and "polygon-1 11 thru
"polygon-npoly" make up the polygon table.
A single
vertex is defined as a triplet of real numbers that
represent the x,y,z location of the vertex, relative to
the center of the object.
A single polygon of an object consists of two
records in the ODF file.
The first record has two
fields, the first field is the number of vertices in the
polygon and the second field is an index into the frame
buffer's color lookup table to determine the color of
the polygon.
The second record of the polygon consist
of a list of indexes into the vertex table of the
object.
Since a polygon has an inside and outside
surface with respect to an object, the convention of
connecting the vertices together in a clockwise
direction to indicate the outer surface is used.
Figure
4.3 shows the format of a polygon entry.
· Under the current implementation, there is no
automated way to define new objects for the ODF.
As it
stands now, the user must manually determine the
vertices and polygons of an object and then enter the
data into the ODF with a text editor.
4.3 Image Description Fiie (IDF)
The IDF is the counter part to the script file for
28
the Image Generator.
This file contains the information
necessary to create the individual images of an
animation sequence.
The IDF is generated by the Image
Definition Generator.
The format of an IDF is:
directive Valuel ••• ValueN.
Where "directive" is the command to execute with
parameters "Valuel" thru "ValueN".
There are three basic types of IDF commands:
instance creation, matrix transformation and
render/display.
The instance creation command is the
Image Generator's counterpart to the creainst command of
the IDG (i.e.
an object).
declares the creation of an instance of
The matrix transformation commands inform
the Image Generator of what transformation to perform on
a given instance of an object (the IDG counterpart to
this command are the movobj and rotobj commands).
render/display command (i.e.
The
the DISPLAY command)
informs the Image Generator that all the transformations
required for this image are complete and actual image
creation can begin.
Appendix H contains a description
of each of IDF commands.
Note, even though the IDF is a text file, no
changes should be made directly to it: any image
specifications should be done through the script file or
29
by modifications to the IDG.
This recommendation is
suggested because direct modifications to the IDG cannot
be traced back to the either the script file or the IDG.
When a user makes direct modifications to the IDF, they
lose the ability to account for actions described within
it.
' .
CHAPTER 5
Video Tape Demonstration
Since the script commands have been defined, it is
now possible to examine the effect of combining the
script commands to form an animation sequence.
Included
as part of this report, is a video tape of three
animation sequences that were created with Prism*.
The
rest of this chapter will give a written explanation of
each sequence, while the video tape gives a visual
demonstration.
In the first sequence, Sequence One, a
cube is animated by rotating it in the lower right
section of the screen.
The second sequence shows the
animation of three objects moving around the screen.
Sequence Three shows the animation of four prisms moving
around in a ferris wheel configuration.
The sequences on the video tape are separated by an
* If the reader does not currently have access to the
video tape, and a video tape player, they may wish to
skip this chapter.
30
31
intentional ten seconds of blank tape.
This was done to
allow the reader to pause or stop the video tape player
between sequences.
5.1 Sequence One
The first sequence on the video tape, displays the
animation of a cube rotating about its center in the
lower right quadrant of the screen.
sequence is shown in figure 5.1.
The script for this
Line 1 of the script,
sets the world coordinates for the lower left corner of
the screen to x=-20.0 and y=-16.0, the upper corner
x=20.0 and y=16.0.
The second line would create a
camera call "carol" It would then create an instance of
object "cube" called "cubel" (line 3).
The next three
commands (lines 4, 5 and 6) set "cubel" to be at screen
position (-10,10.,10.) when the object is displayed.
The starttimejendtime segment would record the cube in a
stationary position for three seconds (lines 7 and 8).
The timeline command sets up a timeline named "timel" of
six elements starting from 3.0 seconds to 10.0 seconds
(line 9).
The valline command (line 10) sets up a
value-line of six elements with values ranging from
to 2520.0.
o.o
The second starttime command (line 11)
signals the beginning of a new segment.
The rotobj
command (line 12) specifies the action (object
rotation), the object (cubel), the axis to rotate around
32
(y), the type of interpolation to use (linear) with the
independent variable (time1) and the dependent variable
(rot1).
The endtime command specifies the ending time
of this segment at 10.0 seconds (line 13).
5.2 Sequence Two
The second sequence on the tape, shows a more
complex scene using three different objects.
The
sequence begins with a cube in the upper-middle section
of the screen and a hex-shaped object in the lower
section of the screen.
righ~
After three seconds, three
different events occur simultaneously.
First, the cube
starts moving down and across the screen and also toward
the viewer.
Second, the hex-shaped object starts
spinning about itself.
And third, a spinning pyramid
rises Up from "below" the screen.
For the remainder of
the sequence, the cube bounces toward the viewer, the
pyramid goes up and then comes back down, and the
hex-shaped object continues to spin in place.
The
script for this sequence is shown in figure 5.2.
The first two lines of the script, set the screen
coordinates and creates a camera.
The
ne~t
three
commands {lines 3, 4, and 5) create an instance of a
hex, a pyramid and a cube.
Commands 6 thru 13, place
the objects in various areas of the screen.
(An
interesting point is that object "pyrl" begins the
33
Figure 5.1 Sequence One Script
l.
2.
3.
4.
5.
6.
7.
world show -20. -16. 20. 16.
creacam caml
creainst cubel cube
setattr cubel ztran 20.
setattr cubel xtran 10.
setattr cubel ytran -10.
starttime show o.
end time
show 3.
timeline timel a 3.
4.
5.
6.
7.
a.
9.
10.
val line rotl a o. 360. 720. lOBO. 1440. 1800. 2160'. 2520.
starttime show 3.
rotobj cubel y linear timel rotl
end time
show 10.
a.
9.
10.
ll.
12.
13.
Figure 5.2 Sequence Two Script
1.
2.
3.
4.
5.
6.
7.
a.
9.
10.
11.
12.
13.
14.
15.
16.
17.
lB.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
world show -20. -16. 20. 16.
creacam caml
creainst hex2 hex
creainst pyrl pyramid
creainst cubel cube
setattr pyrl ztran 20.
setattr pyrl ytran -17.
setattr hex2 ztran 20.
setattr hex2 xtran 10.
setattr hex2 ytran -10.
setattr cubel ztran so.
setattr cubel xtran -20
setattr cubel ytran 10.
starttime show o.
endtime
show 3.
17.
timeline timel a
3.
5.
7.
9.
ll.
13.
15.
valline rotl a
o. 360. 720. lOBO. 1440. 1800. 2160. 2520.
valline rot2 a
o. -360. -720. -1080. -1440, -1800. -2160. -2520.
a.
valline dirl 8 -17. -a.
o.
17.
a.
o.
-17.
valline dir2 a -20. -10.
-5.
o.
3.
5.
12.
20.
timeline time2 3
3.
10.
17.
valline dir3 3 10. -10.
10.
valline dir4 3 50. 20.
15.
setattr pyrl
ytran o.
setattr cubel ztran o.
setattr cubel xtran o.
setattr cubel ytran o.
starttime show 3.
rotobj hex2 y linear timel rotl
rotobj hex2 x linear timel rot1
rotobj pyrl y linear timel rot2
movobj pyrl y spline time1 dirl
movobj cubel z linear time2 dir4
movobj cubel x spline timel dir2
movobj cubel y linear time2 dir3
rotobj cubel x linear timel rot2
endtime
show 17.
34
sequence off screen.) Commands 14 and 15 begin a segment
that records the objects in their current stationary
positions for three seconds.
Commands 16 thru 23
declare some time lines and value lines that will be
used in the next segment of the sequence.
Because of
the way Prism determines an object's location on the
screen, the next four commands (24 thru 27) are required
to reset the cube and pyramid locations such that the
interpolation functions can position the objects
correctly.
The starttime command at line 28, defines
the beginning of a new segment.
Commands 29 thru 36
specify the motions or rotations the object will perform
in this segment.
The endtime command terminates the
segment at 17.0 seconds.
Since the start time was set
to three seconds the actual running time of this segment
is only fourteen seconds.
5.3 Sequence Three
In the last sequence, four prisms are displayed
initially in a "diamond" pattern.
seconds they are stationary.
For the first three
After the third second
they will start moving in a circle in a "ferris wheel"
manner.
When this motion starts, the prisms will also
start rotating about their y-axes'.
After eight
seconds, the camera is panned from right to left, for
the next sixteen seconds.
Figure 5.3 shows the script
' '
35
used to produce this sequence.
The first two lines are the same as the previous
two scripts, they set the world dimension and create a
camera.
Lines 3 thru 6 create the prisms, and lines 7
thru 14 set their attributes for the upcoming segment.
Lines 15 and 16 declare a segment displaying the prisms.
Lines 21 thru 29 declare time lines and value lines for
the forthcoming segments.
Lines 30 thru 43 declare an
eight second segment in which the ferris wheel motion
starts.
In the next segment, lines 44 thru 46, the
ferris wheel motion continues but the camera is now
panned from right to left, this gives the illusion of
the object moving from left to right in the segment.
0 .
36
Figure 5.3 Sequence Three Script
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
ll.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
world show -20. -16. 20. 16.
creacam caml
creainst prism1 prism
creainst prism2 prism
creainst prism3 prism
creainst prism4 prism
setattr prism1 ztran 30.
setattr prisml ytran 12.
setattr prism2 ztran 30.
setattr prism2 xtran -12.
setattr prism3 ztran 30.
setattr prism3 ytran -12.
setattr prism4 ztran 30.
setattr prism4 xtran 12.
starttime show o.
show 3.
endtime
setattr prism1 ytran o.
setattr prism2 xtran o.
setattr prism3 ytran o.
setattr prism4 xtran o.
l.
timeline timel 6 o.
2.
timeline time2 9 o.
2.
l.
360.
720.
val line vall 6 o.
valline val2
9 o. -8.485 -12.
8.485 o.
valline val3
9 12.
valline val4
9 -12. -8.485 o.
8,485 12.
valline val5
9 o.
4.
timeline ti:::e3 5 o.
2.
val line val7 5 o. 45.
o.
starttime show o.
rotobj prisml y linear timel vall
rotobj pris~2 y linear timel vall
rotobj pris~3 y linear time1 vall
rotobj prism4 y linear timel vall
movobj prist:l x spline time2 val2
movobj pris~l y &pline time2 val3
movobj prism2 x spline time2 val4
movobj prism2 y spline time2 val2
movobj prism3 x spline time2 val5
movobj prism3 y spline time2 val4
movobj prism4 x spline time2 val3
movobj pris~4 y spline time2 val5
endtime show B.
starttime shew o.
rotcam caml
y linear time3 val7
sho;..r 8.
end time
4.
5.
6.
4. 5.
1080. 1440. 1800.
-8.485
o. 8.485 12.
-8.486 -12. -8.485
0.
8.486 12. 8.485
o.
8.485 o. -8.485 -12.
6.
8.
-45
0.
)
.
).
7.
8.
8.485 o.
8.485 12.
-8.485 -12.
-8.485 0.
CHAPTER 6
Programs of Prism
Once the object definition and input script files
have been written, the actual generation of the
animation sequence can begin.
To generate a sequence,
Prism uses two individual programs.
The first one, the
Image Description Generator, reads the script and
creates the Image Description File.
The second program,
the Image Generator, uses the output from the Image
Description Generator to create the actual images for
recording.
6.1 Image Description Generator (IDG).
The IDG can be thought of as a single program that
has two functional modules within it.
The first module,
an interpreter known as the script-reader, creates and
modifies IDG data structures based on the information in
37
38
the script.
The second module, the image-describer,
generates the Image Description File based on the data
structures set up by the script-reader.
The IDG processes the script on a
segment-by-segment basis.
The script-reader reads and
interprets the directives in the script file, until it
sees an endtime command.
When an endtime command is
encountered, control is passed to the image-describer.
The function of the image-describer is to calculate the
transformations of the individual objects on a
frame-by-frame basis and then write this data out to the
IDF.
This sequence of interpret/calculate continues
until the last segment of the script is processed.
6.1.1 The Script-reader.
The script-reader module
of the IDG, creates and modifies data structures based
on the information in the user's script.
The IDG script
directives, creainst and creacam, generate data
structures to represent instances of objects (or
cameras).
Once the data structure of an object (or
camera) has been generated, the structure's address, is
placed into an address table for future reference.
Also, the name associated with an instance (or camera),
is placed into a lookup table.
When either a timeline or valline command is
encountered, the script-reader creates a data structure
that holds the data associated with the directive.
As
39
with the object and camera data structures, the address
of these structures are placed into an address table,
and the name associated with the structures are place
into a lookup table.
To specify a motion, or rotation, of an object (or
of a camera) a timejvalue relationship must be
established to determine the interpolation function.
In
the current version of the script-reader, the time;value
relationship is established when a movobj, rotobj,
movcam or rotcam command is encountered.
currently, two
interpolation methods are supported by Prism, linear and
cubic spline.
Because of the nature of both linear and cubic
spline interpolation, the characteristics of both
functions can be described in terms of their
coefficients.
The linear interpolation function has two
coefficients per interval (a cubic spline has four) .
Since a time-line specifies a set of intervals to
interpolate across, a matrix format is used to store the
coefficients for all intervals.
Each row of the matrix
represents an interval in which the coefficients are
valid.
The actual generation of the coefficient matrix, is
dependent upon the type of interpolation scheme used.
Once the time-line and value-lines have been associated
with an object (or a camera) by a motionjrotation
40
command, the determination of the coefficients can
begin.
In the case of linear interpolation, it is straight
forward to generate the coefficients for the given
time/value line pair.
Prism does this by using the
point-slope form of a line, with the time-line as the
independent variable and value-line as the dependent.
For a given time;value line pair, there are n-1 (where n
is the number of elements in the time line) intervals,
therefore linear interpolation must be done n-1 times to
span the whole timejvalue line.
Figure 6.1 shows an
example of the calculations of a coefficient matrix for
a linear interpolation.
The cubic spline interpolation generates a n-1 by 4
matrix, where n is the number of elements in the time
line.
Since the nature of the cubic spline
interpolation algorithm inherently generates a
coefficient matrix to account for the different
intervals, no additional calculations are required.
The
cubic spline algorithm used in Prism was adapted from
the one given in Burden[J].
When an endtime directive is encountered by the
script-reader, control is passed to the image-describer.
At this point in the script, it is assumed that all
motions for this segment have been specified and that
the actual transformation calculations can begin.
,, .
41
Figure 6.1
Coefficient Matrix Calculation
creainst cubel cube
timeline timel 5 o. 1. 2.
3.
4.
valline vall 5 0. 6. 8. 10. 20.
starttime show 7.0
movobj cubel x linear timel vall
endtime show 15.0
5 time-line values => 4 time intervals
=> 4 linear interpolations to
calculate
from
from
from
from
time
time
time
time
interval
interval
interval
interval
0. thru 1.
1. thru 2 .
2. thru 3.
3. thru 4.
gives
gives
gives
gives
this generates the following matrix
[_j J]
v
v
v
v
=
=
=
=
0 +
4 +
4 +
-20
6t
2t
2t
+ lOt
42
6.1.2 Image-Describer.
The main function of the
image-describer is to output Image Generator directives
that will place the objects in the image in the proper
orientation for image rendering.
The image-describer
does this by determining the position of each object by
plugging in the value of the current time of segment
into the object's interpolation function.
(Initially,
the current time was set by a starttime directive.
The
subsequent positions were derived by incrementing the
current time value by the time-step value on a per-frame
basis.)
To determine the proper coefficients to use in the
interpolation function, a search of the time line
associated with the object's coefficients matrix is
performed.
Once the proper time interval is found, the
coefficients corresponding to the time interval are used
in the interpolation function.
For example, figure 6.1
shows a coefficient matrix for a linear interpolation
function with four time intervals.
If the current time
is 2.75, the values in the third row of the coefficient
matrix would be used because 2.75 falls between 2.0 and
3.0 (i.e.
the third time interval) of the associated
time line.
With the coefficients and the current time value,
an interpolated time value can be calculated.
This
calculated value, along with the object identification
43
number and the corresponding attribute, is placed into
the IDF.
After this process is done for all relevant
attributes of the current object, the image-describer
does the next object until all the objects have been
processed.
After all the objects have processed, a
DISPLAY directive is placed into the IDF and control
then reverts back to the script-reader.
This cycle of
read-script/describe segment continues until an·
end-of-file is found in the script file.
6.2 Image Generator (IG)
The second program of the Prism system is the Image
Generator.
It's function is to render and record images
that are described in the IDF.
The IG reads the data
from the IDF on a frame-by-frame basis.
Essentially,
any commands that fall between the previous and current
DISPLAY directives are considered part of the current
image.
Like the IDG, the IG can be broken into two
parts, a directive-reader and an image render/recorder.
6.2.1 Directive-reader.
The main function of the
first segment of the IG is to read the commands
encountered in the IDF.
As mentioned in Chapter 4,
there are three basic types of IDF commands, object
creation, matrix modifications, and the DISPLAY command.
Chapter 4 gave a description of these commands, this
section of the report will describe the effect of these
@
•
44
commands.
The object creation command causes the
directive-reader to generate an instance of the object.
Since at this point, the actual rendering of the object
becomes an issue, an instance of the object is created
that contains the vertex/polygon information from the
Object Definition File.
Also when this data structure
is created a pointer to its transformation matrix is set
up.
The matrix modification commands modify the
transformation matrix for each object based on the
commands in the IDF.
To generate this matrix, Prism
uses the fact that an object's final transformation
matrix can be computed as a series of multiplication of
matrices that contain the object's partial
transformations.
Since an IDF record contains the
information needed to make a partial transformation
matrix for a specified object, the formulation of the
object's final transformation matrix can be done by
multiplying the partial transformation matrices against
the current object's matrix.
once the transformations
are completed for all objects in the current image, the
actual render/recording of the image can be done.
6.2.2 Image Rendering.
The first step of image
rendering is the placement of the objects into their
proper position within the image.
This is done by
45
multiplying the vertices of an object by its
transformation matrix (Hearn[5]).
Once the
multiplication is done, the object is decomposed into a
set of polygon for rendering in the image.
In this version of Prism, the furthest extent to
image rendering was hidden surface removal.
The
technique used was a variation on the
Newell-Newell-Sancha depth-sorting algorithm
(Rogers[l2]).
This algorithm determines the placement
of polygons based on the polygons maximum z value.
By
placing the further polygon from the view point in the
frame buffer first the ones farthest from the view point
will be over written by the one closer to the view
point.
After placing all the polygons onto the frame
buffer, a command is sent to the VTC to record the
image.
Once the image is recorded, the image-render
returns control of the program back to the
directive-reader.
This cycle of transformjrenderjrecord
continues until the end of the IDF is reached.
CHAPTER 7
Portability of Prism
Prism was designed to be easy to port.
This was
done by making three major design considerations.
First, Prism was written entirely in the
language (Kernighan[6]).
c
programming
This should allow for easy
porting to any machine that supports
c.
Second, only
three UNIX dependent routines were used, .calloc, free,
and perror (Bell[2]).
If Prism is being ported to
another UNIX system, no changes should have to be made
with regards to these routines.
If Prism was being
ported to a non-UNIX environment, the porter must then
write jacket* routines to emulate the UNIX calloc, free
and perror calls.
Third, all graphic specific routines
were written with jackets around them.
The following
discussion describes the definition of the jacket
* A jacket routine is a
standardized
subroutine
interface with the system/device dependent called within
it.
46
47
routines in terms of the Raster Technologies One;so (RT
One/80} frame buffer and the Lyon-Lamb VAS-IV VTC.
7.1 Device Specific Jacket Routines
The actual code used to define these routines can
be found in Appendix E (in file dev.c).
The actual
low-level library for the RT One;so, was supplied with
Celerity at time of purchase.
All RT One;so specific
routines are demarcated by a "g1$" prefix.
The actual
references for the g1$ can be found in the Raster
Technologies Model One/10 and Model One/SO Command
Reference Manual (Raster[10]}, but it should be fairly
straight forward to write the corresponding RT One/SO
routines for another graphics device even without the
manual.
The low level VAS-IV (Lyon[16]) routines
(demarcated by "v ") were part of the system library.
As with the RT One;so commands, adapting the above
routines to handle a new recording device should be
straight forward.
7.1.1 Graphinit(),Vidinit() and Recinit().
These
routines set the RT One/SO into various display modes.
The main routine (in igjig.c) calls one of these
routines depending on the parameters at run time (see
Appendix B for run-time options} .
The Graphinit routine
configures the IG to "high resolutionjno recording
mode".
The Vidinit routine configures the IG for NTSC
48
video display mode.
The Recinit routine configures the
RT One/80 for video display mode and initializes the VTC
for recording.
7.1.2 GraphOff().
This routine terminates RT
Onej80 graphics mode.
7.1.3 winit(i).
Routine to determine the minimum
and maximum screen coordinates.
Since this port of
Prism supports a high resolution graphics mode and a
lower resolution video mode, winit was defined to be
able to set the minimum and maximum screen values to
either 1024x1280 (high resolution) or the 512x640 (low
resolution) modes.
7.1.4 wclear().
Routine to clear the frame buffer.
The RT OnejBO g1$clear() command was used for this
routine.
7.1.4 wwait(n).
This routine causes the Prism
program to pause for n seconds.
The RT OnejBO g1$wait
commands was used to implement this routine.
7.1.5 wpoly2().
polygon to the screen.
This routine writes out a single
The g1$polygn command was used
to implement this routine.
7.1.6 wrecord().
media.
This routine records a frame onto
The v rec library routine was used.
~
.
CHAPTER 8
Conclusions
This chapter will present closing remarks about
Prism.
It will give an analysis of Prism's current
ability as an animation system, and it will also discuss
some enhancements that could be made to improve it.
Also some final comments about what was learned from
this project will be stated.
8.1 Analysis of Prism
Prism is a script-based animation system developed
as a Graduate project.
This system shows signs of
promise as a baseline that could lead to many
successors.
Because of its modular design and its
simple method of passing information between its
components, future improvements to the system can be
done incrementally.
49
50
In terms of usability, Prism allows for a
high-level description of object animation.
In the
object definition phase, Prism's vertex/polygon
representation of objects, allows for definition of
geometric objects.
In the motion specification phase,
Prism's high-level script syntax makes it easy to
produce an animation sequence without writing any
low-level (e.g.
FORTRAN or C) code.
This feature
allows the user to concentrate on what the animation
sequence should look like instead of how it will be
produced.
Although the system is complete, there are some
deficiencies within it.
The first problem involves the
Image Generator's inability to cope with objects that go
behind the camera.
"reflection" effect.
The problem manifests itself as a
This effect is caused by trying to
project objects that are positioned behind the viewpoint
onto a viewing surface.
In general, when the Image
Generator attempts to project any point onto a viewing
surface, it multiplies both x and y values of the point
(e.g.
point 1 of figure S.la) by the distance of the
projection point from the view surface.
Then it divides
these values by the z coordinate of the point giving a
projected point on the view surface (point 2).
If as in
figure S.lb, the point is behind the projection point
(point 3) then the projected point is "reflected" onto
Q
•
51
Figure 8.1 Reflection Problem
Figure 8.la
Projection Surface
_.,.point 1
point 2- ' "
/
View point
'
_,"
/"
z direction
~
Figure 8.lb
Projection Surface
\~point 3
''
'
\
\
'
'
View point
'
''
\
z direction
'
'
\
- point 4
~
52
the view surface as point 4.
To overcome this problem,
volume clipping should be done to make sure that only
points in front of the camera are considered (Hearn[5]).
Another problem in the IG module of Prism, is the
incomplete implementation of the the
Newell-Newell-Sancha (NNS) hidden surface algorithm.
In
the NNS algorithm, a polygon clipping step may be
required when a cyclic polygon overlap occurs
(Rogers[l2]).
In the current version of Prism, the
polygon clipping required to overcome this problem was
not implemented.
If a cyclic polygon overlap occurs
Prism will abort the sequence generation.
8.2 Enhancements
There are a number of future projects that can be
done to supplement Prism.
These projects can be
categorized by which phase (i.e.
object definition,
transformation specification, or rendering) of the
animation process they fall within.
8.2.1 Object Definition.
One enhancement that
could be done is the development of an Object Editor for
the ODF.
An Object Editor would aid the user in
generating specifications needed to define an object.
This program can be
envi~ioned
as an interactive
graphics system that would allow the user to input the
shape by using some sort of computer aided design
53
approach to creating objects.
The current technique of
defining objects, mentioned in Chapter 4, becomes very
error-prone when entering complex objects into the ODF.
By using an Object Editor, a user could quickly develop
objects to animate.
8.2.2 Motion Specification.
Another enhancement,
that could be useful to Prism, is a fast playback
sequence generator.
This tool would allow the user to
do animated "pencil sketches" of the script.
This
pencil sketching module would not have to be a very
elaborate rendering (in fact, wire-frames of images
would suffice), but it should have the ability to show
the animation sequence in real-time.
This system should
allow the user to dynamically change the time step of
the images displayed and allow him to single step
through a script.
8.2.3 Object Rendering.
In this module a
sophisticated rendering engine that was capable of
displaying a animation sequence with ray tracing,
refraction, texture mapping and shadow generating
abilities could be built.
Since Prism does not require
the rendering engine to be on the same machine as the
IDG module, the actual image generation can done an fast
mainframe (e.g.
a Cyber 750) and the images created by
it stored in a file to be later brought back to a
machine that is capable of recording images onto media.
54
Figure 8.2 shows the new animation "pipeline" with
the extra components added to it.
8.3 Final Comments
Prism is an 3-dimensional script-based animation
system that allows a user to express the motions of
objects with the use of a script.
major software components:
Prism consist of five
an object specification file
to define objects, a script file to define object
motion, a image definition file to specify a
frame-by-frame description of the script, an image
definition generator to generate the image definition
file, and a image generator to actually create the
viewable animation sequence.
Because of Prism's
division between sequence specification, and the actual
image generation, modification to either the Image
Definition Generator or the Image Generator can be done
independently of each other.
In terms of the academic objectives stated in
chapter 1, the project did achieved the goals.
The
design and implementation of a working animation system
was achieved, and the problems encountered in building
Prism, did provide insight into building an animation
system.
Figure 8.2 Enhanced Prism System
IDG
IG
Display/Record
Device
(
\,
ODF"
Object
Editor
Pencil
Sketch
Rendering
Engine
(J1
(J1
v .
BIBLIOGRAPHY
1.
Anton, Howard. Elementary Linear Algebra.
John Wiley and Sons, 1981.
New York
2.
Bell Laboratories.
Vol. 1. New York
1983.
3.
Burden, Richard L., J. Faires, and Albert Reynolds.
Numerical Analysis. Boston : Prindel, Weber and
Schmidt, 1982.
4.
Foley, J. D., and A. Van Dam. Fundamentals of
Interactive Computer Grahics. Reading, Mass.
Addison-Wesley, 1982.
5.
Hearn, Donald, and M. Baker. Computer Graphics.
Englewood Cliffs, NJ : Prentice-Hall, Inc., 1986.
6.
Kernighan, Brian w., and Dennis M. Ritchie.
The c Programming Lan;uage. Englewood Cliffs, NJ :
Prentice-Hall, 1978.
7.
CSL-7100 Sync Generator, Instruction Manual,
Jackson, Missouri : Lenco Inc., 1984.
8.
PCE-466 Color Encoder, Instruction Manual, Jackson,
Missouri : Lenco Inc., 1984.
9.
Magnenat-Thalmann, Nadia, and Daniel Thalmann.
Computer Animation. Tokyo : Springer-Verlag, 1985.
10.
Raster Technologies Model One/10 and Model One/80
Command Reference. North Billerica, Mass.
Raster
Technologies, 1984.
11.
Reynolds, Craig w.
"Computer Animation with Scripts
and Actors." Computer Graphics 16 (July 1982) :
289-296.
UNIX Programmer's Manual,
Holt, Rinehart and Winston,
56
57
12.
Rogers, David F •• Procedural Elements For Computer
Graphics. New York : McGraw-Hill, 1985.
13.
PVM-1910/1911, Operating Instructions, Sony
Corporation, 1984.
14.
V0-5850, Operating Instructions, Sony Corporation,
1981.
15.
Sturman, David. Computer Animation: 3-D Motion
Specification and Control. ACM SIGGRAPH 86. Dallas,
Texas. Aug 18-22, 1986.
16.
VAS IV Operations Manual.
Lyon-Lamb.
Burbank, Calif.
APPENDIX A.
IDG and IG Error Messages
The general format of an IDG or IG error message is:
%F-RoutineName : message
Where "RoutineName" is the name of the subroutine where
the error occured and message is a text string
associated with the error.
The following is a list of
the error messages printed out the IDG program.
·%F-Lininterp : cannot allocate space for matrix
%F-Lininterp : cannot allocate space for vect
%F-mkCam : cannot allocate space for Caminfo
%F-mkinst : cannot allocate space for Objinfo
%F-ReadScript
could not find object %n
%F-ReadScript
cannot find object %n
%F-ReadScript
unknown command %n
%F-ReadScript
unknown interpolation %n
%F-ReadScript
unknown axis %n
%F-ReadScript
unknown time line %n
%F-ReadScript
unknown value line %n
%F-ReadScript
cannot find camera %n
%F-ReadScript
object n is unknown in database
%F-ReadScript
unknown attribute %n
%F-Sp1Interp
cannot allocate space for matrix
%F-Sp1Interp : cannot allocate space for vect
58
59
The "%n" refers to the offending argument that caused
the program to abort.
The following is a list of the error message
printed out by the IG program.
%F-chnmat : command %n not found
%F-Creainst : object %n not found
%F-Creainst
could not alloqate space for object
%F-Creainst
could not allocate space for matrix
%F-Creainst
could not allocate space for vertex
%F-Creainst
could not allocate space for polygon
%F-ExeDirect : cannot record
%F-ExeDirect : unknown directive
%F-Recinit
could not open VAS term
%F-Recinit : could not program VAS unit
%F-Recinit : could not program find frame
%F-PriObj : cannot allocate space for "plist"
%F-apDspLst : cannot allocate space for polygon link
%F-Hidden : cyclic clipping problem
Again the "%n" refers to the offending argument that
caused the program to abort.
APPENDIX B.
IDG and IG Command syntax
To invoke the Image Description Generator the
following command i~ used :
idg [-d dfile] [-e log] [-o ofile) [-s script]
The program generates the image description file for the
Image generator. the following options are available :
1.
-d dfile : name of IDF to create.
name is direct.dat.
By default the
2.
-e log : name of log file to place audit action of
the script file.
By default the log file is written
to stderr.
3.
-o ofile : name of ODF to reference.
the name is object.dat.
4.
-s script : name of script file to read. By
default the name of the script file to read in
script.dat
By default
To invoke the Image Generator the following command is
used :
ig [-d dfile] [-e log) [-f frame)
60
(-o ofile] -g -r -v
61
1.
-d dfile : name of IDF file to read.
the name is direct.dat.
By default
2.
-e log : name of log file to place information
about actions done by IG. By default, the
information is written out to error.log.
3.
-f frame : number of video frames to record upon
receiving the the DISPLAY directive in the IDF. By
default one frame of video is recorded per DISPLAY
directive.
4.
-g : use high resolution mode. If this option is
chosen, the IG will display the image on the screen
for four seconds.
5.
-o ofile : name of ODF to reference.
the name is object.dat.
6.
-v : display in NTSC video mode. If this option is
chosen, the IG will display the image an NTSC
monitor for four seconds.
7.
-r : display in NTSC video mode and record onto
video tape.
By default
If neither -g, -v or -r is chosen no image will be
displayed, but information will still be written to
error log.
APPENDIX C.
Directory Layout for Prism
Prism was developed with a hierarchical directory
structure with the major code sections having having a
common parent.
There are four major subdirectories
associated with Prism:
idg, ig, lib, and header.
The header directory contains the C header files
common to both the idg and ig and the lib directories.
The idg and ig directories contain code for IDG and IG
components of Prism.
The lib directory held utility
routines used by both the IDG and IG.
62
APPENDIX D.
IDG Routines
The following is a listing of the IDG program.
63
~
Make file for building IDG
#
""
OBJECTS
=
OBJECTS2
LIB
idg.o lininterp.o splinterp.c script.o
script.o lininterp.o splinterp.c
=
= .. jlibjeKtra.a
-lm
idg : $(OBJECTS) idg.h .. ;headerjdirects.h
cc -g -o idg $(OBJECTS) $(LIB)
script
idg.o
: $(OBJECTS2)
idg.h .. jheaderjdirects.h
cc -g -o script $(OBJECTS2)
: idg.c idg.h
cc -g -c idg.c
lininterp.o : idg.h lininterp.c
cc -g -c lininterp.c
splinterp.o : idg.h splinterp.c
cc -g -c splinterp.c
script.o
: idg.h script.c
cc -g -c script.c
0'1
*"
I*
*
idg.c
*
*I
*include
#include
#include
#include
<stdio.h>
"idg.h"
" .. lheaderldirects.h"
<math.h>
char progName[)
"phasel":
main(argc,argv)
int argc;
char **argv;
{
int i,status;
real tdelt;
real CurTime;
I*
* Initialize sysetmlgloballdefault values
*I
PlSysinit();
I*
* Read in command line arguments
*I
PlGetArgs(argc,argv);
I*
* Open files
*I
PlOpenFiles( );
I*
• Get object names from data base
*I
GetObjNames ();
I*
0'1
(J1
* Set
*I
z view
fprintf(drfile,"%d %d
%f~n",VIEWZ,0,20.
);
I*
* Set up motion times
*I
status = ReadScript ();
if (EndTime < StartTime) Abort("EndTime is less than StartTime");
I*
*Go for it ! !!
*I
do
for
(i=O;i<Totinst;i++)
if (btest(Objs[i]->Status,DSBLINST) != 1)
fprintf(drfile,"%d %d %f~n",RESETMAT,i,O. );
CurTime = StartTime;
while (CurTime <= EndTime)
Transcam(CurTime,Cams[O]);
for (i=O;i<Totinst;i++)
if (btest(Objs[i]->Status,DSBLINST) != 1)
TransObj(CurTime,Objs[i],Cams[O] );
I*
* Dispaly things
*I
fprintf(drfile,"%d %d %f~n",DISPLAY,-l,CurTime);
for (i=O;i<Totinst;i++)
if (btest(Objs[i]->Status,DSBLINST) != 1)
fprintf(drfile,"%d %d %f~n",RESETMAT,i,O.);
CurTime += TimeStep;
status = Readscript( );
if (EndTime < StartTime)
Abort("EndTime is less than StartTime");
} while (status != EOF);
0'\
0'\
real
EvalTime(CurTime,Poly)
real curTime;
PolyParms *Poly;
(
;•
•
Routine to calculate the value of the polynomial Poly at
CurTime.
*
Input : CurTime (real) : time to evaluate function at.
Poly ( PolyParms *) : polynomial to evaluate.
Ouput
None.
: Returns the evaluation of the polynomial.
*I
int i;
real \Tal;
i = IScnRVec,CurTime,Poly->Time,Poly->NPoint,O) + 1;
if (i > Poly->Coff->imax) i = Poly->Coff->imax;
val= (*(Poly->Interp))(i,CurTime,Poly);
return( val);
0\
-.)
GetobjNames()
(
;•
•
*
*
*
Routine to read in object database and get the index number and the
names of objects
Written : 18-Jan-1987
Input :
(none)
(none)
outp1ut
modification to global variable TotDBObj, and
arrays DBObj!ndex and DBObjName
*I
name[20];
int i,J,k,index,nvert,nvert2,npoly,icolor,vindex,totobj;
float xval,yval,zval;
c~a~
fscanf(dbfile,"%d",&totobj);
fprintf(elog,"%%I-GetobjNames : totobj %d 'n",totobj);
DBObjindex = (int *)calloc(totobj,sizeof(int));
DBObjName = (char ••) calloc(totobj,sizeof(char *));
for(i=O;i<t~tobj;i++)
{
fscanf(dbfile,"%d %s",&index,name);
DBObjindex[TotDBObj) =index;
DBObjName{TotDBObj) = (char *)calloc(20,sizeof(char) );
strcpy(DBObjName[TotDBObj],namel;
fscanf(dbfile,"%d %d",&npoly,&nvert);
fprintf(elog,"%%I-GetObjNames : index %d name %s npoly %d nvert %d 'n",in
for(j=O;j<nvert;j++)
fscanf(dbfile,"%f %f %f",&xval,&yval,&zval);
for(j=O;j<npoly;j++) {
fscanf(dbfile,"%d %d",&nvert2,&icolor);
for(k=O;k<nvert2;k++)
fscanf(dbfile,~%d",&vindex);
J
TotDBObj++;
m
00
IScnRVec(target,array,numvals,startpos)
real target,array(];
int numvals,startpos;
I*
*
*
Routine to scan array "array" for valu~ "target" starting from position
"startpos".
The array has "numvals" elements in it.
Written
Input
Output:
29-Dec-1986
target : real value to search "array" for.
array
real array to search through.
numvals: number of elements in array.
startpos : begining position to start from.
returns n where : array(n]
<= target
(default
0)
< array(n+ll
*I
int i;
i = startpos;
while (target >= array(i]
&& i<numvals)
i++;
if (i==numvals) return(i);
if (i==startpos)
return(i);
else
return(i-1);
0"1
\!)
Caminfo •
mkcam(I-:ient)
int Ident;
;•
•
•
Routine to create a virtual camera .
Written : 01-Jan-1987
Input : Ident (integer)
*
•
output
identification number for the camera.
returns a pointer to a structure Caminfo .
*I
Caminfo •temp;
if ( (temp=ICaminfo *) calloc(l,sizeof(Caminfo) )) ==NULL)
Abort("%%F-mkCam : cannot allocate space for Caminfo");
temp->IdNumber = Ident;
return( temp);
.....]
0
Objinfo *
mkinstiidNumber,Type)
int IdNumber,Type;
I·
I'
I*
*
*
*
Routine to create an instance of an Object of "Type" with and
identification number of "IdNumber".
Written : 29-Dec-1986
Input : IdNumber (int)
Type (int)
*
*
output
(Objinfo
: identification number to be used by
phase 2 for referenceing this instance
of object "Type".
: Index into object data base to be referenced
by phase 2.
*)
:
pointer structure of type object.
*I
Objinfo *temp;
if ((temp= (Objinfo *) callocll,sizeof(Obj!nfo))) ==NULL)
Abort("%%F-mkinst : cannot allocate space for Objinfo");
temp->IdNumber = IdNumber;
temp->Type = Type;
I*
* Write out directive to drfile
*I
fprintf(drfile,"%d %d %f %d\n",CREAINST,IdNumber,O. ,Type);
return( temp);
....J
1-'
PlGetArgs(icount,args)
int icount;
char ••args;
I*
Read in command line arguments
Input : icount (int)
number of arguments on the command line
args (char**) : array of string on the command line.
*
Output : None : Routine set global variables.
*I
for(icount -=l,args+=l;icount>O;icount--,args++)
if(**args == '-') [
switch (*++(*args))
case
'd'
I*
* name of directive file
*I
strcpyfdrname,*(++argsl );
icount--;
break;
case
'e'
I*
* name of error log file
*I
strcpy'ername,*f++args) );
icount--;
break;
case
'o'
I*
* name
*I
of object file
I*
* name
*I
of script file
strcpy(dbname,*(++args) );
icount--;
break;
case
's'
strcpy(scname,*(++args) );
icount--;
break;
default
I*
....J
N
* error in parameter
*I
fprintf(stderr,
"usage : %s [-d directfile) [-o objfile)\n",pro
exit ();
break;
~
w
PlOpenFiles()
[
;•
•
Routine to open major files for Phasel .
Written : 29-Dec-1986
Input :
•;
(none)
Output :
only global variables affected
(none)
if(ername(O] != 0)
if ( (elog
fopen(ername,"w")) ==NULL) {
fprintf(stderr,"Error in opening error log,n");
fprintf(stderr, "Program aborted \n,n");
exit();
=
}
if( (dbfile = fopen(dbname,"r"))
Abort("Error in opening
if( (drfile = fopen(drname,"w"))
Abort("Error in opening
if((scfile = fopen(scname,"r"))
Abort("Error in opening
==NULL)
database file");
==NULL)
directive file");
==NULL)
script file");
..._]
"""
PlSysinit()
(
I*
Routine to set up some global Phasel variables
*
*
*
*
Written : 23-Dec-1986
Input : none.
output : none.
*I
I*
* set default names
*I
strcpy(dbname,"object.dat");
strcpy(drname,"direct.dat");
elog = stderr;
ername[O]
0;
strcpy(scname,"script.dat");
=
InterpName[O] = (char*) calloc(20,sizeof(char));
InterpName[l] = (char *) calloc(20,sizeof(char));
strcpy(InterpName(O],"linear");
strcpy(InterpName[l],"spline");
Totinterp = 2;
I*
* default start time , end time and time step
*I
=
StartTime
0.;
EndTime = 0.;
Timestep = 1.130.;
I*
* set initial value for TotDBObj
*I
TotDBObj
=
0;
I*
* set value.for variables used by ReadScript
*I
Totinst
=
0;
-._}
l"
76
'-0
0
II o
0
0
Ul
Ul
cv
II
...u cv ru c e
<E-o:>
.........
... u...,
:I ...
e.-~
Ul
nl
·.-t
H
0
0
0
0
0
E-<E-<E-<E-< E-t
TransCam(CurTime,Camera)
real CurTime;
Caminfo *Camera;
{
I*
•
•
Routine to move a camera ("Camera") with respect to "CurTime"
Written : 01-Jan-1987
(Happy New Year ! ! ! )
Input : CurTime (real) : the time of the transformation.
Camera (Caminfo *):the camera to move.
*
*
*I
Output : None.
Modifies structure that •camera" points.
int i;
real val;
if (Camera->XLoc.NPoint != 0)
Camera->XPos = EvalTime(CurTime,&(Camera->XLoc) );
if (Camera->YLoc.NPoint != 0)
Camera->YPos = EvalTime(CurTime,&(Camera->YLoc) );
if (Camera->ZLoc.NPoint != 0)
Camera->ZPos = EvalTime(CurTime,&(Camera->ZLoc) );
if (Camera->XRot.NPoint != 0)
Camera->XTheta = EvalTime(CurTime,&(Camera->XRot) );
if (Camera->YRot.NPoint != 0)
Camera->YTheta
EvalTime(CurTime,&(Camera->YRot) );
if (Camera->ZRot.NPoint != 0)
Camera->ZTheta = EvalTime(CurTime,&(Camera->ZRot) );
=
....]
....]
TransObj(CurTime,Obj,Cam)
real CurTime;
Objinfo *Obj;
Caminfo *Cam;
[
I*
Routine to transform object "Obj" as a function of "CurTime"
*
*
*
Written : 29-Dec-1986
Input : CurTime (real)
Obj (Objinfo *)
Time to caculate for.
: Pointer to object to transform at time
Cam (Caminfo *)
: Pointer to earner to move in respect to.
''CurTime"
*
Output
Routine has .no return value but does write information
to "drfile".
*I
int i;
real •ral;
I*
• Determine Position in X direction
*I
if (Obj->XLoc.NPoint != 0) {
val = EvalTime(CurTime,&(Obj->XLoc)) - Cam->XPos;
fprintf(drfile,"%d %d %f\n",TRANX,Obj->IdNumber,val);
I*
• Determine Position in Y direction
*I
if (Obj->YLoc.NPoint != 0) {
val= EvalTime(CurTime,,(Obj-)YLoc)) - Cam->YPos;;
fprintf(drfile,"%d %d %f\n",TRANY,Obj->IdNumber,val);
I*
• Determine Position in Z direction
*I
if(Obj->ZLoc.NPoint != 0) {
val = EvalTime(CurTime,&(Obj->ZLoc)) - Cam->ZPos;
fprintf(drfile,"%d %d %f\n",TRANZ,Obj->IdNumber,val);
I*
-.J
OJ
* Determine X-Rotation around self
*I
if(Obj->XRot.NPoint != 0)
val= EvalTime(CurTime,&(Obj->XRot));
fprintf(drfile,"%d %d %f,n",ROTSX,Obj->IdNumber,val);
I*
* Determine
*I
Y-Rotation around self
if(Obj->YRot.NPoint != 0) (
val= EvalTime(CurTime,&(Obj->YRot));
fprintf(drfile,"%d %d %f,n",ROTSY,Obj->IdNumber,val);
I*
* Determine
*I
Z-Rotation around self
if(Obj->ZRot.NPoint != 0)
val= EvalTime(CurTime,&(Obj->ZRot) );
fprincf(drfile,"%d %d %f,n",ROTSZ,Obj->IdNumber,val);
I*
* Determine X-Rotation around camera
*I
if(Cam->XRot.NPoint != 0)
val = -(Cam->XTheta);
fprintf(drfile,"%d %d %f,n",ROTX,Obj->IdNumber,val);
I*
* Determine Y-Rotation around camera
*I
if(Cam->YRot.NPoint != 0) (
val= -(Cam->YTheta);
fprintf(drfile,"%d %d %f'n",ROTY,Obj->IdNumber,val);
I*
* Determine Z-Rotation around camera
*I
if(Cam->ZRot.NPoint != 0) (
val = -(Cam->ZTheta);
fprintf(drfile,"%d %d %f,n",ROTZ,Obj->IdNumber,val);
-..!
1.0
""
80
I*
*
lininterp.c
*I
#include "idg.h"
real
CalcLin(index,Xval,Poly)
int index;
real Xval;
PolyParms *Poly;
(
I*
*
*
*
Routine to evaluate polyomial "index" froa the coefficient aatrix
and an independent variable.
Written
Input
*
Output:
.I
int degree,i;
real val;
real temp;
*
29-Dec-1986
index
Xval
Poly
pointer to which polynomial to use evaluate
point to evaluate polynomial with
parameters for linear interpolation
returns evaluation of polynomial "index" with value of "Xval"
val= M'lAL(Poly->Coff,index,l) + MVAL(Poly->Coff,index,2)*Xval;
return( val);
00
1-'
Rmat *
Lininterp(Nstep,Time,Vals)
int Nstep;
real Time[),Vals();
(
I*
*
*
*
*
*
Routine to generate a coefficient matrix points given by
"Vals" vs. Time.
Written : 29-Dec-1986
Input
*
o:
*
Nstep number of values in arrays "Time" and "Vals"
•Time array of reals (independent variable)
*Vals array of reals (dependent variables)
Output: Returns a pointer to a matirx (a Rmat structure)
that has the coefficients for a first degree polynomial
*I
Rmat *matrix;
real Slope;
int i;
if ((matrix= (Rmat *) calloc(l,sizeof(Rmat))) ==NULL)
Abort("%%F-Lin!nterp : cannot allocate space for matrix");
matrix->imax
matrix->jmax
Nstep-1;
2;
if ((matrix->vect =(real *) calloc((Nstep-ll*2,sizeof(real))) ==NULL)
Abort("%%F-Lininterp : cannot allocate space for vect");
for (i=O;i<Nstep-l;i++l {
Slope= (Vals[i+l)-Vals(i) )I(Time(i+l)-Time(i] );
MVAL(matrix,i+1,2) = Slope;
MVAL(matrix,i+l,l) = Vals[i)-(Slope*Time(i));
return(matrixl;
00
1\)
I*
*
*
script.c
*
*I
#include <stdio.h>
#include "idg.h"
#include " .. jheaderldirects.h"
char *RSerror[] = ["%%F-Readscript
"%%F-Readscript
"%%F-ReadScript
"%%F-ReadScript
"%%F-ReadScript
"%tF-ReadScript
"%%F-Readscript
"%%F-ReadScript
"%%F-ReadScript
"%%F-ReadScript
"%%F-Readscript
cound not find object %s \n",
cannot make object",
cannot find object %s \n",
unknown command %s \n",
unknown interpolation %s \n",
unknown axis %s \n",
unknown time line %s \n",
unknown value line %s \n",
cannot find camera %s \n",
object %s is unknown in database \n",
unknown attribute %s \n"
J;
ReadScript()
{
I*
Routine to read in a script file and generate the desired coefficient
matrix for objects to be displayed.
Written : 12-Jan-1987
*
Input
:
Output :
(none)
(none)
: data information in from "scfile"
: global var:Lalbes set.
*I
char command(20],name!20],objname(20];
char AName(20],IName(20],TName{20],VName[20];
int i,nval,status,type;
float tval[8];
status = 0;
while ((status= fscanf(scfile,"%s %s",command,name))
!= EOF) {
if (strcmp(command,"creacam") == 0)
fprintflelog,"%%I-ReadScript : creating camera %s \n",name);
if ( (Cams(TotCam] = mkCam(TotCam)) == 0)
OJ
w
Abort(RSerror[8));
CameraName[Totcam] = (char *) calloc(20,sizeof(char));
strcpy(CameraName[TotCam],name);
Totcam++;
else if (strcmp(command,"creainst") == 0)
fscanf(scfile,"%s",objname);
if ((type= FindName(objname,OBObjName,TotOBObj)) == -1)
fprintf(elog,RSerror[9),objname);
Abort("%%F-ReadScript");
}
type= DBObjindex[type];
fprintf(elog,"%%I-ReadScript : creating object %s of type %d \n",
if ( (Objs[Totinst] = mkinst(Totinst,type)) == NULL)
Abort(RSerror(l));
ObjectName[Totrnst) = (char *)calloc(20,sizeof(char));
strcpy(ObjectName(Totinst),name);
Totinst++;
TotAct++;
else if (strcmp(command,"delinst") == 0) {
fprintf(elog,"%%I-ReadScript : deleting object %s \n",name);
if ( (i = FindName(name,ObjectName,Totinst)) != -1)
fprintf(drfile,"%d %d 0.\n",DSBLINST,i);
TotAct--;
Objs[i)->Status I= OSBLINST;
else {
fprintf(elog,RSerror(O),name);
Abort("%%F-ReadScript");
else if (strcmp(command,"endtime") == 0)
fscanf(scfile,"%f",,tval(O]);
fprintf(elog,"%%I-ReadScript : End Time step
EndTime = (real) tval[O);
return( status);
%f\n",tva1(0]);
else if (strcmp(command,"movcam") == 0)
fscanf(scfile,"%s %s %s %s",AName,IName,TName,VName);
fprintf(elog,"%%I-ReadScript : Moving camera %s with time %s, val
Movcam(name,AName,IName,TName,VName);
else if (strcmp(command,"movobj") == 0)
fscanf(scfile,"%s %s %s %s",AName,IName
,TName,VName);
..,.
())
fprintf(elog,"%%1-ReadScript : moving object %s with time line %s
MovObj(name,AName,1Name,TName,VName);
else if (strcmp(command,"rotcam") == 0)
fscanf(scfile,"%s %s %s %s",AName,1Name
,TName,VName);
fprintf(elog,"%%1-ReadScript : rotating camera %s with time line
RotCam(name,AName,1Name,TName,VName);
else if (strcmp(command,"rotobj") == 0)
fscanf(scfile,"%s %s %s %s",AName,1Name
,TName,VName);
fprintf(elog,"%%I-ReadScript : rotating object %s with time line
RotObj(name,AName,IName,TName,VName);
else if (strcmp(command,"setattr") == 0)
fscanf(scfile,"%s %f",AName,&tval{0]);
fprintf(elog,"%%1-ReadScript : setting
SetAttr(name,AName,tval[O] );
object %s attribute %s wi
else if (strcmp(command,"starttime") == 0)
fscanf(scfile,"%f",&tval{O] );
fprintf(elog,"%%I-ReadScript : Start Time step is
StartTime = (real) tval[O];
%f'\n",tval{O]
else if (strcmp(command,"timeline") == 0)
fscanf(scfile,"%d",&nval);
fprintf(elog,"%%I-Readscript : creating time line %s nval %d'\n",n
Time(TotTimes] = (RVector *)calloc(l,sizeof(RVector) );
TimeName{TotTimes] = (char *)calloc(20,sizeof(char) );
strcpy(TimeName[TotTimes],name);
Time[TotTimes)->NPoint = nval;
Time{TotTimes]->data = (real *)calloc(nval,sizeof(real));
for (i=O;i<nval;i++) [
fscanf(scfile,"%f",&tval[O]);
Time{TotTimes]->data[i] = (real) tval[O];
TotTimes++;
else if (strcmp(command,"timestep") == 0)
fscanf(scfile,"%f",&tval[O]);
fprintf(elog,"%%1-ReadScript : Time step is
Timestep = (real) tval[O];
%f'\n",tval[O]);
else if (strcmp(command,"valline") == 0)
fscanf(scfile,"%d",&nval);
OJ
01
fprintf(elog,"%%1-ReadScript : creating value line %s \n",name);
Value[TotValues] = (RVector *)calloc(l,sizeof(RVector));
ValueName[TotValues] = (char *)calloc(20,sizeof(char));
strcpy(ValueName[TotValues] ,name);
Value[TotValues]->NPoint = nval;
Value[TotValues]->data = (real *)calloc(nval,sizeof(real));
for (i=O;i<nval;i++) {
fscanf(scfile,"%f",&tval[O]);
Value[TotValues]->data(i] = (real) tval[O];
TotValues++;
else if (strcmp(command,"viewz") == 0)
fscanf(scfile,"%f",&tval[O]);
fprintf(elog,"%%1-ReadScript : projection point is
fprintf(drfile,"%d 0 %f\n",V1EWZ,tval[O]);
%f \n",tval)
else if (strcmp(command,"world") == 0) {
fscanf(scfile,"%f %f %f %f",&tval[O],&tval[l]
,&tval[2] ,&tval(3]);
fprintf(elog,"%%1-ReadScript : world corrdinates xmin %f, ymin %f
SetWldC(tval[O],tval[l] ,tval[2] ,tva1[3] );
else
fprintf(elog,RSerror[3],command);
Abort("%%F-ReadScript"l;
return( status);
00
0'1
.,
FindName(Name,List,len)
char Name[],*List[];
int len;
/*
•
Routine to find "Name" in "List"
Input
*
•
•
•
output
Name (char *) : Name to search for in "List"
List (char **): List to search thru.
Len
(int)
: number of elements in "List"
(int)
index value for "Name" in "List"
if "Name" not found in "List" return -1.
*/
int i;
for (i=O;i<len;i++) if (strcmp(Name,List[i]) ==0
return(-!);
return(i);
00
-..]
"'
MovCam(CName,AName,IName,TName,VName)
char *CName,*AName,*IName,*TName,*VName;
{
I*
*
*
*
*
*
*
*
*
*
Routine to generate a motion cofficient for a given direction
Written : 17-Jan-1987
Input : CName
ANa me
!Name
TN a me
VName
Output
(char
(char
(char
(char
(char
(none)
name of camera to move.
direction to move in. (X' y, or z direction).
type of interpolation routine to use.
Name of time array to use.
: Name of value array to use
*)
:
*)
*)
:
:
:
*)
*)
: make modification to an element of global array
"Cams".
*
*I
int icam,itime,ival,iinterp;
if
( (icam = FindName(CName,CameraName,Totcam))
fprintf(elog,RSerror[S],CName);
Abort("%%F-ReadScript");
if
( (itime = FindName(TName,TimeName,TotTimes))
fprintf(elog,RSerror[6] ,TName);
Abort("%%F-ReadScript");
if
( (ival = FindName(VName,ValueName,TotValues))
fprintf(elog,RSerror[7] ,VName);
Abort("%%F-Readscript");
if
( (iinterp = FindName(IName,InterpName,Totinterp)) == -1)
fprintf(elog,RSerror[4] ,!Name);
Abort("%%F-ReadScript");
-1)
-1)
-1)
switch (iinterp)
case 0
if (strcmp(AName,"x")== 0) {
SetTrans(&(Cams[icam]->XLoc) ,Lininterp,CalcLin
00
00
,itime,ival);
==
else if (strcmp(AName,"y")
0) {
SetTrans(&(Cams(icam)->YLoc),Lininterp,CalcLin
,itime,ival);
else if (strcmp(AName,"z") == 0)
SetTrans(&(Cams[icam)->ZLoc) ,Lininterp,CalcLin
,itime,ival);
else
fprintf(elog,RSerror(S),AName);
Abort("%%F-ReadScript");
break;
case 1
if (strcmp(AName,"K")== 0)
SetTrans(&(Cams[icam)->XLoc) ,Splinterp,CalcSpl,
itime,ival);
else if (strcmp(AName,"y") -- 0)
SetTrans(&(Cams[icam]->YLoc) ,Splinterp,CalcSpl,
itime,ival);
else if (strcmp!AName,"z") == 0)
SetTrans(&(Cams[icam]->ZLoc) ,Splinterp,CalcSpl,
itime,ival);
else
fprintf(elog,RSerror[S],AName);
Abort("%%F-ReadScript");
1
break;
00
\0
Movobj(OName,AName,IName,TName,VName)
char *OName,*AName,*IName,*TName,*VName;
{
;•
•
•
•
•
Routine to generate a motion cofficient for a given direction
Written : 12-Jan-1987
•
Input : ON a me
ANa me
I Name
TN a me
VName
•
output
•
(char
(char
(char
(char
(char
(none)
...
..
)
:
)
)
)
:
:
:
:
)
name of object to move.
direction to move in. ( K' y, or z direction) .
type of interpolation routine to use.
Name of time array to use.
Name of value array to use
: make modification to global array "Objs".
*/
int iobj,itime,ival,iinterp;
if ( (iobj = FindName(OName,ObjectName,Totinst))
fprintf(elog,RSerror[2] ,OName);
Abort("%%F-Readscript");
-1)
if
-1)
( (itime = FindName(TName,TimeName,TotTimes))
fprintf(elog,RSerror[6],TName);
Abort("%%F-ReadScript");
if ( (ival = FindName(VName,ValueName,TotValues))
fprintf(elog,RSerror[7],VName);
Abort("%%F-ReadScript");
-1)
if ( (iinterp = FindName(IName,InterpN~me,Totinterp)) == -1)
fprintf(elog,RSerror[4] ,!Name);
Abort("%%F-Readscript");
switch (iinterp)
case 0
if (strcmp(AName,"x")== 0) {
SetTrans(&(Objs[iobj]->XLoc) ,Lininterp,CalcLin
,itime,ival);
\D
0
else if (strcmp(AName,"y") == 0) [
SetTrans(&(Objs[iobj)->YLoc) ,Lininterp,CalcLin
,itime,ival);
else if (strcmp(AName,"z") == 0) [
SetTrans(&(Objs[iobj]->ZLoc),Lininterp,CalcLin
,itime,ival);
else
fprintf(elog,RSerror[5],AName);
Abort("%%F-ReadScript");
break;
case 1
if (strcmp(AName,"x")== 0)
SetTrans(&(Objs(iobj]->XLoci,Splinterp,CalcSpl,
itime,ival);
else if (strcmp(AName,"y") == 0) [
SetTrans(&(Objs[iobj]->YLoc) ,Splinterp,CalcSpl,
itime,ival);
else if (strcmp(AName,"z") == 0) [
SetTrans(&(Objs(iobj]->ZLoc) ,Splinterp,CalcSpl,
itime,ival);
else
fprintf(elog,RSerror[5) ,AName);
Abort("%%F-ReadScript");
break;
\0
1-'
Rotcam(CName,AName,IName,TName,VName)
char *CName,*AName,*IName,*TName,*VName;
{
I*
*
*
*
*
•
•
•
•
•
Routine to generate a rotation cofficient for a given axis
Written :
12-Jan-1987
Input : CName
ANa me
!Name
TN a me
VName
output
(char
(char
(char
(char
(char
(none)
..
..
*)
)
)
)
)
name of camera to move.
direction to rotate in. (x, y, or z axis).
type of interpolation routine to use .
Name of time array to use .
Name of value array to use
: make modification to an element global array "Cams" .
*I
int icam,itime,ival,iinterp;
=
if ( (icam
FindName(CName,CameraName,TotCam))
fprintf(elog,RSerror[S],CName);
Abort("%%F-ReadScript");
if ((itime = FindName(TName,TimeName,TotTimes))
fprintf(elog,RSerror[6],TName);
Abort("%%F-Readscript");
-1)
-1)
if ((ival = FindName(VName,ValueName,TotValues))
fprintf(elog,RSerror[7],VName);
Abort("%%F-ReadScript");
if
(iinterp = FindName(IName,InterpName,Totinterp))
fprintf(elog,RSerror[4],IName);
Abort("%%F-ReadScript");
-1)
-1)
switch (iinterp)
case 0
if
==
(strcmp(AName,"x")
0)
SetTrans(&(Cams[icam]->XRot),Lininterp,CalcLin,
itime,ival);
else if (strcmp(AName,"y")
==
0)
\0
tv
SetTrans(~(Cams[icam]->YRot)
,Lininterp,CalcLin,
itime,ival);
else if (strcmp(AName,"z") == 0)
{
SetTrans(~(Cams{icam]->ZRot)
,Lininterp,CalcLin,
itime,ival);
else
fprintf(elog,RSerror[S],AName);
Abort("%%F-ReadScript");
break;
case 1
if (strcmp(AName,"x"J== 0) {
SetTrans(,(Cams[icam]->XRot) ,Splinterp,CalcSpl,
itime,ival);
else if (strcmp(AName,"y") == 0)
SetTrans(~{Cams[icam]->YRot),Splinterp,CalcSpl,
itime,ival);
1
else if (strcmp(AName,"z") == 0)
[
SetTrans(~(Cams[icam}->ZRot),Splinterp,CalcSpl,
itime,ival);
else
fprintf(elog,RSerror[S},AName);
Abort("%%F-Readscript");
break;
\0
w
RotObj(OName,AName,IName,TName,VName)
char *OName,*AName,*IName,*TName,*VName;
I*
*
Routine to generate a rotation cofficient for a given axis
*
Written : 12-Jan-1987
*
Input : ON a me
ANa me
I Name
TN a me
VName
•
•
*
(char
(char
(char
(char
(char
.
)
*)
*)
*)
*)
:
:
:
:
:
name of object to move.
direction to rotate in. (X' y, or z axis).
type of interpolation routine to use.
Name of time array to use.
Name of value array to use
*
output : (none) : make modification to an element global array "Objs".
*
•/
int iobj,itime,ival,iinterp;
if ((iobj = FindName(OName,ObjectName,Totinst))
fprintf(elog,RSerror[2),0Name);
Abort("%%F-ReadScript");
==
-1)
if ((itime = FindName(TName,TimeName,TotTimes))
fprintf(elog,RSerror[6),TName);
Abort("%%F-ReadScript");
==
-1)
=
if ( (ival
FindName(VName,ValueName,TotValues))
fprintf\elog,RSerror[7) ,VName);
Abort("%%F-Readscript");
if ( (iinterp = FindName(IName,InterpName,Totinterp))
fprintf(elog,RSerror[4) ,IName);
Abort("%%F-ReadScript");
-1)
==
-1) (
switch (iinterp)
case 0
if (strcmp(AName,"x")
==
0) (
SetTrans(~(Objs{iobj)->XRot),Lininterp,CalcLin,
itime,ival);
else if (strcmp(AName,"y")
==
0)
1.0
J>
.,
SetTrans(,(Objs[iobj]->YRot),Lininterp,CalcLin,
itime,ival);
else if (strcmp(AName,"z") == 0) {
SetTrans(&(Objs[iobj]->ZRot) ,Lininterp,CalcLin,
itime,ival);
else
fprintf(elog,RSerror[5],AName);
Abort("%%F-Readscript");
break;
case 1
if (strcmp(AName,"x")== 0) {
SetTrans(&(Objs[iobj]->XRot) ,Splinterp,CalcSpl,
itime,ival);
else if (strcmp(AName,"y") == 0) {
SetTrans(&(Objs[iobj]->YRot) ,Splinterp,CalcSpl,
itime,ival);
else if (strcmp(AName,"z") == Ol {
SetTrans(&(Objs[iobj]->ZRot),Splinterp,CalcSpl,
itime,ival);
else
fprintf(elog,RSerror[5],AName);
Abort("%%F-ReadScript");
break;
\0
U1
SetAttr(OName,AttrName,val)
char OName[),AttrName[];
float val;
{
I*
*
Routine to set translation matirx values before time frame
dependent values are composed over it in phase 2.
*
*
Written
*
*
*
•;
11-Feb-1987
Input : OName (char *) : Name of object to change
AttrName (char •) : Name of attribute to change
val (float *) : Value to set OName to.
Output
(none)
: Information is written out to "drfile".
int iobj,type;
type = 0;
if ( (iobj = FindName(OName,ObjectName,Totinst)) == -1)
fprintf(elog,RSerror(2],0Name);
Abort("%%F-ReadScript");
if (strcmp(AttrName,"xscale") == 0) type = FIXSCALX;
else if (strcmp(AttrName,"yscale") == 0) type= FIXSCALY;
else if (strcmp(AttrName,"zscale") == 0) type = FIXSCALZ;
else if (strcmp(AttrName,"xsrot") == 0) type= FIXROTSX;
else if (strcmp(AttrName,"ysrot") == 0) type= FIXROTSY;
else if (strcmp(AttrName,"zsrot") == 0) type= FIXROTSZ;
else if (strcmp(AttrName,"xtran") == 0) type= FIXTRANX;
else if (strcmp(AttrName,"ytran") == 0) type= FIXTRANY;
else if (strcmp(AttrName,"ztran") == 0) type= FIXTRANZ;
else [
fprintf(elog,RSerror[10) ,AttrName);
Abort!"%%F-ReadScript");
I
fprintf(drfile,"%d %d
%f~n",type,iobj,val);
1.0
m
SetTrans(PCoff,Interp,Calc,itime,ival)
PolyParms *PCoff;
real (*Calc)();
Rmat *((*Interp)( ));
int itime,ival;
;•
•
•
•
•
*
*
Routine to set element PolyParms structure to proper values .
· Written : 17-Jan-1987
Input : PCoff (PolyParms *) : pointer to structure to modify
Interp (Rmat *)
: pointer to function to generate
cofficient matrix.
calc ((*real) ()) : Interpolation routine to be used
when evaluating values for a time
itime (int) : index into "Time" array
ival
(int) : index into "Value" array
*I
PCoff->Coff
=
(*Interp)(Time[itime]->NPoint,
Time[itime]->data,
Value[ival]->data);
PCoff->Time = Time[itime]->data;
PCoff->NPOLnt = Time[itime]->NPoint;
PCoff->Interp = Calc;
1.0
-...)
SetWldC(xmin,ymin,xmax,ymax)
real xmin,ymin,xmax,ymax;
I*
Routine to set world coordinates
*
*
*
*
*
*I
Written : 20-Feb-1987
Input : xmin
ymin
xmax
ymax
output
(real)
(real)
(real)
(real)
(none)
left visible boundry.
lower visible boundry.
right visible boundry.
upper visible boundry.
: writes boundry information to directive file
fprintf(drfile,"%d 0 0. \n",SETWLDC);
fprintf(drfile,"%f %f %f %f \n",xmin,ymin,xmax,ymax);
1.0
():)
I*
•
splinterp.c
*I
linclude "idg.h"
Rmat *Splinterp(Nstep,Time,Vals)
int Nstep;
real Time[], Vals[];
[
I*
Routine to generate a coefficient matirx for points given by
"Vals" vs. Time.
Written : 08-Jan-1987
Input
*
Output
*
*I
number of values in arrays "Time" and "Vals"
: Nstep (int)
array of reals.
The independent variable.
Time[) (real)
The dependent varialbe.
Vals[) (real) : array of reals.
!Rmat) a pointer to a matirx containing to coefficients to
the calculated spline.
Rmat *matrix;
real array [ 20 I;
int i,n;
real b[20],c[20) ,d[20];
real h[20] ,1[20),u[20),z[20),alpha[20];
n = Nstep -
1;
if((matrix = (Rmat *) calloc(l,sizeof(Rmat))) ==NULL)
Abort("%%F-Sp1Interp : cannot allocate space for matrix");
matrix->imax
matrix->jmax
Nstep-1;
4;
if((matrix->vect = (real*) calloc((Nstep-1)*4,sizeof(reall)) ==NULL)
Abort("%\F-Splinterp : cannot allocate space for vect");
for(i=O;i<=n-l;i++) hlil = Time[i+l) - Time[i);
for(i=l;i<=n-l;i++) [
alpha[il = 3. * (Vals[i+l)*h[i-1)-Vals[i)*
(Time[i+l)-Time[i-l))+Vals[i-l)*h[i) );
\0
\0
real CalcSpl(index,Xval,Poly)
int index;
real il:val;
PolyParms *Poly;
{
I*
Routine to calculate a value for Xval based on "Poly" and "index"
*
*
Written : 08-Jan-1987
Input : index
: which polynomal cofficient row to use row to
use from "Poly->Coff"
Xval (real) : the value to evaluate the function for.
Poly (PolyParms *) : the structure holding the cofficient
matrix
*
output
lint)
(real)
evaluation of polynomial "index" with value Xval.
*I
real diff,val;
diff = Xval- Poly->Time{index-1);
val= MVAL(Poly->Coff,index,l);
val += MVAL(Poly->Coff,index,2)*diff;
val+= MVAL(Poly->Coff,index,3)*diff*diff;
val+= MVAL(Poly->Coff,index,4)*diff*diff*diff;
return(val);
1-'
0
0
alpha[i]
1[0]
u[ 01
z!
oI
for
=
=
=
alpha[i]/!h[i-ll*h!il );
1.
0
o
o
o
(i=l;i<=n;i++) [
l[il = 2o*(Time[i+11-Time[i-11) - h[i-11*u[i-11;
u[i] = h[i]/l[i];
z[i] = (alpha[il - h[i-1]*z[i-11 )/l[il;
l[nl = 1.;
z [ n]
c[n]
for
= 0 o;
=
z[n];
(i=n-1 i>=O;i--) (
c[ I= z(i]- u[il • c[i+1];
b[ ] = ( (Vals[i+11 - Vals[i] )/hlil)
- ((h(i]*(c(i+ll + 2o*c[i]) )/3o );
d[i] = (c[i+11 - c(i] )/(3o*h[i] );
for(i=l;i<Nstep;i++)
MVAL!matrix,i,1)
MVAL(matrix,i,2)
MVAL(matrix,i,3)
MVAL(matrix,i,4)
Vals(i-11;
b [ i-11
c( i-ll
d[i-11
return( matrix);
~
0
~
;•
idg.h
•;
#include <stdio.h>
-define OOUBLEPREC
tdefine TRUE 1
#define FALSE 0
~include •
./header;system.h"
linclude • .. /header;rmat.h"
;include " .. ;header;triplet.h"
typedef struct PolyParms
Rmat •coff;
real *Time;
int NPoint;
r~al
(*Interpl( );
] PolyParms;
;•
typedef
Objlnfo
IdNumber;
int Type;
s~ruct
1nt
int
.. /
Status;
PolyParms XLoc,YLoc,ZLoc;
PolyParms X&ot,YRot,ZRot;
real •Time;
int ~Point; ] Objinfo;
typedef struct Caminfo
int IdNumber;
int Type;
int Status;
PolyParms XLoc,YLoc,ZLoc;
PolyParms XRot,YRot,ZRot;
real XPos,YPos,ZPos,XTheta,YTheta,ZTheta;
] Caminfo;
typedef Camlnfo Objinfo;
typedef struct RVector
real •data;
int NPoint; } RVector;
Caminfo *ActCamera;
fiLE
*dbfile,
*drfile,
•elog,
•scfile,
*fopen();
......
0
N
char dbname(40] ,drname(40],ername(40],scname(40];
RVector *Value(20]
,*Time(20];
**DBObjName;
char
•valueName(20), *TimeName(20);
char
char
*ObjectName(20), *InterpName(20);
char
*CameraName(20);
int TotAct, TotCrea, TotTimes, TotValues, Totlnst, Totinterp, TotOBObj;
int TotCam;
int *DBObjindex;
Objinfo •objs(20);
carninfo •cams(20);
Objinfo *mkinst ();
Caminfo *mkCaml);
Rmat *Lininterp();
Rmat *Splint-=rpl);
real E''alTime();
r"al CalcL.in I ) ;
r e a 1 C .1 l •: S p l ( ) ;
real
TimeSt~p,StartTime,EndTime;
......
0
w
APPENDIX E.
IG Routines
The following is a listing of the IG program.
104
rI
ll
Makefile to create IG program
#
ll
OBJECTS2 = creainst.o chnmat.o dev.o mulvert.o prior2.o \
link.o obstruct.o exedirect.o
LIBS
ig
ig.o
.. ;libjextra.a .. ;vas;vas.a -lm -lgs71
ig.o $(OBJECTS2)
cc -g -o ig ig.o
$(0BJECTS2) $(LIBS)
ig.c support.h
cc -g -c ig.c
creainst.o : creainst.c support.h
cc -g -c creainst.c
chnmat.o : chnmat.c .. /header;directs.h support.h
cc -g -c chnmat.c
exedirect.o : exedirect.c plink.h support.h .. /header/directs.h
cc -g -c exedirect.c
dev.o
dev.c support.h graph.h plink.h
cc -g -c dev.c
initobj2.o : initobj2.c support.h
cc -g -c initobj2.c
link.o
link.c plink.h support.h
cc -g -c link.c
matopers.o : matopers.c support.h
cc -g -c matopers.c
mulvert.o : mulvert.c support.h
cc -g -c mulvert.c
obstruct.o : obstruct.c plink.h support.h
cc -g -c obstruct.c
prior2.o : prior2.c .. ;header/directs.h support.h plink.h
cc -g -c prior2.c
support.h :
.. ;header;rmat.h .. ;header;triplet.h .. ;header;system.h
.....
0
Ul
I*
•
chnmat.c
*I
#include <math.h>
#include " .. lheaderldirects.h"
linclude "support.h"
real Vect[l6], Vect2[16];
Rmat tmat = [ 4, 4, Vect };
Rmat tmat2 = [ ~. 4, Vect2 };
chnmat(cmd,val,wmat)
int cmd;
real val;
Rmat *wmat;
[
I*
Routine to transform "wmat" with command "cmd" with value "val".
Written
25-Jun-1986
Input : cmd lint)
: determines which transformation matirx element(s)
will be modified.
val (real) : value t~ change matrix by .
wmat (Rmat *) : transformation matirx to modify.
•
Output : Wmat is modified.
*I
real xsave,ysave,zsave;
real a,ang,b;
int i;
SetidMat(&tmat);
switch(cmd)
case ROTX
ang = val*O.Ol745;
a= cos(ang);
b = sin(ang);
tmat.vect[ptr(&tmat,2,2)]
tmat.vect[ptr(&tmat,3,2) I
tmat.vect[ptr(&tmat,2,3)]
tmat.vect[ptr(&tmat,3,3)]
I* x rot *I
a;
-b;
b·
a;
.......
0
0'1
!lifdef DEBUG!
fprintf(elog,"%%I-chnmat
X rotation around camera, rads %f \n"
,ang);
llendif
break;
case ROTY:
ang = val*O.Ol745;
I* y rot *I
a= cos(ang);
b = sin(ang);
tmat.vect[ptr(&tmat,l,l)l =a;
tmat.vect[ptr(&tmat,3,1)1 = b;
tmat.vect[ptr(&tmat,l,3) I = -b;
tmat.vect[ptr(&tmat,3,3)1 =a;
llifdef DEBUG!
fprintf(elog,"%%I-chnmat : Y rotation around camera, rads %f\n"
, ang);
break;
!lendif
case ROTZ:
ang = val*O.Ol745;
I* z rot *I
a= cos(angl;
b = sin(ang);
tmat.vect[ptr(&tmat,l,lll =a;
tmat.vect[ptr(&tmat,2,1) I = -b;
tmat.vect[ptr(&tmat,1,2) I = b;
tmat.vect[ptr(&tmat,2,2) I = a;
hfdef DEBUG!
fprintf(elog,"%%I-chnmat : Z rotation around camera, rads %f\n"
,ang);
llendif
break;
case VIEWX:
tmat.vect[ptr(&tmat,1,4ll = l.lval;
I* set view from x *I
hfdef DEBUG!
fprintf(elog,"%%I-chnmat : View X : distance %f\n",val);
!lendif
break;
case VIEWl:
tmat.vect[ptr(&tmat,2,4ll
l.lval;
I* set view from y
hfdef DEBUG!
fprintf(elog,"%%I-chnmat : ViewY : distance %f\n",val);
#endif
break;
case VIEWZ:
#ifdef DEBUG!
fprintf(elog,"%%I-chnmat
View z
distance %f\n",val);
#endif
*I
1-'
0
-..J
if
(val== 0.)
tmat.vect(ptr(,tmat,3,4)1 = 0.;
else
tmat.vect(ptr(&tmat,3,4)1 = l.jval;
/* set view from z */
tmat.vect(ptr(&tmat,3,3) I = 0.;
break;
case TRANX:
tmat.vect(ptr(&tmat,4,1) I =val;
;• translate x dir. */
~ifdef DEBUG!
fprintf(elog,"%%I-chnmat : Translate x
distance %f \n",val);
#endif
break;
case TRANY:
tmat.vect(ptr(&tmat,4,2)1 =val;
I* translate y dir. */
hfdef DEBUG!
fprintf(elog,"%%I-chnmat : Translate y
distance %f \n",val);
#end i f
break;
case TRANZ:
tmat.vect(ptr(&tmat,4,3ll =val;
/* translate z dir. */
llifdef DEBUG!
fprintf(elog,"%%I-chnmat : Translate z
distance %f \n",val);
#endif
break;
case GBLS: tmat.vect(ptr(&tmat,4,4)] =val;
;• global scaling
*I
#ifdef DEBUG!
fprintf(elog,"%%I-chnmat : Global scaling factor %f \n",val);
#endif
break;
case SCALX: tmat.vect(ptr(&tmat,l,lll =val;
/* x scaling factor */
!lifdef DEBUG!
fprintf(elog,"%%I-chnmat : Axis scaling for X : %f \n",val);
#end if
break;
case SCALY: tmat.vect(ptr(&tmat,2,2) I = val;
I* y scaling factor *I
tlifdef DEBUG!
fprintf(elog,"%%I-chnmat : Axis scaling for y : %f \n",val);
llendif
break;
case SCALZ: tmat.vect(ptr(&tmat,3,3) I
val;
;• z scaling factor *I
llifdef DEBUG!
fprintf(elog,"%%I-chnmat : Axis scaling for z : %f \n",val);
#endif
break;
case ROTSX :
ang = val*O.Ol745;
;• x rot relitive object center*/
hfdef DEBUG!
fprintf(elog,"%%I-chnmat : X rotation around self, rads %f\n",ang);
#endif
.
......
0
00
a= cos(ang);
b = sin(ang);
MVAL(&tmat,2,2) = a;
MVAL(&tmat,3,2) = -b;
MVAL(&tmat,2,3) = b;
MVAL(&tmat,3,3) = a;
xsave = MVAL(wmat,4,1);
ysave = MVAL(wmat,4,2);
zsave = MVAL(wmat,4,3);
setidMat(&tmat2);
MVAL(&tmat2,4,1) = -xsave;
MVAL(&tmat2,4,2)
-ysave;
MVAL(&tmat2,4,3) = -zsave;
matmul(wmat,&tmat2);
break;
case ROTSY:
ang = val*0.01745;
llifdef DEBUG!
fprintf(elog,"%%I-chnmat
Y
hndif
a= cos(ang);
b = sin(ang);
MVAL(&tmat,l,l) =a;
MVAL(&tmat,3,1) = b;
MVAL(&tmat,l,3) = -b;
MVAL(&tmat,3,3) =a;
xsave = MVAL(wmat,4,1);
ysave = MVAL(wmat,4,2);
zsave = MVAL(wmat,4,3);
SetidMat(&tmat2);
MVAL(&tmat2,4,1) = -xsave;
MVAL(&tmat2,4,2) = -ysave;
MVAL(&tmat2,4,3) = -zsave;
matmul(wmat,&tmat2);
break;
case ROTSZ:
ang = val*0.01745;
llifdef DEBUG!
fprintf(elog,"%%I-chnmat
z
llendif
a= cos(ang);
b = sin(ang);
MVAL(&tmat,l,l) =a;
MVAL(&tmat,2,1) = -b;
MVAL(&tmat,1,2) = b;
MVAL(&tmat,2,2) =a;
=
I* y rot *I
rotation around self,
rads %f\n",ang);
I* z rot *1
rotation around self,
rads %f\n",ang);
1-'
0
1.0
xsave = MVAL(wmat,4,1);
ysave
MVAL(wmat,4,2);
zsave = MVAL(wmat,4,3);
SetidMat(&tmat2);
MVAL(&tmat2,4,1) = -xsave;
MVAL(&tmat2,4,2) = -ysave;
MVAL(&tmat2,4,3) = -zsave;
matmul(wmat,&tmat2);
break;
: fprintf(elog,"%%F-chnmat : command %d, not found \n",cmd);
fprintf(elog,"Program aborted \n");
exit();
break;
=
default
matmul(wmat,&tmat);
switch (cmd)
case ROTSX
case ROTSY
case ROTSZ
I*
l
MVAL(&tmat2,4,1) = xsave;
MVAL(&tmat2,4,2)
ysave;
MVAL(&tmat2,4,3) = zsave;
matmul(wmat,&tmat2).;
break;
=
prtmat(wmat); *I
.......
.......
0
I*
creainst.c
*
*I
#include <stdio.h>
linclude "support.h"
struct object *Creainst(ObjType,ObjTag)
int ObjType,ObjTag;
{
I*
*
*
*
Routine to create an instance of object "ObjType"
Written : 23-Nov-86
*
Input : ObjType (int)
obj·rag (inti
*
*
*
output : None.
*
Index number into "tobj" object table.
currently not used.
Returns a pointer to an object of type ObjType
Error Handler : Program will abort it can't allocate memory it needs
or if ObjType does not exist.
*I
int count;
int index,j,k;
float val,xval,yval,zval;
struct object *Temp;
if (tobj[ObjType].nvert == 0)
fprintf(elog,"%%F-Creainst
fprintf(elog,"%%F-Creainst
exit(l);
object %d not found~n",ObjType);
Program Aborted \n \n");
if ((Temp= (object*) calloc(l,sizeof(object))) ==NULL)
fprintf(elog,
"%%F-Creainst : could not allocate space for object\n");
fprintf(elog,"Program aborted \n ~n");
exit();
Temp->npoly
Temp->nvert
tobj[ObjType] .npoly;
tobj[ObjType] .nvert;
I*
......
......
......
* Set matrix information
*I
if ((Temp->mat.vect =(real*) calloc(l6,sizeof(real))) ==NULL) (
fprintf(elog,
"%%F-Creainst : could not allocate space for matrix,n");
fprintf(elog,"Program aborted 'n' n");
exit();
}
Temp->mat.imax = 4;
Temp->mat.jmax = 4;
SetidMat(&(Temp->mat));
I*
• Set vertex data
*I
if ( (Ternp->vert = (Vertex *I
calloc(tobj[ObjType).nvert,sizeof(Vertex))) ==NULL) (
fprintf(elog,
"%%F-Creainst : could not allocate space for vertex 'n");
fprintf(elog,"Program aborted 'n 'n");
exit ();
}
for(j=O;j<tobj[ObjType).nvert;j++) [
Temp->vert[j].x = tobj[ObjType].vert[j].x
Ternp->vert[j].y = tobj[ObjType].vert[j].y
Temp->vert[j].z = tobj[ObjType].vert[j).z
I*
Set polygon data
*I
if
((Temp->poly = (struct polygn *)
calloc(tobj[ObjType).npoly,sizeof(struct polygn))) ==NULL) [
fprintf(elog
,"%%F-Creainst : could not allocate space for polygon,n");
fprintf(elog,"Program aborted 'n'n");
exit();
}
fvr(j=O;j<Temp->npoly;j++) [
Temp->poly[j].nvert = tobj[ObjType] .poly[j].nvert;
Ternp->poly[j] .icolor = tobj[ObjType] .poly[j] .icolor;
Temp->poly[j] .vindex =
(int *)
calloc(tobj[ObjType].poly[j].nvert,sizeof(int));
f-'
f-'
N
for(k=O;k<tobj[ObjType].poly[j].nvert;k++) {
Temp->poly[j].vindex[k] = tobj[ObjType].poly[j].vindex[k];
return(Temp);
.·
.....
.....
w
"'
t'
;•
•
dev.c
•;
~include
"graph.h"
!I include "plink.h"
!I include
!Ide fine
!I define
#define
!I define
"support.h"
inside 1
outside 2
first
4
second 8
Graph!nit()
{
;•
•
Routine to set up RT one/80 for high resolution graphics mode
Written : ??-Oct-1986
•
tnput : None
Output : None : routine sets up some global variables and initializes
RT onej80 for use.
*I
winit(O);
gl$in1t(3,"dma");
gl$entgra();
gl$moddis(1);
g1$window(-639,-512,640,512);
gl$val8(0);
gl$clear();
g1$movabs(0,0);
g1$emptyb();
I-'
I-'
..,.
""
GraphOff()
{
I*
•
•
•
•
•
*I
Routine to turn off graphics stuff
Written : 10-Jan-1987
Input : none : uses only global variables
Output : none
if (Video == TRUE I I Record
gl$genlck(O);
TRUE)
J
gl$moddis(l);
gl$quit();
gl$stop(l);
1-'
1-'
U1
chardev[]
Recinit ()
"ldev;ttyh3";
[
I*
*
*
*
*
*
*
*
*
*I
Routine to set RT Onel80 up for NTSC video and initializes the
VAS unit for recording.
Written : ??-Oct-1986
Input : None
Output : Sets some global variables and initial1zes the VAS unit.
winit(l);
gl$init(3,"dma");
gl$entgra();
gl$moddis(l);
gl$genlck(l);
gl$emptyb();
i f ( ' ' mkchn(l,dev) !=TRUE) [
wquit( );
fprintf(elog,
"%%F-Recinit : could not open VAS term. \n");
fprintf(elog,"Program aborted \n,n");
exit ();
if (v prog(l,FrmPerRec,l,l,l) !=TRUE) [
wquit ();
fprintf!elog,
"%%F-Recinit : could not program VAS unit \n");
fprintf(elog,"Program aborted \n\n");
exit ();
if (v ee(l) l= TRUE)
wquit ();
fprintf(elog,
"%%F-Recinit : could not program find frame\n");
fprintf(elog,"Program aborted \n\n");
exit ();
gl$scrorg(320,-269);
gl$window(-319,-243,319,242);
gl$val8(0);
....
f-'
0'>
117
0
•• 0
~"'
.. .0
ftl
Ql
ftl
:>
...... 0
u I!
........
<IHJ>
"'"'
Vidinit()
{
I*
*
*
Routine to set RT Onej80 up for video display without recording
image to video tape.
*
*
Written : ??-Oct-1986
*
Input
output
: None
: None
sets up some global varibles and rigs the RT Onej80
up for NTSC video mode.
*I
winit(l);
gl$init(3,"dma");
gl$entgra ();
gl$moddis(l);
gl$scrorg(320,-269);
gl$window(-320,-243,319,242);
gl$genlckll);
gl$val8(0);
gl$clear ();
gl$movabs ( 0, 0);
gl$emptyb ();
I-'
I-'
00
wclear()
[
I*
*
Routine to clear graphics screen to background color.
*
*
Written : ??-Jun-1987
*
*
*
*
*I
Input
None
Output : None
causes RT ONEI80 to clear its screen
gl$val8(BKGRN);
gl$clear ();
I-'
I-'
1.()
wemptyb()
[
;•
•
Routine to flush RT Onej80 information out to buffer .
•
•
Written : ??-Jun-1987
•
Input : None
•
Output : None
*I
flush information out to frame buffer (RT Onej80) .
gl$emptyb();
1-'
N
0
winit(device)
int device;
[
I*
Routine to initialize graphic device
Device dependent routine.
Written
•
??-Jun-1986
Input : device (int)
output
None
determine the type of device configuration to
run.
sets up global structure "screen"
*I
switch (device)
case
0 : screen.imin
screen.imax
case
1
screen.jmin
screen.jmax
break;
sc::een.imin
screen.imax
screen.jmin
screen.jmax
break;
screen.idiff
screen.jdiff
-640
640
-512
512
-320
320
-256
256
screen.imax
screen.jmaK
screen.imin;
screen.jmin;
.......
N
.......
wpoly2(Poly)
struct plink *Poly;
[
I*
Routine to write out polygon out to frame buffer.
*
*
*
Written : ??-Jun-1986
*
*
Input : Poly (plink *)
*
Output : none : Information is written out to the frame buffer.
: pointer to polygon structure
*
*I
int i,j;
int ivect[60],temp(4],npoint,status;
0;
for
i=O; npoint = 0;
(i=O i<(Poly->poly->nvertl;i++) {
vect[npoint] = xddi(Poly->poly->vert2(i}->x);
vect[npoint+l] = yddj(Poly->poly->vert2[i]->y);
npoint += 2;
npoint = Poly->poly->nvert;
I*
* Blank out area where the polygon is going and draw polygon
*I
gl$prmfil(l); gl$val8(0);
gl$polygn(l,&npoint,ivect);
gl$emptyb( );
I*
* Draw polygon
*I
gl$prmfil(l); gl$val8(Poly->poly->icolor);
fprintf(elog,"wpoly2 %d \n",Poly->poly->icolor);
gl$polygn(l,&npoint,ivect);
gl$emptyb( );
......
I\)
I\)
wquit(
[
I*
Routine to terminate graphics mode
*
Written : ??-Jun-1986
*
*
*
*
Input : None : Uses global variable Video to determine if GENLOCk
was used.
"Video" is set in P2GetArgs
Output
None : Tell RT Onel80 to exit graphics mode/
*I
if (Video== TRUE) gl$genlck(0);
gl$quit();
~
N
w
wrecord()
[
I*
*
Routine to tell recording device to record a single images
*
*
Input
*
*
Output : None
None
an image is recorded
*I
v_rec(l);
.......
N
~
wwait(seconds)
int seconds;
(
;•
Routine to cause the frame buffer to wa·it for "seconds" before
writing anything eles out to the device.
Written
Input
•;
??-Jun-1986
seconds ( int)
: number of seconds to wait
Output : None : causes RT One/80 to rest a spell
gl$wait(seconds•6Q);
1-'
tv
Ul
xddi(x)
real x;
[
;•
Routine to convert x world coordinate to physical screen coordinate
Written
??-Jun-1987
Input : x (real)
*
•;
return
output
: x world coordinate to convert to screen coorindate
returns an integer of the physical screen coordinate
(int)(x
* (real)(screen.idiff)jworld.xdiff) );
t-'
N
0'
yddj(y)
real y;
I*
Routine to convert y world coordinate to physicaL screen coordinate
*
*
Written
*
*
Input : y (real)
*
*
??-Jun-1987
: y world coordinate to convert to screen coorindate
output : returns an integer of the physical screen coordinate
*I
return(
( int) (y
* (real) (screen. jdiff )lworld.ydiff) ) ;
1-'
N
-._]
I*
*
*
exedirect.c
*
*I
#include <stdio.h>
#include <math.h>
~include " .. lheaderjdirects.h"
#include "support.h"
#include "plink.h"
ExeDirect()
{
I*
*
Routine to read in directives from "drfile" and execute them.
Written 17-Nov-1986
*
*
*
Input : Reads information from "scfile"
output :
(none)
*I
float tval,tval2[4];
real val,dval[4);
struct object *Creainst();
I*
* "TotAct" total number of active objects for this cycle
*I
int TotAct,CurAct;
int i,j 1 iobj,direct,ObjType;
CurAct
TotAct
=
=
0;
0;
while(fscanf(drfile,"%d %d %f",&direct,&iobj,&tval) != EOF) {
if (direct == DISPLAY) {
fprintf(elog
,"%%I-ExeDirect : Display at time %f \n",tval);
PriObj(CurAct,objlst);
#ifdef LEVELl
ListNodes(DspLst);
llendii
if (Display == TRUE)
1-'
N
00
""'
wclear();
DspPolys(DspLst);
if (Video == TRUE
I I Graphics== TRUE) wwait(4);
wemptyb();
if (Record == TRUE) {
if (wrecord(l) !=TRUE)
wquit();
fprintf(elog,"%%F-ExeDirect : cannot record\n");
fprintf(elog,"Program aborted \n");
exit();
}
free(vtable);
free(vtable2);
free(ptable);
dAllocDspLst(&DspLst);
else if (direct == VIEWZ) [
ProjectPt.vert.z = tva!;
else if (direct >= 0 && direct <= LASTPRIM) [
val = tval;
chnmat(direct,val,&(objlst[iobj}->mat) );
else if (direct == SETWLDC) {
I*
• Set world corrdinates
*I
fscanf(drfile,"%f %f %f %f"
,&tval2[0),&tval2[l),&tval2[2),&tval2[3));
world.xmin ~ (real) tval2[0);
world.ymin = (real) tval2[1);
world.xmax = (real) tval2[2);
world.ymax = (real) tval2[3);
world.xdiff = world.xmax - world.xmin;
world.ydiff = world.ymax - world.ymin;
I*
•;
else if (direct == CREAINST) {
fscanf(drfile,"%d",&ObjType);
objlst[iobj) = Creainst(ObjType,iobj);
prtmat(&(objlst[iobj)->mat) );
To tAct++;
Cur Act++;
1-'
N
\0
else if (direct == RESETMAT) {
Setconst(objlst[iobj]);
else if (direct == DSBL!NST) {
To tAct--;
objlst[iobj]->status I= DISABLED;
else if (direct == FIXROTSX)
objlst[iobj]->xsrot = (real) tval;
else if (direct == FIXROTSY)
objlst[iobj]->ysrot = (real) tval;
else if (direct == FIXROTSZ)
objlst[iobj]->zsrot = (real) tval;
else if (direct == FIXSCALX)
objlst[iobj]->xscale = (real) tval;
else if (direct == FIXSCALY)
objlst[iobj]->yscale = (real) tval;
else if (direct == FIXSCALZ)
objlst[iobj]->zscale = (real) tval;
else if (direct == FIXTRANX)
objlst[iobj]->xcent = (real) tval;
else if (direct == FIXTRANY)
objlst[iobj]->ycent = (real) tval;
else if (direct == FIXTRANZ)
objlst[iobj)->zcent = (real) tval;
else if (direct == STOP) {
return(!);
else
fprintf(elog,"%%F-ExeDirect
direct);.
fprintf(elog,"%%F-ExeDirect
exit ();
unknown directive %d \n",
Program terminated \n");
......
w
0
SetConst(Obj)
object *Obj;
[
I*
*
*
Routine to set constant values for "Obj"'s transformation matrix
Written : 27-Jan-87
*
*
Input : Obj
*
*
*I
Output
(struct object *)
object who's transformation is to
changed.
(none) modifications to "Obj" transformation matrix.
SetidMat(&(Obj->mat));
if (Obj->xscale != 0.) MVAL(&(Obj->mat),l,l) = Obj->xscale;
i f (Obj->yscale != 0.) MVAL(&(Obj->mat) ,2,2) = Obj->yscale;
i f (Obj->zscale != 0.) MVAL(&(Obj->mat),3,3) = Obj->zscale;
if. (Obj->xsrot
if ·cobj->ysrot
if (Obj->zsrot
= 0.) chnmat(ROTSX,Obj->xsrot,&(Obj->matl)
= 0.) chnmat(ROTSY,Obj->ysrot,&(Obj->mat))
= 0.) chnmat(ROTSZ,Obj->zsrot,&(Obj->mat))
(Obj->xcent
if (Obj->ycent
i f (Obj->zcent
= 0.) MVAL(&(Obj->mat),4,1) = Obj->xcent
= 0.) MVAL(&(Obj->mat) ,4,2) = Obj->ycent
= 0.) MVAL(&(Obj->mat),4,3) = obj->zcent
if
,.....
w
,.....
I*
*
ig.c
*
*I
#include <stdio.h>
~include "support.h"
~include "plink.h"
char progName( I = "Prismlig";
main(argc,argv)
int argc;
char **argv;
{
int i,j;
I*
* Initialize systemlgloballdefault values
*I
P2Sysinit();
I*
* Read in command line arguments
*I
P2GetArgs(argc,argv);
I*
• Open files
*I
P20penFiles( );
I*
* Initialize system.
*I
if (Graphics== TRUE) Graphinit( );
if (Video== TRUE) Vidinit( );
if (Record== TRUE) Recinit( );
I*
• Gathter data on objects
*I
1-'
w
N
GatherObj( );
I*
* Execute directives
*I
ExeDirect();
I*
* Turn off graphics stuff
*I
if !Display
TRUE) GraphOff();
I*
• That's all folks
*I
exit ();
1-'
w
w
Gatherobj ()
[
I*
*
*
*
*
*I
Routine to read in object information form object data base file.
Routine assumes that "dbfile" has been ~pened for reading.
Written : 14-0ct-86
char name[20);
int i,index,j,k;
float val,xval,yval,zval;
int count;
count = 0;
fscanf(dbfile,"%d",&totobj);
for(i=O;i<totobj;i++) (
fscanf(dbfile,"%d %s",&index,name);
tobj[index).ident =index;
strcpy(tobj[index].name,name);
fscanf(dbfile,"%d %d",&tobj[index] .npoly,&tobj[index] .nvert);
totpoly += tobj[index] .npoly;
totvert += tobj[1ndex) .nvert;
I*
* Generate translation matrix
*I
tobj[index].mat.vect = (real *) calloc(16,sizeof(real) );
tobj[index].mat.imax = 4; ·
tobj[index] .mat.jmax = 4;
SetidMat(&(tobj[index].mat) );
I*
* Read in verticies of object
*I
tobj[index].vert = (Vertex *)
calloc(tobj[index] .nvert,sizeof(Vertex));
for(j=O;j<tobj[index].nvert;j++) (
fscanf(dbfile,"%f %f %f",,xval,&yval,,zval);
tobj[index].vert[j] .x = xval;
tobj[index].vert[j].y = yval;
tobj[index].vert!j].z = zval;
I*
*
Read in polygon data
*I
tobj[index].poly = (struct polygn *)
calloc(tobj[index] .npoly,sizeof(struct polygn) );
1-'
w
"""
{
fscanf(dbfile,"%d %d"
,&tobj[index] .poly[j].nvert
,&tobj[index] .poly[j] .icolor);
tobj[index].poly[j].ident =count++;
tobj[index].poly[j].vindex =
(int *)
calloc(tobj[index].poly[j] .nvert,sizeof(int));
for(k=O;k<tobj[index].poly[j].nvert;k++) {
fscanf(dbfile,"%d",&tobj[index] .poly[j].vindex[k] );
for(j=O;j<tobj[inde~].npoly;j++)
1-'
w
U1
dAllocDspLst ()
{
I*
*
*
*
*
*
Routine to deallocate space taken up by polygons
Written : ??-Oct-1986
Input : None.
Uses global variables
Output : None.
*I
struct plink *temp,*temp2;
temp = DspLst;
while (temp != NULL) {
free(temp->poly->vert);
free(temp->poly->vert2);
temp2 = temp->next;
free(temp);
temp = temp2;
DspLst
= NULL;
......
w
m
DspPolys(Listl
struct pl1nk *List;
I*
*
Routine to place polygons on screen in order from "List"
*
Written : 24-0ct-1986
*
*
Input : List (struct plink *)
to device
*
output
*
(none)
the list of polygons to write out
Routine writes out to the graphics device.
*I
{
struct plink *temp;
temp = List;
while (temp != NULL)
if (btest (temp-> poly-> status, BEYOND)
wpoly2(temp);
temp
!
=
TRUE)
temp->next;
1-'
w
.......,
char Usage[] = "usage: %s
[-f number]\n";
P2GetArgs(argc,argv)
int argc;
char **argv;
I*
*
[-g]
[-r]
[-v]
[-d directfile]
[-o objfile]\
Routine to read in command line arguments
Written : 07-Jan-1987
Input
output
argc ( int) : number of arguments.
argv lchar **):array of arguments.
(none)
: But global variables are set within this routine.
*I
int i;
for(argc -=l,argv+=l;argc>O;argc--,argv++)
if ( * *argv == '-')
switch (*++(*argv))
case
'g'
I*
* display on graphics device
*I
Graphics = TRUE;
Display = TRUE;
break;
case
'v'
I*
* run on ntsc video
*I
Video = 'll'RUE;
Display = TRUE;
break;
case
'r'
I*
* run on ntsc video
*I
Record = TRUE;
Display = TRUE;
break;
case
'd'
I*
* specified directive file
*I
1-'
w
00
strcpy(drname,*(++argv));
argc--;
break;
case
'e'
I*
* specified error file
*I
strcpy(ername,*(++argv));
argc--;
break;
case
'o'
I*
* specified object data base
*I
strcpy(dbname,*(++argv));
argc--;
break;
case
'f'
I*
* specified number of frames per record
*I
FrmPerRec
argc--;
break;
=
atoi( *(++argv));
default
I*
* error in parameter
*I
fprintf(stderr,Usage,progName);
exit();
break;
.......
w
\0
P20penFiles()
(
;•
Routine to open major files for Phase2.
•
•
•
Written : 07-Jan-1987
Input :
output :
(none)
(none)
: uses global variables .
: modifies global variables .
•;
if ( (elog = fopen(ername,"w")) ==NULL) (
fprintf(stderr,"Error in opening error.log \n");
perror("%F-P20penFiles ");
fprintf(stderr,"Program aborted\n");
exit ( ) ;
if ( (dbfile = fopen(dbname,"r")) ==NULL)
fprintf(stderr,"Error in opening object.dat \n");
perror("%F-P20penFiles ");
fprintf(stderr,"Program aborted\n");
exit();
if ((drfile = fopen(drname,"r")) ==NULL)
fprintf(stderr,"Error in opening direct.dat \n");
perror("%F-P20penFiles ");
fprintf(stderr,"Program aborted\n");
exit ();
......
ol:>o
0
P2Sysinit()
[
I*
Routine to initialize default andlor global values
*
*
*I
Written
19-Nov-1986
I*
* set up default file name for data base and directive files
*I
strcpy(dbname,"object.dat");
strcpyldrname,"direct.dat");
strcpy(ername,"error.log");
I*
* set up global scrach matries
*I
al.imax
a2.imax
4; a1.jmax
4; a2.jmax
4; al.vect
a2.vect
4:
vect;
vect2;
I*
* set up default global world corrdinates
*I
world.xmin = -1.; world.xmax = 1.;
world.ymin = -1.; world.ymax = 1.;
world.xdiff = wor1d.xmax - world.xmin;
world.ydiff = world.ymax - world.ymin;
world.kluge = 1.1;
I* world.xmax + world.xmax*.l
*I
I*
* Set values in parameter input flags
*I
Display = FALSE;
Record
FALSE;
Video = FALSE;
Graphics = FALSE;
=
I*
* Set some global counting values up
*I
1-'
of>.
1-'
totpoly
totvert
totobj
= 0;
= 0;
= 0;
I*
* Number
*I
of frames to record on a record command
FrmPerRec = 1;
......
""'
(\)
I*
*
link.c
*
*I
#include <stdio.h>
#include "plink.h"
#include "support.h"
AppndLst(Node,List)
struct plink *Node,**List;
I*
*
*
*
*
*
Routine to append "Node" to link list "List"
Input : Node (plink *)
List (plink**)
output : None.
Node to append
: List to append to.
: List is modified
*I
[
if (*List== NULL)
*List = Node;
(*List)->last
(*L1st)->next
Node;
NULL;
else
(*List)->last->next =Node;
Node->last = (*List)->last;
Node->next = NULL;
(*List)->last =Node;
.....
"""
w
Connect(Nvert,List)
int Nvert;
struct plink *List;
I*
*
Routine to connect all the plinks of array List
*
*
Input: Nvert ( i n t ) : number of vertices to connect.
List (plink*): Array of plinks to connect.
*
*
output
•
: None.
*I
{
int i.
for(i=O;i<Nvert-l;i++) {
List(i].next = ii<List[i+l];
List(i+l].last = ii<List(i];
}
Lst(i].next
L st(i].last
L st{Oj.last
NULL;
ii<List[i-1];
ii<List[i];
1-'
"".r>
DelNode(Node,List)
struct plink ~Node,**List;
I*
Routine to delete node "Node" off of link list "List"
*
Input : Node (plink •) : Node to delete
List (plink**): List to delete off of
output : None.
: List is modified.
*I
{
struct plink *temp;
if
(~List
Node)
I*
* Case of deleting the first Node off of List
~I
if((*List)->next ==NULL)
I*
* Only one node on List
*I
*List
NULL;
else {
I*
* More than one node on list.
*I
temp= (*List)->last;
*List= (*List)->next;
(*List)->last =temp;
else
I*
* Not deleting first node.
*I
Node->last->next = Node->next;
if (Node->next != NULL) Node->next->last
Node-> last;
.....
""'U1
FirstNode(Node,List)
struct plink *Node,**List;
[
I*
*
*
*
*
*
*
*I
Routine to insert node at the front of .a list
Input : Node (plink *) : Node to insert
List (plink **) : List to insert into.
Output : None.
: List is modified.
Node->next = *List;
Node->last = (*List)->last;
*List = Node;
1--'
""'0'1
InsertNode(Node,List,Ahere)
struct plink *Node,**List,*Ahere;
I*
•
•
Routine to insert "Node" after node "Ahere" in "List"
Special case of this routine is the insertion of Node as the
first element of the List
*
Input
•
•
•
•
•
•
Node (plink*): Node to insert.
List (plink ••) : List to insert into
Ahere (plink *) : Node to insert after .
Output : None.
: List is modified.
*I
[
if
==
(*List
NULL)
*List
Node;
(*List)->next
(•List)->last
return(O);
=
NULL;
Node;
.Node->next = Ahere->next;
Node->last = Ahere;
Ahere->next->last
Node;
Ahere->next = Node;
=
1-'
~
-...]
ListNodes(List)
struct plink *List;
/*
List the elements of linked list "List"
*
Input : List (plink *) : List to print out
*
*
*
Output : None.
*/
[
int i,j;
struct plink *temp;
i = 1;
temp = List;
while (temp != NULL) {
fprintf(elog,"ident : %d \n",temp->poly->ident);
fprintf(elog,"icolor : %d \n",temp->poly->icolor);
fprintf(elog,"xmin : %f, xmax : %f \n",
temp->poly->xmin,temp->poly->xmax);
fprintf(elog,"ymin : %f, ymax : %f \n",
temp->poly->ymin,temp->poly->ymax);
fprintf(elog,"zmin : %f, zmax : %f \n",
temp->poly->zmin,temp->poly-•zmax);
fprintf(elog,"status : %o \n",temp->poly->status);
fprintf(elog,"vsign :
%d \n",temp->poly->vsign);
fprintf(elog,"normal : %f %f %f \n"
,temp->poly->normal.x
,temp->poly->normal.y
,temp->poly->normal.zl;
for(j=O;j<temp->poly->nvert;j++)
fprintf(elog,"element %d value %f %f %f %f %f %f\n"
,j,temp->poly->vert[j)->x
,temp->poly->vert[j)->y
,temp->poly->vert[j)->z
,temp->poly->vert2[j)->x
,temp->poly->vert2[j)->y
,temp->poly->vert2[j)->z);
temp = temp->next;
fprintf(elog,"=========================================\n");
f-'
""'
(X)
I*
*
*
*
*I
mulvert.c
#include "support.h"
mulvert(nvert,vertl,vert2,transmat)
int nvert;
Vertex vertl[).vert2[);
Rmat *transmat;
[
I*
*
*
*
*
*
*
Routine to take "nvert" verteies of "vert!" and multiply
them by the translat1on matrix "transmat" and place the results'
in
~vert2"
Written : 23-0ct-86
*
Input : nvert ( int) : number of vertices to multiply
vert! (Vertex *) : orginal vert1cies
transmat (Rmat *) : translation matrix to multiply vert1 by.
*
Output
vert2 (Vertex
*)
Array to put results into.
*I
int i,j,npoint;
Rmat temp;
real vect[4);
temp.imax = 1;
temp.jmax = 4;
temp.vect = vect;
c
for(i=O;i<nvert;i++) {
temp.vect[O) = vert1[i) .x;
temp.vect[1) = vert1[i].y;
temp.vect[2] = vert1[i).z;
temp.vect[3] = 1.0;
matmul(&temp,transmat);
ltifdef DBUG
fprintf(elog,"back in mpoly \n");
prtmat (&temp);
#endif
vert2 [i ].x
temp.vect[O)Itemp.vect[3)
vert2[i) .y
temp.vect[1]1temp.vect[3]
vert2[i).z
temp.vect[2)jtemp.vect[3)
1-'
~
U)
I*
*
*
*
obstruct.c
*I
tinclude
tinclude
tinclude
tinclude
<stdio.h>
"support.h"
"plink.h"
<math.h>
I*
*
TOL is the tolerence for numbers close to zero.
*I
tdefine TOL l.e-6
real EvalPoint ();
CalcNor(Poly)
struct polygn2 *Poly;
I*
Routine to caculate normal of polygon "Poly"
*
Written Sept-25-1986
•
Input : Poly ( struct polygn2)
: polygon determine normal for
Output : None : structure polygon "Poly" is modified
•
*I
real ul,u2,u3,vl,v2,v3;
ul
u2
u3
=
=
=
vl
v2
v3
=
=
Poly->vert{l)->x - Poly->vert{O)->x;
Poly->vert{l)->y - Poly->vert{O)->y;
Poly->vert[l)->z- Poly->vert{O)->z;
= Poly->vert{2]->x-
Poly->vert{O)->x
Poly->vert{2)->y- Poly->vert{O)->y
Poly->vert{2]->z - Poly->vert[O)->z
Poly->normal.x
Poly->normal.y
Poly->normal.z
u2*v3 - u3*v2;
u3*vl - ul*v3;
ul*v2 - u2*vl;
.....
U1
0
real EvalPoint(Poly,Point)
struct polygn2 *Poly;
Vertex *Po1nt;
{
I*
•
•
*
Point-normal formula equation for a plane .
(see Anton 3rd ed of Elementary Linear Algebra, pg. 117) .
Caculates the Point-normal value of "Point" with respect to
polygnon "Poly".
•
Written : 25-Sept-1986
•
•
Input : Poly (struct polygn2 *) : the plane to test against .
Point (Vertex *) : the point to test against .
,..
output : val (real)
•
Evaluation of point-normal formula.
*I
real val;
val =
Poly->normal.x * (Point->x- Poly->vert[O]->x)
+ Poly->normal.y • (Point->y- Poly->vert[O]->y)
+ Poly->normal.z * (Point->z - Poly->vert[O)->z);
if (fabs(val)
return(val);
<TOLl val= 0.;
......
01
......
Obstruct(P,Q)
struct polygn2 *P,*Q;
[
I*
*
*
Routine to see if polygon "P" obstructs polygon "Q".
*
Written
*
*
*
Input : P (struct polygn2 *)
Q (struct polygn2 *)
*
*
*
*I
29-Sept-1986
base polygon in obstruction test.
candidate polygon.
Output : TRUE or FALSE : if •p• obstructs "Q" return TRUE
else FALSE.
I*
• Disjoint in X ? If disjoint, then no overlap in x direction
•
==> no obstruction.
*I
·if
(IP->xmax < Q->xmin)
return( FALSE);
I I (Q->xmax < P->xmin))
I*
• Disjoint in Y ?.
If disjoint, then no overlap in y direction
==> no obstruction
*I
if
((P->ymax < Q->ymin)
return(FALSE);
I I (Q->ymax < P->ymin))
I*
* Determine Planar relationship
*I
I*
* if results 0 or 1 then Q is in front of P
*I
if
(Planar(P,Q)
POS)
return(FALSE);
I*
• if results 0 or -1 then P is in behind of Q
*I
if
(Planar(Q,P)
NEG)
return(FALSE);
......
Ul
N
153
01
.....
l)
::l
....
.....
"'0
.c
c::
IU
l)
p,
"'
"'
IV
IU
l)
.....
.....
,
IU
IV
.....
.....
IU
"' .......
~
.......
. .
"':::>
~
E-<
c::
....
::l
.....
IV
....
Planar(Polyl,Poly2)
struct polygn2 *Polyl,*Poly2;
I*
*
Routine to establish planar relationship between "Polyl" and "Poly2".
*
Written :
*
*
*
*
Input
*
output
29-Sept-1986
: Polyl
Poly2
(struct polygn *)
(struct polygn *)
first polygon in planar test.
second polygon in planar test.
one of three values
*
"POS" if "Poly2"'s plane is in frdnt of "Polyl"'s plane with
respect to the view point.
*
*
*
"NEG" if "Poly2"'s plane is behind "Polyl"'s plane with
respect to view point.
*
*
"0" if polygon planes are co-planar or if they intersect.
*
*I
int direct,i,same;
real val;
i = 0;
val= 0.;
I*
* find first point that is not co-planar between "Polyl" and "Poly2"
*I
while
(val==O. && i< Poly2->nvert) (
val= Eva1Point(Polyl,Poly2->vert(i));
i++;
if(val==0.)
return(O);
else
if (val> 0.)
direct
else
direct
POS;
NEG;
same = TRUE;
while
(same == TRUE && i< Poly2->nvert)
,.....
U'
.r·.
val = Eva1Point(Polyl,Poly2->vert[i) );
if ((val < 0. && direct== POS) I I
(val > 0. && direct ==NEG)) same= FALSE;
i++;
if (same == FALSE)
return(O);
else
return(direct*Polyl->vsign);
.......
01
01
/*
*
*
*
prior2.c
*/
#include <stdio.h>
#include <math.h>
#include " .. /header/directs.h"
~include "support.h"
#include "plink.h"
real EvalPoint();
PriObj(nobj,objlst)
int nobj;
struct object *objlst[);
/* number of objects
*/
/* table containing list of objects to be */
/*
sorted
*/
/*
Main routine for polygon sorting.
It is assumed that by this
point that the objects• transformation matrix have been completed .
This is where depth sorting starts from .
*
•
•
Written : 23-0ct-1987
Input
Output
•
: nobj (int) number of object to be in "objlst".
objlst (struct object **) : pointer table to actual instances
of objects.
None.
Generates a linked list of polygns to be displayed
on the screen.
*/
int beyon,i,j,k,l,m,n,poffset,voffset,totpoly,totvert;
Vertex **vtemp,**vtemp2;
totpoly = 0;
totvert = 0;
/*
•
allocate space for new vertex table from points of
objects in question.
*/
for
(i=O;i<nobj;i++) [
if (btest(objlst[i)->status,OISABLED)
totvert += objlst[i)->nvert;
!= TRUE)
.......
U1
0'1
totpoly += objlst(i]->npoly;
vtable
vtable2
ptable
I*
*
*I
(Vertex*) calloc(totvert,sizeof(Vertex));
(Vertex *) calloc(totvert,sizeof(Vertex) );
(struct polygn2 *) calloc(totpoly,sizeof(struct polygn2) );
load modified verties into new vertex table
poffset = 0;
vaffset = 0;
SetidMat(&a2);
CalcKluge ();
chnmat(VIEWZ,ProjectPt.vert.z,&a2);
a2.vect[ptr(&a2,4,4)] = 0.;
for (i=O;i<nobj;i++) {
if (btest(objlst(i]->status,DISABLED)
!= TRUE) {
I*
*
Multiply objects by tranformation matrix
for proper transformation.
*I
mulvert(objlst[i]->nvert
,objlst[i]->vert
,&vtable[voffset]
,&(objlst[i]->mat) );
I*
* Determine if polygon is out of view with regards to
* projection point
*I
for
(k=O; k<objlst[i]->nvert;k++) {
if (vtable[vaffset+k].z <= ViewPoint.vert.z)
vtable[voffset+k] .z = world. kluge;
I*
Multiply objects by projection matrix for proper
perspective
*I
mulvert(objlst[i]->nvert
I-'
U1
-...]
,&vtable(voffset]
,&vtable2(voffset]
, &a 2);
I*
* Work on individual polygons of an object
*I
for
(j=O;j<objlst(i]->npoly;j++) [
m = sizeof(Vertex *) * objlst(i]->poly[j].nvert;
vtemp = (Vertex **) calloc(objlst(i]->poly(j].nvert,
sizeof(Vertex *));
vtemp2 = (Vertex **) calloc(objlst(i]->poly[j].nvert,
sizeof (Vertex *));
if (vtemp == NULL I I vtemp2 == ~ULL)
fprintf(elog,"error in space allocation \n");
exit( l;
I*
*
*
*I
m
Get addresses of vtable locations of
the verties and place them in an array
for quick lookup.
=
0;
ptable[j+poffsetl.status = 0;
ptable(j+poffset].vert = vtemp;
ptable(j+poffset].vert2
vtemp2;
for (k=O;k<objlst[i]->poly(j].nvert;k++)
1 = objlst[i]->poly(j].vindex[k];
if (vtable[l+voffset] .z == world.kluge) m++;
ptable(j+poffset].vert(k]
&vtable(l+voffset];
ptable(j+poffset].vert2(k] = &vtable2(1+voffset];
=
=
}
ptable[j+poffset].nvert = objlst(i]->poly(j].nvert;
ptable(j+poffset].ident
objlst(i]->poly(j].ident;
ptable(j+poffset].icolor = objlst(i}->poly(j] .icolor;
if (m == ptable(j+poffset].nvert)
ptable(j+poffset].status I= BEYOND;
FndVals(&ptable(j+poffset]);
CalcNor(&ptable[J+poffset]);
if (EvalPoint(&ptable(j+poffset],&ViewPoint.vert) > 0.)
ptable(j+poffset].vsign = 1;
else
ptable(j+poffset] .vsign = -1;
=
._.
Ul
CP
poffset += objlst[i)->npoly;
voffset += objlst[i)->nvert;
I*
*
Allocate structure needed for PolySort()
*I
if((plist = (plink*) calloc(totpoly,sizeof(plink))) ==NULL) {
fprintf(elog,
"%%F-PriObj, cannot allocate space for '"plist'"\n");
fprintf(elog,"Program aborted
'n ");
exit ():
'n
for(i=O;i<totpoly;i++) {
plist[i).poly = &(ptable[i));
PolySort(totpoly);
Connect(totpoly,plist);
Hidden(plist);
I*
*
All done,
return space back to system
*I
free(plist);
......
U1
\0
apDspLst(PolyLnk)
plink *PolyLnk;
[
I*
*
*
Routine to create and append a a plink structure to a Display
list.
*
Input
*
*
*
output : None.
PolyLnk (plink *)
to display list.
plink structure with data to append
: Modified PolyLnk.
*I
struct plink *temp;
if( (temp= (struct plink *) calloc(l,sizeof(plink) )) ==NULL)
fprintf(elog,"%%F-apDspLst, cannot allocate space for ");
fprintf(elog,"polygon link \n");
fprintf(elog,"Program aborted \n\n");
exit();
AppndLst(temp,&DspLst);
temp->poly = PolyLnk->poly;
1-'
0'\
0
CalcKluge()
{
/*
*
*
*
*
*
*
*
*
Routine to caculate a kluge (the mininum z value allowed) value as a
function of the world space.
This routine is used in PriObj() to keep polygon coordanates from
getting too large with repsect to the device world window.
The current kluge is the maximum value in either the x or y directions
plus ten percent of that value.
Written : 01-Jan-1987
*
Input
: none.
output : none.
*/
real temp[4],temp2,max;
int i;
temp[O]
temp [ 1]
temp[2]
temp[3]
world.xmax;
world.xmin;
•.•orld.ymax;
world.i•max;
max= fabs(temp(O]);
for(i=1;i<4;i++l {
temp2 = fabs(temp[i] );
if (temp2>max) max = temp2;
world. kluge
max*.OOl/ProjectPt.vert.z;
......
~
......
dAllocPLnk(Link)
struct plink **Link;
{
I*
*
*
Routine to free space taken up by elements of "Link"
Input : Link (plink **)
: pointer to link to release
Output : None.
*I
struct plink *temp;
temp = *Link;
whLle (temp !=NULL)
free(temp);
temp = temp->next;
*Link = NULL;
.....
0'1
1\J
struct plink *
FindNxtP(List)
struct plink *List;
I*
Routihe to file next empty link in "List"
*
*
*
*
*I
Input : List (plink
*)
:
pointer to a linked list
output : None : returns a pointer of type plink to the first
empty link.
struct plink *temp;
temp = List;
while (temp !=NULL){
if (btest(temp->poly->status,INUSE) != 1)
temp->poly->status = temp->poly->status
return(temp);
temp
return (temp);
I INUSE;
temp->next;
·.
1-'
0\
w
FndVals(poly)
struct polygn2 *poly;
I*
*
Routine to find the minimum and maximum value of a polygon
*
Written : 23-0ct-1987
*
*
Input : poly (polygn2 *)
*
*
output : None.
Polygon to search through
*I
[
int i;
real xmin,xmax,ymin,ymax,zmin,zmax;
xmin
xmax
ymin
ymax
zmin
zmax
for
if
if
if
if
if
if
poly->vert[O)->x;
poly->vert[O)->x;
poly->vert[O)->y;
poly->vert[O)->y;
~oly->vert[O)->z;
poly->vert[O)->z;
(i=O;i<poly->nvert;i++)
(poly->vert[i)->x < xmin)
(poly->vert[i)->x > xmax)
(poly->vert[i)->y < ymin)
(poly->vert[i]->y > ymax)
(poly->vert[i]->z < zmin)
(poly->vert(i]->z > zmax)
poly->xmin
poly->xmax
poly->ymin
poly->ymax
poly->zmax
pol;•-> zmin
xmin
xmax
ymin
ymax
zmin
zmax
poly->vert[i]->x;
poly->vert[i)->x;
poly->vert[i]->y;
poly->vert[i)->y;
poly->vert[i)->z;
poly->vert[i)->z;
xmin;
xmax;
ymin;
ymax;
zmax;
zmin;
.......
0'1
"""
Hidden(PList)
plink *PList;
[
I"
"
"
"
"
"
"
"
"
"
"
...*
*
"
"
"I
Main routine to determine which order to order polgyons for
displaying.
See page 247 of "Procedural Elements for Computer Graphics" by
Rogers
Major variables
setQ in the link list of polygons to test PolyP against.
PolyP is the polygon that is currently being checked.
PolyQ is the polygon from SetQ that is currently being check
from SetQ.
Input : PList (plink *)
Output : None.
linked list of polygons .
PList is resorted with polygons written out in
depth sorted order.
struct plink *List,*SetQ,PolyP,PolyQ,*curQptr,*curLptr;
struct plink *FindNxtP(),*mkList( );
struct polygn2 *ptemp;
real Planar I);
List= mkList(PList);
I*
fprintf(elog,"Hidden current list \n");
ListNodes(List);
"I
PolyP.next
NULL;
PolyQ.next = NULL;
I*
• read to do priority sort
*I
while ( (curLptr = FindNxtP(List)) != NULL)
PolyP.poly = curLptr->poly;
mkSetQ(PolyP.poly->zmin,&SetQ,List);
curQptr = SetQ;
PolyP.status = 0;
PolyQ.status = 0;
while (curQptr != NULL) [
PolyQ.poly = curQptr->poly;
l!ifdef DB7
fprintf(elog,"Hidden : PolyP.poly->ident
PolyP.poly->ident);
%d\n",
......
0'1
Ul
fprintf(elog,"Hidden : PolyQ.poly->ident
PolyQ.poly->ident);
#endif
%d\n",
if (Obstruct(PolyP.poly,PolyQ.poly) == TRUE) [
if (btest(curQptr->status,SWAPPED) == TRUE) [
fprintf(elog,"%%F-Hidden : cyclic clipping problem\n");
ListNodes(&PolyPJ;
ListNodes(&PolyQ);
exit();
I*
* Swap polygons "PolyP" and
* again with new "PolyP".
*I
"PolyQ" and try
=
ptemp
PolyP.poly;
curQptr->poly = ptemp;
PolyP.poly = PolyQ.poly;
PolyQ.poly = ptemp;
PolyP.poly->status I= INUSE;
PolyQ.poly->status &= -(INUSE);
curQptr->status I= SWAPPED;
curQptr = SetQ;
else [
I*
* PolyP doesn't obstruct PolyQ, test against next element of
* SetQ.
*I
curQptr
= curQptr->next;
}
}
apDspLst(&PolyP);
dAllocPLnk(&SetQ);
......
0\
0\
struct plink *
mkList(List)
struct plink *List;
{
I*
*
•
•
•
•
Routine to create a linked list of the,from the linked list List .
Input : List (plink *)
Output : None.
list to make a copy of .
: returns a pointer to the copy of List .
*I
struct plink *Head,*templ,*temp2;
=
=
Head
NULL;
templ
List;
while(templ != NULL)
temp2
(struct plink *)calloc(l,sizeof(struct plink));
AppndLst(temp2,&Head);
temp2->poly = templ->poly;
templ
templ->next; )
return(Head);
=
=
1-'
0'1
._J
mkSetQ(tstval,Set,List)
real tstval;
struct plink **Set,*List;
I*
*
*
*
*
*
mkSetQ returns the pointer to the beginning of a list of all
all polygons in "List" that have a a "zmax" greater than
tstval.
Input : tstval (int)
z value to test against
List (plink *)
Linked list to search through
output : Set (plink **)
: Linked list of polygons that are greater than
tstval.
*I
[ .
struct plink *temp,*temp2;
*Set = NULL;
temp = List;
·while (temp != NULL) [
if (temp->poly->zmax >= tstval &&
btest(temp->poly->status,INUSEl != 1)
temp2 = (struct plink *) calloc(l,sizeof(struct plink));
temp2->status = 0;
AppndLst(temp2,Set);
temp2->poly = temp->poly;
temp
temp-> next;
1-'
0'1
(X)
PolySort(npoly)
int npoly;
I*
*
*
*
*
*
*
Sort polygons based on max z value
Written : 23-0ct-1987
Input : npoly (int)
number of polygons in "p1ist" to sort.
Output : None.
*I
int i.j;
struct polygn2 *TempPoly;
for(i=O;i<npoly-2;i++)
for(j=npoly-1;j>i;j--)
if (plist[j-1] .poly->zmax < plist[j] .poly->zmax)
TempPoly = plist[j-1].poly;
p1ist[j-1] .poly= plist[j].poly;
plist[j].poly = TempPoly;
......
O't
1.0
I*
*
*
support.h
*
*I
#include
#include
#include
#include
<stdio.h>
" .. lheaderlsystem.h"
" .. lheaderlrmat.h"
"--lheaderltriplet.h"
typedef Triplet Vertex;
typedef Triplet Point;
#define MAXOBJ 100
#define MAXVERT 1000
#define SIGN(val) ( (val) > 0. ? 1
#define
#define
#define
#define
#define
II define
-1)
POS 1
NEG -1
TRUE 1
F!\LSE 0
BEYOND Ox00000004
DISABLED Ox00000008
struct gdevice {
int imin,imax,
jmin,jmax,
idiff,jdiff;
J screen;
struct wcorr
real kluge;
real xmin,xmax,
ymin,ymax,
xdiff,ydiff ] world;
struct polygn {
int ident;
int nvert;
int icolor;
int voffset;
int *vindex;
J;
/* index into a vertex table */
typedef struct object
int ident;
unsigned long status;
char name(10];
1-'
-..J
0
int nvert;
int npoly;
Vertex *vert;
I* address of a vertex table *I
struct polygn *poly;
I* address of a polygon table *I
Rmat mat;
real xcent,ycent,zcent;
real xscale,yscale,zscale;
real xsrot,ysrot,zsrot } object;
struct
int sign;
Point vert;
} ViewPoint,ProjectPt;
struct polygn2
unsigned long status;
int nvert;
int icolor;
int ident;
int vsign;
real xmin,xrnax;
real ymin,ymax;
real zmin,zmax;
Vertex normal;
Vertex **vert;
Vertex **vert2;
};
I*
pointers into a vertex table
*I
FILE *fopen(),*elog,*dbfile,*drfile;
struct object *objlst[lO];
Vertex *vtable,*vtable2;
struct polygn2 *ptable;
int totvert,totpoly,totobj;
int Display,Record,Video,Graphics;
struct object tobj[MAXOBJ],tobj2[MAXOBJ];
Rmat al,a2;
real vect[16] ,vect2[16];
struct plink *DspLst;
char dbname[30] ,drname[30],ername[30];
int FrmPerRec;
I-'
-.J
I-'
172
..c::
..c::
0
z
Q,
I>:
C1
..."'
:.:
""
~
"
a:!
G>
. . . .
.....::
....
'-G>
'0
""
I*
*
*
*
*I
!!define
lldefine
!!define
!!define
!!define
!!define
plink.h
NIL -1
TRUE 1
FALSE 0
WRTNOUT OxOOOOOOOl
INUSE
Ox00000002
SWAPPED Ox00000003
typedef struct plink
struct plink *last;
struct plink •next;
unsigned long status;
struct polygn2 *poly } plink;
plink *plist;
.....
-..)
w
APPENDEX F.
support Routines
The following is a listing of the lib directory.
174
ll
ll
ll
Makefile for utilities
OBJECTS
abort.o btest.o matopers.o
extra.a
$(OBJECTS) .• ;header;system.h .. ;header;rmat.h
cc -c $(OBJECTS)
ar rv extra.a $(OBJECTS)
ranlib extra.a
f-'
-...)
Ul
I*
*
*
*
abort.c
*I
#include <stdio.h>
extern FILE *elog;
Abort(Line)
char *Line;
{
I*
*
Routine to call exit with a message
*
*
Input: Line (char*): A string with a message in it.
*
*
*I
Output : None
fprintf(elog,"'s \n",Line);
fprintf(elog,"Program aborted \n\n");
exit();
.......
--.1
0'1
I*
*
*
*
*I
btest.c
btest(vall,val2)
unsigned long vall,val2;
{
I*
Routine to see if vall and val2 have any bits that are common to each
other.
*
*
*
*
Input : vall (unsigned long) : first word
val2 (unsigned long) : second word
*
*
*I
output
*
if ( (vall '
return(!);
None. Returns 1 if vall and val2 any bits in common.
val2 )
==
0) return(O);
1-'
--..1
--..1
prtmat(mat)
Rmat *mat;
(
I*
Routine to print out value of a matrix
*
*
Input : mat (Rmat
*
*
*
*)
:
the matrix to dump
Output : None.
*I
int i, j;
for(i=l;i<=IMAX(mat);i++) (
for(j=l;j<=JMAX(mat);j++)
fprintf(elog,"%10.4e ",mat->vect[ptr(mat,i,j)]);
fprintf(elog,"\n"); }
I-'
-....]
OJ
.,.
SetidMat(mat)
Rmat *mat;
{
I*
*
Routine
*
t~
set a mat to an identity matrix.
*
Input : mat (Rmat *)
*
Output : None.
*
: matrix to set.
mat get set to its identity.
*I
int i;
for(i=O;i<IMAX(mat)*JMAX(mat);i++)
mat->vect[i) = 0.;
for(i=l;i<=IMAX(mat);i++)
mat->vect[ptr(mat,i,i)) = 1.;
......
-...]
\D
I*
*
matopers.c
*
*
*I
#include <stdio.h>
#include " .. lheaderlsystem.h"
#include " .. lheaderlrmat.h"
extern FILE *elog;
matmul(rmata,rmatb)
Rmat *rmata,*rmatb;
I*
Routine to multiply rmata by rmatb and place the results back
in rmata.
*
*
*
*
Input : rmata (Rmat *) : A matrix
rmatb (Rmat *I : The second matrix
*
*
*I
output
*
rmata : get the product of rmata*rmatb
[
int i,j,k;
real tally,tmat[S][S];
#ifdef DBUG
fprintf(elog,"matmul rmata \n");
prtmat(rmata);
fprintf(elog,"matmul rmatb \n");
prtmat ( rmatb I;
hndif
for (i=l;i<=rmata->imax;i++l
for (j=l;j<=rmatb->imax;j++l
tally= 0.;
for (k=l;k<=rmata->jmax;k++)
tally= rmata->vect[ptr(rmata,i,k))*rmatb->vect[ptr(rmatb,k,j))+tally;
tmat[i)[j) = tally; }
for (i=l;i<=rmata->imax;i++l
for (j=l;j<=rmata->jmax;j++l
rmata->vect[ptr(rmata,i,j))
tmat[i][j];
1-'
OJ
0
APPENDEX G.
Header Files
The following is a listing of the header directory.
181
I*
*
*
directs.h
*
*
List of all directives for system
*I
#define
#define
#define
#define
lldefine
lldefine
#define
#define
#define
lldefine
lldefine
#define
l!det'ine
lldefine
#define
!I define
!!define
ROTX 1
ROTY 2
ROTZ 3
VIEWX 4
VIEWY 5
VIEWZ 6
TRANX 7
TRANY 8
TRANZ 9
GBLS 10
SCALX 11
SCALY 12
SCALZ 13
ROTSX 14
ROTSY 15
ROTSZ 16
LASTPRIM 16
lldefine
!!define
#define
lldefine
#define
lldefine
lldefine
!!define
#define
I define
#define
#define
!I define
#define
lldefine
CREAINST 100
P'IXROTX 101
FIXROTY 102
P'IXROTZ 103
P'IXTRANX 107
FIXTRANY 108
FIXTRANZ 109
FIXGBLS 110
FIXSCALX 111
FIXSCALY 112
P'IXSCALZ 113
FIXROTSX 114
FIXROTSY 115
FIXROTSZ 116
DSBLINST 200
I*
set to same value as last matrix rotation
*I
I*
create an instance of an object
*I
I*
disable an instance of an object
*I
I*
set world coordinates
#define DISPLAY 1000
#define STOP
1001
#define SETWLDC 4000
*I
1-'
00
1\)
'define MATRD 500
#define SETMAT 501
'define RESETMAT 502
/* set object matrix in one fell swoop
/* set matrix back to ident.
/* set object matrix back to normal
*/
*/
*/
.......
00
w
I*
•
*
rmat.h
*
*I
#define
#define
#define
#define
IMAX(mat) ((mat)->imax)
JMAX(mat) (lmat)->jmax)
ptr(mat,i,j) (((mat)->imax)*((j)-1) + (i)-1)
MVAL(matrix,i,j) (matrix)->vect[ptr((matrix),(i),(j))]
typedef struct Rmat (
int imax,jmax;
real •vect; ] Rmat;
f-'
())
""'
185
..
....
....
.
....D.
..
....
. .. .
...............
.........,
....D.
....
E-t >< :.,
......
.
....
.,
., "'
...... .. .. .
IJ .,
;:1 .,
Ill
.....,
.,
'tl
.. . .. . ..
'-
E-t
....
....D.
.<:
D.
'->....
II>
/*
*
*
system.h
*
*/
#define DOUBLEPREC
lifdef DOUBLEPREC
typedef double real;
#else
typedef float real;
#endif
I-'
OJ
0'\
APPENDEX H.
IDF Directives
The following is a table of all the currently
implemented IDF directives in Prism.
Mnemonic
ROTX
ROTY
ROTZ
VIEWZ
TRANX
TRANY
TRANZ
GBLS
SCALX
SCALY
SCALZ
ROTS X
ROTSY
ROTSZ
CREAINST
FIXROTX
FIXROTY
FIXROTZ
FIXTRANX
FIXTRANY
FIXTRANZ
FIXGBLS
FIXSCALX
FIXSCALY
Value
1
2
3
6
7
8
9
10
11
12
13
14
15
16
100
101
102
103
107
108
109
110
111
112
Comment
Rotate around screen orgin, x axis
Rotate around screen orgin, y axis
Rotate around screen orgin, y axis
Set viewpoint
Translate in x direction
Translate in y direction
Translate in z direction
Set global scale factor
Set x scale factor
Set y scale factor
Set z scale factor
Rotate about object's center, x axis
Rotate about object's center, y axis
Rotate about object's center, z axis
Create an instance
Set rotational offset in along x axis
Set rotational offset in along y axis
Set rotational offset in along z axis
Set x position on screen
Set y position on screen
Set z position on screen
Set global scale factor
Set x scale factor
Set y scale factor
187
188
FIXSCALZ
FIXROTSX
FIXROTSY
FIXROTSZ
DSBLINST
MATRD
SETMAT
RESETMAT
DISPLAY
STOP
SETWLDC
113
114
115
116
200
500
501
502
1000
1001
4000
Set z scale factor
Set relative x rotational offset
Set relative y rotational offset
Set relative z rotational offset
Disable an instance of an object
Set object matrix in one fell swoop
Set matrix back to identity
Set object matrix back to default
Display and record image
Exit from IG program
Set world coordinates
APPENDEX I.
Current Object Database
The following is a listing of current Object
Definition File.
7
1 triangle
5 6
-1. -1. -1.
o.
1. -1.
-1.
1. -1.
-1. -1.
1.
o.
1.
1.
1.
1. -1.
3 120
3
5
4
4
130
5
3
2
4 140
3
4
1
3 150
2
0
1
4 160
2
4
5
2 pyramid
5 5
-1. -1. -1.
o.
o.
1.
1. -1. -1.
-1.
1.
-1.
1.
1. -1.
0
0
1
189
190
4 120
2
4
3
3 130
0
1
2
3 140
1
4
2
3 150
0
3
1
3 160
3
4
1
3 cube
6 8
-1. -1. -1.
-1.
1. -1.
1. 1. -1.
1. -1. -1.
-1. -1.
1.
-1. 1. 1.
1. 1. 1.
1. -1.
1.
4 110
0 1 2 3
4 120
0 4 5 1
4 130
3 2 6 7
4 140
7 6 5 4
4 150
2 1 5 6
4 160
3 7 4 0
4 hex
8
12
-0.5 -1. -1.
-1.0 0. -1.
-0.5 1. -1.
0.5 1. -1.
1.0 o. -1.
0.5 -1. -1.
-0.5 -1.
1.
-1.0 o.
1.
-0.5 1.
1.
0.5 1. 1.
1.0 o.
1.
1.
0.5 -1.
6 110
0 1 2 3 4 5
6 120
11 10 9 8 7 6
4 130
5 11 6 0
0
191
4
2
4
3
4
4
4
7
4
6
140
8 9 3
150
9 10 4
160
10 11 5
170
8 2 1
180
7 1 0
5 pube
4 8
-1. -1. -1.
-1. 1. -1.
1. 1. -1.
1. -1. -1.
-1. -1. 1.
-1. 1. 1.
1. 1. 1.
1. -1. 1.
4 110
0 1 2 3
4 140
7 6 5 4
4 150
2 1 5 6
4 160
3 7 4 0
6 prism
5 6
-1.
-2.
-1 .•
o.
1. -2.
-2.
1. -1.
-1.
-1.
2.
o.
1.
2.
1. -1.
2.
3 120
5
4
3
4 130
2
5
3
4 140
3
4
1
3 150
2
0
1
4 160
4
2
5
7 walls
2 8
-1. -1. -1.
-1.
1. -1.
1. 1. -1.
1. -1. -1.
0
0
1
192
-1. -1.
1.
-1.
1. 1.
1. -1.
4 120
0 4 5 1
4 130
3 2 6 7
1.
1.
1.
1.
© Copyright 2026 Paperzz