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