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: MoleculeGraphics.C,v $ 00013 * $Author: johns $ $Locker: $ $State: Exp $ 00014 * $Revision: 1.89 $ $Date: 2021年12月21日 05:59:15 $ 00015 * 00016 *************************************************************************** 00017 * DESCRIPTION: 00018 * Manages a list of graphics objects. They can be queried and modified. 00019 * This is for use by the text interface (and perhaps others). 00020 * 00021 ***************************************************************************/ 00022 00023 #include <stdio.h> 00024 #include "MoleculeGraphics.h" 00025 #include "DispCmds.h" 00026 #include "VMDApp.h" 00027 #include "Inform.h" 00028 #include "JString.h" 00029 #include "Scene.h" 00030 #include "utilities.h" 00031 00032 void MoleculeGraphics::create_cmdlist(void) { 00033 reset_disp_list(); 00034 // set the default values 00035 DispCmdTriangle triangle; 00036 DispCmdCylinder cylinder; 00037 DispCmdPoint point; 00038 DispCmdLine line; 00039 DispCmdCone cone; 00040 DispCmdColorIndex color; 00041 DispCmdLineType linetype; 00042 DispCmdLineWidth linewidth; 00043 DispCmdSphere sphere; 00044 DispCmdSphereRes sph_res; 00045 //DispCmdComment comment; 00046 00047 append(DMATERIALON); 00048 color.putdata(0, cmdList); // use the first color by default (blue) 00049 int last_res = -1; // default sphere resolution 00050 00051 int last_line = ::SOLIDLINE; // default for lines 00052 linetype.putdata(last_line, cmdList); // solid and 00053 int last_width = 1; 00054 linewidth.putdata(last_width, cmdList); // of width 1 00055 00056 ResizeArray<float> pickpointcoords; 00057 ResizeArray<int> pickpointindices; 00058 00059 // go down the list and draw things 00060 int num = num_elements(); 00061 ShapeClass *shape; 00062 int sidx=0; 00063 while (sidx<num) { 00064 shape = &(shapes[sidx]); 00065 00066 switch (shape->shape) { 00067 case NONE: { 00068 break; 00069 } 00070 00071 case POINT: { 00072 append(DMATERIALOFF); 00073 point.putdata(shape->data+0, cmdList); 00074 append(DMATERIALON); 00075 break; 00076 } 00077 00078 case PICKPOINT: 00079 pickpointcoords.append3(shape->data); 00080 pickpointindices.append((int)shape->data[3]); 00081 break; 00082 00083 case LINE: { 00084 append(DMATERIALOFF); 00085 int style = int(shape->data[6]); 00086 int width = int(shape->data[7]); 00087 if (style != last_line) { 00088 linetype.putdata(style, cmdList); 00089 last_line = style; 00090 } 00091 if (width != last_width) { 00092 linewidth.putdata(width, cmdList); 00093 last_width = width; 00094 } 00095 line.putdata(shape->data+0, shape->data+3, cmdList); 00096 append(DMATERIALON); 00097 break; 00098 } 00099 00100 case TRIANGLE: { 00101 ResizeArray<float> triangle_vert_buffer; 00102 int tricount=0; 00103 while ((sidx<num) && (tricount < 50000000) && (shape->shape == TRIANGLE)) { 00104 triangle_vert_buffer.append9(&shape->data[0]); 00105 tricount++; 00106 sidx++; // go to the next shape/object 00107 shape = &(shapes[sidx]); 00108 } 00109 sidx--; // correct count prior to outer loop increment 00110 00111 int cnt = triangle_vert_buffer.num() / 9; 00112 if (cnt > 0) { 00113 DispCmdTriMesh::putdata(&triangle_vert_buffer[0], (float *) NULL, 00114 (float *) NULL, cnt, cmdList); 00115 } 00116 break; 00117 } 00118 00119 case TRINORM: { 00120 triangle.putdata(shape->data+0, shape->data+3 , shape->data+6, 00121 shape->data+9, shape->data+12, shape->data+15, cmdList); 00122 break; 00123 } 00124 00125 case TRICOLOR: { 00126 // compute rgb colors from indices 00127 float colors[9]; 00128 for (int i=0; i<3; i++) { 00129 int c = (int)shape->data[18+i]; 00130 c = clamp_int(c, 0, MAXCOLORS-1); 00131 vec_copy(colors+3L*i, scene->color_value(c)); 00132 } 00133 const float *verts = shape->data+0; 00134 const float *norms = shape->data+9; 00135 int facets[3] = { 0,1,2 }; 00136 DispCmdTriMesh::putdata(verts, norms, colors, 3, facets, 1, 0, cmdList); 00137 } 00138 break; 00139 00140 case CYLINDER: { 00141 cylinder.putdata(shape->data+0, shape->data+3, shape->data[6], 00142 int(shape->data[7]), 00143 (int (shape->data[8])) ? 00144 CYLINDER_TRAILINGCAP | CYLINDER_LEADINGCAP : 0, 00145 cmdList); 00146 break; 00147 } 00148 00149 case CONE: { 00150 cone.putdata(shape->data+0, shape->data+3, shape->data[6], 00151 shape->data[8], int(shape->data[7]), cmdList); 00152 break; 00153 } 00154 00155 case TEXT: { 00156 append(DMATERIALOFF); 00157 DispCmdText text; 00158 text.putdata(shape->data, shapetext[(int)shape->data[5]], shape->data[4], shape->data[3], 0, 0, cmdList); 00159 append(DMATERIALON); 00160 break; 00161 } 00162 00163 case SPHERETUBE: { 00164 if (!shape->extradata) 00165 break; 00166 00167 const int numcoords = int(shape->data[0]); 00168 const int numradii = int(shape->data[1]); 00169 const float defradius = shape->data[2]; 00170 // const int numcolors = shape->data[3]); 00171 const int drawtubes = int(shape->data[4]); 00172 const int res = int(shape->data[5]); 00173 00174 #if 0 00175 printf("***** spheretube draw: coords %d rads %d defrad %f cols %d tubes %d res %d\n", 00176 numcoords, numradii, defradius, numcolors, drawtubes, res); 00177 #endif 00178 00179 const int coordsz = numcoords * 3; 00180 const int colorsz = numcoords * 3; // we MUST provide per-sphere colors 00181 const float *xyz3fv = (float *) shape->extradata; 00182 const float *rgb3fv = xyz3fv + coordsz; 00183 const float *radii1fv = xyz3fv + coordsz + colorsz; 00184 00185 // use either a constant color for all spheres, or use a 00186 // color-per-sphere 00187 float *colors = NULL; 00188 float *tmpradii = NULL; 00189 const float *useradii = NULL; 00190 if ((numradii > 1) && (numradii == numcoords)) { 00191 useradii = radii1fv; 00192 // printf("** using radii array radii[0] = %g\n", useradii[0]); 00193 } else { 00194 // printf("** defradius: %f\n", defradius); 00195 tmpradii = new float[numradii]; 00196 for (int i=0; i<numcoords; i++) { 00197 tmpradii[i] = defradius; 00198 } 00199 useradii = tmpradii; 00200 // printf("** using defradius radii[0] = %g\n", useradii[0]); 00201 } 00202 00203 DispCmdSphereArray cmdSphereArray; 00204 cmdSphereArray.putdata(xyz3fv, 00205 useradii, 00206 rgb3fv, 00207 numcoords, 00208 res, 00209 cmdList); 00210 00211 // optionally draw interconnecting tubes 00212 if (drawtubes) { 00213 // if tubes have varying radii, we must draw cones 00214 int i,j; 00215 for (i=0,j=0; i<(numcoords-1); i++,j+=3) { 00216 // XXX we don't handle color-per sphere yet 00217 cone.putdata(xyz3fv+j, xyz3fv+j+3, 00218 useradii[i], useradii[i+1], res, cmdList); 00219 } 00220 } 00221 00222 delete [] tmpradii; 00223 delete [] colors; 00224 break; 00225 } 00226 00227 00228 #if 0 00229 // these aren't supported yet 00230 case DBEGINREPGEOMGROUP: { 00231 char *s = (char *) (shape); 00232 beginrepgeomgroup.putdata(s,cmdList); 00233 break; 00234 } 00235 00236 case DCOMMENT: { 00237 char *s = (char *) (shape); 00238 comment.putdata(s,cmdList); 00239 break; 00240 } 00241 #endif 00242 00243 case SPHERE: { 00244 int res = int (shape->data[4]); 00245 if (res != last_res) { 00246 sph_res.putdata(res, cmdList); 00247 last_res = res; 00248 } 00249 sphere.putdata(shape->data+0, shape->data[3], cmdList); 00250 break; 00251 } 00252 00253 case MATERIALS: { 00254 if (shape->data[0] == 0) append(DMATERIALOFF); 00255 else append(DMATERIALON); 00256 break; 00257 } 00258 00259 case MATERIAL: { 00260 const float *data = shape->data; 00261 cmdList->ambient = data[0]; 00262 cmdList->specular = data[1]; 00263 cmdList->diffuse = data[2]; 00264 cmdList->shininess = data[3]; 00265 cmdList->mirror = data[4]; 00266 cmdList->opacity = data[5]; 00267 cmdList->outline = data[6]; 00268 cmdList->outlinewidth = data[7]; 00269 cmdList->transmode = data[8]; 00270 cmdList->materialtag = (int)data[9]; 00271 break; 00272 } 00273 00274 case COLOR: { 00275 color.putdata(int(shape->data[0]), cmdList); 00276 break; 00277 } 00278 00279 default: 00280 msgErr << "Sorry, can't draw that" << sendmsg; 00281 } 00282 00283 sidx++; // go to the next shape/object 00284 } 00285 00286 // draw the pickpoints if we have any 00287 if (pickpointindices.num() > 0) { 00288 DispCmdPickPointArray pickPointArray; 00289 pickPointArray.putdata(pickpointindices.num(), &pickpointindices[0], 00290 &pickpointcoords[0], cmdList); 00291 } 00292 00293 needRegenerate = 0; // cmdlist has been udpated 00294 } 00295 00296 00297 // resets the {next,max}_{id,index} values after something is added 00298 // returns the value of the new element 00299 int MoleculeGraphics::added(void) { 00300 needRegenerate = 1; 00301 next_index = shapes.num(); 00302 int retval = next_id; 00303 if (next_id == max_id) { // this was a new shape 00304 max_id++; 00305 } 00306 next_id = max_id; 00307 return retval; 00308 } 00309 00310 00311 int MoleculeGraphics::add_triangle(const float *x1, const float *x2, const float *x3) { 00312 // save the points 00313 ShapeClass s(TRIANGLE, 9, next_id); 00314 float *data = s.data; 00315 vec_copy(data+0, x1); 00316 vec_copy(data+3, x2); 00317 vec_copy(data+6, x3); 00318 00319 // new one goes at next_id 00320 if (next_index < num_elements()) 00321 shapes[next_index] = s; 00322 else 00323 shapes.append(s); 00324 return added(); 00325 } 00326 00327 00328 int MoleculeGraphics::add_trinorm(const float *x1, const float *x2, const float *x3, 00329 const float *n1, const float *n2, const float *n3) { 00330 // save the points 00331 ShapeClass s(TRINORM, 18, next_id); 00332 float *data = s.data; 00333 vec_copy(data+ 0, x1); 00334 vec_copy(data+ 3, x2); 00335 vec_copy(data+ 6, x3); 00336 00337 vec_copy(data+ 9, n1); 00338 vec_normalize(data+ 9); // normalize this normal to prevent problems later 00339 vec_copy(data+12, n2); 00340 vec_normalize(data+12); // normalize this normal to prevent problems later 00341 vec_copy(data+15, n3); 00342 vec_normalize(data+15); // normalize this normal to prevent problems later 00343 00344 // new one goes at next_id 00345 if (next_index < num_elements()) 00346 shapes[next_index] = s; 00347 else 00348 shapes.append(s); 00349 00350 return added(); 00351 } 00352 00353 00354 int MoleculeGraphics::add_tricolor(const float *x1, const float *x2, const float *x3, 00355 const float *n1, const float *n2, const float *n3, int c1, int c2, 00356 int c3) { 00357 ShapeClass s(TRICOLOR, 21, next_id); 00358 float *data = s.data; 00359 vec_copy(data+ 0, x1); 00360 vec_copy(data+ 3, x2); 00361 vec_copy(data+ 6, x3); 00362 00363 vec_copy(data+ 9, n1); 00364 vec_normalize(data+ 9); // normalize this normal to prevent problems later 00365 vec_copy(data+12, n2); 00366 vec_normalize(data+12); // normalize this normal to prevent problems later 00367 vec_copy(data+15, n3); 00368 vec_normalize(data+15); // normalize this normal to prevent problems later 00369 00370 data[18] = (float)c1; 00371 data[19] = (float)c2; 00372 data[20] = (float)c3; 00373 00374 // new one goes at next_id 00375 if (next_index < num_elements()) 00376 shapes[next_index] = s; 00377 else 00378 shapes.append(s); 00379 00380 return added(); 00381 } 00382 00383 00384 int MoleculeGraphics::add_point(const float *x) { 00385 ShapeClass s(POINT, 3, next_id); 00386 float *data = s.data; 00387 vec_copy(data+0, x); 00388 00389 if (next_index < num_elements()) 00390 shapes[next_index] = s; 00391 else 00392 shapes.append(s); 00393 00394 return added(); 00395 } 00396 00397 int MoleculeGraphics::add_pickpoint(const float *x) { 00398 ShapeClass s(PICKPOINT, 4, next_id); 00399 float *data = s.data; 00400 vec_copy(data+0, x); 00401 data[3] = (float) next_index; // this will break for anything >= 2^24 00402 00403 if (next_index < num_elements()) 00404 shapes[next_index] = s; 00405 else 00406 shapes.append(s); 00407 00408 return added(); 00409 } 00410 00411 int MoleculeGraphics::add_line(const float *x1, const float *x2, int style, int width) { 00412 ShapeClass s(LINE, 8, next_id); 00413 float *data = s.data; 00414 vec_copy(data+0, x1); 00415 vec_copy(data+3, x2); 00416 data[6] = float(style) + 0.1f; 00417 data[7] = float(width) + 0.1f; 00418 if (next_index < num_elements()) 00419 shapes[next_index] = s; 00420 else 00421 shapes.append(s); 00422 return added(); 00423 } 00424 00425 00426 int MoleculeGraphics::add_cylinder(const float *x1, const float *x2, float rad, 00427 int n, int filled) { 00428 ShapeClass s(CYLINDER, 9, next_id); 00429 float *data = s.data; 00430 vec_copy(data+0, x1); 00431 vec_copy(data+3, x2); 00432 data[6] = rad; 00433 data[7] = float(n) + 0.1f; 00434 data[8] = float(filled) + 0.1f; 00435 00436 // new one goes at next_id 00437 if (next_index < num_elements()) 00438 shapes[next_index] = s; 00439 else 00440 shapes.append(s); 00441 return added(); 00442 } 00443 00444 00445 int MoleculeGraphics::add_cone(const float *x1, const float *x2, float rad, float radsq, int n) { 00446 // save the points 00447 ShapeClass s(CONE, 9, next_id); 00448 float *data = s.data; 00449 vec_copy(data+0, x1); 00450 vec_copy(data+3, x2); 00451 data[6] = rad; 00452 data[7] = float(n) + 0.1f; 00453 data[8] = radsq; 00454 00455 // new one goes at next_id 00456 if (next_index < num_elements()) 00457 shapes[next_index] = s; 00458 else 00459 shapes.append(s); 00460 return added(); 00461 } 00462 00463 00464 int MoleculeGraphics::add_sphere(const float *x, float rad, int n) { 00465 ShapeClass s(SPHERE, 5, next_id); 00466 float *data = s.data; 00467 vec_copy(data+0, x); 00468 data[3] = rad; 00469 data[4] = float(n) + 0.1f; 00470 00471 // new one goes at next_id 00472 if (next_index < num_elements()) 00473 shapes[next_index] = s; 00474 else 00475 shapes.append(s); 00476 return added(); 00477 } 00478 00479 00480 int MoleculeGraphics::add_text(const float *x, const char *text, 00481 float size, float thickness) { 00482 ShapeClass s(TEXT, 6, next_id); 00483 float *data = s.data; 00484 vec_copy(data+0, x); 00485 data[3] = size; 00486 data[4] = thickness; 00487 data[5] = (float)shapetext.num(); // index where the text will be stored 00488 shapetext.append(stringdup(text)); 00489 if (next_index < num_elements()) 00490 shapes[next_index] = s; 00491 else 00492 shapes.append(s); 00493 return added(); 00494 } 00495 00496 00497 int MoleculeGraphics::add_spheretube(const int numcoords, const float *xyz3fv, 00498 const int numradii, const float *radii1fv, 00499 const int numcolors, 00500 const float *rgb3fv, const int *colorids, 00501 int drawtubes, int res) { 00502 ShapeClass s(SPHERETUBE, 6, next_id); 00503 float *data = s.data; 00504 data[0] = float(numcoords); 00505 data[1] = float(numradii); 00506 data[2] = radii1fv[0]; // if numradii == 1, then this is the global radius 00507 data[3] = float(numcolors); // if numcolors == 0, we pack a 1-color array 00508 data[4] = float(drawtubes); 00509 data[5] = float(res); 00510 00511 // store bulk coordinates in an attached memory buffer 00512 const int coordsz = numcoords * 3; 00513 const int colorsz = numcoords * 3; // we MUST provide per-sphere colors 00514 float *tmp = (float *) malloc((coordsz + colorsz + numradii) * sizeof(float)); 00515 memcpy(tmp, xyz3fv, coordsz * sizeof(float)); 00516 00517 // we must provide full color-per-sphere data presently 00518 if (numcolors < numcoords) { 00519 // use last draw color state, copied to buffer of elements 00520 const float *tc = scene->color_value(colorID); 00521 for (int i=0; i<colorsz; i+=3) { 00522 vec_copy(tmp+coordsz + i, tc); 00523 } 00524 } else { 00525 if (rgb3fv != NULL) { 00526 memcpy(tmp+coordsz, rgb3fv, colorsz * sizeof(float)); 00527 } if (colorids != NULL) { 00528 for (int i=0; i<numcolors; i++) { 00529 int c = colorids[i]; 00530 c = clamp_int(c, 0, MAXCOLORS-1); 00531 vec_copy(tmp+coordsz + i*3, scene->color_value(c)); 00532 } 00533 } 00534 } 00535 00536 memcpy(tmp+coordsz+colorsz, radii1fv, numradii * sizeof(float)); 00537 s.extradata = tmp; 00538 00539 // new one goes at next_id 00540 if (next_index < num_elements()) 00541 shapes[next_index] = s; 00542 else 00543 shapes.append(s); 00544 return added(); 00545 } 00546 00547 00548 int MoleculeGraphics::use_materials(int yes_no) { 00549 ShapeClass s(MATERIALS, 1, next_id); 00550 float *data = s.data; 00551 data[0] = (float) yes_no; 00552 if (next_index < num_elements()) 00553 shapes[next_index] = s; 00554 else 00555 shapes.append(s); 00556 return added(); 00557 } 00558 00559 00560 int MoleculeGraphics::use_material(const Material *mat) { 00561 ShapeClass s(MATERIAL, 10, next_id); 00562 float *data = s.data; 00563 data[0] = mat->ambient; 00564 data[1] = mat->specular; 00565 data[2] = mat->diffuse; 00566 data[3] = mat->shininess; 00567 data[4] = mat->mirror; 00568 data[5] = mat->opacity; 00569 data[6] = mat->outline; 00570 data[7] = mat->outlinewidth; 00571 data[8] = mat->transmode; 00572 data[9] = (float)mat->ind; 00573 00574 if (next_index < num_elements()) 00575 shapes[next_index] = s; 00576 else 00577 shapes.append(s); 00578 return added(); 00579 } 00580 00581 00582 // do this based on the index 00583 int MoleculeGraphics::use_color(int index) { 00584 colorID = index; // record most recently set color index 00585 00586 ShapeClass s(COLOR, 1, next_id); 00587 float *data = s.data; 00588 data[0] = float(index) + 0.1f; // just to be on the safe side for rounding 00589 if (next_index < num_elements()) 00590 shapes[next_index] = s; 00591 else 00592 shapes.append(s); 00593 return added(); 00594 } 00595 00596 00597 // return the index in the array, or -1 if it doesn't exist 00598 int MoleculeGraphics::index_id(int find_id) { 00599 // the values in the array are numerically increasing, so I can do 00600 // a binary search. 00601 int max_loc = num_elements()-1; 00602 int min_loc = 0; 00603 if (max_loc < min_loc) { 00604 return -1; 00605 } 00606 int loc = (max_loc + min_loc) / 2; 00607 int id = shapes[loc].id; 00608 while (id != find_id && min_loc < max_loc) { 00609 if (id < find_id) { 00610 min_loc = loc+1; 00611 } else { 00612 max_loc = loc-1; 00613 } 00614 loc = (max_loc + min_loc) / 2; 00615 if (loc < 0) break; 00616 id = shapes[loc].id; 00617 } 00618 // and make sure it is for real 00619 if (id == find_id && shapes[loc].shape != NONE) { 00620 return loc; 00621 } 00622 return -1; // not found 00623 } 00624 00625 00626 // delete everything 00627 void MoleculeGraphics::delete_all(void) { 00628 shapes.clear(); 00629 delete_shapetext(); // since there are no references to it now 00630 delete_count = 0; // and reset the internal variables 00631 next_index = 0; 00632 next_id = 0; 00633 max_id = 0; 00634 needRegenerate = 1; 00635 } 00636 00637 00638 // delete given the id 00639 void MoleculeGraphics::delete_id(int id) { 00640 int index = index_id(id); 00641 if (index < 0) return; 00642 shapes[index].clear(); 00643 delete_count++; 00644 if (delete_count > 1/* && 00645 float(delete_count)/float(num_elements()) > 0.2*/) { 00646 // clear out the deleted elements 00647 int i, j=0, n = num_elements(); 00648 // moving from i to j 00649 for (i=0; i<n; i++) { 00650 if (shapes[i].shape != NONE) { 00651 if (i != j) { 00652 shapes[j] = shapes[i]; 00653 } 00654 j++; 00655 } 00656 } 00657 i=j; 00658 while (i<n) { 00659 shapes[i].clear(); 00660 i++; 00661 } 00662 // remove in reverse order so we don't have to copy anything 00663 for (int k=n-1; k >= j; k--) shapes.remove(k); 00664 delete_count = 0; 00665 } 00666 needRegenerate = 1; 00667 // delete overrides a replace 00668 next_id = max_id; 00669 next_index = num_elements(); 00670 } 00671 00672 00673 // have the next added shape replace the given element 00674 // returns index 00675 int MoleculeGraphics::replace_id(int id) { 00676 int index = index_id(id); 00677 if (index < 0) return -1; 00678 // if one was already assigned to be replaced, and we want to 00679 // replace another, increase the delete count 00680 if (next_id != max_id) { 00681 delete_count++; 00682 } 00683 // do the replacement 00684 shapes[index].clear(); 00685 next_id = id; 00686 next_index = index; 00687 return index; 00688 } 00689 00690 00691 const char *MoleculeGraphics::info_id(int id) { 00692 int index = index_id(id); 00693 if (index < 0) return NULL; 00694 ShapeClass *shape; 00695 shape = &(shapes[index]); 00696 00697 if (graphics_info_xl != NULL) 00698 delete graphics_info_xl; 00699 00700 switch (shape->shape) { 00701 case NONE: { 00702 graphics_info[0] = '0円'; 00703 return graphics_info; 00704 } 00705 case POINT: { 00706 sprintf(graphics_info, "point {%f %f %f}", 00707 shape->data[0], shape->data[1], shape->data[2]); 00708 return graphics_info; 00709 } 00710 case PICKPOINT: { 00711 sprintf(graphics_info, "pickpoint {%f %f %f} %d", 00712 shape->data[0], shape->data[1], shape->data[2], (int)shape->data[3]); 00713 return graphics_info; 00714 } 00715 case LINE: { 00716 sprintf(graphics_info, "line {%f %f %f} {%f %f %f} style %s width %d", 00717 shape->data[0], shape->data[1], shape->data[2], 00718 shape->data[3], shape->data[4], shape->data[5], 00719 shape->data[6] < 0.5 ? "solid" : "dashed", 00720 int(shape->data[7])); 00721 return graphics_info; 00722 } 00723 case TRIANGLE: { 00724 sprintf(graphics_info, "triangle {%f %f %f} {%f %f %f} {%f %f %f}", 00725 shape->data[0], shape->data[1], shape->data[2], 00726 shape->data[3], shape->data[4], shape->data[5], 00727 shape->data[6], shape->data[7], shape->data[8]); 00728 return graphics_info; 00729 } 00730 case TRINORM: { 00731 sprintf(graphics_info, "trinorm {%f %f %f} {%f %f %f} {%f %f %f} " 00732 "{%f %f %f} {%f %f %f} {%f %f %f}", 00733 shape->data[0], shape->data[1], shape->data[2], 00734 shape->data[3], shape->data[4], shape->data[5], 00735 shape->data[6], shape->data[7], shape->data[8], 00736 shape->data[9], shape->data[10], shape->data[11], 00737 shape->data[12], shape->data[13], shape->data[14], 00738 shape->data[15], shape->data[16], shape->data[17]); 00739 return graphics_info; 00740 } 00741 case TRICOLOR: { 00742 sprintf(graphics_info, "tricolor {%f %f %f} {%f %f %f} {%f %f %f} " 00743 "{%f %f %f} {%f %f %f} {%f %f %f} %d %d %d", 00744 shape->data[0], shape->data[1], shape->data[2], 00745 shape->data[3], shape->data[4], shape->data[5], 00746 shape->data[6], shape->data[7], shape->data[8], 00747 shape->data[9], shape->data[10], shape->data[11], 00748 shape->data[12], shape->data[13], shape->data[14], 00749 shape->data[15], shape->data[16], shape->data[17], 00750 (int)shape->data[18], (int)shape->data[19], (int)shape->data[20]); 00751 return graphics_info; 00752 } 00753 case CYLINDER: { 00754 sprintf(graphics_info, "cylinder {%f %f %f} {%f %f %f} " 00755 "radius %f resolution %d filled %d", 00756 shape->data[0], shape->data[1], shape->data[2], 00757 shape->data[3], shape->data[4], shape->data[5], 00758 shape->data[6], int(shape->data[7]), int(shape->data[8])); 00759 return graphics_info; 00760 } 00761 case CONE: { 00762 sprintf(graphics_info, "cone {%f %f %f} {%f %f %f} " 00763 "radius %f radius2 %f resolution %d", 00764 shape->data[0], shape->data[1], shape->data[2], 00765 shape->data[3], shape->data[4], shape->data[5], 00766 shape->data[6], shape->data[8], int(shape->data[7])); 00767 return graphics_info; 00768 } 00769 case SPHERE: { 00770 sprintf(graphics_info, "sphere {%f %f %f} radius %f resolution %d", 00771 shape->data[0], shape->data[1], shape->data[2], 00772 shape->data[3], int(shape->data[4])); 00773 return graphics_info; 00774 } 00775 case TEXT: { 00776 sprintf(graphics_info, "text {%f %f %f} {%s} size %f thickness %f", 00777 shape->data[0], shape->data[1], shape->data[2], 00778 shapetext[(int)shape->data[5]], shape->data[3], shape->data[4]); 00779 return graphics_info; 00780 } 00781 case SPHERETUBE: { 00782 const int numcoords = int(shape->data[0]); 00783 const int numradii = int(shape->data[1]); 00784 const float defradius = shape->data[2]; 00785 // const int numcolors = int(shape->data[3]); 00786 const int drawtubes = int(shape->data[4]); 00787 const int res = int(shape->data[5]); 00788 const int coordsz = numcoords * 3; 00789 const int colorsz = numcoords * 3; // we MUST provide per-sphere colors 00790 const float *xyz3fv = (float *) shape->extradata; 00791 const float *rgb3fv = xyz3fv + coordsz; 00792 const float *radii1fv = xyz3fv + coordsz + colorsz; 00793 int i; 00794 00795 graphics_info_xl = new JString("spheretube {"); 00796 for (i=0; i<coordsz; i+=3) { 00797 sprintf(graphics_info, "{%g %g %g} ", xyz3fv[i], xyz3fv[i+1], xyz3fv[i+2]); 00798 *graphics_info_xl += (const char *) graphics_info; 00799 } 00800 *graphics_info_xl += "} "; 00801 00802 if (numradii > 1) { 00803 *graphics_info_xl += "radii {"; 00804 for (i=0; i<numcoords; i++) { 00805 sprintf(graphics_info, "%g ", radii1fv[i]); 00806 *graphics_info_xl += (const char *) graphics_info; 00807 } 00808 *graphics_info_xl += "} "; 00809 } else { 00810 sprintf(graphics_info, "radius %g ", defradius); 00811 *graphics_info_xl += "} "; 00812 } 00813 00814 // XXX incorrect logging at present 00815 // XXX right now this will result in colorID arrays getting converted 00816 // into RGB values incorrectly, we'll need to store them 00817 *graphics_info_xl += "colors {"; 00818 for (i=0; i<colorsz; i+=3) { 00819 sprintf(graphics_info, "{%g %g %g} ", rgb3fv[i], rgb3fv[i+1], rgb3fv[i+2]); 00820 *graphics_info_xl += (const char *) graphics_info; 00821 } 00822 *graphics_info_xl += "} "; 00823 00824 if (drawtubes) { 00825 *graphics_info_xl += "drawtubes 1 "; 00826 } 00827 00828 sprintf(graphics_info, "resolution %d ", res); 00829 *graphics_info_xl += (const char *) graphics_info; 00830 return ((const char *) *graphics_info_xl); 00831 } 00832 case MATERIALS: { 00833 sprintf(graphics_info, "materials %d", int(shape->data[0])); 00834 return graphics_info; 00835 } 00836 case MATERIAL: { 00837 sprintf(graphics_info, "material %d", int(shape->data[9])); 00838 return graphics_info; 00839 } 00840 case COLOR: { 00841 sprintf(graphics_info, "color %d", int(shape->data[0])); 00842 return graphics_info; 00843 } 00844 default: 00845 return ""; 00846 } 00847 } 00848 00849 00850 // return the center of volume and scaling factor 00851 #define CHECK_RANGE(v) \ 00852 { \ 00853 if (!found_one) { \ 00854 found_one = 1; \ 00855 minx = maxx = (v)[0]; \ 00856 miny = maxy = (v)[1]; \ 00857 minz = maxz = (v)[2]; \ 00858 } else { \ 00859 if (minx > (v)[0]) minx = (v)[0]; if (maxx < (v)[0]) maxx = (v)[0]; \ 00860 if (miny > (v)[1]) miny = (v)[1]; if (maxy < (v)[1]) maxy = (v)[1]; \ 00861 if (minz > (v)[2]) minz = (v)[2]; if (maxz < (v)[2]) maxz = (v)[2]; \ 00862 } \ 00863 } 00864 00865 00866 void MoleculeGraphics::find_bounds(void) { 00867 float minx=0.0f, maxx=0.0f; 00868 float miny=0.0f, maxy=0.0f; 00869 float minz=0.0f, maxz=0.0f; 00870 int found_one = 0; 00871 // go down the list and draw things 00872 int num = num_elements(); 00873 ShapeClass *shape; 00874 for (int i=0; i<num; i++) { 00875 shape = &(shapes[i]); 00876 switch (shape->shape) { 00877 case NONE: { 00878 break; 00879 } 00880 case POINT: { 00881 CHECK_RANGE(shape->data+0); 00882 break; 00883 } 00884 case PICKPOINT: { 00885 CHECK_RANGE(shape->data+0); 00886 break; 00887 } 00888 case LINE: { 00889 CHECK_RANGE(shape->data+0); 00890 CHECK_RANGE(shape->data+3); 00891 break; 00892 } 00893 case TRIANGLE: { 00894 CHECK_RANGE(shape->data+0); 00895 CHECK_RANGE(shape->data+3); 00896 CHECK_RANGE(shape->data+6); 00897 break; 00898 } 00899 case TRINORM: { 00900 CHECK_RANGE(shape->data+0); 00901 CHECK_RANGE(shape->data+3); 00902 CHECK_RANGE(shape->data+6); 00903 break; 00904 } 00905 case TRICOLOR: { 00906 CHECK_RANGE(shape->data+0); 00907 CHECK_RANGE(shape->data+3); 00908 CHECK_RANGE(shape->data+6); 00909 break; 00910 } 00911 case CYLINDER: { 00912 CHECK_RANGE(shape->data+0); 00913 CHECK_RANGE(shape->data+3); 00914 break; 00915 } 00916 case CONE: { 00917 CHECK_RANGE(shape->data+0); 00918 CHECK_RANGE(shape->data+3); 00919 break; 00920 } 00921 case SPHERE: { // I suppose I should include +/- radius ... 00922 CHECK_RANGE(shape->data+0); 00923 break; 00924 } 00925 case TEXT: { // I suppose I should include the string length size... 00926 CHECK_RANGE(shape->data+0); 00927 break; 00928 } 00929 case SPHERETUBE: { 00930 int numcoords = int(shape->data[0]); 00931 float lmin[3], lmax[3]; 00932 const float *coords = (const float *) shape->extradata; 00933 minmax_3fv_aligned(coords, numcoords, lmin, lmax); 00934 minx = lmin[0]; 00935 miny = lmin[1]; 00936 minz = lmin[2]; 00937 maxx = lmax[0]; 00938 maxy = lmax[1]; 00939 maxz = lmax[2]; 00940 break; 00941 } 00942 default: 00943 break; 00944 } 00945 } 00946 00947 // compute the values for center of volume center and scale 00948 if (!found_one) { 00949 cov_pos[0] = cov_pos[1] = cov_pos[2]; 00950 cov_scale = 0.1f; 00951 } else { 00952 cov_pos[0] = (minx + maxx) / 2.0f; 00953 cov_pos[1] = (miny + maxy) / 2.0f; 00954 cov_pos[2] = (minz + maxz) / 2.0f; 00955 float dx = maxx - minx; 00956 float dy = maxy - miny; 00957 float dz = maxz - minz; 00958 // a bit of sanity check (eg, suppose there is only one point) 00959 if (dx == 0 && dy == 0 && dz == 0) dx = 10; 00960 if (dx > dy) { 00961 if (dx > dz) { 00962 cov_scale = 2.0f / dx; 00963 } else { 00964 cov_scale = 2.0f / dz; 00965 } 00966 } else { 00967 if (dy > dz) { 00968 cov_scale = 2.0f / dy; 00969 } else { 00970 cov_scale = 2.0f / dz; 00971 } 00972 } 00973 } 00974 } 00975 00976 00977 void MoleculeGraphics::delete_shapetext() { 00978 for (int i=0; i<shapetext.num(); i++) 00979 delete [] shapetext[i]; 00980 00981 shapetext.clear(); 00982 } 00983