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