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

DrawMolItemRings.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2011 The Board of Trustees of the           
00004  *cr                        University of Illinois                       
00005  *cr                         All Rights Reserved                        
00006  *cr                                                                   
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: DrawMolItemRings.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.23 $       $Date: 2010/12/16 04:08:13 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *
00019  * Child Displayable component of a molecule; this is responsible for doing
00020  * the actual drawing of a molecule.  It contains an atom color, atom
00021  * selection, and atom representation object to specify how this component
00022  * should look.
00023  *
00024  ***************************************************************************/
00025 
00026 #ifdef VMDWITHCARBS
00027 
00028 #include "utilities.h"
00029 #include "DrawMolItem.h"
00030 #include "DrawMolecule.h"
00031 #include "DrawRingsUtils.h"
00032 #include <stdio.h>
00033 #include <math.h>
00034 
00035 void DrawMolItem::draw_rings_paperchain(float *framepos, float bipyramid_height, int maxringsize) {
00036   int i;
00037   SmallRing *ring;
00038 
00039   sprintf(commentBuffer,"MoleculeID: %d ReprID: %d Beginning PaperChain Rings",
00040           mol->id(), repNumber);
00041   cmdCommentX.putdata(commentBuffer, cmdList);
00042 
00043   mol->find_small_rings_and_links(mol->currentMaxPathLength, maxringsize);
00044     
00045   for (i=0; i < mol->smallringList.num(); i++) {
00046     ring = mol->smallringList[i];
00047     if (smallring_selected(*ring))
00048       paperchain_draw_ring(*ring,framepos,bipyramid_height);
00049   }
00050 }
00051 
00052 
00053 // Return true if all atoms in a ring are selected, false otherwise
00054 bool DrawMolItem::smallring_selected(SmallRing &ring) {
00055   int N = ring.num();
00056   int i;
00057     
00058   for (i=0; i<N; i++)
00059     if (!atomSel->on[ring[i]]) return false;
00060   return true;
00061 }
00062 
00063 
00064 // Return true if all atoms in a ring linkage path are selected, false otherwise
00065 bool DrawMolItem::linkagepath_selected(LinkagePath &path) {
00066   int N = path.num();
00067   int i;
00068 
00069   for (i=0; i<N; i++)
00070     if (!atomSel->on[path[i]]) return false;
00071   return true;
00072 }
00073 
00074 
00075 // Calculate the ring color
00076 void DrawMolItem::paperchain_get_ring_color(SmallRing &ring, float *framepos, float *rgb) {
00077 #if 0
00078   float vmin, vmax;
00079   atomColor->get_colorscale_minmax(&vmin, &vmax);
00080   if (!vmin && !vmax) {
00081     vmin = 0.0;
00082     vmax = 1.0;
00083   }
00084 
00085   hill_reilly_ring_colorscale(ring, framepos, vmin, vmax, scene, rgb);
00086 #elif 1
00087   hill_reilly_ring_color(ring, framepos, rgb);
00088 #else
00089   cremer_pople_ring_color(ring, framepos, rgb);
00090 #endif
00091 }
00092 
00093 
00094 void DrawMolItem::get_ring_centroid_and_normal(float *centroid, float *normal, SmallRing &ring, float *framepos) {
00095   int N = ring.num();
00096   int i, nexti;
00097   float curvec[3], nextvec[3];
00098 
00099   // initialize centroid and centroid normal
00100   centroid[0] = centroid[1] = centroid[2] = 0.0;
00101   normal[0] = normal[1] = normal[2] = 0.0;
00102 
00103   // calculate centroid and normal
00104   for (i=0; i<N; i++) {
00105     // calculate next ring position (wrapping as necessary)
00106     nexti = i+1;
00107     if (nexti >= N) 
00108       nexti = 0;
00109     
00110     vec_copy(curvec, framepos + 3*ring[i]);
00111     vec_copy(nextvec, framepos + 3*ring[nexti]);
00112         
00113     // update centroid
00114     vec_add(centroid, centroid, curvec);
00115     
00116     // update normal (this is Newell's method; see Carbohydra paper)
00117     normal[0] += (curvec[1] - nextvec[1]) * (curvec[2] + nextvec[2]); // (Y_i - Y_next_i) * (Z_i + Z_next_i)
00118     normal[1] += (curvec[2] - nextvec[2]) * (curvec[0] + nextvec[0]); // (Z_i - Z_next_i) * (X_i + X_next_i)
00119     normal[2] += (curvec[0] - nextvec[0]) * (curvec[1] + nextvec[1]); // (X_i - X_next_i) * (Y_i + Y_next_i)      
00120   }
00121 
00122   vec_scale(centroid, 1.0f/N, centroid);
00123   vec_normalize(normal);
00124 }
00125 
00126 
00127 void DrawMolItem::paperchain_draw_ring(SmallRing &ring, float *framepos, float bipyramid_height) {
00128   int N = ring.num(); // the number of atoms in the current ring
00129   int i, nexti;
00130   float centroid[3], normal[3], top[3], bottom[3], curvec[3], nextvec[3], x[3];
00131   float rgb[3];
00132 
00133   paperchain_get_ring_color(ring, framepos, rgb);
00134   get_ring_centroid_and_normal(centroid, normal, ring, framepos);
00135 
00136   // calculate top and bottom points
00137   vec_scale(x, 0.5f*bipyramid_height, normal);
00138   vec_add(top, centroid, x);
00139   vec_sub(bottom, centroid, x);
00140 
00141   append(DMATERIALON); // turn on lighting
00142 
00143 // XXX we should be looping over all of the rings
00144 //     within this routine rather than doing them separately,
00145 //     as we can generate one big triangle mesh from the results
00146 //     eliminating various sources of rendering overhead if we do it right.
00147 
00148 #if 1
00149   // draw triangles
00150   ResizeArray<float> vertices;
00151   ResizeArray<float> colors;
00152   ResizeArray<float> normals;
00153   ResizeArray<int>   facets;
00154 
00155   // add top/bottom vertices first
00156   vertices.append(top[0]);
00157   vertices.append(top[1]);
00158   vertices.append(top[2]);
00159   normals.append(normal[0]);
00160   normals.append(normal[1]);
00161   normals.append(normal[2]);
00162   colors.append(rgb[0]);
00163   colors.append(rgb[1]);
00164   colors.append(rgb[2]);
00165 
00166   vertices.append(bottom[0]);
00167   vertices.append(bottom[1]);
00168   vertices.append(bottom[2]);
00169   normals.append(normal[0]);
00170   normals.append(normal[1]);
00171   normals.append(normal[2]);
00172   colors.append(rgb[0]);
00173   colors.append(rgb[1]);
00174   colors.append(rgb[2]);
00175 
00176   // draw top half
00177   for (i=0; i<N; i++) {
00178     // calculate next ring position (wrapping as necessary)
00179     nexti = i+1;
00180     if (nexti >= N) nexti = 0;
00181     
00182     vec_copy(curvec, framepos + 3*ring[i]);
00183     vec_copy(nextvec, framepos + 3*ring[nexti]);
00184 
00185     vertices.append(curvec[0]);
00186     vertices.append(curvec[1]);
00187     vertices.append(curvec[2]);
00188 
00189     float normtop[3], tmp0[3], tmp1[3];
00190     vec_sub(tmp0, curvec, nextvec);
00191     vec_sub(tmp1, nextvec, top);
00192     cross_prod(normtop, tmp0, tmp1);
00193     vec_normalize(normtop);
00194     normals.append(normtop[0]);
00195     normals.append(normtop[1]);
00196     normals.append(normtop[2]);
00197 
00198     colors.append(rgb[0]);
00199     colors.append(rgb[1]);
00200     colors.append(rgb[2]);
00201 
00202     facets.append(2+i);     // curvec
00203     facets.append(2+nexti); // nextvec
00204     facets.append(0);       // top
00205   }
00206 
00207   // draw bottom half
00208   for (i=0; i<N; i++) {
00209     // calculate next ring position (wrapping as necessary)
00210     nexti = i+1;
00211     if (nexti >= N) nexti = 0;
00212     
00213     vec_copy(curvec, framepos + 3*ring[i]);
00214     vec_copy(nextvec, framepos + 3*ring[nexti]);
00215 
00216     vertices.append(curvec[0]);
00217     vertices.append(curvec[1]);
00218     vertices.append(curvec[2]);
00219 
00220     float normbot[3], tmp0[3], tmp1[3];
00221     vec_sub(tmp0, curvec, nextvec);
00222     vec_sub(tmp1, nextvec, bottom);
00223     cross_prod(normbot, tmp0, tmp1);
00224     vec_normalize(normbot);
00225     normals.append(normbot[0]);
00226     normals.append(normbot[1]);
00227     normals.append(normbot[2]);
00228 
00229     colors.append(rgb[0]);
00230     colors.append(rgb[1]);
00231     colors.append(rgb[2]);
00232 
00233     facets.append(2+N+i);     // curvec
00234     facets.append(2+N+nexti); // nextvec
00235     facets.append(1);         // bottom
00236   }
00237 
00238   // printf("TriMesh N: %d nvert: %d nface: %d  rgb[]=%0.2f,%0.2f,%0.2f\n", N, vertices.num()/3, facets.num()/3, rgb[0], rgb[1], rgb[2]);
00239 
00240   // draw the resulting triangle mesh
00241   cmdTriMesh.putdata(&vertices[0], &normals[0], &colors[0], vertices.num()/3, 
00242                      &facets[0], facets.num()/3, 0, cmdList);
00243 #else    
00244   // draw triangles
00245   for (i=0; i<N; i++) {
00246     // calculate next ring position (wrapping as necessary)
00247     nexti = i+1;
00248     if (nexti >= N) nexti = 0;
00249     
00250     vec_copy(curvec,framepos + 3*ring[i]);
00251     vec_copy(nextvec,framepos + 3*ring[nexti]);
00252 
00253     cmdTriangle.putdata(curvec, nextvec, top, cmdList);
00254     cmdTriangle.putdata(curvec, nextvec, bottom, cmdList);
00255   }
00256 #endif
00257 
00258 }
00259 
00260 
00261 void DrawMolItem::draw_rings_twister(float *framepos, int start_end_centroid, int hide_shared_links,
00262                                      int rib_steps, float rib_width, float rib_height,
00263                                      int maxringsize, int maxpathlength) {
00264   int i;
00265   LinkagePath *path;
00266   SmallRing *start_ring, *end_ring;
00267 
00268   sprintf (commentBuffer,"MoleculeID: %d ReprID: %d Beginning Twister Rings",
00269            mol->id(), repNumber);
00270   cmdCommentX.putdata(commentBuffer, cmdList);
00271 
00272   mol->find_small_rings_and_links(maxpathlength,maxringsize);
00273 
00274   append(DMATERIALOFF); // turn off lighting
00275 
00276   for (i=0; i < mol->smallringLinkages.paths.num(); i++) {
00277     path = mol->smallringLinkages.paths[i];
00278     start_ring = mol->smallringList[path->start_ring];
00279     end_ring = mol->smallringList[path->end_ring];
00280     
00281     if (linkagepath_selected(*path) && smallring_selected(*start_ring) && smallring_selected(*end_ring)) {
00282       if (!hide_shared_links || !mol->smallringLinkages.sharesLinkageEdges(*path))
00283         twister_draw_path(*path,framepos, start_end_centroid, rib_steps, rib_width, rib_height);
00284     }
00285   }
00286 }
00287 
00288 
00289 // XXX: Replace simple cubic spline with spline fitted through all
00290 //      atoms in the path.
00291 void DrawMolItem::twister_draw_path(LinkagePath &path, float *framepos, int start_end_centroid, int rib_steps, float rib_width, float rib_height) {
00292   SmallRing *start_ring = mol->smallringList[path.start_ring];
00293   SmallRing *end_ring = mol->smallringList[path.end_ring];
00294   float start_centroid[3], start_normal[3], end_centroid[3], end_normal[3]; // centroids and normals of start and end rings
00295   float start_pos[3], end_pos[3]; // postions of start and ending atoms
00296   float start_tangent[3], end_tangent[3]; // temporary vectors
00297   float start_rib[3], end_rib[3]; // ribbon start and end points
00298   float rib_interval, rib_inc; // ribbon interval and increment
00299   float splineA[3], splineB[3], splineC[3], splineD[3]; // spline co-efficients
00300   float tangentA[3], tangentB[3], tangentC[3], tangentD[3]; // tanget spline co-efficients
00301   float vectmp1[3], vectmp2[3], ftmp1, ftmp2, ftmp3;
00302   
00303   float min_axis_norm = 1e-4f; // Threshold to determine when we have a reliable rotation axis to rotate a frame about
00304   
00305   get_ring_centroid_and_normal(start_centroid, start_normal, *start_ring, framepos);
00306   get_ring_centroid_and_normal(end_centroid, end_normal, *end_ring, framepos);
00307   vec_copy(start_pos, framepos + 3*path[0]);
00308   vec_copy(end_pos, framepos + 3*path[path.num()-1]);
00309 
00310   vec_sub(start_tangent, start_pos, start_centroid);
00311   vec_scale(vectmp1,dot_prod(start_tangent, start_normal), start_normal);
00312   vec_sub(start_tangent, start_tangent, vectmp1);
00313   vec_normalize(start_tangent); 
00314 
00315   vec_sub(end_tangent, end_centroid, end_pos); // reversed direction for end tangent
00316   vec_scale(vectmp1,dot_prod(end_tangent, end_normal), end_normal);
00317   vec_sub(end_tangent, end_tangent, vectmp1);
00318   vec_normalize(end_tangent); 
00319 
00320   if (start_end_centroid == 1) {
00321     // move start and end points towards their centroid
00322     // and then onto the plane formed by the centroid and
00323     // the ring normal
00324     vec_add(start_rib, start_centroid, start_pos);
00325     vec_scale(start_rib, 0.5, start_rib);
00326     
00327     vec_sub(vectmp1, start_rib, start_centroid);
00328     vec_scale(vectmp1, dot_prod(vectmp1, start_normal), start_normal);
00329     vec_sub(start_rib, start_rib, vectmp1);
00330 
00331     vec_add(end_rib, end_centroid, end_pos);
00332     vec_scale(end_rib, 0.5, end_rib);
00333 
00334     vec_sub(vectmp1, end_rib, end_centroid);
00335     vec_scale(vectmp1, dot_prod(vectmp1, end_normal), end_normal);
00336     vec_sub(end_rib, end_rib, vectmp1);
00337   } else {
00338     vec_copy(start_rib, start_pos);
00339     vec_copy(end_rib, end_pos);
00340   }  
00341 
00342   // Use the smoothness-increasing interval length from "Mathematical Elements for Computer Graphics"
00343   rib_interval = distance(start_rib, end_rib);
00344   rib_inc = rib_interval / rib_steps;
00345 
00346   // Create ribbon spline
00347   ftmp1 = 1.0f / rib_interval;
00348 
00349   vec_zero(splineA);
00350   vec_sub(vectmp1, start_rib, end_rib);
00351   vec_scaled_add(splineA, 2.0f*ftmp1, vectmp1);
00352   vec_add(splineA, splineA, start_tangent);
00353   vec_add(splineA, splineA, end_tangent);
00354   vec_scale(splineA, ftmp1*ftmp1, splineA);
00355 
00356   vec_zero(splineB);
00357   vec_sub(vectmp1, end_rib, start_rib);
00358   vec_scaled_add(splineB, 3.0f*ftmp1, vectmp1);
00359   vec_scaled_add(splineB, -2.0f, start_tangent);
00360   vec_scaled_add(splineB, -1.0f, end_tangent);
00361   vec_scale(splineB, ftmp1, splineB);
00362 
00363   vec_copy(splineC, start_tangent);
00364   vec_copy(splineD, start_rib);
00365 
00366   // Create ribbon tangent spline
00367   vec_zero(tangentA);
00368   vec_scale(tangentB, 3.0f, splineA);
00369   vec_scale(tangentC, 2.0f, splineB);
00370   vec_copy(tangentD, splineC);
00371 
00372   // Construct reference frames along ribbon
00373   ResizeArray<RibbonFrame*> frames;
00374   RibbonFrame *frame, *prev_frame;
00375   
00376   // Initial frame
00377   frame = new RibbonFrame;
00378   vec_copy(frame->forward, start_tangent);
00379   cross_prod(frame->right, start_tangent, start_normal);
00380   vec_normalize(frame->right);
00381   cross_prod(frame->up, frame->right, start_tangent);
00382   vec_copy(frame->origin,start_rib);
00383   frame->arclength = 0.0f;
00384   frames.append(frame);
00385 
00386   // Initial estimates for frames
00387   float new_tangent[3] , rot_axis[3], axis_norm, rot_angle, t;
00388   int i;
00389 
00390   t = rib_inc;
00391   for (i=0; i < rib_steps; i++, t+= rib_inc) {
00392     prev_frame = frames[frames.num() - 1];
00393 
00394     ribbon_spline(new_tangent, tangentA, tangentB, tangentC, tangentD, t);
00395     vec_normalize(new_tangent);
00396 
00397     cross_prod(rot_axis, prev_frame->forward, new_tangent);
00398     axis_norm = norm(rot_axis);
00399 
00400     // copy previous frame
00401     frame = new RibbonFrame;
00402     vec_copy(frame->forward, prev_frame->forward);
00403     vec_copy(frame->right, prev_frame->right);
00404     vec_copy(frame->up, prev_frame->up);
00405     ribbon_spline(frame->origin, splineA, splineB, splineC, splineD, t);
00406     frame->arclength = prev_frame->arclength + distance(frame->origin, prev_frame->origin);
00407 
00408     // rotate frame if tangents not parallel
00409     if (axis_norm > min_axis_norm) {
00410       vec_normalize(rot_axis);
00411       rot_angle = acosf(dot_prod(prev_frame->forward, new_tangent));
00412       
00413       // Rotate frame angle rot_angle about rot_axis using Rodrigue's formula
00414       ftmp1 = cosf(rot_angle);
00415       ftmp2 = sinf(rot_angle);
00416       ftmp3 = 1.0f - ftmp1;
00417       
00418       vec_zero(vectmp1);
00419       vec_scaled_add(vectmp1, ftmp1, frame->forward);
00420       vec_scaled_add(vectmp1, ftmp3*dot_prod(rot_axis, frame->forward), rot_axis);
00421       cross_prod(vectmp2, rot_axis, frame->forward);
00422       vec_scaled_add(vectmp1, ftmp2, vectmp2);
00423       vec_copy(frame->forward, vectmp1);
00424       
00425       vec_zero(vectmp1);
00426       vec_scaled_add(vectmp1, ftmp1, frame->right);
00427       vec_scaled_add(vectmp1, ftmp3*dot_prod(rot_axis, frame->right), rot_axis);
00428       cross_prod(vectmp2, rot_axis, frame->right);
00429       vec_scaled_add(vectmp1, ftmp2, vectmp2);
00430       vec_copy(frame->right, vectmp1);
00431       
00432       vec_zero(vectmp1);
00433       vec_scaled_add(vectmp1, ftmp1, frame->up);
00434       vec_scaled_add(vectmp1, ftmp3*dot_prod(rot_axis, frame->up), rot_axis);
00435       cross_prod(vectmp2, rot_axis, frame->up);
00436       vec_scaled_add(vectmp1, ftmp2, vectmp2);
00437       vec_copy(frame->up, vectmp1);
00438     }
00439     
00440     frames.append(frame);
00441   }
00442 
00443   // calculate correct right axis for final frame and from that the correction angle
00444   float end_right[3], start_right[3], correction_angle, inc_angle, curr_angle;
00445 
00446   vec_copy(start_right, frames[0]->right);
00447   cross_prod(end_right, end_tangent, end_normal);
00448   vec_normalize(end_right);
00449     
00450   correction_angle = acosf(dot_prod(end_right, frames[frames.num()-1]->right));
00451   cross_prod(vectmp1, end_right, frames[frames.num()-1]->right);
00452   if (dot_prod(vectmp1, end_tangent) > 0) 
00453     correction_angle = -correction_angle;
00454   
00455   inc_angle = correction_angle / rib_steps;
00456   curr_angle = -inc_angle;
00457 
00458   // draw triangles
00459   ResizeArray<float> vertices;
00460   ResizeArray<float> colors;
00461   ResizeArray<float> normals;
00462   ResizeArray<int>   facets;
00463   int current_vertex_offset, next_vertex_offset;
00464 
00465   // XXX: Make these colours options in the GUI
00466   float top_color[3] = { 0.5f, 0.5f, 1.0f };
00467   float bottom_color[3] = { 0.9f, 0.9f, 0.9f };
00468 
00469   for (i=0; i <= rib_steps; i++) {
00470     frame = frames[i];
00471     curr_angle += inc_angle;
00472   
00473     // Apply correcting rotation:
00474     // Rotate frame angle curr_angle about frame->forward using Rodigue's formula
00475     ftmp1 = cosf(curr_angle);
00476     ftmp2 = sinf(curr_angle);
00477     ftmp3 = 1.0f - ftmp1;
00478       
00479     vec_zero(vectmp1);
00480     vec_scaled_add(vectmp1, ftmp1, frame->right);
00481     vec_scaled_add(vectmp1, ftmp3*dot_prod(frame->forward, frame->right), frame->forward);
00482     cross_prod(vectmp2, frame->forward, frame->right);
00483     vec_scaled_add(vectmp1, ftmp2, vectmp2);
00484     vec_copy(frame->right, vectmp1);
00485 
00486     vec_zero(vectmp1);
00487     vec_scaled_add(vectmp1, ftmp1, frame->up);
00488     vec_scaled_add(vectmp1, ftmp3*dot_prod(frame->forward, frame->up),frame->forward);
00489     cross_prod(vectmp2, frame->forward, frame->up);
00490     vec_scaled_add(vectmp1, ftmp2, vectmp2);
00491     vec_copy(frame->up, vectmp1);
00492 
00493     // vertices (of this frame's rectangle)
00494     vec_copy(vectmp1, frame->origin); // top right (index: +0)
00495     vec_scaled_add(vectmp1, rib_height, frame->up);
00496     vec_scaled_add(vectmp1, rib_width, frame->right);     
00497     vertices.append(vectmp1[0]);
00498     vertices.append(vectmp1[1]);
00499     vertices.append(vectmp1[2]);
00500     colors.append(top_color[0]);
00501     colors.append(top_color[1]);
00502     colors.append(top_color[2]);
00503     vec_add(vectmp1, frame->up, frame->right);
00504     vec_normalize(vectmp1);
00505     normals.append(vectmp1[0]);
00506     normals.append(vectmp1[1]);
00507     normals.append(vectmp1[2]);
00508 
00509     vec_copy(vectmp1, frame->origin); // bottom right (index: +1)
00510     vec_scaled_add(vectmp1, -rib_height, frame->up);
00511     vec_scaled_add(vectmp1, rib_width, frame->right);     
00512     vertices.append(vectmp1[0]);
00513     vertices.append(vectmp1[1]);
00514     vertices.append(vectmp1[2]);
00515     colors.append(bottom_color[0]);
00516     colors.append(bottom_color[1]);
00517     colors.append(bottom_color[2]);
00518     vec_sub(vectmp1, frame->right, frame->up);
00519     vec_normalize(vectmp1);
00520     normals.append(vectmp1[0]);
00521     normals.append(vectmp1[1]);
00522     normals.append(vectmp1[2]);
00523 
00524     vec_copy(vectmp1,frame->origin); // bottom left (index: +2)
00525     vec_scaled_add(vectmp1, -rib_height, frame->up);
00526     vec_scaled_add(vectmp1, -rib_width, frame->right);     
00527     vertices.append(vectmp1[0]);
00528     vertices.append(vectmp1[1]);
00529     vertices.append(vectmp1[2]);
00530     colors.append(bottom_color[0]);
00531     colors.append(bottom_color[1]);
00532     colors.append(bottom_color[2]);
00533     vec_add(vectmp1, frame->up, frame->right);
00534     vec_negate(vectmp1, vectmp1);
00535     vec_normalize(vectmp1);
00536     normals.append(vectmp1[0]);
00537     normals.append(vectmp1[1]);
00538     normals.append(vectmp1[2]);
00539 
00540     vec_copy(vectmp1,frame->origin); // top left (index: +3)
00541     vec_scaled_add(vectmp1, rib_height, frame->up);
00542     vec_scaled_add(vectmp1, -rib_width, frame->right);     
00543     vertices.append(vectmp1[0]);
00544     vertices.append(vectmp1[1]);
00545     vertices.append(vectmp1[2]);
00546     colors.append(top_color[0]);
00547     colors.append(top_color[1]);
00548     colors.append(top_color[2]);
00549     vec_sub(vectmp1, frame->up, frame->right);
00550     vec_normalize(vectmp1);
00551     normals.append(vectmp1[0]);
00552     normals.append(vectmp1[1]);
00553     normals.append(vectmp1[2]);
00554 
00555     // facets (between this frame's rectangle and the next's)
00556 
00557     if (i == rib_steps) 
00558       continue; // no facets for the last frame
00559 
00560     current_vertex_offset = i*4;
00561     next_vertex_offset = (i+1)*4;
00562 
00563     // top 1
00564     facets.append(current_vertex_offset + 0); // current, top right
00565     facets.append(next_vertex_offset + 0);    // next, top right
00566     facets.append(current_vertex_offset + 3); // current, top left
00567 
00568     // top 2
00569     facets.append(next_vertex_offset + 0);    // next, top right
00570     facets.append(next_vertex_offset + 3);    // next, top left
00571     facets.append(current_vertex_offset + 3); // current, top left
00572 
00573     // bottom 1 
00574     facets.append(current_vertex_offset + 1); // current, bottom right
00575     facets.append(current_vertex_offset + 2); // current, bottom left
00576     facets.append(next_vertex_offset + 1);    // next, bottom right
00577 
00578     // bottom 2
00579     facets.append(next_vertex_offset + 1);    // next, bottom right
00580     facets.append(current_vertex_offset + 2); // current, bottom left
00581     facets.append(next_vertex_offset + 2);    // next, bottom left
00582 
00583     // right 1
00584     facets.append(current_vertex_offset + 0); // current, top right
00585     facets.append(current_vertex_offset + 1); // current, bottom right
00586     facets.append(next_vertex_offset + 0);    // next, top right
00587 
00588     // right 2
00589     facets.append(next_vertex_offset + 0);    // next, top right
00590     facets.append(current_vertex_offset + 1); // current, bottom right
00591     facets.append(next_vertex_offset + 1);    // next, bottom right
00592 
00593     // left 1
00594     facets.append(current_vertex_offset + 3); // current, top left
00595     facets.append(next_vertex_offset + 3);    // next, top left
00596     facets.append(current_vertex_offset + 2); // current, bottom left
00597 
00598     // left 2
00599     facets.append(next_vertex_offset + 3);    // next, top left
00600     facets.append(next_vertex_offset + 2);    // next, bottom left
00601     facets.append(current_vertex_offset + 2); // current, bottom left
00602   }
00603 
00604   if (start_end_centroid == 1) {
00605     float first_atom[3];
00606 
00607     // Draw extensions of ribbon to meet hexagonal disks
00608     twister_draw_ribbon_extensions(vertices, colors, normals, facets,
00609                      start_centroid, start_normal, start_right, start_rib, rib_height, rib_width, top_color, bottom_color);
00610     twister_draw_ribbon_extensions(vertices, colors, normals, facets,
00611                      end_centroid, end_normal, end_right, end_rib, rib_height, rib_width, top_color, bottom_color);
00612 
00613     // Draw hexagonal disks for joining rings
00614     // XXX: do this only once per ring
00615     vec_copy(first_atom,framepos + 3*start_ring->first_atom());
00616     twister_draw_hexagon(vertices, colors, normals, facets,
00617                      start_centroid, start_normal, first_atom, rib_height, rib_width, top_color, bottom_color);
00618 
00619     vec_copy(first_atom,framepos + 3*end_ring->first_atom());
00620     twister_draw_hexagon(vertices, colors, normals, facets,
00621                      end_centroid, end_normal, first_atom, rib_height, rib_width, top_color, bottom_color);
00622   } else {
00623     // Draw start and end end caps
00624     // Start end caps
00625     current_vertex_offset = 0; 
00626 
00627     facets.append(current_vertex_offset + 3); // top left
00628     facets.append(current_vertex_offset + 0); // top right
00629     facets.append(current_vertex_offset + 1); // bottom right
00630     
00631     facets.append(current_vertex_offset + 2); // bottom left
00632     facets.append(current_vertex_offset + 1); // bottom right
00633     facets.append(current_vertex_offset + 3); // top left
00634 
00635     // End end caps
00636     current_vertex_offset = rib_steps*4;
00637 
00638     facets.append(current_vertex_offset + 3); // top left
00639     facets.append(current_vertex_offset + 0); // top right
00640     facets.append(current_vertex_offset + 1); // bottom right
00641     
00642     facets.append(current_vertex_offset + 2); // bottom left
00643     facets.append(current_vertex_offset + 1); // bottom right
00644     facets.append(current_vertex_offset + 3); // top left
00645   }
00646 
00647   // printf("TriMesh - frames: %d ; nvert: %d ; nface: %d\n", frames.num(), vertices.num()/3, facets.num()/3);
00648 
00649   // draw the resulting triangle mesh
00650   cmdTriMesh.putdata(&vertices[0], &normals[0], &colors[0], vertices.num()/3, 
00651                      &facets[0], facets.num()/3, 0, cmdList);
00652 }
00653 
00654 
00655 void DrawMolItem::twister_draw_ribbon_extensions(ResizeArray<float> &vertices, ResizeArray<float> &colors,
00656                                       ResizeArray<float> &normals, ResizeArray<int> &facets,
00657                                       float centroid[3], float normal[3], float right[3], float rib_point[3],
00658                                       float rib_height, float rib_width,
00659                                       float top_color[3], float bottom_color[3]) {
00660 
00661   float vectmp1[3], norm_tmp[3];
00662   float* color;
00663   int first_vertex = vertices.num()/3;  
00664 
00665   float* points[2] = { centroid, rib_point };
00666 
00667   float heights[2] = { rib_height, -rib_height };
00668   float updown[2] = { 1.0, -1.0 };
00669   float* side_colors[2] = { top_color, bottom_color };
00670 
00671   float widths[2] = { rib_width, -rib_width };
00672 
00673   // vertices
00674   for (int height=0; height<2; height++) {
00675     color = side_colors[height];
00676     vec_scale(norm_tmp, updown[height], normal);
00677 
00678     for (int point=0; point<2; point++) {
00679       for (int width=0; width<2; width++) {
00680         vec_copy(vectmp1, points[point]);
00681         vec_scaled_add(vectmp1, heights[height], normal);
00682         vec_scaled_add(vectmp1, width[widths], right);
00683         vertices.append(vectmp1[0]);
00684         vertices.append(vectmp1[1]);
00685         vertices.append(vectmp1[2]);
00686         colors.append(color[0]);
00687         colors.append(color[1]);
00688         colors.append(color[2]);
00689         normals.append(norm_tmp[0]);
00690         normals.append(norm_tmp[1]);
00691         normals.append(norm_tmp[2]);
00692       }
00693     }
00694   }
00695 
00696   // facets
00697   facets.append(first_vertex + 0); // right
00698   facets.append(first_vertex + 6);
00699   facets.append(first_vertex + 4);
00700 
00701   facets.append(first_vertex + 0);
00702   facets.append(first_vertex + 2);
00703   facets.append(first_vertex + 6);
00704 
00705   facets.append(first_vertex + 3); // top
00706   facets.append(first_vertex + 2);
00707   facets.append(first_vertex + 0);
00708 
00709   facets.append(first_vertex + 3);
00710   facets.append(first_vertex + 0);
00711   facets.append(first_vertex + 1);
00712 
00713   facets.append(first_vertex + 1); // left
00714   facets.append(first_vertex + 5);
00715   facets.append(first_vertex + 7);
00716 
00717   facets.append(first_vertex + 1);
00718   facets.append(first_vertex + 7);
00719   facets.append(first_vertex + 3);
00720 
00721   facets.append(first_vertex + 7); // bottom
00722   facets.append(first_vertex + 5);
00723   facets.append(first_vertex + 4);
00724 
00725   facets.append(first_vertex + 7);
00726   facets.append(first_vertex + 4);
00727   facets.append(first_vertex + 6);
00728 }
00729 
00730 
00731 void DrawMolItem::twister_draw_hexagon(ResizeArray<float> &vertices, ResizeArray<float> &colors, ResizeArray<float> &normals,
00732                                       ResizeArray<int> &facets, float centroid[3], float normal[3],
00733                                       float first_atom[3], float rib_height, float rib_width,
00734                                       float top_color[3], float bottom_color[3]) {
00735 
00736   float vectmp1[3];
00737   int top_centroid_offset, bottom_centroid_offset;
00738   int current_vertex = vertices.num()/3;
00739 
00740   // centroid vertices
00741   vec_copy(vectmp1, centroid); // top centroid vertex
00742   vec_scaled_add(vectmp1, rib_height, normal);
00743   vertices.append(vectmp1[0]);
00744   vertices.append(vectmp1[1]);
00745   vertices.append(vectmp1[2]);
00746   colors.append(top_color[0]);
00747   colors.append(top_color[1]);
00748   colors.append(top_color[2]);
00749   normals.append(normal[0]);
00750   normals.append(normal[1]);
00751   normals.append(normal[2]);
00752   top_centroid_offset = current_vertex++;
00753 
00754   vec_copy(vectmp1, centroid); // bottom centroid vertex
00755   vec_scaled_add(vectmp1, -rib_height, normal);
00756   vertices.append(vectmp1[0]);
00757   vertices.append(vectmp1[1]);
00758   vertices.append(vectmp1[2]);
00759   colors.append(bottom_color[0]);
00760   colors.append(bottom_color[1]);
00761   colors.append(bottom_color[2]);
00762   normals.append(-normal[0]);
00763   normals.append(-normal[1]);
00764   normals.append(-normal[2]);
00765   bottom_centroid_offset = current_vertex++;
00766 
00767   // vertices for hexagon edges
00768 
00769   const int polygon_n = 12;
00770   const float rot_angle = (float) VMD_TWOPI / polygon_n;
00771   const int first_edge_offset = current_vertex;
00772 
00773   float current_vec[3], polygon_point[3], vectmp2[3];
00774   float ftmp1, ftmp2, ftmp3;
00775 
00776   // set current_vec to component of (first_atom - centroid)
00777   // that is normal to the ring normal and then
00778   // scale up so that it's wider than the ribbon.
00779   vec_sub(current_vec, first_atom, centroid);
00780   vec_scale(vectmp1,dot_prod(current_vec, normal), normal);
00781   vec_sub(current_vec, current_vec, vectmp1);
00782   vec_normalize(current_vec);
00783   vec_scale(current_vec, (1.0f/cosf(rot_angle/2.0f))*rib_width, current_vec);
00784 
00785   for(int i=0;i<polygon_n;i++) {
00786     vec_add(polygon_point, centroid, current_vec);
00787     vec_copy(vectmp1, polygon_point); // top hexagon vertex
00788     vec_scaled_add(vectmp1, rib_height, normal);
00789     vertices.append(vectmp1[0]);
00790     vertices.append(vectmp1[1]);
00791     vertices.append(vectmp1[2]);
00792     colors.append(top_color[0]);
00793     colors.append(top_color[1]);
00794     colors.append(top_color[2]);
00795     normals.append(normal[0]);
00796     normals.append(normal[1]);
00797     normals.append(normal[2]);
00798     current_vertex++;
00799 
00800     vec_copy(vectmp1, polygon_point); // bottom hexagon vertex
00801     vec_scaled_add(vectmp1, -rib_height, normal);
00802     vertices.append(vectmp1[0]);
00803     vertices.append(vectmp1[1]);
00804     vertices.append(vectmp1[2]);
00805     colors.append(bottom_color[0]);
00806     colors.append(bottom_color[1]);
00807     colors.append(bottom_color[2]);
00808     normals.append(-normal[0]);
00809     normals.append(-normal[1]);
00810     normals.append(-normal[2]);
00811     current_vertex++;
00812 
00813     if (i == polygon_n-1) 
00814       break; // don't bother rotating the last time
00815 
00816     // Rotate current vec pi/3 radians about the ring normal using Rodrigue's formula
00817     ftmp1 = cosf(rot_angle);
00818     ftmp2 = sinf(rot_angle);
00819     ftmp3 = 1.0f - ftmp1;
00820       
00821     vec_zero(vectmp1);
00822     vec_scaled_add(vectmp1, ftmp1, current_vec);
00823     vec_scaled_add(vectmp1, ftmp3*dot_prod(normal, current_vec), normal);
00824     cross_prod(vectmp2, normal, current_vec);
00825     vec_scaled_add(vectmp1, ftmp2, vectmp2);
00826     vec_copy(current_vec, vectmp1);    
00827   }
00828 
00829   // facets
00830   int edge1_top, edge1_bottom, edge2_top, edge2_bottom;
00831   for(int j=0;j<polygon_n;j++) {
00832     edge1_top = first_edge_offset + j*2;
00833     edge1_bottom = edge1_top + 1;
00834     if (j<polygon_n-1) {
00835       edge2_top = edge1_top + 2;
00836       edge2_bottom = edge1_top + 3;
00837     }
00838     else {
00839       edge2_top = first_edge_offset;
00840       edge2_bottom = first_edge_offset + 1;
00841     }
00842   
00843     // top
00844     facets.append(top_centroid_offset);
00845     facets.append(edge1_top);
00846     facets.append(edge2_top);
00847    
00848     // bottom
00849     facets.append(bottom_centroid_offset);
00850     facets.append(edge2_bottom);
00851     facets.append(edge1_bottom);
00852     
00853     // outer edge
00854     facets.append(edge1_bottom);
00855     facets.append(edge2_bottom);
00856     facets.append(edge1_top);
00857 
00858     facets.append(edge1_top);
00859     facets.append(edge2_bottom);
00860     facets.append(edge2_top);
00861   }
00862 }
00863 
00864 
00865 
00866 #endif

Generated on Sat May 26 01:47:57 2012 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002