Main Page Namespace List Class Hierarchy Alphabetical List Compound List File List Namespace Members Compound Members File Members Related Pages

POV3DisplayDevice.C

Go to the documentation of this file.
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: POV3DisplayDevice.C,v $
00012 * $Author: johns $ $Locker: $ $State: Exp $
00013 * $Revision: 1.129 $ $Date: 2020年07月01日 06:09:05 $
00014 *
00015 ***************************************************************************/
00021 #include <string.h>
00022 #include <stdio.h>
00023 #include <math.h>
00024 #include "POV3DisplayDevice.h"
00025 #include "Matrix4.h"
00026 #include "Inform.h"
00027 #include "utilities.h"
00028 #include "DispCmds.h" // need for line styles
00029 #include "config.h" // for VMDVERSION string
00030 #include "Hershey.h" // needed for Hershey font rendering fctns
00031 
00032 #define DEFAULT_RADIUS 0.002f
00033 #define DASH_LENGTH 0.02f
00034 #define PHONG_DIVISOR 64.0f
00035 
00036 // Enable triangle coordinate scaling hacks to prevent POV-Ray 3.x
00037 // from emitting millions of "all determinants too small" warnings
00038 // when rendering finely tessellated geometry. #$@!#@$@ POV-Ray....
00039 // If/when POV-Ray gets fixed, this hack should gladly be removed.
00040 #define POVRAY_BRAIN_DAMAGE_WORKAROUND 1 
00041 #define POVRAY_SCALEHACK 1000.0f
00042 
00044 
00045 // constructor ... initialize some variables
00046 
00047 POV3DisplayDevice::POV3DisplayDevice() : FileRenderer("POV3", "POV-Ray 3.6", "vmdscene.pov", "povray +W%w +H%h -I%s -O%s.tga +D +X +A +FT") {
00048 reset_vars(); // initialize state variables
00049 }
00050 
00051 // destructor
00052 POV3DisplayDevice::~POV3DisplayDevice(void) { }
00053 
00054 
00055 void POV3DisplayDevice::reset_vars(void) {
00056 degenerate_triangles = 0;
00057 degenerate_cylinders = 0;
00058 degenerate_cones = 0;
00059 memset(&clip_on, 0, sizeof(clip_on));
00060 old_materialIndex = -1;
00061 }
00062 
00063 
00065 
00066 void POV3DisplayDevice::text(float *pos, float size, float thickness,
00067 const char *str) {
00068 float textpos[3];
00069 float textsize, textthickness;
00070 hersheyhandle hh;
00071 
00072 // transform the world coordinates
00073 (transMat.top()).multpoint3d(pos, textpos);
00074 textsize = size * 1.5f;
00075 textthickness = thickness*DEFAULT_RADIUS;
00076 
00077 while (*str != '0円') {
00078 float lm, rm, x, y, ox, oy;
00079 int draw, odraw;
00080 ox=oy=x=y=0.0f;
00081 draw=odraw=0;
00082 
00083 hersheyDrawInitLetter(&hh, *str, &lm, &rm);
00084 textpos[0] -= lm * textsize;
00085 
00086 while (!hersheyDrawNextLine(&hh, &draw, &x, &y)) {
00087 float oldpt[3], newpt[3];
00088 if (draw) {
00089 newpt[0] = textpos[0] + textsize * x;
00090 newpt[1] = textpos[1] + textsize * y;
00091 newpt[2] = textpos[2];
00092 
00093 if (odraw) {
00094 // if we have both previous and next points, connect them...
00095 oldpt[0] = textpos[0] + textsize * ox;
00096 oldpt[1] = textpos[1] + textsize * oy;
00097 oldpt[2] = textpos[2];
00098 
00099 fprintf(outfile, "VMD_cylinder(<%.8f,%.8f,%.8f>,<%.8f,%.8f,%.8f>",
00100 oldpt[0], oldpt[1], -oldpt[2], newpt[0], newpt[1], -newpt[2]);
00101 fprintf(outfile, "%.4f,rgbt<%.3f,%.3f,%.3f,%.3f>,%d)\n",
00102 textthickness, matData[colorIndex][0], matData[colorIndex][1],
00103 matData[colorIndex][2], 1 - mat_opacity, 1);
00104 
00105 fprintf(outfile, "VMD_sphere(<%.4f,%.4f,%.4f>,%.4f,",
00106 newpt[0], newpt[1], -newpt[2], textthickness);
00107 fprintf(outfile, "rgbt<%.3f,%.3f,%.3f,%.3f>)\n",
00108 matData[colorIndex][0], matData[colorIndex][1], 
00109 matData[colorIndex][2], 1 - mat_opacity);
00110 } else {
00111 // ...otherwise, just draw the next point
00112 fprintf(outfile, "VMD_sphere(<%.4f,%.4f,%.4f>,%.4f,",
00113 newpt[0], newpt[1], -newpt[2], textthickness);
00114 fprintf(outfile, "rgbt<%.3f,%.3f,%.3f,%.3f>)\n",
00115 matData[colorIndex][0], matData[colorIndex][1], 
00116 matData[colorIndex][2], 1 - mat_opacity);
00117 }
00118 }
00119 
00120 ox=x;
00121 oy=y;
00122 odraw=draw;
00123 }
00124 textpos[0] += rm * textsize;
00125 
00126 str++;
00127 }
00128 }
00129 
00130 
00131 // draw a point
00132 void POV3DisplayDevice::point(float * spdata) {
00133 float vec[3];
00134 // transform the world coordinates
00135 (transMat.top()).multpoint3d(spdata, vec);
00136 
00137 // write_materials();
00138 
00139 // Draw the point
00140 fprintf(outfile, "VMD_point(<%.4f,%.4f,%.4f>,%.4f,rgbt<%.3f,%.3f,%.3f,%.3f>)\n",
00141 vec[0], vec[1], -vec[2], ((float)pointSize)*DEFAULT_RADIUS, 
00142 matData[colorIndex][0], matData[colorIndex][1], 
00143 matData[colorIndex][2], 1 - mat_opacity);
00144 }
00145 
00146 // draw a sphere
00147 void POV3DisplayDevice::sphere(float * spdata) {
00148 float vec[3];
00149 float radius;
00150 
00151 // transform the world coordinates
00152 (transMat.top()).multpoint3d(spdata, vec);
00153 radius = scale_radius(spdata[3]);
00154 
00155 // write_materials();
00156 
00157 // Draw the sphere
00158 fprintf(outfile, "VMD_sphere(<%.4f,%.4f,%.4f>,%.4f,",
00159 vec[0], vec[1], -vec[2], radius);
00160 fprintf(outfile, "rgbt<%.3f,%.3f,%.3f,%.3f>)\n",
00161 matData[colorIndex][0], matData[colorIndex][1], matData[colorIndex][2],
00162 1 - mat_opacity);
00163 }
00164 
00165 // draw a line from a to b
00166 void POV3DisplayDevice::line(float *a, float*b) {
00167 int i, j, test;
00168 float dirvec[3], unitdirvec[3];
00169 float from[3], to[3], tmp1[3], tmp2[3];
00170 
00171 if (lineStyle == ::SOLIDLINE) {
00172 // transform the world coordinates
00173 (transMat.top()).multpoint3d(a, from);
00174 (transMat.top()).multpoint3d(b, to);
00175 
00176 // write_materials();
00177 
00178 // Draw the line
00179 fprintf(outfile, "VMD_line(<%.4f,%.4f,%.4f>,<%.4f,%.4f,%.4f>,",
00180 from[0], from[1], -from[2], to[0], to[1], -to[2]);
00181 fprintf(outfile, "rgbt<%.3f,%.3f,%.3f,%.3f>)\n",
00182 matData[colorIndex][0], matData[colorIndex][1], matData[colorIndex][2],
00183 1 - mat_opacity);
00184 
00185 } 
00186 else if (lineStyle == ::DASHEDLINE) {
00187 // transform the world coordinates
00188 (transMat.top()).multpoint3d(a, tmp1);
00189 (transMat.top()).multpoint3d(b, tmp2);
00190 
00191 // how to create a dashed line
00192 vec_sub(dirvec, tmp2, tmp1); // vector from a to b
00193 vec_copy(unitdirvec, dirvec);
00194 vec_normalize(unitdirvec); // unit vector from a to b
00195 test = 1;
00196 i = 0;
00197 while (test == 1) {
00198 for (j=0; j<3; j++) {
00199 from[j] = (float) (tmp1[j] + (2*i)*DASH_LENGTH*unitdirvec[j]);
00200 to[j] = (float) (tmp1[j] + (2*i + 1)*DASH_LENGTH*unitdirvec[j]);
00201 }
00202 if (fabsf(tmp1[0] - to[0]) >= fabsf(dirvec[0])) {
00203 vec_copy(to, tmp2);
00204 test = 0;
00205 }
00206 
00207 // write_materials();
00208 
00209 // Draw the line
00210 fprintf(outfile, "VMD_line(<%.4f,%.4f,%.4f>,<%.4f,%.4f,%.4f>,",
00211 from[0], from[1], -from[2], to[0], to[1], -to[2]);
00212 fprintf(outfile, "rgbt<%.3f,%.3f,%.3f,%.3f>)\n",
00213 matData[colorIndex][0], matData[colorIndex][1], matData[colorIndex][2],
00214 1 - mat_opacity);
00215 
00216 i++;
00217 }
00218 } 
00219 else {
00220 msgErr << "POV3DisplayDevice: Unknown line style " << lineStyle << sendmsg;
00221 }
00222 }
00223 
00224 
00225 // draw a cylinder
00226 void POV3DisplayDevice::cylinder(float *a, float *b, float r, int filled) {
00227 float from[3], to[3];
00228 float radius;
00229 
00230 // transform the world coordinates
00231 (transMat.top()).multpoint3d(a, from);
00232 (transMat.top()).multpoint3d(b, to);
00233 radius = scale_radius(r);
00234 
00235 // check for degenerate cylinders
00236 if ( ((from[0]-to[0])*(from[0]-to[0]) +
00237 (from[1]-to[1])*(from[1]-to[1]) +
00238 (from[2]-to[2])*(from[2]-to[2])) < 1e-20 ) {
00239 degenerate_cylinders++;
00240 return;
00241 }
00242 
00243 // write_materials();
00244 
00245 fprintf(outfile, "VMD_cylinder(<%g,%g,%g>,<%g,%g,%g>",
00246 from[0], from[1], -from[2], to[0], to[1], -to[2]);
00247 fprintf(outfile, "%.4f,rgbt<%.3f,%.3f,%.3f,%.3f>,%d)\n",
00248 radius, matData[colorIndex][0], matData[colorIndex][1],
00249 matData[colorIndex][2], 1 - mat_opacity, !filled);
00250 }
00251 
00252 // draw a cone
00253 void POV3DisplayDevice::cone(float *a, float *b, float r, int /* resolution */) {
00254 float from[3], to[3];
00255 float radius;
00256 
00257 // transform the world coordinates
00258 (transMat.top()).multpoint3d(a, from);
00259 (transMat.top()).multpoint3d(b, to);
00260 radius = scale_radius(r);
00261 
00262 // check for degenerate cylinders
00263 if ( ((from[0]-to[0])*(from[0]-to[0]) +
00264 (from[1]-to[1])*(from[1]-to[1]) +
00265 (from[2]-to[2])*(from[2]-to[2])) < 1e-20 ) {
00266 degenerate_cones++;
00267 return;
00268 }
00269 
00270 // write_materials();
00271 
00272 // Draw the cone
00273 fprintf(outfile, "VMD_cone (<%g,%g,%g>,<%g,%g,%g>,%.4f,",
00274 from[0], from[1], -from[2], to[0], to[1], -to[2], radius);
00275 fprintf(outfile, "rgbt<%.3f,%.3f,%.3f,%.3f>)\n",
00276 matData[colorIndex][0], matData[colorIndex][1], matData[colorIndex][2],
00277 1 - mat_opacity);
00278 }
00279 
00280 // draw a triangle using the current color
00281 // XXX - POV-Ray doesn't support indexed color for triangles -- we need to
00282 // use an RGB triple. Here we just use the same RGB triple for each vertex
00283 // and call tricolor.
00284 void POV3DisplayDevice::triangle(const float *a, const float *b, const float *c, 
00285 const float *n1, const float *n2, const float *n3) {
00286 float c1[3], c2[3], c3[3];
00287 
00288 memcpy(c1, matData[colorIndex], 3 * sizeof(float));
00289 memcpy(c2, matData[colorIndex], 3 * sizeof(float));
00290 memcpy(c3, matData[colorIndex], 3 * sizeof(float));
00291 
00292 tricolor(a, b, c, n1, n2, n3, c1, c2, c3);
00293 return;
00294 }
00295 
00296 // draw triangle with per-vertex colors
00297 void POV3DisplayDevice::tricolor(const float * xyz1, const float * xyz2, const float * xyz3,
00298 const float * n1, const float * n2, const float * n3,
00299 const float *c1, const float *c2, const float *c3) {
00300 float vec1[3], vec2[3], vec3[3], norm1[3], norm2[3], norm3[3];
00301 float leg1[3], leg2[3], trinorm[3], ang1, ang2, ang3;
00302 
00303 // transform the world coordinates
00304 (transMat.top()).multpoint3d(xyz1, vec1);
00305 (transMat.top()).multpoint3d(xyz2, vec2);
00306 (transMat.top()).multpoint3d(xyz3, vec3);
00307 
00308 // and the normals
00309 (transMat.top()).multnorm3d(n1, norm1);
00310 (transMat.top()).multnorm3d(n2, norm2);
00311 (transMat.top()).multnorm3d(n3, norm3);
00312 
00313 // write_materials();
00314 
00315 // Don't write degenerate triangles -- those with all normals more than 90
00316 // degrees from triangle normal or its inverse.
00317 vec_sub(leg1, vec2, vec1);
00318 vec_sub(leg2, vec3, vec1);
00319 cross_prod(trinorm, leg1, leg2);
00320 ang1 = dot_prod(trinorm, norm1);
00321 ang2 = dot_prod(trinorm, norm2);
00322 ang3 = dot_prod(trinorm, norm3);
00323 if ( ((ang1 >= 0.0) || (ang2 >= 0.0) || (ang3 >= 0.0)) &&
00324 ((ang1 <= 0.0) || (ang2 <= 0.0) || (ang3 <= 0.0)) ) {
00325 degenerate_triangles++;
00326 return;
00327 }
00328 
00329 // If all verticies have the same color, don't bother with per-vertex
00330 // coloring
00331 if ( (c1[0] == c2[0]) && (c1[0] == c3[0]) &&
00332 (c1[1] == c2[1]) && (c1[1] == c3[1]) &&
00333 (c1[2] == c2[2]) && (c1[2] == c3[2]) ) {
00334 fprintf(outfile, "VMD_triangle(");
00335 fprintf(outfile, "<%.8g,%.8g,%.8g>,<%.8g,%.8g,%.8g>,<%.8g,%.8g,%.8g>,",
00336 vec1[0], vec1[1], -vec1[2], vec2[0], vec2[1], -vec2[2], 
00337 vec3[0], vec3[1], -vec3[2]);
00338 fprintf(outfile, "<%.8g,%.8g,%.8g>,<%.8g,%.8g,%.8g>,<%.8g,%.8g,%.8g>,",
00339 norm1[0], norm1[1], -norm1[2], norm2[0], norm2[1], -norm2[2], 
00340 norm3[0], norm3[1], -norm3[2]);
00341 fprintf(outfile, "rgbt<%.3f,%.3f,%.3f,%.3f>)\n",
00342 c1[0], c1[1], c1[2], 1 - mat_opacity);
00343 }
00344 else {
00345 fprintf(outfile, "VMD_tricolor(");
00346 fprintf(outfile, "<%.8g,%.8g,%.8g>,<%.8g,%.8g,%.8g>,<%.8g,%.8g,%.8g>,",
00347 vec1[0], vec1[1], -vec1[2], vec2[0], vec2[1], -vec2[2], 
00348 vec3[0], vec3[1], -vec3[2]);
00349 fprintf(outfile, "<%.8g,%.8g,%.8g>,<%.8g,%.8g,%.8g>,<%.8g,%.8g,%.8g>,",
00350 norm1[0], norm1[1], -norm1[2], norm2[0], norm2[1], -norm2[2], 
00351 norm3[0], norm3[1], -norm3[2]);
00352 fprintf(outfile, "rgbt<%.3f,%.3f,%.3f,%.3f>,rgbt<%.3f,%.3f,%.3f,%.3f>,rgbt<%.3f,%.3f,%.3f,%.3f>)\n",
00353 c1[0], c1[1], c1[2], 1 - mat_opacity, c2[0], c2[1], c2[2], 
00354 1 - mat_opacity, c3[0], c3[1], c3[2], 1 - mat_opacity);
00355 }
00356 }
00357 
00358 #if 1
00359 // Draw a triangle mesh as a mesh2 POV-Ray object
00360 void POV3DisplayDevice::trimesh_c4n3v3(int numverts, float *cnv, 
00361 int numfacets, int *facets) {
00362 int i;
00363 
00364 // write_materials();
00365 
00366 if (clip_on[2]) {
00367 fprintf(outfile, "intersection {\n");
00368 }
00369 fprintf(outfile, "mesh2 {\n");
00370 
00371 // Print the Vertex Vectors
00372 fprintf(outfile, " vertex_vectors {\n");
00373 fprintf(outfile, " %d,\n", numverts);
00374 for (i=0; i<numverts; i++) {
00375 int ind = i * 10;
00376 float vtmp[3];
00377 transMat.top().multpoint3d(cnv + ind + 7, vtmp);
00378 #if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND)
00379 vtmp[0] *= POVRAY_SCALEHACK;
00380 vtmp[1] *= POVRAY_SCALEHACK;
00381 vtmp[2] *= POVRAY_SCALEHACK;
00382 #endif
00383 fprintf(outfile, " <%.4f,%.4f,%.4f>,\n", vtmp[0], vtmp[1], -vtmp[2]);
00384 }
00385 fprintf(outfile, " }\n");
00386 
00387 // Print the Normal Vectors
00388 fprintf(outfile, " normal_vectors {\n");
00389 fprintf(outfile, " %d,\n", numverts);
00390 for (i=0; i<numverts; i++) {
00391 int ind = i * 10;
00392 float ntmp[3];
00393 transMat.top().multnorm3d(cnv + ind + 4, ntmp);
00394 fprintf(outfile, " <%.4f,%.4f,%.4f>,\n", ntmp[0], ntmp[1], -ntmp[2]);
00395 }
00396 fprintf(outfile, " }\n");
00397 
00398 // Print the Texture List
00399 fprintf(outfile, " texture_list {\n");
00400 fprintf(outfile, " %d,\n", numverts);
00401 for (i=0; i<numverts; i++) {
00402 int ind = i * 10;
00403 float *rgb = cnv + ind;
00404 fprintf(outfile, " VMDC(<%.3f,%.3f,%.3f,%.3f>)\n", 
00405 rgb[0], rgb[1], rgb[2], 1 - mat_opacity);
00406 }
00407 fprintf(outfile, " }\n");
00408 
00409 // Face Indices
00410 fprintf(outfile, " face_indices {\n");
00411 fprintf(outfile, " %d\n", numfacets);
00412 for (i = 0; i < numfacets; i++) {
00413 int ind = i * 3;
00414 
00415 fprintf(outfile, " <%d,%d,%d>,%d,%d,%d\n",
00416 facets[ind], facets[ind + 1], facets[ind + 2], 
00417 facets[ind], facets[ind + 1], facets[ind + 2]);
00418 }
00419 fprintf(outfile, " }\n");
00420 
00421 // Object Modifiers
00422 fprintf(outfile, " inside_vector <0, 0, 1>\n");
00423 if (clip_on[1]) {
00424 #if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND)
00425 fprintf(outfile, " clipped_by { VMD_scaledclip[1] }\n");
00426 #else
00427 fprintf(outfile, " clipped_by { VMD_clip[1] }\n");
00428 #endif
00429 }
00430 if (!shadows_enabled())
00431 fprintf(outfile, " no_shadow\n");
00432 
00433 #if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND)
00434 Matrix4 hackmatrix;
00435 hackmatrix.identity();
00436 hackmatrix.scale(1.0f / POVRAY_SCALEHACK);
00437 const float *trans = hackmatrix.mat;
00438 fprintf(outfile, "matrix < \n");
00439 fprintf(outfile, " %f, %f, %f,\n", trans[ 0], trans[ 1], trans[ 2]);
00440 fprintf(outfile, " %f, %f, %f,\n", trans[ 4], trans[ 5], trans[ 6]);
00441 fprintf(outfile, " %f, %f, %f,\n", trans[ 8], trans[ 9], trans[10]);
00442 fprintf(outfile, " %f, %f, %f \n", trans[12], trans[13], trans[14]);
00443 fprintf(outfile, "> ");
00444 #endif
00445 
00446 fprintf(outfile, "}\n");
00447 
00448 if (clip_on[2]) {
00449 fprintf(outfile, " VMD_clip[2]\n");
00450 if (!shadows_enabled())
00451 fprintf(outfile, " no_shadow\n");
00452 fprintf(outfile, "}\n");
00453 }
00454 }
00455 
00456 #else
00457 
00458 // Draw a triangle mesh as a mesh2 POV-Ray object
00459 void POV3DisplayDevice::trimesh_c4n3v3(int numverts, float *cnv, 
00460 int numfacets, int *facets) {
00461 float (*vert)[3], (*norm)[3], (*color)[3];
00462 int i, ind, v0, v1, v2, *c_index, curr_index;
00463 
00464 // write_materials();
00465 
00466 if (clip_on[2]) {
00467 fprintf(outfile, "intersection {\n");
00468 }
00469 fprintf(outfile, "mesh2 {\n");
00470 
00471 // Read the mesh, storing vertex coordinates, normals, and (unique) colors
00472 // XXX - this can use a *lot* of memory, but not as much as POV will when
00473 // parsing the resulting scene file.
00474 vert = new float[numfacets * 3][3];
00475 norm = new float[numfacets * 3][3];
00476 color = new float[numfacets * 3][3];
00477 c_index = new int[numfacets * 3];
00478 curr_index = -1;
00479 
00480 float prev_color[3] = { -1, -1, -1 };
00481 for (i = 0; i < numfacets; i++) {
00482 ind = i * 3;
00483 v0 = facets[ind ] * 10;
00484 v1 = facets[ind + 1] * 10;
00485 v2 = facets[ind + 2] * 10;
00486 
00487 // transform the verticies and store them in the array
00488 transMat.top().multpoint3d(cnv + v0 + 7, vert[ind ]);
00489 transMat.top().multpoint3d(cnv + v1 + 7, vert[ind + 1]);
00490 transMat.top().multpoint3d(cnv + v2 + 7, vert[ind + 2]);
00491 
00492 // transform the normals and store them in the array
00493 transMat.top().multnorm3d(cnv + v0 + 4, norm[ind ]);
00494 transMat.top().multnorm3d(cnv + v1 + 4, norm[ind + 1]);
00495 transMat.top().multnorm3d(cnv + v2 + 4, norm[ind + 2]);
00496 
00497 #if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND)
00498 vert[ind ][0] *= POVRAY_SCALEHACK;
00499 vert[ind ][1] *= POVRAY_SCALEHACK;
00500 vert[ind ][2] *= POVRAY_SCALEHACK;
00501 vert[ind + 1][0] *= POVRAY_SCALEHACK;
00502 vert[ind + 1][1] *= POVRAY_SCALEHACK;
00503 vert[ind + 1][2] *= POVRAY_SCALEHACK;
00504 vert[ind + 2][0] *= POVRAY_SCALEHACK;
00505 vert[ind + 2][1] *= POVRAY_SCALEHACK;
00506 vert[ind + 2][2] *= POVRAY_SCALEHACK;
00507 #endif
00508 
00509 // Only store a color if it's different than the previous color,
00510 // this saves a lot of space for large triangle meshes.
00511 if (memcmp(prev_color, (cnv + v0), 3*sizeof(float)) != 0) {
00512 curr_index++;
00513 memcpy(color[curr_index], (cnv + v0), 3*sizeof(float));
00514 memcpy(prev_color, (cnv + v0), 3*sizeof(float));
00515 }
00516 c_index[ind] = curr_index;
00517 
00518 if (memcmp(prev_color, (cnv + v1), 3*sizeof(float)) != 0) {
00519 curr_index++;
00520 memcpy(color[curr_index], (cnv + v1), 3*sizeof(float));
00521 memcpy(prev_color, (cnv + v1), 3*sizeof(float));
00522 }
00523 c_index[ind+1] = curr_index;
00524 
00525 if (memcmp(prev_color, (cnv + v2), 3*sizeof(float)) != 0) {
00526 curr_index++;
00527 memcpy(color[curr_index], (cnv + v2), 3*sizeof(float));
00528 memcpy(prev_color, (cnv + v2), 3*sizeof(float));
00529 }
00530 c_index[ind+2] = curr_index;
00531 }
00532 
00533 // Print the Vertex Vectors
00534 fprintf(outfile, " vertex_vectors {\n");
00535 fprintf(outfile, " %d,\n", numfacets * 3);
00536 for (i = 0; i < (numfacets * 3); i++) {
00537 fprintf(outfile, " <%.4f,%.4f,%.4f>,\n", 
00538 vert[i][0], vert[i][1], -vert[i][2]);
00539 }
00540 fprintf(outfile, " }\n");
00541 
00542 // Print the Normal Vectors
00543 fprintf(outfile, " normal_vectors {\n");
00544 fprintf(outfile, " %d,\n", numfacets * 3);
00545 for (i = 0; i < (numfacets * 3); i++) {
00546 fprintf(outfile, " <%.4f,%.4f,%.4f>,\n", 
00547 norm[i][0], norm[i][1], -norm[i][2]);
00548 }
00549 fprintf(outfile, " }\n");
00550 
00551 // Print the Texture List
00552 fprintf(outfile, " texture_list {\n");
00553 fprintf(outfile, " %d,\n", curr_index+1);
00554 for (i = 0; i <= curr_index; i++) {
00555 fprintf(outfile, " VMDC(<%.3f,%.3f,%.3f,%.3f>)\n", 
00556 color[i][0], color[i][1], color[i][2], 1 - mat_opacity);
00557 }
00558 fprintf(outfile, " }\n");
00559 
00560 // Face Indices
00561 fprintf(outfile, " face_indices {\n");
00562 fprintf(outfile, " %d\n", numfacets);
00563 for (i = 0; i < numfacets; i++) {
00564 ind = i * 3;
00565 
00566 // Print three vertex/normal and color indicies.
00567 if ((c_index[ind] == c_index[ind+1]) && (c_index[ind] == c_index[ind+2])) {
00568 // Only one color index is required if the triangle doesn't use
00569 // per-vertex shading
00570 fprintf(outfile, " <%d,%d,%d>,%d\n",
00571 ind, ind + 1, ind + 2, c_index[ind]);
00572 }
00573 else {
00574 fprintf(outfile, " <%d,%d,%d>,%d,%d,%d\n",
00575 ind, ind + 1, ind + 2, 
00576 c_index[ind], c_index[ind+1], c_index[ind+2]);
00577 }
00578 }
00579 fprintf(outfile, " }\n");
00580 
00581 // Object Modifiers
00582 fprintf(outfile, " inside_vector <0, 0, 1>\n");
00583 if (clip_on[1]) {
00584 #if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND)
00585 fprintf(outfile, " clipped_by { VMD_scaledclip[1] }\n");
00586 #else
00587 fprintf(outfile, " clipped_by { VMD_clip[1] }\n");
00588 #endif
00589 }
00590 if (!shadows_enabled())
00591 fprintf(outfile, " no_shadow\n");
00592 
00593 #if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND)
00594 Matrix4 hackmatrix;
00595 hackmatrix.identity();
00596 hackmatrix.scale(1.0f / POVRAY_SCALEHACK);
00597 const float *trans = hackmatrix.mat;
00598 fprintf(outfile, "matrix < \n");
00599 fprintf(outfile, " %f, %f, %f,\n", trans[ 0], trans[ 1], trans[ 2]);
00600 fprintf(outfile, " %f, %f, %f,\n", trans[ 4], trans[ 5], trans[ 6]);
00601 fprintf(outfile, " %f, %f, %f,\n", trans[ 8], trans[ 9], trans[10]);
00602 fprintf(outfile, " %f, %f, %f \n", trans[12], trans[13], trans[14]);
00603 fprintf(outfile, "> ");
00604 #endif
00605 
00606 fprintf(outfile, "}\n");
00607 
00608 if (clip_on[2]) {
00609 fprintf(outfile, " VMD_clip[2]\n");
00610 if (!shadows_enabled())
00611 fprintf(outfile, " no_shadow\n");
00612 fprintf(outfile, "}\n");
00613 }
00614 
00615 delete [] vert;
00616 delete [] norm;
00617 delete [] color;
00618 delete [] c_index;
00619 }
00620 #endif
00621 
00622 
00623 // Draw a triangle mesh as a mesh2 POV-Ray object
00624 void POV3DisplayDevice::trimesh_c4u_n3b_v3f(unsigned char *c, signed char *n,
00625 float *v, int numfacets) {
00626 int i;
00627 int numverts = 3*numfacets;
00628 
00629 const float ci2f = 1.0f / 255.0f; // used for uchar2float and normal conv
00630 const float cn2f = 1.0f / 127.5f;
00631 
00632 // write_materials();
00633 
00634 if (clip_on[2]) {
00635 fprintf(outfile, "intersection {\n");
00636 }
00637 fprintf(outfile, "mesh2 {\n");
00638 
00639 // Read the mesh storing a list of unique colors
00640 float (*color)[3] = new float[numverts][3];
00641 int *c_index = new int[numverts];
00642 int curr_index = -1;
00643 float prev_color[3] = { -1, -1, -1 };
00644 for (i = 0; i < numverts; i++) {
00645 // Only store a color if it's different than the previous color,
00646 // this saves a lot of space for large triangle meshes.
00647 float ctmp[3];
00648 int ind = i * 4;
00649 ctmp[0] = c[ind ] * ci2f; 
00650 ctmp[1] = c[ind+1] * ci2f; 
00651 ctmp[2] = c[ind+2] * ci2f; 
00652 if (memcmp(prev_color, ctmp, 3*sizeof(float)) != 0) {
00653 curr_index++;
00654 memcpy(color[curr_index], ctmp, 3*sizeof(float));
00655 memcpy(prev_color, ctmp, 3*sizeof(float));
00656 }
00657 c_index[i] = curr_index;
00658 }
00659 
00660 // Print the Vertex Vectors
00661 fprintf(outfile, " vertex_vectors {\n");
00662 fprintf(outfile, " %d,\n", numverts);
00663 for (i = 0; i < numverts; i++) {
00664 int ind = i * 3;
00665 float vtmp[3];
00666 transMat.top().multpoint3d(v+ind, vtmp);
00667 
00668 #if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND)
00669 vtmp[0] *= POVRAY_SCALEHACK;
00670 vtmp[1] *= POVRAY_SCALEHACK;
00671 vtmp[2] *= POVRAY_SCALEHACK;
00672 #endif
00673 
00674 fprintf(outfile, " <%.4f,%.4f,%.4f>,\n", vtmp[0], vtmp[1], -vtmp[2]);
00675 }
00676 fprintf(outfile, " }\n");
00677 
00678 // Print the Normal Vectors
00679 fprintf(outfile, " normal_vectors {\n");
00680 fprintf(outfile, " %d,\n", numverts);
00681 for (i = 0; i < numverts; i++) {
00682 int ind = i * 3;
00683 float ntmp[3], ntmp2[3];
00684 
00685 // conversion from GLbyte format, Table 2.6, p. 44 of OpenGL spec 1.2.1
00686 // float = (2c+1)/(2^8-1)
00687 ntmp[0] = n[ind ] * cn2f + ci2f;
00688 ntmp[1] = n[ind+1] * cn2f + ci2f;
00689 ntmp[2] = n[ind+2] * cn2f + ci2f;
00690 
00691 // transform the normals and store them in the array
00692 transMat.top().multnorm3d(ntmp, ntmp2);
00693 fprintf(outfile, " <%.3f,%.3f,%.3f>,\n", ntmp2[0], ntmp2[1], -ntmp[2]);
00694 }
00695 fprintf(outfile, " }\n");
00696 
00697 // Print the Texture List
00698 fprintf(outfile, " texture_list {\n");
00699 fprintf(outfile, " %d,\n", curr_index+1);
00700 for (i = 0; i <= curr_index; i++) {
00701 fprintf(outfile, " VMDC(<%.3f,%.3f,%.3f,%.3f>)\n", 
00702 color[i][0], color[i][1], color[i][2], 1 - mat_opacity);
00703 }
00704 fprintf(outfile, " }\n");
00705 
00706 // Face Indices
00707 fprintf(outfile, " face_indices {\n");
00708 fprintf(outfile, " %d\n", numfacets);
00709 for (i = 0; i < numfacets; i++) {
00710 int ind = i * 3;
00711 
00712 // Print three vertex/normal and color indicies.
00713 if ((c_index[ind] == c_index[ind+1]) && (c_index[ind] == c_index[ind+2])) {
00714 // Only one color index is required if the triangle doesn't use
00715 // per-vertex shading
00716 fprintf(outfile, " <%d,%d,%d>,%d\n",
00717 ind, ind + 1, ind + 2, c_index[ind]);
00718 }
00719 else {
00720 fprintf(outfile, " <%d,%d,%d>,%d,%d,%d\n",
00721 ind, ind + 1, ind + 2, 
00722 c_index[ind], c_index[ind+1], c_index[ind+2]);
00723 }
00724 }
00725 fprintf(outfile, " }\n");
00726 
00727 // Object Modifiers
00728 fprintf(outfile, " inside_vector <0, 0, 1>\n");
00729 if (clip_on[1]) {
00730 #if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND)
00731 fprintf(outfile, " clipped_by { VMD_scaledclip[1] }\n");
00732 #else
00733 fprintf(outfile, " clipped_by { VMD_clip[1] }\n");
00734 #endif
00735 }
00736 if (!shadows_enabled())
00737 fprintf(outfile, " no_shadow\n");
00738 
00739 #if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND)
00740 Matrix4 hackmatrix;
00741 hackmatrix.identity();
00742 hackmatrix.scale(1.0f / POVRAY_SCALEHACK);
00743 const float *trans = hackmatrix.mat;
00744 fprintf(outfile, "matrix < \n");
00745 fprintf(outfile, " %f, %f, %f,\n", trans[ 0], trans[ 1], trans[ 2]);
00746 fprintf(outfile, " %f, %f, %f,\n", trans[ 4], trans[ 5], trans[ 6]);
00747 fprintf(outfile, " %f, %f, %f,\n", trans[ 8], trans[ 9], trans[10]);
00748 fprintf(outfile, " %f, %f, %f \n", trans[12], trans[13], trans[14]);
00749 fprintf(outfile, "> ");
00750 #endif
00751 
00752 fprintf(outfile, "}\n");
00753 
00754 if (clip_on[2]) {
00755 fprintf(outfile, " VMD_clip[2]\n");
00756 if (!shadows_enabled())
00757 fprintf(outfile, " no_shadow\n");
00758 fprintf(outfile, "}\n");
00759 }
00760 
00761 delete [] color;
00762 delete [] c_index;
00763 }
00764 
00765 
00766 // Draw a collection of triangle strips as a mesh2 POV-Ray object
00767 void POV3DisplayDevice::tristrip(int numverts, const float *cnv, 
00768 int numstrips, const int *vertsperstrip, 
00769 const int *facets) {
00770 int strip, v, i, numfacets;
00771 float (*vert)[3], (*norm)[3], (*color)[3];
00772 
00773 // POV-Ray does use triangle winding-order to determine the orientation of
00774 // a triangle. Although the default triangle macro doesn't make use of
00775 // this, the interior_texture property can be specified to give
00776 // back-facing triangles a different texture.
00777 int stripaddr[2][3] = { {0, 1, 2}, {1, 0, 2} };
00778 
00779 // write_materials();
00780 
00781 if (clip_on[2]) {
00782 fprintf(outfile, "intersection {\n");
00783 }
00784 fprintf(outfile, "mesh2 {\n");
00785 
00786 // Read the mesh, storing vertex coordinates, normals, and colors
00787 // XXX - this can use a *lot* of memory, but not as much as POV will when
00788 // parsing the resulting scene file.
00789 vert = new float[numverts][3];
00790 norm = new float[numverts][3];
00791 color = new float[numverts][3];
00792 
00793 for (i = 0; i < numverts; i++) {
00794 transMat.top().multpoint3d(cnv + i*10 + 7, vert[i]);
00795 transMat.top().multnorm3d(cnv + i*10 + 4, norm[i]);
00796 
00797 #if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND)
00798 vert[i][0] *= POVRAY_SCALEHACK;
00799 vert[i][1] *= POVRAY_SCALEHACK;
00800 vert[i][2] *= POVRAY_SCALEHACK;
00801 #endif
00802 
00803 memcpy(color[i], cnv + i*10, 3*sizeof(float));
00804 }
00805 
00806 // Print the Vertex Vectors
00807 fprintf(outfile, " vertex_vectors {\n");
00808 fprintf(outfile, " %d,\n", numverts);
00809 for (i = 0; i < numverts; i++) {
00810 fprintf(outfile, " <%.4f,%.4f,%.4f>,\n", 
00811 vert[i][0], vert[i][1], -vert[i][2]);
00812 }
00813 fprintf(outfile, " }\n");
00814 
00815 // Print the Normal Vectors
00816 fprintf(outfile, " normal_vectors {\n");
00817 fprintf(outfile, " %d,\n", numverts);
00818 for (i = 0; i < numverts; i++) {
00819 fprintf(outfile, " <%.4f,%.4f,%.4f>,\n", 
00820 norm[i][0], norm[i][1], -norm[i][2]);
00821 }
00822 fprintf(outfile, " }\n");
00823 
00824 // Print the Texture List
00825 fprintf(outfile, " texture_list {\n");
00826 fprintf(outfile, " %d,\n", numverts);
00827 for (i = 0; i < numverts; i++) {
00828 fprintf(outfile, " VMDC(<%.3f,%.3f,%.3f,%.3f>)\n", 
00829 color[i][0], color[i][1], color[i][2], 1 - mat_opacity);
00830 }
00831 fprintf(outfile, " }\n");
00832 
00833 // Find the number of facets
00834 numfacets = 0;
00835 for (strip = 0; strip < numstrips; strip++) {
00836 numfacets += (vertsperstrip[strip] - 2);
00837 }
00838 
00839 // Print the Face Indices
00840 v = 0;
00841 fprintf(outfile, " face_indices {\n");
00842 fprintf(outfile, " %d\n", numfacets);
00843 for (strip = 0; strip < numstrips; strip++) {
00844 for (i = 0; i < (vertsperstrip[strip] - 2); i++) {
00845 fprintf(outfile, " <%d,%d,%d>,%d,%d,%d\n",
00846 facets[v + (stripaddr[i & 0x01][0])],
00847 facets[v + (stripaddr[i & 0x01][1])],
00848 facets[v + (stripaddr[i & 0x01][2])],
00849 facets[v + (stripaddr[i & 0x01][0])],
00850 facets[v + (stripaddr[i & 0x01][1])],
00851 facets[v + (stripaddr[i & 0x01][2])] );
00852 v++;
00853 }
00854 v += 2;
00855 }
00856 fprintf(outfile, " }\n");
00857 
00858 // Object Modifiers
00859 fprintf(outfile, " inside_vector <0, 0, 1>\n");
00860 if (clip_on[1]) {
00861 #if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND)
00862 fprintf(outfile, " clipped_by { VMD_scaledclip[1] }\n");
00863 #else
00864 fprintf(outfile, " clipped_by { VMD_clip[1] }\n");
00865 #endif
00866 }
00867 
00868 #if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND)
00869 Matrix4 hackmatrix;
00870 hackmatrix.identity();
00871 hackmatrix.scale(1.0f / POVRAY_SCALEHACK);
00872 const float *trans = hackmatrix.mat;
00873 fprintf(outfile, "matrix < \n");
00874 fprintf(outfile, " %f, %f, %f,\n", trans[ 0], trans[ 1], trans[ 2]);
00875 fprintf(outfile, " %f, %f, %f,\n", trans[ 4], trans[ 5], trans[ 6]);
00876 fprintf(outfile, " %f, %f, %f,\n", trans[ 8], trans[ 9], trans[10]);
00877 fprintf(outfile, " %f, %f, %f \n", trans[12], trans[13], trans[14]);
00878 fprintf(outfile, "> ");
00879 #endif
00880 
00881 if (!shadows_enabled())
00882 fprintf(outfile, " no_shadow\n");
00883 fprintf(outfile, "}\n");
00884 
00885 if (clip_on[2]) {
00886 fprintf(outfile, " VMD_clip[2]\n");
00887 if (!shadows_enabled())
00888 fprintf(outfile, " no_shadow\n");
00889 fprintf(outfile, "}\n");
00890 }
00891 
00892 delete [] vert;
00893 delete [] norm;
00894 delete [] color;
00895 }
00896 
00897 // display a comment
00898 void POV3DisplayDevice::comment(const char *s) {
00899 fprintf (outfile, "// %s\n", s);
00900 }
00901 
00903 
00904 void POV3DisplayDevice::write_header() {
00905 long myXsize;
00906 float zDirection;
00907 
00908 // cross-eyes and side-by-side stereo split the screen; so we need
00909 // to cut xSize in half in this case
00910 myXsize = xSize;
00911 //if (inStereo == OPENGL_STEREO_SIDE)
00912 // myXsize /= 2;
00913 // if (inStereo == OPENGL_STEREO_ABOVEBELOW) 
00914 // myXsize *= 2;
00915 fprintf(outfile, "// \n");
00916 fprintf(outfile, "// Molecular graphics export from VMD %s\n", VMDVERSION);
00917 fprintf(outfile, "// http://www.ks.uiuc.edu/Research/vmd/\n");
00918 fprintf(outfile, "// Requires POV-Ray 3.5 or later\n");
00919 fprintf(outfile, "// \n");
00920 
00921 fprintf(outfile, "// POV 3.x input script : %s \n", my_filename);
00922 fprintf(outfile, "// try povray +W%ld +H%ld -I%s ", myXsize, ySize, my_filename);
00923 fprintf(outfile, "-O%s.tga +P +X +A +FT +C", my_filename);
00924 
00925 // need to disable the vista buffer when stereo rendering
00926 if (whichEye != DisplayDevice::NOSTEREO) fprintf(outfile, " -UV");
00927 fprintf(outfile, "\n");
00928 
00929 #if 0
00930 msgInfo << "Default povray command line should be:" << sendmsg;
00931 
00932 msgInfo << " povray +W" << myXsize << " +H" << ySize << " -I" << my_filename
00933 << " -O" << my_filename << ".tga +P +X +A +FT +C";
00934 if (whichEye != DisplayDevice::NOSTEREO) msgInfo << " -UV";
00935 msgInfo << sendmsg;
00936 #endif
00937 
00938 // Warn the user if the plugin was compiled for a different version of POV
00939 // than they're using
00940 fprintf(outfile, "#if (version < 3.5) \n");
00941 fprintf(outfile, "#error \"VMD POV3DisplayDevice has been compiled for POV-Ray 3.5 or above.\\nPlease upgrade POV-Ray or recompile VMD.\"\n");
00942 fprintf(outfile, "#end \n");
00943 
00944 // Initialize POV-Ray state variables
00945 fprintf(outfile, "#declare VMD_clip_on=array[3] {0, 0, 0};\n");
00946 fprintf(outfile, "#declare VMD_clip=array[3];\n");
00947 fprintf(outfile, "#declare VMD_scaledclip=array[3];\n");
00948 fprintf(outfile, "#declare VMD_line_width=%.4f;\n", 
00949 ((float)lineWidth)*DEFAULT_RADIUS);
00950 
00951 //
00952 // Macros for VMD-like graphic primitives in POV.
00953 //
00954 
00955 // Color/Texture: save space when emitting texture lines for mesh2 primitives
00956 fprintf(outfile, "#macro VMDC ( C1 )\n");
00957 fprintf(outfile, " texture { pigment { rgbt C1 }}\n");
00958 fprintf(outfile, "#end\n");
00959 
00960 // Point: can be quickly approximated as spheres with no shading.
00961 fprintf(outfile, "#macro VMD_point (P1, R1, C1)\n");
00962 fprintf(outfile, " #local T = texture { finish { ambient 1.0 diffuse 0.0 phong 0.0 specular 0.0 } pigment { C1 } }\n");
00963 fprintf(outfile, " #if(VMD_clip_on[2])\n");
00964 fprintf(outfile, " intersection {\n");
00965 fprintf(outfile, " sphere {P1, R1 texture {T} #if(VMD_clip_on[1]) clipped_by {VMD_clip[1]} #end %s}\n", (shadows_enabled()) ? "" : "no_shadow");
00966 fprintf(outfile, " VMD_clip[2]\n");
00967 fprintf(outfile, " }\n #else\n");
00968 fprintf(outfile, " sphere {P1, R1 texture {T} #if(VMD_clip_on[1]) clipped_by {VMD_clip[1]} #end %s}\n", (shadows_enabled()) ? "" : "no_shadow");
00969 fprintf(outfile, " #end\n");
00970 fprintf(outfile, "#end\n");
00971 
00972 // Line: can be quickly approximated as cylinders with no shading
00973 fprintf(outfile, "#macro VMD_line (P1, P2, C1)\n");
00974 fprintf(outfile, " #local T = texture { finish { ambient 1.0 diffuse 0.0 phong 0.0 specular 0.0 } pigment { C1 } }\n");
00975 fprintf(outfile, " #if(VMD_clip_on[2])\n");
00976 fprintf(outfile, " intersection {\n");
00977 fprintf(outfile, " cylinder {P1, P2, VMD_line_width texture {T} #if(VMD_clip_on[1]) clipped_by {VMD_clip[1]} #end %s}\n", (shadows_enabled()) ? "" : "no_shadow");
00978 fprintf(outfile, " VMD_clip[2]\n");
00979 fprintf(outfile, " }\n #else\n");
00980 fprintf(outfile, " cylinder {P1, P2, VMD_line_width texture {T} #if(VMD_clip_on[1]) clipped_by {VMD_clip[1]} #end %s}\n", (shadows_enabled()) ? "" : "no_shadow");
00981 fprintf(outfile, " #end\n");
00982 fprintf(outfile, "#end\n");
00983 
00984 // Sphere
00985 fprintf(outfile, "#macro VMD_sphere (P1, R1, C1)\n");
00986 fprintf(outfile, " #local T = texture { pigment { C1 } }\n");
00987 fprintf(outfile, " #if(VMD_clip_on[2])\n");
00988 fprintf(outfile, " intersection {\n");
00989 fprintf(outfile, " sphere {P1, R1 texture {T} #if(VMD_clip_on[1]) clipped_by {VMD_clip[1]} #end %s}\n", (shadows_enabled()) ? "" : "no_shadow");
00990 fprintf(outfile, " VMD_clip[2]\n");
00991 fprintf(outfile, " }\n #else\n");
00992 fprintf(outfile, " sphere {P1, R1 texture {T} #if(VMD_clip_on[1]) clipped_by {VMD_clip[1]} #end %s}\n", (shadows_enabled()) ? "" : "no_shadow");
00993 fprintf(outfile, " #end\n");
00994 fprintf(outfile, "#end\n");
00995 
00996 // Cylinder: open iff O1 == 1
00997 fprintf(outfile, "#macro VMD_cylinder (P1, P2, R1, C1, O1)\n");
00998 fprintf(outfile, " #local T = texture { pigment { C1 } }\n");
00999 fprintf(outfile, " #if(VMD_clip_on[2])\n");
01000 fprintf(outfile, " intersection {\n");
01001 fprintf(outfile, " cylinder {P1, P2, R1 #if(O1) open #end texture {T} #if(VMD_clip_on[1]) clipped_by {VMD_clip[1]} #end %s}\n", (shadows_enabled()) ? "" : "no_shadow");
01002 fprintf(outfile, " VMD_clip[2]\n");
01003 fprintf(outfile, " }\n #else\n");
01004 fprintf(outfile, " cylinder {P1, P2, R1 #if(O1) open #end texture {T} #if(VMD_clip_on[1]) clipped_by {VMD_clip[1]} #end %s}\n", (shadows_enabled()) ? "" : "no_shadow");
01005 fprintf(outfile, " #end\n");
01006 fprintf(outfile, "#end\n");
01007 
01008 // Cone: use the current lineWidth for the cap radius
01009 fprintf(outfile, "#macro VMD_cone (P1, P2, R1, C1)\n");
01010 fprintf(outfile, " #local T = texture { pigment { C1 } }\n");
01011 fprintf(outfile, " #if(VMD_clip_on[2])\n");
01012 fprintf(outfile, " intersection {\n");
01013 fprintf(outfile, " cone {P1, R1, P2, VMD_line_width texture {T} #if(VMD_clip_on[1]) clipped_by {VMD_clip[1]} #end %s}\n", (shadows_enabled()) ? "" : "no_shadow");
01014 fprintf(outfile, " VMD_clip[2]\n");
01015 fprintf(outfile, " }\n #else\n");
01016 fprintf(outfile, " cone {P1, R1, P2, VMD_line_width texture {T} #if(VMD_clip_on[1]) clipped_by {VMD_clip[1]} #end %s}\n", (shadows_enabled()) ? "" : "no_shadow");
01017 fprintf(outfile, " #end\n");
01018 fprintf(outfile, "#end\n");
01019 
01020 // Triangle: single color, vertex normals
01021 // XXX - don't CSG clip triangles, behavior is undefined
01022 fprintf(outfile, "#macro VMD_triangle (P1, P2, P3, N1, N2, N3, C1)\n");
01023 fprintf(outfile, " #local T = texture { pigment { C1 } }\n");
01024 fprintf(outfile, " smooth_triangle {P1, N1, P2, N2, P3, N3 texture {T} #if(VMD_clip_on[1]) clipped_by {VMD_clip[1]} #end %s}\n", (shadows_enabled()) ? "" : "no_shadow");
01025 fprintf(outfile, "#end\n");
01026 
01027 // Tricolor: vertex colors and normals
01028 // XXX - don't CSG clip triangles, behavior is undefined
01029 fprintf(outfile, "#macro VMD_tricolor (P1, P2, P3, N1, N2, N3, C1, C2, C3)\n");
01030 fprintf(outfile, " #local NX = P2-P1;\n");
01031 fprintf(outfile, " #local NY = P3-P1;\n");
01032 fprintf(outfile, " #local NZ = vcross(NX, NY);\n");
01033 fprintf(outfile, " #local T = texture { pigment {\n");
01034 
01035 // Create a color cube with the vertex colors at three corners
01036 fprintf(outfile, " average pigment_map {\n");
01037 fprintf(outfile, " [1 gradient x color_map {[0 rgb 0] [1 C2*3]}]\n");
01038 fprintf(outfile, " [1 gradient y color_map {[0 rgb 0] [1 C3*3]}]\n");
01039 fprintf(outfile, " [1 gradient z color_map {[0 rgb 0] [1 C1*3]}]\n");
01040 fprintf(outfile, " }\n");
01041 
01042 // Transform the cube so those corners match the triangle vertices
01043 fprintf(outfile, " matrix <1.01,0,1,0,1.01,1,0,0,1,-.002,-.002,-1>\n");
01044 fprintf(outfile, " matrix <NX.x,NX.y,NX.z,NY.x,NY.y,NY.z,NZ.x,NZ.y,NZ.z,P1.x,P1.y,P1.z>\n");
01045 fprintf(outfile, " } }\n");
01046 
01047 fprintf(outfile, " smooth_triangle {P1, N1, P2, N2, P3, N3 texture {T} #if(VMD_clip_on[1]) clipped_by {VMD_clip[1]} #end %s}\n", (shadows_enabled()) ? "" : "no_shadow");
01048 fprintf(outfile, "#end\n");
01049 
01050 
01051 // Camera position
01052 // POV uses a left-handed coordinate system 
01053 // VMD uses right-handed, so z(pov) = -z(vmd).
01054 
01055 switch (projection()) {
01056 
01057 case DisplayDevice::ORTHOGRAPHIC:
01058 
01059 fprintf(outfile, "camera {\n");
01060 fprintf(outfile, " orthographic\n");
01061 fprintf(outfile, " location <%.4f, %.4f, %.4f>\n",
01062 eyePos[0], eyePos[1], -eyePos[2]);
01063 fprintf(outfile, " look_at <%.4f, %.4f, %.4f>\n",
01064 eyeDir[0], eyeDir[1], -eyeDir[2]);
01065 fprintf(outfile, " up <0.0000, %.4f, 0.0000>\n", vSize / 2.0f);
01066 fprintf(outfile, " right <%.4f, 0.0000, 0.0000>\n", Aspect * vSize / 2.0f);
01067 fprintf(outfile, "}\n");
01068 
01069 break;
01070 
01071 case DisplayDevice::PERSPECTIVE:
01072 default:
01073 
01074 if (whichEye != DisplayDevice::NOSTEREO) {
01075 if (whichEye == DisplayDevice::LEFTEYE)
01076 fprintf(outfile, "// Stereo rendering enabled. Now rendering left eye.\n");
01077 else
01078 fprintf(outfile, "// Stereo rendering enabled. Now rendering right eye.\n");
01079 
01080 fprintf(outfile, "// POV-Ray may give you a warning about non-perpendicular\n");
01081 fprintf(outfile, "// camera vectors; this is a result of the stereo rendering.\n");
01082 fprintf(outfile, "#warning \"You may ignore the following warning about "
01083 "nonperpendicular camera vectors.\"\n");
01084 }
01085 
01086 fprintf(outfile, "camera {\n");
01087 fprintf(outfile, " up <0, %.4f, 0>\n", vSize);
01088 fprintf(outfile, " right <%.4f, 0, 0>\n", Aspect * vSize);
01089 fprintf(outfile, " location <%.4f, %.4f, %.4f>\n",
01090 eyePos[0], eyePos[1], -eyePos[2]);
01091 fprintf(outfile, " look_at <%.4f, %.4f, %.4f>\n",
01092 eyePos[0] + eyeDir[0],
01093 eyePos[1] + eyeDir[1],
01094 -(eyePos[2] + eyeDir[2]));
01095 
01096 
01097 // POV-Ray doesn't handle negative directions (i.e. when the image
01098 // plane is behind the viewpoint) well: the image should be mirrored
01099 // about both the x and y axes. We simulate this case by using a sky
01100 // vector.
01101 zDirection = eyePos[2] - zDist;
01102 if (zDirection < 0) {
01103 fprintf(outfile, " direction <%.4f, %.4f, %.4f>\n",
01104 -eyePos[0], -eyePos[1], -zDirection);
01105 fprintf(outfile, " sky <0, -1, 0>\n");
01106 }
01107 else {
01108 fprintf(outfile, " direction <%.4f, %.4f, %.4f>\n",
01109 -eyePos[0], -eyePos[1], zDirection);
01110 }
01111 
01112 
01113 // render with depth of field, but only for perspective projection
01114 if (dof_enabled() && (projection() == DisplayDevice::PERSPECTIVE)) {
01115 msgInfo << "DoF focal blur enabled." << sendmsg;
01116 fprintf(outfile, " focal_point <%g, %g, %g>\n",
01117 eyePos[0] + eyeDir[0]*get_dof_focal_dist(),
01118 eyePos[1] + eyeDir[1]*get_dof_focal_dist(),
01119 -(eyePos[2] + eyeDir[2]*get_dof_focal_dist()));
01120 fprintf(outfile, " aperture %f\n", 
01121 vSize * 4.0f * get_dof_focal_dist() / get_dof_fnumber());
01122 fprintf(outfile, " blur_samples 100\n");
01123 fprintf(outfile, " confidence 0.9\n");
01124 fprintf(outfile, " variance 1/128\n");
01125 }
01126 
01127 fprintf(outfile, "}\n");
01128 
01129 break;
01130 
01131 } // switch (projection())
01132 
01133 // Lights
01134 int i;
01135 for (i=0;i<DISP_LIGHTS;i++) {
01136 if (lightState[i].on) {
01137 // directional light source, as implemented in povray 3.5
01138 fprintf(outfile, "light_source { \n <%.4f, %.4f, %.4f> \n",
01139 lightState[i].pos[0], lightState[i].pos[1],
01140 -lightState[i].pos[2]);
01141 fprintf(outfile, " color rgb<%.3f, %.3f, %.3f> \n",
01142 lightState[i].color[0], lightState[i].color[1],
01143 lightState[i].color[2]);
01144 fprintf(outfile, " parallel \n point_at <0.0, 0.0, 0.0> \n}\n");
01145 }
01146 }
01147 
01148 
01149 // background color
01150 fprintf(outfile, "background {\n color rgb<%.3f, %.3f, %.3f>\n}\n", 
01151 backColor[0], backColor[1], backColor[2]);
01152 
01153 // Specify background sky sphere if background gradient mode is enabled.
01154 if (backgroundmode == 1) {
01155 fprintf(outfile, "\n");
01156 fprintf(outfile, "sky_sphere {\n");
01157 fprintf(outfile, " pigment {\n");
01158 fprintf(outfile, " gradient y\n");
01159 fprintf(outfile, " color_map {\n");
01160 fprintf(outfile, " [ 0.0 color rgb<%.3f, %.3f, %.3f> ]\n",
01161 backgradientbotcolor[0], backgradientbotcolor[1], backgradientbotcolor[2]);
01162 fprintf(outfile, " [ 1.0 color rgb<%.3f, %.3f, %.3f> ]\n",
01163 backgradienttopcolor[0], backgradienttopcolor[1], backgradienttopcolor[2]);
01164 fprintf(outfile, " }\n");
01165 fprintf(outfile, " scale 2\n");
01166 fprintf(outfile, " translate -1\n");
01167 fprintf(outfile, " }\n");
01168 fprintf(outfile, "}\n");
01169 fprintf(outfile, "\n");
01170 }
01171 
01172 // depth-cueing (fog)
01173 if (cueingEnabled && (get_cue_density() >= 1e-4)) {
01174 fprintf(outfile, "fog {\n");
01175 
01176 switch (cueMode) {
01177 case CUE_EXP2:
01178 case CUE_LINEAR:
01179 case CUE_EXP:
01180 // XXX We use povray's exponential fog for all cases 
01181 // since it doesn't currently support any other fog types yet.
01182 fprintf(outfile, " distance %.4f \n", 
01183 (get_cue_density() >= 1e4) ? 1e-4 : 1.0/get_cue_density() );
01184 fprintf(outfile, " fog_type 1 \n");
01185 break;
01186 
01187 case NUM_CUE_MODES:
01188 // this should never happen
01189 break;
01190 }
01191 
01192 // for depth-cueing, the fog color is the background color
01193 fprintf(outfile, " color rgb<%.3f, %.3f, %.3f> \n",
01194 backColor[0], backColor[1], backColor[2] );
01195 fprintf(outfile, "} \n");
01196 }
01197 }
01198 
01199 void POV3DisplayDevice::write_trailer(void){
01200 fprintf(outfile, "// End of POV-Ray 3.x generation \n");
01201 
01202 if (degenerate_cones != 0) {
01203 msgWarn << "Skipped " << degenerate_cones 
01204 << " degenerate cones" << sendmsg;
01205 }
01206 if (degenerate_cylinders != 0) {
01207 msgWarn << "Skipped " << degenerate_cylinders 
01208 << " degenerate cylinders" << sendmsg;
01209 }
01210 if (degenerate_triangles != 0) {
01211 msgWarn << "Skipped " << degenerate_triangles 
01212 << " degenerate triangles" << sendmsg;
01213 }
01214 
01215 reset_vars(); // Reset variables before the next rendering.
01216 }
01217 
01218 
01219 void POV3DisplayDevice::write_materials(void) {
01220 if (old_materialIndex != materialIndex) {
01221 
01222 old_materialIndex = materialIndex;
01223 
01224 fprintf(outfile, "#default { texture {\n");
01225 fprintf(outfile, " finish { ambient %.3f diffuse %.3f",
01226 mat_ambient, mat_diffuse);
01227 fprintf(outfile, " phong 0.1 phong_size %.3f specular %.3f }\n",
01228 mat_shininess, mat_specular);
01229 fprintf(outfile, "} }\n");
01230 }
01231 }
01232 
01233 
01234 void POV3DisplayDevice::start_clipgroup(void) {
01235 int i, num_clipplanes[3], mode;
01236 float pov_clip_center[3], pov_clip_distance[VMD_MAX_CLIP_PLANE];
01237 float pov_clip_normal[VMD_MAX_CLIP_PLANE][3];
01238 
01239 write_materials();
01240 
01241 memset(num_clipplanes, 0, 3*sizeof(int));
01242 for (i = 0; i < VMD_MAX_CLIP_PLANE; i++) {
01243 if (clip_mode[i] != 0) {
01244 // Count the number of clipping planes for each clip mode
01245 num_clipplanes[clip_mode[i]]++;
01246 
01247 // Translate the plane center
01248 (transMat.top()).multpoint3d(clip_center[i], pov_clip_center);
01249 
01250 // and the normal
01251 (transMat.top()).multnorm3d(clip_normal[i], pov_clip_normal[i]);
01252 vec_negate(pov_clip_normal[i], pov_clip_normal[i]);
01253 
01254 // POV-Ray uses the distance from the origin to the plane for its
01255 // representation, instead of the plane center
01256 pov_clip_distance[i] = dot_prod(pov_clip_normal[i], pov_clip_center);
01257 }
01258 }
01259 
01260 // Define the clip object for each clip mode
01261 for (mode = 1; mode < 3; mode++) {
01262 if (num_clipplanes[mode] > 0) {
01263 // This flag is used within VMD to determine if clipping information
01264 // should be written to the scene file
01265 clip_on[mode] = 1;
01266 
01267 // This flag is used within POV to determine if clipping should be done
01268 // within macros
01269 fprintf(outfile, "#declare VMD_clip_on[%d]=1;\n", mode);
01270 
01271 if (num_clipplanes[mode] == 1) {
01272 for (i = 0; i < VMD_MAX_CLIP_PLANE; i++) {
01273 if (clip_mode[i] == mode) {
01274 if (mode == 2) {
01275 // Textured plane for CSG clipping
01276 fprintf(outfile, "#declare VMD_clip[%d] = plane { <%.4f, %.4f, %.4f>, %.4f texture { pigment { rgbt<%.3f, %.3f, %.3f, %.3f> } } }\n",
01277 mode, pov_clip_normal[i][0], pov_clip_normal[i][1], 
01278 -pov_clip_normal[i][2], pov_clip_distance[i],
01279 clip_color[i][0], clip_color[i][1], clip_color[i][2],
01280 1 - mat_opacity);
01281 } else {
01282 // Non-textured plane for non-CSG clipping
01283 fprintf(outfile, "#declare VMD_clip[%d] = plane { <%.4f, %.4f, %.4f>, %.4f }\n",
01284 mode, pov_clip_normal[i][0], pov_clip_normal[i][1], 
01285 -pov_clip_normal[i][2], pov_clip_distance[i]);
01286 
01287 #if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND)
01288 // Non-textured plane for non-CSG clipping, but scaled for use
01289 // when emitting meshes with the scaling hack.
01290 fprintf(outfile, "#declare VMD_scaledclip[%d] = plane { <%.4f, %.4f, %.4f>, %.4f }\n",
01291 mode, pov_clip_normal[i][0], pov_clip_normal[i][1], -pov_clip_normal[i][2], 
01292 pov_clip_distance[i] * POVRAY_SCALEHACK);
01293 #endif
01294 }
01295 }
01296 }
01297 }
01298 
01299 // Declare the clipping object to be an intersection of planes
01300 else {
01301 fprintf(outfile, "#declare VMD_clip[%d] = intersection {\n", mode);
01302 for (i = 0; i < VMD_MAX_CLIP_PLANE; i++) {
01303 if (clip_mode[i] == mode) {
01304 if (mode == 2) {
01305 // Textured plane for CSG clipping
01306 fprintf(outfile, " plane { <%.4f, %.4f, %.4f>, %.4f texture { pigment { rgbt<%.3f, %.3f, %.3f, %.3f> } } }\n",
01307 pov_clip_normal[i][0], pov_clip_normal[i][1], 
01308 -pov_clip_normal[i][2], pov_clip_distance[i],
01309 clip_color[i][0], clip_color[i][1], clip_color[i][2],
01310 1 - mat_opacity);
01311 } else {
01312 // Non-textured plane for non-CSG clipping
01313 fprintf(outfile, " plane { <%.4f, %.4f, %.4f>, %.4f }\n",
01314 pov_clip_normal[i][0], pov_clip_normal[i][1], 
01315 -pov_clip_normal[i][2], pov_clip_distance[i]);
01316 }
01317 }
01318 }
01319 fprintf(outfile, "}\n");
01320 
01321 #if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND)
01322 fprintf(outfile, "#declare VMD_scaledclip[%d] = intersection {\n", mode);
01323 for (i = 0; i < VMD_MAX_CLIP_PLANE; i++) {
01324 if (clip_mode[i] == mode) {
01325 if (mode == 2) {
01326 // Textured plane for CSG clipping
01327 fprintf(outfile, " plane { <%.4f, %.4f, %.4f>, %.4f texture { pigment { rgbt<%.3f, %.3f, %.3f, %.3f> } } }\n",
01328 pov_clip_normal[i][0], pov_clip_normal[i][1], 
01329 -pov_clip_normal[i][2], pov_clip_distance[i] * POVRAY_SCALEHACK,
01330 clip_color[i][0], clip_color[i][1], clip_color[i][2],
01331 1 - mat_opacity);
01332 } else {
01333 // Non-textured plane for non-CSG clipping
01334 fprintf(outfile, " plane { <%.4f, %.4f, %.4f>, %.4f }\n",
01335 pov_clip_normal[i][0], pov_clip_normal[i][1], 
01336 -pov_clip_normal[i][2], pov_clip_distance[i] * POVRAY_SCALEHACK);
01337 }
01338 }
01339 }
01340 fprintf(outfile, "}\n");
01341 #endif
01342 
01343 
01344 }
01345 
01346 }
01347 }
01348 }
01349 
01350 void POV3DisplayDevice::end_clipgroup(void) {
01351 int i;
01352 for (i = 0; i < 3; i++) {
01353 if (clip_on[i]) {
01354 fprintf(outfile, "#declare VMD_clip_on[%d]=0;\n", i);
01355 clip_on[i] = 0;
01356 }
01357 }
01358 }
01359 
01360 void POV3DisplayDevice::set_line_width(int new_width) {
01361 // XXX - find out why lineWidth is getting set outside this function!
01362 // if (lineWidth != new_width) {
01363 {
01364 lineWidth = new_width;
01365 fprintf(outfile, "#declare VMD_line_width=%.4f;\n", 
01366 ((float)new_width)*DEFAULT_RADIUS);
01367 }
01368 }
01369 

Generated on Mon Nov 17 02:47:01 2025 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002

AltStyle によって変換されたページ (->オリジナル) /