void PSDisplayDevice::render(const VMDDisplayList *display_list) { DepthSortObject depth_obj; char *cmd_ptr; int draw; int tok; int nc; float a[3], b[3], c[3], d[3]; float cent[3]; float r; Matrix4 ident; float textsize=1.0f; // default text size // first we want to clear the transformation matrix stack while (transMat.num()) transMat.pop(); // push on the identity matrix transMat.push(ident); // load the display list's transformation matrix super_multmatrix(display_list->mat.mat); // Now we need to calculate the normalized position of the light // so we can compute angles of surfaces to that light for shading norm_light[0] = lightState[0].pos[0]; norm_light[1] = lightState[0].pos[1]; norm_light[2] = lightState[0].pos[2]; if (norm_light[0] || norm_light[1] || norm_light[2]) vec_normalize(norm_light); // Computer periodic images ResizeArray<Matrix4> pbcImages; find_pbc_images(display_list, pbcImages); int nimages = pbcImages.num(); for (int pbcimage = 0; pbcimage < nimages; pbcimage++) { transMat.dup(); super_multmatrix(pbcImages[pbcimage].mat); // Loop through the display list and add each object to our // depth-sort list for final rendering. VMDDisplayList::VMDLinkIter cmditer; display_list->first(&cmditer); while ((tok = display_list->next(&cmditer, cmd_ptr)) != DLASTCOMMAND) { draw = 0; nc = -1; switch (tok) { case DPOINT: // allocate memory depth_obj.points = (float *) malloc(sizeof(float) * 2); if (!depth_obj.points) { // memory error if (!memerror) { memerror = 1; msgErr << "PSDisplayDevice: Out of memory. Some " << "objects were not drawn." << sendmsg; } break; } // copy data depth_obj.npoints = 1; depth_obj.color = colorIndex; (transMat.top()).multpoint3d(((DispCmdPoint *) cmd_ptr)->pos, a); memcpy(depth_obj.points, a, sizeof(float) * 2); // compute the distance to the eye depth_obj.dist = compute_dist(a); // valid object to depth sort draw = 1; break; case DSPHERE: { (transMat.top()).multpoint3d(((DispCmdSphere *) cmd_ptr)->pos_r, c); r = scale_radius(((DispCmdSphere *) cmd_ptr)->pos_r[3]); sphere_approx(c, r); break; } case DSPHEREARRAY: { DispCmdSphereArray *sa = (DispCmdSphereArray *) cmd_ptr; int cIndex, rIndex; // cIndex: index of colors & centers // rIndex: index of radii. float * centers; float * radii; float * colors; sa->getpointers(centers, radii, colors); set_sphere_res(sa->sphereres); for (cIndex = 0, rIndex=0; rIndex < sa->numspheres; cIndex+=3, rIndex++) { colorIndex = nearest_index(colors[cIndex], colors[cIndex+1], colors[cIndex+2]); (transMat.top()).multpoint3d(¢ers[cIndex] , c); r = scale_radius(radii[rIndex]); sphere_approx(c, r); } break; } case DLINE: // check for zero-length line (degenerate) if (!memcmp(((DispCmdLine *) cmd_ptr)->pos1, ((DispCmdLine *) cmd_ptr)->pos2, sizeof(float) * 3)) { // degenerate line break; } // allocate memory depth_obj.points = (float *) malloc(sizeof(float) * 4); if (!depth_obj.points) { // memory error if (!memerror) { memerror = 1; msgErr << "PSDisplayDevice: Out of memory. Some " << "objects were not drawn." << sendmsg; } break; } // copy data depth_obj.npoints = 2; depth_obj.color = colorIndex; (transMat.top()).multpoint3d(((DispCmdLine *) cmd_ptr)->pos1, a); (transMat.top()).multpoint3d(((DispCmdLine *) cmd_ptr)->pos2, b); memcpy(depth_obj.points, a, sizeof(float) * 2); memcpy(&depth_obj.points[2], b, sizeof(float) * 2); // compute the centerpoint of the object cent[0] = (a[0] + b[0]) / 2; cent[1] = (a[1] + b[1]) / 2; cent[2] = (a[2] + b[2]) / 2; // compute the distance to the eye depth_obj.dist = compute_dist(cent); // valid object to depth sort draw = 1; break; case DLINEARRAY: { // XXX much replicated code from DLINE float *v = (float *)cmd_ptr; int nlines = (int)v[0]; v++; for (int i=0; i<nlines; i++) { // check for degenerate line if (!memcmp(v,v+3,3*sizeof(float))) break; // allocate memory depth_obj.points = (float *) malloc(sizeof(float) * 4); if (!depth_obj.points) { // memory error if (!memerror) { memerror = 1; msgErr << "PSDisplayDevice: Out of memory. Some " << "objects were not drawn." << sendmsg; } break; } // copy data depth_obj.npoints = 2; depth_obj.color = colorIndex; (transMat.top()).multpoint3d(v, a); (transMat.top()).multpoint3d(v+3, b); memcpy(depth_obj.points, a, sizeof(float) * 2); memcpy(&depth_obj.points[2], b, sizeof(float) * 2); // compute the centerpoint of the object cent[0] = (a[0] + b[0]) / 2; cent[1] = (a[1] + b[1]) / 2; cent[2] = (a[2] + b[2]) / 2; // compute the distance to the eye depth_obj.dist = compute_dist(cent); // we'll add the object here, since we have multiple objects draw = 0; memusage += sizeof(float) * 2 * depth_obj.npoints; points += depth_obj.npoints; objects++; depth_list.append(depth_obj); v += 6; } } break; case DPOLYLINEARRAY: { // XXX much replicated code from DLINE / DLINEARRAY float *v = (float *)cmd_ptr; int nverts = (int)v[0]; v++; for (int i=0; i<nverts-1; i++) { // check for degenerate line if (!memcmp(v,v+3,3*sizeof(float))) break; // allocate memory depth_obj.points = (float *) malloc(sizeof(float) * 4); if (!depth_obj.points) { // memory error if (!memerror) { memerror = 1; msgErr << "PSDisplayDevice: Out of memory. Some " << "objects were not drawn." << sendmsg; } break; } // copy data depth_obj.npoints = 2; depth_obj.color = colorIndex; (transMat.top()).multpoint3d(v, a); (transMat.top()).multpoint3d(v+3, b); memcpy(depth_obj.points, a, sizeof(float) * 2); memcpy(&depth_obj.points[2], b, sizeof(float) * 2); // compute the centerpoint of the object cent[0] = (a[0] + b[0]) / 2; cent[1] = (a[1] + b[1]) / 2; cent[2] = (a[2] + b[2]) / 2; // compute the distance to the eye depth_obj.dist = compute_dist(cent); // we'll add the object here, since we have multiple objects draw = 0; memusage += sizeof(float) * 2 * depth_obj.npoints; points += depth_obj.npoints; objects++; depth_list.append(depth_obj); v += 3; } } break; case DCYLINDER: { int res; (transMat.top()).multpoint3d((float *) cmd_ptr, a); (transMat.top()).multpoint3d(&((float *) cmd_ptr)[3], b); r = scale_radius(((float *) cmd_ptr)[6]); res = (int) ((float *) cmd_ptr)[7]; cylinder_approx(a, b, r, res, (int) ((float *) cmd_ptr)[8]); break; } case DCONE: { (transMat.top()).multpoint3d(((DispCmdCone *) cmd_ptr)->pos1, a); (transMat.top()).multpoint3d(((DispCmdCone *) cmd_ptr)->pos2, b); float r1 = scale_radius(((DispCmdCone *) cmd_ptr)->radius); float r2 = scale_radius(((DispCmdCone *) cmd_ptr)->radius2); // XXX current implementation can't draw truncated cones. if (r2 > 0.0f) { msgWarn << "PSDisplayDevice) can't draw truncated cones" << sendmsg; } cone_approx(a, b, r1); break; } case DTEXTSIZE: textsize = ((DispCmdTextSize *)cmd_ptr)->size; break; case DTEXT: { float* pos = (float *)cmd_ptr; #if 0 // thickness not implemented yet float thickness = pos[3]; // thickness is stored in 4th slot #endif char* txt = (char *)(pos+4); int txtlen = strlen(txt); // allocate memory depth_obj.points = (float *) malloc(sizeof(float) * 2); depth_obj.text = (char *) malloc(sizeof(char) * (txtlen+1)); if ( !(depth_obj.points || depth_obj.text) ) { // memory error if (!memerror) { memerror = 1; msgErr << "PSDisplayDevice: Out of memory. Some " << "objects were not drawn." << sendmsg; } break; } // copy data depth_obj.npoints = 1; depth_obj.color = colorIndex; (transMat.top()).multpoint3d(((DispCmdPoint *) cmd_ptr)->pos, a); memcpy(depth_obj.points, a, sizeof(float) * 2); strcpy(depth_obj.text , txt); // note scale factor, stored into "light_scale", so we didn't // have to add a new structure member just for this. depth_obj.light_scale = textsize * 15; // compute the distance to the eye depth_obj.dist = compute_dist(a); // valid object to depth sort draw = 1; break; } case DTRIANGLE: // check for degenerate triangle if (!memcmp(((DispCmdTriangle *) cmd_ptr)->pos1, ((DispCmdTriangle *) cmd_ptr)->pos2, sizeof(float) * 3) || !memcmp(((DispCmdTriangle *) cmd_ptr)->pos2, ((DispCmdTriangle *) cmd_ptr)->pos3, sizeof(float) * 3) || !memcmp(((DispCmdTriangle *) cmd_ptr)->pos2, ((DispCmdTriangle *) cmd_ptr)->pos3, sizeof(float) * 3)) { // degenerate triangle break; } // allocate memory depth_obj.points = (float *) malloc(sizeof(float) * 6); if (!depth_obj.points) { // memory error if (!memerror) { memerror = 1; msgErr << "PSDisplayDevice: Out of memory. Some " << "objects were not drawn." << sendmsg; } break; } // copy data depth_obj.npoints = 3; depth_obj.color = (nc >= 0) ? nc : colorIndex; (transMat.top()).multpoint3d(((DispCmdTriangle *) cmd_ptr)->pos1, a); (transMat.top()).multpoint3d(((DispCmdTriangle *) cmd_ptr)->pos2, b); (transMat.top()).multpoint3d(((DispCmdTriangle *) cmd_ptr)->pos3, c); memcpy(depth_obj.points, a, sizeof(float) * 2); memcpy(&depth_obj.points[2], b, sizeof(float) * 2); memcpy(&depth_obj.points[4], c, sizeof(float) * 2); // compute the centerpoint of the object cent[0] = (a[0] + b[0] + c[0]) / 3; cent[1] = (a[1] + b[1] + c[1]) / 3; cent[2] = (a[2] + b[2] + c[2]) / 3; // compute the distance to the eye for depth sorting depth_obj.dist = compute_dist(cent); // compute a light shading factor depth_obj.light_scale = compute_light(a, b, c); // valid object to depth sort draw = 1; break; case DTRIMESH_C4F_N3F_V3F: // call a separate routine to break up the mesh into // its component triangles decompose_mesh((DispCmdTriMesh *) cmd_ptr); break; case DTRISTRIP: // call a separate routine to break up the strip into // its component triangles decompose_tristrip((DispCmdTriStrips *) cmd_ptr); break; case DSQUARE: // check for degenerate quadrilateral if (!memcmp(((DispCmdSquare *) cmd_ptr)->pos1, ((DispCmdSquare *) cmd_ptr)->pos2, sizeof(float) * 3) || !memcmp(((DispCmdSquare *) cmd_ptr)->pos1, ((DispCmdSquare *) cmd_ptr)->pos3, sizeof(float) * 3) || !memcmp(((DispCmdSquare *) cmd_ptr)->pos1, ((DispCmdSquare *) cmd_ptr)->pos4, sizeof(float) * 3) || !memcmp(((DispCmdSquare *) cmd_ptr)->pos2, ((DispCmdSquare *) cmd_ptr)->pos3, sizeof(float) * 3) || !memcmp(((DispCmdSquare *) cmd_ptr)->pos2, ((DispCmdSquare *) cmd_ptr)->pos4, sizeof(float) * 3) || !memcmp(((DispCmdSquare *) cmd_ptr)->pos3, ((DispCmdSquare *) cmd_ptr)->pos4, sizeof(float) * 3)) { // degenerate quadrilateral break; } // allocate memory depth_obj.points = (float *) malloc(sizeof(float) * 8); if (!depth_obj.points) { // memory error if (!memerror) { memerror = 1; msgErr << "PSDisplayDevice: Out of memory. Some " << "objects were not drawn." << sendmsg; } break; } // copy data depth_obj.npoints = 4; depth_obj.color = colorIndex; (transMat.top()).multpoint3d(((DispCmdSquare *) cmd_ptr)->pos1, a); (transMat.top()).multpoint3d(((DispCmdSquare *) cmd_ptr)->pos2, b); (transMat.top()).multpoint3d(((DispCmdSquare *) cmd_ptr)->pos3, c); (transMat.top()).multpoint3d(((DispCmdSquare *) cmd_ptr)->pos4, d); memcpy(depth_obj.points, a, sizeof(float) * 2); memcpy(&depth_obj.points[2], b, sizeof(float) * 2); memcpy(&depth_obj.points[4], c, sizeof(float) * 2); memcpy(&depth_obj.points[6], d, sizeof(float) * 2); // compute the centerpoint of the object cent[0] = (a[0] + b[0] + c[0] + d[0]) / 4; cent[1] = (a[1] + b[1] + c[1] + d[1]) / 4; cent[2] = (a[2] + b[2] + c[2] + d[2]) / 4; // compute the distance to the eye for depth sorting depth_obj.dist = compute_dist(cent); // compute a light shading factor depth_obj.light_scale = compute_light(a, b, c); // valid object to depth sort draw = 1; break; case DCOLORINDEX: colorIndex = ((DispCmdColorIndex *) cmd_ptr)->color; break; case DSPHERERES: set_sphere_res(((int *) cmd_ptr)[0]); break; default: // unknown object, so just skip it break; } // if we have a valid object to add to the depth sort list if (draw && depth_obj.npoints) { memusage += sizeof(float) * 2 * depth_obj.npoints; if ( depth_obj.text ) memusage += sizeof(char) * (1+strlen(depth_obj.text)); points += depth_obj.npoints; objects++; depth_list.append(depth_obj); } depth_obj.npoints = 0; depth_obj.points = NULL; } // while (tok != DLASTCOMMAND) transMat.pop(); } // end for() [periodic images] }
int DisplayDevice::pick(int dim, const float *pos, const VMDDisplayList *cmdList, float &eyedist, int *unitcell, float window_size) { char *cmdptr = NULL; int tok; float newEyeDist, currEyeDist = eyedist; int tag = (-1), inRegion, currTag; float minX=0.0f, minY=0.0f, maxX=0.0f, maxY=0.0f; float fminX=0.0f, fminY=0.0f, fminZ=0.0f, fmaxX=0.0f, fmaxY=0.0f, fmaxZ=0.0f; float wpntpos[3], pntpos[3], cpos[3]; if(!cmdList) return (-1); // initialize picking: find screen region to look for object if (dim == 2) { fminX = pos[0] - window_size; fmaxX = pos[0] + window_size; fminY = pos[1] - window_size; fmaxY = pos[1] + window_size; abs_screen_pos(fminX, fminY); abs_screen_pos(fmaxX, fmaxY); #if defined(_MSC_VER) // Win32 lacks the C99 round() routine // Add +/- 0.5 then then round towards zero. #if 1 minX = (int) ((float) (fminX + (fminX >= 0.0f ? 0.5f : -0.5f))); maxX = (int) ((float) (fmaxX + (fmaxX >= 0.0f ? 0.5f : -0.5f))); minY = (int) ((float) (fminY + (fminY >= 0.0f ? 0.5f : -0.5f))); maxY = (int) ((float) (fmaxY + (fmaxY >= 0.0f ? 0.5f : -0.5f))); #else minX = truncf(fminX + (fminX >= 0.0f ? 0.5f : -0.5f)); maxX = truncf(fmaxX + (fmaxX >= 0.0f ? 0.5f : -0.5f)); minY = truncf(fminY + (fminY >= 0.0f ? 0.5f : -0.5f)); maxY = truncf(fmaxY + (fmaxY >= 0.0f ? 0.5f : -0.5f)); // minX = floor(fminX + 0.5); // maxX = floor(fmaxX + 0.5); // minY = floor(fminY + 0.5); // maxY = floor(fmaxY + 0.5); #endif #else minX = round(fminX); maxX = round(fmaxX); minY = round(fminY); maxY = round(fmaxY); #endif } else { fminX = pos[0] - window_size; fmaxX = pos[0] + window_size; fminY = pos[1] - window_size; fmaxY = pos[1] + window_size; fminZ = pos[2] - window_size; fmaxZ = pos[2] + window_size; } // make sure we do not disturb the regular transformation matrix transMat.dup(); (transMat.top()).multmatrix(cmdList->mat); // Transform the current pick point for each periodic image ResizeArray<Matrix4> pbcImages; ResizeArray<int> pbcCells; find_pbc_images(cmdList, pbcImages); find_pbc_cells(cmdList, pbcCells); int pbcimg; for (pbcimg=0; pbcimg<pbcImages.num(); pbcimg++) { transMat.dup(); (transMat.top()).multmatrix(pbcImages[pbcimg]); // scan through the list, getting each command and executing it, until // the end of commands token is found VMDDisplayList::VMDLinkIter cmditer; cmdList->first(&cmditer); while((tok = cmdList->next(&cmditer, cmdptr)) != DLASTCOMMAND) { switch (tok) { case DPICKPOINT: // calculate the transformed position of the point { DispCmdPickPoint *cmd = (DispCmdPickPoint *)cmdptr; vec_copy(wpntpos, cmd->postag); currTag = cmd->tag; } (transMat.top()).multpoint3d(wpntpos, pntpos); // check if in picking region ... different for 2D and 3D if (dim == 2) { // convert the 3D world coordinate to 2D (XY) absolute screen // coordinate, and a normalized Z coordinate. abs_screen_loc_3D(pntpos, cpos); // check to see if the projected picking position falls within the // view frustum, with the XY coords falling within the displayed // window, and the Z coordinate falling within the view volume // between the front and rear clipping planes. inRegion = (cpos[0] >= minX && cpos[0] <= maxX && cpos[1] >= minY && cpos[1] <= maxY && cpos[2] >= 0.0 && cpos[2] <= 1.0); } else { // just check to see if the position is in a box centered on our // pointer. The pointer position should already be transformed. inRegion = (pntpos[0] >= fminX && pntpos[0] <= fmaxX && pntpos[1] >= fminY && pntpos[1] <= fmaxY && pntpos[2] >= fminZ && pntpos[2] <= fmaxZ); } // Clip still-viable pick points against all active clipping planes if (inRegion) { // We must perform a check against all of the active // user-defined clipping planes to ensure that only pick points // associated with visible geometry can be selected. int cp; for (cp=0; cp < VMD_MAX_CLIP_PLANE; cp++) { // The final result is the intersection of all of the // individual clipping plane tests... if (cmdList->clipplanes[cp].mode) { float cpdist[3]; vec_sub(cpdist, wpntpos, cmdList->clipplanes[cp].center); inRegion &= (dot_prod(cpdist, cmdList->clipplanes[cp].normal) > 0.0f); } } } // has a hit occurred? if (inRegion) { // yes, see if it is closer to the eye position than earlier objects if(dim==2) newEyeDist = DTOEYE(pntpos[0], pntpos[1], pntpos[2]); else newEyeDist = DTOPOINT(pntpos[0],pntpos[1],pntpos[2]); if(currEyeDist < 0.0 || newEyeDist < currEyeDist) { currEyeDist = newEyeDist; tag = currTag; if (unitcell) { unitcell[0] = pbcCells[3*pbcimg ]; unitcell[1] = pbcCells[3*pbcimg+1]; unitcell[2] = pbcCells[3*pbcimg+2]; } } } break; case DPICKPOINT_ARRAY: // loop over all of the pick points in the pick point index array DispCmdPickPointArray *cmd = (DispCmdPickPointArray *)cmdptr; float *pickpos=NULL; float *crds=NULL; int *indices=NULL; cmd->getpointers(crds, indices); int i; for (i=0; i<cmd->numpicks; i++) { pickpos = crds + i*3; if (cmd->allselected) { currTag = i + cmd->firstindex; } else { currTag = indices[i]; } vec_copy(wpntpos, pickpos); (transMat.top()).multpoint3d(pickpos, pntpos); // check if in picking region ... different for 2D and 3D if (dim == 2) { // convert the 3D world coordinate to 2D absolute screen coord abs_screen_loc_3D(pntpos, cpos); // check to see if the position falls in our picking region // including the clipping region (cpos[2]) inRegion = (cpos[0] >= minX && cpos[0] <= maxX && cpos[1] >= minY && cpos[1] <= maxY && cpos[2] >= 0.0 && cpos[2] <= 1.0); } else { // just check to see if the position is in a box centered on our // pointer. The pointer position should already be transformed. inRegion = (pntpos[0] >= fminX && pntpos[0] <= fmaxX && pntpos[1] >= fminY && pntpos[1] <= fmaxY && pntpos[2] >= fminZ && pntpos[2] <= fmaxZ); } // Clip still-viable pick points against all active clipping planes if (inRegion) { // We must perform a check against all of the active // user-defined clipping planes to ensure that only pick points // associated with visible geometry can be selected. int cp; for (cp=0; cp < VMD_MAX_CLIP_PLANE; cp++) { // The final result is the intersection of all of the // individual clipping plane tests... if (cmdList->clipplanes[cp].mode) { float cpdist[3]; vec_sub(cpdist, wpntpos, cmdList->clipplanes[cp].center); inRegion &= (dot_prod(cpdist, cmdList->clipplanes[cp].normal) > 0.0f); } } } // has a hit occurred? if (inRegion) { // yes, see if it is closer to the eye than earlier hits if (dim==2) newEyeDist = DTOEYE(pntpos[0], pntpos[1], pntpos[2]); else newEyeDist = DTOPOINT(pntpos[0],pntpos[1],pntpos[2]); if (currEyeDist < 0.0 || newEyeDist < currEyeDist) { currEyeDist = newEyeDist; tag = currTag; if (unitcell) { unitcell[0] = pbcCells[3*pbcimg ]; unitcell[1] = pbcCells[3*pbcimg+1]; unitcell[2] = pbcCells[3*pbcimg+2]; } } } } break; } } // Pop the PBC image transform transMat.pop(); } // end of loop over PBC images // make sure we do not disturb the regular transformation matrix transMat.pop(); // return result; if tag >= 0, we found something eyedist = currEyeDist; return tag; }
int DisplayDevice::pick (int dim, const float *pos, const VMDDisplayList *cmdList, float &eyedist, int *unitcell, float window_size) { char *cmdptr = NULL; int tok; float newEyeDist, currEyeDist = eyedist; int tag = (-1), inRegion, currTag; int minX = 0, minY = 0, maxX = 0, maxY = 0; float fminX = 0.0f, fminY = 0.0f, fminZ = 0.0f, fmaxX = 0.0f, fmaxY = 0.0f, fmaxZ = 0.0f; float pntpos[3]; long cpos[2]; if (!cmdList) return (-1); // initialize picking: find screen region to look for object if (dim == 2) { fminX = pos[0] - window_size; fmaxX = pos[0] + window_size; fminY = pos[1] - window_size; fmaxY = pos[1] + window_size; abs_screen_pos (fminX, fminY); abs_screen_pos (fmaxX, fmaxY); minX = (int) fminX; maxX = (int) fmaxX; minY = (int) fminY; maxY = (int) fmaxY; } else { fminX = pos[0] - window_size; fmaxX = pos[0] + window_size; fminY = pos[1] - window_size; fmaxY = pos[1] + window_size; fminZ = pos[2] - window_size; fmaxZ = pos[2] + window_size; } // make sure we do not disturb the regular transformation matrix transMat.dup (); (transMat.top ()).multmatrix (cmdList->mat); // Transform the current pick point for each periodic image ResizeArray<Matrix4> pbcImages; ResizeArray<int> pbcCells; find_pbc_images (cmdList, pbcImages); find_pbc_cells (cmdList, pbcCells); int pbcimg; for (pbcimg = 0; pbcimg < pbcImages.num (); pbcimg++) { transMat.dup (); (transMat.top ()).multmatrix (pbcImages[pbcimg]); // scan through the list, getting each command and executing it, until // the end of commands token is found VMDDisplayList::VMDLinkIter cmditer; cmdList->first (&cmditer); float *dataBlock = NULL; while ((tok = cmdList->next (&cmditer, cmdptr)) != DLASTCOMMAND) { switch (tok) { case DDATABLOCK: #ifdef VMDCAVE dataBlock = (float *)cmdptr; #else dataBlock = ((DispCmdDataBlock *) cmdptr)->data; #endif break; case DPICKPOINT: case DPICKPOINT_I: // calculate the transformed position of the point if (tok == DPICKPOINT) { DispCmdPickPoint *cmd = (DispCmdPickPoint *) cmdptr; (transMat.top ()).multpoint3d (cmd->postag, pntpos); currTag = cmd->tag; } else { DispCmdPickPointIndex *cmd = (DispCmdPickPointIndex *) cmdptr; (transMat.top ()).multpoint3d (dataBlock + cmd->pos, pntpos); currTag = cmd->tag; } // check if in picking region ... different for 2D and 3D if (dim == 2) { // convert the 3D world coordinate to 2D absolute screen coord abs_screen_loc_3D (pntpos, cpos); // check to see if the position falls in our picking region inRegion = (cpos[0] >= minX && cpos[0] <= maxX && cpos[1] >= minY && cpos[1] <= maxY); } else { // just check to see if the position is in a box centered on our // pointer. The pointer position should already be transformed. inRegion = (pntpos[0] >= fminX && pntpos[0] <= fmaxX && pntpos[1] >= fminY && pntpos[1] <= fmaxY && pntpos[2] >= fminZ && pntpos[2] <= fmaxZ); } // has a hit occurred? if (inRegion) { // yes, see if it is closer to the eye position than earlier objects if (dim == 2) newEyeDist = DTOEYE(pntpos[0], pntpos[1], pntpos[2]); else newEyeDist = DTOPOINT(pntpos[0],pntpos[1],pntpos[2]); if (currEyeDist < 0.0 || newEyeDist < currEyeDist) { currEyeDist = newEyeDist; tag = currTag; if (unitcell) { unitcell[0] = pbcCells[3 * pbcimg]; unitcell[1] = pbcCells[3 * pbcimg + 1]; unitcell[2] = pbcCells[3 * pbcimg + 2]; } } } break; case DPICKPOINT_IARRAY: // loop over all of the pick points in the pick point index array DispCmdPickPointIndexArray *cmd = (DispCmdPickPointIndexArray *) cmdptr; float *pickpos; int *indices; cmd->getpointers (indices); int i; for (i = 0; i < cmd->numpicks; i++) { if (cmd->allselected) { pickpos = dataBlock + i * 3; currTag = i; } else { pickpos = dataBlock + indices[i] * 3; currTag = indices[i]; } (transMat.top ()).multpoint3d (pickpos, pntpos); // check if in picking region ... different for 2D and 3D if (dim == 2) { // convert the 3D world coordinate to 2D absolute screen coord abs_screen_loc_3D (pntpos, cpos); // check to see if the position falls in our picking region inRegion = (cpos[0] >= minX && cpos[0] <= maxX && cpos[1] >= minY && cpos[1] <= maxY); } else { // just check to see if the position is in a box centered on our // pointer. The pointer position should already be transformed. inRegion = (pntpos[0] >= fminX && pntpos[0] <= fmaxX && pntpos[1] >= fminY && pntpos[1] <= fmaxY && pntpos[2] >= fminZ && pntpos[2] <= fmaxZ); } // has a hit occurred? if (inRegion) { // yes, see if it is closer to the eye than earlier hits if (dim == 2) newEyeDist = DTOEYE(pntpos[0], pntpos[1], pntpos[2]); else newEyeDist = DTOPOINT(pntpos[0],pntpos[1],pntpos[2]); if (currEyeDist < 0.0 || newEyeDist < currEyeDist) { currEyeDist = newEyeDist; tag = currTag; if (unitcell) { unitcell[0] = pbcCells[3 * pbcimg]; unitcell[1] = pbcCells[3 * pbcimg + 1]; unitcell[2] = pbcCells[3 * pbcimg + 2]; } } } } break; } } // Pop the PBC image transform transMat.pop (); } // end of loop over PBC images // make sure we do not disturb the regular transformation matrix transMat.pop (); // return result; if tag >= 0, we found something eyedist = currEyeDist; return tag; }