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 Tue Nov 18 02:47:06 2025 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002

AltStyle によって変換されたページ (->オリジナル) /