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