3D for Free
Volume Number: 16
Issue Number: 9
Column Tag: Navigation Services
3D For Free Using the Mac’s Standard Apps
by Tom Djajadiningrat
Converting raw 3D text files to QuickDraw 3D's 3DMF
format using AppleScript
Summary
This article introduces you to the basics of 3D files in general and the 3D Metafile
(3DMF), QuickDraw 3D's native 3D format, in particular. It shows how you can use
AppleScript to easily convert a raw 3D text file into a 3DMF readable by the
QuickDraw 3D Viewer or any other QuickDraw 3D compatible application. With this
knowledge you can make hand-written data or data exported by a spreadsheet or
database application suitable for visualisation as standalone 3D models.
Introduction
The combined power of the suite of goodies that comes standard with your Mac is really
quite amazing. One such goody is the QuickDraw 3D Viewer. The QuickDraw 3D Viewer
makes it possible to do basic viewing of 3D models that are formatted as 3D Metafiles
(3DMF), QuickDraw 3D's native file format. Since the QuickDraw 3D Viewer is
supported by SimpleText, which comes standard with a Mac, files written in 3DMF
format can be viewed on any PowerMacintosh running QuickDraw 3D. Maybe you would
like to visualise your spreadsheet or database data as standalone 3D models or perhaps
you would like to write your own low-polygon count models by hand rather than use a
3D modeller. To achieve this you could make the spreadsheet or database application
export complete 3DMFs. Often though it is quite awkward to get the formatting right.
And though it is possible to write complete 3DMFs by hand, you of course want to
reduce repetitive chores, such as adding brackets, to save time and reduce errors.
Here we take the approach of writing minimalistic 3D files which are then
post-processed into 3DMF. So how do we do this post-processing? Enter two other
Macintosh standard goodies: AppleScript and the ScriptMaker application. Although it
is seldom used for this express purpose, AppleScript is actually quite good at reading
and writing text files. Another nice feature of AppleScript is the ease with which we
can make a droplet: a script which performs certain actions on documents which are
dropped on to it. This allows us to convert multiple files with the ease of drag and drop.
QuickDraw 3D's 3DMF Format
3D models can be described using vertices and faces. A vertex is a point in 3D space
described by x, y and z co-ordinates. A face is a polygon of which each corner point is a
vertex. To prevent unpredictable results a face should be planar: all its vertices
should lie in one plane. Figure 1 shows a technical sketch of a table which consists of a
square face (the table top) and eight triangular faces (the legs). Figure 2 shows the
corresponding 3D model in the QuickDraw 3D Viewer.
Figure 1. Technical sketch of a table.
Figure 2. The 3D model in the QuickDraw 3D Viewer.
Listing 1 shows a 3DMF file for this table. For our example we use the QuickDraw 3D
mesh geometry, which is probably the easiest to understand way to describe a 3D
model. The hash sign (#) marks a comment in a 3DMF. Everything on a line after a
hash is ignored. The 3DMF here consists of two parts. The first part is the header,
3DMetafile ( 1 6 Normal toc> ). The second part is formed by a container which
contains a single mesh object. Let's look at the header first. The header, formed by the
first line of the file, tells us that we have a 3D Metafile for QuickDraw 3D 1.6. The
major version number is 1 and the minor version number is 6. The third field,
Normal, is the type of 3D Metafile. The fourth field of the header, toc>, is a file pointer
to a table of contents which is non-existent in this 3DMF. Don't worry about the type
of 3D Metafile and the table of contents parameters. You do not need to know their exact
meaning to understand this article and later we explain where to read up on the full
3DMF specification.
Listing 1: a 3DMF file
table.3df
3DMetafile ( 1 6 Normal toc> )
#This is a table with a square top and four legs
Container (
Mesh(
20 #number of vertices
1 1.5 -1 #0
-1 1.5 -1 #1
-1 1.5 1 #2
1 1.5 1 #3
1 0 1 #4
0.9 1.5 0.6 #5
0.9 1.5 0.9 #6
0.6 1.5 0.9 #7
1 0 -1 #8
0.6 1.5 -0.9 #9
0.9 1.5 -0.9 #10
0.9 1.5 -0.6 #11
-1 0 -1 #12
-0.9 1.5 -0.6 #13
-0.9 1.5 -0.9 #14
-0.6 1.5 -0.9 #15
-1 0 1 #16
-0.6 1.5 0.9 #17
-0.9 1.5 0.9 #18
-0.9 1.5 0.6 #19
9 #number of faces
0 #number of contours
4 0 1 2 3 #0
3 4 5 6 #1
3 4 6 7 #2
3 8 9 10 #3
3 8 10 11 #4
3 12 13 14 #5
3 12 14 15 #6
3 16 17 18 #7
3 16 18 19 #8
)
Container (
AttributeSet ( )
DiffuseColor (1.0 1.0 0.0) #r g b
)
)
Now let's look at what takes place within the bracket of the container. The container
contains a mesh and another container with a diffuse colour attribute in it. First the
mesh description lists the number of vertices involved. In our case there are twenty
vertices. What follows is a list of vertices which QuickDraw 3D sees as numbered
from 0 to 19. Each vertex is described by three co-ordinates. For example, vertex
number 0 has the co-ordinates x=1, y=1.5 and z=-1. Next is the number of faces,
eight in this case, followed by the number of contours. A contour is a polygonal hole in
a face. Since there are no holes in our table the number of contours is 0. The mesh
description finishes with the eight faces. The first number of a face description is the
number of vertices involved in the face, the remaining numbers specify these
vertices. For example, the square table top is face number 0, which has four corners
formed by the vertices 0, 1, 2 and 3. Finally, there is a diffuse colour attribute which
applies to the whole mesh. It is specified in red, green and blue components, each
ranging from 0.0 to 1.0.
The Raw 3D File
It is very important to carefully consider what the raw 3D file should look like before
you start writing a script to convert it to 3DMF. If you yourself export the file or
write it by hand you are of course in complete control. If someone else does this for
you-say an expert in low-polygon count models - you want to make sure this person
formats the file in such a way that makes life as easy on you as possible. On the other
hand, you may wish to respect this person's way of formatting files. Listing 2 shows an
example of what a raw 3D file might look like. There are some differences between this
raw 3D file and the 3DMF file we just discussed which make conversion pretty
awkward, but it is understandable why the formatting of the raw 3D file is convenient
for the person who writes the file by hand. Because of the vertex and face labels on
each line it is immediately clear whether one is in the vertices or faces section when
quickly scrolling through the file. Because of the commas it is possible to put spaces
between a minus sign and a co-ordinate so that the minus signs line up vertically. This
makes it easier to spot co-ordinates with the wrong sign. Both vertices and faces start
rather than end with their index number so that the indices line up too. A face line does
not include the number of vertices which saves work and reduces errors. Careful
deliberation with all involved can safe much work and frustration.
Listing 2: A raw 3D file
table.txt
Description:This is a table with a square top and four legs
Vertices:20
Vertex: 0, 1, 1.5, -1
Vertex: 1, -1, 1.5, -1
Vertex: 2, -1, 1.5, 1
Vertex: 3, 1, 1.5, 1
Vertex: 4, 1, 0, 1
Vertex: 5, 0.9, 1.5, 0.6
Vertex: 6, 0.9, 1.5, 0.9
Vertex: 7, 0.6, 1.5, 0.9
Vertex: 8, 1, 0, -1
Vertex: 9, 0.6, 1.5, -0.9
Vertex:10, 0.9, 1.5, -0.9
Vertex:11, 0.9, 1.5, -0.6
Vertex:12, -1, 0, -1
Vertex:13, -0.9, 1.5, -0.6
Vertex:14, -0.9, 1.5, -0.9
Vertex:15, -0.6, 1.5, -0.9
Vertex:16, -1, 0, 1
Vertex:17, -0.6, 1.5, 0.9
Vertex:18, -0.9, 1.5, 0.9
Vertex:19, -0.9, 1.5, 0.6
Faces: 9
Face: 0, 0, 1, 2, 3
Face: 1, 4, 5, 6
Face: 2, 4, 6, 7
Face: 3, 8, 9, 10
Face: 4, 8, 10, 11
Face: 5, 12, 13, 14
Face: 6, 12, 14, 15
Face: 7, 16, 17, 18
Face: 8, 16, 18, 19
DiffuseColor:1.0 1.0 0.0
AppleScript
The next thing we do is to write an AppleScript to convert the raw 3D text file to
3DMF. In the folder :Apple Extras:AppleScript you find the application
ScriptMaker which you can use for writing AppleScripts. First we discuss the
structure of our script, then we fill in the details.
The structure
Listing 3 shows the structure of our conversion script Convert to 3DMF. We use the on
open construct so that we can use the script as a droplet. The file specifications of the
files dropped onto the droplet appear in the list inDocList. We traverse the list
inDocList through a repeat command and act on each file in turn. First we do the most
basic of error checking. Within a try statement we check whether the file is of type
'TEXT'. If it is not, we bail out by throwing an error which leads to execution of the on
error portion of the try statement. If it is a text file we call the parse handler. Within
the parse handler we again have a try statement in which we try to extract the
relevant information from the raw 3D text file and format it according to 3DMF
standards. If all goes well we call the writeResultFile handler with as arguments the
file specification of the raw 3D text file and the text of the 3DMF file to write. Within
the writeResultFile handler we try to create a text file within the same directory as
the raw 3D text file and the same name, except for the extension which we make 3df.
Now that we have some idea of the structure of our script, let's turn our attention to
the parse handler.
Listing 3: The structure of Convert to 3DMF
on open (inDocList)
- traverse the list of files that were dropped on the droplet
repeat with theFilePath in inDocList
try
tell application "Finder