00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <math.h>
00026 #include "DisplayDevice.h"
00027 #include "Inform.h"
00028 #include "DispCmds.h"
00029 #include "utilities.h"
00030 #include "Mouse.h"
00031 #include "VMDDisplayList.h"
00032 #include "Scene.h"
00033
00034
00035 static const char *cacheNameStr[1] = { "Off" };
00036 static const char *renderNameStr[1] = { "Normal" };
00037 static const char *stereoNameStr[1] = { "Off" };
00038
00039 const char *DisplayDevice::projNames[NUM_PROJECTIONS] = {
00040 "Perspective", "Orthographic"
00041 };
00042
00043 const char *DisplayDevice::cueModeNames[NUM_CUE_MODES] = {
00044 "Linear", "Exp", "Exp2"
00045 };
00046
00048 DisplayDevice::DisplayDevice (const char *nm) : transMat(16) {
00049 vmdapp = NULL;
00050 name = stringdup(nm);
00051 num_display_processes = 1;
00052 renderer_process = 1;
00053 _needRedraw = 0;
00054 backgroundmode = 0;
00055
00056
00057 lineStyle = ::SOLIDLINE;
00058 lineWidth = 1;
00059 sphereRes = 3;
00060 cylinderRes = 6;
00061 sphereMode = ::SOLIDSPHERE;
00062
00063
00064 aaAvailable = cueingAvailable = TRUE;
00065 aaPrevious = aaEnabled = cueingEnabled = cullingEnabled = FALSE;
00066 xOrig = yOrig = xSize = ySize = 0;
00067 screenX = screenY = 0;
00068
00069
00070
00071
00072 nearClip = 0.5f;
00073 farClip = 10.0f;
00074 eyePos[0] = eyePos[1] = 0.0f; eyePos[2] = 2.0f;
00075 set_screen_pos(2.0f * eyePos[2], 0.0f, 4.0f/3.0f);
00076
00077
00078
00079 cueMode = CUE_EXP2;
00080 cueDensity = 0.32f;
00081 cueStart = 0.5f;
00082 cueEnd = 10.0f;
00083
00084
00085 shadowEnabled = 0;
00086
00087
00088 aoEnabled = 0;
00089 aoAmbient = 0.8f;
00090 aoDirect = 0.3f;
00091
00092
00093 dofEnabled = 0;
00094 dofFNumber = 64;
00095 dofFocalDist = 0.7f;
00096
00097
00098
00099
00100
00101
00102 inStereo = 0;
00103 stereoSwap = 0;
00104 stereoModes = 1;
00105 stereoNames = stereoNameStr;
00106
00107
00108 cacheMode = 0;
00109 cacheModes = 1;
00110 cacheNames = cacheNameStr;
00111
00112
00113 renderMode = 0;
00114 renderModes = 1;
00115 renderNames = renderNameStr;
00116
00117
00118 eyeSep = 0.065f;
00119 eyeDist = eyePos[2];
00120
00121 float lookatorigin[3];
00122 vec_scale(&lookatorigin[0], -1, &eyePos[0]);
00123 set_eye_dir(&lookatorigin[0]);
00124 upDir[0] = upDir[2] = 0.0; upDir[1] = 1.0;
00125 calc_eyedir();
00126 my_projection = PERSPECTIVE;
00127
00128
00129 Matrix4 temp_ident;
00130 transMat.push(temp_ident);
00131
00132 mouseX = mouseY = 0;
00133 }
00134
00135
00136 DisplayDevice::~DisplayDevice(void) {
00137 set_stereo_mode(0);
00138 delete [] name;
00139 }
00140
00141 int DisplayDevice::set_eye_defaults() {
00142 float defaultDir[3];
00143 float defaultPos[3] = {0, 0, 2};
00144 float defaultUp[3] = {0, 1, 0};
00145
00146 vec_scale(&defaultDir[0], -1, &eyePos[0]);
00147 set_eye_dir(&defaultDir[0]);
00148
00149 set_eye_pos(&defaultPos[0]);
00150 set_eye_dir(&defaultDir[0]);
00151 set_eye_up(&defaultUp[0]);
00152
00153 return TRUE;
00154 }
00155
00157
00158
00159
00160 void DisplayDevice::calc_frustum(void) {
00161 float d;
00162 float halfvsize = 0.5f * vSize;
00163 float halfhsize = Aspect * halfvsize;
00164
00165
00166
00167 if(eyePos[2] - zDist != 0.0f) {
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 d = nearClip / (eyePos[2] - zDist);
00179
00180 cpRight = d * halfhsize;
00181 cpLeft = -cpRight;
00182 cpUp = d * halfvsize;
00183 cpDown = -cpUp;
00184 }
00185 }
00186
00187
00188
00189
00190 void DisplayDevice::calc_eyedir(void) {
00191 float *L = eyeDir;
00192 float *U = upDir;
00193 float m, A = 0.5f * eyeSep;
00194 eyeSepDir[0] = L[1] * U[2] - L[2] * U[1];
00195 eyeSepDir[1] = L[2] * U[0] - L[0] * U[2];
00196 eyeSepDir[2] = L[0] * U[1] - L[1] * U[0];
00197 m = sqrtf(eyeSepDir[0] * eyeSepDir[0] + eyeSepDir[1] * eyeSepDir[1] +
00198 eyeSepDir[2] * eyeSepDir[2]);
00199 if(m > 0.0)
00200 A /= m;
00201 else
00202 A = 0.0;
00203 eyeSepDir[0] *= A;
00204 eyeSepDir[1] *= A;
00205 eyeSepDir[2] *= A;
00206 }
00207
00209
00210
00211 DisplayDevice& DisplayDevice::operator=( DisplayDevice &display) {
00212 int i;
00213
00214 xOrig = display.xOrig;
00215 yOrig = display.yOrig;
00216 xSize = display.xSize;
00217 ySize = display.ySize;
00218
00219
00220 transMat.clear();
00221 transMat.push( (display.transMat).top() );
00222
00223 for (i=0; i<3; i++) {
00224 eyePos[i] = display.eyePos[i];
00225 eyeDir[i] = display.eyeDir[i];
00226 upDir[i] = display.upDir[i];
00227 eyeSepDir[i] = display.eyeSepDir[i];
00228 }
00229
00230 whichEye = display.whichEye;
00231 nearClip = display.nearClip;
00232 farClip = display.farClip;
00233 vSize = display.vSize;
00234 zDist = display.zDist;
00235 Aspect = display.Aspect;
00236 cpUp = display.cpUp;
00237 cpDown = display.cpDown;
00238 cpLeft = display.cpLeft;
00239 cpRight = display.cpRight;
00240 inStereo = display.inStereo;
00241 eyeSep = display.eyeSep;
00242 eyeDist = display.eyeDist;
00243 lineStyle = display.lineStyle;
00244 lineWidth = display.lineWidth;
00245 my_projection = display.my_projection;
00246 backgroundmode = display.backgroundmode;
00247 cueingEnabled = display.cueingEnabled;
00248 cueMode = display.cueMode;
00249 cueDensity = display.cueDensity;
00250 cueStart = display.cueStart;
00251 cueEnd = display.cueEnd;
00252 shadowEnabled = display.shadowEnabled;
00253 aoEnabled = display.aoEnabled;
00254 aoAmbient = display.aoAmbient;
00255 aoDirect = display.aoDirect;
00256 dofEnabled = display.dofEnabled;
00257 dofFNumber = display.dofFNumber;
00258 dofFocalDist = display.dofFocalDist;
00259 return *this;
00260 }
00261
00263
00264 void DisplayDevice::do_resize_window(int w, int h) {
00265 xSize = w;
00266 ySize = h;
00267 set_screen_pos((float)xSize / (float)ySize);
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277 void DisplayDevice::queue_events(void) { return; }
00278
00279
00280
00281 int DisplayDevice::read_event(long &, long &) { return FALSE; }
00282
00283
00284
00285
00286
00287
00288 int DisplayDevice::x(void) { return mouseX; }
00289
00290
00291 int DisplayDevice::y(void) { return mouseY; }
00292
00293
00294 int DisplayDevice::shift_state(void) {
00295 return 0;
00296 }
00297
00298
00299
00300 void DisplayDevice::set_cursor(int) { }
00301
00302
00303 void DisplayDevice::aa_on(void) { }
00304 void DisplayDevice::aa_off(void) { }
00305 void DisplayDevice::culling_on(void) { }
00306 void DisplayDevice::culling_off(void) { }
00307
00308
00309 void DisplayDevice::abs_screen_loc_3D(float *wloc, float *sloc) {
00310
00311 for(int i=0; i < 3; i++)
00312 sloc[i] = wloc[i];
00313 }
00314
00315 void DisplayDevice::abs_screen_loc_2D(float *wloc, float *sloc) {
00316
00317 for(int i=0; i < 2; i++)
00318 sloc[i] = wloc[i];
00319 }
00320
00321
00322 void DisplayDevice::set_stereo_mode(int sm) {
00323 if(sm != 0) {
00324 msgErr << "DisplayDevice: Illegal stereo mode " << sm << " specified."
00325 << sendmsg;
00326 } else {
00327 inStereo = sm;
00328 }
00329 }
00330
00331
00332 void DisplayDevice::set_cache_mode(int sm) {
00333 if(sm != 0) {
00334 msgErr << "DisplayDevice: Illegal caching mode " << sm << " specified."
00335 << sendmsg;
00336 } else {
00337 cacheMode = sm;
00338 }
00339 }
00340
00341
00342 void DisplayDevice::set_render_mode(int sm) {
00343 if(sm != 0) {
00344 msgErr << "DisplayDevice: Illegal rendering mode " << sm << " specified."
00345 << sendmsg;
00346 } else {
00347 renderMode = sm;
00348 }
00349 }
00350
00351
00352 void DisplayDevice::loadmatrix(const Matrix4 &m) {
00353 (transMat.top()).loadmatrix(m);
00354 }
00355
00356
00357 void DisplayDevice::multmatrix(const Matrix4 &m) {
00358 (transMat.top()).multmatrix(m);
00359 }
00360
00361
00362
00363
00364
00365 int DisplayDevice::prepare3D(int) { return 1;}
00366 void DisplayDevice::clear(void) { }
00367 void DisplayDevice::left(void) {
00368 whichEye = LEFTEYE;
00369 }
00370 void DisplayDevice::right(void) {
00371 whichEye = RIGHTEYE;
00372 }
00373 void DisplayDevice::normal(void) {
00374 whichEye = NOSTEREO;
00375 }
00376 void DisplayDevice::update(int) { }
00377 void DisplayDevice::reshape(void) { }
00378
00379
00380 unsigned char * DisplayDevice::readpixels_rgb3u(int &x, int &y) {
00381 x = 0;
00382 y = 0;
00383 return NULL;
00384 }
00385
00386
00387 unsigned char * DisplayDevice::readpixels_rgba4u(int &x, int &y) {
00388 x = 0;
00389 y = 0;
00390 return NULL;
00391 }
00392
00393
00394 void DisplayDevice::find_pbc_images(const VMDDisplayList *cmdList,
00395 ResizeArray<Matrix4> &pbcImages) {
00396 if (cmdList->pbc == PBC_NONE) {
00397 pbcImages.append(Matrix4());
00398 return;
00399 }
00400 ResizeArray<int> pbcCells;
00401 find_pbc_cells(cmdList, pbcCells);
00402 for (int i=0; i<pbcCells.num(); i += 3) {
00403 int nx=pbcCells[i ];
00404 int ny=pbcCells[i+1];
00405 int nz=pbcCells[i+2];
00406 Matrix4 mat;
00407 for (int i1=1; i1<=nx; i1++) mat.multmatrix(cmdList->transX);
00408 for (int i2=-1; i2>=nx; i2--) mat.multmatrix(cmdList->transXinv);
00409 for (int i3=1; i3<=ny; i3++) mat.multmatrix(cmdList->transY);
00410 for (int i4=-1; i4>=ny; i4--) mat.multmatrix(cmdList->transYinv);
00411 for (int i5=1; i5<=nz; i5++) mat.multmatrix(cmdList->transZ);
00412 for (int i6=-1; i6>=nz; i6--) mat.multmatrix(cmdList->transZinv);
00413 pbcImages.append(mat);
00414 }
00415 }
00416
00417 void DisplayDevice::find_pbc_cells(const VMDDisplayList *cmdList,
00418 ResizeArray<int> &pbcCells) {
00419 int pbc = cmdList->pbc;
00420 if (pbc == PBC_NONE) {
00421 pbcCells.append3(0, 0, 0);
00422 } else {
00423 int npbc = cmdList->npbc;
00424 int nx = pbc & PBC_X ? npbc : 0;
00425 int ny = pbc & PBC_Y ? npbc : 0;
00426 int nz = pbc & PBC_Z ? npbc : 0;
00427 int nox = pbc & PBC_OPX ? -npbc : 0;
00428 int noy = pbc & PBC_OPY ? -npbc : 0;
00429 int noz = pbc & PBC_OPZ ? -npbc : 0;
00430 int i, j, k;
00431 for (i=nox; i<=nx; i++) {
00432 for (j=noy; j<=ny; j++) {
00433 for (k=noz; k<=nz; k++) {
00434 if (!(pbc & PBC_NOSELF && !i && !j && !k)) {
00435 pbcCells.append3(i, j, k);
00436 }
00437 }
00438 }
00439 }
00440 }
00441 }
00442
00443
00444 void DisplayDevice::find_instance_images(const VMDDisplayList *cmdList,
00445 ResizeArray<Matrix4> &instImages) {
00446 int ninstances = cmdList->instances.num();
00447
00448 #if 0
00449 printf("DisplayDevice::find_instance_images(): cnt: %d flags: %0x\n",
00450 ninstances, cmdList->instanceset);
00451 #endif
00452
00453
00454
00455
00456 if (cmdList->instanceset == INSTANCE_NONE || ninstances == 0) {
00457 instImages.append(Matrix4());
00458 return;
00459 }
00460
00461
00462
00463
00464 if ((cmdList->instanceset & INSTANCE_NOSELF) != INSTANCE_NOSELF) {
00465 #if 0
00466 printf("appending self instance\n");
00467 #endif
00468 instImages.append(Matrix4());
00469 }
00470 for (int i=0; i<ninstances; i++) {
00471 instImages.append(cmdList->instances[i]);
00472 }
00473
00474
00475
00476 if (instImages.num() == 0) {
00477 #if 1
00478 printf("DisplayDevice warning, no instance mats! adding one...\n");
00479 #endif
00480 instImages.append(Matrix4());
00481 }
00482 }
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509 #define DTOEYE(x,y,z) ( (x-eyePos[0])*(x-eyePos[0]) + \
00510 (y-eyePos[1])*(y-eyePos[1]) + \
00511 (z-eyePos[2])*(z-eyePos[2]) )
00512 #define DTOPOINT(x,y,z) ( (x-pos[0])*(x-pos[0]) + \
00513 (y-pos[1])*(y-pos[1]) + \
00514 (z-pos[2])*(z-pos[2]) )
00515
00516 int DisplayDevice::pick(int dim, const float *pos, const VMDDisplayList *cmdList,
00517 float &eyedist, int *unitcell, float window_size) {
00518 char *cmdptr = NULL;
00519 int tok;
00520 float newEyeDist, currEyeDist = eyedist;
00521 int tag = (-1), inRegion, currTag;
00522 float minX=0.0f, minY=0.0f, maxX=0.0f, maxY=0.0f;
00523 float fminX=0.0f, fminY=0.0f, fminZ=0.0f, fmaxX=0.0f, fmaxY=0.0f, fmaxZ=0.0f;
00524 float wpntpos[3], pntpos[3], cpos[3];
00525
00526 if(!cmdList)
00527 return (-1);
00528
00529
00530 if (dim == 2) {
00531 fminX = pos[0] - window_size;
00532 fmaxX = pos[0] + window_size;
00533 fminY = pos[1] - window_size;
00534 fmaxY = pos[1] + window_size;
00535 abs_screen_pos(fminX, fminY);
00536 abs_screen_pos(fmaxX, fmaxY);
00537 #if defined(_MSC_VER)
00538
00539
00540 #if 1
00541 minX = float((int) ((float) (fminX + (fminX >= 0.0f ? 0.5f : -0.5f))));
00542 maxX = float((int) ((float) (fmaxX + (fmaxX >= 0.0f ? 0.5f : -0.5f))));
00543 minY = float((int) ((float) (fminY + (fminY >= 0.0f ? 0.5f : -0.5f))));
00544 maxY = float((int) ((float) (fmaxY + (fmaxY >= 0.0f ? 0.5f : -0.5f))));
00545 #else
00546 minX = truncf(fminX + (fminX >= 0.0f ? 0.5f : -0.5f));
00547 maxX = truncf(fmaxX + (fmaxX >= 0.0f ? 0.5f : -0.5f));
00548 minY = truncf(fminY + (fminY >= 0.0f ? 0.5f : -0.5f));
00549 maxY = truncf(fmaxY + (fmaxY >= 0.0f ? 0.5f : -0.5f));
00550
00551
00552
00553
00554 #endif
00555 #else
00556 minX = round(fminX);
00557 maxX = round(fmaxX);
00558 minY = round(fminY);
00559 maxY = round(fmaxY);
00560 #endif
00561
00562 } else {
00563 fminX = pos[0] - window_size;
00564 fmaxX = pos[0] + window_size;
00565 fminY = pos[1] - window_size;
00566 fmaxY = pos[1] + window_size;
00567 fminZ = pos[2] - window_size;
00568 fmaxZ = pos[2] + window_size;
00569 }
00570
00571
00572 transMat.dup();
00573 (transMat.top()).multmatrix(cmdList->mat);
00574
00575
00576 ResizeArray<Matrix4> pbcImages;
00577 find_pbc_images(cmdList, pbcImages);
00578
00579
00580 ResizeArray<int> pbcCells;
00581 find_pbc_cells(cmdList, pbcCells);
00582
00583
00584 ResizeArray<Matrix4> instanceImages;
00585 find_instance_images(cmdList, instanceImages);
00586 int ninstances = instanceImages.num();
00587
00588 for (int pbcimage=0; pbcimage<pbcImages.num(); pbcimage++) {
00589 transMat.dup();
00590 (transMat.top()).multmatrix(pbcImages[pbcimage]);
00591
00592 for (int instanceimage = 0; instanceimage < ninstances; instanceimage++) {
00593 transMat.dup();
00594 (transMat.top()).multmatrix(instanceImages[instanceimage]);
00595
00596
00597
00598 VMDDisplayList::VMDLinkIter cmditer;
00599 cmdList->first(&cmditer);
00600 while((tok = cmdList->next(&cmditer, cmdptr)) != DLASTCOMMAND) {
00601 switch (tok) {
00602 case DPICKPOINT_ARRAY:
00603
00604 DispCmdPickPointArray *cmd = (DispCmdPickPointArray *)cmdptr;
00605 float *pickpos=NULL;
00606 float *crds=NULL;
00607 int *indices=NULL;
00608 cmd->getpointers(crds, indices);
00609
00610 int i;
00611 for (i=0; i<cmd->numpicks; i++) {
00612 pickpos = crds + i*3L;
00613 if (cmd->allselected) {
00614 currTag = i + cmd->firstindex;
00615 } else {
00616 currTag = indices[i];
00617 }
00618 vec_copy(wpntpos, pickpos);
00619 (transMat.top()).multpoint3d(pickpos, pntpos);
00620
00621
00622 if (dim == 2) {
00623
00624 abs_screen_loc_3D(pntpos, cpos);
00625
00626
00627
00628 inRegion = (cpos[0] >= minX && cpos[0] <= maxX &&
00629 cpos[1] >= minY && cpos[1] <= maxY &&
00630 cpos[2] >= 0.0 && cpos[2] <= 1.0);
00631 } else {
00632
00633
00634 inRegion = (pntpos[0] >= fminX && pntpos[0] <= fmaxX &&
00635 pntpos[1] >= fminY && pntpos[1] <= fmaxY &&
00636 pntpos[2] >= fminZ && pntpos[2] <= fmaxZ);
00637 }
00638
00639
00640 if (inRegion) {
00641
00642
00643
00644 int cp;
00645 for (cp=0; cp < VMD_MAX_CLIP_PLANE; cp++) {
00646
00647
00648 if (cmdList->clipplanes[cp].mode) {
00649 float cpdist[3];
00650 vec_sub(cpdist, wpntpos, cmdList->clipplanes[cp].center);
00651 inRegion &= (dot_prod(cpdist,
00652 cmdList->clipplanes[cp].normal) > 0.0f);
00653 }
00654 }
00655 }
00656
00657
00658 if (inRegion) {
00659
00660 if (dim==2)
00661 newEyeDist = DTOEYE(pntpos[0], pntpos[1], pntpos[2]);
00662 else
00663 newEyeDist = DTOPOINT(pntpos[0],pntpos[1],pntpos[2]);
00664
00665 if (currEyeDist < 0.0 || newEyeDist < currEyeDist) {
00666 currEyeDist = newEyeDist;
00667 tag = currTag;
00668 if (unitcell) {
00669 unitcell[0] = pbcCells[3*pbcimage ];
00670 unitcell[1] = pbcCells[3*pbcimage+1];
00671 unitcell[2] = pbcCells[3*pbcimage+2];
00672 }
00673 }
00674 }
00675 }
00676 break;
00677 }
00678 }
00679
00680
00681 transMat.pop();
00682 }
00683
00684
00685 transMat.pop();
00686 }
00687
00688
00689 transMat.pop();
00690
00691
00692 eyedist = currEyeDist;
00693 return tag;
00694 }
00695
00696
00697