00001 /*************************************************************************** 00002 *cr 00003 *cr (C) Copyright 1995-2019 The Board of Trustees of the 00004 *cr University of Illinois 00005 *cr All Rights Reserved 00006 *cr 00007 ***************************************************************************/ 00008 /*************************************************************************** 00009 * RCS INFORMATION: 00010 * 00011 * $RCSfile: RadianceDisplayDevice.C,v $ 00012 * $Author: johns $ $Locker: $ $State: Exp $ 00013 * $Revision: 1.49 $ $Date: 2020年02月26日 07:21:45 $ 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 // Be careful when you modify the coordinates. To make things view the 00039 // right way, I have to rotate everything around the (x,y,z) = (1,1,1) 00040 // vector so that x->z, y->x, and z->y 00041 00042 #define ORDER(x,y,z) -z, -x, y 00043 00045 00046 // constructor ... initialize some variables 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