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

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

Generated on Fri Nov 8 02:44:34 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002