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