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: RayShadeDisplayDevice.C,v $ 00012 * $Author: johns $ $Locker: $ $State: Exp $ 00013 * $Revision: 1.48 $ $Date: 2020年02月26日 07:21:45 $ 00014 * 00015 ***************************************************************************/ 00021 #include <stdio.h> 00022 #include <string.h> 00023 #include <math.h> 00024 #include <time.h> 00025 #include "RayShadeDisplayDevice.h" 00026 #include "Matrix4.h" 00027 #include "DispCmds.h" 00028 #include "Inform.h" 00029 #include "utilities.h" 00030 #define DEFAULT_RADIUS 0.002f 00031 #define DASH_LENGTH 0.02f 00032 #define SCALE_FACTOR 1.3f 00033 00035 00036 // constructor ... initialize some variables 00037 RayShadeDisplayDevice::RayShadeDisplayDevice() 00038 : FileRenderer("Rayshade", "Rayshade 4.0", "vmdscene.ray", "rayshade < %s > %s.rle") { } 00039 00040 // destructor 00041 RayShadeDisplayDevice::~RayShadeDisplayDevice(void) { } 00042 00044 00045 // fix the scaling 00046 float RayShadeDisplayDevice::scale_fix(float x) { 00047 return ( x / SCALE_FACTOR ); 00048 } 00049 00050 // draw a point 00051 void RayShadeDisplayDevice::point(float * spdata) { 00052 float vec[3]; 00053 00054 // transform the world coordinates 00055 (transMat.top()).multpoint3d(spdata, vec); 00056 00057 write_cindexmaterial(colorIndex, materialIndex); 00058 // draw the sphere 00059 fprintf(outfile, "sphere %5f %5f %5f %5f\n", 00060 scale_fix(float(lineWidth)*DEFAULT_RADIUS), 00061 scale_fix(vec[0]), scale_fix(vec[1]), scale_fix(vec[2])); 00062 } 00063 00064 00065 // draw a sphere 00066 void RayShadeDisplayDevice::sphere(float * spdata) { 00067 float vec[3]; 00068 float radius; 00069 00070 // transform the world coordinates 00071 (transMat.top()).multpoint3d(spdata, vec); 00072 radius = scale_radius(spdata[3]); 00073 00074 write_cindexmaterial(colorIndex, materialIndex); 00075 // draw the sphere 00076 fprintf(outfile, "sphere %5f %5f %5f %5f\n", scale_fix(radius), 00077 scale_fix(vec[0]), scale_fix(vec[1]), scale_fix(vec[2])); 00078 } 00079 00080 00081 00082 // draw a line (cylinder) from a to b 00083 void RayShadeDisplayDevice::line(float *a, float*b) { 00084 int i, j, test; 00085 float dirvec[3], unitdirvec[3]; 00086 float from[3], to[3], tmp1[3], tmp2[3]; 00087 00088 if (lineStyle == ::SOLIDLINE) { 00089 // transform the world coordinates 00090 (transMat.top()).multpoint3d(a, from); 00091 (transMat.top()).multpoint3d(b, to); 00092 00093 write_cindexmaterial(colorIndex, materialIndex); 00094 fprintf(outfile, "cylinder %5f %5f %5f %5f %5f %5f %5f\n", 00095 scale_fix(float(lineWidth)*DEFAULT_RADIUS), 00096 scale_fix(from[0]), scale_fix(from[1]), scale_fix(from[2]), 00097 scale_fix(to[0]), scale_fix(to[1]), scale_fix(to[2])); 00098 00099 } else if (lineStyle == ::DASHEDLINE) { 00100 // transform the world coordinates 00101 (transMat.top()).multpoint3d(a, tmp1); 00102 (transMat.top()).multpoint3d(b, tmp2); 00103 00104 // how to create a dashed line 00105 vec_sub(dirvec, tmp2, tmp1); // vector from a to b 00106 vec_copy(unitdirvec, dirvec); 00107 vec_normalize(unitdirvec); // unit vector from a to b 00108 test = 1; 00109 i = 0; 00110 while (test == 1) { 00111 for (j=0; j<3; j++) { 00112 from[j] = (float) (tmp1[j] + (2*i )*DASH_LENGTH*unitdirvec[j]); 00113 to[j] = (float) (tmp1[j] + (2*i + 1)*DASH_LENGTH*unitdirvec[j]); 00114 } 00115 if (fabsf(tmp1[0] - to[0]) >= fabsf(dirvec[0]) ) { 00116 vec_copy(to, tmp2); 00117 test = 0; 00118 } 00119 00120 // draw the cylinder 00121 write_cindexmaterial(colorIndex, materialIndex); 00122 fprintf(outfile, "cylinder %5f %5f %5f %5f %5f %5f %5f\n", 00123 scale_fix(float(lineWidth)*DEFAULT_RADIUS), 00124 scale_fix(from[0]), scale_fix(from[1]), scale_fix(from[2]), 00125 scale_fix(to[0]), scale_fix(to[1]), scale_fix(to[2])); 00126 i++; 00127 } 00128 } else { 00129 msgErr << "RayShadeDisplayDevice: Unknown line style " << lineStyle << sendmsg; 00130 } 00131 } 00132 00133 00134 // draw a cylinder 00135 void RayShadeDisplayDevice::cylinder(float *a, float *b, float r,int /*filled*/) { 00136 float from[3], to[3]; 00137 float radius; 00138 00139 // transform the world coordinates 00140 (transMat.top()).multpoint3d(a, from); 00141 (transMat.top()).multpoint3d(b, to); 00142 radius = scale_radius(r); 00143 00144 write_cindexmaterial(colorIndex, materialIndex); 00145 fprintf(outfile, "cylinder %5f %5f %5f %5f %5f %5f %5f\n", 00146 scale_fix(radius), 00147 scale_fix(from[0]), scale_fix(from[1]), scale_fix(from[2]), 00148 scale_fix(to[0]), scale_fix(to[1]), scale_fix(to[2])); 00149 00150 // put disks on the ends 00151 fprintf(outfile, "disc %5f %5f %5f %5f %5f %5f %5f\n", 00152 scale_fix(radius), 00153 scale_fix(from[0]), scale_fix(from[1]), scale_fix(from[2]), 00154 scale_fix(from[0]-to[0]), scale_fix(from[1]-to[1]), 00155 scale_fix(from[2]-to[2])); 00156 fprintf(outfile, "disc %5f %5f %5f %5f %5f %5f %5f\n", 00157 scale_fix(radius), 00158 scale_fix(to[0]), scale_fix(to[1]), scale_fix(to[2]), 00159 scale_fix(to[0]-from[0]), scale_fix(to[1]-from[1]), 00160 scale_fix(to[2]-from[2])); 00161 } 00162 00163 // draw a cone 00164 void RayShadeDisplayDevice::cone(float *a, float *b, float r, int /* resolution */) { 00165 float from[3], to[3]; 00166 float radius; 00167 00168 // transform the world coordinates 00169 (transMat.top()).multpoint3d(a, from); 00170 (transMat.top()).multpoint3d(b, to); 00171 radius = scale_radius(r); 00172 00173 write_cindexmaterial(colorIndex, materialIndex); 00174 fprintf(outfile, "cone %5f %5f %5f %5f %5f %5f %5f %5f\n", 00175 scale_fix(radius), 00176 scale_fix(from[0]), scale_fix(from[1]), scale_fix(from[2]), 00177 scale_fix(float(lineWidth)*DEFAULT_RADIUS), 00178 scale_fix(to[0]), scale_fix(to[1]), scale_fix(to[2])); 00179 } 00180 00181 // draw a triangle 00182 void RayShadeDisplayDevice::triangle(const float *a, const float *b, const float *c, const float *n1, const float *n2, const float *n3) { 00183 float vec1[3], vec2[3], vec3[3]; 00184 float norm1[3], norm2[3], norm3[3]; 00185 00186 00187 // transform the world coordinates 00188 (transMat.top()).multpoint3d(a, vec1); 00189 (transMat.top()).multpoint3d(b, vec2); 00190 (transMat.top()).multpoint3d(c, vec3); 00191 00192 // and the normals 00193 (transMat.top()).multnorm3d(n1, norm1); 00194 (transMat.top()).multnorm3d(n2, norm2); 00195 (transMat.top()).multnorm3d(n3, norm3); 00196 00197 write_cindexmaterial(colorIndex, materialIndex); 00198 fprintf(outfile, "triangle %5f %5f %5f %5f %5f %5f ", 00199 scale_fix(vec1[0]), scale_fix(vec1[1]), scale_fix(vec1[2]), 00200 scale_fix(norm1[0]), scale_fix(norm1[1]), scale_fix(norm1[2])); 00201 fprintf(outfile, "%5f %5f %5f %5f %5f %5f ", 00202 scale_fix(vec2[0]), scale_fix(vec2[1]), scale_fix(vec2[2]), 00203 scale_fix(norm2[0]), scale_fix(norm2[1]), scale_fix(norm2[2])); 00204 fprintf(outfile, "%5f %5f %5f %5f %5f %5f\n", 00205 scale_fix(vec3[0]), scale_fix(vec3[1]), scale_fix(vec3[2]), 00206 scale_fix(norm3[0]), scale_fix(norm3[1]), scale_fix(norm3[2])); 00207 } 00208 00210 00211 // initialize the file for output 00212 void RayShadeDisplayDevice::write_header() { 00213 time_t t; 00214 00215 // file for RayShade raytracer. 00216 t = time(NULL); 00217 fprintf(outfile,"/* Rayshade input script: %s\n", my_filename); 00218 fprintf(outfile," Creation date: %s",asctime(localtime(&t))); 00219 fprintf(outfile," ---------------------------- */\n\n"); 00220 00221 00222 // The current view 00223 fprintf(outfile, "\n/* Define current view */\n"); 00224 fprintf(outfile, "eyep %5f %5f %5f\n", eyePos[0], eyePos[1], eyePos[2]); 00225 fprintf(outfile, "lookp %5f %5f %5f\n", eyeDir[0], eyeDir[1], eyeDir[2]); 00226 fprintf(outfile, "up %5f %5f %5f\n", 0.0, 1.0, 0.0); 00227 fprintf(outfile, "fov %5f\n", 45.0); 00228 if (stereo_mode()) { 00229 fprintf(outfile, "eyesep %5f\n", eyesep() ); 00230 } 00231 fprintf(outfile, "maxdepth 10\n"); 00232 00233 // Size of image in pixels 00234 fprintf(outfile, "screen %d %d\n", (int) xSize, (int) ySize); 00235 00236 // Lights 00237 fprintf(outfile, "\n/* Light Definitions */\n"); 00238 00239 for (int i=0;i<DISP_LIGHTS;i++) { 00240 if (lightState[i].on) { 00241 fprintf(outfile, "light %3.2f %3.2f %3.2f ", lightState[i].color[0], 00242 lightState[i].color[1], lightState[i].color[2]); 00243 fprintf(outfile, "directional %5f %5f %5f\n", lightState[i].pos[0], 00244 lightState[i].pos[1], lightState[i].pos[2]); 00245 } 00246 } 00247 00248 // background color 00249 fprintf(outfile, "\n/* Set background color */\n"); 00250 fprintf(outfile, "background %3.2f %3.2f %3.2f\n", 00251 backColor[0], backColor[1], backColor[2]); 00252 00253 // start the objects 00254 fprintf(outfile, "\n/* Start object descriptions */\n"); 00255 // that's all for the header. 00256 } 00257 00258 void RayShadeDisplayDevice::comment(const char *s) { 00259 fprintf (outfile, "\n/* %s */\n", s); 00260 } 00261 00262 00263 // clean up after yourself 00264 void RayShadeDisplayDevice::write_trailer() { 00265 fprintf(outfile,"\n/* End of File */\n"); 00266 msgInfo << "Rayshade file generation finished" << sendmsg; 00267 } 00268 00269 void RayShadeDisplayDevice::write_cindexmaterial(int cindex, int material) { 00270 write_colormaterial((float *) &matData[cindex], material); 00271 } 00272 00273 void RayShadeDisplayDevice::write_colormaterial(float *rgb, int) { 00274 fprintf(outfile, "applysurf diffuse %3.2f %3.2f %3.2f ", 00275 mat_diffuse * rgb[0], 00276 mat_diffuse * rgb[1], 00277 mat_diffuse * rgb[2]); 00278 fprintf(outfile, "specular %3.2f %3.2f %3.2f transp %3.2f", 00279 mat_specular * rgb[0], 00280 mat_specular * rgb[1], 00281 mat_specular * rgb[2], 00282 1.0 - mat_opacity); 00283 fprintf(outfile, "specpow %3.2f\n", mat_shininess); 00284 } 00285