| 1 |
A general scheme has been defined for writing translators from CAD
|
| 2 |
files to Radiance. This scheme should be used by anyone who writes a
|
| 3 |
new translator, since it is both useful and general.
|
| 4 |
|
| 5 |
One of the biggest problems encountered when importing CAD descriptions
|
| 6 |
to a lighting simulation (or any good rendering program) is assigning
|
| 7 |
materials to the surface geometry. Even if the creator of the model
|
| 8 |
has been careful to make 3d surfaces instead of points and lines, most
|
| 9 |
people don't even think about what a surface is made of until they're
|
| 10 |
all done. At that point, of course, it's too late. Even if the user
|
| 11 |
does give a little thought to materials, most CAD systems only permit
|
| 12 |
the assignment of a color index to each surface, which is a start but
|
| 13 |
far short of the information needed to make a good simulation.
|
| 14 |
|
| 15 |
There are only a few CAD systems that "do the right thing" and allow the
|
| 16 |
user to assign material identifiers to objects and individual surfaces.
|
| 17 |
Such a program, GDS for example, makes writing a translator almost
|
| 18 |
trivial, since the material identifiers can refer back to a library of
|
| 19 |
materials maintained by the user, or even imported from the CAD system.
|
| 20 |
|
| 21 |
Most CAD programs, like AutoCAD or Architrion, don't really use the
|
| 22 |
notion of materials in their models at all. Instead, they
|
| 23 |
differentiate surfaces by layer, color, block name, and so forth, none
|
| 24 |
of which clearly makes sense to use as a material identifier. Even if
|
| 25 |
the user creates a model with an intent to perform lighting
|
| 26 |
simulations, he or she has no way to assign materials directly to the
|
| 27 |
objects in the model.
|
| 28 |
|
| 29 |
The only general solution is to use every available piece of information
|
| 30 |
from the CAD model to assign materials. We can do this by using a set
|
| 31 |
of mapping rules, created somehow by the user. (We are working on
|
| 32 |
a HyperCard interface for selecting materials that should be very nice
|
| 33 |
if we ever finish it.) The mapping rules are an ordered list of
|
| 34 |
materials and the conditions a surface must satisfy in order to have
|
| 35 |
that material.
|
| 36 |
|
| 37 |
For example, if we wanted all surfaces in the Block "thingy" with the
|
| 38 |
Color 152 to use the material "wood", and all other surfaces to use the
|
| 39 |
material "default", we would create the following mapping file:
|
| 40 |
|
| 41 |
default ;
|
| 42 |
wood (Block "thingy") (Color 152) ;
|
| 43 |
|
| 44 |
All surfaces would satisfy the first set of conditions (which is empty),
|
| 45 |
but only the surfaces in Block "thingy" with Color 152 would satisfy the
|
| 46 |
second set of conditions.
|
| 47 |
|
| 48 |
Each rule can have up to one condition per qualifier, and different
|
| 49 |
translators will use different qualifiers. A qualifier is simply an
|
| 50 |
attribute that can be used to distinguish surfaces, such as Color,
|
| 51 |
Layer, Reference ID, etc. A condition is either a single value for a
|
| 52 |
specific attribute, or an integer range of values. (Integer ranges are
|
| 53 |
specified in brackets and separated by a colon, eg. [-15:27], and are
|
| 54 |
always inclusive.) A semicolon is used to indicate the end of a rule,
|
| 55 |
which can extend over several lines if necessary.
|
| 56 |
|
| 57 |
The semantics of the rule are such that "and" is the implied conjunction
|
| 58 |
between conditions. Thus, it makes no sense to have more than one
|
| 59 |
condition in a rule for a given qualifier. If the user wants the same
|
| 60 |
material to be used for surfaces that satisfy different conditions,
|
| 61 |
they simply add more rules. For example, if the user also wanted
|
| 62 |
surfaces in Block "yohey" with Colors between 50 and 100 to use "wood",
|
| 63 |
they would add the following rule to the end of the example above:
|
| 64 |
|
| 65 |
wood (Color [50:100]) (Block "yohey") ;
|
| 66 |
|
| 67 |
Note that the order of conditions in a rule is irrelevant. However,
|
| 68 |
the order of rules is very important, since the last rule satisfied
|
| 69 |
determines which material a surface is assigned.
|
| 70 |
|
| 71 |
By convention, the identifier "void" is used to delete unwanted
|
| 72 |
surfaces. It is used in a rule as any other material, but it has the
|
| 73 |
effect of excluding all matching surfaces from the translator output.
|
| 74 |
For example, the following mapping would delete all surfaces in the
|
| 75 |
Layer 2 except those with the color "beige", to which it would assign
|
| 76 |
the material "beige_cloth", and all other surfaces would be "tacky":
|
| 77 |
|
| 78 |
tacky ;
|
| 79 |
void (Layer 2) ;
|
| 80 |
beige_cloth (Layer 2) (Color "beige") ;
|
| 81 |
|
| 82 |
Hopefully, the meaning of the mapping rules is now clear, so we can
|
| 83 |
discuss ways to help the user create the mapping for a given model.
|
| 84 |
|
| 85 |
A translator should provide at least two basic options. The first
|
| 86 |
option, "-n", simply reads the CAD input file and creates a list of
|
| 87 |
qualifiers and values that can be used to differentiate surfaces in the
|
| 88 |
model. The output of the program with "-n" should be something like:
|
| 89 |
|
| 90 |
filename "Example Input File"
|
| 91 |
filetype "Architrion"
|
| 92 |
qualifier Color begin
|
| 93 |
35
|
| 94 |
[100:110]
|
| 95 |
200
|
| 96 |
end
|
| 97 |
qualifier RefId begin
|
| 98 |
1103
|
| 99 |
[5306:5307]
|
| 100 |
"BIG Things"
|
| 101 |
"little Things"
|
| 102 |
end
|
| 103 |
EOF
|
| 104 |
|
| 105 |
This information can be used either by the user or by a program such as
|
| 106 |
HyperCard to create the rules for assigning materials to surfaces in
|
| 107 |
the file. (The "EOF" is literally there, since HyperCard has trouble
|
| 108 |
detecting the end of file.)
|
| 109 |
|
| 110 |
The second option, "-m mapfile" is used to specify the mapping file to
|
| 111 |
be used by the translator. If no mapfile is provided by the user, the
|
| 112 |
translator should have a standard mapping to assign material names
|
| 113 |
based on some set of default paramters. (For example, arch2rad uses
|
| 114 |
color alone to assign materials "c0" through "c255".) To accompany the
|
| 115 |
default mapping, there should be a default materials file with
|
| 116 |
corresponding definitions. These files should be placed in the
|
| 117 |
Radiance library directory under "lib" (ie. "/usr/local/lib/ray/lib").
|
| 118 |
|
| 119 |
To just look at an Architrion building, a user might issue the following
|
| 120 |
commands:
|
| 121 |
|
| 122 |
oconv '\!gensky 6 15 12' /usr/local/lib/ray/lib/arch.mat \
|
| 123 |
'\!arch2rad model.txt' > model.oct
|
| 124 |
rvu -av 3 3 3 -vp -20 -20 5 -vd 1 1 0 model.oct
|
| 125 |
|
| 126 |
Note that by giving oconv commands instead of input files, no temporary
|
| 127 |
files (other than the octree) are necessary. In a more complete
|
| 128 |
example, the user might first create a qualifier list, then run the
|
| 129 |
HyperCard stack for assigning materials, then convert the model
|
| 130 |
with his own materials file, thus:
|
| 131 |
|
| 132 |
arch2rad -n model.txt > model.qual
|
| 133 |
HyperCard MatPick.stack # creates model.map from model.qual
|
| 134 |
arch2rad -m model.map model.txt > model.rad
|
| 135 |
oconv source.rad materials.rad model.rad > model.oct
|
| 136 |
rvu -vf model.vp model.oct
|
| 137 |
|
| 138 |
To write a new translator, include the "trans.h" file in ray/src/cv and
|
| 139 |
link with trans.o and the standard Radiance library. You will need to
|
| 140 |
define your own list of valid qualifiers and use the following routines
|
| 141 |
from trans.c:
|
| 142 |
|
| 143 |
fgetid(ID *idp; char *dls; FILE *fp)
|
| 144 |
/*
|
| 145 |
* Read an id (either a string or an integer) from fp
|
| 146 |
* up to a character in dls. The delimiter will be discarded.
|
| 147 |
* Return EOF at end of file, 0 otherwise. You should free
|
| 148 |
* the id with the macro doneid(idp).
|
| 149 |
*/
|
| 150 |
|
| 151 |
int
|
| 152 |
findid(IDLIST *ilp; ID *idp; int insert)
|
| 153 |
/*
|
| 154 |
* Find (or insert) idp in the list ilp. Uses binary search
|
| 155 |
* to find (or if insert is true, insert) an id in a sorted id
|
| 156 |
* list. Returns index into ilp->id, or -1 if not found and no
|
| 157 |
* insert.
|
| 158 |
*/
|
| 159 |
|
| 160 |
int
|
| 161 |
idcmp(ID *id1, *id2)
|
| 162 |
/*
|
| 163 |
* Compares two identifiers. Numbers compare less than strings.
|
| 164 |
*/
|
| 165 |
|
| 166 |
write_quals(QLIST *qlp; IDLIST idl[]; FILE *fp)
|
| 167 |
/*
|
| 168 |
* Write out qualifiers in array of id lists idl[] to fp.
|
| 169 |
* The qualifier list qlp is used to determine how many and
|
| 170 |
* what to call the qualifiers.
|
| 171 |
*/
|
| 172 |
|
| 173 |
RULEHD *
|
| 174 |
getmapping(char *file; QLIST *qlp)
|
| 175 |
/*
|
| 176 |
* Read mapping rules from "file" and create a list of rules
|
| 177 |
* in reverse order. Prints various syntax errors using eputs()
|
| 178 |
* and calls quit() if there's a serious problem with the input.
|
| 179 |
*/
|
| 180 |
|
| 181 |
matchid(ID *idp; IDMATCH *idm)
|
| 182 |
/*
|
| 183 |
* Checks to see if idp matches the id or range in idm.
|
| 184 |
*/
|
| 185 |
|
| 186 |
Good luck! I will be happy to answer questions ([email protected]).
|