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