| 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]). |