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 <stdlib.h>
00026 #include "utilities.h"
00027 #include "DispCmds.h"
00028 #include "FileRenderer.h"
00029 #include "VMDDisplayList.h"
00030 #include "Inform.h"
00031 #include "Scene.h"
00032 #include "Hershey.h"
00033
00034
00035 FileRenderer::FileRenderer(const char *public_name,
00036 const char *public_pretty_name,
00037 const char *default_file_name,
00038 const char *default_command_line) :
00039 DisplayDevice(public_name), transMat(10)
00040 {
00041
00042 publicName = stringdup(public_name);
00043 publicPrettyName = stringdup(public_pretty_name);
00044 defaultFilename = stringdup(default_file_name);
00045 defaultCommandLine = stringdup(default_command_line);
00046 execCmd = stringdup(defaultCommandLine);
00047 has_aa = 0;
00048 aasamples = -1;
00049 has_imgsize = 0;
00050 imgwidth = imgheight = 0;
00051 aspectratio = 0.0f;
00052 curformat = -1;
00053 textoffset_x = 0;
00054 textoffset_y = 0;
00055 warningflags = FILERENDERER_NOWARNINGS;
00056
00057
00058 outfile = NULL;
00059 isOpened = FALSE;
00060 my_filename = NULL;
00061
00062
00063 sph_nverts = 0;
00064 sph_verts = NULL;
00065 }
00066
00067
00068 FileRenderer::~FileRenderer(void) {
00069
00070 if (sph_verts && sph_nverts)
00071 free(sph_verts);
00072
00073 close_file();
00074 delete [] my_filename;
00075 delete [] publicName;
00076 delete [] publicPrettyName;
00077 delete [] defaultFilename;
00078 delete [] defaultCommandLine;
00079 delete [] execCmd;
00080 }
00081
00082 int FileRenderer::do_define_light(int n, float *color, float *position) {
00083 if (n < 0 || n >= DISP_LIGHTS)
00084 return FALSE;
00085
00086 for (int i=0; i<3; i++) {
00087 lightState[n].color[i] = color[i];
00088 lightState[n].pos[i] = position[i];
00089 }
00090 return TRUE;
00091 }
00092
00093 int FileRenderer::do_activate_light(int n, int turnon) {
00094 if (n < 0 || n >= DISP_LIGHTS)
00095 return FALSE;
00096
00097 lightState[n].on = turnon;
00098 return TRUE;
00099 }
00100
00101 int FileRenderer::do_define_adv_light(int n, float *color,
00102 float *position,
00103 float constant, float linear, float quad,
00104 float *spotdir, float fallstart,
00105 float fallend, int spoton) {
00106 if(n < 0 || n >= DISP_LIGHTS)
00107 return FALSE;
00108
00109 for (int i=0; i < 3; i++) {
00110 advLightState[n].color[i] = color[i];
00111 advLightState[n].pos[i] = position[i];
00112 advLightState[n].spotdir[i] = spotdir[i];
00113 }
00114 advLightState[n].constfactor = constant;
00115 advLightState[n].linearfactor = linear;
00116 advLightState[n].quadfactor = quad;
00117 advLightState[n].fallstart = fallstart;
00118 advLightState[n].fallend = fallend;
00119 advLightState[n].spoton = spoton;
00120 return TRUE;
00121 }
00122
00123 int FileRenderer::do_activate_adv_light(int n, int turnon) {
00124 if (n < 0 || n >= DISP_LIGHTS)
00125 return FALSE;
00126
00127 advLightState[n].on = turnon;
00128 return TRUE;
00129 }
00130
00131
00132
00133 void FileRenderer::do_use_colors() {
00134 for (int i=0; i<MAXCOLORS; i++) {
00135 matData[i][0] = colorData[3*i ];
00136 matData[i][1] = colorData[3*i+1];
00137 matData[i][2] = colorData[3*i+2];
00138 }
00139 }
00140
00141 int FileRenderer::set_imagesize(int *w, int *h) {
00142 if (*w < 0 || *h < 0) return FALSE;
00143 if (*w == imgwidth && *h == imgheight) return TRUE;
00144 if (!aspectratio) {
00145 if (*w) imgwidth = *w;
00146 if (*h) imgheight = *h;
00147 } else {
00148 if (*w) {
00149 imgwidth = *w;
00150 imgheight = (int)(*w / aspectratio);
00151 } else if (*h) {
00152 imgwidth = (int)(*h * aspectratio);
00153 imgheight = *h;
00154 } else {
00155 if (imgwidth || imgheight) {
00156 int wtmp = imgwidth, htmp = imgheight;
00157 set_imagesize(&wtmp, &htmp);
00158 }
00159 }
00160 }
00161 update_exec_cmd();
00162 *w = imgwidth;
00163 *h = imgheight;
00164 return TRUE;
00165 }
00166
00167 float FileRenderer::set_aspectratio(float aspect) {
00168 if (aspect >= 0) aspectratio = aspect;
00169 int w=0, h=0;
00170 set_imagesize(&w, &h);
00171 return aspectratio;
00172 }
00173
00174 int FileRenderer::nearest_index(float r, float g, float b) const {
00175 const float *rcol = matData[BEGREGCLRS];
00176 float lsq = r - rcol[0]; lsq *= lsq;
00177 float tmp = g - rcol[1]; lsq += tmp * tmp;
00178 tmp = b - rcol[2]; lsq += tmp * tmp;
00179 float best = lsq;
00180 int bestidx = BEGREGCLRS;
00181 for (int n=BEGREGCLRS+1; n < (BEGREGCLRS + REGCLRS + MAPCLRS); n++) {
00182 rcol = matData[n];
00183 lsq = r - rcol[0]; lsq *= lsq;
00184 tmp = g - rcol[1]; lsq += tmp * tmp;
00185 tmp = b - rcol[2]; lsq += tmp * tmp;
00186 if (lsq < best) {
00187 best = lsq;
00188 bestidx = n;
00189 }
00190 }
00191 return bestidx;
00192 }
00193
00194 void FileRenderer::set_background(const float * bg) {
00195 backColor[0] = bg[0];
00196 backColor[1] = bg[1];
00197 backColor[2] = bg[2];
00198 }
00199
00200 void FileRenderer::set_backgradient(const float *top, const float *bot) {
00201 vec_copy(backgradienttopcolor, top);
00202 vec_copy(backgradientbotcolor, bot);
00203 }
00204
00205
00206
00207 int FileRenderer::open_file(const char *filename) {
00208 if (isOpened) {
00209 close_file();
00210 }
00211 if ((outfile = fopen(filename, "w")) == NULL) {
00212 msgErr << "Could not open file " << filename
00213 << " in current directory for writing!" << sendmsg;
00214 return FALSE;
00215 }
00216 my_filename = stringdup(filename);
00217 isOpened = TRUE;
00218 reset_state();
00219 return TRUE;
00220 }
00221
00222 void FileRenderer::reset_state(void) {
00223
00224 while (transMat.num()) {
00225 transMat.pop();
00226 }
00227
00228 colorIndex = -1;
00229 materialIndex = -1;
00230 lineWidth = 1;
00231 lineStyle = ::SOLIDLINE;
00232 pointSize = 1;
00233 sphereResolution = 4;
00234 sphereStyle = 1;
00235 materials_on = 0;
00236 }
00237
00238
00239
00240 void FileRenderer::close_file(void) {
00241 if (outfile) {
00242 fclose(outfile);
00243 outfile = NULL;
00244 }
00245 delete [] my_filename;
00246 my_filename = NULL;
00247 isOpened = FALSE;
00248 }
00249
00250
00251 int FileRenderer::prepare3D(int) {
00252
00253
00254
00255 int i;
00256 float lookat[3];
00257 for (i=0; i<3; i++)
00258 lookat[i] = eyePos[i] + eyeDir[i];
00259
00260 switch (whichEye) {
00261 case LEFTEYE:
00262 for (i=0; i<3; i++)
00263 eyePos[i] -= eyeSepDir[i];
00264
00265 for (i=0; i<3; i++)
00266 eyeDir[i] = lookat[i] - eyePos[i];
00267 break;
00268
00269 case RIGHTEYE:
00270 for (i=0; i<3; i++)
00271 eyePos[i] += eyeSepDir[i];
00272
00273 for (i=0; i<3; i++)
00274 eyeDir[i] = lookat[i] - eyePos[i];
00275 break;
00276
00277 case NOSTEREO:
00278 break;
00279 }
00280
00281 if (isOpened) {
00282 write_header();
00283 }
00284
00285 return TRUE;
00286 }
00287
00289
00290 void FileRenderer::render(const VMDDisplayList *cmdList) {
00291 if (!cmdList) return;
00292 int tok, i;
00293 char *cmdptr;
00294
00295
00296
00297
00298 while (transMat.num()) {
00299 transMat.pop();
00300 }
00301 Matrix4 m;
00302 transMat.push(m);
00303 super_multmatrix(cmdList->mat.mat);
00304
00305 colorIndex = 0;
00306 materialIndex = 0;
00307 float textsize = 1;
00308 pointSize = 1;
00309 lineWidth = 1;
00310 lineStyle = ::SOLIDLINE;
00311 sphereResolution = 4;
00312 sphereStyle = 1;
00313
00314
00315 super_set_material(cmdList->materialtag);
00316 mat_ambient = cmdList->ambient;
00317 mat_specular = cmdList->specular;
00318 mat_diffuse = cmdList->diffuse;
00319 mat_shininess = cmdList->shininess;
00320 mat_opacity = cmdList->opacity;
00321 mat_outline = cmdList->outline;
00322 mat_outlinewidth = cmdList->outlinewidth;
00323 mat_transmode = cmdList->transmode;
00324
00325 for (i=0; i<VMD_MAX_CLIP_PLANE; i++) {
00326 clip_mode[i] = cmdList->clipplanes[i].mode;
00327 memcpy(&clip_center[i][0], &cmdList->clipplanes[i].center, 3*sizeof(float));
00328 memcpy(&clip_normal[i][0], &cmdList->clipplanes[i].normal, 3*sizeof(float));
00329 memcpy(&clip_color[i][0], &cmdList->clipplanes[i].color, 3*sizeof(float));
00330 }
00331 start_clipgroup();
00332
00333
00334 ResizeArray<Matrix4> pbcImages;
00335 find_pbc_images(cmdList, pbcImages);
00336
00337
00338
00339
00340 textoffset_x = 0;
00341 textoffset_y = 0;
00342
00343 int nimages = pbcImages.num();
00344 for (int pbcimage = 0; pbcimage < nimages; pbcimage++) {
00345 transMat.dup();
00346 super_multmatrix(pbcImages[pbcimage].mat);
00347
00348 VMDDisplayList::VMDLinkIter cmditer;
00349 cmdList->first(&cmditer);
00350 while ((tok = cmdList->next(&cmditer, cmdptr)) != DLASTCOMMAND) {
00351 switch (tok) {
00352 case DPOINT:
00353 point(((DispCmdPoint *)cmdptr)->pos);
00354 break;
00355
00356 case DPOINTARRAY:
00357 {
00358 DispCmdPointArray *pa = (DispCmdPointArray *)cmdptr;
00359 float *centers, *colors;
00360 pa->getpointers(centers, colors);
00361 point_array(pa->numpoints, pa->size, centers, colors);
00362 }
00363 break;
00364
00365 case DLITPOINTARRAY:
00366 {
00367 DispCmdLitPointArray *pa = (DispCmdLitPointArray *)cmdptr;
00368 float *centers, *normals, *colors;
00369 pa->getpointers(centers, normals, colors);
00370 point_array_lit(pa->numpoints, pa->size, centers, normals, colors);
00371 }
00372 break;
00373
00374 case DSPHERE:
00375 sphere((float *)cmdptr);
00376 break;
00377
00378 case DSPHEREARRAY:
00379 {
00380 DispCmdSphereArray *sa = (DispCmdSphereArray *)cmdptr;
00381 float *centers, *radii, *colors;
00382 sa->getpointers(centers, radii, colors);
00383 sphere_array(sa->numspheres, sa->sphereres, centers, radii, colors);
00384 }
00385 break;
00386
00387 case DLINE:
00388
00389 if (memcmp(cmdptr, cmdptr+3*sizeof(float), 3*sizeof(float))) {
00390 line((float *)cmdptr, ((float *)cmdptr) + 3);
00391 }
00392 break;
00393
00394 case DLINEARRAY:
00395 {
00396 float *v = (float *) cmdptr;
00397 int nlines = (int)v[0];
00398 v++;
00399 line_array(nlines, (float) lineWidth, v);
00400 }
00401 break;
00402
00403 case DPOLYLINEARRAY:
00404 {
00405 float *v = (float *) cmdptr;
00406 int nlines = (int)v[0];
00407 v++;
00408 polyline_array(nlines, (float) lineWidth, v);
00409 }
00410 break;
00411
00412 case DCYLINDER:
00413 if (memcmp(cmdptr, cmdptr+3*sizeof(float), 3*sizeof(float))) {
00414 cylinder((float *)cmdptr, ((float *)cmdptr) + 3, ((float *)cmdptr)[6],
00415 ((int) ((float *) cmdptr)[8]));
00416 }
00417 break;
00418
00419 case DCONE:
00420 {
00421 DispCmdCone *cmd = (DispCmdCone *)cmdptr;
00422 if (memcmp(cmd->pos1, cmd->pos2, 3*sizeof(float)))
00423 cone_trunc(cmd->pos1, cmd->pos2, cmd->radius, cmd->radius2, cmd->res);
00424 }
00425 break;
00426
00427 case DTRIANGLE:
00428 {
00429 DispCmdTriangle *cmd = (DispCmdTriangle *)cmdptr;
00430 triangle(cmd->pos1,cmd->pos2,cmd->pos3,
00431 cmd->norm1, cmd->norm2, cmd->norm3);
00432 }
00433 break;
00434
00435 case DTRIMESH_C3F_N3F_V3F:
00436 {
00437 DispCmdTriMesh *cmd = (DispCmdTriMesh *) cmdptr;
00438 float *c=NULL, *n=NULL, *v=NULL;
00439
00440 if (cmd->pervertexcolors) {
00441 cmd->getpointers(c, n, v);
00442 trimesh_c3f_n3f_v3f(c, n, v, cmd->numfacets);
00443 } else {
00444 cmd->getpointers(n, v);
00445 trimesh_n3f_v3f(n, v, cmd->numfacets);
00446 }
00447 }
00448 break;
00449
00450 case DTRIMESH_C4F_N3F_V3F:
00451 {
00452 DispCmdTriMesh *cmd = (DispCmdTriMesh *) cmdptr;
00453 float *cnv=NULL;
00454 int *f=NULL;
00455 cmd->getpointers(cnv, f);
00456 trimesh_c4n3v3(cmd->numverts, cnv, cmd->numfacets, f);
00457 }
00458 break;
00459
00460 case DTRIMESH_C4U_N3F_V3F:
00461 {
00462 DispCmdTriMesh *cmd = (DispCmdTriMesh *) cmdptr;
00463 unsigned char *c=NULL;
00464 float *n=NULL, *v=NULL;
00465
00466 if (cmd->pervertexcolors) {
00467 cmd->getpointers(c, n, v);
00468 trimesh_c4u_n3f_v3f(c, n, v, cmd->numfacets);
00469 } else {
00470 cmd->getpointers(n, v);
00471 trimesh_n3f_v3f(n, v, cmd->numfacets);
00472 }
00473 }
00474 break;
00475
00476 case DTRIMESH_C4U_N3B_V3F:
00477 {
00478 DispCmdTriMesh *cmd = (DispCmdTriMesh *) cmdptr;
00479 unsigned char *c=NULL;
00480 char *n=NULL;
00481 float *v=NULL;
00482
00483 if (cmd->pervertexcolors) {
00484 cmd->getpointers(c, n, v);
00485 trimesh_c4u_n3b_v3f(c, n, v, cmd->numfacets);
00486 } else {
00487 cmd->getpointers(n, v);
00488 trimesh_n3b_v3f(n, v, cmd->numfacets);
00489 }
00490 }
00491 break;
00492
00493 case DTRISTRIP:
00494 {
00495 DispCmdTriStrips *cmd = (DispCmdTriStrips *) cmdptr;
00496 float *cnv=NULL;
00497 int *f=NULL;
00498 int *vertsperstrip;
00499 cmd->getpointers(cnv, f, vertsperstrip);
00500 tristrip(cmd->numverts, cnv, cmd->numstrips, vertsperstrip, f);
00501 }
00502 break;
00503
00504 case DWIREMESH:
00505 {
00506 DispCmdWireMesh *cmd = (DispCmdWireMesh *) cmdptr;
00507 float *cnv=NULL;
00508 int *l=NULL;
00509 cmd->getpointers(cnv, l);
00510 wiremesh(cmd->numverts, cnv, cmd->numlines, l);
00511 }
00512 break;
00513
00514 case DSQUARE:
00515 {
00516 DispCmdSquare *cmd = (DispCmdSquare *)cmdptr;
00517 square(cmd->norml, cmd->pos1, cmd->pos2, cmd->pos3, cmd->pos4);
00518 }
00519 break;
00520
00521
00523 case DLINEWIDTH:
00524 lineWidth = ((DispCmdLineWidth *)cmdptr)->width;
00525 set_line_width(lineWidth);
00526 break;
00527
00528 case DLINESTYLE:
00529 lineStyle = ((DispCmdLineType *)cmdptr)->type;
00530 set_line_style(lineStyle);
00531 break;
00532
00533 case DSPHERERES:
00534 sphereResolution = ((DispCmdSphereRes *)cmdptr)->res;
00535 set_sphere_res(sphereResolution);
00536 break;
00537
00538 case DSPHERETYPE:
00539 sphereStyle = ((DispCmdSphereType *)cmdptr)->type;
00540 set_sphere_style(sphereStyle);
00541 break;
00542
00543 case DMATERIALON:
00544 super_materials(1);
00545 break;
00546
00547 case DMATERIALOFF:
00548 super_materials(0);
00549 break;
00550
00551 case DCOLORINDEX:
00552 super_set_color(((DispCmdColorIndex *)cmdptr)->color);
00553 break;
00554
00555 case DTEXTSIZE:
00556 textsize = ((DispCmdTextSize *)cmdptr)->size;
00557 break;
00558
00559 case DTEXTOFFSET:
00560 textoffset_x = ((DispCmdTextOffset *)cmdptr)->x;
00561 textoffset_y = ((DispCmdTextOffset *)cmdptr)->y;
00562 break;
00563
00564 case DTEXT:
00565 {
00566 float *pos = (float *)cmdptr;
00567 text(pos, textsize, pos[3], (char *) (pos+4));
00568 }
00569 break;
00570
00571 case DBEGINREPGEOMGROUP:
00572 beginrepgeomgroup((char *)cmdptr);
00573 break;
00574
00575 case DCOMMENT:
00576 comment((char *)cmdptr);
00577 break;
00578
00579
00580 case DPICKPOINT:
00581 pick_point(((DispCmdPickPoint *)cmdptr)->postag,
00582 ((DispCmdPickPoint *)cmdptr)->tag);
00583 break;
00584
00585 case DPICKPOINT_ARRAY:
00586 {
00587 int i;
00588 DispCmdPickPointArray *cmd = ((DispCmdPickPointArray *)cmdptr);
00589 float *crds=NULL;
00590 int *indices=NULL;
00591 cmd->getpointers(crds, indices);
00592 if (cmd->allselected) {
00593 for (i=0; i<cmd->numpicks; i++) {
00594 pick_point(crds + i*3, i);
00595 }
00596 } else {
00597 for (i=0; i<cmd->numpicks; i++) {
00598 pick_point(crds + i*3, indices[i]);
00599 }
00600 }
00601 }
00602 break;
00603
00604
00605 #if 0
00606 case DSTRIPETEXON:
00607 case DSTRIPETEXOFF:
00608 #endif
00609 case DVOLUMETEXTURE:
00610 {
00611 DispCmdVolumeTexture *cmd = (DispCmdVolumeTexture *)cmdptr;
00612 float xplaneeq[4];
00613 float yplaneeq[4];
00614 float zplaneeq[4];
00615 int i;
00616
00617
00618
00619 for (i=0; i<3; i++) {
00620 xplaneeq[i] = cmd->v1[i];
00621 yplaneeq[i] = cmd->v2[i];
00622 zplaneeq[i] = cmd->v3[i];
00623 }
00624 xplaneeq[3] = cmd->v0[0];
00625 yplaneeq[3] = cmd->v0[1];
00626 zplaneeq[3] = cmd->v0[2];
00627
00628
00629 define_volume_texture(cmd->ID, cmd->xsize, cmd->ysize, cmd->zsize,
00630 xplaneeq, yplaneeq, zplaneeq,
00631 cmd->texmap);
00632 volume_texture_on(1);
00633 }
00634 break;
00635
00636 case DVOLSLICE:
00637 {
00638
00639
00640 super_materials(0);
00641 DispCmdVolSlice *cmd = (DispCmdVolSlice *)cmdptr;
00642 volume_texture_on(1);
00643 square(cmd->normal, cmd->v, cmd->v + 3, cmd->v + 6, cmd->v + 9);
00644 volume_texture_off();
00645 super_materials(1);
00646 }
00647 break;
00648
00649 case DVOLTEXON:
00650 volume_texture_on(0);
00651 break;
00652
00653 case DVOLTEXOFF:
00654 volume_texture_off();
00655 break;
00656
00657 #if 0
00658
00659 default:
00660 warningflags |= FILERENDERER_NOMISCFEATURE;
00661 break;
00662 #endif
00663 }
00664 }
00665 transMat.pop();
00666 }
00667 end_clipgroup();
00668 }
00669
00671
00672
00673
00674 void FileRenderer::super_set_color(int color_index) {
00675 if (colorIndex != color_index) {
00676 colorIndex = color_index;
00677 set_color(color_index);
00678 }
00679 }
00680
00681
00682 void FileRenderer::super_set_material(int material_index) {
00683 if (materialIndex != material_index) {
00684 materialIndex = material_index;
00685 set_material(material_index);
00686 }
00687 }
00688
00689
00690 void FileRenderer::super_materials(int on_or_off) {
00691 if (on_or_off) {
00692 materials_on = 1;
00693 activate_materials();
00694 } else {
00695 materials_on = 0;
00696 deactivate_materials();
00697 }
00698 }
00699
00700
00702
00703 void FileRenderer::super_load(float *cmdptr) {
00704 Matrix4 tmp(cmdptr);
00705 (transMat.top()).loadmatrix(tmp);
00706 load(tmp);
00707 }
00708 void FileRenderer::super_multmatrix(const float *cmdptr) {
00709 Matrix4 tmp(cmdptr);
00710 (transMat.top()).multmatrix(tmp);
00711 multmatrix(tmp);
00712 }
00713
00714 void FileRenderer::super_translate(float *cmdptr) {
00715 (transMat.top()).translate( cmdptr[0], cmdptr[1], cmdptr[2]);
00716 translate( cmdptr[0], cmdptr[1], cmdptr[2]);
00717 }
00718
00719 void FileRenderer::super_rot(float * cmdptr) {
00720 (transMat.top()).rot( cmdptr[0], 'x' + (int) (cmdptr[1]) );
00721 rot( cmdptr[0], 'x' + (int) (cmdptr[1]) );
00722 }
00723
00724 void FileRenderer::super_scale(float *cmdptr) {
00725 (transMat.top()).scale( cmdptr[0], cmdptr[1], cmdptr[2] );
00726 scale( cmdptr[0], cmdptr[1], cmdptr[2] );
00727 }
00728
00729 void FileRenderer::super_scale(float s) {
00730 transMat.top().scale(s,s,s);
00731 scale(s,s,s);
00732 }
00733
00734
00735 float FileRenderer::scale_factor(void) {
00736
00737
00738
00739 float scaleFactor;
00740
00741 float *mat = &transMat.top().mat[0];
00742 scaleFactor = (sqrtf(mat[0]*mat[0] + mat[4]*mat[4] + mat[ 8]*mat[ 8]) +
00743 sqrtf(mat[1]*mat[1] + mat[5]*mat[5] + mat[ 9]*mat[ 9]) +
00744 sqrtf(mat[2]*mat[2] + mat[6]*mat[6] + mat[10]*mat[10])) / 3.0f;
00745
00746 return scaleFactor;
00747 }
00748
00749
00750 float FileRenderer::scale_radius(float r) {
00751 float scaleFactor = scale_factor();
00752 if (r < 0.0) {
00753 msgErr << "FileRenderer: Error, Negative radius" << sendmsg;
00754 r = -r;
00755 }
00756 r = r * scaleFactor;
00757 return r;
00758 }
00759
00760
00762 void FileRenderer::set_exec_string(const char *extstr) {
00763 delete [] execCmd;
00764 execCmd = stringdup(extstr);
00765 }
00766
00767
00768
00769 void FileRenderer::cone_trunc(float *base, float *apex, float radius, float radius2, int numsides) {
00770 int h;
00771 float theta, incTheta, cosTheta, sinTheta;
00772 float axis[3], temp[3], perp[3], perp2[3];
00773 float vert0[3], vert1[3], vert2[3], edge0[3], edge1[3], face0[3], face1[3], norm0[3], norm1[3];
00774
00775 axis[0] = base[0] - apex[0];
00776 axis[1] = base[1] - apex[1];
00777 axis[2] = base[2] - apex[2];
00778 vec_normalize(axis);
00779
00780
00781 temp[0] = axis[0] - 1.0f;
00782 temp[1] = 1.0f;
00783 temp[2] = 1.0f;
00784
00785
00786 cross_prod(perp, axis, temp);
00787 vec_normalize(perp);
00788 cross_prod(perp2, axis, perp);
00789
00790
00791 incTheta = (float) VMD_TWOPI / numsides;
00792 theta = 0.0;
00793
00794
00795
00796 if (radius2 > 0) {
00797 float negaxis[3], offsetL[3], offsetT[3], vert3[3];
00798 int filled=1;
00799 vec_negate(negaxis, axis);
00800 memset(vert0, 0, sizeof(vert0));
00801 memset(vert1, 0, sizeof(vert1));
00802 memset(norm0, 0, sizeof(norm0));
00803
00804 for (h=0; h <= numsides+3; h++) {
00805
00806
00807 cosTheta = (float) cosf(theta);
00808 sinTheta = (float) sinf(theta);
00809 offsetL[0] = radius2 * (cosTheta*perp[0] + sinTheta*perp2[0]);
00810 offsetL[1] = radius2 * (cosTheta*perp[1] + sinTheta*perp2[1]);
00811 offsetL[2] = radius2 * (cosTheta*perp[2] + sinTheta*perp2[2]);
00812 offsetT[0] = radius * (cosTheta*perp[0] + sinTheta*perp2[0]);
00813 offsetT[1] = radius * (cosTheta*perp[1] + sinTheta*perp2[1]);
00814 offsetT[2] = radius * (cosTheta*perp[2] + sinTheta*perp2[2]);
00815
00816
00817 vec_copy(vert2, vert0);
00818 vec_copy(vert3, vert1);
00819 vec_copy(norm1, norm0);
00820
00821
00822 vec_add(vert0, base, offsetT);
00823 vec_add(vert1, apex, offsetL);
00824
00825
00826 edge0[0] = vert0[0] - vert1[0];
00827 edge0[1] = vert0[1] - vert1[1];
00828 edge0[2] = vert0[2] - vert1[2];
00829 edge1[0] = vert0[0] - vert2[0];
00830 edge1[1] = vert0[1] - vert2[1];
00831 edge1[2] = vert0[2] - vert2[2];
00832
00833
00834 cross_prod(norm0, edge1, edge0);
00835 vec_normalize(norm0);
00836
00837 if (h > 2) {
00838
00839 triangle(vert0, vert3, vert1, norm0, norm1, norm0);
00840 triangle(vert3, vert0, vert2, norm1, norm0, norm1);
00841
00842
00843 if (filled & CYLINDER_LEADINGCAP) {
00844 triangle(vert1, vert3, apex, axis, axis, axis);
00845 }
00846 if (filled & CYLINDER_TRAILINGCAP) {
00847 triangle(vert0, vert2, base, negaxis, negaxis, negaxis);
00848 }
00849 }
00850
00851 theta += incTheta;
00852 }
00853 } else {
00854
00855 for (h=0; h < numsides+3; h++) {
00856
00857
00858 cosTheta = (float) cosf(theta);
00859 sinTheta = (float) sinf(theta);
00860 vert0[0] = base[0] + radius * (cosTheta*perp[0] + sinTheta*perp2[0]);
00861 vert0[1] = base[1] + radius * (cosTheta*perp[1] + sinTheta*perp2[1]);
00862 vert0[2] = base[2] + radius * (cosTheta*perp[2] + sinTheta*perp2[2]);
00863
00864
00865 edge0[0] = vert0[0] - apex[0];
00866 edge0[1] = vert0[1] - apex[1];
00867 edge0[2] = vert0[2] - apex[2];
00868
00869 if (h > 0) {
00870
00871 cross_prod(face0, edge1, edge0);
00872 vec_normalize(face0);
00873
00874 if (h > 1) {
00875
00876 norm0[0] = (face1[0] + face0[0]) * 0.5f;
00877 norm0[1] = (face1[1] + face0[1]) * 0.5f;
00878 norm0[2] = (face1[2] + face0[2]) * 0.5f;
00879 vec_normalize(norm0);
00880
00881 if (h > 2) {
00882
00883 triangle(vert2, vert1, apex, norm1, norm0, face1);
00884 triangle(vert2, vert1, base, axis, axis, axis);
00885 }
00886
00887 }
00888
00889
00890 memcpy(norm1, norm0, 3*sizeof(float));
00891 memcpy(vert2, vert1, 3*sizeof(float));
00892 memcpy(face1, face0, 3*sizeof(float));
00893 }
00894 memcpy(vert1, vert0, 3*sizeof(float));
00895 memcpy(edge1, edge0, 3*sizeof(float));
00896
00897 theta += incTheta;
00898 }
00899 }
00900 }
00901
00902
00903
00904 void FileRenderer::cylinder(float *base, float *apex, float radius, int filled) {
00905 const int numsides = 20;
00906 int h;
00907 float theta, incTheta, cosTheta, sinTheta;
00908 float axis[3], negaxis[3], temp[3], perp[3], perp2[3], offset[3];
00909
00910 axis[0] = base[0] - apex[0];
00911 axis[1] = base[1] - apex[1];
00912 axis[2] = base[2] - apex[2];
00913 vec_normalize(axis);
00914 vec_negate(negaxis, axis);
00915
00916
00917 temp[0] = axis[0] - 1.0f;
00918 temp[1] = 1.0f;
00919 temp[2] = 1.0f;
00920
00921
00922 cross_prod(perp, axis, temp);
00923 vec_normalize(perp);
00924 cross_prod(perp2, axis, perp);
00925
00926
00927 incTheta = (float) VMD_TWOPI / numsides;
00928 theta = 0.0;
00929
00930 const int stripsz = (2*numsides) * 6;
00931 float *stripnv = new float[stripsz];
00932 memset(stripnv, 0, sizeof(float) * stripsz);
00933
00934 const int capsz = numsides+1;
00935 float *lcapnv = new float[capsz*6];
00936 memset(lcapnv, 0, sizeof(float)*capsz*6);
00937 vec_copy(&lcapnv[0], negaxis);
00938 vec_copy(&lcapnv[3], apex);
00939
00940 float *tcapnv = new float[capsz*6];
00941 memset(tcapnv, 0, sizeof(float)*capsz*6);
00942 vec_copy(&tcapnv[0], axis);
00943 vec_copy(&tcapnv[3], base);
00944
00945 for (h=0; h < numsides; h++) {
00946
00947
00948 cosTheta = (float) cosf(theta);
00949 sinTheta = (float) sinf(theta);
00950 offset[0] = radius * (cosTheta*perp[0] + sinTheta*perp2[0]);
00951 offset[1] = radius * (cosTheta*perp[1] + sinTheta*perp2[1]);
00952 offset[2] = radius * (cosTheta*perp[2] + sinTheta*perp2[2]);
00953
00954
00955 float lvert[3], tvert[3];
00956 vec_add(lvert, apex, offset);
00957 vec_add(tvert, base, offset);
00958 vec_copy(&stripnv[((2*h)*6)+9], lvert);
00959 vec_copy(&stripnv[((2*h)*6)+3], tvert);
00960 vec_copy(&lcapnv[((1+h)*6)+3], lvert);
00961 vec_copy(&tcapnv[((1+h)*6)+3], tvert);
00962
00963
00964 vec_normalize(offset);
00965 vec_copy(&stripnv[((2*h)*6) ], offset);
00966 vec_copy(&stripnv[((2*h)*6)+6], offset);
00967 vec_copy(&lcapnv[((1+h)*6)], negaxis);
00968 vec_copy(&tcapnv[((1+h)*6)], axis);
00969
00970 theta += incTheta;
00971 }
00972
00973 const int vertsperstrip = (numsides + 1)*2;
00974 int *stripfaces = new int[vertsperstrip];
00975 memset(stripfaces, 0, sizeof(float) * vertsperstrip);
00976 for (h=0; h < vertsperstrip-2; h++) {
00977 stripfaces[h] = h;
00978 }
00979 stripfaces[h ] = 0;
00980 stripfaces[h+1] = 1;
00981
00982 tristrip_singlecolor(2*numsides, &stripnv[0],
00983 1, &colorIndex, &vertsperstrip, &stripfaces[0]);
00984 delete [] stripfaces;
00985
00986
00987 if (filled & CYLINDER_LEADINGCAP) {
00988 const int vertsperfan = capsz+1;
00989 int *fanfaces = new int[vertsperfan];
00990 memset(fanfaces, 0, sizeof(float) * vertsperfan);
00991 fanfaces[0] = 0;
00992 for (h=1; h < capsz; h++) {
00993 fanfaces[h] = capsz-h;
00994 }
00995 fanfaces[h] = capsz-1;
00996 trifan_singlecolor(capsz-1, &lcapnv[0],
00997 1, &colorIndex, &vertsperfan, &fanfaces[0]);
00998 delete [] fanfaces;
00999 }
01000 if (filled & CYLINDER_TRAILINGCAP) {
01001 const int vertsperfan = capsz+1;
01002 int *fanfaces = new int[vertsperfan];
01003 memset(fanfaces, 0, sizeof(float) * vertsperfan);
01004 fanfaces[0] = 0;
01005 for (h=1; h < capsz; h++) {
01006 fanfaces[h] = h;
01007 }
01008 fanfaces[h] = 1;
01009 trifan_singlecolor(capsz-1, &tcapnv[0],
01010 1, &colorIndex, &vertsperfan, &fanfaces[0]);
01011 delete [] fanfaces;
01012 }
01013
01014 delete [] stripnv;
01015 delete [] lcapnv;
01016 delete [] tcapnv;
01017 }
01018
01019
01020
01021
01022 void FileRenderer::line(float * a, float * b) {
01023
01024 int i, j, test;
01025 float dirvec[3], unitdirvec[3];
01026 float from[3], to[3];
01027
01028 if (lineStyle == ::SOLIDLINE) {
01029 cylinder(a, b, lineWidth * 0.002f, 0);
01030 } else if (lineStyle == ::DASHEDLINE) {
01031 vec_sub(dirvec, b, a);
01032 vec_copy(unitdirvec, dirvec);
01033 vec_normalize(unitdirvec);
01034 test = 1;
01035 i = 0;
01036 while (test == 1) {
01037 for (j=0; j<3; j++) {
01038 from[j] = (float) (a[j] + (2*i )* 0.05 * unitdirvec[j]);
01039 to[j] = (float) (a[j] + (2*i + 1)* 0.05 * unitdirvec[j]);
01040 }
01041 if (fabsf(a[0] - to[0]) >= fabsf(dirvec[0])) {
01042 vec_copy(to, b);
01043 test = 0;
01044 }
01045 cylinder(from, to, lineWidth * 0.002f, 0);
01046 i++;
01047 }
01048 }
01049 }
01050
01051
01052 void FileRenderer::line_array(int num, float thickness, float *points) {
01053 float *v = points;
01054 for (int i=0; i<num; i++) {
01055
01056 if (memcmp(v, v+3, 3*sizeof(float))) {
01057 line(v, v+3);
01058 }
01059 v += 6;
01060 }
01061 }
01062
01063
01064 void FileRenderer::polyline_array(int num, float thickness, float *points) {
01065 float *v = points;
01066 for (int i=0; i<num-1; i++) {
01067
01068 if (memcmp(v, v+3, 3*sizeof(float))) {
01069 line(v, v+3);
01070 }
01071 v += 3;
01072 }
01073 }
01074
01075
01076
01077 void FileRenderer::sphere(float * xyzr) {
01078 float c[3], r;
01079 int pi, ni;
01080 int i;
01081 int sph_iter = -1;
01082 int sph_desired_iter = 0;
01083
01084
01085 vec_copy(c, xyzr);
01086 r = xyzr[3];
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096 const int sph_iter_table[] = {
01097 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3,
01098 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4 };
01099
01100 if (sphereResolution < 0)
01101 return;
01102 else if (sphereResolution < 32)
01103 sph_desired_iter = sph_iter_table[sphereResolution];
01104 else
01105 sph_desired_iter = (int) (0.8f * sqrtf((float) sphereResolution));
01106
01107
01108
01109
01110 if (!sph_verts || !sph_nverts || sph_iter != sph_desired_iter) {
01111 float a[3], b[3], c[3];
01112 float *newverts;
01113 float *oldverts;
01114 int nverts, ntris;
01115 int level;
01116
01117
01118 if (sph_verts && sph_nverts) free(sph_verts);
01119
01120 newverts = (float *) malloc(sizeof(float) * 36);
01121 nverts = 12;
01122 ntris = 4;
01123
01124
01125
01126
01127 newverts[0] = -1; newverts[1] = 0; newverts[2] = 0;
01128 newverts[3] = 0; newverts[4] = 1; newverts[5] = 0;
01129 newverts[6] = 0; newverts[7] = 0; newverts[8] = 1;
01130
01131
01132 newverts[9] = 0; newverts[10] = 0; newverts[11] = 1;
01133 newverts[12] = 0; newverts[13] = 1; newverts[14] = 0;
01134 newverts[15] = 1; newverts[16] = 0; newverts[17] = 0;
01135
01136
01137 newverts[18] = 0; newverts[19] = 0; newverts[20] = 1;
01138 newverts[21] = 1; newverts[22] = 0; newverts[23] = 0;
01139 newverts[24] = 0; newverts[25] = -1; newverts[26] = 0;
01140
01141
01142 newverts[27] = 0; newverts[28] = 0; newverts[29] = 1;
01143 newverts[30] = 0; newverts[31] = -1; newverts[32] = 0;
01144 newverts[33] = -1; newverts[34] = 0; newverts[35] = 0;
01145
01146 for (level = 1; level < sph_desired_iter; level++) {
01147 oldverts = newverts;
01148
01149
01150
01151 newverts = (float *) malloc(sizeof(float) * 12 * nverts);
01152 if (!newverts) {
01153
01154 sph_iter = -1;
01155 sph_nverts = 0;
01156 sph_verts = NULL;
01157 free(oldverts);
01158 msgErr << "FileRenderer::sphere(): Out of memory. Some "
01159 << "objects were not drawn." << sendmsg;
01160 return;
01161 }
01162
01163 pi = 0;
01164 ni = 0;
01165 for (i = 0; i < ntris; i++) {
01166
01167 a[0] = (oldverts[pi ] + oldverts[pi + 6]) / 2;
01168 a[1] = (oldverts[pi + 1] + oldverts[pi + 7]) / 2;
01169 a[2] = (oldverts[pi + 2] + oldverts[pi + 8]) / 2;
01170 vec_normalize(a);
01171 b[0] = (oldverts[pi ] + oldverts[pi + 3]) / 2;
01172 b[1] = (oldverts[pi + 1] + oldverts[pi + 4]) / 2;
01173 b[2] = (oldverts[pi + 2] + oldverts[pi + 5]) / 2;
01174 vec_normalize(b);
01175 c[0] = (oldverts[pi + 3] + oldverts[pi + 6]) / 2;
01176 c[1] = (oldverts[pi + 4] + oldverts[pi + 7]) / 2;
01177 c[2] = (oldverts[pi + 5] + oldverts[pi + 8]) / 2;
01178 vec_normalize(c);
01179
01180
01181 memcpy(&newverts[ni ], &oldverts[pi], sizeof(float) * 3);
01182 memcpy(&newverts[ni + 3 ], b, sizeof(float) * 3);
01183 memcpy(&newverts[ni + 6 ], a, sizeof(float) * 3);
01184
01185 memcpy(&newverts[ni + 9 ], b, sizeof(float) * 3);
01186 memcpy(&newverts[ni + 12], &oldverts[pi + 3], sizeof(float) * 3);
01187 memcpy(&newverts[ni + 15], c, sizeof(float) * 3);
01188
01189 memcpy(&newverts[ni + 18], a, sizeof(float) * 3);
01190 memcpy(&newverts[ni + 21], b, sizeof(float) * 3);
01191 memcpy(&newverts[ni + 24], c, sizeof(float) * 3);
01192
01193 memcpy(&newverts[ni + 27], a, sizeof(float) * 3);
01194 memcpy(&newverts[ni + 30], c, sizeof(float) * 3);
01195 memcpy(&newverts[ni + 33], &oldverts[pi + 6], sizeof(float) * 3);
01196
01197 pi += 9;
01198 ni += 36;
01199 }
01200
01201 free(oldverts);
01202 nverts *= 4;
01203 ntris *= 4;
01204 }
01205
01206 sph_iter = sph_desired_iter;
01207 sph_nverts = nverts;
01208 sph_verts = newverts;
01209 }
01210
01211
01212
01213
01214 pi = 0;
01215 for (i = 0; i < sph_nverts / 3; i++) {
01216 float v0[3], v1[3], v2[3];
01217 float n0[3], n1[3], n2[3];
01218
01219
01220 v0[0] = r * sph_verts[pi ] + c[0];
01221 v0[1] = r * sph_verts[pi + 1] + c[1];
01222 v0[2] = r * sph_verts[pi + 2] + c[2];
01223 v1[0] = r * sph_verts[pi + 3] + c[0];
01224 v1[1] = r * sph_verts[pi + 4] + c[1];
01225 v1[2] = r * sph_verts[pi + 5] + c[2];
01226 v2[0] = r * sph_verts[pi + 6] + c[0];
01227 v2[1] = r * sph_verts[pi + 7] + c[1];
01228 v2[2] = r * sph_verts[pi + 8] + c[2];
01229
01230
01231 vec_copy(n0, &sph_verts[pi ]);
01232 vec_copy(n1, &sph_verts[pi + 3]);
01233 vec_copy(n2, &sph_verts[pi + 6]);
01234
01235
01236 triangle(v0, v2, v1, n0, n2, n1);
01237
01238
01239 v0[2] = (-r * sph_verts[pi + 2]) + c[2];
01240 v1[2] = (-r * sph_verts[pi + 5]) + c[2];
01241 v2[2] = (-r * sph_verts[pi + 8]) + c[2];
01242
01243
01244 n0[2] = -n0[2];
01245 n1[2] = -n1[2];
01246 n2[2] = -n2[2];
01247
01248
01249 triangle(v0, v1, v2, n0, n1, n2);
01250
01251 pi += 9;
01252 }
01253 }
01254
01255
01256
01257
01258
01259 void FileRenderer::sphere_array(int spnum, int spres,
01260 float *centers, float *radii, float *colors) {
01261 int i, ind;
01262 set_sphere_res(spres);
01263 ind = 0;
01264 for (i=0; i<spnum; i++) {
01265 float xyzr[4];
01266 xyzr[0]=centers[ind ];
01267 xyzr[1]=centers[ind + 1];
01268 xyzr[2]=centers[ind + 2];
01269 xyzr[3]=radii[i];
01270
01271 super_set_color(nearest_index(colors[ind], colors[ind+1], colors[ind+2]));
01272 sphere(xyzr);
01273 ind += 3;
01274 }
01275 }
01276
01277
01278
01279
01280 void FileRenderer::point_array(int num, float size, float *xyz, float *colors) {
01281 int i, ind;
01282
01283 pointSize = (int) size;
01284
01285
01286 for (ind=0,i=0; i<num; i++) {
01287 super_set_color(nearest_index(colors[ind], colors[ind+1], colors[ind+2]));
01288 point(&xyz[ind]);
01289 ind += 3;
01290 }
01291
01292 pointSize = 1;
01293 }
01294
01295
01296
01297
01298 void FileRenderer::point_array_lit(int num, float size,
01299 float *xyz, float *norms, float *colors) {
01300
01301
01302 point_array(num, size, xyz, colors);
01303 }
01304
01305
01306
01307
01308 void FileRenderer::start_clipgroup() {
01309 int i;
01310
01311 for (i=0; i<VMD_MAX_CLIP_PLANE; i++) {
01312 if (clip_mode[i]) {
01313 warningflags |= FILERENDERER_NOCLIP;
01314 break;
01315 }
01316 }
01317 }
01318
01319
01320 void FileRenderer::text(float *pos, float size, float thickness, const char *str) {
01321 #if 1
01322
01323
01324 warningflags |= FILERENDERER_NOTEXT;
01325 #else
01326 hersheyhandle hh;
01327 float lm, rm, x, y, ox, oy;
01328 int draw, odraw;
01329
01330 Matrix4 m;
01331 transMat.push(m);
01332
01333 while (*str != '\0') {
01334 hersheyDrawInitLetter(&hh, *str, &lm, &rm);
01335 (transMat.top()).translate(-lm, 0, 0);
01336 ox=0;
01337 oy=0;
01338 odraw=0;
01339 while (!hersheyDrawNextLine(&hh, &draw, &x, &y)) {
01340 if (draw && odraw) {
01341 float a[3], b[3];
01342 a[0] = ox;
01343 a[1] = oy;
01344 a[2] = 0;
01345 b[0] = x;
01346 b[1] = y;
01347 b[2] = 0;
01348
01349
01350 line(a, b);
01351 }
01352
01353 ox=x;
01354 oy=y;
01355 odraw=draw;
01356 }
01357 (transMat.top()).translate(rm, 0, 0);
01358
01359 str++;
01360 }
01361
01362 transMat.pop();
01363 #endif
01364 }
01365
01366