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(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_c3n3v3(c, n, v, cmd->numfacets);
00443 } else {
00444 cmd->getpointers(n, v);
00445 trimesh_n3v3(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 DTRISTRIP:
00461 {
00462 DispCmdTriStrips *cmd = (DispCmdTriStrips *) cmdptr;
00463 float *cnv=NULL;
00464 int *f=NULL;
00465 int *vertsperstrip;
00466 cmd->getpointers(cnv, f, vertsperstrip);
00467 tristrip(cmd->numverts, cnv, cmd->numstrips, vertsperstrip, f);
00468 }
00469 break;
00470
00471 case DWIREMESH:
00472 {
00473 DispCmdWireMesh *cmd = (DispCmdWireMesh *) cmdptr;
00474 float *cnv=NULL;
00475 int *l=NULL;
00476 cmd->getpointers(cnv, l);
00477 wiremesh(cmd->numverts, cnv, cmd->numlines, l);
00478 }
00479 break;
00480
00481 case DSQUARE:
00482 {
00483 DispCmdSquare *cmd = (DispCmdSquare *)cmdptr;
00484 square(cmd->norml, cmd->pos1, cmd->pos2, cmd->pos3, cmd->pos4);
00485 }
00486 break;
00487
00488
00490 case DLINEWIDTH:
00491 lineWidth = ((DispCmdLineWidth *)cmdptr)->width;
00492 set_line_width(lineWidth);
00493 break;
00494
00495 case DLINESTYLE:
00496 lineStyle = ((DispCmdLineType *)cmdptr)->type;
00497 set_line_style(lineStyle);
00498 break;
00499
00500 case DSPHERERES:
00501 sphereResolution = ((DispCmdSphereRes *)cmdptr)->res;
00502 set_sphere_res(sphereResolution);
00503 break;
00504
00505 case DSPHERETYPE:
00506 sphereStyle = ((DispCmdSphereType *)cmdptr)->type;
00507 set_sphere_style(sphereStyle);
00508 break;
00509
00510 case DMATERIALON:
00511 super_materials(1);
00512 break;
00513
00514 case DMATERIALOFF:
00515 super_materials(0);
00516 break;
00517
00518 case DCOLORINDEX:
00519 super_set_color(((DispCmdColorIndex *)cmdptr)->color);
00520 break;
00521
00522 case DTEXTSIZE:
00523 textsize = ((DispCmdTextSize *)cmdptr)->size;
00524 break;
00525
00526 case DTEXTOFFSET:
00527 textoffset_x = ((DispCmdTextOffset *)cmdptr)->x;
00528 textoffset_y = ((DispCmdTextOffset *)cmdptr)->y;
00529 break;
00530
00531 case DTEXT:
00532 {
00533 float *pos = (float *)cmdptr;
00534 text(pos, textsize, pos[3], (char *) (pos+4));
00535 }
00536 break;
00537
00538 case DBEGINREPGEOMGROUP:
00539 beginrepgeomgroup((char *)cmdptr);
00540 break;
00541
00542 case DCOMMENT:
00543 comment((char *)cmdptr);
00544 break;
00545
00546
00547 case DPICKPOINT:
00548 pick_point(((DispCmdPickPoint *)cmdptr)->postag,
00549 ((DispCmdPickPoint *)cmdptr)->tag);
00550 break;
00551
00552 case DPICKPOINT_ARRAY:
00553 {
00554 int i;
00555 DispCmdPickPointArray *cmd = ((DispCmdPickPointArray *)cmdptr);
00556 float *crds=NULL;
00557 int *indices=NULL;
00558 cmd->getpointers(crds, indices);
00559 if (cmd->allselected) {
00560 for (i=0; i<cmd->numpicks; i++) {
00561 pick_point(crds + i*3, i);
00562 }
00563 } else {
00564 for (i=0; i<cmd->numpicks; i++) {
00565 pick_point(crds + i*3, indices[i]);
00566 }
00567 }
00568 }
00569 break;
00570
00571
00572 #if 0
00573 case DSTRIPETEXON:
00574 case DSTRIPETEXOFF:
00575 #endif
00576 case DVOLUMETEXTURE:
00577 {
00578 DispCmdVolumeTexture *cmd = (DispCmdVolumeTexture *)cmdptr;
00579 float xplaneeq[4];
00580 float yplaneeq[4];
00581 float zplaneeq[4];
00582 int i;
00583
00584
00585
00586 for (i=0; i<3; i++) {
00587 xplaneeq[i] = cmd->v1[i];
00588 yplaneeq[i] = cmd->v2[i];
00589 zplaneeq[i] = cmd->v3[i];
00590 }
00591 xplaneeq[3] = cmd->v0[0];
00592 yplaneeq[3] = cmd->v0[1];
00593 zplaneeq[3] = cmd->v0[2];
00594
00595
00596 define_volume_texture(cmd->ID, cmd->xsize, cmd->ysize, cmd->zsize,
00597 xplaneeq, yplaneeq, zplaneeq,
00598 cmd->texmap);
00599 volume_texture_on(1);
00600 }
00601 break;
00602
00603 case DVOLSLICE:
00604 {
00605
00606
00607 super_materials(0);
00608 DispCmdVolSlice *cmd = (DispCmdVolSlice *)cmdptr;
00609 volume_texture_on(1);
00610 square(cmd->normal, cmd->v, cmd->v + 3, cmd->v + 6, cmd->v + 9);
00611 volume_texture_off();
00612 super_materials(1);
00613 }
00614 break;
00615
00616 case DVOLTEXON:
00617 volume_texture_on(0);
00618 break;
00619
00620 case DVOLTEXOFF:
00621 volume_texture_off();
00622 break;
00623
00624 #if 0
00625
00626 default:
00627 warningflags |= FILERENDERER_NOMISCFEATURE;
00628 break;
00629 #endif
00630 }
00631 }
00632 transMat.pop();
00633 }
00634 end_clipgroup();
00635 }
00636
00638
00639
00640
00641 void FileRenderer::super_set_color(int color_index) {
00642 if (colorIndex != color_index) {
00643 colorIndex = color_index;
00644 set_color(color_index);
00645 }
00646 }
00647
00648
00649 void FileRenderer::super_set_material(int material_index) {
00650 if (materialIndex != material_index) {
00651 materialIndex = material_index;
00652 set_material(material_index);
00653 }
00654 }
00655
00656
00657 void FileRenderer::super_materials(int on_or_off) {
00658 if (on_or_off) {
00659 materials_on = 1;
00660 activate_materials();
00661 } else {
00662 materials_on = 0;
00663 deactivate_materials();
00664 }
00665 }
00666
00667
00669
00670 void FileRenderer::super_load(float *cmdptr) {
00671 Matrix4 tmp(cmdptr);
00672 (transMat.top()).loadmatrix(tmp);
00673 load(tmp);
00674 }
00675 void FileRenderer::super_multmatrix(const float *cmdptr) {
00676 Matrix4 tmp(cmdptr);
00677 (transMat.top()).multmatrix(tmp);
00678 multmatrix(tmp);
00679 }
00680
00681 void FileRenderer::super_translate(float *cmdptr) {
00682 (transMat.top()).translate( cmdptr[0], cmdptr[1], cmdptr[2]);
00683 translate( cmdptr[0], cmdptr[1], cmdptr[2]);
00684 }
00685
00686 void FileRenderer::super_rot(float * cmdptr) {
00687 (transMat.top()).rot( cmdptr[0], 'x' + (int) (cmdptr[1]) );
00688 rot( cmdptr[0], 'x' + (int) (cmdptr[1]) );
00689 }
00690
00691 void FileRenderer::super_scale(float *cmdptr) {
00692 (transMat.top()).scale( cmdptr[0], cmdptr[1], cmdptr[2] );
00693 scale( cmdptr[0], cmdptr[1], cmdptr[2] );
00694 }
00695
00696 void FileRenderer::super_scale(float s) {
00697 transMat.top().scale(s,s,s);
00698 scale(s,s,s);
00699 }
00700
00701
00702 float FileRenderer::scale_factor(void) {
00703
00704
00705
00706 float scaleFactor;
00707
00708 float *mat = &transMat.top().mat[0];
00709 scaleFactor = (sqrtf(mat[0]*mat[0] + mat[4]*mat[4] + mat[ 8]*mat[ 8]) +
00710 sqrtf(mat[1]*mat[1] + mat[5]*mat[5] + mat[ 9]*mat[ 9]) +
00711 sqrtf(mat[2]*mat[2] + mat[6]*mat[6] + mat[10]*mat[10])) / 3.0f;
00712
00713 return scaleFactor;
00714 }
00715
00716
00717 float FileRenderer::scale_radius(float r) {
00718 float scaleFactor = scale_factor();
00719 if (r < 0.0) {
00720 msgErr << "FileRenderer: Error, Negative radius" << sendmsg;
00721 r = -r;
00722 }
00723 r = r * scaleFactor;
00724 return r;
00725 }
00726
00727
00729 void FileRenderer::set_exec_string(const char *extstr) {
00730 delete [] execCmd;
00731 execCmd = stringdup(extstr);
00732 }
00733
00734
00735
00736 void FileRenderer::cone(float *base, float *apex, float radius, float radius2, int numsides) {
00737 int h;
00738 float theta, incTheta, cosTheta, sinTheta;
00739 float axis[3], temp[3], perp[3], perp2[3];
00740 float vert0[3], vert1[3], vert2[3], edge0[3], edge1[3], face0[3], face1[3], norm0[3], norm1[3];
00741
00742 axis[0] = base[0] - apex[0];
00743 axis[1] = base[1] - apex[1];
00744 axis[2] = base[2] - apex[2];
00745 vec_normalize(axis);
00746
00747
00748 temp[0] = axis[0] - 1.0f;
00749 temp[1] = 1.0f;
00750 temp[2] = 1.0f;
00751
00752
00753 cross_prod(perp, axis, temp);
00754 vec_normalize(perp);
00755 cross_prod(perp2, axis, perp);
00756
00757
00758 incTheta = (float) VMD_TWOPI / numsides;
00759 theta = 0.0;
00760
00761
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
00773
00774 cosTheta = (float) cosf(theta);
00775 sinTheta = (float) sinf(theta);
00776 offsetL[0] = radius2 * (cosTheta*perp[0] + sinTheta*perp2[0]);
00777 offsetL[1] = radius2 * (cosTheta*perp[1] + sinTheta*perp2[1]);
00778 offsetL[2] = radius2 * (cosTheta*perp[2] + sinTheta*perp2[2]);
00779 offsetT[0] = radius * (cosTheta*perp[0] + sinTheta*perp2[0]);
00780 offsetT[1] = radius * (cosTheta*perp[1] + sinTheta*perp2[1]);
00781 offsetT[2] = radius * (cosTheta*perp[2] + sinTheta*perp2[2]);
00782
00783
00784 vec_copy(vert2, vert0);
00785 vec_copy(vert3, vert1);
00786 vec_copy(norm1, norm0);
00787
00788
00789 vec_add(vert0, base, offsetT);
00790 vec_add(vert1, apex, offsetL);
00791
00792
00793 edge0[0] = vert0[0] - vert1[0];
00794 edge0[1] = vert0[1] - vert1[1];
00795 edge0[2] = vert0[2] - vert1[2];
00796 edge1[0] = vert0[0] - vert2[0];
00797 edge1[1] = vert0[1] - vert2[1];
00798 edge1[2] = vert0[2] - vert2[2];
00799
00800
00801 cross_prod(norm0, edge1, edge0);
00802 vec_normalize(norm0);
00803
00804 if (h > 2) {
00805
00806 triangle(vert0, vert3, vert1, norm0, norm1, norm0);
00807 triangle(vert3, vert0, vert2, norm1, norm0, norm1);
00808
00809
00810 if (filled & CYLINDER_LEADINGCAP) {
00811 triangle(vert1, vert3, apex, axis, axis, axis);
00812 }
00813 if (filled & CYLINDER_TRAILINGCAP) {
00814 triangle(vert0, vert2, base, negaxis, negaxis, negaxis);
00815 }
00816 }
00817
00818 theta += incTheta;
00819 }
00820 } else {
00821
00822 for (h=0; h < numsides+3; h++) {
00823
00824
00825 cosTheta = (float) cosf(theta);
00826 sinTheta = (float) sinf(theta);
00827 vert0[0] = base[0] + radius * (cosTheta*perp[0] + sinTheta*perp2[0]);
00828 vert0[1] = base[1] + radius * (cosTheta*perp[1] + sinTheta*perp2[1]);
00829 vert0[2] = base[2] + radius * (cosTheta*perp[2] + sinTheta*perp2[2]);
00830
00831
00832 edge0[0] = vert0[0] - apex[0];
00833 edge0[1] = vert0[1] - apex[1];
00834 edge0[2] = vert0[2] - apex[2];
00835
00836 if (h > 0) {
00837
00838 cross_prod(face0, edge1, edge0);
00839 vec_normalize(face0);
00840
00841 if (h > 1) {
00842
00843 norm0[0] = (face1[0] + face0[0]) * 0.5f;
00844 norm0[1] = (face1[1] + face0[1]) * 0.5f;
00845 norm0[2] = (face1[2] + face0[2]) * 0.5f;
00846 vec_normalize(norm0);
00847
00848 if (h > 2) {
00849
00850 triangle(vert2, vert1, apex, norm1, norm0, face1);
00851 triangle(vert2, vert1, base, axis, axis, axis);
00852 }
00853
00854 }
00855
00856
00857 memcpy(norm1, norm0, 3*sizeof(float));
00858 memcpy(vert2, vert1, 3*sizeof(float));
00859 memcpy(face1, face0, 3*sizeof(float));
00860 }
00861 memcpy(vert1, vert0, 3*sizeof(float));
00862 memcpy(edge1, edge0, 3*sizeof(float));
00863
00864 theta += incTheta;
00865 }
00866 }
00867 }
00868
00869
00870
00871 void FileRenderer::cylinder(float *base, float *apex, float radius, int filled) {
00872 const int numsides = 20;
00873 int h;
00874 float theta, incTheta, cosTheta, sinTheta;
00875 float axis[3], negaxis[3], temp[3], perp[3], perp2[3], offset[3];
00876
00877 axis[0] = base[0] - apex[0];
00878 axis[1] = base[1] - apex[1];
00879 axis[2] = base[2] - apex[2];
00880 vec_normalize(axis);
00881 vec_negate(negaxis, axis);
00882
00883
00884 temp[0] = axis[0] - 1.0f;
00885 temp[1] = 1.0f;
00886 temp[2] = 1.0f;
00887
00888
00889 cross_prod(perp, axis, temp);
00890 vec_normalize(perp);
00891 cross_prod(perp2, axis, perp);
00892
00893
00894 incTheta = (float) VMD_TWOPI / numsides;
00895 theta = 0.0;
00896
00897 const int stripsz = (2*numsides) * 6;
00898 float *stripnv = new float[stripsz];
00899 memset(stripnv, 0, sizeof(float) * stripsz);
00900
00901 const int capsz = numsides+1;
00902 float *lcapnv = new float[capsz*6];
00903 memset(lcapnv, 0, sizeof(float)*capsz*6);
00904 vec_copy(&lcapnv[0], negaxis);
00905 vec_copy(&lcapnv[3], apex);
00906
00907 float *tcapnv = new float[capsz*6];
00908 memset(tcapnv, 0, sizeof(float)*capsz*6);
00909 vec_copy(&tcapnv[0], axis);
00910 vec_copy(&tcapnv[3], base);
00911
00912 for (h=0; h < numsides; h++) {
00913
00914
00915 cosTheta = (float) cosf(theta);
00916 sinTheta = (float) sinf(theta);
00917 offset[0] = radius * (cosTheta*perp[0] + sinTheta*perp2[0]);
00918 offset[1] = radius * (cosTheta*perp[1] + sinTheta*perp2[1]);
00919 offset[2] = radius * (cosTheta*perp[2] + sinTheta*perp2[2]);
00920
00921
00922 float lvert[3], tvert[3];
00923 vec_add(lvert, apex, offset);
00924 vec_add(tvert, base, offset);
00925 vec_copy(&stripnv[((2*h)*6)+9], lvert);
00926 vec_copy(&stripnv[((2*h)*6)+3], tvert);
00927 vec_copy(&lcapnv[((1+h)*6)+3], lvert);
00928 vec_copy(&tcapnv[((1+h)*6)+3], tvert);
00929
00930
00931 vec_normalize(offset);
00932 vec_copy(&stripnv[((2*h)*6) ], offset);
00933 vec_copy(&stripnv[((2*h)*6)+6], offset);
00934 vec_copy(&lcapnv[((1+h)*6)], negaxis);
00935 vec_copy(&tcapnv[((1+h)*6)], axis);
00936
00937 theta += incTheta;
00938 }
00939
00940 const int vertsperstrip = (numsides + 1)*2;
00941 int *stripfaces = new int[vertsperstrip];
00942 memset(stripfaces, 0, sizeof(float) * vertsperstrip);
00943 for (h=0; h < vertsperstrip-2; h++) {
00944 stripfaces[h] = h;
00945 }
00946 stripfaces[h ] = 0;
00947 stripfaces[h+1] = 1;
00948
00949 tristrip_singlecolor(2*numsides, &stripnv[0],
00950 1, &colorIndex, &vertsperstrip, &stripfaces[0]);
00951 delete [] stripfaces;
00952
00953
00954 if (filled & CYLINDER_LEADINGCAP) {
00955 const int vertsperfan = capsz+1;
00956 int *fanfaces = new int[vertsperfan];
00957 memset(fanfaces, 0, sizeof(float) * vertsperfan);
00958 fanfaces[0] = 0;
00959 for (h=1; h < capsz; h++) {
00960 fanfaces[h] = capsz-h;
00961 }
00962 fanfaces[h] = capsz-1;
00963 trifan_singlecolor(capsz-1, &lcapnv[0],
00964 1, &colorIndex, &vertsperfan, &fanfaces[0]);
00965 delete [] fanfaces;
00966 }
00967 if (filled & CYLINDER_TRAILINGCAP) {
00968 const int vertsperfan = capsz+1;
00969 int *fanfaces = new int[vertsperfan];
00970 memset(fanfaces, 0, sizeof(float) * vertsperfan);
00971 fanfaces[0] = 0;
00972 for (h=1; h < capsz; h++) {
00973 fanfaces[h] = h;
00974 }
00975 fanfaces[h] = 1;
00976 trifan_singlecolor(capsz-1, &tcapnv[0],
00977 1, &colorIndex, &vertsperfan, &fanfaces[0]);
00978 delete [] fanfaces;
00979 }
00980
00981 delete [] stripnv;
00982 delete [] lcapnv;
00983 delete [] tcapnv;
00984 }
00985
00986
00987
00988
00989 void FileRenderer::line(float * a, float * b) {
00990
00991 int i, j, test;
00992 float dirvec[3], unitdirvec[3];
00993 float from[3], to[3];
00994
00995 if (lineStyle == ::SOLIDLINE) {
00996 cylinder(a, b, lineWidth * 0.002f, 0);
00997 } else if (lineStyle == ::DASHEDLINE) {
00998 vec_sub(dirvec, b, a);
00999 vec_copy(unitdirvec, dirvec);
01000 vec_normalize(unitdirvec);
01001 test = 1;
01002 i = 0;
01003 while (test == 1) {
01004 for (j=0; j<3; j++) {
01005 from[j] = (float) (a[j] + (2*i )* 0.05 * unitdirvec[j]);
01006 to[j] = (float) (a[j] + (2*i + 1)* 0.05 * unitdirvec[j]);
01007 }
01008 if (fabsf(a[0] - to[0]) >= fabsf(dirvec[0])) {
01009 vec_copy(to, b);
01010 test = 0;
01011 }
01012 cylinder(from, to, lineWidth * 0.002f, 0);
01013 i++;
01014 }
01015 }
01016 }
01017
01018
01019 void FileRenderer::line_array(int num, float thickness, float *points) {
01020 float *v = points;
01021 for (int i=0; i<num; i++) {
01022
01023 if (memcmp(v, v+3, 3*sizeof(float))) {
01024 line(v, v+3);
01025 }
01026 v += 6;
01027 }
01028 }
01029
01030
01031 void FileRenderer::polyline_array(int num, float thickness, float *points) {
01032 float *v = points;
01033 for (int i=0; i<num-1; i++) {
01034
01035 if (memcmp(v, v+3, 3*sizeof(float))) {
01036 line(v, v+3);
01037 }
01038 v += 3;
01039 }
01040 }
01041
01042
01043
01044 void FileRenderer::sphere(float * xyzr) {
01045 float c[3], r;
01046 int pi, ni;
01047 int i;
01048 int sph_iter = -1;
01049 int sph_desired_iter = 0;
01050
01051
01052 vec_copy(c, xyzr);
01053 r = xyzr[3];
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063 const int sph_iter_table[] = {
01064 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3,
01065 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4 };
01066
01067 if (sphereResolution < 0)
01068 return;
01069 else if (sphereResolution < 32)
01070 sph_desired_iter = sph_iter_table[sphereResolution];
01071 else
01072 sph_desired_iter = (int) (0.8f * sqrtf((float) sphereResolution));
01073
01074
01075
01076
01077 if (!sph_verts || !sph_nverts || sph_iter != sph_desired_iter) {
01078 float a[3], b[3], c[3];
01079 float *newverts;
01080 float *oldverts;
01081 int nverts, ntris;
01082 int level;
01083
01084
01085 if (sph_verts && sph_nverts) free(sph_verts);
01086
01087 newverts = (float *) malloc(sizeof(float) * 36);
01088 nverts = 12;
01089 ntris = 4;
01090
01091
01092
01093
01094 newverts[0] = -1; newverts[1] = 0; newverts[2] = 0;
01095 newverts[3] = 0; newverts[4] = 1; newverts[5] = 0;
01096 newverts[6] = 0; newverts[7] = 0; newverts[8] = 1;
01097
01098
01099 newverts[9] = 0; newverts[10] = 0; newverts[11] = 1;
01100 newverts[12] = 0; newverts[13] = 1; newverts[14] = 0;
01101 newverts[15] = 1; newverts[16] = 0; newverts[17] = 0;
01102
01103
01104 newverts[18] = 0; newverts[19] = 0; newverts[20] = 1;
01105 newverts[21] = 1; newverts[22] = 0; newverts[23] = 0;
01106 newverts[24] = 0; newverts[25] = -1; newverts[26] = 0;
01107
01108
01109 newverts[27] = 0; newverts[28] = 0; newverts[29] = 1;
01110 newverts[30] = 0; newverts[31] = -1; newverts[32] = 0;
01111 newverts[33] = -1; newverts[34] = 0; newverts[35] = 0;
01112
01113 for (level = 1; level < sph_desired_iter; level++) {
01114 oldverts = newverts;
01115
01116
01117
01118 newverts = (float *) malloc(sizeof(float) * 12 * nverts);
01119 if (!newverts) {
01120
01121 sph_iter = -1;
01122 sph_nverts = 0;
01123 sph_verts = NULL;
01124 free(oldverts);
01125 msgErr << "FileRenderer::sphere(): Out of memory. Some "
01126 << "objects were not drawn." << sendmsg;
01127 return;
01128 }
01129
01130 pi = 0;
01131 ni = 0;
01132 for (i = 0; i < ntris; i++) {
01133
01134 a[0] = (oldverts[pi ] + oldverts[pi + 6]) / 2;
01135 a[1] = (oldverts[pi + 1] + oldverts[pi + 7]) / 2;
01136 a[2] = (oldverts[pi + 2] + oldverts[pi + 8]) / 2;
01137 vec_normalize(a);
01138 b[0] = (oldverts[pi ] + oldverts[pi + 3]) / 2;
01139 b[1] = (oldverts[pi + 1] + oldverts[pi + 4]) / 2;
01140 b[2] = (oldverts[pi + 2] + oldverts[pi + 5]) / 2;
01141 vec_normalize(b);
01142 c[0] = (oldverts[pi + 3] + oldverts[pi + 6]) / 2;
01143 c[1] = (oldverts[pi + 4] + oldverts[pi + 7]) / 2;
01144 c[2] = (oldverts[pi + 5] + oldverts[pi + 8]) / 2;
01145 vec_normalize(c);
01146
01147
01148 memcpy(&newverts[ni ], &oldverts[pi], sizeof(float) * 3);
01149 memcpy(&newverts[ni + 3 ], b, sizeof(float) * 3);
01150 memcpy(&newverts[ni + 6 ], a, sizeof(float) * 3);
01151
01152 memcpy(&newverts[ni + 9 ], b, sizeof(float) * 3);
01153 memcpy(&newverts[ni + 12], &oldverts[pi + 3], sizeof(float) * 3);
01154 memcpy(&newverts[ni + 15], c, sizeof(float) * 3);
01155
01156 memcpy(&newverts[ni + 18], a, sizeof(float) * 3);
01157 memcpy(&newverts[ni + 21], b, sizeof(float) * 3);
01158 memcpy(&newverts[ni + 24], c, sizeof(float) * 3);
01159
01160 memcpy(&newverts[ni + 27], a, sizeof(float) * 3);
01161 memcpy(&newverts[ni + 30], c, sizeof(float) * 3);
01162 memcpy(&newverts[ni + 33], &oldverts[pi + 6], sizeof(float) * 3);
01163
01164 pi += 9;
01165 ni += 36;
01166 }
01167
01168 free(oldverts);
01169 nverts *= 4;
01170 ntris *= 4;
01171 }
01172
01173 sph_iter = sph_desired_iter;
01174 sph_nverts = nverts;
01175 sph_verts = newverts;
01176 }
01177
01178
01179
01180
01181 pi = 0;
01182 for (i = 0; i < sph_nverts / 3; i++) {
01183 float v0[3], v1[3], v2[3];
01184 float n0[3], n1[3], n2[3];
01185
01186
01187 v0[0] = r * sph_verts[pi ] + c[0];
01188 v0[1] = r * sph_verts[pi + 1] + c[1];
01189 v0[2] = r * sph_verts[pi + 2] + c[2];
01190 v1[0] = r * sph_verts[pi + 3] + c[0];
01191 v1[1] = r * sph_verts[pi + 4] + c[1];
01192 v1[2] = r * sph_verts[pi + 5] + c[2];
01193 v2[0] = r * sph_verts[pi + 6] + c[0];
01194 v2[1] = r * sph_verts[pi + 7] + c[1];
01195 v2[2] = r * sph_verts[pi + 8] + c[2];
01196
01197
01198 vec_copy(n0, &sph_verts[pi ]);
01199 vec_copy(n1, &sph_verts[pi + 3]);
01200 vec_copy(n2, &sph_verts[pi + 6]);
01201
01202
01203 triangle(v0, v2, v1, n0, n2, n1);
01204
01205
01206 v0[2] = (-r * sph_verts[pi + 2]) + c[2];
01207 v1[2] = (-r * sph_verts[pi + 5]) + c[2];
01208 v2[2] = (-r * sph_verts[pi + 8]) + c[2];
01209
01210
01211 n0[2] = -n0[2];
01212 n1[2] = -n1[2];
01213 n2[2] = -n2[2];
01214
01215
01216 triangle(v0, v1, v2, n0, n1, n2);
01217
01218 pi += 9;
01219 }
01220 }
01221
01222
01223
01224
01225
01226 void FileRenderer::sphere_array(int spnum, int spres,
01227 float *centers, float *radii, float *colors) {
01228 int i, ind;
01229 set_sphere_res(spres);
01230 ind = 0;
01231 for (i=0; i<spnum; i++) {
01232 float xyzr[4];
01233 xyzr[0]=centers[ind ];
01234 xyzr[1]=centers[ind + 1];
01235 xyzr[2]=centers[ind + 2];
01236 xyzr[3]=radii[i];
01237
01238 super_set_color(nearest_index(colors[ind], colors[ind+1], colors[ind+2]));
01239 sphere(xyzr);
01240 ind += 3;
01241 }
01242 }
01243
01244
01245
01246
01247 void FileRenderer::point_array(int num, float size, float *xyz, float *colors) {
01248 int i, ind;
01249
01250 pointSize = (int) size;
01251
01252
01253 for (ind=0,i=0; i<num; i++) {
01254 super_set_color(nearest_index(colors[ind], colors[ind+1], colors[ind+2]));
01255 point(&xyz[ind]);
01256 ind += 3;
01257 }
01258
01259 pointSize = 1;
01260 }
01261
01262
01263
01264
01265 void FileRenderer::point_array_lit(int num, float size,
01266 float *xyz, float *norms, float *colors) {
01267
01268
01269 point_array(num, size, xyz, colors);
01270 }
01271
01272
01273
01274
01275 void FileRenderer::start_clipgroup() {
01276 int i;
01277
01278 for (i=0; i<VMD_MAX_CLIP_PLANE; i++) {
01279 if (clip_mode[i]) {
01280 warningflags |= FILERENDERER_NOCLIP;
01281 break;
01282 }
01283 }
01284 }
01285
01286
01287 void FileRenderer::text(float *pos, float size, float thickness, const char *str) {
01288 #if 1
01289 warningflags |= FILERENDERER_NOTEXT;
01290 #else
01291 hersheyhandle hh;
01292 float lm, rm, x, y, ox, oy;
01293 int draw, odraw;
01294
01295 Matrix4 m;
01296 transMat.push(m);
01297
01298 while (*str != '\0') {
01299 hersheyDrawInitLetter(&hh, *str, &lm, &rm);
01300 (transMat.top()).translate(-lm, 0, 0);
01301 ox=0;
01302 oy=0;
01303 odraw=0;
01304 while (!hersheyDrawNextLine(&hh, &draw, &x, &y)) {
01305 if (draw && odraw) {
01306 float a[3], b[3];
01307 a[0] = ox;
01308 a[1] = oy;
01309 a[2] = 0;
01310 b[0] = x;
01311 b[1] = y;
01312 b[2] = 0;
01313
01314
01315 line(a, b);
01316 }
01317
01318 ox=x;
01319 oy=y;
01320 odraw=draw;
01321 }
01322 (transMat.top()).translate(rm, 0, 0);
01323
01324 str++;
01325 }
01326
01327 transMat.pop();
01328 #endif
01329 }
01330
01331