Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

DispCmds.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2019 The Board of Trustees of the           
00004  *cr                        University of Illinois                       
00005  *cr                         All Rights Reserved                        
00006  *cr                                                                   
00007  ***************************************************************************/
00008 /***************************************************************************
00009  * RCS INFORMATION:
00010  *
00011  *      $RCSfile: DispCmds.C,v $
00012  *      $Author: johns $        $Locker:  $             $State: Exp $
00013  *      $Revision: 1.121 $      $Date: 2021/05/14 22:47:22 $
00014  *
00015  ***************************************************************************/
00037 #include <string.h>
00038 #include <stdlib.h>
00039 #include <stdio.h>
00040 #include <math.h>
00041 
00042 #ifdef VMDACTC
00043 extern "C" {
00044 // XXX 
00045 // The regular ACTC distribution compiles as plain C, need to send 
00046 // a header file fix to Brad Grantham so C++ codes don't need this.
00047 #include <tc.h>
00048 }
00049 #endif
00050 
00051 #include "Scene.h"
00052 #include "DispCmds.h"
00053 #include "utilities.h"
00054 #include "Matrix4.h"
00055 #include "VMDDisplayList.h"
00056 #include "Inform.h"
00057 #include "VMDApp.h" // needed for texture serial numbers
00058 
00059 //*************************************************************
00060 // Mark the beginning of the geometry associated with a representation
00061 void DispCmdBeginRepGeomGroup::putdata(const char *newtxt, VMDDisplayList *dobj) {
00062   char *buf = (char *) dobj->append(DBEGINREPGEOMGROUP, strlen(newtxt)+1);
00063   if (buf == NULL)
00064     return;
00065   memcpy(buf, newtxt, strlen(newtxt)+1);
00066 }
00067 
00068 
00069 //*************************************************************
00070 // include comments in the display list, useful for Token Rendering
00071 void DispCmdComment::putdata(const char *newtxt, VMDDisplayList *dobj) {
00072   char *buf = (char *) dobj->append(DCOMMENT, strlen(newtxt)+1);
00073   if (buf == NULL)
00074     return;
00075   memcpy(buf, newtxt, strlen(newtxt)+1);
00076 }
00077 
00078 
00079 //*************************************************************
00080 // plot a point at the given position
00081 void DispCmdPoint::putdata(const float *newpos, VMDDisplayList *dobj) {
00082   DispCmdPoint *ptr = (DispCmdPoint *)(dobj->append(DPOINT, 
00083                                        sizeof(DispCmdPoint)));
00084   if (ptr == NULL)
00085     return;
00086   ptr->pos[0]=newpos[0];
00087   ptr->pos[1]=newpos[1];
00088   ptr->pos[2]=newpos[2];
00089 }
00090 
00091 //*************************************************************
00092 // plot a sphere of specified radius at the given position
00093 void DispCmdSphere::putdata(float *newpos, float radius, VMDDisplayList *dobj) {
00094   DispCmdSphere *ptr = (DispCmdSphere *)(dobj->append(DSPHERE, 
00095                                          sizeof(DispCmdSphere)));
00096   if (ptr == NULL)
00097     return;
00098   ptr->pos_r[0]=newpos[0];
00099   ptr->pos_r[1]=newpos[1];
00100   ptr->pos_r[2]=newpos[2];
00101   ptr->pos_r[3]=radius; 
00102 } 
00103 
00104 
00105 void DispCmdSphereArray::putdata(const float * spcenters,
00106                                 const float * spradii,
00107                                 const float * spcolors,
00108                                 int num_spheres,
00109                                 int sphere_res,
00110                                 VMDDisplayList * dobj) {
00111 
00112   DispCmdSphereArray *ptr = (DispCmdSphereArray *) dobj->append(DSPHEREARRAY, 
00113                            sizeof(DispCmdSphereArray) +
00114                            sizeof(float) * num_spheres * 3L +
00115                            sizeof(float) * num_spheres + 
00116                            sizeof(float) * num_spheres * 3L +
00117                            sizeof(int) * 2L);
00118   if (ptr == NULL)
00119     return;
00120   ptr->numspheres = num_spheres;
00121   ptr->sphereres = sphere_res;
00122 
00123   float *centers;
00124   float *radii;
00125   float *colors;
00126   ptr->getpointers(centers, radii, colors);
00127 
00128   memcpy(centers, spcenters, sizeof(float) * num_spheres * 3L);
00129   memcpy(radii, spradii, sizeof(float) * num_spheres);
00130   memcpy(colors, spcolors, sizeof(float) * num_spheres * 3L);
00131 }
00132 
00133 
00134 //*************************************************************
00135 // plot a lattice cube with side length equal to 2x radius at the given position
00136 void DispCmdLatticeCubeArray::putdata(const float * cbcenters,
00137                                       const float * cbradii,
00138                                       const float * cbcolors,
00139                                       int num_cubes,
00140                                       VMDDisplayList * dobj) {
00141 
00142   DispCmdLatticeCubeArray *ptr = (DispCmdLatticeCubeArray *) dobj->append(DCUBEARRAY, 
00143                            sizeof(DispCmdLatticeCubeArray) +
00144                            sizeof(float) * num_cubes * 3L +
00145                            sizeof(float) * num_cubes + 
00146                            sizeof(float) * num_cubes * 3L +
00147                            sizeof(int) * 1L);
00148   if (ptr == NULL)
00149     return;
00150   ptr->numcubes = num_cubes;
00151 
00152   float *centers;
00153   float *radii;
00154   float *colors;
00155   ptr->getpointers(centers, radii, colors);
00156 
00157   memcpy(centers, cbcenters, sizeof(float) * num_cubes * 3L);
00158   memcpy(radii, cbradii, sizeof(float) * num_cubes);
00159   memcpy(colors, cbcolors, sizeof(float) * num_cubes * 3L);
00160 }
00161 
00162 
00163 //*************************************************************
00164 
00165 void DispCmdPointArray::putdata(const float * pcenters,
00166                                 const float * pcolors,
00167                                 float psize,
00168                                 int num_points,
00169                                 VMDDisplayList * dobj) {
00170 
00171   DispCmdPointArray *ptr = (DispCmdPointArray *) dobj->append(DPOINTARRAY, 
00172                            sizeof(DispCmdPointArray) +
00173                            sizeof(float) * num_points * 3L +
00174                            sizeof(float) * num_points * 3L +
00175                            sizeof(float) +
00176                            sizeof(int));
00177   if (ptr == NULL)
00178     return;
00179   ptr->size = psize;
00180   ptr->numpoints = num_points;
00181 
00182   float *centers;
00183   float *colors;
00184   ptr->getpointers(centers, colors);
00185 
00186   memcpy(centers, pcenters, sizeof(float) * num_points * 3L);
00187   memcpy(colors, pcolors, sizeof(float) * num_points * 3L);
00188 }
00189 
00190 void DispCmdPointArray::putdata(const float * pcenters,
00191                                 const int * pcolors,
00192                                 Scene * scene,
00193                                 float psize,
00194                                 int num_atoms,
00195                                 const int *on,
00196                                 int num_selected,
00197                                 VMDDisplayList * dobj) {
00198 
00199   // If we have a reasonable size atom selection and therefore 
00200   // vertex buffer size, we use a very fast/simple path for populating the 
00201   // display command buffer.
00202   // If we have too many vertices, we have to break up the vertex buffers
00203   // and emit several smaller buffers to prevent integer wraparound in 
00204   // vertex indexing in back-end renderers.  
00205   int totalpoints=0;
00206   int i=0;
00207   while (totalpoints < num_selected) {
00208     int chunksize = num_selected - totalpoints;
00209     if (chunksize > VMDMAXVERTEXBUFSZ)
00210       chunksize = VMDMAXVERTEXBUFSZ;
00211 
00212     DispCmdPointArray *ptr = (DispCmdPointArray *) dobj->append(DPOINTARRAY, 
00213                              sizeof(DispCmdPointArray) +
00214                              sizeof(float) * chunksize * 3L +
00215                              sizeof(float) * chunksize * 3L +
00216                              sizeof(float) +
00217                              sizeof(int));
00218     if (ptr == NULL)
00219       return;
00220     ptr->size = psize;
00221     ptr->numpoints = chunksize;
00222 
00223     float *centers, *colors;
00224     ptr->getpointers(centers, colors);
00225 
00226     const float *fp = pcenters + 3L*i;
00227     ptrdiff_t ind;
00228     int cnt;
00229     for (ind=0,cnt=0; ((cnt < VMDMAXVERTEXBUFSZ) && (i < num_atoms)); i++) {
00230       // draw a point for each selected atom
00231       if (on[i]) {
00232         cnt++;
00233         centers[ind    ] = fp[0];
00234         centers[ind + 1] = fp[1];
00235         centers[ind + 2] = fp[2];
00236 
00237         const float *cp = scene->color_value(pcolors[i]);
00238         colors[ind    ] = cp[0];
00239         colors[ind + 1] = cp[1];
00240         colors[ind + 2] = cp[2];
00241         ind += 3L;
00242       }
00243       fp += 3L;
00244     }
00245     totalpoints+=cnt;
00246   }
00247 }
00248 
00249 
00250 
00251 //*************************************************************
00252 
00253 void DispCmdLitPointArray::putdata(const float * pcenters,
00254                                    const float * pnormals,
00255                                    const float * pcolors,
00256                                    float psize,
00257                                    int num_points,
00258                                    VMDDisplayList * dobj) {
00259 
00260   DispCmdLitPointArray *ptr = (DispCmdLitPointArray *) dobj->append(DLITPOINTARRAY, 
00261                            sizeof(DispCmdLitPointArray) +
00262                            sizeof(float) * num_points * 3L +
00263                            sizeof(float) * num_points * 3L +
00264                            sizeof(float) * num_points * 3L +
00265                            sizeof(float) +
00266                            sizeof(int));
00267   if (ptr == NULL)
00268     return;
00269   ptr->size = psize;
00270   ptr->numpoints = num_points;
00271 
00272   float *centers;
00273   float *normals;
00274   float *colors;
00275   ptr->getpointers(centers, normals, colors);
00276 
00277   memcpy(centers, pcenters, sizeof(float) * num_points * 3L);
00278   memcpy(normals, pnormals, sizeof(float) * num_points * 3L);
00279   memcpy(colors, pcolors, sizeof(float) * num_points * 3L);
00280 }
00281 
00282 //*************************************************************
00283 
00284 // plot a line at the given position
00285 void DispCmdLine::putdata(float *newpos1, float *newpos2, VMDDisplayList *dobj) {
00286   DispCmdLine *ptr = (DispCmdLine *)(dobj->append(DLINE, 
00287                                          sizeof(DispCmdLine)));
00288   if (ptr == NULL)
00289     return;
00290   memcpy(ptr->pos1, newpos1, 3L*sizeof(float));
00291   memcpy(ptr->pos2, newpos2, 3L*sizeof(float));
00292 }
00293 
00294 // draw a series of independent lines, (v0 v1), (v2 v3), (v4 v5)
00295 void DispCmdLineArray::putdata(float *v, int n, VMDDisplayList *dobj) {
00296   void *ptr = dobj->append(DLINEARRAY, (1+6L*n)*sizeof(float));
00297   if (ptr == NULL)
00298     return;
00299   float *fltptr = (float *)ptr;
00300   *fltptr = (float)n;
00301   memcpy(fltptr+1, v, 6L*n*sizeof(float));
00302 }
00303 
00304 // draw a series of connected polylines, (v0 v1 v2 v3 v4 v5)
00305 void DispCmdPolyLineArray::putdata(float *v, int n, VMDDisplayList *dobj) {
00306   void *ptr = dobj->append(DPOLYLINEARRAY, (1+3L*n)*sizeof(float));
00307   if (ptr == NULL)
00308     return;
00309   float *fltptr = (float *)ptr;
00310   *fltptr = (float)n;
00311   memcpy(fltptr+1, v, 3L*n*sizeof(float));
00312 }
00313 
00314 //*************************************************************
00315 // draw a triangle
00316 
00317 // set up the data for the DTRIANGLE drawing command
00318 void DispCmdTriangle::set_array(const float *p1,const float *p2,const float *p3,
00319   const float *n1, const float *n2, const float *n3, VMDDisplayList *dobj) {
00320   DispCmdTriangle *ptr = (DispCmdTriangle *)(dobj->append(DTRIANGLE, 
00321                                          sizeof(DispCmdTriangle)));
00322   if (ptr == NULL)
00323     return;
00324   memcpy(ptr->pos1, p1, 3L*sizeof(float)); 
00325   memcpy(ptr->pos2, p2, 3L*sizeof(float)); 
00326   memcpy(ptr->pos3, p3, 3L*sizeof(float)); 
00327   memcpy(ptr->norm1, n1, 3L*sizeof(float)); 
00328   memcpy(ptr->norm2, n2, 3L*sizeof(float)); 
00329   memcpy(ptr->norm3, n3, 3L*sizeof(float)); 
00330 }
00331 
00332 // put in new data, and put the command
00333 void DispCmdTriangle::putdata(const float *p1, const float *p2, 
00334                               const float *p3, VMDDisplayList *dobj) {
00335   int i;
00336   float tmp1[3], tmp2[3], tmp3[3];  // precompute the normal for
00337   for (i=0; i<3; i++) {             //   faster drawings later
00338      tmp1[i] = p2[i] - p1[i];
00339      tmp2[i] = p3[i] - p2[i];
00340   }
00341   cross_prod( tmp3, tmp1, tmp2);  
00342   vec_normalize(tmp3);
00343   set_array(p1, p2, p3, tmp3, tmp3, tmp3, dobj);
00344 }
00345 void DispCmdTriangle::putdata(const float *p1, const float *p2,const float *p3,
00346                               const float *n1, const float *n2,const float *n3,
00347                               VMDDisplayList *dobj) {
00348   set_array(p1,p2,p3,n1,n2,n3,dobj);
00349 }
00350 
00351 //*************************************************************
00352 
00353 // draw a square, given 3 of four points
00354 void DispCmdSquare::putdata(float *p1, float *p2,float *p3,VMDDisplayList *dobj) {
00355   DispCmdSquare *ptr = (DispCmdSquare *)(dobj->append(DSQUARE, 
00356                                          sizeof(DispCmdSquare)));
00357   if (ptr == NULL)
00358     return;
00359   int i;
00360   float tmp1[3], tmp2[3];           // precompute the normal for
00361   for (i=0; i<3; i++) {             //   faster drawings later
00362     tmp1[i] = p2[i] - p1[i];
00363     tmp2[i] = p3[i] - p2[i];
00364   }
00365   cross_prod(ptr->norml, tmp1, tmp2);  
00366   vec_normalize(ptr->norml);
00367 
00368   memcpy(ptr->pos1, p1, 3L*sizeof(float));
00369   memcpy(ptr->pos2, p2, 3L*sizeof(float));
00370   memcpy(ptr->pos3, p3, 3L*sizeof(float));
00371   for (i=0; i<3; i++)
00372     ptr->pos4[i] = p1[i] + tmp2[i];  // compute the fourth point
00373 }
00374 
00375 
00376 //*************************************************************
00377 // draw a mesh consisting of vertices, facets, colors, normals etc.
00378 void DispCmdTriMesh::putdata(const float * vertices,
00379                              const float * normals,
00380                              const float * colors,
00381                              int num_facets,
00382                              VMDDisplayList * dobj) {
00383   // make a triangle mesh (no strips)
00384   DispCmdTriMesh *ptr;
00385   if (colors == NULL) {
00386     ptr = (DispCmdTriMesh *) 
00387                 (dobj->append(DTRIMESH_C3F_N3F_V3F, sizeof(DispCmdTriMesh) +
00388                               sizeof(float) * num_facets * 3L * 6L));
00389   } else {
00390     ptr = (DispCmdTriMesh *) 
00391                 (dobj->append(DTRIMESH_C3F_N3F_V3F, sizeof(DispCmdTriMesh) +
00392                               sizeof(float) * num_facets * 3L * 9L));
00393   }
00394 
00395   if (ptr == NULL)
00396     return;
00397 
00398   ptr->numverts=num_facets * 3L;
00399   ptr->numfacets=num_facets;
00400 
00401   float *c=NULL, *n=NULL, *v=NULL;
00402   if (colors == NULL) {
00403     ptr->pervertexcolors=0;
00404     ptr->getpointers(n, v);
00405   } else {
00406     ptr->pervertexcolors=1;
00407     ptr->getpointers(c, n, v);
00408     memcpy(c, colors,   ptr->numverts * 3L * sizeof(float));
00409   }
00410 
00411   if (normals == NULL) {
00412     ptr->pervertexnormals=0;
00413     ptrdiff_t i;
00414     for (i=0; i<(num_facets * 9L); i+=9) {
00415       float tmp1[3], tmp2[3], tmpnorm[3];
00416       const float *v0 = &vertices[i  ];
00417       const float *v1 = &vertices[i+3];
00418       const float *v2 = &vertices[i+6];
00419 
00420       vec_sub(tmp1, v1, v0);
00421       vec_sub(tmp2, v2, v1);
00422       cross_prod(tmpnorm, tmp1, tmp2);
00423       vec_normalize(tmpnorm);
00424 
00425       n[i  ] = tmpnorm[0];
00426       n[i+1] = tmpnorm[1];
00427       n[i+2] = tmpnorm[2];
00428 
00429       n[i+3] = tmpnorm[0];
00430       n[i+4] = tmpnorm[1];
00431       n[i+5] = tmpnorm[2];
00432 
00433       n[i+6] = tmpnorm[0];
00434       n[i+7] = tmpnorm[1];
00435       n[i+8] = tmpnorm[2];
00436     }  
00437   } else {
00438     ptr->pervertexnormals=1;
00439     memcpy(n, normals,  ptr->numverts * 3L * sizeof(float));
00440   }
00441 
00442   memcpy(v, vertices, ptr->numverts * 3L * sizeof(float));
00443 }
00444 
00445 
00446 //*************************************************************
00447 // draw a mesh consisting of vertices, facets, colors, normals etc.
00448 void DispCmdTriMesh::putdata(const float * vertices,
00449                              const float * normals,
00450                              const unsigned char * colors,
00451                              int num_facets,
00452                              VMDDisplayList * dobj) {
00453   // make a triangle mesh (no strips)
00454   DispCmdTriMesh *ptr;
00455   if (colors == NULL) {
00456     ptr = (DispCmdTriMesh *) 
00457                 (dobj->append(DTRIMESH_C4U_N3F_V3F, sizeof(DispCmdTriMesh) +
00458                               sizeof(float) * num_facets * 3L * 6L));
00459   } else {
00460     ptr = (DispCmdTriMesh *) 
00461                 (dobj->append(DTRIMESH_C4U_N3F_V3F, sizeof(DispCmdTriMesh) +
00462                               4L * sizeof(unsigned char) * num_facets * 3L +
00463                               sizeof(float) * num_facets * 3L * 6L));
00464   }
00465 
00466   if (ptr == NULL)
00467     return;
00468 
00469   ptr->numverts=num_facets * 3L;
00470   ptr->numfacets=num_facets;
00471 
00472   unsigned char *c=NULL;
00473   float *n=NULL, *v=NULL;
00474   if (colors == NULL) {
00475     ptr->pervertexcolors=0;
00476     ptr->getpointers(n, v);
00477   } else {
00478     ptr->pervertexcolors=1;
00479     ptr->getpointers(c, n, v);
00480     memcpy(c, colors,   ptr->numverts * 4L * sizeof(unsigned char));
00481   }
00482 
00483   ptr->pervertexnormals=1;
00484   memcpy(n, normals,  ptr->numverts * 3L * sizeof(float));
00485   memcpy(v, vertices, ptr->numverts * 3L * sizeof(float));
00486 }
00487 
00488 
00489 //*************************************************************
00490 // draw a mesh consisting of vertices, facets, colors, normals etc.
00491 void DispCmdTriMesh::putdata(const float * vertices,
00492                              const char * normals,
00493                              const unsigned char * colors,
00494                              int num_facets,
00495                              VMDDisplayList * dobj) {
00496   // make a triangle mesh (no strips)
00497   DispCmdTriMesh *ptr;
00498   if (colors == NULL) {
00499     ptr = (DispCmdTriMesh *) 
00500                 (dobj->append(DTRIMESH_C4U_N3B_V3F, sizeof(DispCmdTriMesh) +
00501                               sizeof(char) * num_facets * 3L * 3L +
00502                               sizeof(float) * num_facets * 3L * 3L));
00503   } else {
00504     ptr = (DispCmdTriMesh *) 
00505                 (dobj->append(DTRIMESH_C4U_N3B_V3F, sizeof(DispCmdTriMesh) +
00506                               4L * sizeof(unsigned char) * num_facets * 3L +
00507                               sizeof(char) * num_facets * 3L * 3L +
00508                               sizeof(float) * num_facets * 3L * 3L));
00509   }
00510 
00511   if (ptr == NULL)
00512     return;
00513 
00514   ptr->numverts=num_facets * 3L;
00515   ptr->numfacets=num_facets;
00516 
00517   unsigned char *c=NULL;
00518   signed char *n=NULL;
00519   float *v=NULL;
00520   if (colors == NULL) {
00521     ptr->pervertexcolors=0;
00522     ptr->getpointers(n, v);
00523   } else {
00524     ptr->pervertexcolors=1;
00525     ptr->getpointers(c, n, v);
00526     memcpy(c, colors,   ptr->numverts * 4L * sizeof(unsigned char));
00527   }
00528 
00529   ptr->pervertexnormals=1;
00530   memcpy(n, normals,  ptr->numverts * 3L * sizeof(char));
00531   memcpy(v, vertices, ptr->numverts * 3L * sizeof(float));
00532 }
00533 
00534 
00535 // draw a mesh consisting of vertices, facets, colors, normals etc.
00536 void DispCmdTriMesh::putdata(const float * vertices,
00537                              const float * normals,
00538                              const float * colors,
00539                              int num_verts,
00540                              const int * facets,
00541                              int num_facets, 
00542                              int enablestrips,
00543                              VMDDisplayList * dobj) {
00544   int builtstrips = 0; 
00545 
00546 #if defined(VMDACTC) 
00547   if (enablestrips)  {
00548     // Rearrange face data into triangle strips
00549     ACTCData *tc = actcNew();  // intialize ACTC stripification library
00550     ptrdiff_t fsize = num_facets * 3L;
00551     ptrdiff_t i, ind, ii;
00552     ptrdiff_t iPrimCount = 0;
00553     ptrdiff_t iCurrPrimSize;
00554 
00555     // XXX over-allocate the vertex and facet buffers to prevent an
00556     //     apparent bug in ACTC 1.1 from crashing VMD.  This was causing
00557     //     Surf surfaces to crash ACTC at times.
00558     int *p_iPrimSize = new int[fsize + 6];  // num vertices in a primitive 
00559     unsigned int *f2 = new uint[fsize + 6];
00560     
00561     if (tc == NULL) {
00562       msgErr << "ACTC initialization failed, using triangle mesh." << sendmsg;
00563     } else {
00564       msgInfo << "Performing ACTC Triangle Consolidation..." << sendmsg;
00565  
00566       // only produce strips, not fans, give a ridiculously high min value.
00567       actcParami(tc, ACTC_OUT_MIN_FAN_VERTS, 2147483647);
00568 
00569       // disabling honoring vertex winding order might allow ACTC to
00570       // consolidate more triangles into strips, but this is only useful
00571       // if VMD has two-sided lighting enabled.
00572       // actcParami(tc, ACTC_OUT_HONOR_WINDING, ACTC_TRUE);
00573         
00574       // send triangle data over to ACTC library
00575       actcBeginInput(tc);
00576       for (ii=0; ii < num_facets; ii++) {
00577         ind = ii * 3L;
00578         if ((actcAddTriangle(tc, facets[ind], facets[ind + 1], facets[ind + 2])) != ACTC_NO_ERROR) {
00579           msgInfo << "ACTC Add Triangle Error." << sendmsg;
00580         }
00581       }
00582       actcEndInput(tc);
00583         
00584       // get triangle strips back from ACTC, loop through once to get sizes
00585       actcBeginOutput(tc);
00586       i = 0;
00587       while ((actcStartNextPrim(tc, &f2[i], &f2[i+1]) != ACTC_DATABASE_EMPTY)) {
00588         iCurrPrimSize = 2;  // if we're here, we got 2 vertices
00589         i+=2;               // increment array position
00590         while (actcGetNextVert(tc, &f2[i]) != ACTC_PRIM_COMPLETE) {
00591           iCurrPrimSize++;  // increment number of vertices for this primitive
00592           i++;              // increment array position
00593         }
00594 
00595         p_iPrimSize[iPrimCount] = iCurrPrimSize;  // save vertex count
00596         iPrimCount++;       // increment primitive counter
00597       }
00598       actcEndOutput(tc);
00599       msgInfo << "ACTC: Created " << iPrimCount << " triangle strips" << sendmsg;
00600       msgInfo << "ACTC: Average vertices per strip = " << i / iPrimCount  << sendmsg;
00601 
00602       // Draw triangle strips, uses double-sided lighting until we change
00603       // things to allow the callers to specify the desired lighting 
00604       // explicitly.
00605       DispCmdTriStrips::putdata(vertices, normals, colors, num_verts, p_iPrimSize, iPrimCount, f2, i, 1, dobj);
00606           
00607       // delete temporary memory
00608       delete [] f2;
00609       delete [] p_iPrimSize;
00610 
00611       // delete ACTC handle
00612       actcDelete(tc);
00613 
00614       builtstrips = 1; // don't generate a regular triangle mesh
00615     }  
00616   } 
00617 #endif
00618 
00619   if (!builtstrips) {
00620     // make a triangle mesh (no strips)
00621     DispCmdTriMesh *ptr = (DispCmdTriMesh *) 
00622                   (dobj->append(DTRIMESH_C4F_N3F_V3F, sizeof(DispCmdTriMesh) +
00623                                           sizeof(float) * num_verts * 10L +
00624                                           sizeof(int) * num_facets * 3L));
00625     if (ptr == NULL)
00626       return;
00627     ptr->pervertexcolors=1;
00628     ptr->pervertexnormals=1;
00629     ptr->numverts=num_verts;
00630     ptr->numfacets=num_facets;
00631     float *cnv;
00632     int *f;
00633     ptr->getpointers(cnv, f);
00634 
00635 #if 1
00636     ptrdiff_t ind10, ind3;
00637     for (ind10=0,ind3=0; ind10<num_verts*10L; ind10+=10,ind3+=3) {
00638       cnv[ind10    ] =   colors[ind3    ];
00639       cnv[ind10 + 1] =   colors[ind3 + 1]; 
00640       cnv[ind10 + 2] =   colors[ind3 + 2]; 
00641       cnv[ind10 + 3] =   1.0; 
00642       cnv[ind10 + 4] =  normals[ind3    ];
00643       cnv[ind10 + 5] =  normals[ind3 + 1];
00644       cnv[ind10 + 6] =  normals[ind3 + 2];
00645       cnv[ind10 + 7] = vertices[ind3    ];
00646       cnv[ind10 + 8] = vertices[ind3 + 1];
00647       cnv[ind10 + 9] = vertices[ind3 + 2];
00648     }
00649 #else
00650     ptrdiff_t i, ind, ind2;
00651     for (i=0; i<num_verts; i++) {
00652       ind = i * 10L;
00653       ind2 = i * 3L;
00654       cnv[ind    ] =   colors[ind2    ];
00655       cnv[ind + 1] =   colors[ind2 + 1]; 
00656       cnv[ind + 2] =   colors[ind2 + 2]; 
00657       cnv[ind + 3] =   1.0; 
00658       cnv[ind + 4] =  normals[ind2    ];
00659       cnv[ind + 5] =  normals[ind2 + 1];
00660       cnv[ind + 6] =  normals[ind2 + 2];
00661       cnv[ind + 7] = vertices[ind2    ];
00662       cnv[ind + 8] = vertices[ind2 + 1];
00663       cnv[ind + 9] = vertices[ind2 + 2];
00664     } 
00665 #endif
00666 
00667     memcpy(f, facets, ptr->numfacets * 3L * sizeof(int));
00668   }
00669 }
00670 
00671 //*************************************************************
00672 
00673 // draw a set of triangle strips
00674 void DispCmdTriStrips::putdata(const float * vertices,
00675                                const float * normals,
00676                                const float * colors,
00677                                int num_verts,
00678                                const int * verts_per_strip,
00679                                int num_strips,
00680                                const unsigned int * strip_data,
00681                                const int num_strip_verts,
00682                                int double_sided_lighting,
00683                                VMDDisplayList * dobj) {
00684 
00685   DispCmdTriStrips *ptr = (DispCmdTriStrips *) (dobj->append(DTRISTRIP, 
00686                                          sizeof(DispCmdTriStrips) +
00687                                          sizeof(int *) * num_strips +
00688                                          sizeof(float) * num_verts * 10L +
00689                                          sizeof(int) * num_strip_verts +
00690                                          sizeof(int) * num_strips));
00691   if (ptr == NULL) 
00692     return;
00693   ptr->numverts=num_verts;
00694   ptr->numstrips=num_strips;
00695   ptr->numstripverts=num_strip_verts;
00696   ptr->doublesided=double_sided_lighting;
00697 
00698   float *cnv;
00699   int *f;
00700   int *vertsperstrip;
00701   ptr->getpointers(cnv, f, vertsperstrip);
00702 
00703   // copy vertex,color,normal data
00704   ptrdiff_t i, ind, ind2;
00705   for (i=0; i<num_verts; i++) {
00706     ind = i * 10L;
00707     ind2 = i * 3L;
00708     cnv[ind    ] =   colors[ind2    ];
00709     cnv[ind + 1] =   colors[ind2 + 1];
00710     cnv[ind + 2] =   colors[ind2 + 2];
00711     cnv[ind + 3] =   1.0;
00712     cnv[ind + 4] =  normals[ind2    ];
00713     cnv[ind + 5] =  normals[ind2 + 1];
00714     cnv[ind + 6] =  normals[ind2 + 2];
00715     cnv[ind + 7] = vertices[ind2    ];
00716     cnv[ind + 8] = vertices[ind2 + 1];
00717     cnv[ind + 9] = vertices[ind2 + 2];
00718   }
00719 
00720   // copy vertices per strip data
00721   for (i=0; i<num_strips; i++) {
00722     vertsperstrip[i] = verts_per_strip[i];
00723   }
00724 
00725   // copy face (triangle) data
00726   for (i=0; i<num_strip_verts; i++) {
00727     f[i] = strip_data[i];
00728   }
00729 }
00730 
00731 
00732 //*************************************************************
00733 
00734 void DispCmdWireMesh::putdata(const float * vertices,
00735                              const float * normals,
00736                              const float * colors,
00737                              int num_verts,
00738                              const int * lines,
00739                              int num_lines, VMDDisplayList * dobj) {
00740  
00741   DispCmdWireMesh *ptr = (DispCmdWireMesh *) (dobj->append(DWIREMESH, 
00742                                          sizeof(DispCmdWireMesh) +
00743                                          sizeof(float) * num_verts * 10L +
00744                                          sizeof(int) * num_lines * 3L));
00745   if (ptr == NULL) 
00746     return;
00747   ptr->numverts=num_verts;
00748   ptr->numlines=num_lines;
00749 
00750   float *cnv;
00751   int *l;
00752   ptr->getpointers(cnv, l);
00753 
00754   ptrdiff_t i, ind, ind2;
00755   for (i=0; i<num_verts; i++) {
00756     ind = i * 10L;
00757     ind2 = i * 3L;
00758     cnv[ind    ] =   colors[ind2    ];
00759     cnv[ind + 1] =   colors[ind2 + 1]; 
00760     cnv[ind + 2] =   colors[ind2 + 2]; 
00761     cnv[ind + 3] =   1.0; 
00762     cnv[ind + 4] =  normals[ind2    ];
00763     cnv[ind + 5] =  normals[ind2 + 1];
00764     cnv[ind + 6] =  normals[ind2 + 2];
00765     cnv[ind + 7] = vertices[ind2    ];
00766     cnv[ind + 8] = vertices[ind2 + 1];
00767     cnv[ind + 9] = vertices[ind2 + 2];
00768   } 
00769 
00770   memcpy(l, lines, ptr->numlines * 2L * sizeof(int));
00771 }
00772 
00773 //*************************************************************
00774 // plot a cylinder at the given position
00775 // this is used to precalculate the cylinder data for speedup
00776 // in renderers without hardware cylinders.  For example, the GL
00777 // library.  There are res number of edges (with a norm, and two points)
00778 
00779 DispCmdCylinder::DispCmdCylinder(void) {
00780   lastres = 0;
00781 }
00782 
00783 void DispCmdCylinder::putdata(const float *pos1, const float *pos2, float rad, 
00784                       int res, int filled, VMDDisplayList *dobj) {
00785 
00786   float lenaxis[3];
00787   vec_sub(lenaxis, pos1, pos2);  // check that it's valid
00788   if (dot_prod(lenaxis,lenaxis) == 0.0 || res <= 0) return;
00789 
00790   if (lastres != res ) {
00791     rot[0] = cosf( (float) VMD_TWOPI / (float) res);
00792     rot[1] = sinf( (float) VMD_TWOPI / (float) res);
00793   }
00794   lastres = res;
00795   size_t size = (9L + res*3L*3L)*sizeof(float);
00796 
00797   float *pos = (float *)(dobj->append(DCYLINDER, size));
00798   if (pos == NULL) 
00799     return;
00800 
00801   memcpy(pos,   pos1, 3L*sizeof(float));
00802   memcpy(pos+3, pos2, 3L*sizeof(float));
00803   pos[6] = rad;
00804   pos[7] = (float)res;
00805   pos[8] = (float)filled;
00806 
00807   float axis[3];
00808   vec_sub(axis, pos1, pos2);
00809   vec_normalize(axis);
00810   int i;  // find an axis not aligned with the cylinder
00811   if (fabs(axis[0]) < fabs(axis[1]) &&
00812       fabs(axis[0]) < fabs(axis[2])) {
00813      i = 0;
00814   } else if (fabs(axis[1]) < fabs(axis[2])) {
00815      i = 1;
00816   } else {
00817      i = 2;
00818   }
00819   float perp[3];
00820   perp[i] = 0;                    // this is not aligned with the cylinder
00821   perp[(i+1)%3] = axis[(i+2)%3];
00822   perp[(i+2)%3] = -axis[(i+1)%3];
00823   vec_normalize(perp);
00824   float perp2[3];
00825   cross_prod(perp2, axis, perp); // find a normal to the cylinder
00826 
00827   float *posptr = pos+9;
00828   float m = rot[0], n = rot[1];
00829   for (int h=0; h<res; h++) {
00830     float tmp0, tmp1, tmp2;
00831     
00832     tmp0 = m*perp[0] + n*perp2[0]; // add the normal
00833     tmp1 = m*perp[1] + n*perp2[1];
00834     tmp2 = m*perp[2] + n*perp2[2];
00835 
00836     posptr[0] = tmp0; // add the normal
00837     posptr[1] = tmp1;
00838     posptr[2] = tmp2;
00839 
00840     posptr[3] = pos2[0] + rad * tmp0; // start
00841     posptr[4] = pos2[1] + rad * tmp1;
00842     posptr[5] = pos2[2] + rad * tmp2;
00843 
00844     posptr[6] = posptr[3] + lenaxis[0];  // and end of the edge
00845     posptr[7] = posptr[4] + lenaxis[1];
00846     posptr[8] = posptr[5] + lenaxis[2];
00847     posptr += 9;
00848     // use angle addition formulae:
00849     // cos(A+B) = cos A cos B - sin A sin B
00850     // sin(A+B) = cos A sin B + sin A cos B
00851     float mtmp = rot[0]*m - rot[1]*n;
00852     float ntmp = rot[0]*n + rot[1]*m; 
00853     m = mtmp;
00854     n = ntmp;
00855   }
00856 }
00857  
00858 
00859 #if defined(VMDOPTIXRTRT)
00860 //*************************************************************
00861 
00862 void DispCmdCylinderArray::putdata(const float * cylpoints,
00863                                    const float * cylradii,
00864                                    const float * cylcolors,
00865                                    int num_cyls, int cyl_res, int cyl_caps,
00866                                    VMDDisplayList * dobj) {
00867 
00868   DispCmdCylinderArray *ptr = (DispCmdCylinderArray *) dobj->append(DCYLINDERARRAY, 
00869                            sizeof(DispCmdCylinderArray) +
00870                            sizeof(float) * num_cyls * 6L +
00871                            sizeof(float) * num_cyls + 
00872                            sizeof(float) * num_cyls * 3L +
00873                            sizeof(int) * 3L);
00874   if (ptr == NULL)
00875     return;
00876   ptr->numcylinders = num_cyls;
00877   ptr->cylinderres = cyl_res;
00878   ptr->cylindercaps = cyl_caps;
00879 
00880   float *points;
00881   float *radii;
00882   float *colors;
00883   ptr->getpointers(points, radii, colors);
00884 
00885   memcpy(points, cylpoints, sizeof(float) * num_cyls * 6L);
00886   memcpy(radii, cylradii, sizeof(float) * num_cyls);
00887   memcpy(colors, cylcolors, sizeof(float) * num_cyls * 3L);
00888 }
00889 #endif
00890 
00891 
00892 //*************************************************************
00893 
00894 void DispCmdCone::putdata(const float *p1, const float *p2,
00895                           float newrad, float newrad2, int newres,
00896                           VMDDisplayList *dobj) {
00897   DispCmdCone *ptr = (DispCmdCone *)(dobj->append(DCONE, 
00898                                          sizeof(DispCmdCone)));
00899   if (ptr == NULL) 
00900     return;
00901   memcpy(ptr->pos1, p1, 3L*sizeof(float));
00902   memcpy(ptr->pos2, p2, 3L*sizeof(float));
00903   ptr->radius=newrad;
00904   ptr->radius2=newrad2;
00905   ptr->res=newres;
00906 }
00907 
00908 // put in new data, and put the command
00909 void DispCmdColorIndex::putdata(int newcol, VMDDisplayList *dobj) {
00910   DispCmdColorIndex *ptr = (DispCmdColorIndex *)(dobj->append(DCOLORINDEX, 
00911                                          sizeof(DispCmdColorIndex)));
00912   if (ptr == NULL) 
00913     return;
00914   ptr->color = newcol;
00915 }
00916 
00917 //*************************************************************
00918 
00919 // display text at the given text coordinates
00920 void DispCmdText::putdata(const float *c, const char *s, float thickness, 
00921                           float size, float ox, float oy, VMDDisplayList *dobj) {
00922   if (s != NULL) {
00923     size_t len = strlen(s)+1;
00924     char *buf = (char *)(dobj->append(DTEXT, len+7L*sizeof(float)));
00925     if (buf == NULL) 
00926       return;
00927     ((float *)buf)[0] = c[0];          // X
00928     ((float *)buf)[1] = c[1];          // Y
00929     ((float *)buf)[2] = c[2];          // Z
00930     ((float *)buf)[3] = thickness;     // thickness
00931     ((float *)buf)[4] = size;          // size
00932     ((float *)buf)[5] = ox;            // X offset
00933     ((float *)buf)[6] = oy;            // Y offset
00934     memcpy(buf+7L*sizeof(float),s,len); // text string
00935   }
00936 }
00937 
00938 //*************************************************************
00939 
00940 void DispCmdVolSlice::putdata(int mode, const float *pnormal, const float *verts, 
00941     const float *texs, VMDDisplayList *dobj) {
00942 
00943   DispCmdVolSlice *cmd = (DispCmdVolSlice *) dobj->append(DVOLSLICE, 
00944                                        sizeof(DispCmdVolSlice));
00945   if (cmd == NULL)
00946     return;
00947 
00948   cmd->texmode = mode;
00949   memcpy(cmd->normal, pnormal, 3L*sizeof(float));
00950   memcpy(cmd->v, verts, 12L*sizeof(float));
00951   memcpy(cmd->t, texs,  12L*sizeof(float));
00952 }
00953 
00954 //*************************************************************
00955 
00956 
00957 void DispCmdVolumeTexture::putdata(unsigned long texID, 
00958     const int size[3], unsigned char *texptr, const float pv0[3], 
00959     const float pv1[3], const float pv2[3], const float pv3[3], 
00960     VMDDisplayList *dobj) {
00961 
00962   DispCmdVolumeTexture *cmd = (DispCmdVolumeTexture *) dobj->append(DVOLUMETEXTURE,
00963       sizeof(DispCmdVolumeTexture));
00964 
00965   if (cmd == NULL) return;
00966 
00967   cmd->ID = texID;
00968   cmd->xsize = size[0];
00969   cmd->ysize = size[1];
00970   cmd->zsize = size[2];
00971   cmd->texmap = texptr;
00972   memcpy(cmd->v0, pv0, 3L*sizeof(float));
00973   memcpy(cmd->v1, pv1, 3L*sizeof(float));
00974   memcpy(cmd->v2, pv2, 3L*sizeof(float));
00975   memcpy(cmd->v3, pv3, 3L*sizeof(float));
00976 }
00977 
00978 //*************************************************************
00979 // put in new data, and put the command
00980 void DispCmdSphereRes::putdata(int newres, VMDDisplayList *dobj) {
00981   DispCmdSphereRes *ptr  = (DispCmdSphereRes *)dobj->append(DSPHERERES,
00982                            sizeof(DispCmdSphereRes));
00983   if (ptr == NULL)
00984     return;
00985   ptr->res = newres;
00986 }
00987 
00988 //*************************************************************
00989 
00990 // put in new data, and put the command
00991 void DispCmdSphereType::putdata(int newtype, VMDDisplayList *dobj) {
00992   DispCmdSphereType *ptr  = (DispCmdSphereType *)dobj->append(DSPHERETYPE,
00993                            sizeof(DispCmdSphereType));
00994   if (ptr == NULL)
00995     return;
00996   ptr->type = newtype;
00997 }
00998 
00999 //*************************************************************
01000 
01001 // put in new data, and put the command
01002 void DispCmdLineType::putdata(int newtype, VMDDisplayList *dobj) {
01003   DispCmdLineType* ptr  = (DispCmdLineType *)dobj->append(DLINESTYLE,
01004                            sizeof(DispCmdLineType));
01005   if (ptr == NULL)
01006     return;
01007   ptr->type = newtype;
01008 }
01009 
01010 //*************************************************************
01011 
01012 void DispCmdLineWidth::putdata(int newwidth, VMDDisplayList *dobj) {
01013   DispCmdLineWidth * ptr  = (DispCmdLineWidth *)dobj->append(DLINEWIDTH,
01014                            sizeof(DispCmdLineWidth));
01015   if (ptr == NULL)
01016     return;
01017   ptr->width = newwidth;
01018 }
01019 
01020 //*************************************************************
01021 
01022 // put in new data, and put the command
01023 void DispCmdPickPointArray::putdata(int num, int numsel, int firstsel, int *on, 
01024                                     float *coords, VMDDisplayList *dobj) {
01025   if (numsel < 1)
01026     return;
01027 
01028   DispCmdPickPointArray *ptr;
01029   if (num == numsel) {
01030     // if all indices in a contiguous block are enabled (e.g. "all" selection)
01031     // then there's no need to actually store the pick point indices
01032     ptr = (DispCmdPickPointArray *) (dobj->append(DPICKPOINT_ARRAY, 
01033                                      sizeof(DispCmdPickPointArray) +
01034                                      3L * sizeof(float) * numsel));
01035   } else {
01036     // if only some of the indices are selected, then we allocate storage
01037     // for the list of indices to be copied in.
01038     ptr = (DispCmdPickPointArray *) (dobj->append(DPICKPOINT_ARRAY, 
01039                                      sizeof(DispCmdPickPointArray) + 
01040                                      3L * sizeof(float) * numsel +
01041                                      sizeof(int) * numsel));
01042   }
01043 
01044   if (ptr == NULL)
01045     return;
01046 
01047   ptr->numpicks = numsel;
01048   ptr->firstindex = firstsel;
01049 
01050   float *crds;
01051   int *tags;
01052   if (num == numsel) {
01053     // if all indices are selected note it, copy in coords, and we're done.
01054     ptr->allselected = 1;
01055     ptr->getpointers(crds, tags);
01056     memcpy(crds, coords, 3L * sizeof(float) * numsel);
01057   } else {
01058     // if only some indices are selected, copy in the selected ones
01059     ptr->allselected = 0;
01060     ptr->getpointers(crds, tags);
01061 
01062     // copy tags for selected/enabled indices
01063     ptrdiff_t cnt=numsel; // early-exit as soon as we found the last selected atom
01064     ptrdiff_t i, cp;
01065     for (cp=0,i=0; cnt > 0; i++) {
01066       if (on[i]) {
01067         cnt--;
01068 
01069         ptrdiff_t idx = i*3L;
01070         ptrdiff_t idx2 = cp*3L;
01071         crds[idx2    ] = coords[idx    ];
01072         crds[idx2 + 1] = coords[idx + 1];
01073         crds[idx2 + 2] = coords[idx + 2];
01074 
01075         tags[cp] = i + firstsel;
01076 
01077         cp++;
01078       }
01079     }
01080   }
01081 }
01082 
01083 //*************************************************************
01084 
01085 // put in new data, and put the command
01086 void DispCmdPickPointArray::putdata(int num, int *indices,
01087                                     float *coords, VMDDisplayList *dobj) {
01088   DispCmdPickPointArray *ptr;
01089 
01090   ptr = (DispCmdPickPointArray *) (dobj->append(DPICKPOINT_ARRAY, 
01091                                    sizeof(DispCmdPickPointArray) + 
01092                                    3L * sizeof(float) * num +
01093                                    sizeof(int) * num));
01094 
01095   if (ptr == NULL)
01096     return;
01097 
01098   ptr->numpicks = num;
01099   ptr->allselected = 0; // use the index array entries
01100   ptr->firstindex = indices[0];
01101 
01102   float *crds;
01103   int *tags;
01104   ptr->getpointers(crds, tags);
01105   memcpy(crds, coords, num * 3L * sizeof(float));
01106   memcpy(tags, indices, num * sizeof(int));
01107 }
01108 

Generated on Thu Mar 28 02:43:05 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002