00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00026 #include <stdio.h>
00027 #include <string.h>
00028 #include <math.h>
00029 #include "RadianceDisplayDevice.h"
00030 #include "Matrix4.h"
00031 #include "DispCmds.h"
00032 #include "Inform.h"
00033 #include "utilities.h"
00034
00035 #define DEFAULT_RADIUS 0.002
00036 #define DASH_LENGTH 0.02
00037
00038
00039
00040
00041
00042 #define ORDER(x,y,z) -z, -x, y
00043
00045
00046
00047 RadianceDisplayDevice::RadianceDisplayDevice()
00048 : FileRenderer("Radiance", "Radiance 4.0", "vmdscene.rad",
00049 "oconv %s > %s.oct; rview -pe 100 -vp -3.5 0 0 -vd 1 0 0 %s.oct") {
00050 reset_vars(); // initialize state variables
00051 }
00052
00053 //destructor
00054 RadianceDisplayDevice::~RadianceDisplayDevice(void) { }
00055
00056 void RadianceDisplayDevice::reset_vars(void) {
00057 // clear out the r/g/b/t arrays
00058 red.clear();
00059 green.clear();
00060 blue.clear();
00061 trans.clear();
00062
00063 cur_color = 0;
00064 }
00065
00066
00068
00069 // draw a point
00070 void RadianceDisplayDevice::point(float * spdata) {
00071 float vec[3];
00072
00073 // transform the world coordinates
00074 (transMat.top()).multpoint3d(spdata, vec);
00075
00076 // draw the sphere
00077 set_color(colorIndex);
00078
00079 fprintf(outfile, "color%d sphere ball\n0\n0\n4 %4f %4f %4f %4f\n",
00080 cur_color, ORDER(vec[0], vec[1], vec[2]),
00081 float(lineWidth) * DEFAULT_RADIUS);
00082 }
00083
00084 // draw a sphere
00085 void RadianceDisplayDevice::sphere(float * spdata) {
00086
00087 float vec[3];
00088 float radius;
00089
00090 // transform the world coordinates
00091 (transMat.top()).multpoint3d(spdata, vec);
00092 radius = scale_radius(spdata[3]);
00093
00094 // draw the sphere
00095 set_color(colorIndex);
00096
00097 fprintf(outfile, "color%d sphere ball\n0\n0\n4 %4f %4f %4f %4f\n",
00098 cur_color, ORDER(vec[0], vec[1], vec[2]), radius);
00099 }
00100
00101 // draw a line (cylinder) from a to b
00102 void RadianceDisplayDevice::line(float *a, float*b) {
00103 int i, j, test;
00104 float dirvec[3], unitdirvec[3];
00105 float from[3], to[3], tmp1[3], tmp2[3];
00106
00107 if (lineStyle == ::SOLIDLINE) {
00108 // transform the world coordinates
00109 (transMat.top()).multpoint3d(a, from);
00110 (transMat.top()).multpoint3d(b, to);
00111
00112 // draw the cylinder
00113 set_color(colorIndex);
00114 fprintf(outfile, "color%d cylinder cyl\n0\n0\n7 ", cur_color);
00115 fprintf(outfile, "%4f %4f %4f ",
00116 ORDER(from[0], from[1], from[2])); // first point
00117 fprintf(outfile, "%4f %4f %4f ",
00118 ORDER(to[0], to[1], to[2])); // second point
00119 fprintf(outfile, "%4f\n", float(lineWidth)*DEFAULT_RADIUS); // radius
00120
00121 } else if (lineStyle == ::DASHEDLINE) {
00122 // transform the world coordinates
00123 (transMat.top()).multpoint3d(a, tmp1);
00124 (transMat.top()).multpoint3d(b, tmp2);
00125
00126 // how to create a dashed line
00127 vec_sub(dirvec, tmp2, tmp1); // vector from a to b
00128 vec_copy(unitdirvec, dirvec);
00129 vec_normalize(unitdirvec); // unit vector from a to b
00130 test = 1;
00131 i = 0;
00132 while (test == 1) {
00133 for (j=0; j<3; j++) {
00134 from[j] = (float) (tmp1[j] + (2*i )*DASH_LENGTH*unitdirvec[j]);
00135 to[j] = (float) (tmp1[j] + (2*i + 1)*DASH_LENGTH*unitdirvec[j]);
00136 }
00137 if (fabsf(tmp1[0] - to[0]) >= fabsf(dirvec[0])) {
00138 vec_copy(to, tmp2);
00139 test = 0;
00140 }
00141
00142 // draw the cylinder
00143 set_color(colorIndex);
00144 fprintf(outfile, "color%d cylinder cyl\n0\n0\n7 ", cur_color);
00145 // first point
00146 fprintf(outfile, "%4f %4f %4f ", ORDER(from[0], from[1], from[2]));
00147 // second point
00148 fprintf(outfile, "%4f %4f %4f ", ORDER(to[0], to[1], to[2]));
00149 // radius
00150 fprintf(outfile, "%4f\n", float(lineWidth)*DEFAULT_RADIUS);
00151 i++;
00152 }
00153 } else {
00154 msgErr << "RadianceDisplayDevice: Unknown line style " << lineStyle << sendmsg;
00155 }
00156 }
00157
00158 // draw a cylinder
00159 void RadianceDisplayDevice::cylinder(float *a, float *b, float r,int /*filled*/) {
00160
00161 float vec1[3], vec2[3];
00162
00163 // transform the world coordinates
00164 (transMat.top()).multpoint3d(a, vec1);
00165 (transMat.top()).multpoint3d(b, vec2);
00166
00167 // draw the cylinder
00168
00169 set_color(colorIndex);
00170
00171 fprintf(outfile, "color%d cylinder cyl\n0\n0\n7 ", cur_color);
00172 // first point
00173 fprintf(outfile, "%4f %4f %4f ",
00174 ORDER(vec1[0], vec1[1], vec1[2]));
00175 // second point
00176 fprintf(outfile, "%4f %4f %4f ",
00177 ORDER(vec2[0], vec2[1], vec2[2]));
00178 // radius
00179 fprintf(outfile, "%4f\n", scale_radius(r));
00180
00181 // and fill in the ends
00182 float normal[3];
00183 vec_sub(normal, vec1, vec2);
00184 vec_normalize(normal);
00185
00186 // one end
00187 set_color(colorIndex);
00188
00189 fprintf(outfile, "color%d ring cyl_end\n0\n0\n8 ", cur_color);
00190 fprintf(outfile, "%4f %4f %4f ", // location
00191 ORDER(vec1[0], vec1[1], vec1[2]));
00192 fprintf(outfile, "%4f %4f %4f ", // normal
00193 ORDER(normal[0], normal[1], normal[2]));
00194 fprintf(outfile, "0 %4f\n", scale_radius(r)); // radii
00195
00196 // the other end
00197 normal[0] = -normal[0];
00198 normal[1] = -normal[1];
00199 normal[2] = -normal[2];
00200 set_color(colorIndex);
00201
00202 fprintf(outfile, "color%d ring cyl_end\n0\n0\n8 ", cur_color);
00203 fprintf(outfile, "%4f %4f %4f ", // location
00204 ORDER(vec2[0], vec2[1], vec2[2]));
00205 fprintf(outfile, "%4f %4f %4f ", // normal
00206 ORDER(normal[0], normal[1], normal[2]));
00207 fprintf(outfile, "0 %4f\n", scale_radius(r)); // radii
00208
00209 }
00210
00211 // draw a two radius cone
00212 void RadianceDisplayDevice::cone_trunc(float *a, float *b, float rad1, float rad2, int /* resolution */) {
00213
00214 float vec1[3], vec2[3];
00215
00216 // transform the world coordinates
00217 (transMat.top()).multpoint3d(a, vec1);
00218 (transMat.top()).multpoint3d(b, vec2);
00219
00220 set_color(colorIndex);
00221
00222 fprintf(outfile, "color%d cone a_cone\n0\n0\n8 ", cur_color);
00223 // first point
00224 fprintf(outfile, "%4f %4f %4f ",
00225 ORDER(vec2[0], vec2[1], vec2[2]));
00226 // second point
00227 fprintf(outfile, "%4f %4f %4f ",
00228 ORDER(vec1[0], vec1[1], vec1[2]));
00229 // radius
00230 fprintf(outfile, "%4f %4f\n", scale_radius(rad2), scale_radius(rad1));
00231 }
00232
00233 // draw a triangle
00234 void RadianceDisplayDevice::triangle(const float *a, const float *b, const float *c, const float *, const float *, const float *) {
00235
00236 float vec1[3], vec2[3], vec3[3];
00237
00238 // transform the world coordinates
00239 (transMat.top()).multpoint3d(a, vec1);
00240 (transMat.top()).multpoint3d(b, vec2);
00241 (transMat.top()).multpoint3d(c, vec3);
00242
00243 // draw the triangle
00244
00245 set_color(colorIndex);
00246
00247 fprintf(outfile, "color%d polygon poly\n0\n0\n9 ", cur_color); // triangle
00248 fprintf(outfile, "%4f %4f %4f ",
00249 ORDER(vec1[0], vec1[1], vec1[2])); // point one
00250 fprintf(outfile, "%4f %4f %4f ",
00251 ORDER(vec2[0], vec2[1], vec2[2])); // point two
00252 fprintf(outfile, "%4f %4f %4f\n",
00253 ORDER(vec3[0], vec3[1], vec3[2])); // point three
00254 }
00255
00256 // draw a square
00257 void RadianceDisplayDevice::square(float *, float *a, float *b, float *c, float *d) {
00258
00259 float vec1[3], vec2[3], vec3[3], vec4[3];
00260
00261 // transform the world coordinates
00262 (transMat.top()).multpoint3d(a, vec1);
00263 (transMat.top()).multpoint3d(b, vec2);
00264 (transMat.top()).multpoint3d(c, vec3);
00265 (transMat.top()).multpoint3d(d, vec4);
00266
00267 // draw the square
00268
00269 set_color(colorIndex);
00270
00271 fprintf(outfile, "color%d polygon poly\n0\n0\n12 ", cur_color); // triangle
00272 fprintf(outfile, "%4f %4f %4f ",
00273 ORDER(vec1[0], vec1[1], vec1[2])); // point one
00274 fprintf(outfile, "%4f %4f %4f ",
00275 ORDER(vec2[0], vec2[1], vec2[2])); // point two
00276 fprintf(outfile, "%4f %4f %4f ",
00277 ORDER(vec3[0], vec3[1], vec3[2])); // point three
00278 fprintf(outfile, "%4f %4f %4f\n",
00279 ORDER(vec4[0], vec4[1], vec4[2])); // point four
00280
00281 }
00282
00284
00285 void RadianceDisplayDevice::set_color(int cIndex)
00286 {
00287 int num = red.num();
00288 int i;
00289
00290 float r = matData[cIndex][0],
00291 g = matData[cIndex][0 + 1],
00292 b = matData[cIndex][0 + 2],
00293 #if 0 /// XXX
00294 t = 1.0f - matData[cIndex][ALPHA_INDEX];
00295 #else
00296 t = 1.0f;
00297 #endif
00298
00299 for (i = 0; i < num; i++) {
00300 if (r == red[i] && g == green[i] && b == blue[i] && t == trans[i]) {
00301 break;
00302 }
00303 }
00304
00305 if (i == num) { // create a new color category
00306 red.append(r);
00307 green.append(g);
00308 blue.append(b);
00309 trans.append(t);
00310 // define it for radiance
00311 if (t != 0) {
00312 fprintf(outfile, "void trans color%d\n0\n0\n7 ", i);
00313 fprintf(outfile, "%f %f %f .05 .00 %f 1.0\n", r, g, b, t);
00314 }
00315 else {
00316 fprintf(outfile, "void plastic color%d\n0\n0\n5 ", i);
00317 fprintf(outfile, "%f %f %f .05 .05\n", r, g, b);
00318 }
00319 }
00320 //else {
00321 // // the color is 'i' so print it
00322 // fprintf(outfile, "color%d ", i);
00323 //}
00324
00325 // Save the current color
00326 cur_color = i;
00327 }
00328
00329
00330 // write comment to file
00331 void RadianceDisplayDevice::comment(const char *s) {
00332 fprintf (outfile, "# %s\n", s);
00333 }
00334
00336
00337 // initialize the file for output
00338 void RadianceDisplayDevice::write_header() {
00339 int i;
00340
00341 // clear out the r/g/b/t arrays
00342 red.clear();
00343 green.clear();
00344 blue.clear();
00345 trans.clear();
00346
00347 fprintf(outfile, "#\n");
00348 fprintf(outfile, "# Radiance input script: %s\n",my_filename);
00349 fprintf(outfile, "#\n");
00350
00351
00352 // write the light sources
00353 fprintf(outfile, "void dielectric invisible\n0\n0\n5 1 1 1 1 0\n");
00354 fprintf(outfile, "void illum bright\n1 invisible\n0\n"
00355 "3 10000 10000 10000\n");
00356
00357 // do this instead of the right way (see later)
00358 // fprintf(outfile, "bright sphere fixture\n0\n0\n4 -10 0 0 .01\n");
00359
00360 // background color is black until I figure out how to set it
00361 // interactively. I'm thinking of having a glowing sphere or plane
00362
00363 for (i = 0; i < DISP_LIGHTS; i++) {
00364 if (lightState[i].on) {
00365 float vec[3];
00366
00367 (transMat.top()).multpoint3d(lightState[i].pos, vec);
00368
00369 fprintf(outfile,
00370 "bright sphere fixture\n0\n0\n4 %f %f %f .01\n",
00371 ORDER(10 * vec[0], 10 * vec[1], 10 * vec[2]));
00372 }
00373 }
00374 }
00375
00376
00377 // clean up after yourself
00378 void RadianceDisplayDevice::write_trailer() {
00379 msgInfo << "Radiance file generation finished" << sendmsg;
00380 reset_vars(); // reset state variables
00381 }
00382
00383
00384