void DisplayDevice::find_pbc_images (const VMDDisplayList *cmdList, ResizeArray<Matrix4> &pbcImages) { if (cmdList->pbc == PBC_NONE) { pbcImages.append (Matrix4 ()); return; } ResizeArray<int> pbcCells; find_pbc_cells (cmdList, pbcCells); for (int i = 0; i < pbcCells.num (); i += 3) { int nx = pbcCells[i]; int ny = pbcCells[i + 1]; int nz = pbcCells[i + 2]; Matrix4 mat; for (int i1 = 1; i1 <= nx; i1++) mat.multmatrix (cmdList->transX); for (int i2 = -1; i2 >= nx; i2--) mat.multmatrix (cmdList->transXinv); for (int i3 = 1; i3 <= ny; i3++) mat.multmatrix (cmdList->transY); for (int i4 = -1; i4 >= ny; i4--) mat.multmatrix (cmdList->transYinv); for (int i5 = 1; i5 <= nz; i5++) mat.multmatrix (cmdList->transZ); for (int i6 = -1; i6 >= nz; i6--) mat.multmatrix (cmdList->transZinv); pbcImages.append (mat); } }
static void mol_delete_cb(Fl_Widget *w, void *v) { VMDApp *app = (VMDApp *)w->user_data(); MolBrowser *browser = (MolBrowser *)v; ResizeArray<int> idlist; for (int i=0; i<browser->size(); i++) { if (browser->selected(i+1)) { idlist.append(app->molecule_id(i)); } } for (int j=0; j<idlist.num(); j++) app->molecule_delete(idlist[j]); }
ResizeArray<JString *> *generic_get_names(const T &devList) { ResizeArray<JString *> *names = SensorConfig::getnames(); ResizeArray<JString *> *devnames = new ResizeArray<JString *>; for (int i=0; i<names->num(); i++) { JString *jstr = (*names)[i]; SensorConfig config(*jstr); const char *type = config.gettype(); if (devList.typecode(type) >= 0) devnames->append(jstr); else delete jstr; } delete names; return devnames; }
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; }
static PyObject *sasa(PyObject *self, PyObject *args, PyObject *keywds) { int molid = -1, frame = -1; float srad = 0; PyObject *selobj = NULL, *restrictobj = NULL; int samples = -1; const int *sampleptr = NULL; PyObject *pointsobj = NULL; static char *kwlist[] = { (char *)"srad", (char *)"molid", (char *)"frame", (char *)"selected", (char *)"samples", (char *)"points", (char *)"restrict" }; if (!PyArg_ParseTupleAndKeywords(args, keywds, (char *)"fiiO!|iO!O!:atomselection.sasa", kwlist, &srad, &molid, &frame, &PyTuple_Type, &selobj, &samples, &PyList_Type, &pointsobj, &PyTuple_Type, &restrictobj)) return NULL; // validate srad if (srad < 0) { PyErr_SetString(PyExc_ValueError, (char *)"atomselect.sasa: srad must be non-negative."); return NULL; } // validate selection VMDApp *app = get_vmdapp(); AtomSel *sel = sel_from_py(molid, frame, selobj, app); if (!sel) return NULL; // fetch the radii and coordinates const float *radii = app->moleculeList->mol_from_id(sel->molid())->extraflt.data("radius"); const float *coords = sel->coordinates(app->moleculeList); // if samples was given and is valid, use it if (samples > 1) sampleptr = &samples; // if restrict is given, validate it AtomSel *restrictsel = NULL; if (restrictobj) { if (!(restrictsel = sel_from_py(molid, frame, restrictobj, app))) { delete sel; return NULL; } } // if points are requested, fetch them ResizeArray<float> sasapts; ResizeArray<float> *sasaptsptr = pointsobj ? &sasapts : NULL; // go! float sasa = 0; int rc = measure_sasa(sel, coords, radii, srad, &sasa, sasaptsptr, restrictsel, sampleptr); delete sel; delete restrictsel; if (rc) { PyErr_SetString(PyExc_ValueError, (char *)measure_error(rc)); return NULL; } // append surface points to the provided list object. if (pointsobj) { for (int i=0; i<sasapts.num(); i++) { PyList_Append(pointsobj, PyFloat_FromDouble(sasapts[i])); } } // return the total SASA. return PyFloat_FromDouble(sasa); }
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] }
// To write an X3DOM-compatible scene file, we cannot include // LineProperties nodes. void X3DOMDisplayDevice::text(float *pos, float size, float thickness, const char *str) { float textpos[3]; float textsize; hersheyhandle hh; // transform the world coordinates (transMat.top()).multpoint3d(pos, textpos); textsize = size * 1.5f; ResizeArray<int> idxs; ResizeArray<float> pnts; idxs.clear(); pnts.clear(); int idx=0; while (*str != '\0') { float lm, rm, x, y; int draw; x=y=0.0f; draw=0; hersheyDrawInitLetter(&hh, *str, &lm, &rm); textpos[0] -= lm * textsize; while (!hersheyDrawNextLine(&hh, &draw, &x, &y)) { float pt[3]; if (draw) { // add another connected point to the line strip idxs.append(idx); pt[0] = textpos[0] + textsize * x; pt[1] = textpos[1] + textsize * y; pt[2] = textpos[2]; pnts.append(pt[0]); pnts.append(pt[1]); pnts.append(pt[2]); idx++; } else { idxs.append(-1); // pen-up, end of the line strip } } idxs.append(-1); // pen-up, end of the line strip textpos[0] += rm * textsize; str++; } fprintf(outfile, "<Shape>\n"); fprintf(outfile, " "); // // Emit the line properties // fprintf(outfile, "<Appearance><Material "); fprintf(outfile, "ambientIntensity='%g' ", mat_ambient); fprintf(outfile, "diffuseColor='0 0 0' "); const float *rgb = matData[colorIndex]; fprintf(outfile, "emissiveColor='%g %g %g' ", mat_diffuse * rgb[0], mat_diffuse * rgb[1], mat_diffuse * rgb[2]); fprintf(outfile, "/>"); #if 0 // XXX X3DOM v1.1 doesn't handle LineProperties nodes // emit a line thickness directive, if needed if (thickness < 0.99f || thickness > 1.01f) { fprintf(outfile, " <LineProperties linewidthScaleFactor=\"%g\" " "containerField=\"lineProperties\"/>\n", (double) thickness); } #endif fprintf(outfile, "</Appearance>\n"); // // Emit the line set // fprintf(outfile, " <IndexedLineSet coordIndex='"); int i, cnt; cnt = idxs.num(); for (i=0; i<cnt; i++) { fprintf(outfile, "%d ", idxs[i]); } fprintf(outfile, "'>\n"); fprintf(outfile, " <Coordinate point='"); cnt = pnts.num(); for (i=0; i<cnt; i+=3) { fprintf(outfile, "%c%g %g %g", (i==0) ? ' ' : ',', pnts[i], pnts[i+1], pnts[i+2]); } fprintf(outfile, "'/>\n"); fprintf(outfile, " </IndexedLineSet>\n"); fprintf(outfile, "</Shape>\n"); }
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; }
// read in the startup script, execute it, and then execute any other commands // which might be necessary (i.e. to load any molecules at start) // This searches for the startup file in the following // places (and in this order), reading only the FIRST one found: // 1. Current directory // 2. Home directory // 3. 'Default' directory (here, /usr/local/vmd) // If a name was given in the -startup switch, that file is checked for ONLY. void VMDreadStartup(VMDApp *app) { char namebuf[512], *envtxt; int found = FALSE; FILE * tfp; char *DataPath; // path of last resort to find a .vmdrc file // These options were set by environment variables or command line options app->display_set_screen_height(displayHeight); app->display_set_screen_distance(displayDist); app->set_eofexit(eofexit); if (showTitle == TITLE_ON && which_display != DISPLAY_TEXT) { app->display_titlescreen(); } if((envtxt = getenv("VMDDIR")) != NULL) DataPath = stringdup(envtxt); else DataPath = stringdup(DEF_VMDENVVAR); stripslashes(DataPath); // strip out ending '/' chars. // check if the file is available if(startupFileStr) { // name specified by -startup if((tfp = fopen(startupFileStr, "rb")) != NULL) { found = TRUE; fclose(tfp); strcpy(namebuf, startupFileStr); } } else { // search in different directories, for default file const char *def_startup = VMD_STARTUP; // first, look in current dir strcpy(namebuf, def_startup); if((tfp = fopen(namebuf, "rb")) != NULL) { found = TRUE; fclose(tfp); } else { // not found in current dir; look in home dir if((envtxt = getenv("HOME")) != NULL) strcpy(namebuf,envtxt); else strcpy(namebuf,"."); strcat(namebuf,"/"); strcat(namebuf,def_startup); if((tfp = fopen(namebuf, "rb")) != NULL) { found = TRUE; fclose(tfp); } else { // not found in home dir; look in default dir strcpy(namebuf, DataPath); strcat(namebuf,"/"); strcat(namebuf, def_startup); if((tfp = fopen(namebuf, "rb")) != NULL) { found = TRUE; fclose(tfp); } } } } delete [] DataPath; DataPath = NULL; // // execute any commands needed at start // // read in molecules requested via command-line switches FileSpec spec; spec.waitfor = -1; // wait for all files to load before proceeding int molid = -1; // set sentinel value to determine if files were loaded if (startNewMoleculeFlags.num() > 0) { msgInfo << "File loading in progress, please wait." << sendmsg; } for (int i=0; i<startNewMoleculeFlags.num(); i++) { const char *filename = initFilenames[i]; const char *filetype = initFiletypes[i]; if (!filetype) { filetype = app->guess_filetype(filename); if (!filetype) { // assume pdb msgErr << "Unable to determine file type for file '" << filename << "'. Assuming pdb." << sendmsg; filetype = "pdb"; } } if (startNewMoleculeFlags[i]) { molid = app->molecule_load(-1, filename, filetype, &spec); } else { molid = app->molecule_load(molid, filename, filetype, &spec); } if (molid < 0) { msgErr << "Loading of startup molecule files aborted." << sendmsg; break; } } // if the startup file was found, read in the commands there if(found) { app->logfile_read(namebuf); } // Load the extension packages here, _after_ reading the .vmdrc file, // so that the search path for extensions can be customized. app->commandQueue->runcommand( new TclEvalEvent("vmd_load_extension_packages")); // Switch to Python if requested, before reading beginCmdFile if (cmdFileUsesPython) { if (!app->textinterp_change("python")) { // bail out since Python scripts won't be readable by Tcl. msgErr << "Skipping startup script because Python could not be started." << sendmsg; return; } } // after reading in startup file and loading any molecule, the file // specified by the -e option is set up to be executed. if(beginCmdFile) { app->logfile_read(beginCmdFile); } }
int VMDinitialize(int *argc, char ***argv) { int i; #if defined VMDMPI // hack to fix up env vars if necessary for (i=0; i<(*argc); i++) { if(!strupcmp((*argv)[i], "-vmddir")) { if((*argc) > (i + 1)) { setenv("VMDDIR", (*argv)[++i], 1); } else { msgErr << "-vmddir must specify a fully qualified path." << sendmsg; } } } vmd_mpi_init(argc, argv); // initialize MPI, fix up env vars, etc. #endif #if defined(_MSC_VER) && !defined(VMDSEPARATESTARTUP) win32vmdstart(); // get registry info etc #endif #if !defined(VMDNOMACBUNDLE) && defined(__APPLE__) macosxvmdstart(*argc, *argv); // get env variables etc #endif // Tell Tcl where the executable is located const char *argv0 = vmd_initialize_tcl((*argv)[0]); #ifdef VMDTCL // register signal handler tclhandler = Tcl_AsyncCreate(VMDTclAsyncProc, (ClientData)NULL); signal(SIGINT, (sighandler_t) VMDTclSigHandler); #endif // Let people know who we are. VMDtitle(); // Tell the user what we think about the hardware we're running on. // If VMD is compiled for MPI, then we don't print any of the normal // standalone startup messages and instead we use the special MPI-specific // node scan startup messages only. #if !defined(VMDMPI) #if defined(VMDTHREADS) int vmdnumcpus = wkf_thread_numprocessors(); msgInfo << "Multithreading available, " << vmdnumcpus << ((vmdnumcpus > 1) ? " CPUs" : " CPU") << " detected." << sendmsg; #endif long vmdcorefree = vmd_get_avail_physmem_mb(); if (vmdcorefree >= 0) { long vmdcorepcnt = vmd_get_avail_physmem_percent(); msgInfo << "Free system memory: " << vmdcorefree << "MB (" << vmdcorepcnt << "%)" << sendmsg; } #endif // Read environment variables and command line options. // Initialize customArgv with just argv0 to avoid problems with // Tcl extension. customArgv.append((char *)argv0); VMDGetOptions(*argc, *argv); #if (!defined(__APPLE__) && !defined(_MSC_VER)) && (defined(VMDOPENGL) || defined(VMDFLTK)) // If we're using X-windows, we autodetect if the DISPLAY environment // variable is unset, and automatically switch back to text mode without // requiring the user to pass the "-dispdev text" command line parameters if ((which_display == DISPLAY_WIN) && (getenv("DISPLAY") == NULL)) { which_display = DISPLAY_TEXT; } #endif #if defined(VMDTKCON) vmdcon_init(); msgInfo << "Using VMD Console redirection interface." << sendmsg; // we default to a widget mode console, unless text mode is requested. // we don't have an tcl interpreter registered yet, so it is set to NULL. // flushing pending messages to the screen, is only in text mode possible. if ((which_display == DISPLAY_TEXT) || just_print_help) { vmdcon_use_text(NULL); vmdcon_purge(); } else { vmdcon_use_widget(NULL); } #endif #ifdef VMDFLTK // Do various special FLTK initialization stuff here if ((which_display != DISPLAY_TEXT)) { // Cause FLTK to to use 24-bit color for all windows if possible // This must be done before any FLTK windows are shown for the first time. if (!Fl::visual(FL_DOUBLE | FL_RGB8)) { if (!Fl::visual(FL_RGB8)) { Fl::visual(FL_RGB); } } // Disable the use of the arrow keys for navigating buttons and other // non-text widgets, we'll try it out and see how it pans out Fl::visible_focus(0); // Disable Drag 'n Drop since the only text field in VMD is the // atomselection input and DND severely gets in the way there. Fl::dnd_text_ops(0); } #endif // Quit now if the user just wanted a list of command line options. if (just_print_help) { vmd_sleep(10); // This is here so that the user can see the message // before the terminal/shell exits... return 0; } // Set up default allocators; these may be overridden by cave or freevr. vmd_alloc = malloc; // system malloc() in the default case vmd_dealloc = free; // system free() in the default case vmd_realloc = realloc; // system realloc(), set to NULL when not available // check for a CAVE display if (DISPLAY_USES_CAVE(which_display)) { #ifdef VMDCAVE // allocate shared memory pool used to communicate with child renderers int megs = 2048; if (getenv("VMDCAVEMEM") != NULL) { megs = atoi(getenv("VMDCAVEMEM")); } msgInfo << "Attempting to get " << megs << "MB of CAVE Shared Memory" << sendmsg; grab_CAVE_memory(megs); CAVEConfigure(argc, *argv, NULL); // configure cave walls and memory use // point VMD shared memory allocators to CAVE routines vmd_alloc = malloc_from_CAVE_memory; vmd_dealloc = free_to_CAVE_memory; vmd_realloc = NULL; // no realloc() functionality is available presently #else msgErr << "Not compiled with the CAVE options set." << sendmsg; which_display = DISPLAY_WIN; #endif } // check for a FreeVR display if (DISPLAY_USES_FREEVR(which_display)) { #ifdef VMDFREEVR int megs = 2048; if (getenv("VMDFREEVRMEM") != NULL) { megs = atoi(getenv("VMDFREEVRMEM")); } msgInfo << "Attempting to get " << megs << "MB of FreeVR Shared Memory" << sendmsg; grab_FreeVR_memory(megs); // have to do this *before* vrConfigure() if // we want more than the default shared mem. vrConfigure(NULL, NULL, NULL); // configure FreeVR walls // point shared memory allocators to FreeVR routines vmd_alloc = malloc_from_FreeVR_memory; vmd_dealloc = free_to_FreeVR_memory; vmd_realloc = NULL; // no realloc() functionality is available presently #else msgErr << "Not compiled with the FREEVR options set." << sendmsg; which_display = DISPLAY_WIN; #endif } // return custom argc/argv *argc = customArgv.num(); for (i=0; i<customArgv.num(); i++) { (*argv)[i] = customArgv[i]; } return 1; // successful startup }
int text_cmd_mobile(ClientData cd, Tcl_Interp *interp, int argc, const char *argv[]) { VMDApp *app = (VMDApp *)cd; if (argc < 3 || argc > 6) { // if here, something went wrong, so return an error message mobile_usage(interp); return TCL_ERROR; } if (!strupncmp(argv[1], "mode", CMDLEN)) { int m1 = Mobile::OFF; // see if these are string values if (!strupncmp(argv[2], "off", CMDLEN)) m1 = Mobile::OFF; else if (!strupncmp(argv[2], "move", CMDLEN)) m1 = Mobile::MOVE; else if (!strupncmp(argv[2], "animate", CMDLEN)) m1 = Mobile::ANIMATE; else if (!strupncmp(argv[2], "tracker", CMDLEN)) m1 = Mobile::TRACKER; else if (!strupncmp(argv[2], "user", CMDLEN)) m1 = Mobile::USER; else mobile_usage(interp); // error if (!app->mobile_set_mode(m1)) { Tcl_AppendResult(interp, "Unable to set Mobile mode to ", argv[2], argc > 3 ? argv[3] : NULL, NULL); // if here, something went wrong, so return an error message mobile_usage(interp); return TCL_ERROR; } } else if(!strupncmp(argv[1], "port", CMDLEN)) { int port; if (sscanf(argv[2], "%d", &port) == 1) { if (!app->mobile_network_port(port)) { // if here, something went wrong, so return an error message mobile_usage(interp); return TCL_ERROR; } } else { // if here, something went wrong, so return an error message mobile_usage(interp); return TCL_ERROR; } } else if(!strupncmp(argv[1], "get", CMDLEN)) { if (!strupncmp(argv[2], "mode", CMDLEN)) { Tcl_AppendResult(interp, Mobile::get_mode_str((Mobile::MoveMode)app->mobile_get_mode()), NULL); } else if (!strupncmp(argv[2], "clientList", CMDLEN)) { ResizeArray <JString *>* ip; ResizeArray <JString *>* nick; ResizeArray <bool>* active; app->mobile_get_client_list( nick, ip, active); for (int i=0; i<nick->num(); i++) { Tcl_AppendResult(interp, " {", NULL); Tcl_AppendResult(interp, " {", NULL); // here's what we've got.. // (const char *)(*(*nick)[i]) // now to explain it.... // (const char *) Tcl_AppendResult needs a char* // (* ) We have a JString* in ResizeArray that we want to be a JString // (*nick) we have a ResizeArray ptr that we want to be a ResizeArray // [i] specific array elem Tcl_AppendResult(interp, (const char *)(*(*nick)[i]), NULL); Tcl_AppendResult(interp, "}", NULL); Tcl_AppendResult(interp, " {", NULL); Tcl_AppendResult(interp, (const char *)(*(*ip)[i]), NULL); Tcl_AppendResult(interp, "}", NULL); Tcl_AppendResult(interp, " {", NULL); char tmp[10]; sprintf(tmp, "%d", (*active)[i]); Tcl_AppendResult(interp, tmp, NULL); Tcl_AppendResult(interp, "}", NULL); Tcl_AppendResult(interp, " }", NULL); } } else if (!strupncmp(argv[2], "port", CMDLEN)) { char tmpstr[20]; sprintf(tmpstr, "%d", app->mobile_get_network_port()); Tcl_AppendResult(interp, tmpstr, NULL); } else if (!strupncmp(argv[2], "APIsupported", CMDLEN)) { char tmpstr[20]; sprintf(tmpstr, "%d", app->mobile_get_APIsupported()); Tcl_AppendResult(interp, tmpstr, NULL); } else mobile_usage(interp); // error } else if(!strupncmp(argv[1], "sendMsg", CMDLEN)) { if (argc >= 6) { if (!app->mobile_sendMsg(argv[2], argv[3], argv[4], argv[5])) { // if here, something went wrong, so return an error message mobile_usage(interp); return TCL_ERROR; } } else mobile_usage(interp); // error } else if(!strupncmp(argv[1], "set", CMDLEN)) { if (!strupncmp(argv[2], "activeClient", CMDLEN)) { if (argc >= 5) { if (!app->mobile_set_activeClient(argv[3], argv[4])) { // Tcl_AppendResult(interp, "Unable to set activeClient to ", // argv[2], argc > 3 ? argv[3] : NULL, NULL); // if here, something went wrong, so return an error message mobile_usage(interp); return TCL_ERROR; } } else mobile_usage(interp); // error } else mobile_usage(interp); // error } else { // if here, something went wrong, so return an error message mobile_usage(interp); return TCL_ERROR; } // if here, everything worked out ok return TCL_OK; }