00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <stdio.h>
00025 #include <string.h>
00026 #include <math.h>
00027 #define sqr(x) ((x) * (x))
00028
00029 #include "R3dDisplayDevice.h"
00030 #include "Matrix4.h"
00031 #include "DispCmds.h"
00032 #include "Inform.h"
00033 #include "utilities.h"
00034 #include "config.h"
00035 #include "Hershey.h"
00036
00037 #define DEFAULT_RADIUS 0.002f // radius for faking lines with cylinders
00038 #define DASH_LENGTH 0.02f // dash lengths
00039
00040 #define currentColor matData[colorIndex]
00041
00043
00044
00045 R3dDisplayDevice::R3dDisplayDevice(void) :
00046 FileRenderer("Raster3D", "Raster3D 2.7d", "vmdscene.r3d",
00047 "render -avs < %s | display avs:-") {
00048 reset_vars();
00049 }
00050
00051
00052 R3dDisplayDevice::~R3dDisplayDevice(void) { }
00053
00054 void R3dDisplayDevice::reset_vars(void) {
00055
00056 objLegal = 0;
00057 mat_on = 0;
00058 old_mat_shininess = -1;
00059 old_mat_specular = -1;
00060 old_mat_opacity = -1;
00061 }
00062
00063
00065
00066 void R3dDisplayDevice::text(float *pos, float size, float thickness,
00067 const char *str) {
00068 float textpos[3];
00069 float textsize, textthickness;
00070 hersheyhandle hh;
00071
00072
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
00095 oldpt[0] = textpos[0] + textsize * ox;
00096 oldpt[1] = textpos[1] + textsize * oy;
00097 oldpt[2] = textpos[2];
00098
00099 write_materials();
00100 fprintf(outfile, "5\n");
00101 fprintf(outfile, "%7f %7f %7f ", oldpt[0], oldpt[1], oldpt[2]);
00102 fprintf(outfile, "%7f ", textthickness);
00103 fprintf(outfile, "%7f %7f %7f ", newpt[0], newpt[1], newpt[2]);
00104 fprintf(outfile, "%7f ", textthickness);
00105 fprintf(outfile, "%3.2f %3.2f %3.2f\n", sqr(currentColor[0]),
00106 sqr(currentColor[1]), sqr(currentColor[2]));
00107
00108 write_materials();
00109 fprintf(outfile, "2\n");
00110 fprintf(outfile, "%7f %7f %7f ", newpt[0], newpt[1], newpt[2]);
00111 fprintf(outfile, "%7f ", textthickness);
00112 fprintf(outfile, "%3.2f %3.2f %3.2f\n", sqr(currentColor[0]),
00113 sqr(currentColor[1]), sqr(currentColor[2]));
00114 } else {
00115
00116 write_materials();
00117 fprintf(outfile, "2\n");
00118 fprintf(outfile, "%7f %7f %7f ", newpt[0], newpt[1], newpt[2]);
00119 fprintf(outfile, "%7f ", textthickness);
00120 fprintf(outfile, "%3.2f %3.2f %3.2f\n", sqr(currentColor[0]),
00121 sqr(currentColor[1]), sqr(currentColor[2]));
00122 }
00123 }
00124
00125 ox=x;
00126 oy=y;
00127 odraw=draw;
00128 }
00129 textpos[0] += rm * textsize;
00130
00131 str++;
00132 }
00133 }
00134
00135
00136
00137 void R3dDisplayDevice::point(float * spdata) {
00138 float vec[3];
00139
00140
00141 (transMat.top()).multpoint3d(spdata, vec);
00142
00143 write_materials();
00144
00145
00146 fprintf(outfile, "2\n");
00147 fprintf(outfile, "%7f %7f %7f ", vec[0], vec[1], vec[2]);
00148 fprintf(outfile, "%7f ", float(lineWidth)*DEFAULT_RADIUS );
00149 fprintf(outfile, "%3.2f %3.2f %3.2f\n", sqr(currentColor[0]),
00150 sqr(currentColor[1]), sqr(currentColor[2]));
00151 }
00152
00153
00154 void R3dDisplayDevice::sphere(float * spdata) {
00155 float vec[3];
00156 float radius;
00157
00158
00159 (transMat.top()).multpoint3d(spdata, vec);
00160 radius = scale_radius(spdata[3]);
00161
00162
00163 write_materials();
00164
00165
00166 fprintf(outfile, "2\n");
00167 fprintf(outfile, "%7f %7f %7f ", vec[0], vec[1], vec[2]);
00168 fprintf(outfile, "%7f ", radius);
00169 fprintf(outfile, "%3.2f %3.2f %3.2f\n", sqr(currentColor[0]),
00170 sqr(currentColor[1]), sqr(currentColor[2]));
00171 }
00172
00173
00174
00175 void R3dDisplayDevice::line(float *a, float*b) {
00176 int i, j, test;
00177 float dirvec[3], unitdirvec[3];
00178 float from[3], to[3], tmp1[3], tmp2[3];
00179
00180 if (lineStyle == ::SOLIDLINE) {
00181
00182 (transMat.top()).multpoint3d(a, from);
00183 (transMat.top()).multpoint3d(b, to);
00184
00185
00186 fprintf(outfile, "5\n");
00187 fprintf(outfile, "%7f %7f %7f ", from[0], from[1], from[2]);
00188 fprintf(outfile, "%7f ", float(lineWidth)*DEFAULT_RADIUS);
00189 fprintf(outfile, "%7f %7f %7f ", to[0], to[1], to[2]);
00190 fprintf(outfile, "%7f ", float(lineWidth)*DEFAULT_RADIUS);
00191 fprintf(outfile, "%3.2f %3.2f %3.2f\n", sqr(currentColor[0]),
00192 sqr(currentColor[1]), sqr(currentColor[2]));
00193
00194 } else if (lineStyle == ::DASHEDLINE) {
00195
00196 (transMat.top()).multpoint3d(a, tmp1);
00197 (transMat.top()).multpoint3d(b, tmp2);
00198
00199
00200 vec_sub(dirvec, tmp2, tmp1);
00201 vec_copy(unitdirvec, dirvec);
00202 vec_normalize(unitdirvec);
00203 test = 1;
00204 i = 0;
00205 while (test == 1) {
00206 for (j=0; j<3; j++) {
00207 from[j] = (float) (tmp1[j] + (2*i )*DASH_LENGTH*unitdirvec[j]);
00208 to[j] = (float) (tmp1[j] + (2*i + 1)*DASH_LENGTH*unitdirvec[j]);
00209 }
00210 if (fabsf(tmp1[0] - to[0]) >= fabsf(dirvec[0])) {
00211 vec_copy(to, tmp2);
00212 test = 0;
00213 }
00214
00215
00216 fprintf(outfile, "5\n");
00217 fprintf(outfile, "%7f %7f %7f ", from[0], from[1], from[2]);
00218 fprintf(outfile, "%7f ", float(lineWidth)*DEFAULT_RADIUS);
00219 fprintf(outfile, "%7f %7f %7f ", to[0], to[1], to[2]);
00220 fprintf(outfile, "%7f ", float(lineWidth)*DEFAULT_RADIUS);
00221 fprintf(outfile, "%3.2f %3.2f %3.2f\n", sqr(currentColor[0]),
00222 sqr(currentColor[1]), sqr(currentColor[2]));
00223
00224 i++;
00225 }
00226
00227 } else {
00228 msgErr << "R3dDisplayDevice: Unknown line style " << lineStyle << sendmsg;
00229 }
00230
00231 }
00232
00233
00234 void R3dDisplayDevice::cylinder(float *a, float *b, float r, int) {
00235
00236 float vec1[3], vec2[3];
00237 float radius;
00238
00239
00240 (transMat.top()).multpoint3d(a, vec1);
00241 (transMat.top()).multpoint3d(b, vec2);
00242 radius = scale_radius(r);
00243
00244 write_materials();
00245
00247
00248 fprintf(outfile, "5\n");
00249 fprintf(outfile, "%7f %7f %7f ", vec1[0], vec1[1], vec1[2]);
00250 fprintf(outfile, "%7f ", radius);
00251 fprintf(outfile, "%7f %7f %7f ", vec2[0], vec2[1], vec2[2]);
00252 fprintf(outfile, "%7f ", radius);
00253 fprintf(outfile, "%3.2f %3.2f %3.2f\n", sqr(currentColor[0]),
00254 sqr(currentColor[1]), sqr(currentColor[2]));
00255
00256 }
00257
00258
00259 void R3dDisplayDevice::triangle(const float *a, const float *b, const float *c, const float *n1, const float *n2, const float *n3) {
00260
00261 float vec1[3], vec2[3], vec3[3];
00262 float norm1[3], norm2[3], norm3[3];
00263
00264
00265 (transMat.top()).multpoint3d(a, vec1);
00266 (transMat.top()).multpoint3d(b, vec2);
00267 (transMat.top()).multpoint3d(c, vec3);
00268
00269
00270 (transMat.top()).multnorm3d(n1, norm1);
00271 (transMat.top()).multnorm3d(n2, norm2);
00272 (transMat.top()).multnorm3d(n3, norm3);
00273
00274 write_materials();
00275
00276
00277 fprintf(outfile, "1\n");
00278 fprintf(outfile, "%7f %7f %7f ", vec1[0], vec1[1], vec1[2]);
00279 fprintf(outfile, "%7f %7f %7f ", vec2[0], vec2[1], vec2[2]);
00280 fprintf(outfile, "%7f %7f %7f ", vec3[0], vec3[1], vec3[2]);
00281 fprintf(outfile, "%3.2f %3.2f %3.2f\n", sqr(currentColor[0]),
00282 sqr(currentColor[1]), sqr(currentColor[2]));
00283
00284 fprintf(outfile, "7\n");
00285 fprintf(outfile, "%7f %7f %7f ", norm1[0], norm1[1], norm1[2]);
00286 fprintf(outfile, "%7f %7f %7f ", norm2[0], norm2[1], norm2[2]);
00287 fprintf(outfile, "%7f %7f %7f\n", norm3[0], norm3[1], norm3[2]);
00288 }
00289
00290
00291 void R3dDisplayDevice::tricolor(const float *a, const float *b, const float *c, const float *n1, const float *n2, const float *n3, const float *c1, const float *c2, const float *c3) {
00292
00293 float vec1[3], vec2[3], vec3[3];
00294 float norm1[3], norm2[3], norm3[3];
00295
00296
00297 (transMat.top()).multpoint3d(a, vec1);
00298 (transMat.top()).multpoint3d(b, vec2);
00299 (transMat.top()).multpoint3d(c, vec3);
00300
00301
00302 (transMat.top()).multnorm3d(n1, norm1);
00303 (transMat.top()).multnorm3d(n2, norm2);
00304 (transMat.top()).multnorm3d(n3, norm3);
00305
00306 write_materials();
00307
00308
00309 fprintf(outfile, "1\n");
00310 fprintf(outfile, "%7f %7f %7f ", vec1[0], vec1[1], vec1[2]);
00311 fprintf(outfile, "%7f %7f %7f ", vec2[0], vec2[1], vec2[2]);
00312 fprintf(outfile, "%7f %7f %7f ", vec3[0], vec3[1], vec3[2]);
00313 fprintf(outfile, "%3.2f %3.2f %3.2f\n", sqr(currentColor[0]),
00314 sqr(currentColor[1]), sqr(currentColor[2]));
00315
00316 fprintf(outfile, "7\n");
00317 fprintf(outfile, "%7f %7f %7f ", norm1[0], norm1[1], norm1[2]);
00318 fprintf(outfile, "%7f %7f %7f ", norm2[0], norm2[1], norm2[2]);
00319 fprintf(outfile, "%7f %7f %7f\n", norm3[0], norm3[1], norm3[2]);
00320
00321
00322 fprintf(outfile, "17\n");
00323 fprintf(outfile, "%7f %7f %7f %7f %7f %7f %7f %7f %7f\n",
00324 c1[0], c1[1], c1[2], c2[0], c2[1], c2[2], c3[0], c3[1], c3[2]);
00325 }
00326
00327 void R3dDisplayDevice::comment(const char *s) {
00328 int i=0, length;
00329 char buf[71];
00330 const char *index;
00331
00332 if (!objLegal) return;
00333
00334 length = strlen(s);
00335 index = s;
00336
00337 while (i*70 < length) {
00338 strncpy(buf, index, 70);
00339 buf[70] = '\0';
00340 fprintf (outfile, "# %s\n", buf);
00341 index += 70;
00342 i++;
00343 }
00344 }
00345
00347
00348
00349 void R3dDisplayDevice::write_header() {
00350 int tileX, tileY;
00351 int nTilesX, nTilesY;
00352 int i, nlights;
00353 float lightshare;
00354 float scale;
00355
00356 fprintf(outfile, "# \n");
00357 fprintf(outfile, "# Molecular graphics export from VMD %s\n", VMDVERSION);
00358 fprintf(outfile, "# http://www.ks.uiuc.edu/Research/vmd/\n");
00359 fprintf(outfile, "# Requires Raster3D version 2.7d or later\n");
00360 fprintf(outfile, "# \n");
00361
00362 fprintf(outfile, "r3d input script\n");
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373 tileX = 2;
00374 while (xSize / tileX > 192) {
00375 tileX += 2;
00376 if (tileX > 36) {
00377 tileX -= 2;
00378 msgInfo << "Warning: The Raster3D output image has too high a resolution" << sendmsg;
00379 msgInfo << "to be properly rendered. Writing the file anyway, but Raster3D" << sendmsg;
00380 msgInfo << "will probably give an error." << sendmsg;
00381 break;
00382 }
00383 }
00384
00385 tileY = 2;
00386 while (ySize / tileY > 192) {
00387 tileY += 2;
00388 if (tileY > 36) {
00389 tileY -= 2;
00390 if (xSize / tileX > 192) {
00391 msgInfo << "Warning: The Raster3D output image has too high a resolution" << sendmsg;
00392 msgInfo << "to be properly rendered. Writing the file anyway, but Raster3D" << sendmsg;
00393 msgInfo << "will probably give an error." << sendmsg;
00394 }
00395 break;
00396 }
00397 }
00398
00399
00400
00401
00402 nTilesX = xSize / tileX;
00403 nTilesY = ySize / tileY;
00404 if (xSize % tileX >= tileX / 2) nTilesX++;
00405 if (ySize % tileY >= tileY / 2) nTilesY++;
00406
00407 fprintf(outfile, "%d %d tiles in x,y\n", nTilesX, nTilesY);
00408 fprintf(outfile, "%d %d computing pixels per tile\n", tileX, tileY);
00409 fprintf(outfile, "4 alti-aliasing scheme 4; 3x3 -> 2x2\n");
00410 fprintf(outfile, "%3.2f %3.2f %3.2f background color\n",
00411 backColor[0], backColor[1], backColor[2]);
00412 fprintf(outfile, "T shadows on\n");
00413 fprintf(outfile, "20 Phong power\n");
00414 fprintf(outfile, "1.00 secondary light contribution\n");
00415 fprintf(outfile, "0.10 ambient light contribution\n");
00416 fprintf(outfile, "0.50 specular reflection component\n");
00417
00418
00419
00420
00421
00422 switch (projection()) {
00423
00424 case DisplayDevice::ORTHOGRAPHIC:
00425 fprintf(outfile, "0 Eye position (orthographic mode)\n");
00426 break;
00427
00428 case DisplayDevice::PERSPECTIVE:
00429 default:
00430 if (Aspect > 1) fprintf(outfile, "%6.2f Eye position\n",
00431 (-zDist + eyePos[2]) / vSize);
00432 else fprintf(outfile, "%6.2f Eye position\n",
00433 (-zDist + eyePos[2]) / vSize / Aspect);
00434 break;
00435
00436 }
00437
00438
00439
00440 fprintf(outfile, "1 0 0 main light source position\n");
00441
00442
00443
00444
00445
00446
00447 if (Aspect > 1) scale = vSize / 2;
00448 else scale = vSize * Aspect / 2;
00449
00450
00451 fprintf(outfile, "1 0 0 0 global xform matrix\n");
00452 fprintf(outfile, "0 1 0 0\n");
00453 fprintf(outfile, "0 0 1 0\n");
00454 fprintf(outfile, "0 0 0 %.3f\n", scale);
00455
00456 fprintf(outfile, "3\n");
00457 fprintf(outfile, "*\n*\n*\n");
00458
00459
00460
00461
00462 nlights = 0;
00463 for (i = 0; i < DISP_LIGHTS; i++)
00464 if (lightState[i].on) nlights++;
00465
00466
00467 lightshare = nlights ? (1 / (float) nlights) : 0;
00468
00469
00470 for (i = 0; i < DISP_LIGHTS; i++) {
00471 if (lightState[i].on) {
00472 fprintf(outfile, "13\n%f %f %f 100 %f 0 20 1 1 1\n",
00473 lightState[i].pos[0], lightState[i].pos[1], lightState[i].pos[2],
00474 lightshare);
00475 }
00476 }
00477
00478
00479
00480 objLegal = 1;
00481 }
00482
00483 void R3dDisplayDevice::write_trailer(void) {
00484
00485 close_materials();
00486
00487 msgInfo << "Raster3D file generation finished" << sendmsg;
00488
00489 reset_vars();
00490 }
00491
00492
00493
00494 void R3dDisplayDevice::write_materials(void) {
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507 if (!mat_on) {
00508 fprintf(outfile, "8\n");
00509
00510
00511
00512
00513
00514 #if 1
00515
00516 fprintf(outfile, "%.3f %.3f 1 1 1 %.3f 2 0 0 0\n",
00517 #else
00518
00519 fprintf(outfile, "%.3f %.3f 1 1 1 %.3f 0 0 0 0\n",
00520 #endif
00521 mat_shininess, mat_specular, 1 - mat_opacity);
00522
00523 old_mat_shininess = mat_shininess;
00524 old_mat_specular = mat_specular;
00525 old_mat_opacity = mat_opacity;
00526
00527 mat_on = 1;
00528 }
00529 else if (mat_shininess != old_mat_shininess ||
00530 mat_specular != old_mat_specular ||
00531 mat_opacity != old_mat_opacity) {
00532 fprintf(outfile, "9\n");
00533 fprintf(outfile, "8\n");
00534 fprintf(outfile, "%.3f %.3f 1 1 1 %.3f 0 0 0 0\n",
00535 mat_shininess, mat_specular, 1 - mat_opacity);
00536
00537 old_mat_shininess = mat_shininess;
00538 old_mat_specular = mat_specular;
00539 old_mat_opacity = mat_opacity;
00540 }
00541
00542 return;
00543 }
00544
00545 void R3dDisplayDevice::close_materials(void) {
00546 if (mat_on) {
00547 fprintf(outfile, "9\n");
00548 mat_on = 0;
00549 }
00550 return;
00551 }