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: VrmlDisplayDevice.C,v $ 00012 * $Author: johns $ $Locker: $ $State: Exp $ 00013 * $Revision: 1.41 $ $Date: 2020年02月26日 06:51:41 $ 00014 * 00015 ***************************************************************************/ 00024 #include <stdio.h> 00025 #include <string.h> 00026 #include <math.h> 00027 #include <stdlib.h> /* this is for the Hash Table */ 00028 00029 #include "VrmlDisplayDevice.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 00039 00040 // constructor ... initialize some variables 00041 VrmlDisplayDevice::VrmlDisplayDevice(void) : 00042 FileRenderer("VRML-1", "VRML 1.0 (VRML94)", "vmdscene.wrl", "true") { 00043 00044 tList = NULL; 00045 } 00046 00048 void VrmlDisplayDevice::set_color(int mycolorIndex) { 00049 write_cindexmaterial(mycolorIndex, materialIndex); 00050 } 00051 00052 // draw a sphere 00053 void VrmlDisplayDevice::sphere(float *xyzr) { 00054 00055 // draw the sphere 00056 fprintf(outfile, "Separator {\nTranslation { translation %f %f %f }\n", 00057 xyzr[0], xyzr[1], xyzr[2]); 00058 00059 fprintf(outfile, "Sphere { radius %f }\n}\n", xyzr[3]); 00060 } 00061 00064 void VrmlDisplayDevice::line(float *a, float*b) { 00065 // ugly and wasteful, but it will work 00066 // I guess I really should have done the "correct" indexing ... 00067 // I'll worry about that later. 00068 fprintf(outfile, "Coordinate3 {point [ %f %f %f, %f %f %f ] }\n", 00069 a[0], a[1], a[2], b[0], b[1], b[2]); 00070 fprintf(outfile, "IndexedLineSet { coordIndex [0, 1, -1] }\n"); 00071 } 00072 00073 static Matrix4 convert_endpoints_to_matrix(float *a, float *b) { 00074 // I need to transform (0,-1,0) - (0,1,0) radius 1 00075 // into a - b 00076 float c[3]; 00077 vec_sub(c, b, a); 00078 00079 float len = distance(a,b); 00080 if (len == 0.0) { 00081 return Matrix4(); 00082 } 00083 00084 Matrix4 trans; 00085 trans.translate( (a[0] + b[0]) / 2.0f, (a[1] + b[1]) / 2.0f, 00086 (a[2] + b[2]) / 2.0f); 00087 00088 // this is a straight copy from transvec, which takes things 00089 // from the x axis to a given vector 00090 Matrix4 rot; 00091 if (c[0] == 0.0 && c[1] == 0.0) { 00092 // then wants the z axis 00093 if (c[2] > 0) { 00094 rot.rot(-90, 'y'); 00095 } else { 00096 rot.rot(-90, 'y'); 00097 } 00098 } else { 00099 float theta, phi; 00100 theta = (float) atan2(c[1], c[0]); 00101 phi = (float) atan2(c[2], sqrt(c[0]*c[0] + c[1]*c[1])); 00102 Matrix4 m1; m1.rot( (float) (-phi * 180.0f / VMD_PI), 'y'); 00103 rot.rot( (float) (theta * 180.0f / VMD_PI), 'z'); 00104 rot.multmatrix(m1); 00105 } 00106 00107 // Compute everything 00108 Matrix4 mat(trans); 00109 mat.multmatrix(rot); 00110 00111 // now bring to the y axis 00112 mat.rot(-90, 'z'); 00113 00114 return mat; 00115 } 00116 00117 // draw a cylinder 00118 void VrmlDisplayDevice::cylinder(float *a, float *b, float r, int filled) { 00119 if (a[0] == b[0] && a[1] == b[1] && a[2] == b[2]) { 00120 return; // we don't serve your kind here 00121 } 00122 00123 push(); 00124 Matrix4 mat = convert_endpoints_to_matrix(a, b); 00125 load(mat); // print matrix 00126 00127 // draw the cylinder 00128 fprintf(outfile, "Cylinder { \n" 00129 "radius %f\n" 00130 "height %f\n" 00131 "parts %s}\n", 00132 r, distance(a,b), filled ? "ALL" : "SIDES"); 00133 00134 // pop out of this matrix 00135 pop(); 00136 } 00137 00138 00139 // draw a cone 00140 void VrmlDisplayDevice::cone(float *a, float *b, float r, int /* resolution */) { 00141 if (a[0] == b[0] && a[1] == b[1] && a[2] == b[2]) { 00142 return; // we don't serve your kind here 00143 } 00144 00145 push(); 00146 Matrix4 mat = convert_endpoints_to_matrix(a, b); 00147 load(mat); // print matrix 00148 00149 // draw the cylinder 00150 fprintf(outfile, "Cone { \n" 00151 "bottomRadius %f\n" 00152 "height %f}\n", 00153 r, distance(a,b)); 00154 00155 // pop out of this matrix 00156 pop(); 00157 } 00158 00159 00160 // draw a triangle 00161 void VrmlDisplayDevice::triangle(const float *a, const float *b, const float *c, 00162 const float *n1, const float *n2, const float *n3) { 00163 fprintf(outfile, 00164 "Normal { vector [\n" 00165 " %f %f %f,\n %f %f %f,\n %f %f %f\n" 00166 " ] }\n", 00167 n1[0], n1[1], n1[2], n2[0], n2[1], n2[2], 00168 n3[0], n3[1], n3[2]); 00169 fprintf(outfile, 00170 "Coordinate3 {point [\n" 00171 " %f %f %f,\n" 00172 " %f %f %f,\n" 00173 " %f %f %f\n" 00174 " ] }\n", 00175 a[0], a[1], a[2], b[0], b[1], b[2], c[0], c[1], c[2]); 00176 fprintf(outfile, "IndexedFaceSet { coordIndex [0, 1, 2, -1] }\n"); 00177 } 00178 00179 void VrmlDisplayDevice::push(void) { 00180 fprintf(outfile, "#push matrix\nSeparator {\n"); 00181 } 00182 00183 void VrmlDisplayDevice::pop(void) { 00184 fprintf(outfile, "#pop matrix\n}\n"); 00185 } 00186 00187 void VrmlDisplayDevice::multmatrix(const Matrix4 &mat) { 00188 fprintf(outfile, "# multmatrix\n"); 00189 load(mat); 00190 } 00191 00192 void VrmlDisplayDevice::load(const Matrix4 &mat) { 00193 fprintf(outfile, 00194 "MatrixTransform {\n" 00195 " matrix %g %g %g %g\n" 00196 " %g %g %g %g\n" 00197 " %g %g %g %g\n" 00198 " %g %g %g %g\n" 00199 "}\n", 00200 mat.mat[0], mat.mat[1], mat.mat[2], mat.mat[3], 00201 mat.mat[4], mat.mat[5], mat.mat[6], mat.mat[7], 00202 mat.mat[8], mat.mat[9], mat.mat[10], mat.mat[11], 00203 mat.mat[12], mat.mat[13], mat.mat[14], mat.mat[15] 00204 ); 00205 } 00206 00207 void VrmlDisplayDevice::comment(const char *s) { 00208 fprintf (outfile, "# %s\n", s); 00209 } 00210 00212 00213 // initialize the file for output 00214 void VrmlDisplayDevice::write_header(void) { 00215 fprintf(outfile, "#VRML V1.0 ascii\n"); 00216 fprintf(outfile, "# Created with VMD: " 00217 "http://www.ks.uiuc.edu/Research/vmd/\n"); 00218 fprintf(outfile, "Separator {\n"); 00219 } 00220 00221 void VrmlDisplayDevice::write_trailer(void) { 00222 fprintf(outfile, "# That's all, folks\n}\n"); 00223 } 00224 00225 void VrmlDisplayDevice::write_cindexmaterial(int cindex, int material) { 00226 write_colormaterial((float *) &matData[cindex], material); 00227 } 00228 00229 void VrmlDisplayDevice::write_colormaterial(float *rgb, int) { 00230 // just grab the current material definition 00231 fprintf(outfile, "Material { \n"); 00232 fprintf(outfile, "diffuseColor %f %f %f\n", 00233 mat_diffuse * rgb[0], 00234 mat_diffuse * rgb[1], 00235 mat_diffuse * rgb[2]); 00236 fprintf(outfile, "ambientColor %f %f %f\n", 00237 mat_ambient * rgb[0], 00238 mat_ambient * rgb[1], 00239 mat_ambient * rgb[2]); 00240 fprintf(outfile, "specularColor %f %f %f\n", 00241 mat_specular * rgb[0], 00242 mat_specular * rgb[1], 00243 mat_specular * rgb[2]); 00244 fprintf(outfile, "shininess %f\n", 00245 mat_shininess); 00246 fprintf(outfile, "transparency %f\n", 00247 1.0 - mat_opacity); 00248 fprintf(outfile, "}\n"); 00249 } 00250